In this guide, I will show you how to integrate mosparo spam protection into grave CMS comments plugin.
Install mosparo
Install grav (In this guid I am using the docker installation. I am using the following docker-compose.yaml file)
Install grav comments plugin
After creating a new mosparo project, go to the project setting and notice the following settings for the next step:
Put the email
-Block behind the addComment
-Block in the following yaml files:
config/www/user/plugins/comments/comments.yaml
and config/www/user/config/plugins/comments.yaml
...
process:
# - captcha:
# recaptcha_secret: ej32oiej23oiej32oijeoi32jeio32je
- addComment:
- email:
subject: PLUGIN_COMMENTS.EMAIL_NEW_COMMENT_SUBJECT
body: "{% include 'forms/data.html.twig' %}"
- message: PLUGIN_COMMENTS.THANK_YOU_MESSAGE
- reset: true
Edit the following file on your grav Server:
config/www/user/plugins/comments/templates/partials/comments.html.twig
...
{% include "forms/fields/formname/formname.html.twig" %}
<!-- ######################## BEGIN Mosparo integration ######################## -->
<div style="margin-top:10px; margin-bottom:10px;" id="mosparo-box"></div>
<script src="https://mosparo.example.com/build/mosparo-frontend.js" defer></script>
<script>
var m;
window.onload = function(){
m = new mosparo(
'mosparo-box',
'https://mosparo.example.com',
'1d85f632-XXXX-XXXX-XXXX-082ae814ddee',
'kJPK7acjNuXXXXXXXXXXXXXXXXXXXXXXXXXXXajQdQa38',
{
loadCssResource: true
}
);
};
</script>
<!-- ######################## END Mosparo integration ######################## -->
<div class="buttons">
{% for button in grav.config.plugins.comments.form.buttons %}
<button class="button" type="{{ button.type|default('submit') }}">{{ button.value|t|default('Submit') }}</button>
...
Now we implemented mosparo into the frontend of the grav comments plugin. But for hacker or other criminal person it is easy to comment out the mosparo integration (live edit source code of webpage). To prevent this we need to integrate mopsaro into th backend of the grav comment plugin as well.
Open internal the internal shell of the grav container and perform following commands:
cd /config/www/user/plugins/comments
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'e21205b207c3ff031906575712edab6f13eb0b361f2085f1f1237b7126d785e826a450292b6cfd1d64d92e6563bbde02') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
./composer.phar require mosparo/php-api-client
rm composer.*
chown -R abc:users vendor
Now we replace the function onFormProcessed()
in the following file /config/www/user/plugins/comments/comments.php
:
Please edit the following parameters of the function new \Mosparo\ApiClient\Client()
in the following code block:
...
public function onFormProcessed(Event $event)
{
$form = $event['form'];
$action = $event['action'];
$params = $event['params'];
if (!$this->active) {
return;
}
switch ($action) {
case 'addComment':
// ######################## BEGIN Mosparo integration ########################
require_once(__DIR__ . '/vendor/autoload.php');
$client = new \Mosparo\ApiClient\Client("https://mosparo.example.com", "kJPK7acjNuXXXXXXXXXXXXXXXXXXXXXXXXXXXajQdQa38", "hjeJfcWf3BXXXXXXXXXXXXXXXXXXXXXXXXXXXhZKT53GD", ['verify' => true]);
$mosparoSubmitToken = $_POST['_mosparo_submitToken'];
$mosparoValidationToken = $_POST['_mosparo_validationToken'];
$result = $client->verifySubmission($_POST, $mosparoSubmitToken, $mosparoValidationToken);
if ($result->isSubmittable()) {
// Send the email and process the data
$post = isset($_POST['data']) ? $_POST['data'] : [];
$path = $this->grav['uri']->path();
$lang = htmlspecialchars(urldecode($post['lang']), ENT_QUOTES);
$text = htmlspecialchars(urldecode($post['text']), ENT_QUOTES);
$name = htmlspecialchars(urldecode($post['name']), ENT_QUOTES);
if ($name == "SuitDeer" || $name == "suitdeer" || $name == "DeerSuit" || $name == "deersuit" || $name == "Suit" || $name == "suit" || $name == "Deer" || $name == "deer" || $name == "Gero"|| $name == "gero" ) {
break;
}
$email = filter_var(urldecode($post['email']), FILTER_SANITIZE_EMAIL);
$title = htmlspecialchars(urldecode($post['title']), ENT_QUOTES);
if (isset($this->grav['user'])) {
$user = $this->grav['user'];
if ($user->authenticated) {
$name = $user->fullname;
$email = $user->email;
}
}
/** @var Language $language */
$language = $this->grav['language'];
$lang = $language->getLanguage();
$filename = DATA_DIR . 'comments';
$filename .= ($lang ? '/' . $lang : '');
$filename .= $path . '.yaml';
$file = File::instance($filename);
if (file_exists($filename)) {
$data = Yaml::parse($file->content());
$data['comments'][] = [
'text' => $text,
'date' => date('D, d M Y H:i:s', time()),
'author' => $name,
'email' => $email
];
} else {
$data = array(
'title' => $title,
'lang' => $lang,
'comments' => array([
'text' => $text,
'date' => date('D, d M Y H:i:s', time()),
'author' => $name,
'email' => $email
])
);
}
$file->save(Yaml::dump($data));
//clear cache
$this->grav['cache']->delete($this->comments_cache_id);
break;
}
// ######################## END Mosparo integration ########################
}
}
...
Now we replace the function prepareFormData()
in the following file config/www/user/plugins/comments/vendor/mosparo/php-api-client/src/RequestHelper.php
:
...
public function prepareFormData(array $formData): array
{
$formData = $this->cleanupFormData($formData);
$final_array = array();
$final_array = array(
'data[date]' => $formData['data']['date'],
'data[email]' => $formData['data']['email'],
'data[name]' => $formData['data']['name'],
'data[path]' => $formData['data']['path'],
'data[text]' => $formData['data']['text'],
'data[title]' => $formData['data']['title'],
'data[lang]' => $formData['data']['lang']
);
$data = [];
foreach ($final_array as $key => $value) {
if (is_array($value)) {
$data[$key] = $this->prepareFormData($value);
} else {
if (is_numeric($value)) {
$value = strval($value);
} else if ($value === null) {
$value = '';
}
$data[$key] = hash('sha256', $value);
}
}
ksort($data);
return $data;
}
...