class BotchaRecipeNoResubmit in BOTCHA Spam Prevention 7.3
Same name and namespace in other branches
- 6.2 controller/botcha_recipe.controller.inc \BotchaRecipeNoResubmit
- 6.3 controller/recipe/botcha.recipe.controller.inc \BotchaRecipeNoResubmit
- 7.2 controller/botcha_recipe.controller.inc \BotchaRecipeNoResubmit
Hierarchy
- class \BotchaRecipe
- class \BotchaRecipeNoResubmit
Expanded class hierarchy of BotchaRecipeNoResubmit
1 string reference to 'BotchaRecipeNoResubmit'
- botcha_update_7200 in ./
botcha.install - Create flexible relationships between recipe books and recipes and between recipe books and forms.
File
- controller/
recipe/ botcha.recipe.controller.inc, line 386 - Controller layer of the BotchaRecipe objects.
View source
class BotchaRecipeNoResubmit extends BotchaRecipe {
public function getInfo() {
parent::getInfo();
$this->description = t('Prevent form resubmission.' . ' Bots will try to resubmit old form prepared.' . ' Form is remembered, and only one submission is allowed.');
$this->error_text .= '<br />' . t('Form session reuse detected.') . ' ' . t('An old form was submitted again, which may happen' . ' if it was retrieved from browser history using "Back" button.') . '<br />' . t('Please try again - fill all entries on this page' . ' without going "Back".');
}
public function isSpam($form, $form_state) {
// @todo Reduce code duplication (determining which build_id to use).
// @see BotchaRecipe.applyRecipe()
// @see?
$isSpam = parent::isSpam($form, $form_state);
$build_id = isset($_POST['form_build_id']) ? $_POST['form_build_id'] : $form['#build_id'];
if ($cached = cache_get("botcha_{$build_id}", 'cache_form')) {
$data = $cached->data;
if (!isset($data['#cache_token']) || $data['#cache_token'] != $this
->getToken()) {
$isSpam = TRUE;
}
}
return $isSpam;
}
protected function getToken($value = '') {
// A bit customized version of drupal_get_token().
// @see drupal_get_token()
if (empty($_SESSION['botcha_session'])) {
$_SESSION['botcha_session'] = session_id();
}
// @todo Replace with function, depending on BOTCHA_SECRET.
// @see?
// @todo Abstract it.
//return md5($_SESSION['botcha_session'] . $value . BOTCHA_SECRET);
return drupal_hmac_base64($value, $_SESSION['botcha_session'] . drupal_get_private_key() . drupal_get_hash_salt());
}
public function apply(&$form, &$form_state) {
parent::apply($form, $form_state);
// Save build id.
$build_id = $form['#build_id'];
// @todo Reduce code duplication (determining which build_id to use).
// @see BotchaRecipebook.apply()
// @see?
$build_id_submit = isset($_POST['form_build_id']) ? $_POST['form_build_id'] : FALSE;
// Issue the client a new build_id, make sure that the form has it set
// in the hidden field.
if ($build_id_submit != $build_id) {
$form_state['post']['form_build_id'] = $build_id;
}
// 6 hours cache life time for forms should be plenty.
// @todo Provide UI for controlling the botcha_cache_expiration_timeout parameter.
// @see?
$expire = variable_get('botcha_cache_expiration_timeout', 21600);
$data = array();
$data['#cache_token'] = $this
->getToken();
// We use cache_form table.
// Sneaky, but why build our own table since we are working side-by-side with form API?
// @todo Abstract it.
//cache_set('botcha_' . $build_id, $data, 'cache_form', $_SERVER['REQUEST_TIME'] + $expire);
cache_set('botcha_' . $build_id, $data, 'cache_form', REQUEST_TIME + $expire);
}
public function handle($mode, $form, $form_state) {
parent::handle($mode, $form, $form_state);
// @todo Reduce code duplication (determining which build_id to use).
// @see BotchaRecipe.applyRecipe()
// @see?
$build_id = isset($_POST['form_build_id']) ? $_POST['form_build_id'] : $form['#build_id'];
// Invalidate cache so resubmit will not work.
// Make it to expire immediately.
$expire = 0;
$data = array();
// @todo Abstract it.
//cache_set('botcha_' . $build_id, $data, 'cache_form', $_SERVER['REQUEST_TIME'] + $expire);
cache_set('botcha_' . $build_id, $data, 'cache_form', REQUEST_TIME + $expire);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
BotchaRecipe:: |
protected | property | CSS to add to the page. | |
BotchaRecipe:: |
protected | property | Brief description of the recipe. It should contain explanation of how bots would fail with it and what the recipe exactly does. | |
BotchaRecipe:: |
public | property | Name of the field in the form to use in error messages (to mask botcha fields). | |
BotchaRecipe:: |
public | property | Text to give users if botcha recipe blocks submission. It should give some help to real human users in cases of disabled Javascript or CSS. | |
BotchaRecipe:: |
public | property | Identifier of the recipe. | |
BotchaRecipe:: |
protected | property | Javascript to add to the page. | |
BotchaRecipe:: |
protected | property | Method of recipe genration. | |
BotchaRecipe:: |
protected | property | ||
BotchaRecipe:: |
protected | property | Secret. | |
BotchaRecipe:: |
protected | property | Options that received as parameters turned into settings by merging with default values. | |
BotchaRecipe:: |
public | function | Used to get information about the recipe. Must be overridden with calling to parent::generateFormElements. @todo Switch from indexed array to associative. @see? | 2 |
BotchaRecipe:: |
public | function | Should be overridden. | 1 |
BotchaRecipe:: |
public | function | Used to get default recipe data structure. @todo ?Do we need it? | |
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
protected | function | 1 | |
BotchaRecipe:: |
protected | function | ||
BotchaRecipe:: |
protected | function | 3 | |
BotchaRecipe:: |
protected | function | ||
BotchaRecipe:: |
protected | function | ||
BotchaRecipe:: |
public | function | Should be overridden. | 1 |
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
protected | function | Universal getter. Wrapper getProperty is used to let class methods be used not only in getting default settings. It gives flexibility to make calls to the class methods in any order: the first of them will always calculate the property value and set… | |
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
protected | function | ||
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
protected | function | 1 | |
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
public | function | ||
BotchaRecipe:: |
public | function | Magic method __construct. | |
BotchaRecipeNoResubmit:: |
public | function |
Overrides BotchaRecipe:: |
|
BotchaRecipeNoResubmit:: |
public | function |
Used to get information about the recipe.
Must be overridden. Overrides BotchaRecipe:: |
|
BotchaRecipeNoResubmit:: |
protected | function | ||
BotchaRecipeNoResubmit:: |
public | function |
Handle form depending on the result of spam check. Overrides BotchaRecipe:: |
|
BotchaRecipeNoResubmit:: |
public | function |
Spam check. Overrides BotchaRecipe:: |