]> granicus.if.org Git - php/commitdiff
Explode _php_image_output_ctx() into multiple functions
authorMáté Kocsis <kocsismate@woohoolabs.com>
Mon, 6 Jul 2020 09:28:10 +0000 (11:28 +0200)
committerMáté Kocsis <kocsismate@woohoolabs.com>
Mon, 20 Jul 2020 21:25:02 +0000 (23:25 +0200)
Closes GH-5844

ext/gd/gd.c
ext/gd/gd.stub.php
ext/gd/gd_arginfo.h

index eb35655f33a2202f78ae454a38480db8f97a06a8..a64f02aa22c3d088633aa5c9771663923c3ea63f 100644 (file)
@@ -135,6 +135,9 @@ static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS);
 static gdImagePtr _php_image_create_from_string(zend_string *Data, char *tn, gdImagePtr (*ioctx_func_p)());
 static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)());
 static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)());
+static gdIOCtx *create_stream_context_from_zval(zval *to_zval);
+static gdIOCtx *create_stream_context(php_stream *stream, int close_stream);
+static gdIOCtx *create_output_context();
 static int _php_image_type(char data[12]);
 
 /* output streaming (formerly gd_ctx.c) */
@@ -155,10 +158,6 @@ typedef struct _gd_ext_image_object {
 
 static zend_object_handlers php_gd_image_object_handlers;
 
-static const zend_function_entry gd_image_object_methods[] = {
-       PHP_FE_END
-};
-
 static zend_function *php_gd_image_object_get_constructor(zend_object *object)
 {
        zend_throw_error(NULL, "You cannot initialize a GdImage object except through helper functions");
@@ -221,7 +220,7 @@ void php_gd_assign_libgdimageptr_as_extgdimage(zval *val, gdImagePtr image)
 static void php_gd_object_minit_helper()
 {
        zend_class_entry ce;
-       INIT_CLASS_ENTRY(ce, "GdImage", gd_image_object_methods);
+       INIT_CLASS_ENTRY(ce, "GdImage", class_GdImage_methods);
        gd_image_ce = zend_register_internal_class(&ce);
        gd_image_ce->ce_flags |= ZEND_ACC_FINAL;
        gd_image_ce->create_object = php_gd_image_object_create;
@@ -1821,8 +1820,7 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char
                                }
                                (*func_p)(im, fp, q, t);
                                break;
-                       default:
-                               ZEND_UNREACHABLE();
+                       EMPTY_SWITCH_DEFAULT_CASE()
                }
                fflush(fp);
                fclose(fp);
@@ -1848,8 +1846,7 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char
                                }
                                (*func_p)(im, tmp, q, t);
                                break;
-                       default:
-                               ZEND_UNREACHABLE();
+                       EMPTY_SWITCH_DEFAULT_CASE()
                }
 
                fseek(tmp, 0, SEEK_SET);
@@ -1869,7 +1866,45 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char
 /* {{{ Output XBM image to browser or file */
 PHP_FUNCTION(imagexbm)
 {
-       _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageXbmCtx);
+       zval *imgind;
+       char *file = NULL;
+       size_t file_len = 0;
+       zend_long foreground_color = -1;
+       gdImagePtr im;
+       int argc = ZEND_NUM_ARGS();
+       int i;
+       gdIOCtx *ctx = NULL;
+       php_stream *stream;
+
+       if (zend_parse_parameters(argc, "Op!|l", &imgind, gd_image_ce, &file, &file_len, &foreground_color) == FAILURE) {
+               RETURN_THROWS();
+       }
+
+       im = php_gd_libgdimageptr_from_zval_p(imgind);
+
+       if (argc > 1 && file != NULL) {
+               stream = php_stream_open_wrapper(file, "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
+               if (stream == NULL) {
+                       RETURN_FALSE;
+               }
+
+               ctx = create_stream_context(stream, 1);
+       } else {
+               ctx = create_output_context();
+       }
+
+       if (argc < 3) {
+               for (i=0; i < gdImageColorsTotal(im); i++) {
+                       if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) break;
+               }
+               foreground_color = i;
+       }
+
+       gdImageXbmCtx(im, file ? file : "", (int) foreground_color, ctx);
+
+       ctx->gd_free(ctx);
+
+       RETURN_TRUE;
 }
 /* }}} */
 
