diff --git a/framework/Core/lib/Horde/Core/ActiveSync/Connector.php b/framework/Core/lib/Horde/Core/ActiveSync/Connector.php index fdb6b97adcb..345dccee069 100644 --- a/framework/Core/lib/Horde/Core/ActiveSync/Connector.php +++ b/framework/Core/lib/Horde/Core/ActiveSync/Connector.php @@ -294,6 +294,32 @@ public function calendar_move($uid, $source, $target) return $uid; } + /** + * Return an event attachment. + * + * @param string $filereference A filereference pointing to the file: + * calendar:{calendar_id}:{event_uid}:{filename} + * + * @return array An array containing: + * 'content-type' and 'data'. + */ + public function calendar_getAttachment($filereference) + { + if (!$this->_registry->hasMethod( + 'getAttachment', + $this->_registry->hasInterface('calendar'))) { + return false; + } + $fileinfo = explode(':', $filereference, 4); + try { + return $this->_registry->calendar->getAttachment( + $fileinfo[1], $fileinfo[2], $fileinfo[3] + ); + } catch (Horde_Exception $e) { + return false; + } + } + /** * Get a list of all contacts a user can see * diff --git a/framework/Core/lib/Horde/Core/ActiveSync/Driver.php b/framework/Core/lib/Horde/Core/ActiveSync/Driver.php index 96fe843d85a..ffcd823d145 100644 --- a/framework/Core/lib/Horde/Core/ActiveSync/Driver.php +++ b/framework/Core/lib/Horde/Core/ActiveSync/Driver.php @@ -1559,7 +1559,22 @@ public function itemOperationsFetchMailbox( */ public function itemOperationsGetAttachmentData($filereference) { - $att = $this->getAttachment($filereference); + // @todo Slight issue here. Since the filereferences that had previously + // been returned to the client for email attachments only contain + // the mailbox name/uid/part of the message, leaving things as-is would + // mean that a mailbox named 'calendar' would break this code. + // To deal with that cleanly, we really need to prepend 'mail' + // to all email attachments, but this would require a resync of all + // clients to be sure the new filereferences are sent. For now, do + // some sniffing to try to figure it out. + // + // Calendar would have 4 parts, so check that first. + $name_parts = explode(':', $filereference, 4); + if ($name_parts[0] == 'calendar' && !empty($name_parts[3])) { + $att = $atc = $this->_connector->calendar_getAttachment($filereference); + } else { + $att = $this->getAttachment($filereference); + } $airatt = Horde_ActiveSync::messageFactory('AirSyncBaseFileAttachment'); $airatt->data = $att['data']; $airatt->contenttype = $att['content-type']; @@ -1816,8 +1831,12 @@ public function moveMessage($folderid, array $ids, $newfolderid) * Contains the following keys: * - id: (mixed) The UID of the message/item. * - mod: (mixed) A value to indicate the last modification. - * - flags: (array) an empty array if no flag changes. - * - categories: (array|boolean) false if no changes. + * - flags: (array) An array of flag chagnes, empty array if no changes. + * - categories: (array|boolean) An array of EAS categories for email + * messages that exist as IMAP flags, false if no changes. + * - atchash: (array|boolean) An array of clientid->filereference + * mappings for file attachment changes made to appointment + * or draft email folders. @since 2.27.0 */ public function changeMessage($folderid, $id, Horde_ActiveSync_Message_Base $message, $device) { @@ -1849,25 +1868,37 @@ public function changeMessage($folderid, $id, Horde_ActiveSync_Message_Base $mes case Horde_ActiveSync::CLASS_CALENDAR: if (!$id) { try { - $id = $this->_connector->calendar_import($message, $server_id); + // @todo, remove 'import16' hack for H6 + $results = $this->_connector->calendar_import16($message, $server_id); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); $this->_endBuffer(); return false; } - $stat = array('mod' => $this->getSyncStamp($folderid), 'id' => $id, 'flags' => 1); + $stat = array( + 'mod' => $this->getSyncStamp($folderid), + 'id' => $results['uid'], + 'flags' => 1, + 'atchash' => $results['atchash'] + ); } else { // ActiveSync messages do NOT contain the serverUID value, put // it in ourselves so we can have it during import/change. $message->setServerUID($id); try { - $this->_connector->calendar_replace($id, $message, $server_id); + $results = $this->_connector->calendar_replace($id, $message, $server_id); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); $this->_endBuffer(); return false; } $stat = $this->_smartStatMessage($folderid, $id, false); + // @todo Remove this check in H6, when the API always returns. + if (!empty($results)) { + $stat['atchash'] = !empty($results['atchash']) + ? $results['atchash'] + : false; + } } break;