commit 47912a847ceab0892fc0b2f3d30293c6c18d0f07 Author: bernd Date: Mon Mar 1 16:56:53 2021 +0100 initialer commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..4f882ee --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# matrix-register + +Das Programm befindet sich noch in der Entwicklung! Es gibt keine Garantie +für eine korrekte Funktion. + +matrix-register ist eine Webanwendung, welche die Möglichkeit der +Registrierung eines Accounts bei matrix.kraut.space anbietet. Der Nutzer +beantragt über ein Webformular die Registrierung, bekommt eine +Validierungsmail zugesand und nach Bestätigung der Mail den Account +aktiviert. Nach erfolgreicher Validierung wird ein temporäres Passwort +erzeugt und auf der Webseite angezeigt. Deshalb die Empfehlung https zu +benutzen. Auch wenn das Passwort als Hash gespeichert wird - bitte umgehend +per Client ändern. + +## Installation + + + +## Konfiguration + +Datenbank, Loglevel und einige Parameter der Mail werden in etc/register.ini +konfiguriert. Mit einigen Anpassungen dürfte es auch auf andere Host +übertragbar sein. Einige Erläuterungen zu den Parametern befinden sich in +der Konfigurationsdatei. + +## Abhängigkeiten + +matrix-register benötigt zum Arbeiten folgende Programme: + +* einen Webserver mit aktiviertem php-Support +* eine Datenbank (Postgres oder SQLite) +* matrix-synapse diff --git a/etc/register.ini.example b/etc/register.ini.example new file mode 100644 index 0000000..8f016c5 --- /dev/null +++ b/etc/register.ini.example @@ -0,0 +1,55 @@ +; file: register.ini.example +; desc: Konfigurationsdatei für das Programm matrix-register. Die Datei in +; register.ini umbennen und die Optionen anpassen. Das Programm sucht +; die Konfiguration im Verzeichnis ./etc + + +; Treiber für das php-Datenbankmodul PDO. Generell unterstütz das PDO Modul +; die folgenden Trieber: +; PDO_DBLIB (FreeTDS/Microsoft SQL Server/Sybase), +; PDO_FIREBIRD (Firebird/Interbase 6), +; PDO_IBM (IBM DB2), +; PDO_INFORMIX (IBM Informix Dynamic Server), +; PDO_MYSQL (MySQL 3.x/4.x/5.x), +; PDO_OCI (Oracle Call Interface), +; PDO_ODBC (ODBC v3 (IBM DB2, unixODBC, and win32 ODBC)), +; PDO_PGSQL (PostgreSQL), +; PDO_SQLITE (SQLite 3 and SQLite 2), +; PDO_4D (D). +; Die Verfügbarkeit hängt davon ab, ob das Modul den entsprechenden +; Treiber einkompiliert hat. Die verfügbaren Treiber lassen sich mit +; "print_r(PDO::getAvailableDrivers());" ausgeben. Je nach Datenbank +; sind unterschiedliche Optionen nötig. Der verwendete synapse-matrix Server +; unterstützt SQLite oder Postgres-Datenbanken. +driver=PDO_PGSQL + +; Pfad zur Datenbank, wenn diese eine Datei ist (z.B. SQLite). +file= + +; Parameter, um sich mit einem Datenbankserver zu verbinden +host=localhost +port=5432 +database=requests +user=besitzer der datenbank requests +password=total geheimes passwort + +; Loglevel festlegen. Derzeit sind error, warn, info und debug gültige +; Werte. Die Angabe ist nicht Case-Sesitive. +loglevel=debug + +; Logdatei festlegen. Der Benutzer, unter dem der Dienst läuft braucht +; Schreibrechte für das Verzeichnis. +logfile=pfad/zur/logdatei + +; Domainname des Matrixservers, bei der der Account registriert werden soll. +mxdomain="matrix.server.me" + +; Parameter für den Validierungslink. Beide Parameter müssen eine valide +; URL ergeben. Der Token wird vom Programm generiert. +baseurl="https://meine.domain/" +validator="register/validation.php?token=" + +; Parameter für die Validierungsmail +mailfrom="From: Matrix Registrierung " +mailsubject="Ihr Matrix Account bei meiner Domain" +mailclosure="Mfg" diff --git a/index.php b/index.php new file mode 100644 index 0000000..9cc7cae --- /dev/null +++ b/index.php @@ -0,0 +1,154 @@ +' . htmlspecialchars(var_export($_POST, true)) . ''; + $inputLogin = $_POST['login'] ?? ''; + $inputEmail = $_POST['email'] ?? ''; + $inputCaptcha = $_POST['captcha'] ?? ''; + if ($inputCaptcha && $inputLogin && $inputEmail) { + $request = new Request(); + $saved = $request->checkRequest($message); + if ($saved) { + $class = "success"; + $title = "Gespeichet"; + } else { + $class = "error"; + $title = "Sorry"; + $outputLogin = $inputLogin; + $outputEmail = $inputEmail; + } + + } else { + $class = "error"; + $title = "Sorry"; + $message = "Something goes wrong"; + } +} +?> + + + + + + +matrix.kraut.space - request + + + + +
+ + + +
+ +
+

