# HG changeset patch # User Matthew Wild # Date 1256526761 0 # Node ID 11a0cbd6c2161b0eeb280205e5dec057641c793d Initial commit diff -r 000000000000 -r 11a0cbd6c216 XSF.ics --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XSF.ics Mon Oct 26 03:12:41 2009 +0000 @@ -0,0 +1,255 @@ +BEGIN:VCALENDAR +METHOD:PUBLISH +X-WR-TIMEZONE:America/Denver +PRODID:-//Apple Inc.//iCal 3.0//EN +CALSCALE:GREGORIAN +X-WR-CALNAME:XSF +VERSION:2.0 +X-WR-RELCALID:CE7E8908-829D-4649-87DE-FB436960ED5F +X-APPLE-CALENDAR-COLOR:#E51717 +BEGIN:VTIMEZONE +TZID:America/Denver +BEGIN:DAYLIGHT +TZOFFSETFROM:-0700 +TZOFFSETTO:-0600 +DTSTART:20070311T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU +TZNAME:MDT +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:-0600 +TZOFFSETTO:-0700 +DTSTART:20071104T020000 +RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU +TZNAME:MST +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:B7FF24D2-0992-436B-B301-627F84F2E346 +DTSTART;TZID=America/Denver:20081210T130000 +DTSTAMP:20081205T165043Z +SUMMARY:XMPP Council Meeting +CREATED:20081205T165036Z +DTEND;TZID=America/Denver:20081210T140000 +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:BB359785-96F8-47E9-8A78-2C43F13F639A +DTSTART;TZID=America/Denver:20081209T133000 +DTSTAMP:20081205T165051Z +SUMMARY:XSF Board Meeting +CREATED:20081205T165046Z +DTEND;TZID=America/Denver:20081209T140000 +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:D7A9EA8D-614D-44F6-838B-577794739A2E +DTSTART;TZID=America/Denver:20090107T130000 +DTSTAMP:20081211T180238Z +SUMMARY:XMPP Council Meeting +CREATED:20081211T180233Z +DTEND;TZID=America/Denver:20090107T140000 +BEGIN:VALARM +X-WR-ALARMUID:F4FBB5DA-3521-4482-9B95-A9C6EE2B75A9 +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:7AE5D5AB-1692-4A81-9E4F-DE8FBF5A1350 +DTSTART;TZID=America/Denver:20090113T133000 +DTSTAMP:20090106T205107Z +SUMMARY:Board meeting +CREATED:20090106T205104Z +DTEND;TZID=America/Denver:20090113T140000 +BEGIN:VALARM +X-WR-ALARMUID:309564AE-5635-4348-A5D8-828F3149D445 +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:1A29D476-4404-4247-B8BA-72D8F522CF18 +DTSTART;TZID=America/Denver:20090106T133000 +DTSTAMP:20090106T205125Z +SUMMARY:Board meeting +CREATED:20090106T205120Z +DTEND;TZID=America/Denver:20090106T140000 +BEGIN:VALARM +X-WR-ALARMUID:E29A5872-7199-4850-B848-227F870EA3B4 +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:7C0824FB-B70D-4791-B305-4F71AD03D45A +DTSTART;TZID=America/Denver:20090114T130000 +DTSTAMP:20090106T215640Z +SUMMARY:Council meeting +CREATED:20090106T215630Z +DTEND;TZID=America/Denver:20090114T140000 +BEGIN:VALARM +X-WR-ALARMUID:C7DE8A1D-DC31-499F-B601-09A03B595E78 +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:54A717A4-7F0B-4416-ADBD-2B061A0C801C +DTSTART;TZID=America/Denver:20090120T163000 +DTSTAMP:20090120T182935Z +SUMMARY:Last Call ends on XEP-0245 +CREATED:20090120T182928Z +DTEND;TZID=America/Denver:20090120T170000 +BEGIN:VALARM +X-WR-ALARMUID:77E28436-5438-46A5-BE2F-FD34DAF8FAF5 +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:EB6612F1-CD7B-4153-AFCC-DF4D4050DFF8 +DTSTART;TZID=America/Denver:20090121T130000 +DTSTAMP:20090120T182951Z +SUMMARY:XMPP Council meeting +CREATED:20090120T182946Z +DTEND;TZID=America/Denver:20090121T140000 +BEGIN:VALARM +X-WR-ALARMUID:10018B2F-26EB-4269-8F7C-BC78EF59F747 +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:E2878D5E-C2E5-437E-9645-FC29357677FE +DTSTART;TZID=America/Denver:20090120T133000 +DTSTAMP:20090120T183003Z +SUMMARY:XSF Board meeting +CREATED:20090120T182959Z +DTEND;TZID=America/Denver:20090120T140000 +BEGIN:VALARM +X-WR-ALARMUID:11C85270-89E7-4A0F-9A2F-D1F6423D3C62 +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:707BDAA4-E198-45D9-ACC3-65DE14568A28 +DTSTART;TZID=America/Denver:20090212T130000 +DTSTAMP:20090128T174352Z +SUMMARY:XSF Member meeting +CREATED:20090128T174346Z +DTEND;TZID=America/Denver:20090212T140000 +BEGIN:VALARM +X-WR-ALARMUID:88D6DC29-CDB4-4C5A-BB2C-CFA95A15C85F +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:7F548632-2A98-41AC-A886-2BFDDB79E518 +DTSTART;TZID=America/Denver:20090218T130000 +DTSTAMP:20090217T180836Z +SUMMARY:XMPP Council meeting +CREATED:20090217T180831Z +DTEND;TZID=America/Denver:20090218T140000 +BEGIN:VALARM +X-WR-ALARMUID:4444F299-C0D7-45F2-B19B-C7E50AF62B45 +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:FBFFEEBF-22C2-4DE1-B12E-A60C325CF9ED +DTSTART;TZID=America/Denver:20090225T130000 +DTSTAMP:20090219T182044Z +SUMMARY:XMPP Council meeting +CREATED:20090219T182039Z +DTEND;TZID=America/Denver:20090225T140000 +BEGIN:VALARM +X-WR-ALARMUID:57081D2A-92C5-4110-907C-0BF80CACE5E1 +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:E4AF11E5-D75D-4E1A-8F51-617BEE4F53D7 +DTSTART;TZID=America/Denver:20090304T130000 +DTSTAMP:20090225T210636Z +SUMMARY:XMPP Council meeting +CREATED:20090225T210631Z +DTEND;TZID=America/Denver:20090304T140000 +BEGIN:VALARM +X-WR-ALARMUID:F342B40C-96C7-4049-9CA6-1894C30FD23B +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:2 +TRANSP:OPAQUE +UID:BCD089B6-EAD6-4C05-9A26-535F8FED6B52 +DTSTART;TZID=America/Denver:20090312T140000 +DTSTAMP:20090309T204141Z +SUMMARY:Monthly XMPP Meeting +CREATED:20090309T204133Z +DTEND;TZID=America/Denver:20090312T150000 +BEGIN:VALARM +X-WR-ALARMUID:3D7359C9-A4EF-4E21-A883-3CDF3207DB2D +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +BEGIN:VEVENT +SEQUENCE:1 +TRANSP:OPAQUE +UID:7708568E-B195-4154-AC67-6E6F7F9F839F +DTSTART;TZID=America/Denver:20090318T140000 +DTSTAMP:20090310T205549Z +SUMMARY:XMPP Council meeting +CREATED:20090304T225315Z +DTEND;TZID=America/Denver:20090318T150000 +BEGIN:VALARM +X-WR-ALARMUID:887F44EB-AD6C-4E46-BD4C-292A6C65983B +ACTION:AUDIO +TRIGGER:-PT15M +ATTACH;VALUE=URI:Basso +END:VALARM +END:VEVENT +END:VCALENDAR diff -r 000000000000 -r 11a0cbd6c216 ical.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ical.lua Mon Oct 26 03:12:41 2009 +0000 @@ -0,0 +1,46 @@ +module("ical", package.seeall) + +local handler = {}; + +function handler.VEVENT(ical, line) + local k,v = line:match("^(%w+):(.*)$"); + local curr_event = ical[#ical]; + if k and v then + curr_event[k] = v; + end + + if k == "DTSTAMP" then + local t = {}; + t.year, t.month, t.day, t.hour, t.min, t.sec = v:match("^(%d%d%d%d)(%d%d)(%d%d)T(%d%d)(%d%d)(%d%d)Z$"); + for k,v in pairs(t) do t[k] = tonumber(v); end + curr_event.when = os.time(t); + end +end + +function load(data) + local ical, stack = {}, {}; + local line_num = 0; + + -- Parse + for line in data:gmatch("(.-)[\r\n]+") do + line_num = line_num + 1; + if line:match("^BEGIN:") then + local type = line:match("^BEGIN:(%S+)"); + table.insert(stack, type); + table.insert(ical, { type = type }); + elseif line:match("^END:") then + if stack[#stack] ~= line:match("^END:(%S+)") then + return nil, "Parsing error, expected END:"..stack[#stack].." before line "..line_num; + end + table.remove(stack); + elseif handler[stack[#stack]] then + handler[stack[#stack]](ical, line); + end + end + + -- Return calendar + return ical; +end + + +return _M; diff -r 000000000000 -r 11a0cbd6c216 serialization.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/serialization.lua Mon Oct 26 03:12:41 2009 +0000 @@ -0,0 +1,70 @@ +-- Prosody IM v0.4 +-- Copyright (C) 2008-2009 Matthew Wild +-- Copyright (C) 2008-2009 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + +local string_rep = string.rep; +local type = type; +local tostring = tostring; +local t_insert = table.insert; +local t_concat = table.concat; +local error = error; +local pairs = pairs; + +module "serialization" + +local indent = function(i) + return string_rep("\t", i); +end +local function basicSerialize (o) + if type(o) == "number" or type(o) == "boolean" then + return tostring(o); + else -- assume it is a string -- FIXME make sure it's a string. throw an error otherwise. + return (("%q"):format(tostring(o)):gsub("\\\n", "\\n")); + end +end +local function _simplesave(o, ind, t, func) + if type(o) == "number" then + func(t, tostring(o)); + elseif type(o) == "string" then + func(t, (("%q"):format(o):gsub("\\\n", "\\n"))); + elseif type(o) == "table" then + func(t, "{\n"); + for k,v in pairs(o) do + func(t, indent(ind)); + func(t, "["); + func(t, basicSerialize(k)); + func(t, "] = "); + if ind == 0 then + _simplesave(v, 0, t, func); + else + _simplesave(v, ind+1, t, func); + end + func(t, ",\n"); + end + func(t, indent(ind-1)); + func(t, "}"); + elseif type(o) == "boolean" then + func(t, (o and "true" or "false")); + else + error("cannot serialize a " .. type(o)) + end +end + +function append(t, o) + _simplesave(o, 1, t, t.write or t_insert); + return t; +end + +function serialize(o) + return t_concat(append({}, o)); +end + +function deserialize(str) + error("Not implemented"); +end + +return _M; diff -r 000000000000 -r 11a0cbd6c216 test.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test.lua Mon Oct 26 03:12:41 2009 +0000 @@ -0,0 +1,16 @@ +require "ical" +if arg[1] == "-v" then + require "serialization" +end + +events = ical.load(io.open("XSF.ics" or arg[1]):read("*a")) + +if arg[1] == "-v" then + print(serialization.serialize(events)) +end + +for i, event in ipairs(events) do + if event.type == "VEVENT" then + print(event.when and os.date("!%c", event.when) or "Unknown", event.SUMMARY); + end +end