#!/usr/bin/perl # Copyright 2001-2008 Leslie Richardson # This file is part of Open Admin for Schools. # Open Admin for Schools 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. # entry box sizes for input my $homeworklength = 20; my $topiclength = 15; my $maxBlankCounter = 6; # more than 6 blank periods, skip doing back lookups. my $daylimit = 4; # number of school days to look forward or back. my $self = 'dbook.pl'; my %lex = ('Not Assigned' => 'Not Assigned', 'Daybook Main' => 'Daybook Main', 'Main' => 'Main', 'Next Week >>' => 'Next Week >>', '<< Previous Week' => '<< Previous Week', 'Today is a non-cycle Day' => 'Today is a non-cycle Day', 'Day' => 'Day', 'Term' => 'Term', 'Homework Due' => 'Homework Due', 'Desc' => 'Desc', 'Update' => 'Update', 'Please Log In' => 'Please Log In', 'No User Id' => 'No User Id', 'No Password' => 'No Password', 'No Term Found' => 'No Term Found', 'Please check configuration file' => 'Please check configuration file', 'Error' => 'Error', ); use DBI; use CGI; use CGI::Session; use Time::JulianDay; use Date::Business; my $q = CGI->new; my %arr = $q->Vars; # Get passed values eval require "../../etc/admin.conf"; if ( $@ ) { print $lex{Error}. ": $@
\n"; die $lex{Error}. ": $@\n"; } eval require "../../etc/schedule.conf"; if ( $@ ) { print $lex{Error}. ": $@
\n"; die $lex{Error}. ": $@\n"; } eval require "../../lib/libschedule.pl"; if ( $@ ) { print $lex{Error}. ": $@
\n"; die $lex{Error}. ": $@\n"; } my $dsn = "DBI:$dbtype:dbname=$dbase"; $dbh = DBI->connect($dsn,$user,$password); # Set limits for school year: startjd and endjd if (not $schoolstart){ $schoolstart = $g_termstart{1}; } my ($styear,$stmonth,$stday) = split /-/,$schoolstart; my ($endyear,$endmonth,$endday) = split /-/,$schoolend; my $startjd = julian_day($styear,$stmonth,$stday); my $endjd = julian_day($endyear,$endmonth,$endday); # watch for a xxxx-xx-xx key and use for date... foreach my $key (keys %arr) { if ($key =~ m/\d+-\d+-\d/){ # if it contains a hyphen... $arr{date} = $key; delete $arr{$key}; last; } } #strip any leading day text (ie. Monday, 2005-07-29) if ($arr{date} =~ m/\,/){ my ($dud,$date) = split /,/,$arr{date}; $date =~ s/\s//g; $arr{date} = $date; } # Get Session my $session = new CGI::Session("driver:mysql;serializer:FreezeThaw", undef,{Handle => $dbh}) or die CGI::Session->errstr; # Get/Set Session Values (a defined userid means it was passed) if ( $arr{userid} ){ # we want to login, passed userid/password pair. # Check password/userid against database (-1 no user, -2 wrong password; my $error = checkPassword($arr{userid}, $arr{password}); if ($error == -1){ print $q->header; login( $lex{'No User Id'} ); } elsif ( $error == -2 ) { print $q->header; login( $lex{'No Password'} ); } $cookietime = checkCookieTime( $arr{duration} ); # Set values for userid and logged_in in session $session->param('logged_in','1'); $session->expire('logged_in','+20m'); $session->param('duration', $cookietime ); $session->param('userid',$arr{userid}); $userid = $arr{userid}; } else { # check logged_in value in session if ( not $session->param('logged_in') ){ $userid = $session->param('userid'); print $q->header; login( $lex{'Please Log In'}, $userid ); } # Ok, we have a login. Values below we have in environment. $userid = $session->param('userid'); $duration = $session->param('duration'); if ( not ( $duration =~ m/\+/)) { # add + and m if not present $duration = checkCookieTime( $duration ); } $session->expire('logged_in',$duration); } # End of check for logged_in value print $session->header; #foreach my $key (keys %arr) { print "K:$key V:$arr{$key}
\n"; } # Write Updates to Database. if ( $arr{writeflag} ){ # update records, needs the term (set above) delete $arr{writeflag}; updateRecords(); } # If passed a date, use it... otherwise use current day. # If Saturday or Sunday... go to Monday # Note: dow is 1 based, month is 1 based, too. if ($arr{date}) { # Generate a list from those dates. Assume year-mon-day ($year,$month,$day) = split /-/,$arr{date}; $jd = julian_day($year,$month,$day); } else { # No passed date; use current date @tim = localtime(time); $year = $tim[5] + 1900; $month = $tim[4] + 1; $day = $tim[3]; $jd = julian_day($year,$month,$day); if ($jd < $startjd) { # Set Day to first day of school year $jd = $startjd; $year = $styear; $month = $stmonth; $day = $stday; } } $dow = day_of_week($jd); $dow++; # since it is 1 based # Now verify this starting date... $noncycledayFlag = 1; while ($noncycledayFlag) { # repeat until we get a cycle day... # Reset: $year, $month, $day, $dow, $jd if ($dow == 7) { # Saturday $jd += 2; # make it Monday of next week. ($year, $month, $day) = inverse_julian_day($jd); } elsif ($dow == 1) { # Sunday $jd++ ; # make it Monday ($year, $month, $day) = inverse_julian_day($jd); } $dow = day_of_week($jd); $dow++; # since it is 1 based. # Check for day in cycle. my $sth = $dbh->prepare("select count(id) from dates where dayincycle = 'N' and to_days(date) = to_days('$year-$month-$day')"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } if ( my $reccount = $sth->fetchrow ) { # whoops it's a noncycle day, try again. $jd++; ($year, $month, $day) = inverse_julian_day($jd); $dow = day_of_week($jd); $dow++; next; } else { last; } } $mondayjd = $jd - ($dow-2); if (length($month) == 1){ $month = "0".$month;} $currldate = "$dow[$dow], $month[$month] $day"; # Don't want March 01 in long date format... if (length($day) == 1){ $day = "0".$day;} $currsdate = "$year$month$day"; $currdate = $year.'-'.$month.'-'.$day; # no 0 padding... $dow_mday{$currdate} = "$s_dow[$dow] $day"; # Setup the @cycledates (forward and backwards) and matching hash # %dow_mday{date}; my @cycledates; my $tempjd = $jd; # $jd (julian day set above) my $daycount=1; # Daylimit is max school days forward or back to search. while ( $daycount < $daylimit ) { $tempjd--; my ($tempyear,$tempmonth,$tempday) = inverse_julian_day($tempjd); my $tempdow = day_of_week($tempjd) + 1; #check if this day can be a day in cycle; if ( $tempdow == 1 or $tempdow ==7 ) { next; } # not Sun. or Sat. # Check if given date is a non-cycle day. my $sth = $dbh->prepare("select count(id) from dates where dayincycle = 'N' and to_days(date) = to_days('$tempyear-$tempmonth-$tempday')"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } if (my $reccount = $sth->fetchrow){ next; } push @cycledates,"$tempyear-$tempmonth-$tempday"; $dow_mday{$tempyear.'-'.$tempmonth.'-'.$tempday} = "$s_dow[$tempdow] $tempday"; $daycount++; } @cycledates = reverse(@cycledates); # flip around to get right date order... push @cycledates, "$year-$month-$day"; # actual working date. $tempjd = $jd; # $jd (julian day set above) $daycount = 1; $daylimit = 5; while ( $daycount < $daylimit ) { $tempjd++; my ($tempyear,$tempmonth,$tempday) = inverse_julian_day($tempjd); my $tempdow = day_of_week($tempjd) + 1; #check if this day can be a day in cycle; if ( $tempdow == 1 or $tempdow == 7 ) { next; } # not Sun. or Sat. # Check if given date is a non-cycle day. my $sth = $dbh->prepare("select count(id) from dates where dayincycle = 'N' and to_days(date) = to_days('$tempyear-$tempmonth-$tempday')"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } if (my $reccount = $sth->fetchrow){ next; } push @cycledates,"$tempyear-$tempmonth-$tempday"; $dow_mday{$tempyear.'-'.$tempmonth.'-'.$tempday} = "$s_dow[$tempdow] $tempday"; $daycount++; } # Test for correct hash and array values for other cycle days. #print "Hash Start

