forked from berhsi/matrix-register
210 lines
7 KiB
PHP
210 lines
7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* file: lib/request.php
|
|
* date: 28.02.2021
|
|
* user: bernd@nr18.space
|
|
* desc:
|
|
*/
|
|
|
|
|
|
if (!defined('INCLUDES_ALLOWED'))
|
|
die('Access denied.');
|
|
|
|
require("base.php");
|
|
require("static/mail.php");
|
|
|
|
|
|
class Request extends BaseClass {
|
|
|
|
/**
|
|
* Klasse zur Bearbeitung einer Anfrage nach einem Matrix Accuont. Erbt
|
|
* aus der Klasse BaseClass ein Konfigurations- und ein Datenbankobjekt
|
|
* ($this->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->i("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(16) === true) {
|
|
if ($this->saveRequest() === true) {
|
|
if ($this->sendVerificationMail() === true) {
|
|
$login = htmlspecialchars($_POST['login']);
|
|
$message = "Your request for '{$login}' is saved and a
|
|
verification mail is send";
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
private function saveRequest(): bool {
|
|
|
|
/**
|
|
* Veranlaßt die Speicherung der Anfrage in der Tabelle requests.
|
|
* Bekommt aus der Datenbank (auch im Falle einer PDO Exception)
|
|
* einen Boolean zurück.
|
|
*/
|
|
|
|
try {
|
|
$response = $this->db->saveRequest($this->token);
|
|
} catch (Exception $e) {
|
|
$this->log->e("Error: Database returns: {$e->getMessage()}");
|
|
}
|
|
if ($response === true) {
|
|
return true;
|
|
}
|
|
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();
|
|
$this->log->d("Try to send verification mail");
|
|
|
|
$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_VALIDATE_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;
|
|
}
|
|
|
|
}
|
|
|
|
?>
|