Всего 125 977 комментариев

Наумов Алексей
14 января 2022, 10:24
+2
Мне часто приходится делать подобную работу, когда достается старый сайт, обычно почти всегда при его обновлении я перехожу на Fenom. Так что с меня плюсик)
Vladimir
14 января 2022, 10:11
0
Спасибо помогло, странно для всех сайтов ставлю 7.3+ а тут стояла 5.6.
Николай Савин
14 января 2022, 09:50
+1
Повысьте версию php до актуальной. У вас 5.6 вероятно. Минимальная 7.0
Николай Савин
14 января 2022, 09:48
+3
Александр, а чего бы вам, раз уж зашел разговор не написать развернутый материал на тему «101 способ защиты от спама в MODX». Собрать все что упоминалось, сделать какой-то обзор плюсов и минусов. Будет огромная польза для сообщества и вам для кармы
Александр Мельник
14 января 2022, 09:19
+1
спасибо за такой развернутый ответ.
Vladimir
14 января 2022, 09:10
0
Странно почему то и обычная сортировка по тв не работает код простейший
'where' => '{"news-type:=": "[[!#GET.sort-type]]"}',
Тэвэха news-type теговая и значения приходят туда правильные
Vladimir
14 января 2022, 07:21
0
Странно, пытался сменить в настройках при создании как документ, тоже самое получилось 500
Vladimir
14 января 2022, 06:24
0
Вчера вечером всё работало, а на утро через 10 часов перестало
Алексей Соин
13 января 2022, 23:16
+4
Поправил, единственное пока не придумал, как получше обрабатывать комменты и на подумать остается обработка фильтров/модификаторов и свойств, но скорее всего в дальнейшем буду просто выводить предупреждение, что фильтр :default нужно вручную править для fenom синтаксиса и т.д.

Anton
13 января 2022, 20:48
2
+6
Всем привет!

Я борюсь таким образом:
1. Проверяю в сниппете для FormIt с помощи регулярки на наличие ссылки типа site.com И email типа name@mail.com в поле текстового сообщения + в каждом поле такую проверку делаю (Имя, Телефон, Название фирмы, все поля чекаю). Если обнаружена ссылка, то возвращаю false и сообщение, что «Ссылки или электронные адреса в данном поле не разрешены. Вы можете приложить Word, Excel, PDF или текстовый файл с подробным описанием, ссылками и email.».
2. Использую сниппет csrfhelper:
<input type="hidden" name="csrf_token" value="[[!csrfhelper? &key=`contact-us`]]">
А в вызов FormIt добавляю хук csrfhelper_formit.
3. Разумеется, добавляю простейшую проверку на пустоту скрытое поле URL (можно назвать поле любым человекоподобным словом)
<input class="form-control visually-hidden" type="text" name="url" value="">
4. Добавляю таймер на страницу, который не разрешает отправлять форму, если ты менее 15 секунд на странице (обычно спам-боты отправляют спам моментально после загрузки страницы, менее чем за 1-5 секунд) и показываю пользователю сообщение об ошибке «Слишком быстро нажата кнопка Отправить. Подождите, пожалуйста, 15 секунд и отправьте еще раз.»
В форме Fenom-тэг с текущим временем в формате UNIX. Сравниваем его в антиспам-сниппете.
<input class="form-control visually-hidden" type="text" name="formtime" value="{time()}">
5. На всякий случай вырезаю все html-тэги из всех полей :stripTags
6. В доработке хук, который чекает прилагаемый файл через форму: только pdf, word, excel, txt, zip, png, jpg; не больше 25 мегабайт (вроде как стандартное ограничение всеми почтовиками). Если проверка не пройдена, то показываем вежливое сообщение, что мы принимаем только такие файлы и не больше 25 мб.
7. Не забываем про проверку на обязательность заполнения полей со стороны клиента с помощью тэга required. А также проставляем все необходимы типы данных в инпутах: type=«email», type=«number» или же type=«text» во всех полях!

Мое мнение — самое главное вернуть очень понятный человеку и вежливый ответ, что здесь ссылки не разрешены в целях борьбы со спамом, Вы можете приложить файл со всеми ссылками и адресами.

{$_modx->runSnippet('!FormIt', [

	'hooks' => 'antiSpam,spam,csrfhelper_formit,email',

	'spamCheckIp' => '1',
	'csrfKey' => 'contact-us',

	'validate' => 'name:stripTags:required,email:stripTags:required,message:stripTags:required,url:blank',

	'successMessage' => '<div class="alert alert-success mt-3" role="alert"><b>Спасибо!</b> Ваше сообщение было отправлено.</div>'

])}
Сам сниппет antiSpam:
<?php
$name = $hook->getValue('name');
$phone = $hook->getValue('phone');
$email = $hook->getValue('email');
$message = $hook->getValue('message');
$contact_attachment = $hook->getValue('contact_attachment');

