+ my $form=$params{form};
+ if ($form->title eq "preferences" &&
+ IkiWiki::is_admin($params{session}->param("name"))) {
+ push @{$params{buttons}}, "Comment Moderation";
+ if ($form->submitted && $form->submitted eq "Comment Moderation") {
+ commentmoderation($params{cgi}, $params{session});
+ }
+ }
+}
+
+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];
+ }
+ }
+ }
+ }, $dir);
+
+ return @ret;
+}
+
+sub previewcomment ($$$) {
+ my $content=shift;
+ my $location=shift;
+ my $page=shift;
+ my $time=shift;
+
+ my $preview = IkiWiki::htmlize($location, $page, '_comment',
+ IkiWiki::linkify($location, $page,
+ IkiWiki::preprocess($location, $page,
+ IkiWiki::filter($location, $page, $content), 0, 1)));
+
+ my $template = template("comment.tmpl");
+ $template->param(content => $preview);
+ $template->param(ctime => displaytime($time));
+
+ IkiWiki::run_hooks(pagetemplate => sub {
+ shift->(page => $location,
+ destpage => $page,
+ template => $template);
+ });
+
+ $template->param(have_actions => 0);
+
+ return $template->output;
+}
+
+sub commentsshown ($) {
+ my $page=shift;
+
+ return ! pagespec_match($page, "internal(*/$config{comments_pagename}*)",
+ location => $page) &&
+ pagespec_match($page, $config{comments_pagespec},
+ location => $page);
+}
+
+sub commentsopen ($) {
+ my $page = shift;
+
+ return length $config{cgiurl} > 0 &&
+ (! length $config{comments_closed_pagespec} ||
+ ! pagespec_match($page, $config{comments_closed_pagespec},
+ location => $page));
+}
+
+sub pagetemplate (@) {
+ my %params = @_;
+
+ my $page = $params{page};
+ my $template = $params{template};
+ my $shown = ($template->query(name => 'commentslink') ||
+ $template->query(name => 'commentsurl') ||
+ $template->query(name => 'atomcommentsurl') ||
+ $template->query(name => 'comments')) &&
+ commentsshown($page);
+
+ if ($template->query(name => 'comments')) {
+ my $comments = undef;
+ if ($shown) {
+ $comments = IkiWiki::preprocess_inline(
+ pages => "internal($page/$config{comments_pagename}*)",
+ template => 'comment',
+ show => 0,
+ reverse => 'yes',
+ page => $page,
+ destpage => $params{destpage},
+ feedfile => 'comments',
+ emptyfeeds => 'no',
+ );
+ }
+
+ if (defined $comments && length $comments) {
+ $template->param(comments => $comments);
+ }
+
+ if ($shown && commentsopen($page)) {
+ my $addcommenturl = IkiWiki::cgiurl(do => 'comment',
+ page => $page);
+ $template->param(addcommenturl => $addcommenturl);
+ }
+ }
+
+ if ($template->query(name => 'commentsurl')) {
+ if ($shown) {
+ $template->param(commentsurl =>
+ urlto($page, undef, 1).'#comments');
+ }
+ }
+
+ if ($template->query(name => 'atomcommentsurl') && $config{usedirs}) {
+ if ($shown) {
+ # This will 404 until there are some comments, but I
+ # think that's probably OK...
+ $template->param(atomcommentsurl =>
+ urlto($page, undef, 1).'comments.atom');
+ }
+ }
+
+ if ($template->query(name => 'commentslink')) {
+ # XXX Would be nice to say how many comments there are in
+ # the link. But, to update the number, blog pages
+ # would have to update whenever comments of any inlines
+ # page are added, which is not currently done.
+ if ($shown) {
+ $template->param(commentslink =>
+ htmllink($page, $params{destpage}, $page,
+ linktext => gettext("Comments"),
+ anchor => "comments",
+ noimageinline => 1));
+ }
+ }
+
+ # everything below this point is only relevant to the comments
+ # themselves
+ if (!exists $commentstate{$page}) {
+ return;
+ }
+
+ if ($template->query(name => 'commentid')) {
+ $template->param(commentid => page_to_id($page));
+ }
+
+ if ($template->query(name => 'commentuser')) {
+ $template->param(commentuser =>
+ $commentstate{$page}{commentuser});
+ }
+
+ if ($template->query(name => 'commentopenid')) {
+ $template->param(commentopenid =>
+ $commentstate{$page}{commentopenid});
+ }
+
+ if ($template->query(name => 'commentip')) {
+ $template->param(commentip =>
+ $commentstate{$page}{commentip});
+ }
+
+ if ($template->query(name => 'commentauthor')) {
+ $template->param(commentauthor =>
+ $commentstate{$page}{commentauthor});
+ }
+
+ if ($template->query(name => 'commentauthorurl')) {
+ $template->param(commentauthorurl =>
+ $commentstate{$page}{commentauthorurl});
+ }
+
+ if ($template->query(name => 'removeurl') &&
+ IkiWiki::Plugin::remove->can("check_canremove") &&
+ length $config{cgiurl}) {
+ $template->param(removeurl => IkiWiki::cgiurl(do => 'remove',
+ page => $page));
+ $template->param(have_actions => 1);
+ }
+}
+
+sub num_comments ($$) {
+ my $page=shift;
+ my $dir=shift;
+
+ my @comments=glob("$dir/$page/$config{comments_pagename}*._comment");
+ return @comments;
+}
+
+sub unique_comment_location ($$$) {
+ my $page=shift;
+
+ eval q{use Digest::MD5 'md5_hex'};
+ error($@) if $@;
+ my $content_md5=md5_hex(shift);
+
+ my $dir=shift;
+
+ my $location;
+ my $i = num_comments($page, $dir);
+ do {
+ $i++;
+ $location = "$page/$config{comments_pagename}${i}_${content_md5}";
+ } while (-e "$dir/$location._comment");
+
+ 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
+ # comment.
+ my $page=shift;
+
+ eval q{use Digest::MD5 'md5_hex'};
+ error($@) if $@;
+
+ return "comment-".md5_hex($page);
+}
+