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,259 @@
|
|
1
|
+
require "rsec"
|
2
|
+
require "set"
|
3
|
+
require "uri"
|
4
|
+
require "date"
|
5
|
+
require "tzinfo"
|
6
|
+
include Rsec::Helpers
|
7
|
+
require_relative "../../c"
|
8
|
+
require_relative "../../error"
|
9
|
+
|
10
|
+
module Vobject::Vcalendar
|
11
|
+
class Paramcheck
|
12
|
+
class << self
|
13
|
+
def paramcheck(strict, prop, params, ctx)
|
14
|
+
errors = []
|
15
|
+
if params && params[:ALTREP]
|
16
|
+
case prop
|
17
|
+
when :COMMENT, :DESCRIPTION, :LOCATION, :RESOURCES, :SUMMARY,
|
18
|
+
:CONTACT, :NAME, :IMAGE
|
19
|
+
else
|
20
|
+
parse_err(strict, errors, "(:ALTREP parameter given for #{prop}", ctx)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
if params && params[:CN]
|
24
|
+
case prop
|
25
|
+
when :ATTENDEE, :ORGANIZER
|
26
|
+
else
|
27
|
+
parse_err(strict, errors, "(:CN parameter given for #{prop}", ctx)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
if params && params[:CUTYPE]
|
31
|
+
case prop
|
32
|
+
when :ATTENDEE
|
33
|
+
else
|
34
|
+
parse_err(strict, errors, "(:CUTYPE parameter given for #{prop}", ctx)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
if params && params[:DELEGATED_FROM]
|
38
|
+
case prop
|
39
|
+
when :ATTENDEE
|
40
|
+
else
|
41
|
+
parse_err(strict, errors, "(:DELEGATED_FROM parameter given for #{prop}", ctx)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
if params && params[:DELEGATED_TO]
|
45
|
+
case prop
|
46
|
+
when :ATTENDEE
|
47
|
+
else
|
48
|
+
parse_err(strict, errors, "(:DELEGATED_TO parameter given for #{prop}", ctx)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
if params && params[:DIR]
|
52
|
+
case prop
|
53
|
+
when :ATTENDEE, :ORGANIZER
|
54
|
+
else
|
55
|
+
parse_err(strict, errors, "(:DIR parameter given for #{prop}", ctx)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
if params && params[:ENCODING]
|
59
|
+
case prop
|
60
|
+
when :ATTACH, :IMAGE
|
61
|
+
else
|
62
|
+
parse_err(strict, errors, "(:ENCODING parameter given for #{prop}", ctx)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
if params && params[:FMTTYPE]
|
66
|
+
case prop
|
67
|
+
when :ATTACH, :IMAGE
|
68
|
+
else
|
69
|
+
parse_err(strict, errors, "(:FMTTYPE parameter given for #{prop}", ctx)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
if params && params[:FBTYPE]
|
73
|
+
case prop
|
74
|
+
when :FREEBUSY
|
75
|
+
else
|
76
|
+
parse_err(strict, errors, "(:FBTYPE parameter given for #{prop}", ctx)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
if params && params[:LANGUAGE]
|
80
|
+
case prop
|
81
|
+
when :CATEGORIES, :COMMENT, :DESCRIPTION, :LOCATION, :RESOURCES,
|
82
|
+
:SUMMARY, :TZNAME, :ATTENDEE, :CONTACT, :ORGANIZER, :REQUEST_STATUS,
|
83
|
+
:NAME, :CONFERENCE
|
84
|
+
else
|
85
|
+
parse_err(strict, errors, "(:LANGUAGE parameter given for #{prop}", ctx)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
if params && params[:MEMBER]
|
89
|
+
case prop
|
90
|
+
when :ATTENDEE
|
91
|
+
else
|
92
|
+
parse_err(strict, errors, "(:MEMBER parameter given for #{prop}", ctx)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
if params && params[:PARTSTAT]
|
96
|
+
case prop
|
97
|
+
when :ATTENDEE
|
98
|
+
else
|
99
|
+
parse_err(strict, errors, "(:PARTSTAT parameter given for #{prop}", ctx)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
if params && params[:RANGE]
|
103
|
+
case prop
|
104
|
+
when :RECURRENCE_ID
|
105
|
+
else
|
106
|
+
parse_err(strict, errors, "(:RANGE parameter given for #{prop}", ctx)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
if params && params[:RELATED]
|
110
|
+
case prop
|
111
|
+
when :TRIGGER
|
112
|
+
else
|
113
|
+
parse_err(strict, errors, "(:RELATED parameter given for #{prop}", ctx)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
if params && params[:RELTYPE]
|
117
|
+
case prop
|
118
|
+
when :RELATED_TO
|
119
|
+
else
|
120
|
+
parse_err(strict, errors, "(:RELTYPE parameter given for #{prop}", ctx)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
if params && params[:ROLE]
|
124
|
+
case prop
|
125
|
+
when :ATTENDEE
|
126
|
+
else
|
127
|
+
parse_err(strict, errors, "(:ROLE parameter given for #{prop}", ctx)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
if params && params[:RSVP]
|
131
|
+
case prop
|
132
|
+
when :ATTENDEE
|
133
|
+
else
|
134
|
+
parse_err(strict, errors, "(:RSVP parameter given for #{prop}", ctx)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
if params && params[:SENT_BY]
|
138
|
+
case prop
|
139
|
+
when :ATTENDEE, :ORGANIZER
|
140
|
+
else
|
141
|
+
parse_err(strict, errors, "(:SENT_BY parameter given for #{prop}", ctx)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
if params && params[:TZID]
|
145
|
+
case prop
|
146
|
+
when :DTEND, :DUE, :DTSTART, :RECURRENCE_ID, :EXDATE, :RDATE
|
147
|
+
else
|
148
|
+
parse_err(strict, errors, "(:TZID parameter given for #{prop}", ctx)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
if params && params[:DISPLAY]
|
152
|
+
case prop
|
153
|
+
when :IMAGE
|
154
|
+
else
|
155
|
+
parse_err(strict, errors, "(:DISPLAY parameter given for #{prop}", ctx)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
if params && params[:FEATURE]
|
159
|
+
case prop
|
160
|
+
when :CONFERENCE
|
161
|
+
else
|
162
|
+
parse_err(strict, errors, "(:FEATURE parameter given for #{prop}", ctx)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
if params && params[:LABEL]
|
166
|
+
case prop
|
167
|
+
when :CONFERENCE
|
168
|
+
else
|
169
|
+
parse_err(strict, errors, "(:LABEL parameter given for #{prop}", ctx)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
if params && params[:EMAIL]
|
173
|
+
case prop
|
174
|
+
when :ORGANIZER, :ATTENDEE
|
175
|
+
else
|
176
|
+
parse_err(strict, errors, "(:EMAIL parameter given for #{prop}", ctx)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
case prop
|
181
|
+
when :TZURL, :URL, :CONFERENCE, :SOURCE
|
182
|
+
params.each do |key, val|
|
183
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("uri") != 0
|
184
|
+
end
|
185
|
+
when :FREEBUSY
|
186
|
+
params.each do |key, val|
|
187
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("period") != 0
|
188
|
+
end
|
189
|
+
when :COMPLETED
|
190
|
+
params.each do |key, val|
|
191
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("date-time") != 0
|
192
|
+
end
|
193
|
+
when :PERCENT_COMPLETE, :PRIORITY, :REPEAT, :SEQUENCE
|
194
|
+
params.each do |key, val|
|
195
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("integer") != 0
|
196
|
+
end
|
197
|
+
when :DURATION, :REFRESH_INTERVAL
|
198
|
+
params.each do |key, val|
|
199
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("duration") != 0
|
200
|
+
end
|
201
|
+
when :GEO
|
202
|
+
params.each do |key, val|
|
203
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("float") != 0
|
204
|
+
end
|
205
|
+
when :CREATED, :DTSTAMP, :LAST_MODIFIED
|
206
|
+
params.each do |key, val|
|
207
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("date-time") != 0
|
208
|
+
end
|
209
|
+
when :CALSCALE, :METHOD, :PRODID, :VERSION, :CATEGORIES, :CLASS,
|
210
|
+
:COMMENT, :DESCRIPTION, :LOCATION, :RESOURCES, :STATUS, :SUMMARY,
|
211
|
+
:TRANSP, :TZID, :TZNAME, :CONTACT, :RELATED_TO, :UID, :ACTION,
|
212
|
+
:REQUEST_STATUS, :COLOR, :NAME
|
213
|
+
params.each do |key, val|
|
214
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("text") != 0
|
215
|
+
end
|
216
|
+
when :DTEND, :DUE, :DTSTART, :RECURRENCE_ID, :EXDATE
|
217
|
+
params.each do |key, val|
|
218
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("date-time") != 0 && val.casecmp("date") != 0
|
219
|
+
end
|
220
|
+
when :RDATE
|
221
|
+
params.each do |key, val|
|
222
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("period") != 0 && val.casecmp("date") != 0 && val.casecmp("date-time") != 0
|
223
|
+
end
|
224
|
+
when :RRULE
|
225
|
+
params.each do |key, val|
|
226
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("recur") != 0
|
227
|
+
end
|
228
|
+
when :TZOFFSETFROM, :TZOFFSETTO
|
229
|
+
params.each do |key, val|
|
230
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("utc-offset") != 0
|
231
|
+
end
|
232
|
+
when :ATTENDEE, :ORGANIZER
|
233
|
+
params.each do |key, val|
|
234
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("cal-address") != 0
|
235
|
+
end
|
236
|
+
when :TRIGGER
|
237
|
+
params.each do |key, val|
|
238
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("duration") != 0 && val.casecmp("date-time") != 0
|
239
|
+
end
|
240
|
+
when :ATTACH, :IMAGE
|
241
|
+
params.each do |key, val|
|
242
|
+
parse_err(strict, errors, "(illegal value #{val} given for parameter #{key} of #{prop}", ctx) if key == :VALUE && val.casecmp("uri") != 0 && val.casecmp("binary") != 0
|
243
|
+
end
|
244
|
+
end
|
245
|
+
errors
|
246
|
+
end
|
247
|
+
|
248
|
+
private
|
249
|
+
|
250
|
+
def parse_err(strict, errors, msg, ctx)
|
251
|
+
if strict
|
252
|
+
raise ctx.report_error msg, "source"
|
253
|
+
else
|
254
|
+
errors << ctx.report_error(msg, "source")
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require "rsec"
|
2
|
+
require "set"
|
3
|
+
require "uri"
|
4
|
+
require "date"
|
5
|
+
require "tzinfo"
|
6
|
+
include Rsec::Helpers
|
7
|
+
require_relative "../../c"
|
8
|
+
require_relative "../../error"
|
9
|
+
require "vobject"
|
10
|
+
|
11
|
+
module Vobject::Vcalendar
|
12
|
+
class Typegrammars
|
13
|
+
class << self
|
14
|
+
# Ensure each property belongs to a legal component
|
15
|
+
def property_parent(strict, key, component, _value, ctx1)
|
16
|
+
errors = []
|
17
|
+
if key !~ /^x/i && registered_propname?(key.to_s)
|
18
|
+
case component
|
19
|
+
when :EVENT
|
20
|
+
case key
|
21
|
+
when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
|
22
|
+
:GEO, :LAST_MOD, :LOCATION, :ORGANIZER, :PRIORITY, :SEQUENCE, :STATUS,
|
23
|
+
:SUMMARY, :TRANSP, :URL, :RECURRENCE_ID, :RRULE, :DTEND, :DURATION,
|
24
|
+
:ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
|
25
|
+
:RSTATUS, :RELATED, :RESOURCES, :RDATE, :COLOR, :CONFERENCE, :IMAGE
|
26
|
+
else
|
27
|
+
parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
|
28
|
+
end
|
29
|
+
when :TODO
|
30
|
+
case key
|
31
|
+
when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
|
32
|
+
:GEO, :LAST_MOD, :LOCATION, :ORGANIZER, :PRIORITY, :PERCENT_COMPLETED, :SEQUENCE, :STATUS,
|
33
|
+
:SUMMARY, :URL, :RECURRENCE_ID, :RRULE, :DUE, :DURATION,
|
34
|
+
:ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
|
35
|
+
:RSTATUS, :RELATED, :RESOURCES, :RDATE, :COLOR, :CONFERENCE, :IMAGE
|
36
|
+
else
|
37
|
+
parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
|
38
|
+
end
|
39
|
+
when :JOURNAL
|
40
|
+
case key
|
41
|
+
when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
|
42
|
+
:LAST_MOD, :ORGANIZER, :RECURRENCE_ID, :SEQUENCE, :STATUS,
|
43
|
+
:SUMMARY, :URL, :RRULE,
|
44
|
+
:ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
|
45
|
+
:RSTATUS, :RELATED, :RDATE, :COLOR, :IMAGE
|
46
|
+
else
|
47
|
+
parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
|
48
|
+
end
|
49
|
+
when :FREEBUSY
|
50
|
+
case key
|
51
|
+
when :DTSTAMP, :UID, :CONTACT, :DTSTART, :DTEND, :ORGANIZER, :URL,
|
52
|
+
:ATTENDEE, :COMMENT, :FREEBUSY, :RSTATUS
|
53
|
+
else
|
54
|
+
parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
|
55
|
+
end
|
56
|
+
when :TIMEZONE
|
57
|
+
case key
|
58
|
+
when :TZID, :LAST_MODIFIED, :TZURL
|
59
|
+
else
|
60
|
+
parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
|
61
|
+
end
|
62
|
+
when :DAYLIGHT, :STANDARD
|
63
|
+
case key
|
64
|
+
when :DTSTART, :TZOFFSETTO, :TZOFFSETFROM, :RRULE,
|
65
|
+
:COMMENT, :RDATE, :TZNAME
|
66
|
+
else
|
67
|
+
parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
|
68
|
+
end
|
69
|
+
when :ALARM
|
70
|
+
case key
|
71
|
+
when :ACTION, :TRIGGER, :DURATION, :REPEAT, :ATTACH, :DESCRIPTION,
|
72
|
+
:SUMMARY, :ATTENDEE
|
73
|
+
else
|
74
|
+
parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
|
75
|
+
end
|
76
|
+
when :VAVAILABILITY
|
77
|
+
case key
|
78
|
+
when :DTSTAMP, :UID, :BUSYTYPE, :CLASS, :CREATED, :DESCRIPTION,
|
79
|
+
:DTSTART, :LAST_MODIFIED, :LOCATION, :ORGANIZER, :PRIORITY, :SEQUENCE,
|
80
|
+
:SUMMARY, :URL, :DTEND, :DURATION, :CATEGORIES, :COMMENT, :CONTACT
|
81
|
+
else
|
82
|
+
parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
|
83
|
+
end
|
84
|
+
when :AVAILABLE
|
85
|
+
case key
|
86
|
+
when :DTSTAMP, :DTSTART, :UID, :DTEND, :DURATION, :CREATED,
|
87
|
+
:DESCRIPTION, :LAST_MODIFIED, :LOCATION, :RECURRENCE_ID, :RRULE,
|
88
|
+
:SUMMARY, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE, :RDATE
|
89
|
+
else
|
90
|
+
parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
errors
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,606 @@
|
|
1
|
+
require "vobject"
|
2
|
+
require "vobject/propertyvalue"
|
3
|
+
|
4
|
+
module Vobject
|
5
|
+
module Vcalendar
|
6
|
+
module PropertyValue
|
7
|
+
class Text < Vobject::PropertyValue
|
8
|
+
class << self
|
9
|
+
def escape(x)
|
10
|
+
# temporarily escape \\ as \u007f, which is banned from text
|
11
|
+
x.tr("\\", "\u007f").gsub(/\n/, "\\n").gsub(/,/, "\\,").
|
12
|
+
gsub(/;/, "\\;").gsub(/\u007f/, "\\\\\\\\")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(val)
|
17
|
+
self.value = val
|
18
|
+
self.type = "text"
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
Text.escape value
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_hash
|
26
|
+
value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ClassValue < Text
|
31
|
+
def initialize(val)
|
32
|
+
self.value = val
|
33
|
+
self.type = "classvalue"
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_hash
|
37
|
+
value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class TranspValue < Text
|
42
|
+
def initialize(val)
|
43
|
+
self.value = val
|
44
|
+
self.type = "transpvalue"
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_hash
|
48
|
+
value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class ActionValue < Text
|
53
|
+
def initialize(val)
|
54
|
+
self.value = val
|
55
|
+
self.type = "actionvalue"
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_hash
|
59
|
+
value
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class MethodValue < Text
|
64
|
+
def initialize(val)
|
65
|
+
self.value = val
|
66
|
+
self.type = "methodvalue"
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_hash
|
70
|
+
value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Busytype < Text
|
75
|
+
def initialize(val)
|
76
|
+
self.value = val
|
77
|
+
self.type = "busytype"
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_hash
|
81
|
+
value
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class Color < Text
|
86
|
+
def initialize(val)
|
87
|
+
self.value = val
|
88
|
+
self.type = "color"
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_hash
|
92
|
+
value
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class EventStatus < Text
|
97
|
+
def initialize(val)
|
98
|
+
self.value = val
|
99
|
+
self.type = "eventstatus"
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_hash
|
103
|
+
value
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Todostatus < Text
|
108
|
+
def initialize(val)
|
109
|
+
self.value = val
|
110
|
+
self.type = "todostatus"
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_hash
|
114
|
+
value
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class Journalstatus < Text
|
119
|
+
def initialize(val)
|
120
|
+
self.value = val
|
121
|
+
self.type = "journalstatus"
|
122
|
+
end
|
123
|
+
|
124
|
+
def to_hash
|
125
|
+
value
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class Ianatoken < Text
|
130
|
+
def initialize(val)
|
131
|
+
self.value = val
|
132
|
+
self.type = "ianatoken"
|
133
|
+
end
|
134
|
+
|
135
|
+
def to_hash
|
136
|
+
value
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class Binary < Text
|
141
|
+
def initialize(val)
|
142
|
+
self.value = val
|
143
|
+
self.type = "binary"
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_hash
|
147
|
+
value
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class Uri < Text
|
152
|
+
def initialize(val)
|
153
|
+
self.value = val
|
154
|
+
self.type = "uri"
|
155
|
+
end
|
156
|
+
|
157
|
+
def to_hash
|
158
|
+
value
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class Calscale < Vobject::PropertyValue
|
163
|
+
def initialize(val)
|
164
|
+
self.value = val
|
165
|
+
self.type = "calscale"
|
166
|
+
end
|
167
|
+
|
168
|
+
def to_s
|
169
|
+
value
|
170
|
+
end
|
171
|
+
|
172
|
+
def to_hash
|
173
|
+
value
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class Float < Vobject::PropertyValue
|
178
|
+
include Comparable
|
179
|
+
def <=>(another)
|
180
|
+
value <=> another.value
|
181
|
+
end
|
182
|
+
|
183
|
+
def initialize(val)
|
184
|
+
self.value = val
|
185
|
+
self.type = "float"
|
186
|
+
end
|
187
|
+
|
188
|
+
def to_s
|
189
|
+
value.to_s
|
190
|
+
end
|
191
|
+
|
192
|
+
def to_hash
|
193
|
+
value
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class Integer < Vobject::PropertyValue
|
198
|
+
include Comparable
|
199
|
+
def <=>(another)
|
200
|
+
value <=> another.value
|
201
|
+
end
|
202
|
+
|
203
|
+
def initialize(val)
|
204
|
+
self.value = val
|
205
|
+
self.type = "integer"
|
206
|
+
end
|
207
|
+
|
208
|
+
def to_s
|
209
|
+
value.to_s
|
210
|
+
end
|
211
|
+
|
212
|
+
def to_hash
|
213
|
+
value
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
class PercentComplete < Integer
|
218
|
+
def initialize(val)
|
219
|
+
self.value = val
|
220
|
+
self.type = "percentcomplete"
|
221
|
+
end
|
222
|
+
|
223
|
+
def to_hash
|
224
|
+
value
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
class Priority < Integer
|
229
|
+
def initialize(val)
|
230
|
+
self.value = val
|
231
|
+
self.type = "priority"
|
232
|
+
end
|
233
|
+
|
234
|
+
def to_hash
|
235
|
+
value
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
class Date < Vobject::PropertyValue
|
240
|
+
include Comparable
|
241
|
+
def <=>(another)
|
242
|
+
value <=> another.value
|
243
|
+
end
|
244
|
+
|
245
|
+
def initialize(val)
|
246
|
+
self.value = val
|
247
|
+
self.type = "date"
|
248
|
+
end
|
249
|
+
|
250
|
+
def to_s
|
251
|
+
sprintf("%04d%02d%02d", value.year, value.month, value.day)
|
252
|
+
end
|
253
|
+
|
254
|
+
def to_hash
|
255
|
+
value
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
class DateTimeLocal < Vobject::PropertyValue
|
260
|
+
include Comparable
|
261
|
+
def <=>(another)
|
262
|
+
value[:time] <=> another.value[:time]
|
263
|
+
end
|
264
|
+
|
265
|
+
def initialize(val)
|
266
|
+
self.value = val.clone
|
267
|
+
# val consists of :time && :zone values. If :zone is empty, floating local time (i.e. system local time) is assumed
|
268
|
+
self.type = "datetimeLocal"
|
269
|
+
value[:time] = if val[:zone].nil? || val[:zone].empty?
|
270
|
+
::Time.local(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
|
271
|
+
else
|
272
|
+
::Time.utc(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
|
273
|
+
end
|
274
|
+
value[:origtime] = value[:time]
|
275
|
+
end
|
276
|
+
|
277
|
+
def to_s
|
278
|
+
# ret = sprintf("%04d%02d%02dT%02d%02d%02d", value[:year], value[:month], value[:day], value[:hour], value[:min], value[:sec])
|
279
|
+
ret = sprintf("%s%s%sT%s%s%s", value[:year], value[:month], value[:day], value[:hour], value[:min], value[:sec])
|
280
|
+
zone = "Z" if value[:zone] && value[:zone] == "Z"
|
281
|
+
ret = ret + zone if !zone.nil?
|
282
|
+
ret
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
def to_hash
|
287
|
+
ret = {
|
288
|
+
year: value[:year],
|
289
|
+
month: value[:month],
|
290
|
+
day: value[:day],
|
291
|
+
hour: value[:hour],
|
292
|
+
min: value[:min],
|
293
|
+
sec: value[:sec],
|
294
|
+
}
|
295
|
+
ret[:zone] = value[:zone] if value[:zone]
|
296
|
+
ret
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
class DateTimeUTC < Vobject::PropertyValue
|
301
|
+
include Comparable
|
302
|
+
def <=>(another)
|
303
|
+
value[:time] <=> another.value[:time]
|
304
|
+
end
|
305
|
+
|
306
|
+
def initialize(val)
|
307
|
+
self.value = val.clone
|
308
|
+
value[:time] = ::Time.utc(val[:year], val[:month], val[:day], val[:hour], val[:min], val[:sec])
|
309
|
+
value[:origtime] = value[:time]
|
310
|
+
end
|
311
|
+
|
312
|
+
def to_s
|
313
|
+
localtime = value[:origtime]
|
314
|
+
ret = sprintf("%04d%02d%02dT%02d%02d%02dZ", localtime.year, localtime.month, localtime.day,
|
315
|
+
localtime.hour, localtime.min, localtime.sec)
|
316
|
+
ret
|
317
|
+
end
|
318
|
+
|
319
|
+
def to_hash
|
320
|
+
ret = {
|
321
|
+
year: value[:year],
|
322
|
+
month: value[:month],
|
323
|
+
day: value[:day],
|
324
|
+
hour: value[:hour],
|
325
|
+
min: value[:min],
|
326
|
+
sec: value[:sec],
|
327
|
+
}
|
328
|
+
ret
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
class Boolean < Vobject::PropertyValue
|
333
|
+
def initialize(val)
|
334
|
+
self.value = val
|
335
|
+
self.type = "boolean"
|
336
|
+
end
|
337
|
+
|
338
|
+
def to_s
|
339
|
+
value.to_s
|
340
|
+
end
|
341
|
+
|
342
|
+
def to_hash
|
343
|
+
value
|
344
|
+
end
|
345
|
+
|
346
|
+
def to_norm
|
347
|
+
value.to_s.upcase
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
class Duration < Vobject::PropertyValue
|
352
|
+
def initialize(val)
|
353
|
+
self.value = val
|
354
|
+
self.type = "duration"
|
355
|
+
end
|
356
|
+
|
357
|
+
def to_s
|
358
|
+
ret = "P"
|
359
|
+
ret = value[:sign] + ret if value[:sign]
|
360
|
+
ret = ret + "#{value[:weeks]}W" if value[:weeks]
|
361
|
+
ret = ret + "#{value[:days]}D" if value[:days]
|
362
|
+
ret = ret + "T" if value[:hours] || value[:minutes] || value[:seconds]
|
363
|
+
ret = ret + "#{value[:hours]}H" if value[:hours]
|
364
|
+
ret = ret + "#{value[:minutes]}M" if value[:minutes]
|
365
|
+
ret = ret + "#{value[:seconds]}S" if value[:seconds]
|
366
|
+
ret
|
367
|
+
end
|
368
|
+
|
369
|
+
def to_hash
|
370
|
+
value
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
class Time < Vobject::PropertyValue
|
375
|
+
def initialize(val)
|
376
|
+
self.value = val
|
377
|
+
self.type = "time"
|
378
|
+
end
|
379
|
+
|
380
|
+
def to_s
|
381
|
+
ret = "#{value[:hour]}#{value[:min]}#{value[:sec]}"
|
382
|
+
ret = ret + "Z" if value[:utc]
|
383
|
+
ret
|
384
|
+
end
|
385
|
+
|
386
|
+
def to_hash
|
387
|
+
value
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
class Utcoffset < Vobject::PropertyValue
|
392
|
+
def initialize(val)
|
393
|
+
self.value = val
|
394
|
+
self.type = "utcoffset"
|
395
|
+
end
|
396
|
+
|
397
|
+
def to_s
|
398
|
+
ret = "#{value[:sign]}#{value[:hr]}#{value[:min]}"
|
399
|
+
ret += value[:sec] if value[:sec]
|
400
|
+
ret
|
401
|
+
end
|
402
|
+
|
403
|
+
def to_hash
|
404
|
+
value
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
class Geovalue < Vobject::PropertyValue
|
409
|
+
def initialize(val)
|
410
|
+
self.value = val
|
411
|
+
self.type = "geovalue"
|
412
|
+
end
|
413
|
+
|
414
|
+
def to_s
|
415
|
+
ret = "#{value[:lat]};#{value[:long]}"
|
416
|
+
ret
|
417
|
+
end
|
418
|
+
|
419
|
+
def to_hash
|
420
|
+
value
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
class Version < Vobject::PropertyValue
|
425
|
+
def initialize(val)
|
426
|
+
self.value = val
|
427
|
+
self.type = "version"
|
428
|
+
end
|
429
|
+
|
430
|
+
def to_s
|
431
|
+
value.join(";")
|
432
|
+
end
|
433
|
+
|
434
|
+
def to_hash
|
435
|
+
if value.length == 1
|
436
|
+
value[0]
|
437
|
+
else
|
438
|
+
value
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
class Textlist < Vobject::PropertyValue
|
444
|
+
def initialize(val)
|
445
|
+
self.value = val
|
446
|
+
self.type = "textlist"
|
447
|
+
end
|
448
|
+
|
449
|
+
def to_s
|
450
|
+
value.map { |m| Text.escape m }.join(",")
|
451
|
+
end
|
452
|
+
|
453
|
+
def to_hash
|
454
|
+
value
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
class Periodlist < Vobject::PropertyValue
|
459
|
+
def initialize(val)
|
460
|
+
self.value = val
|
461
|
+
self.type = "periodlist"
|
462
|
+
end
|
463
|
+
|
464
|
+
def to_s
|
465
|
+
value.map do |m|
|
466
|
+
ret = m[:start].to_s + "/"
|
467
|
+
ret += m[:end].to_s if m.has_key? :end
|
468
|
+
ret += m[:duration].to_s if m.has_key? :duration
|
469
|
+
ret
|
470
|
+
end.join(",")
|
471
|
+
end
|
472
|
+
|
473
|
+
def to_hash
|
474
|
+
value.map { |m| m.each { |k, v| m[k] = v.to_hash } }
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
class Datelist < Vobject::PropertyValue
|
479
|
+
def initialize(val)
|
480
|
+
self.value = val
|
481
|
+
self.type = "datelist"
|
482
|
+
end
|
483
|
+
|
484
|
+
def to_s
|
485
|
+
value.map(&:to_s).join(",")
|
486
|
+
end
|
487
|
+
|
488
|
+
def to_hash
|
489
|
+
value.map(&:to_hash)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
class Datetimelist < Vobject::PropertyValue
|
494
|
+
def initialize(val)
|
495
|
+
self.value = val
|
496
|
+
self.type = "datetimelist"
|
497
|
+
end
|
498
|
+
|
499
|
+
def to_s
|
500
|
+
value.map(&:to_s).join(",")
|
501
|
+
end
|
502
|
+
|
503
|
+
def to_hash
|
504
|
+
value.map(&:to_hash)
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
class Datetimeutclist < Vobject::PropertyValue
|
509
|
+
def initialize(val)
|
510
|
+
self.value = val
|
511
|
+
self.type = "datetimeutclist"
|
512
|
+
end
|
513
|
+
|
514
|
+
def to_s
|
515
|
+
value.map(&:to_s).join(",")
|
516
|
+
end
|
517
|
+
|
518
|
+
def to_hash
|
519
|
+
value.map(&:to_hash)
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
class Requeststatusvalue < Vobject::PropertyValue
|
524
|
+
def initialize(val)
|
525
|
+
self.value = val
|
526
|
+
self.type = "requeststatusvalue"
|
527
|
+
end
|
528
|
+
|
529
|
+
def to_s
|
530
|
+
ret = "#{value[:statcode]};#{value[:statdesc]}"
|
531
|
+
ret += ";#{value[:extdata]}" if value[:extdata]
|
532
|
+
ret
|
533
|
+
end
|
534
|
+
|
535
|
+
def to_hash
|
536
|
+
value
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
class Recur < Vobject::PropertyValue
|
541
|
+
def initialize(val)
|
542
|
+
self.value = val
|
543
|
+
self.type = "recur"
|
544
|
+
end
|
545
|
+
|
546
|
+
def to_s
|
547
|
+
ret = []
|
548
|
+
value.each do |k, v|
|
549
|
+
ret << "#{k.to_s.upcase}=#{valencode(k, v)}"
|
550
|
+
end
|
551
|
+
ret.join(";")
|
552
|
+
end
|
553
|
+
|
554
|
+
def to_hash
|
555
|
+
ret = {}
|
556
|
+
value.each do |k, v|
|
557
|
+
ret[k] = if v.respond_to?(:to_hash)
|
558
|
+
v.to_hash
|
559
|
+
else
|
560
|
+
v
|
561
|
+
end
|
562
|
+
end
|
563
|
+
ret
|
564
|
+
end
|
565
|
+
|
566
|
+
private
|
567
|
+
|
568
|
+
def valencode(k, v)
|
569
|
+
case k
|
570
|
+
when :bysetpos, :byyearday
|
571
|
+
v.map do |x|
|
572
|
+
ret = x[:ordyrday]
|
573
|
+
ret = x[:sign] + ret if x[:sign]
|
574
|
+
ret
|
575
|
+
end.join(",")
|
576
|
+
when :byweekno
|
577
|
+
v.map do |x|
|
578
|
+
ret = x[:ordwk]
|
579
|
+
ret = x[:sign] + ret if x[:sign]
|
580
|
+
ret
|
581
|
+
end.join(",")
|
582
|
+
when :bymonthday
|
583
|
+
v.map do |x|
|
584
|
+
ret = x[:ordmoday]
|
585
|
+
ret = x[:sign] + ret if x[:sign]
|
586
|
+
ret
|
587
|
+
end.join(",")
|
588
|
+
when :byday
|
589
|
+
v.map do |x|
|
590
|
+
ret = x[:weekday]
|
591
|
+
ret = x[:ordwk] + ret if x[:ordwk]
|
592
|
+
ret = x[:sign] + ret if x[:sign]
|
593
|
+
ret
|
594
|
+
end.join(",")
|
595
|
+
when :bymonth, :byhour, :byminute, :bysecond
|
596
|
+
v.join(",")
|
597
|
+
when :enddate
|
598
|
+
v.to_s
|
599
|
+
else
|
600
|
+
v
|
601
|
+
end
|
602
|
+
end
|
603
|
+
end
|
604
|
+
end
|
605
|
+
end
|
606
|
+
end
|