Class: Vobject::Vcalendar::Typegrammars

Inherits:
Object
  • Object
show all
Defined in:
lib/vobject/vcalendar/typegrammars.rb,
lib/vobject/vcalendar/propertyparent.rb

Class Method Summary collapse

Class Method Details

.actionvalueObject



341
342
343
344
345
# File 'lib/vobject/vcalendar/typegrammars.rb', line 341

def actionvalue
  actionvalue = (/AUDIO/i.r | /DISPLAY/i.r | /EMAIL/i.r | C::IANATOKEN |
                 C::XNAME_VCAL).map { |m| PropertyValue::ActionValue.new m }
  actionvalue.eof
end

.binaryObject



186
187
188
189
190
191
192
193
194
195
# File 'lib/vobject/vcalendar/typegrammars.rb', line 186

def binary
  binary = seq(/[a-zA-Z0-9+\/]*/.r, /={0,2}/.r) do |b, q|
    if (b.length + q.length) % 4 == 0
      PropertyValue::Binary.new(b + q)
    else
      { error: "Malformed binary coding" }
    end
  end
  binary.eof
end

.booleanObject



347
348
349
350
# File 'lib/vobject/vcalendar/typegrammars.rb', line 347

def boolean
  boolean = C::BOOLEAN.map { |b| PropertyValue::Boolean.new b }
  boolean.eof
end

.busytypeObject

RFC 7953



361
362
363
364
365
366
# File 'lib/vobject/vcalendar/typegrammars.rb', line 361

def busytype
  busytype = (/BUSY-UNAVAILABLE/i.r | /BUSY-TENTATIVE/i.r | /BUSY/i.r |
              C::IANATOKEN |
              C::XNAME_VCAL).map { |m| PropertyValue::BusyType.new m }
  busytype.eof
end

.calscalevalueObject



164
165
166
167
# File 'lib/vobject/vcalendar/typegrammars.rb', line 164

def calscalevalue
  calscalevalue = /GREGORIAN/i.r.map { PropertyValue::Calscale.new "GREGORIAN" }
  calscalevalue.eof
end

.classvalueObject



233
234
235
236
237
238
# File 'lib/vobject/vcalendar/typegrammars.rb', line 233

def classvalue
  classvalue = (/PUBLIC/i.r | /PRIVATE/i.r | /CONFIDENTIAL/i.r | C::XNAME_VCAL | C::IANATOKEN).map do |m|
    PropertyValue::ClassValue.new m
  end
  classvalue.eof
end

.colorObject



369
370
371
372
# File 'lib/vobject/vcalendar/typegrammars.rb', line 369

def color
  color = C::COLOR.map { |m| PropertyValue::Color.new m }
  color.eof
end

.date_tObject



261
262
263
264
# File 'lib/vobject/vcalendar/typegrammars.rb', line 261

def date_t
  date_t = C::DATE
  date_t.eof
end

.date_time_tObject



274
275
276
# File 'lib/vobject/vcalendar/typegrammars.rb', line 274

def date_time_t
  C::DATE_TIME.eof
end

.date_time_utc_tObject



289
290
291
292
# File 'lib/vobject/vcalendar/typegrammars.rb', line 289

def date_time_utc_t
  date_time_utc_t = C::DATE_TIME_UTC
  date_time_utc_t.eof
end

.date_time_utclistObject



294
295
296
297
298
299
300
301
302
# File 'lib/vobject/vcalendar/typegrammars.rb', line 294

def date_time_utclist
  date_time_utclist1 = seq(C::DATE_TIME_UTC << ",".r, lazy { date_time_utclist1 }) do |d, l|
    [d, l].flatten
  end | C::DATE_TIME_UTC.map { |d| [d] }
  date_time_utclist = date_time_utclist1.map do |m|
    PropertyValue::Datetimeutclist.new m
  end
  date_time_utclist.eof
end

.date_timelistObject



