vcard 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +15 -5
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +17 -0
- data/Rakefile +4 -52
- data/{LICENSE → VPIM-LICENSE.txt} +2 -2
- data/lib/vcard.rb +304 -28
- data/lib/vcard/attachment.rb +10 -12
- data/lib/vcard/bnf.rb +66 -0
- data/lib/vcard/dirinfo.rb +24 -26
- data/lib/vcard/enumerator.rb +5 -7
- data/lib/vcard/errors.rb +23 -0
- data/lib/vcard/field.rb +56 -58
- data/lib/vcard/vcard.rb +210 -240
- data/lib/vcard/version.rb +3 -0
- data/test/field_test.rb +55 -55
- data/test/fixtures/bday_decode.vcard +3 -0
- data/test/fixtures/bday_decode_2.vcard +6 -0
- data/test/fixtures/empty_tel.vcard +3 -0
- data/test/fixtures/ex1.vcard +7 -0
- data/test/fixtures/ex2.vcard +9 -0
- data/test/fixtures/ex3.vcard +30 -0
- data/test/fixtures/ex_21.vcard +16 -0
- data/test/fixtures/ex_21_case0.vcard +15 -0
- data/test/fixtures/ex_apple1.vcard +13 -0
- data/test/fixtures/ex_attach.vcard +16 -0
- data/test/fixtures/ex_bdays.vcard +8 -0
- data/test/fixtures/ex_encode_1.vcard +10 -0
- data/test/fixtures/ex_ical_1.vcal +47 -0
- data/test/fixtures/gmail.vcard +27 -0
- data/test/fixtures/highrise.vcard +41 -0
- data/test/fixtures/multiple_occurences_of_type.vcard +17 -0
- data/test/fixtures/nickname0.vcard +2 -0
- data/test/fixtures/nickname1.vcard +3 -0
- data/test/fixtures/nickname2.vcard +3 -0
- data/test/fixtures/nickname3.vcard +3 -0
- data/test/fixtures/nickname4.vcard +4 -0
- data/test/fixtures/nickname5.vcard +5 -0
- data/test/fixtures/slash_in_field_name.vcard +3 -0
- data/test/fixtures/tst1.vcard +9 -0
- data/test/fixtures/url_decode.vcard +4 -0
- data/test/test_helper.rb +34 -6
- data/test/vcard_test.rb +87 -577
- data/vcard.gemspec +19 -0
- metadata +88 -43
- data/.document +0 -5
- data/README.rdoc +0 -7
- data/VERSION +0 -1
- data/lib/vcard/rfc2425.rb +0 -367
data/lib/vcard/vcard.rb
CHANGED
@@ -1,15 +1,10 @@
|
|
1
|
-
|
2
|
-
Copyright (C) 2008 Sam Roberts
|
1
|
+
# Copyright (C) 2008 Sam Roberts
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
=end
|
3
|
+
# This library is free software; you can redistribute it and/or modify
|
4
|
+
# it under the same terms as the ruby language itself, see the file
|
5
|
+
# LICENSE-VPIM.txt for details.
|
8
6
|
|
9
|
-
|
10
|
-
require 'stringio'
|
11
|
-
|
12
|
-
module Vpim
|
7
|
+
module Vcard
|
13
8
|
# A vCard, a specialization of a directory info object.
|
14
9
|
#
|
15
10
|
# The vCard format is specified by:
|
@@ -118,7 +113,7 @@ module Vpim
|
|
118
113
|
# TODO - Add #label to support LABEL. Try to find LABEL
|
119
114
|
# in either same group, or with sam params.
|
120
115
|
@@adr_parts.each do |part|
|
121
|
-
instance_variable_set(part,
|
116
|
+
instance_variable_set(part, "")
|
122
117
|
end
|
123
118
|
|
124
119
|
@location = []
|
@@ -132,39 +127,39 @@ module Vpim
|
|
132
127
|
instance_variable_get(part)
|
133
128
|
end
|
134
129
|
|
135
|
-
value =
|
130
|
+
value = ::Vcard.encode_text_list(parts, ";")
|
136
131
|
|
137
132
|
params = [ @location, @delivery, @nonstandard ]
|
138
|
-
params <<
|
133
|
+
params << "pref" if @preferred
|
139
134
|
params = params.flatten.compact.map { |s| s.to_str.downcase }.uniq
|
140
135
|
|
141
136
|
paramshash = {}
|
142
137
|
|
143
|
-
paramshash[
|
138
|
+
paramshash["TYPE"] = params if params.first
|
144
139
|
|
145
|
-
|
140
|
+
::Vcard::DirectoryInfo::Field.create( "ADR", value, paramshash)
|
146
141
|
end
|
147
142
|
|
148
143
|
def Address.decode(card, field) #:nodoc:
|
149
144
|
adr = new
|
150
145
|
|
151
|
-
parts =
|
146
|
+
parts = ::Vcard.decode_text_list(field.value_raw, ";")
|
152
147
|
|
153
148
|
@@adr_parts.each_with_index do |part,i|
|
154
|
-
adr.instance_variable_set(part, parts[i] ||
|
149
|
+
adr.instance_variable_set(part, parts[i] || "")
|
155
150
|
end
|
156
151
|
|
157
|
-
params = field.pvalues(
|
152
|
+
params = field.pvalues("TYPE")
|
158
153
|
|
159
154
|
if params
|
160
155
|
params.each do |p|
|
161
156
|
p.downcase!
|
162
157
|
case p
|
163
|
-
when
|
158
|
+
when "home", "work"
|
164
159
|
adr.location << p
|
165
|
-
when
|
160
|
+
when "postal", "parcel", "dom", "intl"
|
166
161
|
adr.delivery << p
|
167
|
-
when
|
162
|
+
when "pref"
|
168
163
|
adr.preferred = true
|
169
164
|
else
|
170
165
|
adr.nonstandard << p
|
@@ -185,7 +180,7 @@ module Vpim
|
|
185
180
|
# true, false (boolean): whether this is the preferred email address
|
186
181
|
attr_accessor :preferred
|
187
182
|
# internet, x400 (String): the email address format, rarely specified
|
188
|
-
# since the default is
|
183
|
+
# since the default is "internet"
|
189
184
|
attr_accessor :format
|
190
185
|
# home, work (Array of String): the location referred to by the address. The
|
191
186
|
# inclusion of location parameters in a vCard seems to be non-conformant,
|
@@ -195,9 +190,9 @@ module Vpim
|
|
195
190
|
# might be found during decoding, but shouldn't be set during encoding.
|
196
191
|
attr_reader :nonstandard
|
197
192
|
|
198
|
-
def initialize(email=
|
193
|
+
def initialize(email="") #:nodoc:
|
199
194
|
@preferred = false
|
200
|
-
@format =
|
195
|
+
@format = "internet"
|
201
196
|
@location = []
|
202
197
|
@nonstandard = []
|
203
198
|
super(email)
|
@@ -206,7 +201,7 @@ module Vpim
|
|
206
201
|
def inspect #:nodoc:
|
207
202
|
s = "#<#{self.class.to_s}: #{to_str.inspect}"
|
208
203
|
s << ", pref" if preferred
|
209
|
-
s << ", #{format}" if format !=
|
204
|
+
s << ", #{format}" if format != "internet"
|
210
205
|
s << ", " << @location.join(", ") if @location.first
|
211
206
|
s << ", #{@nonstandard.join(", ")}" if @nonstandard.first
|
212
207
|
s
|
@@ -220,16 +215,16 @@ module Vpim
|
|
220
215
|
end
|
221
216
|
|
222
217
|
params = [ @location, @nonstandard ]
|
223
|
-
params << @format if @format !=
|
224
|
-
params <<
|
218
|
+
params << @format if @format != "internet"
|
219
|
+
params << "pref" if @preferred
|
225
220
|
|
226
221
|
params = params.flatten.compact.map { |s| s.to_str.downcase }.uniq
|
227
222
|
|
228
223
|
paramshash = {}
|
229
224
|
|
230
|
-
paramshash[
|
225
|
+
paramshash["TYPE"] = params if params.first
|
231
226
|
|
232
|
-
|
227
|
+
::Vcard::DirectoryInfo::Field.create("EMAIL", value, paramshash)
|
233
228
|
end
|
234
229
|
|
235
230
|
def Email.decode(field) #:nodoc:
|
@@ -241,17 +236,17 @@ module Vpim
|
|
241
236
|
|
242
237
|
eml = Email.new(value)
|
243
238
|
|
244
|
-
params = field.pvalues(
|
239
|
+
params = field.pvalues("TYPE")
|
245
240
|
|
246
241
|
if params
|
247
242
|
params.each do |p|
|
248
243
|
p.downcase!
|
249
244
|
case p
|
250
|
-
when
|
245
|
+
when "home", "work"
|
251
246
|
eml.location << p
|
252
|
-
when
|
247
|
+
when "pref"
|
253
248
|
eml.preferred = true
|
254
|
-
when
|
249
|
+
when "x400", "internet"
|
255
250
|
eml.format = p
|
256
251
|
else
|
257
252
|
eml.nonstandard << p
|
@@ -285,7 +280,7 @@ module Vpim
|
|
285
280
|
# might be found during decoding, but shouldn't be set during encoding.
|
286
281
|
attr_reader :nonstandard
|
287
282
|
|
288
|
-
def initialize(telephone=
|
283
|
+
def initialize(telephone="") #:nodoc:
|
289
284
|
@preferred = false
|
290
285
|
@location = []
|
291
286
|
@capability = []
|
@@ -310,15 +305,15 @@ module Vpim
|
|
310
305
|
end
|
311
306
|
|
312
307
|
params = [ @location, @capability, @nonstandard ]
|
313
|
-
params <<
|
308
|
+
params << "pref" if @preferred
|
314
309
|
|
315
310
|
params = params.flatten.compact.map { |s| s.to_str.downcase }.uniq
|
316
311
|
|
317
312
|
paramshash = {}
|
318
313
|
|
319
|
-
paramshash[
|
314
|
+
paramshash["TYPE"] = params if params.first
|
320
315
|
|
321
|
-
|
316
|
+
::Vcard::DirectoryInfo::Field.create( "TEL", value, paramshash)
|
322
317
|
end
|
323
318
|
|
324
319
|
def Telephone.decode(field) #:nodoc:
|
@@ -330,17 +325,17 @@ module Vpim
|
|
330
325
|
|
331
326
|
tel = Telephone.new(value)
|
332
327
|
|
333
|
-
params = field.pvalues(
|
328
|
+
params = field.pvalues("TYPE")
|
334
329
|
|
335
330
|
if params
|
336
331
|
params.each do |p|
|
337
332
|
p.downcase!
|
338
333
|
case p
|
339
|
-
when
|
334
|
+
when "home", "work", "cell", "car", "pager"
|
340
335
|
tel.location << p
|
341
|
-
when
|
336
|
+
when "voice", "fax", "video", "msg", "bbs", "modem", "isdn", "pcs"
|
342
337
|
tel.capability << p
|
343
|
-
when
|
338
|
+
when "pref"
|
344
339
|
tel.preferred = true
|
345
340
|
else
|
346
341
|
tel.nonstandard << p
|
@@ -379,15 +374,15 @@ module Vpim
|
|
379
374
|
# Override the attr reader to make it dynamic
|
380
375
|
remove_method :formatted
|
381
376
|
def formatted #:nodoc:
|
382
|
-
f = [ @prefix, @given, @additional, @family ].map{|i| i ==
|
383
|
-
if @suffix !=
|
384
|
-
f <<
|
377
|
+
f = [ @prefix, @given, @additional, @family ].map{|i| i == "" ? nil : i.strip}.compact.join(" ")
|
378
|
+
if @suffix != ""
|
379
|
+
f << ", " << @suffix
|
385
380
|
end
|
386
381
|
f
|
387
382
|
end
|
388
383
|
|
389
|
-
def initialize(n=
|
390
|
-
n =
|
384
|
+
def initialize(n="", fn="") #:nodoc:
|
385
|
+
n = ::Vcard.decode_text_list(n, ";") do |item|
|
391
386
|
item.strip
|
392
387
|
end
|
393
388
|
|
@@ -402,18 +397,16 @@ module Vpim
|
|
402
397
|
end
|
403
398
|
|
404
399
|
def encode #:nodoc:
|
405
|
-
|
406
|
-
Vpim.encode_text_list([ @family, @given, @additional, @prefix, @suffix ].map{|n| n.strip}, ';')
|
407
|
-
)
|
400
|
+
::Vcard::DirectoryInfo::Field.create("N", ::Vcard.encode_text_list([ @family, @given, @additional, @prefix, @suffix ].map{|n| n.strip}, ";"))
|
408
401
|
end
|
402
|
+
|
409
403
|
def encode_fn #:nodoc:
|
410
404
|
fn = @fullname.strip
|
411
405
|
if @fullname.length == 0
|
412
406
|
fn = formatted
|
413
407
|
end
|
414
|
-
|
408
|
+
::Vcard::DirectoryInfo::Field.create("FN", fn)
|
415
409
|
end
|
416
|
-
|
417
410
|
end
|
418
411
|
|
419
412
|
def decode_invisible(field) #:nodoc:
|
@@ -429,19 +422,19 @@ module Vpim
|
|
429
422
|
end
|
430
423
|
|
431
424
|
def decode_text(field) #:nodoc:
|
432
|
-
Line.new( field.group, field.name,
|
425
|
+
Line.new( field.group, field.name, ::Vcard.decode_text(field.value_raw) )
|
433
426
|
end
|
434
427
|
|
435
428
|
def decode_n(field) #:nodoc:
|
436
|
-
Line.new( field.group, field.name, Name.new(field.value, self[
|
429
|
+
Line.new( field.group, field.name, Name.new(field.value, self["FN"]).freeze )
|
437
430
|
end
|
438
431
|
|
439
432
|
def decode_date_or_datetime(field) #:nodoc:
|
440
433
|
date = nil
|
441
434
|
begin
|
442
|
-
date =
|
443
|
-
rescue
|
444
|
-
date =
|
435
|
+
date = ::Vcard.decode_date_to_date(field.value_raw)
|
436
|
+
rescue ::Vcard::InvalidEncodingError
|
437
|
+
date = ::Vcard.decode_date_time_to_datetime(field.value_raw)
|
445
438
|
end
|
446
439
|
Line.new( field.group, field.name, date )
|
447
440
|
end
|
@@ -450,7 +443,7 @@ module Vpim
|
|
450
443
|
begin
|
451
444
|
return decode_date_or_datetime(field)
|
452
445
|
|
453
|
-
rescue
|
446
|
+
rescue ::Vcard::InvalidEncodingError
|
454
447
|
# Hack around BDAY dates hat are correct in the month and day, but have
|
455
448
|
# some kind of garbage in the year.
|
456
449
|
if field.value =~ /^\s*(\d+)-(\d+)-(\d+)\s*$/
|
@@ -468,7 +461,7 @@ module Vpim
|
|
468
461
|
end
|
469
462
|
|
470
463
|
def decode_geo(field) #:nodoc:
|
471
|
-
geo =
|
464
|
+
geo = ::Vcard.decode_list(field.value_raw, ";") do |item| item.to_f end
|
472
465
|
Line.new( field.group, field.name, geo )
|
473
466
|
end
|
474
467
|
|
@@ -485,13 +478,11 @@ module Vpim
|
|
485
478
|
end
|
486
479
|
|
487
480
|
def decode_list_of_text(field) #:nodoc:
|
488
|
-
Line.new(
|
489
|
-
Vpim.decode_text_list(field.value_raw).select{|t| t.length > 0}.uniq
|
490
|
-
)
|
481
|
+
Line.new(field.group, field.name, ::Vcard.decode_text_list(field.value_raw).select{|t| t.length > 0}.uniq)
|
491
482
|
end
|
492
483
|
|
493
484
|
def decode_structured_text(field) #:nodoc:
|
494
|
-
Line.new( field.group, field.name,
|
485
|
+
Line.new( field.group, field.name, ::Vcard.decode_text_list(field.value_raw, ";") )
|
495
486
|
end
|
496
487
|
|
497
488
|
def decode_uri(field) #:nodoc:
|
@@ -500,52 +491,52 @@ module Vpim
|
|
500
491
|
|
501
492
|
def decode_agent(field) #:nodoc:
|
502
493
|
case field.kind
|
503
|
-
when
|
494
|
+
when "text"
|
504
495
|
decode_text(field)
|
505
|
-
when
|
496
|
+
when "uri"
|
506
497
|
decode_uri(field)
|
507
|
-
when
|
508
|
-
Line.new( field.group, field.name, Vcard.decode(
|
498
|
+
when "vcard", nil
|
499
|
+
Line.new( field.group, field.name, ::Vcard.decode(::Vcard.decode_text(field.value_raw)).first )
|
509
500
|
else
|
510
501
|
raise InvalidEncodingError, "AGENT type #{field.kind} is not allowed"
|
511
502
|
end
|
512
503
|
end
|
513
504
|
|
514
505
|
def decode_attachment(field) #:nodoc:
|
515
|
-
Line.new( field.group, field.name, Attachment.decode(field,
|
506
|
+
Line.new( field.group, field.name, Attachment.decode(field, "binary", "TYPE") )
|
516
507
|
end
|
517
508
|
|
518
509
|
@@decode = {
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
510
|
+
"BEGIN" => :decode_invisible, # Don't return delimiter
|
511
|
+
"END" => :decode_invisible, # Don't return delimiter
|
512
|
+
"FN" => :decode_invisible, # Returned as part of N.
|
513
|
+
|
514
|
+
"ADR" => :decode_address,
|
515
|
+
"AGENT" => :decode_agent,
|
516
|
+
"BDAY" => :decode_bday,
|
517
|
+
"CATEGORIES" => :decode_list_of_text,
|
518
|
+
"EMAIL" => :decode_email,
|
519
|
+
"GEO" => :decode_geo,
|
520
|
+
"KEY" => :decode_attachment,
|
521
|
+
"LOGO" => :decode_attachment,
|
522
|
+
"MAILER" => :decode_text,
|
523
|
+
"N" => :decode_n,
|
524
|
+
"NAME" => :decode_text,
|
525
|
+
"NICKNAME" => :decode_list_of_text,
|
526
|
+
"NOTE" => :decode_text,
|
527
|
+
"ORG" => :decode_structured_text,
|
528
|
+
"PHOTO" => :decode_attachment,
|
529
|
+
"PRODID" => :decode_text,
|
530
|
+
"PROFILE" => :decode_text,
|
531
|
+
"REV" => :decode_date_or_datetime,
|
532
|
+
"ROLE" => :decode_text,
|
533
|
+
"SOUND" => :decode_attachment,
|
534
|
+
"SOURCE" => :decode_text,
|
535
|
+
"TEL" => :decode_telephone,
|
536
|
+
"TITLE" => :decode_text,
|
537
|
+
"UID" => :decode_text,
|
538
|
+
"URL" => :decode_uri,
|
539
|
+
"VERSION" => :decode_version,
|
549
540
|
}
|
550
541
|
|
551
542
|
@@decode.default = :decode_default
|
@@ -567,7 +558,7 @@ module Vpim
|
|
567
558
|
attr_reader :value
|
568
559
|
|
569
560
|
def initialize(group, name, value) #:nodoc:
|
570
|
-
@group, @name, @value = (group||
|
561
|
+
@group, @name, @value = (group||""), name.to_str, value
|
571
562
|
end
|
572
563
|
|
573
564
|
def self.decode(decode, card, field) #:nodoc:
|
@@ -598,7 +589,7 @@ module Vpim
|
|
598
589
|
unless block_given?
|
599
590
|
map do |f|
|
600
591
|
if( !name || f.name?(name) )
|
601
|
-
|
592
|
+
f2l(f)
|
602
593
|
else
|
603
594
|
nil
|
604
595
|
end
|
@@ -625,9 +616,9 @@ module Vpim
|
|
625
616
|
|
626
617
|
# Create a vCard 3.0 object with the minimum required fields, plus any
|
627
618
|
# +fields+ you want in the card (they can also be added later).
|
628
|
-
def
|
629
|
-
fields.unshift Field.create(
|
630
|
-
super(fields,
|
619
|
+
def self.create(fields = [] )
|
620
|
+
fields.unshift Field.create("VERSION", "3.0")
|
621
|
+
super(fields, "VCARD")
|
631
622
|
end
|
632
623
|
|
633
624
|
# Decode a collection of vCards into an array of Vcard objects.
|
@@ -646,8 +637,8 @@ module Vpim
|
|
646
637
|
# is converted to UTF-8
|
647
638
|
# - 0xFF 0xFE: UTF-16 with a BOM (little-endian), the BOM is stripped and string
|
648
639
|
# is converted to UTF-8
|
649
|
-
# - 0x00
|
650
|
-
# -
|
640
|
+
# - 0x00 "B" or 0x00 "b": UTF-16 (big-endian), the string is converted to UTF-8
|
641
|
+
# - "B" 0x00 or "b" 0x00: UTF-16 (little-endian), the string is converted to UTF-8
|
651
642
|
#
|
652
643
|
# If you know that you have only one vCard, then you can decode that
|
653
644
|
# single vCard by doing something like:
|
@@ -656,7 +647,7 @@ module Vpim
|
|
656
647
|
#
|
657
648
|
# Note: Should the import encoding be remembered, so that it can be reencoded in
|
658
649
|
# the same format?
|
659
|
-
def
|
650
|
+
def self.decode(card)
|
660
651
|
if card.respond_to? :to_str
|
661
652
|
string = card.to_str
|
662
653
|
elsif card.respond_to? :read
|
@@ -665,25 +656,8 @@ module Vpim
|
|
665
656
|
raise ArgumentError, "Vcard.decode cannot be called with a #{card.type}"
|
666
657
|
end
|
667
658
|
|
668
|
-
case string
|
669
|
-
when /^\xEF\xBB\xBF/
|
670
|
-
string = string.sub("\xEF\xBB\xBF", '')
|
671
|
-
when /^\xFE\xFF/
|
672
|
-
arr = string.unpack('n*')
|
673
|
-
arr.shift
|
674
|
-
string = arr.pack('U*')
|
675
|
-
when /^\xFF\xFE/
|
676
|
-
arr = string.unpack('v*')
|
677
|
-
arr.shift
|
678
|
-
string = arr.pack('U*')
|
679
|
-
when /^\x00B/i
|
680
|
-
string = string.unpack('n*').pack('U*')
|
681
|
-
when /^B\x00/i
|
682
|
-
string = string.unpack('v*').pack('U*')
|
683
|
-
end
|
684
|
-
|
685
659
|
string.force_encoding(Encoding::UTF_8)
|
686
|
-
entities =
|
660
|
+
entities = ::Vcard.expand(::Vcard.decode(string))
|
687
661
|
|
688
662
|
# Since all vCards must have a begin/end, the top-level should consist
|
689
663
|
# entirely of entities/arrays, even if its a single vCard.
|
@@ -694,7 +668,7 @@ module Vpim
|
|
694
668
|
vcards = []
|
695
669
|
|
696
670
|
for e in entities
|
697
|
-
vcards.push(new(e.flatten,
|
671
|
+
vcards.push(new(e.flatten, "VCARD"))
|
698
672
|
end
|
699
673
|
|
700
674
|
vcards
|
@@ -702,14 +676,14 @@ module Vpim
|
|
702
676
|
|
703
677
|
# The value of the field named +name+, optionally limited to fields of
|
704
678
|
# type +type+. If no match is found, nil is returned, if multiple matches
|
705
|
-
# are found, the first match to have one of its type values be
|
679
|
+
# are found, the first match to have one of its type values be "PREF"
|
706
680
|
# (preferred) is returned, otherwise the first match is returned.
|
707
681
|
#
|
708
682
|
# FIXME - this will become an alias for #value.
|
709
683
|
def [](name, type=nil)
|
710
684
|
fields = enum_by_name(name).find_all { |f| type == nil || f.type?(type) }
|
711
685
|
|
712
|
-
valued = fields.select { |f| f.value !=
|
686
|
+
valued = fields.select { |f| f.value != "" }
|
713
687
|
if valued.first
|
714
688
|
fields = valued
|
715
689
|
end
|
@@ -732,7 +706,7 @@ module Vpim
|
|
732
706
|
#
|
733
707
|
# If multiple lines exist, the order of preference is:
|
734
708
|
# - lines with values over lines without
|
735
|
-
# - lines with a type of
|
709
|
+
# - lines with a type of "pref" over lines without
|
736
710
|
# If multiple lines are equally preferred, then the first line will be
|
737
711
|
# returned.
|
738
712
|
#
|
@@ -744,18 +718,16 @@ module Vpim
|
|
744
718
|
# Note that the +type+ field parameter is used for different purposes by
|
745
719
|
# the various kinds of vCard lines, but for the addressing lines (ADR,
|
746
720
|
# LABEL, TEL, EMAIL) it is has a reasonably consistent usage. Each
|
747
|
-
# addressing line can occur multiple times, and a +type+ of
|
721
|
+
# addressing line can occur multiple times, and a +type+ of "pref"
|
748
722
|
# indicates that a particular line is the preferred line. Other +type+
|
749
|
-
# values tend to indicate some information about the location (
|
750
|
-
#
|
723
|
+
# values tend to indicate some information about the location ("home",
|
724
|
+
# "work", ...) or some detail about the address ("cell", "fax", "voice",
|
751
725
|
# ...). See the methods for the specific types of line for information
|
752
726
|
# about supported types and their meaning.
|
753
727
|
def value(name, type = nil)
|
754
|
-
v = nil
|
755
|
-
|
756
728
|
fields = enum_by_name(name).find_all { |f| type == nil || f.type?(type) }
|
757
729
|
|
758
|
-
valued = fields.select { |f| f.value !=
|
730
|
+
valued = fields.select { |f| f.value != "" }
|
759
731
|
if valued.first
|
760
732
|
fields = valued
|
761
733
|
end
|
@@ -769,7 +741,7 @@ module Vpim
|
|
769
741
|
if fields.first
|
770
742
|
line = begin
|
771
743
|
Line.decode(@@decode, self, fields.first)
|
772
|
-
rescue
|
744
|
+
rescue ::Vcard::InvalidEncodingError
|
773
745
|
end
|
774
746
|
|
775
747
|
if line
|
@@ -792,22 +764,22 @@ module Vpim
|
|
792
764
|
|
793
765
|
# The first ADR value of type +type+, a Address. Any of the location or
|
794
766
|
# delivery attributes of Address can be used as +type+. A wrapper around
|
795
|
-
# #value(
|
767
|
+
# #value("ADR", +type+).
|
796
768
|
def address(type=nil)
|
797
|
-
value(
|
769
|
+
value("ADR", type)
|
798
770
|
end
|
799
771
|
|
800
772
|
# The ADR values, an array of Address. If a block is given, the values are
|
801
|
-
# yielded. A wrapper around #values(
|
773
|
+
# yielded. A wrapper around #values("ADR").
|
802
774
|
def addresses #:yield:address
|
803
|
-
values(
|
775
|
+
values("ADR")
|
804
776
|
end
|
805
777
|
|
806
778
|
# The AGENT values. Each AGENT value is either a String, a Uri, or a Vcard.
|
807
779
|
# If a block is given, the values are yielded. A wrapper around
|
808
|
-
# #values(
|
780
|
+
# #values("AGENT").
|
809
781
|
def agents #:yield:agent
|
810
|
-
values(
|
782
|
+
values("AGENT")
|
811
783
|
end
|
812
784
|
|
813
785
|
# The BDAY value as either a Date or a DateTime, or nil if there is none.
|
@@ -815,38 +787,38 @@ module Vpim
|
|
815
787
|
# If the BDAY value is invalidly formatted, a feeble heuristic is applied
|
816
788
|
# to find the month and year, and return a Date in the current year.
|
817
789
|
def birthday
|
818
|
-
value(
|
790
|
+
value("BDAY")
|
819
791
|
end
|
820
792
|
|
821
793
|
# The CATEGORIES values, an array of String. A wrapper around
|
822
|
-
# #value(
|
794
|
+
# #value("CATEGORIES").
|
823
795
|
def categories
|
824
|
-
value(
|
796
|
+
value("CATEGORIES")
|
825
797
|
end
|
826
798
|
|
827
799
|
# The first EMAIL value of type +type+, a Email. Any of the location
|
828
800
|
# attributes of Email can be used as +type+. A wrapper around
|
829
|
-
# #value(
|
801
|
+
# #value("EMAIL", +type+).
|
830
802
|
def email(type=nil)
|
831
|
-
value(
|
803
|
+
value("EMAIL", type)
|
832
804
|
end
|
833
805
|
|
834
806
|
# The EMAIL values, an array of Email. If a block is given, the values are
|
835
|
-
# yielded. A wrapper around #values(
|
807
|
+
# yielded. A wrapper around #values("EMAIL").
|
836
808
|
def emails #:yield:email
|
837
|
-
values(
|
809
|
+
values("EMAIL")
|
838
810
|
end
|
839
811
|
|
840
812
|
# The GEO value, an Array of two Floats, +[ latitude, longitude]+. North
|
841
813
|
# of the equator is positive latitude, east of the meridian is positive
|
842
814
|
# longitude. See RFC2445 for more info, there are lots of special cases
|
843
|
-
# and RFC2445
|
815
|
+
# and RFC2445"s description is more complete thant RFC2426.
|
844
816
|
def geo
|
845
|
-
value(
|
817
|
+
value("GEO")
|
846
818
|
end
|
847
819
|
|
848
820
|
# Return an Array of KEY Line#value, or yield each Line#value if a block
|
849
|
-
# is given. A wrapper around #values(
|
821
|
+
# is given. A wrapper around #values("KEY").
|
850
822
|
#
|
851
823
|
# KEY is a public key or authentication certificate associated with the
|
852
824
|
# object that the vCard represents. It is not commonly used, but could
|
@@ -854,11 +826,11 @@ module Vpim
|
|
854
826
|
#
|
855
827
|
# See Attachment for a description of the value.
|
856
828
|
def keys(&proc) #:yield: Line.value
|
857
|
-
values(
|
829
|
+
values("KEY", &proc)
|
858
830
|
end
|
859
831
|
|
860
832
|
# Return an Array of LOGO Line#value, or yield each Line#value if a block
|
861
|
-
# is given. A wrapper around #values(
|
833
|
+
# is given. A wrapper around #values("LOGO").
|
862
834
|
#
|
863
835
|
# LOGO is a graphic image of a logo associated with the object the vCard
|
864
836
|
# represents. Its not common, but would probably be equivalent to the logo
|
@@ -866,7 +838,7 @@ module Vpim
|
|
866
838
|
#
|
867
839
|
# See Attachment for a description of the value.
|
868
840
|
def logos(&proc) #:yield: Line.value
|
869
|
-
values(
|
841
|
+
values("LOGO", &proc)
|
870
842
|
end
|
871
843
|
|
872
844
|
## MAILER
|
@@ -876,35 +848,35 @@ module Vpim
|
|
876
848
|
# N is required for a vCards, this raises InvalidEncodingError if
|
877
849
|
# there is no N so it cannot return nil.
|
878
850
|
def name
|
879
|
-
value(
|
851
|
+
value("N") || raise(::Vcard::InvalidEncodingError, "Missing mandatory N field")
|
880
852
|
end
|
881
853
|
|
882
854
|
# The first NICKNAME value, nil if there are none.
|
883
855
|
def nickname
|
884
|
-
v = value(
|
856
|
+
v = value("NICKNAME")
|
885
857
|
v = v.first if v
|
886
858
|
v
|
887
859
|
end
|
888
860
|
|
889
861
|
# The NICKNAME values, an array of String. The array may be empty.
|
890
862
|
def nicknames
|
891
|
-
values(
|
863
|
+
values("NICKNAME").flatten.uniq
|
892
864
|
end
|
893
865
|
|
894
|
-
# The NOTE value, a String. A wrapper around #value(
|
866
|
+
# The NOTE value, a String. A wrapper around #value("NOTE").
|
895
867
|
def note
|
896
|
-
value(
|
868
|
+
value("NOTE")
|
897
869
|
end
|
898
870
|
|
899
871
|
# The ORG value, an Array of String. The first string is the organization,
|
900
872
|
# subsequent strings are departments within the organization. A wrapper
|
901
|
-
# around #value(
|
873
|
+
# around #value("ORG").
|
902
874
|
def org
|
903
|
-
value(
|
875
|
+
value("ORG")
|
904
876
|
end
|
905
877
|
|
906
878
|
# Return an Array of PHOTO Line#value, or yield each Line#value if a block
|
907
|
-
# is given. A wrapper around #values(
|
879
|
+
# is given. A wrapper around #values("PHOTO").
|
908
880
|
#
|
909
881
|
# PHOTO is an image or photograph information that annotates some aspect of
|
910
882
|
# the object the vCard represents. Commonly there is one PHOTO, and it is a
|
@@ -912,7 +884,7 @@ module Vpim
|
|
912
884
|
#
|
913
885
|
# See Attachment for a description of the value.
|
914
886
|
def photos(&proc) #:yield: Line.value
|
915
|
-
values(
|
887
|
+
values("PHOTO", &proc)
|
916
888
|
end
|
917
889
|
|
918
890
|
## PRODID
|
@@ -924,7 +896,7 @@ module Vpim
|
|
924
896
|
## ROLE
|
925
897
|
|
926
898
|
# Return an Array of SOUND Line#value, or yield each Line#value if a block
|
927
|
-
# is given. A wrapper around #values(
|
899
|
+
# is given. A wrapper around #values("SOUND").
|
928
900
|
#
|
929
901
|
# SOUND is digital sound content information that annotates some aspect of
|
930
902
|
# the vCard. By default this type is used to specify the proper
|
@@ -934,41 +906,41 @@ module Vpim
|
|
934
906
|
#
|
935
907
|
# See Attachment for a description of the value.
|
936
908
|
def sounds(&proc) #:yield: Line.value
|
937
|
-
values(
|
909
|
+
values("SOUND", &proc)
|
938
910
|
end
|
939
911
|
|
940
912
|
## SOURCE
|
941
913
|
|
942
914
|
# The first TEL value of type +type+, a Telephone. Any of the location or
|
943
915
|
# capability attributes of Telephone can be used as +type+. A wrapper around
|
944
|
-
# #value(
|
916
|
+
# #value("TEL", +type+).
|
945
917
|
def telephone(type=nil)
|
946
|
-
value(
|
918
|
+
value("TEL", type)
|
947
919
|
end
|
948
920
|
|
949
921
|
# The TEL values, an array of Telephone. If a block is given, the values are
|
950
|
-
# yielded. A wrapper around #values(
|
922
|
+
# yielded. A wrapper around #values("TEL").
|
951
923
|
def telephones #:yield:tel
|
952
|
-
values(
|
924
|
+
values("TEL")
|
953
925
|
end
|
954
926
|
|
955
927
|
# The TITLE value, a text string specifying the job title, functional
|
956
928
|
# position, or function of the object the card represents. A wrapper around
|
957
|
-
# #value(
|
929
|
+
# #value("TITLE").
|
958
930
|
def title
|
959
|
-
value(
|
931
|
+
value("TITLE")
|
960
932
|
end
|
961
933
|
|
962
934
|
## UID
|
963
935
|
|
964
|
-
# The URL value, a Attachment::Uri. A wrapper around #value(
|
936
|
+
# The URL value, a Attachment::Uri. A wrapper around #value("URL").
|
965
937
|
def url
|
966
|
-
value(
|
938
|
+
value("URL")
|
967
939
|
end
|
968
940
|
|
969
|
-
# The URL values, an Attachment::Uri. A wrapper around #values(
|
941
|
+
# The URL values, an Attachment::Uri. A wrapper around #values("URL").
|
970
942
|
def urls
|
971
|
-
values(
|
943
|
+
values("URL")
|
972
944
|
end
|
973
945
|
|
974
946
|
# The VERSION multiplied by 10 as an Integer. For example, a VERSION:2.1
|
@@ -978,18 +950,18 @@ module Vpim
|
|
978
950
|
# VERSION is required for a vCard, this raises InvalidEncodingError if
|
979
951
|
# there is no VERSION so it cannot return nil.
|
980
952
|
def version
|
981
|
-
v = value(
|
953
|
+
v = value("VERSION")
|
982
954
|
unless v
|
983
|
-
raise
|
955
|
+
raise ::Vcard::InvalidEncodingError, "Invalid vCard - it has no version field!"
|
984
956
|
end
|
985
957
|
v
|
986
958
|
end
|
987
959
|
|
988
960
|
# Make changes to a vCard.
|
989
961
|
#
|
990
|
-
# Yields a
|
962
|
+
# Yields a Vcard::Vcard::Maker that can be used to modify this vCard.
|
991
963
|
def make #:yield: maker
|
992
|
-
|
964
|
+
::Vcard::Vcard::Maker.make2(self) do |maker|
|
993
965
|
yield maker
|
994
966
|
end
|
995
967
|
end
|
@@ -1005,8 +977,8 @@ module Vpim
|
|
1005
977
|
rm << f
|
1006
978
|
|
1007
979
|
# Hack - because we treat N and FN as one field
|
1008
|
-
if f.name?
|
1009
|
-
rm << field(
|
980
|
+
if f.name? "N"
|
981
|
+
rm << field("FN")
|
1010
982
|
end
|
1011
983
|
end
|
1012
984
|
end
|
@@ -1022,7 +994,7 @@ module Vpim
|
|
1022
994
|
#
|
1023
995
|
# It can be used to create completely new vCards using Vcard#make2.
|
1024
996
|
#
|
1025
|
-
# Its is also yielded from
|
997
|
+
# Its is also yielded from Vcard::Vcard#make, in which case it allows a kind
|
1026
998
|
# of transactional approach to changing vCards, so their values can be
|
1027
999
|
# validated after any changes have been made.
|
1028
1000
|
#
|
@@ -1034,10 +1006,10 @@ module Vpim
|
|
1034
1006
|
class Maker
|
1035
1007
|
# Make a vCard.
|
1036
1008
|
#
|
1037
|
-
# Yields +maker+, a
|
1038
|
-
# +card+, and returns +card+, a
|
1009
|
+
# Yields +maker+, a Vcard::Vcard::Maker which allows fields to be added to
|
1010
|
+
# +card+, and returns +card+, a Vcard::Vcard.
|
1039
1011
|
#
|
1040
|
-
# If +card+ is nil or not provided a new
|
1012
|
+
# If +card+ is nil or not provided a new Vcard::Vcard is created and the
|
1041
1013
|
# fields are added to it.
|
1042
1014
|
#
|
1043
1015
|
# Defaults:
|
@@ -1047,7 +1019,7 @@ module Vpim
|
|
1047
1019
|
# information in N, see Vcard::Name#preformatted for more information.
|
1048
1020
|
# - vCards must have a VERSION field. If one does not exist when your block is
|
1049
1021
|
# is finished it will be set to 3.0.
|
1050
|
-
def self.make2(card =
|
1022
|
+
def self.make2(card = ::Vcard::Vcard.create, &block) # :yields: maker
|
1051
1023
|
new(nil, card).make(&block)
|
1052
1024
|
end
|
1053
1025
|
|
@@ -1056,24 +1028,24 @@ module Vpim
|
|
1056
1028
|
# If set, the FN field will be set to +full_name+. Otherwise, FN will
|
1057
1029
|
# be set from the values in #name.
|
1058
1030
|
def self.make(full_name = nil, &block) # :yields: maker
|
1059
|
-
new(full_name,
|
1031
|
+
new(full_name, ::Vcard::Vcard.create).make(&block)
|
1060
1032
|
end
|
1061
1033
|
|
1062
1034
|
def make # :nodoc:
|
1063
1035
|
yield self
|
1064
|
-
unless @card[
|
1065
|
-
raise Unencodeable,
|
1036
|
+
unless @card["N"]
|
1037
|
+
raise Unencodeable, "N field is mandatory"
|
1066
1038
|
end
|
1067
|
-
fn = @card.field(
|
1039
|
+
fn = @card.field("FN")
|
1068
1040
|
if fn && fn.value.strip.length == 0
|
1069
1041
|
@card.delete(fn)
|
1070
1042
|
fn = nil
|
1071
1043
|
end
|
1072
1044
|
unless fn
|
1073
|
-
@card <<
|
1045
|
+
@card << ::Vcard::DirectoryInfo::Field.create("FN", ::Vcard::Vcard::Name.new(@card["N"], "").formatted)
|
1074
1046
|
end
|
1075
|
-
unless @card[
|
1076
|
-
@card <<
|
1047
|
+
unless @card["VERSION"]
|
1048
|
+
@card << ::Vcard::DirectoryInfo::Field.create("VERSION", "3.0")
|
1077
1049
|
end
|
1078
1050
|
@card
|
1079
1051
|
end
|
@@ -1081,9 +1053,9 @@ module Vpim
|
|
1081
1053
|
private
|
1082
1054
|
|
1083
1055
|
def initialize(full_name, card) # :nodoc:
|
1084
|
-
@card = card ||
|
1056
|
+
@card = card || ::Vcard::Vcard::create
|
1085
1057
|
if full_name
|
1086
|
-
@card <<
|
1058
|
+
@card << ::Vcard::DirectoryInfo::Field.create("FN", full_name.strip )
|
1087
1059
|
end
|
1088
1060
|
end
|
1089
1061
|
|
@@ -1096,10 +1068,10 @@ module Vpim
|
|
1096
1068
|
# to set just fullname, or set the other fields to set fullname and the
|
1097
1069
|
# name.
|
1098
1070
|
def fullname=(fullname) #:nodoc: bacwards compat
|
1099
|
-
if @card.field(
|
1100
|
-
raise
|
1071
|
+
if @card.field("FN")
|
1072
|
+
raise ::Vcard::InvalidEncodingError, "Not allowed to add more than one FN field to a vCard."
|
1101
1073
|
end
|
1102
|
-
@card <<
|
1074
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "FN", fullname );
|
1103
1075
|
end
|
1104
1076
|
|
1105
1077
|
# Set the name fields, N and FN.
|
@@ -1123,17 +1095,15 @@ module Vpim
|
|
1123
1095
|
x = begin
|
1124
1096
|
@card.name.dup
|
1125
1097
|
rescue
|
1126
|
-
|
1098
|
+
::Vcard::Vcard::Name.new
|
1127
1099
|
end
|
1128
1100
|
|
1129
|
-
fn = x.fullname
|
1130
|
-
|
1131
1101
|
yield x
|
1132
1102
|
|
1133
1103
|
x.fullname.strip!
|
1134
1104
|
|
1135
1105
|
delete_if do |line|
|
1136
|
-
line.name ==
|
1106
|
+
line.name == "N"
|
1137
1107
|
end
|
1138
1108
|
|
1139
1109
|
@card << x.encode
|
@@ -1144,20 +1114,20 @@ module Vpim
|
|
1144
1114
|
|
1145
1115
|
alias :add_name :name #:nodoc: backwards compatibility
|
1146
1116
|
|
1147
|
-
# Add an address field, ADR. +address+ is a
|
1117
|
+
# Add an address field, ADR. +address+ is a Vcard::Vcard::Address.
|
1148
1118
|
def add_addr # :yield: address
|
1149
|
-
x =
|
1119
|
+
x = ::Vcard::Vcard::Address.new
|
1150
1120
|
yield x
|
1151
1121
|
@card << x.encode
|
1152
1122
|
self
|
1153
1123
|
end
|
1154
1124
|
|
1155
|
-
# Add a telephone field, TEL. +tel+ is a
|
1125
|
+
# Add a telephone field, TEL. +tel+ is a Vcard::Vcard::Telephone.
|
1156
1126
|
#
|
1157
1127
|
# The block is optional, its only necessary if you want to specify
|
1158
1128
|
# the optional attributes.
|
1159
1129
|
def add_tel(number) # :yield: tel
|
1160
|
-
x =
|
1130
|
+
x = ::Vcard::Vcard::Telephone.new(number)
|
1161
1131
|
if block_given?
|
1162
1132
|
yield x
|
1163
1133
|
end
|
@@ -1165,12 +1135,12 @@ module Vpim
|
|
1165
1135
|
self
|
1166
1136
|
end
|
1167
1137
|
|
1168
|
-
# Add an email field, EMAIL. +email+ is a
|
1138
|
+
# Add an email field, EMAIL. +email+ is a Vcard::Vcard::Email.
|
1169
1139
|
#
|
1170
1140
|
# The block is optional, its only necessary if you want to specify
|
1171
1141
|
# the optional attributes.
|
1172
1142
|
def add_email(email) # :yield: email
|
1173
|
-
x =
|
1143
|
+
x = ::Vcard::Vcard::Email.new(email)
|
1174
1144
|
if block_given?
|
1175
1145
|
yield x
|
1176
1146
|
end
|
@@ -1182,9 +1152,9 @@ module Vpim
|
|
1182
1152
|
#
|
1183
1153
|
# It can be set to a single String or an Array of String.
|
1184
1154
|
def nickname=(nickname)
|
1185
|
-
delete_if { |l| l.name ==
|
1155
|
+
delete_if { |l| l.name == "NICKNAME" }
|
1186
1156
|
|
1187
|
-
@card <<
|
1157
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "NICKNAME", nickname );
|
1188
1158
|
end
|
1189
1159
|
|
1190
1160
|
# Add a birthday field, BDAY.
|
@@ -1195,16 +1165,16 @@ module Vpim
|
|
1195
1165
|
# birthdays.
|
1196
1166
|
def birthday=(birthday)
|
1197
1167
|
if !birthday.respond_to? :month
|
1198
|
-
raise ArgumentError,
|
1168
|
+
raise ArgumentError, "birthday must be a date or time object."
|
1199
1169
|
end
|
1200
|
-
delete_if { |l| l.name ==
|
1201
|
-
@card <<
|
1170
|
+
delete_if { |l| l.name == "BDAY" }
|
1171
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "BDAY", birthday );
|
1202
1172
|
end
|
1203
1173
|
|
1204
1174
|
# Add a note field, NOTE. The +note+ String can contain newlines, they
|
1205
1175
|
# will be escaped.
|
1206
1176
|
def add_note(note)
|
1207
|
-
@card <<
|
1177
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "NOTE", ::Vcard.encode_text(note) );
|
1208
1178
|
end
|
1209
1179
|
|
1210
1180
|
# Add an instant-messaging/point of presence address field, IMPP. The address
|
@@ -1241,14 +1211,14 @@ module Vpim
|
|
1241
1211
|
|
1242
1212
|
yield x
|
1243
1213
|
|
1244
|
-
x[:preferred] =
|
1214
|
+
x[:preferred] = "PREF" if x[:preferred]
|
1245
1215
|
|
1246
1216
|
types = x.to_a.flatten.compact.map { |s| s.downcase }.uniq
|
1247
1217
|
|
1248
|
-
params[
|
1218
|
+
params["TYPE"] = types if types.first
|
1249
1219
|
end
|
1250
1220
|
|
1251
|
-
@card <<
|
1221
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "IMPP", url, params)
|
1252
1222
|
self
|
1253
1223
|
end
|
1254
1224
|
|
@@ -1271,14 +1241,14 @@ module Vpim
|
|
1271
1241
|
|
1272
1242
|
yield x
|
1273
1243
|
|
1274
|
-
x[:preferred] =
|
1244
|
+
x[:preferred] = "PREF" if x[:preferred]
|
1275
1245
|
|
1276
1246
|
types = x.to_a.flatten.compact.map { |s| s.downcase }.uniq
|
1277
1247
|
|
1278
|
-
params[
|
1248
|
+
params["TYPE"] = types if types.first
|
1279
1249
|
end
|
1280
1250
|
|
1281
|
-
@card <<
|
1251
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "X-AIM", xaim, params)
|
1282
1252
|
self
|
1283
1253
|
end
|
1284
1254
|
|
@@ -1306,30 +1276,30 @@ module Vpim
|
|
1306
1276
|
x = Struct.new(:image, :link, :type).new
|
1307
1277
|
yield x
|
1308
1278
|
if x[:image] && x[:link]
|
1309
|
-
raise
|
1279
|
+
raise ::Vcard::InvalidEncodingError, "Image is not allowed to be both inline and a link."
|
1310
1280
|
end
|
1311
1281
|
|
1312
1282
|
value = x[:image] || x[:link]
|
1313
1283
|
|
1314
1284
|
if !value
|
1315
|
-
raise
|
1285
|
+
raise ::Vcard::InvalidEncodingError, "A image link or inline data must be provided."
|
1316
1286
|
end
|
1317
1287
|
|
1318
1288
|
params = {}
|
1319
1289
|
|
1320
1290
|
# Don't set type to the empty string.
|
1321
|
-
params[
|
1291
|
+
params["TYPE"] = x[:type] if( x[:type] && x[:type].length > 0 )
|
1322
1292
|
|
1323
1293
|
if x[:link]
|
1324
|
-
params[
|
1294
|
+
params["VALUE"] = "URI"
|
1325
1295
|
else # it's inline, base-64 encode it
|
1326
|
-
params[
|
1296
|
+
params["ENCODING"] = :b64
|
1327
1297
|
if !x[:type]
|
1328
|
-
raise
|
1298
|
+
raise ::Vcard::InvalidEncodingError, "Inline image data must have it's type set."
|
1329
1299
|
end
|
1330
1300
|
end
|
1331
1301
|
|
1332
|
-
@card <<
|
1302
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "PHOTO", value, params )
|
1333
1303
|
self
|
1334
1304
|
end
|
1335
1305
|
|
@@ -1337,36 +1307,36 @@ module Vpim
|
|
1337
1307
|
#
|
1338
1308
|
# It can be set to a single String.
|
1339
1309
|
def title=(title)
|
1340
|
-
delete_if { |l| l.name ==
|
1310
|
+
delete_if { |l| l.name == "TITLE" }
|
1341
1311
|
|
1342
|
-
@card <<
|
1312
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "TITLE", title );
|
1343
1313
|
end
|
1344
1314
|
|
1345
1315
|
# Set the org field, ORG.
|
1346
1316
|
#
|
1347
1317
|
# It can be set to a single String or an Array of String.
|
1348
1318
|
def org=(org)
|
1349
|
-
delete_if { |l| l.name ==
|
1319
|
+
delete_if { |l| l.name == "ORG" }
|
1350
1320
|
|
1351
|
-
@card <<
|
1321
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "ORG", org );
|
1352
1322
|
end
|
1353
1323
|
|
1354
1324
|
|
1355
1325
|
# Add a URL field, URL.
|
1356
1326
|
def add_url(url)
|
1357
|
-
@card <<
|
1327
|
+
@card << ::Vcard::DirectoryInfo::Field.create( "URL", url.to_str );
|
1358
1328
|
end
|
1359
1329
|
|
1360
1330
|
# Add a Field, +field+.
|
1361
1331
|
def add_field(field)
|
1362
1332
|
fieldname = field.name.upcase
|
1363
1333
|
case
|
1364
|
-
when [
|
1365
|
-
raise
|
1334
|
+
when [ "BEGIN", "END" ].include?(fieldname)
|
1335
|
+
raise ::Vcard::InvalidEncodingError, "Not allowed to manually add #{field.name} to a vCard."
|
1366
1336
|
|
1367
|
-
when [
|
1337
|
+
when [ "VERSION", "N", "FN" ].include?(fieldname)
|
1368
1338
|
if @card.field(fieldname)
|
1369
|
-
raise
|
1339
|
+
raise ::Vcard::InvalidEncodingError, "Not allowed to add more than one #{fieldname} to a vCard."
|
1370
1340
|
end
|
1371
1341
|
@card << field
|
1372
1342
|
|
@@ -1387,10 +1357,10 @@ module Vpim
|
|
1387
1357
|
card.each do |field|
|
1388
1358
|
fieldname = field.name.upcase
|
1389
1359
|
case
|
1390
|
-
when [
|
1360
|
+
when [ "BEGIN", "END" ].include?(fieldname)
|
1391
1361
|
# Never copy these
|
1392
1362
|
|
1393
|
-
when [
|
1363
|
+
when [ "VERSION", "N", "FN" ].include?(fieldname) && @card.field(fieldname)
|
1394
1364
|
# Copy these only if they don't already exist.
|
1395
1365
|
|
1396
1366
|
else
|
@@ -1408,9 +1378,9 @@ module Vpim
|
|
1408
1378
|
# Delete +line+ if block yields true.
|
1409
1379
|
def delete_if #:yield: line
|
1410
1380
|
begin
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1381
|
+
@card.delete_if do |line|
|
1382
|
+
yield line
|
1383
|
+
end
|
1414
1384
|
rescue NoMethodError
|
1415
1385
|
# FIXME - this is a hideous hack, allowing a DirectoryInfo to
|
1416
1386
|
# be passed instead of a Vcard, and for it to almost work. Yuck.
|