mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Add API to register custom image handlers
This is modelled similarly to the password registry API. We have an array to which new handlers can be added, and when a built-in handler cannot handle the image, we try the handlers in the array. The standard module is in control of registering a new constant for the image file type so that no clashes can occur. It also updates the image file type count constant. As such, the registration may only happen during module startup.
This commit is contained in:
@@ -303,6 +303,7 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */
|
||||
BASIC_MINIT_SUBMODULE(standard_filters)
|
||||
BASIC_MINIT_SUBMODULE(user_filters)
|
||||
BASIC_MINIT_SUBMODULE(password)
|
||||
BASIC_MINIT_SUBMODULE(image)
|
||||
|
||||
#ifdef ZTS
|
||||
BASIC_MINIT_SUBMODULE(localeconv)
|
||||
@@ -376,6 +377,7 @@ PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */
|
||||
#endif
|
||||
BASIC_MSHUTDOWN_SUBMODULE(crypt)
|
||||
BASIC_MSHUTDOWN_SUBMODULE(password)
|
||||
BASIC_MSHUTDOWN_SUBMODULE(image)
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -658,7 +658,7 @@ const IMAGETYPE_HEIF = UNKNOWN;
|
||||
const IMAGETYPE_UNKNOWN = UNKNOWN;
|
||||
/**
|
||||
* @var int
|
||||
* @cvalue IMAGE_FILETYPE_COUNT
|
||||
* @cvalue IMAGE_FILETYPE_FIXED_COUNT
|
||||
*/
|
||||
const IMAGETYPE_COUNT = UNKNOWN;
|
||||
|
||||
|
||||
4
ext/standard/basic_functions_arginfo.h
generated
4
ext/standard/basic_functions_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 33629477a13fc7b675fe47eeaaac0d9e15dd2e17 */
|
||||
* Stub hash: dcc4e6865dac52b23534b6ef61c0d6be766af6b9 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0)
|
||||
@@ -3647,7 +3647,7 @@ static void register_basic_functions_symbols(int module_number)
|
||||
REGISTER_LONG_CONSTANT("IMAGETYPE_AVIF", IMAGE_FILETYPE_AVIF, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("IMAGETYPE_HEIF", IMAGE_FILETYPE_HEIF, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("IMAGETYPE_UNKNOWN", IMAGE_FILETYPE_UNKNOWN, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT", IMAGE_FILETYPE_COUNT, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT", IMAGE_FILETYPE_FIXED_COUNT, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("INFO_GENERAL", PHP_INFO_GENERAL, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("INFO_CREDITS", PHP_INFO_CREDITS, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("INFO_CONFIGURATION", PHP_INFO_CONFIGURATION, CONST_PERSISTENT);
|
||||
|
||||
@@ -56,6 +56,9 @@ PHPAPI const char php_sig_mif1[4] = {'m', 'i', 'f', '1'};
|
||||
PHPAPI const char php_sig_heic[4] = {'h', 'e', 'i', 'c'};
|
||||
PHPAPI const char php_sig_heix[4] = {'h', 'e', 'i', 'x'};
|
||||
|
||||
static zend_array php_image_handlers;
|
||||
static int php_image_handler_next_id = IMAGE_FILETYPE_FIXED_COUNT;
|
||||
|
||||
/* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type */
|
||||
/* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 */
|
||||
|
||||
@@ -1214,7 +1217,7 @@ bool php_is_image_avif(php_stream* stream) {
|
||||
|
||||
/* {{{ php_image_type_to_mime_type
|
||||
* Convert internal image_type to mime type */
|
||||
PHPAPI char * php_image_type_to_mime_type(int image_type)
|
||||
PHPAPI const char * php_image_type_to_mime_type(int image_type)
|
||||
{
|
||||
switch( image_type) {
|
||||
case IMAGE_FILETYPE_GIF:
|
||||
@@ -1251,7 +1254,13 @@ PHPAPI char * php_image_type_to_mime_type(int image_type)
|
||||
return "image/avif";
|
||||
case IMAGE_FILETYPE_HEIF:
|
||||
return "image/heif";
|
||||
default:
|
||||
default: {
|
||||
const struct php_image_handler *handler = zend_hash_index_find_ptr(&php_image_handlers, (zend_ulong) image_type);
|
||||
if (handler) {
|
||||
return handler->mime_type;
|
||||
}
|
||||
ZEND_FALLTHROUGH;
|
||||
}
|
||||
case IMAGE_FILETYPE_UNKNOWN:
|
||||
return "application/octet-stream"; /* suppose binary format */
|
||||
}
|
||||
@@ -1267,7 +1276,7 @@ PHP_FUNCTION(image_type_to_mime_type)
|
||||
Z_PARAM_LONG(p_image_type)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
ZVAL_STRING(return_value, (char*)php_image_type_to_mime_type(p_image_type));
|
||||
ZVAL_STRING(return_value, php_image_type_to_mime_type(p_image_type));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -1339,7 +1348,13 @@ PHP_FUNCTION(image_type_to_extension)
|
||||
case IMAGE_FILETYPE_HEIF:
|
||||
imgext = ".heif";
|
||||
break;
|
||||
break;
|
||||
default: {
|
||||
const struct php_image_handler *handler = zend_hash_index_find_ptr(&php_image_handlers, (zend_ulong) image_type);
|
||||
if (handler) {
|
||||
imgext = handler->extension;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (imgext) {
|
||||
@@ -1447,6 +1462,15 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp
|
||||
return IMAGE_FILETYPE_XBM;
|
||||
}
|
||||
|
||||
zend_ulong h;
|
||||
zval *zv;
|
||||
ZEND_HASH_FOREACH_NUM_KEY_VAL(&php_image_handlers, h, zv) {
|
||||
const struct php_image_handler *handler = Z_PTR_P(zv);
|
||||
if (handler->identify(stream) == SUCCESS) {
|
||||
return (int) h;
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
return IMAGE_FILETYPE_UNKNOWN;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1455,6 +1479,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
|
||||
{
|
||||
int itype = 0;
|
||||
struct php_gfxinfo *result = NULL;
|
||||
const char *mime_type = NULL;
|
||||
|
||||
if (!stream) {
|
||||
RETURN_FALSE;
|
||||
@@ -1479,6 +1504,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
|
||||
result = php_handle_swf(stream);
|
||||
break;
|
||||
case IMAGE_FILETYPE_SWC:
|
||||
/* TODO: with the new php_image_register_handler() APIs, this restriction could be solved */
|
||||
#if defined(HAVE_ZLIB) && !defined(COMPILE_DL_ZLIB)
|
||||
result = php_handle_swc(stream);
|
||||
#else
|
||||
@@ -1526,19 +1552,36 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
|
||||
result = php_handle_avif(stream);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
default: {
|
||||
struct php_image_handler* handler = zend_hash_index_find_ptr(&php_image_handlers, (zend_ulong) itype);
|
||||
if (handler) {
|
||||
result = handler->get_info(stream);
|
||||
mime_type = handler->mime_type;
|
||||
break;
|
||||
}
|
||||
ZEND_FALLTHROUGH;
|
||||
}
|
||||
case IMAGE_FILETYPE_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
char temp[MAX_LENGTH_OF_LONG * 2 + sizeof("width=\"\" height=\"\"")];
|
||||
array_init(return_value);
|
||||
add_index_long(return_value, 0, result->width);
|
||||
add_index_long(return_value, 1, result->height);
|
||||
if (result->width_str) {
|
||||
add_index_str(return_value, 0, result->width_str);
|
||||
add_index_str(return_value, 1, result->height_str);
|
||||
} else {
|
||||
add_index_long(return_value, 0, result->width);
|
||||
add_index_long(return_value, 1, result->height);
|
||||
}
|
||||
add_index_long(return_value, 2, itype);
|
||||
snprintf(temp, sizeof(temp), "width=\"%d\" height=\"%d\"", result->width, result->height);
|
||||
add_index_string(return_value, 3, temp);
|
||||
if (result->width_str) {
|
||||
add_index_str(return_value, 3, zend_strpprintf_unchecked(0, "width=\"%S\" height=\"%S\"", result->width_str, result->height_str));
|
||||
} else {
|
||||
char temp[MAX_LENGTH_OF_LONG * 2 + sizeof("width=\"\" height=\"\"")];
|
||||
snprintf(temp, sizeof(temp), "width=\"%d\" height=\"%d\"", result->width, result->height);
|
||||
add_index_string(return_value, 3, temp);
|
||||
}
|
||||
|
||||
if (result->bits != 0) {
|
||||
add_assoc_long(return_value, "bits", result->bits);
|
||||
@@ -1546,7 +1589,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *
|
||||
if (result->channels != 0) {
|
||||
add_assoc_long(return_value, "channels", result->channels);
|
||||
}
|
||||
add_assoc_string(return_value, "mime", (char*)php_image_type_to_mime_type(itype));
|
||||
add_assoc_string(return_value, "mime", mime_type ? mime_type : php_image_type_to_mime_type(itype));
|
||||
efree(result);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
@@ -1609,3 +1652,36 @@ PHP_FUNCTION(getimagesizefromstring)
|
||||
php_getimagesize_from_any(INTERNAL_FUNCTION_PARAM_PASSTHRU, FROM_DATA);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHP_MINIT_FUNCTION(image)
|
||||
{
|
||||
zend_hash_init(&php_image_handlers, 4, NULL, NULL, true);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_MSHUTDOWN_FUNCTION(image)
|
||||
{
|
||||
#ifdef ZTS
|
||||
if (!tsrm_is_main_thread()) {
|
||||
return SUCCESS;
|
||||
}
|
||||
#endif
|
||||
zend_hash_destroy(&php_image_handlers);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
extern zend_module_entry basic_functions_module;
|
||||
|
||||
int php_image_register_handler(const struct php_image_handler *handler)
|
||||
{
|
||||
zend_hash_index_add_ptr(&php_image_handlers, (zend_ulong) php_image_handler_next_id, (void *) handler);
|
||||
zend_register_long_constant(handler->const_name, strlen(handler->const_name), php_image_handler_next_id, CONST_PERSISTENT, basic_functions_module.module_number);
|
||||
Z_LVAL_P(zend_get_constant_str(ZEND_STRL("IMAGETYPE_COUNT")))++;
|
||||
return php_image_handler_next_id++;
|
||||
}
|
||||
|
||||
zend_result php_image_unregister_handler(int image_type)
|
||||
{
|
||||
ZEND_ASSERT(image_type >= IMAGE_FILETYPE_FIXED_COUNT);
|
||||
return zend_hash_index_del(&php_image_handlers, (zend_ulong) image_type);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#ifndef PHP_IMAGE_H
|
||||
#define PHP_IMAGE_H
|
||||
|
||||
PHP_MINIT_FUNCTION(image);
|
||||
PHP_MSHUTDOWN_FUNCTION(image);
|
||||
|
||||
/* {{{ enum image_filetype
|
||||
This enum is used to have ext/standard/image.c and ext/exif/exif.c use
|
||||
the same constants for file types.
|
||||
@@ -46,13 +49,13 @@ typedef enum
|
||||
IMAGE_FILETYPE_AVIF,
|
||||
IMAGE_FILETYPE_HEIF,
|
||||
/* WHEN EXTENDING: PLEASE ALSO REGISTER IN basic_function.stub.php */
|
||||
IMAGE_FILETYPE_COUNT
|
||||
IMAGE_FILETYPE_FIXED_COUNT
|
||||
} image_filetype;
|
||||
/* }}} */
|
||||
|
||||
PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetype);
|
||||
|
||||
PHPAPI char * php_image_type_to_mime_type(int image_type);
|
||||
PHPAPI const char * php_image_type_to_mime_type(int image_type);
|
||||
|
||||
PHPAPI bool php_is_image_avif(php_stream *stream);
|
||||
|
||||
@@ -66,4 +69,22 @@ struct php_gfxinfo {
|
||||
unsigned int channels;
|
||||
};
|
||||
|
||||
typedef zend_result (*php_image_identify)(php_stream *stream);
|
||||
typedef struct php_gfxinfo *(*php_image_get_info)(php_stream *stream);
|
||||
|
||||
struct php_image_handler {
|
||||
const char *mime_type;
|
||||
const char *extension;
|
||||
const char *const_name;
|
||||
php_image_identify identify;
|
||||
php_image_get_info get_info;
|
||||
};
|
||||
|
||||
#define PHP_IMAGE_CONST_NAME(suffix) ("IMAGETYPE_" suffix)
|
||||
|
||||
/* This should only be called on module init */
|
||||
PHPAPI int php_image_register_handler(const struct php_image_handler *handler);
|
||||
/* This should only be called on module shutdown */
|
||||
PHPAPI zend_result php_image_unregister_handler(int image_type);
|
||||
|
||||
#endif /* PHP_IMAGE_H */
|
||||
|
||||
@@ -1,81 +1,87 @@
|
||||
--TEST--
|
||||
image_type_to_mime_type() (passinf equivalent integer values)
|
||||
image_type_to_mime_type() (passing equivalent integer values)
|
||||
--CREDITS--
|
||||
Sanjay Mantoor <sanjay.mantoor@gmail.com>
|
||||
--FILE--
|
||||
<?php
|
||||
echo "*** Testing image_type_to_mime_type() : usage variations ***\n";
|
||||
|
||||
for($imagetype = 0; $imagetype <= IMAGETYPE_COUNT; ++$imagetype) {
|
||||
for($imagetype = 0; $imagetype <= 19; ++$imagetype) {
|
||||
echo "\n-- Iteration $imagetype --\n";
|
||||
var_dump(image_type_to_mime_type($imagetype));
|
||||
}
|
||||
|
||||
echo "\n-- Iteration 999 --\n";
|
||||
var_dump(image_type_to_mime_type(999));
|
||||
?>
|
||||
--EXPECTREGEX--
|
||||
\*\*\* Testing image_type_to_mime_type\(\) : usage variations \*\*\*
|
||||
--EXPECT--
|
||||
*** Testing image_type_to_mime_type() : usage variations ***
|
||||
|
||||
-- Iteration 0 --
|
||||
string\(24\) "application\/octet-stream"
|
||||
string(24) "application/octet-stream"
|
||||
|
||||
-- Iteration 1 --
|
||||
string\(9\) "image\/gif"
|
||||
string(9) "image/gif"
|
||||
|
||||
-- Iteration 2 --
|
||||
string\(10\) "image\/jpeg"
|
||||
string(10) "image/jpeg"
|
||||
|
||||
-- Iteration 3 --
|
||||
string\(9\) "image\/png"
|
||||
string(9) "image/png"
|
||||
|
||||
-- Iteration 4 --
|
||||
string\(29\) "application\/x-shockwave-flash"
|
||||
string(29) "application/x-shockwave-flash"
|
||||
|
||||
-- Iteration 5 --
|
||||
string\(9\) "image\/psd"
|
||||
string(9) "image/psd"
|
||||
|
||||
-- Iteration 6 --
|
||||
string\(9\) "image\/bmp"
|
||||
string(9) "image/bmp"
|
||||
|
||||
-- Iteration 7 --
|
||||
string\(10\) "image\/tiff"
|
||||
string(10) "image/tiff"
|
||||
|
||||
-- Iteration 8 --
|
||||
string\(10\) "image\/tiff"
|
||||
string(10) "image/tiff"
|
||||
|
||||
-- Iteration 9 --
|
||||
string\(24\) "application\/octet-stream"
|
||||
string(24) "application/octet-stream"
|
||||
|
||||
-- Iteration 10 --
|
||||
string\(9\) "image\/jp2"
|
||||
string(9) "image/jp2"
|
||||
|
||||
-- Iteration 11 --
|
||||
string\(24\) "application\/octet-stream"
|
||||
string(24) "application/octet-stream"
|
||||
|
||||
-- Iteration 12 --
|
||||
string\(24\) "application\/octet-stream"
|
||||
string(24) "application/octet-stream"
|
||||
|
||||
-- Iteration 13 --
|
||||
string\(2[49]\) "application\/(x-shockwave-flash|octet-stream)"
|
||||
string(29) "application/x-shockwave-flash"
|
||||
|
||||
-- Iteration 14 --
|
||||
string\(9\) "image\/iff"
|
||||
string(9) "image/iff"
|
||||
|
||||
-- Iteration 15 --
|
||||
string\(18\) "image\/vnd.wap.wbmp"
|
||||
string(18) "image/vnd.wap.wbmp"
|
||||
|
||||
-- Iteration 16 --
|
||||
string\(9\) "image\/xbm"
|
||||
string(9) "image/xbm"
|
||||
|
||||
-- Iteration 17 --
|
||||
string\(24\) "image\/vnd.microsoft.icon"
|
||||
string(24) "image/vnd.microsoft.icon"
|
||||
|
||||
-- Iteration 18 --
|
||||
string\(10\) "image\/webp"
|
||||
string(10) "image/webp"
|
||||
|
||||
-- Iteration 19 --
|
||||
string\(10\) "image\/avif"
|
||||
string(10) "image/avif"
|
||||
|
||||
-- Iteration 20 --
|
||||
string\(10\) "image\/heif"
|
||||
|
||||
-- Iteration 21 --
|
||||
string\(24\) "application\/octet-stream"
|
||||
|
||||
-- Iteration 999 --
|
||||
string(24) "application/octet-stream"
|
||||
|
||||
Reference in New Issue
Block a user