You are here

protected_submissions.module in Protected Submissions 7

Same filename and directory in other branches
  1. 8 protected_submissions.module

Blocks submissions from anonymous users that contain pre-defined strings.

File

protected_submissions.module
View source
<?php

/**
 * @file
 * Blocks submissions from anonymous users that contain pre-defined strings.
 */

/**
 * Implements hook_help().
 */
function protected_submissions_help($path, $arg) {
  switch ($path) {
    case 'admin/help#protected_submissions':

      // Help text for the admin section, using the module name in the path.
      return t('<h2>Description</h2>
      Protected Submissions is a light-weight, non-invasive spam protection module
      that enables rejection of node, comment, webform, user profile and contact form
      submissions which contain undesired language scripts or preset patterns.

      <h2>How it works</h2>
      If a user attempts to post a webform, node, comment or a contact form
      containing undesired language script characters or a preset pattern in the name,
      subject or any other text type field, the submission is rejected.

      Roles can be configured to bypass the Protected Submissions validation.

      The number of rejected submissions is shown on the
      <a href="/admin/reports/status">Reports > Status report</a> page.

      The rejected messages are logged and can be viewed on the
      <a href="/admin/reports/dblog">Reports > Recent log messages</a> page.

      <h2>Configuration</h2>

      Go to the <a href="/admin/config/content/protected_submissions">Configuration >
      Content authoring > Protected Submissions configuration</a> page, select
      allowed language scripts, number of characters for language scripts validation,
      and set the reject message text and the patterns to ban.

      If you want to protect only anonymous submissions, then make sure to go
      to <a href="/admin/people/permissions#module-protected_submissions">People
      > Permissions</a> page and put a check mark for authenticated user role
      next to the <i>Bypass Protected Submissions validation</i> option.

      <h2>Troubleshooting</h2>

      Report all problems on <a href="https://www.drupal.org/project/issues/search/protected_submissions">the project\'s issues</a> page.');
  }
}

/**
 * Implements hook_permission().
 */
function protected_submissions_permission() {
  return array(
    'bypass protected_submissions' => array(
      'title' => t('Bypass <a href="@protected_submissions">Protected Submissions</a> validation', array(
        '@protected_submissions' => url('admin/config/content/protected_submissions'),
      )),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function protected_submissions_menu() {
  $items = array();
  $items['admin/config/content/protected_submissions'] = array(
    'title' => 'Protected Submissions',
    'description' => 'Configure the Protected Submissions module settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'protected_submissions_config',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

/**
 * Administrative settings form.
 */
function protected_submissions_config() {
  $form = array();
  $form['#attached']['css'] = array(
    drupal_get_path('module', 'protected_submissions') . '/css/protected_submissions.css',
  );

  // Allowed language scripts.
  $language_scripts = protected_submissions_variable_get('protected_submissions_language_scripts');
  $language_scripts_keys = array_keys($language_scripts);
  $form['protected_submissions_allowed_scripts'] = array(
    '#type' => 'checkboxes',
    '#options' => drupal_map_assoc($language_scripts_keys),
    '#default_value' => protected_submissions_variable_get('protected_submissions_allowed_scripts'),
    '#title' => t('Allowed language scripts'),
    '#required' => TRUE,
    '#description' => t('Select language scripts allowed for submission.'),
  );
  $form['protected_submissions_check_quantity'] = array(
    '#type' => 'textfield',
    '#default_value' => protected_submissions_variable_get('protected_submissions_check_quantity'),
    '#title' => t('Number of characters to validate'),
    '#size' => 5,
    '#required' => TRUE,
    '#description' => t('Spam texts can be constructed using mixed characters from multiple languages.
    Checking each character would cause performance overhead, so we validate only randomly selected characters.
    Indicate how many characters from submitted text should be validated for allowed language scripts.'),
  );

  // Message displayed to users when submission is rejected.
  $form['protected_submissions_reject_message'] = array(
    '#type' => 'textfield',
    '#default_value' => protected_submissions_variable_get('protected_submissions_reject_message'),
    '#title' => t('Reject message'),
    '#size' => 60,
    '#maxlength' => 256,
    '#required' => TRUE,
    '#description' => t('Enter a message to display when submission of undesired pattern is attempted.'),
  );

  // Reject patterns.
  $reject_patterns = protected_submissions_variable_get('protected_submissions_reject_patterns');
  $form['protected_submissions_reject_patterns'] = array(
    '#type' => 'textarea',
    '#rows' => 10,
    '#columns' => 60,
    '#default_value' => strtolower($reject_patterns),
    '#title' => t('Reject patterns'),
    '#required' => TRUE,
    '#description' => t('Enter words or patterns to reject, separating them with commas or new lines.'),
  );

  // Give users option to enable/disable logging if Database Logging is on.
  if (module_exists('dblog')) {
    $form['protected_submissions_log_rejected'] = array(
      '#type' => 'checkbox',
      '#title' => t('Log rejected messages?'),
      '#default_value' => protected_submissions_variable_get('protected_submissions_log_rejected'),
      '#description' => t('Registering every rejected message could quickly flood your website\'s log. If you don\'t need to analyze rejected messages, then you might want to disable logging.'),
    );
  }
  return system_settings_form($form);
}

/**
 * Utility function for getting variable values.
 */
function protected_submissions_variable_get($variable_name) {

  // Have to use the Unicode Character Ranges since only some languages work with
  // $match = preg_match("/\p{$lang_script}/u", $randomChar); PCRE
  // explained on https://www.php.net/manual/en/regexp.reference.unicode.php
  $ucr = [
    'Adlam' => [
      '1E900 - 1E95F',
    ],
    'Ahom' => [
      '11700 - 1173F',
    ],
    'Anatolian Hieroglyphs' => [
      '14400 - 1467F',
    ],
    'Arabic' => [
      '0600 - 06FF',
      '0750 - 077F',
      '08A0 - 08FF',
      'FB50 - FDFF',
      'FE70 - FEFF',
      '10A80 - 10A9F',
      '10A60 - 10A7F',
    ],
    'Aramaic' => [
      '10840 - 1085F',
    ],
    'Armenian' => [
      '0530 - 058F',
      'FB00 - FB4F',
    ],
    'Avestan' => [
      '10B00 - 10B3F',
    ],
    'Balinese' => [
      '1B00 - 1B7F',
    ],
    'Bamum' => [
      'A6A0 - A6FF',
      '16800 - 16A3F',
    ],
    'Bassa Vah' => [
      '16AD0 - 16AFF',
    ],
    'Batak' => [
      '1BC0 - 1BFF',
    ],
    'Bengali and Assamese' => [
      '0980 - 09FF',
    ],
    'Bhaiksuki' => [
      '11C00 - 11C6F',
    ],
    'Bopomofo' => [
      '3100 - 312F',
      '31A0 - 31BF',
    ],
    'Brahmi' => [
      '11000 - 1107F',
    ],
    'Buginese' => [
      '1A00 - 1A1F',
    ],
    'Buhid' => [
      '1740 - 175F',
    ],
    'Canadian Aboriginal' => [
      '1400 - 167F',
      '18B0 - 18FF',
    ],
    'Carian' => [
      '102A0 - 102DF',
    ],
    'Caucasian Albanian' => [
      '10530 - 1056F',
    ],
    'Chakma' => [
      '11100 - 1114F',
    ],
    'Cham' => [
      'AA00 - AA5F',
    ],
    'Cherokee' => [
      '13A0 - 13FF',
      'AB70 - ABBF',
    ],
    'Chorasmian' => [
      '10FB0 - 10FDF',
    ],
    'CJK' => [
      '2E80 - 2EFF',
      '2F00 - 2FDF',
      '2FF0 - 2FFF',
      '3000 - 303F',
      '31C0 - 31EF',
      '3200 - 32FF',
      '3300 - 33FF',
      '3400 - 4DBF',
      '4E00 - 9FFC',
      'F900 - FAFF',
      'FE30 - FE4F',
      '20000 - 2A6DD',
      '2A700 - 2B734',
      '2B740 - 2B81D',
      '2B820 - 2CEA1',
      '2CEB0 - 2EBE0',
      '2F800 - 2FA1F',
      '30000 - 3134A',
    ],
    'Coptic' => [
      '2C80 - 2CFF',
      '0370 - 03FF',
      '102E0 - 102FF',
    ],
    'Cuneiform' => [
      '12000 - 123FF',
      '12400 - 1247F',
      '12480 - 1254F',
      '103A0 - 103DF',
      '10380 - 1039F',
    ],
    'Currency Symbols' => [
      '20A0 - 20CF',
    ],
    'Cypriot Syllabary' => [
      '10800 - 1083F',
    ],
    'Cyrillic' => [
      '0400 - 04FF',
      '0500 - 052F',
      '2DE0 - 2DFF',
      '1C80 - 1C8F',
    ],
    'Deseret' => [
      '10400 - 1044F',
    ],
    'Devanagari' => [
      '0900 - 097F',
      'A8E0 - A8FF',
    ],
    'Dives Akuru' => [
      '11900 - 1195F',
    ],
    'Dogra' => [
      '11800 - 1184F',
    ],
    'Egyptian Hieroglyphs' => [
      '13000 - 1342F',
      '13430 - 1343F',
    ],
    'Elbasan' => [
      '10500 - 1052F',
    ],
    'Elymaic' => [
      '10FE0 - 10FFF',
    ],
    'Ethiopic' => [
      '1200 - 137F',
      '1380 - 139F',
      '2D80 - 2DDF',
      'AB00 - AB2F',
    ],
    'Georgian' => [
      '10A0 - 10FF',
      '1C90 - 1CBF',
      '2D00 - 2D2F',
    ],
    'Glagolitic' => [
      '2C00 - 2C5F',
      '1E000 - 1E02F',
    ],
    'Gothic' => [
      '10330 - 1034F',
    ],
    'Grantha' => [
      '11300 - 1137F',
    ],
    'Greek' => [
      '0370 - 03FF',
      '1F00 - 1FFF',
      '10140 - 1018F',
    ],
    'Gujarati' => [
      '0A80 - 0AFF',
    ],
    'Gunjala Gondi' => [
      '11D60 - 11DAF',
    ],
    'Gurmukhi' => [
      '0A00 - 0A7F',
    ],
    'Hangul Jamo' => [
      '1100 - 11FF',
      'A960 - A97F',
      'D7B0 - D7FF',
      '3130 - 318F',
      'FF00 - FFEF',
    ],
    'Hangul Syllables' => [
      'AC00 - D7AF',
    ],
    'Hanifi Rohingya' => [
      '10D00 - 10D3F',
    ],
    'Hanunoo' => [
      '1720 - 173F',
    ],
    'Hatran' => [
      '108E0 - 108FF',
    ],
    'Hebrew' => [
      '0590 - 05FF',
      'FB00 - FB4F',
    ],
    'Hiragana' => [
      '3040 - 309F',
    ],
    'Javanese' => [
      'A980 - A9DF',
    ],
    'Kaithi' => [
      '11080 - 110CF',
    ],
    'Kana' => [
      '1B100 - 1B12F',
      '1B000 - 1B0FF',
      '1B130 - 1B16F',
    ],
    'Kanbun' => [
      '3190 - 319F',
    ],
    'Kannada' => [
      '0C80 - 0CFF',
    ],
    'Katakana' => [
      '30A0 - 30FF',
      '31F0 - 31FF',
      'FF00 - FFEF',
    ],
    'Kayah Li' => [
      'A900 - A92F',
    ],
    'Kharoshthi' => [
      '10A00 - 10A5F',
    ],
    'Khitan Small Script' => [
      '18B00 - 18CFF',
    ],
    'Khmer' => [
      '1780 - 17FF',
      '19E0 - 19FF',
    ],
    'Khojki' => [
      '11200 - 1124F',
    ],
    'Khudawadi' => [
      '112B0 - 112FF',
    ],
    'Lao' => [
      '0E80 - 0EFF',
    ],
    'Latin' => [
      '0000 - 007F',
      '0080 - 00FF',
      '0100 - 017F',
      '0180 - 024F',
      '0250 - 02AF',
      '02B0 - 02FF',
      '1D00 - 1D7F',
      '1D80 - 1DBF',
      '1E00 - 1EFF',
      '2070 - 209F',
      '2100 - 214F',
      '2150 - 218F',
      '2C60 - 2C7F',
      'A720 - A7FF',
      'AB30 - AB6F',
      'FB00 - FB4F',
      'FF00 - FFEF',
      '2000 - 206F',
    ],
    'Lepcha' => [
      '1C00 - 1C4F',
    ],
    'Limbu' => [
      '1900 - 194F',
    ],
    'Lisu' => [
      'A4D0 - A4FF',
      '11FB0 - 11FBF',
    ],
    'Lycian' => [
      '10280 - 1029F',
    ],
    'Lydian' => [
      '10920 - 1093F',
    ],
    'Mahajani' => [
      '11150 - 1117F',
    ],
    'Makasar' => [
      '11EE0 - 11EFF',
    ],
    'Malayalam' => [
      '0D00 - 0D7F',
    ],
    'Mandaic' => [
      '0840 - 085F',
    ],
    'Manichaean' => [
      '10AC0 - 10AFF',
    ],
    'Marchen' => [
      '11C70 - 11CBF',
    ],
    'Masaram Gondi' => [
      '11D00 - 11D5F',
    ],
    'Medefaidrin' => [
      '16E40 - 16E9F',
    ],
    'Meetei Mayek' => [
      'ABC0 - ABFF',
      'AAE0 - AAFF',
    ],
    'Mende Kikaku' => [
      '1E800 - 1E8DF',
    ],
    'Meroitic' => [
      '109A0 - 109FF',
      '10980 - 1099F',
    ],
    'Miao' => [
      '16F00 - 16F9F',
    ],
    'Modi' => [
      '11600 - 1165F',
    ],
    'Modifier Letters' => [
      'A700 - A71F',
      '02B0 - 02FF',
    ],
    'Mongolian' => [
      '1800 - 18AF',
      '11660 - 1167F',
    ],
    'Mro' => [
      '16A40 - 16A6F',
    ],
    'Myanmar' => [
      '1000 - 109F',
      'AA60 - AA7F',
      'A9E0 - A9FF',
    ],
    'Multani' => [
      '11280 - 112AF',
    ],
    'Nabataean' => [
      '10880 - 108AF',
    ],
    'Nandinagari' => [
      '119A0 - 119FF',
    ],
    'New Tai Lue' => [
      '1980 - 19DF',
    ],
    'Newa' => [
      '11400 - 1147F',
    ],
    'Nko' => [
      '07C0 - 07FF',
    ],
    'Nushu' => [
      '1B170 - 1B2FF',
    ],
    'Nyiakeng Puachue Hmong' => [
      '1E100 - 1E14F',
    ],
    'Ogham' => [
      '1680 - 169F',
    ],
    'Ol Chiki' => [
      '1C50 - 1C7F',
    ],
    'Old Hungarian' => [
      '10C80 - 10CFF',
    ],
    'Old Italic' => [
      '10300 - 1032F',
    ],
    'Old Permic' => [
      '10350 - 1037F',
    ],
    'Old Persian' => [
      '103A0 - 103D',
    ],
    'Old Sogdian' => [
      '10F00 - 10F2F',
    ],
    'Old Turkic' => [
      '10C00 - 10C4F',
    ],
    'Oriya' => [
      '0B00 - 0B7F',
    ],
    'Osage' => [
      '104B0 - 104FF',
    ],
    'Osmanya' => [
      '10480 - 104AF',
    ],
    'Pahawh Hmong' => [
      '16B00 - 16B8F',
    ],
    'Pahlavi' => [
      '10B60 - 10B7F',
      '10B80 - 10BAF',
    ],
    'Palmyrene' => [
      '10860 - 1087F',
    ],
    'Parthian' => [
      '10B40 - 10B5F',
    ],
    'Pau Cin Hau' => [
      '11AC0 - 11AFF',
    ],
    'Phags Pa' => [
      'A840 - A87F',
    ],
    'Phoenician' => [
      '10900 - 1091F',
    ],
    'Rejang' => [
      'A930 - A95F',
    ],
    'Runic' => [
      '16A0 - 16FF',
    ],
    'Samaritan' => [
      '0800 - 083F',
    ],
    'Saurashtra' => [
      'A880 - A8DF',
    ],
    'Sharada' => [
      '11180 - 111DF',
    ],
    'Shavian' => [
      '10450 - 1047F',
    ],
    'Siddham' => [
      '11580 - 115FF',
    ],
    'Sinhala' => [
      '0D80 - 0DFF',
      '111E0 - 111FF',
    ],
    'Sogdian' => [
      '10F30 - 10F6F',
    ],
    'Sora Sompeng' => [
      '110D0 - 110FF',
    ],
    'Soyombo' => [
      '11A50 - 11AAF',
    ],
    'Sundanese' => [
      '1B80 - 1BBF',
      '1CC0 - 1CCF',
    ],
    'Superscripts and Subscripts' => [
      '2070 - 209F',
    ],
    'Syloti Nagri' => [
      'A800 - A82F',
    ],
    'Syriac' => [
      '0700 - 074F',
      '0860 - 086F',
    ],
    'Tagalog' => [
      '1700 - 171F',
    ],
    'Tagbanwa' => [
      '1760 - 177F',
    ],
    'Tai Le' => [
      '1950 - 197F',
    ],
    'Tai Tham' => [
      '1A20 - 1AAF',
    ],
    'Tai Viet' => [
      'AA80 - AADF',
    ],
    'Takri' => [
      '11680 - 116CF',
    ],
    'Tamil' => [
      '0B80 - 0BFF',
      '11FC0 - 11FFF',
    ],
    'Tangut' => [
      '17000 - 187F7',
      '18800 - 18AFF',
      '18D00 - 18D08',
    ],
    'Telugu' => [
      '0C00 - 0C7F',
    ],
    'Thaana' => [
      '0780 - 07BF',
    ],
    'Thai' => [
      '0E00 - 0E7F',
    ],
    'Tibetan' => [
      '0F00 - 0FFF',
    ],
    'Tifinagh' => [
      '2D30 - 2D7F',
    ],
    'Tirhuta' => [
      '11480 - 114DF',
    ],
    'Ugaritic' => [
      '10380 - 1039F',
    ],
    'Vai' => [
      'A500 - A63F',
    ],
    'Vedic Extensions' => [
      '1CD0 - 1CFF',
    ],
    'Wancho' => [
      '1E2C0 - 1E2FF',
    ],
    'Warang Citi' => [
      '118A0 - 118FF',
    ],
    'Yezidi' => [
      '10E80 - 10EBF',
    ],
    'Yi' => [
      'A000 - A48F',
      'A490 - A4CF',
    ],
    'Yijing' => [
      '4DC0 - 4DFF',
    ],
    'Zanabazar Square' => [
      '11A00 - 11A4F',
    ],
  ];
  ksort($ucr);
  $defaults = [
    'protected_submissions_reject_message' => t('Oops! It looks like your post contains spam content. If you believe otherwise, please contact the website\'s administrator. We apologize for the inconvenience.'),
    'protected_submissions_reject_patterns' => "http://, https://, www, ftp://, mailto:, smb://, afp://, file://, gopher://, news://, ssl://, sslv2://, sslv3://, tls://, tcp://, udp://, url=\nsex, porn, fuck, free, win, captcha, spam, hello. and bye., reading this message, great website, late client",
    'protected_submissions_rejected' => 0,
    'protected_submissions_allowed_scripts' => [
      'Latin',
    ],
    'protected_submissions_language_scripts' => $ucr,
    'protected_submissions_check_quantity' => 50,
    'protected_submissions_log_rejected' => 1,
  ];
  return variable_get($variable_name, array_key_exists($variable_name, $defaults) ? $defaults[$variable_name] : '');
}

/**
 * Implements hook_form_alter().
 */
function protected_submissions_form_alter(&$form, &$form_state, $form_id) {
  global $user;

  // Exit early if current user has bypass permission.
  // Not using user_access(), because user #1 has all privileges per
  // https://api.drupal.org/api/drupal/modules!user!user.module/function/user_access/7.x
  $found_key = array_search(TRUE, array_column(user_role_permissions($user->roles), 'bypass protected_submissions'));
  if ($found_key !== FALSE) {
    return;
  }
  if (strpos($form_id, '_node_form') !== FALSE || strpos($form_id, 'comment_node_') !== FALSE || strpos($form_id, 'contact_') !== FALSE || strpos($form_id, 'webform_') !== FALSE) {
    $form['#validate'][] = '_protected_submissions_validate';
  }
}

/**
 * Validate the submitted text fields.
 */
function _protected_submissions_validate($form, &$form_state) {
  $check_text = NULL;

  // Get user defined reject message.
  $reject_message = protected_submissions_variable_get('protected_submissions_reject_message');

  // Get list of user defined trigger patterns.
  $reject_patterns = protected_submissions_variable_get('protected_submissions_reject_patterns');
  $reject_patterns = strtolower($reject_patterns);

  // Get the quantity of previously rejected submissions.
  $rejected = protected_submissions_variable_get('protected_submissions_rejected');

  // Get user's choice if the rejected messages are logged or not.
  $log_rejected = protected_submissions_variable_get('protected_submissions_log_rejected');

  // Turn multiline string into a single comma-separated string.
  $reject_patterns = str_replace(array(
    "\r",
    "\n",
  ), ",", $reject_patterns);
  $reject_patterns = str_replace(',,', ',', $reject_patterns);

  // Escape delimiter.
  $reject_patterns = str_replace('@', '\\@', $reject_patterns);

  // Turn to array.
  $reject_patterns = explode(",", $reject_patterns);

  // Trim white spaces of array values in php.
  $reject_patterns = array_map('trim', $reject_patterns);

  // Remove empty array members.
  $reject_patterns = array_filter($reject_patterns);

  // Get submitted values;.
  $values = $form_state['values'];
  if (strpos($values['form_id'], 'webform_') !== FALSE) {

    // Webforms.
    if (isset($values['submitted'])) {
      foreach ($values['submitted'] as $key => $value) {
        if ($form['submitted'][$key]['#webform_component']['form_key'] == $key) {
          if ($form['submitted'][$key]['#webform_component']['type'] == 'textfield' || $form['submitted'][$key]['#webform_component']['type'] == 'textarea') {
            $check_text .= ' ' . $value;
          }
        }
        if (!empty($form['submitted'][$key]['#webform_component']['children'])) {
          foreach ($form['submitted'][$key]['#webform_component']['children'] as $cid => $component) {
            if ($component['type'] == 'textfield' || $component['type'] == 'textarea') {
              $check_text .= ' ' . $value[$component['form_key']];
            }
          }
        }
      }
    }
  }
  else {

    // Nodes, comments, contact forms.
    foreach ($values as $key => $value) {
      if (isset($form[$key])) {
        if (isset($form[$key]['#type'])) {

          // Node, comment or contact form title (textfield) and contact message (textarea).
          if ($form[$key]['#type'] == 'textfield' || $form[$key]['#type'] == 'textarea') {
            $check_text .= ' ' . $form[$key]['#value'];
          }
        }
        if (isset($form[$key][LANGUAGE_NONE][0]['value']['#type'])) {

          // Node text area or field.
          if ($form[$key][LANGUAGE_NONE][0]['value']['#type'] == 'textarea' || $form[$key][LANGUAGE_NONE][0]['value']['#type'] == 'textfield') {

            // Find all values.
            $array_shift = array_shift($values[$key]);
            foreach ($array_shift as $var) {
              if (!empty($var['value'])) {
                $check_text .= ' ' . $var['value'];
              }
            }
          }
        }
      }
    }
  }

  /**
   * Check if random UTF characters from the text belong to allowed
   * language scripts.
   */
  $stripped = strip_tags($check_text);
  $stripped = preg_replace('/[0-9]+/', '', $stripped);
  $stripped = preg_replace('/[[:punct:]]+/', '', trim($stripped));
  $stripped = preg_replace('/\\s+/', '', $stripped);

  // Get user defined language script.
  $allowed_scripts_raw = protected_submissions_variable_get('protected_submissions_allowed_scripts');

  // Clean up the array.
  foreach ($allowed_scripts_raw as $key => $value) {
    if ($value != FALSE) {
      $allowed_scripts[] = $value;
    }
  }
  $language_scripts = protected_submissions_variable_get('protected_submissions_language_scripts');

  // Get number of characters for language script validation.
  $check_quantity = protected_submissions_variable_get('protected_submissions_check_quantity');
  $language_failed = FALSE;
  for ($i = 0; $i < $check_quantity; $i++) {

    // Get a random letter from text stripped of all special characters and numbers.
    mb_internal_encoding("UTF-8");
    $random_char = mb_substr($stripped, rand(0, mb_strlen($stripped) - 1), 1);
    if (!empty(trim($random_char))) {
      if ($i < $check_quantity) {
        if (_if_char_allowed($random_char, $allowed_scripts, $language_scripts) == FALSE) {
          form_set_error("user", $reject_message);
          $rejected = $rejected + 1;

          // Save the new value.
          variable_set('protected_submissions_rejected', $rejected);
          if ($log_rejected == TRUE) {

            // Save the watchdog message.
            $check_text = str_replace($random_char, mb_strtoupper("<strong>{$random_char}</strong>"), $check_text);
            watchdog('rejected language', "Rejected:<em>{$check_text}</em>", $variables = array(), WATCHDOG_WARNING, $link = NULL);
          }

          // Since the first pattern found break the loop.
          $language_failed = TRUE;
          break;
        }
      }
    }
  }

  // Search for reject patterns in the concatenated text.
  if ($language_failed == FALSE) {
    $check_text = strtolower($check_text);
    foreach ($reject_patterns as $pattern) {
      $clean_pattern = preg_quote($pattern, '@');
      if (preg_match("@\\b{$clean_pattern}\\b@i", $check_text)) {
        form_set_error("user", $reject_message);
        $rejected = $rejected + 1;

        // Save the new value.
        variable_set('protected_submissions_rejected', $rejected);
        if ($log_rejected == TRUE) {

          // Save the watchdog message.
          $check_text = str_replace($pattern, mb_strtoupper("<strong>{$pattern}</strong>"), $check_text);
          watchdog('rejected pattern', "Rejected:<em>{$check_text}</em>", $variables = array(), WATCHDOG_WARNING, $link = NULL);
        }

        // Since the first pattern found break the loop.
        break;
      }
    }
  }
}

// Helper function to check if character belongs to allowed language scripts.
function _if_char_allowed($random_char, $allowed_scripts, $language_scripts) {
  $char = mb_convert_encoding($random_char, 'UCS-2LE', 'UTF-8');
  $char = ord(substr($char, 1, 1)) * 256 + ord(substr($char, 0, 1));
  foreach ($allowed_scripts as $key => $lang_script) {

    // Iterate through only allowed scripts.
    if ($lang_script != FALSE) {
      foreach ($language_scripts[$lang_script] as $key => $range) {
        $range = explode(' - ', $range);

        // Turn first and last Unicode hex to decimals and compare with the character.
        if (hexdec($range[0]) < $char && $char < hexdec($range[1])) {
          $found = TRUE;
        }
      }
    }
  }
  if (isset($found) && $found == TRUE) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}

/**
 * Implements hook_requirements().
 * Provides stats for rejected submissions on the status page.
 */
function protected_submissions_requirements($phase) {
  $requirements = array();
  $rejected = protected_submissions_variable_get('protected_submissions_rejected');
  $requirements['protected_submissions'] = array(
    'title' => t('Protected submissions'),
    'value' => t('Total of @count submissions containing <a href="@patterns">spam patterns</a> have been rejected.', array(
      '@count' => $rejected,
      '@patterns' => '/admin/config/content/protected_submissions',
    )),
    'severity' => REQUIREMENT_INFO,
  );
  return $requirements;
}

Functions

Namesort descending Description
protected_submissions_config Administrative settings form.
protected_submissions_form_alter Implements hook_form_alter().
protected_submissions_help Implements hook_help().
protected_submissions_menu Implements hook_menu().
protected_submissions_permission Implements hook_permission().
protected_submissions_requirements Implements hook_requirements(). Provides stats for rejected submissions on the status page.
protected_submissions_variable_get Utility function for getting variable values.
_if_char_allowed
_protected_submissions_validate Validate the submitted text fields.