add authentication and multiple database support master
authorJulien Moutinho <julm+ikiwiki+search@autogeree.net>
Sun, 30 Mar 2014 20:39:05 +0000 (22:39 +0200)
committerJulien Moutinho <julm+ikiwiki+search@autogeree.net>
Sun, 30 Mar 2014 20:57:46 +0000 (22:57 +0200)
search.pm
templates/searchform.tmpl
templates/searchquery.tmpl

index 24b16fe..c42ad68 100644 (file)
--- a/search.pm
+++ b/search.pm
@@ -13,6 +13,7 @@ sub import {
        hook(type => "indexhtml", id => "search", call => \&indexhtml);
        hook(type => "delete", id => "search", call => \&delete);
        hook(type => "cgi", id => "search", call => \&cgi);
+       hook(type => "sessioncgi", id => "search", call => \&sessioncgi);
        hook(type => "disable", id => "search", call => \&disable);
        hook(type => "needsbuild", id => "search", call => \&needsbuild);
                
@@ -53,28 +54,56 @@ sub checkconfig () {
                $config{omega_cgi}="/usr/lib/cgi-bin/omega/omega";
        }
 
+       # Parsing "search"
+       my @search = ();
+       if (defined $config{search_db}
+        and   (ref($config{search_db}) eq "ARRAY")) {
+               my $length = $#{$config{search_db}}+1;
+               my $columns = 4;
+               if (($length % $columns) != 0) {
+                       error("config{search_db} length($length) must be a multiple of $columns.");
+                }
+               for(my $row = 0; $row < $length/$columns; $row++) {
+                       my ($db, $auth, $dest, $index)
+                        = @{$config{search_db}}[($columns*$row+0)..($columns*($row+1))];
+                       my $auth_yesno = IkiWiki::yesno($auth);
+                       push @search,
+                        { db    => $db
+                        , auth  => $auth_yesno
+                        , dest  => $dest
+                        , index => $index
+                        };
+                }
+        }
+       $config{search} = \@search;
+
        # This is a mass dependency, so if the search form template
        # changes, every page is rebuilt.
        add_depends("", "templates/searchform.tmpl");
 }
 
-my $form;
+my $form = {};
 sub pagetemplate (@) {
        my %params=@_;
        my $page=$params{page};
        my $template=$params{template};
 
+       my @search = grep {
+               pagespec_match($page, $_->{dest})
+        } @{$config{search}};
+
        # Add search box to page header.
-       if ($template->query(name => "searchform")) {
-               if (! defined $form) {
+       if (@search > 0 and $template->query(name => "searchform")) {
+               my $form_id = join(' ', (map {$_->{db}} @search));
+               if (! defined $form->{$form_id}) {
                        my $searchform = template("searchform.tmpl", blind_cache => 1);
                        $searchform->param(searchaction => IkiWiki::cgiurl());
+                       $searchform->param(searchdb => [map {{db=>$_->{db}}} @search]);
                        $searchform->param(html5 => $config{html5});
-                       $form=$searchform->output;
-               }
-
-               $template->param(searchform => $form);
-       }
+                       $form->{$form_id}=$searchform->output;
+                }
+               $template->param(searchform => $form->{$form_id});
+        }
 }
 
 my $scrubber;
