From dcb85727c3649c254c985d840aa2efb36f727872 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Sat, 3 Sep 2011 02:10:48 +0200 Subject: Completely remove glib dependency. --- src/Makefile.am | 4 +- src/afc.c | 28 +-- src/afc.h | 16 +- src/debug.c | 3 +- src/debug.h | 17 +- src/house_arrest.h | 2 - src/lockdown.c | 5 +- src/mobilesync.c | 1 - src/property_list_service.c | 5 +- src/restore.c | 1 - src/userpref.c | 492 ++++++++++++++++++++++++++++++++++++-------- src/userpref.h | 19 +- 12 files changed, 460 insertions(+), 133 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index f42ac08..5531f8d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) -AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) +AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) +AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) ${libpthread_LIBS} lib_LTLIBRARIES = libimobiledevice.la libimobiledevice_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBIMOBILEDEVICE_SO_VERSION) -no-undefined diff --git a/src/afc.c b/src/afc.c index fd5143a..a0869ca 100644 --- a/src/afc.c +++ b/src/afc.c @@ -364,7 +364,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, uint3 } if (current_count >= sizeof(uint64_t)) { - param1 = GUINT64_FROM_LE(*(uint64_t*)(*dump_here)); + param1 = le64toh(*(uint64_t*)(*dump_here)); } debug_info("packet data size = %i", current_count); @@ -577,8 +577,10 @@ afc_error_t afc_get_device_info_key(afc_client_t client, const char *key, char * break; } } - - g_strfreev(kvps); + for (ptr = kvps; *ptr; ptr++) { + free(*ptr); + } + free(kvps); return ret; } @@ -764,7 +766,7 @@ idevice_error_t afc_file_open(afc_client_t client, const char *filename, afc_file_mode_t file_mode, uint64_t *handle) { - uint64_t file_mode_loc = GUINT64_TO_LE(file_mode); + uint64_t file_mode_loc = htole64(file_mode); uint32_t bytes = 0; char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1)); afc_error_t ret = AFC_E_UNKNOWN_ERROR; @@ -842,7 +844,7 @@ afc_file_read(afc_client_t client, uint64_t handle, char *data, uint32_t length, /* Send the read command */ AFCFilePacket *packet = (AFCFilePacket *) malloc(sizeof(AFCFilePacket)); packet->filehandle = handle; - packet->size = GUINT64_TO_LE(((length - current_count) < MAXIMUM_READ_SIZE) ? (length - current_count) : MAXIMUM_READ_SIZE); + packet->size = htole64(((length - current_count) < MAXIMUM_READ_SIZE) ? (length - current_count) : MAXIMUM_READ_SIZE); client->afc_packet->operation = AFC_OP_READ; client->afc_packet->entire_length = client->afc_packet->this_length = 0; ret = afc_dispatch_packet(client, (char *) packet, sizeof(AFCFilePacket), &bytes_loc); @@ -1035,7 +1037,7 @@ afc_error_t afc_file_lock(afc_client_t client, uint64_t handle, afc_lock_op_t op { char *buffer = malloc(16); uint32_t bytes = 0; - uint64_t op = GUINT64_TO_LE(operation); + uint64_t op = htole64(operation); afc_error_t ret = AFC_E_UNKNOWN_ERROR; if (!client || (handle == 0)) @@ -1084,8 +1086,8 @@ afc_error_t afc_file_lock(afc_client_t client, uint64_t handle, afc_lock_op_t op afc_error_t afc_file_seek(afc_client_t client, uint64_t handle, int64_t offset, int whence) { char *buffer = (char *) malloc(sizeof(char) * 24); - int64_t offset_loc = (int64_t)GUINT64_TO_LE(offset); - uint64_t whence_loc = GUINT64_TO_LE(whence); + int64_t offset_loc = (int64_t)htole64(offset); + uint64_t whence_loc = htole64(whence); uint32_t bytes = 0; afc_error_t ret = AFC_E_UNKNOWN_ERROR; @@ -1156,7 +1158,7 @@ afc_error_t afc_file_tell(afc_client_t client, uint64_t handle, uint64_t *positi if (bytes > 0 && buffer) { /* Get the position */ memcpy(position, buffer, sizeof(uint64_t)); - *position = GUINT64_FROM_LE(*position); + *position = le64toh(*position); } if (buffer) free(buffer); @@ -1182,7 +1184,7 @@ afc_error_t afc_file_truncate(afc_client_t client, uint64_t handle, uint64_t new { char *buffer = (char *) malloc(sizeof(char) * 16); uint32_t bytes = 0; - uint64_t newsize_loc = GUINT64_TO_LE(newsize); + uint64_t newsize_loc = htole64(newsize); afc_error_t ret = AFC_E_UNKNOWN_ERROR; if (!client || (handle == 0)) @@ -1227,7 +1229,7 @@ afc_error_t afc_truncate(afc_client_t client, const char *path, uint64_t newsize char *response = NULL; char *send = (char *) malloc(sizeof(char) * (strlen(path) + 1 + 8)); uint32_t bytes = 0; - uint64_t size_requested = GUINT64_TO_LE(newsize); + uint64_t size_requested = htole64(newsize); afc_error_t ret = AFC_E_UNKNOWN_ERROR; if (!client || !path || !client->afc_packet || !client->connection) @@ -1271,7 +1273,7 @@ afc_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, const c char *response = NULL; char *send = (char *) malloc(sizeof(char) * (strlen(target)+1 + strlen(linkname)+1 + 8)); uint32_t bytes = 0; - uint64_t type = GUINT64_TO_LE(linktype); + uint64_t type = htole64(linktype); afc_error_t ret = AFC_E_UNKNOWN_ERROR; if (!client || !target || !linkname || !client->afc_packet || !client->connection) @@ -1319,7 +1321,7 @@ afc_error_t afc_set_file_time(afc_client_t client, const char *path, uint64_t mt char *response = NULL; char *send = (char *) malloc(sizeof(char) * (strlen(path) + 1 + 8)); uint32_t bytes = 0; - uint64_t mtime_loc = GUINT64_TO_LE(mtime); + uint64_t mtime_loc = htole64(mtime); afc_error_t ret = AFC_E_UNKNOWN_ERROR; if (!client || !path || !client->afc_packet || !client->connection) diff --git a/src/afc.h b/src/afc.h index 79078ec..c86828c 100644 --- a/src/afc.h +++ b/src/afc.h @@ -33,16 +33,16 @@ typedef struct { } AFCPacket; #define AFCPacket_to_LE(x) \ - (x)->entire_length = GUINT64_TO_LE((x)->entire_length); \ - (x)->this_length = GUINT64_TO_LE((x)->this_length); \ - (x)->packet_num = GUINT64_TO_LE((x)->packet_num); \ - (x)->operation = GUINT64_TO_LE((x)->operation); + (x)->entire_length = htole64((x)->entire_length); \ + (x)->this_length = htole64((x)->this_length); \ + (x)->packet_num = htole64((x)->packet_num); \ + (x)->operation = htole64((x)->operation); #define AFCPacket_from_LE(x) \ - (x)->entire_length = GUINT64_FROM_LE((x)->entire_length); \ - (x)->this_length = GUINT64_FROM_LE((x)->this_length); \ - (x)->packet_num = GUINT64_FROM_LE((x)->packet_num); \ - (x)->operation = GUINT64_FROM_LE((x)->operation); + (x)->entire_length = le64toh((x)->entire_length); \ + (x)->this_length = le64toh((x)->this_length); \ + (x)->packet_num = le64toh((x)->packet_num); \ + (x)->operation = le64toh((x)->operation); typedef struct { uint64_t filehandle, size; diff --git a/src/debug.c b/src/debug.c index 26a9678..ece2b1d 100644 --- a/src/debug.c +++ b/src/debug.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "debug.h" #include "libimobiledevice/libimobiledevice.h" @@ -54,7 +55,7 @@ static void debug_print_line(const char *func, const char *file, int line, const time_t the_time; time(&the_time); - str_time = g_new0 (gchar, 255); + str_time = (char*)malloc(255); strftime(str_time, 254, "%H:%M:%S", localtime (&the_time)); /* generate header text */ diff --git a/src/debug.h b/src/debug.h index 2fd0960..cb1bf97 100644 --- a/src/debug.h +++ b/src/debug.h @@ -24,7 +24,14 @@ #define DEBUG_H #include -#include + +#ifndef LIBIMOBILEDEVICE_INTERNAL +#ifdef WIN32 +#define LIBIMOBILEDEVICE_INTERNAL +#else +#define LIBIMOBILEDEVICE_INTERNAL __attribute__((visibility("hidden"))) +#endif +#endif #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && !defined(STRIP_DEBUG_CODE) #define debug_info(...) debug_info_real (__func__, __FILE__, __LINE__, __VA_ARGS__) @@ -37,14 +44,14 @@ #define debug_plist(a) #endif -G_GNUC_INTERNAL inline void debug_info_real(const char *func, +LIBIMOBILEDEVICE_INTERNAL inline void debug_info_real(const char *func, const char *file, int line, const char *format, ...); -G_GNUC_INTERNAL inline void debug_buffer(const char *data, const int length); -G_GNUC_INTERNAL inline void debug_buffer_to_file(const char *file, const char *data, const int length); -G_GNUC_INTERNAL inline void debug_plist_real(const char *func, +LIBIMOBILEDEVICE_INTERNAL inline void debug_buffer(const char *data, const int length); +LIBIMOBILEDEVICE_INTERNAL inline void debug_buffer_to_file(const char *file, const char *data, const int length); +LIBIMOBILEDEVICE_INTERNAL inline void debug_plist_real(const char *func, const char *file, int line, plist_t plist); diff --git a/src/house_arrest.h b/src/house_arrest.h index 6d13a88..708f1b5 100644 --- a/src/house_arrest.h +++ b/src/house_arrest.h @@ -21,8 +21,6 @@ #ifndef IHOUSE_ARREST_H #define IHOUSE_ARREST_H -#include - #include "libimobiledevice/house_arrest.h" #include "property_list_service.h" diff --git a/src/lockdown.c b/src/lockdown.c index 1783df6..424cf89 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -26,7 +26,6 @@ #define __USE_GNU 1 #include #include -#include #include #include #include @@ -1200,8 +1199,8 @@ lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datu memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size); oroot_cert->size = pem_root_cert.size; - g_free(pem_root_cert.data); - g_free(pem_host_cert.data); + free(pem_root_cert.data); + free(pem_host_cert.data); if (dev_pem.data) gnutls_free(dev_pem.data); diff --git a/src/mobilesync.c b/src/mobilesync.c index e600452..9b31ad5 100644 --- a/src/mobilesync.c +++ b/src/mobilesync.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "mobilesync.h" #include "device_link_service.h" diff --git a/src/property_list_service.c b/src/property_list_service.c index 8af958e..47b119f 100644 --- a/src/property_list_service.c +++ b/src/property_list_service.c @@ -20,7 +20,6 @@ */ #include #include -#include #include "property_list_service.h" #include "idevice.h" @@ -138,7 +137,7 @@ static property_list_service_error_t internal_plist_send(property_list_service_c return PROPERTY_LIST_SERVICE_E_PLIST_ERROR; } - nlen = GUINT32_TO_BE(length); + nlen = htobe32(length); debug_info("sending %d bytes", length); idevice_connection_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); if (bytes == sizeof(nlen)) { @@ -226,7 +225,7 @@ static property_list_service_error_t internal_plist_receive_timeout(property_lis debug_info("initial read failed!"); return PROPERTY_LIST_SERVICE_E_MUX_ERROR; } else { - pktlen = GUINT32_FROM_BE(pktlen); + pktlen = be32toh(pktlen); if (pktlen < (1 << 24)) { /* prevent huge buffers */ uint32_t curlen = 0; char *content = NULL; diff --git a/src/restore.c b/src/restore.c index 031eaea..eedddab 100644 --- a/src/restore.c +++ b/src/restore.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "property_list_service.h" diff --git a/src/userpref.c b/src/userpref.c index 4aab67b..d44d5aa 100644 --- a/src/userpref.c +++ b/src/userpref.c @@ -19,9 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include #include #include #include @@ -30,6 +27,15 @@ #include #include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#endif + #include "userpref.h" #include "debug.h" @@ -41,18 +47,239 @@ #define LIBIMOBILEDEVICE_ROOT_CERTIF "RootCertificate.pem" #define LIBIMOBILEDEVICE_HOST_CERTIF "HostCertificate.pem" +#ifdef WIN32 +#define DIR_SEP '\\' +#define DIR_SEP_S "\\" +#else +#define DIR_SEP '/' +#define DIR_SEP_S "/" +#endif + +static char __config_dir[512] = {0, }; + +#ifdef WIN32 +static char *userpref_utf16_to_utf8(wchar_t *unistr, long len, long *items_read, long *items_written) +{ + if (!unistr || (len <= 0)) return NULL; + char *outbuf = (char*)malloc(3*(len+1)); + int p = 0; + int i = 0; + + wchar_t wc; + + while (i < len) { + wc = unistr[i++]; + if (wc >= 0x800) { + outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF)); + outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F)); + outbuf[p++] = (char)(0x80 + (wc & 0x3F)); + } else if (wc >= 0x80) { + outbuf[p++] = (char)(0xC0 + ((wc >> 6) & 0x1F)); + outbuf[p++] = (char)(0x80 + (wc & 0x3F)); + } else { + outbuf[p++] = (char)(wc & 0x7F); + } + } + if (items_read) { + *items_read = i; + } + if (items_written) { + *items_written = p; + } + outbuf[p] = 0; + + return outbuf; +} +#endif + +static const char *userpref_get_config_dir() +{ + if (__config_dir[0]) return __config_dir; +#ifdef WIN32 + wchar_t path[MAX_PATH+1]; + HRESULT hr; + LPITEMIDLIST pidl = NULL; + BOOL b = FALSE; + + hr = SHGetSpecialFolderLocation (NULL, CSIDL_LOCAL_APPDATA, &pidl); + if (hr == S_OK) { + b = SHGetPathFromIDListW (pidl, path); + if (b) { + char *cdir = userpref_utf16_to_utf8 (path, wcslen(path), NULL, NULL); + strcpy(__config_dir, cdir); + free(cdir); + CoTaskMemFree (pidl); + } + } +#else + const char *cdir = getenv("XDG_CONFIG_HOME"); + if (!cdir) { + cdir = getenv("HOME"); + strcpy(__config_dir, cdir); + strcat(__config_dir, DIR_SEP_S); + strcat(__config_dir, ".config"); + } else { + strcpy(__config_dir, cdir); + } +#endif + strcat(__config_dir, DIR_SEP_S); + strcat(__config_dir, LIBIMOBILEDEVICE_CONF_DIR); + + int i = strlen(__config_dir)-1; + while ((i > 0) && (__config_dir[i] == DIR_SEP)) { + __config_dir[i--] = '\0'; + } + + return __config_dir; +} + +static int mkdir_with_parents(const char *dir, int mode) +{ + if (!dir) return -1; + if (mkdir(dir, mode) == 0) { + return 0; + } else { + if (errno == EEXIST) return 0; + } + int res; + char *parent = strdup(dir); + parent = dirname(parent); + if (parent) { + res = mkdir_with_parents(parent, mode); + } else { + res = -1; + } + free(parent); + if (res == 0) { + mkdir_with_parents(dir, mode); + } + return res; +} + +static int config_write(const char *cfgfile, plist_t dict) +{ + if (!cfgfile || !dict || (plist_get_node_type(dict) != PLIST_DICT)) { + return -1; + } + int res = -1; + +#if 1 // old style config + plist_t hostid = plist_dict_get_item(dict, "HostID"); + if (hostid && (plist_get_node_type(hostid) == PLIST_STRING)) { + char *hostidstr = NULL; + plist_get_string_val(hostid, &hostidstr); + if (hostidstr) { + FILE *fd = fopen(cfgfile, "w"); + if (fd) { + fprintf(fd, "\n[Global]\nHostID=%s\n", hostidstr); + fclose(fd); + res = 0; + } + free(hostidstr); + } + } +#endif +#if 0 + char *xml = NULL; + uint32_t length = 0; + + plist_to_xml(dict, &xml, &length); + if (!xml) { + return res; + } + + FILE *fd = fopen(cfgfile, "w"); + if (!fd) { + free(xml); + return res; + } + + if (fwrite(xml, 1, length, fd) == length) { + res = 0; + } else { + fprintf(stderr, "%s: ERROR: failed to write configuration to '%s'\n", __func__, cfgfile); + } + fclose(fd); + + free(xml); +#endif + return res; +} + +static int config_read(const char *cfgfile, plist_t *dict) +{ + if (!cfgfile || !dict) { + return -1; + } + + int res = -1; + FILE *fd = fopen(cfgfile, "r+"); + if (!fd) { + return -1; + } + + fseek(fd, 0, SEEK_END); + unsigned long int size = ftell(fd); + fseek(fd, 0, SEEK_SET); + unsigned char *contents = NULL; + + contents = malloc(size); + if (fread(contents, 1, size, fd) != size) { + free(contents); + fclose(fd); + return -1; + } + plist_t plist = NULL; + + if (!memcmp(contents, "bplist00", 8)) { + plist_from_bin((const char*)contents, (uint32_t)size, &plist); + fclose(fd); + } else { + if (memchr(contents, '<', size)) { + plist_from_xml((const char*)contents, (uint32_t)size, &plist); + } + if (plist) { + fclose(fd); + } else { + // try parsing old format config file + char line[256]; + fseek(fd, 0, SEEK_SET); + while (fgets(line, 256, fd)) { + size_t llen = strlen(line)-1; + while ((llen > 0) && ((line[llen] == '\n') || (line[llen] == '\r'))) { + line[llen] = '\0'; + } + if (!strncmp(line, "HostID=", 7)) { + plist = plist_new_dict(); + plist_dict_insert_item(plist, "HostID", plist_new_string(line+7)); + break; + } + } + fclose(fd); + if (plist) { + // write new format config + config_write(cfgfile, plist); + } + } + } + free(contents); + if (plist) { + *dict = plist; + res = 0; + } + return res; +} /** * Creates a freedesktop compatible configuration directory. */ static void userpref_create_config_dir(void) { - gchar *config_dir = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, NULL); - - if (!g_file_test(config_dir, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) - g_mkdir_with_parents(config_dir, 0755); - - g_free(config_dir); + const char *config_path = userpref_get_config_dir(); + struct stat st; + if (stat(config_path, &st) != 0) { + mkdir_with_parents(config_path, 0755); + } } static int get_rand(int min, int max) @@ -94,10 +321,8 @@ static char *userpref_generate_host_id() */ static int userpref_set_host_id(const char *host_id) { - GKeyFile *key_file; - gsize length; - gchar *buf, *config_file; - GIOChannel *file; + const char *config_path; + char *config_file; if (!host_id) return 0; @@ -105,24 +330,34 @@ static int userpref_set_host_id(const char *host_id) /* Make sure config directory exists */ userpref_create_config_dir(); + config_path = userpref_get_config_dir(); + config_file = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_CONF_FILE)+1); + strcpy(config_file, config_path); + strcat(config_file, DIR_SEP_S); + strcat(config_file, LIBIMOBILEDEVICE_CONF_FILE); + /* Now parse file to get the HostID */ - key_file = g_key_file_new(); + plist_t config = NULL; + config_read(config_file, &config); + if (!config) { + config = plist_new_dict(); + plist_dict_insert_item(config, "HostID", plist_new_string(host_id)); + } else { + plist_t n = plist_dict_get_item(config, "HostID"); + if (n) { + plist_set_string_val(n, host_id); + } else { + plist_dict_insert_item(config, "HostID", plist_new_string(host_id)); + } + } /* Store in config file */ debug_info("setting hostID to %s", host_id); - g_key_file_set_value(key_file, "Global", "HostID", host_id); - - /* Write config file on disk */ - buf = g_key_file_to_data(key_file, &length, NULL); - config_file = - g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_CONF_FILE, NULL); - file = g_io_channel_new_file(config_file, "w", NULL); - g_free(config_file); - g_io_channel_write_chars(file, buf, length, NULL, NULL); - g_io_channel_shutdown(file, TRUE, NULL); - g_io_channel_unref(file); - - g_key_file_free(key_file); + + config_write(config_file, config); + plist_free(config); + + free(config_file); return 1; } @@ -135,23 +370,25 @@ static int userpref_set_host_id(const char *host_id) */ void userpref_get_host_id(char **host_id) { - gchar *config_file; - GKeyFile *key_file; - gchar *loc_host_id; + const char *config_path; + char *config_file; - config_file = - g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_CONF_FILE, NULL); + config_path = userpref_get_config_dir(); + config_file = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_CONF_FILE)+1); + strcpy(config_file, config_path); + strcat(config_file, DIR_SEP_S); + strcat(config_file, LIBIMOBILEDEVICE_CONF_FILE); /* now parse file to get the HostID */ - key_file = g_key_file_new(); - if (g_key_file_load_from_file(key_file, config_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) { - loc_host_id = g_key_file_get_value(key_file, "Global", "HostID", NULL); - if (loc_host_id) - *host_id = strdup((char *) loc_host_id); - g_free(loc_host_id); + plist_t config = NULL; + if (config_read(config_file, &config) == 0) { + plist_t n_host_id = plist_dict_get_item(config, "HostID"); + if (n_host_id && (plist_get_node_type(n_host_id) == PLIST_STRING)) { + plist_get_string_val(n_host_id, host_id); + } } - g_key_file_free(key_file); - g_free(config_file); + plist_free(config); + free(config_file); if (!*host_id) { /* no config, generate host_id */ @@ -173,15 +410,23 @@ void userpref_get_host_id(char **host_id) int userpref_has_device_public_key(const char *uuid) { int ret = 0; - gchar *config_file; + const char *config_path; + char *config_file; + struct stat st; + + if (!uuid) return 0; /* first get config file */ - gchar *device_file = g_strconcat(uuid, ".pem", NULL); - config_file = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, device_file, NULL); - if (g_file_test(config_file, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) + config_path = userpref_get_config_dir(); + config_file = (char*)malloc(strlen(config_path)+1+strlen(uuid)+4+1); + strcpy(config_file, config_path); + strcat(config_file, DIR_SEP_S); + strcat(config_file, uuid); + strcat(config_file, ".pem"); + + if ((stat(config_file, &st) == 0) && S_ISREG(st.st_mode)) ret = 1; - g_free(config_file); - g_free(device_file); + free(config_file); return ret; } @@ -202,10 +447,13 @@ int userpref_has_device_public_key(const char *uuid) */ userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count) { - GDir *config_dir; - gchar *config_path; - const gchar *dir_file; - GList *uuids = NULL; + struct slist_t { + char *name; + void *next; + }; + DIR *config_dir; + const char *config_path; + struct slist_t *uuids = NULL; unsigned int i; unsigned int found = 0; @@ -218,29 +466,44 @@ userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count) *count = 0; } - config_path = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, NULL); - - config_dir = g_dir_open(config_path,0,NULL); + config_path = userpref_get_config_dir(); + config_dir = opendir(config_path); if (config_dir) { - while ((dir_file = g_dir_read_name(config_dir))) { - if (g_str_has_suffix(dir_file, ".pem") && (strlen(dir_file) == 44)) { - uuids = g_list_append(uuids, g_strndup(dir_file, strlen(dir_file)-4)); + struct dirent *entry; + struct slist_t *listp = uuids; + while ((entry = readdir(config_dir))) { + char *ext = strstr(entry->d_name, ".pem"); + if (ext && ((ext - entry->d_name) == 40) && (strlen(entry->d_name) == 44)) { + struct slist_t *ne = (struct slist_t*)malloc(sizeof(struct slist_t)); + ne->name = (char*)malloc(41); + strncpy(ne->name, entry->d_name, 40); + ne->name[40] = 0; + ne->next = NULL; + if (!listp) { + listp = ne; + uuids = listp; + } else { + listp->next = ne; + listp = listp->next; + } found++; } } - g_dir_close(config_dir); + closedir(config_dir); } *list = (char**)malloc(sizeof(char*) * (found+1)); - for (i = 0; i < found; i++) { - (*list)[i] = g_list_nth_data(uuids, i); + i = 0; + while (uuids) { + (*list)[i++] = uuids->name; + struct slist_t *old = uuids; + uuids = uuids->next; + free(old); } (*list)[i] = NULL; if (count) { *count = found; } - g_list_free(uuids); - g_free(config_path); return USERPREF_E_SUCCESS; } @@ -266,15 +529,18 @@ userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t userpref_create_config_dir(); /* build file path */ - gchar *device_file = g_strconcat(uuid, ".pem", NULL); - gchar *pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, device_file, NULL); + const char *config_path = userpref_get_config_dir(); + char *pem = (char*)malloc(strlen(config_path)+1+strlen(uuid)+4+1); + strcpy(pem, config_path); + strcat(pem, DIR_SEP_S); + strcat(pem, uuid); + strcat(pem, ".pem"); /* store file */ FILE *pFile = fopen(pem, "wb"); fwrite(public_key.data, 1, public_key.size, pFile); fclose(pFile); - g_free(pem); - g_free(device_file); + free(pem); return USERPREF_E_SUCCESS; } @@ -292,14 +558,17 @@ userpref_error_t userpref_remove_device_public_key(const char *uuid) return USERPREF_E_SUCCESS; /* build file path */ - gchar *device_file = g_strconcat(uuid, ".pem", NULL); - gchar *pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, device_file, NULL); + const char *config_path = userpref_get_config_dir(); + char *pem = (char*)malloc(strlen(config_path)+1+strlen(uuid)+4+1); + strcpy(pem, config_path); + strcat(pem, DIR_SEP_S); + strcat(pem, uuid); + strcat(pem, ".pem"); /* remove file */ - g_remove(pem); + remove(pem); - g_free(pem); - g_free(device_file); + free(pem); return USERPREF_E_SUCCESS; } @@ -314,18 +583,50 @@ userpref_error_t userpref_remove_device_public_key(const char *uuid) */ static int userpref_get_file_contents(const char *file, gnutls_datum_t * data) { - gboolean success; - gsize size; - char *content; - gchar *filepath; + int success; + unsigned long int size = 0; + unsigned char *content = NULL; + const char *config_path; + char *filepath; + FILE *fd; if (NULL == file || NULL == data) return 0; /* Read file */ - filepath = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, file, NULL); - success = g_file_get_contents(filepath, &content, &size, NULL); - g_free(filepath); + config_path = userpref_get_config_dir(); + filepath = (char*)malloc(strlen(config_path)+1+strlen(file)+1); + strcpy(filepath, config_path); + strcat(filepath, DIR_SEP_S); + strcat(filepath, file); + + fd = fopen(filepath, "rb"); + if (fd) { + fseek(fd, 0, SEEK_END); + size = ftell(fd); + fseek(fd, 0, SEEK_SET); + + // prevent huge files + if (size > 0xFFFFFF) { + fprintf(stderr, "%s: file is too big (> 16MB). Refusing to read the contents to memory!", __func__); + } else { + size_t p = 0; + content = (unsigned char*)malloc(size); + while (!feof(fd)) { + p += fread(content+p, 1, size-p, fd); + if (ferror(fd) != 0) { + break; + } + if (p >= size) { + success = 1; + break; + } + } + } + fclose(fd); + } + + free(filepath); /* Add it to the gnutls_datnum_t structure */ if (success) { @@ -549,8 +850,8 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert)) return USERPREF_E_SUCCESS; else { - g_free(pem_root_cert->data); - g_free(pem_host_cert->data); + gnutls_free(pem_root_cert->data); + gnutls_free(pem_host_cert->data); } return USERPREF_E_INVALID_CONF; } @@ -570,7 +871,8 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert) { FILE *pFile; - gchar *pem; + char *pem; + const char *config_path; if (!root_key || !host_key || !root_cert || !host_cert) return USERPREF_E_INVALID_ARG; @@ -578,30 +880,44 @@ userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_d /* Make sure config directory exists */ userpref_create_config_dir(); + config_path = userpref_get_config_dir(); + /* Now write keys and certificates to disk */ - pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_ROOT_PRIVKEY, NULL); + pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_ROOT_PRIVKEY)+1); + strcpy(pem, config_path); + strcat(pem, DIR_SEP_S); + strcat(pem, LIBIMOBILEDEVICE_ROOT_PRIVKEY); pFile = fopen(pem, "wb"); fwrite(root_key->data, 1, root_key->size, pFile); fclose(pFile); - g_free(pem); + free(pem); - pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_HOST_PRIVKEY, NULL); + pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_HOST_PRIVKEY)+1); + strcpy(pem, config_path); + strcat(pem, DIR_SEP_S); + strcat(pem, LIBIMOBILEDEVICE_HOST_PRIVKEY); pFile = fopen(pem, "wb"); fwrite(host_key->data, 1, host_key->size, pFile); fclose(pFile); - g_free(pem); + free(pem); - pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_ROOT_CERTIF, NULL); + pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_ROOT_CERTIF)+1); + strcpy(pem, config_path); + strcat(pem, DIR_SEP_S); + strcat(pem, LIBIMOBILEDEVICE_ROOT_CERTIF); pFile = fopen(pem, "wb"); fwrite(root_cert->data, 1, root_cert->size, pFile); fclose(pFile); - g_free(pem); + free(pem); - pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIMOBILEDEVICE_CONF_DIR, LIBIMOBILEDEVICE_HOST_CERTIF, NULL); + pem = (char*)malloc(strlen(config_path)+1+strlen(LIBIMOBILEDEVICE_HOST_CERTIF)+1); + strcpy(pem, config_path); + strcat(pem, DIR_SEP_S); + strcat(pem, LIBIMOBILEDEVICE_HOST_CERTIF); pFile = fopen(pem, "wb"); fwrite(host_cert->data, 1, host_cert->size, pFile); fclose(pFile); - g_free(pem); + free(pem); return USERPREF_E_SUCCESS; } diff --git a/src/userpref.h b/src/userpref.h index f9d3913..e16fd65 100644 --- a/src/userpref.h +++ b/src/userpref.h @@ -23,7 +23,14 @@ #define USERPREF_H #include -#include + +#ifndef LIBIMOBILEDEVICE_INTERNAL +#ifdef WIN32 +#define LIBIMOBILEDEVICE_INTERNAL +#else +#define LIBIMOBILEDEVICE_INTERNAL __attribute__((visibility("hidden"))) +#endif +#endif #define USERPREF_E_SUCCESS 0 #define USERPREF_E_INVALID_ARG -1 @@ -34,12 +41,12 @@ typedef int16_t userpref_error_t; -G_GNUC_INTERNAL userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt); -G_GNUC_INTERNAL userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert); -G_GNUC_INTERNAL userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert); -G_GNUC_INTERNAL userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key); +LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt); +LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert); +LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert); +LIBIMOBILEDEVICE_INTERNAL userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key); userpref_error_t userpref_remove_device_public_key(const char *uuid); -G_GNUC_INTERNAL int userpref_has_device_public_key(const char *uuid); +LIBIMOBILEDEVICE_INTERNAL int userpref_has_device_public_key(const char *uuid); userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count); void userpref_get_host_id(char **host_id); -- cgit v1.1-32-gdbae