parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

Защита от флуда (собрание сочинений)

Spearance 30.03.2005 14:56

Для нерегулярных читателей хочу напомнить что в примерах появился интересный класс антифлуд или как я его называю антидаблпостинг.

Когдато давно в форуме проходил тред "Цифры на гифчике - 2 или портим малину спамерам" автор Sanja v.2, о дополнительной защите от роботов и спамеров с применением картинок.

Так вот просуммировав эти знания можно придти к такому коду:
# $Id: verify.p,v 1.0.4.0 2005/03/29 Eugene Spearance Exp $

@USE
antiflood.p

@CLASS
verify

@BASE
antiflood

@auto[]
# Перекрываем значения переменных из antiflood.p
$DOUBLE_FILE[_antidouble]
$EXPIRES_UID(1/(24*2))

########################################
# Метод перекрывающий @get[] из antiflood.p
#####
@get[_uid][_number]
^BASE:_anti_cache[]
^if(def $_uid){
	$UID[$_uid]
}{
	$_number[^_random_number[]]
	$VISITOR[^BASE:_visitor[]]
	$UID[^BASE:_get[$VISITOR]]
	^if(!def $UID){
		^rem{ *** генерим uid *** }
		$UID[^BASE:_generate[]]
		
		^rem{ *** сохраняем его в хешфайле *** }
		^BASE:_set[$UID;$_number;$EXPIRES_UID]

		^rem{ *** сохраняем какой uid был выдан данному посетителю последний разб чтобы если он *** }
		^rem{ *** положит на F5 что-нить тяжелое и пойдет на обед он не зафлудил бы нам сильно хешфайл *** }
		^BASE:_set[$VISITOR;$UID;$EXPIRES_VISITOR]
	}
}
$result[$UID]
### @get[]


########################################
# Метод перекрывающий @exec[] из antiflood.p
#####
@exec[number;code]
^BASE:_open[]
^file:lock[$DATA_DIR/$LOCK_FILE]{
	^if(^BASE:_get[$UID] eq $number){
		^rem{ *** в хешфайле есть соответствующий uid - выполняем код *** }
		$code

		^BASE:_delete[$UID]
		^BASE:_delete[$VISITOR]
	}{
		^rem{ *** э, князь, ты не прав: не знаем мы ничего про такой uid, до свидания *** }
		^throw[antiflood;Unknown UID]
	}
}
#end @exec[]


########################################
@_random_number[]
$result(^math:random(99999))
$result[^result.format[%05u]]
### End @_random_number[]


########################################
# Выводит заданное число в виде картинки
#####
@display_image[uuid;img_path][image;image_number;file_name]
^if(def $img_path){$img_path[^img_path.match[(.+?)/?^$][m]{$match.1}]}
$image[^image::create(100;20;0xFFFFFF)] 
^try{
	^rem{ *** Если $uuid не задан, будет выведена пустая картинка *** }
	$check[^BASE:_get[$uuid]]

	^rem{ *** Картинки с номерами имеют названия fsXY.gif, где X - номер на картинке, *** }
	^rem{ *** а Y - вариант. Число может быть представлено любой картинкой, чтобы     *** }
	^rem{ *** затруднить распознавание автоматическими средствами.                    *** }

	^for[i](0;4){
		$file_name[fs^math:random(9)^check.mid($i;1)]
		$image_number[^image::load[$img_path/${file_name}.gif]]

		^rem{ *** Накладываем картиноку на фон *** }
		^image.copy[$image_number](0;0;20;20;^eval($i*20);0) 
	}
}{
	$exception.handled(1)
	^image.line(0;0;99;19;0xDDDDDD)
	^image.line(99;0;0;19;0xDDDDDD)
	^image.rectangle(0;0;99;19;0xDDDDDD)
}
$response:body[^image.gif[]]
### End @display_image[]
Что необходимо для работы:
1. Создать img.html

Внутри него написать код:
@USE
verify.p

@main[]
^verify:display_image[$form:uuid;путь_к_папке_с_номерками]
Чтобы не делать блокировку картинок в .htaccess картинки можно положить вне веб пространства.

2. Сделать запись в .htaccess
RewriteEngine On

RewriteRule ^uuid_(.*)\.gif$  /путь_к файлу_от_корня/img.html?uuid=$1 [L]
3. Вставить в нужное место код
@USE
verify.p


###########################################################################
@main[]
# получаем uid
$uid[^verify:get[$form:uid]]

$is_show_form(1)

# пришло $form:uid - постят форму
^if(def $form:uid){
	^try{
		^verify:exec[$form:number]{
			^rem{ *** проверяем все-ли в форме заполнено как надо *** }
			^check[]

			^rem{ *** тут ваш код по добавлению пришедших данных куда вам больше хочется *** }
			<p>Ваше сообщение было успешно добавлено.</p>
			$is_show_form(0)
		}
	}{
		^if($exception.type eq "antiflood"){
			$exception.handled(1)
			<p>Неверно набран номер с картинки.</p>
			$is_show_form(0)
		}
		^if($exception.type eq "check"){
			$exception.handled(1)
			<p>Не заполнены обязательные поля формы.</p>
		}
	}
}

# если надо - показываем форму
^if($is_show_form){
	<form method="post">
		<input type="hidden" name="uid" value="$uid" />
    	
		<i>* Имя:</i><br />
		<input type="text" name="name" value="$form:name" /><br />
    	
		<i>E-mail:</i><br />
		<input type="text" name="email" value="$form:email" /><br />
    	
		<i>Сообщение:</i><br />
		<textarea name="text">$form:text</textarea><br />
    	    	<i>Введите номер с картинки:</i><br />
    	    	<input type="text" name="number" size="5" maxlength="5" /> <img src="/uuid_${uid}.gif" width="100" height="20" alt="включите поддержку картинок" />
		<input type="submit" name="action" value="Отправить" />
	</form>
}
#end @main[]


###########################################################################
@check[]
^if(!def $form:name){
	^throw[check;Не заполнены обязательные поля формы.]
}
#end @check[]
Вот собственно и всё. Использование этих классов, позволяет избавиться от базы данных.
Ссылка на файл с картинками вот.

P.S. Заранее извиняйте за обилие кода. Misha и Sanja, спасибо за идеи и код.