diff options
author | rvelices <rv-github@modusoptimus.com> | 2007-01-06 11:13:08 +0000 |
---|---|---|
committer | rvelices <rv-github@modusoptimus.com> | 2007-01-06 11:13:08 +0000 |
commit | f992150313a63d30aeda6e5f3dcd64fc62a06adb (patch) | |
tree | 6295bead230ea82610b53a09a9d52b15a6991768 /include | |
parent | 6314122c5d610f2fbc9fc5c60dec32f7f901a2bb (diff) |
Web service first version.
git-svn-id: http://piwigo.org/svn/trunk@1698 68402e56-0260-453c-a942-63ccdbb3a9ee
Diffstat (limited to 'include')
-rw-r--r-- | include/ws_core.inc.php | 611 | ||||
-rw-r--r-- | include/ws_functions.inc.php | 716 | ||||
-rw-r--r-- | include/ws_protocols/json_encoder.php | 90 | ||||
-rw-r--r-- | include/ws_protocols/php_encoder.php | 57 | ||||
-rw-r--r-- | include/ws_protocols/rest_encoder.php | 285 | ||||
-rw-r--r-- | include/ws_protocols/rest_handler.php | 60 | ||||
-rw-r--r-- | include/ws_protocols/xmlrpc_encoder.php | 118 |
7 files changed, 1937 insertions, 0 deletions
diff --git a/include/ws_core.inc.php b/include/ws_core.inc.php new file mode 100644 index 000000000..61c94b295 --- /dev/null +++ b/include/ws_core.inc.php @@ -0,0 +1,611 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $URL: svn+ssh://rvelices@svn.gna.org/svn/phpwebgallery/trunk/action.php $ +// | last update : $Date: 2006-12-21 18:49:12 -0500 (Thu, 21 Dec 2006) $ +// | last modifier : $Author: rvelices $ +// | revision : $Rev: 1678 $ +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +/**** WEB SERVICE CORE CLASSES************************************************ + * PwgServer - main object - the link between web service methods, request + * handler and response encoder + * PwgRequestHandler - base class for handlers + * PwgResponseEncoder - base class for response encoders + * PwgError, PwgNamedArray, PwgNamedStruct - can be used by web service functions + * as return values + */ + + +define( 'WS_PARAM_ACCEPT_ARRAY', 0x010000 ); +define( 'WS_PARAM_FORCE_ARRAY', 0x030000 ); +define( 'WS_PARAM_OPTIONAL', 0x040000 ); + +define( 'WS_ERR_INVALID_METHOD', 1001 ); +define( 'WS_ERR_MISSING_PARAM', 1002 ); +define( 'WS_ERR_INVALID_PARAM', 1003 ); + +define( 'WS_XML_ATTRIBUTES', 'attributes_xml_'); +define( 'WS_XML_CONTENT', 'content_xml_'); + +/** + * PwgError object can be returned from any web service function implementation. + */ +class PwgError +{ + var $_code; + var $_codeText; + + function PwgError($code, $codeText) + { + $this->_code = $code; + $this->_codeText = $codeText; + } + + function code() { return $this->_code; } + function message() { return $this->_codeText; } +} + +/** + * Simple wrapper around an array (keys are consecutive integers starting at 0). + * Provides naming clues for xml output (xml attributes vs. xml child elements?) + * Usually returned by web service function implementation. + */ +class PwgNamedArray +{ + /*private*/ var $_content; + /*private*/ var $_itemName; + /*private*/ var $_xmlAttributes; + + /** + * Constructs a named array + * @param arr array (keys must be consecutive integers starting at 0) + * @param itemName string xml element name for values of arr (e.g. image) + * @param xmlAttributes array of sub-item attributes that will be encoded as + * xml attributes instead of xml child elements + */ + function PwgNamedArray(&$arr, $itemName, $xmlAttributes=array() ) + { + $this->_content = $arr; + $this->_itemName = $itemName; + $this->_xmlAttributes = array_flip($xmlAttributes); + } +} +/** + * Simple wrapper around a "struct" (php array whose keys are not consecutive + * integers starting at 0). Provides naming clues for xml output (what is xml + * attributes and what is element) + */ +class PwgNamedStruct +{ + /*private*/ var $_content; + /*private*/ var $_name; + /*private*/ var $_xmlAttributes; + + /** + * Constructs a named struct (usually returned by web service function + * implementation) + * @param name string - containing xml element name + * @param content array - the actual content (php array) + * @param xmlAttributes array - name of the keys in $content that will be + * encoded as xml attributes (if null - automatically prefer xml attributes + * whenever possible) + */ + function PwgNamedStruct($name, $content, $xmlAttributes=null, $xmlElements=null ) + { + $this->_name = $name; + $this->_content = $content; + if ( isset($xmlAttributes) ) + { + $this->_xmlAttributes = array_flip($xmlAttributes); + } + else + { + $this->_xmlAttributes = array(); + foreach ($this->_content as $key=>$value) + { + if (!empty($key) and (is_scalar($value) or is_null($value)) ) + { + if ( empty($xmlElements) or !in_array($key,$xmlElements) ) + { + $this->_xmlAttributes[$key]=1; + } + } + } + } + } +} + + +/** + * Replace array_walk_recursive() + * + * @category PHP + * @package PHP_Compat + * @link http://php.net/function.array_walk_recursive + * @author Tom Buskens <ortega@php.net> + * @author Aidan Lister <aidan@php.net> + * @version $Revision: 1.7 $ + * @since PHP 5 + * @require PHP 4.0.6 (is_callable) + */ +if (!function_exists('array_walk_recursive')) { + function array_walk_recursive(&$input, $funcname) + { + if (!is_callable($funcname)) { + if (is_array($funcname)) { + $funcname = $funcname[0] . '::' . $funcname[1]; + } + user_error('array_walk_recursive() Not a valid callback ' . $user_func, + E_USER_WARNING); + return; + } + + if (!is_array($input)) { + user_error('array_walk_recursive() The argument should be an array', + E_USER_WARNING); + return; + } + + $args = func_get_args(); + + foreach ($input as $key => $item) { + if (is_array($item)) { + array_walk_recursive($item, $funcname, $args); + $input[$key] = $item; + } else { + $args[0] = &$item; + $args[1] = &$key; + call_user_func_array($funcname, $args); + $input[$key] = $item; + } + } + } +} + +/** + * Abstract base class for request handlers. + */ +class PwgRequestHandler +{ + /** Virtual abstract method. Decodes the request (GET or POST) handles the + * method invocation as well as response sending. + */ + function handleRequest(&$server) { assert(false); } +} + +/** + * + * Base class for web service response encoder. + */ +class PwgResponseEncoder +{ + /** encodes the web service response to the appropriate output format + * @param response mixed the unencoded result of a service method call + */ + function encodeResponse($response) { assert(false); } + + /** default "Content-Type" http header for this kind of response format + */ + function getContentType() { assert(false); } + + /** + * returns true if the parameter is a 'struct' (php array type whose keys are + * NOT consecutive integers starting with 0) + */ + function is_struct(&$data) + { + if (is_array($data) ) + { + if (range(0, count($data) - 1) !== array_keys($data) ) + { # string keys, unordered, non-incremental keys, .. - whatever, make object + return true; + } + } + return false; + } + + /** + * removes all XML formatting from $response (named array, named structs, etc) + * usually called by every response encoder, except rest xml. + */ + function flattenResponse(&$response) + { + PwgResponseEncoder::_mergeAttributesAndContent($response); + PwgResponseEncoder::_removeNamedArray($response); + PwgResponseEncoder::_removeNamedStruct($response); + if (is_array($response)) + { // need to call 2 times (first time might add new arrays) + array_walk_recursive($response, array('PwgResponseEncoder', '_remove_named_callback') ); + array_walk_recursive($response, array('PwgResponseEncoder', '_remove_named_callback') ); + } +//print_r($response); + PwgResponseEncoder::_mergeAttributesAndContent($response); + } + + /*private*/ function _remove_named_callback(&$value, $key) + { + do + { + $changed = 0; + $changed += PwgResponseEncoder::_removeNamedArray($value); + $changed += PwgResponseEncoder::_removeNamedStruct($value); + // print_r('walk '.$key."<br/>\n"); + } + while ($changed); + } + + /*private*/ function _mergeAttributesAndContent(&$value) + { + if ( !is_array($value) ) + return; +/* $first_key = ''; + if (count($value)) { $ak = array_keys($value); $first_key = $ak[0]; } + + print_r( '_mergeAttributesAndContent is_struct='.PwgResponseEncoder::is_struct($value) + .' count='.count($value) + .' first_key='.$first_key + ."<br/>\n" + );*/ + $ret = 0; + if (PwgResponseEncoder::is_struct($value)) + { + if ( isset($value[WS_XML_ATTRIBUTES]) ) + { + $value = array_merge( $value, $value[WS_XML_ATTRIBUTES] ); + unset( $value[WS_XML_ATTRIBUTES] ); + $ret=1; + } + if ( isset($value[WS_XML_CONTENT]) ) + { + $cont_processed = 0; + if ( count($value)==1 ) + { + $value = $value[WS_XML_CONTENT]; + $cont_processed=1; + } + else + { + if (PwgResponseEncoder::is_struct($value[WS_XML_CONTENT])) + { + $value = array_merge( $value, $value[WS_XML_CONTENT] ); + unset( $value[WS_XML_CONTENT] ); + $cont_processed=1; + } + } + $ret += $cont_processed; + if (!$cont_processed) + { + $value['_content'] = $value[WS_XML_CONTENT]; + unset( $value[WS_XML_CONTENT] ); + $ret++; + } + } + } + + foreach ($value as $key=>$v) + { + if ( PwgResponseEncoder::_mergeAttributesAndContent($v) ) + { + $value[$key]=$v; + $ret++; + } + } + return $ret; + } + + /*private*/ function _removeNamedArray(&$value) + { + if ( strtolower( get_class($value) ) =='pwgnamedarray') + { + $value = $value->_content; + return 1; + } + return 0; + } + + /*private*/ function _removeNamedStruct(&$value) + { + if ( strtolower( get_class($value) ) =='pwgnamedstruct') + { + if ( isset($value->_content['']) ) + { + $unknown = $value->_content['']; + unset( $value->_content[''] ); + $value->_content[$value->_name] = $unknown; + } + $value = $value->_content; + return 1; + } + return 0; + } +} + + + +class PwgServer +{ + var $_requestHandler; + var $_requestFormat; + var $_responseEncoder; + var $_responseFormat; + + var $_methods; + var $_methodSignatures; + + function PwgServer() + { + $methods = array(); + } + + /** + * Initializes the request handler. + */ + function setHandler($requestFormat, &$requestHandler) + { + $this->_requestHandler = &$requestHandler; + $this->_requestFormat = $requestFormat; + } + + /** + * Initializes the request handler. + */ + function setEncoder($responseFormat, &$encoder) + { + $this->_responseEncoder = &$encoder; + $this->_responseFormat = $responseFormat; + } + + /** + * Runs the web service call (handler and response encoder should have been + * created) + */ + function run() + { + if ( is_null($this->_responseEncoder) ) + { + @header("HTTP/1.1 500 Server error"); + @header("Status: 500 Server error"); + @header("Content-Type: text/plain"); + echo ("Cannot process your request. Unknown response format. +Request format: ".@$this->_requestFormat." handler:".$this->_requestHandler." +Response format: ".@$this->_responseFormat." encoder:".$this->_responseEncoder." + "); + var_export($this); + die(0); + } + + if ( is_null($this->_requestHandler) ) + { + $this->sendResponse( + new PwgError(500, 'Unknown request format') + ); + return; + } + + $this->addMethod('reflection.getMethodList', + array('PwgServer', 'ws_getMethodList'), + null, '' ); + $this->addMethod('reflection.getMethodDetails', + array('PwgServer', 'ws_getMethodDetails'), + array('methodName'),''); + + trigger_action('ws_add_methods', array(&$this) ); + uksort( $this->_methods, 'strnatcmp' ); + $this->_requestHandler->handleRequest($this); + } + + /** + * Encodes a response and sends it back to the browser. + */ + function sendResponse($response) + { + $encodedResponse = $this->_responseEncoder->encodeResponse($response); + $contentType = $this->_responseEncoder->getContentType(); + + @header('Content-Type: '.$contentType); + print_r($encodedResponse); + } + + /** + * Registers a web service method. + * @param methodName string - the name of the method as seen externally + * @param callback mixed - php method to be invoked internally + * @param params array - map of allowed parameter names with optional default + * values and parameter flags. Example of $params: + * array( 'param1' => array('default'=>523, 'flags'=>WS_PARAM_FORCE_ARRAY) ) . + * Possible parameter flags are: + * WS_PARAM_ALLOW_ARRAY - this parameter can be an array + * WS_PARAM_FORCE_ARRAY - if this parameter is scalar, force it to an array + * before invoking the method + * @param description string - a description of the method. + */ + function addMethod($methodName, $callback, $params=array(), $description, $include_file='') + { + $this->_methods[$methodName] = $callback; + $this->_methodDescriptions[$methodName] = $description; + + if (!is_array($params)) + { + $params = array(); + } + + if ( range(0, count($params) - 1) === array_keys($params) ) + { + $params = array_flip($params); + } + + foreach( $params as $param=>$options) + { + if ( !is_array($options) ) + { + $params[$param] = array('flags'=>0); + } + else + { + $flags = isset($options['flags']) ? $options['flags'] : 0; + if ( array_key_exists('default', $options) ) + { + $flags |= WS_PARAM_OPTIONAL; + } + $options['flags'] = $flags; + $params[$param] = $options; + } + } + $this->_methodSignatures[$methodName] = $params; + } + + function hasMethod($methodName) + { + return isset($this->_methods[$methodName]); + } + + function getMethodDescription($methodName) + { + $desc = @$this->_methodDescriptions[$methodName]; + return isset($desc) ? $desc : ''; + } + + function getMethodSignature($methodName) + { + $signature = @$this->_methodSignatures[$methodName]; + return isset($signature) ? $signature : array(); + } + + /*static*/ function isPost() + { + return isset($HTTP_RAW_POST_DATA) or !empty($_POST); + } + + /*static*/ function makeArrayParam(&$param) + { + if ( $param==null ) + { + $param = array(); + } + else + { + if (! is_array($param) ) + { + $param = array($param); + } + } + } + + /** + * Invokes a registered method. Returns the return of the method (or + * a PwgError object if the method is not found) + * @param methodName string the name of the method to invoke + * @param params array array of parameters to pass to the invoked method + */ + function invoke($methodName, $params) + { + $callback = @$this->_methods[$methodName]; + + if ( $callback==null ) + { + return new PwgError(WS_ERR_INVALID_METHOD, 'Method name "'.$methodName.'" is not valid'); + } + + // parameter check and data coercion ! + $signature = @$this->_methodSignatures[$methodName]; + $missing_params = array(); + foreach($signature as $name=>$options) + { + $flags = $options['flags']; + if ( !array_key_exists($name, $params) ) + {// parameter not provided in the request + if ( !($flags&WS_PARAM_OPTIONAL) ) + { + $missing_params[] = $name; + } + else if ( array_key_exists('default',$options) ) + { + $params[$name] = $options['default']; + if ( ($flags&WS_PARAM_FORCE_ARRAY) ) + { + $this->makeArrayParam( $params[$name] ); + } + } + } + else + {// parameter provided - do some basic checks + $the_param = $params[$name]; + if ( is_array($the_param) and ($flags&WS_PARAM_ACCEPT_ARRAY)==0 ) + { + return new PwgError(WS_ERR_INVALID_PARAM, $name.' must be scalar' ); + } + if ( ($flags&WS_PARAM_FORCE_ARRAY) ) + { + $this->makeArrayParam( $the_param ); + } + $params[$name] = $the_param; + } + } + if (count($missing_params)) + { + return new PwgError(WS_ERR_MISSING_PARAM, 'Missing parameters: '.implode(',',$missing_params)); + } + + $result = call_user_func_array($callback, array($params, &$this) ); + return $result; + } + + /** + * WS reflection method implementation: lists all available methods + */ + /*static*/ function ws_getMethodList($params, &$service) + { + return array('methods' => new PwgNamedArray( array_keys($service->_methods),'method' ) ); + } + + /** + * WS reflection method implementation: gets information about a given method + */ + /*static*/ function ws_getMethodDetails($params, &$service) + { + $methodName = $params['methodName']; + if (!$service->hasMethod($methodName)) + { + return new PwgError(WS_ERR_INVALID_PARAM, + 'Requested method does not exist'); + } + $res = array( + 'name' => $methodName, + 'description' => $service->getMethodDescription($methodName), + 'params' => array(), + ); + $signature = $service->getMethodSignature($methodName); + foreach ($signature as $name => $options) + { + $param_data = array( + 'name' => $name, + 'optional' => ($options['flags']&WS_PARAM_OPTIONAL)?true:false, + ); + if (isset($options['default'])) + { + $param_data['defaultValue'] = $options['default']; + } + $res['params'][] = $param_data; + } + return $res; + } +} +?> diff --git a/include/ws_functions.inc.php b/include/ws_functions.inc.php new file mode 100644 index 000000000..7e1f1a1ba --- /dev/null +++ b/include/ws_functions.inc.php @@ -0,0 +1,716 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $URL: svn+ssh://rvelices@svn.gna.org/svn/phpwebgallery/trunk/action.php $ +// | last update : $Date: 2006-12-21 18:49:12 -0500 (Thu, 21 Dec 2006) $ +// | last modifier : $Author: rvelices $ +// | revision : $Rev: 1678 $ +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +/**** IMPLEMENTATION OF WEB SERVICE METHODS ***********************************/ + +/** + * returns a "standard" (for our web service) array of sql where clauses that + * filters the images (images table only) + */ +function ws_std_image_sql_filter( $params, $tbl_name='' ) +{ + $clauses = array(); + if ( is_numeric($params['f_min_rate']) ) + { + $clauses[] = $tbl_name.'average_rate>'.$params['f_min_rate']; + } + if ( is_numeric($params['f_max_rate']) ) + { + $clauses[] = $tbl_name.'average_rate<='.$params['f_max_rate']; + } + if ( is_numeric($params['f_min_hit']) ) + { + $clauses[] = $tbl_name.'hit>'.$params['f_min_hit']; + } + if ( is_numeric($params['f_max_hit']) ) + { + $clauses[] = $tbl_name.'hit<='.$params['f_max_hit']; + } + if ( isset($params['f_min_date_posted']) ) + { + $clauses[] = $tbl_name."date_available>='".$params['f_min_date_posted']."'"; + } + if ( isset($params['f_max_date_posted']) ) + { + $clauses[] = $tbl_name."date_available<'".$params['f_max_date_posted']."'"; + } + if ( isset($params['f_min_date_created']) ) + { + $clauses[] = $tbl_name."date_creation>='".$params['f_min_date_created']."'"; + } + if ( isset($params['f_max_date_created']) ) + { + $clauses[] = $tbl_name."date_creation<'".$params['f_max_date_created']."'"; + } + if ( is_numeric($params['f_min_ratio']) ) + { + $clauses[] = $tbl_name.'width/'.$tbl_name.'height>'.$params['f_min_ratio']; + } + if ( is_numeric($params['f_max_ratio']) ) + { + $clauses[] = $tbl_name.'width/'.$tbl_name.'height<='.$params['f_max_ratio']; + } + if ( $params['f_with_thumbnail'] ) + { + $clauses[] = $tbl_name.'tn_ext IS NOT NULL'; + } + return $clauses; +} + +/** + * returns a "standard" (for our web service) ORDER BY sql clause for images + */ +function ws_std_image_sql_order( $params, $tbl_name='' ) +{ + $ret = ''; + if ( empty($params['order']) ) + { + return $ret; + } + $matches = array(); + preg_match_all('/([a-z_]+) *(?:(asc|desc)(?:ending)?)? *(?:, *|$)/i', + $params['order'], $matches); + for ($i=0; $i<count($matches[1]); $i++) + { + switch ($matches[1][$i]) + { + case 'date_created': + $matches[1][$i] = 'date_creation'; break; + case 'date_posted': + $matches[1][$i] = 'date_available'; break; + case 'rand': case 'random': + $matches[1][$i] = 'RAND()'; break; + } + $sortable_fields = array('id', 'file', 'name', 'hit', 'average_rate', + 'date_creation', 'date_available', 'RAND()' ); + if ( in_array($matches[1][$i], $sortable_fields) ) + { + if (!empty($ret)) + $ret .= ', '; + if ($matches[1][$i] != 'RAND()' ) + { + $ret .= $tbl_name; + } + $ret .= $matches[1][$i]; + $ret .= ' '.$matches[2][$i]; + } + } + return $ret; +} + +/** + * returns an array map of urls (thumb/element) for image_row - to be returned + * in a standard way by different web service methods + */ +function ws_std_get_urls($image_row) +{ + $ret = array( + 'tn_url' => get_thumbnail_url($image_row), + 'element_url' => get_element_url($image_row) + ); + global $user; + if ($user['enabled_high'] and $image_row['has_high'] ) + { + $ret['high_url'] = get_high_url($image_row); + } + return $ret; +} + + +function ws_getVersion($params, &$service) +{ + return PHPWG_VERSION; +} + +/** + * returns images per category (wb service method) + */ +function ws_categories_getImages($params, &$service) +{ + @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php'); + global $user, $conf; + + $images = array(); + + //------------------------------------------------- get the related categories + $where_clauses = array(); + foreach($params['cat_id'] as $cat_id) + { + $cat_id = (int)$cat_id; + if ($cat_id<=0) + continue; + if ($params['recursive']) + { + $where_clauses[] = 'uppercats REGEXP \'(^|,)'.$cat_id.'(,|$)\''; + } + else + { + $where_clauses[] = 'id='.$cat_id; + } + } + if (!empty($where_clauses)) + { + $where_clauses = array( '('. + implode(' + OR ', $where_clauses) . ')' + ); + } + $where_clauses[] = 'id NOT IN ('.$user['forbidden_categories'].')'; + + $query = ' +SELECT id, name, image_order + FROM '.CATEGORIES_TABLE.' + WHERE '. implode(' + AND ', $where_clauses); + $result = pwg_query($query); + $cats = array(); + while ($row = mysql_fetch_assoc($result)) + { + $row['id'] = (int)$row['id']; + $cats[ $row['id'] ] = $row; + } + + //-------------------------------------------------------- get the images + if ( !empty($cats) ) + { + $where_clauses = ws_std_image_sql_filter( $params, 'i.' ); + $where_clauses[] = 'category_id IN (' + .implode(',', array_keys($cats) ) + .')'; + $order_by = ws_std_image_sql_order($params, 'i.'); + if (empty($order_by)) + {// TODO check for category order by (image_order) + $order_by = $conf['order_by']; + } + else + { + $order_by = 'ORDER BY '.$order_by; + } + $query = ' +SELECT i.*, GROUP_CONCAT(category_id) cat_ids + FROM '.IMAGES_TABLE.' i + INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON i.id=image_id + WHERE '. implode(' + AND ', $where_clauses).' +GROUP BY i.id +'.$order_by.' +LIMIT '.$params['per_page']*$params['page'].','.$params['per_page']; + + $result = pwg_query($query); + while ($row = mysql_fetch_assoc($result)) + { + $image = array(); + foreach ( array('id', 'width', 'height', 'hit') as $k ) + { + if (isset($row[$k])) + { + $image[$k] = (int)$row[$k]; + } + } + foreach ( array('name', 'file') as $k ) + { + $image[$k] = $row[$k]; + } + $image = array_merge( $image, ws_std_get_urls($row) ); + + $image_cats = array(); + foreach ( explode(',', $row['cat_ids']) as $cat_id ) + { + $url = make_index_url( + array( + 'category' => $cat_id, + 'cat_name' => $cats[$cat_id]['name'], + ) + ); + $page_url = make_picture_url( + array( + 'category' => $cat_id, + 'cat_name' => $cats[$cat_id]['name'], + 'image_id' => $row['id'], + 'image_file' => $row['file'], + ) + ); + array_push( $image_cats, array( + WS_XML_ATTRIBUTES => array ( + 'id' => (int)$cat_id, + 'url' => $url, + 'page_url' => $page_url, + ) + ) + ); + } + + $image['categories'] = new PwgNamedArray( + $image_cats,'category', array('id','url','page_url') + ); + array_push($images, $image); + } + } + + return array( 'images' => + array ( + WS_XML_ATTRIBUTES => + array( + 'page' => $params['page'], + 'per_page' => $params['per_page'], + 'count' => count($images) + ), + WS_XML_CONTENT => new PwgNamedArray($images, 'image', + array('id', 'tn_url', 'element_url', 'file','width','height','hit') ) + ) + ); +} + +/** + * returns a list of categories + */ +function ws_categories_getList($params, &$service) +{ + global $user; + + $query = ' +SELECT id, name, uppercats, global_rank, + max_date_last, count_images AS nb_images, count_categories AS nb_categories + FROM '.CATEGORIES_TABLE.' + INNER JOIN '.USER_CACHE_CATEGORIES_TABLE.' ON id=cat_id'; + + $where = array(); + $where[]= 'user_id='.$user['id']; + if ($params['cat_id']>0) + { + $where[] = 'uppercats REGEXP \'(^|,)'. + (int)($params['cat_id']) + .'(,|$)\''; + } + + if (!$params['recursive']) + { + if ($params['cat_id']>0) + $where[] = 'id_uppercat='.(int)($params['cat_id']); + else + $where[] = 'id_uppercat IS NULL'; + } + + if ($params['public']) + { + $where[] = 'status = "public"'; + } + else + { + $where[] = 'id NOT IN ('.$user['forbidden_categories'].')'; + } + + $query .= ' + WHERE '. implode(' + AND ', $where); + $query .= ' +ORDER BY global_rank'; + + $result = pwg_query($query); + + $cats = array(); + while ($row = mysql_fetch_assoc($result)) + { + $row['url'] = make_index_url( + array( + 'category' => $row['id'], + 'cat_name' => $row['name'], + ) + ); + foreach( array('id','nb_images','nb_categories') as $key) + { + $row[$key] = (int)$row[$key]; + } + array_push($cats, $row); + } + usort($cats, 'global_rank_compare'); + return array( + 'categories' => + new PwgNamedArray($cats,'category', + array('id','url','nb_images','nb_categories','max_date_last') + ) + ); +} + +function ws_images_getInfo($params, &$service) +{ + @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php'); + global $user; + $params['image_id'] = (int)$params['image_id']; + if ( $params['image_id']<=0 ) + { + return new PwgError(WS_ERR_INVALID_PARAM, "Invalid image_id"); + } + $query=' +SELECT * FROM '.IMAGES_TABLE.' + WHERE id='.$params['image_id'].' +LIMIT 1'; + $image_row = mysql_fetch_assoc(pwg_query($query)); + if ($image_row==null) + { + return new PwgError(999, "image_id not found"); + } + array_merge( $image_row, ws_std_get_urls($image_row) ); + + //-------------------------------------------------------- related categories + $query = ' +SELECT c.id,c.name,c.uppercats,c.global_rank + FROM '.IMAGE_CATEGORY_TABLE.' + INNER JOIN '.CATEGORIES_TABLE.' c ON category_id = id + WHERE image_id = '.$image_row['id'].' + AND category_id NOT IN ('.$user['forbidden_categories'].') +;'; + $result = pwg_query($query); + $related_categories = array(); + while ($row = mysql_fetch_assoc($result)) + { + $row['url'] = make_index_url( + array( + 'category' => $row['id'], + 'cat_name' => $row['name'], + ) + ); + + $row['page_url'] = make_picture_url( + array( + 'image_id' => $image_row['id'], + 'image_file' => $image_row['file'], + 'category' => $row['id'], + 'cat_name' => $row['name'], + ) + ); + array_push($related_categories, $row); + } + usort($related_categories, 'global_rank_compare'); + if ( empty($related_categories) ) + { + return new PwgError(401, 'Access denied'); + } + + //-------------------------------------------------------------- related tags + $query = ' +SELECT id, name, url_name + FROM '.IMAGE_TAG_TABLE.' + INNER JOIN '.TAGS_TABLE.' ON tag_id = id + WHERE image_id = '.$image_row['id'].' +;'; + $result = pwg_query($query); + $related_tags = array(); + while ($row = mysql_fetch_assoc($result)) + { + $row['url'] = make_index_url( + array( + 'tags' => array($row) + ) + ); + $row['page_url'] = make_picture_url( + array( + 'image_id' => $image_row['id'], + 'image_file' => $image_row['file'], + 'tags' => array($row), + ) + ); + array_push($related_tags, $row); + } + //---------------------------------------------------------- related comments + $query = ' +SELECT COUNT(id) nb_comments + FROM '.COMMENTS_TABLE.' + WHERE image_id = '.$image_row['id']; + list($nb_comments) = array_from_query($query, 'nb_comments'); + + $query = ' +SELECT id, date, author, content + FROM '.COMMENTS_TABLE.' + WHERE image_id = '.$image_row['id'].' + AND validated="true"'; + $query .= ' + ORDER BY date DESC + LIMIT 0, 5'; + + $result = pwg_query($query); + $related_comments = array(); + while ($row = mysql_fetch_assoc($result)) + { + array_push($related_comments, $row); + } + + //------------------------------------------------------------- related rates + $query = ' +SELECT COUNT(rate) AS count + , ROUND(AVG(rate),2) AS average + , ROUND(STD(rate),2) AS stdev + FROM '.RATE_TABLE.' + WHERE element_id = '.$image_row['id'].' +;'; + $row = mysql_fetch_assoc(pwg_query($query)); + + $ret = $image_row; + $ret['rates'] = array( WS_XML_ATTRIBUTES => $row ); + $ret['categories'] = new PwgNamedArray($related_categories, 'category', array('id','url', 'page_url') ); + $ret['tags'] = new PwgNamedArray($related_tags, 'tag', array('id','url_name','url','page_url') ); + $ret['comments'] = array( + WS_XML_ATTRIBUTES => array('nb_comments' => $nb_comments), + WS_XML_CONTENT => new PwgNamedArray($related_comments, 'comment', array('id') ) + ); + unset($ret['path']); + unset($ret['storage_category_id']); + return new PwgNamedStruct('image',$ret, null, array('name','comment') ); +} + + +function ws_session_login($params, &$service) +{ + global $conf; + + if (!$service->isPost()) + { + return new PwgError(400, "This method requires POST"); + } + + $username = $params['username']; + // retrieving the encrypted password of the login submitted + $query = ' +SELECT '.$conf['user_fields']['id'].' AS id, + '.$conf['user_fields']['password'].' AS password + FROM '.USERS_TABLE.' + WHERE '.$conf['user_fields']['username'].' = \''.$username.'\' +;'; + $row = mysql_fetch_assoc(pwg_query($query)); + + if ($row['password'] == $conf['pass_convert']($params['password'])) + { + log_user($row['id'], false); + return true; + } + return new PwgError(999, 'Invalid username/password'); +} + +function ws_session_logout($params, &$service) +{ + global $user, $conf; + if (!$user['is_the_guest']) + { + $_SESSION = array(); + session_unset(); + session_destroy(); + setcookie(session_name(),'',0, + ini_get('session.cookie_path'), + ini_get('session.cookie_domain') + ); + setcookie($conf['remember_me_name'], '', 0, cookie_path()); + } + return true; +} + +function ws_session_getStatus($params, &$service) +{ + global $user; + $res = array(); + $res['username'] = $user['is_the_guest'] ? 'guest' : $user['username']; + $res['status'] = $user['status']; + return $res; +} + + +function ws_tags_getList($params, &$service) +{ + global $user; + $tags = get_available_tags(explode(',', $user['forbidden_categories'])); + if ($params['sort_by_counter']) + { + usort($tags, create_function('$a,$b', 'return -$a["counter"]+$b["counter"];') ); + } + else + { + usort($tags, 'name_compare'); + } + for ($i=0; $i<count($tags); $i++) + { + $tags[$i]['id'] = (int)$tags[$i]['tag_id']; + $tags[$i]['counter'] = (int)$tags[$i]['counter']; + unset($tags[$i]['tag_id']); + $tags[$i]['url'] = make_index_url( + array( + 'section'=>'tags', + 'tags'=>array($tags[$i]) + ) + ); + } + return array('tags' => new PwgNamedArray($tags, 'tag', array('id','url_name','url', 'counter' )) ); +} + +function ws_tags_getImages($params, &$service) +{ + @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php'); + global $user, $conf; + + // first build all the tag_ids we are interested in + $tag_ids = array(); + $tags = get_available_tags(); + $tags_by_id = array(); + for( $i=0; $i<count($tags); $i++ ) + { + $tags[$i]['tag_id']=(int)$tags[$i]['tag_id']; + $tags[$i]['id']=(int)$tags[$i]['tag_id']; //required by make_xxx_url + } + foreach( $tags as $tag ) + { + $tags_by_id[ $tag['tag_id'] ] = $tag; + if ( + in_array($tag['name'], $params['tag_name']) + or + in_array($tag['url_name'], $params['tag_url_name']) + ) + { + $tag_ids[] = $tag['tag_id']; + } + } + unset($tags); + + foreach( $params['tag_id'] as $tag_id ) + { + if ( (int)$tag_id > 0 ) + { + $tag_ids[] = $tag_id; + } + } + + $tag_ids = array_unique( $tag_ids ); + + $image_ids = array(); + $image_tag_map = array(); + + if ( !empty($tag_ids) ) + { // build list of image ids with associated tags per image + if ($params['tag_mode_and']) + { + $image_ids = get_image_ids_for_tags( $tag_ids ); + } + else + { + $query = ' +SELECT image_id, GROUP_CONCAT(tag_id) tag_ids + FROM '.IMAGE_TAG_TABLE.' + WHERE tag_id IN ('.implode(',',$tag_ids).') + GROUP BY image_id'; + $result = pwg_query($query); + while ( $row=mysql_fetch_assoc($result) ) + { + $row['image_id'] = (int)$row['image_id']; + array_push( $image_ids, $row['image_id'] ); + $image_tag_map[ $row['image_id'] ] = explode(',', $row['tag_ids']); + } + } + } + + $images = array(); + if ( !empty($image_ids)) + { + $where_clauses = ws_std_image_sql_filter($params); + $where_clauses[] = 'category_id NOT IN ('.$user['forbidden_categories'].')'; + $where_clauses[] = 'id IN ('.implode(',',$image_ids).')'; + $order_by = ws_std_image_sql_order($params); + if (empty($order_by)) + { + $order_by = $conf['order_by']; + } + else + { + $order_by = 'ORDER BY '.$order_by; + } + + $query = ' +SELECT DISTINCT i.* FROM '.IMAGES_TABLE.' i + INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON i.id=image_id + WHERE '. implode(' + AND ', $where_clauses).' +'.$order_by.' +LIMIT '.$params['per_page']*$params['page'].','.$params['per_page']; + + $result = pwg_query($query); + while ($row = mysql_fetch_assoc($result)) + { + foreach ( array('id', 'width', 'height', 'hit') as $k ) + { + if (isset($row[$k])) + { + $image[$k] = (int)$row[$k]; + } + } + foreach ( array('name', 'file') as $k ) + { + $image[$k] = $row[$k]; + } + $image = array_merge( $image, ws_std_get_urls($row) ); + + $image_tag_ids = ($params['tag_mode_and']) ? $tag_ids : $image_tag_map[$image['id']]; + $image_tags = array(); + foreach ($image_tag_ids as $tag_id) + { + $url = make_index_url( + array( + 'section'=>'tags', + 'tags'=> array($tags_by_id[$tag_id]) + ) + ); + $page_url = make_picture_url( + array( + 'section'=>'tags', + 'tags'=> array($tags_by_id[$tag_id]), + 'image_id' => $row['id'], + 'image_file' => $row['file'], + ) + ); + array_push($image_tags, array( + 'id' => (int)$tag_id, + 'url' => $url, + 'page_url' => $page_url, + ) + ); + } + $image['tags'] = new PwgNamedArray($image_tags, 'tag', + array('id','url_name','url','page_url') + ); + array_push($images, $image); + } + } + + return array( 'images' => + array ( + WS_XML_ATTRIBUTES => + array( + 'page' => $params['page'], + 'per_page' => $params['per_page'], + 'count' => count($images) + ), + WS_XML_CONTENT => new PwgNamedArray($images, 'image', + array('id', 'tn_url', 'element_url', 'file','width','height','hit') ) + ) + ); +} + +?> diff --git a/include/ws_protocols/json_encoder.php b/include/ws_protocols/json_encoder.php new file mode 100644 index 000000000..ffeb59954 --- /dev/null +++ b/include/ws_protocols/json_encoder.php @@ -0,0 +1,90 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $URL: svn+ssh://rvelices@svn.gna.org/svn/phpwebgallery/trunk/action.php $ +// | last update : $Date: 2006-12-21 18:49:12 -0500 (Thu, 21 Dec 2006) $ +// | last modifier : $Author: rvelices $ +// | revision : $Rev: 1678 $ +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + + +#_____________________ PHP 5.2 +if (! function_exists('json_encode')) { + function json_encode($data) { + switch (gettype($data)) { + case 'boolean': + return ($data ? 'true' : 'false'); + case 'null': + case 'NULL': + return 'null'; + case 'integer': + case 'double': + return $data; + case 'string': + return '"'. str_replace(array("\\",'"',"/","\n","\r","\t"), array("\\\\",'\"',"\\/","\\n","\\r","\\t"), $data) .'"'; + case 'object': + case 'array': + if ($data === array()) return '[]'; # empty array + if (range(0, count($data) - 1) !== array_keys($data) ) { # string keys, unordered, non-incremental keys, .. - whatever, make object + $out = "\n".'{'; + foreach($data as $key => $value) { + $out .= json_encode((string) $key) . ':' . json_encode($value) . ','; + } + $out = substr($out, 0, -1) . "\n". '}'; + }else{ + # regular array + $out = "\n".'[' . join("\n".',', array_map('json_encode', $data)) ."\n".']'; + } + return $out; + } + } +} + +class PwgJsonEncoder extends PwgResponseEncoder +{ + function encodeResponse($response) + { + $respClass = strtolower( get_class($response) ); + if ($respClass=='pwgerror') + { + return json_encode( + array( + 'stat' => 'fail', + 'err' => $response->code(), + 'message' => $response->message(), + ) + ); + } + parent::flattenResponse($response); + return json_encode( + array( + 'stat' => 'ok', + 'result' => $response, + ) + ); + } + + function getContentType() + { + return 'text/plain'; + } +} + +?> diff --git a/include/ws_protocols/php_encoder.php b/include/ws_protocols/php_encoder.php new file mode 100644 index 000000000..f12df2594 --- /dev/null +++ b/include/ws_protocols/php_encoder.php @@ -0,0 +1,57 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $URL: svn+ssh://rvelices@svn.gna.org/svn/phpwebgallery/trunk/action.php $ +// | last update : $Date: 2006-12-21 18:49:12 -0500 (Thu, 21 Dec 2006) $ +// | last modifier : $Author: rvelices $ +// | revision : $Rev: 1678 $ +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +class PwgSerialPhpEncoder extends PwgResponseEncoder +{ + function encodeResponse($response) + { + $respClass = strtolower( get_class($response) ); + if ($respClass=='pwgerror') + { + return serialize( + array( + 'stat' => 'fail', + 'err' => $response->code(), + 'message' => $response->message(), + ) + ); + } + parent::flattenResponse($response); + return serialize( + array( + 'stat' => 'ok', + 'result' => $response + ) + ); + } + + function getContentType() + { + return 'text/plain'; + } +} + +?> diff --git a/include/ws_protocols/rest_encoder.php b/include/ws_protocols/rest_encoder.php new file mode 100644 index 000000000..c66cf2536 --- /dev/null +++ b/include/ws_protocols/rest_encoder.php @@ -0,0 +1,285 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $URL: svn+ssh://rvelices@svn.gna.org/svn/phpwebgallery/trunk/action.php $ +// | last update : $Date: 2006-12-21 18:49:12 -0500 (Thu, 21 Dec 2006) $ +// | last modifier : $Author: rvelices $ +// | revision : $Rev: 1678 $ +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + + +class PwgXmlWriter +{ + var $_indent; + var $_indentStr; + + var $_elementStack; + var $_lastTagOpen; + var $_indentLevel; + + var $_encodedXml; + + function PwgXmlWriter() + { + $this->_elementStack = array(); + $this->_lastTagOpen = false; + $this->_indentLevel = 0; + + $this->_encodedXml = ''; + $this->_indent = true; + $this->_indentStr = "\t"; + } + + function &getOutput() + { + return $this->_encodedXml; + } + + + function start_element($name) + { + $this->_end_prev(false); + if (!empty($this->_elementStack)) + { + $this->_eol_indent(); + } + $this->_indentLevel++; + $this->_indent(); + $this->_output( '<'.$name ); + $this->_lastTagOpen = true; + array_push( $this->_elementStack, $name); + } + + function end_element($x) + { + $close_tag = $this->_end_prev(true); + $name = array_pop( $this->_elementStack ); + if ($close_tag) + { + $this->_indentLevel--; + $this->_indent(); +// $this->_eol_indent(); + $this->_output('</'.$name.">"); + } + } + + function write_content($value) + { + $this->_end_prev(false); + $value = (string)$value; + $need_cdata = (strpos($value, "\r")!==false)?true:false; + if ($need_cdata) + { + $this->_output( '<![CDATA[' . $value . ']]>' ); + } + else + { + $this->_output( htmlspecialchars( $value ) ); + } + } + + function write_attribute($name, $value) + { + $this->_output(' '.$name.'="'.$this->encode_attribute($value).'"'); + } + + function encode_attribute($value) + { + return htmlspecialchars( (string)$value); + } + + function _end_prev($done) + { + $ret = true; + if ($this->_lastTagOpen) + { + if ($done) + { + $this->_indentLevel--; + $this->_output( ' />' ); + //$this->_eol_indent(); + $ret = false; + } + else + { + $this->_output( '>' ); + } + $this->_lastTagOpen = false; + } + return $ret; + } + + function _eol_indent() + { + if ($this->_indent) + $this->_output("\n"); + } + + function _indent() + { + if ($this->_indent and + $this->_indentLevel > count($this->_elementStack) ) + { + $this->_output( + str_repeat( $this->_indentStr, count($this->_elementStack) ) + ); + } + } + + function _output($raw_content) + { + $this->_encodedXml .= $raw_content; + } +} + +class PwgRestEncoder extends PwgResponseEncoder +{ + function encodeResponse($response) + { + global $lang_info; + $respClass = strtolower( get_class($response) ); + if ($respClass=='pwgerror') + { + $ret = '<?xml version="1.0"?> +<rsp stat="fail"> + <err code="'.$response->code().'" msg="'.htmlspecialchars($response->message()).'" /> +</rsp>'; + return $ret; + } + +//parent::flattenResponse($response); + + $this->_writer = new PwgXmlWriter(); + $this->encode($response); + $ret = $this->_writer->getOutput(); + $ret = '<?xml version="1.0" encoding="'.$lang_info['charset'].'" ?> +<rsp stat="ok"> +'.$ret.' +</rsp>'; + + return $ret; + } + + function getContentType() + { + return 'text/xml'; + } + + function encode_array($data, $itemName, $xml_attributes=array()) + { + foreach ($data as $item) + { + $this->_writer->start_element( $itemName ); + $this->encode($item, $xml_attributes); + $this->_writer->end_element( $itemName ); + } + } + + function encode_struct($data, $skip_underscore, $xml_attributes=array()) + { + foreach ($data as $name => $value) + { + if (is_numeric($name)) + continue; + if ($skip_underscore and $name[0]=='_') + continue; + if ( is_null($value) ) + continue; // null means we dont put it + if ( $name==WS_XML_ATTRIBUTES) + { + foreach ($value as $attr_name => $attr_value) + { + $this->_writer->write_attribute($attr_name, $attr_value); + } + unset($data[$name]); + } + else if ( isset($xml_attributes[$name]) ) + { + $this->_writer->write_attribute($name, $value); + unset($data[$name]); + } + } + + foreach ($data as $name => $value) + { + if (is_numeric($name)) + continue; + if ($skip_underscore and $name[0]=='_') + continue; + if ( is_null($value) ) + continue; // null means we dont put it + if ($name!=WS_XML_CONTENT) + $this->_writer->start_element($name); + $this->encode($value); + if ($name!=WS_XML_CONTENT) + $this->_writer->end_element($name); + } + } + + function encode($data, $xml_attributes=array() ) + { + switch (gettype($data)) + { + case 'null': + case 'NULL': + $this->_writer->write_content(''); + break; + case 'boolean': + $this->_writer->write_content($data ? '1' : '0'); + break; + case 'integer': + case 'double': + $this->_writer->write_content($data); + break; + case 'string': + $this->_writer->write_content($data); + break; + case 'array': + $is_array = range(0, count($data) - 1) === array_keys($data); + if ($is_array) + { + $this->encode_array($data, 'item' ); + } + else + { + $this->encode_struct($data, false, $xml_attributes); + } + break; + case 'object': + switch ( strtolower(get_class($data)) ) + { + case 'pwgnamedarray': + $this->encode_array($data->_content, $data->_itemName, $data->_xmlAttributes); + break; + case 'pwgnamedstruct': + $this->encode_array( array($data->_content), $data->_name, $data->_xmlAttributes); + break; + default: + $this->encode_struct(get_object_vars($data), true); + break; + } + break; + default: + trigger_error("Invalid type ". gettype($data)." ".get_class($data), E_USER_WARNING ); + } + } +} + +?> diff --git a/include/ws_protocols/rest_handler.php b/include/ws_protocols/rest_handler.php new file mode 100644 index 000000000..184fc205a --- /dev/null +++ b/include/ws_protocols/rest_handler.php @@ -0,0 +1,60 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $URL: svn+ssh://rvelices@svn.gna.org/svn/phpwebgallery/trunk/action.php $ +// | last update : $Date: 2006-12-21 18:49:12 -0500 (Thu, 21 Dec 2006) $ +// | last modifier : $Author: rvelices $ +// | revision : $Rev: 1678 $ +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +class PwgRestRequestHandler +{ + function handleRequest(&$service) + { + $params = array(); + + $param_array = $service->isPost() ? $_POST : $_GET; + foreach ($param_array as $name => $value) + { + if ($name=='format') + continue; + if ($name=='method') + { + $method = $value; + } + else + { + $params[$name]=$value; + } + } + + if ( empty($method) ) + { + $service->sendResponse( + new PwgError(400, 'Missing "method" name') + ); + return; + } + $resp = $service->invoke($method, $params); + $service->sendResponse($resp); + } +} + +?> diff --git a/include/ws_protocols/xmlrpc_encoder.php b/include/ws_protocols/xmlrpc_encoder.php new file mode 100644 index 000000000..69919165e --- /dev/null +++ b/include/ws_protocols/xmlrpc_encoder.php @@ -0,0 +1,118 @@ +<?php +// +-----------------------------------------------------------------------+ +// | PhpWebGallery - a PHP based picture gallery | +// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net | +// +-----------------------------------------------------------------------+ +// | branch : BSF (Best So Far) +// | file : $URL: svn+ssh://rvelices@svn.gna.org/svn/phpwebgallery/trunk/action.php $ +// | last update : $Date: 2006-12-21 18:49:12 -0500 (Thu, 21 Dec 2006) $ +// | last modifier : $Author: rvelices $ +// | revision : $Rev: 1678 $ +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +function xmlrpc_encode($data) +{ + switch (gettype($data)) + { + case 'boolean': + return '<boolean>'.($data ? '1' : '0').'</boolean>'; + case 'integer': + return '<int>'.$data.'</int>'; + case 'double': + return '<double>'.$data.'</double>'; + case 'string': + return '<string>'.htmlspecialchars($data).'</string>'; + case 'object': + case 'array': + $is_array = range(0, count($data) - 1) === array_keys($data); + if ($is_array) + { + $return = '<array><data>'."\n"; + foreach ($data as $item) + { + $return .= ' <value>'.xmlrpc_encode($item)."</value>\n"; + } + $return .= '</data></array>'; + } + else + { + $return = '<struct>'."\n"; + foreach ($data as $name => $value) + { + $name = htmlspecialchars($name); + $return .= " <member><name>$name</name><value>"; + $return .= xmlrpc_encode($value)."</value></member>\n"; + } + $return .= '</struct>'; + } + return $return; + } +} + +class PwgXmlRpcEncoder extends PwgResponseEncoder +{ + function encodeResponse($response) + { + $respClass = strtolower( get_class($response) ); + if ($respClass=='pwgerror') + { + $code = $response->code(); + $msg = htmlspecialchars($response->message()); + $ret = <<<EOD +<methodResponse> + <fault> + <value> + <struct> + <member> + <name>faultCode</name> + <value><int>{$code}</int></value> + </member> + <member> + <name>faultString</name> + <value><string>{$msg}</string></value> + </member> + </struct> + </value> + </fault> +</methodResponse> +EOD; + return $ret; + } + + parent::flattenResponse($response); + $ret = xmlrpc_encode($response); + $ret = <<<EOD +<methodResponse> + <params> + <param> + <value> + $ret + </value> + </param> + </params> +</methodResponse> +EOD; + return $ret; + } + + function getContentType() + { + return 'text/xml'; + } +} + +?> |