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