+ }
+}
+
+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);