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.

---
 configure.ac                                  |  16 +-
 dev/Makefile.am                               |  14 +-
 dev/ideviceclient.c                           |   9 +-
 include/libimobiledevice/installation_proxy.h |   3 +-
 include/libimobiledevice/mobilesync.h         |   3 +-
 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 +-
 tools/Makefile.am                             |  18 +-
 tools/ideviceimagemounter.c                   |  25 +-
 tools/ideviceinfo.c                           |  66 +++-
 tools/idevicepair.c                           |   3 +-
 tools/idevicesyslog.c                         |   3 +-
 22 files changed, 583 insertions(+), 170 deletions(-)

diff --git a/configure.ac b/configure.ac
index 5078afd..98b0008 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,12 +27,15 @@ AC_PROG_LIBTOOL
 
 # Checks for libraries.
 PKG_CHECK_MODULES(libusbmuxd, libusbmuxd >= 0.1.4)
-PKG_CHECK_MODULES(libglib2, glib-2.0 >= 2.14.1)
 PKG_CHECK_MODULES(libgnutls, gnutls >= 2.2.0)
 PKG_CHECK_MODULES(libtasn1, libtasn1 >= 1.1)
 PKG_CHECK_MODULES(libplist, libplist >= 0.15)
 PKG_CHECK_MODULES(libplistmm, libplist++ >= 0.15)
 AC_CHECK_LIB(gcrypt, gcry_control, [AC_SUBST(libgcrypt_LIBS,[-lgcrypt])], [AC_MSG_ERROR([libgcrypt is required to build libimobiledevice])])
+AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])])
+
+PKG_CHECK_MODULES(libglib2, glib-2.0 >= 2.14.1, enable_glib2=yes, enable_glib2=no)
+AM_CONDITIONAL([HAVE_GLIB2],[test "x$enable_glib2" == "xyes"])
 
 # Checks for header files.
 AC_HEADER_STDC
@@ -51,6 +54,17 @@ AC_FUNC_MALLOC
 AC_FUNC_REALLOC
 AC_CHECK_FUNCS([strcasecmp strdup strerror strndup])
 
+AC_DEFINE(LITTLE_ENDIAN,0,[little endian])
+AC_DEFINE(BIG_ENDIAN,1,[big endian])
+AC_C_BIGENDIAN([ac_cv_c_bigendian="yes"], [ac_cv_c_bigendian="no"], [], [])
+if test "x$ac_cv_c_bigendian" = "xyes"; then
+    AC_DEFINE(BYTE_ORDER,1,[big endian byte order])
+else
+    AC_DEFINE(BYTE_ORDER,0,[little endian byte order])
+fi
+
+
+
 AC_ARG_WITH([swig],
             [AS_HELP_STRING([--without-swig],
             [build Python bindings using swig (default is yes)])],
diff --git a/dev/Makefile.am b/dev/Makefile.am
index 72c00a3..c1d2b45 100644
--- a/dev/Makefile.am
+++ b/dev/Makefile.am
@@ -1,10 +1,14 @@
 AM_CPPFLAGS = -I$(top_srcdir)/include
 
-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(LFS_CFLAGS)
-AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS)
+AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(LFS_CFLAGS)
+AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libpthread_LIBS)
 
 if ENABLE_DEVTOOLS
-noinst_PROGRAMS = ideviceclient lckd-client afccheck filerelaytest housearresttest
+noinst_PROGRAMS = ideviceclient afccheck filerelaytest housearresttest
+
+if HAVE_GLIB2
+noinst_PROGRAMS += lckd-client
+endif
 
 ideviceclient_SOURCES = ideviceclient.c
 ideviceclient_CFLAGS = $(AM_CFLAGS)
@@ -12,8 +16,8 @@ ideviceclient_LDFLAGS = $(AM_LDFLAGS)
 ideviceclient_LDADD = ../src/libimobiledevice.la
 
 lckd_client_SOURCES = lckdclient.c
-lckd_client_CFLAGS = $(AM_CFLAGS)
-lckd_client_LDFLAGS = -lreadline $(AM_LDFLAGS)
+lckd_client_CFLAGS = $(AM_CFLAGS) $(libglib2_CFLAGS)
+lckd_client_LDFLAGS = -lreadline $(AM_LDFLAGS) $(libglib2_LIBS)
 lckd_client_LDADD = ../src/libimobiledevice.la
 
 afccheck_SOURCES = afccheck.c