Komm in die Matrix ...

+Der Krautspace ist auch in der Matrix zu +erreichen. Ihr findet uns dort unter #krautchan:matrix.kraut.space oder #krautchan:matrix.org. Da wir uns ein dezentrales Internet +wünschen, betreiben wir auch einen eigenen Matrix-Server. Wenn Ihr dort +einen Account möchtet, schreibt eine Mail an matrix@kraut.space oder benutzt +das untenstehende Formular. +
+ +
+

Als Benutzer für den Matrix Chat registrieren

+ +

Über dieses Formular können Sie einen Account für die Benutzung des +Matrix-Chats auf dem Server matrix.kraut.space registrieren. Der +Benutzername sollte aus einem Wort ohne Umlaute, Leer- oder Sonderzeichen +bestehen. Stellen Sie sicher, daß Sie eine gültige E-Mail-Adresse angegeben +- an diese wird die Bestätigungsmail gesendet. Nach erfolgreicher +Aktivierung Ihres Accounts bekommen Sie Ihr vorläufiges Passwort. Sie +sollte dieses danach unverzüglich über Ihren Matrix-Client ändern.

+
+ +
+ +

+ + + +

+ +
+ +
+
+
Registrieren +
+ +
+
+ +
+
+ +
+ +
+
+
+ +
+

Bitte beachten Sie bei der Auswahl des Benutzernamens, daß die +Spezifikation für den 'localpart' der Matrix-ID neben Kleinbuchstaben und +Zahlen lediglich noch die Zeichen Minus, Punkt, Gleichheitszeichen, +Unterstrich und den Schrägstrich zuläßt.

