From b676dff3351a104b8ffdd0e31e105c9b73850047 Mon Sep 17 00:00:00 2001
Message-Id: <b676dff3351a104b8ffdd0e31e105c9b73850047.1358710793.git.dmitriy.trt@gmail.com>
From: "Dmitriy.trt" <dmitriy.trt@gmail.com>
Date: Mon, 21 Jan 2013 02:39:48 +0700
Subject: [PATCH] Issue #1893960: Actually convert offset from characters to
 bytes and vice versa

---
 tests/textimage_preg_match.test |   53 +++++++++++++++++++++++++++++++++++++++
 textimage.info                  |    2 ++
 textimage.utils.inc             |    4 +--
 3 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/tests/textimage_preg_match.test b/tests/textimage_preg_match.test
new file mode 100644
index 0000000..4a63c0d
--- /dev/null
+++ b/tests/textimage_preg_match.test
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * Checks that drupal_preg_match() function works as expected.
+ */
+class TextimagePregMatchTestCase extends DrupalUnitTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'UTF-8 character-based variant of preg_match()',
+      'description' => 'Unit tests for the UTF-8 character-based wrapper of the preg_match() function.',
+      'group' => 'Textimage',
+    );
+  }
+
+  /**
+   * Sets up unit test environment.
+   *
+   * Includes the file with drupal_preg_match() function.
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    module_load_include('utils.inc', 'textimage');
+  }
+
+  /**
+   * Performs the tests for the offset argument.
+   */
+  public function testOffsetArgument() {
+    // Character 'п' is 2 bytes length and preg_match() would start from the
+    // second 'п' character and not from the first 'z'.
+    $result = drupal_preg_match('/п/u', 'ппzz', $matches, NULL, 2);
+    $this->assertFalse($result, t('String was skipped using character-based offset.'));
+
+    // Again, character 'п' is 2 bytes length and we skip 1 character, so
+    // preg_match() would fail, because the string with byte offset 1 is not a
+    // valid UTF-8 string.
+    $result = drupal_preg_match('/.*$/u', 'пzz', $matches, NULL, 1);
+    $this->assertTrue($result && $matches[0] === 'zz', t('String was matched using character-based offset.'));
+  }
+
+  /**
+   * Performs the tests for the captured offset.
+   */
+  public function testCapturedOffset() {
+    // Character 'п' is 2 bytes length and non-unicode preg_match would return
+    // 2 here.
+    $result = drupal_preg_match('/z/u', 'пz', $matches, PREG_OFFSET_CAPTURE);
+    $this->assertTrue($result && $matches[0][1] === 1, t('Returned offset is character-based.'));
+  }
+
+}
diff --git a/textimage.info b/textimage.info
index e1cded1..d94c84b 100755
--- a/textimage.info
+++ b/textimage.info
@@ -3,3 +3,5 @@ description = Provides text to image manipulations.
 core = 7.x
 
 configure = admin/config/media/textimage
+
+files[] = tests/textimage_preg_match.test
diff --git a/textimage.utils.inc b/textimage.utils.inc
index 90b93d0..ef6b909 100644
--- a/textimage.utils.inc
+++ b/textimage.utils.inc
@@ -224,7 +224,7 @@ if (!function_exists('drupal_preg_match')) {
    */
   function drupal_preg_match($pattern, $subject, &$matches, $flags = NULL, $offset = 0) {
     // Convert the offset value from characters to bytes.
-    $offset = drupal_strlen(drupal_substr($subject, 0, $offset));
+    $offset = strlen(drupal_substr($subject, 0, $offset));
 
     $return_value = preg_match($pattern, $subject, $matches, $flags, $offset);
 
@@ -232,7 +232,7 @@ if (!function_exists('drupal_preg_match')) {
       foreach ($matches as &$match) {
         // Convert the offset returned by preg_match from bytes back to
         // characters.
-        $match[1] = drupal_strlen(drupal_substr($subject, 0, $match[1]));
+        $match[1] = drupal_strlen(substr($subject, 0, $match[1]));
       }
     }
     return $return_value;
-- 
1.7.10.4

