X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/3479809f96fa9c7a5d9f86c18c581f9a343a3aef..85cc90cccdb4a4c7a83a3e0964dbb7d84fc385e4:/IkiWiki.pm
diff --git a/IkiWiki.pm b/IkiWiki.pm
index db16a0854..f1a5f8058 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -1,6 +1,7 @@
#!/usr/bin/perl
package IkiWiki;
+
use warnings;
use strict;
use Encode;
@@ -87,6 +88,8 @@ sub defaultconfig () { #{{{
numbacklinks => 10,
account_creation_password => "",
prefix_directives => 0,
+ hardlink => 0,
+ cgi_disable_uploads => 1,
} #}}}
sub checkconfig () { #{{{
@@ -102,6 +105,12 @@ sub checkconfig () { #{{{
}
}
+ if (ref $config{ENV} eq 'HASH') {
+ foreach my $val (keys %{$config{ENV}}) {
+ $ENV{$val}=$config{ENV}{$val};
+ }
+ }
+
if ($config{w3mmode}) {
eval q{use Cwd q{abs_path}};
error($@) if $@;
@@ -281,17 +290,22 @@ sub htmlpage ($) { #{{{
return targetpage($page, $config{htmlext});
} #}}}
-sub srcfile ($) { #{{{
+sub srcfile_stat { #{{{
my $file=shift;
+ my $nothrow=shift;
- return "$config{srcdir}/$file" if -e "$config{srcdir}/$file";
+ return "$config{srcdir}/$file", stat(_) if -e "$config{srcdir}/$file";
foreach my $dir (@{$config{underlaydirs}}, $config{underlaydir}) {
- return "$dir/$file" if -e "$dir/$file";
+ return "$dir/$file", stat(_) if -e "$dir/$file";
}
- error("internal error: $file cannot be found in $config{srcdir} or underlay");
+ error("internal error: $file cannot be found in $config{srcdir} or underlay") unless $nothrow;
return;
} #}}}
+sub srcfile ($;$) { #{{{
+ return (srcfile_stat(@_))[0];
+} #}}}
+
sub add_underlay ($) { #{{{
my $dir=shift;
@@ -323,12 +337,9 @@ sub readfile ($;$$) { #{{{
return $ret;
} #}}}
-sub writefile ($$$;$$) { #{{{
- my $file=shift; # can include subdirs
- my $destdir=shift; # directory to put file in
- my $content=shift;
- my $binary=shift;
- my $writer=shift;
+sub prep_writefile ($$) { #{{{
+ my $file=shift;
+ my $destdir=shift;
my $test=$file;
while (length $test) {
@@ -337,12 +348,8 @@ sub writefile ($$$;$$) { #{{{
}
$test=dirname($test);
}
- my $newfile="$destdir/$file.ikiwiki-new";
- if (-l $newfile) {
- error("cannot write to a symlink ($newfile)");
- }
- my $dir=dirname($newfile);
+ my $dir=dirname("$destdir/$file");
if (! -d $dir) {
my $d="";
foreach my $s (split(m!/+!, $dir)) {
@@ -353,6 +360,23 @@ sub writefile ($$$;$$) { #{{{
}
}
+ return 1;
+} #}}}
+
+sub writefile ($$$;$$) { #{{{
+ my $file=shift; # can include subdirs
+ my $destdir=shift; # directory to put file in
+ my $content=shift;
+ my $binary=shift;
+ my $writer=shift;
+
+ prep_writefile($file, $destdir);
+
+ my $newfile="$destdir/$file.ikiwiki-new";
+ if (-l $newfile) {
+ error("cannot write to a symlink ($newfile)");
+ }
+
my $cleanup = sub { unlink($newfile) };
open (my $out, '>', $newfile) || error("failed to write $newfile: $!", $cleanup);
binmode($out) if ($binary);
@@ -509,13 +533,18 @@ sub displaytime ($;$) { #{{{
return decode_utf8(POSIX::strftime($format, localtime($time)));
} #}}}
-sub beautify_url ($) { #{{{
+sub beautify_urlpath ($) { #{{{
my $url=shift;
if ($config{usedirs}) {
$url =~ s!/index.$config{htmlext}$!/!;
}
- $url =~ s!^$!./!; # Browsers don't like empty links...
+
+ # Ensure url is not an empty link, and
+ # if it's relative, make that explicit to avoid colon confusion.
+ if ($url !~ /\//) {
+ $url="./$url";
+ }
return $url;
} #}}}
@@ -525,7 +554,7 @@ sub urlto ($$) { #{{{
my $from=shift;
if (! length $to) {
- return beautify_url(baseurl($from));
+ return beautify_urlpath(baseurl($from)."index.$config{htmlext}");
}
if (! $destsources{$to}) {
@@ -534,7 +563,7 @@ sub urlto ($$) { #{{{
my $link = abs2rel($to, dirname(htmlpage($from)));
- return beautify_url($link);
+ return beautify_urlpath($link);
} #}}}
sub htmllink ($$$;@) { #{{{
@@ -573,15 +602,15 @@ sub htmllink ($$$;@) { #{{{
return " "create",
- page => pagetitle(lc($link), 1),
+ page => lc($link),
from => $lpage
).
- "\">?$linktext"
+ "\" rel=\"nofollow\">?$linktext"
}
}
$bestlink=abs2rel($bestlink, dirname(htmlpage($page)));
- $bestlink=beautify_url($bestlink);
+ $bestlink=beautify_urlpath($bestlink);
if (! $opts{noimageinline} && isinlinableimage($bestlink)) {
return "";
@@ -610,14 +639,18 @@ sub userlink ($) { #{{{
return "$oiduser";
}
else {
+ eval q{use CGI 'escapeHTML'};
+ error($@) if $@;
+
return htmllink("", "", escapeHTML(
length $config{userdir} ? $config{userdir}."/".$user : $user
), noimageinline => 1);
}
} #}}}
-sub htmlize ($$$) { #{{{
+sub htmlize ($$$$) { #{{{
my $page=shift;
+ my $destpage=shift;
my $type=shift;
my $content=shift;
@@ -636,6 +669,7 @@ sub htmlize ($$$) { #{{{
run_hooks(sanitize => sub {
$content=shift->(
page => $page,
+ destpage => $destpage,
content => $content,
);
});
@@ -667,7 +701,7 @@ sub linkify ($$$) { #{{{
return $content;
} #}}}
-my %preprocessing;
+our %preprocessing;
our $preprocess_preview=0;
sub preprocess ($$$;$$) { #{{{
my $page=shift; # the page the data comes from
@@ -902,7 +936,7 @@ sub loadindex () { #{{{
my $in;
if (! open ($in, "<", "$config{wikistatedir}/indexdb")) {
if (-e "$config{wikistatedir}/index") {
- system("ikiwiki-transition", "indexdb", $config{wikistatedir});
+ system("ikiwiki-transition", "indexdb", $config{srcdir});
open ($in, "<", "$config{wikistatedir}/indexdb") || return;
}
else {
@@ -914,12 +948,13 @@ sub loadindex () { #{{{
return 0;
}
my %index=%$ret;
- foreach my $page (keys %index) {
- my %d=%{$index{$page}};
+ foreach my $src (keys %index) {
+ my %d=%{$index{$src}};
+ my $page=pagename($src);
$pagectime{$page}=$d{ctime};
if (! $config{rebuild}) {
+ $pagesources{$page}=$src;
$pagemtime{$page}=$d{mtime};
- $pagesources{$page}=$d{src};
$renderedfiles{$page}=$d{dest};
if (exists $d{links} && ref $d{links}) {
$links{$page}=$d{links};
@@ -961,23 +996,23 @@ sub saveindex () { #{{{
my %index;
foreach my $page (keys %pagemtime) {
next unless $pagemtime{$page};
+ my $src=$pagesources{$page};
- $index{$page}={
+ $index{$src}={
ctime => $pagectime{$page},
mtime => $pagemtime{$page},
- src => $pagesources{$page},
dest => $renderedfiles{$page},
links => $links{$page},
};
if (exists $depends{$page}) {
- $index{$page}{depends} = $depends{$page};
+ $index{$src}{depends} = $depends{$page};
}
if (exists $pagestate{$page}) {
foreach my $id (@hookids) {
foreach my $key (keys %{$pagestate{$page}{$id}}) {
- $index{$page}{state}{$id}{$key}=$pagestate{$page}{$id}{$key};
+ $index{$src}{state}{$id}{$key}=$pagestate{$page}{$id}{$key};
}
}
}
@@ -1167,6 +1202,12 @@ sub gettext { #{{{
}
} #}}}
+sub yesno ($) { #{{{
+ my $val=shift;
+
+ return (defined $val && lc($val) eq gettext("yes"));
+} #}}}
+
sub pagespec_merge ($$) { #{{{
my $a=shift;
my $b=shift;
@@ -1232,6 +1273,11 @@ sub pagespec_translate ($) { #{{{
}
}
+ if (! length $code) {
+ $code=0;
+ }
+
+ no warnings;
return eval 'sub { my $page=shift; '.$code.' }';
} #}}}
@@ -1246,7 +1292,7 @@ sub pagespec_match ($$;@) { #{{{
}
my $sub=pagespec_translate($spec);
- return IkiWiki::FailReason->new('syntax error') if $@;
+ return IkiWiki::FailReason->new("syntax error in pagespec \"$spec\"") if $@;
return $sub->($page, @params);
} #}}}
@@ -1256,6 +1302,13 @@ sub pagespec_valid ($) { #{{{
my $sub=pagespec_translate($spec);
return ! $@;
} #}}}
+
+sub glob2re ($) { #{{{
+ my $re=quotemeta(shift);
+ $re=~s/\\\*/.*/g;
+ $re=~s/\\\?/./g;
+ return $re;
+} #}}}
package IkiWiki::FailReason;
@@ -1267,7 +1320,9 @@ use overload ( #{{{
); #}}}
sub new { #{{{
- return bless \$_[1], $_[0];
+ my $class = shift;
+ my $value = shift;
+ return bless \$value, $class;
} #}}}
package IkiWiki::SuccessReason;
@@ -1280,7 +1335,9 @@ use overload ( #{{{
); #}}}
sub new { #{{{
- return bless \$_[1], $_[0];
+ my $class = shift;
+ my $value = shift;
+ return bless \$value, $class;
}; #}}}
package IkiWiki::PageSpec;
@@ -1299,12 +1356,8 @@ sub match_glob ($$;@) { #{{{
$glob="$from/$glob" if length $from;
}
- # turn glob into safe regexp
- $glob=quotemeta($glob);
- $glob=~s/\\\*/.*/g;
- $glob=~s/\\\?/./g;
-
- if ($page=~/^$glob$/i) {
+ my $regexp=IkiWiki::glob2re($glob);
+ if ($page=~/^$regexp$/i) {
if (! IkiWiki::isinternal($page) || $params{internal}) {
return IkiWiki::SuccessReason->new("$glob matches $page");
}