Mercurial > pidgin
annotate src/log.c @ 7715:9f6dc7b4fc57
[gaim-migrate @ 8360]
I didn't do this earlier, because I figured people would still want to add
their own HTML tags using CVS, but I strongly doubt anyone will be hit with
the overwhelming desire to manually change the font size in an IM until that
gets implemented. I'm escaping HTML now. This will only happen with protocols
that support HTML, other protocols will receive just the text in the box.
When the toolbar gets widgetized, it will become desensitive when the current
account does not support HTML.
Also, because it's been asked of me, your default outgoing font will be set
in the wysiwyg entry widget, and ctrl-up will show the correct formatting.
committer: Tailor Script <tailor@pidgin.im>
| author | Sean Egan <seanegan@gmail.com> |
|---|---|
| date | Wed, 03 Dec 2003 04:29:26 +0000 |
| parents | 9e122b8f564f |
| children | 68e205e746c9 |
| rev | line source |
|---|---|
| 7431 | 1 /** |
| 2 * @file log.c Logging API | |
| 3 * @ingroup core | |
| 4 * | |
| 5 * gaim | |
| 6 * | |
| 7 * Copyright (C) 2003 Buzz Lightyear | |
| 7436 | 8 * |
| 7431 | 9 * This program is free software; you can redistribute it and/or modify |
| 10 * it under the terms of the GNU General Public License as published by | |
| 11 * the Free Software Foundation; either version 2 of the License, or | |
| 12 * (at your option) any later version. | |
| 13 * | |
| 14 * This program is distributed in the hope that it will be useful, | |
| 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 * GNU General Public License for more details. | |
| 18 * | |
| 19 * You should have received a copy of the GNU General Public License | |
| 20 * along with this program; if not, write to the Free Software | |
| 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 4184 | 22 */ |
| 4195 | 23 |
| 7431 | 24 #include "account.h" |
|
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
25 #include "debug.h" |
| 7431 | 26 #include "internal.h" |
|
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
27 #include "log.h" |
| 5548 | 28 #include "prefs.h" |
|
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
29 #include "util.h" |
|
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
30 |
| 7457 | 31 static GaimLogLogger html_logger; |
| 7431 | 32 static GaimLogLogger txt_logger; |
| 33 static GaimLogLogger old_logger; | |
|
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
34 |
| 7431 | 35 /************************************************************************** |
| 36 * PUBLIC LOGGING FUNCTIONS *********************************************** | |
| 37 **************************************************************************/ | |
| 4184 | 38 |
| 7431 | 39 GaimLog *gaim_log_new(GaimLogType type, const char *name, GaimAccount *account, time_t time) |
| 40 { | |
| 41 GaimLog *log = g_new0(GaimLog, 1); | |
| 42 log->name = g_strdup(name); | |
| 43 log->account = account; | |
| 44 log->time = time; | |
| 45 log->logger = gaim_log_logger_get(); | |
| 7440 | 46 if (log->logger && log->logger->create) |
| 47 log->logger->create(log); | |
| 7431 | 48 return log; |
| 4184 | 49 } |
| 50 | |
| 7431 | 51 void gaim_log_free(GaimLog *log) |
| 4184 | 52 { |
| 7431 | 53 g_return_if_fail(log); |
| 54 if (log->logger && log->logger->finalize) | |
| 55 log->logger->finalize(log); | |
| 56 g_free(log->name); | |
| 57 g_free(log); | |
| 58 } | |
| 7436 | 59 |
| 4184 | 60 |
| 7436 | 61 void gaim_log_write(GaimLog *log, GaimMessageFlags type, |
| 7431 | 62 const char *from, time_t time, const char *message) |
| 63 { | |
| 64 g_return_if_fail(log); | |
| 65 g_return_if_fail(log->logger); | |
| 7442 | 66 g_return_if_fail(log->logger->write); |
| 7431 | 67 |
| 7555 | 68 if ((log->type == GAIM_LOG_IM && gaim_prefs_get_bool("/core/logging/log_ims")) || |
| 69 (log->type == GAIM_LOG_CHAT && gaim_prefs_get_bool("/core/logging/log_chats"))) | |
| 7553 | 70 (log->logger->write)(log, type, from, time, message); |
| 4184 | 71 } |
| 72 | |
| 7431 | 73 char *gaim_log_read(GaimLog *log, GaimLogReadFlags *flags) |
| 4184 | 74 { |
| 7542 | 75 GaimLogReadFlags mflags; |
| 7431 | 76 g_return_val_if_fail(log && log->logger, NULL); |
| 7462 | 77 if (log->logger->read) { |
| 7535 | 78 char *ret = (log->logger->read)(log, flags ? flags : &mflags); |
|
7478
3c21f3084ff0
[gaim-migrate @ 8091]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7473
diff
changeset
|
79 gaim_str_strip_cr(ret); |
| 7462 | 80 return ret; |
| 81 } | |
| 7470 | 82 return (_("<b><font color=\"red\">The logger has no read function</font></b>")); |
| 4184 | 83 } |
| 7616 | 84 |
| 7556 | 85 int gaim_log_get_size(GaimLog *log) |
| 86 { | |
| 87 g_return_val_if_fail(log && log->logger, 0); | |
| 88 if (log->logger->size) | |
| 89 return log->logger->size(log); | |
| 90 return 0; | |
| 91 } | |
| 92 | |
| 93 int gaim_log_get_total_size(const char *name, GaimAccount *account) | |
| 94 { | |
| 95 GList *logs = gaim_log_get_logs(name, account); | |
| 96 int size = 0; | |
| 7616 | 97 |
| 98 | |
| 7556 | 99 while (logs) { |
| 100 GList *logs2 = logs->next; | |
| 101 GaimLog *log = (GaimLog*)(logs->data); | |
| 102 size += gaim_log_get_size(log); | |
| 7685 | 103 gaim_log_free(log); |
| 7556 | 104 g_list_free_1(logs); |
| 105 logs = logs2; | |
| 106 } | |
| 7616 | 107 |
| 7556 | 108 return size; |
| 109 } | |
| 4184 | 110 |
| 7431 | 111 /**************************************************************************** |
| 112 * LOGGER FUNCTIONS ********************************************************* | |
| 113 ****************************************************************************/ | |
| 4184 | 114 |
| 7431 | 115 static GaimLogLogger *current_logger = NULL; |
| 116 static GSList *loggers = NULL; | |
| 7436 | 117 |
| 7431 | 118 static void logger_pref_cb(const char *name, GaimPrefType type, |
| 119 gpointer value, gpointer data) | |
| 120 { | |
| 121 GaimLogLogger *logger; | |
| 122 GSList *l = loggers; | |
| 123 while (l) { | |
| 124 logger = l->data; | |
| 125 if (!strcmp(logger->id, value)) { | |
| 126 gaim_log_logger_set(logger); | |
| 127 return; | |
| 4184 | 128 } |
| 7431 | 129 l = l->next; |
| 130 } | |
| 131 gaim_log_logger_set(&txt_logger); | |
| 132 } | |
| 4184 | 133 |
| 134 | |
| 7440 | 135 GaimLogLogger *gaim_log_logger_new(void(*create)(GaimLog *), |
| 7436 | 136 void(*write)(GaimLog *, GaimMessageFlags, const char *, |
| 7431 | 137 time_t, const char *), |
| 138 void(*finalize)(GaimLog *), GList*(*list)(const char*, GaimAccount*), | |
| 7556 | 139 char*(*read)(GaimLog*, GaimLogReadFlags*), |
| 140 int(*size)(GaimLog*)) | |
| 7431 | 141 { |
| 142 GaimLogLogger *logger = g_new0(GaimLogLogger, 1); | |
| 7440 | 143 logger->create = create; |
| 7431 | 144 logger->write = write; |
| 145 logger->finalize = finalize; | |
| 146 logger->list = list; | |
| 147 logger->read = read; | |
| 7556 | 148 logger->size = size; |
| 7431 | 149 return logger; |
| 4184 | 150 } |
| 151 | |
| 7431 | 152 void gaim_log_logger_free(GaimLogLogger *logger) |
| 4184 | 153 { |
| 7431 | 154 g_free(logger); |
| 155 } | |
| 4184 | 156 |
| 7431 | 157 void gaim_log_logger_add (GaimLogLogger *logger) |
| 158 { | |
| 159 g_return_if_fail(logger); | |
| 160 if (g_slist_find(loggers, logger)) | |
| 161 return; | |
| 162 loggers = g_slist_append(loggers, logger); | |
| 163 } | |
| 164 | |
| 165 void gaim_log_logger_remove (GaimLogLogger *logger) | |
| 166 { | |
| 167 g_return_if_fail(logger); | |
| 168 g_slist_remove(loggers, logger); | |
| 4184 | 169 } |
| 170 | |
| 7431 | 171 void gaim_log_logger_set (GaimLogLogger *logger) |
| 4184 | 172 { |
| 7431 | 173 g_return_if_fail(logger); |
| 174 current_logger = logger; | |
| 7436 | 175 } |
| 4184 | 176 |
| 7431 | 177 GaimLogLogger *gaim_log_logger_get() |
| 178 { | |
| 179 return current_logger; | |
| 180 } | |
| 4184 | 181 |
| 7431 | 182 GList *gaim_log_logger_get_options(void) |
| 183 { | |
| 184 GSList *n; | |
| 185 GList *list = NULL; | |
| 186 GaimLogLogger *data; | |
| 4184 | 187 |
| 7431 | 188 for (n = loggers; n; n = n->next) { |
| 189 data = n->data; | |
| 190 if (!data->write) | |
| 191 continue; | |
| 7494 | 192 list = g_list_append(list, _(data->name)); |
| 7431 | 193 list = g_list_append(list, data->id); |
| 4184 | 194 } |
| 195 | |
| 7431 | 196 return list; |
| 197 } | |
| 198 | |
| 7436 | 199 static gint log_compare(gconstpointer y, gconstpointer z) |
| 7431 | 200 { |
| 7436 | 201 const GaimLog *a = y; |
| 202 const GaimLog *b = z; | |
| 203 | |
| 7431 | 204 return b->time - a->time; |
| 205 } | |
| 206 | |
| 207 GList *gaim_log_get_logs(const char *name, GaimAccount *account) | |
| 208 { | |
| 209 GList *logs = NULL; | |
| 210 GSList *n; | |
| 211 for (n = loggers; n; n = n->next) { | |
| 212 GaimLogLogger *logger = n->data; | |
| 213 if (!logger->list) | |
| 214 continue; | |
| 215 logs = g_list_concat(logs, logger->list(name, account)); | |
| 216 } | |
| 7436 | 217 |
| 7431 | 218 return g_list_sort(logs, log_compare); |
| 219 } | |
| 220 | |
| 221 void gaim_log_init(void) | |
| 7436 | 222 { |
| 7431 | 223 gaim_prefs_add_none("/core/logging"); |
| 7555 | 224 gaim_prefs_add_bool("/core/logging/log_ims", FALSE); |
| 225 gaim_prefs_add_bool("/core/logging/log_chats", FALSE); | |
| 7431 | 226 gaim_prefs_add_string("/core/logging/format", "txt"); |
| 7457 | 227 gaim_log_logger_add(&html_logger); |
| 7431 | 228 gaim_log_logger_add(&txt_logger); |
| 229 gaim_log_logger_add(&old_logger); | |
| 230 gaim_prefs_connect_callback("/core/logging/format", | |
| 231 logger_pref_cb, NULL); | |
| 232 gaim_prefs_trigger_callback("/core/logging/format"); | |
| 233 } | |
| 234 | |
| 235 /**************************************************************************** | |
| 236 * LOGGERS ****************************************************************** | |
| 237 ****************************************************************************/ | |
| 238 | |
| 7616 | 239 struct generic_logger_data { |
| 240 char *path; | |
| 241 FILE *file; | |
| 242 }; | |
| 243 | |
| 7431 | 244 static GList *log_lister_common(const char *screenname, GaimAccount *account, const char *ext, GaimLogLogger *logger) |
| 245 { | |
| 246 GDir *dir; | |
| 247 GList *list = NULL; | |
| 7628 | 248 const char *filename; |
| 7431 | 249 char *me = g_strdup(gaim_normalize(account, gaim_account_get_username(account))); |
| 4184 | 250 |
| 7431 | 251 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
| 252 (gaim_find_prpl(gaim_account_get_protocol(account)))->list_icon(account, NULL); | |
| 253 char *path = g_build_filename(gaim_user_dir(), "logs", prpl, me, gaim_normalize(account, screenname), NULL); | |
| 254 | |
| 7447 | 255 g_free(me); |
| 256 | |
| 7431 | 257 if (!(dir = g_dir_open(path, 0, NULL))) { |
| 258 g_free(path); | |
| 259 return NULL; | |
| 260 } | |
| 261 while ((filename = g_dir_read_name(dir))) { | |
| 7628 | 262 if (gaim_str_has_suffix(filename, ext)) { |
| 7431 | 263 const char *l = filename; |
| 264 struct tm time; | |
| 265 GaimLog *log; | |
| 7616 | 266 struct generic_logger_data *data; |
| 7431 | 267 char d[5]; |
| 7436 | 268 |
| 7431 | 269 strncpy(d, l, 4); |
| 270 d[4] = '\0'; | |
| 271 time.tm_year = atoi(d) - 1900; | |
| 272 l = l + 5; | |
| 273 | |
| 274 strncpy(d, l, 2); | |
| 275 d[2] = '\0'; | |
| 276 time.tm_mon = atoi(d) - 1; | |
| 277 l = l + 3; | |
| 278 | |
| 279 strncpy(d, l, 2); | |
| 280 time.tm_mday = atoi(d); | |
| 281 l = l + 3; | |
| 282 | |
| 283 strncpy(d, l, 2); | |
| 284 time.tm_hour = atoi(d); | |
| 285 l = l + 2; | |
| 7436 | 286 |
| 7431 | 287 strncpy(d, l, 2); |
| 288 time.tm_min = atoi(d); | |
| 289 l = l + 2; | |
| 290 | |
| 291 strncpy(d, l, 2); | |
| 292 time.tm_sec = atoi(d); | |
| 293 l = l + 2; | |
| 294 log = gaim_log_new(GAIM_LOG_IM, screenname, account, mktime(&time)); | |
| 295 log->logger = logger; | |
| 7616 | 296 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
| 297 data->path = g_build_filename(path, filename, NULL); | |
| 7431 | 298 list = g_list_append(list, log); |
| 4184 | 299 } |
| 300 } | |
| 7431 | 301 g_dir_close(dir); |
| 7447 | 302 g_free(path); |
| 7431 | 303 return list; |
| 304 } | |
| 4184 | 305 |
| 7556 | 306 /* Only to be used with logs listed from log_lister_common */ |
| 7616 | 307 int log_sizer_common(GaimLog *log) |
| 7556 | 308 { |
| 309 struct stat st; | |
| 7616 | 310 struct generic_logger_data *data = log->logger_data; |
| 7556 | 311 |
| 7616 | 312 if (!data->path || stat(data->path, &st)) |
| 7556 | 313 st.st_size = 0; |
| 314 | |
| 315 return st.st_size; | |
| 316 } | |
| 317 | |
| 7431 | 318 #if 0 /* Maybe some other time. */ |
| 7443 | 319 /**************** |
| 7431 | 320 ** XML LOGGER ** |
| 321 ****************/ | |
| 322 | |
| 323 static const char *str_from_msg_type (GaimMessageFlags type) | |
| 324 { | |
| 7443 | 325 |
| 7431 | 326 return ""; |
| 7443 | 327 |
| 7431 | 328 } |
| 329 | |
| 7443 | 330 static void xml_logger_write(GaimLog *log, |
| 331 GaimMessageFlags type, | |
| 7431 | 332 const char *from, time_t time, const char *message) |
| 333 { | |
| 334 char date[64]; | |
| 335 char *xhtml = NULL; | |
| 336 if (!log->logger_data) { | |
| 337 /* This log is new. We could use the loggers 'new' function, but | |
| 338 * creating a new file there would result in empty files in the case | |
| 339 * that you open a convo with someone, but don't say anything. | |
| 340 */ | |
| 341 char *ud = gaim_user_dir(); | |
| 342 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); | |
| 343 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO | |
| 344 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
| 345 char *dir; | |
| 346 FILE *file; | |
| 347 | |
| 7453 | 348 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); |
| 7443 | 349 |
| 350 dir = g_build_filename(ud, "logs", | |
| 7431 | 351 prpl, guy, gaim_normalize(log->account, log->name), NULL); |
| 7612 | 352 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
| 7447 | 353 g_free(guy); |
| 7443 | 354 |
| 7431 | 355 char *filename = g_build_filename(dir, date, NULL); |
| 356 g_free(dir); | |
| 7443 | 357 |
| 7431 | 358 log->logger_data = fopen(filename, "a"); |
| 359 if (!log->logger_data) { | |
| 360 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); | |
| 7564 | 361 g_free(filename); |
| 7431 | 362 return; |
| 363 } | |
| 7564 | 364 g_free(filename); |
| 7431 | 365 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" |
| 366 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); | |
| 7443 | 367 |
| 7453 | 368 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
| 7431 | 369 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", |
| 370 date, log->name, prpl); | |
| 371 } | |
| 7443 | 372 |
| 7453 | 373 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
| 7431 | 374 gaim_markup_html_to_xhtml(message, &xhtml, NULL); |
| 375 if (from) | |
| 7443 | 376 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", |
| 377 str_from_msg_type(type), | |
| 7431 | 378 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
| 379 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
| 380 from, date, xhtml); | |
| 381 else | |
| 7443 | 382 fprintf(log->logger_data, "<message %s %s time='%s'>%s</message>\n", |
| 383 str_from_msg_type(type), | |
| 7431 | 384 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
| 385 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
| 7443 | 386 date, xhtml): |
| 7431 | 387 fflush(log->logger_data); |
| 388 g_free(xhtml); | |
| 7443 | 389 } |
| 390 | |
| 7431 | 391 static void xml_logger_finalize(GaimLog *log) |
| 392 { | |
| 393 if (log->logger_data) { | |
| 394 fprintf(log->logger_data, "</conversation>\n"); | |
| 395 fclose(log->logger_data); | |
| 396 log->logger_data = NULL; | |
| 397 } | |
| 398 } | |
| 7443 | 399 |
| 7431 | 400 static GList *xml_logger_list(const char *sn, GaimAccount *account) |
| 401 { | |
| 402 return log_lister_common(sn, account, ".xml", &xml_logger); | |
| 4184 | 403 } |
| 404 | |
| 7431 | 405 static GaimLogLogger xml_logger = { |
| 406 N_("XML"), "xml", | |
| 407 NULL, | |
| 408 xml_logger_write, | |
| 409 xml_logger_finalize, | |
| 410 xml_logger_list, | |
| 411 NULL | |
| 412 }; | |
| 413 #endif | |
|
5563
9eb5b13fd412
[gaim-migrate @ 5965]
Christian Hammond <chipx86@chipx86.com>
parents:
5560
diff
changeset
|
414 |
| 7431 | 415 /**************************** |
| 7457 | 416 ** HTML LOGGER ************* |
| 417 ****************************/ | |
| 418 | |
| 419 static void html_logger_write(GaimLog *log, GaimMessageFlags type, | |
| 420 const char *from, time_t time, const char *message) | |
| 421 { | |
| 7489 | 422 GaimConnection *gc = gaim_account_get_connection(log->account); |
| 7457 | 423 char date[64]; |
| 7616 | 424 struct generic_logger_data *data = log->logger_data; |
| 7618 | 425 if(!data) { |
| 7457 | 426 /* This log is new */ |
| 427 char *ud = gaim_user_dir(); | |
| 428 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); | |
| 7553 | 429 char *chat; |
| 7457 | 430 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
| 431 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
| 432 char *dir; | |
| 433 char *filename; | |
| 434 | |
| 7553 | 435 if (log->type == GAIM_LOG_CHAT) { |
| 436 chat = g_strdup_printf("%s.chat", guy); | |
| 437 g_free(guy); | |
| 438 guy = chat; | |
| 439 } | |
| 440 | |
| 7457 | 441 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.html", localtime(&log->time)); |
| 442 | |
| 443 dir = g_build_filename(ud, "logs", | |
| 444 prpl, guy, gaim_normalize(log->account, log->name), NULL); | |
| 7612 | 445 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
| 7457 | 446 g_free(guy); |
| 447 | |
| 448 filename = g_build_filename(dir, date, NULL); | |
| 449 g_free(dir); | |
| 450 | |
| 7616 | 451 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
| 452 | |
| 453 data->file = fopen(filename, "a"); | |
| 454 if (!data->file) { | |
| 7623 | 455 gaim_debug(GAIM_DEBUG_ERROR, "log", |
| 456 "Could not create log file %s\n", filename); | |
| 7564 | 457 g_free(filename); |
| 7457 | 458 return; |
| 459 } | |
| 460 g_free(filename); | |
| 461 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); | |
| 7616 | 462 fprintf(data->file, "<html><head><title>"); |
| 463 fprintf(data->file, "Conversation with %s at %s on %s (%s)", | |
| 7457 | 464 log->name, date, gaim_account_get_username(log->account), prpl); |
| 7616 | 465 fprintf(data->file, "</title></head><body>"); |
| 466 fprintf(data->file, | |
| 7457 | 467 "<h3>Conversation with %s at %s on %s (%s)</h3>\n", |
| 468 log->name, date, gaim_account_get_username(log->account), prpl); | |
| 469 } | |
| 7623 | 470 |
| 471 /* if we can't write to the file, give up before we hurt ourselves */ | |
| 472 if(!data->file) | |
| 473 return; | |
| 474 | |
| 7457 | 475 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
| 7489 | 476 if (type & GAIM_MESSAGE_SYSTEM) |
| 7616 | 477 fprintf(data->file, "(%s)<b> %s</b><br/>\n", date, message); |
| 7489 | 478 else if (type & GAIM_MESSAGE_WHISPER) |
| 7616 | 479 fprintf(data->file, "<font color=\"#6C2585\">(%s)<b> %s:</b></font> %s<br/>\n", |
| 7489 | 480 date, from, message); |
| 481 else if (type & GAIM_MESSAGE_AUTO_RESP) { | |
| 482 if (type & GAIM_MESSAGE_SEND) | |
| 7616 | 483 fprintf(data->file, _("<font color=\"#16569E\">(%s) <b>%s <AUTO-REPLY>:</b></font> %s<br/>\n"), date, from, message); |
| 7489 | 484 else if (type & GAIM_MESSAGE_RECV) |
| 7616 | 485 fprintf(data->file, _("<font color=\"#A82F2F\">(%s) <b>%s <AUTO-REPLY>:</b></font> %s<br/>\n"), date, from, message); |
| 7564 | 486 } else if (type & GAIM_MESSAGE_RECV) { |
| 487 char *msg = g_strdup(message); | |
| 488 if(gaim_message_meify(msg, -1)) | |
| 7616 | 489 fprintf(data->file, "<font color=\"#6C2585\">(%s) <b>***%s</b></font> <font sml=\"%s\">%s</font><br/>\n", |
| 7564 | 490 date, from, gc->prpl->info->name, msg); |
| 491 else | |
| 7616 | 492 fprintf(data->file, "<font color=\"#A82F2F\">(%s) <b>%s:</b></font> <font sml=\"%s\">%s</font><br/>\n", |
| 7564 | 493 date, from, gc->prpl->info->name, msg); |
| 494 g_free(msg); | |
| 495 } else if (type & GAIM_MESSAGE_SEND) { | |
| 496 char *msg = g_strdup(message); | |
| 497 if(gaim_message_meify(msg, -1)) | |
| 7616 | 498 fprintf(data->file, "<font color=\"#6C2585\">(%s) <b>***%s</b></font> <font sml=\"%s\">%s</font><br/>\n", |
| 7564 | 499 date, from, gc->prpl->info->name, msg); |
| 500 else | |
| 7616 | 501 fprintf(data->file, "<font color=\"#16569E\">(%s) <b>%s:</b></font> <font sml=\"%s\">%s</font><br/>\n", |
| 7564 | 502 date, from, gc->prpl->info->name, msg); |
| 503 g_free(msg); | |
| 504 } | |
| 7616 | 505 fflush(data->file); |
| 7457 | 506 } |
| 507 | |
| 508 static void html_logger_finalize(GaimLog *log) | |
| 509 { | |
| 7616 | 510 struct generic_logger_data *data = log->logger_data; |
| 511 if (data) { | |
| 512 if(data->file) { | |
| 513 fprintf(data->file, "</body></html>"); | |
| 514 fclose(data->file); | |
| 515 } | |
| 516 g_free(data->path); | |
| 7463 | 517 } |
| 7457 | 518 } |
| 519 | |
| 520 static GList *html_logger_list(const char *sn, GaimAccount *account) | |
| 521 { | |
| 522 return log_lister_common(sn, account, ".html", &html_logger); | |
| 523 } | |
| 524 | |
| 525 static char *html_logger_read(GaimLog *log, GaimLogReadFlags *flags) | |
| 526 { | |
| 527 char *read, *minus_header; | |
| 7616 | 528 struct generic_logger_data *data = log->logger_data; |
| 7457 | 529 *flags = GAIM_LOG_READ_NO_NEWLINE; |
| 7616 | 530 if (!data || !data->path) |
| 531 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
| 532 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
| 7457 | 533 minus_header = strchr(read, '\n'); |
| 534 if (!minus_header) | |
| 535 minus_header = g_strdup(read); | |
| 536 else | |
| 537 minus_header = g_strdup(minus_header + 1); | |
| 538 g_free(read); | |
| 539 return minus_header; | |
| 540 } | |
| 7471 | 541 return g_strdup(_("<font color=\"red\"><b>Could not read file: %s</b></font>")); |
| 7457 | 542 } |
| 543 | |
| 544 static GaimLogLogger html_logger = { | |
| 545 N_("HTML"), "html", | |
| 546 NULL, | |
| 547 html_logger_write, | |
| 548 html_logger_finalize, | |
| 549 html_logger_list, | |
| 7556 | 550 html_logger_read, |
| 551 log_sizer_common | |
| 7457 | 552 }; |
| 553 | |
| 554 | |
| 555 | |
| 556 | |
| 557 /**************************** | |
| 7431 | 558 ** PLAIN TEXT LOGGER ******* |
| 559 ****************************/ | |
| 4184 | 560 |
| 7436 | 561 static void txt_logger_write(GaimLog *log, |
| 562 GaimMessageFlags type, | |
| 7431 | 563 const char *from, time_t time, const char *message) |
| 564 { | |
| 565 char date[64]; | |
| 566 char *stripped = NULL; | |
| 7616 | 567 struct generic_logger_data *data = log->logger_data; |
| 568 if (!data) { | |
| 7431 | 569 /* This log is new. We could use the loggers 'new' function, but |
| 570 * creating a new file there would result in empty files in the case | |
| 571 * that you open a convo with someone, but don't say anything. | |
| 572 */ | |
| 573 char *ud = gaim_user_dir(); | |
| 7473 | 574 char *filename; |
| 7431 | 575 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); |
| 7553 | 576 char *chat; |
| 7431 | 577 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
| 578 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
| 579 char *dir; | |
| 7436 | 580 |
| 7553 | 581 if (log->type == GAIM_LOG_CHAT) { |
| 582 chat = g_strdup_printf("%s.chat", guy); | |
| 583 g_free(guy); | |
| 584 guy = chat; | |
| 585 } | |
| 7453 | 586 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.txt", localtime(&log->time)); |
| 7436 | 587 |
| 588 dir = g_build_filename(ud, "logs", | |
| 7431 | 589 prpl, guy, gaim_normalize(log->account, log->name), NULL); |
| 7612 | 590 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
| 7447 | 591 g_free(guy); |
| 7436 | 592 |
| 7473 | 593 filename = g_build_filename(dir, date, NULL); |
| 7431 | 594 g_free(dir); |
| 7436 | 595 |
| 7616 | 596 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
| 597 | |
| 598 data->file = fopen(filename, "a"); | |
| 599 if (!data->file) { | |
| 7431 | 600 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); |
| 7564 | 601 g_free(filename); |
| 7431 | 602 return; |
| 4184 | 603 } |
| 7447 | 604 g_free(filename); |
| 7453 | 605 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
| 7616 | 606 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", |
| 7431 | 607 log->name, date, gaim_account_get_username(log->account), prpl); |
| 608 } | |
| 7436 | 609 |
| 7623 | 610 /* if we can't write to the file, give up before we hurt ourselves */ |
| 611 if(!data->file) | |
| 612 return; | |
| 613 | |
| 7453 | 614 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
| 7431 | 615 stripped = gaim_markup_strip_html(message); |
| 7489 | 616 if (type & GAIM_MESSAGE_SEND || |
| 7541 | 617 type & GAIM_MESSAGE_RECV) { |
| 7564 | 618 if (type & GAIM_MESSAGE_AUTO_RESP) { |
| 7616 | 619 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date, from, stripped); |
| 7564 | 620 } else { |
| 621 if(gaim_message_meify(stripped, -1)) | |
| 7616 | 622 fprintf(data->file, "(%s) ***%s %s\n", date, from, |
| 7564 | 623 stripped); |
| 624 else | |
| 7616 | 625 fprintf(data->file, "(%s) %s: %s\n", date, from, |
| 7564 | 626 stripped); |
| 627 } | |
| 628 } else if (type & GAIM_MESSAGE_SYSTEM) | |
| 7616 | 629 fprintf(data->file, "(%s) %s\n", date, stripped); |
| 7489 | 630 else if (type & GAIM_MESSAGE_NO_LOG) { |
| 631 /* This shouldn't happen */ | |
| 632 g_free(stripped); | |
| 633 return; | |
| 634 } else if (type & GAIM_MESSAGE_WHISPER) | |
| 7616 | 635 fprintf(data->file, "(%s) *%s* %s", date, from, stripped); |
| 7489 | 636 else |
| 7616 | 637 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "", from ? ":" : "", stripped); |
| 7489 | 638 |
| 7616 | 639 fflush(data->file); |
| 7431 | 640 g_free(stripped); |
| 641 } | |
| 642 | |
| 643 static void txt_logger_finalize(GaimLog *log) | |
| 644 { | |
| 7616 | 645 struct generic_logger_data *data = log->logger_data; |
| 646 if (data) { | |
| 647 if(data->file) | |
| 648 fclose(data->file); | |
| 649 if(data->path) | |
| 650 g_free(data->path); | |
| 651 } | |
| 7431 | 652 } |
| 653 | |
| 654 static GList *txt_logger_list(const char *sn, GaimAccount *account) | |
| 655 { | |
| 656 return log_lister_common(sn, account, ".txt", &txt_logger); | |
| 657 } | |
| 658 | |
| 659 static char *txt_logger_read(GaimLog *log, GaimLogReadFlags *flags) | |
| 660 { | |
| 661 char *read, *minus_header; | |
| 7616 | 662 struct generic_logger_data *data = log->logger_data; |
| 7457 | 663 *flags = 0; |
| 7616 | 664 if (!data || !data->path) |
| 665 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
| 666 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
| 7431 | 667 minus_header = strchr(read, '\n'); |
| 668 if (!minus_header) | |
| 669 minus_header = g_strdup(read); | |
| 7436 | 670 else |
| 7431 | 671 minus_header = g_strdup(minus_header + 1); |
| 672 g_free(read); | |
| 673 return minus_header; | |
| 674 } | |
| 7471 | 675 return g_strdup(_("<font color=\"red\"><b>Could not read file: %s</b></font>")); |
| 7436 | 676 } |
| 7431 | 677 |
| 678 static GaimLogLogger txt_logger = { | |
| 679 N_("Plain text"), "txt", | |
| 680 NULL, | |
| 681 txt_logger_write, | |
| 682 txt_logger_finalize, | |
| 683 txt_logger_list, | |
| 7556 | 684 txt_logger_read, |
| 685 log_sizer_common | |
| 7431 | 686 }; |
| 687 | |
| 688 /**************** | |
| 689 * OLD LOGGER *** | |
| 690 ****************/ | |
| 691 | |
| 692 /* The old logger doesn't write logs, only reads them. This is to include | |
| 693 * old logs in the log viewer transparently. | |
| 694 */ | |
| 695 | |
| 696 struct old_logger_data { | |
| 697 char *path; | |
| 698 int offset; | |
| 699 int length; | |
| 700 }; | |
| 701 | |
| 7436 | 702 static GList *old_logger_list(const char *sn, GaimAccount *account) |
| 7431 | 703 { |
| 704 FILE *file; | |
| 705 char buf[BUF_LONG]; | |
| 706 struct tm tm; | |
| 707 struct old_logger_data *data = NULL; | |
| 7676 | 708 char month[4]; |
| 7431 | 709 char *logfile = g_strdup_printf("%s.log", gaim_normalize(account, sn)); |
| 710 char *path = g_build_filename(gaim_user_dir(), "logs", logfile, NULL); | |
| 711 char *newlog; | |
| 712 | |
| 713 GaimLog *log = NULL; | |
| 714 GList *list = NULL; | |
| 715 | |
| 7473 | 716 g_free(logfile); |
| 717 | |
| 7461 | 718 if (!(file = fopen(path, "rb"))) { |
| 7447 | 719 g_free(path); |
| 7431 | 720 return NULL; |
| 7447 | 721 } |
| 7436 | 722 |
| 7431 | 723 while (fgets(buf, BUF_LONG, file)) { |
| 724 if ((newlog = strstr(buf, "---- New C"))) { | |
| 725 int length; | |
| 726 int offset; | |
| 727 char convostart[32]; | |
| 728 char *temp = strchr(buf, '@'); | |
| 7436 | 729 |
| 7431 | 730 if (temp == NULL || strlen(temp) < 2) |
| 731 continue; | |
| 7436 | 732 |
| 7431 | 733 temp++; |
| 734 length = strcspn(temp, "-"); | |
| 735 if (length > 31) length = 31; | |
| 7436 | 736 |
| 7431 | 737 offset = ftell(file); |
| 7436 | 738 |
| 7431 | 739 if (data) { |
| 7436 | 740 data->length = offset - data->offset - length; |
| 741 if(strstr(buf, "----</H3><BR>")) { | |
| 742 data->length -= | |
| 743 strlen("<HR><BR><H3 Align=Center> ---- New Conversation @ ") + | |
| 744 strlen("----</H3><BR>"); | |
| 745 } else { | |
| 746 data->length -= | |
| 747 strlen("---- New Conversation @ ") + strlen("----"); | |
| 748 } | |
| 749 | |
| 7461 | 750 if(strchr(buf, '\r')) |
| 751 data->length--; | |
| 752 | |
| 7431 | 753 if (data->length != 0) |
| 754 list = g_list_append(list, log); | |
| 755 else | |
| 756 gaim_log_free(log); | |
| 757 } | |
| 758 | |
| 759 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
| 760 log->logger = &old_logger; | |
| 761 | |
| 7436 | 762 data = g_new0(struct old_logger_data, 1); |
| 7431 | 763 data->offset = offset; |
| 7616 | 764 data->path = g_strdup(path); |
| 7431 | 765 log->logger_data = data; |
| 766 | |
| 7436 | 767 |
| 7431 | 768 g_snprintf(convostart, length, "%s", temp); |
| 7676 | 769 sscanf(convostart, "%*s %s %d %d:%d:%d %d", |
| 770 month, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &tm.tm_year); | |
| 771 /* Ugly hack, in case current locale is not English */ | |
| 772 if (strcmp(month, "Jan") == 0) { | |
| 773 tm.tm_mon= 0; | |
| 774 } else if (strcmp(month, "Feb") == 0) { | |
| 775 tm.tm_mon = 1; | |
| 776 } else if (strcmp(month, "Mar") == 0) { | |
| 777 tm.tm_mon = 2; | |
| 778 } else if (strcmp(month, "Apr") == 0) { | |
| 779 tm.tm_mon = 3; | |
| 780 } else if (strcmp(month, "May") == 0) { | |
| 781 tm.tm_mon = 4; | |
| 782 } else if (strcmp(month, "Jun") == 0) { | |
| 783 tm.tm_mon = 5; | |
| 784 } else if (strcmp(month, "Jul") == 0) { | |
| 785 tm.tm_mon = 6; | |
| 786 } else if (strcmp(month, "Aug") == 0) { | |
| 787 tm.tm_mon = 7; | |
| 788 } else if (strcmp(month, "Sep") == 0) { | |
| 789 tm.tm_mon = 8; | |
| 790 } else if (strcmp(month, "Oct") == 0) { | |
| 791 tm.tm_mon = 9; | |
| 792 } else if (strcmp(month, "Nov") == 0) { | |
| 793 tm.tm_mon = 10; | |
| 794 } else if (strcmp(month, "Dec") == 0) { | |
| 795 tm.tm_mon = 11; | |
| 796 } | |
| 797 tm.tm_year -= 1900; | |
| 7431 | 798 log->time = mktime(&tm); |
| 4184 | 799 } |
| 800 } | |
| 7613 | 801 |
| 802 if (data) { | |
| 803 data->length = ftell(file) - data->offset; | |
| 804 if (data->length != 0) | |
| 805 list = g_list_append(list, log); | |
| 806 else | |
| 807 gaim_log_free(log); | |
| 808 } | |
| 809 | |
| 7616 | 810 g_free(path); |
| 7431 | 811 fclose(file); |
| 812 return list; | |
| 4184 | 813 } |
|
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
814 |
| 7616 | 815 static char * old_logger_read (GaimLog *log, GaimLogReadFlags *flags) |
|
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
816 { |
| 7431 | 817 struct old_logger_data *data = log->logger_data; |
| 7461 | 818 FILE *file = fopen(data->path, "rb"); |
| 7431 | 819 char *read = g_malloc(data->length + 1); |
| 820 fseek(file, data->offset, SEEK_SET); | |
| 821 fread(read, data->length, 1, file); | |
| 822 read[data->length] = '\0'; | |
| 7436 | 823 *flags = 0; |
| 824 if(strstr(read, "<BR>")) | |
| 825 *flags |= GAIM_LOG_READ_NO_NEWLINE; | |
| 7431 | 826 return read; |
| 827 } | |
|
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
828 |
| 7616 | 829 static int old_logger_size (GaimLog *log) |
| 7556 | 830 { |
| 831 struct old_logger_data *data = log->logger_data; | |
| 7616 | 832 return data ? data->length : 0; |
| 833 } | |
| 834 | |
| 835 static void old_logger_finalize(GaimLog *log) | |
| 836 { | |
| 837 struct old_logger_data *data = log->logger_data; | |
| 838 g_free(data->path); | |
| 839 g_free(data); | |
| 7556 | 840 } |
| 841 | |
| 7431 | 842 static GaimLogLogger old_logger = { |
| 843 "old logger", "old", | |
| 7616 | 844 NULL, NULL, |
| 845 old_logger_finalize, | |
| 7431 | 846 old_logger_list, |
| 7616 | 847 old_logger_read, |
| 848 old_logger_size | |
| 7431 | 849 }; |
