/[drupal]/contributions/modules/captcha/captcha.module
ViewVC logotype

Diff of /contributions/modules/captcha/captcha.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.19, Sun Jan 15 18:51:40 2006 UTC revision 1.20, Mon Jan 30 04:38:50 2006 UTC
# Line 1  Line 1 
1  <?php  <?php
2  // $Id: captcha.module,v 1.18 2006/01/12 23:34:58 arnabdotorg Exp $  // $Id: captcha.module,v 1.19 2006/01/15 18:51:40 arnabdotorg Exp $
3    
4  function captcha_help($section = "admin/help#captcha") {  function captcha_help($section = "admin/help#captcha") {
5    $output = "";    $output = "";
# Line 30  function captcha_menu($may_cache) { Line 30  function captcha_menu($may_cache) {
30    
31    $suffix = '';    $suffix = '';
32    if (arg(2)!=null) $suffix='/'.arg(2);    if (arg(2)!=null) $suffix='/'.arg(2);
33    
34    $items[] = array('path' => 'captcha/image'.$suffix, 'title' => t('captcha image'),    $items[] = array('path' => 'captcha/image'.$suffix, 'title' => t('captcha image'),
35      'callback' => '_captcha_image', 'access' => user_access('access captchas'),      'callback' => _captcha_call('_captcha_image'), 'access' => user_access('access captchas'),
36      'type' => MENU_CALLBACK);      'type' => MENU_CALLBACK);
37    
38    return $items;    return $items;
# Line 66  function captcha_settings() { Line 66  function captcha_settings() {
66    
67    }    }
68    
69    $form['captcha_user_register'] = array(    //this is where you can add more captcha points
70                                            '#type' => 'checkbox',    $captcha_points = array(
71                                            '#title' => t('Check during user registration'),                        'comment_form' => t('Comment Form'),
72                                            '#default_value' => _captcha_istrue("captcha_user_register", "true"),                        'user_login' => t('User Login Form'),
73                                            '#description' =>  t('If enabled, users will be asked to recognize an image during user registration.'),                        'user_login_block' => t('User Login Form Block'),
74                                          );                        'user_edit' => t('User Edit Form'),
75    $form['captcha_comment_anonymous'] = array(                        'user_register' => t('User Registration Form'),
76                                            '#type' => 'checkbox',                        'user_pass' => t('User Forgot Password Form'),
77                                            '#title' => t('Check during anonymous comments.'),                        'contact_mail_user' => t('User Contact Form'),
78                                            '#default_value' => _captcha_istrue("captcha_comment_anonymous", "true"),                        'contact_mail_page' => t('Sitewide Contact Form'),
79                                            '#description' =>   t('If enabled, anonymous users will be asked to recognize an image while posting .'),                        'node_form' => t('Create a node'),
80                                          );                      );
81    
82    $form['captcha_comment_registered'] = array(    $roles = user_roles();
83                                            '#type' => 'checkbox',  
84                                            '#title' => t('Check during registered user comments.'),    foreach($roles as $role) {
85                                            '#default_value' => _captcha_istrue("captcha_comment_registered", "true"),      $varsuffix = strtr($role,' ','_') .'_captcha';
86                                            '#description' =>   t('If enabled, registered users will be asked to recognize an image while posting .'),      $form[$varsuffix] = array('#type' => 'fieldset', '#title' => t('Captcha Points for the role '. $role), '#collapsible' => TRUE, '#collapsed' => TRUE);
87                                          );      foreach($captcha_points as $captcha_point=>$captcha_point_description) {
88          $varname = $captcha_point .'_'. $varsuffix;
89          $form[$varsuffix][$varname] = array(
90                                         '#type' => 'checkbox',
91                                         '#title' => $captcha_point_description,
92                                         '#default_value' => variable_get($varname, NULL)
93                                        );
94        }
95      }
96    
97      $form['captcha_type'] = array(
98                                '#type' => 'select',
99                                '#title' => t('Type of captcha to use'),
100                                '#default_value' => variable_get('captcha_type','image'),
101                                '#options' => _captcha_types(),
102                                '#description' => t('Select what kind of challenge you want to pose to the user')
103                              );
104    
105    $form['captcha_fonts_path'] = array(    $form['captcha_fonts_path'] = array(
106                                    '#type' => 'textfield',                                    '#type' => 'textfield',
# Line 96  function captcha_settings() { Line 111  function captcha_settings() {
111                                    '#description' => t('Location of the directory where the Truetype (.ttf) fonts are stored. If you do not provide any fonts, the module will use the default font for text.'),                                    '#description' => t('Location of the directory where the Truetype (.ttf) fonts are stored. If you do not provide any fonts, the module will use the default font for text.'),
112                                  );                                  );
113    
   
