241 lines
6.3 KiB
PHP
241 lines
6.3 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
|
||
|
|
use Gregwar\Captcha\CaptchaBuilder;
|
||
|
|
use Lewp\Resolve;
|
||
|
|
|
||
|
|
return new class extends Lewp\Module
|
||
|
|
{
|
||
|
|
|
||
|
|
const KEY_CSRF_TOKEN = 'csrf_token';
|
||
|
|
const KEY_CAPTCHA_PHRASE = 'captcha_phrase';
|
||
|
|
|
||
|
|
private function createForm()
|
||
|
|
{
|
||
|
|
$form = $this->createAndSetupElement(
|
||
|
|
'form',
|
||
|
|
'',
|
||
|
|
[
|
||
|
|
'method' => 'post',
|
||
|
|
'action' => '',
|
||
|
|
]
|
||
|
|
);
|
||
|
|
// LABEL NAME
|
||
|
|
$label_name = $this->createAndSetupElement(
|
||
|
|
'label',
|
||
|
|
$this->loadTextFile(Resolve::arrayToId([
|
||
|
|
$this->getLanguage(),
|
||
|
|
'name'
|
||
|
|
])),
|
||
|
|
[
|
||
|
|
'for' => 'name',
|
||
|
|
]
|
||
|
|
);
|
||
|
|
$form->appendChild($label_name);
|
||
|
|
// NAME INPUT
|
||
|
|
$name = $this->createAndSetupElement(
|
||
|
|
'input',
|
||
|
|
'',
|
||
|
|
[
|
||
|
|
'id' => 'name',
|
||
|
|
'name' => 'name',
|
||
|
|
'type' => 'text',
|
||
|
|
'value' => $_POST['name'] ?? '',
|
||
|
|
]
|
||
|
|
);
|
||
|
|
$form->appendChild($name);
|
||
|
|
// LABEL Email
|
||
|
|
$label_email = $this->createAndSetupElement(
|
||
|
|
'label',
|
||
|
|
$this->loadTextFile(Resolve::arrayToId([
|
||
|
|
$this->getLanguage(),
|
||
|
|
'email'
|
||
|
|
])),
|
||
|
|
[
|
||
|
|
'for' => 'email'
|
||
|
|
]
|
||
|
|
);
|
||
|
|
$form->appendChild($label_email);
|
||
|
|
// EMAIL INPUT
|
||
|
|
$email = $this->createAndSetupElement(
|
||
|
|
'input',
|
||
|
|
'',
|
||
|
|
[
|
||
|
|
'id' => 'email',
|
||
|
|
'name' => 'email',
|
||
|
|
'type' => 'email',
|
||
|
|
'value' => $_POST['email'] ?? '',
|
||
|
|
]
|
||
|
|
);
|
||
|
|
$form->appendChild($email);
|
||
|
|
// LABEL Message
|
||
|
|
$label_message = $this->createAndSetupElement(
|
||
|
|
'label',
|
||
|
|
$this->loadTextFile(Resolve::arrayToId([
|
||
|
|
$this->getLanguage(),
|
||
|
|
'message'
|
||
|
|
])),
|
||
|
|
[
|
||
|
|
'for' => 'message'
|
||
|
|
]
|
||
|
|
);
|
||
|
|
$form->appendChild($label_message);
|
||
|
|
// MESSAGE INPUT
|
||
|
|
$message = $this->createAndSetupElement(
|
||
|
|
'textarea',
|
||
|
|
$_POST['message'] ?? '',
|
||
|
|
[
|
||
|
|
'id' => 'message',
|
||
|
|
'name' => 'message',
|
||
|
|
]
|
||
|
|
);
|
||
|
|
$form->appendChild($message);
|
||
|
|
// LABEL Captcha
|
||
|
|
$label_captcha = $this->createAndSetupElement(
|
||
|
|
'label',
|
||
|
|
'',
|
||
|
|
[
|
||
|
|
'for' => self::KEY_CAPTCHA_PHRASE
|
||
|
|
]
|
||
|
|
);
|
||
|
|
$label_captcha->appendChild($this->generateCaptcha());
|
||
|
|
$form->appendChild($label_captcha);
|
||
|
|
// CAPTCHA INPUT
|
||
|
|
$captcha = $this->createAndSetupElement(
|
||
|
|
'input',
|
||
|
|
'',
|
||
|
|
[
|
||
|
|
'id' => 'captchainput',
|
||
|
|
'name' => self::KEY_CAPTCHA_PHRASE,
|
||
|
|
'type' => 'text',
|
||
|
|
]
|
||
|
|
);
|
||
|
|
$form->appendChild($captcha);
|
||
|
|
// SUBMIT BUTTON
|
||
|
|
$submit = $this->createAndSetupElement(
|
||
|
|
'button',
|
||
|
|
$this->loadTextFile(Resolve::arrayToId([
|
||
|
|
$this->getLanguage(),
|
||
|
|
'submit'
|
||
|
|
])),
|
||
|
|
[
|
||
|
|
'id' => 'submit',
|
||
|
|
'type' => 'submit',
|
||
|
|
]
|
||
|
|
);
|
||
|
|
$form->appendChild($submit);
|
||
|
|
// ADD CSRF CHECK
|
||
|
|
$form->appendChild($this->generateCsrfInput());
|
||
|
|
return $form;
|
||
|
|
}
|
||
|
|
|
||
|
|
private function generateCsrfInput()
|
||
|
|
{
|
||
|
|
// create token and save to session
|
||
|
|
$token = bin2hex(random_bytes(6));
|
||
|
|
$this->getSession()->set(self::KEY_CSRF_TOKEN, $token);
|
||
|
|
return $this->createAndSetupElement(
|
||
|
|
'input',
|
||
|
|
'',
|
||
|
|
[
|
||
|
|
'type' => 'hidden',
|
||
|
|
'name' => self::KEY_CSRF_TOKEN,
|
||
|
|
'value' => $token,
|
||
|
|
]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
private function validateCsrfInput() : bool
|
||
|
|
{
|
||
|
|
if (!$this->formSubmitted()) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
$token = $this->getSession()->get(self::KEY_CSRF_TOKEN);
|
||
|
|
if (
|
||
|
|
is_null($_POST[self::KEY_CSRF_TOKEN])
|
||
|
|
|| $_POST[self::KEY_CSRF_TOKEN] !== $token
|
||
|
|
) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private function generateCaptcha()
|
||
|
|
{
|
||
|
|
$builder = new CaptchaBuilder();
|
||
|
|
$builder->build();
|
||
|
|
$this->getSession()->set(self::KEY_CAPTCHA_PHRASE, $builder->getPhrase());
|
||
|
|
$img_captcha = $this->createAndSetupElement(
|
||
|
|
'img',
|
||
|
|
'',
|
||
|
|
[
|
||
|
|
'id' => 'captcha',
|
||
|
|
'src' => $builder->inline(),
|
||
|
|
]
|
||
|
|
);
|
||
|
|
return $img_captcha;
|
||
|
|
}
|
||
|
|
|
||
|
|
private function validateCaptcha() : bool
|
||
|
|
{
|
||
|
|
if (!$this->formSubmitted()) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
$valid_phrase = $this->getSession()->get(self::KEY_CAPTCHA_PHRASE);
|
||
|
|
if (
|
||
|
|
is_null($_POST[self::KEY_CAPTCHA_PHRASE])
|
||
|
|
|| $_POST[self::KEY_CAPTCHA_PHRASE] !== $valid_phrase
|
||
|
|
) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private function formSubmitted()
|
||
|
|
{
|
||
|
|
return (
|
||
|
|
!is_null($_POST['name'])
|
||
|
|
|| !is_null($_POST['email'])
|
||
|
|
|| !is_null($_POST['message'])
|
||
|
|
) ? true : false;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function run(array $options = []) : bool
|
||
|
|
{
|
||
|
|
if (!$this->validateCsrfInput()) {
|
||
|
|
$this->getSession()->getFlashBag()->add(
|
||
|
|
'error',
|
||
|
|
$this->loadTextFile(Resolve::arrayToId([
|
||
|
|
$this->getLanguage(),
|
||
|
|
'flashmessages',
|
||
|
|
'error',
|
||
|
|
'csrf-failed'
|
||
|
|
]))
|
||
|
|
);
|
||
|
|
}
|
||
|
|
if (!$this->validateCaptcha()) {
|
||
|
|
$this->getSession()->getFlashBag()->add(
|
||
|
|
'error',
|
||
|
|
$this->loadTextFile(Resolve::arrayToId([
|
||
|
|
$this->getLanguage(),
|
||
|
|
'flashmessages',
|
||
|
|
'error',
|
||
|
|
'captcha-failed'
|
||
|
|
]))
|
||
|
|
);
|
||
|
|
}
|
||
|
|
$form = $this->createForm();
|
||
|
|
$this->appendChild($form);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function onWebsocketRequest(
|
||
|
|
\Lewp\Websocket\Message $message
|
||
|
|
) : \Lewp\Websocket\Message {
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|