Index: libgsm/phonemgr-listener.c
===================================================================
--- libgsm/phonemgr-listener.c	(revision 300)
+++ libgsm/phonemgr-listener.c	(working copy)
@@ -105,6 +105,7 @@
 static void phonemgr_listener_class_init (PhonemgrListenerClass *klass);
 static void phonemgr_listener_init (PhonemgrListener *bc);
 static void phonemgr_listener_finalize (GObject *obj);
+static void phonemgr_listener_get_own_details (PhonemgrListener *l);
 
 #ifndef DUMMY
 static void phonemgr_listener_thread (PhonemgrListener *l);
@@ -503,6 +504,7 @@
 	l->connected = TRUE;
 
 	phonemgr_listener_emit_status (l, PHONEMGR_LISTENER_CONNECTED);
+	phonemgr_listener_get_own_details (l);
 
 	l->thread = g_thread_create ((GThreadFunc) phonemgr_listener_thread,
 				     l, TRUE, NULL);
@@ -828,7 +830,7 @@
 	} else if (error == GN_ERR_INVALIDMEMORYTYPE) {
 		g_message ("Couldn't get our own phone number (no Own Number phonebook)");
 		return;
-	} else if (error == GN_ERR_NOTREADY) {
+	} else {
 		return;
 	}
 
@@ -969,8 +971,6 @@
 {
 	g_mutex_lock (l->mutex);
 	CHECK_EXIT;
-	phonemgr_listener_get_own_details (l);
-	CHECK_EXIT;
 	phonemgr_listener_set_sms_notification (l, TRUE);
 	CHECK_EXIT;
 	phonemgr_listener_set_call_notification (l, TRUE);
@@ -1172,7 +1172,248 @@
 		g_warning ("Can't set date: %s", phonemgr_utils_gn_error_to_string (error, &perr));
 }
 
+char **
+phonemgr_listener_list_all_data (PhonemgrListener *l,
+				 PhonemgrListenerDataType type)
+{
+	switch (type) {
+	case PHONEMGR_LISTENER_DATA_CONTACT:
+		{
+			GPtrArray *a;
+			gn_memory_status memstat;
+			gn_error error;
+			guint i;
+
+			g_mutex_lock (l->mutex);
+			memstat.memory_type = gn_str2memory_type("ME");
+			l->phone_state->data.memory_status = &memstat;
+			error = phonemgr_listener_gnokii_func (GN_OP_GetMemoryStatus, l);
+			//FIXME better error?
+			if (error != GN_ERR_NONE) {
+				g_mutex_unlock (l->mutex);
+				break;
+			}
+			a = g_ptr_array_sized_new (memstat.used);
+			for (i = 1; i <= memstat.used; i++) {
+				char *uuid;
+				uuid = g_strdup_printf ("GPM-UUID-%s-%s-%d", l->imei, "ME", i);
+				g_ptr_array_add (a, uuid);
+			}
+
+			memstat.memory_type = gn_str2memory_type("SM");
+			l->phone_state->data.memory_status = &memstat;
+			error = phonemgr_listener_gnokii_func (GN_OP_GetMemoryStatus, l);
+			//FIXME better error?
+			if (error != GN_ERR_NONE) {
+				g_ptr_array_add (a, NULL);
+				g_mutex_unlock (l->mutex);
+				return (char **) g_ptr_array_free (a, FALSE);
+			}
+
+			for (i = 1; i <= memstat.used; i++) {
+				char *uuid;
+				uuid = g_strdup_printf ("GPM-UUID-%s-%s-%d", l->imei, "SM", i);
+				g_ptr_array_add (a, uuid);
+			}
+			g_ptr_array_add (a, NULL);
+			g_mutex_unlock (l->mutex);
+
+			return (char **) g_ptr_array_free (a, FALSE);
+		}
+	case PHONEMGR_LISTENER_DATA_CALENDAR:
+		break;
+	case PHONEMGR_LISTENER_DATA_TODO:
+		break;
+	default:
+		g_assert_not_reached ();
+	}
+
+	return NULL;
+}
+
+static gboolean
+phonemgr_listener_parse_data_uuid (const char *dataid,
+				   char **memory_type,
+				   int *index)
+{
+	char *s;
+
+	g_return_val_if_fail (dataid != NULL, FALSE);
+
+	if (g_str_has_prefix (dataid, "GPM-UUID-") == FALSE)
+		return FALSE;
+	s = strchr (dataid + strlen ("GPM-UUID-") + 1, '-');
+	if (s == NULL)
+		return FALSE;
+	if (strlen(s) < 5)
+		return FALSE;
+	*memory_type = g_strndup (s + 1, 2);
+	*index = atoi (s + 4);
+	return TRUE;
+}
+
+char *
+phonemgr_listener_get_data (PhonemgrListener *l,
+			    PhonemgrListenerDataType type,
+			    const char *dataid)
+{
+	switch (type) {
+	case PHONEMGR_LISTENER_DATA_CONTACT:
+		{
+			gn_phonebook_entry entry;
+			char *memory_type, *retval;
+			gn_error error;
+			int index;
+
+			if (phonemgr_listener_parse_data_uuid (dataid, &memory_type, &index) == FALSE)
+				return NULL;
+
+			g_mutex_lock (l->mutex);
+
+			memset(&entry, 0, sizeof(gn_phonebook_entry));
+			entry.memory_type = gn_str2memory_type(memory_type);
+			entry.location = index;
+
+			l->phone_state->data.phonebook_entry = &entry;
+			error = phonemgr_listener_gnokii_func (GN_OP_ReadPhonebook, l);
+			if (error != GN_ERR_NONE || entry.empty != FALSE) {
+				g_mutex_unlock (l->mutex);
+				return NULL;
+			}
+
+			retval = gn_phonebook2vcardstr (&entry);
+			g_free (memory_type);
+
+			g_mutex_unlock (l->mutex);
+
+			return retval;
+		}
+		break;
+	case PHONEMGR_LISTENER_DATA_CALENDAR:
+		break;
+	case PHONEMGR_LISTENER_DATA_TODO:
+		break;
+	default:
+		g_assert_not_reached ();
+	}
+
+	return NULL;
+}
+
 gboolean
