'JPG'), $_captcha_formats); } if ($_captcha_imagetypes & IMG_GIF) { $_captcha_default_format = 1; $_captcha_formats = array_merge(array(1 => 'GIF'), $_captcha_formats); } if ($_captcha_imagetypes & IMG_PNG) { $_captcha_default_format = 0; $_captcha_formats = array_merge(array(0 => 'PNG'), $_captcha_formats); } } /** * Implementation of hook_help(). */ function captcha_help($section = "admin/help#captcha") { $output = ""; switch ($section) { case 'admin/help#captcha': $output = t('Users would be shown a graphic image with some text which they will have to enter manually to verify they are not a bot. CAPTCHA requires PHP to be compiled with GD support.'); break; case 'admin/modules#description': $output = t("Adds a Captcha to specified forms."); if (!function_exists('imagecreate')) { $output .= " ".t("GD support is not detected. This module requires PHP to be compiled with GD support."); } break; } return $output; } /** * Implementation of hook_settings(). */ function captcha_settings() { global $_captcha_default_format, $_captcha_formats; $group .= form_select(t('Image format'), 'captcha_format', variable_get('captcha_format', $_captcha_default_format), $_captcha_formats, t("Output captcha image format. These are the formats supported in your PHP so if you can't see the image, try another one.")); $output .= form_group(t('Image Options'),$group); if (function_exists('imagecreate')) { $group = form_radios(t('user registration'), 'captcha_newuser', variable_get('captcha_newuser', 0), array(0 => t('No CAPTCHA support'), 1 => t('CAPTCHA support'))); $group .= form_radios(t('comments'), 'captcha_comment', variable_get('captcha_comment', 0), array(0 => t('No CAPTCHA support'), 1 => t('CAPTCHA support'), 2 => t('CAPTCHA support only for anonymous user'))); foreach (node_list() as $type) { $group .= form_radios(t(node_invoke($type,'node_name')), "captcha_node_$type", variable_get("captcha_node_$type", 0), array(0 => t('No CAPTCHA support'), 1 => t('CAPTCHA support'), 2 => t('CAPTCHA support only for anonymous user'))); } $output .= form_group(t('Form Options'),$group); } return $output; } /** * Implementation of hook_menu(). */ function captcha_menu($may_cache) { $items = array(); $items[] = array('path' => 'captcha/image', 'title' => t('captcha image'), 'callback' => '_captcha_image', 'access' => user_access('access content'), 'type' => MENU_CALLBACK); return $items; } /** * Implementation of hook_link(). */ function captcha_link($type, $node = 0, $main) { if ($type == 'system') { menu('captcha', t('captcha image'), 'captcha_image', 0, MENU_HIDE); } } /** * Implementation of hook_nodeapi(). */ function captcha_nodeapi(&$node, $op, $arg) { global $user; $type = $node->type; // check if captcha is enabled for form type if (variable_get("captcha_node_$type",0) != 1 && !(variable_get("captcha_node_$type",0) == 2 && !$user->uid)) return; // check for GD support if (!function_exists('imagecreate')) return; switch ($op) { case 'validate': $node->captcha = trim($node->captcha); if (isset($node->captcha) && $node->captcha != variable_get('captcha_code','') || variable_get('captcha_code','') == '') { form_set_error('captcha', t('The user verification code you entered is not correct.')); } break; case 'form post': variable_set('captcha_code', _captcha_generate_code()); $group = form_item('',''.t('captcha image').''); $group .= form_textfield(t('Code'), 'captcha', NULL, 15, 15, t('Enter the characters shown in the image above.'), NULL, TRUE); $output = form_group(t('Human user verification'),$group); return $output; } } /** * User callback; adds captcha field to new user form. */ function captcha_user($type, &$edit, &$user, $category = NULL) { global $user; // check if user is logged in if ($user->uid) return; // check if captcha is enabled for form type if (variable_get('captcha_newuser',0) == 0) return; // check for GD support if (!function_exists('imagecreate')) return; switch ($type) { case 'validate': if ($edit['captcha'] == '' || variable_get('captcha_code','') == '' || $edit['captcha'] != variable_get('captcha_code','')) { form_set_error('captcha', t('The user verification code you entered is not correct.')); // variable_set('captcha_code', _captcha_generate_code()); } break; case 'register': variable_set('captcha_code', _captcha_generate_code()); $group = form_item('',''.t('captcha image').''); $group .= form_textfield(t('Code'), 'captcha', NULL, 15, 15, t('Enter the characters shown in the image above.'), NULL, TRUE); return array(array('title' => t('Human user verification'), 'data'=>$group)); } } /** * Comment callback; adds captcha field to new comment form. */ function captcha_comment($op,$edit) { global $user; // check if captcha is enabled for form type if (variable_get('captcha_comment',0) != 1 && !(variable_get('captcha_comment',0) == 2 && !$user->uid)) return; // check for GD support if (!function_exists('imagecreate')) return; switch ($op) { case 'validate': // only validate captcha if "Post comment" button is used if ($_POST['op'] == t('Post comment') && (variable_get('captcha_code','') == '' || $edit['captcha'] != variable_get('captcha_code',''))) { form_set_error('captcha', t('The user verification code you entered is not correct.')); } break; case 'form': // only show captcha form if the "Post comment" button is visible if (!variable_get('comment_preview', 1) || ($_POST['op'] == t('Preview comment')) || ($_POST['op'] == t('Post comment'))) { variable_set('captcha_code', _captcha_generate_code()); $group = form_item('',''.t('captcha image').''); $group .= form_textfield(t('Code'), 'captcha', NULL, 15, 15, t('Enter the characters shown in the image above.'), NULL, TRUE); $output = form_group(t('Human user verification'),$group); return $output; } } } /** * Prints an image containing a captcha code. */ function _captcha_image() { global $_captcha_default_format, $_captcha_formats; // Check for captcha code and exit if not existant to prevent abuse $captchaCode = variable_get('captcha_code',''); if ($captchaCode == '') return drupal_goto(); // Check for GD support if (!function_exists('imagecreate')) return drupal_goto(); // define the image dimensions $imageWidth = 280; $imageHeight = 60; $img = imagecreate($imageWidth,$imageHeight); // draw image $img = _captcha_image_arcs($img,$captchaCode); // Set headers header('Expires: Mon, 01 Jan 1997 05:00:00 GMT'); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); switch (variable_get('captcha_format',$_captcha_default_format)) { case 2: header('Content-type: image/jpg'); break; case 1: header('Content-type: image/gif'); break; default: header('Content-type: image/png'); break; } // output the image switch (variable_get('captcha_format',$_captcha_default_format)) { case 2: imagejpeg($img); break; case 1: imagegif($img); break; default: imagepng($img); break; } // destroy the image imagedestroy($img); } /** * Returns a captcha code. */ function _captcha_generate_code() { $charlist = 'QWERTYUPLKJHGFDSAZXCVBNM23456789'; $length = rand(6,8); $code = ''; srand((double) microtime() * 1000000); for ($i=0;$i<$length;$i++) { $char = substr($charlist, rand() % strlen($charlist), 1); if (preg_match("/".$char."/",$code) == 0) { $code .= $char; } else { $i--; } } return $code; } /** * Returns an array of files with TTF extensions in the specified directory. */ function _captcha_font_list($dir) { $filelist = array(); if ($handle = opendir($dir)) { while ($file = readdir($handle)) { if (preg_match("/\.ttf$/i",$file) == 1) $filelist[] = $file; } closedir($handle); } return $filelist; } /** * Draws a captcha image */ function _captcha_image_arcs($img,$code) { // define colors $backgroundColor = imagecolorallocate($img,224,224,224); $borderColor = imagecolorallocate($img,0,0,0); $textColor = imagecolorallocate($img,0,0,0); $noiseColor = imagecolorallocate($img,0,0,0); // define number of noise elements $noiseCount = rand(imagesx($img)/30,imagesx($img)/10); // draw image background imagefill($img,0,0,$backgroundColor); // draw image noise for ($i=0;$i<$noiseCount;$i++) { $segmentCount = rand(1,4); $x = rand(10,imagesx($img)-10); $y = rand(4,imagesy($img)-10); $angle = rand(0,180); for ($j=0;$j<$segmentCount;$j++) { // randomly draw an arc or a line if (rand(0,3) == 1) { imagearc($img,$x,$y,rand(10,15),rand(10,15),rand(0,224),rand(180,360),$noiseColor); $x += rand(-20,20); $y += rand(-20,20); } else { $segmentAngle = $angle + rand(-2,2); $segmentLength = rand(3,10); $xLength = round($segmentLength * cos($segmentAngle)); $yLength = round($segmentLength * sin($segmentAngle)); imageline($img,$x,$y,$x+$xLength,$y+$yLength,$noiseColor); $x += $xLength; $y += $yLength; } } } // Get truetype font list $fontDir = 'modules/captcha'; $fonts = _captcha_font_list($fontDir); if (count($fonts) > 0) { // write text using a truetype font $charSize = 20; // font size $charWidth = 0; // width of previous character $x = 20; // initial x position // iterate over characters for ($i=0;$i