source: logging.c @ fa981f3

release-1.8release-1.9
Last change on this file since fa981f3 was 6829afc, checked in by David Benjamin <davidben@mit.edu>, 11 years ago
Define CALLER_OWN macro Replace our exising uses of G_GNUC_WARN_UNUSED_RESULT with it. The old macro is just way too long. This also more clearly specifies the intent.
  • Property mode set to 100644
File size: 13.2 KB
RevLine 
[7d4fbcd]1#include "owl.h"
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <sys/param.h>
6
[cc305b5]7typedef struct _owl_log_entry { /* noproto */
8  char *filename;
9  char *message;
10} owl_log_entry;
11
12
13static GMainContext *log_context;
14static GMainLoop *log_loop;
15static GThread *logging_thread;
16
[15b34fd]17/* This is now the one function that should be called to log a
18 * message.  It will do all the work necessary by calling the other
19 * functions in this file as necessary.
20 */
[c08c70a]21void owl_log_message(const owl_message *m) {
[15b34fd]22  owl_function_debugmsg("owl_log_message: entering");
23
[3c7d086a]24  if (m == NULL) {
25    owl_function_debugmsg("owl_log_message: passed null message");
26    return;
27  }
28
[15b34fd]29  /* should we be logging this message? */
30  if (!owl_log_shouldlog_message(m)) {
31    owl_function_debugmsg("owl_log_message: not logging message");
32    return;
33  }
34
35  /* handle incmoing messages */
36  if (owl_message_is_direction_in(m)) {
37    owl_log_incoming(m);
38    owl_function_debugmsg("owl_log_message: leaving");
39    return;
40  }
41
42  /* handle outgoing messages */
[42947f1]43  owl_log_outgoing(m);
44
[15b34fd]45  owl_function_debugmsg("owl_log_message: leaving");
46}
[7d4fbcd]47
[15b34fd]48/* Return 1 if we should log the given message, otherwise return 0 */
[c08c70a]49int owl_log_shouldlog_message(const owl_message *m) {
[4542047]50  const owl_filter *f;
[12c35df]51
[15b34fd]52  /* If there's a logfilter and this message matches it, log */
53  f=owl_global_get_filter(&g, owl_global_get_logfilter(&g));
54  if (f && owl_filter_message_match(f, m)) return(1);
[7d4fbcd]55
[15b34fd]56  /* otherwise we do things based on the logging variables */
57
58  /* skip login/logout messages if appropriate */
59  if (!owl_global_is_loglogins(&g) && owl_message_is_loginout(m)) return(0);
60     
61  /* check direction */
62  if ((owl_global_get_loggingdirection(&g)==OWL_LOGGING_DIRECTION_IN) && owl_message_is_direction_out(m)) {
63    return(0);
64  }
65  if ((owl_global_get_loggingdirection(&g)==OWL_LOGGING_DIRECTION_OUT) && owl_message_is_direction_in(m)) {
66    return(0);
67  }
68
69  if (owl_message_is_type_zephyr(m)) {
70    if (owl_message_is_personal(m) && !owl_global_is_logging(&g)) return(0);
71    if (!owl_message_is_personal(m) && !owl_global_is_classlogging(&g)) return(0);
72  } else {
73    if (owl_message_is_private(m) || owl_message_is_loginout(m)) {
74      if (!owl_global_is_logging(&g)) return(0);
75    } else {
76      if (!owl_global_is_classlogging(&g)) return(0);
77    }
[7d4fbcd]78  }
[15b34fd]79  return(1);
80}
81
[6829afc]82CALLER_OWN char *owl_log_zephyr(const owl_message *m)
[d427f08]83{
[cc305b5]84    char *tmp = NULL;
85    GString *buffer = NULL;
86    buffer = g_string_new("");
87    tmp = short_zuser(owl_message_get_sender(m));
88    g_string_append_printf(buffer, "Class: %s Instance: %s", 
89                           owl_message_get_class(m), 
90                           owl_message_get_instance(m));
91    if (strcmp(owl_message_get_opcode(m), "")) {
92      g_string_append_printf(buffer, " Opcode: %s", 
93                             owl_message_get_opcode(m));
94    }
95    g_string_append_printf(buffer, "\n");
96    g_string_append_printf(buffer, "Time: %s Host: %s\n", 
97                           owl_message_get_timestr(m), 
98                           owl_message_get_hostname(m));
99    g_string_append_printf(buffer, "From: %s <%s>\n\n", 
100                           owl_message_get_zsig(m), tmp);
101    g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m));
[ddbbcffa]102    g_free(tmp);
[cc305b5]103    return g_string_free(buffer, FALSE);
104}
105
[6829afc]106CALLER_OWN char *owl_log_aim(const owl_message *m)
[d427f08]107{
[cc305b5]108    GString *buffer = NULL;
109    buffer = g_string_new("");
110    g_string_append_printf(buffer, "From: <%s> To: <%s>\n", 
111                           owl_message_get_sender(m), owl_message_get_recipient(m));
112    g_string_append_printf(buffer, "Time: %s\n\n", 
113                           owl_message_get_timestr(m));
114    if (owl_message_is_login(m)) {
115        g_string_append_printf(buffer, "LOGIN\n\n");
116    } else if (owl_message_is_logout(m)) {
117        g_string_append_printf(buffer, "LOGOUT\n\n");
118    } else {
119        g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m));
120    }
121    return g_string_free(buffer, FALSE);
122}
123
[6829afc]124CALLER_OWN char *owl_log_jabber(const owl_message *m)
[d427f08]125{
[cc305b5]126    GString *buffer = NULL;
127    buffer = g_string_new("");
128    g_string_append_printf(buffer, "From: <%s> To: <%s>\n",
129                           owl_message_get_sender(m), 
130                           owl_message_get_recipient(m));
131    g_string_append_printf(buffer, "Time: %s\n\n", 
132                           owl_message_get_timestr(m));
133    g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m));
134    return g_string_free(buffer, FALSE);
135}
136
[6829afc]137CALLER_OWN char *owl_log_generic(const owl_message *m)
[d427f08]138{
[cc305b5]139    GString *buffer;
140    buffer = g_string_new("");
141    g_string_append_printf(buffer, "From: <%s> To: <%s>\n", 
142                           owl_message_get_sender(m), 
143                           owl_message_get_recipient(m));
144    g_string_append_printf(buffer, "Time: %s\n\n", 
145                           owl_message_get_timestr(m));
146    g_string_append_printf(buffer, "%s\n\n", 
147                           owl_message_get_body(m));
148    return g_string_free(buffer, FALSE);
149}
150
151static void owl_log_error_main_thread(gpointer data)
152{
153  owl_function_error("%s", (const char*)data);
[42947f1]154}
155
[cc305b5]156static void owl_log_error(const char *message)
157{
158  char *data = g_strdup(message);
159  owl_select_post_task(owl_log_error_main_thread,
160                       data, g_free, g_main_context_default());
[42947f1]161}
162
[cc305b5]163static void owl_log_write_entry(gpointer data)
164{
165  owl_log_entry *msg = (owl_log_entry*)data;
166  FILE *file = NULL;
167  file = fopen(msg->filename, "a");
168  if (!file) {
169    owl_log_error("Unable to open file for logging");
170    return;
171  }
172  fprintf(file, "%s", msg->message);
173  fclose(file);
[42947f1]174}
175
[cc305b5]176static void owl_log_entry_free(void *data)
177{
178  owl_log_entry *msg = (owl_log_entry*)data;
179  if (msg) {
180    g_free(msg->message);
181    g_free(msg->filename);
182    g_free(msg);
183  }
184}
185
186void owl_log_enqueue_message(const char *buffer, const char *filename)
187{
188  owl_log_entry *log_msg = NULL; 
189  log_msg = g_new(owl_log_entry,1);
190  log_msg->message = g_strdup(buffer);
191  log_msg->filename = g_strdup(filename);
192  owl_select_post_task(owl_log_write_entry, log_msg, 
193                       owl_log_entry_free, log_context);
[42947f1]194}
195
[c08c70a]196void owl_log_append(const owl_message *m, const char *filename) {
[cc305b5]197  char *buffer = NULL;
198  if (owl_message_is_type_zephyr(m)) {
199    buffer = owl_log_zephyr(m);
200  } else if (owl_message_is_type_jabber(m)) {
201    buffer = owl_log_jabber(m);
202  } else if (owl_message_is_type_aim(m)) {
203    buffer = owl_log_aim(m);
204  } else {
205    buffer = owl_log_generic(m);
206  }
207  owl_log_enqueue_message(buffer, filename);
208  g_free(buffer);
[42947f1]209}
210
[c08c70a]211void owl_log_outgoing(const owl_message *m)
[15b34fd]212{
[e3a75ed]213  char *filename, *logpath;
[9c590d4]214  char *to, *temp;
[839697d]215  GList *cc;
[9c590d4]216
217  /* expand ~ in path names */
[60d7935]218  logpath = owl_util_makepath(owl_global_get_logpath(&g));
[15b34fd]219
[42947f1]220  /* Figure out what path to log to */
221  if (owl_message_is_type_zephyr(m)) {
[af1920fd]222    /* If this has CC's, do all but the "recipient" which we'll do below */
[839697d]223    cc = owl_message_get_cc_without_recipient(m);
224    while (cc != NULL) {
225      temp = short_zuser(cc->data);
[e3a75ed]226      filename = g_strdup_printf("%s/%s", logpath, temp);
[839697d]227      owl_log_append(m, filename);
228
[e3a75ed]229      g_free(filename);
[ddbbcffa]230      g_free(temp);
231      g_free(cc->data);
[839697d]232      cc = g_list_delete_link(cc, cc);
[9c590d4]233    }
[839697d]234
[9c590d4]235    to = short_zuser(owl_message_get_recipient(m));
[42947f1]236  } else if (owl_message_is_type_jabber(m)) {
[3472845]237    to = g_strdup_printf("jabber:%s", owl_message_get_recipient(m));
[7865479]238    g_strdelimit(to, "/", '_');
[42947f1]239  } else if (owl_message_is_type_aim(m)) {
[28ee32b]240    char *temp2;
[9c590d4]241    temp = owl_aim_normalize_screenname(owl_message_get_recipient(m));
[28ee32b]242    temp2 = g_utf8_strdown(temp,-1);
[3472845]243    to = g_strdup_printf("aim:%s", temp2);
[ddbbcffa]244    g_free(temp2);
245    g_free(temp);
[42947f1]246  } else {
[d4927a7]247    to = g_strdup("loopback");
[42947f1]248  }
[7d4fbcd]249
[e3a75ed]250  filename = g_strdup_printf("%s/%s", logpath, to);
[42947f1]251  owl_log_append(m, filename);
[ddbbcffa]252  g_free(to);
[e3a75ed]253  g_free(filename);
[7d4fbcd]254
[e3a75ed]255  filename = g_strdup_printf("%s/all", logpath);
[42947f1]256  owl_log_append(m, filename);
[ddbbcffa]257  g_free(logpath);
[e3a75ed]258  g_free(filename);
[7d4fbcd]259}
260
[42947f1]261
[24ccc01]262void owl_log_outgoing_zephyr_error(const owl_zwrite *zw, const char *text)
[2b86d14]263{
[e3a75ed]264  char *filename, *logpath;
[fe3b017]265  char *tobuff, *recip;
[180cd15]266  owl_message *m;
[cc305b5]267  GString *msgbuf;
[180cd15]268  /* create a present message so we can pass it to
[c79a047]269   * owl_log_shouldlog_message(void)
[180cd15]270   */
[96828e4]271  m = g_new(owl_message, 1);
[e5da3fe]272  /* recip_index = 0 because there can only be one recipient anyway */
273  owl_message_create_from_zwrite(m, zw, text, 0);
[180cd15]274  if (!owl_log_shouldlog_message(m)) {
[91634ec]275    owl_message_delete(m);
[180cd15]276    return;
277  }
[91634ec]278  owl_message_delete(m);
[2b86d14]279
[180cd15]280  /* chop off a local realm */
[fe3b017]281  recip = owl_zwrite_get_recip_n_with_realm(zw, 0);
282  tobuff = short_zuser(recip);
283  g_free(recip);
[2b86d14]284
285  /* expand ~ in path names */
[60d7935]286  logpath = owl_util_makepath(owl_global_get_logpath(&g));
[e3a75ed]287  filename = g_strdup_printf("%s/%s", logpath, tobuff);
[cc305b5]288  msgbuf = g_string_new("");
289  g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);
290  if (text[strlen(text)-1] != '\n') {
291    g_string_append_printf(msgbuf, "\n");
[2b86d14]292  }
[cc305b5]293  owl_log_enqueue_message(msgbuf->str, filename);
294  g_string_free(msgbuf, TRUE);
[2b86d14]295
[e3a75ed]296  filename = g_strdup_printf("%s/all", logpath);
[ddbbcffa]297  g_free(logpath);
[cc305b5]298  msgbuf = g_string_new("");
299  g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);
300  if (text[strlen(text)-1] != '\n') {
301    g_string_append_printf(msgbuf, "\n");
[2b86d14]302  }
[cc305b5]303  owl_log_enqueue_message(msgbuf->str, filename);
304  g_string_free(msgbuf, TRUE);
[2b86d14]305
[ddbbcffa]306  g_free(tobuff);
[2b86d14]307}
308
[c08c70a]309void owl_log_incoming(const owl_message *m)
[15283bb]310{
[e3a75ed]311  char *filename, *allfilename, *logpath;
[e19eb97]312  const char *from=NULL;
[65b2173]313  char *frombuff=NULL;
[7d4fbcd]314  int len, ch, i, personal;
[12c35df]315
[15b34fd]316  /* figure out if it's a "personal" message or not */
[aac889a]317  if (owl_message_is_type_zephyr(m)) {
318    if (owl_message_is_personal(m)) {
[42947f1]319      personal = 1;
[aac889a]320    } else {
[42947f1]321      personal = 0;
[aac889a]322    }
[2182be3]323  } else if (owl_message_is_type_jabber(m)) {
[42947f1]324    /* This needs to be fixed to handle groupchat */
[e19eb97]325    const char* msgtype = owl_message_get_attribute_value(m,"jtype");
[42947f1]326    if (msgtype && !strcmp(msgtype,"groupchat")) {
327      personal = 0;
328    } else {
329      personal = 1;
330    }
[7d4fbcd]331  } else {
[79a0e82]332    if (owl_message_is_private(m) || owl_message_is_loginout(m)) {
[42947f1]333      personal = 1;
[aac889a]334    } else {
[42947f1]335      personal = 0;
[aac889a]336    }
[7d4fbcd]337  }
338
[2182be3]339
[aac889a]340  if (owl_message_is_type_zephyr(m)) {
341    if (personal) {
[3066d23]342      from=frombuff=short_zuser(owl_message_get_sender(m));
[aac889a]343    } else {
[d4927a7]344      from=frombuff=g_strdup(owl_message_get_class(m));
[7d4fbcd]345    }
[aac889a]346  } else if (owl_message_is_type_aim(m)) {
347    /* we do not yet handle chat rooms */
[28ee32b]348    char *normalto, *temp;
349    temp = owl_aim_normalize_screenname(owl_message_get_sender(m));
350    normalto = g_utf8_strdown(temp, -1);
[3472845]351    from=frombuff=g_strdup_printf("aim:%s", normalto);
[ddbbcffa]352    g_free(normalto);
353    g_free(temp);
[37eab7f]354  } else if (owl_message_is_type_loopback(m)) {
[d4927a7]355    from=frombuff=g_strdup("loopback");
[2182be3]356  } else if (owl_message_is_type_jabber(m)) {
[5c30091]357    if (personal) {
[cc305b5]358      from=frombuff=g_strdup_printf("jabber:%s", 
359                                    owl_message_get_sender(m));
[5c30091]360    } else {
[cc305b5]361      from=frombuff=g_strdup_printf("jabber:%s", 
362                                    owl_message_get_recipient(m));
[5c30091]363    }
[e6449bc]364  } else {
[d4927a7]365    from=frombuff=g_strdup("unknown");
[7d4fbcd]366  }
367 
368  /* check for malicious sender formats */
369  len=strlen(frombuff);
370  if (len<1 || len>35) from="weird";
371  if (strchr(frombuff, '/')) from="weird";
372
373  ch=frombuff[0];
[28ee32b]374  if (!g_ascii_isalnum(ch)) from="weird";
[7d4fbcd]375
376  for (i=0; i<len; i++) {
[e1c4636]377    if (frombuff[i]<'!' || frombuff[i]>='~') from="weird";
[7d4fbcd]378  }
379
380  if (!strcmp(frombuff, ".") || !strcasecmp(frombuff, "..")) from="weird";
381
382  if (!personal) {
[28ee32b]383    if (strcmp(from, "weird")) {
384      char* temp = g_utf8_strdown(frombuff, -1);
385      if (temp) {
[ddbbcffa]386        g_free(frombuff);
[28ee32b]387        from = frombuff = temp;
388      }
389    }
[7d4fbcd]390  }
391
[e1c4636]392  /* create the filename (expanding ~ in path names) */
[7d4fbcd]393  if (personal) {
[60d7935]394    logpath = owl_util_makepath(owl_global_get_logpath(&g));
[e3a75ed]395    filename = g_strdup_printf("%s/%s", logpath, from);
396    allfilename = g_strdup_printf("%s/all", logpath);
[d0961fe]397    owl_log_append(m, allfilename);
[e3a75ed]398    g_free(allfilename);
[7d4fbcd]399  } else {
[60d7935]400    logpath = owl_util_makepath(owl_global_get_classlogpath(&g));
[e3a75ed]401    filename = g_strdup_printf("%s/%s", logpath, from);
[7d4fbcd]402  }
[37eab7f]403
[42947f1]404  owl_log_append(m, filename);
[e3a75ed]405  g_free(filename);
[7d4fbcd]406
[d0961fe]407  if (personal && owl_message_is_type_zephyr(m)) {
[af1920fd]408    /* We want to log to all of the CC'd people who were not us, or
409     * the sender, as well.
410     */
[839697d]411    char *temp;
412    GList *cc;
[d0961fe]413    cc = owl_message_get_cc_without_recipient(m);
[839697d]414    while (cc != NULL) {
415      temp = short_zuser(cc->data);
416      if (strcasecmp(temp, frombuff) != 0) {
[e3a75ed]417        filename = g_strdup_printf("%s/%s", logpath, temp);
[839697d]418        owl_log_append(m, filename);
[e3a75ed]419        g_free(filename);
[d0961fe]420      }
[839697d]421
[ddbbcffa]422      g_free(temp);
423      g_free(cc->data);
[839697d]424      cc = g_list_delete_link(cc, cc);
[d0961fe]425    }
426  }
[7d4fbcd]427
[ddbbcffa]428  g_free(frombuff);
429  g_free(logpath);
[7d4fbcd]430}
[cc305b5]431
432static gpointer owl_log_thread_func(gpointer data)
433{
434  log_context = g_main_context_new();
435  log_loop = g_main_loop_new(log_context, FALSE);
436  g_main_loop_run(log_loop);
437  return NULL;
438}
439
440void owl_log_init(void) 
441{
442  GError *error = NULL;
443  logging_thread = g_thread_create(owl_log_thread_func,
444                                   NULL,
445                                   TRUE,
446                                   &error);
447  if (error) {
448    endwin();
449    fprintf(stderr, "Error spawning logging thread: %s\n", error->message);
450    fflush(stderr);
451    exit(1);
452  }
453 
454}
455
456static void owl_log_quit_func(gpointer data)
457{
458  g_main_loop_quit(log_loop);
459}
460
461void owl_log_shutdown(void)
462{
463  owl_select_post_task(owl_log_quit_func, NULL,
464                       NULL, log_context);
465  g_thread_join(logging_thread);
466}
Note: See TracBrowser for help on using the repository browser.