]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/Plugin/mailbox.pm
Initial, hardcoded address sanitizing
[git.ikiwiki.info.git] / IkiWiki / Plugin / mailbox.pm
index d925e42be0d2b6ca7e3ae2476a5ce79524436b3d..75a64d61b2fcd001a716a07ef26867cf86dac0af 100644 (file)
@@ -5,6 +5,7 @@
 # This file is distributed under the Artistic License/GPL2+
 
 use Email::MIME;
+use Email::MIME::Modifier;
 package Email::MIMEFolder;
 use base 'Email::Folder';
 sub bless_message { return  Email::MIME->new($_[1]) };
@@ -16,9 +17,10 @@ use Email::FolderType qw(folder_type);
 use IkiWiki 2.00;
 use Email::Thread;
 use CGI 'escapeHTML';
-use Data::Dumper;
-
-
+use File::Temp qw/tempfile/;
+use File::MimeInfo::Magic;
+use Date::Parse;
+use Email::Address;
 
 my %metaheaders;
 
@@ -27,14 +29,18 @@ sub import { #{{{
        hook(type => "preprocess", id => "mailbox", call => \&preprocess);
        hook(type => "scan", id => "mailbox", call => \&scan);
        hook(type => "pagetemplate", id=>"mailbox", call => \&pagetemplate);
+       hook(type => "htmlize",id=>"mbox",call => \&mbox_htmlize);
+       IkiWiki::loadplugin("filecheck");
 } # }}}
 
 sub scan(@){
        my %params=@_;
        my $page=$params{page};
+       
+       my $linktext=$config{url}.'/mailbox.css';
 
        push @{$metaheaders{$page}}, 
-              '<link rel="stylesheet" href="mailbox.css" type="text/css"/>'
+              '<link rel="stylesheet" href="'.$linktext.'" type="text/css"/>'
 }
 
 sub preprocess (@) { #{{{
@@ -57,6 +63,12 @@ sub preprocess (@) { #{{{
 
 } # }}}
 
+sub mbox_htmlize(@){
+    my %params=@_;
+    
+    my $path=$config{srcdir} . '/' . $params{page}.".mbox";
+    return format_mailbox(path=>$path,type=>'Mbox',destpage=>$params{page});
+}
 
 ### The guts of the plugin
 ### parameters 
@@ -71,7 +83,11 @@ sub format_mailbox(@){
 
     $threader->thread();
 
-    return join "\n", map { format_thread(thread=>$_) } $threader->rootset;
+    my @roots= sort  { str2time($a->header('Date'))  <=> 
+                          str2time($b->header('Date'))}  ($threader->rootset);
+
+    return join "\n", map { format_thread(%params,thread=>$_) } @roots; 
+
 }
 
 sub format_thread(@){
@@ -82,28 +98,44 @@ sub format_thread(@){
     my $output="";
 
     if ($thread->message) {
-       $output .= format_message(message=>$thread->message);
+       $output .= format_message(%params,message=>$thread->message);
     } else {
        $output .= sprintf gettext("Message %s not available"), $thread->messageid;
     }
 
     if ($thread->child){
        $output .= '<div class="emailthreadindent">' .
-           format_thread(thread=>$thread->child).
+           format_thread(%params,thread=>$thread->child).
            '</div>';
     }
 
     if ($thread->next){
-       $output .= format_thread(thread=>$thread->next);
+       $output .= format_thread(%params,thread=>$thread->next);
     }
     return $output;
 }
 
+sub sanitize_address($$){
+    my $hdrname=shift;
+    my $val=shift;
+
+    if ($hdrname =~ qr/From|To|Reply-To|CC/){
+       my @addrs=Email::Address->parse($val);
+       foreach my $addr (@addrs){
+           $addr->address("DELETED");
+       }
+       $val=join(",",map {$_->format;} @addrs);
+    }
+    return $val;
+                    }
+
 sub make_pair($$){
     my $message=shift;
     my $name=shift;
-    my $val=$message->header($_);
-    
+    my $val=$message->header($name);
+
+    $val = sanitize_address($name,$val);
+
     $val = escapeHTML($val);
 
     my $hash={'HEADERNAME'=>$name,'VAL'=>$val};
@@ -115,6 +147,10 @@ sub format_message(@){
     my $message=$params{message} || 
        error gettext("missing parameter"). "message";
 
+
+    my $dest=$params{destpage} || 
+       error gettext("missing parameter"). "destpage";
+
     my $keep_headers=$params{headers} || qr/^(subject|from|date)[:]?$/i;
     
     my $template= 
@@ -123,13 +159,38 @@ sub format_message(@){
     my $output="";
 
     my @names = grep  {m/$keep_headers/;}  ($message->header_names);
+    
     my @headers=map { make_pair($message,$_) } @names;
     
+    
 
     $template->param(HEADERS=>[@headers]);
 
+    my $allowed_attachments=$params{allowed_attachments} || 
+       "maxsize(100kb) and mimetype(text/plain)";
+
+    my @parts=$message->parts;
 
-    my $body= join("\n", map { $_->body }  $message->parts);
+    my $partcount=1;
+    foreach(@parts){
+       #this sucks. But someone would need to modify filecheck to
+       #accept a blob of content. Or maybe hacking with IO::Scalar
+       my $tmpfile=File::Temp->new();
+
+       binmode $tmpfile,':utf8';
+       print $tmpfile $_->body();
+
+       my $allowed=pagespec_match($dest, $allowed_attachments, file=>$tmpfile);
+
+       if (!$allowed) {
+           debug("clobbering attachment $partcount");
+           $_->content_type_set('text/plain');
+           $_->body_set("[ omitting part $partcount: $allowed ]");
+
+       }
+       $partcount++;
+    }
+    my $body= join("\n", map { $_->body }  @parts);
 
     $template->param(body=>format_body($body));