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.
455 lines
11 KiB
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;
|
|
}
|
|
|
|
|