diff --git a/configure.php b/configure.php index 3d4f6151..cd206f86 100644 --- a/configure.php +++ b/configure.php @@ -8,7 +8,7 @@ set_include_path .PATH_SEPARATOR.__DIR__ ); -const _DEVELOPER_MODE = TRUE; +const _DEBUG_MODE = TRUE; const _CONFIG_DIR = '/home/juan/.config'; const _LOG_DIR = '/tmp'; const _DATA_DIR = '/tmp'; diff --git a/js/db/conn.js b/js/db/conn.js index 0385167d..61d88834 100644 --- a/js/db/conn.js +++ b/js/db/conn.js @@ -62,7 +62,7 @@ Db.Conn.implement else if (guest) var params = {'guest': true}; - var request = new Vn.JsonRequest ('login'); + var request = new Vn.JsonRequest ('core/login'); request.send (params, this._onOpen.bind (this, callback)); } @@ -94,7 +94,7 @@ Db.Conn.implement { this.signalEmit ('loading-changed', true); - var request = new Vn.JsonRequest ('logout'); + var request = new Vn.JsonRequest ('core/logout'); request.send (null, this._onClose.bind (this, callback)); } @@ -127,7 +127,7 @@ Db.Conn.implement if (this._requestsCount === 1) this.signalEmit ('loading-changed', true); - var request = new Vn.JsonRequest ('query'); + var request = new Vn.JsonRequest ('core/query'); request.send ({'sql': sql}, this._onExec.bind (this, callback)); } diff --git a/js/hedera/app.js b/js/hedera/app.js index 250fbfc3..c1f19258 100644 --- a/js/hedera/app.js +++ b/js/hedera/app.js @@ -117,23 +117,20 @@ Vn.App = new Class ,_onConnError: function (conn, error) { - if (error instanceof Vn.Error) - switch (error.code) + if (error instanceof Vn.JsonException) + switch (error.exception) { - case 'badLogin': + case 'Vn\\Web\\BadLoginException': Htk.Toast.showError (_('Invalid login')); this._logout (); break; - case 'sessionExpired': + case 'Vn\\Web\\SessionExpiredException': Htk.Toast.showError (_('You\'ve been too idle')); this._logout (); break; - case 'newVersion': + case 'Vn\\Web\\OutdatedVersionException': this._newVersion (error); break; - case 'internalError': - Htk.Toast.showError (_('There was an internal error')); - break; default: Htk.Toast.showError (error.message); } @@ -152,29 +149,13 @@ Vn.App = new Class ,_newVersion: function (error) { - if (this.newVersionBlock || this.skipVersion) + if (this.skipVersion) return; - - this.newVersionBlock = true; - var reload; - var message = _('New version available') +"\n\n"+ error.message; + this.skipVersion = true; - if (error.code == 'criticalVersion') - { - alert (message) - reload = true; - } - else - { - reload = confirm (message); - this.skipVersion = true; - } - - if (reload) + if (confirm (_('New version available'))) location.reload (); - - this.newVersionBlock = false; } ,_notifyError: function (error) diff --git a/js/hedera/module.js b/js/hedera/module.js index 5df67f91..398e16fb 100644 --- a/js/hedera/module.js +++ b/js/hedera/module.js @@ -68,7 +68,7 @@ Vn.Module = new Class var klassName = this.toCamelCase (this.moduleName); try { - this.klass = eval (klassName); + this.klass = Vn[klassName]; } catch (e) { @@ -85,7 +85,7 @@ Vn.Module = new Class ,toCamelCase: function (dashedName) { - var camelCase = 'Vn.'+ dashedName.charAt (0).toUpperCase (); + var camelCase = dashedName.charAt (0).toUpperCase (); camelCase += dashedName.substr (1).replace (/\w\-\w/g, function (token) { return token.charAt (0) + token.charAt (2).toUpperCase (); diff --git a/js/vn/builder.js b/js/vn/builder.js index 1560f086..5abea78d 100644 --- a/js/vn/builder.js +++ b/js/vn/builder.js @@ -527,20 +527,10 @@ Vn.Builder = new Class ,_getMethod: function (value) { if (this.signalData) - var methodName = 'this.signalData.'+ value; + var method = this.signalData[value]; else - var methodName = value; + var method = window[value]; - var method; - - try { - method = eval (methodName); - } - catch (e) - { - method = undefined; - } - if (method === undefined) this._showError ('Function \'%s\' not found', value); diff --git a/js/vn/error.js b/js/vn/json-exception.js similarity index 71% rename from js/vn/error.js rename to js/vn/json-exception.js index 9980d59e..1ece1c21 100644 --- a/js/vn/error.js +++ b/js/vn/json-exception.js @@ -1,11 +1,14 @@ /** * This class stores the database errors. **/ -Vn.Error = new Class +Vn.JsonException = new Class ({ - domain: null - ,code: null + exception: null ,message: null + ,code: null + ,file: null + ,line: null + ,trace: null ,initialize: function (domain, code, message) { diff --git a/js/vn/json-request.js b/js/vn/json-request.js index 0014fd05..dd031656 100644 --- a/js/vn/json-request.js +++ b/js/vn/json-request.js @@ -21,7 +21,7 @@ Vn.JsonRequest = new Class ,send: function (params, callback) { - var url = 'rest.php?method='+ encodeURIComponent (this._methodName); + var url = 'json.php?method='+ encodeURIComponent (this._methodName); this.sendWithUrl (params, callback, 'post', url); } @@ -30,31 +30,38 @@ Vn.JsonRequest = new Class if (request.readyState !== 4) return; - var jsData = null; + var data = null; var error = null; try { - if (request.status !== 200) - throw new Error (request.statusText); - var json = JSON.parse (request.responseText); var jsData = json.data; - var jsError = json.error; - - if (jsError) - throw new Vn.Error ( - jsError.domain, - jsError.code, - jsError.message); + var jsWarns = json.warnings; + + if (request.status == 200) + { + data = jsData; + } + else + { + var ex = new Vn.JsonException (); + ex.exception = jsData.exception; + ex.message = jsData.message; + ex.code = jsData.code; + ex.file = jsData.file; + ex.line = jsData.line; + ex.trace = jsData.trace; + throw ex; + } } catch (e) { - jsData = null; + data = null; error = e; } if (callback) - callback (this, jsData, error); + callback (this, data, error); } ,sendForm: function (form, callback) diff --git a/js/vn/locale.js b/js/vn/locale.js index ce298c3a..7e153546 100644 --- a/js/vn/locale.js +++ b/js/vn/locale.js @@ -44,7 +44,7 @@ Vn.Locale = if (request.status == 200) { try { - this.add (eval ('('+ request.responseText +')')); + this.add (JSON.parse (request.responseText)); success = true; } catch (e) { diff --git a/js/vn/main.js b/js/vn/main.js index ec2c8ab6..83a93c81 100644 --- a/js/vn/main.js +++ b/js/vn/main.js @@ -6,7 +6,6 @@ Vn.includeLib ('vn', ,'cookie' ,'date' ,'value' - ,'error' ,'url' ,'mutators' ,'object' @@ -16,6 +15,7 @@ Vn.includeLib ('vn', ,'hash-param' ,'node' ,'builder' + ,'json-exception' ,'json-request' ]); diff --git a/json.php b/json.php new file mode 100755 index 00000000..3b38f063 --- /dev/null +++ b/json.php @@ -0,0 +1,9 @@ +run (); + +?> diff --git a/rest/tpv/confirm-mail.php b/rest/tpv/confirm-mail.php index 8d4bd1f4..df5557ec 100644 --- a/rest/tpv/confirm-mail.php +++ b/rest/tpv/confirm-mail.php @@ -1,11 +1,12 @@ confirm ($params, $db); + $success = Tpv::confirm ($db, $params); } catch (\Exception $e) { @@ -64,9 +65,7 @@ class TpvConfirmMail extends Vn\Web\JsonRequest else $folder = $imapConf['error_folder']; - $folder = sprintf ('INBOX.%s', $folder); - - if (!imap_mail_move ($imap, $msg, $folder)) + if (!imap_mail_move ($imap, $msg, "INBOX.$folder")) trigger_error (imap_last_error (), E_USER_WARNING); } @@ -100,10 +99,7 @@ class TpvConfirmMail extends Vn\Web\JsonRequest } } - return [ - 'processed' => $count, - 'deleted' => $deleted - ]; + echo "TPV: $count mails processed, $deleted mails deleted"; } } diff --git a/rest/tpv/confirm-post.php b/rest/tpv/confirm-post.php index e124c458..9716c28b 100644 --- a/rest/tpv/confirm-post.php +++ b/rest/tpv/confirm-post.php @@ -1,16 +1,16 @@ confirm ($_POST); - return TRUE; + Tpv::confirm ($db, $_POST); } } diff --git a/rest/tpv/confirm-soap.php b/rest/tpv/confirm-soap.php index a1fddd5e..3a757362 100644 --- a/rest/tpv/confirm-soap.php +++ b/rest/tpv/confirm-soap.php @@ -2,6 +2,7 @@ require_once ('vn/web/http-request.php'); require_once ('vn/web/util.php'); +require_once (__DIR__.'/tpv.php'); /** * Gets transaction confirmation from SOAP service. @@ -34,13 +35,13 @@ function procesaNotificacionSIS ($XML) try { $xml = new SimpleXMLElement ($requestString); - $request = (array) $xml->{'Request'}; + $params = (array) $xml->{'Request'}; - if (!(isset ($request['Ds_Amount']) - && isset ($request['Ds_Order']) - && isset ($request['Ds_MerchantCode']) - && isset ($request['Ds_Currency']) - && isset ($request['Ds_Response']))) + if (!(isset ($params['Ds_Amount']) + && isset ($params['Ds_Order']) + && isset ($params['Ds_MerchantCode']) + && isset ($params['Ds_Currency']) + && isset ($params['Ds_Response']))) throw new Exception ('Missing required parameters'); // Checks the signature @@ -51,7 +52,7 @@ function procesaNotificacionSIS ($XML) $key = $db->getValue ( 'SELECT secret_key FROM tpv_merchant WHERE id = #' - ,[$request['Ds_MerchantCode']] + ,[$params['Ds_MerchantCode']] ); if (sha1 ($shaString.$key) != $xml->{'Signature'}) @@ -59,7 +60,7 @@ function procesaNotificacionSIS ($XML) // Confirms the transaction - $tpvConfirmSoap->confirm ($request); + Tpv::confirm ($db, $params); } catch (Exception $e) { diff --git a/vn/web/app.php b/vn/web/app.php index d65ef633..a4381718 100755 --- a/vn/web/app.php +++ b/vn/web/app.php @@ -12,23 +12,25 @@ use Vn\Db\Conn; /** * Thrown when user credentials could not be fetched. **/ -class SessionExpiredException extends \Exception {} +class SessionExpiredException extends Lib\UserException {} /** * Thrown when user credentials are invalid. **/ -class BadLoginException extends \Exception {} +class BadLoginException extends Lib\UserException {} /** * Thrown when client version is outdated. **/ -class OutdatedVersionException extends \Exception {} +class OutdatedVersionException extends Lib\UserException {} /** * Main class for web applications. **/ abstract class App extends Lib\App { + protected $conn = NULL; + /** * Starts the user session. **/ @@ -36,7 +38,8 @@ abstract class App extends Lib\App { if ($this->isHttps ()) ini_set ('session.cookie_secure', TRUE); - + + ini_set ('session.hash_function', 'sha512'); session_start (); // Setting the locale @@ -124,7 +127,7 @@ abstract class App extends Lib\App function getVersion () { return (int) strftime ('%G%m%d%H%M%S', - filectime ($_SERVER['SCRIPT_FILENAME'])); + filectime (__FILE__ /* $_SERVER['SCRIPT_FILENAME'] */)); } /** @@ -145,147 +148,6 @@ abstract class App extends Lib\App else return parent::getConfigFile (); } - - /** - * Tries to retrieve user credentials from many sources such as POST, - * SESSION or COOKIES. If $_POST['remember'] is defined the user credentials - * are saved on the client brownser for future logins, cookies names are - * 'vn_user' for the user name and 'vn_pass' for user password, the - * password is encoded using base64_encode() function and should be decoded - * using base64_decode(). - **/ - function login () - { - if ($this->conn) - return $this->conn; - - $user = NULL; - $password = NULL; - $rememberUser = TRUE; - $rememberPass = FALSE; - $credentialsChanged = TRUE; - $wasLoged = isset ($_SESSION['user']); - - if (isset ($_POST['guest'])) - { - $sysConn = $this->getSysConn (); - $row = $sysConn->getRow ( - 'SELECT guest_user, guest_pass FROM config'); - - if ($row) - { - $user = $row['guest_user']; - $password = base64_decode ($row['guest_pass']); - $rememberUser = FALSE; - } - } - elseif (isset ($_POST['user']) && isset ($_POST['password'])) - { - $user = $_POST['user']; - $password = $_POST['password']; - - if (isset ($_POST['remember']) && $_POST['remember']) - $rememberPass = TRUE; - } - elseif (isset ($_SESSION['user'])) - { - $user = $_SESSION['user']; - $password = $_SESSION['password']; - $credentialsChanged = FALSE; - } - elseif (isset ($_COOKIE['vn_user']) && isset ($_COOKIE['vn_pass'])) - { - $user = $_COOKIE['vn_user']; - $password = base64_decode ($_COOKIE['vn_pass']); - $rememberPass = TRUE; - } - - if (!isset ($user)) - throw new SessionExpiredException (); - - try { - $db = $this->createConnection ($user, $password); - $db->query ('CALL user_session_start (#)', [session_id ()]); - $this->conn = $db; - - if ($rememberUser) - { - $cookieLife = time () + 7 * 86400; // 7 Days - setcookie ('vn_user', $user, $cookieLife); - - if ($rememberPass) - setcookie ('vn_pass', - base64_encode ($password), $cookieLife); - } - - $_SESSION['user'] = $user; - $_SESSION['password'] = $password; - } - catch (\Exception $e) - { - $this->conn = NULL; - throw new BadLoginException (); - } - - // Registering the user access - - if (!$wasLoged) - unset ($_SESSION['visitUser']); - - if (isset ($_SESSION['access']) - && !isset ($_SESSION['visitUser'])) - { - $sysConn = $this->getSysConn (); - $_SESSION['visitUser'] = $sysConn->getValue ( - 'CALL visit_user_new (#, #, #)', - [ - $_SESSION['access'] - ,nullIf ($_SESSION, 'visitUser') - ,session_id () - ] - ); - - if (!isset ($_SESSION['visitUnknown'])) - $_SESSION['visitUnknown'] = $_SESSION['visitUser']; - } - - return $db; - } - - /** - * Cleans the last saved used credentials. - **/ - function logout () - { - $_SESSION['visitUser'] = nullIf ($_SESSION, 'visitUnknown'); - - setcookie ('vn_pass', '', -1); - unset ($_COOKIE['vn_pass']); - unset ($_SESSION['user']); - unset ($_SESSION['password']); - - if ($this->conn) - { - $this->conn->query ( - 'DELETE FROM user_session_view ' - .'WHERE connection_id = CONNECTION_ID()' - ); - $this->conn->close (); - $this->conn = NULL; - } - } - - /** - * Deinitializes the Application. When init method is called, this - * function is called automatically at the end of the script . - **/ - function deinit () - { - if ($this->conn) - $this->conn->query ('CALL user_session_end ()'); - - parent::deinit (); - } } ?> diff --git a/vn/web/html-app.php b/vn/web/html-app.php index 067fec4a..b3aa0c2e 100644 --- a/vn/web/html-app.php +++ b/vn/web/html-app.php @@ -98,7 +98,7 @@ class HtmlApp extends App function printHeader () { header ('Content-Type: text/html; charset=UTF-8'); - header ("Content-Security-Policy: default-src 'self'"); + header ("Content-Security-Policy: default-src 'self'; img-src *"); } function globalErrorHandler () diff --git a/vn/web/http-request.php b/vn/web/http-request.php index afa126d1..576bf644 100644 --- a/vn/web/http-request.php +++ b/vn/web/http-request.php @@ -5,38 +5,8 @@ namespace Vn\Web; require_once (__DIR__.'/rest-app.php'); /** - * Base class for rest services. + * Base class for REST services. **/ -class HttpRequest extends \Vn\Lib\Method -{ - function listen () - { - try { - $this->run (); - } - catch (SessionExpiredException $e) - { - $this->httpError (403); - } - catch (BadLoginException $e) - { - $this->httpError (401); - } - catch (Exception $e) - { - $this->httpError (400); - } - } - - function httpError ($code) - { - - } - - function setError ($message, $code) - { - http_response_code (400); - } -} +abstract class HttpRequest extends \Vn\Lib\Method {} ?> diff --git a/vn/web/json-app.php b/vn/web/json-app.php new file mode 100644 index 00000000..413c7d53 --- /dev/null +++ b/vn/web/json-app.php @@ -0,0 +1,126 @@ +init (); + $this->startSession (); + + // Checks the client version + + if (!empty ($_COOKIE['vn_version'])) + $clientVersion = (int) $_COOKIE['vn_version']; + + if (isset ($clientVersion) + && $clientVersion < $this->getVersion ()) + throw new OutdatedVersionException (); + + $method = $this->loadMethod ($_REQUEST['method']); + $json = $method->run (); + $this->replyJson ($json); + } + + function replyJson ($jsonData) + { + $reply = new JsonReply (); + $reply->data = $jsonData; + $reply->warnings = $this->warnings; + + header ('Content-Type: application/json; charset=UTF-8'); + echo json_encode ($reply); + } + + function errorHandler ($errno, $message, $file, $line, $context) + { + $eUserWarn = + E_USER_NOTICE + | E_USER_WARNING + | E_USER_DEPRECATED; + $eCoreWarn = + E_NOTICE + | E_WARNING + | E_DEPRECATED; + + $eWarn = $eUserWarn | $eCoreWarn; + $eUser = $eUserWarn | E_USER_ERROR; + + $json = new JsonException (); + + if (_DEBUG_MODE || $errno & $eUser) + $json->message = $message; + else + $json->message = 'Something went wrong'; + + if (_DEBUG_MODE) + { + $json->code = $errno; + $json->file = $file; + $json->line = $line; + } + + if ($errno & $eWarn) + { + if (!isset ($this->warnings)) + $this->warnings = []; + + $this->warnings[] = $json; + } + else + { + http_response_code (500); + $this->replyJson ($json); + exit (); + } + + return !($errno & $eUser); + } + + function exceptionHandler ($e) + { + $json = new JsonException (); + + if (_DEBUG_MODE || $e instanceof Lib\UserException) + { + $json->exception = get_class ($e); + $json->message = $e->getMessage (); + } + else + { + $json->exception = 'Exception'; + $json->message = 'Something went wrong'; + } + + if (_DEBUG_MODE) + { + $json->code = $e->getCode (); + $json->file = $e->getFile (); + $json->line = $e->getLine (); + $json->trace = $e->getTraceAsString (); + } + + $this->statusFromException ($e); + $this->replyJson ($json); + + if (!($e instanceof Lib\UserException)) + throw $e; + } +} + +?> diff --git a/vn/web/json-message.php b/vn/web/json-exception.php similarity index 57% rename from vn/web/json-message.php rename to vn/web/json-exception.php index 69dbf00e..783d071f 100755 --- a/vn/web/json-message.php +++ b/vn/web/json-exception.php @@ -5,20 +5,18 @@ namespace Vn\Web; /** * Class used to store information about errors, warnings and info messages. * - * @property string $domain The domain name - * @property string $code The code of message + * @property string $exception The exception name * @property string $message The message string + * @property string $code The code of message **/ -class JsonMessage +class JsonException { - var $code; + var $exception = NULL; var $message; - - function __construct ($code, $message) - { - $this->code = $code; - $this->message = $message; - } + var $code = NULL; + var $file = NULL; + var $line = NULL; + var $trace = NULL; } ?> diff --git a/vn/web/json-reply.php b/vn/web/json-reply.php index 9a7b7ea4..8248ff79 100755 --- a/vn/web/json-reply.php +++ b/vn/web/json-reply.php @@ -2,17 +2,18 @@ namespace Vn\Web; +require_once (__DIR__.'/json-exception.php'); + /** * Class used for replies. * - * @property Error $error The error object or %NULL if no error - * @property array $warnings Array with warning messages * @property Object $data The returned data + * @property array $warnings Array with warning messages **/ class JsonReply { - var $warnings = NULL; var $data = NULL; + var $warnings = NULL; } ?> diff --git a/vn/web/json-request.php b/vn/web/json-request.php index c6cfa4c6..bde39840 100644 --- a/vn/web/json-request.php +++ b/vn/web/json-request.php @@ -2,82 +2,11 @@ namespace Vn\Web; -require_once (__DIR__.'/http-request.php'); -require_once (__DIR__.'/json-reply.php'); -require_once (__DIR__.'/json-message.php'); +require_once (__DIR__.'/json-app.php'); /** - * Base class for rest services. + * Base class for JSON services. **/ -class JsonRequest extends HttpRequest -{ - function listen () - { - try { - // Checks the client version - - if (!empty ($_COOKIE['vn_version'])) - $clientVersion = (int) $_COOKIE['vn_version']; - - if (isset ($clientVersion) - && $clientVersion < $this->getVersion ()) - throw new Lib\UserException (s('Critical version available'), 'newVersion'); - - // Fetchs the result - - $json = $this->run (); - $this->json ($json); - } - catch (SessionExpiredException $e) - { - $this->setError (s('The session has expired'), 'sessionExpired'); - } - catch (BadLoginException $e) - { - $this->setError (s('Invalid login'), 'badLogin'); - } - catch (Lib\UserException $e) - { - $this->setError ($e->getMessage (), $e->getCode ()); - } - } - - function json ($json) - { - $reply = new JsonReply (); - $reply->data = $json; - - if ($this->warnings) - { - $reply->warnings = []; - - foreach ($this->warnings as $warning) - $reply->warnings = $warning; - } - - $this->replyJson ($reply); - } - - function replyJson ($reply) - { - header ('Content-Type: application/json; charset=UTF-8'); - echo json_encode ($reply); - } - - function addWarning ($message, $code) - { - if (!isset ($this->reply->warnings)) - $this->reply->warnings = []; - - $this->warnings[] = new JsonMessage ($code, $message); - } - - function setError ($message, $code) - { - http_response_code (400); - $reply = new JsonMessage ($code, $message); - $this->replyJson ($reply); - } -} +abstract class JsonRequest extends \Vn\Lib\Method {} ?> diff --git a/vn/web/rest-app.php b/vn/web/rest-app.php index e8b5c37f..dcf6025c 100644 --- a/vn/web/rest-app.php +++ b/vn/web/rest-app.php @@ -4,72 +4,204 @@ namespace Vn\Web; require_once (__DIR__.'/app.php'); +use Vn\Lib; + /** - * Base class for rest services. + * Base class for REST application. **/ class RestApp extends App { - private $error = NULL; - private $warnings = NULL; - function run () { - $this->reply = new JsonReply (); + ini_set ('display_errors', _DEBUG_MODE); + set_error_handler ([$this, 'errorHandler'], E_ALL); + set_exception_handler ([$this, 'exceptionHandler']); $this->init (); $this->startSession (); + $method = $this->loadMethod ($_REQUEST['method']); + $method->run (); + } + + /** + * Tries to retrieve user credentials from many sources such as POST, + * SESSION or COOKIES. If $_POST['remember'] is defined the user credentials + * are saved on the client brownser for future logins, cookies names are + * 'vn_user' for the user name and 'vn_pass' for user password, the + * password is encoded using base64_encode() function and should be decoded + * using base64_decode(). + **/ + function login () + { + if ($this->conn) + return $this->conn; + + $user = NULL; + $password = NULL; + $rememberUser = TRUE; + $rememberPass = FALSE; + $credentialsChanged = TRUE; + $wasLoged = isset ($_SESSION['user']); + + if (isset ($_POST['guest'])) + { + $sysConn = $this->getSysConn (); + $row = $sysConn->getRow ( + 'SELECT guest_user, guest_pass FROM config'); + + if ($row) + { + $user = $row['guest_user']; + $password = base64_decode ($row['guest_pass']); + $rememberUser = FALSE; + } + } + elseif (isset ($_POST['user']) && isset ($_POST['password'])) + { + $user = $_POST['user']; + $password = $_POST['password']; + + if (isset ($_POST['remember']) && $_POST['remember']) + $rememberPass = TRUE; + } + elseif (isset ($_SESSION['user'])) + { + $user = $_SESSION['user']; + $password = $_SESSION['password']; + $credentialsChanged = FALSE; + } + elseif (isset ($_COOKIE['vn_user']) && isset ($_COOKIE['vn_pass'])) + { + $user = $_COOKIE['vn_user']; + $password = base64_decode ($_COOKIE['vn_pass']); + $rememberPass = TRUE; + } + + if (!isset ($user)) + throw new SessionExpiredException (); + try { - // Checks the client version + $db = $this->createConnection ($user, $password); + $db->query ('CALL user_session_start (#)', [session_id ()]); + $this->conn = $db; - if (!empty ($_COOKIE['vn_version'])) - $clientVersion = (int) $_COOKIE['vn_version']; + if ($rememberUser) + { + $cookieLife = time () + 7 * 86400; // 7 Days + setcookie ('vn_user', $user, $cookieLife); - if (isset ($clientVersion) - && $clientVersion < $this->getVersion ()) - throw new Lib\UserException (s('Critical version available'), 'newVersion'); + if ($rememberPass) + setcookie ('vn_pass', + base64_encode ($password), $cookieLife); + } - // Fetchs the result + $_SESSION['user'] = $user; + $_SESSION['password'] = $password; + } + catch (\Exception $e) + { + $this->conn = NULL; + throw new BadLoginException (); + } - $method = $this->loadMethod ($_REQUEST['method']); - $method->run (); + // Registering the user access + + if (!$wasLoged) + unset ($_SESSION['visitUser']); + + if (isset ($_SESSION['access']) + && !isset ($_SESSION['visitUser'])) + { + $sysConn = $this->getSysConn (); + $_SESSION['visitUser'] = $sysConn->getValue ( + 'CALL visit_user_new (#, #, #)', + [ + $_SESSION['access'] + ,nullIf ($_SESSION, 'visitUser') + ,session_id () + ] + ); + + if (!isset ($_SESSION['visitUnknown'])) + $_SESSION['visitUnknown'] = $_SESSION['visitUser']; + } + + return $db; + } + + /** + * Cleans the last saved used credentials. + **/ + function logout () + { + $_SESSION['visitUser'] = nullIf ($_SESSION, 'visitUnknown'); + + setcookie ('vn_pass', '', -1); + unset ($_COOKIE['vn_pass']); + unset ($_SESSION['user']); + unset ($_SESSION['password']); + + if ($this->conn) + { + $this->conn->query ( + 'DELETE FROM user_session_view ' + .'WHERE connection_id = CONNECTION_ID()' + ); + $this->conn->close (); + $this->conn = NULL; + } + } + + /** + * Deinitializes the Application. When init method is called, this + * function is called automatically at the end of the script . + **/ + function deinit () + { + if ($this->conn) + $this->conn->query ('CALL user_session_end ()'); + + parent::deinit (); + } + + function statusFromException ($e) + { + try { + throw $e; } catch (SessionExpiredException $e) - { - $this->setError (s('The session has expired'), 'sessionExpired'); - } + { $status = 401; } catch (BadLoginException $e) - { - $this->setError (s('Invalid login'), 'badLogin'); - } + { $status = 401; } catch (Lib\UserException $e) - { - $this->setError ($e->getMessage (), $e->getCode ()); - } + { $status = 400; } + catch (\Exception $e) + { $status = 500; } + + http_response_code ($status); } - + function errorHandler ($errno, $message, $file, $line, $context) { - switch ($errno) - { - case E_USER_WARNING: - $this->addWarning ($message, $errno); - break; - case E_WARNING: - case E_CORE_WARNING: - case E_COMPILE_WARNING: - $this->addWarning ('Something has gone wrong', 'internalWarning'); - default: - return parent::errorHandler ($errno, $message, $file, $line, $context); - } - - return TRUE; + $eFlag = + E_USER_NOTICE + | E_USER_WARNING + | E_USER_DEPRECATED + | E_NOTICE + | E_WARNING + | E_DEPRECATED; + + if (!($errno & $eFlag)) + http_response_code (500); + + return FALSE; } - function globalErrorHandler () + function exceptionHandler ($e) { - $this->setError ('An internal error has occurred', 'internalError'); - exit (0); + $this->statusFromException ($e); + throw $e; } }