diff options
| -rw-r--r-- | demos/address-book/protected/application.xml | 12 | ||||
| -rw-r--r-- | demos/address-book/protected/pages/AddressProvider.php | 25 | ||||
| -rw-r--r-- | demos/address-book/protected/pages/Home.page | 15 | ||||
| -rw-r--r-- | demos/address-book/protected/pages/flex/bin/flex_address_book.swf | bin | 300237 -> 307529 bytes | |||
| -rw-r--r-- | demos/address-book/protected/pages/flex/flex_address_book.mxml | 88 | ||||
| -rw-r--r-- | framework/3rdParty/WsdlGen/Wsdl.php | 2 | ||||
| -rw-r--r-- | framework/Web/Services/TSoapService.php | 76 | 
7 files changed, 173 insertions, 45 deletions
| diff --git a/demos/address-book/protected/application.xml b/demos/address-book/protected/application.xml index 8e87be8c..8b68fe8f 100644 --- a/demos/address-book/protected/application.xml +++ b/demos/address-book/protected/application.xml @@ -3,8 +3,9 @@  <paths>
  	<using namespace="System.Data.*" />
 +	<using namespace="System.Security.*" />
  	<using namespace="System.Data.ActiveRecord.*" />
 -	<using namespace="System.Web.Services.TSoapService" />
 +	<using namespace="System.Web.Services.*" />
  </paths>
  <modules>
 @@ -12,6 +13,14 @@  	<module id="sqlite-db" class="TActiveRecordConfig">
  		<database ConnectionString="sqlite:./protected/pages/sqlite.db" />
  	</module>
 +
 +	<!-- authentication and authorization -->
 +  	<module id="users" class="TUserManager" PasswordMode="Clear">
 +		<user name="demo" password="demo" />
 +      	<user name="admin" password="admin" />
 +     </module>
 +    <module id="auth" class="TAuthManager" UserManager="users" LoginPage="Login" />
 +
  </modules>
  <services>
 @@ -21,6 +30,7 @@  			provider="Application.pages.AddressProvider"
  			ClassMaps="AddressRecord" />
  	</service>
 +
  </services>
  </application>
\ No newline at end of file diff --git a/demos/address-book/protected/pages/AddressProvider.php b/demos/address-book/protected/pages/AddressProvider.php index bbfedd1b..ae0b369f 100644 --- a/demos/address-book/protected/pages/AddressProvider.php +++ b/demos/address-book/protected/pages/AddressProvider.php @@ -6,9 +6,31 @@ Prado::using('Application.pages.AddressRecord');   * @version $Id$
   * @since 3.1
   */
 -class AddressProvider
 +class AddressProvider extends TApplicationComponent
  {
  	/**
 +	 * @throws exception if not logged in
 +	 */ 
 +	public function __construct($server)
 +	{
 +		$authMethods = $server->getRequestedMethod()!=='login';
 +		$guestUser = $this->User ? $this->User->IsGuest : true;
 +		if($authMethods && $guestUser)
 +			throw new TException('authentication required');
 +	}
 +
 +	/**
 +	 * @param string $username
 +	 * @param string $password
 +	 * @return boolean
 +	 * @soapmethod
 +	 */
 +	public function login($username, $password)
 +	{
 +		return $this->Application->Modules['auth']->login($username, $password);
 +	}
 +
 +	/**
  	 * @return AddressRecord[]
  	 * @soapmethod
  	 */
 @@ -17,7 +39,6 @@ class AddressProvider  		return AddressRecord::finder()->findAll();
  	}
 -
  	/**
  	 * Update address if $data->id > 0, otherwise add new address.
  	 * @param AddressRecord $data
 diff --git a/demos/address-book/protected/pages/Home.page b/demos/address-book/protected/pages/Home.page index 801267e7..1489cf86 100644 --- a/demos/address-book/protected/pages/Home.page +++ b/demos/address-book/protected/pages/Home.page @@ -2,24 +2,15 @@  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
  	<title>Prado Address Book</title>
 -	<style type="text/css">
 -	/*<![CDATA[*/
 -		body
 -		{
 -			margin:0; padding: 0;
 -		}
 -	/*]]>*/
 -	</style>
  </head>
  <body>
 -
 -<div style="margin: 5em auto">
 +<h1>Prado + Flex + Soap Demo</h1>
 +<h3>Flash player version 9 or greater is required.</h3>
 +<p>Username/password: demo/demo </p>
  <com:Application.pages.FlexApp
  	BinDirectory=<%~ flex/bin %>
  	AppName="flex_address_book"
  	Parameters.wsdl="<%= $this->Request->constructUrl('soap', 'address-book.wsdl') %>"
  	Width="100%" Height="300"/>
 -</div>
 -
  </body>
  </html>
