vpim 0.695 → 13.11.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/{README → README.rdoc} +2 -13
- data/lib/vpim.rb +1 -0
- data/lib/vpim/address.rb +3 -2
- data/lib/vpim/agent/atomize.rb +4 -0
- data/lib/vpim/agent/base.rb +74 -0
- data/lib/vpim/agent/calendars.rb +1 -0
- data/lib/vpim/agent/handler.rb +27 -0
- data/lib/vpim/agent/ics.rb +162 -0
- data/lib/vpim/attachment.rb +1 -0
- data/lib/vpim/date.rb +3 -2
- data/lib/vpim/dirinfo.rb +5 -4
- data/lib/vpim/duration.rb +1 -0
- data/lib/vpim/enumerator.rb +1 -0
- data/lib/vpim/field.rb +3 -2
- data/lib/vpim/icalendar.rb +9 -5
- data/lib/vpim/maker/vcard.rb +1 -0
- data/lib/vpim/property/base.rb +1 -0
- data/lib/vpim/property/common.rb +1 -0
- data/lib/vpim/property/location.rb +10 -0
- data/lib/vpim/property/priority.rb +2 -1
- data/lib/vpim/property/recurrence.rb +1 -0
- data/lib/vpim/property/resources.rb +1 -2
- data/lib/vpim/repo.rb +2 -1
- data/lib/vpim/rfc2425.rb +32 -24
- data/lib/vpim/rrule.rb +9 -8
- data/lib/vpim/time.rb +1 -0
- data/lib/vpim/vcard.rb +13 -11
- data/lib/vpim/version.rb +2 -2
- data/lib/vpim/vevent.rb +3 -1
- data/lib/vpim/view.rb +3 -2
- data/lib/vpim/vjournal.rb +1 -0
- data/lib/vpim/vpim.rb +2 -1
- data/lib/vpim/vtodo.rb +1 -0
- data/samples/agent.ru +10 -0
- data/test/test_all.rb +2 -0
- data/test/test_date.rb +6 -5
- data/test/test_dur.rb +1 -0
- data/test/test_field.rb +3 -2
- data/test/test_ical.rb +12 -2
- data/test/test_misc.rb +13 -0
- data/test/test_repo.rb +22 -2
- data/test/test_rrule.rb +1 -0
- data/test/test_vcard.rb +53 -1
- metadata +36 -46
- data/lib/vpim/agent/app.rb +0 -194
- data/lib/vpim/agent/main.rb +0 -327
- data/lib/vpim/agent/scraps.rb +0 -292
- data/test/test_agent_app.rb +0 -74
- data/test/test_agent_atomize.rb +0 -84
- data/test/test_agent_calendars.rb +0 -128
- data/test/test_view.rb +0 -79
data/lib/vpim/agent/main.rb
DELETED
@@ -1,327 +0,0 @@
|
|
1
|
-
require 'etc'
|
2
|
-
require 'pp'
|
3
|
-
require 'rss/maker'
|
4
|
-
require 'socket'
|
5
|
-
require 'webrick'
|
6
|
-
require 'vpim/icalendar'
|
7
|
-
require 'vpim/vcard'
|
8
|
-
|
9
|
-
#--------------------------------------------------------------------------------
|
10
|
-
# Load DNSSD support, if possible.
|
11
|
-
# TODO - should be in net/dns/dnssd
|
12
|
-
# FIXME - doesn't work with dnssd
|
13
|
-
@avoid_native = true
|
14
|
-
begin
|
15
|
-
if @avoid_native
|
16
|
-
raise LoadError
|
17
|
-
else
|
18
|
-
require 'dnssd'
|
19
|
-
end
|
20
|
-
rescue LoadError
|
21
|
-
begin
|
22
|
-
require 'net/dns/mdns-sd'
|
23
|
-
DNSSD = Net::DNS::MDNSSD
|
24
|
-
rescue LoadError
|
25
|
-
DNSSD = nil
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
#--------------------------------------------------------------------------------
|
30
|
-
# Set up server environment.
|
31
|
-
|
32
|
-
# Find the user's name and host.
|
33
|
-
|
34
|
-
require 'etc'
|
35
|
-
|
36
|
-
$user = Etc.getpwuid(Process.uid).gecos
|
37
|
-
$host = Socket.gethostname
|
38
|
-
|
39
|
-
$services = []
|
40
|
-
|
41
|
-
$stuff = []
|
42
|
-
|
43
|
-
def register(name, path, protocol = 'http')
|
44
|
-
# $services << DNSSD.register(name, '_http._tcp', 'local', $port, 'path' => path )
|
45
|
-
|
46
|
-
puts "register #{name.inspect} on path #{path.inspect} with #{protocol}"
|
47
|
-
|
48
|
-
$stuff << [name, path, protocol]
|
49
|
-
end
|
50
|
-
|
51
|
-
# Create a HTTP server, possibly on a dynamic port.
|
52
|
-
# - Dynamic ports don't actually work well. While it is true we can advertise them,
|
53
|
-
# non-DNSSD aware clients will store the hostname and port when they subscribe to
|
54
|
-
# a calendar, but when the server restarts the port will be different. Not good.
|
55
|
-
$port = 8191
|
56
|
-
|
57
|
-
server = WEBrick::HTTPServer.new( :Port => $port )
|
58
|
-
|
59
|
-
if $port == 0
|
60
|
-
# Server may have created multiple listeners, all on a different dynamically
|
61
|
-
# assigned port.
|
62
|
-
families = Socket.getaddrinfo(nil, 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
|
63
|
-
|
64
|
-
listeners = []
|
65
|
-
|
66
|
-
families.each do |af, one, dns, addr|
|
67
|
-
listeners << TCPServer.new(addr, $port)
|
68
|
-
$port = listeners.first.addr[1] unless $port != 0
|
69
|
-
end
|
70
|
-
|
71
|
-
listeners.each do |s|
|
72
|
-
puts "listen on #{s.addr.inspect}"
|
73
|
-
end
|
74
|
-
|
75
|
-
# So we replace them with our TCPServer sockets which are all on the same
|
76
|
-
# (dynamically assigned) port.
|
77
|
-
server.listeners.each do |s| s.close end
|
78
|
-
server.listeners.replace listeners
|
79
|
-
server.config[:Port] = $port
|
80
|
-
end
|
81
|
-
|
82
|
-
server.config[:MimeTypes]['ics'] = 'text/calendar'
|
83
|
-
server.config[:MimeTypes]['vcf'] = 'text/directory'
|
84
|
-
|
85
|
-
#--------------------------------------------------------------------------------
|
86
|
-
# Mount services
|
87
|
-
|
88
|
-
##### Vcard Birthdays as iCalendar
|
89
|
-
=begin
|
90
|
-
$vcf_bday_file = 'vpim-bday.vcf'
|
91
|
-
$vcf_bday_path = '/vcf/bday.ics'
|
92
|
-
|
93
|
-
class VcfBdayIcsServlet < WEBrick::HTTPServlet::AbstractServlet
|
94
|
-
def do_GET(req, resp)
|
95
|
-
cal = Vpim::Icalendar.create
|
96
|
-
|
97
|
-
open($vcf_bday_file) do |vcf|
|
98
|
-
Vpim::Vcard.decode(vcf).each do |card|
|
99
|
-
begin
|
100
|
-
bday = card.birthday
|
101
|
-
if bday
|
102
|
-
cal.push Vpim::Icalendar::Vevent.create_yearly(
|
103
|
-
card.birthday,
|
104
|
-
"Birthday for #{card['fn'].strip}"
|
105
|
-
)
|
106
|
-
$stderr.puts "#{card['fn']} -> bday #{cal.events.last.dtstart}"
|
107
|
-
end
|
108
|
-
rescue
|
109
|
-
$stderr.puts $!
|
110
|
-
$stderr.puts $!.backtrace.join("\n")
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
resp.body = cal.encode
|
116
|
-
resp['content-type'] = 'text/calendar'
|
117
|
-
|
118
|
-
# Is this necessary, or is it default?
|
119
|
-
raise WEBrick::HTTPStatus::OK
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
server.mount( $vcf_bday_path, VcfBdayIcsServlet )
|
124
|
-
|
125
|
-
register( "Calendar for all the Birthdays in my vCards", $vcf_bday_path, 'webcal' )
|
126
|
-
=end
|
127
|
-
|
128
|
-
##### iCalendar as calendars
|
129
|
-
# Export local calendars two different ways
|
130
|
-
=begin
|
131
|
-
$ical_folder = File.expand_path( "~/Library/Calendars" )
|
132
|
-
|
133
|
-
#
|
134
|
-
# Here we write a servlet to display all the allowed calendars with
|
135
|
-
# webcal links, so they open in iCal.
|
136
|
-
#
|
137
|
-
$ical_include = /^[A-Z]/
|
138
|
-
$ical_title = "My Calendars"
|
139
|
-
|
140
|
-
class IcalIcsServlet < WEBrick::HTTPServlet::AbstractServlet
|
141
|
-
def do_GET(req, resp)
|
142
|
-
body = ''
|
143
|
-
# body << @options.inspect
|
144
|
-
|
145
|
-
folder, include, exclude = *@options
|
146
|
-
|
147
|
-
path = req.path_info
|
148
|
-
|
149
|
-
# body << "\n"
|
150
|
-
# body << "path=#{path.inspect}\n"
|
151
|
-
|
152
|
-
all = Dir.entries(folder).select do |f| f =~ /\.ics$/ end
|
153
|
-
|
154
|
-
if include
|
155
|
-
all.reject! do |f| !(f =~ include) end
|
156
|
-
end
|
157
|
-
if exclude
|
158
|
-
all.reject! do |f| f =~ exclude end
|
159
|
-
end
|
160
|
-
|
161
|
-
# body << "#{all.inspect}\n"
|
162
|
-
|
163
|
-
if(path == '')
|
164
|
-
body << "<ul>\n"
|
165
|
-
all.each do |f|
|
166
|
-
n = f.sub('.ics', '')
|
167
|
-
body << "<li><a href=\"webcal://#{$host}:#{$port}/calfile/#{f}\">#{n}</a>\n"
|
168
|
-
end
|
169
|
-
body << "</ul>\n"
|
170
|
-
end
|
171
|
-
|
172
|
-
resp.body = body
|
173
|
-
resp['content-type'] = 'text/html'
|
174
|
-
raise WEBrick::HTTPStatus::OK
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
server.mount( '/calweb', IcalIcsServlet, $ical_folder, $ical_include)
|
179
|
-
|
180
|
-
register( "My Calendars as webcal:// Feeds", '/calweb' )
|
181
|
-
|
182
|
-
#
|
183
|
-
# We use the WEBrick file servlet to actually serve calendar files.
|
184
|
-
# FIXME - this means that if you guess someone's calendar name, you can
|
185
|
-
# download it, despite the rudimentary security.
|
186
|
-
#
|
187
|
-
server.mount( '/calfile', WEBrick::HTTPServlet::FileHandler, $ical_folder, :FancyIndexing=>true )
|
188
|
-
|
189
|
-
# For debugging...
|
190
|
-
register( 'My Calendar Folder', '/calfile' )
|
191
|
-
|
192
|
-
=end
|
193
|
-
|
194
|
-
##### iCalendar/todo as RSS
|
195
|
-
=begin
|
196
|
-
$ics_todo_title = 'My Todo Items as an RSS Feed'
|
197
|
-
$ics_todo_path = "/ics/todo.rss"
|
198
|
-
|
199
|
-
class IcalTodoRssServlet < WEBrick::HTTPServlet::AbstractServlet
|
200
|
-
def do_GET(req, resp)
|
201
|
-
rss = RSS::Maker.make("0.9") do |maker|
|
202
|
-
title = $ics_todo_title
|
203
|
-
link = 'http:///'
|
204
|
-
maker.channel.title = title
|
205
|
-
maker.channel.link = link
|
206
|
-
maker.channel.description = title
|
207
|
-
maker.channel.language = 'en-us'
|
208
|
-
|
209
|
-
# These are required, or RSS::Maker silently returns nil!
|
210
|
-
maker.image.url = "maker.image.url"
|
211
|
-
maker.image.title = "maker.image.title"
|
212
|
-
|
213
|
-
Dir[ $ical_folder + "/*.ics" ].each do |file|
|
214
|
-
# TODO: use the open with a block variant
|
215
|
-
Vpim::Icalendar.decode(File.open(file)).each do |cal|
|
216
|
-
cal.todos.each do |todo|
|
217
|
-
if !todo.status || todo.status.upcase != "COMPLETED"
|
218
|
-
item = maker.items.new_item
|
219
|
-
item.title = todo.summary
|
220
|
-
item.link = todo.properties['url'] || link
|
221
|
-
item.description = todo.description || todo.summary
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
resp.body = rss.to_s
|
229
|
-
resp['content-type'] = 'text/xml'
|
230
|
-
|
231
|
-
raise WEBrick::HTTPStatus::OK
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
server.mount( $ics_todo_path, IcalTodoRssServlet )
|
236
|
-
|
237
|
-
register( $ics_todo_title, $ics_todo_path )
|
238
|
-
=end
|
239
|
-
|
240
|
-
##### Local calendars
|
241
|
-
|
242
|
-
require "vpim/agent/calendars"
|
243
|
-
|
244
|
-
$ical_folder = File.expand_path( "~/Library/Calendars" )
|
245
|
-
|
246
|
-
class CalendarsServlet < WEBrick::HTTPServlet::AbstractServlet
|
247
|
-
def do_GET(req, resp)
|
248
|
-
body = ''
|
249
|
-
# body << @options.inspect
|
250
|
-
|
251
|
-
folder = *@options
|
252
|
-
|
253
|
-
# TODO Should be longer lived
|
254
|
-
repo = Vpim::Repo::Apple3.new($ical_folder)
|
255
|
-
rest = Vpim::Agent::Calendars.new(repo)
|
256
|
-
path = Vpim::Agent::Path.new(req.request_uri, req.path)
|
257
|
-
|
258
|
-
begin
|
259
|
-
body, form = rest.get(path)
|
260
|
-
status = 200
|
261
|
-
rescue Vpim::Agent::NotFound
|
262
|
-
body = $!.to_s
|
263
|
-
form = "text/plain" # should be HTML!
|
264
|
-
status = 404
|
265
|
-
end
|
266
|
-
|
267
|
-
resp.status = status
|
268
|
-
resp.body = body
|
269
|
-
resp['content-type'] = form
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
server.mount( '/calendars', CalendarsServlet, $ical_folder )
|
274
|
-
|
275
|
-
register( "Calendars", '/calendars' )
|
276
|
-
|
277
|
-
#--------------------------------------------------------------------------------
|
278
|
-
## Top-level page.
|
279
|
-
|
280
|
-
$vpim_title = "vAgent for #{$user}"
|
281
|
-
|
282
|
-
class VpimServlet < WEBrick::HTTPServlet::AbstractServlet
|
283
|
-
def do_GET(req, resp)
|
284
|
-
body = <<"EOF"
|
285
|
-
<h1>#{$vpim_title}</h1>
|
286
|
-
|
287
|
-
See:
|
288
|
-
<ul>
|
289
|
-
EOF
|
290
|
-
|
291
|
-
$stuff.each do |name,path,protocol|
|
292
|
-
#body << "<li><a href=\"#{protocol}://#{$host}:#{$port}#{path}\">#{name}</a>\n"
|
293
|
-
#
|
294
|
-
# $host is wrong, it lacks the domain - we should derive this from how
|
295
|
-
# we are called, or just leave it out.
|
296
|
-
body << "<li><a href=\"#{path}\">#{name}</a>\n"
|
297
|
-
end
|
298
|
-
|
299
|
-
body << "</ul>\n"
|
300
|
-
|
301
|
-
resp.body = body
|
302
|
-
resp['content-type'] = 'text/html'
|
303
|
-
raise WEBrick::HTTPStatus::OK
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
server.mount( '/', VpimServlet )
|
308
|
-
|
309
|
-
#--------------------------------------------------------------------------------
|
310
|
-
# Run server
|
311
|
-
|
312
|
-
if DNSSD
|
313
|
-
$services << DNSSD.register($vpim_title, '_http._tcp', 'local', $port, 'path' => '/' )
|
314
|
-
end
|
315
|
-
|
316
|
-
['INT', 'TERM'].each do |signal|
|
317
|
-
trap(signal) do
|
318
|
-
server.shutdown
|
319
|
-
$services.each do |s|
|
320
|
-
s.stop
|
321
|
-
end
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
server.start
|
326
|
-
|
327
|
-
|
data/lib/vpim/agent/scraps.rb
DELETED
@@ -1,292 +0,0 @@
|
|
1
|
-
require 'etc'
|
2
|
-
require 'rss/maker'
|
3
|
-
require 'socket'
|
4
|
-
require 'webrick'
|
5
|
-
require 'vpim/icalendar'
|
6
|
-
require 'vpim/vcard'
|
7
|
-
|
8
|
-
# Notes on debugging with dnssd API: check system.log, it should give info.
|
9
|
-
|
10
|
-
#require 'pp'
|
11
|
-
#module Kernel
|
12
|
-
# def to_pp
|
13
|
-
# s = PP.pp(self, '')
|
14
|
-
# s.chomp!
|
15
|
-
# s
|
16
|
-
# end
|
17
|
-
#end
|
18
|
-
|
19
|
-
|
20
|
-
#--------------------------------------------------------------------------------
|
21
|
-
# Load DNSSD support, if possible.
|
22
|
-
# TODO - should be in net/dns/dnssd
|
23
|
-
# FIXME - doesn't work with dnssd
|
24
|
-
@avoid_native = true
|
25
|
-
begin
|
26
|
-
if @avoid_native
|
27
|
-
raise LoadError
|
28
|
-
else
|
29
|
-
require 'dnssd'
|
30
|
-
end
|
31
|
-
rescue LoadError
|
32
|
-
begin
|
33
|
-
require 'net/dns/mdns-sd'
|
34
|
-
DNSSD = Net::DNS::MDNSSD
|
35
|
-
rescue LoadError
|
36
|
-
DNSSD = nil
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
#--------------------------------------------------------------------------------
|
41
|
-
# Set up server environment.
|
42
|
-
|
43
|
-
# Find the user's name and host.
|
44
|
-
|
45
|
-
require 'etc'
|
46
|
-
|
47
|
-
$user = Etc.getpwuid(Process.uid).gecos
|
48
|
-
$host = Socket.gethostname
|
49
|
-
|
50
|
-
$services = []
|
51
|
-
|
52
|
-
$stuff = []
|
53
|
-
|
54
|
-
def register(name, path, protocol = 'http')
|
55
|
-
# $services << DNSSD.register(name, '_http._tcp', 'local', $port, 'path' => path )
|
56
|
-
|
57
|
-
puts "register #{name.inspect} on path #{path.inspect} with #{protocol}"
|
58
|
-
|
59
|
-
$stuff << [name, path, protocol]
|
60
|
-
end
|
61
|
-
|
62
|
-
# Create a HTTP server, possibly on a dynamic port.
|
63
|
-
# - Dynamic ports don't actually work well. While it is true we can advertise them,
|
64
|
-
# non-DNSSD aware clients will store the hostname and port when they subscribe to
|
65
|
-
# a calendar, but when the server restarts the port will be different. Not good.
|
66
|
-
$port = 8191
|
67
|
-
|
68
|
-
server = WEBrick::HTTPServer.new( :Port => $port )
|
69
|
-
|
70
|
-
if $port == 0
|
71
|
-
# Server may have created multiple listeners, all on a different dynamically
|
72
|
-
# assigned port.
|
73
|
-
families = Socket.getaddrinfo(nil, 1, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
|
74
|
-
|
75
|
-
listeners = []
|
76
|
-
|
77
|
-
families.each do |af, one, dns, addr|
|
78
|
-
listeners << TCPServer.new(addr, $port)
|
79
|
-
$port = listeners.first.addr[1] unless $port != 0
|
80
|
-
end
|
81
|
-
|
82
|
-
listeners.each do |s|
|
83
|
-
puts "listen on #{s.addr.inspect}"
|
84
|
-
end
|
85
|
-
|
86
|
-
# So we replace them with our TCPServer sockets which are all on the same
|
87
|
-
# (dynamically assigned) port.
|
88
|
-
server.listeners.each do |s| s.close end
|
89
|
-
server.listeners.replace listeners
|
90
|
-
server.config[:Port] = $port
|
91
|
-
end
|
92
|
-
|
93
|
-
server.config[:MimeTypes]['ics'] = 'text/calendar'
|
94
|
-
server.config[:MimeTypes]['vcf'] = 'text/directory'
|
95
|
-
|
96
|
-
#--------------------------------------------------------------------------------
|
97
|
-
# Mount services
|
98
|
-
|
99
|
-
##### Vcard Birthdays as iCalendar
|
100
|
-
|
101
|
-
$vcf_bday_file = 'vpim-bday.vcf'
|
102
|
-
$vcf_bday_path = '/vcf/bday.ics'
|
103
|
-
|
104
|
-
class VcfBdayIcsServlet < WEBrick::HTTPServlet::AbstractServlet
|
105
|
-
def do_GET(req, resp)
|
106
|
-
cal = Vpim::Icalendar.create
|
107
|
-
|
108
|
-
open($vcf_bday_file) do |vcf|
|
109
|
-
Vpim::Vcard.decode(vcf).each do |card|
|
110
|
-
begin
|
111
|
-
bday = card.birthday
|
112
|
-
if bday
|
113
|
-
cal.push Vpim::Icalendar::Vevent.create_yearly(
|
114
|
-
card.birthday,
|
115
|
-
"Birthday for #{card['fn'].strip}"
|
116
|
-
)
|
117
|
-
$stderr.puts "#{card['fn']} -> bday #{cal.events.last.dtstart}"
|
118
|
-
end
|
119
|
-
rescue
|
120
|
-
$stderr.puts $!
|
121
|
-
$stderr.puts $!.backtrace.join("\n")
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
resp.body = cal.encode
|
127
|
-
resp['content-type'] = 'text/calendar'
|
128
|
-
|
129
|
-
# Is this necessary, or is it default?
|
130
|
-
raise WEBrick::HTTPStatus::OK
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
server.mount( $vcf_bday_path, VcfBdayIcsServlet )
|
135
|
-
|
136
|
-
register( "Calendar for all the Birthdays in my vCards", $vcf_bday_path, 'webcal' )
|
137
|
-
|
138
|
-
##### iCalendar as calendars
|
139
|
-
# Export local calendars two different ways
|
140
|
-
|
141
|
-
$ical_folder = File.expand_path( "~/Library/Calendars" )
|
142
|
-
|
143
|
-
#
|
144
|
-
# Here we write a servlet to display all the allowed calendars with
|
145
|
-
# webcal links, so they open in iCal.
|
146
|
-
#
|
147
|
-
$ical_include = /^[A-Z]/
|
148
|
-
$ical_title = "My Calendars"
|
149
|
-
|
150
|
-
class IcalIcsServlet < WEBrick::HTTPServlet::AbstractServlet
|
151
|
-
def do_GET(req, resp)
|
152
|
-
body = ''
|
153
|
-
# body << @options.inspect
|
154
|
-
|
155
|
-
folder, include, exclude = *@options
|
156
|
-
|
157
|
-
path = req.path_info
|
158
|
-
|
159
|
-
# body << "\n"
|
160
|
-
# body << "path=#{path.inspect}\n"
|
161
|
-
|
162
|
-
all = Dir.entries(folder).select do |f| f =~ /\.ics$/ end
|
163
|
-
|
164
|
-
if include
|
165
|
-
all.reject! do |f| !(f =~ include) end
|
166
|
-
end
|
167
|
-
if exclude
|
168
|
-
all.reject! do |f| f =~ exclude end
|
169
|
-
end
|
170
|
-
|
171
|
-
# body << "#{all.inspect}\n"
|
172
|
-
|
173
|
-
if(path == '')
|
174
|
-
body << "<ul>\n"
|
175
|
-
all.each do |f|
|
176
|
-
n = f.sub('.ics', '')
|
177
|
-
body << "<li><a href=\"webcal://#{$host}:#{$port}/calfile/#{f}\">#{n}</a>\n"
|
178
|
-
end
|
179
|
-
body << "</ul>\n"
|
180
|
-
end
|
181
|
-
|
182
|
-
resp.body = body
|
183
|
-
resp['content-type'] = 'text/html'
|
184
|
-
raise WEBrick::HTTPStatus::OK
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
server.mount( '/calweb', IcalIcsServlet, $ical_folder, $ical_include)
|
189
|
-
|
190
|
-
register( "My Calendars as webcal:// Feeds", '/calweb' )
|
191
|
-
|
192
|
-
#
|
193
|
-
# We use the WEBrick file servlet to actually serve calendar files.
|
194
|
-
# FIXME - this means that if you guess someone's calendar name, you can
|
195
|
-
# download it, despite the rudimentary security.
|
196
|
-
#
|
197
|
-
server.mount( '/calfile', WEBrick::HTTPServlet::FileHandler, $ical_folder, :FancyIndexing=>true )
|
198
|
-
|
199
|
-
# For debugging...
|
200
|
-
register( 'My Calendar Folder', '/calfile' )
|
201
|
-
|
202
|
-
##### iCalendar/todo as RSS
|
203
|
-
|
204
|
-
$ics_todo_title = 'My Todo Items as an RSS Feed'
|
205
|
-
$ics_todo_path = "/ics/todo.rss"
|
206
|
-
|
207
|
-
class IcalTodoRssServlet < WEBrick::HTTPServlet::AbstractServlet
|
208
|
-
def do_GET(req, resp)
|
209
|
-
rss = RSS::Maker.make("0.9") do |maker|
|
210
|
-
title = $ics_todo_title
|
211
|
-
link = 'http:///'
|
212
|
-
maker.channel.title = title
|
213
|
-
maker.channel.link = link
|
214
|
-
maker.channel.description = title
|
215
|
-
maker.channel.language = 'en-us'
|
216
|
-
|
217
|
-
# These are required, or RSS::Maker silently returns nil!
|
218
|
-
maker.image.url = "maker.image.url"
|
219
|
-
maker.image.title = "maker.image.title"
|
220
|
-
|
221
|
-
Dir[ $ical_folder + "/*.ics" ].each do |file|
|
222
|
-
# TODO: use the open with a block variant
|
223
|
-
Vpim::Icalendar.decode(File.open(file)).each do |cal|
|
224
|
-
cal.todos.each do |todo|
|
225
|
-
if !todo.status || todo.status.upcase != "COMPLETED"
|
226
|
-
item = maker.items.new_item
|
227
|
-
item.title = todo.summary
|
228
|
-
item.link = todo.properties['url'] || link
|
229
|
-
item.description = todo.description || todo.summary
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
resp.body = rss.to_s
|
237
|
-
resp['content-type'] = 'text/xml'
|
238
|
-
|
239
|
-
raise WEBrick::HTTPStatus::OK
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
server.mount( $ics_todo_path, IcalTodoRssServlet )
|
244
|
-
|
245
|
-
register( $ics_todo_title, $ics_todo_path )
|
246
|
-
|
247
|
-
|
248
|
-
#--------------------------------------------------------------------------------
|
249
|
-
## Top-level page.
|
250
|
-
|
251
|
-
$vpim_title = "vPim for #{$user}"
|
252
|
-
|
253
|
-
class VpimServlet < WEBrick::HTTPServlet::AbstractServlet
|
254
|
-
def do_GET(req, resp)
|
255
|
-
body = <<"EOF"
|
256
|
-
<h1>#{$vpim_title}</h1>
|
257
|
-
|
258
|
-
You can access:
|
259
|
-
<ul>
|
260
|
-
EOF
|
261
|
-
|
262
|
-
$stuff.each do |name,path,protocol|
|
263
|
-
body << "<li><a href=\"#{protocol}://#{$host}:#{$port}#{path}\">#{name}</a>\n"
|
264
|
-
end
|
265
|
-
|
266
|
-
body << "</ul>\n"
|
267
|
-
|
268
|
-
resp.body = body
|
269
|
-
resp['content-type'] = 'text/html'
|
270
|
-
raise WEBrick::HTTPStatus::OK
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
server.mount( '/', VpimServlet )
|
275
|
-
|
276
|
-
#--------------------------------------------------------------------------------
|
277
|
-
# Run server
|
278
|
-
|
279
|
-
$services << DNSSD.register($vpim_title, '_http._tcp', 'local', $port, 'path' => '/' )
|
280
|
-
|
281
|
-
['INT', 'TERM'].each do |signal|
|
282
|
-
trap(signal) do
|
283
|
-
server.shutdown
|
284
|
-
$services.each do |s|
|
285
|
-
s.stop
|
286
|
-
end
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
server.start
|
291
|
-
|
292
|
-
|