@@ -1889,7 +1924,6 @@ PHP_FUNCTION(imagepng)
 /* }}} */
 #endif /* HAVE_GD_PNG */
 
-
 #ifdef HAVE_GD_WEBP
 /* {{{ Output WEBP image to browser or file */
 PHP_FUNCTION(imagewebp)
@@ -1899,7 +1933,6 @@ PHP_FUNCTION(imagewebp)
 /* }}} */
 #endif /* HAVE_GD_WEBP */
 
-
 #ifdef HAVE_GD_JPG
 /* {{{ Output JPEG image to browser or file */
 PHP_FUNCTION(imagejpeg)
@@ -1912,7 +1945,43 @@ PHP_FUNCTION(imagejpeg)
 /* {{{ Output WBMP image to browser or file */
 PHP_FUNCTION(imagewbmp)
 {
-       _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageWBMPCtx);
+       zval *imgind;
+       zend_long foreground_color = -1;
+       gdImagePtr im;
+       int argc = ZEND_NUM_ARGS();
+       int i;
+       gdIOCtx *ctx = NULL;
+       zval *to_zval = NULL;
+
+       if (zend_parse_parameters(argc, "O|z!l", &imgind, gd_image_ce, &to_zval, &foreground_color) == FAILURE) {
+               RETURN_THROWS();
+       }
+
+       im = php_gd_libgdimageptr_from_zval_p(imgind);
+
+       if (argc > 1 && to_zval != NULL) {
+               ctx = create_stream_context_from_zval(to_zval);
+               if (!ctx) {
+                       RETURN_FALSE;
+               }
+       } else {
+               ctx = create_output_context();
+       }
+
+       if (argc < 3) {
+               for (i=0; i < gdImageColorsTotal(im); i++) {
+                       if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i))
+                               break;
+               }
+
+               foreground_color = i;
+       }
+
+       gdImageWBMPCtx(im, foreground_color, ctx);
+
+       ctx->gd_free(ctx);
+
+       RETURN_TRUE;
 }
 /* }}} */
 
@@ -1934,7 +2003,33 @@ PHP_FUNCTION(imagegd2)
 /* {{{ Output BMP image to browser or file */
 PHP_FUNCTION(imagebmp)
 {
-       _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_BMP, "BMP", gdImageBmpCtx);
+       zval *imgind;
+       zend_bool compressed = 1;
+       gdImagePtr im;
+       int argc = ZEND_NUM_ARGS();
+       gdIOCtx *ctx = NULL;
+       zval *to_zval = NULL;
+
+       if (zend_parse_parameters(argc, "O|z!b", &imgind, gd_image_ce, &to_zval, &compressed) == FAILURE) {
+               RETURN_THROWS();
+       }
+
+       im = php_gd_libgdimageptr_from_zval_p(imgind);
+
+       if (argc > 1 && to_zval != NULL) {
+               ctx = create_stream_context_from_zval(to_zval);
+               if (!ctx) {
+                       RETURN_FALSE;
+               }
+       } else {
+               ctx = create_output_context();
+       }
+
+       gdImageBmpCtx(im, ctx, (int) compressed);
+
+       ctx->gd_free(ctx);
+
+       RETURN_TRUE;
 }
 /* }}} */
 #endif
@@ -3998,140 +4093,122 @@ static void _php_image_stream_ctxfreeandclose(struct gdIOCtx *ctx) /* {{{ */
        }
 } /* }}} */
 
