summaryrefslogtreecommitdiff
path: root/IkiWiki
diff options
context:
space:
mode:
Diffstat (limited to 'IkiWiki')
-rw-r--r--IkiWiki/Plugin/404.pm1
-rw-r--r--IkiWiki/Plugin/amazon_s3.pm6
-rw-r--r--IkiWiki/Plugin/anonok.pm1
-rw-r--r--IkiWiki/Plugin/attachment.pm1
-rw-r--r--IkiWiki/Plugin/autoindex.pm20
-rw-r--r--IkiWiki/Plugin/blogspam.pm1
-rw-r--r--IkiWiki/Plugin/bzr.pm31
-rw-r--r--IkiWiki/Plugin/calendar.pm32
-rw-r--r--IkiWiki/Plugin/color.pm10
-rw-r--r--IkiWiki/Plugin/comments.pm64
-rw-r--r--IkiWiki/Plugin/conditional.pm3
-rw-r--r--IkiWiki/Plugin/creole.pm1
-rw-r--r--IkiWiki/Plugin/cutpaste.pm1
-rw-r--r--IkiWiki/Plugin/cvs.pm6
-rw-r--r--IkiWiki/Plugin/darcs.pm16
-rw-r--r--IkiWiki/Plugin/date.pm1
-rw-r--r--IkiWiki/Plugin/editdiff.pm1
-rw-r--r--IkiWiki/Plugin/editpage.pm12
-rw-r--r--IkiWiki/Plugin/edittemplate.pm1
-rw-r--r--IkiWiki/Plugin/filecheck.pm18
-rw-r--r--IkiWiki/Plugin/format.pm10
-rw-r--r--IkiWiki/Plugin/fortune.pm1
-rw-r--r--IkiWiki/Plugin/getsource.pm1
-rw-r--r--IkiWiki/Plugin/git.pm52
-rw-r--r--IkiWiki/Plugin/google.pm1
-rw-r--r--IkiWiki/Plugin/goto.pm1
-rw-r--r--IkiWiki/Plugin/graphviz.pm1
-rw-r--r--IkiWiki/Plugin/haiku.pm1
-rw-r--r--IkiWiki/Plugin/highlight.pm3
-rw-r--r--IkiWiki/Plugin/hnb.pm1
-rw-r--r--IkiWiki/Plugin/html.pm1
-rw-r--r--IkiWiki/Plugin/htmlscrubber.pm7
-rw-r--r--IkiWiki/Plugin/httpauth.pm72
-rw-r--r--IkiWiki/Plugin/img.pm1
-rw-r--r--IkiWiki/Plugin/inline.pm6
-rw-r--r--IkiWiki/Plugin/link.pm1
-rw-r--r--IkiWiki/Plugin/linkmap.pm1
-rw-r--r--IkiWiki/Plugin/listdirectives.pm1
-rw-r--r--IkiWiki/Plugin/lockedit.pm1
-rw-r--r--IkiWiki/Plugin/map.pm1
-rw-r--r--IkiWiki/Plugin/mdwn.pm1
-rw-r--r--IkiWiki/Plugin/mercurial.pm6
-rw-r--r--IkiWiki/Plugin/meta.pm78
-rw-r--r--IkiWiki/Plugin/mirrorlist.pm1
-rw-r--r--IkiWiki/Plugin/moderatedcomments.pm38
-rw-r--r--IkiWiki/Plugin/monotone.pm6
-rw-r--r--IkiWiki/Plugin/more.pm1
-rw-r--r--IkiWiki/Plugin/norcs.pm8
-rw-r--r--IkiWiki/Plugin/opendiscussion.pm5
-rw-r--r--IkiWiki/Plugin/openid.pm66
-rw-r--r--IkiWiki/Plugin/orphans.pm1
-rw-r--r--IkiWiki/Plugin/otl.pm1
-rw-r--r--IkiWiki/Plugin/pagecount.pm1
-rw-r--r--IkiWiki/Plugin/pagestats.pm22
-rw-r--r--IkiWiki/Plugin/parentlinks.pm1
-rw-r--r--IkiWiki/Plugin/passwordauth.pm58
-rw-r--r--IkiWiki/Plugin/po.pm9
-rw-r--r--IkiWiki/Plugin/poll.pm1
-rw-r--r--IkiWiki/Plugin/polygen.pm1
-rw-r--r--IkiWiki/Plugin/postsparkline.pm1
-rw-r--r--IkiWiki/Plugin/progress.pm1
-rw-r--r--IkiWiki/Plugin/rawhtml.pm1
-rw-r--r--IkiWiki/Plugin/recentchanges.pm2
-rw-r--r--IkiWiki/Plugin/relativedate.pm2
-rw-r--r--IkiWiki/Plugin/remove.pm3
-rw-r--r--IkiWiki/Plugin/rename.pm5
-rw-r--r--IkiWiki/Plugin/repolist.pm1
-rw-r--r--IkiWiki/Plugin/search.pm16
-rw-r--r--IkiWiki/Plugin/shortcut.pm1
-rw-r--r--IkiWiki/Plugin/sidebar.pm59
-rw-r--r--IkiWiki/Plugin/signinedit.pm1
-rw-r--r--IkiWiki/Plugin/sortnaturally.pm32
-rw-r--r--IkiWiki/Plugin/sparkline.pm1
-rw-r--r--IkiWiki/Plugin/svn.pm46
-rw-r--r--IkiWiki/Plugin/table.pm1
-rw-r--r--IkiWiki/Plugin/tag.pm31
-rw-r--r--IkiWiki/Plugin/template.pm11
-rw-r--r--IkiWiki/Plugin/teximg.pm4
-rw-r--r--IkiWiki/Plugin/textile.pm1
-rw-r--r--IkiWiki/Plugin/tla.pm8
-rw-r--r--IkiWiki/Plugin/toc.pm1
-rw-r--r--IkiWiki/Plugin/toggle.pm1
-rw-r--r--IkiWiki/Plugin/txt.pm10
-rw-r--r--IkiWiki/Plugin/typography.pm2
-rw-r--r--IkiWiki/Plugin/version.pm1
-rw-r--r--IkiWiki/Plugin/websetup.pm61
-rw-r--r--IkiWiki/Plugin/wikitext.pm1
-rw-r--r--IkiWiki/Plugin/wmd.pm3
-rw-r--r--IkiWiki/Render.pm73
-rw-r--r--IkiWiki/Setup.pm163
-rw-r--r--IkiWiki/Setup/Automator.pm34
-rw-r--r--IkiWiki/Setup/Standard.pm72
-rw-r--r--IkiWiki/Setup/Yaml.pm50
-rw-r--r--IkiWiki/Wrapper.pm16
94 files changed, 1106 insertions, 306 deletions
diff --git a/IkiWiki/Plugin/404.pm b/IkiWiki/Plugin/404.pm
index 85486e559..8adfd5dd9 100644
--- a/IkiWiki/Plugin/404.pm
+++ b/IkiWiki/Plugin/404.pm
@@ -21,6 +21,7 @@ sub getsetup () {
# server admin action too
safe => 0,
rebuild => 0,
+ section => "web",
}
}
diff --git a/IkiWiki/Plugin/amazon_s3.pm b/IkiWiki/Plugin/amazon_s3.pm
index 3571c4189..cfd8cd347 100644
--- a/IkiWiki/Plugin/amazon_s3.pm
+++ b/IkiWiki/Plugin/amazon_s3.pm
@@ -133,6 +133,10 @@ sub getbucket {
}
if (! $bucket) {
+ # Try to use existing bucket.
+ $bucket=$s3->bucket($config{amazon_s3_bucket});
+ }
+ if (! $bucket) {
error(gettext("Failed to create S3 bucket: ").
$s3->err.": ".$s3->errstr."\n");
}
@@ -178,7 +182,7 @@ sub writefile ($$$;$$) {
# First, write the file to disk.
my $ret=$IkiWiki::Plugin::amazon_s3::subs{'IkiWiki::writefile'}->($file, $destdir, $content, $binary, $writer);
-
+
my @keys=IkiWiki::Plugin::amazon_s3::file2keys("$destdir/$file");
# Store the data in S3.
diff --git a/IkiWiki/Plugin/anonok.pm b/IkiWiki/Plugin/anonok.pm
index 243b98920..0e74cbfad 100644
--- a/IkiWiki/Plugin/anonok.pm
+++ b/IkiWiki/Plugin/anonok.pm
@@ -15,6 +15,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
anonok_pagespec => {
type => "pagespec",
diff --git a/IkiWiki/Plugin/attachment.pm b/IkiWiki/Plugin/attachment.pm
index cbe6efc21..ad1dd9bca 100644
--- a/IkiWiki/Plugin/attachment.pm
+++ b/IkiWiki/Plugin/attachment.pm
@@ -19,6 +19,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "web",
},
allowed_attachments => {
type => "pagespec",
diff --git a/IkiWiki/Plugin/autoindex.pm b/IkiWiki/Plugin/autoindex.pm
index 555856b11..c71d73349 100644
--- a/IkiWiki/Plugin/autoindex.pm
+++ b/IkiWiki/Plugin/autoindex.pm
@@ -61,8 +61,16 @@ sub refresh () {
}
my %deleted;
- if (ref $pagestate{index}{autoindex}{deleted}) {
- %deleted=%{$pagestate{index}{autoindex}{deleted}};
+ if (ref $wikistate{autoindex}{deleted}) {
+ %deleted=%{$wikistate{autoindex}{deleted}};
+ }
+ elsif (ref $pagestate{index}{autoindex}{deleted}) {
+ # compatability code
+ %deleted=%{$pagestate{index}{autoindex}{deleted}};
+ delete $pagestate{index}{autoindex};
+ }
+
+ if (keys %deleted) {
foreach my $dir (keys %deleted) {
# remove deleted page state if the deleted page is re-added,
# or if all its subpages are deleted
@@ -71,7 +79,7 @@ sub refresh () {
delete $deleted{$dir};
}
}
- $pagestate{index}{autoindex}{deleted}=\%deleted;
+ $wikistate{autoindex}{deleted}=\%deleted;
}
my @needed;
@@ -82,10 +90,10 @@ sub refresh () {
# This page must have just been deleted, so
# don't re-add it. And remember it was
# deleted.
- if (! ref $pagestate{index}{autoindex}{deleted}) {
- $pagestate{index}{autoindex}{deleted}={};
+ if (! ref $wikistate{autoindex}{deleted}) {
+ $wikistate{autoindex}{deleted}={};
}
- ${$pagestate{index}{autoindex}{deleted}}{$dir}=1;
+ ${$wikistate{autoindex}{deleted}}{$dir}=1;
}
else {
push @needed, $dir;
diff --git a/IkiWiki/Plugin/blogspam.pm b/IkiWiki/Plugin/blogspam.pm
index 626c8ec42..c4e5cf390 100644
--- a/IkiWiki/Plugin/blogspam.pm
+++ b/IkiWiki/Plugin/blogspam.pm
@@ -18,6 +18,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
blogspam_pagespec => {
type => 'pagespec',
diff --git a/IkiWiki/Plugin/bzr.pm b/IkiWiki/Plugin/bzr.pm
index 883007367..f79ca7c8f 100644
--- a/IkiWiki/Plugin/bzr.pm
+++ b/IkiWiki/Plugin/bzr.pm
@@ -20,6 +20,7 @@ sub import {
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+ hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
}
sub checkconfig () {
@@ -36,6 +37,7 @@ sub getsetup () {
plugin => {
safe => 0, # rcs plugin
rebuild => undef,
+ section => "rcs",
},
bzr_wrapper => {
type => "string",
@@ -72,31 +74,40 @@ sub bzr_log ($) {
my @infos = ();
my $key = undef;
+ my %info;
while (<$out>) {
my $line = $_;
my ($value);
if ($line =~ /^message:/) {
$key = "message";
- $infos[$#infos]{$key} = "";
+ $info{$key} = "";
}
elsif ($line =~ /^(modified|added|renamed|renamed and modified|removed):/) {
$key = "files";
- unless (defined($infos[$#infos]{$key})) { $infos[$#infos]{$key} = ""; }
+ $info{$key} = "" unless defined $info{$key};
}
elsif (defined($key) and $line =~ /^ (.*)/) {
- $infos[$#infos]{$key} .= "$1\n";
+ $info{$key} .= "$1\n";
}
elsif ($line eq "------------------------------------------------------------\n") {
+ push @infos, {%info} if keys %info;
+ %info = ();
$key = undef;
- push (@infos, {});
}
- else {
+ elsif ($line =~ /: /) {
chomp $line;
+ if ($line =~ /^revno: (\d+)/) {
+ $key = "revno";
+ $value = $1;
+ }
+ else {
($key, $value) = split /: +/, $line, 2;
- $infos[$#infos]{$key} = $value;
- }
+ }
+ $info{$key} = $value;
+ }
}
close $out;
+ push @infos, {%info} if keys %info;
return @infos;
}
@@ -212,7 +223,7 @@ sub rcs_recentchanges ($) {
foreach my $info (bzr_log($out)) {
my @pages = ();
my @message = ();
-
+
foreach my $msgline (split(/\n/, $info->{message})) {
push @message, { line => $msgline };
}
@@ -296,4 +307,8 @@ sub rcs_getctime ($) {
return $ctime;
}
+sub rcs_getmtime ($) {
+ error "rcs_getmtime is not implemented for bzr\n"; # TODO
+}
+
1
diff --git a/IkiWiki/Plugin/calendar.pm b/IkiWiki/Plugin/calendar.pm
index 2b87451ce..aeb5f3d29 100644
--- a/IkiWiki/Plugin/calendar.pm
+++ b/IkiWiki/Plugin/calendar.pm
@@ -22,7 +22,7 @@ use warnings;
use strict;
use IkiWiki 3.00;
use Time::Local;
-use POSIX;
+use POSIX ();
my $time=time;
my @now=localtime($time);
@@ -38,6 +38,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
archivebase => {
type => "string",
@@ -46,6 +47,14 @@ sub getsetup () {
safe => 1,
rebuild => 1,
},
+ archive_pagespec => {
+ type => "pagespec",
+ example => "posts/* and !*/Discussion",
+ description => "PageSpec of pages to include in the archives; used by ikiwiki-calendar command",
+ link => 'ikiwiki/PageSpec',
+ safe => 1,
+ rebuild => 0,
+ },
}
sub is_leap_year (@) {
@@ -155,11 +164,11 @@ sub format_month (@) {
# Start producing the month calendar
$calendar=<<EOF;
<table class="month-calendar">
- <caption class="month-calendar-head">
- $purl
- $url
- $nurl
- </caption>
+ <tr>
+ <th class="month-calendar-arrow">$purl</th>
+ <th class="month-calendar-head" colspan="5">$url</th>
+ <th class="month-calendar-arrow">$nurl</th>
+ </tr>
<tr>
EOF
@@ -303,13 +312,14 @@ sub format_year (@) {
add_depends($params{page}, "$archivebase/$nyear", deptype("presence"));
# Start producing the year calendar
+ my $m=$params{months_per_row}-2;
$calendar=<<EOF;
<table class="year-calendar">
- <caption class="year-calendar-head">
- $purl
- $url
- $nurl
- </caption>
+ <tr>
+ <th class="year-calendar-arrow">$purl</th>
+ <th class="year-calendar-head" colspan="$m">$url</th>
+ <th class="year-calendar-arrow">$nurl</th>
+ </tr>
<tr>
<th class="year-calendar-subhead" colspan="$params{months_per_row}">Months</th>
</tr>
diff --git a/IkiWiki/Plugin/color.pm b/IkiWiki/Plugin/color.pm
index 20505893b..d550dd9f4 100644
--- a/IkiWiki/Plugin/color.pm
+++ b/IkiWiki/Plugin/color.pm
@@ -10,6 +10,16 @@ use IkiWiki 3.00;
sub import {
hook(type => "preprocess", id => "color", call => \&preprocess);
hook(type => "format", id => "color", call => \&format);
+ hook(type => "getsetup", id => "color", call => \&getsetup);
+}
+
+sub getsetup () {
+ return
+ plugin => {
+ safe => 1,
+ rebuild => undef,
+ section => "widget",
+ },
}
sub preserve_style ($$$) {
diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm
index 5586cca52..0aa043215 100644
--- a/IkiWiki/Plugin/comments.pm
+++ b/IkiWiki/Plugin/comments.pm
@@ -38,6 +38,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1,
+ section => "web",
},
comments_pagespec => {
type => 'pagespec',
@@ -171,9 +172,8 @@ sub preprocess {
else {
$commentauthorurl = IkiWiki::cgiurl(
do => 'goto',
- page => (length $config{userdir}
- ? "$config{userdir}/$commentuser"
- : "$commentuser"));
+ page => IkiWiki::userpage($commentuser)
+ );
$commentauthor = $commentuser;
}
@@ -221,7 +221,9 @@ sub preprocess {
}
if (defined $params{subject}) {
- $pagestate{$page}{meta}{title} = $params{subject};
+ # decode title the same way meta does
+ eval q{use HTML::Entities};
+ $pagestate{$page}{meta}{title} = decode_entities($params{subject});
}
if ($params{page} =~ m/\/\Q$config{comments_pagename}\E\d+_/) {
@@ -736,39 +738,43 @@ sub pagetemplate (@) {
}
if ($shown && commentsopen($page)) {
- my $addcommenturl = IkiWiki::cgiurl(do => 'comment',
- page => $page);
- $template->param(addcommenturl => $addcommenturl);
+ $template->param(addcommenturl => addcommenturl($page));
}
}
- if ($template->query(name => 'commentsurl')) {
- if ($shown) {
+ if ($shown) {
+ if ($template->query(name => 'commentsurl')) {
$template->param(commentsurl =>
urlto($page, undef, 1).'#comments');
}
- }
- if ($template->query(name => 'atomcommentsurl') && $config{usedirs}) {
- if ($shown) {
+ if ($template->query(name => 'atomcommentsurl') && $config{usedirs}) {
# This will 404 until there are some comments, but I
# think that's probably OK...
$template->param(atomcommentsurl =>
urlto($page, undef, 1).'comments.atom');
}
- }
- if ($template->query(name => 'commentslink')) {
- # XXX Would be nice to say how many comments there are in
- # the link. But, to update the number, blog pages
- # would have to update whenever comments of any inlines
- # page are added, which is not currently done.
- if ($shown) {
- $template->param(commentslink =>
- htmllink($page, $params{destpage}, $page,
- linktext => gettext("Comments"),
+ if ($template->query(name => 'commentslink')) {
+ my $num=num_comments($page, $config{srcdir});
+ my $link;
+ if ($num > 0) {
+ $link = htmllink($page, $params{destpage}, $page,
+ linktext => sprintf(ngettext("%i comment", "%i comments", $num), $num),
anchor => "comments",
- noimageinline => 1));
+ noimageinline => 1
+ );
+ }
+ elsif (commentsopen($page)) {
+ $link = "<a href=\"".addcommenturl($page)."\">".
+ #translators: Here "Comment" is a verb;
+ #translators: the user clicks on it to
+ #translators: post a comment.
+ gettext("Comment").
+ "</a>";
+ }
+ $template->param(commentslink => $link)
+ if defined $link;
}
}
@@ -816,6 +822,12 @@ sub pagetemplate (@) {
}
}
+sub addcommenturl ($) {
+ my $page=shift;
+
+ return IkiWiki::cgiurl(do => 'comment', page => $page);
+}
+
sub num_comments ($$) {
my $page=shift;
my $dir=shift;
@@ -829,7 +841,7 @@ sub unique_comment_location ($$$) {
eval q{use Digest::MD5 'md5_hex'};
error($@) if $@;
- my $content_md5=md5_hex(shift);
+ my $content_md5=md5_hex(Encode::encode_utf8(shift));
my $dir=shift;
@@ -845,14 +857,14 @@ sub unique_comment_location ($$$) {
sub page_to_id ($) {
# Converts a comment page name into a unique, legal html id
- # addtibute value, that can be used as an anchor to link to the
+ # attribute value, that can be used as an anchor to link to the
# comment.
my $page=shift;
eval q{use Digest::MD5 'md5_hex'};
error($@) if $@;
- return "comment-".md5_hex($page);
+ return "comment-".md5_hex(Encode::encode_utf8(($page)));
}
package IkiWiki::PageSpec;
diff --git a/IkiWiki/Plugin/conditional.pm b/IkiWiki/Plugin/conditional.pm
index aad617812..8a5796149 100644
--- a/IkiWiki/Plugin/conditional.pm
+++ b/IkiWiki/Plugin/conditional.pm
@@ -16,6 +16,7 @@ sub getsetup {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
@@ -29,7 +30,7 @@ sub preprocess_if (@) {
}
my $result=0;
- if (! IkiWiki::yesno($params{all}) ||
+ if ((exists $params{all} && ! IkiWiki::yesno($params{all})) ||
# An optimisation to avoid needless looping over every page
# for simple uses of some of the tests.
$params{test} =~ /^([\s\!()]*((enabled|sourcepage|destpage|included)\([^)]*\)|(and|or))[\s\!()]*)+$/) {
diff --git a/IkiWiki/Plugin/creole.pm b/IkiWiki/Plugin/creole.pm
index 425e71043..a1e4b31d3 100644
--- a/IkiWiki/Plugin/creole.pm
+++ b/IkiWiki/Plugin/creole.pm
@@ -17,6 +17,7 @@ sub getsetup {
plugin => {
safe => 1,
rebuild => 1, # format plugin
+ section => "format",
},
}
diff --git a/IkiWiki/Plugin/cutpaste.pm b/IkiWiki/Plugin/cutpaste.pm
index 417442f34..01e9ce043 100644
--- a/IkiWiki/Plugin/cutpaste.pm
+++ b/IkiWiki/Plugin/cutpaste.pm
@@ -19,6 +19,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/cvs.pm b/IkiWiki/Plugin/cvs.pm
index f6db8bc98..360d97249 100644
--- a/IkiWiki/Plugin/cvs.pm
+++ b/IkiWiki/Plugin/cvs.pm
@@ -49,6 +49,7 @@ sub import {
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+ hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
}
sub genwrapper () {
@@ -85,6 +86,7 @@ sub getsetup () {
plugin => {
safe => 0, # rcs plugin
rebuild => undef,
+ section => "rcs",
},
cvsrepo => {
type => "string",
@@ -484,4 +486,8 @@ sub rcs_getctime ($) {
return $date;
}
+sub rcs_getmtime ($) {
+ error "rcs_getmtime is not implemented for cvs\n"; # TODO
+}
+
1
diff --git a/IkiWiki/Plugin/darcs.pm b/IkiWiki/Plugin/darcs.pm
index 0d68f27e5..c1d6661d3 100644
--- a/IkiWiki/Plugin/darcs.pm
+++ b/IkiWiki/Plugin/darcs.pm
@@ -18,6 +18,7 @@ sub import {
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+ hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
}
sub silentsystem (@) {
@@ -51,7 +52,7 @@ sub darcs_info ($$$) {
return $_;
}
-sub file_in_vc($$) {
+sub file_in_vc ($$) {
my $repodir = shift;
my $file = shift;
@@ -69,7 +70,7 @@ sub file_in_vc($$) {
return $found;
}
-sub darcs_rev($) {
+sub darcs_rev ($) {
my $file = shift; # Relative to the repodir.
my $repodir = $config{srcdir};
@@ -78,7 +79,7 @@ sub darcs_rev($) {
return defined $hash ? $hash : "";
}
-sub checkconfig() {
+sub checkconfig () {
if (defined $config{darcs_wrapper} && length $config{darcs_wrapper}) {
push @{$config{wrappers}}, {
wrapper => $config{darcs_wrapper},
@@ -87,11 +88,12 @@ sub checkconfig() {
}
}
-sub getsetup() {
+sub getsetup () {
return
plugin => {
safe => 0, # rcs plugin
rebuild => undef,
+ section => "rcs",
},
darcs_wrapper => {
type => "string",
@@ -237,7 +239,7 @@ sub rcs_commit ($$$;$$) {
}
}
-sub rcs_commit_staged($$$) {
+sub rcs_commit_staged ($$$) {
my ($message, $user, $ipaddr) = @_;
my $author;
@@ -426,4 +428,8 @@ sub rcs_getctime ($) {
return $date;
}
+sub rcs_getmtime ($) {
+ error "rcs_getmtime is not implemented for darcs\n"; # TODO
+}
+
1
diff --git a/IkiWiki/Plugin/date.pm b/IkiWiki/Plugin/date.pm
index 652e6df0a..ea5c9a9c5 100644
--- a/IkiWiki/Plugin/date.pm
+++ b/IkiWiki/Plugin/date.pm
@@ -15,6 +15,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/editdiff.pm b/IkiWiki/Plugin/editdiff.pm
index 7df6a9ffb..d8f53a42e 100644
--- a/IkiWiki/Plugin/editdiff.pm
+++ b/IkiWiki/Plugin/editdiff.pm
@@ -19,6 +19,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "web",
},
}
diff --git a/IkiWiki/Plugin/editpage.pm b/IkiWiki/Plugin/editpage.pm
index fca970c60..44fe5514a 100644
--- a/IkiWiki/Plugin/editpage.pm
+++ b/IkiWiki/Plugin/editpage.pm
@@ -17,6 +17,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1,
+ section => "core",
},
}
@@ -245,8 +246,9 @@ sub cgi_editpage ($$) {
push @page_locs, $dir.$page;
}
- push @page_locs, "$config{userdir}/$page"
- if length $config{userdir};
+ my $userpage=IkiWiki::userpage($page);
+ push @page_locs, $userpage
+ if ! grep { $_ eq $userpage } @page_locs;
}
@page_locs = grep {
@@ -271,8 +273,10 @@ sub cgi_editpage ($$) {
check_canedit($_, $q, $session, 1)
} @page_locs;
if (! @editable_locs) {
- # let it throw an error this time
- map { check_canedit($_, $q, $session) } @page_locs;
+ # now let it throw an error, or prompt for
+ # login
+ map { check_canedit($_, $q, $session) }
+ ($best_loc, @page_locs);
}
my @page_types;
diff --git a/IkiWiki/Plugin/edittemplate.pm b/IkiWiki/Plugin/edittemplate.pm
index a163b0d84..5f0551d92 100644
--- a/IkiWiki/Plugin/edittemplate.pm
+++ b/IkiWiki/Plugin/edittemplate.pm
@@ -23,6 +23,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "web",
},
}
diff --git a/IkiWiki/Plugin/filecheck.pm b/IkiWiki/Plugin/filecheck.pm
index 01d490961..1549b82db 100644
--- a/IkiWiki/Plugin/filecheck.pm
+++ b/IkiWiki/Plugin/filecheck.pm
@@ -5,7 +5,7 @@ use warnings;
use strict;
use IkiWiki 3.00;
-my %units=( #{{{ # size in bytes
+my %units=( # size in bytes
B => 1,
byte => 1,
KB => 2 ** 10,
@@ -75,9 +75,9 @@ sub match_maxsize ($$;@) {
}
my %params=@_;
- my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page};
+ my $file=exists $params{file} ? $params{file} : IkiWiki::srcfile($IkiWiki::pagesources{$page});
if (! defined $file) {
- return IkiWiki::ErrorReason->new("no file specified");
+ return IkiWiki::ErrorReason->new("file does not exist");
}
if (-s $file > $maxsize) {
@@ -96,9 +96,9 @@ sub match_minsize ($$;@) {
}
my %params=@_;
- my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page};
+ my $file=exists $params{file} ? $params{file} : IkiWiki::srcfile($IkiWiki::pagesources{$page});
if (! defined $file) {
- return IkiWiki::ErrorReason->new("no file specified");
+ return IkiWiki::ErrorReason->new("file does not exist");
}
if (-s $file < $minsize) {
@@ -114,9 +114,9 @@ sub match_mimetype ($$;@) {
my $wanted=shift;
my %params=@_;
- my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page};
+ my $file=exists $params{file} ? $params{file} : IkiWiki::srcfile($IkiWiki::pagesources{$page});
if (! defined $file) {
- return IkiWiki::ErrorReason->new("no file specified");
+ return IkiWiki::ErrorReason->new("file does not exist");
}
# Use ::magic to get the mime type, the idea is to only trust
@@ -147,9 +147,9 @@ sub match_virusfree ($$;@) {
my $wanted=shift;
my %params=@_;
- my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page};
+ my $file=exists $params{file} ? $params{file} : IkiWiki::srcfile($IkiWiki::pagesources{$page});
if (! defined $file) {
- return IkiWiki::ErrorReason->new("no file specified");
+ return IkiWiki::ErrorReason->new("file does not exist");
}
if (! exists $IkiWiki::config{virus_checker} ||
diff --git a/IkiWiki/Plugin/format.pm b/IkiWiki/Plugin/format.pm
index 1513cbed7..d54e71131 100644
--- a/IkiWiki/Plugin/format.pm
+++ b/IkiWiki/Plugin/format.pm
@@ -7,6 +7,16 @@ use IkiWiki 3.00;
sub import {
hook(type => "preprocess", id => "format", call => \&preprocess);
+ hook(type => "getsetup", id => "format", call => \&getsetup);
+}
+
+sub getsetup () {
+ return
+ plugin => {
+ safe => 1,
+ rebuild => undef,
+ section => "widget",
+ },
}
sub preprocess (@) {
diff --git a/IkiWiki/Plugin/fortune.pm b/IkiWiki/Plugin/fortune.pm
index 17e57dea1..f481c7eac 100644
--- a/IkiWiki/Plugin/fortune.pm
+++ b/IkiWiki/Plugin/fortune.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/getsource.pm b/IkiWiki/Plugin/getsource.pm
index d1555430e..b362de726 100644
--- a/IkiWiki/Plugin/getsource.pm
+++ b/IkiWiki/Plugin/getsource.pm
@@ -17,6 +17,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1,
+ section => "web",
},
getsource_mimetype => {
type => "string",
diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm
index 1eec6aee6..aa402c04f 100644
--- a/IkiWiki/Plugin/git.pm
+++ b/IkiWiki/Plugin/git.pm
@@ -25,6 +25,7 @@ sub import {
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+ hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
hook(type => "rcs", id => "rcs_receive", call => \&rcs_receive);
}
@@ -68,6 +69,7 @@ sub getsetup () {
plugin => {
safe => 0, # rcs plugin
rebuild => undef,
+ section => "rcs",
},
git_wrapper => {
type => "string",
@@ -614,23 +616,51 @@ sub rcs_diff ($) {
}
}
-sub rcs_getctime ($) {
+{
+my %time_cache;
+
+sub findtimes ($$) {
my $file=shift;
+ my $id=shift; # 0 = mtime ; 1 = ctime
+
# Remove srcdir prefix
$file =~ s/^\Q$config{srcdir}\E\/?//;
- my @raw_lines = run_or_die('git', 'log',
- '--follow', '--no-merges',
- '--pretty=raw', '--raw', '--abbrev=40', '--always', '-c',
- '-r', '--', $file);
- my @ci;
- while (my $parsed = parse_diff_tree("", \@raw_lines)) {
- push @ci, $parsed;
+ if (! keys %time_cache) {
+ my $date;
+ foreach my $line (run_or_die('git', 'log',
+ '--pretty=format:%ct',
+ '--name-only', '--relative')) {
+ if (! defined $date && $line =~ /^(\d+)$/) {
+ $date=$line;
+ }
+ elsif (! length $line) {
+ $date=undef;
+ }
+ else {
+ if (! $time_cache{$line}) {
+ $time_cache{$line}[0]=$date; # mtime
+ }
+ $time_cache{$line}[1]=$date; # ctime
+ }
+ }
}
- my $ctime = $ci[$#ci]->{'author_epoch'};
- debug("ctime for '$file': ". localtime($ctime));
- return $ctime;
+ return exists $time_cache{$file} ? $time_cache{$file}[$id] : 0;
+}
+
+}
+
+sub rcs_getctime ($) {
+ my $file=shift;
+
+ return findtimes($file, 1);
+}
+
+sub rcs_getmtime ($) {
+ my $file=shift;
+
+ return findtimes($file, 0);
}
sub rcs_receive () {
diff --git a/IkiWiki/Plugin/google.pm b/IkiWiki/Plugin/google.pm
index 483fa1707..48ad4c8ce 100644
--- a/IkiWiki/Plugin/google.pm
+++ b/IkiWiki/Plugin/google.pm
@@ -17,6 +17,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1,
+ section => "web",
},
}
diff --git a/IkiWiki/Plugin/goto.pm b/IkiWiki/Plugin/goto.pm
index 439552f62..03bd682b3 100644
--- a/IkiWiki/Plugin/goto.pm
+++ b/IkiWiki/Plugin/goto.pm
@@ -14,6 +14,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "web",
}
}
diff --git a/IkiWiki/Plugin/graphviz.pm b/IkiWiki/Plugin/graphviz.pm
index 32e994d6b..bec122076 100644
--- a/IkiWiki/Plugin/graphviz.pm
+++ b/IkiWiki/Plugin/graphviz.pm
@@ -18,6 +18,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/haiku.pm b/IkiWiki/Plugin/haiku.pm
index 5a062a276..bf23dce67 100644
--- a/IkiWiki/Plugin/haiku.pm
+++ b/IkiWiki/Plugin/haiku.pm
@@ -16,6 +16,7 @@ sub getsetup {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/highlight.pm b/IkiWiki/Plugin/highlight.pm
index 9bdde85ae..e517ac5c0 100644
--- a/IkiWiki/Plugin/highlight.pm
+++ b/IkiWiki/Plugin/highlight.pm
@@ -23,6 +23,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1, # format plugin
+ section => "format",
},
tohighlight => {
type => "string",
@@ -79,7 +80,7 @@ my %highlighters;
# Parse highlight's config file to get extension => language mappings.
sub read_filetypes () {
- open (IN, $filetypes);
+ open (IN, $filetypes) || error("$filetypes: $!");
while (<IN>) {
chomp;
if (/^\$ext\((.*)\)=(.*)$/) {
diff --git a/IkiWiki/Plugin/hnb.pm b/IkiWiki/Plugin/hnb.pm
index bd2177a06..32c9cf3ad 100644
--- a/IkiWiki/Plugin/hnb.pm
+++ b/IkiWiki/Plugin/hnb.pm
@@ -23,6 +23,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1, # format plugin
+ section => "format",
},
}
diff --git a/IkiWiki/Plugin/html.pm b/IkiWiki/Plugin/html.pm
index a7d5e8ce9..4dbae081b 100644
--- a/IkiWiki/Plugin/html.pm
+++ b/IkiWiki/Plugin/html.pm
@@ -21,6 +21,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1, # format plugin
+ section => "format",
},
}
diff --git a/IkiWiki/Plugin/htmlscrubber.pm b/IkiWiki/Plugin/htmlscrubber.pm
index a249cdf7a..9f40c752f 100644
--- a/IkiWiki/Plugin/htmlscrubber.pm
+++ b/IkiWiki/Plugin/htmlscrubber.pm
@@ -30,9 +30,9 @@ sub import {
"msnim", "notes", "rsync", "secondlife", "skype", "ssh",
"sftp", "smb", "sms", "snews", "webcal", "ymsgr",
);
- # data is a special case. Allow data:image/*, but
- # disallow data:text/javascript and everything else.
- $safe_url_regexp=qr/^(?:(?:$uri_schemes):|data:image\/|[^:]+(?:$|\/))/i;
+ # data is a special case. Allow a few data:image/ types,
+ # but disallow data:text/javascript and everything else.
+ $safe_url_regexp=qr/^(?:(?:$uri_schemes):|data:image\/(?:png|jpeg|gif)|[^:]+(?:$|[\/\?]))/i;
}
sub getsetup () {
@@ -40,6 +40,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "core",
},
htmlscrubber_skip => {
type => "pagespec",
diff --git a/IkiWiki/Plugin/httpauth.pm b/IkiWiki/Plugin/httpauth.pm
index 127c321f0..478f67446 100644
--- a/IkiWiki/Plugin/httpauth.pm
+++ b/IkiWiki/Plugin/httpauth.pm
@@ -9,6 +9,10 @@ use IkiWiki 3.00;
sub import {
hook(type => "getsetup", id => "httpauth", call => \&getsetup);
hook(type => "auth", id => "httpauth", call => \&auth);
+ hook(type => "formbuilder_setup", id => "httpauth",
+ call => \&formbuilder_setup);
+ hook(type => "canedit", id => "httpauth", call => \&canedit,
+ first => 1);
}
sub getsetup () {
@@ -16,6 +20,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
cgiauthurl => {
type => "string",
@@ -24,6 +29,23 @@ sub getsetup () {
safe => 1,
rebuild => 0,
},
+ httpauth_pagespec => {
+ type => "pagespec",
+ example => "!*/Discussion",
+ description => "PageSpec of pages where only httpauth will be used for authentication",
+ safe => 0,
+ rebuild => 0,
+ },
+}
+
+sub redir_cgiauthurl ($;@) {
+ my $cgi=shift;
+
+ IkiWiki::redirect($cgi,
+ @_ > 1 ? IkiWiki::cgiurl(cgiurl => $config{cgiauthurl}, @_)
+ : $config{cgiauthurl}."?@_"
+ );
+ exit;
}
sub auth ($$) {
@@ -33,9 +55,53 @@ sub auth ($$) {
if (defined $cgi->remote_user()) {
$session->param("name", $cgi->remote_user());
}
- elsif (defined $config{cgiauthurl}) {
- IkiWiki::redirect($cgi, $config{cgiauthurl}.'?'.$cgi->query_string());
- exit;
+}
+
+sub formbuilder_setup (@) {
+ my %params=@_;
+
+ my $form=$params{form};
+ my $session=$params{session};
+ my $cgi=$params{cgi};
+ my $buttons=$params{buttons};
+
+ if ($form->title eq "signin" &&
+ ! defined $cgi->remote_user() && defined $config{cgiauthurl}) {
+ my $button_text="Login with HTTP auth";
+ push @$buttons, $button_text;
+
+ if ($form->submitted && $form->submitted eq $button_text) {
+ # bounce thru cgiauthurl and then back to
+ # the stored postsignin action
+ redir_cgiauthurl($cgi, do => "postsignin");
+ }
+ }
+}
+
+sub test_httpauth_pagespec ($) {
+ my $page=shift;
+
+ return (
+ );
+}
+
+sub canedit ($$$) {
+ my $page=shift;
+ my $cgi=shift;
+ my $session=shift;
+
+ if (! defined $cgi->remote_user() &&
+ defined $config{httpauth_pagespec} &&
+ length $config{httpauth_pagespec} &&
+ defined $config{cgiauthurl} &&
+ pagespec_match($page, $config{httpauth_pagespec})) {
+ return sub {
+ # bounce thru cgiauthurl and back to edit action
+ redir_cgiauthurl($cgi, $cgi->query_string());
+ };
+ }
+ else {
+ return undef;
}
}
diff --git a/IkiWiki/Plugin/img.pm b/IkiWiki/Plugin/img.pm
index 82db15a7e..f06121578 100644
--- a/IkiWiki/Plugin/img.pm
+++ b/IkiWiki/Plugin/img.pm
@@ -19,6 +19,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm
index 401852513..3359af314 100644
--- a/IkiWiki/Plugin/inline.pm
+++ b/IkiWiki/Plugin/inline.pm
@@ -49,6 +49,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "core",
},
rss => {
type => "boolean",
@@ -159,7 +160,7 @@ sub preprocess_inline (@) {
my $rss=(($config{rss} || $config{allowrss}) && exists $params{rss}) ? yesno($params{rss}) : $config{rss};
my $atom=(($config{atom} || $config{allowatom}) && exists $params{atom}) ? yesno($params{atom}) : $config{atom};
my $quick=exists $params{quick} ? yesno($params{quick}) : 0;
- my $feeds=! $nested && (exists $params{feeds} ? yesno($params{feeds}) : !$quick);
+ my $feeds=! $nested && (exists $params{feeds} ? yesno($params{feeds}) : !$quick && ! $raw);
my $emptyfeeds=exists $params{emptyfeeds} ? yesno($params{emptyfeeds}) : 1;
my $feedonly=yesno($params{feedonly});
if (! exists $params{show} && ! $archive) {
@@ -552,7 +553,8 @@ sub genfeed ($$$$$@) {
if (exists $pagestate{$p}) {
if (exists $pagestate{$p}{meta}{guid}) {
- $itemtemplate->param(guid => $pagestate{$p}{meta}{guid});
+ eval q{use HTML::Entities};
+ $itemtemplate->param(guid => HTML::Entities::encode_numeric($pagestate{$p}{meta}{guid}));
}
if (exists $pagestate{$p}{meta}{updated}) {
diff --git a/IkiWiki/Plugin/link.pm b/IkiWiki/Plugin/link.pm
index 4c1add985..3838aec09 100644
--- a/IkiWiki/Plugin/link.pm
+++ b/IkiWiki/Plugin/link.pm
@@ -20,6 +20,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1,
+ section => "core",
},
}
diff --git a/IkiWiki/Plugin/linkmap.pm b/IkiWiki/Plugin/linkmap.pm
index 68eb6c8c6..ac26e072e 100644
--- a/IkiWiki/Plugin/linkmap.pm
+++ b/IkiWiki/Plugin/linkmap.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/listdirectives.pm b/IkiWiki/Plugin/listdirectives.pm
index 09f08c567..8a67f7160 100644
--- a/IkiWiki/Plugin/listdirectives.pm
+++ b/IkiWiki/Plugin/listdirectives.pm
@@ -19,6 +19,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
directive_description_dir => {
type => "string",
diff --git a/IkiWiki/Plugin/lockedit.pm b/IkiWiki/Plugin/lockedit.pm
index 74ddbb153..1466e8337 100644
--- a/IkiWiki/Plugin/lockedit.pm
+++ b/IkiWiki/Plugin/lockedit.pm
@@ -15,6 +15,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
locked_pages => {
type => "pagespec",
diff --git a/IkiWiki/Plugin/map.pm b/IkiWiki/Plugin/map.pm
index 788b96827..ce3ac1d24 100644
--- a/IkiWiki/Plugin/map.pm
+++ b/IkiWiki/Plugin/map.pm
@@ -21,6 +21,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/mdwn.pm b/IkiWiki/Plugin/mdwn.pm
index 3de59ef3d..b892eabee 100644
--- a/IkiWiki/Plugin/mdwn.pm
+++ b/IkiWiki/Plugin/mdwn.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1, # format plugin
+ section => "format",
},
multimarkdown => {
type => "boolean",
diff --git a/IkiWiki/Plugin/mercurial.pm b/IkiWiki/Plugin/mercurial.pm
index 11fdec529..34e009c7a 100644
--- a/IkiWiki/Plugin/mercurial.pm
+++ b/IkiWiki/Plugin/mercurial.pm
@@ -20,6 +20,7 @@ sub import {
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+ hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
}
sub checkconfig () {
@@ -36,6 +37,7 @@ sub getsetup () {
plugin => {
safe => 0, # rcs plugin
rebuild => undef,
+ section => "rcs",
},
mercurial_wrapper => {
type => "string",
@@ -253,4 +255,8 @@ sub rcs_getctime ($) {
return $ctime;
}
+sub rcs_getmtime ($) {
+ error "rcs_getmtime is not implemented for mercurial\n"; # TODO
+}
+
1
diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm
index 55c9ddbd1..128a6342c 100644
--- a/IkiWiki/Plugin/meta.pm
+++ b/IkiWiki/Plugin/meta.pm
@@ -20,6 +20,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "core",
},
}
@@ -87,15 +88,21 @@ sub preprocess (@) {
# Metadata collection that needs to happen during the scan pass.
if ($key eq 'title') {
- $pagestate{$page}{meta}{title}=HTML::Entities::encode_numeric($value);
+ $pagestate{$page}{meta}{title}=$value;
+ if (exists $params{sortas}) {
+ $pagestate{$page}{meta}{titlesort}=$params{sortas};
+ }
+ else {
+ delete $pagestate{$page}{meta}{titlesort};
+ }
return "";
}
elsif ($key eq 'description') {
- $pagestate{$page}{meta}{description}=HTML::Entities::encode_numeric($value);
+ $pagestate{$page}{meta}{description}=$value;
# fallthrough
}
elsif ($key eq 'guid') {
- $pagestate{$page}{meta}{guid}=HTML::Entities::encode_numeric($value);
+ $pagestate{$page}{meta}{guid}=$value;
# fallthrough
}
elsif ($key eq 'license') {
@@ -115,6 +122,12 @@ sub preprocess (@) {
}
elsif ($key eq 'author') {
$pagestate{$page}{meta}{author}=$value;
+ if (exists $params{sortas}) {
+ $pagestate{$page}{meta}{authorsort}=$params{sortas};
+ }
+ else {
+ delete $pagestate{$page}{meta}{authorsort};
+ }
# fallthorough
}
elsif ($key eq 'authorurl') {
@@ -263,15 +276,20 @@ sub pagetemplate (@) {
$template->param(meta => join("\n", grep { (! $seen{$_}) && ($seen{$_}=1) } @{$metaheaders{$page}}));
}
if (exists $pagestate{$page}{meta}{title} && $template->query(name => "title")) {
- $template->param(title => $pagestate{$page}{meta}{title});
+ $template->param(title => HTML::Entities::encode_numeric($pagestate{$page}{meta}{title}));
$template->param(title_overridden => 1);
}
- foreach my $field (qw{author authorurl description permalink}) {
+ foreach my $field (qw{author authorurl permalink}) {
$template->param($field => $pagestate{$page}{meta}{$field})
if exists $pagestate{$page}{meta}{$field} && $template->query(name => $field);
}
+ foreach my $field (qw{description}) {
+ $template->param($field => HTML::Entities::encode_numeric($pagestate{$page}{meta}{$field}))
+ if exists $pagestate{$page}{meta}{$field} && $template->query(name => $field);
+ }
+
foreach my $field (qw{license copyright}) {
if (exists $pagestate{$page}{meta}{$field} && $template->query(name => $field) &&
($page eq $destpage || ! exists $pagestate{$destpage}{meta}{$field} ||
@@ -281,6 +299,33 @@ sub pagetemplate (@) {
}
}
+sub get_sort_key {
+ my $page = shift;
+ my $meta = shift;
+
+ # e.g. titlesort (also makes sense for author)
+ my $key = $pagestate{$page}{meta}{$meta . "sort"};
+ return $key if defined $key;
+
+ # e.g. title
+ $key = $pagestate{$page}{meta}{$meta};
+ return $key if defined $key;
+
+ # fall back to closer-to-core things
+ if ($meta eq 'title') {
+ return pagetitle(IkiWiki::basename($page));
+ }
+ elsif ($meta eq 'date') {
+ return $IkiWiki::pagectime{$page};
+ }
+ elsif ($meta eq 'updated') {
+ return $IkiWiki::pagemtime{$page};
+ }
+ else {
+ return '';
+ }
+}
+
sub match {
my $field=shift;
my $page=shift;
@@ -331,4 +376,27 @@ sub match_copyright ($$;@) {
IkiWiki::Plugin::meta::match("copyright", @_);
}
+package IkiWiki::SortSpec;
+
+sub cmp_meta {
+ my $meta = shift;
+ error(gettext("sort=meta requires a parameter")) unless defined $meta;
+
+ if ($meta eq 'updated' || $meta eq 'date') {
+ return IkiWiki::Plugin::meta::get_sort_key($a, $meta)
+ <=>
+ IkiWiki::Plugin::meta::get_sort_key($b, $meta);
+ }
+
+ return IkiWiki::Plugin::meta::get_sort_key($a, $meta)
+ cmp
+ IkiWiki::Plugin::meta::get_sort_key($b, $meta);
+}
+
+# A prototype of how sort=title could behave in 4.0 or something
+sub cmp_meta_title {
+ $_[0] = 'title';
+ return cmp_meta(@_);
+}
+
1
diff --git a/IkiWiki/Plugin/mirrorlist.pm b/IkiWiki/Plugin/mirrorlist.pm
index d0a6107ef..92be7913e 100644
--- a/IkiWiki/Plugin/mirrorlist.pm
+++ b/IkiWiki/Plugin/mirrorlist.pm
@@ -15,6 +15,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1,
+ section => "web",
},
mirrorlist => {
type => "string",
diff --git a/IkiWiki/Plugin/moderatedcomments.pm b/IkiWiki/Plugin/moderatedcomments.pm
index 2555927b7..b0a328a06 100644
--- a/IkiWiki/Plugin/moderatedcomments.pm
+++ b/IkiWiki/Plugin/moderatedcomments.pm
@@ -15,11 +15,13 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
- moderate_users => {
- type => 'boolean',
- example => 1,
- description => 'Moderate comments of logged-in users?',
+ moderate_pagespec => {
+ type => 'pagespec',
+ example => 'user(http://*)',
+ description => 'PageSpec matching users or comment locations to moderate',
+ link => 'ikiwiki/PageSpec',
safe => 1,
rebuild => 0,
},
@@ -31,14 +33,32 @@ sub checkcontent (@) {
# only handle comments
return undef unless pagespec_match($params{page}, "postcomment(*)",
location => $params{page});
+
+ # backwards compatability
+ if (exists $config{moderate_users} &&
+ ! exists $config{moderate_pagespec}) {
+ $config{moderate_pagespec} = $config{moderate_users}
+ ? "!admin()"
+ : "!user(*)";
+ }
+
+ # default is to moderate all except admins
+ if (! exists $config{moderate_pagespec}) {
+ $config{moderate_pagespec}="!admin()";
+ }
- # admins and maybe users can comment w/o moderation
my $session=$params{session};
my $user=$session->param("name") if $session;
- return undef if defined $user && (IkiWiki::is_admin($user) ||
- (exists $config{moderate_users} && ! $config{moderate_users}));
-
- return gettext("comment needs moderation");
+ if (pagespec_match($params{page}, $config{moderate_pagespec},
+ location => $params{page},
+ (defined $user ? (user => $user) : ()),
+ (defined $ENV{REMOTE_ADDR} ? (ip => $ENV{REMOTE_ADDR}) : ()),
+ )) {
+ return gettext("comment needs moderation");
+ }
+ else {
+ return undef;
+ }
}
1
diff --git a/IkiWiki/Plugin/monotone.pm b/IkiWiki/Plugin/monotone.pm
index 9502804f1..67d4abbaa 100644
--- a/IkiWiki/Plugin/monotone.pm
+++ b/IkiWiki/Plugin/monotone.pm
@@ -23,6 +23,7 @@ sub import {
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+ hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
}
sub checkconfig () {
@@ -68,6 +69,7 @@ sub getsetup () {
plugin => {
safe => 0, # rcs plugin
rebuild => undef,
+ section => "rcs",
},
mtn_wrapper => {
type => "string",
@@ -692,4 +694,8 @@ sub rcs_getctime ($) {
return $date;
}
+sub rcs_getmtime ($) {
+ error "rcs_getmtime is not implemented for monotone\n"; # TODO
+}
+
1
diff --git a/IkiWiki/Plugin/more.pm b/IkiWiki/Plugin/more.pm
index 77d5fb077..266c8e1d0 100644
--- a/IkiWiki/Plugin/more.pm
+++ b/IkiWiki/Plugin/more.pm
@@ -17,6 +17,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/norcs.pm b/IkiWiki/Plugin/norcs.pm
index bfe84c0e1..053652a5f 100644
--- a/IkiWiki/Plugin/norcs.pm
+++ b/IkiWiki/Plugin/norcs.pm
@@ -18,6 +18,7 @@ sub import {
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+ hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
}
sub getsetup () {
@@ -25,6 +26,7 @@ sub getsetup () {
plugin => {
safe => 0, # rcs plugin
rebuild => 0,
+ section => "rcs",
},
}
@@ -62,7 +64,11 @@ sub rcs_diff ($) {
}
sub rcs_getctime ($) {
- error gettext("getctime not implemented");
+ return 0;
+}
+
+sub rcs_getmtime ($) {
+ return 0;
}
1
diff --git a/IkiWiki/Plugin/opendiscussion.pm b/IkiWiki/Plugin/opendiscussion.pm
index 4517ff88b..2805f60ef 100644
--- a/IkiWiki/Plugin/opendiscussion.pm
+++ b/IkiWiki/Plugin/opendiscussion.pm
@@ -7,7 +7,8 @@ use IkiWiki 3.00;
sub import {
hook(type => "getsetup", id => "opendiscussion", call => \&getsetup);
- hook(type => "canedit", id => "opendiscussion", call => \&canedit);
+ hook(type => "canedit", id => "opendiscussion", call => \&canedit,
+ first => 1);
}
sub getsetup () {
@@ -15,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
}
@@ -24,6 +26,7 @@ sub canedit ($$) {
my $session=shift;
return "" if $page=~/(\/|^)\Q$config{discussionpage}\E$/i;
+ return "" if pagespec_match($page, "postcomment(*)");
return undef;
}
diff --git a/IkiWiki/Plugin/openid.pm b/IkiWiki/Plugin/openid.pm
index dc0e0f48e..7b1a17831 100644
--- a/IkiWiki/Plugin/openid.pm
+++ b/IkiWiki/Plugin/openid.pm
@@ -26,6 +26,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
openidsignup => {
type => "string",
@@ -56,7 +57,7 @@ sub formbuilder_setup (@) {
# OpenID fieldset.
$form->fieldsets("OpenID");
- $form->field(
+ $form->field(
name => "openid_url",
label => gettext("Log in with")." ".htmllink("", "", "ikiwiki/OpenID", noimageinline => 1),
fieldset => "OpenID",
@@ -82,13 +83,14 @@ sub formbuilder_setup (@) {
}
}
}
- elsif ($form->title eq "preferences") {
- if (! defined $form->field(name => "name")) {
- $form->field(name => "OpenID", disabled => 1,
- value => $session->param("name"),
- size => 50, force => 1,
- fieldset => "login");
- }
+ elsif ($form->title eq "preferences" &&
+ IkiWiki::openiduser($session->param("name"))) {
+ $form->field(name => "openid_url", disabled => 1,
+ label => htmllink("", "", "ikiwiki/OpenID", noimageinline => 1),
+ value => $session->param("name"),
+ size => 50, force => 1,
+ fieldset => "login");
+ $form->field(name => "email", type => "hidden");
}
}
@@ -112,6 +114,28 @@ sub validate ($$$;$) {
}
}
+ # Ask for client to provide a name and email, if possible.
+ # Try sreg and ax
+ if ($claimed_identity->can("set_extension_args")) {
+ $claimed_identity->set_extension_args(
+ 'http://openid.net/extensions/sreg/1.1',
+ {
+ optional => 'email,fullname,nickname',
+ },
+ );
+ $claimed_identity->set_extension_args(
+ 'http://openid.net/srv/ax/1.0',
+ {
+ mode => 'fetch_request',
+ 'required' => 'email,fullname,nickname,firstname',
+ 'type.email' => "http://schema.openid.net/contact/email",
+ 'type.fullname' => "http://axschema.org/namePerson",
+ 'type.nickname' => "http://axschema.org/namePerson/friendly",
+ 'type.firstname' => "http://axschema.org/namePerson/first",
+ },
+ );
+ }
+
my $check_url = $claimed_identity->check_url(
return_to => IkiWiki::cgiurl(do => "postsignin"),
trust_root => $config{cgiurl},
@@ -138,6 +162,32 @@ sub auth ($$) {
}
elsif (my $vident = $csr->verified_identity) {
$session->param(name => $vident->url);
+
+ my @extensions;
+ if ($vident->can("signed_extension_fields")) {
+ @extensions=grep { defined } (
+ $vident->signed_extension_fields('http://openid.net/extensions/sreg/1.1'),
+ $vident->signed_extension_fields('http://openid.net/srv/ax/1.0'),
+ );
+ }
+ foreach my $ext (@extensions) {
+ foreach my $field (qw{value.email email}) {
+ if (exists $ext->{$field} &&
+ defined $ext->{$field} &&
+ length $ext->{$field}) {
+ $session->param(email => $ext->{$field});
+ last;
+ }
+ }
+ foreach my $field (qw{value.nickname nickname value.fullname fullname value.firstname}) {
+ if (exists $ext->{$field} &&
+ defined $ext->{$field} &&
+ length $ext->{$field}) {
+ $session->param(username => $ext->{$field});
+ last;
+ }
+ }
+ }
}
else {
error("OpenID failure: ".$csr->err);
diff --git a/IkiWiki/Plugin/orphans.pm b/IkiWiki/Plugin/orphans.pm
index 702943f87..e3cc3c940 100644
--- a/IkiWiki/Plugin/orphans.pm
+++ b/IkiWiki/Plugin/orphans.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/otl.pm b/IkiWiki/Plugin/otl.pm
index 3ab2441bf..3801a6ec2 100644
--- a/IkiWiki/Plugin/otl.pm
+++ b/IkiWiki/Plugin/otl.pm
@@ -17,6 +17,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1, # format plugin
+ section => "format",
},
}
diff --git a/IkiWiki/Plugin/pagecount.pm b/IkiWiki/Plugin/pagecount.pm
index 8d36f057e..dd5de3c83 100644
--- a/IkiWiki/Plugin/pagecount.pm
+++ b/IkiWiki/Plugin/pagecount.pm
@@ -15,6 +15,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/pagestats.pm b/IkiWiki/Plugin/pagestats.pm
index 4313aa271..17b26f7ba 100644
--- a/IkiWiki/Plugin/pagestats.pm
+++ b/IkiWiki/Plugin/pagestats.pm
@@ -27,6 +27,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
@@ -74,7 +75,7 @@ sub preprocess (@) {
}
if ($style eq 'table') {
- return "<table class='pageStats'>\n".
+ return "<table class='".(exists $params{class} ? $params{class} : "pageStats")."'>\n".
join("\n", map {
"<tr><td>".
htmllink($params{page}, $params{destpage}, $_, noimageinline => 1).
@@ -86,16 +87,31 @@ sub preprocess (@) {
else {
# In case of misspelling, default to a page cloud
- my $res = "<div class='pagecloud'>\n";
+ my $res;
+ if ($style eq 'list') {
+ $res = "<ul class='".(exists $params{class} ? $params{class} : "list")."'>\n";
+ }
+ else {
+ $res = "<div class='".(exists $params{class} ? $params{class} : "pagecloud")."'>\n";
+ }
foreach my $page (sort keys %counts) {
next unless $counts{$page} > 0;
my $class = $classes[$counts{$page} * scalar(@classes) / ($max + 1)];
+
+ $res.="<li>" if $style eq 'list';
$res .= "<span class=\"$class\">".
htmllink($params{page}, $params{destpage}, $page).
"</span>\n";
+ $res.="</li>" if $style eq 'list';
+
+ }
+ if ($style eq 'list') {
+ $res .= "</ul>\n";
+ }
+ else {
+ $res .= "</div>\n";
}
- $res .= "</div>\n";
return $res;
}
diff --git a/IkiWiki/Plugin/parentlinks.pm b/IkiWiki/Plugin/parentlinks.pm
index e678a057d..728bbc399 100644
--- a/IkiWiki/Plugin/parentlinks.pm
+++ b/IkiWiki/Plugin/parentlinks.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1,
+ section => "core",
},
}
diff --git a/IkiWiki/Plugin/passwordauth.pm b/IkiWiki/Plugin/passwordauth.pm
index 8cf5af51e..4848b47bb 100644
--- a/IkiWiki/Plugin/passwordauth.pm
+++ b/IkiWiki/Plugin/passwordauth.pm
@@ -19,6 +19,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
account_creation_password => {
type => "string",
@@ -104,11 +105,11 @@ sub formbuilder_setup (@) {
my $session=$params{session};
my $cgi=$params{cgi};
- if ($form->title eq "signin" || $form->title eq "register") {
+ if ($form->title eq "signin" || $form->title eq "register" || $cgi->param("do") eq "register") {
$form->field(name => "name", required => 0);
$form->field(name => "password", type => "password", required => 0);
- if ($form->submitted eq "Register" || $form->submitted eq "Create Account") {
+ if ($form->submitted eq "Register" || $form->submitted eq "Create Account" || $cgi->param("do") eq "register") {
$form->field(name => "confirm_password", type => "password");
$form->field(name => "account_creation_password", type => "password")
if (defined $config{account_creation_password} &&
@@ -207,19 +208,34 @@ sub formbuilder_setup (@) {
}
}
elsif ($form->title eq "preferences") {
- $form->field(name => "name", disabled => 1,
- value => $session->param("name"), force => 1,
- fieldset => "login");
- $form->field(name => "password", type => "password",
- fieldset => "login",
- validate => sub {
- shift eq $form->field("confirm_password");
- }),
- $form->field(name => "confirm_password", type => "password",
- fieldset => "login",
- validate => sub {
- shift eq $form->field("password");
- }),
+ my $user=$session->param("name");
+ if (! IkiWiki::openiduser($user)) {
+ $form->field(name => "name", disabled => 1,
+ value => $user, force => 1,
+ fieldset => "login");
+ $form->field(name => "password", type => "password",
+ fieldset => "login",
+ validate => sub {
+ shift eq $form->field("confirm_password");
+ });
+ $form->field(name => "confirm_password", type => "password",
+ fieldset => "login",
+ validate => sub {
+ shift eq $form->field("password");
+ });
+
+ my $userpage=IkiWiki::userpage($user);
+ if (exists $pagesources{$userpage}) {
+ $form->text(gettext("Your user page: ").
+ htmllink("", "", $userpage,
+ noimageinline => 1));
+ }
+ else {
+ $form->text("<a href=\"".
+ IkiWiki::cgiurl(do => "edit", page => $userpage).
+ "\">".gettext("Create your user page")."</a>");
+ }
+ }
}
}
@@ -232,7 +248,7 @@ sub formbuilder (@) {
my $buttons=$params{buttons};
if ($form->title eq "signin" || $form->title eq "register") {
- if ($form->submitted && $form->validate) {
+ if (($form->submitted && $form->validate) || $cgi->param("do") eq "register") {
if ($form->submitted eq 'Login') {
$session->param("name", $form->field("name"));
IkiWiki::cgi_postsignin($cgi, $session);
@@ -295,7 +311,7 @@ sub formbuilder (@) {
$form->field(name => "name", required => 0);
push @$buttons, "Reset Password";
}
- elsif ($form->submitted eq "Register") {
+ elsif ($form->submitted eq "Register" || $cgi->param("do") eq "register") {
@$buttons="Create Account";
}
}
@@ -336,6 +352,14 @@ sub sessioncgi ($$) {
IkiWiki::cgi_prefs($q, $session);
exit;
}
+ elsif ($q->param("do") eq "register") {
+ # After registration, need to go somewhere, so show prefs page.
+ $session->param(postsignin => "do=prefs");
+ # Due to do=register, this will run in registration-only
+ # mode.
+ IkiWiki::cgi_signin($q, $session);
+ exit;
+ }
}
sub auth ($$) {
diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm
index f8801185e..759e812e6 100644
--- a/IkiWiki/Plugin/po.pm
+++ b/IkiWiki/Plugin/po.pm
@@ -85,7 +85,8 @@ sub getsetup () {
return
plugin => {
safe => 0,
- rebuild => 1,
+ rebuild => 1, # format plugin
+ section => "format",
},
po_master_language => {
type => "string",
@@ -132,6 +133,7 @@ sub checkconfig () {
$field, 'po'));
}
}
+ delete $config{po_slave_languages}{$config{po_master_language}{code}};;
map {
islanguagecode($_)
@@ -173,7 +175,8 @@ sub checkconfig () {
if ($config{po_master_language}{code} ne 'en') {
# Add underlay containing translated source files
# for the master language.
- add_underlay("locale/$config{po_master_language}{code}/$underlay");
+ add_underlay("locale/$config{po_master_language}{code}/$underlay")
+ if -d "$config{underlaydirbase}/locale/$config{po_master_language}{code}/$underlay";
}
}
}
@@ -307,7 +310,7 @@ sub pagetemplate (@) {
if (ishomepage($page) && $template->query(name => "title")) {
$template->param(title => $config{wikiname});
}
-} # }}}
+}
# Add the renamed page translations to the list of to-be-renamed pages.
sub renamepages (@) {
diff --git a/IkiWiki/Plugin/poll.pm b/IkiWiki/Plugin/poll.pm
index bc1e3501e..6bc4579c2 100644
--- a/IkiWiki/Plugin/poll.pm
+++ b/IkiWiki/Plugin/poll.pm
@@ -17,6 +17,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/polygen.pm b/IkiWiki/Plugin/polygen.pm
index bc21d71c7..78e3611e1 100644
--- a/IkiWiki/Plugin/polygen.pm
+++ b/IkiWiki/Plugin/polygen.pm
@@ -20,6 +20,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/postsparkline.pm b/IkiWiki/Plugin/postsparkline.pm
index 0d5a12e33..2fae9c5fe 100644
--- a/IkiWiki/Plugin/postsparkline.pm
+++ b/IkiWiki/Plugin/postsparkline.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/progress.pm b/IkiWiki/Plugin/progress.pm
index fe64b40b1..d27df5ca8 100644
--- a/IkiWiki/Plugin/progress.pm
+++ b/IkiWiki/Plugin/progress.pm
@@ -18,6 +18,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/rawhtml.pm b/IkiWiki/Plugin/rawhtml.pm
index ad8a610c1..0838bcb22 100644
--- a/IkiWiki/Plugin/rawhtml.pm
+++ b/IkiWiki/Plugin/rawhtml.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1, # changes file types
+ section => "format",
},
}
diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm
index fa851e466..5c7b71aaa 100644
--- a/IkiWiki/Plugin/recentchanges.pm
+++ b/IkiWiki/Plugin/recentchanges.pm
@@ -124,7 +124,7 @@ sub store ($$$) {
elsif (length $config{cgiurl}) {
$change->{authorurl} = IkiWiki::cgiurl(
do => "goto",
- page => (length $config{userdir} ? "$config{userdir}/" : "").$change->{author},
+ page => IkiWiki::userpage($change->{author}),
);
}
diff --git a/IkiWiki/Plugin/relativedate.pm b/IkiWiki/Plugin/relativedate.pm
index 06df2efd5..7f006af83 100644
--- a/IkiWiki/Plugin/relativedate.pm
+++ b/IkiWiki/Plugin/relativedate.pm
@@ -5,7 +5,7 @@ use warnings;
no warnings 'redefine';
use strict;
use IkiWiki 3.00;
-use POSIX;
+use POSIX ();
use Encode;
sub import {
diff --git a/IkiWiki/Plugin/remove.pm b/IkiWiki/Plugin/remove.pm
index 3c1e0c713..0fc180f69 100644
--- a/IkiWiki/Plugin/remove.pm
+++ b/IkiWiki/Plugin/remove.pm
@@ -18,6 +18,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "web",
},
}
@@ -48,7 +49,7 @@ sub check_canremove ($$$) {
# This is sorta overkill, but better safe than sorry.
if (! defined pagetype($pagesources{$page})) {
if (IkiWiki::Plugin::attachment->can("check_canattach")) {
- IkiWiki::Plugin::attachment::check_canattach($session, $page, $file);
+ IkiWiki::Plugin::attachment::check_canattach($session, $page, "$config{srcdir}/$file");
}
else {
error("removal of attachments is not allowed");
diff --git a/IkiWiki/Plugin/rename.pm b/IkiWiki/Plugin/rename.pm
index 8213d21f6..1a9da6363 100644
--- a/IkiWiki/Plugin/rename.pm
+++ b/IkiWiki/Plugin/rename.pm
@@ -18,6 +18,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "web",
},
}
@@ -49,7 +50,7 @@ sub check_canrename ($$$$$$) {
IkiWiki::check_canedit($src, $q, $session);
if ($attachment) {
if (IkiWiki::Plugin::attachment->can("check_canattach")) {
- IkiWiki::Plugin::attachment::check_canattach($session, $src, $srcfile);
+ IkiWiki::Plugin::attachment::check_canattach($session, $src, "$config{srcdir}/$srcfile");
}
else {
error("renaming of attachments is not allowed");
@@ -84,7 +85,7 @@ sub check_canrename ($$$$$$) {
if ($attachment) {
# Note that $srcfile is used here, not $destfile,
# because it wants the current file, to check it.
- IkiWiki::Plugin::attachment::check_canattach($session, $dest, $srcfile);
+ IkiWiki::Plugin::attachment::check_canattach($session, $dest, "$config{srcdir}/$srcfile");
}
}
diff --git a/IkiWiki/Plugin/repolist.pm b/IkiWiki/Plugin/repolist.pm
index f69ec3988..ba7c5f0aa 100644
--- a/IkiWiki/Plugin/repolist.pm
+++ b/IkiWiki/Plugin/repolist.pm
@@ -15,6 +15,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "web",
},
repositories => {
type => "string",
diff --git a/IkiWiki/Plugin/search.pm b/IkiWiki/Plugin/search.pm
index 393c17e0f..c0e8703d8 100644
--- a/IkiWiki/Plugin/search.pm
+++ b/IkiWiki/Plugin/search.pm
@@ -20,6 +20,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1,
+ section => "web",
},
omega_cgi => {
type => "string",
@@ -109,6 +110,7 @@ sub index (@) {
# data used by omega
# Decode html entities in it, since omega re-encodes them.
eval q{use HTML::Entities};
+ error $@ if $@;
$doc->set_data(
"url=".urlto($params{page}, "")."\n".
"sample=".decode_entities($sample)."\n".
@@ -213,9 +215,19 @@ sub setupfiles () {
writefile("omega.conf", $config{wikistatedir}."/xapian",
"database_dir .\n".
"template_dir ./templates\n");
+
+ # Avoid omega interpreting anything in the misctemplate
+ # as an omegascript command.
+ my $misctemplate=IkiWiki::misctemplate(gettext("search"), "\0");
+ eval q{use HTML::Entities};
+ error $@ if $@;
+ $misctemplate=encode_entities($misctemplate, '\$');
+
+ my $querytemplate=readfile(IkiWiki::template_file("searchquery.tmpl"));
+ $misctemplate=~s/\0/$querytemplate/;
+
writefile("query", $config{wikistatedir}."/xapian/templates",
- IkiWiki::misctemplate(gettext("search"),
- readfile(IkiWiki::template_file("searchquery.tmpl"))));
+ $misctemplate);
$setup=1;
}
}
diff --git a/IkiWiki/Plugin/shortcut.pm b/IkiWiki/Plugin/shortcut.pm
index 1840a5722..0cedbe447 100644
--- a/IkiWiki/Plugin/shortcut.pm
+++ b/IkiWiki/Plugin/shortcut.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/sidebar.pm b/IkiWiki/Plugin/sidebar.pm
index 41812e1c1..0350f2b71 100644
--- a/IkiWiki/Plugin/sidebar.pm
+++ b/IkiWiki/Plugin/sidebar.pm
@@ -10,6 +10,7 @@ use IkiWiki 3.00;
sub import {
hook(type => "getsetup", id => "sidebar", call => \&getsetup);
+ hook(type => "preprocess", id => "sidebar", call => \&preprocess);
hook(type => "pagetemplate", id => "sidebar", call => \&pagetemplate);
}
@@ -19,11 +20,51 @@ sub getsetup () {
safe => 1,
rebuild => 1,
},
+ global_sidebars => {
+ type => "boolean",
+ examples => 1,
+ description => "show sidebar page on all pages?",
+ safe => 1,
+ rebuild => 1,
+ },
+}
+
+my %pagesidebar;
+
+sub preprocess (@) {
+ my %params=@_;
+
+ my $page=$params{page};
+ return "" unless $page eq $params{destpage};
+
+ if (! defined $params{content}) {
+ $pagesidebar{$page}=undef;
+ }
+ else {
+ my $file = $pagesources{$page};
+ my $type = pagetype($file);
+
+ $pagesidebar{$page}=
+ IkiWiki::htmlize($page, $page, $type,
+ IkiWiki::linkify($page, $page,
+ IkiWiki::preprocess($page, $page,
+ IkiWiki::filter($page, $page, $params{content}))));
+ }
+
+ return "";
}
+my $oldfile;
+my $oldcontent;
+
sub sidebar_content ($) {
my $page=shift;
+ return delete $pagesidebar{$page} if defined $pagesidebar{$page};
+
+ return if ! exists $pagesidebar{$page} &&
+ defined $config{global_sidebars} && ! $config{global_sidebars};
+
my $sidebar_page=bestlink($page, "sidebar") || return;
my $sidebar_file=$pagesources{$sidebar_page} || return;
my $sidebar_type=pagetype($sidebar_file);
@@ -34,7 +75,16 @@ sub sidebar_content ($) {
# currently requires a wiki rebuild.
add_depends($page, $sidebar_page);
- my $content=readfile(srcfile($sidebar_file));
+ my $content;
+ if (defined $oldfile && $sidebar_file eq $oldfile) {
+ $content=$oldcontent;
+ }
+ else {
+ $content=readfile(srcfile($sidebar_file));
+ $oldcontent=$content;
+ $oldfile=$sidebar_file;
+ }
+
return unless length $content;
return IkiWiki::htmlize($sidebar_page, $page, $sidebar_type,
IkiWiki::linkify($sidebar_page, $page,
@@ -47,11 +97,10 @@ sub sidebar_content ($) {
sub pagetemplate (@) {
my %params=@_;
- my $page=$params{page};
my $template=$params{template};
-
- if ($template->query(name => "sidebar")) {
- my $content=sidebar_content($page);
+ if ($params{destpage} eq $params{page} &&
+ $template->query(name => "sidebar")) {
+ my $content=sidebar_content($params{destpage});
if (defined $content && length $content) {
$template->param(sidebar => $content);
}
diff --git a/IkiWiki/Plugin/signinedit.pm b/IkiWiki/Plugin/signinedit.pm
index 8b44a68f7..31160c02f 100644
--- a/IkiWiki/Plugin/signinedit.pm
+++ b/IkiWiki/Plugin/signinedit.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
}
diff --git a/IkiWiki/Plugin/sortnaturally.pm b/IkiWiki/Plugin/sortnaturally.pm
new file mode 100644
index 000000000..62e42767c
--- /dev/null
+++ b/IkiWiki/Plugin/sortnaturally.pm
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+# Sort::Naturally-powered title_natural sort order for IkiWiki
+package IkiWiki::Plugin::sortnaturally;
+
+use IkiWiki 3.00;
+no warnings;
+
+sub import {
+ hook(type => "getsetup", id => "sortnaturally", call => \&getsetup);
+}
+
+sub getsetup {
+ return
+ plugin => {
+ safe => 1,
+ rebuild => undef,
+ },
+}
+
+sub checkconfig () {
+ eval q{use Sort::Naturally};
+ error $@ if $@;
+}
+
+package IkiWiki::SortSpec;
+
+sub cmp_title_natural {
+ Sort::Naturally::ncmp(IkiWiki::pagetitle(IkiWiki::basename($a)),
+ IkiWiki::pagetitle(IkiWiki::basename($b)))
+}
+
+1;
diff --git a/IkiWiki/Plugin/sparkline.pm b/IkiWiki/Plugin/sparkline.pm
index fb4849492..42665ac63 100644
--- a/IkiWiki/Plugin/sparkline.pm
+++ b/IkiWiki/Plugin/sparkline.pm
@@ -24,6 +24,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/svn.pm b/IkiWiki/Plugin/svn.pm
index 06b987f51..d10b4888d 100644
--- a/IkiWiki/Plugin/svn.pm
+++ b/IkiWiki/Plugin/svn.pm
@@ -19,6 +19,7 @@ sub import {
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+ hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
}
sub checkconfig () {
@@ -44,6 +45,7 @@ sub getsetup () {
plugin => {
safe => 0, # rcs plugin
rebuild => undef,
+ section => "rcs",
},
svnrepo => {
type => "string",
@@ -348,9 +350,18 @@ sub rcs_diff ($) {
return `svnlook diff $config{svnrepo} -r$rev --no-diff-deleted`;
}
-sub rcs_getctime ($) {
+{
+
+my ($lastfile, $lastmtime, $lastctime);
+
+sub findtimes ($) {
my $file=shift;
+ if (defined $lastfile && $lastfile eq $file) {
+ return $lastmtime, $lastctime;
+ }
+ $lastfile=$file;
+
my $svn_log_infoline=qr/^r\d+\s+\|\s+[^\s]+\s+\|\s+(\d+-\d+-\d+\s+\d+:\d+:\d+\s+[-+]?\d+).*/;
my $child = open(SVNLOG, "-|");
@@ -358,24 +369,39 @@ sub rcs_getctime ($) {
exec("svn", "log", $file) || error("svn log $file failed to run");
}
- my $date;
+ my ($cdate, $mdate);
while (<SVNLOG>) {
if (/$svn_log_infoline/) {
- $date=$1;
+ $cdate=$1;
+ $mdate=$1 unless defined $mdate;
}
}
- close SVNLOG || warn "svn log $file exited $?";
+ close SVNLOG || error "svn log $file exited $?";
- if (! defined $date) {
- warn "failed to parse svn log for $file\n";
- return 0;
+ if (! defined $cdate) {
+ error "failed to parse svn log for $file\n";
}
eval q{use Date::Parse};
error($@) if $@;
- $date=str2time($date);
- debug("found ctime ".localtime($date)." for $file");
- return $date;
+
+ $lastctime=str2time($cdate);
+ $lastmtime=str2time($mdate);
+ return $lastmtime, $lastctime;
+}
+
+}
+
+sub rcs_getctime ($) {
+ my $file=shift;
+
+ return (findtimes($file))[1];
+}
+
+sub rcs_getmtime ($) {
+ my $file=shift;
+
+ return (findtimes($file))[0];
}
1
diff --git a/IkiWiki/Plugin/table.pm b/IkiWiki/Plugin/table.pm
index 96d63f455..2edd1eacd 100644
--- a/IkiWiki/Plugin/table.pm
+++ b/IkiWiki/Plugin/table.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm
index fdd63d637..9e6f417bf 100644
--- a/IkiWiki/Plugin/tag.pm
+++ b/IkiWiki/Plugin/tag.pm
@@ -6,8 +6,6 @@ use warnings;
use strict;
use IkiWiki 3.00;
-my %tags;
-
sub import {
hook(type => "getopt", id => "tag", call => \&getopt);
hook(type => "getsetup", id => "tag", call => \&getsetup);
@@ -94,13 +92,12 @@ sub preprocess_tag (@) {
foreach my $tag (keys %params) {
$tag=linkpage($tag);
- $tags{$page}{$tag}=1;
-
+
+ # hidden WikiLink
+ add_link($page, tagpage($tag), 'tag');
+
# add tagpage if necessary
gentag($tag);
-
- # hidden WikiLink
- add_link($page, tagpage($tag));
}
return "";
@@ -114,15 +111,13 @@ sub preprocess_taglink (@) {
return join(" ", map {
if (/(.*)\|(.*)/) {
my $tag=linkpage($2);
- $tags{$params{page}}{$tag}=1;
- add_link($params{page}, tagpage($tag));
+ add_link($params{page}, tagpage($tag), 'tag');
return taglink($params{page}, $params{destpage}, $tag,
linktext => pagetitle($1));
}
else {
my $tag=linkpage($_);
- $tags{$params{page}}{$tag}=1;
- add_link($params{page}, tagpage($tag));
+ add_link($params{page}, tagpage($tag), 'tag');
return taglink($params{page}, $params{destpage}, $tag);
}
}
@@ -137,17 +132,19 @@ sub pagetemplate (@) {
my $destpage=$params{destpage};
my $template=$params{template};
+ my $tags = $typedlinks{$page}{tag};
+
$template->param(tags => [
map {
link => taglink($page, $destpage, $_, rel => "tag")
- }, sort keys %{$tags{$page}}
- ]) if exists $tags{$page} && %{$tags{$page}} && $template->query(name => "tags");
+ }, sort keys %$tags
+ ]) if defined $tags && %$tags && $template->query(name => "tags");
if ($template->query(name => "categories")) {
# It's an rss/atom template. Add any categories.
- if (exists $tags{$page} && %{$tags{$page}}) {
+ if (defined $tags && %$tags) {
$template->param(categories => [map { category => $_ },
- sort keys %{$tags{$page}}]);
+ sort keys %$tags]);
}
}
}
@@ -155,9 +152,7 @@ sub pagetemplate (@) {
package IkiWiki::PageSpec;
sub match_tagged ($$;@) {
- my $page = shift;
- my $glob = shift;
- return match_link($page, IkiWiki::Plugin::tag::tagpage($glob));
+ return match_link($_[0], IkiWiki::Plugin::tag::tagpage($_[1]), linktype => 'tag');
}
1
diff --git a/IkiWiki/Plugin/template.pm b/IkiWiki/Plugin/template.pm
index 39d9667f9..98a13b5fa 100644
--- a/IkiWiki/Plugin/template.pm
+++ b/IkiWiki/Plugin/template.pm
@@ -19,6 +19,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
@@ -36,7 +37,13 @@ sub preprocess (@) {
my $template_page="templates/$params{id}";
add_depends($params{page}, $template_page);
- my $template_file=$pagesources{$template_page};
+ my $template_file;
+ if (exists $pagesources{$template_page}) {
+ $template_file=srcfile($pagesources{$template_page});
+ }
+ else {
+ $template_file=IkiWiki::template_file("$params{id}.tmpl")
+ }
return sprintf(gettext("template %s not found"),
htmllink($params{page}, $params{destpage}, "/".$template_page))
unless defined $template_file;
@@ -49,7 +56,7 @@ sub preprocess (@) {
$$text_ref=&Encode::decode_utf8($$text_ref);
chomp $$text_ref;
},
- filename => srcfile($template_file),
+ filename => $template_file,
die_on_bad_params => 0,
no_includes => 1,
blind_cache => 1,
diff --git a/IkiWiki/Plugin/teximg.pm b/IkiWiki/Plugin/teximg.pm
index f92ed0132..521af499f 100644
--- a/IkiWiki/Plugin/teximg.pm
+++ b/IkiWiki/Plugin/teximg.pm
@@ -8,6 +8,7 @@ use strict;
use Digest::MD5 qw(md5_hex);
use File::Temp qw(tempdir);
use HTML::Entities;
+use Encode;
use IkiWiki 3.00;
my $default_prefix = <<EOPREFIX;
@@ -31,6 +32,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
teximg_dvipng => {
type => "boolean",
@@ -102,7 +104,7 @@ sub create ($$$) {
$height = 12;
}
- my $digest = md5_hex($code, $height);
+ my $digest = md5_hex(Encode::encode_utf8($code), $height);
my $imglink= $params->{page} . "/$digest.png";
my $imglog = $params->{page} . "/$digest.log";
diff --git a/IkiWiki/Plugin/textile.pm b/IkiWiki/Plugin/textile.pm
index 8cc5a7951..56bb4bffc 100644
--- a/IkiWiki/Plugin/textile.pm
+++ b/IkiWiki/Plugin/textile.pm
@@ -19,6 +19,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1, # format plugin
+ section => "format",
},
}
diff --git a/IkiWiki/Plugin/tla.pm b/IkiWiki/Plugin/tla.pm
index f4b20a6ec..f5ad0cc96 100644
--- a/IkiWiki/Plugin/tla.pm
+++ b/IkiWiki/Plugin/tla.pm
@@ -18,6 +18,7 @@ sub import {
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+ hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
}
sub checkconfig () {
@@ -34,6 +35,7 @@ sub getsetup () {
plugin => {
safe => 0, # rcs plugin
rebuild => undef,
+ section => "rcs",
},
tla_wrapper => {
type => "string",
@@ -161,7 +163,7 @@ sub rcs_remove ($) {
error("rcs_remove not implemented for tla"); # TODO
}
-sub rcs_rename ($$) { # {{{a
+sub rcs_rename ($$) {
my ($src, $dest) = @_;
error("rcs_rename not implemented for tla"); # TODO
@@ -283,4 +285,8 @@ sub rcs_getctime ($) {
return $date;
}
+sub rcs_getmtime ($) {
+ error "rcs_getmtime is not implemented for tla\n"; # TODO
+}
+
1
diff --git a/IkiWiki/Plugin/toc.pm b/IkiWiki/Plugin/toc.pm
index b8537d3eb..ac07b9af6 100644
--- a/IkiWiki/Plugin/toc.pm
+++ b/IkiWiki/Plugin/toc.pm
@@ -18,6 +18,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/toggle.pm b/IkiWiki/Plugin/toggle.pm
index ef066a42f..f9c899540 100644
--- a/IkiWiki/Plugin/toggle.pm
+++ b/IkiWiki/Plugin/toggle.pm
@@ -20,6 +20,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/txt.pm b/IkiWiki/Plugin/txt.pm
index 8599bdc8e..0d9a0b35b 100644
--- a/IkiWiki/Plugin/txt.pm
+++ b/IkiWiki/Plugin/txt.pm
@@ -29,6 +29,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 1, # format plugin
+ section => "format",
},
}
@@ -38,7 +39,14 @@ sub filter (@) {
my %params = @_;
my $content = $params{content};
- if (defined $pagesources{$params{page}} && $pagesources{$params{page}} =~ /\.txt$/) {
+ if (defined $pagesources{$params{page}} &&
+ $pagesources{$params{page}} =~ /\.txt$/) {
+ if ($pagesources{$params{page}} eq 'robots.txt' &&
+ $params{page} eq $params{destpage}) {
+ will_render($params{page}, 'robots.txt');
+ writefile('robots.txt', $config{destdir}, $content);
+ }
+
encode_entities($content, "<>&");
if ($findurl) {
my $finder = URI::Find->new(sub {
diff --git a/IkiWiki/Plugin/typography.pm b/IkiWiki/Plugin/typography.pm
index f62be82bb..9389b24d4 100644
--- a/IkiWiki/Plugin/typography.pm
+++ b/IkiWiki/Plugin/typography.pm
@@ -9,7 +9,7 @@ use IkiWiki 3.00;
sub import {
hook(type => "getopt", id => "typography", call => \&getopt);
hook(type => "getsetup", id => "typography", call => \&getsetup);
- IkiWiki::hook(type => "sanitize", id => "typography", call => \&sanitize);
+ hook(type => "sanitize", id => "typography", call => \&sanitize);
}
sub getopt () {
diff --git a/IkiWiki/Plugin/version.pm b/IkiWiki/Plugin/version.pm
index 587cd55fa..c13643478 100644
--- a/IkiWiki/Plugin/version.pm
+++ b/IkiWiki/Plugin/version.pm
@@ -17,6 +17,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => undef,
+ section => "widget",
},
}
diff --git a/IkiWiki/Plugin/websetup.pm b/IkiWiki/Plugin/websetup.pm
index e477bcc20..d444c0a3d 100644
--- a/IkiWiki/Plugin/websetup.pm
+++ b/IkiWiki/Plugin/websetup.pm
@@ -18,6 +18,7 @@ sub getsetup () {
plugin => {
safe => 1,
rebuild => 0,
+ section => "web",
},
websetup_force_plugins => {
type => "string",
@@ -26,6 +27,13 @@ sub getsetup () {
safe => 0,
rebuild => 0,
},
+ websetup_unsafe => {
+ type => "string",
+ example => [],
+ description => "list of additional setup field keys to treat as unsafe",
+ safe => 0,
+ rebuild => 0,
+ },
websetup_show_unsafe => {
type => "boolean",
example => 1,
@@ -56,6 +64,12 @@ sub formatexample ($$) {
}
}
+sub issafe ($) {
+ my $key=shift;
+
+ return ! grep { $_ eq $key } @{$config{websetup_unsafe}};
+}
+
sub showfields ($$$@) {
my $form=shift;
my $plugin=shift;
@@ -66,27 +80,30 @@ sub showfields ($$$@) {
while (@_) {
my $key=shift;
my %info=%{shift()};
+
+ if ($key eq 'plugin') {
+ %plugininfo=%info;
+ next;
+ }
# skip internal settings
next if defined $info{type} && $info{type} eq "internal";
# XXX hashes not handled yet
next if ref $config{$key} && ref $config{$key} eq 'HASH' || ref $info{example} eq 'HASH';
# maybe skip unsafe settings
- next if ! $info{safe} && ! ($config{websetup_show_unsafe} && $config{websetup_advanced});
+ next if ! ($config{websetup_show_unsafe} && $config{websetup_advanced}) &&
+ (! $info{safe} || ! issafe($key));
# maybe skip advanced settings
next if $info{advanced} && ! $config{websetup_advanced};
# these are handled specially, so don't show
next if $key eq 'add_plugins' || $key eq 'disable_plugins';
- if ($key eq 'plugin') {
- %plugininfo=%info;
- next;
- }
-
push @show, $key, \%info;
}
- my $section=defined $plugin ? $plugin." ".gettext("plugin") : "main";
+ my $section=defined $plugin
+ ? sprintf(gettext("%s plugin:"), $plugininfo{section}).$plugin
+ : "main";
my %enabledfields;
my $shownfields=0;
@@ -97,6 +114,16 @@ sub showfields ($$$@) {
@show=();
}
+ my $section_fieldset;
+ if (defined $plugin) {
+ # Define the combined fieldset for the plugin's section.
+ # This ensures that this fieldset comes first.
+ $section_fieldset=sprintf(gettext("%s plugins"), $plugininfo{section});
+ $form->field(name => "placeholder.$plugininfo{section}",
+ type => "hidden",
+ fieldset => $section_fieldset);
+ }
+
# show plugin toggle
if (defined $plugin && (! $plugin_forced || $config{websetup_advanced})) {
my $name="enable.$plugin";
@@ -137,10 +164,13 @@ sub showfields ($$$@) {
my $name=defined $plugin ? $plugin.".".$key : $section.".".$key;
my $value=$config{$key};
+ if (! defined $value) {
+ $value="";
+ }
- if ($info{safe} && (ref $value eq 'ARRAY' || ref $info{example} eq 'ARRAY')) {
- $value=[(ref $value eq 'ARRAY' ? map { Encode::encode_utf8($_) } @{$value} : ""),
- "", ""]; # blank items for expansion
+ if (ref $value eq 'ARRAY' || ref $info{example} eq 'ARRAY') {
+ $value=[(ref $value eq 'ARRAY' ? map { Encode::encode_utf8($_) } @{$value} : "")];
+ push @$value, "", "" if $info{safe} && issafe($key); # blank items for expansion
}
else {
$value=Encode::encode_utf8($value);
@@ -194,7 +224,7 @@ sub showfields ($$$@) {
}
}
- if (! $info{safe}) {
+ if (! $info{safe} || ! issafe($key)) {
$form->field(name => $name, disabled => 1);
}
else {
@@ -203,11 +233,11 @@ sub showfields ($$$@) {
$shownfields++;
}
- # if no fields were shown for the plugin, drop it into the
- # plugins fieldset
+ # if no fields were shown for the plugin, drop it into a combined
+ # fieldset for its section
if (defined $plugin && (! $plugin_forced || $config{websetup_advanced}) &&
! $shownfields) {
- $form->field(name => "enable.$plugin", fieldset => "plugins");
+ $form->field(name => "enable.$plugin", fieldset => $section_fieldset);
}
return %enabledfields;
@@ -258,7 +288,6 @@ sub showform ($$) {
params => $cgi,
fieldsets => [
[main => gettext("main")],
- [plugins => gettext("plugins")]
],
action => $config{cgiurl},
template => {type => 'div'},
@@ -331,7 +360,7 @@ sub showform ($$) {
@value=0;
}
- if (! $info{safe}) {
+ if (! $info{safe} || ! issafe($key)) {
error("unsafe field $key"); # should never happen
}
diff --git a/IkiWiki/Plugin/wikitext.pm b/IkiWiki/Plugin/wikitext.pm
index accb03bbe..b24630b15 100644
--- a/IkiWiki/Plugin/wikitext.pm
+++ b/IkiWiki/Plugin/wikitext.pm
@@ -16,6 +16,7 @@ sub getsetup () {
plugin => {
safe => 0, # format plugin
rebuild => undef,
+ section => "format",
},
}
diff --git a/IkiWiki/Plugin/wmd.pm b/IkiWiki/Plugin/wmd.pm
index 9ddd237ab..99b136281 100644
--- a/IkiWiki/Plugin/wmd.pm
+++ b/IkiWiki/Plugin/wmd.pm
@@ -4,7 +4,6 @@ package IkiWiki::Plugin::wmd;
use warnings;
use strict;
use IkiWiki 3.00;
-use POSIX;
use Encode;
sub import {
@@ -17,6 +16,8 @@ sub getsetup () {
return
plugin => {
safe => 1,
+ rebuild => 0,
+ section => "web",
},
}
diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
index 0c21455fb..796af6af2 100644
--- a/IkiWiki/Render.pm
+++ b/IkiWiki/Render.pm
@@ -167,6 +167,7 @@ sub scan ($) {
else {
$links{$page}=[];
}
+ delete $typedlinks{$page};
run_hooks(scan => sub {
shift->(
@@ -346,6 +347,8 @@ sub find_new_files ($) {
my @new;
my @internal_new;
+ my $times_noted;
+
foreach my $file (@$files) {
my $page=pagename($file);
if (exists $pagesources{$page} && $pagesources{$page} ne $file) {
@@ -357,16 +360,33 @@ sub find_new_files ($) {
if (isinternal($page)) {
push @internal_new, $file;
}
- else {
+ elsif ($config{rcs}) {
+ if (! $times_noted) {
+ debug(sprintf(gettext("querying %s for file creation and modification times.."), $config{rcs}));
+ $times_noted=1;
+ }
+
push @new, $file;
- if ($config{getctime} && -e "$config{srcdir}/$file") {
+ if ($config{gettime} && -e "$config{srcdir}/$file") {
eval {
- my $time=rcs_getctime("$config{srcdir}/$file");
- $pagectime{$page}=$time;
+ my $ctime=rcs_getctime("$config{srcdir}/$file");
+ if ($ctime > 0) {
+ $pagectime{$page}=$ctime;
+ }
};
if ($@) {
print STDERR $@;
}
+ my $mtime;
+ eval {
+ $mtime=rcs_getmtime("$config{srcdir}/$file");
+ };
+ if ($@) {
+ print STDERR $@;
+ }
+ elsif ($mtime > 0) {
+ utime($mtime, $mtime, "$config{srcdir}/$file");
+ }
}
}
$pagecase{lc $page}=$page;
@@ -393,6 +413,7 @@ sub find_del_files ($) {
push @del, $pagesources{$page};
}
$links{$page}=[];
+ delete $typedlinks{$page};
$renderedfiles{$page}=[];
$pagemtime{$page}=0;
}
@@ -494,6 +515,29 @@ sub remove_unrendered () {
}
}
+sub link_types_changed ($$) {
+ # each is of the form { type => { link => 1 } }
+ my $new = shift;
+ my $old = shift;
+
+ return 0 if !defined $new && !defined $old;
+ return 1 if !defined $new || !defined $old;
+
+ while (my ($type, $links) = each %$new) {
+ foreach my $link (keys %$links) {
+ return 1 unless exists $old->{$type}{$link};
+ }
+ }
+
+ while (my ($type, $links) = each %$old) {
+ foreach my $link (keys %$links) {
+ return 1 unless exists $new->{$type}{$link};
+ }
+ }
+
+ return 0;
+}
+
sub calculate_changed_links ($$$) {
my ($changed, $del, $oldlink_targets)=@_;
@@ -520,6 +564,14 @@ sub calculate_changed_links ($$$) {
}
$linkchangers{lc($page)}=1;
}
+
+ # we currently assume that changing the type of a link doesn't
+ # change backlinks
+ if (!exists $linkchangers{lc($page)}) {
+ if (link_types_changed($typedlinks{$page}, $oldtypedlinks{$page})) {
+ $linkchangers{lc($page)}=1;
+ }
+ }
}
return \%backlinkchanged, \%linkchangers;
@@ -560,7 +612,7 @@ sub render_dependent ($$$$$$$) {
if (exists $depends{$p} && ! defined $reason) {
foreach my $dep (keys %{$depends{$p}}) {
my $sub=pagespec_translate($dep);
- next if $@ || ! defined $sub;
+ next unless defined $sub;
# only consider internal files
# if the page explicitly depends
@@ -695,6 +747,17 @@ sub refresh () {
}
}
+sub clean_rendered {
+ lockwiki();
+ loadindex();
+ remove_unrendered();
+ foreach my $page (keys %oldrenderedfiles) {
+ foreach my $file (@{$oldrenderedfiles{$page}}) {
+ prune($config{destdir}."/".$file);
+ }
+ }
+}
+
sub commandline_render () {
lockwiki();
loadindex();
diff --git a/IkiWiki/Setup.pm b/IkiWiki/Setup.pm
index 8a25ecc57..06102058b 100644
--- a/IkiWiki/Setup.pm
+++ b/IkiWiki/Setup.pm
@@ -1,6 +1,8 @@
#!/usr/bin/perl
-# Ikiwiki setup files are perl files that 'use IkiWiki::Setup::foo',
-# passing it some sort of configuration data.
+# Ikiwiki setup files can be perl files that 'use IkiWiki::Setup::foo',
+# passing it some sort of configuration data. Or, they can contain
+# the module name at the top, without the 'use', and the whole file is
+# then fed into that module.
package IkiWiki::Setup;
@@ -10,24 +12,58 @@ use IkiWiki;
use open qw{:utf8 :std};
use File::Spec;
-sub load ($) {
- my $setup=IkiWiki::possibly_foolish_untaint(shift);
- $config{setupfile}=File::Spec->rel2abs($setup);
+sub load ($;$) {
+ my $file=IkiWiki::possibly_foolish_untaint(shift);
+ my $safemode=shift;
+
+ $config{setupfile}=File::Spec->rel2abs($file);
#translators: The first parameter is a filename, and the second
#translators: is a (probably not translated) error message.
- open (IN, $setup) || error(sprintf(gettext("cannot read %s: %s"), $setup, $!));
- my $code;
+ open (IN, $file) || error(sprintf(gettext("cannot read %s: %s"), $file, $!));
+ my $content;
{
local $/=undef;
- $code=<IN> || error("$setup: $!");
+ $content=<IN> || error("$file: $!");
}
-
- ($code)=$code=~/(.*)/s;
close IN;
- eval $code;
- error("$setup: ".$@) if $@;
+ if ($content=~/((?:use|require)\s+)?IkiWiki::Setup::(\w+)/) {
+ $config{setuptype}=$2;
+ if ($1) {
+ error sprintf(gettext("cannot load %s in safe mode"), $file)
+ if $safemode;
+ eval IkiWiki::possibly_foolish_untaint($content);
+ error("$file: ".$@) if $@;
+ }
+ else {
+ eval qq{require IkiWiki::Setup::$config{setuptype}};
+ error $@ if $@;
+ "IkiWiki::Setup::$config{setuptype}"->loaddump(IkiWiki::possibly_foolish_untaint($content));
+ }
+ }
+ else {
+ error sprintf(gettext("failed to parse %s"), $file);
+ }
+}
+
+sub dump ($) {
+ my $file=IkiWiki::possibly_foolish_untaint(shift);
+
+ eval qq{require IkiWiki::Setup::$config{setuptype}};
+ error $@ if $@;
+ my @dump="IkiWiki::Setup::$config{setuptype}"->gendump(
+ "Setup file for ikiwiki.",
+ "",
+ "Passing this to ikiwiki --setup will make ikiwiki generate",
+ "wrappers and build the wiki.",
+ "",
+ "Remember to re-run ikiwiki --setup any time you edit this file.",
+ );
+
+ open (OUT, ">", $file) || die "$file: $!";
+ print OUT "$_\n" foreach @dump;
+ close OUT;
}
sub merge ($) {
@@ -77,7 +113,6 @@ sub merge ($) {
sub getsetup () {
# Gets all available setup data from all plugins. Returns an
# ordered list of [plugin, setup] pairs.
- my @ret;
# disable logging to syslog while dumping, broken plugins may
# whine when loaded
@@ -85,38 +120,116 @@ sub getsetup () {
$config{syslog}=undef;
# Load all plugins, so that all setup options are available.
- my @plugins=grep { $_ ne $config{rcs} } sort(IkiWiki::listplugins());
- unshift @plugins, $config{rcs} if $config{rcs}; # rcs plugin 1st
+ my @plugins=IkiWiki::listplugins();
foreach my $plugin (@plugins) {
eval { IkiWiki::loadplugin($plugin) };
if (exists $IkiWiki::hooks{checkconfig}{$plugin}{call}) {
my @s=eval { $IkiWiki::hooks{checkconfig}{$plugin}{call}->() };
}
}
-
+
+ my %sections;
foreach my $plugin (@plugins) {
if (exists $IkiWiki::hooks{getsetup}{$plugin}{call}) {
# use an array rather than a hash, to preserve order
my @s=eval { $IkiWiki::hooks{getsetup}{$plugin}{call}->() };
next unless @s;
- push @ret, [ $plugin, \@s ],
+
+ # set default section value (note use of shared
+ # hashref between array and hash)
+ my %s=@s;
+ if (! exists $s{plugin} || ! $s{plugin}->{section}) {
+ $s{plugin}->{section}="other";
+ }
+
+ # only the selected rcs plugin is included
+ if ($config{rcs} && $plugin eq $config{rcs}) {
+ $s{plugin}->{section}="core";
+ }
+ elsif ($s{plugin}->{section} eq "rcs") {
+ next;
+ }
+
+ push @{$sections{$s{plugin}->{section}}}, [ $plugin, \@s ];
}
}
$config{syslog}=$syslog;
- return @ret;
+ return map { sort { $a->[0] cmp $b->[0] } @{$sections{$_}} }
+ sort { # core first, other last, otherwise alphabetical
+ ($b eq "core") <=> ($a eq "core")
+ ||
+ ($a eq "other") <=> ($b eq "other")
+ ||
+ $a cmp $b
+ } keys %sections;
}
-sub dump ($) {
- my $file=IkiWiki::possibly_foolish_untaint(shift);
+sub commented_dump ($$) {
+ my $dumpline=shift;
+ my $indent=shift;
+
+ my %setup=(%config);
+ my @ret;
- require IkiWiki::Setup::Standard;
- my @dump=IkiWiki::Setup::Standard::gendump("Setup file for ikiwiki.");
+ # disable logging to syslog while dumping
+ $config{syslog}=undef;
- open (OUT, ">", $file) || die "$file: $!";
- print OUT "$_\n" foreach @dump;
- close OUT;
+ eval q{use Text::Wrap};
+ die $@ if $@;
+
+ my %section_plugins;
+ push @ret, commented_dumpvalues($dumpline, $indent, \%setup, IkiWiki::getsetup());
+ foreach my $pair (IkiWiki::Setup::getsetup()) {
+ my $plugin=$pair->[0];
+ my $setup=$pair->[1];
+ my %s=@{$setup};
+ my $section=$s{plugin}->{section};
+ push @{$section_plugins{$section}}, $plugin;
+ if (@{$section_plugins{$section}} == 1) {
+ push @ret, "", $indent.("#" x 70), "$indent# $section plugins",
+ sub {
+ wrap("$indent# (", "$indent# ",
+ join(", ", @{$section_plugins{$section}})).")"
+ },
+ $indent.("#" x 70);
+ }
+
+ my @values=commented_dumpvalues($dumpline, $indent, \%setup, @{$setup});
+ if (@values) {
+ push @ret, "", "$indent# $plugin plugin", @values;
+ }
+ }
+
+ return map { ref $_ ? $_->() : $_ } @ret;
+}
+
+sub commented_dumpvalues ($$$@) {
+ my $dumpline=shift;
+ my $indent=shift;
+ my $setup=shift;
+ my @ret;
+ while (@_) {
+ my $key=shift;
+ my %info=%{shift()};
+
+ next if $key eq "plugin" || $info{type} eq "internal";
+
+ push @ret, "$indent# ".$info{description} if exists $info{description};
+
+ if (exists $setup->{$key} && defined $setup->{$key}) {
+ push @ret, $dumpline->($key, $setup->{$key}, $info{type}, "");
+ delete $setup->{$key};
+ }
+ elsif (exists $info{example}) {
+ push @ret, $dumpline->($key, $info{example}, $info{type}, "#");
+ }
+ else {
+ push @ret, $dumpline->($key, "", $info{type}, "#");
+ }
+ }
+ return @ret;
}
1
diff --git a/IkiWiki/Setup/Automator.pm b/IkiWiki/Setup/Automator.pm
index 9fee4dcb7..2dcb424e5 100644
--- a/IkiWiki/Setup/Automator.pm
+++ b/IkiWiki/Setup/Automator.pm
@@ -38,19 +38,22 @@ sub sanitize_wikiname ($) {
sub import (@) {
my $this=shift;
+ $config{setuptype}='Standard';
IkiWiki::Setup::merge({@_});
- # Avoid overwriting any existing files.
- foreach my $key (qw{srcdir destdir repository dumpsetup}) {
- next unless exists $config{$key};
- my $add="";
- my $dir=IkiWiki::dirname($config{$key})."/";
- my $base=IkiWiki::basename($config{$key});
- while (-e $dir.$add.$base) {
- $add=1 if ! $add;
- $add++;
+ if (! $config{force_overwrite}) {
+ # Avoid overwriting any existing files.
+ foreach my $key (qw{srcdir destdir repository dumpsetup}) {
+ next unless exists $config{$key};
+ my $add="";
+ my $dir=IkiWiki::dirname($config{$key})."/";
+ my $base=IkiWiki::basename($config{$key});
+ while (-e $dir.$add.$base) {
+ $add=1 if ! $add;
+ $add++;
+ }
+ $config{$key}=$dir.$add.$base;
}
- $config{$key}=$dir.$add.$base;
}
# Set up wrapper
@@ -69,9 +72,15 @@ sub import (@) {
}
elsif ($config{rcs} eq 'bzr') {
# TODO
+ print STDERR "warning: do not know how to set up the bzr_wrapper hook!\n";
}
elsif ($config{rcs} eq 'mercurial') {
# TODO
+ print STDERR "warning: do not know how to set up the mercurial_wrapper hook!\n";
+ }
+ elsif ($config{rcs} eq 'tla') {
+ # TODO
+ print STDERR "warning: do not know how to set up the tla_wrapper hook!\n";
}
elsif ($config{rcs} eq 'cvs') {
$config{cvs_wrapper}=$config{repository}."/CVSROOT/post-commit";
@@ -121,9 +130,10 @@ sub import (@) {
IkiWiki::run_hooks(checkconfig => sub { shift->() });
};
if ($@) {
+ my $err=$@;
print STDERR sprintf(gettext("** Disabling plugin %s, since it is failing with this message:"),
$plugin)."\n";
- print STDERR "$@\n";
+ print STDERR "$err\n";
push @{$bakconfig{disable_plugins}}, $plugin;
}
}
@@ -142,7 +152,7 @@ sub import (@) {
# Create admin user(s).
foreach my $admin (@{$config{adminuser}}) {
- next if $admin=~/^http\?:\/\//; # openid
+ next if defined IkiWiki::openiduser($admin);
# Prompt for password w/o echo.
my ($password, $password2);
diff --git a/IkiWiki/Setup/Standard.pm b/IkiWiki/Setup/Standard.pm
index 951bcfc56..c85069304 100644
--- a/IkiWiki/Setup/Standard.pm
+++ b/IkiWiki/Setup/Standard.pm
@@ -1,7 +1,4 @@
#!/usr/bin/perl
-# Standard ikiwiki setup module.
-# Parameters to import should be all the standard ikiwiki config stuff,
-# plus an array of wrappers to set up.
package IkiWiki::Setup::Standard;
@@ -9,10 +6,22 @@ use warnings;
use strict;
use IkiWiki;
+# Parameters to import should be all the standard ikiwiki config, in a hash.
sub import {
IkiWiki::Setup::merge($_[1]);
}
+sub gendump ($@) {
+ my $class=shift;
+
+ "#!/usr/bin/perl",
+ "#",
+ (map { "# $_" } @_),
+ "use IkiWiki::Setup::Standard {",
+ IkiWiki::Setup::commented_dump(\&dumpline, "\t"),
+ "}"
+}
+
sub dumpline ($$$$) {
my $key=shift;
my $value=shift;
@@ -57,61 +66,4 @@ sub dumpline ($$$$) {
return "\t$prefix$key => $dumpedvalue,";
}
-sub dumpvalues ($@) {
- my $setup=shift;
- my @ret;
- while (@_) {
- my $key=shift;
- my %info=%{shift()};
-
- next if $key eq "plugin" || $info{type} eq "internal";
-
- push @ret, "\t# ".$info{description} if exists $info{description};
-
- if (exists $setup->{$key} && defined $setup->{$key}) {
- push @ret, dumpline($key, $setup->{$key}, $info{type}, "");
- delete $setup->{$key};
- }
- elsif (exists $info{example}) {
- push @ret, dumpline($key, $info{example}, $info{type}, "#");
- }
- else {
- push @ret, dumpline($key, "", $info{type}, "#");
- }
- }
- return @ret;
-}
-
-sub gendump ($) {
- my $description=shift;
- my %setup=(%config);
- my @ret;
-
- # disable logging to syslog while dumping
- $config{syslog}=undef;
-
- push @ret, dumpvalues(\%setup, IkiWiki::getsetup());
- foreach my $pair (IkiWiki::Setup::getsetup()) {
- my $plugin=$pair->[0];
- my $setup=$pair->[1];
- my @values=dumpvalues(\%setup, @{$setup});
- if (@values) {
- push @ret, "", "\t# $plugin plugin", @values;
- }
- }
-
- unshift @ret,
- "#!/usr/bin/perl",
- "# $description",
- "#",
- "# Passing this to ikiwiki --setup will make ikiwiki generate",
- "# wrappers and build the wiki.",
- "#",
- "# Remember to re-run ikiwiki --setup any time you edit this file.",
- "use IkiWiki::Setup::Standard {";
- push @ret, "}";
-
- return @ret;
-}
-
1
diff --git a/IkiWiki/Setup/Yaml.pm b/IkiWiki/Setup/Yaml.pm
new file mode 100644
index 000000000..904784728
--- /dev/null
+++ b/IkiWiki/Setup/Yaml.pm
@@ -0,0 +1,50 @@
+#!/usr/bin/perl
+
+package IkiWiki::Setup::Yaml;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub loaddump ($$) {
+ my $class=shift;
+ my $content=shift;
+
+ eval q{use YAML::Any};
+ eval q{use YAML} if $@;
+ die $@ if $@;
+ $YAML::Syck::ImplicitUnicode=1;
+ IkiWiki::Setup::merge(Load($content));
+}
+
+sub gendump ($@) {
+ my $class=shift;
+
+ "# IkiWiki::Setup::Yaml - YAML formatted setup file",
+ "#",
+ (map { "# $_" } @_),
+ "#",
+ IkiWiki::Setup::commented_dump(\&dumpline, "")
+}
+
+
+sub dumpline ($$$$) {
+ my $key=shift;
+ my $value=shift;
+ my $type=shift;
+ my $prefix=shift;
+
+ eval q{use YAML::Old};
+ eval q{use YAML} if $@;
+ die $@ if $@;
+ $YAML::UseHeader=0;
+
+ my $dump=Dump({$key => $value});
+ chomp $dump;
+ if (length $prefix) {
+ $dump=join("\n", map { $prefix.$_ } split(/\n/, $dump));
+ }
+ return $dump;
+}
+
+1
diff --git a/IkiWiki/Wrapper.pm b/IkiWiki/Wrapper.pm
index 5427a5c80..3f3e63ca6 100644
--- a/IkiWiki/Wrapper.pm
+++ b/IkiWiki/Wrapper.pm
@@ -76,8 +76,8 @@ EOF
{
int fd=open("$config{wikistatedir}/cgilock", O_CREAT | O_RDWR, 0666);
if (fd != -1 && flock(fd, LOCK_EX) == 0) {
- char *fd_s;
- asprintf(&fd_s, "%i", fd);
+ char *fd_s=malloc(8);
+ sprintf(fd_s, "%i", fd);
setenv("IKIWIKI_CGILOCK_FD", fd_s, 1);
}
}
@@ -105,7 +105,7 @@ extern char **environ;
char *newenviron[$#envsave+6];
int i=0;
-addenv(char *var, char *val) {
+void addenv(char *var, char *val) {
char *s=malloc(strlen(var)+1+strlen(val)+1);
if (!s)
perror("malloc");
@@ -121,8 +121,18 @@ $check_commit_hook
$envsave
newenviron[i++]="HOME=$ENV{HOME}";
newenviron[i++]="WRAPPED_OPTIONS=$configstring";
+
+#ifdef __TINYC__
+ if (clearenv() != 0) {
+ perror("clearenv");
+ exit(1);
+ }
+ for (; i>0; i--)
+ putenv(newenviron[i-1]);
+#else
newenviron[i]=NULL;
environ=newenviron;
+#endif
if (setregid(getegid(), -1) != 0 &&
setregid(getegid(), -1) != 0) {