Mercurial > pidgin
annotate src/log.c @ 7863:6ee2fe9bb74e
[gaim-migrate @ 8517]
"Patch 2: ssl-plugins.patch
Other plugins might need to use the NSS/GNUTLS libraries,
which shouldn't be initialized multiple times in the same
thread (at least NSS says this is a bad thing to do).
This patch
enables other plugins to load either the NSS or
GNUTLS plugin,
and
a) have them init on load, rather when sslconn inits them
b) have them not stomp on each other if the other one has
already loaded." --Bill Tompkins (obobo)
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Sun, 14 Dec 2003 16:46:28 +0000 |
parents | 21be2d9e8399 |
children | b4c2f92d4d24 |
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" |
7764 | 30 #include "stringref.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
31 |
7457 | 32 static GaimLogLogger html_logger; |
7431 | 33 static GaimLogLogger txt_logger; |
34 static GaimLogLogger old_logger; | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5839
diff
changeset
|
35 |
7431 | 36 /************************************************************************** |
37 * PUBLIC LOGGING FUNCTIONS *********************************************** | |
38 **************************************************************************/ | |
4184 | 39 |
7431 | 40 GaimLog *gaim_log_new(GaimLogType type, const char *name, GaimAccount *account, time_t time) |
41 { | |
42 GaimLog *log = g_new0(GaimLog, 1); | |
43 log->name = g_strdup(name); | |
44 log->account = account; | |
45 log->time = time; | |
46 log->logger = gaim_log_logger_get(); | |
7440 | 47 if (log->logger && log->logger->create) |
48 log->logger->create(log); | |
7431 | 49 return log; |
4184 | 50 } |
51 | |
7431 | 52 void gaim_log_free(GaimLog *log) |
4184 | 53 { |
7431 | 54 g_return_if_fail(log); |
55 if (log->logger && log->logger->finalize) | |
56 log->logger->finalize(log); | |
57 g_free(log->name); | |
58 g_free(log); | |
59 } | |
7436 | 60 |
4184 | 61 |
7436 | 62 void gaim_log_write(GaimLog *log, GaimMessageFlags type, |
7431 | 63 const char *from, time_t time, const char *message) |
64 { | |
65 g_return_if_fail(log); | |
66 g_return_if_fail(log->logger); | |
7442 | 67 g_return_if_fail(log->logger->write); |
7431 | 68 |
7555 | 69 if ((log->type == GAIM_LOG_IM && gaim_prefs_get_bool("/core/logging/log_ims")) || |
70 (log->type == GAIM_LOG_CHAT && gaim_prefs_get_bool("/core/logging/log_chats"))) | |
7553 | 71 (log->logger->write)(log, type, from, time, message); |
4184 | 72 } |
73 | |
7431 | 74 char *gaim_log_read(GaimLog *log, GaimLogReadFlags *flags) |
4184 | 75 { |
7542 | 76 GaimLogReadFlags mflags; |
7431 | 77 g_return_val_if_fail(log && log->logger, NULL); |
7462 | 78 if (log->logger->read) { |
7535 | 79 char *ret = (log->logger->read)(log, flags ? flags : &mflags); |
7478
3c21f3084ff0
[gaim-migrate @ 8091]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7473
diff
changeset
|
80 gaim_str_strip_cr(ret); |
7462 | 81 return ret; |
82 } | |
7470 | 83 return (_("<b><font color=\"red\">The logger has no read function</font></b>")); |
4184 | 84 } |
7616 | 85 |
7556 | 86 int gaim_log_get_size(GaimLog *log) |
87 { | |
88 g_return_val_if_fail(log && log->logger, 0); | |
89 if (log->logger->size) | |
90 return log->logger->size(log); | |
91 return 0; | |
92 } | |
93 | |
94 int gaim_log_get_total_size(const char *name, GaimAccount *account) | |
95 { | |
96 GList *logs = gaim_log_get_logs(name, account); | |
97 int size = 0; | |
7616 | 98 |
99 | |
7556 | 100 while (logs) { |
101 GList *logs2 = logs->next; | |
102 GaimLog *log = (GaimLog*)(logs->data); | |
103 size += gaim_log_get_size(log); | |
7685 | 104 gaim_log_free(log); |
7556 | 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); | |
7752 | 518 g_free(data); |
7463 | 519 } |
7457 | 520 } |
521 | |
522 static GList *html_logger_list(const char *sn, GaimAccount *account) | |
523 { | |
524 return log_lister_common(sn, account, ".html", &html_logger); | |
525 } | |
526 | |
527 static char *html_logger_read(GaimLog *log, GaimLogReadFlags *flags) | |
528 { | |
529 char *read, *minus_header; | |
7616 | 530 struct generic_logger_data *data = log->logger_data; |
7457 | 531 *flags = GAIM_LOG_READ_NO_NEWLINE; |
7616 | 532 if (!data || !data->path) |
533 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
534 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7457 | 535 minus_header = strchr(read, '\n'); |
536 if (!minus_header) | |
537 minus_header = g_strdup(read); | |
538 else | |
539 minus_header = g_strdup(minus_header + 1); | |
540 g_free(read); | |
541 return minus_header; | |
542 } | |
7471 | 543 return g_strdup(_("<font color=\"red\"><b>Could not read file: %s</b></font>")); |
7457 | 544 } |
545 | |
546 static GaimLogLogger html_logger = { | |
547 N_("HTML"), "html", | |
548 NULL, | |
549 html_logger_write, | |
550 html_logger_finalize, | |
551 html_logger_list, | |
7556 | 552 html_logger_read, |
553 log_sizer_common | |
7457 | 554 }; |
555 | |
556 | |
557 | |
558 | |
559 /**************************** | |
7431 | 560 ** PLAIN TEXT LOGGER ******* |
561 ****************************/ | |
4184 | 562 |
7436 | 563 static void txt_logger_write(GaimLog *log, |
564 GaimMessageFlags type, | |
7431 | 565 const char *from, time_t time, const char *message) |
566 { | |
567 char date[64]; | |
568 char *stripped = NULL; | |
7616 | 569 struct generic_logger_data *data = log->logger_data; |
570 if (!data) { | |
7431 | 571 /* This log is new. We could use the loggers 'new' function, but |
572 * creating a new file there would result in empty files in the case | |
573 * that you open a convo with someone, but don't say anything. | |
574 */ | |
575 char *ud = gaim_user_dir(); | |
7473 | 576 char *filename; |
7431 | 577 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); |
7553 | 578 char *chat; |
7431 | 579 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
580 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
581 char *dir; | |
7436 | 582 |
7553 | 583 if (log->type == GAIM_LOG_CHAT) { |
584 chat = g_strdup_printf("%s.chat", guy); | |
585 g_free(guy); | |
586 guy = chat; | |
587 } | |
7453 | 588 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.txt", localtime(&log->time)); |
7436 | 589 |
590 dir = g_build_filename(ud, "logs", | |
7431 | 591 prpl, guy, gaim_normalize(log->account, log->name), NULL); |
7612 | 592 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
7447 | 593 g_free(guy); |
7436 | 594 |
7473 | 595 filename = g_build_filename(dir, date, NULL); |
7431 | 596 g_free(dir); |
7436 | 597 |
7616 | 598 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
599 | |
600 data->file = fopen(filename, "a"); | |
601 if (!data->file) { | |
7431 | 602 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); |
7564 | 603 g_free(filename); |
7431 | 604 return; |
4184 | 605 } |
7447 | 606 g_free(filename); |
7453 | 607 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
7616 | 608 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", |
7431 | 609 log->name, date, gaim_account_get_username(log->account), prpl); |
610 } | |
7436 | 611 |
7623 | 612 /* if we can't write to the file, give up before we hurt ourselves */ |
613 if(!data->file) | |
614 return; | |
615 | |
7453 | 616 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
7431 | 617 stripped = gaim_markup_strip_html(message); |
7489 | 618 if (type & GAIM_MESSAGE_SEND || |
7541 | 619 type & GAIM_MESSAGE_RECV) { |
7564 | 620 if (type & GAIM_MESSAGE_AUTO_RESP) { |
7616 | 621 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date, from, stripped); |
7564 | 622 } else { |
623 if(gaim_message_meify(stripped, -1)) | |
7616 | 624 fprintf(data->file, "(%s) ***%s %s\n", date, from, |
7564 | 625 stripped); |
626 else | |
7616 | 627 fprintf(data->file, "(%s) %s: %s\n", date, from, |
7564 | 628 stripped); |
629 } | |
630 } else if (type & GAIM_MESSAGE_SYSTEM) | |
7616 | 631 fprintf(data->file, "(%s) %s\n", date, stripped); |
7489 | 632 else if (type & GAIM_MESSAGE_NO_LOG) { |
633 /* This shouldn't happen */ | |
634 g_free(stripped); | |
635 return; | |
636 } else if (type & GAIM_MESSAGE_WHISPER) | |
7616 | 637 fprintf(data->file, "(%s) *%s* %s", date, from, stripped); |
7489 | 638 else |
7616 | 639 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "", from ? ":" : "", stripped); |
7489 | 640 |
7616 | 641 fflush(data->file); |
7431 | 642 g_free(stripped); |
643 } | |
644 | |
645 static void txt_logger_finalize(GaimLog *log) | |
646 { | |
7616 | 647 struct generic_logger_data *data = log->logger_data; |
648 if (data) { | |
649 if(data->file) | |
650 fclose(data->file); | |
651 if(data->path) | |
652 g_free(data->path); | |
7752 | 653 g_free(data); |
7616 | 654 } |
7431 | 655 } |
656 | |
657 static GList *txt_logger_list(const char *sn, GaimAccount *account) | |
658 { | |
659 return log_lister_common(sn, account, ".txt", &txt_logger); | |
660 } | |
661 | |
662 static char *txt_logger_read(GaimLog *log, GaimLogReadFlags *flags) | |
663 { | |
664 char *read, *minus_header; | |
7616 | 665 struct generic_logger_data *data = log->logger_data; |
7457 | 666 *flags = 0; |
7616 | 667 if (!data || !data->path) |
668 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
669 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7431 | 670 minus_header = strchr(read, '\n'); |
671 if (!minus_header) | |
672 minus_header = g_strdup(read); | |
7436 | 673 else |
7431 | 674 minus_header = g_strdup(minus_header + 1); |
675 g_free(read); | |
676 return minus_header; | |
677 } | |
7471 | 678 return g_strdup(_("<font color=\"red\"><b>Could not read file: %s</b></font>")); |
7436 | 679 } |
7431 | 680 |
681 static GaimLogLogger txt_logger = { | |
682 N_("Plain text"), "txt", | |
683 NULL, | |
684 txt_logger_write, | |
685 txt_logger_finalize, | |
686 txt_logger_list, | |
7556 | 687 txt_logger_read, |
688 log_sizer_common | |
7431 | 689 }; |
690 | |
691 /**************** | |
692 * OLD LOGGER *** | |
693 ****************/ | |
694 | |
695 /* The old logger doesn't write logs, only reads them. This is to include | |
696 * old logs in the log viewer transparently. | |
697 */ | |
698 | |
699 struct old_logger_data { | |
7764 | 700 GaimStringref *pathref; |
7431 | 701 int offset; |
702 int length; | |
703 }; | |
704 | |
7436 | 705 static GList *old_logger_list(const char *sn, GaimAccount *account) |
7431 | 706 { |
707 FILE *file; | |
708 char buf[BUF_LONG]; | |
709 struct tm tm; | |
7761 | 710 char month[4]; |
7431 | 711 struct old_logger_data *data = NULL; |
712 char *logfile = g_strdup_printf("%s.log", gaim_normalize(account, sn)); | |
7764 | 713 char *pathstr = g_build_filename(gaim_user_dir(), "logs", logfile, NULL); |
714 GaimStringref *pathref = gaim_stringref_new(pathstr); | |
7431 | 715 char *newlog; |
7761 | 716 int logfound = 0; |
717 int lastoff = 0; | |
718 int newlen; | |
7791 | 719 time_t lasttime = 0; |
7431 | 720 |
721 GaimLog *log = NULL; | |
722 GList *list = NULL; | |
723 | |
7473 | 724 g_free(logfile); |
7764 | 725 g_free(pathstr); |
7473 | 726 |
7764 | 727 if (!(file = fopen(gaim_stringref_value(pathref), "rb"))) { |
728 gaim_stringref_unref(pathref); | |
7431 | 729 return NULL; |
7447 | 730 } |
7436 | 731 |
7431 | 732 while (fgets(buf, BUF_LONG, file)) { |
733 if ((newlog = strstr(buf, "---- New C"))) { | |
734 int length; | |
735 int offset; | |
736 char convostart[32]; | |
737 char *temp = strchr(buf, '@'); | |
7436 | 738 |
7431 | 739 if (temp == NULL || strlen(temp) < 2) |
740 continue; | |
7436 | 741 |
7431 | 742 temp++; |
743 length = strcspn(temp, "-"); | |
744 if (length > 31) length = 31; | |
7436 | 745 |
7431 | 746 offset = ftell(file); |
7436 | 747 |
7761 | 748 if (logfound) { |
749 newlen = offset - lastoff - length; | |
7436 | 750 if(strstr(buf, "----</H3><BR>")) { |
7761 | 751 newlen -= |
752 sizeof("<HR><BR><H3 Align=Center> ---- New Conversation @ ") + | |
753 sizeof("----</H3><BR>") - 2; | |
7436 | 754 } else { |
7761 | 755 newlen -= |
756 sizeof("---- New Conversation @ ") + sizeof("----") - 2; | |
7436 | 757 } |
758 | |
7461 | 759 if(strchr(buf, '\r')) |
7770 | 760 newlen--; |
7461 | 761 |
7761 | 762 if (newlen != 0) { |
763 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
764 log->logger = &old_logger; | |
765 log->time = lasttime; | |
766 data = g_new0(struct old_logger_data, 1); | |
767 data->offset = lastoff; | |
768 data->length = newlen; | |
7764 | 769 data->pathref = gaim_stringref_ref(pathref); |
7761 | 770 log->logger_data = data; |
7431 | 771 list = g_list_append(list, log); |
7761 | 772 } |
7431 | 773 } |
774 | |
7761 | 775 logfound = 1; |
776 lastoff = offset; | |
7436 | 777 |
7431 | 778 g_snprintf(convostart, length, "%s", temp); |
7676 | 779 sscanf(convostart, "%*s %s %d %d:%d:%d %d", |
780 month, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &tm.tm_year); | |
781 /* Ugly hack, in case current locale is not English */ | |
782 if (strcmp(month, "Jan") == 0) { | |
783 tm.tm_mon= 0; | |
784 } else if (strcmp(month, "Feb") == 0) { | |
785 tm.tm_mon = 1; | |
786 } else if (strcmp(month, "Mar") == 0) { | |
787 tm.tm_mon = 2; | |
788 } else if (strcmp(month, "Apr") == 0) { | |
789 tm.tm_mon = 3; | |
790 } else if (strcmp(month, "May") == 0) { | |
791 tm.tm_mon = 4; | |
792 } else if (strcmp(month, "Jun") == 0) { | |
793 tm.tm_mon = 5; | |
794 } else if (strcmp(month, "Jul") == 0) { | |
795 tm.tm_mon = 6; | |
796 } else if (strcmp(month, "Aug") == 0) { | |
797 tm.tm_mon = 7; | |
798 } else if (strcmp(month, "Sep") == 0) { | |
799 tm.tm_mon = 8; | |
800 } else if (strcmp(month, "Oct") == 0) { | |
801 tm.tm_mon = 9; | |
802 } else if (strcmp(month, "Nov") == 0) { | |
803 tm.tm_mon = 10; | |
804 } else if (strcmp(month, "Dec") == 0) { | |
805 tm.tm_mon = 11; | |
806 } | |
807 tm.tm_year -= 1900; | |
7761 | 808 lasttime = mktime(&tm); |
4184 | 809 } |
810 } | |
7613 | 811 |
7761 | 812 if (logfound) { |
813 if ((newlen = ftell(file) - lastoff) != 0) { | |
814 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
815 log->logger = &old_logger; | |
816 log->time = lasttime; | |
817 data = g_new0(struct old_logger_data, 1); | |
818 data->offset = lastoff; | |
819 data->length = newlen; | |
7764 | 820 data->pathref = gaim_stringref_ref(pathref); |
7761 | 821 log->logger_data = data; |
7613 | 822 list = g_list_append(list, log); |
7761 | 823 } |
7613 | 824 } |
825 | |
7764 | 826 gaim_stringref_unref(pathref); |
7431 | 827 fclose(file); |
828 return list; | |
4184 | 829 } |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
830 |
7616 | 831 static char * old_logger_read (GaimLog *log, GaimLogReadFlags *flags) |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
832 { |
7431 | 833 struct old_logger_data *data = log->logger_data; |
7764 | 834 FILE *file = fopen(gaim_stringref_value(data->pathref), "rb"); |
7431 | 835 char *read = g_malloc(data->length + 1); |
836 fseek(file, data->offset, SEEK_SET); | |
837 fread(read, data->length, 1, file); | |
838 read[data->length] = '\0'; | |
7436 | 839 *flags = 0; |
840 if(strstr(read, "<BR>")) | |
841 *flags |= GAIM_LOG_READ_NO_NEWLINE; | |
7431 | 842 return read; |
843 } | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
844 |
7616 | 845 static int old_logger_size (GaimLog *log) |
7556 | 846 { |
847 struct old_logger_data *data = log->logger_data; | |
7616 | 848 return data ? data->length : 0; |
849 } | |
850 | |
851 static void old_logger_finalize(GaimLog *log) | |
852 { | |
853 struct old_logger_data *data = log->logger_data; | |
7764 | 854 gaim_stringref_unref(data->pathref); |
7616 | 855 g_free(data); |
7556 | 856 } |
857 | |
7431 | 858 static GaimLogLogger old_logger = { |
859 "old logger", "old", | |
7616 | 860 NULL, NULL, |
861 old_logger_finalize, | |
7431 | 862 old_logger_list, |
7616 | 863 old_logger_read, |
864 old_logger_size | |
7431 | 865 }; |