From 973d4b03459257b46f54268fd9c78a54a39a39ec Mon Sep 17 00:00:00 2001 From: eclipse Date: Sun, 2 Mar 2025 19:50:47 +0100 Subject: [PATCH] added DB functions --- content/php/confirm.php | 55 +++++++++++++++++++++++++++---------- content/php/settings.php | 54 ++++++++++++++++++++++++++++-------- content/php/subscribe.php | 11 ++------ content/php/unsubscribe.php | 29 +++++++++++++++++-- 4 files changed, 113 insertions(+), 36 deletions(-) diff --git a/content/php/confirm.php b/content/php/confirm.php index 1b6d666..91e43b6 100644 --- a/content/php/confirm.php +++ b/content/php/confirm.php @@ -1,31 +1,56 @@ prepare($general['sql']['create_table']); + if ( ! $query->execute() ) { + error_log('Datenbankfehler beim Prüfen/Erzeugen der Tabelle.'); + return "Ein Fehler ist aufgetreten."; + } + + // check if record exists + $query = $pdo->prepare($general['sql']['read_record']); + if ( ! $query->execute([':e' => $subscriberAddress]) ) { + error_log("Datenbankfehler: Adresscheck für Emailadresse {$subscriberAddress} ergab einen Fehler."); + return 'Datenbankfehler.'; + } + if ( $query->fetch() ) { + error_log("Datenbankfehler: Emailadresse {$subscriberAddress} ist bereits eingetragen."); + return "Emailadresse ist bereits eingetragen."; + } + + // create record + $query = $pdo->prepare($general['sql']['create_record']); + if ( ( ! $query->execute([':e' => $subscriberAddress, ':n' => $subscriberName]) ) or ( $query->fetch() ) ) { + error_log("Datenbankfehler: Einfügen von Emailadresse {$subscriberAddress} ergab einen Fehler."); + return 'Datenbankfehler.'; + } + } catch(\PDOException $e) { + error_log("Datenbankfehler: {$e->getMessage()}"); + return $e->getMessage(); + } return TRUE; } -function CheckConfirmationHash($confEmail, $confCode) { - global $general; - return (md5($confEmail . $general['uniqueKey']) === $confCode); -} - -require(dirname(__FILE__) . '/settings.php'); - if (isset($_GET['c']) && isset($_GET['e'])) { $c = filter_var($_GET['c'], FILTER_SANITIZE_STRING); $e = filter_var($_GET['e'], FILTER_SANITIZE_STRING); - if (CheckConfirmationHash($e, $c)) { + if ( GetConfirmationHash($e) === $c ) { $result = AddSubscriberToDB($e); - if ($result == TRUE) { + if ($result === TRUE) { GracefulExit($successURL, 'Bestätigung erfolgt: Newsletter-Anmeldung bestätigt'); } elseif (gettype($result == 'string')) { GracefulExit($errorURL, "Bestätigung fehlgeschlagen: {$result}"); diff --git a/content/php/settings.php b/content/php/settings.php index 7f28c61..44979e6 100644 --- a/content/php/settings.php +++ b/content/php/settings.php @@ -11,16 +11,28 @@ require $dname . '/SMTP.php'; // general constants $general = [ -// 'domain' => 'tobias-radloff.de', + // site domain (used for building confirmation links) +/* 'domain' => 'tobias-radloff.de', */ 'domain' => 'localhost', + // string concatenated with email address to create a non-recreatable md5 hash 'uniqueKey' => '***REMOVED***', // works like password salt + // file name of confirm script 'confirmScript' => '/confirm.php', - 'statusCode' => 'HTTP/1.1 303 See Other' + // status code to be used when redirection to success or error page + 'statusCode' => 'HTTP/1.1 303 See Other', + // array of SQL statements used + 'sql' => [ + 'create_table' => 'CREATE TABLE IF NOT EXISTS subscribers (id INTEGER PRIMARY KEY, email TEXT NOT NULL UNIQUE, name TEXT);', + 'create_record' => 'INSERT INTO subscribers(email, name) VALUES(:e, :n);', + 'read_record' => 'SELECT 1 FROM subscribers WHERE email = :e;', + 'update_record' => '', + 'delete_record' => 'DELETE FROM subscribers WHERE email = :e;' + ] ]; - +// complete site URL $general['siteURL'] = 'https://' . $general['domain']; -// smtp info +// SMTP server information $smtp = [ 'host' => '***REMOVED*** 'port' => 587, @@ -31,28 +43,47 @@ $smtp = [ 'fromName' => 'Tobias Radloffs Newsletter', ]; +// body of confirmation email $bodyConfirmation = [ 'Hallo!', 'Bitte bestätige die Anmeldung für meinen Newsletter, indem du auf den folgenden Link klickst:', - '%Placeholder%', // placeholder + '%Placeholder%', 'Bis bald und viele Grüße, Tobias' ]; -// mail contents +// contents of confirmation email $mailConfirmation = [ 'subject' => 'Newsletter-Anmeldung bestaetigen', 'bodyHTML' => '

