1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13: class Horde_Rpc_ActiveSync extends Horde_Rpc
14: {
15: 16: 17: 18: 19:
20: private $_get;
21:
22: 23: 24: 25: 26:
27: private $_server;
28:
29: 30: 31: 32: 33:
34: private $_backend;
35:
36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
47: public function __construct(Horde_Controller_Request_Http $request, array $params = array())
48: {
49: parent::__construct($request, $params);
50:
51:
52: $this->_get = $request->getGetVars();
53: if ($request->getMethod() == 'POST' &&
54: (empty($this->_get['Cmd']) || empty($this->_get['DeviceId']) || empty($this->_get['DeviceType']))) {
55:
56: $this->_logger->err('Missing required parameters.');
57: throw new Horde_Rpc_Exception('Your device requested the ActiveSync URL wihtout required parameters.');
58: }
59:
60:
61: if ($request->getMethod() == 'POST' && empty($this->_get['User'])) {
62: $serverVars = $this->_request->getServerVars();
63: if ($serverVars['PHP_AUTH_USER']) {
64: $this->_get['User'] = $serverVars['PHP_AUTH_USER'];
65: } elseif ($serverVars['Authorization']) {
66: $hash = str_replace('Basic ', '', $serverVars['Authorization']);
67: $hash = base64_decode($hash);
68: if (strpos($hash, ':') !== false) {
69: list($this->_get['User'], $pass) = explode(':', $hash, 2);
70: }
71: }
72: if (empty($this->_get['User'])) {
73: $this->_logger->err('Missing required parameters.');
74: throw new Horde_Rpc_Exception('Your device requested the ActiveSync URL wihtout required parameters.');
75: }
76: }
77:
78: $this->_backend = $params['backend'];
79: $this->_server = $params['server'];
80: $this->_server->setProvisioning(empty($params['provisioning']) ? false : $params['provisioning']);
81: }
82:
83: 84: 85: 86: 87:
88: public function getResponseContentType()
89: {
90: return 'application/vnd.ms-sync.wbxml';
91: }
92:
93: 94: 95: 96: 97: 98:
99: public function getInput()
100: {
101: return null;
102: }
103:
104: 105: 106: 107: 108: 109: 110:
111: public function getResponse($request)
112: {
113:
114: ob_start(null, 1048576);
115: $serverVars = $this->_request->getServerVars();
116: switch ($serverVars['REQUEST_METHOD']) {
117: case 'OPTIONS':
118: case 'GET':
119: if ($serverVars['REQUEST_METHOD'] == 'GET' &&
120: $this->_get['Cmd'] != 'OPTIONS') {
121: throw new Horde_Rpc_Exception('Trying to access the ActiveSync endpoint from a browser. Not Supported.');
122: }
123: $this->_logger->debug('Horde_Rpc_ActiveSync::getResponse() starting for OPTIONS');
124: try {
125: $this->_server->handleRequest('Options', null, null);
126: } catch (Horde_ActiveSync_Exception $e) {
127: $this->_handleError($e);
128: }
129: break;
130:
131: case 'POST':
132: Horde_ActiveSync::activeSyncHeader();
133: $this->_logger->debug('Horde_Rpc_ActiveSync::getResponse() starting for ' . $this->_get['Cmd']);
134: try {
135: $this->_server->handleRequest($this->_get['Cmd'], $this->_get['DeviceId']);
136: } catch (Horde_ActiveSync_Exception $e) {
137: $this->_handleError($e);
138: }
139: break;
140: }
141: }
142:
143: 144: 145: 146:
147: public function sendOutput($output)
148: {
149:
150:
151:
152:
153:
154:
155: $len = ob_get_length();
156: $data = ob_get_contents();
157: ob_end_clean();
158:
159:
160:
161:
162: header('Content-Type: application/vnd.ms-sync.wbxml');
163: header('Content-Length: ' . $len);
164: echo $data;
165: }
166:
167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179:
180: public function authorize()
181: {
182: $this->_logger->debug('Horde_Rpc_ActiveSync::authorize() starting');
183: if (!$this->_requireAuthorization) {
184: return true;
185: }
186:
187:
188: $serverVars = $this->_request->getServerVars();
189: $user = $pass = '';
190: if (!empty($serverVars['PHP_AUTH_USER'])) {
191: $user = $serverVars['PHP_AUTH_USER'];
192: $pass = $serverVars['PHP_AUTH_PW'];
193: } elseif (!empty($serverVars['Authorization'])) {
194: $hash = str_replace('Basic ', '', $serverVars['Authorization']);
195: $hash = base64_decode($hash);
196: if (strpos($hash, ':') !== false) {
197: list($user, $pass) = explode(':', $hash, 2);
198: }
199: }
200:
201:
202: $pos = strrpos($user, '\\');
203: if ($pos !== false) {
204: $domain = substr($user, 0, $pos);
205: $user = substr($user, $pos + 1);
206: } else {
207: $domain = null;
208: }
209:
210:
211: $results = $this->_backend->logon($user, $pass, $domain);
212: if (!$results && empty($this->_policykey)) {
213: header('HTTP/1.1 401 Unauthorized');
214: header('WWW-Authenticate: Basic realm="Horde RPC"');
215: $this->_logger->info('Access denied for user: ' . $user . '. Username or password incorrect.');
216: }
217:
218:
219: if (empty($this->_get['User'])) {
220: return false;
221: }
222: $results = $this->_backend->setup($this->_get['User']);
223: if (!$results) {
224: header('HTTP/1.1 401 Unauthorized');
225: header('WWW-Authenticate: Basic realm="Horde RPC"');
226: echo 'Access denied or user ' . $this->_get['User'] . ' unknown.';
227: }
228:
229: $this->_logger->debug('Horde_Rpc_ActiveSync::authorize() exiting');
230:
231: return true;
232: }
233:
234: 235: 236: 237: 238: 239: 240:
241: protected function _handleError($e)
242: {
243: $trace = $e->getTraceAsString();
244: $m = $e->getMessage();
245: $buffer = ob_get_clean();
246:
247: $this->_logger->err('Error in communicating with ActiveSync server: ' . $m);
248: $this->_logger->err($trace);
249: $this->_logger->err('Buffer contents: ' . $buffer);
250: throw new Horde_Rpc_Exception($e);
251: }
252:
253: }
254: