2016-03-20 14:02:55 +01:00
< ? 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 .
*
2016-05-01 11:57:48 +02:00
* Also handle queued requests ( menuaction == 'api.queue' ) containing multiple requests
2016-03-20 14:02:55 +01:00
*
* @ param string menuaction to call
* @ param string $input_data is the RAW input data as it was received from the client
2018-11-01 11:59:31 +01:00
* @ throws \InvalidArgumentException if JSON can not be parsed ( json_last_error ())
* or did not contain request [ parameters ] array ( 999 )
2016-03-20 14:02:55 +01:00
*/
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 ;
2018-11-01 11:59:31 +01:00
// no or empty payload is eg. used by dynamicly loading tree nodes (uses just GET parameters)
if ( ! isset ( $input_data ) || $input_data === '' )
2016-03-20 14:02:55 +01:00
{
2018-11-01 11:59:31 +01:00
$parameters = array ();
2016-03-20 14:02:55 +01:00
}
else
{
2021-03-21 18:27:09 +01:00
if ( function_exists ( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc ()) $input_data = stripslashes ( $input_data );
2018-11-01 11:59:31 +01:00
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 );
}
2016-03-20 14:02:55 +01:00
}
// do we have a single request or an array of queued requests
2016-05-01 11:57:48 +02:00
if ( $menuaction == 'api.queue' )
2016-03-20 14:02:55 +01:00
{
$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 );
}
2020-05-22 10:16:59 +02:00
// check if we have push notifications, if notifications app available
if ( class_exists ( 'notifications_push' )) notifications_push :: get ();
2016-03-20 14:02:55 +01:00
}
/**
* 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
2016-04-07 22:42:06 +02:00
Api\Framework :: js_files ( array ());
2016-03-20 14:02:55 +01:00
call_user_func_array ( array ( $ajaxClass , $functionName ),
Api\Translation :: convert ( $parameters , 'utf-8' ));
2020-05-22 10:16:59 +02:00
2016-03-20 14:02:55 +01:00
}
}