| 1 | module("ical", package.seeall) |
| 2 | |
| 3 | local handler = {}; |
| 4 | |
| 5 | function handler.VEVENT(ical, line) |
| 6 | local k,v = line:match("^(%w+):(.*)$"); |
| 7 | local curr_event = ical[#ical]; |
| 8 | if k and v then |
| 9 | curr_event._last_key = k; |
| 10 | curr_event[k] = v; |
| 11 | elseif line:sub(1,1) == " " then |
| 12 | curr_event[curr_event._last_key] = curr_event[curr_event._last_key]..line:sub(2); |
| 13 | return; |
| 14 | end |
| 15 | |
| 16 | if k == "DTSTAMP" then |
| 17 | local t = {}; |
| 18 | t.year, t.month, t.day = v:match("^(%d%d%d%d)(%d%d)(%d%d)"); |
| 19 | t.hour, t.min, t.sec = v:match("T(%d%d)(%d%d)(%d%d)Z$"); |
| 20 | for k,v in pairs(t) do t[k] = tonumber(v); end |
| 21 | curr_event.when = os.time(t); |
| 22 | end |
| 23 | end |
| 24 | |
| 25 | function load(data) |
| 26 | local ical, stack = {}, {}; |
| 27 | local line_num = 0; |
| 28 | |
| 29 | -- Parse |
| 30 | local hold_buffer; |
| 31 | for line in data:gmatch("(.-)[\r\n]+") do |
| 32 | line_num = line_num + 1; |
| 33 | if line:match("^BEGIN:") then |
| 34 | local type = line:match("^BEGIN:(%S+)"); |
| 35 | table.insert(stack, type); |
| 36 | table.insert(ical, { type = type }); |
| 37 | elseif line:match("^END:") then |
| 38 | if stack[#stack] ~= line:match("^END:(%S+)") then |
| 39 | return nil, "Parsing error, expected END:"..stack[#stack].." before line "..line_num; |
| 40 | end |
| 41 | table.remove(stack); |
| 42 | elseif handler[stack[#stack]] then |
| 43 | handler[stack[#stack]](ical, (hold_buffer or "")..line); |
| 44 | end |
| 45 | end |
| 46 | |
| 47 | -- Return calendar |
| 48 | return ical; |
| 49 | end |
| 50 | |
| 51 | |
| 52 | return _M; |