-/* {{{ _php_image_output_ctx */
+static gdIOCtx *create_stream_context_from_zval(zval *to_zval) {
+       php_stream *stream;
+       int close_stream = 1;
+
+       if (Z_TYPE_P(to_zval) == IS_RESOURCE) {
+               php_stream_from_zval_no_verify(stream, to_zval);
+               if (stream == NULL) {
+                       return NULL;
+               }
+               close_stream = 0;
+       } else if (Z_TYPE_P(to_zval) == IS_STRING) {
+               if (CHECK_ZVAL_NULL_PATH(to_zval)) {
+                       zend_argument_type_error(2, "must not contain null bytes");
+                       return NULL;
+               }
+
+               stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
+               if (stream == NULL) {
+                       return NULL;
+               }
+       } else {
+               zend_argument_type_error(2, "must be a file name or a stream resource, %s given", zend_zval_type_name(to_zval));
+               return NULL;
+       }
+
+       return create_stream_context(stream, close_stream);
+}
+
+static gdIOCtx *create_stream_context(php_stream *stream, int close_stream) {
+       gdIOCtx *ctx = ecalloc(1, sizeof(gdIOCtx));
+
+       ctx->putC = _php_image_stream_putc;
+       ctx->putBuf = _php_image_stream_putbuf;
+       if (close_stream) {
+               ctx->gd_free = _php_image_stream_ctxfreeandclose;
+       } else {
+               ctx->gd_free = _php_image_stream_ctxfree;
+       }
+       ctx->data = (void *)stream;
+
+       return ctx;
+}
+
+static gdIOCtx *create_output_context() {
+       gdIOCtx *ctx = ecalloc(1, sizeof(gdIOCtx));
+
+       ctx->putC = _php_image_output_putc;
+       ctx->putBuf = _php_image_output_putbuf;
+       ctx->gd_free = _php_image_output_ctxfree;
+
+       return ctx;
+}
+
 static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)())
 {
        zval *imgind;
-       char *file = NULL;
-       size_t file_len = 0;
-       zend_long quality, basefilter;
-       zend_bool compressed = 1;
+       zend_long quality = -1, basefilter = -1;
        gdImagePtr im;
        int argc = ZEND_NUM_ARGS();
-       int q = -1, i;
-       int f = -1;
+       int i;
        gdIOCtx *ctx = NULL;
        zval *to_zval = NULL;
-       php_stream *stream;
-       int close_stream = 1;
 
-       /* The third (quality) parameter for Wbmp and Xbm stands for the foreground color index when called
-        * from imagey<type>().
-        */
-       switch (image_type) {
-               case PHP_GDIMG_TYPE_XBM:
-                       if (zend_parse_parameters(argc, "Op!|ll", &imgind, gd_image_ce, &file, &file_len, &quality, &basefilter) == FAILURE) {
-                               RETURN_THROWS();
-                       }
-                       break;
-               case PHP_GDIMG_TYPE_BMP:
-                       if (zend_parse_parameters(argc, "O|z!b", &imgind, gd_image_ce, &to_zval, &compressed) == FAILURE) {
-                               RETURN_THROWS();
-                       }
-                       break;
-               default:
-                       /* PHP_GDIMG_TYPE_GIF
-                        * PHP_GDIMG_TYPE_PNG
-                        * PHP_GDIMG_TYPE_JPG
-                        * PHP_GDIMG_TYPE_WBM
-                        * PHP_GDIMG_TYPE_WEBP
-                        * */
-                       if (zend_parse_parameters(argc, "O|z!ll", &imgind, gd_image_ce, &to_zval, &quality, &basefilter) == FAILURE) {
-                               RETURN_THROWS();
-                       }
+       if (image_type == PHP_GDIMG_TYPE_PNG) {
+               if (zend_parse_parameters(argc, "O|z!ll", &imgind, gd_image_ce, &to_zval, &quality, &basefilter) == FAILURE) {
+                       RETURN_THROWS();
+               }
+       } else {
+               if (zend_parse_parameters(argc, "O|z!l", &imgind, gd_image_ce, &to_zval, &quality) == FAILURE) {
+                       RETURN_THROWS();
+               }
        }
 
        im = php_gd_libgdimageptr_from_zval_p(imgind);
 
-       if (image_type != PHP_GDIMG_TYPE_BMP && argc >= 3) {
-               q = quality; /* or colorindex for foreground of BW images (defaults to black) */
-               if (argc == 4) {
-                       f = basefilter;
-               }
-       }
-
        if (argc > 1 && to_zval != NULL) {
-               if (Z_TYPE_P(to_zval) == IS_RESOURCE) {
-                       php_stream_from_zval_no_verify(stream, to_zval);
-                       if (stream == NULL) {
-                               RETURN_FALSE;
-                       }
-                       close_stream = 0;
-               } else if (Z_TYPE_P(to_zval) == IS_STRING) {
-                       if (CHECK_ZVAL_NULL_PATH(to_zval)) {
-                               zend_argument_type_error(2, "must not contain null bytes");
-                               RETURN_THROWS();
-                       }
-
-                       stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
-                       if (stream == NULL) {
-                               RETURN_FALSE;
-                       }
-               } else {
-                       php_error_docref(NULL, E_WARNING, "Invalid 2nd parameter, it must a filename or a stream");
-                       RETURN_FALSE;
-               }
-       } else if (argc > 1 && file != NULL) {
-               stream = php_stream_open_wrapper(file, "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
-               if (stream == NULL) {
+               ctx = create_stream_context_from_zval(to_zval);
+               if (!ctx) {
                        RETURN_FALSE;
                }
        } else {
-               ctx = ecalloc(1, sizeof(gdIOCtx));
-               ctx->putC = _php_image_output_putc;
-               ctx->putBuf = _php_image_output_putbuf;
-               ctx->gd_free = _php_image_output_ctxfree;
-       }
-
-       if (!ctx)       {
-               ctx = ecalloc(1, sizeof(gdIOCtx));
-               ctx->putC = _php_image_stream_putc;
-               ctx->putBuf = _php_image_stream_putbuf;
-               if (close_stream) {
-                       ctx->gd_free = _php_image_stream_ctxfreeandclose;
-               } else {
-                       ctx->gd_free = _php_image_stream_ctxfree;
-               }
-               ctx->data = (void *)stream;
+               ctx = create_output_context();
        }
 
-       switch(image_type) {
+       switch (image_type) {
                case PHP_GDIMG_TYPE_JPG:
-                       (*func_p)(im, ctx, q);
+                       (*func_p)(im, ctx, (int) quality);
                        break;
                case PHP_GDIMG_TYPE_WEBP:
-                       if (q == -1) {
-                               q = 80;
+                       if (quality == -1) {
+                               quality = 80;
                        }
-                       (*func_p)(im, ctx, q);
+                       (*func_p)(im, ctx, (int) quality);
                        break;
                case PHP_GDIMG_TYPE_PNG:
-                       (*func_p)(im, ctx, q, f);
+                       (*func_p)(im, ctx, (int) quality, (int) basefilter);
                        break;
-               case PHP_GDIMG_TYPE_XBM:
                case PHP_GDIMG_TYPE_WBM:
                        if (argc < 3) {
-                               for(i=0; i < gdImageColorsTotal(im); i++) {
-                                       if(!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) break;
+                               for (i=0; i < gdImageColorsTotal(im); i++) {
+                                       if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) break;
                                }
-                               q = i;
-                       }
-                       if (image_type == PHP_GDIMG_TYPE_XBM) {
-                               (*func_p)(im, file ? file : "", q, ctx);
-                       } else {
-                               (*func_p)(im, q, ctx);
+                               quality = (int) i;
                        }
+
+                       (*func_p)(im, (int) quality, ctx);
                        break;
-               case PHP_GDIMG_TYPE_BMP:
-                       (*func_p)(im, ctx, (int) compressed);
-                       break;
-               default:
+               case PHP_GDIMG_TYPE_GIF:
                        (*func_p)(im, ctx);
                        break;
+                EMPTY_SWITCH_DEFAULT_CASE()
        }
 
        ctx->gd_free(ctx);
 
        RETURN_TRUE;
 }
+
 /* }}} */
index 3202a8b54190a3b5691ea3228895d3e098500810..a284944102e1f422b455dc059b02e48610f12eb2 100644 (file)
@@ -2,6 +2,10 @@
 
 /** @generate-function-entries */
 
+final class GdImage
+{
+}
+
 function gd_info(): array {}
 
 function imageloadfont(string $filename): int|false {}
index b8e95e7cd988704788838654988a4dbf4b07280d..5209f7a34c279d5da19e12c88b68fb3095632551 100644 (file)
@@ -1,5 +1,5 @@
 /* This is a generated file, edit the .stub.php file instead.
- * Stub hash: ce2eb70f449197eca39ca5d8c53ee1369577b035 */
+ * Stub hash: bb1f9f45ea75ccb96886d8fe5a2bc8f5c06e6661 */
 
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0)
 ZEND_END_ARG_INFO()
@@ -855,3 +855,8 @@ static const zend_function_entry ext_functions[] = {
        ZEND_FE(imageresolution, arginfo_imageresolution)
        ZEND_FE_END
 };
+
+
+static const zend_function_entry class_GdImage_methods[] = {
+       ZEND_FE_END
+};