changeset 17982:ee8b3014bc36

merge of 'aad9a598920b4a24ad65e717487bb821e563d9d2' and 'd59e5dbda202af43060a90172a7ed20f89090cc2'
author Michael Shkutkov <mshkutkov@soc.pidgin.im>
date Wed, 13 Jun 2007 12:26:39 +0000
parents f10e6ba2a619 (current diff) c8d2e131cc37 (diff)
children 535a71646a47
files
diffstat 1 files changed, 398 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/plugins/log_reader.c	Wed Jun 13 12:07:32 2007 +0000
+++ b/libpurple/plugins/log_reader.c	Wed Jun 13 12:26:39 2007 +0000
@@ -1724,6 +1724,359 @@
 
 }
 
+/*****************************************************************************
+ * QIP Logger                                                           *
+ *****************************************************************************/
+
+/* The QIP logger doesn't write logs, only reads them.  This is to include
+ * QIP logs in the log viewer transparently.
+ */
+#define QIP_LOG_DELIMITER "--------------------------------------"
+#define QIP_LOG_IN_MESSAGE (QIP_LOG_DELIMITER "<-")
+#define QIP_LOG_OUT_MESSAGE (QIP_LOG_DELIMITER ">-")
+#define QIP_LOG_IN_MESSAGE_ESC (QIP_LOG_DELIMITER "&lt;-")
+#define QIP_LOG_OUT_MESSAGE_ESC (QIP_LOG_DELIMITER "&gt;-")
+
+#define DEBUG_MESSAGE(var, sign, value, title) if(var sign value) \
+						purple_debug(PURPLE_DEBUG_ERROR, title,	\
+						#var " " #sign " " #value "\n");
+
+static PurpleLogLogger *qip_logger;
+static void qip_logger_finalize(PurpleLog *log);
+
+struct qip_logger_data {
+	
+	char *path; /* FIXME: Change this to use PurpleStringref like log.c:old_logger_list  */
+	int offset;
+	int length;
+};
+
+static GList *qip_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account)
+{
+	GList *list = NULL;
+	const char *logdir;
+	PurplePlugin *plugin;
+	PurplePluginProtocolInfo *prpl_info;
+	const char *buddy_name;
+	char *username;
+	char *filename;
+	char *path;
+	GError *error = NULL;
+	gchar *contents = NULL;
+	gsize length;
+	gchar *c;
+
+	purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
+				"start\n");
+
+	g_return_val_if_fail(sn != NULL, list);
+	g_return_val_if_fail(account != NULL, list);
+
+	purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
+				"arguments not NULL\n");
+
+	/* QIP is ICQ messenger. Should we add prpl-aim? */
+	if (strcmp(account->protocol_id, "prpl-icq"))
+		return list;
+		
+	purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
+				"protocol is 'prpl-icq'\n");
+
+	logdir = purple_prefs_get_string("/plugins/core/log_reader/qip/log_directory");
+
+	/* By clearing the log directory path, this logger can be (effectively) disabled. */
+	if (!*logdir)
+		return list;
+
+	plugin = purple_find_prpl(purple_account_get_protocol_id(account));
+	if (!plugin)
+		return NULL;
+
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
+	if (!prpl_info->list_icon)
+		return NULL;
+
+	buddy_name = g_strdup(purple_normalize(account, sn));
+	purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
+				"buddy_name %s\n", buddy_name);
+
+	username = g_strdup(purple_normalize(account, account->username));
+	purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
+				"username %s\n", username);
+				
+	purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
+				"sn %s\n", sn);
+	
+	filename = g_strdup_printf("%s.txt", buddy_name);
+	path = g_build_filename(
+		logdir, username, "History", filename, NULL);
+	purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
+				"Reading %s\n", path);
+	if (!g_file_get_contents(path, &contents, &length, &error))
+		if (error)
+			g_error_free(error);
+		
+	if (contents) {
+		struct qip_logger_data *data = NULL;
+		
+		purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
+			"File %s is found\n", filename);
+		c = contents;
+		if (purple_str_has_prefix(c, QIP_LOG_IN_MESSAGE) || 
+			purple_str_has_prefix(c, QIP_LOG_OUT_MESSAGE)) {
+			
+			/* find next line */
+			while(*c && *c != '\n') {
+				c++;
+			}
+
+			if (*c) {
+				char *timestamp = c;
+				
+				while (*timestamp && (*timestamp !='('))
+					timestamp++;
+				
+				if (*timestamp == '(') {
+					struct tm tm;
+					
+					timestamp++;
+					
+					/*  Parse the time, day, month and year */
+					if (sscanf(timestamp, "%u:%u:%u %u/%u/%u",
+							&tm.tm_hour, &tm.tm_min, &tm.tm_sec,
+							&tm.tm_mday, &tm.tm_mon, &tm.tm_year) != 6) {
+						purple_debug(PURPLE_DEBUG_ERROR, "QIP logger list",
+										"Parsing timestamp error\n");
+					} else {
+						PurpleLog *log;
+
+						
+						/* cos month of year in [0,11] */
+						tm.tm_mon -= 1; 
+						/* cos years since 1900 */
+						tm.tm_year -= 1900;
+
+						purple_debug(PURPLE_DEBUG_INFO, 
+							"QIP logger list",
+							"Parsing timestamp: %u/%u/%u %u:%u:%u\n", 
+								tm.tm_year, tm.tm_mon, tm.tm_mday,
+								tm.tm_hour, tm.tm_min, tm.tm_sec);
+						
+						/* Let the C library deal with
+						* daylight savings time.
+						*/
+						tm.tm_isdst = -1;
+
+						data = g_new0(
+							struct qip_logger_data, 1);
+						data->path = g_strdup(path);
+						data->offset = 0;
+						data->length = strlen(contents);
+						
+						/* XXX: Look into this later... Should we pass in a struct tm? */
+						log = purple_log_new(PURPLE_LOG_IM,
+							sn, account, NULL, mktime(&tm), NULL);
+						
+						log->logger = qip_logger;
+						log->logger_data = data;
+						
+						list = g_list_append(list, log);
+					} 
+				} 
+			} 
+		} 
+	
+		g_free(contents); 
+	} 
+
+	g_free(username);
+	g_free(path);
+	g_free(filename);
+
+	return list;
+}
+	
+static char * qip_logger_read (PurpleLog *log, PurpleLogReadFlags *flags)
+{
+	struct qip_logger_data *data;
+	char *read;	
+	FILE *file;
+	PurpleBuddy *buddy;
+	char *escaped;
+	GString *formatted;
+	char *c;
+	const char *line;
+	
+	purple_debug(PURPLE_DEBUG_INFO, "QIP logger read",
+		"start\n");
+	
+	DEBUG_MESSAGE(log, ==, NULL, "QIP logger read");
+	g_return_val_if_fail(log != NULL, g_strdup(""));
+	
+	data = log->logger_data;
+	
+	DEBUG_MESSAGE(data->path, ==, NULL, "QIP logger read");
+	g_return_val_if_fail(data->path != NULL, g_strdup(""));
+
+	DEBUG_MESSAGE(data->length, <=, 0, "QIP logger read");
+	g_return_val_if_fail(data->length > 0, g_strdup(""));
+
+
+	purple_debug(PURPLE_DEBUG_INFO, "QIP logger read",
+				"Reading %s\n", data->path);
+	
+	read = g_malloc(data->length + 2);
+	
+	file = g_fopen(data->path, "rb");
+	fseek(file, data->offset, SEEK_SET);
+	fread(read, data->length, 1, file);
+	fclose(file);
+	
+	if (read[data->length-1] == '\n') {
+		read[data->length] = '\0';
+	} else {
+		read[data->length] = '\n';
+		read[data->length+1] = '\0';
+	}
+	
+	/* Load miscellaneous data. */
+	buddy = purple_find_buddy(log->account, log->name);
+	
+	escaped = g_markup_escape_text(read, -1);
+	g_free(read);
+	read = escaped;
+	
+	/* Apply formatting... */
+	formatted = g_string_sized_new(strlen(read));
+	c = read;
+	line = read;
+	
+	while (*c)
+	{
+		gboolean is_in_message = FALSE;
+		
+		if (purple_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC) || 
+			purple_str_has_prefix(line, QIP_LOG_OUT_MESSAGE_ESC)) {
+			const char *buddy_name;
+			is_in_message = purple_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC);
+			
+			purple_debug(PURPLE_DEBUG_INFO, "QIP loggger read",
+					"%s message\n", (is_in_message) ? "incoming" : "Outgoing");
+			
+			/* find next line */
+			while(*c && *c!= '\n') 
+				c++;
+			/* XXX: Do we need buddy_name when we have buddy->alias? */
+			buddy_name = c;
+			
+			/* we hope that nickname hasn't '(' symbol */
+			while (*c && *c != '(') 
+				c++;
+
+			if (*c == '(') {
+				const char *timestamp = c;
+				int hour;
+				int min;
+				int sec;
+				
+				timestamp++;
+					
+				/*  Parse the time, day, month and year */
+				if (sscanf(timestamp, "%u:%u:%u",
+							&hour, &min, &sec) != 3) 
+					purple_debug(PURPLE_DEBUG_ERROR, "QIP logger read",
+									"Parsing timestamp error\n");
+				else {
+					g_string_append(formatted, "<font size=\"2\">");
+					g_string_append_printf(formatted, 
+							"(%u:%02u:%02u) %cM ", hour % 12, 
+							min, sec, (hour >= 12) ? 'P': 'A');
+					g_string_append(formatted, "</font> ");
+					
+					if (is_in_message) {
+						if (buddy_name != NULL && buddy->alias) {
+							g_string_append_printf(formatted, 
+								"<span style=\"color: #A82F2F;\">"
+								"<b>%s</b></span>: ", buddy->alias);
+						}
+					} else {
+						const char *acct_name;
+						acct_name = purple_account_get_alias(log->account);
+						if (!acct_name)
+							acct_name = purple_account_get_username(log->account);
+
+						g_string_append_printf(formatted,
+							"<span style=\"color: #16569E;\">"
+							"<b>%s</b></span>: ", acct_name);
+					}
+					
+					/* find next line */
+					while(c && *c != '\n') 
+						c++;
+
+					line = ++c;
+
+					if ((c = strstr(c, "\n")))
+						*c = '\0';
+					
+					purple_debug(PURPLE_DEBUG_INFO, "QIP logger read",
+						"writing message: \"%s\"\n", line);
+						
+					g_string_append(formatted, line);
+					line = ++c;
+					g_string_append_c(formatted, '\n');
+				}
+			}
+		} else {
+			if ((c = strchr(c, '\n')))
+				*c = '\0';
+		
+			if (line[0] != '\n' && line[0] != '\r') {
+				purple_debug(PURPLE_DEBUG_INFO, "QIP logger read",
+					"line is not delimiter \"%s\"\n", line);
+				
+				g_string_append(formatted, line);
+				g_string_append_c(formatted, '\n');
+			}
+			line = ++c;
+		}
+	}
+	g_free(read);
+	/* XXX: TODO: Avoid this g_strchomp() */
+	return g_strchomp(g_string_free(formatted, FALSE));
+}
+
+static int qip_logger_size (PurpleLog *log)
+{
+	struct qip_logger_data *data;
+	char *text;
+	size_t size;
+
+	g_return_val_if_fail(log != NULL, 0);
+
+	data = log->logger_data;
+
+	if (purple_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) {
+		return data ? data->length : 0;
+	}
+
+	text = qip_logger_read(log, NULL); 
+	size = strlen(text);
+	g_free(text);
+
+	return size;
+}
+
+static void qip_logger_finalize(PurpleLog *log)
+{
+	struct qip_logger_data *data;
+
+	g_return_if_fail(log != NULL);
+
+	data = log->logger_data;
+
+	g_free(data->path);
+}
 
 /*****************************************************************************
  * Plugin Code                                                               *
@@ -1970,12 +2323,35 @@
 		path = g_strdup("");
 #endif
 
-	purple_prefs_add_string("/plugins/core/log_reader/trillian/log_directory", path);
-	g_free(path);
-
 #ifdef _WIN32
 	} /* !found */
 #endif
