initial
This commit is contained in:
81
include/accounts.php
Normal file
81
include/accounts.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Accounts extends Renderer {
|
||||
public function __construct(?string $templateName) {
|
||||
parent::__construct($templateName);
|
||||
$this->renderInactiveUsers();
|
||||
$this->renderActiveUsers();
|
||||
}
|
||||
|
||||
private function renderInactiveUsers(): void {
|
||||
$result = mysqli_query($this->dbConnection, 'SELECT * FROM user WHERE active=0');
|
||||
$content = '<tbody>';
|
||||
while ($row = mysqli_fetch_assoc($result)) {
|
||||
$content .= '<tr><td>' . $row['username'] . '</td><td>' . $this->decode($row['realname'], $row['salt'])
|
||||
. '</td><td>' . $this->decode($row['email'], $row['salt']) . '</td>'
|
||||
. '<td><button type="submit" name="action" value="activate:' . $row['username'] . '">Aktivieren</button>'
|
||||
. '<button type="submit" name="action" value="delete:' . $row['username'] . '">Löschen</button></td></tr>';
|
||||
}
|
||||
$content .= '</tbody>';
|
||||
$this->content['inactive_accounts'] = $content;
|
||||
}
|
||||
|
||||
private function renderActiveUsers(): void {
|
||||
$result = mysqli_query($this->dbConnection, 'SELECT * FROM user WHERE active=1');
|
||||
$content = '<tbody>';
|
||||
while ($row = mysqli_fetch_assoc($result)) {
|
||||
$content .= '<tr><td>' . $row['username'] . '</td><td>' . $this->decode($row['realname'], $row['salt'])
|
||||
. '</td><td>' . $this->decode($row['email'], $row['salt']) . '</td>'
|
||||
. '<td><button type="submit" name="action" value="delete:' . $row['username'] . '">Löschen</button></td></tr>';
|
||||
}
|
||||
$content .= '</tbody>';
|
||||
$this->content['active_accounts'] = $content;
|
||||
}
|
||||
|
||||
protected function formAction(): void {
|
||||
$actionParams = explode(':', trim(filter_input(INPUT_POST, 'action', FILTER_SANITIZE_STRING)));
|
||||
switch ($actionParams[0]) {
|
||||
case 'activate':
|
||||
$this->activateAccount($actionParams[1]);
|
||||
break;
|
||||
case 'delete':
|
||||
$this->deleteAccount($actionParams[1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function activateAccount(string $accountName): void {
|
||||
$emailTo = 'Vorstand Förderverein AJS <foerderverein-ajs@gmx.de>';
|
||||
mysqli_begin_transaction($this->dbConnection);
|
||||
mysqli_query($this->dbConnection, sprintf('UPDATE `user` SET `active`=1 WHERE `username`="%s"', $accountName));
|
||||
mysqli_commit($this->dbConnection);
|
||||
$result = mysqli_query($this->dbConnection, 'SELECT * FROM user WHERE `username` = lower("' . trim(filter_input(INPUT_POST, 'username', FILTER_SANITIZE_ADD_SLASHES)) . '")');
|
||||
$user = mysqli_fetch_assoc($result);
|
||||
$message = 'Dein Account "' . $accountName . '" wurde aktiviert.';
|
||||
$headers = 'From: ' . $emailTo . "\r\n" .
|
||||
'Reply-To: ' . $emailTo . "\r\n" .
|
||||
'X-Mailer: PHP/' . phpversion();
|
||||
mail($user['email'], 'Zugang zu internem Bereich beantragt', $message, $headers);
|
||||
header('Location: accounts', true, 301);
|
||||
die();
|
||||
}
|
||||
|
||||
private function deleteAccount(string $accountName): void {
|
||||
$emailTo = 'Vorstand Förderverein AJS <foerderverein-ajs@gmx.de>';
|
||||
$result = mysqli_query($this->dbConnection, 'SELECT * FROM user WHERE `username` = lower("' . trim(filter_input(INPUT_POST, 'username', FILTER_SANITIZE_ADD_SLASHES)) . '")');
|
||||
$user = mysqli_fetch_assoc($result);
|
||||
mysqli_begin_transaction($this->dbConnection);
|
||||
mysqli_query($this->dbConnection, sprintf('UPDATE `user` SET `active`=-1 WHERE `username`="%s"', $accountName));
|
||||
mysqli_commit($this->dbConnection);
|
||||
$message = 'Der Account "' . $accountName . '" wurde als gelöscht markiert.';
|
||||
$headers = 'From: ' . $emailTo . "\r\n" .
|
||||
'Reply-To: ' . $emailTo . "\r\n" .
|
||||
'X-Mailer: PHP/' . phpversion();
|
||||
mail($user['email'], 'Zugang zu internem Bereich beantragt', $message, $headers);
|
||||
header('Location: accounts', true, 301);
|
||||
die();
|
||||
}
|
||||
}
|
||||
57
include/bulkmail.php
Normal file
57
include/bulkmail.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Bulkmail extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Betreff', 'type' => 'text', 'size' => 50, 'name' => 'subject', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'optional' => false],
|
||||
['label' => 'Text', 'type' => 'textarea', 'name' => 'body', 'combine_with_next_line' => false, 'filter' => FILTER_UNSAFE_RAW, 'optional' => false, 'rows' => 20, 'cols' => '60'],
|
||||
['label' => 'Signatur', 'type' => 'combobox', 'size' => 5, 'name' => 'signature', 'combine_with_next_line' => false,
|
||||
'values' => ['Persönliche Signatur', 'Vorstandssignatur'],
|
||||
],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Email an alle aktiven Mitglieder absenden';
|
||||
|
||||
protected function formAction(): void {
|
||||
$this->sendEmail($this->generateSubject(), $this->generateBody(), $this->generateSignature(filter_input(INPUT_POST, 'signature')));
|
||||
}
|
||||
|
||||
protected function generateSubject(): string {
|
||||
return filter_input(INPUT_POST, 'subject', FILTER_SANITIZE_STRING);
|
||||
}
|
||||
|
||||
protected function generateBody(): string {
|
||||
return preg_replace('/(<script(.*)\/script>|<iframe(.*)\/iframe>)/', '', filter_input(INPUT_POST, 'body'));
|
||||
}
|
||||
|
||||
protected function sendEmail(string $subject, string $body, string $signature): void {
|
||||
$mail = $this->initSmtpMailer();;
|
||||
$bccRecipients = $this->loadReceivers();
|
||||
try {
|
||||
$mail->setFrom('foerderverein-ajs@gmx.de', 'Förderverein der August-Jaspert-Schule');
|
||||
$mail->addReplyTo('foerderverein-ajs@gmx.de', 'Förderverein der August-Jaspert-Schule');
|
||||
$mail->addAddress('vorstand@fvajs.de', 'Vorstand des FVAJS');
|
||||
foreach ($bccRecipients as $recipient) {
|
||||
$mail->addBCC($recipient);
|
||||
}
|
||||
$this->sendMail($mail, $subject, $body, $signature);
|
||||
} catch (Exception $e) {
|
||||
$this->templateName = 'error_smtp';
|
||||
}
|
||||
$this->templateName = 'bulkmail_success';
|
||||
$this->content['recipients'] = implode('<br />', $bccRecipients);
|
||||
}
|
||||
|
||||
protected function loadReceivers(): array {
|
||||
$query = 'SELECT c.first_name, c.last_name, c.email, c.salt
|
||||
FROM clubmember c
|
||||
JOIN clubmember_status cs
|
||||
ON cs.id = c.membership_status
|
||||
WHERE cs.status_text = "Mitgliedschaft bestätigt"';
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
$recipientsList = [];
|
||||
while ($row = mysqli_fetch_assoc($dbResult)) {
|
||||
$recipientsList[] = $this->decode($row['email'], $row['salt']);
|
||||
}
|
||||
return $recipientsList;
|
||||
}
|
||||
}
|
||||
29
include/contact.php
Normal file
29
include/contact.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Contact extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Ihre Nachricht an uns:', 'type' => 'textarea', 'size' => 50, 'name' => 'message', 'combine_with_next_line' => false,
|
||||
'rows' => 14, 'cols' => 100],
|
||||
['label' => 'Ihr Name', 'type' => 'text', 'size' => 50, 'name' => 'sendername', 'combine_with_next_line' => false],
|
||||
['label' => 'Ihre Email-Adresse', 'type' => 'text', 'size' => 50, 'name' => 'senderemail', 'combine_with_next_line' => false],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Nachricht absenden';
|
||||
|
||||
protected function formAction(): void {
|
||||
$message = filter_input(INPUT_POST, 'message', FILTER_SANITIZE_STRING);
|
||||
$senderName = filter_input(INPUT_POST, 'sendername', FILTER_SANITIZE_STRING);
|
||||
$senderEmail = filter_input(INPUT_POST, 'senderemail', FILTER_SANITIZE_EMAIL);
|
||||
$noForm = trim($message) !== '';
|
||||
if (!$noForm) {
|
||||
$this->errors[] = 'Leider haben Sie keine Nachricht an uns hinterlassen. Bitte versuchen Sie es nochmal.';
|
||||
return;
|
||||
}
|
||||
$mail = $this->initSmtpMailer();
|
||||
$mail->setFrom(($senderEmail !== '') ? $senderEmail : 'foerderverein-ajs@gmx.de', ($senderName !== '') ? $senderName: 'Anonymer Sender');
|
||||
$mail->addReplyTo(($senderEmail !== '') ? $senderEmail : 'foerderverein-ajs@gmx.de', ($senderName !== '') ? $senderName: 'Anonymer Sender');
|
||||
$mail->addAddress('foerderverein-ajs@gmx.de', 'Vorstand Förderverein AJS');
|
||||
$this->sendMail($mail, 'Kontaktformular', $message, '');
|
||||
$this->templateName = 'message_success';
|
||||
}
|
||||
}
|
||||
17
include/deletedocument.php
Normal file
17
include/deletedocument.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Deletedocument extends Renderer {
|
||||
|
||||
public function render(): void {
|
||||
if ($_SESSION['userid'] === 0 && in_array($this->getScriptName() , $this->internalMenuItems, false)) {
|
||||
$this->templateName = 'login_error';
|
||||
parent::render();
|
||||
return;
|
||||
}
|
||||
$query = 'DELETE FROM `document` WHERE `title` = "' . filter_input(INPUT_POST, 'file', FILTER_SANITIZE_ADD_SLASHES) . '"';
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
@unlink('/var/shared/fvajs/' . filter_input(INPUT_GET, 'ts', FILTER_SANITIZE_STRING));
|
||||
echo '';
|
||||
}
|
||||
}
|
||||
72
include/documents.php
Normal file
72
include/documents.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Documents extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Dokumenttitel', 'type' => 'text', 'size' => 50, 'name' => 'documenttitle', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'optional' => false],
|
||||
['label' => 'Dokumentdatei', 'type' => 'file', 'size' => 50000, 'name' => 'document', 'combine_with_next_line' => false, 'optional' => true],
|
||||
['label' => 'Oder Datei erstellen aus', 'type' => 'textarea', 'cols' => 80, 'rows' => '15', 'name' => 'newtext', 'combine_with_next_line' => false, 'optional' => true],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Dokument hinzufügen';
|
||||
protected string $encType = 'multipart/form-data';
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function formAction(): void {
|
||||
$this->formCheckFields();
|
||||
if (count($this->errors) === 0) {
|
||||
$newFileName = $this->generateRandomString(64);
|
||||
$salt = $this->generateRandomString();
|
||||
$this->saveFile($newFileName, $salt);
|
||||
$query = sprintf('INSERT INTO ffajs.document
|
||||
(title, original_filename, local_filename, salt)
|
||||
VALUES("%s", "%s", "%s", "%s")', trim(filter_input(INPUT_POST, 'documenttitle', $this->formFields[0]['filter'])),
|
||||
$this->getOriginalFileName(),
|
||||
$newFileName, $salt);
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
}
|
||||
}
|
||||
|
||||
protected function formCheckFields(): bool {
|
||||
parent::formCheckFields();
|
||||
$result = mysqli_query($this->dbConnection, 'SELECT `id` FROM `document` WHERE `title` = "' . trim(filter_input(INPUT_POST, 'documenttitle', $this->formFields[0]['filter'])) . '"');
|
||||
if (mysqli_num_rows($result) > 0) {
|
||||
$this->errors['documenttitle'] = 'Der Titel existiert bereits';
|
||||
}
|
||||
return count($this->errors) === 0;
|
||||
}
|
||||
|
||||
protected function saveFile(string $newFileName, string $salt): void {
|
||||
if (trim(filter_input(INPUT_POST, 'newtext', FILTER_SANITIZE_STRING)) !== '') {
|
||||
$content = filter_input(INPUT_POST, 'newtext', FILTER_SANITIZE_STRING);
|
||||
} elseif ($_FILES['document']['tmp_name']) {
|
||||
$content = file_get_contents($_FILES['document']['tmp_name']);
|
||||
} else {
|
||||
$this->errors['newtext'] = 'Es muss eine Datei hochgeladen oder hier ein Text eingegeben werden.';
|
||||
return;
|
||||
}
|
||||
$this->saveFileLocal($newFileName, $content, $salt);
|
||||
}
|
||||
|
||||
protected function generateContent(): void {
|
||||
$result = mysqli_query($this->dbConnection, 'SELECT * FROM `document` ORDER BY `title`');
|
||||
$tableBody = '';
|
||||
while ($row = mysqli_fetch_assoc($result)) {
|
||||
$tableBody .= '<tr>';
|
||||
$tableBody .= '<td>' . $row['title'] . '</td>';
|
||||
$tableBody .= '<td>' . $row['original_filename'] . '</td>';
|
||||
$tableBody .= '<td><a href="download?file=' . $row['local_filename'] . '">Download</a></td>';
|
||||
$tableBody .= '<td><button type="button" name="delete" value="' . $row['local_filename'] . '">Löschen</button></td>';
|
||||
$tableBody .= '</tr>';
|
||||
}
|
||||
$this->content['documents'] = $tableBody;
|
||||
}
|
||||
|
||||
protected function getOriginalFileName(): string {
|
||||
return trim(filter_input(INPUT_POST, 'newtext', FILTER_SANITIZE_STRING)) !== ''
|
||||
? trim(filter_input(INPUT_POST, 'documenttitle', $this->formFields[0]['filter'])) . '.txt'
|
||||
: $_FILES['document']['name'];
|
||||
}
|
||||
}
|
||||
31
include/download.php
Normal file
31
include/download.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Download extends Renderer {
|
||||
|
||||
public function render(): void {
|
||||
if ($_SESSION['userid'] === 0 && in_array($this->getScriptName() , $this->internalMenuItems, false)) {
|
||||
$this->templateName = 'login_error';
|
||||
parent::render();
|
||||
return;
|
||||
}
|
||||
$params = $this->getUriParams();
|
||||
$query = sprintf('SELECT `original_filename`, `salt` FROM `document` WHERE `local_filename` = "%s"', $params['file']);
|
||||
$result = mysqli_query($this->dbConnection, $query);
|
||||
if (mysqli_num_rows($result) < 1) {
|
||||
die ('Datei nicht gefunden');
|
||||
}
|
||||
$row = mysqli_fetch_assoc($result);
|
||||
$encryptedFile = file_get_contents('/var/shared/fvajs/' . $params['file']);
|
||||
$decryptedFile = $this->decode($encryptedFile, $row['salt']);
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header("Cache-Control: no-cache, must-revalidate");
|
||||
header("Expires: 0");
|
||||
header('Content-Disposition: attachment; filename="' . $row['original_filename'] . '"');
|
||||
header('Content-Length: ' . strlen($decryptedFile));
|
||||
header('Pragma: public');
|
||||
flush();
|
||||
echo $decryptedFile;
|
||||
}
|
||||
}
|
||||
89
include/editmember.php
Normal file
89
include/editmember.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Editmember extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Nachname', 'type' => 'text', 'size' => 50, 'name' => 'lastname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'last_name', 'optional' => false],
|
||||
['label' => 'Vorname', 'type' => 'text', 'size' => 50, 'name' => 'firstname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'first_name', 'optional' => false],
|
||||
['label' => 'Straße', 'type' => 'text', 'size' => 50, 'name' => 'streetname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'street', 'optional' => false],
|
||||
['label' => 'Plz', 'type' => 'text', 'size' => 5, 'name' => 'zip', 'combine_with_next_line' => true, 'regex' => '/^([0-9]{5})$/', 'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'zip', 'optional' => false],
|
||||
['label' => 'Ort', 'type' => 'text', 'size' => 40, 'name' => 'town', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'town', 'optional' => false],
|
||||
['label' => 'Birthday', 'type' => 'date', 'size' => 50, 'name' => 'birthdate', 'combine_with_next_line' => false, 'regex' => '/^((19|20)([0-9]){2}-[0-9]{2})-([0-9]{2})$/', 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'birthdate', 'optional' => false],
|
||||
['label' => 'Phone', 'type' => 'text', 'size' => 50, 'name' => 'phone', 'combine_with_next_line' => false, '/^0([0-9]{2,6})([ ]{0,1})([-\/]{0,1})([ ]{0,1})([0-9 ]{4,25})$/', 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'phone', 'optional' => false],
|
||||
['label' => 'Email', 'type' => 'email', 'size' => 50, 'name' => 'email', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_EMAIL, 'dbfield' => 'email', 'optional' => true],
|
||||
['label' => 'Name des Kindes', 'type' => 'text', 'size' => 50, 'name' => 'childname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'child_name', 'optional' => true],
|
||||
['label' => 'Straße des Kindes', 'type' => 'text', 'size' => 50, 'name' => 'childstreet', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'child_street', 'optional' => true],
|
||||
['label' => 'Gewählter Beitrag', 'type' => 'number', 'size' => 50, 'name' => 'subscription', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'subscription', 'optional' => false],
|
||||
['label' => 'Geldinstitut', 'type' => 'text', 'size' => 50, 'name' => 'bankname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'bank_name', 'optional' => true],
|
||||
['label' => 'IBAN', 'type' => 'text', 'size' => 50, 'name' => 'iban', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'iban', 'optional' => true],
|
||||
['label' => 'BIC', 'type' => 'text', 'size' => 50, 'name' => 'bic', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'bic', 'optional' => true],
|
||||
['label' => 'Kontoinhaber', 'type' => 'text', 'size' => 50, 'name' => 'accountmember', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'account_member_name', 'optional' => true],
|
||||
['label' => 'Mitgliedsstatus', 'type' => 'dbselect', 'size' => 0, 'name' => 'status', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'membership_status',
|
||||
'sourcedb' => 'clubmember_status', 'optionfield' => 'status_text', 'encryption' => false],
|
||||
['label' => 'Position im Verein', 'type' => 'dbselect', 'size' => 0, 'name' => 'position', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'position_id',
|
||||
'sourcedb' => 'clubmember_position', 'optionfield' => 'description', 'encryption' => false, 'with_null_field' => true],
|
||||
['label' => 'Online-Account', 'type' => 'dbselect', 'size' => 0, 'name' => 'user_id', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'user_id',
|
||||
'sourcedb' => 'user', 'optionfield' => 'username', 'encryption' => false, 'with_null_field' => true],
|
||||
];
|
||||
protected string $dbTable = 'clubmember';
|
||||
protected bool $dbGenerateSaltField = true;
|
||||
protected bool $dbUpdate = true;
|
||||
protected string $formSendButtonLabel = 'Änderungen speichern';
|
||||
protected bool $saveAllFields = true;
|
||||
|
||||
public function __construct(?string $templateName = null) {
|
||||
parent::__construct($templateName);
|
||||
$id = $this->getUriParams()['id'];
|
||||
$this->loadUserData($id);
|
||||
}
|
||||
|
||||
protected function loadUserData(string $id): void {
|
||||
$query = sprintf("SELECT c.first_name as firstname, c.last_name as lastname, c.street as streetname, c.zip, c.town, c.birthdate, c.phone, c.email, "
|
||||
. " c.child_name as childname, c.child_street as childstreet, c.subscription, c.bank_name as bankname, c.iban , c.bic , "
|
||||
. " c.account_member_name as accountmember, c.membership_status as status, c.position_id as position, c.user_id as user_id, c.salt "
|
||||
. "FROM clubmember c "
|
||||
. "WHERE c.id = %d", $id);
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
if (mysqli_num_rows($dbResult) === 0) {
|
||||
$this->templateName = 'notfound_error';
|
||||
return;
|
||||
}
|
||||
$line = mysqli_fetch_assoc($dbResult);
|
||||
$salt = $line['salt'];
|
||||
array_walk($line, function(&$item, $key) use ($salt) {
|
||||
if (!isset($item)) {
|
||||
return;
|
||||
} elseif ($this->fieldHasToBeEncrypted($key)) {
|
||||
$item = $this->decode($item, $salt);
|
||||
}
|
||||
});
|
||||
$this->predefines = $line;
|
||||
}
|
||||
|
||||
protected function formAction(): void {
|
||||
if (!$this->formCheckFields()) {
|
||||
return;
|
||||
}
|
||||
$saltQuery = "SELECT id, membership_status, salt FROM clubmember c WHERE id=" . $this->getUriParams()['id'];
|
||||
$dbResult = mysqli_query($this->dbConnection, $saltQuery);
|
||||
if (!$dbResult) {
|
||||
return;
|
||||
}
|
||||
$oldDataRow = mysqli_fetch_assoc($dbResult);
|
||||
$this->salt = $oldDataRow['salt'];
|
||||
$this->saveToDb();
|
||||
if (filter_input(INPUT_POST, 'status', FILTER_SANITIZE_NUMBER_INT) != $oldDataRow['membership_status']) {
|
||||
$this->saveMembershipStatusChangeHistory($oldDataRow['id'], $oldDataRow['membership_status'],
|
||||
filter_input(INPUT_POST, 'status', FILTER_SANITIZE_NUMBER_INT));
|
||||
}
|
||||
$this->cleanFields = false;
|
||||
$this->messages[] = 'Mitglied erfolgreich bearbeitet.';
|
||||
}
|
||||
|
||||
protected function saveMembershipStatusChangeHistory(string $clubmemberId, string $oldStatus, string $newStatus): void {
|
||||
$query = sprintf("INSERT INTO ffajs.clubmember_status_history (clubmember_id, changer_id, old_status_id, new_status_id, change_timestamp) "
|
||||
. "VALUES(%d, %d, %d, %d, now()); ",
|
||||
$clubmemberId, $_SESSION['userid'], $oldStatus, $newStatus);
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
}
|
||||
}
|
||||
72
include/emailinbox.php
Normal file
72
include/emailinbox.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
require 'renderer.php';
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
class Emailinbox extends Renderer {
|
||||
|
||||
public function __construct(?string $templateName = null) {
|
||||
parent::__construct();
|
||||
if (!$this->connectToImap()) {
|
||||
$this->templateName = 'imaperror';
|
||||
}
|
||||
}
|
||||
|
||||
protected function readEmailHeaders(): array {
|
||||
$cleanedHeaders = [];
|
||||
try {
|
||||
$mailsIds = $this->mbox->searchMailbox('ALL');
|
||||
} catch(PhpImap\Exceptions\ConnectionException $ex) {
|
||||
echo "IMAP connection failed: " . implode(",", $ex->getErrors('all'));
|
||||
die();
|
||||
}
|
||||
|
||||
if(!$mailsIds) {
|
||||
die('Mailbox is empty');
|
||||
}
|
||||
$headers = $this->mbox->getMailsInfo($mailsIds);
|
||||
foreach ($headers as $header) {
|
||||
try {
|
||||
$cleanedHeaders[trim($header->msgno)] = [
|
||||
'title' => $header->subject,
|
||||
'date' => \DateTime::createFromFormat('D, d M Y H:i:s O', str_replace(' (CET)', '', $header->date))->setTimezone(new DateTimeZone('Europe/Berlin')),
|
||||
'from' => $header->from,
|
||||
'unread' => !$header->seen,
|
||||
];
|
||||
} catch (\exception $err) {
|
||||
}
|
||||
}
|
||||
return $cleanedHeaders;
|
||||
}
|
||||
|
||||
protected function getDateObjectFromString(string $dateString) {
|
||||
$date = DateTime::createFromFormat(DateTimeInterface::RFC1123, $dateString);
|
||||
if (!$date) {
|
||||
$date = DateTime::createFromFormat(DateTimeInterface::RFC1123, substr($dateString, 0, -6));
|
||||
}
|
||||
if (!$date) {
|
||||
$date = DateTime::createFromFormat('d M Y H:i:s O', $dateString);
|
||||
}
|
||||
if (!$date) {
|
||||
echo $dateString;
|
||||
}
|
||||
return $date;
|
||||
}
|
||||
|
||||
protected function generateContent(): void {
|
||||
$headers = $this->readEmailHeaders();
|
||||
uasort($headers, ['Emailinbox', 'compareDateTimes']);
|
||||
array_walk($headers, function(&$item, $key) {
|
||||
$newItem = '<tr>';
|
||||
$newItem .= '<td style="white-space:nowrap">' . ($item['date'] === false ? '' : $item['date']->format('d.m.Y H:i:s')) . '</td>';
|
||||
$newItem .= '<td><a href="mail?uid=' . $key . '">' . ($item['unread'] === 'U' ? '<b>' : '') . $item['title'] . ($item['unread'] === 'u' ? '</b>' : '') . '</td>';
|
||||
$newItem .= '<td>' . $item['from'] . '</td>';
|
||||
$newItem .= '</tr>';
|
||||
$item = $newItem;
|
||||
});
|
||||
$this->content['mails'] = implode('', $headers);
|
||||
}
|
||||
|
||||
protected function compareDateTimes($item1, $item2): int {
|
||||
return $item2['date'] <=> $item1['date'];
|
||||
}
|
||||
}
|
||||
7
include/footer.php
Normal file
7
include/footer.php
Normal file
@@ -0,0 +1,7 @@
|
||||
</main>
|
||||
<footer>
|
||||
<span class="footer-copyright">(c) 2022 Förderverein August-Jaspert-Schule e.V.</span>
|
||||
<a href="imprint.php" class="footer-imprint">Impressum</span>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
13
include/header.php
Normal file
13
include/header.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Förderverein August-Jaspert-Schule e.V.</title>
|
||||
<link rel="stylesheet" type="text/css" href="style/main.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Förderverein August-Jaspert-Schule e.V.</h1>
|
||||
</header>
|
||||
<?php include 'include/menu.php'; ?>
|
||||
<main>
|
||||
31
include/login.php
Normal file
31
include/login.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Login extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Benutzername', 'type' => 'text', 'size' => 50, 'name' => 'username', 'combine_with_next_line' => false],
|
||||
['label' => 'Paßwort', 'type' => 'password', 'size' => 50, 'name' => 'password', 'combine_with_next_line' => false],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Einloggen';
|
||||
|
||||
protected function formAction(): void {
|
||||
$this->userId = 0;
|
||||
$result = mysqli_query($this->dbConnection, 'SELECT * FROM user WHERE `username` = lower("' . trim(filter_input(INPUT_POST, 'username', FILTER_SANITIZE_ADD_SLASHES)) . '")');
|
||||
if ($result->num_rows !== 1) {
|
||||
$this->errors[] = 'Benutzer und/oder Paßwort falsch';
|
||||
return;
|
||||
}
|
||||
$user = $result->fetch_assoc();
|
||||
if (!password_verify(filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING), $user['password'])) {
|
||||
$this->errors[] = 'Benutzer und/oder Paßwort falsch';
|
||||
return;
|
||||
}
|
||||
if ($user['active'] !== '1') {
|
||||
$this->errors[] = 'Dein Zugang ist noch nicht freigeschaltet.';
|
||||
return;
|
||||
}
|
||||
$_SESSION['userid'] = $user['id'];
|
||||
header('Location: accounts', true, 301);
|
||||
die();
|
||||
}
|
||||
}
|
||||
11
include/logout.php
Normal file
11
include/logout.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Logout extends Renderer {
|
||||
public function __construct(?string $templateName = null) {
|
||||
session_start();
|
||||
$_SESSION['userid'] = 0;
|
||||
session_write_close();
|
||||
header('Location: index', true, 301);
|
||||
}
|
||||
}
|
||||
34
include/mail.php
Normal file
34
include/mail.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
require 'vendor/autoload.php';
|
||||
require 'mailhandling.php';
|
||||
|
||||
class Mail extends Mailhandling {
|
||||
// protected $mbox = null;
|
||||
protected $uid = 0;
|
||||
|
||||
public function __construct(?string $templateName = null) {
|
||||
parent::__construct();
|
||||
if (!$this->connectToImap()) {
|
||||
$this->templateName = 'imaperror';
|
||||
return;
|
||||
}
|
||||
$this->uid = $this->getUriParams()['uid'];
|
||||
$this->content['uid'] = $this->uid;
|
||||
}
|
||||
|
||||
protected function generateContent(): void {
|
||||
$messageStructure = imap_fetchstructure($this->mbox, $this->uid);
|
||||
$this->fetchEmailHeader($this->content);
|
||||
$this->fetchEmailBody($messageStructure, $this->content, 'INBOX', FT_PEEK);
|
||||
$this->renderAttachments($messageStructure);
|
||||
}
|
||||
|
||||
protected function renderAttachments($messageStructure): void {
|
||||
$attachments = $this->getAttachments($messageStructure);
|
||||
$contentArray = [];
|
||||
foreach ($attachments as $attachment) {
|
||||
$contentArray[] = $attachment['filename'];
|
||||
}
|
||||
$this->content['attachments'] = implode('<br>', $contentArray);
|
||||
}
|
||||
}
|
||||
82
include/mailhandling.php
Normal file
82
include/mailhandling.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
require 'renderer.php';
|
||||
|
||||
class Mailhandling extends Renderer {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
if (!$this->connectToImap()) {
|
||||
$this->templateName = 'imaperror';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected function fetchEmailHeader(array &$content): void {
|
||||
$header = imap_headerinfo($this->mbox, $this->uid);
|
||||
$content['sender'] = imap_utf8($header->fromaddress);
|
||||
$content['receiver'] = imap_utf8($header->toaddress);
|
||||
$content['subject'] = imap_utf8($header->subject);
|
||||
$content['senddate'] = date('d.m.Y H:i:s', strtotime($header->date));
|
||||
}
|
||||
|
||||
protected function fetchEmailBody($messageStructure, array &$content): void {
|
||||
$message = imap_fetchbody($this->mbox, $this->uid, 1.1, FT_PEEK);
|
||||
if($message == '') {
|
||||
$message = imap_fetchbody($this->mbox, $this->uid, 1, FT_PEEK);
|
||||
}
|
||||
$decodedMessage = quoted_printable_decode($message);
|
||||
if (isset($messageStructure->parts) && isset($messageStructure->parts[1]) && isset($messageStructure->parts[1]->parameters)
|
||||
&& isset($messageStructure->parts[1]->parameters) && is_array($messageStructure->parts[1]->parameters) && isset($messageStructure->parts[1]->parameters[0]->value) && strtolower($messageStructure->parts[1]->parameters[0]->value) != 'utf-8') {
|
||||
$decodedMessage = utf8_encode($decodedMessage);
|
||||
}
|
||||
$content['emailbody'] = nl2br($decodedMessage);
|
||||
}
|
||||
|
||||
|
||||
protected function getAttachments($structure): array {
|
||||
$attachments = [];
|
||||
if(isset($structure->parts) && count($structure->parts)) {
|
||||
for($i = 0; $i < count($structure->parts); $i++) {
|
||||
$attachments[$i] = [
|
||||
'is_attachment' => false,
|
||||
'filename' => '',
|
||||
'name' => '',
|
||||
'attachment' => ''];
|
||||
|
||||
if($structure->parts[$i]->ifdparameters) {
|
||||
foreach($structure->parts[$i]->dparameters as $object) {
|
||||
if(strtolower($object->attribute) == 'filename') {
|
||||
$attachments[$i]['is_attachment'] = true;
|
||||
$attachments[$i]['filename'] = $object->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($structure->parts[$i]->ifparameters) {
|
||||
foreach($structure->parts[$i]->parameters as $object) {
|
||||
if(strtolower($object->attribute) == 'name') {
|
||||
$attachments[$i]['is_attachment'] = true;
|
||||
$attachments[$i]['name'] = $object->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($attachments[$i]['is_attachment']) {
|
||||
$attachments[$i]['attachment'] = imap_fetchbody($this->mbox, $this->uid, $i+1);
|
||||
if($structure->parts[$i]->encoding == 3) { // 3 = BASE64
|
||||
$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
|
||||
}
|
||||
elseif($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
|
||||
$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
|
||||
}
|
||||
}
|
||||
if ($attachments[$i]['is_attachment']) {
|
||||
}
|
||||
}
|
||||
}
|
||||
$realAttachments = array_filter($attachments, function($attachment) {
|
||||
return $attachment['is_attachment'];
|
||||
});
|
||||
return $realAttachments;
|
||||
}
|
||||
}
|
||||
30
include/members.php
Normal file
30
include/members.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Members extends Renderer {
|
||||
public function __construct(?string $templateName = null) {
|
||||
parent::__construct($templateName);
|
||||
$result = mysqli_query($this->dbConnection,
|
||||
'SELECT c.*, cs.`status_text`, (SELECT ph.`payment_date` FROM `paying_history` ph WHERE ph.`clubmember_id` = c.`id` ORDER BY `payment_date` DESC LIMIT 1) as last_payment '
|
||||
. 'FROM `clubmember` c '
|
||||
. 'JOIN `clubmember_status` cs '
|
||||
. ' ON cs.`id` = c.`membership_status` '
|
||||
. 'WHERE cs.`status_text` NOT IN ("Mitgliedschaft abgelehnt", "Mitgliedschaft gekündigt") '
|
||||
. 'ORDER BY c.`last_name`, c.`first_name`');
|
||||
$tableBody = '<tbody>';
|
||||
while ($row = mysqli_fetch_assoc($result)) {
|
||||
$tableBody .= '<tr>'
|
||||
. '<td>' . $row['id'] . '</td>'
|
||||
. '<td>' . $this->decode($row['last_name'], $row['salt']) . ', ' . $this->decode($row['first_name'], $row['salt']) . '</td>'
|
||||
. '<td>' . $this->decode($row['email'], $row['salt']) . '</td>'
|
||||
. '<td>' . $row['last_payment'] . '</td>'
|
||||
. '<td>' . $row['membership_start'] . '</td>'
|
||||
. '<td>' . $row['status_text'] . '</td>'
|
||||
. '<td><a href="editmember?id=' . $row['id'] . '">Bearbeiten</a> '
|
||||
. '<a href="payings?id=' . $row['id'] . '">Zahlungen</a></td>'
|
||||
. '</tr>';
|
||||
}
|
||||
$tableBody .= '</tbody>';
|
||||
$this->content['memberlist'] = $tableBody;
|
||||
}
|
||||
}
|
||||
125
include/membership.php
Normal file
125
include/membership.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Membership extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Vorname', 'type' => 'text', 'size' => 50, 'name' => 'firstname', 'combine_with_next_line' => false],
|
||||
['label' => 'Nachname', 'type' => 'text', 'size' => 50, 'name' => 'lastname', 'combine_with_next_line' => false],
|
||||
['label' => 'Straße (mit Hausnummer)', 'type' => 'text', 'size' => 50, 'name' => 'street', 'combine_with_next_line' => false],
|
||||
['label' => 'Plz', 'type' => 'text', 'size' => 5, 'name' => 'zip', 'combine_with_next_line' => true],
|
||||
['label' => 'Ort', 'type' => 'text', 'size' => 40, 'name' => 'town', 'combine_with_next_line' => false],
|
||||
['label' => 'Geburtsdatum', 'type' => 'date', 'size' => 50, 'name' => 'birthdate', 'combine_with_next_line' => false],
|
||||
['label' => 'Telefon-Nr.', 'type' => 'text', 'size' => 50, 'name' => 'phone', 'combine_with_next_line' => false],
|
||||
['label' => 'Email-Adresse', 'type' => 'email', 'size' => 50, 'name' => 'email', 'combine_with_next_line' => false],
|
||||
['label' => 'Name des Kindes (Optional)', 'type' => 'text', 'size' => 50, 'name' => 'childname', 'combine_with_next_line' => false],
|
||||
['label' => 'Straße des Kindes (Optional)', 'type' => 'text', 'size' => 50, 'name' => 'childstreet', 'combine_with_next_line' => false],
|
||||
['label' => 'Gewählter Jahresbeitrag', 'type' => 'combobox', 'size' => 50, 'name' => 'payheight', 'combine_with_next_line' => false,
|
||||
'values' => ['12 €', '25 €', '50 €', '60 €', '100 €', 'Selbst wählen'], 'default' => '25 €',],
|
||||
['label' => 'Höhe des freien Beitrags (Optional)', 'type' => 'number', 'size' => 50, 'name' => 'freepayheight', 'value' => 0, 'combine_with_next_line' => false],
|
||||
['label' => 'Ich stimme der elektronischen Verarbeitung und Speicherung meiner Daten zu', 'type' => 'checkbox', 'size' => 1, 'name' => 'accept_electronical_usage', 'value' => 1],
|
||||
['type' => 'spacer', 'value' => ''],
|
||||
['type' => 'infotext', 'label' => '<h3>(Optional) Bankeinzugsinformationen</h3>'],
|
||||
['label' => 'Geldinstitut', 'type' => 'text', 'size' => 50, 'name' => 'bankname', 'combine_with_next_line' => false],
|
||||
['label' => 'IBAN', 'type' => 'text', 'size' => 50, 'name' => 'iban', 'combine_with_next_line' => false],
|
||||
['label' => 'BIC', 'type' => 'text', 'size' => 50, 'name' => 'bic', 'combine_with_next_line' => false],
|
||||
['label' => 'Kontoinhaber', 'type' => 'text', 'size' => 50, 'name' => 'accountmembername', 'combine_with_next_line' => false],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Mitgliedschaftsantrag vorausgefüllt beantragen';
|
||||
|
||||
protected function formAction(): void {
|
||||
$formData['firstname'] = trim(filter_input(INPUT_POST, 'firstname', FILTER_SANITIZE_STRING));
|
||||
$formData['lastname'] = trim(filter_input(INPUT_POST, 'lastname', FILTER_SANITIZE_STRING));
|
||||
$formData['street'] = trim(filter_input(INPUT_POST, 'street', FILTER_SANITIZE_STRING));
|
||||
$formData['zip'] = trim(filter_input(INPUT_POST, 'zip', FILTER_SANITIZE_STRING));
|
||||
$formData['town'] = trim(filter_input(INPUT_POST, 'town', FILTER_SANITIZE_STRING));
|
||||
$formData['birthDate'] = trim(filter_input(INPUT_POST, 'birthdate', FILTER_SANITIZE_STRING));
|
||||
$formData['phoneNumber'] = trim(filter_input(INPUT_POST, 'phone', FILTER_SANITIZE_STRING));
|
||||
$formData['email'] = trim(filter_input(INPUT_POST, 'email', FILTER_SANITIZE_STRING));
|
||||
$formData['childName'] = trim(filter_input(INPUT_POST, 'childname', FILTER_SANITIZE_STRING));
|
||||
$formData['childStreet'] = trim(filter_input(INPUT_POST, 'childstreet', FILTER_SANITIZE_STRING));
|
||||
$formData['payHeight'] = trim(filter_input(INPUT_POST, 'payheight', FILTER_SANITIZE_STRING));
|
||||
$formData['bankname'] = trim(filter_input(INPUT_POST, 'bankname', FILTER_SANITIZE_STRING));
|
||||
$formData['iban'] = trim(filter_input(INPUT_POST, 'iban', FILTER_SANITIZE_STRING));
|
||||
$formData['bic'] = trim(filter_input(INPUT_POST, 'bic', FILTER_SANITIZE_STRING));
|
||||
$formData['agreedElectronicalHandling'] = intval(filter_input(INPUT_POST, 'accept_electronical_usage', FILTER_SANITIZE_NUMBER_INT));
|
||||
$formData['accountmembername'] = trim(filter_input(INPUT_POST, 'accountmembername', FILTER_SANITIZE_STRING));
|
||||
$this->checkFormData($formData);
|
||||
$this->saveNewMember($formData);
|
||||
$this->sendEmail($formData);
|
||||
}
|
||||
|
||||
protected function checkFormData(array $formData): void {
|
||||
if ($formData['payHeight'] === 'Selbst wählen') {
|
||||
$formData['payHeight'] = filter_input(INPUT_POST, 'freepayheight', FILTER_SANITIZE_NUMBER_INT);
|
||||
}
|
||||
if (!preg_match('/^([0-9]{5})$/', $formData['zip'])) {
|
||||
$this->errors['zip'] = 'Die Postleitzahl ist nicht korrekt';
|
||||
}
|
||||
if (!preg_match('/^((19|20)([0-9]){2}-[0-9]{2})-([0-9]{2})$/', $formData['birthDate']) || (DateTimeImmutable::createFromFormat('Y-m-d', $formData['birthDate']))->getTimestamp() > time()) {
|
||||
$this->errors['birthdate'] = 'Das eingegebene Geburtsdatum ist nicht korrekt';
|
||||
}
|
||||
if (!preg_match('/^0([0-9]{2,6})([ ]{0,1})([-\/]{0,1})([ ]{0,1})([0-9 ]{4,25})$/', $formData['phoneNumber'])) {
|
||||
$this->errors['phone'] = 'Die Telefonnummer ist nicht korrekt';
|
||||
}
|
||||
if (!filter_var($formData['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$this->errors['email'] = 'Die Email-Adresse ist inkorrekt';
|
||||
}
|
||||
if ($formData['agreedElectronicalHandling'] !== 1) {
|
||||
$this->errors['accept_electronical_usage'] = 'Für die Online-Registrierung müssen Sie der elektronischen Verarbeitung zustimmen';
|
||||
}
|
||||
}
|
||||
|
||||
protected function saveNewMember(array $formData): void {
|
||||
$salt = $this->generateRandomString();
|
||||
$query = sprintf("INSERT INTO ffajs.clubmember( "
|
||||
. " first_name, last_name, street, zip, town, "
|
||||
. " birthdate, phone, email, child_name, child_street, "
|
||||
. " subscription, bank_name, iban, bic, account_member_name, "
|
||||
. " membership_status, salt) "
|
||||
. "VALUES('%s', '%s', '%s', '%s', '%s', "
|
||||
. " '%s', '%s', '%s', '%s', '%s', "
|
||||
. " '%s', '%s', '%s', '%s', '%s', "
|
||||
. " %d, '%s') ",
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'firstname', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'lastname', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'street', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'zip', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'town', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'birthDate', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'phoneNumber', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'email', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'childName', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'childStreet', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'payHeight', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'bankname', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'iban', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'bic', $salt),
|
||||
$this->getDbEncryptedValueIfNeeded($formData, 'accountmembername', $salt),
|
||||
1,
|
||||
$salt);
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
}
|
||||
|
||||
protected function sendEmail(array $formData): void {
|
||||
$noForm = count($this->errors) === 0;
|
||||
if ($noForm) {
|
||||
$data = ['Name' => $formData['firstname'], $formData['lastname'], 'Strasse' => $formData['street'], 'Ort' => $formData['zip'] . ' ' . $formData['town'],
|
||||
'Geburtstag' => $formData['birthDate'], 'Telefon' => $formData['phoneNumber'], 'Email' => $formData['email'],
|
||||
'Name des Kindes' => $formData['childName'], 'Straße des Kindes' => $formData['childStreet'],
|
||||
'Gewünschter Mitgliedsbeitrag' => $formData['payHeight'], 'Geldinstitut' => $formData['bankname'],
|
||||
'IBAN' => $formData['iban'], 'BIC' => $formData['bic'], 'Kontoinhaber' => $formData['accountmembername'],
|
||||
'Elektronischer Verarbeitung zugestimmg' => $formData['agreedElectronicalHandling']
|
||||
];
|
||||
$mail = $this->initSmtpMailer();
|
||||
$mail->setFrom($formData['email'], $formData['firstname'] . ' ' . $formData['lastname']);
|
||||
$mail->addReplyTo($formData['email'], $formData['firstname'] . ' ' . $formData['lastname']);
|
||||
$mail->addAddress('foerderverein-ajs@gmx.de', 'Vorstand Förderverein AJS');
|
||||
$message = '';
|
||||
foreach ($data as $field => $value) {
|
||||
$message .= $field . ': ' . $value . "\n";
|
||||
}
|
||||
$this->sendMail($mail, 'Mitgliedsantrag', $message, '');
|
||||
$this->templateName = 'membership_success';
|
||||
}
|
||||
}
|
||||
}
|
||||
38
include/newmember.php
Normal file
38
include/newmember.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Newmember extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Nachname', 'type' => 'text', 'size' => 50, 'name' => 'lastname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'last_name', 'optional' => false],
|
||||
['label' => 'Vorname', 'type' => 'text', 'size' => 50, 'name' => 'firstname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'first_name', 'optional' => false],
|
||||
['label' => 'Straße', 'type' => 'text', 'size' => 50, 'name' => 'streetname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'street', 'optional' => false],
|
||||
['label' => 'Plz', 'type' => 'text', 'size' => 5, 'name' => 'zip', 'combine_with_next_line' => true, 'regex' => '/^([0-9]{5})$/', 'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'zip', 'optional' => false],
|
||||
['label' => 'Ort', 'type' => 'text', 'size' => 40, 'name' => 'town', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'town', 'optional' => false],
|
||||
['label' => 'Birthday', 'type' => 'date', 'size' => 50, 'name' => 'birthdate', 'combine_with_next_line' => false, 'regex' => '/^((19|20)([0-9]){2}-[0-9]{2})-([0-9]{2})$/', 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'birthdate', 'optional' => false],
|
||||
['label' => 'Phone', 'type' => 'text', 'size' => 50, 'name' => 'phone', 'combine_with_next_line' => false, '/^0([0-9]{2,6})([ ]{0,1})([-\/]{0,1})([ ]{0,1})([0-9 ]{4,25})$/', 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'phone', 'optional' => false],
|
||||
['label' => 'Email', 'type' => 'email', 'size' => 50, 'name' => 'email', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_EMAIL, 'dbfield' => 'email', 'optional' => true],
|
||||
['label' => 'Name des Kindes', 'type' => 'text', 'size' => 50, 'name' => 'childname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'child_name', 'optional' => true],
|
||||
['label' => 'Straße des Kindes', 'type' => 'text', 'size' => 50, 'name' => 'childstreet', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'child_street', 'optional' => true],
|
||||
['label' => 'Gewählter Beitrag', 'type' => 'number', 'size' => 50, 'name' => 'subscription', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'subscription', 'optional' => false],
|
||||
['label' => 'Geldinstitut', 'type' => 'text', 'size' => 50, 'name' => 'bankname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'bank_name', 'optional' => true],
|
||||
['label' => 'IBAN', 'type' => 'text', 'size' => 50, 'name' => 'iban', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'iban', 'optional' => true],
|
||||
['label' => 'BIC', 'type' => 'text', 'size' => 50, 'name' => 'bic', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'bic', 'optional' => true],
|
||||
['label' => 'Kontoinhaber', 'type' => 'text', 'size' => 50, 'name' => 'accountmember', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'account_member_name', 'optional' => true],
|
||||
['label' => 'Mitgliedsstatus', 'type' => 'dbselect', 'size' => 0, 'name' => 'status', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'membership_status',
|
||||
'sourcedb' => 'clubmember_status', 'optionfield' => 'status_text', 'encryption' => false],
|
||||
['label' => 'Position im Verein', 'type' => 'dbselect', 'size' => 0, 'name' => 'position', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'position_id',
|
||||
'sourcedb' => 'clubmember_position', 'optionfield' => 'description', 'encryption' => false, 'with_null_field' => true],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Eintragen';
|
||||
protected string $dbTable = 'clubmember';
|
||||
protected bool $dbGenerateSaltField = true;
|
||||
|
||||
protected function formAction(): void {
|
||||
if (!$this->formCheckFields()) {
|
||||
return;
|
||||
}
|
||||
$this->saveToDb();
|
||||
$this->cleanFields = true;
|
||||
$this->messages[] = 'Mitglied erfolgreich eingetragen.';
|
||||
}
|
||||
}
|
||||
40
include/newpassword.php
Normal file
40
include/newpassword.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Newpassword extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Email-Adresse', 'type' => 'email', 'size' => 50, 'name' => 'email', 'combine_with_next_line' => false],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Login-Name zusenden und Paßwort-Reset anfordern';
|
||||
|
||||
protected function formAction(): void {
|
||||
$email = trim(filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL));
|
||||
$query = 'SELECT id, realname, email, username, salt FROM user';
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
while ($row = mysqli_fetch_assoc($dbResult)) {
|
||||
if ($email === $this->decode($row['email'], $row['salt'])) {
|
||||
$salt = $row['salt'];
|
||||
$this->sendResetEmail($row['id'], $row['username'], $this->decode($row['email'], $salt), $this->decode($row['realname'], $salt));
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->templateName = 'newpassword_done';
|
||||
}
|
||||
|
||||
protected function sendResetEmail(int $id, string $username, string $emailAddress, string $realName) {
|
||||
$resetId = $this->generateRandomString();
|
||||
$query = 'update user set recreate_db_hash="' . $resetId . '" where id=' . $id;
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
$mail = $this->initSmtpMailer();
|
||||
$mail->setFrom('foerderverein-ajs@gmx.de', 'Förderverein der August-Jaspert-Schule');
|
||||
$mail->addReplyTo('foerderverein-ajs@gmx.de', 'Förderverein der August-Jaspert-Schule');
|
||||
$mail->addAddress($emailAddress, $realName);
|
||||
$this->sendMail($mail, 'Passwort zurücksetzen für ' . filter_input(INPUT_SERVER, 'SERVER_NAME'), $this->getEmailBody($username, $realName, $resetId), $this->generateSignature(''));
|
||||
}
|
||||
|
||||
protected function getEmailBody(string $username, string $realname, string $code) {
|
||||
$rawBody = file_get_contents('templates/resetaccountmailbody.html');
|
||||
return str_replace(['{{name}}', '{{username}}', '{{server}}', '{{code}}', '{{protocol}}'],
|
||||
[$realname, $username, filter_input(INPUT_SERVER, 'SERVER_NAME'), $code, (filter_input(INPUT_SERVER, 'HTTPS') ? 's' : '') ], $rawBody);
|
||||
}
|
||||
}
|
||||
76
include/payings.php
Normal file
76
include/payings.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Payings extends Renderer {
|
||||
// ['label' => 'Nachname', 'type' => 'text', 'size' => 50, 'name' => 'lastname', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'last_name', 'optional' => false],
|
||||
protected array $formFields = [
|
||||
['label' => 'Datum', 'type' => 'date', 'size' => 10, 'name' => 'date', 'combine_with_next_line' => false,
|
||||
'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'payment_date', 'optional' => false, 'encryption' => false],
|
||||
['label' => 'Betrag', 'type' => 'number', 'size' => 10, 'name' => 'value', 'combine_with_next_line' => false,
|
||||
'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'payment_height', 'optional' => false, 'encryption' => false],
|
||||
['label' => '', 'type' => 'hidden', 'size'=> 1, 'name' => 'clubmember-id', 'value' => 0, 'combine_with_next_line' => false,
|
||||
'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'clubmember_id', 'optional' => false, 'encryption' => false],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Zahlung eintragen';
|
||||
protected string $dbTable = 'paying_history';
|
||||
|
||||
public function __construct(?string $templateName = null) {
|
||||
parent::__construct($templateName);
|
||||
$id = $this->getUriParams()['id'];
|
||||
$this->formFields[2]['value'] = $id;
|
||||
$this->loadUserData($id);
|
||||
}
|
||||
|
||||
protected function loadUserData(string $id): void {
|
||||
$query = sprintf("SELECT c.first_name, c.last_name, c.salt "
|
||||
. "FROM clubmember c "
|
||||
. "WHERE c.id = %d", $id);
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
if (mysqli_num_rows($dbResult) === 0) {
|
||||
$this->templateName = 'notfound_error';
|
||||
return;
|
||||
}
|
||||
$line = mysqli_fetch_assoc($dbResult);
|
||||
$salt = $line['salt'];
|
||||
$this->content['member-name'] = $this->decode($line['last_name'], $salt) . ', ' . $this->decode($line['first_name'], $salt);
|
||||
$this->predefines = $line;
|
||||
}
|
||||
|
||||
protected function generateContent(): void {
|
||||
$this->loadPayHistory($this->getUriParams()['id']);
|
||||
}
|
||||
|
||||
protected function loadPayHistory(string $id): void {
|
||||
$query = sprintf("SELECT ph.payment_date, ph.payment_height, u.realname, u.salt "
|
||||
. "FROM paying_history ph "
|
||||
. "JOIN `user` u "
|
||||
. " ON u.id = ph.registered_by_id "
|
||||
. "WHERE ph.clubmember_id = %d "
|
||||
. "ORDER BY payment_date DESC", $id);
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
$tableBody = '';
|
||||
while ($row = mysqli_fetch_assoc($dbResult)) {
|
||||
$tableBody .= '<tr>';
|
||||
$tableBody .= '<td>' . $row['payment_date'] . '</td>';
|
||||
$tableBody .= '<td>' . $row['payment_height'] . '</td>';
|
||||
$tableBody .= '<td>' . $this->decode($row['realname'], $row['salt']) . '</td>';
|
||||
$tableBody .= '</tr>';
|
||||
}
|
||||
$this->content['payings'] = $tableBody;
|
||||
}
|
||||
|
||||
protected function formAction(): void {
|
||||
if (!$this->formCheckFields()) {
|
||||
return;
|
||||
}
|
||||
$this->saveToDb();
|
||||
$this->cleanFields = true;
|
||||
}
|
||||
|
||||
protected function createDbKeyValues(): array {
|
||||
$data = parent::createDbKeyValues();
|
||||
$data['keys'][] = '`registered_by_id`';
|
||||
$data['values'][] = $_SESSION['userid'];
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
137
include/planboard.php
Normal file
137
include/planboard.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Planboard extends Renderer {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function generateContent(): void {
|
||||
$this->setOwnColor();
|
||||
$this->setColorLegend();
|
||||
$this->setContentTopics();
|
||||
}
|
||||
|
||||
protected function setOwnColor(): void {
|
||||
$query = sprintf('SELECT c.color
|
||||
FROM `user` u
|
||||
JOIN color c
|
||||
ON c.id = u.color_id
|
||||
WHERE u.id = %d', $_SESSION['userid']);
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
$row = mysqli_fetch_assoc($dbResult);
|
||||
$this->content['owncolor'] = (!$row) ? '000000' : $row['color'];
|
||||
}
|
||||
|
||||
protected function setColorLegend(): void {
|
||||
$legendData = [];
|
||||
$query = 'SELECT c.color, c2.last_name, c2.first_name, u.realname, u.salt usalt, c2.salt csalt
|
||||
FROM `user` u
|
||||
JOIN color c
|
||||
ON c.id = u.color_id
|
||||
LEFT JOIN clubmember c2
|
||||
ON c2.user_id = u.id
|
||||
WHERE u.active = 1';
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
while ($row = mysqli_fetch_assoc($dbResult)) {
|
||||
$legendData[] = '<div style="color:#' . $row['color'] . '">' . (($row['last_name'])
|
||||
? $this->decode($row['last_name'], $row['csalt']) . ', ' . $this->decode($row['first_name'], $row['csalt'])
|
||||
: $this->decode($row['realname'], $row['usalt'])) . '</div>';
|
||||
}
|
||||
$this->content['colors'] = implode('', $legendData);
|
||||
}
|
||||
|
||||
protected function setContentTopics(): void {
|
||||
$topics = $this->getAllTopics();
|
||||
$prerenderedTopics = [];
|
||||
foreach ($topics as $topic) {
|
||||
$prerenderedTopics[] = '<option value="' . $topic['id'] . '">' . $topic['title'] . '</option>';
|
||||
}
|
||||
$this->content['topics'] = implode('', $prerenderedTopics);
|
||||
}
|
||||
|
||||
public function render(): void {
|
||||
$action = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_STRING);
|
||||
if ($action === 'generate') {
|
||||
$this->generateDiscussion();
|
||||
return;
|
||||
}
|
||||
if ($action === 'fetchtopic') {
|
||||
$this->fetchTopic();
|
||||
return;
|
||||
}
|
||||
if ($action === 'setshortdescription') {
|
||||
$this->setShortDescription();
|
||||
return;
|
||||
}
|
||||
if ($action == 'setdiscussion') {
|
||||
$this->setDiscussion();
|
||||
}
|
||||
parent::render();
|
||||
}
|
||||
|
||||
protected function generateDiscussion(): void {
|
||||
$topicName = TRIM(filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING));
|
||||
if ($topicName === '') {
|
||||
echo '{"error": "Der Topic darf nicht leer sein."}';
|
||||
return;
|
||||
}
|
||||
$query = sprintf('SELECT id
|
||||
FROM discussion d
|
||||
where title = "%s"', $topicName);
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
if (mysqli_num_rows($dbResult) > 0) {
|
||||
echo '{"error": "Der Topic existiert schon."}';
|
||||
return;
|
||||
}
|
||||
$query = sprintf('INSERT INTO discussion (title, short_description, discussion) VALUES ("%s", "", "[]")', $topicName);
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
$id = mysqli_insert_id($this->dbConnection);
|
||||
$output = [
|
||||
'topics' => $this->getAllTopics(),
|
||||
'id' => $id,
|
||||
];
|
||||
echo json_encode($output);
|
||||
}
|
||||
|
||||
protected function getAllTopics(): array {
|
||||
$query = 'SELECT d.id, d.title
|
||||
FROM discussion d
|
||||
ORDER BY d.title ';
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
$result = [];
|
||||
while ($row = mysqli_fetch_assoc($dbResult)) {
|
||||
$result[] = ['id' => $row['id'], 'title' => $row['title'] ];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function fetchTopic(): void {
|
||||
$query = sprintf('SELECT short_description, discussion
|
||||
FROM discussion d
|
||||
WHERE id = %d', TRIM(filter_input(INPUT_POST, 'id', FILTER_SANITIZE_STRING)));
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
$row = mysqli_fetch_assoc($dbResult);
|
||||
$result = [
|
||||
'shortdescription' => ($row ? $row['short_description'] : ''),
|
||||
'discussion' => ($row ? $row['discussion'] : '[]'),
|
||||
];
|
||||
echo json_encode($result);
|
||||
}
|
||||
|
||||
protected function setShortDescription(): void {
|
||||
$query = sprintf('UPDATE discussion SET short_description = "%s" WHERE id = %d',
|
||||
filter_input(INPUT_POST, 'text', FILTER_SANITIZE_ADD_SLASHES),
|
||||
filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT));
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
echo '{"result":"success"}';
|
||||
}
|
||||
|
||||
protected function setDiscussion(): void {
|
||||
$query = sprintf('UPDATE discussion SET discussion = "%s" WHERE id = %d',
|
||||
filter_input(INPUT_POST, 'text', FILTER_SANITIZE_ADD_SLASHES),
|
||||
filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT));
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
echo '{"result":"success"}';
|
||||
}
|
||||
}
|
||||
31
include/projects.php
Normal file
31
include/projects.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Projects extends Renderer {
|
||||
protected function generateContent(): void {
|
||||
$query = 'SELECT p.short_title, p.description, pt.caption
|
||||
FROM project p
|
||||
JOIN project_type pt
|
||||
ON pt.id = p.project_type_id
|
||||
ORDER BY pt.order_id, p.short_title';
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
$previousSection = '';
|
||||
$output = '';
|
||||
while ($row = mysqli_fetch_assoc($dbResult)) {
|
||||
if ($row['caption'] != $previousSection) {
|
||||
if ($output !== '') {
|
||||
$output .= '</ul>';
|
||||
}
|
||||
$output .= '<h3>' . $row['caption'] . '</h3><ul>';
|
||||
$previousSection = $row['caption'];
|
||||
}
|
||||
$output .= '<li>' . $row['short_title'];
|
||||
if (trim($row['description']) != '') {
|
||||
$output .= ' - ' . $row['description'];
|
||||
}
|
||||
$output .= '</li>';
|
||||
}
|
||||
$output .= '</ul>';
|
||||
$this->content['projects'] = $output;
|
||||
}
|
||||
}
|
||||
114
include/projectsmanagement.php
Normal file
114
include/projectsmanagement.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Projectsmanagement extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Projekt', 'type' => 'dbselect', 'size' => 0, 'name' => 'shorttitle', 'combine_with_next_line' => true, 'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'shorttitle',
|
||||
'sourcedb' => 'project', 'optionfield' => 'short_title', 'encryption' => false, 'with_null_field' => true],
|
||||
['label' => '', 'type' => 'text', 'size' => 20, 'name' => 'new_title', 'combine_with_next_line' => true, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'shorttitle',
|
||||
'optional' => true],
|
||||
['label' => '', 'type' => 'button', 'size' => 0, 'name' => 'addproject', 'combine_with_next_line' => false, 'filter' => false, 'text' => 'Projekt hinzufügen'],
|
||||
['label' => 'Kurze Beschreibung', 'type' => 'text', 'size' => 50, 'name' => 'description', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_STRING, 'dbfield' => 'description',
|
||||
'optionial' => true],
|
||||
['label' => 'Projektart', 'type' => 'dbselect', 'size' => 0, 'name' => 'projecttype', 'combine_with_next_line' => false, 'filter' => FILTER_SANITIZE_NUMBER_INT, 'dbfield' => 'project_type_id',
|
||||
'sourcedb' => 'project_type', 'optionfield' => 'caption', 'encryption' => false, 'with_null_field' => false],
|
||||
];
|
||||
protected bool $isAjaxForm = true;
|
||||
|
||||
public function render(): void {
|
||||
$action = trim(filter_input(INPUT_POST, 'action', FILTER_SANITIZE_STRING));
|
||||
if ($action != '') {
|
||||
switch ($action) {
|
||||
case 'create':
|
||||
$this->createProject();
|
||||
break;
|
||||
case 'getdetails':
|
||||
$this->getDetails();
|
||||
break;
|
||||
case 'setdescription':
|
||||
$this->setDescription();
|
||||
break;
|
||||
case 'setprojecttype':
|
||||
$this->setProjectType();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
parent::render();
|
||||
}
|
||||
|
||||
protected function createProject(): void {
|
||||
$newName = trim(filter_input(INPUT_POST, 'newname', FILTER_SANITIZE_STRING));
|
||||
if ($newName == '') {
|
||||
echo '{"error": "Jedes Projekt benötigt einen Namen."}';
|
||||
return;
|
||||
}
|
||||
$query = sprintf('select id from project p where short_title = "%s"', $newName);
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
if (mysqli_num_rows($dbResult) > 0) {
|
||||
echo '{"error": "Ein Projekt mit dem Namen existiert bereits."}';
|
||||
return;
|
||||
}
|
||||
$query = sprintf('INSERT INTO project (short_title, description, project_type_id)
|
||||
SELECT "%s", "", id
|
||||
FROM project_type p
|
||||
WHERE caption = "Fortlaufende Projekte"', $newName);
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
$id = mysqli_insert_id($this->dbConnection);
|
||||
$query = 'SELECT id, short_title FROM project p ORDER BY short_title';
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
$list = [];
|
||||
while ($row = mysqli_fetch_assoc($dbResult)) {
|
||||
$list[] = ['id' => $row['id'], 'title' => $row['short_title'] ];
|
||||
}
|
||||
echo json_encode(['list' => $list, 'id' => $id]);
|
||||
}
|
||||
|
||||
protected function setDescription(): void {
|
||||
$newDescription = trim(filter_input(INPUT_POST, 'description', FILTER_SANITIZE_ADD_SLASHES));
|
||||
$query = sprintf('UPDATE project SET description = "%s" WHERE id = "%d"', $newDescription, filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT));
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
echo '{}';
|
||||
}
|
||||
|
||||
protected function getDetails(): void {
|
||||
$query = sprintf('SELECT description, project_type_id FROM project WHERE id = %d', filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT));
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
if ($row = mysqli_fetch_assoc($dbResult)) {
|
||||
echo json_encode(['description' => $row['description'], 'projecttype' => $row['project_type_id']]);
|
||||
} else {
|
||||
echo json_encode(['description' => '', 'projecttype' => '1']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function setProjectType(): void {
|
||||
$newProjectType = trim(filter_input(INPUT_POST, 'newtype', FILTER_SANITIZE_NUMBER_INT));
|
||||
$query = sprintf('UPDATE project SET project_type_id = "%d" WHERE id = "%d"', $newProjectType, filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT));
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
echo '{}';
|
||||
}
|
||||
|
||||
protected function generateContent(): void {
|
||||
$typesQuery = 'SELECT * FROM project_type ORDER BY id';
|
||||
$typesResult = mysqli_query($this->dbConnection, $typesQuery);
|
||||
$types = [];
|
||||
while ($row = mysqli_fetch_assoc($typesResult)) {
|
||||
$types[$row['id'] ] = $row['caption'];
|
||||
}
|
||||
$query = 'SELECT * FROM project ORDER BY short_title';
|
||||
$result = mysqli_query($this->dbConnection, $query);
|
||||
$overviewHtml = '<table><thead><tr><th>Projekt</th><th>Projekttyp</th><tr><thead><tbody>';
|
||||
while ($row = mysqli_fetch_assoc($result)) {
|
||||
$overviewHtml .= '<tr><td>' . $row['short_title'] . '</td>';
|
||||
$overviewHtml .= '<td><select name="project_type" data="' . $row['id'] . '">';
|
||||
foreach ($types as $id => $type) {
|
||||
$overviewHtml .= '<option value="' . $id . '"' . ($id == $row['project_type_id'] ? ' selected' : '') . '>' . $type . '</option>';
|
||||
}
|
||||
$overviewHtml .= '</select></td>';
|
||||
$overviewHtml .= '</tr>';
|
||||
}
|
||||
$overviewHtml .= '</tbody></table>';
|
||||
$this->content['projects'] = $overviewHtml;
|
||||
}
|
||||
}
|
||||
76
include/register.php
Normal file
76
include/register.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Register extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Gewünscher Benutzername', 'type' => 'text', 'size' => 50, 'name' => 'username', 'combine_with_next_line' => false],
|
||||
['label' => 'Vollständiger Name', 'type' => 'text', 'size' => 50, 'name' => 'fullname', 'combine_with_next_line' => false],
|
||||
['label' => 'Email-Adresse', 'type' => 'email', 'size' => 50, 'name' => 'email', 'combine_with_next_line' => false],
|
||||
['label' => 'Gewünschtes Paßwort', 'type' => 'password', 'size' => 50, 'name' => 'password', 'combine_with_next_line' => false],
|
||||
['label' => 'Paßwort wiederholen', 'type' => 'password', 'size' => 50, 'name' => 'password2', 'combine_with_next_line' => false],
|
||||
['label' => 'Ich stimme der Speicherung meiner Daten zu.', 'type' => 'checkbox', 'size' => 50, 'name' => 'accept', 'combine_with_next_line' => false,
|
||||
'value' => 1],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Zugang beantragen';
|
||||
|
||||
protected function formAction(): void {
|
||||
$this->writeToDb();
|
||||
$this->sendEmail();
|
||||
$this->templateName = 'register_successful';
|
||||
}
|
||||
|
||||
protected function formCheckFields(): bool {
|
||||
$username = trim(filter_input(INPUT_POST, 'username', FILTER_SANITIZE_ADD_SLASHES));
|
||||
$user = mysqli_query($this->dbConnection, 'SELECT * FROM user WHERE `username` = lower("' . $username . '")');
|
||||
if ($user->num_rows !== 0) {
|
||||
$this->errors[] = 'Der Benutzername existiert bereits.';
|
||||
}
|
||||
if (!preg_match('/^([a-z0-9]{3,16})$/', $username)) {
|
||||
$this->errors['username'] = 'Der Benutzername darf nur aus Buchstaben (ohne Umlaute) und Zahlen bestehen und muss zwischen drei und sechzen Zeichen lang sein.';
|
||||
}
|
||||
if (!filter_var(strtolower(trim(filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL)), FILTER_VALIDATE_EMAIL))) {
|
||||
$this->errors['email'] = 'Die Email-Adresse ist inkorrekt';
|
||||
}
|
||||
if (strlen(filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING)) < 8) {
|
||||
$this->errors['password'] = 'Das gewählte Paßwort ist zu kurz (Minimum: 8 Zeichen).';
|
||||
}
|
||||
if (filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING) !== filter_input(INPUT_POST, 'password2', FILTER_SANITIZE_STRING)) {
|
||||
$this->errors['password2'] = 'Die Paßwörter stimmen nicht überein.';
|
||||
}
|
||||
if (filter_input(INPUT_POST, 'accept', FILTER_SANITIZE_NUMBER_INT) !== '1') {
|
||||
$this->errors['accept'] = 'Sie müssen der Speicherung Ihrer Daten zustimmen.';
|
||||
}
|
||||
return (count($errors) === 0);
|
||||
}
|
||||
|
||||
protected function writeToDb(): void {
|
||||
$salt = $this->generateRandomString();
|
||||
$encryptedName = $this->encode(trim(filter_input(INPUT_POST, 'fullname', FILTER_SANITIZE_STRING), $salt));
|
||||
$email = strtolower(trim(filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL)));
|
||||
$encryptedEmail = $this->encode($email, $salt);
|
||||
$query = sprintf("INSERT INTO ffajs.`user` (username, password, realname, email, active, save_data_accepted, salt, color_id) "
|
||||
. "VALUES('%s', '%s', '%s', '%s', 0, %d, '%s', (SELECT c.id
|
||||
FROM color c
|
||||
left join `user` u
|
||||
on u.color_id = c.id
|
||||
where u.id is null
|
||||
order by rand()
|
||||
limit 1))",
|
||||
strtolower(trim(filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING))),
|
||||
password_hash(filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING), PASSWORD_DEFAULT),
|
||||
$encryptedName,
|
||||
$encryptedEmail,
|
||||
filter_input(INPUT_POST, 'accept', FILTER_SANITIZE_NUMBER_INT) ?: 0,
|
||||
$salt);
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
}
|
||||
|
||||
protected function sendEmail(): void {
|
||||
$mail = $this->initSmtpMailer();
|
||||
$mail->setFrom('foerderverein-ajs@gmx.de', 'Förderverein der August-Jaspert-Schule');
|
||||
$mail->addReplyTo('foerderverein-ajs@gmx.de', 'Förderverein der August-Jaspert-Schule');
|
||||
$mail->addAddress('foerderverein-ajs@gmx.de', 'Förderverein der August-Jaspert-Schule');
|
||||
$message = 'Ein neuer Antrag auf Benutzerzugang wurde gestellt';
|
||||
$this->sendMail($mail, 'Zugang zu internem Bereich beantragt', $message, '');
|
||||
}
|
||||
}
|
||||
517
include/renderer.php
Normal file
517
include/renderer.php
Normal file
@@ -0,0 +1,517 @@
|
||||
<?php
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PhpImap\Mailbox;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
class Renderer {
|
||||
protected string $templateName;
|
||||
private array $menuItems = [];
|
||||
protected array $internalMenuItems = [];
|
||||
protected $hiddenCount = 0;
|
||||
protected array $predefines = [];
|
||||
protected array $errors = [];
|
||||
protected array $formFields = [];
|
||||
protected string $formSendButtonLabel = '';
|
||||
protected bool $isAjaxForm = false;
|
||||
protected string $encType = 'application/x-www-form-urlencoded';
|
||||
protected $dbConnection;
|
||||
protected string $encryptionKey = 'CXOoBDbt0qjJ6zlTILGVsFIZTE0aTZUC';
|
||||
protected array $content = [];
|
||||
protected string $dbTable = '';
|
||||
protected bool $dbGenerateSaltField = false;
|
||||
protected bool $dbUpdate = false;
|
||||
protected bool $cleanFields = false;
|
||||
protected array $messages = [];
|
||||
protected string $salt = '';
|
||||
private string $website = '';
|
||||
protected bool $saveAllFields = false;
|
||||
protected string $imapServer = 'imap.gmx.net';
|
||||
protected int $imapPort = 993;
|
||||
protected string $smtpServer = 'mail.gmx.net';
|
||||
protected int $smtpPort = 465;
|
||||
protected string $emailUser = 'foerderverein-ajs@gmx.de';
|
||||
protected string $emailPassword = 'HarheimerWeg16';
|
||||
protected $mbox;
|
||||
|
||||
public function __construct(?string $templateName = null) {
|
||||
session_start();
|
||||
$this->createPublicMenuItems();
|
||||
$this->createInternalMenuItems();
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
$_SESSION['userid'] = 0;
|
||||
}
|
||||
$scriptName = $this->getScriptName();
|
||||
if (!in_array($scriptName, array_merge($this->menuItems, $this->internalMenuItems))) {
|
||||
header('Location: /', true, 301);
|
||||
return;
|
||||
}
|
||||
$this->templateName = $templateName ?: (!in_array($scriptName, ['ffajs', 'fvajs', '', '/']) ? $scriptName : 'index');
|
||||
$this->connectDb();
|
||||
}
|
||||
|
||||
private function createPublicMenuItems(): void {
|
||||
$this->menuItems = $this->getMenuItemsFromFile('publicpages');
|
||||
}
|
||||
|
||||
private function createInternalMenuItems(): void {
|
||||
$this->internalMenuItems = $this->getMenuItemsFromFile('internalpages');
|
||||
}
|
||||
|
||||
private function getMenuItemsFromFile(string $fileName): array {
|
||||
$items = json_decode(file_get_contents('conf/' . $fileName . '.conf'));
|
||||
$menu = [];
|
||||
foreach ($items as $url => $caption) {
|
||||
$menu[($caption !== '' ? $caption : '$hidden:0' . $this->hiddenCount++)] = $url;
|
||||
}
|
||||
return $menu;
|
||||
}
|
||||
|
||||
public function getScriptName(): string {
|
||||
return $this->getSplittedUri()[0];
|
||||
}
|
||||
|
||||
public function getUrl(): string {
|
||||
return filter_input(INPUT_SERVER, 'REQUEST_URI');
|
||||
}
|
||||
|
||||
protected function getUriParams(): array {
|
||||
$paramPairs = explode('&', $this->getSplittedUri()[1]);
|
||||
$result = [];
|
||||
foreach ($paramPairs as $paramPair) {
|
||||
$pair = explode('=', $paramPair);
|
||||
if (count($pair) === 2) {
|
||||
$result[$pair[0]] = $pair[1];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getSplittedUri(): array {
|
||||
$scriptNameParts = pathinfo(filter_input(INPUT_SERVER, 'REQUEST_URI'));
|
||||
$uri = $scriptNameParts['filename'] ?: 'index';
|
||||
return explode('?', $uri);
|
||||
}
|
||||
|
||||
private function connectDb(): void {
|
||||
$user = 'ffajs';
|
||||
$password = 'BpAJSis1999xx';
|
||||
$host = 'tsschulz.de';
|
||||
$port = 3306;
|
||||
$db = 'ffajs';
|
||||
$this->dbConnection = mysqli_connect($host, $user, $password, $db, $port);
|
||||
}
|
||||
|
||||
public function render(): void {
|
||||
if (trim(filter_input(INPUT_POST, 'action', FILTER_SANITIZE_STRING)) !== '') {
|
||||
$this->formAction();
|
||||
}
|
||||
$this->website = file_get_contents('templates/page.html');
|
||||
$this->header();
|
||||
$this->menu();
|
||||
if ($_SESSION['userid'] === 0 && in_array($this->getScriptName() , $this->internalMenuItems, false)) {
|
||||
$this->templateName = 'login_error';
|
||||
}
|
||||
$this->body();
|
||||
$this->footer();
|
||||
echo $this->website;
|
||||
}
|
||||
|
||||
private function header(): void {
|
||||
$this->website = str_replace('{{header}}', file_get_contents('templates/header.html'), $this->website);
|
||||
}
|
||||
|
||||
private function menu(): void {
|
||||
$menu = '<menu>';
|
||||
$scriptName = $this->getScriptName();
|
||||
foreach ($this->menuItems as $page => $link) {
|
||||
if (substr($page, 0, 8) === '$hidden:') {
|
||||
continue;
|
||||
}
|
||||
$menu .= '<a href="' . $link . '"' . ($link === $scriptName ? 'class="active"' : '') . '>' . $page . '</a>';
|
||||
}
|
||||
if (isset($_SESSION) && $_SESSION['userid'] === 0) {
|
||||
$menu .= '<a href="login" class="login"><img src="' . (filter_input(INPUT_SERVER, 'HTTP_HOST') == 'localhost' ? '/ffajs' : '') .
|
||||
'/images/icons/key.png" class="menu-icon" alt="login" /></a>';
|
||||
} else {
|
||||
$menu .= '<div class="internal-menu-main"><span class="intern">Verwaltung</span><div class="internal-menu-sub">';
|
||||
foreach ($this->internalMenuItems as $page => $link) {
|
||||
if (substr($page, 0, 8) === '$hidden:') {
|
||||
continue;
|
||||
}
|
||||
$menu .= '<a class="intern" href="' . $link . '"' . ($link === $scriptName ? 'class="active"' : '') . '>' . $page . '</a>';
|
||||
}
|
||||
$menu .= '</div></div>';
|
||||
$menu .= '<a href="logout" class="login"><img src="' . (filter_input(INPUT_SERVER, 'HTTP_HOST') == 'localhost' ? '/ffajs' : '') .
|
||||
'/images/icons/key.png" class="menu-icon" alt="logout" /></a>';
|
||||
}
|
||||
$menu .= '</menu>';
|
||||
$this->website = str_replace('{{menu}}', $menu, $this->website);
|
||||
}
|
||||
|
||||
protected function body(): void {
|
||||
$this->generateContent();
|
||||
$rawContent = file_get_contents('templates/' . $this->templateName . '.html');
|
||||
$errorHtml = count($this->errors) > 0
|
||||
? '<div class="error">' . implode('<br />', $this->errors) . '</div>'
|
||||
: '';
|
||||
$messagesHtml = count($this->messages) > 0
|
||||
? '<div class="messages">' . implode('<br />', $this->messages) . '</div>'
|
||||
: '';
|
||||
$placeholders = ['{{errors}}', '{{form}}', '{{messages}}'];
|
||||
$renderedContent = [$errorHtml, $this->renderForm(), $messagesHtml];
|
||||
foreach ($this->content as $placeholder => $html) {
|
||||
$placeholders[] = '{{' . $placeholder . '}}';
|
||||
$renderedContent[] = $html;
|
||||
}
|
||||
$content = str_replace($placeholders, $renderedContent, $rawContent);
|
||||
$this->website = str_replace('{{content}}', $content, $this->website);
|
||||
}
|
||||
|
||||
private function footer(): void {
|
||||
$this->website = str_replace('{{footer}}', file_get_contents('templates/footer.html'), $this->website);
|
||||
}
|
||||
|
||||
protected function showInputField(array $errors, string $inputType, string $fieldName, int $fieldLength): void {
|
||||
echo '<input type="' . $inputType . '" name="' . $fieldName . '" size="' . $fieldLength . '" value="' . filter_input(INPUT_POST, $fieldName, FILTER_SANITIZE_STRING) . '" />';
|
||||
if (isset($errors[$fieldName])) {
|
||||
echo '<span class="error">' . $errors[$fieldName] . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
protected function renderForm(): string {
|
||||
$form = '<form method="post" action="' . $this->getUrl() . '" enctype="' . $this->encType . '"><table class="form">';
|
||||
$label = '';
|
||||
$input = '';
|
||||
$error = '';
|
||||
for ($formFieldIndex = 0; $formFieldIndex < count($this->formFields); ++$formFieldIndex) {
|
||||
$newLabelExtension = $this->renderLabel($formFieldIndex);
|
||||
$label .= (strlen($label) > 0 && strlen($newLabelExtension) > 0 ? ' / ' : '') . $newLabelExtension;
|
||||
$input .= $this->renderInput($formFieldIndex);
|
||||
if (isset($this->formFields[$formFieldIndex]['name']) && isset($this->errors[$this->formFields[$formFieldIndex]['name'] ])) {
|
||||
$error .= '<span class="error">' . $this->errors[$this->formFields[$formFieldIndex]['name'] ] . '</span>';
|
||||
}
|
||||
if (!isset($this->formFields[$formFieldIndex]['combine_with_next_line'] ) || !$this->formFields[$formFieldIndex]['combine_with_next_line']) {
|
||||
$form .= '<tr><th>' . $label . '</th><td>' . $input . '</td><td>' . $error . '</td></tr>';
|
||||
$label = '';
|
||||
$input = '';
|
||||
$error = '';
|
||||
}
|
||||
}
|
||||
$form .= '</table>';
|
||||
if (!$this->isAjaxForm) {
|
||||
$form .= '<button type="submit" name="action" value="submit">' . $this->formSendButtonLabel . '</button>';
|
||||
}
|
||||
$form .= '<button type="reset">Zurücksetzen</button>';
|
||||
$form .= '</form>';
|
||||
return $form;
|
||||
}
|
||||
|
||||
protected function renderLabel(int $index): string {
|
||||
if (!isset($this->formFields[$index]['name']) && !isset($this->formFields[$index]['label'])) {
|
||||
return '';
|
||||
} elseif (isset($this->formFields[$index]['label'])) {
|
||||
return $this->formFields[$index]['label'];
|
||||
}
|
||||
return '<label for="' . $this->formFields[$index]['name'] . '">' . $this->formFields[$index]['label'] . '</label>';
|
||||
}
|
||||
|
||||
protected function renderInput(int $index): string {
|
||||
if ($this->formFields[$index]['type'] === 'combobox') {
|
||||
return $this->renderCombobox($index);
|
||||
}
|
||||
if ($this->formFields[$index]['type'] === 'textarea') {
|
||||
return $this->renderTextarea($index);
|
||||
}
|
||||
if ($this->formFields[$index]['type'] === 'infotext') {
|
||||
return '';
|
||||
}
|
||||
if ($this->formFields[$index]['type'] === 'dbselect') {
|
||||
return $this->renderDbSelect($index);
|
||||
}
|
||||
if ($this->formFields[$index]['type'] === 'spacer') {
|
||||
return ' ';
|
||||
}
|
||||
if ($this->formFields[$index]['type'] === 'button') {
|
||||
return $this->renderButton($index);
|
||||
}
|
||||
return $this->renderStandardInput($index);
|
||||
}
|
||||
|
||||
protected function renderCombobox(int $index): string {
|
||||
$inputField = '<select size="1" id="' . $this->formFields[$index]['name']
|
||||
. '" name="' . $this->formFields[$index]['name'] . '" size="' . $this->formFields[$index]['size'] . '"'
|
||||
. ' value="' . $this->inputValue($index) . '">';
|
||||
$inputValue = $this->inputValue($index);
|
||||
foreach ($this->formFields[$index]['values'] as $value) {
|
||||
$inputField .= '<option value="' . $value . '"';
|
||||
if ($value == $inputValue || (isset($this->formFields[$index]['default']) && $inputValue == '' && $value == $this->formFields[$index]['default'])) {
|
||||
$inputField .= ' selected';
|
||||
}
|
||||
$inputField .= '>' . $value . '</option>';
|
||||
}
|
||||
$inputField .= '</select>';
|
||||
return $inputField;
|
||||
}
|
||||
|
||||
protected function renderStandardInput(int $index): string {
|
||||
return '<input type="' . $this->formFields[$index]['type'] . '" id="' . $this->formFields[$index]['name'] .
|
||||
'" name="' . $this->formFields[$index]['name'] . '" size="' . $this->formFields[$index]['size'] . '"' .
|
||||
' value="' . $this->inputValue($index) . '" />';
|
||||
}
|
||||
|
||||
protected function renderTextarea(int $index): string {
|
||||
return '<textarea id="' . $this->formFields[$index]['name'] .'" '
|
||||
. 'name="' . $this->formFields[$index]['name'] . '" cols="' . $this->formFields[$index]['cols'] . '" '
|
||||
. 'rows="' . $this->formFields[$index]['rows'] . '">' . $this->inputValue($index) . '</textarea>';
|
||||
}
|
||||
|
||||
protected function renderDbSelect(int $index): string {
|
||||
$query = 'SELECT `id`, `' . $this->formFields[$index]['optionfield'] . '` as label FROM `' . $this->formFields[$index]['sourcedb'] . '` ORDER BY `id`';
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
$inputValue = $this->inputValue($index);
|
||||
$selectField = '<select id="' . $this->formFields[$index]['name'] . '" '
|
||||
. 'name="' . $this->formFields[$index]['name'] . '">';
|
||||
if (isset($this->formFields[$index]['with_null_field']) && $this->formFields[$index]['with_null_field'] === true) {
|
||||
$selectField .= '<option value="NULL">---</option>';
|
||||
}
|
||||
while ($row = mysqli_fetch_assoc($dbResult)) {
|
||||
$selectField .= '<option value="' . $row['id'] . '"';
|
||||
if ($row['id'] == $inputValue) {
|
||||
$selectField .= ' selected';
|
||||
}
|
||||
$selectField .= '>' . $row['label'] . '</option>';
|
||||
}
|
||||
$selectField .= '</select>';
|
||||
return $selectField;
|
||||
}
|
||||
|
||||
protected function renderButton(int $index): string {
|
||||
return '<button id="' . $this->formFields[$index]['name'] . '" name="' . $this->formFields[$index]['name'] . '">' . $this->formFields[$index]['text'] . '</button>';
|
||||
}
|
||||
|
||||
protected function inputValue($index): string {
|
||||
if (isset($this->formFields[$index]['value'])) {
|
||||
return $this->formFields[$index]['value'];
|
||||
} elseif ($this->cleanFields) {
|
||||
return '';
|
||||
}
|
||||
$value = filter_input(INPUT_POST, $this->formFields[$index]['name'], FILTER_SANITIZE_STRING) ?: '';
|
||||
if (trim($value) === '' && isset($this->predefines[$this->formFields[$index]['name']])) {
|
||||
$value = $this->predefines[$this->formFields[$index]['name']];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
protected function formAction(): void {
|
||||
|
||||
}
|
||||
|
||||
protected function formCheckFields(): bool {
|
||||
foreach ($this->formFields as $field) {
|
||||
$value = filter_input(INPUT_POST, $field['name'], isset($field['filter']) ? $field['filter'] : FILTER_SANITIZE_STRING);
|
||||
if (isset($field['optional']) && ($field['optional'] == false) && trim($value) === '' && $field['type'] !== 'file') {
|
||||
$this->errors[$field['name']] = 'Das Feld darf nicht leer sein';
|
||||
continue;
|
||||
}
|
||||
if (isset($field['regex']) && !preg_match($field['regex'], $value)) {
|
||||
$this->errors[$field['name']] = 'Inkorrekte eingabe';
|
||||
}
|
||||
}
|
||||
return count($this->errors) === 0;
|
||||
}
|
||||
|
||||
protected function createDbInsert(): string {
|
||||
$preparedFieldData = $this->createDbKeyValues();
|
||||
return 'INSERT INTO `' . $this->dbTable . '` (' . implode(', ', $preparedFieldData['keys'])
|
||||
. ') VALUES (' . implode(', ', $preparedFieldData['values']) . ')';
|
||||
}
|
||||
|
||||
protected function createKeyValuePairsForUpdate(array $data): string {
|
||||
$resultArray = [];
|
||||
$numEntries = count($data['keys']);
|
||||
for ($i = 0; $i < $numEntries; ++$i) {
|
||||
$resultArray[] = $data['keys'][$i] . ' = ' . $data['values'][$i];
|
||||
}
|
||||
return implode(', ', $resultArray);
|
||||
}
|
||||
|
||||
protected function createDbUpdate(): string {
|
||||
$preparedFieldData = $this->createDbKeyValues();
|
||||
$query = 'UPDATE `' . $this->dbTable . '` SET ';
|
||||
$query .= $this->createKeyValuePairsForUpdate($preparedFieldData);
|
||||
$query .= ' WHERE `id` = ' . $this->getUriParams()['id'];
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function saveToDb(): void {
|
||||
$query = $this->dbUpdate
|
||||
? $this->createDbUpdate()
|
||||
: $this->createDbInsert();
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
}
|
||||
|
||||
protected function createDbKeyValues(): array {
|
||||
$keysArray = [];
|
||||
$valuesArray = [];
|
||||
$salt = $this->salt != '' ? $this->salt : $this->generateRandomString();
|
||||
foreach ($this->formFields as $field) {
|
||||
if (!$this->saveAllFields && isset($field['optional']) && $field['optional'] === true && trim(filter_input(INPUT_POST, $field['name'], $field['filter'])) === '') {
|
||||
continue;
|
||||
}
|
||||
$keysArray[] = '`' . $field['dbfield'] . '`';
|
||||
if (isset($field['with_null_field']) && filter_input(INPUT_POST, $field['name']) === 'NULL') {
|
||||
$valuesArray[] = 'NULL';
|
||||
} else {
|
||||
$rawValue = filter_input(INPUT_POST, $field['name'], $field['filter']);
|
||||
$dbValue = $rawValue === '' || (isset($field['encryption']) && $field['encryption'] === false) ? $rawValue : $this->encode($rawValue, $salt);
|
||||
$valuesArray[] = '"' . $dbValue . '"';
|
||||
}
|
||||
}
|
||||
if ($this->dbGenerateSaltField) {
|
||||
$keysArray[] = '`salt`';
|
||||
$valuesArray[] = '"' . $salt . '"';
|
||||
}
|
||||
return ['keys' => $keysArray, 'values' => $valuesArray];
|
||||
}
|
||||
|
||||
protected function getDbEncryptedValueIfNeeded(array $formData, string $fieldName, string $salt): mixed {
|
||||
$formField = $this->getFormField($fieldName);
|
||||
if (count($formField) !== 0) {
|
||||
if (!$this->fieldHasToBeEncrypted($fieldName)) {
|
||||
return $formData[$fieldName];
|
||||
}
|
||||
}
|
||||
return $this->encode($formData[$fieldName], $salt);
|
||||
}
|
||||
|
||||
protected function getFormField($fieldName): array {
|
||||
foreach ($this->formFields as $formField) {
|
||||
if (!isset($formField['name'])) {
|
||||
continue;
|
||||
}
|
||||
if ($formField['name'] === $fieldName) {
|
||||
return $formField;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function fieldHasToBeEncrypted(string $fieldName): bool {
|
||||
$formField = $this->getFormField($fieldName);
|
||||
return !isset($formField['encryption']) || $formField['encryption'] !== false;
|
||||
}
|
||||
|
||||
protected function generateContent(): void {
|
||||
|
||||
}
|
||||
|
||||
protected function generateRandomString($length = 16) {
|
||||
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$charactersLength = strlen($characters);
|
||||
$randomString = '';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
||||
}
|
||||
return $randomString;
|
||||
}
|
||||
|
||||
protected function encode(string $toEncode, string $salt): string {
|
||||
return openssl_encrypt($toEncode, 'aes-256-cbc', $this->encryptionKey, 0, $salt);
|
||||
}
|
||||
|
||||
protected function decode(string $toDecode, string $salt): string {
|
||||
return openssl_decrypt($toDecode, 'aes-256-cbc', $this->encryptionKey, 0, $salt);
|
||||
}
|
||||
|
||||
|
||||
protected function initSmtpMailer(): PHPMailer {
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->SMTPDebug = SMTP::DEBUG_OFF;
|
||||
$mail->isSMTP();
|
||||
$mail->Host = $this->smtpServer;
|
||||
$mail->Port = $this->smtpPort;
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = $this->emailUser;
|
||||
$mail->Password = $this->emailPassword;
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||
$mail->CharSet = PHPMailer::CHARSET_UTF8;
|
||||
$mail->isHTML(true);
|
||||
return $mail;
|
||||
}
|
||||
|
||||
protected function sendMail(PHPMailer $mail, string $subject, string $body, string $signature): void {
|
||||
$completeBody = $body . $signature . $this->emailLegalInformation();
|
||||
$mail->Subject = $subject;
|
||||
$mail->Body = $completeBody;
|
||||
$mail->AltBody = 'Diese Email benötigt HTML-Ansicht';
|
||||
$mail->send();
|
||||
}
|
||||
|
||||
protected function connectToImap(): bool {
|
||||
$this->mbox = new PhpImap\Mailbox(
|
||||
'{' . $this->imapServer . ':' . $this->imapPort . '/imap/ssl}INBOX',
|
||||
$this->emailUser,
|
||||
$this->emailPassword,
|
||||
__DIR__,
|
||||
'UTF-8',
|
||||
true,
|
||||
false
|
||||
);
|
||||
$this->mbox->setConnectionArgs(
|
||||
CL_EXPUNGE,
|
||||
3,
|
||||
[]
|
||||
);
|
||||
/* $this->mbox = imap_open ("{" . $this->imapServer . ":" . $this->imapPort . "/imap/ssl}INBOX", $this->emailUser, $this->emailPassword);
|
||||
if ($this->mbox === false) {
|
||||
$errors = imap_errors();
|
||||
$this->errors = is_array($errors) ? $errors : [$errors];
|
||||
}*/
|
||||
return ($this->mbox !== false);
|
||||
}
|
||||
|
||||
protected function saveFileLocal(string $newFileName, string $content, string $salt): void {
|
||||
$encodedFile = $this->encode($content, $salt);
|
||||
file_put_contents('/var/shared/fvajs/' . $newFileName, $encodedFile);
|
||||
}
|
||||
|
||||
protected function emailLegalInformation(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function generateSignature(string $signatureType): string {
|
||||
$sender = ($signatureType === 'Persönliche Signatur') ? $this->generatePersonalSignature() : 'Der Vorstand';
|
||||
return '<p>-------------<br/>'
|
||||
. $sender .'<br/><br/>'
|
||||
. 'Verein der Freunde und Förderer der August-Jaspert-Schule e.V.<br/>'
|
||||
. 'Harheimer Weg 16<br/>'
|
||||
. '60437 Frankfurt<br/>'
|
||||
. 'Email: foerderverein-ajs@gmx.de<br/>'
|
||||
. 'Homepage: https://fvajs.de<br/>'
|
||||
. 'Registergerich: Amtsgerich Frankfurt a.M. <Registernummer>'
|
||||
. 'Vertretungsberechtigt: Lucas Fastabend, Alexandra <nachname>, Torsten Schulz'
|
||||
. '</p>';
|
||||
}
|
||||
|
||||
protected function generatePersonalSignature(): string {
|
||||
$query = sprintf('SELECT c.first_name, c.last_name, c.salt, cp.description
|
||||
FROM clubmember c
|
||||
JOIN `user` u
|
||||
ON u.id = c.user_id
|
||||
LEFT JOIN clubmember_position cp
|
||||
ON cp.id = c.position_id
|
||||
WHERE u.id = %d', $_SESSION['userid']);
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
$row = mysqli_fetch_assoc($dbResult);
|
||||
$name = $this->decode($row['first_name'], $row['salt']) . ' ' . $this->decode($row['last_name'], $row['salt']);
|
||||
if (trim($row['description']) === '') {
|
||||
return name;
|
||||
}
|
||||
return htmlspecialchars($name . ' (' . $row['description'] . ')');
|
||||
}
|
||||
|
||||
}
|
||||
71
include/savemail.php
Normal file
71
include/savemail.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
require 'mailhandling.php';
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
class Savemail extends Mailhandling {
|
||||
// protected $mbox = null;
|
||||
protected $uid = 0;
|
||||
|
||||
public function __construct(?string $templateName = null) {
|
||||
parent::__construct();
|
||||
if (!$this->connectToImap()) {
|
||||
$this->templateName = 'imaperror';
|
||||
return;
|
||||
}
|
||||
$this->uid = $this->getUriParams()['uid'];
|
||||
$this->type = $this->getUriParams()['type'];
|
||||
$this->content['uid'] = $this->uid;
|
||||
if ($this->type === 'content') {
|
||||
$this->saveEmailBody();
|
||||
}
|
||||
}
|
||||
|
||||
protected function saveEmailBody(): void {
|
||||
$messageStructure = imap_fetchstructure($this->mbox, $this->uid);
|
||||
$this->fetchEmailHeader($this->content);
|
||||
$this->fetchEmailBody($messageStructure, $this->content);
|
||||
$content = $this->generateBodyContent();
|
||||
$newFileName = $this->generateRandomString(64);
|
||||
$salt = $this->generateRandomString();
|
||||
$breaks = array("<br />","<br>","<br/>");
|
||||
$rerenderedContent = str_ireplace($breaks, "\r\n", $content);
|
||||
$this->saveFileLocal($newFileName, $rerenderedContent, $salt);
|
||||
$this->generateDocumentTitle();
|
||||
$query = sprintf('INSERT INTO ffajs.document
|
||||
(title, original_filename, local_filename, salt)
|
||||
VALUES("%s", "%s", "%s", "%s")', $this->content['saved-title'],
|
||||
$this->content['saved-title'],
|
||||
$newFileName, $salt);
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
}
|
||||
|
||||
protected function generateBodyContent(): string {
|
||||
return 'Von: ' . $this->content['sender'] . "\n"
|
||||
. 'An: ' . $this->content['receiver'] . "\n"
|
||||
. 'Datum: ' . $this->content['senddate'] . "\n"
|
||||
. 'Betreff: ' . $this->content['subject'] . "\n\n"
|
||||
. $this->content['emailbody'];
|
||||
}
|
||||
|
||||
protected function generateDocumentTitle(): void {
|
||||
$originalSubject = $this->content['subject'];
|
||||
$count = 0;
|
||||
$found = false;
|
||||
do {
|
||||
$query = sprintf('SELECT id
|
||||
FROM document d
|
||||
WHERE lower(trim(d.title)) = lower(trim("%s"))', $originalSubject);
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
if (mysqli_num_rows($dbResult) > 0) {
|
||||
$found = true;
|
||||
$counter = 0;
|
||||
if (preg_match('/(.*):(\d+)$/', trim($originalSubject))) {
|
||||
$counter = preg_split('/(.*):(\d+)$/', trim($originalSubject));
|
||||
$originalSubject = preg_replace('/(.*):(\d+)$/', '{1}', $originalSubject);
|
||||
}
|
||||
$originalSubject .= ':' . (++$counter);
|
||||
}
|
||||
} while ($found === true && ($count++ < 10));
|
||||
$this->content['saved-title'] = $originalSubject;
|
||||
}
|
||||
}
|
||||
52
include/setpassword.php
Normal file
52
include/setpassword.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
include 'renderer.php';
|
||||
|
||||
class Setpassword extends Renderer {
|
||||
protected array $formFields = [
|
||||
['label' => 'Benutzername', 'type' => 'text', 'size' => 50, 'name' => 'username', 'combine_with_next_line' => false],
|
||||
['label' => '', 'type' => 'hidden', 'name' => 'code', 'combine_with_next_line' => false, 'size' => 50],
|
||||
['label' => 'Neues Paßwort', 'type' => 'password', 'name' => 'newpassword1', 'combine_with_next_line' => false, 'size' => 50],
|
||||
['label' => 'Paßwort wiederolen', 'type' => 'password', 'name' => 'newpassword2', 'combine_with_next_line' => false, 'size' => 50],
|
||||
];
|
||||
protected string $formSendButtonLabel = 'Neues Paßwort setzen';
|
||||
protected array $errors = [];
|
||||
|
||||
protected function generateContent(): void {
|
||||
$this->formFields[1]['value'] = filter_input(INPUT_GET, 'code', FILTER_SANITIZE_STRING);
|
||||
}
|
||||
|
||||
protected function formAction(): void {
|
||||
if (!$this->formCheckFields()) {
|
||||
return;
|
||||
}
|
||||
$query = 'UPDATE user SET password="' . password_hash(filter_input(INPUT_POST, 'newpassword1', FILTER_SANITIZE_STRING), PASSWORD_DEFAULT) . '", recreate_db_hash = NULL ' .
|
||||
'WHERE username="' . trim(filter_input(INPUT_POST, 'username', FILTER_SANITIZE_ADD_SLASHES)) . '"';
|
||||
mysqli_query($this->dbConnection, $query);
|
||||
$this->templateName = 'passwordresettet';
|
||||
}
|
||||
|
||||
protected function formCheckFields(): bool {
|
||||
$userName = trim(filter_input(INPUT_POST, 'username', FILTER_SANITIZE_ADD_SLASHES));
|
||||
if (!preg_match('/^([a-z0-9]{3,16})$/', $userName)) {
|
||||
$this->errors['username'] = 'Der Benutzername darf nur aus Buchstaben (ohne Umlaute) und Zahlen bestehen und muss zwischen drei und sechzen Zeichen lang sein.';
|
||||
} else {
|
||||
$query = 'SELECT id, recreate_db_hash FROM user WHERE username="' . $userName . '"';
|
||||
$dbResult = mysqli_query($this->dbConnection, $query);
|
||||
if (mysqli_num_rows($dbResult) == 0) {
|
||||
$this->errors['username'] = 'Der Benutzername ist nicht vergeben';
|
||||
} else {
|
||||
$row = mysqli_fetch_assoc($dbResult);
|
||||
if ($row['recreate_db_hash'] !== filter_input(INPUT_POST, 'code', FILTER_SANITIZE_STRING)) {
|
||||
$this->errors[] = 'Ungültige Anfrage. Bitte beginnen Sie den Vorgan von vorne.';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strlen(filter_input(INPUT_POST, 'newpassword1', FILTER_SANITIZE_STRING)) < 8) {
|
||||
$this->errors['newpassword1'] = 'Das gewählte Paßwort ist zu kurz (Minimum: 8 Zeichen).';
|
||||
}
|
||||
if (filter_input(INPUT_POST, 'newpassword2', FILTER_SANITIZE_STRING) !== filter_input(INPUT_POST, 'newpassword1', FILTER_SANITIZE_STRING)) {
|
||||
$this->errors['newpassword2'] = 'Die Paßwörter stimmen nicht überein.';
|
||||
}
|
||||
return (count($this->errors) === 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user