vcard 0.2.2 → 0.2.3
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/vcard.rb +26 -47
- data/lib/vcard/bnf.rb +5 -2
- data/lib/vcard/version.rb +1 -1
- data/test/test_helper.rb +6 -6
- metadata +2 -8
data/lib/vcard.rb
CHANGED
@@ -30,9 +30,9 @@ module Vcard
|
|
30
30
|
line.chomp!
|
31
31
|
# If it's a continuation line, add it to the last.
|
32
32
|
# If it's an empty line, drop it from the input.
|
33
|
-
if
|
33
|
+
if line =~ /^[ \t]/
|
34
34
|
unfolded[-1] << line[1, line.size-1]
|
35
|
-
elsif
|
35
|
+
elsif line =~ /^$/
|
36
36
|
else
|
37
37
|
unfolded << line
|
38
38
|
end
|
@@ -49,14 +49,13 @@ module Vcard
|
|
49
49
|
item.chomp!(sep)
|
50
50
|
list << yield(item)
|
51
51
|
end
|
52
|
+
|
52
53
|
list
|
53
54
|
end
|
54
55
|
|
55
56
|
# Convert a RFC 2425 date into an array of [year, month, day].
|
56
57
|
def self.decode_date(v) # :nodoc:
|
57
|
-
|
58
|
-
raise ::Vcard::InvalidEncodingError, "date not valid (#{v})"
|
59
|
-
end
|
58
|
+
raise ::Vcard::InvalidEncodingError, "date not valid (#{v})" unless v =~ Bnf::DATE
|
60
59
|
[$1.to_i, $2.to_i, $3.to_i]
|
61
60
|
end
|
62
61
|
|
@@ -70,31 +69,29 @@ module Vcard
|
|
70
69
|
|
71
70
|
# Encode a Date object as "yyyymmdd".
|
72
71
|
def self.encode_date(d) # :nodoc:
|
73
|
-
"%0.4d%0.2d%0.2d" % [
|
72
|
+
"%0.4d%0.2d%0.2d" % [d.year, d.mon, d.day]
|
74
73
|
end
|
75
74
|
|
76
75
|
# Encode a Date object as "yyyymmdd".
|
77
76
|
def self.encode_time(d) # :nodoc:
|
78
|
-
"%0.4d%0.2d%0.2d" % [
|
77
|
+
"%0.4d%0.2d%0.2d" % [d.year, d.mon, d.day]
|
79
78
|
end
|
80
79
|
|
81
80
|
# Encode a Time or DateTime object as "yyyymmddThhmmss"
|
82
81
|
def self.encode_date_time(d) # :nodoc:
|
83
|
-
"%0.4d%0.2d%0.2dT%0.2d%0.2d%0.2d" % [
|
82
|
+
"%0.4d%0.2d%0.2dT%0.2d%0.2d%0.2d" % [d.year, d.mon, d.day, d.hour, d.min, d.sec]
|
84
83
|
end
|
85
84
|
|
86
85
|
# Convert a RFC 2425 time into an array of [hour,min,sec,secfrac,timezone]
|
87
86
|
def self.decode_time(v) # :nodoc:
|
88
|
-
|
89
|
-
raise ::Vcard::InvalidEncodingError, "time '#{v}' not valid"
|
90
|
-
end
|
87
|
+
raise ::Vcard::InvalidEncodingError, "time '#{v}' not valid" unless match = Bnf::TIME.match(v)
|
91
88
|
hour, min, sec, secfrac, tz = match.to_a[1..5]
|
92
89
|
|
93
90
|
[hour.to_i, min.to_i, sec.to_i, secfrac ? secfrac.to_f : 0, tz]
|
94
91
|
end
|
95
92
|
|
96
93
|
def self.array_datetime_to_time(dtarray) #:nodoc:
|
97
|
-
# We get [
|
94
|
+
# We get [year, month, day, hour, min, sec, usec, tz]
|
98
95
|
tz = (dtarray.pop == "Z") ? :gm : :local
|
99
96
|
Time.send(tz, *dtarray)
|
100
97
|
rescue ArgumentError => e
|
@@ -108,9 +105,7 @@ module Vcard
|
|
108
105
|
|
109
106
|
# Convert a RFC 2425 date-time into an array of [year,mon,day,hour,min,sec,secfrac,timezone]
|
110
107
|
def self.decode_date_time(v) # :nodoc:
|
111
|
-
|
112
|
-
raise ::Vcard::InvalidEncodingError, "date-time '#{v}' not valid"
|
113
|
-
end
|
108
|
+
raise ::Vcard::InvalidEncodingError, "date-time '#{v}' not valid" unless match = Bnf::DATE_TIME.match(v)
|
114
109
|
year, month, day, hour, min, sec, secfrac, tz = match.to_a[1..8]
|
115
110
|
|
116
111
|
[
|
@@ -135,9 +130,7 @@ module Vcard
|
|
135
130
|
|
136
131
|
# Convert an RFC2425 INTEGER value into an Integer
|
137
132
|
def self.decode_integer(v) # :nodoc:
|
138
|
-
|
139
|
-
raise ::Vcard::InvalidEncodingError, "integer not valid (#{v})"
|
140
|
-
end
|
133
|
+
raise ::Vcard::InvalidEncodingError, "integer not valid (#{v})" unless v =~ Bnf::INTEGER
|
141
134
|
v.to_i
|
142
135
|
end
|
143
136
|
|
@@ -148,9 +141,7 @@ module Vcard
|
|
148
141
|
def self.decode_date_list(v) # :nodoc:
|
149
142
|
decode_list(v) do |date|
|
150
143
|
date.strip!
|
151
|
-
if date.length > 0
|
152
|
-
decode_date(date)
|
153
|
-
end
|
144
|
+
decode_date(date) if date.length > 0
|
154
145
|
end.compact
|
155
146
|
end
|
156
147
|
|
@@ -158,9 +149,7 @@ module Vcard
|
|
158
149
|
def self.decode_time_list(v) # :nodoc:
|
159
150
|
decode_list(v) do |time|
|
160
151
|
time.strip!
|
161
|
-
if time.length > 0
|
162
|
-
decode_time(time)
|
163
|
-
end
|
152
|
+
decode_time(time) if time.length > 0
|
164
153
|
end.compact
|
165
154
|
end
|
166
155
|
|
@@ -168,9 +157,7 @@ module Vcard
|
|
168
157
|
def self.decode_date_time_list(v) # :nodoc:
|
169
158
|
decode_list(v) do |datetime|
|
170
159
|
datetime.strip!
|
171
|
-
if datetime.length > 0
|
172
|
-
decode_date_time(datetime)
|
173
|
-
end
|
160
|
+
decode_date_time(datetime) if datetime.length > 0
|
174
161
|
end.compact
|
175
162
|
end
|
176
163
|
|
@@ -197,27 +184,21 @@ module Vcard
|
|
197
184
|
end
|
198
185
|
|
199
186
|
def self.encode_text(v) #:nodoc:
|
200
|
-
v.to_str.gsub(/([\\,;\n])/) { $1 == "\n" ? "\\n" : "
|
187
|
+
v.to_str.gsub(/([\\,;\n])/) { $1 == "\n" ? "\\n" : "\\#{$1}" }
|
201
188
|
end
|
202
189
|
|
203
190
|
# v is an Array of String, or just a single String
|
204
191
|
def self.encode_text_list(v, sep = ",") #:nodoc:
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
encode_text(v)
|
209
|
-
end
|
192
|
+
v.to_ary.map { |t| encode_text(t) }.join(sep)
|
193
|
+
rescue
|
194
|
+
encode_text(v)
|
210
195
|
end
|
211
196
|
|
212
197
|
# Convert a +sep+-seperated list of TEXT values into an array of values.
|
213
198
|
def self.decode_text_list(value, sep = ",") # :nodoc:
|
214
199
|
# Need to do in two stages, as best I can find.
|
215
|
-
list = value.scan(/([^#{sep}\\]*(?:\\.[^#{sep}\\]*)*)#{sep}/).map
|
216
|
-
|
217
|
-
end
|
218
|
-
if value.match(/([^#{sep}\\]*(?:\\.[^#{sep}\\]*)*)$/)
|
219
|
-
list << $1
|
220
|
-
end
|
200
|
+
list = value.scan(/([^#{sep}\\]*(?:\\.[^#{sep}\\]*)*)#{sep}/).map { |v| decode_text(v.first) }
|
201
|
+
list << $1 if value.match(/([^#{sep}\\]*(?:\\.[^#{sep}\\]*)*)$/)
|
221
202
|
list
|
222
203
|
end
|
223
204
|
|
@@ -236,7 +217,7 @@ module Vcard
|
|
236
217
|
if value =~ Bnf::ALL_SAFECHARS
|
237
218
|
value
|
238
219
|
elsif value =~ Bnf::ALL_QSAFECHARS
|
239
|
-
|
220
|
+
%Q{"#{value}"}
|
240
221
|
else
|
241
222
|
raise ::Vcard::Unencodable, "param-value #{value.inspect}"
|
242
223
|
end
|
@@ -245,7 +226,7 @@ module Vcard
|
|
245
226
|
# Unfold the lines in +card+, then return an array of one Field object per
|
246
227
|
# line.
|
247
228
|
def self.decode(card) #:nodoc:
|
248
|
-
unfold(card).
|
229
|
+
unfold(card).map { |line| DirectoryInfo::Field.decode(line) }
|
249
230
|
end
|
250
231
|
|
251
232
|
|
@@ -259,15 +240,14 @@ module Vcard
|
|
259
240
|
dst = []
|
260
241
|
# stack used to track our nesting level, as we see begin/end we start a
|
261
242
|
# new/finish the current entity, and push/pop that entity from the stack
|
262
|
-
current = [
|
243
|
+
current = [dst]
|
263
244
|
|
264
245
|
for f in src
|
265
246
|
if f.name? "BEGIN"
|
266
|
-
e = [
|
247
|
+
e = [f]
|
267
248
|
|
268
249
|
current.last.push(e)
|
269
250
|
current.push(e)
|
270
|
-
|
271
251
|
elsif f.name? "END"
|
272
252
|
current.last.push(f)
|
273
253
|
|
@@ -276,7 +256,6 @@ module Vcard
|
|
276
256
|
end
|
277
257
|
|
278
258
|
current.pop
|
279
|
-
|
280
259
|
else
|
281
260
|
current.last.push(f)
|
282
261
|
end
|
@@ -296,8 +275,8 @@ module Vcard
|
|
296
275
|
inner = []
|
297
276
|
fields.each do |line|
|
298
277
|
case line
|
299
|
-
when Array
|
300
|
-
else
|
278
|
+
when Array then inner << line
|
279
|
+
else outer << line
|
301
280
|
end
|
302
281
|
end
|
303
282
|
return outer, inner
|
data/lib/vcard/bnf.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: ascii
|
1
2
|
# Copyright (C) 2008 Sam Roberts
|
2
3
|
|
3
4
|
# This library is free software; you can redistribute it and/or modify
|
@@ -59,12 +60,14 @@ module Vcard
|
|
59
60
|
|
60
61
|
# QSAFE-CHAR = WSP / %x21 / %x23-7E / NON-US-ASCII
|
61
62
|
# ; Any character except CTLs and DQUOTE
|
62
|
-
|
63
|
+
# set ascii encoding so that multibyte chars can be properly escaped
|
64
|
+
QSAFECHAR = Regexp.new("[ \t\x21\x23-\x7e\x80-\xff]")
|
63
65
|
ALL_QSAFECHARS = /\A#{QSAFECHAR}*\z/
|
64
66
|
|
65
67
|
# SAFE-CHAR = WSP / %x21 / %x23-2B / %x2D-39 / %x3C-7E / NON-US-ASCII
|
66
68
|
# ; Any character except CTLs, DQUOTE, ";", ":", ","
|
67
|
-
|
69
|
+
# escape character classes then create new Regexp
|
70
|
+
SAFECHAR = Regexp.new(Regexp.escape("[ \t\x21\x23-\x2b\x2d-\x39\x3c-\x7e\x80-\xff]"))
|
68
71
|
ALL_SAFECHARS = /\A#{SAFECHAR}*\z/
|
69
72
|
end
|
70
73
|
end
|
data/lib/vcard/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -7,25 +7,25 @@ class Test::Unit::TestCase
|
|
7
7
|
# Test equivalence where whitespace is compressed.
|
8
8
|
|
9
9
|
def assert_equal_nospace(expected, got)
|
10
|
-
expected = expected.gsub(/\s+/,
|
11
|
-
got = expected.gsub(/\s+/,
|
10
|
+
expected = expected.gsub(/\s+/, "")
|
11
|
+
got = expected.gsub(/\s+/, "")
|
12
12
|
assert_equal(expected, got)
|
13
13
|
end
|
14
14
|
|
15
15
|
def utf_name_test(c)
|
16
16
|
card = Vcard::Vcard.decode(c).first
|
17
17
|
assert_equal("name", card.name.family)
|
18
|
-
rescue
|
19
|
-
|
18
|
+
rescue => exception
|
19
|
+
exception.message << " #{c.inspect}"
|
20
20
|
raise
|
21
21
|
end
|
22
22
|
|
23
23
|
def be(s)
|
24
|
-
s.unpack(
|
24
|
+
s.unpack("U*").pack("n*")
|
25
25
|
end
|
26
26
|
|
27
27
|
def le(s)
|
28
|
-
s.unpack(
|
28
|
+
s.unpack("U*").pack("v*")
|
29
29
|
end
|
30
30
|
|
31
31
|
def vcard(name)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vcard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-14 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Vcard extracted from Vpim
|
15
15
|
email:
|
@@ -76,18 +76,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
76
76
|
- - ! '>='
|
77
77
|
- !ruby/object:Gem::Version
|
78
78
|
version: '0'
|
79
|
-
segments:
|
80
|
-
- 0
|
81
|
-
hash: 376442794917458825
|
82
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
80
|
none: false
|
84
81
|
requirements:
|
85
82
|
- - ! '>='
|
86
83
|
- !ruby/object:Gem::Version
|
87
84
|
version: '0'
|
88
|
-
segments:
|
89
|
-
- 0
|
90
|
-
hash: 376442794917458825
|
91
85
|
requirements: []
|
92
86
|
rubyforge_project:
|
93
87
|
rubygems_version: 1.8.24
|