+
+	/* Add QIP log directory preference. */
+	purple_prefs_add_none("/plugins/core/log_reader/qip");
+
+#ifdef _WIN32 
+	/* Calculate default Messenger Plus! log directory. */
+	folder = wpurple_get_special_folder(CSIDL_PROGRAM_FILES);
+	if (folder) {
+#endif
+	path = g_build_filename(
+#ifdef _WIN32 
+		folder,
+#else
+		PURPLE_LOG_READER_WINDOWS_MOUNT_POINT, "Program Files",
+#endif
+		"QIP", "Users", NULL);
+#ifdef _WIN32
+	g_free(folder);
+	} else /* !folder */
+		path = g_strdup("");
+#endif
+
+	purple_debug(PURPLE_DEBUG_INFO, "QIP log reader", "QIP log directory %s\n", path);
+
+	purple_prefs_add_string("/plugins/core/log_reader/qip/log_directory", path);
+	g_free(path);
 }
 
 static gboolean
@@ -2019,11 +2395,24 @@
 												messenger_plus_logger_read,
 												messenger_plus_logger_size);
 	purple_log_logger_add(messenger_plus_logger);
+	
 #endif
 
 	/* The names of IM clients are marked for translation at the request of
 	   translators who wanted to transliterate them.  Many translators
 	   choose to leave them alone.  Choose what's best for your language. */