278
279
280
281
282
283
284
285
286
287
# File 'lib/vobject/vcalendar/typegrammars.rb', line 278

def date_timelist
  date_timelist1 = seq(C::DATE_TIME << ",".r,
                       lazy { date_timelist1 }) do |d, l|
    [d, l].flatten
  end | C::DATE_TIME.map { |d| [d] }
  date_timelist = date_timelist1.map do |m|
    PropertyValue::Datetimelist.new m
  end
  date_timelist.eof
end

.datelistObject



266
267
268
269
270
271
272
# File 'lib/vobject/vcalendar/typegrammars.rb', line 266

def datelist
  datelist1 = seq(C::DATE << ",".r, lazy { datelist1 }) do |d, l|
    [d, l].flatten
  end | C::DATE.map { |d| [d] }
  datelist = datelist1.map { |m| PropertyValue::Datelist.new m }
  datelist.eof
end

.duration_tObject



304
305
306
307
# File 'lib/vobject/vcalendar/typegrammars.rb', line 304

def duration_t
  duration = C::DURATION.map { |d| PropertyValue::Duration.new d }
  duration.eof
end

.eventstatusObject



240
241
242
243
244
245
# File 'lib/vobject/vcalendar/typegrammars.rb', line 240

def eventstatus
  eventstatus = (/TENTATIVE/i.r | /CONFIRMED/i.r | /CANCELLED/i.r).map do |m|
    PropertyValue::EventStatus.new m
  end
  eventstatus.eof
end

.float_tObject



142
143
144
145
# File 'lib/vobject/vcalendar/typegrammars.rb', line 142

def float_t
  float_t = prim(:double).map { |f| PropertyValue::Float.new f }
  float_t.eof
end

.geovalueObject



152
153
154
155
156
157
158
159
160
161
162
# File 'lib/vobject/vcalendar/typegrammars.rb', line 152

def geovalue
  float = prim(:double)
  geovalue = seq(float << ";".r, float) do |a, b|
    if a <= 180.0 && a >= -180.0 && b <= 180 && b > -180
      PropertyValue::Geovalue.new(lat: a, long: b)
    else
      { error: "Latitude/Longitude outside of range -180..180" }
    end
  end
  geovalue.eof
end

.iana_tokenObject



169
170
171
172
# File 'lib/vobject/vcalendar/typegrammars.rb', line 169

def iana_token
  iana_token = C::IANATOKEN.map { |x| PropertyValue::Ianatoken.new x }
  iana_token.eof
end

.integerObject



115
116
117
118
# File 'lib/vobject/vcalendar/typegrammars.rb', line 115

def integer
  integer = prim(:int32).map { |i| PropertyValue::Integer.new i }
  integer.eof
end

.journalstatusObject



254
255
256
257
258
259
# File 'lib/vobject/vcalendar/typegrammars.rb', line 254

def journalstatus
  journalstatus = (/DRAFT/i.r | /FINAL/i.r | /CANCELLED/i.r).map do |m|
    PropertyValue::Journalstatus.new m
  end
  journalstatus.eof
end

.methodvalueObject

RFC 5546



353
354
355
356
357
358
# File 'lib/vobject/vcalendar/typegrammars.rb', line 353

def methodvalue
  methodvalue = (/PUBLISH/i.r | /REQUEST/i.r | /REPLY/i.r | /ADD/i.r |
                 /CANCEL/i.r | /REFRESH/i.r | /COUNTER/i.r |
                 /DECLINECOUNTER/i.r).map { |m| PropertyValue::MethodValue.new m }
  methodvalue.eof
end

.percent_completeObject



120
121
122
123
124
125
126
127
128
129
# File 'lib/vobject/vcalendar/typegrammars.rb', line 120

def percent_complete
  integer = prim(:int32).map do |a|
    if a >= 0 && a <= 100
      PropertyValue::PercentComplete.new a
    else
      { error: "Percentage outside of range 0..100" }
    end
  end
  integer.eof
end

