X-Git-Url: http://git.tremily.us/?p=ikiwiki.git;a=blobdiff_plain;f=IkiWiki%2FPlugin%2Fcomments.pm;h=3cafcbe9c6860dbfb95087da454bf364617f1292;hp=bbf850a17f24399a7e1fff86743f1c23d4c7503c;hb=937b24e0cf98d75dd353d80267efddcecab9e908;hpb=6d27bbd026ebed85f8501b6b4daefaba73061574 diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm index bbf850a17..3cafcbe9c 100644 --- a/IkiWiki/Plugin/comments.pm +++ b/IkiWiki/Plugin/comments.pm @@ -26,8 +26,11 @@ sub import { hook(type => "preprocess", id => '_comment', call => \&preprocess); hook(type => "sessioncgi", id => 'comment', call => \&sessioncgi); hook(type => "htmlize", id => "_comment", call => \&htmlize); + hook(type => "htmlize", id => "_comment_pending", + call => \&htmlize_pending); hook(type => "pagetemplate", id => "comments", call => \&pagetemplate); - hook(type => "formbuilder_setup", id => "comments", call => \&formbuilder_setup); + hook(type => "formbuilder_setup", id => "comments", + call => \&formbuilder_setup); # Load goto to fix up user page links for logged-in commenters IkiWiki::loadplugin("goto"); IkiWiki::loadplugin("inline"); @@ -104,6 +107,14 @@ sub htmlize { return $params{content}; } +sub htmlize_pending { + my %params = @_; + return sprintf(gettext("this comment needs %s"), + ''. + gettext("moderation").''); +} + # FIXME: copied verbatim from meta sub safeurl ($) { my $url=shift; @@ -221,7 +232,9 @@ sub preprocess { } if (defined $params{subject}) { - $pagestate{$page}{meta}{title} = $params{subject}; + # decode title the same way meta does + eval q{use HTML::Entities}; + $pagestate{$page}{meta}{title} = decode_entities($params{subject}); } if ($params{page} =~ m/\/\Q$config{comments_pagename}\E\d+_/) { @@ -249,6 +262,10 @@ sub sessioncgi ($$) { elsif ($do eq 'commentmoderation') { commentmoderation($cgi, $session); } + elsif ($do eq 'commentsignin') { + IkiWiki::cgi_signin($cgi, $session); + exit; + } } # Mostly cargo-culted from IkiWiki::plugin::editpage @@ -272,7 +289,7 @@ sub editcomment ($$) { action => $config{cgiurl}, header => 0, table => 0, - template => scalar IkiWiki::template_params('editcomment.tmpl'), + template => { template('editcomment.tmpl') }, ); IkiWiki::decode_form_utf8($form); @@ -326,7 +343,7 @@ sub editcomment ($$) { if (! defined $session->param('name')) { # Make signinurl work and return here. - $form->tmpl_param(signinurl => IkiWiki::cgiurl(do => 'signin')); + $form->tmpl_param(signinurl => IkiWiki::cgiurl(do => 'commentsignin')); $session->param(postsignin => $ENV{QUERY_STRING}); IkiWiki::cgi_savesession($session); } @@ -336,7 +353,7 @@ sub editcomment ($$) { my $page = $form->field('page'); $page = IkiWiki::possibly_foolish_untaint($page); if (! defined $page || ! length $page || - IkiWiki::file_pruned($page, $config{srcdir})) { + IkiWiki::file_pruned($page)) { error(gettext("bad page name")); } @@ -460,9 +477,15 @@ sub editcomment ($$) { $postcomment=0; if (! $ok) { - my $penddir=$config{wikistatedir}."/comments_pending"; - $location=unique_comment_location($page, $content, $penddir); - writefile("$location._comment", $penddir, $content); + $location=unique_comment_location($page, $content, $config{srcdir}, "._comment_pending"); + writefile("$location._comment_pending", $config{srcdir}, $content); + + # Refresh so anything that deals with pending + # comments can be updated. + require IkiWiki::Render; + IkiWiki::refresh(); + IkiWiki::saveindex(); + IkiWiki::printheader($session); print IkiWiki::misctemplate(gettext(gettext("comment stored for moderation")), "

