vobject 0.1.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/macos.yml +38 -0
  3. data/.github/workflows/ubuntu.yml +56 -0
  4. data/.github/workflows/windows.yml +40 -0
  5. data/.hound.yml +3 -0
  6. data/.rubocop.tb.yml +650 -0
  7. data/.rubocop.yml +1077 -0
  8. data/Gemfile +1 -1
  9. data/LICENSE.txt +21 -17
  10. data/README.adoc +151 -0
  11. data/Rakefile +1 -1
  12. data/lib/c.rb +173 -0
  13. data/lib/error.rb +19 -0
  14. data/lib/vcalendar.rb +77 -0
  15. data/lib/vcard.rb +67 -0
  16. data/lib/vobject.rb +13 -170
  17. data/lib/vobject/component.rb +87 -36
  18. data/lib/vobject/parameter.rb +116 -0
  19. data/lib/vobject/parametervalue.rb +26 -0
  20. data/lib/vobject/property.rb +134 -55
  21. data/lib/vobject/propertyvalue.rb +46 -0
  22. data/lib/vobject/vcalendar/component.rb +106 -0
  23. data/lib/vobject/vcalendar/grammar.rb +595 -0
  24. data/lib/vobject/vcalendar/paramcheck.rb +259 -0
  25. data/lib/vobject/vcalendar/propertyparent.rb +98 -0
  26. data/lib/vobject/vcalendar/propertyvalue.rb +606 -0
  27. data/lib/vobject/vcalendar/typegrammars.rb +605 -0
  28. data/lib/vobject/vcard/v3_0/component.rb +40 -0
  29. data/lib/vobject/vcard/v3_0/grammar.rb +175 -0
  30. data/lib/vobject/vcard/v3_0/paramcheck.rb +110 -0
  31. data/lib/vobject/vcard/v3_0/parameter.rb +17 -0
  32. data/lib/vobject/vcard/v3_0/property.rb +18 -0
  33. data/lib/vobject/vcard/v3_0/propertyvalue.rb +401 -0
  34. data/lib/vobject/vcard/v3_0/typegrammars.rb +425 -0
  35. data/lib/vobject/vcard/v4_0/component.rb +40 -0
  36. data/lib/vobject/vcard/v4_0/grammar.rb +224 -0
  37. data/lib/vobject/vcard/v4_0/paramcheck.rb +269 -0
  38. data/lib/vobject/vcard/v4_0/parameter.rb +18 -0
  39. data/lib/vobject/vcard/v4_0/property.rb +63 -0
  40. data/lib/vobject/vcard/v4_0/propertyvalue.rb +404 -0
  41. data/lib/vobject/vcard/v4_0/typegrammars.rb +539 -0
  42. data/lib/vobject/version.rb +1 -1
  43. data/vobject.gemspec +19 -16
  44. metadata +81 -26
  45. data/.travis.yml +0 -5
  46. data/README.md +0 -94
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in ruby-vobject.gemspec
4
4
  gemspec
@@ -1,21 +1,25 @@
1
- The MIT License (MIT)
1
+ BSD 2-Clause License
2
2
 
