X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/e674bb1445378ce43ae60720e42d6c418270001a..f826251a6d506d6f8a31e30abfbe89338351bd6a:/IkiWiki.pm

diff --git a/IkiWiki.pm b/IkiWiki.pm
index fa49b2c34..2190f008c 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -717,7 +717,7 @@ sub pagename ($) {
 
 	my $type=pagetype($file);
 	my $page=$file;
- 	$page=~s/\Q.$type\E*$//
+	$page=~s/\Q.$type\E*$//
 		if defined $type && !$hooks{htmlize}{$type}{keepextension}
 			&& !$hooks{htmlize}{$type}{noextension};
 	if ($config{indexpages} && $page=~/(.*)\/index$/) {
@@ -911,7 +911,7 @@ sub will_render ($$;$) {
 	if (-d _) {
 		foreach my $p (keys %renderedfiles, keys %oldrenderedfiles) {
 			foreach my $f (@{$renderedfiles{$p}}, @{$oldrenderedfiles{$p}}) {
-				if ($f eq dirname($dest) || dirname($f) eq $dest) {
+				if (dirname($f) eq $dest) {
 					unlink("$config{destdir}/$f");
 					rmdir(dirname("$config{destdir}/$f"));
 				}
@@ -1118,6 +1118,15 @@ sub urlto ($$;$) {
 	return beautify_urlpath($link);
 }
 
+sub isselflink ($$) {
+	# Plugins can override this function to support special types
+	# of selflinks.
+	my $page=shift;
+	my $link=shift;
+
+	return $page eq $link;
+}
+
 sub htmllink ($$$;@) {
 	my $lpage=shift; # the page doing the linking
 	my $page=shift; # the page that will contain the link (different for inline)
@@ -1143,7 +1152,7 @@ sub htmllink ($$$;@) {
 	}
 	
 	return "<span class=\"selflink\">$linktext</span>"
-		if length $bestlink && $page eq $bestlink &&
+		if length $bestlink && isselflink($page, $bestlink) &&
 		   ! defined $opts{anchor};
 	
 	if (! $destsources{$bestlink}) {
@@ -1510,6 +1519,69 @@ sub check_content (@) {
 	return defined $ok ? $ok : 1;
 }
 
+sub check_canchange (@) {
+	my %params = @_;
+	my $cgi = $params{cgi};
+	my $session = $params{session};
+	my @changes = @{$params{changes}};
+
+	my %newfiles;
+	foreach my $change (@changes) {
+		# This untaint is safe because we check file_pruned and
+		# wiki_file_regexp.
+		my ($file)=$change->{file}=~/$config{wiki_file_regexp}/;
+		$file=possibly_foolish_untaint($file);
+		if (! defined $file || ! length $file ||
+		    file_pruned($file)) {
+			error(gettext("bad file name %s"), $file);
+		}
+
+		my $type=pagetype($file);
+		my $page=pagename($file) if defined $type;
+
+		if ($change->{action} eq 'add') {
+			$newfiles{$file}=1;
+		}
+
+		if ($change->{action} eq 'change' ||
+		    $change->{action} eq 'add') {
+			if (defined $page) {
+				check_canedit($page, $cgi, $session);
+				next;
+			}
+			else {
+				if (IkiWiki::Plugin::attachment->can("check_canattach")) {
+					IkiWiki::Plugin::attachment::check_canattach($session, $file, $change->{path});
+					check_canedit($file, $cgi, $session);
+					next;
+				}
+			}
+		}
+		elsif ($change->{action} eq 'remove') {
+			# check_canremove tests to see if the file is present
+			# on disk. This will fail when a single commit adds a
+			# file and then removes it again. Avoid the problem
+			# by not testing the removal in such pairs of changes.
+			# (The add is still tested, just to make sure that
+			# no data is added to the repo that a web edit
+			# could not add.)
+			next if $newfiles{$file};
+
+			if (IkiWiki::Plugin::remove->can("check_canremove")) {
+				IkiWiki::Plugin::remove::check_canremove(defined $page ? $page : $file, $cgi, $session);
+				check_canedit(defined $page ? $page : $file, $cgi, $session);
+				next;
+			}
+		}
+		else {
+			error "unknown action ".$change->{action};
+		}
+
+		error sprintf(gettext("you are not allowed to change %s"), $file);
+	}
+}
+
+
 my $wikilock;
 
 sub lockwiki () {
@@ -1587,6 +1659,12 @@ sub loadindex () {
 	if (exists $index->{version} && ! ref $index->{version}) {
 		$pages=$index->{page};
 		%wikistate=%{$index->{state}};
+		# Handle plugins that got disabled by loading a new setup.
+		if (exists $config{setupfile}) {
+			require IkiWiki::Setup;
+			IkiWiki::Setup::disabled_plugins(
+				grep { ! $loaded_plugins{$_} } keys %wikistate);
+		}
 	}
 	else {
 		$pages=$index;
@@ -1654,11 +1732,7 @@ sub loadindex () {
 sub saveindex () {
 	run_hooks(savestate => sub { shift->() });
 
-	my %hookids;
-	foreach my $type (keys %hooks) {
-		$hookids{$_}=1 foreach keys %{$hooks{$type}};
-	}
-	my @hookids=keys %hookids;
+	my @plugins=keys %loaded_plugins;
 
 	if (! -d $config{wikistatedir}) {
 		mkdir($config{wikistatedir});
@@ -1692,7 +1766,7 @@ sub saveindex () {
 		}
 
 		if (exists $pagestate{$page}) {
-			foreach my $id (@hookids) {
+			foreach my $id (@plugins) {
 				foreach my $key (keys %{$pagestate{$page}{$id}}) {
 					$index{page}{$src}{state}{$id}{$key}=$pagestate{$page}{$id}{$key};
 				}
@@ -1701,7 +1775,8 @@ sub saveindex () {
 	}
 
 	$index{state}={};
-	foreach my $id (@hookids) {
+	foreach my $id (@plugins) {
+		$index{state}{$id}={}; # used to detect disabled plugins
 		foreach my $key (keys %{$wikistate{$id}}) {
 			$index{state}{$id}{$key}=$wikistate{$id}{$key};
 		}
@@ -1721,12 +1796,15 @@ sub template_file ($) {
 	my $name=shift;
 	
 	my $tpage=($name =~ s/^\///) ? $name : "templates/$name";
+	my $template;
 	if ($name !~ /\.tmpl$/ && exists $pagesources{$tpage}) {
-		$tpage=$pagesources{$tpage};
+		$template=srcfile($pagesources{$tpage}, 1);
 		$name.=".tmpl";
 	}
+	else {
+		$template=srcfile($tpage, 1);
+	}
 
-	my $template=srcfile($tpage, 1);
 	if (defined $template) {
 		return $template, $tpage, 1 if wantarray;
 		return $template;
@@ -1754,12 +1832,14 @@ sub template_depends ($$;@) {
 	my $page=shift;
 	
 	my ($filename, $tpage, $untrusted)=template_file($name);
+	if (! defined $filename) {
+		error(sprintf(gettext("template %s not found"), $name))
+	}
+
 	if (defined $page && defined $tpage) {
 		add_depends($page, $tpage);
 	}
-
-	return unless defined $filename;
-
+	
 	my @opts=(
 		filter => sub {
 			my $text_ref = shift;
@@ -2387,10 +2467,16 @@ sub derel ($$) {
 	my $path=shift;
 	my $from=shift;
 
-	if ($path =~ m!^\./!) {
-		$from=~s#/?[^/]+$## if defined $from;
-		$path=~s#^\./##;
-		$path="$from/$path" if defined $from && length $from;
+	if ($path =~ m!^\.(/|$)!) {
+		if ($1) {
+			$from=~s#/?[^/]+$## if defined $from;
+			$path=~s#^\./##;
+			$path="$from/$path" if defined $from && length $from;
+		}
+		else {
+			$path = $from;
+			$path = "" unless defined $path;
+		}
 	}
 
 	return $path;
@@ -2424,13 +2510,16 @@ sub match_internal ($$;@) {
 sub match_page ($$;@) {
 	my $page=shift;
 	my $match=match_glob($page, shift, @_);
-	if ($match && ! (exists $IkiWiki::pagesources{$page}
-	    && defined IkiWiki::pagetype($IkiWiki::pagesources{$page}))) {
-		return IkiWiki::FailReason->new("$page is not a page");
-	}
-	else {
-		return $match;
+	if ($match) {
+		my $source=exists $IkiWiki::pagesources{$page} ?
+			$IkiWiki::pagesources{$page} :
+			$IkiWiki::delpagesources{$page};
+		my $type=defined $source ? IkiWiki::pagetype($source) : undef;
+		if (! defined $type) {	
+			return IkiWiki::FailReason->new("$page is not a page");
+		}
 	}
+	return $match;
 }
 
 sub match_link ($$;@) {