libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

jpeg_extractor.c (4738B)


      1 /*
      2      This file is part of libextractor.
      3      Copyright (C) 2002, 2003, 2004, 2012 Vidyut Samanta and Christian Grothoff
      4 
      5      libextractor is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      libextractor is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with libextractor; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19  */
     20 /**
     21  * @file plugins/jpeg_extractor.c
     22  * @brief plugin to support JPEG files
     23  * @author Christian Grothoff
     24  */
     25 #include "platform.h"
     26 #include "extractor.h"
     27 #if WINDOWS || DARWIN
     28 #if DARWIN
     29 typedef int boolean;
     30 #endif
     31 #define HAVE_BOOLEAN
     32 #endif
     33 #include <jpeglib.h>
     34 #include <setjmp.h>
     35 
     36 
     37 /**
     38  * Context for custom functions.
     39  */
     40 struct Context
     41 {
     42   /**
     43    * Environment for longjmp from within error_exit handler.
     44    */
     45   jmp_buf env;
     46 };
     47 
     48 
     49 /**
     50  * Function used to avoid having libjpeg write error messages to the console.
     51  */
     52 static void
     53 no_emit (j_common_ptr cinfo, int msg_level)
     54 {
     55   /* do nothing */
     56 }
     57 
     58 
     59 /**
     60  * Function used to avoid having libjpeg write error messages to the console.
     61  */
     62 static void
     63 no_output (j_common_ptr cinfo)
     64 {
     65   /* do nothing */
     66 }
     67 
     68 
     69 /**
     70  * Function used to avoid having libjpeg kill our process.
     71  */
     72 static void
     73 no_exit (j_common_ptr cinfo)
     74 {
     75   struct Context *ctx = cinfo->client_data;
     76 
     77   /* we're not allowed to return (by API definition),
     78      and we don't want to abort/exit.  So we longjmp
     79      to our cleanup code instead. */
     80   longjmp (ctx->env, 1);
     81 }
     82 
     83 
     84 /**
     85  * Main entry method for the 'image/jpeg' extraction plugin.
     86  *
     87  * @param ec extraction context provided to the plugin
     88  */
     89 void
     90 EXTRACTOR_jpeg_extract_method (struct EXTRACTOR_ExtractContext *ec)
     91 {
     92   struct jpeg_decompress_struct jds;
     93   struct jpeg_error_mgr em;
     94   void *buf;
     95   ssize_t size;
     96   int is_jpeg;
     97   unsigned int rounds;
     98   char format[128];
     99   struct jpeg_marker_struct *mptr;
    100   struct Context ctx;
    101 
    102   is_jpeg = 0;
    103   rounds = 0; /* used to avoid going on forever for non-jpeg files */
    104   jpeg_std_error (&em);
    105   em.emit_message = &no_emit;
    106   em.output_message = &no_output;
    107   em.error_exit = &no_exit;
    108   jds.client_data = &ctx;
    109   if (1 == setjmp (ctx.env))
    110     goto EXIT; /* we get here if libjpeg calls 'no_exit' because it wants to die */
    111   jds.err = &em;
    112   jpeg_create_decompress (&jds);
    113   jpeg_save_markers (&jds, JPEG_COM, 1024 * 8);
    114   while ( (1 == is_jpeg) || (rounds++ < 8) )
    115   {
    116     if (-1 == (size = ec->read (ec->cls,
    117                                 &buf,
    118                                 16 * 1024)))
    119       break;
    120     if (0 == size)
    121       break;
    122     jpeg_mem_src (&jds, buf, size);
    123     if (0 == is_jpeg)
    124     {
    125       if (JPEG_HEADER_OK == jpeg_read_header (&jds, 1))
    126         is_jpeg = 1; /* ok, really a jpeg, keep going until the end */
    127       continue;
    128     }
    129     jpeg_consume_input (&jds);
    130   }
    131 
    132   if (1 != is_jpeg)
    133     goto EXIT;
    134   if (0 !=
    135       ec->proc (ec->cls,
    136                 "jpeg",
    137                 EXTRACTOR_METATYPE_MIMETYPE,
    138                 EXTRACTOR_METAFORMAT_UTF8,
    139                 "text/plain",
    140                 "image/jpeg",
    141                 strlen ("image/jpeg") + 1))
    142     goto EXIT;
    143   snprintf (format,
    144             sizeof (format),
    145             "%ux%u",
    146             (unsigned int) jds.image_width,
    147             (unsigned int) jds.image_height);
    148   if (0 !=
    149       ec->proc (ec->cls,
    150                 "jpeg",
    151                 EXTRACTOR_METATYPE_IMAGE_DIMENSIONS,
    152                 EXTRACTOR_METAFORMAT_UTF8,
    153                 "text/plain",
    154                 format,
    155                 strlen (format) + 1))
    156     goto EXIT;
    157   for (mptr = jds.marker_list; NULL != mptr; mptr = mptr->next)
    158   {
    159     size_t off;
    160 
    161     if (JPEG_COM != mptr->marker)
    162       continue;
    163     off = 0;
    164     while ( (off < mptr->data_length) &&
    165             (isspace (((const unsigned char *) mptr->data)[mptr->data_length
    166                                                            - 1 - off])) )
    167       off++;
    168     if (0 !=
    169         ec->proc (ec->cls,
    170                   "jpeg",
    171                   EXTRACTOR_METATYPE_COMMENT,
    172                   EXTRACTOR_METAFORMAT_C_STRING,
    173                   "text/plain",
    174                   (const char *) mptr->data,
    175                   mptr->data_length - off))
    176       goto EXIT;
    177   }
    178 
    179 EXIT:
    180   jpeg_destroy_decompress (&jds);
    181 }
    182 
    183 
    184 /* end of jpeg_extractor.c */