#!/usr/bin/perl -w # # Wcal 2.0 copyright by Joël Savignon . # # Released under GNU General Public License (GPL). # # TAB size 4 # require 5.004; use Data::Dumper; use Date::Manip; use Socket; use strict; no strict 'refs'; # These you can edit $::CONF_FILE = '/etc/wcal.conf'; $::MSG_FILE = '/etc/wcal.msg'; $::DIRECTORY = '/var/www/VIRTUAL/www.homebase.dk/www/wcal'; $::DB_DIR = '/var/wcal'; # settable in wcal.conf in 1.x versions $::REFRESH_DELAY = 900; # view refreshed every 900 seconds = 15 minutes $::PATH_BASENAME = 'wcal'; # last component of the wcal directory name # Values below affect the proportions of the frames $::FIRST_HOUR = 8; $::LAST_HOUR = 23; $::MANY_WEEKS_VERT = 2; $::MANY_WEEKS_HOR = 7; $::FIRST_DAY = 'monday'; # Colors $::THCOLOR = '#E2E3FC'; $::TDCOLOR = '#D9F4F4'; $::NOW_THCOLOR = '#CAFFD0'; $::NOW_TDCOLOR = '#CAFFD0'; $::REPEAT_WEEK_TEXTCOLOR = '#C02090'; $::REPEAT_MONTH_TEXTCOLOR = '#008844'; $::BG_TDCOLOR = '#F2F3FC'; $::ERROR_COLOR = '#e06060'; @::EVENT_COLS = ('#D9F4F4','#FFFFAA','#AAFFFF','#FFAAFF','#FFAAAA','#AAAAFF','#AAFFAA','#80FFE0','#E080E0','#C0DCC0','#C0C0C0','#FF0080','#A4C8F0','#FF8000','#FF80C0','#8080C0','#FFFFFF'); # No need to touch these $::MAX_DURATION = 21; # maximum duration of an event in days $::CURRENT_DB_VERSION = 2; # Wcal 1.00 had version 1 databases $::HTTP_HEADER = "Content-Type: text/html\n\n"; # internationalization sub __ { my $str = shift; return $::msgs->{$str}->{$::REMOTE_LANG} || $str; } # fusion sub strcal { if ($::query->{'cal'}) { return "&cal=".join("&cal=",split(/\n/,$::query->{'cal'})); } else { return ""; } } sub lncal { my $year = shift; my $week = shift; if ($::query->{'cal'}) { my $str = $::BASE_URL.'/fusion.cgi?t=links&cal='.join("&cal=",split(/\n/,$::query->{'cal'})); if ($year && $week) { $str .= '&year='.$year.'&week='.$week; } return "$::LONG_NAME"; } else { return $::LONG_NAME; } } # Query string decoder, ripped from CGI_Lite sub decode_url_encoded_data ($) { my ($reference_data) = @_; my ($code, $self); $code = <<'End_of_URL_Decode'; my (@key_value_pairs, $delimiter, $key_value, $key, $value); @key_value_pairs = (); return unless ($$reference_data); $delimiter = '&'; $$reference_data =~ tr/+/ /; @key_value_pairs = split (/$delimiter/, $$reference_data); foreach $key_value (@key_value_pairs) { ($key, $value) = split (/=/, $key_value, 2); $key =~ s/%([\da-fA-F]{2})/chr (hex ($1))/eg; $value =~ s/%([\da-fA-F]{2})/chr (hex ($1))/eg; # print Socket "'$key':'$value'\n"; if ($self->{$key}) { $self->{$key} .= "\n$value"; } else { $self->{$key} = $value; } } End_of_URL_Decode eval ($code); return $self; } # And encoder, ripped too sub url_encode { my $string = shift; my $str1 = '([\x00-\x20"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF])'; $string =~ s/$str1/ sprintf ('%%%x', ord ($1))/eg; return $string; } sub strip_space ($) { my ($s) = @_; $s =~ s/^\s*(.*?)\s*$/$1/; return $s; } sub wday_to_dmwday ($) { my ($wday) = @_; if ($::FIRST_DAY eq 'monday') { return ($wday + 1); } else { if ($wday == 0) { return 7; } else { return $wday; } } } sub dmwday_to_wday ($) { my ($dmwday) = @_; return ($::FIRST_DAY eq 'monday' ? $dmwday - 1 : $dmwday % 7); } sub get_now () { if (! defined $::now_cache) { my (@n); @n = &UnixDate (&ParseDate ('now'), $::FIRST_DAY eq 'monday' ? "%G": "%L", "%m", "%d", $::FIRST_DAY eq 'monday' ? "%W" : "%U", "%w"); $::now_cache = { 'year' => $n[0] + 0, 'month' => $n[1] + 0, 'day' => $n[2] + 0, 'week' => $n[3] + 0, 'wday' => dmwday_to_wday ($n[4]) }; } return $::now_cache; } sub get_next_year_week ($$) { my ($year, $week) = @_; my ($cacheid); $cacheid = sprintf ("%04d%02d", $year, $week); if (! defined $::nyw_cache{$cacheid}) { my ($y, $w); ($y, $w) = &UnixDate (&DateCalc ("$::FIRST_DAY week $week in $year", "+ 7 days"), $::FIRST_DAY eq 'monday' ? "%G": "%L", $::FIRST_DAY eq 'monday' ? "%W" : "%U"); $::nyw_cache{$cacheid} = [$y + 0, $w + 0]; } return @{$::nyw_cache{$cacheid}}; } sub get_prev_year_week ($$) { my ($year, $week) = @_; my ($cacheid); $cacheid = sprintf ("%04d%02d", $year, $week); if (! defined $::pyw_cache{$cacheid}) { my ($y, $w); ($y, $w) = &UnixDate (&DateCalc ("$::FIRST_DAY week $week in $year", "- 7 days"), $::FIRST_DAY eq 'monday' ? "%G": "%L", $::FIRST_DAY eq 'monday' ? "%W" : "%U"); $::pyw_cache{$cacheid} = [$y + 0, $w + 0]; } return @{$::pyw_cache{$cacheid}}; } sub get_month_day_by_firstday_year_week ($$) { my ($year, $week) = @_; my ($cacheid); $cacheid = sprintf ("%04d%02d", $year, $week); if (! defined $::md_cache{$cacheid}) { my ($month, $day); ($month, $day) = &UnixDate (&ParseDate ("$::FIRST_DAY week $week in $year"), "%m", "%d"); $::md_cache{$cacheid} = [$month + 0, $day + 0]; } return @{$::md_cache{$cacheid}}; } sub get_month_day_by_wday_year_week ($$$) { my ($wday, $year, $week) = @_; my ($cacheid); $cacheid = sprintf ("%04d%02d%1d", $year, $week, $wday); if (! defined $::md2_cache{$cacheid}) { my ($month, $day); ($month, $day) = &UnixDate (&ParseDate ($::weekdays2[$wday] . " week $week in $year"), "%m", "%d"); $::md2_cache{$cacheid} = [$month + 0, $day + 0]; } return @{$::md2_cache{$cacheid}}; } sub get_year_week_by_firstday_year_week_minus_days ($$$) { my ($year, $week, $days) = @_; my ($cacheid); $cacheid = sprintf ("%04d%02d%10d", $year, $week, $days); if (! defined $::yw_cache{$cacheid}) { my ($ryear, $rweek); ($ryear, $rweek) = &UnixDate (&DateCalc ("$::FIRST_DAY week $week in $year", "- $days days"), $::FIRST_DAY eq 'monday' ? "%G": "%L", $::FIRST_DAY eq 'monday' ? "%W" : "%U"); $::yw_cache{$cacheid} = [$ryear + 0, $rweek + 0]; } return @{$::yw_cache{$cacheid}}; } sub week_wday_by_year_month_day ($$$) { my ($year, $month, $day) = @_; my ($cacheid); $cacheid = sprintf ("%04d%02d%2d", $year, $month, $day); if (! defined $::ww_cache{$cacheid}) { my ($week, $wday); ($week, $wday) = &UnixDate (&ParseDate ("$month/$day/$year"), $::FIRST_DAY eq 'monday' ? "%W" : "%U", "%w"); $::ww_cache{$cacheid} = [$week + 0, dmwday_to_wday ($wday)]; } return @{$::ww_cache{$cacheid}}; } sub get_start_end_by_year_week_wday_duration ($$$$) { my ($startyear, $startweek, $startwday, $duration) = @_; my ($cacheid); $cacheid = sprintf ("%04d%02d%2d%03d", $startyear, $startweek, $startwday, $duration); if (! defined $::se_cache{$cacheid}) { my ($startmonth, $startday, $endyear, $endweek, $endwday, $endmonth, $endday); ($startmonth, $startday) = get_month_day_by_wday_year_week ($startwday, $startyear, $startweek); ($endyear, $endweek, $endwday) = &UnixDate (&DateCalc (&ParseDate (sprintf ("%04d-W%02d-%1d", $startyear, $startweek, wday_to_dmwday ($startwday))), "+ " . ($duration - 1) . " days"), $::FIRST_DAY eq 'monday' ? "%G": "%L", $::FIRST_DAY eq 'monday' ? "%W" : "%U", "%w"); $endwday = dmwday_to_wday ($endwday); ($endmonth, $endday) = get_month_day_by_wday_year_week ($endwday, $endyear, $endweek); $::se_cache{$cacheid} = [ $startmonth + 0, $startday + 0, $endyear + 0, $endweek + 0, dmwday_to_wday ($endwday), $endmonth + 0, $endday + 0 ]; } return @{$::se_cache{$cacheid}}; } sub get_year_week_wday_by_year_week_wday_plus_days ($$$$) { my ($year, $week, $wday, $days) = @_; my ($cacheid); $cacheid = sprintf ("%04d%02d%02d%10d", $year, $week, $wday, $days); if (! defined $::yww_cache{$cacheid}) { my ($nyear, $nweek, $nwday); ($nyear, $nweek, $nwday) = &UnixDate (&DateCalc (sprintf ("%04d-W%02d-%1d", $year, $week, wday_to_dmwday ($wday)), "+ $days days"), $::FIRST_DAY eq 'monday' ? "%G": "%L", $::FIRST_DAY eq 'monday' ? "%W" : "%U", "%w"); $::yww_cache{$cacheid} = [$nyear + 0, $nweek + 0, dmwday_to_wday ($nwday)]; } return @{$::yww_cache{$cacheid}}; } sub fit_in_week ($$$$) { my ($year, $week, $wday, $duration) = @_; my ($endyear, $endweek, $endwday); ($endyear, $endweek, $endwday) = get_year_week_wday_by_year_week_wday_plus_days ($year, $week, $wday, $duration-1); if ($endyear != $year or $endweek != $week) { return 0; } else { return 1; } } sub fit_in_month ($$$$) { my ($year, $week, $wday, $duration) = @_; my ($month, $day); my ($endyear, $endweek, $endwday); my ($endmonth, $endday); ($month, $day) = get_month_day_by_wday_year_week ($wday, $year, $week); ($endyear, $endweek, $endwday) = get_year_week_wday_by_year_week_wday_plus_days ($year, $week, $wday, $duration-1); ($endmonth, $endday) = get_month_day_by_wday_year_week ($endwday, $endyear, $endweek); if ($endyear != $year or $endmonth != $month) { return 0; } else { return 1; } } sub clipboard_set ($$) { my ($key, $data_ref) = @_; $::clipboard{$key} = $data_ref; return; } sub clipboard_get ($) { my ($key) = @_; if (defined $::clipboard{$key}) { return $::clipboard{$key}; } else { return ''; } } sub format_hour ($) { my ($hour) = @_; if ($::CLOCK eq '24-hour') { return ($hour + 0); } else { my ($newhour); $newhour = $hour; $newhour = 24 if $hour == 0; $newhour -= 12 if $hour > 12; return ($newhour + 0) . ($hour < 12 ? "am" : "pm"); } } sub format_hour_padded ($) { my ($hour) = @_; if ($::CLOCK eq '24-hour') { return sprintf ("%02d", $hour); } else { my ($newhour); $newhour = $hour; $newhour = 24 if $hour == 0; $newhour -= 12 if $hour > 12; return sprintf ("%02d", $newhour) . ($hour < 12 ? "am" : "pm"); } } sub format_time ($$) { my ($hour, $min) = @_; if ($::CLOCK eq '24-hour') { return ($hour + 0) . ":" . sprintf ("%02d", $min); } else { my ($newhour); $newhour = $hour; $newhour = 24 if $hour == 0; $newhour -= 12 if $hour > 12; return ($newhour + 0) . ":" . sprintf ("%02d", $min) . ($hour < 12 ? "am" : "pm"); } } sub format_time_padded ($$) { my ($hour, $min) = @_; if ($::CLOCK eq '24-hour') { return sprintf ("%02d", $hour) . ":" . sprintf ("%02d", $min); } else { my ($newhour); $newhour = $hour; $newhour = 24 if $hour == 0; $newhour -= 12 if $hour > 12; return sprintf ("%02d", $newhour) . ":" . sprintf ("%02d", $min) . ($hour < 12 ? "am" : "pm"); } } sub format_alarm_type { my ($type, $single) = @_; if ($type == 1) { if ($single) { return __("minute"); } else { return __("minutes"); } } elsif ($type == 2) { if ($single) { return __("heure"); } else { return __("heures"); } } elsif ($type == 3) { if ($single) { return __("jour"); } else { return __("jours"); } } else { return ""; } } sub img_alarm { my ($val, $type, $chk) = @_; if ($val) { my $img = ($chk ? "alarm2" : "alarm"); return ' '.__('; } else { return ""; } } sub img_note { my ($data) = @_; if ($data) { $data =~ s/
/ /mg; return ' '.__('; } else { return ""; } } sub txt_alarm { my ($val, $type, $chk) = @_; if ($val) { my $col = ($chk ? "#00AA00" : "#FF0000"); return '
'.__("Alarme")." : ".$val." ".format_alarm_type($type, ($val == 1)).''; } else { return ""; } } sub has_html ($) { my ($text) = @_; return $text =~ /[<>&]/; } sub newline_to_html ($) { my ($text) = @_; $text =~ s/\015\012/
/sg; return $text; } sub html_to_newline ($) { my ($text) = @_; $text =~ s/
/\015\012/sg; return $text; } sub events_version ($) { my ($events) = @_; my ($version); $version = $events->[0]; if (ref $version) { $version = 1; } return $version; } sub convert_events_from_v1_to_v2 ($$$) { my ($events, $year, $week) = @_; my ($dayid, $eventhour, $eventid); for $dayid (0 .. $#$events) { for $eventhour (keys %{$events->[$dayid]}) { for $eventid (0 .. $#{$events->[$dayid]->{$eventhour}}) { my (@old_event, %new_event); @old_event = @{$events->[$dayid]->{$eventhour}->[$eventid]}; %new_event = ( 'id' => $old_event[0], 'min' => $old_event[1], 'lengthmin' => $old_event[2], 'title' => $old_event[3], 'data' => $old_event[4], 'rt' => $old_event[5], 'startyear' => $year, 'startweek' => $week, 'startwday' => $dayid, 'duration' => 1 ); $events->[$dayid]->{$eventhour}->[$eventid] = \%new_event; } } } # insert version number into beginning of the array unshift (@$events, $::CURRENT_DB_VERSION); return; } sub read_events ($;$$) { my ($rt, $year, $week) = @_; my ($filename, $now); my @filenames; my $id; my ($refs, $ref, $old_slash); if ($main::DATA_ID) { if ($rt eq 'n') { $filename = sprintf "$::DB_DIR/w-$main::DATA_ID-%04d%02d.db", $year, $week; } else { $filename = "$::DB_DIR/r$rt-$main::DATA_ID.db"; } if (open F, $filename) { $old_slash = $/; undef $/; $refs = eval (); $/ = $old_slash; close F; # backwards compatibility if (events_version ($refs) < 2) { $now = get_now (); convert_events_from_v1_to_v2 ($refs, $year || $now->{'year'}, $week || $now->{'week'}); } shift @$refs; } } elsif ($main::DATA_IDS) { my $cl = 0; foreach $id (split(/\n/,$main::DATA_IDS)) { $cl++; if ($rt eq 'n') { $filename = sprintf "$::DB_DIR/w-$id-%04d%02d.db", $year, $week; } else { $filename = "$::DB_DIR/r$rt-$id.db"; } if (open F, $filename) { $old_slash = $/; undef $/; $ref = eval (); $/ = $old_slash; close F; # backwards compatibility if (events_version ($ref) < 2) { $now = get_now (); convert_events_from_v1_to_v2 ($ref, $year || $now->{'year'}, $week || $now->{'week'}); } shift @$ref; # add cal index my $i; my $key; my $val; my $vl; for ($i=0; $i < ($rt eq 'm' ? 32 : 7); $i++) { while (($key, $val) = each (%{@{$ref}[$i]})) { foreach $vl (@{$val}) { %{$vl}->{cal} = $cl; } } } if (!$refs) { $refs = $ref; next; } # fusion for ($i=0; $i < ($rt eq 'm' ? 32 : 7); $i++) { while (($key, $val) = each (%{@{$ref}[$i]})) { if (%{@{$refs}[$i]}->{$key}) { push @{%{@{$refs}[$i]}->{$key}}, @{$val}; } else { @{%{@{$refs}[$i]}->{$key}} = @{$val}; } } } } } } if ($refs) { return $refs; } elsif ($rt eq 'n' or $rt eq 'w') { return [ {}, {}, {}, {}, {}, {}, {} ]; } elsif ($rt eq 'm') { # let's give month 32 days to make sure return [ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ] } # can't happen } sub write_events ($$;$$) { my ($weekdata, $rt, $year, $week) = @_; my ($filename); if ($rt eq 'n') { if (! defined $year or ! $year or ! defined $week or ! $week) { return "The file type is no-repeat, but week or year not given, or zero."; } $filename = sprintf "$::DB_DIR/w-${main::DATA_ID}-%04d%02d.db", $year, $week; # Remove cached week file unlink sprintf ("$::DB_DIR/cache/w-${main::DATA_ID}-%04d%02d.html", $year, $week); } else { my (@files); $filename = "$::DB_DIR/r$rt-${main::DATA_ID}.db"; # Remove all cached week files if (opendir (TDH, "$::DB_DIR/cache")) { @files = grep { /^w-${main::DATA_ID}-\d{6}\.html$/ } readdir (TDH); closedir TDH; for (@files) { unlink "$::DB_DIR/cache/$_"; } } } # add the version identifier unshift (@$weekdata, $::CURRENT_DB_VERSION); if (open F, ">$filename") { $Data::Dumper::Terse = 1; flock (F, 2); print F Dumper ($weekdata); flock (F, 8); close F; return ''; } else { return "File $filename can't be opened for writing: $!"; } # and remove the version identifier again shift @$weekdata; } sub read_general () { my ($week) = @_; if (-f "$::DB_DIR/general.db" and ! -r "$::DB_DIR/general.db") { return "No write permission for file $::DB_DIR/general.db"; } if (open F, "$::DB_DIR/general.db") { my ($ref, $old_slash); $old_slash = $/; undef $/; $ref = eval (); $/ = $old_slash; close F; if ($@) { return "Error in processing file $::DB_DIR/general.db: $@"; } else { return $ref; } } else { return { 'highid' => 56 }; } } sub write_general ($) { my ($gendata) = @_; if (open F, ">$::DB_DIR/general.db") { $Data::Dumper::Terse = 1; flock (F, 2); print F Dumper ($gendata); flock (F, 8); close F; return ''; } else { return "File $::DB_DIR/general.db can't be opened for writing: $!"; } } # Print year, month and day in chosen date format sub pd_year_month_day ($$$) { my ($year, $month, $day) = @_; my ($t); $t = $::DATE_FORMAT; if ($t == 1) { return "$day.$month.$year"; } elsif ($t == 2) { return "$month/$day/$year"; } elsif ($t == 3) { return "$day/$month/$year"; } elsif ($t == 4) { return "$year/$month/$day"; } elsif ($t == 5) { return "$year-$month-$day"; } elsif ($t == 5) { return sprintf ("%04d%02d%02d", $year, $month, $day); } else { return "[DATE TYPE $t]"; } } sub pd_month_day ($$) { my ($month, $day) = @_; my ($t); $t = $::DATE_FORMAT; if ($t == 1) { return "$day.$month"; } elsif ($t == 2) { return "$month/$day"; } elsif ($t == 3) { return "$day/$month"; } elsif ($t == 4) { return "$month/$day"; } elsif ($t == 5) { return "$month-$day"; } elsif ($t == 6) { return sprintf ("%02d%02d", $month, $day); } else { return "[DATE TYPE $t]"; } } sub pd_month_day_padded ($$) { my ($month, $day) = @_; my ($t); $t = $::DATE_FORMAT; if ($t == 1) { return sprintf "%02d.%02d", $day, $month; } elsif ($t == 2) { return sprintf "%02d/%02d", $month, $day; } elsif ($t == 3) { return sprintf "%02d/%02d", $day, $month; } elsif ($t == 4) { return sprintf "%02d/%02d", $month, $day; } elsif ($t == 5) { return sprintf "%02d-%02d", $month, $day; } elsif ($t == 6) { return sprintf "%02d%02d", $month, $day; } else { return "[DATE TYPE $t]"; } } sub pd_single_event_date ($$$$) { my ($rt, $year, $week, $wday) = @_; my ($month, $day); ($month, $day) = get_month_day_by_wday_year_week ($wday, $year, $week); if ($rt eq 'n') { return pd_year_month_day ($year, $month, $day); } elsif ($rt eq 'w') { return __($::weekdays[$wday]); } else { return $day . "."; } } sub pd_event_date ($$$$$) { my ($rt, $startyear, $startweek, $startwday, $duration) = @_; my ($ret); $ret = ''; $ret .= pd_single_event_date ($rt, $startyear, $startweek, $startwday); if ($duration > 1) { ($startyear, $startweek, $startwday) = get_year_week_wday_by_year_week_wday_plus_days ($startyear, $startweek, $startwday, $duration - 1); $ret .= " to " . pd_single_event_date ($rt, $startyear, $startweek, $startwday); } if ($rt eq 'w') { $ret .= " ".__("hebdomadaire"); } elsif ($rt eq 'm') { $ret .= " ".__("mensuelle"); } return $ret; } sub join_days (@) { my (@daylist) = @_; my (%sum_day, $day_ref, $hour, $event_ref); %sum_day = (); for $day_ref (@daylist) { for $hour (keys %$day_ref) { for $event_ref (@{$day_ref->{$hour}}) { push @{$sum_day{$hour}}, $event_ref; } } } return \%sum_day; } sub build_day ($$$$) { my ($year, $week, $wday, $day) = @_; my ($e_n, $e_rw, $e_rm, $sum_day_ref); $e_n = read_events ('n', $year, $week); $e_rw = read_events ('w'); $e_rm = read_events ('m'); $sum_day_ref = join_days ($e_n->[$wday], $e_rw->[$wday], $e_rm->[$day]); return $sum_day_ref; } sub build_week ($$) { my ($year, $week) = @_; my ($e_n, $e_rw, $e_rm, @sum_week, $wday); $e_n = read_events ('n', $year, $week); $e_rw = read_events ('w'); $e_rm = read_events ('m'); for $wday (0 .. 6) { my ($month, $day); ($month, $day) = get_month_day_by_wday_year_week ($wday, $year, $week); $sum_week[$wday] = join_days ($e_n->[$wday], $e_rw->[$wday], $e_rm->[$day]); } return \@sum_week; } sub build_week_list ($$) { my ($start_year, $start_week) = @_; my ($week_filename, @weeks, @ret, %weeks); my ($e_n, $e_rw, $e_rm, @sum_week); my ($cyear, $cweek, $cdate); my ($end_year, $end_week, $end_date); $e_rw = read_events ('w'); $e_rm = read_events ('m'); if ($main::DATA_ID) { if (! opendir (DIR, $::DB_DIR)) { return "can't open $::DB_DIR for reading: $!"; } # gather all week filenames, 199805, 199806, 199807 ... 199851 @weeks = map { /^w-$main::DATA_ID-(\d{4}\d{2})\.db$/ && $1 } grep { /^w-$main::DATA_ID-(\d{4}\d{2})\.db$/ && $1 >= sprintf ("%04d%02d", $start_year, $start_week) } sort readdir(DIR); close DIR; } else { my $id; my @wks; foreach $id (split(/\n/,$main::DATA_IDS)) { if (! opendir (DIR, $::DB_DIR)) { return "can't open $::DB_DIR for reading: $!"; } # gather all week filenames, 199805, 199806, 199807 ... 199851 @wks = map { /^w-$id-(\d{4}\d{2})\.db$/ && $1 } grep { /^w-$id-(\d{4}\d{2})\.db$/ && $1 >= sprintf ("%04d%02d", $start_year, $start_week) } sort readdir(DIR); close DIR; push @weeks, @wks; } } # return immediately if no events if (scalar @weeks == 0) { return []; } # figure out the filename of the last week file $weeks[$#weeks] =~ /^(....)(..)$/; ($end_year, $end_week) = ($1, $2); $end_date = sprintf ("%04d%02d", $end_year, $end_week); # generate an array of filenames between first and last week filename into %weeks $cyear = $start_year; $cweek = $start_week; $cdate = sprintf "%04d%02d", $cyear, $cweek; do { $weeks{$cdate} = $weeks[0] == $cdate ? shift @weeks : 0; ($cyear, $cweek) = get_next_year_week ($cyear, $cweek); $cdate = sprintf "%04d%02d", $cyear, $cweek; } while ($cdate le $end_date); @ret = (); for $week_filename (sort keys %weeks) { my ($year, $week, @sum_week); $week_filename =~ /^(\d\d\d\d)(\d\d)/; ($year, $week) = ($1, $2); # if $weeks{$week_filename} has true value, then there are week # events for that week - only in that case we will use the repeat events if ($weeks{$week_filename}) { my ($e_n, $wday); $e_n = read_events ('n', $year, $week); # Combine week files and repeat files @sum_week = (); for $wday (0 .. 6) { my ($day, $month); ($month, $day) = get_month_day_by_wday_year_week ($wday, $year, $week); $sum_week[$wday] = join_days ($e_n->[$wday], $e_rw->[$wday], $e_rm->[$day]); } } else { @sum_week = ( {}, {}, {}, {}, {}, {}, {} ); # ignore repeat events too } push @ret, [\@sum_week, $year, $week]; } return \@ret; } sub week_cache_read ($$) { my ($year, $week) = @_; my ($filename, $data, $old_slash); local (*CRFH); if (!$main::DATA_ID) { return undef; } $filename = sprintf "$::DB_DIR/cache/w-%s-%04d%02d.html", $main::DATA_ID, $year, $week; if (! open (CRFH, $filename)) { return undef; } $old_slash = $/; undef $/; $data = ; $/ = $old_slash; close CRFH; return \$data; } sub week_cache_write_open ($$) { my ($year, $week) = @_; my ($dirname, $filename, $cfh); $cfh = 'this_is_a_filehandle'; $dirname = "$::DB_DIR/cache"; if ($main::DATA_ID) { $filename = sprintf "%s/w-%s-%04d%02d.html", $dirname, $main::DATA_ID, $year, $week; } else { $filename = sprintf "%s/w-fusion-%04d%02d.html", $dirname, $year, $week; } if (! -e $dirname) { if (! mkdir ($dirname, 0770)) { my $str1 = "can't create directory $dirname: $!"; return \$str1; } } if (! open ($cfh, ">$filename")) { my $str2 = "can't open file $filename for writing: $!"; return \$str2; } flock ($cfh, 2); return $cfh; } sub header_body ($) { return \$::H_BODY; } sub week_cache_write_close ($) { my ($fh) = @_; if (fileno(F)) { flock (F, 8); } close $fh; } sub week_split_events_noon ($) { my ($events_ref) = @_; my ($e1, $e2, $e3, $day, $hour); for (@$events_ref) { for $day (0 .. 6) { my (%hours); %hours = %{$events_ref->[$day]}; $e1->[$day] = {}; $e2->[$day] = {}; $e3->[$day] = {}; if (%hours) { for $hour (keys %hours) { if ($hour == -1) { $e3->[$day]->{$hour} = $events_ref->[$day]->{$hour}; } elsif ($hour < 12) { $e1->[$day]->{$hour} = $events_ref->[$day]->{$hour}; } else { $e2->[$day]->{$hour} = $events_ref->[$day]->{$hour}; } } } } } return ($e1, $e2, $e3); } sub week_print_events ($$$$$$) { my ($fh, $events_ref, $use_now_wday, $year, $week, $weekdays_ref) = @_; my ($day_offset, $day_ref, $hour, $event_ref); $day_offset = 0; for $day_ref (@$events_ref) { if (%$day_ref) { print $fh "\n"; print $fh "\n"; for $hour (sort { $a <=> $b } keys %$day_ref) { for $event_ref (@{$day_ref->{$hour}}) { print $fh '\n"; } } print $fh "
'; my ($id, $min, $title, $data, $lengthmin, $rt, $color, $color_end); my ($startyear, $startweek, $startwday, $duration); my ($alval, $altype, $alchk, $strike); $id = $event_ref->{'id'}; $min = $event_ref->{'min'}; $lengthmin = $event_ref->{'lengthmin'}; $title = $event_ref->{'title'}; $data = $event_ref->{'data'}; $rt = $event_ref->{'rt'}; $startyear = $event_ref->{'startyear'}; $startweek = $event_ref->{'startweek'}; $startwday = $event_ref->{'startwday'}; $duration = $event_ref->{'duration'}; $alval = $event_ref->{'alval'} || 0; $altype = $event_ref->{'altype'} || 0; $alchk = $event_ref->{'alchk'} || ""; $strike = $event_ref->{'strike'} || 0; if ($rt eq 'w') { $color = ""; } elsif ($rt eq 'm') { $color = ""; } else { $color = ''; } $color_end = ""; my $st = strcal(); print $fh "$color", $strike ? "" : "", $hour == -1 ? "" : ("",format_time ($hour, $min)," - ",format_time (int ($hour + ($min + $lengthmin)/60) % 24, ($min + $lengthmin) % 60)," "), $title, $strike ? "" : "", $color_end, "", img_note($data), img_alarm($alval, $altype, $alchk), "
\n"; } else { print $fh " \n"; } $day_offset++; } return; } # CGI input: year, week OR nothing, in which case current date is used sub show_week (;$) { my ($cacheonly) = @_; my ($week, $month, $day, $year, $first_day); my ($weekdata, $i, @weekdays, $cached_week_ref, $cache_fh); my ($now_date, $now_year, $now_week, $now_wday, $use_now_wday); my ($events1, $events2, $events3, $wday_name, $now_ref); $year = $::query->{'year'}; $week = $::query->{'week'}; if (! defined $year or ! defined $week) { my ($ref); $ref = get_now (); ($year, $week) = ($ref->{'year'}, $ref->{'week'}); } # If the week is in cache, return it sw_check_cache: $cached_week_ref = week_cache_read ($year, $week); if (defined $cached_week_ref) { $$cached_week_ref =~ s/X_USER_X/$main::USER/g; print Socket $$cached_week_ref; return; } # Find the current day to mark it in the output $now_ref = get_now (); ($now_year, $now_week, $now_wday) = ($now_ref->{'year'}, $now_ref->{'week'}, $now_ref->{'wday'}); if ($year == $now_year and $week == $now_week) { $use_now_wday = $now_wday + 0; } else { $use_now_wday = -1; } if (defined $main::DATA_ID && $main::DATA_ID) { # Start writing the week into cache $cache_fh = week_cache_write_open ($year, $week); if (ref $cache_fh) { print Socket "Internal error: $$cache_fh\n"; return; } } else # fusion { $cache_fh = "Socket"; } # Build year/month/day information of the required week ($month, $day) = get_month_day_by_firstday_year_week ($year, $week); $weekdays[0] = [$month, $day]; for $i (1..6) { my ($month, $day); ($month, $day) = get_month_day_by_wday_year_week ($i, $year, $week); $weekdays[$i] = [$month, $day]; } my $st = strcal(); print $cache_fh "\n"; print $cache_fh $::H_BODY; # Determine previous and next year & week my ($prev_week, $next_week, $prev_year, $next_year); $prev_week = $week - 1; $next_week = $week + 1; $prev_year = $next_year = $year; if ($prev_week < 2) { ($prev_year, $prev_week )= get_prev_year_week ($year, $week); } elsif ($next_week > 50) { ($next_year, $next_week )= get_next_year_week ($year, $week); } # cal links for fusion my $stl = lncal($year, $week); # Output title line print $cache_fh "\n"; print $cache_fh "\n"; print $cache_fh "\n"; print $cache_fh "\n"; print $cache_fh "
$stl\"".__("Semaine\n"; print $cache_fh " ",sprintf(__("%s Semaine %s Année %s"),__($::months[$month]),$week,$year)," \n"; print $cache_fh "\"".__("Semaine".__("Autres vues")."
\n\n"; print $cache_fh "\n"; print $cache_fh "\n"; # Print weekday names $i = 0; for $wday_name (@main::weekdays_short) { my ($color); if ($i == $use_now_wday) { $color = $::NOW_THCOLOR; } else { $color = $::THCOLOR; } if ($i <= 4) { print $cache_fh "\n"; week_print_events ($cache_fh, $events1, $use_now_wday, $year, $week, \@weekdays); print $cache_fh "\n"; week_print_events ($cache_fh, $events2, $use_now_wday, $year, $week, \@weekdays); print $cache_fh "\n"; week_print_events ($cache_fh, $events3, $use_now_wday, $year, $week, \@weekdays); print $cache_fh "
"; } else { print $cache_fh ""; } my $st = strcal(); print $cache_fh "", pd_month_day ($weekdays[$i]->[0], $weekdays[$i]->[1]), " ", __($wday_name), "\n"; $i++; } $weekdata = build_week ($year, $week); ($events1, $events2, $events3) = week_split_events_noon ($weekdata); print $cache_fh "
\n\n"; if (defined $main::DATA_ID && $main::DATA_ID) { # Now the cache should exist, so retry (someone may have removed it meanwhile, but then we just retry) week_cache_write_close ($cache_fh); goto sw_check_cache; } } sub show_day () { my ($day, $month, $week, $year, $wday, $wday_name, $eventsdata, @hours, @thours, $day_ref, $rt); my ($now_ref, $now_thcolor, $is_now_day, $hour, $event_ref); # see if we are given the day or not - if year exists, assume yes $year = $::query->{'year'}; if (! defined $year) { my ($now_ref); $now_ref = get_now (); ($year, $month, $day, $week, $wday) = ($now_ref->{'year'}, $now_ref->{'month'}, $now_ref->{'day'}, $now_ref->{'week'}, $now_ref->{'wday'}); } else { $week = $::query->{'week'}; $wday = $::query->{'wday'}; } $wday_name = $::weekdays[$wday]; ($month, $day) = get_month_day_by_wday_year_week ($wday, $year, $week); $day_ref = build_day ($year, $week, $wday, $day); # Build list of events on each hour @hours = (); for $hour (sort { $a <=> $b } keys %$day_ref) { if ($hour == -1) { for $event_ref (@{$day_ref->{$hour}}) { push @{$hours[24]}, $event_ref; } } else { for $event_ref (@{$day_ref->{$hour}}) { push @{$hours[$hour]}, $event_ref; } } } # Count how many events will be on each row my ($max_c, $cols, @rows); $max_c = 0; @rows = (0) x ($::LAST_HOUR + 1); for $hour ($::FIRST_HOUR .. $::LAST_HOUR) { if ($hours[$hour]) { for $event_ref (@{$hours[$hour]}) { my ($lengthmin, $min, $end_hour, $h); $lengthmin = $event_ref->{'lengthmin'}; $min = $event_ref->{'min'}; $end_hour = $hour + int (($lengthmin + $min - 1) / 60) % 24; for $h ($hour .. $end_hour) { my ($c); $c = ++$rows[$h]; if ($c > $max_c) { $max_c = $c; } } } } } $max_c = 1 if $max_c == 0; $cols = $max_c + 1; $now_ref = get_now (); if ($now_ref->{'year'} == $year and $now_ref->{'month'} == $month and $now_ref->{'day'} == $day) { $is_now_day = 1; } else { $is_now_day = 0; } if ($is_now_day) { $now_thcolor = $::NOW_THCOLOR; } else { $now_thcolor = $::THCOLOR; } my $st = strcal(); print Socket "\n"; print Socket "\n"; print Socket $::H_BODY; print Socket "\n"; print Socket "\n"; print Socket "
\n"; print Socket "
", pd_year_month_day ($year, $month, $day), " ", __("$wday_name")."\n"; if (defined $::READ_ONLY and $::READ_ONLY ne 'true' and clipboard_get ($::REMOTE_USER)) { print Socket "  [".__("Coller")."]\n"; } print Socket "
\n"; if ($::READ_ONLY ne 'true') { print Socket ""; print Socket ">\n"; } else { print Socket ">\n"; } print Socket " 1) { print Socket "COLSPAN=\"$max_c\""; } print Socket ">\n"; my $isev = 0; my $sthour; my $sttime; for $hour (0 .. $::FIRST_HOUR-1, $::LAST_HOUR+1 .. 25) { if ($hours[$hour]) { $isev = 1; my (@events, $event_ref); @events = @{$hours[$hour]}; for $event_ref (@events) { my ($id, $min, $title, $data, $lengthmin, $rcolor, $rcolor_end); my ($startyear, $startweek, $startwday, $duration); my ($alval, $altype, $alchk, $strike); $id = $event_ref->{'id'}; $min = $event_ref->{'min'}; $lengthmin = $event_ref->{'lengthmin'}; $title = $event_ref->{'title'}; $data = $event_ref->{'data'}; $rt = $event_ref->{'rt'}; $startyear = $event_ref->{'startyear'}; $startweek = $event_ref->{'startweek'}; $startwday = $event_ref->{'startwday'}; $duration = $event_ref->{'duration'}; $alval = $event_ref->{'alval'} || 0; $altype = $event_ref->{'altype'} || 0; $alchk = $event_ref->{'alchk'} || ""; $strike = $event_ref->{'strike'} || 0; if ($rt eq 'w') { $rcolor = ""; $rcolor_end = ""; } elsif ($rt eq 'm') { $rcolor = ""; $rcolor_end = ""; } else { $rcolor = $rcolor_end = ''; } if ($hour == 24) { $sthour = -1; $sttime = ""; } else { $sthour = $hour; $sttime = "".format_time($hour, $min)." - ".format_time(int($hour + ($min + $lengthmin)/60) % 24, ($min + $lengthmin) % 60)." "; } print Socket '
"; } print Socket format_hour_padded ($hour); if ($::READ_ONLY ne 'true') { print Socket "\n"; } # # Print events for this hour # if ($hours[$hour]) { my (@events, $event_ref); @events = @{$hours[$hour]}; for $event_ref (@events) { my ($id, $min, $title, $data, $lengthmin, $rcolor, $rcolor_end); my ($startyear, $startweek, $startwday, $duration); my ($alval, $altype, $alchk, $strike); $id = $event_ref->{'id'}; $min = $event_ref->{'min'}; $lengthmin = $event_ref->{'lengthmin'}; $title = $event_ref->{'title'}; $data = $event_ref->{'data'}; $rt = $event_ref->{'rt'}; $startyear = $event_ref->{'startyear'}; $startweek = $event_ref->{'startweek'}; $startwday = $event_ref->{'startwday'}; $duration = $event_ref->{'duration'}; $alval = $event_ref->{'alval'} || 0; $altype = $event_ref->{'altype'} || 0; $alchk = $event_ref->{'alchk'} || ""; $strike = $event_ref->{'strike'} || 0; if ($rt eq 'w') { $rcolor = ""; $rcolor_end = ""; } elsif ($rt eq 'm') { $rcolor = ""; $rcolor_end = ""; } else { $rcolor = $rcolor_end = ''; } print Socket '{'year'}; $week = $::query->{'week'}; $wday = $::query->{'wday'} || 0; $wday_name = $::weekdays[$wday]; $hour = $::query->{'hour'} || 0; $min = $::query->{'min'} || 0; $lengthmin = $::query->{'lengthmin'} || 0; $title = $::query->{'title'}; $data = $::query->{'data'}; $rt = $::query->{'rt'}; $is_now = $::query->{'is_now'}; $startyear = $::query->{'startyear'}; $startweek = $::query->{'startweek'}; $startwday = $::query->{'startwday'}; $duration = $::query->{'duration'}; $alval = $::query->{'alval'} || 0; $altype = $::query->{'altype'} || 0; $alchk = $::query->{'alchk'} || ""; $strike = $::query->{'strike'} || 0; if (! defined $year or ! defined $title) { my ($n); $n = get_now (); show_other_views ($n->{'year'}, $n->{'week'}); return; } ($month, $day) = get_month_day_by_wday_year_week ($wday, $year, $week); $endhour = int ($hour + ($min + $lengthmin) / 60) % 24; $endmin = int (($min + $lengthmin) % 60); print Socket $::H_BODY; if ($is_now) { $now_thcolor = $::NOW_THCOLOR; } else { $now_thcolor = $::THCOLOR; } if ($rt eq 'w') { $rcolor = "COLOR=\"$::REPEAT_WEEK_TEXTCOLOR\""; } elsif ($rt eq 'm') { $rcolor = "COLOR=\"$::REPEAT_MONTH_TEXTCOLOR\""; } else { $rcolor = ''; } print Socket "
\n\n"; print Socket "
".__("Tâche le")." ", pd_event_date ($rt, $startyear, $startweek, $startwday, $duration); print Socket "\n
\n"; my ($stk1, $stk2) = $strike ? ("","") : ("",""); if ($hour == -1) { printf Socket "

$stk1$title$stk2"; } else { printf Socket "

$stk1%s - %s $title$stk2", format_time ($hour, $min), format_time ($endhour, $endmin); } print Socket (($rt eq 'w') ? ' ('.__("hebdomadaire").')' : ( ( $rt eq 'm' ) ? ' ('.__("mensuelle").')' : '' )); print Socket "", txt_alarm($alval, $altype, $alchk), "
\n"; print Socket "

$data\n"; print Socket "

\n"; my $st = strcal(); if ($::READ_ONLY ne 'true') { my ($enc_title, $enc_data); $enc_title = url_encode ($title); $enc_data = url_encode ($data); my $stk3 = $strike ? __("Activer") : __("Désactiver"); print Socket "", "[".__("Editer")."]\n"; print Socket "   ", "[".__("Couper")."]\n"; print Socket "   ", "[".__("Copier")."]\n"; print Socket "   ", "[".__("Supprimer")."]\n"; print Socket "   ", "[$stk3]\n"; } print Socket "
\n"; } sub add_edit_event_ask () { my ($id, $year, $month, $day, $week, $wday, $wday_name, $weekdata, @hours, $day_ref); my ($hour, $min, $lengthmin, $title, $data, $endhour, $endmin, $rt, $duration); my ($startyear, $startweek, $startwday, $startmonth, $startday); my ($endyear, $endweek, $endwday, $endmonth, $endday); $id = $::query->{'id'} || ''; $year = $::query->{'year'}; $week = $::query->{'week'}; $wday = $::query->{'wday'}; $wday_name = $::weekdays[$wday]; $hour = $::query->{'hour'}; $min = $::query->{'min'} || 0; $lengthmin = $::query->{'lengthmin'}; $rt = $::query->{'rt'} || 'n'; $title = $::query->{'title'} || ''; $data = $::query->{'data'} || ''; $startyear = $::query->{'startyear'} || $year; $startweek = $::query->{'startweek'} || $week; $startwday = defined $::query->{'startwday'} ? $::query->{'startwday'} : $wday; $duration = $::query->{'duration'} || 1; my $strike = $::query->{'strike'} || 0; ($month, $day) = get_month_day_by_wday_year_week ($wday, $year, $week); if ($id) { if ($hour == -1) { $endhour = -1; $endmin = -1; } else { $endhour = int ($hour + ($min + $lengthmin) / 60) % 24; $endmin = int (($min + $lengthmin) % 60); } } else { $endhour = $hour+1; $endmin = 0; } ($startmonth, $startday, $endyear, $endweek, $endwday, $endmonth, $endday) = get_start_end_by_year_week_wday_duration ($startyear, $startweek, $startwday, $duration); print Socket $::H_BODY; print Socket "
\n"; print Socket "\n"; print Socket "\n"; print Socket "
"; if ($id) { print Socket __("Editer tâche"); } else { print Socket __("Ajouter tâche"); } print Socket " ".pd_event_date ($rt, $startyear, $startweek, $startwday, $duration); print Socket "
\n"; print Socket "
\n\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; # Event time print Socket "\n"; # Duration (days) print Socket "\n"; # Alarm print Socket ""; my $alval = $::query->{'alval'} || 0; print Socket "\n"; # Title print Socket ""; # Data print Socket ""; print Socket "
\n"; print Socket __("Heure début")."\n"; print Socket "\n"; print Socket " - \n"; print Socket "\n"; print Socket "\n
".__("Durée")."\n"; # Repeat my ($sn, $sw, $sm); $sn = $sw = $sm = ''; if ($rt eq 'n') { $sn = 'SELECTED'; } elsif ($rt eq 'w') { $sw = 'SELECTED'; } elsif ($rt eq 'm') { $sm = 'SELECTED'; } print Socket "\n
".__("Alarme")."\n"; my $altype = $::query->{'altype'} || 0; print Socket "\n"; print Socket ' ".__("lancée"); print Socket "
".__("Titre").""; print Socket "
\n"; # Submit my ($submit_value); $submit_value = ($id ? __("Valider") : __("Ajouter")); print Socket "\n"; print Socket "
\n"; print Socket "
\n"; print Socket "
\n"; print Socket "\n"; } sub print_event_error_start () { print Socket $::H_BODY; print Socket "
\n"; print Socket "\n


\n\n"; } sub print_event_error_end () { print Socket "

\n\n"; } sub day_index ($$$$) { my ($rt, $year, $week, $wday) = @_; my ($index); # Index by day or wday, depending on repeat type if ($rt eq 'n' or $rt eq 'w') { $index = $wday + 0; } else { my ($month, $day); ($month, $day) = get_month_day_by_wday_year_week ($wday, $year, $week); $index = $day + 0; } return $index; } # Read, update, and write new highest event id into general database # Return the (id, possible error or false) sub next_id () { my ($id, $gendata, $err); $gendata = read_general (); if (! ref $gendata eq 'HASH') { $err = $gendata; return ('', $err); } $id = $gendata->{'highid'} + 1; $gendata->{'highid'} = $id; $err = write_general ($gendata); if ($err) { return ('', $err); } return ($id, ''); } sub remove_events ($$$$$$$) { my ($rt, $year, $week, $wday, $duration, $hour, $id) = @_; my ($i); for $i (0 .. $duration - 1) { my ($cyear, $cweek, $cwday, $index_day, $hour_ref, $eventsdata, @hour, $err); ($cyear, $cweek, $cwday) = get_year_week_wday_by_year_week_wday_plus_days ($year, $week, $wday, $i); $index_day = day_index ($rt, $cyear, $cweek, $cwday); $eventsdata = read_events ($rt, $cyear, $cweek); $hour_ref = $eventsdata->[$index_day]->{$hour}; if (ref $hour_ref eq 'ARRAY') { my ($i); @hour = @$hour_ref; for $i (0 .. $#hour) { if ($hour[$i]->{'id'} == $id) { splice (@hour, $i, 1); goto re_found; } } } return "internal error: the event isn't in the database (user ${main::DATA_ID}, year $cyear, week $cweek, wday $cwday, id $id, rt $rt)"; re_found: if (@hour) { $eventsdata->[$index_day]->{$hour+0} = \@hour; } else { # no events left for this hour, so remove whole hour delete $eventsdata->[$index_day]->{$hour}; } $err = write_events ($eventsdata, $rt, $cyear, $cweek); if ($err) { return $err; } } return ''; } sub add_events { my ($rt, $year, $week, $wday, $duration, $hour, $id, $min, $lengthmin, $title, $data, $alval, $altype, $alchk, $strike) = @_; my ($i, $err); if (!$alval) { $alval = 0; } if (!$altype) { $altype = 0; } if (!$alchk) { $alchk = ""; } if (!$strike) { $strike = 0; } # Figure out the new $id if (! $id) { my ($gendata); # Read, update, and write new highest event id into general database $gendata = read_general (); if (! ref $gendata eq 'HASH') { $err = $gendata; return $err; } $id = $gendata->{'highid'} + 1; $gendata->{'highid'} = $id; $err = write_general ($gendata); if ($err) { return $err; } } for $i (0 .. $duration - 1) { my ($cyear, $cweek, $cwday, $index_day, $eventsdata); ($cyear, $cweek, $cwday) = get_year_week_wday_by_year_week_wday_plus_days ($year, $week, $wday, $i); $index_day = day_index ($rt, $cyear, $cweek, $cwday); # Read events, add, write back $eventsdata = read_events ($rt, $cyear, $cweek); push @{$eventsdata->[$index_day]->{$hour+0}}, { 'id' => $id + 0, 'min' => $min + 0, 'lengthmin' => $lengthmin + 0, 'title' => $title, 'data' => $data, 'rt' => $rt, 'startyear' => $year + 0, 'startweek' => $week + 0, 'startwday' => $wday + 0, 'duration' => $duration + 0, 'alval' => $alval + 0, 'altype' => $altype + 0, 'alchk' => $alchk, 'strike' => $strike, }; $err = write_events ($eventsdata, $rt, $cyear, $cweek); if ($err) { return $err; } } return ''; } sub add_event_commit () { my ($id, $year, $month, $day, $week, $wday, $wday_name, $rt); my ($hour1, $min1, $hour2, $min2, $lengthmin, $title, $data, $endhour, $endmin); my ($err, $i); my ($oldrt, $oldhour); my ($oldhour_ref, @hour, $oldduration, $duration); my ($startyear, $startweek, $startwday, $startmonth, $startday); my ($alval, $altype, $alchk, $strike); $oldrt = $::query->{'oldrt'}; $oldhour = $::query->{'oldhour'}; $oldduration = $::query->{'oldduration'}; $id = $::query->{'id'} || ''; $year = $::query->{'year'}; $week = $::query->{'week'}; $wday = $::query->{'wday'}; $startyear = $::query->{'startyear'}; $startweek = $::query->{'startweek'}; $startwday = $::query->{'startwday'}; $duration = $::query->{'duration'}; $hour1 = $::query->{'hour1'}; $min1 = $::query->{'min1'}; $hour2 = $::query->{'hour2'}; $min2 = $::query->{'min2'}; $rt = $::query->{'rt'}; $title = strip_space $::query->{'title'}; $data = strip_space $::query->{'data'} || ''; $alval = $::query->{'alval'} || 0; $altype = $::query->{'altype'} || 0; $alchk = $::query->{'alchk'} || ""; $strike = $::query->{'strike'} || 0; ($startmonth, $startday) = get_month_day_by_wday_year_week ($startwday, $startyear, $startweek); if ($hour1 == -1) { $min1 = -1; $hour2 = -1; $min2 = -1; $lengthmin = -1; } else { $lengthmin = $hour2*60 + $min2 - $hour1*60 - $min1; } if (! defined $title or ! $title) { return "The title of the event must be entered."; } elsif (! &ParseDate ("$startmonth/$startday/$startyear")) { return "Date $startday.$startmonth.$startyear is invalid." } elsif ($duration < 1 or $duration > $::MAX_DURATION) { return "You chose impossible duration \"$duration\"." } elsif ($rt eq 'w' and ! fit_in_week ($startyear, $startweek, $startwday, $duration)) { return "Weekly repeating event must fit entirely in one week." } elsif ($rt eq 'm' and ! fit_in_month ($startyear, $startweek, $startwday, $duration)) { return "Monthly repeating event must fit entirely in one month (the month you placed it in specifically)." } elsif ($rt ne 'n' and $rt ne 'w' and $rt ne 'm') { return "You chose impossible repeat type \"$rt\"." } elsif (has_html $title or has_html $data) { return "Text contains one more more of the illegal characters <, > and &." } elsif ($lengthmin <= 0 && $hour1 != -1) { return "The start of the event ($hour1:$min1) must be before its end ($hour2:$min2)." } $title = newline_to_html $title; $data = newline_to_html $data; # # Remove the old event. The old one only exists if $id is set so this is # an edit command. # if ($id) { $err = remove_events ($oldrt, $startyear, $startweek, $startwday, $oldduration, $oldhour, $id); if ($err) { return $err; } } # # Figure out the new $id # if (! $id) { ($id, $err) = next_id (); if ($err) { return $err; } } # # Add event for each day # $err = add_events ($rt, $startyear, $startweek, $startwday, $duration, $hour1, $id, $min1, $lengthmin, $title, $data, $alval, $altype, $alchk, $strike); if ($err) { return $err; } # # When we get here, add has been succesful. # # Return the id and some other items to redraw(), since he doesn't know # them otherwise. # return { 'id' => $id, 'lengthmin' => $lengthmin, 'data' => $data, 'title' => $title }; } sub remove_event_commit ($$$$$$$$$$$$$$) { my ($year, $week, $wday, $id, $hour, $rt, $min, $lengthmin, $title, $data, $startyear, $startweek, $startwday, $duration) = @_; my ($err); if (! defined $id or ! defined $week or ! defined $wday or ! defined $rt or ! defined $duration) { return "some data of the event to be removed not given"; } # # Copy data into clipboard # clipboard_set ($::REMOTE_USER, { 'hour' => $hour, 'min' => $min, 'lengthmin' => $lengthmin, 'title' => $title, 'data' => $data, 'rt' => $rt, 'startyear' => $startyear, 'startweek' => $startweek, 'startwday' => $startwday, 'duration' => $duration } ); # # Remove the event from the database # $err = remove_events ($rt, $startyear, $startweek, $startwday, $duration, $hour, $id); if ($err) { return $err; } return ''; } sub delete_event_commit ($$$$$$$$$$$$$$) { my ($year, $week, $wday, $id, $hour, $rt, $min, $lengthmin, $title, $data, $startyear, $startweek, $startwday, $duration) = @_; my ($err); if (! defined $id or ! defined $week or ! defined $wday or ! defined $rt or ! defined $duration) { return "some data of the event to be removed not given"; } # # Remove the event from the database # $err = remove_events ($rt, $startyear, $startweek, $startwday, $duration, $hour, $id); if ($err) { return $err; } return ''; } sub switch_strike_event_commit { my ($year, $week, $wday, $id, $hour, $rt, $min, $lengthmin, $title, $data, $startyear, $startweek, $startwday, $duration, $alval, $altype, $alchk, $strike) = @_; my ($err); if (! defined $id or ! defined $week or ! defined $wday or ! defined $rt or ! defined $duration) { return "some data of the event to be striked not given"; } # # Strike/unstrike the event in the database # $strike = 1 - $strike; $err = remove_events ($rt, $startyear, $startweek, $startwday, $duration, $hour, $id); if ($err) { return $err; } $err = add_events ($rt, $startyear, $startweek, $startwday, $duration, $hour, $id, $min, $lengthmin, $title, $data, $alval, $altype, $alchk, $strike); if ($err) { return $err; } return ''; } sub copy_event () { my ($hour, $min, $lengthmin, $title, $data, $rt, $startyear, $startweek, $startwday, $duration); $hour = $::query->{'hour'}; $min = $::query->{'min'}; $lengthmin = $::query->{'lengthmin'}; $title = $::query->{'title'}; $data = $::query->{'data'}; $rt = $::query->{'rt'}; $startyear = $::query->{'startyear'}; $startweek = $::query->{'startweek'}; $startwday = $::query->{'startwday'}; $duration = $::query->{'duration'}; return if ! check_write_access (); clipboard_set ($::REMOTE_USER, { 'hour' => $hour, 'min' => $min, 'lengthmin' => $lengthmin, 'title' => $title, 'data' => $data, 'rt' => $rt, 'startyear' => $startyear, 'startweek' => $startweek, 'startwday' => $startwday, 'duration' => $duration } ); # Show_even() re-reads the variables from %$::query show_event (); } sub paste_event_commit ($$$) { my ($year, $week, $wday) = @_; my ($event_ref, $err, $id); # Read the event data from clipboard $event_ref = clipboard_get ($::REMOTE_USER); if (! $event_ref) { return "There is no event in clipboard for your computer $::REMOTE_USER."; } # # Find new id # ($id, $err) = next_id (); if ($err) { return $err; } # # Update some fields # $event_ref->{'startyear'} = $year; $event_ref->{'startweek'} = $week; $event_ref->{'startwday'} = $wday; $event_ref->{'id'} = $id; # # Make some sanity checks # my ($startmonth, $startday, $startyear, $startweek, $startwday, $duration, $rt); ($startmonth, $startday) = get_month_day_by_wday_year_week ($wday, $year, $week); $startyear = $year; $startweek = $week; $startwday = $wday; $duration = $event_ref->{'duration'}; $rt = $event_ref->{'rt'}; if (! &ParseDate ("$startmonth/$startday/$startyear")) { return "Date $startday.$startmonth.$startyear is invalid." } elsif ($rt eq 'w' and ! fit_in_week ($startyear, $startweek, $startwday, $duration)) { return "Weekly repeating event must fit entirely in one week." } elsif ($rt eq 'm' and ! fit_in_month ($startyear, $startweek, $startwday, $duration)) { return "Monthly repeating event must fit entirely in one month (the month you placed it in, specifically)." } # # Add event for each day # $err = add_events ( $event_ref->{'rt'}, $event_ref->{'startyear'}, $event_ref->{'startweek'}, $event_ref->{'startwday'}, $event_ref->{'duration'}, $event_ref->{'hour'}, $event_ref->{'id'}, $event_ref->{'min'}, $event_ref->{'lengthmin'}, $event_ref->{'title'}, $event_ref->{'data'} ); if ($err) { return $err; } # When we get here, add has been succesful return $event_ref; } sub xxx_event_error () { my ($error1, $error2); $error1 = $::query->{'error1'}; $error2 = $::query->{'error2'}; print Socket $::H_BODY; print Socket "
\n"; print Socket "\n"; print Socket ""; print Socket "
\n"; print Socket "

$error1

\n"; print Socket "

$error2\n

\n"; print Socket "\n"; return; } sub show_event_list () { my ($year, $week, $alldata_ref, $lastweek); my ($cweek, $cyear, $cmonth, $cday, $end_cmonth, $end_cday); my ($now_ref, $now_year, $now_week, $now_wday, $week_ref, $wday, $hour); $year = $::query->{'year'}; $week = $::query->{'week'}; $alldata_ref = build_week_list ($year, $week); if (ref $alldata_ref ne 'ARRAY') { print Socket "

Listing events failed: $alldata_ref

\n"; return; } $now_ref = get_now (); ($now_year, $now_week, $now_wday) = ($now_ref->{'year'}, $now_ref->{'week'}, $now_ref->{'wday'}); print Socket $::H_BODY; print Socket "
\n
\n

\n"; print Socket "\n"; my $str = sprintf(__("Tâches depuis la semaine %d de l'année %d"), $week, $year); print Socket ""; printf Socket "%s %s - %s\n", __($::weekdays_short[$wday]), format_time_padded ($hour1, $min1), format_time_padded ($hour2, $min2); print Socket "
$str\n"; print Socket "
\n"; my $st = strcal(); $lastweek = -1; for $week_ref (@$alldata_ref) { for $wday (0..6) { for $hour (sort {$a <=> $b} keys %{$week_ref->[0]->[$wday]}) { my ($event_ref); $cyear = $week_ref->[1]; $cweek = $week_ref->[2]; # Change of week if ($cweek != $lastweek) { my ($b_month, $b_day, $e_month, $e_day, $color); $lastweek = $cweek; ($b_month, $b_day) = get_month_day_by_firstday_year_week ($cyear, $cweek); ($e_month, $e_day) = get_month_day_by_wday_year_week (6, $cyear, $cweek); if ($cyear == $now_year and $cweek == $now_week) { $color = $::NOW_TDCOLOR; } else { $color = $::TDCOLOR; } print Socket "
".sprintf(__("Semaine %s"), $cweek).", ", pd_year_month_day ($cyear, $b_month, $b_day), " - ", pd_year_month_day ($cyear, $e_month, $e_day), "\n"; } for $event_ref (@{$week_ref->[0]->[$wday]->{$hour}}) { my (%e, $hour1, $min1, $hour2, $min2, $lengthmin); my ($tmonth, $tday, $twday, $id, $min, $title, $data, $rt, $day, $color, $rcolor); my ($startyear, $startweek, $startwday, $duration); %e = %$event_ref; $hour1 = $hour; $id = $e{'id'}; $min1 = $e{'min'}; $lengthmin = $e{'lengthmin'}; $title = $e{'title'}; $data = $e{'data'}; $rt = $e{'rt'}; $startyear = $event_ref->{'startyear'}; $startweek = $event_ref->{'startweek'}; $startwday = $event_ref->{'startwday'}; $duration = $event_ref->{'duration'}; $hour2 = ($hour1 + int (($min1+$lengthmin) / 60)) % 24; $min2 = ($min1 + $lengthmin) % 60; ($cmonth, $cday) = get_month_day_by_wday_year_week ($wday, $cyear, $cweek); if ($cyear == $now_year and $cweek == $now_week and $wday == $now_wday) { $color = " BGCOLOR=\"$::NOW_TDCOLOR\""; } else { $color = " BGCOLOR=\"$::BG_TDCOLOR\""; } if ($rt eq 'w') { $rcolor = "COLOR=\"$::REPEAT_WEEK_TEXTCOLOR\""; } elsif ($rt eq 'm') { $rcolor = "COLOR=\"$::REPEAT_MONTH_TEXTCOLOR\""; } else { $rcolor = ''; } print Socket "
", $e{'title'}, "", $data || " ", "\n"; } } } } print Socket "

\n"; return; } sub show_other_views (;$$) { my ($year, $week) = @_; my ($month, $moffset); $year = $year || $::query->{'year'}; $week = $week || $::query->{'week'}; print Socket $::H_BODY; print Socket "

\n\n"; print Socket "
".__("Autres vues").""; print Socket "\n
\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "
    \n"; my $str = sprintf(__("Agendas %s"), $::ORGANIZATION); my $st = strcal(); print Socket "
  • $str\n"; $str = sprintf(__("Tâches depuis la semaine %d de l'année %d"), $week, $year); print Socket "
  • $str"; print Socket "
    \n"; $str = sprintf(__("Purger l'agenda jusqu'à la semaine %d de l'année %d"), , $week, $year); if (!$st && $::USER !~ /^\wo_/ && -e "/dev/pilot") { print Socket "
  • $str"; } print Socket "
\n"; print Socket "
\n"; my ($cyear, $cweek, $cmonth, $cday, $now_year, $now_week, $n); $n = get_now (); $now_year = $n->{'year'}; $now_week = $n->{'week'}; ($cyear, $cweek) = get_year_week_by_firstday_year_week_minus_days ($year, $week, ($::MANY_WEEKS_VERT * $::MANY_WEEKS_HOR + int ($::MANY_WEEKS_HOR / 2)) * 7); for $moffset (-$::MANY_WEEKS_VERT .. $::MANY_WEEKS_VERT) { my ($m); print Socket "\n"; for $m (0 .. $::MANY_WEEKS_HOR-1) { ($cmonth, $cday) = get_month_day_by_firstday_year_week ($cyear, $cweek); if ($cweek == $now_week and $cyear == $now_year) { printf Socket "\n", $cweek, pd_month_day_padded ($cmonth, $cday); } else { printf Socket "\n", $cweek, pd_month_day_padded ($cmonth, $cday); } $cweek++; if ($cweek > 50) { $cweek--; ($cyear, $cweek) = get_next_year_week ($cyear, $cweek); } } print Socket "\n"; } print Socket "
%02d : %s%02d : %s
\n"; print Socket "
\n"; print Socket "
\n\n"; return; } sub redraw_print_frameset ($$$) { my ($tweek, $tday, $tevent) = @_; my ($top_y, $left_x); if ($::SCREEN_RESOLUTION eq '800x600') { $top_y = 200; $left_x = 250; } else { $top_y = 250; $left_x = 320 } my $title = sprintf(__("Agenda %s"), $::LONG_NAME); my $st = ""; if ($::query->{'cal'}) { $st .= "&cal=".join("&cal=", split(/\n/, $::query->{'cal'})); } print Socket <$title frameborder="0" marginheight="0" marginwidth="3" name="fhead" scrolling="no" target="fday" noresize> <body> </body> END return; } sub check_write_access () { if ($::READ_ONLY eq 'true') { print Socket $::H_BODY; print Socket "
\n"; print Socket "\n"; print Socket "
 

This user has no write permission.

 

\n"; print Socket "\n"; return 0; } return 1; } sub redraw () { my ($view, $id, $year, $week, $wday, $wday_name); my ($hour, $min, $lengthmin, $title, $data, $rt); my ($tweek, $tday, $tevent); my ($startyear, $startweek, $startwday, $duration); my ($alval, $altype, $alchk, $strike); $view = $::query->{'view'}; $id = $::query->{'id'}; $year = $::query->{'year'}; $week = $::query->{'week'}; $wday = $::query->{'wday'} || 0; $wday_name = $::weekdays[$wday]; $hour = $::query->{'hour'}; $min = $::query->{'min'}; $lengthmin = $::query->{'lengthmin'}; $title = $::query->{'title'}; $data = $::query->{'data'}; $rt = $::query->{'rt'} || 'n'; $startyear = $::query->{'startyear'}; $startweek = $::query->{'startweek'}; $startwday = $::query->{'startwday'}; $duration = $::query->{'duration'}; $alval = $::query->{'alval'}; $altype = $::query->{'altype'}; $alchk = $::query->{'alchk'} || ""; $strike = $::query->{'strike'} || 0; if (! defined $view or $view eq '' or $view eq 'default') { $tweek = "$::MY_URL/?t=week"; $tday = "$::MY_URL/?t=day"; $tevent = "$::MY_URL/?t=event"; redraw_print_frameset ($tweek, $tday, $tevent); } elsif ($view eq 'week') { $tweek = "$::MY_URL/?t=week&year=$year&week=$week"; $tday = "$::MY_URL/?t=day"; $tevent = "$::MY_URL/?t=event"; redraw_print_frameset ($tweek, $tday, $tevent); } elsif ($view eq 'event') { $tweek = "$::MY_URL/?t=week&year=$year&week=$week"; $tday = "$::MY_URL/?t=day&year=$year&week=$week&wday=$wday"; $tevent = "$::MY_URL/?t=event&id=$id&year=$year&week=$week&wday=$wday&hour=$hour&min=$min&lengthmin=$lengthmin&title=" . url_encode ($title) . "&data=" . url_encode ($data) . "&rt=$rt&startyear=$startyear&startweek=$startweek&startwday=$startwday&duration=$duration"; redraw_print_frameset ($tweek, $tday, $tevent); } elsif ($view eq 'after_remove_event') { my ($err); return if ! check_write_access (); $err = remove_event_commit ($year, $week, $wday, $id, $hour, $rt, $min, $lengthmin, $title, $data, $startyear, $startweek, $startwday, $duration); $tweek = "$::MY_URL/?t=week&year=$year&week=$week"; $tday = "$::MY_URL/?t=day&year=$year&week=$week&wday=$wday&rt=$rt"; if ($err) { $tevent = "$::MY_URL/?t=xxx_event_error&error1=" . url_encode ("Error removing event") . "&error2=" . (url_encode $err); } else { $tevent = "$::MY_URL/?t=event"; } redraw_print_frameset ($tweek, $tday, $tevent); } elsif ($view eq 'after_delete_event') { my ($err); return if ! check_write_access (); $err = delete_event_commit ($year, $week, $wday, $id, $hour, $rt, $min, $lengthmin, $title, $data, $startyear, $startweek, $startwday, $duration); $tweek = "$::MY_URL/?t=week&year=$year&week=$week"; $tday = "$::MY_URL/?t=day&year=$year&week=$week&wday=$wday&rt=$rt"; if ($err) { $tevent = "$::MY_URL/?t=xxx_event_error&error1=" . url_encode ("Error removing event") . "&error2=" . (url_encode $err); } else { $tevent = "$::MY_URL/?t=event"; } redraw_print_frameset ($tweek, $tday, $tevent); } elsif ($view eq 'paste_event') { my ($err); return if ! check_write_access (); $err = paste_event_commit ($year, $week, $wday); $tweek = "$::MY_URL/?t=week&year=$year&week=$week"; $tday = "$::MY_URL/?t=day&year=$year&week=$week&wday=$wday&rt=$rt"; if (ref $err ne 'HASH') { $tevent = "$::MY_URL/?t=xxx_event_error&error1=" . url_encode ("Error pasting event from clipboard") . "&error2=" . (url_encode $err); } else { $tevent = "$::MY_URL/?t=event&id=" . $err->{'id'} . "&year=$year&week=$week&wday=$wday&hour=" . $err->{'hour'} . "&min=" . $err->{'min'} . "&lengthmin=" . $err->{'lengthmin'} . "&title=" . url_encode ($err->{'title'}) . "&data=" . url_encode ($err->{'data'}) . "&rt=" . $err->{'rt'} . "&startyear=" . $err->{'startyear'} . "&startweek=" . $err->{'startweek'} . "&startwday=" . $err->{'startwday'} . "&duration=" . $err->{'duration'}; } redraw_print_frameset ($tweek, $tday, $tevent); } elsif ($view eq 'add_event') { my ($err); return if ! check_write_access (); $err = add_event_commit (); $tweek = "$::MY_URL/?t=week&year=$year&week=$week"; $tday = "$::MY_URL/?t=day&year=$year&week=$week&wday=$wday&rt=$rt"; if (ref $err ne 'HASH') { $tevent = "$::MY_URL/?t=xxx_event_error&error1=" . url_encode ("Error adding an event") . "&error2=" . (url_encode $err); } else { $tevent = "$::MY_URL/?t=event&id=" . $err->{'id'} . "&year=$year&week=$week&wday=$wday&hour=" . $::query->{'hour1'} . "&min=" . $::query->{'min1'} . "&lengthmin=" . $err->{'lengthmin'} . "&title=" . url_encode ($err->{'title'}) . "&data=" . url_encode ($err->{'data'}) . "&rt=$rt&startyear=$startyear&startweek=$startweek&startwday=$startwday&duration=$duration&alval=$alval&altype=$altype&alchk=$alchk&strike=$strike"; } redraw_print_frameset ($tweek, $tday, $tevent); } elsif ($view eq 'after_strike_event') { my ($err); return if ! check_write_access (); $err = switch_strike_event_commit ($year, $week, $wday, $id, $hour, $rt, $min, $lengthmin, $title, $data, $startyear, $startweek, $startwday, $duration, $alval, $altype, $alchk, $strike); $tweek = "$::MY_URL/?t=week&year=$year&week=$week"; $tday = "$::MY_URL/?t=day&year=$year&week=$week&wday=$wday&rt=$rt"; if ($err) { $tevent = "$::MY_URL/?t=xxx_event_error&error1=" . url_encode ("Error striking event") . "&error2=" . (url_encode $err); } else { $strike = 1 - $strike; $tevent = "$::MY_URL/?t=event&id=$id&year=$year&week=$week&wday=$wday&hour=$hour&min=$min&lengthmin=$lengthmin&title=" . url_encode ($title) . "&data=" . url_encode ($data) . "&rt=$rt&startyear=$startyear&startweek=$startweek&startwday=$startwday&duration=$duration&alval=$alval&altype=$altype&alchk=$alchk&strike=$strike"; } redraw_print_frameset ($tweek, $tday, $tevent); } else { print Socket "

Redraw: Unknown view \"$view\".\n"; } return; } sub create_users () { my (@users, $user); if (! chdir ($::DIRECTORY)) { return "Can't change into directory $::DIRECTORY: $!

Make sure it exists, and its permissions are as explained in file INSTALL of the Wcal distribution."; } @users = sort (keys (%$::USER_CONFS)); for $user (@users) { my ($desc); $desc = $::USER_CONFS->{$user}->{'long name'}; if (-d $user and -M $user > -M $::CONF_FILE) { system "/bin/rm -rf $user"; } if (! -d $user) { my ($access_file, $access_file_name); if (! mkdir ($user, 0755)) { return "Internal error: can't create user '$user': $!"; } if (! link ('index.cgi', $user . '/index.cgi')) { return "Internal error: can't create hard link 'index.cgi -> $user/index.cgi': $!"; } $access_file_name = $::USER_CONFS->{$user}->{'access file name'}; $access_file = $::USER_CONFS->{$user}->{'access file'}; if ($access_file and $access_file_name) { if (! open (AF, ">$user/$access_file_name")) { return "Internal error: can't create access file $user/$access_file_name: $!"; } print AF "# This file is automatically generated from $::CONF_FILE - do not edit\n"; print AF $access_file; close AF; } } } return ''; } # Removes all cache files. sub purge_cache_all () { my (@files); if (! opendir (DIR, "$::DB_DIR/cache")) { return; } @files = grep { /^w-[^-]+-\d\d\d\d\d\d\.html$/ } readdir (DIR); closedir DIR; for (@files) { unlink "$::DB_DIR/cache/$_" or warn "can't remove $::DB_DIR/cache/$_: $!\n"; } } # Removes cached week views and Date::Manip wrapper caches. # Supposed to be called at first request after midnight. sub purge_cache_newday () { my (@files); my ($now_ref, $foo, $week1, $week2); # # Cached dates. # Other date caches stay valid accross date change. # undef $::now_cache; # # Cached week for this week, or all weeks if the week has changed # $now_ref = get_now (); $week1 = sprintf ("%02d", $now_ref->{'week'}); ($foo, $week2) = get_prev_year_week ($now_ref->{'year'}, $week1); $week2 = sprintf ("%02d", $week2); if (! opendir (DIR, "$::DB_DIR/cache")) { return; } if ($week1 == $week2) { @files = grep { /^w-[^-]+-\d\d\d\d$week1\.html$/ } readdir (DIR); } else { @files = grep { /^w-[^-]+-\d\d\d\d\d\d\.html$/ } readdir (DIR); } closedir DIR; for (@files) { unlink "$::DB_DIR/cache/$_" or warn "can't remove $::DB_DIR/cache/$_: $!\n"; } return; } # Create socket and make it listen sub init_socket () { if (! socket (SSocket, PF_INET, SOCK_STREAM, getprotobyname('tcp')) ) { print STDERR "$0: can't create socket: $!"; exit 1; } if (! setsockopt(SSocket, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) ) { print STDERR "$0: can't set socketopt SO_REUSEADDR: $!"; exit 1; } if (! bind(SSocket, sockaddr_in($::PORT, INADDR_ANY)) ) { print STDERR "$0: can't bind socket to INADDR_ANY: $!"; exit 1; } if (! listen(SSocket, SOMAXCONN) ) { print STDERR "$0: can't make socket listen: $!"; exit 1; } } sub parse_config_line ($) { my ($line) = @_; my ($key, $value); if ($line =~ /^#/ or $line =~ /^\s*$/) { return ''; } if ($line =~ /=/) { ($key, $value) = split (/=/, $_, 2); } else { ($key, $value) = ($_, ''); } $key =~ s/^\s*(.*?)\s*$/$1/; $key = lc $key; $key =~ tr/ \t/ /s; if ($key !~ /^[a-z0-9_ ]+$/) { return "Config file line $. key '$key' has invalid characters"; } $value =~ s/^\s*(.*?)\s*$/$1/; return {'key' => $key, 'value' => $value}; } sub import_settings ($) { my ($s_ref) = @_; $::PASSWORD = $s_ref->{'password'}; $::PORT = $s_ref->{'port'}; $::BASE_URL = $s_ref->{'base url'}; $::IMG_URL = $::BASE_URL . '/images'; $::ORGANIZATION = $s_ref->{'organization'}; $::LONG_NAME = $s_ref->{'long name'}; $::READ_ONLY = $s_ref->{'read only'}; $::DATA_ID = $s_ref->{'data id'}; $::FIRST_DAY = $s_ref->{'first day'}; $::DATE_FORMAT = $s_ref->{'date format'}; $::CLOCK = $s_ref->{'clock'}; $::SCREEN_RESOLUTION = $s_ref->{'screen resolution'}; $::MY_URL = $::BASE_URL . "/" . (defined $::USER ? $::USER.'/index.cgi' : 'index.cgi'); $::MY_URL_XUSER = $::BASE_URL . "/" . (defined $::USER ? 'X_USER_X/index.cgi' : 'index.cgi'); $::REMOTE_LANG = $s_ref->{'remote lang'} || "en"; $::REMOTE_MAIL = $s_ref->{'remote mail'} || "root"; $::REMOTE_CAL = $s_ref->{'remote cal'} || "all"; $::H_BODY = "\n"; return; } # Reads global config data from /etc/wcal.conf sub read_config () { my ($key, $value, $line, $line_ref, %global_conf, %user_confs, $cuser, $conf_ref); my (@current_access_file, $reading_access_file); my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks); my ($valid_line); if (! open (CONF, "<$::CONF_FILE")) { my $str1 = "can't open $::CONF_FILE for reading: $!"; return \$str1; } # Conf file must not be read/writeable by 'other' ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat (CONF); if ($mode & 6) { close CONF; my $str2 = "Configuration file $::CONF_FILE must not have read or write permission for 'other' (do 'chmod o= $::CONF_FILE)'.\n"; return \$str2; } # Empty the settings from the last run %global_conf = (); %user_confs = (); $conf_ref = \%global_conf; $cuser = ''; $reading_access_file = 0; # Set some defaults $global_conf{'host'} = 'localhost'; $global_conf{'port'} = '13134'; $global_conf{'base url'} = '/wcal'; $global_conf{'access file name'} = '.htaccess'; $global_conf{'access file'} = ''; $global_conf{'organization'} = 'My Organization'; $global_conf{'read only'} = 'false'; $global_conf{'first day'} = 'monday'; $global_conf{'date format'} = 1; $global_conf{'clock'} = '24-hour'; $global_conf{'screen resolution'} = '1024x768'; $global_conf{'top left corner'} = ' '; $global_conf{'remote lang'} = 'en'; $global_conf{'remote mail'} = 'root'; $global_conf{'remote cal'} = 'all'; while () { chomp; $line = $_; # If we are reading access file, do special processing if ($reading_access_file) { $line =~ s/^\s*(.*?)\s*$/$1/; if ($line =~ /^end access file$/i) { $conf_ref->{'access file'} = join ("\n", @current_access_file) . "\n"; $reading_access_file = 0; } else { push @current_access_file, $line; } next; } # Else do the normal processing $line_ref = parse_config_line ($line); next if ! $line_ref; # skip comments and empty lines if (! ref $line_ref) { # if return value not empty, and not a reference, it's an error close CONF; return \$line_ref; } $key = $line_ref->{'key'}; $value = $line_ref->{'value'}; # 'user' field starts user definition if ($key eq 'user') { if (! defined $global_conf{'password'}) { close CONF; my $str2 = "Configuration file $::CONF_FILE line $. starts user definition, but the password field hasn't yet occured (password must be given in global section before any user definitions)"; return \$str2; } $cuser = $value; $conf_ref = {}; next; } # 'end user' field ends user definition if ($key eq 'end user') { my ($gkey); # Copy each global conf field into user definition if it isn't given in user definition for $gkey (keys %global_conf) { if (! defined $conf_ref->{$gkey}) { $conf_ref->{$gkey} = $global_conf{$gkey}; } } # Long name = user, if not explicitely given if (! defined $conf_ref->{'long name'}) { $conf_ref->{'long name'} = $cuser; } # Data id = user, if not explicitely given if (! defined $conf_ref->{'data id'}) { $conf_ref->{'data id'} = $cuser; } # Empty 'top left corner' replaced with  , to make browsers happier. if ($conf_ref->{'top left corner'} eq '') { $conf_ref->{'top left corner'} = ' '; } $user_confs{$cuser} = $conf_ref; $cuser = ''; $conf_ref = \%global_conf; next; } # 'access file' starts (default / user) access file definition if ($key eq 'access file') { if ($value) { close CONF; my $str3 = "Configuration file $::CONF_FILE line $. starts access file definition, but has value field"; return \$str3; } @current_access_file = (); $reading_access_file = 1; next; } $valid_line = 0; # Some fields can only occur in global section if ($cuser and ($key eq 'port' or $key eq 'address')) { close CONF; my $str4 = "Configuration file $::CONF_FILE line $. has in user $cuser definition parameter '$key' that can only occur in global section"; return \$str4; } # And some only in user definition if (! $cuser and ($key eq 'long name' or $key eq 'read only')) { close CONF; my $str5 = "Configuration file $::CONF_FILE line $. has in global section parameter '$key' that can only occur in user definition"; return \$str5; } # READ ONLY field can have only values true or false if ($key eq 'read only') { $value = lc $value; if ($value ne 'true' and $value ne 'false') { close CONF; my $str6 = "Configuration file $::CONF_FILE line $. has invalid value for option 'read only'. Allowed values are true and false (default false)."; return \$str6; } $valid_line = 1; } # FIRST DAY can be only monday or sunday elsif ($key eq 'first day') { if ($value ne 'monday' and $value ne 'sunday') { close CONF; my $str7 = "Configuration file $::CONF_FILE line $. has invalid value for option 'first day'. Allowed values are monday and sunday (default monday)."; return \$str7; } $value = lc $value; $valid_line = 1; } # DATE FORMAT must be between 1 and 5 elsif ($key eq 'date format') { if ($value < 1 or $value > 6) { close CONF; my $str8 = "Configuration file $::CONF_FILE line $. has invalid value for option 'date format'. Allowed values are 1 to 6 (default 1)."; return \$str8; } $valid_line = 1; } # PORT must be a integer number elsif ($key eq 'port') { if ($value !~ /^\d+$/ or $value < 1 or $value > 65535) { close CONF; my $str9 = "Configuration file $::CONF_FILE line $. has invalid value for option 'port'. Allowed values are integer numbers between 1 and 65535 (default 13134)."; return \$str9; } $valid_line = 1; } # CLOCK must be 24-hour or 12-hour elsif ($key eq 'clock') { $value = lc $value; if ($value ne '24-hour' and $value ne '12-hour') { close CONF; my $str10 = "Configuration file $::CONF_FILE line $. has invalid value for option 'clock'. Allowed values are '24-hour' and '12-hour' (default 24-hour)."; return \$str10; } $valid_line = 1; } # SCREEN RESOLUTION must be 800x600 or 1024x768 elsif ($key eq 'screen resolution') { $value = lc $value; if ($value ne '800x600' and $value ne '1024x768') { close CONF; my $str11 = "Configuration file $::CONF_FILE line $. has invalid value for option 'screen resolution'. Allowed values are '800x600' and '1024x768' (default 1024x768)."; return \$str11; } $valid_line = 1; } # DATABASE DIRECTORY is deprecated elsif ($key eq 'database directory') { print STDERR "Configuration variable 'database directory' is deprecated and won't be used."; print STDERR "If you have database in a place other than $::DB_DIR, move it there now."; $valid_line = 1; } # OTHERS - no particular syntax required, but must be a valid key elsif ($key eq 'base url' or $key eq 'password' or $key eq 'organization' or $key eq 'access file name' or $key eq 'data id' or $key eq 'long name' or $key eq 'address' or $key eq 'top left corner' or $key eq 'lang' or $key eq 'remote lang' or $key eq 'remote mail' or $key eq 'remote cal' or $key eq 'install dir') { $valid_line = 1; } if (! $valid_line) { close CONF; my $str12 = "Configuration file $::CONF_FILE line $. has unknown option '$key'."; return \$str12; } $conf_ref->{$key} = $value; } close CONF; if ($reading_access_file or $cuser) { my $str13 = "End of configuration file $::CONF_FILE while reading access file or user definition"; return \$str13; } $::GLOBAL_CONF = \%global_conf; $::USER_CONFS = \%user_confs; import_settings ($::GLOBAL_CONF); purge_cache_all (); return 1; } # Read CGI environment and conf option from Socket (sent by the cgi-proxy) sub read_environment () { my ($key, $value, $user); while () { chomp; last if /^$/; my ($key, $value); ($key, $value) = split (/=/, $_, 2); $key =~ tr/\x00-\x1f\x80-\x9f//d; # filter out control characters, $value =~ tr/\x00-\x1f\x80-\x9f//d; # including infamous NUL if ($key eq 'QUERY_STRING') { $::query = decode_url_encoded_data \$value; } elsif ($key eq 'REMOTE_USER') { $::REMOTE_USER = $value; $ENV{REMOTE_USER} = $::REMOTE_USER; } elsif ($key eq 'REMOTE_PASS') { $::REMOTE_PASS = $value; $ENV{REMOTE_PASS} = $::REMOTE_PASS; } elsif ($key eq 'REMOTE_MAIL') { $::REMOTE_MAIL = $value; } elsif ($key eq 'REMOTE_CAL') { $::REMOTE_CAL = $value; } elsif ($key eq 'REMOTE_LANG') { $::REMOTE_LANG = $value; } elsif ($key =~ /^__/) { $key = lc $key; if ($key eq '__password') { # print Socket "

got: '$value', correct is '$::PASSWORD'\n"; if ($value ne $::PASSWORD) { print Socket "

Invalid password\n"; return 0; } } elsif ($key eq '__user') { $::USER = $value; } elsif ($key eq '__gid') { $::GID = $value; } else { print Socket "

Unknown configuration option '$key'\n"; return 0; } } } # print Socket "

$::MY_URL\n"; # Make sure we received all the mandatory options if (! $::USER) { print Socket "

User not sent by cgi-proxy\n"; return 0; } return 1; } sub siginthandler { exit (1); } sub sighuphandler { my ($res); return; # do nothing, this is just a kludge that doesn't work $::GID = 60; $res = read_config (); if (ref $res) { print STDERR "

Re-reading configureation failed: ", $$res, " - configuration not changed.\n"; } else { $res = create_users (); if ($res) { print STDERR "

Error creating new users: $res\n"; } } return; } sub check_and_set_first_day () { my ($gen); $gen = read_general (); if (! ref $gen) { print "error: $gen\n"; exit (1); } if (defined $gen->{'first day'} and $gen->{'first day'} ne $::FIRST_DAY) { print <{'first day'}) { my ($err); $gen->{'first day'} = $::FIRST_DAY; $err = write_general ($gen); if ($err) { print "error: $err\n"; exit (1); } } return; } sub show_links () { print Socket $::H_BODY; my @cals = split(/\n/, $::query->{'cal'}); my $st = ""; if ($::query->{'year'} && $::query->{'week'}) { $st = '&year='.$::query->{'year'}.'&week='.$::query->{'week'}; } print Socket '

'.$::LONG_NAME."

\n"; print Socket "\n"; my $cal; my $i = 1; foreach $cal (@cals) { print Socket '
'.%{$::USER_CONFS->{$cal}}->{'long name'}."\n"; } print Socket "
"; } sub clear_events { my $week = shift; my $year = shift; if ($week) { my $file; opendir(DIR, $::DB_DIR); while ($file = readdir(DIR)) { if ($file =~ /^w\-$::USER\-(\d\d\d\d)(\d\d)\.db$/) { if (($1 < $year) || (($1 == $year) && ($2 <= $week))) { unlink($::DB_DIR."/".$file); } } } closedir(DIR); opendir(DIR, $::DB_DIR."/cache"); while ($file = readdir(DIR)) { if ($file =~ /^w\-$::USER\-(\d\d\d\d)(\d\d)\.html$/) { if (($1 < $year) || (($1 == $year) && ($2 <= $week))) { unlink($::DB_DIR."/cache/".$file); } } } closedir(DIR); } else { system('\rm '.$::DB_DIR.'/*'.$::USER.'*'); system('\rm '.$::DB_DIR.'/cache/*'.$::USER.'*'); } } sub all_events () { opendir(DIR, $::DB_DIR); my @events; my $event; my $evw; my $i; my $key; my $val; my $file; while ($file = readdir(DIR)) { if ($file =~ /^w\-$::USER\-(\d\d\d\d)(\d\d)\.db$/) { $evw = read_events('n', $1, $2); for ($i=0; $i<7; $i++) { while (($key, $val) = each(%{@{$evw}[$i]})) { foreach $event (@{$val}) { $event->{hour} = $key; push @events, $event; } } } } } return \@events; } sub show_purge () { my $str; my $week = $::query->{'week'}; my $year = $::query->{'year'}; print Socket $::H_BODY; print Socket "\n"; print Socket "\n"; print Socket "
"; print Socket __("Transfert Palm Pilot"); print Socket "
\n"; if ($::query->{'purge'}) { clear_events($week, $year); $str = sprintf(__("Agenda %s purgé jusqu'à la semaine %d de l'année %d"), ''.$::LONG_NAME.'', $week, $year); print Socket "

$str

\n"; } elsif ($::query->{'cancel'}) { $str = sprintf(__("Purge de l'agenda %s annulée"), ''.$::LONG_NAME.''); print Socket "

$str

\n"; } else { print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "\n"; print Socket "{'week'}>\n"; print Socket "{'year'}>\n"; my $submit_value = __("Oui"); print Socket "

".sprintf(__("Voulez-vous réellement purger l'agenda %s jusqu'à la semaine %d de l'année %d ?"), $::LONG_NAME, $::query->{'week'}, $::query->{'year'})."\n"; print Socket "

\n"; $submit_value = __("Non"); print Socket "\n"; print Socket "
\n"; } print Socket "
\n"; } sub checkAlarm { my $event = shift; my $cal = shift; my $hour = shift; my $day = shift; my $et = shift; my $week = shift; my $year = shift; my @types = ("", "minutes", "hours" , "days"); # compute start date my $now=&ParseDate("today"); my $begin; my $end; my $alarm; my $strdate; my @format; my @tab; my $chk = 1; my $min = $event->{min}; my $notime; if ($hour == -1) { $hour = 0; $min = 0; $notime = 1; } if ($et eq "w") { $begin = &DateCalc(&ParseDate(sprintf("%04d-w%02d-%d", $event->{startyear}, $event->{startweek}, $event->{startwday}+1)), sprintf("+%dhours +%dminutes", $hour, $min)); $alarm = &DateCalc($begin, sprintf("-%d%s", $event->{alval}, $types[$event->{altype}])); if ($alarm gt $now) { return 0; } } elsif ($et eq "rw") { $alarm = &DateCalc($now, sprintf("+%d%s", $event->{alval}, $types[$event->{altype}])); @format = ("%w"); my $wday = &UnixDate($alarm, @format); $wday = 1 + $event->{startwday} - $wday; if ($wday > 0) { return 0; } elsif ($wday < 0) { $begin = &DateCalc($alarm, $wday."days"); } else { $begin = $alarm; } $begin = substr($begin,0,8).sprintf("%02d:%02d:00", $hour, $min); if ($begin gt $alarm || ($event->{alchk} && $begin le $event->{alchk})) { return 0; } $chk = $begin; } elsif ($et eq "rm") { $alarm = &DateCalc($now, sprintf("+%d%s", $event->{alval}, $types[$event->{altype}])); @format = ("%d"); my $mday = &UnixDate($alarm, @format); $mday = $day - $mday; if ($mday > 0) { return 0; } elsif ($mday < 0) { $begin = &DateCalc($alarm, $mday."days"); } else { $begin = $alarm; } $begin = substr($begin,0,8).sprintf("%02d:%02d:00", $hour, $min); if ($begin gt $alarm || ($event->{alchk} && $begin le $event->{alchk})) { return 0; } $chk = $begin; } my $email = "root"; my $head; my $body; $email = $::REMOTE_MAIL; $head = sprintf(__("Agenda %s"), %{$::USER_CONFS->{$cal}}->{'long name'}); if ($notime) { @format = ("%d","%m","%y"); @tab = &UnixDate($begin, @format); $strdate = sprintf("%02d/%02d/%02d", @tab); } else { @format = ("%d","%m","%y","%H","%M"); @tab = &UnixDate($begin, @format); $strdate = sprintf("%02d/%02d/%02d %02d:%02d", @tab); $end = &DateCalc($begin, sprintf("+%dminutes", $event->{lengthmin})); @format = ("%H","%M"); @tab = &UnixDate($end, @format); $strdate .= sprintf(" - %02d:%02d", @tab); } my $data = $event->{data}; $data =~ s/
/\n\t /mg; $body = $head."\n"; $head .= " : ".$event->{title}."\n"; $body .= "************************************************************\n"; $body .= __("Date")."\t: ".$strdate."\n"; $body .= __("Titre")."\t: ".$event->{title}."\n"; if ($data) { $body .= __("Note")."\t: ".$data."\n"; } $body .= "************************************************************\n"; system('mail -s "'.$head.'" '.$email." <); $/ = $old_slash; close F; shift @$refs; $day = 0; foreach $devents (@$refs) { while (($hour,$events) = each (%$devents)) { foreach $event (@$events) { if ($event->{alval} && !$event->{strike} && (!$event->{alchk} || $event->{alchk} ne "1")) { if ($chk = checkAlarm($event, $cal, $hour, $day, $et, $week, $year)) { $::USER = $cal; $::DATA_ID = $cal; print Socket "$event->{'title'} ($event->{'id'}) checked\n"; $err = remove_events( $event->{'rt'}, $event->{'startyear'}, $event->{'startweek'}, $event->{'startwday'}, $event->{'duration'}, $hour, $event->{'id'}); if (!$err) { $err = add_events( $event->{'rt'}, $event->{'startyear'}, $event->{'startweek'}, $event->{'startwday'}, $event->{'duration'}, $hour, $event->{'id'}, $event->{'min'}, $event->{'lengthmin'}, $event->{'title'}, $event->{'data'}, $event->{'alval'}, $event->{'altype'}, $chk); } } } } } $day++; } } } } closedir(DIR); } sub list_users () { my (@users, $user); my $str = sprintf(__("Agendas %s"), $::ORGANIZATION); print Socket "$str\n"; print Socket $::H_BODY; if (! chdir ($::DIRECTORY)) { print Socket "

Can't change into directory $::DIRECTORY: $!"; print Socket "

Make sure it exists, and its permissions are as explained in file INSTALL of the Wcal distribution."; exit (1); } print Socket "

$str

"; print Socket sprintf(__("Cliquez sur un calendrier ou sélectionnez les calendriers pour la %s"), ''.__("Fusion").""); print Socket '
'."\n"; print Socket "

    \n"; @users = sort (keys (%$::USER_CONFS)); for $user (@users) { my ($desc); $desc = $::USER_CONFS->{$user}->{'long name'}; print Socket ' '; print Socket "$desc
    \n"; } print Socket "
\n"; print Socket '
'."\n"; print Socket "\n"; return; } sub main () { my ($config_result, $last_run, $last_conf, $res); $SIG{HUP} = $SIG{PIPE} = 'IGNORE'; $SIG{ALRM} = \&purge_cache_all; $ENV{'PATH'} = '/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin'; # To pass taint checks # # Make sure the $::DIRECTORY variable is set # if ($::DIRECTORY =~ /^_X_DIRECTOR/) { print "You haven't set the variable $::DIRECTORY at top of wcald.\n"; print "It is automatically set by Makefile. If you're installing manually,\n"; print "set the variable the name directory you installed wcald to.\n"; exit 1; } # # Refuse to run as root # if ($> == 0) { die "Won't run as root.\n"; } # # Check some file permissions # if (! -d $::DB_DIR or ! -w $::DB_DIR or (sprintf "%04o", ((stat ($::DB_DIR))[2]) & 07777) ne '0700') { die "$::DB_DIR must exist, be writable and have mode 0700.\n"; } if (! -d "$::DB_DIR/cache") { mkdir ("$::DB_DIR/cache", 0700) or die "mkdir (\"$::DB_DIR/cache\", 0700): $!\n"; } if (! -d $::DIRECTORY or ! -w $::DIRECTORY or (sprintf "%04o", ((stat ($::DIRECTORY))[2]) & 07777) ne '0750') { die "$::DIRECTORY must exist, be writable and have mode 0750.\n"; } # # Read in wcal.msg # open(MSG, $::MSG_FILE) or die "Can't open $::MSG_FILE for reading: $!"; my $old_slash = $/; undef $/; $::msgs = eval (); $/ = $old_slash; close(MSG); # # Read configuration and create users # $config_result = read_config (); if (ref $config_result) { die "$0: error: ", $$config_result, "\n"; } $res = create_users (); if ($res) { die "$0: error creating users: $res\n"; } # # Make sure current database (if one exists) uses same 'first day' # parameter as we're currently using. # check_and_set_first_day (); # # Set the date constants # if ($::FIRST_DAY eq 'monday') { @::weekdays = qw (Lundi Mardi Mercredi Jeudi Vendredi Samedi Dimanche); @::weekdays_short = qw (lun mar mer jeu ven sam dim); @::weekdays2 = qw (Monday Tuesday Wednesday Thursday Friday Saturday Sunday); &Date_Init ('FirstDay=1'); } else { @::weekdays = qw (Dimanche Lundi Mardi Mercredi Jeudi Vendredi Samedi); @::weekdays_short = qw (dim lun mar mer jeu ven sam); @::weekdays2 = qw (Sunday Monday Tuesday Wednesday Thursday Friday Saturday); &Date_Init ('FirstDay=7'); } @::months = qw (Erreur Janvier Février Mars Avril Mai Juin Juillet Août Septembre Octobre Novembre Décembre); init_socket (); $last_run = (localtime(time))[7]; $last_conf = 0; while (1) { my ($query_type, $pid, $paddr, $cgi, %user, $now_run, $now_conf); $SIG{'INT'} = $SIG{'TERM'} = \&siginthandler; $SIG{'HUP'} = \&sighuphandler; $paddr = accept (Socket, SSocket); $SIG{'INT'} = $SIG{'TERM'} = $SIG{'HUP'} = 'IGNORE'; # # Purge cache when day changes # $now_run = (localtime(time))[7]; if ($now_run != $last_run) { $last_run = $now_run; purge_cache_newday (); } # # Start outputing HTML # print Socket $::HTTP_HEADER; print Socket "\n"; # # Read CGI environment and the config options that cgi-proxy passes to us # Includes QUERY_STRING (decoded into $::query), # __password (checked) and __user (stored in $::USER) # if (! read_environment ()) { next; } # # Re-read config if it has changed # $now_conf = (stat($::CONF_FILE))[9]; if ($now_conf != $last_conf) { $last_conf = $now_conf; $config_result = read_config (); if (ref $config_result) { while () { chomp; last if /^$/; }; # Read environment to make cgi-proxy happy print Socket $::H_BODY; print Socket "

Configuration has changed.

"; print Socket "

Re-reading configureation failed: ", $$config_result, " - configuration not changed.\n"; print Socket "

Click me to go to the main view\n"; print Socket "\n"; next; } else { $res = create_users (); if ($res) { print Socket $::H_BODY; print Socket "

Configuration has changed.

"; print Socket "

Error creating new users: $res\n"; print Socket "

Click me to go to the main view\n"; print Socket "\n"; next; } # fall through: just serve the request } } # show a list of users if (!$::query->{'cal'} && $::USER eq $::PATH_BASENAME) { list_users (); next; } # # Dispatch the operation # # Make sure the users exists if ($::USER_CONFS->{$::USER}) { import_settings ($::USER_CONFS->{$::USER}); $::DATA_IDS = 0; } else # fusion { $::READ_ONLY = 'true'; $::DATA_ID = 0; $::DATA_IDS = $::query->{'cal'}; $::LONG_NAME = __('Fusion'); $::MY_URL = $::BASE_URL.'/fusion.cgi'; $::MY_URL_XUSER = $::BASE_URL.'/fusion.cgi'; } $::query->{'u'} = $::USER; $query_type = $::query->{'t'} || ''; if ($query_type eq 'redraw' or $query_type eq '') { redraw (); } elsif ($query_type eq 'week') { show_week (); } elsif ($query_type eq 'day') { show_day (); } elsif ($query_type eq 'event') { show_event (); } elsif ($query_type eq 'copy_event') { copy_event (); } elsif ($query_type eq 'add_edit') { add_edit_event_ask () if check_write_access (); } elsif ($query_type eq 'add_edit_confirm') { add_edit_event_confirm () if check_write_access (); } elsif ($query_type eq 'remove') { remove_event_confirm () if check_write_access (); } elsif ($query_type eq 'xxx_event_error') { xxx_event_error (); } elsif ($query_type eq 'event_list') { show_event_list (); } elsif ($query_type eq 'views') { show_other_views (); } elsif ($query_type eq 'links') { show_links (); } elsif ($query_type eq 'purge') { show_purge (); } elsif ($query_type eq 'checkalarm') { check_alarm (); } else { print Socket "

Unknown command '$query_type'.

\n"; } undef $::query; } continue { print Socket "\n"; close Socket; } # not reached } main();