.periodlistObject



309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/vobject/vcalendar/typegrammars.rb', line 309

def periodlist
  period_explicit = seq(C::DATE_TIME << "/".r, C::DATE_TIME) do |s, e|
    { start: s, end: e }
  end
  period_start = seq(C::DATE_TIME << "/".r, C::DURATION) do |s, d|
    { start: s, duration: PropertyValue::Duration.new(d) }
  end
  period = period_explicit | period_start
  periodlist1 = seq(period << ",".r, lazy { periodlist1 }) do |p, l|
    [p, l].flatten
  end | period.map { |p| [p] }
  periodlist = periodlist1.map { |m| PropertyValue::Periodlist.new m }
  periodlist.eof
end

.priorityObject



131
132
133
134
135
136
137
138
139
140
# File 'lib/vobject/vcalendar/typegrammars.rb', line 131

def priority
  integer = prim(:int32).map do |a|
    if a >= 0 && a <= 9
      PropertyValue::Priority.new a
    else
      { error: "Percentage outside of range 0..100" }
    end
  end
  integer.eof
end

.property_parent(strict, key, component, _value, ctx1) ⇒ Object

Ensure each property belongs to a legal component



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/vobject/vcalendar/propertyparent.rb', line 15

def property_parent(strict, key, component, _value, ctx1)
  errors = []
  if key !~ /^x/i && registered_propname?(key.to_s)
    case component
    when :EVENT
      case key
      when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
        :GEO, :LAST_MOD, :LOCATION, :ORGANIZER, :PRIORITY, :SEQUENCE, :STATUS,
        :SUMMARY, :TRANSP, :URL, :RECURRENCE_ID, :RRULE, :DTEND, :DURATION,
        :ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
        :RSTATUS, :RELATED, :RESOURCES, :RDATE, :COLOR, :CONFERENCE, :IMAGE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :TODO
      case key
      when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
        :GEO, :LAST_MOD, :LOCATION, :ORGANIZER, :PRIORITY, :PERCENT_COMPLETED, :SEQUENCE, :STATUS,
        :SUMMARY, :URL, :RECURRENCE_ID, :RRULE, :DUE, :DURATION,
        :ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
        :RSTATUS, :RELATED, :RESOURCES, :RDATE, :COLOR, :CONFERENCE, :IMAGE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :JOURNAL
      case key
      when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
        :LAST_MOD, :ORGANIZER, :RECURRENCE_ID, :SEQUENCE, :STATUS,
        :SUMMARY, :URL, :RRULE,
        :ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
        :RSTATUS, :RELATED, :RDATE, :COLOR, :IMAGE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :FREEBUSY
      case key
      when :DTSTAMP, :UID, :CONTACT, :DTSTART, :DTEND, :ORGANIZER, :URL,
        :ATTENDEE, :COMMENT, :FREEBUSY, :RSTATUS
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :TIMEZONE
      case key
      when :TZID, :LAST_MODIFIED, :TZURL
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :DAYLIGHT, :STANDARD
      case key
      when :DTSTART, :TZOFFSETTO, :TZOFFSETFROM, :RRULE,
        :COMMENT, :RDATE, :TZNAME
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :ALARM
      case key
      when :ACTION, :TRIGGER, :DURATION, :REPEAT, :ATTACH, :DESCRIPTION,
        :SUMMARY, :ATTENDEE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :VAVAILABILITY
      case key
      when :DTSTAMP, :UID, :BUSYTYPE, :CLASS, :CREATED, :DESCRIPTION,
        :DTSTART, :LAST_MODIFIED, :LOCATION, :ORGANIZER, :PRIORITY, :SEQUENCE,
        :SUMMARY, :URL, :DTEND, :DURATION, :CATEGORIES, :COMMENT, :CONTACT
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :AVAILABLE
      case key
      when :DTSTAMP, :DTSTART, :UID, :DTEND, :DURATION, :CREATED,
        :DESCRIPTION, :LAST_MODIFIED, :LOCATION, :RECURRENCE_ID, :RRULE,
        :SUMMARY, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE, :RDATE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    end
  end
  errors
