315 } catch (Exception $e) { |
321 } catch (Exception $e) { |
316 require_once 'Zend/Amf/Server/Exception.php'; |
322 require_once 'Zend/Amf/Server/Exception.php'; |
317 throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e); |
323 throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e); |
318 } |
324 } |
319 // Add the new loaded class to the server. |
325 // Add the new loaded class to the server. |
|
326 require_once 'Zend/Amf/Server/Exception.php'; |
320 $this->setClass($className, $source); |
327 $this->setClass($className, $source); |
321 } |
328 } |
322 |
329 |
323 if (!isset($this->_table[$qualifiedName])) { |
330 if (!isset($this->_table[$qualifiedName])) { |
324 // Source is null or doesn't contain specified method |
331 // Source is null or doesn't contain specified method |
331 $argv = $info->getInvokeArguments(); |
338 $argv = $info->getInvokeArguments(); |
332 |
339 |
333 if (0 < count($argv)) { |
340 if (0 < count($argv)) { |
334 $params = array_merge($params, $argv); |
341 $params = array_merge($params, $argv); |
335 } |
342 } |
|
343 |
|
344 $params = $this->_castParameters($info, $params); |
336 |
345 |
337 if ($info instanceof Zend_Server_Reflection_Function) { |
346 if ($info instanceof Zend_Server_Reflection_Function) { |
338 $func = $info->getName(); |
347 $func = $info->getName(); |
339 $this->_checkAcl(null, $func); |
348 $this->_checkAcl(null, $func); |
340 $return = call_user_func_array($func, $params); |
349 $return = call_user_func_array($func, $params); |
492 $response = $this->getResponse(); |
501 $response = $this->getResponse(); |
493 |
502 |
494 // set response encoding |
503 // set response encoding |
495 $response->setObjectEncoding($objectEncoding); |
504 $response->setObjectEncoding($objectEncoding); |
496 |
505 |
497 $responseBody = $request->getAmfBodies(); |
506 // Authenticate, if we have credential headers |
498 |
507 $error = false; |
499 $handleAuth = false; |
508 $headers = $request->getAmfHeaders(); |
500 if ($this->_auth) { |
509 if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) |
501 $headers = $request->getAmfHeaders(); |
510 && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid) |
502 if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) && |
511 && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password) |
503 isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) { |
512 ) { |
504 $handleAuth = true; |
513 try { |
|
514 if ($this->_handleAuth( |
|
515 $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid, |
|
516 $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password |
|
517 )) { |
|
518 // use RequestPersistentHeader to clear credentials |
|
519 $response->addAmfHeader( |
|
520 new Zend_Amf_Value_MessageHeader( |
|
521 Zend_Amf_Constants::PERSISTENT_HEADER, |
|
522 false, |
|
523 new Zend_Amf_Value_MessageHeader( |
|
524 Zend_Amf_Constants::CREDENTIALS_HEADER, |
|
525 false, null |
|
526 ) |
|
527 ) |
|
528 ); |
|
529 } |
|
530 } catch (Exception $e) { |
|
531 // Error during authentication; report it |
|
532 $error = $this->_errorMessage( |
|
533 $objectEncoding, |
|
534 '', |
|
535 $e->getMessage(), |
|
536 $e->getTraceAsString(), |
|
537 $e->getCode(), |
|
538 $e->getLine() |
|
539 ); |
|
540 $responseType = Zend_AMF_Constants::STATUS_METHOD; |
505 } |
541 } |
506 } |
542 } |
507 |
543 |
508 // Iterate through each of the service calls in the AMF request |
544 // Iterate through each of the service calls in the AMF request |
509 foreach($responseBody as $body) |
545 foreach($request->getAmfBodies() as $body) |
510 { |
546 { |
|
547 if ($error) { |
|
548 // Error during authentication; just report it and be done |
|
549 $responseURI = $body->getResponseURI() . $responseType; |
|
550 $newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $error); |
|
551 $response->addAmfBody($newBody); |
|
552 continue; |
|
553 } |
511 try { |
554 try { |
512 if ($handleAuth) { |
555 switch ($objectEncoding) { |
513 if ($this->_handleAuth( |
556 case Zend_Amf_Constants::AMF0_OBJECT_ENCODING: |
514 $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid, |
557 // AMF0 Object Encoding |
515 $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)) { |
|
516 // use RequestPersistentHeader to clear credentials |
|
517 $response->addAmfHeader( |
|
518 new Zend_Amf_Value_MessageHeader( |
|
519 Zend_Amf_Constants::PERSISTENT_HEADER, |
|
520 false, |
|
521 new Zend_Amf_Value_MessageHeader( |
|
522 Zend_Amf_Constants::CREDENTIALS_HEADER, |
|
523 false, null))); |
|
524 $handleAuth = false; |
|
525 } |
|
526 } |
|
527 |
|
528 if ($objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) { |
|
529 // AMF0 Object Encoding |
|
530 $targetURI = $body->getTargetURI(); |
|
531 $message = ''; |
|
532 |
|
533 // Split the target string into its values. |
|
534 $source = substr($targetURI, 0, strrpos($targetURI, '.')); |
|
535 |
|
536 if ($source) { |
|
537 // Break off method name from namespace into source |
|
538 $method = substr(strrchr($targetURI, '.'), 1); |
|
539 $return = $this->_dispatch($method, $body->getData(), $source); |
|
540 } else { |
|
541 // Just have a method name. |
|
542 $return = $this->_dispatch($targetURI, $body->getData()); |
|
543 } |
|
544 } else { |
|
545 // AMF3 read message type |
|
546 $message = $body->getData(); |
|
547 if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) { |
|
548 // async call with command message |
|
549 $return = $this->_loadCommandMessage($message); |
|
550 } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) { |
|
551 require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php'; |
|
552 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); |
|
553 $return->body = $this->_dispatch($message->operation, $message->body, $message->source); |
|
554 } else { |
|
555 // Amf3 message sent with netConnection |
|
556 $targetURI = $body->getTargetURI(); |
558 $targetURI = $body->getTargetURI(); |
|
559 $message = ''; |
557 |
560 |
558 // Split the target string into its values. |
561 // Split the target string into its values. |
559 $source = substr($targetURI, 0, strrpos($targetURI, '.')); |
562 $source = substr($targetURI, 0, strrpos($targetURI, '.')); |
560 |
563 |
561 if ($source) { |
564 if ($source) { |
564 $return = $this->_dispatch($method, $body->getData(), $source); |
567 $return = $this->_dispatch($method, $body->getData(), $source); |
565 } else { |
568 } else { |
566 // Just have a method name. |
569 // Just have a method name. |
567 $return = $this->_dispatch($targetURI, $body->getData()); |
570 $return = $this->_dispatch($targetURI, $body->getData()); |
568 } |
571 } |
569 } |
572 break; |
|
573 case Zend_Amf_Constants::AMF3_OBJECT_ENCODING: |
|
574 default: |
|
575 // AMF3 read message type |
|
576 $message = $body->getData(); |
|
577 if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) { |
|
578 // async call with command message |
|
579 $return = $this->_loadCommandMessage($message); |
|
580 } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) { |
|
581 require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php'; |
|
582 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); |
|
583 $return->body = $this->_dispatch($message->operation, $message->body, $message->source); |
|
584 } else { |
|
585 // Amf3 message sent with netConnection |
|
586 $targetURI = $body->getTargetURI(); |
|
587 |
|
588 // Split the target string into its values. |
|
589 $source = substr($targetURI, 0, strrpos($targetURI, '.')); |
|
590 |
|
591 if ($source) { |
|
592 // Break off method name from namespace into source |
|
593 $method = substr(strrchr($targetURI, '.'), 1); |
|
594 $return = $this->_dispatch($method, $body->getData(), $source); |
|
595 } else { |
|
596 // Just have a method name. |
|
597 $return = $this->_dispatch($targetURI, $body->getData()); |
|
598 } |
|
599 } |
|
600 break; |
570 } |
601 } |
571 $responseType = Zend_AMF_Constants::RESULT_METHOD; |
602 $responseType = Zend_AMF_Constants::RESULT_METHOD; |
572 } catch (Exception $e) { |
603 } catch (Exception $e) { |
573 $return = $this->_errorMessage($objectEncoding, $message, |
604 $return = $this->_errorMessage($objectEncoding, $message, |
574 $e->getMessage(), $e->getTraceAsString(),$e->getCode(), $e->getLine()); |
605 $e->getMessage(), $e->getTraceAsString(),$e->getCode(), $e->getLine()); |
931 */ |
962 */ |
932 public function listMethods() |
963 public function listMethods() |
933 { |
964 { |
934 return array_keys($this->_table); |
965 return array_keys($this->_table); |
935 } |
966 } |
|
967 |
|
968 /** |
|
969 * Cast parameters |
|
970 * |
|
971 * Takes the provided parameters from the request, and attempts to cast them |
|
972 * to objects, if the prototype defines any as explicit object types |
|
973 * |
|
974 * @param Reflection $reflectionMethod |
|
975 * @param array $params |
|
976 * @return array |
|
977 */ |
|
978 protected function _castParameters($reflectionMethod, array $params) |
|
979 { |
|
980 $prototypes = $reflectionMethod->getPrototypes(); |
|
981 $nonObjectTypes = array( |
|
982 'null', |
|
983 'mixed', |
|
984 'void', |
|
985 'unknown', |
|
986 'bool', |
|
987 'boolean', |
|
988 'number', |
|
989 'int', |
|
990 'integer', |
|
991 'double', |
|
992 'float', |
|
993 'string', |
|
994 'array', |
|
995 'object', |
|
996 'stdclass', |
|
997 ); |
|
998 $types = array(); |
|
999 foreach ($prototypes as $prototype) { |
|
1000 foreach ($prototype->getParameters() as $parameter) { |
|
1001 $type = $parameter->getType(); |
|
1002 if (in_array(strtolower($type), $nonObjectTypes)) { |
|
1003 continue; |
|
1004 } |
|
1005 $position = $parameter->getPosition(); |
|
1006 $types[$position] = $type; |
|
1007 } |
|
1008 } |
|
1009 |
|
1010 if (empty($types)) { |
|
1011 return $params; |
|
1012 } |
|
1013 |
|
1014 foreach ($params as $position => $value) { |
|
1015 if (!isset($types[$position])) { |
|
1016 // No specific type to cast to? done |
|
1017 continue; |
|
1018 } |
|
1019 |
|
1020 $type = $types[$position]; |
|
1021 |
|
1022 if (!class_exists($type)) { |
|
1023 // Not a class, apparently. done |
|
1024 continue; |
|
1025 } |
|
1026 |
|
1027 if ($value instanceof $type) { |
|
1028 // Already of the right type? done |
|
1029 continue; |
|
1030 } |
|
1031 |
|
1032 if (!is_array($value) && !is_object($value)) { |
|
1033 // Can't cast scalars to objects easily; done |
|
1034 continue; |
|
1035 } |
|
1036 |
|
1037 // Create instance, and loop through value to set |
|
1038 $object = new $type; |
|
1039 foreach ($value as $property => $defined) { |
|
1040 $object->{$property} = $defined; |
|
1041 } |
|
1042 |
|
1043 $params[$position] = $object; |
|
1044 } |
|
1045 |
|
1046 return $params; |
|
1047 } |
936 } |
1048 } |