+
+ +
+ + + +
+ + diff --git a/lib/base.php b/lib/base.php new file mode 100644 index 0000000..1e07b7d --- /dev/null +++ b/lib/base.php @@ -0,0 +1,92 @@ +log = new Logger(); + } catch (Exception $e) { + throw new Exception("Can't create logger instance"); + } + $this->log->d("Create a instance of BaseClass"); + /** + * Instanz der Klasse Config erstellen und Konfigurationsdatei + * einlesen lassen. + */ + try { + $this->config = new Config(); + $this->config->loadConfig($this->config_path); + $this->log->d("Configuration file parsed"); + } catch (Exception $e) { + $this->log->e("Error: {$e->getMessage()}"); + } + $this->log->setLogLevel($this->config->getLogLevel()); + /** + * Instanz der Klasse Datenbank erstellen. Die Datenbank bekommt die + * Instanz der Klasse Config übergeben. Wenn nicht vorhanden wird + * die Tabelle requests angelegt. + */ + try { + $this->db = getDatabase($this->config, $this->log); + } catch (Exception $e) { + $this->log->e("Error: {$e->getMessage()}"); + } + } + + public function generateToken(int $length): bool { + + /** + * Generiert einen Token aus zufälligen Bits der Länge 'length'. + * Speichert diesen Token in der als Refeenz übergebenen Variable. + */ + + try { + $this->token = bin2hex(random_bytes($length)); + } catch (Exception $e) { + $this->log->e("Token creation failed"); + return false; + } + return true; + } + + +} + + +?> diff --git a/lib/config.php b/lib/config.php new file mode 100644 index 0000000..5923f39 --- /dev/null +++ b/lib/config.php @@ -0,0 +1,100 @@ +config = @parse_ini_file($config_path); + if ($this->config === false) + { + throw new Exception("Failed to parse configuration file"); + } + } + + public function getDbDriver(): string { + $driver = $this->config['driver'] ?? "PDO_PGSQL"; + return $driver; + } + + public function getDbFile(): string { + $file = $this->config['file'] ?? "./request.db"; + return $file; + } + + public function getDbHost(): string { + $host = $this->config['host'] ?? "localhost"; + return $host; + } + + public function getDbPort(): int { + $port = $this->config['port'] ?? 5432; + return $port; + } + + public function getDbBase(): string { + $database = $this->config['database'] ?? "requests"; + return $database; + } + + public function getDbUser(): string { + $user = $this->config['user'] ?? "matrixadmin"; + return $user; + } + + public function getDbPass(): string { + $password = $this->config['password'] ?? "geheim"; + return $password; + } + + public function getLogLevel(): string { + $loglevel = strtoupper($this->config['loglevel']) ?? "INFO"; + return $loglevel; + } + + public function getLogFile(): string { + $logfile = $this->config['logfile'] ?? "log/register.log"; + return $logfile; + } + + public function getMxDomain(): string { + $driver = $this->config['mxdomain'] ?? "matrix.kraut.space"; + return $driver; + } + + public function getBaseURL(): string { + $baseurl = $this->config['baseurl'] ?? ""; + return $baseurl; + } + + public function getValidator(): string { + $validator = $this->config['validator'] ?? "validator.php?token="; + return $validator; + } + + public function getMailFrom(): string { + $mailfrom = $this->config['mailfrom'] ?? ""; + return $mailfrom; + } + + public function getMailSubject(): string { + $mailsubject = $this->config['mailsubject'] ?? "Ihr Matrix Account"; + return $mailsubject; + } + + public function getMailClosure(): string { + $mailclosure = $this->config['mailclosure'] ?? "MfG"; + return $mailclosure; + } + +} + +?> diff --git a/lib/db.php b/lib/db.php new file mode 100644 index 0000000..e05ccf9 --- /dev/null +++ b/lib/db.php @@ -0,0 +1,340 @@ +connect($config); + $db = new Database($pdo, $log); + } catch (PDOException $e) { + throw new Exception($e->getMessage()); + } + return $db; +} + +class Connection { + + /** + * Stellt die Verbindung zur Datenbank her. Derzeit sind Postgres, MySQL + * und SQLite Datenbanken möglich. + */ + + private static $conn; + + public function connect(&$config) + { + + $driver = $config->getDbDriver(); + $file = $config->getDbFile(); + $host = $config->getDbHost(); + $port = $config->getDbPort(); + $base = $config->getDbBase(); + $user = $config->getDbUser(); + $pass = $config->getDbPass(); + + try { + if ($driver === "PDO_PGSQL") { + $pdo = new PDO("pgsql:host=$host;port=$port;dbname=$base", $user, $pass); + } + else if ($driver === "PDO_SQLITE") { + $pdo = new PDO("sqlite:$file"); + } + else { + throw new Exception("Wrong driver for database: {$driver}"); + return false; + } + } catch (PDOException $e) { + throw new Exception($e->getMessage()); + } + if (isset($pdo)) { + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } + return $pdo; + } + + public static function get() + { + if (null === static::$conn) + { + static::$conn = new static(); + } + return static::$conn; + } + + public static function close() + { + static::$conn = null; + return true; + } + +} + + +class Database { + + /** + * Stellt das Datenbankobjekt und die Methoden zum Arbeiten mit der + * Datenbank zur verfügung. + */ + + private $pdo; + private $log; + + public function __construct($pdo, $log) + { + $this->pdo = $pdo; + $this->log = $log; + $this->log->d("Databaseobject created"); + // hier vielleicht TableCreate hin + + } + + public function TableExists(): int + { + $stmt = "SELECT * FROM information_schema.tables WHERE + table_type = 'BASE TABLE' and + table_name = 'requests'"; + $response = $this->pdo->query($stmt); + $count = $response->rowCount(); + return $count; + } + + public function createTable() + { + $stmt = "CREATE TABLE IF NOT EXISTS requests ( + id serial PRIMARY KEY, + nick varchar(80) NOT NULL UNIQUE, + email varchar(80) NOT NULL, + token char(32) NOT NULL UNIQUE, + time integer NOT NULL);"; + $this->pdo->exec($stmt); + return $this; + } + + + public function UserExistsInUsers(string $nick): bool + { + /** + * Sucht in der Tabelle users nach bereits angelegten Nutzern. Die + * Abfrage der Datenbank wird an die Funktion searchUser delegiert. + * Sollte diese eine Exception werfen, wird true (es gibt einen + * Benutzer) zurück gegeben. Ansonsten wird der Rückgabewert + * von der Funktion getNick ausgewertet, die aus der übergebenen + * Matrix-ID den localpart extrahiert. + */ + + $this->log->d("Search for localpart {$nick} in users"); + $query = "SELECT name FROM users WHERE name LIKE :nick"; + $pattern = "%$nick%"; + try { + $response = $this->searchUser($query, $pattern); + } catch (PDOException $e) { + $this->log->e("searchUser() returns true because PDOException"); + return true; + } + $count = count($response); + if ($count == 0) + { + $this->log->d("Nothing found"); + return false; + } + else + { + foreach ($response as $array) { + $uid = $this->getNick($array['name']); + $this->log->d("Compare {$nick} with {$uid}"); + if ($uid === $nick) { + $this->log->i("MID localpart already exists: {$nick}"); + return true; + } else { + $this->log->d("False"); + } + } + } + return false; + } + + public function UserExistsInRequests(string $nick): bool + { + /** + * Sucht in der Tabelle requests nach breits beantragten + * Nutzernamen. Die Abfrage der Datenbank wird an die Funktion + * searchUser delegiert. Sollte diese eine Exception werfen, wird + * true (es gibt einen benutzer) zurück gegeben. Ansonsten wird die + * Anzahl der Treffer ausgewertet. + */ + + $this->log->d("Search for localpart {$nick} in requests"); + $query = "SELECT nick FROM requests WHERE nick = :nick"; + try { + $response = $this->searchUser($query, $nick); + } catch (PDOException $e) { + $this->log->e("searchUser() returns true because PDOException"); + return true; + } + $count = count($response); + if ($count > 0) { + $this->log->d("Search for {$nick}: {$count} hit(s)"); + return true; + } + $this->log->d("Nothing found"); + return false; + } + + private function searchUser(string $query, string $nick): array + { + /** + * Führt die Suchoperartion auf der Datenbank aus. Bekommt dafür den + * Querystring und den Nick übergeben. Sollte Abfrage der Datenbank + * fehlschlagen, wirft die Funktion die Exception an die aufrufende + * Funktion. + */ + + try + { + $stmt = $this->pdo->prepare($query, + array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)); + $stmt->execute(array(':nick' => $nick)); // gibt bool zurück + $response = $stmt->fetchAll(); + return $response; + } + catch (PDOException $e) + { + $errormsg = $e->getMessage(); + $this->log->e("A PDO-Exception occurres"); + $this->log->e("Error: {$errormsg}"); + throw new PDOException($errormsg); + } + } + + private function getNick(string $mid): string + { + /** + * Extrahiert aus einer Matrix-ID den localpart. + * TODO: In eine bibliothek auslagern? (/lib/common) + */ + + $this->log->d("Extract nick from {$mid}"); + $uid = ""; + $append = false; + $strarray = str_split($mid); + foreach ($strarray as $char) + { + if ($char == '@') + { + $append = true; + } + else if ($char == ':') + { + $this->log->d("Extracted: {$uid}"); + return $uid; + } + else + { + if ($append === true) + { + $uid = $uid.$char; + } + } + } + } + + public function saveRequest($token): bool + { + /** + * Speichert den gewünschten Nick, die Emailadresse, das Token und + * einen Zeitstempel in der Tabelle Requests. + * TODO: Sollten/Müssen Nick und Email noch durch htmlspecialchars() + * oder reichen die prepared Statments? + */ + + $nick = $_POST['login']; + $email = $_POST['email']; + date_default_timezone_set("Europe/Berlin"); + $time = time(); + $this->log->d("Save request for: {$nick} with {$token} at {$time}"); + try { + $stmt = $this->pdo->prepare("INSERT INTO requests + (nick, email, token, time) VALUES + (:nick, :email, :token, :time)"); + $response = $stmt->execute(array(':nick' => $nick, + ':email' => $email, + ':token' => $token, + ':time' => $time)); + } catch (PDOException $e) { + $errmsg = $e->getMessage(); + $this->log->e("Saving request failed"); + $this->log->e("Error: {$errmsg}"); + return false; + } + $this->log->i("Request saved successfull"); + $this->log->d("Database returns: {$response}"); + return true; + } + + public function getToken(): array { + + /** + * Sucht in der Tabelle requests nach dem Token. Gibt im Erfolgsfall + * ein Array mit ID, Name und Token zurück. Andernfalls ein leeres + * Array. Im Falle eines Datenbankfehlers wird eine Exception + * geworfen. + */ + + $token = $_GET['token']; + $query = "SELECT id, nick, token FROM requests WHERE token = :token"; + try { + $stmt = $this->pdo->prepare($query, + array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)); + $stmt->execute(array(':token' => $token)); // gibt bool zurück + $response = $stmt->fetchAll(); + } catch (PDOException $e) { + $this->log->e("PDO Exception occures"); + throw new Exception($e->getMessage()); + } + $this->log->d("Database operation successfull"); + return $response; + } + + public function removeToken(int $id): int { + + /** + * Entfernt den Request aus der Tabelle requests. Wird aufgerufen, + * wenn die Registrierung des Nicks am Matrixserver erfolgreich war. + */ + + $query = "DELETE FROM requests WHERE id = :id"; + try { + $stmt = $this->pdo->prepare($query, + array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)); + $stmt->execute(array(':id' => $id)); // gibt bool zurück + } catch (PDOException $e) { + $this->log->e("PDO Exception occures"); + throw new Exception($e->getMessage()); + return false; + } + $this->log->d("Database operation successfull"); + return $stmt->rowCount();; + } + +} + +?> diff --git a/lib/logger.php b/lib/logger.php new file mode 100644 index 0000000..a2875ff --- /dev/null +++ b/lib/logger.php @@ -0,0 +1,73 @@ + 10, + "WARN" => 20, + "INFO" => 30, + "DEBUG" => 40, + ); + public $loglevel = "INFO"; + private $logfile = "log/register.log"; + private $app = "matrix-register"; + + public function e(string $msg) { + $this->logMsg("ERROR", $msg); + } + + public function w(string $msg) { + $this->logMsg("WARN", $msg); + } + + public function i(string $msg) { + $this->logMsg("INFO", $msg); + } + + public function d(string $msg) { + $this->logMsg("DEBUG", $msg); + } + + public function setLogLevel(string $level) { + if (array_key_exists($level, $this->levelnumbers) === true) { + $this->loglevel = $level; + $this->writeLog("INFO", "Loglevel set to {$level}"); + } else { + $this->writeLog("WARN", "{$level} is not a valid loglevel."); + } + } + + private function logMsg(string $label, string $msg) { + $msglevel = $this->levelnumbers[$label]; + $loglevel = $this->levelnumbers[$this->loglevel]; + if ($loglevel >= $msglevel) { + $this->writeLog($label, $msg); + } + } + + private function writeLog(string $label, string $msg) { + $app = $this->app; + $file = $this->logfile; + error_log(date("[Y-m-d H:i:s]")." [".$label."] [".$app."] ".$msg."\n", 3, $file); + } + +} + + +?> diff --git a/lib/register.php b/lib/register.php new file mode 100644 index 0000000..2aa55ca --- /dev/null +++ b/lib/register.php @@ -0,0 +1,113 @@ +config, $this->db), die Funktion generateToken(), sowie die + * Variable $this->token. + */ + + private $dataSet = []; + + public function registerUser(&$message): bool { + + /** + * Hauptfunktion der Klasse Registrator - steuert die Validierung und + * das Registrieren der Anfrage. + */ + + if (!isset($this->db)) { + $this->log->e("There is no database"); + return false; + } + + $this->log->d("Validation started for token: {$_GET['token']}"); + if ($this->checkToken() === true) { + if ($this->generateToken($token, 32) === true) { + if ($this->registerMXID() === true) { + $message = "Your temporary password is {$tmp_passwd}. Please + immediately change your password!"; + if ($this->removeToken() === true) { + return true; + } + } + } + } + return false; + } + + private function checkToken(): bool { + + /** + * Läßt in der Tabelle requests schauen, ob es $_GET['token'] gibt. + * Speichert das zurückgegebene Array in der Variable $dataSet. Gibt + * die Datenbank eine Exception zurück oder ist das Array leer, gibt + * sie False, andernfals True zurück. + */ + + try { + $this->dataSet = $this->db->getToken(); + } catch (Exception $e) { + $this->log->e("Error: {$e->getMessage()}"); + return false; + } + + $count = count($this->dataSet); + if ($count === 0) { + $this->log->d("Token {$_GET['token']} not found in database"); + } else if ($count > 1) { + $this->log->e("Error: More than one token found"); + } else { + $this->log->d("Token found for nick: {$this->dataSet[1]}"); + return true; + } + return false; + } + + private function registerMXID(string $tmp_passwd): bool { + + /** + * Registriert den Nutzer am Matrixserver. Dazu wird ein zufälliger + * String erzeugt und zusammen mit dem Nick ein CLI Tool aus dem Paket + * Paket von matrix-synapse aufgerufen. + */ + + // $cmd = "register_new_matrix_user -u {$this->dataSet[1]} -p {$tmp_pass}"; + // $response = system($cmd); + return true; + } + + private function removeToken(): bool { + + /** + * Läßt den Request aus der tabelle requests entfernen. + */ + + $id = $this->dataSet[0]; + $nick = $this->dataSet[1]; + $token = $this->dataSet[2]; + try { + $response = $this->db->deleteToken($id); + } catch (Exception $e) { + $this->log->e("Error: {$e->getMessage()}"); + return false; + } + return true; + } + +} + +?> diff --git a/lib/request.php b/lib/request.php new file mode 100644 index 0000000..c1509b8 --- /dev/null +++ b/lib/request.php @@ -0,0 +1,197 @@ +config, $this->db), die Funktion generateToken() und sowie + * die Variable $this-token. + */ + + public function checkRequest(string &$message): bool { + + /** + * Hauptfunktion der Klasse Request - steuert alle Prüfungen, das + * Speichern des Requests und das Versenden der Email. Gibt True + * oder False zurück und setzt die Variable "message", welche auf + * der Webseite ausgegeben wird. + */ + + if (!isset($this->db)) { + $this->log->e("There is no database"); + $message = "Something goes wrong"; + return false; + } + + $this->log->d("Request started for nick: {$_POST['login']}"); + if (false === $this->checkCaptcha()) { + $message = "Captcha invalid"; + return false; + } else if (false === $this->checkEmail()) { + $message = "Email invalid"; + return false; + } else if (false === $this->checkMXID($this->config->getMxDomain())) { + $message = "User ID invalid"; + return false; + } else if (false === $this->checkUser()) { + $message = "User Id is already taken"; + return false; + } else { + if ($this->generateToken($token, 16) === true) { + if ($this->saveRequest() === true) { + if ($this->sendVerificationMail() === true) { + return true; + } + } + } + } + return false; + } + + + private function saveRequest(): bool { + + /** + * Veranlaßt die Speicherung der Anfrage in der Tabelle requests. + * TODO: Exceptions behandeln. + */ + + $response = $this->db->saveRequest($this->token); + if (!$response) { + return false; + } + return false; + } + + private function sendVerificationMail(): bool { + + /** + * Verschickt die Mail mit dem Verifizierungslink. + * TODO: Reicht filter_input()? Was kann hier passieren? + */ + + $mailTo = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL); + $mxdomain = $this->config->getMxDomain(); + $baseurl = $this->config->getBaseURL(); + $validator = $this->config->getValidator(); + $mailFrom = $this->config->getMailFrom(); + $mailSubject = $this->config->getMailSubject(); + $mailClosure = $this->config->getMailClosure(); + + $link = $baseurl . $validator . $this->token . "\r\n\r\n"; + $mailbody = MAILTEXT1 . $mxdomain . MAILTEXT2 . "\r\n\r\n" . $link . $mailClosure; + if (mail($mailTo, $mailSubject, $mailbody, $mailFrom)) + { + $this->log->i("Validationmail successfull send"); + return true; + } + $this->log->e("Sending validation mail failed"); + return false; + } + + private function checkCaptcha(): bool { + + /** + * Prüfen, ob das Captcha die korrekte Hausnummer abbildet. + * Filter_input gibt im Erfolgsfall einen Integer zurück. + */ + + $this->log->d("Checking captcha"); + $captcha = filter_input(INPUT_POST, 'captcha', FILTER_VALIDATE_INT); + if ($captcha == 26) { + $this->log->d("Captcha valid"); + return true; + } + $this->log->e("Invalid captcha"); + return false; + } + + private function checkEmail(): bool { + + /** + * Prüfen, ob die Emailadresse schematisch gültig ist. filter_input + * gibt im Erfolgsfall den Wert, im Fehlerfall false oder null, wenn + * die Variable nicht gestzt ist, zurück. Letzteres wird beim + * vorangehenden Test checkForms geprüft und kann daher nicht + * auftreten. + */ + + $this->log->d("Checking email schema"); + if (filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL)) { + $this->log->d("Email schema is valid"); + return true; + } + $this->log->e("Email schema invalid"); + return false; + } + + private function checkMXID(string $mxid): bool { + + /** + * Prüft, ob der gewünschte localpart nur Zeichen enthält, die von + * der Matrix-Spezifikation erlaubt sind. Die Spezifikation erlaubt + * nur Kleinbuchstaben, Ziffern, Minus, Punkt, Gleichheitszeichen, + * Unterstrich und Schrägstrich. Geprüft wird auch, ob die Länge des + * gewünschten localpart zusammen mit dem domainpart sowie dem @ und + * : die Länge von 255 Zeichen nicht überschreiten. + */ + + $this->log->d("Check MXID localpart"); + $str_array = str_split($_POST['login']); + $max_length = 255 - (mb_strlen($mxid) + 2); + $specials = array('-', '.', '=', '_', '/'); + $numbers = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); + $possibles = array_merge(range('a', 'z'), $numbers, $specials); + + foreach ($str_array as $item) { + if (in_array($item, $possibles, true) === false) { + $this->log->e("MXID localpart: invalid character: {$item}"); + return false; + } + } + if (mb_strlen($_POST['login']) > $max_length) { + $this->log->e("MXID localpart: too long"); + return false; + } + $this->log->d("MXID localpart is valid"); + return true; + } + + private function checkUser(): bool { + + /** + * Prüft, ob der gewünschte Nutzernamen nicht bereits vergeben ist. + * Dazu wird in den Datenbanktabellen users (bereits registrierte + * benutzer) und requests (bereits beantragte benutzer) nach einer + * eventuellen Übereinstimmung geschaut. Eine spezielle Behandlung + * des Suchstrings ist nach meiner Meinung hier nicht nötig, da der + * String vorher auf Matrix-konforme Zeichen getestet wurde und die + * Datenbankfuntionen prepared Statements verwendet. + */ + + $this->log->d("Checking if username is available"); + $nick = $_POST['login']; + if ($this->db->UserExistsInRequests($nick) === true) { + return false; + } + if ($this->db->UserExistsInUsers($nick) === true) { + return false; + } + return true; + } + +} + +?> diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..1b43a4d Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..dec9f50 Binary files /dev/null and b/static/logo.png differ diff --git a/static/mail.php b/static/mail.php new file mode 100644 index 0000000..be4cd7c --- /dev/null +++ b/static/mail.php @@ -0,0 +1,20 @@ + diff --git a/static/register.css b/static/register.css new file mode 100644 index 0000000..a83601e --- /dev/null +++ b/static/register.css @@ -0,0 +1,89 @@ +/* + +file: register.css +date: 04.01.2021 +author: bernd@nr18.space + +*/ + +html, body { + padding: 0; + margin: 0; + color: #333; + background-color: white; + font-family: DejaVu Sans; + font-size: 100%; + line-height: 1.4; + height: 100%; + box-sizing: border-box; +} + +#wrapper { + min-height: 100%; + max-width: 800px; + margin: 0 auto; + padding: 1.5em 3%; +} + +main { + padding-top: 1em; +} + +.success { + display: block; + padding: 1em; + border-radius: 0.5em; + background-color: #82c385; +} + +.error { + display: block; + padding: 1em; + border-radius: 0.5em; + background-color: #db6884; +} + +section#formular { + margin: 2em; +} + +fieldset { + max-width: 500px; + margin: auto; + padding: 2em; + display: flex; + flex-direction: column; +} + +.formrow { + display: flex; + flex-direction: row; + margin-bottom: 1.4em; +} + +label.formlabel { + display: block; + text-align: right; +} + +input.forminput { + width: 60%; + margin-left: 1em; +} + +#captchaframe { + margin-top: 1em; + border: 1px solid #333; + border-radius: 2px; + padding: 1em; + text-align: center; +} + +input#captchainput { + width: 30%; +} + +input[type=submit] { + width: max-content; +} + diff --git a/static/web.php b/static/web.php new file mode 100644 index 0000000..0829198 --- /dev/null +++ b/static/web.php @@ -0,0 +1,37 @@ + + + + + +END; +const HTML_HEADER = << +

+ Logo Krautspace + Hackspace Jena e.V. +

+ +END; +const HTML_FOOTER = << +

Krautspace Jena e.V. | 07743 Jena | Krautgasse 26

+

+ Impressum + Datenschutz +

+ +END; + +?> diff --git a/validation.php b/validation.php new file mode 100644 index 0000000..844ba9b --- /dev/null +++ b/validation.php @@ -0,0 +1,69 @@ +registerUser($message); + if ($registered) { + $class = "success"; + $title = "Congratulations"; + } else { + $class = "error"; + $title = "Sorry"; + $message = "Failed to register your account."; + } + } else { + $class = "error"; + $title = "Sorry"; + $message = "Something goes wrong."; + } +} + +?> + + + + + +matrix.kraut.space - register + + + + +
+ + + +
+ +
+ +

+ + + +

+ +
+ +
+ + + +
+ +