Overview

Packages

  • ActiveSync
  • None

Classes

  • Horde_ActiveSync
  • Horde_ActiveSync_Connector_Exporter
  • Horde_ActiveSync_Connector_Importer
  • Horde_ActiveSync_Driver_Base
  • Horde_ActiveSync_Exception
  • Horde_ActiveSync_Exception_InvalidRequest
  • Horde_ActiveSync_Exception_StateGone
  • Horde_ActiveSync_Message_Base
  • Horde_ActiveSync_Request_Base
  • Horde_ActiveSync_Request_FolderCreate
  • Horde_ActiveSync_Request_FolderSync
  • Horde_ActiveSync_Request_GetHierarchy
  • Horde_ActiveSync_Request_GetItemEstimate
  • Horde_ActiveSync_Request_MeetingResponse
  • Horde_ActiveSync_Request_MoveItems
  • Horde_ActiveSync_Request_Notify
  • Horde_ActiveSync_Request_Ping
  • Horde_ActiveSync_Request_Provision
  • Horde_ActiveSync_Request_Search
  • Horde_ActiveSync_Request_SendMail
  • Horde_ActiveSync_Request_SmartForward
  • Horde_ActiveSync_Request_SmartReply
  • Horde_ActiveSync_Request_Sync
  • Horde_ActiveSync_State_File
  • Horde_ActiveSync_Sync
  • Horde_ActiveSync_Wbxml
  • Horde_ActiveSync_Wbxml_Decoder
  • Horde_ActiveSync_Wbxml_Encoder
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Base class for handling ActiveSync requests
  4:  *
  5:  * Copyright 2009-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * @author Michael J. Rubinsky <mrubinsk@horde.org>
  8:  * @package ActiveSync
  9:  */
 10: /**
 11:  * Zarafa Deutschland GmbH, www.zarafaserver.de
 12:  * This file is distributed under GPL-2.0.
 13:  * Consult COPYING file for details
 14:  */
 15: abstract class Horde_ActiveSync_Request_Base
 16: {
 17:     /**
 18:      * Driver for communicating with the backend datastore.
 19:      *
 20:      * @var Horde_ActiveSync_Driver_Base
 21:      */
 22:     protected $_driver;
 23: 
 24:     /**
 25:      * Encoder
 26:      *
 27:      * @var Horde_ActiveSync_Wbxml_Encoder
 28:      */
 29:     protected $_encoder;
 30: 
 31:     /**
 32:      * Decoder
 33:      *
 34:      * @var Horde_ActiveSync_Wbxml_Decoder
 35:      */
 36:     protected $_decoder;
 37: 
 38:     /**
 39:      * Request object
 40:      *
 41:      * @var Horde_Controller_Request_Http
 42:      */
 43:     protected $_request;
 44: 
 45:     /**
 46:      * Whether we require provisioned devices.
 47:      * Valid values are true, false, or Horde_ActiveSync::PROVISIONING_LOOSE.
 48:      * Loose allows devices that don't know about provisioning to continue to
 49:      * function, but requires devices that are capable to be provisioned.
 50:      *
 51:      * @var mixed
 52:      */
 53:     protected $_provisioning;
 54: 
 55:     /**
 56:      * The ActiveSync Version
 57:      *
 58:      * @var string
 59:      */
 60:     protected $_version;
 61: 
 62:     /**
 63:      * Used to track what error code to send back to PIM on failure
 64:      *
 65:      * @var integer
 66:      */
 67:     protected $_statusCode = 0;
 68: 
 69:     /**
 70:      * State object
 71:      *
 72:      * @var Horde_ActiveSync_State_Base
 73:      */
 74:     protected $_state;
 75: 
 76:     /**
 77:      * ActiveSync server
 78:      *
 79:      * @var Horde_ActiveSync
 80:      */
 81:     protected $_activeSync;
 82: 
 83:     /**
 84:      * Logger
 85:      *
 86:      * @var Horde_Log_Logger
 87:      */
 88:     protected $_logger;
 89: 
 90:     /**
 91:      * The device info
 92:      *
 93:      * @var stdClass
 94:      */
 95:     protected $_device;
 96: 
 97:     /**
 98:      * Const'r
 99:      *
100:      * @param Horde_ActiveSync_Driver $driver            The backend driver
101:      * @param Horde_ActiveSync_Wbxml_Decoder $decoder    The Wbxml decoder
102:      * @param Horde_ActiveSync_Wbxml_Endcodder $encdoer  The Wbxml encoder
103:      * @param Horde_Controller_Request_Http $request     The request object
104:      * @param string $provisioning                       Is provisioning required?
105:      *
106:      * @return Horde_ActiveSync
107:      */
108:     public function __construct(Horde_ActiveSync_Driver_Base $driver,
109:                                 Horde_ActiveSync_Wbxml_Decoder $decoder,
110:                                 Horde_ActiveSync_Wbxml_Encoder $encoder,
111:                                 Horde_Controller_Request_Http $request,
112:                                 Horde_ActiveSync $as,
113:                                 $device,
114:                                 $provisioning)
115:     {
116:         /* Backend driver */
117:         $this->_driver = $driver;
118: 
119:         /* server */
120:         $this->_activeSync = $as;
121: 
122:         /* Wbxml handlers */
123:         $this->_encoder = $encoder;
124:         $this->_decoder = $decoder;
125: 
126:         /* The http request */
127:         $this->_request = $request;
128: 
129:         /* Provisioning support */
130:         $this->_provisioning = $provisioning;
131: 
132:         /* Get the state object */
133:         $this->_state = &$driver->getStateObject();
134: 
135:         /* Device info */
136:         $this->_device = $device;
137:     }
138: 
139:     /**
140:      * Ensure the PIM's policy key is current.
141:      *
142:      * @param integer $sentKey  The policykey sent to us by the PIM
143:      *
144:      * @return boolean
145:      */
146:     public function checkPolicyKey($sentKey)
147:     {
148:          $this->_logger->debug('[' . $this->_device->id . '] Checking policykey for device '
149:             . ' Key: ' . $sentKey
150:             . ' User: ' . $this->_driver->getUser());
151: 
152:          $this->_device = $this->_state->loadDeviceInfo($this->_device->id, $this->_driver->getUser());
153: 
154:          // Use looseprovisioning?
155:          if (empty($sentKey) && $this->_hasBrokenProvisioning() &&
156:              $this->_provisioning == Horde_ActiveSync::PROVISIONING_LOOSE) {
157:             $sentKey = null;
158:          }
159: 
160:         // Don't attempt if we don't care
161:         if ($this->_provisioning !== false) {
162:             $state = $this->_driver->getStateObject();
163:             $storedKey = $state->getPolicyKey($this->_device->id);
164:             $this->_logger->debug('[' . $this->_device->id . '] Stored key: ' . $storedKey);
165: 
166:             /* Loose provsioning should allow a blank key */
167:             if ((empty($storedKey) || $storedKey != $sentKey) &&
168:                ($this->_provisioning !== Horde_ActiveSync::PROVISIONING_LOOSE ||
169:                ($this->_provisioning === Horde_ActiveSync::PROVISIONING_LOOSE && !is_null($sentKey)))) {
170: 
171:                     Horde_ActiveSync::provisioningRequired();
172:                     return false;
173:             }
174:         }
175: 
176:         $this->_logger->debug('Policykey: ' . $sentKey . ' verified.');
177: 
178:         return true;
179:     }
180: 
181:     public function setLogger(Horde_Log_Logger $logger)
182:     {
183:         $this->_logger = $logger;
184:     }
185: 
186:     /**
187:      *
188:      * @param string $version
189:      * @param string $devId
190:      */
191:     public function handle()
192:     {
193:         $this->_version = $this->_activeSync->getProtocolVersion();
194:         $this->_logger->info('Request being handled for device: ' . $this->_device->id . ' Supporting protocol version: ' . $this->_version);
195:     }
196: 
197:     /**
198:      * Utility function to help determine if a device has broken provisioning.
199:      * This is impossible to get 100% right since versions of Android that
200:      * are broken and versions that are not both use the same User-Agent string
201:      * (Android/0.3 for both 2.1, 2.2 and even 2.3). We err on the side
202:      * of device compatibility at the expense of not being able to provision
203:      * some non-broken android devices when provisioning is set to
204:      * Horde_ActiveSync::PROVISIONING_LOOSE.
205:      *
206:      * @TODO This should be added to a device object, once we implement
207:      * Horde_ActiveSync_Device API.
208:      *
209:      * @return boolean
210:      */
211:     protected function _hasBrokenProvisioning()
212:     {
213:         if (strpos($this->_device->userAgent, 'Android') !== false) {
214:             if (preg_match('@EAS[/-]{0,1}([.0-9]{2,})@', $this->_device->userAgent, $matches)) {
215:                 return ($matches[1] < 1.2);
216:             }
217:             return true;
218:         }
219: 
220:         // WP7 not only doesn't support all EAS 2.5 security poliices, it flat
221:         // out refuses to notify the server of a partial acceptance and just
222:         // completely fails.
223:         if (strpos($this->_device->userAgent, 'MSFT-WP/7') !== false) {
224:             return true;
225:         }
226: 
227:         // Not an android device - enforce provisioning if needed.
228:         return false;
229:     }
230: 
231:     /**
232:      * Clean up after initial pairing. Initial pairing can happen either as a
233:      * result of either a FOLDERSYNC or PROVISION command, depending on the
234:      * device capabilities.
235:      *
236:      * @TODO Move this to a device object??
237:      */
238:     protected function _cleanUpAfterPairing()
239:     {
240:         // Android sends a bogus device id of 'validate' during initial
241:         // handshake. This data is never used again, and the resulting
242:         // FOLDERSYNC response is ignored by the client. Remove the entry,
243:         // to avoid having 2 device entries for every android client.
244:         if ($this->_device->id == 'validate') {
245:             $this->_state->removeState(null, 'validate');
246:         }
247:     }
248: 
249: }
250: 
API documentation generated by ApiGen