moriyoshi               Fri Jan  3 00:28:25 2003 EDT

  Modified files:              
    /php4/ext/iconv     iconv.c 
  Log:
  More shift-sequence awareness for iconv_substr()
  
  
Index: php4/ext/iconv/iconv.c
diff -u php4/ext/iconv/iconv.c:1.70 php4/ext/iconv/iconv.c:1.71
--- php4/ext/iconv/iconv.c:1.70 Fri Jan  3 00:26:44 2003
+++ php4/ext/iconv/iconv.c      Fri Jan  3 00:28:25 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: iconv.c,v 1.70 2003/01/03 05:26:44 moriyoshi Exp $ */
+/* $Id: iconv.c,v 1.71 2003/01/03 05:28:25 moriyoshi Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -311,41 +311,70 @@
        size_t prev_in_left = in_left;
 #endif
 
-       while (in_left > 0) {
-               out_left = buf_growth - out_left;
-               {
-                       size_t newlen;
-                       smart_str_alloc((d), out_left, 0);
-               }
+       if (in_p != NULL) {
+               while (in_left > 0) {
+                       out_left = buf_growth - out_left;
+                       {
+                               size_t newlen;
+                               smart_str_alloc((d), out_left, 0);
+                       }
 
-               out_p = (d)->c + (d)->len;
+                       out_p = (d)->c + (d)->len;
 
-               if (icv(cd, &in_p, &in_left, (char **) &out_p, &out_left) == 
(size_t)-1) {
+                       if (icv(cd, &in_p, &in_left, (char **) &out_p, &out_left) == 
+(size_t)-1) {
 #if ICONV_SUPPORTS_ERRNO
-                       switch (errno) { 
-                               case EINVAL:
-                                       return PHP_ICONV_ERR_ILLEGAL_CHAR;
+                               switch (errno) { 
+                                       case EINVAL:
+                                               return PHP_ICONV_ERR_ILLEGAL_CHAR;
 
-                               case EILSEQ:
-                                       return PHP_ICONV_ERR_ILLEGAL_SEQ;
+                                       case EILSEQ:
+                                               return PHP_ICONV_ERR_ILLEGAL_SEQ;
 
-                               case E2BIG:
-                                       break;
+                                       case E2BIG:
+                                               break;
 
-                               default:
-                                       return PHP_ICONV_ERR_UNKNOWN;
-                       }
+                                       default:
+                                               return PHP_ICONV_ERR_UNKNOWN;
+                               }
 #else
-                       if (prev_in_left == in_left) {
-                               return PHP_ICONV_ERR_UNKNOWN;           
+                               if (prev_in_left == in_left) {
+                                       return PHP_ICONV_ERR_UNKNOWN;           
+                               }
+#endif
                        }
+#if !ICONV_SUPPORTS_ERRNO
+                       prev_in_left = in_left;
 #endif
+                       (d)->len += (buf_growth - out_left);
+                       buf_growth <<= 1;
                }
-#if !ICONV_SUPPORTS_ERRNO
-               prev_in_left = in_left;
+       } else {
+               for (;;) {
+                       out_left = buf_growth - out_left;
+                       {
+                               size_t newlen;
+                               smart_str_alloc((d), out_left, 0);
+                       }
+
+                       out_p = (d)->c + (d)->len;
+
+                       if (icv(cd, NULL, NULL, (char **) &out_p, &out_left) == 
+(size_t)0) {
+                               (d)->len += (buf_growth - out_left);
+                               break;
+                       } else {
+#if ICONV_SUPPORTS_ERRNO
+                               if (errno != E2BIG) {
+                                       return PHP_ICONV_ERR_UNKNOWN;
+                               }
+#else
+                               if (out_left != 0) {
+                                       return PHP_ICONV_ERR_UNKNOWN;
+                               }       
 #endif
-               (d)->len += (buf_growth - out_left);
-               buf_growth <<= 1;
+                       }
+                       (d)->len += (buf_growth - out_left);
+                       buf_growth <<= 1;
+               }
        }
        return PHP_ICONV_ERR_SUCCESS;
 }
@@ -622,7 +651,7 @@
 
        php_iconv_err_t err = PHP_ICONV_ERR_SUCCESS;
 
-       iconv_t cd;
+       iconv_t cd1, cd2;
 
        const char *in_p;
        size_t in_left;
@@ -632,8 +661,6 @@
 
        unsigned int cnt;
 
-       const char *substr_ofs;
-
        /* normalize the offset and the length */
        if (offset < 0 || len < 0) {
                unsigned int total_len;
@@ -653,9 +680,9 @@
                }
        }
 
-       cd = icv_open(GENERIC_SUPERSET_NAME, enc);
+       cd1 = icv_open(GENERIC_SUPERSET_NAME, enc);
 
-       if (cd == (iconv_t)(-1)) {
+       if (cd1 == (iconv_t)(-1)) {
 #if ICONV_SUPPORTS_ERRNO
                if (errno == EINVAL) {
                        return PHP_ICONV_ERR_WRONG_CHARSET;
@@ -667,7 +694,7 @@
 #endif
        }
 
-       substr_ofs = NULL;
+       cd2 = NULL;
 
        for (in_p = str, in_left = nbytes, cnt = 0; in_left > 0 && len > 0; ++cnt) {
                size_t prev_in_left;
@@ -676,18 +703,35 @@
 
                prev_in_left = in_left;
 
-               if (cnt >= offset) {
-                       if (substr_ofs == NULL) {
-                               substr_ofs = in_p;
+               if (icv(cd1, &in_p, &in_left, (char **) &out_p, &out_left) == 
+(size_t)-1) {
+                       if (prev_in_left == in_left) {
+                               break;
                        }
-                       --len;
                }
 
-               if (icv(cd, &in_p, &in_left, (char **) &out_p, &out_left) == 
(size_t)-1) {
-                       if (prev_in_left == in_left) {
-                               break;
+               if (cnt >= offset) {
+                       if (cd2 == NULL) {
+                               cd2 = icv_open(enc, GENERIC_SUPERSET_NAME);
+
+                               if (cd2 == (iconv_t)(-1)) {
+                                       cd2 = NULL;
+#if ICONV_SUPPORTS_ERRNO
+                                       if (errno == EINVAL) {
+                                               err = PHP_ICONV_ERR_WRONG_CHARSET;
+                                       } else {
+                                               err = PHP_ICONV_ERR_CONVERTER;
+                                       }
+#else
+                                       err = PHP_ICONV_ERR_UNKNOWN;
+#endif
+                                       break;
+                               }
                        }
+
+                       _php_iconv_appendl(pretval, buf, sizeof(buf), cd2);
+                       --len;
                }
+
        }
 
 #if ICONV_SUPPORTS_ERRNO
@@ -709,14 +753,19 @@
        }
 #endif
        if (err == PHP_ICONV_ERR_SUCCESS) {
-               if (substr_ofs != NULL) {
-                       smart_str_appendl(pretval, substr_ofs, (size_t)(in_p - 
substr_ofs));
+               if (cd2 != NULL) {
+                       _php_iconv_appendl(pretval, NULL, 0, cd2);
                }
                smart_str_0(pretval);
        }
 
-       icv_close(cd);
+       if (cd1 != NULL) {
+               icv_close(cd1);
+       }
 
+       if (cd2 != NULL) {
+               icv_close(cd2);
+       }       
        return err;
 }
 



-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to