/** * Constructor * * @access public */ public function StateManager() { $this->statemachine = ZPush::GetStateMachine(); $this->hierarchyOperation = ZPush::HierarchyCommand(Request::GetCommandCode()); $this->deleteOldStates = Request::GetCommandCode() === ZPush::COMMAND_SYNC || $this->hierarchyOperation; $this->synchedFolders = array(); }
public function __construct() { parent::__construct(); $this->preserved = array(); // static vars come from the parent class $this->latest = array("pid" => self::$pid, "ip" => Request::GetRemoteAddr(), "user" => self::$user, "start" => $_SERVER['REQUEST_TIME'], "devtype" => Request::GetDeviceType(), "devid" => self::$devid, "devagent" => Request::GetUserAgent(), "command" => Request::GetCommandCode(), "ended" => 0, "push" => false); $this->key = self::PREFIX . self::$devid . '|' . self::$user . '|' . self::$pid; $this->AnnounceInformation("initializing"); }
/** * Constructor * * @access public */ public function TopCollector() { // initialize super parameters $this->allocate = 2097152; // 2 MB $this->type = 20; parent::__construct(); // initialize params $this->InitializeParams(); $this->preserved = array(); // static vars come from the parent class $this->latest = array("pid" => self::$pid, "ip" => Request::GetRemoteAddr(), "user" => self::$user, "start" => self::$start, "devtype" => Request::GetDeviceType(), "devid" => self::$devid, "devagent" => Request::GetUserAgent(), "command" => Request::GetCommandCode(), "ended" => 0, "push" => false); $this->AnnounceInformation("initializing"); }
if (Request::IsMethodPOST() && (Request::GetCommandCode() === false || !Request::GetGETUser() || !Request::GetDeviceID() || !Request::GetDeviceType())) { throw new FatalException("Requested the Z-Push URL without the required GET parameters"); } // Load the backend $backend = ZPush::GetBackend(); // always request the authorization header if (!Request::AuthenticationInfo()) { throw new AuthenticationRequiredException("Access denied. Please send authorisation information"); } // check the provisioning information if (PROVISIONING === true && Request::IsMethodPOST() && ZPush::CommandNeedsProvisioning(Request::GetCommandCode()) && (Request::WasPolicyKeySent() && Request::GetPolicyKey() == 0 || ZPush::GetDeviceManager()->ProvisioningRequired(Request::GetPolicyKey())) && (LOOSE_PROVISIONING === false || LOOSE_PROVISIONING === true && Request::WasPolicyKeySent())) { //TODO for AS 14 send a wbxml response throw new ProvisioningRequiredException(); } // most commands require an authenticated user if (ZPush::CommandNeedsAuthentication(Request::GetCommandCode())) { RequestProcessor::Authenticate(); } // Do the actual processing of the request if (Request::IsMethodGET()) { throw new NoPostRequestException("This is the Z-Push location and can only be accessed by Microsoft ActiveSync-capable devices", NoPostRequestException::GET_REQUEST); } // Do the actual request header(ZPush::GetServerHeader()); // announce the supported AS versions (if not already sent to device) if (ZPush::GetDeviceManager()->AnnounceASVersion()) { $versions = ZPush::GetSupportedProtocolVersions(true); ZLog::Write(LOGLEVEL_INFO, sprintf("Announcing latest AS version to device: %s", $versions)); header("X-MS-RP: " . $versions); } RequestProcessor::Initialize();
/** * Indicates if the next messages should be ignored (not be sent to the mobile!) * * @param string $messageid (opt) id of the message which is to be exported next * @param string $folderid (opt) parent id of the message * @param boolean $markAsIgnored (opt) to peek without setting the next message to be * ignored, set this value to false * @access public * @return boolean */ public function IgnoreNextMessage($markAsIgnored = true, $messageid = false, $folderid = false) { // as the next message id is not available at all point this method is called, we use different indicators. // potentialbroken indicates that we know that the broken message should be exported next, // alltho we do not know for sure as it's export message orders can change // if the $messageid is available and matches then we are sure and only then really ignore it $potentialBroken = false; $realBroken = false; if (Request::GetCommandCode() == ZPush::COMMAND_SYNC && $this->ignore_messageid !== false) { $potentialBroken = true; } if ($messageid !== false && $this->ignore_messageid == $messageid) { $realBroken = true; } // this call is just to know what should be happening // no further actions necessary if ($markAsIgnored === false) { return $potentialBroken; } // we should really do something here // first we check if we are in the loop mode, if so, // we update the potential broken id message so we loop count the same message $changedData = false; // exclusive block if ($this->blockMutex()) { $loopdata = $this->hasData() ? $this->getData() : array(); // check and initialize the array structure $this->checkArrayStructure($loopdata, $folderid); $current = $loopdata[self::$devid][self::$user][$folderid]; // we found our broken message! if ($realBroken) { $this->ignore_messageid = false; $current['ignored'] = $messageid; $changedData = true; // check if this message was broken before - here we know that it still is and remove it from the tracking $brokenkey = self::BROKENMSGS . "-" . $folderid; if (isset($loopdata[self::$devid][self::$user][$brokenkey]) && isset($loopdata[self::$devid][self::$user][$brokenkey][$messageid])) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("LoopDetection->IgnoreNextMessage(): previously broken message '%s' is still broken and will not be tracked anymore", $messageid)); unset($loopdata[self::$devid][self::$user][$brokenkey][$messageid]); } } else { // update potential id if looping on an item if (isset($current['loopcount'])) { $current['potential'] = $messageid; // this message should be the broken one, but is not!! // we should reset the loop count because this is certainly not the broken one if ($potentialBroken) { $current['loopcount'] = 1; ZLog::Write(LOGLEVEL_DEBUG, "LoopDetection->IgnoreNextMessage(): this should be the broken one, but is not! Resetting loop count."); } ZLog::Write(LOGLEVEL_DEBUG, sprintf("LoopDetection->IgnoreNextMessage(): Loop mode, potential broken message id '%s'", $current['potential'])); $changedData = true; } } // update loop data if ($changedData == true) { $loopdata[self::$devid][self::$user][$folderid] = $current; $ok = $this->setData($loopdata); } $this->releaseMutex(); } // end exclusive block if ($realBroken) { ZPush::GetTopCollector()->AnnounceInformation("Broken message ignored", true); } return $realBroken; }
/** * Loads the command handler and processes a command sent from the mobile * * @access public * @return boolean */ public static function HandleRequest() { $handler = ZPush::GetRequestHandlerForCommand(Request::GetCommandCode()); // TODO handle WBXML exceptions here and print stack return $handler->Handle(Request::GetCommandCode()); }
/** * Loads the command handler and processes a command sent from the mobile * * @access public * @return boolean */ public static function HandleRequest() { $handler = ZPush::GetRequestHandlerForCommand(Request::GetCommandCode()); // if there is an error decoding wbxml, consume remaining data and include it in the WBXMLException if (!$handler->Handle(Request::GetCommandCode())) { $wbxmlLog = "no decoder"; if (self::$decoder) { self::$decoder->readRemainingData(); $wbxmlLog = self::$decoder->getWBXMLLog(); } throw new WBXMLException("Debug data: " . $wbxmlLog); } // also log WBXML in happy case if (self::$decoder && @constant('WBXML_DEBUG') === true) { ZLog::Write(LOGLEVEL_WBXML, "WBXML-IN : " . self::$decoder->getWBXMLLog(), false); } }
/** * Loads the command handler and processes a command sent from the mobile * * @access public * @return boolean */ public static function HandleRequest() { $handler = ZPush::GetRequestHandlerForCommand(Request::GetCommandCode()); // if there is an error decoding wbxml, consume remaining data and include it in the WBXMLException try { if (!$handler->Handle(Request::GetCommandCode())) { throw new WBXMLException(sprintf("Unknown error in %s->Handle()", get_class($handler))); } } catch (Exception $ex) { ZLog::Write(LOGLEVEL_FATAL, "WBXML debug data: " . Request::GetInputAsBase64(), false); throw $ex; } // also log WBXML in happy case if (ZLog::WbxmlDebug()) { ZLog::Write(LOGLEVEL_WBXML, "WBXML-IN : " . Request::GetInputAsBase64(), false); } }
/** * Indicates if the next messages should be ignored (not be sent to the mobile!) * * @param string $messageid (opt) id of the message which is to be exported next * @param string $folderid (opt) parent id of the message * @param boolean $markAsIgnored (opt) to peek without setting the next message to be * ignored, set this value to false * @access public * @return boolean */ public function IgnoreNextMessage($markAsIgnored = true, $messageid = false, $folderid = false) { // as the next message id is not available at all point this method is called, we use different indicators. // potentialbroken indicates that we know that the broken message should be exported next, // alltho we do not know for sure as it's export message orders can change // if the $messageid is available and matches then we are sure and only then really ignore it $potentialBroken = false; $realBroken = false; if (Request::GetCommandCode() == ZPush::COMMAND_SYNC && $this->ignore_messageid !== false) { $potentialBroken = true; } if ($messageid !== false && $this->ignore_messageid == $messageid) { $realBroken = true; } // this call is just to know what should be happening // no further actions necessary if ($markAsIgnored === false) { return $potentialBroken; } // we should really do something here // first we check if we are in the loop mode, if so, // we update the potential broken id message so we loop count the same message // we found our broken message! if ($realBroken) { $this->ignore_messageid = false; self::$redis->hSet(self::$keyfolder . $folderid, 'ignored', $messageid); // check if this message was broken before - here we know that it still is and remove it from the tracking if ($this->RemoveBrokenMessage($folderid, $messageid)) { ZLog::Write(LOGLEVEL_DEBUG, "LoopDetection->IgnoreNextMessage(): previously broken message '{$messageid}' is still broken and will not be tracked anymore (folder = {$folderid})"); } ZPush::GetTopCollector()->AnnounceInformation("Broken message ignored", true); } else { // update potential id if looping on an item if (self::$redis->hGet(self::$keyfolder . $folderid, 'loopcount') !== false) { // this message should be the broken one, but is not!! // we should reset the loop count because this is certainly not the broken one if ($potentialBroken) { self::$redis->hMset(self::$keyfolder . $folderid, array('potential' => $messageid, 'loopcount' => 1)); ZLog::Write(LOGLEVEL_DEBUG, "LoopDetection->IgnoreNextMessage(): this should be the broken one, but is not! Resetting loop count."); } else { self::$redis->hSet(self::$keyfolder . $folderid, 'potential', $messageid); } ZLog::Write(LOGLEVEL_DEBUG, sprintf("LoopDetection->IgnoreNextMessage(): Loop mode, potential broken message id '%s'", $messageid)); } } return $realBroken; }