vcard 0.1.1 → 0.2.0
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/.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.
|