end

.recurObject

property value types, each defining their own parser



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/vobject/vcalendar/typegrammars.rb', line 17

def recur
  freq = /SECONDLY/i.r | /MINUTELY/i.r | /HOURLY/i.r | /DAILY/i.r |
    /WEEKLY/i.r | /MONTHLY/i.r | /YEARLY/i.r
  enddate = C::DATE_TIME | C::DATE
  seconds = /[0-9]{1,2}/.r
  byseclist = seq(seconds << ",".r, lazy { byseclist }) do |s, l|
    [s, l].flatten
  end | seconds.map { |s| [s] }
  minutes = /[0-9]{1,2}/.r
  byminlist = seq(minutes << ",".r, lazy { byminlist }) do |m, l|
    [m, l].flatten
  end | minutes.map { |m| [m] }
  hours = /[0-9]{1,2}/.r
  byhrlist = seq(hours << ",".r, lazy { byhrlist }) do |h, l|
    [h, l].flatten
  end | hours.map { |h| [h] }
  ordwk = /[0-9]{1,2}/.r
  weekday = /SU/i.r | /MO/i.r | /TU/i.r | /WE/i.r | /TH/i.r | /FR/i.r | /SA/i.r
  weekdaynum1 = seq(C::SIGN._?, ordwk) do |s, o|
    h = { ordwk: o }
    h[:sign] = s[0] unless s.empty?
    h
  end
  weekdaynum = seq(weekdaynum1._?, weekday) do |a, b|
    h = { weekday: b }
    h = h.merge a[0] unless a.empty?
    h
  end
  bywdaylist = seq(weekdaynum << ",".r, lazy { bywdaylist }) do |w, l|
    [w, l].flatten
  end | weekdaynum.map { |w| [w] }
  ordmoday = /[0-9]{1,2}/.r
  monthdaynum = seq(C::SIGN._?, ordmoday) do |s, o|
    h = { ordmoday: o }
    h[:sign] = s[0] unless s.empty?
    h
  end
  bymodaylist = seq(monthdaynum << ",".r, lazy { bymodaylist }) do |m, l|
    [m, l].flatten
  end | monthdaynum.map { |m| [m] }
  ordyrday = /[0-9]{1,3}/.r
  yeardaynum = seq(C::SIGN._?, ordyrday) do |s, o|
    h = { ordyrday: o }
    h[:sign] = s[0] unless s.empty?
    h
  end
  byyrdaylist = seq(yeardaynum << ",".r, lazy { byyrdaylist }) do |y, l|
    [y, l].flatten
  end | yeardaynum.map { |y| [y] }
  weeknum = seq(C::SIGN._?, ordwk) do |s, o|
    h = { ordwk: o }
    h[:sign] = s[0] unless s.empty?
    h
  end
  bywknolist = seq(weeknum << ",".r, lazy { bywknolist }) do |w, l|
    [w, l].flatten
  end | weeknum.map { |w| [w] }
  # monthnum = /[0-9]{1,2}/.r
  # RFC 7529 add leap month indicator
  monthnum = /[0-9]{1,2}L?/i.r
  bymolist = seq(monthnum << ",".r, lazy { bymolist }) do |m, l|
    [m, l].flatten
  end | monthnum.map { |m| [m] }
  setposday = yeardaynum
  bysplist = seq(setposday << ",".r, lazy { bysplist }) do |s, l|
    [s, l].flatten
  end | setposday.map { |s| [s] }
  # http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/calendar.xml
  rscale = C::XNAME_VCAL | /buddhist/i.r | /chinese/i.r | /coptic/i.r | /dangi/i.r |
    /ethioaa/i.r | /ethiopic-amete-alem/i.r | /ethiopic/i.r |
    /gregory/i.r | /hebrew/i.r | /indian/i.r | /islamic/i.r |
    /islamic-umalqura/i.r | /islamic-tbla/i.r | /islamic-civil/i.r |
    /islamic-rgsa/i.r | /iso8601/i.r | /japanese/i.r | /persian/i.r |
    /roc/i.r | /islamicc/i.r | /gregorian/i.r
  skip = /OMIT/i.r | /BACKWARD/i.r | /FORWARD/i.r
  recur_rule_part = 	seq(/FREQ/i.r << "=".r, freq) { |_k, v| { freq: v } } |
    seq(/UNTIL/i.r << "=".r, enddate) { |_k, v| { until: v } } |
    seq(/COUNT/i.r << "=".r, /[0-9]+/i.r) { |_k, v| { count: v } } |
    seq(/INTERVAL/i.r << "=".r, /[0-9]+/i.r) { |_k, v| { interval: v } } |
    seq(/BYSECOND/i.r << "=".r, byseclist) { |_k, v| { bysecond: v } } |
    seq(/BYMINUTE/i.r << "=".r, byminlist) { |_k, v| { byminute: v } } |
    seq(/BYHOUR/i.r << "=".r, byhrlist) { |_k, v| { byhour: v } } |
    seq(/BYDAY/i.r << "=".r, bywdaylist) { |_k, v| { byday: v } } |
    seq(/BYMONTHDAY/i.r << "=".r, bymodaylist) { |_k, v| { bymonthday: v } } |
    seq(/BYYEARDAY/i.r << "=".r, byyrdaylist) { |_k, v| { byyearday: v } } |
    seq(/BYWEEKNO/i.r << "=".r, bywknolist) { |_k, v| { byweekno: v } } |
    seq(/BYMONTH/i.r << "=".r, bymolist) { |_k, v| { bymonth: v } } |
    seq(/BYSETPOS/i.r << "=".r, bysplist) { |_k, v| { bysetpos: v } } |
    seq(/WKST/i.r << "=".r, weekday) { |_k, v| { wkst: v } } |
    # RFC 7529
    seq(/RSCALE/i.r << "=".r, rscale) { |_k, v| { rscale: v } } |
    seq(/SKIP/i.r << "=".r, skip) { |_k, v| { skip: v } }
  recur1 = seq(recur_rule_part, ";", lazy { recur1 }) { |h, _, r| h.merge r } |
    recur_rule_part
  recur = recur1.map { |r| PropertyValue::Recur.new r }
  recur.eof
