tilia-vobject 4.0.0.pre.alpha2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +32 -0
- data/.simplecov +4 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.sabre.md +626 -0
- data/CONTRIBUTING.md +25 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +68 -0
- data/LICENSE +27 -0
- data/LICENSE.sabre +27 -0
- data/README.md +63 -0
- data/Rakefile +17 -0
- data/bin/vobject +7 -0
- data/lib/tilia/v_object/birthday_calendar_generator.rb +142 -0
- data/lib/tilia/v_object/cli.rb +582 -0
- data/lib/tilia/v_object/component/available.rb +107 -0
- data/lib/tilia/v_object/component/v_alarm.rb +114 -0
- data/lib/tilia/v_object/component/v_availability.rb +128 -0
- data/lib/tilia/v_object/component/v_calendar.rb +468 -0
- data/lib/tilia/v_object/component/v_card.rb +457 -0
- data/lib/tilia/v_object/component/v_event.rb +127 -0
- data/lib/tilia/v_object/component/v_free_busy.rb +81 -0
- data/lib/tilia/v_object/component/v_journal.rb +75 -0
- data/lib/tilia/v_object/component/v_time_zone.rb +51 -0
- data/lib/tilia/v_object/component/v_todo.rb +147 -0
- data/lib/tilia/v_object/component.rb +591 -0
- data/lib/tilia/v_object/date_time_parser.rb +486 -0
- data/lib/tilia/v_object/document.rb +218 -0
- data/lib/tilia/v_object/element_list.rb +18 -0
- data/lib/tilia/v_object/eof_exception.rb +8 -0
- data/lib/tilia/v_object/free_busy_data.rb +149 -0
- data/lib/tilia/v_object/free_busy_generator.rb +465 -0
- data/lib/tilia/v_object/i_tip/broker.rb +909 -0
- data/lib/tilia/v_object/i_tip/i_tip_exception.rb +9 -0
- data/lib/tilia/v_object/i_tip/message.rb +109 -0
- data/lib/tilia/v_object/i_tip/same_organizer_for_all_components_exception.rb +13 -0
- data/lib/tilia/v_object/i_tip.rb +10 -0
- data/lib/tilia/v_object/node.rb +192 -0
- data/lib/tilia/v_object/parameter.rb +327 -0
- data/lib/tilia/v_object/parse_exception.rb +7 -0
- data/lib/tilia/v_object/parser/json.rb +149 -0
- data/lib/tilia/v_object/parser/mime_dir.rb +543 -0
- data/lib/tilia/v_object/parser/parser.rb +61 -0
- data/lib/tilia/v_object/parser/xml/element/key_value.rb +60 -0
- data/lib/tilia/v_object/parser/xml/element.rb +11 -0
- data/lib/tilia/v_object/parser/xml.rb +322 -0
- data/lib/tilia/v_object/parser.rb +10 -0
- data/lib/tilia/v_object/property/binary.rb +96 -0
- data/lib/tilia/v_object/property/boolean.rb +57 -0
- data/lib/tilia/v_object/property/flat_text.rb +52 -0
- data/lib/tilia/v_object/property/float_value.rb +107 -0
- data/lib/tilia/v_object/property/i_calendar/cal_address.rb +49 -0
- data/lib/tilia/v_object/property/i_calendar/date.rb +15 -0
- data/lib/tilia/v_object/property/i_calendar/date_time.rb +330 -0
- data/lib/tilia/v_object/property/i_calendar/duration.rb +65 -0
- data/lib/tilia/v_object/property/i_calendar/period.rb +124 -0
- data/lib/tilia/v_object/property/i_calendar/recur.rb +173 -0
- data/lib/tilia/v_object/property/i_calendar.rb +14 -0
- data/lib/tilia/v_object/property/integer_value.rb +60 -0
- data/lib/tilia/v_object/property/text.rb +352 -0
- data/lib/tilia/v_object/property/time.rb +85 -0
- data/lib/tilia/v_object/property/unknown.rb +30 -0
- data/lib/tilia/v_object/property/uri.rb +78 -0
- data/lib/tilia/v_object/property/utc_offset.rb +56 -0
- data/lib/tilia/v_object/property/v_card/date.rb +31 -0
- data/lib/tilia/v_object/property/v_card/date_and_or_time.rb +343 -0
- data/lib/tilia/v_object/property/v_card/date_time.rb +22 -0
- data/lib/tilia/v_object/property/v_card/language_tag.rb +41 -0
- data/lib/tilia/v_object/property/v_card/time_stamp.rb +74 -0
- data/lib/tilia/v_object/property/v_card.rb +13 -0
- data/lib/tilia/v_object/property.rb +532 -0
- data/lib/tilia/v_object/reader.rb +73 -0
- data/lib/tilia/v_object/recur/event_iterator.rb +417 -0
- data/lib/tilia/v_object/recur/no_instances_exception.rb +11 -0
- data/lib/tilia/v_object/recur/r_date_iterator.rb +138 -0
- data/lib/tilia/v_object/recur/r_rule_iterator.rb +717 -0
- data/lib/tilia/v_object/recur.rb +10 -0
- data/lib/tilia/v_object/settings.rb +32 -0
- data/lib/tilia/v_object/splitter/i_calendar.rb +95 -0
- data/lib/tilia/v_object/splitter/splitter_interface.rb +31 -0
- data/lib/tilia/v_object/splitter/v_card.rb +56 -0
- data/lib/tilia/v_object/splitter.rb +9 -0
- data/lib/tilia/v_object/string_util.rb +58 -0
- data/lib/tilia/v_object/time_zone_data/exchange_zones.rb +96 -0
- data/lib/tilia/v_object/time_zone_data/lotus_zones.rb +104 -0
- data/lib/tilia/v_object/time_zone_data/php_zones.rb +49 -0
- data/lib/tilia/v_object/time_zone_data/windows_zones.rb +121 -0
- data/lib/tilia/v_object/time_zone_data.rb +10 -0
- data/lib/tilia/v_object/time_zone_util.rb +213 -0
- data/lib/tilia/v_object/uuid_util.rb +51 -0
- data/lib/tilia/v_object/v_card_converter.rb +354 -0
- data/lib/tilia/v_object/version.rb +9 -0
- data/lib/tilia/v_object/writer.rb +56 -0
- data/lib/tilia/v_object.rb +45 -0
- data/lib/tilia/vobject.rb +1 -0
- data/resources/schema/xcal.rng +1192 -0
- data/resources/schema/xcard.rng +388 -0
- data/test/test_helper.rb +56 -0
- data/test/v_object/attach_issue_test.rb +19 -0
- data/test/v_object/birthday_calendar_generator_test.rb +463 -0
- data/test/v_object/cli_mock.rb +19 -0
- data/test/v_object/cli_test.rb +460 -0
- data/test/v_object/component/available_test.rb +59 -0
- data/test/v_object/component/v_alarm_test.rb +160 -0
- data/test/v_object/component/v_availability_test.rb +388 -0
- data/test/v_object/component/v_calendar_test.rb +646 -0
- data/test/v_object/component/v_card_test.rb +258 -0
- data/test/v_object/component/v_event_test.rb +85 -0
- data/test/v_object/component/v_free_busy_test.rb +59 -0
- data/test/v_object/component/v_journal_test.rb +85 -0
- data/test/v_object/component/v_time_zone_test.rb +47 -0
- data/test/v_object/component/v_todo_test.rb +172 -0
- data/test/v_object/component_test.rb +419 -0
- data/test/v_object/date_time_parser_test.rb +526 -0
- data/test/v_object/document_test.rb +71 -0
- data/test/v_object/element_list_test.rb +27 -0
- data/test/v_object/em_client_test.rb +53 -0
- data/test/v_object/empty_parameter_test.rb +65 -0
- data/test/v_object/empty_value_issue_test.rb +25 -0
- data/test/v_object/fake_component.rb +21 -0
- data/test/v_object/free_busy_data_test.rb +285 -0
- data/test/v_object/free_busy_generator_test.rb +637 -0
- data/test/v_object/google_colon_escaping_test.rb +27 -0
- data/test/v_object/i_calendar/attach_parse_test.rb +24 -0
- data/test/v_object/i_tip/broker_attendee_reply_test.rb +1042 -0
- data/test/v_object/i_tip/broker_delete_event_test.rb +175 -0
- data/test/v_object/i_tip/broker_new_event_test.rb +440 -0
- data/test/v_object/i_tip/broker_process_message_test.rb +153 -0
- data/test/v_object/i_tip/broker_process_reply_test.rb +402 -0
- data/test/v_object/i_tip/broker_tester.rb +71 -0
- data/test/v_object/i_tip/broker_update_event_test.rb +763 -0
- data/test/v_object/i_tip/evolution_test.rb +2644 -0
- data/test/v_object/i_tip/message_test.rb +25 -0
- data/test/v_object/issue153.vcf +352 -0
- data/test/v_object/issue153_test.rb +12 -0
- data/test/v_object/issue26_test.rb +25 -0
- data/test/v_object/issue36_work_around_test.rb +37 -0
- data/test/v_object/issue40_test.rb +26 -0
- data/test/v_object/issue64.vcf +351 -0
- data/test/v_object/issue64_test.rb +17 -0
- data/test/v_object/issue96_test.rb +22 -0
- data/test/v_object/issue_undefined_index_test.rb +24 -0
- data/test/v_object/j_cal_test.rb +150 -0
- data/test/v_object/j_card_test.rb +192 -0
- data/test/v_object/line_folding_issue_test.rb +19 -0
- data/test/v_object/mock_document.rb +6 -0
- data/test/v_object/parameter_test.rb +109 -0
- data/test/v_object/parser/json_test.rb +370 -0
- data/test/v_object/parser/mime_dir_test.rb +14 -0
- data/test/v_object/parser/quoted_printable_test.rb +78 -0
- data/test/v_object/parser/xml_test.rb +2563 -0
- data/test/v_object/property/binary_test.rb +12 -0
- data/test/v_object/property/boolean_test.rb +18 -0
- data/test/v_object/property/compound_test.rb +43 -0
- data/test/v_object/property/float_test.rb +20 -0
- data/test/v_object/property/i_calendar/cal_address_test.rb +26 -0
- data/test/v_object/property/i_calendar/date_time_test.rb +303 -0
- data/test/v_object/property/i_calendar/duration_test.rb +14 -0
- data/test/v_object/property/i_calendar/recur_test.rb +39 -0
- data/test/v_object/property/text_test.rb +81 -0
- data/test/v_object/property/v_card/date_and_or_time_test.rb +205 -0
- data/test/v_object/property/v_card/language_tag_test.rb +35 -0
- data/test/v_object/property_test.rb +338 -0
- data/test/v_object/reader_test.rb +403 -0
- data/test/v_object/recur/event_iterator/by_month_in_daily_test.rb +52 -0
- data/test/v_object/recur/event_iterator/by_set_pos_hang_test.rb +55 -0
- data/test/v_object/recur/event_iterator/expand_floating_times_test.rb +109 -0
- data/test/v_object/recur/event_iterator/fifth_tuesday_problem_test.rb +45 -0
- data/test/v_object/recur/event_iterator/incorrect_expand_test.rb +53 -0
- data/test/v_object/recur/event_iterator/infinite_loop_problem_test.rb +75 -0
- data/test/v_object/recur/event_iterator/issue48_test.rb +43 -0
- data/test/v_object/recur/event_iterator/issue50_test.rb +123 -0
- data/test/v_object/recur/event_iterator/main_test.rb +1222 -0
- data/test/v_object/recur/event_iterator/missing_overridden_test.rb +55 -0
- data/test/v_object/recur/event_iterator/no_instances_test.rb +32 -0
- data/test/v_object/recur/event_iterator/override_first_event_test.rb +106 -0
- data/test/v_object/recur/r_date_iterator_test.rb +44 -0
- data/test/v_object/recur/r_rule_iterator_test.rb +608 -0
- data/test/v_object/recurrence_iterator/UntilRespectsTimezoneTest.ics +39 -0
- data/test/v_object/slash_r_test.rb +15 -0
- data/test/v_object/splitter/i_calendar_test.rb +299 -0
- data/test/v_object/splitter/v_card_test.rb +173 -0
- data/test/v_object/string_util_test.rb +37 -0
- data/test/v_object/test_case.rb +42 -0
- data/test/v_object/time_zone_util_test.rb +271 -0
- data/test/v_object/uuid_util_test.rb +18 -0
- data/test/v_object/v_card21_test.rb +43 -0
- data/test/v_object/v_card_converter_test.rb +419 -0
- data/test/v_object/version_test.rb +15 -0
- data/test/v_object/writer_test.rb +33 -0
- data/tilia-vobject.gemspec +17 -0
- metadata +308 -0
@@ -0,0 +1,354 @@
|
|
1
|
+
require 'base64'
|
2
|
+
module Tilia
|
3
|
+
module VObject
|
4
|
+
# This utility converts vcards from one version to another.
|
5
|
+
class VCardConverter
|
6
|
+
# Converts a vCard object to a new version.
|
7
|
+
#
|
8
|
+
# targetVersion must be one of:
|
9
|
+
# Document::VCARD21
|
10
|
+
# Document::VCARD30
|
11
|
+
# Document::VCARD40
|
12
|
+
#
|
13
|
+
# Currently only 3.0 and 4.0 as input and output versions.
|
14
|
+
#
|
15
|
+
# 2.1 has some minor support for the input version, it's incomplete at the
|
16
|
+
# moment though.
|
17
|
+
#
|
18
|
+
# If input and output version are identical, a clone is returned.
|
19
|
+
#
|
20
|
+
# @param Component\VCard input
|
21
|
+
# @param int target_version
|
22
|
+
def convert(input, target_version)
|
23
|
+
input_version = input.document_type
|
24
|
+
return input.dup if input_version == target_version
|
25
|
+
|
26
|
+
unless [Tilia::VObject::Document::VCARD21, Tilia::VObject::Document::VCARD30, Tilia::VObject::Document::VCARD40].include? input_version
|
27
|
+
fail ArgumentError, 'Only vCard 2.1, 3.0 and 4.0 are supported for the input data'
|
28
|
+
end
|
29
|
+
unless [Tilia::VObject::Document::VCARD30, Tilia::VObject::Document::VCARD40].include? target_version
|
30
|
+
fail ArgumentError, 'You can only use vCard 3.0 or 4.0 for the target version'
|
31
|
+
end
|
32
|
+
|
33
|
+
new_version = target_version == Tilia::VObject::Document::VCARD40 ? '4.0' : '3.0'
|
34
|
+
|
35
|
+
output = Tilia::VObject::Component::VCard.new('VERSION' => new_version)
|
36
|
+
|
37
|
+
input.children.each do |property|
|
38
|
+
convert_property(input, output, property, target_version)
|
39
|
+
end
|
40
|
+
|
41
|
+
output
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
# Handles conversion of a single property.
|
47
|
+
#
|
48
|
+
# @param Component\VCard input
|
49
|
+
# @param Component\VCard output
|
50
|
+
# @param Property property
|
51
|
+
# @param int target_version
|
52
|
+
#
|
53
|
+
# @return void
|
54
|
+
def convert_property(input, output, property, target_version)
|
55
|
+
# Skipping these, those are automatically added.
|
56
|
+
return nil if %w(VERSION PRODID).include?(property.name)
|
57
|
+
|
58
|
+
parameters = property.parameters
|
59
|
+
value_type = nil
|
60
|
+
if parameters.key?('VALUE')
|
61
|
+
value_type = parameters['VALUE'].value
|
62
|
+
parameters.delete('VALUE')
|
63
|
+
end
|
64
|
+
|
65
|
+
value_type = property.value_type unless value_type
|
66
|
+
|
67
|
+
new_property = output.create_property(
|
68
|
+
property.name,
|
69
|
+
property.parts,
|
70
|
+
{}, # parameters will get added a bit later.
|
71
|
+
value_type
|
72
|
+
)
|
73
|
+
|
74
|
+
if target_version == Tilia::VObject::Document::VCARD30
|
75
|
+
if property.is_a?(Tilia::VObject::Property::Uri) && %w(PHOTO LOGO SOUND).include?(property.name)
|
76
|
+
new_property = convert_uri_to_binary(output, new_property)
|
77
|
+
elsif property.is_a? Tilia::VObject::Property::VCard::DateAndOrTime
|
78
|
+
# In vCard 4, the birth year may be optional. This is not the
|
79
|
+
# case for vCard 3. Apple has a workaround for this that
|
80
|
+
# allows applications that support Apple's extension still
|
81
|
+
# omit birthyears in vCard 3, but applications that do not
|
82
|
+
# support this, will just use a random birthyear. We're
|
83
|
+
# choosing 1604 for the birthyear, because that's what apple
|
84
|
+
# uses.
|
85
|
+
parts = Tilia::VObject::DateTimeParser.parse_v_card_date_time(property.value)
|
86
|
+
if parts['year'].nil?
|
87
|
+
new_value = format('1604-%02i-%02i', parts['month'].to_i, parts['date'].to_i)
|
88
|
+
new_property.value = new_value
|
89
|
+
new_property['X-APPLE-OMIT-YEAR'] = '1604'
|
90
|
+
end
|
91
|
+
|
92
|
+
if new_property.name == 'ANNIVERSARY'
|
93
|
+
# Microsoft non-standard anniversary
|
94
|
+
new_property.name = 'X-ANNIVERSARY'
|
95
|
+
|
96
|
+
# We also need to add a new apple property for the same
|
97
|
+
# purpose. This apple property needs a 'label' in the same
|
98
|
+
# group, so we first need to find a groupname that doesn't
|
99
|
+
# exist yet.
|
100
|
+
x = 1
|
101
|
+
loop do
|
102
|
+
break if output.select("ITEM#{x}.").empty?
|
103
|
+
x += 1
|
104
|
+
end
|
105
|
+
output.add("ITEM#{x}.X-ABDATE", new_property.value, 'VALUE' => 'DATE-AND-OR-TIME')
|
106
|
+
output.add("ITEM#{x}.X-ABLABEL", '_$!<Anniversary>!$_')
|
107
|
+
end
|
108
|
+
elsif property.name == 'KIND'
|
109
|
+
case property.value.downcase
|
110
|
+
when 'org'
|
111
|
+
# vCard 3.0 does not have an equivalent to KIND:ORG,
|
112
|
+
# but apple has an extension that means the same
|
113
|
+
# thing.
|
114
|
+
new_property = output.create_property('X-ABSHOWAS', 'COMPANY')
|
115
|
+
when 'individual'
|
116
|
+
# Individual is implicit, so we skip it.
|
117
|
+
return nil
|
118
|
+
when 'group'
|
119
|
+
# OS X addressbook property
|
120
|
+
new_property = output.create_property('X-ADDRESSBOOKSERVER-KIND', 'GROUP')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
elsif target_version == Tilia::VObject::Document::VCARD40
|
124
|
+
# These properties were removed in vCard 4.0
|
125
|
+
return nil if %w(NAME MAILER LABEL CLASS).include?(property.name)
|
126
|
+
|
127
|
+
if property.is_a?(Tilia::VObject::Property::Binary)
|
128
|
+
new_property = convert_binary_to_uri(output, new_property, parameters)
|
129
|
+
elsif property.is_a?(Tilia::VObject::Property::VCard::DateAndOrTime) && parameters.key?('X-APPLE-OMIT-YEAR')
|
130
|
+
# If a property such as BDAY contained 'X-APPLE-OMIT-YEAR',
|
131
|
+
# then we're stripping the year from the vcard 4 value.
|
132
|
+
parts = Tilia::VObject::DateTimeParser.parse_v_card_date_time(property.value)
|
133
|
+
if parts['year'] == property['X-APPLE-OMIT-YEAR'].value.to_i
|
134
|
+
new_value = format('--%02i-%02i', parts['month'], parts['date'])
|
135
|
+
new_property.value = new_value
|
136
|
+
end
|
137
|
+
|
138
|
+
# Regardless if the year matched or not, we do need to strip
|
139
|
+
# X-APPLE-OMIT-YEAR.
|
140
|
+
parameters.delete('X-APPLE-OMIT-YEAR')
|
141
|
+
end
|
142
|
+
|
143
|
+
case property.name
|
144
|
+
when 'X-ABSHOWAS'
|
145
|
+
if property.value.upcase == 'COMPANY'
|
146
|
+
new_property = output.create_property('KIND', 'ORG')
|
147
|
+
end
|
148
|
+
when 'X-ADDRESSBOOKSERVER-KIND'
|
149
|
+
if property.value.upcase == 'GROUP'
|
150
|
+
new_property = output.create_property('KIND', 'GROUP')
|
151
|
+
end
|
152
|
+
when 'X-ANNIVERSARY'
|
153
|
+
new_property.name = 'ANNIVERSARY'
|
154
|
+
# If we already have an anniversary property with the same
|
155
|
+
# value, ignore.
|
156
|
+
output.select('ANNIVERSARY').each do |anniversary|
|
157
|
+
return nil if anniversary.value == new_property.value
|
158
|
+
end
|
159
|
+
when 'X-ABDATE'
|
160
|
+
# Find out what the label was, if it exists.
|
161
|
+
label = input["#{property.group}.X-ABLABEL"]
|
162
|
+
|
163
|
+
# We only support converting anniversaries.
|
164
|
+
if property.group && label && label.value == '_$!<Anniversary>!$_'
|
165
|
+
# If we already have an anniversary property with the same
|
166
|
+
# value, ignore.
|
167
|
+
output.select('ANNIVERSARY').each do |anniversary|
|
168
|
+
return nil if anniversary.value == new_property.value
|
169
|
+
end
|
170
|
+
new_property.name = 'ANNIVERSARY'
|
171
|
+
end
|
172
|
+
# Apple's per-property label system.
|
173
|
+
when 'X-ABLABEL'
|
174
|
+
if new_property.value == '_$!<Anniversary>!$_'
|
175
|
+
# We can safely remove these, as they are converted to
|
176
|
+
# ANNIVERSARY properties.
|
177
|
+
return nil
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# set property group
|
183
|
+
new_property.group = property.group
|
184
|
+
|
185
|
+
if target_version == Tilia::VObject::Document::VCARD40
|
186
|
+
convert_parameters40(new_property, parameters)
|
187
|
+
else
|
188
|
+
convert_parameters30(new_property, parameters)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Lastly, we need to see if there's a need for a VALUE parameter.
|
192
|
+
#
|
193
|
+
# We can do that by instantating a empty property with that name, and
|
194
|
+
# seeing if the default valueType is identical to the current one.
|
195
|
+
temp_property = output.create_property(new_property.name)
|
196
|
+
if temp_property.value_type != new_property.value_type
|
197
|
+
new_property['VALUE'] = new_property.value_type
|
198
|
+
end
|
199
|
+
|
200
|
+
output.add(new_property)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Converts a BINARY property to a URI property.
|
204
|
+
#
|
205
|
+
# vCard 4.0 no longer supports BINARY properties.
|
206
|
+
#
|
207
|
+
# @param Component\VCard output
|
208
|
+
# @param Tilia::VObject::Property::Uri property The input property.
|
209
|
+
# @param parameters List of parameters that will eventually be added to
|
210
|
+
# the new property.
|
211
|
+
#
|
212
|
+
# @return Tilia::VObject::Property::Uri
|
213
|
+
def convert_binary_to_uri(output, new_property, parameters)
|
214
|
+
value = new_property.value
|
215
|
+
new_property = output.create_property(
|
216
|
+
new_property.name,
|
217
|
+
nil, # no value
|
218
|
+
{}, # no parameters yet
|
219
|
+
'URI' # Forcing the BINARY type
|
220
|
+
)
|
221
|
+
|
222
|
+
mime_type = 'application/octet-stream'
|
223
|
+
|
224
|
+
# See if we can find a better mimetype.
|
225
|
+
if parameters.key?('TYPE')
|
226
|
+
new_types = []
|
227
|
+
parameters['TYPE'].parts.each do |type_part|
|
228
|
+
if %w(JPEG PNG GIF).include?(type_part.upcase)
|
229
|
+
mime_type = "image/#{type_part.downcase}"
|
230
|
+
else
|
231
|
+
new_types << type_part
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# If there were any parameters we're not converting to a
|
236
|
+
# mime-type, we need to keep them.
|
237
|
+
if new_types.any?
|
238
|
+
parameters['TYPE'].parts = new_types
|
239
|
+
else
|
240
|
+
parameters.delete('TYPE')
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
new_property.value = "data:#{mime_type};base64,#{Base64.strict_encode64(value)}"
|
245
|
+
new_property
|
246
|
+
end
|
247
|
+
|
248
|
+
# Converts a URI property to a BINARY property.
|
249
|
+
#
|
250
|
+
# In vCard 4.0 attachments are encoded as data: uri. Even though these may
|
251
|
+
# be valid in vCard 3.0 as well, we should convert those to BINARY if
|
252
|
+
# possible, to improve compatibility.
|
253
|
+
#
|
254
|
+
# @param Component\VCard output
|
255
|
+
# @param Tilia::VObject::Property::Uri property The input property.
|
256
|
+
#
|
257
|
+
# @return Tilia::VObject::Property::Binary|null
|
258
|
+
def convert_uri_to_binary(output, new_property)
|
259
|
+
value = new_property.value
|
260
|
+
|
261
|
+
# Only converting data: uris
|
262
|
+
return new_property if value[0...5] != 'data:'
|
263
|
+
|
264
|
+
new_property = output.create_property(
|
265
|
+
new_property.name,
|
266
|
+
nil, # no value
|
267
|
+
{}, # no parameters yet
|
268
|
+
'BINARY'
|
269
|
+
)
|
270
|
+
|
271
|
+
mime_type = value[5...value.index(',')]
|
272
|
+
if mime_type.index(';')
|
273
|
+
mime_type = mime_type[0...mime_type.index(';')]
|
274
|
+
new_property.value = Base64.decode64(value[value.index(',') + 1..-1])
|
275
|
+
else
|
276
|
+
new_property.value = value[value.index(',') + 1..-1]
|
277
|
+
end
|
278
|
+
|
279
|
+
new_property['ENCODING'] = 'b'
|
280
|
+
case mime_type
|
281
|
+
when 'image/jpeg'
|
282
|
+
new_property['TYPE'] = 'JPEG'
|
283
|
+
when 'image/png'
|
284
|
+
new_property['TYPE'] = 'PNG'
|
285
|
+
when 'image/gif'
|
286
|
+
new_property['TYPE'] = 'GIF'
|
287
|
+
end
|
288
|
+
|
289
|
+
new_property
|
290
|
+
end
|
291
|
+
|
292
|
+
# Adds parameters to a new property for vCard 4.0.
|
293
|
+
#
|
294
|
+
# @param Property new_property
|
295
|
+
# @param array parameters
|
296
|
+
#
|
297
|
+
# @return void
|
298
|
+
def convert_parameters40(new_property, parameters)
|
299
|
+
# Adding all parameters.
|
300
|
+
parameters.each do |_, param|
|
301
|
+
# vCard 2.1 allowed parameters with no name
|
302
|
+
param.no_name = false if param.no_name
|
303
|
+
|
304
|
+
case param.name
|
305
|
+
# We need to see if there's any TYPE=PREF, because in vCard 4
|
306
|
+
# that's now PREF=1.
|
307
|
+
when 'TYPE'
|
308
|
+
param.parts.each do |param_part|
|
309
|
+
if param_part.upcase == 'PREF'
|
310
|
+
new_property.add('PREF', '1')
|
311
|
+
else
|
312
|
+
new_property.add(param.name, param_part)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
when 'ENCODING', 'CHARSET'
|
316
|
+
# These no longer exist in vCard 4
|
317
|
+
else
|
318
|
+
new_property.add(param.name, param.parts)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# Adds parameters to a new property for vCard 3.0.
|
324
|
+
#
|
325
|
+
# @param Property new_property
|
326
|
+
# @param array parameters
|
327
|
+
#
|
328
|
+
# @return void
|
329
|
+
def convert_parameters30(new_property, parameters)
|
330
|
+
# Adding all parameters.
|
331
|
+
parameters.each do |_, param|
|
332
|
+
# vCard 2.1 allowed parameters with no name
|
333
|
+
param.no_name = false if param.no_name
|
334
|
+
|
335
|
+
case param.name
|
336
|
+
when 'ENCODING'
|
337
|
+
# This value only existed in vCard 2.1, and should be
|
338
|
+
# removed for anything else.
|
339
|
+
if param.value.upcase != 'QUOTED-PRINTABLE'
|
340
|
+
new_property.add(param.name, param.parts)
|
341
|
+
end
|
342
|
+
# Converting PREF=1 to TYPE=PREF.
|
343
|
+
#
|
344
|
+
# Any other PREF numbers we'll drop.
|
345
|
+
when 'PREF'
|
346
|
+
new_property.add('TYPE', 'PREF') if param.value == '1'
|
347
|
+
else
|
348
|
+
new_property.add(param.name, param.parts)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'json'
|
2
|
+
module Tilia
|
3
|
+
module VObject
|
4
|
+
# iCalendar/vCard/jCal/jCard/xCal/xCard writer object.
|
5
|
+
#
|
6
|
+
# This object provides a few (static) convenience methods to quickly access
|
7
|
+
# the serializers.
|
8
|
+
class Writer
|
9
|
+
# Serializes a vCard or iCalendar object.
|
10
|
+
#
|
11
|
+
# @param Component component
|
12
|
+
#
|
13
|
+
# @return string
|
14
|
+
def self.write(component)
|
15
|
+
component.serialize
|
16
|
+
end
|
17
|
+
|
18
|
+
# Serializes a jCal or jCard object.
|
19
|
+
#
|
20
|
+
# @param Component component
|
21
|
+
# @param int options
|
22
|
+
#
|
23
|
+
# @return string
|
24
|
+
def self.write_json(component)
|
25
|
+
component.json_serialize.to_json
|
26
|
+
end
|
27
|
+
|
28
|
+
# Serializes a xCal or xCard object.
|
29
|
+
#
|
30
|
+
# @param Component component
|
31
|
+
#
|
32
|
+
# @return string
|
33
|
+
def self.write_xml(component)
|
34
|
+
writer = Tilia::Xml::Writer.new
|
35
|
+
writer.open_memory
|
36
|
+
writer.set_indent(true)
|
37
|
+
|
38
|
+
writer.start_document(encoding: LibXML::XML::Encoding::UTF_8)
|
39
|
+
|
40
|
+
if component.is_a? Tilia::VObject::Component::VCalendar
|
41
|
+
writer.start_element('icalendar')
|
42
|
+
writer.write_attribute('xmlns', Tilia::VObject::Parser::Xml::XCAL_NAMESPACE)
|
43
|
+
else
|
44
|
+
writer.start_element('vcards')
|
45
|
+
writer.write_attribute('xmlns', Tilia::VObject::Parser::Xml::XCARD_NAMESPACE)
|
46
|
+
end
|
47
|
+
|
48
|
+
component.xml_serialize(writer)
|
49
|
+
|
50
|
+
writer.end_element
|
51
|
+
|
52
|
+
writer.output_memory
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Namespace for Tilia library
|
2
|
+
module Tilia
|
3
|
+
# Load active support core extensions
|
4
|
+
require 'active_support'
|
5
|
+
require 'active_support/core_ext'
|
6
|
+
|
7
|
+
# Mail encoding stuff
|
8
|
+
require 'mail'
|
9
|
+
|
10
|
+
# Char detecting functions
|
11
|
+
require 'rchardet'
|
12
|
+
|
13
|
+
# Our XML stuff
|
14
|
+
require 'tilia/xml'
|
15
|
+
|
16
|
+
# Namespace of tilia_vobject library
|
17
|
+
module VObject
|
18
|
+
require 'tilia/v_object/version'
|
19
|
+
require 'tilia/v_object/element_list'
|
20
|
+
require 'tilia/v_object/node'
|
21
|
+
require 'tilia/v_object/parameter'
|
22
|
+
require 'tilia/v_object/property'
|
23
|
+
require 'tilia/v_object/date_time_parser'
|
24
|
+
require 'tilia/v_object/uuid_util'
|
25
|
+
require 'tilia/v_object/component'
|
26
|
+
require 'tilia/v_object/document'
|
27
|
+
require 'tilia/v_object/parse_exception'
|
28
|
+
require 'tilia/v_object/eof_exception'
|
29
|
+
require 'tilia/v_object/reader'
|
30
|
+
require 'tilia/v_object/settings'
|
31
|
+
require 'tilia/v_object/string_util'
|
32
|
+
require 'tilia/v_object/time_zone_util'
|
33
|
+
require 'tilia/v_object/writer'
|
34
|
+
require 'tilia/v_object/i_tip'
|
35
|
+
require 'tilia/v_object/parser'
|
36
|
+
require 'tilia/v_object/recur'
|
37
|
+
require 'tilia/v_object/splitter'
|
38
|
+
require 'tilia/v_object/time_zone_data'
|
39
|
+
require 'tilia/v_object/v_card_converter'
|
40
|
+
require 'tilia/v_object/birthday_calendar_generator'
|
41
|
+
require 'tilia/v_object/free_busy_data'
|
42
|
+
require 'tilia/v_object/free_busy_generator'
|
43
|
+
require 'tilia/v_object/cli'
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'tilia/v_object'
|