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.
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.
34 #ifdef HAVE_SYS_TYPES_H
35 #include <sys/types.h>
48 #include "file_wrappers.h"
50 #include "mime_file.h"
55 } mime_file_private_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 */
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]))
93 mime_set_pkthdr(struct wtap_pkthdr
*phdr
, int packet_size
)
95 phdr
->presence_flags
= 0;
99 phdr
->caplen
= packet_size
;
100 phdr
->len
= packet_size
;
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
];
112 if (priv
->last_packet
) {
113 *err
= file_error(wth
->fh
, err_info
);
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 */
127 wth
->phdr
.ts
.nsecs
= 1000000000;
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
);
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) {
149 mime_set_pkthdr(phdr
, length
);
151 return wtap_read_packet_bytes(wth
->random_fh
, buf
, length
, err
,
156 mime_file_open(wtap
*wth
, int *err
, gchar
**err_info
)
158 char magic_buf
[128]; /* increase buffer size when needed */
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
);
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
))) {
186 return 0; /* many files matched, bad file */
193 if (file_seek(wth
->fh
, 0, SEEK_SET
, err
) == -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
));