Edit: /usr/share/usermin/man/search.cgi (11608B)
#!/usr/bin/perl
# search.cgi
# Search for manual pages, and display a list of matches or an exact page
require './man-lib.pl';
use Config;
&ReadParse();
$in{'for'} || &error($text{'search_efor'});
@for = split(/\s+/, $in{'for'});
@howto = split(/\s+/, $config{'howto_dir'});
@doc = split(/\s+/, $config{'doc_dir'});
foreach $s (split(/\0/, $in{'section'})) {
if ($s =~ /^([^:]+):(.*)/) {
$section{$1}++;
$opts{$1} = $2;
}
else {
$section{$s}++;
}
}
if ($in{'check'} && $config{'check'}) {
@check = split(/\s+/, $config{'check'});
foreach $s (keys %section) {
delete($section{$s}) if (&indexof($s, @check) < 0);
}
}
if ($section{'doc'}) {
# Look in the system documentation directory (usually /usr/doc)
foreach $d (@doc) {
push(@rv, map { [ $text{'search_doc'},
"view_doc.cgi?file=".&urlize($_->[0]),
substr($_->[0], length($d)+1),
$_->[1], 1 ] }
&find_contents($d, \@for,
$howto[0], 1, $in{'exact'}));
}
}
if ($section{'custom'}) {
# Look in the custom documentation directory
push(@rv, map { [ $text{'search_custom'},
"view_doc.cgi?file=".&urlize($_->[0]),
substr($_->[0], length($config{'custom_dir'})+1),
$_->[1], 1 ] }
&find_contents($config{'custom_dir'}, \@for,
$howto[0], 1, $in{'exact'}));
}
if ($section{'howto'}) {
# Look in the HOWTO directory
foreach $h (@howto) {
push(@rv, map { [ $text{'search_howto'},
"view_howto.cgi?file=".&urlize($_->[0]),
$_->[2], $_->[1], 2 ] }
&find_contents($h, \@for, undef, 0, $in{'exact'}));
}
@rv = grep { $_->[2] !~ /^index/i } @rv;
}
if ($section{'kernel'}) {
# Look in the linux kernel Documentation directory
push(@rv, map { [ $text{'search_kernel'},
"view_kernel.cgi?file=".&urlize($_->[0]),
substr($_->[0], length($config{'kernel_dir'})+1),
$_->[1], 1 ] }
&find_contents($config{'kernel_dir'}, \@for,
undef, 1, $in{'exact'}));
}
if ($section{'kde'}) {
# Look in the KDE documentation directory
push(@rv, map { [ $text{'search_kde'},
"view_kde.cgi?file=".&urlize($_->[0]),
substr($_->[0], length($config{'kde_dir'})+1),
$_->[1], 1 ] }
&find_contents($config{'kde_dir'}, \@for,
undef, 1, $in{'exact'}));
}
if ($section{'perl'}) {
if ($in{'exact'}) {
# Check for an exact module name match
local @f = $in{'and'} ? ( $for[0] ) : @for;
foreach $f (@f) {
chop($out = &backquote_command("$perl_doc -l ".quotemeta($f)." 2>/dev/null", 1));
if ($out) {
local $doc = &parse_perl_module($out);
$doc->{'name'} =~ s/^\s*(\S+)\s+-\s+//;
push(@rv, [ $text{'search_perl'},
"view_perl.cgi?mod=$f",
$f, $doc->{'name'}, 1 ]);
}
}
}
else {
# Search the text of all perl modules
foreach $d ($Config{'sitelib'}, $Config{'privlib'}) {
&open_execute_command(FIND, "find $d -name '*.pm' -print", 1, 1);
while($path =
) {
chop($path);
local $doc = &parse_perl_module($path);
local ($any = 0, $all = 1);
foreach $f (@for) {
if ($doc->{'name'} !~ /$f/i &&
$doc->{'description'} !~ /$f/i) {
$all = 0;
}
else {
$any = 1;
}
}
next if (!$all && $in{'and'} || !$any);
$doc->{'name'} =~ s/^\s*(\S+)\s+-\s+//;
local $modfile =
&backquote_command("$perl_doc -l ".quotemeta($doc->{'package'})." 2>/dev/null", 1);
if ($doc->{'package'} && $modfile) {
push(@rv, [ $text{'search_perl'},
"view_perl.cgi?mod=$doc->{'package'}",
$doc->{'package'},
&html_escape($doc->{'name'}),
1 ]);
}
}
close(FIND);
}
}
}
if ($section{'help'}) {
# Look in the webmin module help pages
opendir(DIR, $root_directory);
foreach my $m (readdir(DIR)) {
# Is this a module with help
local $dir = "$root_directory/$m/help";
next if (!-d $dir || $m =~ /^\./ || -l "$root_directory/$m");
local %minfo = &get_module_info($m);
next if (!%minfo || !&check_os_support(\%minfo));
# Check the help pages
local @pfx;
opendir(DIR2, $dir);
while($f = readdir(DIR2)) {
push(@pfx, $1) if ($f =~ /^([^\.]+)\.html$/);
}
closedir(DIR2);
HELP: foreach $p (&unique(@pfx)) {
local $file = &help_file($m, $p);
local $help = &read_file_contents($file);
if ($help =~ /([^<]+)<\/header>/) {
$header = $1;
}
else { next; }
$help =~ s//inchelp($1, $m)/ge;
$help =~ s/<[^>]+>//g;
local $matches = 0;
if ($in{'exact'}) {
# Just check header
foreach $f (@for) {
$matches++ if ($header =~ /\Q$f\E/i);
}
}
else {
# Check entire body
foreach $f (@for) {
$matches++ if ($help =~ /\Q$f\E/i);
}
}
if (($in{'and'} && $matches == @for) ||
(!$in{'and'} && $matches)) {
push(@rv, [ $text{'search_help'},
"/help.cgi/$m/$p?x=1",
"$m/$p",
&html_escape($header),
2 ]);
}
}
}
}
if ($section{'man'}) {
# Look in manual pages (searches are never exact)
$cmd = $config{'search_cmd'};
map { s/\\/\\\\/g; s/'/\\'/g; } @for;
if ($in{'and'}) {
local $qm = quotemeta($for[0]);
$cmd =~ s/PAGE/$qm/;
}
else {
local $fors = join(" ", map { quotemeta($_) } @for);
$cmd =~ s/PAGE/$fors/;
}
&set_manpath($opts{'man'});
&open_execute_command(MAN, $cmd, 1, 1);
while() {
$got .= $_;
if (/(([^,\s]+).*)\s*\((\S+)\)\s+-\s+(.*)/ &&
!$done{$2,$3}++) {
local ($page, $sect, $desc) = ($1, $3, $4);
if ($page =~ /^(\S+)\s*\[(.+)\]/) {
$page = "$1 $2";
}
local @pp = split(/[\s+,]/, $page);
map { s/\((\S+)\)//; } @pp;
# Keywords must be page name or desc
local ($any = 0, $all = 1, $exact);
foreach $f (@for) {
if ($desc !~ /$f/i && $page !~ /$f/i &&
&indexof($f, @pp) < 0) {
$all = 0;
}
else {
$any = 1;
}
$exact++ if (&indexof($f, @pp) >= 0);
}
next if (!$all && $in{'and'} || !$any);
push(@rv, [ $text{'search_man'},
"view_man.cgi?page=$pp[0]&sec=$3&opts=".
$opts{'man'}, "$pp[0] ($sect)",
&html_escape($desc),
$exact ? 4 : 3 ]);
}
}
close(MAN);
}
if ($section{'google'}) {
# Try to call the Google search engine, once for general results and
# once for doxfer
local %doneurl;
foreach my $host ("", "host:doxfer.webmin.com") {
local ($grv, $error);
local $j = $in{'and'} ? ' and ' : ' or ';
&http_download($google_host, $google_port, "$google_page?q=".
&urlize(join($j, @for)." ".$host).
"&sourceid=webmin&num=20",
\$grv, \$error);
if (!$error) {
# Parse the results
while($grv =~ /(]*>|