$regExpGSM = '/(\d{3})(?:(?:-*|\s*|\.*|\)*|\)\s*))(\d{3})(?:(?:-*|\s*|\.*|\)*))(\d{3})/';
$regExpURL = '/[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b[-a-zA-Z0-9@:%_\+.~#?&=]*/i';
$regExpEmail = '/(?<=\b)\w([\w\.\-_0-9])*(@| at )[\w0-9][\w\-_0-9]*((\.| DOT )[\w\-_0-9]+)+(?=\b)/';
$regExpExt = '/^([A-Za-z0-9-_.])+\.(png|jpe?g|gif|bmp)$/';

/*Check regExp email*/
if (preg_match($regExpEmail, $name)) {
    $hook->addError('emailInName', 'Email-адреса не разрешены в поле Имя. Вы можете приложить Word, Excel, PDF или текстовый файл с подробным описанием, ссылками и электронной почтой.');
    return false;
} elseif (preg_match($regExpEmail, $message)) {
    $hook->addError('emailInMessage', 'Email-адреса не разрешены в поле Сообщения. Вы можете приложить Word, Excel, PDF или текстовый файл с подробным описанием, ссылками и электронной почтой.');
    return false;

    /*Check regExp URL's*/
} elseif (preg_match($regExpURL, $name)) {
    $hook->addError('linkInName', 'Ссылки на сайты не разрешены в поле Имя. Вы можете приложить Word, Excel, PDF или текстовый файл с подробным описанием, ссылками и электронной почтой.');
    return false;
} elseif (preg_match($regExpURL, $message)) {
    $hook->addError('linkInMessage', 'Ссылки на сайты не разрешены в поле Сообщения. Вы можете приложить Word, Excel, PDF или текстовый файл с подробным описанием, ссылками и электронной почтой.');
    return false;
	
/*И так далее по всем полям чекаю регулярками выше*/

/*Проверяем, что не слишком быстро нажимается кнопка "Отправить"*/
} elseif ($_POST['formtime'] > time() - 15) {
    $hook->addError('fastSending', 'Слишком быстро нажата кнопка Отправить. Подождите, пожалуйста, 15 секунд и отправьте еще раз.');
    return false;

} else {
    return true;
}
В самой форме плейсхолдеры для вывода человекопонятных ошибок:
[[!+fi.error.csrf_token:notempty=`
<div class="alert alert-warning mt-3 mb-2">[[!+fi.error.csrf_token]]</div>
`]]
[[!+fi.error.fastSending:notempty=`
<div class="alert alert-warning mt-3 mb-2">[[!+fi.error.fastSending]]</div>
`]]

[[+fi.statusMessage]]
[[+fi.successMessage]]

<input type="text" class="form-control"
       placeholder="Ваше имя *"
       name="name"
       value="[[!+fi.name]]"
       required>
<span class="error_name">[[+fi.error.name]]</span>
До этого у меня была всего-лишь одна проверка regExp на наличие ссылки и email в поле Сообщения (message). Спама почти не было, но стал приходить спам типа Buy our viagra on usa-pharma.shop, пропускались такие ссылки. Более длинная регулярка уже иногда блочила любой текст, если юзер пишет сообщение и после точки сразу пишет слово нового предложения.

Добавил проверку на 15 секундное ожидание (человеку просто не реально раньше 15й секунды заполнить все поля и отправить форму). Можно поставить 5 секунд.

После этого стали приходить сообщение только от человеков, никакого спама.

Не отловленные ошибки надо бы логгировать (у меня был этот кусок кода для логгирования не отправленных форм через FormIt, но не могу найти, он в старых хуках был).

Ну и можно по IP блочить вдобавок, как выше уже предложено.

Я не очень силен в PHP, как смог так и написал, поэтому большая просьба помочь хорошо доработать данный сниппет/хук и поделиться им здесь.
Алексей Соин
13 января 2022, 19:21
+6
Выводится сниппет если не понять что за тег, а так пока переводит чанки, сниппеты, системные значения. Доработать даный конвертер не трудно, но не хотелось бы тратить время на сервис, который никому не нужен. Хотелось бы услышать, нужен ли он кому-то (например лайк/дизлайк вот этого моего коммента, или в гитхабе плюсами). Если нужно, выделю время на доработки.
Владислав
13 января 2022, 19:21
0
Спасибо большое, я думаю с ним сделаю то что мне нужно
Александр Мельник
13 января 2022, 19:19
+2
на кнопку вешаете слушатель события click.
При клике выполняете
— считываете год, например с дата атрибута кнопки
— делаете ajax запрос на файл php передавая год

