Skip to content

Commit

Permalink
Support container elements containing multiple object types.
Browse files Browse the repository at this point in the history
  • Loading branch information
mrubinsk committed Sep 10, 2016
1 parent 2509c98 commit 2f1516c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 23 deletions.
Expand Up @@ -259,13 +259,17 @@ public function __construct(array $options = array())
Horde_ActiveSync::AIRSYNCBASE_LOCATION => array(self::KEY_ATTRIBUTE => 'location', self::KEY_TYPE => 'Horde_ActiveSync_Message_AirSyncBaseLocation'),
self::POOMCAL_CLIENTUID => array(self::KEY_ATTRIBUTE => 'clientuid'),
Horde_ActiveSync::AIRSYNCBASE_INSTANCEID => array(self::KEY_ATTRIBUTE => 'instanceid', self::KEY_TYPE => self::TYPE_DATE),
Horde_ActiveSync::AIRSYNCBASE_ATTACHMENTS => array(self::KEY_ATTRIBUTE => 'airsyncbaseattachments', self::KEY_TYPE => 'Horde_ActiveSync_Message_AirSyncBaseAttachments')
Horde_ActiveSync::AIRSYNCBASE_ATTACHMENTS => array(
self::KEY_ATTRIBUTE => 'airsyncbaseattachments',
self::KEY_TYPE => array('Horde_ActiveSync_Message_AirSyncBaseAttachment', 'Horde_ActiveSync_Message_AirSyncBaseAdd', 'Horde_ActiveSync_Message_AirSyncBaseDelete'),
self::KEY_VALUES => array(Horde_ActiveSync::AIRSYNCBASE_ATTACHMENT, Horde_ActiveSync::AIRSYNCBASE_ADD, Horde_ActiveSync::AIRSYNCBASE_DELETE)
),
);
$this->_properties += array(
'location' => false,
'clientuid' => false,
'instanceid' => false,
'airsyncbaseattachments' => false
'airsyncbaseattachments' => array(),
);
}
}
Expand Down
65 changes: 46 additions & 19 deletions framework/ActiveSync/lib/Horde/ActiveSync/Message/Base.php
Expand Up @@ -51,7 +51,6 @@ class Horde_ActiveSync_Message_Base
const TYPE_MAPI_GOID = 5;
const TYPE_DATE_LOCAL = 6;
const PROPERTY_NO_CONTAINER = 7;
const PROPERTY_MULTI_ARRAY = 8;

