@@ -1023,7 +1023,8 @@ ZEND_TSRMLS_CACHE_UPDATE();
1023
1023
mbstring_globals -> illegalchars = 0 ;
1024
1024
mbstring_globals -> encoding_translation = 0 ;
1025
1025
mbstring_globals -> strict_detection = 0 ;
1026
- mbstring_globals -> outconv = NULL ;
1026
+ mbstring_globals -> outconv_enabled = false;
1027
+ mbstring_globals -> outconv_state = 0 ;
1027
1028
mbstring_globals -> http_output_conv_mimetypes = NULL ;
1028
1029
#ifdef HAVE_MBREGEX
1029
1030
mbstring_globals -> mb_regex_globals = php_mb_regex_globals_alloc ();
@@ -1144,11 +1145,6 @@ PHP_RSHUTDOWN_FUNCTION(mbstring)
1144
1145
MBSTRG (current_detect_order_list ) = NULL ;
1145
1146
MBSTRG (current_detect_order_list_size ) = 0 ;
1146
1147
}
1147
- if (MBSTRG (outconv ) != NULL ) {
1148
- MBSTRG (illegalchars ) += mbfl_buffer_illegalchars (MBSTRG (outconv ));
1149
- mbfl_buffer_converter_delete (MBSTRG (outconv ));
1150
- MBSTRG (outconv ) = NULL ;
1151
- }
1152
1148
1153
1149
/* clear http input identification. */
1154
1150
MBSTRG (http_input_identify ) = NULL ;
@@ -1166,6 +1162,9 @@ PHP_RSHUTDOWN_FUNCTION(mbstring)
1166
1162
MBSTRG (http_output_set ) = 0 ;
1167
1163
MBSTRG (http_input_set ) = 0 ;
1168
1164
1165
+ MBSTRG (outconv_enabled ) = false;
1166
+ MBSTRG (outconv_state ) = 0 ;
1167
+
1169
1168
#ifdef HAVE_MBREGEX
1170
1169
PHP_RSHUTDOWN (mb_regex ) (INIT_FUNC_ARGS_PASSTHRU );
1171
1170
#endif
@@ -1548,112 +1547,83 @@ PHP_FUNCTION(mb_parse_str)
1548
1547
}
1549
1548
/* }}} */
1550
1549
1551
- /* {{{ Returns string in output buffer converted to the http_output encoding */
1552
1550
PHP_FUNCTION (mb_output_handler )
1553
1551
{
1554
- char * arg_string ;
1555
- size_t arg_string_len ;
1552
+ zend_string * str ;
1556
1553
zend_long arg_status ;
1557
- mbfl_string string , result ;
1558
- const char * charset ;
1559
- char * p ;
1560
- const mbfl_encoding * encoding ;
1561
- int last_feed ;
1562
- size_t len ;
1563
- unsigned char send_text_mimetype = 0 ;
1564
- char * s , * mimetype = NULL ;
1565
1554
1566
1555
ZEND_PARSE_PARAMETERS_START (2 , 2 )
1567
- Z_PARAM_STRING ( arg_string , arg_string_len )
1556
+ Z_PARAM_STR ( str )
1568
1557
Z_PARAM_LONG (arg_status )
1569
1558
ZEND_PARSE_PARAMETERS_END ();
1570
1559
1571
- encoding = MBSTRG (current_http_output_encoding );
1572
-
1573
- /* start phase only */
1574
- if ((arg_status & PHP_OUTPUT_HANDLER_START ) != 0 ) {
1575
- /* delete the converter just in case. */
1576
- if (MBSTRG (outconv )) {
1577
- MBSTRG (illegalchars ) += mbfl_buffer_illegalchars (MBSTRG (outconv ));
1578
- mbfl_buffer_converter_delete (MBSTRG (outconv ));
1579
- MBSTRG (outconv ) = NULL ;
1580
- }
1560
+ const mbfl_encoding * encoding = MBSTRG (current_http_output_encoding );
1561
+ if (encoding == & mbfl_encoding_pass ) {
1562
+ RETURN_STR (zend_string_copy (str ));
1563
+ }
1581
1564
1582
- if (encoding == & mbfl_encoding_pass ) {
1583
- RETURN_STRINGL ( arg_string , arg_string_len ) ;
1584
- }
1565
+ if (arg_status & PHP_OUTPUT_HANDLER_START ) {
1566
+ bool free_mimetype = false ;
1567
+ char * mimetype = NULL ;
1585
1568
1586
- /* analyze mime type */
1587
- if (SG (sapi_headers ).mimetype &&
1588
- _php_mb_match_regex (
1589
- MBSTRG (http_output_conv_mimetypes ),
1590
- SG (sapi_headers ).mimetype ,
1591
- strlen (SG (sapi_headers ).mimetype ))) {
1592
- if ((s = strchr (SG (sapi_headers ).mimetype ,';' )) == NULL ) {
1569
+ /* Analyze mime type */
1570
+ if (SG (sapi_headers ).mimetype && _php_mb_match_regex (MBSTRG (http_output_conv_mimetypes ), SG (sapi_headers ).mimetype , strlen (SG (sapi_headers ).mimetype ))) {
1571
+ char * s ;
1572
+ if ((s = strchr (SG (sapi_headers ).mimetype , ';' )) == NULL ) {
1593
1573
mimetype = estrdup (SG (sapi_headers ).mimetype );
1594
1574
} else {
1595
- mimetype = estrndup (SG (sapi_headers ).mimetype ,s - SG (sapi_headers ).mimetype );
1575
+ mimetype = estrndup (SG (sapi_headers ).mimetype , s - SG (sapi_headers ).mimetype );
1596
1576
}
1597
- send_text_mimetype = 1 ;
1577
+ free_mimetype = true ;
1598
1578
} else if (SG (sapi_headers ).send_default_content_type ) {
1599
1579
mimetype = SG (default_mimetype ) ? SG (default_mimetype ) : SAPI_DEFAULT_MIMETYPE ;
1600
1580
}
1601
1581
1602
- /* if content-type is not yet set, set it and activate the converter */
1603
- if (SG (sapi_headers ).send_default_content_type || send_text_mimetype ) {
1604
- charset = encoding -> mime_name ;
1582
+ /* If content-type is not yet set, set it and enable conversion */
1583
+ if (SG (sapi_headers ).send_default_content_type || free_mimetype ) {
1584
+ const char * charset = encoding -> mime_name ;
1605
1585
if (charset ) {
1606
- len = spprintf ( & p , 0 , "Content-Type: %s; charset=%s" , mimetype , charset );
1586
+ char * p ;
1587
+ size_t len = spprintf (& p , 0 , "Content-Type: %s; charset=%s" , mimetype , charset );
1607
1588
if (sapi_add_header (p , len , 0 ) != FAILURE ) {
1608
1589
SG (sapi_headers ).send_default_content_type = 0 ;
1609
1590
}
1610
1591
}
1611
- /* activate the converter */
1612
- MBSTRG (outconv ) = mbfl_buffer_converter_new (MBSTRG (current_internal_encoding ), encoding , 0 );
1613
- if (send_text_mimetype ){
1614
- efree (mimetype );
1615
- }
1592
+
1593
+ MBSTRG (outconv_enabled ) = true;
1594
+ }
1595
+
1596
+ if (free_mimetype ) {
1597
+ efree (mimetype );
1616
1598
}
1617
1599
}
1618
1600
1619
- /* just return if the converter is not activated. */
1620
- if (MBSTRG (outconv ) == NULL ) {
1621
- RETURN_STRINGL (arg_string , arg_string_len );
1601
+ if (!MBSTRG (outconv_enabled )) {
1602
+ RETURN_STR (zend_string_copy (str ));
1622
1603
}
1623
1604
1624
- /* flag */
1625
- last_feed = ((arg_status & PHP_OUTPUT_HANDLER_END ) != 0 );
1626
- /* mode */
1627
- mbfl_buffer_converter_illegal_mode (MBSTRG (outconv ), MBSTRG (current_filter_illegal_mode ));
1628
- mbfl_buffer_converter_illegal_substchar (MBSTRG (outconv ), MBSTRG (current_filter_illegal_substchar ));
1605
+ mb_convert_buf buf ;
1606
+ mb_convert_buf_init (& buf , ZSTR_LEN (str ), MBSTRG (current_filter_illegal_substchar ), MBSTRG (current_filter_illegal_mode ));
1629
1607
1630
- /* feed the string */
1631
- mbfl_string_init (& string );
1632
- /* these are not needed. convd has encoding info.
1633
- string.encoding = MBSTRG(current_internal_encoding);
1634
- */
1635
- string .val = (unsigned char * )arg_string ;
1636
- string .len = arg_string_len ;
1608
+ uint32_t wchar_buf [128 ];
1609
+ unsigned char * in = (unsigned char * )ZSTR_VAL (str );
1610
+ size_t in_len = ZSTR_LEN (str );
1611
+ bool last_feed = ((arg_status & PHP_OUTPUT_HANDLER_END ) != 0 );
1637
1612
1638
- mbfl_buffer_converter_feed (MBSTRG (outconv ), & string );
1639
- if (last_feed ) {
1640
- mbfl_buffer_converter_flush (MBSTRG (outconv ));
1613
+ while (in_len ) {
1614
+ size_t out_len = MBSTRG (current_internal_encoding )-> to_wchar (& in , & in_len , wchar_buf , 128 , & MBSTRG (outconv_state ));
1615
+ ZEND_ASSERT (out_len <= 128 );
1616
+ encoding -> from_wchar (wchar_buf , out_len , & buf , !in_len && last_feed );
1641
1617
}
1642
- /* get the converter output, and return it */
1643
- mbfl_buffer_converter_result (MBSTRG (outconv ), & result );
1644
1618
1645
- // TODO: avoid reallocation ???
1646
- RETVAL_STRINGL ((char * )result .val , result .len ); /* the string is already strdup()'ed */
1647
- efree (result .val );
1619
+ MBSTRG (illegalchars ) += buf .errors ;
1620
+ RETVAL_STR (mb_convert_buf_result (& buf ));
1648
1621
1649
- /* delete the converter if it is the last feed. */
1650
1622
if (last_feed ) {
1651
- MBSTRG (illegalchars ) += mbfl_buffer_illegalchars (MBSTRG (outconv ));
1652
- mbfl_buffer_converter_delete (MBSTRG (outconv ));
1653
- MBSTRG (outconv ) = NULL ;
1623
+ MBSTRG (outconv_enabled ) = false;
1624
+ MBSTRG (outconv_state ) = 0 ;
1654
1625
}
1655
1626
}
1656
- /* }}} */
1657
1627
1658
1628
/* {{{ Convert a multibyte string to an array. If split_length is specified,
1659
1629
break the string down into chunks each split_length characters long. */
0 commit comments