В php файле
— инициализируете modx (https://docs.modx.com/current/en/extending-modx/modx-class/loading-externally)
— вызываете сниппет pdoResources составив для него условие выбора года
— сниппет вернет html

Получаете этот html в том скрипте где делали ajax запрос. Выводите на страницу в нужно место.
Михаил
13 января 2022, 19:00
0
pdoArchive глянь
Fullstack
13 января 2022, 17:59
0
Круто! Единственное, он преобразует только сниппеты
Fullstack
13 января 2022, 17:57
+1
Он не на всех сайтах применим. На простых — да. А что-то более менее гибкое уже не разработаешь. Или когда стоит (особенно ребром) вопрос скорости сайта
Дима Сайт old см. профиль
13 января 2022, 14:42
0
@alex, возможно вам подойдет компонент modstore.pro/packages/other/anotherpages

Или можно написать плагин на 404 ошибку и там уже брать ресурс от первой части URL, и добавлять 2ю часть, конвертируя (как бы) фразу Russia-Moscow-Moldova-Kishinev в export_country=22, export_city=33, import_country=44, import_city=55 но учтите что есть города типа Ростов-На-Дону поэтому разделитель в URL лучше взять такой, чтобы не встречался в названиях городов, например | или транслитирировать названия с этим учетом.

То ли ещё будет, когда вы столкнетесь с одинаковыми названиями населенных пунктов…
Например:
Москва — город, столица России.
Москва, Кировская область, Верхошижемский район (деревня).
Москва, Псковская область, Порховский район (деревня)
Москва, Тверская область, Пеновский район (деревня)
и т.п.

Вообще, задача может иметь ряд подводных камней, если не чувствуете уверенность лучше перенесите топик из Вопросов в раздел Работа, переводить числовые id в текстовые значения всегда довольно проблематично
Vladimir
13 января 2022, 13:55
0
Лог такой
0.0002599: pdoTools loaded
0.0000460: xPDO query object created
0.0010431: Included list of tvs: img
0.0003240: leftJoined modTemplateVarResource as TVimg
0.0006390: Added selection of modResource: SQL_CALC_FOUND_ROWS `id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `alias_visible`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type`, `uri`, `uri_override`, `hide_children_in_tree`, `show_in_tree`, `properties`
0.0000269: Added selection of modTemplateVarResource: IFNULL(`value`, '') AS `tv.img`
0.0000231: Replaced TV conditions
0.0017660: Processed additional conditions
0.0027940: Added where condition: 0=, modResource.parent:IN(8,9,20), modResource.template:IN(7), modResource.published=1, modResource.deleted=0
0.0000138: Replaced TV conditions
0.0002139: Sorted by modResource.parent, ASC
0.0002470: Sorted by modResource.menuindex, ASC
0.0000048: Limited to 8, offset 0
0.0006542: SQL prepared "SELECT SQL_CALC_FOUND_ROWS `modResource`.`id`, `modResource`.`type`, `modResource`.`contentType`, `modResource`.`pagetitle`, `modResource`.`longtitle`, `modResource`.`description`, `modResource`.`alias`, `modResource`.`alias_visible`, `modResource`.`link_attributes`, `modResource`.`published`, `modResource`.`pub_date`, `modResource`.`unpub_date`, `modResource`.`parent`, `modResource`.`isfolder`, `modResource`.`introtext`, `modResource`.`richtext`, `modResource`.`template`, `modResource`.`menuindex`, `modResource`.`searchable`, `modResource`.`cacheable`, `modResource`.`createdby`, `modResource`.`createdon`, `modResource`.`editedby`, `modResource`.`editedon`, `modResource`.`deleted`, `modResource`.`deletedon`, `modResource`.`deletedby`, `modResource`.`publishedon`, `modResource`.`publishedby`, `modResource`.`menutitle`, `modResource`.`donthit`, `modResource`.`privateweb`, `modResource`.`privatemgr`, `modResource`.`content_dispo`, `modResource`.`hidemenu`, `modResource`.`class_key`, `modResource`.`context_key`, `modResource`.`content_type`, `modResource`.`uri`, `modResource`.`uri_override`, `modResource`.`hide_children_in_tree`, `modResource`.`show_in_tree`, `modResource`.`properties`, IFNULL(`TVimg`.`value`, '') AS `tv.img` FROM `modx_site_content` AS `modResource` LEFT JOIN `modx_site_tmplvar_contentvalues` `TVimg` ON `TVimg`.`contentid` = `modResource`.`id` AND `TVimg`.`tmplvarid` = 23 WHERE  ( `modResource`.`parent` IN (8,9,20) AND `modResource`.`template` IN (7) AND `modResource`.`published` = 1 AND `modResource`.`deleted` = 0 )  ORDER BY modResource.parent ASC, modResource.menuindex ASC LIMIT 8 "
0.0011570: SQL executed
0.0003688: Total rows: 2
0.0000539: Rows fetched
0.0066609: Prepared and processed TVs
0.0017228: Loaded "modChunk" with name "newsTpl"
0.0034592: Compiled Fenom chunk with name "modchunk/30"
0.0171959: Returning processed chunks
0.0317860: Total time
8 912 896: Memory usage
0.0107419: pdoTools loaded
0.0004611: Created inline "modChunk" with name "f7da63f2d337d08ca9dcacc531069c1e"
0.0072119: Loaded "modSnippet" with name "pdoResources"
0.0416641: Created inline "modChunk" with name "e6747421ac951eec87076a3f44c6a184"
0.0601921: Total time
8 912 896: Memory usage
Илья
13 января 2022, 11:50
0
Здравствуйте! Не могли бы вы показать ваш вызов сниппета полностью? Сейчас бьюсь с этой же задачей, не могу добиться вывода ресурсов с множественным выводом.
Спасибо!