diff --git a/dev/ideviceclient.c b/dev/ideviceclient.c
index d952594..0400fed 100644
--- a/dev/ideviceclient.c
+++ b/dev/ideviceclient.c
@@ -23,7 +23,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <glib.h>
 
 #include <libimobiledevice/libimobiledevice.h>
 #include <libimobiledevice/lockdown.h>
@@ -138,18 +137,20 @@ int main(int argc, char *argv[])
 			printf("Directory time.\n");
 			for (i = 0; dirs[i]; i++) {
 				printf("/%s\n", dirs[i]);
+				free(dirs[i]);
 			}
-
-			g_strfreev(dirs);
+			if (dirs)
+				free(dirs);
 
 			dirs = NULL;
 			afc_get_device_info(afc, &dirs);
 			if (dirs) {
 				for (i = 0; dirs[i]; i += 2) {
 					printf("%s: %s\n", dirs[i], dirs[i + 1]);
+					free(dirs[i]);
 				}
+				free(dirs);
 			}
-			g_strfreev(dirs);
 
 			uint64_t my_file = 0;
 			char **info = NULL;
diff --git a/include/libimobiledevice/installation_proxy.h b/include/libimobiledevice/installation_proxy.h
index f5f00e8..11fb66e 100644
--- a/include/libimobiledevice/installation_proxy.h
+++ b/include/libimobiledevice/installation_proxy.h
@@ -28,7 +28,6 @@ extern "C" {
 #endif
 
 #include <libimobiledevice/libimobiledevice.h>
-#include <glib.h>
 
 /** @name Error Codes */
 /*@{*/
@@ -66,7 +65,7 @@ instproxy_error_t instproxy_restore(instproxy_client_t client, const char *appid
 instproxy_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);
 
 plist_t instproxy_client_options_new();
-void instproxy_client_options_add(plist_t client_options, ...) G_GNUC_NULL_TERMINATED;
+void instproxy_client_options_add(plist_t client_options, ...);
 void instproxy_client_options_free(plist_t client_options);
 
 #ifdef __cplusplus
diff --git a/include/libimobiledevice/mobilesync.h b/include/libimobiledevice/mobilesync.h
index 7658b7d..bd717ee 100644
--- a/include/libimobiledevice/mobilesync.h
+++ b/include/libimobiledevice/mobilesync.h
@@ -29,7 +29,6 @@ extern "C" {
 #endif
 
 #include <libimobiledevice/libimobiledevice.h>
-#include <glib.h>
 
 /** @name Error Codes */
 /*@{*/
@@ -93,7 +92,7 @@ mobilesync_anchors_t mobilesync_anchors_new(const char *device_anchor, const cha
 void mobilesync_anchors_free(mobilesync_anchors_t anchors);
 
 plist_t mobilesync_actions_new();
-void mobilesync_actions_add(plist_t actions, ...) G_GNUC_NULL_TERMINATED;
+void mobilesync_actions_add(plist_t actions, ...);
 void mobilesync_actions_free(plist_t actions);
 
 #ifdef __cplusplus
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 <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <time.h>
 
 #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 <plist/plist.h>
-#include <glib.h>
+
+#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 <glib.h>
-
 #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 <stdio.h>
 #include <ctype.h>
-#include <glib.h>
 #include <libtasn1.h>
 #include <gnutls/x509.h>
 #include <plist/plist.h>
@@ -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 <string.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <glib.h>
 
 #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 <stdlib.h>
 #include <string.h>
-#include <glib.h>
 
 #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 <errno.h>
 #include <string.h>
 #include <stdlib.h>
-#include <glib.h>
 #include <plist/plist.h>
 
 #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 <glib.h>
-#include <glib/gstdio.h>
-#include <glib/gprintf.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -30,6 +27,15 @@
 #include <gnutls/x509.h>
 #include <gcrypt.h>
 
+#include <dirent.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef WIN32
+#include <shlobj.h>
+#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 <gnutls/gnutls.h>
-#include <glib.h>
+
+#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);
 
diff --git a/tools/Makefile.am b/tools/Makefile.am
index bb13eb9..f23b0b1 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,9 +1,13 @@
 AM_CPPFLAGS = -I$(top_srcdir)/include
 
-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(LFS_CFLAGS)
-AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS)
+AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(LFS_CFLAGS)
+AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS)
 
-bin_PROGRAMS = idevice_id ideviceinfo idevicepair idevicesyslog idevicebackup idevicebackup2 ideviceimagemounter idevicescreenshot ideviceenterrecovery idevicedate
+bin_PROGRAMS = idevice_id ideviceinfo idevicepair idevicesyslog ideviceimagemounter idevicescreenshot ideviceenterrecovery idevicedate
+
+if HAVE_GLIB2
+bin_PROGRAMS += idevicebackup idevicebackup2
+endif
 
 ideviceinfo_SOURCES = ideviceinfo.c
 ideviceinfo_CFLAGS = $(AM_CFLAGS)
@@ -26,13 +30,13 @@ idevice_id_LDFLAGS = $(AM_LDFLAGS)
 idevice_id_LDADD = ../src/libimobiledevice.la
 
 idevicebackup_SOURCES = idevicebackup.c
-idevicebackup_CFLAGS = $(AM_CFLAGS)
-idevicebackup_LDFLAGS = $(AM_LDFLAGS)
+idevicebackup_CFLAGS = $(AM_CFLAGS) $(libglib2_CFLAGS)
+idevicebackup_LDFLAGS = $(AM_LDFLAGS) $(libglib2_LIBS)
 idevicebackup_LDADD = ../src/libimobiledevice.la
 
 idevicebackup2_SOURCES = idevicebackup2.c
-idevicebackup2_CFLAGS = $(AM_CFLAGS)
-idevicebackup2_LDFLAGS = $(AM_LDFLAGS)
+idevicebackup2_CFLAGS = $(AM_CFLAGS) $(libglib2_CFLAGS)
+idevicebackup2_LDFLAGS = $(AM_LDFLAGS) $(libglib2_LIBS)
 idevicebackup2_LDADD = ../src/libimobiledevice.la
 
 ideviceimagemounter_SOURCES = ideviceimagemounter.c
diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c
index 3fb4ac5..b4512f5 100644
--- a/tools/ideviceimagemounter.c
+++ b/tools/ideviceimagemounter.c
@@ -28,8 +28,9 @@
 #include <string.h>
 #include <getopt.h>
 #include <errno.h>
-#include <glib.h>
 #include <libgen.h>
+#include <time.h>
+#include <sys/time.h>
 
 #include <libimobiledevice/libimobiledevice.h>
 #include <libimobiledevice/lockdown.h>
@@ -165,7 +166,7 @@ static void plist_node_to_string(plist_t node)
 	double d;
 	uint8_t b;
 	uint64_t u = 0;
-	GTimeVal tv = { 0, 0 };
+	struct timeval tv = { 0, 0 };
 
 	plist_type t;
 
@@ -214,9 +215,23 @@ static void plist_node_to_string(plist_t node)
 
 	case PLIST_DATE:
 		plist_get_date_val(node, (int32_t*)&tv.tv_sec, (int32_t*)&tv.tv_usec);
-		s = g_time_val_to_iso8601(&tv);
-		printf("%s\n", s);
-		free(s);
+		{
+			time_t ti = (time_t)tv.tv_sec;
+			struct tm *btime = localtime(&ti);
+			if (btime) {
+				s = (char*)malloc(24);
+ 				memset(s, 0, 24);
+				if (strftime(s, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) {
+					free (s);
+					s = NULL;
+				}
+			}
+		}
+		if (s) {
+			puts(s);
+			free(s);
+		}
+		puts("\n");
 		break;
 
 	case PLIST_ARRAY:
diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c
index c5c060e..6633459 100644
--- a/tools/ideviceinfo.c
+++ b/tools/ideviceinfo.c
@@ -23,7 +23,8 @@
 #include <string.h>
 #include <errno.h>
 #include <stdlib.h>
-#include <glib.h>
+#include <time.h>
+#include <sys/time.h>
 
 #include <libimobiledevice/libimobiledevice.h>
 #include <libimobiledevice/lockdown.h>
@@ -58,6 +59,36 @@ static const char *domains[] = {
 	NULL
 };
 
+static const char base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char base64_pad = '=';
+
+static char *base64encode(const unsigned char *buf, size_t size)
+{
+	if (!buf || !(size > 0)) return NULL;
+	int outlen = (size / 3) * 4;
+	char *outbuf = (char*)malloc(outlen+5); // 4 spare bytes + 1 for '\0'
+	size_t n = 0;
+	size_t m = 0;
+	unsigned char input[3];
+	unsigned int output[4];
+	while (n < size) {
+		input[0] = buf[n];
+		input[1] = (n+1 < size) ? buf[n+1] : 0;
+		input[2] = (n+2 < size) ? buf[n+2] : 0;
+		output[0] = input[0] >> 2;
+		output[1] = ((input[0] & 3) << 4) + (input[1] >> 4);
+		output[2] = ((input[1] & 15) << 2) + (input[2] >> 6);
+		output[3] = input[2] & 63;
+		outbuf[m++] = base64_str[(int)output[0]];
+		outbuf[m++] = base64_str[(int)output[1]];
+		outbuf[m++] = (n+1 < size) ? base64_str[(int)output[2]] : base64_pad;
+		outbuf[m++] = (n+2 < size) ? base64_str[(int)output[3]] : base64_pad;
+		n+=3;
+	}
+	outbuf[m] = 0; // 0-termination!
+	return outbuf;
+}
+
 static int indent_level = 0;
 
 static int is_domain_known(char *domain)
@@ -121,7 +152,7 @@ static void plist_node_to_string(plist_t node)
 	double d;
 	uint8_t b;
 	uint64_t u = 0;
-	GTimeVal tv = { 0, 0 };
+	struct timeval tv = { 0, 0 };
 
 	plist_type t;
 
@@ -161,10 +192,14 @@ static void plist_node_to_string(plist_t node)
 	case PLIST_DATA:
 		plist_get_data_val(node, &data, &u);
 		if (u > 0) {
-			s = g_base64_encode((guchar *)data, u);
+			s = base64encode((unsigned char*)data, u);
 			free(data);
-			printf("%s\n", s);
-			g_free(s);
+			if (s) {
+				printf("%s\n", s);
+				free(s);
+			} else {
+				printf("\n");
+			}
 		} else {
 			printf("\n");
 		}
@@ -172,9 +207,24 @@ static void plist_node_to_string(plist_t node)
 
 	case PLIST_DATE:
 		plist_get_date_val(node, (int32_t*)&tv.tv_sec, (int32_t*)&tv.tv_usec);
-		s = g_time_val_to_iso8601(&tv);
-		printf("%s\n", s);
-		free(s);
+		{
+			time_t ti = (time_t)tv.tv_sec;
+			struct tm *btime = localtime(&ti);
+			if (btime) {
+				s = (char*)malloc(24);
+ 				memset(s, 0, 24);
+				if (strftime(s, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) {
+					free (s);
+					s = NULL;
+				}
+			}
+		}
+		if (s) {
+			printf("%s\n", s);
+			free(s);
+		} else {
+			printf("\n");
+		}
 		break;
 
 	case PLIST_ARRAY:
diff --git a/tools/idevicepair.c b/tools/idevicepair.c
index b9676b9..9eebc5c 100644
--- a/tools/idevicepair.c
+++ b/tools/idevicepair.c
@@ -148,9 +148,10 @@ int main(int argc, char **argv)
 		userpref_get_paired_uuids(&uuids, &count);
 		for (i = 0; i < count; i++) {
 			printf("%s\n", uuids[i]);
+			free(uuids[i]);
 		}
 		if (uuids)
-			g_strfreev(uuids);
+			free(uuids);
 		if (uuid)
 			free(uuid);
 		return EXIT_SUCCESS;
diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c
index 30e0c55..05e614f 100644
--- a/tools/idevicesyslog.c
+++ b/tools/idevicesyslog.c
@@ -24,7 +24,6 @@
 #include <errno.h>
 #include <signal.h>
 #include <stdlib.h>
-#include <glib.h>
 
 #include <libimobiledevice/libimobiledevice.h>
 #include <libimobiledevice/lockdown.h>
@@ -123,7 +122,7 @@ int main(int argc, char *argv[])
 					break;
 				}
 
-				datalen = GUINT32_FROM_BE(datalen);
+				datalen = be32toh(datalen);
 
 				if (datalen == 0)
 					continue;
-- 
cgit v1.1-32-gdbae