@ -911,6 +911,24 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
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 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
} 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 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
goto out ;
case E2BIG :
if ( prev_in_left = = in_left ) {
err = PHP_ICONV_ERR_UNKNOWN ;
goto out ;
}
break ;
default :
@ -1123,36 +1155,47 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
# endif
}
if ( out_size > out_left ) {
if ( ( buf [ 0 ] > = 33 & & buf [ 0 ] < = 60 ) | |
( buf [ 0 ] > = 62 & & buf [ 0 ] < = 126 ) ) {
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
}
for ( p = ( unsigned char * ) buf ; p < ( unsigned char * ) out_p ; p + + ) {
nbytes_required + = qp_table [ * p ] ;
}
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 ;
if ( nbytes_required < = char_cnt - 2 ) {
break ;
}
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 ;
out_size - = ( ( nbytes_required - ( char_cnt - 2 ) ) + 1 ) / ( 3 - 1 ) ;
in_left = ini_in_left ;
in_p = ini_in_p ;
}
break ;
}
}
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 @@ PHP_FUNCTION(iconv_mime_encode)
}
}
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 ;
}
}