NULL, 'success' => NULL, 'notice' => NULL]; /** * Returns the current login status * * The login status is stored in the session cookie. If it is not even set it means the login is invalid. * * @return The login status or false if none is set so far */ static public function isLoginValid(){ return ($_SESSION['login'] ?? false); } /** * A little Box with the login status as html entity * * @return string htmlEntity showing the login status */ static public function htmlLoginStatus(){ return "
". "Datum: ".date("Y-m-d")."
". "Angemeldet als ".htmlspecialchars($_SESSION['user']['username']).".
". "Sitzung beenden". "
"; } /** * Checks, if there already is a valid login, if not redirect to the login form * * @retval void */ static public function authentificate(){ session_start(); if ( !self::isLoginValid() ) { header("Location: login?returnToUrl=".urlencode($_SERVER['REQUEST_URI'].($_POST['fragment'] ?? "")), TRUE, 301); exit(); // should'nt matter } } static public function getMessages(){return self::$message;} static public function addMessage($type, $message){self::$message[$type] = (self::$message[$type] ?? "").$message;} /** * check password for user * * @param string $loginName user who wants to get in * @param string $password passwor for the user * * @retval true $password belongs to $loginName * @retval false otherwise */ static public function checkCredentials($loginName, $password){ sleep(1); // just to discurrage brute force attacks // Check for dbConnection if(!dbConnector::getDbConnection()){ self::addMessage('error', "
No DbConnection available
"); return false; } // query all users with the entered name $user = dbConnector::query( "SELECT `id`, `loginName`, `pwHash`, `config` FROM `wkParticipo_Users` WHERE `loginName` = :loginName", ['loginName' => ['value'=>$loginName, 'data_type'=>PDO::PARAM_STR]] ); // If there is no such user OR the password isn't valid the login fails if( empty($user || !password_verify( $password, $user['pwHash']) )){ sleep(5); // discourage brute force attacks self::addMessage('error', "
Falsches Passwort oder LoginName
"); return false; } session_start(); // case valid login: Set the session data $_SESSION = array( 'login' => true, 'user' => array( 'username' => $row['loginName'], 'userId' => $row['id'], 'userConfig' => json_decode($row['config'], true) ) ); // Logging Logins logLoginsToJsonFile($_SESSION['user']['username']); self::addMessage('success', "
Anmeldung erfolgreich
"); return true; } } /** * Action element of an MaterializeCss (App-)card */ class AppCardAction{ private $caption = null; //< Caption for the action private $link = "."; //< link for the action /** * Constructor for the AppAction * * @param string $caption caption for the action * @param string $link link to the action */ function __construct( $caption, $link = "." ){ //! @todo input sanitation $this->link = $link; $this->caption = $caption; } /** * Create htmlCode for the action * * @return string with htmlCode of the action */ function htmlCode(){ return "link."\">".$this->caption.""; } /** * Create AppCardAction from assoziative array * * @param array $member array with the member values * @return AppCardAction */ static public function fromArray($member){ $caption = $member['caption'] ?? null; $link = $member['link'] ?? "."; return new AppCardAction($caption, $link); } } /** * MaterializeCss card for an App */ class AppCard{ private $title = ""; //< title of the card private $description = ""; //< description of the App private $link = null; //< link for the card-content private $imgUrl = null; //< url for an image right under the title private $actionList = []; //< list of actions for the bottom of the card /** * Constructor for the AppCard * * @param string $title title of the card * @param string $description description of the card * @param string $link link for the card-content * @param string $imgUrl url for an image right under the title * @param array $actionList list of actions at the bottom of the card */ function __construct($title, $description, $link=null, $imgUrl=null, $actionList=[]){ //! @todo input sanitation $this->title = $title; $this->description = $description; $this->link = $link; $this->imgUrl = $imgUrl; $this->actionList = $actionList; } /** * Create htmlCode for the AppCard * * @return string html code for the AppCard */ public function htmlCode($options=[]){ $extraClass = $options['extraClass'] ?? ""; $actionListCode = ""; foreach($this->actionList as $a){ $actionListCode .= $a->htmlCode(); } return "
". "
". (($this->link!=null)?("link."\">"):(""))."
". "".$this->title."". (($this->imgUrl!=null)?("\"".$this-title."\" style=\"display:block;margin-left:auto;margin-right:auto;max-height:10vh;\" class=\"responsive-img\" src=\"".$this->imgUrl."\" />"):("")). "