3
- Copyright (c) 2017 Peter Tam
3
+ Copyright (c) 2018, Ribose
4
+ All rights reserved.
4
5
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
11
8
 
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
14
11
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,151 @@
1
+ == Ruby vObject parser
2
+
3
+ image:https://img.shields.io/gem/v/ruby-vobject.svg["Gem Version", link="https://rubygems.org/gems/vobject"]
4
+ image:https://github.com/riboseinc/ruby-vobject/workflows/macos/badge.svg["Build Status (macOS)", link="https://github.com/riboseinc/ruby-vobject/actions?workflow=macos"]
5
+ image:https://github.com/riboseinc/ruby-vobject/workflows/ubuntu/badge.svg["Build Status (ubuntu)", link="https://github.com/riboseinc/ruby-vobject/actions?workflow=ubuntu"]
6
+ image:https://github.com/riboseinc/ruby-vobject/workflows/windows/badge.svg["Build Status (Windows)", link="https://github.com/riboseinc/ruby-vobject/actions?workflow=windows"]
7
+ image:https://codeclimate.com/github/riboseinc/ruby-vobject/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/riboseinc/ruby-vobject"]
8
+ image:https://img.shields.io/github/issues-pr-raw/riboseinc/ruby-vobject.svg["Pull Requests", link="https://github.com/riboseinc/ruby-vobject/pulls"]
9
+ image:https://img.shields.io/github/commits-since/riboseinc/ruby-vobject/latest.svg["Commits since latest",link="https://github.com/riboseinc/ruby-vobject/releases"]
10
+
11
+
12
+ The main purpose of the gem is to parse vobject formatted text into a ruby
13
+ hash format. Currently there are two possiblities of vobjects, namely
14
+ iCalendar (https://tools.ietf.org/html/rfc5545) and vCard
15
+ (https://tools.ietf.org/html/rfc6350). This gem parses iCalendar objects
16
+ and vCard objects in versions 3.0 and 4.0, together with any subsequent
17
+ additions to those specifications in other RFCs (see below).
18
+
19
+ A secondary purpose is to create a normalised form of Vobjects (iCalendars
20
+ and vCards version 4.0), which can be used to compare two Vobjects with minor
21
+ formatting differences
22
+
23
+ NOTE: This gem used to be named `ruby-vobject` (from versions 0.1.0 to 1.0.1),
24
+ but for clarity purposes it is now simply called `vobject` (from version 1.0.2
25
+ onwards).
26
+
27
+ == Installation
28
+
29
+ Add this line to your application's Gemfile:
30
+
31
+ [source,ruby]
32
+ ----
33
+ gem 'vobject'
34
+ ----
35
+
36
+ And then execute:
37
+
38
+ [source,console]
39
+ ----
40
+ $ bundle
41
+ ----
42
+
43
+ Or install it yourself as:
44
+
45
+ [source,console]
46
+ ----
47
+ $ gem install vobject
48
+ ----
49
+
50
+ == Usage
51
+
52
+ [source,ruby]
53
+ ----
54
+ require 'vcalendar'
55
+ require 'JSON'
56
+ require 'pp'
57
+
58
+ ics = File.read "spec/examples/vcalendar/timezones/America/Denver.ics"
59
+ # parse VCalendar into native object structure, with strict validation
60
+ # (raises exception on any deviation from the spec)
61
+ pp Vcalendar.parse(ics, true)
62
+ # parse VCalendar into native object structure, without strict validation
63
+ # (errors other than syntax errors are logged, but object still parses)
64
+ pp Vcalendar.parse(ics, false)
65
+ # list any errors
66
+ pp Vcalendar.parse(ics, false).get_errors
67
+ # convert VCalendar into Ruby hash
68
+ pp Vcalendar.parse(ics).to_hash
69
+ # convert VCalendar into JSON
70
+ pp JSON.parse(Vcalendar.parse(ics).to_json)
71
+ # convert VCalendar into VCalendar text
72
+ print Vcalendar.parse(ics).to_s
73
+ # convert VCalendar into normalised VCalendar text
74
+ print Vcalendar.parse(ics).to_norm
75
+ ----
76
+
77
+ [source,ruby]
78
+ ----
79
+ require 'vcard'
80
+ require 'JSON'
81
+ require 'pp'
82
+
83
+ vcf = File.read "spec/examples/vcard/vcard3.vcf"
84
+ # parse Vcard into native object structure (version 3), strict validation
85
+ pp Vcard.parse(vcf, '3.0', true)
86
+ # parse Vcard into Ruby hash
87
+ pp Vcard.parse(vcf, '3.0', true).to_hash
88
+ # parse Vcard into JSON
89
+ pp JSON.parse(Vcard.parse(vcf, '3.0', true).to_json)
90
+ # parse Vcard into VCard text
91
+ print Vcard.parse(vcf, '3.0', true).to_s
92
+ vcf = File.read "spec/examples/vcard/example61.vcf"
93
+ # parse Vcard into native object structure (version 4), lax validation
94
+ pp Vcard.parse(vcf, '4.0', false)
95
+ # list any errors
96
+ pp Vcard.parse(vcf, '4.0', false).get_errors
97
+ ----
98
+
99
+ * Recognises all of VCard v3.0, Vcard v4.0, and Vcalendar v2.0
100
+ * Components, properties, and parameters are all objects.
101
+ ** Each type of component is a distinct object.
102
+ * The parameters of a property are represented as an array of parameter objects.
103
+ * If a property has multiple values, given on separate lines, they are represented
104
+ as an array of value properties. Each value hash may have its own parameters.
105
+ * The values of properties are also typed objects.
106
+ * Objects can be parsed from text files.
107
+ * Objects can be populated from hashes of property value objects.
108
+ * Objects can be converted to Ruby hashes with native property value types (`.to_hash`), JSON objects with the same value types (`.to_json`), and round-tripped back to ICAL/VCARD string representations (`.to_s`).
109
+ * The normalised form of Vobjects (`.to_norm`) applies normalising conventions to the string representation; most notably presenting elements of a vCard in sorted order.
110
+ ** Normalisation follows the draft RFC `draft-calconnect-vobject-and-normalization`.
111
+ * Validation can be strict or lax.
112
+ ** If strict, an exception is raised on any syntax error, type mismatch, or other mismatch to the specification, such as mandatory elements.
113
+ ** If lax, an exception is still raised on syntax errors, but other issues are listed in an error field of the resulting object.
114
+ * Normalisation follows the draft RFC `draft-calconnect-vobject-and-normalization`.
115
+
116
+ Running spec:
117
+
118
+ [source,console]
119
+ ----
120
+ bundle exec rspec
121
+ ----
122
+
123
+ == Implementation
124
+
125
+ This gem is implemented using ttps://github.com/luikore/rsec[Rsec], a very fast PEG grammar based on StringScanner.
126
+
127
+ == Coverage
128
+
129
+ This tool is intended as a reference implementation, and it is very strict in its conformance: it requires all rules for parameter coocurrence,
130
+ property typing, parameter typing, permitted properties within components, etc to be met by objects.
131
+
132
+ The tool only parses one object at a time, and does not parse Vobject streams.
133
+
134
+ This tool supports v2.0 iCal as specified in RFC 5545, and as updated in RFC 5546 (registry for values of METHOD and REQUEST-STATUS),
135
+ RFC 6868 (caret escapes for parameter values), RFC 7529 (non-Gregorian Calendars), RFC 7953 (VAVAILABILITY component), and
136
+ RFC 7986 (new properties).
137
+
138
+ This tool supports v3.0 vCard as specified in RFC 2425 and RFC 2426, and as updated in RFC 2739 (calendar attributes) and RFC 4770 (extensions for Instant Messaging). It allows for the VCARD 2.1 style specification of PREF parameters in RFC 2739.
139
+
140
+ This tool supports v4.0 vCard as specified in RFC 6350, and as updated in RFC 6868 (parameter encoding), RFC 6474 (place of birth, place and date of death), RFC 6715 (OMA CAB extensions), and RF 6473 (KIND:application).
141
+
142
+
143
+ == Contributing
144
+
145
+ Bug reports and pull requests are welcome on GitHub at https://github.com/riboseinc/vobject. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the http://contributor-covenant.org[Contributor Covenant] code of conduct.
146
+
147
+
148
+ == License
149
+
150
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
151
+
data/Rakefile CHANGED
@@ -3,4 +3,4 @@ require "rspec/core/rake_task"
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
@@ -0,0 +1,173 @@
1
+ require "rsec"
2
+ require "set"
3
+ require "uri"
4
+ require_relative "vobject/vcalendar/propertyvalue"
5
+
6
+ module C
7
+ # definitions common to classes
8
+ SIGN = /[+-]/i.r
9
+ BOOLEAN = /TRUE/i.r.map { true } | /FALSE/i.r.map { false }
10
+ IANATOKEN = /[a-zA-Z\d\-]+/.r
11
+ vendorid_vcal = /[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]/.r
12
+ XNAME_VCAL = seq(/[xX]-/, vendorid_vcal, "-", IANATOKEN).map(&:join)
13
+ vendorid_vcard = /[a-zA-Z0-9]+/.r # different from iCal
14
+ XNAME_VCARD = seq(/[xX]-/, vendorid_vcard, "-", IANATOKEN).map(&:join)
15
+ TEXT = /([ \t\u0021\u0023-\u002b\u002d-\u0039\u003c-\u005b\u005d-\u007e\u0080-\u3ffff:"]|\\[nN;,\\])*/.r
16
+ TEXT3 = /([ \t\u0021\u0023-\u002b\u002d-\u0039\u003c-\u005b\u005d-\u007e\u0080-\u3ffff:"]|\\[nN;,\\]?)*/.r
17
+ TEXT4 = /([ \t\u0021\u0023-\u002b\u002d-\u005b\u005d-\u007e\u0080-\u3ffff:"]|\\[nN,\\])*/.r
18
+ COMPONENT4 = /([ \t\u0021\u0023-\u002b\u002d-\u003a\u003c-\u005b\u005d-\u007e\u0080-\u3ffff:"]|\\[nN,;\\])*/.r
19
+ DATE = seq(/[0-9]{4}/.r, /[0-9]{2}/.r, /[0-9]{2}/.r) do |yy, mm, dd|
20
+ Vobject::Vcalendar::PropertyValue::Date.new Time.utc(yy, mm, dd)
21
+ end
22
+ DATE_TIME = seq(/[0-9]{4}/.r, /[0-9]{2}/.r, /[0-9]{2}/.r << "T".r,
23
+ /[0-9]{2}/.r, /[0-9]{2}/.r, /[0-9]{2}/.r, /Z/i.r._?) do |yy, mm, dd, h, m, s, z|
24
+ if z.empty?
25
+ #Vobject::Vcalendar::PropertyValue::DateTimeLocal.new(time: Time.local(yy, mm, dd, h, m, s), zone: "")
26
+ Vobject::Vcalendar::PropertyValue::DateTimeLocal.new(year: yy, month: mm, day: dd, hour: h, min: m, sec: s, zone: "")
27
+ else
28
+ #Vobject::Vcalendar::PropertyValue::DateTimeUTC.new(time: Time.utc(yy, mm, dd, h, m, s), zone: "Z")
29
+ Vobject::Vcalendar::PropertyValue::DateTimeUTC.new(year: yy, month: mm, day: dd, hour: h, min: m, sec: s, zone: "Z")
30
+ end
31
+ end
32
+ DATE_TIME_UTC = seq(/[0-9]{4}/.r, /[0-9]{2}/.r, /[0-9]{2}/.r << "T".r,
33
+ /[0-9]{2}/.r, /[0-9]{2}/.r, /[0-9]{2}/.r, /Z/i.r._?) do |yy, mm, dd, h, m, s, _z|
34
+ #Vobject::Vcalendar::PropertyValue::DateTimeUTC.new(time: Time.utc(yy, mm, dd, h, m, s), zone: "Z")
35
+ Vobject::Vcalendar::PropertyValue::DateTimeUTC.new(year: yy, month: mm, day: dd, hour: h, min: m, sec: s, zone: "Z")
36
+ end
37
+ TIME = seq(/[0-9]{2}/.r, /[0-9]{2}/.r, /[0-9]{2}/.r, /Z/i.r._?) do |h, m, s, z|
38
+ hash = { hour: h, min: m, sec: s }
39
+ hash[:utc] = not(z.empty?)
40
+ hash
41
+ end
42
+ ICALPROPNAMES = /BEGIN/i.r | /END/i.r | /CALSCALE/i.r | /METHOD/i.r | /VERSION/i.r |
43
+ /ATTACH/i.r | /IMAGE/i.r | /CATEGORIES/i.r | /RESOURCERS/i.r | /CLASS/i.r |
44
+ /COMMENT/i.r | /DESCRIPTION/i.r | /LOCATION/i.r | /SUMMARY/i.r | /TZID/i.r |
45
+ /TZNAME/i.r | /CONTACT/i.r | /RELATED-TO/i.r | /UID/i.r | /PRODID/i.r | /NAME/i.r |
46
+ /GEO/i.r | /PERCENT-COMPLETE/i.r | /PRIORITY/i.r | /STATUS/i.r | /COMPLETED/i.r |
47
+ /CREATEED/i.r | /DTSTAMP/i.r | /LAST-MODIFIED/i.r | /DTEND/i.r | /DTSTART/i.r |
48
+ /DUE/i.r | /RECURRENCE-ID/i.r | /EXDATE/i.r | /RDATE/i.r | /TRIGGER/i.r |
49
+ /FREEBUSY/i.r | /TRANSP/i.r | /TZOFFSETFROM/i.r | /TZOFFSETTO/i.r |
50
+ /TZURI/i.r | /URL/i.r | /SOURCE/i.r | /CONFERENCE/i.r | /ATTENDEE/i.r |
51
+ /ORGANIZER/i.r | /RRULE/i.r | /ACTION/i.r | /REPEAT/i.r | /SEQUENCE/i.r |
52
+ /REQUEST-STATUS/i.r | /BUSYTYPE/i.r | /REFRESH-INTERVAL/i.r | /COLOR/i.r
53
+ VCARD3PROPNAMES = /BEGIN/i.r | /END/i.r | /SOURCE/i.r | /NAME/i.r | /PROFILE/i.r |
54
+ /VERSION/i.r | /URL/i.r | /FN/i.r | /NICKNAME/i.r | /LABEL/i.r | /EMAIL/i.r |
55
+ /MAILER/i.r | /TITLE/i.r | /ROLE/i.r | /NOTE/i.r | /PRODID/.r | /SORT-STRING/i.r |
56
+ /UID/i.r | /CLASS/i.r | /ORG/i.r | /CATEGORIES/i.r | /N/i.r | /PHOTO/i.r |
57
+ /LOGO/i.r | /SOUND/i.r | /KEY/i.r | /BDAY/i.r | /REV/i.r | /ADR/i.r |
58
+ /TEL/i.r | /TZ/i.r | /GEO/i.r | /AGENT/i.r | /IMPP/i.r |
59
+ /FBURL/i.r | /CALADRURI/i.r | /CALURI/i.r | /CAPURI/i.r
60
+ VCARD4PROPNAMES = /SOURCE/i.r | /KIND/i.r | /FN/i.r | /NICKNAME/i.r | /NOTE/i.r | /N/i.r |
61
+ /PHOTO/i.r | /BDAY/i.r | /ANNIVERSARY/i.r | /GENDER/i.r | /ADR/i.r |
62
+ /TEL/i.r | /EMAIL/i.r | /IMPP/i.r | /LANG/i.r | /TZ/i.r |
63
+ /GEO/i.r | /TITLE/i.r | /ROLE/i.r | /LOGO/i.r | /ORG/i.r |
64
+ /MEMBER/i.r | /RELATED/i.r | /CATEGORIES/i.r | /PRODID/i.r |
65
+ /REV/i.r | /SOUND/i.r | /UID/i.r | /CLIENTPIDMAP/i.r | /URL/i.r |
66
+ /KEY/i.r | /FBURL/i.r | /CALADRURI/i.r | /CALURI/i.r | /XML/i.r |
67
+ /BIRTHPLACE/i.r | /DEATHPLACE/i.r | /DEATHDATE/i.r | /EXPERTISE/i.r |
68
+ /HOBBY/i.r | /INTEREST/i.r | /ORG-DIRECTORY/i.r |
69
+ beginend = /BEGIN/i.r | /END/i.r
70
+ NAME_VCAL = C::XNAME_VCAL | seq("".r ^ beginend, C::IANATOKEN)[1]
71
+ NAME_VCARD = C::XNAME_VCARD | seq("".r ^ beginend, C::IANATOKEN)[1]
72
+ durday = seq(/[0-9]+/.r, "D") { |d, _| { days: d.to_i } }
73
+ dursecond = seq(/[0-9]+/.r, "S") { |d, _| { seconds: d.to_i } }
74
+ durminute = seq(/[0-9]+/.r, "M", dursecond._?) do |d, _, s|
75
+ hash = { minutes: d.to_i }
76
+ hash = hash.merge s[0] unless s.empty?
77
+ hash
78
+ end
79
+ durhour = seq(/[0-9]+/.r, "H", durminute._?) do |d, _, m|
80
+ hash = { hours: d.to_i }
81
+ hash = hash.merge m[0] unless m.empty?
82
+ hash
83
+ end
84
+ durweek = seq(/[0-9]+/.r, "W") { |d, _| { weeks: d.to_i } }
85
+ durtime1 = durhour | durminute | dursecond
86
+ durtime = seq("T", durtime1) { |_, d| d }
87
+ durdate = seq(durday, durtime._?) do |d, t|
88
+ d = d.merge t[0] unless t.empty?
89
+ d
90
+ end
91
+ duration1 = durdate | durtime | durweek
92
+ DURATION = seq(SIGN._?, "P", duration1) do |s, _, d|
93
+ d[:sign] = s[0] unless s.empty?
94
+ d
95
+ end
96
+
97
+ non_ascii = /[\u0080-\u3ffff]/
98
+ wsp = /[ \t]/.r
99
+ q_safe_char_vcal = wsp | /[\u0021\u0023-\u007e]/ | non_ascii
100
+ safe_char_vcal = wsp | /[\u0021\u0023-\u0039\u003c-\u007e]/ | non_ascii
101
+ q_safe_char_vcard = wsp | /[!\u0023-\u007e]/ | non_ascii
102
+ safe_char_vcard = wsp | /[!\u0023-\u0039\u003c-\u007e]/ | non_ascii
103
+ v_char = /[\u0021-\u007e]/.r
104
+ value_char = wsp | v_char | non_ascii
105
+
106
+ QUOTEDSTRING_VCAL = seq(/"/.r >> q_safe_char_vcal.star <<
107
+ /"/.r) { |q| q.join("") }
108
+ PTEXT_VCAL = safe_char_vcal.star.map(&:join)
109
+ QUOTEDSTRING_VCARD = seq(/"/.r >> q_safe_char_vcard.star <<
110
+ /"/.r) { |q| q.join("") }
111
+ PTEXT_VCARD = safe_char_vcard.star.map(&:join)
112
+ VALUE = value_char.star.map(&:join)
113
+
114
+ rfc5646irregular = /en-GB-oed/i.r | /i-ami/i.r | /i-bnn/i.r | /i-default/i.r | /i-enochian/i.r |
115
+ /i-hak/i.r | /i-klingon/i.r | /i-lux/i.r | /i-mingo/i.r |
116
+ /i-navajo/i.r | /i-pwn/i.r | /i-tao/i.r | /i-tay/i.r |
117
+ /i-tsu/i.r | /sgn-BE-FR/i.r | /sgn-BE-NL/i.r | /sgn-CH-DE/i.r
118
+ rfc5646regular = /art-lojban/i.r | /cel-gaulish/i.r | /no-bok/i.r | /no-nyn/i.r |
119
+ /zh-guoyu/i.r | /zh-hakka/i.r | /zh-min/i.r | /zh-min-nan/i.r |
120
+ /zh-xiang/i.r
121
+ rfc5646grandfathered = rfc5646irregular | rfc5646regular
122
+ rfc5646privateuse1 = seq("-", /[0-9A-Za-z]{1,8}/.r)
123
+ rfc5646privateuse = seq("x", rfc5646privateuse1 * (1..-1))
124
+ rfc5646extension1 = seq("-", /[0-9A-Za-z]{2,8}/.r)
125
+ rfc5646extension = seq("-", /[0-9][A-WY-Za-wy-z]/.r, rfc5646extension1 * (1..-1))
126
+ rfc5646variant = seq("-", /[A-Za-z]{5,8}/.r) | seq("-", /[0-9][A-Za-z0-9]{3}/)
127
+ rfc5646region = seq("-", /[A-Za-z]{2}/.r) | seq("-", /[0-9]{3}/)
128
+ rfc5646script = seq("-", /[A-Za-z]{4}/.r)
129
+ rfc5646extlang = seq(/[A-Za-z]{3}/.r, /[A-Za-z]{3}/.r._?, /[A-Za-z]{3}/.r._?)
130
+ rfc5646language = seq(/[A-Za-z]{2,3}/.r, rfc5646extlang._?) | /[A-Za-z]{4}/.r | /[A-Za-z]{5,8}/.r
131
+ rfc5646langtag = seq(rfc5646language, rfc5646script._?, rfc5646region._?,
132
+ rfc5646variant.star, rfc5646extension.star, rfc5646privateuse._?) do |a, b, c, d, e, f|
133
+ [a, b, c, d, e, f].flatten.join("")
134
+ end
135
+ RFC5646LANGVALUE = rfc5646langtag | rfc5646privateuse | rfc5646grandfathered
136
+
137
+ # https://www.w3.org/TR/2011/REC-css3-color-20110607/#svg-color
138
+ COLOR = /AliceBlue/i.r | /AntiqueWhite/i.r | /Aqua/i.r | /Aquamarine/i.r | /Azure/i.r | /Beige/i.r |
139
+ /Bisque/i.r | /Black/i.r | /BlanchedAlmond/i.r | /Blue/i.r | /BlueViolet/i.r | /Brown/i.r |
140
+ /BurlyWood/i.r | /CadetBlue/i.r | /Chartreuse/i.r | /Chocolate/i.r | /Coral/i.r |
141
+ /CornflowerBlue/i.r | /Cornsilk/i.r | /Crimson/i.r | /Cyan/i.r | /DarkBlue/i.r |
142
+ /DarkCyan/i.r | /DarkGoldenRod/i.r | /DarkGray/i.r | /DarkGrey/i.r | /DarkGreen/i.r |
143
+ /DarkKhaki/i.r | /DarkMagenta/i.r | /DarkOliveGreen/i.r | /DarkOrange/i.r | /DarkOrchid/i.r |
144
+ /DarkRed/i.r | /DarkSalmon/i.r | /DarkSeaGreen/i.r | /DarkSlateBlue/i.r | /DarkSlateGray/i.r |
145
+ /DarkSlateGrey/i.r | /DarkTurquoise/i.r | /DarkViolet/i.r | /DeepPink/i.r | /DeepSkyBlue/i.r |
146
+ /DimGray/i.r | /DimGrey/i.r | /DodgerBlue/i.r | /FireBrick/i.r | /FloralWhite/i.r | /ForestGreen/i.r |
147
+ /Fuchsia/i.r | /Gainsboro/i.r | /GhostWhite/i.r | /Gold/i.r | /GoldenRod/i.r | /Gray/i.r | /Grey/i.r |
148
+ /Green/i.r | /GreenYellow/i.r | /HoneyDew/i.r | /HotPink/i.r | /IndianRed/i.r | /Indigo/i.r |
149
+ /Ivory/i.r | /Khaki/i.r | /Lavender/i.r | /LavenderBlush/i.r | /LawnGreen/i.r | /LemonChiffon/i.r |
150
+ /LightBlue/i.r | /LightCoral/i.r | /LightCyan/i.r | /LightGoldenRodYellow/i.r | /LightGray/i.r |
151
+ /LightGrey/i.r | /LightGreen/i.r | /LightPink/i.r | /LightSalmon/i.r | /LightSeaGreen/i.r |
152
+ /LightSkyBlue/i.r | /LightSlateGray/i.r | /LightSlateGrey/i.r | /LightSteelBlue/i.r |
153
+ /LightYellow/i.r | /Lime/i.r | /LimeGreen/i.r | /Linen/i.r | /Magenta/i.r | /Maroon/i.r |
154
+ /MediumAquaMarine/i.r | /MediumBlue/i.r | /MediumOrchid/i.r | /MediumPurple/i.r |
155
+ /MediumSeaGreen/i.r | /MediumSlateBlue/i.r | /MediumSpringGreen/i.r | /MediumTurquoise/i.r |
156
+ /MediumVioletRed/i.r | /MidnightBlue/i.r | /MintCream/i.r | /MistyRose/i.r | /Moccasin/i.r |
157
+ /NavajoWhite/i.r | /Navy/i.r | /OldLace/i.r | /Olive/i.r | /OliveDrab/i.r | /Orange/i.r |
158
+ /OrangeRed/i.r | /Orchid/i.r | /PaleGoldenRod/i.r | /PaleGreen/i.r | /PaleTurquoise/i.r |
159
+ /PaleVioletRed/i.r | /PapayaWhip/i.r | /PeachPuff/i.r | /Peru/i.r | /Pink/i.r | /Plum/i.r |
160
+ /PowderBlue/i.r | /Purple/i.r | /RebeccaPurple/i.r | /Red/i.r | /RosyBrown/i.r | /RoyalBlue/i.r |
161
+ /SaddleBrown/i.r | /Salmon/i.r | /SandyBrown/i.r | /SeaGreen/i.r | /SeaShell/i.r | /Sienna/i.r |
162
+ /Silver/i.r | /SkyBlue/i.r | /SlateBlue/i.r | /SlateGray/i.r | /SlateGrey/i.r | /Snow/i.r |
163
+ /SpringGreen/i.r | /SteelBlue/i.r | /Tan/i.r | /Teal/i.r | /Thistle/i.r | /Tomato/i.r |
164
+ /Turquoise/i.r | /Violet/i.r | /Wheat/i.r | /White/i.r | /WhiteSmoke/i.r | /Yellow/i.r | /YellowGreen/i.r
165
+
166
+ UTC_OFFSET = seq(C::SIGN, /[0-9]{2}/.r, /[0-9]{2}/.r, /[0-9]{2}/.r._?) do |s, h, m, z|
167
+ h = { sign: s, hour: h, min: m }
168
+ h[:sec] = z[0] unless z.empty?
169
+ h
170
+ end
171
+ ZONE = UTC_OFFSET.map { |u| u } |
172
+ /Z/i.r.map { "Z" }
173
+ end
@@ -0,0 +1,19 @@
1
+ # expand error reporting of Rsec
2
+ class Rsec::ParseContext
3
+ def report_error(msg, source)
4
+ if pos <= @last_fail_pos
5
+ line = line @last_fail_pos
6
+ col = col @last_fail_pos
7
+ line_text = line_text @last_fail_pos
8
+ expect_tokens = Rsec::Fail.get_tokens @last_fail_mask
9
+ expects = ", expect token [ #{expect_tokens.join ' | '} ]"
10
+ else
11
+ line = line pos
12
+ col = col pos
13
+ line_text = line_text pos
14
+ expects = nil
15
+ end
16
+ msg = "#{msg}\nin #{source}:#{line} at #{col}#{expects}"
17
+ Rsec::SyntaxError.new msg, line_text, line, col
18
+ end
19
+ end
@@ -0,0 +1,77 @@
1
+ require "vobject"
2
+ require "vobject/component"
3
+ require "vobject/vcalendar/component"
4
+ require "vobject/vcalendar/grammar"
5
+ require "json"
6
+
7
+ class Vcalendar < Vobject::Component
8
+ attr_accessor :comp_name, :children, :version
9
+
10
+ class << self
11
+ def parse(vcf, strict)
12
+ Vobject::Component::Vcalendar.parse(vcf, strict)
13
+ end
14
+ end
15
+
16
+ def initialize(key, cs, err)
17
+ super key, cs, err
18
+ end
19
+
20
+ def child_class(key, val)
21
+ base_class = if key == :VTODO
22
+ Vobject::Component::Vcalendar::ToDo
23
+ elsif key == :VFREEBUSY
24
+ Vobject::Component::Vcalendar::FreeBusy
25
+ elsif key == :JOURNAL
26
+ Vobject::Component::Vcalendar::Journal
27
+ elsif key == :STANDARD
28
+ Vobject::Component::Vcalendar::Timezone::Standard
29
+ elsif key == :DAYLIGHT
30
+ Vobject::Component::Vcalendar::Timezone::Daylight
31
+ elsif key == :VTIMEZONE
32
+ Vobject::Component::Vcalendar::Timezone
33
+ elsif key == :VEVENT
34
+ Vobject::Component::Vcalendar::Event
35
+ elsif key == :VALARM
36
+ Vobject::Component::Vcalendar::Alarm
37
+ elsif key == :VAVAILABILITY
38
+ Vobject::Component::Vcalendar::Vavailability
39
+ elsif key == :AVAILABLE
40
+ Vobject::Component::Vcalendar::Vavailability::Available
41
+ elsif !(val.is_a?(Hash) && !val.has_key?(:value))
42
+ property_base_class
43
+ else
44
+ Vobject::Component::Vcalendar
45
+ end
46
+ return base_class if [:CLASS, :OBJECT, :METHOD].include?
47
+ camelized_key = key.to_s.downcase.split("_").map(&:capitalize).join("")
48
+ base_class.const_get(camelized_key) rescue base_class
49
+ end
50
+
51
+ private
52
+
53
+ def raise_invalid_parsing
54
+ raise "Vobject component parse failed"
55
+ end
56
+ end
57
+
58
+ class Vobject::Component::Vcalendar::ToDo < Vobject::Component::Vcalendar
59
+ end
60
+ class Vobject::Component::Vcalendar::Freebusy < Vobject::Component::Vcalendar
61
+ end
62
+ class Vobject::Component::Vcalendar::Journal < Vobject::Component::Vcalendar
63
+ end
64
+ class Vobject::Component::Vcalendar::Timezone < Vobject::Component::Vcalendar
65
+ end
66
+ class Vobject::Component::Vcalendar::Timezone::Standard < Vobject::Component::Vcalendar::Timezone
67
+ end
68
+ class Vobject::Component::Vcalendar::Timezone::Daylight < Vobject::Component::Vcalendar::Timezone
69
+ end
70
+ class Vobject::Component::Vcalendar::Event < Vobject::Component::Vcalendar
71
+ end
72
+ class Vobject::Component::Vcalendar::Alarm < Vobject::Component::Vcalendar
73
+ end
74
+ class Vobject::Component::Vcalendar::Vavailability < Vobject::Component::Vcalendar
75
+ end
76
+ # class Vobject::Component::Vcalendar::Vavailability::Available < Vobject::Component::Vcalendar::Vavailability
77
+ # end