Mercurial > pidgin
annotate src/log.c @ 11261:b53606580f68
[gaim-migrate @ 13439]
Patch #1226486 from Levi Bard
Fixes bug #1224178
If you change the topic in a chat room and that topic change is rejected, the
topic field is wrong -- it shows the new topic even thought it didn't get set.
This patch resets the GUI's topic immediately when you hit enter. Then, if the
topic change is successful, the server will echo the topic change back to us
and we'll update the GUI to the new topic.
The only question is, does the server always echo the topic back to us? From the
core's point of view, I'm ready to assume yes. It's the case for both IRC and
Jabber*. If someone could test changing a topic in SILC or Zephyr, that'd be
great. If servers using those protocols do not echo the topic back, the prpl
will have to fake it as appropriate.
* I didn't actually test on Jabber, but Nathan said the server will echo the
topic change back. If it's broken, let me know.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 14 Aug 2005 06:55:57 +0000 |
parents | bb0d7b719af2 |
children | ef9280fdc511 |
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 { |
7431 | 433 gaim_prefs_add_none("/core/logging"); |
7555 | 434 gaim_prefs_add_bool("/core/logging/log_ims", FALSE); |
435 gaim_prefs_add_bool("/core/logging/log_chats", FALSE); | |
8573 | 436 gaim_prefs_add_bool("/core/logging/log_system", FALSE); |
437 gaim_prefs_add_bool("/core/logging/log_signon_signoff", FALSE); | |
438 gaim_prefs_add_bool("/core/logging/log_idle_state", FALSE); | |
439 gaim_prefs_add_bool("/core/logging/log_away_state", FALSE); | |
440 gaim_prefs_add_bool("/core/logging/log_own_states", FALSE); | |
441 | |
7431 | 442 gaim_prefs_add_string("/core/logging/format", "txt"); |
7457 | 443 gaim_log_logger_add(&html_logger); |
7431 | 444 gaim_log_logger_add(&txt_logger); |
445 gaim_log_logger_add(&old_logger); | |
10087 | 446 gaim_prefs_connect_callback(NULL, "/core/logging/format", |
7431 | 447 logger_pref_cb, NULL); |
448 gaim_prefs_trigger_callback("/core/logging/format"); | |
8635 | 449 |
450 logsize_users = g_hash_table_new_full((GHashFunc)_gaim_logsize_user_hash, | |
451 (GEqualFunc)_gaim_logsize_user_equal, | |
452 (GDestroyNotify)_gaim_logsize_user_free_key, NULL); | |
7431 | 453 } |
454 | |
455 /**************************************************************************** | |
456 * LOGGERS ****************************************************************** | |
457 ****************************************************************************/ | |
458 | |
10822 | 459 void gaim_log_common_writer(GaimLog *log, time_t time, const char *ext) |
9763 | 460 { |
461 char date[64]; | |
10822 | 462 GaimLogCommonLoggerData *data = log->logger_data; |
9763 | 463 |
464 if(!data) { | |
465 /* This log is new */ | |
9923 | 466 char *dir, *filename, *path; |
10577 | 467 |
9923 | 468 dir = gaim_log_get_log_dir(log->type, log->name, log->account); |
10577 | 469 if (dir == NULL) |
470 return; | |
471 | |
9923 | 472 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
9763 | 473 |
474 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S", localtime(&log->time)); | |
475 | |
476 filename = g_strdup_printf("%s%s", date, ext ? ext : ""); | |
477 | |
478 path = g_build_filename(dir, filename, NULL); | |
479 g_free(dir); | |
480 g_free(filename); | |
481 | |
10822 | 482 log->logger_data = data = g_new0(GaimLogCommonLoggerData, 1); |
9763 | 483 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
484 data->file = g_fopen(path, "a"); |
9763 | 485 if (!data->file) { |
486 gaim_debug(GAIM_DEBUG_ERROR, "log", | |
9892 | 487 "Could not create log file %s\n", path); |
9763 | 488 g_free(path); |
489 return; | |
490 } | |
491 g_free(path); | |
10577 | 492 } |
9763 | 493 } |
494 | |
10822 | 495 GList *gaim_log_common_lister(GaimLogType type, const char *name, GaimAccount *account, const char *ext, GaimLogLogger *logger) |
7431 | 496 { |
497 GDir *dir; | |
498 GList *list = NULL; | |
7628 | 499 const char *filename; |
8111 | 500 char *path; |
501 | |
502 if(!account) | |
503 return NULL; | |
504 | |
9923 | 505 path = gaim_log_get_log_dir(type, name, account); |
10577 | 506 if (path == NULL) |
507 return NULL; | |
7447 | 508 |
7431 | 509 if (!(dir = g_dir_open(path, 0, NULL))) { |
510 g_free(path); | |
511 return NULL; | |
512 } | |
8898 | 513 |
7431 | 514 while ((filename = g_dir_read_name(dir))) { |
8577 | 515 if (gaim_str_has_suffix(filename, ext) && |
516 strlen(filename) == 17 + strlen(ext)) { | |
7431 | 517 GaimLog *log; |
10822 | 518 GaimLogCommonLoggerData *data; |
8577 | 519 time_t stamp = gaim_str_to_time(filename, FALSE); |
7431 | 520 |
8898 | 521 log = gaim_log_new(type, name, account, stamp); |
7431 | 522 log->logger = logger; |
10822 | 523 log->logger_data = data = g_new0(GaimLogCommonLoggerData, 1); |
7616 | 524 data->path = g_build_filename(path, filename, NULL); |
7431 | 525 list = g_list_append(list, log); |
4184 | 526 } |
527 } | |
7431 | 528 g_dir_close(dir); |
7447 | 529 g_free(path); |
7431 | 530 return list; |
531 } | |
4184 | 532 |
10822 | 533 int gaim_log_common_sizer(GaimLog *log) |
7556 | 534 { |
535 struct stat st; | |
10822 | 536 GaimLogCommonLoggerData *data = log->logger_data; |
7556 | 537 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
538 if (!data->path || g_stat(data->path, &st)) |
7556 | 539 st.st_size = 0; |
540 | |
541 return st.st_size; | |
542 } | |
543 | |
11025 | 544 /* This will build log sets for all loggers that use the common logger |
545 * functions because they use the same directory structure. */ | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
546 static void log_get_log_sets_common(GHashTable *sets) |
11025 | 547 { |
548 gchar *log_path = g_build_filename(gaim_user_dir(), "logs", NULL); | |
549 GDir *log_dir = g_dir_open(log_path, 0, NULL); | |
550 const gchar *protocol; | |
551 | |
552 if (log_dir == NULL) { | |
553 g_free(log_path); | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
554 return; |
11025 | 555 } |
556 | |
557 while ((protocol = g_dir_read_name(log_dir)) != NULL) { | |
558 gchar *protocol_path = g_build_filename(log_path, protocol, NULL); | |
559 GDir *protocol_dir; | |
560 const gchar *username; | |
561 gchar *protocol_unescaped; | |
562 GList *account_iter; | |
563 GList *accounts = NULL; | |
564 | |
565 if ((protocol_dir = g_dir_open(protocol_path, 0, NULL)) == NULL) { | |
566 g_free(protocol_path); | |
567 continue; | |
568 } | |
569 | |
570 /* Using g_strdup() to cover the one-in-a-million chance that a | |
571 * prpl's list_icon function uses gaim_unescape_filename(). */ | |
572 protocol_unescaped = g_strdup(gaim_unescape_filename(protocol)); | |
573 | |
574 /* Find all the accounts for protocol. */ | |
575 for (account_iter = gaim_accounts_get_all() ; account_iter != NULL ; account_iter = account_iter->next) { | |
576 GaimPlugin *prpl; | |
577 GaimPluginProtocolInfo *prpl_info; | |
578 | |
579 prpl = gaim_find_prpl(gaim_account_get_protocol_id((GaimAccount *)account_iter->data)); | |
580 if (!prpl) | |
581 continue; | |
582 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
583 | |
584 if (!strcmp(protocol_unescaped, prpl_info->list_icon((GaimAccount *)account_iter->data, NULL))) | |
585 accounts = g_list_append(accounts, account_iter->data); | |
586 } | |
587 g_free(protocol_unescaped); | |
588 | |
589 while ((username = g_dir_read_name(protocol_dir)) != NULL) { | |
590 gchar *username_path = g_build_filename(protocol_path, username, NULL); | |
591 GDir *username_dir; | |
592 const gchar *username_unescaped; | |
593 GaimAccount *account = NULL; | |
594 gchar *name; | |
595 | |
596 if ((username_dir = g_dir_open(username_path, 0, NULL)) == NULL) { | |
597 g_free(username_path); | |
598 continue; | |
599 } | |
600 | |
601 /* Find the account for username in the list of accounts for protocol. */ | |
602 username_unescaped = gaim_unescape_filename(username); | |
603 for (account_iter = g_list_first(accounts) ; account_iter != NULL ; account_iter = account_iter->next) { | |
604 if (!strcmp(((GaimAccount *)account_iter->data)->username, username_unescaped)) { | |
605 account = account_iter->data; | |
606 break; | |
607 } | |
608 } | |
609 | |
610 /* Don't worry about the cast, name will point to dynamically allocated memory shortly. */ | |
611 while ((name = (gchar *)g_dir_read_name(username_dir)) != NULL) { | |
612 size_t len; | |
613 GaimLogSet *set = g_new0(GaimLogSet, 1); | |
614 | |
615 /* Unescape the filename. */ | |
616 name = g_strdup(gaim_unescape_filename(name)); | |
617 | |
618 /* Get the (possibly new) length of name. */ | |
619 len = strlen(name); | |
620 | |
621 set->account = account; | |
622 set->name = name; | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
623 set->normalized_name = g_strdup(gaim_normalize(account, name)); |
11025 | 624 |
625 /* Chat for .chat or .system at the end of the name to determine the type. */ | |
626 set->type = GAIM_LOG_IM; | |
627 if (len > 7) { | |
628 gchar *tmp = &name[len - 7]; | |
629 if (!strcmp(tmp, ".system")) { | |
630 set->type = GAIM_LOG_SYSTEM; | |
631 *tmp = '\0'; | |
632 } | |
633 } | |
634 if (len > 5) { | |
635 gchar *tmp = &name[len - 5]; | |
636 if (!strcmp(tmp, ".chat")) { | |
637 set->type = GAIM_LOG_CHAT; | |
638 *tmp = '\0'; | |
639 } | |
640 } | |
641 | |
642 /* Determine if this (account, name) combination exists as a buddy. */ | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
643 set->buddy = (gaim_find_buddy(account, name) != NULL); |
11025 | 644 |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
645 log_add_log_set_to_hash(sets, set); |
11025 | 646 } |
647 g_free(username_path); | |
648 g_dir_close(username_dir); | |
649 } | |
650 g_free(protocol_path); | |
651 g_dir_close(protocol_dir); | |
652 } | |
653 g_free(log_path); | |
654 g_dir_close(log_dir); | |
655 } | |
656 | |
7431 | 657 #if 0 /* Maybe some other time. */ |
7443 | 658 /**************** |
7431 | 659 ** XML LOGGER ** |
660 ****************/ | |
661 | |
662 static const char *str_from_msg_type (GaimMessageFlags type) | |
663 { | |
7443 | 664 |
7431 | 665 return ""; |
7443 | 666 |
7431 | 667 } |
668 | |
7443 | 669 static void xml_logger_write(GaimLog *log, |
670 GaimMessageFlags type, | |
7431 | 671 const char *from, time_t time, const char *message) |
672 { | |
673 char date[64]; | |
674 char *xhtml = NULL; | |
10577 | 675 |
7431 | 676 if (!log->logger_data) { |
677 /* This log is new. We could use the loggers 'new' function, but | |
678 * creating a new file there would result in empty files in the case | |
679 * that you open a convo with someone, but don't say anything. | |
680 */ | |
9923 | 681 char *dir = gaim_log_get_log_dir(log->type, log->name, log->account); |
7431 | 682 FILE *file; |
10577 | 683 |
684 if (dir == NULL) | |
685 return; | |
686 | |
7453 | 687 strftime(date, sizeof(date), "%Y-%m-%d.%H%M%S.xml", localtime(&log->time)); |
7443 | 688 |
7612 | 689 gaim_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR); |
7443 | 690 |
7431 | 691 char *filename = g_build_filename(dir, date, NULL); |
692 g_free(dir); | |
7443 | 693 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
694 log->logger_data = g_fopen(filename, "a"); |
7431 | 695 if (!log->logger_data) { |
696 gaim_debug(GAIM_DEBUG_ERROR, "log", "Could not create log file %s\n", filename); | |
7564 | 697 g_free(filename); |
7431 | 698 return; |
699 } | |
7564 | 700 g_free(filename); |
7431 | 701 fprintf(log->logger_data, "<?xml version='1.0' encoding='UTF-8' ?>\n" |
702 "<?xml-stylesheet href='file:///usr/src/web/htdocs/log-stylesheet.xsl' type='text/xml' ?>\n"); | |
7443 | 703 |
7453 | 704 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
7431 | 705 fprintf(log->logger_data, "<conversation time='%s' screenname='%s' protocol='%s'>\n", |
706 date, log->name, prpl); | |
707 } | |
7443 | 708 |
9923 | 709 /* if we can't write to the file, give up before we hurt ourselves */ |
710 if(!data->file) | |
711 return; | |
712 | |
7453 | 713 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); |
7431 | 714 gaim_markup_html_to_xhtml(message, &xhtml, NULL); |
715 if (from) | |
7443 | 716 fprintf(log->logger_data, "<message %s %s from='%s' time='%s'>%s</message>\n", |
717 str_from_msg_type(type), | |
7431 | 718 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
719 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
720 from, date, xhtml); | |
721 else | |
7443 | 722 fprintf(log->logger_data, "<message %s %s time='%s'>%s</message>\n", |
723 str_from_msg_type(type), | |
7431 | 724 type & GAIM_MESSAGE_SEND ? "direction='sent'" : |
725 type & GAIM_MESSAGE_RECV ? "direction='received'" : "", | |
7443 | 726 date, xhtml): |
7431 | 727 fflush(log->logger_data); |
728 g_free(xhtml); | |
7443 | 729 } |
730 | |
7431 | 731 static void xml_logger_finalize(GaimLog *log) |
732 { | |
733 if (log->logger_data) { | |
734 fprintf(log->logger_data, "</conversation>\n"); | |
735 fclose(log->logger_data); | |
736 log->logger_data = NULL; | |
737 } | |
738 } | |
7443 | 739 |
8898 | 740 static GList *xml_logger_list(GaimLogType type, const char *sn, GaimAccount *account) |
7431 | 741 { |
10822 | 742 return gaim_log_common_lister(type, sn, account, ".xml", &xml_logger); |
4184 | 743 } |
744 | |
7431 | 745 static GaimLogLogger xml_logger = { |
746 N_("XML"), "xml", | |
747 NULL, | |
748 xml_logger_write, | |
749 xml_logger_finalize, | |
750 xml_logger_list, | |
8096 | 751 NULL, |
11025 | 752 NULL, |
7431 | 753 NULL |
754 }; | |
755 #endif | |
5563
9eb5b13fd412
[gaim-migrate @ 5965]
Christian Hammond <chipx86@chipx86.com>
parents:
5560
diff
changeset
|
756 |
7431 | 757 /**************************** |
7457 | 758 ** HTML LOGGER ************* |
759 ****************************/ | |
760 | |
761 static void html_logger_write(GaimLog *log, GaimMessageFlags type, | |
762 const char *from, time_t time, const char *message) | |
763 { | |
9763 | 764 char *msg_fixed; |
7457 | 765 char date[64]; |
9613 | 766 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); |
10822 | 767 GaimLogCommonLoggerData *data = log->logger_data; |
9613 | 768 |
7618 | 769 if(!data) { |
9763 | 770 const char *prpl = |
771 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); | |
10822 | 772 gaim_log_common_writer(log, time, ".html"); |
7457 | 773 |
9763 | 774 data = log->logger_data; |
7457 | 775 |
9763 | 776 /* if we can't write to the file, give up before we hurt ourselves */ |
777 if(!data->file) | |
778 return; | |
7616 | 779 |
7457 | 780 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
|
781 fprintf(data->file, "<html><head>"); |
11094
59a1ff5a4bae
[gaim-migrate @ 13119]
Richard Laager <rlaager@wiktel.com>
parents:
11092
diff
changeset
|
782 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
|
783 fprintf(data->file, "<title>"); |
7616 | 784 fprintf(data->file, "Conversation with %s at %s on %s (%s)", |
7457 | 785 log->name, date, gaim_account_get_username(log->account), prpl); |
7616 | 786 fprintf(data->file, "</title></head><body>"); |
787 fprintf(data->file, | |
7457 | 788 "<h3>Conversation with %s at %s on %s (%s)</h3>\n", |
789 log->name, date, gaim_account_get_username(log->account), prpl); | |
9763 | 790 |
7457 | 791 } |
7623 | 792 |
9892 | 793 /* if we can't write to the file, give up before we hurt ourselves */ |
794 if(!data->file) | |
795 return; | |
796 | |
7882 | 797 gaim_markup_html_to_xhtml(message, &msg_fixed, NULL); |
798 | |
8577 | 799 if(log->type == GAIM_LOG_SYSTEM){ |
9592 | 800 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); |
8577 | 801 fprintf(data->file, "---- %s @ %s ----<br/>\n", msg_fixed, date); |
802 } else { | |
803 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); | |
804 if (type & GAIM_MESSAGE_SYSTEM) | |
805 fprintf(data->file, "<font size=\"2\">(%s)</font><b> %s</b><br/>\n", date, msg_fixed); | |
806 else if (type & GAIM_MESSAGE_WHISPER) | |
807 fprintf(data->file, "<font color=\"#6C2585\"><font size=\"2\">(%s)</font><b> %s:</b></font> %s<br/>\n", | |
808 date, from, msg_fixed); | |
809 else if (type & GAIM_MESSAGE_AUTO_RESP) { | |
810 if (type & GAIM_MESSAGE_SEND) | |
811 fprintf(data->file, _("<font color=\"#16569E\"><font size=\"2\">(%s)</font> <b>%s <AUTO-REPLY>:</b></font> %s<br/>\n"), date, from, msg_fixed); | |
812 else if (type & GAIM_MESSAGE_RECV) | |
813 fprintf(data->file, _("<font color=\"#A82F2F\"><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 if(gaim_message_meify(msg_fixed, -1)) | |
10735
a0edd89ddb83
[gaim-migrate @ 12337]
Luke Schierer <lschiere@pidgin.im>
parents:
10732
diff
changeset
|
816 fprintf(data->file, "<font color=\"#062585\"><font size=\"2\">(%s)</font> <b>***%s</b></font> %s<br/>\n", |
10645 | 817 date, from, msg_fixed); |
8577 | 818 else |
10645 | 819 fprintf(data->file, "<font color=\"#A82F2F\"><font size=\"2\">(%s)</font> <b>%s:</b></font> %s<br/>\n", |
820 date, from, msg_fixed); | |
8577 | 821 } else if (type & GAIM_MESSAGE_SEND) { |
822 if(gaim_message_meify(msg_fixed, -1)) | |
10735
a0edd89ddb83
[gaim-migrate @ 12337]
Luke Schierer <lschiere@pidgin.im>
parents:
10732
diff
changeset
|
823 fprintf(data->file, "<font color=\"#062585\"><font size=\"2\">(%s)</font> <b>***%s</b></font> %s<br/>\n", |
10645 | 824 date, from, msg_fixed); |
8577 | 825 else |
10645 | 826 fprintf(data->file, "<font color=\"#16569E\"><font size=\"2\">(%s)</font> <b>%s:</b></font> %s<br/>\n", |
827 date, from, msg_fixed); | |
8577 | 828 } |
7564 | 829 } |
8573 | 830 |
7882 | 831 g_free(msg_fixed); |
7616 | 832 fflush(data->file); |
7457 | 833 } |
834 | |
835 static void html_logger_finalize(GaimLog *log) | |
836 { | |
10822 | 837 GaimLogCommonLoggerData *data = log->logger_data; |
7616 | 838 if (data) { |
839 if(data->file) { | |
840 fprintf(data->file, "</body></html>"); | |
841 fclose(data->file); | |
842 } | |
843 g_free(data->path); | |
7752 | 844 g_free(data); |
7463 | 845 } |
7457 | 846 } |
847 | |
8898 | 848 static GList *html_logger_list(GaimLogType type, const char *sn, GaimAccount *account) |
7457 | 849 { |
10822 | 850 return gaim_log_common_lister(type, sn, account, ".html", &html_logger); |
7457 | 851 } |
852 | |
8573 | 853 static GList *html_logger_list_syslog(GaimAccount *account) |
854 { | |
10822 | 855 return gaim_log_common_lister(GAIM_LOG_SYSTEM, ".system", account, ".html", &html_logger); |
8573 | 856 } |
857 | |
7457 | 858 static char *html_logger_read(GaimLog *log, GaimLogReadFlags *flags) |
859 { | |
860 char *read, *minus_header; | |
10822 | 861 GaimLogCommonLoggerData *data = log->logger_data; |
7457 | 862 *flags = GAIM_LOG_READ_NO_NEWLINE; |
7616 | 863 if (!data || !data->path) |
864 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
865 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7457 | 866 minus_header = strchr(read, '\n'); |
867 if (!minus_header) | |
868 minus_header = g_strdup(read); | |
869 else | |
870 minus_header = g_strdup(minus_header + 1); | |
871 g_free(read); | |
872 return minus_header; | |
873 } | |
8578 | 874 return g_strdup_printf(_("<font color=\"red\"><b>Could not read file: %s</b></font>"), data->path); |
7457 | 875 } |
876 | |
877 static GaimLogLogger html_logger = { | |
878 N_("HTML"), "html", | |
9819 | 879 NULL, |
7457 | 880 html_logger_write, |
881 html_logger_finalize, | |
882 html_logger_list, | |
7556 | 883 html_logger_read, |
10822 | 884 gaim_log_common_sizer, |
8573 | 885 NULL, |
11025 | 886 html_logger_list_syslog, |
887 NULL | |
7457 | 888 }; |
889 | |
890 | |
891 | |
892 | |
893 /**************************** | |
7431 | 894 ** PLAIN TEXT LOGGER ******* |
895 ****************************/ | |
4184 | 896 |
7436 | 897 static void txt_logger_write(GaimLog *log, |
898 GaimMessageFlags type, | |
7431 | 899 const char *from, time_t time, const char *message) |
900 { | |
901 char date[64]; | |
9763 | 902 GaimPlugin *plugin = gaim_find_prpl(gaim_account_get_protocol_id(log->account)); |
10822 | 903 GaimLogCommonLoggerData *data = log->logger_data; |
9763 | 904 char *stripped = NULL; |
905 | |
906 if(!data) { | |
7431 | 907 /* This log is new. We could use the loggers 'new' function, but |
908 * creating a new file there would result in empty files in the case | |
909 * that you open a convo with someone, but don't say anything. | |
910 */ | |
9763 | 911 const char *prpl = |
912 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); | |
10822 | 913 gaim_log_common_writer(log, time, ".txt"); |
8898 | 914 |
9763 | 915 data = log->logger_data; |
7436 | 916 |
9763 | 917 /* if we can't write to the file, give up before we hurt ourselves */ |
918 if(!data->file) | |
919 return; | |
7616 | 920 |
7453 | 921 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&log->time)); |
7616 | 922 fprintf(data->file, "Conversation with %s at %s on %s (%s)\n", |
7431 | 923 log->name, date, gaim_account_get_username(log->account), prpl); |
924 } | |
7436 | 925 |
7623 | 926 /* if we can't write to the file, give up before we hurt ourselves */ |
927 if(!data->file) | |
928 return; | |
929 | |
8573 | 930 stripped = gaim_markup_strip_html(message); |
931 | |
932 if(log->type == GAIM_LOG_SYSTEM){ | |
9592 | 933 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&time)); |
8573 | 934 fprintf(data->file, "---- %s @ %s ----\n", stripped, date); |
935 } else { | |
936 strftime(date, sizeof(date), "%H:%M:%S", localtime(&time)); | |
937 if (type & GAIM_MESSAGE_SEND || | |
938 type & GAIM_MESSAGE_RECV) { | |
939 if (type & GAIM_MESSAGE_AUTO_RESP) { | |
940 fprintf(data->file, _("(%s) %s <AUTO-REPLY>: %s\n"), date, | |
941 from, stripped); | |
942 } else { | |
943 if(gaim_message_meify(stripped, -1)) | |
944 fprintf(data->file, "(%s) ***%s %s\n", date, from, | |
945 stripped); | |
946 else | |
947 fprintf(data->file, "(%s) %s: %s\n", date, from, | |
948 stripped); | |
949 } | |
950 } else if (type & GAIM_MESSAGE_SYSTEM) | |
951 fprintf(data->file, "(%s) %s\n", date, stripped); | |
952 else if (type & GAIM_MESSAGE_NO_LOG) { | |
953 /* This shouldn't happen */ | |
954 g_free(stripped); | |
955 return; | |
956 } else if (type & GAIM_MESSAGE_WHISPER) | |
957 fprintf(data->file, "(%s) *%s* %s", date, from, stripped); | |
958 else | |
959 fprintf(data->file, "(%s) %s%s %s\n", date, from ? from : "", | |
960 from ? ":" : "", stripped); | |
961 } | |
962 | |
963 fflush(data->file); | |
964 g_free(stripped); | |
7431 | 965 } |
966 | |
967 static void txt_logger_finalize(GaimLog *log) | |
968 { | |
10822 | 969 GaimLogCommonLoggerData *data = log->logger_data; |
7616 | 970 if (data) { |
971 if(data->file) | |
972 fclose(data->file); | |
973 if(data->path) | |
974 g_free(data->path); | |
7752 | 975 g_free(data); |
7616 | 976 } |
7431 | 977 } |
978 | |
8898 | 979 static GList *txt_logger_list(GaimLogType type, const char *sn, GaimAccount *account) |
7431 | 980 { |
10822 | 981 return gaim_log_common_lister(type, sn, account, ".txt", &txt_logger); |
7431 | 982 } |
983 | |
8573 | 984 static GList *txt_logger_list_syslog(GaimAccount *account) |
985 { | |
10822 | 986 return gaim_log_common_lister(GAIM_LOG_SYSTEM, ".system", account, ".txt", &txt_logger); |
8573 | 987 } |
988 | |
7431 | 989 static char *txt_logger_read(GaimLog *log, GaimLogReadFlags *flags) |
990 { | |
8517 | 991 char *read, *minus_header, *minus_header2; |
10822 | 992 GaimLogCommonLoggerData *data = log->logger_data; |
7457 | 993 *flags = 0; |
7616 | 994 if (!data || !data->path) |
995 return g_strdup(_("<font color=\"red\"><b>Unable to find log path!</b></font>")); | |
996 if (g_file_get_contents(data->path, &read, NULL, NULL)) { | |
7431 | 997 minus_header = strchr(read, '\n'); |
998 if (!minus_header) | |
999 minus_header = g_strdup(read); | |
7436 | 1000 else |
7431 | 1001 minus_header = g_strdup(minus_header + 1); |
1002 g_free(read); | |
10732
c4cb90065e1d
[gaim-migrate @ 12334]
Luke Schierer <lschiere@pidgin.im>
parents:
10645
diff
changeset
|
1003 minus_header2 = g_markup_escape_text(minus_header, -1); |
8517 | 1004 g_free(minus_header); |
1005 return minus_header2; | |
7431 | 1006 } |
8578 | 1007 return g_strdup_printf(_("<font color=\"red\"><b>Could not read file: %s</b></font>"), data->path); |
7436 | 1008 } |
7431 | 1009 |
1010 static GaimLogLogger txt_logger = { | |
1011 N_("Plain text"), "txt", | |
9819 | 1012 NULL, |
7431 | 1013 txt_logger_write, |
1014 txt_logger_finalize, | |
1015 txt_logger_list, | |
7556 | 1016 txt_logger_read, |
10822 | 1017 gaim_log_common_sizer, |
8573 | 1018 NULL, |
11025 | 1019 txt_logger_list_syslog, |
1020 NULL | |
7431 | 1021 }; |
1022 | |
1023 /**************** | |
1024 * OLD LOGGER *** | |
1025 ****************/ | |
1026 | |
1027 /* The old logger doesn't write logs, only reads them. This is to include | |
1028 * old logs in the log viewer transparently. | |
1029 */ | |
1030 | |
1031 struct old_logger_data { | |
7764 | 1032 GaimStringref *pathref; |
7431 | 1033 int offset; |
1034 int length; | |
1035 }; | |
1036 | |
8898 | 1037 static GList *old_logger_list(GaimLogType type, const char *sn, GaimAccount *account) |
7431 | 1038 { |
1039 FILE *file; | |
1040 char buf[BUF_LONG]; | |
1041 struct tm tm; | |
7761 | 1042 char month[4]; |
7431 | 1043 struct old_logger_data *data = NULL; |
1044 char *logfile = g_strdup_printf("%s.log", gaim_normalize(account, sn)); | |
7764 | 1045 char *pathstr = g_build_filename(gaim_user_dir(), "logs", logfile, NULL); |
1046 GaimStringref *pathref = gaim_stringref_new(pathstr); | |
7431 | 1047 char *newlog; |
7761 | 1048 int logfound = 0; |
1049 int lastoff = 0; | |
1050 int newlen; | |
7791 | 1051 time_t lasttime = 0; |
7431 | 1052 |
1053 GaimLog *log = NULL; | |
1054 GList *list = NULL; | |
1055 | |
7473 | 1056 g_free(logfile); |
7764 | 1057 g_free(pathstr); |
7473 | 1058 |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
1059 if (!(file = g_fopen(gaim_stringref_value(pathref), "rb"))) { |
7764 | 1060 gaim_stringref_unref(pathref); |
7431 | 1061 return NULL; |
7447 | 1062 } |
7436 | 1063 |
7431 | 1064 while (fgets(buf, BUF_LONG, file)) { |
1065 if ((newlog = strstr(buf, "---- New C"))) { | |
1066 int length; | |
1067 int offset; | |
1068 char convostart[32]; | |
1069 char *temp = strchr(buf, '@'); | |
7436 | 1070 |
7431 | 1071 if (temp == NULL || strlen(temp) < 2) |
1072 continue; | |
7436 | 1073 |
7431 | 1074 temp++; |
1075 length = strcspn(temp, "-"); | |
1076 if (length > 31) length = 31; | |
7436 | 1077 |
7431 | 1078 offset = ftell(file); |
7436 | 1079 |
7761 | 1080 if (logfound) { |
1081 newlen = offset - lastoff - length; | |
7436 | 1082 if(strstr(buf, "----</H3><BR>")) { |
7761 | 1083 newlen -= |
1084 sizeof("<HR><BR><H3 Align=Center> ---- New Conversation @ ") + | |
1085 sizeof("----</H3><BR>") - 2; | |
7436 | 1086 } else { |
7761 | 1087 newlen -= |
1088 sizeof("---- New Conversation @ ") + sizeof("----") - 2; | |
7436 | 1089 } |
1090 | |
7461 | 1091 if(strchr(buf, '\r')) |
7770 | 1092 newlen--; |
7461 | 1093 |
7761 | 1094 if (newlen != 0) { |
1095 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
1096 log->logger = &old_logger; | |
1097 log->time = lasttime; | |
1098 data = g_new0(struct old_logger_data, 1); | |
1099 data->offset = lastoff; | |
1100 data->length = newlen; | |
7764 | 1101 data->pathref = gaim_stringref_ref(pathref); |
7761 | 1102 log->logger_data = data; |
7431 | 1103 list = g_list_append(list, log); |
7761 | 1104 } |
7431 | 1105 } |
1106 | |
7761 | 1107 logfound = 1; |
1108 lastoff = offset; | |
7436 | 1109 |
7431 | 1110 g_snprintf(convostart, length, "%s", temp); |
7676 | 1111 sscanf(convostart, "%*s %s %d %d:%d:%d %d", |
1112 month, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &tm.tm_year); | |
1113 /* Ugly hack, in case current locale is not English */ | |
1114 if (strcmp(month, "Jan") == 0) { | |
1115 tm.tm_mon= 0; | |
1116 } else if (strcmp(month, "Feb") == 0) { | |
1117 tm.tm_mon = 1; | |
1118 } else if (strcmp(month, "Mar") == 0) { | |
1119 tm.tm_mon = 2; | |
1120 } else if (strcmp(month, "Apr") == 0) { | |
1121 tm.tm_mon = 3; | |
1122 } else if (strcmp(month, "May") == 0) { | |
1123 tm.tm_mon = 4; | |
1124 } else if (strcmp(month, "Jun") == 0) { | |
1125 tm.tm_mon = 5; | |
1126 } else if (strcmp(month, "Jul") == 0) { | |
1127 tm.tm_mon = 6; | |
1128 } else if (strcmp(month, "Aug") == 0) { | |
1129 tm.tm_mon = 7; | |
1130 } else if (strcmp(month, "Sep") == 0) { | |
1131 tm.tm_mon = 8; | |
1132 } else if (strcmp(month, "Oct") == 0) { | |
1133 tm.tm_mon = 9; | |
1134 } else if (strcmp(month, "Nov") == 0) { | |
1135 tm.tm_mon = 10; | |
1136 } else if (strcmp(month, "Dec") == 0) { | |
1137 tm.tm_mon = 11; | |
1138 } | |
1139 tm.tm_year -= 1900; | |
7761 | 1140 lasttime = mktime(&tm); |
4184 | 1141 } |
1142 } | |
7613 | 1143 |
7761 | 1144 if (logfound) { |
1145 if ((newlen = ftell(file) - lastoff) != 0) { | |
1146 log = gaim_log_new(GAIM_LOG_IM, sn, account, -1); | |
1147 log->logger = &old_logger; | |
1148 log->time = lasttime; | |
1149 data = g_new0(struct old_logger_data, 1); | |
1150 data->offset = lastoff; | |
1151 data->length = newlen; | |
7764 | 1152 data->pathref = gaim_stringref_ref(pathref); |
7761 | 1153 log->logger_data = data; |
7613 | 1154 list = g_list_append(list, log); |
7761 | 1155 } |
7613 | 1156 } |
1157 | |
7764 | 1158 gaim_stringref_unref(pathref); |
7431 | 1159 fclose(file); |
1160 return list; | |
4184 | 1161 } |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
1162 |
8898 | 1163 static int old_logger_total_size(GaimLogType type, const char *name, GaimAccount *account) |
8096 | 1164 { |
1165 char *logfile = g_strdup_printf("%s.log", gaim_normalize(account, name)); | |
1166 char *pathstr = g_build_filename(gaim_user_dir(), "logs", logfile, NULL); | |
1167 int size; | |
1168 struct stat st; | |
1169 | |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
1170 if (g_stat(pathstr, &st)) |
8096 | 1171 size = 0; |
1172 else | |
1173 size = st.st_size; | |
1174 | |
1175 g_free(logfile); | |
1176 g_free(pathstr); | |
1177 | |
1178 return size; | |
1179 } | |
1180 | |
7616 | 1181 static char * old_logger_read (GaimLog *log, GaimLogReadFlags *flags) |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
1182 { |
7431 | 1183 struct old_logger_data *data = log->logger_data; |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10577
diff
changeset
|
1184 FILE *file = g_fopen(gaim_stringref_value(data->pathref), "rb"); |
10906 | 1185 char *tmp, *read = g_malloc(data->length + 1); |
7431 | 1186 fseek(file, data->offset, SEEK_SET); |
1187 fread(read, data->length, 1, file); | |
8370 | 1188 fclose(file); |
7431 | 1189 read[data->length] = '\0'; |
7436 | 1190 *flags = 0; |
1191 if(strstr(read, "<BR>")) | |
1192 *flags |= GAIM_LOG_READ_NO_NEWLINE; | |
10906 | 1193 else { |
1194 tmp = g_markup_escape_text(read, -1); | |
1195 g_free(read); | |
1196 read = tmp; | |
1197 } | |
7431 | 1198 return read; |
1199 } | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4227
diff
changeset
|
1200 |
7616 | 1201 static int old_logger_size (GaimLog *log) |
7556 | 1202 { |
1203 struct old_logger_data *data = log->logger_data; | |
7616 | 1204 return data ? data->length : 0; |
1205 } | |
1206 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
1207 static void old_logger_get_log_sets(GaimLogSetCallback cb, GHashTable *sets) |
11025 | 1208 { |
1209 char *log_path = g_build_filename(gaim_user_dir(), "logs", NULL); | |
1210 GDir *log_dir = g_dir_open(log_path, 0, NULL); | |
1211 gchar *name; | |
1212 GaimBlistNode *gnode, *cnode, *bnode; | |
1213 | |
1214 g_free(log_path); | |
1215 if (log_dir == NULL) | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
1216 return; |
11025 | 1217 |
1218 /* Don't worry about the cast, name will be filled with a dynamically allocated data shortly. */ | |
1219 while ((name = (gchar *)g_dir_read_name(log_dir)) != NULL) { | |
1220 size_t len; | |
1221 gchar *ext; | |
1222 GaimLogSet *set; | |
1223 gboolean found = FALSE; | |
1224 | |
1225 /* Unescape the filename. */ | |
1226 name = g_strdup(gaim_unescape_filename(name)); | |
1227 | |
1228 /* Get the (possibly new) length of name. */ | |
1229 len = strlen(name); | |
1230 | |
1231 if (len < 5) { | |
1232 g_free(name); | |
1233 continue; | |
1234 } | |
1235 | |
1236 /* Make sure we're dealing with a log file. */ | |
1237 ext = &name[len - 4]; | |
1238 if (strcmp(ext, ".log")) { | |
1239 g_free(name); | |
1240 continue; | |
1241 } | |
1242 | |
1243 set = g_new0(GaimLogSet, 1); | |
1244 | |
1245 /* Chat for .chat at the end of the name to determine the type. */ | |
1246 *ext = '\0'; | |
1247 set->type = GAIM_LOG_IM; | |
1248 if (len > 9) { | |
1249 char *tmp = &name[len - 9]; | |
1250 if (!strcmp(tmp, ".chat")) { | |
1251 set->type = GAIM_LOG_CHAT; | |
1252 *tmp = '\0'; | |
1253 } | |
1254 } | |
1255 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
1256 set->name = set->normalized_name = name; |
11025 | 1257 |
1258 /* Search the buddy list to find the account and to determine if this is a buddy. */ | |
1259 for (gnode = gaim_get_blist()->root; !found && gnode != NULL; gnode = gnode->next) | |
1260 { | |
1261 if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
1262 continue; | |
1263 | |
1264 for (cnode = gnode->child; !found && cnode != NULL; cnode = cnode->next) | |
1265 { | |
1266 if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) | |
1267 continue; | |
1268 | |
1269 for (bnode = cnode->child; !found && bnode != NULL; bnode = bnode->next) | |
1270 { | |
1271 GaimBuddy *buddy = (GaimBuddy *)bnode; | |
1272 | |
1273 if (!strcmp(buddy->name, name)) { | |
1274 set->account = buddy->account; | |
1275 set->buddy = TRUE; | |
1276 found = TRUE; | |
1277 } | |
1278 } | |
1279 } | |
1280 } | |
1281 | |
11177
3924db2b1ca8
[gaim-migrate @ 13285]
Richard Laager <rlaager@wiktel.com>
parents:
11094
diff
changeset
|
1282 cb(sets, set); |
11025 | 1283 } |
1284 g_dir_close(log_dir); | |
1285 } | |
1286 | |
7616 | 1287 static void old_logger_finalize(GaimLog *log) |
1288 { | |
1289 struct old_logger_data *data = log->logger_data; | |
7764 | 1290 gaim_stringref_unref(data->pathref); |
7616 | 1291 g_free(data); |
7556 | 1292 } |
1293 | |
7431 | 1294 static GaimLogLogger old_logger = { |
1295 "old logger", "old", | |
7616 | 1296 NULL, NULL, |
1297 old_logger_finalize, | |
7431 | 1298 old_logger_list, |
7616 | 1299 old_logger_read, |
8096 | 1300 old_logger_size, |
8573 | 1301 old_logger_total_size, |
11025 | 1302 NULL, |
1303 old_logger_get_log_sets | |
7431 | 1304 }; |