Mercurial > pidgin.yaz
annotate plugins/log_reader.c @ 13119:fcde3faa1f57
[gaim-migrate @ 15481]
This adds support for displaying log timestamps in their original timezone. If your OS's definition of struct tm sucks, then the log timestamps will show up in your local timezone, but converted, so the time is accurate. Yay! Anyway, this all works, as I've renamed lots of my log files locally, but currently, there's no code to save new logs in this name format. That's held up on a portability issue and backwards compatibility issue.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sat, 04 Feb 2006 20:55:52 +0000 |
parents | ae51c59bf819 |
children | 3a97c65196d1 |
rev | line source |
---|---|
11459 | 1 #ifdef HAVE_CONFIG_H |
2 # include <config.h> | |
3 #endif | |
4 | |
5 #include <stdio.h> | |
6 | |
7 #ifndef GAIM_PLUGINS | |
8 # define GAIM_PLUGINS | |
9 #endif | |
10 | |
11 #include "internal.h" | |
12 | |
13 #include "debug.h" | |
14 #include "log.h" | |
15 #include "plugin.h" | |
16 #include "pluginpref.h" | |
17 #include "prefs.h" | |
18 #include "stringref.h" | |
19 #include "util.h" | |
20 #include "version.h" | |
21 #include "xmlnode.h" | |
22 | |
23 /* This must be the last Gaim header included. */ | |
24 #ifdef _WIN32 | |
25 #include "win32dep.h" | |
26 #endif | |
27 | |
28 /* Where is the Windows partition mounted? */ | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
29 #ifndef GAIM_LOG_READER_WINDOWS_MOUNT_POINT |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
30 #define GAIM_LOG_READER_WINDOWS_MOUNT_POINT "/mnt/windows" |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
31 #endif |
11459 | 32 |
33 enum name_guesses { | |
34 NAME_GUESS_UNKNOWN, | |
35 NAME_GUESS_ME, | |
36 NAME_GUESS_THEM | |
37 }; | |
38 | |
39 | |
40 /***************************************************************************** | |
41 * Adium Logger * | |
42 *****************************************************************************/ | |
43 | |
44 /* The adium logger doesn't write logs, only reads them. This is to include | |
45 * Adium logs in the log viewer transparently. | |
46 */ | |
47 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
48 static GaimLogLogger *adium_logger; |
11459 | 49 |
50 enum adium_log_type { | |
51 ADIUM_HTML, | |
52 ADIUM_TEXT, | |
53 }; | |
54 | |
55 struct adium_logger_data { | |
56 char *path; | |
57 enum adium_log_type type; | |
58 }; | |
59 | |
60 static GList *adium_logger_list(GaimLogType type, const char *sn, GaimAccount *account) | |
61 { | |
62 GList *list = NULL; | |
63 const char *logdir; | |
64 GaimPlugin *plugin; | |
65 GaimPluginProtocolInfo *prpl_info; | |
66 char *prpl_name; | |
67 char *temp; | |
68 char *path; | |
69 GDir *dir; | |
70 | |
71 g_return_val_if_fail(sn != NULL, list); | |
72 g_return_val_if_fail(account != NULL, list); | |
73 | |
74 logdir = gaim_prefs_get_string("/plugins/core/log_reader/adium/log_directory"); | |
75 | |
76 /* By clearing the log directory path, this logger can be (effectively) disabled. */ | |
77 if (!*logdir) | |
78 return list; | |
79 | |
80 plugin = gaim_find_prpl(gaim_account_get_protocol_id(account)); | |
81 if (!plugin) | |
82 return NULL; | |
83 | |
84 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(plugin); | |
85 if (!prpl_info->list_icon) | |
86 return NULL; | |
87 | |
88 prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1); | |
89 | |
90 temp = g_strdup_printf("%s.%s", prpl_name, account->username); | |
91 path = g_build_filename(logdir, temp, sn, NULL); | |
92 g_free(temp); | |
93 | |
94 dir = g_dir_open(path, 0, NULL); | |
95 if (dir) { | |
96 const gchar *file; | |
97 | |
98 while ((file = g_dir_read_name(dir))) { | |
99 if (!g_str_has_prefix(file, sn)) | |
100 continue; | |
101 if (g_str_has_suffix(file, ".html")) { | |
102 struct tm tm; | |
103 const char *date = file; | |
104 | |
105 date += strlen(sn) + 2; | |
106 if (sscanf(date, "%u|%u|%u", | |
107 &tm.tm_year, &tm.tm_mon, &tm.tm_mday) != 3) { | |
108 | |
109 gaim_debug(GAIM_DEBUG_ERROR, "Adium log parse", | |
110 "Filename timestamp parsing error\n"); | |
111 } else { | |
112 char *filename = g_build_filename(path, file, NULL); | |
113 FILE *handle = fopen(filename, "rb"); | |
114 char *contents; | |
115 char *contents2; | |
116 struct adium_logger_data *data; | |
117 GaimLog *log; | |
118 | |
119 if (!handle) { | |
120 g_free(filename); | |
121 continue; | |
122 } | |
123 | |
124 /* XXX: This is really inflexible. */ | |
125 contents = g_malloc(57); | |
126 fread(contents, 56, 1, handle); | |
127 fclose(handle); | |
128 contents[56] = '\0'; | |
129 | |
130 /* XXX: This is fairly inflexible. */ | |
131 contents2 = contents; | |
132 while (*contents2 && *contents2 != '>') | |
133 contents2++; | |
134 if (*contents2) | |
135 contents2++; | |
136 while (*contents2 && *contents2 != '>') | |
137 contents2++; | |
138 if (*contents2) | |
139 contents2++; | |
140 | |
141 if (sscanf(contents2, "%u.%u.%u", | |
142 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 3) { | |
143 | |
144 gaim_debug(GAIM_DEBUG_ERROR, "Adium log parse", | |
145 "Contents timestamp parsing error\n"); | |
146 g_free(contents); | |
147 g_free(filename); | |
148 continue; | |
149 } | |
150 g_free(contents); | |
151 | |
152 data = g_new0(struct adium_logger_data, 1); | |
153 data->path = filename; | |
154 data->type = ADIUM_HTML; | |
155 | |
156 tm.tm_year -= 1900; | |
157 tm.tm_mon -= 1; | |
158 | |
13119
fcde3faa1f57
[gaim-migrate @ 15481]
Richard Laager <rlaager@wiktel.com>
parents:
12727
diff
changeset
|
159 /* XXX: Look into this later... Should we pass in a struct tm? */ |
fcde3faa1f57
[gaim-migrate @ 15481]
Richard Laager <rlaager@wiktel.com>
parents:
12727
diff
changeset
|
160 log = gaim_log_new(GAIM_LOG_IM, sn, account, NULL, mktime(&tm), NULL); |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
161 log->logger = adium_logger; |
11459 | 162 log->logger_data = data; |
163 | |
164 list = g_list_append(list, log); | |
165 } | |
166 } else if (g_str_has_suffix(file, ".adiumLog")) { | |
167 struct tm tm; | |
168 const char *date = file; | |
169 | |
170 date += strlen(sn) + 2; | |
171 if (sscanf(date, "%u|%u|%u", | |
172 &tm.tm_year, &tm.tm_mon, &tm.tm_mday) != 3) { | |
173 | |
174 gaim_debug(GAIM_DEBUG_ERROR, "Adium log parse", | |
175 "Filename timestamp parsing error\n"); | |
176 } else { | |
177 char *filename = g_build_filename(path, file, NULL); | |
178 FILE *handle = fopen(filename, "rb"); | |
179 char *contents; | |
180 char *contents2; | |
181 struct adium_logger_data *data; | |
182 GaimLog *log; | |
183 | |
184 if (!handle) { | |
185 g_free(filename); | |
186 continue; | |
187 } | |
188 | |
189 /* XXX: This is really inflexible. */ | |
190 contents = g_malloc(14); | |
191 fread(contents, 13, 1, handle); | |
192 fclose(handle); | |
193 contents[13] = '\0'; | |
194 | |
195 contents2 = contents; | |
196 while (*contents2 && *contents2 != '(') | |
197 contents2++; | |
198 if (*contents2) | |
199 contents2++; | |
200 | |
201 if (sscanf(contents2, "%u.%u.%u", | |
202 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 3) { | |
203 | |
204 gaim_debug(GAIM_DEBUG_ERROR, "Adium log parse", | |
205 "Contents timestamp parsing error\n"); | |
206 g_free(contents); | |
207 g_free(filename); | |
208 continue; | |
209 } | |
210 | |
211 g_free(contents); | |
212 | |
213 tm.tm_year -= 1900; | |
214 tm.tm_mon -= 1; | |
215 | |
216 data = g_new0(struct adium_logger_data, 1); | |
217 data->path = filename; | |
218 data->type = ADIUM_TEXT; | |
219 | |
13119
fcde3faa1f57
[gaim-migrate @ 15481]
Richard Laager <rlaager@wiktel.com>
parents:
12727
diff
changeset
|
220 /* XXX: Look into this later... Should we pass in a struct tm? */ |
fcde3faa1f57
[gaim-migrate @ 15481]
Richard Laager <rlaager@wiktel.com>
parents:
12727
diff
changeset
|
221 log = gaim_log_new(GAIM_LOG_IM, sn, account, NULL, mktime(&tm), NULL); |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
222 log->logger = adium_logger; |
11459 | 223 log->logger_data = data; |
224 | |
225 list = g_list_append(list, log); | |
226 } | |
227 } | |
228 } | |
229 g_dir_close(dir); | |
230 } | |
231 | |
232 g_free(prpl_name); | |
233 g_free(path); | |
234 | |
235 return list; | |
236 } | |
237 | |
238 static char *adium_logger_read (GaimLog *log, GaimLogReadFlags *flags) | |
239 { | |
240 struct adium_logger_data *data; | |
241 GError *error = NULL; | |
242 gchar *read = NULL; | |
243 gsize length; | |
244 | |
245 g_return_val_if_fail(log != NULL, g_strdup("")); | |
246 | |
247 data = log->logger_data; | |
248 | |
249 g_return_val_if_fail(data->path != NULL, g_strdup("")); | |
250 | |
251 gaim_debug(GAIM_DEBUG_INFO, "Adium log read", | |
252 "Reading %s\n", data->path); | |
253 if (!g_file_get_contents(data->path, &read, &length, &error)) { | |
254 gaim_debug(GAIM_DEBUG_ERROR, "Adium log read", | |
255 "Error reading log\n"); | |
256 if (error) | |
257 g_error_free(error); | |
258 return g_strdup(""); | |
259 } | |
260 | |
261 if (data->type != ADIUM_HTML) { | |
262 char *escaped = g_markup_escape_text(read, -1); | |
263 g_free(read); | |
264 read = escaped; | |
265 } | |
266 | |
267 #ifdef WIN32 | |
268 /* This problem only seems to show up on Windows. | |
269 * The BOM is displaying as a space at the beginning of the log. | |
270 */ | |
271 if (g_str_has_prefix(read, "\xef\xbb\xbf")) | |
272 { | |
273 /* FIXME: This feels so wrong... */ | |
274 char *temp = g_strdup(&(read[3])); | |
275 g_free(read); | |
276 read = temp; | |
277 } | |
278 #endif | |
279 | |
280 /* TODO: Apply formatting. | |
281 * Replace the above hack with something better, since we'll | |
282 * be looping over the entire log file contents anyway. | |
283 */ | |
284 | |
285 return read; | |
286 } | |
287 | |
288 static int adium_logger_size (GaimLog *log) | |
289 { | |
290 struct adium_logger_data *data; | |
291 char *text; | |
292 size_t size; | |
293 | |
294 g_return_val_if_fail(log != NULL, 0); | |
295 | |
296 data = log->logger_data; | |
297 | |
298 if (gaim_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) { | |
299 struct stat st; | |
300 | |
301 if (!data->path || stat(data->path, &st)) | |
302 st.st_size = 0; | |
303 | |
304 return st.st_size; | |
305 } | |
306 | |
307 text = adium_logger_read(log, NULL); | |
308 size = strlen(text); | |
309 g_free(text); | |
310 | |
311 return size; | |
312 } | |
313 | |
314 static void adium_logger_finalize(GaimLog *log) | |
315 { | |
316 struct adium_logger_data *data; | |
317 | |
318 g_return_if_fail(log != NULL); | |
319 | |
320 data = log->logger_data; | |
321 | |
322 g_free(data->path); | |
323 } | |
324 | |
325 | |
326 /***************************************************************************** | |
327 * Fire Logger * | |
328 *****************************************************************************/ | |
329 | |
330 /* The fire logger doesn't write logs, only reads them. This is to include | |
331 * Fire logs in the log viewer transparently. | |
332 */ | |
333 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
334 static GaimLogLogger *fire_logger; |
11459 | 335 |
336 struct fire_logger_data { | |
337 }; | |
338 | |
339 static GList *fire_logger_list(GaimLogType type, const char *sn, GaimAccount *account) | |
340 { | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
341 /* TODO: Do something here. */ |
11459 | 342 return NULL; |
343 } | |
344 | |
345 static char * fire_logger_read (GaimLog *log, GaimLogReadFlags *flags) | |
346 { | |
347 struct fire_logger_data *data; | |
348 | |
349 g_return_val_if_fail(log != NULL, g_strdup("")); | |
350 | |
351 data = log->logger_data; | |
352 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
353 /* TODO: Do something here. */ |
11459 | 354 return g_strdup(""); |
355 } | |
356 | |
357 static int fire_logger_size (GaimLog *log) | |
358 { | |
359 g_return_val_if_fail(log != NULL, 0); | |
360 | |
361 if (gaim_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) | |
362 return 0; | |
363 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
364 /* TODO: Do something here. */ |
11459 | 365 return 0; |
366 } | |
367 | |
368 static void fire_logger_finalize(GaimLog *log) | |
369 { | |
370 g_return_if_fail(log != NULL); | |
371 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
372 /* TODO: Do something here. */ |
11459 | 373 } |
374 | |
375 | |
376 /***************************************************************************** | |
377 * Messenger Plus! Logger * | |
378 *****************************************************************************/ | |
379 | |
380 /* The messenger_plus logger doesn't write logs, only reads them. This is to include | |
381 * Messenger Plus! logs in the log viewer transparently. | |
382 */ | |
383 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
384 static GaimLogLogger *messenger_plus_logger; |
11459 | 385 |
386 struct messenger_plus_logger_data { | |
387 }; | |
388 | |
389 static GList *messenger_plus_logger_list(GaimLogType type, const char *sn, GaimAccount *account) | |
390 { | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
391 /* TODO: Do something here. */ |
11459 | 392 return NULL; |
393 } | |
394 | |
395 static char * messenger_plus_logger_read (GaimLog *log, GaimLogReadFlags *flags) | |
396 { | |
397 struct messenger_plus_logger_data *data = log->logger_data; | |
398 | |
399 g_return_val_if_fail(log != NULL, g_strdup("")); | |
400 | |
401 data = log->logger_data; | |
402 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
403 /* TODO: Do something here. */ |
11459 | 404 return g_strdup(""); |
405 } | |
406 | |
407 static int messenger_plus_logger_size (GaimLog *log) | |
408 { | |
409 g_return_val_if_fail(log != NULL, 0); | |
410 | |
411 if (gaim_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) | |
412 return 0; | |
413 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
414 /* TODO: Do something here. */ |
11459 | 415 return 0; |
416 } | |
417 | |
418 static void messenger_plus_logger_finalize(GaimLog *log) | |
419 { | |
420 g_return_if_fail(log != NULL); | |
421 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
422 /* TODO: Do something here. */ |
11459 | 423 } |
424 | |
425 | |
426 /***************************************************************************** | |
427 * MSN Messenger Logger * | |
428 *****************************************************************************/ | |
429 | |
430 /* The msn logger doesn't write logs, only reads them. This is to include | |
431 * MSN Messenger message histories in the log viewer transparently. | |
432 */ | |
433 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
434 static GaimLogLogger *msn_logger; |
11459 | 435 |
436 struct msn_logger_data { | |
437 xmlnode *root; | |
438 xmlnode *message; | |
439 const char *session_id; | |
440 int last_log; | |
441 GString *text; | |
442 }; | |
443 | |
444 static time_t msn_logger_parse_timestamp(xmlnode *message) | |
445 { | |
446 const char *date; | |
447 const char *time; | |
448 struct tm tm; | |
449 char am_pm; | |
450 | |
451 g_return_val_if_fail(message != NULL, (time_t)0); | |
452 | |
453 date = xmlnode_get_attrib(message, "Date"); | |
454 if (!(date && *date)) { | |
455 gaim_debug(GAIM_DEBUG_ERROR, "MSN log timestamp parse", | |
456 "Attribute missing: %s\n", "Date"); | |
457 return (time_t)0; | |
458 } | |
459 | |
460 time = xmlnode_get_attrib(message, "Time"); | |
461 if (!(time && *time)) { | |
462 gaim_debug(GAIM_DEBUG_ERROR, "MSN log timestamp parse", | |
463 "Attribute missing: %s\n", "Time"); | |
464 return (time_t)0; | |
465 } | |
466 | |
467 if (sscanf(date, "%u/%u/%u", &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3) | |
468 gaim_debug(GAIM_DEBUG_ERROR, "MSN log timestamp parse", | |
469 "%s parsing error\n", "Date"); | |
470 | |
471 if (sscanf(time, "%u:%u:%u %c", &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &am_pm) != 4) | |
472 gaim_debug(GAIM_DEBUG_ERROR, "MSN log timestamp parse", | |
473 "%s parsing error\n", "Time"); | |
474 | |
475 tm.tm_year -= 1900; | |
476 tm.tm_mon -= 1; | |
477 if (am_pm == 'P') { | |
478 tm.tm_hour += 12; | |
479 } else if (tm.tm_hour == 12) { | |
480 /* 12 AM = 00 hr */ | |
481 tm.tm_hour = 0; | |
482 } | |
483 /* Let the C library deal with daylight savings time. */ | |
484 tm.tm_isdst = -1; | |
485 | |
486 return mktime(&tm); | |
487 } | |
488 | |
489 | |
490 static GList *msn_logger_list(GaimLogType type, const char *sn, GaimAccount *account) | |
491 { | |
492 GList *list = NULL; | |
493 char *username; | |
494 GaimBuddy *buddy; | |
495 const char *logdir; | |
496 const char *savedfilename = NULL; | |
497 char *logfile; | |
498 char *path; | |
499 GError *error = NULL; | |
500 gchar *contents = NULL; | |
501 gsize length; | |
502 xmlnode *root; | |
503 xmlnode *message; | |
504 const char *old_session_id = ""; | |
505 struct msn_logger_data *data = NULL; | |
506 | |
507 g_return_val_if_fail(sn != NULL, list); | |
508 g_return_val_if_fail(account != NULL, list); | |
509 | |
510 if (strcmp(account->protocol_id, "prpl-msn")) | |
511 return list; | |
512 | |
513 logdir = gaim_prefs_get_string("/plugins/core/log_reader/msn/log_directory"); | |
514 | |
515 /* By clearing the log directory path, this logger can be (effectively) disabled. */ | |
516 if (!*logdir) | |
517 return list; | |
518 | |
519 buddy = gaim_find_buddy(account, sn); | |
520 | |
521 if ((username = g_strdup(gaim_account_get_string( | |
522 account, "log_reader_msn_log_folder", NULL)))) { | |
523 /* As a special case, we allow the null string to kill the parsing | |
524 * straight away. This would allow the user to deal with the case | |
525 * when two account have the same username at different domains and | |
526 * only one has logs stored. | |
527 */ | |
528 if (!*username) { | |
529 g_free(username); | |
530 return list; | |
531 } | |
532 } else { | |
533 username = g_strdup(gaim_normalize(account, account->username)); | |
534 } | |
535 | |
536 if (buddy) | |
537 savedfilename = gaim_blist_node_get_string(&buddy->node, "log_reader_msn_log_filename"); | |
538 | |
539 if (savedfilename) { | |
540 /* As a special case, we allow the null string to kill the parsing | |
541 * straight away. This would allow the user to deal with the case | |
542 * when two buddies have the same username at different domains and | |
543 * only one has logs stored. | |
544 */ | |
545 if (!*savedfilename) { | |
546 g_free(username); | |
547 return list; | |
548 } | |
549 | |
550 logfile = g_strdup(savedfilename); | |
551 } else { | |
552 logfile = g_strdup_printf("%s.xml", gaim_normalize(account, sn)); | |
553 } | |
554 | |
555 path = g_build_filename(logdir, username, "History", logfile, NULL); | |
556 | |
557 if (!g_file_test(path, G_FILE_TEST_EXISTS)) { | |
558 gboolean found = FALSE; | |
559 char *at_sign; | |
560 GDir *dir; | |
561 | |
562 g_free(path); | |
563 | |
564 if (savedfilename) { | |
565 /* We had a saved filename, but it doesn't exist. | |
566 * Returning now is the right course of action because we don't | |
567 * want to detect another file incorrectly. | |
568 */ | |
569 g_free(username); | |
570 g_free(logfile); | |
571 return list; | |
572 } | |
573 | |
574 /* Perhaps we're using a new version of MSN with the weird numbered folders. | |
575 * I don't know how the numbers are calculated, so I'm going to attempt to | |
576 * find logs by pattern matching... | |
577 */ | |
578 | |
579 at_sign = g_strrstr(username, "@"); | |
580 if (at_sign) | |
581 *at_sign = '\0'; | |
582 | |
583 dir = g_dir_open(logdir, 0, NULL); | |
584 if (dir) { | |
585 const gchar *name; | |
586 | |
587 while ((name = g_dir_read_name(dir))) { | |
588 const char *c = name; | |
589 | |
590 if (!g_str_has_prefix(c, username)) | |
591 continue; | |
592 | |
593 c += strlen(username); | |
594 while (*c) { | |
595 if (!g_ascii_isdigit(*c)) | |
596 break; | |
597 | |
598 c++; | |
599 } | |
600 | |
601 path = g_build_filename(logdir, name, NULL); | |
602 /* The !c makes sure we got to the end of the while loop above. */ | |
603 if (!*c && g_file_test(path, G_FILE_TEST_IS_DIR)) { | |
604 char *history_path = g_build_filename( | |
605 path, "History", NULL); | |
606 if (g_file_test(history_path, G_FILE_TEST_IS_DIR)) { | |
607 gaim_account_set_string(account, | |
608 "log_reader_msn_log_folder", name); | |
609 g_free(path); | |
610 path = history_path; | |
611 found = TRUE; | |
612 break; | |
613 } | |
614 g_free(path); | |
615 g_free(history_path); | |
616 } | |
617 else | |
618 g_free(path); | |
619 } | |
620 g_dir_close(dir); | |
621 } | |
622 g_free(username); | |
623 | |
624 if (!found) { | |
625 g_free(logfile); | |
626 return list; | |
627 } | |
628 | |
629 /* If we've reached this point, we've found a History folder. */ | |
630 | |
631 username = g_strdup(gaim_normalize(account, sn)); | |
632 at_sign = g_strrstr(username, "@"); | |
633 if (at_sign) | |
634 *at_sign = '\0'; | |
635 | |
636 found = FALSE; | |
637 dir = g_dir_open(path, 0, NULL); | |
638 if (dir) { | |
639 const gchar *name; | |
640 | |
641 while ((name = g_dir_read_name(dir))) { | |
642 const char *c = name; | |
643 | |
644 if (!g_str_has_prefix(c, username)) | |
645 continue; | |
646 | |
647 c += strlen(username); | |
648 while (*c) { | |
649 if (!g_ascii_isdigit(*c)) | |
650 break; | |
651 | |
652 c++; | |
653 } | |
654 | |
655 path = g_build_filename(path, name, NULL); | |
656 if (!strcmp(c, ".xml") && | |
657 g_file_test(path, G_FILE_TEST_EXISTS)) { | |
658 found = TRUE; | |
659 g_free(logfile); | |
660 logfile = g_strdup(name); | |
661 break; | |
662 } | |
663 else | |
664 g_free(path); | |
665 } | |
666 g_dir_close(dir); | |
667 } | |
668 g_free(username); | |
669 | |
670 if (!found) { | |
671 g_free(logfile); | |
672 return list; | |
673 } | |
674 } else { | |
675 g_free(username); | |
676 g_free(logfile); | |
677 logfile = NULL; /* No sense saving the obvious buddy@domain.com. */ | |
678 } | |
679 | |
680 gaim_debug(GAIM_DEBUG_INFO, "MSN log read", | |
681 "Reading %s\n", path); | |
682 if (!g_file_get_contents(path, &contents, &length, &error)) { | |
683 g_free(path); | |
684 gaim_debug(GAIM_DEBUG_ERROR, "MSN log read", | |
685 "Error reading log\n"); | |
686 if (error) | |
687 g_error_free(error); | |
688 return list; | |
689 } | |
690 g_free(path); | |
691 | |
692 /* Reading the file was successful... | |
693 * Save its name if it involves the crazy numbers. The idea here is that you could | |
694 * then tweak the blist.xml file by hand if need be. This would be the case if two | |
695 * buddies have the same username at different domains. One set of logs would get | |
696 * detected for both buddies. | |
697 * | |
698 * I can't think of how buddy would be NULL. | |
699 */ | |
700 if (buddy && logfile) { | |
701 gaim_blist_node_set_string(&buddy->node, "log_reader_msn_log_filename", logfile); | |
702 g_free(logfile); | |
703 } | |
704 | |
705 root = xmlnode_from_str(contents, length); | |
706 g_free(contents); | |
707 if (!root) | |
708 return list; | |
709 | |
710 for (message = xmlnode_get_child(root, "Message"); message; | |
711 message = xmlnode_get_next_twin(message)) { | |
712 const char *session_id; | |
713 | |
714 session_id = xmlnode_get_attrib(message, "SessionID"); | |
715 if (!session_id) { | |
716 gaim_debug(GAIM_DEBUG_ERROR, "MSN log parse", | |
717 "Error parsing message: %s\n", "SessionID missing"); | |
718 continue; | |
719 } | |
720 | |
721 if (strcmp(session_id, old_session_id)) { | |
722 /* | |
723 * The session ID differs from the last message. | |
724 * Thus, this is the start of a new conversation. | |
725 */ | |
726 GaimLog *log; | |
727 | |
728 data = g_new0(struct msn_logger_data, 1); | |
729 data->root = root; | |
730 data->message = message; | |
731 data->session_id = session_id; | |
732 data->text = NULL; | |
733 data->last_log = FALSE; | |
734 | |
13119
fcde3faa1f57
[gaim-migrate @ 15481]
Richard Laager <rlaager@wiktel.com>
parents:
12727
diff
changeset
|
735 /* XXX: Look into this later... Should we pass in a struct tm? */ |
fcde3faa1f57
[gaim-migrate @ 15481]
Richard Laager <rlaager@wiktel.com>
parents:
12727
diff
changeset
|
736 log = gaim_log_new(GAIM_LOG_IM, sn, account, NULL, msn_logger_parse_timestamp(message), NULL); |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
737 log->logger = msn_logger; |
11459 | 738 log->logger_data = data; |
739 | |
740 list = g_list_append(list, log); | |
741 } | |
742 old_session_id = session_id; | |
743 } | |
744 | |
745 if (data) | |
746 data->last_log = TRUE; | |
747 | |
748 return list; | |
749 } | |
750 | |
751 static char * msn_logger_read (GaimLog *log, GaimLogReadFlags *flags) | |
752 { | |
753 struct msn_logger_data *data; | |
754 GString *text = NULL; | |
755 xmlnode *message; | |
756 | |
757 g_return_val_if_fail(log != NULL, g_strdup("")); | |
758 | |
759 data = log->logger_data; | |
760 | |
761 if (data->text) { | |
762 /* The GTK code which displays the logs g_free()s whatever is | |
763 * returned from this function. Thus, we can't reuse the str | |
764 * part of the GString. The only solution is to free it and | |
765 * start over. | |
766 */ | |
767 g_string_free(data->text, FALSE); | |
768 } | |
769 | |
770 text = g_string_new(""); | |
771 | |
772 if (!data->root || !data->message || !data->session_id) { | |
773 /* Something isn't allocated correctly. */ | |
774 gaim_debug(GAIM_DEBUG_ERROR, "MSN log parse", | |
775 "Error parsing message: %s\n", "Internal variables inconsistent"); | |
776 data->text = text; | |
777 | |
778 return text->str; | |
779 } | |
780 | |
781 for (message = data->message; message; | |
782 message = xmlnode_get_next_twin(message)) { | |
783 | |
784 const char *new_session_id; | |
785 xmlnode *text_node; | |
786 const char *from_name = NULL; | |
787 const char *to_name = NULL; | |
788 xmlnode *from; | |
789 xmlnode *to; | |
790 enum name_guesses name_guessed = NAME_GUESS_UNKNOWN; | |
791 const char *their_name; | |
792 time_t time_unix; | |
793 struct tm *tm_new; | |
794 char *timestamp; | |
795 const char *style; | |
796 | |
797 new_session_id = xmlnode_get_attrib(message, "SessionID"); | |
798 | |
799 /* If this triggers, something is wrong with the XML. */ | |
800 if (!new_session_id) { | |
801 gaim_debug(GAIM_DEBUG_ERROR, "MSN log parse", | |
802 "Error parsing message: %s\n", "New SessionID missing"); | |
803 break; | |
804 } | |
805 | |
806 if (strcmp(new_session_id, data->session_id)) { | |
807 /* The session ID differs from the first message. | |
808 * Thus, this is the start of a new conversation. | |
809 */ | |
810 break; | |
811 } | |
812 | |
813 text_node = xmlnode_get_child(message, "Text"); | |
814 if (!text_node) | |
815 continue; | |
816 | |
817 from = xmlnode_get_child(message, "From"); | |
818 if (from) { | |
819 xmlnode *user = xmlnode_get_child(from, "User"); | |
820 | |
821 if (user) { | |
822 from_name = xmlnode_get_attrib(user, "FriendlyName"); | |
823 | |
824 /* This saves a check later. */ | |
825 if (!*from_name) | |
826 from_name = NULL; | |
827 } | |
828 } | |
829 | |
830 to = xmlnode_get_child(message, "To"); | |
831 if (to) { | |
832 xmlnode *user = xmlnode_get_child(to, "User"); | |
833 if (user) { | |
834 to_name = xmlnode_get_attrib(user, "FriendlyName"); | |
835 | |
836 /* This saves a check later. */ | |
837 if (!*to_name) | |
838 to_name = NULL; | |
839 } | |
840 } | |
841 | |
842 their_name = from_name; | |
843 if (from_name && gaim_prefs_get_bool("/plugins/core/log_reader/use_name_heuristics")) { | |
844 const char *friendly_name = gaim_connection_get_display_name(log->account->gc); | |
845 | |
11702
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
846 if (friendly_name != NULL) { |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
847 int friendly_name_length = strlen(friendly_name); |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
848 int alias_length = strlen(log->account->alias); |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
849 GaimBuddy *buddy = gaim_find_buddy(log->account, log->name); |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
850 gboolean from_name_matches; |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
851 gboolean to_name_matches; |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
852 |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
853 if (buddy && buddy->alias) |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
854 their_name = buddy->alias; |
11459 | 855 |
11702
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
856 /* Try to guess which user is me. |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
857 * The first step is to determine if either of the names matches either my |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
858 * friendly name or alias. For this test, "match" is defined as: |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
859 * ^(friendly_name|alias)([^a-zA-Z0-9].*)?$ |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
860 */ |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
861 from_name_matches = ((g_str_has_prefix( |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
862 from_name, friendly_name) && |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
863 !isalnum(*(from_name + friendly_name_length))) || |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
864 (g_str_has_prefix(from_name, log->account->alias) && |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
865 !isalnum(*(from_name + alias_length)))); |
11459 | 866 |
11702
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
867 to_name_matches = ((g_str_has_prefix( |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
868 to_name, friendly_name) && |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
869 !isalnum(*(to_name + friendly_name_length))) || |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
870 (g_str_has_prefix(to_name, log->account->alias) && |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
871 !isalnum(*(to_name + alias_length)))); |
11459 | 872 |
11702
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
873 if (from_name_matches) { |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
874 if (!to_name_matches) { |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
875 name_guessed = NAME_GUESS_ME; |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
876 } |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
877 } else if (to_name_matches) { |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
878 name_guessed = NAME_GUESS_THEM; |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
879 } else { |
994f1c7bee8b
[gaim-migrate @ 13993]
Richard Laager <rlaager@wiktel.com>
parents:
11503
diff
changeset
|
880 if (buddy && buddy->alias) { |
11459 | 881 char *alias = g_strdup(buddy->alias); |
882 | |
883 /* "Truncate" the string at the first non-alphanumeric | |
884 * character. The idea is to relax the comparison. | |
885 */ | |
886 char *temp; | |
887 for (temp = alias; *temp ; temp++) { | |
888 if (!isalnum(*temp)) { | |
889 *temp = '\0'; | |
890 break; | |
891 } | |
892 } | |
893 alias_length = strlen(alias); | |
894 | |
895 /* Try to guess which user is them. | |
896 * The first step is to determine if either of the names | |
897 * matches their alias. For this test, "match" is | |
898 * defined as: ^alias([^a-zA-Z0-9].*)?$ | |
899 */ | |
900 from_name_matches = (g_str_has_prefix( | |
901 from_name, alias) && | |
902 !isalnum(*(from_name + | |
903 alias_length))); | |
904 | |
905 to_name_matches = (g_str_has_prefix( | |
906 to_name, alias) && | |
907 !isalnum(*(to_name + | |
908 alias_length))); | |
909 | |
910 g_free(alias); | |
911 | |
912 if (from_name_matches) { | |
913 if (!to_name_matches) { | |
914 name_guessed = NAME_GUESS_THEM; | |
915 } | |
916 } else if (to_name_matches) { | |
917 name_guessed = NAME_GUESS_ME; | |
918 } else if (buddy->server_alias) { | |
919 friendly_name_length = | |
920 strlen(buddy->server_alias); | |
921 | |
922 /* Try to guess which user is them. | |
923 * The first step is to determine if either of | |
924 * the names matches their friendly name. For | |
925 * this test, "match" is defined as: | |
926 * ^friendly_name([^a-zA-Z0-9].*)?$ | |
927 */ | |
928 from_name_matches = (g_str_has_prefix( | |
929 from_name, | |
930 buddy->server_alias) && | |
931 !isalnum(*(from_name + | |
932 friendly_name_length))); | |
933 | |
934 to_name_matches = (g_str_has_prefix( | |
935 to_name, buddy->server_alias) && | |
936 !isalnum(*(to_name + | |
937 friendly_name_length))); | |
938 | |
939 if (from_name_matches) { | |
940 if (!to_name_matches) { | |
941 name_guessed = NAME_GUESS_THEM; | |
942 } | |
943 } else if (to_name_matches) { | |
944 name_guessed = NAME_GUESS_ME; | |
945 } | |
946 } | |
947 } | |
948 } | |
949 } | |
950 } | |
951 | |
952 if (name_guessed != NAME_GUESS_UNKNOWN) { | |
953 text = g_string_append(text, "<span style=\"color: #"); | |
954 if (name_guessed == NAME_GUESS_ME) | |
955 text = g_string_append(text, "16569E"); | |
956 else | |
957 text = g_string_append(text, "A82F2F"); | |
958 text = g_string_append(text, ";\">"); | |
959 } | |
960 | |
961 time_unix = msn_logger_parse_timestamp(message); | |
962 tm_new = localtime(&time_unix); | |
963 | |
964 timestamp = g_strdup_printf("<font size=\"2\">(%02u:%02u:%02u)</font> ", | |
965 tm_new->tm_hour, tm_new->tm_min, tm_new->tm_sec); | |
966 text = g_string_append(text, timestamp); | |
967 g_free(timestamp); | |
968 | |
969 if (from_name) { | |
970 text = g_string_append(text, "<b>"); | |
971 | |
972 if (name_guessed == NAME_GUESS_ME) | |
973 text = g_string_append(text, log->account->alias); | |
974 else if (name_guessed == NAME_GUESS_THEM) | |
975 text = g_string_append(text, their_name); | |
976 else | |
977 text = g_string_append(text, from_name); | |
978 | |
979 text = g_string_append(text, ":</b> "); | |
980 } | |
981 | |
982 if (name_guessed != NAME_GUESS_UNKNOWN) | |
983 text = g_string_append(text, "</span>"); | |
984 | |
985 style = xmlnode_get_attrib(text_node, "Style"); | |
986 | |
987 if (style && *style) { | |
988 text = g_string_append(text, "<span style=\""); | |
989 text = g_string_append(text, style); | |
990 text = g_string_append(text, "\">"); | |
991 text = g_string_append(text, xmlnode_get_data(text_node)); | |
992 text = g_string_append(text, "</span>\n"); | |
993 } else { | |
994 text = g_string_append(text, xmlnode_get_data(text_node)); | |
995 text = g_string_append(text, "\n"); | |
996 } | |
997 } | |
998 | |
999 data->text = text; | |
1000 | |
1001 return text->str; | |
1002 } | |
1003 | |
1004 static int msn_logger_size (GaimLog *log) | |
1005 { | |
1006 char *text; | |
1007 size_t size; | |
1008 | |
1009 g_return_val_if_fail(log != NULL, 0); | |
1010 | |
1011 if (gaim_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) | |
1012 return 0; | |
1013 | |
1014 text = msn_logger_read(log, NULL); | |
1015 size = strlen(text); | |
1016 g_free(text); | |
1017 | |
1018 return size; | |
1019 } | |
1020 | |
1021 static void msn_logger_finalize(GaimLog *log) | |
1022 { | |
1023 struct msn_logger_data *data; | |
1024 | |
1025 g_return_if_fail(log != NULL); | |
1026 | |
1027 data = log->logger_data; | |
1028 | |
1029 if (data->last_log) | |
1030 xmlnode_free(data->root); | |
1031 | |
1032 if (data->text) | |
1033 g_string_free(data->text, FALSE); | |
1034 } | |
1035 | |
1036 | |
1037 /***************************************************************************** | |
1038 * Trillian Logger * | |
1039 *****************************************************************************/ | |
1040 | |
1041 /* The trillian logger doesn't write logs, only reads them. This is to include | |
1042 * Trillian logs in the log viewer transparently. | |
1043 */ | |
1044 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1045 static GaimLogLogger *trillian_logger; |
11459 | 1046 static void trillian_logger_finalize(GaimLog *log); |
1047 | |
1048 struct trillian_logger_data { | |
1049 char *path; /* FIXME: Change this to use GaimStringref like log.c:old_logger_list */ | |
1050 int offset; | |
1051 int length; | |
1052 char *their_nickname; | |
1053 }; | |
1054 | |
1055 static GList *trillian_logger_list(GaimLogType type, const char *sn, GaimAccount *account) | |
1056 { | |
1057 GList *list = NULL; | |
1058 const char *logdir; | |
1059 GaimPlugin *plugin; | |
1060 GaimPluginProtocolInfo *prpl_info; | |
1061 char *prpl_name; | |
1062 const char *buddy_name; | |
1063 char *filename; | |
1064 char *path; | |
1065 GError *error = NULL; | |
1066 gchar *contents = NULL; | |
1067 gsize length; | |
1068 gchar *line; | |
1069 gchar *c; | |
1070 | |
1071 g_return_val_if_fail(sn != NULL, list); | |
1072 g_return_val_if_fail(account != NULL, list); | |
1073 | |
1074 logdir = gaim_prefs_get_string("/plugins/core/log_reader/trillian/log_directory"); | |
1075 | |
1076 /* By clearing the log directory path, this logger can be (effectively) disabled. */ | |
1077 if (!*logdir) | |
1078 return list; | |
1079 | |
1080 plugin = gaim_find_prpl(gaim_account_get_protocol_id(account)); | |
1081 if (!plugin) | |
1082 return NULL; | |
1083 | |
1084 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(plugin); | |
1085 if (!prpl_info->list_icon) | |
1086 return NULL; | |
1087 | |
1088 prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1); | |
1089 | |
1090 buddy_name = gaim_normalize(account, sn); | |
1091 | |
1092 filename = g_strdup_printf("%s.log", buddy_name); | |
1093 path = g_build_filename( | |
1094 logdir, prpl_name, filename, NULL); | |
1095 | |
1096 gaim_debug(GAIM_DEBUG_INFO, "Trillian log list", | |
1097 "Reading %s\n", path); | |
1098 /* FIXME: There's really no need to read the entire file at once. | |
1099 * See src/log.c:old_logger_list for a better approach. | |
1100 */ | |
1101 if (!g_file_get_contents(path, &contents, &length, &error)) { | |
1102 if (error) { | |
1103 g_error_free(error); | |
1104 error = NULL; | |
1105 } | |
1106 g_free(path); | |
1107 | |
1108 path = g_build_filename( | |
1109 logdir, prpl_name, "Query", filename, NULL); | |
1110 gaim_debug(GAIM_DEBUG_INFO, "Trillian log list", | |
1111 "Reading %s\n", path); | |
1112 if (!g_file_get_contents(path, &contents, &length, &error)) { | |
1113 if (error) | |
1114 g_error_free(error); | |
1115 } | |
1116 } | |
1117 g_free(filename); | |
1118 | |
1119 if (contents) { | |
1120 struct trillian_logger_data *data = NULL; | |
1121 int offset = 0; | |
1122 int last_line_offset = 0; | |
1123 | |
1124 line = contents; | |
1125 c = contents; | |
1126 while (*c) { | |
1127 offset++; | |
1128 | |
1129 if (*c != '\n') { | |
1130 c++; | |
1131 continue; | |
1132 } | |
1133 | |
1134 *c = '\0'; | |
1135 if (g_str_has_prefix(line, "Session Close ")) { | |
1136 if (data && !data->length) | |
1137 data->length = last_line_offset - data->offset; | |
1138 if (!data->length) { | |
1139 /* This log had no data, so we remove it. */ | |
1140 GList *last = g_list_last(list); | |
1141 | |
1142 gaim_debug(GAIM_DEBUG_INFO, "Trillian log list", | |
1143 "Empty log. Offset %i\n", data->offset); | |
1144 | |
1145 trillian_logger_finalize((GaimLog *)last->data); | |
1146 list = g_list_delete_link(list, last); | |
1147 } | |
1148 } else if (line[0] && line[1] && line [3] && | |
1149 g_str_has_prefix(&line[3], "sion Start ")) { | |
1150 | |
1151 char *their_nickname = line; | |
1152 char *timestamp; | |
1153 | |
1154 if (data && !data->length) | |
1155 data->length = last_line_offset - data->offset; | |
1156 | |
1157 while (*their_nickname && (*their_nickname != ':')) | |
1158 their_nickname++; | |
1159 their_nickname++; | |
1160 | |
1161 /* This code actually has nothing to do with | |
1162 * the timestamp YET. I'm simply using this | |
1163 * variable for now to NUL-terminate the | |
1164 * their_nickname string. | |
1165 */ | |
1166 timestamp = their_nickname; | |
1167 while (*timestamp && *timestamp != ')') | |
1168 timestamp++; | |
1169 | |
1170 if (*timestamp == ')') { | |
1171 char *month; | |
1172 struct tm tm; | |
1173 | |
1174 *timestamp = '\0'; | |
1175 if (line[0] && line[1] && line[2]) | |
1176 timestamp += 3; | |
1177 | |
1178 /* Now we start dealing with the timestamp. */ | |
1179 | |
1180 /* Skip over the day name. */ | |
1181 while (*timestamp && (*timestamp != ' ')) | |
1182 timestamp++; | |
1183 *timestamp = '\0'; | |
1184 timestamp++; | |
1185 | |
1186 /* Parse out the month. */ | |
1187 month = timestamp; | |
1188 while (*timestamp && (*timestamp != ' ')) | |
1189 timestamp++; | |
1190 *timestamp = '\0'; | |
1191 timestamp++; | |
1192 | |
1193 /* Parse the day, time, and year. */ | |
1194 if (sscanf(timestamp, "%u %u:%u:%u %u", | |
1195 &tm.tm_mday, &tm.tm_hour, | |
1196 &tm.tm_min, &tm.tm_sec, | |
1197 &tm.tm_year) != 5) { | |
1198 | |
1199 gaim_debug(GAIM_DEBUG_ERROR, | |
1200 "Trillian log timestamp parse", | |
1201 "Session Start parsing error\n"); | |
1202 } else { | |
1203 GaimLog *log; | |
1204 | |
1205 tm.tm_year -= 1900; | |
1206 | |
1207 /* Let the C library deal with | |
1208 * daylight savings time. | |
1209 */ | |
1210 tm.tm_isdst = -1; | |
1211 | |
1212 /* Ugly hack, in case current locale | |
1213 * is not English. This code is taken | |
1214 * from log.c. | |
1215 */ | |
1216 if (strcmp(month, "Jan") == 0) { | |
1217 tm.tm_mon= 0; | |
1218 } else if (strcmp(month, "Feb") == 0) { | |
1219 tm.tm_mon = 1; | |
1220 } else if (strcmp(month, "Mar") == 0) { | |
1221 tm.tm_mon = 2; | |
1222 } else if (strcmp(month, "Apr") == 0) { | |
1223 tm.tm_mon = 3; | |
1224 } else if (strcmp(month, "May") == 0) { | |
1225 tm.tm_mon = 4; | |
1226 } else if (strcmp(month, "Jun") == 0) { | |
1227 tm.tm_mon = 5; | |
1228 } else if (strcmp(month, "Jul") == 0) { | |
1229 tm.tm_mon = 6; | |
1230 } else if (strcmp(month, "Aug") == 0) { | |
1231 tm.tm_mon = 7; | |
1232 } else if (strcmp(month, "Sep") == 0) { | |
1233 tm.tm_mon = 8; | |
1234 } else if (strcmp(month, "Oct") == 0) { | |
1235 tm.tm_mon = 9; | |
1236 } else if (strcmp(month, "Nov") == 0) { | |
1237 tm.tm_mon = 10; | |
1238 } else if (strcmp(month, "Dec") == 0) { | |
1239 tm.tm_mon = 11; | |
1240 } | |
1241 | |
1242 data = g_new0( | |
1243 struct trillian_logger_data, 1); | |
1244 data->path = g_strdup(path); | |
1245 data->offset = offset; | |
1246 data->length = 0; | |
1247 data->their_nickname = | |
1248 g_strdup(their_nickname); | |
1249 | |
13119
fcde3faa1f57
[gaim-migrate @ 15481]
Richard Laager <rlaager@wiktel.com>
parents:
12727
diff
changeset
|
1250 /* XXX: Look into this later... Should we pass in a struct tm? */ |
11459 | 1251 log = gaim_log_new(GAIM_LOG_IM, |
13119
fcde3faa1f57
[gaim-migrate @ 15481]
Richard Laager <rlaager@wiktel.com>
parents:
12727
diff
changeset
|
1252 sn, account, NULL, mktime(&tm), NULL); |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1253 log->logger = trillian_logger; |
11459 | 1254 log->logger_data = data; |
1255 | |
1256 list = g_list_append(list, log); | |
1257 } | |
1258 } | |
1259 } | |
1260 c++; | |
1261 line = c; | |
1262 last_line_offset = offset; | |
1263 } | |
1264 | |
1265 g_free(contents); | |
1266 } | |
1267 g_free(path); | |
1268 | |
1269 g_free(prpl_name); | |
1270 | |
1271 return list; | |
1272 } | |
1273 | |
1274 static char * trillian_logger_read (GaimLog *log, GaimLogReadFlags *flags) | |
1275 { | |
1276 struct trillian_logger_data *data; | |
1277 char *read; | |
1278 FILE *file; | |
1279 GaimBuddy *buddy; | |
1280 char *escaped; | |
1281 GString *formatted; | |
1282 char *c; | |
1283 char *line; | |
1284 | |
1285 g_return_val_if_fail(log != NULL, g_strdup("")); | |
1286 | |
1287 data = log->logger_data; | |
1288 | |
1289 g_return_val_if_fail(data->path != NULL, g_strdup("")); | |
1290 g_return_val_if_fail(data->length > 0, g_strdup("")); | |
1291 g_return_val_if_fail(data->their_nickname != NULL, g_strdup("")); | |
1292 | |
1293 gaim_debug(GAIM_DEBUG_INFO, "Trillian log read", | |
1294 "Reading %s\n", data->path); | |
1295 | |
1296 read = g_malloc(data->length + 2); | |
1297 | |
1298 file = fopen(data->path, "rb"); | |
1299 fseek(file, data->offset, SEEK_SET); | |
1300 fread(read, data->length, 1, file); | |
1301 fclose(file); | |
1302 | |
1303 if (read[data->length-1] == '\n') { | |
1304 read[data->length] = '\0'; | |
1305 } else { | |
1306 read[data->length] = '\n'; | |
1307 read[data->length+1] = '\0'; | |
1308 } | |
1309 | |
1310 /* Load miscellaneous data. */ | |
1311 buddy = gaim_find_buddy(log->account, log->name); | |
1312 | |
1313 escaped = g_markup_escape_text(read, -1); | |
1314 g_free(read); | |
1315 read = escaped; | |
1316 | |
1317 /* Apply formatting... */ | |
1318 formatted = g_string_new(""); | |
1319 c = read; | |
1320 line = read; | |
1321 while (*c) | |
1322 { | |
1323 if (*c == '\n') | |
1324 { | |
1325 char *link_temp_line; | |
1326 char *link; | |
1327 char *timestamp; | |
1328 char *footer = NULL; | |
1329 *c = '\0'; | |
1330 | |
1331 /* Convert links. | |
1332 * | |
1333 * The format is (Link: URL)URL | |
1334 * So, I want to find each occurance of "(Link: " and replace that chunk with: | |
1335 * <a href=" | |
1336 * Then, replace the next ")" with: | |
1337 * "> | |
1338 * Then, replace the next " " (or add this if the end-of-line is reached) with: | |
1339 * </a> | |
1340 */ | |
1341 link_temp_line = NULL; | |
1342 while ((link = g_strstr_len(line, strlen(line), "(Link: "))) { | |
1343 GString *temp; | |
1344 | |
1345 if (!*link) | |
1346 continue; | |
1347 | |
1348 *link = '\0'; | |
1349 link++; | |
1350 | |
1351 temp = g_string_new(line); | |
1352 g_string_append(temp, "<a href=\""); | |
1353 | |
1354 if (strlen(link) >= 6) { | |
1355 link += (sizeof("(Link: ") - 1); | |
1356 | |
1357 while (*link && *link != ')') { | |
1358 g_string_append_c(temp, *link); | |
1359 link++; | |
1360 } | |
1361 if (link) { | |
1362 link++; | |
1363 | |
1364 g_string_append(temp, "\">"); | |
1365 while (*link && *link != ' ') { | |
1366 g_string_append_c(temp, *link); | |
1367 link++; | |
1368 } | |
1369 g_string_append(temp, "</a>"); | |
1370 } | |
1371 | |
1372 g_string_append(temp, link); | |
1373 | |
1374 /* Free the last round's line. */ | |
1375 if (link_temp_line) | |
1376 g_free(line); | |
1377 | |
1378 line = temp->str; | |
1379 g_string_free(temp, FALSE); | |
1380 | |
1381 /* Save this memory location so we can free it later. */ | |
1382 link_temp_line = line; | |
1383 } | |
1384 } | |
1385 | |
1386 timestamp = ""; | |
1387 if (*line == '[') { | |
1388 timestamp = line; | |
1389 while (*timestamp && *timestamp != ']') | |
1390 timestamp++; | |
1391 if (*timestamp == ']') { | |
1392 *timestamp = '\0'; | |
1393 line++; | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1394 /* TODO: Parse the timestamp and convert it to Gaim's format. */ |
11459 | 1395 g_string_append_printf(formatted, |
1396 "<font size=\"2\">(%s)</font> ", line); | |
1397 line = timestamp; | |
1398 if (line[1] && line[2]) | |
1399 line += 2; | |
1400 } | |
1401 | |
1402 if (g_str_has_prefix(line, "*** ")) { | |
1403 line += (sizeof("*** ") - 1); | |
1404 g_string_append(formatted, "<b>"); | |
1405 footer = "</b>"; | |
1406 if (g_str_has_prefix(line, "NOTE: This user is offline.")) { | |
1407 line = _("User is offline."); | |
1408 } else if (g_str_has_prefix(line, | |
1409 "NOTE: Your status is currently set to ")) { | |
1410 | |
1411 line += (sizeof("NOTE: ") - 1); | |
1412 } else if (g_str_has_prefix(line, "Auto-response sent to ")) { | |
1413 g_string_append(formatted, _("Auto-response sent:")); | |
1414 while (*line && *line != ':') | |
1415 line++; | |
1416 if (*line) | |
1417 line++; | |
1418 g_string_append(formatted, "</b>"); | |
1419 footer = NULL; | |
1420 } else if (strstr(line, " signed off ")) { | |
1421 if (buddy->alias) | |
1422 g_string_append_printf(formatted, | |
1423 _("%s logged out."), buddy->alias); | |
1424 else | |
1425 g_string_append_printf(formatted, | |
1426 _("%s logged out."), log->name); | |
1427 line = ""; | |
1428 } else if (strstr(line, " signed on ")) { | |
1429 if (buddy->alias) | |
1430 g_string_append(formatted, buddy->alias); | |
1431 else | |
1432 g_string_append(formatted, log->name); | |
1433 line = " logged in."; | |
1434 } else if (g_str_has_prefix(line, | |
1435 "One or more messages may have been undeliverable.")) { | |
1436 | |
1437 g_string_append(formatted, | |
1438 "<span style=\"color: #ff0000;\">"); | |
1439 g_string_append(formatted, | |
1440 _("One or more messages may have been " | |
1441 "undeliverable.")); | |
1442 line = ""; | |
1443 footer = "</span></b>"; | |
1444 } else if (g_str_has_prefix(line, | |
1445 "You have been disconnected.")) { | |
1446 | |
1447 g_string_append(formatted, | |
1448 "<span style=\"color: #ff0000;\">"); | |
1449 g_string_append(formatted, | |
1450 _("You were disconnected from the server.")); | |
1451 line = ""; | |
1452 footer = "</span></b>"; | |
1453 } else if (g_str_has_prefix(line, | |
1454 "You are currently disconnected.")) { | |
1455 | |
1456 g_string_append(formatted, | |
1457 "<span style=\"color: #ff0000;\">"); | |
1458 line = _("You are currently disconnected. Messages " | |
1459 "will not be received unless you are " | |
1460 "logged in."); | |
1461 footer = "</span></b>"; | |
1462 } else if (g_str_has_prefix(line, | |
1463 "Your previous message has not been sent.")) { | |
1464 | |
1465 g_string_append(formatted, | |
1466 "<span style=\"color: #ff0000;\">"); | |
1467 | |
1468 if (g_str_has_prefix(line, | |
1469 "Your previous message has not been sent. " | |
1470 "Reason: Maximum length exceeded.")) { | |
1471 | |
1472 g_string_append(formatted, | |
1473 _("Message could not be sent because " | |
1474 "the maximum length was exceeded.")); | |
1475 line = ""; | |
1476 } else { | |
1477 g_string_append(formatted, | |
1478 _("Message could not be sent.")); | |
1479 line += (sizeof( | |
1480 "Your previous message " | |
1481 "has not been sent. ") - 1); | |
1482 } | |
1483 | |
1484 footer = "</span></b>"; | |
1485 } | |
1486 } else if (g_str_has_prefix(line, data->their_nickname)) { | |
1487 if (buddy->alias) { | |
1488 line += strlen(data->their_nickname) + 2; | |
1489 g_string_append_printf(formatted, | |
1490 "<span style=\"color: #A82F2F;\">" | |
1491 "<b>%s</b></span>: ", buddy->alias); | |
1492 } | |
1493 } else { | |
1494 char *line2 = line; | |
1495 while (*line2 && *line2 != ':') | |
1496 line2++; | |
1497 if (*line2 == ':') { | |
1498 line2++; | |
1499 line = line2; | |
1500 g_string_append_printf(formatted, | |
1501 "<span style=\"color: #16569E;\">" | |
1502 "<b>%s</b></span>:", log->account->alias); | |
1503 } | |
1504 } | |
1505 } | |
1506 | |
1507 g_string_append(formatted, line); | |
1508 | |
1509 if (footer) | |
1510 g_string_append(formatted, footer); | |
1511 | |
1512 g_string_append_c(formatted, '\n'); | |
1513 | |
1514 if (link_temp_line) | |
1515 g_free(link_temp_line); | |
1516 | |
1517 c++; | |
1518 line = c; | |
1519 } else | |
1520 c++; | |
1521 } | |
1522 | |
1523 g_free(read); | |
1524 read = formatted->str; | |
1525 g_string_free(formatted, FALSE); | |
1526 | |
1527 return read; | |
1528 } | |
1529 | |
1530 static int trillian_logger_size (GaimLog *log) | |
1531 { | |
1532 struct trillian_logger_data *data; | |
1533 char *text; | |
1534 size_t size; | |
1535 | |
1536 g_return_val_if_fail(log != NULL, 0); | |
1537 | |
1538 data = log->logger_data; | |
1539 | |
1540 if (gaim_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) { | |
1541 return data ? data->length : 0; | |
1542 } | |
1543 | |
1544 text = trillian_logger_read(log, NULL); | |
1545 size = strlen(text); | |
1546 g_free(text); | |
1547 | |
1548 return size; | |
1549 } | |
1550 | |
1551 static void trillian_logger_finalize(GaimLog *log) | |
1552 { | |
1553 struct trillian_logger_data *data; | |
1554 | |
1555 g_return_if_fail(log != NULL); | |
1556 | |
1557 data = log->logger_data; | |
1558 | |
1559 g_free(data->path); | |
1560 g_free(data->their_nickname); | |
1561 | |
1562 } | |
1563 | |
1564 | |
1565 /***************************************************************************** | |
1566 * Plugin Code * | |
1567 *****************************************************************************/ | |
1568 | |
1569 static void | |
1570 init_plugin(GaimPlugin *plugin) | |
1571 { | |
1572 char *path; | |
1573 #ifdef _WIN32 | |
1574 char *folder; | |
1575 #endif | |
1576 | |
1577 g_return_if_fail(plugin != NULL); | |
1578 | |
1579 gaim_prefs_add_none("/plugins/core/log_reader"); | |
1580 | |
1581 | |
1582 /* Add general preferences. */ | |
1583 | |
1584 gaim_prefs_add_bool("/plugins/core/log_reader/fast_sizes", FALSE); | |
1585 gaim_prefs_add_bool("/plugins/core/log_reader/use_name_heuristics", TRUE); | |
1586 | |
1587 | |
1588 /* Add Adium log directory preference. */ | |
1589 gaim_prefs_add_none("/plugins/core/log_reader/adium"); | |
1590 | |
1591 /* Calculate default Adium log directory. */ | |
1592 #ifdef _WIN32 | |
1593 path = ""; | |
1594 #else | |
1595 path = g_build_filename(gaim_home_dir(), "Library", "Application Support", | |
1596 "Adium 2.0", "Users", "Default", "Logs", NULL); | |
1597 #endif | |
1598 | |
1599 gaim_prefs_add_string("/plugins/core/log_reader/adium/log_directory", path); | |
1600 | |
1601 #ifndef _WIN32 | |
1602 g_free(path); | |
1603 #endif | |
1604 | |
1605 | |
1606 /* Add Fire log directory preference. */ | |
1607 gaim_prefs_add_none("/plugins/core/log_reader/fire"); | |
1608 | |
1609 /* Calculate default Fire log directory. */ | |
1610 #ifdef _WIN32 | |
1611 path = ""; | |
1612 #else | |
1613 path = g_build_filename(gaim_home_dir(), "Library", "Application Support", | |
1614 "Fire", "Sessions", NULL); | |
1615 #endif | |
1616 | |
1617 gaim_prefs_add_string("/plugins/core/log_reader/fire/log_directory", path); | |
1618 | |
1619 #ifndef _WIN32 | |
1620 g_free(path); | |
1621 #endif | |
1622 | |
1623 | |
1624 /* Add Messenger Plus! log directory preference. */ | |
1625 gaim_prefs_add_none("/plugins/core/log_reader/messenger_plus"); | |
1626 | |
1627 /* Calculate default Messenger Plus! log directory. */ | |
1628 #ifdef _WIN32 | |
1629 folder = wgaim_get_special_folder(CSIDL_PERSONAL); | |
1630 if (folder) { | |
1631 #endif | |
1632 path = g_build_filename( | |
1633 #ifdef _WIN32 | |
1634 folder, | |
1635 #else | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1636 GAIM_LOG_READER_WINDOWS_MOUNT_POINT, "Documents and Settings", |
11459 | 1637 g_get_user_name(), "My Documents", |
1638 #endif | |
1639 "My Chat Logs", NULL); | |
1640 #ifdef _WIN32 | |
1641 g_free(folder); | |
1642 } else /* !folder */ | |
1643 path = g_strdup(""); | |
1644 #endif | |
1645 | |
1646 gaim_prefs_add_string("/plugins/core/log_reader/messenger_plus/log_directory", path); | |
1647 g_free(path); | |
1648 | |
1649 | |
1650 /* Add MSN Messenger log directory preference. */ | |
1651 gaim_prefs_add_none("/plugins/core/log_reader/msn"); | |
1652 | |
1653 /* Calculate default MSN message history directory. */ | |
1654 #ifdef _WIN32 | |
1655 folder = wgaim_get_special_folder(CSIDL_PERSONAL); | |
1656 if (folder) { | |
1657 #endif | |
1658 path = g_build_filename( | |
1659 #ifdef _WIN32 | |
1660 folder, | |
1661 #else | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1662 GAIM_LOG_READER_WINDOWS_MOUNT_POINT, "Documents and Settings", |
11459 | 1663 g_get_user_name(), "My Documents", |
1664 #endif | |
1665 "My Received Files", NULL); | |
1666 #ifdef _WIN32 | |
1667 g_free(folder); | |
1668 } else /* !folder */ | |
1669 path = g_strdup(""); | |
1670 #endif | |
1671 | |
1672 gaim_prefs_add_string("/plugins/core/log_reader/msn/log_directory", path); | |
1673 g_free(path); | |
1674 | |
1675 | |
1676 /* Add Trillian log directory preference. */ | |
1677 gaim_prefs_add_none("/plugins/core/log_reader/trillian"); | |
1678 | |
1679 #ifdef _WIN32 | |
1680 /* XXX: While a major hack, this is the most reliable way I could | |
1681 * think of to determine the Trillian installation directory. | |
1682 */ | |
1683 HKEY hKey; | |
1684 char buffer[1024] = ""; | |
1685 DWORD size = (sizeof(buffer) - 1); | |
1686 DWORD type; | |
1687 | |
1688 path = NULL; | |
1689 /* TODO: Test this after removing the trailing "\\". */ | |
1690 if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, "Trillian.SkinZip\\shell\\Add\\command\\", | |
1691 0, KEY_QUERY_VALUE, &hKey)) { | |
1692 | |
1693 if(ERROR_SUCCESS == RegQueryValueEx(hKey, "", NULL, &type, (LPBYTE)buffer, &size)) { | |
1694 char *value = buffer; | |
1695 char *temp; | |
1696 | |
1697 /* Ensure the data is null terminated. */ | |
1698 value[size] = '\0'; | |
1699 | |
1700 /* Break apart buffer. */ | |
1701 if (*value == '"') { | |
1702 value++; | |
1703 temp = value; | |
1704 while (*temp && *temp != '"') | |
1705 temp++; | |
1706 } else { | |
1707 temp = value; | |
1708 while (*temp && *temp != ' ') | |
1709 temp++; | |
1710 } | |
1711 *temp = '\0'; | |
1712 | |
1713 /* Set path. */ | |
1714 if (g_str_has_suffix(value, "trillian.exe")) | |
1715 { | |
1716 value[strlen(value) - (sizeof("trillian.exe") - 1)] = '\0'; | |
1717 path = g_build_filename(value, "users", "default", "talk.ini", NULL); | |
1718 } | |
1719 } | |
1720 RegCloseKey(hKey); | |
1721 } | |
1722 | |
1723 if (!path) { | |
1724 char *folder = wgaim_get_special_folder(CSIDL_PROGRAM_FILES); | |
1725 if (folder) | |
1726 path = g_build_filename(folder, "Trillian", | |
1727 "users", "default", "talk.ini", NULL); | |
1728 g_free(folder); | |
1729 } | |
1730 } | |
1731 | |
1732 gboolean found = FALSE; | |
1733 | |
1734 if (path) { | |
1735 /* Read talk.ini file to find the log directory. */ | |
1736 GError *error = NULL; | |
1737 | |
1738 #if 0 && GTK_CHECK_VERSION(2,6,0) /* FIXME: Not tested yet. */ | |
1739 GKeyFile *key_file; | |
1740 | |
1741 gaim_debug(GAIM_DEBUG_INFO, "Trillian talk.ini read", | |
1742 "Reading %s\n", path); | |
1743 if (!g_key_file_load_from_file(key_file, path, G_KEY_FILE_NONE, GError &error)) { | |
1744 gaim_debug(GAIM_DEBUG_ERROR, "Trillian talk.ini read", | |
1745 "Error reading talk.ini\n"); | |
1746 if (error) | |
1747 g_error_free(error); | |
1748 } else { | |
1749 char *logdir = g_key_file_get_string(key_file, "Logging", "Directory", &error); | |
1750 if (error) { | |
1751 gaim_debug(GAIM_DEBUG_ERROR, "Trillian talk.ini read", | |
1752 "Error reading Directory value from Logging section\n"); | |
1753 g_error_free(error); | |
1754 } | |
1755 | |
1756 if (logdir) { | |
1757 g_strchomp(logdir); | |
1758 gaim_prefs_add_string( | |
1759 "/plugins/core/log_reader/trillian/log_directory", logdir); | |
1760 found = TRUE; | |
1761 } | |
1762 | |
1763 g_key_file_free(key_file); | |
1764 } | |
1765 #else /* !GTK_CHECK_VERSION(2,6,0) */ | |
1766 GError *error = NULL; | |
1767 gsize length; | |
1768 | |
1769 gaim_debug(GAIM_DEBUG_INFO, "Trillian talk.ini read", | |
1770 "Reading %s\n", path); | |
1771 if (!g_file_get_contents(path, &contents, &length, &error)) { | |
1772 gaim_debug(GAIM_DEBUG_ERROR, "Trillian talk.ini read", | |
1773 "Error reading talk.ini\n"); | |
1774 if (error) | |
1775 g_error_free(error); | |
1776 } else { | |
1777 char *line = contents; | |
1778 while (*contents) { | |
1779 if (*contents == '\n') { | |
1780 *contents = '\0'; | |
1781 | |
1782 /* XXX: This assumes the first Directory key is under [Logging]. */ | |
1783 if (g_str_has_prefix(line, "Directory=")) { | |
1784 line += (sizeof("Directory=") - 1); | |
1785 g_strchomp(line); | |
1786 gaim_prefs_add_string( | |
1787 "/plugins/core/log_reader/trillian/log_directory", | |
1788 line); | |
1789 found = TRUE; | |
1790 } | |
1791 | |
1792 contents++; | |
1793 line = contents; | |
1794 } else | |
1795 contents++; | |
1796 } | |
1797 g_free(path); | |
1798 g_free(contents); | |
1799 } | |
1800 #endif /* !GTK_CHECK_VERSION(2,6,0) */ | |
1801 } /* path */ | |
1802 | |
1803 if (!found) { | |
1804 #endif /* defined(_WIN32) */ | |
1805 | |
1806 /* Calculate default Trillian log directory. */ | |
1807 #ifdef _WIN32 | |
1808 folder = wgaim_get_special_folder(CSIDL_PROGRAM_FILES); | |
1809 if (folder) { | |
1810 #endif | |
1811 path = g_build_filename( | |
1812 #ifdef _WIN32 | |
1813 folder, | |
1814 #else | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1815 GAIM_LOG_READER_WINDOWS_MOUNT_POINT, "Program Files", |
11459 | 1816 #endif |
1817 "Trillian", "users", "default", "logs", NULL); | |
1818 #ifdef _WIN32 | |
1819 g_free(folder); | |
1820 } else /* !folder */ | |
1821 path = g_strdup(""); | |
1822 #endif | |
1823 | |
1824 gaim_prefs_add_string("/plugins/core/log_reader/trillian/log_directory", path); | |
1825 g_free(path); | |
1826 | |
1827 #ifdef _WIN32 | |
1828 } /* !found */ | |
1829 #endif | |
1830 } | |
1831 | |
1832 static gboolean | |
1833 plugin_load(GaimPlugin *plugin) | |
1834 { | |
1835 g_return_val_if_fail(plugin != NULL, FALSE); | |
1836 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1837 adium_logger = gaim_log_logger_new("adium", "Adium", 6, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1838 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1839 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1840 adium_logger_finalize, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1841 adium_logger_list, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1842 adium_logger_read, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1843 adium_logger_size); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1844 gaim_log_logger_add(adium_logger); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1845 |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1846 fire_logger = gaim_log_logger_new("fire", "Fire", 6, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1847 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1848 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1849 fire_logger_finalize, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1850 fire_logger_list, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1851 fire_logger_read, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1852 fire_logger_size); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1853 gaim_log_logger_add(fire_logger); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1854 |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1855 messenger_plus_logger = gaim_log_logger_new("messenger_plus", "Messenger Plus!", 6, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1856 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1857 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1858 messenger_plus_logger_finalize, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1859 messenger_plus_logger_list, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1860 messenger_plus_logger_read, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1861 messenger_plus_logger_size); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1862 gaim_log_logger_add(messenger_plus_logger); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1863 |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1864 msn_logger = gaim_log_logger_new("msn", "MSN Messenger", 6, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1865 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1866 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1867 msn_logger_finalize, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1868 msn_logger_list, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1869 msn_logger_read, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1870 msn_logger_size); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1871 gaim_log_logger_add(msn_logger); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1872 |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1873 trillian_logger = gaim_log_logger_new("trillian", "Trillian", 6, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1874 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1875 NULL, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1876 trillian_logger_finalize, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1877 trillian_logger_list, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1878 trillian_logger_read, |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1879 trillian_logger_size); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1880 gaim_log_logger_add(trillian_logger); |
11459 | 1881 |
1882 return TRUE; | |
1883 } | |
1884 | |
1885 static gboolean | |
1886 plugin_unload(GaimPlugin *plugin) | |
1887 { | |
1888 g_return_val_if_fail(plugin != NULL, FALSE); | |
1889 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1890 gaim_log_logger_remove(adium_logger); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1891 gaim_log_logger_remove(fire_logger); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1892 gaim_log_logger_remove(messenger_plus_logger); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1893 gaim_log_logger_remove(msn_logger); |
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1894 gaim_log_logger_remove(trillian_logger); |
11459 | 1895 |
1896 return TRUE; | |
1897 } | |
1898 | |
1899 static GaimPluginPrefFrame * | |
1900 get_plugin_pref_frame(GaimPlugin *plugin) | |
1901 { | |
1902 GaimPluginPrefFrame *frame; | |
1903 GaimPluginPref *ppref; | |
1904 | |
1905 g_return_val_if_fail(plugin != NULL, FALSE); | |
1906 | |
1907 frame = gaim_plugin_pref_frame_new(); | |
1908 | |
1909 | |
1910 /* Add general preferences. */ | |
1911 | |
1912 ppref = gaim_plugin_pref_new_with_label(_("General Log Reading Configuration")); | |
1913 gaim_plugin_pref_frame_add(frame, ppref); | |
1914 | |
1915 ppref = gaim_plugin_pref_new_with_name_and_label( | |
1916 "/plugins/core/log_reader/fast_sizes", _("Fast size calculations")); | |
1917 gaim_plugin_pref_frame_add(frame, ppref); | |
1918 | |
1919 ppref = gaim_plugin_pref_new_with_name_and_label( | |
1920 "/plugins/core/log_reader/use_name_heuristics", _("Use name heuristics")); | |
1921 gaim_plugin_pref_frame_add(frame, ppref); | |
1922 | |
1923 | |
1924 /* Add Log Directory preferences. */ | |
1925 | |
1926 ppref = gaim_plugin_pref_new_with_label(_("Log Directory")); | |
1927 gaim_plugin_pref_frame_add(frame, ppref); | |
1928 | |
1929 ppref = gaim_plugin_pref_new_with_name_and_label( | |
1930 "/plugins/core/log_reader/adium/log_directory", _("Adium")); | |
1931 gaim_plugin_pref_frame_add(frame, ppref); | |
1932 | |
1933 ppref = gaim_plugin_pref_new_with_name_and_label( | |
1934 "/plugins/core/log_reader/fire/log_directory", _("Fire")); | |
1935 gaim_plugin_pref_frame_add(frame, ppref); | |
1936 | |
1937 ppref = gaim_plugin_pref_new_with_name_and_label( | |
1938 "/plugins/core/log_reader/messenger_plus/log_directory", _("Messenger Plus!")); | |
1939 gaim_plugin_pref_frame_add(frame, ppref); | |
1940 | |
1941 ppref = gaim_plugin_pref_new_with_name_and_label( | |
1942 "/plugins/core/log_reader/msn/log_directory", _("MSN Messenger")); | |
1943 gaim_plugin_pref_frame_add(frame, ppref); | |
1944 | |
1945 ppref = gaim_plugin_pref_new_with_name_and_label( | |
1946 "/plugins/core/log_reader/trillian/log_directory", _("Trillian")); | |
1947 gaim_plugin_pref_frame_add(frame, ppref); | |
1948 | |
1949 return frame; | |
1950 } | |
1951 | |
1952 static GaimPluginUiInfo prefs_info = { | |
12727
ae51c59bf819
[gaim-migrate @ 15071]
Richard Laager <rlaager@wiktel.com>
parents:
11702
diff
changeset
|
1953 get_plugin_pref_frame, |
ae51c59bf819
[gaim-migrate @ 15071]
Richard Laager <rlaager@wiktel.com>
parents:
11702
diff
changeset
|
1954 0, /* page_num (reserved) */ |
ae51c59bf819
[gaim-migrate @ 15071]
Richard Laager <rlaager@wiktel.com>
parents:
11702
diff
changeset
|
1955 NULL /* frame (reserved) */ |
11459 | 1956 }; |
1957 | |
1958 static GaimPluginInfo info = | |
1959 { | |
1960 GAIM_PLUGIN_MAGIC, | |
1961 GAIM_MAJOR_VERSION, | |
1962 GAIM_MINOR_VERSION, | |
1963 GAIM_PLUGIN_STANDARD, /**< type */ | |
1964 NULL, /**< ui_requirement */ | |
1965 0, /**< flags */ | |
1966 NULL, /**< dependencies */ | |
1967 GAIM_PRIORITY_DEFAULT, /**< priority */ | |
1968 "core-log_reader", /**< id */ | |
1969 N_("Log Reader"), /**< name */ | |
1970 VERSION, /**< version */ | |
1971 | |
1972 /** summary */ | |
1973 N_("Includes other IM clients' logs in the " | |
1974 "log viewer."), | |
1975 | |
1976 /** description */ | |
1977 N_("When viewing logs, this plugin will include " | |
1978 "logs from other IM clients. Currently, this " | |
1979 "includes Adium, Fire, Messenger Plus!, " | |
1980 "MSN Messenger, and Trillian."), | |
1981 | |
11503
cd0c8830d881
[gaim-migrate @ 13748]
Richard Laager <rlaager@wiktel.com>
parents:
11459
diff
changeset
|
1982 "Richard Laager <rlaager@users.sf.net>", /**< author */ |
11459 | 1983 GAIM_WEBSITE, /**< homepage */ |
1984 plugin_load, /**< load */ | |
1985 plugin_unload, /**< unload */ | |
1986 NULL, /**< destroy */ | |
1987 NULL, /**< ui_info */ | |
1988 NULL, /**< extra_info */ | |
1989 &prefs_info, /**< prefs_info */ | |
1990 NULL /**< actions */ | |
1991 }; | |
1992 | |
1993 GAIM_INIT_PLUGIN(log_reader, init_plugin, info) |