X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/blobdiff_plain/1c4d4e1e0474b6ffd3b8e0213d8a4804a3597e34..7bbfbf82fb17c05cc70ec042c1fdd4e0fb370b12:/ikiwiki diff --git a/ikiwiki b/ikiwiki index add627739..bda2d0401 100755 --- a/ikiwiki +++ b/ikiwiki @@ -10,7 +10,8 @@ use Getopt::Long; my (%links, %oldlinks, %oldpagemtime, %renderedfiles, %pagesources); -my %config=( #{{{ +# Holds global config settings, also used by some modules. +our %config=( #{{{ wiki_file_prune_regexp => qr{((^|/).svn/|\.\.|^\.|\/\.|\.html?$)}, wiki_link_regexp => qr/\[\[([^\s]+)\]\]/, wiki_file_regexp => qr/(^[-A-Za-z0-9_.:\/+]+$)/, @@ -69,11 +70,8 @@ sub error { #{{{ if ($config{cgi}) { print "Content-type: text/html\n\n"; print misctemplate("Error", "

Error: @_

"); - exit 1; - } - else { - die @_; } + die @_; } #}}} sub debug ($) { #{{{ @@ -168,14 +166,17 @@ sub writefile ($$) { #{{{ close OUT; } #}}} -sub findlinks ($) { #{{{ +sub findlinks ($$) { #{{{ my $content=shift; + my $page=shift; my @links; while ($content =~ /(??$link" - } - else { - return "?$link" - } + return "?$link" } $bestlink=File::Spec->abs2rel($bestlink, dirname($page)); @@ -307,14 +309,14 @@ sub parentlinks ($) { #{{{ my $skip=1; foreach my $dir (reverse split("/", $page)) { if (! $skip) { + $path.="../"; unshift @ret, { url => "$path$dir.html", page => $dir }; } else { $skip=0; } - $path.="../"; } - unshift @ret, { url => $path , page => $config{wikiname} }; + unshift @ret, { url => length $path ? $path : ".", page => $config{wikiname} }; return @ret; } #}}} @@ -364,10 +366,10 @@ sub check_overwrite ($$) { #{{{ my $src=shift; if (! exists $renderedfiles{$src} && -e $dest && ! $config{rebuild}) { - error("$dest exists and was rendered from ". + error("$dest already exists and was rendered from ". join(" ",(grep { $renderedfiles{$_} eq $dest } keys %renderedfiles)). - ", not from $src before not overwriting"); + ", before, so not rendering from $src"); } } #}}} @@ -379,7 +381,7 @@ sub render ($) { #{{{ if ($type ne 'unknown') { my $page=pagename($file); - $links{$page}=[findlinks($content)]; + $links{$page}=[findlinks($content, $page)]; $content=linkify($content, $file); $content=htmlize($type, $content); @@ -399,6 +401,25 @@ sub render ($) { #{{{ } } #}}} +sub lockwiki () { #{{{ + # Take an exclusive lock on the wiki to prevent multiple concurrent + # run issues. The lock will be dropped on program exit. + if (! -d "$config{srcdir}/.ikiwiki") { + mkdir("$config{srcdir}/.ikiwiki"); + } + open(WIKILOCK, ">$config{srcdir}/.ikiwiki/lockfile") || error ("cannot write to lockfile: $!"); + if (! flock(WIKILOCK, 2 | 4)) { + debug("wiki seems to be locked, waiting for lock"); + my $wait=600; # arbitrary, but don't hang forever to + # prevent process pileup + for (1..600) { + return if flock(WIKILOCK, 2 | 4); + sleep 1; + } + error("wiki is locked; waited $wait seconds without lock being freed (possible stuck process or stale lock?)"); + } +} #}}} + sub loadindex () { #{{{ open (IN, "$config{srcdir}/.ikiwiki/index") || return; while () { @@ -483,7 +504,7 @@ sub rcs_recentchanges ($) { #{{{ my $infoline=qr/^r(\d+)\s+\|\s+([^\s]+)\s+\|\s+(\d+-\d+-\d+\s+\d+:\d+:\d+\s+[-+]?\d+).*/; my $state='start'; my ($rev, $user, $when, @pages, @message); - foreach (`LANG=C svn log -v '$svn_url'`) { + foreach (`LANG=C svn log --limit $num -v '$svn_url'`) { chomp; if ($state eq 'start' && /$div/) { $state='header'; @@ -523,7 +544,7 @@ sub rcs_recentchanges ($) { #{{{ @pages=@message=(); } elsif ($state eq 'body') { - push @message, {line => $_}, + push @message, {line => escapeHTML($_)}, } } } @@ -555,7 +576,7 @@ sub refresh () { #{{{ $File::Find::prune=1; use warnings "all"; } - elsif (! -d $_) { + elsif (! -d $_ && ! -l $_) { my ($f)=/$config{wiki_file_regexp}/; # untaint if (! defined $f) { warn("skipping bad filename $_\n"); @@ -638,8 +659,7 @@ FILE: foreach my $file (@files) { foreach my $file (keys %rendered, @del) { my $page=pagename($file); if (exists $links{$page}) { - foreach my $link (@{$links{$page}}) { - $link=bestlink($page, $link); + foreach my $link (map { bestlink($page, $_) } @{$links{$page}}) { if (length $link && ! exists $oldlinks{$page} || ! grep { $_ eq $link } @{$oldlinks{$page}}) { @@ -648,8 +668,7 @@ FILE: foreach my $file (@files) { } } if (exists $oldlinks{$page}) { - foreach my $link (@{$oldlinks{$page}}) { - $link=bestlink($page, $link); + foreach my $link (map { bestlink($page, $_) } @{$oldlinks{$page}}) { if (length $link && ! exists $links{$page} || ! grep { $_ eq $link } @{$links{$page}}) { @@ -692,7 +711,7 @@ sub gen_wrapper (@) { #{{{ push @params, "--cgiurl=$config{cgiurl}" if length $config{cgiurl}; push @params, "--historyurl=$config{historyurl}" if length $config{historyurl}; push @params, "--anonok" if $config{anonok}; - my $params=join(" ", map { "\'$_\'" } @params); + my $params=join(" ", @params); my $call=''; foreach my $p ($this, $this, @params) { $call.=qq{"$p", }; @@ -1022,26 +1041,31 @@ sub cgi_editpage ($$) { #{{{ } my @page_locs; + my $best_loc; my ($from)=$form->param('from')=~/$config{wiki_file_regexp}/; if (! defined $from || ! length $from || $from ne $form->param('from') || $from=~/$config{wiki_file_prune_regexp}/ || $from=~/^\//) { - @page_locs=$page; + @page_locs=$best_loc=$page; } else { my $dir=$from."/"; $dir=~s![^/]+/$!!; push @page_locs, $dir.$page; push @page_locs, "$from/$page"; + $best_loc="$from/$page"; while (length $dir) { $dir=~s![^/]+/$!!; push @page_locs, $dir.$page; } + + @page_locs = grep { ! exists + $pagesources{lc($_)} } @page_locs; } $form->tmpl_param("page_select", 1); $form->field(name => "page", type => 'select', - options => \@page_locs); + options => \@page_locs, value => $best_loc); $form->title("creating $page"); } elsif ($form->field("do") eq "edit") { @@ -1096,7 +1120,9 @@ sub cgi_editpage ($$) { #{{{ rcs_commit($message); } else { + loadindex(); refresh(); + saveindex(); } # The trailing question mark tries to avoid broken @@ -1159,25 +1185,13 @@ sub setup () { # {{{ ($code)=$code=~/(.*)/s; close IN; - my (%setup); eval $code; error($@) if $@; - - gen_wrapper(%config, %setup, %{$setup{cgiwrapper}}) if $setup{cgiwrapper}; - gen_wrapper(%config, %setup, %{$setup{svnwrapper}}) if $setup{svnwrapper}; - - print "$setup{wikiname} setup complete, now forcing a rebuild\n"; - foreach my $c (keys %setup) { - $config{$c}=possibly_foolish_untaint($setup{$c}) - if defined $setup{$c} && ! ref $setup{$c}; - } - $config{rebuild}=1; - refresh(); - saveindex(); exit; } #}}} # main {{{ +lockwiki(); setup() if $config{setup}; if ($config{wrapper}) { gen_wrapper(%config);