vpim 0.17 → 0.323
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/vpim/dirinfo.rb +11 -5
- data/lib/vpim/field.rb +26 -21
- data/lib/vpim/icalendar.rb +21 -105
- data/lib/vpim/maker/vcard.rb +31 -28
- data/lib/vpim/property/base.rb +63 -0
- data/lib/vpim/property/common.rb +159 -0
- data/lib/vpim/property/location.rb +29 -0
- data/lib/vpim/property/priority.rb +35 -0
- data/lib/vpim/property/resources.rb +16 -0
- data/lib/vpim/rfc2425.rb +21 -4
- data/lib/vpim/rrule.rb +1 -1
- data/lib/vpim/vcard.rb +5 -5
- data/lib/vpim/version.rb +16 -0
- data/lib/vpim/vevent.rb +54 -204
- data/lib/vpim/vpim.rb +10 -15
- data/lib/vpim.rb +14 -0
- metadata +9 -19
- data/lib/vpim/agent/plist.rb +0 -86
- data/lib/vpim/date.rb~ +0 -198
- data/lib/vpim/dirinfo.rb~ +0 -242
- data/lib/vpim/duration.rb~ +0 -121
- data/lib/vpim/enumerator.rb~ +0 -29
- data/lib/vpim/field.rb~ +0 -594
- data/lib/vpim/icalendar.rb~ +0 -548
- data/lib/vpim/maker/vcard.rb~ +0 -382
- data/lib/vpim/rfc2425.rb~ +0 -246
- data/lib/vpim/rrule.rb~ +0 -482
- data/lib/vpim/time.rb~ +0 -42
- data/lib/vpim/vcard.rb~ +0 -232
- data/lib/vpim/vevent.rb~ +0 -381
- data/lib/vpim/vpim.rb~ +0 -128
data/lib/vpim/vevent.rb
CHANGED
@@ -10,69 +10,55 @@ require 'vpim/dirinfo'
|
|
10
10
|
require 'vpim/field'
|
11
11
|
require 'vpim/rfc2425'
|
12
12
|
require 'vpim/vpim'
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
COMPLETED:20040303T050000Z
|
19
|
-
DTSTAMP:20040304T011707Z
|
20
|
-
DTSTART;TZID=Canada/Eastern:20030524T115238
|
21
|
-
SEQUENCE:2
|
22
|
-
STATUS:COMPLETED
|
23
|
-
SUMMARY:Wash Car
|
24
|
-
UID:E7609713-8E13-11D7-8ACC-000393AD088C
|
25
|
-
END:VTODO
|
26
|
-
|
27
|
-
BEGIN:VTODO
|
28
|
-
DTSTAMP:20030909T015533Z
|
29
|
-
DTSTART;TZID=Canada/Eastern:20030808T000000
|
30
|
-
SEQUENCE:1
|
31
|
-
SUMMARY:Renew Passport
|
32
|
-
UID:EC76B256-BBE9-11D7-8401-000393AD088C
|
33
|
-
END:VTODO
|
34
|
-
|
35
|
-
|
36
|
-
=end
|
13
|
+
require 'vpim/property/base'
|
14
|
+
require 'vpim/property/common'
|
15
|
+
require 'vpim/property/priority'
|
16
|
+
require 'vpim/property/location'
|
17
|
+
require 'vpim/property/resources'
|
37
18
|
|
38
19
|
module Vpim
|
39
20
|
class Icalendar
|
40
|
-
class
|
41
|
-
|
42
|
-
|
21
|
+
class Vjournal
|
22
|
+
include Vpim::Icalendar::Property::Base
|
23
|
+
include Vpim::Icalendar::Property::Common
|
43
24
|
|
25
|
+
def initialize(fields) #:nodoc:
|
44
26
|
outer, inner = Vpim.outer_inner(fields)
|
45
27
|
|
46
28
|
@properties = Vpim::DirectoryInfo.create(outer)
|
47
29
|
|
48
30
|
@elements = inner
|
31
|
+
end
|
49
32
|
|
50
|
-
|
51
|
-
|
33
|
+
# Create a Vjournal component.
|
34
|
+
def self.create(fields=[])
|
35
|
+
di = DirectoryInfo.create([], 'VJOURNAL')
|
52
36
|
|
53
|
-
|
54
|
-
@description = @properties.text('DESCRIPTION').first
|
55
|
-
@comment = @properties.text('COMMENT').first
|
56
|
-
@location = @properties.text('LOCATION').first
|
57
|
-
@status = @properties.text('STATUS').first
|
58
|
-
@uid = @properties.text('UID').first
|
59
|
-
@priority = @properties.text('PRIORITY').first
|
37
|
+
Vpim::DirectoryInfo::Field.create_array(fields).each { |f| di.push_unique f }
|
60
38
|
|
61
|
-
|
62
|
-
|
63
|
-
@dtstart = @properties.field('dtstart')
|
64
|
-
@dtend = @properties.field('dtend')
|
65
|
-
@duration = @properties.field('duration')
|
66
|
-
@due = @properties.field('due')
|
67
|
-
@rrule = @properties['rrule']
|
39
|
+
new(di.to_a)
|
40
|
+
end
|
68
41
|
|
69
|
-
|
70
|
-
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
71
45
|
|
72
|
-
|
46
|
+
module Vpim
|
47
|
+
class Icalendar
|
48
|
+
class Vtodo
|
49
|
+
include Vpim::Icalendar::Property::Base
|
50
|
+
include Vpim::Icalendar::Property::Common
|
51
|
+
include Vpim::Icalendar::Property::Priority
|
52
|
+
include Vpim::Icalendar::Property::Location
|
53
|
+
include Vpim::Icalendar::Property::Resources
|
73
54
|
|
74
|
-
|
75
|
-
|
55
|
+
def initialize(fields) #:nodoc:
|
56
|
+
outer, inner = Vpim.outer_inner(fields)
|
57
|
+
|
58
|
+
@properties = Vpim::DirectoryInfo.create(outer)
|
59
|
+
|
60
|
+
@elements = inner
|
61
|
+
end
|
76
62
|
|
77
63
|
# Create a new Vtodo object.
|
78
64
|
#
|
@@ -94,37 +80,6 @@ module Vpim
|
|
94
80
|
new(di.to_a)
|
95
81
|
end
|
96
82
|
|
97
|
-
=begin
|
98
|
-
I think that the initialization shouldn't be done in the #initialize, so, for example,
|
99
|
-
@status = @properties.text('STATUS').first
|
100
|
-
should be in the method below.
|
101
|
-
|
102
|
-
That way, I can construct a Vtodo by just including a module for each field that is allowed
|
103
|
-
in a Vtodo, simply.
|
104
|
-
=end
|
105
|
-
def status
|
106
|
-
if(!@status); return nil; end
|
107
|
-
|
108
|
-
s = @status.upcase
|
109
|
-
|
110
|
-
unless @status_values.include?(s)
|
111
|
-
raise Vpim::InvalidEncodingError, "Invalid status '#{@status}'"
|
112
|
-
end
|
113
|
-
|
114
|
-
s
|
115
|
-
end
|
116
|
-
|
117
|
-
# +priority+ is a number from 1 to 9, with 1 being the highest and 0
|
118
|
-
# meaning "no priority", equivalent to not specifying the PRIORITY field.
|
119
|
-
# Other values are reserved by RFC2446.
|
120
|
-
def priority
|
121
|
-
p = @priority ? @priority.to_i : 0
|
122
|
-
|
123
|
-
if( p < 0 || p > 9 )
|
124
|
-
raise Vpim::InvalidEncodingError, 'Invalid priority #{@priority} - it must be 0-9!'
|
125
|
-
end
|
126
|
-
p
|
127
|
-
end
|
128
83
|
end
|
129
84
|
end
|
130
85
|
end
|
@@ -132,35 +87,20 @@ end
|
|
132
87
|
module Vpim
|
133
88
|
class Icalendar
|
134
89
|
class Vevent
|
135
|
-
|
136
|
-
|
90
|
+
include Vpim::Icalendar::Property::Base
|
91
|
+
include Vpim::Icalendar::Property::Common
|
92
|
+
include Vpim::Icalendar::Property::Priority
|
93
|
+
include Vpim::Icalendar::Property::Location
|
94
|
+
include Vpim::Icalendar::Property::Resources
|
137
95
|
|
96
|
+
def initialize(fields) #:nodoc:
|
138
97
|
outer, inner = Vpim.outer_inner(fields)
|
139
98
|
|
140
99
|
@properties = Vpim::DirectoryInfo.create(outer)
|
141
100
|
|
142
101
|
@elements = inner
|
143
102
|
|
144
|
-
# TODO - don't get properties here, put the accessor in a module,
|
145
|
-
# which can cache the results.
|
146
|
-
|
147
|
-
@summary = @properties.text('SUMMARY').first
|
148
|
-
@description = @properties.text('DESCRIPTION').first
|
149
|
-
@comment = @properties.text('COMMENT').first
|
150
|
-
@location = @properties.text('LOCATION').first
|
151
|
-
@status = @properties.text('STATUS').first
|
152
|
-
@uid = @properties.text('UID').first
|
153
|
-
|
154
103
|
# See "TODO - fields" in dirinfo.rb
|
155
|
-
@dtstamp = @properties.field('dtstamp')
|
156
|
-
@dtstart = @properties.field('dtstart')
|
157
|
-
@dtend = @properties.field('dtend')
|
158
|
-
@duration = @properties.field('duration')
|
159
|
-
@rrule = @properties['rrule']
|
160
|
-
|
161
|
-
# Need to seperate status-handling out into a module...
|
162
|
-
@status_values = [ 'TENTATIVE', 'CONFIRMED', 'CANCELLED' ];
|
163
|
-
|
164
104
|
end
|
165
105
|
|
166
106
|
# Create a new Vevent object. All events must have a DTSTART field,
|
@@ -195,13 +135,6 @@ module Vpim
|
|
195
135
|
)
|
196
136
|
end
|
197
137
|
|
198
|
-
attr_reader :description, :summary, :comment, :location
|
199
|
-
attr_reader :properties, :fields # :nodoc:
|
200
|
-
|
201
|
-
#--
|
202
|
-
# The methods below should be shared, somehow, by all calendar components, not just Events.
|
203
|
-
#++
|
204
|
-
|
205
138
|
# Accept an event invitation. The +invitee+ is the Address that wishes
|
206
139
|
# to accept the event invitation as confirmed.
|
207
140
|
def accept(invitee)
|
@@ -225,68 +158,24 @@ module Vpim
|
|
225
158
|
Vevent.new(fields)
|
226
159
|
end
|
227
160
|
|
228
|
-
# Status values are not rejected during decoding. However, if the
|
229
|
-
# status is requested, and it's value is not one of the defined
|
230
|
-
# allowable values, an exception is raised.
|
231
|
-
def status
|
232
|
-
if(!@status); return nil; end
|
233
|
-
|
234
|
-
s = @status.upcase
|
235
|
-
|
236
|
-
unless @status_values.include?(s)
|
237
|
-
raise Vpim::InvalidEncodingError, "Invalid status '#{@status}'"
|
238
|
-
end
|
239
|
-
|
240
|
-
s
|
241
|
-
end
|
242
|
-
|
243
|
-
# TODO - def status? ...
|
244
|
-
|
245
|
-
# TODO - def status= ...
|
246
|
-
|
247
|
-
# The unique identifier of this calendar component, a string. It cannot be
|
248
|
-
# nil, if it is not found in the component, the calendar is malformed, and
|
249
|
-
# this method will raise an exception.
|
250
|
-
def uid
|
251
|
-
if(!@uid)
|
252
|
-
raise Vpim::InvalidEncodingError, 'Invalid component - no UID field was found!'
|
253
|
-
end
|
254
|
-
|
255
|
-
@uid
|
256
|
-
end
|
257
|
-
|
258
|
-
# The time stamp for this calendar component. Describe what this is....
|
259
|
-
# This field is required!
|
260
|
-
def dtstamp
|
261
|
-
if(!@dtstamp)
|
262
|
-
raise Vpim::InvalidEncodingError, 'Invalid component - no DTSTAMP field was found!'
|
263
|
-
end
|
264
|
-
|
265
|
-
@dtstamp.to_time.first
|
266
|
-
end
|
267
|
-
|
268
|
-
# The start time for this calendar component. Describe what this is....
|
269
|
-
# This field is required!
|
270
|
-
def dtstart
|
271
|
-
if(!@dtstart)
|
272
|
-
raise Vpim::InvalidEncodingError, 'Invalid component - no DTSTART field was found!'
|
273
|
-
end
|
274
|
-
|
275
|
-
@dtstart.to_time.first
|
276
|
-
end
|
277
|
-
|
278
161
|
=begin
|
279
162
|
# Set the start time for the event to +start+, a Time object.
|
280
163
|
# TODO - def dtstart=(start) ... start should be allowed to be Time/Date/DateTime
|
281
164
|
=end
|
282
165
|
|
166
|
+
def transparency
|
167
|
+
proptoken 'TRANSP', ["OPAQUE", "TRANSPARENT"], "OPAQUE"
|
168
|
+
end
|
169
|
+
|
283
170
|
# The duration in seconds of a Event, Todo, or Vfreebusy component, or
|
284
171
|
# for Alarms, the delay period prior to repeating the alarm. The
|
285
172
|
# duration is calculated from the DTEND and DTBEGIN fields if the
|
286
173
|
# DURATION field is not present. Durations of zero seconds are possible.
|
287
174
|
def duration
|
288
|
-
|
289
|
-
|
175
|
+
dur = @properties.field 'DURATION'
|
176
|
+
dte = @properties.field 'DTEND'
|
177
|
+
if !dur
|
178
|
+
return nil unless dte
|
290
179
|
|
291
180
|
b = dtstart
|
292
181
|
e = dtend
|
@@ -294,7 +183,7 @@ module Vpim
|
|
294
183
|
return (e - b).to_i
|
295
184
|
end
|
296
185
|
|
297
|
-
Icalendar.decode_duration(
|
186
|
+
Icalendar.decode_duration(dur.value_raw)
|
298
187
|
end
|
299
188
|
|
300
189
|
# The end time for this calendar component. For an Event, if there is no
|
@@ -302,8 +191,9 @@ module Vpim
|
|
302
191
|
# However, the end time will be calculated from the event duration, if
|
303
192
|
# present.
|
304
193
|
def dtend
|
305
|
-
|
306
|
-
|
194
|
+
dte = @properties.field 'DTEND'
|
195
|
+
if dte
|
196
|
+
dte.to_time.first
|
307
197
|
elsif duration
|
308
198
|
dtstart + duration
|
309
199
|
else
|
@@ -314,7 +204,7 @@ module Vpim
|
|
314
204
|
# The recurrence rule, if any, for this event. Recurrence starts at the
|
315
205
|
# DTSTART time.
|
316
206
|
def rrule
|
317
|
-
|
207
|
+
propvalue 'RRULE'
|
318
208
|
end
|
319
209
|
|
320
210
|
# The times this event occurs, as a Vpim::Rrule.
|
@@ -324,7 +214,7 @@ module Vpim
|
|
324
214
|
# Note: occurences are currently calculated only from DTSTART and RRULE,
|
325
215
|
# no allowance for EXDATE or other fields is made.
|
326
216
|
def occurences
|
327
|
-
Vpim::Rrule.new(dtstart,
|
217
|
+
Vpim::Rrule.new(dtstart, rrule)
|
328
218
|
end
|
329
219
|
|
330
220
|
# Check if this event overlaps with the time period later than or equal to +t0+, but
|
@@ -333,46 +223,6 @@ module Vpim
|
|
333
223
|
occurences.each_until(t1).detect { |t| tend = t + (duration || 0); tend > t0 }
|
334
224
|
end
|
335
225
|
|
336
|
-
# Return the event organizer, an object of Icalendar::Address (or nil if
|
337
|
-
# there is no ORGANIZER field).
|
338
|
-
#
|
339
|
-
# TODO - verify that it is illegal for there to be more than one
|
340
|
-
# ORGANIZER, if more than one is allowed, this needs to return an array.
|
341
|
-
def organizer
|
342
|
-
unless instance_variables.include? "@organizer"
|
343
|
-
@organizer = @properties.field('ORGANIZER')
|
344
|
-
|
345
|
-
if @organizer
|
346
|
-
@organizer = Icalendar::Address.new(@organizer)
|
347
|
-
end
|
348
|
-
end
|
349
|
-
@organizer.freeze
|
350
|
-
end
|
351
|
-
|
352
|
-
# Return an array of attendees, an empty array if there are none. The
|
353
|
-
# attendees are objects of Icalendar::Address. If +uri+ is specified
|
354
|
-
# only the return the attendees with this +uri+.
|
355
|
-
def attendees(uri = nil)
|
356
|
-
unless instance_variables.include? "@attendees"
|
357
|
-
@attendees = @properties.enum_by_name('ATTENDEE').map { |a| Icalendar::Address.new(a).freeze }
|
358
|
-
@attendees.freeze
|
359
|
-
end
|
360
|
-
if uri
|
361
|
-
@attendees.select { |a| a == uri } .freeze
|
362
|
-
else
|
363
|
-
@attendees
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
# Return true if the +uri+, usually a mailto: URI, is an attendee.
|
368
|
-
def attendee?(uri)
|
369
|
-
attendees.include? uri
|
370
|
-
end
|
371
|
-
|
372
|
-
# CONTACT - value is text, parameters are ALTREP and LANGUAGE.
|
373
|
-
#
|
374
|
-
# textual contact information, or an altrep referring to a URI pointing
|
375
|
-
# at a vCard or LDAP entry...
|
376
226
|
end
|
377
227
|
end
|
378
228
|
end
|
data/lib/vpim/vpim.rb
CHANGED
@@ -12,7 +12,6 @@
|
|
12
12
|
# Author:: Sam Roberts <sroberts@uniserve.com>
|
13
13
|
# Copyright:: Copyright (C) 2006 Sam Roberts
|
14
14
|
# License:: May be distributed under the same terms as Ruby
|
15
|
-
# Version:: 0.17
|
16
15
|
# Homepage:: http://vpim.rubyforge.org
|
17
16
|
#
|
18
17
|
# vCard (RFC 2426) is a format for personal information, see Vpim::Vcard and
|
@@ -21,17 +20,17 @@
|
|
21
20
|
# iCalendar (RFC 2445) is a format for calendar related information, see
|
22
21
|
# Vpim::Icalendar.
|
23
22
|
#
|
24
|
-
# iCalendar was called vCalendar pre-IETF
|
25
|
-
# these "v-formats" are commonly used personal information management, the
|
23
|
+
# iCalendar was called vCalendar pre-IETF standardization, and since both of
|
24
|
+
# these "v-formats" are commonly used for personal information management, the
|
26
25
|
# library is called "vpim".
|
27
26
|
#
|
28
27
|
# vCard and iCalendar support is built on top of an implementation of the MIME
|
29
28
|
# Content-Type for Directory Information (RFC 2425). The basic RFC 2425 format
|
30
29
|
# is implemented by Vpim::DirectoryInfo and Vpim::DirectoryInfo::Field.
|
31
30
|
#
|
32
|
-
# The libary is
|
33
|
-
#
|
34
|
-
# is missing
|
31
|
+
# The libary is quite useable, but there is always more that could be done.
|
32
|
+
# Since I have a more on my todo list than I have time, if you think something
|
33
|
+
# is missing or have API suggestions, please contact me. I can't promise
|
35
34
|
# instantaneous turnaround, but I might be able to suggest another approach,
|
36
35
|
# and features requested by users of vPim are high priority for me.
|
37
36
|
#
|
@@ -77,21 +76,17 @@
|
|
77
76
|
# - link:rrule.txt: utility for printing recurrence rules
|
78
77
|
# - link:ics-dump.txt: utility for dumping contents of .ics files
|
79
78
|
module Vpim
|
80
|
-
VERSION = "0.17"
|
81
|
-
|
82
|
-
# Return the API version as a string.
|
83
|
-
def Vpim.version
|
84
|
-
VERSION
|
85
|
-
end
|
86
79
|
end
|
87
80
|
|
81
|
+
require 'vpim/version'
|
82
|
+
|
88
83
|
module Vpim
|
89
84
|
# Exception used to indicate that data being decoded is invalid, the message
|
90
85
|
# usually gives some clue as to exactly what is invalid.
|
91
86
|
class InvalidEncodingError < StandardError; end
|
92
87
|
end
|
93
88
|
|
94
|
-
module Vpim::Methods
|
89
|
+
module Vpim::Methods #:nodoc:
|
95
90
|
module_function
|
96
91
|
|
97
92
|
# Case-insensitive comparison of +str0+ to +str1+, returns true or false.
|
@@ -111,9 +106,9 @@ module Vpim::Methods
|
|
111
106
|
def casecmp?(str0, str1)
|
112
107
|
if str0 == nil
|
113
108
|
if str1 == nil
|
114
|
-
|
109
|
+
return true
|
115
110
|
else
|
116
|
-
return
|
111
|
+
return false
|
117
112
|
end
|
118
113
|
end
|
119
114
|
|
data/lib/vpim.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (C) 2006 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
|
+
# I think a file like this may be required by ruby-gems.
|
10
|
+
|
11
|
+
require 'vpim/icalendar'
|
12
|
+
require 'vpim/vcard'
|
13
|
+
require 'vpim/maker/vcard'
|
14
|
+
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: vpim
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date: 2006-03-
|
6
|
+
version: "0.323"
|
7
|
+
date: 2006-03-20 00:00:00 -08:00
|
8
8
|
summary: a library to manipulate vCards and iCalendars
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -28,36 +28,26 @@ cert_chain:
|
|
28
28
|
authors:
|
29
29
|
- Sam Roberts
|
30
30
|
files:
|
31
|
-
- lib/vpim
|
32
|
-
- lib/vpim/agent
|
31
|
+
- lib/vpim.rb
|
33
32
|
- lib/vpim/date.rb
|
34
|
-
- lib/vpim/date.rb~
|
35
33
|
- lib/vpim/dirinfo.rb
|
36
|
-
- lib/vpim/dirinfo.rb~
|
37
34
|
- lib/vpim/duration.rb
|
38
|
-
- lib/vpim/duration.rb~
|
39
35
|
- lib/vpim/enumerator.rb
|
40
|
-
- lib/vpim/enumerator.rb~
|
41
36
|
- lib/vpim/field.rb
|
42
|
-
- lib/vpim/field.rb~
|
43
37
|
- lib/vpim/icalendar.rb
|
44
|
-
- lib/vpim/icalendar.rb~
|
45
|
-
- lib/vpim/maker
|
46
38
|
- lib/vpim/rfc2425.rb
|
47
|
-
- lib/vpim/rfc2425.rb~
|
48
39
|
- lib/vpim/rrule.rb
|
49
|
-
- lib/vpim/rrule.rb~
|
50
40
|
- lib/vpim/time.rb
|
51
|
-
- lib/vpim/time.rb~
|
52
41
|
- lib/vpim/vcard.rb
|
53
|
-
- lib/vpim/
|
42
|
+
- lib/vpim/version.rb
|
54
43
|
- lib/vpim/vevent.rb
|
55
|
-
- lib/vpim/vevent.rb~
|
56
44
|
- lib/vpim/vpim.rb
|
57
|
-
- lib/vpim/vpim.rb~
|
58
|
-
- lib/vpim/agent/plist.rb
|
59
45
|
- lib/vpim/maker/vcard.rb
|
60
|
-
- lib/vpim/
|
46
|
+
- lib/vpim/property/base.rb
|
47
|
+
- lib/vpim/property/common.rb
|
48
|
+
- lib/vpim/property/location.rb
|
49
|
+
- lib/vpim/property/priority.rb
|
50
|
+
- lib/vpim/property/resources.rb
|
61
51
|
test_files: []
|
62
52
|
|
63
53
|
rdoc_options: []
|
data/lib/vpim/agent/plist.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
# http://www2a.biglobe.ne.jp/~seki/ruby/src/plist.rb
|
2
|
-
require 'rexml/document'
|
3
|
-
require 'time'
|
4
|
-
|
5
|
-
class Plist #:nodoc:
|
6
|
-
def self.file_to_plist(fname)
|
7
|
-
File.open(fname) do |fp|
|
8
|
-
doc = REXML::Document.new(fp)
|
9
|
-
return self.new.visit(REXML::XPath.match(doc, '/plist/')[0])
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
setup_method_table
|
15
|
-
end
|
16
|
-
|
17
|
-
def visit(node)
|
18
|
-
visit_one(node.elements[1])
|
19
|
-
end
|
20
|
-
|
21
|
-
def visit_one(node)
|
22
|
-
choose_method(node.name).call(node)
|
23
|
-
end
|
24
|
-
|
25
|
-
def visit_null(node)
|
26
|
-
p node if $DEBUG
|
27
|
-
nil
|
28
|
-
end
|
29
|
-
|
30
|
-
def visit_dict(node)
|
31
|
-
dict = {}
|
32
|
-
es = node.elements.to_a
|
33
|
-
while key = es.shift
|
34
|
-
next unless key.name == 'key'
|
35
|
-
dict[key.text] = visit_one(es.shift)
|
36
|
-
end
|
37
|
-
dict
|
38
|
-
end
|
39
|
-
|
40
|
-
def visit_array(node)
|
41
|
-
node.elements.collect do |x|
|
42
|
-
visit_one(x)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def visit_integer(node)
|
47
|
-
node.text.to_i
|
48
|
-
end
|
49
|
-
|
50
|
-
def visit_real(node)
|
51
|
-
node.text.to_f
|
52
|
-
end
|
53
|
-
|
54
|
-
def visit_string(node)
|
55
|
-
node.text.to_s
|
56
|
-
end
|
57
|
-
|
58
|
-
def visit_date(node)
|
59
|
-
Time.parse(node.text.to_s)
|
60
|
-
end
|
61
|
-
|
62
|
-
def visit_true(node)
|
63
|
-
true
|
64
|
-
end
|
65
|
-
|
66
|
-
def visit_false(node)
|
67
|
-
false
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
def choose_method(name)
|
72
|
-
@method.fetch(name, method(:visit_null))
|
73
|
-
end
|
74
|
-
|
75
|
-
def setup_method_table
|
76
|
-
@method = {}
|
77
|
-
@method['dict'] = method(:visit_dict)
|
78
|
-
@method['integer'] = method(:visit_integer)
|
79
|
-
@method['real'] = method(:visit_real)
|
80
|
-
@method['string'] = method(:visit_string)
|
81
|
-
@method['date'] = method(:visit_date)
|
82
|
-
@method['true'] = method(:visit_true)
|
83
|
-
@method['false'] = method(:visit_false)
|
84
|
-
@method['array'] = method(:visit_array)
|
85
|
-
end
|
86
|
-
end
|