diff options
-rw-r--r-- | src/ideviceinstaller.c | 137 |
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"; char *udid = NULL; char *cmdarg = NULL; +char *extsinf = NULL; +char *extmeta = NULL; enum cmd_mode { CMD_NONE = 0, @@ -433,6 +435,8 @@ static void print_usage(int argc, char **argv, int is_error) " (can be passed multiple times)\n" " install PATH Install app from package file specified by PATH.\n" " PATH can also be a .ipcc file for carrier bundles.\n" + " -s, --sinf PATH Pass an external SINF file\n" + " -m, --metadata PATH Pass an external iTunesMetadata file\n" " uninstall BUNDLEID Uninstall app specified by BUNDLEID.\n" " upgrade PATH Upgrade app from package file specified by PATH.\n" "\n" @@ -491,6 +495,8 @@ static void parse_opts(int argc, char **argv) { "all", no_argument, NULL, LIST_ALL }, { "xml", no_argument, NULL, OUTPUT_XML }, { "json", no_argument, NULL, OUTPUT_JSON }, + { "sinf", required_argument, NULL, 's' }, + { "metadata", required_argument, NULL, 'm' }, { "uninstall", no_argument, NULL, ARCHIVE_UNINSTALL }, { "app-only", no_argument, NULL, ARCHIVE_APP_ONLY }, { "docs-only", no_argument, NULL, ARCHIVE_DOCS_ONLY }, @@ -501,7 +507,7 @@ static void parse_opts(int argc, char **argv) int c; while (1) { - c = getopt_long(argc, argv, "hu:nwdvb:a:", longopts, (int*)0); + c = getopt_long(argc, argv, "hu:nwdvb:a:s:m:", longopts, (int*)0); if (c == -1) { break; } @@ -543,6 +549,22 @@ static void parse_opts(int argc, char **argv) } plist_array_append_item(bundle_ids, plist_new_string(optarg)); break; + case 's': + if (!*optarg) { + printf("ERROR: path for --sinf must not be empty!\n"); + print_usage(argc, argv, 1); + exit(2); + } + extsinf = strdup(optarg); + break; + case 'm': + if (!*optarg) { + printf("ERROR: path for --metadata must not be empty!\n"); + print_usage(argc, argv, 1); + exit(2); + } + extmeta = strdup(optarg); + break; case 'w': use_notifier = 1; break; @@ -746,6 +768,37 @@ static void afc_upload_dir(afc_client_t afc, const char* path, const char* afcpa } } +static char *buf_from_file(const char *filename, size_t *size) +{ + struct stat st; + FILE *fp = NULL; + + if (stat(filename, &st) == -1 || (fp = fopen(filename, "r")) == NULL) { + return NULL; + } + size_t filesize = st.st_size; + if (filesize == 0) { + return NULL; + } + char *ibuf = malloc(filesize * sizeof(char)); + if (ibuf == NULL) { + return NULL; + } + size_t amount = fread(ibuf, 1, filesize, fp); + if (amount != filesize) { + fprintf(stderr, "ERROR: could not read %ld bytes from %s\n", filesize, filename); + free(ibuf); + return NULL; + } + fclose(fp); + + if (size) { + *size = filesize; + } + + return ibuf; +} + int main(int argc, char **argv) { idevice_t device = NULL; @@ -1153,21 +1206,41 @@ run_again: goto leave_cleanup; } - /* extract iTunesMetadata.plist from package */ char *zbuf = NULL; uint32_t len = 0; plist_t meta_dict = NULL; - if (zip_get_contents(zf, ITUNES_METADATA_PLIST_FILENAME, 0, &zbuf, &len) == 0) { - meta = plist_new_data(zbuf, len); - if (memcmp(zbuf, "bplist00", 8) == 0) { - plist_from_bin(zbuf, len, &meta_dict); + + if (extmeta) { + size_t flen = 0; + zbuf = buf_from_file(extmeta, &flen); + if (zbuf && flen) { + meta = plist_new_data(zbuf, flen); + if (memcmp(zbuf, "bplist00", 8) == 0) { + plist_from_bin(zbuf, flen, &meta_dict); + } else { + plist_from_xml(zbuf, flen, &meta_dict); + } + free(zbuf); } else { - plist_from_xml(zbuf, len, &meta_dict); + fprintf(stderr, "WARNING: could not load external iTunesMetadata %s!\n", extmeta); } - } else { - fprintf(stderr, "WARNING: could not locate %s in archive!\n", ITUNES_METADATA_PLIST_FILENAME); + zbuf = NULL; + } + + if (!meta && !meta_dict) { + /* extract iTunesMetadata.plist from package */ + if (zip_get_contents(zf, ITUNES_METADATA_PLIST_FILENAME, 0, &zbuf, &len) == 0) { + meta = plist_new_data(zbuf, len); + if (memcmp(zbuf, "bplist00", 8) == 0) { + plist_from_bin(zbuf, len, &meta_dict); + } else { + plist_from_xml(zbuf, len, &meta_dict); + } + } else { + fprintf(stderr, "WARNING: could not locate %s in archive!\n", ITUNES_METADATA_PLIST_FILENAME); + } + free(zbuf); } - free(zbuf); /* determine .app directory in archive */ zbuf = NULL; @@ -1231,23 +1304,37 @@ run_again: goto leave_cleanup; } - char *sinfname = NULL; - if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundleexecutable, bundleexecutable) < 0) { - fprintf(stderr, "Out of memory!?\n"); - goto leave_cleanup; + if (extsinf) { + size_t flen = 0; + zbuf = buf_from_file(extsinf, &flen); + if (zbuf && flen) { + sinf = plist_new_data(zbuf, flen); + free(zbuf); + } else { + fprintf(stderr, "WARNING: could not load external SINF %s!\n", extsinf); + } + zbuf = NULL; } - free(bundleexecutable); - /* extract .sinf from package */ - zbuf = NULL; - len = 0; - if (zip_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) { - sinf = plist_new_data(zbuf, len); - } else { - fprintf(stderr, "WARNING: could not locate %s in archive!\n", sinfname); + if (!sinf) { + char *sinfname = NULL; + if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundleexecutable, bundleexecutable) < 0) { + fprintf(stderr, "Out of memory!?\n"); + goto leave_cleanup; + } + free(bundleexecutable); + + /* extract .sinf from package */ + zbuf = NULL; + len = 0; + if (zip_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) { + sinf = plist_new_data(zbuf, len); + } else { + fprintf(stderr, "WARNING: could not locate %s in archive!\n", sinfname); + } + free(sinfname); + free(zbuf); } - free(sinfname); - free(zbuf); /* copy archive to device */ pkgname = NULL; @@ -1582,6 +1669,8 @@ leave_cleanup: free(udid); free(copy_path); + free(extsinf); + free(extmeta); free(bundleidentifier); plist_free(bundle_ids); plist_free(return_attrs); |