forked from extern/egroupware
199 lines
6.7 KiB
PHP
199 lines
6.7 KiB
PHP
<?php
|
|
/**
|
|
* EGroupware API: JSON - Contains functions and classes for doing JSON requests.
|
|
*
|
|
* @link http://www.egroupware.org
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
* @package api
|
|
* @subpackage json
|
|
* @author Andreas Stoeckel <as@stylite.de>
|
|
* @author Ralf Becker <ralfbecker@outdoor-training.de>
|
|
* @version $Id$
|
|
*/
|
|
|
|
namespace EGroupware\Api\Json;
|
|
|
|
use ReflectionMethod;
|
|
use EGroupware\Api;
|
|
|
|
// explicitly import old, not yet ported api classes
|
|
use notifications_push;
|
|
|
|
/**
|
|
* Class handling JSON requests to the server
|
|
*/
|
|
class Request
|
|
{
|
|
private static $_hadJSONRequest = false;
|
|
|
|
/**
|
|
* Check if JSON request running or (re)set JSON request flag
|
|
*
|
|
* Can be used to:
|
|
* - detect regular JSON request:
|
|
* Api\Json\Request::isJSONRequest()
|
|
* - switch regular JSON response handling off, which would send arbitrary output via response method "html".
|
|
* Neccessary if json.php is used to send arbitrary JSON data eg. nodes for foldertree!
|
|
* Api\Json\Request::isJSONRequest(false)
|
|
*
|
|
* @param boolean $set =null
|
|
* @return boolean
|
|
*/
|
|
public static function isJSONRequest($set=null)
|
|
{
|
|
$ret = self::$_hadJSONRequest;
|
|
if (isset($set)) self::$_hadJSONRequest = $set;
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Parses the raw input data supplied with the input_data parameter and calls the menuaction
|
|
* passing all parameters supplied in the request to it.
|
|
*
|
|
* Also handle queued requests (menuaction == 'api.queue') containing multiple requests
|
|
*
|
|
* @param string menuaction to call
|
|
* @param string $input_data is the RAW input data as it was received from the client
|
|
* @throws \InvalidArgumentException if JSON can not be parsed (json_last_error())
|
|
* or did not contain request[parameters] array (999)
|
|
*/
|
|
public function parseRequest($menuaction, $input_data)
|
|
{
|
|
// Remember that we currently are in a JSON request - e.g. used in the redirect code
|
|
self::$_hadJSONRequest = true;
|
|
|
|
// no or empty payload is eg. used by dynamicly loading tree nodes (uses just GET parameters)
|
|
if (!isset($input_data) || $input_data === '')
|
|
{
|
|
$parameters = array();
|
|
}
|
|
else
|
|
{
|
|
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) $input_data = stripslashes($input_data);
|
|
|
|
if (($json_data = json_decode($input_data,true)) === null && json_last_error() !== JSON_ERROR_NONE)
|
|
{
|
|
throw new \InvalidArgumentException('JSON '.json_last_error_msg(), json_last_error());
|
|
}
|
|
elseif (is_array($json_data) && isset($json_data['request']) && isset($json_data['request']['parameters']) && is_array($json_data['request']['parameters']))
|
|
{
|
|
//error_log(__METHOD__.__LINE__.array2string($json_data['request']).function_backtrace());
|
|
$parameters =& $json_data['request']['parameters'];
|
|
}
|
|
else
|
|
{
|
|
throw new \InvalidArgumentException('Missing request:parameters object', 999);
|
|
}
|
|
}
|
|
// do we have a single request or an array of queued requests
|
|
if ($menuaction == 'api.queue')
|
|
{
|
|
$responses = array();
|
|
$response = Response::get();
|
|
foreach($parameters[0] as $uid => $data)
|
|
{
|
|
//error_log("$uid: menuaction=$data[menuaction], parameters=".array2string($data['parameters']));
|
|
$this->handleRequest($data['menuaction'], (array)$data['parameters']);
|
|
$responses[$uid] = $response->initResponseArray();
|
|
//error_log("responses[$uid]=".array2string($responses[$uid]));
|
|
}
|
|
$response->data($responses); // send all responses as data
|
|
}
|
|
else
|
|
{
|
|
$this->handleRequest($menuaction, $parameters);
|
|
}
|
|
// check if we have push notifications, if notifications app available
|
|
if (class_exists('notifications_push')) notifications_push::get();
|
|
}
|
|
|
|
/**
|
|
* Request handler
|
|
*
|
|
* @param string $menuaction
|
|
* @param array $parameters
|
|
*/
|
|
public function handleRequest($menuaction, array $parameters)
|
|
{
|
|
if (strpos($menuaction,'::') !== false && strpos($menuaction,'.') === false) // static method name app_something::method
|
|
{
|
|
@list($className,$functionName,$handler) = explode('::',$menuaction);
|
|
if (substr($className, 0, 11) == 'EGroupware\\')
|
|
{
|
|
list(,$appName) = explode('\\', strtolower($className));
|
|
}
|
|
else
|
|
{
|
|
list($appName) = explode('_',$className);
|
|
}
|
|
|
|
// Check for a real static method, avoid instanciation if it is
|
|
$m = new ReflectionMethod($menuaction);
|
|
if($m->isStatic())
|
|
{
|
|
$ajaxClass = $className;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
@list($appName, $className, $functionName, $handler) = explode('.',$menuaction);
|
|
}
|
|
//error_log("json.php: appName=$appName, className=$className, functionName=$functionName, handler=$handler");
|
|
|
|
switch($handler)
|
|
{
|
|
case '/etemplate/process_exec':
|
|
$_GET['menuaction'] = $appName.'.'.$className.'.'.$functionName;
|
|
$appName = $className = 'etemplate';
|
|
$functionName = 'process_exec';
|
|
$menuaction = 'etemplate.etemplate.process_exec';
|
|
|
|
$parameters = array(
|
|
$parameters[0]['etemplate_exec_id'],
|
|
$parameters[0]['submit_button'],
|
|
$parameters[0],
|
|
'xajaxResponse',
|
|
);
|
|
//error_log("xajax_doXMLHTTP() /etemplate/process_exec handler: arg0='$menuaction', menuaction='$_GET[menuaction]'");
|
|
break;
|
|
case 'etemplate': // eg. ajax code in an eTemplate widget
|
|
$menuaction = ($appName = 'etemplate').'.'.$className.'.'.$functionName;
|
|
break;
|
|
case 'template': // calling current template / framework object
|
|
$menuaction = $appName.'.'.$className.'.'.$functionName;
|
|
$className = get_class($GLOBALS['egw']->framework);
|
|
list($template) = explode('_', $className);
|
|
break;
|
|
}
|
|
|
|
if(substr($className,0,4) != 'ajax' && substr($className,-4) != 'ajax' &&
|
|
$menuaction != 'etemplate.etemplate.process_exec' && substr($functionName,0,4) != 'ajax' ||
|
|
!preg_match('/^[A-Za-z0-9_\\\\-]+(\.[A-Za-z0-9_\\\\]+\.|::)[A-Za-z0-9_]+$/',$menuaction))
|
|
{
|
|
// stopped for security reasons
|
|
error_log("className='$className', functionName='$functionName', menuaction='$menuaction'");
|
|
error_log($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
|
// send message also to the user
|
|
throw new Exception\InvalidName($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
|
}
|
|
|
|
if (isset($template))
|
|
{
|
|
$ajaxClass = $GLOBALS['egw']->framework;
|
|
}
|
|
else if (!$ajaxClass)
|
|
{
|
|
$ajaxClass = class_exists($className) ? new $className() : CreateObject($appName.'.'.$className);
|
|
}
|
|
|
|
// for Ajax: no need to load the "standard" javascript files,
|
|
// they are already loaded, in fact jquery has a problem if loaded twice
|
|
Api\Framework::js_files(array());
|
|
|
|
call_user_func_array(array($ajaxClass, $functionName),
|
|
Api\Translation::convert($parameters, 'utf-8'));
|
|
|
|
|
|
}
|
|
}
|