moriyoshi               Sun Dec 21 20:30:02 2003 EDT

  Modified files:              
    /php-src/ext/iconv  iconv.c 
  Log:
  - Fix multibyte handling errors in iconv_mime_encode() when quoted-printable
    encoding scheme is used.
  - Fix segfault that occurs in iconv_mime_encode() when input_charset or
    output_charset parameter is not specified in the associative array. 
  
  
  
Index: php-src/ext/iconv/iconv.c
diff -u php-src/ext/iconv/iconv.c:1.109 php-src/ext/iconv/iconv.c:1.110
--- php-src/ext/iconv/iconv.c:1.109     Sun Dec  7 19:38:00 2003
+++ php-src/ext/iconv/iconv.c   Sun Dec 21 20:30:00 2003
@@ -18,7 +18,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: iconv.c,v 1.109 2003/12/08 00:38:00 moriyoshi Exp $ */
+/* $Id: iconv.c,v 1.110 2003/12/22 01:30:00 moriyoshi Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -911,6 +911,24 @@
        size_t in_left;
        char *out_p;
        size_t out_left;
+       static int qp_table[256] = {
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x00 */
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 */
+               3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x20 */
+               1, 1, 1, 1, 1, 1, 1 ,1, 1, 1, 1, 1, 1, 3, 1, 3, /* 0x30 */
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 */
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, /* 0x50 */
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 */
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, /* 0x70 */
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x80 */
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x90 */
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xA0 */
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xB0 */
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xC0 */
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xD0 */
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xE0 */
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3  /* 0xF0 */
+       };
 
        out_charset_len = strlen(out_charset);
        lfchars_len = strlen(lfchars);
@@ -1086,16 +1104,26 @@
                        } break; /* case PHP_ICONV_ENC_SCHEME_BASE64: */
 
                        case PHP_ICONV_ENC_SCHEME_QPRINT: {
+                               size_t ini_in_left;
+                               const char *ini_in_p;
+                               const unsigned char *p;
+                               size_t nbytes_required;
+
                                smart_str_appendc(pretval, 'Q');
                                char_cnt--;
                                smart_str_appendc(pretval, '?');
                                char_cnt--;
 
-                               prev_in_left = in_left;
+                               prev_in_left = ini_in_left = in_left;
+                               ini_in_p = in_p;
+
+                               for (out_size = char_cnt; out_size > 0;) {
+                                       size_t prev_out_left;
+
+                                       nbytes_required = 0;
 
-                               while (in_left > 0) {
                                        out_p = buf;
-                                       out_left = out_size = 1;
+                                       out_left = out_size;
 
                                        if (iconv(cd, (char **)&in_p, &in_left, (char 
**) &out_p, &out_left) == (size_t)-1) {
 #if ICONV_SUPPORTS_ERRNO
@@ -1109,6 +1137,10 @@
                                                                goto out;
 
                                                        case E2BIG:
+                                                               if (prev_in_left == 
in_left) {
+                                                                       err = 
PHP_ICONV_ERR_UNKNOWN;
+                                                                       goto out;
+                                                               }
                                                                break;
        
                                                        default:
@@ -1123,36 +1155,47 @@
 #endif
                                        }
 
-                                       if (out_size > out_left) {
-                                               if ((buf[0] >= 33 && buf[0] <= 60) ||
-                                                       (buf[0] >= 62 && buf[0] <= 
126)) {
-
-                                                       if (char_cnt >= 1 + 2) {
-                                                               
smart_str_appendc(pretval, buf[0]);
-                                                               char_cnt--;
-                                                       } else {
-                                                               in_p -= (prev_in_left 
- in_left);
-                                                               in_left = prev_in_left;
+                                       prev_out_left = out_left;
+                                       if (iconv(cd, NULL, NULL, (char **) &out_p, 
&out_left) == (size_t)-1) {
+#if ICONV_SUPPORTS_ERRNO
+                                               if (errno != E2BIG) {
+                                                       err = PHP_ICONV_ERR_UNKNOWN;
+                                                       goto out;
+                                               }
+#else
+                                               if (out_left == prev_out_left) {
+                                                       err = PHP_ICONV_ERR_UNKNOWN;
+                                                       goto out;
+                                               }
+#endif
+                                       }
 
-                                                               break;
-                                                       }
-                                               } else {
-                                                       if (char_cnt >= 3 + 2) { 
-                                                               static char 
qp_digits[] = "0123456789ABCDEF";
-                                                               
smart_str_appendc(pretval, '=');
-                                                               
smart_str_appendc(pretval, qp_digits[(buf[0] >> 4) & 0x0f]);
-                                                               
smart_str_appendc(pretval, qp_digits[(buf[0] & 0x0f)]);
-                                                               char_cnt -= 3;
-                                                       } else {
-                                                               in_p -= (prev_in_left 
- in_left);
-                                                               in_left = prev_in_left;
+                                       for (p = (unsigned char *)buf; p < (unsigned 
char *)out_p; p++) {
+                                               nbytes_required += qp_table[*p];
+                                       }
 
-                                                               break;
-                                                       }
-                                               }
+                                       if (nbytes_required <= char_cnt - 2) {
+                                               break;
+                                       }
+
+                                       out_size -= ((nbytes_required - (char_cnt - 
2)) + 1) / (3 - 1);
+                                       in_left = ini_in_left;
+                                       in_p = ini_in_p;
+                               }
+
+                               for (p = (unsigned char *)buf; p < (unsigned char 
*)out_p; p++) {
+                                       if (qp_table[*p] == 1) {
+                                               smart_str_appendc(pretval, *(char *)p);
+                                               char_cnt--;
+                                       } else {
+                                               static char qp_digits[] = 
"0123456789ABCDEF";
+                                               smart_str_appendc(pretval, '=');
+                                               smart_str_appendc(pretval, 
qp_digits[(*p >> 4) & 0x0f]);
+                                               smart_str_appendc(pretval, 
qp_digits[(*p & 0x0f)]);
+                                               char_cnt -= 3;
                                        }
-                                       prev_in_left = in_left;
                                }
+                               prev_in_left = in_left;
 
                                smart_str_appendl(pretval, "?=", sizeof("?=") - 1);
                                char_cnt -= 2;
@@ -1904,19 +1947,19 @@
                }
        }
 
+       in_charset = ICONVG(internal_encoding);
+
        if (zend_hash_find(Z_ARRVAL_P(pref), "input-charset", sizeof("input-charset"), 
(void **)&ppval) == SUCCESS) {
                if (Z_TYPE_PP(ppval) == IS_STRING && Z_STRLEN_PP(ppval) > 0) {
                        in_charset = Z_STRVAL_PP(ppval);
-               } else {
-                       in_charset = ICONVG(internal_encoding);
                }
        }
 
+       out_charset = in_charset;
+
        if (zend_hash_find(Z_ARRVAL_P(pref), "output-charset", 
sizeof("output-charset"), (void **)&ppval) == SUCCESS) {
                if (Z_TYPE_PP(ppval) == IS_STRING && Z_STRLEN_PP(ppval) > 0) {
                        out_charset = Z_STRVAL_PP(ppval);
-               } else {
-                       out_charset = in_charset;
                }
        }
 

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

Reply via email to