X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/09902169560ec64800c5622d87fd2d85c246fc93..7144eb3973ac73a5f79440f91a7c01665fb83aa4:/ikiwiki

diff --git a/ikiwiki b/ikiwiki
index 4246c7e78..7e140bbec 100755
--- a/ikiwiki
+++ b/ikiwiki
@@ -1,21 +1,16 @@
 #!/usr/bin/perl -T
+$ENV{PATH}="/usr/local/bin:/usr/bin:/bin";
 
 use warnings;
 use strict;
-use File::Find;
 use Memoize;
 use File::Spec;
 use HTML::Template;
+use Getopt::Long;
 
-BEGIN {
-	$blosxom::version="is a proper perl module too much to ask?";
-	do "/usr/bin/markdown";
-}
-
-$ENV{PATH}="/usr/local/bin:/usr/bin:/bin";
 my (%links, %oldlinks, %oldpagemtime, %renderedfiles, %pagesources);
 
-my %config=(
+my %config=( #{{{
 	wiki_file_prune_regexp => qr{((^|/).svn/|\.\.|^\.|\/\.|\.html?$)},
 	wiki_link_regexp => qr/\[\[([^\s]+)\]\]/,
 	wiki_file_regexp => qr/(^[-A-Za-z0-9_.:\/+]+$)/,
@@ -23,23 +18,54 @@ my %config=(
 	wikiname => "wiki",
 	default_pageext => ".mdwn",
 	cgi => 0,
-	url => "",
-	cgiurl => "",
-	historyurl => "",
 	svn => 1,
+	url => '',
+	cgiurl => '',
+	historyurl => '',
 	anonok => 0,
 	rebuild => 0,
-	wrapper => 0,
+	wrapper => undef,
+	wrappermode => undef,
 	srcdir => undef,
 	destdir => undef,
 	templatedir => undef,
-);
+	setup => undef,
+); #}}}
+
+GetOptions( #{{{
+	"setup=s" => \$config{setup},
+	"wikiname=s" => \$config{wikiname},
+	"verbose|v!" => \$config{verbose},
+	"rebuild!" => \$config{rebuild},
+	"wrapper=s" => sub { $config{wrapper}=$_[1] ? $_[1] : "ikiwiki-wrap" },
+	"wrappermode=i" => \$config{wrappermode},
+	"svn!" => \$config{svn},
+	"anonok!" => \$config{anonok},
+	"cgi!" => \$config{cgi},
+	"url=s" => \$config{url},
+	"cgiurl=s" => \$config{cgiurl},
+	"historyurl=s" => \$config{historyurl},
+	"exclude=s@" => sub {
+		$config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$_[1]/;
+	},
+) || usage();
+
+if (! $config{setup}) {
+	usage() unless @ARGV == 3;
+	$config{srcdir} = possibly_foolish_untaint(shift);
+	$config{templatedir} = possibly_foolish_untaint(shift);
+	$config{destdir} = possibly_foolish_untaint(shift);
+	if ($config{cgi} && ! length $config{url}) {
+		error("Must specify url to wiki with --url when using --cgi");
+	}
+}
+#}}}
 
 sub usage { #{{{
 	die "usage: ikiwiki [options] source templates dest\n";
 } #}}}
 
-sub error ($) { #{{{
+sub error { #{{{
 	if ($config{cgi}) {
 		print "Content-type: text/html\n\n";
 		print misctemplate("Error", "<p>Error: @_</p>");
@@ -66,7 +92,7 @@ sub mtime ($) { #{{{
 	return (stat($page))[9];
 } #}}}
 
-sub possibly_foolish_untaint ($) { #{{{
+sub possibly_foolish_untaint { #{{{
 	my $tainted=shift;
 	my ($untainted)=$tainted=~/(.*)/;
 	return $untainted;
@@ -146,17 +172,18 @@ sub findlinks ($) { #{{{
 	my $content=shift;
 
 	my @links;
-	while ($content =~ /$config{wiki_link_regexp}/g) {
+	while ($content =~ /(?<!\\)$config{wiki_link_regexp}/g) {
 		push @links, lc($1);
 	}
 	return @links;
 } #}}}
 
-# Given a page and the text of a link on the page, determine which existing
-# page that link best points to. Prefers pages under a subdirectory with
-# the same name as the source page, failing that goes down the directory tree
-# to the base looking for matching pages.
 sub bestlink ($$) { #{{{
+	# Given a page and the text of a link on the page, determine which
+	# existing page that link best points to. Prefers pages under a
+	# subdirectory with the same name as the source page, failing that
+	# goes down the directory tree to the base looking for matching
+	# pages.
 	my $page=shift;
 	my $link=lc(shift);
 	
@@ -220,7 +247,9 @@ sub linkify ($$) { #{{{
 	my $content=shift;
 	my $file=shift;
 
-	$content =~ s/$config{wiki_link_regexp}/htmllink(pagename($file), $1)/eg;
+	$content =~ s{(\\?)$config{wiki_link_regexp}}{
+		$1 ? "[[$2]]" : htmllink(pagename($file), $2)
+	}eg;
 	
 	return $content;
 } #}}}
@@ -229,6 +258,13 @@ sub htmlize ($$) { #{{{
 	my $type=shift;
 	my $content=shift;
 	
+	if (! $INC{"/usr/bin/markdown"}) {
+		no warnings 'once';
+		$blosxom::version="is a proper perl module too much to ask?";
+		use warnings 'all';
+		do "/usr/bin/markdown";
+	}
+	
 	if ($type eq '.mdwn') {
 		return Markdown::Markdown($content);
 	}
@@ -271,14 +307,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;
 } #}}}
 
@@ -321,9 +357,9 @@ sub finalize ($$) { #{{{
 	return $template->output;
 } #}}}
 
-# Important security check. Make sure to call this before saving any files
-# to the source directory.
 sub check_overwrite ($$) { #{{{
+	# Important security check. Make sure to call this before saving
+	# any files to the source directory.
 	my $dest=shift;
 	my $src=shift;
 	
@@ -509,11 +545,15 @@ sub refresh () { #{{{
 	# Find existing pages.
 	my %exists;
 	my @files;
+	
+	eval q{use File::Find};
 	find({
 		no_chdir => 1,
 		wanted => sub {
 			if (/$config{wiki_file_prune_regexp}/) {
+				no warnings 'once';
 				$File::Find::prune=1;
+				use warnings "all";
 			}
 			elsif (! -d $_) {
 				my ($f)=/$config{wiki_file_regexp}/; # untaint
@@ -628,9 +668,8 @@ FILE:		foreach my $file (@files) {
 	}
 } #}}}
 
-# Generates a C wrapper program for running ikiwiki in a specific way.
-# The wrapper may be safely made suid.
-sub gen_wrapper () { #{{{
+sub gen_wrapper (@) { #{{{
+	my %config=(@_);
 	eval q{use Cwd 'abs_path'};
 	$config{srcdir}=abs_path($config{srcdir});
 	$config{destdir}=abs_path($config{destdir});
@@ -639,6 +678,10 @@ sub gen_wrapper () { #{{{
 		error("$this doesn't seem to be executable");
 	}
 
+	if ($config{setup}) {
+		error("cannot create a wrapper that uses a setup file");
+	}
+	
 	my @params=($config{srcdir}, $config{templatedir}, $config{destdir},
 		"--wikiname=$config{wikiname}");
 	push @params, "--verbose" if $config{verbose};
@@ -700,12 +743,15 @@ $envsave
 }
 EOF
 	close OUT;
-	if (system("gcc", "ikiwiki-wrap.c", "-o", "ikiwiki-wrap") != 0) {
+	if (system("gcc", "ikiwiki-wrap.c", "-o", possibly_foolish_untaint($config{wrapper})) != 0) {
 		error("failed to compile ikiwiki-wrap.c");
 	}
 	unlink("ikiwiki-wrap.c");
-	print "successfully generated ikiwiki-wrap\n";
-	exit 0;
+	if (defined $config{wrappermode} &&
+	    ! chmod(oct($config{wrappermode}), possibly_foolish_untaint($config{wrapper}))) {
+		error("chmod $config{wrapper}: $!");
+	}
+	print "successfully generated $config{wrapper}\n";
 } #}}}
 		
 sub misctemplate ($$) { #{{{
@@ -1104,35 +1150,39 @@ sub cgi () { #{{{
 	}
 } #}}}
 
-# main {{{
-if (grep /^-/, @ARGV) {
-	eval {use Getopt::Long};
-	GetOptions(
-		"wikiname=s" => \$config{wikiname},
-		"verbose|v!" => \$config{verbose},
-		"rebuild!" => \$config{rebuild},
-		"wrapper!" => \$config{wrapper},
-		"svn!" => \$config{svn},
-		"anonok!" => \$config{anonok},
-		"cgi!" => \$config{cgi},
-		"url=s" => \$config{url},
-		"cgiurl=s" => \$config{cgiurl},
-		"historyurl=s" => \$config{historyurl},
-		"exclude=s@" => sub {
-			$config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$_[1]/;
-		},
-	) || usage();
-}
-usage() unless @ARGV == 3;
-$config{srcdir} = possibly_foolish_untaint(shift);
-$config{templatedir} = possibly_foolish_untaint(shift);
-$config{destdir} = possibly_foolish_untaint(shift);
+sub setup () { # {{{
+	my $setup=possibly_foolish_untaint($config{setup});
+	delete $config{setup};
+	open (IN, $setup) || error("read $setup: $!\n");
+	local $/=undef;
+	my $code=<IN>;
+	($code)=$code=~/(.*)/s;
+	close IN;
 
-if ($config{cgi} && ! length $config{url}) {
-	error("Must specify url to wiki with --url when using --cgi");
-}
+	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;
+} #}}}
 
-gen_wrapper() if $config{wrapper};
+# main {{{
+setup() if $config{setup};
+if ($config{wrapper}) {
+	gen_wrapper(%config);
+	exit;
+}
 memoize('pagename');
 memoize('bestlink');
 loadindex() unless $config{rebuild};