diff --git a/Router.php b/Router.php index 332c36e..6fff50a 100644 --- a/Router.php +++ b/Router.php @@ -16,11 +16,14 @@ require_once 'vendor/autoload.php'; // Application and Models autoload spl_autoload_register(function ($class_name) { - if(file_exists(__DIR__."/application/".$class_name.'.php')){ - include __DIR__."/application/".$class_name.'.php'; + if (file_exists(__DIR__ . "/application/" . $class_name . '.php')) { + include __DIR__ . "/application/" . $class_name . '.php'; +// echo "Load class " . __DIR__ . "/application/" . $class_name . '.php' . "
\n"; } - elseif(file_exists(__DIR__."/models/".$class_name.'.php')) { - include __DIR__."/models/".$class_name.'.php'; + elseif(file_exists(__DIR__ . "/models/" . $class_name . ".php")) { + include_once __DIR__."/models/Model.php"; + include_once __DIR__ . "/models/" . $class_name . ".php"; +// echo "Load class ".__DIR__."/models/".$class_name.'.php'."
\n"; } }); @@ -31,6 +34,12 @@ $twigSettings = PRODUCTION?['cache' => __dir__.'/tmp/']:[]; $loader = new Twig\Loader\FilesystemLoader(__dir__ . '/templates/'.Config::get('system', 'template', 'default')."/"); $twig = new Twig\Environment($loader, $twigSettings); +$filter = new Twig\TwigFilter('t', function ($string) { + return _(strip_tags($string)); +}); + +$twig->addFilter($filter); + class Config { private static $instance = null; @@ -53,4 +62,16 @@ class Config { } return $default; } +} + +function model($name){ + return; + if(file_exists(__DIR__ . "/models/" . $name . ".php")){ + include_once __DIR__ . "/models/Model.php"; + include_once __DIR__ . "/models/" . $name . ".php"; + } + else { + echo "FAULT
\n"; + echo __DIR__ . "/models/" . $name . ".php". " doesn't exist"; + } } \ No newline at end of file diff --git a/application/Auth.php b/application/Auth.php index 72b2f36..115ba58 100644 --- a/application/Auth.php +++ b/application/Auth.php @@ -17,10 +17,21 @@ class Auth { } public static function loginWithCredentials($email, $pass, bool $stayLoggedIn = false){ - $Auth = new Auth(); + session_destroy(); + self::$instance = null; + $Auth = Auth::getInstance(); $err = []; + if(strlen($email) < 3){ + $err[] = __("Please enter a valid email."); + } + if(strlen($pass) < 3){ + $err[] = __("Please enter a valid password. Hint: The passwords need to have at least 6 characters."); + } + + if(!empty($err)){ return $err; } + // get user from database $getUserSQL = "SELECT pwd, user_id, user_email FROM user WHERE user_email = ? LIMIT 1;"; $getUserRes = DB::query($getUserSQL, $email); @@ -41,14 +52,16 @@ class Auth { $userKey = GenKey(); $shaUserKey = sha1($userKey); $expire = $stayLoggedIn?30:0; // if "stay logged in", stay logged in for 30 days. + $ctime = time(); $updateUserSQL = "INSERT INTO user_login (user_id, ckey, ctime, expire, agent) VALUES (?, ?, ?, ?, ?);"; try { - DB::query($updateUserSQL, $dbUserId, $userKey, time(), $expire, $md5agent); + DB::query($updateUserSQL, $dbUserId, $userKey, $ctime, $expire, $md5agent); $_SESSION['user_id'] = $dbUserId; $_SESSION['user_name'] = $dbUserName; $_SESSION['user_agent'] = $md5agent; $_SESSION['user_key'] = $shaUserKey; + $_SESSION['user_ctime'] = $ctime; if($stayLoggedIn){ setcookie("auth", $shaUserKey.".".$dbUserId, time() + (30 * 24*60*60), "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true ); @@ -56,11 +69,11 @@ class Auth { return true; } catch(DatabaseException $e){ - $err[] = "Failed to login.\n".$e; + $err[] = __("Failed to login.")."\n".$e; } } else { - $err[] = "Username and/or Password is wrong."; + $err[] = __("The provided combination of username and password is not recognized in the system. Verify your details or create an account."); } return $err; @@ -102,8 +115,76 @@ class Auth { return false; } - public static function logout(){} + public static function logout($everywhere = false){ + if(Auth::checkLogin()){ + $logoutSql = "DELETE FROM user_login WHERE user_id = ?"; + $sqlparams[] = $_SESSION['user_id']; + if(!$everywhere){ +// $logoutSql .= " AND agent = ?"; +// $sqlparams[] = md5($_SERVER['HTTP_USER_AGENT']); + $logoutSql .= " AND ctime = ?"; + $sqlparams[] = $_SESSION['user_ctime']; + } + DB::query($logoutSql, $sqlparams); + } + + // Delete session-cookie + $params = session_get_cookie_params(); + setcookie(session_name(), '', time() - 42000, + $params["path"], $params["domain"], + $params["secure"], $params["httponly"] + ); + + setcookie('auth', '', time() - 42000, "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true ); + + // Finally, destroy the session. + session_destroy(); + } + + + public static function register($userEmail, $userPass, $metadata = []){ + $err = []; + + $userName = $metadata['newName'] ?? ''; + + if(strlen($userPass) < 6){ + $err[] = __("Password is too short. Password needs to be at least 6 characters!"); + } + else if(strlen($userPass) > 30){ + $err[] = __("Password is too long. Max length is set to 30 characters. If you believe it should be higher please contact the developers."); + } + + if(strlen($userEmail) > 220){ + $err[] = __("Your email-address is too long. Can you please register with another email?"); + } + + if(strlen($userName) > 200){ + $err[] = __("Your name seems to be too long to fit this system. Maybe you can short it down somehow?"); + } + + if(empty($err)){ + // HASH PASSWORD + $newPass = PwdGen($userPass, true); + + $createUserSQL = "INSERT INTO user SET user_email = ?, pwd = ?, full_name = ?;"; + try { + DB::query($createUserSQL, $userEmail, $newPass, $userName); + $newID = DB::insert_id(); + + if(empty($newID)){ return false; } + + $updateUserSQL = "UPDATE user SET md5_id = ? WHERE user_id = ?;"; + DB::query($updateUserSQL, md5($newID), $newID); + + return true; + } catch (DatabaseException $e) { + $err[] = __("Something went wrong").":
" . $e; + } + } + + return $err; + } public static function checkLogin($strict = false): bool { $Auth = Auth::getInstance(); diff --git a/application/DB.php b/application/DB.php index 234cbd1..867aef5 100644 --- a/application/DB.php +++ b/application/DB.php @@ -4,16 +4,24 @@ class DB { private static $instance = null; private $db; + /** + * @throws DatabaseException + */ private function __construct(){ - $this->db = new mysqli( - Config::get('database', 'host'), - Config::get('database', "user"), - Config::get('database', "pass"), - Config::get('database', "database") - ); + try { + $this->db = new mysqli( + Config::get('database', 'host'), + Config::get('database', "user"), + Config::get('database', "pass"), + Config::get('database', "database") + ); - if($this->db->connect_error){ - die("Connection failed: " . $this->db->connect_error); + if($this->db->connect_error){ + throw new DatabaseException("Database connection failed: ". $this->db->connect_error); + } + } + catch (mysqli_sql_exception $e){ + throw new DatabaseException($e->getMessage(), $e->getCode()); } } @@ -52,16 +60,12 @@ class DB { } /** + * @param integer $mode 0: Execute normally - 1: Execute, but print query - 2: Only print query + * @param string $sql Input SQL as string + * @param mixed ...$params A list or an array of values for the query * @throws DatabaseException */ - private static function doQuery($mode, $sql, ...$params){ - /* - Modes: - 0: Execute normally - 1: Execute, but print query - 2: Only print query - */ - + private static function doQuery(int $mode, string $sql, ...$params){ // Check if query parameters comes as an array, or as individual arguments if(count($params) == 1 && is_array($params[0])){ $params = $params[0]; @@ -69,7 +73,7 @@ class DB { // Create type-specification for query $types = ""; - foreach($params as &$value){ + foreach($params as $value){ if(is_double($value)){ $types .= "d"; } @@ -90,17 +94,44 @@ class DB { return []; } - $stmt = $db->db->prepare($sql); - if( - $stmt === false || - $stmt->bind_param($types, ...$params) === false || - $stmt->execute() === false - ){ - throw new DatabaseException($db->db->error); + try { + $stmt = $db->db->prepare($sql); + if( + $stmt === false || + (!empty($params) && $stmt->bind_param($types, ...$params) === false) || + $stmt->execute() === false + ){ + throw new DatabaseException($db->db->error); + } + } + catch (mysqli_sql_exception $e){ + throw new DatabaseException($e->getMessage(), $e->getCode()); } return $stmt->get_result(); } + + /** + * @throws DatabaseException + */ + public static function multiQuery(...$sql){ + $db = DB::getInstance(); + + foreach ($sql as $s){ + try { + $db->db->multi_query($s); + } + catch (mysqli_sql_exception $e){ + throw new DatabaseException($e->getMessage(), $e->getCode()); + } + } + } + + public static function insert_id(){ + $db = DB::getInstance(); + + return $db->db->insert_id; + } } class DatabaseException extends Exception { diff --git a/application/Translator.php b/application/Translator.php new file mode 100644 index 0000000..4564b4a --- /dev/null +++ b/application/Translator.php @@ -0,0 +1,170 @@ +language = "nb"; + $this->country = "NO"; + $this->charset = "utf8"; + + $this->locale = $this->language."_".$this->country.".".$this->charset; + + if (defined('LC_MESSAGES')) { + setlocale(LC_MESSAGES, $this->locale); + bindtextdomain("domain1", __dir__."/../locale/"); + } else { + echo "IS IN THE ELSE - PART"; + } + + textdomain("domain1"); + } +} + +/* +use Gettext\Loader\PoLoader; + +class Translator { + private static $instance = null; + private $translations; + private $language; + private $country; + private $charset; + private $locale; + + private function __construct($lang = "nb", $contry = "NO", $charset = "utf8"){ + + $this->language = $lang; + $this->country = $contry; + $this->charset = $charset; + $this->locale = $this->language."_".$this->country.".".$this->charset; + + //import from a .po file: + $poloader = new PoLoader(); + $this->translations = $poloader->loadFile('locale/'.$this->language.'.po'); + } + + public static function getInstance(): Translator { + if(self::$instance == null){ + self::$instance = new Translator(); + } + + return self::$instance; + } + + static public function translate($string, $domain = "messages"): string { + $trans = self::getInstance(); + + return $trans->translations; + } + + static public function getBrowserSupportedLanguage(){ + $language = null; + $input = $_SERVER['HTTP_ACCEPT_LANGUAGE']; + + $supported_languages = ["en", "no"]; + + $browserLanguages = explode(",", str_replace(' ', '', strtolower($input))); + + foreach ($browserLanguages as $languageString){ + // Stop looking for languages if one is found + if(!empty($language)){ break; } + + // Check for language in format "en_US" + $stringParts = explode('-', $languageString); + + // If not in that format, check for "en;q=0.9" format + if(count($stringParts) <= 1){ + $stringParts = explode(';', $languageString); + } + + // If whichever format, check if the first key is a supported language + if(count($stringParts) > 1 && in_array($stringParts[0], $supported_languages)){ + $language = $stringParts[0]; + } + // If in neither format, check the whole string + elseif(in_array($languageString, $supported_languages)){ + $language = $languageString; + } + } + + // If no language found, set the first one in the supported-list + if(empty($language)){ + $language = $supported_languages[0]; + } + + return $language; + } +} +*/ + +use Gettext\Scanner\PhpScanner; +use Gettext\Translations; +use Gettext\Generator\PoGenerator; +use Gettext\Generator\MoGenerator; + + +class TranslatorScanning { + public $scanner; + + public function __construct($domain = "default"){ + + $phpScanner = new PhpScanner( + Translations::create($domain) + ); + + //Set a default domain, so any translations with no domain specified, will be added to that domain + $phpScanner->setDefaultDomain($domain); + + //Extract all comments starting with 'i18n:' and 'Translators:' + $phpScanner->extractCommentsStartingWith('i18n:', 'Translators:'); + + //Scan files + foreach (glob(__DIR__.'/../www/{*,*/*,*/*/*}.php', GLOB_BRACE) as $file) { +// echo $file."
\n"; + $phpScanner->scanFile($file); + } + + $this->scanner = $phpScanner; + } + + public function save(){ + //Save the translations in .po files + $generator = new PoGenerator(); + + foreach ($this->phpScanner->getTranslations() as $domain => $translations) { + echo "Generate file: ".__DIR__."/../www/{$domain}.po
\n"; + $generator->generateFile($translations, __DIR__."/../www/{$domain}.po"); + } + } + + + public static function compiler(){ + $loader = new PoLoader(); + + //From a file + $translations = $loader->loadFile(__DIR__."/../www/domain1.po"); + + $generator = new MoGenerator(); + $generator->generateFile($translations, __DIR__."/../www/domain1.mo"); + + + +// From a string +// $string = file_get_contents('locales2/en.po'); +// $translations = $loader->loadString($string); + } +} + +// Resources: https://packagist.org/packages/gettext/gettext +// Resources: https://www.sitepoint.com/easy-multi-language-twig-apps-with-gettext/ + + +function __($string, ...$values): string { + if(DEBUG){ + logTranslationKey($string); + } + return sprintf( _($string), $values); +} + +function logTranslationKey($string){ + file_put_contents("translationkeys.txt", file_get_contents("translationkeys.txt") . "\n" . $string); +} \ No newline at end of file diff --git a/application/Utils.php b/application/Utils.php index f2ebe84..9349599 100644 --- a/application/Utils.php +++ b/application/Utils.php @@ -18,5 +18,16 @@ class Utils { } } - + public static function debug(...$args){ + foreach($args as $arg){ + echo "
";
+            if(is_bool($arg)){
+                var_dump($arg);
+            }
+            else {
+                echo print_r($arg, true);
+            }
+            echo "
\n"; + } + } } \ No newline at end of file diff --git a/application/WebPage.php b/application/WebPage.php index e74163e..e87da69 100644 --- a/application/WebPage.php +++ b/application/WebPage.php @@ -17,6 +17,8 @@ class WebPage { public function __construct(){ + new Translator(); + $this->pr = Config::get('system', 'projectroot', ''); $this->loggedIn = Auth::checkLogin(); @@ -28,6 +30,11 @@ class WebPage { } try { + if(isset($_POST) && !empty($_POST)){ + $this->sanitizePost(); + $this->doPost(); + } + $this->prepareNavbar(); $this->load(); @@ -35,7 +42,7 @@ class WebPage { $this->template = str_replace('.php', '.html', $_SERVER['SCRIPT_NAME']); } - if($this->httpStatus == 200){ + if($this->httpStatus == 200 || $this instanceof ErrorPage){ global $twig; if(DEBUG){ @@ -43,7 +50,7 @@ class WebPage { header("X-Script-name: ".$_SERVER['SCRIPT_NAME']); } - http_response_code(200); + http_response_code($this->httpStatus); echo $twig->render($this->template, $this->vars()); } @@ -55,7 +62,9 @@ class WebPage { catch (\Twig\Error\LoaderError $e){ http_response_code(500); if( $e->getCode() == 0){ + echo "
";
                 print_r($e->getMessage());
