#!/usr/bin/perl -Tw # # Exchange Calendar to iCal webcal link # David McNett http://slacker.com/~nugget/ # # $Id: exchange_calendar_dump,v 1.5 2006/03/28 01:05:28 nugget Exp $ # # This script is suitable for use either as a directly-run CGI script or as a # cronned dump to a static file. It's purpose is to export a user calendar # that's maintained within Microsoft Exchange Server to a form which is # subscribe-able from Apple's iCal or Mozilla Sunbird. # # With this script, a user can manage their work calendar within MS Exchange # but still have read-only access (with alarms) inside iCal or Sunbird. # # Requires fetchmail and a web server (to publish the webcal link) # # First, set up fetchmail with a ~/.fetchmailrc that resembles this: # # set logfile /home/nugget/fetchmail.log # defaults proto imap # # poll imapserver.example.com # user "imapusername" # pass "imappassword" # folder "Calendar" # ssl # keep # fetchall # mda /bin/cat # # # Then set up a crontab entry to periodically run this script and pipe the # output to a file which is exposed on your web server: # # */15 * * * * $HOME/bin/exchange_calendar_dump > /tmp/calendar.tmp \ # && mv /tmp/calendar.tmp $HOME/public_html/calendar.ics # # Once you've got that going, you should see the calendar.ics file # automatically populated with all the events in your Exchange calendar. # You can then subscribe to it by opening up the appropriate url in # iCal or Sunbird: # # webcal://yourwebserver.example.com/~username/calendar.ics # use strict; $ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin'; open DUMP, "/usr/local/bin/fetchmail|" or die "Unable to run fetchmail"; my $spititout = 0; my $dtstart = 0; print "BEGIN:VCALENDAR\n"; while() { my $buf = $_; if($buf =~ /^BEGIN:VEVENT$/) { $spititout = 1; $dtstart = 0; } if($spititout>0) { if($buf =~ /^DTSTART[^:]+:(\d\d\d\d\d\d\d\d)T000000/) { $buf = "DTSTART:$1\n"; $dtstart = $1; } elsif($buf =~ /^DTEND[^:]+:(\d\d\d\d\d\d\d\d)T000000/) { my $dtend = $1; if($dtstart != 0) { my $days = $dtend - $dtstart; $buf = "DURATION:P" . $days . "D\n"; } } elsif($buf =~ /^ACTION:DISPLAY$/) { $buf = "ACTION:AUDIO\nATTACH;VALUE=URI:Morse\n"; } print $buf; } if($buf =~ /^END:VEVENT$/) { $spititout = 0; } } close DUMP; print "END:VCALENDAR\n"; exit ($? >> 8); # (c) Copyright 2006 David McNett . All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # -- # Yes, it's sort of silly when the license is longer than the code but # I think it's better to be explicit so there's no confusion about how this # stuff can be re-used. I'd hate for people to assume it was GPL'd or # something.