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