114    if (isset($fonts_path)) {    if (isset($fonts_path)) {
115      $imagefontinfo .= t('Number of fonts found: ').count(_captcha_font_list());      $imagefontinfo .= t('Number of fonts found: ').count(_captcha_font_list());
116    }    }
# Line 116  function captcha_settings() { Line 130  function captcha_settings() {
130    return $form;    return $form;
131  }  }
132    
 /**  
 * Implementation of hook_menu(), for adding form elements & validation.  
 */  
 function captcha_user($type, &$edit, &$newuser, $category = NULL) {  
   
   global $user;  
   
   // What type of registration action are we taking?  
   // make sure this is a registration, and captcha is enabled for registration  
   if (_captcha_istrue("captcha_user_register") && !$newuser->uid && !$user->uid) {  
     switch ($type) {  
       case 'register':  
         // Add two items to the resigtration form.  
         return array( t('Verify Registration') => _captcha_form());  
         break;  
   
       case 'validate':  
         // The user has filled out the form and checked the "accept" box.  
         if (_captcha_validate($edit['captcha_word']))   {  
           $_SESSION['captcha']='';  
           // on success return the values you want to store  
           return array("captcha_correct" => 1);  
         }  
         else {  
           // on error return an error message  
           form_set_error('captcha_word', t("Please re-recognize the word shown in the image."));  
           return $edit;  
         }  
         break;  
     }  
   }  
 }  
   
 /**  
 * Comment callback; adds captcha field to new comment form.  
 */  
 function captcha_comment($edit, $op) {  
   
   switch ($op) {  
     case 'validate': //this is redundant, not followed  
       // only validate captcha once for a comment.  
       // this implementation basically sets a flag when you've successfully validated a captcha;  
       // any successive comment inserted uses and invalidates the set flag.  
       if (!$_SESSION['captcha_comment_correct']) {  
         if (_captcha_validate($edit['captcha_word'])) {  
           $_SESSION['captcha_comment_correct'] =  true;  
           //reset captcha variable to prevent session highjacking vulnerability #26741  
           $_SESSION['captcha']='';  
         }  
         else {  
           form_set_error('captcha_word', t('The captcha verification code you entered is not correct.'));  
         }  
       }  
       break;  
     case 'insert':  
       //invalidate captcha after one comment insert  
       $_SESSION['captcha_comment_correct'] = false;  
       $_SESSION['captcha']='';  
       break;  
   }  
 }  
   
 function _captcha_form() {  
   
   $form['captcha_image'] = array (  
     '#type' => 'item',  
     '#title' =>  'captcha image',  
     '#value' => '<img src="' . url('captcha/image/'.time()) . '"  alt="Captcha Image: you will need to recognize the text in it."/>',  
   );  
   
   $form['captcha_word'] = array (  
     '#type' => 'textfield',  
     '#title' => t('Word'),  
     '#defaultvalue' => '',  
     '#description' => t('Please type in the letters/numbers that are shown in the image above.'),  
   );  
   
   return $form;  
 }  