/**
* Holds the mapping for object properties
Expand Down Expand Up @@ -374,13 +373,38 @@ public function decodeStream(Horde_ActiveSync_Wbxml_Decoder &$decoder)
if (isset($map[self::KEY_VALUES])) {
// Handle arrays of attribute values
while (1) {
// Do not get start tag for an array without a container
if (!(isset($map[self::KEY_PROPERTY]) &&
$map[self::KEY_PROPERTY] == self::PROPERTY_NO_CONTAINER) &&
!$decoder->getElementStartTag($map[self::KEY_VALUES])) {
// If we can have multiple types of objects in this
// container, or we are parsing a NO_CONTAINER,
// check that we are not at the end tag of the
// or we have a valid start tag for the NO_CONTAINER
// object. If not, break out of loop.
if (is_array($map[self::KEY_VALUES])) {
$token = $decoder->peek();
if ($token[Horde_ActiveSync_Wbxml_Decoder::EN_TYPE] == Horde_ActiveSync_Wbxml_Decoder::EN_TYPE_ENDTAG) {
break;
}
} elseif (!(isset($map[self::KEY_PROPERTY]) && $map[self::KEY_PROPERTY] == self::PROPERTY_NO_CONTAINER) &&
!$decoder->getElementStartTag($map[self::KEY_VALUES])) {
break;
}
if (isset($map[self::KEY_TYPE])) {

// We know we have some valid value, parse out what
// it is. Either an array of (possibly varied)
// objects, a single object, or simple value.
if (is_array($map[self::KEY_VALUES])) {
$token = $decoder->getToken();
if (($idx = array_search($token[Horde_ActiveSync_Wbxml_Decoder::EN_TAG], $map[self::KEY_VALUES])) !== false) {
$class = $map[self::KEY_TYPE][$idx];
$decoded = new $class(array(
'protocolversion' => $this->_version,
'logger' => $this->_logger)
);
$decoded->commandType = $this->commandType;
$decoded->decodeStream($decoder);
} else {
throw new Horde_ActiveSync_Exception('Error in message map configuration');
}
} elseif (isset($map[self::KEY_TYPE])) {
$class = $map[self::KEY_TYPE];
$decoded = new $class(array(
'protocolversion' => $this->_version,
Expand All @@ -391,14 +415,21 @@ public function decodeStream(Horde_ActiveSync_Wbxml_Decoder &$decoder)
} else {
$decoded = $decoder->getElementContent();
}

// Assign the parsed value to the mapped attribute.
if (!isset($this->{$map[self::KEY_ATTRIBUTE]})) {
$this->{$map[self::KEY_ATTRIBUTE]} = array($decoded);
} else {
$this->{$map[self::KEY_ATTRIBUTE]}[] = $decoded;
}

// Get the end tag of this attribute node.
if (!$decoder->getElementEndTag()) {
throw new Horde_ActiveSync_Exception('Missing expected wbxml end tag');
}

// For NO_CONTAINER attributes, need some magic to
// make sure we break out properly.
if (isset($map[self::KEY_PROPERTY]) && $map[self::KEY_PROPERTY] == self::PROPERTY_NO_CONTAINER) {
$e = $decoder->peek();
// Go back to the initial while if another block
Expand Down Expand Up @@ -455,18 +486,7 @@ public function decodeStream(Horde_ActiveSync_Wbxml_Decoder &$decoder)
);
throw new Horde_ActiveSync_Exception('Missing expected wbxml end tag');
}
// If we have a container that can hold multiple
// properties that are also containers, but not all of
// the same type, we have to hanlde separately.
if (isset($map[self::KEY_PROPERTY]) &&
$map[self::KEY_PROPERTY] == self::PROPERTY_MULTI_ARRAY) {
if (!is_array($this->{$map[self::KEY_ATTRIBUTE]})) {
$this->{$map[self::KEY_ATTRIBUTE]} = array();
}
$this->{$map[self::KEY_ATTRIBUTE]}[] = $decoded;
} else {
$this->{$map[self::KEY_ATTRIBUTE]} = $decoded;
}
$this->{$map[self::KEY_ATTRIBUTE]} = $decoded;
}
}
} elseif ($entity[Horde_ActiveSync_Wbxml::EN_TYPE] == Horde_ActiveSync_Wbxml::EN_TYPE_ENDTAG) {
Expand Down Expand Up @@ -525,8 +545,15 @@ public function encodeStream(Horde_ActiveSync_Wbxml_Encoder &$encoder)
}
foreach ($this->{$map[self::KEY_ATTRIBUTE]} as $element) {
if (is_object($element)) {
// Hanlde multi-typed array containers.
if (is_array($map[self::KEY_VALUES])) {
$idx = array_search(get_class($element), $map[self::KEY_TYPE]);
$tag = $map[self::KEY_VALUES][$idx];
} else {
$tag = $map[self::KEY_VALUES];
}
// Outputs object container (eg Attachment)
$encoder->startTag($map[self::KEY_VALUES]);
$encoder->startTag($tag);
$element->encodeStream($encoder);
$encoder->endTag();
} else {
Expand Down
8 changes: 6 additions & 2 deletions framework/ActiveSync/lib/Horde/ActiveSync/Message/Mail.php
Expand Up @@ -255,15 +255,19 @@ public function __construct(array $options = array())
$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),
Horde_ActiveSync::AIRSYNCBASE_ATTACHMENTS => array(
self::KEY_ATTRIBUTE => 'airsyncbaseattachments',
self::KEY_TYPE => array('Horde_ActiveSync_Message_AirSyncBaseAttachment', 'Horde_ActiveSync_Message_AirSyncBaseAdd', 'Horde_ActiveSync_Message_AirSyncBaseDelete'),
self::KEY_VALUES => array(Horde_ActiveSync::AIRSYNCBASE_ATTACHMENT, Horde_ActiveSync::AIRSYNCBASE_ADD, Horde_ActiveSync::AIRSYNCBASE_DELETE),
),
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,
'airsyncbaseattachments' => array(),
'contentclass' => false,
'flag' => false,
);
Expand Down

0 comments on commit 2f1516c

Please sign in to comment.