@@ -89,8 +118,12 @@ sub indexhtml (@) {
        # A unique pageterm is used to identify the document for a page.
        my $pageterm=pageterm($params{page});
        return unless defined $pageterm;
+       my $search = (grep {
+               pagespec_match($params{page}, $_->{index})
+        } @{$config{search}})[0];
+       return unless defined $search;
        
-       my $db=xapiandb();
+       my $db=xapiandb($search->{db});
        my $doc=Search::Xapian::Document->new();
        my $caption=pagetitle($params{page});
        my $title;
@@ -176,11 +209,14 @@ sub indexhtml (@) {
 sub delete (@) {
        return if $config{google_search};
 
-       my $db=xapiandb();
        foreach my $page (@_) {
                my $pageterm=pageterm(pagename($page));
-               $db->delete_document_by_term($pageterm) if defined $pageterm;
-       }
+               foreach my $search (@{$config{search}}) {
+                       my $db=xapiandb($search->{db});
+                       $db->delete_document_by_term($pageterm)
+                               if defined $pageterm;
+                }
+        }
 }
 
 sub cgi ($) {
@@ -190,18 +226,66 @@ sub cgi ($) {
                if ($config{google_search}) {
                        print $cgi->redirect("https://www.google.com/search?sitesearch=$config{url}&q=".$cgi->param('P'));
                        exit 0;
-               }
+                }
                else {
-                       # only works for GET requests
-                       chdir("$config{wikistatedir}/xapian") || error("chdir: $!");
-                       $ENV{OMEGA_CONFIG_FILE}="./omega.conf";
-                       $ENV{CGIURL}=IkiWiki::cgiurl();
-                       IkiWiki::loadindex();
-                       $ENV{HELPLINK}=htmllink("", "", "ikiwiki/searching",
-                               noimageinline => 1, linktext => "Help");
-                       exec($config{omega_cgi}) || error("$config{omega_cgi} failed: $!");
-               }
-       }
+                       if (defined $cgi->param('DB')) {
+                               my @db = map {split('/', $_)} ($cgi->param('DB'));
+                               my @search = map {
+                                       my $db = $_;
+                                       grep { $db eq $_->{db} } @{$config{search}};
+                                } @db;
+                               my $auth_needed = 0;
+                               foreach (@search) {
+                                       if ($_->{auth}) {
+                                               $auth_needed = 1;
+                                               last;
+                                        }
+                                }
+                               if (not $auth_needed) {
+                                       # only works for GET requests
+                                       chdir("$config{wikistatedir}/xapian") || error("chdir: $!");
+                                       $ENV{OMEGA_CONFIG_FILE}="./omega.conf";
+                                       $ENV{CGIURL}=IkiWiki::cgiurl();
+                                       IkiWiki::loadindex();
+                                       $ENV{HELPLINK}=htmllink("", "", "ikiwiki/searching",
+                                               noimageinline => 1, linktext => "Help");
+                                       exec($config{omega_cgi}) || error("$config{omega_cgi} failed: $!");
+                                }
+                        }
+                }
+        }
+}
+
+sub sessioncgi ($) {
+       my $cgi=shift;
+       my $session=shift;
+       
+       if ($cgi->param('do') eq 'search') {
+               eval q{use CGI qw(-oldstyle_urls)};
+                       # NOTE: ampersands separators are required for xapian-omega
+               IkiWiki::needsignin($cgi, $session);
+               IkiWiki::cgi_savesession($session);
+               my $headers;
+               do {
+                       open(my $STDOUT_diverted, '>', \$headers) or die;
+                       my $STDOUT_original = select $STDOUT_diverted;
+                       IkiWiki::printheader($session);
+                       select $STDOUT_original;
+                       close $STDOUT_diverted;
+                       local $/ = "\r\n";
+                       chomp $headers;
+                };
+               print $headers;
+               chdir("$config{wikistatedir}/xapian") || error("chdir: $!");
+               $ENV{OMEGA_CONFIG_FILE}="./omega.conf";
+               $ENV{CGIURL}=IkiWiki::cgiurl();
+               $ENV{REQUEST_METHOD}='GET';
+               $ENV{QUERY_STRING}=$cgi->query_string();
+               IkiWiki::loadindex();
+               $ENV{HELPLINK}=htmllink("", "", "ikiwiki/searching",
+                       noimageinline => 1, linktext => "Help");
+               exec($config{omega_cgi}) || error("$config{omega_cgi} failed: $!");
+        }
 }
 
 sub pageterm ($) {
@@ -226,18 +310,19 @@ sub pageterm ($) {
        }
 }
 
-my $db;
-sub xapiandb () {
-       if (! defined $db) {
+my $db = {};
+sub xapiandb ($) {
+       my ($dbname) = @_;
+       if (! defined $db->{$dbname}) {
                eval q{
                        use Search::Xapian;
                        use Search::Xapian::WritableDatabase;
                };
                error($@) if $@;
-               $db=Search::Xapian::WritableDatabase->new($config{wikistatedir}."/xapian/default",
+               $db->{$dbname}=Search::Xapian::WritableDatabase->new($config{wikistatedir}."/xapian/".$dbname,
                        Search::Xapian::DB_CREATE_OR_OPEN());
        }
-       return $db;
+       return $db->{$dbname};
 }
 
 {
index cb65d12..f8baf55 100644 (file)
@@ -1,6 +1,12 @@
 <form method="get" action="<TMPL_VAR SEARCHACTION>" id="searchform">
 <div>
+<input type="hidden" id="searchdo" name="do" value="search" />
+<TMPL_LOOP NAME="SEARCHDB">
+<input type="hidden" id="searchdb" name="DB" value="<TMPL_VAR DB>" />
+</TMPL_LOOP>
 <input type="text" id="searchbox" name="P" value="" size="16"
-<TMPL_IF HTML5>placeholder="search"</TMPL_IF> />
+<TMPL_IF HTML5>placeholder="search <TMPL_LOOP NAME="SEARCHDB"
+><TMPL_UNLESS NAME="__first__">, </TMPL_UNLESS
+><TMPL_VAR DB></TMPL_LOOP>"</TMPL_IF> />
 </div>
 </form>
index 15bc78e..8c59f97 100644 (file)
@@ -34,6 +34,7 @@ $def{NEXT,$if{$ne{$last,$msize},<INPUT TYPE=submit NAME="&gt;" VALUE="Next">}}
 <FORM NAME=P METHOD=GET 
 ACTION="$html{$env{CGIURL}}" TARGET="_top">
 <div style="text-align:center">
+<INPUT type="hidden" id="searchdo" name="do" value="search" />
 <INPUT NAME=P VALUE="$html{$query}" SIZE=65>
 <INPUT TYPE=SUBMIT VALUE="Search">
 $env{HELPLINK}