package OnSearch::UI; #$Id: UI.pm,v 1.26 2005/08/16 05:34:03 kiesling Exp $ use strict; use warnings; use Carp; use Socket; use Storable qw/fd_retrieve/; use Fcntl qw(:DEFAULT :flock); use OnSearch; use OnSearch::Utils; use PerlIO::OnSearchIO; my $VERSION='$Revision: 1.26 $'; require Exporter; require DynaLoader; my (@ISA, @EXPORT_OK); @ISA = qw(Exporter DynaLoader); @EXPORT_OK = (qw/DESTROY/); ### ### Some character entity constants. ### my $GT_ent = '>'; my $LT_ent = '<'; =head1 NAME OnSearch::UI.pm - User interface library for OnSearch. =head1 DESCRIPTION OnSearch::UI provides an object oriented user interface for the OnSearch search engine and page templates for the application's dynamic HTML content. =head1 EXPORTS =head2 DESTROY (I) Perl calls DESTROY when deleting unused OnSearch::UI objects. =head1 METHODS The UI.pm methods are listed and described below. =cut ### ### These are the three basic types of matches. See the comments ### in Search.pm. ### my @matchtypes = (qw/any all exact/); =head2 $ui -> parbreak (); Template for a paragraph break. $ui -> parbreak -> wprint; =cut sub parbreak { my $self = shift; $self -> {text} = '

'; return $self; } =head2 $ui -> input_form (I, I); OnSearch search page template. The arguments are hash references of user preferences. =cut sub input_form { my $self = shift; my $prefs = $_[0]; my $vol_prefs = $_[1]; my ($case_opt, $nocase_opt, $matchany_opt, $matchall_opt, $partword_opt,$matchexact_opt, $completeword_opt, $pagesize_opt, %dfmatch, $nresults_opt, %volumes, $OnSearchDir); $case_opt = $nocase_opt = ''; $matchany_opt = $matchall_opt = $matchexact_opt = ''; $partword_opt = $completeword_opt = ''; my $c = OnSearch::AppConfig -> new; %volumes = $c -> Volumes; $OnSearchDir = $c -> str (qw/OnSearchDir/); $self -> volume_info (\%volumes, $vol_prefs); my $volinfo = $self -> {text}; if ($prefs !~ /defaults|none/) { my %prefs = $c->parse_prefs ($prefs); (($prefs{matchcase} =~ /yes/) ? $case_opt = 'checked' : $nocase_opt = 'checked'); $partword_opt = ($prefs{partword} =~ /yes/) ? 'checked' : ''; $completeword_opt = ($prefs{partword} =~ /no/) ? 'checked' : ''; foreach (@matchtypes) { $dfmatch{$_} = (m"$prefs{matchtype}" ? 'checked' : ''); } $pagesize_opt = $prefs{pagesize}; $nresults_opt = $prefs{nresults}; } else { ### ### These are the default search options. ### $case_opt = 'checked'; $dfmatch{$_} = '' foreach (@matchtypes); $dfmatch{any} = 'checked'; $completeword_opt = 'checked'; $pagesize_opt = $c->str ('PageSize'); $nresults_opt = $c->str ('ResultsPerFile'); } $self -> {text} =<
Enter a word or phrase to search for.


$volinfo


END_OF_INPUT_FORM return $self; } =head2 $ui -> process_error (I); User warning template. When called from OnSearch::browser_warn(), also logs the message. $ui -> process_error ($message) -> wprint; =cut sub process_error { my $self = $_[0]; my $msg = $_[1]; $self -> {text} = qq{ OnSearch Error


OnSearch Error

OnSearch encountered the following error:

$msg

For help with this error, contact $ENV{SERVER_ADMIN}.
$ENV{SERVER_SIGNATURE}


}; return $self; } =head2 $ui -> brief_warning (I); Template that formats a warning about a user errror. To print the warning to the browser, use the following method calls. $ui -> brief_warning ($message) -> wprint; =cut sub brief_warning { my $self = $_[0]; my $msg = $_[1]; $self -> {text} = qq{ OnSearch Warning


Warning

$msg


}; return $self; } =head2 $ui -> header_css (I); HTTP header template that includes a link for an external style sheet named, "styles.css." =cut sub header_css { my $self = $_[0]; my $title = $_[1]; $self -> {text} =<<END_OF_TEMPLATE; Content-Type: text/html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"> <head><title>$title END_OF_TEMPLATE return $self; } =head2 $ui -> navbar_map (); Graphical navbar image map template. =cut sub navbar_map { my $self = shift; my $c = OnSearch::AppConfig -> new; my $OnSearchDir = $c -> str (qw/OnSearchDir/); $self -> {text} =< END_OF_MAP return $self; } =head2 $ui -> header_back (); HTTP header template the Web browser to the previous page. =cut ### ### TO DO - Try to make this work with internet explorer. ### sub header_back { my $self = shift; $self -> {text} =< OnSearch $ENV{HTTP_REFERER} END_OF_TEMPLATE return $self; } =head2 $ui -> navbar (); Template for graphical and text-mode navigation bars. =cut sub navbar { my $self = shift; my $c = OnSearch::AppConfig -> new; my $OnSearchDir = $c -> str (qw/OnSearchDir/); if ($ENV{HTTP_USER_AGENT} =~ /lynx/i) { $self -> {text} =<
[Search] [Archive] [Filters] [Admin] [About]
END_OF_TEMPLATE return $self; } $self -> {text} =<

