From c108c43a6e8a3a09fcb7a9d4d74f85076d33ad2f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 4 Aug 2012 21:46:54 +0000 Subject: adding test for gif extractor --- src/plugins/Makefile.am | 26 +++- src/plugins/gif_extractor.c | 327 +++++++++++-------------------------------- src/plugins/mime_extractor.c | 2 +- src/plugins/test_gif.c | 77 ++++++++++ 4 files changed, 187 insertions(+), 245 deletions(-) create mode 100644 src/plugins/test_gif.c diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index fe847db..447b674 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -25,9 +25,15 @@ PLUGIN_MIME=libextractor_mime.la TEST_MIME=test_mime endif +if HAVE_GIF +PLUGIN_GIF=libextractor_gif.la +TEST_GIF=test_gif +endif + plugin_LTLIBRARIES = \ $(PLUGIN_OGG) \ - $(PLUGIN_MIME) + $(PLUGIN_MIME) \ + $(PLUGIN_GIF) if HAVE_ZZUF fuzz_tests=fuzz_default.sh @@ -35,7 +41,8 @@ endif check_PROGRAMS = \ $(TEST_OGG) \ - $(TEST_MIME) + $(TEST_MIME) \ + $(TEST_GIF) TESTS = \ $(fuzz_tests) \ @@ -81,4 +88,19 @@ test_mime_LDADD = \ $(top_builddir)/src/plugins/libtest.la +libextractor_gif_la_SOURCES = \ + gif_extractor.c +libextractor_gif_la_LDFLAGS = \ + $(PLUGINFLAGS) +libextractor_gif_la_LIBADD = \ + $(top_builddir)/src/main/libextractor.la \ + $(top_builddir)/src/common/libextractor_common.la \ + -lgif + +test_gif_SOURCES = \ + test_gif.c +test_gif_LDADD = \ + $(top_builddir)/src/plugins/libtest.la + + diff --git a/src/plugins/gif_extractor.c b/src/plugins/gif_extractor.c index 055fd9f..1e85f87 100644 --- a/src/plugins/gif_extractor.c +++ b/src/plugins/gif_extractor.c @@ -1,10 +1,10 @@ /* This file is part of libextractor. - (C) 2002, 2003, 2009 Vidyut Samanta and Christian Grothoff + (C) 2012 Vidyut Samanta and Christian Grothoff libextractor is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. libextractor is distributed in the hope that it will be useful, but @@ -20,261 +20,104 @@ #include "platform.h" #include "extractor.h" -#include "pack.h" +#include -#define DEBUG_GIF 0 -#if DEBUG_GIF -#define PRINT(a,b) fprintf(stderr,a,b) -#else -#define PRINT(a,b) -#endif - -struct GifHeader -{ - char gif[3]; - char version[3]; - uint16_t screen_width; - uint16_t screen_height; - unsigned char flags; -#define HEADER_FLAGS__SIZE_OF_GLOBAL_COLOR_TABLE 0x07 -#define HEADER_FLAGS__SORT_FLAG 0x08 -#define HEADER_FLAGS__COLOR_RESOLUTION 0x70 -#define HEADER_FLAGS__GLOBAL_COLOR_TABLE_FLAG 0x80 - unsigned char background_color_index; - unsigned char pixel_aspect_ratio; -}; - -#define GIF_HEADER_SIZE 13 -#define GIF_HEADER_SPEC "3b3bhhbbb" -#define GIF_HEADER_FIELDS(p) \ - &(p)->gif,\ - &(p)->version, \ - &(p)->screen_width, \ - &(p)->screen_height, \ - &(p)->flags, \ - &(p)->background_color_index, \ - &(p)->pixel_aspect_ratio - -struct GifDescriptor -{ - unsigned char image_separator; - uint16_t image_left; - uint16_t image_top; - uint16_t image_width; - uint16_t image_height; - unsigned char flags; -#define DESCRIPTOR_FLAGS__PIXEL_SIZE 0x07 -#define DESCRIPTOR_FLAGS__RESERVED 0x18 -#define DESCRIPTOR_FLAGS__SORT_FLAG 0x20 -#define DESCRIPTOR_FLAGS__INTERLACE_FLAG 0x40 -#define DESCRIPTOR_FLAGS__LOCAL_COLOR_TABLE_FLAG 0x80 -}; - -#define GIF_DESCRIPTOR_SIZE 10 -#define GIF_DESCRIPTOR_SPEC "chhhhc" -#define GIF_DESCRIPTOR_FIELDS(p) \ - &(p)->image_separator, \ - &(p)->image_left, \ - &(p)->image_top, \ - &(p)->image_width, \ - &(p)->image_height, \ - &(p)->flags - -struct GifExtension -{ - unsigned char extension_introducer; - unsigned char graphic_control_label; -}; - -/** - * Skip a data block. - * @return the position after the block - */ -static size_t -skipDataBlock (const unsigned char *data, size_t pos, const size_t size) -{ - while ((pos < size) && (data[pos] != 0)) - pos += data[pos] + 1; - return pos + 1; -} /** - * skip an extention block - * @return the position after the block + * Callback invoked by libgif to read data. + * + * @param ft the file handle, including our extract context + * @param bt where to write the data + * @param arg number of bytes to read + * @return -1 on error, otherwise number of bytes read */ -static size_t -skipExtensionBlock (const unsigned char *data, - size_t pos, const size_t size, - const struct GifExtension * ext) +static int +gif_read_func (GifFileType *ft, + GifByteType *bt, + int arg) { - return skipDataBlock (data, pos + sizeof (struct GifExtension), size); + struct EXTRACTOR_ExtractContext *ec = ft->UserData; + void *data; + ssize_t ret; + + ret = ec->read (ec->cls, + &data, + arg); + if (-1 == ret) + return -1; + memcpy (bt, data, ret); + return ret; } -/** - * @return the offset after the global color map - */ -static size_t -skipGlobalColorMap (const unsigned char *data, - const size_t size, - const struct GifHeader * header) -{ - size_t gct_size; - - if ((header->flags & HEADER_FLAGS__GLOBAL_COLOR_TABLE_FLAG) > 0) - gct_size = - 3 * - (1 << ((header->flags & HEADER_FLAGS__SIZE_OF_GLOBAL_COLOR_TABLE) + 1)); - else - gct_size = 0; - return GIF_HEADER_SIZE + gct_size; -} /** - * @return the offset after the local color map + * Main entry method for the 'image/gif' extraction plugin. + * + * @param ec extraction context provided to the plugin */ -static size_t -skipLocalColorMap (const unsigned char *data, - size_t pos, const size_t size, - const struct GifDescriptor * descriptor) +void +EXTRACTOR_gif_extract_method (struct EXTRACTOR_ExtractContext *ec) { - size_t lct_size; - - if (pos + GIF_DESCRIPTOR_SIZE > size) - return size; - if ((descriptor->flags & DESCRIPTOR_FLAGS__LOCAL_COLOR_TABLE_FLAG) > 0) - lct_size = - 3 * (1 << ((descriptor->flags & DESCRIPTOR_FLAGS__PIXEL_SIZE) + 1)); - else - lct_size = 0; - return pos + GIF_DESCRIPTOR_SIZE + lct_size; -} - -static int -parseComment (const unsigned char *data, - size_t pos, const size_t size, - EXTRACTOR_MetaDataProcessor proc, - void *proc_cls) -{ - size_t length; - size_t off; - size_t curr = pos; - int ret; - - length = 0; - while ( (curr < size) && - (data[curr] != 0) ) + GifFileType *gif_file; + GifRecordType gif_type; + GifByteType *ext; + int et; + char dims[128]; + + if (NULL == (gif_file = DGifOpen (ec, &gif_read_func))) + return; /* not a GIF */ + if (0 != + ec->proc (ec->cls, + "gif", + EXTRACTOR_METATYPE_MIMETYPE, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "image/gif", + strlen ("image/gif") + 1)) + return; + snprintf (dims, + sizeof (dims), + "%dx%d", + gif_file->SHeight, + gif_file->SWidth); + if (0 != + ec->proc (ec->cls, + "gif", + EXTRACTOR_METATYPE_IMAGE_DIMENSIONS, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + dims, + strlen (dims) + 1)) + return; + while (1) { - length += data[curr]; - curr += data[curr] + 1; - if (length > 65536) + if (GIF_OK != + DGifGetRecordType (gif_file, + &gif_type)) break; - } - if ( (length < 65536) && - (curr < size) ) - { - char comment[length+1]; - - curr = pos; - off = 0; - while ((data[curr] != 0) && (curr < size)) + if (UNDEFINED_RECORD_TYPE == gif_type) + break; + if (EXTENSION_RECORD_TYPE != gif_type) + continue; + if (GIF_OK != + DGifGetExtension (gif_file, &et, &ext)) + continue; + if (COMMENT_EXT_FUNC_CODE == et) { - if (off + data[curr] >= size) - break; - memcpy (&comment[off], - &data[curr] + 1, - data[curr]); - off += data[curr]; - curr += data[curr] + 1; + ec->proc (ec->cls, + "gif", + EXTRACTOR_METATYPE_COMMENT, + EXTRACTOR_METAFORMAT_C_STRING, + "text/plain", + (char*) &ext[1], + (uint8_t) ext[0]); + break; } - comment[off] = '\0'; - ret = proc (proc_cls, - "gif", - EXTRACTOR_METATYPE_COMMENT, - EXTRACTOR_METAFORMAT_UTF8, - "text/plain", - comment, - length+1); + while ( (GIF_ERROR != + DGifGetExtensionNext(gif_file, &ext)) && + (NULL != ext) ) ; /* keep going */ } - else - { - /* too big */ - ret = 0; - } - return ret; + DGifCloseFile (gif_file); } - -int -EXTRACTOR_gif_extract (const unsigned char *data, - size_t size, - EXTRACTOR_MetaDataProcessor proc, - void *proc_cls, - const char *options) -{ - size_t pos; - struct GifHeader header; - struct GifDescriptor gd; - char tmp[128]; - - if (size < GIF_HEADER_SIZE) - return 0; - EXTRACTOR_common_cat_unpack (data, GIF_HEADER_SPEC, GIF_HEADER_FIELDS (&header)); - if (0 != strncmp (&header.gif[0], "GIF", 3)) - return 0; - if (0 != strncmp (&header.version[0], "89a", 3)) - return 0; /* only 89a has support for comments */ - if (0 != proc (proc_cls, - "gif", - EXTRACTOR_METATYPE_MIMETYPE, - EXTRACTOR_METAFORMAT_UTF8, - "text/plain", - "image/gif", - strlen ("image/gif")+1)) - return 1; - snprintf (tmp, - sizeof(tmp), - "%ux%u", - header.screen_width, header.screen_height); - if (0 != proc (proc_cls, - "gif", - EXTRACTOR_METATYPE_IMAGE_DIMENSIONS, - EXTRACTOR_METAFORMAT_UTF8, - "text/plain", - tmp, - strlen (tmp)+1)) - return 1; - pos = skipGlobalColorMap (data, size, &header); - PRINT ("global color map ends at %d\n", pos); - while (pos < size) - { - switch (data[pos]) - { - case ',': /* image descriptor block */ - PRINT ("skipping local color map %d\n", pos); - EXTRACTOR_common_cat_unpack (&data[pos], - GIF_DESCRIPTOR_SPEC, - GIF_DESCRIPTOR_FIELDS (&gd)); - pos = skipLocalColorMap (data, pos, size, &gd); - break; - case '!': /* extension block */ - PRINT ("skipping extension block %d\n", pos); - if (data[pos + 1] == (unsigned char) 0xFE) - { - if (0 != parseComment (data, pos + 2, size, proc, proc_cls)) - return 1; - } - pos = skipExtensionBlock (data, pos, size, - (const struct GifExtension *) & data[pos]); - break; - case ';': - PRINT ("hit terminator at %d!\n", pos); - return 0; /* terminator! */ - default: /* raster data block */ - PRINT ("skipping data block at %d\n", pos); - pos = skipDataBlock (data, pos + 1, size); - break; - } - } - PRINT ("returning at %d\n", pos); - return 0; -} +/* end of gif_extractor.c */ diff --git a/src/plugins/mime_extractor.c b/src/plugins/mime_extractor.c index 392429a..592ba5f 100644 --- a/src/plugins/mime_extractor.c +++ b/src/plugins/mime_extractor.c @@ -4,7 +4,7 @@ libextractor is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. libextractor is distributed in the hope that it will be useful, but diff --git a/src/plugins/test_gif.c b/src/plugins/test_gif.c new file mode 100644 index 0000000..8fa8185 --- /dev/null +++ b/src/plugins/test_gif.c @@ -0,0 +1,77 @@ +/* + This file is part of libextractor. + (C) 2012 Vidyut Samanta and Christian Grothoff + + libextractor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + libextractor is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libextractor; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file plugins/test_gif.c + * @brief testcase for ogg plugin + * @author Christian Grothoff + */ +#include "platform.h" +#include "test_lib.h" + + + +/** + * Main function for the GIF testcase. + * + * @param argc number of arguments (ignored) + * @param argv arguments (ignored) + * @return 0 on success + */ +int +main (int argc, char *argv[]) +{ + struct SolutionData gif_image_sol[] = + { + { + EXTRACTOR_METATYPE_MIMETYPE, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "image/gif", + strlen ("image/gif") + 1, + 0 + }, + { + EXTRACTOR_METATYPE_IMAGE_DIMENSIONS, + EXTRACTOR_METAFORMAT_UTF8, + "text/plain", + "4x4", + strlen ("4x4") + 1, + 0 + }, + { + EXTRACTOR_METATYPE_COMMENT, + EXTRACTOR_METAFORMAT_C_STRING, + "text/plain", + "Testing keyword extraction\n", + strlen ("Testing keyword extraction\n"), + 0 + }, + { 0, 0, NULL, NULL, 0, -1 } + }; + struct ProblemSet ps[] = + { + { "testdata/gif_image.gif", + gif_image_sol }, + { NULL, NULL } + }; + return ET_main ("gif", ps); +} + +/* end of test_gif.c */ -- cgit v1.2.3