/** * Add/Edit a message * * @param string $folderid The server id of the message's folder. * @param string $id The server's uid for the message if this is a * change to an existing message, false if new. * @param Horde_ActiveSync_Message_Base $message The activesync message. * @param Horde_ActiveSync_Device $device The device information * @since 2.5.0 * * @return array|boolean A stat array if successful, otherwise false. * 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. */ public function changeMessage($folderid, $id, Horde_ActiveSync_Message_Base $message, $device) { $this->_logger->info(sprintf("[%s] Horde_Core_ActiveSync_Driver::changeMessage(%s, %s ...)", $this->_pid, $folderid, $id)); ob_start(); $folder_split = $this->_parseFolderId($folderid); if (is_array($folder_split)) { $folder_class = $folder_split[self::FOLDER_PART_CLASS]; $server_id = $folder_split[self::FOLDER_PART_ID]; } else { $folder_class = $folder_split; $server_id = null; } $stat = false; switch ($folder_class) { case Horde_ActiveSync::CLASS_CALENDAR: if (!$id) { try { $id = $this->_connector->calendar_import($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); } else { // ActiveSync messages do NOT contain the serverUID value, put // it in ourselves so we can have it during import/change. $message->setServerUID($id); if (!empty($device->supported[self::APPOINTMENTS_FOLDER_UID])) { $message->setSupported($device->supported[self::APPOINTMENTS_FOLDER_UID]); } try { $this->_connector->calendar_replace($id, $message); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); $this->_endBuffer(); return false; } $stat = $this->_smartStatMessage($folderid, $id, false); } break; case Horde_ActiveSync::CLASS_CONTACTS: if (!$id) { try { $id = $this->_connector->contacts_import($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); } else { if (!empty($device->supported[self::CONTACTS_FOLDER_UID])) { $message->setSupported($device->supported[self::CONTACTS_FOLDER_UID]); } try { $this->_connector->contacts_replace($id, $message); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); $this->_endBuffer(); return false; } $stat = $this->_smartStatMessage($folderid, $id, false); } break; case Horde_ActiveSync::CLASS_TASKS: if (!$id) { try { $id = $this->_connector->tasks_import($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); } else { if (!empty($device->supported[self::TASKS_FOLDER_UID])) { $message->setSupported($device->supported[self::TASKS_FOLDER_UID]); } try { $this->_connector->tasks_replace($id, $message); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); $this->_endBuffer(); return false; } $stat = $this->_smartStatMessage($folderid, $id, false); } break; case Horde_ActiveSync::CLASS_NOTES: if (!$id) { try { $id = $this->_connector->notes_import($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); } else { if (!empty($device->supported[self::NOTES_FOLDER_UID])) { $message->setSupported($device->supported[self::NOTES_FOLDER_UID]); } try { $this->_connector->notes_replace($id, $message); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); $this->_endBuffer(); return false; } $stat = $this->_smartStatMessage($folderid, $id, false); } break; default: if ($message instanceof Horde_ActiveSync_Message_Mail) { $stat = array('id' => $id, 'mod' => 0, 'flags' => array(), 'categories' => false); if ($message->read !== '') { $this->setReadFlag($folderid, $id, $message->read); $stat['flags'] = array_merge($stat['flags'], array('read' => $message->read)); } if ($message->propertyExists('flag')) { if (!$message->flag) { $message->flag = Horde_ActiveSync::messageFactory('Flag'); } $this->_imap->setMessageFlag($folderid, $id, $message->flag); $stat['flags'] = array_merge($stat['flags'], array('flagged' => $message->flag->flagstatus)); } if ($message->propertyExists('categories')) { // We *try* to make sure the category is added as a custom // IMAP flag. This might fail in some edge cases, like e.g. // with non-ascii characters. $this->_connector->mail_ensureMessageFlags($message->categories); $this->_imap->categoriesToFlags($folderid, $message->categories, $id); $stat['categories'] = $message->categories; } } else { $this->_endBuffer(); return false; } } $this->_endBuffer(); return $stat; }
/** * Add/Edit a message * * @param string $folderid The server id of the message's folder. * @param string $id The server's uid for the message if this is a * change to an existing message, false if new. * @param Horde_ActiveSync_Message_Base $message The activesync message. * @param Horde_ActiveSync_Device $device The device information * @since 2.5.0 * * @return array|boolean A stat array if successful, otherwise false. * Contains the following keys: * - id: (mixed) The UID of the message/item. * - mod: (mixed) A value to indicate the last modification. * - 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 * - conversationid: (hex encoded opaque value) The conversationid value * if adding Draft email message. @since 2.28.0 * - conversationindex: (integer) The conversation index value if adding * Draft email message @since 2.28.0 */ public function changeMessage($folderid, $id, Horde_ActiveSync_Message_Base $message, $device) { $this->_logger->info(sprintf("[%s] Horde_Core_ActiveSync_Driver::changeMessage(%s, %s ...)", $this->_pid, $folderid, $id)); // Short circuit OUTBOX modifications to work around broken clients. if ($folderid == 'OUTBOX') { return false; } ob_start(); $folder_split = $this->_parseFolderId($folderid); if (is_array($folder_split)) { $folder_class = $folder_split[self::FOLDER_PART_CLASS]; $server_id = $folder_split[self::FOLDER_PART_ID]; } else { $folder_class = $folder_split; $server_id = null; } $stat = false; switch ($folder_class) { case Horde_ActiveSync::CLASS_CALENDAR: if (!$id) { try { // @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' => $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 { $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; case Horde_ActiveSync::CLASS_CONTACTS: if (!$id) { try { $id = $this->_connector->contacts_import($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); } else { try { $this->_connector->contacts_replace($id, $message); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); $this->_endBuffer(); return false; } $stat = $this->_smartStatMessage($folderid, $id, false); } break; case Horde_ActiveSync::CLASS_TASKS: if (!$id) { try { $id = $this->_connector->tasks_import($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); } else { try { $this->_connector->tasks_replace($id, $message); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); $this->_endBuffer(); return false; } $stat = $this->_smartStatMessage($folderid, $id, false); } break; case Horde_ActiveSync::CLASS_NOTES: if (!$id) { try { $id = $this->_connector->notes_import($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); } else { try { $this->_connector->notes_replace($id, $message); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); $this->_endBuffer(); return false; } $stat = $this->_smartStatMessage($folderid, $id, false); } break; default: if ($message instanceof Horde_ActiveSync_Message_Mail) { $stat = array('id' => $id, 'mod' => 0, 'flags' => array(), 'categories' => false); // Check for draft sync. if ($this->_version >= Horde_ActiveSync::VERSION_SIXTEEN && $folderid == $this->getSpecialFolderNameByType(self::SPECIAL_DRAFTS)) { // @todo Does this only happen on drafts? if ($message->send) { $this->_logger->err('NOT YET SUPPORTED.'); return $stat; } // Are we addding/changing a draft email? if ($message->airsyncbasebody) { $draft_folder = $this->getSpecialFolderNameByType(self::SPECIAL_DRAFTS); $draft = new Horde_Core_ActiveSync_Mail_Draft($this->_imap, $this->_user, $this->_version); $draft->setDraftMessage($message); // Do we need an existing Draft message? if ($id && !empty($message->airsyncbaseattachments)) { $draft->getExistingDraftMessage($draft_folder, $id); } // Append the message and return results. $results = $draft->append($draft_folder); $stat['id'] = $results['uid']; $stat['atchash'] = $results['atchash']; $stat['conversationid'] = bin2hex($message->subject); $stat['conversationindex'] = time(); return $stat; } } if ($message->read !== '') { $this->setReadFlag($folderid, $id, $message->read); $stat['flags'] = array_merge($stat['flags'], array('read' => $message->read)); // Do RFC 3798 MDN checks. If $message->read is being set to // FLAG_READ_SEEN, then we *might* be able to send one. if ($message->read == Horde_ActiveSync_Message_Mail::FLAG_READ_SEEN) { $this->_logger->info(sprintf("[%s] Checking for MDN", $this->_pid)); $mdn = new Horde_Core_ActiveSync_Mdn($folderid, $id, $this->_imap, $this->_connector); if ($mdn->mdnCheck()) { $this->_logger->info(sprintf("[%s] Sending MDN", $this->_pid)); } } } if ($message->propertyExists('flag')) { if (!$message->flag) { $message->flag = Horde_ActiveSync::messageFactory('Flag'); } $this->_imap->setMessageFlag($folderid, $id, $message->flag); $stat['flags'] = array_merge($stat['flags'], array('flagged' => $message->flag->flagstatus)); } if ($message->propertyExists('categories')) { // We *try* to make sure the category is added as a custom // IMAP flag. This might fail in some edge cases, like e.g. // with non-ascii characters. $this->_connector->mail_ensureMessageFlags($message->categories); $this->_imap->categoriesToFlags($folderid, $message->categories, $id); $stat['categories'] = $message->categories; } } else { $this->_endBuffer(); return false; } } $this->_endBuffer(); return $stat; }