Mercurial > pidgin
annotate src/log.c @ 7665:0351ff7030d0
[gaim-migrate @ 8309]
Felipe Contreras (aka revo aka shx) writes:
" Basically that, currently gaim will not display
international "subjects" or "from" fields from emails,
like "a??a" or "Pa?l".
This implements the propper RFC that specify the format
for those fields."
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Sun, 30 Nov 2003 04:17:17 +0000 |
parents | e293d0c42ccb |
children | 5c5acdf8b982 |
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); | |
103 g_free(log->name); | |
104 g_free(log); | |
105 g_list_free_1(logs); | |
106 logs = logs2; | |
107 } | |
7616 | 108 |
7556 | 109 return size; |
110 } | |
4184 | 111 |
7431 | 112 /**************************************************************************** |
113 * LOGGER FUNCTIONS ********************************************************* | |
114 ****************************************************************************/ | |
4184 | 115 |
7431 | 116 static GaimLogLogger *current_logger = NULL; |
117 static GSList *loggers = NULL; | |
7436 | 118 |
7431 | 119 static void logger_pref_cb(const char *name, GaimPrefType type, |
120 gpointer value, gpointer data) | |
121 { | |
122 GaimLogLogger *logger; | |
123 GSList *l = loggers; | |
124 while (l) { | |
125 logger = l->data; | |
126 if (!strcmp(logger->id, value)) { | |
127 gaim_log_logger_set(logger); | |
128 return; | |
4184 | 129 } |
7431 | 130 l = l->next; |
131 } | |
132 gaim_log_logger_set(&txt_logger); | |
133 } | |
4184 | 134 |
135 | |
7440 | 136 GaimLogLogger *gaim_log_logger_new(void(*create)(GaimLog *), |
7436 | 137 void(*write)(GaimLog *, GaimMessageFlags, const char *, |
7431 | 138 time_t, const char *), |
139 void(*finalize)(GaimLog *), GList*(*list)(const char*, GaimAccount*), | |
7556 | 140 char*(*read)(GaimLog*, GaimLogReadFlags*), |
141 int(*size)(GaimLog*)) | |
7431 | 142 { |
143 GaimLogLogger *logger = g_new0(GaimLogLogger, 1); | |
7440 | 144 logger->create = create; |
7431 | 145 logger->write = write; |
146 logger->finalize = finalize; | |
147 logger->list = list; | |
148 logger->read = read; | |
7556 | 149 logger->size = size; |
7431 | 150 return logger; |
4184 | 151 } |
152 | |
7431 | 153 void gaim_log_logger_free(GaimLogLogger *logger) |
4184 | 154 { |
7431 | 155 g_free(logger); |
156 } | |
4184 | 157 |
7431 | 158 void gaim_log_logger_add (GaimLogLogger *logger) |
159 { | |
160 g_return_if_fail(logger); | |
161 if (g_slist_find(loggers, logger)) | |
162 return; | |
163 loggers = g_slist_append(loggers, logger); | |
164 } | |
165 | |
166 void gaim_log_logger_remove (GaimLogLogger *logger) | |
167 { | |
168 g_return_if_fail(logger); | |
169 g_slist_remove(loggers, logger); | |
4184 | 170 } |
171 | |
7431 | 172 void gaim_log_logger_set (GaimLogLogger *logger) |
4184 | 173 { |
7431 | 174 g_return_if_fail(logger); |
175 current_logger = logger; | |
7436 | 176 } |
4184 | 177 |
7431 | 178 GaimLogLogger *gaim_log_logger_get() |
179 { | |
180 return current_logger; | |
181 } | |
4184 | 182 |
7431 | 183 GList *gaim_log_logger_get_options(void) |
184 { | |
185 GSList *n; | |
186 GList *list = NULL; | |
187 GaimLogLogger *data; | |
4184 | 188 |
7431 | 189 for (n = loggers; n; n = n->next) { |
190 data = n->data; | |
191 if (!data->write) | |
192 continue; | |
7494 | 193 list = g_list_append(list, _(data->name)); |
7431 | 194 list = g_list_append(list, data->id); |
4184 | 195 } |
196 | |
7431 | 197 return list; |
198 } | |
199 | |
7436 | 200 static gint log_compare(gconstpointer y, gconstpointer z) |
7431 | 201 { |
7436 | 202 const GaimLog *a = y; |
203 const GaimLog *b = z; | |
204 | |
7431 | 205 return b->time - a->time; |
206 } | |
207 | |
208 GList *gaim_log_get_logs(const char *name, GaimAccount *account) | |
209 { | |
210 GList *logs = NULL; | |
211 GSList *n; | |
212 for (n = loggers; n; n = n->next) { | |
213 GaimLogLogger *logger = n->data; | |
214 if (!logger->list) | |
215 continue; | |
216 logs = g_list_concat(logs, logger->list(name, account)); | |
217 } | |
7436 | 218 |
7431 | 219 return g_list_sort(logs, log_compare); |
220 } | |
221 | |
222 void gaim_log_init(void) | |
7436 | 223 { |
7431 | 224 gaim_prefs_add_none("/core/logging"); |
7555 | 225 gaim_prefs_add_bool("/core/logging/log_ims", FALSE); |
226 gaim_prefs_add_bool("/core/logging/log_chats", FALSE); | |
7431 | 227 gaim_prefs_add_string("/core/logging/format", "txt"); |
7457 | 228 gaim_log_logger_add(&html_logger); |
7431 | 229 gaim_log_logger_add(&txt_logger); |
230 gaim_log_logger_add(&old_logger); | |
231 gaim_prefs_connect_callback("/core/logging/format", | |
232 logger_pref_cb, NULL); | |
233 gaim_prefs_trigger_callback("/core/logging/format"); | |
234 } | |
235 | |
236 /**************************************************************************** | |
237 * LOGGERS ****************************************************************** | |
238 ****************************************************************************/ | |
239 | |
7616 | 240 struct generic_logger_data { |
241 char *path; | |
242 FILE *file; | |
243 }; | |
244 | |
7431 | 245 static GList *log_lister_common(const char *screenname, GaimAccount *account, const char *ext, GaimLogLogger *logger) |
246 { | |
247 GDir *dir; | |
248 GList *list = NULL; | |
7628 | 249 const char *filename; |
7431 | 250 char *me = g_strdup(gaim_normalize(account, gaim_account_get_username(account))); |
4184 | 251 |
7431 | 252 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
253 (gaim_find_prpl(gaim_account_get_protocol(account)))->list_icon(account, NULL); | |
254 char *path = g_build_filename(gaim_user_dir(), "logs", prpl, me, gaim_normalize(account, screenname), NULL); | |
255 | |
7447 | 256 g_free(me); |
257 | |
7431 | 258 if (!(dir = g_dir_open(path, 0, NULL))) { |
259 g_free(path); | |
260 return NULL; | |
261 } | |
262 while ((filename = g_dir_read_name(dir))) { | |
7628 | 263 if (gaim_str_has_suffix(filename, ext)) { |
7431 | 264 const char *l = filename; |
265 struct tm time; | |
266 GaimLog *log; | |
7616 | 267 struct generic_logger_data *data; |
7431 | 268 char d[5]; |
7436 | 269 |
7431 | 270 strncpy(d, l, 4); |
271 d[4] = '\0'; | |
272 time.tm_year = atoi(d) - 1900; | |
273 l = l + 5; | |
274 | |
275 strncpy(d, l, 2); | |
276 d[2] = '\0'; | |
277 time.tm_mon = atoi(d) - 1; | |
278 l = l + 3; | |
279 | |
280 strncpy(d, l, 2); | |
281 time.tm_mday = atoi(d); | |
282 l = l + 3; | |
283 | |
284 strncpy(d, l, 2); | |
285 time.tm_hour = atoi(d); | |
286 l = l + 2; | |
7436 | 287 |
7431 | 288 strncpy(d, l, 2); |
289 time.tm_min = atoi(d); | |
290 l = l + 2; | |
291 | |
292 strncpy(d, l, 2); | |
293 time.tm_sec = atoi(d); | |
294 l = l + 2; | |
295 log = gaim_log_new(GAIM_LOG_IM, screenname, account, mktime(&time)); | |
296 log->logger = logger; | |
7616 | 297 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
298 data->path = g_build_filename(path, filename, NULL); | |
7431 | 299 list = g_list_append(list, log); |
4184 | 300 } |
301 } | |
7431 | 302 g_dir_close(dir); |
7447 | 303 g_free(path); |
7431 | 304 return list; |
305 } | |
4184 | 306 |
7556 | 307 /* Only to be used with logs listed from log_lister_common */ |
7616 | 308 int log_sizer_common(GaimLog *log) |
7556 | 309 { |
310 struct stat st; | |
7616 | 311 struct generic_logger_data *data = log->logger_data; |
7556 | 312 |
7616 | 313 if (!data->path || stat(data->path, &st)) |
7556 | 314 st.st_size = 0; |
315 | |
316 return st.st_size; | |
317 } | |
318 | |
7431 | 319 #if 0 /* Maybe some other time. */ |
7443 | 320 /**************** |
7431 | 321 ** XML LOGGER ** |
322 ****************/ | |
323 | |
324 static const char *str_from_msg_type (GaimMessageFlags type) | |
325 { | |
7443 | 326 |
7431 | 327 return ""; |
7443 | 328 |
7431 | 329 } |
330 | |
7443 | 331 static void xml_logger_write(GaimLog *log, |
332 GaimMessageFlags type, | |
7431 | 333 const char *from, time_t time, const char *message) |
334 { | |
335 char date[64]; | |
336 char *xhtml = NULL; | |
337 if (!log->logger_data) { | |
338 /* This log is new. We could use the loggers 'new' function, but | |
339 * creating a new file there would result in empty files in the case | |
340 * that you open a convo with someone, but don't say anything. | |
341 */ | |
342 char *ud = gaim_user_dir(); | |
343 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); | |
344 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO | |
345 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
346 char *dir; | |
347 FILE *file; | |
348 | |
7453 | 349 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); |
7443 | 350 |
351 dir = g_build_filename(ud, "logs", | |
7431 | 352 prpl, guy, gaim_normalize(log->account, log->name), NULL); |
7612 | 353 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
7447 | 354 g_free(guy); |
7443 | 355 |
7431 | 356 char *filename = g_build_filename(dir, date, NULL); |
357 g_free(dir); | |
7443 | 358 |
7431 | 359 log->logger_data = fopen(filename, "a"); |
360 if (!log->logger_data) { | |
361 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); | |
7564 | 362 g_free(filename); |
7431 | 363 return; |
364 } | |
7564 | 365 g_free(filename); |
7431 | 366 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" |
367 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); | |
7443 | 368 |
7453 | 369 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
7431 | 370 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", |
371 date, log->name, prpl); | |
372 } | |
7443 | 373 |
7453 | 374 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
7431 | 375 gaim_markup_html_to_xhtml(message, &xhtml, NULL); |
376 if (from) | |
7443 | 377 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", |
378 str_from_msg_type(type), | |
7431 | 379 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
380 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
381 from, date, xhtml); | |
382 else | |
7443 | 383 fprintf(log->logger_data, "<message %s %s time='%s'>%s</message>\n", |
384 str_from_msg_type(type), | |
7431 | 385 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
386 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
7443 | 387 date, xhtml): |
7431 | 388 fflush(log->logger_data); |
389 g_free(xhtml); | |
7443 | 390 } |
391 | |
7431 | 392 static void xml_logger_finalize(GaimLog *log) |
393 { | |
394 if (log->logger_data) { | |
395 fprintf(log->logger_data, "</conversation>\n"); | |
396 fclose(log->logger_data); | |
397 log->logger_data = NULL; | |
398 } | |
399 } | |
7443 | 400 |
7431 | 401 static GList *xml_logger_list(const char *sn, GaimAccount *account) |
402 { | |
403 return log_lister_common(sn, account, ".xml", &xml_logger); | |
4184 | 404 } |
405 | |
7431 | 406 static GaimLogLogger xml_logger = { |
407 N_("XML"), "xml", | |
408 NULL, | |
409 xml_logger_write, | |
410 xml_logger_finalize, | |
411 xml_logger_list, | |
412 NULL | |
413 }; | |
414 #endif | |
5563
9eb5b13fd412
[gaim-migrate @ 5965]
Christian Hammond <chipx86@chipx86.com>
parents:
5560
diff
changeset
|
415 |
7431 | 416 /**************************** |
7457 | 417 ** HTML LOGGER ************* |
418 ****************************/ | |
419 | |
420 static void html_logger_write(GaimLog *log, GaimMessageFlags type, | |
421 const char *from, time_t time, const char *message) | |
422 { | |
7489 | 423 GaimConnection *gc = gaim_account_get_connection(log->account); |
7457 | 424 char date[64]; |
7616 | 425 struct generic_logger_data *data = log->logger_data; |
7618 | 426 if(!data) { |
7457 | 427 /* This log is new */ |
428 char *ud = gaim_user_dir(); | |
429 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); | |
7553 | 430 char *chat; |
7457 | 431 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
432 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
433 char *dir; | |
434 char *filename; | |
435 | |
7553 | 436 if (log->type == GAIM_LOG_CHAT) { |
437 chat = g_strdup_printf("%s.chat", guy); | |
438 g_free(guy); | |
439 guy = chat; | |
440 } | |
441 | |
7457 | 442 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.html", localtime(&log->time)); |
443 | |
444 dir = g_build_filename(ud, "logs", | |
445 prpl, guy, gaim_normalize(log->account, log->name), NULL); | |
7612 | 446 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
7457 | 447 g_free(guy); |
448 | |
449 filename = g_build_filename(dir, date, NULL); | |
450 g_free(dir); | |
451 | |
7616 | 452 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
453 | |
454 data->file = fopen(filename, "a"); | |
455 if (!data->file) { | |
7623 | 456 gaim_debug(GAIM_DEBUG_ERROR, "log", |
457 "Could not create log file %s\n", filename); | |
7564 | 458 g_free(filename); |
7457 | 459 return; |
460 } | |
461 g_free(filename); | |
462 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); | |
7616 | 463 fprintf(data->file, "<html><head><title>"); |
464 fprintf(data->file, "Conversation with %s at %s on %s (%s)", | |
7457 | 465 log->name, date, gaim_account_get_username(log->account), prpl); |
7616 | 466 fprintf(data->file, "</title></head><body>"); |
467 fprintf(data->file, | |
7457 | 468 "<h3>Conversation with %s at %s on %s (%s)</h3>\n", |
469 log->name, date, gaim_account_get_username(log->account), prpl); | |
470 } | |
7623 | 471 |
472 /* if we can't write to the file, give up before we hurt ourselves */ | |
473 if(!data->file) | |
474 return; | |
475 | |
7457 | 476 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
7489 | 477 if (type & GAIM_MESSAGE_SYSTEM) |
7616 | 478 fprintf(data->file, "(%s)<b> %s</b><br/>\n", date, message); |
7489 | 479 else if (type & GAIM_MESSAGE_WHISPER) |
7616 | 480 fprintf(data->file, "<font color=\"#6C2585\">(%s)<b> %s:</b></font> %s<br/>\n", |
7489 | 481 date, from, message); |
482 else if (type & GAIM_MESSAGE_AUTO_RESP) { | |
483 if (type & GAIM_MESSAGE_SEND) | |
7616 | 484 fprintf(data->file, _("<font color=\"#16569E\">(%s) <b>%s <AUTO-REPLY>:</b></font> %s<br/>\n"), date, from, message); |
7489 | 485 else if (type & GAIM_MESSAGE_RECV) |
7616 | 486 fprintf(data->file, _("<font color=\"#A82F2F\">(%s) <b>%s <AUTO-REPLY>:</b></font> %s<br/>\n"), date, from, message); |
7564 | 487 } else if (type & GAIM_MESSAGE_RECV) { |
488 char *msg = g_strdup(message); | |
489 if(gaim_message_meify(msg, -1)) | |
7616 | 490 fprintf(data->file, "<font color=\"#6C2585\">(%s) <b>***%s</b></font> <font sml=\"%s\">%s</font><br/>\n", |
7564 | 491 date, from, gc->prpl->info->name, msg); |
492 else | |
7616 | 493 fprintf(data->file, "<font color=\"#A82F2F\">(%s) <b>%s:</b></font> <font sml=\"%s\">%s</font><br/>\n", |
7564 | 494 date, from, gc->prpl->info->name, msg); |
495 g_free(msg); | |
496 } else if (type & GAIM_MESSAGE_SEND) { | |
497 char *msg = g_strdup(message); | |
498 if(gaim_message_meify(msg, -1)) | |
7616 | 499 fprintf(data->file, "<font color=\"#6C2585\">(%s) <b>***%s</b></font> <font sml=\"%s\">%s</font><br/>\n", |
7564 | 500 date, from, gc->prpl->info->name, msg); |
501 else | |
7616 | 502 fprintf(data->file, "<font color=\"#16569E\">(%s) <b>%s:</b></font> <font sml=\"%s\">%s</font><br/>\n", |
7564 | 503 date, from, gc->prpl->info->name, msg); |
504 g_free(msg); | |
505 } | |
7616 | 506 fflush(data->file); |
7457 | 507 } |
508 | |
509 static void html_logger_finalize(GaimLog *log) | |
510 { | |
7616 | 511 struct generic_logger_data *data = log->logger_data; |
512 if (data) { | |
513 if(data->file) { | |
514 fprintf(data->file, "</body></html>"); | |
515 fclose(data->file); | |
516 } | |
517 g_free(data->path); | |
7463 | 518 } |
7457 | 519 } |
520 | |
521 static GList *html_logger_list(const char *sn, GaimAccount *account) | |
522 { | |
523 return log_lister_common(sn, account, ".html", &html_logger); | |
524 } | |
525 | |
526 static char *html_logger_read(GaimLog *log, GaimLogReadFlags *flags) | |
527 { | |
528 char *read, *minus_header; | |
7616 | 529 struct generic_logger_data *data = log->logger_data; |
7457 | 530 *flags = GAIM_LOG_READ_NO_NEWLINE; |
7616 | 531 if (!data || !data->path) |
532 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
533 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7457 | 534 minus_header = strchr(read, '\n'); |
535 if (!minus_header) | |
536 minus_header = g_strdup(read); | |
537 else | |
538 minus_header = g_strdup(minus_header + 1); | |
539 g_free(read); | |
540 return minus_header; | |
541 } | |
7471 | 542 return g_strdup(_("<font color=\"red\"><b>Could not read file: %s</b></font>")); |
7457 | 543 } |
544 | |
545 static GaimLogLogger html_logger = { | |
546 N_("HTML"), "html", | |
547 NULL, | |
548 html_logger_write, | |
549 html_logger_finalize, | |
550 html_logger_list, | |
7556 | 551 html_logger_read, |
552 log_sizer_common | |
7457 | 553 }; |
554 | |
555 | |
556 | |
557 | |
558 /**************************** | |
7431 | 559 ** PLAIN TEXT LOGGER ******* |
560 ****************************/ | |
4184 | 561 |
7436 | 562 static void txt_logger_write(GaimLog *log, |
563 GaimMessageFlags type, | |
7431 | 564 const char *from, time_t time, const char *message) |
565 { | |
566 char date[64]; | |
567 char *stripped = NULL; | |
7616 | 568 struct generic_logger_data *data = log->logger_data; |
569 if (!data) { | |
7431 | 570 /* This log is new. We could use the loggers 'new' function, but |
571 * creating a new file there would result in empty files in the case | |
572 * that you open a convo with someone, but don't say anything. | |
573 */ | |
574 char *ud = gaim_user_dir(); | |
7473 | 575 char *filename; |
7431 | 576 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); |
7553 | 577 char *chat; |
7431 | 578 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
579 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
580 char *dir; | |
7436 | 581 |
7553 | 582 if (log->type == GAIM_LOG_CHAT) { |
583 chat = g_strdup_printf("%s.chat", guy); | |
584 g_free(guy); | |
585 guy = chat; | |
586 } | |
7453 | 587 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.txt", localtime(&log->time)); |
7436 | 588 |
589 dir = g_build_filename(ud, "logs", | |
7431 | 590 prpl, guy, gaim_normalize(log->account, log->name), NULL); |
7612 | 591 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
7447 | 592 g_free(guy); |
7436 | 593 |
7473 | 594 filename = g_build_filename(dir, date, NULL); |
7431 | 595 g_free(dir); |
7436 | 596 |
7616 | 597 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
598 | |
599 data->file = fopen(filename, "a"); | |
600 if (!data->file) { | |
7431 | 601 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); |
7564 | 602 g_free(filename); |
7431 | 603 return; |
4184 | 604 } |
7447 | 605 g_free(filename); |
7453 | 606 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
7616 | 607 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", |
7431 | 608 log->name, date, gaim_account_get_username(log->account), prpl); |
609 } | |
7436 | 610 |
7623 | 611 /* if we can't write to the file, give up before we hurt ourselves */ |
612 if(!data->file) | |
613 return; | |
614 | |
7453 | 615 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
7431 | 616 stripped = gaim_markup_strip_html(message); |
7489 | 617 if (type & GAIM_MESSAGE_SEND || |
7541 | 618 type & GAIM_MESSAGE_RECV) { |
7564 | 619 if (type & GAIM_MESSAGE_AUTO_RESP) { |
7616 | 620 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date, from, stripped); |
7564 | 621 } else { |
622 if(gaim_message_meify(stripped, -1)) | |
7616 | 623 fprintf(data->file, "(%s) ***%s %s\n", date, from, |
7564 | 624 stripped); |
625 else | |
7616 | 626 fprintf(data->file, "(%s) %s: %s\n", date, from, |
7564 | 627 stripped); |
628 } | |
629 } else if (type & GAIM_MESSAGE_SYSTEM) | |
7616 | 630 fprintf(data->file, "(%s) %s\n", date, stripped); |
7489 | 631 else if (type & GAIM_MESSAGE_NO_LOG) { |
632 /* This shouldn't happen */ | |
633 g_free(stripped); | |
634 return; | |
635 } else if (type & GAIM_MESSAGE_WHISPER) | |
7616 | 636 fprintf(data->file, "(%s) *%s* %s", date, from, stripped); |
7489 | 637 else |
7616 | 638 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "", from ? ":" : "", stripped); |
7489 | 639 |
7616 | 640 fflush(data->file); |
7431 | 641 g_free(stripped); |
642 } | |
643 | |
644 static void txt_logger_finalize(GaimLog *log) | |
645 { | |
7616 | 646 struct generic_logger_data *data = log->logger_data; |
647 if (data) { | |
648 if(data->file) | |
649 fclose(data->file); | |
650 if(data->path) | |
651 g_free(data->path); | |
652 } | |
7431 | 653 } |
654 | |
655 static GList *txt_logger_list(const char *sn, GaimAccount *account) | |
656 { | |
657 return log_lister_common(sn, account, ".txt", &txt_logger); | |
658 } | |
659 | |
660 static char *txt_logger_read(GaimLog *log, GaimLogReadFlags *flags) | |
661 { | |
662 char *read, *minus_header; | |
7616 | 663 struct generic_logger_data *data = log->logger_data; |
7457 | 664 *flags = 0; |
7616 | 665 if (!data || !data->path) |
666 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
667 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7431 | 668 minus_header = strchr(read, '\n'); |
669 if (!minus_header) | |
670 minus_header = g_strdup(read); | |
7436 | 671 else |
7431 | 672 minus_header = g_strdup(minus_header + 1); |
673 g_free(read); | |
674 return minus_header; | |
675 } | |
7471 | 676 return g_strdup(_("<font color=\"red\"><b>Could not read file: %s</b></font>")); |
7436 | 677 } |
7431 | 678 |
679 static GaimLogLogger txt_logger = { | |
680 N_("Plain text"), "txt", | |
681 NULL, | |
682 txt_logger_write, | |
683 txt_logger_finalize, | |
684 txt_logger_list, | |
7556 | 685 txt_logger_read, |
686 log_sizer_common | |
7431 | 687 }; |
688 | |
689 /**************** | |
690 * OLD LOGGER *** | |
691 ****************/ | |
692 | |
693 /* The old logger doesn't write logs, only reads them. This is to include | |
694 * old logs in the log viewer transparently. | |
695 */ | |
696 | |
697 struct old_logger_data { | |
698 char *path; | |
699 int offset; | |
700 int length; | |
701 }; | |
702 | |
7436 | 703 static GList *old_logger_list(const char *sn, GaimAccount *account) |
7431 | 704 { |
705 FILE *file; | |
706 char buf[BUF_LONG]; | |
707 struct tm tm; | |
708 struct old_logger_data *data = NULL; | |
709 char day[4], month[4], year[5]; | |
710 char *logfile = g_strdup_printf("%s.log", gaim_normalize(account, sn)); | |
711 char *date; | |
712 char *path = g_build_filename(gaim_user_dir(), "logs", logfile, NULL); | |
713 char *newlog; | |
714 | |
715 GaimLog *log = NULL; | |
716 GList *list = NULL; | |
717 | |
7473 | 718 g_free(logfile); |
719 | |
7461 | 720 if (!(file = fopen(path, "rb"))) { |
7447 | 721 g_free(path); |
7431 | 722 return NULL; |
7447 | 723 } |
7436 | 724 |
7431 | 725 while (fgets(buf, BUF_LONG, file)) { |
726 if ((newlog = strstr(buf, "---- New C"))) { | |
727 int length; | |
728 int offset; | |
729 GDate gdate; | |
730 char convostart[32]; | |
731 char *temp = strchr(buf, '@'); | |
7436 | 732 |
7431 | 733 if (temp == NULL || strlen(temp) < 2) |
734 continue; | |
7436 | 735 |
7431 | 736 temp++; |
737 length = strcspn(temp, "-"); | |
738 if (length > 31) length = 31; | |
7436 | 739 |
7431 | 740 offset = ftell(file); |
7436 | 741 |
7431 | 742 if (data) { |
7436 | 743 data->length = offset - data->offset - length; |
744 if(strstr(buf, "----</H3><BR>")) { | |
745 data->length -= | |
746 strlen("<HR><BR><H3 Align=Center> ---- New Conversation @ ") + | |
747 strlen("----</H3><BR>"); | |
748 } else { | |
749 data->length -= | |
750 strlen("---- New Conversation @ ") + strlen("----"); | |
751 } | |
752 | |
7461 | 753 if(strchr(buf, '\r')) |
754 data->length--; | |
755 | |
7431 | 756 if (data->length != 0) |
757 list = g_list_append(list, log); | |
758 else | |
759 gaim_log_free(log); | |
760 } | |
761 | |
762 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
763 log->logger = &old_logger; | |
764 | |
7436 | 765 data = g_new0(struct old_logger_data, 1); |
7431 | 766 data->offset = offset; |
7616 | 767 data->path = g_strdup(path); |
7431 | 768 log->logger_data = data; |
769 | |
7436 | 770 |
7431 | 771 g_snprintf(convostart, length, "%s", temp); |
772 sscanf(convostart, "%*s %s %s %d:%d:%d %s", | |
773 month, day, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, year); | |
774 date = g_strdup_printf("%s %s %s", month, day, year); | |
775 g_date_set_parse(&gdate, date); | |
776 tm.tm_mday = g_date_get_day(&gdate); | |
777 tm.tm_mon = g_date_get_month(&gdate) - 1; | |
778 tm.tm_year = g_date_get_year(&gdate) - 1900; | |
779 log->time = mktime(&tm); | |
7616 | 780 g_free(date); |
7431 | 781 |
4184 | 782 } |
783 } | |
7613 | 784 |
785 if (data) { | |
786 data->length = ftell(file) - data->offset; | |
787 if (data->length != 0) | |
788 list = g_list_append(list, log); | |
789 else | |
790 gaim_log_free(log); | |
791 } | |
792 | |
7616 | 793 g_free(path); |
7431 | 794 fclose(file); |
795 return list; | |
4184 | 796 } |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
797 |
7616 | 798 static char * old_logger_read (GaimLog *log, GaimLogReadFlags *flags) |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
799 { |
7431 | 800 struct old_logger_data *data = log->logger_data; |
7461 | 801 FILE *file = fopen(data->path, "rb"); |
7431 | 802 char *read = g_malloc(data->length + 1); |
803 fseek(file, data->offset, SEEK_SET); | |
804 fread(read, data->length, 1, file); | |
805 read[data->length] = '\0'; | |
7436 | 806 *flags = 0; |
807 if(strstr(read, "<BR>")) | |
808 *flags |= GAIM_LOG_READ_NO_NEWLINE; | |
7431 | 809 return read; |
810 } | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
811 |
7616 | 812 static int old_logger_size (GaimLog *log) |
7556 | 813 { |
814 struct old_logger_data *data = log->logger_data; | |
7616 | 815 return data ? data->length : 0; |
816 } | |
817 | |
818 static void old_logger_finalize(GaimLog *log) | |
819 { | |
820 struct old_logger_data *data = log->logger_data; | |
821 g_free(data->path); | |
822 g_free(data); | |
7556 | 823 } |
824 | |
7431 | 825 static GaimLogLogger old_logger = { |
826 "old logger", "old", | |
7616 | 827 NULL, NULL, |
828 old_logger_finalize, | |
7431 | 829 old_logger_list, |
7616 | 830 old_logger_read, |
831 old_logger_size | |
7431 | 832 }; |