Witness: working witness.cnf
[wireshark-wip.git] / wiretap / mime_file.c
bloba9703c390971d910093719f80057af4cd7d0ed16
1 /* mime_file.c
3 * MIME file format decoder for the Wiretap library.
5 * This is for use with Wireshark dissectors that handle file
6 * formats (e.g., because they handle a particular MIME media type).
7 * It breaks the file into chunks of at most WTAP_MAX_PACKET_SIZE,
8 * each of which is reported as a packet, so that files larger than
9 * WTAP_MAX_PACKET_SIZE can be handled by reassembly.
11 * The "MIME file" dissector does the reassembly, and hands the result
12 * off to heuristic dissectors to try to identify the file's contents.
14 * $Id$
16 * Wiretap Library
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include "config.h"
34 #ifdef HAVE_SYS_TYPES_H
35 #include <sys/types.h>
36 #endif
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
42 #include <errno.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <time.h>
47 #include "wtap-int.h"
48 #include "file_wrappers.h"
49 #include "buffer.h"
50 #include "mime_file.h"
52 typedef struct {
53 gboolean last_packet;
55 } mime_file_private_t;
57 typedef struct {
58 const guint8 *magic;
59 guint magic_len;
60 } mime_files_t;
63 * Written by Marton Nemeth <nm127@freemail.hu>
64 * Copyright 2009 Marton Nemeth
65 * The JPEG and JFIF specification can be found at:
67 * http://www.jpeg.org/public/jfif.pdf
68 * http://www.w3.org/Graphics/JPEG/itu-t81.pdf
70 static const guint8 jpeg_jfif_magic[] = { 0xFF, 0xD8, /* SOF */
71 0xFF /* start of the next marker */
74 /* <?xml */
75 static const guint8 xml_magic[] = { '<', '?', 'x', 'm', 'l' };
76 static const guint8 png_magic[] = { 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n' };
77 static const guint8 gif87a_magic[] = { 'G', 'I', 'F', '8', '7', 'a'};
78 static const guint8 gif89a_magic[] = { 'G', 'I', 'F', '8', '9', 'a'};
79 static const guint8 elf_magic[] = { 0x7F, 'E', 'L', 'F'};
81 static const mime_files_t magic_files[] = {
82 { jpeg_jfif_magic, sizeof(jpeg_jfif_magic) },
83 { xml_magic, sizeof(xml_magic) },
84 { png_magic, sizeof(png_magic) },
85 { gif87a_magic, sizeof(gif87a_magic) },
86 { gif89a_magic, sizeof(gif89a_magic) },
87 { elf_magic, sizeof(elf_magic) }
90 #define N_MAGIC_TYPES (sizeof(magic_files) / sizeof(magic_files[0]))
92 static void
93 mime_set_pkthdr(struct wtap_pkthdr *phdr, int packet_size)
95 phdr->presence_flags = 0;
97 phdr->ts.secs = 0;
98 phdr->ts.nsecs = 0;
99 phdr->caplen = packet_size;
100 phdr->len = packet_size;
103 static gboolean
104 mime_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
106 mime_file_private_t *priv = (mime_file_private_t *) wth->priv;
108 char _buf[WTAP_MAX_PACKET_SIZE];
109 guint8 *buf;
110 int packet_size;
112 if (priv->last_packet) {
113 *err = file_error(wth->fh, err_info);
114 return FALSE;
117 *data_offset = file_tell(wth->fh);
119 /* try to read max WTAP_MAX_PACKET_SIZE bytes */
120 packet_size = file_read(_buf, sizeof(_buf), wth->fh);
122 if (packet_size <= 0) {
123 mime_set_pkthdr(&wth->phdr, 0);
124 priv->last_packet = TRUE;
125 /* signal error for packet-mime-encap */
126 if (packet_size < 0)
127 wth->phdr.ts.nsecs = 1000000000;
128 return TRUE;
131 mime_set_pkthdr(&wth->phdr, packet_size);
133 /* copy to wth frame buffer */
134 buffer_assure_space(wth->frame_buffer, packet_size);
135 buf = buffer_start_ptr(wth->frame_buffer);
136 memcpy(buf, _buf, packet_size);
138 return TRUE;
141 static gboolean
142 mime_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int length, int *err, gchar **err_info)
144 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) {
145 *err_info = NULL;
146 return FALSE;
149 mime_set_pkthdr(phdr, length);
151 return wtap_read_packet_bytes(wth->random_fh, buf, length, err,
152 err_info);
156 mime_file_open(wtap *wth, int *err, gchar **err_info)
158 char magic_buf[128]; /* increase buffer size when needed */
159 int bytes_read;
160 gboolean found_file;
161 /* guint file_ok; */
162 guint i;
164 guint read_bytes = 0;
166 for (i = 0; i < N_MAGIC_TYPES; i++)
167 read_bytes = MAX(read_bytes, magic_files[i].magic_len);
169 read_bytes = (guint)MIN(read_bytes, sizeof(magic_buf));
170 bytes_read = file_read(magic_buf, read_bytes, wth->fh);
172 if (bytes_read < 0) {
173 *err = file_error(wth->fh, err_info);
174 return -1;
176 if (bytes_read == 0)
177 return 0;
179 found_file = FALSE;
180 for (i = 0; i < N_MAGIC_TYPES; i++) {
181 if ((guint) bytes_read >= magic_files[i].magic_len && !memcmp(magic_buf, magic_files[i].magic, MIN(magic_files[i].magic_len, (guint) bytes_read))) {
182 if (!found_file) {
183 found_file = TRUE;
184 /* file_ok = i; */
185 } else
186 return 0; /* many files matched, bad file */
190 if (!found_file)
191 return 0;
193 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
194 return -1;
196 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_MIME;
197 wth->file_encap = WTAP_ENCAP_MIME;
198 wth->tsprecision = WTAP_FILE_TSPREC_SEC;
199 wth->subtype_read = mime_read;
200 wth->subtype_seek_read = mime_seek_read;
201 wth->snapshot_length = 0;
203 wth->priv = g_malloc0(sizeof(mime_file_private_t));
205 return 1;