+	qip_logger = purple_log_logger_new("qip", _("QIP"), 6,
+											NULL,
+											NULL,
+											qip_logger_finalize,
+											qip_logger_list,
+											qip_logger_read,
+											qip_logger_size);
+	purple_log_logger_add(qip_logger);
+		
+	/* The names of IM clients are marked for translation at the request of
+	   translators who wanted to transliterate them.  Many translators
+	   choose to leave them alone.  Choose what's best for your language. */
 	msn_logger = purple_log_logger_new("msn", _("MSN Messenger"), 6,
 									 NULL,
 									 NULL,
@@ -2060,6 +2449,7 @@
 #endif
 	purple_log_logger_remove(msn_logger);
 	purple_log_logger_remove(trillian_logger);
+	purple_log_logger_remove(qip_logger);
 
 	return TRUE;
 }
@@ -2109,6 +2499,11 @@
 #endif
 
 	ppref = purple_plugin_pref_new_with_name_and_label(
+		"/plugins/core/log_reader/qip/log_directory", _("QIP"));
+	purple_plugin_pref_frame_add(frame, ppref);
+	purple_debug(PURPLE_DEBUG_INFO, "QIP log reader", "QIP creating directory\n");
+
+	ppref = purple_plugin_pref_new_with_name_and_label(
 		"/plugins/core/log_reader/msn/log_directory", _("MSN Messenger"));
 	purple_plugin_pref_frame_add(frame, ppref);