#! /usr/bin/perl -w # # Quick hack to convert the output syncml-ds-tool to something # Evolution and Google Calendar will understand. # # Unfortunately, Evolution doesn't seem to understand BASE64-coding, # nor the quoted-printable syncml-ds-tool emits, but at least this # script will use encoding a lot less than syncml-ds-tool does. # # Google Calendar had problems with a couple of my calendar entries, I # didn't see anything obviously wrong about them, and in my case I # just deleted them using Emacs... # # Your mileage will vary. Good luck :-) # # Written by Kjetil Torgrim Homme 2011 # Released into the Public Domain. # # Version 0.2 use strict; use MIME::Base64; use MIME::QuotedPrint; use Encode; use utf8; use Getopt::Long; sub usage { print STDERR <<"_end_"; Usage: $0 [--skip-rrule] This script performs rudimentary conversion of vCalendar. It does not understand recurring rules, so if you want to strip them to get a more compliant file, use --skip-rrule. _end_ exit(64); } my $skip_rrule; GetOptions("skip-rrule" => \$skip_rrule) or usage(); print "BEGIN:VCALENDAR\r\n"; print "VERSION:2.0\r\n"; my $default_charset = "US-ASCII"; while (<>) { # remove crap added by syncml-ds-tool next if /^-----(BEGIN|END) CHANGE-----/; next if /^(BEGIN|END):VCALENDAR/; if (/^VERSION:(\d).0/) { $default_charset = "US-ASCII" if $1 eq "1"; $default_charset = "UTF-8" if $1 eq "2"; next; } # Strictly speaking we should remember these values and fix # DTSTART if it doesn't specify timezone itself. next if /^TZ:/i; next if /^DAYLIGHT:/i; next if /^RRULE:/i && $skip_rrule; if (/^ATTENDEE;/i) { s/;(?:STATUS|X-STATUS|EXPECT)=.*?([;:])/$1/gi; } if (/;ENCODING=QUOTED-PRINTABLE[;:]/i) { my $prop = $_; $prop =~ s/;ENCODING=QUOTED-PRINTABLE//i; my $charset = $default_charset; if (/;CHARSET=([^;:]*)/i) { $charset = $1; $prop =~ s/;CHARSET=[^:;]*//i; } $prop =~ s/:.*//s; my $value = $_; $value =~ s/.*?://; $value =~ s/\r?\n$//; $value =~ /(.*?)=?$/; my $content = decode_qp($1); while ($value =~ /=$/) { $value = <>; last if !defined $value; $value =~ s/\r?\n$//; $value =~ /(.*?)=?$/; $content .= decode_qp($1); } $content =~ s/\r?\n/\\n/g; $content = decode($charset, $content); my $len; if ($content =~ /[:;\x00-\x1f]/) { $content = encode_base64(encode("UTF-8", $content), ""); $prop .= ";ENCODING=BASE64"; $len = 72 - (length($prop) + 4 - length($prop)%4); $len = 4 if $len < 4; } else { $content = encode("UTF-8", $content); $len = length($content); } print $prop, ":", substr($content, 0, $len), "\r\n"; while (length($content) > $len) { $content = substr($content, $len); $len = 72; last if $content eq ""; print " ", substr($content, 0, $len), "\r\n"; } } elsif (/^AALARM[;:]/) { # rewrite to VALARM (DALARM is to-do) print "BEGIN:VALARM\r\n"; print "ACTION:AUDIO\r\n"; s/\r?\n$//; # Strip any params, since they're probably not valid anyway s/;.*?:/;/; # replace with ; to simplify split below my ($x, $runTime, $snoozeTime, $repeatCount, $audioContent) = split(/;/); $runTime ||= "START"; print "TRIGGER:$runTime\r\n"; print "DURATION:$snoozeTime\r\n" if $snoozeTime; print "REPEAT:$repeatCount\r\n" if $repeatCount; print "ATTACH:$audioContent\r\n" if $audioContent; print "END:VALARM\r\n"; } else { print $_; } } print "END:VCALENDAR\r\n";