6.0.0-beta1
▾
Tasks
New Task
Search
Photos
Wiki
▾
Tickets
New Ticket
Search
dev.horde.org
Toggle Alerts Log
Help
10/18/25
H
istory
A
ttachments
C
omment
W
atch
Download
Comment on [#13664] accept event to Horde CalDAV calendar from Thunderbird Lightning parses Attendees
*
Your Email Address
*
Spam protection
Enter the letters below:
.__.. , __ .___.._. [__] \./ / ` _/ | | | | \__../__._|_
Comment
> Dear, > > A meeting request arrives by e-mail in Thunderbird 31.2.0 with > Lightning 3.3.1 installed from an external calendar application. On > accepting the meeting request putting it into a Kronolith calendar > installed/connected from Lightning using CalDAV, Horde parses the > attendees and puts them into the newly created request. > > As a result Kronolith: > -> sends notifications to all the attendees from the organizers > meeting as it is seen as a new meeting in Horde, effectively > duplicating and hijacking someone else's meeting. > -> this happens for everyone accepting, and possibly also accepting > the wrongly newly created meeting, with a mailing spree through the > organization and towards the external partner as a result. > -> Horde treats accepting requests from Thunderbird differently than > from within IMP with totally different meetings in Kronolith as a > result, not working consistently. > -> Ligthing cannot be used as a mail client for accepting invites. > > Thunderbird/Ligthning adds a header X-MOZ-RECEIVED-SEQUENCE to a > meeting request being an accept on a received invite compared to a > new meeting request created in LIghtning directly. > > We could get a working, yes ugly but still a solution, patched up > Kronolith with the following code changes whereby we check for the > X-MOZ-RECEIVED-SEQUENCE header. Hope it is any help to you. > > vi /var/www/horde/kronolith/lib/Event.php > > 363 /** > 364 * The cached event duration, split up in time units. > 365 * > 366 * @see getDuration() > 367 * @var stdClass > 368 */ > 369 protected $_duration; > 370 > 371 //OpenOutsourcing added properties > 372 //public $organizer; > 373 public $x_moz_received_sequence; > 374 public $x_moz_received_attendees = array(); > 375 > 376 /** > 377 * Constructor. > 378 * > 379 * @param Kronolith_Driver $driver The backend driver that > this event is > 380 * stored in. > 381 * @param mixed $eventObject Backend specific event object > 382 * that this will represent. > 383 */ > 384 public function __construct(Kronolith_Driver $driver, > $eventObject = null) > > 1052 /** > 1053 * Updates the properties of this event from a > Horde_Icalendar_Vevent > 1054 * object. > 1055 * > 1056 * @param Horde_Icalendar_Vevent $vEvent The iCalendar data > to update > 1057 * from. > 1058 * @param boolean $parseAttendees Parse attendees too? > 1059 * @since Kronolith 4.2 > 1060 */ > 1061 public function fromiCalendar($vEvent, $parseAttendees = false) > 1062 { > 1063 > 1064 // OpenOutsourcing > 1065 // Add X-MOZ-RECEIVED-SEQUENCE to object > 1066 try { > 1067 $this->x_moz_received_sequence = False; > 1068 // This call throws exception when attribute does not exist > 1069 $moz_received = > $vEvent->getAttribute('X-MOZ-RECEIVED-SEQUENCE'); > 1070 $this->x_moz_received_sequence = True; > 1071 } catch (Horde_Icalendar_Exception $e) {} > > 2659 public function addAttendee($email, $attendance, $response, > $name = null) > 2660 { > 2661 if ($attendance == Kronolith::PART_IGNORE) { > 2662 if (isset($this->attendees[$email])) { > 2663 $attendance = $this->attendees[$email]['attendance']; > 2664 } else { > 2665 $attendance = Kronolith::PART_REQUIRED; > 2666 } > 2667 } > 2668 if (empty($name) && isset($this->attendees[$email]) && > 2669 !empty($this->attendees[$email]['name'])) { > 2670 $name = $this->attendees[$email]['name']; > 2671 } > 2672 > 2673 // OpenOutsourcing > 2674 // Add IF and wrap existing code into ELSE > 2675 if ($this->x_moz_received_sequence == True) { > 2676 $this->x_moz_received_attendees[$email] = array( > 2677 'attendance' => $attendance, > 2678 'response' => $response, > 2679 'name' => $name > 2680 ); > 2681 } > 2682 else { > 2683 $this->attendees[$email] = array( > 2684 'attendance' => $attendance, > 2685 'response' => $response, > 2686 'name' => $name > 2687 ); > 2688 } > 2689 } > > vi /var/www/horde/kronolith/lib/Application.php > 800 public function davPutObject($collection, $object, $data) > ... > 854 // Save entry. > 855 $id = $event->save(); > 856 > 857 if (!$existing_event) { > 858 $dav->addObjectMap($id, $object, $internal); > 859 } > 860 > 861 // OpenOutsourcing > 862 // Send ACCEPT and DECLINE messages on > X-MOZ-RECEIVED-SEQUENCE > 863 if($event->x_moz_received_sequence == True) { > 864 > 865 $ident_user = > $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')- > >create($event->creator); > 866 $reply_to = $ident_user->getValue('from_addr'); > 867 > 868 /** Invitation responses */ > 869 $RESPONSE_NONE = 1; > 870 $RESPONSE_ACCEPTED = 2; > 871 $RESPONSE_DECLINED = 3; > 872 $RESPONSE_TENTATIVE = 4; > 873 > 874 $response = $RESPONSE_NONE; > 875 foreach ($event->x_moz_received_attendees as > $email => $status) { > 876 if ($email == $reply_to) { > 877 $response = $status['response']; > 878 } > 879 } > 880 > 881 $resource = new Horde_Itip_Resource_Identity( > 882 $GLOBALS['injector']->getInstance('IMP_Identity'), > 883 $content->getAttribute('ATTENDEE'), > 884 $reply_to > 885 ); > 886 > 887 switch ($response) { > 888 case $RESPONSE_ACCEPTED: > 889 $type = new > Horde_Itip_Response_Type_Accept($resource); > 890 break; > 891 case $RESPONSE_TENTATIVE: > 892 $type = new > Horde_Itip_Response_Type_Tentative($resource); > 893 break; > 894 case $RESPONSE_DECLINED: > 895 $type = new > Horde_Itip_Response_Type_Decline($resource); > 896 break; > 897 default: > 898 $type = new > Horde_Itip_Response_Type_Accept($resource); > 899 break; > 900 } > 901 > 902 try { > 903 Horde_Itip::factory($content, > $resource)->sendMultiPartResponse( > 904 $type, > 905 new Horde_Itip_Response_Options_Horde( > 906 'UTF-8', > 907 array( > 908 'dns' => > $GLOBALS['injector']->getInstance('Net_DNS2_Resolver'), > 909 'server' => > $GLOBALS['conf']['server']['name'] > 910 ) > 911 ), > 912 $GLOBALS['injector']->getInstance('IMP_Mail') > 913 ); > 914 } catch (Horde_Itip_Exception $e) { > 915 system("echo SENT ERROR >> /tmp/willem"); > 916 } > 917 //$type = new > Horde_Itip_Response_Type_Decline($resource); > 918 } > 919 > 920 // Send iTip messages. > > KR, > > Willem
Attachment
Watch this ticket
N
ew Ticket
M
y Tickets
S
earch
Q
uery Builder
R
eports
Saved Queries
Open Bugs
Bugs waiting for Feedback
Open Bugs in Releases
Open Enhancements
Enhancements waiting for Feedback
Bugs with Patches
Enhancements with Patches
Release Showstoppers
Stalled Tickets
New Tickets
Horde 5 Showstoppers