From 8d2e3c2528e67f8650c122f014364a34bf690d2a Mon Sep 17 00:00:00 2001 From: Andrew Dolgov <noreply@fakecake.org> Date: Tue, 23 Feb 2021 22:26:07 +0300 Subject: [PATCH] drop errors.php and simplify error handling --- api/index.php | 8 +++-- backend.php | 12 ++++---- classes/api.php | 39 +++++++++++++++---------- classes/feeds.php | 10 +------ classes/handler/public.php | 14 ++++----- classes/pluginhandler.php | 6 ++-- classes/pref/feeds.php | 2 -- classes/pref/labels.php | 2 -- classes/pref/prefs.php | 2 +- classes/pref/users.php | 2 -- classes/rpc.php | 19 +++++++----- errors.php | 60 -------------------------------------- include/functions.php | 28 ------------------ include/login_form.php | 5 ++-- index.php | 5 ++-- js/App.js | 60 +++++++++++++------------------------- js/common.js | 5 +++- prefs.php | 5 ++-- public.php | 6 ++-- 19 files changed, 92 insertions(+), 198 deletions(-) delete mode 100644 errors.php diff --git a/api/index.php b/api/index.php index 4e2c06b9d..d85a1103c 100644 --- a/api/index.php +++ b/api/index.php @@ -34,9 +34,11 @@ if (!\Sessions\validate_session()) { header("Content-Type: text/json"); - print json_encode(array("seq" => -1, - "status" => 1, - "content" => array("error" => "NOT_LOGGED_IN"))); + print json_encode([ + "seq" => -1, + "status" => API::STATUS_ERR, + "content" => [ "error" => API::E_NOT_LOGGED_IN ] + ]); return; } diff --git a/backend.php b/backend.php index 9bc1449d0..206d866b7 100644 --- a/backend.php +++ b/backend.php @@ -45,7 +45,7 @@ if (!empty($_SESSION["uid"])) { if (!\Sessions\validate_session()) { header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); return; } UserHelper::load_user_plugins($_SESSION["uid"]); @@ -106,7 +106,7 @@ if (strpos($method, "_") === 0) { user_error("Refusing to invoke method $method of handler $op which starts with underscore.", E_USER_WARNING); header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); return; } @@ -130,7 +130,7 @@ } else { user_error("Refusing to invoke method $method of handler $op which has required parameters.", E_USER_WARNING); header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); } } else { if (method_exists($handler, "catchall")) { @@ -141,19 +141,19 @@ return; } else { header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); return; } } else { user_error("Refusing to invoke method $method of handler $op with invalid CSRF token.", E_USER_WARNING); header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); return; } } } header("Content-Type: text/json"); - print error_json(13); + print Errors::to_json(Errors::E_UNKNOWN_METHOD); ?> diff --git a/classes/api.php b/classes/api.php index 6f3ee77db..1b3ee7d92 100755 --- a/classes/api.php +++ b/classes/api.php @@ -6,6 +6,13 @@ class API extends Handler { const STATUS_OK = 0; const STATUS_ERR = 1; + const E_API_DISABLED = "API_DISABLED"; + const E_NOT_LOGGED_IN = "NOT_LOGGED_IN"; + const E_LOGIN_ERROR = "LOGIN_ERROR"; + const E_INCORRECT_USAGE = "INCORRECT_USAGE"; + const E_UNKNOWN_METHOD = "UNKNOWN_METHOD"; + const E_OPERATION_FAILED = "E_OPERATION_FAILED"; + private $seq; private static function _param_to_bool($p) { @@ -13,9 +20,11 @@ class API extends Handler { } private function _wrap($status, $reply) { - print json_encode(array("seq" => $this->seq, - "status" => $status, - "content" => $reply)); + print json_encode([ + "seq" => $this->seq, + "status" => $status, + "content" => $reply + ]); } function before($method) { @@ -23,12 +32,12 @@ class API extends Handler { header("Content-Type: text/json"); if (empty($_SESSION["uid"]) && $method != "login" && $method != "isloggedin") { - $this->_wrap(self::STATUS_ERR, array("error" => 'NOT_LOGGED_IN')); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_NOT_LOGGED_IN)); return false; } if (!empty($_SESSION["uid"]) && $method != "logout" && !get_pref('ENABLE_API_ACCESS')) { - $this->_wrap(self::STATUS_ERR, array("error" => 'API_DISABLED')); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_API_DISABLED)); return false; } @@ -69,13 +78,13 @@ class API extends Handler { "api_level" => self::API_LEVEL)); } else { // else we are not logged in user_error("Failed login attempt for $login from " . UserHelper::get_user_ip(), E_USER_WARNING); - $this->_wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR")); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_LOGIN_ERROR)); } } else { - $this->_wrap(self::STATUS_ERR, array("error" => "API_DISABLED")); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_API_DISABLED)); } } else { - $this->_wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR")); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_LOGIN_ERROR)); return; } } @@ -221,7 +230,7 @@ class API extends Handler { $this->_wrap(self::STATUS_OK, $headlines); } } else { - $this->_wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_INCORRECT_USAGE)); } } @@ -281,7 +290,7 @@ class API extends Handler { "updated" => $num_updated)); } else { - $this->_wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_INCORRECT_USAGE)); } } @@ -356,7 +365,7 @@ class API extends Handler { $this->_wrap(self::STATUS_OK, $articles); } else { - $this->_wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_INCORRECT_USAGE)); } } @@ -481,7 +490,7 @@ class API extends Handler { $this->_wrap($reply[0], $reply[1]); } else { - $this->_wrap(self::STATUS_ERR, array("error" => 'UNKNOWN_METHOD', "method" => $method)); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_UNKNOWN_METHOD, "method" => $method)); } } @@ -493,7 +502,7 @@ class API extends Handler { if (Article::_create_published_article($title, $url, $content, "", $_SESSION["uid"])) { $this->_wrap(self::STATUS_OK, array("status" => 'OK')); } else { - $this->_wrap(self::STATUS_ERR, array("error" => 'Publishing failed')); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_OPERATION_FAILED)); } } @@ -816,7 +825,7 @@ class API extends Handler { Pref_Feeds::remove_feed($feed_id, $_SESSION["uid"]); $this->_wrap(self::STATUS_OK, array("status" => "OK")); } else { - $this->_wrap(self::STATUS_ERR, array("error" => "FEED_NOT_FOUND")); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_OPERATION_FAILED)); } } @@ -831,7 +840,7 @@ class API extends Handler { $this->_wrap(self::STATUS_OK, array("status" => $rc)); } else { - $this->_wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); + $this->_wrap(self::STATUS_ERR, array("error" => self::E_INCORRECT_USAGE)); } } diff --git a/classes/feeds.php b/classes/feeds.php index eaedc1aee..a38cbae97 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -499,15 +499,7 @@ class Feeds extends Handler_Protected { // this is parsed by handleRpcJson() on first viewfeed() to set cdm expanded, etc $reply['runtime-info'] = RPC::make_runtime_info(); - $reply_json = json_encode($reply); - - if (!$reply_json) { - $reply_json = json_encode(["error" => ["code" => 15, - "message" => json_last_error_msg()]]); - } - - print $reply_json; - + print json_encode($reply); } private function _generate_dashboard_feed() { diff --git a/classes/handler/public.php b/classes/handler/public.php index 79dff37b5..42be6f713 100755 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -240,7 +240,7 @@ class Handler_Public extends Handler { } else { header("Content-Type: text/plain; charset=utf-8"); - print json_encode(array("error" => array("message" => "Unknown format"))); + print "Unknown format: $format."; } } @@ -290,7 +290,7 @@ class Handler_Public extends Handler { header("Location: index.php"); } else { header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); } } @@ -408,7 +408,7 @@ class Handler_Public extends Handler { function index() { header("Content-Type: text/plain"); - print error_json(13); + print Errors::to_json(Errors::E_UNKNOWN_METHOD); } function forgotpass() { @@ -659,7 +659,7 @@ class Handler_Public extends Handler { <div class="content"> <?php - @$op = clean($_REQUEST["subop"]); + @$op = clean($_REQUEST["subop"] ?? ""); $updater = new DbUpdater(Db::pdo(), Config::get(Config::DB_TYPE), SCHEMA_VERSION); if ($op == "performupdate") { @@ -802,17 +802,17 @@ class Handler_Public extends Handler { } else { user_error("PluginHandler[PUBLIC]: Requested private method '$method' of plugin '$plugin_name'.", E_USER_WARNING); header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); } } else { user_error("PluginHandler[PUBLIC]: Requested unknown method '$method' of plugin '$plugin_name'.", E_USER_WARNING); header("Content-Type: text/json"); - print error_json(13); + print Errors::to_json(Errors::E_UNKNOWN_METHOD); } } else { user_error("PluginHandler[PUBLIC]: Requested method '$method' of unknown plugin '$plugin_name'.", E_USER_WARNING); header("Content-Type: text/json"); - print error_json(14); + print Errors::to_json(Errors::E_UNKNOWN_PLUGIN); } } diff --git a/classes/pluginhandler.php b/classes/pluginhandler.php index 608f80dcb..75b823822 100644 --- a/classes/pluginhandler.php +++ b/classes/pluginhandler.php @@ -15,15 +15,15 @@ class PluginHandler extends Handler_Protected { $plugin->$method(); } else { user_error("Rejected ${plugin_name}->${method}(): invalid CSRF token.", E_USER_WARNING); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); } } else { user_error("Rejected ${plugin_name}->${method}(): unknown method.", E_USER_WARNING); - print error_json(13); + print Errors::to_json(Errors::E_UNKNOWN_METHOD); } } else { user_error("Rejected ${plugin_name}->${method}(): unknown plugin.", E_USER_WARNING); - print error_json(14); + print Errors::to_json(Errors::E_UNKNOWN_PLUGIN); } } } diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php index 7c3a40647..086c52697 100755 --- a/classes/pref/feeds.php +++ b/classes/pref/feeds.php @@ -561,8 +561,6 @@ class Pref_Feeds extends Handler_Protected { "all" => $this::get_ts_languages(), ] ]); - } else { - print json_encode(["error" => "FEED_NOT_FOUND"]); } } diff --git a/classes/pref/labels.php b/classes/pref/labels.php index 0b826e13f..5bc094d55 100644 --- a/classes/pref/labels.php +++ b/classes/pref/labels.php @@ -16,8 +16,6 @@ class Pref_Labels extends Handler_Protected { if ($line = $sth->fetch(PDO::FETCH_ASSOC)) { print json_encode($line); - } else { - print json_encode(["error" => "LABEL_NOT_FOUND"]); } } diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index 7ee03c21f..0d0dcadbc 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -1063,7 +1063,7 @@ class Pref_Prefs extends Handler_Protected { } } else { header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); } } diff --git a/classes/pref/users.php b/classes/pref/users.php index f30abe001..13f808cb3 100644 --- a/classes/pref/users.php +++ b/classes/pref/users.php @@ -19,8 +19,6 @@ class Pref_Users extends Handler_Administrative { "user" => $row, "access_level_names" => $access_level_names ]); - } else { - print json_encode(["error" => "USER_NOT_FOUND"]); } } diff --git a/classes/rpc.php b/classes/rpc.php index 52d514aae..d0388a066 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -118,16 +118,22 @@ class RPC extends Handler_Protected { $_SESSION["hasSandbox"] = clean($_REQUEST["hasSandbox"]) === "true"; $_SESSION["clientTzOffset"] = clean($_REQUEST["clientTzOffset"]); - $reply = array(); + $error = Errors::E_SUCCESS; - $reply['error'] = sanity_check(); + if (get_schema_version(true) != SCHEMA_VERSION) { + $error = Errors::E_SCHEMA_MISMATCH; + } + + if ($error == Errors::E_SUCCESS) { + $reply = []; - if ($reply['error']['code'] == 0) { $reply['init-params'] = $this->make_init_params(); $reply['runtime-info'] = $this->make_runtime_info(); - } - print json_encode($reply); + print json_encode($reply); + } else { + print Errors::to_json($error); + } } /*function completeLabels() { @@ -315,10 +321,7 @@ class RPC extends Handler_Protected { $msg, 'client-js:' . $file, $line, $context); echo json_encode(array("message" => "HOST_ERROR_LOGGED")); - } else { - echo json_encode(array("error" => "MESSAGE_NOT_FOUND")); } - } function checkforupdates() { diff --git a/errors.php b/errors.php deleted file mode 100644 index 3195c4b64..000000000 --- a/errors.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - set_include_path(__DIR__ ."/include" . PATH_SEPARATOR . - get_include_path()); - - require_once "functions.php"; - - function get_error_types() { - $ERRORS[0] = ""; - - $ERRORS[1] = __("This program requires XmlHttpRequest " . - "to function properly. Your browser doesn't seem to support it."); - - $ERRORS[2] = __("This program requires cookies " . - "to function properly. Your browser doesn't seem to support them."); - - $ERRORS[3] = __("Backend sanity check failed."); - - $ERRORS[4] = __("Frontend sanity check failed."); - - $ERRORS[5] = __("Incorrect database schema version. <a href='db-updater.php'>Please update</a>."); - - $ERRORS[6] = __("Request not authorized."); - - $ERRORS[7] = __("No operation to perform."); - - $ERRORS[8] = __("Could not display feed: query failed. Please check label match syntax or local configuration."); - - $ERRORS[8] = __("Denied. Your access level is insufficient to access this page."); - - $ERRORS[9] = __("Configuration check failed"); - - $ERRORS[10] = __("Your version of MySQL is not currently supported. Please see official site for more information."); - - $ERRORS[11] = "[This error is not returned by server]"; - - $ERRORS[12] = __("SQL escaping test failed, check your database and PHP configuration"); - - $ERRORS[13] = __("Method not found"); - - $ERRORS[14] = __("Plugin not found"); - - $ERRORS[15] = __("Encoding data as JSON failed"); - - return $ERRORS; - } - - if ($_REQUEST['mode'] ?? "" == 'js') { - header("Content-Type: text/javascript; charset=UTF-8"); - - print "var ERRORS = [];\n"; - - foreach (get_error_types() as $id => $error) { - - $error = preg_replace("/\n/", "", $error); - $error = preg_replace("/\"/", "\\\"", $error); - - print "ERRORS[$id] = \"$error\";\n"; - } - } -?> diff --git a/include/functions.php b/include/functions.php index a698fa79d..d916301fb 100644 --- a/include/functions.php +++ b/include/functions.php @@ -323,20 +323,6 @@ } } - function sanity_check() { - require_once 'errors.php'; - $ERRORS = get_error_types(); - - $error_code = 0; - $schema_version = get_schema_version(true); - - if ($schema_version != SCHEMA_VERSION) { - $error_code = 5; - } - - return array("code" => $error_code, "message" => $ERRORS[$error_code]); - } - function file_is_locked($filename) { if (file_exists(Config::get(Config::LOCK_DIRECTORY) . "/$filename")) { if (function_exists('flock')) { @@ -533,20 +519,6 @@ return file_exists("themes/$theme") || file_exists("themes.local/$theme"); } - /** - * @SuppressWarnings(unused) - */ - function error_json($code) { - require_once "errors.php"; - $ERRORS = get_error_types(); - - @$message = $ERRORS[$code]; - - return json_encode(array("error" => - array("code" => $code, "message" => $message))); - - } - function arr_qmarks($arr) { return str_repeat('?,', count($arr) - 1) . '?'; } diff --git a/include/login_form.php b/include/login_form.php index 168fe50aa..06bf57470 100755 --- a/include/login_form.php +++ b/include/login_form.php @@ -6,11 +6,10 @@ <link rel="shortcut icon" type="image/png" href="images/favicon.png"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <?php - foreach (array("lib/dojo/dojo.js", + foreach (["lib/dojo/dojo.js", "lib/dojo/tt-rss-layer.js", "js/common.js", - "js/utility.js", - "errors.php?mode=js") as $jsfile) { + "js/utility.js"] as $jsfile) { echo javascript_tag($jsfile); diff --git a/index.php b/index.php index 1f2802864..a21db6fc5 100644 --- a/index.php +++ b/index.php @@ -69,11 +69,10 @@ </script> <?php - foreach (array("lib/dojo/dojo.js", + foreach (["lib/dojo/dojo.js", "lib/dojo/tt-rss-layer.js", "js/tt-rss.js", - "js/common.js", - "errors.php?mode=js") as $jsfile) { + "js/common.js"] as $jsfile) { echo javascript_tag($jsfile); diff --git a/js/App.js b/js/App.js index 68f3740c5..6cad062f0 100644 --- a/js/App.js +++ b/js/App.js @@ -407,23 +407,15 @@ const App = { const counters = reply['counters']; const runtime_info = reply['runtime-info']; - if (error) { - const code = error['code']; - - if (code && code != 0) { - const msg = error['message']; - - console.warn("[handleRpcJson] received fatal error ", code, msg); - - /* global ERRORS */ - this.Error.fatal(ERRORS[code], {info: msg, code: code}); - return false; - } + if (error && error.code && error.code != App.Error.E_SUCCESS) { + console.warn("handleRpcJson: fatal error", error); + this.Error.fatal(error.code); + return false; } if (seq && this.get_seq() != seq) { - console.warn("[handleRpcJson] sequence mismatch: ", seq, '!=', this.get_seq()); - return; + console.warn("handleRpcJson: sequence mismatch: ", seq, '!=', this.get_seq()); + return false; } // not in preferences @@ -442,10 +434,13 @@ const App = { if (netalert) netalert.hide(); + return true; } else { if (netalert) netalert.show(); Notify.error("Communication problem with server."); + + return false; } }, parseRuntimeInfo: function(data) { @@ -487,20 +482,6 @@ const App = { PluginHost.run(PluginHost.HOOK_RUNTIME_INFO_LOADED, data); }, backendSanityCallback: function(reply) { - if (!reply) { - this.Error.fatal(ERRORS[3]); - return; - } - - if (reply['error']) { - const code = reply['error']['code']; - - if (code && code != 0) { - return this.Error.fatal(ERRORS[code], - {code: code, info: reply['error']['message']}); - } - } - console.log("sanity check ok"); const params = reply['init-params']; @@ -547,24 +528,25 @@ const App = { this.initSecondStage(); }, Error: { + E_SUCCESS: "E_SUCCESS", + E_UNAUTHORIZED: "E_UNAUTHORIZED", + E_SCHEMA_MISMATCH: "E_SCHEMA_MISMATCH", fatal: function (error, params = {}) { - if (params.code) { - if (params.code == 6) { - window.location.href = "index.php"; - return; - } else if (params.code == 5) { - window.location.href = "public.php?op=dbupdate"; - return; - } - } + if (error == App.Error.E_UNAUTHORIZED) { + window.location.href = "index.php"; + return; + } else if (error == App.Error.E_SCHEMA_MISMATCH) { + window.location.href = "public.php?op=dbupdate"; + return; + } - return this.report(error, + return this.report(__("Fatal error: %s").replace("%s", error), {...{title: __("Fatal error")}, ...params}); }, report: function(error, params = {}) { if (!error) return; - console.error("[Error.report]", error, params); + console.error("error.report:", error, params); const message = params.message ? params.message : error.toString(); diff --git a/js/common.js b/js/common.js index df1bf8690..670ee1b30 100755 --- a/js/common.js +++ b/js/common.js @@ -179,7 +179,10 @@ const xhr = { console.log('xhr.json', '<<<', obj); if (obj && typeof App != "undefined") - App.handleRpcJson(obj); + if (!App.handleRpcJson(obj)) { + reject(obj); + return; + } if (complete != undefined) complete(obj); diff --git a/prefs.php b/prefs.php index 851dd898a..57ddbba7c 100644 --- a/prefs.php +++ b/prefs.php @@ -51,11 +51,10 @@ </script> <?php - foreach (array("lib/dojo/dojo.js", + foreach (["lib/dojo/dojo.js", "lib/dojo/tt-rss-layer.js", "js/common.js", - "js/prefs.js", - "errors.php?mode=js") as $jsfile) { + "js/prefs.js"] as $jsfile) { echo javascript_tag($jsfile); diff --git a/public.php b/public.php index 43aa66c1d..28f95d0a9 100644 --- a/public.php +++ b/public.php @@ -37,7 +37,7 @@ if (strpos($method, "_") === 0) { user_error("Refusing to invoke method $method which starts with underscore.", E_USER_WARNING); header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); return; } @@ -50,7 +50,7 @@ } else { user_error("Refusing to invoke method $method which has required parameters.", E_USER_WARNING); header("Content-Type: text/json"); - print error_json(6); + print Errors::to_json(Errors::E_UNAUTHORIZED); } } else if (method_exists($handler, 'index')) { $handler->index(); @@ -60,5 +60,5 @@ } header("Content-Type: text/plain"); - print error_json(13); + print Errors::to_json(Errors::E_UNKNOWN_METHOD); ?> -- GitLab