Coverage Report

Created: 2026-07-12 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/file-gif.c
Line
Count
Source
1
/* file-gif.c
2
 *
3
 * Routines for image/gif media dissection
4
 * Copyright 2003, 2004, Olivier Biot.
5
 *
6
 * Refer to the AUTHORS file or the AUTHORS section in the man page
7
 * for contacting the author(s) of this file.
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * Compuserve GIF media decoding functionality provided by Olivier Biot.
14
 *
15
 * The two GIF specifications are found at several locations, such as W3C:
16
 * http://www.w3.org/Graphics/GIF/spec-gif87.txt
17
 * http://www.w3.org/Graphics/GIF/spec-gif89a.txt
18
 *
19
 * SPDX-License-Identifier: GPL-2.0-or-later
20
 */
21
#include "config.h"
22
23
#include <epan/packet.h>
24
#include <epan/expert.h>
25
#include <wsutil/array.h>
26
27
#include <wsutil/str_util.h>
28
29
void proto_register_gif(void);
30
void proto_reg_handoff_gif(void);
31
32
33
/************************** Variable declarations **************************/
34
35
static const value_string vals_true_false[] = {
36
    { 0, "False" },
37
    { 1, "True" },
38
    { 0, NULL },
39
};
40
41
static const value_string vals_extensions[] = {
42
    { 0xF9, "Graphics Control" },
43
    { 0xFE, "Comment" },
44
    { 0xFF, "Application" },
45
    { 0x01, "Plain Text" },
46
    { 0x00, NULL },
47
};
48
49
enum {
50
    GIF_87a = 0x87,
51
    GIF_89a = 0x89
52
};
53
54
static dissector_handle_t gif_handle;
55
56
static int proto_gif;
57
58
static int hf_background_color;
59
static int hf_data_block;
60
static int hf_extension;
61
static int hf_extension_label;
62
static int hf_global_color_map;
63
static int hf_global_color_map_ordered;
64
static int hf_global_color_map_present;
65
static int hf_global_color_resolution;
66
static int hf_global_image_bpp;
67
static int hf_image;
68
static int hf_image_code_size;
69
static int hf_image_height;
70
static int hf_image_left;
71
static int hf_image_top;
72
static int hf_image_width;
73
static int hf_local_color_map;
74
static int hf_local_color_map_ordered;
75
static int hf_local_color_map_present;
76
static int hf_local_color_resolution;
77
static int hf_local_image_bpp;
78
static int hf_pixel_aspect_ratio;
79
static int hf_screen_height;
80
static int hf_screen_width;
81
static int hf_trailer;
82
static int hf_version;
83
84
/* Initialize the subtree pointers */
85
static int ett_gif;
86
static int ett_global_flags;
87
static int ett_local_flags;
88
static int ett_extension;
89
static int ett_image;
90
91
static expert_field ei_gif_unknown_data_block_type;
92
93
/****************** GIF protocol dissection functions ******************/
94
95
static int
96
dissect_gif_data_block_seq(tvbuff_t *tvb, int offset, proto_tree *tree)
97
84
{
98
84
    int offset_start = offset;
99
84
    uint8_t len;
100
84
    proto_item *db_ti;
101
102
198
    do {
103
        /* Read length of data block */
104
198
        len = tvb_get_uint8(tvb, offset);
105
198
        db_ti = proto_tree_add_item(tree, hf_data_block,
106
198
                tvb, offset, 1, ENC_NA);
107
198
        proto_item_append_text(db_ti, " (length = %u)", len);
108
198
        offset += (1 + len);
109
198
    } while (len > 0);
110
111
84
    return offset - offset_start;
112
84
}
113
114
/* There are two Compuserve GIF standards: GIF87a and GIF89a. GIF image files
115
 * always convey their version in the first 6 bytes, written as an US-ASCII
116
 * string representation of the version: "GIF87a" or "GIF89a".
117
 */
