26
26
#include <unistd.h>
27
27
#endif
28
28
#include "php_image.h"
29
+ #include "../gd/php_gd.h"
29
30
30
31
#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB )
31
32
#include "zlib.h"
@@ -1149,9 +1150,9 @@ static struct gfxinfo *php_handle_webp(php_stream * stream)
1149
1150
}
1150
1151
/* }}} */
1151
1152
1152
- /* {{{ php_handle_avif */
1153
- / * There's no simple way to get this information - so, for now, this is unsupported.
1154
- Simply return 0 for everything.
1153
+ /* {{{ php_handle_avif
1154
+ * There's no simple way to get this information - so, for now, this is unsupported.
1155
+ * Simply return 0 for everything.
1155
1156
*/
1156
1157
static struct gfxinfo * php_handle_avif (php_stream * stream ) {
1157
1158
struct gfxinfo * result ;
@@ -1178,64 +1179,82 @@ static uint32_t php_ntohl(val) {
1178
1179
}
1179
1180
/* }}} */
1180
1181
1182
+ /* {{{ php_image_read_bytes
1183
+ * A generalized function that reads bytes from an image_reader struct.
1184
+ * It can read either from a php_stream or a zend_string.
1185
+ */
1186
+ static size_t php_image_read_bytes (php_gd_image_reader * reader , char * buf , size_t count ) {
1187
+ if (reader -> stream ) {
1188
+ return php_stream_read (reader -> stream , buf , count );
1189
+ }
1190
+
1191
+ if (reader -> data ) {
1192
+ if (ZSTR_LEN (reader -> data ) < reader -> data_pos + count ) {
1193
+ return 0 ;
1194
+ }
1195
+
1196
+ memcpy (buf , ZSTR_VAL (reader -> data ) + reader -> data_pos , count );
1197
+ reader -> data_pos += count ;
1198
+ return count ;
1199
+ }
1200
+
1201
+ return 0 ;
1202
+ }
1203
+ /* }}} */
1204
+
1181
1205
/* {{{ php_is_image_avif
1182
- detect whether an image is of type AVIF
1183
-
1184
- An AVIF image will start off a header "box".
1185
- This starts with with a four-byte integer containing the number of bytes in the filetype box.
1186
- This must be followed by the string "ftyp".
1187
- Next comes a four-byte string indicating the "major brand".
1188
- If that's "avif" or "avis", this is an AVIF image.
1189
- Next, there's a four-byte "minor version" field, which we can ignore.
1190
- Next comes an array of four-byte strings containing "compatible brands".
1191
- These extend to the end of the box.
1192
- If any of the compatible brands is "avif" or "avis", then this is an AVIF image.
1193
- Otherwise, well, it's not.
1194
-
1195
- For more, see https://mpeg.chiariglione.org/standards/mpeg-4/iso-base-media-file-format/text-isoiec-14496-12-5th-edition
1196
- */
1197
- static int php_is_image_avif (php_stream * stream ) {
1206
+ * detect whether an image is of type AVIF
1207
+ *
1208
+ * An AVIF image will start off a header "box".
1209
+ * This starts with with a four-byte integer containing the number of bytes in the filetype box.
1210
+ * This must be followed by the string "ftyp".
1211
+ * Next comes a four-byte string indicating the "major brand".
1212
+ * If that's "avif" or "avis", this is an AVIF image.
1213
+ * Next, there's a four-byte "minor version" field, which we can ignore.
1214
+ * Next comes an array of four-byte strings containing "compatible brands".
1215
+ * These extend to the end of the box.
1216
+ * If any of the compatible brands is "avif" or "avis", then this is an AVIF image.
1217
+ * Otherwise, well, it's not.
1218
+ * For more, see https://mpeg.chiariglione.org/standards/mpeg-4/iso-base-media-file-format/text-isoiec-14496-12-5th-edition
1219
+ */
1220
+ int php_is_image_avif (php_gd_image_reader * reader ) {
1198
1221
uint32_t header_size_reversed , header_size , i ;
1199
1222
char box_type [4 ], brand [4 ];
1200
1223
1201
- if (php_stream_rewind (stream )) {
1202
- return 0 ;
1203
- }
1204
-
1205
- if (php_stream_read (stream , (char * ) & header_size_reversed , 4 ) != 4 ) {
1224
+ if (php_image_read_bytes (reader , (char * ) & header_size_reversed , 4 ) != 4 ) {
1206
1225
return 0 ;
1207
1226
}
1208
1227
1209
1228
header_size = php_ntohl (header_size_reversed );
1210
1229
1211
- // If the box type isn't "ftyp", it can't be an AVIF image.
1212
- if (php_stream_read ( stream , box_type , 4 ) != 4 ) {
1230
+ /* If the box type isn't "ftyp", it can't be an AVIF image. */
1231
+ if (php_image_read_bytes ( reader , box_type , 4 ) != 4 ) {
1213
1232
return 0 ;
1214
1233
}
1215
1234
1216
1235
if (memcmp (box_type , "ftyp" , 4 )) {
1217
1236
return 0 ;
1218
1237
}
1219
1238
1220
- // If the major brand is "avif" or "avis", it's an AVIF image.
1221
- if (php_stream_read ( stream , brand , 4 ) != 4 ) {
1239
+ /* If the major brand is "avif" or "avis", it's an AVIF image. */
1240
+ if (php_image_read_bytes ( reader , brand , 4 ) != 4 ) {
1222
1241
return 0 ;
1223
1242
}
1224
1243
1225
1244
if (!memcmp (brand , "avif" , 4 ) || !memcmp (brand , "avis" , 4 )) {
1226
1245
return 1 ;
1227
1246
}
1228
1247
1229
- // Skip the next four bytes, which are the "minor version".
1230
- if (php_stream_read ( stream , brand , 4 ) != 4 ) {
1248
+ /* Skip the next four bytes, which are the "minor version". */
1249
+ if (php_image_read_bytes ( reader , brand , 4 ) != 4 ) {
1231
1250
return 0 ;
1232
1251
}
1233
1252
1234
- // Look for "avif" or "avis" in any member of compatible_brands[], to the end of the header.
1235
- // Note we've already read four groups of four bytes.
1253
+ /* Look for "avif" or "avis" in any member of compatible_brands[], to the end of the header.
1254
+ Note we've already read four groups of four bytes. */
1236
1255
1237
1256
for (i = 16 ; i < header_size ; i += 4 ) {
1238
- if (php_stream_read ( stream , brand , 4 ) != 4 ) {
1257
+ if (php_image_read_bytes ( reader , brand , 4 ) != 4 ) {
1239
1258
return 0 ;
1240
1259
}
1241
1260
@@ -1381,7 +1400,7 @@ PHP_FUNCTION(image_type_to_extension)
1381
1400
1382
1401
/* {{{ php_imagetype
1383
1402
detect filetype from first bytes */
1384
- PHPAPI int php_getimagetype (php_stream * stream , const char * input , char * filetype )
1403
+ PHPAPI int php_getimagetype (php_stream * stream , const char * input , char * filetype )
1385
1404
{
1386
1405
char tmp [12 ];
1387
1406
int twelve_bytes_read ;
@@ -1458,7 +1477,10 @@ PHPAPI int php_getimagetype(php_stream * stream, const char *input, char *filety
1458
1477
return IMAGE_FILETYPE_WBMP ;
1459
1478
}
1460
1479
1461
- if (php_is_image_avif (stream )) {
1480
+ php_gd_image_reader reader ;
1481
+ reader .stream = stream ;
1482
+
1483
+ if (!php_stream_rewind (stream ) && php_is_image_avif (& reader )) {
1462
1484
return IMAGE_FILETYPE_AVIF ;
1463
1485
}
1464
1486
0 commit comments