+                echo "
"; } else { echo $e; @@ -63,12 +72,21 @@ class WebPage { } catch(\Twig\Error\RuntimeError | \Twig\Error\SyntaxError | Exception $e) { http_response_code(500); - echo $e; - print_r( $this->vars() ); + + if(!$this instanceof ErrorPage){ + $e = new ErrorPage(500, $e, print_r( $this->vars(), true )); + } + else { + echo "

A critical error occurred!

"; + echo "
".$e."
"; + } + } } - function load(){ throw new Exception("Incomplete implementation"); } + function load(){ throw new Exception("Incomplete implementation"); } + + function doPost(){ throw new Exception("Incomplete implementation"); } function vars(): array { return (array) $this; @@ -83,6 +101,20 @@ class WebPage { ["href"=>"/review/", "name"=>"Review", "active"=>$this->activePage=="/review/"?'active':''] ], $this->navbar ?? []); } + + protected function sanitizePost(){ + $data = []; + + foreach($_POST as $key => $value){ + if(($data[$key] = Utils::filter($value)) === false){ + $err[] = __("Failed to sanitize: `%s`: %s \t-\t type: %s\n", $key, $value, gettype($value)); + } + } + + if(!empty($err)){ return $err; } + $this->data = $data; + return true; + } } class WebPageAuth extends WebPage { @@ -91,4 +123,38 @@ class WebPageAuth extends WebPage { parent::__construct(); } } +} + +class ErrorPage extends WebPage { + + public $errCode = 500; + public $errormessage = "An unexpected error occurred"; + public $errorDescription = ""; + public $template = "errors/500.html"; + + public function load(){ + if($this->errCode != 500){ + $this->template = "errors/$this->errCode.html"; + } + } + + public function __construct($errCode = 500, $e = "", $extra = ""){ + $this->errCode = $errCode; + if($e instanceof Exception){ + $this->errormessage = $e->getMessage(); + } + $this->errorDescription = $e; + $this->errorDescription .= "\n".$extra; + + parent::__construct(); + } +} + +function isExecutingPage($file) : bool { + $file1 = explode("/", $file); + $request = str_replace('/','', $_SERVER['REQUEST_URI']); + if(strstr($request, '?')){ + $request = explode('?', $request)[0]; + } + return $request == $file1[ array_key_last($file1) ]; } \ No newline at end of file diff --git a/composer.json b/composer.json index 4777dcc..5d6ce76 100644 --- a/composer.json +++ b/composer.json @@ -2,6 +2,9 @@ "require": { "twbs/bootstrap": "5.1.3", "twig/twig": "^3.3", - "ext-mysqli": "*" + "ext-mysqli": "*", + "gettext/gettext": "^5.6", + "ext-gettext": "*", + "gettext/php-scanner": "^1.3" } } diff --git a/composer.lock b/composer.lock index 215e281..ea81e02 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,271 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0daa3afffc94d70bd593d310cef916f8", + "content-hash": "6111dbb0fd97c255b22341c3bbfb4f67", "packages": [ + { + "name": "gettext/gettext", + "version": "v5.6.1", + "source": { + "type": "git", + "url": "https://github.com/php-gettext/Gettext.git", + "reference": "017e249601d32b9a88c2eb4c10eac89bf582a7d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/017e249601d32b9a88c2eb4c10eac89bf582a7d3", + "reference": "017e249601d32b9a88c2eb4c10eac89bf582a7d3", + "shasum": "" + }, + "require": { + "gettext/languages": "^2.3", + "php": "^7.2|^8.0" + }, + "require-dev": { + "brick/varexporter": "^0.3.5", + "friendsofphp/php-cs-fixer": "^3.2", + "oscarotero/php-cs-fixer-config": "^2.0", + "phpunit/phpunit": "^8.0|^9.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gettext\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "description": "PHP gettext manager", + "homepage": "https://github.com/php-gettext/Gettext", + "keywords": [ + "JS", + "gettext", + "i18n", + "mo", + "po", + "translation" + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/php-gettext/Gettext/issues", + "source": "https://github.com/php-gettext/Gettext/tree/v5.6.1" + }, + "funding": [ + { + "url": "https://paypal.me/oscarotero", + "type": "custom" + }, + { + "url": "https://github.com/oscarotero", + "type": "github" + }, + { + "url": "https://www.patreon.com/misteroom", + "type": "patreon" + } + ], + "time": "2021-12-04T11:33:21+00:00" + }, + { + "name": "gettext/languages", + "version": "2.9.0", + "source": { + "type": "git", + "url": "https://github.com/php-gettext/Languages.git", + "reference": "ed56dd2c7f4024cc953ed180d25f02f2640e3ffa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-gettext/Languages/zipball/ed56dd2c7f4024cc953ed180d25f02f2640e3ffa", + "reference": "ed56dd2c7f4024cc953ed180d25f02f2640e3ffa", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4" + }, + "bin": [ + "bin/export-plural-rules" + ], + "type": "library", + "autoload": { + "psr-4": { + "Gettext\\Languages\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michele Locati", + "email": "mlocati@gmail.com", + "role": "Developer" + } + ], + "description": "gettext languages with plural rules", + "homepage": "https://github.com/php-gettext/Languages", + "keywords": [ + "cldr", + "i18n", + "internationalization", + "l10n", + "language", + "languages", + "localization", + "php", + "plural", + "plural rules", + "plurals", + "translate", + "translations", + "unicode" + ], + "support": { + "issues": "https://github.com/php-gettext/Languages/issues", + "source": "https://github.com/php-gettext/Languages/tree/2.9.0" + }, + "funding": [ + { + "url": "https://paypal.me/mlocati", + "type": "custom" + }, + { + "url": "https://github.com/mlocati", + "type": "github" + } + ], + "time": "2021-11-11T17:30:39+00:00" + }, + { + "name": "gettext/php-scanner", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/php-gettext/PHP-Scanner.git", + "reference": "989a2cffa1d0f43d13b14c83a50429119b5eb8e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-gettext/PHP-Scanner/zipball/989a2cffa1d0f43d13b14c83a50429119b5eb8e4", + "reference": "989a2cffa1d0f43d13b14c83a50429119b5eb8e4", + "shasum": "" + }, + "require": { + "gettext/gettext": "^5.5.0", + "nikic/php-parser": "^4.2", + "php": ">=7.2" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.15", + "oscarotero/php-cs-fixer-config": "^1.0", + "phpunit/phpunit": "^8.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gettext\\Scanner\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "description": "PHP scanner for gettext", + "homepage": "https://github.com/php-gettext/PHP-Scanner", + "keywords": [ + "gettext", + "i18n", + "php", + "scanner", + "translation" + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/php-gettext/PHP-Scanner/issues", + "source": "https://github.com/php-gettext/PHP-Scanner/tree/v1.3.1" + }, + "time": "2022-03-18T11:47:55+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.13.2", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", + "reference": "210577fe3cf7badcc5814d99455df46564f3c077", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" + }, + "time": "2021-11-30T19:35:32+00:00" + }, { "name": "symfony/polyfill-ctype", "version": "v1.25.0", @@ -304,7 +567,10 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "ext-mysqli": "*", + "ext-gettext": "*" + }, "platform-dev": [], - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } diff --git a/scripts/cron.php b/scripts/cron.php new file mode 100644 index 0000000..9b91928 --- /dev/null +++ b/scripts/cron.php @@ -0,0 +1,7 @@ + @@ -71,10 +71,11 @@ {% endif %} {% block content %}{% endblock %} + +{% block endContent %}{% endblock %} + \ No newline at end of file diff --git a/templates/default/errors/500.html b/templates/default/errors/500.html new file mode 100644 index 0000000..12d6ce8 --- /dev/null +++ b/templates/default/errors/500.html @@ -0,0 +1,12 @@ +{% extends "assets/base.html.twig" %} + +{% block content %} +

Logo PaperBag

+
+ +

500 - An unexpected error occured

+

{{ errormessage }}

+
{{ errorDescription }}
+ +
+{% endblock %} \ No newline at end of file diff --git a/templates/default/login.html b/templates/default/login.html index c2a016e..91c310f 100644 --- a/templates/default/login.html +++ b/templates/default/login.html @@ -9,7 +9,7 @@
- +
@@ -19,7 +19,7 @@
- + diff --git a/templates/default/register.html b/templates/default/register.html new file mode 100644 index 0000000..6704df4 --- /dev/null +++ b/templates/default/register.html @@ -0,0 +1,36 @@ +{% extends "assets/base.html.twig" %} + +{% block content %} +
+ +

Register

+ +
+ +
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ +
+
+

Already have an account? Login

+
+{% endblock %} \ No newline at end of file diff --git a/www/login.php b/www/login.php index c493373..a105480 100644 --- a/www/login.php +++ b/www/login.php @@ -4,7 +4,7 @@ require_once '../Router.php'; class LoginPage extends WebPage { public $pagekey = "login"; - public $title = "PaperBag - Plan & Execute Your Shopping"; + public $title = "Login - PaperBag - Plan & Execute Your Shopping"; public $returnToPage = "/"; function load(){ @@ -17,13 +17,9 @@ class LoginPage extends WebPage { if(isset($_GET['thank'])){ $this->msg[] = "Thank you for registering. Please log in to continue!"; } - - if(isset($_POST) && !empty($_POST)){ - $this->doPost(); - } } - private function findReturnPage(){ + protected function findReturnPage(){ if(isset($_POST['referrerPage'])){ $this->returnToPage = $_POST['referrerPage']; } @@ -39,23 +35,22 @@ class LoginPage extends WebPage { } } - private function doPost(){ - $data = []; - - foreach($_POST as $key => $value){ - if(($data[$key] = Utils::filter($value)) === false){ - echo "Failed to sanitize: `".$key."`: ".$value." \t-\t type: ".gettype($value)."\n"; - } - } - + function doPost(){ $stayLoggedIn = isset($_POST['stayLoggedIn']); - $err = Auth::loginWithCredentials($data['loginEmail'], $data['loginPwd'], $stayLoggedIn); + $err = Auth::loginWithCredentials($this->data['loginEmail'], $this->data['loginPwd'], $stayLoggedIn); if($err === true){ header("Location: ".$this->returnToPage); die(); } + + // Do not send the password back to the client... + $this->data['loginPwd'] = null; + $this->err = $err; } } -$a = new LoginPage(); +// For use when class is extended upon +if(isExecutingPage(__file__)){ + $a = new LoginPage(); +} \ No newline at end of file diff --git a/www/logout.php b/www/logout.php index a43c6c4..83abc75 100644 --- a/www/logout.php +++ b/www/logout.php @@ -1,7 +1,6 @@ $value) { - if (($data[$key] = filter($value)) === false) { - print_r($value); - echo "Failed to sanitize: `" . $key . "`: " . $value . " \t-\t type: " . gettype($value) . "\n"; + function load(){ + $this->findReturnPage(); + + if(Auth::checkLogin(true)){ + header("Location: ".$this->returnToPage); } } - $userEmail = $data['newEmail']; - $userPass = $data['newPassword']; - $userName = $data['newName'] ?? ''; - - if(strlen($userPass) < 6){ - $err[] = "Password is too short. Password needs to be at least 6 characters!"; - } - else if(strlen($userPass) > 30){ - $err[] = "Password is too long. Max length is set to 30 characters. If you believe it should be higher please contact the developers."; - } - - if(strlen($userEmail) > 220){ - $err[] = "Your email-address is too long. Can you please register with another email?"; - } - - if(strlen($userName) > 200){ - $err[] = "Your name seems to be too large to fit this system. Maybe you can short it somehow?"; - } - - if(empty($err)){ - // HASH PASSWORD - $newPass = PwdGen($userPass, true); - - $createUserSQL = "INSERT INTO user SET full_name = '$userName', user_email = '$userEmail', pwd = '$newPass';"; - if($db->query($createUserSQL)){ - $newID = $db->insert_id; - $updateUserSQL = "UPDATE user SET md5_id = '".md5($newID)."' WHERE user_id = '$newID';"; - $db->query($updateUserSQL); - + function doPost(){ + $err = Auth::register($this->data['newEmail'], $this->data['newPassword'], $this->data); + if($err === true){ header("Location: login.php?thank"); + die(); } - else { - $err[] = "Something went wrong:
".$db->error; - } + $this->err = $err; + // Do not send the password back to the client... + $this->data['newPassword'] = null; } } -?> - - - - Register - PaperBag - - -
-
- - -
- -

Register

-
- - $e
"; - } - echo "
"; - } - ?> - -
- -
- - -
-
- - -
-
- - -
-
-
- - -
-
-
- -
-
-

Already have an account? Login

-
-
- -
- - \ No newline at end of file +$a = new RegisterPage();