| [ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 3 include_once 'SyncML/Command.php'; 4 include_once 'SyncML/Command/Status.php'; 5 include_once 'SyncML/Command/Alert.php'; 6 include_once 'SyncML/Command/Sync.php'; 7 include_once 'SyncML/Command/Final.php'; 8 include_once 'SyncML/Sync.php'; 9 include_once 'SyncML/Backend.php'; 10 11 /** 12 * The SyncML_SyncHdr and SyncML_SyncBody classes provides 13 * a SyncHdr and SyncBody in SyncML Representation Protocol, version 14 * 1.1 5.2.2 and 5.2.3. Most of the work is passed on to 15 * SyncML_Command_Alert and SyncML_Command_Sync. 16 * 17 * There are two global objects that are used by SyncML: 18 * 1) $_SESSION['SyncML.state']: 19 * session object used to maintain the state between the individual 20 * SyncML messages. 21 * 22 * 2) $GLOBALS['backend'] 23 * Backend to handle the communication with the datastore. Currently the 24 * horde backend is the only backend provided. 25 * 26 * $Horde: framework/SyncML/SyncML.php,v 1.21.10.10 2006/01/01 21:28:35 jan Exp $ 27 * 28 * Copyright 2003-2006 Anthony Mills <amills@pyramid6.com> 29 * 30 * See the enclosed file COPYING for license information (LGPL). If you 31 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 32 * 33 * @author Anthony Mills <amills@pyramid6.com> 34 * @author Karsten Fourmont <fourmont@gmx.de> 35 * @since Horde 3.0 36 * @package SyncML 37 */ 38 class SyncML_ContentHandler { 39 40 /** 41 * Output ContentHandler used to output XML events. 42 * 43 * @var object 44 */ 45 var $_output; 46 47 /** 48 * Stack for holding the xml elements during creation of the object from 49 * the xml event flow. 50 * 51 * @var array 52 */ 53 var $_Stack = array(); 54 55 /** 56 * @var string 57 */ 58 var $_chars; 59 60 function setOutput(&$output) 61 { 62 $this->_output = &$output; 63 } 64 65 function startElement($uri, $element, $attrs) 66 { 67 $this->_Stack[] = $element; 68 } 69 70 function endElement($uri, $element) 71 { 72 if (isset($this->_chars)) { 73 unset($this->_chars); 74 } 75 76 array_pop($this->_Stack); 77 } 78 79 function characters($str) 80 { 81 if (isset($this->_chars)) { 82 $this->_chars = $this->_chars . $str; 83 } else { 84 $this->_chars = $str; 85 } 86 } 87 88 } 89 90 91 /** 92 * Defined in SyncML Representation Protocol, version 1.1 5.2.2 93 * 94 * @package SyncML 95 */ 96 class SyncML_SyncMLHdr extends SyncML_ContentHandler { 97 98 /** 99 * Defined in SyncML Representation Protocol, version 1.1 5.1.9. User name. 100 * 101 * @var string 102 */ 103 var $_locName; 104 105 /** 106 * Defined in SyncML Representation Protocol, version 1.1 5.1.18 107 * 108 * @var string 109 */ 110 var $_sessionID; 111 112 /** 113 * Defined in SyncML Representation Protocol, version 1.1. Must be 1.0 (0) 114 * or 1.1 (1). 115 * 116 * @var string 117 */ 118 var $_version; 119 120 /** 121 * Defined in SyncML Representation Protocol, version 1.1 5.1.12 122 * 123 * @var string 124 */ 125 var $_msgID; 126 127 /** 128 * Defined in SyncML Representation Protocol, version 1.1 5.1.10 129 * 130 * @var string 131 */ 132 var $_targetURI; 133 134 /** 135 * Defined in SyncML Representation Protocol, version 1.1 5.1.10, 5.1.20 136 * 137 * @var string 138 */ 139 var $_sourceURI; 140 141 var $_credData; 142 143 var $_credFormat; 144 145 var $_credType; 146 147 var $_maxMsgSize; 148 149 function getStateFromSession($sourceURI, $locName, $sessionID) 150 { 151 $GLOBALS['backend'] = &new SyncML_Backend_Horde(); 152 153 // Reload the Horde SessionHandler if necessary. 154 Horde::setupSessionHandler(); 155 156 // SyncML protocol does not require the client to send the 157 // username on any messages but the first. So unfortunately 158 // we can't use it to make a unique session id. 159 session_id('syncml' . preg_replace('/[^a-zA-Z0-9]/', 160 '', $sourceURI . $sessionID)); 161 session_start(); 162 163 // It would seem multisync does not send the user name once it 164 // has been authorized. Make sure we have a valid session id. 165 session_id('syncml' . preg_replace('/[^a-zA-Z0-9]/', '', $sourceURI . $sessionID)); 166 @session_start(); 167 168 if (!isset($_SESSION['SyncML.state'])) { 169 // Create a new state if one does not already exist. 170 $GLOBALS['backend']->logMessage('New session created: ' 171 . session_id(), 172 __FILE__, __LINE__, PEAR_LOG_DEBUG); 173 174 $_SESSION['SyncML.state'] = &new SyncML_State($sourceURI, 175 $locName, 176 $sessionID); 177 } else { 178 $GLOBALS['backend']->logMessage('Existing session continued: ' 179 . session_id(), 180 __FILE__, __LINE__, PEAR_LOG_DEBUG); 181 } 182 183 return $_SESSION['SyncML.state']; 184 } 185 186 function startElement($uri, $element, $attrs) 187 { 188 parent::startElement($uri, $element, $attrs); 189 } 190 191 function endElement($uri, $element) 192 { 193 switch (count($this->_Stack)) { 194 case 1: 195 // </SyncHdr></SyncML> 196 // Find the state. 197 $state = $this->getStateFromSession($this->_sourceURI, $this->_locName, $this->_sessionID); 198 199 $state->setVersion($this->_version); 200 $state->setMsgID($this->_msgID); 201 $state->setTargetURI($this->_targetURI); 202 $state->setPassword($this->_credData); 203 $state->setWBXML(is_a($this->_output, 'XML_WBXML_Encoder')); 204 205 // Store login name in state if not already set 206 if (empty($state->_locName) && !empty($this->_locName)) { 207 $state->setLocName($this->_locName); 208 } 209 if (!empty($this->_maxMsgSize)) { 210 $state->setMaxMsgSize($this->_maxMsgSize); 211 } 212 213 $str = 'authorized=' . $state->isAuthorized() . 214 ' version=' . $state->getVersion() . 215 ' msgid=' . $state->getMsgID() . 216 ' source=' . $state->getSourceURI() . 217 ' target=' . $state->getTargetURI() . 218 ' user=' . $state->getLocName() . 219 ' charset=' . NLS::getCharset() . 220 ' wbxml=' . $state->isWBXML() 221 222 ; 223 224 $_SESSION['SyncML.state'] = $state; 225 226 $GLOBALS['backend']->logMessage($str, __FILE__, __LINE__, PEAR_LOG_DEBUG); 227 228 // Got the state; now write our SyncHdr header. 229 $this->outputSyncHdr($this->_output); 230 break; 231 232 case 2: 233 if ($element == 'VerProto') { 234 // </VerProto></SyncHdr></SyncML> 235 if (trim($this->_chars) == 'SyncML/1.1') { 236 $this->_version = 1; 237 } else { 238 $this->_version = 0; 239 } 240 } elseif ($element == 'SessionID') { 241 // </SessionID></SyncHdr></SyncML> 242 $this->_sessionID = trim($this->_chars); 243 } elseif ($element == 'MsgID') { 244 // </MsgID></SyncHdr></SyncML> 245 $this->_msgID = intval(trim($this->_chars)); 246 } elseif ($element == 'Cred') { 247 // </Cred></SyncHdr></SyncML> 248 $this->_credData = base64_decode($this->_credData); 249 250 $tmp = explode(':', $this->_credData); 251 $this->_locName = $tmp[0]; 252 $this->_credData = $tmp[1]; 253 Horde::logMessage('SyncML: received credentials for user=' 254 . $this->_locName , 'cred=' 255 . $this->_credData, 256 __FILE__, __LINE__, PEAR_LOG_DEBUG); 257 258 } 259 break; 260 261 case 3: 262 if ($element == 'LocURI') { 263 if ($this->_Stack[1] == 'Source') { 264 // </LocURI></Source></SyncHdr></SyncML> 265 $this->_sourceURI = trim($this->_chars); 266 } elseif ($this->_Stack[1] == 'Target') { 267 // </LocURI></Target></SyncHdr></SyncML> 268 $this->_targetURI = trim($this->_chars); 269 } 270 } elseif ($element == 'LocName') { 271 if ($this->_Stack[1] == 'Source') { 272 // </LocName></Source></SyncHdr></SyncML> 273 $this->_locName = trim($this->_chars); 274 } 275 } elseif ($element == 'Data') { 276 // </Data></Cred></SyncHdr></SyncML> 277 if ($this->_Stack[1] == 'Cred') { 278 $this->_credData = trim($this->_chars); 279 } 280 } elseif ($element == 'MaxMsgSize') { 281 // </MaxMsgSize></Meta></SyncHdr></SyncML> 282 $this->_maxMsgSize = intval($this->_chars); 283 } 284 break; 285 286 case 4: 287 if ($this->_Stack[1] == 'Cred') { 288 if ($element == 'Format') { 289 // </Format></Meta></Cred></SyncHdr></SyncML> 290 $this->_credFormat = trim($this->_chars); 291 } elseif ($element == 'Type') { 292 // </Type></Meta></Cred></SyncHdr></SyncML> 293 $this->_credType = trim($this->_chars); 294 } 295 } 296 break; 297 } 298 299 parent::endElement($uri, $element); 300 } 301 302 function outputSyncHdr(&$output) 303 { 304 $attrs = array(); 305 306 $state = &$_SESSION['SyncML.state']; 307 308 $uri = $state->getURI(); 309 $uriMeta = $state->getURIMeta(); 310 311 $output->startElement($uri, 'SyncHdr', $attrs); 312 313 $output->startElement($uri, 'VerDTD', $attrs); 314 $chars = ($this->_version == 1) ? '1.1' : '1.0'; 315 $output->characters($chars); 316 $output->endElement($uri, 'VerDTD'); 317 318 $output->startElement($uri, 'VerProto', $attrs); 319 $chars = ($this->_version == 1) ? 'SyncML/1.1' : 'SyncML/1.0'; 320 $output->characters($chars); 321 $output->endElement($uri, 'VerProto'); 322 323 $output->startElement($uri, 'SessionID', $attrs); 324 $output->characters($this->_sessionID); 325 $output->endElement($uri, 'SessionID'); 326 327 $output->startElement($uri, 'MsgID', $attrs); 328 $output->characters($this->_msgID); 329 $output->endElement($uri, 'MsgID'); 330 331 $output->startElement($uri, 'Target', $attrs); 332 $output->startElement($uri, 'LocURI', $attrs); 333 $output->characters($this->_sourceURI); 334 $output->endElement($uri, 'LocURI'); 335 $output->startElement($uri, 'LocName', $attrs); 336 $output->characters($state->getLocName()); 337 $output->endElement($uri, 'LocName'); 338 $output->endElement($uri, 'Target'); 339 340 $output->startElement($uri, 'Source', $attrs); 341 $output->startElement($uri, 'LocURI', $attrs); 342 $output->characters($this->_targetURI); 343 $output->endElement($uri, 'LocURI'); 344 $output->endElement($uri, 'Source'); 345 346 /* 347 Do not send RespURI Element. It's optional and may be misleading: 348 $this->_targetURI is data from the client and not guaranteed to be 349 the correct URL for access. Let the client just stay with the same 350 URL it has used for the previous request(s). 351 */ 352 //$output->startElement($uri, 'RespURI', $attrs); 353 //$output->characters($this->_targetURI); 354 //$output->endElement($uri, 'RespURI'); 355 356 /* 357 $output->startElement($uri, 'Meta', $attrs); 358 359 // Dummy Max MsqSize, this is just put in to make the packet 360 // work, it is not a real value. 361 $output->startElement($uriMeta, 'MaxMsgSize', $attrs); 362 $chars = '50000'; 363 $output->characters($chars); 364 $output->endElement($uriMeta, 'MaxMsgSize'); 365 366 // Dummy MaxObjSize, this is just put in to make the packet 367 // work, it is not a real value. 368 $output->startElement($uriMeta, 'MaxObjSize', $attrs); 369 $chars = '4000000'; 370 $output->characters($chars); 371 $output->endElement($uriMeta, 'MaxObjSize'); 372 373 $output->endElement($uri, 'Meta'); 374 */ 375 376 $output->endElement($uri, 'SyncHdr'); 377 } 378 379 function getSourceURI() 380 { 381 return $this->_sourceURI; 382 } 383 384 function getLocName() 385 { 386 return $this->_locName; 387 } 388 389 function getSessionID() 390 { 391 return $this->_sessionID; 392 } 393 394 function getVersion() 395 { 396 return $this->_version; 397 } 398 399 function getMsgID() 400 { 401 return $this->_msgID; 402 } 403 404 function getTargetURI() 405 { 406 return $this->_targetURI; 407 } 408 409 function opaque($o) 410 { 411 } 412 413 } 414 415 /** 416 * Defined in SyncML Representation Protocol, version 1.1 5.2.3 417 * 418 * @package SyncML 419 */ 420 class SyncML_SyncMLBody extends SyncML_ContentHandler { 421 422 var $_currentCmdID = 1; 423 424 var $_currentCommand; 425 426 var $_actionCommands = false; 427 428 function startElement($uri, $element, $attrs) 429 { 430 parent::startElement($uri, $element, $attrs); 431 432 switch (count($this->_Stack)) { 433 case 1: 434 $state = &$_SESSION['SyncML.state']; 435 436 $this->_actionCommands = false; // so far, we have not seen commands that require action from our side 437 438 // <SyncML><SyncBody> 439 $uri = $state->getURI(); 440 $this->_output->startElement($uri, $element, $attrs); 441 442 // Right our status about the header. 443 $status = &new SyncML_Command_Status(($state->isAuthorized()) ? 444 RESPONSE_AUTHENTICATION_ACCEPTED : RESPONSE_INVALID_CREDENTIALS, 'SyncHdr'); 445 $status->setSourceRef($state->getSourceURI()); 446 $status->setTargetRef($state->getTargetURI()); 447 $status->setCmdRef(0); 448 449 $this->_currentCmdID = $status->output($this->_currentCmdID, $this->_output); 450 break; 451 452 case 2: 453 // <SyncML><SyncBody><[Command]> 454 $this->_currentCommand = SyncML_Command::factory($element); 455 $this->_currentCommand->startElement($uri, $element, $attrs); 456 457 if ($element != 'Status' && $element != 'Map' && $element != 'Final') { 458 // We've got to do something! This can't be the last 459 // packet. 460 $this->_actionCommands = true; 461 } 462 break; 463 464 default: 465 // <SyncML><SyncBody><Command><...> 466 $this->_currentCommand->startElement($uri, $element, $attrs); 467 break; 468 } 469 } 470 471 function endElement($uri, $element) 472 { 473 switch (count($this->_Stack)) { 474 case 1: 475 // </SyncBody></SyncML> 476 $state = &$_SESSION['SyncML.state']; 477 478 if ($state->hasPendingElements()) { 479 /* still something to do: don't close session */ 480 $this->_actionCommands = true; 481 } 482 $this->_currentCmdID = SyncML_Command_Final::outputFinal( 483 $this->_currentCmdID, 484 $this->_output); 485 $this->_output->endElement($uri, $element); 486 487 if (!$this->_actionCommands) { 488 // This packet did not contain any real actions, just 489 // status and map. This means we're done. The session 490 // can be closed and the anchors saved for the next 491 // sync. 492 $GLOBALS['backend']->logMessage('sync' . session_id() . 493 ' completed successfully!' . 494 ' Storing Client-TS ' . 495 $state->_clientAnchorNext, 496 __FILE__, __LINE__, PEAR_LOG_INFO); 497 $GLOBALS['backend']->writeSyncSummary( 498 $state->getSyncIdentifier(), 499 $state->_clientAnchorNext, 500 $state->_serverAnchorNext); 501 $log = $state->getLog(); 502 $s = ''; 503 foreach ($log as $k => $v) { 504 $s .= " $k=$v"; 505 } 506 $GLOBALS['backend']->logMessage('Summary:' . $s, __FILE__, __LINE__, PEAR_LOG_INFO); 507 508 // Session can be closed here. 509 session_unset(); 510 session_destroy(); 511 } else { 512 $GLOBALS['backend']->logMessage('SyncML: return message completed', 513 __FILE__, __LINE__, PEAR_LOG_DEBUG); 514 } 515 break; 516 517 case 2: 518 // </[Command]></SyncBody></SyncML> 519 $this->_currentCommand->endElement($uri, $element); 520 521 $this->_currentCmdID = $this->_currentCommand->output($this->_currentCmdID, $this->_output); 522 523 unset($this->_currentCommand); 524 break; 525 526 default: 527 // </...></[Command]></SyncBody></SyncML> 528 $this->_currentCommand->endElement($uri, $element); 529 break; 530 } 531 532 parent::endElement($uri, $element); 533 } 534 535 function characters($str) 536 { 537 if (isset($this->_currentCommand)) { 538 $this->_currentCommand->characters($str); 539 } 540 } 541 542 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |