Mercurial > pidgin
annotate src/log.c @ 11243:a511b77a368b
[gaim-migrate @ 13408]
sf patch #1246384, from shiyee
"This patch globally defines
spacings and boreders according to the Gnome Human
Interfaces Guidelines, and uses those defines where
appropriate. No visual changes are made, but the the
intention is that the defines should help promote
uniformness."
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Fri, 12 Aug 2005 23:53:28 +0000 |
parents | 3924db2b1ca8 |
children | bb0d7b719af2 |
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 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
46 static void log_get_log_sets_common(GHashTable *sets); |
8635 | 47 |
7431 | 48 /************************************************************************** |
49 * PUBLIC LOGGING FUNCTIONS *********************************************** | |
50 **************************************************************************/ | |
4184 | 51 |
7431 | 52 GaimLog *gaim_log_new(GaimLogType type, const char *name, GaimAccount *account, time_t time) |
53 { | |
54 GaimLog *log = g_new0(GaimLog, 1); | |
8635 | 55 log->name = g_strdup(gaim_normalize(account, name)); |
7431 | 56 log->account = account; |
57 log->time = time; | |
8573 | 58 log->type = type; |
8096 | 59 log->logger_data = NULL; |
7431 | 60 log->logger = gaim_log_logger_get(); |
7440 | 61 if (log->logger && log->logger->create) |
62 log->logger->create(log); | |
7431 | 63 return log; |
4184 | 64 } |
65 | |
7431 | 66 void gaim_log_free(GaimLog *log) |
4184 | 67 { |
7431 | 68 g_return_if_fail(log); |
69 if (log->logger && log->logger->finalize) | |
70 log->logger->finalize(log); | |
71 g_free(log->name); | |
72 g_free(log); | |
73 } | |
7436 | 74 |
75 void gaim_log_write(GaimLog *log, GaimMessageFlags type, | |
7431 | 76 const char *from, time_t time, const char *message) |
77 { | |
10173 | 78 struct _gaim_logsize_user *lu; |
79 | |
7431 | 80 g_return_if_fail(log); |
81 g_return_if_fail(log->logger); | |
7442 | 82 g_return_if_fail(log->logger->write); |
7431 | 83 |
10171
829a569993e0
[gaim-migrate @ 11263]
Luke Schierer <lschiere@pidgin.im>
parents:
10087
diff
changeset
|
84 (log->logger->write)(log, type, from, time, message); |
829a569993e0
[gaim-migrate @ 11263]
Luke Schierer <lschiere@pidgin.im>
parents:
10087
diff
changeset
|
85 |
829a569993e0
[gaim-migrate @ 11263]
Luke Schierer <lschiere@pidgin.im>
parents:
10087
diff
changeset
|
86 lu = g_new(struct _gaim_logsize_user, 1); |
9892 | 87 |
10171
829a569993e0
[gaim-migrate @ 11263]
Luke Schierer <lschiere@pidgin.im>
parents:
10087
diff
changeset
|
88 lu->name = g_strdup(gaim_normalize(log->account, log->name)); |
829a569993e0
[gaim-migrate @ 11263]
Luke Schierer <lschiere@pidgin.im>
parents:
10087
diff
changeset
|
89 lu->account = log->account; |
829a569993e0
[gaim-migrate @ 11263]
Luke Schierer <lschiere@pidgin.im>
parents:
10087
diff
changeset
|
90 g_hash_table_remove(logsize_users, lu); |
829a569993e0
[gaim-migrate @ 11263]
Luke Schierer <lschiere@pidgin.im>
parents:
10087
diff
changeset
|
91 g_free(lu->name); |
829a569993e0
[gaim-migrate @ 11263]
Luke Schierer <lschiere@pidgin.im>
parents:
10087
diff
changeset
|
92 g_free(lu); |
9892 | 93 |
4184 | 94 } |
95 | |
7431 | 96 char *gaim_log_read(GaimLog *log, GaimLogReadFlags *flags) |
4184 | 97 { |
7542 | 98 GaimLogReadFlags mflags; |
7431 | 99 g_return_val_if_fail(log && log->logger, NULL); |
7462 | 100 if (log->logger->read) { |
7535 | 101 char *ret = (log->logger->read)(log, flags ? flags : &mflags); |
7478
3c21f3084ff0
[gaim-migrate @ 8091]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7473
diff
changeset
|
102 gaim_str_strip_cr(ret); |
7462 | 103 return ret; |
104 } | |
7470 | 105 return (_("<b><font color=\"red\">The logger has no read function</font></b>")); |
4184 | 106 } |
7616 | 107 |
7556 | 108 int gaim_log_get_size(GaimLog *log) |
109 { | |
110 g_return_val_if_fail(log && log->logger, 0); | |
8096 | 111 |
7556 | 112 if (log->logger->size) |
113 return log->logger->size(log); | |
114 return 0; | |
115 } | |
116 | |
8635 | 117 static guint _gaim_logsize_user_hash(struct _gaim_logsize_user *lu) |
118 { | |
119 return g_str_hash(lu->name); | |
120 } | |
121 | |
122 static guint _gaim_logsize_user_equal(struct _gaim_logsize_user *lu1, | |
123 struct _gaim_logsize_user *lu2) | |
124 { | |
125 return ((!strcmp(lu1->name, lu2->name)) && lu1->account == lu2->account); | |
126 } | |
127 | |
128 static void _gaim_logsize_user_free_key(struct _gaim_logsize_user *lu) | |
129 { | |
130 g_free(lu->name); | |
131 g_free(lu); | |
132 } | |
133 | |
8898 | 134 int gaim_log_get_total_size(GaimLogType type, const char *name, GaimAccount *account) |
7556 | 135 { |
9677 | 136 gpointer ptrsize; |
137 int size = 0; | |
8096 | 138 GSList *n; |
8635 | 139 struct _gaim_logsize_user *lu; |
8096 | 140 |
8635 | 141 lu = g_new(struct _gaim_logsize_user, 1); |
142 lu->name = g_strdup(gaim_normalize(account, name)); | |
143 lu->account = account; | |
144 | |
9677 | 145 if(g_hash_table_lookup_extended(logsize_users, lu, NULL, &ptrsize)) { |
146 size = GPOINTER_TO_INT(ptrsize); | |
8635 | 147 g_free(lu->name); |
148 g_free(lu); | |
149 } else { | |
150 for (n = loggers; n; n = n->next) { | |
151 GaimLogLogger *logger = n->data; | |
7616 | 152 |
8635 | 153 if(logger->total_size){ |
8898 | 154 size += (logger->total_size)(type, name, account); |
8635 | 155 } else if(logger->list) { |
8898 | 156 GList *logs = (logger->list)(type, name, account); |
8635 | 157 int this_size = 0; |
158 | |
159 while (logs) { | |
160 GList *logs2 = logs->next; | |
161 GaimLog *log = (GaimLog*)(logs->data); | |
162 this_size += gaim_log_get_size(log); | |
163 gaim_log_free(log); | |
164 g_list_free_1(logs); | |
165 logs = logs2; | |
166 } | |
167 | |
168 size += this_size; | |
8096 | 169 } |
8635 | 170 } |
8096 | 171 |
8635 | 172 g_hash_table_replace(logsize_users, lu, GINT_TO_POINTER(size)); |
7556 | 173 } |
174 return size; | |
175 } | |
4184 | 176 |
10822 | 177 char * |
10577 | 178 gaim_log_get_log_dir(GaimLogType type, const char *name, GaimAccount *account) |
179 { | |
180 GaimPlugin *prpl; | |
181 GaimPluginProtocolInfo *prpl_info; | |
182 const char *prpl_name; | |
183 char *acct_name; | |
9926 | 184 const char *target; |
10577 | 185 char *dir; |
9926 | 186 |
10577 | 187 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); |
188 if (!prpl) | |
189 return NULL; | |
190 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
191 prpl_name = prpl_info->list_icon(account, NULL); | |
192 | |
193 acct_name = g_strdup(gaim_escape_filename(gaim_normalize(account, | |
194 gaim_account_get_username(account)))); | |
9923 | 195 |
196 if (type == GAIM_LOG_CHAT) { | |
197 char *temp = g_strdup_printf("%s.chat", gaim_normalize(account, name)); | |
9926 | 198 target = gaim_escape_filename(temp); |
9923 | 199 g_free(temp); |
200 } else if(type == GAIM_LOG_SYSTEM) { | |
9926 | 201 target = ".system"; |
9923 | 202 } else { |
9926 | 203 target = gaim_escape_filename(gaim_normalize(account, name)); |
9923 | 204 } |
205 | |
10577 | 206 dir = g_build_filename(gaim_user_dir(), "logs", prpl_name, acct_name, target, NULL); |
9926 | 207 |
9923 | 208 g_free(acct_name); |
10577 | 209 |
9923 | 210 return dir; |
211 } | |
212 | |
7431 | 213 /**************************************************************************** |
214 * LOGGER FUNCTIONS ********************************************************* | |
215 ****************************************************************************/ | |
4184 | 216 |
7431 | 217 static GaimLogLogger *current_logger = NULL; |
7436 | 218 |
7431 | 219 static void logger_pref_cb(const char *name, GaimPrefType type, |
220 gpointer value, gpointer data) | |
221 { | |
222 GaimLogLogger *logger; | |
223 GSList *l = loggers; | |
224 while (l) { | |
225 logger = l->data; | |
226 if (!strcmp(logger->id, value)) { | |
227 gaim_log_logger_set(logger); | |
228 return; | |
4184 | 229 } |
7431 | 230 l = l->next; |
231 } | |
232 gaim_log_logger_set(&txt_logger); | |
233 } | |
4184 | 234 |
235 | |
8898 | 236 GaimLogLogger *gaim_log_logger_new( |
237 void(*create)(GaimLog *), | |
238 void(*write)(GaimLog *, GaimMessageFlags, const char *, time_t, const char *), | |
239 void(*finalize)(GaimLog *), | |
240 GList*(*list)(GaimLogType type, const char*, GaimAccount*), | |
241 char*(*read)(GaimLog*, GaimLogReadFlags*), | |
11025 | 242 int(*size)(GaimLog*), |
243 int(*total_size)(GaimLogType type, const char *name, GaimAccount *account), | |
244 GList*(*list_syslog)(GaimAccount *account), | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
245 void(*get_log_sets)(GaimLogSetCallback cb, GHashTable *sets)) |
7431 | 246 { |
247 GaimLogLogger *logger = g_new0(GaimLogLogger, 1); | |
11025 | 248 |
7440 | 249 logger->create = create; |
7431 | 250 logger->write = write; |
251 logger->finalize = finalize; | |
252 logger->list = list; | |
253 logger->read = read; | |
7556 | 254 logger->size = size; |
11025 | 255 logger->total_size = total_size; |
256 logger->list_syslog = list_syslog; | |
257 logger->get_log_sets = get_log_sets; | |
258 | |
7431 | 259 return logger; |
4184 | 260 } |
261 | |
7431 | 262 void gaim_log_logger_free(GaimLogLogger *logger) |
4184 | 263 { |
7431 | 264 g_free(logger); |
265 } | |
4184 | 266 |
7431 | 267 void gaim_log_logger_add (GaimLogLogger *logger) |
268 { | |
269 g_return_if_fail(logger); | |
270 if (g_slist_find(loggers, logger)) | |
271 return; | |
272 loggers = g_slist_append(loggers, logger); | |
273 } | |
274 | |
275 void gaim_log_logger_remove (GaimLogLogger *logger) | |
276 { | |
277 g_return_if_fail(logger); | |
278 g_slist_remove(loggers, logger); | |
4184 | 279 } |
280 | |
7431 | 281 void gaim_log_logger_set (GaimLogLogger *logger) |
4184 | 282 { |
7431 | 283 g_return_if_fail(logger); |
284 current_logger = logger; | |
7436 | 285 } |
4184 | 286 |
7431 | 287 GaimLogLogger *gaim_log_logger_get() |
288 { | |
289 return current_logger; | |
290 } | |
4184 | 291 |
7431 | 292 GList *gaim_log_logger_get_options(void) |
293 { | |
294 GSList *n; | |
295 GList *list = NULL; | |
296 GaimLogLogger *data; | |
4184 | 297 |
7431 | 298 for (n = loggers; n; n = n->next) { |
299 data = n->data; | |
300 if (!data->write) | |
301 continue; | |
7494 | 302 list = g_list_append(list, _(data->name)); |
7431 | 303 list = g_list_append(list, data->id); |
4184 | 304 } |
305 | |
7431 | 306 return list; |
307 } | |
308 | |
8573 | 309 gint gaim_log_compare(gconstpointer y, gconstpointer z) |
7431 | 310 { |
7436 | 311 const GaimLog *a = y; |
312 const GaimLog *b = z; | |
313 | |
7431 | 314 return b->time - a->time; |
315 } | |
316 | |
8898 | 317 GList *gaim_log_get_logs(GaimLogType type, const char *name, GaimAccount *account) |
7431 | 318 { |
319 GList *logs = NULL; | |
320 GSList *n; | |
321 for (n = loggers; n; n = n->next) { | |
322 GaimLogLogger *logger = n->data; | |
323 if (!logger->list) | |
324 continue; | |
8898 | 325 logs = g_list_concat(logs, logger->list(type, name, account)); |
7431 | 326 } |
7436 | 327 |
8573 | 328 return g_list_sort(logs, gaim_log_compare); |
329 } | |
330 | |
11025 | 331 gint gaim_log_set_compare(gconstpointer y, gconstpointer z) |
332 { | |
333 const GaimLogSet *a = y; | |
334 const GaimLogSet *b = z; | |
335 gint ret = 0; | |
336 | |
337 /* This logic seems weird at first... | |
338 * If either account is NULL, we pretend the accounts are | |
339 * equal. This allows us to detect duplicates that will | |
340 * exist if one logger knows the account and another | |
341 * doesn't. */ | |
342 if (a->account != NULL && b->account != NULL) { | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
343 ret = strcmp(gaim_account_get_username(a->account), gaim_account_get_username(b->account)); |
11025 | 344 if (ret != 0) |
345 return ret; | |
346 } | |
347 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
348 ret = strcmp(a->normalized_name, b->normalized_name); |
11025 | 349 if (ret != 0) |
350 return ret; | |
351 | |
352 return (gint)b->type - (gint)a->type; | |
353 } | |
354 | |
355 guint log_set_hash(gconstpointer key) | |
356 { | |
357 const GaimLogSet *set = key; | |
358 | |
359 /* The account isn't hashed because we need GaimLogSets with NULL accounts | |
360 * to be found when we search by a GaimLogSet that has a non-NULL account | |
361 * but the same type and name. */ | |
362 return g_int_hash((gint *)&set->type) + g_str_hash(set->name); | |
363 } | |
364 | |
365 gboolean log_set_equal(gconstpointer a, gconstpointer b) | |
366 { | |
367 /* I realize that the choices made for GList and GHashTable | |
368 * make sense for those data types, but I wish the comparison | |
369 * functions were compatible. */ | |
370 return !gaim_log_set_compare(a, b); | |
371 } | |
372 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
373 void log_add_log_set_to_hash(GHashTable *sets, GaimLogSet *set) |
11025 | 374 { |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
375 GaimLogSet *existing_set = g_hash_table_lookup(sets, set); |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
376 |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
377 if (existing_set == NULL) |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
378 g_hash_table_insert(sets, set, set); |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
379 else if (existing_set->account == NULL && set->account != NULL) |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
380 g_hash_table_replace(sets, set, set); |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
381 else |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
382 gaim_log_set_free(set); |
11025 | 383 } |
384 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
385 GHashTable *gaim_log_get_log_sets(void) |
11025 | 386 { |
387 GSList *n; | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
388 GHashTable *sets = g_hash_table_new_full(log_set_hash, log_set_equal, |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
389 (GDestroyNotify)gaim_log_set_free, NULL); |
11025 | 390 |
391 /* Get the log sets from all the loggers. */ | |
392 for (n = loggers; n; n = n->next) { | |
393 GaimLogLogger *logger = n->data; | |
394 | |
395 if (!logger->get_log_sets) | |
396 continue; | |
397 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
398 logger->get_log_sets(log_add_log_set_to_hash, sets); |
11025 | 399 } |
400 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
401 log_get_log_sets_common(sets); |
11025 | 402 |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
403 /* Return the GHashTable of unique GaimLogSets. */ |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
404 return sets; |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
405 } |
11025 | 406 |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
407 void gaim_log_set_free(GaimLogSet *set) |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
408 { |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
409 g_return_if_fail(set != NULL); |
11025 | 410 |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
411 g_free(set->name); |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
412 if (set->normalized_name != set->name) |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
413 g_free(set->normalized_name); |
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
414 g_free(set); |
11025 | 415 } |
416 | |
8573 | 417 GList *gaim_log_get_system_logs(GaimAccount *account) |
418 { | |
419 GList *logs = NULL; | |
420 GSList *n; | |
421 for (n = loggers; n; n = n->next) { | |
422 GaimLogLogger *logger = n->data; | |
423 if (!logger->list_syslog) | |
424 continue; | |
425 logs = g_list_concat(logs, logger->list_syslog(account)); | |
426 } | |
427 | |
428 return g_list_sort(logs, gaim_log_compare); | |
7431 | 429 } |
430 | |
431 void gaim_log_init(void) | |
7436 | 432 { |
11033
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
11025
diff
changeset
|
433 gaim_debug_register_category("log"); |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
11025
diff
changeset
|
434 |
7431 | 435 gaim_prefs_add_none("/core/logging"); |
7555 | 436 gaim_prefs_add_bool("/core/logging/log_ims", FALSE); |
437 gaim_prefs_add_bool("/core/logging/log_chats", FALSE); | |
8573 | 438 gaim_prefs_add_bool("/core/logging/log_system", FALSE); |
439 gaim_prefs_add_bool("/core/logging/log_signon_signoff", FALSE); | |
440 gaim_prefs_add_bool("/core/logging/log_idle_state", FALSE); | |
441 gaim_prefs_add_bool("/core/logging/log_away_state", FALSE); | |
442 gaim_prefs_add_bool("/core/logging/log_own_states", FALSE); | |
443 | |
7431 | 444 gaim_prefs_add_string("/core/logging/format", "txt"); |
7457 | 445 gaim_log_logger_add(&html_logger); |
7431 | 446 gaim_log_logger_add(&txt_logger); |
447 gaim_log_logger_add(&old_logger); | |
10087 | 448 gaim_prefs_connect_callback(NULL, "/core/logging/format", |
7431 | 449 logger_pref_cb, NULL); |
450 gaim_prefs_trigger_callback("/core/logging/format"); | |
8635 | 451 |
452 logsize_users = g_hash_table_new_full((GHashFunc)_gaim_logsize_user_hash, | |
453 (GEqualFunc)_gaim_logsize_user_equal, | |
454 (GDestroyNotify)_gaim_logsize_user_free_key, NULL); | |
7431 | 455 } |
456 | |
457 /**************************************************************************** | |
458 * LOGGERS ****************************************************************** | |
459 ****************************************************************************/ | |
460 | |
10822 | 461 void gaim_log_common_writer(GaimLog *log, time_t time, const char *ext) |
9763 | 462 { |
463 char date[64]; | |
10822 | 464 GaimLogCommonLoggerData *data = log->logger_data; |
9763 | 465 |
466 if(!data) { | |
467 /* This log is new */ | |
9923 | 468 char *dir, *filename, *path; |
10577 | 469 |
9923 | 470 dir = gaim_log_get_log_dir(log->type, log->name, log->account); |
10577 | 471 if (dir == NULL) |
472 return; | |
473 | |
9923 | 474 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
9763 | 475 |
476 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S", localtime(&log->time)); | |
477 | |
478 filename = g_strdup_printf("%s%s", date, ext ? ext : ""); | |
479 | |
480 path = g_build_filename(dir, filename, NULL); | |
481 g_free(dir); | |
482 g_free(filename); | |
483 | |
10822 | 484 log->logger_data = data = g_new0(GaimLogCommonLoggerData, 1); |
9763 | 485 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
486 data->file = g_fopen(path, "a"); |
9763 | 487 if (!data->file) { |
488 gaim_debug(GAIM_DEBUG_ERROR, "log", | |
9892 | 489 "Could not create log file %s\n", path); |
9763 | 490 g_free(path); |
491 return; | |
492 } | |
493 g_free(path); | |
10577 | 494 } |
9763 | 495 } |
496 | |
10822 | 497 GList *gaim_log_common_lister(GaimLogType type, const char *name, GaimAccount *account, const char *ext, GaimLogLogger *logger) |
7431 | 498 { |
499 GDir *dir; | |
500 GList *list = NULL; | |
7628 | 501 const char *filename; |
8111 | 502 char *path; |
503 | |
504 if(!account) | |
505 return NULL; | |
506 | |
9923 | 507 path = gaim_log_get_log_dir(type, name, account); |
10577 | 508 if (path == NULL) |
509 return NULL; | |
7447 | 510 |
7431 | 511 if (!(dir = g_dir_open(path, 0, NULL))) { |
512 g_free(path); | |
513 return NULL; | |
514 } | |
8898 | 515 |
7431 | 516 while ((filename = g_dir_read_name(dir))) { |
8577 | 517 if (gaim_str_has_suffix(filename, ext) && |
518 strlen(filename) == 17 + strlen(ext)) { | |
7431 | 519 GaimLog *log; |
10822 | 520 GaimLogCommonLoggerData *data; |
8577 | 521 time_t stamp = gaim_str_to_time(filename, FALSE); |
7431 | 522 |
8898 | 523 log = gaim_log_new(type, name, account, stamp); |
7431 | 524 log->logger = logger; |
10822 | 525 log->logger_data = data = g_new0(GaimLogCommonLoggerData, 1); |
7616 | 526 data->path = g_build_filename(path, filename, NULL); |
7431 | 527 list = g_list_append(list, log); |
4184 | 528 } |
529 } | |
7431 | 530 g_dir_close(dir); |
7447 | 531 g_free(path); |
7431 | 532 return list; |
533 } | |
4184 | 534 |
10822 | 535 int gaim_log_common_sizer(GaimLog *log) |
7556 | 536 { |
537 struct stat st; | |
10822 | 538 GaimLogCommonLoggerData *data = log->logger_data; |
7556 | 539 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
540 if (!data->path || g_stat(data->path, &st)) |
7556 | 541 st.st_size = 0; |
542 | |
543 return st.st_size; | |
544 } | |
545 | |
11025 | 546 /* This will build log sets for all loggers that use the common logger |
547 * functions because they use the same directory structure. */ | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
548 static void log_get_log_sets_common(GHashTable *sets) |
11025 | 549 { |
550 gchar *log_path = g_build_filename(gaim_user_dir(), "logs", NULL); | |
551 GDir *log_dir = g_dir_open(log_path, 0, NULL); | |
552 const gchar *protocol; | |
553 | |
554 if (log_dir == NULL) { | |
555 g_free(log_path); | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
556 return; |
11025 | 557 } |
558 | |
559 while ((protocol = g_dir_read_name(log_dir)) != NULL) { | |
560 gchar *protocol_path = g_build_filename(log_path, protocol, NULL); | |
561 GDir *protocol_dir; | |
562 const gchar *username; | |
563 gchar *protocol_unescaped; | |
564 GList *account_iter; | |
565 GList *accounts = NULL; | |
566 | |
567 if ((protocol_dir = g_dir_open(protocol_path, 0, NULL)) == NULL) { | |
568 g_free(protocol_path); | |
569 continue; | |
570 } | |
571 | |
572 /* Using g_strdup() to cover the one-in-a-million chance that a | |
573 * prpl's list_icon function uses gaim_unescape_filename(). */ | |
574 protocol_unescaped = g_strdup(gaim_unescape_filename(protocol)); | |
575 | |
576 /* Find all the accounts for protocol. */ | |
577 for (account_iter = gaim_accounts_get_all() ; account_iter != NULL ; account_iter = account_iter->next) { | |
578 GaimPlugin *prpl; | |
579 GaimPluginProtocolInfo *prpl_info; | |
580 | |
581 prpl = gaim_find_prpl(gaim_account_get_protocol_id((GaimAccount *)account_iter->data)); | |
582 if (!prpl) | |
583 continue; | |
584 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
585 | |
586 if (!strcmp(protocol_unescaped, prpl_info->list_icon((GaimAccount *)account_iter->data, NULL))) | |
587 accounts = g_list_append(accounts, account_iter->data); | |
588 } | |
589 g_free(protocol_unescaped); | |
590 | |
591 while ((username = g_dir_read_name(protocol_dir)) != NULL) { | |
592 gchar *username_path = g_build_filename(protocol_path, username, NULL); | |
593 GDir *username_dir; | |
594 const gchar *username_unescaped; | |
595 GaimAccount *account = NULL; | |
596 gchar *name; | |
597 | |
598 if ((username_dir = g_dir_open(username_path, 0, NULL)) == NULL) { | |
599 g_free(username_path); | |
600 continue; | |
601 } | |
602 | |
603 /* Find the account for username in the list of accounts for protocol. */ | |
604 username_unescaped = gaim_unescape_filename(username); | |
605 for (account_iter = g_list_first(accounts) ; account_iter != NULL ; account_iter = account_iter->next) { | |
606 if (!strcmp(((GaimAccount *)account_iter->data)->username, username_unescaped)) { | |
607 account = account_iter->data; | |
608 break; | |
609 } | |
610 } | |
611 | |
612 /* Don't worry about the cast, name will point to dynamically allocated memory shortly. */ | |
613 while ((name = (gchar *)g_dir_read_name(username_dir)) != NULL) { | |
614 size_t len; | |
615 GaimLogSet *set = g_new0(GaimLogSet, 1); | |
616 | |
617 /* Unescape the filename. */ | |
618 name = g_strdup(gaim_unescape_filename(name)); | |
619 | |
620 /* Get the (possibly new) length of name. */ | |
621 len = strlen(name); | |
622 | |
623 set->account = account; | |
624 set->name = name; | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
625 set->normalized_name = g_strdup(gaim_normalize(account, name)); |
11025 | 626 |
627 /* Chat for .chat or .system at the end of the name to determine the type. */ | |
628 set->type = GAIM_LOG_IM; | |
629 if (len > 7) { | |
630 gchar *tmp = &name[len - 7]; | |
631 if (!strcmp(tmp, ".system")) { | |
632 set->type = GAIM_LOG_SYSTEM; | |
633 *tmp = '\0'; | |
634 } | |
635 } | |
636 if (len > 5) { | |
637 gchar *tmp = &name[len - 5]; | |
638 if (!strcmp(tmp, ".chat")) { | |
639 set->type = GAIM_LOG_CHAT; | |
640 *tmp = '\0'; | |
641 } | |
642 } | |
643 | |
644 /* Determine if this (account, name) combination exists as a buddy. */ | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
645 set->buddy = (gaim_find_buddy(account, name) != NULL); |
11025 | 646 |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
647 log_add_log_set_to_hash(sets, set); |
11025 | 648 } |
649 g_free(username_path); | |
650 g_dir_close(username_dir); | |
651 } | |
652 g_free(protocol_path); | |
653 g_dir_close(protocol_dir); | |
654 } | |
655 g_free(log_path); | |
656 g_dir_close(log_dir); | |
657 } | |
658 | |
7431 | 659 #if 0 /* Maybe some other time. */ |
7443 | 660 /**************** |
7431 | 661 ** XML LOGGER ** |
662 ****************/ | |
663 | |
664 static const char *str_from_msg_type (GaimMessageFlags type) | |
665 { | |
7443 | 666 |
7431 | 667 return ""; |
7443 | 668 |
7431 | 669 } |
670 | |
7443 | 671 static void xml_logger_write(GaimLog *log, |
672 GaimMessageFlags type, | |
7431 | 673 const char *from, time_t time, const char *message) |
674 { | |
675 char date[64]; | |
676 char *xhtml = NULL; | |
10577 | 677 |
7431 | 678 if (!log->logger_data) { |
679 /* This log is new. We could use the loggers 'new' function, but | |
680 * creating a new file there would result in empty files in the case | |
681 * that you open a convo with someone, but don't say anything. | |
682 */ | |
9923 | 683 char *dir = gaim_log_get_log_dir(log->type, log->name, log->account); |
7431 | 684 FILE *file; |
10577 | 685 |
686 if (dir == NULL) | |
687 return; | |
688 | |
7453 | 689 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); |
7443 | 690 |
7612 | 691 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
7443 | 692 |
7431 | 693 char *filename = g_build_filename(dir, date, NULL); |
694 g_free(dir); | |
7443 | 695 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
696 log->logger_data = g_fopen(filename, "a"); |
7431 | 697 if (!log->logger_data) { |
698 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); | |
7564 | 699 g_free(filename); |
7431 | 700 return; |
701 } | |
7564 | 702 g_free(filename); |
7431 | 703 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" |
704 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); | |
7443 | 705 |
7453 | 706 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
7431 | 707 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", |
708 date, log->name, prpl); | |
709 } | |
7443 | 710 |
9923 | 711 /* if we can't write to the file, give up before we hurt ourselves */ |
712 if(!data->file) | |
713 return; | |
714 | |
7453 | 715 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
7431 | 716 gaim_markup_html_to_xhtml(message, &xhtml, NULL); |
717 if (from) | |
7443 | 718 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", |
719 str_from_msg_type(type), | |
7431 | 720 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
721 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
722 from, date, xhtml); | |
723 else | |
7443 | 724 fprintf(log->logger_data, "<message %s %s time='%s'>%s</message>\n", |
725 str_from_msg_type(type), | |
7431 | 726 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
727 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
7443 | 728 date, xhtml): |
7431 | 729 fflush(log->logger_data); |
730 g_free(xhtml); | |
7443 | 731 } |
732 | |
7431 | 733 static void xml_logger_finalize(GaimLog *log) |
734 { | |
735 if (log->logger_data) { | |
736 fprintf(log->logger_data, "</conversation>\n"); | |
737 fclose(log->logger_data); | |
738 log->logger_data = NULL; | |
739 } | |
740 } | |
7443 | 741 |
8898 | 742 static GList *xml_logger_list(GaimLogType type, const char *sn, GaimAccount *account) |
7431 | 743 { |
10822 | 744 return gaim_log_common_lister(type, sn, account, ".xml", &xml_logger); |
4184 | 745 } |
746 | |
7431 | 747 static GaimLogLogger xml_logger = { |
748 N_("XML"), "xml", | |
749 NULL, | |
750 xml_logger_write, | |
751 xml_logger_finalize, | |
752 xml_logger_list, | |
8096 | 753 NULL, |
11025 | 754 NULL, |
7431 | 755 NULL |
756 }; | |
757 #endif | |
5563
9eb5b13fd412
[gaim-migrate @ 5965]
Christian Hammond <chipx86@chipx86.com>
parents:
5560
diff
changeset
|
758 |
7431 | 759 /**************************** |
7457 | 760 ** HTML LOGGER ************* |
761 ****************************/ | |
762 | |
763 static void html_logger_write(GaimLog *log, GaimMessageFlags type, | |
764 const char *from, time_t time, const char *message) | |
765 { | |
9763 | 766 char *msg_fixed; |
7457 | 767 char date[64]; |
9613 | 768 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); |
10822 | 769 GaimLogCommonLoggerData *data = log->logger_data; |
9613 | 770 |
7618 | 771 if(!data) { |
9763 | 772 const char *prpl = |
773 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); | |
10822 | 774 gaim_log_common_writer(log, time, ".html"); |
7457 | 775 |
9763 | 776 data = log->logger_data; |
7457 | 777 |
9763 | 778 /* if we can't write to the file, give up before we hurt ourselves */ |
779 if(!data->file) | |
780 return; | |
7616 | 781 |
7457 | 782 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
11092
68652f4ad6a7
[gaim-migrate @ 13115]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
783 fprintf(data->file, "<html><head>"); |
11094
59a1ff5a4bae
[gaim-migrate @ 13119]
Richard Laager <rlaager@wiktel.com>
parents:
11092
diff
changeset
|
784 fprintf(data->file, "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">"); |
11092
68652f4ad6a7
[gaim-migrate @ 13115]
Richard Laager <rlaager@wiktel.com>
parents:
11033
diff
changeset
|
785 fprintf(data->file, "<title>"); |
7616 | 786 fprintf(data->file, "Conversation with %s at %s on %s (%s)", |
7457 | 787 log->name, date, gaim_account_get_username(log->account), prpl); |
7616 | 788 fprintf(data->file, "</title></head><body>"); |
789 fprintf(data->file, | |
7457 | 790 "<h3>Conversation with %s at %s on %s (%s)</h3>\n", |
791 log->name, date, gaim_account_get_username(log->account), prpl); | |
9763 | 792 |
7457 | 793 } |
7623 | 794 |
9892 | 795 /* if we can't write to the file, give up before we hurt ourselves */ |
796 if(!data->file) | |
797 return; | |
798 | |
7882 | 799 gaim_markup_html_to_xhtml(message, &msg_fixed, NULL); |
800 | |
8577 | 801 if(log->type == GAIM_LOG_SYSTEM){ |
9592 | 802 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); |
8577 | 803 fprintf(data->file, "---- %s @ %s ----<br/>\n", msg_fixed, date); |
804 } else { | |
805 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); | |
806 if (type & GAIM_MESSAGE_SYSTEM) | |
807 fprintf(data->file, "<font size=\"2\">(%s)</font><b> %s</b><br/>\n", date, msg_fixed); | |
808 else if (type & GAIM_MESSAGE_WHISPER) | |
809 fprintf(data->file, "<font color=\"#6C2585\"><font size=\"2\">(%s)</font><b> %s:</b></font> %s<br/>\n", | |
810 date, from, msg_fixed); | |
811 else if (type & GAIM_MESSAGE_AUTO_RESP) { | |
812 if (type & GAIM_MESSAGE_SEND) | |
813 fprintf(data->file, _("<font color=\"#16569E\"><font size=\"2\">(%s)</font> <b>%s <AUTO-REPLY>:</b></font> %s<br/>\n"), date, from, msg_fixed); | |
814 else if (type & GAIM_MESSAGE_RECV) | |
815 fprintf(data->file, _("<font color=\"#A82F2F\"><font size=\"2\">(%s)</font> <b>%s <AUTO-REPLY>:</b></font> %s<br/>\n"), date, from, msg_fixed); | |
816 } else if (type & GAIM_MESSAGE_RECV) { | |
817 if(gaim_message_meify(msg_fixed, -1)) | |
10735
a0edd89ddb83
[gaim-migrate @ 12337]
Luke Schierer <lschiere@pidgin.im>
parents:
10732
diff
changeset
|
818 fprintf(data->file, "<font color=\"#062585\"><font size=\"2\">(%s)</font> <b>***%s</b></font> %s<br/>\n", |
10645 | 819 date, from, msg_fixed); |
8577 | 820 else |
10645 | 821 fprintf(data->file, "<font color=\"#A82F2F\"><font size=\"2\">(%s)</font> <b>%s:</b></font> %s<br/>\n", |
822 date, from, msg_fixed); | |
8577 | 823 } else if (type & GAIM_MESSAGE_SEND) { |
824 if(gaim_message_meify(msg_fixed, -1)) | |
10735
a0edd89ddb83
[gaim-migrate @ 12337]
Luke Schierer <lschiere@pidgin.im>
parents:
10732
diff
changeset
|
825 fprintf(data->file, "<font color=\"#062585\"><font size=\"2\">(%s)</font> <b>***%s</b></font> %s<br/>\n", |
10645 | 826 date, from, msg_fixed); |
8577 | 827 else |
10645 | 828 fprintf(data->file, "<font color=\"#16569E\"><font size=\"2\">(%s)</font> <b>%s:</b></font> %s<br/>\n", |
829 date, from, msg_fixed); | |
8577 | 830 } |
7564 | 831 } |
8573 | 832 |
7882 | 833 g_free(msg_fixed); |
7616 | 834 fflush(data->file); |
7457 | 835 } |
836 | |
837 static void html_logger_finalize(GaimLog *log) | |
838 { | |
10822 | 839 GaimLogCommonLoggerData *data = log->logger_data; |
7616 | 840 if (data) { |
841 if(data->file) { | |
842 fprintf(data->file, "</body></html>"); | |
843 fclose(data->file); | |
844 } | |
845 g_free(data->path); | |
7752 | 846 g_free(data); |
7463 | 847 } |
7457 | 848 } |
849 | |
8898 | 850 static GList *html_logger_list(GaimLogType type, const char *sn, GaimAccount *account) |
7457 | 851 { |
10822 | 852 return gaim_log_common_lister(type, sn, account, ".html", &html_logger); |
7457 | 853 } |
854 | |
8573 | 855 static GList *html_logger_list_syslog(GaimAccount *account) |
856 { | |
10822 | 857 return gaim_log_common_lister(GAIM_LOG_SYSTEM, ".system", account, ".html", &html_logger); |
8573 | 858 } |
859 | |
7457 | 860 static char *html_logger_read(GaimLog *log, GaimLogReadFlags *flags) |
861 { | |
862 char *read, *minus_header; | |
10822 | 863 GaimLogCommonLoggerData *data = log->logger_data; |
7457 | 864 *flags = GAIM_LOG_READ_NO_NEWLINE; |
7616 | 865 if (!data || !data->path) |
866 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
867 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7457 | 868 minus_header = strchr(read, '\n'); |
869 if (!minus_header) | |
870 minus_header = g_strdup(read); | |
871 else | |
872 minus_header = g_strdup(minus_header + 1); | |
873 g_free(read); | |
874 return minus_header; | |
875 } | |
8578 | 876 return g_strdup_printf(_("<font color=\"red\"><b>Could not read file: %s</b></font>"), data->path); |
7457 | 877 } |
878 | |
879 static GaimLogLogger html_logger = { | |
880 N_("HTML"), "html", | |
9819 | 881 NULL, |
7457 | 882 html_logger_write, |
883 html_logger_finalize, | |
884 html_logger_list, | |
7556 | 885 html_logger_read, |
10822 | 886 gaim_log_common_sizer, |
8573 | 887 NULL, |
11025 | 888 html_logger_list_syslog, |
889 NULL | |
7457 | 890 }; |
891 | |
892 | |
893 | |
894 | |
895 /**************************** | |
7431 | 896 ** PLAIN TEXT LOGGER ******* |
897 ****************************/ | |
4184 | 898 |
7436 | 899 static void txt_logger_write(GaimLog *log, |
900 GaimMessageFlags type, | |
7431 | 901 const char *from, time_t time, const char *message) |
902 { | |
903 char date[64]; | |
9763 | 904 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); |
10822 | 905 GaimLogCommonLoggerData *data = log->logger_data; |
9763 | 906 char *stripped = NULL; |
907 | |
908 if(!data) { | |
7431 | 909 /* This log is new. We could use the loggers 'new' function, but |
910 * creating a new file there would result in empty files in the case | |
911 * that you open a convo with someone, but don't say anything. | |
912 */ | |
9763 | 913 const char *prpl = |
914 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); | |
10822 | 915 gaim_log_common_writer(log, time, ".txt"); |
8898 | 916 |
9763 | 917 data = log->logger_data; |
7436 | 918 |
9763 | 919 /* if we can't write to the file, give up before we hurt ourselves */ |
920 if(!data->file) | |
921 return; | |
7616 | 922 |
7453 | 923 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
7616 | 924 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", |
7431 | 925 log->name, date, gaim_account_get_username(log->account), prpl); |
926 } | |
7436 | 927 |
7623 | 928 /* if we can't write to the file, give up before we hurt ourselves */ |
929 if(!data->file) | |
930 return; | |
931 | |
8573 | 932 stripped = gaim_markup_strip_html(message); |
933 | |
934 if(log->type == GAIM_LOG_SYSTEM){ | |
9592 | 935 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); |
8573 | 936 fprintf(data->file, "---- %s @ %s ----\n", stripped, date); |
937 } else { | |
938 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); | |
939 if (type & GAIM_MESSAGE_SEND || | |
940 type & GAIM_MESSAGE_RECV) { | |
941 if (type & GAIM_MESSAGE_AUTO_RESP) { | |
942 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date, | |
943 from, stripped); | |
944 } else { | |
945 if(gaim_message_meify(stripped, -1)) | |
946 fprintf(data->file, "(%s) ***%s %s\n", date, from, | |
947 stripped); | |
948 else | |
949 fprintf(data->file, "(%s) %s: %s\n", date, from, | |
950 stripped); | |
951 } | |
952 } else if (type & GAIM_MESSAGE_SYSTEM) | |
953 fprintf(data->file, "(%s) %s\n", date, stripped); | |
954 else if (type & GAIM_MESSAGE_NO_LOG) { | |
955 /* This shouldn't happen */ | |
956 g_free(stripped); | |
957 return; | |
958 } else if (type & GAIM_MESSAGE_WHISPER) | |
959 fprintf(data->file, "(%s) *%s* %s", date, from, stripped); | |
960 else | |
961 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "", | |
962 from ? ":" : "", stripped); | |
963 } | |
964 | |
965 fflush(data->file); | |
966 g_free(stripped); | |
7431 | 967 } |
968 | |
969 static void txt_logger_finalize(GaimLog *log) | |
970 { | |
10822 | 971 GaimLogCommonLoggerData *data = log->logger_data; |
7616 | 972 if (data) { |
973 if(data->file) | |
974 fclose(data->file); | |
975 if(data->path) | |
976 g_free(data->path); | |
7752 | 977 g_free(data); |
7616 | 978 } |
7431 | 979 } |
980 | |
8898 | 981 static GList *txt_logger_list(GaimLogType type, const char *sn, GaimAccount *account) |
7431 | 982 { |
10822 | 983 return gaim_log_common_lister(type, sn, account, ".txt", &txt_logger); |
7431 | 984 } |
985 | |
8573 | 986 static GList *txt_logger_list_syslog(GaimAccount *account) |
987 { | |
10822 | 988 return gaim_log_common_lister(GAIM_LOG_SYSTEM, ".system", account, ".txt", &txt_logger); |
8573 | 989 } |
990 | |
7431 | 991 static char *txt_logger_read(GaimLog *log, GaimLogReadFlags *flags) |
992 { | |
8517 | 993 char *read, *minus_header, *minus_header2; |
10822 | 994 GaimLogCommonLoggerData *data = log->logger_data; |
7457 | 995 *flags = 0; |
7616 | 996 if (!data || !data->path) |
997 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
998 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7431 | 999 minus_header = strchr(read, '\n'); |
1000 if (!minus_header) | |
1001 minus_header = g_strdup(read); | |
7436 | 1002 else |
7431 | 1003 minus_header = g_strdup(minus_header + 1); |
1004 g_free(read); | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10645
diff
changeset
|
1005 minus_header2 = g_markup_escape_text(minus_header, -1); |
8517 | 1006 g_free(minus_header); |
1007 return minus_header2; | |
7431 | 1008 } |
8578 | 1009 return g_strdup_printf(_("<font color=\"red\"><b>Could not read file: %s</b></font>"), data->path); |
7436 | 1010 } |
7431 | 1011 |
1012 static GaimLogLogger txt_logger = { | |
1013 N_("Plain text"), "txt", | |
9819 | 1014 NULL, |
7431 | 1015 txt_logger_write, |
1016 txt_logger_finalize, | |
1017 txt_logger_list, | |
7556 | 1018 txt_logger_read, |
10822 | 1019 gaim_log_common_sizer, |
8573 | 1020 NULL, |
11025 | 1021 txt_logger_list_syslog, |
1022 NULL | |
7431 | 1023 }; |
1024 | |
1025 /**************** | |
1026 * OLD LOGGER *** | |
1027 ****************/ | |
1028 | |
1029 /* The old logger doesn't write logs, only reads them. This is to include | |
1030 * old logs in the log viewer transparently. | |
1031 */ | |
1032 | |
1033 struct old_logger_data { | |
7764 | 1034 GaimStringref *pathref; |
7431 | 1035 int offset; |
1036 int length; | |
1037 }; | |
1038 | |
8898 | 1039 static GList *old_logger_list(GaimLogType type, const char *sn, GaimAccount *account) |
7431 | 1040 { |
1041 FILE *file; | |
1042 char buf[BUF_LONG]; | |
1043 struct tm tm; | |
7761 | 1044 char month[4]; |
7431 | 1045 struct old_logger_data *data = NULL; |
1046 char *logfile = g_strdup_printf("%s.log", gaim_normalize(account, sn)); | |
7764 | 1047 char *pathstr = g_build_filename(gaim_user_dir(), "logs", logfile, NULL); |
1048 GaimStringref *pathref = gaim_stringref_new(pathstr); | |
7431 | 1049 char *newlog; |
7761 | 1050 int logfound = 0; |
1051 int lastoff = 0; | |
1052 int newlen; | |
7791 | 1053 time_t lasttime = 0; |
7431 | 1054 |
1055 GaimLog *log = NULL; | |
1056 GList *list = NULL; | |
1057 | |
7473 | 1058 g_free(logfile); |
7764 | 1059 g_free(pathstr); |
7473 | 1060 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
1061 if (!(file = g_fopen(gaim_stringref_value(pathref), "rb"))) { |
7764 | 1062 gaim_stringref_unref(pathref); |
7431 | 1063 return NULL; |
7447 | 1064 } |
7436 | 1065 |
7431 | 1066 while (fgets(buf, BUF_LONG, file)) { |
1067 if ((newlog = strstr(buf, "---- New C"))) { | |
1068 int length; | |
1069 int offset; | |
1070 char convostart[32]; | |
1071 char *temp = strchr(buf, '@'); | |
7436 | 1072 |
7431 | 1073 if (temp == NULL || strlen(temp) < 2) |
1074 continue; | |
7436 | 1075 |
7431 | 1076 temp++; |
1077 length = strcspn(temp, "-"); | |
1078 if (length > 31) length = 31; | |
7436 | 1079 |
7431 | 1080 offset = ftell(file); |
7436 | 1081 |
7761 | 1082 if (logfound) { |
1083 newlen = offset - lastoff - length; | |
7436 | 1084 if(strstr(buf, "----</H3><BR>")) { |
7761 | 1085 newlen -= |
1086 sizeof("<HR><BR><H3 Align=Center> ---- New Conversation @ ") + | |
1087 sizeof("----</H3><BR>") - 2; | |
7436 | 1088 } else { |
7761 | 1089 newlen -= |
1090 sizeof("---- New Conversation @ ") + sizeof("----") - 2; | |
7436 | 1091 } |
1092 | |
7461 | 1093 if(strchr(buf, '\r')) |
7770 | 1094 newlen--; |
7461 | 1095 |
7761 | 1096 if (newlen != 0) { |
1097 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
1098 log->logger = &old_logger; | |
1099 log->time = lasttime; | |
1100 data = g_new0(struct old_logger_data, 1); | |
1101 data->offset = lastoff; | |
1102 data->length = newlen; | |
7764 | 1103 data->pathref = gaim_stringref_ref(pathref); |
7761 | 1104 log->logger_data = data; |
7431 | 1105 list = g_list_append(list, log); |
7761 | 1106 } |
7431 | 1107 } |
1108 | |
7761 | 1109 logfound = 1; |
1110 lastoff = offset; | |
7436 | 1111 |
7431 | 1112 g_snprintf(convostart, length, "%s", temp); |
7676 | 1113 sscanf(convostart, "%*s %s %d %d:%d:%d %d", |
1114 month, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &tm.tm_year); | |
1115 /* Ugly hack, in case current locale is not English */ | |
1116 if (strcmp(month, "Jan") == 0) { | |
1117 tm.tm_mon= 0; | |
1118 } else if (strcmp(month, "Feb") == 0) { | |
1119 tm.tm_mon = 1; | |
1120 } else if (strcmp(month, "Mar") == 0) { | |
1121 tm.tm_mon = 2; | |
1122 } else if (strcmp(month, "Apr") == 0) { | |
1123 tm.tm_mon = 3; | |
1124 } else if (strcmp(month, "May") == 0) { | |
1125 tm.tm_mon = 4; | |
1126 } else if (strcmp(month, "Jun") == 0) { | |
1127 tm.tm_mon = 5; | |
1128 } else if (strcmp(month, "Jul") == 0) { | |
1129 tm.tm_mon = 6; | |
1130 } else if (strcmp(month, "Aug") == 0) { | |
1131 tm.tm_mon = 7; | |
1132 } else if (strcmp(month, "Sep") == 0) { | |
1133 tm.tm_mon = 8; | |
1134 } else if (strcmp(month, "Oct") == 0) { | |
1135 tm.tm_mon = 9; | |
1136 } else if (strcmp(month, "Nov") == 0) { | |
1137 tm.tm_mon = 10; | |
1138 } else if (strcmp(month, "Dec") == 0) { | |
1139 tm.tm_mon = 11; | |
1140 } | |
1141 tm.tm_year -= 1900; | |
7761 | 1142 lasttime = mktime(&tm); |
4184 | 1143 } |
1144 } | |
7613 | 1145 |
7761 | 1146 if (logfound) { |
1147 if ((newlen = ftell(file) - lastoff) != 0) { | |
1148 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
1149 log->logger = &old_logger; | |
1150 log->time = lasttime; | |
1151 data = g_new0(struct old_logger_data, 1); | |
1152 data->offset = lastoff; | |
1153 data->length = newlen; | |
7764 | 1154 data->pathref = gaim_stringref_ref(pathref); |
7761 | 1155 log->logger_data = data; |
7613 | 1156 list = g_list_append(list, log); |
7761 | 1157 } |
7613 | 1158 } |
1159 | |
7764 | 1160 gaim_stringref_unref(pathref); |
7431 | 1161 fclose(file); |
1162 return list; | |
4184 | 1163 } |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
1164 |
8898 | 1165 static int old_logger_total_size(GaimLogType type, const char *name, GaimAccount *account) |
8096 | 1166 { |
1167 char *logfile = g_strdup_printf("%s.log", gaim_normalize(account, name)); | |
1168 char *pathstr = g_build_filename(gaim_user_dir(), "logs", logfile, NULL); | |
1169 int size; | |
1170 struct stat st; | |
1171 | |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
1172 if (g_stat(pathstr, &st)) |
8096 | 1173 size = 0; |
1174 else | |
1175 size = st.st_size; | |
1176 | |
1177 g_free(logfile); | |
1178 g_free(pathstr); | |
1179 | |
1180 return size; | |
1181 } | |
1182 | |
7616 | 1183 static char * old_logger_read (GaimLog *log, GaimLogReadFlags *flags) |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
1184 { |
7431 | 1185 struct old_logger_data *data = log->logger_data; |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
1186 FILE *file = g_fopen(gaim_stringref_value(data->pathref), "rb"); |
10906 | 1187 char *tmp, *read = g_malloc(data->length + 1); |
7431 | 1188 fseek(file, data->offset, SEEK_SET); |
1189 fread(read, data->length, 1, file); | |
8370 | 1190 fclose(file); |
7431 | 1191 read[data->length] = '\0'; |
7436 | 1192 *flags = 0; |
1193 if(strstr(read, "<BR>")) | |
1194 *flags |= GAIM_LOG_READ_NO_NEWLINE; | |
10906 | 1195 else { |
1196 tmp = g_markup_escape_text(read, -1); | |
1197 g_free(read); | |
1198 read = tmp; | |
1199 } | |
7431 | 1200 return read; |
1201 } | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
1202 |
7616 | 1203 static int old_logger_size (GaimLog *log) |
7556 | 1204 { |
1205 struct old_logger_data *data = log->logger_data; | |
7616 | 1206 return data ? data->length : 0; |
1207 } | |
1208 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
1209 static void old_logger_get_log_sets(GaimLogSetCallback cb, GHashTable *sets) |
11025 | 1210 { |
1211 char *log_path = g_build_filename(gaim_user_dir(), "logs", NULL); | |
1212 GDir *log_dir = g_dir_open(log_path, 0, NULL); | |
1213 gchar *name; | |
1214 GaimBlistNode *gnode, *cnode, *bnode; | |
1215 | |
1216 g_free(log_path); | |
1217 if (log_dir == NULL) | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
1218 return; |
11025 | 1219 |
1220 /* Don't worry about the cast, name will be filled with a dynamically allocated data shortly. */ | |
1221 while ((name = (gchar *)g_dir_read_name(log_dir)) != NULL) { | |
1222 size_t len; | |
1223 gchar *ext; | |
1224 GaimLogSet *set; | |
1225 gboolean found = FALSE; | |
1226 | |
1227 /* Unescape the filename. */ | |
1228 name = g_strdup(gaim_unescape_filename(name)); | |
1229 | |
1230 /* Get the (possibly new) length of name. */ | |
1231 len = strlen(name); | |
1232 | |
1233 if (len < 5) { | |
1234 g_free(name); | |
1235 continue; | |
1236 } | |
1237 | |
1238 /* Make sure we're dealing with a log file. */ | |
1239 ext = &name[len - 4]; | |
1240 if (strcmp(ext, ".log")) { | |
1241 g_free(name); | |
1242 continue; | |
1243 } | |
1244 | |
1245 set = g_new0(GaimLogSet, 1); | |
1246 | |
1247 /* Chat for .chat at the end of the name to determine the type. */ | |
1248 *ext = '\0'; | |
1249 set->type = GAIM_LOG_IM; | |
1250 if (len > 9) { | |
1251 char *tmp = &name[len - 9]; | |
1252 if (!strcmp(tmp, ".chat")) { | |
1253 set->type = GAIM_LOG_CHAT; | |
1254 *tmp = '\0'; | |
1255 } | |
1256 } | |
1257 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
1258 set->name = set->normalized_name = name; |
11025 | 1259 |
1260 /* Search the buddy list to find the account and to determine if this is a buddy. */ | |
1261 for (gnode = gaim_get_blist()->root; !found && gnode != NULL; gnode = gnode->next) | |
1262 { | |
1263 if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
1264 continue; | |
1265 | |
1266 for (cnode = gnode->child; !found && cnode != NULL; cnode = cnode->next) | |
1267 { | |
1268 if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) | |
1269 continue; | |
1270 | |
1271 for (bnode = cnode->child; !found && bnode != NULL; bnode = bnode->next) | |
1272 { | |
1273 GaimBuddy *buddy = (GaimBuddy *)bnode; | |
1274 | |
1275 if (!strcmp(buddy->name, name)) { | |
1276 set->account = buddy->account; | |
1277 set->buddy = TRUE; | |
1278 found = TRUE; | |
1279 } | |
1280 } | |
1281 } | |
1282 } | |
1283 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
1284 cb(sets, set); |
11025 | 1285 } |
1286 g_dir_close(log_dir); | |
1287 } | |
1288 | |
7616 | 1289 static void old_logger_finalize(GaimLog *log) |
1290 { | |
1291 struct old_logger_data *data = log->logger_data; | |
7764 | 1292 gaim_stringref_unref(data->pathref); |
7616 | 1293 g_free(data); |
7556 | 1294 } |
1295 | |
7431 | 1296 static GaimLogLogger old_logger = { |
1297 "old logger", "old", | |
7616 | 1298 NULL, NULL, |
1299 old_logger_finalize, | |
7431 | 1300 old_logger_list, |
7616 | 1301 old_logger_read, |
8096 | 1302 old_logger_size, |
8573 | 1303 old_logger_total_size, |
11025 | 1304 NULL, |
1305 old_logger_get_log_sets | |
7431 | 1306 }; |