vpim 0.658 → 0.695
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +6 -0
- data/bin/reminder +17 -11
- data/bin/rrule +0 -0
- data/lib/vpim/agent/app.rb +194 -0
- data/lib/vpim/agent/atomize.rb +101 -0
- data/lib/vpim/agent/calendars.rb +173 -0
- data/lib/vpim/agent/main.rb +327 -0
- data/lib/vpim/agent/scraps.rb +292 -0
- data/lib/vpim/repo.rb +81 -1
- data/lib/vpim/rrule.rb +0 -0
- data/lib/vpim/version.rb +2 -2
- data/samples/cmd-itip.rb +0 -0
- data/samples/ics-dump.rb +0 -0
- data/samples/ics-to-rss.rb +0 -0
- data/samples/mutt-aliases-to-vcf.rb +0 -0
- data/samples/reminder.rb +17 -11
- data/samples/rrule.rb +0 -0
- data/samples/vcf-dump.rb +0 -0
- data/samples/vcf-lines.rb +0 -0
- data/samples/vcf-to-ics.rb +0 -0
- data/samples/vcf-to-mutt.rb +0 -0
- data/test/test_agent_app.rb +74 -0
- data/test/test_agent_atomize.rb +84 -0
- data/test/test_agent_calendars.rb +128 -0
- data/test/test_all.rb +1 -1
- data/test/test_date.rb +0 -0
- data/test/test_dur.rb +0 -0
- data/test/test_field.rb +0 -0
- data/test/test_ical.rb +22 -0
- data/test/test_repo.rb +44 -92
- data/test/test_rrule.rb +0 -0
- data/test/test_vcard.rb +0 -0
- metadata +14 -10
- data/lib/atom.rb +0 -728
- data/lib/atom/pub.rb +0 -206
- data/lib/atom/version.rb +0 -9
- data/lib/atom/xml/parser.rb +0 -305
- data/lib/plist.rb +0 -22
- data/lib/plist/generator.rb +0 -224
- data/lib/plist/parser.rb +0 -225
data/CHANGES
CHANGED
data/bin/reminder
CHANGED
@@ -18,8 +18,8 @@ Usage: #{$0} [where]
|
|
18
18
|
|
19
19
|
Shows events and todos occuring soon.
|
20
20
|
|
21
|
-
By default, the Apple iCal v3 calendars are used, but if a location where
|
22
|
-
|
21
|
+
By default, the Apple iCal v3 calendars are used, but if a location where .ics
|
22
|
+
files can be found is specified, any calendars found there will be used.
|
23
23
|
|
24
24
|
Options
|
25
25
|
-h,--help Print this helpful message.
|
@@ -29,6 +29,7 @@ Options
|
|
29
29
|
EOF
|
30
30
|
|
31
31
|
opt_debug = nil
|
32
|
+
opt_dump = nil
|
32
33
|
opt_verbose = nil
|
33
34
|
opt_days = 7
|
34
35
|
|
@@ -53,6 +54,9 @@ opts.each do |opt, arg|
|
|
53
54
|
|
54
55
|
when "--debug" then
|
55
56
|
opt_verbose = true
|
57
|
+
if opt_debug
|
58
|
+
opt_dump = true
|
59
|
+
end
|
56
60
|
opt_debug = true
|
57
61
|
end
|
58
62
|
end
|
@@ -64,12 +68,12 @@ if ARGV.length > 0
|
|
64
68
|
calendars << cal
|
65
69
|
end
|
66
70
|
else
|
67
|
-
Vpim::Repo::
|
71
|
+
Vpim::Repo::Apple3.new.each() do |cal|
|
68
72
|
calendars << cal
|
69
73
|
end
|
70
74
|
end
|
71
75
|
|
72
|
-
if
|
76
|
+
if opt_dump
|
73
77
|
pp ARGV
|
74
78
|
pp calendars
|
75
79
|
end
|
@@ -81,7 +85,7 @@ t0[0] = t0[1] = t0[2] = 0 # sec,min,hour = 0
|
|
81
85
|
t0 = Time.local(*t0)
|
82
86
|
t1 = t0 + opt_days * SECSPERDAY
|
83
87
|
|
84
|
-
if
|
88
|
+
if opt_dump
|
85
89
|
puts "to: #{t0}"
|
86
90
|
puts "t1: #{t1}"
|
87
91
|
end
|
@@ -95,12 +99,13 @@ all_events = []
|
|
95
99
|
all_todos = []
|
96
100
|
|
97
101
|
calendars.each do |cal|
|
98
|
-
if opt_debug; puts cal.name; end
|
102
|
+
if opt_debug; puts "Calendar: #{cal.name}"; end
|
99
103
|
|
104
|
+
# TODO - mv collection algorithm to library
|
100
105
|
begin
|
101
106
|
cal.events.each do |e|
|
102
107
|
begin
|
103
|
-
if
|
108
|
+
if opt_dump; pp e; end
|
104
109
|
if e.occurs_in?(t0, t1)
|
105
110
|
if e.summary
|
106
111
|
all_events.push(e)
|
@@ -111,12 +116,13 @@ calendars.each do |cal|
|
|
111
116
|
end
|
112
117
|
end
|
113
118
|
|
114
|
-
all_todos.concat(cal.todos)
|
119
|
+
all_todos.concat(cal.todos.to_a)
|
115
120
|
end
|
116
121
|
end
|
117
122
|
|
118
123
|
puts
|
119
124
|
|
125
|
+
# TODO - mv sorting algorithm to library
|
120
126
|
def start_of_first_occurrence(t0, t1, e)
|
121
127
|
e.occurrences(t1) do |t|
|
122
128
|
# An event might start before t0, but end after it..., in which case
|
@@ -137,7 +143,7 @@ all_events.each do |e|
|
|
137
143
|
|
138
144
|
if opt_verbose
|
139
145
|
if e.description; puts " description=#{e.description}"; end
|
140
|
-
if e.comments
|
146
|
+
if e.comments.any?; puts " comment=#{e.comments.first}"; end
|
141
147
|
if e.location; puts " location=#{e.location}"; end
|
142
148
|
if e.status; puts " status=#{e.status}"; end
|
143
149
|
if e.dtstart; puts " dtstart=#{e.dtstart}"; end
|
@@ -145,15 +151,15 @@ all_events.each do |e|
|
|
145
151
|
end
|
146
152
|
|
147
153
|
i = 1
|
148
|
-
e.occurrences
|
154
|
+
e.occurrences(t1) do |t|
|
149
155
|
# An event might start before t0, but end after it..., in which case
|
150
156
|
# we are still interested.
|
151
157
|
dstr = ''
|
152
158
|
if e.duration
|
153
|
-
d = e.duration
|
154
159
|
dstr = " for #{Vpim::Duration.new(e.duration).to_s}"
|
155
160
|
end
|
156
161
|
|
162
|
+
# TODO - mv to library, as variant of occurs_in?
|
157
163
|
if (t + (e.duration || 0)) >= t0
|
158
164
|
puts " ##{i} on #{t}#{dstr}"
|
159
165
|
i += 1
|
data/bin/rrule
CHANGED
File without changes
|
@@ -0,0 +1,194 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (C) 2009 Sam Roberts
|
3
|
+
|
4
|
+
This library is free software; you can redistribute it and/or modify it
|
5
|
+
under the same terms as the ruby language itself, see the file COPYING for
|
6
|
+
details.
|
7
|
+
=end
|
8
|
+
|
9
|
+
require 'sinatra'
|
10
|
+
require 'vpim/agent/atomize'
|
11
|
+
require 'vpim/repo'
|
12
|
+
require 'vpim/view'
|
13
|
+
|
14
|
+
require 'cgi'
|
15
|
+
|
16
|
+
configure do
|
17
|
+
server = Sinatra::Application.server
|
18
|
+
set :server, Proc.new {
|
19
|
+
if ENV.include?("PHP_FCGI_CHILDREN")
|
20
|
+
break "fastcgi" # Must NOT be the correct class name!
|
21
|
+
elsif ENV.include?("REQUEST_METHOD")
|
22
|
+
break "cgi" # Must NOT be the correct class name!
|
23
|
+
else
|
24
|
+
# Fall back on whatever it was going to be.
|
25
|
+
server
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
# I could wrap the Repo/Calendar/Atomize in a small class that would memoize
|
31
|
+
# ical data and atom output. Maybe even do an HTTP head for fast detection of
|
32
|
+
# change? Does a calendar have updated information? Can we memoize atom when
|
33
|
+
# ics doesn't change?
|
34
|
+
|
35
|
+
module Vpim
|
36
|
+
module Agent
|
37
|
+
module App
|
38
|
+
def self.atomize(caluri, feeduri)
|
39
|
+
repo = Vpim::Repo::Uri.new(caluri)
|
40
|
+
cal = repo.find{true}
|
41
|
+
cal = View.week(cal)
|
42
|
+
feed = Agent::Atomize.calendar(cal, feeduri, caluri, cal.name)
|
43
|
+
return feed.to_xml, Agent::Atomize::MIME
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
get '/ics' do
|
50
|
+
from = env['QUERY_STRING']
|
51
|
+
|
52
|
+
url = URI.parse(request.url)
|
53
|
+
url.query = nil
|
54
|
+
url_base = url.to_s
|
55
|
+
url_atom = nil
|
56
|
+
|
57
|
+
@url_ics = from # ics from here
|
58
|
+
@url_atom = nil
|
59
|
+
|
60
|
+
if not from.empty?
|
61
|
+
# Error out if we can't atomize the feed
|
62
|
+
Vpim::Agent::App.atomize(from, "http://example.com")
|
63
|
+
|
64
|
+
url = URI.parse(request.url)
|
65
|
+
url.path << "/atom"
|
66
|
+
url_atom = url.to_s
|
67
|
+
end
|
68
|
+
|
69
|
+
@url_base = url_base # clean input form
|
70
|
+
@url_atom = url_atom # atomized ics from here
|
71
|
+
|
72
|
+
haml :"ics.haml"
|
73
|
+
end
|
74
|
+
|
75
|
+
post '/ics' do
|
76
|
+
from = params[:url]
|
77
|
+
url = URI.parse(request.url)
|
78
|
+
url.query = from
|
79
|
+
redirect url.to_s
|
80
|
+
end
|
81
|
+
|
82
|
+
# When we support other forms..
|
83
|
+
#get '/ics/:form' do
|
84
|
+
# form = params[:form]
|
85
|
+
get '/ics/atom' do
|
86
|
+
from = env['QUERY_STRING']
|
87
|
+
port = env["SERVER_PORT"].to_i
|
88
|
+
here = request.url
|
89
|
+
|
90
|
+
if from.empty?
|
91
|
+
url = URI.parse(here)
|
92
|
+
url.path.sub(/atom$/, "")
|
93
|
+
redirect here.to_s
|
94
|
+
end
|
95
|
+
|
96
|
+
xml, xmltype = Vpim::Agent::App.atomize(from, here)
|
97
|
+
|
98
|
+
content_type xmltype
|
99
|
+
body xml
|
100
|
+
end
|
101
|
+
|
102
|
+
get '/ics/style.css' do
|
103
|
+
content_type 'text/css'
|
104
|
+
sass :"ics.sass"
|
105
|
+
end
|
106
|
+
|
107
|
+
error do
|
108
|
+
@url_error = CGI.escapeHTML(env['sinatra.error'].inspect)
|
109
|
+
haml :"ics.haml"
|
110
|
+
end
|
111
|
+
|
112
|
+
use_in_file_templates!
|
113
|
+
|
114
|
+
# FIXME - hard-coded :action paths below, bad!
|
115
|
+
|
116
|
+
__END__
|
117
|
+
@@ics.sass
|
118
|
+
body
|
119
|
+
:background-color gray
|
120
|
+
:font-size medium
|
121
|
+
a
|
122
|
+
:color black
|
123
|
+
:font-style italic
|
124
|
+
a:hover
|
125
|
+
:color darkred
|
126
|
+
|
127
|
+
#header
|
128
|
+
:border-bottom 3px solid darkred
|
129
|
+
#title
|
130
|
+
:color black
|
131
|
+
:font-size large
|
132
|
+
|
133
|
+
.text
|
134
|
+
:width 80%
|
135
|
+
-#:color yellow
|
136
|
+
|
137
|
+
#submit
|
138
|
+
:margin-top 30px
|
139
|
+
:margin-left 5%
|
140
|
+
#form
|
141
|
+
:padding
|
142
|
+
:top 10px
|
143
|
+
:bottom 10px
|
144
|
+
:left 10px
|
145
|
+
:right 10px
|
146
|
+
:text-align left
|
147
|
+
#url
|
148
|
+
:width 80%
|
149
|
+
#button
|
150
|
+
:font-weight bold
|
151
|
+
:text-align center
|
152
|
+
|
153
|
+
#subscribe
|
154
|
+
:margin-left 5%
|
155
|
+
-#.feed
|
156
|
+
-# :margin-left 10%
|
157
|
+
|
158
|
+
#footer
|
159
|
+
:border-top 3px solid darkred
|
160
|
+
:margin-top 20px
|
161
|
+
@@ics.haml
|
162
|
+
%html
|
163
|
+
%head
|
164
|
+
%title Subscribe to calendar feeds as atom feeds
|
165
|
+
%link{:href => '/ics/style.css', :media => 'screen', :type => 'text/css'}
|
166
|
+
%body
|
167
|
+
#header
|
168
|
+
%span#title Subscribe to calendar feeds as atom feeds
|
169
|
+
#submit
|
170
|
+
.text Calendar feeds are great, but sometimes all you want is an atom feed of what's coming up in the next week.
|
171
|
+
.text Paste the URL of the calendar below, submit it, and subscribe.
|
172
|
+
%form#form{:method => 'POST', :action => '/ics'}
|
173
|
+
%input#url{:name => 'url', :value => params[:url]}
|
174
|
+
%input#button{:type => 'submit', :value => 'Submit'}
|
175
|
+
- if @url_atom
|
176
|
+
#subscribe
|
177
|
+
.text
|
178
|
+
Subscribe to
|
179
|
+
%a{:href => @url_ics}= @url_ics
|
180
|
+
as:
|
181
|
+
%ul.feed
|
182
|
+
%a{:href => @url_atom}= @url_atom
|
183
|
+
(atom feed)
|
184
|
+
- if @url_error
|
185
|
+
#error.text
|
186
|
+
#preamble Sorry, trying to access:
|
187
|
+
#source= @url_ics
|
188
|
+
#transition resulted in:
|
189
|
+
#destination= @url_error
|
190
|
+
#footer
|
191
|
+
.text
|
192
|
+
:textile
|
193
|
+
Coming from the "Octet Cloud":http://octetcloud.com/ using "vPim":http://vpim.rubyforge.org/, piloted by cloud monkey "Sam Roberts":mailto:vieuxtech@gmail.com
|
194
|
+
|
@@ -0,0 +1,101 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (C) 2009 Sam Roberts
|
3
|
+
|
4
|
+
This library is free software; you can redistribute it and/or modify it
|
5
|
+
under the same terms as the ruby language itself, see the file COPYING for
|
6
|
+
details.
|
7
|
+
=end
|
8
|
+
|
9
|
+
require "atom"
|
10
|
+
|
11
|
+
module Vpim
|
12
|
+
module Agent
|
13
|
+
|
14
|
+
module Atomize
|
15
|
+
MIME = "application/atom+xml"
|
16
|
+
|
17
|
+
# +ical+, an icalendar, or at least a Repo calendar's subset of an Icalendar
|
18
|
+
# +feeduri+, the atom xml should know the URI of where the feed is available from.
|
19
|
+
# +caluri+, optionally, the URI of the calendar its converted from.
|
20
|
+
#
|
21
|
+
# TODO - and the URI of an alternative/html representation of this feed?
|
22
|
+
def self.calendar(ical, feeduri, caluri = nil, calname = nil)
|
23
|
+
mime = MIME
|
24
|
+
|
25
|
+
feeduri = feeduri.to_str
|
26
|
+
caluri = caluri
|
27
|
+
calname = (calname or caluri or "Unknown").to_str
|
28
|
+
|
29
|
+
f = Atom::Feed.new
|
30
|
+
# Mandatory attributes:
|
31
|
+
# For ID, we should use http://.../ics/atom?....., or just the URL of the ics?
|
32
|
+
# I think it can be a full URI... or maybe a sha-1 of our full URI?
|
33
|
+
# or like gmail, no id for feed,
|
34
|
+
# <id>tag:gmail.google.com,2004:1295062805013769502</id>
|
35
|
+
#
|
36
|
+
f.id = feeduri
|
37
|
+
f.title = calname
|
38
|
+
f.updated = Time.now
|
39
|
+
f.authors << Atom::Person.new(:name => (caluri or calname))
|
40
|
+
f.generator = Atom::Generator.new do |g|
|
41
|
+
g.name = Vpim::PRODID
|
42
|
+
g.uri = "http://vpim.rubyforge.org"
|
43
|
+
g.version = Vpim::VERSION
|
44
|
+
end
|
45
|
+
|
46
|
+
f.links << Atom::Link.new do |l|
|
47
|
+
l.href = feeduri
|
48
|
+
l.type = mime
|
49
|
+
l.rel = :self
|
50
|
+
end
|
51
|
+
|
52
|
+
if caluri
|
53
|
+
# This is maybe better described as :via, but with :alternate being
|
54
|
+
# an html view of this feed.
|
55
|
+
f.links << Atom::Link.new do |l|
|
56
|
+
l.href = caluri
|
57
|
+
l.type = "text/calendar"
|
58
|
+
l.rel = :alternate
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# .icon = uri to the vAgent icon
|
63
|
+
entry_id = 0
|
64
|
+
ical.events do |ve|
|
65
|
+
# TODO - infinite?
|
66
|
+
ve.occurrences do |t|
|
67
|
+
f.entries << Atom::Entry.new do |e|
|
68
|
+
# iCalendar -> atom
|
69
|
+
# -----------------
|
70
|
+
# summary -> title
|
71
|
+
# description -> text/content
|
72
|
+
# uid -> id
|
73
|
+
# created -> published?
|
74
|
+
# organizer -> author?
|
75
|
+
# contact -> author?
|
76
|
+
# last-mod -> semantically, this is updated, but atom doesn't
|
77
|
+
# have the notion that an entry has a relationship to a time,
|
78
|
+
# other than the time the entry itself was published, and when
|
79
|
+
# the entry gets updated. We'll abuse updated for the event's time.
|
80
|
+
# categories -> where do "tags" go in atom, if anywhere?
|
81
|
+
# attachment -> into a link?
|
82
|
+
e.title = ve.summary if ve.summary
|
83
|
+
e.content = Atom::Content::Text.new(ve.description) if ve.description
|
84
|
+
e.updated = t
|
85
|
+
|
86
|
+
# Use "tag:", as defined by RFC4151, and use event UID if possible. Otherwise,
|
87
|
+
# construct something. Maybe I should mix something in to make it unique for
|
88
|
+
# each time a feed is generated for the calendar?
|
89
|
+
entry_id += 1
|
90
|
+
tag = ve.uid || "#{entry_id}@#{feeduri}"
|
91
|
+
e.id = "tag:vpim.rubyforge.org,2009:#{tag}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
return f
|
96
|
+
end
|
97
|
+
end # Atomize
|
98
|
+
|
99
|
+
end # Agent
|
100
|
+
end # Vpim
|
101
|
+
|
@@ -0,0 +1,173 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (C) 2008 Sam Roberts
|
3
|
+
|
4
|
+
This library is free software; you can redistribute it and/or modify it
|
5
|
+
under the same terms as the ruby language itself, see the file COPYING for
|
6
|
+
details.
|
7
|
+
=end
|
8
|
+
|
9
|
+
require "cgi"
|
10
|
+
require "uri"
|
11
|
+
|
12
|
+
require "vpim/repo"
|
13
|
+
require "vpim/agent/atomize"
|
14
|
+
|
15
|
+
module Vpim
|
16
|
+
module Agent
|
17
|
+
# On failure, raise this with an error message. text/plain for now,
|
18
|
+
# text/html later. Will convert to a 404 and a message.
|
19
|
+
class NotFound < Exception
|
20
|
+
def initialize(name, path)
|
21
|
+
super %{Resource "#{name}" under "#{path.prefix}" was not found!}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Path
|
26
|
+
def self.split_path(path)
|
27
|
+
begin
|
28
|
+
path = path.to_ary
|
29
|
+
rescue NameError
|
30
|
+
path = path.split("/")
|
31
|
+
end
|
32
|
+
path.map{|w| CGI.unescape(w)}
|
33
|
+
end
|
34
|
+
|
35
|
+
# URI is the uri being queried, base is where this path is mounted under?
|
36
|
+
def initialize(uri, base = "")
|
37
|
+
@uri = URI.parse(uri.to_s)
|
38
|
+
#pp [uri, base, @uri]
|
39
|
+
if @uri.path.size == 0
|
40
|
+
@uri.path = "/"
|
41
|
+
end
|
42
|
+
@path = Path.split_path(@uri.path)
|
43
|
+
@base = base.to_str
|
44
|
+
@mark = 0
|
45
|
+
|
46
|
+
@base.split.size.times{ shift }
|
47
|
+
end
|
48
|
+
|
49
|
+
def uri
|
50
|
+
@uri.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_path
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
# TODO - call this #next
|
58
|
+
def shift
|
59
|
+
if @path[@mark]
|
60
|
+
@path[@mark += 1]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def append(name, scheme = nil)
|
65
|
+
uri = @uri.dup
|
66
|
+
uri.path += "/" + CGI.escape(name)
|
67
|
+
if scheme
|
68
|
+
uri.scheme = scheme
|
69
|
+
end
|
70
|
+
uri
|
71
|
+
end
|
72
|
+
|
73
|
+
def prefix(len = nil)
|
74
|
+
len ||= @mark
|
75
|
+
@path[0, len].map{|p| CGI.escape(p)}.join("/") + "/"
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
module Form
|
81
|
+
ATOM = Atomize::MIME
|
82
|
+
HTML = "text/html"
|
83
|
+
ICS = "text/calendar"
|
84
|
+
PLAIN = "text/plain"
|
85
|
+
VCF = "text/directory"
|
86
|
+
end
|
87
|
+
|
88
|
+
# Return an HTML description of a list of resources accessible under this
|
89
|
+
# path.
|
90
|
+
class ResourceList
|
91
|
+
def initialize(description, items)
|
92
|
+
@description = description
|
93
|
+
@items = items
|
94
|
+
end
|
95
|
+
|
96
|
+
def get(path)
|
97
|
+
return <<__, Form::HTML
|
98
|
+
<html><body>
|
99
|
+
#{@description}
|
100
|
+
<ul>
|
101
|
+
#{
|
102
|
+
@items.map do |name,description,scheme|
|
103
|
+
"<li><a href=\"#{path.append(name,scheme)}\">#{description || name}</a></li>\n"
|
104
|
+
end
|
105
|
+
}
|
106
|
+
</ul>
|
107
|
+
</body></html>
|
108
|
+
__
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Return calendar information based on RESTful (lovein' the jargon...)
|
113
|
+
# paths. Input is a Vpim::Repo.
|
114
|
+
#
|
115
|
+
# .../coding/month/atom
|
116
|
+
# .../coding/events/month/ics <- next month?
|
117
|
+
# .../coding/events/month/2008-04/ics <- a specified month?
|
118
|
+
# .../coding/week/atom
|
119
|
+
# .../year/atom
|
120
|
+
class Calendars
|
121
|
+
def initialize(repo)
|
122
|
+
@repo = repo
|
123
|
+
end
|
124
|
+
|
125
|
+
class Calendar
|
126
|
+
def initialize(cal)
|
127
|
+
@cal = cal
|
128
|
+
@list = ResourceList.new(
|
129
|
+
"Calendar #{@cal.name.inspect}:",
|
130
|
+
[
|
131
|
+
["calendar", "download"],
|
132
|
+
["calendar", "subscription", "webcal"],
|
133
|
+
["atom", "syndication"],
|
134
|
+
]
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
def get(path)
|
139
|
+
form = path.shift
|
140
|
+
|
141
|
+
# TODO should redirect to an object, so that extra paths can be
|
142
|
+
# handled more gracefully.
|
143
|
+
case form
|
144
|
+
when nil
|
145
|
+
return @list.get(path)
|
146
|
+
when "calendar"
|
147
|
+
return @cal.encode, Form::ICS
|
148
|
+
when "atom"
|
149
|
+
return Atomize.calendar(@cal, path.uri, nil, @cal.name).to_xml, Form::ATOM
|
150
|
+
else
|
151
|
+
raise NotFound.new(form, path)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Get object at this path. Return value is a tuple of data and mime content type.
|
157
|
+
def get(path)
|
158
|
+
case name = path.to_path.shift
|
159
|
+
when nil
|
160
|
+
list = ResourceList.new("Calendars:", @repo.map{|c| c.name})
|
161
|
+
return list.get(path)
|
162
|
+
else
|
163
|
+
if cal = @repo.find{|c| c.name == name}
|
164
|
+
return Calendar.new(cal).get(path)
|
165
|
+
else
|
166
|
+
raise NotFound.new(name, path)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|