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