".$this->description."

". "
".(($this->link!=null)?("
"):("")). "
".$actionListCode."
". "
". "
"; } /** * Create AppCard from an associative array * * @param array $member array with member as keys and values as the member values * @return AppCard from array values */ static public function fromArray($member){ $title = $member['title'] ?? ""; $description = $member['description'] ?? ""; $link = $member['link'] ?? null; $imgUrl = $member['imgUrl'] ?? null; $actionList = $member['actions'] ?? []; return new AppCard($title, $description, $link, $imgUrl, $actionList); } } /** * Generate a html table of the last logins of the users * * @param string $jsonFileName path to the json file with the logged logins * @return string Html table of users last logins */ function lastLoginTable($jsonFileName="lastLogins.json"){ $lastLogins=json_decode( file_get_contents($jsonFileName), true); $lastLoginsTable = "". "". ""; foreach( $lastLogins as $userName => $lastLogins ){ $lastLoginsTable .= ""; } $lastLoginsTable .= "
userNamelastLogins
".$userName."".$lastLogins['lastLogins'][0]."
"; return $lastLoginsTable; } /// Eine Fehler/Warnung/Notiz/Erfolgsmeldung als divBox im String zurückgeben function htmlRetMessage($anRetMessage){ $retHtmlString = ""; if( !empty($anRetMessage) ){ $retHtmlString .= "
"; if( !empty($anRetMessage['error']) ){ $retHtmlString .= "
"; $retHtmlString .= "ERROR:
"; $retHtmlString .= $anRetMessage['error']; $retHtmlString .= "
"; } if( !empty($anRetMessage['warning']) ){ $retHtmlString .= "
"; $retHtmlString .= "WARNING:
"; $retHtmlString .= $anRetMessage['warning']; $retHtmlString .= "
"; } if( !empty($anRetMessage['notice']) ){ $retHtmlString .= "
"; $retHtmlString .= "Info:
"; $retHtmlString .= $anRetMessage['notice']; $retHtmlString .= "
"; } if( !empty($anRetMessage['success']) ){ $retHtmlString .= "
"; $retHtmlString .= "SUCCESS:
"; $retHtmlString .= $anRetMessage['success']; $retHtmlString .= "
"; } $retHtmlString .= "
"; } return $retHtmlString; } /** * load a MarkdownFile with yaml header * * @param string $fileName filename of the markdown file * @return array assocative array('yaml'=>array(..), 'mdText'=>string) containing the yamlHeader as associative array and the markdown text as string */ function loadMarkdownFile($fileName){ // load the whole file $fileText = file_get_contents($fileName); // split at '---' to get ((),yamls,array) $fileParts = preg_split('/[\n]*[-]{3}[\n]/', $fileText, 3); // not all mdfiles have a yamlHeader, so the mdText can be at different indices $yaml=[]; $mdText = ""; switch( count($fileParts) ){ case 1:{ $mdText = $fileParts[0]; break; } case 3:{ $yaml = Spyc::YAMLLoadString($fileParts[1]); $mdText = $fileParts[2]; break; } default:{ $mdText = $fileText; } } // get a title, if none is in the markdown if(!array_key_exists('title', $yaml)){ // find the first heading, set it as header and remove it from the markdown if( preg_match("/^#(.*)$/m", $mdText, $matches) ){ $yaml['title'] = $matches[1]; $mdText = preg_replace("/^#(.*)$/m", "", $mdText, 1); } else{ // fallback for the title, if not even one heading is found $yaml['title'] = ""; } } return array( 'yaml' => $yaml , 'mdText' => $mdText ); } /** * Log the Login of an user into a logFile * * @param string $userName name of the user * @param string $fileName filename to log to * @return void */ function logLoginsToJsonFile($userName, $fileName="lastLogins.json"){ try{ $lastLogins = json_decode(file_get_contents($fileName), true); if(!array_key_exists($userName, $lastLogins)) $lastLogins[$userName] = []; if(!array_key_exists('lastLogins', $lastLogins[$userName])) $lastLogins[$userName]['lastLogins'] = []; $lastLogins[$userName]['lastLogins'] = array_merge( array( date('Y-m-d H:i:s') ), $lastLogins[$userName]['lastLogins'] ); file_put_contents($fileName, json_encode($lastLogins)); } catch (Exception $e){ // silently ignore errors } } class dbConnector{ static private $db = null; // connect to the database public static function connect($hostname, $dbName, $user, $password){ return self::setDbConnection( self::connectToPdo($hostname, $dbName, $user, $password) ); } public static function getDbConnection(){return self::$db;} /// perform a pdo-query /// /// @param $aQueryString /// @param $aBindArray e.g. array( /// ':userId' => array('value'=>$anUserId, 'data_type'=>PDO::PARAM_INT), /// ':attributeId'=> array('value'=>$anAttributeId, 'data_type'=>PDO::PARAM_INT) ) /// @param $someOption function query($aQueryString, $aBindArray = array(), $someOptions = array()){ // Standardbelegungen if( empty($someOptions['dbCharset' ]) ) $someOptions['dbCharset' ] = "ISO-8859-1"; if( empty($someOptions['outCharset']) ) $someOptions['outCharset'] = "UTF-8"; if( empty($someOptions['dontFetch' ]) ) $someOptions['dontFetch' ] = false; /// @toDo: Bisher wird nur die Rückgabe konvertiert. Eigentlich muss /// doch auch die Eingabe konvertiert werden. Aber das jetzt /// umzustellen wird schwer! Die User im Wettkampfplaner sind ja z.B. /// als UTF8 in latin1(?) gespeichert. /// @toDo: Die Standardwerte sollten vielleicht aus einer config /// kommen, nicht hardcoded try{ $pdoStatement = self::$db->prepare( $aQueryString ); foreach( $aBindArray as $bindName => $bind ){ if( $bind['data_type'] == PDO::PARAM_STR) $bind['value'] = iconv( $someOptions['outCharset'], $someOptions['dbCharset'], $bind['value'] ); $pdoStatement->bindValue( $bindName, $bind['value'], (isset($bind['data_type'])?$bind['data_type']:PDO::PARAM_STR) ); } $pdoResult = $pdoStatement->execute(); if(!$pdoResult){ echo("Error during dbQuery!\n"); echo("DB-Error:\n"); var_dump(self::$db->errorInfo()); } if($someOptions['dontFetch']){ $ret = NULL; } else{ $ret = $pdoStatement->fetchAll(PDO::FETCH_ASSOC); } } catch(PDOException $db_error){ print "Error!: " . $db_error->getMessage() . "
"; return null; } // Zeichensatzkonvertierung if( is_array($ret) ){ foreach($ret as &$entry){ array_walk( $entry, function (&$value, $key, $someOptions) { $value = iconv($someOptions['dbCharset'], $someOptions['outCharset'], $value); }, $someOptions ); } } return $ret; } // get a Connection to the database static private function connectToPdo($hostname, $dbName, $user, $password){ $dbConnection=null; try{ $dbConnection = new PDO( 'mysql:host='.$hostname.';dbname='.$dbName, $user, $password ); } catch(PDOException $dbError){ echo( "Error whilst getting a dbConnection!: " . $dbError->getMessage() ); } return $dbConnection; } // set the dbConnection (just setting, no establishing) private static function setDbConnection($dbConnection){ $success = false; if($dbConnection instanceof PDO){ self::$db = $dbConnection; $success = true; } else{ self::$db = null; } } } ?>