From 9363bfad7ef1ea88d98bf05e7a8663c125865863 Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Fri, 8 Mar 2002 01:09:54 +0000 Subject: [PATCH] -Support for IFD Arrays #necessary for update/write operations --- ext/exif/exif.c | 605 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 416 insertions(+), 189 deletions(-) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 25b8a14dc8..6e1226d96c 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -98,10 +98,12 @@ PHP_MINFO_FUNCTION(exif); /* {{{ exif_module_entry */ zend_module_entry exif_module_entry = { - STANDARD_MODULE_HEADER, +#if ZEND_MODULE_API_NO >= 20010901 + STANDARD_MODULE_HEADER, +#endif "exif", exif_functions, - NULL, NULL, + NULL, NULL, NULL, NULL, PHP_MINFO(exif), EXIF_VERSION, @@ -447,22 +449,36 @@ static const struct { /* {{{ exif_get_tagname Get headername for tag_num or NULL if not defined */ -static char * exif_get_tagname(int tag_num, char *ret) +static char * exif_get_tagname(int tag_num, char *ret, int len) { int i,t; + char tmp[32]; for (i=0;;i++) { if ( (t=TagTable[i].Tag) == tag_num || !t) { - if (ret) { - strcpy(ret,TagTable[i].Desc); - if ( !t) sprintf(ret,"UndefinedTag:0x%04X", tag_num); + if (ret && len) { + if ( !t) break; + strncpy(ret,TagTable[i].Desc,abs(len)); + if ( len<0) { + len = -len; + ret[len-1]='\0'; + for(i=strlen(ret);iinfo_list[section_index].list,(image_info->info_list[section_index].count+1)*sizeof(image_info_value)); + list = erealloc(image_info->info_list[section_index].list,(image_info->info_list[section_index].count+1)*sizeof(image_info_data)); if ( !list) { - php_error(E_WARNING,"Cannot allocate memory for all data"); + php_error(E_ERROR,"Cannot allocate memory for all data"); return; } image_info->info_list[section_index].list = list; - image_info->sections_found |= 1<info_list[section_index].list[image_info->info_list[section_index].count]; - info_value->name = emalloc(strlen(name)+1); - strcpy(info_value->name, name); + info_data = &image_info->info_list[section_index].list[image_info->info_list[section_index].count]; + info_data->tag = tag; + info_data->format = format; + info_data->length = length; + info_data->name = emalloc(strlen(name)+1); + if ( !info_data->name) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return; + } + info_value = &info_data->value; + strcpy(info_data->name, name); - info_value->tag = tag; - info_value->format = format; - info_value->length = 1; /* we do not support arrays other than STRING/UNDEFINED */ switch (format) { - case TAG_FMT_BYTE: - info_value->value.u = *(uchar*)value; - break; - case TAG_FMT_STRING: length = php_strnlen(value,length); - info_value->value.s = emalloc(length+1); - strcpy(info_value->value.s,value); - info_value->length = length; - break; - - case TAG_FMT_USHORT: - info_value->value.u = php_ifd_get16u(value,image_info->motorola_intel); - break; - - case TAG_FMT_ULONG: - info_value->value.u = php_ifd_get32u(value,image_info->motorola_intel); - break; - - case TAG_FMT_URATIONAL: - info_value->value.ur.num = php_ifd_get32u(value, image_info->motorola_intel); - info_value->value.ur.den = php_ifd_get32u(4+(char *)value, image_info->motorola_intel); - break; - - case TAG_FMT_SBYTE: - info_value->value.i = *(char*)value; + info_data->length = length; + info_value->s = emalloc(length+1); + if ( !info_value->s) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return; + } + strcpy(info_value->s,value); break; default: @@ -792,45 +805,143 @@ void exif_add_image_info( image_info_type *image_info, int section_index, char * * So not return but use type UNDEFINED * return; */ - info_value->tag = TAG_FMT_UNDEFINED;/* otherwise not freed from memory */ + info_data->tag = TAG_FMT_UNDEFINED;/* otherwise not freed from memory */ + case TAG_FMT_SBYTE: + case TAG_FMT_BYTE: + /* in contrast to strings bytes do not need to allocate buffer for NULL if length==0 */ + if ( length<1) + break; + if ( format==TAG_FMT_BYTE && length==1) + { + info_value->u = *(uchar*)value; + break; + } + if ( format==TAG_FMT_SBYTE && length==1) + { + info_value->i = *(char*)value; + break; + } case TAG_FMT_UNDEFINED: - info_value->value.s = emalloc(length+1); - memcpy(info_value->value.s,value,length); - info_value->value.s[length] = '\0'; - info_value->length = length; /* not +1 !!! */ + info_value->s = emalloc(length+1); + if ( !info_value->s) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return; + } + memcpy(info_value->s,value,length); + info_value->s[length] = '\0'; break; + case TAG_FMT_USHORT: + case TAG_FMT_ULONG: + case TAG_FMT_URATIONAL: case TAG_FMT_SSHORT: - info_value->value.i = php_ifd_get16s(value,image_info->motorola_intel); - break; - case TAG_FMT_SLONG: - info_value->value.i = php_ifd_get32s(value,image_info->motorola_intel); - break; - case TAG_FMT_SRATIONAL: - info_value->value.sr.num = php_ifd_get32u(value, image_info->motorola_intel); - info_value->value.sr.den = php_ifd_get32u(4+(char *)value, image_info->motorola_intel); - break; - case TAG_FMT_SINGLE: - php_error(E_WARNING, "Found value of type single"); - info_value->value.f = (double)*(float *)value; - case TAG_FMT_DOUBLE: - php_error(E_WARNING, "Found value of type double"); - info_value->value.d = *(double *)value; - break; + if ( length==0) { + break; + } else + if ( length>1) { + info_data->value.list = emalloc(length*sizeof(image_info_value)); + if ( !info_data->value.list) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return; + } + info_value = &info_data->value.list[0]; + } else { + info_value = &info_data->value; + } + for (index=0; indexu = php_ifd_get16u(value,motorola_intel); + break; + + case TAG_FMT_ULONG: + info_value->u = php_ifd_get32u(value,motorola_intel); + break; + + case TAG_FMT_URATIONAL: + info_value->ur.num = php_ifd_get32u(value, motorola_intel); + info_value->ur.den = php_ifd_get32u(4+(char *)value, motorola_intel); + break; + + case TAG_FMT_SSHORT: + info_value->i = php_ifd_get16s(value,motorola_intel); + break; + + case TAG_FMT_SLONG: + info_value->i = php_ifd_get32s(value,motorola_intel); + break; + + case TAG_FMT_SRATIONAL: + info_value->sr.num = php_ifd_get32u(value, motorola_intel); + info_value->sr.den = php_ifd_get32u(4+(char *)value, motorola_intel); + break; + + case TAG_FMT_SINGLE: + php_error(E_WARNING, "Found value of type single"); + info_value->f = (double)*(float *)value; + + case TAG_FMT_DOUBLE: + php_error(E_WARNING, "Found value of type double"); + info_value->d = *(double *)value; + break; + } + info_value = &info_data->value.list[index]; + } + } + image_info->sections_found |= 1<info_list[section_index].count++; +} +/* }}} */ + +/* {{{ exif_iif_add_tag + Add a tag from IFD to image_info +*/ +void exif_iif_add_tag( image_info_type *image_info, int section_index, char *name, int tag, int format, int length, void* value) +{ + exif_iif_add_value( image_info, section_index, name, tag, format, length, value, image_info->motorola_intel); +} +/* }}} */ + +/* {{{ exif_iif_add_int + Add a tag from IFD to image_info +*/ +void exif_iif_add_int( image_info_type *image_info, int section_index, char *name, int value) +{ + int index; + image_info_data *info_data; + image_info_data *list; + + list = erealloc(image_info->info_list[section_index].list,(image_info->info_list[section_index].count+1)*sizeof(image_info_data)); + if ( !list) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return; } + image_info->info_list[section_index].list = list; + info_data = &image_info->info_list[section_index].list[image_info->info_list[section_index].count]; + info_data->tag = TAG_NONE; + info_data->format = TAG_FMT_SLONG; + info_data->length = 1; + info_data->name = emalloc(strlen(name)+1); + if ( !info_data->name) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return; + } + strcpy(info_data->name, name); + info_data->value.i = value; + image_info->sections_found |= 1<info_list[section_index].count++; } /* }}} */ -/* {{{ exif_free_image_info +/* {{{ exif_iif_free Free memory allocated for image_info */ -void exif_free_image_info( image_info_type *image_info, int section_index) +void exif_iif_free( image_info_type *image_info, int section_index) { int i; @@ -839,11 +950,29 @@ void exif_free_image_info( image_info_type *image_info, int section_index) for (i=0; i < image_info->info_list[section_index].count; i++) { efree(image_info->info_list[section_index].list[i].name); - if ( image_info->info_list[section_index].list[i].format == TAG_FMT_STRING - ||image_info->info_list[section_index].list[i].format == TAG_FMT_UNDEFINED - ) + switch(image_info->info_list[section_index].list[i].format) { - efree(image_info->info_list[section_index].list[i].value.s); + case TAG_FMT_SBYTE: + case TAG_FMT_BYTE: + /* in contrast to strings bytes do not need to allocate buffer for NULL if length==0 */ + if (image_info->info_list[section_index].list[i].length<=1) + break; + default: + case TAG_FMT_UNDEFINED: + case TAG_FMT_STRING: + efree(image_info->info_list[section_index].list[i].value.s); + break; + + case TAG_FMT_USHORT: + case TAG_FMT_ULONG: + case TAG_FMT_URATIONAL: + case TAG_FMT_SSHORT: + case TAG_FMT_SLONG: + case TAG_FMT_SRATIONAL: + case TAG_FMT_SINGLE: + case TAG_FMT_DOUBLE: + /* nothing to do here */ + break; } } efree(image_info->info_list[section_index].list); @@ -859,13 +988,13 @@ void exif_free_image_info( image_info_type *image_info, int section_index) void add_assoc_image_info( pval *value, int sub_array, image_info_type *image_info, int section_index) { char buffer[64]; - int idx=0; - image_info_value *info_value; + int i, ap, l, b, idx=0, done; + image_info_value *info_value; + image_info_data *info_data; + pval *tmpi, *array; if ( image_info->info_list[section_index].count) { - int i; - pval *tmpi; if ( sub_array) { MAKE_STD_ZVAL(tmpi); @@ -876,59 +1005,132 @@ void add_assoc_image_info( pval *value, int sub_array, image_info_type *image_in for(i=0; iinfo_list[section_index].count; i++) { - info_value = &image_info->info_list[section_index].list[i]; - #ifdef EXIF_DEBUG - php_error(E_NOTICE,"adding info #%d: '%s:%s'", i, exif_get_sectionname(section_index), info_value->name); - #endif - switch(info_value->format) + done = 0; + info_data = &image_info->info_list[section_index].list[i]; + info_value = &info_data->value; + if (info_data->length==0) { - default: - /* Standard says more types possible but skip them... - * but allow users to handle data if they know how to - * So not return but use type UNDEFINED - * return; - */ - case TAG_FMT_UNDEFINED: - add_assoc_stringl(tmpi, info_value->name, info_value->value.s, info_value->length, 1); - break; + add_assoc_null(tmpi, info_data->name); + } else { + switch (info_data->format) + { + default: + /* Standard says more types possible but skip them... + * but allow users to handle data if they know how to + * So not return but use type UNDEFINED + * return; + */ + case TAG_FMT_UNDEFINED: + add_assoc_stringl(tmpi, info_data->name, info_value->s, info_data->length, 1); + break; - case TAG_FMT_STRING: - if (section_index==SECTION_COMMENT) { - add_index_string(tmpi, idx++, info_value->value.s, 1); - } else { - add_assoc_string(tmpi, info_value->name, info_value->value.s, 1); - } - break; + case TAG_FMT_STRING: + if (section_index==SECTION_COMMENT) { + add_index_string(tmpi, idx++, info_value->s, 1); + } else { + add_assoc_string(tmpi, info_data->name, info_value->s, 1); + } + break; - case TAG_FMT_BYTE: - case TAG_FMT_USHORT: - case TAG_FMT_ULONG: - add_assoc_long(tmpi, info_value->name, (int)info_value->value.u); + case TAG_FMT_URATIONAL: + case TAG_FMT_SRATIONAL: break; + case TAG_FMT_BYTE: + case TAG_FMT_SBYTE: + case TAG_FMT_USHORT: + case TAG_FMT_SSHORT: + case TAG_FMT_SINGLE: + case TAG_FMT_DOUBLE: + case TAG_FMT_ULONG: + case TAG_FMT_SLONG: + /* now the rest, first see if it becomes an array */ + if ( (l = info_data->length) > 1) { + array = NULL; + MAKE_STD_ZVAL(array); + array_init(array); + info_value = &info_data->value.list[0]; + } + for(ap=0; apformat) + { + case TAG_FMT_BYTE: + if (l>1) { + info_value = &info_data->value; + for (b=0;bs[b])); + } + break; + } + case TAG_FMT_USHORT: + case TAG_FMT_ULONG: + if (l==1) { + add_assoc_long(tmpi, info_data->name, (int)info_value->u); + } else { + add_index_long(array, ap, (int)info_value->u); + } + break; - case TAG_FMT_URATIONAL: - sprintf(buffer,"%i/%i", info_value->value.ur.num, info_value->value.ur.den); - add_assoc_string(tmpi, info_value->name, buffer, 1); - break; + case TAG_FMT_URATIONAL: + sprintf(buffer,"%i/%i", info_value->ur.num, info_value->ur.den); + if (l==1) { + add_assoc_string(tmpi, info_data->name, buffer, 1); + } else { + add_index_string(array, ap, buffer, 1); + } + break; - case TAG_FMT_SBYTE: - case TAG_FMT_SSHORT: - case TAG_FMT_SLONG: - add_assoc_long(tmpi, info_value->name, info_value->value.i); - break; + case TAG_FMT_SBYTE: + if (l>1) { + info_value = &info_data->value; + for (b=0;bs[b]); + } + break; + } + case TAG_FMT_SSHORT: + case TAG_FMT_SLONG: + if (l==1) { + add_assoc_long(tmpi, info_data->name, info_value->i); + } else { + add_index_long(array, ap, info_value->i); + } + break; - case TAG_FMT_SRATIONAL: - sprintf(buffer,"%i/%i", info_value->value.sr.num, info_value->value.sr.den); - add_assoc_string(tmpi, info_value->name, buffer, 1); - break; + case TAG_FMT_SRATIONAL: + sprintf(buffer,"%i/%i", info_value->sr.num, info_value->sr.den); + if (l==1) { + add_assoc_string(tmpi, info_data->name, buffer, 1); + } else { + add_index_string(array, ap, buffer, 1); + } + break; - case TAG_FMT_SINGLE: - add_assoc_double(tmpi, info_value->name, info_value->value.f); - break; + case TAG_FMT_SINGLE: + if (l==1) { + add_assoc_double(tmpi, info_data->name, info_value->f); + } else { + add_index_double(array, ap, info_value->f); + } + break; - case TAG_FMT_DOUBLE: - add_assoc_double(tmpi, info_value->name, info_value->value.d); - break; + case TAG_FMT_DOUBLE: + if (l==1) { + add_assoc_double(tmpi, info_data->name, info_value->d); + } else { + add_index_double(array, ap, info_value->d); + } + break; + } + info_value = &info_data->value.list[ap]; + } + if ( l>1) { + add_assoc_zval(tmpi, info_data->name, array); + } + break; + } } } if ( sub_array) { @@ -998,7 +1200,7 @@ void add_assoc_image_info( pval *value, int sub_array, image_info_type *image_in */ static void exif_process_COM (image_info_type *image_info, uchar *value, int length) { - exif_add_image_info( image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length, value); + exif_iif_add_tag( image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length, value); } /* }}} */ @@ -1109,7 +1311,7 @@ PHP_FUNCTION(exif_tagname) convert_to_long_ex(p_num); tag = Z_LVAL_PP(p_num); - szTemp = exif_get_tagname(tag,NULL); + szTemp = exif_get_tagname(tag,NULL,0); if ( tag<0 || !szTemp || !szTemp[0]) { RETURN_BOOL(FALSE); } else { @@ -1132,7 +1334,7 @@ static void exif_extract_thumbnail(image_info_type *ImageInfo, char *offset, uns } ImageInfo->Thumbnail = emalloc(ImageInfo->ThumbnailSize); if (!ImageInfo->Thumbnail) { - php_error(E_WARNING, "Could not allocate memory for thumbnail"); + php_error(E_ERROR, "Could not allocate memory for thumbnail"); return; } else { /* Check to make sure we are not going to go past the ExifLength */ @@ -1156,6 +1358,10 @@ static int exif_process_string_raw(char **result,char *value,size_t byte_count) */ if (byte_count) { (*result) = emalloc(byte_count+1); + if ( !*result) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return 0; + } memcpy(*result, value, byte_count); (*result)[byte_count] = '\0'; return byte_count+1; @@ -1175,6 +1381,10 @@ static int exif_process_string(char **result,char *value,size_t byte_count) { */ if ((byte_count=php_strnlen(value,byte_count)) > 0) { (*result) = emalloc(byte_count+1); + if ( !*result) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return 0; + } memcpy(*result, value, byte_count); (*result)[byte_count] = '\0'; return byte_count+1; @@ -1206,6 +1416,10 @@ static int exif_process_user_comment(char **pszInfoPtr,char *szEncoding,char *sz } if (l>1) { *pszInfoPtr = emalloc(l+1); + if ( !*pszInfoPtr) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return 0; + } wcstombs(*pszInfoPtr, (wchar_t*)(szValuePtr), l+1); (*pszInfoPtr)[l] = '\0'; return l+1; @@ -1290,11 +1504,11 @@ static void exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, ch if (value_ptr < dir_entry) { /* we can read this if offset_val > 0 */ /* some files have their values in other parts of the file */ - php_error(E_WARNING, "process tag(x%04X=%s): Illegal pointer offset(x%04X < x%04X)", tag, exif_get_tagname(tag,tagname), offset_val, dir_entry); + php_error(E_WARNING, "process tag(x%04X=%s): Illegal pointer offset(x%04X < x%04X)", tag, exif_get_tagname(tag,tagname,-13), offset_val, dir_entry); } else { /* this is for sure not allowed */ /* exception are IFD pointers */ - php_error(E_WARNING, "process tag(x%04X=%s): Illegal pointer offset(x%04X + x%04X = x%04X > x%04X)", tag, exif_get_tagname(tag,tagname), offset_val, byte_count, offset_val+byte_count, IFDlength); + php_error(E_WARNING, "process tag(x%04X=%s): Illegal pointer offset(x%04X + x%04X = x%04X > x%04X)", tag, exif_get_tagname(tag,tagname,-13), offset_val, byte_count, offset_val+byte_count, IFDlength); } return; } @@ -1305,7 +1519,7 @@ static void exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, ch ImageInfo->sections_found |= FOUND_ANY_TAG; #ifdef EXIF_DEBUG - php_error(E_NOTICE,"process tag(x%04x=%s,@x%04X+x%04X(=%d)): %s", tag, exif_get_tagname(tag,tagname), value_ptr-offset_base, byte_count, byte_count, format==TAG_FMT_STRING?(value_ptr?value_ptr:""):exif_get_tagformat(format)); + php_error(E_NOTICE,"process tag(x%04X=%s,@x%04X + x%04X(=%d)): %s%s", tag, exif_get_tagname(tag,tagname,-13), offset_val, byte_count, byte_count, components&&format!=TAG_FMT_UNDEFINED&&format!=TAG_FMT_STRING?"ARRAY OF ":"", format==TAG_FMT_STRING?(value_ptr?value_ptr:""):exif_get_tagformat(format)); #endif if (section_index==SECTION_THUMBNAIL) { switch(tag) { @@ -1330,8 +1544,8 @@ static void exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, ch if (byte_count>1 && (l=php_strnlen(value_ptr,byte_count)) > 0) { if ( lsections_found |= FOUND_INTEROP; sub_section_index = SECTION_INTEROP; - /* we do not know how to handle that yet */ - /* return; */ break; } SubdirStart = offset_base + php_ifd_get32u(value_ptr, ImageInfo->motorola_intel); @@ -1457,7 +1669,7 @@ static void exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, ch /* correctly would be to set components as length * but we are ignoring length for those types where it is not the same as byte_count */ - exif_add_image_info( ImageInfo, section_index, exif_get_tagname(tag,tagname), tag, format, byte_count, value_ptr); + exif_iif_add_tag( ImageInfo, section_index, exif_get_tagname(tag,tagname,sizeof(tagname)), tag, format, components, value_ptr); } /* }}} */ @@ -1478,7 +1690,7 @@ static void exif_process_IFD_in_JPEG(image_info_type *ImageInfo, char *DirStart, NumDirEntries = php_ifd_get16u(DirStart, ImageInfo->motorola_intel); if ((DirStart+2+NumDirEntries*12) > (OffsetBase+IFDlength)) { - php_error(E_WARNING, "Illegally sized directory x%04X + 2 + x%04X*12 = x%04X > x%04X", (int)DirStart+2-(int)OffsetBase, NumDirEntries, (int)DirStart+2+NumDirEntries*12-(int)OffsetBase, IFDlength); + php_error(E_WARNING, "Illegal directory size: x%04X + 2 + x%04X*12 = x%04X > x%04X", (int)DirStart+2-(int)OffsetBase, NumDirEntries, (int)DirStart+2+NumDirEntries*12-(int)OffsetBase, IFDlength); return; } @@ -1500,7 +1712,7 @@ static void exif_process_IFD_in_JPEG(image_info_type *ImageInfo, char *DirStart, #ifdef EXIF_DEBUG php_error(E_NOTICE,"expect next IFD to be thumbnail"); #endif - exif_process_IFD_in_JPEG(ImageInfo, OffsetBase + NextDirOffset, OffsetBase, IFDlength, SECTION_THUMBNAIL);/**/ + exif_process_IFD_in_JPEG(ImageInfo, OffsetBase + NextDirOffset, OffsetBase, IFDlength, SECTION_THUMBNAIL); } } /* }}} */ @@ -1527,6 +1739,7 @@ static void exif_process_TIFF_in_JPEG(image_info_type *ImageInfo, char *CharBuf, return; } + ImageInfo->sections_found |= FOUND_IFD0; /* First directory starts at offset 8. Offsets starts at 0. */ exif_process_IFD_in_JPEG(ImageInfo, CharBuf+8, CharBuf, length/*-14*/, SECTION_IFD0); @@ -1568,10 +1781,10 @@ static void exif_process_APP12(image_info_type *ImageInfo, char *buffer, unsigne int l1, l2=0; if ( (l1 = php_strnlen(buffer+2,length-2)) > 0) { - exif_add_image_info( ImageInfo, SECTION_APP12, "Company", TAG_NONE, TAG_FMT_STRING, l1, buffer+2); + exif_iif_add_tag( ImageInfo, SECTION_APP12, "Company", TAG_NONE, TAG_FMT_STRING, l1, buffer+2); if ( length > 2+l1+1) { l2 = php_strnlen(buffer+2+l1+1,length-2-l1+1); - exif_add_image_info( ImageInfo, SECTION_APP12, "Info", TAG_NONE, TAG_FMT_STRING, l2, buffer+2+l1+1); + exif_iif_add_tag( ImageInfo, SECTION_APP12, "Info", TAG_NONE, TAG_FMT_STRING, l2, buffer+2+l1+1); } } #ifdef EXIF_DEBUG @@ -1597,7 +1810,7 @@ static int exif_scan_JPEG_header(image_info_type *ImageInfo, FILE *infile) #ifdef EXIF_DEBUG fpos = ftell(infile); - php_error(E_NOTICE,"search section %d at 0x%04X", ImageInfo->sections_count, fpos); + php_error(E_NOTICE,"needing section %d @ 0x%04X", ImageInfo->sections_count, fpos); #endif for (a=0;a<7;a++) { @@ -1629,6 +1842,10 @@ static int exif_scan_JPEG_header(image_info_type *ImageInfo, FILE *infile) ImageInfo->sections[ImageInfo->sections_count].Size = itemlen; Data = (uchar *)emalloc(itemlen+1); /* Add 1 to allow sticking a 0 at the end. */ + if ( !Data) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return FALSE; + } ImageInfo->sections[ImageInfo->sections_count].Data = Data; /* Store first two pre-read bytes. */ @@ -1659,7 +1876,7 @@ static int exif_scan_JPEG_header(image_info_type *ImageInfo, FILE *infile) size = ep-cp; Data = (uchar *)emalloc(size); if (Data == NULL) { - php_error(E_WARNING, "could not allocate data for entire image"); + php_error(E_ERROR, "could not allocate data for entire image"); return FALSE; } @@ -1689,8 +1906,8 @@ static int exif_scan_JPEG_header(image_info_type *ImageInfo, FILE *infile) break; case M_EXIF: - if ( !(ImageInfo->sections_found&FOUND_EXIF)) { - ImageInfo->sections_found |= FOUND_EXIF; + if ( !(ImageInfo->sections_found&FOUND_IFD0)) { + /*ImageInfo->sections_found |= FOUND_EXIF;*/ /* Seen files from some 'U-lead' software with Vivitar scanner that uses marker 31 later in the file (no clue what for!) */ exif_process_APP1(ImageInfo, (char *)Data, itemlen); @@ -1751,6 +1968,10 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, FILE *infile, si if ( ImageInfo->FileSize >= dir_offset+2) { ImageInfo->sections[sn].Size = 2; ImageInfo->sections[sn].Data = emalloc(ImageInfo->sections[sn].Size); + if ( !ImageInfo->sections[sn].Data) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return FALSE; + } fseek(infile,dir_offset,SEEK_SET); /* we do not know the order of sections */ fread(ImageInfo->sections[sn].Data, 1, 2, infile); num_entries = php_ifd_get16u(ImageInfo->sections[sn].Data, ImageInfo->motorola_intel); @@ -1761,6 +1982,10 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, FILE *infile, si if ( ImageInfo->FileSize >= dir_offset+dir_size) { ImageInfo->sections[sn].Size = dir_size; ImageInfo->sections[sn].Data = erealloc(ImageInfo->sections[sn].Data,ImageInfo->sections[sn].Size); + if ( !ImageInfo->sections[sn].Data) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return FALSE; + } fread(ImageInfo->sections[sn].Data+2, 1, dir_size-2, infile); next_offset = php_ifd_get32u(ImageInfo->sections[sn].Data + dir_size - 4, ImageInfo->motorola_intel); #ifdef EXIF_DEBUG @@ -1828,6 +2053,10 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, FILE *infile, si } ImageInfo->sections[sn].Size = ifd_size; ImageInfo->sections[sn].Data = erealloc(ImageInfo->sections[sn].Data,ImageInfo->sections[sn].Size); + if ( !ImageInfo->sections[sn].Data) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + return FALSE; + } if ( ImageInfo->FileSize >= ImageInfo->sections[sn].Size) { if ( ifd_size > dir_size) { /* read values not stored in directory itself */ @@ -1866,17 +2095,15 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, FILE *infile, si case TAG_INTEROP_IFD_POINTER: ImageInfo->sections_found |= FOUND_INTEROP; sub_section_index = SECTION_INTEROP; - /* we do not know how to handle that yet */ - /* return; */ break; } entry_offset = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel); #ifdef EXIF_DEBUG - php_error(E_NOTICE,"Found other IFD: %s at x%04X", exif_get_tagname(entry_tag,tagname), entry_offset); + php_error(E_NOTICE,"Next IFD %s at x%04X", exif_get_sectionname(sub_section_index), entry_offset); #endif exif_process_IFD_in_TIFF(ImageInfo,infile,entry_offset,sub_section_index); #ifdef EXIF_DEBUG - php_error(E_NOTICE,"TIFF subsection %s done", exif_get_sectionname(sub_section_index)); + php_error(E_NOTICE,"Next IFD %s done", exif_get_sectionname(sub_section_index)); #endif } else { exif_process_IFD_TAG(ImageInfo,dir_entry,ImageInfo->sections[sn].Data-dir_offset,ifd_size,section_index,0); @@ -1895,7 +2122,7 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, FILE *infile, si if (ImageInfo->ThumbnailOffset && ImageInfo->ThumbnailSize) { ImageInfo->Thumbnail = emalloc(ImageInfo->ThumbnailSize); if (!ImageInfo->Thumbnail) { - php_error(E_WARNING, "Could not allocate memory for thumbnail"); + php_error(E_ERROR, "Could not allocate memory for thumbnail"); } else { fseek(infile,ImageInfo->ThumbnailOffset,SEEK_SET); fread(ImageInfo->Thumbnail, 1, ImageInfo->ThumbnailSize, infile); @@ -1995,7 +2222,7 @@ int php_exif_discard_imageinfo(image_info_type *ImageInfo) if (ImageInfo->FileName) efree(ImageInfo->FileName); if (ImageInfo->Thumbnail) efree(ImageInfo->Thumbnail); for (i=0; i= 2) { convert_to_string_ex(p_sections_needed); sections_str = emalloc(strlen(Z_STRVAL_PP(p_sections_needed))+3); + if ( !sections_str) { + php_error(E_ERROR,"Cannot allocate memory for all data"); + RETURN_FALSE; + } sprintf(sections_str,",%s,",Z_STRVAL_PP(p_sections_needed)); /* sections_str DOES start with , and SPACES are NOT allowed in names */ s = sections_str; @@ -2113,7 +2343,7 @@ PHP_FUNCTION(exif_read_data) sections_str = exif_get_sectionlist(ImageInfo.sections_found); #ifdef EXIF_DEBUG - php_error(E_NOTICE,"Sections found: %s", sections_str[0] ? sections_str : "None"); + php_error(E_NOTICE,"sections found: %s", sections_str[0] ? sections_str : "None"); #endif ImageInfo.sections_found |= FOUND_COMPUTED;/* do not inform about in debug*/ @@ -2124,40 +2354,37 @@ PHP_FUNCTION(exif_read_data) } #ifdef EXIF_DEBUG - php_error(E_NOTICE,"Returning information"); + php_error(E_NOTICE,"generate section FILE"); #endif - /*************************************************************************************************/ - /* generic created information must use motorola/intel organisation from the executing processor */ - i = 1; - ImageInfo.motorola_intel = (*(char*)&i) ? 0 : 1; - /* no more external processing from here */ - /*************************************************************************************************/ - /* now we can add our information */ - exif_add_image_info( &ImageInfo, SECTION_FILE, "FileName", TAG_NONE, TAG_FMT_STRING, strlen(ImageInfo.FileName), ImageInfo.FileName); - exif_add_image_info( &ImageInfo, SECTION_FILE, "FileDateTime", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.FileDateTime); - exif_add_image_info( &ImageInfo, SECTION_FILE, "FileSize", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.FileSize); - exif_add_image_info( &ImageInfo, SECTION_FILE, "SectionsFound", TAG_NONE, TAG_FMT_STRING, strlen(sections_str), sections_str); + exif_iif_add_tag( &ImageInfo, SECTION_FILE, "FileName", TAG_NONE, TAG_FMT_STRING, strlen(ImageInfo.FileName), ImageInfo.FileName); + exif_iif_add_int( &ImageInfo, SECTION_FILE, "FileDateTime", ImageInfo.FileDateTime); + exif_iif_add_int( &ImageInfo, SECTION_FILE, "FileSize", ImageInfo.FileSize); + exif_iif_add_tag( &ImageInfo, SECTION_FILE, "SectionsFound", TAG_NONE, TAG_FMT_STRING, strlen(sections_str), sections_str); + + #ifdef EXIF_DEBUG + php_error(E_NOTICE,"generate section COMPUTED"); + #endif if (ImageInfo.Width>0 && ImageInfo.Height>0) { sprintf(tmp, "width=\"%d\" height=\"%d\"", ImageInfo.Width, ImageInfo.Height); - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "html", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "Height", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.Height); - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "Width", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.Width); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "html", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); + exif_iif_add_int( &ImageInfo, SECTION_COMPUTED, "Height", ImageInfo.Height); + exif_iif_add_int( &ImageInfo, SECTION_COMPUTED, "Width", ImageInfo.Width); } - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "IsColor", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.IsColor); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "IsColor", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.IsColor); if (ImageInfo.FocalLength) { sprintf(tmp, "%4.1fmm", ImageInfo.FocalLength); - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "FocalLength", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "FocalLength", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); if(ImageInfo.CCDWidth) { sprintf(tmp, "%dmm", (int)(ImageInfo.FocalLength/ImageInfo.CCDWidth*35+0.5)); - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "35mmFocalLength", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "35mmFocalLength", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); } } if(ImageInfo.CCDWidth) { sprintf(tmp, "%dmm", (int)ImageInfo.CCDWidth); - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "CCDWidth", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "CCDWidth", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); } if(ImageInfo.ExposureTime>0) { if(ImageInfo.ExposureTime <= 0.5) { @@ -2165,11 +2392,11 @@ PHP_FUNCTION(exif_read_data) } else { sprintf(tmp, "%0.3f s", ImageInfo.ExposureTime); } - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "ExposureTime", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "ExposureTime", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); } if(ImageInfo.ApertureFNumber) { sprintf(tmp, "f/%.1f", ImageInfo.ApertureFNumber); - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "ApertureFNumber", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "ApertureFNumber", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); } if(ImageInfo.Distance) { if(ImageInfo.Distance<0) { @@ -2177,17 +2404,17 @@ PHP_FUNCTION(exif_read_data) } else { sprintf(tmp, "%0.2fm", ImageInfo.Distance); } - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "FocusDistance", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "FocusDistance", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); } if (ImageInfo.UserComment) { - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "UserComment", TAG_NONE, TAG_FMT_STRING, strlen(ImageInfo.UserComment), ImageInfo.UserComment); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "UserComment", TAG_NONE, TAG_FMT_STRING, strlen(ImageInfo.UserComment), ImageInfo.UserComment); if ( (len=ImageInfo.UserCommentEncoding[0])) { - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "UserCommentEncoding", TAG_NONE, TAG_FMT_STRING, len, ImageInfo.UserCommentEncoding); + exif_iif_add_tag( &ImageInfo, SECTION_COMPUTED, "UserCommentEncoding", TAG_NONE, TAG_FMT_STRING, len, ImageInfo.UserCommentEncoding); } } if ( read_thumbnail && ImageInfo.ThumbnailSize) { - exif_add_image_info( &ImageInfo, SECTION_THUMBNAIL, "THUMBNAIL", TAG_NONE, TAG_FMT_UNDEFINED, ImageInfo.ThumbnailSize, ImageInfo.Thumbnail); + exif_iif_add_tag( &ImageInfo, SECTION_THUMBNAIL, "THUMBNAIL", TAG_NONE, TAG_FMT_UNDEFINED, ImageInfo.ThumbnailSize, ImageInfo.Thumbnail); } efree(sections_str); @@ -2243,7 +2470,6 @@ PHP_FUNCTION(exif_thumbnail) if ( !ImageInfo.Thumbnail || !ImageInfo.ThumbnailSize) { php_exif_discard_imageinfo(&ImageInfo); - php_error(E_NOTICE,"No thumbnail data found"); RETURN_FALSE; } @@ -2275,3 +2501,4 @@ PHP_FUNCTION(exif_thumbnail) * vim600: sw=4 ts=4 tw=78 fdm=marker * vim<600: sw=4 ts=4 tw=78 */ + \ No newline at end of file -- 2.40.0