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