--- parser3/src/classes/image.C 2002/11/28 08:38:14 1.85 +++ parser3/src/classes/image.C 2003/03/17 14:48:04 1.90.4.1 @@ -1,11 +1,11 @@ /** @file Parser: @b image parser class. - Copyright(c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) + Copyright(c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char* IDENT_IMAGE_C="$Date: 2002/11/28 08:38:14 $"; +static const char* IDENT_IMAGE_C="$Date: 2003/03/17 14:48:04 $"; /* jpegsize: gets the width and height (in pixels) of a jpeg file @@ -24,6 +24,7 @@ static const char* IDENT_IMAGE_C="$Date: #include "pa_request.h" #include "pa_vfile.h" #include "pa_vimage.h" +#include "pa_vdate.h" // class @@ -59,7 +60,7 @@ public: if(limit==0) return 0; - void *lbuf=pool.malloc(limit); + void *lbuf=pool.malloc_atomic(limit); size_t read_size=(size_t)::read(f, lbuf, limit); abuf=lbuf; if(ssize_t(read_size)<0 || read_size>limit) throw Exception(0, @@ -72,7 +73,7 @@ public: /*override*/void seek(long value, int whence) { if(lseek(f, value, whence)<0) - throw Exception("file.seek", + throw Exception("image.format", &file_name, "seek(value=%ld, whence=%d) failed: %s (%d), actual filename '%s'", value, whence, strerror(errno), errno, fname); @@ -104,11 +105,11 @@ public: switch(whence) { case SEEK_CUR: new_offset=offset+value; break; case SEEK_SET: new_offset=(size_t)value; break; - default: throw Exception("file.seek", 0, "whence #%d not supported", 0, whence); break; + default: throw Exception(0, 0, "whence #%d not supported", 0, whence); break; // never } if((ssize_t)new_offset<0 || new_offset>size) - throw Exception("file.seek", + throw Exception("image.format", &file_name, "seek(value=%l, whence=%d) failed: out of buffer, new_offset>size (%l>%l) or new_offset<0", value, whence, new_offset, size); @@ -189,6 +190,8 @@ struct JPG_Exif_IFD_entry { #define JPG_IFD_TAG_EXIF_OFFSET 0x8769 +#define JPEG_EXIF_DATE_CHARS 20 + // inline ushort x_endian_to_ushort(uchar b0, uchar b1) { @@ -275,6 +278,9 @@ static Value *parse_IFD_entry_formatted_ return 0; } +// date.C +time_t cstr_to_time_t(char *cstr, const String *report_error_origin); + static Value *parse_IFD_entry_formatted_value(Pool& pool, bool is_big, ushort format, size_t component_size, uint components_count, @@ -282,6 +288,18 @@ static Value *parse_IFD_entry_formatted_ if(format==2) { // ascii string, exception: the only type with varying size const char *cstr=(const char *)value; size_t size=components_count; + // Data format is "YYYY:MM:DD HH:MM:SS"+0x00, total 20bytes + if(size==JPEG_EXIF_DATE_CHARS + && isdigit(cstr[0]) + && cstr[JPEG_EXIF_DATE_CHARS-1]==0) { + char cstr_writable[JPEG_EXIF_DATE_CHARS]; + strcpy(cstr_writable, cstr); + + time_t t=cstr_to_time_t(cstr_writable, 0/* do not throw exception, just return bad result */); + if(t>=0) + return new(pool) VDate(pool, t); + } + if(const char *premature_zero_pos=(const char *)memchr(cstr, 0, size)) size=premature_zero_pos-cstr; return new(pool) VString(*new(pool) String(pool, cstr, size, true/*tainted*/)); @@ -295,7 +313,7 @@ static Value *parse_IFD_entry_formatted_ for(uint i=0; isize()); + gdImage::Point *all_p=(gdImage::Point *)pool.malloc_atomic(sizeof(gdImage::Point)*table->size()); gdImage::Point *add_p=all_p; table->for_each(add_point, &add_p); image->FilledPolygonReplaceColor(all_p, table->size(), @@ -837,7 +855,7 @@ static void _polyline(Request& r, const &method_name, "coordinates must be table"); - gdImage::Point *all_p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*table->size()); + gdImage::Point *all_p=(gdImage::Point *)pool.malloc_atomic(sizeof(gdImage::Point)*table->size()); gdImage::Point *add_p=all_p; table->for_each(add_point, &add_p); image->Polygon(all_p, table->size(), @@ -860,7 +878,7 @@ static void _polygon(Request& r, const S &method_name, "coordinates must be table"); - gdImage::Point *all_p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*table->size()); + gdImage::Point *all_p=(gdImage::Point *)pool.malloc_atomic(sizeof(gdImage::Point)*table->size()); gdImage::Point *add_p=all_p; table->for_each(add_point, &add_p); image->Polygon(all_p, table->size(), @@ -882,7 +900,7 @@ static void _polybar(Request& r, const S &method_name, "coordinates must be table"); - gdImage::Point *all_p=(gdImage::Point *)pool.malloc(sizeof(gdImage::Point)*table->size()); + gdImage::Point *all_p=(gdImage::Point *)pool.malloc_atomic(sizeof(gdImage::Point)*table->size()); gdImage::Point *add_p=all_p; table->for_each(add_point, &add_p); image->FilledPolygon(all_p, table->size(), @@ -924,7 +942,7 @@ public: return spacebarspace; int tr=ifont.GetTransparent(); for(int x=ifont.SX()-1; x>=0; x--) { - for(int y=0; y