| Current Path : /home/j/u/v/juvelize/martine/components/com_easybookreloaded/models/ |
| Current File : /home/j/u/v/juvelize/martine/components/com_easybookreloaded/models/entry.php |
<?php
/**
* @copyright
* @package Easybook Reloaded - EBR for Joomla! 3.x
* @author Viktor Vogel <admin@kubik-rubik.de>
* @version 3.4.1.1-FREE - 2021-08-29
* @link https://kubik-rubik.de/ebr-easybook-reloaded
*
* @license GNU/GPL
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
defined('_JEXEC') || die('Restricted access');
use EasybookReloaded\{Helper, Content, Route};
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\{Factory, Language\Text, Uri\Uri, Mail\MailHelper};
use Joomla\Input\Input;
/**
* Class EasybookReloadedModelEntry
*
* @since 3.4.0-FREE
* @version 3.4.1.1-FREE
*/
class EasybookReloadedModelEntry extends BaseDatabaseModel
{
/**
* @var object $data
* @since 3.4.0-FREE
*/
protected $data;
/**
* @var int|string $id
* @since 3.4.0-FREE
*/
protected $id;
/**
* @var array $badWords
* @since 3.4.0-FREE
*/
protected $badWords;
/**
* @var object $input
* @since 3.4.0-FREE
*/
protected $input;
/**
* @var object $user
* @since 3.4.0-FREE
*/
protected $user;
/**
* @var object $session
* @since 3.4.0-FREE
*/
protected $session;
/**
* @var object $app
* @since 3.4.0-FREE
*/
protected $app;
/**
* EasybookReloadedModelEntry constructor.
*
* @throws Exception
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
public function __construct()
{
parent::__construct();
$this->app = Factory::getApplication();
$this->user = Factory::getUser();
$this->session = Factory::getSession();
$this->input = new Input();
$this->id = $this->input->getInt('cid', 0);
// Requests from the notification mail do send a valid hash value
if ($hashRequest = $this->input->getString('hash')) {
$hashData = explode('-', $hashRequest);
if (count($hashData) !== 2) {
return;
}
if (!empty($hashData[0]) && is_numeric($hashData[0])) {
$this->id = $hashData[0];
}
}
}
/**
* Stores the guestbook entries into the database
*
* @return bool|JTable
* @throws Exception
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
public function store()
{
$row = $this->getTable('entry', 'EasybookReloadedTable');
// Load all request variables
$data = $this->input->request->getArray();
array_walk(
$data,
static function (&$data) {
$data = htmlspecialchars(strip_tags(trim($data)));
}
);
// Get unfiltered request variable for gbtext
$data['gbtext'] = htmlspecialchars($this->input->getRaw('gbtext'), ENT_QUOTES);
$date = Factory::getDate();
if ($this->user->guest === 0 && !EASYBOOK_CANEDIT) {
$data['gbname'] = $this->user->get('username');
if (Helper::getParams('registeredUsername')) {
$data['gbname'] = $this->user->get('name');
}
$data['gbmail'] = $this->user->get('email');
}
if (!isset($data['id'])) {
$data['gbdate'] = $date->toSql();
$data['published'] = Helper::getParams('defaultPublished', 1);
$data['gbip'] = '0.0.0.0';
if (Helper::getParams('enableLog', true)) {
$data['gbip'] = Content::getIpAddress();
}
$data['gbcomment'] = null;
}
$data['gbimage'] = '';
$data['gbimageUpload'] = '';
// Validate the entered data
if (!$this->validate($data)) {
return false;
}
if (!$row->save($data)) {
throw new Exception(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 404);
}
$this->clearSession();
return $row;
}
/**
* Validates all entered data that was submitted by the user
*
* @param $data
*
* @return bool
* @throws Exception
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
private function validate(&$data): bool
{
$errors = [];
$error = false;
$gbId = Route::getGbId();
$this->session->clear('gbid', 'easybookreloaded');
if (!empty($gbId)) {
if ((int)$data['gbid'] !== $gbId) {
unset($data['gbid']);
$error = true;
$errors['gbid'] = true;
}
} else {
// No chance, my little friend :-)
unset($data['gbid']);
$error = true;
$errors['gbid'] = true;
}
if ($this->user->guest || Helper::getParams('enableSpamCheckRegistered')) {
$time = $this->session->get('time', null, 'easybookreloaded');
if ($time === '') {
$error = true;
$errors['sessionVariable'] = true;
} elseif ((time() - Helper::getParams('typeTimeSeconds')) <= $time) {
$error = true;
$errors['spamCheckResult'] = true;
}
if (Helper::getParams('enableSpamCheck', true)) {
$spamcheck1 = $this->session->get('spamcheck1', false, 'easybookreloaded');
$spamcheck2 = $this->session->get('spamcheck2', false, 'easybookreloaded');
$spamcheckResult = $this->session->get('spamCheckResult', null, 'easybookreloaded');
$spamCheckFieldName = $this->session->get('spamCheckFieldName', false, 'easybookreloaded');
if ((empty($spamcheck1)) || (empty($spamcheck2)) || ($spamcheckResult === null) || (empty($spamCheckFieldName))) {
$error = true;
$errors['sessionVariable'] = true;
} elseif ($data[$spamCheckFieldName] === '' || (int)$data[$spamCheckFieldName] !== $spamcheckResult) {
$error = true;
$errors['easycalccheck'] = true;
}
}
if (Helper::getParams('spamCheckQuestion') && (Helper::getParams('spamCheckQuestionQuestion') && Helper::getParams('spamCheckQuestionAnswer'))) {
$spamcheckQuestionFieldName = $this->session->get('spamCheckQuestionFieldName', null, 'easybookreloaded');
if ($spamcheckQuestionFieldName === '') {
$error = true;
$errors['sessionVariable'] = true;
} else {
$spamcheckQuestionAnswer = Text::_(Helper::getParams('spamCheckQuestionAnswer'));
if (strtolower($data[$spamcheckQuestionFieldName]) !== strtolower($spamcheckQuestionAnswer)) {
$error = true;
$errors['easycalccheckQuestion'] = true;
}
}
}
// Akismet - Further information: http://akismet.com/
if (Helper::getParams('akismet')) {
$akismetKey = Helper::getParams('akismetKey');
if ($akismetKey) {
$akismetUrl = Uri::getInstance()->toString();
$name = $data['gbname'];
$email = $data['gbmail'];
$comment = $data['gbtext'];
// Add title if provided
if (!empty($data['gbtitle'])) {
$comment = $data['gbtitle'] . ' ' . $comment;
}
// Check homepage if provided
$url = '';
if (!empty($data['gbpage'])) {
$url = $data['gbpage'];
}
$akismet = new Akismet($akismetUrl, $akismetKey);
$akismet->setCommentAuthor($name);
$akismet->setCommentAuthorEmail($email);
$akismet->setCommentAuthorURL($url);
$akismet->setCommentContent($comment);
if ($akismet->isCommentSpam()) {
$error = true;
$errors['akismet'] = true;
}
}
}
}
if (Helper::getParams('blockIp')) {
$gbIp = Content::getIpAddress();
$ips = array_map('trim', explode(',', Helper::getParams('blockIp')));
foreach ($ips as $ip) {
$ipRegexp = str_replace('x', '..?.?', preg_quote($ip, '@'));
if (preg_match('@' . $ipRegexp . '@', $gbIp)) {
$error = true;
$errors['easycalccheck'] = true;
}
}
}
if (Helper::getParams('timeLockIp') && Helper::getParams('enableLog')) {
$gbIp = Content::getIpAddress();
$dateLastEntry = $this->lastEntryDate($gbIp);
if (!empty($dateLastEntry)) {
date_default_timezone_set('UTC');
$dateBack = strftime("%Y-%m-%d %H:%M:%S", time() - Helper::getParams('timeLockIp'));
if ($dateLastEntry > $dateBack) {
$error = true;
$errors['iptimelock'] = true;
}
}
}
if (empty($data['gbname'])) {
$error = true;
$errors['name'] = true;
}
if (empty($data['gbtext'])) {
$error = true;
$errors['text'] = true;
} else {
if (preg_match_all('@\[img\].+\[/img\]@isU', $data['gbtext'], $matches)) {
$text = $data['gbtext'];
foreach ($matches[0] as $value) {
$img = str_replace(['\'', "\""], '', $value);
if (strpos($img, ' ') === true) {
$imgNew = substr($img, 0, strpos($img, ' ')) . '[/img]';
$text = str_replace($value, $imgNew, $text);
}
}
$data['gbtext'] = $text;
}
if (preg_match_all('@https?://(www\.)?([a-zA-Z0-9-]+\.)?([a-zA-Z0-9-]{3,65})(\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))@is', $data['gbtext'], $matches) && count($matches[0]) > Helper::getParams('maxNumberLinks')) {
$error = true;
$errors['tooManyLinks'] = true;
}
if (preg_match('@\[link.*\].*\[/link\]@isU', $data['gbtext'])) {
$error = true;
$errors['easycalccheck'] = true;
}
}
if (!empty($data['gbicq'])) {
$allowed = '@^[0-9]+$@';
if (!preg_match($allowed, $data['gbicq'])) {
$error = true;
$errors['icq'] = true;
}
}
if (!empty($data['gbskype'])) {
$allowed = '@^[A-Za-z0-9_\.-]+$@';
if (!preg_match($allowed, $data['gbskype'])) {
$error = true;
$errors['skype'] = true;
}
}
if (!empty($data['gbpage'])) {
$data['gbpage'] = str_replace(['\'', "\""], '', $data['gbpage']);
if (strpos($data['gbpage'], ' ') === true) {
$data['gbpage'] = substr($data['gbpage'], 0, strpos($data['gbpage'], ' '));
}
// Add scheme if not provided
if (!preg_match('@^https?://@i', $data['gbpage'])) {
$data['gbpage'] = 'http://' . $data['gbpage'];
}
$data['gbpage'] = htmlspecialchars($data['gbpage'], ENT_QUOTES);
}
if ((!empty($data['gbmail']) || Helper::getParams('requireMail', true)) && !MailHelper::isEmailAddress($data['gbmail'])) {
$error = true;
$errors['mail'] = true;
}
if ((Helper::getParams('showTitle', true)) && (empty($data['gbtitle']) && Helper::getParams('requireTitle', true))) {
$error = true;
$errors['title'] = true;
} elseif (!empty($data['gbtitle'])) {
$data['gbtitle'] = htmlspecialchars($data['gbtitle'], ENT_QUOTES);
}
if (Helper::getParams('badwordfilter', true)) {
$badWords = $this->getBadWordList();
$badWordFilterRegexp = Helper::getParams('badwordFilterRegex', false);
if (!empty($badWordFilterRegexp)) {
foreach ($badWords as $badWord) {
$data['gbtext'] = preg_replace('@' . $badWord . '@iU', '***', $data['gbtext']);
if (!empty($data['gbtitle'])) {
$data['gbtitle'] = preg_replace('@' . $badWord . '@iU', '***', $data['gbtitle']);
}
}
} else {
$data['gbtext'] = str_replace($badWords, '***', $data['gbtext']);
if (!empty($data['gbtitle'])) {
$data['gbtitle'] = str_replace($badWords, '***', $data['gbtitle']);
}
}
}
if (empty($data['eugdpr']) && Helper::getParams('eugdpr', true)) {
$error = true;
$errors['eugdpr'] = true;
}
if ($error) {
$this->session->set('errors', $errors, 'easybookreloaded');
$this->app->setUserState('ebValidationErrors', $errors);
$this->app->setUserState('ebValidationData', $data);
return false;
}
return true;
}
/**
* Checks the latest date of an entry from a specific IP address
*
* @param string $ip
*
* @return mixed
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
private function lastEntryDate(string $ip)
{
$query = "SELECT " . $this->_db->quoteName('gbdate') . " FROM " . $this->_db->quoteName('#__easybook') . " WHERE " . $this->_db->quoteName('gbip') . " = " . $this->_db->quote($ip) . " ORDER BY gbdate DESC";
$this->_db->setQuery($query);
return $this->_db->loadResult();
}
/**
* Loads all language bad words from the database for the validation check
*
* @return mixed
* @since 3.4.0-FREE
*/
private function getBadWordList()
{
if (empty($this->badWords)) {
$query = "SELECT " . $this->_db->quoteName('word') . " FROM " . $this->_db->quoteName('#__easybook_badwords') . " ORDER BY length(word) DESC";
$this->_db->setQuery($query);
$this->badWords = $this->_db->loadColumn();
}
return $this->badWords;
}
/**
* Clears saved session data if entry was stored successfully in the database
*
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
private function clearSession(): void
{
$this->session->clear('spamcheck1', 'easybookreloaded');
$this->session->clear('spamcheck2', 'easybookreloaded');
$this->session->clear('spamCheckResult', 'easybookreloaded');
$this->session->clear('spamCheckFieldName', 'easybookreloaded');
$this->session->clear('operator', 'easybookreloaded');
$this->session->clear('time', 'easybookreloaded');
$this->session->clear('spamCheckQuestionFieldName', 'easybookreloaded');
}
/**
* Deletes an entry using the Table class
*
* @return bool
* @throws Exception
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
public function delete(): bool
{
$row = $this->getTable('entry', 'EasybookReloadedTable');
if (!$row->delete($this->id)) {
throw new Exception(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 404);
}
return true;
}
/**
* Changes the status of an entry - online / offline
*
* @return int
* @throws Exception
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
public function publish(): int
{
$data = $this->getData();
$status = (int)!$data->published;
$query = "UPDATE " . $this->_db->quoteName('#__easybook') . " SET " . $this->_db->quoteName('published') . " = " . $this->_db->quote($status) . " WHERE " . $this->_db->quoteName('id') . " = " . $this->_db->quote($this->id) . " LIMIT 1;";
$this->_db->setQuery($query);
if (!$this->_db->execute()) {
return -1;
}
return $status;
}
/**
* Loads the entry data when a form is loaded
*
* @return JTable|mixed
* @throws Exception
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
public function getData()
{
// Error occurred - load the form with entered data again
if ($this->input->get('retry') === 'true') {
$this->data = $this->getTable('entry', 'EasybookReloadedTable');
$this->data->bind($this->app->getUserState('ebValidationData'));
}
// Modification process of an existing entry
if (empty($this->data) && !empty($this->id)) {
$query = "SELECT * FROM " . $this->_db->quoteName('#__easybook') . " WHERE " . $this->_db->quoteName('id') . " = " . $this->_db->quote($this->id);
$this->_db->setQuery($query);
$this->data = $this->_db->loadObject();
}
if (!empty($this->data)) {
$this->session->set('gbid', $this->data->gbid, 'easybookreloaded');
return $this->data;
}
// First loading of the form - new entry
$this->data = $this->getTable('entry', 'EasybookReloadedTable');
$this->data->id = 0;
if ($this->user->get('id')) {
if (Helper::getParams('registeredUsername')) {
$this->data->gbname = $this->user->get('name');
} else {
$this->data->gbname = $this->user->get('username');
}
$this->data->gbmail = $this->user->get('email');
}
// Okay, if we get here, then the gbid must be set. If not, then we have a direct call.
$gbId = Route::getGbId();
if (empty($gbId)) {
$this->session->set('gbid', 0, 'easybookreloaded');
}
return $this->data;
}
/**
* Creates math exercise and saves values to the session for the validation process
*
* @throws Exception
* @version 3.4.1.0-FREE
* @since 3.4.0-FREE
*/
public function getCalcCheck(): void
{
if ($this->user->guest || Helper::getParams('enableSpamCheckRegistered')) {
$this->session->set('time', time(), 'easybookreloaded');
if (Helper::getParams('enableSpamCheck', true)) {
$spamcheck1 = random_int(1, Helper::getParams('maxValue', 20));
$spamcheck2 = random_int(1, Helper::getParams('maxValue', 20));
$spamcheckResult = $spamcheck1 + $spamcheck2;
$operatorOutput = '+';
$operator = random_int(0, 1);
if (Helper::getParams('operator') === 1 || (Helper::getParams('operator') === 2 && $operator === 1)) {
$spamcheckResult = $spamcheck1 - $spamcheck2;
$operatorOutput = '-';
}
$spamCheckFieldName = $this->getRandomValue();
$this->session->set('spamcheck1', $spamcheck1, 'easybookreloaded');
$this->session->set('spamcheck2', $spamcheck2, 'easybookreloaded');
$this->session->set('spamCheckResult', $spamcheckResult, 'easybookreloaded');
$this->session->set('spamCheckFieldName', $spamCheckFieldName, 'easybookreloaded');
$this->session->set('operator', $operatorOutput, 'easybookreloaded');
}
if (Helper::getParams('spamCheckQuestion') && (Helper::getParams('spamCheckQuestionQuestion') && Helper::getParams('spamCheckQuestionAnswer'))) {
$spamcheckQuestionFieldName = $this->getRandomValue();
$this->session->set('spamCheckQuestionFieldName', $spamcheckQuestionFieldName, 'easybookreloaded');
}
}
}
/**
* Creates a random string for the calc check field ID
*
* @return string
* @throws Exception
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
private function getRandomValue(): string
{
$randomString = '';
// first character has to be a letter
$characters = range('a', 'z');
$randomString .= $characters[random_int(0, 25)];
// other characters arbitrarily
$numbers = range(0, 9);
$characters = array_merge($characters, $numbers);
$stringLength = random_int(4, 12);
for ($i = 0; $i < $stringLength; $i++) {
$randomString .= $characters[random_int(0, 35)];
}
return $randomString;
}
/**
* Saves the comment from authorized users with admin rights for the component
*
* @return int
* @throws Exception
* @since 3.4.0-FREE
* @version 3.4.1.1-FREE
*/
public function saveComment(): int
{
$row = $this->getTable('entry', 'EasybookReloadedTable');
// Load all request variables
$data = $this->input->request->getArray();
array_walk(
$data,
static function (&$data) {
$data = htmlspecialchars(strip_tags(trim($data)));
}
);
// Get unfiltered request variable for gbtext
$data['gbcomment'] = htmlspecialchars($this->input->getRaw('gbcomment'), ENT_QUOTES);
$gbId = Route::getGbId();
$this->session->clear('gbid', 'easybookreloaded');
if (empty($gbId)) {
return 0;
}
if ((int)$data['gbid'] !== $gbId) {
return 0;
}
if (!$row->save($data)) {
throw new Exception(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 404);
}
return $data['id'] ?? 0;
}
/**
* Loads entry data from the database using JTable
*
* @param int $id
*
* @return object
* @throws Exception
* @since 3.4.0-FREE
* @version 3.4.1.0-FREE
*/
public function getRow(int $id): object
{
$table = $this->getTable('entry', 'EasybookReloadedTable');
$table->load($id);
return $table;
}
}