\n"; #foreach my $key (keys %dow_mday) { # print "K:$key V:$dow_mday{$key}
\n"; #} #print "Start
\n"; #foreach my $date (@cycledates) { # print "$dow_mday{$date} ($date)
\n"; #} # Find DayInCycle my $dayInCycle = findDayInCycle($currdate, $dbh); $term = findTerm($currdate); if ( not $term ){ # No term found! print "

". $lex{'No Term Found'}. ".

\n"; print "

". $lex{'Please check configuration file'}. "
$schooldate

\n"; print "\n"; exit; } my (@subjects, @bigsubjects); # Get the subject info; stuff into 'subjects' array. $sth = $dbh->prepare("select description,smdesc,subjsec from subject where teacher $sql{like} '%($userid%' order by description"); $sth->execute; if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } # Prep for loop finding the subjects my $sth1 = $dbh->prepare("select day, period from schedat where term = '$term' and subjsec = ? "); while (my ($description,$smdesc,$subjsec) = $sth->fetchrow){ push @bigsubjects,"$description ($subjsec)"; push @subjects,$subjsec; $sth1->execute($subjsec); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;} # Create 2D subject array (of [period][day] indexes) while (my ($day, $period) = $sth1->fetchrow){ if ($subject[$period][$day] != $subjsec){ $subject[$period][$day] .= "$subjsec "; } } } # Heading of Document print "$doctype\n". $lex{'Daybook Main'}. " \n"; print "[ ". $lex{Main}. " | \n"; print "Schedule ] $currldate  \n"; print $lex{Day}. " $dayInCycle
\n"; #print $lex{Term}. " $term
\n"; # Do the Days to Click On... print "
\n"; #print "\n"; #print "
\n"; print "
\n"; foreach my $date ( @cycledates ) { print "\n"; } print "
"; #print "
"; print "
\n\n"; # Halt if dayInCycle undefined. (ie. due to being a non-cycle day) if (not $dayInCycle){ print $lex{'Today is a non-cycle Day'}. "
\n"; print "\n"; die; } # Start the main form. print "\n"; print "
\n"; print "\n"; print " \n"; # Setup Selects for use inside loop. my $sth2 = $dbh->prepare("select description from subject where subjsec = ?"); my $sth3 = $dbh->prepare("select distinct topic from dbkdata where subjsec = ? and topic != '' order by date desc"); my $sth4 = $dbh->prepare("select distinct category from dbkdata where subjsec = ? and category != '' order by category"); # Loop through each subject-section for my $period (1..$#subject){ my $subjsec = $subject[$period][$dayInCycle]; $subjsec =~ s/\s$//; # Get Subject Description $sth2->execute($subjsec); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } my $desc = $sth2->fetchrow; # Get topics my @topics; $sth3->execute($subjsec); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } while (my $topic = $sth3->fetchrow){ push @topics,$topic; } # Get categories my @categories; $sth4->execute($subjsec); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;} while ( my $cat = $sth4->fetchrow ) { push @categories, $cat; } # Get Previous Period (not in current day...) my $pn; # previous note $sth1 = $dbh->prepare("select notes, date, period from dbkdata where subjsec = ? and to_days(date) < to_days('$currdate') order by date desc, period desc"); $sth1->execute( $subjsec ); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } my $blankCounter = 0; my $previousPeriod; NOTE: while ( my ($prevnote, $prevdate, $prevperiod) = $sth1->fetchrow) { if ( not $prevnote ) { $blankCounter++; if ($blankCounter > $maxBlankCounter) { last; } next NOTE; } # Get dow for prevdate; my ($year,$month,$day) = split /-/,$prevdate; my $jd = julian_day($year,$month,$day); my $dow = day_of_week($jd) + 1; my $prevdow = $s_dow[$dow]; # @sdow (short days of week) defined in admin.conf my $prevsdate = "$month-$day"; $previousPeriod = "$prevdow, $prevsdate: $prevnote\n"; last; } # get current data, if any. my $sth1 = $dbh->prepare("select topic, notes, homework, hwdate, category from dbkdata where subjsec = '$subjsec' and period = '$period' and date = '$currdate' "); $sth1->execute; if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } my ($topic, $notes, $homework, $hwdate, $category) = $sth1->fetchrow; # Display the current subject and period. print "
"; print "Period $period Time: $ptime[$period]"; if (not $desc) { $desc = $lex{'Not Assigned'}; } print "  $desc
\n"; # Topic - display. print "Topic \n\n"; # Now print Category Section print "Category \n"; print "\n"; # print $lex{'Homework Due'}. ": "; # print $lex{Desc}. ":
\n"; if ($previousPeriod) { print "
$previousPeriod
\n"; } print "\n"; } print "
\n"; print "
\n"; #-------- sub login { # print error, login screen and exit; #-------- my $error = shift; print "$doctype\n$error\n"; print "\n"; print "$chartype\n\n"; #print "Passed:
\n"; #foreach my $key (sort keys %arr ) { #print "K:$key V:$arr{$key}
\n"; #} print "

