Add options for using external sinf and iTunes metadata

This commit is contained in:
Francesco Tamagni
2019-05-22 21:08:31 +02:00
committed by Nikias Bassen
parent 5cbf60922b
commit 03d93c67ff
+113 -24
View File
@@ -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);