1     #!/usr/bin/perl -Tw
2     use strict;
3     $|++;
4
5     use CGI qw(:all);
6     use HTML::CalendarMonthSimple;
7     use Cache::FileCache;
8     use URI::Find;
9
10    my $PLANFILE = "/home/merlyn/.plan";
11
12    my ($formonth, $foryear);
13    {
14      my @NOW = localtime;
15      $formonth = param('month');
16      $formonth = $NOW[4]+1  unless defined 
         $formonth and $formonth !~ /\D/ and
17        $formonth >= 1 and $formonth <= 12;
18      $foryear = param('year');
19      $foryear = $NOW[5]+1900 unless defined 
         $foryear and $foryear !~ /\D/ and
20        $foryear >= 2001 and $foryear <= 2005;
21    }
22
23    my $cache = Cache::FileCache->new
        ({namespace => 'whereami',
24                                       username => 'nobody'});
25
26    my %events;
27
28    my @nowidentity = (stat($PLANFILE))
        [0,1,9];
29
30    if (my $cached = $cache->get('data')) {
31      my ($events, @identity) = @$cached;
32      if ("@nowidentity" eq "@identity") {
33        ## we have a valid cache
34        %events = %$events;
35      }
36    }
37
38    unless (%events) {
39      ## no cache, so compute from scratch
40      require Date::Manip; local $ENV{PATH} = 
          "";
41      Date::Manip->import;
42
43      @ARGV = $PLANFILE;
44      while (<>) {
45        next unless
46          /^(\d+)\s+to\s+(\d+)(\s+\S+\s+\d+):\s+(.*)/ or
47            /^(\d+\s+\S+)\s+to\s+(\d+\s+\S+)(\s+\d+):\s+(.*)/ or
48              /^(\d+\s+\S+\s+\d+)\s+to\s+(\d+\s+\S+\s+\d+)():\s+(.*)/;
49        my ($start, $end, $where) = 
    	    ("$1$3","$2$3", $4);
50        $end = DateCalc($end, "+ 1 day");
51        for (ParseRecur("every day", undef, 
           $start, $end)) {
52          my ($y, $m, $d) = UnixDate
            ($_, "%Y", "%m", "%d");
53          push @{$events{0+$y}{0+$m}}, [$d, 
            $where];
54        }
55      }
56      $cache->set('data', [\%events, 
          @nowidentity]);
57    }
58
59    my $cal = HTML::CalendarMonthSimple->
        new(year => $foryear, month => 
          $formonth);
60    $cal->width('100%');
61    $cal->bgcolor('white');
62    $cal->todaycolor('grey');
63    $cal->bordercolor('black');
64    $cal->contentcolor('black');
65    $cal->todaycontentcolor('black');
66    $cal->headercolor('#ccffcc');
67
68    {
69      my $myself = url(-relative => 1);
70      my $previous = sprintf 
          "%s?year=%d&month=%d", $myself,
71        $formonth == 1 ? ($foryear - 1, 12) : 
     	  ($foryear, $formonth - 1);
72      my $next = sprintf 
          "%s?year=%d&month=%d", $myself,
73        $formonth == 12 ? ($foryear + 1, 1) : 
          ($foryear, $formonth + 1);
74      $cal->header(table({width => '100%', 
          border => 0,
75                          cellspacing => 0, cellpadding => 2},
76                         Tr(td({align => 'left', width => '1*'},
77                               a({href => $previous}, "previous")),
78                            td({align => 'center', width => '1*'},
79                               b($cal->monthname, $cal->year)),
80                            td({align => 'right', width => '1*'},
81                               a({href => $next}, "next")))));
82    }
83
84    print header, start_html("My Calendar for 
        ".$cal->monthname." ".$cal->year);
85
86    for (@{$events{0+$foryear}{0+$formonth}}) 
        {
87      my ($d, $where) = @$_;
88      for ($where) {
89        find_uris($_, sub {my ($uri, $text) = 
           @_;
90                           qq{\1<a href="\1$uri\1" 			target=_blank>\1$text\1</a>\1} });
91        s/\G(.*?)(?:\001(.*?)\001)?/escapeHTML($1).
          (defined $2 ? $2 : "")/eig;
92      }
93      $cal->addcontent(0+$d, $where);
94    }
95
96    { local $^W = 0; print $cal->as_HTML; }
97
98    print end_html;