, section => "widget"
};
}
+my $params_re
+ = qr{
+ (?>
+ (?>(?:[^\[\]]|\[[^\[]|\][^\]])+)
+ |
+ (?'loop'
+ \[\[
+ (?>
+ (?>(?:[^\[\]]|\[[^\[]|\][^\]])+)
+ |
+ (?&loop)
+ )*
+ \]\]
+ )
+ )*
+ }x;
sub scan (@) {
my %params = @_;
- my $page = $params{page};
my $content = $params{content};
my $prefix = $config{prefix_directives} ? "!poll" : "poll";
- my $type = IkiWiki::pagetype($pagesources{$page});
+ my $type = IkiWiki::pagetype($pagesources{$params{page}});
if (defined $type and $type eq "mdwn") {
my %polls = ();
- while ($content =~ m{(\\?)\[\[\Q$prefix\E(\s+id="([^"]*)")?\s+(.+?)\s*\]\]}gs) {
+ while ($content =~ m{(\\?)\[\[\Q$prefix\E(\s+id="([^"]*)")?\s+($params_re)\s*\]\]}gs) {
my ($escape, $poll, $directive) = ($1, $3, $4);
next if $escape;
$poll = '' unless defined $poll;
- error("poll id=`$poll' must match (|[a-z][a-z0-9_-]*) on page=`$page'")
+ error("poll id=`$poll' must match (|[a-z][a-z0-9_-]*) on page=`$params{page}'")
unless $poll =~ m/^(|[a-z][a-z0-9_-]*)$/;
my %poll = ();
+ my $userdir = defined $config{userdir} ? $config{userdir}.'/' : '';
while ($directive =~ m/(^|\s+)(\d+)(="([^"]*)")?\s+"?([^"]*)"?/gs) {
my ($unknown_votes, $known_votes, $choice) = ($2, $4, $5);
- my @known_votes = defined $known_votes ? split(/\s+/, $known_votes) : ();
- $poll{$choice} =
- { unknown_votes => $unknown_votes
- , known_votes => \@known_votes
- };
+ my @known_votes = defined $known_votes ? grep {length $_ > 0} (split(/\s+/, $known_votes)) : ();
+ $poll{$choice} =
+ { unknown_votes => $unknown_votes
+ , known_votes => \@known_votes
+ };
foreach my $user (@known_votes) {
- my $userpage = linkpage(($config{userdir}?$config{userdir}.'/':'').$user);
- add_link($page, $userpage);
+ my $userpage_best = bestlink($params{page}, $user);
+ $userpage_best = (length $userpage_best > 0 ? $userpage_best : bestlink($userdir, $user));
+ $userpage_best = (length $userpage_best > 0 ? $userpage_best : ($user =~ m{/} ? '/' : $userdir).$user);
+ #debug("user=$user");
+ #debug("userpage_best=$userpage_best");
+ add_link($params{page}, $userpage_best);
}
}
- error("poll id=`$poll' already exists on page=`$page'")
+ error("poll id=`$poll' already exists on page=`$params{page}'")
if exists $polls{$poll};
$polls{$poll} = \%poll;
}
- $IkiWiki::pagestate{$page}{poll} = \%polls;
+ $IkiWiki::pagestate{$params{page}}{poll} = \%polls;
}
}
sub preprocess (@) {
my $known_votes = shift;
next
unless $unknown_votes =~ /^\d+$/;
- my @users = $known_votes ? split(/\s+/, $known_votes) : ();
+ my @users = $known_votes ? grep {length $_ > 0} (split(/\s+/, $known_votes)) : ();
my $choice = shift;
shift;
my $tot = ($unknown_votes + @users);
}
use URI::Escape;
my $uri_page = URI::Escape::uri_escape_utf8($params{page}, '^A-Za-z0-9\-\._~/');
+ my $userdir = defined $config{userdir} ? $config{userdir}.'/' : '';
my $ret="";
foreach my $choice (@choices) {
if ($open && exists $config{cgiurl}) {
if $showpercent;
if (@{$choices{$choice}{users}} > 0) {
$votes .= " : ".join(', ', map {
- my $userpage = linkpage(($config{userdir}?$config{userdir}.'/':'').$_);
- htmllink($params{page}, $params{destpage}, '/'.$userpage, linktext => pagetitle($_))
+ my $user = $_;
+ #my $userpage = linkpage(($config{userdir}?$config{userdir}.'/':'').$_);
+ #htmllink($params{page}, $params{destpage}, $userpage, linktext => pagetitle($_))
+ my $userpage_best = bestlink($userdir, $user);
+ $userpage_best = (length $userpage_best > 0 ? $userpage_best : bestlink($userdir, $user));
+ $userpage_best = (length $userpage_best > 0 ? $userpage_best : ($user =~ m{/} ? '/' : $userdir).$user);
+ htmllink
+ ( $params{page}
+ , $params{destpage}
+ , $userpage_best
+ , noimageinline => 1 )
} @{$choices{$choice}{users}});
$votes .= " + ".$choices{$choice}{unknown_votes}." "
. ($choices{$choice}{unknown_votes} > 1 ? gettext("unknowns") : gettext("unknown"))
if $choices{$choice}{unknown_votes};
}
if ($open && exists $config{cgiurl}) {
+ my $choice_escaped = URI::Escape::uri_escape_utf8($choice, '^A-Za-z0-9\ \-\._~/');
$ret.="<input type=\"hidden\" name=\"do\" value=\"poll\" />\n";
$ret.="<input type=\"hidden\" name=\"num\" value=\"$num\" />\n";
$ret.="<input type=\"hidden\" name=\"page\" value=\"$uri_page\" />\n";
- $ret.="<input type=\"hidden\" name=\"choice\" value=\"$choice\" />\n";
+ $ret.="<input type=\"hidden\" name=\"choice\" value=\"$choice_escaped\" />\n";
$ret.="<input type=\"submit\" value=\"".gettext("vote")."\" />\n";
}
$ret.="<span class='description'>$choice</span>";
my $cgi=shift;
my $session=shift;
if (defined $cgi->param('do') && $cgi->param('do') eq "poll") {
- my $choice=decode_utf8($cgi->param('choice'));
+ my $choice = Encode::decode_utf8(URI::Escape::uri_unescape(IkiWiki::possibly_foolish_untaint($cgi->param('choice'))));
+
if (! defined $choice || not length $choice) {
error("no choice specified");
}
use Data::Dumper;
error("bad page name");
}
+ &IkiWiki::check_canedit($page, $cgi, $session);
# Did they vote before? If so, let them change their vote,
# and check for dups.
my $user = $session->param("name");
my %users;
foreach (split(/\s+/, $known_votes)) {
- $users{$_} = 1;
+ $users{$_} = 1
+ if length $_ > 0;
}
if ($action eq 'add') {
if (defined $user) {
return "$params";
};
my $id='';
- $content =~ s{(\\?)\[\[\Q$prefix\E(\s+id="([^"]*)")?(\s+)(.+?)(\s*)\]\]}{$id=$3;$1.'[['.$prefix.$2.$4.$edit->($1, $5).$6.']]'}gse;
+ $content =~
+ s{
+ (?<escape>\\?)
+ \[\[\Q$prefix\E
+ (?:(?<id_space>\s+)id="(?<id>[^"]*)")?
+ (?<params_space>\s+)
+ (?<params>$params_re)
+ (?<end_space>\s*)
+ \]\]
+ }
+ {$id=$+{id};
+ $+{escape}
+ .'[['.$prefix
+ .($+{id} eq ''?'':$+{id_space}.'id="'.$+{id}.'"')
+ .$+{params_space}
+ .$edit->($+{escape}, $+{params})
+ .$+{end_space}
+ .']]'
+ }egsx;
# Store their vote, update the page, and redirect to it.
writefile($pagesources{$page}, $config{srcdir}, $content);
my ($page, $match, %params) = @_;
my $polls = $IkiWiki::pagestate{$page}{poll};
if (defined $polls and %$polls) {
- my ($match_poll, $match_user, $match_choice) = $match =~ m/^id=(.*?) user=(.*?) choice=(.*?)$/;
- if (exists $polls->{$match_poll}) {
- my %poll = %{$polls->{$match_poll}};
+ my ($match_id, $match_user, $match_choice) = $match =~ m/^id=(.*?) user=(.*?) choice=(.*?)$/;
+ my $match_id_re = IkiWiki::glob2re($match_id?$match_id:'*');
+ my @polls = grep {$_ =~ $match_id_re} (keys %$polls);
+ return IkiWiki::FailReason->new("no poll match id=`$match_id'", $page => $IkiWiki::DEPEND_CONTENT)
+ unless @polls > 0;
+ foreach my $poll (@polls) {
+ my %poll = %{$polls->{$poll}};
my $match_user_re = IkiWiki::glob2re($match_user?$match_user:'*');
my $match_choice_re = IkiWiki::glob2re($match_choice?$match_choice:'*');
while (my ($choice, $data) = each %poll) {
}
}
}
- return IkiWiki::FailReason->new("no user=`$match_user' has voted for choice=`$match_choice'", $page => $IkiWiki::DEPEND_CONTENT);
- }
- else {
- return IkiWiki::FailReason->new("no poll id=`$match_poll'", $page => $IkiWiki::DEPEND_CONTENT);
}
+ return IkiWiki::FailReason->new("no user=`$match_user' has voted for choice=`$match_choice'", $page => $IkiWiki::DEPEND_CONTENT);
}
else {
return IkiWiki::FailReason->new("no poll", $page => $IkiWiki::DEPEND_CONTENT);