Fwd: smarty apps can automagically be webservices

[email protected] (Martin Sarsale) Mon, 28 Mar 2005 11:01:17 -0300
Newsgroups php.smarty.dev
Message-ID <[email protected]>
---------- Forwarded message ----------
From: Martin Sarsale <[email protected]>
Date: Wed, 23 Mar 2005 14:04:30 -0300
Subject: smarty apps can automagically be webservices
To: [email protected]


Dear all:
The other day I had an idea which Im not sure if it's something
completely stupid or it rocks :)
For the last years, I've been thinking that html interfaces for
webapps suck (you're always reinventing the wheel, and it's a lot of
work if you want to do something great as gmail).

I understand that html is the best way to do "public" interfaces but
for the backoffice I wanted to have something that felt better to the
user (XUL, XWT, or just develop a client using webservices).

I started thinking about it and I noticed that it would be very easy
to have smarty apps to act as webservices by just adding some lines of
code at the start of the original code.

The idea is pretty simple: when the client asks for it, we send the
variables set into the smarty object, encoded as XML-RPC.
When the user makes a XML-RPC request, we'll translate it into HTTP
parameters ($_GET, $_POST and $_REQUEST variables).

This implementation just extends smarty class and when "display"
method is called, we check if the user has asked for the xmlrpc
version ("xmlrpc=1" on the GET string).
Also at the beginning (I don't like how this is implemented very much)
we check if the current is a XMLRPC request and if it is, we decode
the parameters and set them as $_GET,$_POST and $_REQUEST variables.

This has some security problems because the user can see all the
variables on the template and it's common to have sensitive
information assigned but not shown (think of a user listing where you
assign the output from "select * from users" to the template and in
the table users you have the password field. You won't print that
field on the template, but it still available if you ask for the
xmlrpc version).

I've been playing with this code and tikiwiki and I found that when a
lot of variables are assigned to the template, the answer gets pretty
big, so the xmlrpc client can ask for specific variables (
http://url/x.php?xmlrpc=1&xmlrpcvars[]=varX&xmlrpcvars[]=varY )
Also, if the webapp developer wants to tight things a bit he can
specify which variables he wants to provide to xmlrpc clients using
the xmlrpcvars (array) attribute ($smarty->xmlrpcvars=array('varX');)

I would like to hear some opinions about this, I know it's not a real
webservices server but I think some people can find it usefull to
instantly have its apps working as webservices.

pd: you'll find the code attached


--
Martin Sarsale - [email protected]




-- 
Martin Sarsale - [email protected]
smarty_xmlrpc.php (application/x-httpd-php, 1.5 KB)
<?
class Smarty_XMLRPC extends Smarty {
	var $xmlrpcvars=array();
	function display($resource_name, $cache_id = null, $compile_id = null){
		
		if (!empty($_GET['xmlrpc'])){
			if (empty($this->xmlrpcvars) && empty($_GET['xmlrpcvars'])){
				$ret=$this->_tpl_vars;
			}else{
				$ret=array();
				$vars=$this->xmlrpcvars;
				if (empty($vars) && isset($_GET['xmlrpcvars']) && is_array($_GET['xmlrpcvars'])){
					$vars=$vars+$_GET['xmlrpcvars'];
				}
				foreach($vars as $v){
					$ret[$v]=$this->_tpl_vars[$v];
				}
			}
			print xmlrpc_encode($ret);
		}else{
			if ($cache_id){
				return parent::display($resource_name,$cache_id);
			}elseif($compile_id){
				return parent::display($resource_name,$cache_id,$compile_id);
			}else{
				return parent::display($resource_name);
			}
		}
		
	}
}
if (!empty($_GET['xmlrpc'])){
	$vars=(isset($HTTP_RAW_POST_DATA)) ? xmlrpc_decode($HTTP_RAW_POST_DATA) : array();
	$method=(isset($HTTP_RAW_POST_DATA)) ? xmlrpc_parse_method_descriptions($HTTP_RAW_POST_DATA) : null;
	if (!empty($method) && isset($method['methodname'])){
				$_POST[$k]=$_REQUEST[$k]=$_GET[$k]=$method['methodname'];
	}
	if ($vars){
		foreach($vars[0] as $k=>$v){
			if (!is_numeric($k)){
				$_POST[$k]=$k;
				$_REQUEST[$k]=&$_POST[$k];
				$_GET[$k]=&$_POST[$k];
			}
		}
	}
	// ob_start(); print_R($y); print_R($_POST); print_R($_GET); print_R($_REQUEST); $x=ob_get_contents(); ob_end_clean(); $f=fopen("/tmp/log",'a'); fputs($f,$x."\n-------------\n"); fclose($f);

}
?>