' . implode('

', $bodyConfirmation) . '

', 'bodyText' => implode("\n\n", $bodyConfirmation) ]; -// DB constants +// database information $db = [ - 'host' => '', - 'port' => '', - 'username' => '', - 'password' => '' + 'sqlite' => [ + 'dsn' => 'sqlite:../newsletter.sqlite', + ], + 'mysql' => [ + 'dsn' => '', + 'host' => '', + 'port' => '', + 'username' => '', + 'password' => '' + ] ]; +function GetConfirmationHash($confEmail) { + global $general; + return md5($confEmail . $general['uniqueKey'] ); +} + +// connects to database and returns PDO object +function getPDO($dbType = 'sqlite') { + global $db; + return new \PDO($db[$dbType]['dsn']); +} + +// Sends an email to single recipient with subject and body specified in an array. Returns an error message on failure, TRUE on success. function SendEmail($recipientAddress, $mailContents, $link = NULL) { global $general, $smtp; @@ -92,6 +123,7 @@ function SendEmail($recipientAddress, $mailContents, $link = NULL) { } } +// redirects to specified URL via GET request and conveys an optional message function GracefulExit($location, $message = NULL) { global $general; header($general['statusCode']); diff --git a/content/php/subscribe.php b/content/php/subscribe.php index d980bf8..9ca2276 100644 --- a/content/php/subscribe.php +++ b/content/php/subscribe.php @@ -6,20 +6,15 @@ $errorURL = '/newsletter/subscribe-error.html'; require(dirname(__FILE__) . '/settings.php'); -function MakeConfirmationHash($confEmail, $confCode) { - return md5($confEmail . $confCode); -} - if (isset($_POST['email'])) { $email = filter_var(trim($_POST['email'], FILTER_SANITIZE_STRING)); -error_log("Email ist: {$email}"); + if (filter_var($email, FILTER_VALIDATE_EMAIL)) { - $hashedUnique = MakeConfirmationHash($email, $general['uniqueKey']); - $confirmQuery = http_build_query(['c' => $hashedUnique, 'e' => $email]); + $confirmQuery = http_build_query(['c' => GetConfirmationHash($email), 'e' => $email]); $confirmLink = $general['siteURL'] . $general['confirmScript'] . "?" . $confirmQuery; $result = SendEmail($email, $mailConfirmation, $confirmLink); - if ( $result == TRUE ) { + if ( $result === TRUE ) { GracefulExit($successURL, 'Anmeldung wird fortgesetzt: Email mit Bestätigungslink wurde versandt.'); } else { GracefulExit($errorURL, 'Anmeldung fehlgeschlagen: Fehler beim Versenden der Bestätigungs-Email.'); diff --git a/content/php/unsubscribe.php b/content/php/unsubscribe.php index c90f113..1786cd1 100644 --- a/content/php/unsubscribe.php +++ b/content/php/unsubscribe.php @@ -7,14 +7,39 @@ $errorURL = '/newsletter/unsubscribe-error.html'; function RemoveSubscriberFromDB($subscriberAddress) { - error_log("removing subscriber {$subscriberAddress} from DB ..."); + global $general; + + try { + $pdo = getPDO(); + + // make sure record exists + $query = $pdo->prepare($general['sql']['read_record']); + if ( ! $query->execute([':e' => $subscriberAddress]) ) { + error_log("Datenbankfehler: Adresscheck für {$subscriberAddress} ergab einen Fehler."); + return 'Datenbankfehler.'; + } + if ( ! $query->fetch() ) { + error_log("Datenbankfehler: Emailadresse {$subscriberAddress} nicht in Datenbank vorhanden."); + return "Emailadresse nicht bekannt."; + } + + // delete record + $query = $pdo->prepare($general['sql']['delete_record']); + if ( ! $query->execute([':e' => $subscriberAddress])) { + error_log("Datenbankfehler: Löschen von Emailadresse {$subscriberAddress} ergab einen Fehler."); + return 'Fehler beim Löschen des Datenbankeintrags.'; + } + } catch(\PDOException $e) { + error_log("Datenbankfehler: {$e->getMessage()}"); + return $e->getMessage(); + } return TRUE; } if (isset($_GET['e'])) { $e = filter_var($_GET["e"], FILTER_SANITIZE_STRING); $result = RemoveSubscriberFromDB($e); - if ($result == TRUE) { + if ($result === TRUE) { GracefulExit($successURL, "Abmeldung für {$e} erfolgreich."); } elseif (gettype($result == 'string')) { GracefulExit($errorURL, "Abmeldung fehlgeschlagen: {$result}");