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 */