forked from berhsi/matrix-register
Merge branch 'spamschutz'
schwacher spamschutz, funktionen in common.php ausgelagert
This commit is contained in:
commit
a82ea913bd
5 changed files with 256 additions and 109 deletions
|
@ -9,8 +9,8 @@ require("lib/request.php");
|
||||||
$outputLogin = null;
|
$outputLogin = null;
|
||||||
$outputEmail = null;
|
$outputEmail = null;
|
||||||
$class=null;
|
$class=null;
|
||||||
$title = null;
|
$title = "Sorry";
|
||||||
$message = ""; // checkRequest() erwartet einen string
|
$message = "Something goes wrong";
|
||||||
$saved = false;
|
$saved = false;
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$title = "Success";
|
$title = "Success";
|
||||||
} else {
|
} else {
|
||||||
$class = "error";
|
$class = "error";
|
||||||
$title = "Sorry";
|
|
||||||
$outputLogin = $inputLogin;
|
$outputLogin = $inputLogin;
|
||||||
$outputEmail = $inputEmail;
|
$outputEmail = $inputEmail;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +33,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
} else {
|
} else {
|
||||||
$class = "error";
|
$class = "error";
|
||||||
$title = "Error";
|
$title = "Error";
|
||||||
$message = "Something goes wrong";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
67
lib/common.php
Normal file
67
lib/common.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file: common.php
|
||||||
|
* date: 03.03.2021
|
||||||
|
* author: bernd@nr18.space
|
||||||
|
* desc: Allgemeine Funktionen, die mal in lib/db.php waren aber nichts mit
|
||||||
|
* der Datenbank zu tun haben.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
if (!defined('INCLUDES_ALLOWED'))
|
||||||
|
die('Access denied.');
|
||||||
|
|
||||||
|
|
||||||
|
function getNow(): int {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zeitzone aud Berlin setzen und die aktuelle Zeit in Sekunden seit
|
||||||
|
* 01.01.1970 zurückgeben.
|
||||||
|
*/
|
||||||
|
|
||||||
|
date_default_timezone_set("Europe/Berlin");
|
||||||
|
return time();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNick(string $mid): string
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Extrahiert aus einer Matrix-ID den localpart.
|
||||||
|
* TODO: In eine bibliothek auslagern? (/lib/common)
|
||||||
|
*/
|
||||||
|
|
||||||
|
$uid = "";
|
||||||
|
$append = false;
|
||||||
|
$strarray = str_split($mid);
|
||||||
|
foreach ($strarray as $char)
|
||||||
|
{
|
||||||
|
if ($char == '@')
|
||||||
|
{
|
||||||
|
$append = true;
|
||||||
|
}
|
||||||
|
else if ($char == ':')
|
||||||
|
{
|
||||||
|
return $uid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($append === true)
|
||||||
|
{
|
||||||
|
$uid = $uid.$char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRemoteHexIP() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wandelt die IP des anfragenden Clients in einen Hexadezimalen
|
||||||
|
* String um.
|
||||||
|
* TODO: Funktion allgemeiner halten? IP als Parameter übergeben?
|
||||||
|
*/
|
||||||
|
|
||||||
|
return bin2hex(inet_pton($_SERVER['REMOTE_ADDR']));
|
||||||
|
}
|
||||||
|
|
142
lib/db.php
142
lib/db.php
|
@ -7,10 +7,17 @@
|
||||||
* desc: Anbindung an die (Postgres) Datenbank.
|
* desc: Anbindung an die (Postgres) Datenbank.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
ini_set("display_errors", "on");
|
||||||
|
ini_set("display_startip_errors", "on");
|
||||||
|
|
||||||
|
|
||||||
if (!defined('INCLUDES_ALLOWED'))
|
if (!defined('INCLUDES_ALLOWED'))
|
||||||
die('Access denied.');
|
die('Access denied.');
|
||||||
|
|
||||||
|
require_once("common.php");
|
||||||
|
|
||||||
|
|
||||||
function testDriver(): bool
|
function testDriver(): bool
|
||||||
{
|
{
|
||||||
print_r(PDO::getAvailableDrivers());
|
print_r(PDO::getAvailableDrivers());
|
||||||
|
@ -108,8 +115,11 @@ class Database {
|
||||||
* und die Instanz des Loggers. Läßt kontrollieren ob die Tabelle zum
|
* und die Instanz des Loggers. Läßt kontrollieren ob die Tabelle zum
|
||||||
* Eintragen der Requests vorhanden ist und stößt die Erstellung der
|
* Eintragen der Requests vorhanden ist und stößt die Erstellung der
|
||||||
* Tabelle an, wenn sie fehlt.
|
* Tabelle an, wenn sie fehlt.
|
||||||
* TODO: Geht das eleganter? So wird das bei jeder Anfrage
|
* TODO: Geht das eleganter? So wird bei jedem Request kontrolliert,
|
||||||
* ausgeführt.
|
* ob die Tabelle vorhanden ist. Anderseits gibt eine Konstruktor
|
||||||
|
* nichts zurück. Ergo wird bei einem Fehler beim Erstellen der
|
||||||
|
* Tabelle auch nicht abgebrochen, sondern erst beim Versuch etwas
|
||||||
|
* hineinzuschreiben.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$this->pdo = $pdo;
|
$this->pdo = $pdo;
|
||||||
|
@ -130,14 +140,18 @@ class Database {
|
||||||
/**
|
/**
|
||||||
* Kontrolliert, ob eine Tabelle zum Eintragen der Requests
|
* Kontrolliert, ob eine Tabelle zum Eintragen der Requests
|
||||||
* vorhanden ist.
|
* vorhanden ist.
|
||||||
* TODO: Die Query ist Postgres spezifisch. Treiber durchreichen und
|
|
||||||
* eine Weiche anlegen?
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$this->log->d("Check if table requests exists");
|
$this->log->d("Check if table requests exists");
|
||||||
$stmt = "SELECT * FROM information_schema.tables WHERE
|
if ($this->pdo->driver === "PDO_PGSQL") {
|
||||||
|
$stmt = "SELECT * FROM information_schema.tables WHERE
|
||||||
table_type = 'BASE TABLE' and
|
table_type = 'BASE TABLE' and
|
||||||
table_name = 'requests'";
|
table_name = 'requests'";
|
||||||
|
} else if ($this->pdo->driver === "PDO_PSQLITE") {
|
||||||
|
// ungetestet
|
||||||
|
$stmt = "SELECT 1 FROM sqlite_master WHERE type='table' and
|
||||||
|
name='requests'";
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
$response = $this->pdo->query($stmt);
|
$response = $this->pdo->query($stmt);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
|
@ -154,23 +168,38 @@ class Database {
|
||||||
public function createTable(): bool
|
public function createTable(): bool
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Erstellt die Tabelle Requests.
|
* Erstellt die Tabelle Requests. Wir speichern die IP als 16 Byte
|
||||||
|
* Binary. Damit soll später ein gewisser Schutz gegen Spammer
|
||||||
|
* erreicht werden. (Wie viele Requests innerhalb welcher Zeit)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$this->log->n("try to create table requests");
|
$this->log->n("Try to create table requests");
|
||||||
$stmt = "CREATE TABLE IF NOT EXISTS requests (
|
if ($this->pdo->driver === "PDO_PGSQL") {
|
||||||
|
$stmt = "CREATE TABLE IF NOT EXISTS requests (
|
||||||
id serial PRIMARY KEY,
|
id serial PRIMARY KEY,
|
||||||
nick varchar(80) NOT NULL UNIQUE,
|
nick varchar(80) NOT NULL UNIQUE,
|
||||||
email varchar(80) NOT NULL,
|
email varchar(80) NOT NULL,
|
||||||
token char(32) NOT NULL UNIQUE,
|
token char(32) NOT NULL UNIQUE,
|
||||||
|
ip bytea,
|
||||||
time integer NOT NULL);";
|
time integer NOT NULL);";
|
||||||
|
} else if ($this->pdo->driver === "PDO_PSQLITE") {
|
||||||
|
// ungetestet
|
||||||
|
$stmt = "CREATE TABLE IF NOT EXISTS request (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
nick TEXT NUT NULL UNIQUE;
|
||||||
|
email TEXT NOT NULL,
|
||||||
|
token TEXT NOT NULL UNIQUE,
|
||||||
|
ip BLOB,
|
||||||
|
time INTEGER NOT NULL);";
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
$this->pdo->exec($stmt);
|
$this->pdo->exec($stmt);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
$this->log-e("Failed to create table requests");
|
$this->log->e("Failed to create table requests");
|
||||||
|
$this->log->e("Error: {$e->getMessage()}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->log-n("Table requests successfull created");
|
$this->log->n("Table requests successfull created");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +212,8 @@ class Database {
|
||||||
* Sollte diese eine Exception werfen, wird true (es gibt einen
|
* Sollte diese eine Exception werfen, wird true (es gibt einen
|
||||||
* Benutzer) zurück gegeben. Ansonsten wird der Rückgabewert
|
* Benutzer) zurück gegeben. Ansonsten wird der Rückgabewert
|
||||||
* von der Funktion getNick ausgewertet, die aus der übergebenen
|
* von der Funktion getNick ausgewertet, die aus der übergebenen
|
||||||
* Matrix-ID den localpart extrahiert.
|
* Matrix-ID den localpart extrahiert. Nutzt für die Suche die
|
||||||
|
* Klassenfunktion searchUser(). Braucht getNick() common.php!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$this->log->d("Search for localpart {$nick} in users");
|
$this->log->d("Search for localpart {$nick} in users");
|
||||||
|
@ -204,7 +234,7 @@ class Database {
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach ($response as $array) {
|
foreach ($response as $array) {
|
||||||
$uid = $this->getNick($array['name']);
|
$uid = getNick($array['name']);
|
||||||
$this->log->d("Compare {$nick} with {$uid}");
|
$this->log->d("Compare {$nick} with {$uid}");
|
||||||
if ($uid === $nick) {
|
if ($uid === $nick) {
|
||||||
$this->log->i("MXID localpart already exists: {$nick}");
|
$this->log->i("MXID localpart already exists: {$nick}");
|
||||||
|
@ -224,7 +254,8 @@ class Database {
|
||||||
* Nutzernamen. Die Abfrage der Datenbank wird an die Funktion
|
* Nutzernamen. Die Abfrage der Datenbank wird an die Funktion
|
||||||
* searchUser delegiert. Sollte diese eine Exception werfen, wird
|
* searchUser delegiert. Sollte diese eine Exception werfen, wird
|
||||||
* true (es gibt einen benutzer) zurück gegeben. Ansonsten wird die
|
* true (es gibt einen benutzer) zurück gegeben. Ansonsten wird die
|
||||||
* Anzahl der Treffer ausgewertet.
|
* Anzahl der Treffer ausgewertet. Nutzt für die Suche die eigene
|
||||||
|
* Funktion searchUser().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$this->log->d("Search for localpart {$nick} in requests");
|
$this->log->d("Search for localpart {$nick} in requests");
|
||||||
|
@ -237,7 +268,7 @@ class Database {
|
||||||
}
|
}
|
||||||
$count = count($response);
|
$count = count($response);
|
||||||
if ($count > 0) {
|
if ($count > 0) {
|
||||||
$this->log->d("Search for {$nick}: {$count} hit(s)");
|
$this->log->n("Search for {$nick}: {$count} hit(s)");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
$this->log->d("Nothing found");
|
$this->log->d("Nothing found");
|
||||||
|
@ -270,69 +301,68 @@ class Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getNick(string $mid): string
|
public function getTimestamps(): array {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Extrahiert aus einer Matrix-ID den localpart.
|
* Schaut in der Datenbank, ob es bereits Einträge mit der aktuellen
|
||||||
* TODO: In eine bibliothek auslagern? (/lib/common)
|
* Remote IP gibt und gibt alle Einträge des dazu gehörendem
|
||||||
|
* Zeitstempels zurück. Braucht getRemoteHexIP() aus common.php!
|
||||||
|
* TODO: flexibler gestalten? IP als Parameter übergeben?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$this->log->d("Extract nick from {$mid}");
|
$ip = getRemoteHexIP();
|
||||||
$uid = "";
|
$this->log->i("Search for IP: {$_SERVER['REMOTE_ADDR']}");
|
||||||
$append = false;
|
$stmt = $this->pdo->prepare("SELECT time FROM requests WHERE
|
||||||
$strarray = str_split($mid);
|
ip = :ip");
|
||||||
foreach ($strarray as $char)
|
try {
|
||||||
{
|
$stmt->BindValue(':ip', $ip, PDO::PARAM_LOB);
|
||||||
if ($char == '@')
|
$stmt->execute();
|
||||||
{
|
$response = $stmt->fetchAll();
|
||||||
$append = true;
|
} catch (PDOException $e) {
|
||||||
}
|
$this->log->e("getIPs: ERROR: {$e->getMessage()}");
|
||||||
else if ($char == ':')
|
|
||||||
{
|
|
||||||
$this->log->d("Extracted: {$uid}");
|
|
||||||
return $uid;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ($append === true)
|
|
||||||
{
|
|
||||||
$uid = $uid.$char;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
$count = count($response);
|
||||||
|
$this->log->d("{$count} Timestamps found");;
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function saveRequest($token): bool
|
public function saveRequest($token): bool
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Speichert den gewünschten Nick, die Emailadresse, das Token und
|
* Speichert den gewünschten Nick, die Emailadresse, das Token, die
|
||||||
* einen Zeitstempel in der Tabelle Requests.
|
* IP und einen Zeitstempel in der Tabelle Requests. Braucht die
|
||||||
|
* Funktionen getRemoteHexIP() und getNow() aus common.php.
|
||||||
|
* TODO: IP nicht Hexadezimal, sondern Binär speichern. Spart Platz
|
||||||
|
* und ist schneller. Bin ich leider zu blöd für.
|
||||||
* TODO: Sollten/Müssen Nick und Email noch durch htmlspecialchars()
|
* TODO: Sollten/Müssen Nick und Email noch durch htmlspecialchars()
|
||||||
* oder reichen die prepared Statments?
|
* oder reichen die prepared Statments?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
$ip = getRemoteHexIP();
|
||||||
$nick = $_POST['login'];
|
$nick = $_POST['login'];
|
||||||
$email = $_POST['email'];
|
$email = $_POST['email'];
|
||||||
date_default_timezone_set("Europe/Berlin");
|
$time = getNow();
|
||||||
$time = time();
|
|
||||||
$this->log->d("Save request for: {$nick} with {$token} at {$time}");
|
$this->log->d("Save request for: {$nick} with {$token} at {$time}");
|
||||||
try {
|
try {
|
||||||
$stmt = $this->pdo->prepare("INSERT INTO requests
|
$stmt = $this->pdo->prepare("INSERT INTO requests
|
||||||
(nick, email, token, time) VALUES
|
(nick, email, token, ip, time) VALUES
|
||||||
(:nick, :email, :token, :time)");
|
(:nick, :email, :token, :ip, :time)");
|
||||||
$response = $stmt->execute(array(':nick' => $nick,
|
$stmt->BindValue(':nick', $nick);
|
||||||
':email' => $email,
|
$stmt->BindValue(':email', $email);
|
||||||
':token' => $token,
|
$stmt->BindValue(':token', $token);
|
||||||
':time' => $time));
|
$stmt->BindValue(':ip', $ip, PDO::PARAM_LOB);
|
||||||
|
$stmt->BindValue(':time', $time);
|
||||||
|
$response = $stmt->execute();
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
$errmsg = $e->getMessage();
|
|
||||||
$this->log->e("Saving request failed");
|
$this->log->e("Saving request failed");
|
||||||
$this->log->e("Error: {$errmsg}");
|
$this->log->e("Error: {$e->getMessage()}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->log->i("Request saved successfull");
|
if ($response) {
|
||||||
$this->log->d("Database returns: {$response}");
|
$this->log->n("Request saved successfull");
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getToken(): array {
|
public function getToken(): array {
|
||||||
|
|
|
@ -114,12 +114,11 @@ class Registrator extends BaseClass {
|
||||||
private function removeRequest(): bool {
|
private function removeRequest(): bool {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Läßt den Request aus der tabelle requests entfernen.
|
* Läßt den Request aus der Tabelle requests entfernen.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$id = $this->dataSet[0]['id'];
|
$id = $this->dataSet[0]['id'];
|
||||||
$nick = $this->dataSet[0]['nick'];
|
$nick = $this->dataSet[0]['nick'];
|
||||||
$token = $this->dataSet[0]['token'];
|
|
||||||
try {
|
try {
|
||||||
$response = $this->db->removeRequest($id);
|
$response = $this->db->removeRequest($id);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
|
147
lib/request.php
147
lib/request.php
|
@ -13,6 +13,7 @@ if (!defined('INCLUDES_ALLOWED'))
|
||||||
|
|
||||||
require("base.php");
|
require("base.php");
|
||||||
require("static/mail.php");
|
require("static/mail.php");
|
||||||
|
require_once("common.php");
|
||||||
|
|
||||||
|
|
||||||
class Request extends BaseClass {
|
class Request extends BaseClass {
|
||||||
|
@ -52,6 +53,9 @@ class Request extends BaseClass {
|
||||||
} else if (false === $this->checkUser()) {
|
} else if (false === $this->checkUser()) {
|
||||||
$message = "User Id is already taken";
|
$message = "User Id is already taken";
|
||||||
return false;
|
return false;
|
||||||
|
} else if (false === $this->checkRequests()) {
|
||||||
|
$message = "Too many requests";
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if ($this->generateToken(16) === true) {
|
if ($this->generateToken(16) === true) {
|
||||||
if ($this->saveRequest() === true) {
|
if ($this->saveRequest() === true) {
|
||||||
|
@ -67,53 +71,6 @@ class Request extends BaseClass {
|
||||||
return false;
|
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 {
|
private function checkCaptcha(): bool {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -205,6 +162,102 @@ class Request extends BaseClass {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function checkRequests(): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prüft, ob für es von der aktuellen Remote IP bereits Anfragen
|
||||||
|
* gibt. Diese sollten gewisse Limits nicht überschreiten.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$timestamps = $this->db->getTimestamps();
|
||||||
|
$now = getNow();
|
||||||
|
|
||||||
|
// Wenn es der erste Request ist -> return true
|
||||||
|
$count = count($timestamps);
|
||||||
|
if ($count === 0) {
|
||||||
|
$this->log->i("First request from {$_SERVER['REMOTE_ADDR']}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$first = $timestamps[array_key_first($timestamps)]['time'];
|
||||||
|
$last = $timestamps[array_key_last($timestamps)]['time'];
|
||||||
|
$duration = $last - $first;
|
||||||
|
$average = $duration / $count;
|
||||||
|
|
||||||
|
// Maximal 10 Anfragen in 24 Stunden
|
||||||
|
if ($count > 10 && $duration < 86400) {
|
||||||
|
$this->log->n("To many requests in 24 hours");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wenn der letzte Request weniger als 10 Sekunden her ist -> return
|
||||||
|
// false
|
||||||
|
if (($now - $last) < 5) {
|
||||||
|
$this->log->n("Time between two requests under 5 seconds");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wenn die durchschnittliche Dauer zwischen allen Anfragen unter 30
|
||||||
|
// Sekunden liegt -> return false
|
||||||
|
if (($average) < 30 && $count > 3) {
|
||||||
|
$this->log->n("Duration between all requests under 10 seconds");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nicht mehr als 20 Anfragen von einer IP in der Datenbank
|
||||||
|
// speichern -> return false
|
||||||
|
if ($count > 20) {
|
||||||
|
$this->log->n("To many requests in database");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
Loading…
Reference in a new issue