118
119
static int
120
dissect_gif(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
121
287
{
122
287
    proto_item *ti;
123
287
    proto_tree *gif_tree; /* Main GIF tree */
124
287
    proto_tree *subtree;
125
287
    unsigned offset = 0;
126
287
    uint8_t peek;
127
287
    bool color_map_present;
128
287
    uint8_t color_resolution;
129
287
    uint8_t image_bpp;
130
287
    const uint8_t *ver_str;
131
287
    uint8_t version;
132
133
287
    if (tvb_reported_length(tvb) < 20)
134
38
        return 0;
135
136
    /* Check whether we're processing a GIF object */
137
    /* see http://www.w3.org/Graphics/GIF/spec-gif89a.txt section 17 */
138
249
    if (tvb_strneql(tvb, 0, "GIF87a", 6) == 0) {
139
11
        version = GIF_87a;
140
238
    } else if (tvb_strneql(tvb, 0, "GIF89a", 6) == 0) {
141
33
        version = GIF_89a;
142
205
    } else {
143
        /* Not a GIF image! */
144
205
        return 0;
145
205
    }
146
147
44
    ti = proto_tree_add_item(tree, proto_gif, tvb, offset, -1, ENC_NA);
148
44
    gif_tree = proto_item_add_subtree(ti, ett_gif);
149
150
    /* GIF signature */
151
44
    proto_tree_add_item_ret_string(gif_tree, hf_version,
152
44
            tvb, offset, 6, ENC_ASCII|ENC_NA, pinfo->pool, &ver_str);
153
44
    proto_item_append_text(ti, ", Version: %s", ver_str);
154
44
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", ver_str);
155
44
    offset += 6;
156
157
    /* Screen descriptor */
158
44
    proto_tree_add_item(gif_tree, hf_screen_width, tvb, offset, 2, ENC_LITTLE_ENDIAN);
159
44
    offset += 2;
160
44
    proto_tree_add_item(gif_tree, hf_screen_height, tvb, offset, 2, ENC_LITTLE_ENDIAN);
161
44
    offset += 2;
162
163
44
    peek = tvb_get_uint8(tvb, offset);
164
    /* Bitfield gccc 0ppp
165
     *          g... .... : global color map present
166
     *          .ccc .... : color resolution in bits (add one)
167
     *          .... 0... : GIF87a - reserved (no use)
168
     *                      GIF89a - ordered (most important color 1st)
169
     *          .... .ppp : bits per pixel in image (add one)
170
     */
171
44
    color_map_present = peek & 0x80;
172
44
    color_resolution = 1 + ((peek & 0x60) >> 4);
173
44
    image_bpp = 1 + (peek & 0x07);
174
175
44
    subtree = proto_tree_add_subtree(gif_tree, tvb, offset, 1, ett_global_flags, &ti,
176
44
            "Global settings:");
177
44
    if (color_map_present)
178
4
        proto_item_append_text(ti, " (Global color table present)");
179
44
    proto_item_append_text(ti,
180
44
            " (%u bit%s per color) (%u bit%s per pixel)",
181
44
            color_resolution, plurality(color_resolution, "", "s"),
182
44
            image_bpp, plurality(image_bpp, "", "s"));
183
44
    proto_tree_add_item(subtree, hf_global_color_map_present,
184
44
            tvb, offset, 1, ENC_LITTLE_ENDIAN);
185
44
    proto_tree_add_item(subtree, hf_global_color_resolution,
186
44
            tvb, offset, 1, ENC_LITTLE_ENDIAN);
187
44
    if (version == GIF_89a) {
188
33
        proto_tree_add_item(subtree, hf_global_color_map_ordered,
189
33
                tvb, offset, 1, ENC_LITTLE_ENDIAN);
190
33
    }
191
44
    proto_tree_add_item(subtree, hf_global_image_bpp,
192
44
            tvb, offset, 1, ENC_LITTLE_ENDIAN);
193
44
    offset++;
194
195
    /* Background color */
196
44
    proto_tree_add_item(gif_tree, hf_background_color,
197
44
            tvb, offset, 1, ENC_LITTLE_ENDIAN);
198
44
    offset++;
199
200
    /* byte at offset 12 is 0x00 - reserved in GIF87a but encodes the
201
     * pixel aspect ratio in GIF89a as:
202
     *      aspect-ratio = (15 + pixel-aspect-ratio) / 64
203
     * where the aspect-ratio is not computed if pixel-aspect-ratio == 0
204
     */
205
44
    if (version == GIF_89a) {
206
33
        peek = tvb_get_uint8(tvb, offset);
207
33
        if (peek) {
208
            /* Only display if different from 0 */
209
28
            proto_tree_add_uint_format(gif_tree, hf_pixel_aspect_ratio,
210
28
                    tvb, offset, 1, peek,
211
28
                    "%u, yields an aspect ratio of (15 + %u) / 64 = %.2f",
212
28
                    peek, peek, (float)(15 + peek) / 64.0);
213
28
        }
214
33
    }
215
44
    offset++;
216
217
    /* Global color map
218
     * If present, it takes 2 ^ (image_bpp) byte tuples (R, G, B)
219
     * that contain the Red, Green and Blue intensity of the colors
220
     * in the Global Color Map */
221
44
    if (color_map_present) {
222
4
        unsigned len;
223
224
4
        len = 3 * (1 << image_bpp);
225
4
        proto_tree_add_item(gif_tree, hf_global_color_map,
226
4
                tvb, offset, len, ENC_NA);
227
4
        offset += len;
228
4
    }
229
230
231
    /* From now on, a set of images prefixed with the image separator
232
     * character 0x2C (',') will appear in the byte stream. Each image
233
     * hence consists of:
234
     * - The image separator character 0x2C
235
     * - Image left (16 bits LSB first): pixels from left border
236
     * - Image top (16 bits LSB first): pixels from to border
237
     * - Image width (16 bits LSB first)
238
     * - Image height (16 bits LSB first)
239
     * - A bitfield MI00 0ppp
240
     *              M... .... : Use global color map if unset (ignore ppp);
241
     *                          if set a local color map will be defined.
242
     *              .I.. .... : Image formatted in interlaced order if set;
243
     *                          otherwise it is plain sequential order
244
     *              ..0. .... : GIF87a - Reserved
245
     *              ..s. ....   GIF89a - Set if local color map is ordered
246
     *              ...0 0... : Reserved
247
     *              .... .ppp : bits per pixel in image (add one)
248
     * - If the local color map bit is set, then a local color table follows
249
     *   with length = 3 x 2 ^ (1 + bits per pixel)
250
     * - The raster data
251
     *
252
     * NOTE that the GIF specification only requires that:
253
     *      image left + image width  <= screen width
254
     *      image top  + image height <= screen height
255
     *
256
     * The Raster Data is encoded as follows:
257
     * - Code size (1 byte)
258
     * - Blocks consisting of
259
     *      o Byte count (1 byte): number of bytes in the block
260
     *      o Data bytes: as many as specified in the byte count
261
     *   End of data is given with an empty block (byte count == 0).
262
     *
263
     *
264
     * GIF terminator
265
     * This is a synchronization method, based on the final character 0x3B
266
     * (';') at the end of an image
267
     *
268
     *
269
     * GIF extension
270
     * This is a block of data encoded as:
271
     * - The GIF extension block introducer 0x21 ('!')
272
     * - The extension function code (1 byte)
273
     * - Blocks consisting of
274
     *      o Byte count (1 byte): number of bytes in the block
275
     *      o Data bytes: as many as specified in the byte count
276
     *   End of data is given with an empty block (byte count == 0).
277
     *
278
     * NOTE that the GIF extension block can only appear at the following
279
     * locations:
280
     * - Immediately before an Image Descriptor
281
     * - Before the GIF termination character
282
     */
283
7.38k
    while (tvb_reported_length_remaining(tvb, offset)) {
284
7.34k
        int ret;
285
7.34k
        int offset_start = offset;
286
287
7.34k
        peek = tvb_get_uint8(tvb, offset);
288
7.34k
        if (peek == 0x21) { /* GIF extension block */
289
48
            ti = proto_tree_add_item(gif_tree, hf_extension,
290
48
                    tvb, offset, 1, ENC_NA);
291
48
            subtree = proto_item_add_subtree(ti, ett_extension);
292
48
            offset++;
293
48
            proto_tree_add_item(subtree, hf_extension_label,
294
48
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
295
48
            peek = tvb_get_uint8(tvb, offset);
296
48
            proto_item_append_text(ti, ": %s",
297
48
                    val_to_str(pinfo->pool, peek, vals_extensions,
298
48
                        "<Warning: Unknown extension 0x%02X>"));
299
48
            offset++;
300
48
            ret = dissect_gif_data_block_seq(tvb, offset, subtree);
301
48
            if (ret <= 0)
302
0
                break;
303
48
            offset += ret;
304
7.29k
        } else if (peek == 0x2C) { /* Image separator */
305
39
            proto_tree *subtree2;
306
39
            proto_item *ti2;
307
308
39
            ti = proto_tree_add_item(gif_tree, hf_image,
309
39
                    tvb, offset, 1, ENC_NA);
310
39
            subtree = proto_item_add_subtree(ti, ett_image);
311
39
            offset++;
312
            /* Screen descriptor */
313
39
            proto_tree_add_item(subtree, hf_image_left,
314
39
                    tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
315
39
            proto_tree_add_item(subtree, hf_image_top,
316
39
                    tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
317
39
            proto_tree_add_item(subtree, hf_image_width,
318
39
                    tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
319
39
            proto_tree_add_item(subtree, hf_image_height,
320
39
                    tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
321
            /* bit field */
322
39
            peek = tvb_get_uint8(tvb, offset);
323
39
            color_map_present = peek & 0x80;
324
39
            color_resolution = 1 + ((peek & 0x60) >> 4);
325
39
            image_bpp = 1 + (peek & 0x07);
326
327
39
            subtree2 = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_local_flags, &ti2,
328
39
                    "Local settings:");
329
39
            if (color_map_present)
330
13
                proto_item_append_text(ti2, " (Local color table present)");
331
39
            proto_item_append_text(ti2,
332
39
                    " (%u bit%s per color) (%u bit%s per pixel)",
333
39
                    color_resolution, plurality(color_resolution, "", "s"),
334
39
                    image_bpp, plurality(image_bpp, "", "s"));
335
39
            proto_tree_add_item(subtree2, hf_local_color_map_present,
336
39
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
337
39
            proto_tree_add_item(subtree2, hf_local_color_resolution,
338
39
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
339
39
            if (version == GIF_89a) {
340
28
                proto_tree_add_item(subtree2, hf_local_color_map_ordered,
341
28
                        tvb, offset, 1, ENC_LITTLE_ENDIAN);
342
28
            }
343
39
            proto_tree_add_item(subtree2, hf_global_image_bpp,
344
39
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
345
39
            offset++;
346
347
            /* Local color map
348
             * If present, it takes 2 ^ (image_bpp) byte tuples (R, G, B)
349
             * that contain the Red, Green and Blue intensity of the colors
350
             * in the Local Color Map */
351
39
            if (color_map_present) {
352
13
                unsigned len;
353
354
13
                len = 3 * (1 << image_bpp);
355
13
                proto_tree_add_item(subtree, hf_local_color_map,
356
13
                        tvb, offset, len, ENC_NA);
357
13
                offset += len;
358
13
            }
359
360
39
            proto_tree_add_item(subtree, hf_image_code_size,
361
39
                    tvb, offset, 1, ENC_LITTLE_ENDIAN);
362
39
            offset++;
363
39
            ret = dissect_gif_data_block_seq(tvb, offset, subtree);
364
39
            if (ret <= 0)
365
0
                break;
366
39
            offset += ret;
367
7.25k
        } else if (peek == 0x3B) { /* Trailer byte */
368
            /* GIF processing stops at this very byte */
369
5
            proto_tree_add_item(gif_tree, hf_trailer,
370
5
                    tvb, offset, 1, ENC_NA);
371
5
            offset++;
372
5
            break;
373
7.25k
        } else {
374
7.25k
            proto_tree_add_expert(gif_tree, pinfo,
375
7.25k
                    &ei_gif_unknown_data_block_type,
376
7.25k
                    tvb, offset, 1);
377
7.25k
            offset++;
378
7.25k
        }
379
7.34k
        proto_item_set_len(ti, offset-offset_start);
380
7.34k
    } /* while */
381
382
44
    return offset;
383
249
}
384
385
static bool
386
dissect_gif_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
387
287
{
388
287
    return dissect_gif(tvb, pinfo, tree, data) > 0;
389
287
}
390
391
392
/****************** Register the protocol with Wireshark ******************/
393
394
395
/* This format is required because a script is used to build the C function
396
 * that calls the protocol registration. */
397
398
void
399
proto_register_gif(void)
400
15
{
401
15
    static hf_register_info hf[] = {
402
15
        { &hf_version,
403
15
            { "Version", "image-gif.version",
404
15
              FT_STRING, BASE_NONE, NULL, 0x00,
405
15
              "GIF Version", HFILL }
406
15
        },
407
15
        { &hf_screen_width,
408
15
            { "Screen width", "image-gif.screen.width",
409
15
              FT_UINT16, BASE_DEC, NULL, 0x00,
410
15
              NULL, HFILL }
411
15
        },
412
15
        { &hf_screen_height,
413
15
            { "Screen height", "image-gif.screen.height",
414
15
              FT_UINT16, BASE_DEC, NULL, 0x00,
415
15
              NULL, HFILL }
416
15
        },
417
15
        { &hf_global_color_map_present,
418
15
            { "Global color map is present", "image-gif.global.color_map.present",
419
15
              FT_UINT8, BASE_DEC, VALS(vals_true_false), 0x80,
420
15
              "Indicates if the global color map is present", HFILL }
421
15
        },
422
15
        { &hf_global_color_resolution,
423
15
            { "Bits per color minus 1", "image-gif.global.color_bpp",
424
15
              FT_UINT8, BASE_DEC, NULL, 0x70,
425
15
              "The number of bits per color is one plus the field value.", HFILL }
426
15
        },
427
15
        { &hf_global_color_map_ordered,
428
15
            { "Global color map is ordered", "image-gif.global.color_map.ordered",
429
15
              FT_UINT8, BASE_DEC, VALS(vals_true_false), 0x08,
430
15
              "Indicates whether the global color map is ordered.", HFILL }
431
15
        },
432
15
        { &hf_global_image_bpp,
433
15
            { "Image bits per pixel minus 1", "image-gif.global.bpp",
434
15
              FT_UINT8, BASE_DEC, NULL, 0x07,
435
15
              "The number of bits per pixel is one plus the field value.", HFILL }
436
15
        },
437
15
        { &hf_background_color,
438
15
            { "Background color index", "image-gif.image_background_index",
439
15
              FT_UINT8, BASE_DEC, NULL, 0x00,
440
15
              "Index of the background color in the color map.", HFILL }
441
15
        },
442
15
        { &hf_pixel_aspect_ratio,
443
15
            { "Global pixel aspect ratio", "image-gif.global.pixel_aspect_ratio",
444
15
              FT_UINT8, BASE_DEC, NULL, 0x00,
445
15
              "Gives an approximate value of the aspect ratio of the pixels.", HFILL }
446
15
        },
447
15
        { &hf_global_color_map,
448
15
            { "Global color map", "image-gif.global.color_map",
449
15
              FT_BYTES, BASE_NONE, NULL, 0x00,
450
15
              "Global color map.", HFILL }
451
15
        },
452
15
        { &hf_image_left,
453
15
            { "Image left position", "image-gif.image.left",
454
15
              FT_UINT16, BASE_DEC, NULL, 0x00,
455
15
              "Offset between left of Screen and left of Image.", HFILL }
456
15
        },
457
15
        { &hf_image_top,
458
15
            { "Image top position", "image-gif.image.top",
459
15
              FT_UINT16, BASE_DEC, NULL, 0x00,
460
15
              "Offset between top of Screen and top of Image.", HFILL }
461
15
        },
462
15
        { &hf_image_width,
463
15
            { "Image width", "image-gif.image.width",
464
15
              FT_UINT16, BASE_DEC, NULL, 0x00,
465
15
              "Image width.", HFILL }
466
15
        },
467
15
        { &hf_image_height,
468
15
            { "Image height", "image-gif.image.height",
469
15
              FT_UINT16, BASE_DEC, NULL, 0x00,
470
15
              "Image height.", HFILL }
471
15
        },
472
15
        { &hf_local_color_map_present,
473
15
            { "Local color map is present", "image-gif.local.color_map.present",
474
15
              FT_UINT8, BASE_DEC, VALS(vals_true_false), 0x80,
475
15
              "Indicates if the local color map is present", HFILL }
476
15
        },
477
15
        { &hf_local_color_resolution,
478
15
            { "Bits per color minus 1", "image-gif.local.color_bpp",
479
15
              FT_UINT8, BASE_DEC, NULL, 0x70,
480
15
              "The number of bits per color is one plus the field value.", HFILL }
481
15
        },
482
15
        { &hf_local_color_map_ordered,
483
15
            { "Local color map is ordered", "image-gif.local.color_map.ordered",
484
15
              FT_UINT8, BASE_DEC, VALS(vals_true_false), 0x08,
485
15
              "Indicates whether the local color map is ordered.", HFILL }
486
15
        },
487
15
        { &hf_local_image_bpp,
488
15
            { "Image bits per pixel minus 1", "image-gif.local.bpp",
489
15
              FT_UINT8, BASE_DEC, NULL, 0x07,
490
15
              "The number of bits per pixel is one plus the field value.", HFILL }
491
15
        },
492
15
        { &hf_local_color_map,
493
15
            { "Local color map", "image-gif.local.color_map",
494
15
              FT_BYTES, BASE_NONE, NULL, 0x00,
495
15
              "Local color map.", HFILL }
496
15
        },
497
15
        { &hf_extension,
498
15
            { "Extension", "image-gif.extension",
499
15
              FT_NONE, BASE_NONE, NULL, 0x00,
500
15
              "Extension.", HFILL }
501
15
        },
502
15
        { &hf_extension_label,
503
15
            { "Extension label", "image-gif.extension.label",
504
15
              FT_UINT8, BASE_HEX, VALS(vals_extensions), 0x00,
505
15
              "Extension label.", HFILL }
506
15
        },
507
15
        { &hf_image,
508
15
            { "Image", "image-gif.image",
509
15
              FT_NONE, BASE_NONE, NULL, 0x00,
510
15
              "Image.", HFILL }
511
15
        },
512
15
        { &hf_image_code_size,
513
15
            { "LZW minimum code size", "image-gif.image.code_size",
514
15
              FT_UINT8, BASE_DEC, NULL, 0x00,
515
15
              "Minimum code size for the LZW compression.", HFILL }
516
15
        },
517
15
        { &hf_trailer,
518
15
            { "Trailer (End of the GIF stream)", "image-gif.end",
519
15
              FT_NONE, BASE_NONE, NULL, 0x00,
520
15
              "This byte tells the decoder that the data stream is finished.", HFILL }
521
15
        },
522
15
        { &hf_data_block,
523
15
            { "Data block", "image-gif.data_block",
524
15
              FT_UINT_BYTES, BASE_NONE|BASE_ALLOW_ZERO, NULL, 0x00,
525
15
              NULL, HFILL }
526
15
        },
527
15
    };
528
529
    /* Setup protocol subtree array */
530
15
    static int *ett[] = {
531
15
        &ett_gif,
532
15
        &ett_global_flags,
533
15
        &ett_local_flags,
534
15
        &ett_extension,
535
15
        &ett_image,
536
15
    };
537
538
15
    static ei_register_info ei[] = {
539
15
        { &ei_gif_unknown_data_block_type,
540
15
            { "gif.data_block_type.unknown", PI_PROTOCOL, PI_WARN,
541
15
                "Unknown GIF data block type", EXPFILL }
542
15
        }
543
15
    };
544
545
15
    expert_module_t* expert_gif;
546
547
    /* Register the protocol name and description */
548
15
    proto_gif = proto_register_protocol("Compuserve GIF", "GIF image", "image-gif");
549
550
    /* Required function calls to register the header fields
551
     * and subtrees used */
552
15
    proto_register_field_array(proto_gif, hf, array_length(hf));
553
15
    proto_register_subtree_array(ett, array_length(ett));
554
15
    expert_gif = expert_register_protocol(proto_gif);
555
15
    expert_register_field_array(expert_gif, ei, array_length(ei));
556
557
15
    gif_handle = register_dissector("image-gif", dissect_gif, proto_gif);
558
15
}
559
560
561
void
562
proto_reg_handoff_gif(void)
563
15
{
564
    /* Register the GIF media type */
565
15
    dissector_add_string("media_type", "image/gif", gif_handle);
566
15
    heur_dissector_add("http", dissect_gif_heur, "GIF file in HTTP", "gif_http", proto_gif, HEURISTIC_ENABLE);
567
15
    heur_dissector_add("wtap_file", dissect_gif_heur, "GIF file", "gif_wtap", proto_gif, HEURISTIC_ENABLE);
568
15
}
569
570
/*
571
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
572
 *
573
 * Local variables:
574
 * c-basic-offset: 4
575
 * tab-width: 8
576
 * indent-tabs-mode: nil
577
 * End:
578
 *
579
 * vi: set shiftwidth=4 tabstop=8 expandtab:
580
 * :indentSize=4:tabSize=8:noTabs=true:
581
 */