Changeset dca6255


Ignore:
Timestamp:
Jan 7, 2014, 6:00:46 PM (8 years ago)
Author:
Jason Gross <jgross@mit.edu>
Children:
e38cc20
Parents:
e7ab1d7
git-author:
Jason Gross <jgross@mit.edu> (07/12/11 14:42:39)
git-committer:
Jason Gross <jgross@mit.edu> (01/07/14 18:00:46)
Message:
Moved log file name generation to perl

I don't think that the class/personal distinction is the best for
general protocols, but I don't know what should replace it.  I've made
class-logging default to only zephyr (a slight change from previous
behavior, where jabber MUC's would be logged to $classlogpath, as well
as all non-private non-login messages from other protocols), but made
logging path generation overridable.

TODO: Decide whether or not to filter out more 'bad' characters.
Perhaps we should remove '!' because it indicates history in some shells
and makes things obnoxious, or '~' becase it indicates homedirs in many
shells.
* '/' is for separating directories, and we don't want to accidentally
  make subdirectories

We first NFKC for zephyrs, and then apply lc.  The zephyr servers
apply case-folded NFKC (so says
http://zephyr.1ts.org/browser/zephyr/server/zstring.c).  We should
probably use Unicode::CaseFold instead of lc.  I'm also not sure what
the order case-adjustment and normalization should be.

We first NFKC, then apply lc, to jabbers, as per
http://xmpp.org/internet-drafts/attic/draft-ietf-xmpp-nodeprep-03.html
(though I can't actually find anything that specifies the case-folding
algorithm, nor the ordering).

We now use lc instead of g_utf8_strdown to normalize AIM screennames.
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • logging.c

    rc877a63 rdca6255  
    3030  }
    3131
    32   /* handle incmoing messages */
    33   if (owl_message_is_direction_in(m)) {
    34     owl_log_incoming(m);
    35     owl_function_debugmsg("owl_log_message: leaving");
    36     return;
    37   }
    38 
    39   /* handle outgoing messages */
    40   owl_log_outgoing(m);
     32  owl_log_perl(m);
    4133
    4234  owl_function_debugmsg("owl_log_message: leaving");
     
    133125  g_free(buffer);
    134126}
    135 
    136 void owl_log_outgoing(const owl_message *m)
    137 {
    138   char *filename, *logpath;
    139   char *to, *temp;
    140   GList *cc;
    141 
    142   /* expand ~ in path names */
    143   logpath = owl_util_makepath(owl_global_get_logpath(&g));
    144 
    145   /* Figure out what path to log to */
    146   if (owl_message_is_type_zephyr(m)) {
    147     /* If this has CC's, do all but the "recipient" which we'll do below */
    148     cc = owl_message_get_cc_without_recipient(m);
    149     while (cc != NULL) {
    150       temp = short_zuser(cc->data);
    151       filename = g_build_filename(logpath, temp, NULL);
    152       owl_log_append(m, filename);
    153 
    154       g_free(filename);
    155       g_free(temp);
    156       g_free(cc->data);
    157       cc = g_list_delete_link(cc, cc);
    158     }
    159 
    160     to = short_zuser(owl_message_get_recipient(m));
    161   } else if (owl_message_is_type_jabber(m)) {
    162     to = g_strdup_printf("jabber:%s", owl_message_get_recipient(m));
    163     g_strdelimit(to, "/", '_');
    164   } else if (owl_message_is_type_aim(m)) {
    165     char *temp2;
    166     temp = owl_aim_normalize_screenname(owl_message_get_recipient(m));
    167     temp2 = g_utf8_strdown(temp,-1);
    168     to = g_strdup_printf("aim:%s", temp2);
    169     g_free(temp2);
    170     g_free(temp);
    171   } else {
    172     to = g_strdup("loopback");
    173   }
    174 
    175   filename = g_build_filename(logpath, to, NULL);
    176   owl_log_append(m, filename);
    177   g_free(to);
    178   g_free(filename);
    179 
    180   filename = g_build_filename(logpath, "all", NULL);
    181   owl_log_append(m, filename);
    182   g_free(logpath);
    183   g_free(filename);
    184 }
    185 
    186127
    187128void owl_log_outgoing_zephyr_error(const owl_zwrite *zw, const char *text)
     
    232173}
    233174
    234 void owl_log_incoming(const owl_message *m)
    235 {
    236   char *filename, *allfilename, *logpath;
    237   const char *from=NULL;
    238   char *frombuff=NULL;
    239   int len, ch, i, personal;
    240 
    241   /* figure out if it's a "personal" message or not */
    242   if (owl_message_is_type_zephyr(m)) {
    243     if (owl_message_is_personal(m)) {
    244       personal = 1;
    245     } else {
    246       personal = 0;
    247     }
    248   } else if (owl_message_is_type_jabber(m)) {
    249     /* This needs to be fixed to handle groupchat */
    250     const char* msgtype = owl_message_get_attribute_value(m,"jtype");
    251     if (msgtype && !strcmp(msgtype,"groupchat")) {
    252       personal = 0;
    253     } else {
    254       personal = 1;
    255     }
    256   } else {
    257     if (owl_message_is_private(m) || owl_message_is_loginout(m)) {
    258       personal = 1;
    259     } else {
    260       personal = 0;
    261     }
    262   }
    263 
    264 
    265   if (owl_message_is_type_zephyr(m)) {
    266     if (personal) {
    267       from=frombuff=short_zuser(owl_message_get_sender(m));
    268     } else {
    269       from=frombuff=g_strdup(owl_message_get_class(m));
    270     }
    271   } else if (owl_message_is_type_aim(m)) {
    272     /* we do not yet handle chat rooms */
    273     char *normalto, *temp;
    274     temp = owl_aim_normalize_screenname(owl_message_get_sender(m));
    275     normalto = g_utf8_strdown(temp, -1);
    276     from=frombuff=g_strdup_printf("aim:%s", normalto);
    277     g_free(normalto);
    278     g_free(temp);
    279   } else if (owl_message_is_type_loopback(m)) {
    280     from=frombuff=g_strdup("loopback");
    281   } else if (owl_message_is_type_jabber(m)) {
    282     if (personal) {
    283       from=frombuff=g_strdup_printf("jabber:%s",
    284                                     owl_message_get_sender(m));
    285     } else {
    286       from=frombuff=g_strdup_printf("jabber:%s",
    287                                     owl_message_get_recipient(m));
    288     }
    289   } else {
    290     from=frombuff=g_strdup("unknown");
    291   }
    292  
    293   /* check for malicious sender formats */
    294   len=strlen(frombuff);
    295   if (len<1 || len>35) from="weird";
    296   if (strchr(frombuff, '/')) from="weird";
    297 
    298   ch=frombuff[0];
    299   if (!g_ascii_isalnum(ch)) from="weird";
    300 
    301   for (i=0; i<len; i++) {
    302     if (frombuff[i]<'!' || frombuff[i]>='~') from="weird";
    303   }
    304 
    305   if (!strcmp(frombuff, ".") || !strcasecmp(frombuff, "..")) from="weird";
    306 
    307   if (!personal) {
    308     if (strcmp(from, "weird")) {
    309       char* temp = g_utf8_strdown(frombuff, -1);
    310       if (temp) {
    311         g_free(frombuff);
    312         from = frombuff = temp;
    313       }
    314     }
    315   }
    316 
    317   /* create the filename (expanding ~ in path names) */
    318   if (personal) {
    319     logpath = owl_util_makepath(owl_global_get_logpath(&g));
    320     filename = g_build_filename(logpath, from, NULL);
    321     allfilename = g_build_filename(logpath, "all", NULL);
    322     owl_log_append(m, allfilename);
    323     g_free(allfilename);
    324   } else {
    325     logpath = owl_util_makepath(owl_global_get_classlogpath(&g));
    326     filename = g_build_filename(logpath, from, NULL);
    327   }
    328 
    329   owl_log_append(m, filename);
    330   g_free(filename);
    331 
    332   if (personal && owl_message_is_type_zephyr(m)) {
    333     /* We want to log to all of the CC'd people who were not us, or
    334      * the sender, as well.
    335      */
    336     char *temp;
    337     GList *cc;
    338     cc = owl_message_get_cc_without_recipient(m);
    339     while (cc != NULL) {
    340       temp = short_zuser(cc->data);
    341       if (strcasecmp(temp, frombuff) != 0) {
    342         filename = g_build_filename(logpath, temp, NULL);
    343         owl_log_append(m, filename);
    344         g_free(filename);
    345       }
    346 
    347       g_free(temp);
    348       g_free(cc->data);
    349       cc = g_list_delete_link(cc, cc);
    350     }
    351   }
    352 
    353   g_free(frombuff);
    354   g_free(logpath);
     175void owl_log_perl(const owl_message *m)
     176{
     177  char *filenames_string = owl_perlconfig_call_with_message("BarnOwl::Logging::get_filenames_as_string", m);
     178  char **filenames = g_strsplit(filenames_string, "\n", 0);
     179  char **filename_ptr;
     180  g_free(filenames_string);
     181
     182  for (filename_ptr = filenames; *filename_ptr != NULL; filename_ptr++) {
     183    owl_log_append(m, *filename_ptr);
     184  }
     185
     186  g_strfreev(filenames);
    355187}
    356188
  • perl/Makefile.am

    ra870319 rdca6255  
    1313        lib/BarnOwl/Hook.pm \
    1414        lib/BarnOwl/Hooks.pm \
     15        lib/BarnOwl/Logging.pm \
    1516        lib/BarnOwl/MainLoopCompatHook.pm \
    1617        lib/BarnOwl/Message.pm \
  • perl/lib/BarnOwl.pm

    recd4edf rdca6255  
    3838use BarnOwl::Hook;
    3939use BarnOwl::Hooks;
     40use BarnOwl::Logging;
    4041use BarnOwl::Message;
    4142use BarnOwl::Style;
  • perl/lib/BarnOwl/Message.pm

    rc877a63 rdca6255  
    160160        return $m->body;
    161161    }
     162}
     163
     164=head2 log_filenames MESSAGE
     165
     166Returns a list of filenames to which this message should be logged.
     167The filenames should be relative to the path returned by
     168C<log_base_path>.  See L<BarnOwl::Logging::get_filenames> for the
     169specification of valid filenames, and for what happens if this
     170method returns an invalid filename.
     171
     172=cut
     173
     174sub log_filenames {
     175    my ($m) = @_;
     176    my $filename = lc($m->type);
     177    $filename = "unknown" if !defined $filename || $filename eq '';
     178    if ($m->is_incoming && $m->pretty_sender) {
     179        $filename .= ":" . $m->pretty_sender;
     180    } elsif ($m->is_outgoing && $m->pretty_recipient) {
     181        $filename .= ":" . $m->pretty_recipient;
     182    }
     183    return ($filename);
     184}
     185
     186=head2 log_to_all_file MESSAGE
     187
     188There is an C<all> file.  This method determines if C<MESSAGE>
     189should get logged to it, in addition to any files returned by
     190C<log_filenames>.
     191
     192It defaults to returning true if and only if C<MESSAGE> is outgoing.
     193
     194=cut
     195
     196sub log_to_all_file {
     197    my ($m) = @_;
     198    return $m->is_outgoing;
     199}
     200
     201=head2 log_base_path MESSAGE
     202
     203Returns the base path for logging, the folder in which all messages
     204of this class get logged.
     205
     206Defaults to the BarnOwl variable C<logpath>.
     207
     208=cut
     209
     210sub log_base_path {
     211    return BarnOwl::getvar('logpath');
    162212}
    163213
  • perl/lib/BarnOwl/Message/AIM.pm

    r7011c3dc rdca6255  
    2424}
    2525
     26sub normalize_screenname {
     27    my ($screenname) = @_;
     28    $screenname =~ s/\s+//g;
     29    return lc($screenname);
     30}
     31
     32sub log_filenames {
     33    return map { normalize_screenname($_) } BarnOwl::Message::log_filenames(@_);
     34}
    2635
    27361;
  • perl/lib/BarnOwl/Message/Zephyr.pm

    rc877a63 rdca6255  
    99
    1010use base qw( BarnOwl::Message );
     11use Unicode::Normalize qw( NFKC );
    1112
    1213sub strip_realm {
     
    132133    return $1 if $self->body =~ /^\s*cc:\s+([^\n]+)/i;
    133134    return undef;
     135}
     136
     137sub zephyr_cc_without_recipient {
     138    my $self = shift;
     139    my $recipient = lc(strip_realm($self->recipient));
     140    my $cc = $self->zephyr_cc;
     141    return grep { lc(strip_realm($_)) ne $recipient } split(/\s+/, $cc) if defined $cc;
     142    return ();
    134143}
    135144
     
    240249}
    241250
     251sub log_filenames {
     252    my ($m) = @_;
     253    my @filenames = ();
     254    if ($m->is_personal) {
     255        @filenames = $m->zephyr_cc_without_recipient;
     256    }
     257    if ($m->is_incoming) {
     258        if ($m->is_personal) {
     259            push @filenames, $m->sender;
     260        } else {
     261            return (lc(NFKC($m->class)));
     262        }
     263    } else {
     264        push @filenames, $m->recipient;
     265    }
     266    return map { lc(NFKC(strip_realm($_))) } @filenames;
     267}
     268
     269sub log_to_class_file {
     270    my ($m) = @_;
     271    return !$m->is_personal;
     272}
     273
     274sub log_base_path {
     275    my ($m) = @_;
     276    if ($m->log_to_class_file) {
     277        return BarnOwl::getvar('classlogpath');
     278    } else {
     279        return BarnOwl::getvar('logpath');
     280    }
     281}
     282
    2422831;
  • perl/modules/Jabber/lib/BarnOwl/Message/Jabber.pm

    ra27acf7 rdca6255  
    1515
    1616use base qw( BarnOwl::Message );
     17use Unicode::Normalize qw( NFKC );
    1718
    1819sub jtype { shift->{jtype} };
     
    172173}
    173174
     175sub log_filenames {
     176    return map { lc(NFKC($_)) } BarnOwl::Message::log_filenames(@_);
     177}
     178
    174179=head1 SEE ALSO
    175180
Note: See TracChangeset for help on using the changeset viewer.