#include <math.h>
#include "SAPI.h"
#include "php_gd.h"
-#include "ext/standard/fsock.h"
#include "ext/standard/info.h"
#if HAVE_SYS_WAIT_H
static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int);
#endif
-#ifdef GD2_VERS
+#if HAVE_LIBGD15
/* it's >= 1.5, i.e. has IOCtx */
#define USE_GD_IOCTX 1
#else
#undef USE_GD_IOCTX
#endif
-#ifndef USE_GD_IOCTX
+#ifdef USE_GD_IOCTX
+#include "gd_ctx.c"
+#else
#define gdImageCreateFromGifCtx NULL
#define gdImageCreateFromJpegCtx NULL
#define gdImageCreateFromPngCtx NULL
#define gdImageCreateFromWBMPCtx NULL
+typedef FILE gdIOCtx;
+#define CTX_PUTC(c,fp) fputc(c, fp)
#endif
+static void _php_image_output_wbmp(gdImagePtr im, gdIOCtx *fp);
+
#ifdef THREAD_SAFE
DWORD GDlibTls;
static int numthreads=0;
if(issock && socketd) {
#ifdef USE_GD_IOCTX
gdIOCtx* io_ctx;
-#define CHUNK_SIZE 8192
- int read_len=0,buff_len=0,buff_size=5*CHUNK_SIZE;
- char *buff,*buff_cur;
+ int buff_size;
+ char *buff,*buff_em;
- buff = malloc(buff_size); /* Should be malloc! GD uses free */
- buff_cur = buff;
+ buff_size = php_fread_all(&buff_em, socketd, fp, issock);
- do {
- if(buff_len > buff_size - CHUNK_SIZE) {
- buff_size += CHUNK_SIZE;
- buff = realloc(buff, buff_size);
- }
- read_len = SOCK_FREAD(buff_cur, CHUNK_SIZE, socketd);
- buff_len += read_len;
- buff_cur += read_len;
- } while(read_len>0);
+ if(!buff_size) {
+ php_error(E_WARNING,"%s: Cannot read image data",get_active_function_name());
+ RETURN_FALSE;
+ }
+
+ buff = malloc(buff_size); /* Should be malloc! GD uses free */
+ memcpy(buff, buff_em, buff_size);
+ efree(buff_em);
- io_ctx = gdNewDynamicCtx(buff_len,buff);
+ io_ctx = gdNewDynamicCtx(buff_size,buff);
if(!io_ctx) {
php_error(E_WARNING,"%s: Cannot allocate GD IO context",get_active_function_name());
+ RETURN_FALSE;
}
im = (*ioctx_func_p)(io_ctx);
io_ctx->free(io_ctx);
PHP_FUNCTION(imagegif)
{
#ifdef HAVE_GD_GIF
+#ifdef USE_GD_IOCTX
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageGifCtx);
+#else
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageGif);
+#endif
#else /* HAVE_GD_GIF */
php_error(E_WARNING, "ImageGif: No GIF support in this PHP build");
RETURN_FALSE;
PHP_FUNCTION(imagepng)
{
#ifdef HAVE_GD_PNG
+#ifdef USE_GD_IOCTX
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePngCtx);
+#else
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePng);
+#endif
#else /* HAVE_GD_PNG */
php_error(E_WARNING, "ImagePng: No PNG support in this PHP build");
RETURN_FALSE;
PHP_FUNCTION(imagejpeg)
{
#ifdef HAVE_GD_JPG
+#ifdef USE_GD_IOCTX
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageJpegCtx);
+#else
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageJpeg);
+#endif
#else /* HAVE_GD_JPG */
php_error(E_WARNING, "ImageJpeg: No JPG support in this PHP build");
RETURN_FALSE;
Output WBMP image to browser or file */
PHP_FUNCTION(imagewbmp)
{
+#ifdef USE_GD_IOCTX
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", _php_image_output_wbmp);
+#else
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", _php_image_output_wbmp);
+#endif
}
/* }}} */
/* {{{ _php_image_output_wbmp(gdImagePtr im, FILE *fp)
*/
-static void _php_image_output_wbmp(gdImagePtr im, FILE *fp)
+static void _php_image_output_wbmp(gdImagePtr im, gdIOCtx *fp)
{
int x, y;
int c, p, width, height;
/* WBMP header, black and white, no compression */
- fputc(0,fp); fputc(0,fp);
+ CTX_PUTC(0,fp); CTX_PUTC(0,fp);
/* Width and height of image */
c = 1; width = im->sx;
while(width & 0x7f << 7*c) c++;
- while(c > 1) fputc(0x80 | ((width >> 7*--c) & 0xff), fp);
- fputc(width & 0x7f,fp);
+ while(c > 1) CTX_PUTC(0x80 | ((width >> 7*--c) & 0xff), fp);
+ CTX_PUTC(width & 0x7f,fp);
c = 1; height = im->sy;
while(height & 0x7f << 7*c) c++;
- while(c > 1) fputc(0x80 | ((height >> 7*--c) & 0xff), fp);
- fputc(height & 0x7f,fp);
+ while(c > 1) CTX_PUTC(0x80 | ((height >> 7*--c) & 0xff), fp);
+ CTX_PUTC(height & 0x7f,fp);
/* Actual image data */
for(y = 0; y < im->sy; y++) {
if(im->pixels[y][x] == 0) c = c | (1 << (7-p));
#endif
if(++p == 8) {
- fputc(c,fp);
+ CTX_PUTC(c,fp);
p = c = 0;
}
}
- if(p) fputc(c,fp);
+ if(p) CTX_PUTC(c,fp);
}
}
/* }}} */
--- /dev/null
+#define CTX_PUTC(c,ctx) ctx->putC(ctx, c)
+
+static void _php_image_output_putc(struct gdIOCtx *ctx, int c)
+{
+ php_write(&c, 1);
+}
+
+static int _php_image_output_putbuf(struct gdIOCtx *ctx, const void* buf, int l)
+{
+ return php_write((void *)buf, l);
+}
+
+static void _php_image_output_ctxfree(struct gdIOCtx *ctx)
+{
+ if(ctx) {
+ efree(ctx);
+ }
+}
+
+static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)())
+{
+ zval **imgind, **file, **quality;
+ gdImagePtr im;
+ char *fn = NULL;
+ FILE *fp = NULL;
+ int argc = ZEND_NUM_ARGS();
+ int q = -1;
+ gdIOCtx *ctx;
+ GDLS_FETCH();
+
+ /* The quality parameter for Wbmp stands for the threshold
+ So the q variable */
+
+ if (argc < 1 || argc > 3 || zend_get_parameters_ex(argc, &imgind, &file, &quality) == FAILURE)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ ZEND_FETCH_RESOURCE(im, gdImagePtr, imgind, -1, "Image", le_gd);
+
+ if (argc > 1) {
+ convert_to_string_ex(file);
+ fn = Z_STRVAL_PP(file);
+ if (argc == 3) {
+ convert_to_long_ex(quality);
+ q = Z_LVAL_PP(quality);
+ }
+ }
+
+ if ((argc == 2) || (argc == 3 && Z_STRLEN_PP(file))) {
+ if (!fn || fn == empty_string || php_check_open_basedir(fn)) {
+ php_error(E_WARNING, "%s: invalid filename '%s'", get_active_function_name(), fn);
+ RETURN_FALSE;
+ }
+
+ fp = V_FOPEN(fn, "wb");
+ if (!fp) {
+ php_error(E_WARNING, "%s: unable to open '%s' for writing", get_active_function_name(), fn);
+ RETURN_FALSE;
+ }
+
+ ctx = gdNewFileCtx(fp);
+ } else {
+ if(!php_header()) {
+ RETURN_TRUE;
+ }
+ ctx = emalloc(sizeof(gdIOCtx));
+ ctx->putC = _php_image_output_putc;
+ ctx->putBuf = _php_image_output_putbuf;
+ ctx->free = _php_image_output_ctxfree;
+
+#if APACHE && defined(CHARSET_EBCDIC)
+ SLS_FETCH();
+ /* This is a binary file already: avoid EBCDIC->ASCII conversion */
+ ap_bsetflag(php3_rqst->connection->client, B_EBCDIC2ASCII, 0);
+#endif
+ }
+
+ switch(image_type) {
+ case PHP_GDIMG_TYPE_JPG:
+ (*func_p)(im, ctx, q);
+ break;
+ case PHP_GDIMG_TYPE_WBM:
+ if(q<0||q>255) {
+ php_error(E_WARNING, "%s: invalid threshold value '%d'. It must be between 0 and 255",get_active_function_name(), q);
+ }
+ /* break missing intentionally */
+ default:
+ (*func_p)(im, ctx);
+ break;
+ }
+
+ ctx->free(ctx);
+
+ if(fp) {
+ fflush(fp);
+ fclose(fp);
+ }
+
+ RETURN_TRUE;
+}