X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/3a5a030bac2c4e6f4c09f2470ff6109d9d78cccf..efcbeaa0:/IkiWiki.pm?ds=sidebyside

diff --git a/IkiWiki.pm b/IkiWiki.pm
index 83679243f..0d87242eb 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -358,11 +358,20 @@ sub getsetup () {
 		safe => 0, # paranoia
 		rebuild => 0,
 	},
+	libdirs => {
+		type => "string",
+		default => [],
+		example => ["$ENV{HOME}/.local/share/ikiwiki"],
+		description => "extra library and plugin directories",
+		advanced => 1,
+		safe => 0, # directory
+		rebuild => 0,
+	},
 	libdir => {
 		type => "string",
 		default => "",
 		example => "$ENV{HOME}/.ikiwiki/",
-		description => "extra library and plugin directory",
+		description => "extra library and plugin directory (searched after libdirs)",
 		advanced => 1,
 		safe => 0, # directory
 		rebuild => 0,
@@ -557,6 +566,25 @@ sub getsetup () {
 		safe => 1,
 		rebuild => 1,
 	},
+	deterministic => {
+		type => "boolean",
+		default => 0,
+		description => "try harder to produce deterministic output",
+		safe => 1,
+		rebuild => 1,
+		advanced => 1,
+	},
+}
+
+sub getlibdirs () {
+	my @libdirs;
+	if ($config{libdirs}) {
+		@libdirs = @{$config{libdirs}};
+	}
+	if (length $config{libdir}) {
+		push @libdirs, $config{libdir};
+	}
+	return @libdirs;
 }
 
 sub defaultconfig () {
@@ -599,9 +627,20 @@ sub checkconfig () {
 	if (defined $config{timezone} && length $config{timezone}) {
 		$ENV{TZ}=$config{timezone};
 	}
-	else {
+	elsif (defined $ENV{TZ} && length $ENV{TZ}) {
 		$config{timezone}=$ENV{TZ};
 	}
+	else {
+		eval q{use Config qw()};
+		error($@) if $@;
+
+		if ($Config::Config{d_gnulibc} && -e '/etc/localtime') {
+			$config{timezone}=$ENV{TZ}=':/etc/localtime';
+		}
+		else {
+			$config{timezone}=$ENV{TZ}='GMT';
+		}
+	}
 
 	if ($config{w3mmode}) {
 		eval q{use Cwd q{abs_path}};
@@ -701,14 +740,14 @@ sub checkconfig () {
 sub listplugins () {
 	my %ret;
 
-	foreach my $dir (@INC, $config{libdir}) {
+	foreach my $dir (@INC, getlibdirs()) {
 		next unless defined $dir && length $dir;
 		foreach my $file (glob("$dir/IkiWiki/Plugin/*.pm")) {
 			my ($plugin)=$file=~/.*\/(.*)\.pm$/;
 			$ret{$plugin}=1;
 		}
 	}
-	foreach my $dir ($config{libdir}, "$installdir/lib/ikiwiki") {
+	foreach my $dir (getlibdirs(), "$installdir/lib/ikiwiki") {
 		next unless defined $dir && length $dir;
 		foreach my $file (glob("$dir/plugins/*")) {
 			$ret{basename($file)}=1 if -x $file;
@@ -719,8 +758,8 @@ sub listplugins () {
 }
 
 sub loadplugins () {
-	if (defined $config{libdir} && length $config{libdir}) {
-		unshift @INC, possibly_foolish_untaint($config{libdir});
+	foreach my $dir (getlibdirs()) {
+		unshift @INC, possibly_foolish_untaint($dir);
 	}
 
 	foreach my $plugin (@{$config{default_plugins}}, @{$config{add_plugins}}) {
@@ -753,8 +792,8 @@ sub loadplugin ($;$) {
 
 	return if ! $force && grep { $_ eq $plugin} @{$config{disable_plugins}};
 
-	foreach my $dir (defined $config{libdir} ? possibly_foolish_untaint($config{libdir}) : undef,
-	                 "$installdir/lib/ikiwiki") {
+	foreach my $possiblytainteddir (getlibdirs(), "$installdir/lib/ikiwiki") {
+		my $dir = possibly_foolish_untaint($possiblytainteddir);
 		if (defined $dir && -x "$dir/plugins/$plugin") {
 			eval { require IkiWiki::Plugin::external };
 			if ($@) {
@@ -804,10 +843,9 @@ sub log_message ($$) {
 			$log_open=1;
 		}
 		eval {
-			# keep a copy to avoid editing the original config repeatedly
-			my $wikiname = $config{wikiname};
-			utf8::encode($wikiname);
-			Sys::Syslog::syslog($type, "[$wikiname] %s", join(" ", @_));
+			my $message = "[$config{wikiname}] ".join(" ", @_);
+			utf8::encode($message);
+			Sys::Syslog::syslog($type, "%s", $message);
 		};
                 if ($@) {
                     print STDERR "failed to syslog: $@" unless $log_failed;
@@ -1186,7 +1224,7 @@ sub cgiurl (@) {
 	}
 
 	return $cgiurl."?".
-		join("&", map $_."=".uri_escape_utf8($params{$_}), keys %params);
+		join("&", map $_."=".uri_escape_utf8($params{$_}), sort(keys %params));
 }
 
 sub cgiurl_abs (@) {
@@ -1194,6 +1232,19 @@ sub cgiurl_abs (@) {
 	URI->new_abs(cgiurl(@_), $config{cgiurl});
 }
 
+# Same as cgiurl_abs, but when the user connected using https,
+# will be a https url even if the cgiurl is normally a http url.
+#
+# This should be used for anything involving emailing a login link,
+# because a https session cookie will not be sent over http.
+sub cgiurl_abs_samescheme (@) {
+	my $u=cgiurl_abs(@_);
+	if (($ENV{HTTPS} && lc $ENV{HTTPS} ne "off")) {
+		$u=~s/^http:/https:/i;
+	}
+	return $u
+}
+
 sub baseurl (;$) {
 	my $page=shift;
 
@@ -1255,14 +1306,20 @@ sub formattime ($;$) {
 
 my $strftime_encoding;
 sub strftime_utf8 {
-	# strftime doesn't know about encodings, so make sure
+	# strftime didn't know about encodings in older Perl, so make sure
 	# its output is properly treated as utf8.
 	# Note that this does not handle utf-8 in the format string.
+	my $result = POSIX::strftime(@_);
+
+	if (Encode::is_utf8($result)) {
+		return $result;
+	}
+
 	($strftime_encoding) = POSIX::setlocale(&POSIX::LC_TIME) =~ m#\.([^@]+)#
 		unless defined $strftime_encoding;
 	$strftime_encoding
-		? Encode::decode($strftime_encoding, POSIX::strftime(@_))
-		: POSIX::strftime(@_);
+		? Encode::decode($strftime_encoding, $result)
+		: $result;
 }
 
 sub date_3339 ($) {
@@ -1399,6 +1456,7 @@ sub userpage ($) {
 	return length $config{userdir} ? "$config{userdir}/$user" : $user;
 }
 
+# Username to display for openid accounts.
 sub openiduser ($) {
 	my $user=shift;
 
@@ -1433,6 +1491,36 @@ sub openiduser ($) {
 	return;
 }
 
+# Username to display for emailauth accounts. 
+sub emailuser ($) {
+	my $user=shift;
+	if (defined $user && $user =~ m/(.+)@/) {
+		my $nick=$1;
+		# remove any characters from not allowed in wiki files
+		# support use w/o %config set
+		my $chars = defined $config{wiki_file_chars} ? $config{wiki_file_chars} : "-[:alnum:]+/.:_";
+		$nick=~s/[^$chars]/_/g;
+		return $nick;
+	}
+	return;
+}
+
+# Some user information should not be exposed in commit metadata, etc.
+# This generates a cloaked form of such information.
+sub cloak ($) {
+	my $user=shift;
+	# cloak email address using http://xmlns.com/foaf/spec/#term_mbox_sha1sum
+	if ($user=~m/(.+)@/) {
+		my $nick=$1;
+		eval q{use Digest::SHA};
+		return $user if $@;
+		return $nick.'@'.Digest::SHA::sha1_hex("mailto:$user");
+	}
+	else {
+		return $user;
+	}
+}
+
 sub htmlize ($$$$) {
 	my $page=shift;
 	my $destpage=shift;
@@ -1578,6 +1666,8 @@ sub preprocess ($$$;$$) {
 				if ($@) {
 					my $error=$@;
 					chomp $error;
+					eval q{use HTML::Entities};
+					$error = encode_entities($error);
 				 	$ret="[[!$command <span class=\"error\">".
 						gettext("Error").": $error"."</span>]]";
 				}
@@ -1755,7 +1845,7 @@ sub check_canchange (@) {
 		$file=possibly_foolish_untaint($file);
 		if (! defined $file || ! length $file ||
 		    file_pruned($file)) {
-			error(gettext("bad file name %s"), $file);
+			error(sprintf(gettext("bad file name %s"), $file));
 		}
 
 		my $type=pagetype($file);