cpw.nader.asynclogging-3: 707a4975: Fixed crashes related to reading and lis...

morshed.nader at gmail.com morshed.nader at gmail.com
Thu Jan 5 15:27:07 EST 2012


----------------------------------------------------------------------
Revision: 707a4975a14984ae2de9ed5c0167adb94a2b893d
Parent:   0b4e54874f6ee7b4bc331766d5cc0b2864e8f8e6
Author:   morshed.nader at gmail.com
Date:     01/05/12 07:15:07
Branch:   im.pidgin.cpw.nader.asynclogging-3
URL: http://d.pidgin.im/viewmtn/revision/info/707a4975a14984ae2de9ed5c0167adb94a2b893d

Changelog: 

Fixed crashes related to reading and listing logs
Fixed listing logs giving incorrect, invalid file paths
Made purple_common_log_list use the same GFileEnumerator code that the _async function uses
Got rid of all the purple_log_get_log_sets code (Now only maintaining the purple_logs... functions)
Fixed some cases where g_return_if_fail was seeing invalid purplelog objects
Changed the get_log_sets_fn code to not require the dummy log object

Changes against parent 0b4e54874f6ee7b4bc331766d5cc0b2864e8f8e6

  patched  libpurple/commonlog.c
  patched  libpurple/log.c
  patched  libpurple/log.h
  patched  libpurple/oldlog.c

-------------- next part --------------
============================================================
--- libpurple/log.c	eefff1f79e8aaf2ab538f0ff41fdd24071ec14b8
+++ libpurple/log.c	af903bd8912e9b48f73a8c55b3e92fc0131730ee
@@ -130,8 +130,8 @@ static gssize purple_log_real_total_size
 static GList *purple_log_real_list_logs_finish(GAsyncResult *, GError **);
 static GList *purple_log_real_list_syslog_finish(GAsyncResult *, GError **);
 static gssize purple_log_real_total_size_finish(GAsyncResult *, GError **);
-static GHashTable *purple_log_real_get_log_sets_finish(PurpleLog *,
-	GAsyncResult *, GError **);
+static GHashTable *purple_log_real_get_log_sets_finish(GAsyncResult *,
+	GError **);
 
 static GHashTable *log_get_log_sets_common(GCancellable *, GError **);
 static void log_get_log_sets_common_async(gint, GCancellable *,
@@ -1151,73 +1151,13 @@ steal_log_sets(gpointer key, gpointer va
 	return TRUE;
 }
 
-GHashTable *
-purple_log_get_log_sets(PurpleLog *log, GCancellable *cancellable,
-	GError **error)
-{
-	PurpleLogClass *class;
-
-	g_return_val_if_fail(PURPLE_IS_LOG(log), NULL);
-
-	class = PURPLE_LOG_GET_CLASS(log);
-
-	if (class->get_log_sets_fn == NULL) {
-		g_set_error_literal(error,
-			G_IO_ERROR,
-			G_IO_ERROR_NOT_SUPPORTED,
-			_("Operation not supported"));
-
-		return NULL;
-	}
-
-	return class->get_log_sets_fn(log, cancellable, error);
-}
-
-void
-purple_log_get_log_sets_async(PurpleLog *log, gint io_priority,
-	GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata)
-{
-	PurpleLogClass *class;
-
-	g_return_if_fail(PURPLE_IS_LOG(log));
-
-	class = PURPLE_LOG_GET_CLASS(log);
-
-	if (class->get_log_sets_async == NULL)
-		_notify_not_supported(G_OBJECT(log), cb, userdata);
-	else
-		class->get_log_sets_async(log, io_priority, cancellable, cb, userdata);
-}
-
 static GHashTable *
-purple_log_real_get_log_sets_finish(PurpleLog *log, GAsyncResult *res,
-	GError **error)
+purple_log_real_get_log_sets_finish(GAsyncResult *res, GError **error)
 {
 	return g_hash_table_ref(g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res)));
 }
 
 GHashTable *
