summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ideviceinstaller.c137
1 files changed, 113 insertions, 24 deletions
diff --git a/src/ideviceinstaller.c b/src/ideviceinstaller.c
index d2efbd3..a46b312 100644
--- a/src/ideviceinstaller.c
+++ b/src/ideviceinstaller.c
@@ -94,6 +94,8 @@ const char APPARCH_PATH[] = "ApplicationArchives";
94 94
95char *udid = NULL; 95char *udid = NULL;
96char *cmdarg = NULL; 96char *cmdarg = NULL;
97char *extsinf = NULL;
98char *extmeta = NULL;
97 99
98enum cmd_mode { 100enum cmd_mode {
99 CMD_NONE = 0, 101 CMD_NONE = 0,
@@ -433,6 +435,8 @@ static void print_usage(int argc, char **argv, int is_error)
433 " (can be passed multiple times)\n" 435 " (can be passed multiple times)\n"
434 " install PATH Install app from package file specified by PATH.\n" 436 " install PATH Install app from package file specified by PATH.\n"
435 " PATH can also be a .ipcc file for carrier bundles.\n" 437 " PATH can also be a .ipcc file for carrier bundles.\n"
438 " -s, --sinf PATH Pass an external SINF file\n"
439 " -m, --metadata PATH Pass an external iTunesMetadata file\n"
436 " uninstall BUNDLEID Uninstall app specified by BUNDLEID.\n" 440 " uninstall BUNDLEID Uninstall app specified by BUNDLEID.\n"
437 " upgrade PATH Upgrade app from package file specified by PATH.\n" 441 " upgrade PATH Upgrade app from package file specified by PATH.\n"
438 "\n" 442 "\n"
@@ -491,6 +495,8 @@ static void parse_opts(int argc, char **argv)
491 { "all", no_argument, NULL, LIST_ALL }, 495 { "all", no_argument, NULL, LIST_ALL },
492 { "xml", no_argument, NULL, OUTPUT_XML }, 496 { "xml", no_argument, NULL, OUTPUT_XML },
493 { "json", no_argument, NULL, OUTPUT_JSON }, 497 { "json", no_argument, NULL, OUTPUT_JSON },
498 { "sinf", required_argument, NULL, 's' },
499 { "metadata", required_argument, NULL, 'm' },
494 { "uninstall", no_argument, NULL, ARCHIVE_UNINSTALL }, 500 { "uninstall", no_argument, NULL, ARCHIVE_UNINSTALL },
495 { "app-only", no_argument, NULL, ARCHIVE_APP_ONLY }, 501 { "app-only", no_argument, NULL, ARCHIVE_APP_ONLY },
496 { "docs-only", no_argument, NULL, ARCHIVE_DOCS_ONLY }, 502 { "docs-only", no_argument, NULL, ARCHIVE_DOCS_ONLY },
@@ -501,7 +507,7 @@ static void parse_opts(int argc, char **argv)
501 int c; 507 int c;
502 508
503 while (1) { 509 while (1) {
504 c = getopt_long(argc, argv, "hu:nwdvb:a:", longopts, (int*)0); 510 c = getopt_long(argc, argv, "hu:nwdvb:a:s:m:", longopts, (int*)0);
505 if (c == -1) { 511 if (c == -1) {
506 break; 512 break;
507 } 513 }
@@ -543,6 +549,22 @@ static void parse_opts(int argc, char **argv)
543 } 549 }
544 plist_array_append_item(bundle_ids, plist_new_string(optarg)); 550 plist_array_append_item(bundle_ids, plist_new_string(optarg));
545 break; 551 break;
552 case 's':
553 if (!*optarg) {
554 printf("ERROR: path for --sinf must not be empty!\n");
555 print_usage(argc, argv, 1);
556 exit(2);
557 }
558 extsinf = strdup(optarg);
559 break;
560 case 'm':
561 if (!*optarg) {
562 printf("ERROR: path for --metadata must not be empty!\n");
563 print_usage(argc, argv, 1);
564 exit(2);
565 }
566 extmeta = strdup(optarg);
567 break;
546 case 'w': 568 case 'w':
547 use_notifier = 1; 569 use_notifier = 1;
548 break; 570 break;
@@ -746,6 +768,37 @@ static void afc_upload_dir(afc_client_t afc, const char* path, const char* afcpa
746 } 768 }
747} 769}
748 770
771static char *buf_from_file(const char *filename, size_t *size)
772{
773 struct stat st;
774 FILE *fp = NULL;
775
776 if (stat(filename, &st) == -1 || (fp = fopen(filename, "r")) == NULL) {
777 return NULL;
778 }
779 size_t filesize = st.st_size;
780 if (filesize == 0) {
781 return NULL;
782 }
783 char *ibuf = malloc(filesize * sizeof(char));
784 if (ibuf == NULL) {
785 return NULL;
786 }
787 size_t amount = fread(ibuf, 1, filesize, fp);
788 if (amount != filesize) {
789 fprintf(stderr, "ERROR: could not read %ld bytes from %s\n", filesize, filename);
790 free(ibuf);
791 return NULL;
792 }
793 fclose(fp);
794
795 if (size) {
796 *size = filesize;
797 }
798
799 return ibuf;
800}
801
749int main(int argc, char **argv) 802int main(int argc, char **argv)
750{ 803{
751 idevice_t device = NULL; 804 idevice_t device = NULL;
@@ -1153,21 +1206,41 @@ run_again:
1153 goto leave_cleanup; 1206 goto leave_cleanup;
1154 } 1207 }
1155 1208
1156 /* extract iTunesMetadata.plist from package */
1157 char *zbuf = NULL; 1209 char *zbuf = NULL;
1158 uint32_t len = 0; 1210 uint32_t len = 0;
1159 plist_t meta_dict = NULL; 1211 plist_t meta_dict = NULL;
1160 if (zip_get_contents(zf, ITUNES_METADATA_PLIST_FILENAME, 0, &zbuf, &len) == 0) { 1212
1161 meta = plist_new_data(zbuf, len); 1213 if (extmeta) {
1162 if (memcmp(zbuf, "bplist00", 8) == 0) { 1214 size_t flen = 0;
1163 plist_from_bin(zbuf, len, &meta_dict); 1215 zbuf = buf_from_file(extmeta, &flen);
1216 if (zbuf && flen) {
1217 meta = plist_new_data(zbuf, flen);
1218 if (memcmp(zbuf, "bplist00", 8) == 0) {
1219 plist_from_bin(zbuf, flen, &meta_dict);
1220 } else {
1221 plist_from_xml(zbuf, flen, &meta_dict);
1222 }
1223 free(zbuf);
1164 } else { 1224 } else {
1165 plist_from_xml(zbuf, len, &meta_dict); 1225 fprintf(stderr, "WARNING: could not load external iTunesMetadata %s!\n", extmeta);
1166 } 1226 }
1167 } else { 1227 zbuf = NULL;
1168 fprintf(stderr, "WARNING: could not locate %s in archive!\n", ITUNES_METADATA_PLIST_FILENAME); 1228 }
1229
1230 if (!meta && !meta_dict) {
1231 /* extract iTunesMetadata.plist from package */
1232 if (zip_get_contents(zf, ITUNES_METADATA_PLIST_FILENAME, 0, &zbuf, &len) == 0) {
1233 meta = plist_new_data(zbuf, len);
1234 if (memcmp(zbuf, "bplist00", 8) == 0) {
1235 plist_from_bin(zbuf, len, &meta_dict);
1236 } else {
1237 plist_from_xml(zbuf, len, &meta_dict);
1238 }
1239 } else {
1240 fprintf(stderr, "WARNING: could not locate %s in archive!\n", ITUNES_METADATA_PLIST_FILENAME);
1241 }
1242 free(zbuf);
1169 } 1243 }
1170 free(zbuf);
1171 1244
1172 /* determine .app directory in archive */ 1245 /* determine .app directory in archive */
1173 zbuf = NULL; 1246 zbuf = NULL;
@@ -1231,23 +1304,37 @@ run_again:
1231 goto leave_cleanup; 1304 goto leave_cleanup;
1232 } 1305 }
1233 1306
1234 char *sinfname = NULL; 1307 if (extsinf) {
1235 if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundleexecutable, bundleexecutable) < 0) { 1308 size_t flen = 0;
1236 fprintf(stderr, "Out of memory!?\n"); 1309 zbuf = buf_from_file(extsinf, &flen);
1237 goto leave_cleanup; 1310 if (zbuf && flen) {
1311 sinf = plist_new_data(zbuf, flen);
1312 free(zbuf);
1313 } else {
1314 fprintf(stderr, "WARNING: could not load external SINF %s!\n", extsinf);
1315 }
1316 zbuf = NULL;
1238 } 1317 }
1239 free(bundleexecutable);
1240 1318
1241 /* extract .sinf from package */ 1319 if (!sinf) {
1242 zbuf = NULL; 1320 char *sinfname = NULL;
1243 len = 0; 1321 if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundleexecutable, bundleexecutable) < 0) {
1244 if (zip_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) { 1322 fprintf(stderr, "Out of memory!?\n");
1245 sinf = plist_new_data(zbuf, len); 1323 goto leave_cleanup;
1246 } else { 1324 }
1247 fprintf(stderr, "WARNING: could not locate %s in archive!\n", sinfname); 1325 free(bundleexecutable);
1326
1327 /* extract .sinf from package */
1328 zbuf = NULL;
1329 len = 0;
1330 if (zip_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) {
1331 sinf = plist_new_data(zbuf, len);
1332 } else {
1333 fprintf(stderr, "WARNING: could not locate %s in archive!\n", sinfname);
1334 }
1335 free(sinfname);
1336 free(zbuf);
1248 } 1337 }
1249 free(sinfname);
1250 free(zbuf);
1251 1338
1252 /* copy archive to device */ 1339 /* copy archive to device */
1253 pkgname = NULL; 1340 pkgname = NULL;
@@ -1582,6 +1669,8 @@ leave_cleanup:
1582 1669
1583 free(udid); 1670 free(udid);
1584 free(copy_path); 1671 free(copy_path);
1672 free(extsinf);
1673 free(extmeta);
1585 free(bundleidentifier); 1674 free(bundleidentifier);
1586 plist_free(bundle_ids); 1675 plist_free(bundle_ids);
1587 plist_free(return_attrs); 1676 plist_free(return_attrs);