Tie-iCal-0.15000755000000000000 011635731512 13361 5ustar00unknownunknown000000000000Tie-iCal-0.15/Build.PL000444000000000000 43611635724214 14776 0ustar00unknownunknown000000000000use Module::Build; my $build = Module::Build->new( module_name => 'Tie::iCal', license => 'perl', requires => { 'Tie::File' => '0.97', }, dist_author => 'Blair Sutton ', dist_abstract => 'Tie iCal files to Perl hashes', ); $build->create_build_script;Tie-iCal-0.15/CHANGES000444000000000000 164511635730575 14527 0ustar00unknownunknown000000000000CHANGES 0.14 -> 0.15 added NEXTKEY performance patch by BenRifkah Bergsten-Buret. added bug fix by Krishna Sethuraman. 0.13 -> 0.14 some optimisations, i.e. substr instead of m// "NAME:" becomes "NAME => ''" added outlook sync sample 0.12 -> 0.13 corrected unfold behaviour with "\n" character sequences. corrected property extraction with "\n" character sequences. added more documentation. 0.11 -> 0.12 fixed typo in Makefile.PL ASTRACT. fixed exists reset key interator bug in seekUid. added uniquify.pl example. added more documentation. 0.10 -> 0.11 added modified parse_line to ignore single quotes. remove dependency on Text::ParseWords. added b_tie.t test. fixed UID bug on STORE method. fixed typo in subcomponent creation. added c_storefetch.t test. fold lines over 75 characters. 0.09 -> 0.10 support multiple content lines with/without params. FETCH, EXISTS, DELETE all use seekUid.Tie-iCal-0.15/Makefile.PL000444000000000000 100011635724214 15460 0ustar00unknownunknown000000000000use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'Tie::iCal', 'VERSION_FROM' => 'lib/Tie/iCal.pm', 'PM' => { 'lib/Tie/iCal.pm' => '$(INST_LIBDIR)/iCal.pm', }, 'PL_FILES' => {}, 'PREREQ_PM' => { 'Tie::File' => '0.97', }, ($] ge '5.005') ? ( 'AUTHOR' => 'Blair Sutton (bsdz@cpan.org)', 'ABSTRACT' => 'Tie iCal files to Perl hashes', ) : (), ); Tie-iCal-0.15/MANIFEST000444000000000000 41411635731406 14630 0ustar00unknownunknown000000000000Makefile.PL Build.PL MANIFEST This list of files META.yml README t/a_use.t t/b_tie.t t/c_storefetch.t t/d_keeptidy.t samples/demo.pl samples/dump.pl samples/demo.ics samples/uniquify.pl samples/outlooksync.pl TODO CHANGES lib/Tie/iCal.pm META.json Tie-iCal-0.15/META.json000444000000000000 164311635731511 15142 0ustar00unknownunknown000000000000{ "abstract" : "Tie iCal files to Perl hashes", "author" : [ "Blair Sutton " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.38, CPAN::Meta::Converter version 2.112150", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Tie-iCal", "prereqs" : { "configure" : { "requires" : { "Module::Build" : "0.38" } }, "runtime" : { "requires" : { "Tie::File" : "0.97" } } }, "provides" : { "Tie::iCal" : { "file" : "lib/Tie/iCal.pm", "version" : "0.15" } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ] }, "version" : "0.15" } Tie-iCal-0.15/META.yml000444000000000000 105111635731511 14763 0ustar00unknownunknown000000000000--- abstract: 'Tie iCal files to Perl hashes' author: - 'Blair Sutton ' build_requires: {} configure_requires: Module::Build: 0.38 dynamic_config: 1 generated_by: 'Module::Build version 0.38, CPAN::Meta::Converter version 2.112150' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Tie-iCal provides: Tie::iCal: file: lib/Tie/iCal.pm version: 0.15 requires: Tie::File: 0.97 resources: license: http://dev.perl.org/licenses/ version: 0.15 Tie-iCal-0.15/README000444000000000000 106211635724214 14376 0ustar00unknownunknown000000000000Tie::iCal ========= Copyright (c) 2006 Blair Sutton. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. INSTALLATION To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module requires these other modules and libraries: Tie::File This should come bundled with the latest version of Perl. INSTRUCTIONS Please read the perldoc. AUTHOR Blair Sutton (bsdz@cpan.org) Tie-iCal-0.15/TODO000444000000000000 13611635724214 14167 0ustar00unknownunknown000000000000To Do ===== delete empty VCALENDAR blocks. add recurrence to outlooksync.pl more examples.Tie-iCal-0.15/lib000755000000000000 011635731512 14127 5ustar00unknownunknown000000000000Tie-iCal-0.15/lib/Tie000755000000000000 011635731512 14650 5ustar00unknownunknown000000000000Tie-iCal-0.15/lib/Tie/iCal.pm000444000000000000 3776211635730721 16253 0ustar00unknownunknown000000000000package Tie::iCal; use strict; require Exporter; our $VERSION = 0.15; our @ISA = qw(Exporter); use Tie::File; =head1 NAME Tie::iCal - Tie iCal files to Perl hashes. =head1 VERSION This document describes version 0.14 released 1st September 2006. =head1 SYNOPSIS use Tie::iCal; tie %my_events, 'Tie::iCal', "mycalendar.ics" or die "Failed to tie file!\n"; tie %your_events, 'Tie::iCal', "yourcalendar.ics" or die "Failed to tie file!\n"; $my_events{"A-NEW-UNIQUE-ID"} = [ 'VEVENT', { 'SUMMARY' => 'Bastille Day Party', 'DTSTAMP' => '19970714T170000Z', 'DTEND' => '19970715T035959Z', } ]; tie %our_events, 'Tie::iCal', "ourcalendar.ics" or die "Failed to tie file!\n"; # assuming %my_events and %your_events # have no common keys (unless that's your intention) # while (my($uid,$event) = each(%my_events)) { $our_events{$uid} = $event; } while (my($uid,$event) = each(%your_events)) { $our_events{$uid} = $event; } untie %our_events; untie %your_events; untie %my_events; =head1 DEPENDENCIES Tie::File =head1 DESCRIPTION Tie::iCal represents an RFC2445 iCalendar file as a Perl hash. Each key in the hash represents an iCalendar component like VEVENT, VTODO or VJOURNAL. Each component in the file must have a unique UID property as specified in the RFC 2445. A file containing non-unique UIDs can be converted to have only unique UIDs (see samples/uniquify.pl). The module makes very little effort in understanding what each iCalendar property means and concentrates on the format of the iCalendar file only. =head1 FILE LOCKING The Tie::iCal object returned by tie can also be used to access the underlying Tie::File object. This is accessable via the 'A' class variable. This may be useful for file locking. my $ical = tie %events, 'Tie::iCal', "mycalendar.ics"; $ical->{A}->flock; =head1 DATES The iCalendar specification uses a special format for dates. This module makes no effort in trying to interpret dates in this format. You should look at the Date::ICal module that can convert between Unix epoch dates and iCalendar date strings. =cut sub TIEHASH { my ($p, $f, %O) = @_; tie my @a, 'Tie::File', $f, recsep => "\r\n" or die "failed to open ical file\n"; $O{A} = \@a; # file array $O{i} = 0; # current file index for FIRSTKEY and NEXTKEY $O{C} = (); # uid to index cache bless \%O => $p; } sub FETCH { my $self = shift; my $uid = shift; my $index = $self->seekUid($uid); return defined $index ? $self->toHash($index) : undef; } sub EXISTS { my $self = shift; my $uid = shift; my $index = $self->seekUid($uid); return defined $index ? 1 : 0; } sub FIRSTKEY { my $self = shift; $self->{i} = 0; for my $line (@{$self->{A}}) { if (substr($line, 0, 3) eq 'UID') { if ($self->unfold($self->{i}) =~ /^UID.*:(.*)$/) { $self->{C}->{$1} = $self->{i}; # cache in any case return $1; } else { warn("FIRSTKEY: discovered illegal UID property format, should be like UID;...:..., ignoring for now\n"); } } $self->{i}++; } } sub NEXTKEY { my $self = shift; # start search one line after the current point my $start_idx = ++$self->{i}; for my $line (@{$self->{A}}[$start_idx .. (@{$self->{A}} - 1)]) { if ($line =~ m/^UID/) { if ($self->unfold($self->{i}) =~ /^UID.*:(.*)$/) { $self->{C}->{$1} = $self->{i}; # cache in any case return $1; } else { warn("NEXTKEY: discovered illegal UID property format, should be like UID;...:..., ignoring for now\n"); } } $self->{i}++; } return undef; } sub SCALAR { my $self = shift; my $count = 0; for my $line (@{$self->{A}}) { $count++ if substr($line, 0, 3) eq 'UID'; } return $count; } sub ceil { return int($_[0]) + (int($_[0]) != $_[0]); } sub fold { my $MAXLENGTH = 75; my @A; foreach my $string (@_) { my @B = unpack("A$MAXLENGTH" x (&ceil(length($string)/$MAXLENGTH)), $string); push @A, $B[0], map { ' '.$_ } @B[1..$#B]; } return @A; } sub STORE { my $self = shift; my $uid = shift; my $c = shift; die "event must be array!\n" if ref $c ne 'ARRAY'; $self->DELETE($uid); push @{$self->{A}}, fold($self->toiCal($uid, $c)); } sub DELETE { my $self = shift; my $uid = shift; my $index = $self->seekUid($uid); return defined $index ? $self->removeComponent($index) : 0; } sub CLEAR { my $self = shift; @{$self->{A}} = (); } sub DESTROY { my $self = shift; untie $self->{A}; } sub debug { my $self = shift; print(STDERR shift, "\n") if $self->{debug}; } sub unfold { my $self = shift; my $index = shift; my $result = ${$self->{A}}[$index]; my $i = 1; until (${$self->{A}}[$index + $i] !~ /^ (.*)$/s) { $result .= $1; $i++; } $self->debug("unfolded index $index to $result"); return $result; } sub seekUid { my $self = shift; my $uid = shift; my $index; # check cache # if (exists $self->{C}->{$uid}) { $self->debug("found cached index for $uid, checking.."); $index = $self->{C}->{$uid}; if ($self->unfold($index) =~ /^UID.*:(.*)$/) { if ($1 eq $uid) { $self->debug("found key $uid in cache"); return $index; } else { $self->debug("could not find key $uid in cache, deleting"); delete $self->{C}->{$uid}; } } else { warn("seekUid: discovered illegal UID property format, should be like UID;...:..., ignoring for now\n"); } } # not in cache then lets search the file # $index = 0; for my $line (@{$self->{A}}) { if (substr($line, 0, 3) eq 'UID') { if ($self->unfold($index) =~ /^UID.*:(.*)$/) { $self->{C}->{$1} = $index; # cache in any case if ($1 eq $uid) { $self->debug("found key $uid"); return $index; } } else { warn("discovered illegal UID property format, should be like UID;...:..., ignoring for now\n"); } } $index++; } # doesn't exist! # return undef; } sub removeComponent { my $self = shift; my $index = shift; my $i; $i = 0; $i++ until ${$self->{A}}[$index - $i] =~ /^BEGIN:(\w+)$/; my $si = $index - $i; my $component = $1; $i = 0; $i++ until ${$self->{A}}[$index + $i] =~ /^END:$component/; my $fi = $index + $i; $self->debug("component $component found between [$si, $fi]"); splice @{$self->{A}}, $si, $fi - $si + 1; } =head1 How Tie::iCal interprets iCal files Tie::iCal interprets files by mapping iCal components into Perl hash keys and iCal content lines into various Perl arrays and hashes. =head2 Components An iCal component such as VEVENT, VTODO or VJOURNAL maps to a hash key:- BEGIN:VEVENT UID:a_unique_uid NAME1:VALUE1 .. END:VEVENT corresponds to $events{'a_unique_uid'} = ['VEVENT', {'NAME1' => 'VALUE1'}] =head2 Subcomponents An iCal subcomponent such as VALARM maps to a list of hash keys:- BEGIN:VALARM TRIGGER;VALUE=DURATION:-PT1S TRIGGER;VALUE=DURATION:-PT1S END:VALARM BEGIN:VALARM X-TIE-ICAL;VALUE=ANOTHER:HERE X-TIE-ICAL:HERE2 X-TIE-ICAL-NAME:HERE2 END:VALARM corresponds to 'VALARM' => [ { 'TRIGGER' => [ [{'VALUE' => 'DURATION'},'-PT1S'], [{'VALUE' => 'DURATION'},'-PT1S'] ] }, { 'X-TIE-ICAL' => [ [{'VALUE' => 'ANOTHER'},'HERE'], ['HERE2'] ], 'X-TIE-ICAL-NAME' => 'HERE2' } ] To see how individual content lines are formed see below. =head2 Content Lines Once unfolded, a content line may look like:- NAME;PARAM1=PVAL1;PARAM2=PVAL2;...:VALUE1,VALUE2,... having an equivalent perl data structure like: - 'NAME' => [{'PARAM1'=>'PVAL1', 'PARAM2'=>'PVAL2', ..}, 'VALUE1', 'VALUE2', ..] or NAME:VALUE1,VALUE2,... having an equivalent perl data structure like: - 'NAME' => ['VALUE1', 'VALUE2', ..] or NAME:VALUE having an equivalent perl data structure like: - 'NAME' => 'VALUE' An blank value is mapped from NAME: to 'NAME' => '' Multiple contentlines with same name, i.e. FREEBUSY, ATTENDEE:- NAME;PARAM10=PVAL10;PARAM20=PVAL20;...:VALUE10,VALUE20,... NAME;PARAM11=PVAL11;PARAM21=PVAL21;...:VALUE11,VALUE21,... ... having an equivalent perl data structure like: - 'NAME' => [ [{'PARAM10'=>'PVAL10', 'PARAM20'=>'PVAL20', ..}, 'VALUE10', 'VALUE20', ..], [{'PARAM11'=>'PVAL11', 'PARAM21'=>'PVAL21', ..}, 'VALUE11', 'VALUE21', ..], ... ] or NAME:VALUE10,VALUE20,... NAME:VALUE11,VALUE21,... ... having an equivalent perl data structure like: - 'NAME' => [ ['VALUE10', 'VALUE20', ..], ['VALUE11', 'VALUE21', ..], ... ] or in a mixed form, i.e. NAME:VALUE10,VALUE20,... NAME;PARAM11=PVAL11;PARAM21=PVAL21:VALUE11,VALUE21,... NAME:VALUE12,VALUE22,... ... having an equivalent perl data structure like: - 'NAME' => [ ['VALUE10', 'VALUE20', ..], [{'PARAM11'=>'PVAL11', 'PARAM21'=>'PVAL21', ..}, 'VALUE11', 'VALUE21', ..], ['VALUE12', 'VALUE22', ..], ... ] =cut sub toiCal { my $self = shift; my $uid = shift; my $c = shift; my $excludeComponent = shift; my @lines; my ($component, $e) = $excludeComponent ? (undef, $c) : @$c; push @lines, "BEGIN:VCALENDAR", "VERSION:2.0", "PRODID:-//Numen Inest/NONSGML Tie::iCal $VERSION//EN", "BEGIN:$component", "UID:$uid" if ! $excludeComponent; foreach my $name (keys %$e) { if ($name eq 'RRULE') { if (ref($$e{$name}) ne 'HASH') { warn "RRULE property should be expressed as a hash, ignoring..\n"; } else { my @rrule; foreach my $k (keys %{$$e{$name}}) { push @rrule, ref(${$$e{$name}}{$k}) eq 'ARRAY' ? "$k=".join(',', @{${$$e{$name}}{$k}}) : "$k=".${$$e{$name}}{$k}; } push @lines, "$name:".join(';',@rrule); } } elsif (ref(\$$e{$name}) eq 'SCALAR') { push @lines, "$name:$$e{$name}"; } elsif (ref($$e{$name}) eq 'ARRAY') { if (@{$$e{$name}} && !grep({ref($_) ne 'HASH'} @{$$e{$name}})) { # strict list of hashes => we have a subcomponent push @lines, "BEGIN:$name"; foreach my $sc (@{$$e{$name}}) { push @lines, $self->toiCal(undef, $sc, 1); } push @lines, "END:$name"; } elsif (@{$$e{$name}} && !grep({ref($_) ne 'ARRAY'} @{$$e{$name}})) { # strict list of arrays => we have several content lines foreach my $cl (@{$$e{$name}}) { if (ref(${$cl}[0]) eq 'HASH') { # we have params my ($params, @values) = @{$cl}; push @lines, "$name;".join(";", map { "$_=$$params{$_}" } keys(%$params)).":".join(',',@values); } else { # we only have values push @lines, "$name:".join(',',@{$cl}); } } } else { my ($params, @values) = @{$$e{$name}}; push @lines, "$name;".join(";", map { "$_=$$params{$_}" } keys(%$params)).":".join(',',@values); } } else { warn "ignoring unimplemented ",ref(\${$e}{$name})," -> ",$name."\n"; } } push @lines, "END:$component", "END:VCALENDAR" if ! $excludeComponent; return @lines; } # taken from Text::ParseWords without single quote as quote char # and keep flag # sub parse_line { # We will be testing undef strings no warnings; use re 'taint'; # if it's tainted, leave it as such my($delimiter, $line) = @_; my($word, @pieces); while (length($line)) { $line =~ s/^(["]) # a $quote ((?:\\.|(?!\1)[^\\])*) # and $quoted text \1 # followed by the same quote | # --OR-- ^((?:\\.|[^\\"])*?) # an $unquoted text (\Z(?!\n)|(?-x:$delimiter)|(?!^)(?=["])) # plus EOL, delimiter, or quote //xs or return; # extended layout my($quote, $quoted, $unquoted, $delim) = ($1, $2, $3, $4); return() unless( defined($quote) || length($unquoted) || length($delim)); $quoted = "$quote$quoted$quote"; $word .= defined $quote ? $quoted : $unquoted; if (length($delim)) { push(@pieces, $word); undef $word; } if (!length($line)) { push(@pieces, $word); } } return(@pieces); } sub toHash { my $self = shift; my $index = shift; my $excludeComponent = shift; my $i; $i = 0; $i++ until ${$self->{A}}[$index - $i] =~ /^BEGIN:(\w+)$/; my $si = $index - $i; my $component = $1; $i = 0; $i++ until ${$self->{A}}[$index + $i] =~ /^END:$component/; my $fi = $index + $i; $self->debug("component $component found between [$si, $fi]"); my %e; my $subComponent = ''; for my $i ($si+1..$fi-1) { next if ${$self->{A}}[$i] =~ m/^UID/; if (${$self->{A}}[$i] =~ m/^\w+/) { my $contentLine = $self->unfold($i); if ($subComponent ne '') { # we are in a subcomponent $subComponent = '' if $contentLine =~ /^END:$subComponent$/; next; } elsif ($contentLine =~ /^BEGIN:(\w+)$/) { # we have found a subcomponent $subComponent = $1; push @{$e{$subComponent}}, $self->toHash($i, 1); } elsif ($contentLine =~ /^[\w-]+;.*$/s) { # we have params my ($nameAndParamString, @valueFragments) = &parse_line(':', $contentLine); my @values = &parse_line(',', join(':', @valueFragments)); my ($name, @params) = &parse_line(';', $nameAndParamString); my %params = map { my ($p, $v) = split(/=/, $_); $p => $v } @params; if (exists $e{$name}) { if (!(@{$e{$name}} && !grep({ref($_) ne 'ARRAY'} @{$e{$name}}))) { # not a strict list of arrays $self->debug("found singleton data, converting to list.."); $e{$name} = [$e{$name}, [{%params}, @values]]; } else { push @{$e{$name}}, [{%params}, @values]; } } else { $e{$name} = [{%params}, @values]; } } elsif ($contentLine =~ /^[\w-]+:.*$/s) { # we don't have params my ($name, @valueFragments) = &parse_line(':', $contentLine); my @values; if ($name eq 'RRULE') { my @params = &parse_line(';', join(':', @valueFragments)); my %params = map { my ($p, $v) = split(/=/, $_); $p => $v =~ /,/ ? [split(/,/,$v)] : $v } @params; push @values, {%params}; } else { @values = &parse_line(',', join(':', @valueFragments)); } if (exists $e{$name}) { if (!(ref($e{$name}) eq 'ARRAY' && @{$e{$name}} && !grep({ref($_) ne 'ARRAY'} @{$e{$name}}))) { # not a strict list of arrays $self->debug("found singleton data, converting to list.."); $e{$name} = [$e{$name}, [@values]]; } else { push @{$e{$name}}, [@values]; } } else { if (@values == 0) { $e{$name} = ""; } elsif (@values == 1) { $e{$name} = $values[0]; } else { $e{$name} = [@values]; } } } else { # what do we have? warn("discovered illegal property format, should be like NAME;...:..., ignoring for now\n"); } } } return $excludeComponent ? \%e : [$component, \%e] ; } =head1 BUGS Property names are assumed not to be folded, i.e. DESCR IPTION:blah blah.. RRULE property does not support parameters. Property names that begin with UID can potentially confuse this module. Subcomponents such as VALARM must exist after any UID property. Deleting events individually may leave non-RFC2445 compliant empty VCALENDAR objects. =head1 AUTHOR Blair Sutton, , L =head1 COPYRIGHT Copyright (c) 2006 Blair Sutton. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L, L =cut 1;Tie-iCal-0.15/samples000755000000000000 011635731512 15025 5ustar00unknownunknown000000000000Tie-iCal-0.15/samples/demo.ics000444000000000000 3751011635724214 16635 0ustar00unknownunknown000000000000BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :413dd998-67d6-11d9-9a33-e4a59cf11a95 SUMMARY :my event DESCRIPTION :my note LOCATION :my location URL :http://myurl.com STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X ;MEMBER=AlarmEmailAddress :me@myaddress RRULE :FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,WE,TH EXDATE :20050118T000000 DTSTART :20050118T160000Z DTEND :20050118T170000Z DTSTAMP :20050116T154856Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :927172676 SUMMARY :Summer Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20020826 DTSTAMP :20020430T114937Z END:VEVENT BEGIN:VEVENT UID :1ce81410-4769-11d9-8693-ee0b0a9128b1 SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20041228 DTEND ;VALUE=DATE :20041229 DTSTAMP :20041206T092748Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :2285be0e-4769-11d9-9032-fb135edc90b2 SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20041227 DTEND ;VALUE=DATE :20041228 DTSTAMP :20041206T092802Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :3be6a610-4769-11d9-bf60-e015b2923205 SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050325 DTEND ;VALUE=DATE :20050326 DTSTAMP :20041206T092845Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :42faa140-4769-11d9-8181-bcd3c0ece72d SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050328 DTEND ;VALUE=DATE :20050329 DTSTAMP :20041206T092857Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :496a1a2e-4769-11d9-8b9e-9a84f95c649f SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050502 DTEND ;VALUE=DATE :20050503 DTSTAMP :20041206T092907Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :4f246064-4769-11d9-add5-c041a1ed7968 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050530 DTEND ;VALUE=DATE :20050531 DTSTAMP :20041206T092917Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :56208410-4769-11d9-840a-ff72353214de SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050829 DTEND ;VALUE=DATE :20050830 DTSTAMP :20041206T092929Z LAST-MODIFIED :20041206T092938Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :6389be50-4769-11d9-b537-96d51d02ab76 SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20051227 DTEND ;VALUE=DATE :20051228 DTSTAMP :20041206T092951Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :698ded6c-4769-11d9-9e35-8764b0ff2b8e SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20051226 DTEND ;VALUE=DATE :20051227 DTSTAMP :20041206T093001Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :7323412e-4769-11d9-8f2d-c469be04ddf5 SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060102 DTEND ;VALUE=DATE :20060103 DTSTAMP :20041206T093018Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :7ff3e4ee-4769-11d9-b1d4-e2dcd6159dd0 SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060414 DTEND ;VALUE=DATE :20060415 DTSTAMP :20041206T093038Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :85c3a04e-4769-11d9-8af7-cda5e3e98ebe SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060417 DTEND ;VALUE=DATE :20060418 DTSTAMP :20041206T093047Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :8c18df5e-4769-11d9-ac09-e97dffd65595 SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060501 DTEND ;VALUE=DATE :20060502 DTSTAMP :20041206T093101Z LAST-MODIFIED :20041206T093108Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :958a6fda-4769-11d9-88db-e91b56d7b8f8 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060529 DTEND ;VALUE=DATE :20060530 DTSTAMP :20041206T093113Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :9f39fd7a-4769-11d9-a665-99a1ee535d36 SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060828 DTEND ;VALUE=DATE :20060829 DTSTAMP :20041206T093129Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :a6b9427c-4769-11d9-964c-e7e2f4c2006a SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20061225 DTEND ;VALUE=DATE :20061226 DTSTAMP :20041206T093144Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :ab98305a-4769-11d9-b056-be29252508db SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20061226 DTEND ;VALUE=DATE :20061227 DTSTAMP :20041206T093151Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :b36fac5e-4769-11d9-9833-cbe45ff8e08b SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070101 DTEND ;VALUE=DATE :20070102 DTSTAMP :20041206T093204Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :ba1d2270-4769-11d9-bc2f-f524346ae56f SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070406 DTEND ;VALUE=DATE :20070407 DTSTAMP :20041206T093217Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :bf0cc0c4-4769-11d9-bd28-8ce79732df58 SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070409 DTEND ;VALUE=DATE :20070410 DTSTAMP :20041206T093225Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :c70f271c-4769-11d9-85d5-eeae49afa7c8 SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070507 DTEND ;VALUE=DATE :20070508 DTSTAMP :20041206T093238Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :cd6b8d3a-4769-11d9-8ec2-b2672c137a80 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070528 DTEND ;VALUE=DATE :20070529 DTSTAMP :20041206T093248Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :d5de0218-4769-11d9-8ab6-fc42c8cf7511 SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070827 DTEND ;VALUE=DATE :20070828 DTSTAMP :20041206T093303Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :e2435c06-4769-11d9-8189-85efc4fcc75a SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20071225 DTEND ;VALUE=DATE :20071226 DTSTAMP :20041206T093325Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :e6b9626c-4769-11d9-9636-b4b242071a07 SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20071226 DTEND ;VALUE=DATE :20071227 DTSTAMP :20041206T093331Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :eed602a2-4769-11d9-9c29-87e14bef7e97 SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20080101 DTEND ;VALUE=DATE :20080102 DTSTAMP :20041206T093345Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :de525990-4768-11d9-b210-dbb23e96122f SUMMARY :New Year's day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040101 DTEND ;VALUE=DATE :20040102 DTSTAMP :20041206T092559Z LAST-MODIFIED :20041207T102901Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :eaabc7bc-4768-11d9-a9f0-d813f0b4250b SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040409 DTEND ;VALUE=DATE :20040410 DTSTAMP :20041206T092625Z LAST-MODIFIED :20041207T102903Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :f3741142-4768-11d9-90f2-b75bdc777a72 SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040412 DTEND ;VALUE=DATE :20040413 DTSTAMP :20041206T092637Z LAST-MODIFIED :20041207T102903Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :ffac1e82-4768-11d9-af34-c8169769d183 SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040503 DTEND ;VALUE=DATE :20040504 DTSTAMP :20041206T092702Z LAST-MODIFIED :20041207T102903Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :06af693c-4769-11d9-88da-f9a496177710 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040531 DTEND ;VALUE=DATE :20040601 DTSTAMP :20041206T092714Z LAST-MODIFIED :20041207T102904Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :0fcfe9c4-4769-11d9-b1de-afc927cc7b57 SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040830 DTEND ;VALUE=DATE :20040831 DTSTAMP :20041206T092731Z LAST-MODIFIED :20041207T102904Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :359d52c2-4769-11d9-9cd3-fde74dbfad50 SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20050103T010338 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20050103 DTEND ;VALUE=DATE :20050104 DTSTAMP :20041206T092833Z LAST-MODIFIED :20050103T010338Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :971445858 SUMMARY :Christmas Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20021225 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :925921922 SUMMARY :Boxing Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20021226 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :936923338 SUMMARY :New Year's Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030101 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :962980365 SUMMARY :Good Friday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030418 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :909072250 SUMMARY :Easter Monday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030421 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :940352282 SUMMARY :May Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030505 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :975821516 SUMMARY :Spring Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030526 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :902762343 SUMMARY :Summer Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030825 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :956630271 SUMMARY :Christmas Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20031225 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :911737808 SUMMARY :Boxing Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20031226 DTSTAMP :20020430T114937Z END:VEVENT BEGIN:VEVENT ORGANIZER:Mailto:B@example.com ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN=BIG A:Mailto:A@example.com ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=B:Mailto:B@example.com ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=C:Mailto:C@example.com ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=Hal:Mailto:D@example.com ATTENDEE;RSVP=FALSE;CUTYPE=ROOM:conf_Big@example.com ATTENDEE:conf_Big1@example.com ATTENDEE;ROLE=NON-PARTICIPANT;RSVP=FALSE:Mailto:E@example.com DTSTAMP:19970611T190000Z DTSTART:19970701T190000Z DTEND:19970701T193000Z SUMMARY:Conference UID:calsrv.example.com-873970198738777@example.com SEQUENCE:1 STATUS:CONFIRMED END:VEVENT END:VCALENDAR Tie-iCal-0.15/samples/demo.pl000444000000000000 471011635724214 16446 0ustar00unknownunknown000000000000use Tie::iCal; use Data::Dumper; print "TIEHASH test.."; tie %events, 'Tie::iCal', "./demo.ics", 'debug' => 0 or die "Failed to tie file!\n"; print "ok\n"; print "FETCH test..\n"; print Dumper($events{'413dd998-67d6-11d9-9a33-e4a59cf11a95'}); print "FETCH cache test..\n"; print Dumper($events{'413dd998-67d6-11d9-9a33-e4a59cf11a95'}); print "EXISTS test..\n"; if (exists $events{'calsrv.example.com-873970198738777@example.com'}) { print "Found key 'calsrv.example.com-873970198738777\@example.com', printing it..\n"; print Dumper($events{'calsrv.example.com-873970198738777@example.com'})."\n"; } if (!exists $events{'this_UID_does_not_exist'}) { print "Did not find non-existant key\n"; } print "FIRSTKEY test..\n"; print each(%events)."\n"; print "NEXTKEY test..\n"; #~ print "list keys..\n"; #~ foreach (keys %events) { print $_."\n" } #~ print "list values..\n"; #~ foreach (values %events) { print Dumper($_)."\n" } while (($key, $value) = each %events) { print $key, "\n" } print "COUNT test..\n"; print scalar(%events)."\n"; print "DELETE test..\n"; use File::Copy; copy("./demo.ics","./democopy.ics"); tie %eventscopy, 'Tie::iCal', "./democopy.ics", 'debug' => 1 or die "Failed to tie file!\n"; delete $eventscopy{'1ce81410-4769-11d9-8693-ee0b0a9128b1'}; if (!exists $events{'1ce81410-4769-11d9-8693-ee0b0a9128b1'}) { print "Did not find deleted key\n"; } print "STORE test..\n"; $eventscopy{"A-UNIQUE-ID"} = [ 'VEVENT', { 'URL' => 'http//myurl.com', 'SUMMARY' => 'my event', 'CLASS' => 'PRIVATE', 'LOCATION' => 'my location', 'X' => [{'MEMBER' => 'AlarmEmailAddress'}, 'me@myaddress'], 'STATUS' => 'TENTATIVE', 'DTSTAMP' => '20050116T154856Z', 'DTEND' => '20050118T170000Z', 'VALARM' => [ { 'TRIGGER' => [{'VALUE' => 'DURATION'}, '-PT1S'] } ], 'DESCRIPTION' => 'my note', 'X-MOZILLA-ALARM-DEFAULT-LENGTH' => '0', 'RRULE' => { 'FREQ' => 'WEEKLY', 'BYDAY' => [ 'TU', 'WE', 'TH' ], 'INTERVAL' => '1' }, 'EXDATE' => '20050118T000000', 'DTSTART' => '20050118T160000Z', 'ATTENDEE' => [ [{'CN' => 'BIG A','ROLE' => 'CHAIR','PARTSTAT' => 'ACCEPTED'},'MailtoA@example.com'], [{'CN' => 'B','RSVP' => 'TRUE','CUTYPE' => 'INDIVIDUAL'},'MailtoB@example.com'], ['MailtoB@example.com'] ] } ]; print "hit Enter to test CLEAR..\n"; getc(STDIN); print "CLEAR test..\n"; %eventscopy = ();Tie-iCal-0.15/samples/dump.pl000444000000000000 35711635724214 16452 0ustar00unknownunknown000000000000use Tie::iCal; use Data::Dumper; my $tievar = tie my %events, 'Tie::iCal', $ARGV[0], 'debug' => 0 or die "Failed to tie file!\n"; while (($uid, $event) = each %events) { print "\nUID:$uid\n"; print Dumper($event)."\n"; } Tie-iCal-0.15/samples/outlooksync.pl000444000000000000 2101411635724214 20127 0ustar00unknownunknown000000000000=head1 USAGE outlooksync.pl [--help] --ical [--olcal ] =head1 OPTIONS =over 8 =item B<--help|-?> Print this message. =item B<--cal|-i> Specify source RFC2445 iCalendar file to be synchronised, This option is mandatory. =item B<--olcal|-o> Specify destination Outlook calendar folder to synchronise with. If one is not specified then the default top level will be used. If the specified calendar does not exist it will be created. =head1 TODO Sync based on last modification time. =cut use strict; use Getopt::Long; use Pod::Usage; use vars qw/$verbose $icsFile $destFolder $ignoreCompleteTodos/; BEGIN { my $help = 0; if ( !GetOptions( 'ical|i=s' => \$icsFile, 'olcal|o=s' => \$destFolder, 'ignorecompletetodos' => \$ignoreCompleteTodos, 'verbose|v' => \$verbose, 'help|?' => \$help, ) || $help || !defined $icsFile ) { pod2usage(-verbose => 2); exit; } if (!-f $icsFile) { print "Cannot find iCal file '$icsFile'. It will be created\n"; } } use Tie::iCal; use Date::ICal; use Data::Dumper; use Win32::OLE qw(in with); BEGIN { print STDERR "Loading all OLE typelibs will take some time..."; } use Win32::OLE::Const 'Microsoft Outlook'; print STDERR "loaded.\n"; use Win32::OLE::Variant; use Win32::OLE::NLS qw(:LOCALE :DATE); $Win32::OLE::Warn = 3; use Win32; debug("Verbose logging is turned on."); debug("Using iCalendar file '$icsFile'"); # get Outlook object # my $Outlook; eval { $Outlook = Win32::OLE->GetActiveObject('Outlook.Application') }; die "Could not find Outlook. Is it installed?" if $@; unless (defined $Outlook) { $Outlook = Win32::OLE->new('Outlook.Application', sub {$_[0]->Quit;}) or die "Could not start Outlook."; } # get calendar, tasks and journal folder objects # # * see if destination folder exists # * if it doesn't create one # my $olCalendarItems = getDestinationFolder('olFolderCalendar', $destFolder)->Items(); my $olTaskItems = getDestinationFolder('olFolderTasks', $destFolder)->Items(); my $olJournalItems = getDestinationFolder('olFolderJournal', $destFolder)->Items(); my @olEvents; push @olEvents, in($olCalendarItems); push @olEvents, in($olTaskItems); push @olEvents, in($olJournalItems); # tie iCalendar file to a Perl hash # my $tievar = tie my %icalEvents, 'Tie::iCal', $icsFile, 'debug' => 0 or die "Failed to tie file!\n"; # cycle through outlook events # # * if an event does have an "iCalendarId" check it exists in ics file # and if it doesn't then add it. # # * if an event does not have an "iCalendar Id", add it to a list to # deal with later # debug("Processing Outlook events."); my @olEventsWithoutIds; my %olUids; foreach my $olEvent (@olEvents) { if ($olEvent->{UserProperties}->{"iCalendar Id"}) { my $olUid = $olEvent->{UserProperties}->{"iCalendar Id"}->Value; if (exists $icalEvents{$olUid}) { debug("$olUid: Ignoring Outlook/iCal event."); } else { debug("$olUid: Adding Outlook event to iCal"); olEventToIcal(\%icalEvents, $olUid, $olEvent); } $olUids{$olUid} = undef; } else { debug(": Delay Outlook event without 'iCalendar Id'."); push @olEventsWithoutIds, $olEvent; } } # cycle through outlook events without uids # # * add a unique uid # * add this event to ical # debug("Processing unidentified Outlook events."); foreach my $olEvent (@olEventsWithoutIds) { my $newUid = createUniqueID(\%icalEvents); $olEvent->{UserProperties}->Add("iCalendar Id", olText); $olEvent->{UserProperties}->{"iCalendar Id"} = $newUid; $olEvent->Save; debug("$newUid: Adding Outlook event to iCal (new Uid)."); olEventToIcal(\%icalEvents, $newUid, $olEvent); $olUids{$newUid} = undef; } # cycle through ical appointments # # * if event has already been seen ignore # debug("Processing iCalendar events."); my $i = 0; while (my ($icalUid, $icalEvent) = each %icalEvents) { if (!exists $olUids{$icalUid}) { if ($icalEvent->[0] eq 'VEVENT') { icalEventToOutlook($olCalendarItems, $icalUid, $icalEvent); } elsif ($icalEvent->[0] eq 'VTODO') { icalEventToOutlook($olTaskItems, $icalUid, $icalEvent); } else { debug("Unsupported iCalendar type '$icalEvent->[0]'.. skipping."); } } $i++; } debug("Processed $i ical records."); exit; sub debug { print STDERR $_[0]."\n" if $verbose; } sub getDestinationFolder { my ($olFolderType, $destFolderName) = @_; my $olFolder = $Outlook->GetNamespace("MAPI")->GetDefaultFolder(&{\&{$olFolderType}}()); if (defined $destFolderName) { debug("Searching for Outlook folder type '$olFolderType' called '$destFolderName'."); my $calExists = 0; foreach my $cal (in($olFolder->Folders())) { if ($cal->{name} eq $destFolderName) { $calExists = 1; debug("Found destination folder '$destFolderName'."); last; } } if (!$calExists) { debug("destination calendar '$destFolderName' does not exists.. creating."); $olFolder->{Folders}->Add($destFolderName); } return $olFolder->Folders($destFolderName); } else { debug("Using default Outlook folder for type '$olFolderType'."); return $olFolder; } } sub icalEventToOutlook { my ($olEvents, $icalUid, $icalEvent) = @_; debug("$icalUid: Adding event to Outlook."); my $olEvent = $olEvents->Add(); $olEvent->{UserProperties}->Add("iCalendar Id", olText); $olEvent->{UserProperties}->{"iCalendar Id"} = $icalUid; if ($icalEvent->[0] eq 'VEVENT') { setOutlookValue($olEvent, 'Subject', $icalEvent->[1]->{SUMMARY}); setOutlookValue($olEvent, 'Body', $icalEvent->[1]->{DESCRIPTION}); setOutlookValue($olEvent, 'Location', $icalEvent->[1]->{LOCATION}); setOutlookValue($olEvent, 'Start', tiedDateToVariant($icalEvent->[1]->{DTSTART})); setOutlookValue($olEvent, 'End', tiedDateToVariant($icalEvent->[1]->{DTEND})); } elsif ($icalEvent->[0] eq 'VTODO') { setOutlookValue($olEvent, 'Subject', $icalEvent->[1]->{SUMMARY}); setOutlookValue($olEvent, 'Body', $icalEvent->[1]->{DESCRIPTION}); setOutlookValue($olEvent, 'StartDate', tiedDateToVariant($icalEvent->[1]->{DTSTART})); setOutlookValue($olEvent, 'DueDate', tiedDateToVariant($icalEvent->[1]->{DUE})); setOutlookValue($olEvent, 'PercentComplete', $icalEvent->[1]->{'PERCENT-COMPLETE'}); } $olEvent->Save; #print Dumper($icalEvent->[1])."\n"; } sub setOutlookValue { my ($olEvent, $key, $value) = @_; if ($value ne '') { $olEvent->{$key} = $value; } } sub olEventToIcal { my ($icalEventsHref, $olUid, $olEvent) = @_; debug("$olUid: Adding event to iCalendar."); if ($olEvent->{MessageClass} eq 'IPM.Appointment') { $icalEventsHref->{$olUid} = [ 'VEVENT', { 'SUMMARY' => $olEvent->{Subject}, 'DESCRIPTION' => $olEvent->{Body}, 'LOCATION' => $olEvent->{Location}, 'DTSTART' => variantDateToIcal($olEvent->{start}), 'DTEND' => variantDateToIcal($olEvent->{end}), } ]; } elsif ($olEvent->{MessageClass} eq 'IPM.Task') { $icalEventsHref->{$olUid} = [ 'VTODO', { 'SUMMARY' => $olEvent->{Subject}, 'DESCRIPTION' => $olEvent->{Body}, 'DTSTART' => variantDateToIcal($olEvent->{StartDate}), 'DUE' => variantDateToIcal($olEvent->{DueDate}), 'PERCENT-COMPLETE' => $olEvent->{PercentComplete}, } ]; } else { # TODO: IPM.Activity debug("Unsupported Outlook message class '$olEvent->{MessageClass}'.. skipping."); } #print $olEvent->{isrecurring}."\n"; } sub tiedDateToVariant { if (ref($_[0]) eq '') { return icalDateToVariant($_[0]); } elsif (ref($_[0]) eq 'ARRAY') { return icalDateToVariant($_[0]->[1]); # big assumption? } else { debug("Unrecognized ical date format"); return undef; } } sub icalDateToVariant { my $x = Date::ICal->new(ical => $_[0]); my $s = sprintf ("%s/%s/%s %s:%s", $x->day, $x->month, $x->year, $x->hour, $x->min); return $s; #return Variant(VT_DATE, $s); } sub variantDateToIcal { my ($year, $month, $day) = split(/ /, $_[0]->Date("yyyy M d")); my ($hour, $minute, $sec) = split(/ /, $_[0]->Time("H m s")); return Date::ICal->new( year => $year, month => $month, day => $day, hour => $hour, min => $minute, sec => $sec )->ical; } # modified mozilla recipe # sub createUniqueID { my $href = shift; my $newID = ""; while ($newID eq "" || exists $$href{$newID}) { $newID = Win32::GuidGen(); } return $newID; } Tie-iCal-0.15/samples/uniquify.pl000444000000000000 310611635724214 17371 0ustar00unknownunknown000000000000use Tie::iCal; unlink "unique.ics", "nonunique.ics"; open ICS, ">nonunique.ics"; while () { print ICS $_ } close ICS; tie %events, 'Tie::iCal', "nonunique.ics", 'debug' => 0 or die "Failed to tie file!\n"; tie %newevents, 'Tie::iCal', "unique.ics", 'debug' => 0 or die "Failed to tie file!\n"; print STDERR "Converting nonunique.ics to unique.ics..\n"; while (($uid, $event) = each %events) { my $newuid = createUniqueID(\%events); print STDERR "Converting old key $uid to new key $newuid..\n"; $newevents{$newuid} = $event; } print STDERR "done\n"; untie %events; untie %newevents; exit; # modified mozilla recipe # sub createUniqueID { my $href = shift; my $newID = ""; while ($newID eq "" || exists $$href{$newID}) { $newID = int(900000000 + rand(100000000)); } return $newID; } __END__ BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Numen Inest/NONSGML Tie::iCal 0.11//EN BEGIN:VEVENT UID:9999 SUMMARY:My Event DTSTART;VALUE=DATE:20031225 DTEND;VALUE=DATE:20031226 END:VEVENT BEGIN:VEVENT UID:9999 SUMMARY:My Event DTSTART;VALUE=DATE:20031225 DTEND;VALUE=DATE:20031226 END:VEVENT BEGIN:VEVENT UID:9999 SUMMARY:My Event DTSTART;VALUE=DATE:20031225 DTEND;VALUE=DATE:20031226 END:VEVENT BEGIN:VEVENT UID:9999 SUMMARY:My Event DTSTART;VALUE=DATE:20031225 DTEND;VALUE=DATE:20031226 END:VEVENT BEGIN:VEVENT UID:9999 SUMMARY:My Event DTSTART;VALUE=DATE:20031225 DTEND;VALUE=DATE:20031226 END:VEVENT BEGIN:VEVENT UID:9999 SUMMARY:My Event DTSTART;VALUE=DATE:20031225 DTEND;VALUE=DATE:20031226 END:VEVENT END:VCALENDARTie-iCal-0.15/t000755000000000000 011635731512 13624 5ustar00unknownunknown000000000000Tie-iCal-0.15/t/a_use.t000444000000000000 16411635724214 15224 0ustar00unknownunknown000000000000#!/usr/bin/env perl -w use strict; use Test; BEGIN { plan tests => 1 } use Tie::iCal; ok(1); exit; __END__ Tie-iCal-0.15/t/b_tie.t000444000000000000 4376411635724214 15267 0ustar00unknownunknown000000000000#!/usr/bin/env perl -w use strict; use Test; BEGIN { plan tests => 14 } open ICS, ">test.ics"; while () { print ICS $_ } close ICS; use Tie::iCal; # TIEHASH ok(tie my %events, 'Tie::iCal', "test.ics", 'debug' => 0); # FETCH my ($comp, $hash) = @{$events{'413dd998-67d6-11d9-9a33-e4a59cf11a95'}}; ok($comp eq 'VEVENT'); ok(${$hash}{'SUMMARY'} eq 'my event'); # FETCH cache my ($comp1, $hash1) = @{$events{'413dd998-67d6-11d9-9a33-e4a59cf11a95'}}; ok($comp1 eq 'VEVENT'); ok(${$hash1}{'SUMMARY'} eq 'my event'); # EXISTS ok(exists $events{'calsrv.example.com-873970198738777@example.com'}); ok(!exists $events{'this_UID_does_not_exist'}); # FIRSTKEY ok(each(%events) eq '413dd998-67d6-11d9-9a33-e4a59cf11a95'); # NEXTKEY my $count = 0; while (my ($key, $value) = each %events) { $count++; } ok($count == 45); # COUNT ok(scalar(keys %events) == 46); # DELETE delete $events{'1ce81410-4769-11d9-8693-ee0b0a9128b1'}; ok(!exists $events{'1ce81410-4769-11d9-8693-ee0b0a9128b1'}); # STORE $events{'A-UNIQUE-ID'} = [ 'VEVENT', { 'URL' => 'http//myurl.com', 'SUMMARY' => 'my event', 'CLASS' => 'PRIVATE', 'LOCATION' => 'my location', 'X' => [{'MEMBER' => 'AlarmEmailAddress'}, 'me@myaddress'], 'STATUS' => 'TENTATIVE', 'DTSTAMP' => '20050116T154856Z', 'DTEND' => '20050118T170000Z', 'VALARM' => [ { 'TRIGGER' => [{'VALUE' => 'DURATION'}, '-PT1S'] } ], 'DESCRIPTION' => 'my note', 'X-MOZILLA-ALARM-DEFAULT-LENGTH' => '0', 'RRULE' => { 'FREQ' => 'WEEKLY', 'BYDAY' => [ 'TU', 'WE', 'TH' ], 'INTERVAL' => '1' }, 'EXDATE' => '20050118T000000', 'DTSTART' => '20050118T160000Z', 'ATTENDEE' => [ [{'CN' => 'BIG A','ROLE' => 'CHAIR','PARTSTAT' => 'ACCEPTED'},'MailtoA@example.com'], [{'CN' => 'B','RSVP' => 'TRUE','CUTYPE' => 'INDIVIDUAL'},'MailtoB@example.com'], ['MailtoB@example.com'] ] } ]; my ($comp2, $hash2) = @{$events{'A-UNIQUE-ID'}}; ok($comp2 eq 'VEVENT'); ok(${$hash2}{'LOCATION'} eq 'my location'); # CLEAR %events = (); ok(-z 'test.ics'); untie %events; unlink 'test.ics'; exit; __END__ BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :413dd998-67d6-11d9-9a33-e4a59cf11a95 SUMMARY :my event DESCRIPTION :my note LOCATION :my location URL :http://myurl.com STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X ;MEMBER=AlarmEmailAddress :me@myaddress RRULE :FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,WE,TH EXDATE :20050118T000000 DTSTART :20050118T160000Z DTEND :20050118T170000Z DTSTAMP :20050116T154856Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :927172676 SUMMARY :Summer Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20020826 DTSTAMP :20020430T114937Z END:VEVENT BEGIN:VEVENT UID :1ce81410-4769-11d9-8693-ee0b0a9128b1 SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20041228 DTEND ;VALUE=DATE :20041229 DTSTAMP :20041206T092748Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :2285be0e-4769-11d9-9032-fb135edc90b2 SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20041227 DTEND ;VALUE=DATE :20041228 DTSTAMP :20041206T092802Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :3be6a610-4769-11d9-bf60-e015b2923205 SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050325 DTEND ;VALUE=DATE :20050326 DTSTAMP :20041206T092845Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :42faa140-4769-11d9-8181-bcd3c0ece72d SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050328 DTEND ;VALUE=DATE :20050329 DTSTAMP :20041206T092857Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :496a1a2e-4769-11d9-8b9e-9a84f95c649f SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050502 DTEND ;VALUE=DATE :20050503 DTSTAMP :20041206T092907Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :4f246064-4769-11d9-add5-c041a1ed7968 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050530 DTEND ;VALUE=DATE :20050531 DTSTAMP :20041206T092917Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :56208410-4769-11d9-840a-ff72353214de SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050829 DTEND ;VALUE=DATE :20050830 DTSTAMP :20041206T092929Z LAST-MODIFIED :20041206T092938Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :6389be50-4769-11d9-b537-96d51d02ab76 SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20051227 DTEND ;VALUE=DATE :20051228 DTSTAMP :20041206T092951Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :698ded6c-4769-11d9-9e35-8764b0ff2b8e SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20051226 DTEND ;VALUE=DATE :20051227 DTSTAMP :20041206T093001Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :7323412e-4769-11d9-8f2d-c469be04ddf5 SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060102 DTEND ;VALUE=DATE :20060103 DTSTAMP :20041206T093018Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :7ff3e4ee-4769-11d9-b1d4-e2dcd6159dd0 SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060414 DTEND ;VALUE=DATE :20060415 DTSTAMP :20041206T093038Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :85c3a04e-4769-11d9-8af7-cda5e3e98ebe SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060417 DTEND ;VALUE=DATE :20060418 DTSTAMP :20041206T093047Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :8c18df5e-4769-11d9-ac09-e97dffd65595 SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060501 DTEND ;VALUE=DATE :20060502 DTSTAMP :20041206T093101Z LAST-MODIFIED :20041206T093108Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :958a6fda-4769-11d9-88db-e91b56d7b8f8 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060529 DTEND ;VALUE=DATE :20060530 DTSTAMP :20041206T093113Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :9f39fd7a-4769-11d9-a665-99a1ee535d36 SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060828 DTEND ;VALUE=DATE :20060829 DTSTAMP :20041206T093129Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :a6b9427c-4769-11d9-964c-e7e2f4c2006a SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20061225 DTEND ;VALUE=DATE :20061226 DTSTAMP :20041206T093144Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :ab98305a-4769-11d9-b056-be29252508db SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20061226 DTEND ;VALUE=DATE :20061227 DTSTAMP :20041206T093151Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :b36fac5e-4769-11d9-9833-cbe45ff8e08b SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070101 DTEND ;VALUE=DATE :20070102 DTSTAMP :20041206T093204Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :ba1d2270-4769-11d9-bc2f-f524346ae56f SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070406 DTEND ;VALUE=DATE :20070407 DTSTAMP :20041206T093217Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :bf0cc0c4-4769-11d9-bd28-8ce79732df58 SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070409 DTEND ;VALUE=DATE :20070410 DTSTAMP :20041206T093225Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :c70f271c-4769-11d9-85d5-eeae49afa7c8 SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070507 DTEND ;VALUE=DATE :20070508 DTSTAMP :20041206T093238Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :cd6b8d3a-4769-11d9-8ec2-b2672c137a80 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070528 DTEND ;VALUE=DATE :20070529 DTSTAMP :20041206T093248Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :d5de0218-4769-11d9-8ab6-fc42c8cf7511 SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070827 DTEND ;VALUE=DATE :20070828 DTSTAMP :20041206T093303Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :e2435c06-4769-11d9-8189-85efc4fcc75a SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20071225 DTEND ;VALUE=DATE :20071226 DTSTAMP :20041206T093325Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :e6b9626c-4769-11d9-9636-b4b242071a07 SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20071226 DTEND ;VALUE=DATE :20071227 DTSTAMP :20041206T093331Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :eed602a2-4769-11d9-9c29-87e14bef7e97 SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20080101 DTEND ;VALUE=DATE :20080102 DTSTAMP :20041206T093345Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :de525990-4768-11d9-b210-dbb23e96122f SUMMARY :New Year's day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040101 DTEND ;VALUE=DATE :20040102 DTSTAMP :20041206T092559Z LAST-MODIFIED :20041207T102901Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :eaabc7bc-4768-11d9-a9f0-d813f0b4250b SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040409 DTEND ;VALUE=DATE :20040410 DTSTAMP :20041206T092625Z LAST-MODIFIED :20041207T102903Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :f3741142-4768-11d9-90f2-b75bdc777a72 SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040412 DTEND ;VALUE=DATE :20040413 DTSTAMP :20041206T092637Z LAST-MODIFIED :20041207T102903Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :ffac1e82-4768-11d9-af34-c8169769d183 SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040503 DTEND ;VALUE=DATE :20040504 DTSTAMP :20041206T092702Z LAST-MODIFIED :20041207T102903Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :06af693c-4769-11d9-88da-f9a496177710 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040531 DTEND ;VALUE=DATE :20040601 DTSTAMP :20041206T092714Z LAST-MODIFIED :20041207T102904Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :0fcfe9c4-4769-11d9-b1de-afc927cc7b57 SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040830 DTEND ;VALUE=DATE :20040831 DTSTAMP :20041206T092731Z LAST-MODIFIED :20041207T102904Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :359d52c2-4769-11d9-9cd3-fde74dbfad50 SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20050103T010338 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20050103 DTEND ;VALUE=DATE :20050104 DTSTAMP :20041206T092833Z LAST-MODIFIED :20050103T010338Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :971445858 SUMMARY :Christmas Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20021225 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :925921922 SUMMARY :Boxing Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20021226 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :936923338 SUMMARY :New Year's Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030101 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :962980365 SUMMARY :Good Friday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030418 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :909072250 SUMMARY :Easter Monday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030421 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :940352282 SUMMARY :May Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030505 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :975821516 SUMMARY :Spring Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030526 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :902762343 SUMMARY :Summer Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030825 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :956630271 SUMMARY :Christmas Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20031225 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :911737808 SUMMARY :Boxing Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20031226 DTSTAMP :20020430T114937Z END:VEVENT BEGIN:VEVENT ORGANIZER:Mailto:B@example.com ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN=BIG A:Mailto:A@example.com ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=B:Mailto:B@example.com ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=C:Mailto:C@example.com ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=Hal:Mailto:D@example.com ATTENDEE;RSVP=FALSE;CUTYPE=ROOM:conf_Big@example.com ATTENDEE:conf_Big1@example.com ATTENDEE;ROLE=NON-PARTICIPANT;RSVP=FALSE:Mailto:E@example.com DTSTAMP:19970611T190000Z DTSTART:19970701T190000Z DTEND:19970701T193000Z SUMMARY:Conference UID:calsrv.example.com-873970198738777@example.com SEQUENCE:1 STATUS:CONFIRMED END:VEVENT END:VCALENDARTie-iCal-0.15/t/c_storefetch.t000444000000000000 4177011635724214 16650 0ustar00unknownunknown000000000000#!/usr/bin/env perl -w use strict; use Test; BEGIN { plan tests => 49 } open ICS, ">test1.ics"; while () { print ICS $_ } close ICS; use Tie::iCal; # TIEHASH ok(tie my %events1, 'Tie::iCal', "test1.ics", 'debug' => 0); ok(tie my %events2, 'Tie::iCal', "test2.ics", 'debug' => 0); ok(scalar(keys %events1) == 46); while (my ($key, $value) = each %events1) { $events2{$key} = $value; ok(compare($events1{$key}, $events2{$key})); } untie %events1; untie %events2; unlink 'test1.ics'; unlink 'test2.ics'; exit; sub compare { my ($a, $b) = @_; return 0 if ref($a) ne ref($b); if (ref($a) eq 'ARRAY') { return 0 if $#$a != $#$b; for my $i (0..$#$a) { return 0 if !compare($$a[$i], $$b[$i]); } } elsif (ref($a) eq 'HASH') { my @A = sort keys %$a; my @B = sort keys %$b; return 0 if $#A != $#B; for my $j (0..$#A) { return 0 if !compare($A[$j], $B[$j]); return 0 if !compare($$a{$A[$j]}, $$b{$B[$j]}); } } else { return 0 if $a ne $b; } return 1; } __END__ BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :413dd998-67d6-11d9-9a33-e4a59cf11a95 SUMMARY :my event DESCRIPTION :my note LOCATION :my location URL :http://myurl.com STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X ;MEMBER=AlarmEmailAddress :me@myaddress RRULE :FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,WE,TH EXDATE :20050118T000000 DTSTART :20050118T160000Z DTEND :20050118T170000Z DTSTAMP :20050116T154856Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :927172676 SUMMARY :Summer Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20020826 DTSTAMP :20020430T114937Z END:VEVENT BEGIN:VEVENT UID :1ce81410-4769-11d9-8693-ee0b0a9128b1 SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20041228 DTEND ;VALUE=DATE :20041229 DTSTAMP :20041206T092748Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :2285be0e-4769-11d9-9032-fb135edc90b2 SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20041227 DTEND ;VALUE=DATE :20041228 DTSTAMP :20041206T092802Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :3be6a610-4769-11d9-bf60-e015b2923205 SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050325 DTEND ;VALUE=DATE :20050326 DTSTAMP :20041206T092845Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :42faa140-4769-11d9-8181-bcd3c0ece72d SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050328 DTEND ;VALUE=DATE :20050329 DTSTAMP :20041206T092857Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :496a1a2e-4769-11d9-8b9e-9a84f95c649f SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050502 DTEND ;VALUE=DATE :20050503 DTSTAMP :20041206T092907Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :4f246064-4769-11d9-add5-c041a1ed7968 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050530 DTEND ;VALUE=DATE :20050531 DTSTAMP :20041206T092917Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :56208410-4769-11d9-840a-ff72353214de SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20050829 DTEND ;VALUE=DATE :20050830 DTSTAMP :20041206T092929Z LAST-MODIFIED :20041206T092938Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :6389be50-4769-11d9-b537-96d51d02ab76 SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20051227 DTEND ;VALUE=DATE :20051228 DTSTAMP :20041206T092951Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :698ded6c-4769-11d9-9e35-8764b0ff2b8e SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20051226 DTEND ;VALUE=DATE :20051227 DTSTAMP :20041206T093001Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :7323412e-4769-11d9-8f2d-c469be04ddf5 SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060102 DTEND ;VALUE=DATE :20060103 DTSTAMP :20041206T093018Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :7ff3e4ee-4769-11d9-b1d4-e2dcd6159dd0 SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060414 DTEND ;VALUE=DATE :20060415 DTSTAMP :20041206T093038Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :85c3a04e-4769-11d9-8af7-cda5e3e98ebe SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060417 DTEND ;VALUE=DATE :20060418 DTSTAMP :20041206T093047Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :8c18df5e-4769-11d9-ac09-e97dffd65595 SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060501 DTEND ;VALUE=DATE :20060502 DTSTAMP :20041206T093101Z LAST-MODIFIED :20041206T093108Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :958a6fda-4769-11d9-88db-e91b56d7b8f8 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060529 DTEND ;VALUE=DATE :20060530 DTSTAMP :20041206T093113Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :9f39fd7a-4769-11d9-a665-99a1ee535d36 SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20060828 DTEND ;VALUE=DATE :20060829 DTSTAMP :20041206T093129Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :a6b9427c-4769-11d9-964c-e7e2f4c2006a SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20061225 DTEND ;VALUE=DATE :20061226 DTSTAMP :20041206T093144Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :ab98305a-4769-11d9-b056-be29252508db SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20061226 DTEND ;VALUE=DATE :20061227 DTSTAMP :20041206T093151Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :b36fac5e-4769-11d9-9833-cbe45ff8e08b SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070101 DTEND ;VALUE=DATE :20070102 DTSTAMP :20041206T093204Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :ba1d2270-4769-11d9-bc2f-f524346ae56f SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070406 DTEND ;VALUE=DATE :20070407 DTSTAMP :20041206T093217Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :bf0cc0c4-4769-11d9-bd28-8ce79732df58 SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070409 DTEND ;VALUE=DATE :20070410 DTSTAMP :20041206T093225Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :c70f271c-4769-11d9-85d5-eeae49afa7c8 SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070507 DTEND ;VALUE=DATE :20070508 DTSTAMP :20041206T093238Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :cd6b8d3a-4769-11d9-8ec2-b2672c137a80 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070528 DTEND ;VALUE=DATE :20070529 DTSTAMP :20041206T093248Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :d5de0218-4769-11d9-8ab6-fc42c8cf7511 SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20070827 DTEND ;VALUE=DATE :20070828 DTSTAMP :20041206T093303Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :e2435c06-4769-11d9-8189-85efc4fcc75a SUMMARY :Christmas Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20071225 DTEND ;VALUE=DATE :20071226 DTSTAMP :20041206T093325Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :e6b9626c-4769-11d9-9636-b4b242071a07 SUMMARY :Boxing Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20071226 DTEND ;VALUE=DATE :20071227 DTSTAMP :20041206T093331Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :eed602a2-4769-11d9-9c29-87e14bef7e97 SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 DTSTART ;VALUE=DATE :20080101 DTEND ;VALUE=DATE :20080102 DTSTAMP :20041206T093345Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :de525990-4768-11d9-b210-dbb23e96122f SUMMARY :New Year's day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040101 DTEND ;VALUE=DATE :20040102 DTSTAMP :20041206T092559Z LAST-MODIFIED :20041207T102901Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :eaabc7bc-4768-11d9-a9f0-d813f0b4250b SUMMARY :Good Friday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040409 DTEND ;VALUE=DATE :20040410 DTSTAMP :20041206T092625Z LAST-MODIFIED :20041207T102903Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :f3741142-4768-11d9-90f2-b75bdc777a72 SUMMARY :Easter Monday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040412 DTEND ;VALUE=DATE :20040413 DTSTAMP :20041206T092637Z LAST-MODIFIED :20041207T102903Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :ffac1e82-4768-11d9-af34-c8169769d183 SUMMARY :Early May Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040503 DTEND ;VALUE=DATE :20040504 DTSTAMP :20041206T092702Z LAST-MODIFIED :20041207T102903Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :06af693c-4769-11d9-88da-f9a496177710 SUMMARY :Spring Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040531 DTEND ;VALUE=DATE :20040601 DTSTAMP :20041206T092714Z LAST-MODIFIED :20041207T102904Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :0fcfe9c4-4769-11d9-b1de-afc927cc7b57 SUMMARY :Summer Bank Holiday STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20041207T102901 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20040830 DTEND ;VALUE=DATE :20040831 DTSTAMP :20041206T092731Z LAST-MODIFIED :20041207T102904Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT BEGIN:VEVENT UID :359d52c2-4769-11d9-9cd3-fde74dbfad50 SUMMARY :New Year's Day STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X-MOZILLA-LASTALARMACK :20050103T010338 X-MOZILLA-RECUR-DEFAULT-INTERVAL :0 DTSTART ;VALUE=DATE :20050103 DTEND ;VALUE=DATE :20050104 DTSTAMP :20041206T092833Z LAST-MODIFIED :20050103T010338Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :971445858 SUMMARY :Christmas Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20021225 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :925921922 SUMMARY :Boxing Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20021226 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :936923338 SUMMARY :New Year's Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030101 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :962980365 SUMMARY :Good Friday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030418 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :909072250 SUMMARY :Easter Monday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030421 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :940352282 SUMMARY :May Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030505 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :975821516 SUMMARY :Spring Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030526 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :902762343 SUMMARY :Summer Bank Holiday CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20030825 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :956630271 SUMMARY :Christmas Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20031225 DTSTAMP :20020430T114937Z END:VEVENT END:VCALENDAR BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :911737808 SUMMARY :Boxing Day CATEGORIES :Holidays CLASS :PUBLIC DTSTART ;VALUE=DATE :20031226 DTSTAMP :20020430T114937Z END:VEVENT BEGIN:VEVENT ORGANIZER:Mailto:B@example.com ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;CN=BIG A:Mailto:A@example.com ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=B:Mailto:B@example.com ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=C:Mailto:C@example.com ATTENDEE;RSVP=TRUE;CUTYPE=INDIVIDUAL;CN=Hal:Mailto:D@example.com ATTENDEE;RSVP=FALSE;CUTYPE=ROOM:conf_Big@example.com ATTENDEE:conf_Big1@example.com ATTENDEE;ROLE=NON-PARTICIPANT;RSVP=FALSE:Mailto:E@example.com DTSTAMP:19970611T190000Z DTSTART:19970701T190000Z DTEND:19970701T193000Z SUMMARY:Conference UID:calsrv.example.com-873970198738777@example.com SEQUENCE:1 STATUS:CONFIRMED END:VEVENT END:VCALENDARTie-iCal-0.15/t/d_keeptidy.t000444000000000000 420311635724214 16267 0ustar00unknownunknown000000000000#!/usr/bin/env perl -w use strict; use Test; BEGIN { plan tests => 5 } open ICS, ">test.ics"; while () { print ICS $_ } close ICS; use Tie::iCal; # TIEHASH ok(tie my %events, 'Tie::iCal', "test.ics", 'debug' => 0); # DELETE delete $events{'1ce81410-4769-11d9-8693-ee0b0a9128b1'}; ok(!exists $events{'1ce81410-4769-11d9-8693-ee0b0a9128b1'}); # STORE $events{'A-UNIQUE-ID'} = [ 'VEVENT', { 'URL' => 'http//myurl.com', 'SUMMARY' => 'my event', 'CLASS' => 'PRIVATE', 'LOCATION' => 'my location', 'X' => [{'MEMBER' => 'AlarmEmailAddress'}, 'me@myaddress'], 'STATUS' => 'TENTATIVE', 'DTSTAMP' => '20050116T154856Z', 'DTEND' => '20050118T170000Z', 'VALARM' => [ { 'TRIGGER' => [{'VALUE' => 'DURATION'}, '-PT1S'] } ], 'DESCRIPTION' => 'my note', 'X-MOZILLA-ALARM-DEFAULT-LENGTH' => '0', 'RRULE' => { 'FREQ' => 'WEEKLY', 'BYDAY' => [ 'TU', 'WE', 'TH' ], 'INTERVAL' => '1' }, 'EXDATE' => '20050118T000000', 'DTSTART' => '20050118T160000Z', 'ATTENDEE' => [ [{'CN' => 'BIG A','ROLE' => 'CHAIR','PARTSTAT' => 'ACCEPTED'},'MailtoA@example.com'], [{'CN' => 'B','RSVP' => 'TRUE','CUTYPE' => 'INDIVIDUAL'},'MailtoB@example.com'], ['MailtoB@example.com'] ] } ]; my ($comp2, $hash2) = @{$events{'A-UNIQUE-ID'}}; ok($comp2 eq 'VEVENT'); ok(${$hash2}{'LOCATION'} eq 'my location'); # CLEAR %events = (); ok(-z 'test.ics'); untie %events; #unlink 'test.ics'; exit; __END__ BEGIN:VCALENDAR VERSION :2.0 PRODID :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN BEGIN:VEVENT UID :413dd998-67d6-11d9-9a33-e4a59cf11a95 SUMMARY :my event DESCRIPTION :my note LOCATION :my location URL :http://myurl.com STATUS :TENTATIVE CLASS :PRIVATE X-MOZILLA-ALARM-DEFAULT-LENGTH :0 X ;MEMBER=AlarmEmailAddress :me@myaddress RRULE :FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,WE,TH EXDATE :20050118T000000 DTSTART :20050118T160000Z DTEND :20050118T170000Z DTSTAMP :20050116T154856Z BEGIN:VALARM TRIGGER ;VALUE=DURATION :-PT1S END:VALARM END:VEVENT END:VCALENDAR