X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/de5b1b004578c44dcc7d33748941108a88c6eb9d..c56d48dbd92fbb24b6d0da77df4dc5384f6e564f:/IkiWiki/Plugin/mailbox.pm diff --git a/IkiWiki/Plugin/mailbox.pm b/IkiWiki/Plugin/mailbox.pm index 8f501ea40..92ddf99f3 100644 --- a/IkiWiki/Plugin/mailbox.pm +++ b/IkiWiki/Plugin/mailbox.pm @@ -5,67 +5,89 @@ # 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]) }; + package IkiWiki::Plugin::mailbox; +use Email::FolderType qw(folder_type); use IkiWiki 2.00; -use Email::Folder; 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; + 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}}, - '' + '' } sub preprocess (@) { #{{{ my %params=@_; my $page=$params{page}; - my $type=$params{type} || 'maildir'; + my $type=$params{type} || 'Maildir'; my $path=$params{path} || error gettext("missing parameter") . " path"; # hmm, this should probably only be inserted once per page. - # note, mbox is not a directory, needs to be special cased - my $dir=bestdir($page,$params{path}) || + my $dir=bestpath($page,$params{path}) || error("could not find ".$params{path}); $params{path} = $config{srcdir} ."/" . $dir; - - return format_mailbox(path=>$dir,%params); + $params{type} = $type; + + return format_mailbox(%params); } # }}} +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 sub format_mailbox(@){ my %params=@_; - my $path=$params{path} || error("path parameter mandatory"); + my $path=$params{path} || error gettext("missing parameter "). 'path'; + my $type=$params{type} || error gettext("missing paramater ")."type"; - my $folder=Email::MIMEFolder->new($path) || error("mailbox could not be opened"); + debug('type='.$type); + my $folder=Email::MIMEFolder->new($path,reader=>'Email::Folder::'.$type) || error("mailbox could not be opened"); my $threader=new Email::Thread($folder->messages); $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(@){ @@ -76,28 +98,53 @@ 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; + $output .= sprintf gettext("Message %s not available"), $thread->messageid; } if ($thread->child){ $output .= '
' . - format_thread(thread=>$thread->child). + format_thread(%params,thread=>$thread->child). '
'; } 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; + my $strategy= $config{mailbox_obfuscation_strategy} || "delete"; + + return $val if ($strategy eq "none"); + + if ($hdrname =~ qr/From|To|Reply-To|CC/){ + my @addrs=Email::Address->parse($val); + foreach my $addr (@addrs){ + if ($strategy eq "rot13"){ + my $orig=$addr->address; + $orig =~ y/A-Za-z/N-ZA-Mn-za-m/; + $addr->address($orig); + } else { + $addr->address(gettext("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}; @@ -109,7 +156,11 @@ sub format_message(@){ my $message=$params{message} || error gettext("missing parameter"). "message"; - my $keep_headers=$params{headers} || qr/^(subject|from|date)/i; + + my $dest=$params{destpage} || + error gettext("missing parameter"). "destpage"; + + my $keep_headers=$params{headers} || qr/^(subject|from|date)[:]?$/i; my $template= template("email.tmpl") || error gettext("missing template"); @@ -117,13 +168,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 $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); - my $body= join("\n", map { $_->body } $message->parts); + 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)); @@ -141,10 +217,10 @@ sub format_body($){ } ### Utilities -# From Arpit Jain +# based on bestdir From Arpit Jain # http://ikiwiki.info/todo/Bestdir_along_with_bestlink_in_IkiWiki.pm/ # need to clarify license -sub bestdir ($$) { #{{{ +sub bestpath ($$) { #{{{ my $page=shift; my $link=shift; my $cwd=$page; @@ -157,7 +233,7 @@ sub bestdir ($$) { #{{{ my $l=$cwd; $l.="/" if length $l; $l.=$link; - if (-d "$config{srcdir}/$l") { + if (-d "$config{srcdir}/$l" || -f "$config{srcdir}/$l") { return $l; } } while $cwd=~s!/?[^/]+$!!; @@ -165,7 +241,7 @@ sub bestdir ($$) { #{{{ if (length $config{userdir}) { my $l = "$config{userdir}/".lc($link); - if (-d $l) { + if (-d $l || -f $l) { return $l; } } @@ -179,6 +255,11 @@ sub pagetemplate (@) { #{{{ my $destpage=$params{destpage}; my $template=$params{template}; + + if ($page =~ /.*comments/ && defined($config{mailbox_copyright})){ + $template->param(COPYRIGHT=>$config{mailbox_copyright}); + } + if (exists $metaheaders{$page} && $template->query(name => "meta")) { # avoid duplicate meta lines my %seen; @@ -188,4 +269,19 @@ sub pagetemplate (@) { #{{{ +package Email::FolderType::MH; + +sub match { + my $folder = shift; + return 0 if (! -d $folder); + opendir DIR,$folder || error("opendir failed"); + + while (){ + return 0 if (!m|\.| && !m|\.\.| && !m|\d+|); + } + return 1; +} + + + 1;