You are here

text_captcha.module in CAPTCHA 5.3

Same filename and directory in other branches
  1. 6 text_captcha/text_captcha.module

Implementation of a text based CAPTCHA.

File

text_captcha/text_captcha.module
View source
<?php

/**
 * @file
 * Implementation of a text based CAPTCHA.
 */

/**
 * Implementation of a simple text based CAPTCHA, for use with the CAPTCHA module
 */
define('TEXT_CAPTCHA_GENERATE_NONSENSE_WORDS', 0);
define('TEXT_CAPTCHA_USER_DEFINED_WORDS', 1);
define('TEXT_CAPTCHA_USER_DEFINED_WORD_MINIMUM', 20);

/**
 * Implementation of hook_help().
 */
function text_captcha_help($section) {
  switch ($section) {
    case 'admin/user/captcha/text_captcha':
      return '<p>' . t('In this challenge the visitor is asked for the n<sup>th</sup> word of a given phrase.') . '</p>';
  }
  return $output;
}

/**
 * Implementation of hook_menu().
 */
function text_captcha_menu($may_cache) {
  $items = array();
  if ($may_cache) {

    // add an administration tab for text_captcha
    $items[] = array(
      'path' => 'admin/user/captcha/text_captcha',
      'title' => t('Text CAPTCHA'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'text_captcha_settings_form',
      ),
      'type' => MENU_LOCAL_TASK,
    );
  }
  return $items;
}

/**
 * Administration form
 */
function text_captcha_settings_form() {
  $form = array();

  // radio buttons for selecting the kind of words to use
  $form['text_captcha_words'] = array(
    '#type' => 'radios',
    '#title' => t('Kind of words to use in the phrase'),
    '#options' => array(
      TEXT_CAPTCHA_GENERATE_NONSENSE_WORDS => t('Generate nonsense random words.'),
      TEXT_CAPTCHA_USER_DEFINED_WORDS => t('Use user defined words.'),
    ),
    '#default_value' => variable_get('text_captcha_words', TEXT_CAPTCHA_GENERATE_NONSENSE_WORDS),
  );

  // textarea for user defined words
  $form['text_captcha_userdefined_words'] = array(
    '#type' => 'textarea',
    '#title' => t('User defined words'),
    '#default_value' => variable_get('text_captcha_userdefined_words', ''),
    '#description' => t('Enter a bunch of space separated words (at least @min).', array(
      '@min' => TEXT_CAPTCHA_USER_DEFINED_WORD_MINIMUM,
    )),
  );

  // textfield for the number of words in the CAPTCHA phrase
  $form['text_captcha_word_quantity'] = array(
    '#type' => 'textfield',
    '#title' => t('Number of words in the phrase'),
    '#default_value' => (int) variable_get('text_captcha_word_quantity', 5),
    '#size' => 2,
    '#maxlength' => 2,
  );
  return system_settings_form($form);
}

/**
 * Validate function of the administration form
 */
function text_captcha_settings_form_validate($form_id, $form_values) {
  if ($form_id == 'text_captcha_settings_form') {
    if ($form_values['text_captcha_words'] == TEXT_CAPTCHA_USER_DEFINED_WORDS) {

      // check if there are at minimum TEXT_CAPTCHA_USER_DEFINED_WORD_MINIMUM user defined words
      if (count(explode(' ', $form_values['text_captcha_userdefined_words'])) < TEXT_CAPTCHA_USER_DEFINED_WORD_MINIMUM) {
        form_set_error('text_captcha_userdefined_words', t('You need to enter at least @min words if you want to use user defined words.', array(
          '@min' => TEXT_CAPTCHA_USER_DEFINED_WORD_MINIMUM,
        )));
      }
    }

    // chech text_captcha_word_quantity
    $word_quantity = (int) $form_values['text_captcha_word_quantity'];
    if ($word_quantity < 4 || $word_quantity > 10) {
      form_set_error('text_captcha_word_quantity', t('Number of words in the phrase should be between 4 and 10.'));
    }
  }
}

