From 8e8dbb2258cec6970745f825ade32a01348083e4 Mon Sep 17 00:00:00 2001 From: mikespub Date: Fri, 21 Jul 2023 00:11:08 +0200 Subject: [PATCH] clean up copied class files --- base.php | 515 +------------------------------ lib/Input/Request.php | 351 +-------------------- lib/Language/Translation.php | 399 +----------------------- lib/Language/Transliteration.php | 4 +- lib/Output/Format.php | 365 +--------------------- 5 files changed, 12 insertions(+), 1622 deletions(-) diff --git a/base.php b/base.php index 71f266442..76a325a35 100644 --- a/base.php +++ b/base.php @@ -4,6 +4,7 @@ * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Sébastien Lucas + * @author mikespub */ namespace SebLucas\Cops\Input; @@ -31,517 +32,3 @@ class Config "opds" => "opds.php", ]; } - -/** - * Summary of Request - */ -class Request -{ - /** - * Summary of urlParams - * @var array - */ - public $urlParams = []; - - public function __construct() - { - $this->init(); - } - - /** - * Summary of useServerSideRendering - * @return bool|int - */ - public function render() - { - global $config; - return preg_match('/' . $config['cops_server_side_render'] . '/', self::agent()); - } - - /** - * Summary of query - * @return mixed - */ - public function query() - { - if (isset($_SERVER['QUERY_STRING'])) { - return $_SERVER['QUERY_STRING']; - } - return ""; - } - - /** - * Summary of agent - * @return mixed - */ - public function agent() - { - if (isset($_SERVER['HTTP_USER_AGENT'])) { - return $_SERVER['HTTP_USER_AGENT']; - } - return ""; - } - - /** - * Summary of init - * @return void - */ - public function init() - { - $this->urlParams = []; - if (!empty($_GET)) { - foreach ($_GET as $name => $value) { - $this->urlParams[$name] = $_GET[$name]; - } - } - } - - /** - * Summary of get - * @param mixed $name - * @param mixed $default - * @return mixed - */ - public function get($name, $default = null) - { - if (!empty($this->urlParams) && isset($this->urlParams[$name]) && $this->urlParams[$name] != '') { - return $this->urlParams[$name]; - } - return $default; - } - - /** - * Summary of set - * @param mixed $name - * @param mixed $value - * @return void - */ - public function set($name, $value) - { - $this->urlParams[$name] = $value; - } - - /** - * Summary of option - * @param mixed $option - * @return mixed - */ - public function option($option) - { - global $config; - if (isset($_COOKIE[$option])) { - if (isset($config ['cops_' . $option]) && is_array($config ['cops_' . $option])) { - return explode(',', $_COOKIE[$option]); - } elseif (!preg_match('/[^A-Za-z0-9\-_.@]/', $_COOKIE[$option])) { - return $_COOKIE[$option]; - } - } - if (isset($config ['cops_' . $option])) { - return $config ['cops_' . $option]; - } - - return ''; - } - - /** - * Summary of style - * @return string - */ - public function style() - { - global $config; - $style = self::option('style'); - if (!preg_match('/[^A-Za-z0-9\-_]/', $style)) { - return 'templates/' . self::template() . '/styles/style-' . self::option('style') . '.css'; - } - return 'templates/' . $config['cops_template'] . '/styles/style-' . $config['cops_template'] . '.css'; - } - - /** - * Summary of template - * @return mixed - */ - public function template() - { - global $config; - $template = self::option('template'); - if (!preg_match('/[^A-Za-z0-9\-_]/', $template)) { - return $template; - } - return $config['cops_template']; - } - - /** - * Summary of verifyLogin - * @return bool - */ - public static function verifyLogin($serverVars = null) - { - global $config; - $serverVars ??= $_SERVER; - if (isset($config['cops_basic_authentication']) && - is_array($config['cops_basic_authentication'])) { - if (!isset($serverVars['PHP_AUTH_USER']) || - (isset($serverVars['PHP_AUTH_USER']) && - ($serverVars['PHP_AUTH_USER'] != $config['cops_basic_authentication']['username'] || - $serverVars['PHP_AUTH_PW'] != $config['cops_basic_authentication']['password']))) { - return false; - } - } - return true; - } - - /** - * Summary of notFound - * @return void - */ - public static function notFound() - { - header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found'); - header('Status: 404 Not Found'); - - $_SERVER['REDIRECT_STATUS'] = 404; - } - - /** - * Summary of build - * @param array $params - * @param ?array $server - * @param ?array $cookie - * @param ?array $config - * @return Request - */ - public static function build($params, $server = null, $cookie = null, $config = null) - { - // ['db' => $db, 'page' => $pageId, 'id' => $id, 'query' => $query, 'n' => $n] - $request = new self(); - $request->urlParams = $params; - return $request; - } -} - -namespace SebLucas\Cops\Output; - -use SebLucas\Cops\Input\Config; -use SebLucas\Template\doT; -use DOMDocument; - -class Format -{ - /** - * This method is a direct copy-paste from - * http://tmont.com/blargh/2010/1/string-format-in-php - */ - public static function str_format($format) - { - $args = func_get_args(); - $format = array_shift($args); - - preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE); - $offset = 0; - foreach ($matches[1] as $data) { - $i = $data[0]; - $format = substr_replace($format, @$args[(int)$i], $offset + $data[1] - 1, 2 + strlen($i)); - $offset += strlen(@$args[(int)$i]) - 2 - strlen($i); - } - - return $format; - } - - public static function addURLParam($urlParams, $paramName, $paramValue) - { - if (empty($urlParams)) { - $urlParams = ''; - } - $start = ''; - if (preg_match('#^\?(.*)#', $urlParams, $matches)) { - $start = '?'; - $urlParams = $matches[1]; - } - $params = []; - parse_str($urlParams, $params); - if (empty($paramValue) && strval($paramValue) !== "0") { - unset($params[$paramName]); - } else { - $params[$paramName] = $paramValue; - } - return $start . http_build_query($params); - } - - public static function addDatabaseParam($urlParams, $database) - { - if (!is_null($database)) { - $urlParams = self::addURLParam($urlParams, 'db', $database); - } - return $urlParams; - } - - public static function addVersion($url) - { - if (str_contains($url, '?')) { - $url .= '&v=' . Config::VERSION; - } else { - $url .= '?v=' . Config::VERSION; - } - return $url; - } - - public static function serverSideRender($data, $theme = 'default') - { - // Get the templates - $header = file_get_contents('templates/' . $theme . '/header.html'); - $footer = file_get_contents('templates/' . $theme . '/footer.html'); - $main = file_get_contents('templates/' . $theme . '/main.html'); - $bookdetail = file_get_contents('templates/' . $theme . '/bookdetail.html'); - $page = file_get_contents('templates/' . $theme . '/page.html'); - - // Generate the function for the template - $template = new doT(); - $dot = $template->template($page, ['bookdetail' => $bookdetail, - 'header' => $header, - 'footer' => $footer, - 'main' => $main]); - // If there is a syntax error in the function created - // $dot will be equal to FALSE - if (!$dot) { - return false; - } - // Execute the template - if (!empty($data)) { - return $dot($data); - } - - return null; - } - - public static function xml2xhtml($xml) - { - return preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', function ($m) { - $xhtml_tags = ['br', 'hr', 'input', 'frame', 'img', 'area', 'link', 'col', 'base', 'basefont', 'param']; - if (in_array($m[1], $xhtml_tags)) { - return '<' . $m[1] . $m[2] . ' />'; - } else { - return '<' . $m[1] . $m[2] . '>'; - } - }, $xml); - } - - public static function display_xml_error($error) - { - $return = ''; - $return .= str_repeat('-', $error->column) . "^\n"; - - switch ($error->level) { - case LIBXML_ERR_WARNING: - $return .= 'Warning ' . $error->code . ': '; - break; - case LIBXML_ERR_ERROR: - $return .= 'Error ' . $error->code . ': '; - break; - case LIBXML_ERR_FATAL: - $return .= 'Fatal Error ' . $error->code . ': '; - break; - } - - $return .= trim($error->message) . - "\n Line: " . $error->line . - "\n Column: " . $error->column; - - if ($error->file) { - $return .= "\n File: " . $error->file; - } - - return "$return\n\n--------------------------------------------\n\n"; - } - - public static function are_libxml_errors_ok() - { - $errors = libxml_get_errors(); - - foreach ($errors as $error) { - if ($error->code == 801) { - return false; - } - } - return true; - } - - public static function html2xhtml($html) - { - $doc = new DOMDocument(); - libxml_use_internal_errors(true); - - $doc->loadHTML('' . - $html . ''); // Load the HTML - $output = $doc->saveXML($doc->documentElement); // Transform to an Ansi xml stream - $output = self::xml2xhtml($output); - if (preg_match('#(.*)#ms', $output, $matches)) { - $output = $matches [1]; // Remove - } - /* - // In case of error with summary, use it to debug - $errors = libxml_get_errors(); - - foreach ($errors as $error) { - $output .= self::display_xml_error($error); - } - */ - - if (!self::are_libxml_errors_ok()) { - $output = 'HTML code not valid.'; - } - - libxml_use_internal_errors(false); - return $output; - } -} - -namespace SebLucas\Cops\Language; - -class Translation -{ - /** - * Get all accepted languages from the browser and put them in a sorted array - * languages id are normalized : fr-fr -> fr_FR - * @return array of languages - */ - public static function getAcceptLanguages() - { - $langs = []; - - if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - // break up string into pieces (languages and q factors) - $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE']; - if (preg_match('/^(\w{2})-\w{2}$/', $accept, $matches)) { - // Special fix for IE11 which send fr-FR and nothing else - $accept = $accept . ',' . $matches[1] . ';q=0.8'; - } - preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $accept, $lang_parse); - - if (count($lang_parse[1])) { - $langs = []; - foreach ($lang_parse[1] as $lang) { - // Format the language code (not standard among browsers) - if (strlen($lang) == 5) { - $lang = str_replace('-', '_', $lang); - $splitted = preg_split('/_/', $lang); - $lang = $splitted[0] . '_' . strtoupper($splitted[1]); - } - array_push($langs, $lang); - } - // create a list like "en" => 0.8 - $langs = array_combine($langs, $lang_parse[4]); - - // set default to 1 for any without q factor - foreach ($langs as $lang => $val) { - if ($val === '') { - $langs[$lang] = 1; - } - } - - // sort list based on value - arsort($langs, SORT_NUMERIC); - } - } - - return $langs; - } - - /** - * Find the best translation file possible based on the accepted languages - * @return array of language and language file - */ - public static function getLangAndTranslationFile() - { - global $config; - $langs = []; - $lang = 'en'; - if (!empty($config['cops_language'])) { - $lang = $config['cops_language']; - } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - $langs = self::getAcceptLanguages(); - } - //echo var_dump($langs); - $lang_file = null; - foreach ($langs as $language => $val) { - $temp_file = dirname(__FILE__). '/lang/Localization_' . $language . '.json'; - if (file_exists($temp_file)) { - $lang = $language; - $lang_file = $temp_file; - break; - } - } - if (empty($lang_file)) { - $lang_file = dirname(__FILE__). '/lang/Localization_' . $lang . '.json'; - } - return [$lang, $lang_file]; - } - - /** - * This method is based on this page - * http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/ - */ - public static function localize($phrase, $count=-1, $reset=false) - { - global $config; - if ($count == 0) { - $phrase .= '.none'; - } - if ($count == 1) { - $phrase .= '.one'; - } - if ($count > 1) { - $phrase .= '.many'; - } - - /* Static keyword is used to ensure the file is loaded only once */ - static $translations = null; - if ($reset) { - $translations = null; - } - /* If no instance of $translations has occured load the language file */ - if (is_null($translations)) { - $lang_file_en = null; - [$lang, $lang_file] = self::getLangAndTranslationFile(); - if ($lang != 'en') { - $lang_file_en = dirname(__FILE__). '/lang/' . 'Localization_en.json'; - } - - $lang_file_content = file_get_contents($lang_file); - /* Load the language file as a JSON object and transform it into an associative array */ - $translations = json_decode($lang_file_content, true); - - /* Clean the array of all unfinished translations */ - foreach (array_keys($translations) as $key) { - if (preg_match('/^##TODO##/', $key)) { - unset($translations [$key]); - } - } - if (!is_null($lang_file_en)) { - $lang_file_content = file_get_contents($lang_file_en); - $translations_en = json_decode($lang_file_content, true); - $translations = array_merge($translations_en, $translations); - } - } - if (array_key_exists($phrase, $translations)) { - return $translations[$phrase]; - } - return $phrase; - } - - public static function useNormAndUp() - { - global $config; - return $config ['cops_normalized_search'] == '1'; - } - - public static function normalizeUtf8String($s) - { - return Transliteration::process($s); - } - - public static function normAndUp($s) - { - return mb_strtoupper(self::normalizeUtf8String($s), 'UTF-8'); - } -} diff --git a/lib/Input/Request.php b/lib/Input/Request.php index 71f266442..81cf2204f 100644 --- a/lib/Input/Request.php +++ b/lib/Input/Request.php @@ -4,34 +4,11 @@ * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Sébastien Lucas + * @author mikespub */ namespace SebLucas\Cops\Input; -require 'config.php'; -/** @var array $config */ - -date_default_timezone_set($config['default_timezone']); - -/** - * Summary of Config - */ -class Config -{ - public const VERSION = '1.3.6'; - public const ENDPOINT = [ - "index" => "index.php", - "feed" => "feed.php", - "json" => "getJSON.php", - "fetch" => "fetch.php", - "read" => "epubreader.php", - "epubfs" => "epubfs.php", - "restapi" => "restapi.php", - "check" => "checkconfig.php", - "opds" => "opds.php", - ]; -} - /** * Summary of Request */ @@ -219,329 +196,3 @@ public static function build($params, $server = null, $cookie = null, $config = return $request; } } - -namespace SebLucas\Cops\Output; - -use SebLucas\Cops\Input\Config; -use SebLucas\Template\doT; -use DOMDocument; - -class Format -{ - /** - * This method is a direct copy-paste from - * http://tmont.com/blargh/2010/1/string-format-in-php - */ - public static function str_format($format) - { - $args = func_get_args(); - $format = array_shift($args); - - preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE); - $offset = 0; - foreach ($matches[1] as $data) { - $i = $data[0]; - $format = substr_replace($format, @$args[(int)$i], $offset + $data[1] - 1, 2 + strlen($i)); - $offset += strlen(@$args[(int)$i]) - 2 - strlen($i); - } - - return $format; - } - - public static function addURLParam($urlParams, $paramName, $paramValue) - { - if (empty($urlParams)) { - $urlParams = ''; - } - $start = ''; - if (preg_match('#^\?(.*)#', $urlParams, $matches)) { - $start = '?'; - $urlParams = $matches[1]; - } - $params = []; - parse_str($urlParams, $params); - if (empty($paramValue) && strval($paramValue) !== "0") { - unset($params[$paramName]); - } else { - $params[$paramName] = $paramValue; - } - return $start . http_build_query($params); - } - - public static function addDatabaseParam($urlParams, $database) - { - if (!is_null($database)) { - $urlParams = self::addURLParam($urlParams, 'db', $database); - } - return $urlParams; - } - - public static function addVersion($url) - { - if (str_contains($url, '?')) { - $url .= '&v=' . Config::VERSION; - } else { - $url .= '?v=' . Config::VERSION; - } - return $url; - } - - public static function serverSideRender($data, $theme = 'default') - { - // Get the templates - $header = file_get_contents('templates/' . $theme . '/header.html'); - $footer = file_get_contents('templates/' . $theme . '/footer.html'); - $main = file_get_contents('templates/' . $theme . '/main.html'); - $bookdetail = file_get_contents('templates/' . $theme . '/bookdetail.html'); - $page = file_get_contents('templates/' . $theme . '/page.html'); - - // Generate the function for the template - $template = new doT(); - $dot = $template->template($page, ['bookdetail' => $bookdetail, - 'header' => $header, - 'footer' => $footer, - 'main' => $main]); - // If there is a syntax error in the function created - // $dot will be equal to FALSE - if (!$dot) { - return false; - } - // Execute the template - if (!empty($data)) { - return $dot($data); - } - - return null; - } - - public static function xml2xhtml($xml) - { - return preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', function ($m) { - $xhtml_tags = ['br', 'hr', 'input', 'frame', 'img', 'area', 'link', 'col', 'base', 'basefont', 'param']; - if (in_array($m[1], $xhtml_tags)) { - return '<' . $m[1] . $m[2] . ' />'; - } else { - return '<' . $m[1] . $m[2] . '>'; - } - }, $xml); - } - - public static function display_xml_error($error) - { - $return = ''; - $return .= str_repeat('-', $error->column) . "^\n"; - - switch ($error->level) { - case LIBXML_ERR_WARNING: - $return .= 'Warning ' . $error->code . ': '; - break; - case LIBXML_ERR_ERROR: - $return .= 'Error ' . $error->code . ': '; - break; - case LIBXML_ERR_FATAL: - $return .= 'Fatal Error ' . $error->code . ': '; - break; - } - - $return .= trim($error->message) . - "\n Line: " . $error->line . - "\n Column: " . $error->column; - - if ($error->file) { - $return .= "\n File: " . $error->file; - } - - return "$return\n\n--------------------------------------------\n\n"; - } - - public static function are_libxml_errors_ok() - { - $errors = libxml_get_errors(); - - foreach ($errors as $error) { - if ($error->code == 801) { - return false; - } - } - return true; - } - - public static function html2xhtml($html) - { - $doc = new DOMDocument(); - libxml_use_internal_errors(true); - - $doc->loadHTML('' . - $html . ''); // Load the HTML - $output = $doc->saveXML($doc->documentElement); // Transform to an Ansi xml stream - $output = self::xml2xhtml($output); - if (preg_match('#(.*)#ms', $output, $matches)) { - $output = $matches [1]; // Remove - } - /* - // In case of error with summary, use it to debug - $errors = libxml_get_errors(); - - foreach ($errors as $error) { - $output .= self::display_xml_error($error); - } - */ - - if (!self::are_libxml_errors_ok()) { - $output = 'HTML code not valid.'; - } - - libxml_use_internal_errors(false); - return $output; - } -} - -namespace SebLucas\Cops\Language; - -class Translation -{ - /** - * Get all accepted languages from the browser and put them in a sorted array - * languages id are normalized : fr-fr -> fr_FR - * @return array of languages - */ - public static function getAcceptLanguages() - { - $langs = []; - - if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - // break up string into pieces (languages and q factors) - $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE']; - if (preg_match('/^(\w{2})-\w{2}$/', $accept, $matches)) { - // Special fix for IE11 which send fr-FR and nothing else - $accept = $accept . ',' . $matches[1] . ';q=0.8'; - } - preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $accept, $lang_parse); - - if (count($lang_parse[1])) { - $langs = []; - foreach ($lang_parse[1] as $lang) { - // Format the language code (not standard among browsers) - if (strlen($lang) == 5) { - $lang = str_replace('-', '_', $lang); - $splitted = preg_split('/_/', $lang); - $lang = $splitted[0] . '_' . strtoupper($splitted[1]); - } - array_push($langs, $lang); - } - // create a list like "en" => 0.8 - $langs = array_combine($langs, $lang_parse[4]); - - // set default to 1 for any without q factor - foreach ($langs as $lang => $val) { - if ($val === '') { - $langs[$lang] = 1; - } - } - - // sort list based on value - arsort($langs, SORT_NUMERIC); - } - } - - return $langs; - } - - /** - * Find the best translation file possible based on the accepted languages - * @return array of language and language file - */ - public static function getLangAndTranslationFile() - { - global $config; - $langs = []; - $lang = 'en'; - if (!empty($config['cops_language'])) { - $lang = $config['cops_language']; - } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - $langs = self::getAcceptLanguages(); - } - //echo var_dump($langs); - $lang_file = null; - foreach ($langs as $language => $val) { - $temp_file = dirname(__FILE__). '/lang/Localization_' . $language . '.json'; - if (file_exists($temp_file)) { - $lang = $language; - $lang_file = $temp_file; - break; - } - } - if (empty($lang_file)) { - $lang_file = dirname(__FILE__). '/lang/Localization_' . $lang . '.json'; - } - return [$lang, $lang_file]; - } - - /** - * This method is based on this page - * http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/ - */ - public static function localize($phrase, $count=-1, $reset=false) - { - global $config; - if ($count == 0) { - $phrase .= '.none'; - } - if ($count == 1) { - $phrase .= '.one'; - } - if ($count > 1) { - $phrase .= '.many'; - } - - /* Static keyword is used to ensure the file is loaded only once */ - static $translations = null; - if ($reset) { - $translations = null; - } - /* If no instance of $translations has occured load the language file */ - if (is_null($translations)) { - $lang_file_en = null; - [$lang, $lang_file] = self::getLangAndTranslationFile(); - if ($lang != 'en') { - $lang_file_en = dirname(__FILE__). '/lang/' . 'Localization_en.json'; - } - - $lang_file_content = file_get_contents($lang_file); - /* Load the language file as a JSON object and transform it into an associative array */ - $translations = json_decode($lang_file_content, true); - - /* Clean the array of all unfinished translations */ - foreach (array_keys($translations) as $key) { - if (preg_match('/^##TODO##/', $key)) { - unset($translations [$key]); - } - } - if (!is_null($lang_file_en)) { - $lang_file_content = file_get_contents($lang_file_en); - $translations_en = json_decode($lang_file_content, true); - $translations = array_merge($translations_en, $translations); - } - } - if (array_key_exists($phrase, $translations)) { - return $translations[$phrase]; - } - return $phrase; - } - - public static function useNormAndUp() - { - global $config; - return $config ['cops_normalized_search'] == '1'; - } - - public static function normalizeUtf8String($s) - { - return Transliteration::process($s); - } - - public static function normAndUp($s) - { - return mb_strtoupper(self::normalizeUtf8String($s), 'UTF-8'); - } -} diff --git a/lib/Language/Translation.php b/lib/Language/Translation.php index 71f266442..a7d2f12db 100644 --- a/lib/Language/Translation.php +++ b/lib/Language/Translation.php @@ -4,402 +4,15 @@ * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Sébastien Lucas + * @author mikespub */ -namespace SebLucas\Cops\Input; - -require 'config.php'; -/** @var array $config */ - -date_default_timezone_set($config['default_timezone']); - -/** - * Summary of Config - */ -class Config -{ - public const VERSION = '1.3.6'; - public const ENDPOINT = [ - "index" => "index.php", - "feed" => "feed.php", - "json" => "getJSON.php", - "fetch" => "fetch.php", - "read" => "epubreader.php", - "epubfs" => "epubfs.php", - "restapi" => "restapi.php", - "check" => "checkconfig.php", - "opds" => "opds.php", - ]; -} - -/** - * Summary of Request - */ -class Request -{ - /** - * Summary of urlParams - * @var array - */ - public $urlParams = []; - - public function __construct() - { - $this->init(); - } - - /** - * Summary of useServerSideRendering - * @return bool|int - */ - public function render() - { - global $config; - return preg_match('/' . $config['cops_server_side_render'] . '/', self::agent()); - } - - /** - * Summary of query - * @return mixed - */ - public function query() - { - if (isset($_SERVER['QUERY_STRING'])) { - return $_SERVER['QUERY_STRING']; - } - return ""; - } - - /** - * Summary of agent - * @return mixed - */ - public function agent() - { - if (isset($_SERVER['HTTP_USER_AGENT'])) { - return $_SERVER['HTTP_USER_AGENT']; - } - return ""; - } - - /** - * Summary of init - * @return void - */ - public function init() - { - $this->urlParams = []; - if (!empty($_GET)) { - foreach ($_GET as $name => $value) { - $this->urlParams[$name] = $_GET[$name]; - } - } - } - - /** - * Summary of get - * @param mixed $name - * @param mixed $default - * @return mixed - */ - public function get($name, $default = null) - { - if (!empty($this->urlParams) && isset($this->urlParams[$name]) && $this->urlParams[$name] != '') { - return $this->urlParams[$name]; - } - return $default; - } - - /** - * Summary of set - * @param mixed $name - * @param mixed $value - * @return void - */ - public function set($name, $value) - { - $this->urlParams[$name] = $value; - } - - /** - * Summary of option - * @param mixed $option - * @return mixed - */ - public function option($option) - { - global $config; - if (isset($_COOKIE[$option])) { - if (isset($config ['cops_' . $option]) && is_array($config ['cops_' . $option])) { - return explode(',', $_COOKIE[$option]); - } elseif (!preg_match('/[^A-Za-z0-9\-_.@]/', $_COOKIE[$option])) { - return $_COOKIE[$option]; - } - } - if (isset($config ['cops_' . $option])) { - return $config ['cops_' . $option]; - } - - return ''; - } - - /** - * Summary of style - * @return string - */ - public function style() - { - global $config; - $style = self::option('style'); - if (!preg_match('/[^A-Za-z0-9\-_]/', $style)) { - return 'templates/' . self::template() . '/styles/style-' . self::option('style') . '.css'; - } - return 'templates/' . $config['cops_template'] . '/styles/style-' . $config['cops_template'] . '.css'; - } - - /** - * Summary of template - * @return mixed - */ - public function template() - { - global $config; - $template = self::option('template'); - if (!preg_match('/[^A-Za-z0-9\-_]/', $template)) { - return $template; - } - return $config['cops_template']; - } - - /** - * Summary of verifyLogin - * @return bool - */ - public static function verifyLogin($serverVars = null) - { - global $config; - $serverVars ??= $_SERVER; - if (isset($config['cops_basic_authentication']) && - is_array($config['cops_basic_authentication'])) { - if (!isset($serverVars['PHP_AUTH_USER']) || - (isset($serverVars['PHP_AUTH_USER']) && - ($serverVars['PHP_AUTH_USER'] != $config['cops_basic_authentication']['username'] || - $serverVars['PHP_AUTH_PW'] != $config['cops_basic_authentication']['password']))) { - return false; - } - } - return true; - } - - /** - * Summary of notFound - * @return void - */ - public static function notFound() - { - header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found'); - header('Status: 404 Not Found'); - - $_SERVER['REDIRECT_STATUS'] = 404; - } - - /** - * Summary of build - * @param array $params - * @param ?array $server - * @param ?array $cookie - * @param ?array $config - * @return Request - */ - public static function build($params, $server = null, $cookie = null, $config = null) - { - // ['db' => $db, 'page' => $pageId, 'id' => $id, 'query' => $query, 'n' => $n] - $request = new self(); - $request->urlParams = $params; - return $request; - } -} - -namespace SebLucas\Cops\Output; - -use SebLucas\Cops\Input\Config; -use SebLucas\Template\doT; -use DOMDocument; - -class Format -{ - /** - * This method is a direct copy-paste from - * http://tmont.com/blargh/2010/1/string-format-in-php - */ - public static function str_format($format) - { - $args = func_get_args(); - $format = array_shift($args); - - preg_match_all('/(?=\{)\{(\d+)\}(?!\})/', $format, $matches, PREG_OFFSET_CAPTURE); - $offset = 0; - foreach ($matches[1] as $data) { - $i = $data[0]; - $format = substr_replace($format, @$args[(int)$i], $offset + $data[1] - 1, 2 + strlen($i)); - $offset += strlen(@$args[(int)$i]) - 2 - strlen($i); - } - - return $format; - } - - public static function addURLParam($urlParams, $paramName, $paramValue) - { - if (empty($urlParams)) { - $urlParams = ''; - } - $start = ''; - if (preg_match('#^\?(.*)#', $urlParams, $matches)) { - $start = '?'; - $urlParams = $matches[1]; - } - $params = []; - parse_str($urlParams, $params); - if (empty($paramValue) && strval($paramValue) !== "0") { - unset($params[$paramName]); - } else { - $params[$paramName] = $paramValue; - } - return $start . http_build_query($params); - } - - public static function addDatabaseParam($urlParams, $database) - { - if (!is_null($database)) { - $urlParams = self::addURLParam($urlParams, 'db', $database); - } - return $urlParams; - } - - public static function addVersion($url) - { - if (str_contains($url, '?')) { - $url .= '&v=' . Config::VERSION; - } else { - $url .= '?v=' . Config::VERSION; - } - return $url; - } - - public static function serverSideRender($data, $theme = 'default') - { - // Get the templates - $header = file_get_contents('templates/' . $theme . '/header.html'); - $footer = file_get_contents('templates/' . $theme . '/footer.html'); - $main = file_get_contents('templates/' . $theme . '/main.html'); - $bookdetail = file_get_contents('templates/' . $theme . '/bookdetail.html'); - $page = file_get_contents('templates/' . $theme . '/page.html'); - - // Generate the function for the template - $template = new doT(); - $dot = $template->template($page, ['bookdetail' => $bookdetail, - 'header' => $header, - 'footer' => $footer, - 'main' => $main]); - // If there is a syntax error in the function created - // $dot will be equal to FALSE - if (!$dot) { - return false; - } - // Execute the template - if (!empty($data)) { - return $dot($data); - } - - return null; - } - - public static function xml2xhtml($xml) - { - return preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', function ($m) { - $xhtml_tags = ['br', 'hr', 'input', 'frame', 'img', 'area', 'link', 'col', 'base', 'basefont', 'param']; - if (in_array($m[1], $xhtml_tags)) { - return '<' . $m[1] . $m[2] . ' />'; - } else { - return '<' . $m[1] . $m[2] . '>'; - } - }, $xml); - } - - public static function display_xml_error($error) - { - $return = ''; - $return .= str_repeat('-', $error->column) . "^\n"; - - switch ($error->level) { - case LIBXML_ERR_WARNING: - $return .= 'Warning ' . $error->code . ': '; - break; - case LIBXML_ERR_ERROR: - $return .= 'Error ' . $error->code . ': '; - break; - case LIBXML_ERR_FATAL: - $return .= 'Fatal Error ' . $error->code . ': '; - break; - } - - $return .= trim($error->message) . - "\n Line: " . $error->line . - "\n Column: " . $error->column; - - if ($error->file) { - $return .= "\n File: " . $error->file; - } - - return "$return\n\n--------------------------------------------\n\n"; - } - - public static function are_libxml_errors_ok() - { - $errors = libxml_get_errors(); - - foreach ($errors as $error) { - if ($error->code == 801) { - return false; - } - } - return true; - } - - public static function html2xhtml($html) - { - $doc = new DOMDocument(); - libxml_use_internal_errors(true); - - $doc->loadHTML('' . - $html . ''); // Load the HTML - $output = $doc->saveXML($doc->documentElement); // Transform to an Ansi xml stream - $output = self::xml2xhtml($output); - if (preg_match('#(.*)#ms', $output, $matches)) { - $output = $matches [1]; // Remove - } - /* - // In case of error with summary, use it to debug - $errors = libxml_get_errors(); - - foreach ($errors as $error) { - $output .= self::display_xml_error($error); - } - */ - - if (!self::are_libxml_errors_ok()) { - $output = 'HTML code not valid.'; - } - - libxml_use_internal_errors(false); - return $output; - } -} - namespace SebLucas\Cops\Language; class Translation { + public const BASE_DIR = './lang'; + /** * Get all accepted languages from the browser and put them in a sorted array * languages id are normalized : fr-fr -> fr_FR @@ -464,7 +77,7 @@ public static function getLangAndTranslationFile() //echo var_dump($langs); $lang_file = null; foreach ($langs as $language => $val) { - $temp_file = dirname(__FILE__). '/lang/Localization_' . $language . '.json'; + $temp_file = self::BASE_DIR . '/Localization_' . $language . '.json'; if (file_exists($temp_file)) { $lang = $language; $lang_file = $temp_file; @@ -472,7 +85,7 @@ public static function getLangAndTranslationFile() } } if (empty($lang_file)) { - $lang_file = dirname(__FILE__). '/lang/Localization_' . $lang . '.json'; + $lang_file = self::BASE_DIR . '/Localization_' . $lang . '.json'; } return [$lang, $lang_file]; } @@ -504,7 +117,7 @@ public static function localize($phrase, $count=-1, $reset=false) $lang_file_en = null; [$lang, $lang_file] = self::getLangAndTranslationFile(); if ($lang != 'en') { - $lang_file_en = dirname(__FILE__). '/lang/' . 'Localization_en.json'; + $lang_file_en = self::BASE_DIR . '/Localization_en.json'; } $lang_file_content = file_get_contents($lang_file); diff --git a/lib/Language/Transliteration.php b/lib/Language/Transliteration.php index c4ead13e3..b1865a95f 100644 --- a/lib/Language/Transliteration.php +++ b/lib/Language/Transliteration.php @@ -9,6 +9,8 @@ class Transliteration { + public const BASE_DIR = './resources/transliteration-data'; + /** * Transliterates UTF-8 encoded text to US-ASCII. * @@ -182,7 +184,7 @@ public static function replace($ord, $unknown = '?', $langcode = null) $bank = $ord >> 8; if (!isset($map[$bank][$langcode])) { - $file = './resources/transliteration-data/' . sprintf('x%02x', $bank) . '.php'; + $file = self::BASE_DIR . '/' . sprintf('x%02x', $bank) . '.php'; if (file_exists($file)) { $base = []; $variant = []; diff --git a/lib/Output/Format.php b/lib/Output/Format.php index 71f266442..f009a5214 100644 --- a/lib/Output/Format.php +++ b/lib/Output/Format.php @@ -4,222 +4,9 @@ * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Sébastien Lucas + * @author mikespub */ -namespace SebLucas\Cops\Input; - -require 'config.php'; -/** @var array $config */ - -date_default_timezone_set($config['default_timezone']); - -/** - * Summary of Config - */ -class Config -{ - public const VERSION = '1.3.6'; - public const ENDPOINT = [ - "index" => "index.php", - "feed" => "feed.php", - "json" => "getJSON.php", - "fetch" => "fetch.php", - "read" => "epubreader.php", - "epubfs" => "epubfs.php", - "restapi" => "restapi.php", - "check" => "checkconfig.php", - "opds" => "opds.php", - ]; -} - -/** - * Summary of Request - */ -class Request -{ - /** - * Summary of urlParams - * @var array - */ - public $urlParams = []; - - public function __construct() - { - $this->init(); - } - - /** - * Summary of useServerSideRendering - * @return bool|int - */ - public function render() - { - global $config; - return preg_match('/' . $config['cops_server_side_render'] . '/', self::agent()); - } - - /** - * Summary of query - * @return mixed - */ - public function query() - { - if (isset($_SERVER['QUERY_STRING'])) { - return $_SERVER['QUERY_STRING']; - } - return ""; - } - - /** - * Summary of agent - * @return mixed - */ - public function agent() - { - if (isset($_SERVER['HTTP_USER_AGENT'])) { - return $_SERVER['HTTP_USER_AGENT']; - } - return ""; - } - - /** - * Summary of init - * @return void - */ - public function init() - { - $this->urlParams = []; - if (!empty($_GET)) { - foreach ($_GET as $name => $value) { - $this->urlParams[$name] = $_GET[$name]; - } - } - } - - /** - * Summary of get - * @param mixed $name - * @param mixed $default - * @return mixed - */ - public function get($name, $default = null) - { - if (!empty($this->urlParams) && isset($this->urlParams[$name]) && $this->urlParams[$name] != '') { - return $this->urlParams[$name]; - } - return $default; - } - - /** - * Summary of set - * @param mixed $name - * @param mixed $value - * @return void - */ - public function set($name, $value) - { - $this->urlParams[$name] = $value; - } - - /** - * Summary of option - * @param mixed $option - * @return mixed - */ - public function option($option) - { - global $config; - if (isset($_COOKIE[$option])) { - if (isset($config ['cops_' . $option]) && is_array($config ['cops_' . $option])) { - return explode(',', $_COOKIE[$option]); - } elseif (!preg_match('/[^A-Za-z0-9\-_.@]/', $_COOKIE[$option])) { - return $_COOKIE[$option]; - } - } - if (isset($config ['cops_' . $option])) { - return $config ['cops_' . $option]; - } - - return ''; - } - - /** - * Summary of style - * @return string - */ - public function style() - { - global $config; - $style = self::option('style'); - if (!preg_match('/[^A-Za-z0-9\-_]/', $style)) { - return 'templates/' . self::template() . '/styles/style-' . self::option('style') . '.css'; - } - return 'templates/' . $config['cops_template'] . '/styles/style-' . $config['cops_template'] . '.css'; - } - - /** - * Summary of template - * @return mixed - */ - public function template() - { - global $config; - $template = self::option('template'); - if (!preg_match('/[^A-Za-z0-9\-_]/', $template)) { - return $template; - } - return $config['cops_template']; - } - - /** - * Summary of verifyLogin - * @return bool - */ - public static function verifyLogin($serverVars = null) - { - global $config; - $serverVars ??= $_SERVER; - if (isset($config['cops_basic_authentication']) && - is_array($config['cops_basic_authentication'])) { - if (!isset($serverVars['PHP_AUTH_USER']) || - (isset($serverVars['PHP_AUTH_USER']) && - ($serverVars['PHP_AUTH_USER'] != $config['cops_basic_authentication']['username'] || - $serverVars['PHP_AUTH_PW'] != $config['cops_basic_authentication']['password']))) { - return false; - } - } - return true; - } - - /** - * Summary of notFound - * @return void - */ - public static function notFound() - { - header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found'); - header('Status: 404 Not Found'); - - $_SERVER['REDIRECT_STATUS'] = 404; - } - - /** - * Summary of build - * @param array $params - * @param ?array $server - * @param ?array $cookie - * @param ?array $config - * @return Request - */ - public static function build($params, $server = null, $cookie = null, $config = null) - { - // ['db' => $db, 'page' => $pageId, 'id' => $id, 'query' => $query, 'n' => $n] - $request = new self(); - $request->urlParams = $params; - return $request; - } -} - namespace SebLucas\Cops\Output; use SebLucas\Cops\Input\Config; @@ -395,153 +182,3 @@ public static function html2xhtml($html) return $output; } } - -namespace SebLucas\Cops\Language; - -class Translation -{ - /** - * Get all accepted languages from the browser and put them in a sorted array - * languages id are normalized : fr-fr -> fr_FR - * @return array of languages - */ - public static function getAcceptLanguages() - { - $langs = []; - - if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - // break up string into pieces (languages and q factors) - $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE']; - if (preg_match('/^(\w{2})-\w{2}$/', $accept, $matches)) { - // Special fix for IE11 which send fr-FR and nothing else - $accept = $accept . ',' . $matches[1] . ';q=0.8'; - } - preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $accept, $lang_parse); - - if (count($lang_parse[1])) { - $langs = []; - foreach ($lang_parse[1] as $lang) { - // Format the language code (not standard among browsers) - if (strlen($lang) == 5) { - $lang = str_replace('-', '_', $lang); - $splitted = preg_split('/_/', $lang); - $lang = $splitted[0] . '_' . strtoupper($splitted[1]); - } - array_push($langs, $lang); - } - // create a list like "en" => 0.8 - $langs = array_combine($langs, $lang_parse[4]); - - // set default to 1 for any without q factor - foreach ($langs as $lang => $val) { - if ($val === '') { - $langs[$lang] = 1; - } - } - - // sort list based on value - arsort($langs, SORT_NUMERIC); - } - } - - return $langs; - } - - /** - * Find the best translation file possible based on the accepted languages - * @return array of language and language file - */ - public static function getLangAndTranslationFile() - { - global $config; - $langs = []; - $lang = 'en'; - if (!empty($config['cops_language'])) { - $lang = $config['cops_language']; - } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - $langs = self::getAcceptLanguages(); - } - //echo var_dump($langs); - $lang_file = null; - foreach ($langs as $language => $val) { - $temp_file = dirname(__FILE__). '/lang/Localization_' . $language . '.json'; - if (file_exists($temp_file)) { - $lang = $language; - $lang_file = $temp_file; - break; - } - } - if (empty($lang_file)) { - $lang_file = dirname(__FILE__). '/lang/Localization_' . $lang . '.json'; - } - return [$lang, $lang_file]; - } - - /** - * This method is based on this page - * http://www.mind-it.info/2010/02/22/a-simple-approach-to-localization-in-php/ - */ - public static function localize($phrase, $count=-1, $reset=false) - { - global $config; - if ($count == 0) { - $phrase .= '.none'; - } - if ($count == 1) { - $phrase .= '.one'; - } - if ($count > 1) { - $phrase .= '.many'; - } - - /* Static keyword is used to ensure the file is loaded only once */ - static $translations = null; - if ($reset) { - $translations = null; - } - /* If no instance of $translations has occured load the language file */ - if (is_null($translations)) { - $lang_file_en = null; - [$lang, $lang_file] = self::getLangAndTranslationFile(); - if ($lang != 'en') { - $lang_file_en = dirname(__FILE__). '/lang/' . 'Localization_en.json'; - } - - $lang_file_content = file_get_contents($lang_file); - /* Load the language file as a JSON object and transform it into an associative array */ - $translations = json_decode($lang_file_content, true); - - /* Clean the array of all unfinished translations */ - foreach (array_keys($translations) as $key) { - if (preg_match('/^##TODO##/', $key)) { - unset($translations [$key]); - } - } - if (!is_null($lang_file_en)) { - $lang_file_content = file_get_contents($lang_file_en); - $translations_en = json_decode($lang_file_content, true); - $translations = array_merge($translations_en, $translations); - } - } - if (array_key_exists($phrase, $translations)) { - return $translations[$phrase]; - } - return $phrase; - } - - public static function useNormAndUp() - { - global $config; - return $config ['cops_normalized_search'] == '1'; - } - - public static function normalizeUtf8String($s) - { - return Transliteration::process($s); - } - - public static function normAndUp($s) - { - return mb_strtoupper(self::normalizeUtf8String($s), 'UTF-8'); - } -}