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