end

.registered_propnameObject



381
382
383
384
# File 'lib/vobject/vcalendar/typegrammars.rb', line 381

def registered_propname
  registered_propname = C::NAME_VCAL
  registered_propname.eof
end

.registered_propname?(x) ⇒ Boolean

Returns:

  • (Boolean)


386
387
388
389
# File 'lib/vobject/vcalendar/typegrammars.rb', line 386

def registered_propname?(x)
  p = registered_propname.parse(x)
  not(Rsec::INVALID[p])
end

.request_statusvalueObject



221
222
223
224
225
226
227
228
229
230
231
# File 'lib/vobject/vcalendar/typegrammars.rb', line 221

def request_statusvalue
  @req_status = Set.new %w{2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 4.0 5.0 5.1 5.2 5.3}
  extdata = seq(";".r, C::TEXT) { |_, t| t }
  request_statusvalue = seq(/[0-9](\.[0-9]){1,2}/.r << ";".r, C::TEXT, extdata._?) do |n, t1, t2|
    return { error: "Invalid request status #{n}" } unless @req_status.include?(n) # RFC 5546
    hash = { statcode: n, statdesc: t1 }
    hash[:extdata] = t2[0] unless t2.empty?
    Vobject::Vcalendar::PropertyValue::Requeststatusvalue.new hash
  end
  request_statusvalue.eof
end

.text_tObject



208
209
210
211
# File 'lib/vobject/vcalendar/typegrammars.rb', line 208

