public static function GetCalendarRestriction($store, $timestamp) { // This is our viewing window $start = $timestamp; $end = 0x7fffffff; // infinite end $props = MAPIMapping::GetAppointmentProperties(); $props = getPropIdsFromStrings($store, $props); $restriction = array(RES_OR, array(array(RES_AND, array(array(RES_PROPERTY, array(RELOP => RELOP_LE, ULPROPTAG => $props["starttime"], VALUE => $end)), array(RES_PROPERTY, array(RELOP => RELOP_GE, ULPROPTAG => $props["endtime"], VALUE => $start)))), array(RES_OR, array(array(RES_AND, array(array(RES_EXIST, array(ULPROPTAG => $props["recurrenceend"])), array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => $props["isrecurring"], VALUE => true)), array(RES_PROPERTY, array(RELOP => RELOP_GE, ULPROPTAG => $props["recurrenceend"], VALUE => $start)))), array(RES_AND, array(array(RES_NOT, array(array(RES_EXIST, array(ULPROPTAG => $props["recurrenceend"])))), array(RES_PROPERTY, array(RELOP => RELOP_LE, ULPROPTAG => $props["starttime"], VALUE => $end)), array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => $props["isrecurring"], VALUE => true)))))))); // global OR return $restriction; }
/** * Sets properties for an email message * * @param mixed $mapimessage * @param SyncMail $message * * @access private * @return void */ private function setFlag($mapimessage, &$message) { // do nothing if protocoll version is lower than 12.0 as flags haven't been defined before if (Request::GetProtocolVersion() < 12.0) { return; } $message->flag = new SyncMailFlags(); $this->getPropsFromMAPI($message->flag, $mapimessage, MAPIMapping::GetMailFlagsMapping()); }
/** * Checks if mapimessage is inside the synchronization interval * also defined by MAPIUtils::GetCalendarRestriction() * * @param MAPIStore $store mapi store * @param MAPIMessage $mapimessage the mapi message to be checked * @param long $timestamp the lower time limit * * @access public * @return boolean */ public static function IsInCalendarSyncInterval($store, $mapimessage, $timestamp) { // This is our viewing window $start = $timestamp; $end = 0x7fffffff; // infinite end $props = MAPIMapping::GetAppointmentProperties(); $props = getPropIdsFromStrings($store, $props); $p = mapi_getprops($mapimessage, array($props["starttime"], $props["endtime"], $props["recurrenceend"], $props["isrecurring"], $props["recurrenceend"])); if (isset($p[$props["endtime"]]) && isset($p[$props["starttime"]]) && $p[$props["endtime"]] > $start && $p[$props["starttime"]] < $end || isset($p[$props["isrecurring"]]) && isset($p[$props["recurrenceend"]]) && $p[$props["isrecurring"]] == true && $p[$props["recurrenceend"]] >= $start || isset($p[$props["isrecurring"]]) && isset($p[$props["starttime"]]) && !isset($p[$props["recurrenceend"]]) && $p[$props["isrecurring"]] == true && $p[$props["starttime"]] <= $end) { ZLog::Write(LOGLEVEL_DEBUG, "MAPIUtils->IsInCalendarSyncInterval: Message is in the synchronization interval"); return true; } ZLog::Write(LOGLEVEL_WARN, "MAPIUtils->IsInCalendarSyncInterval: Message is OUTSIDE the synchronization interval"); return false; }
/** * Processes a response to a meeting request. * CalendarID is a reference and has to be set if a new calendar item is created * * @param string $requestid id of the object containing the request * @param string $folderid id of the parent folder of $requestid * @param string $response * * @access public * @return string id of the created/updated calendar obj * @throws StatusException */ public function MeetingResponse($requestid, $folderid, $response) { // Use standard meeting response code to process meeting request $reqentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid), hex2bin($requestid)); if (!$reqentryid) { throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s', '%s', '%s'): Error, unable to entryid of the message 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } $mapimessage = mapi_msgstore_openentry($this->store, $reqentryid); if (!$mapimessage) { throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error, unable to open request message for response 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } $meetingrequest = new Meetingrequest($this->store, $mapimessage); if (!$meetingrequest->isMeetingRequest()) { throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error, attempt to respond to non-meeting request", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } if ($meetingrequest->isLocalOrganiser()) { throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error, attempt to response to meeting request that we organized", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } // Process the meeting response. We don't have to send the actual meeting response // e-mail, because the device will send it itself. switch ($response) { case 1: // accept // accept default: $entryid = $meetingrequest->doAccept(false, false, false, false, false, false, true); // last true is the $userAction break; case 2: // tentative $entryid = $meetingrequest->doAccept(true, false, false, false, false, false, true); // last true is the $userAction break; case 3: // decline $meetingrequest->doDecline(false); break; } // F/B will be updated on logoff // We have to return the ID of the new calendar item, so do that here $calendarid = ""; if (isset($entryid)) { $newitem = mapi_msgstore_openentry($this->store, $entryid); $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY)); $calendarid = bin2hex($newprops[PR_SOURCE_KEY]); } // on recurring items, the MeetingRequest class responds with a wrong entryid if ($requestid == $calendarid) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): returned calender id is the same as the requestid - re-searching", $requestid, $folderid, $response)); $props = MAPIMapping::GetMeetingRequestProperties(); $props = getPropIdsFromStrings($this->store, $props); $messageprops = mapi_getprops($mapimessage, array($props["goidtag"])); $goid = $messageprops[$props["goidtag"]]; $items = $meetingrequest->findCalendarItems($goid); if (is_array($items)) { $newitem = mapi_msgstore_openentry($this->store, $items[0]); $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY)); $calendarid = bin2hex($newprops[PR_SOURCE_KEY]); ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): found other calendar entryid", $requestid, $folderid, $response)); } if ($requestid == $calendarid) { throw new StatusException(sprintf("BackendZarafa->MeetingResponse('%s','%s', '%s'): Error finding the accepted meeting response in the calendar", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } } // delete meeting request from Inbox $folderentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid)); $folder = mapi_msgstore_openentry($this->store, $folderentryid); mapi_folder_deletemessages($folder, array($reqentryid), 0); return $calendarid; }
/** * Returns categories for a message. * * @param binary $parentsourcekey * @param binary $sourcekey * * @access public * @return array or false on failure */ public function GetMessageCategories($parentsourcekey, $sourcekey) { $entryid = mapi_msgstore_entryidfromsourcekey($this->store, $parentsourcekey, $sourcekey); if (!$entryid) { ZLog::Write(LOGLEVEL_INFO, sprintf("MAPIProvider->GetMessageCategories(): Couldn't retrieve message, sourcekey: '%s', parentsourcekey: '%s'", bin2hex($sourcekey), bin2hex($parentsourcekey))); return false; } $mapimessage = mapi_msgstore_openentry($this->store, $entryid); $emailMapping = MAPIMapping::GetEmailMapping(); $emailMapping = array("categories" => $emailMapping["categories"]); $messageCategories = $this->getProps($mapimessage, $emailMapping); if (isset($messageCategories[$emailMapping["categories"]]) && is_array($messageCategories[$emailMapping["categories"]])) { return $messageCategories[$emailMapping["categories"]]; } return false; }
/** * Processes a response to a meeting request. * CalendarID is a reference and has to be set if a new calendar item is created * * @param string $requestid id of the object containing the request * @param string $folderid id of the parent folder of $requestid * @param string $response * * @access public * @return string id of the created/updated calendar obj * @throws StatusException */ public function MeetingResponse($requestid, $folderid, $response) { // Use standard meeting response code to process meeting request list($fid, $requestid) = Utils::SplitMessageId($requestid); $reqentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid), hex2bin($requestid)); if (!$reqentryid) { throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s', '%s', '%s'): Error, unable to entryid of the message 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } $mapimessage = mapi_msgstore_openentry($this->store, $reqentryid); if (!$mapimessage) { throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Error, unable to open request message for response 0x%X", $requestid, $folderid, $response, mapi_last_hresult()), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } $meetingrequest = new Meetingrequest($this->store, $mapimessage, $this->session); if (!$meetingrequest->isMeetingRequest()) { throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Error, attempt to respond to non-meeting request", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } if ($meetingrequest->isLocalOrganiser()) { throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Error, attempt to response to meeting request that we organized", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } // Process the meeting response. We don't have to send the actual meeting response // e-mail, because the device will send it itself. switch ($response) { case 1: // accept // accept default: $entryid = $meetingrequest->doAccept(false, false, false, false, false, false, true); // last true is the $userAction break; case 2: // tentative $entryid = $meetingrequest->doAccept(true, false, false, false, false, false, true); // last true is the $userAction break; case 3: // decline $meetingrequest->doDecline(false); break; } // F/B will be updated on logoff // We have to return the ID of the new calendar item, so do that here $calendarid = ""; $calFolderId = ""; if (isset($entryid)) { $newitem = mapi_msgstore_openentry($this->store, $entryid); // new item might be in a delegator's store. ActiveSync does not support accepting them. if (!$newitem) { throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Object with entryid '%s' was not found in user's store (0x%X). It might be in a delegator's store.", $requestid, $folderid, $response, bin2hex($entryid), mapi_last_hresult()), SYNC_MEETRESPSTATUS_SERVERERROR, null, LOGLEVEL_WARN); } $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY)); $calendarid = bin2hex($newprops[PR_SOURCE_KEY]); $calFolderId = bin2hex($newprops[PR_PARENT_SOURCE_KEY]); } // on recurring items, the MeetingRequest class responds with a wrong entryid if ($requestid == $calendarid) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): returned calender id is the same as the requestid - re-searching", $requestid, $folderid, $response)); $props = MAPIMapping::GetMeetingRequestProperties(); $props = getPropIdsFromStrings($this->store, $props); $messageprops = mapi_getprops($mapimessage, array($props["goidtag"])); $goid = $messageprops[$props["goidtag"]]; $items = $meetingrequest->findCalendarItems($goid); if (is_array($items)) { $newitem = mapi_msgstore_openentry($this->store, $items[0]); $newprops = mapi_getprops($newitem, array(PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY)); $calendarid = bin2hex($newprops[PR_SOURCE_KEY]); $calFolderId = bin2hex($newprops[PR_PARENT_SOURCE_KEY]); ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): found other calendar entryid", $requestid, $folderid, $response)); } if ($requestid == $calendarid) { throw new StatusException(sprintf("BackendKopano->MeetingResponse('%s','%s', '%s'): Error finding the accepted meeting response in the calendar", $requestid, $folderid, $response), SYNC_MEETRESPSTATUS_INVALIDMEETREQ); } } // delete meeting request from Inbox $folderentryid = mapi_msgstore_entryidfromsourcekey($this->store, hex2bin($folderid)); $folder = mapi_msgstore_openentry($this->store, $folderentryid); mapi_folder_deletemessages($folder, array($reqentryid), 0); $prefix = ''; // prepend the short folderid of the target calendar: if available and short ids are used if ($calFolderId) { $shortFolderId = ZPush::GetDeviceManager()->GetFolderIdForBackendId($calFolderId); if ($calFolderId != $shortFolderId) { $prefix = $shortFolderId . ':'; } } return $prefix . $calendarid; }