\ No newline at end of file diff --git a/demos/address-book/protected/pages/flex/bin/flex_address_book.swf b/demos/address-book/protected/pages/flex/bin/flex_address_book.swfBinary files differ index 9c3e63ef..03e29cf8 100644 --- a/demos/address-book/protected/pages/flex/bin/flex_address_book.swf +++ b/demos/address-book/protected/pages/flex/bin/flex_address_book.swf diff --git a/demos/address-book/protected/pages/flex/flex_address_book.mxml b/demos/address-book/protected/pages/flex/flex_address_book.mxml index d6db809a..eac50fe7 100644 --- a/demos/address-book/protected/pages/flex/flex_address_book.mxml +++ b/demos/address-book/protected/pages/flex/flex_address_book.mxml @@ -10,10 +10,27 @@  	backgroundGradientColors="0" 
  	layout="vertical" creationComplete="initApp()">
  	<mx:states>
 -		<mx:State name="details">
 +		<mx:State name="grid">
 +			<mx:RemoveChild target="{form1}"/>
 +			<mx:AddChild relativeTo="{panel1}" position="lastChild">
 +				<mx:HBox id="hbox1">
 +					<mx:DataGrid id="list1" dataProvider="{addrSrv.getAllAddress.lastResult}" 
 +							width="350" click="currentState='details'">
 +						<mx:columns>
 +							<mx:DataGridColumn headerText="Name" width="175" dataField="username"/>
 +							<mx:DataGridColumn headerText="Phone" dataField="phone"/>
 +						</mx:columns>
 +					</mx:DataGrid>
 +				</mx:HBox>
 +			</mx:AddChild>
 +			<mx:SetProperty target="{button2}" name="visible" value="true"/>
 +			<mx:SetProperty target="{button3}" name="visible" value="true"/>
 +			<mx:SetProperty target="{controlbar1}" name="height"/>
 +		</mx:State>
 +		<mx:State name="details" basedOn="grid">
  			<mx:AddChild relativeTo="{hbox1}" position="lastChild">
  				<mx:Form>
 -					<mx:FormItem label="Username:">
 +					<mx:FormItem label="Name:">
  						<mx:TextInput id="_username" text="{list1.selectedItem.username}"/>
  					</mx:FormItem>
  					<mx:FormItem label="Phone:">
 @@ -28,10 +45,15 @@  	<mx:PhoneNumberValidator id="val1" source="{_phone}" property="text" />
  	<mx:StringValidator id="val2" source="{_username}" property="text"
  		minLength="3" maxLength="20" />
 +	
 +	<mx:Validator id="val3" source="{login_name}" property="text" />
 +	<mx:Validator id="val4" source="{login_pass}" property="text" />
 +	<mx:Validator id="val5" requiredFieldError="Username and password did not match!" />	
  	<mx:WebService id="addrSrv" fault="dataError(event)">
  		<mx:operation name="saveAddress" result="addrSrv.getAllAddress()" />
  		<mx:operation name="deleteAddress" result="addrSrv.getAllAddress()" />
 +		<mx:operation name="login" result="loginReturned(event)" />
  	</mx:WebService>
  	<mx:Script>
 @@ -49,7 +71,6 @@  			private function initApp():void
  			{
  				addrSrv.loadWSDL(getAddressBookWsdl());
 -				addrSrv.getAllAddress();
  			}
  			private function getAddressBookWsdl():String
 @@ -75,31 +96,62 @@  					data.username = _username.text;
  					data.phone = _phone.text;
  					addrSrv.saveAddress(data);
 -					currentState='';
 +					currentState='grid';
  				}
  			}
  			private function doDelete():void
  			{
  				addrSrv.deleteAddress(list1.selectedItem.id);
 -				currentState='';
 +				currentState='grid';
 +			}
 +			
 +			private function doLogin():void
 +			{
 +				if(Validator.validateAll([val3, val4]).length == 0)
 +				{
 +					addrSrv.login(login_name.text, login_pass.text);
 +					login_name.enabled=false;
 +					login_pass.enabled=false;
 +					progress1.visible=true;
 +				}	
 +			}
 +			
 +			private function loginReturned(event:ResultEvent):void
 +			{
 +				if(!event.result)
 +				{
 +					login_name.enabled=true;
 +					login_pass.enabled=true;
 +					progress1.visible=false;
 +					Alert.show("Username and password did not match!", "Login Error");
 +				}
 +				else
 +				{
 +					addrSrv.getAllAddress();
 +					currentState='grid';
 +				}
  			}
  		]]>
  	</mx:Script>
 -
 -	
 +		
  	<mx:Panel layout="vertical" title="Prado Address Book" id="panel1" resizeEffect="Resize">
 -		<mx:HBox id="hbox1">
 -			<mx:DataGrid id="list1" dataProvider="{addrSrv.getAllAddress.lastResult}" width="350" click="currentState='details'">
 -				<mx:columns>
 -					<mx:DataGridColumn headerText="Name" width="150" dataField="username"/>
 -					<mx:DataGridColumn headerText="Phone" dataField="phone"/>
 -				</mx:columns>
 -			</mx:DataGrid>
 -		</mx:HBox>
 -		<mx:ControlBar id="controlbar1">
 -			<mx:Button label="New" click="list1.selectedIndex=-1; currentState='details'"/>
 -			<mx:Button label="Delete" enabled="{list1.selectedIndex >= 0}" click="doDelete()"/>
 +		<mx:Form id="form1">
 +			<mx:FormItem label="Username:">
 +				<mx:TextInput id="login_name" />
 +			</mx:FormItem>
 +			<mx:FormItem label="Password:">
 +				<mx:TextInput id="login_pass"/>
 +			</mx:FormItem>
 +			<mx:FormItem>
 +				<mx:Button label="Login" click="doLogin()" id="button1"/>
 +			</mx:FormItem>
 +		<mx:ProgressBar width="100%" indeterminate="true" id="progress1" showEffect="Fade" hideEffect="Fade"
 +				labelPlacement="center" label="Verifying..." color="#ffffff" visible="false"/>
 +		</mx:Form>
 +		<mx:ControlBar id="controlbar1" height="10">
 +			<mx:Button label="New" click="list1.selectedIndex=-1; currentState='details'" visible="false" id="button2"/>
 +			<mx:Button label="Delete" enabled="{list1.selectedIndex >= 0}" click="doDelete()" visible="false" id="button3"/>
  		</mx:ControlBar>
  	</mx:Panel>
 diff --git a/framework/3rdParty/WsdlGen/Wsdl.php b/framework/3rdParty/WsdlGen/Wsdl.php index 56676a26..eb41049f 100644 --- a/framework/3rdParty/WsdlGen/Wsdl.php +++ b/framework/3rdParty/WsdlGen/Wsdl.php @@ -85,7 +85,7 @@ class Wsdl  	{  		$this->serviceName = $name;  		if ($serviceUri == '') $serviceUri = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']; -		$this->serviceUri = $serviceUri; +		$this->serviceUri = str_replace('&', '&', $serviceUri);  		$this->types = new ArrayObject();  		$this->targetNamespace = 'urn:'.$name.'wsdl';  	} diff --git a/framework/Web/Services/TSoapService.php b/framework/Web/Services/TSoapService.php index e4a1c67e..d838217e 100644 --- a/framework/Web/Services/TSoapService.php +++ b/framework/Web/Services/TSoapService.php @@ -286,7 +286,11 @@ class TSoapServer extends TApplicationComponent  	private $_uri='';  	private $_classMap;  	private $_persistent=false; -	private $_wsdlUri=''; +	private $_wsdlUri='';
 +
 +	private $_requestedMethod;
 +
 +	private $_server;  	/**  	 * @return string the ID of the SOAP server @@ -316,31 +320,81 @@ class TSoapServer extends TApplicationComponent  		{  			Prado::using($provider);  			$providerClass=($pos=strrpos($provider,'.'))!==false?substr($provider,$pos+1):$provider; +			$this->guessMethodCallRequested($providerClass);
  			$server=$this->createServer(); -			$server->setClass($providerClass); +			$server->setClass($providerClass, $this);  			if($this->_persistent)  				$server->setPersistence(SOAP_PERSISTENCE_SESSION);  		}  		else  			$server=$this->createServer();  		try -		{		 +		{
  			$server->handle();  		}  		catch (Exception $e) -		{ -			$server->fault("SERVER", $e->getMessage(),"", $e->__toString(), ''); +		{
 +			if($this->getApplication()->getMode()===TApplicationMode::Debug)
 +				$this->fault($e->getMessage(), $e->__toString());
 +			else
 +				$this->fault($e->getMessage());  		} +	}
 +
 +	/**
 +	 * Generate a SOAP fault message.
 +	 * @param string message title
 +	 * @param mixed message details
 +	 * @param string message code, defalt is 'SERVER'.
 +	 * @param string actors
 +	 * @param string message name
 +	 */
 +	public function fault($title, $details='', $code='SERVER', $actor='', $name='')
 +	{
 +		$this->_server->fault($code, $title, $actor, $details, $name);
 +	}
 +
 +	/**
 +	 * Guess the SOAP method request from the actual SOAP message
 +	 *
 +	 * @param string $class current handler class.
 +	 */
 +	protected function guessMethodCallRequested($class)
 +	{
 +		$namespace = $class.'wsdl';
 +		$message = file_get_contents("php://input");
 +		$matches= array();
 +		if(preg_match('/xmlns:([^=]+)="urn:'.$namespace.'"/', $message, $matches))
 +		{
 +			if(preg_match('/<'.$matches[1].':([a-zA-Z_]+[a-zA-Z0-9_]+)/', $message, $method))
 +			{
 +				$this->_requestedMethod = $method[1];
 +			}
 +		}
 +	}
 +
 +	/**
 +	 * Soap method guessed from the SOAP message received.
 +	 * @return string soap method request, null if not found.
 +	 */
 +	public function getRequestedMethod()
 +	{
 +		return $this->_requestedMethod;
  	}  	/** -	 * Creates the SoapServer instance. +	 * Creates the SoapServer instance.
 +	 * @return SoapServer  	 */  	protected function createServer() -	{ -		if($this->getApplication()->getMode()===TApplicationMode::Debug) -			ini_set("soap.wsdl_cache_enabled",0); -		return new SoapServer($this->getWsdlUri(),$this->getOptions()); +	{
 +		if($this->_server===null)
 +		{
 +			if($this->getApplication()->getMode()===TApplicationMode::Debug) +				ini_set("soap.wsdl_cache_enabled",0); +			$this->_server = new SoapServer($this->getWsdlUri(),$this->getOptions());
 +		} +		return $this->_server;
  	}  	/** @@ -533,7 +587,7 @@ class TSoapServer extends TApplicationComponent  	/**  	 * @return string comma delimit list of class names -	 */	 +	 */  	public function setClassMaps($classes)  	{  		$this->_classMap = $classes; | 
