You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/korganizer/ical2vcal.in

455 lines
11 KiB

#! @PERL@
# THE ABOVE LINE SHOULD POINT TO YOUR PERL EXECUTABLE!
# ical2vcal
# (c) 1998 Preston Brown
# Part of the KOrganizer Project
#
# This utility will read ~/.calendar in the ical format as input, and output
# a file in the versit vCalendar format with a .vcs extension.
#
# This code is covered by the GNU Public License. Please see the file
# COPYING for more information.
#
# MINIMAL ERROR CHECKING! HIGHLY PRIMITIVE! YOU HAVE BEEN WARNED!
# open the calendar.
$home = $ENV{"HOME"};
$pcount = 0;
$exitstatus = 0;
$filename = "$home/.calendar";
if (defined($ARGV[0]) && defined($ARGV[1])) {
$filename = $ARGV[0];
$outfilename = $ARGV[1];
} elsif (defined($ARGV[0])) {
$outfilename = $ARGV[0];
} else {
exit -1;
}
if (!open(ICALFILE, $filename)) {
exit -1;
}
if (!open(VCALFILE, ">$outfilename")) {
exit -1;
}
$line = <ICALFILE>;
&write_header;
if ($line =~ /Calendar(\s+)\[v/) {
while ($line = &getLine) {
if (($line =~ /^Appt/) || ($line =~ /^Note/)) {
&process_appointment;
&write_appointment;
} else {
# silently skip line
}
}
} else {
# not a ical file?!
exit -2;
}
close(ICALFILE);
close(VCALFILE);
sub getLine
{
$_ = <ICALFILE>;
if (!defined($_)) {
&write_footer;
exit $exitstatus;
}
s/\\\[/\(/g;
s/\\\]/\)/g;
$pcount += tr/\[//;
$pcount -= tr/\]//;
return $_;
}
sub process_appointment
{
undef(%curappt);
# this is a count of the total # of parentheses.
while ($pcount) {
$line = &getLine;
# check to see if more is left to be processed.
if ($pcount > 0) {
# process the line.
if ($line =~ /^Start/) {
# start time (minutes since midnight)
$_ = $line;
($totalmin) = /\[(\d+)\]/;
$min = $totalmin % 60;
$hour = int ($totalmin / 60);
$curappt{"starthour"} = $hour;
$curappt{"startmin"} = $min;
} elsif ($line =~ /^Length/) {
# time length (minutes)
$_ = $line;
($lengthmin) = /\[(\d+)\]/;
$min = $lengthmin % 60;
$hour = int ($lengthmin / 60);
$curappt{"endhour"} = $hour;
$curappt{"endmin"} = $min;
} elsif ($line =~ /^Uid/) {
# unique identifier
$_ = $line;
($uid) = /\[(.+)\]/;
$curappt{"uid"} = $uid ;
} elsif ($line =~ /^Owner/) {
# appointment's owner
$_ = $line;
($attendee) = /\[(\w+)\]/;
$curappt{"attendee"} = $attendee;
} elsif ($line =~ /^Contents/) {
# description
$description = "";
$_ = $line;
# special case where it's all in one place:
if (/\[(.*)\]/) {
$summary = $1;
} else {
($summary) = /\[(.*)/;
$_ = &getLine;
while (!(/\]$/)) {
chop;
$description = $description . " " . $_;
$_ = &getLine;
}
/(.*)\]$/;
$description = $description . $1;
}
$curappt{"summary"} = $summary;
if (length($description) > 0) {
$summary = $summary . "...";
$curappt{"description"} = $description;
}
} elsif ($line =~ /^Text/) {
$description = "";
$_ = $line;
if (/\[\d+\s+\[(.*)\]\]/) {
$summary = $1;
} else {
($summary) = /\[\d+\s+\[(.*)$/;
$_ = &getLine;
while (!(/\]$/)) {
chop;
$description = $description . " " . $_;
$_ = &getLine;
}
/^(.*)\]\]/;
$description = $description . $1;
}
$curappt{"summary"} = $summary;
if (length($description) > 0) {
$summary = $summary . "...";
$curappt{"description"} = $description;
}
} elsif ($line =~ /^Alarms/) {
$_ = $line;
($alarm) = /(\d+)\]/;
$curappt{"alarmtime"} = $alarm;
} elsif ($line =~ /^Todo/) {
$curappt{"todo"} = 1;
} elsif ($line =~ /^Dates/) {
# dates to occur on
&process_dates;
} elsif ($line =~ /^\]/) {
# do nothing
} elsif ($line =~ /^Hilite/) {
# do nothing
} elsif ($line =~ /^Remind/) {
# do nothing
} elsif ($line =~ /^Done/) {
$curappt{"done"}=1;
} else {
# do nothing
;
}
} # if $pcount > 0
} # while pcount
if (defined($curappt{"starthour"})) {
# fix up end time, just peg it at the end of the day
$endhour = $curappt{"starthour"} + $curappt{"endhour"};
$endmin = $curappt{"startmin"} + $curappt{"endmin"};
$endhour = $endhour + int ($endmin / 60);
$endmin = $endmin % 60;
$curappt{"endhour"} = $endhour;
$curappt{"endmin"} = $endmin;
if ($endhour >= 24) {
$curappt{"endhour"} = 23;
$curappt{"endmin"} = 55;
}
}
}
sub output
{
$outline = shift(@_);
print VCALFILE $outline;
print VCALFILE "\n";
# print($outline);
# print("\n");
}
sub write_header
{
output("BEGIN:VCALENDAR");
output("PRODID:-//K Desktop Environment//NONSGML KOrganizer//EN");
output("VERSION:1.0");
}
sub write_footer
{
output("END:VCALENDAR");
}
sub write_appointment
{
if (defined($curappt{"tossme"})) {
return;
}
if (defined($curappt{"todo"})) {
output("BEGIN:VTODO");
} else {
output("BEGIN:VEVENT");
}
$tmpstr = &date_to_str($curappt{"startyear"},
$curappt{"startmonth"},
$curappt{"startday"});
if (defined($curappt{"starthour"})) {
$tmpstr = $tmpstr . &time_to_str($curappt{"starthour"},
$curappt{"startmin"});
} else {
$tmpstr = $tmpstr . &time_to_str("0","0");
}
output("DCREATED:" . $tmpstr);
output("UID:" . $curappt{"uid"});
output("SEQUENCE:0");
output("LAST-MODIFIED:$tmpstr");
output("DTSTART:$tmpstr");
if (defined($curappt{"starthour"})) {
$tmpstr = &date_to_str($curappt{"startyear"},
$curappt{"startmonth"},
$curappt{"startday"}) .
&time_to_str($curappt{"endhour"},
$curappt{"endmin"});
}
output("DTEND:$tmpstr");
if (defined($curappt{"summary"})) {
$summary = $curappt{"summary"};
output("SUMMARY:$summary");
}
if (defined($curappt{"description"})) {
$description = $curappt{"description"};
output("DESCRIPTION:$description");
}
if (defined($curappt{"attendee"})) {
$attendee = "ATTENDEE;ROLE=OWNER:" . $curappt{"attendee"};
output($attendee);
}
if (defined($curappt{"alarm"})) {
}
if (defined($curappt{"repeats"})) {
# wow what a mess
$rule = "RRULE:";
if ($curappt{"repeats"} eq "DAILY") {
$rule = $rule . "D" . $curappt{"period"};
} elsif ($curappt{"repeats"} eq "WEEKLY") {
$rule = $rule . "W1" . " ";
$rule = $rule . $curappt{"weekdays"};
} elsif ($curappt{"repeats"} eq "MONTHLY") {
$rule = $rule . "MD" . $curappt{"period"};
$rule = $rule . " " . $curappt{"startday"};
}
if ($curappt{"endrepeat"} && ($curappt{"endrepeat"} =~ /T/)) {
$rule = $rule . " " . $curappt{"endrepeat"};
} elsif ($curappt{"endrepeat"}) {
$rule = $rule . " \#" . $curappt{"endrepeat"};
} else {
$rule = $rule . " \#0";
}
output($rule);
}
if (defined($curappt{"exceptions"})) {
$exceptions = "EXDATE:" . $curappt{"exceptions"};
chop($exceptions);
output($exceptions);
}
if (defined($curappt{"todo"})) {
if (defined($curappt{"done"})) {
output("STATUS:COMPLETED");
} else {
output("STATUS:NEEDS ACTION");
}
}
output("CLASS:PUBLIC");
output("PRIORITY:0");
output("TRANSP:0");
output("RELATED-TO:0");
if (defined($curappt{"todo"})) {
output("END:VTODO\n");
} else {
output("END:VEVENT\n");
}
}
sub date_to_str
{
$year = shift(@_);
$month = shift(@_);
$day = shift(@_);
my($datestr);
$datestr = sprintf("%04d%02d%02d",$year,$month,$day);
return $datestr;
}
sub time_to_str
{
$hour = shift(@_);
$min = shift(@_);
my($timestr);
$timestr = sprintf("T%02d%02d00",$hour,$min);
return $timestr;
}
sub process_dates
{
# first, test for single
$_ = $line;
if (/\[Single/) {
&repeat_none;
} elsif (/\[Days/) {
&repeat_daily;
} elsif (/\[WeekDays/) {
&repeat_weekly;
} elsif (/\[Months/) {
&repeat_monthly;
} elsif (/\[ComplexMonths/) {
$exitstatus = 1;
#printf("WARNING: complex repeating month entry detected, we don't support.\n");
#printf("converting to a single occurrence on the original start date.\n");
$line = &getLine;
&repeat_none;
} elsif (/\[Empty/) {
# silently toss
$curappt{"tossme"} = "TRUE";
} else {
$exitstatus = 1;
#print "didn't understand line: $_";
}
while ($line = &getLine) {
if ($line =~ /^\]/) {
return;
} elsif ($line =~ /^Finish/) {
($day, $month, $year) = /(\d+)\/(\d+)\/(\d+)/;
$curappt{"endrepeat"} = &date_to_str($year, $month, $day);
$curappt{"endrepeat"} = $curappt{"endrepeat"} . &time_to_str("0","0");
} elsif ($line =~ /^Deleted/) {
($day, $month, $year) = /(\d+)\/(\d+)\/(\d+)/;
if (defined($curappt{"exceptions"})) {
$curappt{"exceptions"} = $curappt{"exceptions"} .
&date_to_str($year, $month, $day) . ";";
} else {
$curappt{"exceptions"} = &date_to_str($year, $month, $day) .
";";
}
} else {
$exitstatus = 1;
#print "trashed line: $line";
}
}
}
sub repeat_none
{
# just a one time shot
($day, $month, $year) = /(\d+)\/(\d+)\/(\d+)/;
$curappt{"startmonth"} = $month;
$curappt{"startday"} = $day;
$curappt{"startyear"} = $year;
}
sub repeat_daily
{
# repeats on a daily basis
$curappt{"repeats"} = "DAILY";
($skip) = /(\d+)$/;
$curappt{"period"} = $skip;
$line = &getLine;
($day, $month, $year) = /(\d+)\/(\d+)\/(\d+)/;
$curappt{"startmonth"} = $month;
$curappt{"startday"} = $day;
$curappt{"startyear"} = $year;
}
sub repeat_weekly
{
# repeats on a weekly basis, a few days a week
$curappt{"repeats"} = "WEEKLY";
$startofdates = index($_,"WeekDays") + length("WeekDays");
$endofdates = index($_,"Months");
$datestr = substr($_,$startofdates,($endofdates-$startofdates));
$datestr =~ s/^\s+//;
@days = split(/\s+/,$datestr);
$datestr = "";
foreach $date (@days) {
if ($date == 1) {
$datestr = $datestr . "SU ";
} elsif ($date == 2) {
$datestr = $datestr . "MO ";
} elsif ($date == 3) {
$datestr = $datestr . "TU ";
} elsif ($date == 4) {
$datestr = $datestr . "WE ";
} elsif ($date == 5) {
$datestr = $datestr . "TH ";
} elsif ($date == 6) {
$datestr = $datestr . "FR ";
} elsif ($date == 7) {
$datestr = $datestr . "SA ";
}
}
# remove one trailing whitespace
chop($datestr);
$curappt{"weekdays"} = $datestr;
$line = &getLine;
($day, $month, $year) = /(\d+)\/(\d+)\/(\d+)/;
$curappt{"startmonth"} = $month;
$curappt{"startday"} = $day;
$curappt{"startyear"} = $year;
}
sub repeat_monthly
{
# repeats on a daily basis
$curappt{"repeats"} = "MONTHLY";
($skip) = /(\d+)$/;
$curappt{"period"} = $skip;
$line = &getLine;
($day, $month, $year) = /(\d+)\/(\d+)\/(\d+)/;
$curappt{"startmonth"} = $month;
$curappt{"startday"} = $day;
$curappt{"startyear"} = $year;
}