/** * Send a message change over the wbxml stream * * @param string $id The uid of the message * @param Horde_ActiveSync_Message_Base $message The message object */ public function messageChange($id, Horde_ActiveSync_Message_Base $message) { // Just ignore any messages that are not from this collection and // prevent sending the same object twice in one request. if ($message->getClass() != $this->_currentCollection['class'] || in_array($id, $this->_seenObjects)) { $this->_logger->notice(sprintf('[%s] IGNORING message %s since it looks like it was already sent or does not belong to this collection. Class: %s, CurrentClass: %s', $this->_procid, $id, $message->getClass(), $this->_currentCollection['class'])); return; } // Ignore any empty objects. if ($message->isEmpty()) { $this->_logger->notice(sprintf('[%s] IGNORING message %s since it looks like it does not contain any data. Class: %s, CurrentClass: %s', $this->_procid, $id, $message->getClass(), $this->_currentCollection['class'])); return; } // Remember this message $this->_seenObjects[] = $id; // Specify if this is an ADD or a MODIFY change? if ($message->flags === Horde_ActiveSync::FLAG_NEWMESSAGE) { $this->_encoder->startTag(Horde_ActiveSync::SYNC_ADD); } else { $this->_encoder->startTag(Horde_ActiveSync::SYNC_MODIFY); } // Send the message $this->_encoder->startTag(Horde_ActiveSync::SYNC_SERVERENTRYID); $this->_encoder->content($id); $this->_encoder->endTag(); $this->_encoder->startTag(Horde_ActiveSync::SYNC_DATA); try { $message->encodeStream($this->_encoder); } catch (Horde_ActiveSync_Exception $e) { $this->_logger->err($e); } $this->_encoder->endTag(); $this->_encoder->endTag(); }
/** * Const'r * * @see Horde_ActiveSync_Message_Base::__construct() */ public function __construct(array $options = array()) { parent::__construct($options); if ($this->_version >= Horde_ActiveSync::VERSION_FOURTEEN) { $this->_mapping += array(Horde_ActiveSync::AIRSYNCBASE_PREVIEW => array(self::KEY_ATTRIBUTE => 'preview')); $this->_properties += array('preview' => false); } }
/** * Const'r * * @see Horde_ActiveSync_Message_Base::__construct() */ public function __construct(array $options = array()) { parent::__construct($options); if ($this->_version > Horde_ActiveSync::VERSION_FOURTEEN) { $this->_mapping += array(Horde_ActiveSync_Message_Mail::POOMMAIL2_MEETINGMESSAGETYPE => array(self::KEY_ATTRIBUTE => 'meetingmessagetype')); $this->_properties += array('meetingmessagetype' => false); } }
/** * Const'r * * @see Horde_ActiveSync_Message_Base::__construct() */ public function __construct(array $options = array()) { parent::__construct($options); if ($this->_version < Horde_ActiveSync::VERSION_TWELVE) { $this->_mapping += array(self::POOMCAL_BODY => array(self::KEY_ATTRIBUTE => 'body'), self::POOMCAL_BODYTRUNCATED => array(self::KEY_ATTRIBUTE => 'bodytruncated'), self::POOMCAL_RTF => array(self::KEY_ATTRIBUTE => 'rtf')); $this->_properties += array('body' => false, 'bodytruncated' => 0, 'rtf' => false); } else { $this->_mapping += array(Horde_ActiveSync::AIRSYNCBASE_BODY => array(self::KEY_ATTRIBUTE => 'airsyncbasebody', self::KEY_TYPE => 'Horde_ActiveSync_Message_AirSyncBaseBody')); $this->_properties += array('airsyncbasebody' => false); if ($this->_version >= Horde_ActiveSync::VERSION_FOURTEEN) { $this->_mapping += array(self::POOMCAL_RESPONSEREQUESTED => array(self::KEY_ATTRIBUTE => 'responserequested'), self::POOMCAL_APPOINTMENTREPLYTIME => array(self::KEY_ATTRIBUTE => 'appointmentreplytime', self::KEY_TYPE => self::TYPE_DATE_DASHES), self::POOMCAL_RESPONSETYPE => array(self::KEY_ATTRIBUTE => 'responsetype'), self::POOMCAL_DISALLOWNEWTIMEPROPOSAL => array(self::KEY_ATTRIBUTE => 'disallownewtimeproposal')); $this->_properties += array('disallownewtimeproposal' => false, 'responserequested' => false, 'appointmentreplytime' => false, 'responsetype' => false); } if ($this->_version >= Horde_ActiveSync::VERSION_FOURTEENONE) { $this->_mapping += array(self::POOMCAL_ONLINECONFLINK => array(self::KEY_ATTRIBUTE => 'onlinemeetingconflink'), self::POOMCAL_ONLINEEXTLINK => array(self::KEY_ATTRIBUTE => 'onlinemeetingexternallink')); $this->_properties += array('onlinemeetingconflink' => false, 'onlinemeetingexternallink' => false); } } }
/** * Const'r * * @see Horde_ActiveSync_Message_Base::__construct() */ public function __construct(array $options = array()) { parent::__construct($options); if ($this->_version < Horde_ActiveSync::VERSION_TWELVE) { $this->_mapping += array(self::POOMTASKS_BODY => array(self::KEY_ATTRIBUTE => 'body'), self::POOMTASKS_RTF => array(self::KEY_ATTRIBUTE => 'rtf'), self::POOMTASKS_BODYTRUNCATED => array(self::KEY_ATTRIBUTE => 'bodytruncated')); $this->_properties += array('body' => false, 'rtf' => false, 'bodytruncated' => 0); } else { $this->_mapping += array(Horde_ActiveSync::AIRSYNCBASE_BODY => array(self::KEY_ATTRIBUTE => 'airsyncbasebody', self::KEY_TYPE => 'Horde_ActiveSync_Message_AirSyncBaseBody')); $this->_properties += array('airsyncbasebody' => false); } }
/** * Const'r * * @see Horde_ActiveSync_Message_Base::__construct() */ public function __construct(array $options = array()) { parent::__construct($options); if ($this->_version >= Horde_ActiveSync::VERSION_FOURTEEN) { $this->_mapping += array(Horde_ActiveSync_Message_Appointment::POOMCAL_CALENDARTYPE => array(self::KEY_ATTRIBUTE => 'calendartype'), Horde_ActiveSync_Message_Appointment::POOMCAL_ISLEAPMONTH => array(self::KEY_ATTRIBUTE => 'isleapmonth')); $this->_properties += array('calendartype' => false, 'isleapmonth' => false); } if ($this->_version == Horde_ActiveSync::VERSION_FOURTEENONE) { $this->_mapping += array(Horde_ActiveSync_Message_Appointment::POOMCAL_FIRSTDAYOFWEEK => array(self::KEY_ATTRIBUTE => 'firstdayofweek')); $this->_properties += array('firstdayofweek' => false); } }
protected function _formatDate(Horde_Date $dt, $type) { if (empty($this->_device)) { $date = $dt; } else { $date = $this->_device->normalizePoomContactsDates($dt, true); } return parent::_formatDate($date, $type); }
/** * Determines if the property specified has been ghosted by the client. * A ghosted property 1) IS listed in the supported list and 2) NOT * present in the current message. If it's IN the supported list and NOT * in the current message, then it IS ghosted and the server should keep * the field's current value when performing any change action due to this * message. * * @param string $property The property to check * * @return boolean */ public function isGhosted($property) { $isGhosted = parent::isGhosted($property); if (!$isGhosted && $property == self::PICTURE && $this->_device->hasQuirk(Horde_ActiveSYnc_Device::QUIRK_NEEDS_SUPPORTED_PICTURE_TAG)) { return true; } return $isGhosted; }
/** * Determines if the property specified has been ghosted by the client. * A property is ghosted if it is NOT listed in the SUPPORTED list sent * by the client AND is NOT present in the request data. * * @param string $property The property to check * @param array $options An array of options: * - ignoreEmptyPictureTagCheck: boolean If true, will not check for the * QUIRK_INCORRECTLY_SENDS_EMPTY_PICTURE_TAG quirk. @since 2.32.0 * * @return boolean */ public function isGhosted($property, $options = array()) { // MS-ASCMD 2.2.3.168: // An empty SUPPORTED container indicates that ALL elements able to be // ghosted ARE ghosted. A *missing* SUPPORTED tag indicates that NO // fields are ghosted - any ghostable properties are always considered // NOT ghosted. Some clients like iOS 4.x screw this up by not sending // any SUPPORTED container and also not sending the picture field during // edits. if ($property == $this->_mapping[self::PICTURE][self::KEY_ATTRIBUTE]) { if (empty($options['ignoreEmptyPictureTagCheck']) && $this->_device->hasQuirk(Horde_ActiveSync_Device::QUIRK_INCORRECTLY_SENDS_EMPTY_PICTURE_TAG) && (!empty($this->_exists[$property]) && $this->{$property} == '' || empty($this->_exists[$property]))) { return true; } if (empty($this->_exists[$property]) && empty($this->_supported) && $this->_device->hasQuirk(Horde_ActiveSync_Device::QUIRK_NEEDS_SUPPORTED_PICTURE_TAG)) { return true; } } return parent::isGhosted($property); }
/** * Const'r * * @see Horde_ActiveSync_Message_Base::__construct() */ public function __construct(array $options = array()) { parent::__construct($options); if ($this->_version == Horde_ActiveSync::VERSION_TWOFIVE) { $this->_mapping += array(self::POOMMAIL_ATTACHMENTS => array(self::KEY_ATTRIBUTE => 'attachments', self::KEY_TYPE => 'Horde_ActiveSync_Message_Attachment', self::KEY_VALUES => self::POOMMAIL_ATTACHMENT), self::POOMMAIL_BODYTRUNCATED => array(self::KEY_ATTRIBUTE => 'bodytruncated'), self::POOMMAIL_BODYSIZE => array(self::KEY_ATTRIBUTE => 'bodysize'), self::POOMMAIL_BODY => array(self::KEY_ATTRIBUTE => 'body')); $this->_properties += array('attachments' => false, 'bodytruncated' => false, 'bodysize' => false, 'body' => false); } if ($this->_version >= Horde_ActiveSync::VERSION_TWELVE) { $this->_mapping += array(Horde_ActiveSync::AIRSYNCBASE_NATIVEBODYTYPE => array(self::KEY_ATTRIBUTE => 'airsyncbasenativebodytype'), Horde_ActiveSync::AIRSYNCBASE_BODY => array(self::KEY_ATTRIBUTE => 'airsyncbasebody', self::KEY_TYPE => 'Horde_ActiveSync_Message_AirSyncBaseBody'), Horde_ActiveSync::AIRSYNCBASE_ATTACHMENTS => array(self::KEY_ATTRIBUTE => 'airsyncbaseattachments', self::KEY_TYPE => 'Horde_ActiveSync_Message_AirSyncBaseAttachment', self::KEY_VALUES => Horde_ActiveSync::AIRSYNCBASE_ATTACHMENT), self::POOMMAIL_FLAG => array(self::KEY_ATTRIBUTE => 'flag', self::KEY_TYPE => 'Horde_ActiveSync_Message_Flag'), self::POOMMAIL_CONTENTCLASS => array(self::KEY_ATTRIBUTE => 'contentclass')); $this->_properties += array('airsyncbasenativebodytype' => false, 'airsyncbasebody' => false, 'airsyncbaseattachments' => false, 'contentclass' => false, 'flag' => false); if ($this->_version >= Horde_ActiveSync::VERSION_FOURTEEN) { $this->_mapping += array(self::POOMMAIL_CATEGORIES => array(self::KEY_ATTRIBUTE => 'categories', self::KEY_VALUES => self::POOMMAIL_CATEGORY), self::POOMMAIL_CATEGORY => array(self::KEY_ATTRIBUTE => 'category'), self::POOMMAIL2_UMCALLERID => array(self::KEY_ATTRIBUTE => 'umcallerid'), self::POOMMAIL2_UMUSERNOTES => array(self::KEY_ATTRIBUTE => 'umusernotes'), self::POOMMAIL2_UMATTDURATION => array(self::KEY_ATTRIBUTE => 'umattduration'), self::POOMMAIL2_UMATTORDER => array(self::KEY_ATTRIBUTE => 'umattorder'), self::POOMMAIL2_CONVERSATIONID => array(self::KEY_ATTRIBUTE => 'conversationid'), self::POOMMAIL2_CONVERSATIONINDEX => array(self::KEY_ATTRIBUTE => 'conversationindex'), self::POOMMAIL2_LASTVERBEXECUTED => array(self::KEY_ATTRIBUTE => 'lastverbexecuted'), self::POOMMAIL2_LASTVERBEXECUTIONTIME => array(self::KEY_ATTRIBUTE => 'lastverbexecutiontime', self::KEY_TYPE => self::TYPE_DATE_DASHES), self::POOMMAIL2_RECEIVEDASBCC => array(self::KEY_ATTRIBUTE => 'receivedasbcc'), self::POOMMAIL2_SENDER => array(self::KEY_ATTRIBUTE => 'sender'), self::POOMMAIL2_CALENDARTYPE => array(self::KEY_ATTRIBUTE => 'calendartype'), self::POOMMAIL2_ISLEAPMONTH => array(self::KEY_ATTRIBUTE => 'isleapmonth'), self::POOMMAIL2_ACCOUNTID => array(self::KEY_ATTRIBUTE => 'accountid'), self::POOMMAIL2_FIRSTDAYOFWEEK => array(self::KEY_ATTRIBUTE => 'firstdayofweek')); $this->_properties += array('umcallerid' => false, 'umusernotes' => false, 'umattduration' => false, 'umattorder' => false, 'conversationid' => false, 'conversationindex' => false, 'lastverbexecuted' => false, 'lastverbexecutiontime' => false, 'receivedasbcc' => false, 'sender' => false, 'calendartype' => false, 'isleapmonth' => false, 'accountid' => false, 'firstdayofweek' => false, 'categories' => array(), 'messageid' => false, 'answered' => false, 'forwarded' => false); } if ($this->_version > Horde_ActiveSync::VERSION_FOURTEEN) { $this->_mapping += array(Horde_ActiveSync::AIRSYNCBASE_BODYPART => array(self::KEY_ATTRIBUTE => 'airsyncbasebodypart', self::KEY_TYPE => 'Horde_ActiveSync_Message_AirSyncBaseBodypart')); $this->_properties += array('airsyncbasebodypart' => false); } } }
public function &__get($property) { // The saveinsent is an empty tag, and is considered true if it is // present. // Deal with the empty tags that are considered true if they are present switch ($property) { case 'saveinsent': case 'replacemime': $return = $this->_properties[$property] !== false; return $return; } return parent::__get($property); }
/** * Override parent class' method. In EAS 16.0, top level appointment * properties are ALWAYS ghosted if they are not explicitly sent. * * @param string $property The property to check * * @return boolean */ public function isGhosted($property) { if ($this->_version >= Horde_ActiveSync::VERSION_SIXTEEN && empty($this->_exists[$property])) { return true; } return parent::isGhosted($property); }
/** * Import a message change from the wbxml stream * * @param string|boolean $id A server message id or * false if a new message. * @param Horde_ActiveSync_Message_Base $message A message object * @param Horde_ActiveSync_Device $device A device descriptor * @param integer $clientid Client id sent from client. * on message addition. * @param string $class The collection class - needed for SMS since the * actual serverid will be for an email folder. * @since 2.6.0 * @param string $synckey The synckey currently being processed when * processing a SYNC_MODIFY command. * @since 2.31.0 * * @todo Revisit passing $class for SMS. Probably pass class in the * const'r. * * @return array|boolean A stat array, or an array containing the 'error' * key on error, or false on duplicate addition. */ public function importMessageChange($id, Horde_ActiveSync_Message_Base $message, Horde_ActiveSync_Device $device, $clientid, $class = false, $synckey = false) { // Don't support SMS, but can't tell client that. Send back a phoney // UID for any imported SMS objects. if ($class == Horde_ActiveSync::CLASS_SMS || strpos($id, 'IGNORESMS_') === 0) { return 'IGNORESMS_' . $clientid; } // Changing an existing object if ($id && $this->_flags == Horde_ActiveSync::CONFLICT_OVERWRITE_PIM) { // This is complicated by the fact that in EAS 16.0, clients // will send a CHANGE for adding/editing an exception along with // a seperate change with the entire appointment - even if nothing // else has changed. This leads to conficts (since the appointment // is marked as changed after the first edit). Sniff that out here // and prevent the conflict check for those messages. if (!$message instanceof Horde_ActiveSync_Message_Appointment && $this->_state->isDuplicatePIMChange($id, $synckey)) { $conflict = $this->_isConflict(Horde_ActiveSync::CHANGE_TYPE_CHANGE, $this->_folderId, $id); if ($conflict) { $this->_logger->notice(sprintf('[%s] Conflict when updating %s, will overwrite client version on next sync.', $this->_procid, $id)); return array($id, 'error' => array(Horde_ActiveSync_Request_Sync::STATUS_CONFLICT)); } } } elseif (!$id && ($uid = $this->_state->isDuplicatePIMAddition($clientid))) { // Already saw this addition, but client never received UID $this->_logger->notice(sprintf('[%s] Duplicate addition for %s', $this->_procid, $uid)); return $uid; } // Set the supported/ghosted data if this is a SYNC_MODIFY. if ($id && !empty($device->supported[$class])) { $message->setSupported($device->supported[$class]); } // Tell the backend about the change if (!($stat = $this->_as->driver->changeMessage($this->_folderId, $id, $message, $device))) { $this->_logger->err(sprintf('[%s] Change message failed when updating %s', $this->_procid, $id)); return $id ? array(0 => $id, 'error' => Horde_ActiveSync_Request_Sync::STATUS_NOTFOUND) : array(0 => false, 'error' => Horde_ActiveSync_Request_Sync::STATUS_SERVERERROR); } $stat['serverid'] = $this->_folderId; // Record the state of the message. // Email messages are only changed if they are Drafts or if we are // updating flags. // When CHANGING a draft message, we are actually deleting the old one // and replacing it with a message (since we can't edit an existing // IMAP message while keeping the UID the same). So, do not call // updateState() for these messages since we don't want to ignore // this as a PIM sourced change - the change will be caught during // normal ping/sync cycle. if ($message instanceof Horde_ActiveSync_Message_Mail) { if (!empty($message->airsyncbasebody) && !empty($id)) { // Changing an existing Draft mail. return $stat; } // Either a flag change, or adding a new Draft mail. $changeType = !empty($message->airsyncbasebody) ? Horde_ActiveSync::CHANGE_TYPE_DRAFT : Horde_ActiveSync::CHANGE_TYPE_FLAGS; } else { $changeType = Horde_ActiveSync::CHANGE_TYPE_CHANGE; } $this->_state->updateState($changeType, $stat, Horde_ActiveSync::CHANGE_ORIGIN_PIM, $this->_as->driver->getUser(), $clientid); return $stat; }
/** * Set the list of non-ghosted fields for this message. * * @param array $fields The array of fields. */ public function setSupported(array $fields) { // See if we need to explicitly add the picture tag to the supported list. parent::setSupported($fields); if ($this->_device->hasQuirk(Horde_ActiveSync_Device::QUIRK_NEEDS_SUPPORTED_PICTURE_TAG) && !in_array($this->_mapping[self::PICTURE][self::KEY_ATTRIBUTE], $this->_supported)) { $this->_supported[] = $this->_mapping[self::PICTURE][self::KEY_ATTRIBUTE]; } }