@@ -56,6 +56,9 @@ PHPAPI const char php_sig_mif1[4] = {'m', 'i', 'f', '1'};
5656PHPAPI const char php_sig_heic [4 ] = {'h' , 'e' , 'i' , 'c' };
5757PHPAPI const char php_sig_heix [4 ] = {'h' , 'e' , 'i' , 'x' };
5858
59+ static zend_array php_image_handlers ;
60+ static int php_image_handler_next_id = IMAGE_FILETYPE_FIXED_COUNT ;
61+
5962/* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type */
6063/* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 */
6164
@@ -1214,7 +1217,7 @@ bool php_is_image_avif(php_stream* stream) {
12141217
12151218/* {{{ php_image_type_to_mime_type
12161219 * Convert internal image_type to mime type */
1217- PHPAPI char * php_image_type_to_mime_type (int image_type )
1220+ PHPAPI const char * php_image_type_to_mime_type (int image_type )
12181221{
12191222 switch ( image_type ) {
12201223 case IMAGE_FILETYPE_GIF :
@@ -1251,7 +1254,13 @@ PHPAPI char * php_image_type_to_mime_type(int image_type)
12511254 return "image/avif" ;
12521255 case IMAGE_FILETYPE_HEIF :
12531256 return "image/heif" ;
1254- default :
1257+ default : {
1258+ const struct php_image_handler * handler = zend_hash_index_find_ptr (& php_image_handlers , (zend_ulong ) image_type );
1259+ if (handler ) {
1260+ return handler -> mime_type ;
1261+ }
1262+ ZEND_FALLTHROUGH ;
1263+ }
12551264 case IMAGE_FILETYPE_UNKNOWN :
12561265 return "application/octet-stream" ; /* suppose binary format */
12571266 }
@@ -1267,7 +1276,7 @@ PHP_FUNCTION(image_type_to_mime_type)
12671276 Z_PARAM_LONG (p_image_type )
12681277 ZEND_PARSE_PARAMETERS_END ();
12691278
1270- ZVAL_STRING (return_value , ( char * ) php_image_type_to_mime_type (p_image_type ));
1279+ ZVAL_STRING (return_value , php_image_type_to_mime_type (p_image_type ));
12711280}
12721281/* }}} */
12731282
@@ -1339,7 +1348,13 @@ PHP_FUNCTION(image_type_to_extension)
13391348 case IMAGE_FILETYPE_HEIF :
13401349 imgext = ".heif" ;
13411350 break ;
1342- break ;
1351+ default : {
1352+ const struct php_image_handler * handler = zend_hash_index_find_ptr (& php_image_handlers , (zend_ulong ) image_type );
1353+ if (handler ) {
1354+ imgext = handler -> extension ;
1355+ }
1356+ break ;
1357+ }
13431358 }
13441359
13451360 if (imgext ) {
@@ -1447,6 +1462,15 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp
14471462 return IMAGE_FILETYPE_XBM ;
14481463 }
14491464
1465+ zend_ulong h ;
1466+ zval * zv ;
1467+ ZEND_HASH_FOREACH_NUM_KEY_VAL (& php_image_handlers , h , zv ) {
1468+ const struct php_image_handler * handler = Z_PTR_P (zv );
1469+ if (handler -> identify (stream ) == SUCCESS ) {
1470+ return (int ) h ;
1471+ }
1472+ } ZEND_HASH_FOREACH_END ();
1473+
14501474 return IMAGE_FILETYPE_UNKNOWN ;
14511475}
14521476/* }}} */
@@ -1455,6 +1479,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
14551479{
14561480 int itype = 0 ;
14571481 struct php_gfxinfo * result = NULL ;
1482+ const char * mime_type = NULL ;
14581483
14591484 if (!stream ) {
14601485 RETURN_FALSE ;
@@ -1479,6 +1504,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
14791504 result = php_handle_swf (stream );
14801505 break ;
14811506 case IMAGE_FILETYPE_SWC :
1507+ /* TODO: with the new php_image_register_handler() APIs, this restriction could be solved */
14821508#if defined(HAVE_ZLIB ) && !defined(COMPILE_DL_ZLIB )
14831509 result = php_handle_swc (stream );
14841510#else
@@ -1526,27 +1552,44 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
15261552 result = php_handle_avif (stream );
15271553 }
15281554 break ;
1529- default :
1555+ default : {
1556+ struct php_image_handler * handler = zend_hash_index_find_ptr (& php_image_handlers , (zend_ulong ) itype );
1557+ if (handler ) {
1558+ result = handler -> get_info (stream );
1559+ mime_type = handler -> mime_type ;
1560+ break ;
1561+ }
1562+ ZEND_FALLTHROUGH ;
1563+ }
15301564 case IMAGE_FILETYPE_UNKNOWN :
15311565 break ;
15321566 }
15331567
15341568 if (result ) {
1535- char temp [MAX_LENGTH_OF_LONG * 2 + sizeof ("width=\"\" height=\"\"" )];
15361569 array_init (return_value );
1537- add_index_long (return_value , 0 , result -> width );
1538- add_index_long (return_value , 1 , result -> height );
1570+ if (result -> width_str ) {
1571+ add_index_str (return_value , 0 , result -> width_str );
1572+ add_index_str (return_value , 1 , result -> height_str );
1573+ } else {
1574+ add_index_long (return_value , 0 , result -> width );
1575+ add_index_long (return_value , 1 , result -> height );
1576+ }
15391577 add_index_long (return_value , 2 , itype );
1540- snprintf (temp , sizeof (temp ), "width=\"%d\" height=\"%d\"" , result -> width , result -> height );
1541- add_index_string (return_value , 3 , temp );
1578+ if (result -> width_str ) {
1579+ add_index_str (return_value , 3 , zend_strpprintf_unchecked (0 , "width=\"%S\" height=\"%S\"" , result -> width_str , result -> height_str ));
1580+ } else {
1581+ char temp [MAX_LENGTH_OF_LONG * 2 + sizeof ("width=\"\" height=\"\"" )];
1582+ snprintf (temp , sizeof (temp ), "width=\"%d\" height=\"%d\"" , result -> width , result -> height );
1583+ add_index_string (return_value , 3 , temp );
1584+ }
15421585
15431586 if (result -> bits != 0 ) {
15441587 add_assoc_long (return_value , "bits" , result -> bits );
15451588 }
15461589 if (result -> channels != 0 ) {
15471590 add_assoc_long (return_value , "channels" , result -> channels );
15481591 }
1549- add_assoc_string (return_value , "mime" , ( char * ) php_image_type_to_mime_type (itype ));
1592+ add_assoc_string (return_value , "mime" , mime_type ? mime_type : php_image_type_to_mime_type (itype ));
15501593 efree (result );
15511594 } else {
15521595 RETURN_FALSE ;
@@ -1609,3 +1652,36 @@ PHP_FUNCTION(getimagesizefromstring)
16091652 php_getimagesize_from_any (INTERNAL_FUNCTION_PARAM_PASSTHRU , FROM_DATA );
16101653}
16111654/* }}} */
1655+
1656+ PHP_MINIT_FUNCTION (image )
1657+ {
1658+ zend_hash_init (& php_image_handlers , 4 , NULL , NULL , true);
1659+ return SUCCESS ;
1660+ }
1661+
1662+ PHP_MSHUTDOWN_FUNCTION (image )
1663+ {
1664+ #ifdef ZTS
1665+ if (!tsrm_is_main_thread ()) {
1666+ return SUCCESS ;
1667+ }
1668+ #endif
1669+ zend_hash_destroy (& php_image_handlers );
1670+ return SUCCESS ;
1671+ }
1672+
1673+ extern zend_module_entry basic_functions_module ;
1674+
1675+ int php_image_register_handler (const struct php_image_handler * handler )
1676+ {
1677+ zend_hash_index_add_ptr (& php_image_handlers , (zend_ulong ) php_image_handler_next_id , (void * ) handler );
1678+ zend_register_long_constant (handler -> const_name , strlen (handler -> const_name ), php_image_handler_next_id , CONST_PERSISTENT , basic_functions_module .module_number );
1679+ Z_LVAL_P (zend_get_constant_str (ZEND_STRL ("IMAGETYPE_COUNT" )))++ ;
1680+ return php_image_handler_next_id ++ ;
1681+ }
1682+
1683+ zend_result php_image_unregister_handler (int image_type )
1684+ {
1685+ ZEND_ASSERT (image_type >= IMAGE_FILETYPE_FIXED_COUNT );
1686+ return zend_hash_index_del (& php_image_handlers , (zend_ulong ) image_type );
1687+ }
0 commit comments