#!/usr/bin/perl -w
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# First, some initialization to determine where we are and how to find stuff:
#
&startup($V = 1);
#
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
#NAME
# index.cgi - CGI program for delivering assorted content as web pages
# show - CGI program for delivering assorted content as web pages
#
#SYNOPSIS
# http://example.com/dir/
# http://example.com/dir/index.cgi
# http://example.com/dir/?params...
# http://example.com/dir/index.cgi?params...
#
#DESCRIPTION
# This program is installed as index.cgi or other name in a directory. It
# Delivers assorted "content" as a web page, calling various routines to do
# the conversion of various kinds of data to HTML.
#
# The main motive behind this program is to help people who are put off by
# "scary" URLs, by hiding most of the informations in ways that this program
# can quickly discover, thus making for shorter URLs. The primary information
# used includes this program's name, assorted things in its environment,
# directory and subdirectories, and whatever the browser has passed as "form"
# data.
#
#VARIABLES
# This program is invoked for (nearly) every reference to the web site that
# it manages, so it has been designed with the idea of a lot of short runs.
# There is a set of global variables that everything works on. Among the
# most important are the variables with single-letter names:
# $B The text from a button that the user pushed
# $C the "class" of the request: blog, event, doc, etc.
# $D the current day (2 digits, 1-31)
# $L The Layout (F=Full, M=Mobile)
# $M The current month (2 digits, 1-12)
# $Q The current Query, if known
# $P This program's name, without the directories
# $R Random number, a token used to avoid duplicate messages
# $S The session id (0 if no session)
# $T The current blog Topic
# $V The Verbose level (default=1 to get error messages only)
# $Y The current year (4 digits)
#
# In addition, there is a set of global variables that deal with the task
# that the current invocation has been asked to perform.
$Class = ''; # the general area (doc, blog, event, etc.)
$Action = ''; # what sort of operation we're performing on the Object
$Object = ''; # The sort of data object we're dealing with
$Argnam = ''; # Is the name of the Object
$Parent = ''; # The name of the object's "parent", if any
#
#REQUIRES
#
($cwd = `/bin/pwd`) =~ s"[\r\s]*$"";
print STDERR "$0: CWD='$cwd'\n" if $V>8;
push @INC, 'pm', '../pm'; # Where to find our perl modules
require "now.pm"; # Simple Date/Time routine
require "dump.pm"; # Some data-dump routines
require "cgilocal.pm"; # Setup for this installation
require "DT.pm"; # Complex Date/Time routines
require "HTMLenc.pm"; # HTML encoding routines
require "ISOdate.pm"; # Get date/time in ISO standard format
require "dates.pm"; # Date menu routines
require "parse.pm"; # Routines to parse command-related stuff passed to us by clients
require "taintsubs.pm"; # Routines to untaint incoming data strings
require "sendsubs.pm"; # Routines to send various common messages
require "sessions.pm"; # Routines to implement persistent Web sessions
require "schedules.pm"; # Routines to format table data as HTML
require "sitemisc.pm"; # Miscellaneous other stuff
require "account.pm"; # Routines that deal with logged-in users
require "frame.pm"; # Routines for the web-page boilerplate stuff
use Time::Local; # Time conversion
use CGI;
use CGI::Carp 'fatalsToBrowser';
use diagnostics;
#
#OPTIONS
#
#FILES
#
#BUGS
#
#SEE ALSO
#
#AUTHOR John Chambers
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Assorted global variables:
$| = 1; # Unbuffered stdout
# A few special variables with single-letter names:
our $L = '' unless $L; # Layout, F (full) or M (mobile)
our $P = '?' unless $P; # Program name, minus directories
our $S = 0 unless $S; # Session id number
our $T = 'All' unless $T; # Blog topic defaults to the latest news
# Miscellaneous globals:
our %admins; # List of users allowed to do administrative changes
our %buttonrewrite; # Rewrite buttons, mostly to expand compact buttons
our $announceLimit = 2; # Limit to announcements on main page
our %data = (); # Form variables as a hash table
our $docname = $contentname | 'Home'; # Default document name (if all else fails)
our $docpath = ''; # Default document full path (to be calculated)
our %editors; # List of users allowed to edit
our $exitstat = 0; # Set to nonzero to get failure on exit
our $indent = ' '; # Default indent
our $Lopen = 0; # Set to 1 when logfile is writable
our $Lsrc = '???'; # Where we got the value of $L
our $Layout = '??'; # Name of layout, for messages
our @names = (); # List of HTML form variable names
our $RA = &tIPad($ENV{'REMOTE_ADDR'}) || '0.0.0.0';
our $showdir = 0; # Show directory listing at exit
our $UA = &tText($ENV{'HTTP_USER_AGENT'}) || '';
our $TZ; # Time zone, in ISOdate.pm
our $unumb = 0; # User id number
our $fname = ''; # User full name
our $uname = ''; # User login name
our $showAllInfo = 0; # If true, all fields in .info files are shown
our $srvr = ''; # The name of the current server.
our $Vpwd = 5; # Verbose level for showing passwords
our $Vuser = 1 # Verbose level for user info
unless defined $Vuser;
#if (($RA =~ /^192\.168\./) || ($RA =~ /^0\.0\.0\.\0/)) {
# $V = 3 if $V<3; # DEBUG: Level for local requests
#}
#if (-f `/bin/hostname`) { # Can we find our hostname?
if ($x = `/bin/hostname`) { # Try to find our hostname?
if ($x =~ /([-_\w]+)\s*$/) { # Strip off everything but the FQDN
$srvr = $1; # What we know about this server
}
}
#}
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
our %blogOps = ( # Display names for the new/blog stuff
'blog' => 1,
'news blog' => 1,
'news' => 1,
);
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Global tables of user account info:
#AcctInfo = (); # A miscellaneous user's account info
%UserInfo = (); # The current logged-in user's account info
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Parse out some of the pieces of our program name
($P,$Pdir,$Pbase,$Psuff) = &progName($0);
print STDERR "P='$P' Pdir='$Pdir' Pbase='$Pbase' Psuff='$Psuff' V=$V.\n" if $V>8;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Set up the CGI interface, and check a few form variables. In the default
# call we will have no form data, so the program must not assume that any
# form variable is defined.
$cgi = new CGI;
@names = sort $cgi->param(); # our variable names
#data = $cgi->Vars; # All our form data
if ($x = $cgi->param(V)) { # Look for verbosity first
if ($x =~ /(\d+)/) { # Does it contain a number?
$V = int($1); # Accept it as our verbosity
} else {
&sendLog("$P: Invalid V=\"$x\" in param list.\n") if $V>0;
}
}
if ($x = $cgi->param(L)) { # Look for layout next
$Layout = $Layout{$L = $x} || 'full'; # Layout's name
$Lsrc = 'cgi->param()'; # Where we got the layout
&sendAll("Info: Layout L='$L'='$Layout' ($Lsrc) [new CGI]") if $Lopen && $V>1;
}
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Create a logfile for this process. If we can't do this, we make STDERR the #
# logfile. If that fails, we squawk and give up. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
$logdir = 'log'; # Where to put logfiles
$logfile = $logdir.'/'.$CYMD.$HMS.'_'.$$.'_'.$Pbase.'.log'; # Logfile with PID
$outfile = "$logdir/$Pbase.log"; # Single name for debugging
$lstfile = "$logdir/last.log"; # Single name for all programs
if (open(L,">>$logfile")) {
$Lopen = 1; # Logfile is now open
&sendLog("Logfile: '$logfile'\n") if $V>3;
print STDERR "$0: Logfile: '$logfile'\n" if $V>1;
} else {
print STDERR "$0: ### Can't write \"$logfile\" ($!) ###\n";
if (open(L,'>&STDERR')) { # Logfile is STDERR
$Lopen = 1; # Logfile is now open
&sendLog("Logfile: STDERR.") if $V>3;
} else {
$Lopen = 0; # Logfile is not open
print STDERR "$0: ### Can't write logfile ($!) ###\n" if $V>0;
&quit(1);
}
}
print STDERR "$0: Logfile done.\n" if $V>1;
select L; $| = 1; select STDOUT;
$R = 0 unless defined $R;
&sendLog("$CYMD $HMS pid=$$ L=$L R=$R S=$S RA=$RA T='$T' V=$V.") if $V>0;
unlink($outfile); link($logfile,$outfile); # Link log to simpler name
unlink($lstfile); link($logfile,$lstfile); # Link log to "last.log" name
&sendLog("$CYMD $HMS UA={$UA}") if $V>0;
&sendLog("$P: L='$L'=$Layout ($Lsrc) HTML5:$usehtml5") if $V>0;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Make a pass through the data looking for certain special pieces of data, #
# and "expand" them by generating some new form params. This is mostly to #
# deal with the limitations of tags, which don't permit #
# passing an arg. So we encode the arg as part of the name attribute, in the #
# form "cmd:arg". If found, we store the command and arg fields as $data{cmd} #
# and $data{arg}. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
$B = $cgi->param('B') || $B || ''; # Does the form data have a button name?
$Q = $cgi->param('Q') || $Q || ''; # Q often encodes the area/object/classification
&sendLog("Info: B='$B' L='$L' [B param]") if $V>0;
&parseData(); # Try to figure out the command's Action, Object, etc.
&sendLog("$P: Action='$Action' Class='$Class' Object='$Object' $Argnam='$Argnam'") if $V>0;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
&sendLog("$P: This is the '$orgabbr' '$orgname' site.\n") if $V>0;
if ($V>2) {
&dumpData('main');
for $nam (sort keys %ENV) {
$val = $ENV{$nam};
&sendLog("Info: # $nam: \"$val\"");
}
&sendLog("Info: #################################\n");
}
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Extract a few common things that may be passed in forms:
$B = &tWord($data{B},'') unless $B; # Button pushed?
$b = lc($B); # Lower-case version of button name
&sendLog("Info: B='$B' b='$b' [from data]") if $V>0;
if ($x = ($data{title} || $B)) { # Did we get a title string?
&sendLog("$P: Task: $x") if $V>0;
$maintitle .= " $x";
}
if ($L eq 'M') {
&sendLog("$P: Add 'mobile' to maintitle.") if $V>0;
$maintitle .= " [mobile]";
}
$R = $data{R} || '0'; # Random token
$S = $data{S} || $Default{'S'} || '0'; # Session id
$T = &tWord($data{topic} || $data{T},$T); # Blog topic
$C = &tWord($data{C} || $T || ''); # Request class
&sendLog("$P: B='$B' C='$C' L='$L' R='$R' S='$S' T='$T' V='$V'") if $V>0;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Try to figure out whether this is a small-screen "mobile" device, and set #
# the $L "Layout" variable appropriately. Our default layout is formatted for #
# a larger screen, but the $L='M' layout will change some things so they fit #
# better on a small screen. This is known to be a difficult problem in #
# general. It's too bad the HTML standards don't include the client sending #
# the screen/window dimenstions to us. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
#mobileUApat = 'Android|iPhone|iPad|Opera Mini'; # Recognize some mobile devices
$mobileUApat = 'Android|iPhone|iPad|Opera Mini'; # Recognize some mobile devices
#Meta = ''; # Extra command to send.
if ($Pbase eq 'mobile') {
$devtyp = 'mobile';
$L = 'M'; # The client requested "mobile" format
$Lsrc = "program name $Pbase";
&sendLog("Layout $L ('mobile' in $Lsrc)") if $V>0;
} elsif ($UA =~ m"($mobileUApat)") {
$devtyp = $1;
$L = 'M'; # This is a known "mobile handheld" aka "smart phone"
$Lsrc = "UA contains '$1'";
&sendLog("Layout $L (mobile device '$1')") if $V>0;
# $Meta = '\n';
} elsif ($x = $data{L}) { # Look into the form data for the layout
$L = $devtyp = $x;
$Lsrc = 'form data';
$L =~ s/^(.).*/$1/; # Trim to one char (obsolete?)
&sendLog("Layout $L (L='$x' in $Lsrc)") if $V>0;
} else {
$devtyp = '??';
}
unless ($L) { # If nothing has decided a layout yet
$L = 'F';
$Lsrc = 'default';
}
$Layout = $Layout{$L};
&sendLog("Layout L='$L'=$Layout ($Lsrc) [after mobile check]") if $V>0;
&sendLog("maintitle=\"$maintitle\"\n") if $V>3;
&sendLog("PATH='" . join(':',$ENV{'PATH'}) . "'") if $V>0;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Here's where we put out the HTTP/HTML header stuff. Can we just hand this #
# off to the CGI module? #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
print "Content-type: text/html\n\n";
print "\n";
print "\n"; # N.B.: L='F' if called from the Mobile button from a "Full" page
print "\n";
print "\t$maintitle Online\n";
print "\t\n";
#rint "\t\n";
print "\t\n";
print "\t\n";
print "\t\n" if $usehtml5;
#rint "\t$Meta\n" if $Meta;
print "\n";
print "\n";
print "\n";
print "
";
print "\n";
}
sub Button {my $F='Button'; my($B,$A) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Handle a button push. The $B arg is the text on the button. The $A is #
# whatever extra info the caller passed us. We may also look around in %data #
# for more information. Note that we convert $A and $B to $a and $b, the #
# all-lower-case versions. So far, we don't actually use $a here, but only #
# pass $A to various routines. But in some cases, we might want to hide the #
# capitalizations from the rest of the coe. For $B, the button's text, we #
# usually want to ignore case, so we usually use $b instead. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
local($a,$Arg,$b,$f,$fnam,$prnt,$source,$unam,$unum,$x);
$B = '' unless defined $B; $b = lc($B);
$A = '' unless defined $A; $a = lc($A);
&sendLog("$F: Called with '$B'/'$b' '$A'/'$a'") if $V>0;
if ($x = $buttonrewrite{$B}) { # Expanded button name?
&sendLog("$F: Rewrite button '$B' as '$x'.") if $V>0;
$B = $x; $b = lc($b);
&sendLog("$F: Rewrote B='B' b='$b'") if $V>0;
}
# $b =~ s/^\s+//;
# $b =~ s/\s+$//;
&sendLog("$F: b='$b'") if $V>0;
if ($Object && $Action && $Argnam) {
&sendLog("$F: Action='$Action' Class='$Class' Object='$Object' $Argnam='$Argnam' ........................") if $V>0;
$source = frame(); # Call frame for global setup variables
return $source if $source;
# If the Object/Action/Argnam globals are set up, that should be all we
# need to do here to get the requested content in the content frame. If
# the globals haven't been set up, we fall back on the earlier code that
# tests the %data info here. Eventually the rest should be phased out.
} elsif ($b eq 'add new event') {
&sendLog("$F: B='$B' b='$b' ........................................") if $V>0;
$source = &frame('add','event');
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'create message') {
&sendLog("$F: B='$B' b='$b' ........................................") if $V>0;
$source = &frame('add','doc');
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'events' || $b eq 'all events') { # Request for the Events table
&sendLog("$F: B='$B' b='$b' ........................................") if $V>0;
$source = &frame('show','events','All Events');
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'edit' || $b eq 'dup') {
&sendLog("$F: $B button '$b' recognized as edit operation.") if $V>0;
if (($Object eq 'event') && ($x = $Argnam)) {
&sendLog("$F: Call editEvent('edit',...)") if $V>1;
$source = &frame('edit','event',$x) || '';
&sendLog("$F: Return source='$source'") if $V>1;
return $source;
} elsif (($Q = $data{Q}) eq 'blog') {
&sendLog("$F: Editing a blog entry ...");
$Arg = $Argnam;
&sendLog("$F: Call frame('edit','blog','$Arg')");
$source = &frame('edit','blog',$Arg);
} elsif (($dir = $data{_DIR}) && ($nam = $data{_NAM})) {
&sendLog("$F: Edit dir='$dir' nam='$nam' suf='$suf'") if $V>0;
$source = &frame($b,$dir,"$nam.$suf");
return $source if $source;
} elsif (($Arg = $Argnam) =~ m"^doc/") {
&send_LW("$F: Edit doc '$Arg' ...");
$source = &frame($b,'doc',$ARG); # Send edit page for document
return $source if $source;
} else {
&sendLog("$F: ### Don't know what to edit.") if $V>0;
}
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'files') {
&sendLog("$F: Files button '$b' recognized.") if $V>0;
$source = &frame('show',$b);
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'flyer') {
&sendLog("$F: Flyer button '$b' recognized.") if $V>0;
$source = &frame('show',$b);
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'flyers' || $b eq 'all flyers') {
&sendLog("$F: Flyers button '$b' recognized.") if $V>0;
$source = &frame('show','flyers');
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'home' || $b eq 'home page') {
&sendLog("$F: '$b' button recognized.") if $V>0;
$source = &frame('show','home page',"Home$L");
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'list') {
&sendLog("$F: List button '$b' recognized.") if $V>0;
$source = &frame('list',$b);
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'login') { # Request for login form
&sendLog("$F: Login button recognized.") if $V>0;
if (($user = $data{'uname'}) && ($pswd = $data{pswd})) {
&sendLog("$F: Login attempt with user='$user'") if $V>0;
# $source = &frame('login','user',$user);
$unum = &login(lc($user),$pswd,$S);
&sendLog("$F: login returned '$unum'") if $V>0;
if (defined($unum)) {
&send_LW("Account '$uname' ($unumb) is logged in.\n");
} else {
&send_LW("### Login failed ###\n");
}
# Whether the login succeded or failed, bounce to the home page.
$source = &frame('show','home page',"Home$L");
return $source if $source;
} else {
&sendLog("$F: No user info; showing login form.") if $V>0;
$source = &frame('show','doc',"$docdir/Login$L.html");
return $source if $source;
}
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'logout') { # Request for logout
&sendLog("$F: '$b' button recognized.") if $V>0;
if (($ulog,$unum,$unam,$uadr) = chkLogin($RA,$S)) {
&sendLog("$F: Log out ulog=$ulog unum=$unum unam=$unam uadr=$uadr S='$S'") if $V>0;
if ($bkupfile = &logoutUser($unum,$unam,$uadr,$S)) {
&sendLog("$F: Logout succeeded, session file is '$bkupfile'") if $V>0;
$uname = $Default{uname}; # change login to default
$unumb = $Default{unumb};
$S = '0';
$loggedout = 1; # Should block later tries to get the S and user info
&send_LW("User $unum '$unam' is now logged out.") if $V>0;
&sendLog("$F: Show the home page to the logged-out user ...") if $V>0;
$Frame = $framefile = "$docdir/$framename$L.html"; # Default frame file
$source = &frame('show','home page',"Home$L");
return 'logoutUser()'; # Tell the caller that we succeeded
}
} else {
&sendLog("$F: Can't find session for RA='$RA' S='$S'") if $V>0;
}
&send_LW("$F: Logout failed.");
} elsif ($b eq 'mobile') { # Switch to compact "mobile" layout
&sendLog("$F: '$b' button recognized.") if $V>0;
$Layout = $Layout{$L = 'M'}; # Change the layout to Mobile
$Lsrc = "$B button";
&sendLog("Layout L='$L'=$Layout ($Lsrc) [b='mobile']") if $V>0;
$Frame = $framefile = "$docdir/$framename$L.html"; # Default frame file
$source = &frame('show','home page',"Home$L");
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'news' || $b eq 'blog' || $b eq 'news blog') {
&sendLog("$F: News/blog button '$b' recognized.") if $V>0;
$source = &frame('show','blog',$T); # Show the current news/blog topic
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b =~ /^board *meeting/i) { # Board meeting schedule
&sendLog("$F: '$B' recognized.") if $V>0;
$Action = 'Show';
$Object = 'Board';
$Argnam = 'Meetings';
&sendLog("$F: Action='$Action' Class='$Class' Object='$Object' Argnam='$Argnam'") if $V>0;
$source = &frame(); # Try to produce the schedule
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($B =~ /^(\w+)\s+(schedule)$/i) { # Some schedule?
&sendLog("$F: '$1' schedule recognized.") if $V>0;
$source = &Schedule($B); # Try to produce the schedule
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'post') {
$A = &tWord($data{Q},'') unless $A;
$a = lc($A);
&sendLog("$F: '$b' button recognized; arg='$A'/'$a'") if $V>0;
if ($a eq 'blog') {
&sendLog("$F: Blog post Arg='$A'.......................................") if $V>1;
$A = &tText($data{topic},'All');
&sendLog("$F: Arg (topic) is '$A'") if $V>0;
$source = &frame($b,'blog',$A);
return $source if $source;
} elsif ($a eq 'event') {
&sendLog("$F: Event post Arg='$A'/'$a' .......................................") if $V>1;
$A = &tText($data{Type},'');
&sendLog("$F: Arg (Type) is '$A'") if $V>0;
$source = &frame($b,'event',$A);
return $source if $source;
} elsif ($a eq 'event') {
&sendLog("$F: Post event page .......................................") if $V>1;
$source = &frame($B,$A);
return $source if $source;
} elsif ($a eq 'reply') {
&sendLog("$F: Post reply page .......................................") if $V>1;
$source = &frame($B,'blog',$A);
return $source if $source;
}
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'preview') {
$A = &tWord($data{Q},'') unless $A;
$a = lc($A);
&sendLog("$F: Preview button '$B' recognized; arg='$A'/'$a'") if $V>0;
if ($a eq 'blog') {
&sendLog("$F: Blog post/preview A='$A'.......................................") if $V>1;
$A = &tText($data{topic},'All');
&sendLog("$F: Arg (topic) is '$A'") if $V>0;
$source = &frame($b,'blog',$A);
return $source if $source;
} elsif ($a eq 'event') {
&sendLog("$F: Event preview A='$A'.......................................") if $V>1;
$A = &tText($data{Type},'All');
&sendLog("$F: Arg (Type) is '$A'") if $V>0;
$source = &frame($b,'event',$A);
return $source if $source;
} elsif ($a eq 'reply' || $a eq 'quote') {
&sendLog("$F: Preview $a to blog message ...................") if $V>1;
$prnt = $Parent || '';
&sendLog("$F: Preview $A to blog message '$prnt'") if $V>1;
$source = &frame($b,'blog',$A);
return $source if $source;
} elsif ($a eq 'event') {
&sendLog("$F: Preview event .......................................") if $V>1;
$source = &frame($B,$A);
return $source if $source;
}
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'refresh') {
&sendLog("$F: '$b' button recognized.") if $V>0;
require "events.pm";
if (defined($x = $data{events})) {
&sendLog("$F: Refresh '$x' page .......................................") if $V>1;
$source = &frame('Refresh','events',$x);
return $source if $source;
}
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'register' || $b eq 'new account') {
require "account.pm";
if ($nam = $data{uname}) {
&sendLog("$F: Register new user '$nam' .......................................") if $V>1;
$source = &frame('register','user',$nam);
return $source if $source;
} else {
&sendLog("$F: Show registration page .......................................") if $V>1;
$source = &frame('register','form','');
return $source if $source;
}
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'reply' || $b eq 'quote') { # Requests dealing with reply messages
require "blogsubs.pm"; # All the blog routines are here
&sendLog("$F: Reply ($b) recognized <=================") if $V>0;
if ($prnt = $Parent) {
&sendLog("$F: Parent '$prnt' found.") if $V>0;
} else {
&send_LW("$F: +++ Reply/Quote not yet implemented fully +++\n") if $V>1;
}
$source = &frame('blog',$b,$Parent);
&sendLog("$F: Button '$b' returned '$source'") if $V>0;
} elsif ($b eq 'save') {
&sendLog("$F: Save button '$B' '$b' recognized.") if $V>0;
if (($file = $data{file}) || ($file = $Argnam)) {
&sendLog("$F: Save file \"$file\" ...") if $V>0;
$source = &frame('save','file',$file);
return $source if $source;
&sendLog("$F: frame('save','file','$x') failed.") if $V>0;
} else {
&sendLog("$F: ### Don't know what to save.") if $V>0;
}
} elsif ($b eq 'send file' || substr($b,0,6) eq 'upload') {
&sendLog("$F: Upload button '$B' '$b' recognized.") if $V>0;
if ($x = $data{FileClass}) {
$Action = 'upload';
$Object = 'file';
$Argnam = 'Bulletin';
&sendLog("$F: Action='$Action' Class='$Class' Object='$Object' Argnam='$Argnam'") if $V>0;
}
$source = &frame('upload','file',$x);
return $source if $source;
&sendLog("$F: frame('upload','file','$x') failed.") if $V>0;
} elsif ($b eq 'send picture') {
&sendLog("$F: Send Picture button '$B' '$b' recognized.") if $V>0;
$source = &frame('upload','picture',$x);
return $source if $source;
&sendLog("$F: frame('upload','picture','$x') failed.") if $V>0;
} elsif ($b eq 'show') {
&sendLog("$F: Show button '$B' '$b' recognized.") if $V>0;
if ($x = $Argnam) { # Do we have a message id?
&sendLog("$F: Show blog msg '$x' ...") if $V>0;
$source = &frame('show','blog',$x);
return $source if $source;
&sendLog("$F: frame('show','blog','$x') failed.") if $V>0;
} elsif ($x = $data{doc}) {
&sendLog("$F: Show doc '$x' ...") if $V>0;
$Arg = $x;
$source = &frame('show','doc',$Arg);
return $source if $source;
&sendLog("$F: frame('show','doc',$Arg) failed.") if $V>0;
} elsif ($x = $Argnam) { # Do we have an argument (file)?
&sendLog("$F: Show arg '$x' ...") if $V>0;
$source = &frame('show','doc',$x);
return $source if $source;
&sendLog("$F: frame('show','doc','$x') failed.") if $V>0;
}
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'switch') {
&sendLog("$F: Switch '$b' button recognized.") if $V>0;
$A = &tWord($data{Q},'') unless $A;
&sendLog("$F: '$b' button recognized; arg='$A'.") if $V>0;
if ($A eq 'blog') {
&sendLog("$F: Switch blog topic .......................................") if $V>1;
$A = &tText($data{topic},'');
&sendLog("$F: topic='$A' B='$B'") if $V>0;
$source = &frame($B,'blog',$A);
return $source if $source;
}
&sendLog("$F: Button '$b' failed, arg '$A' not recognized.") if $V>0;
} elsif ($b eq 'update') {
&sendLog("$F: '$b' button recognized.") if $V>0;
if ($data{Q} eq 'user') {
&sendLog("$F: Update user info ...") if $V>0;
$unam = &tWord($data{uname});
$unum = &tInt($data{unumb});
$fnam = &tText($data{fname});
&sendLog("$F: Update user $unum/$unam '$fnam' info ...") if $V>0;
$source = &frame('Update user',$unam,$unum);
return $source if $source;
&sendLog("$F: frame('Update user''$uname','unumb') failed.") if $V>0;
}
&sendLog("$F: Button '$b' failed.") if $V>0;
} elsif ($b eq 'account' ||$b eq 'user') {
&sendLog("$F: '$b' button recognized.") if $V>0;
if (defined($U = $data{U})) {
&sendLog("$F: Show user '$U' ...") if $V>0;
$source = &frame('show','user',$U);
return $source if $source;
&sendLog("$F: frame('show','user','unumb') failed.") if $V>0;
}
} elsif ($b eq 'accounts' || $b eq 'all accounts') {
&sendLog("$F: '$b' button recognized; sending list of accounts.") if $V>0;
$source = &frame('show','accounts');
return $source if $source;
&sendLog("$F: frame('show','accounts') failed.") if $V>0;
} elsif ($b eq 'board of directors') {
&sendLog("$F: '$b' button recognized; sending list of board members.") if $V>0;
$Arg = $Argnam;
$source = &frame('show','doc',$Arg);
return $source if $source;
&sendLog("$F: frame('show','doc',$Arg) failed.") if $V>0;
} elsif ($b eq 'members') {
&sendLog("$F: '$b' button recognized; sending list of members.") if $V>0;
if (-f ($f = "$docdir/Members.html")) {
&sendLog("$F: $f exists; send it ...") if $V>0;
$Frame = ''; # This doc is shown unframed
&webpage($Content = $f);
return $f;
} else {
&sendLog("$F: $f does not exist.") if $V>0;
&acctList('M');
$source = &frame('show','members');
}
return $source if $source;
&sendLog("$F: frame('show','members') failed.") if $V>0;
} elsif ($b eq 'users') { # This may not be used any more
&sendLog("$F: '$b' button recognized; sending list of users.") if $V>0;
$source = &frame('show','users');
return $source if $source;
&sendLog("$F: frame('show','users') failed.") if $V>0;
} elsif ($b eq 'send password') { # Lost-password gimmick
&sendLog("$F: '$b' button recognized.") if $V>0;
$source = &frame('SendPW','users');
return $source if $source;
&sendLog("$F: frame('show','users') failed.") if $V>0;
}
if (-d "file/$B") {
&sendLog("$F: Directory file/$B requested.") if $V>0;
$data{D} = "file/$B"; # Add directory request to data
$source = &frame('list',$b);
return $source if $source;
&sendLog("$F: Button '$b' failed.") if $V>0;
}
&sendLog("$F: Button '$b' not recognized.") if $V>0;
return '';
}
sub dumpData {
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# This produces a symbolic dump of the %data table. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
local($nam, $val);
&sendLog("data: ########## %data ##########\n");
$Vpw = 1 unless defined $Vpw;
for $nam (sort keys %data) {
next if lc($nam) eq 'pswd' && $V<$Vpw; # Don't log password unless debugging
$val = $data{$nam};
&sendLog("data: # $nam: \"$val\"");
}
&sendLog("data: #################################\n");
}
sub EditButton {my $F='EditButton'; my($file) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# This produces the "edit" buttons at the right in a number of pages. It is #
# used to let the user edit the text object that's displayed. This is done to #
# give parts of the site a wiki-like functionality, letting anyone with edit #
# privileges to revise the text. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
&sendLog("$F: Called with file='$file'") if $V>0;
unless (-f $file) {
&send_LW("$F: ### No edit button; \"$file\" isn't a file ###") if $V>0;
}
if ($editors{$uname} || $admins{$uname}) {
&sendLog("$F: $unumb/$uname is allowed to edit.") if $V>1;
print "\t\n";
} else {
&send_LW("$F: ### [$uname can't edit]") if $V>3;
}
return '';
}
sub homePanel {my $F='homePanel'; my($name) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Show our home page in the content panel. The reason for the $name arg is #
# that we sometimes want to include some special string, such as the site #
# name, in the home page's name. But usually we don't. Homepage.html was the #
# original name, before we had the $L layout) variable. This routine came #
# about because different sites wanted different names for their "home" page, #
# often with both Full and Mobile formats. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
&sendLog("$F: Called for '$name', '$L' layout.") if $V>0;
if (-f ($x = "$docdir/$name$L.html")
|| -f ($x = "$docdir/$name.html")
|| -f ($x = "$docdir/Home$L.html")
|| -f ($x = "$docdir/Home.html")
|| -f ($x = "$docdir/HomePage.html")) {
&sendLog("$F: File '$x' exists.") if $V>0;
$Content = $contentfile = $x;
&webfile($x);
return $x;
}
&sendLog("$F: Can't find $docdir/$name$L.html file.") if $V>0;
return '';
}
sub Schedule {my $F='Schedule'; my($what) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Produce a schedule of some event type. If the arg is null, we produce all#
# events.
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
local($file,$source);
&sendLog("$F: Called for '$what' ...") if $V>0;
$source = &frame('show','events',$what);
&sendLog("$F: frame() returned '$source'") if $V>0;
return $source;
}
sub checkLogin {my $F='checkLogin';
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Do we have a login from this client's address? If so, that might be the #
# user that's talking to us. We might also look for some ways of verifying #
# this, but for non-admin users, it doesn't much matter. The return value is #
# a (uname,unumb) list, or null if we fail. But we shouldn't fail, because we #
# default to ('visitor',0). #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# First, is someone trying to log in or out?
if (($Pbase eq 'login') || defined($logarg = $data{login})) { # Is it a login attempt?
&sendLog("$F: Pbase='$Pbase' Login request ...") if $V>0;
&sendLog("$F: Pbase='$Pbase' Psuff='$Psuff' logarg='$logarg'") if $V>1;
$uname = $data{uname};
if ($uname =~ /^(.+):(\d)$/) { # Verbose level on param?
$uname = $1;
&sendLog("$F: Change V from $V to $2.\n") if $V>0;
$V = int($2);
}
$pswd = $data{pswd};
if ($unumb = &login($uname,$pswd,0)) {
&sendLog("$F: Logged in as '$unumb/$uname' from $RA.") if $V>0;
&saveSess($S,$unumb,$uname,$RA);
++$loggedin;
} else {
print "
\n";
&send_LW("### Login name or password incorrect ###") if $V>0;
&send_LW("### Attempted login as \"$uname\" failed ###") if $V>0;
print "
\n";
$uname = $Default{'uname'};
$unumb = $Default{'unumb'};
$S = '0';
}
} elsif (($Pbase eq 'logout') || defined($logarg = $data{logout})) { # Is it a logout attempt?
&sendLog("$F: Pbase='$Pbase' Logout request ..") if $V>0;
($ulog,$unumb,$uname,$uadr) = chkLogin($RA,$S);
&sendLog("$F: Log out ulog=$ulog unumb=$unumb uname=$uname uadr=$uadr") if $V>0;
if ($bkupfile = &logoutUser($unumb,$uname,$uadr,$S)) {
&sendLog("$F: Logout succeeded, session file is '$bkupfile'");
$uname = $Default{uname}; # change login to default
$unumb = $Default{unumb};
$S = '0';
$loggedout = 1; # Should block later tries to get the S and user info
} else {
&send_LW("$F: Logout failed.");
}
} else {
&sendLog("$F: Call chkLogin('$RA','$S') ...") if $V>0;
($ulog,$unumb,$uname,$uadr) = chkLogin($RA,$S);
if (defined($ulog) && defined($unumb) && defined($uname) && defined($uadr)) {
&sendLog("$F: ulog='$ulog'") if $V>0; # && defined $ulog;
&sendLog("$F: unumb='$unumb'") if $V>0; # && defined $unumb;
&sendLog("$F: uname='$uname'") if $V>0; # && defined $uname;
&sendLog("$F: uadr='$uadr'") if $V>0; # && defined $uadr;
&sendLog("$F: ulog='$ulog' unumb='$unumb' uname='$uname' uadr='$uadr'") if $V>0;
if ($ulog && $unumb && $uname && $uadr) {
&sendLog("$F: UID $unumb/$uname S $S from $uadr at $ulog.") if $V>0;
%UserInfo = &getAcctInfo($uname); # Load whatever is known about the user.
$unumb = &tText($UserInfo{unumb},'0');
$uname = &tText($UserInfo{uname},'???');
$fname = &tText($UserInfo{fname},'???_???');
&sendLog("$F: uname='$uname' unumb='$unumb' fname='$fname' V='$V' after getAcctInfo()") if $V>0;
&dumpTable("$uname UserInfo",\%UserInfo) if $V>1;
$loggedin = 1;
} else {
&send_LW("$F: No logged-in user found for $RA.") if $V>0;
$loggedin = 0;
}
} else {
&sendLog("$F: No login found.") if $V>0;
}
}
$uname = $Default{uname} unless defined $uname;
$unumb = $Default{unumb} unless defined $unumb;
&sendLog("$F: uname='$uname'") if $V>0;
&sendLog("$F: unumb='$unumb'") if $V>0;
return ($uname,$unumb);
}
sub showEvents {my $F='showEvents'; local($what) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Special kludge to generate a table of events, which we sometimes want to do #
# in the home page. The main problem is that we can't call eventsPanel() from #
# within the doc/Home* files, since the events.pm module may not have been #
# loaded. So we have this routine in the main module that loads events.pm and #
# then calls eventsPanel() to produce the table. Note that the caller has to #
# pass us the table description, which we pass on to eventsPanel() to tell it #
# which table to produce. Note also that we discard eventPanel's return #
# value, because it would be sent to the client and would show up at a funny #
# place on their screen. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
require "events.pm";
&sendLog("$F: Called ...") if $V>0;
&sendLog("$F: Action='$Action' Class='$Class' Object='$Object' Argnam='$Argnam'") if $V>0;
print "
\n";
&sendLog("$F: Call eventsPanel('$what')") if $V>0;
&eventsPanel($what,'');
print "
\n";
return ''; # Whatever is returned will be sent to client
}
sub Message {my $F='Message'; local($Act,$Obj,$path) = @_;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# This handles a request to do something with a message. The $Act arg says #
# what we are doing with it, the $Obj arg says what kind of message it is, #
# and the $path is the file name (null for new messages). The return value is #
# the "source" string saying who did the work, null if we failed for some #
# reason. #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
local($Data,@Data,$dir,$fil,$line,$lines,$v,$x);
local($act) = lc($Act) || 'show';
local($obj) = lc($Act) || 'doc';
$path = '' unless defined $path;
&sendLog("$F: Called for Act='$Act' Obj='$Obj' '$path'") if $V>1;
if ($path =~ m"^(.*)/([^/]*)$") {
$dir = $1;
$fil = $2;
&send_LW("$F: Message dir '$dir' file '$fil'") if $V>0;
} elsif ($path) {
$dir = '';
$fil = $1;
&send_LW("$F: Message file '$fil', directory not supplied.") if $V>0;
} else {
$dir = $fil = '';
&sendLog("$F: No file; assuming new message.") if $V>0;
}
print "
\n";
print "\n";
print "
\n";
return "$F()";
}
sub editDocFile {my $F='editDocFile'; local($Act,$path) = @_;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# This handles a request to edit a file. #
# We send a textarea widget that shows the file's contents.
# The user can edit it, and hit the preview or save buttons.
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
local($Data,@Data,$line,$lines,$v,$x);
local($act) = lc($Act);
&sendLog("$F: $Act '$path'") if $V>0;
unless (-f $path) {
&send_LW("$F: ### No file $path") if $V>1;
return 0;
}
if ($act eq 'edit') {
&send_LW("$F: Edit file '$path'") if $V>1;
unless (open(F,$path)) {
&send_LW("$P/$F: Can't read '$path' ($!)") if $V>1;
return 0;
}
&send_LW("$P/$F: Reading '$path' ...") if $V>1;
$lines = 0;
@Data = ();
&sendLog("$F: Read '$path' ...") if $V>4;
while ($line = ) {
$line =~ s/[\r\s]+$//; # Trim trailing white stuff
&sendLog("$F: LINE: {$line}") if $V>1;
push @Data, $line;
++$lines;
}
close F;
} elsif ($act eq 'save') {
&send_LW("$F: Save file '$path'") if $V>1;
unless ($Data = $data{data}) {
&send_LW("$F: ### No data found ###") if $V>0;
return '';
}
&sendLog("$F: data={$Data}") if $V>1;
@Data = split("\n",$Data);
unless (open(F,">$path")) {
&send_LW("$F: ### Can't write '$path' [$!]") if $V>0;
return '';
}
for $line (@Data) {
&sendLog("$F: LINE: {$line}") if $V>1;
++$lines;
print F "$line\n";
}
close F;
&send_LW("$F: Wrote data to file '$path'") if $V>0;
} elsif ($act eq 'preview') {
&send_LW("$F: Preview file '$path'") if $V>1;
unless ($Data = $data{data}) {
&send_LW("$F: ### No data found ###") if $V>0;
return '';
}
&sendLog("$F: data={$Data}") if $V>1;
@Data = split("\n",$Data);
for $line (@Data) {
&sendLog("$F: LINE: {$line}") if $V>1;
++$lines;
}
}
print "
\n";
print "\n";
print "
\n";
return "$F()";
}
sub editPanel {my $F='editPanel'; local($obj,$arg,$file) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# This generates a frame for the "edit" content, and then calls editTable() #
# to produce the edit content. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
&sendLog("$F: Called with obj='$obj' act='$act' file='$file'") if $V>0;
if ($obj eq 'blog') {
&sendLog("$F: obj=blog.") if $V>0;
if ($act eq 'edit') {
&sendLog("$F: obj=blog act=edit file='$file'") if $V>0;
require "blogsubs.pm"; # All the blog routines are here
$Content = "editBlogFile($file)";
&sendLog("$F: Content='$Content'") if $V>1;
&editBlogFile($file,$how);
} else {
}
} else {
}
return $F;
}
sub frameFtr {my $F='frameFtr';
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
}
sub frameHdr {my $F='frameHdr';
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
}
sub max {my $F='max';
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Scan the arg list for numbers (optional '-', digits including at most one #
# '.'), returning the value of the largest number. Undefined args are treated #
# as zero. The return value is undef if no arg contains at least one digit. #
# Note that the return value is a string, not a numeric type. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
local($a,$x,$v); # arg, result
for $a (@_) { # Run thru the arg list
$x = $a || '0'; # Null/undef args are zero
&sendLog("$F: Test '$x'") if $V>5;
if (($x =~ /(-*\d*.\d+)/) # Test for a decimal number
|| ($x =~ /-*(\d+)/)) { # Test for an integer
if (!defined($v) || ($x > $v)) { # Both defined; compare them
$v = $1; # Remember the numeric substring
}
} else {
&sendLog("$F: Called with nonnumeric arg '$x'") if $V>1;
}
}
&sendLog("$F: Return '$v'") if $V>2;
return $v;
}
sub fileTable {my $F = 'fileTable'; local($class) = @_;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Produce a list of the files in the given file/$class directory. #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
my($base,$dir,$tmsg,@info,$line,$lines,$name,$file,$dataf,$files,@files,$suff);
$class = 'Misc' unless $class;
&sendLog("$F: Called for class='$class'") if $V>1;
@files = sort glob("file/$class/*");
$files = int(@files);
&sendLog("$F: We found $files files in file/$class/") if $V>1;
print "\n";
print "
\n";
print " $orgname $class:\n";
print "\n";
while (@files) {
$file = pop @files;
@info = ();
if (($dir,$name) = ($file =~ m"(.*)/+([^/]+)[\r\s]*$")) {
if (($base,$suff) = ($name =~ /(.*)\.(\w+)$/)) {
next if $suff eq 'info';
} else {
$base = $name;
$suff = '';
}
print "\n";
print " \n";
if (-f ($dataf = "$dir/$base.info")) {
# @info = &fil2html($dir,"$base.info");
&sendLog("$F: Read info file '$dataf' ...") if $V>0;
$lines = 0;
if (open(DATA,$dataf)) {
while ($line = ) {
$line =~ s/[\r\s]*$/ /;
next if !$showAllInfo && $line =~ /^(From|Poster):/;
&sendLog("$F: LINE: {$line}") if $V>1;
push @info, $line;
++$lines;
}
close DATA;
} else {
&sendLog("$F: ### Can't read '$dataf' ###") if $V>0;
&sendLog("$F: ### No info about file '$file' ###") if $V>0;
}
print "\n";
print " \n";
}
print "\n";
}
}
print "
\n";
return "$F()"; # Tell frame that we produced the content
}
sub flyerPanel {my $F='flyerPanel'; local($job,$act,$arg) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# This just generates a table of the flyer .pdf files so the user can click #
# on one. It assumes that the flyers are in the file/Flyers/ directory, have #
# 'flyer' or 'Flyer' in the names, and have a .pdf suffix. #
# #
# Kludge: Some users just want to be shown the one "current" flyer. If job is #
# just "flyer", we list just the most recent flyer, and then give them a #
# "Flyers" button that will get the rest. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
local($f,$file,$flyerpat,$flyers,@flyers,$source);
&sendLog("$F: Called for job='$job' act='$act' arg='$arg'") if $V>0;
$Content = 'flyerPanel()';
&sendLog("$F: Content='$Content'") if $V>1;
if ($job eq 'flyer') { # Some sites want a "single current flyer" button
if ($source = fileTable('Flyer')) {
&sendLog("$F: source='$source'") if $V>1;
return $source;
}
}
if ($job eq 'flyers') { # Most sites have either no or many flyers
if ($source = fileTable('Flyers')) {
&sendLog("$F: source='$source'") if $V>1;
return $source;
}
}
# The rest is the original code that just lists the "flyer[s]" files. This
# is probably no longer in use, though this should be verified before we
# delete the rest of this routine.
$flyerpat = "file/Flyers/*[Ff]lyer*.pdf";
&sendLog("$F: flyerpat=/$flyerpat/") if $V>0;
@flyers = glob $flyerpat;
print "
\n";
print "$orgname Flyers\n";
print "\n";
while ($f = pop @flyers) {
($file = $f) =~ s".*/""; # File name without directory
print "\n";
++$flyers;
&sendLog("$F: Flyer $flyers: '$file'") if $V>0;
last if $job eq 'flyer';
}
unless ($flyers > 0) {
print "\n";
}
print "
\n";
# if ($job eq 'flyer') { # Send button to get list of all the flyers
# print " \n";
# }
print "
\n";
return $F;
}
sub op {my $F='op'; local($Op) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# This is our dispatcher for an "query", usually from the $data{Q} form #
# param. We look at the requested query and assorted other data, and call #
# various routines to process the request. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
my($act,$arg,$file,$frame,$msgid,$msgpath,$nam,$op,$ops,$source,$Val,$val);
$source = 0; # Failure; set >0 for success.
$op = lc($Op);
&sendLog("$F: Op='$Op' op='$op' =======================================") if $V>0;
if ($op eq 'all') {
&sendLog("$F: 'all' op ...") if $V>0;
if (($act = $data{event}) =~ /^Add/i) {
&sendLog("$F: Button: Adding a new event") if $V>0;
$source = &Frame('event','new',$val);
} elsif (($act = $data{events}) eq 'Refresh') {
&sendLog("$F: show event page .......................................") if $V>1;
require "events.pm";
$source = &Frame('All Events');
}
} elsif ($op eq 'login') {
&sendLog("$F: login op ...") if $V>0;
$source = &opLogin();
} elsif ($op eq 'mobile') {
&sendLog("$F: mobile op ...") if $V>0;
$source = &opMobile();
} elsif ($op eq 'blog') {
&sendLog("$F: Blog operation ...") if $V>0;
require "blogsubs.pm";
$ops = 0;
$act = $data{post}; # This will usually be undefined
if (defined($act) && ($act eq 'Post')) { # Post a reply on a blog message
&sendLog("$F: Post reply .......................................") if $V>0;
if ($file = $data{parent}) {
&sendLog("$F: Post a reply to blog msg '$file'") if $V>1;
$source = Frame('blog','postreply',$file);
++$ops;
} else {
&sendLog("$F: No parent message found in data.") if $V>0;
$source = &Frame('blog','post',$T); # Post message to current topic
}
} else {
&sendLog("$F: op=blog, look in names for \"op:arg\" name ...") if $V>1;
for $nam (@names) { # Scan the names for interesting params
$Val = $data{$nam};
$val = lc($Val);
&sendLog("$F: nam='$nam' Val='$Val' val='$val'") if $V>1;
if ($nam =~ /^op:(.*)$/) { # op:messageid operates on a blog message
$file = $1;
&sendLog("$F: val='$val' '$file' ++++++++++++++++++++++++++++++") if $V>0;
++$ops;
if ($val eq 'edit') { # Edit the blog message
$source = &Frame('blog','edit',$file);
} elsif ($val eq 'show') { # Show the blog message (and replies)
&sendLog("$F: Show blog message $file ...") if $V>1;
$source = &Frame('blog','tree',$file);
} elsif ($val eq 'reply') { # Reply to the blog message, without quote
&sendLog("$F: Reply to a blog message [$val].") if $V>1;
$source = Frame('blog',$val,$file); # Send reply form with or w/o quote
} elsif ($val eq 'quote') { # Reply to the blog message, with quote
&sendLog("$F: Quote a blog message [$file].") if $V>1;
$source = Frame('blog',$val,$file); # Send reply form with or w/o quote
}
} elsif ($nam eq 'save') { # Is this still in use?
if ($path = $data{path}) {
&send_LW("$F: Save to '$path'") if $V>1;
&saveBlogFile($path);
} else {
&send_LW("$F: Save path not found in form data.") if $V>0;
}
} else {
&sendLog("$F: Ignore $nam=\"" . &strenc($val) . "\".") if $V>1;
}
}
}
if ($ops < 1) {
&sendLog("$F: show blog page .......................................") if $V>0;
&Frame('blog','show',$T); # Show the current topic
}
} elsif ($op eq 'event') {
&sendLog("$F: event ...") if $V>0;
require "events.pm";
if (($val = lc($data{op})) eq 'preview') {
&sendLog("$F: event preview ...") if $V>0;
&Frame('event','preview');
} elsif ((($val = lc($data{op})) eq 'send') || ($val eq 'post')) {
&sendLog("$F: new event to be posted ...") if $V>0;
&Frame('event','post');
} else {
&sendLog("$F: Search the data for an op:arg name ...") if $V>1;
for $nam (@names) {
if (($act,$arg) = ($nam =~ /^(\w+):(.*)$/)) {
$val = $data{$nam};
&sendLog("$F: act='$act' arg='$arg' val='$val' -------------------------") if $V>0;
if ($act eq 'edit') {
&sendLog("$F: Call editEvent('$act',...)") if $V>1;
$source = editEvent($act,$arg) || '';
&sendLog("$F: Return '$source'") if $V>1;
return $source;
} elsif ($act eq 'delete') {
if ($val eq 'Really delete') {
&sendLog("$F: Really delete '$arg'") if $V>1;
&Frame($act,$val,$arg);
} else {
&sendLog("$F: Call editEvent('$act',...)") if $V>1;
$source = editEvent($act,$arg) || '';
&sendLog("$F: Return '$source'") if $V>1;
return $source;
}
}
}
}
$source = 0; # Failure
}
} elsif ($val = $data{event}) {
&sendLog("$F: Button:event='$val' ...") if $V>0;
require "events.pm";
if (lc($val) eq 'add a new event') {
&sendLog("$F: Button: Adding a new event") if $V>0;
$source = &Frame('event','new',$val);
} else {
&sendLog("$F: Button event='$val' not recognized.") if $V>0;
}
} elsif ($op eq 'reply' || $op eq 'quote') { # Requests dealing with reply messages
require "blogsubs.pm"; # All the blog routines are here
&sendLog("$F: Reply ($op) ...") if $V>0;
for $nam (@names) {
$Val = $data{$nam};
$val = lc($Val);
if ($nam =~ /^op:(.*)$/) { # op:messageid operates on a blog message
$file = $1;
&sendLog("$F: val='$val' '$file'") if $V>1;
if ($val eq 'edit') { # Edit the blog message
&sendLog("$F: edit .......................................") if $V>1;
&sendLog("$F: Edit blog message '$file' ...") if $V>1;
$source = &Frame('blog','edit',$file);
} elsif ($val eq 'reply' || $val eq 'quote') { # Reply on the blog message
&sendLog("$F: Reply/quote form .......................................") if $V>1;
&sendLog("$F: Reply on blog message '$file' ...") if $V>1;
$source = Frame('blog',$val,$file); # Send reply form with or w/o quote
} elsif (lc($data{preview}) eq 'preview') { # Preview a reply
&sendLog("$F: Reply/preview .......................................") if $V>1;
$subj = $data{subj} || $data{subject} || '???';
$R = $data{R} || 0;
&sendLog("$F: R='$R'") if $V>1;
&sendLog("$F: op='$op'") if $V>1;
&sendLog("$F: subj='$subj'") if $V>1;
&sendLog("$F: file='$file'") if $V>1;
&sendLog("$F: nam='$nam'") if $V>1;
&sendLog("$F: uname='$uname'") if $V>1;
$source = Frame('blog','preview',$file);
} else {
&send_LW("$F: +++ Replies not yet implemented fully +++\n") if $V>1;
}
}
}
} elsif ($op eq 'event' || $op eq 'events' || $op eq 'refresh') {
&sendLog("$F: show event page .......................................") if $V>1;
require "events.pm";
$source = &Frame('events');
} elsif ($op eq 'post') {
&sendLog("$F: show post page .......................................") if $V>1;
} elsif ($op eq 'register') {
require "blogsubs.pm"; # All the blog routines are here
if ($nam = $data{uname}) {
&sendLog("$F: Register new user '$nam' .......................................") if $V>1;
$source = &Frame('register','user',$nam);
} else {
&sendLog("$F: Show registration page .......................................") if $V>1;
$source = &Frame('register','form','');
}
} elsif ($op eq 'show') { # Show the user something
&sendLog("$F: Show .......................................") if $V>1;
require "blogsubs.pm";
if ($docname = $data{D}) { # Request to show a document?
&send_LW("$F: Frame='$Frame'") if $V>1;
&send_LW("$F: docname='$docname'") if $V>1;
if (-f $docname) {
&Frame('show','doc',$docname);
} elsif (-f ($docpath = "doc/$docname")) {
&send_LW("$F: docpath='$docpath'") if $V>1;
&Frame('show','doc',$docpath);
} else {
&send_LW("$F: Don't know document file to show.") if $V>1;
}
} elsif ($msgid = $data{M}) { # Request to show a blog message?
&sendLog("$F: msgid='$msgid'") if $V>1;
&sendLog("$F: Frame='$Frame'") if $V>1;
$source = &Frame('blog','tree',$msgid);
} else {
&send_LW("$F: Don't know what to show.") if $V>1;
}
} elsif ($op eq 'user') {
&sendLog("$F: op='user' ........................................") if $V>0;
if ($data{update} eq 'Update') {
&sendLog("$F: Update user info ...") if $V>0;
if ($idname = &tWord($data{uname})) {
&sendLog("$F: Update account $idname info ...") if $V>0;
$source = Frame('user','update',$idname);
} elsif ($uname) {
&sendLog("$F: Update user $unumb/$uname info ...") if $V>0;
$source = Frame('user','update',$uname);
} else {
&send_LW("$F: ### Can't figure out who to update.\n") if $V>0;
}
} else {
&sendLog("$F: Default: Show user info ...") if $V>0;
$source = &Frame('user','show',$uname);
}
} elsif ($blogOps{$op}) {
&sendLog("$F: blog op '$op' ...") if $V>1;
&Frame('blog','show',$op); # Show the current topic
} elsif (-f ($file = "doc/$op")) {
&sendLog("$F: File '$file' .......................................") if $V>1;
$frame = (-f "doc/$framename$L.html")
? "doc/$framename$L.html"
: "doc/MainPage.html";
&sendLog("$F: frame='$frame'") if $V>1;
&sendLog("$F: file='$file'") if $V>1;
&Frame('show','doc',$file);
} else {
&send_LW("$F: Can't handle op='$op'.") if $V>1;
}
return $source;
}
sub opLogin {my $F='opLogin';
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# One way to get a Login prompt is with the form param Q=login, which leads #
# here. All we do is send the client our Login form, wrapped in our standard #
# pretty frame. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
local($f) = "$docdir/Login.html";
&sendLog("$F: Called.") if $V>0;
if (-f $f) {
$Content = $contentfile = $f; # Send the user this document
&sendLog("$F: Frame='$Frame'") if $V>0;
&sendLog("$F: Content='$Content'") if $V>1;
&Frame('show','doc',$Content);
}
return '';
}
sub opMobile {my $F='opMobile';
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Setup for "mobile" devices with small screens. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
local($f) = "$docdir/HomeM.html";
&sendLog("$F: Called.") if $V>0;
if (-f $f) {
$L = 'M'; # Switch us to "Mobile" layout
&send_LW("$F: L='$L' A='$Q' S='$S' T='$T' [opMobile()]") if $V>1;
$Frame = $framefile = "$docdir/$framename$L.html"; # Default frame
$Content = $contentfile = $f; # Send the user this document
&send_LW("$F: Frame='$Frame'") if $V>0;
&sendLog("$F: Content='$Content'") if $V>1;
return &Frame('show','doc',$Content);
}
return '';
}
sub postPanel {my $F='postPanel'; local($op,$parent) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# This generates a frame for the "post" and "reply" content, and then calls #
# postTable() to produce the post content. For a "post" command, we just get #
# the data and user info, and we must create the new blog message. For a #
# reply, we also get the second $parent arg, which should be the message id #
# for the parent message. We'll create a message the same way, but we'll also #
# link the two message files together via Reply: and Parent: header lines. #
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
require "blogsubs.pm"; # All the blog routines are here
&sendLog("$F: op='$op' parent='$parent'") if $V>1;
unless ($parent) {
$parent = &tWord($data{parent} || $data{Parent},''); # Parent message id, if any
&sendLog("$F: parent='$parent'") if $V>1;
}
if ($bloggers{$uname} || $editors{$uname} || $admins{$uname}) {
&sendLog("$F: User $unumb/$uname is a blogger.") if $V>1;
&sendLog("$F: Parent file is '$parent'") if $V>1;
return &newMsg($parent);
}
&send_LW("$F: ### User $unumb/$uname isn't a blogger.") if $V>1;
return undef;
}
sub quit {local($stat) = @_;
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
# Produce some more debug info, close out the HTML tags, and exit.
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = #
local($func,$file,$line) = caller;
&sendLog("$P: ================ Finish up and exit $stat ...") if $V>0;
# $func = '?' unless defined $func;
# $file = '?' unless defined $file;
# $line = '?' unless defined $line;
print "
'$Frame'+'$Content'
\n" if $V>1;
print "Quit with status $stat. \n" if $V>0 && $stat;
&sendLog("$P: Quit in $file, $func line $line with status $stat.") if $V>0;
&sendLog("$P: End of '$orgabbr' '$orgname' page.\n") if $V>0;
print "