vpim 0.17 → 0.323
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/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/dirinfo.rb
CHANGED
@@ -20,7 +20,7 @@ module Vpim
|
|
20
20
|
#
|
21
21
|
# A vCard, for example, is a specialization of a directory info object.
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# - [RFC2425] the directory information framework (ftp://ftp.ietf.org/rfc/rfc2425.txt)
|
24
24
|
class DirectoryInfo
|
25
25
|
include Enumerable
|
26
26
|
|
@@ -42,7 +42,7 @@ module Vpim
|
|
42
42
|
# Decode +card+ into a DirectoryInfo object.
|
43
43
|
#
|
44
44
|
# +card+ may either be a something that is convertible to a string using
|
45
|
-
# #to_str or an
|
45
|
+
# #to_str or an Array of objects that can be joined into a string using
|
46
46
|
# #join("\n"), or an IO object (which will be read to end-of-file).
|
47
47
|
#
|
48
48
|
# The lines in the string may be delimited using IETF (CRLF) or Unix (LF) conventions.
|
@@ -108,7 +108,13 @@ module Vpim
|
|
108
108
|
#
|
109
109
|
# TODO - call this #texts(), as in the plural?
|
110
110
|
def text(name)
|
111
|
-
|
111
|
+
accum = []
|
112
|
+
each do |f|
|
113
|
+
if f.name? name
|
114
|
+
accum << f.to_text
|
115
|
+
end
|
116
|
+
end
|
117
|
+
accum
|
112
118
|
end
|
113
119
|
|
114
120
|
# Array of all the Field#group()s.
|
@@ -161,9 +167,9 @@ module Vpim
|
|
161
167
|
# end
|
162
168
|
# end
|
163
169
|
#
|
164
|
-
# or to get an array of all the fields in group '
|
170
|
+
# or to get an array of all the fields in group 'AGROUP', you could do:
|
165
171
|
#
|
166
|
-
# card.enum_by_group('
|
172
|
+
# card.enum_by_group('AGROUP').to_a
|
167
173
|
def enum_by_group(group)
|
168
174
|
Enumerator.new(self, Proc.new { |field| field.group?(group) })
|
169
175
|
end
|
data/lib/vpim/field.rb
CHANGED
@@ -67,7 +67,7 @@ module Vpim
|
|
67
67
|
pvalues.each do |pvalue|
|
68
68
|
# check if we need to do any encoding
|
69
69
|
if Vpim::Methods.casecmp?(pname, 'ENCODING') && pvalue == :b64
|
70
|
-
pvalue = '
|
70
|
+
pvalue = 'B' # the RFC definition of the base64 param value
|
71
71
|
value = [ value.to_str ].pack('m').gsub("\n", '')
|
72
72
|
end
|
73
73
|
|
@@ -139,7 +139,7 @@ module Vpim
|
|
139
139
|
params = $3
|
140
140
|
|
141
141
|
# v2.1 params have no '=' sign, figure out what kind of param it
|
142
|
-
# is (either its a known encoding, or we treat it as a '
|
142
|
+
# is (either its a known encoding, or we treat it as a 'TYPE'
|
143
143
|
# param).
|
144
144
|
|
145
145
|
if $2 == ""
|
@@ -192,9 +192,9 @@ module Vpim
|
|
192
192
|
# name (a String) to either a single string or symbol, or an array of
|
193
193
|
# strings and symbols (parameters can be multi-valued).
|
194
194
|
#
|
195
|
-
# If '
|
195
|
+
# If 'ENCODING' => :b64 is specified as a parameter, the value will be
|
196
196
|
# base-64 encoded. If it's already base-64 encoded, then use String
|
197
|
-
# values ('
|
197
|
+
# values ('ENCODING' => 'B'), and no further encoding will be done by
|
198
198
|
# this routine.
|
199
199
|
#
|
200
200
|
# Currently handled value types are:
|
@@ -290,16 +290,21 @@ module Vpim
|
|
290
290
|
# Note: Both the RFC 2425 encoding param ("b", meaning base-64) and the
|
291
291
|
# vCard 2.1 encoding params ("base64", "quoted-printable", "8bit", and
|
292
292
|
# "7bit") are supported.
|
293
|
+
#
|
294
|
+
# FIXME:
|
295
|
+
# - should use the VALUE parameter
|
296
|
+
# - should also take a default value type, so it can be converted
|
297
|
+
# if VALUE parameter is not present.
|
293
298
|
def value
|
294
299
|
case encoding
|
295
|
-
when nil, '
|
300
|
+
when nil, '8BIT', '7BIT' then @value
|
296
301
|
|
297
302
|
# Hack - if the base64 lines started with 2 SPC chars, which is invalid,
|
298
303
|
# there will be extra spaces in @value. Since no SPC chars show up in
|
299
304
|
# b64 encodings, they can be safely stripped out before unpacking.
|
300
|
-
when '
|
305
|
+
when 'B', 'BASE64' then @value.gsub(' ', '').unpack('m*').first
|
301
306
|
|
302
|
-
when '
|
307
|
+
when 'QUOTED-PRINTABLE' then @value.unpack('M*').first
|
303
308
|
|
304
309
|
else
|
305
310
|
raise Vpim::InvalidEncodingError, "unrecognized encoding (#{encoding})"
|
@@ -346,7 +351,7 @@ module Vpim
|
|
346
351
|
def type?(type)
|
347
352
|
type = type.to_str
|
348
353
|
|
349
|
-
types = param('
|
354
|
+
types = param('TYPE')
|
350
355
|
|
351
356
|
if types
|
352
357
|
types = types.detect { |t| Vpim::Methods.casecmp?(t, type) }
|
@@ -354,18 +359,18 @@ module Vpim
|
|
354
359
|
end
|
355
360
|
|
356
361
|
# Is this field marked as preferred? A vCard field is preferred if
|
357
|
-
# #type?('
|
362
|
+
# #type?('PREF'). This method is not necessarily meaningful for
|
358
363
|
# non-vCard profiles.
|
359
364
|
def pref?
|
360
|
-
type? '
|
365
|
+
type? 'PREF'
|
361
366
|
end
|
362
367
|
|
363
368
|
# Set whether a field is marked as preferred. See #pref?
|
364
369
|
def pref=(ispref)
|
365
370
|
if ispref
|
366
|
-
pvalue_iadd('
|
371
|
+
pvalue_iadd('TYPE', 'PREF')
|
367
372
|
else
|
368
|
-
pvalue_idel('
|
373
|
+
pvalue_idel('TYPE', 'PREF')
|
369
374
|
end
|
370
375
|
end
|
371
376
|
|
@@ -378,13 +383,13 @@ module Vpim
|
|
378
383
|
# The value of the ENCODING parameter, if present, or nil if not
|
379
384
|
# present.
|
380
385
|
def encoding
|
381
|
-
e = param(
|
386
|
+
e = param('ENCODING')
|
382
387
|
|
383
388
|
if e
|
384
389
|
if e.length > 1
|
385
|
-
raise Vpim::InvalidEncodingError, "multi-valued param '
|
390
|
+
raise Vpim::InvalidEncodingError, "multi-valued param 'ENCODING' (#{e})"
|
386
391
|
end
|
387
|
-
e = e.first.
|
392
|
+
e = e.first.upcase
|
388
393
|
end
|
389
394
|
e
|
390
395
|
end
|
@@ -392,10 +397,10 @@ module Vpim
|
|
392
397
|
# The type of the value, as specified by the VALUE parameter, nil if
|
393
398
|
# unspecified.
|
394
399
|
def kind
|
395
|
-
v = param('
|
400
|
+
v = param('VALUE')
|
396
401
|
if v
|
397
402
|
if v.size > 1
|
398
|
-
raise InvalidEncodingError, "multi-valued param '
|
403
|
+
raise InvalidEncodingError, "multi-valued param 'VALUE' (#{values})"
|
399
404
|
end
|
400
405
|
v = v.first
|
401
406
|
end
|
@@ -465,7 +470,7 @@ module Vpim
|
|
465
470
|
# characters, this method will strip them, if present.
|
466
471
|
#
|
467
472
|
# In theory, #value could also do this, but it would need to know that
|
468
|
-
# the value is of type '
|
473
|
+
# the value is of type 'TEXT', and often for text values the 'VALUE'
|
469
474
|
# parameter is not present, so knowledge of the expected type of the
|
470
475
|
# field is required from the decoder.
|
471
476
|
def to_text
|
@@ -502,10 +507,10 @@ module Vpim
|
|
502
507
|
# currently has. See Field.create() for a description of +pvalue+.
|
503
508
|
#
|
504
509
|
# Example:
|
505
|
-
# if field['
|
506
|
-
# field['
|
510
|
+
# if field['TYPE']
|
511
|
+
# field['TYPE'] << 'HOME'
|
507
512
|
# else
|
508
|
-
# field['
|
513
|
+
# field['TYPE'] = [ 'HOME' ]
|
509
514
|
# end
|
510
515
|
#
|
511
516
|
# TODO - this could be an alias to #pvalue_set
|
data/lib/vpim/icalendar.rb
CHANGED
@@ -12,106 +12,6 @@ require 'vpim/rrule'
|
|
12
12
|
require 'vpim/vevent'
|
13
13
|
require 'vpim/vpim'
|
14
14
|
|
15
|
-
=begin
|
16
|
-
|
17
|
-
... ; y/n (whether I've seen it in Apple's calendars)
|
18
|
-
name
|
19
|
-
section
|
20
|
-
type/comments
|
21
|
-
|
22
|
-
|
23
|
-
icalbody = icalprops component
|
24
|
-
|
25
|
-
icalprops =
|
26
|
-
prodid / ; y PRODID 4.7.3 required, TEXT
|
27
|
-
version / ; y 4.7.4 required, TEXT, "2.0"
|
28
|
-
calscal / ; y 4.7.1 only defined value is GREGORIAN
|
29
|
-
method / ; n METHOD 4.7.2 used with transport protocols
|
30
|
-
|
31
|
-
component =
|
32
|
-
eventc / ; y VEVENT 4.6.1
|
33
|
-
todoc / ; y VTODO 4.6.2
|
34
|
-
journalc / ; n
|
35
|
-
freebusyc / ; n
|
36
|
-
timezonec / ; n
|
37
|
-
|
38
|
-
alarmc ; y VALARM 4.6.6 occurs inside a VEVENT or a VTODO
|
39
|
-
|
40
|
-
class ; y CLASS 4.8.1.3 private/public/confidentical/... (default=public)
|
41
|
-
|
42
|
-
comment ; n 4.8.1.4 TEXT
|
43
|
-
description ; y 4.8.1.5 TEXT
|
44
|
-
summary ; y 4.8.1.12 TEXT
|
45
|
-
location ; y 4.8.1.7 TEXT intended venue
|
46
|
-
|
47
|
-
priority ; n why? 4.8.1.9 INTEGER, why isn't this seen for my TODO items?
|
48
|
-
|
49
|
-
status ; y 4.8.1.11 TEXT, different values defined for event, todo, journal
|
50
|
-
|
51
|
-
Event: TENTATIVE, CONFIRMED, CANCELLED
|
52
|
-
|
53
|
-
Todo: NEEDS-ACTION, COMPLETED, IN-PROCESS, CANCELLED
|
54
|
-
|
55
|
-
Journal: DRAFT, FINAL, CANCELLED
|
56
|
-
|
57
|
-
dtstart ; y DTSTART 4.8.2.4 DATE-TIME is default, value=date can be set
|
58
|
-
dtend ; y DTEND 4.8.2.2 Unless it has Z (UTC), or a tzid, then it is local-time.
|
59
|
-
|
60
|
-
dtstamp ; y DTSTAMP 4.8.7.2 DATE-TIME, creation time, inclusion is mandatory, but what does
|
61
|
-
it mean? It seems to be when the icalendar was actually created (as opposed to when the user entered
|
62
|
-
the information into the calendar database, for example), but in that case my Apple icalendars should
|
63
|
-
have all components having the same DTSTAMP, but they don't!
|
64
|
-
|
65
|
-
duration ; y DURATION 4.8.2.5 dur-value
|
66
|
-
|
67
|
-
dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
|
68
|
-
|
69
|
-
dur-date = dur-day [dur-time]
|
70
|
-
= 1*DIGIT "D" [ dur-time ]
|
71
|
-
|
72
|
-
dur-time = "T" (dur-hour / dur-minute / dur-second)
|
73
|
-
= "T" (
|
74
|
-
1*DIGIT "H" [ 1*DIGIT "M" [ 1*DIGIT "S" ] ] /
|
75
|
-
1*DIGIT "M" [ 1*DIGIT "S" ] /
|
76
|
-
1*DIGIT "S"
|
77
|
-
)
|
78
|
-
|
79
|
-
dur-week = 1*DIGIT "W"
|
80
|
-
dur-day = 1*DIGIT "D"
|
81
|
-
dur-hour = 1*DIGIT "H" [dur-minute]
|
82
|
-
dur-minute = 1*DIGIT "M" [dur-second]
|
83
|
-
dur-second = 1*DIGIT "S"
|
84
|
-
|
85
|
-
The EBNF is complicated, because they want to say that /some/ component
|
86
|
-
must be present, and that if you have a "T", you need a time after it,
|
87
|
-
and that you can't have an hour followed by seconds with no intervening
|
88
|
-
minutes... but we don't care about that during decoding, so we rewrite
|
89
|
-
the EBNF as:
|
90
|
-
|
91
|
-
dur-value = ["+" / "-"] "P" [ 1*DIGIT "W" ] [ 1*DIGIT "D" ] [ "T" [ 1*DIGIT "H" ] [ 1*DIGIT "M" ] [ 1*DIGIT "S" ] ]
|
92
|
-
|
93
|
-
dtdue ; n DTDUE 4.8.2.3
|
94
|
-
|
95
|
-
uid ; y UID 4.8.4.7 TEXT, recommended to generate them in RFC822 form
|
96
|
-
|
97
|
-
rrule ; y RRULE 4.8.5.4 RECUR, can occur multiple times!
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
VEVENT Ifx:
|
102
|
-
|
103
|
-
TEXT: summary, description, comment, location, uid
|
104
|
-
|
105
|
-
think about: uid
|
106
|
-
|
107
|
-
Vevent#status -> The status, upper-case.
|
108
|
-
Vevent#status= -> set a new status, only allow the defined statuses!
|
109
|
-
Vevent#status?(s) -> check if the status is s
|
110
|
-
|
111
|
-
can contain alarms... should it include an alarms module?
|
112
|
-
|
113
|
-
=end
|
114
|
-
|
115
15
|
module Vpim
|
116
16
|
# An iCalendar.
|
117
17
|
#
|
@@ -167,12 +67,13 @@ module Vpim
|
|
167
67
|
# Categorize the components
|
168
68
|
@vevents = []
|
169
69
|
@vtodos = []
|
70
|
+
@vjournals = []
|
170
71
|
@others = []
|
171
72
|
|
172
73
|
inner.each do |component|
|
173
74
|
# First field in every component should be a "BEGIN:".
|
174
75
|
name = component.first
|
175
|
-
if ! name.name? '
|
76
|
+
if ! name.name? 'BEGIN'
|
176
77
|
raise InvalidEncodingError, "calendar component begins with #{name.name}, instead of BEGIN!"
|
177
78
|
end
|
178
79
|
|
@@ -181,6 +82,7 @@ module Vpim
|
|
181
82
|
case name
|
182
83
|
when 'VEVENT' then @vevents << Vevent.new(component)
|
183
84
|
when 'VTODO' then @vtodos << Vtodo.new(component)
|
85
|
+
when 'VJOURNAL' then @vjournals << Vjournal.new(component)
|
184
86
|
else @others << component
|
185
87
|
end
|
186
88
|
end
|
@@ -255,6 +157,8 @@ module Vpim
|
|
255
157
|
@vevents << component
|
256
158
|
when Vtodo
|
257
159
|
@vtodos << component
|
160
|
+
when Vjournal
|
161
|
+
@vjournals << component
|
258
162
|
else
|
259
163
|
raise ArgumentError, "can't add component type #{component.type} to a calendar"
|
260
164
|
end
|
@@ -359,23 +263,29 @@ module Vpim
|
|
359
263
|
# transport a snapshot of some calendar information; without the intention
|
360
264
|
# of conveying a scheduling semantic.
|
361
265
|
#
|
362
|
-
# Note that this can't be called
|
266
|
+
# Note that this method can't be called +method+, thats already a method of
|
267
|
+
# Object.
|
363
268
|
def protocol
|
364
269
|
m = @properties['METHOD']
|
365
270
|
m ? m.upcase : m
|
366
271
|
end
|
367
272
|
|
368
|
-
# The array of all calendar
|
273
|
+
# The array of all calendar event components (each is a Vevent).
|
369
274
|
#
|
370
275
|
# TODO - should this take an interval: t0,t1?
|
371
276
|
def events
|
372
277
|
@vevents
|
373
278
|
end
|
374
279
|
|
375
|
-
# The array of all calendar
|
280
|
+
# The array of all calendar todo components (each is a Vtodo).
|
376
281
|
def todos
|
377
282
|
@vtodos
|
378
283
|
end
|
284
|
+
|
285
|
+
# The array of all calendar journal components (each is a Vjournal).
|
286
|
+
def journals
|
287
|
+
@vjournals
|
288
|
+
end
|
379
289
|
end
|
380
290
|
|
381
291
|
end
|
@@ -488,6 +398,10 @@ module Vpim
|
|
488
398
|
end
|
489
399
|
end
|
490
400
|
|
401
|
+
def inspect
|
402
|
+
"#<Vpim::Icalendar::Address:cn=#{cn.inspect} status=#{partstat} rsvp?=#{rsvp} #{uri.inspect}>"
|
403
|
+
end
|
404
|
+
|
491
405
|
# The participation role for the calendar user specified by the address.
|
492
406
|
#
|
493
407
|
# The standard roles are:
|
@@ -526,13 +440,15 @@ module Vpim
|
|
526
440
|
#
|
527
441
|
# See #partstat.
|
528
442
|
def partstat=(status)
|
529
|
-
@field['
|
443
|
+
@field['PARTSTAT'] = status.to_str
|
530
444
|
status
|
531
445
|
end
|
532
446
|
|
533
447
|
# The value of the RSVP field, either +true+ or +false+. It is used to
|
534
448
|
# specify whether there is an expectation of a favor of a reply from the
|
535
449
|
# calendar user specified by the property value.
|
450
|
+
#
|
451
|
+
# TODO - should be #rsvp?
|
536
452
|
def rsvp
|
537
453
|
return false unless r = @field.param('RSVP')
|
538
454
|
r = r.first
|
data/lib/vpim/maker/vcard.rb
CHANGED
@@ -16,6 +16,7 @@ module Vpim
|
|
16
16
|
# - link:ex_mkvcard.txt: example of creating a vCard
|
17
17
|
# - link:ex_cpvcard.txt: example of copying and them modifying a vCard
|
18
18
|
# - link:ex_mkv21vcard.txt: example of creating version 2.1 vCard
|
19
|
+
# - link:ex_mkyourown.txt: example of adding support for new fields to Maker::Vcard
|
19
20
|
class Vcard
|
20
21
|
# Make a vCard.
|
21
22
|
#
|
@@ -80,16 +81,13 @@ module Vpim
|
|
80
81
|
#
|
81
82
|
# All attributes are optional.
|
82
83
|
#
|
83
|
-
# Warning: This is the only mandatory field besides the full name, FN
|
84
|
-
#
|
85
|
-
# string "#{prefix} #{given} #{additional} #{family},
|
86
|
-
#
|
87
|
-
# FIXME: is it possible to deduce given/family from the full_name?
|
88
|
-
#
|
89
|
-
# FIXME: Each attribute can currently only have a single String value.
|
90
|
-
#
|
91
|
-
# FIXME: Need to escape specials in the String.
|
84
|
+
# Warning: This is the only mandatory field besides the full name, FN.
|
85
|
+
# FN: can be set in #make, or by #fullname=, and if not set will be
|
86
|
+
# constucted as the string "#{prefix} #{given} #{additional} #{family},
|
87
|
+
# #{suffix}".
|
92
88
|
def add_name # :yield: n
|
89
|
+
# FIXME: Each attribute can currently only have a single String value.
|
90
|
+
# FIXME: Need to escape specials in the String.
|
93
91
|
x = Struct.new(:family, :given, :additional, :prefix, :suffix).new
|
94
92
|
yield x
|
95
93
|
@card << Vpim::DirectoryInfo::Field.create(
|
@@ -101,8 +99,8 @@ module Vpim
|
|
101
99
|
|
102
100
|
# Add a full name field, FN.
|
103
101
|
#
|
104
|
-
# Normally the FN field value is derived from the N: field value,
|
105
|
-
# it can be explicitly set.
|
102
|
+
# Normally the FN field value is derived from the N: field value, see
|
103
|
+
# #add_name, but it can be explicitly set.
|
106
104
|
def fullname=(fullname)
|
107
105
|
if @card.field('FN')
|
108
106
|
raise Vpim::InvalidEncodingError, "Not allowed to add more than one FN field to a vCard."
|
@@ -130,9 +128,8 @@ module Vpim
|
|
130
128
|
# strings.
|
131
129
|
#
|
132
130
|
# TODO - Add #label to support LABEL.
|
133
|
-
#
|
134
|
-
# FIXME - Need to escape specials in the String.
|
135
131
|
def add_addr # :yield: adr
|
132
|
+
# FIXME - Need to escape specials in the String.
|
136
133
|
x = Struct.new(
|
137
134
|
:location, :preferred, :delivery,
|
138
135
|
:pobox, :extended, :street, :locality, :region, :postalcode, :country
|
@@ -143,12 +140,12 @@ module Vpim
|
|
143
140
|
|
144
141
|
# All these attributes go into the TYPE parameter.
|
145
142
|
params = [ x[:location], x[:delivery] ]
|
146
|
-
params << '
|
143
|
+
params << 'PREF' if x[:preferred]
|
147
144
|
params = params.flatten.uniq.compact.map { |s| s.to_str }
|
148
145
|
|
149
146
|
paramshash = {}
|
150
147
|
|
151
|
-
paramshash['
|
148
|
+
paramshash['TYPE'] = params if params.first
|
152
149
|
|
153
150
|
@card << Vpim::DirectoryInfo::Field.create( 'ADR', values, paramshash)
|
154
151
|
self
|
@@ -172,11 +169,11 @@ module Vpim
|
|
172
169
|
|
173
170
|
yield x
|
174
171
|
|
175
|
-
x[:preferred] = '
|
172
|
+
x[:preferred] = 'PREF' if x[:preferred]
|
176
173
|
|
177
174
|
types = x.to_a.flatten.uniq.compact.map { |s| s.to_str }
|
178
175
|
|
179
|
-
params['
|
176
|
+
params['TYPE'] = types if types.first
|
180
177
|
end
|
181
178
|
|
182
179
|
@card << Vpim::DirectoryInfo::Field.create( 'TEL', number, params)
|
@@ -198,11 +195,11 @@ module Vpim
|
|
198
195
|
|
199
196
|
yield x
|
200
197
|
|
201
|
-
x[:preferred] = '
|
198
|
+
x[:preferred] = 'PREF' if x[:preferred]
|
202
199
|
|
203
200
|
types = x.to_a.flatten.uniq.compact.map { |s| s.to_str }
|
204
201
|
|
205
|
-
params['
|
202
|
+
params['TYPE'] = types if types.first
|
206
203
|
end
|
207
204
|
|
208
205
|
@card << Vpim::DirectoryInfo::Field.create( 'EMAIL', email, params)
|
@@ -226,6 +223,7 @@ module Vpim
|
|
226
223
|
end
|
227
224
|
@card << Vpim::DirectoryInfo::Field.create( 'BDAY', birthday );
|
228
225
|
end
|
226
|
+
|
229
227
|
=begin
|
230
228
|
TODO - need text=() implemented in Field
|
231
229
|
|
@@ -269,11 +267,11 @@ TODO - need text=() implemented in Field
|
|
269
267
|
|
270
268
|
yield x
|
271
269
|
|
272
|
-
x[:preferred] = '
|
270
|
+
x[:preferred] = 'PREF' if x[:preferred]
|
273
271
|
|
274
|
-
types = x.to_a.flatten.uniq.compact.map { |s| s.
|
272
|
+
types = x.to_a.flatten.uniq.compact.map { |s| s.upcase }
|
275
273
|
|
276
|
-
params['
|
274
|
+
params['TYPE'] = types if types.first
|
277
275
|
end
|
278
276
|
|
279
277
|
@card << Vpim::DirectoryInfo::Field.create( 'IMPP', url, params)
|
@@ -299,11 +297,11 @@ TODO - need text=() implemented in Field
|
|
299
297
|
|
300
298
|
yield x
|
301
299
|
|
302
|
-
x[:preferred] = '
|
300
|
+
x[:preferred] = 'PREF' if x[:preferred]
|
303
301
|
|
304
|
-
types = x.to_a.flatten.uniq.compact.map { |s| s.
|
302
|
+
types = x.to_a.flatten.uniq.compact.map { |s| s.upcase }
|
305
303
|
|
306
|
-
params['
|
304
|
+
params['TYPE'] = types if types.first
|
307
305
|
end
|
308
306
|
|
309
307
|
@card << Vpim::DirectoryInfo::Field.create( 'X-AIM', xaim, params)
|
@@ -346,12 +344,12 @@ TODO - need text=() implemented in Field
|
|
346
344
|
params = {}
|
347
345
|
|
348
346
|
# Don't set type to the empty string.
|
349
|
-
params['
|
347
|
+
params['TYPE'] = x[:type] if( x[:type] && x[:type].length > 0 )
|
350
348
|
|
351
349
|
if x[:link]
|
352
|
-
params['
|
350
|
+
params['VALUE'] = 'URI'
|
353
351
|
else # it's inline, base-64 encode it
|
354
|
-
params['
|
352
|
+
params['ENCODING'] = :b64
|
355
353
|
if !x[:type]
|
356
354
|
raise Vpim::InvalidEncodingError, 'Inline image data must have it\'s type set.'
|
357
355
|
end
|
@@ -361,6 +359,11 @@ TODO - need text=() implemented in Field
|
|
361
359
|
self
|
362
360
|
end
|
363
361
|
|
362
|
+
# Add a URL field, URL:.
|
363
|
+
def add_url(url)
|
364
|
+
@card << Vpim::DirectoryInfo::Field.create( 'URL', url.to_str );
|
365
|
+
end
|
366
|
+
|
364
367
|
# Add a Field, +field+.
|
365
368
|
def add_field(field)
|
366
369
|
fieldname = field.name.upcase
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Vpim
|
2
|
+
class Icalendar
|
3
|
+
module Property #:nodoc:
|
4
|
+
|
5
|
+
# FIXME - these should be part of Dirinfo
|
6
|
+
module Base
|
7
|
+
# Value of first property with name +name+
|
8
|
+
def propvalue(name) #:nodoc:
|
9
|
+
prop = @properties.detect { |f| f.name? name }
|
10
|
+
if prop
|
11
|
+
prop = prop.value
|
12
|
+
end
|
13
|
+
prop
|
14
|
+
end
|
15
|
+
|
16
|
+
def proptoken(name, allowed, default_token = nil) #:nodoc:
|
17
|
+
prop = propvalue name
|
18
|
+
|
19
|
+
if prop
|
20
|
+
prop = prop.to_str.upcase
|
21
|
+
unless allowed.include?(prop)
|
22
|
+
raise Vpim::InvalidEncodingError, "Invalid #{name} value '#{prop}'"
|
23
|
+
end
|
24
|
+
else
|
25
|
+
prop = default_token
|
26
|
+
end
|
27
|
+
|
28
|
+
prop
|
29
|
+
end
|
30
|
+
|
31
|
+
# Value as DATE-TIME or DATE of object of first property with name +name+
|
32
|
+
def proptime(name) #:nodoc:
|
33
|
+
prop = @properties.detect { |f| f.name? name }
|
34
|
+
if prop
|
35
|
+
prop = prop.to_time.first
|
36
|
+
end
|
37
|
+
prop
|
38
|
+
end
|
39
|
+
|
40
|
+
# Value as TEXT of first property with name +name+
|
41
|
+
def proptext(name) #:nodoc:
|
42
|
+
prop = @properties.detect { |f| f.name? name }
|
43
|
+
if prop
|
44
|
+
prop = prop.to_text
|
45
|
+
end
|
46
|
+
prop
|
47
|
+
end
|
48
|
+
|
49
|
+
# Array of values as TEXT of all properties with name +name+
|
50
|
+
def proptextarray(name) #:nodoc:
|
51
|
+
@properties.select{ |f| f.name? name }.map{ |p| p.to_text }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Array of values as TEXT list of all properties with name +name+
|
55
|
+
def proptextlistarray(name) #:nodoc:
|
56
|
+
@properties.select{ |f| f.name? name }.map{ |p| Vpim.decode_text_list(p.value_raw) }.flatten
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|