vobject 0.1.0 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|