133    
134    
135  function captcha_form_alter($formid, &$form) {  function captcha_form_alter($formid, &$form) {
136    
137    global $user;    global $user;
138      $captcha_type = variable_get("captcha_type", NULL);
139    
140    switch($formid) {    if (!$captcha_type) return;
     case 'comment_form':  
141    
142        // check if captcha is enabled for form type    $flag = true;
143        if ($user->uid == 0 && !_captcha_istrue("captcha_comment_anonymous")) return;    $trigger = NULL;
144        if ($user->uid != 0 && !_captcha_istrue("captcha_comment_registered")) return;  
145      foreach($user->roles as $role) {
146        // include logic to remove captcha if the current entry is a valid captcha      $candidate_trigger = $formid .'_'. strtr($role,' ','_') .'_captcha';
147        if (!$_SESSION['captcha_comment_correct'] && !($_POST['edit']['captcha_word'] != '' && _captcha_validate($_POST['edit']['captcha_word']))) {      if (variable_get($candidate_trigger, NULL)) {
148          $form['captcha'] = _captcha_form();        $trigger = $candidate_trigger;
149        }      }
150        else {      else {
151          $_SESSION['captcha']='';        $flag = false;
         unset($form['captcha']);  
       }  
152        break;        break;
153        }
154    }    }
155  }  
156      if ($flag && isset($trigger)) {
157  function _captcha_validate($string) {      if ($captcha_type = _captcha_load()) {
158          $form['#submit'] = array('captcha_submit' => array()) + $form['#submit'];
159    $captcha_word = drupal_strtolower($string);        if (!_captcha_validate($_POST['edit']['captcha_response'])) {
160    if ($captcha_word != $_SESSION['captcha']) {          call_user_func_array('_captcha_'. $captcha_type .'_challenge', array(&$form, &$_SESSION['captcha']));
161      return false;        }
162        }
163    }    }
   
   return true;  
164  }  }
165    
166    
167  /**  /**
168  * Returns a random string for use in a captcha  * On submit, captcha is reset
169  */  */
170  function _captcha_code() {  function captcha_submit() {
171      if($_SESSION['captcha_correct']) {
172      $consts='bcdgjxvmnprst';      unset($_SESSION['captcha_correct']);
173      $vowels='aeiou';      unset($_SESSION['captcha']);
174      }
175      for ($x=0; $x < 6; $x++) {  }
       mt_srand ((double) microtime() * 1000000);  
       $const[$x] = drupal_substr($consts,mt_rand(0,drupal_strlen($consts)-1),1);  
       $vow[$x] = drupal_substr($vowels,mt_rand(0,drupal_strlen($vowels)-1),1);  
     }  
176    
     $string = $const[0] . $vow[0] .$const[2] . $const[1] . $vow[1] . $const[3] . $vow[3] . $const[4];  
     $string = drupal_substr($string,0,rand(5,8));  
177    
178      //everytime we create a new code, we write it to session  function _captcha_validate($captcha_response) {
     $_SESSION['captcha'] = drupal_strtolower($string);  
179    
180      return $string;    if ($_SESSION['captcha_correct']) return TRUE;
181      if (is_array($captcha_response)) $captcha_response = $captcha_response['#value'];
182      if (trim($captcha_response) == '') return FALSE;
183    
184      global $user;
185      $trigger = NULL;
186      if ($captcha_type = _captcha_load()) {
187        call_user_func_array('_captcha_'. $captcha_type .'_validate', array(&$captcha_response, &$_SESSION['captcha_correct']));
188      }
189    
190      return $_SESSION['captcha_correct'];
191  }  }
192    
 /**  
 * Returns a random string for use in a captcha  
 */  
 function _captcha_istrue($variable, $default="true") {  
     return (variable_get($variable, "")== true);  
 }  
