LTP GCOV extension - code coverage report
Current view: directory - ext/standard - image.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 532
Code covered: 3.4 % Executed lines: 18
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
      16                 :    |          Marcus Boerger <helly@php.net>                              |
      17                 :    +----------------------------------------------------------------------+
      18                 :  */
      19                 : 
      20                 : /* $Id: image.c,v 1.114.2.2.2.4 2007/02/24 02:17:27 helly Exp $ */
      21                 : 
      22                 : #include "php.h"
      23                 : #include <stdio.h>
      24                 : #if HAVE_FCNTL_H
      25                 : #include <fcntl.h>
      26                 : #endif
      27                 : #include "fopen_wrappers.h"
      28                 : #include "ext/standard/fsock.h"
      29                 : #if HAVE_UNISTD_H
      30                 : #include <unistd.h>
      31                 : #endif
      32                 : #include "php_image.h"
      33                 : 
      34                 : #if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
      35                 : #include "zlib.h"
      36                 : #endif
      37                 : 
      38                 : /* file type markers */
      39                 : PHPAPI const char php_sig_gif[3] = {'G', 'I', 'F'};
      40                 : PHPAPI const char php_sig_psd[4] = {'8', 'B', 'P', 'S'};
      41                 : PHPAPI const char php_sig_bmp[2] = {'B', 'M'};
      42                 : PHPAPI const char php_sig_swf[3] = {'F', 'W', 'S'};
      43                 : PHPAPI const char php_sig_swc[3] = {'C', 'W', 'S'};
      44                 : PHPAPI const char php_sig_jpg[3] = {(char) 0xff, (char) 0xd8, (char) 0xff};
      45                 : PHPAPI const char php_sig_png[8] = {(char) 0x89, (char) 0x50, (char) 0x4e, (char) 0x47,
      46                 :                                     (char) 0x0d, (char) 0x0a, (char) 0x1a, (char) 0x0a};
      47                 : PHPAPI const char php_sig_tif_ii[4] = {'I','I', (char)0x2A, (char)0x00};
      48                 : PHPAPI const char php_sig_tif_mm[4] = {'M','M', (char)0x00, (char)0x2A};
      49                 : PHPAPI const char php_sig_jpc[3]  = {(char)0xff, (char)0x4f, (char)0xff};
      50                 : PHPAPI const char php_sig_jp2[12] = {(char)0x00, (char)0x00, (char)0x00, (char)0x0c,
      51                 :                                      (char)0x6a, (char)0x50, (char)0x20, (char)0x20,
      52                 :                                      (char)0x0d, (char)0x0a, (char)0x87, (char)0x0a};
      53                 : PHPAPI const char php_sig_iff[4] = {'F','O','R','M'};
      54                 : 
      55                 : /* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type */
      56                 : /* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 */
      57                 : 
      58                 : /* return info as a struct, to make expansion easier */
      59                 : 
      60                 : struct gfxinfo {
      61                 :         unsigned int width;
      62                 :         unsigned int height;
      63                 :         unsigned int bits;
      64                 :         unsigned int channels;
      65                 : };
      66                 : 
      67                 : /* {{{ PHP_MINIT_FUNCTION(imagetypes)
      68                 :  * Register IMAGETYPE_<xxx> constants used by GetImageSize(), image_type_to_mime_type, ext/exif */
      69                 : PHP_MINIT_FUNCTION(imagetypes)
      70             220 : {
      71             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_GIF",     IMAGE_FILETYPE_GIF,     CONST_CS | CONST_PERSISTENT);
      72             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_JPEG",    IMAGE_FILETYPE_JPEG,    CONST_CS | CONST_PERSISTENT);
      73             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_PNG",     IMAGE_FILETYPE_PNG,     CONST_CS | CONST_PERSISTENT);
      74             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_SWF",     IMAGE_FILETYPE_SWF,     CONST_CS | CONST_PERSISTENT);
      75             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_PSD",     IMAGE_FILETYPE_PSD,     CONST_CS | CONST_PERSISTENT);
      76             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_BMP",     IMAGE_FILETYPE_BMP,     CONST_CS | CONST_PERSISTENT);
      77             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_TIFF_II", IMAGE_FILETYPE_TIFF_II, CONST_CS | CONST_PERSISTENT);
      78             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_TIFF_MM", IMAGE_FILETYPE_TIFF_MM, CONST_CS | CONST_PERSISTENT);
      79             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_JPC",     IMAGE_FILETYPE_JPC,     CONST_CS | CONST_PERSISTENT);
      80             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_JP2",     IMAGE_FILETYPE_JP2,     CONST_CS | CONST_PERSISTENT);
      81             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_JPX",     IMAGE_FILETYPE_JPX,     CONST_CS | CONST_PERSISTENT);
      82             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_JB2",     IMAGE_FILETYPE_JB2,     CONST_CS | CONST_PERSISTENT);
      83                 : #if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
      84                 :         REGISTER_LONG_CONSTANT("IMAGETYPE_SWC",     IMAGE_FILETYPE_SWC,     CONST_CS | CONST_PERSISTENT);
      85                 : #endif  
      86             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_IFF",     IMAGE_FILETYPE_IFF,     CONST_CS | CONST_PERSISTENT);
      87             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_WBMP",    IMAGE_FILETYPE_WBMP,    CONST_CS | CONST_PERSISTENT);
      88             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_JPEG2000",IMAGE_FILETYPE_JPC,     CONST_CS | CONST_PERSISTENT); /* keep alias */
      89             220 :         REGISTER_LONG_CONSTANT("IMAGETYPE_XBM",     IMAGE_FILETYPE_XBM,     CONST_CS | CONST_PERSISTENT);
      90             220 :         return SUCCESS;
      91                 : }
      92                 : /* }}} */
      93                 : 
      94                 : /* {{{ php_handle_gif
      95                 :  * routine to handle GIF files. If only everything were that easy... ;} */
      96                 : static struct gfxinfo *php_handle_gif (php_stream * stream TSRMLS_DC)
      97               0 : {
      98               0 :         struct gfxinfo *result = NULL;
      99                 :         unsigned char dim[5];
     100                 : 
     101               0 :         if (php_stream_seek(stream, 3, SEEK_CUR))
     102               0 :                 return NULL;
     103                 : 
     104               0 :         if (php_stream_read(stream, dim, sizeof(dim)) != sizeof(dim))
     105               0 :                 return NULL;
     106                 : 
     107               0 :         result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
     108               0 :         result->width    = (unsigned int)dim[0] | (((unsigned int)dim[1])<<8);
     109               0 :         result->height   = (unsigned int)dim[2] | (((unsigned int)dim[3])<<8);
     110               0 :         result->bits     = dim[4]&0x80 ? ((((unsigned int)dim[4])&0x07) + 1) : 0;
     111               0 :         result->channels = 3; /* allways */
     112                 : 
     113               0 :         return result;
     114                 : }
     115                 : /* }}} */
     116                 : 
     117                 : /* {{{ php_handle_psd
     118                 :  */
     119                 : static struct gfxinfo *php_handle_psd (php_stream * stream TSRMLS_DC)
     120               0 : {
     121               0 :         struct gfxinfo *result = NULL;
     122                 :         unsigned char dim[8];
     123                 : 
     124               0 :         if (php_stream_seek(stream, 11, SEEK_CUR))
     125               0 :                 return NULL;
     126                 : 
     127               0 :         if (php_stream_read(stream, dim, sizeof(dim)) != sizeof(dim))
     128               0 :                 return NULL;
     129                 : 
     130               0 :         result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
     131               0 :         result->height   =  (((unsigned int)dim[0]) << 24) + (((unsigned int)dim[1]) << 16) + (((unsigned int)dim[2]) << 8) + ((unsigned int)dim[3]);
     132               0 :         result->width    =  (((unsigned int)dim[4]) << 24) + (((unsigned int)dim[5]) << 16) + (((unsigned int)dim[6]) << 8) + ((unsigned int)dim[7]);
     133                 : 
     134               0 :         return result;
     135                 : }
     136                 : /* }}} */
     137                 : 
     138                 : /* {{{ php_handle_bmp
     139                 :  */
     140                 : static struct gfxinfo *php_handle_bmp (php_stream * stream TSRMLS_DC)
     141               0 : {
     142               0 :         struct gfxinfo *result = NULL;
     143                 :         unsigned char dim[16];
     144                 :         int size;
     145                 : 
     146               0 :         if (php_stream_seek(stream, 11, SEEK_CUR))
     147               0 :                 return NULL;
     148                 : 
     149               0 :         if (php_stream_read(stream, dim, sizeof(dim)) != sizeof(dim))
     150               0 :                 return NULL;
     151                 : 
     152               0 :         size   = (((unsigned int)dim[ 3]) << 24) + (((unsigned int)dim[ 2]) << 16) + (((unsigned int)dim[ 1]) << 8) + ((unsigned int) dim[ 0]);
     153               0 :         if (size == 12) {
     154               0 :                 result = (struct gfxinfo *) ecalloc (1, sizeof(struct gfxinfo));
     155               0 :                 result->width    =  (((unsigned int)dim[ 5]) << 8) + ((unsigned int) dim[ 4]);
     156               0 :                 result->height   =  (((unsigned int)dim[ 7]) << 8) + ((unsigned int) dim[ 6]);
     157               0 :                 result->bits     =  ((unsigned int)dim[11]);
     158               0 :         } else if (size > 12 && (size <= 64 || size == 108)) {
     159               0 :                 result = (struct gfxinfo *) ecalloc (1, sizeof(struct gfxinfo));
     160               0 :                 result->width    =  (((unsigned int)dim[ 7]) << 24) + (((unsigned int)dim[ 6]) << 16) + (((unsigned int)dim[ 5]) << 8) + ((unsigned int) dim[ 4]);
     161               0 :                 result->height   =  (((unsigned int)dim[11]) << 24) + (((unsigned int)dim[10]) << 16) + (((unsigned int)dim[ 9]) << 8) + ((unsigned int) dim[ 8]);
     162               0 :                 result->bits     =  (((unsigned int)dim[15]) <<  8) +  ((unsigned int)dim[14]);
     163                 :         } else {
     164               0 :                 return NULL;
     165                 :         }
     166                 : 
     167               0 :         return result;
     168                 : }
     169                 : /* }}} */
     170                 : 
     171                 : /* {{{ php_swf_get_bits
     172                 :  * routines to handle SWF files. */
     173                 : static unsigned long int php_swf_get_bits (unsigned char* buffer, unsigned int pos, unsigned int count)
     174               0 : {
     175                 :         unsigned int loop;
     176               0 :         unsigned long int result = 0;
     177                 : 
     178               0 :         for (loop = pos; loop < pos + count; loop++)
     179                 :         {
     180               0 :                 result = result +
     181                 :                         ((((buffer[loop / 8]) >> (7 - (loop % 8))) & 0x01) << (count - (loop - pos) - 1));
     182                 :         }
     183               0 :         return result;
     184                 : }
     185                 : /* }}} */
     186                 : 
     187                 : #if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
     188                 : /* {{{ php_handle_swc
     189                 :  */
     190                 : static struct gfxinfo *php_handle_swc(php_stream * stream TSRMLS_DC)
     191                 : {
     192                 :         struct gfxinfo *result = NULL;
     193                 : 
     194                 :         long bits;
     195                 :         unsigned char a[64];
     196                 :         unsigned long len=64, szlength;
     197                 :         int factor=1,maxfactor=16;
     198                 :         int slength, status=0;
     199                 :         char *b, *buf=NULL, *bufz=NULL;
     200                 : 
     201                 :         b = ecalloc (1, len + 1);
     202                 : 
     203                 :         if (php_stream_seek(stream, 5, SEEK_CUR))
     204                 :                 return NULL;
     205                 : 
     206                 :         if (php_stream_read(stream, a, sizeof(a)) != sizeof(a))
     207                 :                 return NULL;
     208                 : 
     209                 :         if (uncompress(b, &len, a, sizeof(a)) != Z_OK) {
     210                 :                 /* failed to decompress the file, will try reading the rest of the file */
     211                 :                 if (php_stream_seek(stream, 8, SEEK_SET))
     212                 :                         return NULL;
     213                 : 
     214                 :                 slength = php_stream_copy_to_mem(stream, &bufz, PHP_STREAM_COPY_ALL, 0);
     215                 :                 
     216                 :                 /*
     217                 :                  * zlib::uncompress() wants to know the output data length
     218                 :                  * if none was given as a parameter
     219                 :                  * we try from input length * 2 up to input length * 2^8
     220                 :                  * doubling it whenever it wasn't big enough
     221                 :                  * that should be eneugh for all real life cases
     222                 :                 */
     223                 :                 
     224                 :                 do {
     225                 :                         szlength=slength*(1<<factor++);
     226                 :                         buf = (char *) erealloc(buf,szlength);
     227                 :                         status = uncompress(buf, &szlength, bufz, slength);
     228                 :                 } while ((status==Z_BUF_ERROR)&&(factor<maxfactor));
     229                 :                 
     230                 :                 if (bufz) {
     231                 :                         pefree(bufz, 0);
     232                 :                 }       
     233                 :                 
     234                 :                 if (status == Z_OK) {
     235                 :                          memcpy(b, buf, len);
     236                 :                 }
     237                 :                 
     238                 :                 if (buf) { 
     239                 :                         efree(buf);
     240                 :                 }       
     241                 :         }
     242                 :         
     243                 :         if (!status) {
     244                 :                 result = (struct gfxinfo *) ecalloc (1, sizeof (struct gfxinfo));
     245                 :                 bits = php_swf_get_bits (b, 0, 5);
     246                 :                 result->width = (php_swf_get_bits (b, 5 + bits, bits) -
     247                 :                         php_swf_get_bits (b, 5, bits)) / 20;
     248                 :                 result->height = (php_swf_get_bits (b, 5 + (3 * bits), bits) -
     249                 :                         php_swf_get_bits (b, 5 + (2 * bits), bits)) / 20;
     250                 :         } else {
     251                 :                 result = NULL;
     252                 :         }       
     253                 :                 
     254                 :         efree (b);
     255                 :         return result;
     256                 : }
     257                 : /* }}} */
     258                 : #endif
     259                 : 
     260                 : /* {{{ php_handle_swf
     261                 :  */
     262                 : static struct gfxinfo *php_handle_swf (php_stream * stream TSRMLS_DC)
     263               0 : {
     264               0 :         struct gfxinfo *result = NULL;
     265                 :         long bits;
     266                 :         unsigned char a[32];
     267                 : 
     268               0 :         if (php_stream_seek(stream, 5, SEEK_CUR))
     269               0 :                 return NULL;
     270                 : 
     271               0 :         if (php_stream_read(stream, a, sizeof(a)) != sizeof(a))
     272               0 :                 return NULL;
     273                 : 
     274               0 :         result = (struct gfxinfo *) ecalloc (1, sizeof (struct gfxinfo));
     275               0 :         bits = php_swf_get_bits (a, 0, 5);
     276               0 :         result->width = (php_swf_get_bits (a, 5 + bits, bits) -
     277                 :                 php_swf_get_bits (a, 5, bits)) / 20;
     278               0 :         result->height = (php_swf_get_bits (a, 5 + (3 * bits), bits) -
     279                 :                 php_swf_get_bits (a, 5 + (2 * bits), bits)) / 20;
     280               0 :         result->bits     = 0;
     281               0 :         result->channels = 0;
     282               0 :         return result;
     283                 : }
     284                 : /* }}} */
     285                 : 
     286                 : /* {{{ php_handle_png
     287                 :  * routine to handle PNG files */
     288                 : static struct gfxinfo *php_handle_png (php_stream * stream TSRMLS_DC)
     289               0 : {
     290               0 :         struct gfxinfo *result = NULL;
     291                 :         unsigned char dim[9];
     292                 : /* Width:              4 bytes
     293                 :  * Height:             4 bytes
     294                 :  * Bit depth:          1 byte
     295                 :  * Color type:         1 byte
     296                 :  * Compression method: 1 byte
     297                 :  * Filter method:      1 byte
     298                 :  * Interlace method:   1 byte
     299                 :  */
     300                 : 
     301               0 :         if (php_stream_seek(stream, 8, SEEK_CUR))
     302               0 :                 return NULL;
     303                 : 
     304               0 :         if((php_stream_read(stream, dim, sizeof(dim))) < sizeof(dim))
     305               0 :                 return NULL;
     306                 : 
     307               0 :         result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
     308               0 :         result->width  = (((unsigned int)dim[0]) << 24) + (((unsigned int)dim[1]) << 16) + (((unsigned int)dim[2]) << 8) + ((unsigned int)dim[3]);
     309               0 :         result->height = (((unsigned int)dim[4]) << 24) + (((unsigned int)dim[5]) << 16) + (((unsigned int)dim[6]) << 8) + ((unsigned int)dim[7]);
     310               0 :         result->bits   = (unsigned int)dim[8];
     311               0 :         return result;
     312                 : }
     313                 : /* }}} */
     314                 : 
     315                 : /* routines to handle JPEG data */
     316                 : 
     317                 : /* some defines for the different JPEG block types */
     318                 : #define M_SOF0  0xC0                    /* Start Of Frame N */
     319                 : #define M_SOF1  0xC1                    /* N indicates which compression process */
     320                 : #define M_SOF2  0xC2                    /* Only SOF0-SOF2 are now in common use */
     321                 : #define M_SOF3  0xC3
     322                 : #define M_SOF5  0xC5                    /* NB: codes C4 and CC are NOT SOF markers */
     323                 : #define M_SOF6  0xC6
     324                 : #define M_SOF7  0xC7
     325                 : #define M_SOF9  0xC9
     326                 : #define M_SOF10 0xCA
     327                 : #define M_SOF11 0xCB
     328                 : #define M_SOF13 0xCD
     329                 : #define M_SOF14 0xCE
     330                 : #define M_SOF15 0xCF
     331                 : #define M_SOI   0xD8
     332                 : #define M_EOI   0xD9                    /* End Of Image (end of datastream) */
     333                 : #define M_SOS   0xDA                    /* Start Of Scan (begins compressed data) */
     334                 : #define M_APP0  0xe0
     335                 : #define M_APP1  0xe1
     336                 : #define M_APP2  0xe2
     337                 : #define M_APP3  0xe3
     338                 : #define M_APP4  0xe4
     339                 : #define M_APP5  0xe5
     340                 : #define M_APP6  0xe6
     341                 : #define M_APP7  0xe7
     342                 : #define M_APP8  0xe8
     343                 : #define M_APP9  0xe9
     344                 : #define M_APP10 0xea
     345                 : #define M_APP11 0xeb
     346                 : #define M_APP12 0xec
     347                 : #define M_APP13 0xed
     348                 : #define M_APP14 0xee
     349                 : #define M_APP15 0xef
     350                 : #define M_COM   0xFE            /* COMment                                  */
     351                 : 
     352                 : #define M_PSEUDO 0xFFD8                 /* pseudo marker for start of image(byte 0) */
     353                 : 
     354                 : /* {{{ php_read2
     355                 :  */
     356                 : static unsigned short php_read2(php_stream * stream TSRMLS_DC)
     357               0 : {
     358                 :         unsigned char a[2];
     359                 : 
     360                 :         /* just return 0 if we hit the end-of-file */
     361               0 :         if((php_stream_read(stream, a, sizeof(a))) <= 0) return 0;
     362                 : 
     363               0 :         return (((unsigned short)a[0]) << 8) + ((unsigned short)a[1]);
     364                 : }
     365                 : /* }}} */
     366                 : 
     367                 : /* {{{ php_next_marker
     368                 :  * get next marker byte from file */
     369                 : static unsigned int php_next_marker(php_stream * stream, int last_marker, int comment_correction, int ff_read TSRMLS_DC)
     370               0 : {
     371               0 :         int a=0, marker;
     372                 : 
     373                 :         /* get marker byte, swallowing possible padding                           */
     374               0 :         if (last_marker==M_COM && comment_correction) {
     375                 :                 /* some software does not count the length bytes of COM section           */
     376                 :                 /* one company doing so is very much envolved in JPEG... so we accept too */
     377                 :                 /* by the way: some of those companies changed their code now...          */
     378               0 :                 comment_correction = 2;
     379                 :         } else {
     380               0 :                 last_marker = 0;
     381               0 :                 comment_correction = 0;
     382                 :         }
     383               0 :         if (ff_read) {
     384               0 :                 a = 1; /* already read 0xff in filetype detection */
     385                 :         }
     386                 :         do {
     387               0 :                 if ((marker = php_stream_getc(stream)) == EOF)
     388                 :                 {
     389               0 :                         return M_EOI;/* we hit EOF */
     390                 :                 }
     391               0 :                 if (last_marker==M_COM && comment_correction>0)
     392                 :                 {
     393               0 :                         if (marker != 0xFF)
     394                 :                         {
     395               0 :                                 marker = 0xff;
     396               0 :                                 comment_correction--;
     397                 :                         } else {
     398               0 :                                 last_marker = M_PSEUDO; /* stop skipping non 0xff for M_COM */
     399                 :                         }
     400                 :                 }
     401               0 :                 if (++a > 25)
     402                 :                 {
     403                 :                         /* who knows the maxim amount of 0xff? though 7 */
     404                 :                         /* but found other implementations              */
     405               0 :                         return M_EOI;
     406                 :                 }
     407               0 :         } while (marker == 0xff);
     408               0 :         if (a < 2)
     409                 :         {
     410               0 :                 return M_EOI; /* at least one 0xff is needed before marker code */
     411                 :         }
     412               0 :         if ( last_marker==M_COM && comment_correction)
     413                 :         {
     414               0 :                 return M_EOI; /* ah illegal: char after COM section not 0xFF */
     415                 :         }
     416               0 :         return (unsigned int)marker;
     417                 : }
     418                 : /* }}} */
     419                 : 
     420                 : /* {{{ php_skip_variable
     421                 :  * skip over a variable-length block; assumes proper length marker */
     422                 : static int php_skip_variable(php_stream * stream TSRMLS_DC)
     423               0 : {
     424               0 :         off_t length = ((unsigned int)php_read2(stream TSRMLS_CC));
     425                 : 
     426               0 :         if (length < 2)      {
     427               0 :                 return 0;
     428                 :         }
     429               0 :         length = length - 2;
     430               0 :         php_stream_seek(stream, (long)length, SEEK_CUR);
     431               0 :         return 1;
     432                 : }
     433                 : /* }}} */
     434                 : 
     435                 : /* {{{ php_read_APP
     436                 :  */
     437                 : static int php_read_APP(php_stream * stream, unsigned int marker, zval *info TSRMLS_DC)
     438               0 : {
     439                 :         unsigned short length;
     440                 :         unsigned char *buffer;
     441                 :         unsigned char markername[16];
     442                 :         zval *tmp;
     443                 : 
     444               0 :         length = php_read2(stream TSRMLS_CC);
     445               0 :         if (length < 2)      {
     446               0 :                 return 0;
     447                 :         }
     448               0 :         length -= 2;                            /* length includes itself */
     449                 : 
     450               0 :         buffer = emalloc(length);
     451                 : 
     452               0 :         if (php_stream_read(stream, buffer, (long) length) <= 0) {
     453               0 :                 efree(buffer);
     454               0 :                 return 0;
     455                 :         }
     456                 : 
     457               0 :         snprintf(markername, sizeof(markername), "APP%d", marker - M_APP0);
     458                 : 
     459               0 :         if (zend_hash_find(Z_ARRVAL_P(info), markername, strlen(markername)+1, (void **) &tmp) == FAILURE) {
     460                 :                 /* XXX we onyl catch the 1st tag of it's kind! */
     461               0 :                 add_assoc_stringl(info, markername, buffer, length, 1);
     462                 :         }
     463                 : 
     464               0 :         efree(buffer);
     465               0 :         return 1;
     466                 : }
     467                 : /* }}} */
     468                 : 
     469                 : /* {{{ php_handle_jpeg
     470                 :    main loop to parse JPEG structure */
     471                 : static struct gfxinfo *php_handle_jpeg (php_stream * stream, zval *info TSRMLS_DC) 
     472               0 : {
     473               0 :         struct gfxinfo *result = NULL;
     474               0 :         unsigned int marker = M_PSEUDO;
     475               0 :         unsigned short length, ff_read=1;
     476                 : 
     477                 :         for (;;) {
     478               0 :                 marker = php_next_marker(stream, marker, 1, ff_read TSRMLS_CC);
     479               0 :                 ff_read = 0;
     480               0 :                 switch (marker) {
     481                 :                         case M_SOF0:
     482                 :                         case M_SOF1:
     483                 :                         case M_SOF2:
     484                 :                         case M_SOF3:
     485                 :                         case M_SOF5:
     486                 :                         case M_SOF6:
     487                 :                         case M_SOF7:
     488                 :                         case M_SOF9:
     489                 :                         case M_SOF10:
     490                 :                         case M_SOF11:
     491                 :                         case M_SOF13:
     492                 :                         case M_SOF14:
     493                 :                         case M_SOF15:
     494               0 :                                 if (result == NULL) {
     495                 :                                         /* handle SOFn block */
     496               0 :                                         result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
     497               0 :                                         length = php_read2(stream TSRMLS_CC);
     498               0 :                                         result->bits     = php_stream_getc(stream);
     499               0 :                                         result->height   = php_read2(stream TSRMLS_CC);
     500               0 :                                         result->width    = php_read2(stream TSRMLS_CC);
     501               0 :                                         result->channels = php_stream_getc(stream);
     502               0 :                                         if (!info || length < 8) { /* if we don't want an extanded info -> return */
     503               0 :                                                 return result;
     504                 :                                         }
     505               0 :                                         if (php_stream_seek(stream, length - 8, SEEK_CUR)) { /* file error after info */
     506               0 :                                                 return result;
     507                 :                                         }
     508                 :                                 } else {
     509               0 :                                         if (!php_skip_variable(stream TSRMLS_CC)) {
     510               0 :                                                 return result;
     511                 :                                         }
     512                 :                                 }
     513               0 :                                 break;
     514                 : 
     515                 :                         case M_APP0:
     516                 :                         case M_APP1:
     517                 :                         case M_APP2:
     518                 :                         case M_APP3:
     519                 :                         case M_APP4:
     520                 :                         case M_APP5:
     521                 :                         case M_APP6:
     522                 :                         case M_APP7:
     523                 :                         case M_APP8:
     524                 :                         case M_APP9:
     525                 :                         case M_APP10:
     526                 :                         case M_APP11:
     527                 :                         case M_APP12:
     528                 :                         case M_APP13:
     529                 :                         case M_APP14:
     530                 :                         case M_APP15:
     531               0 :                                 if (info) {
     532               0 :                                         if (!php_read_APP(stream, marker, info TSRMLS_CC)) { /* read all the app markes... */
     533               0 :                                                 return result;
     534                 :                                         }
     535                 :                                 } else {
     536               0 :                                         if (!php_skip_variable(stream TSRMLS_CC)) {
     537               0 :                                                 return result;
     538                 :                                         }
     539                 :                                 }
     540               0 :                                 break;
     541                 : 
     542                 :                         case M_SOS:
     543                 :                         case M_EOI:
     544               0 :                                 return result;  /* we're about to hit image data, or are at EOF. stop processing. */
     545                 :                         
     546                 :                         default:
     547               0 :                                 if (!php_skip_variable(stream TSRMLS_CC)) { /* anything else isn't interesting */
     548               0 :                                         return result;
     549                 :                                 }
     550                 :                                 break;
     551                 :                 }
     552               0 :         }
     553                 : 
     554                 :         return result; /* perhaps image broken -> no info but size */
     555                 : }
     556                 : /* }}} */
     557                 : 
     558                 : /* {{{ php_read4
     559                 :  */
     560                 : static unsigned int php_read4(php_stream * stream TSRMLS_DC)
     561               0 : {
     562                 :         unsigned char a[4];
     563                 : 
     564                 :         /* just return 0 if we hit the end-of-file */
     565               0 :         if ((php_stream_read(stream, a, sizeof(a))) != sizeof(a)) return 0;
     566                 : 
     567               0 :         return (((unsigned int)a[0]) << 24)
     568                 :              + (((unsigned int)a[1]) << 16)
     569                 :              + (((unsigned int)a[2]) <<  8)
     570                 :              + (((unsigned int)a[3]));
     571                 : }
     572                 : /* }}} */
     573                 : 
     574                 : /* {{{ JPEG 2000 Marker Codes */
     575                 : #define JPEG2000_MARKER_PREFIX 0xFF /* All marker codes start with this */
     576                 : #define JPEG2000_MARKER_SOC 0x4F /* Start of Codestream */
     577                 : #define JPEG2000_MARKER_SOT 0x90 /* Start of Tile part */
     578                 : #define JPEG2000_MARKER_SOD 0x93 /* Start of Data */
     579                 : #define JPEG2000_MARKER_EOC 0xD9 /* End of Codestream */
     580                 : #define JPEG2000_MARKER_SIZ 0x51 /* Image and tile size */
     581                 : #define JPEG2000_MARKER_COD 0x52 /* Coding style default */ 
     582                 : #define JPEG2000_MARKER_COC 0x53 /* Coding style component */
     583                 : #define JPEG2000_MARKER_RGN 0x5E /* Region of interest */
     584                 : #define JPEG2000_MARKER_QCD 0x5C /* Quantization default */
     585                 : #define JPEG2000_MARKER_QCC 0x5D /* Quantization component */
     586                 : #define JPEG2000_MARKER_POC 0x5F /* Progression order change */
     587                 : #define JPEG2000_MARKER_TLM 0x55 /* Tile-part lengths */
     588                 : #define JPEG2000_MARKER_PLM 0x57 /* Packet length, main header */
     589                 : #define JPEG2000_MARKER_PLT 0x58 /* Packet length, tile-part header */
     590                 : #define JPEG2000_MARKER_PPM 0x60 /* Packed packet headers, main header */
     591                 : #define JPEG2000_MARKER_PPT 0x61 /* Packed packet headers, tile part header */
     592                 : #define JPEG2000_MARKER_SOP 0x91 /* Start of packet */
     593                 : #define JPEG2000_MARKER_EPH 0x92 /* End of packet header */
     594                 : #define JPEG2000_MARKER_CRG 0x63 /* Component registration */
     595                 : #define JPEG2000_MARKER_COM 0x64 /* Comment */
     596                 : /* }}} */
     597                 : 
     598                 : /* {{{ php_handle_jpc
     599                 :    Main loop to parse JPEG2000 raw codestream structure */
     600                 : static struct gfxinfo *php_handle_jpc(php_stream * stream TSRMLS_DC)
     601               0 : {
     602               0 :         struct gfxinfo *result = NULL;
     603                 :         unsigned short dummy_short;
     604                 :         int highest_bit_depth, bit_depth;
     605                 :         unsigned char first_marker_id;
     606                 :         unsigned int i;
     607                 : 
     608                 :         /* JPEG 2000 components can be vastly different from one another.
     609                 :            Each component can be sampled at a different resolution, use
     610                 :            a different colour space, have a seperate colour depth, and
     611                 :            be compressed totally differently! This makes giving a single
     612                 :            "bit depth" answer somewhat problematic. For this implementation
     613                 :            we'll use the highest depth encountered. */
     614                 : 
     615                 :         /* Get the single byte that remains after the file type indentification */
     616               0 :         first_marker_id = php_stream_getc(stream);
     617                 : 
     618                 :         /* Ensure that this marker is SIZ (as is mandated by the standard) */
     619               0 :         if (first_marker_id != JPEG2000_MARKER_SIZ) {
     620               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "JPEG2000 codestream corrupt(Expected SIZ marker not found after SOC)");
     621               0 :                 return NULL;
     622                 :         }
     623                 : 
     624               0 :         result = (struct gfxinfo *)ecalloc(1, sizeof(struct gfxinfo));
     625                 : 
     626               0 :         dummy_short = php_read2(stream TSRMLS_CC); /* Lsiz */
     627               0 :         dummy_short = php_read2(stream TSRMLS_CC); /* Rsiz */
     628               0 :         result->width = php_read4(stream TSRMLS_CC); /* Xsiz */
     629               0 :         result->height = php_read4(stream TSRMLS_CC); /* Ysiz */
     630                 : 
     631                 : #if MBO_0
     632                 :         php_read4(stream TSRMLS_CC); /* XOsiz */
     633                 :         php_read4(stream TSRMLS_CC); /* YOsiz */
     634                 :         php_read4(stream TSRMLS_CC); /* XTsiz */
     635                 :         php_read4(stream TSRMLS_CC); /* YTsiz */
     636                 :         php_read4(stream TSRMLS_CC); /* XTOsiz */
     637                 :         php_read4(stream TSRMLS_CC); /* YTOsiz */
     638                 : #else
     639               0 :         if (php_stream_seek(stream, 24, SEEK_CUR)) {
     640               0 :                 efree(result);
     641               0 :                 return NULL;
     642                 :         }
     643                 : #endif
     644                 : 
     645               0 :         result->channels = php_read2(stream TSRMLS_CC); /* Csiz */
     646               0 :         if (result->channels < 0 || result->channels > 256) {
     647               0 :                 efree(result);
     648               0 :                 return NULL;
     649                 :         }
     650                 : 
     651                 :         /* Collect bit depth info */
     652               0 :         highest_bit_depth = bit_depth = 0;
     653               0 :         for (i = 0; i < result->channels; i++) {
     654               0 :                 bit_depth = php_stream_getc(stream); /* Ssiz[i] */
     655               0 :                 bit_depth++;
     656               0 :                 if (bit_depth > highest_bit_depth) {
     657               0 :                         highest_bit_depth = bit_depth;
     658                 :                 }
     659                 : 
     660               0 :                 php_stream_getc(stream); /* XRsiz[i] */
     661               0 :                 php_stream_getc(stream); /* YRsiz[i] */
     662                 :         }
     663                 : 
     664               0 :         result->bits = highest_bit_depth;
     665                 : 
     666               0 :         return result;
     667                 : }
     668                 : /* }}} */
     669                 : 
     670                 : /* {{{ php_handle_jp2
     671                 :    main loop to parse JPEG 2000 JP2 wrapper format structure */
     672                 : static struct gfxinfo *php_handle_jp2(php_stream *stream TSRMLS_DC)
     673               0 : {
     674               0 :         struct gfxinfo *result = NULL;
     675                 :         unsigned int box_length;
     676                 :         unsigned int box_type;
     677               0 :         char jp2c_box_id[] = {(char)0x6a, (char)0x70, (char)0x32, (char)0x63};
     678                 : 
     679                 :         /* JP2 is a wrapper format for JPEG 2000. Data is contained within "boxes".
     680                 :            Boxes themselves can be contained within "super-boxes". Super-Boxes can
     681                 :            contain super-boxes which provides us with a hierarchical storage system.
     682                 : 
     683                 :            It is valid for a JP2 file to contain multiple individual codestreams.
     684                 :            We'll just look for the first codestream at the root of the box structure
     685                 :            and handle that.
     686                 :         */
     687                 : 
     688                 :         for (;;)
     689                 :         {
     690               0 :                 box_length = php_read4(stream TSRMLS_CC); /* LBox */
     691                 :                 /* TBox */
     692               0 :                 if (php_stream_read(stream, (void *)&box_type, sizeof(box_type)) != sizeof(box_type)) {
     693                 :                         /* Use this as a general "out of stream" error */
     694               0 :                         break;
     695                 :                 }
     696                 : 
     697               0 :                 if (box_length == 1) {
     698                 :                         /* We won't handle XLBoxes */
     699               0 :                         return NULL;
     700                 :                 }
     701                 : 
     702               0 :                 if (!memcmp(&box_type, jp2c_box_id, 4))
     703                 :                 {
     704                 :                         /* Skip the first 3 bytes to emulate the file type examination */
     705               0 :                         php_stream_seek(stream, 3, SEEK_CUR);
     706                 : 
     707               0 :                         result = php_handle_jpc(stream TSRMLS_CC);
     708               0 :                         break;
     709                 :                 }
     710                 : 
     711                 :                 /* Stop if this was the last box */
     712               0 :                 if ((int)box_length <= 0) {
     713               0 :                         break;
     714                 :                 }
     715                 : 
     716                 :                 /* Skip over LBox (Which includes both TBox and LBox itself */
     717               0 :                 if (php_stream_seek(stream, box_length - 8, SEEK_CUR)) {
     718               0 :                         break;
     719                 :                 }
     720               0 :         }
     721                 : 
     722               0 :         if (result == NULL) {
     723               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "JP2 file has no codestreams at root level");
     724                 :         }
     725                 : 
     726               0 :         return result;
     727                 : }
     728                 : /* }}} */
     729                 : 
     730                 : /* {{{ tiff constants
     731                 :  */
     732                 : PHPAPI const int php_tiff_bytes_per_format[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
     733                 : 
     734                 : /* uncompressed only */
     735                 : #define TAG_IMAGEWIDTH              0x0100
     736                 : #define TAG_IMAGEHEIGHT             0x0101
     737                 : /* compressed images only */
     738                 : #define TAG_COMP_IMAGEWIDTH         0xA002
     739                 : #define TAG_COMP_IMAGEHEIGHT        0xA003
     740                 : 
     741                 : #define TAG_FMT_BYTE       1
     742                 : #define TAG_FMT_STRING     2
     743                 : #define TAG_FMT_USHORT     3
     744                 : #define TAG_FMT_ULONG      4
     745                 : #define TAG_FMT_URATIONAL  5
     746                 : #define TAG_FMT_SBYTE      6
     747                 : #define TAG_FMT_UNDEFINED  7
     748                 : #define TAG_FMT_SSHORT     8
     749                 : #define TAG_FMT_SLONG      9
     750                 : #define TAG_FMT_SRATIONAL 10
     751                 : #define TAG_FMT_SINGLE    11
     752                 : #define TAG_FMT_DOUBLE    12
     753                 : /* }}} */
     754                 : 
     755                 : /* {{{ php_ifd_get16u
     756                 :  * Convert a 16 bit unsigned value from file's native byte order */
     757                 : static int php_ifd_get16u(void *Short, int motorola_intel)
     758               0 : {
     759               0 :         if (motorola_intel) {
     760               0 :                 return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];
     761                 :         } else {
     762               0 :                 return (((unsigned char *)Short)[1] << 8) | ((unsigned char *)Short)[0];
     763                 :         }
     764                 : }
     765                 : /* }}} */
     766                 : 
     767                 : /* {{{ php_ifd_get16s
     768                 :  * Convert a 16 bit signed value from file's native byte order */
     769                 : static signed short php_ifd_get16s(void *Short, int motorola_intel)
     770               0 : {
     771               0 :         return (signed short)php_ifd_get16u(Short, motorola_intel);
     772                 : }
     773                 : /* }}} */
     774                 : 
     775                 : /* {{{ php_ifd_get32s
     776                 :  * Convert a 32 bit signed value from file's native byte order */
     777                 : static int php_ifd_get32s(void *Long, int motorola_intel)
     778               0 : {
     779               0 :         if (motorola_intel) {
     780               0 :                 return  ((( char *)Long)[0] << 24) | (((unsigned char *)Long)[1] << 16)
     781                 :                       | (((unsigned char *)Long)[2] << 8 ) | (((unsigned char *)Long)[3] << 0 );
     782                 :         } else {
     783               0 :                 return  ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16)
     784                 :                       | (((unsigned char *)Long)[1] << 8 ) | (((unsigned char *)Long)[0] << 0 );
     785                 :         }
     786                 : }
     787                 : /* }}} */
     788                 : 
     789                 : /* {{{ php_ifd_get32u
     790                 :  * Convert a 32 bit unsigned value from file's native byte order */
     791                 : static unsigned php_ifd_get32u(void *Long, int motorola_intel)
     792               0 : {
     793               0 :         return (unsigned)php_ifd_get32s(Long, motorola_intel) & 0xffffffff;
     794                 : }
     795                 : /* }}} */
     796                 : 
     797                 : /* {{{ php_handle_tiff
     798                 :    main loop to parse TIFF structure */
     799                 : static struct gfxinfo *php_handle_tiff (php_stream * stream, zval *info, int motorola_intel TSRMLS_DC)
     800               0 : {
     801               0 :         struct gfxinfo *result = NULL;
     802                 :         int i, num_entries;
     803                 :         unsigned char *dir_entry;
     804               0 :         size_t ifd_size, dir_size, entry_value, width=0, height=0, ifd_addr;
     805                 :         int entry_tag , entry_type;
     806                 :         char *ifd_data, ifd_ptr[4];
     807                 : 
     808               0 :         if (php_stream_read(stream, ifd_ptr, 4) != 4)
     809               0 :                 return NULL;
     810               0 :         ifd_addr = php_ifd_get32u(ifd_ptr, motorola_intel);
     811               0 :         if (php_stream_seek(stream, ifd_addr-8, SEEK_CUR))
     812               0 :                 return NULL;
     813               0 :         ifd_size = 2;
     814               0 :         ifd_data = emalloc(ifd_size);
     815               0 :         if (php_stream_read(stream, ifd_data, 2) != 2) {
     816               0 :                 efree(ifd_data);
     817               0 :                 return NULL;
     818                 :         }
     819               0 :         num_entries = php_ifd_get16u(ifd_data, motorola_intel);
     820               0 :         dir_size = 2/*num dir entries*/ +12/*length of entry*/*num_entries +4/* offset to next ifd (points to thumbnail or NULL)*/;
     821               0 :         ifd_size = dir_size;
     822               0 :         ifd_data = erealloc(ifd_data,ifd_size);
     823               0 :         if (php_stream_read(stream, ifd_data+2, dir_size-2) != dir_size-2) {
     824               0 :                 efree(ifd_data);
     825               0 :                 return NULL;
     826                 :         }
     827                 :         /* now we have the directory we can look how long it should be */
     828               0 :         ifd_size = dir_size;
     829               0 :         for(i=0;i<num_entries;i++) {
     830               0 :                 dir_entry        = ifd_data+2+i*12;
     831               0 :                 entry_tag    = php_ifd_get16u(dir_entry+0, motorola_intel);
     832               0 :                 entry_type   = php_ifd_get16u(dir_entry+2, motorola_intel);
     833               0 :                 switch(entry_type) {
     834                 :                         case TAG_FMT_BYTE:
     835                 :                         case TAG_FMT_SBYTE:
     836               0 :                                 entry_value  = (size_t)(dir_entry[8]);
     837               0 :                                 break;
     838                 :                         case TAG_FMT_USHORT:
     839               0 :                                 entry_value  = php_ifd_get16u(dir_entry+8, motorola_intel);
     840               0 :                                 break;
     841                 :                         case TAG_FMT_SSHORT:
     842               0 :                                 entry_value  = php_ifd_get16s(dir_entry+8, motorola_intel);
     843               0 :                                 break;
     844                 :                         case TAG_FMT_ULONG:
     845               0 :                                 entry_value  = php_ifd_get32u(dir_entry+8, motorola_intel);
     846               0 :                                 break;
     847                 :                         case TAG_FMT_SLONG:
     848               0 :                                 entry_value  = php_ifd_get32s(dir_entry+8, motorola_intel);
     849               0 :                                 break;
     850                 :                         default:
     851               0 :                                 continue;
     852                 :                 }
     853               0 :                 switch(entry_tag) {
     854                 :                         case TAG_IMAGEWIDTH:
     855                 :                         case TAG_COMP_IMAGEWIDTH:
     856               0 :                                 width  = entry_value;
     857               0 :                                 break;
     858                 :                         case TAG_IMAGEHEIGHT:
     859                 :                         case TAG_COMP_IMAGEHEIGHT:
     860               0 :                                 height = entry_value;
     861                 :                                 break;
     862                 :                 }
     863                 :         }
     864               0 :         efree(ifd_data);
     865               0 :         if ( width && height) {
     866                 :                 /* not the same when in for-loop */
     867               0 :                 result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
     868               0 :                 result->height   = height;
     869               0 :                 result->width    = width;
     870               0 :                 result->bits     = 0;
     871               0 :                 result->channels = 0;
     872               0 :                 return result;
     873                 :         }
     874               0 :         return NULL;
     875                 : }
     876                 : /* }}} */
     877                 : 
     878                 : /* {{{ php_handle_psd
     879                 :  */
     880                 : static struct gfxinfo *php_handle_iff(php_stream * stream TSRMLS_DC)
     881               0 : {
     882                 :         struct gfxinfo * result;
     883                 :         unsigned char a[10];
     884                 :         int chunkId;
     885                 :         int size;
     886                 :         short width, height, bits;
     887                 : 
     888               0 :         if (php_stream_read(stream, a, 8) != 8) {
     889               0 :                 return NULL;
     890                 :         }
     891               0 :         if (strncmp(a+4, "ILBM", 4) && strncmp(a+4, "PBM ", 4)) {
     892               0 :                 return NULL;
     893                 :         }
     894                 : 
     895                 :         /* loop chunks to find BMHD chunk */
     896                 :         do {
     897               0 :                 if (php_stream_read(stream, a, 8) != 8) {
     898               0 :                         return NULL;
     899                 :                 }
     900               0 :                 chunkId = php_ifd_get32s(a+0, 1);
     901               0 :                 size    = php_ifd_get32s(a+4, 1);
     902               0 :                 if (size < 0) {
     903               0 :                         return NULL;
     904                 :                 }
     905               0 :                 if ((size & 1) == 1) {
     906               0 :                         size++;
     907                 :                 }
     908               0 :                 if (chunkId == 0x424d4844) { /* BMHD chunk */
     909               0 :                         if (size < 9 || php_stream_read(stream, a, 9) != 9) {
     910               0 :                                 return NULL;
     911                 :                         }
     912               0 :                         width  = php_ifd_get16s(a+0, 1);
     913               0 :                         height = php_ifd_get16s(a+2, 1);
     914               0 :                         bits   = a[8] & 0xff;
     915               0 :                         if (width > 0 && height > 0 && bits > 0 && bits < 33) {
     916               0 :                                 result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
     917               0 :                                 result->width    = width;
     918               0 :                                 result->height   = height;
     919               0 :                                 result->bits     = bits;
     920               0 :                                 result->channels = 0;
     921               0 :                                 return result;
     922                 :                         }
     923                 :                 } else {
     924               0 :                         if (php_stream_seek(stream, size, SEEK_CUR)) {
     925               0 :                                 return NULL;
     926                 :                         }
     927                 :                 }
     928               0 :         } while (1);
     929                 : }
     930                 : /* }}} */
     931                 : 
     932                 : /* {{{ php_get_wbmp
     933                 :  * int WBMP file format type
     934                 :  * byte Header Type
     935                 :  *      byte Extended Header
     936                 :  *              byte Header Data (type 00 = multibyte)
     937                 :  *              byte Header Data (type 11 = name/pairs)
     938                 :  * int Number of columns
     939                 :  * int Number of rows
     940                 :  */
     941                 : static int php_get_wbmp(php_stream *stream, struct gfxinfo **result, int check TSRMLS_DC)
     942               0 : {
     943               0 :         int i, width = 0, height = 0;
     944                 : 
     945               0 :         if (php_stream_rewind(stream)) {
     946               0 :                 return 0;
     947                 :         }
     948                 : 
     949                 :         /* get type */
     950               0 :         if (php_stream_getc(stream) != 0) {
     951               0 :                 return 0;
     952                 :         }
     953                 : 
     954                 :         /* skip header */
     955                 :         do {
     956               0 :                 i = php_stream_getc(stream);
     957               0 :                 if (i < 0) {
     958               0 :                         return 0;
     959                 :                 }
     960               0 :         } while (i & 0x80);
     961                 : 
     962                 :         /* get width */
     963                 :         do {
     964               0 :                 i = php_stream_getc(stream);
     965               0 :                 if (i < 0) {
     966               0 :                         return 0;
     967                 :                 }
     968               0 :                 width = (width << 7) | (i & 0x7f);
     969               0 :         } while (i & 0x80);
     970                 :         
     971                 :         /* get height */
     972                 :         do {
     973               0 :                 i = php_stream_getc(stream);
     974               0 :                 if (i < 0) {
     975               0 :                         return 0;
     976                 :                 }
     977               0 :                 height = (height << 7) | (i & 0x7f);
     978               0 :         } while (i & 0x80);
     979                 : 
     980                 :         /* maximum valid sizes for wbmp (although 127x127 may be a more accurate one) */
     981               0 :         if (!height || !width || height > 2048 || width > 2048) {
     982               0 :                 return 0;
     983                 :         }
     984                 :         
     985               0 :         if (!check) {
     986               0 :                 (*result)->width = width;
     987               0 :                 (*result)->height = height;
     988                 :         }
     989                 : 
     990               0 :         return IMAGE_FILETYPE_WBMP;
     991                 : }
     992                 : /* }}} */
     993                 : 
     994                 : /* {{{ php_handle_wbmp
     995                 : */
     996                 : static struct gfxinfo *php_handle_wbmp(php_stream * stream TSRMLS_DC)
     997               0 : {
     998               0 :         struct gfxinfo *result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
     999                 : 
    1000               0 :         if (!php_get_wbmp(stream, &result, 0 TSRMLS_CC)) {
    1001               0 :                 efree(result);
    1002               0 :                 return NULL;
    1003                 :         }
    1004                 : 
    1005               0 :         return result;
    1006                 : }
    1007                 : /* }}} */
    1008                 : 
    1009                 : /* {{{ php_get_xbm
    1010                 :  */
    1011                 : static int php_get_xbm(php_stream *stream, struct gfxinfo **result TSRMLS_DC)
    1012               0 : {
    1013                 :     char *fline;
    1014                 :     char *iname;
    1015                 :     char *type;
    1016                 :     int value;
    1017               0 :     unsigned int width = 0, height = 0;
    1018                 : 
    1019               0 :         if (result) {
    1020               0 :                 *result = NULL;
    1021                 :         }
    1022               0 :         if (php_stream_rewind(stream)) {
    1023               0 :                 return 0;
    1024                 :         }
    1025               0 :         while ((fline=php_stream_gets(stream, NULL, 0)) != NULL) {
    1026               0 :                 iname = estrdup(fline); /* simple way to get necessary buffer of required size */
    1027               0 :                 if (sscanf(fline, "#define %s %d", iname, &value) == 2) {
    1028               0 :                         if (!(type = strrchr(iname, '_'))) {
    1029               0 :                                 type = iname;
    1030                 :                         } else {
    1031               0 :                                 type++;
    1032                 :                         }
    1033                 :         
    1034               0 :                         if (!strcmp("width", type)) {
    1035               0 :                                 width = (unsigned int) value;
    1036               0 :                                 if (height) {
    1037               0 :                                         efree(iname);
    1038               0 :                                         break;
    1039                 :                                 }
    1040                 :                         }
    1041               0 :                         if (!strcmp("height", type)) {
    1042               0 :                                 height = (unsigned int) value;
    1043               0 :                                 if (width) {
    1044               0 :                                         efree(iname);
    1045               0 :                                         break;
    1046                 :                                 }
    1047                 :                         }
    1048                 :                 }
    1049               0 :                 efree(fline);
    1050               0 :                 efree(iname);
    1051                 :         }
    1052               0 :         if (fline) {
    1053               0 :                 efree(fline);
    1054                 :         }
    1055                 : 
    1056               0 :         if (width && height) {
    1057               0 :                 if (result) {
    1058               0 :                         *result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
    1059               0 :                         (*result)->width = width;
    1060               0 :                         (*result)->height = height;
    1061                 :                 }
    1062               0 :                 return IMAGE_FILETYPE_XBM;
    1063                 :         }
    1064                 : 
    1065               0 :         return 0;
    1066                 : }
    1067                 : /* }}} */
    1068                 : 
    1069                 : /* {{{ php_handle_xbm
    1070                 :  */
    1071                 : static struct gfxinfo *php_handle_xbm(php_stream * stream TSRMLS_DC)
    1072               0 : {
    1073                 :         struct gfxinfo *result;
    1074               0 :         php_get_xbm(stream, &result TSRMLS_CC);
    1075               0 :         return result;
    1076                 : }
    1077                 : /* }}} */
    1078                 : 
    1079                 : /* {{{ php_image_type_to_mime_type
    1080                 :  * Convert internal image_type to mime type */
    1081                 : PHPAPI char * php_image_type_to_mime_type(int image_type)
    1082               0 : {
    1083               0 :         switch( image_type) {
    1084                 :                 case IMAGE_FILETYPE_GIF:
    1085               0 :                         return "image/gif";
    1086                 :                 case IMAGE_FILETYPE_JPEG:
    1087               0 :                         return "image/jpeg";
    1088                 :                 case IMAGE_FILETYPE_PNG:
    1089               0 :                         return "image/png";
    1090                 :                 case IMAGE_FILETYPE_SWF:
    1091                 :                 case IMAGE_FILETYPE_SWC:
    1092               0 :                         return "application/x-shockwave-flash";
    1093                 :                 case IMAGE_FILETYPE_PSD:
    1094               0 :                         return "image/psd";
    1095                 :                 case IMAGE_FILETYPE_BMP:
    1096               0 :                         return "image/bmp";
    1097                 :                 case IMAGE_FILETYPE_TIFF_II:
    1098                 :                 case IMAGE_FILETYPE_TIFF_MM:
    1099               0 :                         return "image/tiff";
    1100                 :                 case IMAGE_FILETYPE_IFF:
    1101               0 :                         return "image/iff";
    1102                 :                 case IMAGE_FILETYPE_WBMP:
    1103               0 :                         return "image/vnd.wap.wbmp";
    1104                 :                 case IMAGE_FILETYPE_JPC:
    1105               0 :                         return "application/octet-stream";
    1106                 :                 case IMAGE_FILETYPE_JP2:
    1107               0 :                         return "image/jp2";
    1108                 :                 case IMAGE_FILETYPE_XBM:
    1109               0 :                         return "image/xbm";
    1110                 :                 default:
    1111                 :                 case IMAGE_FILETYPE_UNKNOWN:
    1112               0 :                         return "application/octet-stream"; /* suppose binary format */
    1113                 :         }
    1114                 : }
    1115                 : /* }}} */
    1116                 : 
    1117                 : /* {{{ proto string image_type_to_mime_type(int imagetype)
    1118                 :    Get Mime-Type for image-type returned by getimagesize, exif_read_data, exif_thumbnail, exif_imagetype */
    1119                 : PHP_FUNCTION(image_type_to_mime_type)
    1120               0 : {
    1121                 :         zval **p_image_type;
    1122               0 :         int arg_c = ZEND_NUM_ARGS();
    1123                 : 
    1124               0 :         if ((arg_c!=1) || zend_get_parameters_ex(arg_c, &p_image_type) == FAILURE) {
    1125               0 :                 RETVAL_FALSE;
    1126               0 :                 WRONG_PARAM_COUNT;
    1127                 :         }
    1128               0 :         convert_to_long_ex(p_image_type);
    1129               0 :         ZVAL_STRING(return_value, (char*)php_image_type_to_mime_type(Z_LVAL_PP(p_image_type)), 1);
    1130                 : }
    1131                 : /* }}} */
    1132                 : 
    1133                 : /* {{{ proto string image_type_to_extension(int imagetype [, bool include_dot])
    1134                 :    Get file extension for image-type returned by getimagesize, exif_read_data, exif_thumbnail, exif_imagetype */
    1135                 : PHP_FUNCTION(image_type_to_extension)
    1136               0 : {
    1137                 :         long image_type;
    1138               0 :         zend_bool inc_dot=1;
    1139                 : 
    1140               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|b", &image_type, &inc_dot) == FAILURE) {
    1141               0 :                 RETURN_FALSE;
    1142                 :         }
    1143                 : 
    1144               0 :         switch (image_type) {
    1145                 :                 case IMAGE_FILETYPE_GIF:
    1146               0 :                         RETURN_STRING(".gif" + !inc_dot, 1);
    1147                 :                 case IMAGE_FILETYPE_JPEG:
    1148               0 :                         RETURN_STRING(".jpeg" + !inc_dot, 1);
    1149                 :                 case IMAGE_FILETYPE_PNG:
    1150               0 :                         RETURN_STRING(".png" + !inc_dot, 1);
    1151                 :                 case IMAGE_FILETYPE_SWF:
    1152                 :                 case IMAGE_FILETYPE_SWC:
    1153               0 :                         RETURN_STRING(".swf" + !inc_dot, 1);
    1154                 :                 case IMAGE_FILETYPE_PSD:
    1155               0 :                         RETURN_STRING(".psd" + !inc_dot, 1);
    1156                 :                 case IMAGE_FILETYPE_BMP:
    1157                 :                 case IMAGE_FILETYPE_WBMP:
    1158               0 :                         RETURN_STRING(".bmp" + !inc_dot, 1);
    1159                 :                 case IMAGE_FILETYPE_TIFF_II:
    1160                 :                 case IMAGE_FILETYPE_TIFF_MM:
    1161               0 :                         RETURN_STRING(".tiff" + !inc_dot, 1);
    1162                 :                 case IMAGE_FILETYPE_IFF:
    1163               0 :                         RETURN_STRING(".iff" + !inc_dot, 1);
    1164                 :                 case IMAGE_FILETYPE_JPC:
    1165               0 :                         RETURN_STRING(".jpc" + !inc_dot, 1);
    1166                 :                 case IMAGE_FILETYPE_JP2:
    1167               0 :                         RETURN_STRING(".jp2" + !inc_dot, 1);
    1168                 :                 case IMAGE_FILETYPE_JPX:
    1169               0 :                         RETURN_STRING(".jpx" + !inc_dot, 1);
    1170                 :                 case IMAGE_FILETYPE_JB2:
    1171               0 :                         RETURN_STRING(".jb2" + !inc_dot, 1);
    1172                 :                 case IMAGE_FILETYPE_XBM:
    1173               0 :                         RETURN_STRING(".xbm" + !inc_dot, 1);
    1174                 :         }
    1175                 : 
    1176               0 :         RETURN_FALSE;
    1177                 : }
    1178                 : /* }}} */
    1179                 : 
    1180                 : /* {{{ php_imagetype
    1181                 :    detect filetype from first bytes */
    1182                 : PHPAPI int php_getimagetype(php_stream * stream, char *filetype TSRMLS_DC)
    1183               0 : {
    1184                 :         char tmp[12];
    1185                 : 
    1186               0 :         if ( !filetype) filetype = tmp;
    1187               0 :         if((php_stream_read(stream, filetype, 3)) != 3) {
    1188               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Read error!");
    1189               0 :                 return IMAGE_FILETYPE_UNKNOWN;
    1190                 :         }
    1191                 : 
    1192                 : /* BYTES READ: 3 */
    1193               0 :         if (!memcmp(filetype, php_sig_gif, 3)) {
    1194               0 :                 return IMAGE_FILETYPE_GIF;
    1195               0 :         } else if (!memcmp(filetype, php_sig_jpg, 3)) {
    1196               0 :                 return IMAGE_FILETYPE_JPEG;
    1197               0 :         } else if (!memcmp(filetype, php_sig_png, 3)) {
    1198               0 :                 if (php_stream_read(stream, filetype+3, 5) != 5) {
    1199               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Read error!");
    1200               0 :                         return IMAGE_FILETYPE_UNKNOWN;
    1201                 :                 }
    1202               0 :                 if (!memcmp(filetype, php_sig_png, 8)) {
    1203               0 :                         return IMAGE_FILETYPE_PNG;
    1204                 :                 } else {
    1205               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "PNG file corrupted by ASCII conversion");
    1206               0 :                         return IMAGE_FILETYPE_UNKNOWN;
    1207                 :                 }
    1208               0 :         } else if (!memcmp(filetype, php_sig_swf, 3)) {
    1209               0 :                 return IMAGE_FILETYPE_SWF;
    1210               0 :         } else if (!memcmp(filetype, php_sig_swc, 3)) {
    1211               0 :                 return IMAGE_FILETYPE_SWC;
    1212               0 :         } else if (!memcmp(filetype, php_sig_psd, 3)) {
    1213               0 :                 return IMAGE_FILETYPE_PSD;
    1214               0 :         } else if (!memcmp(filetype, php_sig_bmp, 2)) {
    1215               0 :                 return IMAGE_FILETYPE_BMP;
    1216               0 :         } else if (!memcmp(filetype, php_sig_jpc, 3)) {
    1217               0 :                 return IMAGE_FILETYPE_JPC;
    1218                 :         }
    1219                 : 
    1220               0 :         if (php_stream_read(stream, filetype+3, 1) != 1) {
    1221               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Read error!");
    1222               0 :                 return IMAGE_FILETYPE_UNKNOWN;
    1223                 :         }
    1224                 : /* BYTES READ: 4 */
    1225               0 :         if (!memcmp(filetype, php_sig_tif_ii, 4)) {
    1226               0 :                 return IMAGE_FILETYPE_TIFF_II;
    1227                 :         } else
    1228               0 :         if (!memcmp(filetype, php_sig_tif_mm, 4)) {
    1229               0 :                 return IMAGE_FILETYPE_TIFF_MM;
    1230                 :         }
    1231               0 :         if (!memcmp(filetype, php_sig_iff, 4)) {
    1232               0 :                 return IMAGE_FILETYPE_IFF;
    1233                 :         }
    1234                 : 
    1235               0 :         if (php_stream_read(stream, filetype+4, 8) != 8) {
    1236               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Read error!");
    1237               0 :                 return IMAGE_FILETYPE_UNKNOWN;
    1238                 :         }
    1239                 : /* BYTES READ: 12 */
    1240               0 :         if (!memcmp(filetype, php_sig_jp2, 12)) {
    1241               0 :                 return IMAGE_FILETYPE_JP2;
    1242                 :         }
    1243                 : 
    1244                 : /* AFTER ALL ABOVE FAILED */
    1245               0 :         if (php_get_wbmp(stream, NULL, 1 TSRMLS_CC)) {
    1246               0 :                 return IMAGE_FILETYPE_WBMP;
    1247                 :         }
    1248               0 :         if (php_get_xbm(stream, NULL TSRMLS_CC)) {
    1249               0 :                 return IMAGE_FILETYPE_XBM;
    1250                 :         }
    1251               0 :         return IMAGE_FILETYPE_UNKNOWN;
    1252                 : }
    1253                 : /* }}} */
    1254                 : 
    1255                 : /* {{{ proto array getimagesize(string imagefile [, array info])
    1256                 :    Get the size of an image as 4-element array */
    1257                 : PHP_FUNCTION(getimagesize)
    1258               0 : {
    1259               0 :         zval **arg1, **info = NULL;
    1260               0 :         int itype = 0;
    1261                 :         char *temp;
    1262               0 :         struct gfxinfo *result = NULL;
    1263               0 :         php_stream * stream = NULL;
    1264                 : 
    1265               0 :         switch(ZEND_NUM_ARGS()) {
    1266                 : 
    1267                 :         case 1:
    1268               0 :                 if (zend_get_parameters_ex(1, &arg1) == FAILURE) {
    1269               0 :                         RETVAL_FALSE;
    1270               0 :                         WRONG_PARAM_COUNT;
    1271                 :                 }
    1272               0 :                 convert_to_string_ex(arg1);
    1273               0 :                 break;
    1274                 : 
    1275                 :         case 2:
    1276               0 :                 if (zend_get_parameters_ex(2, &arg1, &info) == FAILURE) {
    1277               0 :                         RETVAL_FALSE;
    1278               0 :                         WRONG_PARAM_COUNT;
    1279                 :                 }
    1280               0 :                 zval_dtor(*info);
    1281                 : 
    1282               0 :                 array_init(*info);
    1283                 : 
    1284               0 :                 convert_to_string_ex(arg1);
    1285               0 :                 break;
    1286                 : 
    1287                 :         default:
    1288               0 :                 RETVAL_FALSE;
    1289               0 :                 WRONG_PARAM_COUNT;
    1290                 :         }
    1291                 : 
    1292               0 :         stream = php_stream_open_wrapper(Z_STRVAL_PP(arg1), "rb", STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL);
    1293                 : 
    1294               0 :         if (!stream) {
    1295               0 :                 RETURN_FALSE;
    1296                 :         }
    1297                 : 
    1298               0 :         itype = php_getimagetype(stream, NULL TSRMLS_CC);
    1299               0 :         switch( itype) {
    1300                 :                 case IMAGE_FILETYPE_GIF:
    1301               0 :                         result = php_handle_gif (stream TSRMLS_CC);
    1302               0 :                         break;
    1303                 :                 case IMAGE_FILETYPE_JPEG:
    1304               0 :                         if (info) {
    1305               0 :                                 result = php_handle_jpeg(stream, *info TSRMLS_CC);
    1306                 :                         } else {
    1307               0 :                                 result = php_handle_jpeg(stream, NULL TSRMLS_CC);
    1308                 :                         }
    1309               0 :                         break;
    1310                 :                 case IMAGE_FILETYPE_PNG:
    1311               0 :                         result = php_handle_png(stream TSRMLS_CC);
    1312               0 :                         break;
    1313                 :                 case IMAGE_FILETYPE_SWF:
    1314               0 :                         result = php_handle_swf(stream TSRMLS_CC);
    1315               0 :                         break;
    1316                 :                 case IMAGE_FILETYPE_SWC:
    1317                 : #if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
    1318                 :                         result = php_handle_swc(stream TSRMLS_CC);
    1319                 : #else
    1320               0 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "The image is a compressed SWF file, but you do not have a static version of the zlib extension enabled.");
    1321                 : 
    1322                 : #endif
    1323               0 :                         break;
    1324                 :                 case IMAGE_FILETYPE_PSD:
    1325               0 :                         result = php_handle_psd(stream TSRMLS_CC);
    1326               0 :                         break;
    1327                 :                 case IMAGE_FILETYPE_BMP:
    1328               0 :                         result = php_handle_bmp(stream TSRMLS_CC);
    1329               0 :                         break;
    1330                 :                 case IMAGE_FILETYPE_TIFF_II:
    1331               0 :                         result = php_handle_tiff(stream, NULL, 0 TSRMLS_CC);
    1332               0 :                         break;
    1333                 :                 case IMAGE_FILETYPE_TIFF_MM:
    1334               0 :                         result = php_handle_tiff(stream, NULL, 1 TSRMLS_CC);
    1335               0 :                         break;
    1336                 :                 case IMAGE_FILETYPE_JPC:
    1337               0 :                         result = php_handle_jpc(stream TSRMLS_CC);
    1338               0 :                         break;
    1339                 :                 case IMAGE_FILETYPE_JP2:
    1340               0 :                         result = php_handle_jp2(stream TSRMLS_CC);
    1341               0 :                         break;
    1342                 :                 case IMAGE_FILETYPE_IFF:
    1343               0 :                         result = php_handle_iff(stream TSRMLS_CC);
    1344               0 :                         break;
    1345                 :                 case IMAGE_FILETYPE_WBMP:
    1346               0 :                         result = php_handle_wbmp(stream TSRMLS_CC);
    1347               0 :                         break;
    1348                 :                 case IMAGE_FILETYPE_XBM:
    1349               0 :                         result = php_handle_xbm(stream TSRMLS_CC);
    1350                 :                         break;
    1351                 :                 default:
    1352                 :                 case IMAGE_FILETYPE_UNKNOWN:
    1353                 :                         break;
    1354                 :         }
    1355                 : 
    1356               0 :         php_stream_close(stream);
    1357                 : 
    1358               0 :         if (result) {
    1359               0 :                 array_init(return_value);
    1360               0 :                 add_index_long(return_value, 0, result->width);
    1361               0 :                 add_index_long(return_value, 1, result->height);
    1362               0 :                 add_index_long(return_value, 2, itype);
    1363               0 :                 spprintf(&temp, 0, "width=\"%d\" height=\"%d\"", result->width, result->height);
    1364               0 :                 add_index_string(return_value, 3, temp, 0);
    1365                 : 
    1366               0 :                 if (result->bits != 0) {
    1367               0 :                         add_assoc_long(return_value, "bits", result->bits);
    1368                 :                 }
    1369               0 :                 if (result->channels != 0) {
    1370               0 :                         add_assoc_long(return_value, "channels", result->channels);
    1371                 :                 }
    1372               0 :                 add_assoc_string(return_value, "mime", (char*)php_image_type_to_mime_type(itype), 1);
    1373               0 :                 efree(result);
    1374                 :         } else {
    1375               0 :                 RETURN_FALSE;
    1376                 :         }
    1377                 : }
    1378                 : /* }}} */
    1379                 : 
    1380                 : /*
    1381                 :  * Local variables:
    1382                 :  * tab-width: 4
    1383                 :  * c-basic-offset: 4
    1384                 :  * End:
    1385                 :  * vim600: sw=4 ts=4 fdm=marker
    1386                 :  * vim<600: sw=4 ts=4
    1387                 :  */

Generated by: LTP GCOV extension version 1.5