X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/blobdiff_plain/edb69335f2ca5d42c62f6a4cce0b044da5ef88e8..41efa5ac923c47ebd5538ee5894b11e9ccf7637c:/IkiWiki/Plugin/comments.pm diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm index b45a4a97b..4ed696026 100644 --- a/IkiWiki/Plugin/comments.pm +++ b/IkiWiki/Plugin/comments.pm @@ -9,6 +9,7 @@ use warnings; use strict; use IkiWiki 2.00; use Encode; +use POSIX qw(strftime); use constant PREVIEW => "Preview"; use constant POST_COMMENT => "Post comment"; @@ -17,7 +18,7 @@ use constant CANCEL => "Cancel"; sub import { #{{{ hook(type => "checkconfig", id => 'comments', call => \&checkconfig); hook(type => "getsetup", id => 'comments', call => \&getsetup); - hook(type => "preprocess", id => 'comment', call => \&preprocess); + hook(type => "preprocess", id => '_comment', call => \&preprocess); hook(type => "sessioncgi", id => 'comment', call => \&sessioncgi); hook(type => "htmlize", id => "_comment", call => \&htmlize); hook(type => "pagetemplate", id => "comments", call => \&pagetemplate); @@ -30,6 +31,18 @@ sub htmlize { # {{{ return $params{content}; } # }}} +# FIXME: copied verbatim from meta +sub safeurl ($) { #{{{ + my $url=shift; + if (exists $IkiWiki::Plugin::htmlscrubber::{safe_url_regexp} && + defined $IkiWiki::Plugin::htmlscrubber::safe_url_regexp) { + return $url=~/$IkiWiki::Plugin::htmlscrubber::safe_url_regexp/; + } + else { + return 1; + } +} #}}} + sub preprocess { # {{{ my %params = @_; my $page = $params{page}; @@ -64,30 +77,54 @@ sub preprocess { # {{{ ); }); - # override any metadata + # set metadata, possibly overriding [[!meta]] directives from the + # comment itself + + my $commentuser; + my $commentip; + my $commentauthor; + my $commentauthorurl; if (defined $params{username}) { - my ($authorurl, $author) = linkuser($params{username}); - $pagestate{$page}{meta}{author} = $author; - $pagestate{$page}{meta}{authorurl} = $authorurl; + $commentuser = $params{username}; + ($commentauthorurl, $commentauthor) = + linkuser($params{username}); } - elsif (defined $params{ip}) { - $pagestate{$page}{meta}{author} = sprintf( - gettext("Anonymous (IP: %s)"), - $params{ip}); - delete $pagestate{$page}{meta}{authorurl}; + else { + if (defined $params{ip}) { + $commentip = $params{ip}; + } + $commentauthor = gettext("Anonymous"); + } + + $pagestate{$page}{comments}{commentuser} = $commentuser; + $pagestate{$page}{comments}{commentip} = $commentip; + $pagestate{$page}{comments}{commentauthor} = $commentauthor; + $pagestate{$page}{comments}{commentauthorurl} = $commentauthorurl; + if (!defined $pagestate{$page}{meta}{author}) { + $pagestate{$page}{meta}{author} = $commentauthor; + } + if (!defined $pagestate{$page}{meta}{authorurl}) { + $pagestate{$page}{meta}{authorurl} = $commentauthorurl; + } + + if ($config{comments_allowauthor}) { + if (defined $params{claimedauthor}) { + $pagestate{$page}{meta}{author} = $params{claimedauthor}; + } + + if (defined $params{url} and safeurl($params{url})) { + $pagestate{$page}{meta}{authorurl} = $params{url}; + } } else { - $pagestate{$page}{meta}{author} = gettext("Anonymous"); - delete $pagestate{$page}{meta}{authorurl}; + $pagestate{$page}{meta}{author} = $commentauthor; + $pagestate{$page}{meta}{authorurl} = $commentauthorurl; } if (defined $params{subject}) { $pagestate{$page}{meta}{title} = $params{subject}; } - else { - delete $pagestate{$page}{meta}{title}; - } my $baseurl = urlto($params{destpage}, undef, 1); my $anchor = ""; @@ -146,7 +183,15 @@ sub getsetup () { #{{{ type => 'boolean', default => 0, example => 0, - description => 'Allow directives in newly posted comments?', + description => 'Interpret directives in comments?', + safe => 1, + rebuild => 0, + }, + comments_allowauthor => { + type => 'boolean', + default => 0, + example => 0, + description => 'Allow anonymous commenters to set an author name?', safe => 1, rebuild => 0, }, @@ -168,15 +213,6 @@ sub checkconfig () { #{{{ unless defined $config{comments_pagename}; } #}}} -# FIXME: logic taken from editpage, should be common code? -sub getcgiuser ($) { # {{{ - my $session = shift; - my $user = $session->param('name'); - $user = $ENV{REMOTE_ADDR} unless defined $user; - debug("getcgiuser() -> $user"); - return $user; -} # }}} - # This is exactly the same as recentchanges_link :-( sub linkcgi ($) { #{{{ my $cgi=shift; @@ -242,10 +278,10 @@ sub sessioncgi ($$) { #{{{ my @buttons = (POST_COMMENT, PREVIEW, CANCEL); my $form = CGI::FormBuilder->new( - fields => [qw{do sid page subject body type}], + fields => [qw{do sid page subject editcontent type author url}], charset => 'utf-8', method => 'POST', - required => [qw{body}], + required => [qw{editcontent}], javascript => 0, params => $cgi, action => $config{cgiurl}, @@ -265,7 +301,7 @@ sub sessioncgi ($$) { #{{{ my $type = $form->param('type'); if (defined $type && length $type && $IkiWiki::hooks{htmlize}{$type}) { - $type = possibly_foolish_untaint($type); + $type = IkiWiki::possibly_foolish_untaint($type); } else { $type = $config{default_pageext}; @@ -275,15 +311,32 @@ sub sessioncgi ($$) { #{{{ @page_types = grep { !/^_/ } keys %{$IkiWiki::hooks{htmlize}}; } + my $allow_author = $config{comments_allowauthor}; + $form->field(name => 'do', type => 'hidden'); $form->field(name => 'sid', type => 'hidden', value => $session->id, force => 1); $form->field(name => 'page', type => 'hidden'); $form->field(name => 'subject', type => 'text', size => 72); - $form->field(name => 'body', type => 'textarea', rows => 10); + $form->field(name => 'editcontent', type => 'textarea', rows => 10); $form->field(name => "type", value => $type, force => 1, type => 'select', options => \@page_types); + $form->tmpl_param(username => $session->param('name')); + + if ($allow_author and !defined $session->param('name')) { + $form->tmpl_param(allowauthor => 1); + $form->field(name => 'author', type => 'text', size => '40'); + $form->field(name => 'url', type => 'text', size => '40'); + } + else { + $form->tmpl_param(allowauthor => 0); + $form->field(name => 'author', type => 'hidden', value => '', + force => 1); + $form->field(name => 'url', type => 'hidden', value => '', + force => 1); + } + # The untaint is OK (as in editpage) because we're about to pass # it to file_pruned anyway my $page = $form->field('page'); @@ -332,11 +385,9 @@ sub sessioncgi ($$) { #{{{ IkiWiki::check_canedit($page . "[postcomment]", $cgi, $session); - my ($authorurl, $author) = linkuser(getcgiuser($session)); - - my $body = $form->field('body') || ''; - $body =~ s/\r\n/\n/g; - $body =~ s/\r/\n/g; + my $editcontent = $form->field('editcontent') || ''; + $editcontent =~ s/\r\n/\n/g; + $editcontent =~ s/\r/\n/g; # FIXME: check that the wiki is locked right now, because # if it's not, there are mad race conditions! @@ -352,8 +403,8 @@ sub sessioncgi ($$) { #{{{ my $anchor = "${comments_pagename}${i}"; - $body =~ s/"/\\"/g; - my $content = "[[!comment format=$type\n"; + $editcontent =~ s/"/\\"/g; + my $content = "[[!_comment format=$type\n"; # FIXME: handling of double quotes probably wrong? if (defined $session->param('name')) { @@ -368,13 +419,28 @@ sub sessioncgi ($$) { #{{{ } } + if ($allow_author) { + my $author = $form->field('author'); + if (length $author) { + $author =~ s/"/"/g; + $content .= " claimedauthor=\"$author\"\n"; + } + my $url = $form->field('url'); + if (length $url) { + $url =~ s/"/"/g; + $content .= " url=\"$url\"\n"; + } + } + my $subject = $form->field('subject'); - $subject =~ s/"/"/g; - $content .= " subject=\"$subject\"\n"; + if (length $subject) { + $subject =~ s/"/"/g; + $content .= " subject=\"$subject\"\n"; + } - $content .= " date=\"" . IkiWiki::formattime(time, '%X %x') . "\"\n"; + $content .= " date=\"" . decode_utf8(strftime('%Y-%m-%dT%H:%M:%SZ', gmtime)) . "\"\n"; - $content .= " content=\"\"\"\n$body\n\"\"\"]]\n"; + $content .= " content=\"\"\"\n$editcontent\n\"\"\"]]\n"; # This is essentially a simplified version of editpage: # - the user does not control the page that's created, only the parent @@ -398,8 +464,6 @@ sub sessioncgi ($$) { #{{{ $template->param(content => $preview); $template->param(title => $form->field('subject')); $template->param(ctime => displaytime(time)); - $template->param(author => $author); - $template->param(authorurl => $authorurl); $form->tmpl_param(page_preview => $template->output); } @@ -495,6 +559,8 @@ sub pagetemplate (@) { #{{{ reverse => 'yes', page => $page, destpage => $params{destpage}, + feedfile => 'comments', + emptyfeeds => 'no', ); $comments = IkiWiki::preprocess_inline(@args); } @@ -509,6 +575,26 @@ sub pagetemplate (@) { #{{{ $template->param(commenturl => $commenturl); } } + + if ($template->query(name => 'commentuser')) { + $template->param(commentuser => + $pagestate{$page}{comments}{commentuser}); + } + + if ($template->query(name => 'commentip')) { + $template->param(commentip => + $pagestate{$page}{comments}{commentip}); + } + + if ($template->query(name => 'commentauthor')) { + $template->param(commentauthor => + $pagestate{$page}{comments}{commentauthor}); + } + + if ($template->query(name => 'commentauthorurl')) { + $template->param(commentauthorurl => + $pagestate{$page}{comments}{commentauthorurl}); + } } # }}} package IkiWiki::PageSpec;