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