#!/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 "
\n"; print "
$warning
\n" if $warning; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # ### It is now safe to write HTML to the client ### # t= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # Session data: &sendLog("$P: Look for session info [V=$V] ...") if $V>5; $S = &findSID(); # Session id number (0 for users not logged in) &sendLog("$CYMD $HMS P=$$ '$P' L='$L' S='$S' V=$V [session data].\n") if $V>0; &sendLog("$P: Save unumb='$unumb' uname='$uname' fname='$fname' IP=$RA.") if $V>1; $loggedin = 0; # True after a successful login $loggedout = 0; # True after a successful logout if (($arg = $data{V}) && ($arg =~ /^(\d+)/)) { $V = &max(int($1),$V); &sendLog("$P: V='$V' (session/user info)") if $V>5; } if (($arg = $data{S}) && ($arg =~ /^(\d+)/)) { $S = int($1); $maintitle .= " [$S]" if $V>2; } elsif (($arg = $data{S}) && ($arg =~ /^(\d+)/)) { $S = int($1); $maintitle .= " [$S]" if $V>2; } # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # print "$0: P='$P' Pbase='$Pbase' Psuff='$Psuff'
\n" if $V>3; if ($pathinfo = $ENV{'PATH_INFO'}) { print "$P: pathinfo='$pathinfo'
\n" if $V>1; } else { print "$P: No PATH_INFO data.
\n" if $V>3; } # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # Special case: Before we check for requested queries, we check to see if we # have a logged-in user. This entails checking to see whether this request is # a login attempt. #sendLog("$P: ================ ____ ...") if $V>0; &sendLog("$P: ================ Check for logged-in user ...") if $V>0; ($uname,$unumb) = &checkLogin(); # Do we have an active login? &sendLog("Caller: unumb='$unumb' uname='$uname' fname='$fname'") if $V>0; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # Now dump the form and environment stuff. We waited until now to do it # because during debugging we often want to display this data to special # users. &sendLog("$P: ================ Dump the parameter info ...") if $V>0; &sendLog("$P: Vform='$Vform' Venv='$Venv'") if $V>0; &showFormData() if $V>$Vform; &showEnv() if $V>$Venv; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # Figure out if we have an active session. If the user has a session file, we # assume that this is a continuation of that session. But mostly, we look for # a session-id number in a few places. # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # &sendLog("$P: ================ Look for session info ...") if $V>0; &send_LW("$Pdir/$P: Session $S user $unumb/$uname from RA=$RA Venv=$Venv V=$V.") if $V>2; if ($S) { &send_LW("$P: Found session $S user $unumb/$uname from RA=$RA V=$V.") if $V>3; } elsif ($loggedout) { &send_LW("$P: Logged out; accepting S='$S'") if $V>1; } else { &send_LW("$P: Check for session $S ...") if $V>3; $S = &findSID(); &send_LW("$P: Session ID: '$S'") if $V>2; &loadSess($S); unless ($ulog = $Session{'when'}) { $ulog = $Session{'when'} = "$CYMDHMS $TZ"; } &sendLog("$CYMDHMS P=$$ '$P' from RA=$RA at $ulog S=$S V=$V V=$V.\n") if $V>1; } if (defined $debuggers{$uname}) { &sendLog("$P: debuggers{$uname}='" . $debuggers{$uname} . "'") if $V>1; $V = &max($debuggers{$uname},$V); # Set verbose level for this user &sendLog("$P: V=$V from debuggers{$uname}") if $V>0; } &sendLog("$P: V='$V' Vuser='$Vuser' unumb='$unumb' uname='$uname'") if $V>0; if ($unumb > 0) { if ($V> 0) { &showUser($uname,$unumb,$S,$RA,$ulog); } else { &sendLog("$P: Logged in as '$uname' [user $unumb session $S]\n") if $V>0; } } else { &sendLog("$P: Not logged in.") if $V>0; } # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # Set up some framing stuff. Most of the code here has been moved away ... # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # &sendLog("$P: ================ Framing ...") if $V>0; &send_LW("$P: docdir='$docdir'") if $V>2; &send_LW("$P: layout='$L' framename='$framename' docname='$docname'") if $V>2; $Frame = $framefile = "$docdir/$framename$L.html"; # Default frame file $Content = $contentfile = ''; # List of files used for "content" $source = ''; # Returned by most routines to explain where they got the content &sendLog("$P: Frame='$Frame'") if $V>1; &sendLog("$P: Content='$Content'") if $V>1; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # Special case: Called with no form args. We send the home page for whatever # # layout we've guessed is appropriate for the client. This is also where we # # handle a "cold call" without any form params, by sending our "home page". # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # $x = int(@names); &sendLog("$P: There are $x things in %data.") if $V>0; unless ($x > 0) { # No form data? $contentname = 'Home' unless defined $contentname; &sendLog("$P: No form data; show '$contentname$L' doc.") if $V>0; $Content = &frame('show','doc',"$contentname$L.html"); &quit(0); } # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # Check for the 'B' param, which is produced by most buttons to say which # # operation is requested. # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # &sendLog("$P: ================ Check for a Button push ...") if $V>0; if ($B ) { # Was a button pushed? &sendLog("$P: Button B='$B' b='$b' pushed.") if $V>0; if ($source = &Button($B)) { &sendLog("$P: Button returned '$source'") if $V>0; &quit(0); } &sendLog("$P: Button returned null.") if $V>1; } &sendLog("$P: data{B} is null.") if $V>1; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # The 'op' form param is a command to perform some operation. Depending on # # the specific operation, there should be further params in %data, but they # # can mostly be handled by the subroutines. Here, we mostly just bounce the # # request to the frame() - or the obsolete Frame() - routine, which draws the # # page frame and calls content-specific subroutines to fill in the content # # block. # # NOTE: We should rewrite all the calls of Frame() to call frame() instead. # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # &sendLog("$P: ================ Check the op variable ...") if $V>0; &sendLog("$P: data{op}='$data{op}'") if $V>0 && defined $data{op}; if ($Op = $data{op} || '') { # Perform an operation of some sort &sendLog("$P: Op='$Op'") if $V>0; $Op = &tText($Op,''); # Make sure it's untainted $op = lc($Op); # Canonicalize to lower case $Q = $data{Q} || ''; # Preserved query topic &sendLog("$P: Op='$Op' op='$op' Q='$Q'") if $V>0; if ($op eq 'showUser') { &sendLog("$P: Show user info.") if $V>0; &showUser($uname,$unumb,$S,$RA,$ulog); # } elsif ($op eq 'events') { # Request for the Events table # &sendLog("$P: Op='$Op' op='$op' ........................................") if $V>0; ## $Content = $source = &Frame($Op); ## &sendLog("$P: Frame returned '$source'") if $V>0; # &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 ($op eq 'all events') { # Request for the Events table # &sendLog("$P: op='$op' ........................................") if $V>0; # $source = &Frame($Op); } elsif ($op eq 'flyer') { # Request for Flyer (just one) &sendLog("$P: op='flyers' ........................................") if $V>0; $source = &Frame($op); } elsif ($op eq 'flyers') { # Request for Flyers (all of them) &sendLog("$P: op='flyers' ........................................") if $V>0; $source = &Frame($op); } elsif ($op eq 'home') { # Request for the site's home page &sendLog("$P: op='home' ........................................") if $V>0; $Content = $contentfile = "$docdir/Home$L.html"; &sendLog("$P: Content='$Content'") if $V>1; $source = &frame('show','doc',$Content); &quit(0); } elsif ($op eq 'login') { # Request for the login form &sendLog("$P: op='login' ........................................") if $V>0; $Content = $contentfile = "$docdir/Login$L.html"; &sendLog("$P: Content='$Content'") if $V>0; $source = &Frame('show','doc',$Content); &quit(0); } elsif ($op eq 'blog' || $op eq 'news') { &sendLog("$P: op='blog/news' ........................................") if $V>0; if ($post = $data{post}) { &sendLog("$P: op='$op' post='$post'") if $V>0; $source = &Frame('blog','post',$T); # Post message to current topic } elsif ($Q eq 'next') { &sendLog("$P: Next ........................................") if $V>0; &sendLog("$P: Next op='$op' Q='$Q'") if $V>0; $source = &frame('blog','next',$T); # Post message to current topic &sendLog("$P: frame('blog','next','$T') returned '$source'") if $V>0; } else { &sendLog("$P: op='$op' Show the message.") if $V>0; $source = &frame('blog','show',$T); # Show the current topic } } elsif ($op eq 'mobile') { &sendLog("$P: op='mobile' ........................................") if $V>0; $L = 'M'; # Change the layout to Mobile $Frame = $framefile = "$docdir/$framename$L.html"; # Default frame file # } elsif ($op eq 'refresh') { # &sendLog("$P: Refresh event page .......................................") if $V>1; # require "events.pm"; # $source = &Frame('events'); } elsif ($op eq 'register') { # Request for the user registration form &sendLog("$P: op='register' ........................................") if $V>0; $Content = $contentfile = "$docdir/Register$L.html"; &sendLog("$P: Content='$Content'") if $V>1; $source = &Frame('show','doc',$Content); &quit(0); } elsif ($op eq 'user') { &sendLog("$P: op='user' ........................................") if $V>0; if ($data{update} eq 'Update') { &sendLog("$P: Update user $unumb/$uname info ...") if $V>0; $source = acctUpdate($uname,$unumb); } else { &sendLog("$P: Default: Show user info ...") if $V>0; $source = &Frame('user','show',$uname); } } else { &sendLog("$P: Op='$Op' op='$op' unknown.") if $V>0; } } $source = '' unless defined $source; &sendLog("$P: source='$source'") if $V>0; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # The above can't be used for some tasks. HTML is a bit weird in how it # # passes us different data from various sorts of invocations (, , # # etc. Here we try a few more schemes to figure out what query has been # # requested, and call the appropriate routine to handle it. # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # &sendLog("$P: ================ Check the Q variable ...") if $V>0; &sendLog("$P: data{Q}='" . $data{Q} . "'") if $V>1 && defined($data{Q}); &sendLog("$P: data{D}='" . $data{D} . "'") if $V>1 && defined($data{D}); &sendLog("$P: data{op}='" . $data{op} . "'") if $V>1 && defined($data{op}); &sendLog("$P: data{doc}='" . $data{doc} . "'") if $V>1 && defined($data{doc}); if ($source) { &sendLog("$P: Done by '$source'; further testing skipped.") if $V>0; } elsif ($Q = $data{Q}) { # The 'Q' param is the primary query &sendLog("$P: Q='$Q'") if $V>0; if ($Q eq 'blog') { &sendLog("$P: Blog query ...") if $V>0; if ($txt = $data{blogtext}) { &sendLog("$P: Blog query {$txt}") if $V>0; $source = &frame('post',$Q,$txt); } &send_LW("$P: [Q='$Q' not understood]") if $V>0; } elsif ($Q eq 'show') { &sendLog("$P: Show something ...") if $V>0; if ($op = $data{op}) { &sendLog("$P: Show op='$op' ...") if $V>0; $Content = $source = &frame('show','event',$op); } else { &send_LW("$P: Query='show' but no 'op' variable found in data.") if $V>0; } } else { $source = &op($Q) || ''; &sendLog("$P: source='$source'") if $V>2; } } else { &sendLog("$P: No Q variable.") if $V>0; if (defined($doc = $data{D})) { # The 'D' param displays a (HTML) document &sendLog("$P: Show doc='$doc'") if $V>0; $source = &Frame('show','doc',$doc); } elsif (defined($doc = $data{doc})) { # Display a (HTML) document &sendLog("$P: Show doc='$doc'") if $V>0; $source = &Frame('show','doc',$doc); } elsif ($act = $data{event}) { # Was an 'event' button pushed? &sendLog("$P: Button:event act='$act'") if $V>0; require "events.pm"; $source = &Frame('event',$act); &sendLog("$P: Frame('event','$act') returned '$source'") if $V>0; } elsif ($act = $data{events}) { # Was an 'events' button pushed? &sendLog("$P: Button:events act='$act'") if $V>0; require "events.pm"; $source = &Frame('events',$act); &sendLog("$P: Frame('events','$act') returned '$source'") if $V>0; } else { # Did the referrer give us frame or doc name? &sendLog("$P: Scan for type:file ...") if $V>0; for $nam (@names) { $val = $data{$nam}; &sendLog("$P: Test nam='$nam' val='$val' ...") if $V>0; if ($nam =~ /^(\w+):(.*)$/) { # op:arg pair? $fld = $1; $arg = $2; &sendLog("$P: Got '$fld:$arg' ...") if $V>0; if ($fld eq 'doc') { &sendLog("$P: Show doc '$arg'"); $Content = $source = &frame('show','doc',$arg); } elsif ($fld eq 'event') { &sendLog("$P: Event $val '$2'"); $Content = $source = &frame('event',$val,$arg); } else { &sendLog("$P: Skip $nam='$val'"); } } } &sendLog("$P: framefile='$framefile'") if $V>0; &sendLog("$P: contentfile='$contentfile'") if $V>0; &sendLog("$P: Frame='$Frame'") if $V>0; &sendLog("$P: Content='$Content'") if $V>0; } } $source = '' unless defined $source; unless ($source) { &sendLog("$P: Look for default frame and content ...") if $V>1; if ($x = $data{frame}) { $Frame = $framefile = "$docdir/" . $x; &send_LW("$P: Frame='$Frame'") if $V>1; } &send_LW("$P: framename='$framename' docname='$docname'") if $V>2; if (-f ($x = $docpath) || -f ($x = "$docdir/$docname$L.html")) { &sendLog("$P: \"$x\" exists.") if $V>1; $Content = $contentfile = $docpath = $x; &sendLog("$P: docname=\"$docname\" docpath=\"$docpath\"") if $V>1; } elsif (-f "$docdir/$framename$L.html") { &sendLog("$P: $docdir/$framename$L.html exists.") if $V>1; $Content = $contentfile = "$docdir/Home$L.html"; &sendLog("$P: framefile='$framefile'") if $V>1; &sendLog("$P: Frame='$Frame'") if $V>1; &sendLog("$P: contentfile='$contentfile'") if $V>1; &sendLog("$P: Content='$Content'") if $V>1; } else { &send_LW("$P: Can't find anything to do.") if $V>0; } } # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # That completes our scan of the form params for commands. This looks like a # # "cold call", with no instructions. In that case, we just send them our home # # page, and wait for further requests. # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # &sendLog("$P: ================ Give up and send a home page ...") if $V>0; if ($source) { # Have we done an query yet? &send_LW("$P: source='$source' [after op testing]") if $V>2; } else { &sendLog("$P: No query requested; checking for default files ...") if $V>1; &sendLog("$P: Frame '$Frame' is a file.") if -f $Frame && $V>1; &sendLog("$P: Content '$Content' is a file.") if -f $Content && $V>1; if (-f $Frame && -f $Content) { &sendLog("$P: Frame='$Frame'") if $V>1; &sendLog("$P: Content='$Content'") if $V>1; &frame('show','doc',$Content); print "$P: Page '$Frame'+'$Content' done.
\n" if $V>3; } else { &send_LW("$P: Frame '$Frame' not a file.") if !-f $framefile && $V>1; &send_LW("$P: Content '$Content' not a file.") if !-f $Content && $V>1; } } # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # if ($V>3 || $showdir) { &sendLog("$P: ================ Show debug info ...") if $V>0; print "
\n"; print "Here are the things at this site:
\n"; unless (opendir(CWD,".")) { print "\n*** Can't read current directory\n" if $V>1; &quit(1); } print "\n"; for $f (sort readdir(CWD)) { next if substr($f,0,1) eq '.'; $desc = $Descr{$f} || '?'; $suff = (-d $f) ? '/' : ''; &sendLog("$P: Descr{$f}='" . ($Descr{$f} || '') . "'\n") if $V>6; print "\n"; } print "
$f$suff$desc
\n"; closedir(CWD); } # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # &sendLog("$P: ================ Give up ...") if $V>0; &sendLog("$CYMDHMS P='$P' PID=$$ done.\n") if $V>1; &quit($exitstat); # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # sub IDline { # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # Produce the "ID line" that shows some useful stuff about the call, mostly # # used for debugging and diagnostic purposes. This might be produced only at # # verbose levels >1, when we're not actively debugging anything. # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # local $srvrL = '[' ; local $srvrR = ']'; print "
"; print "$srvrL$srvr:$cwd/$P $devtyp V=$V $RA$srvrR
$srvrL$UA$srvrR"; 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"; print "\t \n"; print "\t\t\n"; &formQLSTV('edit',"\t\t"); 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"; &formQLSTV('doc'); print "\n"; &send_LW("$F: We found $lines lines in '$path'") if $V>1; print "\n"; print "\n"; print "\t\n"; print "\t\n"; print "\n"; print "\n"; print "\t\n"; print "\t\n"; print "\n"; print "
Directory:
File name:
\n"; print "Message:
\n"; print "
\n"; print "\n"; 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"; &formQLSTV('doc'); print "\n"; &send_LW("$F: We found $lines lines in '$path'") if $V>1; print "Editing '$path':
\n"; print "
\n"; print "\n"; 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 "
$name
  \n"; for $line (@info) { print " $line\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 "
