/**
* Handle request
*
* @return boolean
*/
protected function _handle()
{
$this->_logger->info(sprintf('[%s] Handling SEARCH command.', $this->_device->id));
$search_status = self::SEARCH_STATUS_SUCCESS;
$store_status = self::STORE_STATUS_SUCCESS;
$this->_collections = $this->_activeSync->getCollectionsObject();
if (!$this->_decoder->getElementStartTag(self::SEARCH_SEARCH) || !$this->_decoder->getElementStartTag(self::SEARCH_STORE) || !$this->_decoder->getElementStartTag(self::SEARCH_NAME)) {
$search_status = self::SEARCH_STATUS_ERROR;
}
$search_name = $this->_decoder->getElementContent();
if (!$this->_decoder->getElementEndTag()) {
$search_status = self::SEARCH_STATUS_ERROR;
$store_status = self::STORE_STATUS_PROTERR;
}
if (!$this->_decoder->getElementStartTag(self::SEARCH_QUERY)) {
$search_status = self::SEARCH_STATUS_ERROR;
$store_status = self::STORE_STATUS_PROTERR;
}
$search_query = array();
switch (Horde_String::lower($search_name)) {
case 'documentlibrary':
$search_query['query'] = $this->_parseQuery();
break;
case 'mailbox':
$search_query['query'] = $this->_parseQuery();
break;
case 'gal':
$search_query['query'] = $this->_decoder->getElementContent();
}
if (!$this->_decoder->getElementEndTag()) {
$search_status = self::SEARCH_STATUS_ERROR;
$store_status = self::STORE_STATUS_PROTERR;
}
$mime = Horde_ActiveSync::MIME_SUPPORT_NONE;
if ($this->_decoder->getElementStartTag(self::SEARCH_OPTIONS)) {
$searchbodypreference = array();
while (1) {
if ($this->_decoder->getElementStartTag(self::SEARCH_RANGE)) {
$search_query['range'] = $this->_decoder->getElementContent();
if (!$this->_decoder->getElementEndTag()) {
$search_status = self::SEARCH_STATUS_ERROR;
$store_status = self::STORE_STATUS_PROTERR;
}
}
if ($this->_decoder->getElementStartTag(self::SEARCH_DEEPTRAVERSAL)) {
if (!($search_query['deeptraversal'] = $this->_decoder->getElementContent())) {
$search_query['deeptraversal'] = true;
} elseif (!$this->_decoder->getElementEndTag()) {
return false;
}
}
if ($this->_decoder->getElementStartTag(self::SEARCH_REBUILDRESULTS)) {
if (!($search_query['rebuildresults'] = $this->_decoder->getElementContent())) {
$search_query['rebuildresults'] = true;
} elseif (!$this->_decoder->getElementEndTag()) {
return false;
}
}
if ($this->_decoder->getElementStartTag(self::SEARCH_USERNAME)) {
if (!($search_query['username'] = $this->_decoder->getElementContent())) {
return false;
} elseif (!$this->_decoder->getElementEndTag()) {
return false;
}
}
if ($this->_decoder->getElementStartTag(self::SEARCH_PASSWORD)) {
if (!($search_query['password'] = $this->_decoder->getElementContent())) {
return false;
} else {
if (!$this->_decoder->getElementEndTag()) {
return false;
}
}
}
if ($this->_decoder->getElementStartTag(self::SEARCH_SCHEMA)) {
if (!($search_query['schema'] = $this->_decoder->getElementContent())) {
$search_query['schema'] = true;
} elseif (!$this->_decoder->getElementEndTag()) {
return false;
}
}
// 14.1 Only
if ($this->_decoder->getElementStartTag(self::SEARCH_PICTURE)) {
$search_query[self::SEARCH_PICTURE] = true;
if ($this->_decoder->getElementStartTag(self::SEARCH_MAXSIZE)) {
$search_query[self::SEARCH_MAXSIZE] = $this->_decoder->getElementContent();
if (!$this->_decoder->getElementEndTag()) {
return false;
}
}
if ($this->_decoder->getElementStartTag(self::SEARCH_MAXPICTURES)) {
$search_query[self::SEARCH_MAXPICTURES] = $this->_decoder->getElementContent();
if (!$this->_decoder->getElementEndTag()) {
return false;
}
}
}
if ($this->_decoder->getElementStartTag(Horde_ActiveSync::AIRSYNCBASE_BODYPREFERENCE)) {
$this->_bodyPrefs($searchbodypreference);
$searchbodypreference = empty($searchbodypreference['bodyprefs']) ? array() : $searchbodypreference['bodyprefs'];
}
if ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_MIMESUPPORT)) {
$this->_mimeSupport($searchbodypreference);
}
// EAS 14.1
if ($this->_device->version >= Horde_ActiveSync::VERSION_FOURTEENONE) {
$rm = array();
if ($this->_decoder->getElementStartTag(Horde_ActiveSync::RM_SUPPORT)) {
$this->_rightsManagement($rm);
}
if ($this->_decoder->getElementStartTag(Horde_ActiveSync::AIRSYNCBASE_BODYPARTPREFERENCE)) {
$this->_bodyPartPrefs($search_query);
}
}
$e = $this->_decoder->peek();
if ($e[Horde_ActiveSync_Wbxml::EN_TYPE] == Horde_ActiveSync_Wbxml::EN_TYPE_ENDTAG) {
$this->_decoder->getElementEndTag();
break;
}
}
}
if (!$this->_decoder->getElementEndTag()) {
//store
$search_status = self::SEARCH_STATUS_ERROR;
$store_status = self::STORE_STATUS_PROTERR;
}
if (!$this->_decoder->getElementEndTag()) {
//search
$search_status = self::SEARCH_STATUS_ERROR;
$store_status = self::STORE_STATUS_PROTERR;
}
$search_query['range'] = empty($search_query['range']) ? '0-99' : $search_query['range'];
switch (Horde_String::lower($search_name)) {
case 'mailbox':
$search_query['rebuildresults'] = !empty($search_query['rebuildresults']);
$search_query['deeptraversal'] = !empty($search_query['deeptraversal']);
break;
}
// Get search results from backend
$search_result = $this->_driver->getSearchResults($search_name, $search_query);
// @TODO: Remove for H6. Total should be returned from the search call,
// if it's not, do the best we can an use the count of results from
// this page.
if (empty($search_result['total'])) {
$search_result['total'] = count($search_result['rows']);
}
/* Send output */
$this->_encoder->startWBXML();
$this->_encoder->startTag(self::SEARCH_SEARCH);
$this->_encoder->startTag(self::SEARCH_STATUS);
$this->_encoder->content($search_status);
$this->_encoder->endTag();
$this->_encoder->startTag(self::SEARCH_RESPONSE);
$this->_encoder->startTag(self::SEARCH_STORE);
$this->_encoder->startTag(self::SEARCH_STATUS);
$this->_encoder->content($store_status);
$this->_encoder->endTag();
if (is_array($search_result['rows']) && !empty($search_result['rows'])) {
$count = 0;
foreach ($search_result['rows'] as $u) {
$count++;
switch (Horde_String::lower($search_name)) {
case 'documentlibrary':
$this->_encoder->startTag(self::SEARCH_RESULT);
$doc = Horde_ActiveSync::messageFactory('DocumentLibrary');
$doc->linkid = $u['linkid'];
$doc->displayname = $u['name'];
$doc->isfolder = $u['is_folder'] ? '1' : '0';
$doc->creationdate = $u['created'];
$doc->lastmodifieddate = $u['modified'];
$doc->ishidden = '0';
$doc->contentlength = $u['content-length'];
if (!empty($u['content-type'])) {
$doc->contenttype = $u['content-type'];
}
$this->_encoder->startTag(self::SEARCH_PROPERTIES);
$doc->encodeStream($this->_encoder);
$this->_encoder->endTag();
$this->_encoder->endTag();
continue;
case 'gal':
$this->_encoder->startTag(self::SEARCH_RESULT);
$this->_encoder->startTag(self::SEARCH_PROPERTIES);
$this->_encoder->startTag(Horde_ActiveSync::GAL_DISPLAYNAME);
$this->_encoder->content($u[Horde_ActiveSync::GAL_DISPLAYNAME]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_PHONE);
$this->_encoder->content($u[Horde_ActiveSync::GAL_PHONE]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_OFFICE);
$this->_encoder->content($u[Horde_ActiveSync::GAL_OFFICE]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_TITLE);
$this->_encoder->content($u[Horde_ActiveSync::GAL_TITLE]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_COMPANY);
$this->_encoder->content($u[Horde_ActiveSync::GAL_COMPANY]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_ALIAS);
$this->_encoder->content($u[Horde_ActiveSync::GAL_ALIAS]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_FIRSTNAME);
$this->_encoder->content($u[Horde_ActiveSync::GAL_FIRSTNAME]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_LASTNAME);
$this->_encoder->content($u[Horde_ActiveSync::GAL_LASTNAME]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_HOMEPHONE);
$this->_encoder->content($u[Horde_ActiveSync::GAL_HOMEPHONE]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_MOBILEPHONE);
$this->_encoder->content($u[Horde_ActiveSync::GAL_MOBILEPHONE]);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::GAL_EMAILADDRESS);
$this->_encoder->content($u[Horde_ActiveSync::GAL_EMAILADDRESS]);
$this->_encoder->endTag();
if ($this->_device->version >= Horde_ActiveSync::VERSION_FOURTEENONE && !empty($u[Horde_ActiveSync::GAL_PICTURE])) {
$this->_encoder->startTag(Horde_ActiveSync::GAL_PICTURE);
$u[Horde_ActiveSync::GAL_PICTURE]->encodeStream($this->_encoder);
$this->_encoder->endTag();
}
$this->_encoder->endTag();
//properties
$this->_encoder->endTag();
//result
break;
case 'mailbox':
$this->_encoder->startTag(self::SEARCH_RESULT);
$this->_encoder->startTag(Horde_ActiveSync::SYNC_FOLDERTYPE);
$this->_encoder->content(Horde_ActiveSync::CLASS_EMAIL);
$this->_encoder->endTag();
$this->_encoder->startTag(self::SEARCH_LONGID);
$this->_encoder->content($u['uniqueid']);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::SYNC_FOLDERID);
$this->_encoder->content($this->_collections->getFolderUidForBackendId($u['searchfolderid']));
$this->_encoder->endTag();
$this->_encoder->startTag(self::SEARCH_PROPERTIES);
$msg = $this->_driver->ItemOperationsFetchMailbox($u['uniqueid'], $searchbodypreference, $mime);
$msg->encodeStream($this->_encoder);
$this->_encoder->endTag();
//properties
$this->_encoder->endTag();
//result
}
}
if (!empty($search_query['range'])) {
$range = explode('-', $search_query['range']);
// If total results are less than max range,
// we have all results and must modify the returned range.
if ($count < $range[1] - $range[0] + 1) {
$search_range = $range[0] . '-' . ($count - 1);
} else {
$search_range = $search_query['range'];
}
}
$this->_encoder->startTag(self::SEARCH_RANGE);
$this->_encoder->content($search_range);
$this->_encoder->endTag();
$this->_encoder->startTag(self::SEARCH_TOTAL);
$this->_encoder->content($search_result['total']);
$this->_encoder->endTag();
}
$this->_encoder->endTag();
//store
$this->_encoder->endTag();
//response
$this->_encoder->endTag();
//search
return true;
}