+phonemgr_listener_delete_data (PhonemgrListener *l,
+			       PhonemgrListenerDataType type,
+			       const char *dataid)
+{
+	switch (type) {
+	case PHONEMGR_LISTENER_DATA_CONTACT:
+		{
+			gn_phonebook_entry entry;
+			char *memory_type, *retval;
+			gn_error error;
+			int index;
+
+			if (phonemgr_listener_parse_data_uuid (dataid, &memory_type, &index) == FALSE)
+				return FALSE;
+
+			g_mutex_lock (l->mutex);
+
+			memset(&entry, 0, sizeof(gn_phonebook_entry));
+			entry.memory_type = gn_str2memory_type(memory_type);
+			entry.location = index;
+			entry.empty = TRUE;
+
+			l->phone_state->data.phonebook_entry = &entry;
+			error = phonemgr_listener_gnokii_func (GN_OP_DeletePhonebook, l);
+			g_free (memory_type);
+
+			g_mutex_unlock (l->mutex);
+
+			return (error != GN_ERR_NONE);
+		}
+		break;
+	case PHONEMGR_LISTENER_DATA_CALENDAR:
+		break;
+	case PHONEMGR_LISTENER_DATA_TODO:
+		break;
+	default:
+		g_assert_not_reached ();
+	}
+
+	return FALSE;
+}
+
+char *
+phonemgr_listener_put_data (PhonemgrListener *l,
+			    PhonemgrListenerDataType type,
+			    const char *data)
+{
+	switch (type) {
+	case PHONEMGR_LISTENER_DATA_CONTACT:
+		{
+			gn_phonebook_entry entry;
+			char *retval;
+			gn_error error;
+			guint i;
+
+			g_mutex_lock (l->mutex);
+
+			memset(&entry, 0, sizeof(gn_phonebook_entry));
+			//FIXME parse the vcard using an unbroken gn_vcard2phonebook
+			entry.memory_type = GN_MT_ME;
+
+			/* Find an empty spot */
+			for (i = 1; ; i++) {
+				gn_phonebook_entry aux;
+
+				memcpy(&aux, &entry, sizeof(gn_phonebook_entry));
+				l->phone_state->data.phonebook_entry = &aux;
+				l->phone_state->data.phonebook_entry->location = i;
+				error = phonemgr_listener_gnokii_func (GN_OP_ReadPhonebook, l);
+				if (error != GN_ERR_NONE && error != GN_ERR_EMPTYLOCATION)
+					break;
+				if (aux.empty || error == GN_ERR_EMPTYLOCATION) {
+					entry.location = aux.location;
+					error = GN_ERR_NONE;
+					break;
+				}
+			}
+
+			if (error != GN_ERR_NONE) {
+				g_mutex_unlock (l->mutex);
+				return NULL;
+			}
+
+			//FIXME what's that for?
+			gn_phonebook_entry_sanitize(&entry);
+
+			l->phone_state->data.phonebook_entry = &entry;
+			error = phonemgr_listener_gnokii_func (GN_OP_WritePhonebook, l);
+
+			if (error != GN_ERR_NONE) {
+				g_mutex_unlock (l->mutex);
+				return NULL;
+			}
+
+			retval = g_strdup_printf ("GPM-UUID-%s-%s-%d", l->imei, "ME", entry.location);
+
+			g_mutex_unlock (l->mutex);
+
+			return retval;
+		}
+		break;
+	case PHONEMGR_LISTENER_DATA_CALENDAR:
+		break;
+	case PHONEMGR_LISTENER_DATA_TODO:
+		break;
+	default:
+		g_assert_not_reached ();
+	}
+
+	return FALSE;
+}
+
+gboolean
 phonemgr_listener_connected (PhonemgrListener *l)
 {
 	g_return_val_if_fail (PHONEMGR_IS_LISTENER (l), FALSE);
Index: libgsm/glibgsmtest.c
===================================================================
--- libgsm/glibgsmtest.c	(revision 299)
+++ libgsm/glibgsmtest.c	(working copy)
@@ -111,7 +111,7 @@
 	g_thread_init (NULL);
 	g_type_init ();
 	
-	listener = phonemgr_listener_new (TRUE);
+	listener = phonemgr_listener_new (FALSE);
 
 	g_signal_connect (G_OBJECT (listener), "message",
 			G_CALLBACK (message), (gpointer) listener);
@@ -127,15 +127,34 @@
 			  G_CALLBACK (network_status), (gpointer) listener);
 
 //	if (phonemgr_listener_connect (listener, "1", &err)) {
