151 lines
5.1 KiB
PHP
151 lines
5.1 KiB
PHP
<?php
|
|
/**
|
|
* EGroupware - general JSON handler for EGroupware
|
|
*
|
|
* @link http://www.egroupware.org
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
* @package api
|
|
* @subpackage ajax
|
|
* @author Andreas Stoeckel <as@stylite.de>
|
|
*/
|
|
|
|
use EGroupware\Api;
|
|
use EGroupware\Api\Egw;
|
|
use EGroupware\Api\Json;
|
|
|
|
/**
|
|
* callback if the session-check fails, redirects to login.php, if no valid basic auth credentials given
|
|
*
|
|
* @param array &$anon_account anon account_info with keys 'login', 'passwd' and optional 'passwd_type'
|
|
* @return boolean|string true if we allow anon access and anon_account is set, a sessionid or false otherwise
|
|
*/
|
|
function login_redirect(&$anon_account)
|
|
{
|
|
// allow to make json calls via basic auth
|
|
if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW']) &&
|
|
($session_id = Api\Header\Authenticate::autocreate_session_callback($anon_account)))
|
|
{
|
|
return $session_id;
|
|
}
|
|
Json\Request::isJSONRequest(true); // because Api\Json\Request::parseRequest() is not (yet) called
|
|
$response = Json\Response::get();
|
|
$response->apply('framework.callOnLogout');
|
|
$response->redirect($GLOBALS['egw_info']['server']['webserver_url'].'/login.php?cd=10', true);
|
|
|
|
// under PHP 8 the destructor is called to late and the response is not send
|
|
$GLOBALS['egw']->__destruct();
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
* Exception handler for xajax, return the message (and trace, if enabled) as alert() to the user
|
|
*
|
|
* Does NOT return!
|
|
*
|
|
* @param Exception|Error $e
|
|
*/
|
|
function ajax_exception_handler($e)
|
|
{
|
|
// handle redirects without logging
|
|
if (is_a($e, 'EGroupware\\Api\\Exception\\Redirect'))
|
|
{
|
|
Egw::redirect($e->url, $e->app);
|
|
}
|
|
// logging all exceptions to the error_log
|
|
$message = null;
|
|
if (function_exists('_egw_log_exception'))
|
|
{
|
|
_egw_log_exception($e,$message);
|
|
}
|
|
$response = Json\Response::get();
|
|
$message .= ($message ? "\n\n" : '').$e->getMessage();
|
|
|
|
$message .= "\n\n".$e->getFile().' ('.$e->getLine().')';
|
|
// only show trace (incl. function arguments) if explicitly enabled, eg. on a development system
|
|
if ($GLOBALS['egw_info']['server']['exception_show_trace'])
|
|
{
|
|
$message .= "\n\n".$e->getTraceAsString();
|
|
}
|
|
$response->message($message, 'error');
|
|
|
|
// under PHP 8 the destructor is called to late and the response is not send
|
|
$GLOBALS['egw']->__destruct();
|
|
exit;
|
|
}
|
|
|
|
// set our own exception handler, to not get the html from eGW's default one
|
|
set_exception_handler('ajax_exception_handler');
|
|
|
|
try {
|
|
if (!isset($_GET['menuaction']))
|
|
{
|
|
throw new InvalidArgumentException('Missing menuaction GET parameter', 998);
|
|
}
|
|
if (strpos($_GET['menuaction'],'::') !== false && strpos($_GET['menuaction'],'.') === false) // static method name app_something::method
|
|
{
|
|
@list($className,$functionName,$handler) = explode('::',$_GET['menuaction'])+[2 => null];
|
|
|
|
if (substr($className, 0, 11) == 'EGroupware\\')
|
|
{
|
|
list(,$appName) = explode('\\', strtolower($className));
|
|
}
|
|
else
|
|
{
|
|
list($appName) = explode('_',$className);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
@list($appName, $className, $functionName, $handler) = explode('.',$_GET['menuaction']);
|
|
}
|
|
//error_log("json.php: appName=$appName, className=$className, functionName=$functionName, handler=$handler");
|
|
|
|
$GLOBALS['egw_info'] = array(
|
|
'flags' => array(
|
|
'currentapp' => $appName,
|
|
'noheader' => True,
|
|
'disable_Template_class' => True,
|
|
'autocreate_session_callback' => 'login_redirect',
|
|
'no_exception_handler' => true, // we already installed our own
|
|
// only log ajax requests which represent former GET requests or submits
|
|
// cuts down updates to egw_access_log table
|
|
'no_dla_update' => !preg_match('/(Etemplate::ajax_process_content|\.jdots_framework\.ajax_exec\.template)/', $_GET['menuaction']),
|
|
)
|
|
);
|
|
include_once('./header.inc.php');
|
|
|
|
|
|
//Create a new json handler
|
|
$json = new Json\Request();
|
|
|
|
//Check whether the request data is set
|
|
if (isset($GLOBALS['egw_unset_vars']['_POST[json_data]']))
|
|
{
|
|
$json->isJSONRequest(true); // otherwise exception is not send back to client, as we have not yet called parseRequest()
|
|
throw new Json\Exception\ScriptTags("JSON Data contains script tags. Aborting...");
|
|
}
|
|
// check if we have a real json request
|
|
if (strpos($_SERVER['CONTENT_TYPE'], 'application/json') === 0)
|
|
{
|
|
$json->parseRequest($_GET['menuaction'], file_get_contents('php://input'));
|
|
}
|
|
else
|
|
{
|
|
$json->parseRequest($_GET['menuaction'], $_REQUEST['json_data']);
|
|
}
|
|
Json\Response::get();
|
|
|
|
// run egw destructor now explicit, in case a (notification) email is send via Egw::on_shutdown(),
|
|
// as stream-wrappers used by Horde Smtp fail when PHP is already in destruction
|
|
$GLOBALS['egw']->__destruct();
|
|
}
|
|
// missing menuaction GET parameter or request:parameters object or unparsable JSON
|
|
catch (\InvalidArgumentException $e) {
|
|
if (isset($json)) $json->isJSONRequest(false); // no regular json request processing
|
|
|
|
// give a proper HTTP status 400 Bad Request with some JSON payload explaining the problem
|
|
http_response_code(400);
|
|
header('Content-Type: application/json');
|
|
echo json_encode(array('error' => $e->getMessage(), 'errno' => $e->getCode()));
|
|
}
|
|
// other exceptions are handled by our ajax_exception_handler sending them back as alerts to client-side
|