]> granicus.if.org Git - php/commitdiff
Add iconv_mime_decode_headers() to parse multiple MIME headers.
authorMoriyoshi Koizumi <moriyoshi@php.net>
Mon, 1 Dec 2003 22:46:45 +0000 (22:46 +0000)
committerMoriyoshi Koizumi <moriyoshi@php.net>
Mon, 1 Dec 2003 22:46:45 +0000 (22:46 +0000)
A few trivial fixes.

NEWS
ext/iconv/iconv.c

diff --git a/NEWS b/NEWS
index fe899cb6855b2b271ea59c64e22a2cffd0cc3e67..5c69a5c5648097388ecedfbfb7109357d21b9951 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,7 @@ PHP                                                                        NEWS
   . php_check_syntax(). check php script for parse errors. (Ilia)
   . image_type_to_extension(). return extension based on image type. (Ilia)
   . stream_socket_sendto() and stream_socket_recvfrom(). (Wez)
+  . iconv_mime_decode_headers(). (Moriyoshi)
 - Route stat() and family via streams API. (Sara)
 - Fixed __autoload() to preserve case of the passed class name. (Andi)
 - Fixed bug #26072 (--disable-libxml does not work). (Jani)
index ee7268e03c11aee82d16939e5a2be598c225424d..2efca367c811d0c1696f000a61e995766ee7984c 100644 (file)
@@ -75,6 +75,7 @@ function_entry iconv_functions[] = {
        PHP_FE(iconv_strrpos,                                                   NULL)
        PHP_FE(iconv_mime_encode,                                               NULL)
        PHP_FE(iconv_mime_decode,                                               NULL)
+       PHP_FE(iconv_mime_decode_headers,                               NULL)
        {NULL, NULL, NULL}
 };
 /* }}} */
@@ -101,6 +102,10 @@ ZEND_DECLARE_MODULE_GLOBALS(iconv)
 ZEND_GET_MODULE(iconv)
 #endif
 
+#ifdef HAVE_LIBICONV
+#define iconv libiconv
+#endif
+
 /* {{{ typedef enum php_iconv_err_t */
 typedef enum _php_iconv_err_t {
        PHP_ICONV_ERR_SUCCESS           = SUCCESS,
@@ -124,10 +129,6 @@ typedef enum _php_iconv_enc_scheme_t {
 #define PHP_ICONV_MIME_DECODE_STRICT            (1<<0)
 #define PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR (1<<1)
 
-#ifdef HAVE_LIBICONV
-#define iconv libiconv
-#endif
-
 /* {{{ prototypes */ 
 static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l, iconv_t cd);
 static php_iconv_err_t _php_iconv_appendc(smart_str *d, const char c, iconv_t cd);
@@ -144,7 +145,7 @@ static php_iconv_err_t _php_iconv_strpos(unsigned int *pretval, const char *hays
 
 static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fname, size_t fname_nbytes, const char *fval, size_t fval_nbytes, unsigned int max_line_len, const char *lfchars, php_iconv_enc_scheme_t enc_scheme, const char *out_charset, const char *enc);
 
-static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *str, size_t str_nbytes, const char *enc, int mode);
+static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *str, size_t str_nbytes, const char *enc, const char **next_pos, int mode);
 /* }}} */
 
 /* {{{ static globals */
@@ -1173,7 +1174,7 @@ out:
 /* }}} */
 
 /* {{{ _php_iconv_mime_decode() */