$error

\n

\n"; print "Userid: \n"; print "Password:
\n"; print "Cookie Duration: (min)
\n\n"; # put hidden fields here. foreach my $key (sort keys %arr ) { print "\n"; } print "

\n"; print "[ Main ]
\n"; exit; } #----------- sub findTerm { #----------- my $date = shift; # Passed Date. (Must be yyyy-mm-dd) my $maxterms = 12; # search up to 12 terms. my ($yr,$mo,$da) = split /-/,$date; if (length($mo) == 1){ $mo = "0".$mo;} if (length($da) == 1){ $da = "0".$da;} $date = $yr.$mo.$da; # create date object from passed date. my $dateobj = new Date::Business(DATE=>$date); # Figure out the current term, if not passed term #my $term = 0; # should return undefined... for (1..$maxterms){ # Loop through each term 1->12 my $startdate = $g_termstart{$_}; $startdate =~ s/-//g; my $startobj = new Date::Business(DATE => $startdate); my $enddate = $g_termend{$_}; $enddate =~ s/-//g; #print "SD: $startdate ED: $enddate
\n"; my $endobj = new Date::Business(DATE => $enddate); $startoffset = $dateobj->diffb($startobj,'prev','next'); $endoffset = $dateobj->diffb($endobj,'prev','next'); # print "StartOffset: $startoffset Endoffset: $endoffset
\n"; if ($startoffset >= 0 and $endoffset <= 0){ $term = $_; last; } } return $term; } # End of findTerm #---------------- sub updateRecords { #---------------- my %rec = %arr; # Don't mess with %arr hash since this is passed through to display functions. my $date = $rec{date}; delete $rec{date}; if (not $userid) { # try $arr{userid} $userid = $rec{userid}; delete $rec{userid}; } delete $rec{password}; #print $q->header; #foreach my $key (sort keys %rec) { print "K:$key V:$rec{$key}
\n"; } #print "Date: $date
\n"; #print "User: $userid
\n"; # Create Data hash foreach my $key (keys %rec){ if ($key and $rec{$key}){ #$key = $dbh->quote( $key ); # not needed since split apart below. #$rec{$key} = $dbh->quote( $rec{$key} ); $rec{$key} =~ s/'/''/g; #print "
K: $key V: $rec{$key}
\n"; my ($period, $subjsec, $type) = split /:/,$key; $subjsec =~ s/\s+//g; # strip space if (not $data{"$period:$subjsec"}){ $data{"$period:$subjsec"} = {}; } ${$data{"$period:$subjsec"}}{$type} = $rec{$key}; } } # Now update it, loop through data hash. foreach my $key (keys %data){ my ($period,$subjsec) = split /:/,$key; #print "Period: $period Subjsec: $subjsec
\n"; # Check for existing record my $sth = $dbh->prepare("select id from dbkdata where subjsec = '$subjsec' and userid = '$userid' and period = '$period' and date = '$date'"); $sth->execute; if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } my $id = $sth->fetchrow; if (${$data{$key}}{newcat}){ ${$data{$key}}{cat} = ${$data{$key}}{newcat}; } if (${$data{$key}}{newtop}){ ${$data{$key}}{top} = ${$data{$key}}{newtop}; } if ( ${$data{$key}}{hwd} =~ m/^\+\S+/){ # Find future date of this class. ${data{$key}}{hwd} = findFutureClass($date,$period,$userid,$term, $subjsec,${$data{$key}}{hwd}); } if ($id){ # update the record my $sth = $dbh->prepare("update dbkdata set topic = '${$data{$key}}{top}', notes = '${$data{$key}}{not}', homework = '${$data{$key}}{hwk}', hwdate = '${$data{$key}}{hwd}', category = '${$data{$key}}{cat}' where id = '$id'"); $sth->execute; if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } } else { # add a record my $sth = $dbh->prepare("insert into dbkdata values ( $sql{default},'$userid','$date','$subjsec','$period', '${$data{$key}}{top}','${$data{$key}}{not}','${$data{$key}}{hwk}', '${$data{$key}}{hwd}','${$data{$key}}{cat}')"); $sth->execute; if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } } #foreach my $innerkey (keys %{$data{$key}}){ # print "K: $innerkey IV: ${$data{$key}}{$innerkey}
\n"; #} } } # End of updateRecords #---------------- sub checkPassword { #---------------- my ($userid, $password) = @_; if (not $userid){ return -1;} if (not $password){ return -2;} #check for presence of userid my $sth = $dbh->prepare("select count(userid) from staff where userid = ?"); $sth->execute($userid); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } my $count = $sth->fetchrow; if ($count < 1){ return -1;} # no userid #check for presence of correct password and userid my $sth = $dbh->prepare("select count(userid) from staff where userid = ? and passwd = ? "); $sth->execute($userid, $password); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } my $count = $sth->fetchrow; if ($count < 1){ return -2;} # not correct password return 0; # if all ok... } #------------------ sub checkCookieTime { #------------------ # Requires defaults of: $defaulttime, $maximumtime, $minimumtime $defaulttime = 20; $maximumtime = 60; $minimumtime = 3; my ($duration) = @_; if ($duration) { $cookietime = $duration; } else { $cookietime = $defaulttime; } $cookietime = $minimumtime if $cookietime < $minimumtime; $cookietime = $maximumtime if $cookietime > $maximumtime; $cookietime = "+".$cookietime."m"; # set format return $cookietime; }