]> sipb.mit.edu Git - ikiwiki.git/blobdiff - ikiwiki
add support for generating per-page rss feeds
[ikiwiki.git] / ikiwiki
diff --git a/ikiwiki b/ikiwiki
index b59aa8c8fa6c1cdfbe3504f01dd2b18c15f5b863..5c708919a9288c460c1094adf367b27e2f8777f8 100755 (executable)
--- a/ikiwiki
+++ b/ikiwiki
 #!/usr/bin/perl -T
-
 $ENV{PATH}="/usr/local/bin:/usr/bin:/bin";
 
-use lib '.'; # For use without installation, removed by Makefile.
-
 package IkiWiki;
 use warnings;
 use strict;
-use Memoize;
 use File::Spec;
 use HTML::Template;
+use lib '.'; # For use without installation, removed by Makefile.
 
 use vars qw{%config %links %oldlinks %oldpagemtime %renderedfiles %pagesources};
 
-# 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_.:\/+]+$)/,
-       verbose => 0,
-       wikiname => "wiki",
-       default_pageext => ".mdwn",
-       cgi => 0,
-       svn => 1,
-       url => '',
-       cgiurl => '',
-       historyurl => '',
-       diffurl => '',
-       anonok => 0,
-       rebuild => 0,
-       wrapper => undef,
-       wrappermode => undef,
-       srcdir => undef,
-       destdir => undef,
-       templatedir => "/usr/share/ikiwiki/templates",
-       setup => undef,
-       adminuser => undef,
-); #}}}
-
-# option parsing #{{{
-if (! exists $ENV{WRAPPED_OPTIONS}) {
-       eval q{use Getopt::Long};
-       GetOptions(
-               "setup|s=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},
-               "diffurl=s" => \$config{diffurl},
-               "exclude=s@" => sub {
-                       $config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$_[1]/;
-               },
-               "adminuser=s@" => sub { push @{$config{adminuser}}, $_[1] },
-               "templatedir=s" => sub { $config{templatedir}=possibly_foolish_untaint($_[1]) },
-       ) || usage();
-
-       if (! $config{setup}) {
-               usage() unless @ARGV == 2;
-               $config{srcdir} = possibly_foolish_untaint(shift);
-               $config{destdir} = possibly_foolish_untaint(shift);
-               checkoptions();
-       }
-}
-else {
-       # wrapper passes a full config structure in the environment
-       # variable
-       eval possibly_foolish_untaint($ENV{WRAPPED_OPTIONS});
-       checkoptions();
-}
-#}}}
-
-sub checkoptions { #{{{
+sub usage () { #{{{
+       die "usage: ikiwiki [options] source dest\n";
+} #}}}
+
+sub getconfig () { #{{{
+       if (! exists $ENV{WRAPPED_OPTIONS}) {
+               %config=(
+                       wiki_file_prune_regexp => qr{((^|/).svn/|\.\.|^\.|\/\.|\.html?$)},
+                       wiki_link_regexp => qr/\[\[([^\s\]]+)\]\]/,
+                       wiki_file_regexp => qr/(^[-A-Za-z0-9_.\&;:\/+]+$)/,
+                       verbose => 0,
+                       wikiname => "wiki",
+                       default_pageext => ".mdwn",
+                       cgi => 0,
+                       svn => 1,
+                       url => '',
+                       cgiurl => '',
+                       historyurl => '',
+                       diffurl => '',
+                       anonok => 0,
+                       rss => 0,
+                       rebuild => 0,
+                       wrapper => undef,
+                       wrappermode => undef,
+                       srcdir => undef,
+                       destdir => undef,
+                       templatedir => "/usr/share/ikiwiki/templates",
+                       setup => undef,
+                       adminuser => undef,
+               );
+
+               eval q{use Getopt::Long};
+               GetOptions(
+                       "setup|s=s" => \$config{setup},
+                       "wikiname=s" => \$config{wikiname},
+                       "verbose|v!" => \$config{verbose},
+                       "rebuild!" => \$config{rebuild},
+                       "wrappermode=i" => \$config{wrappermode},
+                       "svn!" => \$config{svn},
+                       "anonok!" => \$config{anonok},
+                       "rss!" => \$config{rss},
+                       "cgi!" => \$config{cgi},
+                       "url=s" => \$config{url},
+                       "cgiurl=s" => \$config{cgiurl},
+                       "historyurl=s" => \$config{historyurl},
+                       "diffurl=s" => \$config{diffurl},
+                       "exclude=s@" => sub {
+                               $config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$_[1]/;
+                       },
+                       "adminuser=s@" => sub {
+                               push @{$config{adminuser}}, $_[1]
+                       },
+                       "templatedir=s" => sub {
+                               $config{templatedir}=possibly_foolish_untaint($_[1])
+                       },
+                       "wrapper:s" => sub {
+                               $config{wrapper}=$_[1] ? $_[1] : "ikiwiki-wrap"
+                       },
+               ) || usage();
+
+               if (! $config{setup}) {
+                       usage() unless @ARGV == 2;
+                       $config{srcdir} = possibly_foolish_untaint(shift @ARGV);
+                       $config{destdir} = possibly_foolish_untaint(shift @ARGV);
+                       checkconfig();
+               }
+       }
+       else {
+               # wrapper passes a full config structure in the environment
+               # variable
+               eval possibly_foolish_untaint($ENV{WRAPPED_OPTIONS});
+               checkconfig();
+       }
+} #}}}
+
+sub checkconfig () { #{{{
        if ($config{cgi} && ! length $config{url}) {
-               error("Must specify url to wiki with --url when using --cgi");
+               error("Must specify url to wiki with --url when using --cgi\n");
+       }
+       if ($config{rss} && ! length $config{url}) {
+               error("Must specify url to wiki with --url when using --rss\n");
        }
        
        $config{wikistatedir}="$config{srcdir}/.ikiwiki"
                unless exists $config{wikistatedir};
        
        if ($config{svn}) {
-               require IkiWiki::RCS::SVN;
+               require IkiWiki::Rcs::SVN;
                $config{rcs}=1;
        }
        else {
-               require IkiWiki::RCS::Stub;
+               require IkiWiki::Rcs::Stub;
                $config{rcs}=0;
        }
 } #}}}
 
