@@ -56,6 +56,9 @@ PHPAPI const char php_sig_mif1[4] = {'m', 'i', 'f', '1'};
56
56
PHPAPI const char php_sig_heic [4 ] = {'h' , 'e' , 'i' , 'c' };
57
57
PHPAPI const char php_sig_heix [4 ] = {'h' , 'e' , 'i' , 'x' };
58
58
59
+ static zend_array php_image_handlers ;
60
+ static int php_image_handler_next_id = IMAGE_FILETYPE_FIXED_COUNT ;
61
+
59
62
/* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type */
60
63
/* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 */
61
64
@@ -1214,7 +1217,7 @@ bool php_is_image_avif(php_stream* stream) {
1214
1217
1215
1218
/* {{{ php_image_type_to_mime_type
1216
1219
* 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 )
1218
1221
{
1219
1222
switch ( image_type ) {
1220
1223
case IMAGE_FILETYPE_GIF :
@@ -1251,7 +1254,13 @@ PHPAPI char * php_image_type_to_mime_type(int image_type)
1251
1254
return "image/avif" ;
1252
1255
case IMAGE_FILETYPE_HEIF :
1253
1256
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
+ }
1255
1264
case IMAGE_FILETYPE_UNKNOWN :
1256
1265
return "application/octet-stream" ; /* suppose binary format */
1257
1266
}
@@ -1267,7 +1276,7 @@ PHP_FUNCTION(image_type_to_mime_type)
1267
1276
Z_PARAM_LONG (p_image_type )
1268
1277
ZEND_PARSE_PARAMETERS_END ();
1269
1278
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 ));
1271
1280
}
1272
1281
/* }}} */
1273
1282
@@ -1339,7 +1348,13 @@ PHP_FUNCTION(image_type_to_extension)
1339
1348
case IMAGE_FILETYPE_HEIF :
1340
1349
imgext = ".heif" ;
1341
1350
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
+ }
1343
1358
}
1344
1359
1345
1360
if (imgext ) {
@@ -1447,6 +1462,15 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp
1447
1462
return IMAGE_FILETYPE_XBM ;
1448
1463
}
1449
1464
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
+
1450
1474
return IMAGE_FILETYPE_UNKNOWN ;
1451
1475
}
1452
1476
/* }}} */
@@ -1455,6 +1479,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
1455
1479
{
1456
1480
int itype = 0 ;
1457
1481
struct php_gfxinfo * result = NULL ;
1482
+ const char * mime_type = NULL ;
1458
1483
1459
1484
if (!stream ) {
1460
1485
RETURN_FALSE ;
@@ -1479,6 +1504,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
1479
1504
result = php_handle_swf (stream );
1480
1505
break ;
1481
1506
case IMAGE_FILETYPE_SWC :
1507
+ /* TODO: with the new php_image_register_handler() APIs, this restriction could be solved */
1482
1508
#if defined(HAVE_ZLIB ) && !defined(COMPILE_DL_ZLIB )
1483
1509
result = php_handle_swc (stream );
1484
1510
#else
@@ -1526,27 +1552,44 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
1526
1552
result = php_handle_avif (stream );
1527
1553
}
1528
1554
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
+ }
1530
1564
case IMAGE_FILETYPE_UNKNOWN :
1531
1565
break ;
1532
1566
}
1533
1567
1534
1568
if (result ) {
1535
- char temp [MAX_LENGTH_OF_LONG * 2 + sizeof ("width=\"\" height=\"\"" )];
1536
1569
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
+ }
1539
1577
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
+ }
1542
1585
1543
1586
if (result -> bits != 0 ) {
1544
1587
add_assoc_long (return_value , "bits" , result -> bits );
1545
1588
}
1546
1589
if (result -> channels != 0 ) {
1547
1590
add_assoc_long (return_value , "channels" , result -> channels );
1548
1591
}
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 ));
1550
1593
efree (result );
1551
1594
} else {
1552
1595
RETURN_FALSE ;
@@ -1609,3 +1652,36 @@ PHP_FUNCTION(getimagesizefromstring)
1609
1652
php_getimagesize_from_any (INTERNAL_FUNCTION_PARAM_PASSTHRU , FROM_DATA );
1610
1653
}
1611
1654
/* }}} */
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