@@ -1290,6 +1290,18 @@ typedef struct {
12901290	mn_offset_mode_t  offset_mode ;
12911291} maker_note_type ;
12921292
1293+ #define  FOURCC (id ) (((uint32_t)(id[0])<<24) | (id[1]<<16) | (id[2]<<8) | (id[3]))
1294+ 
1295+ typedef  struct  {
1296+ 	uint64_t 	size ;
1297+ 	uint32_t 	type ;
1298+ } isobmff_box_type ;
1299+ 
1300+ typedef  struct  {
1301+ 	uint32_t 	offset ;
1302+ 	uint32_t 	size ;
1303+ } isobmff_item_pos_type ;
1304+ 
12931305/* Some maker notes (e.g. DJI info tag) require custom parsing */ 
12941306#define  REQUIRES_CUSTOM_PARSING  NULL
12951307
@@ -4279,11 +4291,128 @@ static bool exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offs
42794291	return  result ;
42804292}
42814293
4294+ static  int  exif_isobmff_parse_box (unsigned char   * buf , isobmff_box_type  * box )
4295+ {
4296+ 	box -> size  =  php_ifd_get32u (buf , 1 );
4297+ 	buf  +=  4 ;
4298+ 	box -> type  =  php_ifd_get32u (buf , 1 );
4299+ 	if  (box -> size  !=  1 ) {
4300+ 		return  8 ;
4301+ 	}
4302+ 	buf  +=  4 ;
4303+ 	box -> size  =  php_ifd_get64u (buf , 1 );
4304+ 	return  16 ;
4305+ }
4306+ 
4307+ static  void  exif_isobmff_parse_meta (unsigned char   * data , unsigned char   * end , isobmff_item_pos_type  * pos )
4308+ {
4309+ 	isobmff_box_type  box , item ;
4310+ 	unsigned char   * box_offset , * p , * p2 ;
4311+ 	int  header_size , exif_id  =  -1 , version , item_count , i ;
4312+ 
4313+ 	for  (box_offset  =  data  +  4 ; box_offset  <  end ; box_offset  +=  box .size ) {
4314+ 		header_size  =  exif_isobmff_parse_box (box_offset , & box );
4315+ 		if  (box .type  ==  FOURCC ("iinf" )) {
4316+ 			p  =  box_offset  +  header_size ;
4317+ 			version  =  p [0 ];
4318+ 			p  +=  4 ;
4319+ 			if  (version  <  2 ) {
4320+ 				item_count  =  php_ifd_get16u (p , 1 );
4321+ 				p  +=  2 ;
4322+ 			} else  {
4323+ 				item_count  =  php_ifd_get32u (p , 1 );
4324+ 				p  +=  4 ;
4325+ 			}
4326+ 			for  (i = 0 ; i  <  item_count ; i ++ ) {
4327+ 				header_size  =  exif_isobmff_parse_box (p , & item );
4328+ 				if  (!memcmp (p  +  header_size  +  8 , "Exif" , 4 )) {
4329+ 					exif_id  =  php_ifd_get16u (p  +  header_size  +  4 , 1 );
4330+ 					break ;
4331+ 				}
4332+ 				p  +=  item .size ;
4333+ 			}
4334+ 			if  (exif_id  <  0 ) {
4335+ 				break ;
4336+ 			}
4337+ 		}
4338+ 		else  if  (box .type  ==  FOURCC ("iloc" )) {
4339+ 			p  =  box_offset  +  header_size ;
4340+ 			version  =  p [0 ];
4341+ 			p  +=  6 ;
4342+ 			if  (version  <  2 ) {
4343+ 				item_count  =  php_ifd_get16u (p , 1 );
4344+ 				p  +=  2 ;
4345+ 			} else  {
4346+ 				item_count  =  php_ifd_get32u (p , 1 );
4347+ 				p  +=  4 ;
4348+ 			}
4349+ 			for  (i  =  0 , p2  =  p ; i < item_count ; i ++ , p2  +=  16 ) {
4350+ 				if  (php_ifd_get16u (p2 , 1 ) ==  exif_id ) {
4351+ 					pos -> offset  =  php_ifd_get32u (p2  +  8 , 1 );
4352+ 					pos -> size  =  php_ifd_get32u (p2  +  12 , 1 );
4353+ 					break ;
4354+ 				}
4355+ 			}
4356+ 			break ;
4357+ 		}
4358+ 	}
4359+ }
4360+ 
4361+ static  bool  exif_scan_HEIF_header (image_info_type  * ImageInfo , unsigned char   * buf )
4362+ {
4363+ 	isobmff_box_type  box ;
4364+ 	isobmff_item_pos_type  pos ;
4365+ 	unsigned char   * data ;
4366+ 	off_t  offset ;
4367+ 	uint64_t  limit ;
4368+ 	int  box_header_size , remain ;
4369+ 	bool  ret  =  false;
4370+ 
4371+ 	pos .size  =  0 ;
4372+ 	for  (offset  =  php_ifd_get32u (buf , 1 ); ImageInfo -> FileSize  >  offset  +  16 ; offset  +=  box .size ) {
4373+ 		if  ((php_stream_seek (ImageInfo -> infile , offset , SEEK_SET ) <  0 ) || 
4374+ 			(exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )buf , 16 ) !=  16 )) {
4375+ 			break ;
4376+ 		}
4377+ 		box_header_size  =  exif_isobmff_parse_box (buf , & box );
4378+ 		if  (box .type  ==  FOURCC ("meta" )) {
4379+ 			limit  =  box .size  -  box_header_size ;
4380+ 			data  =  (unsigned char   * )emalloc (limit );
4381+ 			remain  =  16  -  box_header_size ;
4382+ 			if  (remain ) {
4383+ 				memcpy (data , buf  +  box_header_size , remain );
4384+ 			}
4385+ 			if  (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(data  +  remain ), limit  -  remain ) ==  limit  -  remain ) {
4386+ 				exif_isobmff_parse_meta (data , data  +  limit , & pos );
4387+ 			}
4388+ 			if  ((pos .size ) && 
4389+ 				(ImageInfo -> FileSize  >= pos .offset  +  pos .size ) && 
4390+ 				(php_stream_seek (ImageInfo -> infile , pos .offset  +  2 , SEEK_SET ) >= 0 )) {
4391+ 				if  (limit  >= pos .size  -  2 ) {
4392+ 					limit  =  pos .size  -  2 ;
4393+ 				} else  {
4394+ 					limit  =  pos .size  -  2 ;
4395+ 					efree (data );
4396+ 					data  =  (unsigned char   * )emalloc (limit );
4397+ 				}
4398+ 				if  (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )data , limit ) ==  limit ) {
4399+ 					exif_process_APP1 (ImageInfo , (char * )data , limit , pos .offset  +  2 );
4400+ 					ret  =  true;
4401+ 				}
4402+ 			}
4403+ 			efree (data );
4404+ 			break ;
4405+ 		}
4406+ 	}
4407+ 
4408+ 	return  ret ;
4409+ }
4410+ 
42824411/* {{{ exif_scan_FILE_header 
42834412 * Parse the marker stream until SOS or EOI is seen; */ 
42844413static  bool  exif_scan_FILE_header (image_info_type  * ImageInfo )
42854414{
4286- 	unsigned char   file_header [8 ];
4415+ 	unsigned char   file_header [16 ];
42874416
42884417	ImageInfo -> FileType  =  IMAGE_FILETYPE_UNKNOWN ;
42894418
@@ -4344,6 +4473,17 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo)
43444473				exif_error_docref (NULL  EXIFERR_CC , ImageInfo , E_WARNING , "Invalid  TIFF  file ");
43454474				return  false;
43464475			}
4476+ 		} else  if  ((ImageInfo -> FileSize  >  12 ) && 
4477+ 			   (!memcmp (file_header  +  4 , "ftyp" , 4 )) && 
4478+ 			   (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(file_header  +  8 ), 4 ) ==  4 ) && 
4479+ 			   ((!memcmp (file_header  +  8 , "heic" , 4 )) ||  (!memcmp (file_header  +  8 , "heix" , 4 )) ||  (!memcmp (file_header  +  8 , "mif1" , 4 )))) {
4480+ 			if  (exif_scan_HEIF_header (ImageInfo , file_header )) {
4481+ 				ImageInfo -> FileType  =  IMAGE_FILETYPE_HEIF ;
4482+ 				return  true;
4483+ 			} else  {
4484+ 				exif_error_docref (NULL  EXIFERR_CC , ImageInfo , E_WARNING , "Invalid  HEIF  file ");
4485+ 				return  false;
4486+ 			}
43474487		} else  {
43484488			exif_error_docref (NULL  EXIFERR_CC , ImageInfo , E_WARNING , "File  not  supported ");
43494489			return  false;
0 commit comments