diff --git a/kronolith/lib/Event.php b/kronolith/lib/Event.php index a66159c1997..250867aebb3 100644 --- a/kronolith/lib/Event.php +++ b/kronolith/lib/Event.php @@ -1926,6 +1926,60 @@ public function fromASAppointment(Horde_ActiveSync_Message_Appointment $message) $this->initialized = true; } + /** + * @todo Do we need to update History here too? + */ + public function addEASFiles($message) + { + $results = array( + 'add' => array(), + 'delete' => array() + ); + // EAS 16.0 + $supported = true; + if ($message->getProtocolVersion() < Horde_ActiveSync::VERSION_SIXTEEN || + !$this->id) { + $not_supported = true; + } + + if ($att = $message->airsyncbaseattachments) { + if ($att->add) { + foreach ($att->add as $add) { + if (!$supported) { + $results['add'][$add->clientid] = false; + continue; + } + $info = $this->_addEASFile($add); + $results['add'][$add->clientid] = $this->_getEASFileReference($info['name']); + } + } + if ($att->delete) { + foreach ($atcs->delete as $del_ob) { + $file_parts = explode(':', $del_ob->filereference, 4); + $this->deleteFile($file_parts[3]); + } + } + } + + return $results; + } + + protected function _getEASFileReference($filename) + { + return sprintf('calendar:%s:%s:%s', $this->calendar, $this->uid, $filename); + } + + protected function _addEASFile(Horde_ActiveSync_Message_AirSyncBaseAdd $add) + { + $info = array( + 'name' => empty($add->displayname) ? 'Untitled' : $add->displayname, + 'data' => $add->content + ); + $this->addFileFromData($info); + + return $info; + } + /** * Export this event as a MS ActiveSync Message * @@ -2278,6 +2332,33 @@ public function toASAppointment(array $options = array()) $message->onlinemeetingexternallink = $this->url; } + // 16.0 + if ($options['protocolversion'] >= Horde_ActiveSync::VERSION_SIXTEEN) { + $files = $this->listFiles(); + if (count($files)) { + $message->airsyncbaseattachments = new Horde_ActiveSync_Message_AirSyncBaseAttachments( + array( + 'logger' => $GLOBALS['injector']->getInstance('Horde_Log_Logger'), + 'protocolversion' => $options['protocolversion'] + ) + ); + $message->airsyncbaseattachments->attachment = array(); + foreach ($files as $file) { + $atc = new Horde_ActiveSync_Message_AirSyncBaseAttachment( + array( + 'logger' => $GLOBALS['injector']->getInstance('Horde_Log_Logger'), + 'protocolversion' => $options['protocolversion'] + ) + ); + $atc->displayname = $file['name']; + $atc->attname = $this->_getEASFileReference($file['name']); + $atc->attmethod = Horde_ActiveSync_Message_AirSyncBaseAttachment::ATT_TYPE_NORMAL; + $atc->attsize = $file['size']; + $message->airsyncbaseattachments->attachment[] = $atc; + } + } + } + return $message; } @@ -4211,6 +4292,34 @@ public function addFile(array $info) } } + public function addFileFromData($info) + { + if (empty($this->uid)) { + throw new Kronolith_Exception("VFS not supported until object saved"); + } + + $vfs = $this->vfsInit(); + $dir = Kronolith::VFS_PATH . '/' . $this->getVfsUid(); + $file = $info['name']; + while ($vfs->exists($dir, $file)) { + if (preg_match('/(.*)\[(\d+)\](\.[^.]*)?$/', $file, $match)) { + $file = $match[1] . '[' . ++$match[2] . ']' . $match[3]; + } else { + $dot = strrpos($file, '.'); + if ($dot === false) { + $file .= '[1]'; + } else { + $file = substr($file, 0, $dot) . '[1]' . substr($file, $dot); + } + } + } + try { + $vfs->writeData($dir, $file, $info['data'], true); + } catch (Horde_Vfs_Exception $e) { + throw new Kronolith_Exception($e); + } + } + /** * Deletes a file from the VFS backend associated with this event. *