@@ -52,6 +52,9 @@ PHPAPI const char php_sig_ico[4] = {(char)0x00, (char)0x00, (char)0x01, (char)0x
52
52
PHPAPI const char php_sig_riff [4 ] = {'R' , 'I' , 'F' , 'F' };
53
53
PHPAPI const char php_sig_webp [4 ] = {'W' , 'E' , 'B' , 'P' };
54
54
55
+ static zend_array php_image_handlers ;
56
+ static int php_image_handler_next_id = IMAGE_FILETYPE_FIXED_COUNT ;
57
+
55
58
/* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type */
56
59
/* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 */
57
60
@@ -1205,7 +1208,7 @@ bool php_is_image_avif(php_stream* stream) {
1205
1208
1206
1209
/* {{{ php_image_type_to_mime_type
1207
1210
* Convert internal image_type to mime type */
1208
- PHPAPI char * php_image_type_to_mime_type (int image_type )
1211
+ PHPAPI const char * php_image_type_to_mime_type (int image_type )
1209
1212
{
1210
1213
switch ( image_type ) {
1211
1214
case IMAGE_FILETYPE_GIF :
@@ -1240,7 +1243,13 @@ PHPAPI char * php_image_type_to_mime_type(int image_type)
1240
1243
return "image/webp" ;
1241
1244
case IMAGE_FILETYPE_AVIF :
1242
1245
return "image/avif" ;
1243
- default :
1246
+ default : {
1247
+ const struct php_image_handler * handler = zend_hash_index_find_ptr (& php_image_handlers , (zend_ulong ) image_type );
1248
+ if (handler ) {
1249
+ return handler -> mime_type ;
1250
+ }
1251
+ ZEND_FALLTHROUGH ;
1252
+ }
1244
1253
case IMAGE_FILETYPE_UNKNOWN :
1245
1254
return "application/octet-stream" ; /* suppose binary format */
1246
1255
}
@@ -1256,7 +1265,7 @@ PHP_FUNCTION(image_type_to_mime_type)
1256
1265
Z_PARAM_LONG (p_image_type )
1257
1266
ZEND_PARSE_PARAMETERS_END ();
1258
1267
1259
- ZVAL_STRING (return_value , ( char * ) php_image_type_to_mime_type (p_image_type ));
1268
+ ZVAL_STRING (return_value , php_image_type_to_mime_type (p_image_type ));
1260
1269
}
1261
1270
/* }}} */
1262
1271
@@ -1325,6 +1334,13 @@ PHP_FUNCTION(image_type_to_extension)
1325
1334
case IMAGE_FILETYPE_AVIF :
1326
1335
imgext = ".avif" ;
1327
1336
break ;
1337
+ default : {
1338
+ const struct php_image_handler * handler = zend_hash_index_find_ptr (& php_image_handlers , (zend_ulong ) image_type );
1339
+ if (handler ) {
1340
+ imgext = handler -> extension ;
1341
+ }
1342
+ break ;
1343
+ }
1328
1344
}
1329
1345
1330
1346
if (imgext ) {
@@ -1427,6 +1443,15 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp
1427
1443
return IMAGE_FILETYPE_XBM ;
1428
1444
}
1429
1445
1446
+ zend_ulong h ;
1447
+ zval * zv ;
1448
+ ZEND_HASH_FOREACH_NUM_KEY_VAL (& php_image_handlers , h , zv ) {
1449
+ const struct php_image_handler * handler = Z_PTR_P (zv );
1450
+ if (handler -> identify (stream ) == SUCCESS ) {
1451
+ return (int ) h ;
1452
+ }
1453
+ } ZEND_HASH_FOREACH_END ();
1454
+
1430
1455
return IMAGE_FILETYPE_UNKNOWN ;
1431
1456
}
1432
1457
/* }}} */
@@ -1435,6 +1460,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
1435
1460
{
1436
1461
int itype = 0 ;
1437
1462
struct php_gfxinfo * result = NULL ;
1463
+ const char * mime_type = NULL ;
1438
1464
1439
1465
if (!stream ) {
1440
1466
RETURN_FALSE ;
@@ -1459,6 +1485,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
1459
1485
result = php_handle_swf (stream );
1460
1486
break ;
1461
1487
case IMAGE_FILETYPE_SWC :
1488
+ /* TODO: with the new php_image_register_handler() APIs, this restriction could be solved */
1462
1489
#if defined(HAVE_ZLIB ) && !defined(COMPILE_DL_ZLIB )
1463
1490
result = php_handle_swc (stream );
1464
1491
#else
@@ -1501,27 +1528,44 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
1501
1528
case IMAGE_FILETYPE_AVIF :
1502
1529
result = php_handle_avif (stream );
1503
1530
break ;
1504
- default :
1531
+ default : {
1532
+ struct php_image_handler * handler = zend_hash_index_find_ptr (& php_image_handlers , (zend_ulong ) itype );
1533
+ if (handler ) {
1534
+ result = handler -> get_info (stream );
1535
+ mime_type = handler -> mime_type ;
1536
+ break ;
1537
+ }
1538
+ ZEND_FALLTHROUGH ;
1539
+ }
1505
1540
case IMAGE_FILETYPE_UNKNOWN :
1506
1541
break ;
1507
1542
}
1508
1543
1509
1544
if (result ) {
1510
- char temp [MAX_LENGTH_OF_LONG * 2 + sizeof ("width=\"\" height=\"\"" )];
1511
1545
array_init (return_value );
1512
- add_index_long (return_value , 0 , result -> width );
1513
- add_index_long (return_value , 1 , result -> height );
1546
+ if (result -> width_str ) {
1547
+ add_index_str (return_value , 0 , result -> width_str );
1548
+ add_index_str (return_value , 1 , result -> height_str );
1549
+ } else {
1550
+ add_index_long (return_value , 0 , result -> width );
1551
+ add_index_long (return_value , 1 , result -> height );
1552
+ }
1514
1553
add_index_long (return_value , 2 , itype );
1515
- snprintf (temp , sizeof (temp ), "width=\"%d\" height=\"%d\"" , result -> width , result -> height );
1516
- add_index_string (return_value , 3 , temp );
1554
+ if (result -> width_str ) {
1555
+ add_index_str (return_value , 3 , zend_strpprintf_unchecked (0 , "width=\"%S\" height=\"%S\"" , result -> width_str , result -> height_str ));
1556
+ } else {
1557
+ char temp [MAX_LENGTH_OF_LONG * 2 + sizeof ("width=\"\" height=\"\"" )];
1558
+ snprintf (temp , sizeof (temp ), "width=\"%d\" height=\"%d\"" , result -> width , result -> height );
1559
+ add_index_string (return_value , 3 , temp );
1560
+ }
1517
1561
1518
1562
if (result -> bits != 0 ) {
1519
1563
add_assoc_long (return_value , "bits" , result -> bits );
1520
1564
}
1521
1565
if (result -> channels != 0 ) {
1522
1566
add_assoc_long (return_value , "channels" , result -> channels );
1523
1567
}
1524
- add_assoc_string (return_value , "mime" , ( char * ) php_image_type_to_mime_type (itype ));
1568
+ add_assoc_string (return_value , "mime" , mime_type ? mime_type : php_image_type_to_mime_type (itype ));
1525
1569
efree (result );
1526
1570
} else {
1527
1571
RETURN_FALSE ;
@@ -1584,3 +1628,36 @@ PHP_FUNCTION(getimagesizefromstring)
1584
1628
php_getimagesize_from_any (INTERNAL_FUNCTION_PARAM_PASSTHRU , FROM_DATA );
1585
1629
}
1586
1630
/* }}} */
1631
+
1632
+ PHP_MINIT_FUNCTION (image )
1633
+ {
1634
+ zend_hash_init (& php_image_handlers , 4 , NULL , NULL , true);
1635
+ return SUCCESS ;
1636
+ }
1637
+
1638
+ PHP_MSHUTDOWN_FUNCTION (image )
1639
+ {
1640
+ #ifdef ZTS
1641
+ if (!tsrm_is_main_thread ()) {
1642
+ return SUCCESS ;
1643
+ }
1644
+ #endif
1645
+ zend_hash_destroy (& php_image_handlers );
1646
+ return SUCCESS ;
1647
+ }
1648
+
1649
+ extern zend_module_entry basic_functions_module ;
1650
+
1651
+ int php_image_register_handler (const struct php_image_handler * handler )
1652
+ {
1653
+ zend_hash_index_add_ptr (& php_image_handlers , (zend_ulong ) php_image_handler_next_id , (void * ) handler );
1654
+ zend_register_long_constant (handler -> const_name , strlen (handler -> const_name ), php_image_handler_next_id , CONST_PERSISTENT , basic_functions_module .module_number );
1655
+ Z_LVAL_P (zend_get_constant_str (ZEND_STRL ("IMAGETYPE_COUNT" )))++ ;
1656
+ return php_image_handler_next_id ++ ;
1657
+ }
1658
+
1659
+ zend_result php_image_unregister_handler (int image_type )
1660
+ {
1661
+ ZEND_ASSERT (image_type >= IMAGE_FILETYPE_FIXED_COUNT );
1662
+ return zend_hash_index_del (& php_image_handlers , (zend_ulong ) image_type );
1663
+ }
0 commit comments