$file
(No flyers found)
\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 "
\n"; &IDline() if $V>0; print "\n"; print "\n"; print "\n"; exit $stat; } sub randint {local($max) = @_; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # Returns a (pseudo-)random integer in the range [1,$max] # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # if (0) { # Version that uses rand my($flt) = rand(1.0); return(int($max * $flt) + 1); } if (1) { return(((time + $$) % $max) +1); # Version that uses time and process id } } sub regPanel {my $F='regPanel'; local($job,$act,$user) = @_; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # This generates a frame for the "register" content, and then calls addAcct() # # to produce the registration content. # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # local($src) = ''; local($unam) = &name2uname(&tText($user)); &sendLog("[$F] Called job='$job' act='$act' user='$user' -> unam='$unam'") if $V>0; if ($act eq 'form') { &sendLog("[$F] Produce registration form ...") if $V>0; $Content = $src = "doc/Register.html"; &sendLog("[$F] Content='$Content'") if $V>1; &webfile($Content); } elsif ($act eq 'user') { &send_LW("[$F] Register new user '$unam' ...") if $V>0; $v=3 if $V<3; # Debugging registrations. $unum = &addAcct($unam); # Generate the form to edit the account's info: &sendLog("$F: Call acctUpdate('$unam','$unum') ...\n") if $V>0; $val = &acctUpdate($unam,$unum); &sendLog("$F: acctUpdate('$unam','$unum') returned '$val'.\n") if $V>0; } else { &sendLog("[$F] Unknown act '$act'") if $V>0; } return $F; } sub replyPanel {my $F='replyPanel'; local($file,$how) = @_; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # This generates a frame for the "reply" content, then calls replyFile() # # to produce the commentary. # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # &sendLog("$F: Called with file='$file' how='$how'") if $V>0; require "blogsubs.pm"; # All the blog routines are here if ($bloggers{$uname} || $admins{$uname}) { &sendLog("$F: User $unumb/$uname is a blogger.") if $V>1; $Content = &replyFile($file,$how); &sendLog("$F: Content='$Content'") if $V>1; } else { &sendLog("$F: User $unumb/$uname is not a blogger.") if $V>1; } return $Content; } sub startup { local($x) = shift || 2; # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # # This is the first thing we do when we start up. It should assume little or # # nothing about the environment. Its job is to look at the environment and # # try to figure out what might be useful to us. # # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # $V = $x; # Global verbose level $ENV{PATH} = '/bin:/usr/bin'; # Untainted search path needed ($cwd = `/bin/pwd`) =~ s"[\r\s]+$""; print STDERR "$0: CWD='$cwd'\n" if $V>8; if ($ENV{SCRIPT_NAME} =~ m"/mobile/") { # Request for "mobile" layout $L = 'M'; # $L is the layout, 'F'ull or 'M'obile $Lsrc = 'SCRIPT_NAME'; # Where we got the layout $Layout = 'mobile'; chdir ".."; # Back up to the main directory ($cwd = `/bin/pwd`) =~ s"^(.*)[\r\s]+$"$1"; # This should untaint the directory path } $ENV{HOME} = $cwd unless $ENV{HOME}; # Make sure we have a HOME directory defined print STDERR "$0/startup: CWD='$cwd' L='$L'='$Layout'\n" if $V>8; push @INC, 'pm', '../pm'; # Where to find our perl modules } sub mainRef { # = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # @ARG; }