comparison mcabber/src/histolog.c @ 1437:071c8170b7de

Add option 'statefile' to keep track of unread messages across restarts (Suggested by micressor)
author Mikael Berthe <mikael@lilotux.net>
date Mon, 25 Feb 2008 20:27:56 +0100
parents 6fb141142388
children ec55cdf44335
comparison
equal deleted inserted replaced
1436:6fb141142388 1437:071c8170b7de
24 #include <time.h> 24 #include <time.h>
25 #include <ctype.h> 25 #include <ctype.h>
26 #include <sys/types.h> 26 #include <sys/types.h>
27 #include <sys/stat.h> 27 #include <sys/stat.h>
28 #include <fcntl.h> 28 #include <fcntl.h>
29 #include <unistd.h>
29 30
30 #include "histolog.h" 31 #include "histolog.h"
31 #include "hbuf.h" 32 #include "hbuf.h"
32 #include "jabglue.h" 33 #include "jabglue.h"
33 #include "utils.h" 34 #include "utils.h"
34 #include "logprint.h" 35 #include "screen.h"
35 #include "settings.h" 36 #include "settings.h"
36 #include "utils.h" 37 #include "utils.h"
38 #include "roster.h"
37 39
38 static guint UseFileLogging; 40 static guint UseFileLogging;
39 static guint FileLoadLogs; 41 static guint FileLoadLogs;
40 static char *RootDir; 42 static char *RootDir;
41 43
389 g_free(RootDir); 391 g_free(RootDir);
390 RootDir = NULL; 392 RootDir = NULL;
391 } 393 }
392 } 394 }
393 395
396 guint hlog_is_enabled(void)
397 {
398 return UseFileLogging;
399 }
400
394 inline void hlog_write_message(const char *bjid, time_t timestamp, int sent, 401 inline void hlog_write_message(const char *bjid, time_t timestamp, int sent,
395 const char *msg) 402 const char *msg)
396 { 403 {
397 guchar info; 404 guchar info;
398 /* sent=1 message sent by mcabber 405 /* sent=1 message sent by mcabber
414 // XXX Check status value? 421 // XXX Check status value?
415 write_histo_line(bjid, timestamp, 'S', toupper(imstatus2char[status]), 422 write_histo_line(bjid, timestamp, 'S', toupper(imstatus2char[status]),
416 status_msg); 423 status_msg);
417 } 424 }
418 425
426
427 // hlog_save_state()
428 // If enabled, save the current state of the roster
429 // (i.e. pending messages) to a temporary file.
430 void hlog_save_state(void)
431 {
432 gpointer unread_ptr, first_unread;
433 const char *bjid;
434 char *statefile_xp;
435 FILE *fp;
436 const char *statefile = settings_opt_get("statefile");
437
438 if (!statefile || !UseFileLogging)
439 return;
440
441 statefile_xp = expand_filename(statefile);
442 fp = fopen(statefile_xp, "w");
443 if (!fp) {
444 scr_LogPrint(LPRINT_NORMAL, "Cannot open state file [%s]",
445 strerror(errno));
446 goto hlog_save_state_return;
447 }
448
449 if (!jb_getonline()) {
450 // We're not connected. Let's use the unread_jids hash.
451 GList *unread_jid = unread_jid_get_list();
452 unread_ptr = unread_jid;
453 for ( ; unread_jid ; unread_jid = g_list_next(unread_jid))
454 fprintf(fp, "%s\n", (char*)unread_jid->data);
455 g_list_free(unread_ptr);
456 goto hlog_save_state_return;
457 }
458
459 if (!current_buddy) // Safety check -- shouldn't happen.
460 goto hlog_save_state_return;
461
462 // We're connected. Let's use unread_msg().
463 unread_ptr = first_unread = unread_msg(NULL);
464 if (!first_unread)
465 goto hlog_save_state_return;
466
467 do {
468 guint type = buddy_gettype(unread_ptr);
469 if (type & (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)) {
470 bjid = buddy_getjid(unread_ptr);
471 if (bjid)
472 fprintf(fp, "%s\n", bjid);
473 }
474 unread_ptr = unread_msg(unread_ptr);
475 } while (unread_ptr && unread_ptr != first_unread);
476
477 hlog_save_state_return:
478 if (fp) {
479 long filelen = ftell(fp);
480 fclose(fp);
481 if (!filelen)
482 unlink(statefile_xp);
483 }
484 g_free(statefile_xp);
485 }
486
487 // hlog_load_state()
488 // If enabled, load the current state of the roster
489 // (i.e. pending messages) from a temporary file.
490 // This function adds the JIDs to the unread_jids hash table,
491 // so it should only be called at startup.
492 void hlog_load_state(void)
493 {
494 char bjid[1024];
495 char *statefile_xp;
496 FILE *fp;
497 const char *statefile = settings_opt_get("statefile");
498
499 if (!statefile || !UseFileLogging)
500 return;
501
502 statefile_xp = expand_filename(statefile);
503 fp = fopen(statefile_xp, "r");
504 if (fp) {
505 char *eol;
506 while (!feof(fp)) {
507 if (fgets(bjid, sizeof bjid, fp) == NULL)
508 break;
509 // Let's remove the trailing newline.
510 // Also remove whitespace, if the file as been (badly) manually modified.
511 for (eol = bjid; *eol; eol++) ;
512 for (eol--; eol >= bjid && (*eol == '\n' || *eol == ' '); *eol-- = 0) ;
513 // Safety checks...
514 if (!bjid[0])
515 continue;
516 if (check_jid_syntax(bjid)) {
517 scr_LogPrint(LPRINT_LOGNORM,
518 "ERROR: Invalid JID in state file. Corrupted file?");
519 break;
520 }
521 // Display a warning if there are pending messages but the user
522 // won't see them because load_log isn't set.
523 if (!FileLoadLogs) {
524 scr_LogPrint(LPRINT_LOGNORM, "WARNING: unread message from <%s>.",
525 bjid);
526 scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE);
527 }
528 // Add the JID to unread_jids. It will be used when the contact is
529 // added to the roster.
530 unread_jid_add(bjid);
531 }
532 fclose(fp);
533 }
534 g_free(statefile_xp);
535 }
536
419 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ 537 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */