#!/usr/bin/perl -w
# Debian Packages: libwww-perl,libhttp-dav-perl
# Include all recurring events no matter what 'pre' is set to.

use strict;
use Getopt::Long;
use HTTP::DAV;

# Set this to 1 to get debugging output
use constant DEBUG => 1;

use constant USAGEMSG =>  <<USAGE;
Usage: perl getics.pl --user <username> --pwd <password> [ --cal <calname> --out <filename> --pre <#> ]
        --user  <username>   Login name for calendar account (required)
        --pwd   <password>   Password for account (required)
        --cal   <calname>    Name of calendar - default "personal"
        --out   <filename>   New calendar file - default "calendar.ics"
        --pre   <# of days>  Ignore calendar entries older than '# of days' - default 7
                             Set to '99' to include all events.
USAGE

my ($user,$pwd,$incl,$tz,$item,$startdate,$rr);
my $cal = "personal";
my $tmpfile = "/var/tmp/tempcal.ics";
my $outfile = "calendar.ics";
my $pre = 7;
my $version = 0;
my $prodid = 0;
my $getall = 0;
my $count = 0;
my $tcount = 0;
my $line = 0;
my @event;

die USAGEMSG unless GetOptions('user=s' => \$user,
                               'pwd=s'  => \$pwd,
                               'cal:s'  => \$cal,
                               'out:s'  => \$outfile,
                               'pre:i'  => \$pre );

## Check we have all the required values...
die USAGEMSG unless ($user && $pwd) ;

print "Username: $user   Password: $pwd    Calendar: $cal\n" if DEBUG;

## Set our DAV URL to use
my $davurl = "http://webmail.company.ca/SOGo/dav/$user/Calendar/$cal/";

## Determine range of events to output
if ($pre == 99) {
  $getall = 1;
  print "We want all events\n" if DEBUG;
} else {
  my ($sec,$min,$hour,$day,$month,$year,@rest) = localtime(time - ($pre * 86400));
  $startdate = sprintf "%.4d%.2d%.2d", $year+1900, $month+1, $day;
  print "Starting date we want: $startdate\n" if DEBUG;
}

my $dav = HTTP::DAV->new();

## Open the DAV collection
$dav->credentials( -user=>$user,
                   -pass=>$pwd,
                   -url =>$davurl,
                   -realm=>"SOGo" );
$dav->open( -url=>"$davurl" )
      or die("Couldn't open $davurl: " .$dav->message . "\n");

## Open new calendar file for writing
open NEWCAL, ">$outfile"
      or die "Cannot create calendar file: $!\n";
print NEWCAL "BEGIN:VCALENDAR\n";

## Loop over the DAV collection getting each of the ICS files
if ( my $r=$dav->propfind( -url=>"$davurl", -depth=>1) ) {
  if ( $r->is_collection ) {
    my $reslist = $r->get_resourcelist();
    unless (defined($reslist)) {
      print "No events for $user!\n" if DEBUG;
      print NEWCAL "END:VCALENDAR\r\n";
      close NEWCAL;
      exit();
    }
    foreach my $url ($reslist->get_urls()) {
      $tcount++;
      print "\n" . $url if DEBUG;
      $dav->get( -url=>$url, -to=>$tmpfile)
          or die "Cannot download ics file $url\n";

      ## Read the downloaded file and save into new file
      ## Remove extra/duplicate attributes
      open ICS, "$tmpfile" or die "Cannot open downloaded file: $!\n";
      $incl = 1;
      $tz = 0;
      @event = ();
      $item = 0;
      $rr = 0;
      $line = 0;
      while (<ICS>) {
        chomp;
        s/\r$//;
        $line++;
        if (/^VERSION/) {
          if ($version==0) {
            print NEWCAL "$_\r\n";
            $version = 1;
          }
          next;
        }
        if (/^PRODID/) {
          if ($prodid==0) {
            print NEWCAL "$_\r\n";
            $prodid = 1;
          }
          next;
        }
        if (/VCALENDAR/) {
          next;
        }
        ## Not geeting all records so we need to see if this record should be included
        if ($getall == 0) {
          ## Test for timezone record
          if (/^BEGIN:VTIMEZONE/) {
            $tz = 1;
          }
          if (/^END:VTIMEZONE/) {
            $tz = 0;
          }
          ## Include all recurring events
          if (/^RRULE/ && ! $tz) {
            $rr = 1;
            $incl = 1;
          }
          ## Test DTEND if not a TimeZone record
          if (/^DTEND/ && ! ($tz || $rr) ) {
            my $tmpdate = substr($_, index($_,":") + 1, 8);
            print "\nDate: $tmpdate\n" if DEBUG;
            if ($tmpdate < $startdate) {
              $incl = 0;
            }
          }
        }
        $event[$item]=$_;
        $item++;
      }
      print "Number of lines: $line\n" if DEBUG;
      ## Output the event if it is within the desired date range
      if ($incl == 1) {
        foreach (@event) {
          print NEWCAL "$_\r\n";
        }
        $count++;
        print "ICS file included. Record: $count\n" if DEBUG;
      } else {
        print "ICS file not included.\n" if DEBUG;
      }
      close ICS;
    }
  }
}
## Print the footer...
print "\n" if DEBUG;
print NEWCAL "END:VCALENDAR\r\n";
print "Total URLs: $tcount    Records output: $count.\n" if DEBUG;
close NEWCAL;
