summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/libimobiledevice/installation_proxy.h2
-rw-r--r--src/installation_proxy.c97
2 files changed, 99 insertions, 0 deletions
diff --git a/include/libimobiledevice/installation_proxy.h b/include/libimobiledevice/installation_proxy.h
index 049c0d7..428d1af 100644
--- a/include/libimobiledevice/installation_proxy.h
+++ b/include/libimobiledevice/installation_proxy.h
@@ -65,9 +65,11 @@ instproxy_error_t instproxy_archive(instproxy_client_t client, const char *appid
65instproxy_error_t instproxy_restore(instproxy_client_t client, const char *appid, plist_t client_options, instproxy_status_cb_t status_cb, void *user_data); 65instproxy_error_t instproxy_restore(instproxy_client_t client, const char *appid, plist_t client_options, instproxy_status_cb_t status_cb, void *user_data);
66instproxy_error_t instproxy_remove_archive(instproxy_client_t client, const char *appid, plist_t client_options, instproxy_status_cb_t status_cb, void *user_data); 66instproxy_error_t instproxy_remove_archive(instproxy_client_t client, const char *appid, plist_t client_options, instproxy_status_cb_t status_cb, void *user_data);
67 67
68/* Helper */
68plist_t instproxy_client_options_new(); 69plist_t instproxy_client_options_new();
69void instproxy_client_options_add(plist_t client_options, ...); 70void instproxy_client_options_add(plist_t client_options, ...);
70void instproxy_client_options_free(plist_t client_options); 71void instproxy_client_options_free(plist_t client_options);
72instproxy_error_t instproxy_client_get_path_for_bundle_identifier(instproxy_client_t client, const char* bundle_id, char** path);
71 73
72#ifdef __cplusplus 74#ifdef __cplusplus
73} 75}
diff --git a/src/installation_proxy.c b/src/installation_proxy.c
index 3e2726e..e18c9c4 100644
--- a/src/installation_proxy.c
+++ b/src/installation_proxy.c
@@ -775,3 +775,100 @@ void instproxy_client_options_free(plist_t client_options)
775 plist_free(client_options); 775 plist_free(client_options);
776 } 776 }
777} 777}
778
779/**
780 * Query the device for the path of an application.
781 *
782 * @param client The connected installation proxy client.
783 * @param appid ApplicationIdentifier of app to retrieve the path for.
784 * @param path Pointer to store the device path for the application
785 * which is set to NULL if it could not be determined.
786 *
787 * @return INSTPROXY_E_SUCCESS on success, INSTPROXY_E_OP_FAILED if
788 * the path could not be determined or an INSTPROXY_E_* error
789 * value if an error occured.
790 *
791 * @note This implementation browses all applications and matches the
792 * right entry by the application identifier.
793 */
794instproxy_error_t instproxy_client_get_path_for_bundle_identifier(instproxy_client_t client, const char* appid, char** path)
795{
796 if (!client || !client->parent || !appid)
797 return INSTPROXY_E_INVALID_ARG;
798
799 plist_t apps = NULL;
800
801 // create client options for any application types
802 plist_t client_opts = instproxy_client_options_new();
803 instproxy_client_options_add(client_opts, "ApplicationType", "Any", NULL);
804
805 // only return attributes we need
806 plist_t return_attributes = plist_new_array();
807 plist_array_append_item(return_attributes, plist_new_string("CFBundleIdentifier"));
808 plist_array_append_item(return_attributes, plist_new_string("CFBundleExecutable"));
809 plist_array_append_item(return_attributes, plist_new_string("Path"));
810 instproxy_client_options_add(client_opts, "ReturnAttributes", return_attributes, NULL);
811
812 // query device for list of apps
813 instproxy_error_t ierr = instproxy_browse(client, client_opts, &apps);
814 instproxy_client_options_free(client_opts);
815 if (ierr != INSTPROXY_E_SUCCESS) {
816 return ierr;
817 }
818
819 plist_t app_found = NULL;
820 uint32_t i;
821 for (i = 0; i < plist_array_get_size(apps); i++) {
822 char *appid_str = NULL;
823 plist_t app_info = plist_array_get_item(apps, i);
824 plist_t idp = plist_dict_get_item(app_info, "CFBundleIdentifier");
825 if (idp) {
826 plist_get_string_val(idp, &appid_str);
827 }
828 if (appid_str && strcmp(appid, appid_str) == 0) {
829 app_found = app_info;
830 }
831 free(appid_str);
832 if (app_found) {
833 break;
834 }
835 }
836
837 if (!app_found) {
838 *path = NULL;
839 return INSTPROXY_E_OP_FAILED;
840 }
841
842 char* path_str = NULL;
843 plist_t path_p = plist_dict_get_item(app_found, "Path");
844 if (path_p) {
845 plist_get_string_val(path_p, &path_str);
846 }
847
848 char* exec_str = NULL;
849 plist_t exec_p = plist_dict_get_item(app_found, "CFBundleExecutable");
850 if (exec_p) {
851 plist_get_string_val(exec_p, &exec_str);
852 }
853
854 if (!path_str) {
855 debug_info("app path not found");
856 return INSTPROXY_E_OP_FAILED;
857 }
858
859 if (!exec_str) {
860 debug_info("bundle executable not found");
861 return INSTPROXY_E_OP_FAILED;
862 }
863
864 plist_free(apps);
865
866 char* ret = (char*)malloc(strlen(path_str) + 1 + strlen(exec_str) + 1);
867 strcpy(ret, path_str);
868 strcat(ret, "/");
869 strcat(ret, exec_str);
870
871 *path = ret;
872
873 return INSTPROXY_E_SUCCESS;
874}