vobject 0.1.0 → 1.0.2
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.
- checksums.yaml +5 -5
- data/.github/workflows/macos.yml +38 -0
- data/.github/workflows/ubuntu.yml +56 -0
- data/.github/workflows/windows.yml +40 -0
- data/.hound.yml +3 -0
- data/.rubocop.tb.yml +650 -0
- data/.rubocop.yml +1077 -0
- data/Gemfile +1 -1
- data/LICENSE.txt +21 -17
- data/README.adoc +151 -0
- data/Rakefile +1 -1
- data/lib/c.rb +173 -0
- data/lib/error.rb +19 -0
- data/lib/vcalendar.rb +77 -0
- data/lib/vcard.rb +67 -0
- data/lib/vobject.rb +13 -170
- data/lib/vobject/component.rb +87 -36
- data/lib/vobject/parameter.rb +116 -0
- data/lib/vobject/parametervalue.rb +26 -0
- data/lib/vobject/property.rb +134 -55
- data/lib/vobject/propertyvalue.rb +46 -0
- data/lib/vobject/vcalendar/component.rb +106 -0
- data/lib/vobject/vcalendar/grammar.rb +595 -0
- data/lib/vobject/vcalendar/paramcheck.rb +259 -0
- data/lib/vobject/vcalendar/propertyparent.rb +98 -0
- data/lib/vobject/vcalendar/propertyvalue.rb +606 -0
- data/lib/vobject/vcalendar/typegrammars.rb +605 -0
- data/lib/vobject/vcard/v3_0/component.rb +40 -0
- data/lib/vobject/vcard/v3_0/grammar.rb +175 -0
- data/lib/vobject/vcard/v3_0/paramcheck.rb +110 -0
- data/lib/vobject/vcard/v3_0/parameter.rb +17 -0
- data/lib/vobject/vcard/v3_0/property.rb +18 -0
- data/lib/vobject/vcard/v3_0/propertyvalue.rb +401 -0
- data/lib/vobject/vcard/v3_0/typegrammars.rb +425 -0
- data/lib/vobject/vcard/v4_0/component.rb +40 -0
- data/lib/vobject/vcard/v4_0/grammar.rb +224 -0
- data/lib/vobject/vcard/v4_0/paramcheck.rb +269 -0
- data/lib/vobject/vcard/v4_0/parameter.rb +18 -0
- data/lib/vobject/vcard/v4_0/property.rb +63 -0
- data/lib/vobject/vcard/v4_0/propertyvalue.rb +404 -0
- data/lib/vobject/vcard/v4_0/typegrammars.rb +539 -0
- data/lib/vobject/version.rb +1 -1
- data/vobject.gemspec +19 -16
- metadata +81 -26
- data/.travis.yml +0 -5
- data/README.md +0 -94
@@ -0,0 +1,18 @@
|
|
1
|
+
require "vobject/parameter"
|
2
|
+
|
3
|
+
module Vcard::V4_0
|
4
|
+
class Parameter < Vobject::Parameter
|
5
|
+
|
6
|
+
def parameter_base_class
|
7
|
+
version_class.const_get(:Parameter)
|
8
|
+
end
|
9
|
+
|
10
|
+
def property_base_class
|
11
|
+
version_class.const_get(:Property)
|
12
|
+
end
|
13
|
+
|
14
|
+
def version_class
|
15
|
+
Vcard::V4_0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "vobject/property"
|
2
|
+
require "vobject/parameter"
|
3
|
+
require "pp"
|
4
|
+
|
5
|
+
module Vcard::V4_0
|
6
|
+
class Property < Vobject::Property
|
7
|
+
=begin
|
8
|
+
def parameter_base_class
|
9
|
+
version_class.const_get(:Parameter)
|
10
|
+
end
|
11
|
+
=end
|
12
|
+
|
13
|
+
def property_base_class
|
14
|
+
version_class.const_get(:Property)
|
15
|
+
end
|
16
|
+
|
17
|
+
=begin
|
18
|
+
def to_norm
|
19
|
+
puts "XXX"
|
20
|
+
if norm.nil?
|
21
|
+
if multiple.nil? || multiple.empty?
|
22
|
+
ret = to_norm_line
|
23
|
+
else
|
24
|
+
arr = []
|
25
|
+
multiple.sort.each do |x|
|
26
|
+
arr << x.to_norm_line
|
27
|
+
end
|
28
|
+
ret = arr.join("")
|
29
|
+
end
|
30
|
+
norm = ret
|
31
|
+
end
|
32
|
+
norm
|
33
|
+
end
|
34
|
+
=end
|
35
|
+
|
36
|
+
def to_norm_line
|
37
|
+
line = group ? "#{group}." : ""
|
38
|
+
line << name.to_s.tr("_", "-").upcase
|
39
|
+
|
40
|
+
# add mandatory VALUE param
|
41
|
+
outparams = params
|
42
|
+
if outparams.nil?
|
43
|
+
outparams = []
|
44
|
+
end
|
45
|
+
outparams = outparams.select { |p| p.param_name != :VALUE }
|
46
|
+
outparams << Vobject::Parameter.new(:VALUE, value.type)
|
47
|
+
|
48
|
+
(outparams || {}).sort.each do |p|
|
49
|
+
line << ";#{p.to_norm}"
|
50
|
+
end
|
51
|
+
|
52
|
+
line << ":#{value.to_norm}"
|
53
|
+
|
54
|
+
line = Vobject::fold_line(line) << "\n"
|
55
|
+
|
56
|
+
line
|
57
|
+
end
|
58
|
+
|
59
|
+
def version_class
|
60
|
+
Vcard::V4_0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,404 @@
|
|
1
|
+
require "vobject"
|
2
|
+
require "vobject/propertyvalue"
|
3
|
+
|
4
|
+
module Vcard::V4_0
|
5
|
+
module PropertyValue
|
6
|
+
class Text < Vobject::PropertyValue
|
7
|
+
class << self
|
8
|
+
def escape(x)
|
9
|
+
# temporarily escape \\ as \u007f, which is banned from text
|
10
|
+
x.tr("\\", "\u007f").gsub(/\n/, "\\n").gsub(/,/, "\\,").gsub(/\u007f/, "\\\\")
|
11
|
+
end
|
12
|
+
|
13
|
+
def escape_component(x)
|
14
|
+
# temporarily escape \\ as \u007f, which is banned from text
|
15
|
+
x.tr("\\", "\u007f").gsub(/\n/, "\\n").gsub(/,/, "\\,").gsub(/;/, "\\;").gsub(/\u007f/, "\\\\")
|
16
|
+
end
|
17
|
+
|
18
|
+
def listencode(x)
|
19
|
+
ret = if x.is_a?(Array)
|
20
|
+
x.map { |m| Text.escape_component m }.join(",")
|
21
|
+
elsif x.nil? || x.empty?
|
22
|
+
""
|
23
|
+
else
|
24
|
+
Text.escape_component x
|
25
|
+
end
|
26
|
+
ret
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(val)
|
31
|
+
self.value = val
|
32
|
+
self.type = "text"
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
Text.escape value
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_hash
|
40
|
+
value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Kindvalue < Text
|
45
|
+
def initialize(val)
|
46
|
+
self.value = val
|
47
|
+
self.type = "text"
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_hash
|
51
|
+
value
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Lang < Text
|
56
|
+
def initialize(val)
|
57
|
+
self.value = val
|
58
|
+
self.type = "language-tag"
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_hash
|
62
|
+
value
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Ianatoken < Text
|
67
|
+
def initialize(val)
|
68
|
+
self.value = val
|
69
|
+
self.type = "text"
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_hash
|
73
|
+
value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Uri < Text
|
78
|
+
def initialize(val)
|
79
|
+
self.value = val
|
80
|
+
self.type = "uri"
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_hash
|
84
|
+
value
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_s
|
88
|
+
value
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Clientpidmap < Text
|
93
|
+
def initialize(val)
|
94
|
+
self.value = val
|
95
|
+
# not explicitly specified in spec
|
96
|
+
self.type = "text"
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_s
|
100
|
+
"#{value[:pid]};#{value[:uri]}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_hash
|
104
|
+
value
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class Float < Vobject::PropertyValue
|
109
|
+
include Comparable
|
110
|
+
def <=>(another)
|
111
|
+
value <=> another.value
|
112
|
+
end
|
113
|
+
|
114
|
+
def initialize(val)
|
115
|
+
self.value = val
|
116
|
+
self.type = "float"
|
117
|
+
end
|
118
|
+
|
119
|
+
def to_s
|
120
|
+
value
|
121
|
+
end
|
122
|
+
|
123
|
+
def to_hash
|
124
|
+
value
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Integer < Vobject::PropertyValue
|
129
|
+
include Comparable
|
130
|
+
def <=>(another)
|
131
|
+
value <=> another.value
|
132
|
+
end
|
133
|
+
|
134
|
+
def initialize(val)
|
135
|
+
self.value = val
|
136
|
+
self.type = "integer"
|
137
|
+
end
|
138
|
+
|
139
|
+
def to_s
|
140
|
+
value.to_s
|
141
|
+
end
|
142
|
+
|
143
|
+
def to_hash
|
144
|
+
value
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class Date < Vobject::PropertyValue
|
149
|
+
include Comparable
|
150
|
+
def <=>(another)
|
151
|
+
value[:date] <=> another.value[:date]
|
152
|
+
end
|
153
|
+
|
154
|
+
def initialize(val)
|
155
|
+
self.value = val.clone
|
156
|
+
self.type = "date"
|
157
|
+
# fill in unspecified month && year && date; only for purposes of comparison
|
158
|
+
val[:year] = sprintf("%04d", ::Date.today.year) unless val.has_key?(:year)
|
159
|
+
val[:month] = sprintf("%02d", ::Date.today.month) unless val.has_key?(:month)
|
160
|
+
val[:day] = sprintf("%02d", ::Date.today.day) unless val.has_key?(:day)
|
161
|
+
value[:date] = ::Time.utc(val[:year], val[:month], val[:day])
|
162
|
+
end
|
163
|
+
|
164
|
+
def to_s
|
165
|
+
ret = ""
|
166
|
+
ret << if value[:year]
|
167
|
+
value[:year]
|
168
|
+
else
|
169
|
+
"--"
|
170
|
+
end
|
171
|
+
if value[:month]
|
172
|
+
ret << value[:month]
|
173
|
+
elsif value[:day]
|
174
|
+
ret << "-"
|
175
|
+
end
|
176
|
+
if value[:day]
|
177
|
+
ret << value[:day]
|
178
|
+
end
|
179
|
+
ret
|
180
|
+
end
|
181
|
+
|
182
|
+
def to_hash
|
183
|
+
ret = {}
|
184
|
+
ret[:year] = value[:year] if value[:year]
|
185
|
+
ret[:month] = value[:month] if value[:month]
|
186
|
+
ret[:day] = value[:day] if value[:day]
|
187
|
+
ret
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class DateTimeLocal < Vobject::PropertyValue
|
192
|
+
include Comparable
|
193
|
+
def <=>(another)
|
194
|
+
value[:time] <=> another.value[:time]
|
195
|
+
end
|
196
|
+
|
197
|
+
def initialize(val)
|
198
|
+
self.value = val.clone
|
199
|
+
# val consists of :time && :zone values. If :zone is empty, floating local time (i.e. system local time) is assumed
|
200
|
+
self.type = "date-time"
|
201
|
+
# fill in unspecified month && year && date; only for purposes of comparison
|
202
|
+
val[:year] = sprintf("%04d", ::Date.today.year) unless val.has_key?(:year)
|
203
|
+
val[:month] = sprintf("%02d", ::Date.today.month) unless val.has_key?(:month)
|
204
|
+
val[:day] = sprintf("%02d", ::Date.today.day) unless val.has_key?(:day)
|
205
|
+
val[:hour] = 0 unless val.has_key?(:hour)
|
206
|
+
val[:min] = 0 unless val.has_key?(:min)
|
207
|
+
val[:sec] = 0 unless val.has_key?(:sec)
|
208
|
+
value[:time] = if val[:zone].empty?
|
209
|
+
::Time.utc(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
|
210
|
+
else
|
211
|
+
::Time.local(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
|
212
|
+
end
|
213
|
+
if val[:zone] && val[:zone] != "Z"
|
214
|
+
offset = val[:zone][:hour] * 3600 + val[:zone][:min] * 60
|
215
|
+
offset += val[:zone][:sec] if val[:zone][:sec]
|
216
|
+
offset = -offset if val[:sign] == "-"
|
217
|
+
value[:time] += offset.to_i
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def to_s
|
222
|
+
ret = ""
|
223
|
+
ret << if value[:year]
|
224
|
+
value[:year]
|
225
|
+
else
|
226
|
+
"--"
|
227
|
+
end
|
228
|
+
if value[:month]
|
229
|
+
ret << value[:month]
|
230
|
+
elsif value[:day]
|
231
|
+
ret << "-"
|
232
|
+
end
|
233
|
+
if value[:day]
|
234
|
+
ret << value[:day]
|
235
|
+
end
|
236
|
+
ret << "T"
|
237
|
+
ret << value[:hour] if value[:hour]
|
238
|
+
ret << value[:min] if value[:min]
|
239
|
+
ret << value[:sec] if value[:sec]
|
240
|
+
ret << value[:zone] if value[:zone] == "Z"
|
241
|
+
if value[:zone].is_a?(Hash)
|
242
|
+
ret << value[:zone][:sign]
|
243
|
+
ret << value[:zone][:hour]
|
244
|
+
ret << value[:zone][:min]
|
245
|
+
ret << value[:zone][:sec] if value[:zone][:sec]
|
246
|
+
end
|
247
|
+
ret
|
248
|
+
end
|
249
|
+
|
250
|
+
def to_hash
|
251
|
+
ret = {}
|
252
|
+
ret[:year] = value[:year] if value[:year]
|
253
|
+
ret[:month] = value[:month] if value[:month]
|
254
|
+
ret[:day] = value[:day] if value[:day]
|
255
|
+
ret[:hour] = value[:hour] if value[:hour]
|
256
|
+
ret[:min] = value[:min] if value[:min]
|
257
|
+
ret[:sec] = value[:sec] if value[:sec]
|
258
|
+
ret[:zone] = value[:zone] if value[:zone]
|
259
|
+
ret
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
class Time < Vobject::PropertyValue
|
264
|
+
def initialize(val)
|
265
|
+
self.value = val
|
266
|
+
self.type = "time"
|
267
|
+
end
|
268
|
+
|
269
|
+
def to_s
|
270
|
+
ret = ""
|
271
|
+
ret << value[:hour] if value[:hour]
|
272
|
+
ret << value[:min] if value[:min]
|
273
|
+
ret << value[:sec] if value[:sec]
|
274
|
+
ret << value[:zone] if value[:zone]
|
275
|
+
ret
|
276
|
+
end
|
277
|
+
|
278
|
+
def to_hash
|
279
|
+
value
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
class Utcoffset < Vobject::PropertyValue
|
284
|
+
def initialize(val)
|
285
|
+
self.value = val
|
286
|
+
self.type = "utc-offset"
|
287
|
+
end
|
288
|
+
|
289
|
+
def to_s
|
290
|
+
ret = "#{value[:sign]}#{value[:hr]}#{value[:min]}"
|
291
|
+
ret += value[:sec] if value[:sec]
|
292
|
+
ret
|
293
|
+
end
|
294
|
+
|
295
|
+
def to_hash
|
296
|
+
value
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
class Version < Vobject::PropertyValue
|
301
|
+
def initialize(val)
|
302
|
+
self.value = val
|
303
|
+
self.type = "text"
|
304
|
+
end
|
305
|
+
|
306
|
+
def to_s
|
307
|
+
value
|
308
|
+
end
|
309
|
+
|
310
|
+
def to_hash
|
311
|
+
value
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
class Gender < Vobject::PropertyValue
|
316
|
+
def initialize(val)
|
317
|
+
self.value = val
|
318
|
+
self.type = "text"
|
319
|
+
end
|
320
|
+
|
321
|
+
def to_s
|
322
|
+
ret = value[:sex]
|
323
|
+
ret << ";#{value[:gender]}" if !value[:gender].empty?
|
324
|
+
ret
|
325
|
+
end
|
326
|
+
|
327
|
+
def to_hash
|
328
|
+
value
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
class Textlist < Vobject::PropertyValue
|
333
|
+
def initialize(val)
|
334
|
+
self.value = val
|
335
|
+
self.type = "text"
|
336
|
+
end
|
337
|
+
|
338
|
+
def to_s
|
339
|
+
value.map { |m| Text.escape m }.join(",")
|
340
|
+
end
|
341
|
+
|
342
|
+
def to_hash
|
343
|
+
value
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
class Org < Vobject::PropertyValue
|
348
|
+
def initialize(val)
|
349
|
+
self.value = val
|
350
|
+
self.type = "text"
|
351
|
+
end
|
352
|
+
|
353
|
+
def to_s
|
354
|
+
value.map { |m| Text.escape_component m }.join(";")
|
355
|
+
end
|
356
|
+
|
357
|
+
def to_hash
|
358
|
+
value
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
class Fivepartname < Vobject::PropertyValue
|
363
|
+
def initialize(val)
|
364
|
+
self.value = val
|
365
|
+
self.type = "text"
|
366
|
+
end
|
367
|
+
|
368
|
+
def to_s
|
369
|
+
ret = Text.listencode value[:surname]
|
370
|
+
ret += ";#{Text.listencode value[:givenname]}"
|
371
|
+
ret += ";#{Text.listencode value[:additionalname]}"
|
372
|
+
ret += ";#{Text.listencode value[:honprefix]}"
|
373
|
+
ret += ";#{Text.listencode value[:honsuffix]}"
|
374
|
+
ret
|
375
|
+
end
|
376
|
+
|
377
|
+
def to_hash
|
378
|
+
value
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
class Address < Vobject::PropertyValue
|
383
|
+
def initialize(val)
|
384
|
+
self.value = val
|
385
|
+
self.type = "text"
|
386
|
+
end
|
387
|
+
|
388
|
+
def to_s
|
389
|
+
ret = Text.listencode value[:pobox]
|
390
|
+
ret += ";#{Text.listencode value[:ext]}"
|
391
|
+
ret += ";#{Text.listencode value[:street]}"
|
392
|
+
ret += ";#{Text.listencode value[:locality]}"
|
393
|
+
ret += ";#{Text.listencode value[:region]}"
|
394
|
+
ret += ";#{Text.listencode value[:code]}"
|
395
|
+
ret += ";#{Text.listencode value[:country]}"
|
396
|
+
ret
|
397
|
+
end
|
398
|
+
|
399
|
+
def to_hash
|
400
|
+
value
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|