def text_t
  text_t = C::TEXT.map { |t| PropertyValue::Text.new(unescape(t)) }
  text_t.eof
end

.textlistObject



213
214
215
216
217
218
219
# File 'lib/vobject/vcalendar/typegrammars.rb', line 213

def textlist
  textlist1 =
    seq(C::TEXT << ",".r, lazy { textlist1 }) { |a, b| [unescape(a), b].flatten } |
    C::TEXT.map { |t| [unescape(t)] }
  textlist = textlist1.map { |m| PropertyValue::Textlist.new m }
  textlist.eof
end

.time_tObject



147
148
149
150
# File 'lib/vobject/vcalendar/typegrammars.rb', line 147

def time_t
  time_t = C::TIME.map { |t| PropertyValue::Time.new t }
  time_t.eof
end

.todostatusObject



247
248
249
250
251
252
# File 'lib/vobject/vcalendar/typegrammars.rb', line 247

def todostatus
  todostatus = (/NEEDS-ACTION/i.r | /COMPLETED/i.r | /IN-PROCESS/i.r | /CANCELLED/i.r).map do |m|
    PropertyValue::Todostatus.new m
  end
  todostatus.eof
end

.transpvalueObject



324
325
326
327
328
329
# File 'lib/vobject/vcalendar/typegrammars.rb', line 324

def transpvalue
  transpvalue = (/OPAQUE/i.r | /TRANSPARENT/i.r).map do |m|
    PropertyValue::TranspValue.new m
  end
  transpvalue.eof
end

.typematch(strict, key, params, component, value, ctx) ⇒ Object

Enforce type restrictions on values of particular properties. If successful, return typed interpretation of string



393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
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
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
# File 'lib/vobject/vcalendar/typegrammars.rb', line 393