/**
 * function for generating a random nonsense word of a given number of characters
 */
function _text_captcha_generate_nonsense_word($characters) {
  $vowels = "bcdfghjklmnpqrstvwxyz";
  $consonants = "aeiou";
  $vowel_max = strlen($vowels) - 1;
  $consonant_max = strlen($consonants) - 1;
  $word = '';
  $o = mt_rand(0, 1);

  // randomly start with vowel or consonants
  for ($i = 0; $i < $characters; ++$i) {
    if (($i + $o) % 2) {
      $word .= $consonants[mt_rand(0, $consonant_max)];
    }
    else {
      $word .= $vowels[mt_rand(0, $vowel_max)];
    }
  }
  return $word;
}

/**
 * function for generating an array of words
 */
function _text_captcha_generate_words($num) {
  $words = array();
  if (variable_get('text_captcha_words', TEXT_CAPTCHA_GENERATE_NONSENSE_WORDS) == TEXT_CAPTCHA_USER_DEFINED_WORDS) {

    // use user defined words
    $uwords = explode(' ', variable_get('text_captcha_userdefined_words', ''));
    $keys = array_rand($uwords, $num);
    foreach ($keys as $key) {
      $words[] = $uwords[$key];
    }
  }
  else {

    // generate nonsense words
    for ($w = 0; $w < $num; ++$w) {
      $words[] = _text_captcha_generate_nonsense_word(mt_rand(3, 7));
    }
  }
  return $words;
}

/**
 * function that returns a textual represention of an ordinal
 */
function _text_captcha_ordinal($n) {
  $ordinalmap = array(
    1 => t('first'),
    2 => t('second'),
    3 => t('third'),
    4 => t('fourth'),
    5 => t('fifth'),
    6 => t('sixth'),
    7 => t('seventh'),
    8 => t('eighth'),
    9 => t('ninth'),
    10 => t('tenth'),
  );
  if (array_key_exists($n, $ordinalmap)) {
    return $ordinalmap[$n];
  }
  else {
    return "{$n}th";
  }
}

/**
 * Implementation of hook_captcha
 */
function text_captcha_captcha($op, $captcha_type = '') {
  switch ($op) {
    case 'list':
      return array(
        'Text',
      );
    case 'generate':
      if ($captcha_type == 'Text') {

        // generate words
        $words = _text_captcha_generate_words((int) variable_get('text_captcha_word_quantity', 5));

        // pick a random word
        $key = array_rand($words, 1);
        $answer = $words[$key];

        // store the answer and build the form elements
        $result = array();
        $result['solution'] = $answer;
        $result['form']['captcha_response'] = array(
          '#type' => 'textfield',
          '#title' => t('What is the @nth word in the phrase "@words"?', array(
            '@nth' => _text_captcha_ordinal($key + 1),
            '@words' => implode(' ', $words),
          )),
          '#weight' => 0,
          '#required' => TRUE,
          '#size' => 15,
        );
        return $result;
      }
  }
}

Functions

Namesort descending Description
text_captcha_captcha Implementation of hook_captcha
text_captcha_help Implementation of hook_help().
text_captcha_menu Implementation of hook_menu().
text_captcha_settings_form Administration form
text_captcha_settings_form_validate Validate function of the administration form
_text_captcha_generate_nonsense_word function for generating a random nonsense word of a given number of characters
_text_captcha_generate_words function for generating an array of words
_text_captcha_ordinal function that returns a textual represention of an ordinal

Constants

Namesort descending Description
TEXT_CAPTCHA_GENERATE_NONSENSE_WORDS Implementation of a simple text based CAPTCHA, for use with the CAPTCHA module
TEXT_CAPTCHA_USER_DEFINED_WORDS
TEXT_CAPTCHA_USER_DEFINED_WORD_MINIMUM