-	if (phonemgr_listener_connect (listener, "00:12:D2:79:B7:33", &err)) {
+	if (phonemgr_listener_connect (listener, "00:1E:45:AD:F1:96", &err)) {
 //	if (phonemgr_listener_connect (listener, "/dev/rfcomm0", &err)) {
+		char **array;
+		guint i;
+
 		g_message ("Connected OK");
 
-		g_timeout_add_seconds (1, (GSourceFunc) send_message, listener);
+		array = phonemgr_listener_list_all_data (listener, PHONEMGR_LISTENER_DATA_CONTACT);
+		if (array == NULL) {
+			g_message ("BLEEEEEEH");
+			return 1;
+		}
+		for (i = 0; array[i] != NULL; i++) {
+			char *vcard;
 
-		loop = g_main_loop_new (NULL, FALSE);
-		g_main_loop_run (loop);
+			vcard = phonemgr_listener_get_data (listener, PHONEMGR_LISTENER_DATA_CONTACT, array[i]);
+			if (vcard != NULL) {
+				g_print ("%s\n", vcard);
+			}
+		}
 
+		g_strfreev (array);
+
+//		g_timeout_add_seconds (1, (GSourceFunc) send_message, listener);
+
+//		loop = g_main_loop_new (NULL, FALSE);
+//		g_main_loop_run (loop);
+
 		phonemgr_listener_disconnect (listener);
 	} else {
 		g_error ("Couldn't connect to the phone: %s\n",
Index: libgsm/phonemgr-listener.h
===================================================================
--- libgsm/phonemgr-listener.h	(revision 299)
+++ libgsm/phonemgr-listener.h	(working copy)
@@ -56,6 +56,12 @@
 	PHONEMGR_LISTENER_CALL_UNKNOWN
 } PhonemgrListenerCallStatus;
 
+typedef enum {
+	PHONEMGR_LISTENER_DATA_CONTACT,
+	PHONEMGR_LISTENER_DATA_CALENDAR,
+	PHONEMGR_LISTENER_DATA_TODO
+} PhonemgrListenerDataType;
+
 #define CALL_NAME_UNKNOWN "Unknown"
 #define CALL_NAME_RESTRICTED "Withheld"
 
@@ -89,6 +95,19 @@
 void phonemgr_listener_set_time		(PhonemgrListener *l,
 					 time_t time);
 
+char ** phonemgr_listener_list_all_data
+					(PhonemgrListener *l,
+					 PhonemgrListenerDataType type);
+char * phonemgr_listener_get_data	(PhonemgrListener *l,
+					 PhonemgrListenerDataType type,
+					 const char *dataid);
+gboolean phonemgr_listener_delete_data	(PhonemgrListener *l,
+					 PhonemgrListenerDataType type,
+					 const char *dataid);
+char * phonemgr_listener_put_data	(PhonemgrListener *l,
+					 PhonemgrListenerDataType type,
+					 const char *data);
+
 gboolean phonemgr_listener_connected	(PhonemgrListener *listener);
 
 /* Error types */