-sub usage { #{{{
-       die "usage: ikiwiki [options] source dest\n";
-} #}}}
-
-sub error { #{{{
+sub error ($) { #{{{
        if ($config{cgi}) {
                print "Content-type: text/html\n\n";
                print misctemplate("Error", "<p>Error: @_</p>");
@@ -107,6 +114,12 @@ sub error { #{{{
        die @_;
 } #}}}
 
+sub possibly_foolish_untaint ($) { #{{{
+       my $tainted=shift;
+       my ($untainted)=$tainted=~/(.*)/;
+       return $untainted;
+} #}}}
+
 sub debug ($) { #{{{
        return unless $config{verbose};
        if (! $config{cgi}) {
@@ -117,12 +130,6 @@ sub debug ($) { #{{{
        }
 } #}}}
 
-sub possibly_foolish_untaint { #{{{
-       my $tainted=shift;
-       my ($untainted)=$tainted=~/(.*)/;
-       return $untainted;
-} #}}}
-
 sub basename ($) { #{{{
        my $file=shift;
 
@@ -232,7 +239,14 @@ sub isinlinableimage ($) { #{{{
        $file=~/\.(png|gif|jpg|jpeg)$/;
 } #}}}
 
-sub htmllink { #{{{
+sub pagetitle ($) { #{{{
+       my $page=shift;
+       $page=~s/__(\d+)__/&#$1;/g;
+       $page=~y/_/ /;
+       return $page;
+} #}}}
+
+sub htmllink ($$;$$) { #{{{
        my $page=shift;
        my $link=shift;
        my $noimageinline=shift; # don't turn links into inline html images
@@ -246,7 +260,9 @@ sub htmllink { #{{{
                $bestlink="$page/".lc($link);
        }
 
-       return $link if length $bestlink && $page eq $bestlink;
+       my $linktext=pagetitle($link);
+       
+       return $linktext if length $bestlink && $page eq $bestlink;
        
        # TODO BUG: %renderedfiles may not have it, if the linked to page
        # was also added and isn't yet rendered! Note that this bug is
@@ -256,7 +272,7 @@ sub htmllink { #{{{
                $bestlink=htmlpage($bestlink);
        }
        if (! grep { $_ eq $bestlink } values %renderedfiles) {
-               return "<a href=\"$config{cgiurl}?do=create&page=$link&from=$page\">?</a>$link"
+               return "<a href=\"$config{cgiurl}?do=create&page=$link&from=$page\">?</a>$linktext"
        }
        
        $bestlink=File::Spec->abs2rel($bestlink, dirname($page));
@@ -264,7 +280,7 @@ sub htmllink { #{{{
        if (! $noimageinline && isinlinableimage($bestlink)) {
                return "<img src=\"$bestlink\">";
        }
-       return "<a href=\"$bestlink\">$link</a>";
+       return "<a href=\"$bestlink\">$linktext</a>";
 } #}}}
 
 sub indexlink () { #{{{
@@ -425,28 +441,31 @@ sub globlist_match ($$) { #{{{
        return 0;
 } #}}}
 
-# main {{{
-memoize('pagename');
-memoize('bestlink');
-if ($config{setup}) {
-       require IkiWiki::Setup;
-       setup();
-}
-lockwiki();
-if ($config{wrapper}) {
-       require IkiWiki::Wrapper;
-       gen_wrapper();
-       exit;
-}
-loadindex() unless $config{rebuild};
-if ($config{cgi}) {
-       require IkiWiki::CGI;
-       cgi();
-}
-else {
-       require IkiWiki::Render;
-       rcs_update();
-       refresh();
-       saveindex();
-}
-#}}}
+sub main () { #{{{
+       getconfig();
+       
+       if ($config{setup}) {
+               require IkiWiki::Setup;
+               setup();
+       }
+       elsif ($config{wrapper}) {
+               lockwiki();
+               require IkiWiki::Wrapper;
+               gen_wrapper();
+       }
+       elsif ($config{cgi}) {
+               lockwiki();
+               require IkiWiki::CGI;
+               cgi();
+       }
+       else {
+               lockwiki();
+               loadindex() unless $config{rebuild};
+               require IkiWiki::Render;
+               rcs_update();
+               refresh();
+               saveindex();
+       }
+} #}}}
+
+main;