NavBar
END_OF_TEMPLATE return $self; } =head2 $ui -> javascripts (); Javascript function HTML template. =cut sub javascripts { my $self = shift; $self -> {text} =< function validate () { if (document.inputform.searchterm.value == '') { document.inputform.action = document.URL; ErrorWindow ('searchterm'); } } function ErrorWindow (p) { window.open ('error.cgi?'+p, 'Error', 'scrollbars=no,menubar=no,width=300,height=180') } function CloseErrorWindow () { window.close () } END_OF_TEMPLATE return $self; } =head2 $ui -> error_dialog (I); Template for a HTTP header that uses Javascript to pop up an error dialog box. =cut sub error_dialog { my $self = shift; my $error = $_[0]; $self->{text} = < OnSearch END_OF_TEXT return $self; } =head2 $ui -> critical_error_form (I); Template for a critical error form that is compatible with all Web browsers. =cut sub critical_error_form { my $self = shift; my $text = $_[0]; $self -> {text} =<

END_OF_TEMPLATE return $self; } =head2 $ui -> results_form (I, I, I) Template to format the results of a matching document. =cut sub results_form { my $self = shift; my $rlist = $_[0]; my ($ext, $searchterm, $doc_url, $r, $regex, $cfg, $OnSearchDir); $cfg = OnSearch::AppConfig -> new; $OnSearchDir = $cfg -> str (qw/OnSearchDir/); $ext = ++($self -> {ext}); $searchterm = $self -> {searchterm}; $doc_url = $rlist->[0]; $regex = $self->{q}->{displayregex}; $self -> {text} =< EOM $self -> {text} .= qq| |; shift @{$rlist}; foreach $r (@{$rlist}) { $r =~ s"\<"<"g; $r =~ s"\>">"g; $r =~ s/\n/ /g; $r =~ s"($regex)"$1<\/strong>"g; $self -> {text} .= qq|\n|; } $self -> {text} .= qq|
View
$r
|; return $self; } =head2 $ui -> results_header (); Template for the page numbers that appear at the top of each page of results. For page number and results counts, and formatting the results header and results footer, UI.pm uses _queue_indexes to calculate the indexes. =cut sub results_header { my $self = $_[0]; my $id; $id = $self -> {q} -> {id}; my ($s, $us); my ($first, $last, $nextp, $prevp) = $self -> _queue_indexes (); my $total = $#{$self->{r}} + 1; $self -> {text} =<

$LT_ent$LT_ent  EOM my $i = ($nextp > 10) ? $nextp - 10 : 1; my $max = ($nextp > 10) ? $nextp : 10; for (; $i <= $max; $i++) { if ($i == $self -> {pageno}) { $s = ''; $us = ''; } else { $s = ''; $us = ''; } $self -> {text} .= qq|$s$i$us \n|; } $self -> {text} .= qq|$GT_ent$GT_ent 

|; return $self; } =head2 $ui -> results_footer (); Format the page numbers and results totals that appear at the bottom of each page of results. =cut sub results_footer { my $self = $_[0]; my $id = $self -> {q} -> {id}; my ($s, $us); my ($first, $last, $nextp, $prevp) = $self -> _queue_indexes (); my $total = $#{$self->{r}} + 1; $self -> {text} =<

Results $first to $last of $total documents.

$LT_ent$LT_ent  EOM my $i = ($nextp > 10) ? $nextp - 10 : 1; my $max = ($nextp > 10) ? $nextp : 10; for (; $i <= $max; $i++) { if ($i == $self -> {pageno}) { $s = ''; $us = ''; } else { $s = ''; $us = ''; } $self -> {text} .= qq|$s$i$us \n|; } $self -> {text} .= qq|$GT_ent$GT_ent 

|; return $self; } sub _queue_indexes { my $self = shift; my ($first, $last, $nextp, $prevp); $first = (($self -> {pageno} - 1) * $self -> {pagesize}) + 1; ### ### If the page is past the end of the results queue, simply print ### the queue head pointer. ### if ($first <= 0) { if ($#{$self->{r}} < 0) { $first = 0; } else { $first = 1; } } $last = (($first + $self -> {pagesize}) <= ($#{$self->{r}} + 1)) ? (($self->{pageno} - 1) * $self->{pagesize}) + $self->{pagesize} : $#{$self->{r}} + 1; $nextp = $self -> {pageno} + 1; $prevp = $self -> {pageno} - 1; if ($prevp <= 0) { $prevp = 1; } return ($first, $last, $nextp, $prevp); } =head2 $ui -> admin_page (I, I,, I, I); Template for the OnSearch administrator page. =cut sub admin_page { my $self = shift; my ($lastindex, $idxsecs, $backup_opt, $digitsonly_opt) = @_; my $backups = ''; my $digitsonly = ''; my ($cfg, $OnSearchDir); $cfg = OnSearch::AppConfig -> new; $OnSearchDir = $cfg -> str (qw/OnSearchDir/); $backups = 'checked' if $backup_opt ne '0'; $digitsonly = 'checked' if $digitsonly_opt ne '0'; $self -> {text} =<
EOP return $self; } =head2 $ui -> fileindex_form (); Template for the file uploading and indexing form. =cut sub fileindex_form { my $self = shift; my ($cfg, $OnSearchDir); $cfg = OnSearch::AppConfig -> new; $OnSearchDir = $cfg -> str (qw/OnSearchDir/); $self -> {text} =<
 
EOT return $self; } =head2 $ui -> archive_title (); Template for the Archive page title. =cut sub archive_title { my $self = shift; $self -> {text} =<