mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
- add a weak/tolerant mode to the jpeg loader
* new INI option to enable it (off by default) gd.jpeg_ignore_warning (0|1) * The default mode is the current behavior * if the warning mode is enabled, the image may be loaded succesfully but the jpeg warnings will be raise as notices
This commit is contained in:
21
ext/gd/gd.c
21
ext/gd/gd.c
@@ -35,6 +35,7 @@
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/head.h"
|
||||
#include <math.h>
|
||||
#include "SAPI.h"
|
||||
@@ -309,6 +310,12 @@ zend_module_entry gd_module_entry = {
|
||||
ZEND_GET_MODULE(gd)
|
||||
#endif
|
||||
|
||||
/* {{{ PHP_INI_BEGIN */
|
||||
PHP_INI_BEGIN()
|
||||
PHP_INI_ENTRY("gd.jpeg_ignore_warning", "0", PHP_INI_ALL, NULL)
|
||||
PHP_INI_END()
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_free_gd_image
|
||||
*/
|
||||
static void php_free_gd_image(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
||||
@@ -357,6 +364,8 @@ PHP_MINIT_FUNCTION(gd)
|
||||
le_ps_enc = zend_register_list_destructors_ex(php_free_ps_enc, NULL, "gd PS encoding", module_number);
|
||||
#endif
|
||||
|
||||
REGISTER_INI_ENTRIES();
|
||||
|
||||
REGISTER_LONG_CONSTANT("IMG_GIF", 1, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("IMG_JPG", 2, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("IMG_JPEG", 2, CONST_CS | CONST_PERSISTENT);
|
||||
@@ -1375,7 +1384,8 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
|
||||
php_stream *stream;
|
||||
FILE * fp = NULL;
|
||||
int argc=ZEND_NUM_ARGS();
|
||||
|
||||
long ignore_warning;
|
||||
|
||||
if ((image_type == PHP_GDIMG_TYPE_GD2PART && argc != 5) ||
|
||||
(image_type != PHP_GDIMG_TYPE_GD2PART && argc != 1) ||
|
||||
zend_get_parameters_ex(argc, &file, &srcx, &srcy, &width, &height) == FAILURE) {
|
||||
@@ -1444,6 +1454,11 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
|
||||
im = gdImageCreateFromXpm(fn);
|
||||
break;
|
||||
#endif
|
||||
case PHP_GDIMG_TYPE_JPG:
|
||||
ignore_warning = INI_INT("gd.jpeg_ignore_warning");
|
||||
im = gdImageCreateFromJpeg(fp, ignore_warning);
|
||||
break;
|
||||
|
||||
default:
|
||||
im = (*func_p)(fp);
|
||||
break;
|
||||
@@ -3575,6 +3590,7 @@ static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type )
|
||||
int int_threshold;
|
||||
int x, y;
|
||||
float x_ratio, y_ratio;
|
||||
long ignore_warning;
|
||||
|
||||
if (argc != 5 || zend_get_parameters_ex(argc, &f_org, &f_dest, &height, &width, &threshold) == FAILURE) {
|
||||
ZEND_WRONG_PARAM_COUNT();
|
||||
@@ -3631,7 +3647,8 @@ static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type )
|
||||
|
||||
#ifdef HAVE_GD_JPG
|
||||
case PHP_GDIMG_TYPE_JPG:
|
||||
im_org = gdImageCreateFromJpeg(org);
|
||||
ignore_warning = INI_INT("gd.jpeg_ignore_warning");
|
||||
im_org = gdImageCreateFromJpeg(org, ignore_warning);
|
||||
if (im_org == NULL) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' Not a valid JPEG file", fn_dest);
|
||||
RETURN_FALSE;
|
||||
|
||||
@@ -233,8 +233,8 @@ gdImagePtr gdImageCreateFromPng(FILE *fd);
|
||||
gdImagePtr gdImageCreateFromPngCtx(gdIOCtxPtr in);
|
||||
gdImagePtr gdImageCreateFromWBMP(FILE *inFile);
|
||||
gdImagePtr gdImageCreateFromWBMPCtx(gdIOCtx *infile);
|
||||
gdImagePtr gdImageCreateFromJpeg(FILE *infile);
|
||||
gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile);
|
||||
gdImagePtr gdImageCreateFromJpeg(FILE *infile, int ignore_warning);
|
||||
gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile, int ignore_warning);
|
||||
|
||||
/* A custom data source. */
|
||||
/* The source function must return -1 on error, otherwise the number
|
||||
|
||||
@@ -45,6 +45,33 @@ typedef struct _jmpbuf_wrapper
|
||||
jmp_buf jmpbuf;
|
||||
} jmpbuf_wrapper;
|
||||
|
||||
static long php_jpeg_emit_message(j_common_ptr jpeg_info, int level)
|
||||
{
|
||||
char message[JMSG_LENGTH_MAX];
|
||||
|
||||
(jpeg_info->err->format_message)(jpeg_info,message);
|
||||
|
||||
/* It is a warning message */
|
||||
if (level < 0) {
|
||||
/* display only the 1st warning, as would do a default libjpeg
|
||||
* unless strace_level >= 3
|
||||
*/
|
||||
if ((jpeg_info->err->num_warnings == 0) || (jpeg_info->err->trace_level >= 3)) {
|
||||
php_gd_error_ex(E_NOTICE, "gd-jpeg, libjpeg: recoverable error: %s\n", message);
|
||||
}
|
||||
|
||||
jpeg_info->err->num_warnings++;
|
||||
} else {
|
||||
/* strace msg, Show it if trace_level >= level. */
|
||||
if (jpeg_info->err->trace_level >= level) {
|
||||
php_gd_error_ex(E_NOTICE, "gd-jpeg, libjpeg: strace message: %s\n", message);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Called by the IJG JPEG library upon encountering a fatal error */
|
||||
static void fatal_jpeg_error (j_common_ptr cinfo)
|
||||
{
|
||||
@@ -207,21 +234,21 @@ void gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
|
||||
gdFree (row);
|
||||
}
|
||||
|
||||
gdImagePtr gdImageCreateFromJpeg (FILE * inFile)
|
||||
gdImagePtr gdImageCreateFromJpeg (FILE * inFile, int ignore_warning)
|
||||
{
|
||||
gdImagePtr im;
|
||||
gdIOCtx *in = gdNewFileCtx(inFile);
|
||||
im = gdImageCreateFromJpegCtx(in);
|
||||
im = gdImageCreateFromJpegCtx(in, ignore_warning);
|
||||
in->gd_free (in);
|
||||
|
||||
return im;
|
||||
}
|
||||
|
||||
gdImagePtr gdImageCreateFromJpegPtr (int size, void *data)
|
||||
gdImagePtr gdImageCreateFromJpegPtr (int size, void *data, int ignore_warning)
|
||||
{
|
||||
gdImagePtr im;
|
||||
gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
|
||||
im = gdImageCreateFromJpegCtx(in);
|
||||
im = gdImageCreateFromJpegCtx(in, ignore_warning);
|
||||
in->gd_free(in);
|
||||
|
||||
return im;
|
||||
@@ -231,11 +258,12 @@ void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
|
||||
|
||||
static int CMYKToRGB(int c, int m, int y, int k, int inverted);
|
||||
|
||||
|
||||
/*
|
||||
* Create a gd-format image from the JPEG-format INFILE. Returns the
|
||||
* image, or NULL upon error.
|
||||
*/
|
||||
gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
|
||||
gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile, int ignore_warning)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
@@ -255,6 +283,11 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
|
||||
|
||||
cinfo.err = jpeg_std_error (&jerr);
|
||||
cinfo.client_data = &jmpbufw;
|
||||
|
||||
if (ignore_warning) {
|
||||
cinfo.err->emit_message = (void (*)(j_common_ptr,int)) php_jpeg_emit_message;
|
||||
}
|
||||
|
||||
if (setjmp (jmpbufw.jmpbuf) != 0) {
|
||||
/* we're here courtesy of longjmp */
|
||||
if (row) {
|
||||
@@ -386,12 +419,12 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
|
||||
if (jpeg_finish_decompress (&cinfo) != TRUE) {
|
||||
php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source");
|
||||
}
|
||||
|
||||
/* Thanks to Truxton Fulton */
|
||||
if (cinfo.err->num_warnings > 0) {
|
||||
goto error;
|
||||
if (!ignore_warning) {
|
||||
if (cinfo.err->num_warnings > 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jpeg_destroy_decompress (&cinfo);
|
||||
gdFree (row);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user