PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/standard - image.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 480 585 82.1 %
Date: 2014-04-08 Functions: 31 32 96.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 08 Apr 2014 11:59:45 +0000 (8 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.