". @@ -538,21 +561,24 @@ sub commentmoderation ($$) { my %vars=$cgi->Vars; my $added=0; foreach my $id (keys %vars) { - if ($id =~ /(.*)\Q._comment\E$/) { + if ($id =~ /(.*)\._comment(?:_pending)?$/) { my $action=$cgi->param($id); next if $action eq 'Defer' && ! $rejectalldefer; # Make sure that the id is of a legal - # pending comment before untainting. - my ($f)= $id =~ /$config{wiki_file_regexp}/; + # pending comment. + my ($f) = $id =~ /$config{wiki_file_regexp}/; if (! defined $f || ! length $f || - IkiWiki::file_pruned($f, $config{srcdir})) { + IkiWiki::file_pruned($f)) { error("illegal file"); } - my $page=IkiWiki::possibly_foolish_untaint(IkiWiki::dirname($1)); - my $file="$config{wikistatedir}/comments_pending/". - IkiWiki::possibly_foolish_untaint($id); + my $page=IkiWiki::dirname($f); + my $file="$config{srcdir}/$f"; + if (! -e $file) { + # old location + $file="$config{wikistatedir}/comments_pending/".$f; + } if ($action eq 'Accept') { my $content=eval { readfile($file) }; @@ -565,9 +591,6 @@ sub commentmoderation ($$) { $added++; } - # This removes empty subdirs, so the - # .ikiwiki/comments_pending dir will - # go away when all are moderated. require IkiWiki::Render; IkiWiki::prune($file); } @@ -594,16 +617,15 @@ sub commentmoderation ($$) { } my @comments=map { - my ($id, $ctime)=@{$_}; - my $file="$config{wikistatedir}/comments_pending/$id"; - my $content=readfile($file); + my ($id, $dir, $ctime)=@{$_}; + my $content=readfile("$dir/$id"); my $preview=previewcomment($content, $id, - IkiWiki::dirname($_), $ctime); + $id, $ctime); { id => $id, view => $preview, - } - } sort { $b->[1] <=> $a->[1] } comments_pending(); + } + } sort { $b->[2] <=> $a->[2] } comments_pending(); my $template=template("commentmoderation.tmpl"); $template->param( @@ -633,30 +655,35 @@ sub formbuilder_setup (@) { } sub comments_pending () { - my $dir="$config{wikistatedir}/comments_pending/"; - return unless -d $dir; - my @ret; + eval q{use File::Find}; error($@) if $@; - find({ - no_chdir => 1, - wanted => sub { - $_=decode_utf8($_); - if (IkiWiki::file_pruned($_, $dir)) { - $File::Find::prune=1; - } - elsif (! -l $_ && ! -d _) { - $File::Find::prune=0; - my ($f)=/$config{wiki_file_regexp}/; # untaint - if (defined $f && $f =~ /\Q._comment\E$/) { - my $ctime=(stat($f))[10]; - $f=~s/^\Q$dir\E\/?//; - push @ret, [$f, $ctime]; + + my $find_comments=sub { + my $dir=shift; + my $extension=shift; + return unless -d $dir; + find({ + no_chdir => 1, + wanted => sub { + my $file=decode_utf8($_); + $file=~s/^\Q$dir\E\/?//; + return if ! length $file || IkiWiki::file_pruned($file) + || -l $_ || -d _ || $file !~ /\Q$extension\E$/; + my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint + if (defined $f) { + my $ctime=(stat($_))[10]; + push @ret, [$f, $dir, $ctime]; } } - } - }, $dir); + }, $dir); + }; + + $find_comments->($config{srcdir}, "._comment_pending"); + # old location + $find_comments->("$config{wikistatedir}/comments_pending/", + "._comment"); return @ret; } @@ -674,7 +701,8 @@ sub previewcomment ($$$) { my $template = template("comment.tmpl"); $template->param(content => $preview); - $template->param(ctime => displaytime($time)); + $template->param(ctime => displaytime($time, undef, 1)); + $template->param(html5 => $config{html5}); IkiWiki::run_hooks(pagetemplate => sub { shift->(page => $location, @@ -690,7 +718,7 @@ sub previewcomment ($$$) { sub commentsshown ($) { my $page=shift; - return ! pagespec_match($page, "internal(*/$config{comments_pagename}*)", + return ! pagespec_match($page, "comment(*)", location => $page) && pagespec_match($page, $config{comments_pagespec}, location => $page); @@ -720,7 +748,7 @@ sub pagetemplate (@) { my $comments = undef; if ($shown) { $comments = IkiWiki::preprocess_inline( - pages => "internal($page/$config{comments_pagename}*)", + pages => "comment($page)", template => 'comment', show => 0, reverse => 'yes', @@ -834,35 +862,34 @@ sub num_comments ($$) { return @comments; } -sub unique_comment_location ($$$) { +sub unique_comment_location ($$$$) { my $page=shift; - eval q{use Digest::MD5 'md5_hex'}; error($@) if $@; my $content_md5=md5_hex(Encode::encode_utf8(shift)); - my $dir=shift; + my $ext=shift || "._comment"; my $location; my $i = num_comments($page, $dir); do { $i++; $location = "$page/$config{comments_pagename}${i}_${content_md5}"; - } while (-e "$dir/$location._comment"); + } while (-e "$dir/$location$ext"); return $location; } sub page_to_id ($) { # Converts a comment page name into a unique, legal html id - # addtibute value, that can be used as an anchor to link to the + # attribute value, that can be used as an anchor to link to the # comment. my $page=shift; eval q{use Digest::MD5 'md5_hex'}; error($@) if $@; - return "comment-".md5_hex(Encode::encode_utf8(($page)); + return "comment-".md5_hex(Encode::encode_utf8(($page))); } package IkiWiki::PageSpec; @@ -874,7 +901,37 @@ sub match_postcomment ($$;@) { if (! $postcomment) { return IkiWiki::FailReason->new("not posting a comment"); } - return match_glob($page, $glob); + return match_glob($page, $glob, @_); +} + +sub match_comment ($$;@) { + my $page = shift; + my $glob = shift; + + if (! IkiWiki::isinternal($page)) { + return IkiWiki::FailReason->new("$page is not a comment"); + } + my $type=IkiWiki::pagetype($IkiWiki::pagesources{$page}); + if (defined $type && $type ne "_comment") { + return IkiWiki::FailReason->new("$page is not a comment"); + } + + return match_glob($page, "$glob/*", internal => 1, @_); +} + +sub match_comment_pending ($$;@) { + my $page = shift; + my $glob = shift; + + if (! IkiWiki::isinternal($page)) { + return IkiWiki::FailReason->new("$page is not a pending comment"); + } + my $type=IkiWiki::pagetype($IkiWiki::pagesources{$page}); + if (defined $type && $type ne "_comment_pending") { + return IkiWiki::FailReason->new("$page is not a pending comment"); + } + + return match_glob($page, "$glob/*", internal => 1, @_); } 1