]> sipb.mit.edu Git - ikiwiki.git/blobdiff - IkiWiki/Plugin/comments.pm
comments: don't interpolate IP into anonymous user's "name"
[ikiwiki.git] / IkiWiki / Plugin / comments.pm
index 13ced6ffd806d456e3549ca90d380dc7f36e56f8..e43bbc49ed3ba0e3606bbb6acb1887ade226b261 100644 (file)
@@ -22,7 +22,6 @@ sub import { #{{{
        hook(type => "htmlize", id => "_comment", call => \&htmlize);
        hook(type => "pagetemplate", id => "comments", call => \&pagetemplate);
        hook(type => "cgi", id => "comments", call => \&linkcgi);
-       IkiWiki::loadplugin("mdwn");
        IkiWiki::loadplugin("inline");
 } # }}}
 
@@ -31,6 +30,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};
@@ -65,30 +76,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 = "";
@@ -147,7 +182,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,
                },
@@ -169,15 +212,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;
@@ -243,10 +277,10 @@ sub sessioncgi ($$) { #{{{
 
        my @buttons = (POST_COMMENT, PREVIEW, CANCEL);
        my $form = CGI::FormBuilder->new(
-               fields => [qw{do sid page subject body}],
+               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},
@@ -264,13 +298,43 @@ sub sessioncgi ($$) { #{{{
                });
        IkiWiki::decode_form_utf8($form);
 
+       my $type = $form->param('type');
+       if (defined $type && length $type && $IkiWiki::hooks{htmlize}{$type}) {
+               $type = IkiWiki::possibly_foolish_untaint($type);
+       }
+       else {
+               $type = $config{default_pageext};
+       }
+       my @page_types;
+       if (exists $IkiWiki::hooks{htmlize}) {
+               @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 => 5,
-               cols => 80);
+       $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
@@ -320,11 +384,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!
@@ -340,8 +402,8 @@ sub sessioncgi ($$) { #{{{
 
        my $anchor = "${comments_pagename}${i}";
 
-       $body =~ s/"/\\"/g;
-       my $content = "[[!comment format=mdwn\n";
+       $editcontent =~ s/"/\\"/g;
+       my $content = "[[!comment format=$type\n";
 
        # FIXME: handling of double quotes probably wrong?
        if (defined $session->param('name')) {
@@ -356,13 +418,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 .= " 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
@@ -371,7 +448,7 @@ sub sessioncgi ($$) { #{{{
        # - this means that if they do, rocks fall and everyone dies
 
        if ($form->submitted eq PREVIEW) {
-               my $preview = IkiWiki::htmlize($location, $page, 'mdwn',
+               my $preview = IkiWiki::htmlize($location, $page, '_comment',
                                IkiWiki::linkify($page, $page,
                                        IkiWiki::preprocess($page, $page,
                                                IkiWiki::filter($location,
@@ -386,8 +463,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);
        }
@@ -497,6 +572,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;