-static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *str, size_t str_nbytes, const char *enc, int mode)
+static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *str, size_t str_nbytes, const char *enc, const char **next_pos, int mode)
 {
        php_iconv_err_t err = PHP_ICONV_ERR_SUCCESS;
 
@@ -1191,6 +1192,10 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
 
        php_iconv_enc_scheme_t enc_scheme;
 
+       if (next_pos != NULL) {
+               *next_pos = NULL;
+       }
+
        cd_pl = iconv_open(enc, "ASCII");
 
        if (cd_pl == (iconv_t)(-1)) {
@@ -1416,10 +1421,11 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
 
                        case 8:
                                if (*p1 != ' ' && *p1 != '\t') {
-                                       err = PHP_ICONV_ERR_MALFORMED;
-                                       goto out;
+                                       --p1;
+                                       str_left = 1; /* quit_loop */
+                                       break;
                                }
-                               if (encoded_word = NULL) {
+                               if (encoded_word == NULL) {
                                        _php_iconv_appendc(pretval, ' ', cd_pl);
                                }
                                spaces = NULL;
@@ -1540,6 +1546,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
                                                                break;
 
                                                        case ' ': case '\t':
+                                                               spaces = p1;
                                                                scan_stat = 11;
                                                                break;
 
@@ -1569,7 +1576,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
                                                break;
 
                                        case '=':
-                                               if (spaces != NULL) {
+                                               if (spaces != NULL && encoded_word == NULL) {
                                                        _php_iconv_appendl(pretval, spaces, (size_t)(p1 - spaces), cd_pl);
                                                        spaces = NULL;
                                                }
@@ -1617,16 +1624,23 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
                }
        }
 
-       if (scan_stat != 0 && scan_stat != 11 && scan_stat != 12) {
-               if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
-                       if (scan_stat == 1) {
-                               _php_iconv_appendc(pretval, '=', cd_pl);
+       switch (scan_stat) {
+               case 0: case 8: case 11: case 12:
+                       break;
+               default:
+                       if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
+                               if (scan_stat == 1) {
+                                       _php_iconv_appendc(pretval, '=', cd_pl);
+                               }
+                               err = 0;
+                       } else {
+                               err = PHP_ICONV_ERR_MALFORMED;
+                               goto out;
                        }
-                       err = 0;
-               } else {
-                       err = PHP_ICONV_ERR_MALFORMED;
-                       goto out;
-               }
+       }
+
+       if (next_pos != NULL) {
+               *next_pos = p1;
        }
 
        smart_str_0(pretval);
@@ -1950,7 +1964,7 @@ PHP_FUNCTION(iconv_mime_decode)
        int encoded_str_len;
        char *charset;
        int charset_len;
-       long mode;
+       long mode = 0;
        
        smart_str retval = {0};
 
@@ -1964,7 +1978,7 @@ PHP_FUNCTION(iconv_mime_decode)
                RETURN_FALSE;
        }
 
-       err = _php_iconv_mime_decode(&retval, encoded_str, encoded_str_len, charset, mode);
+       err = _php_iconv_mime_decode(&retval, encoded_str, encoded_str_len, charset, NULL, mode);
        _php_iconv_show_error(err, charset, "???" TSRMLS_CC);
 
        if (err == PHP_ICONV_ERR_SUCCESS) {
@@ -1980,6 +1994,79 @@ PHP_FUNCTION(iconv_mime_decode)
 }
 /* }}} */
 
+/* {{{ proto array iconv_mime_decode_headers(string headers [, int mode, string charset])
+   Decodes multiple mime header fields */
+PHP_FUNCTION(iconv_mime_decode_headers)
+{
+       const char *encoded_str;
+       int encoded_str_len;
+       char *charset;
+       int charset_len;
+       long mode = 0;
+       
+       php_iconv_err_t err;
+
+       charset = ICONVG(internal_encoding);
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls",
+               &encoded_str, &encoded_str_len, &mode, &charset, &charset_len) == FAILURE) {
+
+               RETURN_FALSE;
+       }
+
+       array_init(return_value);
+
+       while (encoded_str_len > 0) {
+               smart_str decoded_header = {0};
+               char *header_name;
+               size_t header_name_len;
+               char *header_value = NULL;
+               size_t header_value_len;
+               char *p, *limit;
+               const char *next_pos;
+
+               if (PHP_ICONV_ERR_SUCCESS != (err = _php_iconv_mime_decode(&decoded_header, encoded_str, encoded_str_len, charset, &next_pos, mode))) {
+                       smart_str_free(&decoded_header);
+                       break;
+               }
+
+               limit = decoded_header.c + decoded_header.len;
+               for (p = decoded_header.c; p < limit; p++) {
+                       if (*p == ':') {
+                               *p = '\0';
+                               header_name = decoded_header.c;
+                               header_name_len = (p - decoded_header.c) + 1;
+
+                               while (++p < limit) {
+                                       if (*p != ' ' && *p != '\t') {
+                                               break;
+                                       }
+                               }
+
+                               header_value = p;
+                               header_value_len = limit - p;
+
+                               break;
+                       }
+               }
+
+               if (header_name != NULL) {
+                       add_assoc_stringl_ex(return_value, header_name, header_name_len, header_value, header_value_len, 1);
+               }
+               encoded_str_len -= next_pos - encoded_str;
+               encoded_str = next_pos; 
+
+               smart_str_free(&decoded_header);
+       }
+
+       if (err != PHP_ICONV_ERR_SUCCESS) {
+               _php_iconv_show_error(err, charset, "???" TSRMLS_CC);
+               zval_dtor(return_value);
+               RETVAL_FALSE;
+       }
+}
+/* }}} */
+
 /* {{{ proto string iconv(string in_charset, string out_charset, string str)
    Returns str converted to the out_charset character set */
 PHP_NAMED_FUNCTION(php_if_iconv)