tilia-vobject 4.0.0.pre.alpha5 → 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.sabre.md +59 -2
- data/Gemfile +1 -8
- data/Gemfile.lock +18 -12
- data/LICENSE +1 -1
- data/LICENSE.sabre +1 -1
- data/lib/tilia/v_object.rb +1 -0
- data/lib/tilia/v_object/birthday_calendar_generator.rb +11 -11
- data/lib/tilia/v_object/cli.rb +39 -38
- data/lib/tilia/v_object/component.rb +47 -50
- data/lib/tilia/v_object/component/available.rb +4 -37
- data/lib/tilia/v_object/component/v_alarm.rb +6 -18
- data/lib/tilia/v_object/component/v_availability.rb +6 -39
- data/lib/tilia/v_object/component/v_calendar.rb +66 -98
- data/lib/tilia/v_object/component/v_card.rb +42 -69
- data/lib/tilia/v_object/component/v_event.rb +5 -17
- data/lib/tilia/v_object/component/v_free_busy.rb +4 -16
- data/lib/tilia/v_object/component/v_journal.rb +16 -16
- data/lib/tilia/v_object/component/v_time_zone.rb +2 -14
- data/lib/tilia/v_object/component/v_todo.rb +17 -36
- data/lib/tilia/v_object/date_time_parser.rb +24 -24
- data/lib/tilia/v_object/document.rb +25 -25
- data/lib/tilia/v_object/free_busy_data.rb +7 -7
- data/lib/tilia/v_object/free_busy_generator.rb +73 -75
- data/lib/tilia/v_object/i_tip.rb +1 -0
- data/lib/tilia/v_object/i_tip/broker.rb +134 -116
- data/lib/tilia/v_object/i_tip/i_tip_exception.rb +1 -1
- data/lib/tilia/v_object/i_tip/message.rb +13 -13
- data/lib/tilia/v_object/invalid_data_exception.rb +8 -0
- data/lib/tilia/v_object/node.rb +22 -27
- data/lib/tilia/v_object/parameter.rb +22 -22
- data/lib/tilia/v_object/parse_exception.rb +1 -1
- data/lib/tilia/v_object/parser.rb +1 -0
- data/lib/tilia/v_object/parser/json.rb +9 -19
- data/lib/tilia/v_object/parser/mime_dir.rb +73 -39
- data/lib/tilia/v_object/parser/parser.rb +9 -14
- data/lib/tilia/v_object/parser/xml.rb +33 -50
- data/lib/tilia/v_object/parser/xml/element.rb +1 -0
- data/lib/tilia/v_object/parser/xml/element/key_value.rb +2 -2
- data/lib/tilia/v_object/property.rb +52 -52
- data/lib/tilia/v_object/property/binary.rb +10 -10
- data/lib/tilia/v_object/property/boolean.rb +6 -6
- data/lib/tilia/v_object/property/flat_text.rb +3 -3
- data/lib/tilia/v_object/property/float_value.rb +10 -10
- data/lib/tilia/v_object/property/i_calendar.rb +1 -0
- data/lib/tilia/v_object/property/i_calendar/cal_address.rb +3 -3
- data/lib/tilia/v_object/property/i_calendar/date_time.rb +29 -57
- data/lib/tilia/v_object/property/i_calendar/duration.rb +6 -6
- data/lib/tilia/v_object/property/i_calendar/period.rb +10 -10
- data/lib/tilia/v_object/property/i_calendar/recur.rb +16 -24
- data/lib/tilia/v_object/property/integer_value.rb +8 -8
- data/lib/tilia/v_object/property/text.rb +21 -36
- data/lib/tilia/v_object/property/time.rb +29 -6
- data/lib/tilia/v_object/property/unknown.rb +2 -2
- data/lib/tilia/v_object/property/uri.rb +24 -5
- data/lib/tilia/v_object/property/utc_offset.rb +5 -5
- data/lib/tilia/v_object/property/v_card.rb +1 -0
- data/lib/tilia/v_object/property/v_card/date.rb +3 -3
- data/lib/tilia/v_object/property/v_card/date_and_or_time.rb +30 -42
- data/lib/tilia/v_object/property/v_card/date_time.rb +1 -1
- data/lib/tilia/v_object/property/v_card/language_tag.rb +4 -4
- data/lib/tilia/v_object/property/v_card/time_stamp.rb +5 -5
- data/lib/tilia/v_object/reader.rb +12 -11
- data/lib/tilia/v_object/recur.rb +2 -0
- data/lib/tilia/v_object/recur/event_iterator.rb +30 -27
- data/lib/tilia/v_object/recur/max_instances_exceeded_exception.rb +10 -0
- data/lib/tilia/v_object/recur/no_instances_exception.rb +1 -1
- data/lib/tilia/v_object/recur/r_date_iterator.rb +15 -41
- data/lib/tilia/v_object/recur/r_rule_iterator.rb +23 -156
- data/lib/tilia/v_object/settings.rb +16 -0
- data/lib/tilia/v_object/splitter.rb +1 -0
- data/lib/tilia/v_object/splitter/i_calendar.rb +5 -5
- data/lib/tilia/v_object/splitter/splitter_interface.rb +2 -2
- data/lib/tilia/v_object/splitter/v_card.rb +5 -5
- data/lib/tilia/v_object/string_util.rb +25 -9
- data/lib/tilia/v_object/time_zone_data.rb +1 -0
- data/lib/tilia/v_object/time_zone_util.rb +6 -6
- data/lib/tilia/v_object/uuid_util.rb +3 -3
- data/lib/tilia/v_object/v_card_converter.rb +24 -21
- data/lib/tilia/v_object/version.rb +1 -1
- data/lib/tilia/v_object/writer.rb +7 -7
- data/test/test_helper.rb +3 -3
- data/test/v_object/birthday_calendar_generator_test.rb +22 -0
- data/test/v_object/component/v_alarm_test.rb +3 -1
- data/test/v_object/component/v_calendar_test.rb +40 -4
- data/test/v_object/component/v_card_test.rb +1 -1
- data/test/v_object/component_test.rb +5 -3
- data/test/v_object/date_time_parser_test.rb +15 -5
- data/test/v_object/free_busy_generator_test.rb +5 -5
- data/test/v_object/i_tip/broker_attendee_reply_test.rb +19 -0
- data/test/v_object/i_tip/broker_delete_event_test.rb +146 -2
- data/test/v_object/i_tip/broker_new_event_test.rb +21 -0
- data/test/v_object/i_tip/broker_process_reply_test.rb +10 -0
- data/test/v_object/i_tip/broker_tester.rb +1 -1
- data/test/v_object/i_tip/broker_update_event_test.rb +36 -0
- data/test/v_object/issue259_test.rb +24 -0
- data/test/v_object/issue40_test.rb +3 -1
- data/test/v_object/j_cal_test.rb +15 -12
- data/test/v_object/parser/json_test.rb +5 -5
- data/test/v_object/parser/mime_dir_test.rb +109 -0
- data/test/v_object/property/binary_test.rb +4 -2
- data/test/v_object/property/i_calendar/date_time_test.rb +3 -1
- data/test/v_object/property/uri_test.rb +23 -0
- data/test/v_object/recur/event_iterator/by_month_in_daily_test.rb +1 -1
- data/test/v_object/recur/event_iterator/by_set_pos_hang_test.rb +1 -1
- data/test/v_object/recur/event_iterator/expand_floating_times_test.rb +9 -9
- data/test/v_object/recur/event_iterator/handle_r_date_expand_test.rb +51 -0
- data/test/v_object/recur/event_iterator/incorrect_expand_test.rb +3 -5
- data/test/v_object/recur/event_iterator/infinite_loop_problem_test.rb +3 -1
- data/test/v_object/{issue26_test.rb → recur/event_iterator/issue26_test.rb} +3 -1
- data/test/v_object/recur/event_iterator/main_test.rb +9 -3
- data/test/v_object/recur/event_iterator/max_instances_test.rb +38 -0
- data/test/v_object/recur/event_iterator/missing_overridden_test.rb +3 -5
- data/test/v_object/recur/event_iterator/no_instances_test.rb +5 -3
- data/test/v_object/recur/event_iterator/override_first_event_test.rb +9 -9
- data/test/v_object/recur/r_date_iterator_test.rb +18 -0
- data/test/v_object/recur/r_rule_iterator_test.rb +4 -4
- data/test/v_object/splitter/i_calendar_test.rb +27 -7
- data/test/v_object/splitter/v_card_test.rb +5 -3
- data/test/v_object/test_case.rb +14 -4
- data/tilia-vobject.gemspec +2 -2
- metadata +17 -11
data/lib/tilia/v_object/i_tip.rb
CHANGED
@@ -37,7 +37,7 @@ module Tilia
|
|
37
37
|
# server, but if you're writing an iTip application that doesn't deal with
|
38
38
|
# CalDAV, you may want to ignore this parameter.
|
39
39
|
#
|
40
|
-
# @
|
40
|
+
# @return [Boolean]
|
41
41
|
attr_accessor :schedule_agent_server_rules
|
42
42
|
|
43
43
|
# The broker will try during 'parseEvent' figure out whether the change
|
@@ -49,7 +49,7 @@ module Tilia
|
|
49
49
|
# This list is taken from:
|
50
50
|
# * http://tools.ietf.org/html/rfc5546#section-2.1.4
|
51
51
|
#
|
52
|
-
# @
|
52
|
+
# @return [Array<String>]
|
53
53
|
attr_accessor :significant_change_properties
|
54
54
|
|
55
55
|
# This method is used to process an incoming itip message.
|
@@ -78,10 +78,10 @@ module Tilia
|
|
78
78
|
#
|
79
79
|
# If the iTip message was not supported, we will always return false.
|
80
80
|
#
|
81
|
-
# @param Message itip_message
|
82
|
-
# @param VCalendar existing_object
|
81
|
+
# @param [Message] itip_message
|
82
|
+
# @param [VCalendar] existing_object
|
83
83
|
#
|
84
|
-
# @return VCalendar
|
84
|
+
# @return [VCalendar, nil]
|
85
85
|
def process_message(itip_message, existing_object = nil)
|
86
86
|
# We only support events at the moment.
|
87
87
|
return false unless itip_message.component == 'VEVENT'
|
@@ -118,11 +118,11 @@ module Tilia
|
|
118
118
|
# people. If the user was an attendee, we need to make sure that the
|
119
119
|
# organizer gets the 'declined' message.
|
120
120
|
#
|
121
|
-
# @param VCalendar
|
122
|
-
# @param
|
123
|
-
# @param VCalendar
|
121
|
+
# @param [VCalendar, String] calendar
|
122
|
+
# @param [String, Array<String>] user_href
|
123
|
+
# @param [VCalendar, String, nil] old_calendar
|
124
124
|
#
|
125
|
-
# @return
|
125
|
+
# @return [Array]
|
126
126
|
def parse_event(calendar, user_href, old_calendar = nil)
|
127
127
|
if old_calendar
|
128
128
|
if old_calendar.is_a?(String)
|
@@ -196,11 +196,11 @@ module Tilia
|
|
196
196
|
else
|
197
197
|
# This is an attendee deleting the event.
|
198
198
|
event_info['attendees'].each do |key, attendee|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
}
|
203
|
-
|
199
|
+
next unless user_href.include?(attendee['href'])
|
200
|
+
|
201
|
+
event_info['attendees'][key]['instances'] = {
|
202
|
+
'master' => { 'id' => 'master', 'partstat' => 'DECLINED' }
|
203
|
+
}
|
204
204
|
end
|
205
205
|
end
|
206
206
|
|
@@ -220,7 +220,7 @@ module Tilia
|
|
220
220
|
end
|
221
221
|
end
|
222
222
|
|
223
|
-
|
223
|
+
[]
|
224
224
|
end
|
225
225
|
|
226
226
|
protected
|
@@ -231,10 +231,10 @@ module Tilia
|
|
231
231
|
# invite, or an update to an existing one.
|
232
232
|
#
|
233
233
|
#
|
234
|
-
# @param Message itip_message
|
235
|
-
# @param VCalendar existing_object
|
234
|
+
# @param [Message] itip_message
|
235
|
+
# @param [VCalendar, nil] existing_object
|
236
236
|
#
|
237
|
-
# @return VCalendar
|
237
|
+
# @return [VCalendar, nil]
|
238
238
|
def process_message_request(itip_message, existing_object = nil)
|
239
239
|
if !existing_object
|
240
240
|
# This is a new invite, and we're just going to copy over
|
@@ -264,10 +264,10 @@ module Tilia
|
|
264
264
|
# attendee got removed from an event, or an event got cancelled
|
265
265
|
# altogether.
|
266
266
|
#
|
267
|
-
# @param Message itip_message
|
268
|
-
# @param VCalendar existing_object
|
267
|
+
# @param [Message] itip_message
|
268
|
+
# @param [VCalendar, nil] existing_object
|
269
269
|
#
|
270
|
-
# @return VCalendar
|
270
|
+
# @return [VCalendar, nil]
|
271
271
|
def process_message_cancel(itip_message, existing_object = nil)
|
272
272
|
if !existing_object
|
273
273
|
# The event didn't exist in the first place, so we're just
|
@@ -287,10 +287,10 @@ module Tilia
|
|
287
287
|
# The message is a reply. This is for example an attendee telling
|
288
288
|
# an organizer he accepted the invite, or declined it.
|
289
289
|
#
|
290
|
-
# @param Message itip_message
|
291
|
-
# @param VCalendar existing_object
|
290
|
+
# @param [Message] itip_message
|
291
|
+
# @param [VCalendar, nil] existing_object
|
292
292
|
#
|
293
|
-
# @return VCalendar
|
293
|
+
# @return [VCalendar, nil]
|
294
294
|
def process_message_reply(itip_message, existing_object = nil)
|
295
295
|
# A reply can only be processed based on an existing object.
|
296
296
|
# If the object is not available, the reply is ignored.
|
@@ -317,33 +317,33 @@ module Tilia
|
|
317
317
|
recur_id = vevent.key?('RECURRENCE-ID') ? vevent['RECURRENCE-ID'].value : 'master'
|
318
318
|
master_object = vevent if recur_id == 'master'
|
319
319
|
|
320
|
-
|
321
|
-
attendee_found = false
|
322
|
-
if vevent.key?('ATTENDEE')
|
323
|
-
vevent['ATTENDEE'].each do |attendee|
|
324
|
-
if attendee.value == itip_message.sender
|
325
|
-
attendee_found = true
|
326
|
-
attendee['PARTSTAT'] = instances[recur_id]
|
327
|
-
attendee['SCHEDULE-STATUS'] = request_status
|
328
|
-
# Un-setting the RSVP status, because we now know
|
329
|
-
# that the attendee already replied.
|
330
|
-
attendee.delete('RSVP')
|
331
|
-
break
|
332
|
-
end
|
333
|
-
end
|
334
|
-
end
|
320
|
+
next unless instances.key?(recur_id)
|
335
321
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
322
|
+
attendee_found = false
|
323
|
+
if vevent.key?('ATTENDEE')
|
324
|
+
vevent['ATTENDEE'].each do |attendee|
|
325
|
+
next unless attendee.value == itip_message.sender
|
326
|
+
|
327
|
+
attendee_found = true
|
328
|
+
attendee['PARTSTAT'] = instances[recur_id]
|
329
|
+
attendee['SCHEDULE-STATUS'] = request_status
|
330
|
+
# Un-setting the RSVP status, because we now know
|
331
|
+
# that the attendee already replied.
|
332
|
+
attendee.delete('RSVP')
|
333
|
+
break
|
343
334
|
end
|
335
|
+
end
|
344
336
|
|
345
|
-
|
337
|
+
unless attendee_found
|
338
|
+
# Adding a new attendee. The iTip documentation calls this
|
339
|
+
# a party crasher.
|
340
|
+
attendee = vevent.add('ATTENDEE', itip_message.sender, 'PARTSTAT' => instances[recur_id])
|
341
|
+
if itip_message.sender_name
|
342
|
+
attendee['CN'] = itip_message.sender_name
|
343
|
+
end
|
346
344
|
end
|
345
|
+
|
346
|
+
instances.delete(recur_id)
|
347
347
|
end
|
348
348
|
|
349
349
|
unless master_object
|
@@ -380,17 +380,17 @@ module Tilia
|
|
380
380
|
attendee_found = false
|
381
381
|
if new_object.key?('ATTENDEE')
|
382
382
|
new_object['ATTENDEE'].each do |attendee|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
383
|
+
next unless attendee.value == itip_message.sender
|
384
|
+
|
385
|
+
attendee_found = true
|
386
|
+
attendee['PARTSTAT'] = partstat
|
387
|
+
break
|
388
388
|
end
|
389
389
|
end
|
390
390
|
|
391
391
|
unless attendee_found
|
392
392
|
# Adding a new attendee
|
393
|
-
attendee = new_object.add('ATTENDEE', itip_message.sender, 'PARTSTAT' => partstat
|
393
|
+
attendee = new_object.add('ATTENDEE', itip_message.sender, 'PARTSTAT' => partstat)
|
394
394
|
|
395
395
|
if itip_message.sender_name
|
396
396
|
attendee['CN'] = itip_message.sender_name
|
@@ -410,11 +410,11 @@ module Tilia
|
|
410
410
|
# We will detect which attendees got added, which got removed and create
|
411
411
|
# specific messages for these situations.
|
412
412
|
#
|
413
|
-
# @param VCalendar calendar
|
414
|
-
# @param
|
415
|
-
# @param
|
413
|
+
# @param [VCalendar] calendar
|
414
|
+
# @param [Hash] event_info
|
415
|
+
# @param [Hash] old_event_info
|
416
416
|
#
|
417
|
-
# @return
|
417
|
+
# @return [Array<Message>]
|
418
418
|
def parse_event_for_organizer(calendar, event_info, old_event_info)
|
419
419
|
# Merging attendee lists.
|
420
420
|
attendees = {}
|
@@ -478,6 +478,12 @@ module Tilia
|
|
478
478
|
end
|
479
479
|
|
480
480
|
event.add(calendar['VEVENT']['DTSTART'].clone)
|
481
|
+
if calendar['VEVENT'].key?('DTEND')
|
482
|
+
event.add(calendar['VEVENT']['DTEND'].clone)
|
483
|
+
elsif calendar['VEVENT'].key?('DURATION')
|
484
|
+
event.add(calendar['VEVENT']['DURATION'].clone)
|
485
|
+
end
|
486
|
+
|
481
487
|
org = event.add('ORGANIZER', event_info['organizer'])
|
482
488
|
if event_info['organizer_name']
|
483
489
|
org['CN'] = event_info['organizer_name']
|
@@ -519,10 +525,10 @@ module Tilia
|
|
519
525
|
# We need to find a list of events that the attendee
|
520
526
|
# is not a part of to add to the list of exceptions.
|
521
527
|
exceptions = []
|
522
|
-
event_info['instances'].each do |
|
523
|
-
|
524
|
-
|
525
|
-
|
528
|
+
event_info['instances'].each do |id, _vevent|
|
529
|
+
next if attendee['newInstances'].key?(id)
|
530
|
+
|
531
|
+
exceptions << id
|
526
532
|
end
|
527
533
|
|
528
534
|
# If there were exceptions, we need to add it to an
|
@@ -540,15 +546,15 @@ module Tilia
|
|
540
546
|
current_event['ORGANIZER'].delete('SCHEDULE-FORCE-SEND')
|
541
547
|
current_event['ORGANIZER'].delete('SCHEDULE-STATUS')
|
542
548
|
|
543
|
-
current_event['ATTENDEE'].each do |
|
544
|
-
|
545
|
-
|
549
|
+
current_event['ATTENDEE'].each do |event_attendee|
|
550
|
+
event_attendee.delete('SCHEDULE-FORCE-SEND')
|
551
|
+
event_attendee.delete('SCHEDULE-STATUS')
|
546
552
|
|
547
553
|
# We're adding PARTSTAT=NEEDS-ACTION to ensure that
|
548
554
|
# iOS shows an "Inbox Item"
|
549
|
-
|
550
|
-
|
551
|
-
|
555
|
+
next if event_attendee.key?('PARTSTAT')
|
556
|
+
|
557
|
+
event_attendee['PARTSTAT'] = 'NEEDS-ACTION'
|
552
558
|
end
|
553
559
|
end
|
554
560
|
|
@@ -560,19 +566,19 @@ module Tilia
|
|
560
566
|
messages << message
|
561
567
|
end
|
562
568
|
|
563
|
-
|
569
|
+
messages
|
564
570
|
end
|
565
571
|
|
566
572
|
# Parse an event update for an attendee.
|
567
573
|
#
|
568
574
|
# This function figures out if we need to send a reply to an organizer.
|
569
575
|
#
|
570
|
-
# @param VCalendar calendar
|
571
|
-
# @param
|
572
|
-
# @param
|
573
|
-
# @param
|
576
|
+
# @param [VCalendar] calendar
|
577
|
+
# @param [Hash] event_info
|
578
|
+
# @param [Hash] old_event_info
|
579
|
+
# @param [String] attendee
|
574
580
|
#
|
575
|
-
# @return Message
|
581
|
+
# @return [Array<Message>]
|
576
582
|
def parse_event_for_attendee(calendar, event_info, old_event_info, attendee)
|
577
583
|
if schedule_agent_server_rules && event_info['organizer_schedule_agent'] == 'CLIENT'
|
578
584
|
return []
|
@@ -616,16 +622,16 @@ module Tilia
|
|
616
622
|
# We only need to do that though, if the master event is not declined.
|
617
623
|
if instances.key?('master') && instances['master']['newstatus'] != 'DECLINED'
|
618
624
|
event_info['exdate'].each do |ex_date|
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
625
|
+
next if old_event_info['exdate'].include?(ex_date)
|
626
|
+
|
627
|
+
if instances.key?(ex_date)
|
628
|
+
instances[ex_date]['newstatus'] = 'DECLINED'
|
629
|
+
else
|
630
|
+
instances[ex_date] = {
|
631
|
+
'id' => ex_date,
|
632
|
+
'oldstatus' => nil,
|
633
|
+
'newstatus' => 'DECLINED'
|
634
|
+
}
|
629
635
|
end
|
630
636
|
end
|
631
637
|
end
|
@@ -672,6 +678,12 @@ module Tilia
|
|
672
678
|
instance_obj = event_info['instances'][instance['id']]
|
673
679
|
|
674
680
|
event.add(instance_obj['DTSTART'].clone)
|
681
|
+
if instance_obj.key?('DTEND')
|
682
|
+
event.add(instance_obj['DTEND'].clone)
|
683
|
+
elsif instance_obj.key?('DURATION')
|
684
|
+
event.add(instance_obj['DURATION'].clone)
|
685
|
+
end
|
686
|
+
|
675
687
|
if instance_obj.key?('SUMMARY')
|
676
688
|
event.add('SUMMARY', instance_obj['SUMMARY'].value)
|
677
689
|
elsif !summary.blank?
|
@@ -686,9 +698,9 @@ module Tilia
|
|
686
698
|
|
687
699
|
# Treat is as a DATE field
|
688
700
|
if instance['id'].size <= 8
|
689
|
-
|
701
|
+
event.add('DTSTART', dt, 'VALUE' => 'DATE')
|
690
702
|
else
|
691
|
-
|
703
|
+
event.add('DTSTART', dt)
|
692
704
|
end
|
693
705
|
|
694
706
|
event.add('SUMMARY', summary) unless summary.blank?
|
@@ -698,9 +710,9 @@ module Tilia
|
|
698
710
|
dt = Tilia::VObject::DateTimeParser.parse(instance['id'], event_info['timezone'])
|
699
711
|
# Treat is as a DATE field
|
700
712
|
if instance['id'].size <= 8
|
701
|
-
|
713
|
+
event.add('RECURRENCE-ID', dt, 'VALUE' => 'DATE')
|
702
714
|
else
|
703
|
-
|
715
|
+
event.add('RECURRENCE-ID', dt)
|
704
716
|
end
|
705
717
|
end
|
706
718
|
|
@@ -736,9 +748,9 @@ module Tilia
|
|
736
748
|
# 4. attendees
|
737
749
|
# 5. instances
|
738
750
|
#
|
739
|
-
# @param VCalendar calendar
|
751
|
+
# @param [VCalendar] calendar
|
740
752
|
#
|
741
|
-
# @return
|
753
|
+
# @return [Hash]
|
742
754
|
def parse_event_info(calendar = nil)
|
743
755
|
uid = nil
|
744
756
|
organizer = nil
|
@@ -780,14 +792,18 @@ module Tilia
|
|
780
792
|
fail Tilia::VObject::ITip::SameOrganizerForAllComponentsException, 'Every instance of the event must have the same organizer.'
|
781
793
|
end
|
782
794
|
end
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
795
|
+
|
796
|
+
if vevent['ORGANIZER'].key?('SCHEDULE-FORCE-SEND')
|
797
|
+
organizer_force_send = vevent['ORGANIZER']['SCHEDULE-FORCE-SEND'].to_s.upcase
|
798
|
+
else
|
799
|
+
organizer_force_send = nil
|
800
|
+
end
|
801
|
+
|
802
|
+
if vevent['ORGANIZER'].key?('SCHEDULE-AGENT')
|
803
|
+
organizer_schedule_agent = vevent['ORGANIZER']['SCHEDULE-AGENT'].to_s.upcase
|
804
|
+
else
|
805
|
+
organizer_schedule_agent = 'SERVER'
|
806
|
+
end
|
791
807
|
end
|
792
808
|
|
793
809
|
if sequence.nil? && vevent.key?('SEQUENCE')
|
@@ -796,7 +812,7 @@ module Tilia
|
|
796
812
|
|
797
813
|
if vevent.key?('EXDATE')
|
798
814
|
vevent.select('EXDATE').each do |val|
|
799
|
-
exdate
|
815
|
+
exdate += val.parts
|
800
816
|
end
|
801
817
|
exdate.sort!
|
802
818
|
end
|
@@ -816,15 +832,17 @@ module Tilia
|
|
816
832
|
next
|
817
833
|
end
|
818
834
|
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
835
|
+
if attendee.key?('PARTSTAT')
|
836
|
+
part_stat = attendee['PARTSTAT'].to_s.upcase
|
837
|
+
else
|
838
|
+
part_stat = 'NEEDS-ACTION'
|
839
|
+
end
|
823
840
|
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
841
|
+
if attendee.key?('SCHEDULE-FORCE-SEND')
|
842
|
+
force_send = attendee['SCHEDULE-FORCE-SEND'].to_s.upcase
|
843
|
+
else
|
844
|
+
force_send = nil
|
845
|
+
end
|
828
846
|
|
829
847
|
if attendees.key?(attendee.normalized_value)
|
830
848
|
attendees[attendee.normalized_value]['instances'][recur_id] = {
|
@@ -851,17 +869,17 @@ module Tilia
|
|
851
869
|
end
|
852
870
|
|
853
871
|
significant_change_properties.each do |prop|
|
854
|
-
|
855
|
-
property_values = vevent.select(prop)
|
872
|
+
next unless vevent.key?(prop)
|
856
873
|
|
857
|
-
|
874
|
+
property_values = vevent.select(prop)
|
858
875
|
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
876
|
+
significant_change_hash += prop + ':'
|
877
|
+
|
878
|
+
if prop == 'EXDATE'
|
879
|
+
significant_change_hash += exdate.join(',') + ';'
|
880
|
+
else
|
881
|
+
property_values.each do |val|
|
882
|
+
significant_change_hash += val.value + ';'
|
865
883
|
end
|
866
884
|
end
|
867
885
|
end
|
@@ -889,7 +907,7 @@ module Tilia
|
|
889
907
|
|
890
908
|
public
|
891
909
|
|
892
|
-
#
|
910
|
+
# Sets instance variables
|
893
911
|
def initialize
|
894
912
|
@schedule_agent_server_rules = true
|
895
913
|
@significant_change_properties = [
|