summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/ideviceinstaller.c90
2 files changed, 74 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac
index 0332df3..3e41809 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,7 +21,7 @@ LT_INIT
21 21
22# Checks for libraries. 22# Checks for libraries.
23PKG_CHECK_MODULES(libimobiledevice, libimobiledevice-1.0 >= 1.3.0) 23PKG_CHECK_MODULES(libimobiledevice, libimobiledevice-1.0 >= 1.3.0)
24PKG_CHECK_MODULES(libplist, libplist-2.0 >= 2.2.0) 24PKG_CHECK_MODULES(libplist, libplist-2.0 >= 2.3.0)
25PKG_CHECK_MODULES(libzip, libzip >= 0.10) 25PKG_CHECK_MODULES(libzip, libzip >= 0.10)
26 26
27# Checks for header files. 27# Checks for header files.
diff --git a/src/ideviceinstaller.c b/src/ideviceinstaller.c
index caba7f0..4b1b3d7 100644
--- a/src/ideviceinstaller.c
+++ b/src/ideviceinstaller.c
@@ -121,7 +121,9 @@ int err_occurred = 0;
121int notified = 0; 121int notified = 0;
122plist_t bundle_ids = NULL; 122plist_t bundle_ids = NULL;
123plist_t return_attrs = NULL; 123plist_t return_attrs = NULL;
124int xml_mode = 0; 124#define FORMAT_XML 1
125#define FORMAT_JSON 2
126int output_format = 0;
125int opt_list_user = 0; 127int opt_list_user = 0;
126int opt_list_system = 0; 128int opt_list_system = 0;
127char *copy_path = NULL; 129char *copy_path = NULL;
@@ -469,7 +471,8 @@ enum numerical_opts {
469 ARCHIVE_DOCS_ONLY, 471 ARCHIVE_DOCS_ONLY,
470 ARCHIVE_COPY_PATH, 472 ARCHIVE_COPY_PATH,
471 ARCHIVE_COPY_REMOVE, 473 ARCHIVE_COPY_REMOVE,
472 OUTPUT_XML 474 OUTPUT_XML,
475 OUTPUT_JSON
473}; 476};
474 477
475static void parse_opts(int argc, char **argv) 478static void parse_opts(int argc, char **argv)
@@ -487,6 +490,7 @@ static void parse_opts(int argc, char **argv)
487 { "system", no_argument, NULL, LIST_SYSTEM }, 490 { "system", no_argument, NULL, LIST_SYSTEM },
488 { "all", no_argument, NULL, LIST_ALL }, 491 { "all", no_argument, NULL, LIST_ALL },
489 { "xml", no_argument, NULL, OUTPUT_XML }, 492 { "xml", no_argument, NULL, OUTPUT_XML },
493 { "json", no_argument, NULL, OUTPUT_JSON },
490 { "uninstall", no_argument, NULL, ARCHIVE_UNINSTALL }, 494 { "uninstall", no_argument, NULL, ARCHIVE_UNINSTALL },
491 { "app-only", no_argument, NULL, ARCHIVE_APP_ONLY }, 495 { "app-only", no_argument, NULL, ARCHIVE_APP_ONLY },
492 { "docs-only", no_argument, NULL, ARCHIVE_DOCS_ONLY }, 496 { "docs-only", no_argument, NULL, ARCHIVE_DOCS_ONLY },
@@ -559,7 +563,10 @@ static void parse_opts(int argc, char **argv)
559 opt_list_system = 1; 563 opt_list_system = 1;
560 break; 564 break;
561 case OUTPUT_XML: 565 case OUTPUT_XML:
562 xml_mode = 1; 566 output_format = FORMAT_XML;
567 break;
568 case OUTPUT_JSON:
569 output_format = FORMAT_JSON;
563 break; 570 break;
564 case ARCHIVE_UNINSTALL: 571 case ARCHIVE_UNINSTALL:
565 skip_uninstall = 0; 572 skip_uninstall = 0;
@@ -852,7 +859,7 @@ run_again:
852 plist_dict_set_item(client_opts, "BundleIDs", plist_copy(bundle_ids)); 859 plist_dict_set_item(client_opts, "BundleIDs", plist_copy(bundle_ids));
853 } 860 }
854 861
855 if (!xml_mode) { 862 if (!output_format && !return_attrs) {
856 return_attrs = plist_new_array(); 863 return_attrs = plist_new_array();
857 plist_array_append_item(return_attrs, plist_new_string("CFBundleIdentifier")); 864 plist_array_append_item(return_attrs, plist_new_string("CFBundleIdentifier"));
858 plist_array_append_item(return_attrs, plist_new_string("CFBundleShortVersionString")); 865 plist_array_append_item(return_attrs, plist_new_string("CFBundleShortVersionString"));
@@ -863,20 +870,59 @@ run_again:
863 instproxy_client_options_add(client_opts, "ReturnAttributes", return_attrs, NULL); 870 instproxy_client_options_add(client_opts, "ReturnAttributes", return_attrs, NULL);
864 } 871 }
865 872
866 if (xml_mode) { 873 if (output_format) {
867 err = instproxy_browse(ipc, client_opts, &apps); 874 err = instproxy_browse(ipc, client_opts, &apps);
868 875
869 if (!apps || (plist_get_node_type(apps) != PLIST_ARRAY)) { 876 if (!apps || (plist_get_node_type(apps) != PLIST_ARRAY)) {
870 fprintf(stderr, "ERROR: instproxy_browse returnd an invalid plist!\n"); 877 fprintf(stderr, "ERROR: instproxy_browse returnd an invalid plist!\n");
871 goto leave_cleanup; 878 goto leave_cleanup;
872 } 879 }
873 char *xml = NULL; 880 char *buf = NULL;
874 uint32_t len = 0; 881 uint32_t len = 0;
875 882 if (output_format == FORMAT_XML) {
876 plist_to_xml(apps, &xml, &len); 883 plist_err_t perr = plist_to_xml(apps, &buf, &len);
877 if (xml) { 884 if (perr != PLIST_ERR_SUCCESS) {
878 puts(xml); 885 fprintf(stderr, "ERROR: Failed to convert data to XML format (%d).\n", perr);
879 free(xml); 886 }
887 } else if (output_format == FORMAT_JSON) {
888 /* for JSON, we need to convert some stuff since it doesn't support PLIST_DATA nodes */
889 plist_array_iter aiter = NULL;
890 plist_array_new_iter(apps, &aiter);
891 plist_t entry = NULL;
892 do {
893 plist_array_next_item(apps, aiter, &entry);
894 if (!entry) break;
895 plist_t items = plist_dict_get_item(entry, "UIApplicationShortcutItems");
896 plist_array_iter inner = NULL;
897 plist_array_new_iter(items, &inner);
898 plist_t item = NULL;
899 do {
900 plist_array_next_item(items, inner, &item);
901 if (!item) break;
902 plist_t userinfo = plist_dict_get_item(item, "UIApplicationShortcutItemUserInfo");
903 if (userinfo) {
904 plist_t data_node = plist_dict_get_item(userinfo, "data");
905
906 if (data_node) {
907 char *strbuf = NULL;
908 uint32_t buflen = 0;
909 plist_write_to_string(data_node, &strbuf, &buflen, PLIST_FORMAT_LIMD, PLIST_OPT_NO_NEWLINE);
910 plist_set_string_val(data_node, strbuf);
911 free(strbuf);
912 }
913 }
914 } while (item);
915 free(inner);
916 } while (entry);
917 free(aiter);
918 plist_err_t perr = plist_to_json(apps, &buf, &len, 1);
919 if (perr != PLIST_ERR_SUCCESS) {
920 fprintf(stderr, "ERROR: Failed to convert data to JSON format (%d).\n", perr);
921 }
922 }
923 if (buf) {
924 puts(buf);
925 free(buf);
880 } 926 }
881 plist_free(apps); 927 plist_free(apps);
882 goto leave_cleanup; 928 goto leave_cleanup;
@@ -1265,13 +1311,23 @@ run_again:
1265 goto leave_cleanup; 1311 goto leave_cleanup;
1266 } 1312 }
1267 1313
1268 if (xml_mode) { 1314 if (output_format) {
1269 char *xml = NULL; 1315 char *buf = NULL;
1270 uint32_t len = 0; 1316 uint32_t len = 0;
1271 plist_to_xml(dict, &xml, &len); 1317 if (output_format == FORMAT_XML) {
1272 if (xml) { 1318 plist_err_t perr = plist_to_xml(dict, &buf, &len);
1273 puts(xml); 1319 if (perr != PLIST_ERR_SUCCESS) {
1274 free(xml); 1320 fprintf(stderr, "ERROR: Failed to convert data to XML format (%d).\n", perr);
1321 }
1322 } else if (output_format == FORMAT_JSON) {
1323 plist_err_t perr = plist_to_json(dict, &buf, &len, 1);
1324 if (perr != PLIST_ERR_SUCCESS) {
1325 fprintf(stderr, "ERROR: Failed to convert data to JSON format (%d).\n", perr);
1326 }
1327 }
1328 if (buf) {
1329 puts(buf);
1330 free(buf);
1275 } 1331 }
1276 plist_free(dict); 1332 plist_free(dict);
1277 goto leave_cleanup; 1333 goto leave_cleanup;