Create an insecure bank application
This commit is contained in:
23
webroot/lib/View/AccessDeniedPage.php
Normal file
23
webroot/lib/View/AccessDeniedPage.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
class AccessDeniedPage extends BankingPage
|
||||
{
|
||||
public function sendHeader(): void
|
||||
{
|
||||
http_response_code(403);
|
||||
}
|
||||
|
||||
public function sendTitle(): void
|
||||
{
|
||||
echo 'Zugriff Verweigert';
|
||||
}
|
||||
|
||||
public function sendMainContent(): void
|
||||
{
|
||||
echo '<h1>Zugriff Verweigert</h1>';
|
||||
echo '<p>Bitte wähle eine andere Seite in der Navigation aus.</p>';
|
||||
}
|
||||
}
|
32
webroot/lib/View/BankingPage.php
Normal file
32
webroot/lib/View/BankingPage.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
use Model\Context;
|
||||
|
||||
abstract class BankingPage extends Html
|
||||
{
|
||||
public function __construct(protected Context $context)
|
||||
{
|
||||
}
|
||||
|
||||
public function sendHead(): void
|
||||
{
|
||||
parent::sendHead();
|
||||
echo '<link href="/style.css" rel="stylesheet">';
|
||||
}
|
||||
|
||||
public function sendBody(): void
|
||||
{
|
||||
echo '<nav><ul>';
|
||||
foreach ($this->context->navigation as $entry) {
|
||||
$entry->send($this->context);
|
||||
}
|
||||
echo '</ul></nav><main>';
|
||||
$this->sendMainContent();
|
||||
echo '</main>';
|
||||
}
|
||||
|
||||
abstract public function sendMainContent(): void;
|
||||
}
|
60
webroot/lib/View/BookingOverviewPage.php
Normal file
60
webroot/lib/View/BookingOverviewPage.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
class BookingOverviewPage extends BankingPage
|
||||
{
|
||||
public array $bookings = [];
|
||||
public int $finalBalance = 0;
|
||||
|
||||
public function sendTitle(): void
|
||||
{
|
||||
echo 'Umsatz-Übersicht';
|
||||
}
|
||||
|
||||
protected static function bookingText(int $type, ?string $relatedName)
|
||||
{
|
||||
switch ($type) {
|
||||
case 1:
|
||||
return "Einzahlung";
|
||||
case 2:
|
||||
return "Auszahlung";
|
||||
case 3:
|
||||
if ($relatedName === null) {
|
||||
return "Überweisung ins Leere";
|
||||
} else {
|
||||
return "Überweisung an {$relatedName}";
|
||||
}
|
||||
case 4:
|
||||
if ($relatedName === null) {
|
||||
return "Überweisung aus dem Nichts";
|
||||
} else {
|
||||
return "Überweisung von {$relatedName}";
|
||||
}
|
||||
default:
|
||||
return "Unbekannter Vorgang";
|
||||
}
|
||||
}
|
||||
|
||||
public function sendMainContent(): void
|
||||
{
|
||||
$userName = htmlspecialchars($this->context->session->user->name);
|
||||
|
||||
echo "<h1>Umsatz-Übersicht für {$userName}</h1>";
|
||||
if (empty($this->bookings)) {
|
||||
echo '<p><i>Keine Buchungen</i></p>';
|
||||
}
|
||||
echo '<table>';
|
||||
foreach ($this->bookings as $booking) {
|
||||
$timeInfo = date('d.m.Y H:i', $booking['time']);
|
||||
$text = htmlspecialchars(static::bookingText($booking['type'], $booking['relatedName']));
|
||||
$comment = htmlspecialchars($booking['comment']);
|
||||
$amount = MoneyFormatter::formatAmount($booking['amount']);
|
||||
echo "<tr><td>{$timeInfo}</td><td>{$text}</td><td>{$comment}</td><td>{$amount}</td></tr>";
|
||||
}
|
||||
$final = MoneyFormatter::formatAmount($this->finalBalance);
|
||||
echo "<tr><td></td><td>Kontostand:</td><td></td><td>{$final}</td></tr>";
|
||||
echo '</table>';
|
||||
}
|
||||
}
|
106
webroot/lib/View/CashTransactionPage.php
Normal file
106
webroot/lib/View/CashTransactionPage.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
use Model\Context;
|
||||
|
||||
class CashTransactionPage extends BankingPage
|
||||
{
|
||||
protected string $title;
|
||||
|
||||
public string $fieldCustomer = '';
|
||||
public string $fieldAmount = '';
|
||||
public string $fieldText = '';
|
||||
public bool $formWasSent = false;
|
||||
|
||||
public bool $errorCustomerNotFound = false;
|
||||
public bool $errorAmountInvalid = false;
|
||||
public bool $errorAmountZero = false;
|
||||
public bool $errorInsufficientFunds = false;
|
||||
public bool $errorTextTooLong = false;
|
||||
|
||||
public bool $success = false;
|
||||
public ?string $successCustomer = null;
|
||||
public ?int $successAmount = null;
|
||||
|
||||
public function __construct(protected Context $context)
|
||||
{
|
||||
parent::__construct($context);
|
||||
switch ($context->currentPage) {
|
||||
case '/deposit.php':
|
||||
$this->title = 'Einzahlen';
|
||||
break;
|
||||
case '/withdraw.php':
|
||||
$this->title = 'Auszahlen';
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($_POST['customer'], $_POST['amount'], $_POST['text'])) {
|
||||
$this->formWasSent = true;
|
||||
$this->fieldCustomer = (string) $_POST['customer'];
|
||||
$this->fieldAmount = (string) $_POST['amount'];
|
||||
$this->fieldText = (string) $_POST['text'];
|
||||
}
|
||||
}
|
||||
|
||||
public function renderErrors(): string
|
||||
{
|
||||
$errors = [];
|
||||
if ($this->errorCustomerNotFound) {
|
||||
$errors[] = '[!] Der angegebene Kunde konnte nicht gefunden werden.';
|
||||
}
|
||||
if ($this->errorAmountInvalid) {
|
||||
$errors[] = '[!] Der eingegebene Betrag entspricht nicht dem vorgesehenen Format.';
|
||||
}
|
||||
if ($this->errorAmountZero) {
|
||||
$errors[] = '[!] Der Betrag muss größer als 0,00 € sein.';
|
||||
}
|
||||
if ($this->errorInsufficientFunds) {
|
||||
$errors[] = '[!] Das Konto des Kunden ist nicht ausreichend gedeckt.';
|
||||
}
|
||||
if ($this->errorTextTooLong) {
|
||||
$errors[] = '[!] Der Buchungstext darf nicht länger als 100 Zeichen sein.';
|
||||
}
|
||||
return implode('<br>', $errors);
|
||||
}
|
||||
|
||||
public function sendTitle(): void
|
||||
{
|
||||
echo $this->title;
|
||||
}
|
||||
|
||||
public function sendMainContent(): void
|
||||
{
|
||||
$customer = htmlspecialchars($this->fieldCustomer);
|
||||
$amount = htmlspecialchars($this->fieldAmount);
|
||||
$text = htmlspecialchars($this->fieldText);
|
||||
|
||||
echo "<h1>{$this->title}</h1>";
|
||||
|
||||
$errors = $this->renderErrors();
|
||||
if (!empty($errors)) {
|
||||
echo "<p class=\"error\">{$errors}</p>";
|
||||
}
|
||||
|
||||
if ($this->success) {
|
||||
$successCustomer = htmlspecialchars($this->successCustomer);
|
||||
$successAmount = MoneyFormatter::formatAmount($this->successAmount);
|
||||
switch ($this->context->currentPage) {
|
||||
case '/deposit.php':
|
||||
echo "<p class=\"success\">Es wurden {$successAmount} auf das Konto von {$successCustomer} eingezahlt.</p>";
|
||||
break;
|
||||
case '/withdraw.php':
|
||||
echo "<p class=\"success\">Es wurden {$successAmount} aus dem Konto von {$successCustomer} ausgezahlt.</p>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
echo "<form class=\"cash-transaction\" action=\"{$this->context->currentPage}\" method=\"post\">";
|
||||
echo "<label for=\"customer\">Kundenname:</label><input type=\"text\" name=\"customer\" id=\"customer\" maxlength=\"20\" value=\"{$customer}\"><br>";
|
||||
echo "<label for=\"amount\">Betrag:</label><input type=\"text\" name=\"amount\" id=\"amount\" value=\"{$amount}\"><br>";
|
||||
echo "<label for=\"text\">Buchungstext:</label><input type=\"text\" name=\"text\" id=\"text\" value=\"{$text}\"><br>";
|
||||
echo "<input type=\"submit\" value=\"{$this->title}\">";
|
||||
echo '</form>';
|
||||
}
|
||||
}
|
28
webroot/lib/View/FrontPage.php
Normal file
28
webroot/lib/View/FrontPage.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
class FrontPage extends BankingPage
|
||||
{
|
||||
public function sendTitle(): void
|
||||
{
|
||||
echo 'Online-Banking';
|
||||
}
|
||||
|
||||
public function sendMainContent(): void
|
||||
{
|
||||
echo '<h1>Online-Banking Instanz mit Sicherheitslücken</h1>';
|
||||
echo '<p>In dieser Applikation gibt es mindestens zwei Sicherheitslücken. Kannst du sie ausnutzen?</p>';
|
||||
echo '<p>Ablauf:</p><ol>';
|
||||
echo '<li>Registriere dich über das entsprechende Formular.</li>';
|
||||
echo '<li>Nenne mir deinen Nutzernamen.</li>';
|
||||
echo '<li>Du erhältst 1000,00 € Startkapital.</li>';
|
||||
echo '<li>Nutze mindestens eine Sicherheitslücke aus und erschleiche 1 Million € oder mehr.</li>';
|
||||
echo '</ol>';
|
||||
echo '<p class="pre">Die beiden beabsichtigten Lücken wurden jeweils in einem kurzen Text-Dokument beschrieben. Die SHA256-Hashwerte dieser Dokumente lauten:<br><br>';
|
||||
echo 'bb86334c2c4ecb4c3f35c35392a3867824216f0e23bee5c7b60953e41d7b7590 sicherheitsluecke-1.txt<br>';
|
||||
echo '75dde975461d9d20c81aa10a42ae886820bead9201bc032b16ce00dba873d89a sicherheitsluecke-2.txt<br><br>';
|
||||
echo 'Damit kann später zweifelsfrei überprüft werden, ob eine gefundene Sicherheitslücke tatsächlich beabsichtigt war oder ob es sich um eine weitere, unbeabsichtigte Lücke handelt.</p>';
|
||||
}
|
||||
}
|
30
webroot/lib/View/Html.php
Normal file
30
webroot/lib/View/Html.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
abstract class Html implements Sendable
|
||||
{
|
||||
public function send(): void
|
||||
{
|
||||
$this->sendHeader();
|
||||
echo '<!doctype html>';
|
||||
$this->sendHead();
|
||||
$this->sendBody();
|
||||
}
|
||||
|
||||
public function sendHeader(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function sendHead(): void
|
||||
{
|
||||
echo '<meta charset="UTF-8"><title>';
|
||||
$this->sendTitle();
|
||||
echo '</title>';
|
||||
}
|
||||
|
||||
abstract public function sendTitle(): void;
|
||||
|
||||
abstract public function sendBody(): void;
|
||||
}
|
44
webroot/lib/View/LoginPage.php
Normal file
44
webroot/lib/View/LoginPage.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
class LoginPage extends BankingPage
|
||||
{
|
||||
public string $fieldUsername = '';
|
||||
public string $fieldPassword = '';
|
||||
public bool $formWasSent = false;
|
||||
|
||||
public bool $errorLoginDataInvalid = false;
|
||||
|
||||
public function __construct(...$args)
|
||||
{
|
||||
parent::__construct(...$args);
|
||||
if (isset($_POST['username'], $_POST['password'])) {
|
||||
$this->formWasSent = true;
|
||||
$this->fieldUsername = (string) $_POST['username'];
|
||||
$this->fieldPassword = (string) $_POST['password'];
|
||||
}
|
||||
}
|
||||
|
||||
public function sendTitle(): void
|
||||
{
|
||||
echo 'Einloggen';
|
||||
}
|
||||
|
||||
public function sendMainContent(): void
|
||||
{
|
||||
$username = htmlspecialchars($this->fieldUsername);
|
||||
$password = htmlspecialchars($this->fieldPassword);
|
||||
|
||||
echo '<h1>Einloggen</h1>';
|
||||
if ($this->errorLoginDataInvalid) {
|
||||
echo '<p class="error">[!] Der Login war nicht erfolgreich.</p>';
|
||||
}
|
||||
echo '<form class="login" action="/login.php" method="post">';
|
||||
echo "<label for=\"username\">Nutzername:</label><input type=\"text\" name=\"username\" id=\"username\" maxlength=\"20\" value=\"{$username}\"><br>";
|
||||
echo "<label for=\"password\">Passwort:</label><input type=\"password\" name=\"password\" id=\"password\" value=\"{$password}\"><br>";
|
||||
echo '<input type="submit" value="Einloggen">';
|
||||
echo '</form>';
|
||||
}
|
||||
}
|
21
webroot/lib/View/LoginRedirection.php
Normal file
21
webroot/lib/View/LoginRedirection.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
use Model\Context;
|
||||
|
||||
class LoginRedirection implements Sendable
|
||||
{
|
||||
public function __construct(protected Context $context)
|
||||
{
|
||||
}
|
||||
|
||||
public function send(): void
|
||||
{
|
||||
$sessid = $this->context->session->newSessid;
|
||||
http_response_code(303); // "see other" redirection
|
||||
setcookie('sessid', $sessid, time() + 86400 * 365); // session creation
|
||||
header('Location: /bookings.php'); // login redirection
|
||||
}
|
||||
}
|
16
webroot/lib/View/LogoutRedirection.php
Normal file
16
webroot/lib/View/LogoutRedirection.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
use Model\Context;
|
||||
|
||||
class LogoutRedirection implements Sendable
|
||||
{
|
||||
public function send(): void
|
||||
{
|
||||
http_response_code(303); // "see other" redirection
|
||||
setcookie('sessid', '', 1); // delete cookie
|
||||
header('Location: /'); // redirection to home
|
||||
}
|
||||
}
|
30
webroot/lib/View/MoneyFormatter.php
Normal file
30
webroot/lib/View/MoneyFormatter.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
class MoneyFormatter
|
||||
{
|
||||
public static function formatAmount(int $amount): string
|
||||
{
|
||||
if ($amount < 0) {
|
||||
$inner = static::formatAmount(-$amount);
|
||||
return "<span class=\"negative\">- {$inner}</span>";
|
||||
}
|
||||
$euro = intdiv($amount, 100);
|
||||
$cent = sprintf("%02d", $amount % 100);
|
||||
return "{$euro},{$cent} €";
|
||||
}
|
||||
|
||||
public static function parseAmount(string $amount): ?int
|
||||
{
|
||||
$pattern = '/^([0-9]+)(,([0-9]{2}))?$/';
|
||||
if (preg_match($pattern, $amount, $matches)) {
|
||||
$euro = (int) $matches[1];
|
||||
$cent = (int) ($matches[3] ?? 0);
|
||||
$amount = 100 * $euro + $cent;
|
||||
return (int) $amount;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
77
webroot/lib/View/RegisterPage.php
Normal file
77
webroot/lib/View/RegisterPage.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
use Model\Context;
|
||||
|
||||
class RegisterPage extends BankingPage
|
||||
{
|
||||
public string $fieldUsername = '';
|
||||
public string $fieldPassword = '';
|
||||
public string $fieldRepeatPassword = '';
|
||||
public bool $formWasSent = false;
|
||||
|
||||
public bool $errorUsernameEmpty = false;
|
||||
public bool $errorUsernameTooLong = false;
|
||||
public bool $errorUsernameInUse = false;
|
||||
public bool $errorPasswordEmpty = false;
|
||||
public bool $errorPasswordsMismatch = false;
|
||||
|
||||
public function __construct(...$args)
|
||||
{
|
||||
parent::__construct(...$args);
|
||||
if (isset($_POST['username'], $_POST['password'], $_POST['repeat_password'])) {
|
||||
$this->formWasSent = true;
|
||||
$this->fieldUsername = (string) $_POST['username'];
|
||||
$this->fieldPassword = (string) $_POST['password'];
|
||||
$this->fieldRepeatPassword = (string) $_POST['repeat_password'];
|
||||
}
|
||||
}
|
||||
|
||||
public function sendTitle(): void
|
||||
{
|
||||
echo 'Registrieren';
|
||||
}
|
||||
|
||||
public function renderErrors(): string
|
||||
{
|
||||
$errors = [];
|
||||
if ($this->errorUsernameEmpty) {
|
||||
$errors[] = '[!] Bitte wähle einen Nutzernamen.';
|
||||
}
|
||||
if ($this->errorUsernameTooLong) {
|
||||
$errors[] = '[!] Der Nutzername darf nicht länger als 20 Zeichen sein.';
|
||||
}
|
||||
if ($this->errorUsernameInUse) {
|
||||
$errors[] = '[!] Der Nutzername wird bereits von einem Account verwendet.';
|
||||
}
|
||||
if ($this->errorPasswordEmpty) {
|
||||
$errors[] = '[!] Bitte wähle ein Passwort.';
|
||||
}
|
||||
if ($this->errorPasswordsMismatch) {
|
||||
$errors[] = '[!] Die beiden Passwörter stimmen nicht überein.';
|
||||
}
|
||||
return implode('<br>', $errors);
|
||||
}
|
||||
|
||||
public function sendMainContent(): void
|
||||
{
|
||||
$username = htmlspecialchars($this->fieldUsername);
|
||||
$password = htmlspecialchars($this->fieldPassword);
|
||||
$repeatPassword = htmlspecialchars($this->fieldRepeatPassword);
|
||||
|
||||
echo '<h1>Registrieren</h1>';
|
||||
echo '<p>Erstelle dir hier einen neuen Banking-Account.</p>';
|
||||
$errors = $this->renderErrors();
|
||||
if (!empty($errors)) {
|
||||
echo "<p class=\"error\">{$errors}</p>";
|
||||
}
|
||||
echo '<form class="register" action="/register.php" method="post">';
|
||||
echo "<label for=\"username\">Nutzername:</label><input type=\"text\" name=\"username\" id=\"username\" maxlength=\"20\" value=\"{$username}\"><br>";
|
||||
echo "<label for=\"password\">Passwort:</label><input type=\"password\" name=\"password\" id=\"password\" value=\"{$password}\"><br>";
|
||||
echo "<label for=\"repeat_password\">Passwort wiederholen:</label><input type=\"password\" name=\"repeat_password\" id=\"repeat_password\" value=\"{$repeatPassword}\"><br>";
|
||||
echo '<input type="submit" value="Jetzt registrieren">';
|
||||
echo '</form>';
|
||||
}
|
||||
}
|
9
webroot/lib/View/Sendable.php
Normal file
9
webroot/lib/View/Sendable.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
interface Sendable
|
||||
{
|
||||
public function send(): void;
|
||||
}
|
89
webroot/lib/View/TransferPage.php
Normal file
89
webroot/lib/View/TransferPage.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace View;
|
||||
|
||||
use Model\Context;
|
||||
|
||||
class TransferPage extends BankingPage
|
||||
{
|
||||
public string $fieldTarget = '';
|
||||
public string $fieldAmount = '';
|
||||
public string $fieldText = '';
|
||||
public bool $formWasSent = false;
|
||||
|
||||
public bool $errorTargetNotFound = false;
|
||||
public bool $errorAmountInvalid = false;
|
||||
public bool $errorAmountZero = false;
|
||||
public bool $errorInsufficientFunds = false;
|
||||
public bool $errorTextTooLong = false;
|
||||
|
||||
public bool $success = false;
|
||||
public ?string $successTarget = null;
|
||||
public ?int $successAmount = null;
|
||||
|
||||
public function __construct(protected Context $context)
|
||||
{
|
||||
parent::__construct($context);
|
||||
|
||||
if (isset($_POST['target'], $_POST['amount'], $_POST['text'])) {
|
||||
$this->formWasSent = true;
|
||||
$this->fieldTarget = (string) $_POST['target'];
|
||||
$this->fieldAmount = (string) $_POST['amount'];
|
||||
$this->fieldText = (string) $_POST['text'];
|
||||
}
|
||||
}
|
||||
|
||||
public function renderErrors(): string
|
||||
{
|
||||
$errors = [];
|
||||
if ($this->errorTargetNotFound) {
|
||||
$errors[] = '[!] Der angegebene Nutzername (Zielkonto) konnte nicht gefunden werden.';
|
||||
}
|
||||
if ($this->errorAmountInvalid) {
|
||||
$errors[] = '[!] Der eingegebene Betrag entspricht nicht dem vorgesehenen Format.';
|
||||
}
|
||||
if ($this->errorAmountZero) {
|
||||
$errors[] = '[!] Der Betrag muss größer als 0,00 € sein.';
|
||||
}
|
||||
if ($this->errorInsufficientFunds) {
|
||||
$errors[] = '[!] Dein Konto ist nicht ausreichend gedeckt.';
|
||||
}
|
||||
if ($this->errorTextTooLong) {
|
||||
$errors[] = '[!] Der Buchungstext darf nicht länger als 100 Zeichen sein.';
|
||||
}
|
||||
return implode('<br>', $errors);
|
||||
}
|
||||
|
||||
public function sendTitle(): void
|
||||
{
|
||||
echo 'Überweisen';
|
||||
}
|
||||
|
||||
public function sendMainContent(): void
|
||||
{
|
||||
$target = htmlspecialchars($this->fieldTarget);
|
||||
$amount = htmlspecialchars($this->fieldAmount);
|
||||
$text = htmlspecialchars($this->fieldText);
|
||||
|
||||
echo "<h1>Überweisen</h1>";
|
||||
|
||||
$errors = $this->renderErrors();
|
||||
if (!empty($errors)) {
|
||||
echo "<p class=\"error\">{$errors}</p>";
|
||||
}
|
||||
|
||||
if ($this->success) {
|
||||
$successTarget = htmlspecialchars($this->successTarget);
|
||||
$successAmount = MoneyFormatter::formatAmount($this->successAmount);
|
||||
echo "<p class=\"success\">Es wurden {$successAmount} an {$successTarget} überwiesen.</p>";
|
||||
}
|
||||
|
||||
echo "<form class=\"transfer\" action=\"{$this->context->currentPage}\" method=\"post\">";
|
||||
echo "<label for=\"target\">Zielkonto (Nutzername):</label><input type=\"text\" name=\"target\" id=\"target\" maxlength=\"20\" value=\"{$target}\"><br>";
|
||||
echo "<label for=\"amount\">Betrag:</label><input type=\"text\" name=\"amount\" id=\"amount\" value=\"{$amount}\"><br>";
|
||||
echo "<label for=\"text\">Buchungstext:</label><input type=\"text\" name=\"text\" id=\"text\" value=\"{$text}\"><br>";
|
||||
echo "<input type=\"submit\" value=\"Überweisen\">";
|
||||
echo '</form>';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user