Exclude working directory from library path (CVE-2016-1238)
[ikiwiki] / ikiwiki-comment.in
1 #!/usr/bin/perl
2 no lib '.';
3 use warnings;
4 use strict;
5 use FindBin; use lib $FindBin::Bin; # For use in nonstandard directory, munged by Makefile.
6 use IkiWiki;
7 use IkiWiki::Plugin::comments;
8 use Getopt::Long;
9
10 sub usage {
11         die gettext("usage: ikiwiki-comment pagefile [options]") . "\n";
12 }
13
14 sub main {
15         my $pagefile=shift || usage();
16         my $interactive = -t STDIN;
17         my $content;
18         my ($format, $username, $subject, $date, $url, $email, $ip);
19         GetOptions(
20                 'format:s'      => \$format,
21                 'username:s'    => \$username,
22                 'subject:s'     => \$subject,
23                 'date:s'        => \$date,
24                 'url:s'         => \$url,
25                 'email:s'       => \$email,
26                 'ip:s'          => \$ip,
27         ) || usage();
28
29         my $dir=get_dir($pagefile);
30         my $page=get_page($pagefile);
31
32         IkiWiki::Plugin::comments::checkconfig();
33
34         if ($interactive) {
35                 $format         ||= 'mdwn';
36                 $username       ||= get_username();
37                 $subject        ||= get_subject($page, $dir);
38                 $date           ||= IkiWiki::Plugin::comments::commentdate();
39                 $url            ||= undef;
40                 $email          ||= undef;
41                 $ip             ||= undef;
42         } else {
43                 $format         ||= undef;
44                 die "must supply username" unless defined $username;
45                 $subject        ||= get_subject($page, $dir);
46                 die "must supply date" unless defined $date;
47                 $url            ||= undef;
48                 $email          ||= undef;
49                 $ip             ||= undef;
50                 chomp($content = join('', <STDIN>));
51         }
52
53         my $comment=get_comment($format, $username, $subject, $date, $url, $email, $ip, $content);
54
55         # For interactive use, this will yield a hash of the comment before
56         # it's edited, but that's ok; the date provides sufficient entropy
57         # to avoid collisions, and the hash of a comment does not need to
58         # match its actual content.
59         # Doing it this way avoids needing to move the file to a final
60         # location after it's edited.
61         my $location=IkiWiki::Plugin::comments::unique_comment_location($page, $comment, $dir)."._comment";
62
63         IkiWiki::writefile($location, $dir, $comment);
64         exec_editor("$dir/$location") if $interactive;
65 }
66
67 sub get_dir {
68         my ($file) = @_;
69         my $dir=IkiWiki::dirname($file);
70         $dir="." unless length $dir;
71         return $dir;
72 }
73
74 sub get_page {
75         my ($file) = @_;
76         my $page=IkiWiki::basename($file);
77         $page=~s/\.[^.]+$// unless -d $file;
78         return $page;
79 }
80
81 sub get_username {
82         my $username = getpwuid($<);
83         $username="" unless defined $username;
84         return $username;
85 }
86
87 sub get_subject {
88         my ($page, $dir) = @_;
89         my $comment_num=1+IkiWiki::Plugin::comments::num_comments($page, $dir);
90         return "comment $comment_num";
91 }
92
93 sub get_comment {
94         my ($format, $username, $subject, $date, $url, $email, $ip, $content) = @_;
95         $format = defined $format ? $format = " format=$format" : q{};
96         $content = '' unless defined $content;
97         my $comment="[[!comment$format\n";
98         $comment.=" username=\"$username\"\n";
99         $comment.=" subject=\"\"\"$subject\"\"\"\n";
100         $comment.=" date=\"$date\"\n";
101         $comment.=" url=\"$url\"\n" if defined $url;
102         $comment.=" email=\"$email\"\n" if defined $email;
103         $comment.=" ip=\"$ip\"\n" if defined $ip;
104         $comment.=" content=\"\"\"\n$content\n\"\"\"]]\n";
105         return $comment;
106 }
107
108 sub exec_editor {
109         my ($file) = @_;
110
111         my @editor="vi";
112         if (-x "/usr/bin/editor") {
113                 @editor="/usr/bin/editor";
114         }
115         if (exists $ENV{EDITOR}) {
116                 @editor=split(' ', $ENV{EDITOR});
117         }
118         if (exists $ENV{VISUAL}) {
119                 @editor=split(' ', $ENV{VISUAL});
120         }
121         exec(@editor, $file);
122 }
123
124 main(@ARGV);