summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ideviceinstaller.c333
1 files changed, 212 insertions, 121 deletions
diff --git a/src/ideviceinstaller.c b/src/ideviceinstaller.c
index 67e06f9..acf2b6b 100644
--- a/src/ideviceinstaller.c
+++ b/src/ideviceinstaller.c
@@ -212,6 +212,7 @@ static void print_usage(int argc, char **argv)
212 " -o list_all\t- list all types of apps\n" 212 " -o list_all\t- list all types of apps\n"
213 " -o xml\t\t- print full output as xml plist\n" 213 " -o xml\t\t- print full output as xml plist\n"
214 " -i, --install ARCHIVE\tInstall app from package file specified by ARCHIVE.\n" 214 " -i, --install ARCHIVE\tInstall app from package file specified by ARCHIVE.\n"
215 " \tARCHIVE can also be a .ipcc file for carrier bundles.\n"
215 " -u, --uninstall APPID\tUninstall app specified by APPID.\n" 216 " -u, --uninstall APPID\tUninstall app specified by APPID.\n"
216 " -g, --upgrade APPID\tUpgrade app specified by APPID.\n" 217 " -g, --upgrade APPID\tUpgrade app specified by APPID.\n"
217 " -L, --list-archives\tList archived applications, possible options:\n" 218 " -L, --list-archives\tList archived applications, possible options:\n"
@@ -525,152 +526,242 @@ run_again:
525 goto leave_cleanup; 526 goto leave_cleanup;
526 } 527 }
527 528
528 /* extract iTunesMetadata.plist from package */ 529 plist_t client_opts = instproxy_client_options_new();
529 char *zbuf = NULL;
530 uint32_t len = 0;
531 if (zip_f_get_contents(zf, "iTunesMetadata.plist", 0, &zbuf, &len) == 0) {
532 meta = plist_new_data(zbuf, len);
533 }
534 if (zbuf) {
535 free(zbuf);
536 }
537 530
538 /* we need to get the CFBundleName first */ 531 if ((strlen(appid) > 5) && (strcmp(&appid[strlen(appid)-5], ".ipcc") == 0)) {
539 plist_t info = NULL; 532 char* ipcc = strdup(appid);
540 zbuf = NULL; 533 if ((asprintf(&pkgname, "%s/%s", PKG_PATH, basename(ipcc)) > 0) && pkgname) {
541 len = 0; 534 afc_make_directory(afc, pkgname);
542 if (zip_f_get_contents(zf, "Info.plist", ZIP_FL_NODIR, &zbuf, &len) < 0) { 535 }
543 zip_unchange_all(zf);
544 zip_close(zf);
545 goto leave_cleanup;
546 }
547 if (memcmp(zbuf, "bplist00", 8) == 0) {
548 plist_from_bin(zbuf, len, &info);
549 } else {
550 plist_from_xml(zbuf, len, &info);
551 }
552 free(zbuf);
553 536
554 if (!info) { 537 printf("Uploading %s package contents...\n", basename(ipcc));
555 fprintf(stderr, "Could not parse Info.plist!\n"); 538
556 zip_unchange_all(zf); 539 /* extract the contents of the .ipcc file to PublicStaging/<name>.ipcc directory */
557 zip_close(zf); 540 zip_uint64_t numzf = zip_get_num_entries(zf, 0);
558 goto leave_cleanup; 541 zip_uint64_t i = 0;
559 } 542 for (i = 0; numzf > 0 && i < numzf; i++) {
543 const char* zname = zip_get_name(zf, i, 0);
544 char* dstpath = NULL;
545 if (!zname) continue;
546 if (zname[strlen(zname)-1] == '/') {
547 // directory
548 if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) > 0) && dstpath) {
549 afc_make_directory(afc, dstpath); }
550 free(dstpath);
551 dstpath = NULL;
552 } else {
553 // file
554 struct zip_file* zfile = zip_fopen_index(zf, i, 0);
555 if (!zfile) continue;
556
557 if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) <= 0) || !dstpath || (afc_file_open(afc, dstpath, AFC_FOPEN_WRONLY, &af) != AFC_E_SUCCESS)) {
558 fprintf(stderr, "ERROR: can't open afc://%s for writing\n", dstpath);
559 free(dstpath);
560 dstpath = NULL;
561 zip_fclose(zfile);
562 continue;
563 }
560 564
561 char *bundlename = NULL; 565 struct zip_stat zs;
566 zip_stat_init(&zs);
567 if (zip_stat_index(zf, i, 0, &zs) != 0) {
568 fprintf(stderr, "ERROR: zip_stat_index %ld failed!\n", i);
569 free(dstpath);
570 dstpath = NULL;
571 zip_fclose(zfile);
572 continue;
573 }
562 574
563 plist_t bname = plist_dict_get_item(info, "CFBundleName"); 575 free(dstpath);
564 if (bname) { 576 dstpath = NULL;
565 plist_get_string_val(bname, &bundlename); 577
566 } 578 zip_uint64_t zfsize = 0;
567 plist_free(info); 579 while (zfsize < zs.size) {
580 zip_int64_t amount = zip_fread(zfile, buf, sizeof(buf));
581 if (amount == 0) {
582 break;
583 }
584
585 if (amount > 0) {
586 uint32_t written, total = 0;
587 while (total < amount) {
588 written = 0;
589 if (afc_file_write(afc, af, buf, amount, &written) !=
590 AFC_E_SUCCESS) {
591 fprintf(stderr, "AFC Write error!\n");
592 break;
593 }
594 total += written;
595 }
596 if (total != amount) {
597 fprintf(stderr, "Error: wrote only %d of %zu\n", total, amount);
598 afc_file_close(afc, af);
599 zip_fclose(zfile);
600 free(dstpath);
601 goto leave_cleanup;
602 }
603 }
604
605 zfsize += amount;
606 }
568 607
569 if (!bundlename) { 608 afc_file_close(afc, af);
570 fprintf(stderr, "Could not determine CFBundleName!\n"); 609 af = 0;
571 zip_unchange_all(zf);
572 zip_close(zf);
573 goto leave_cleanup;
574 }
575 610
576 char *sinfname = NULL; 611 zip_fclose(zfile);
577 if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundlename, bundlename) < 0) { 612 }
578 fprintf(stderr, "Out of memory!?\n"); 613 }
579 goto leave_cleanup; 614 free(ipcc);
580 } 615 printf("done.\n");
581 free(bundlename);
582 616
583 /* extract .sinf from package */ 617 instproxy_client_options_add(client_opts, "PackageType", "CarrierBundle", NULL);
584 zbuf = NULL; 618 } else {
585 len = 0; 619 /* extract iTunesMetadata.plist from package */
586 if (zip_f_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) { 620 char *zbuf = NULL;
587 sinf = plist_new_data(zbuf, len); 621 uint32_t len = 0;
588 } 622 if (zip_f_get_contents(zf, "iTunesMetadata.plist", 0, &zbuf, &len) == 0) {
589 free(sinfname); 623 meta = plist_new_data(zbuf, len);
590 if (zbuf) { 624 }
625 if (zbuf) {
626 free(zbuf);
627 }
628
629 /* we need to get the CFBundleName first */
630 plist_t info = NULL;
631 zbuf = NULL;
632 len = 0;
633 if (zip_f_get_contents(zf, "Info.plist", ZIP_FL_NODIR, &zbuf, &len) < 0) {
634 zip_unchange_all(zf);
635 zip_close(zf);
636 goto leave_cleanup;
637 }
638 if (memcmp(zbuf, "bplist00", 8) == 0) {
639 plist_from_bin(zbuf, len, &info);
640 } else {
641 plist_from_xml(zbuf, len, &info);
642 }
591 free(zbuf); 643 free(zbuf);
592 }
593 644
594 zip_unchange_all(zf); 645 if (!info) {
595 zip_close(zf); 646 fprintf(stderr, "Could not parse Info.plist!\n");
647 zip_unchange_all(zf);
648 zip_close(zf);
649 goto leave_cleanup;
650 }
596 651
597 /* copy archive to device */ 652 char *bundlename = NULL;
598 f = fopen(appid, "r");
599 if (!f) {
600 fprintf(stderr, "fopen: %s: %s\n", appid, strerror(errno));
601 goto leave_cleanup;
602 }
603 653
604 pkgname = NULL; 654 plist_t bname = plist_dict_get_item(info, "CFBundleName");
605 if (asprintf(&pkgname, "%s/%s", PKG_PATH, basename(appid)) < 0) { 655 if (bname) {
606 fprintf(stderr, "Out of memory!?\n"); 656 plist_get_string_val(bname, &bundlename);
607 goto leave_cleanup; 657 }
608 } 658 plist_free(info);
609 659
610 printf("Copying '%s' --> '%s'\n", appid, pkgname); 660 if (!bundlename) {
661 fprintf(stderr, "Could not determine CFBundleName!\n");
662 zip_unchange_all(zf);
663 zip_close(zf);
664 goto leave_cleanup;
665 }
611 666
612 char **strs = NULL; 667 char *sinfname = NULL;
613 if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) { 668 if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundlename, bundlename) < 0) {
614 if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { 669 fprintf(stderr, "Out of memory!?\n");
615 fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); 670 goto leave_cleanup;
616 } 671 }
617 } 672 free(bundlename);
618 if (strs) { 673
619 int i = 0; 674 /* extract .sinf from package */
620 while (strs[i]) { 675 zbuf = NULL;
621 free(strs[i]); 676 len = 0;
622 i++; 677 if (zip_f_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) {
678 sinf = plist_new_data(zbuf, len);
679 }
680 free(sinfname);
681 if (zbuf) {
682 free(zbuf);
623 } 683 }
624 free(strs);
625 }
626 684
627 if ((afc_file_open(afc, pkgname, AFC_FOPEN_WRONLY, &af) != 685 /* copy archive to device */
628 AFC_E_SUCCESS) || !af) { 686 f = fopen(appid, "r");
629 fclose(f); 687 if (!f) {
630 fprintf(stderr, "afc_file_open on '%s' failed!\n", pkgname); 688 fprintf(stderr, "fopen: %s: %s\n", appid, strerror(errno));
631 free(pkgname); 689 goto leave_cleanup;
632 goto leave_cleanup; 690 }
633 }
634 691
635 size_t amount = 0; 692 pkgname = NULL;
636 do { 693 if (asprintf(&pkgname, "%s/%s", PKG_PATH, basename(appid)) < 0) {
637 amount = fread(buf, 1, sizeof(buf), f); 694 fprintf(stderr, "Out of memory!?\n");
638 if (amount > 0) { 695 goto leave_cleanup;
639 uint32_t written, total = 0; 696 }
640 while (total < amount) { 697
641 written = 0; 698 printf("Copying '%s' --> '%s'\n", appid, pkgname);
642 if (afc_file_write(afc, af, buf, amount, &written) != 699
643 AFC_E_SUCCESS) { 700 char **strs = NULL;
644 fprintf(stderr, "AFC Write error!\n"); 701 if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) {
645 break; 702 if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) {
646 } 703 fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH);
647 total += written; 704 }
705 }
706 if (strs) {
707 int i = 0;
708 while (strs[i]) {
709 free(strs[i]);
710 i++;
648 } 711 }
649 if (total != amount) { 712 free(strs);
650 fprintf(stderr, "Error: wrote only %d of %zu\n", total, 713 }
714
715 if ((afc_file_open(afc, pkgname, AFC_FOPEN_WRONLY, &af) !=
716 AFC_E_SUCCESS) || !af) {
717 fclose(f);
718 fprintf(stderr, "afc_file_open on '%s' failed!\n", pkgname);
719 free(pkgname);
720 goto leave_cleanup;
721 }
722
723 size_t amount = 0;
724 do {
725 amount = fread(buf, 1, sizeof(buf), f);
726 if (amount > 0) {
727 uint32_t written, total = 0;
728 while (total < amount) {
729 written = 0;
730 if (afc_file_write(afc, af, buf, amount, &written) !=
731 AFC_E_SUCCESS) {
732 fprintf(stderr, "AFC Write error!\n");
733 break;
734 }
735 total += written;
736 }
737 if (total != amount) {
738 fprintf(stderr, "Error: wrote only %d of %zu\n", total,
651 amount); 739 amount);
652 afc_file_close(afc, af); 740 afc_file_close(afc, af);
653 fclose(f); 741 fclose(f);
654 free(pkgname); 742 free(pkgname);
655 goto leave_cleanup; 743 goto leave_cleanup;
744 }
656 } 745 }
657 } 746 }
658 } 747 while (amount > 0);
659 while (amount > 0);
660 748
661 afc_file_close(afc, af); 749 afc_file_close(afc, af);
662 fclose(f); 750 fclose(f);
663 751
664 printf("done.\n"); 752 printf("done.\n");
665 753
666 /* perform installation or upgrade */ 754 if (sinf) {
667 plist_t client_opts = instproxy_client_options_new(); 755 instproxy_client_options_add(client_opts, "ApplicationSINF", sinf, NULL);
668 if (sinf) { 756 }
669 instproxy_client_options_add(client_opts, "ApplicationSINF", sinf, NULL); 757 if (meta) {
670 } 758 instproxy_client_options_add(client_opts, "iTunesMetadata", meta, NULL);
671 if (meta) { 759 }
672 instproxy_client_options_add(client_opts, "iTunesMetadata", meta, NULL);
673 } 760 }
761 zip_unchange_all(zf);
762 zip_close(zf);
763
764 /* perform installation or upgrade */
674 if (install_mode) { 765 if (install_mode) {
675 printf("Installing '%s'\n", pkgname); 766 printf("Installing '%s'\n", pkgname);
676#ifdef HAVE_LIBIMOBILEDEVICE_1_1 767#ifdef HAVE_LIBIMOBILEDEVICE_1_1