193    
194  /**  /**
195  * Returns an array of files with TTF extensions in the specified directory.  * Returns an array of files with TTF extensions in the specified directory.
# Line 279  function _captcha_font_list() { Line 209  function _captcha_font_list() {
209    return $filelist;    return $filelist;
210  }  }
211    
212    function _captcha_call($func) {
213      _captcha_load();
214      //if (function_exists($func)) call_user_func_array($func, array());
215    }
216    
217  /**  /**
218  * Prints an image containing a captcha code.  * Loads the current captcha system into memory
219  */  */
220  function _captcha_image() {  function _captcha_load() {
221    
222      // there are a few hard coded functions I'd like to eliminate here,    $captcha_type = variable_get("captcha_type", NULL);
223      // but for the time being we'll let them be.    $path = drupal_get_path('module', 'captcha');
224      include_once($path.'/captcha_'.$captcha_type.'.inc');
     //if we don't have GD2 functions, we can't generate the image  
     if (!function_exists('imagecreatetruecolor')) return;  
   
     // 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');  
   
     header('Content-type: image/png');  
   
     $string = _captcha_code();  
   
     // set up image, the first number is the width and the second is the height  
     $im = imagecreatetruecolor(180, 80);  
   
     // creates two variables to store color  
     $background = imagecolorallocate($im, rand(180, 250), rand(180, 250), rand(180, 250));  
     $foreground = imagecolorallocate($im, rand(0, 80), rand(0, 80), rand(0, 80));  
   
     // fill image with bgcolor  
     imagefill($im, 0, 0, $background);  
   
     // Get truetype font list  
     $fonts = _captcha_font_list();  
225    
226      // writes string    $function_challenge = '_captcha_'. $captcha_type .'_challenge';
227      if (function_exists(imagettftext) && count($fonts) > 0) {    $function_validate  = '_captcha_'. $captcha_type .'_validate';
228    
229        // write text using a truetype font    if(function_exists($function_challenge) && function_exists($function_validate)) {
230        $charSize = 24;        // font size      return $captcha_type;
231        $charWidth = 0;        // width of previous character    }
232        $x = 10;               // initial x position    else return false;
       $y = 30;  
   
       // iterate over characters  
       for ($i=0;$i<drupal_strlen($string);$i++) {  
         // define angle and position of character based on previous character dimension  
         $x += ($charWidth * rand(1.0, 1.6));  
         $y += rand(-5,5);  
         $charAngle = rand(-5,5);  
         $charSize += rand(-2,2);  
         $char = drupal_substr($string,$i,1);  
   
         // select random font  
         $font = $fonts[rand(0,count($fonts)-1)];  
   
         // draw character  
         imagettftext($im,$charSize,$charAngle,$x,$y,$foreground,$font,$char);  
   
         // capture character dimensions to increment x position  
         $bbox = imagettfbbox($charSize,$charAngle,$font,$char);  
         $charWidth = max($bbox[0],$bbox[2],$bbox[4],$bbox[6]) - min($bbox[0],$bbox[2],$bbox[4],$bbox[6]);  
       }  
     }  
   
     else {  
       // write text using a built-in font  
       $x = 10;  
       $y = 0;  
   
       for ($i=0;$i<drupal_strlen($string);$i++) {  
         imagestring($im,5,$x,$y,drupal_substr($string,$i,1),$foreground);  
         $x += rand(10,15);  
         $y += rand(-4,4);  
       }  
   
     }  
233    
234      // strikethrough  }
     imageline($im, rand(0, 120), rand(0, 120), rand(0, 120), rand(0, 120), $foreground);  
235    
236      // rotate only if function is defined (many PHP installations have this function missing)  /**
237      if (function_exists('imagerotate')) {  * Generates list of available captcha methods
238        $im2 = imagerotate($im,rand(-20,45),$background);  */
239        imagedestroy($im);  function _captcha_types() {
240        $im = $im2;    static $types;
     }  
241    
242      // add cloud only if function is defined (many PHP installations have this function missing)    if (!isset($types)) {
243      if (function_exists('imagecolorallocatealpha')) {      $types = array();
244        $middleground = imagecolorallocatealpha($im, rand(160, 200), rand(160, 200), rand(160, 200), 80);      $path = drupal_get_path('module', 'captcha');
245        $files = file_scan_directory($path, '^captcha_.*\.inc$');
246        // random shapes      foreach ($files as $filename => $file) {
247        for ($x=0; $x<50;$x++) {        include_once($filename);
248          imageline($im, rand(0, 120), rand(0, 120), rand(0, 120), rand(0, 120), $middleground);        $function_challenge = '_'. $file->name .'_challenge';
249          imageellipse($im, rand(0, 120), rand(0, 120), rand(0, 120), rand(0, 120), $middleground);        $function_validate  = '_'. $file->name .'_validate';
250          if(function_exists($function_challenge) && function_exists($function_validate)) {
251            $types[] = substr($file->name, 8);
252        }        }
253      }      }
254      }
255      //output to browser    //post process types
256      imagepng($im);    foreach($types as $type) {
257      imagedestroy($im);      $r_types[$type] = $type;
258      }
259      return $r_types;
260  }  }
261    
262  ?>  ?>

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.20

  ViewVC Help
Powered by ViewVC 1.1.2