-purple_log_get_log_sets_finish(PurpleLog *log, GAsyncResult *res,
-	GError **error)
-{
-	g_return_val_if_fail(log == NULL || PURPLE_IS_LOG(log), NULL);
-	g_return_val_if_fail(G_IS_ASYNC_RESULT(res), NULL);
-
-	if (G_IS_SIMPLE_ASYNC_RESULT(res)) {
-		GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
-
-		if (g_simple_async_result_propagate_error(simple, error))
-			return NULL;
-	}
-
-	if (log == NULL)
-		/* Result of purple_log_common */
-		return g_hash_table_ref(g_simple_async_result_get_op_res_gpointer(G_SIMPLE_ASYNC_RESULT(res)));
-	else
-		return PURPLE_LOG_GET_CLASS(log)->get_log_sets_finish(log, res, error);
-}
-
-GHashTable *
 purple_logs_get_log_sets(GCancellable *cancellable, GError **error)
 {
 	GArray *array;
@@ -1231,28 +1171,21 @@ purple_logs_get_log_sets(GCancellable *c
 	array = purple_log_logger_get_all();
 
 	for (i = 0; i < array->len; i++) {
-		PurpleLog *log;
-		GType log_type = g_array_index(array, GType, i);
+		PurpleLogClass *klass = g_array_index(array, PurpleLogClass *, i);
 
-		log = g_object_new(log_type, NULL);
-		one_set = purple_log_get_log_sets(log, cancellable, &err);
+		if (klass->get_log_sets_fn == NULL)
+			continue;
 
-		if (one_set == NULL) {
-			g_object_unref(log);
+		one_set = klass->get_log_sets_fn(cancellable, &err);
 
-			if (err->code == G_IO_ERROR_NOT_SUPPORTED) {
-				g_clear_error(&err);
-				continue;
-			} else {
-				g_propagate_error(error, err);
-				g_hash_table_destroy(sets);
-				return NULL;
-			}
+		if (one_set == NULL) {
+			g_propagate_error(error, err);
+			g_hash_table_destroy(sets);
+			return NULL;
 		}
 
 		g_hash_table_foreach_steal(one_set, steal_log_sets, sets);
 		g_hash_table_destroy(one_set);
-		g_object_unref(log);
 	}
 
 	one_set = log_get_log_sets_common(cancellable, error);
@@ -1289,11 +1222,15 @@ purple_logs_get_log_sets_async(gint io_p
 
 	/* Get the log sets from all the loggers. */
 	for (i = 0; i < array->len; i++) {
-		GType log_type = g_array_index(array, GType, i);
-		PurpleLog *log = g_object_new(log_type, NULL);
+		PurpleLogClass *klass = g_array_index(array, PurpleLogClass *, i);
 
-		purple_log_get_log_sets_async(log, io_priority, cancellable,
-			log_hash_cb, callback_data);
+		if (klass->get_log_sets_async == NULL) {
+			callback_data->counter--;
+			continue;
+		}
+
+		klass->get_log_sets_async(io_priority, cancellable, log_hash_cb,
+			callback_data);
 	}
 
 	log_get_log_sets_common_async(io_priority, cancellable, log_hash_cb,
@@ -1723,7 +1660,7 @@ purple_log_system_init(void)
 {
 	void *handle = purple_log_system_get_handle();
 
-	loggers = g_array_sized_new(FALSE, FALSE, sizeof(GType), 3);
+	loggers = g_array_sized_new(FALSE, FALSE, sizeof(PurpleLogClass *), 3);
 
 	purple_prefs_add_none("/purple/logging");
 	purple_prefs_add_bool("/purple/logging/log_ims", TRUE);
@@ -2169,17 +2106,14 @@ log_hash_cb(GObject *object, GAsyncResul
 log_hash_cb(GObject *object, GAsyncResult *res, gpointer userdata)
 {
 	_purple_log_sets_callback_data *callback_data = userdata;
-	PurpleLog *log = PURPLE_LOG(object);
 	GError *error = NULL;
 	GHashTable *one_set;
 
-	one_set = purple_log_get_log_sets_finish(log, res, &error);
+	one_set = purple_logs_get_log_sets_finish(res, &error);
 
 	if (one_set == NULL) {
-		if (error->code != G_IO_ERROR_NOT_SUPPORTED)
-			purple_debug_error("log", "Error getting log sets for %s: %s\n",
-				log != NULL ? PURPLE_LOG_GET_CLASS(log)->logger_name : "log_list_log_sets_common",
-				error->message);
+		purple_debug_error("log", "Error getting log sets: %s\n",
+			error->message);
 	} else {
 		g_hash_table_foreach_steal(one_set, steal_log_sets,
 			callback_data->sets);
============================================================
--- libpurple/log.h	614b8c711936fe92f5efed11d1b470b7fb02a9a8
+++ libpurple/log.h	2e5e14c1a81e72c3d90381b6830cd71815edc6b9
@@ -217,16 +217,14 @@ struct _PurpleLogClass {
 	 * Loggers which implement this function must create a PurpleLogSet,
 	 * then call @a cb with @a sets and the newly created PurpleLogSet.
 	 */
-	GHashTable * (* get_log_sets_fn) (PurpleLog *log, GCancellable *cancellable,
-		GError **error);
+	GHashTable * (* get_log_sets_fn) (GCancellable *cancellable, GError **error);
 
 	/** Asynchronously gets all available log sets */
-	void (* get_log_sets_async) (PurpleLog *log, gint io_priority,
-		GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
+	void (* get_log_sets_async) (gint io_priority, GCancellable *cancellable,
+		GAsyncReadyCallback cb, gpointer userdata);
 
 	/** Finishes an asynchronous get log sets operation */
-	GHashTable * (* get_log_sets_finish) (PurpleLog *log, GAsyncResult *res,
-		GError **error);
+	GHashTable * (* get_log_sets_finish) (GAsyncResult *res, GError **error);
 
 	/** Removes a log */
 	gboolean (* remove_fn) (PurpleLog *log, GCancellable *cancellable,
@@ -643,59 +641,6 @@ gssize purple_logs_get_total_size_finish
 gssize purple_logs_get_total_size_finish(GAsyncResult *res, GError **error);
 
 /**
- * Returns a hash table of log sets.
- *
- * A "log set" here means the information necessary to gather the
- * PurpleLogs for a given buddy/chat. This information would be passed
- * to purple_log_get_log to get a list of logs.
- *
- * The primary use of this function is to get a list of everyone the
- * user has ever talked to (assuming he or she uses logging).
- *
- * The table that's returned will free all log sets in it when
- * destroyed. If a log set is removed from the table, it
- * must be freed with purple_log_set_free().
- *
- * @param log          A dummy log of the type of logger to use
- * @param cancellable  (allow-none): GCancellable object
- * @param error        (out) (allow-none): a GError location to store the error
- *
- * @return             A table of all available unique log sets
- */
-GHashTable *purple_log_get_log_sets(PurpleLog *log, GCancellable *cancellable,
-	GError **error);
-
-/**
- * Asychronously gets a hash table of log sets.
- * For more details, see purple_log_get_log_sets().
- *
- * @param log          A dummy log of the type of logger to use
- * @param io_priority  The io priority of the request
- * @param cancellable  (allow-none): GCancellable object
- * @param cb           (allow-none): A GAsyncReadyCallback to call when the
-                       request is satisfied
- * @param userdata     (allow-none): The data to pass to callback function
- *
- * @since 3.0.0
- */
-void purple_log_get_log_sets_async(PurpleLog *log, gint io_priority,
-	GCancellable *cancellable, GAsyncReadyCallback cb, gpointer userdata);
-
-/**
- * Finishes asynchronously getting a hash table of log sets
- *
- * @param log          A dummy log of the type of logger to use
- * @param res          A GAsyncResult
- * @param error        (out) (allow-none): a GError location to store the error
- *
- * @return             The hash table of log sets or %NULL on error
- *
- * @since 3.0.0
- */
-GHashTable *purple_log_get_log_sets_finish(PurpleLog *log, GAsyncResult *res,
-	GError **error);
-
-/**
  * Gets a hash table for the combined log sets of all accounts.
  * See purple_log_get_log_sets() for more details.
  *
============================================================
--- libpurple/oldlog.c	acd0976061d273561c46e7af9ce9a56f037bf90a
+++ libpurple/oldlog.c	d269cc7cc81e499e0b5e0a326c1e3823e94fb363
@@ -31,39 +31,10 @@ PurpleLogClass *old_klass = NULL;
 G_DEFINE_TYPE (PurpleOldLog, purple_old_log, PURPLE_TYPE_COMMON_LOG)
 PurpleLogClass *old_klass = NULL;
 
-static GList *purple_old_log_list(PurpleLogChatType, const gchar *,
-	PurpleAccount *, GCancellable *, GError **);
-static gint purple_old_log_total_size(PurpleLogChatType,
-	const gchar *, PurpleAccount *, GCancellable *, GError **);
-static gchar *purple_old_log_read(PurpleLog *, PurpleLogReadFlags *,
-	GCancellable *, GError **);
-static GHashTable *purple_old_log_get_log_sets(PurpleLog *, GCancellable *,
-	GError **);
-
-
 /**
  * The old logger doesn't write logs, only reads them.  This is to include
  * old logs in the log viewer transparently.
  */
-static void
-purple_old_log_class_init(PurpleOldLogClass *class)
-{
-	PurpleLogClass *log_class = PURPLE_LOG_CLASS(class);
-
-	log_class->logger_name = _("Old flat format");
-	log_class->logger_id = "old";
-
-	log_class->list_fn = purple_old_log_list;
-	log_class->read_fn = purple_old_log_read;
-	log_class->total_size_fn = purple_old_log_total_size;
-	log_class->get_log_sets_fn = purple_old_log_get_log_sets;
-}
-
-static void
-purple_old_log_init(PurpleOldLog *old_log)
-{
-}
-
 /* XXX: Needs testing!!! */
 static GList *
 purple_old_log_list(PurpleLogChatType chat_type, const gchar *sn,
@@ -473,8 +444,7 @@ static GHashTable *
 }
 
 static GHashTable *
-purple_old_log_get_log_sets(PurpleLog *log, GCancellable *cancellable,
-	GError **error)
+purple_old_log_get_log_sets(GCancellable *cancellable, GError **error)
 {
 	PurpleBlistNode *gnode, *cnode, *bnode;
 	PurpleBuddy *buddy;
@@ -589,6 +559,25 @@ purple_old_log_get_log_sets(PurpleLog *l
 	return sets;
 }
 
+static void
+purple_old_log_class_init(PurpleOldLogClass *class)
+{
+	PurpleLogClass *log_class = PURPLE_LOG_CLASS(class);
+
+	log_class->logger_name = _("Old flat format");
+	log_class->logger_id = "old";
+
+	log_class->list_fn = purple_old_log_list;
+	log_class->read_fn = purple_old_log_read;
+	log_class->total_size_fn = purple_old_log_total_size;
+	log_class->get_log_sets_fn = purple_old_log_get_log_sets;
+}
+
+static void
+purple_old_log_init(PurpleOldLog *old_log)
+{
+}
+
 void
 purple_old_log_system_init(void)
 {
============================================================
--- libpurple/commonlog.c	7757634c9565ef02ad7fd522d588cd7852a7c99c
+++ libpurple/commonlog.c	368445850bb030be3cc0b4d8d30a7a3a4802189e
@@ -771,7 +771,8 @@ purple_common_log_read_async_2(GIOChanne
 			return FALSE;
 		}
 
-		memcpy(data->contents + data->size, buffer, bytes);
+		data->contents = tmp;
+		memcpy(data->contents + data->size, buffer, sizeof(gchar) * bytes);
 		data->size += bytes;
 
 		return TRUE;
@@ -829,19 +830,21 @@ static PurpleLog *
 
 /* XXX: Poorly named */
 static PurpleLog *
-create_log(const gchar *dir, const gchar *filename, PurpleLogChatType chat_type,
-	const gchar *name, PurpleAccount *account, PurpleLogClass *klass)
+create_log(const gchar *path, PurpleLogChatType chat_type, const gchar *name,
+	PurpleAccount *account, PurpleLogClass *klass)
 {
 	PurpleLog *log;
-	gchar *tmp;
+	gchar *basename;
 	struct tm tm;
 #if defined (HAVE_TM_GMTOFF) && defined (HAVE_STRUCT_TM_TM_ZONE)
 	long tz_off;
 	const gchar *rest, *end;
 	time_t stamp;
 
-	stamp = purple_str_to_time(purple_unescape_filename(filename),
+	basename = g_path_get_basename(path);
+	stamp = purple_str_to_time(purple_unescape_filename(basename),
 		FALSE, &tm, &tz_off, &rest);
+	g_free(basename);
 
 	/**
 	 * As zero is a valid offset, PURPLE_NO_TZ_OFF means no offset was
@@ -864,15 +867,17 @@ create_log(const gchar *dir, const gchar
 		g_free(tmp);
 	}
 #else
-	time_t stamp = purple_str_to_time(filename, FALSE, &tm, NULL, NULL);
+	time_t stamp;
 
+	basename = g_path_get_basename(path);
+	stamp = purple_str_to_time(basename, FALSE, &tm, NULL, NULL);
+	g_free(basename);
+
 	log = purple_log_new(klass, chat_type, name, account, NULL,
 		stamp, (stamp != 0) ?  &tm : NULL);
 #endif
 
-	tmp = g_build_filename(dir, filename, NULL);
-	purple_common_log_set_path(PURPLE_COMMON_LOG(log), tmp);
-	g_free(tmp);
+	purple_common_log_set_path(PURPLE_COMMON_LOG(log), path);
 
 	return log;
 }
@@ -882,10 +887,11 @@ purple_common_log_list(PurpleLogChatType
 	PurpleAccount *account, const gchar *ext, PurpleLogClass *klass,
 	GCancellable *cancellable, GError **error)
 {
-	GDir *dir;
 	GError *err = NULL;
+	GFile *dir;
+	GFileEnumerator *enumerator;
+	GFileInfo *info;
 	GList *list = NULL;
-	const gchar *filename;
 	gchar *path;
 
 	g_return_val_if_fail(name != NULL, NULL);
@@ -904,42 +910,53 @@ purple_common_log_list(PurpleLogChatType
 		return NULL;
 	}
 
-	dir = g_dir_open(path, 0, &err);
+	dir = g_file_new_for_path(path);
+	g_free(path);
 
-	if (dir == NULL) {
+	enumerator = g_file_enumerate_children(dir, G_FILE_ATTRIBUTE_STANDARD_NAME,
+		G_FILE_QUERY_INFO_NONE, cancellable, &err);
+
+	if (enumerator == NULL) {
 		if (err->code == G_FILE_ERROR_NOENT)
 			g_clear_error(&err);
 		else
 			g_propagate_error(error, err);
 
-		g_free(path);
+		g_object_unref(dir);
 
 		return NULL;
 	}
 
 	g_clear_error(&err);
 
-	while ((filename = g_dir_read_name(dir)) != NULL) {
-		if (g_cancellable_set_error_if_cancelled(cancellable, error)) {
-			g_dir_close(dir);
-			g_free(path);
-			purple_log_list_free(list);
+	while ((info = g_file_enumerator_next_file(enumerator, cancellable, &err)) != NULL) {
+		GFile *child_file;
+		PurpleLog *log;
+		gchar *child_path;
 
-			return NULL;
+		child_file = g_file_get_child(dir, g_file_info_get_name(info));
+		child_path = g_file_get_path(child_file);
+		g_object_unref(child_file);
+
+		if (!purple_str_has_suffix(child_path, ext)) {
+			g_free(child_path);
+			continue;
 		}
 
-		if (purple_str_has_suffix(filename, ext) &&
-		    strlen(filename) >= (17 + strlen(ext))) /* XXX: ? */
-		{
-			PurpleLog *log = create_log(path, filename, chat_type, name,
-				account, klass);
-			list = g_list_prepend(list, log);
-		}
+		log = create_log(child_path, chat_type, name, account, klass);
+
+		g_free(child_path);
+		list = g_list_prepend(list, log);
 	}
 
-	g_dir_close(dir);
-	g_free(path);
+	g_object_unref(dir);
+	g_object_unref(enumerator);
 
+	if (err != NULL) {
+		g_propagate_error(error, err);
+		return NULL;
+	}
+		
 	return list;
 }
 
@@ -1041,7 +1058,7 @@ purple_common_log_list_async_3(GObject *
 			continue;
 		}
 
-		log = create_log(dir_path, child_path, data->chat_type, data->name,
+		log = create_log(child_path, data->chat_type, data->name,
 			data->account, data->klass);
 
 		g_free(child_path);


More information about the Commits mailing list