? image_captcha_utf.patch
? image_captcha/fonts/VeraSe.ttf
Index: image_captcha/image_captcha.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/captcha/image_captcha/Attic/image_captcha.module,v
retrieving revision 1.1.4.6
diff -u -b -B -u -p -r1.1.4.6 image_captcha.module
--- image_captcha/image_captcha.module	3 Aug 2007 18:18:37 -0000	1.1.4.6
+++ image_captcha/image_captcha.module	6 Aug 2007 09:11:44 -0000
@@ -138,6 +138,38 @@ function image_captcha_settings_form_val
 }
 
 /**
+ * Helper function for splitting an utf8 string correctly
+ * assumes the given utf8 string is well formed
+ */
+function _image_captcha_utf8_split($str) {
+  $characters = array();
+  $len = strlen($str);
+  for ($i=0; $i < $len; ) {
+    $chr = ord($str[$i]);
+    if ($chr & 0x80) {
+      if (($chr & 0xE0) == 0xC0) { // two byte character
+        $width = 2;
+      }
+      elseif (($chr & 0xF0) == 0xE0) { // three byte character
+        $width = 3;
+      }
+      elseif (($chr & 0xF8) == 0xF0) { // four byte character
+        $width = 4;
+      }
+      else {
+      }
+    }
+    else {
+      // one byte character
+      $width = 1;
+    }
+    $characters[] = substr($str, $i, $width);
+    $i += $width;
+  }
+  return $characters;
+}
+
+/**
  * Implementation of hook_captcha
  */
 function image_captcha_captcha($op, $captcha_type='') {
@@ -153,12 +185,11 @@ function image_captcha_captcha($op, $cap
     case 'generate':
       if ($captcha_type == 'Image') {
         // generate a captcha code
-        $allowed_chars = variable_get('image_captcha_image_allowed_chars', IMAGE_CAPTCHA_ALLOWED_CHARACTERS);
-        $max = strlen($allowed_chars) - 1;
-        $len = mt_rand((int)variable_get('image_captcha_code_min', 5), (int)variable_get('image_captcha_code_max', 7));
+        $allowed_chars = _image_captcha_utf8_split(variable_get('image_captcha_image_allowed_chars', IMAGE_CAPTCHA_ALLOWED_CHARACTERS));
+        $code_length = mt_rand((int)variable_get('image_captcha_code_min', 5), (int)variable_get('image_captcha_code_max', 7));
         $code = '';
-        for ($i = 0; $i < $len; $i++) {
-          $code .= $allowed_chars[mt_rand(0, $max)];
+        for ($i = 0; $i < $code_length; $i++) {
+          $code .= $allowed_chars[array_rand($allowed_chars)];
         }
         // store the answer in $_SESSION for the image generator function (which happens in another http request)
         $seed = mt_rand();
@@ -356,7 +387,8 @@ function _image_captcha_image_generator_
 }
 
 function _image_captcha_image_generator_print_string(&$image, $width, $height, $font, $font_size, $text, $colors, $offset = 0) {
-  $len = strlen($text);
+  $characters = _image_captcha_utf8_split($text);
+  $len = count($characters);
   $num_colors = count($colors) - 1;
 
   $entire_textbox = imagettfbbox($font_size, 0, $font, $text);
@@ -365,7 +397,7 @@ function _image_captcha_image_generator_
   $x = $offset + mt_rand(0, $max_delta_x);
   for ($i = 0; $i < $len; $i++) {
 
-    $textbox = imagettfbbox($font_size, 0, $font, $text[$i]);
+    $textbox = imagettfbbox($font_size, 0, $font, $characters[$i]);
     $char_width = abs($textbox[0]) + abs($textbox[2]);
 
     if ($x > $width - $char_width) {
@@ -373,7 +405,7 @@ function _image_captcha_image_generator_
     }
 
     $y = abs($textbox[5]) + mt_rand(0, abs($textbox[5] / 2)) + 10;
-    imagettftext($image, $font_size, 0, $x, $y, $color[mt_rand(0, $num_colors)], $font , $text[$i]);
+    imagettftext($image, $font_size, 0, $x, $y, $color[mt_rand(0, $num_colors)], $font , $characters[$i]);
 
     // Add the 'double vision' character noise.
     if (variable_get('image_captcha_char_noise', 0)) {
@@ -385,7 +417,7 @@ function _image_captcha_image_generator_
         $dup_x = $width - $char_width;
       }
       $y = abs($textbox[5]) + mt_rand(0, abs($textbox[5] / 2)) + 10;
-      imagettftext($image, $font_size, 0, $dup_x, $y, $color[mt_rand(0, $num_colors)], $font , $text[$i]);
+      imagettftext($image, $font_size, 0, $dup_x, $y, $color[mt_rand(0, $num_colors)], $font , $characters[$i]);
       if ($dup_x > $x) {
         $x = $dup_x;
       }