def typematch(strict, key, params, component, value, ctx)
  errors = []
  errors << property_parent(strict, key, component, value, ctx)
  ctx1 = Rsec::ParseContext.new value, "source"
  case key
  when :CALSCALE
    ret = calscalevalue._parse ctx1
  when :METHOD
    ret = methodvalue._parse ctx1
  when :VERSION
    ret = versionvalue._parse ctx1
  when :ATTACH
    ret = if params[:VALUE] == "BINARY"
            binary._parse ctx1
          else
            uri._parse ctx1
          end
  when :IMAGE
    parse_err(strict, errors, "No VALUE parameter specified for property #{key}", ctx1) if params.empty?
    parse_err(strict, errors, "No VALUE parameter specified for property #{key}", ctx1) unless params[:VALUE]
    if params[:VALUE] == "BINARY"
      parse_err(strict, errors, "No ENCODING parameter specified for property #{key}", ctx1) unless params[:ENCODING]
      parse_err(strict, errors, "Incorrect ENCODING parameter specified for property #{key}", ctx1) unless params[:ENCODING] == "BASE64"
      ret = binary._parse ctx1
    elsif params[:VALUE] == "URI"
      ret = uri._parse ctx1
    else
      parse_err(strict, errors, "Incorrect VALUE parameter specified for property #{key}", ctx1)
    end
  when :CATEGORIES, :RESOURCES
    ret = textlist._parse ctx1
  when :CLASS
    ret = classvalue._parse ctx1
  when :COMMENT, :DESCRIPTION, :LOCATION, :SUMMARY, :TZID, :TZNAME,
    :CONTACT, :RELATED_TO, :UID, :PRODID, :NAME
    ret = text_t._parse ctx1
  when :GEO
    ret = geovalue._parse ctx1
  when :PERCENT_COMPLETE
    ret = percent_complete._parse ctx1
  when :PRIORITY
    ret = priority._parse ctx1
  when :STATUS
    ret = case component
          when :EVENT
            eventstatus._parse ctx1
          when :TODO
            todostatus._parse ctx1
          when :JOURNAL
            journalstatus._parse ctx1
          else
            text_t._parse ctx1
          end
  when :COMPLETED, :CREATED, :DTSTAMP, :LAST_MODIFIED
    ret = date_time_utc_t._parse ctx1
  when :DTEND, :DTSTART, :DUE, :RECURRENCE_ID
    if params && params[:VALUE] == "DATE"
      ret = date_t._parse ctx1
    elsif component == :FREEBUSY
      ret = date_time_utc_t._parse ctx1
    elsif params && params[:TZID]
      if [:STANDARD || :DAYLIGHT].include? component
        parse_err(strict, errors, "Specified TZID within property #{key} in #{component}", ctx1)
      end
      begin
        tz = TZInfo::Timezone.get(params[:TZID])
        ret = date_time_t._parse ctx1
        # note that we use the registered tz information to map to UTC, rather than look up the values witin the VTIMEZONE component
        ret.value[:time] = tz.local_to_utc(ret.value[:time])
        ret.value[:zone] = params[:TZID]
      rescue
        # undefined timezone: default to floating local
        ret = date_time_t._parse ctx1
      end
    else
      ret = date_time_t._parse ctx1
    end
  when :EXDATE
    if params && params[:VALUE] == "DATE"
      ret = datelist._parse ctx1
    elsif params && params[:TZID]
      if [:STANDARD || :DAYLIGHT].include? component
        parse_err(strict, errors, "Specified TZID within property #{key} in #{component}", ctx1)
      end
      tz = TZInfo::Timezone.get(params[:TZID])
      ret = date_timelist._parse ctx1
      ret.value.each do |x|
        x.value[:time] = tz.local_to_utc(x.value[:time])
        x.value[:zone] = params[:TZID]
      end
    else
      ret = date_timelist._parse ctx1
    end
  when :RDATE
    if params && params[:VALUE] == "DATE"
      ret = datelist._parse ctx1
    elsif params && params[:VALUE] == "PERIOD"
      ret = periodlist._parse ctx1
    elsif params && params[:TZID]
      if [:STANDARD || :DAYLIGHT].include? component
        parse_err(strict, errors, "Specified TZID within property #{key} in #{component}", ctx1)
      end
      tz = TZInfo::Timezone.get(params[:TZID])
      ret = date_timelist._parse ctx1
      ret.value.each do |x|
        x.value[:time] = tz.local_to_utc(x.value[:time])
        x.value[:zone] = params[:TZID]
      end
    else
      ret = date_timelist._parse ctx1
    end
  when :TRIGGER
    if params && params[:VALUE] == "DATE-TIME" || /^\d{8}T/.match(value)
      if params && params[:RELATED]
        parse_err(strict, errors, "Specified RELATED within property #{key} as date-time", ctx1)
      end
      ret = date_time_utc_t._parse ctx1
    else
      ret = duration_t._parse ctx1
    end
  when :FREEBUSY
    ret = periodlist._parse ctx1
  when :TRANSP
    ret = transpvalue._parse ctx1
  when :TZOFFSETFROM, :TZOFFSETTO
    ret = utc_offset._parse ctx1
  when :TZURI, :URL, :SOURCE, :CONFERENCE
    if key == :CONFERENCE
      parse_err(strict, errors, "Missing URI VALUE parameter", ctx1) if params.empty?
      parse_err(strict, errors, "Missing URI VALUE parameter", ctx1) if !params[:VALUE]
      parse_err(strict, errors, "report_error Type mismatch of VALUE parameter #{params[:VALUE]} for property #{key}", ctx1) if params[:VALUE] != "URI"
    end
    ret = uri._parse ctx1
  when :ATTENDEE, :ORGANIZER
    ret = uri._parse ctx1
  when :RRULE
    ret = recur._parse ctx1
  when :ACTION
    ret = actionvalue._parse ctx1
  when :REPEAT, :SEQUENCE
    ret = integer._parse ctx1
  when :REQUEST_STATUS
    ret = request_statusvalue._parse ctx1
    # RFC 7953
  when :BUSYTYPE
    ret = busytype._parse ctx1
    # RFC 7986
  when :REFRESH_INTERVAL
    parse_err(strict, errors, "Missing VALUE parameter for property #{key}", ctx1) if params.empty?
    parse_err(strict, errors, "Missing VALUE parameter for property #{key}", ctx1) if !params[:VALUE]
    parse_err(strict, errors, "Type mismatch of VALUE parameter #{params[:VALUE]} for property #{key}", ctx1) if params[:VALUE] != "DURATION"
    ret = duration_t._parse ctx1
    # RFC 7986
  when :COLOR
    ret = color._parse ctx1
  else
    if params && params[:VALUE]
      case params[:VALUE]
      when "BOOLEAN"
        ret = boolean._parse ctx1
      when "BINARY"
        ret = binary._parse ctx1
      when "CAL-ADDRESS"
        ret = uri._parse ctx1
      when "DATE-TIME"
        ret = date_time_t._parse ctx1
      when "DATE"
        ret = date_t._parse ctx1
      when "DURATION"
        ret = duration_t._parse ctx1
      when "FLOAT"
        ret = float_t._parse ctx1
      when "INTEGER"
        ret = integer._parse ctx1
      when "PERIOD"
        ret = period._parse ctx1
      when "RECUR"
        ret = recur._parse ctx1
      when "TEXT"
        ret = text_t._parse ctx1
      when "TIME"
        ret = time_t._parse ctx1
      when "URI"
        ret = uri._parse ctx1
      when "UTC-OFFSET"
        ret = utc_offset._parse ctx1
      end
    else
      ret = text_t._parse ctx1
    end
  end
  if ret.is_a?(Hash) && ret[:error]
    parse_err(strict, errors, "#{ret[:error]} for property #{key}, value #{value}", ctx)
  end
  if Rsec::INVALID[ret]
    parse_err(strict, errors, "Type mismatch for property #{key}, value #{value}", ctx)
  end
  Rsec::Fail.reset
  [ret, errors]
