#!/usr/local/bin/perl ##---------------------------------------------------------------------------## ## File: ## $Id: mhaadmin.cgi,v 1.3 2001/12/24 13:31:57 ehood Exp $ ## Author: ## Earl Hood mhonarc@pobox.com ## Description: ## CGI program for MHonArc archive administration. ##---------------------------------------------------------------------------## ## Copyright (C) 1998,1999 Earl Hood, mhonarc@pobox.com ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ## 02111-1307, USA ##---------------------------------------------------------------------------## package MHAHttpAdmin; use lib qw ( . ./lib ); use CGI; use CGI::Carp; ##---------------------------------------------------------------------------## ## Main routine ## ##---------------------------------------------------------------------------## use vars qw( $JSMenuBar $JSIndexPage $JSMesgPage ); BEGIN: { jscript_define(); $ENV{'M2H_USELOCALTIME'} = 1; } my $Debug = 0; # set to 1 for debug mode, messages sent to server log my $Rc; my $menulogo; my $noteicon; my $query; my $action; my $archive; my $pagesize; my @body_attr = ( '-bgcolor' => "#dddddd", '-text' => "#000000", '-link' => "#0000ee", '-vlink' => "#551a8b", '-alink' => "#ff0000", ); MAIN: { $Rc = require 'mhaadmin.rc' or croak qq/Error: Unable to require resource file\n/; if ($Debug) { warn '@INC=', join(':', @INC), "\n"; } $menulogo = "$Rc->{'iconurl'}/mhaicon.png"; $noteicon = "$Rc->{'iconurl'}/mhanote_s.png"; $ENV{'M2H_LOCKMETHOD'} = $Rc->{'lockmethod'} if defined($Rc->{'lockmethod'}); ## Load main MHonArc library require 'mhamain.pl'; if ($Debug) { warn qq/MHonArc version = $mhonarc::VERSION\n/; } if ($Debug) { warn qq/lockmethod = $ENV{'M2H_LOCKMETHOD'}\n/; } ## Initialize CGI environment $query = new CGI; ## Initialize MHonArc mhonarc::initialize(); ## Get archive $archive = $query->param('archive'); if ($archive !~ /\S/) { $archive = $query->param('archive') || (sort { $Rc->{archive}{$a}[0] cmp $Rc->{archive}{$b}[0] } keys %{$Rc->{archive}})[0]; } ## Get action $action = $query->param('action'); if ($Debug) { warn qq/(archive=$archive, action=$action)/; } ## Check if deleting messages if ($action eq 'delete') { my %dup = (); my @msgnum = grep { /\S/ && ($dup{$_}++ < 1 ) } $query->param('msgnum'); if (@msgnum) { mhonarc::process_input( '-outdir', $archive, '-quiet', '-rmm', @msgnum); } $action = 'index'; } ## Print menubar if ($action eq 'menubar') { do_menu_bar(); last MAIN; } ## Viewing a message if ($action eq 'show') { do_mesg_view(); last MAIN; } ## Showing index do_index(); } ## End: MAIN ##---------------------------------------------------------------------------## ## Subroutines ##---------------------------------------------------------------------------## ##---------------------------------------------------------------------------## ## do_menu_bar outputs the menubar. Output is targeted to the ## menubar frame. ## sub do_menu_bar { if ($Debug) { warn qq/do_menu_bar/; } print $query->header( '-target' => 'mhaMenuBar'); print $query->start_html( '-title' => 'MHonArc Admin: Menubar', '-script' => $JSMenuBar, @body_attr); print $query->startform( '-name' => 'menuBarForm', '-method' => 'post', '-action' => $query->url()); print_main_menus(); print $query->endform(); print $query->end_html(); } ##---------------------------------------------------------------------------## ## do_index display the message index. Output is targeted to ## the main window frame. ## sub do_index { if ($Debug) { warn qq/do_index/; } my $page = $query->param('page'); my $pagenum = $query->param('pagenum'); my $pagesize = $query->param('pagesize') || 50; my $sort = $query->param('sort') || 'sort'; my $thread = ($sort =~ /^t/ ? 1 : 0); ## Print header print $query->header( '-target' => 'mhaWorkArea'); print $query->start_html( '-title' => 'MHonArc Admin: Message Index', '-script' => $JSIndexPage, @body_attr); #print $query->dump; print $query->startform( '-name' => 'listForm', '-method' => 'post', '-action' => $query->url()); ## Write some hidden fields $action = 'index'; $query->param('action', $action); print $query->hidden( '-name' => 'action', '-value' => $action), "\n"; $query->param('archive', $archive); print $query->hidden( '-name' => 'archive', '-value' => $archive), "\n"; $query->param('pagesize', $pagesize); print $query->hidden( '-name' => 'pagesize', '-value' => $pagesize), "\n"; $query->param('sort', $sort); print $query->hidden( '-name' => 'sort', '-value' => $sort), "\n"; $query->param('page', 'cur'); print $query->hidden( '-name' => 'page', '-value' => $page), "\n"; ## Open archive mhonarc::open_archive( '-nolock', '-outdir', $archive, '-quiet', '-nodoc', '-multipg', '-idxsize', $pagesize, "-$sort", $thread ? ('-nomain', '-thread') : ('-nothread', '-main'), '-genidx'); mhonarc::close_archive(); ## Set index resources set_resources(); $thread ? set_thread_idx_resources($sort) : set_main_idx_resources($sort); mhonarc::compute_threads() if $thread; ## Figure out what index page to print my $totalpgs; if ($pagesize == 0) { $totalpgs = 1; } else { $totalpgs = int($mhonarc::NumOfMsgs/$pagesize); ++$totalpgs if ($mhonarc::NumOfMsgs/$pagesize) > $totalpgs; $totalpgs = 1 if $totalpgs == 0; } $pagenum = 1 unless $pagenum; PAGENUM: { if ($page =~ /first/i) { $pagenum = 1; last PAGENUM; } if ($page =~ /last/i) { $pagenum = $totalpgs; last PAGENUM; } if ($page =~ /next/i) { ++$pagenum; last PAGENUM; } if ($page =~ /prev/i) { --$pagenum; last PAGENUM; } } $pagenum = $totalpgs if $pagenum > $totalpgs; $pagenum = 1 if $pagenum < 1; $query->param('pagenum', $pagenum); print $query->hidden( '-name' => 'pagenum', '-value' => $pagenum); ## Print index $thread ? mhonarc::write_thread_index($pagenum) : mhonarc::write_main_index($pagenum); ## Done print $query->endform(); print $query->end_html(); } ##---------------------------------------------------------------------------## ## do_mesg_view displays message(s). Output is targeted to the ## message view frame/window. ## sub do_mesg_view { if ($Debug) { warn qq/do_mesg_view/; } my %dup = (); my @msgnum = grep { /\S/ && ($dup{$_}++ < 1 ) } $query->param('msgnum'); ## Print header print $query->header( '-target' => 'mhaMesgView'); print $query->start_html( '-title' => "MHonArc Admin: Message View", '-script' => $JSMesgPage, '-onload' => 'window.focus();', @body_attr); print $query->startform( '-name' => 'listForm', '-method' => 'post', '-action' => $query->url()); ## Open archive (just to load db and routines) mhonarc::open_archive( '-outdir', $archive, '-nolock', '-readdb', '-quiet'); mhonarc::close_archive(); ## Print message foreach (@msgnum) { print_mha_mesg($archive, $_, "$archive/" . mhonarc::msgnum_filename($_)); print "
\n"; } print '
', $query->button( '-name' => 'closeBtn', '-value' => 'Close', '-onClick' => 'window.close();'), "
\n"; print $query->endform(); print $query->end_html(); } ############################################################################### ##---------------------------------------------------------------------------## ## print_mha_mesg() outputs the message data part of a message ## page in an archive. ## sub print_mha_mesg { my $arch = shift; my $msgnum = shift; my $filename = shift; if (!open(MHAMESG, $filename)) { my $errstr = qq/Unable to open "$filename"\n/; carp $errstr; print html_error($errstr); return 0; } ## Get URL to archive my $base = $Rc->{archive}{$arch}[1]; ## Read header comments and print them. my %field = (); my @field = (); my $field; while () { last if /^/; if (/^/) { push(@field, $1); push(@{$field{$1}}, mhonarc::entify(mhonarc::uncommentize($2))); } } my $atitle = $Rc->{archive}{$arch}[0]; print < $atitle: $msgnum EOT my %printed = (); foreach $field (@field) { next if $printed{$field}; $printed{$field} = 1; print qq(\n), qq($field \n), qq(); print join(",
", @{$field{$field}}); print qq(\n); } print "\n"; ## Just extract the message header and body part of the page. Adjust ## relative URLs so links to derived files will work. my $replsub = sub { my $url = shift; unless ($url =~ /^[\w]+:/ or $url =~ /^\// or $url =~ /^#/) { return $base . $url; } $url; }; while () { next unless /^/i; while () { last if /^/i; s/(href\s*=\s*["'])([^"']+)(["']) /join("",$1,&$replsub($2),$3) /xgei; s/(src\s*=\s*["'])([^"']+)(["']) /join("",$1,&$replsub($2),$3) /xgei; print; } last; } close MHAMESG; ## Done 1; } ##---------------------------------------------------------------------------## sub set_resources { my $cgiurl = $query->url() . "?archive=$archive"; $mhonarc::NOTE =<<'EOT';
$NOTETEXT$
EOT $mhonarc::NOTEIA = ""; $mhonarc::NOTEICON =< EOT $mhonarc::NOTEICONIA=''; } ##---------------------------------------------------------------------------## sub set_main_idx_resources { my $sort = shift; my $cgiurl = $query->url() . "?archive=$archive"; $mhonarc::IDXPGBEG = ''; $mhonarc::IDXPGEND = ''; $mhonarc::LIBEG =<
\$IDXTITLE\$
\$NUMOFIDXMSG\$/\$NUMOFMSG\$ by \$SORTTYPE\$ Page \$PAGENUM\$/\$NUMOFPAGES\$
EOT $mhonarc::LIEND =<<'EOT'; EOT my $colheads, $colcnt; my @col = (); $col[0] =< EOT if ($sort eq 'authsort') { $colheads = ''; $col[1] = ''; $col[2] = ''; } elsif ($sort eq 'subsort') { $colheads = ''; $col[1] = ''; $col[2] = ''; } elsif ($sort eq 'nosort') { $colheads = ''; $col[1] = ''; $col[2] = ''; $col[3] = ''; } else { $colheads = ''; $col[1] = ''; $col[2] = ''; $col[3] = ''; } $colcnt = scalar(@col); $mhonarc::LIBEG .= $colheads; $mhonarc::LIEND .= $colheads; $mhonarc::LIEND .=<<'EOT';
Number
Number
\$NOTEICON\$ \$MSGNUM\$
DateSubject
$YYYYMMDD$$SUBJECTNA$DateFrom
$YYYYMMDD$$FROMNAME$DateFromSubject
$YYYYMMDD$$FROMNAME$$SUBJECTNA$DateFromSubject
$MSGLOCALDATE(;%H:%M)$$FROMNAME$$SUBJECTNA$
$NUMOFIDXMSG$/$NUMOFMSG$ by $SORTTYPE$ Page $PAGENUM$/$NUMOFPAGES$
EOT $mhonarc::LITMPL = join("", @col); $mhonarc::NOTEICONIA='   '; $mhonarc::AUTHBEG =< \$FROMNAME\$ EOT $mhonarc::AUTHEND =< EOT $mhonarc::DAYBEG =< \$MSGLOCALDATE(;%B %d, %Y)\$ EOT $mhonarc::DAYEND =< EOT $mhonarc::SUBJECTBEG =< \$SUBJECTNA\$ EOT $mhonarc::SUBJECTEND =< EOT } ##---------------------------------------------------------------------------## sub set_thread_idx_resources { my $cgiurl = $query->url() . "?archive=$archive"; $mhonarc::TIDXPGBEG = ''; $mhonarc::TIDXPGEND = ''; $mhonarc::THEAD =<
\$TIDXTITLE\$
\$NUMOFIDXMSG\$/\$NUMOFMSG\$ by \$SORTTYPE\$ Page \$PAGENUM\$/\$NUMOFPAGES\$
EOT $mhonarc::TFOOT =<<'EOT';
$NUMOFIDXMSG$/$NUMOFMSG$ by $SORTTYPE$ Page $PAGENUM$/$NUMOFPAGES$
EOT $mhonarc::TSINGLETXT =< \$NOTEICON\$\$MSGNUM\$, \$SUBJECTNA\$, \$FROMNAME\$ EOT $mhonarc::TTOPBEG =< \$SUBJECTNA\$
\$NOTEICON\$\$MSGNUM\$, \$FROMNAME\$ EOT $mhonarc::TTOPEND =<<'EOT';
EOT $mhonarc::TLITXT =< \$NOTEICON\$\$MSGNUM\$, \$FROMNAME\$ EOT $mhonarc::TLIEND =<<'EOT'; EOT $mhonarc::TSUBLISTBEG =<<'EOT';
EOT $mhonarc::TSUBLISTEND =<<'EOT';
EOT $mhonarc::TSUBJECTBEG =<<'EOT'; Possible follow-ups EOT $mhonarc::TSUBJECTEND =<<'EOT'; EOT $mhonarc::TLINONE =<<'EOT';
Message not available EOT $mhonarc::TLINONEEND =<<'EOT';
EOT $mhonarc::TINDENTBEG =<<'EOT';
EOT $mhonarc::TINDENTEND =<<'EOT';
EOT $mhonarc::TCONTBEG =<<'EOT';
$SUBJECTNA$ (continued)
EOT $mhonarc::TCONTEND =<<'EOT';
EOT } ##---------------------------------------------------------------------------## sub print_main_menus { print < MHonArc        EOT } ##---------------------------------------------------------------------------## sub html_error { print <<'EOT';
Note
EOT; print $query->p(@_); print <<'EOT';
EOT } ##---------------------------------------------------------------------------## ## JavaScript Code ##---------------------------------------------------------------------------## sub jscript_define { ## JavaScript for main index page ##-----------------------------------------------------------------------## $JSMenuBar =<<'EOJS'; // Set the selection of all messages function checkAll (form, val) { var i; for (i=0; i < form.elements.length; ++i) { if (form.elements[i].name == 'msgnum') { form.elements[i].checked = val; } } } // Process Archive menu selection function process_file_menu (menu) { var choice = menu.options[menu.selectedIndex].value; var text = menu.options[menu.selectedIndex].text; var list_form = parent.mhaWorkArea.document.listForm; var type = choice.substr(0,4); var val = choice.substr(5); if (choice != "title") { list_form.archive.value = val; parent.defaultStatus = text; parent.status = text; list_form.action.value = 'index'; list_form.submit(); } menu.options[menu.selectedIndex].selected = false; menu.options[0].selected = true; } // Process Edit menu selection function process_edit_menu (menu) { var choice = menu.options[menu.selectedIndex].value; var list_form = parent.mhaWorkArea.document.listForm; menu.options[menu.selectedIndex].selected = false; menu.options[0].selected = true; if (choice == "selectAll") { checkAll(list_form, true); } else if (choice == "unselectAll") { checkAll(list_form, false); } else if (choice == "reset") { list_form.reset(); } else if (choice == "show") { list_form.action.value = 'show'; window.open('javascript:void(0)', 'mhaMesgView', 'menubar=0,resizable=1,toolbar=0,scrollbars=1'); list_form.submit(); } else if (choice == "delete") { if (window.confirm("Delete selected messages?")) { list_form.action.value = 'delete'; list_form.submit(); } } } // Process View menu selection function process_view_menu (menu) { var choice = menu.options[menu.selectedIndex].value; var list_form = parent.mhaWorkArea.document.listForm; var type = choice.substr(0,4); var val = choice.substr(5); var n; menu.options[menu.selectedIndex].selected = false; menu.options[0].selected = true; if (type == "sort") { list_form.sort.value = val; list_form.action.value = 'index'; list_form.submit(); } else if (type == "rfsh") { list_form.action.value = 'index'; list_form.submit(); } else if (type == "pgsz") { n = parseInt( window.prompt( "Maximum number of message listed per page:", list_form.pagesize.value)); if ((!isNaN(n)) && (n >= 0) && (n != list_form.pagesize.value)) { list_form.pagesize.value = n; list_form.action.value = 'index'; list_form.submit(); } } else if (type == "page") { list_form.page.value = val; list_form.action.value = 'index'; list_form.submit(); } } EOJS ## JavaScript for main index page ##-----------------------------------------------------------------------## $JSIndexPage =<<'EOJS'; // Handle button navigation function changePage (f, val) { f.page.value = val; f.action.value = 'index'; f.submit(); } // Set the selection of all messages in a group function checkGroup (topmesg) { var val = topmesg.checked; var i; for (i=0; i < topmesg.form.elements.length; ++i) { if (topmesg.form.elements[i] == topmesg) { break; } } ++i; if (i >= topmesg.form.elements.length) { return; } while (topmesg.form.elements[i].name == 'msgnum') { topmesg.form.elements[i].checked = val; ++i; } } // Open a message view window for a message function open_mesg_view (cgiurl) { window.open(cgiurl, 'mhaMesgView', 'menubar=0,resizable=1,toolbar=0,scrollbars=1'); } EOJS }