Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/file-png.c
Line
Count
Source (jump to first uncovered line)
1
/* file-png.c
2
 *
3
 * Routines for PNG (Portable Network Graphics) image file dissection
4
 *
5
 * Copyright 2006 Ronnie Sahlberg
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
/* See http://www.w3.org/TR/PNG for specification
14
 */
15
#include "config.h"
16
17
#include <epan/packet.h>
18
#include <epan/expert.h>
19
#include <epan/tfs.h>
20
#include <wsutil/array.h>
21
22
0
#define MAKE_TYPE_VAL(a, b, c, d)   ((a)<<24 | (b)<<16 | (c)<<8 | (d))
23
24
0
#define CHUNK_TYPE_IHDR   MAKE_TYPE_VAL('I', 'H', 'D', 'R')
25
0
#define CHUNK_TYPE_bKGD   MAKE_TYPE_VAL('b', 'K', 'G', 'D')
26
0
#define CHUNK_TYPE_gAMA   MAKE_TYPE_VAL('g', 'A', 'M', 'A')
27
#define CHUNK_TYPE_iCCP   MAKE_TYPE_VAL('i', 'C', 'C', 'P')
28
0
#define CHUNK_TYPE_cHRM   MAKE_TYPE_VAL('c', 'H', 'R', 'M')
29
0
#define CHUNK_TYPE_pHYs   MAKE_TYPE_VAL('p', 'H', 'Y', 's')
30
#define CHUNK_TYPE_iTXt   MAKE_TYPE_VAL('i', 'T', 'X', 't')
31
0
#define CHUNK_TYPE_tEXt   MAKE_TYPE_VAL('t', 'E', 'X', 't')
32
#define CHUNK_TYPE_sBIT   MAKE_TYPE_VAL('s', 'B', 'I', 'T')
33
0
#define CHUNK_TYPE_sRGB   MAKE_TYPE_VAL('s', 'R', 'G', 'B')
34
0
#define CHUNK_TYPE_tIME   MAKE_TYPE_VAL('t', 'I', 'M', 'E')
35
#define CHUNK_TYPE_IDAT   MAKE_TYPE_VAL('I', 'D', 'A', 'T')
36
#define CHUNK_TYPE_IEND   MAKE_TYPE_VAL('I', 'E', 'N', 'D')
37
#define CHUNK_TYPE_tRNS   MAKE_TYPE_VAL('t', 'R', 'N', 'S')
38
#define CHUNK_TYPE_PLTE   MAKE_TYPE_VAL('P', 'L', 'T', 'E')
39
40
static const value_string chunk_types[] = {
41
    { CHUNK_TYPE_IHDR, "Image Header" },
42
    { CHUNK_TYPE_bKGD, "Background colour" },
43
    { CHUNK_TYPE_gAMA, "Image gamma" },
44
    { CHUNK_TYPE_iCCP, "Embedded ICC profile" },
45
    { CHUNK_TYPE_cHRM, "Primary chromaticities and white point" },
46
    { CHUNK_TYPE_pHYs, "Physical pixel dimensions" },
47
    { CHUNK_TYPE_iTXt, "International textual data" },
48
    { CHUNK_TYPE_tEXt, "Textual data" },
49
    { CHUNK_TYPE_sBIT, "Significant bits" },
50
    { CHUNK_TYPE_sRGB, "Standard RGB colour space" },
51
    { CHUNK_TYPE_tIME, "Image last-modification time" },
52
    { CHUNK_TYPE_IDAT, "Image data chunk" },
53
    { CHUNK_TYPE_IEND, "Image Trailer" },
54
    { CHUNK_TYPE_tRNS, "Transparency" },
55
    { CHUNK_TYPE_PLTE, "Palette" },
56
    { 0, NULL }
57
};
58
59
60
void proto_register_png(void);
61
void proto_reg_handoff_png(void);
62
63
static const true_false_string png_chunk_anc = {
64
    "This is an ANCILLARY chunk",
65
    "This is a CRITICAL chunk"
66
};
67
68
static const true_false_string png_chunk_priv = {
69
    "This is a PRIVATE chunk",
70
    "This is a PUBLIC chunk"
71
};
72
73
static const true_false_string png_chunk_stc = {
74
    "This chunk is SAFE TO COPY",
75
    "This chunk is NOT safe to copy"
76
};
77
78
static const value_string colour_type_vals[] = {
79
    { 0,    "Greyscale"},
80
    { 2,    "Truecolour"},
81
    { 3,    "Indexed-colour"},
82
    { 4,    "Greyscale with alpha"},
83
    { 6,    "Truecolour with alpha"},
84
    { 0, NULL }
85
};
86
87
static const value_string compression_method_vals[] = {
88
    { 0,    "Deflate"},
89
    { 0, NULL }
90
};
91
92
static const value_string filter_method_vals[] = {
93
    { 0,    "Adaptive"},
94
    { 0, NULL }
95
};
96
97
static const value_string interlace_method_vals[] = {
98
    { 0,    "No interlace"},
99
    { 1,    "Adam7"},
100
    { 0, NULL }
101
};
102
103
static const value_string srgb_intent_vals[] = {
104
    { 0, "Perceptual" },
105
    { 1, "Relative colorimetric" },
106
    { 2, "Saturation" },
107
    { 3, "Absolute colorimetric" },
108
    { 0, NULL }
109
};
110
111
static const value_string phys_unit_vals[] = {
112
    { 0,    "Unit is unknown"},
113
    { 1,    "Unit is METRE"},
114
    { 0, NULL }
115
};
116
117
static int proto_png;
118
119
static int hf_png_bkgd_blue;
120
static int hf_png_bkgd_green;
121
static int hf_png_bkgd_greyscale;
122
static int hf_png_bkgd_palette_index;
123
static int hf_png_bkgd_red;
124
static int hf_png_chrm_blue_x;
125
static int hf_png_chrm_blue_y;
126
static int hf_png_chrm_green_x;
127
static int hf_png_chrm_green_y;
128
static int hf_png_chrm_red_x;
129
static int hf_png_chrm_red_y;
130
static int hf_png_chrm_white_x;
131
static int hf_png_chrm_white_y;
132
static int hf_png_chunk_crc;
133
static int hf_png_chunk_data;
134
static int hf_png_chunk_flag_anc;
135
static int hf_png_chunk_flag_priv;
136
static int hf_png_chunk_flag_stc;
137
static int hf_png_chunk_len;
138
static int hf_png_chunk_type_str;
139
static int hf_png_gama_gamma;
140
static int hf_png_ihdr_bitdepth;
141
static int hf_png_ihdr_colour_type;
142
static int hf_png_ihdr_compression_method;
143
static int hf_png_ihdr_filter_method;
144
static int hf_png_ihdr_height;
145
static int hf_png_ihdr_interlace_method;
146
static int hf_png_ihdr_width;
147
static int hf_png_phys_horiz;
148
static int hf_png_phys_unit;
149
static int hf_png_phys_vert;
150
static int hf_png_signature;
151
static int hf_png_srgb_intent;
152
static int hf_png_text_keyword;
153
static int hf_png_text_string;
154
static int hf_png_time_day;
155
static int hf_png_time_hour;
156
static int hf_png_time_minute;
157
static int hf_png_time_month;
158
static int hf_png_time_second;
159
static int hf_png_time_year;
160
161
static int ett_png;
162
static int ett_png_chunk;
163
164
static expert_field ei_png_chunk_too_large;
165
166
static dissector_handle_t png_handle;
167
168
static void
169
dissect_png_ihdr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
170
0
{
171
0
    proto_tree_add_item(tree, hf_png_ihdr_width, tvb, 0, 4, ENC_BIG_ENDIAN);
172
0
    proto_tree_add_item(tree, hf_png_ihdr_height, tvb, 4, 4, ENC_BIG_ENDIAN);
173
0
    proto_tree_add_item(tree, hf_png_ihdr_bitdepth, tvb, 8, 1, ENC_BIG_ENDIAN);
174
0
    proto_tree_add_item(tree, hf_png_ihdr_colour_type, tvb, 9, 1, ENC_BIG_ENDIAN);
175
0
    proto_tree_add_item(tree, hf_png_ihdr_compression_method, tvb, 10, 1, ENC_BIG_ENDIAN);
176
0
    proto_tree_add_item(tree, hf_png_ihdr_filter_method, tvb, 11, 1, ENC_BIG_ENDIAN);
177
0
    proto_tree_add_item(tree, hf_png_ihdr_interlace_method, tvb, 12, 1, ENC_BIG_ENDIAN);
178
179
0
}
180
181
static void
182
dissect_png_srgb(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
183
0
{
184
0
    proto_tree_add_item(tree, hf_png_srgb_intent,
185
0
            tvb, 0, 1, ENC_BIG_ENDIAN);
186
0
}
187
188
static void
189
dissect_png_text(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
190
0
{
191
0
    int offset=0, nul_offset;
192
193
0
    nul_offset = tvb_find_uint8(tvb, offset, tvb_captured_length_remaining(tvb, offset), 0);
194
    /* nul_offset == 0 means empty keyword, this is not allowed by the png standard */
195
0
    if (nul_offset<=0) {
196
        /* XXX exception */
197
0
        return;
198
0
    }
199
200
0
    proto_tree_add_item(tree, hf_png_text_keyword, tvb, offset, nul_offset, ENC_ISO_8859_1);
201
0
    offset = nul_offset+1; /* length of the key word + 0 character */
202
203
0
    proto_tree_add_item(tree, hf_png_text_string, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_ISO_8859_1);
204
205
0
}
206
207
static void
208
dissect_png_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
209
0
{
210
0
    proto_tree_add_item(tree, hf_png_time_year, tvb, 0, 2, ENC_BIG_ENDIAN);
211
0
    proto_tree_add_item(tree, hf_png_time_month, tvb, 2, 1, ENC_BIG_ENDIAN);
212
0
    proto_tree_add_item(tree, hf_png_time_day, tvb, 3, 1, ENC_BIG_ENDIAN);
213
0
    proto_tree_add_item(tree, hf_png_time_hour, tvb, 4, 1, ENC_BIG_ENDIAN);
214
0
    proto_tree_add_item(tree, hf_png_time_minute, tvb, 5, 1, ENC_BIG_ENDIAN);
215
0
    proto_tree_add_item(tree, hf_png_time_second, tvb, 6, 1, ENC_BIG_ENDIAN);
216
0
}
217
218
static void
219
dissect_png_phys(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
220
0
{
221
0
    proto_tree_add_item(tree, hf_png_phys_horiz, tvb, 0, 4, ENC_BIG_ENDIAN);
222
0
    proto_tree_add_item(tree, hf_png_phys_vert, tvb, 4, 4, ENC_BIG_ENDIAN);
223
0
    proto_tree_add_item(tree, hf_png_phys_unit, tvb, 8, 1, ENC_BIG_ENDIAN);
224
0
}
225
226
static void
227
dissect_png_bkgd(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
228
0
{
229
0
    switch(tvb_reported_length(tvb)){
230
0
        case 1: /* colour type 3 */
231
0
            proto_tree_add_item(tree, hf_png_bkgd_palette_index, tvb, 0, 1, ENC_BIG_ENDIAN);
232
0
            break;
233
0
        case 2: /* colour type 0, 4 */
234
0
            proto_tree_add_item(tree, hf_png_bkgd_greyscale, tvb, 0, 2, ENC_BIG_ENDIAN);
235
0
            break;
236
0
        case 6: /* colour type 2, 6 */
237
0
            proto_tree_add_item(tree, hf_png_bkgd_red, tvb, 0, 2, ENC_BIG_ENDIAN);
238
0
            proto_tree_add_item(tree, hf_png_bkgd_green, tvb, 2, 2, ENC_BIG_ENDIAN);
239
0
            proto_tree_add_item(tree, hf_png_bkgd_blue, tvb, 4, 2, ENC_BIG_ENDIAN);
240
0
            break;
241
0
    }
242
0
}
243
244
static void
245
dissect_png_chrm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
246
0
{
247
0
    float  wx, wy, rx, ry, gx, gy, bx, by;
248
0
    int    offset = 0;
249
250
0
    wx = tvb_get_ntohl(tvb, offset) / 100000.0f;
251
0
    proto_tree_add_float(tree, hf_png_chrm_white_x,
252
0
            tvb, offset, 4, wx);
253
0
    offset += 4;
254
255
0
    wy = tvb_get_ntohl(tvb, offset) / 100000.0f;
256
0
    proto_tree_add_float(tree, hf_png_chrm_white_y,
257
0
            tvb, offset, 4, wy);
258
0
    offset += 4;
259
260
0
    rx = tvb_get_ntohl(tvb, offset) / 100000.0f;
261
0
    proto_tree_add_float(tree, hf_png_chrm_red_x,
262
0
            tvb, offset, 4, rx);
263
0
    offset += 4;
264
265
0
    ry = tvb_get_ntohl(tvb, offset) / 100000.0f;
266
0
    proto_tree_add_float(tree, hf_png_chrm_red_y,
267
0
            tvb, offset, 4, ry);
268
0
    offset += 4;
269
270
0
    gx = tvb_get_ntohl(tvb, offset) / 100000.0f;
271
0
    proto_tree_add_float(tree, hf_png_chrm_green_x,
272
0
            tvb, offset, 4, gx);
273
0
    offset += 4;
274
275
0
    gy = tvb_get_ntohl(tvb, offset) / 100000.0f;
276
0
    proto_tree_add_float(tree, hf_png_chrm_green_y,
277
0
            tvb, offset, 4, gy);
278
0
    offset += 4;
279
280
0
    bx = tvb_get_ntohl(tvb, offset) / 100000.0f;
281
0
    proto_tree_add_float(tree, hf_png_chrm_blue_x,
282
0
            tvb, offset, 4, bx);
283
0
    offset += 4;
284
285
0
    by = tvb_get_ntohl(tvb, offset) / 100000.0f;
286
0
    proto_tree_add_float(tree, hf_png_chrm_blue_y,
287
0
            tvb, offset, 4, by);
288
0
}
289
290
static void
291
dissect_png_gama(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
292
0
{
293
0
    float  gamma;
294
295
0
    gamma = tvb_get_ntohl(tvb, 0) / 100000.0f;
296
0
    proto_tree_add_float(tree, hf_png_gama_gamma,
297
0
            tvb, 0, 4, gamma);
298
0
}
299
300
static int
301
dissect_png(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
302
311
{
303
311
    proto_tree *tree;
304
311
    proto_item *ti;
305
311
    int         offset=0;
306
    /* http://libpng.org/pub/png/spec/1.2/PNG-Structure.html#PNG-file-signature */
307
311
    static const uint8_t magic[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
308
309
311
    if (tvb_captured_length(tvb) < 20)
310
133
        return 0;
311
178
    if (tvb_memeql(tvb, 0, magic, sizeof(magic)) != 0)
312
175
        return 0;
313
314
3
    col_append_str(pinfo->cinfo, COL_INFO, " (PNG)");
315
316
3
    ti=proto_tree_add_item(parent_tree, proto_png, tvb, offset, -1, ENC_NA);
317
3
    tree=proto_item_add_subtree(ti, ett_png);
318
319
3
    proto_tree_add_item(tree, hf_png_signature, tvb, offset, 8, ENC_NA);
320
3
    offset+=8;
321
322
5
    while(tvb_reported_length_remaining(tvb, offset) > 0){
323
3
        uint32_t    len_field;
324
3
        proto_item *len_it;
325
3
        proto_tree *chunk_tree;
326
3
        uint32_t    type;
327
3
        uint8_t    *type_str;
328
3
        tvbuff_t   *chunk_tvb;
329
330
3
        len_field = tvb_get_ntohl(tvb, offset);
331
332
3
        type = tvb_get_ntohl(tvb, offset+4);
333
3
        type_str = tvb_get_string_enc(pinfo->pool,
334
3
                tvb, offset+4, 4, ENC_ASCII|ENC_NA);
335
336
        /* 4 byte len field, 4 byte chunk type, 4 byte CRC */
337
3
        chunk_tree = proto_tree_add_subtree_format(tree, tvb, offset, 4+4+len_field+4, ett_png_chunk, NULL,
338
3
                "%s (%s)", val_to_str_const(type, chunk_types, "unknown"), type_str);
339
340
3
        len_it = proto_tree_add_item(chunk_tree, hf_png_chunk_len,
341
3
                tvb, offset, 4, ENC_BIG_ENDIAN);
342
3
        offset+=4;
343
3
        if (len_field > INT_MAX) {
344
1
            expert_add_info(pinfo, len_it, &ei_png_chunk_too_large);
345
1
            return offset;
346
1
        }
347
348
2
        proto_tree_add_item(chunk_tree, hf_png_chunk_type_str,
349
2
                tvb, offset, 4, ENC_ASCII);
350
351
2
        proto_tree_add_item(chunk_tree, hf_png_chunk_flag_anc, tvb, offset, 4, ENC_BIG_ENDIAN);
352
2
        proto_tree_add_item(chunk_tree, hf_png_chunk_flag_priv, tvb, offset, 4, ENC_BIG_ENDIAN);
353
2
        proto_tree_add_item(chunk_tree, hf_png_chunk_flag_stc, tvb, offset, 4, ENC_BIG_ENDIAN);
354
2
        offset+=4;
355
356
2
        chunk_tvb=tvb_new_subset_length(tvb, offset, len_field);
357
2
        switch (type) {
358
0
            case CHUNK_TYPE_IHDR:
359
0
                dissect_png_ihdr(chunk_tvb, pinfo, chunk_tree);
360
0
                break;
361
0
            case CHUNK_TYPE_bKGD:
362
0
                dissect_png_bkgd(chunk_tvb, pinfo, chunk_tree);
363
0
                break;
364
0
            case CHUNK_TYPE_cHRM:
365
0
                dissect_png_chrm(chunk_tvb, pinfo, chunk_tree);
366
0
                break;
367
0
            case CHUNK_TYPE_gAMA:
368
0
                dissect_png_gama(chunk_tvb, pinfo, chunk_tree);
369
0
                break;
370
0
            case CHUNK_TYPE_pHYs:
371
0
                dissect_png_phys(chunk_tvb, pinfo, chunk_tree);
372
0
                break;
373
0
            case CHUNK_TYPE_sRGB:
374
0
                dissect_png_srgb(chunk_tvb, pinfo, chunk_tree);
375
0
                break;
376
0
            case CHUNK_TYPE_tEXt:
377
0
                dissect_png_text(chunk_tvb, pinfo, chunk_tree);
378
0
                break;
379
0
            case CHUNK_TYPE_tIME:
380
0
                dissect_png_time(chunk_tvb, pinfo, chunk_tree);
381
0
                break;
382
2
            default:
383
2
                if (len_field>0) {
384
2
                    proto_tree_add_item(chunk_tree, hf_png_chunk_data,
385
2
                            tvb, offset, len_field, ENC_NA);
386
2
                }
387
2
                break;
388
2
        }
389
2
        offset += len_field;
390
391
2
        proto_tree_add_item(chunk_tree, hf_png_chunk_crc, tvb, offset, 4, ENC_BIG_ENDIAN);
392
2
        offset+=4;
393
2
    }
394
2
    return offset;
395
3
}
396
397
void
398
proto_register_png(void)
399
14
{
400
14
    static hf_register_info hf[] = {
401
14
        { &hf_png_signature,
402
14
            { "PNG Signature", "png.signature",
403
14
              FT_BYTES, BASE_NONE, NULL, 0,
404
14
              NULL, HFILL }
405
14
        },
406
14
        { &hf_png_chunk_data,
407
14
            { "Data", "png.chunk.data",
408
14
              FT_NONE, BASE_NONE, NULL, 0,
409
14
              NULL, HFILL }
410
14
        },
411
14
        { &hf_png_chunk_type_str,
412
14
            { "Type", "png.chunk.type",
413
14
              FT_STRING, BASE_NONE, NULL, 0,
414
14
              NULL, HFILL }
415
14
        },
416
14
        { &hf_png_chunk_len,
417
14
            { "Len", "png.chunk.len",
418
14
              FT_UINT32, BASE_DEC, NULL, 0,
419
14
              NULL, HFILL }
420
14
        },
421
14
        { &hf_png_chunk_crc,
422
14
            { "CRC", "png.chunk.crc",
423
14
              FT_UINT32, BASE_HEX, NULL, 0,
424
14
              NULL, HFILL }
425
14
        },
426
14
        { &hf_png_chunk_flag_anc,
427
14
            { "Ancillary", "png.chunk.flag.ancillary",
428
14
              FT_BOOLEAN, 32, TFS(&png_chunk_anc), 0x20000000,
429
14
              NULL, HFILL }
430
14
        },
431
14
        { &hf_png_chunk_flag_priv,
432
14
            { "Private", "png.chunk.flag.private",
433
14
              FT_BOOLEAN, 32, TFS(&png_chunk_priv), 0x00200000,
434
14
              NULL, HFILL }
435
14
        },
436
14
        { &hf_png_chunk_flag_stc,
437
14
            { "Safe To Copy", "png.chunk.flag.stc",
438
14
              FT_BOOLEAN, 32, TFS(&png_chunk_stc), 0x00000020,
439
14
              NULL, HFILL }
440
14
        },
441
14
        { &hf_png_ihdr_width,
442
14
            { "Width", "png.ihdr.width",
443
14
              FT_UINT32, BASE_DEC, NULL, 0,
444
14
              NULL, HFILL }
445
14
        },
446
14
        { &hf_png_ihdr_height,
447
14
            { "Height", "png.ihdr.height",
448
14
              FT_UINT32, BASE_DEC, NULL, 0,
449
14
              NULL, HFILL }
450
14
        },
451
14
        { &hf_png_ihdr_bitdepth,
452
14
            { "Bit Depth", "png.ihdr.bitdepth",
453
14
              FT_UINT8, BASE_DEC, NULL, 0,
454
14
              NULL, HFILL }
455
14
        },
456
14
        { &hf_png_ihdr_colour_type,
457
14
            { "Colour Type", "png.ihdr.colour_type",
458
14
              FT_UINT8, BASE_DEC, VALS(colour_type_vals), 0,
459
14
              NULL, HFILL }
460
14
        },
461
14
        { &hf_png_ihdr_compression_method,
462
14
            { "Compression Method", "png.ihdr.compression_method",
463
14
              FT_UINT8, BASE_DEC, VALS(compression_method_vals), 0,
464
14
              NULL, HFILL }
465
14
        },
466
14
        { &hf_png_ihdr_filter_method,
467
14
            { "Filter Method", "png.ihdr.filter_method",
468
14
              FT_UINT8, BASE_DEC, VALS(filter_method_vals), 0,
469
14
              NULL, HFILL }
470
14
        },
471
14
        { &hf_png_ihdr_interlace_method,
472
14
            { "Interlace Method", "png.ihdr.interlace_method",
473
14
              FT_UINT8, BASE_DEC, VALS(interlace_method_vals), 0,
474
14
              NULL, HFILL }
475
14
        },
476
14
        { &hf_png_srgb_intent,
477
14
            { "Intent", "png.srgb.intent",
478
14
              FT_UINT8, BASE_DEC, VALS(srgb_intent_vals), 0,
479
14
              NULL, HFILL }
480
14
        },
481
14
        { &hf_png_text_keyword,
482
14
            { "Keyword", "png.text.keyword",
483
14
              FT_STRING, BASE_NONE, NULL, 0,
484
14
              NULL, HFILL }
485
14
        },
486
14
        { &hf_png_text_string,
487
14
            { "String", "png.text.string",
488
14
              FT_STRING, BASE_NONE, NULL, 0,
489
14
              NULL, HFILL }
490
14
        },
491
14
        { &hf_png_time_year,
492
14
            { "Year", "png.time.year",
493
14
              FT_UINT16, BASE_DEC, NULL, 0,
494
14
              NULL, HFILL }
495
14
        },
496
14
        { &hf_png_time_month,
497
14
            { "Month", "png.time.month",
498
14
              FT_UINT8, BASE_DEC, NULL, 0,
499
14
              NULL, HFILL }
500
14
        },
501
14
        { &hf_png_time_day,
502
14
            { "Day", "png.time.day",
503
14
              FT_UINT8, BASE_DEC, NULL, 0,
504
14
              NULL, HFILL }
505
14
        },
506
14
        { &hf_png_time_hour,
507
14
            { "Hour", "png.time.hour",
508
14
              FT_UINT8, BASE_DEC, NULL, 0,
509
14
              NULL, HFILL }
510
14
        },
511
14
        { &hf_png_time_minute,
512
14
            { "Minute", "png.time.minute",
513
14
              FT_UINT8, BASE_DEC, NULL, 0,
514
14
              NULL, HFILL }
515
14
        },
516
14
        { &hf_png_time_second,
517
14
            { "Second", "png.time.second",
518
14
              FT_UINT8, BASE_DEC, NULL, 0,
519
14
              NULL, HFILL }
520
14
        },
521
14
        { &hf_png_phys_horiz,
522
14
            { "Horizontal pixels per unit", "png.phys.horiz",
523
14
              FT_UINT32, BASE_DEC, NULL, 0,
524
14
              NULL, HFILL }
525
14
        },
526
14
        { &hf_png_phys_vert,
527
14
            { "Vertical pixels per unit", "png.phys.vert",
528
14
              FT_UINT32, BASE_DEC, NULL, 0,
529
14
              NULL, HFILL }
530
14
        },
531
14
        { &hf_png_phys_unit,
532
14
            { "Unit", "png.phys.unit",
533
14
              FT_UINT8, BASE_DEC, VALS(phys_unit_vals), 0,
534
14
              NULL, HFILL }
535
14
        },
536
14
        { &hf_png_bkgd_palette_index,
537
14
            { "Palette Index", "png.bkgd.palette_index",
538
14
              FT_UINT8, BASE_DEC, NULL, 0,
539
14
              NULL, HFILL }
540
14
        },
541
14
        { &hf_png_bkgd_greyscale,
542
14
            { "Greyscale", "png.bkgd.greyscale",
543
14
              FT_UINT16, BASE_HEX, NULL, 0,
544
14
              NULL, HFILL }
545
14
        },
546
14
        { &hf_png_bkgd_red,
547
14
            { "Red", "png.bkgd.red",
548
14
              FT_UINT16, BASE_HEX, NULL, 0,
549
14
              NULL, HFILL }
550
14
        },
551
14
        { &hf_png_bkgd_green,
552
14
            { "Green", "png.bkgd.green",
553
14
              FT_UINT16, BASE_HEX, NULL, 0,
554
14
              NULL, HFILL }
555
14
        },
556
14
        { &hf_png_bkgd_blue,
557
14
            { "Blue", "png.bkgd.blue",
558
14
              FT_UINT16, BASE_HEX, NULL, 0,
559
14
              NULL, HFILL }
560
14
        },
561
14
        { &hf_png_chrm_white_x,
562
14
            { "White X", "png.chrm.white.x",
563
14
              FT_FLOAT, BASE_NONE, NULL, 0,
564
14
              NULL, HFILL }
565
14
        },
566
14
        { &hf_png_chrm_white_y,
567
14
            { "White Y", "png.chrm.white.y",
568
14
              FT_FLOAT, BASE_NONE, NULL, 0,
569
14
              NULL, HFILL }
570
14
        },
571
14
        { &hf_png_chrm_red_x,
572
14
            { "Red X", "png.chrm.red.x",
573
14
              FT_FLOAT, BASE_NONE, NULL, 0,
574
14
              NULL, HFILL }
575
14
        },
576
14
        { &hf_png_chrm_red_y,
577
14
            { "Red Y", "png.chrm.red.y",
578
14
              FT_FLOAT, BASE_NONE, NULL, 0,
579
14
              NULL, HFILL }
580
14
        },
581
14
        { &hf_png_chrm_green_x,
582
14
            { "Green X", "png.chrm.green.x",
583
14
              FT_FLOAT, BASE_NONE, NULL, 0,
584
14
              NULL, HFILL }
585
14
        },
586
14
        { &hf_png_chrm_green_y,
587
14
            { "Green Y", "png.chrm.green.y",
588
14
              FT_FLOAT, BASE_NONE, NULL, 0,
589
14
              NULL, HFILL }
590
14
        },
591
14
        { &hf_png_chrm_blue_x,
592
14
            { "Blue X", "png.chrm.blue.x",
593
14
              FT_FLOAT, BASE_NONE, NULL, 0,
594
14
              NULL, HFILL }
595
14
        },
596
14
        { &hf_png_chrm_blue_y,
597
14
            { "Blue Y", "png.chrm.blue.y",
598
14
              FT_FLOAT, BASE_NONE, NULL, 0,
599
14
              NULL, HFILL }
600
14
        },
601
14
        { &hf_png_gama_gamma,
602
14
            { "Gamma", "png.gama.gamma",
603
14
              FT_FLOAT, BASE_NONE, NULL, 0,
604
14
              NULL, HFILL }
605
14
        },
606
14
    };
607
608
14
    static int *ett[] =
609
14
    {
610
14
        &ett_png,
611
14
        &ett_png_chunk,
612
14
    };
613
614
14
    static ei_register_info ei[] = {
615
14
        { &ei_png_chunk_too_large,
616
14
            { "png.chunk_too_large", PI_PROTOCOL, PI_WARN,
617
14
                "chunk size too large, dissection of this chunk is not supported", EXPFILL }}
618
14
    };
619
14
    expert_module_t *expert_png;
620
621
14
    proto_png = proto_register_protocol("Portable Network Graphics","PNG","png");
622
14
    proto_register_field_array(proto_png, hf, array_length(hf));
623
14
    proto_register_subtree_array(ett, array_length(ett));
624
625
14
    expert_png = expert_register_protocol(proto_png);
626
14
    expert_register_field_array(expert_png, ei, array_length(ei));
627
628
14
    png_handle = register_dissector("png", dissect_png, proto_png);
629
14
}
630
631
static bool dissect_png_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
632
305
{
633
305
    return dissect_png(tvb, pinfo, tree, data) > 0;
634
305
}
635
636
void
637
proto_reg_handoff_png(void)
638
14
{
639
14
    dissector_add_string("media_type", "image/png", png_handle);
640
14
    heur_dissector_add("http", dissect_png_heur, "PNG file in HTTP", "png_http", proto_png, HEURISTIC_ENABLE);
641
14
    heur_dissector_add("wtap_file", dissect_png_heur, "PNG file in HTTP", "png_wtap", proto_png, HEURISTIC_ENABLE);
642
14
}
643
644
/*
645
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
646
 *
647
 * Local variables:
648
 * c-basic-offset: 4
649
 * tab-width: 8
650
 * indent-tabs-mode: nil
651
 * End:
652
 *
653
 * vi: set shiftwidth=4 tabstop=8 expandtab:
654
 * :indentSize=4:tabSize=8:noTabs=true:
655
 */