0byt3m1n1
Path:
/
data
/
0
/
0
/
16
/
156
/
16482
/
user
/
16848
/
cgi-bin
/
[
Home
]
File: eventcalendar.pl
#! /usr/local/bin/perl -w # eventcalendar.pl # # perl cgi to view and interact with an event calendar # by Nermware # # Requires perl v5.6.1 or higher # ###################################################################################################### # Rev 3.0 .. 11/02/03 .. Many new features .. new repeats, ding option, moon phases, holidays, # ......................... categories, etc. .. Contains code inspired by Daniel Moore (ironwing of yabb fame) # Rev 3.1 .. 12/19/03 .. Fixed display of Europe weeks in the year view # Rev 3.1.1 .. 1/13/04 .. Fix cutoff of eventcaladmin.js script # Rev 3.1.2 .. 1/14/04 .. Fix for currupt style sheet with some CGI.pm versions # Rev 3.1.3 .. 2/10/04 .. Fix to handle rev 0.11 Astro::MoonPhase.pm # Rev 3.1.4 .. 2/14/04 .. Added auto-linking to news and mailto .. fixed moonphase shutoff # Rev 3.1.5 .. 2/26/04 .. Repaired so that view up can go beyond next month. Requires viewup.pm rev 1.1 # Rev 3.1.6 .. 3/18/04 .. Added vars to allow language for the entry page How To instructions, + on/off flag # Rev 3.1.7 .. 3/28/04 .. Added Palm Sunday. # Rev 3.1.7a .. 4/8/04 .. Removed duplicate $homepage # Rev 3.1.8 .. 7/25/04 .. (Thanks to Dalton) Fixed minor bug in sort, Un-highlighted today on printer friendly page (line 923) # Rev 3.1.9 .. 12/19/04 .. Thanks to Chris, fixed viewup bug where next year & next month where incorrect for view up dayno >=365 # Rev 3.2 .. 12/29/04 .. Changed day number from button to div for better formating ###################################################################################################### # License: See http://www.gnu.org/copyleft/gpl.html, the GNU General Public License. # Note: The term free as used in this license is in reference to freedom, not price. # Copyright (C) 2003, Nermware # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ---------------------------------------------------------- ## Modules Used ## # ---------------------------------------------------------- use Time::Local; use File::Basename; use CGI qw/:standard :html3/; use CGI::Pretty; use CGI::Carp qw(fatalsToBrowser carpout); # # # # # # # # # # # # # # # # Freely change below # # or use a language file # # # # # # # # # # # # # # # # ########### Basic Configuration ############# # Every page has a meta comment indicating adapted from the original .. # Please change or comment this. $adaptcom = 'eventcalendar.pl Rev by Geof Gibson for IBRockin\''; # Where you want people to email to $myemail = 'rockin@ibrockin.com'; # Use the above email address as a button on the month view page $usemyemail = 1; # Check my sanity $sanitycheckok = 1; # Base url of all pages # Example .. $baseurl = 'http://www.nermware.com/'; # NOTE: .. Leave this unset to force this script to figure it out. # Set this only if this fails to render it correctly # See 'When things don't seem to work' in the Readme file # $baseurl = 'http://www.ibrockin.com/'; # path to the cgi directory relative to your web page directory # probibly /cgi-bin or /bin # NOTE: .. Leave this unset to force this script to figure it out. # Set this only if this fails to render it correctly $cgidir = './cgi-bin'; # Note .. if when edit or view is selected, and link path is incorrect with # 'eventcalendar./eventcalendar.pl' in the path, then set the above $baseurl # and $cgidir as indicated. # Name of this script .. eventcalendar.pl if not changed # $scriptname = "eventcalendar-test.pl"; # path to the master calendar database, relative to the cgi bin directory $majordbfile = '../cgi-bin/caldb/eventcaldb'; # Path to holiday database, relative to the cgi bin directory $holidaydbfile = '../cgi-bin/caldb/holidaydb'; # Enable holiday treatment of holidays .. i.e. holidays are entered into the holiday database # Else entered into the major databases. Holidays in holiday database are treated differently. The # entries are entered only if in the year 2000. # Note: To enter holidays into the holiday database, three things have to be true # 1. Holiday ok flag is set and $holidaydbfile is readable # 2. The subject is $holiday # 3. selected year is 2000 .. all holidays, excluding those like Easter, epoch in the year 2000 # This is so that earlier entries with repeats on the entered holiday don't overwrite it $holidayok = 1; # Europe ? $europe = 0; # change to 1 if europe week is to be viewed (starts # with monday & dates are viewed day/month/year) # Path to the local css style sheet. Comment out if no stylesheet. $csspath = "./style.css"; # Show image of phase of the moon? $moonphaseok = 0; # Defined home page relative to base url $homepage = '/home.htm'; # Calculate Easter, Good Friday and Ash Wednesday ? $easterok = 1; ########## Titles and Names of Things ########## ## Use language files for native language ## # Title of the today button $todaytitle = 'This Month'; # Text of the home link $hometext = 'HOME'; # Title of the goto column $gototitle = 'Go To'; # Title of the select month column $selmonthtitle = 'Select Month'; # Title of the select year column $selyeartitle = 'Select Year'; # Title of the view calendar column $viewcaltitle = "View Calendar"; # Label of the view month button $vwmobutton = "Month View"; # Label of the view year button $vwyrbutton = "Year View"; # Title of the return button $returntitle = "Return to Month View"; # Title of the entry fields and such $titletitle = 'Event'; $occurstitle = 'Occurs'; $commenttitle = 'Comment'; $subjecttitle = 'Type'; $theforword = 'For'; # Annual event only text .. shown whenever an annual event only subject is selected $annualtext = 'Annual<br />Event</br />Only'; # As shown on the calendar, and used by the entry forms # hash mapping of the text background 'catagory' colors. Map color values to names # Syntax .. key value => label %titlebgmap = ( 'none' => 'All', '#33ffcc' => "IT", '#ccff66' => "HR", '#ff0033' => "Sales", '#66cccc' => "Engineering", '#ffff99' => "Advertising", '#66ccff' => "Finance" ); # Sequence placement of value->lables using values in the prefered sequence # Note .. these values must match the keys of %titlebgmap. If they don't, the mismatching will # not be availible @titlebgvalues = ("none","#33ffcc","#ccff66","#ff0033","#66cccc","#ffff99","#66ccff"); # Repeatlabels are the labels in the occur menu. # Change these for other then English but keep the same order @repeatlabels = ('One time only','Daily','Mon-Fri','Every other Mon-Fri','Weekly','Every other week','Monthly by date','Monthly by weekday','Monthly by last weekday','Yearly by date','Yearly by weekday','Yearly by last weekday'); # %unittext is the text units shown for Day, Days, Weeks, Months, or # Years. Change according to language. %unittext = ( 'Day' => 'Day', 'Days' => 'Days', 'Weeks' => 'Weeks', 'Months' => 'Months', 'Years' => 'Years' ); # Show instructions for the entry page (1=yes, 0=no) $showinstructions = 1; # Instructions for entry fields $howtotitle = 'How To Use'; $howtoinstruct = 'Use these entry forms as follows'; %instructions = ( $titletitle => "$titletitle is displayed on the calendar.", $subjecttitle => "Select a $subjecttitle from the menu. For $subjecttitle 'Other', use the $commenttitle field.", $commenttitle => "Enter a $commenttitle about the $subjecttitle or the 'Other' $subjecttitle", $occurstitle => "$occurstitle for entered number of: " . join("\, ",@repeatlabels) . "</u>" ); # Titles for the days of the week # Change for other languages but keep same order @weekdaytitles = qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday); # Title for each month # Change for other languages but keep same order @monthtitles = qw(January February March April May June July August September October November December); # Title of the calendar page $calpgtitle = 'IBRockin\' Event Calendar'; # Title of the calendar (not the page) $caltitle = 'IBRockin\' Event Calendar'; # How To instructions at bottom of month view $monthhowto = "<i>To <u>View</u> a day's information, select the event. To <u>edit</u> a day's information, select the date.</i>"; # years to show in the menu @menuyears = qw(2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025); # Selection for subject menu @sbjlist = qw(Meeting Trip Birthday Marriage Anniversary Church School Party Banquet Game Vacation Holiday Memorial Other); # Always repeat these subjects .. annual events only @alwaysrepeat = qw(Birthday Anniversary Holiday Memorial); # Default subject list selection $sbjdefault = 'Meeting'; # Entry Page title $enpgtitle = 'Event Calendar Day Information Entry Page'; # Day view page title $dypgtitle = 'Event Calendar Day Information Viewer Page'; # Year view page title $yrpgtitle = 'Event Calendar Year'; # Entry page lables $applylabel = "Apply entry"; $deletelabel = "Delete entry"; $resetlabel = "Reset entry"; # Edit and view data phrases. Used in the month view's status section, and popup title $editphrase = 'Click to edit'; $viewphrase = 'Click to view'; $printertext = "Printer Friendly Page"; # Your native word for Holiday $holiday = 'Holiday'; # Words for moon images $moonword_new = 'New'; $moonword_first = 'First Qtr'; $moonword_full = 'Full'; $moonword_last = 'Last Qtr'; # Native words for Easter $easter = 'Easter'; $gfriday = 'Good Friday'; $ashwed = 'Ash Wednesday'; $palmsun = 'Palm Sunday'; ######### Colors ######### # Title text foreground color $caltitlecolor = "navy"; # Color of the background row for the name of the days of the week $wkdbgcolor = "$caltitlecolor"; # Color of the text for the name of the days of the week $wkdfgcolor = "#fff0b0"; # Background color of all pages $pagebgcolor = "#e0e0ff"; # Calendar background color (not the page background color) $calbgcolor = "#d0d0f0"; # Regular day of month button number foreground color $dayfgcolor = "$caltitlecolor"; # Regular day of month button number background color $daybgcolor = "$pagebgcolor"; # Highlighted day of month number (fg) & button (bg) color $hdayfgcolor = "$wkdfgcolor"; $hdaybgcolor = "$wkdbgcolor"; # Calendar day data text color $ctxtfgcolor = "$caltitlecolor"; # Calendar day data text background color # If unset (commented out), background is the same as cell background. # Example: $ctxtbgcolor = 'white'; # $ctxtbgcolor = 'white'; # Catagory background color on/off # If 0, background colors representing catagory are not shown $catagorycoloron = 1; # Bottom menu cell background color $mnubgcolor = "$wkdbgcolor"; # Bottom menu text foreground color $mnufgcolor = "$wkdfgcolor"; # Weekend cell color $calwebgcolor = "#c0c0e0"; # Prev and Next buttons cell background color $pnbgcolor = "$wkdbgcolor"; # Prev and Next buttons text foreground color $pnfgcolor = "$wkdfgcolor"; # Month & Year calendar cell background color $myrbgcolor = "$wkdbgcolor"; # Month & Year text color $myrfgcolor = "$wkdfgcolor"; #### Enter day page #### # Caption text color $capfgcolor = "$caltitlecolor"; # Title cell background color $titlebgcolor = "#e6e6ff"; # Title text foreground color $titlefgcolor = "$caltitlecolor"; # Subject cell background color $sbjbgcolor = "$titlebgcolor"; # Subject text foreground color $sbjfgcolor = "$titlefgcolor"; # Comment cell background color $cmtbgcolor = "$titlebgcolor"; # Comment text foreground color $cmtfgcolor = "$titlefgcolor"; # Add/Change & Delete button cell background color $acdbgcolor = "$pnbgcolor"; # Add/Change & Delete button text foreground color $acdfgcolor = "$pnfgcolor"; # Instructions text foreground color $insfgcolor = "$titlefgcolor"; ########### Sizes and Limits ############ # The size of the bg labels as shown in the enterday form # This limits the size for better viewing on the entry page $titlebgsize = "5"; # Month view day number button size (x-small, small, medium, large, x-large, xx-large, smaller, larger) $buttonsize = 'large'; # Max length of the entered title that's viewed on the month view calendar # day cells $maxtitlelen = 16; # Max number of entries $maxentries = 6; # Max number of repeat occurences $maxrepeats = 100; # Set to 1 to return to the enter data page when entries are added, changed, or deleted # else 0 to return to calendar page $returnenterday = 0; # Set offset in minutes server time zone is ater (+) or before (-) gmt # Default is EST, 5 hours * 60 minutes, unless Europe, then 0 # This is so that correct day is shown for local time # Note that after the 1st eventcalendar page is shown, viewer's offset is read and used. # However, this will get you close to what your users expect. $gmtoffset = 300; $gmtoffset = 0 if($europe); ########### Over all fonts ############ # List of fonts families. # Note: style sheet defined in $csspath over writes this font stuff. $fontfamily = "serif"; # Default font size $fontsize = '12pt'; ########### Images ############ # Where images are kept relative to base url $imagedir = '/eventcalimages'; # Background Image # Note: style sheet defined in $csspath over writes this background stuff. #$background = "$imagedir/bg4.jpeg"; # Placement of background image (fixed or scroll) $bgimgplace = "fixed"; # Repeat of background image (repeat, repeat-x, repeat-y or no-repeat) $bgimgrepeat = "repeat"; # Moon phase images directory $moonimgdir = $imagedir; # Button images $buttonimgdir = $imagedir; # # # # # # # # # # # # # # # # No More Variable Changes # # # # # # # # # # # # # # # # # ---------------------------------------------------------- ## Sub Routines ## # ---------------------------------------------------------- sub GetActType { # Get the type of activity to do # Set default type my($type) = "display"; # Get the selected action type argument $type = $webpage_obj->param('acttype') if(defined($webpage_obj->param('acttype'))); $type = 'newdata' if(defined($webpage_obj->param('newdata'))); $type = 'deldata' if(defined($webpage_obj->param('deldata'))); # return good checks of type of action return($type) if ($type =~ /display|viewyear|enterday|viewday|newdata|deldata|viewup|print/); # If not one of these .. not a good type return('badtype'); } # ---------------------------------------------------------- sub GetSelDate { # Get the selected day, month and year. If none selected, use present month and year. # Get local time offset in minutes. $gmtminos = $webpage_obj->param('gmtminos')?$webpage_obj->param('gmtminos'):$gmtoffset; # Preset selected month, day, and year my($selmonth,$selday,$selyear); ($selmonth,$selday,$selyear) = (gmtime(time-$gmtminos*60))[4,3,5]; # Fix up year to match reality $selyear = $selyear+1900; # Get the selected month, day and year if there are any $selmonth = $webpage_obj->param('selmonth') if (defined($webpage_obj->param('selmonth'))); $selday = $webpage_obj->param('selday') if (defined($webpage_obj->param('selday'))); $selyear = $webpage_obj->param('selyear') if (defined($webpage_obj->param('selyear'))); # Return selected month, day, year return($selmonth,$selday,$selyear); } # ---------------------------------------------------------- sub GetDbData { # Get data from the database # Data is indexed by date number # Gets nothing but uses $majordbfile, & $holidaydbfile # Returns nothing but loads %dayinfo # Note .. using gmt time to avoid Day-light savings time snafu # Database file is Date Number Index|title{subject{comments{repeatby{repeatnum # pattern then repeats (except for the index). Each entry is delimited by the pipe | # and each value is delimited by the left { # Get 1st day of the month day number my($thismonth) = $seldate[0]; my($thisyear) = $seldate[2]; my($selmonfst) = timegm(0,0,0,1,$thismonth,$thisyear); # Don't need this if newdata or delete # This is used to retrieve only that data that is displayed for selected month # New and Deleted data requires all data for the database is re-written # To prevent duplicate data being entered into the database. # This is a change from pre 3.0 versions. Pre 3.0 versions # appended the data to the database thus, in some cases, duplicating the data # in the database, and retaining history. Version 3.0 and above does not # retain any history of changes. # Get next months number my($nextmonth) = $thismonth+1; if($acttype eq 'viewup') { # So that ssi upcoming events will go into next month $nextmonth++; # So that data is read for all the dayno days $nextmonth = $nextmonth + int $dayno/30 if($dayno); } # Look for next year and month my($nextyear) = $thisyear; $nextyear = $nextyear + int $nextmonth/12; $nextmonth = $nextmonth%12; # Get 1st day of next month my($nxtmonfst) = timegm(0,0,0,1,$nextmonth,$nextyear); # Get the db files to read from push(my(@dbfiles),$majordbfile); push(@dbfiles,$holidaydbfile) if(-r $holidaydbfile); my($db); my($newdataok) = ($acttype=~/newdata|deldata/)?1:0; # Get the data from the databases foreach $db (@dbfiles) { # Open the database table file die("ERROR .. unable to read $db\n") unless(-r $db && open(DBFILE,$db)); # Seek thru the database file to select the index that falls # the day before the 1st day of next month # to load up the hash table associative array of value arrays # Read each line in the file and strip the \nl my(@line,$index,$strline,$theline,$cnt); while ($theline = <DBFILE>) { # Ignore comments next if($theline =~ /^\#/); # No del characters $theline =~ s/\x7f//g; chomp($theline); # Next if blank line next if(!$theline); # Change all crs to spaces $theline =~ s/\x0d/\x20/g; # Load the line string $strline = $strline . $theline; # Line must end with 1 or more number digits next if($strline !~ /\{\d+$/); # Line string must begin with >= 1 digit followed by a pipe symbol if($strline !~ /^\d+\|/) { $strline = $theline = ''; next; } # Split each entry into an element of an array @line = split(/\|/,$strline); $strline = ''; # Get and strip the index $index = shift(@line); next if(!$index || ($index =~ /\D/)); # dayinfo is a hash by index of the line array reference if($newdataok || ($index < $nxtmonfst)) { $dayinfo{$index} = [@line]; } } close(DBFILE); } # Don't continue if this is enterday, deldata or newdata. # Can't change repeated data anyway. # Only can change or delete what's in the database return if($acttype !~ /display|view|print/); # Calculate Easter? GetEaster($thisyear,$thismonth) if($easterok && ($thismonth >= 1 && $thismonth <= 3)); # Preset the number of seconds in 24hrs and seconds in 168hrs (1 week) my($daysecs) = 24*60*60; my($weeksecs) = $daysecs*7; # Loop thru each hash and see if it repeats my($i,$element,@entry,$repeatfor,$newindex,$addsecs,$addyears,$addmonths,$repeatby,$weekdaynum,$eventweekday); foreach $index (keys %dayinfo) { # Read the repeat number to see if other hashes need to be made # Split each entry into an array foreach $element (@{$dayinfo{$index}}) { next if(!$element); # Check for tainted element # Element should be formated as title{subject{comments{repeatby{repeatfor next if($element !~ /.+\{.+\{.*\{.+\{\d+/); @entry = split('{',$element); # Choose what to view next if($chooseok && !ChoiceOk(\@entry)); # The repeat number is the last element of the entry array $repeatfor = $entry[$#entry]; $repeatby = $entry[$#entry-1]; next if(!($repeatfor && $repeatby)); # Skip if number is not pure .. i.e. its tainted with non-numbers like 12ab34 next if($repeatfor =~ /\D/); # Always repeat this event? (based on subject in $entry[1] if(grep(/$entry[1]/, @alwaysrepeat)) { $repeatfor = $maxrepeats; # Protect against always repeats for days or months, can always repeat on annual events only $repeatby = ($repeatby !~ /Year/) ? 'Year' : $repeatby; } # Grandfather in the old database $repeatby = 'Day' if($repeatby eq 'Day(s Day-ly'); $repeatby = 'Once' if(($repeatby eq 'Day(s Day-ly') && ($repeatfor == 1)); $repeatby = 'Week' if($repeatby eq 'Week(s Week-ly'); $repeatby = 'Month' if($repeatby eq 'Month(s Month-ly'); $repeatby = 'Year' if($repeatby eq 'Year(s Year-ly'); # Limit repeats. $repeatfor = $maxrepeats if($repeatfor > $maxrepeats); if($repeatfor > 1) { # It needs to be repeated. # The way it repeats it is by: # 1. What is the repeat by .. by days, weeks, months, years, etc. # 2. if days or weeks, loop the repeat number -1, add daysecs, bi-daysecs, weeksecs, or bi-weeksecs # 3. then create a copy of the entry with the new hash index (seconds) # 4. if by months, years, etc. change the index (secs) to month, year, etc # 5. loop the repeat number -1, add 1 to the month or year, etc # 6. change back this new date to seconds # 7. as with #3 above, create a copy of the entry with the new hash index. # 1. What is the repeat by .. by days, weeks, months, years, etc. next if($repeatby !~ /Day|Week|Month|Year/); $newindex = $index; $addsecs = $daysecs if($repeatby =~ /Day/); $addsecs = 2*$daysecs if($repeatby eq 'BiDay'); $addsecs = $weeksecs if($repeatby =~ /Week/); $addsecs = 2*$weeksecs if($repeatby eq 'BiWeek'); # 2. if days or weeks, loop the repeat number -1, add daysecs, bi-daysecs, weeksecs, or bi-weeksecs # 3. then create a copy of the entry with the new hash index (seconds) if($repeatby =~ /Day|Week/) { for($i=2;$i<=$repeatfor;$i++) { $newindex = $newindex + $addsecs; # Use the new element onto the end of the array if its before next month last if($newindex >= $nxtmonfst); # Set repeat number to 0 to prevent double repeats and to show this is a repeated entry $entry[$#entry] = 0; $weekdaynum = (gmtime($newindex))[6]; # Work Day? if($repeatby =~ /WkDay|BiDay/) { $newindex = $newindex + $daysecs + $addsecs if($weekdaynum == 6); $newindex = $newindex + $daysecs if($weekdaynum == 0); } $dayinfo{$newindex}->[++$#{$dayinfo{$newindex}}] = join('{',@entry) if($newindex >= $selmonfst); } # Get the next element next; } # 4->7 .. uses months or years # Set the months or years to add $addyears = $addmonths = 0; $addyears = 1 if($repeatby =~ /Year/); $addmonths = 1 if($repeatby =~ /Month/); # Get month & year for this index my(@thisdate) = gmtime($index); # (see below "# How this works") 1. get week day of present event .. must be done prior to looping $eventweekday = $thisdate[6] if($repeatby =~ /Xweekday/); # Start looping for($i=2;$i<=$repeatfor;$i++) { # Add to it $thisdate[4] = $thisdate[4] + $addmonths; $thisdate[5] = $thisdate[5] + $addyears; if($thisdate[4] > 11) { $thisdate[4]=0; $thisdate[5]++; } # Don't let this exceed its max year of 2037 last if($thisdate[5] > 137); # If month or year by week day if($repeatby =~ /Xweekday/) { # How this works # 1. get week day of present event .. must be done prior to looping # 2. get week number of event (1-5) # 3. tmp new day of month = week number * 7 # 4. set new month or year # 5. get day of week for new day in new month (or year) # 6. new day offset = week day of tmp new day of month - week day of event # 7. new day offset = new day offset + 7 if(new day offset < 0) # 8. new day of month = new day of month - new day offset # 2. get week number of event (1-5) # 3. tmp new day of month = week number * 7 $thisdate[3] = (int(($thisdate[3]-1)/7)+1) * 7; # Date out of range? $thisdate[3] = ($thisdate[3] > 31) ? ($thisdate[3] - 7) : $thisdate[3]; } # Change it back to seconds # 4. set new month or year # cut off the wday, yday and isdst @thisdate = splice(@thisdate,0,6); $newindex = timegm(@thisdate); # If month or year by week day if($repeatby =~ /Xweekday/) { # 5. get day of week for new day in new month (or year) @thisdate = gmtime($newindex); # 6. new day offset = week day of new day of month - week day of event # 7. new day offset = new day offset + 7 if(new day offset < 0) # 8. new day of month = new day of month - new day offset $thisdate[3] = $thisdate[3]-((($thisdate[6]-$eventweekday)<0)?($thisdate[6]-$eventweekday+7):($thisdate[6]-$eventweekday)); # Set new index # splice off the wday, yday and isdst @thisdate = splice(@thisdate,0,6); $newindex = timegm(@thisdate); # Last week day of month? if($repeatby =~ /LastXweekday/) { $newindex = ((gmtime($newindex))[3] < 25) ? ($newindex + $weeksecs) : $newindex; $newindex = ((gmtime($newindex))[4] > $thisdate[4]) ? ($newindex - $weeksecs) : $newindex; } } # Use the new element onto the end of the array if its before next month last if($newindex >= $nxtmonfst); # Don't use this index if this month is not the expected month. # I.E. the expected month doesn't have this day, thus shows next month if((gmtime($newindex))[4] > $thisdate[4]) { $i--; next; } next if($newindex < $selmonfst); # Set repeat number to 0 to prevent double repeats and to show this is a repeated entry $entry[$#entry] = 0; $dayinfo{$newindex}->[++$#{$dayinfo{$newindex}}] = join('{',@entry); } } } } } # ---------------------------------------------------------- sub ViewMonth { # Display the month view calendar page # in order to view the calendar page .. need to know: # what month, day, and year to view # what information is listed for the days viewed # To create the calendar: # Get the day of the week for the 1st day of the month. Then skip those weekdays # from sunday (or monday) and place the 1 there. Continue counting until next # sunday (or monday) to start a new row # (or week) on the table. Keep counting until the last day of the month. Then # skip those days until saturday (or sunday). # How this works to list the entries: # A hash list of entries for each day of given month is retrieved # from the database table. # As each day is about to be viewed, the hash list is checked for entries. # if there are any, they will be viewed along with the anchored day number. # to view the month, day, and year, extract todays month and year my($thismonth) = $seldate[0]; my($thisyear) = $seldate[2]; my($monthname) = $monthtitles[$thismonth]; # next get the number of sec for the 1st day of today's month and today's year # This will be the starting number of seconds for the begining of this month my($thisdaysecs) = timegm(0,0,0,1,$thismonth,$thisyear); # Get the day of the week for the 1st day of this month my($thisdayweek) = (gmtime($thisdaysecs))[6]; # Need the number of seconds in a 24 hr day my($daysecs) = 24*60*60; # Get today's local seconds at midnight. Need to subtract local time offset seconds # from gmt time for local time is behind gmt time my(@today) = gmtime(time-$gmtminos*60); my($todaysecs) = timegm(0,0,0,$today[3],$today[4],$today[5]); # Get next months number my($nextmonth) = $thismonth+1; my($nextyear) = $thisyear; if($nextmonth > 11) { $nextmonth = 0; $nextyear = $thisyear+1; } # Get previous months number my($prevmonth) = $thismonth-1; my($prevyear) = $thisyear; if($prevmonth < 0) { $prevmonth = 11; $prevyear = $thisyear-1; } # Skip this stuff if display is for printing if($acttype eq 'display') { # Add to the header cookie if admin-security $theheader{'-cookie'} = $cookiepass if(!$adminok && $cookiepass); # Onload the Set GmtOffset number $htmlstart{"-onload"} = $htmlstart{-onload} ? $htmlstart{"-onload"} . "SetGmtOffset()" : "SetGmtOffset();"; # Regular jscode & Admin script? if($adminon && (-r './eventcaladmin.js')) { my($jsfile,$jsfilesize); open(JSCODE, "<./eventcaladmin.js"); $jsfilesize = read(JSCODE, $jsfile, 4096); close JSCODE; push(@jscode, { -language => 'JavaScript1.1', -type => 'text/javascript', -code => "$jsfile" } ) if($jsfilesize); } $htmlstart{"-script"} = [@jscode]; } # Start the page StartPage(); # The start of the table print "\n".'<table border="1" cellpadding="1" cellspacing="1" width="90%" align="center">'; my($prevmonthtitle) = substr($monthtitles[$prevmonth],0,3); my($nextmonthtitle) = substr($monthtitles[$nextmonth],0,3); # Display view print "\n".$webpage_obj->Tr( $webpage_obj->th({-style=>"background-color:$pnbgcolor"}, $webpage_obj->div({ -style => "font-size:large;font-weight:bold;color:$pnfgcolor;background-color:$pnbgcolor;cursor:pointer;text-align:center;border-width:2px;border-style:outset", -onclick => "SetCalForm('1','$prevmonth','$prevyear','display');" },"$prevmonthtitle" ), ), $webpage_obj->th({-style=>"background-color:$myrbgcolor", -colspan=>"5"}, $webpage_obj->span({-style=>"font-size:x-large;color:$myrfgcolor;font-weight:bold;text-align:center"}, "$monthname $thisyear" ) ), $webpage_obj->th({-style=>"background-color:$pnbgcolor"}, $webpage_obj->div({ -style => "font-size:large;font-weight:bold;color:$pnfgcolor;background-color:$pnbgcolor;cursor:pointer;text-align:center;border-width:2px;border-style:outset", -onclick => "SetCalForm('1','$nextmonth','$nextyear','display');" },"$nextmonthtitle" ), ) ) if($acttype eq 'display'); # Print view print "\n".$webpage_obj->Tr( $webpage_obj->th({-style=>"background-color:$myrbgcolor", -colspan=>"7"}, $webpage_obj->span({-style=>"font-size:x-large;color:$myrfgcolor;font-weight:bold;text-align:center"}, "$monthname $thisyear" ) ) ) if($acttype eq 'print'); # Test for europe week, i.e. starts with monday my(@dayheadings); my(@wdtitles) = @weekdaytitles; push(@wdtitles,shift(@wdtitles)) if($europe); push(@dayheadings, $webpage_obj->Tr( $webpage_obj->th({-style=>"background-color:$wkdbgcolor;color:$wkdfgcolor;width:14%"},[ @wdtitles ]) ) ); print "@dayheadings\n"; # Make weekrow # Pad calendar over to 1st day of the month my(@weekrow, $colspan); $colspan = $thisdayweek if($thisdayweek > 0); # Check for europe if($europe) { $colspan = $thisdayweek-1 if($thisdayweek > 0); $colspan = 6 if($thisdayweek == 0); } push(@weekrow,$webpage_obj->td({-colspan => "$colspan"})) if($colspan); # Loop thru the days of this month my($thisdaymonth, $cell, $celldata, $daynumfgcolor, $daynumbgcolor, $doonclick, $monthnumber, $cellbgcolor, $textbgcolor, $textfgcolor, $moonok, $moonimage, $mooncomment, $maxchars, $titletext, $disdings); $thisdaymonth=1; for(;$thisdaysecs <= $thisdaysecs+$daysecs*31;$thisdaysecs += $daysecs) { # Is this the 1st day of next month? last if ((gmtime($thisdaysecs))[4] != $thismonth); # Note .. hash array is index|title,subject,comment,repeatnum,repeatby|title,... # Extract the title from the hash array if it exists $celldata = $cell = $doonclick = $monthnumber = ""; # Get this day of the month and week ($thisdaymonth,$thisdayweek) = (gmtime($thisdaysecs))[3,6]; # What to do on click $doonclick = "SetCalForm('$thisdaymonth','$thismonth','$thisyear','enterday');"; $doonclick = "CookieCheck('$thisdaymonth','$thismonth','$thisyear','enterday');" if($adminon); # Highlight for todays date $daynumfgcolor = $dayfgcolor; $daynumbgcolor = $daybgcolor; if(($acttype eq 'display') && ($todaysecs == $thisdaysecs)) { $daynumfgcolor = $hdayfgcolor; $daynumbgcolor = $hdaybgcolor; } # Set background color for the weekend and regular days $cellbgcolor = $calbgcolor; $cellbgcolor = $calwebgcolor if($thisdayweek =~ /0|6/); # Include the moon image phase if($moonphaseok) { $moonok = GetMoonImage($thisdaysecs+$daysecs+($gmtoffset*60),\$moonimage,\$mooncomment); # Sometimes this errors with 2 days with moons, if so, don't use this moon $moonok = (GetMoonImage($thisdaysecs+($gmtoffset*60)+2*$daysecs,\$moonimage,\$mooncomment)?0:1) if($moonok); if($moonok) { $monthnumber = $webpage_obj->div({ -style => "float:right;font-size:x-small;color:$ctxtfgcolor" },$mooncomment, $webpage_obj->img({-src=>$moonimage,-title=>$mooncomment,-alt=>$mooncomment,-width=>"19",-height=>"19"}) ); } } # display view $monthnumber = $monthnumber . "\n" . $webpage_obj->div( { -style => "color:$daynumfgcolor;background-color:$daynumbgcolor;font-size:$buttonsize;font-weight:bold;width:1.3em;height:1.0em;border-style:outset;border-width:2px;text-align:center;vertical-align:middle;font-family:$fontfamily;cursor:pointer", -title => "$editphrase", -onclick => "$doonclick", -onmouseover => "window.status='$editphrase'; return true;", -onmouseout => "window.status='';return true;" },$thisdaymonth ) if($acttype eq 'display'); # print view $monthnumber = $monthnumber . "\n" . $webpage_obj->div( { -style => "color:$daynumfgcolor;background-color:$daynumbgcolor;font-size:$buttonsize;font-weight:bold;width:1.3em;height:1.0em;border-style:outset;border-width:2px;text-align:center;vertical-align:middle;font-family:$fontfamily" },$thisdaymonth ) if($acttype eq 'print'); # Box the month number & moon if there is one # $cell = $webpage_obj->div($monthnumber); $cell = $monthnumber; # Add the cell data if (defined($dayinfo{$thisdaysecs})) { # Loop thru each hash entry # $dayinfo{$thiddaysecs} contains a reference to an array # This array's elements each have the scalar line of the entered data # Arranged as entry 1, ... , last entry # Sort it redistributes this array's elements in alphabetical order # by the configured key (Catagory, Title, or Subject) if($groupsortok) { SortIt($dayinfo{$thisdaysecs}); } foreach $info (@{$dayinfo{$thisdaysecs}}) { @daydata = split(/\{/,$info); next if(!($daydata[0] && $daydata[1]) || ($daydata[1] =~ /DELETED/)); next if($chooseok && !ChoiceOk(\@daydata)); # Load cell if there is something to load if($daydata[0] =~ /[0-z]/) { # Preset colors $textbgcolor = $cellbgcolor; $textbgcolor = $ctxtbgcolor if(defined($ctxtbgcolor)); $textfgcolor = $ctxtfgcolor; # (groupsort option) Group heading if($groupsortok) { GroupHead(\$celldata,\@daydata); } # Extract data text bg color if($daydata[0] =~ /^\#.{6}\s/) { $textbgcolor = substr($daydata[0],0,7) if($catagorycoloron); $daydata[0] =~ s/^\#.{6}\s//; } # Is this a holiday? if($daydata[1] eq $holiday) { # Then reverse the fg & bg colors to make it stand out $textfgcolor = $textbgcolor; $textbgcolor = $ctxtfgcolor; # Add it to the cell next to the button $cell = $cell . $webpage_obj->div({ -style => "background:$textbgcolor;color:$textfgcolor;font-size:smaller;text-align:center;font-weight:bold" }, $daydata[0] ); next; } # Dings require to be displayed $disdings = (($daydata[0] =~ /^w..\&\#\d{3}/) && $dingsok); $maxchars = $maxtitlelen; # Increase max title length if to also display dings $maxchars = $maxtitlelen + 9 if($disdings); # Limit the characters that can be displayed $daydata[0] = substr($daydata[0],0,$maxchars) if(length($daydata[0]) > $maxchars); # Display data dings if enabled DisplayDing(\@daydata) if($disdings); # Display the day data in the day cell # Default title $titlebgmap{$cellbgcolor} = ""; # The cell text with link # Make cell stuff for display if($acttype eq 'display') { $titletext = ($titlebgmap{$textbgcolor}) ? "$titlebgmap{$textbgcolor} \($daydata[1]\)" : "\($daydata[1]\)"; $titletext = ($daydata[2]) ? "$titletext " . substr("$daydata[2]",0,64) : "$titletext"; $celldata = $celldata . $webpage_obj->div( $webpage_obj->span({ -onclick => "SetCalForm('$thisdaymonth','$thismonth','$thisyear','viewday');", -title => "$titletext", -onmouseover => "window.status = '$viewphrase';return true;", -onmouseout => "window.status = '';return true;", -style => "text-decoration:none;background:$textbgcolor;color:$textfgcolor;font-size:smaller;cursor:pointer" },$daydata[0] ) ) ; } # Make cell stuff for print if($acttype eq 'print') { $celldata = $celldata . $webpage_obj->div( $webpage_obj->span({ -style => "background:$textbgcolor;color:$textfgcolor;font-size:smaller" },$daydata[0] ) ) ; } } } $cell = $cell . $celldata; } # Print this row if this is Europe and Monday if($europe && ($thisdayweek == 1)) { print $webpage_obj->Tr(@weekrow) if(@weekrow); @weekrow = (); } # Print this row if this is not Europe and Sunday elsif(!$europe && ($thisdayweek == 0)) { print $webpage_obj->Tr(@weekrow) if(@weekrow); @weekrow = (); } # Push this cell on to the week row push(@weekrow,$webpage_obj->td({-style=>"background-color:$cellbgcolor;vertical-align:top"},$webpage_obj->div({-style=>"min-height:70px"},$cell))); } # Close out the table and form print $webpage_obj->Tr(@weekrow) if(@weekrow); print "</table>\n"; # Put instructions # Print view icon print $webpage_obj->div({-style=>"color:$insfgcolor;font-weight:bold;font-size:smaller;text-align:center"}, $monthhowto),"<p />" if($acttype eq 'display'); # Standard return return 1; } # ---------------------------------------------------------- sub ViewYear { # Display all the months of selected year # with anchors to month view # Page is a block of floating tables where each table is a month in the year # Resizing the page should rearrange the tables (month) to fill the page width # Create the blocks of tables my($monthnum,$heading,@tablearray,@dayheadings,@atablerow,@tablerows,$thisdaysecs,$weekdaynum,$daynum,@wdtitles); # Need the number of seconds in a 24 hr day my($daysecs) = 24*60*60; # What year was selected? my($thisyear) = $seldate[2]; # Get the week day headings, 1st character of weekdaytitles @wdtitles = @weekdaytitles; push(@wdtitles, shift(@wdtitles)) if($europe); foreach $heading (@wdtitles) { push(@dayheadings,substr($heading,0,1)); } # Loop thru the 12 blocks (months) for($monthnum=0;$monthnum<=11;$monthnum++) { # Clear table rows for this month @tablerows = (); @atablerow = (); # next get the number of sec for the 1st day of today's month and today's year # This will be the starting number of seconds for the begining of this month $thisdaysecs = timegm(0,0,0,1,$monthnum,$thisyear); # Get the day of the week for the 1st day of this month $weekdaynum = (gmtime($thisdaysecs))[6]; # Adjust weekdaynum for europe if($europe) { $weekdaynum--; $weekdaynum = ($weekdaynum<0)?6:$weekdaynum; } ## Make weekrow ## # Pad calendar over to 1st day of the month push(@atablerow,$webpage_obj->th({-colspan => "$weekdaynum"})) if($weekdaynum); # Loop thru the days of this month for(;$thisdaysecs<=$thisdaysecs+$daysecs*31;$thisdaysecs += $daysecs) { # Is this still in this month? last if ((gmtime($thisdaysecs))[4] != $monthnum); # Get this day of the month and week ($daynum,$weekdaynum) = (gmtime($thisdaysecs))[3,6]; # Adjust weekdaynum for europe if($europe) { $weekdaynum--; $weekdaynum = ($weekdaynum<0)?6:$weekdaynum; } # Add this cell to the table row push(@atablerow, $webpage_obj->th({ -style => "font-weight:bold;color:$dayfgcolor;background-color:$daybgcolor;font-size:small" }, $daynum ) ); # Is this row complete? if($weekdaynum == 6) { push(@tablerows,join("",@atablerow)); @atablerow = (); } } if($atablerow[0]) { push(@tablerows,join('',@atablerow)); } push(@tablearray, $webpage_obj->div({-style=>"float:left;margin-left:1em;height:13em"}, $webpage_obj->table({-style=>"border-style:ridge;border-width:2px"}, $webpage_obj->Tr( $webpage_obj->th({ -colspan => "7", -style => "background-color:$myrbgcolor" }, $webpage_obj->submit( -name => (@monthtitles)[$monthnum], -style => "color:$myrfgcolor;background-color:$myrbgcolor;width:8em;font-weight:bold;font-size:medium;cursor:pointer", -onclick => "document.yearform.selmonth.value = $monthnum; document.yearform.acttype.value = 'display'; return true;" ) ) ), $webpage_obj->Tr([ $webpage_obj->th({ -style => "color:$wkdfgcolor;background-color:$wkdbgcolor;weight:bold;font-size:small" }, [@dayheadings] ), @tablerows ]) ) ) ); } # Make next and previous year buttons push(my(@nxtprebutts), $webpage_obj->div({-style=>"margin-left:1em;margin-bottom:2em:padding-left:2em"}, $webpage_obj->submit( -name => 'preyearbutt', -style => "color:$wkdfgcolor;background-color:$wkdbgcolor;font-size:medium;font-weight:bold;cursor:pointer", -value => ($thisyear-1), -onclick => "document.yearform.selyear.value = " . ($thisyear-1). "; document.yearform.acttype.value = 'viewyear';return true;" ), $webpage_obj->submit( -name => 'nxtyearbutt', -style => "color:$wkdfgcolor;background-color:$wkdbgcolor;font-size:medium;font-weight:bold;cursor:pointer", -value => ($thisyear+1), -onclick => "document.yearform.selyear.value=".($thisyear+1)."; document.yearform.acttype.value='viewyear';return true;" ) ) ); # Hide the others HideEm(\@nxtprebutts); # Start the page StartPage(); # Print the blocks of tables print $webpage_obj->div({-style=>"position:relative;margin-left:1em;margin-right:1em"}, $webpage_obj->startform( -name => 'yearform', -method => 'post', -action => "$scriptpath" ), $webpage_obj->hidden( -name => 'selmonth', -value => '0' ), $webpage_obj->hidden( -name => 'selyear', -value => "$thisyear" ), $webpage_obj->hidden( -name => 'acttype', -value => "display" ), @nxtprebutts, @tablearray, $webpage_obj->endform ) ; # Return status return 1; } # ---------------------------------------------------------- sub ViewCalForm { # Display the calendar form on the calendar page # this form can be used to select a year and month to view # Choose menus? if($chooseok) { my($chooseref) = MkChoose(); print (@$chooseref); } # Put the form in a table # Set the labels hash my(%retval) = ( '0' => "$monthtitles[0]", '1' => "$monthtitles[1]", '2' => "$monthtitles[2]", '3' => "$monthtitles[3]", '4' => "$monthtitles[4]", '5' => "$monthtitles[5]", '6' => "$monthtitles[6]", '7' => "$monthtitles[7]", '8' => "$monthtitles[8]", '9' => "$monthtitles[9]", '10' => "$monthtitles[10]", '11' => "$monthtitles[11]" ); my(@today) = gmtime(time-$gmtminos*60); $today[5] = $today[5] + 1900; print $webpage_obj->table({-border=>"2", -cellpadding=>"2", -cellspacing=>"3", -width=>"90%", -align=>"center"}, $webpage_obj->Tr([ $webpage_obj->th({-style=>"background-color:$myrbgcolor;width:92px", -rowspan=>"2"}, $webpage_obj->div({ -title => "$hometext", -style => "float:left;cursor:pointer;width:40px;height:40px;border-width:2px;border-style:outset;text-align:center;vertical-align:middle", -onclick => "document.location='$homepage'", -onmouseover => "window.status='$hometext'; return true;", -onmouseout => "window.status='';return true;" }, $webpage_obj->img({ -src => "$buttonimgdir/homebutton.gif" } ) ), $webpage_obj->div({ -title => "$printertext", -style => "float:right;cursor:pointer;width:40px;height:40px;border-width:2px;border-style:outset;text-align:center;vertical-align:middle", -onclick => "SetCalForm('1','$seldate[0]','$seldate[2]','print');", -onmouseover => "window.status='$printertext'; return true;", -onmouseout => "window.status='';return true;" }, $webpage_obj->img({ -src => "$buttonimgdir/printbutton.gif" } ) ) ) . $webpage_obj->th({-style=>"background-color:$myrbgcolor"},[ $webpage_obj->span({ -style => "background-color:$myrbgcolor;color:$myrfgcolor;font-weight:bold;font-size:larger" },"$gototitle" ), $webpage_obj->span({ -style => "background-color:$myrbgcolor;color:$myrfgcolor;font-weight:bold;font-size:larger" },"$selmonthtitle" ), $webpage_obj->span({ -style => "background-color:$myrbgcolor;color:$myrfgcolor;font-weight:bold;font-size:larger" },"$selyeartitle" ), $webpage_obj->span({ -style => "background-color:$myrbgcolor;color:$myrfgcolor;font-weight:bold;font-size:larger" },"$viewcaltitle" ) ]), $webpage_obj->th({-style=>"background-color:$mnubgcolor", -align=>"center", -valign=>"middle"},[ $webpage_obj->button( -name => $todaytitle, -style => "background-color:$mnubgcolor;color:$mnufgcolor;font-weight:bold;font-size:smaller;cursor:pointer", -onclick => "SetCalForm('$today[3]','$today[4]','$today[5]','display');" ), $webpage_obj->popup_menu( -name => 'selmonth', -style => "background-color:$mnubgcolor;color:$mnufgcolor;font-weight:bold;font-size:smaller", -size => '1', -values => ['0','1','2','3','4','5','6','7','8','9','10','11'], -labels => \%retval, -default => "$seldate[0]" ), $webpage_obj->popup_menu( -name => 'selyear', -style => "background-color:$mnubgcolor;color:$mnufgcolor;font-weight:bold;font-size:smaller", -default => "$seldate[2]", -size => '1', -values => [@menuyears] ), $webpage_obj->submit( -name => "$vwmobutton", -style => "background-color:$mnubgcolor;color:$mnufgcolor;font-weight:bold;font-size:smaller;cursor:pointer", -onclick => "document.calform.acttype.value='display';return true;" ) . ' ' . $webpage_obj->submit( -name => "$vwyrbutton", -style => "background-color:$mnubgcolor;color:$mnufgcolor;font-weight:bold;font-size:smaller;cursor:pointer", -onclick => "document.calform.acttype.value='viewyear';return true;" ) ]) ]) ); print $webpage_obj->endform; } # ---------------------------------------------------------- sub EnterDay { # Display the enter data form with the data already entered. # Return if not adminok if($adminon) { return if(!$adminok); } # Extract the day number using @seldate # @seldate format is month day year my($daynum) = timegm(0,0,0,$seldate[1],$seldate[0],$seldate[2]); my($dayofweek) = $weekdaytitles[(gmtime($daynum))[6]]; my($monthname) = $monthtitles[$seldate[0]]; # Get any data for this day from the dayinfo hash list # Hash array is Title,Subject,Comments,repeatby,repeatnum if (defined($dayinfo{$daynum})) { # Get each array of values for this day my(@daydata); foreach $entry (@{ $dayinfo{$daynum} }) { @daydata = split(/\{/,$entry); push(@dayvars,[ @daydata ]); } } # Get this days string my($datestring) = ($seldate[0]+1) . '/' . $seldate[1] . '/' . $seldate[2]; $datestring = $seldate[1] . '/' . ($seldate[0]+1) . '/' . $seldate[2] if($europe); # Load the javascript to process occurs time units # Create javascript match to string my($matchto) = join('|',@alwaysrepeat); push(my(@enterdayscript), 'var subjectexp = new RegExp(/'.$matchto.'/); function SetTimeUnit(entrynum) { var entrynum; var occursid = "occurs" + entrynum; var timeunitid = "timeunit" + entrynum; var fortextid = "fortext" + entrynum; var annonlyid = "annonly" + entrynum; var formid = entrynum + 1; var timeunit = document.getElementById(timeunitid); var fortext = document.getElementById(fortextid); var repeatbyidx = document.forms[formid].repeatby.selectedIndex; var repeatnum = document.forms[formid].repeatnum; var subjectidx = document.forms[formid].subject.options[document.forms[formid].subject.selectedIndex]; var annonly = document.getElementById(annonlyid); var ghostcolor = "#f8f8ff"; var normcolor = "'.$titlefgcolor.'"; annonly.style.visibility = "hidden"; // OK to set defaults? if(repeatbyidx > 0) { if(repeatnum.value == 1) repeatnum.value = 2; repeatnum.disabled = false; } timeunit.innerHTML = ""; timeunit.style.color = normcolor; repeatnum.style.color = normcolor; fortext.style.color = normcolor; // No repeats .. once only or always repeat if(repeatbyidx == 0 || subjectexp.test(subjectidx.value)) { repeatnum.disabled = true; timeunit.style.color = ghostcolor; repeatnum.style.color = ghostcolor; fortext.style.color = ghostcolor; } if(repeatbyidx == 0) { repeatnum.value = 1; timeunit.innerHTML = "'.$unittext{Day}.'"; } if(subjectexp.test(subjectidx.value)) { repeatnum.value = 99; annonly.style.visibility = "visible"; if(repeatbyidx < 9) { repeatbyidx = 9; document.forms[formid].repeatby.selectedIndex = 9; } } if(repeatbyidx >= 1 && repeatbyidx <= 3) { timeunit.innerHTML = "'.$unittext{Days}.'"; } if(repeatbyidx == 4 || repeatbyidx == 5) { timeunit.innerHTML = "'.$unittext{Weeks}.'"; } if(repeatbyidx >= 6 && repeatbyidx <= 8) { timeunit.innerHTML = "'.$unittext{Months}.'"; } if(repeatbyidx >= 9 && repeatbyidx <= 11) { timeunit.innerHTML = "'.$unittext{Years}.'"; } }', "function PreSetTimeUnit() { for(i=0;i<$maxentries;i++) { SetTimeUnit(i); } }", 'function ReSetTimeUnit(entry) { var entry; var formnum = entry + 1; var subjectidx = document.forms[formnum].subject.options[document.forms[formnum].subject.selectedIndex]; var repeatvalue = document.forms[formnum].repeatnum.value; if(!(subjectexp.test(subjectidx.value)) && (repeatvalue == 99)) document.forms[formnum].repeatby.selectedIndex = 0; SetTimeUnit(entry); }' ); $htmlstart{'-onload'} = 'PreSetTimeUnit();'; if(defined(&MkDingScript)) { my($dingscriptref) = MkDingScript(); push(@enterdayscript,@$dingscriptref); } my($scriptcode) = join("\n",@enterdayscript); $htmlstart{'-script'} = { -language => "JavaScript1.1", -type => 'text/javascript', -code => "$scriptcode" }; # Start the page StartPage(); # Set the entry number string my($entrynumstr)=1; # Top of the page push(my(@pagetop), '<hr width="95%"/>', "\n</center>\n" ); push(@pagetop, $webpage_obj->div({-style=>"font-size:120%;color:$insfgcolor;font-weight:bold"},"<u>$howtotitle</u>"), $webpage_obj->div({-style=>"font-size:80%;color:$insfgcolor"},"<u>$howtoinstruct</u>") ) if($showinstructions); print "@pagetop"; # Instructions print $webpage_obj->ul( $webpage_obj->li({-style=>"list-style-type: disc; font-weight: bold"},[ "$titletitle" . $webpage_obj->ul( $webpage_obj->li({-style=>"list-style-type: circle; font-weight: bold"}, "$instructions{$titletitle}") ), "$subjecttitle" . $webpage_obj->ul( $webpage_obj->li({-style=>"list-style-type: circle; font-weight: bold"}, "$instructions{$subjecttitle}") ), "$commenttitle" . $webpage_obj->ul( $webpage_obj->li({-style=>"list-style-type: circle; font-weight: bold"}, "$instructions{$commenttitle}") ), "$occurstitle" . $webpage_obj->ul( $webpage_obj->li({-style=>"list-style-type: circle; font-weight: bold"}, "$instructions{$occurstitle}") ) ]) ) if($showinstructions); print "<hr align='center' width='95%'/>" if($showinstructions); # Display the maxentries form tables # PreSet the subject, repeatnum .. repeat by number # and repeatby .. repeat every what: days, weeks my($title) = ""; my($subject) = "$sbjdefault"; my($repeatnum) = 1; my($repeatby) = "Once"; my($comment) = ""; my($titlebgselect) = 'none'; my(@entrytable,$categories,$subjecttitlebox,%subjectlist,$entrynum,@hidethese,$formstart); my($dingfamref) = \0; $subjecttitlebox = $subjecttitle . ' '; # Preset the subject list %subjectlist = ( -name => "subject", -size => '4', -values => [@sbjlist], -default => "$subject", -style => "color:$sbjfgcolor;background-color:$sbjbgcolor;font-weight:bold" ); # Loop to show each entry box for ($entrynum=0;$entrynum<$maxentries;$entrynum++) { # Get the name, subject, comment, repeat by and repeat number if (defined($dayvars[$entrynum]->[1]) && ($dayvars[$entrynum]->[1] ne 'DELETED')) { $title = $dayvars[$entrynum]->[0] if($dayvars[$entrynum]->[0]); $subject = $dayvars[$entrynum]->[1] if($dayvars[$entrynum]->[1]); $comment = $dayvars[$entrynum]->[2] if($dayvars[$entrynum]->[2]); $repeatby = $dayvars[$entrynum]->[3] if($dayvars[$entrynum]->[3]); $repeatnum = $dayvars[$entrynum]->[4] if($dayvars[$entrynum]->[4]); # Replace html break code $comment =~ s/<br\/>\ /\n/g; # Extract the bg color for the text if($title =~ /^#.{6}\s/) { $titlebgselect = $titlebgvalues[0]; $titlebgselect = substr($title,0,7); # Don't show background color in the title field $title =~ s/^#.{6}\s//; } if($dingsok) { # Get the dings family style code $dingfamref = ExtractDing(\$title) if($title); if($$dingfamref) { # Don't show the w..dings ClearDings(\$title); } } } # Grandfather in the old database $repeatby = 'Once' if(($repeatby =~ /Day/) && ($repeatnum == 1)); # Preset the default subject $subjectlist{'-default'} = "$subject"; # Start the form $formstart = "\n" . $webpage_obj->startform( -method => 'post', -action => "$scriptpath", -name => 'entryform' . $entrynum ); # Set the form number push(@hidethese,$webpage_obj->hidden(-name=>"formnum", -value=>"$entrynum")."\n"); # set the day, month and year push(@hidethese, $webpage_obj->hidden(-name=>"selmonth", -value=>"$seldate[0]")."\n", $webpage_obj->hidden(-name=>"selday", -value=>"$seldate[1]")."\n", $webpage_obj->hidden(-name=>"selyear", -value=>"$seldate[2]")."\n" ); # Hide the default hidden params HideEm(\@hidethese); # Make the categories MkCategories(\$categories,$titlebgselect); # Default function for subject list onchange $subjectlist{"-onchange"} = "ReSetTimeUnit($entrynum);"; # Set the box for the title and ding stuff if($dingsok) { $subjecttitlebox = $subjecttitle.' '.$webpage_obj->div({-id=>'ding'.$entrynum, -style=>"color:$sbjfgcolor;margin-top:8px;font-family:webdings;font-weight:normal;font-size:larger"},''); # Append the show ding javascript function to onchange $subjectlist{"-onchange"} ="ShowDing($entrynum);" . $subjectlist{"-onchange"}; } # Load the table push(@entrytable, $webpage_obj->caption({-style=>"color:$capfgcolor;font-size:larger;font-weight:bold"}, "#$entrynumstr, $dayofweek, $monthname $seldate[1], $seldate[2] ($datestring)" ), $webpage_obj->Tr([ $webpage_obj->td({-style=>"background-color:$cmtbgcolor;align:left;width:46%"}, $webpage_obj->div({ -style=>"font-size:large;font-weight:bold;color:$titlefgcolor;float:left;padding-left:8px;padding-right:2px" }, "$titletitle " ) . $webpage_obj->input({ -name => "title", -type => "text", -size => "$maxtitlelen", -value => "$title", -style => "color:$titlefgcolor;background-color:$titlebgcolor;font-weight:bold;margin-left:8px" }) . "\n" . $categories ) . $webpage_obj->td({-style=>"background-color:$cmtbgcolor;align:left;width:54%"}, $webpage_obj->span({ -style=>"color:$titlefgcolor;font-size:large;font-weight:bold;float:left;padding-left:8px;padding-right:3px" }, "$occurstitle" ) . $webpage_obj->popup_menu( -name => "repeatby", -size => "1", -values => [qw(Once Day WkDay BiDay Week BiWeek Month MonthXweekday MonthLastXweekday Year YearXweekday YearLastXweekday)], -labels => { 'Once' => "$repeatlabels[0]", 'Day' => "$repeatlabels[1]", 'WkDay' => "$repeatlabels[2]", 'BiDay' => "$repeatlabels[3]", 'Week' => "$repeatlabels[4]", 'BiWeek' => "$repeatlabels[5]", 'Month' => "$repeatlabels[6]", 'MonthXweekday' => "$repeatlabels[7]", 'MonthLastXweekday' => "$repeatlabels[8]", 'Year' => "$repeatlabels[9]", 'YearXweekday' => "$repeatlabels[10]", 'YearLastXweekday' => "$repeatlabels[11]" }, -default => "$repeatby", -style => "color:$titlefgcolor;background-color:$titlebgcolor;font-weight:bold", -onchange => "SetTimeUnit($entrynum);" ) . $webpage_obj->span({ -id => "fortext" . $entrynum, -style => "color:$titlefgcolor;font-size:large;font-weight:bold;padding-left:3px;padding-right:3px" }, $theforword ) . $webpage_obj->input({ -name => "repeatnum", -type => "text", -size => "2", -maxlength => "2", -value => "$repeatnum", -style => "color:$titlefgcolor;background-color:$titlebgcolor;font-weight:bold" }) . $webpage_obj->span({ -id => "timeunit" . $entrynum, -style => "color:$titlefgcolor;font-size:large;font-weight:bold;padding-left:3px" }, "" ) ), $webpage_obj->th({-style=>"background-color:$cmtbgcolor;align:center"}, $webpage_obj->div({ -style=>"float:left;padding-left:8px;color:$sbjfgcolor;font-size:large" }, $subjecttitlebox ) . $webpage_obj->div({ -id => "annonly" . $entrynum, -style => "color:$titlefgcolor;font-weight:bold;float:right;padding-right:8px;padding-top:10px;visibility:hidden;font-size:medium" }, $annualtext ) . $webpage_obj->div({ -style=>"color:$sbjfgcolor" }, $webpage_obj->scrolling_list(%subjectlist) ) ) . $webpage_obj->th({-style=>"background-color:$cmtbgcolor;align:center"}, $webpage_obj->span({ -style=>"color:$cmtfgcolor;font-size:large;float:left;padding-left:8px" }, "$commenttitle " ) . $webpage_obj->textarea( -name => "comment", -rows => "3", -columns => "32", -default => "$comment", -style => "color:$cmtfgcolor;background-color:$cmtbgcolor;font-weight:bold" ) ), $webpage_obj->th({-style=>"background-color:$acdbgcolor;align:center", -colspan=>'2'}, $webpage_obj->div({ -style => "float:left;margin-left:40px;border-width:2px;border-style:ridge" }, $webpage_obj->submit( -name => "deldata", -label => "$deletelabel #$entrynumstr", -style => "color:$acdfgcolor;background-color:$acdbgcolor;font-weight:bold;font-size:larger;cursor:pointer" ) ) . $webpage_obj->div({ -style => "float:right;margin-right:40px;border-width:2px;border-style:ridge" }, $webpage_obj->submit( -name => "newdata", -label => "$applylabel #$entrynumstr", -style => "color:$acdfgcolor;background-color:$acdbgcolor;font-weight:bold;font-size:larger;cursor:pointer" ) ) . $webpage_obj->div({ -style => "border-width:2px;border-style:ridge" }, $webpage_obj->reset( -value => "$resetlabel #$entrynumstr", -style => "color:$acdfgcolor;background-color:$acdbgcolor;font-weight:bold;font-size:larger;cursor:pointer", -onclick => "document.entryform$entrynum.reset();SetTimeUnit($entrynum);return(false);" ) ) ) ]) ); # Print the start of form, what's hidden, the table, and end of form print($formstart,@hidethese, $webpage_obj->table({-border=>"2",-align=>"center",-width=>"80%"},@entrytable), "\n".$webpage_obj->endform, "\n".'<hr width="75%" size="2"></hr>' ); # Inc the entry number string $entrynumstr++; # ReSet the defaults $title = ""; $subject = "$sbjdefault"; $repeatnum = 1; $repeatby = "Once"; $comment = ""; $titlebgselect = 'none'; @entrytable = (); $categories = ''; @hidethese = (); } # Return status return 1; } # ---------------------------------------------------------- sub MkCategories { # Make the categories section # Takes reference to the categories section string # Also, takes titlebgselect value # Returns nothing my($catref) = shift; my($titlebgselect) = shift; my($titlebgwidth) = ($titlebgsize + 0.4) . 'em'; # Set the background color for each entry my($color,@radiobuttons,$checkok); foreach $color (@titlebgvalues) { next if(!$titlebgmap{$color}); $checkok = ($color eq $titlebgselect) ? 'checked' : ''; push(@radiobuttons, $webpage_obj->span({ -style=>"border-width:1px;border-style:dotted;color:$titlefgcolor;font-weight:bold;float:left;width:$titlebgwidth;background-color:$color" }, "<input type=\"radio\" name=\"titlebgselect\" value=\"$color\" $checkok" . " style=\"color:$titlefgcolor;background-color:$color;font-weight:bold;font-size:smaller\">" . substr($titlebgmap{$color},0,$titlebgsize) . "</input>" ) ); } # Set the category section. Note the position arg allows the # radio buttons to flow with the size of the page $$catref = $webpage_obj->div({ -style=>"color:$titlefgcolor;font-weight:bold;font-size:smaller;position:relative;margin-left:8px;margin-right:4px"}, join("",@radiobuttons) ); } # ---------------------------------------------------------- sub ViewDay { # View the day's data. # Extract the day number using @seldate # @seldate format is month day year my($daynum) = timegm(0,0,0,$seldate[1],$seldate[0],$seldate[2]); my($dayofweek) = $weekdaytitles[(gmtime($daynum))[6]]; my($monthname) = $monthtitles[$seldate[0]]; # Get any data for this day from the dayinfo hash list # Hash array is Title,Subject,Comments,repeatby,repeatnum my($entry, @daydata, @dayvars); if (defined($dayinfo{$daynum})) { # Get each array of values for this day foreach $entry (@{$dayinfo{$daynum}}) { next if(!$entry); @daydata = split(/\{/,$entry); next if($chooseok && !ChoiceOk(\@daydata)); push(@dayvars, [ @daydata ]); } } # Get this days string my($datestring) = ($seldate[0]+1) . '/' . $seldate[1] . '/' . $seldate[2]; $datestring = $seldate[1] . '/' . ($seldate[0]+1) . '/' . $seldate[2] if($europe); # Start the page StartPage(); # PreSet the subject my($subject) = ""; # Display view tables with the data print "\n<hr width='90%' />\n" . '<table border=0 width=90% align="center">' . $webpage_obj->caption({-style=>"color:$capfgcolor;font-size:larger;font-weight:bold"}, "$dayofweek, $monthname $seldate[1], $seldate[2] ($datestring)" ) . $webpage_obj->Tr( $webpage_obj->td({-style=>"background-color:$pnbgcolor", -colspan=>"2"}, "<hr width=97% size=4>" ) ) ; my($entrydataref,$urlstring,$urllink,$urlcnt,$inhere,$urllen,$url,$commentfield,$backcolor,$colorstring); foreach $entrydataref (@dayvars) { next if((!defined($entrydataref->[0])) || ($entrydataref->[1] eq 'DELETED')); # Get and Remove background color prefix $backcolor = $titlebgcolor; if($entrydataref->[0] =~ /^\#.{6}\s/) { $backcolor = substr($entrydataref->[0],0,7) if($catagorycoloron); $entrydataref->[0] =~ s/^\#.{6}\s//; } # Get the string associated with the back highlight color $colorstring = ''; $colorstring = $titlebgmap{$backcolor} if(defined($titlebgmap{$backcolor})); # Make url links in the comment field if it looks like there are any $commentfield = $entrydataref->[2]; ParseLinks(\$commentfield); # load ding code if there is one DisplayDing($entrydataref) if($dingsok); # Title Cells my($titlecells) = $webpage_obj->td({-bgcolor=>"$backcolor", -align=>'left'}, "$entrydataref->[0]"); $titlecells = $webpage_obj->td({-bgcolor=>"$backcolor", -align=>'left'}, "$colorstring .. $entrydataref->[0]") if($colorstring); $titlecells = $webpage_obj->th({-bgcolor=>"$titlebgcolor", -width=>"20%"}, "$titletitle") . $titlecells; # All view day table cells push(my(@viewtablecells), $titlecells, $webpage_obj->th({-style=>"background-color:$sbjbgcolor;width:20%"}, "$subjecttitle") . $webpage_obj->td({-style=>"background-color:$backcolor;align:left"}, "$entrydataref->[1]"), $webpage_obj->th({-style=>"background-color:$cmtbgcolor;width:20%"}, "$commenttitle") . $webpage_obj->td({-style=>"background-color:$backcolor;align:left"}, "$commentfield"), $webpage_obj->td({-style=>"background-color:$pnbgcolor", -colspan=>"2"}, "<hr width=97% size=4>") ); # Put in the table rows print $webpage_obj->Tr([ @viewtablecells ]); } # Close the table print "</table>\n"; # Return status return 1; } # ---------------------------------------------------------- sub ParseLinks { # Parse the text for links # Takes a reference to the text. # Returns nothing my($text_ref) = shift; # Parse for text begining with urls # Code from The Perl Journal my($urls) = "(" . join('|',qw{http ftp gopher telnet wais file}) . ")"; my($uris) = "(" . join('|',qw{mailto news}) . ")"; my($ltrs) = '\w'; my($gunk) = '/#~:.?+=&%@!\-'; my($punc) = '.:?\-'; my($any) = "${ltrs}${gunk}${punc}"; # This is for links that begin with an url .. see $urls $$text_ref =~ s{\b(${urls}:[$any]+?)(?=[$punc]*[^$any]|\Z)}{<a href="$1" target="comment_link">$1</a>}goix; # This is for links that begin with an uri .. see $uris $$text_ref =~ s{\b(${uris}:[$any]+?)(?=[$punc]*[^$any]|\Z)}{<a href="$1">$1</a>}goix; # This is for links that start with <sp>www $$text_ref =~ s{\s(www[\.${ltrs}]+?)(?=[$punc]*[^$any]|\Z)}{<a href="http://$1" target="comment_link">$1</a>}goix; } # ---------------------------------------------------------- sub NewData { # Get and enter the new data into the calendar database file # How it works # 1. Create a new database row in the database using the %dayinfo hash # 2. Append new data into the database file # Return if not adminok if($adminon) { return if(!$adminok); } # Get the newdata # New data entry number is designated by the submit title # Extract the day number using @seldate # @seldate format is month day year my($daynum) = timegm(0,0,0,$seldate[1],$seldate[0],$seldate[2]); # Create the row for the database file # row format is "daysec id number|title,subject,comment,repeat # by,repeat number # Then repeats for each entry without daysecs id number # Check which one this is (1st, 2nd, ...) my($arrayloc) = $webpage_obj->param('formnum') || 0; # Get the data to be entered .. replace all bad chars with spaces my($title) = $webpage_obj->param('title') || ''; my($subject) = $webpage_obj->param('subject') || ''; my($comment) = $webpage_obj->param('comment') || ''; my($repeatby) = $webpage_obj->param('repeatby') || 'Once'; my($repeatnum) = $webpage_obj->param('repeatnum') || 1; my($titlebgselect) = $webpage_obj->param('titlebgselect') || 'none'; # No need to keep these parameters $webpage_obj->delete('title'); $webpage_obj->delete('subject'); $webpage_obj->delete('comment'); $webpage_obj->delete('repeatby'); $webpage_obj->delete('repeatnum'); $webpage_obj->delete('titlebgselect'); # remove any pipes,braces, & ^M $title =~ s/[\{\|\cM]//g; $subject =~ s/[\{\|\cM]//g; $comment =~ s/[\{\|\cM]//g; $repeatby =~ s/[\{\|\cM]//g; $repeatnum =~ s/[\{\|\cM]//g; $titlebgselect =~ s/[\{\|\cM]//g; # html-ise comments $comment =~ s/\t/\ \ \ \ /g; $comment =~ s/\n/<br\/>\ /g; # Do nothing if there is nothing to do # Note that nothing in title replaces something in database # Rev 2.9.8 return if(!($title || $dayinfo{$daynum}->[$arrayloc])); # Mark as deleted if deleted $title = '' if($title !~ /[0-z]+/); $subject = "DELETED" if(($acttype eq 'deldata') || (!$title && $dayinfo{$daynum}->[$arrayloc])); # OK to use holiday processing? # To enter holidays into the holiday database, three things have to be true # 1. Holiday ok flag is set # 2. The subject is $holiday # 3. selected year is 2000 .. all holidays, excluding those like Easter, epoch in the year 2000 # This is so that earlier entries with repeats on the entered holiday don't overwrite it $holidayok = ($holidayok && ($subject eq $holiday) && ($seldate[2] == 2000)); # Load dings .. no dings for holidays in holiday database LoadDing(\$title,$subject) if($dingsok && !$holidayok); # Prefix the selected title bg color to title .. no highlight for holidays in holiday database $title = $titlebgselect . " " . $title if(($titlebgselect =~ /\#.{6}/) && !$holidayok); # Create the database entry my($dbentry) = join('{',$title,$subject,$comment,$repeatby,$repeatnum); # Put this into the dayinfo hash list at its proper location $dayinfo{$daynum}->[$arrayloc]="$dbentry"; # Preset the dbfile my($dbfile) = $majordbfile; my($dayentry,$dbrow); # Append the data if this is to put into the holiday database if($holidayok) { # Set the dbfile to the holiday database $dbfile = $holidaydbfile; die("ERROR .. unable to open $dbfile\n") unless open(DBFILE,">>$dbfile"); # Start the db row with the daysecs id number $dbrow = "$daynum"; # Put in the pipe delimiters foreach $dayentry (@{$dayinfo{$daynum}}) { $dbrow = join('|',$dbrow,$dayentry); } print(DBFILE "$dbrow\n"); close(DBFILE); return; } # Enter the data into the database file # As of ver 3.0, all the database is re-written to prevent duplicate and deleted entries # this in-turn, reduces the size of the database. However, no history is retained # Note .. This is not so for the holiday database. See above. die("ERROR .. unable to write $dbfile\n") unless(-w $dbfile && open(DBFILE,">$dbfile")); my($dayindex); foreach $dayindex (sort{$a<=>$b} keys %dayinfo) { # Start each row in the database with the day number. $dbrow = $dayindex; # Loop the entries for this day foreach $dayentry (@{$dayinfo{$dayindex}}) { # Entries must have a title and not have a subject of DELETED $dbrow = join('|',$dbrow,$dayentry) if($dayentry && $dayentry !~ /(^{)|(^.+{DELETED{)/); } print(DBFILE "$dbrow\n") if($dbrow ne $dayindex); } close(DBFILE); } # ---------------------------------------------------------- sub LoadScript { # Loads the javascript code for use by webpage_obj->start_html push(@jscode, { -language => 'JavaScript1.1', -type => 'text/javascript', -code => ' function SetGmtOffset() { // function to set the minutes from gmt the local time is var thedate = new Date(); document.calform.gmtminos.value = thedate.getTimezoneOffset(); } function SetCalForm(theday, themonth, theyear, theacttype) { // function to load the calform with the selected parameters document.calform.selday.value = theday; document.calform.selmonth.options[themonth].selected=true; document.calform.acttype.value = theacttype; // Get the index for the year selected for(i=0;i<document.calform.selyear.options.length;i++) { if(document.calform.selyear.options[i].text == theyear) break; } document.calform.selyear.options[i].selected=true; // submit the form with the new values document.calform.submit(); }' } ); } # ---------------------------------------------------------- sub StartPage { # Start the html page # Gets nothing but uses acttype to determin what type of page this is # Returns nothing # Set the default header stuff and print it %theheader=( -type => 'text/html', -expires => '-1d', -charset => 'iso-8859-1' ); print $webpage_obj->header(%theheader); # Get the title my($thetitle) = $caltitle; $thetitle = $enpgtitle if($acttype eq 'enterday'); $thetitle = $dypgtitle if($acttype eq 'viewday'); $thetitle = $yrpgtitle . ' ' . $seldate[2] if($acttype eq 'viewyear'); # Reset the title for the base html start tags $htmlstart{'-title'} = "$thetitle"; # %htmlstart should be already setup print $webpage_obj->start_html(%htmlstart); # Check for no script push(my(@noscripttext), '<noscript> <hr size=4 /> <h1 style="text-align:center">This page uses javascript 1.1</h1> For this page to function properly, your browser must support javascript 1.1. <br /> Your browser either does not support javascript or has javascript support disabled. <br /> Javascript support must be enabled to correctly view and interact with this page. <br /> For a browser upgrade, I recommend at least Netscape 6, or Mozilla 1.1 <br /> <hr size=4 /> </noscript>' ); print @noscripttext if($acttype ne 'print'); # Top of the page push(my(@topofpage), $webpage_obj->h1({-style=>"color:$caltitlecolor;text-align:center;font-size:X-large"},"<u>$thetitle</u>") ); # Demo mode hidden vars my($tohide); my(@hiddenparams) = qw(admindemo dingsoff chooseoff groupsortoff moonphaseoff); if($acttype eq 'display') { # Set the select form of hidden values push(@topofpage, $webpage_obj->startform( -name => 'calform', -method => 'post', -action => "$scriptpath" ) ); # Create the hidden gmt minute offset push(@topofpage, $webpage_obj->hidden( -name => 'gmtminos', -value => "$gmtminos" ) ); # Required hidden to transfer to other pages push(@topofpage, $webpage_obj->hidden( -name => "selday", -value => '1' ), $webpage_obj->hidden( -name => "acttype", -value => 'display' ) ); # Hide group by if groupby exists push(@topofpage,$webpage_obj->hidden(-name=>'groupby',-value=>"$groupby")) if($groupsortok); # Include hidden demo mode foreach $tohide (@hiddenparams) { push(@topofpage,"\n".$webpage_obj->hidden(-name=>"$tohide",-value=>'1')) if($webpage_obj->param($tohide)); } } if($acttype !~ /display|print/) { push(@topofpage, $webpage_obj->startform(-name=>'return',-action=>"$scriptpath")); # Add the return button push(@topofpage, $webpage_obj->div({-style=>"text-align:center"}, $webpage_obj->submit( -style => "background-color:$pagebgcolor;color:$ctxtfgcolor;font-weight:bold;cursor:pointer", -name => 'Back', -label => "$returntitle" ) ) ); # Hide the other params HideEm(\@topofpage); # Hide the default params for the return button and end the form push(@topofpage, $webpage_obj->hidden(-name=>'selmonth',-value=>"$seldate[0]")."\n", $webpage_obj->hidden(-name=>'selday', -value=>"$seldate[1]")."\n", $webpage_obj->hidden(-name=>'selyear', -value=>"$seldate[2]")."\n", $webpage_obj->hidden(-name=>'gmtminos',-value=>"$gmtminos")."\n", $webpage_obj->endform,"\n" ) } # View top of page print "@topofpage"; } # ---------------------------------------------------------- sub HideEm { # Create hidden params # Takes and loads the ref to the array of where to put the hide param code # returns nothing my($hidecoderef) = shift; my(@hiddenparams) = qw(admindemo dingsoff chooseoff groupsortoff moonphaseoff); # Demo mode hidden vars foreach $tohide (@hiddenparams) { push(@$hidecoderef,$webpage_obj->hidden(-name=>"$tohide",-value=>'1')."\n") if($webpage_obj->param($tohide)); } # Hide the choices if using choose (i.e search) HideChoices($hidecoderef) if($chooseok); # Hide group by if using groupsort and groupby exists push(@$hidecoderef,$webpage_obj->hidden(-name=>'groupby',-value=>"$groupby")) if($groupsortok); } # ---------------------------------------------------------- sub GetMoonImage { # Get the image for the phase of the moon # Takes seconds for the day, otherwise know as the day index, # And references to the moonimage & the mooncomment # Returns status .. 1 = ok, 0 = not ok my($seconds) = shift; my($image_ref) = shift; my($comment_ref) = shift; # Return if not ok to calculate moon phases and get images return(0) if(!($moonphaseok && $seconds)); my($imagepath) = $moonimgdir . '/'; # Phase is a number between 0 (new moon) and 1000000 also new moon) # Therefore, 500000 is a full moon .. note: phase actually returns a fraction between 0 & 1 # But its rounded to 7 digits # Get the moon information my($phasefract) = Astro::MoonPhase::phase($seconds); # To deal with integers, sprintf rounds the fraction my($phasenum) = sprintf("%7.0f",1000000*$phasefract); # Range is the number between the min and max phase number that a phase is in my($range) = 53850; my($halfrange) = $range/2; # New Moon my($newmin) = 1000000 - $halfrange; my($newmax) = $halfrange; # 1st quarter my($firstmin) = 250000 - $halfrange; my($firstmax) = 250000 + $halfrange; # Full Moon my($fullmin) = 500000 - $halfrange; my($fullmax) = 500000 + $halfrange; # Last quarter my($lastmin) = 750000 - $halfrange; my($lastmax) = 750000 + $halfrange; # Images for each phase my($newimage) = "new_sml.gif"; my($firstimage) = "first_sml.gif"; my($fullimage) = "full_sml.gif"; my($lastimage) = "last_sml.gif"; my($theimage,$comment); $theimage = $comment = ''; if(($phasenum >= $newmin) || ($phasenum <= $newmax)) { $theimage = ($imagepath . $newimage); $comment = "$moonword_new"; } if(($phasenum >= $firstmin) && ($phasenum <= $firstmax)) { $theimage = ($imagepath . $firstimage); $comment = "$moonword_first"; } if(($phasenum >= $fullmin) && ($phasenum <= $fullmax)) { $theimage = ($imagepath . $fullimage); $comment = "$moonword_full"; } if(($phasenum >= $lastmin) && ($phasenum <= $lastmax)) { $theimage = ($imagepath . $lastimage); $comment = "$moonword_last"; } if($theimage) { $$image_ref = $theimage; $$comment_ref = $comment; return(1) } return(0); } # ---------------------------------------------------------- sub GetEaster { # Get the date for Easter, Good Friday, & Ash Wed .. or should I say calculate # Receives the present year and month # Returns nothing but sets $dayinfo hash accordingly # How it's done # A is Year MOD 19 # B is Year MOD 4 # C is Year MOD 7 # D is (19 * A + 24) MOD 30 # E is (2 * B + 4 * C + 6 * D + 5) MOD 7 # Where MOD is "the remainder after division by". # Then Easter Sunday is March (22 + D + E). (The date will of course be in April if (22 + D + E) > 31.) my($year) = shift; my($month) = shift; my($A,$B,$C,$D,$E); $A = $year % 19; $B = $year % 4; $C = $year % 7; $D = (19 * $A +24) % 30; $E = (2 * $B + 4 *$C +6 *$D +5) % 7; # Convert to secs my($addsecs) = $D*24*60*60 + $E*24*60*60; my($eastersecs) = timegm(0,0,0,22,2,$year) + $addsecs; my($eastermonth) = (gmtime($eastersecs))[4]; my($daysecs) = 24*60*60; my($gfridaysecs) = $eastersecs - 2 * $daysecs; my($gfrimonth) = (gmtime($gfridaysecs))[4]; my($ashwedsecs) = $eastersecs - 46 * $daysecs; my($ashwedmonth) = (gmtime($ashwedsecs))[4]; my($palmsunsecs) = $eastersecs - 7 * $daysecs; my($palmsunmonth) = (gmtime($palmsunsecs))[4]; # Set the %dayinfo hash to indicate Easter my(@easterinfo) = ("$easter\{$holiday\{$easter\{Once\{1"); my(@gfridayinfo) = ("$gfriday\{$holiday\{$gfriday\{Once\{1"); my(@ashwedinfo) = ("$ashwed\{$holiday\{$ashwed\{Once\{1"); my(@palmsuninfo) = ("$palmsun\{$holiday\{$palmsun\{Once\{1"); # Easter in this month if($eastermonth == $month) { if(!defined($dayinfo{$eastersecs})) { $dayinfo{$eastersecs} = [@easterinfo]; } else { push(@{$dayinfo{$eastersecs}},@easterinfo); } } # Good Friday in this month if($gfrimonth == $month) { if(!defined($dayinfo{$gfridaysecs})) { $dayinfo{$gfridaysecs} = [@gfridayinfo]; } else { push(@{$dayinfo{$gfridaysecs}},@gfridayinfo); } } # Ash Wed in this month if($ashwedmonth == $month) { if(!defined($dayinfo{$ashwedsecs})) { $dayinfo{$ashwedsecs} = [@ashwedinfo]; } else { push(@{$dayinfo{$ashwedsecs}},@ashwedinfo); } } # Palm Sunday in this month if($palmsunmonth == $month) { if(!defined($dayinfo{$palmsunsecs})) { $dayinfo{$palmsunsecs} = [@palmsuninfo]; } else { push(@{$dayinfo{$palmsunsecs}},@palmsuninfo); } } } # ---------------------------------------------------------- sub GetLanguage { # Get the language file opendir(LANGDIR,"./"); my(@languages) = grep(/^eventcallang/,readdir(LANGDIR)); close(LANGDIR); return if(!$languages[0]); # Use the 1st, and hopefully only, language file seen if(-r "./$languages[0]") { require "./$languages[0]"; } } # ---------------------------------------------------------- sub EndPage { # Send out page trailer info print $webpage_obj->h5({-style=>'text-align:center;color:brown'}, "Original .. <a href='http://www.nermware.com'>$origcom</a><br>Adapted .. $adaptcom"); if($usemyemail) { print $webpage_obj->div({-style=>"text-align: center"}, $webpage_obj->start_form,$webpage_obj->button( -style => "background-color:$pagebgcolor;color:$ctxtfgcolor;cursor:pointer", -value => "Email To: $myemail", -onClick => "location=\'mailto:$myemail\'" ),$webpage_obj->end_form ); } } # ---------------------------------------------------------- sub ErrorPage { # The output when pagestat is 0 # Something went wrong .. unable to send out a page # Takes nothing but uses $acttype # Returns nothing print $webpage_obj->header; # Set the title $htmlstart{'-title'} = "Event Calendar Error"; # %htmlstart should be already setup print $webpage_obj->start_html(%htmlstart); # De-taint $acttype; $acttype =~ s/[;:?@&$.`]/ /g; # Explanation of error print($webpage_obj->h1({-style=>"text-align:center;color:white;background-color:blue"},"Event Calendar Error"), $webpage_obj->h2({-style=>"text-align:center;color:white;background-color:blue"},"Unable to perform action $acttype."), $webpage_obj->end_html ); } # ---------------------------------------------------------- sub SanityCheck { # Check to see if all the pieces I need are availible my($homeurl) = $webpage_obj->self_url(); # base url? $baseurl = substr($homeurl,0,index($homeurl,'/',7)+1) if(!$baseurl); # My name? my($filename,$dirpath,$filesuffix) = fileparse($0,('\.pl','\.cgi')); $scriptname = $filename.$filesuffix if(!$scriptname); # cgidir? if(!$cgidir) { # The cgi directory should be relative to the web page's home directory $cgidir = dirname(substr($homeurl,length($baseurl))); } croak("\$cgidir=$cgidir, \$baseurl=$baseurl, \$scriptname=$scriptname. These must be set.\n") if(!($cgidir && $baseurl && $scriptname)); # Check for database directory ($filename,$dirpath,$filesuffix) = fileparse($majordbfile); my(@dirs) = split('/',$dirpath); my($shortpath, @croakmsg, $croakstr); for($i=1;$i<=$#dirs;$i++) { $shortpath = join('/',@dirs[0..$i]); push(@croakmsg,$shortpath) if(! -e $shortpath); } if($croakmsg[0]) { $croakstr = join(',',@croakmsg); croak('Please create these missing directories: ' . $croakstr . "\n"); } # Check for database file if(! -e $majordbfile) { open(DBFILE,">$majordbfile"); close DBFILE; } # Check for holiday database file if(! -e $holidaydbfile) { open(DBFILE,">$holidaydbfile"); close DBFILE; } } # ---------------------------------------------------------- # ---------------------------------------------------------- ## Main Start ## # Set Rev. $rev = "3.2"; # Create webpage object $webpage_obj = new CGI; # Am I ok? SanityCheck() if($sanitycheckok); # Get language file GetLanguage(); # Clear jscode & cookie @jscode = (); $cookiepass = ''; # path/name of this script in the cgi directory $scriptpath = $cgidir . '/' . $scriptname; # Every page has a meta comment indicating original source .. Please do # not change this $origcom = "eventcalendar.pl Rev $rev .. Nermware"; # Set the overall style $style = "color:$ctxtfgcolor;\nfont-size:$fontsize;\nfont-family:$fontfamily;\nbackground-color:$pagebgcolor"; # Background Image? $style = $style.";\nbackground:url($background) $bgimgrepeat $bgimgplace" if($background); # Set base html start tags %theheader = (); %htmlstart = ( -meta => {'Author',"$origcom",'Adapted',"$adaptcom"}, -author => "$myemail", -title => "$calpgtitle", -xbase => "$baseurl", -link => "$ctxtfgcolor", -vlink => "$ctxtfgcolor", -style => {-code => "body \{$style\}"}, -dtd => "-//W3C//DTD HTML 4.01 Transitional//EN" ); $htmlstart{'-style'} = {-src=>$csspath} if($csspath); # Webdings? $dingsok = (-r './dings.pm' && !$webpage_obj->param('dingsoff'))?require dings:0; # OK to show phase of the moon $moonphaseok = ($moonphaseok && !$webpage_obj->param('moonphaseoff') && require MoonPhase)?1:0; # OK to use the choose option $chooseok = (-r './choose.pm' && !$webpage_obj->param('chooseoff'))?require choose:0; GetChoiceParams() if($chooseok); # Get the action .. default is display calendar $acttype = GetActType(); # Get the selected month or present month if none is selected. @seldate = GetSelDate(); # Do Admin Stuff $adminok = (-r './eventcaladmin.pm')?require eventcaladmin:0; $adminok = DoAdmin() if($adminok && $adminon && ($acttype =~ /enterday|newdata|deldata/)); # Upcomming events via ssi? $viewupok = (-r './viewup.pm' && $acttype eq 'viewup')?require viewup:0; # Demostrate ssi if($webpage_obj->param('viewupon')) { print $webpage_obj->redirect($baseurl."ssi_test.shtml"); exit; } # Group sort option? $groupsortok = (-r './groupsort.pm' && !$webpage_obj->param('groupsortoff'))?require groupsort:0; $groupsortok = GetGroupBy() if($groupsortok); # Load the javascript code LoadScript(); # Get database data from the calendar database GetDbData() if($acttype ne 'viewyear'); # if new data, then enter new stuff into the database table # and then re-view the calendar. if($acttype =~ /newdata|deldata/) { NewData(); # Change acttype to display so these new entries are fully viewed $acttype = 'display'; GetDbData(); $acttype = 'enterday' if($returnenterday); } # Send out the selected web page $pagestat = 0; # If enter data, then view enter page $pagestat = ($acttype eq 'enterday')?EnterDay():$pagestat; # If view day, then view viewer page $pagestat = ($acttype eq 'viewday')?ViewDay():$pagestat; # If view year, then view year page $pagestat = ($acttype eq 'viewyear')?ViewYear():$pagestat; # If view up, then view upcomming events page $pagestat = ($viewupok)?ViewUp():$pagestat; # Admin demo mode? if($webpage_obj->param('admindemo')) { $caltitle = $caltitle . "<br/>Admin-Security Demo Mode .. Password = Nermware"; } # If display, get the months data, then view calendar and calendar form $pagestat = ($acttype =~ /display|print/)?ViewMonth():$pagestat; ViewCalForm() if($pagestat && $acttype eq 'display'); # End the page if($pagestat && $acttype =~ /newdata|deldata|enterday|viewday|display|print|viewyear/) { # Comment EndPage(); if you don't want the Version, originator, email link, etc stuff EndPage(); print $webpage_obj->end_html; } # Don't need the params anymore .. delete them so they are not used $webpage_obj->delete_all(); # fall thru with error page ErrorPage if(!$pagestat); ## That's all folks ## ## Main End ##