end

.unescape(x) ⇒ Object

text escapes: \ ; , N n



375
376
377
378
379
# File 'lib/vobject/vcalendar/typegrammars.rb', line 375

def unescape(x)
  # temporarily escape \\ as \007f, which is disallowed in any text
  x.gsub(/\\\\/, "\u007f").gsub(/\\;/, ";").gsub(/\\,/, ",").
    gsub(/\\[Nn]/, "\n").tr("\u007f", "\\")
end

.uriObject



197
198
199
200
201
202
203
204
205
206
# File 'lib/vobject/vcalendar/typegrammars.rb', line 197

def uri
  uri = /\S+/.r.map do |s|
    if s =~ URI::DEFAULT_PARSER.make_regexp
      PropertyValue::Uri.new(s)
    else
      { error: "Invalid URI" }
    end
  end
  uri.eof
end

.utc_offsetObject



331
332
333
334
335
336
337
338
339
# File 'lib/vobject/vcalendar/typegrammars.rb', line 331

def utc_offset
  utc_offset = seq(C::SIGN, /[0-9]{2}/.r, /[0-9]{2}/.r,
                   /[0-9]{2}/.r._?) do |sign, h, m, sec|
    hash = { sign: sign, hr: h, min: m }
    hash[:sec] = sec[0] unless sec.empty?
    PropertyValue::Utcoffset.new hash
  end
  utc_offset.eof
end

.versionvalueObject



174
175
176
177
178
179
180
181
182
183
184
# File 'lib/vobject/vcalendar/typegrammars.rb', line 174

def versionvalue
  versionvalue = seq(prim(:double) << ";".r,
                     prim(:double)) do |x, y|
    PropertyValue::Version.new [x, y]
  end | "2.0".r.map do
    PropertyValue::Version.new ["2.0"]
  end | prim(:double).map do |v|
    PropertyValue::Version.new v
  end
  versionvalue.eof
end