Web Services

Right now the web services are exposed as SOAP. Work is underway to support REST. The NuSoap library is used,but it does not support the entire WS* stack. Thus HTTP Basic authentication is used. Research is underway in to the recently released WSF/PHP SOAP library( released last month). Its the only library that supports the entire WS* stack.

SAHANA web services requirements

  1. In the admin section, you can turn off authentication for web services. Thus if you turn off authentication here is sample code to access the web service.
<?php
// Pull in the NuSOAP code
require_once('nusoap.php');
 
$url='http://localhost/trunk/index.php?stream=soap&act=reg&wbsmod=or&mod=ws';
//make sure you specify the URL of the Sahana server, you installed
$client = new soapclient($url);
 
// Check for an error
$err = $client->getError();
if ($err) {
    // Display the error
    echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
    // At this point, you know the call that follows will fail
}
// Call the SOAP method
$result = $client->call('shn_or_type_list', array('name' => 'Ravindra'));
?>
  1. If authentication is required, please read this section

Since i wanted to authenticate based on the following policy, had to use the basic authentication credentials in an alternative way. I used this policy ,since just user name and password sent as plain text for basic authentication is very insecure.

Policy: In the process of signing up for the API key the following are issued

  1. API key
  2. Password
  3. Secret Code

API key and Password helps to identify the user. How ever, since these are transmitted in plain text needed something additional to prevent impersonation.Thus a digest is signed using HMAC_Sha1 algorithm and this signature is sent in the basic authentication. The digest is also , sent created using the time and few other values. How ever ,yet to write code to use those. Since the secret is shared only between the web server and user , only the user could have signed to be matched with the signature created with the shared secret at the server applied on the digest. How ever with basic authentication, only two values could be sent, but here 4 values are being sent. API key, password and digest were sent as PHP_AUTH_USER separated by comma. PHP_AUTH_PW contains the signature. How ever , there are restrictions on the characters what can be sent in PHP_AUTH_PW. Thus most of the time , only part of the weird signature gets transmitted. As a work around md5 hash is applied to the signature and sent , and doing the comparison also md5 is used at the last stage. from the client side, the NuSoap method “setCredentials”, helps to specify these parameters programmatically.

Here is the complete client code when authentication is required at the server.

<?php
// Pull in the NuSOAP code
require_once('nusoap.php');
$digest="adsadsdsd";//can be anything for the moment
$secret="64b941befb07d2d3522c9aff7b858a6b";
// replace with the secret you obtain when you sign up for the Key
$sign=_sahana_hmac_sha1($digest,$secret);
$sign=md5($sign);
$url='http://localhost/trunk/index.php?stream=soap&act=reg&wbsmod=or&mod=ws';
//make sure you specify the URL of the Sahana server, you installed
$client = new soapclient($url);
$api_key=””;//specify the API Key you obtain when you sign up for the Key
$pwd=””;//specify the Password you obtain when you sign up for the Key
$arg1=trim($api_key.",".$pwd.",".$digest);
$client->setCredentials($arg1,$sign);
// Check for an error
$err = $client->getError();
if ($err) {
    // Display the error
    echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
    // At this point, you know the call that follows will fail
}
// Call the SOAP method
$result = $client->call('shn_or_type_list', array('name' => 'Ravindra'));
 
function _sahana_hmac_sha1($data,$key) {
	if(($data==null)or($key==null)){
		return null;
	}
    $blocksize = 64;
    $hashfunc = 'sha1';
 
    if (strlen($key) > $blocksize) {
        $key = pack('H*', $hashfunc($key));
    }
 
    $key = str_pad($key, $blocksize, chr(0x00));
    $ipad = str_repeat(chr(0x36), $blocksize);
    $opad = str_repeat(chr(0x5c), $blocksize);
    $hmac = pack(
                    'H*', $hashfunc(
                            ($key^$opad).pack(
                                    'H*', $hashfunc(
                                            ($key^$ipad).$data
                                    )
                            )
                    )
                );
    return $hmac;
}
 
?>

Module developers can expose their functions using Sahana Web Services module. Developers needs to create two files to to their module directory.

  1. api.inc
  2. ws.xml

api.inc

In this file, developers can define functions that are expected to be exposed as Web Services.

e.g.

/**.
 *This function return all the catalog names
 * @access public
 * @return array
 */
function shn_cs_get_all_catalog_names()
{
    global $global;
    $db=$global["db"];
    $query="SELECT ct_uuid,parentid,name FROM ct_catalogue";
    $res=$db->Execute($query);
    $unit_name_arr = array();
 
    while(!$res==NULL && !$res->EOF)
    {
    	$catalog_list[] = array('ct_id' => $res->fields["ct_uuid"], 'parent_id' => $res->fields["parentid"], 'name' => $res->fields["name"]);
    	$res->MoveNext();
    }
 
    return $catalog_list;
}

ws.xml

This file is used by the WS module to identify exposed services and their input/output types.

e.g.

<?xml version="1.0" encoding="ISO-8859-1"?>
<web_services>
	<services>
	 	<service>
	 		<name>
	 			demo function
	 		</name>
	 		<http_type>GET</http_type>
	 		<api_function>
	 			shn_demo_function
	 		</api_function>
	 		<params>
                             <param name="param0" />
                             <param name="param1" />
                        </params>
                        <input_form>false</input_form>
             		<output type="BasicArray" />
	 		<documentation>
	 			A demo function
	 		</documentation>
	  	</service>
	 	<service>
	 		<!-- another service definition goes here -->
	 	</service>
	 </services>
 </web_services>

According to the parameter list (that lies beween “params” tag), Web service client interface will be automatically created to get parameters from the user.

E.g.

In above example there are two params. So there will be two text boxes will be populated in the client interface to get parameter values.

If Developer needs to have his/her own Client interface, he or she can write a function in his/her api.inc in the following format.

function shn_<module>_ws_default()

e.g. If developer needs to have his/her own client interface in Synchronization module then he/she can write that client interface in following function.

 
function shn_sync_ws_default(){
//your code here (client interface)
}

**Important - Also developer needs to add special XML tag called <input_form> into the ws.xml and pass the value either “true” or “false”. If it is “true” then ws module will automatically call the above function (shn_<module>_ws_default()) and generate developer's web interface. Otherwise (if it is “false”)it will generate client interface for according to developers param values.


Navigation
  • Navigate