Mercurial > pidgin.yaz
annotate src/log.c @ 7971:6fca0d9cc98b
[gaim-migrate @ 8648]
this particular work of art is topic changing support for jabber, and
support for setting the topic by just changing the text in the chat window.
hopefully someone less lazy than I will implement the right function for
IRC, and any other chats that do topics.
committer: Tailor Script <tailor@pidgin.im>
author | Nathan Walp <nwalp@pidgin.im> |
---|---|
date | Fri, 02 Jan 2004 06:16:44 +0000 |
parents | 1b8261f374ea |
children | 17b90334f3cc |
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 |
7956 | 252 /* does this seem like a bad way to get this component of the path to anyone else? --Nathan */ |
7431 | 253 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
7956 | 254 (gaim_find_prpl(gaim_account_get_protocol_id(account)))->list_icon(account, NULL); |
7431 | 255 char *path = g_build_filename(gaim_user_dir(), "logs", prpl, me, gaim_normalize(account, screenname), NULL); |
256 | |
7447 | 257 g_free(me); |
258 | |
7431 | 259 if (!(dir = g_dir_open(path, 0, NULL))) { |
260 g_free(path); | |
261 return NULL; | |
262 } | |
263 while ((filename = g_dir_read_name(dir))) { | |
7628 | 264 if (gaim_str_has_suffix(filename, ext)) { |
7431 | 265 const char *l = filename; |
266 struct tm time; | |
267 GaimLog *log; | |
7616 | 268 struct generic_logger_data *data; |
7431 | 269 char d[5]; |
7436 | 270 |
7431 | 271 strncpy(d, l, 4); |
272 d[4] = '\0'; | |
273 time.tm_year = atoi(d) - 1900; | |
274 l = l + 5; | |
275 | |
276 strncpy(d, l, 2); | |
277 d[2] = '\0'; | |
278 time.tm_mon = atoi(d) - 1; | |
279 l = l + 3; | |
280 | |
281 strncpy(d, l, 2); | |
282 time.tm_mday = atoi(d); | |
283 l = l + 3; | |
284 | |
285 strncpy(d, l, 2); | |
286 time.tm_hour = atoi(d); | |
287 l = l + 2; | |
7436 | 288 |
7431 | 289 strncpy(d, l, 2); |
290 time.tm_min = atoi(d); | |
291 l = l + 2; | |
292 | |
293 strncpy(d, l, 2); | |
294 time.tm_sec = atoi(d); | |
295 l = l + 2; | |
296 log = gaim_log_new(GAIM_LOG_IM, screenname, account, mktime(&time)); | |
297 log->logger = logger; | |
7616 | 298 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
299 data->path = g_build_filename(path, filename, NULL); | |
7431 | 300 list = g_list_append(list, log); |
4184 | 301 } |
302 } | |
7431 | 303 g_dir_close(dir); |
7447 | 304 g_free(path); |
7431 | 305 return list; |
306 } | |
4184 | 307 |
7556 | 308 /* Only to be used with logs listed from log_lister_common */ |
7616 | 309 int log_sizer_common(GaimLog *log) |
7556 | 310 { |
311 struct stat st; | |
7616 | 312 struct generic_logger_data *data = log->logger_data; |
7556 | 313 |
7616 | 314 if (!data->path || stat(data->path, &st)) |
7556 | 315 st.st_size = 0; |
316 | |
317 return st.st_size; | |
318 } | |
319 | |
7431 | 320 #if 0 /* Maybe some other time. */ |
7443 | 321 /**************** |
7431 | 322 ** XML LOGGER ** |
323 ****************/ | |
324 | |
325 static const char *str_from_msg_type (GaimMessageFlags type) | |
326 { | |
7443 | 327 |
7431 | 328 return ""; |
7443 | 329 |
7431 | 330 } |
331 | |
7443 | 332 static void xml_logger_write(GaimLog *log, |
333 GaimMessageFlags type, | |
7431 | 334 const char *from, time_t time, const char *message) |
335 { | |
336 char date[64]; | |
337 char *xhtml = NULL; | |
338 if (!log->logger_data) { | |
339 /* This log is new. We could use the loggers 'new' function, but | |
340 * creating a new file there would result in empty files in the case | |
341 * that you open a convo with someone, but don't say anything. | |
342 */ | |
343 char *ud = gaim_user_dir(); | |
344 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); | |
345 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO | |
346 (gaim_find_prpl(gaim_account_get_protocol(log->account)))->list_icon(log->account, NULL); | |
347 char *dir; | |
348 FILE *file; | |
349 | |
7453 | 350 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); |
7443 | 351 |
352 dir = g_build_filename(ud, "logs", | |
7431 | 353 prpl, guy, gaim_normalize(log->account, log->name), NULL); |
7612 | 354 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
7447 | 355 g_free(guy); |
7443 | 356 |
7431 | 357 char *filename = g_build_filename(dir, date, NULL); |
358 g_free(dir); | |
7443 | 359 |
7431 | 360 log->logger_data = fopen(filename, "a"); |
361 if (!log->logger_data) { | |
362 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); | |
7564 | 363 g_free(filename); |
7431 | 364 return; |
365 } | |
7564 | 366 g_free(filename); |
7431 | 367 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" |
368 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); | |
7443 | 369 |
7453 | 370 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
7431 | 371 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", |
372 date, log->name, prpl); | |
373 } | |
7443 | 374 |
7453 | 375 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
7431 | 376 gaim_markup_html_to_xhtml(message, &xhtml, NULL); |
377 if (from) | |
7443 | 378 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", |
379 str_from_msg_type(type), | |
7431 | 380 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
381 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
382 from, date, xhtml); | |
383 else | |
7443 | 384 fprintf(log->logger_data, "<message %s %s time='%s'>%s</message>\n", |
385 str_from_msg_type(type), | |
7431 | 386 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
387 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
7443 | 388 date, xhtml): |
7431 | 389 fflush(log->logger_data); |
390 g_free(xhtml); | |
7443 | 391 } |
392 | |
7431 | 393 static void xml_logger_finalize(GaimLog *log) |
394 { | |
395 if (log->logger_data) { | |
396 fprintf(log->logger_data, "</conversation>\n"); | |
397 fclose(log->logger_data); | |
398 log->logger_data = NULL; | |
399 } | |
400 } | |
7443 | 401 |
7431 | 402 static GList *xml_logger_list(const char *sn, GaimAccount *account) |
403 { | |
404 return log_lister_common(sn, account, ".xml", &xml_logger); | |
4184 | 405 } |
406 | |
7431 | 407 static GaimLogLogger xml_logger = { |
408 N_("XML"), "xml", | |
409 NULL, | |
410 xml_logger_write, | |
411 xml_logger_finalize, | |
412 xml_logger_list, | |
413 NULL | |
414 }; | |
415 #endif | |
5563
9eb5b13fd412
[gaim-migrate @ 5965]
Christian Hammond <chipx86@chipx86.com>
parents:
5560
diff
changeset
|
416 |
7431 | 417 /**************************** |
7457 | 418 ** HTML LOGGER ************* |
419 ****************************/ | |
420 | |
421 static void html_logger_write(GaimLog *log, GaimMessageFlags type, | |
422 const char *from, time_t time, const char *message) | |
423 { | |
7489 | 424 GaimConnection *gc = gaim_account_get_connection(log->account); |
7457 | 425 char date[64]; |
7882 | 426 char *msg_fixed; |
7616 | 427 struct generic_logger_data *data = log->logger_data; |
7618 | 428 if(!data) { |
7457 | 429 /* This log is new */ |
430 char *ud = gaim_user_dir(); | |
431 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); | |
7553 | 432 char *chat; |
7457 | 433 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
7956 | 434 (gaim_find_prpl(gaim_account_get_protocol_id(log->account)))->list_icon(log->account, NULL); |
7457 | 435 char *dir; |
436 char *filename; | |
437 | |
7553 | 438 if (log->type == GAIM_LOG_CHAT) { |
439 chat = g_strdup_printf("%s.chat", guy); | |
440 g_free(guy); | |
441 guy = chat; | |
442 } | |
443 | |
7457 | 444 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.html", localtime(&log->time)); |
445 | |
446 dir = g_build_filename(ud, "logs", | |
447 prpl, guy, gaim_normalize(log->account, log->name), NULL); | |
7612 | 448 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
7457 | 449 g_free(guy); |
450 | |
451 filename = g_build_filename(dir, date, NULL); | |
452 g_free(dir); | |
453 | |
7616 | 454 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
455 | |
456 data->file = fopen(filename, "a"); | |
457 if (!data->file) { | |
7623 | 458 gaim_debug(GAIM_DEBUG_ERROR, "log", |
459 "Could not create log file %s\n", filename); | |
7564 | 460 g_free(filename); |
7457 | 461 return; |
462 } | |
463 g_free(filename); | |
464 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); | |
7616 | 465 fprintf(data->file, "<html><head><title>"); |
466 fprintf(data->file, "Conversation with %s at %s on %s (%s)", | |
7457 | 467 log->name, date, gaim_account_get_username(log->account), prpl); |
7616 | 468 fprintf(data->file, "</title></head><body>"); |
469 fprintf(data->file, | |
7457 | 470 "<h3>Conversation with %s at %s on %s (%s)</h3>\n", |
471 log->name, date, gaim_account_get_username(log->account), prpl); | |
472 } | |
7623 | 473 |
474 /* if we can't write to the file, give up before we hurt ourselves */ | |
475 if(!data->file) | |
476 return; | |
477 | |
7882 | 478 gaim_markup_html_to_xhtml(message, &msg_fixed, NULL); |
479 | |
7457 | 480 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
7489 | 481 if (type & GAIM_MESSAGE_SYSTEM) |
7882 | 482 fprintf(data->file, "(%s)<b> %s</b><br/>\n", date, msg_fixed); |
7489 | 483 else if (type & GAIM_MESSAGE_WHISPER) |
7616 | 484 fprintf(data->file, "<font color=\"#6C2585\">(%s)<b> %s:</b></font> %s<br/>\n", |
7882 | 485 date, from, msg_fixed); |
7489 | 486 else if (type & GAIM_MESSAGE_AUTO_RESP) { |
487 if (type & GAIM_MESSAGE_SEND) | |
7882 | 488 fprintf(data->file, _("<font color=\"#16569E\">(%s) <b>%s <AUTO-REPLY>:</b></font> %s<br/>\n"), date, from, msg_fixed); |
7489 | 489 else if (type & GAIM_MESSAGE_RECV) |
7882 | 490 fprintf(data->file, _("<font color=\"#A82F2F\">(%s) <b>%s <AUTO-REPLY>:</b></font> %s<br/>\n"), date, from, msg_fixed); |
7564 | 491 } else if (type & GAIM_MESSAGE_RECV) { |
7882 | 492 if(gaim_message_meify(msg_fixed, -1)) |
7616 | 493 fprintf(data->file, "<font color=\"#6C2585\">(%s) <b>***%s</b></font> <font sml=\"%s\">%s</font><br/>\n", |
7882 | 494 date, from, gc->prpl->info->name, msg_fixed); |
7564 | 495 else |
7616 | 496 fprintf(data->file, "<font color=\"#A82F2F\">(%s) <b>%s:</b></font> <font sml=\"%s\">%s</font><br/>\n", |
7882 | 497 date, from, gc->prpl->info->name, msg_fixed); |
7564 | 498 } else if (type & GAIM_MESSAGE_SEND) { |
7882 | 499 if(gaim_message_meify(msg_fixed, -1)) |
7616 | 500 fprintf(data->file, "<font color=\"#6C2585\">(%s) <b>***%s</b></font> <font sml=\"%s\">%s</font><br/>\n", |
7882 | 501 date, from, gc->prpl->info->name, msg_fixed); |
7564 | 502 else |
7616 | 503 fprintf(data->file, "<font color=\"#16569E\">(%s) <b>%s:</b></font> <font sml=\"%s\">%s</font><br/>\n", |
7882 | 504 date, from, gc->prpl->info->name, msg_fixed); |
7564 | 505 } |
7882 | 506 g_free(msg_fixed); |
7616 | 507 fflush(data->file); |
7457 | 508 } |
509 | |
510 static void html_logger_finalize(GaimLog *log) | |
511 { | |
7616 | 512 struct generic_logger_data *data = log->logger_data; |
513 if (data) { | |
514 if(data->file) { | |
515 fprintf(data->file, "</body></html>"); | |
516 fclose(data->file); | |
517 } | |
518 g_free(data->path); | |
7752 | 519 g_free(data); |
7463 | 520 } |
7457 | 521 } |
522 | |
523 static GList *html_logger_list(const char *sn, GaimAccount *account) | |
524 { | |
525 return log_lister_common(sn, account, ".html", &html_logger); | |
526 } | |
527 | |
528 static char *html_logger_read(GaimLog *log, GaimLogReadFlags *flags) | |
529 { | |
530 char *read, *minus_header; | |
7616 | 531 struct generic_logger_data *data = log->logger_data; |
7457 | 532 *flags = GAIM_LOG_READ_NO_NEWLINE; |
7616 | 533 if (!data || !data->path) |
534 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
535 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7457 | 536 minus_header = strchr(read, '\n'); |
537 if (!minus_header) | |
538 minus_header = g_strdup(read); | |
539 else | |
540 minus_header = g_strdup(minus_header + 1); | |
541 g_free(read); | |
542 return minus_header; | |
543 } | |
7471 | 544 return g_strdup(_("<font color=\"red\"><b>Could not read file: %s</b></font>")); |
7457 | 545 } |
546 | |
547 static GaimLogLogger html_logger = { | |
548 N_("HTML"), "html", | |
549 NULL, | |
550 html_logger_write, | |
551 html_logger_finalize, | |
552 html_logger_list, | |
7556 | 553 html_logger_read, |
554 log_sizer_common | |
7457 | 555 }; |
556 | |
557 | |
558 | |
559 | |
560 /**************************** | |
7431 | 561 ** PLAIN TEXT LOGGER ******* |
562 ****************************/ | |
4184 | 563 |
7436 | 564 static void txt_logger_write(GaimLog *log, |
565 GaimMessageFlags type, | |
7431 | 566 const char *from, time_t time, const char *message) |
567 { | |
568 char date[64]; | |
569 char *stripped = NULL; | |
7616 | 570 struct generic_logger_data *data = log->logger_data; |
571 if (!data) { | |
7431 | 572 /* This log is new. We could use the loggers 'new' function, but |
573 * creating a new file there would result in empty files in the case | |
574 * that you open a convo with someone, but don't say anything. | |
575 */ | |
576 char *ud = gaim_user_dir(); | |
7473 | 577 char *filename; |
7431 | 578 char *guy = g_strdup(gaim_normalize(log->account, gaim_account_get_username(log->account))); |
7553 | 579 char *chat; |
7431 | 580 const char *prpl = GAIM_PLUGIN_PROTOCOL_INFO |
7956 | 581 (gaim_find_prpl(gaim_account_get_protocol_id(log->account)))->list_icon(log->account, NULL); |
7431 | 582 char *dir; |
7436 | 583 |
7553 | 584 if (log->type == GAIM_LOG_CHAT) { |
585 chat = g_strdup_printf("%s.chat", guy); | |
586 g_free(guy); | |
587 guy = chat; | |
588 } | |
7453 | 589 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.txt", localtime(&log->time)); |
7436 | 590 |
591 dir = g_build_filename(ud, "logs", | |
7431 | 592 prpl, guy, gaim_normalize(log->account, log->name), NULL); |
7612 | 593 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
7447 | 594 g_free(guy); |
7436 | 595 |
7473 | 596 filename = g_build_filename(dir, date, NULL); |
7431 | 597 g_free(dir); |
7436 | 598 |
7616 | 599 log->logger_data = data = g_new0(struct generic_logger_data, 1); |
600 | |
601 data->file = fopen(filename, "a"); | |
602 if (!data->file) { | |
7431 | 603 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); |
7564 | 604 g_free(filename); |
7431 | 605 return; |
4184 | 606 } |
7447 | 607 g_free(filename); |
7453 | 608 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
7616 | 609 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", |
7431 | 610 log->name, date, gaim_account_get_username(log->account), prpl); |
611 } | |
7436 | 612 |
7623 | 613 /* if we can't write to the file, give up before we hurt ourselves */ |
614 if(!data->file) | |
615 return; | |
616 | |
7453 | 617 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
7431 | 618 stripped = gaim_markup_strip_html(message); |
7489 | 619 if (type & GAIM_MESSAGE_SEND || |
7541 | 620 type & GAIM_MESSAGE_RECV) { |
7564 | 621 if (type & GAIM_MESSAGE_AUTO_RESP) { |
7616 | 622 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date, from, stripped); |
7564 | 623 } else { |
624 if(gaim_message_meify(stripped, -1)) | |
7616 | 625 fprintf(data->file, "(%s) ***%s %s\n", date, from, |
7564 | 626 stripped); |
627 else | |
7616 | 628 fprintf(data->file, "(%s) %s: %s\n", date, from, |
7564 | 629 stripped); |
630 } | |
631 } else if (type & GAIM_MESSAGE_SYSTEM) | |
7616 | 632 fprintf(data->file, "(%s) %s\n", date, stripped); |
7489 | 633 else if (type & GAIM_MESSAGE_NO_LOG) { |
634 /* This shouldn't happen */ | |
635 g_free(stripped); | |
636 return; | |
637 } else if (type & GAIM_MESSAGE_WHISPER) | |
7616 | 638 fprintf(data->file, "(%s) *%s* %s", date, from, stripped); |
7489 | 639 else |
7616 | 640 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "", from ? ":" : "", stripped); |
7489 | 641 |
7616 | 642 fflush(data->file); |
7431 | 643 g_free(stripped); |
644 } | |
645 | |
646 static void txt_logger_finalize(GaimLog *log) | |
647 { | |
7616 | 648 struct generic_logger_data *data = log->logger_data; |
649 if (data) { | |
650 if(data->file) | |
651 fclose(data->file); | |
652 if(data->path) | |
653 g_free(data->path); | |
7752 | 654 g_free(data); |
7616 | 655 } |
7431 | 656 } |
657 | |
658 static GList *txt_logger_list(const char *sn, GaimAccount *account) | |
659 { | |
660 return log_lister_common(sn, account, ".txt", &txt_logger); | |
661 } | |
662 | |
663 static char *txt_logger_read(GaimLog *log, GaimLogReadFlags *flags) | |
664 { | |
665 char *read, *minus_header; | |
7616 | 666 struct generic_logger_data *data = log->logger_data; |
7457 | 667 *flags = 0; |
7616 | 668 if (!data || !data->path) |
669 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
670 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7431 | 671 minus_header = strchr(read, '\n'); |
672 if (!minus_header) | |
673 minus_header = g_strdup(read); | |
7436 | 674 else |
7431 | 675 minus_header = g_strdup(minus_header + 1); |
676 g_free(read); | |
677 return minus_header; | |
678 } | |
7471 | 679 return g_strdup(_("<font color=\"red\"><b>Could not read file: %s</b></font>")); |
7436 | 680 } |
7431 | 681 |
682 static GaimLogLogger txt_logger = { | |
683 N_("Plain text"), "txt", | |
684 NULL, | |
685 txt_logger_write, | |
686 txt_logger_finalize, | |
687 txt_logger_list, | |
7556 | 688 txt_logger_read, |
689 log_sizer_common | |
7431 | 690 }; |
691 | |
692 /**************** | |
693 * OLD LOGGER *** | |
694 ****************/ | |
695 | |
696 /* The old logger doesn't write logs, only reads them. This is to include | |
697 * old logs in the log viewer transparently. | |
698 */ | |
699 | |
700 struct old_logger_data { | |
7764 | 701 GaimStringref *pathref; |
7431 | 702 int offset; |
703 int length; | |
704 }; | |
705 | |
7436 | 706 static GList *old_logger_list(const char *sn, GaimAccount *account) |
7431 | 707 { |
708 FILE *file; | |
709 char buf[BUF_LONG]; | |
710 struct tm tm; | |
7761 | 711 char month[4]; |
7431 | 712 struct old_logger_data *data = NULL; |
713 char *logfile = g_strdup_printf("%s.log", gaim_normalize(account, sn)); | |
7764 | 714 char *pathstr = g_build_filename(gaim_user_dir(), "logs", logfile, NULL); |
715 GaimStringref *pathref = gaim_stringref_new(pathstr); | |
7431 | 716 char *newlog; |
7761 | 717 int logfound = 0; |
718 int lastoff = 0; | |
719 int newlen; | |
7791 | 720 time_t lasttime = 0; |
7431 | 721 |
722 GaimLog *log = NULL; | |
723 GList *list = NULL; | |
724 | |
7473 | 725 g_free(logfile); |
7764 | 726 g_free(pathstr); |
7473 | 727 |
7764 | 728 if (!(file = fopen(gaim_stringref_value(pathref), "rb"))) { |
729 gaim_stringref_unref(pathref); | |
7431 | 730 return NULL; |
7447 | 731 } |
7436 | 732 |
7431 | 733 while (fgets(buf, BUF_LONG, file)) { |
734 if ((newlog = strstr(buf, "---- New C"))) { | |
735 int length; | |
736 int offset; | |
737 char convostart[32]; | |
738 char *temp = strchr(buf, '@'); | |
7436 | 739 |
7431 | 740 if (temp == NULL || strlen(temp) < 2) |
741 continue; | |
7436 | 742 |
7431 | 743 temp++; |
744 length = strcspn(temp, "-"); | |
745 if (length > 31) length = 31; | |
7436 | 746 |
7431 | 747 offset = ftell(file); |
7436 | 748 |
7761 | 749 if (logfound) { |
750 newlen = offset - lastoff - length; | |
7436 | 751 if(strstr(buf, "----</H3><BR>")) { |
7761 | 752 newlen -= |
753 sizeof("<HR><BR><H3 Align=Center> ---- New Conversation @ ") + | |
754 sizeof("----</H3><BR>") - 2; | |
7436 | 755 } else { |
7761 | 756 newlen -= |
757 sizeof("---- New Conversation @ ") + sizeof("----") - 2; | |
7436 | 758 } |
759 | |
7461 | 760 if(strchr(buf, '\r')) |
7770 | 761 newlen--; |
7461 | 762 |
7761 | 763 if (newlen != 0) { |
764 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
765 log->logger = &old_logger; | |
766 log->time = lasttime; | |
767 data = g_new0(struct old_logger_data, 1); | |
768 data->offset = lastoff; | |
769 data->length = newlen; | |
7764 | 770 data->pathref = gaim_stringref_ref(pathref); |
7761 | 771 log->logger_data = data; |
7431 | 772 list = g_list_append(list, log); |
7761 | 773 } |
7431 | 774 } |
775 | |
7761 | 776 logfound = 1; |
777 lastoff = offset; | |
7436 | 778 |
7431 | 779 g_snprintf(convostart, length, "%s", temp); |
7676 | 780 sscanf(convostart, "%*s %s %d %d:%d:%d %d", |
781 month, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &tm.tm_year); | |
782 /* Ugly hack, in case current locale is not English */ | |
783 if (strcmp(month, "Jan") == 0) { | |
784 tm.tm_mon= 0; | |
785 } else if (strcmp(month, "Feb") == 0) { | |
786 tm.tm_mon = 1; | |
787 } else if (strcmp(month, "Mar") == 0) { | |
788 tm.tm_mon = 2; | |
789 } else if (strcmp(month, "Apr") == 0) { | |
790 tm.tm_mon = 3; | |
791 } else if (strcmp(month, "May") == 0) { | |
792 tm.tm_mon = 4; | |
793 } else if (strcmp(month, "Jun") == 0) { | |
794 tm.tm_mon = 5; | |
795 } else if (strcmp(month, "Jul") == 0) { | |
796 tm.tm_mon = 6; | |
797 } else if (strcmp(month, "Aug") == 0) { | |
798 tm.tm_mon = 7; | |
799 } else if (strcmp(month, "Sep") == 0) { | |
800 tm.tm_mon = 8; | |
801 } else if (strcmp(month, "Oct") == 0) { | |
802 tm.tm_mon = 9; | |
803 } else if (strcmp(month, "Nov") == 0) { | |
804 tm.tm_mon = 10; | |
805 } else if (strcmp(month, "Dec") == 0) { | |
806 tm.tm_mon = 11; | |
807 } | |
808 tm.tm_year -= 1900; | |
7761 | 809 lasttime = mktime(&tm); |
4184 | 810 } |
811 } | |
7613 | 812 |
7761 | 813 if (logfound) { |
814 if ((newlen = ftell(file) - lastoff) != 0) { | |
815 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
816 log->logger = &old_logger; | |
817 log->time = lasttime; | |
818 data = g_new0(struct old_logger_data, 1); | |
819 data->offset = lastoff; | |
820 data->length = newlen; | |
7764 | 821 data->pathref = gaim_stringref_ref(pathref); |
7761 | 822 log->logger_data = data; |
7613 | 823 list = g_list_append(list, log); |
7761 | 824 } |
7613 | 825 } |
826 | |
7764 | 827 gaim_stringref_unref(pathref); |
7431 | 828 fclose(file); |
829 return list; | |
4184 | 830 } |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
831 |
7616 | 832 static char * old_logger_read (GaimLog *log, GaimLogReadFlags *flags) |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
833 { |
7431 | 834 struct old_logger_data *data = log->logger_data; |
7764 | 835 FILE *file = fopen(gaim_stringref_value(data->pathref), "rb"); |
7431 | 836 char *read = g_malloc(data->length + 1); |
837 fseek(file, data->offset, SEEK_SET); | |
838 fread(read, data->length, 1, file); | |
839 read[data->length] = '\0'; | |
7436 | 840 *flags = 0; |
841 if(strstr(read, "<BR>")) | |
842 *flags |= GAIM_LOG_READ_NO_NEWLINE; | |
7431 | 843 return read; |
844 } | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
845 |
7616 | 846 static int old_logger_size (GaimLog *log) |
7556 | 847 { |
848 struct old_logger_data *data = log->logger_data; | |
7616 | 849 return data ? data->length : 0; |
850 } | |
851 | |
852 static void old_logger_finalize(GaimLog *log) | |
853 { | |
854 struct old_logger_data *data = log->logger_data; | |
7764 | 855 gaim_stringref_unref(data->pathref); |
7616 | 856 g_free(data); |
7556 | 857 } |
858 | |
7431 | 859 static GaimLogLogger old_logger = { |
860 "old logger", "old", | |
7616 | 861 NULL, NULL, |
862 old_logger_finalize, | |
7431 | 863 old_logger_list, |
7616 | 864 old_logger_read, |
865 old_logger_size | |
7431 | 866 }; |