3 * Routines for PNG (Portable Network Graphics) image file dissection
5 * Copyright 2006 Ronnie Sahlberg
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
13 /* See http://www.w3.org/TR/PNG for specification
17 #include <epan/packet.h>
18 #include <epan/expert.h>
20 #include <wsutil/array.h>
22 #define MAKE_TYPE_VAL(a, b, c, d) ((a)<<24 | (b)<<16 | (c)<<8 | (d))
24 #define CHUNK_TYPE_IHDR MAKE_TYPE_VAL('I', 'H', 'D', 'R')
25 #define CHUNK_TYPE_bKGD MAKE_TYPE_VAL('b', 'K', 'G', 'D')
26 #define CHUNK_TYPE_gAMA MAKE_TYPE_VAL('g', 'A', 'M', 'A')
27 #define CHUNK_TYPE_iCCP MAKE_TYPE_VAL('i', 'C', 'C', 'P')
28 #define CHUNK_TYPE_cHRM MAKE_TYPE_VAL('c', 'H', 'R', 'M')
29 #define CHUNK_TYPE_pHYs MAKE_TYPE_VAL('p', 'H', 'Y', 's')
30 #define CHUNK_TYPE_iTXt MAKE_TYPE_VAL('i', 'T', 'X', 't')
31 #define CHUNK_TYPE_tEXt MAKE_TYPE_VAL('t', 'E', 'X', 't')
32 #define CHUNK_TYPE_sBIT MAKE_TYPE_VAL('s', 'B', 'I', 'T')
33 #define CHUNK_TYPE_sRGB MAKE_TYPE_VAL('s', 'R', 'G', 'B')
34 #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')
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" },
60 void proto_register_png(void);
61 void proto_reg_handoff_png(void);
63 static const true_false_string png_chunk_anc
= {
64 "This is an ANCILLARY chunk",
65 "This is a CRITICAL chunk"
68 static const true_false_string png_chunk_priv
= {
69 "This is a PRIVATE chunk",
70 "This is a PUBLIC chunk"
73 static const true_false_string png_chunk_stc
= {
74 "This chunk is SAFE TO COPY",
75 "This chunk is NOT safe to copy"
78 static const value_string colour_type_vals
[] = {
81 { 3, "Indexed-colour"},
82 { 4, "Greyscale with alpha"},
83 { 6, "Truecolour with alpha"},
87 static const value_string compression_method_vals
[] = {
92 static const value_string filter_method_vals
[] = {
97 static const value_string interlace_method_vals
[] = {
103 static const value_string srgb_intent_vals
[] = {
105 { 1, "Relative colorimetric" },
107 { 3, "Absolute colorimetric" },
111 static const value_string phys_unit_vals
[] = {
112 { 0, "Unit is unknown"},
113 { 1, "Unit is METRE"},
117 static int proto_png
;
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
;
162 static int ett_png_chunk
;
164 static expert_field ei_png_chunk_too_large
;
166 static dissector_handle_t png_handle
;
169 dissect_png_ihdr(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
171 proto_tree_add_item(tree
, hf_png_ihdr_width
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
172 proto_tree_add_item(tree
, hf_png_ihdr_height
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
173 proto_tree_add_item(tree
, hf_png_ihdr_bitdepth
, tvb
, 8, 1, ENC_BIG_ENDIAN
);
174 proto_tree_add_item(tree
, hf_png_ihdr_colour_type
, tvb
, 9, 1, ENC_BIG_ENDIAN
);
175 proto_tree_add_item(tree
, hf_png_ihdr_compression_method
, tvb
, 10, 1, ENC_BIG_ENDIAN
);
176 proto_tree_add_item(tree
, hf_png_ihdr_filter_method
, tvb
, 11, 1, ENC_BIG_ENDIAN
);
177 proto_tree_add_item(tree
, hf_png_ihdr_interlace_method
, tvb
, 12, 1, ENC_BIG_ENDIAN
);
182 dissect_png_srgb(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
184 proto_tree_add_item(tree
, hf_png_srgb_intent
,
185 tvb
, 0, 1, ENC_BIG_ENDIAN
);
189 dissect_png_text(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
191 int offset
=0, nul_offset
;
193 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 */
200 proto_tree_add_item(tree
, hf_png_text_keyword
, tvb
, offset
, nul_offset
, ENC_ISO_8859_1
|ENC_NA
);
201 offset
= nul_offset
+1; /* length of the key word + 0 character */
203 proto_tree_add_item(tree
, hf_png_text_string
, tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
), ENC_ISO_8859_1
|ENC_NA
);
208 dissect_png_time(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
210 proto_tree_add_item(tree
, hf_png_time_year
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
211 proto_tree_add_item(tree
, hf_png_time_month
, tvb
, 2, 1, ENC_BIG_ENDIAN
);
212 proto_tree_add_item(tree
, hf_png_time_day
, tvb
, 3, 1, ENC_BIG_ENDIAN
);
213 proto_tree_add_item(tree
, hf_png_time_hour
, tvb
, 4, 1, ENC_BIG_ENDIAN
);
214 proto_tree_add_item(tree
, hf_png_time_minute
, tvb
, 5, 1, ENC_BIG_ENDIAN
);
215 proto_tree_add_item(tree
, hf_png_time_second
, tvb
, 6, 1, ENC_BIG_ENDIAN
);
219 dissect_png_phys(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
221 proto_tree_add_item(tree
, hf_png_phys_horiz
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
222 proto_tree_add_item(tree
, hf_png_phys_vert
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
223 proto_tree_add_item(tree
, hf_png_phys_unit
, tvb
, 8, 1, ENC_BIG_ENDIAN
);
227 dissect_png_bkgd(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
229 switch(tvb_reported_length(tvb
)){
230 case 1: /* colour type 3 */
231 proto_tree_add_item(tree
, hf_png_bkgd_palette_index
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
233 case 2: /* colour type 0, 4 */
234 proto_tree_add_item(tree
, hf_png_bkgd_greyscale
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
236 case 6: /* colour type 2, 6 */
237 proto_tree_add_item(tree
, hf_png_bkgd_red
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
238 proto_tree_add_item(tree
, hf_png_bkgd_green
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
239 proto_tree_add_item(tree
, hf_png_bkgd_blue
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
245 dissect_png_chrm(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
247 float wx
, wy
, rx
, ry
, gx
, gy
, bx
, by
;
250 wx
= tvb_get_ntohl(tvb
, offset
) / 100000.0f
;
251 proto_tree_add_float(tree
, hf_png_chrm_white_x
,
255 wy
= tvb_get_ntohl(tvb
, offset
) / 100000.0f
;
256 proto_tree_add_float(tree
, hf_png_chrm_white_y
,
260 rx
= tvb_get_ntohl(tvb
, offset
) / 100000.0f
;
261 proto_tree_add_float(tree
, hf_png_chrm_red_x
,
265 ry
= tvb_get_ntohl(tvb
, offset
) / 100000.0f
;
266 proto_tree_add_float(tree
, hf_png_chrm_red_y
,
270 gx
= tvb_get_ntohl(tvb
, offset
) / 100000.0f
;
271 proto_tree_add_float(tree
, hf_png_chrm_green_x
,
275 gy
= tvb_get_ntohl(tvb
, offset
) / 100000.0f
;
276 proto_tree_add_float(tree
, hf_png_chrm_green_y
,
280 bx
= tvb_get_ntohl(tvb
, offset
) / 100000.0f
;
281 proto_tree_add_float(tree
, hf_png_chrm_blue_x
,
285 by
= tvb_get_ntohl(tvb
, offset
) / 100000.0f
;
286 proto_tree_add_float(tree
, hf_png_chrm_blue_y
,
291 dissect_png_gama(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
295 gamma
= tvb_get_ntohl(tvb
, 0) / 100000.0f
;
296 proto_tree_add_float(tree
, hf_png_gama_gamma
,
301 dissect_png(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, void *data _U_
)
306 /* http://libpng.org/pub/png/spec/1.2/PNG-Structure.html#PNG-file-signature */
307 static const uint8_t magic
[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
309 if (tvb_captured_length(tvb
) < 20)
311 if (tvb_memeql(tvb
, 0, magic
, sizeof(magic
)) != 0)
314 col_append_str(pinfo
->cinfo
, COL_INFO
, " (PNG)");
316 ti
=proto_tree_add_item(parent_tree
, proto_png
, tvb
, offset
, -1, ENC_NA
);
317 tree
=proto_item_add_subtree(ti
, ett_png
);
319 proto_tree_add_item(tree
, hf_png_signature
, tvb
, offset
, 8, ENC_NA
);
322 while(tvb_reported_length_remaining(tvb
, offset
) > 0){
325 proto_tree
*chunk_tree
;
330 len_field
= tvb_get_ntohl(tvb
, offset
);
332 type
= tvb_get_ntohl(tvb
, offset
+4);
333 type_str
= tvb_get_string_enc(pinfo
->pool
,
334 tvb
, offset
+4, 4, ENC_ASCII
|ENC_NA
);
336 /* 4 byte len field, 4 byte chunk type, 4 byte CRC */
337 chunk_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 4+4+len_field
+4, ett_png_chunk
, NULL
,
338 "%s (%s)", val_to_str_const(type
, chunk_types
, "unknown"), type_str
);
340 len_it
= proto_tree_add_item(chunk_tree
, hf_png_chunk_len
,
341 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
343 if (len_field
> INT_MAX
) {
344 expert_add_info(pinfo
, len_it
, &ei_png_chunk_too_large
);
348 proto_tree_add_item(chunk_tree
, hf_png_chunk_type_str
,
349 tvb
, offset
, 4, ENC_ASCII
);
351 proto_tree_add_item(chunk_tree
, hf_png_chunk_flag_anc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
352 proto_tree_add_item(chunk_tree
, hf_png_chunk_flag_priv
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
353 proto_tree_add_item(chunk_tree
, hf_png_chunk_flag_stc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
356 chunk_tvb
=tvb_new_subset_length(tvb
, offset
, len_field
);
358 case CHUNK_TYPE_IHDR
:
359 dissect_png_ihdr(chunk_tvb
, pinfo
, chunk_tree
);
361 case CHUNK_TYPE_bKGD
:
362 dissect_png_bkgd(chunk_tvb
, pinfo
, chunk_tree
);
364 case CHUNK_TYPE_cHRM
:
365 dissect_png_chrm(chunk_tvb
, pinfo
, chunk_tree
);
367 case CHUNK_TYPE_gAMA
:
368 dissect_png_gama(chunk_tvb
, pinfo
, chunk_tree
);
370 case CHUNK_TYPE_pHYs
:
371 dissect_png_phys(chunk_tvb
, pinfo
, chunk_tree
);
373 case CHUNK_TYPE_sRGB
:
374 dissect_png_srgb(chunk_tvb
, pinfo
, chunk_tree
);
376 case CHUNK_TYPE_tEXt
:
377 dissect_png_text(chunk_tvb
, pinfo
, chunk_tree
);
379 case CHUNK_TYPE_tIME
:
380 dissect_png_time(chunk_tvb
, pinfo
, chunk_tree
);
384 proto_tree_add_item(chunk_tree
, hf_png_chunk_data
,
385 tvb
, offset
, len_field
, ENC_NA
);
391 proto_tree_add_item(chunk_tree
, hf_png_chunk_crc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
398 proto_register_png(void)
400 static hf_register_info hf
[] = {
402 { "PNG Signature", "png.signature",
403 FT_BYTES
, BASE_NONE
, NULL
, 0,
406 { &hf_png_chunk_data
,
407 { "Data", "png.chunk.data",
408 FT_NONE
, BASE_NONE
, NULL
, 0,
411 { &hf_png_chunk_type_str
,
412 { "Type", "png.chunk.type",
413 FT_STRING
, BASE_NONE
, NULL
, 0,
417 { "Len", "png.chunk.len",
418 FT_UINT32
, BASE_DEC
, NULL
, 0,
422 { "CRC", "png.chunk.crc",
423 FT_UINT32
, BASE_HEX
, NULL
, 0,
426 { &hf_png_chunk_flag_anc
,
427 { "Ancillary", "png.chunk.flag.ancillary",
428 FT_BOOLEAN
, 32, TFS(&png_chunk_anc
), 0x20000000,
431 { &hf_png_chunk_flag_priv
,
432 { "Private", "png.chunk.flag.private",
433 FT_BOOLEAN
, 32, TFS(&png_chunk_priv
), 0x00200000,
436 { &hf_png_chunk_flag_stc
,
437 { "Safe To Copy", "png.chunk.flag.stc",
438 FT_BOOLEAN
, 32, TFS(&png_chunk_stc
), 0x00000020,
441 { &hf_png_ihdr_width
,
442 { "Width", "png.ihdr.width",
443 FT_UINT32
, BASE_DEC
, NULL
, 0,
446 { &hf_png_ihdr_height
,
447 { "Height", "png.ihdr.height",
448 FT_UINT32
, BASE_DEC
, NULL
, 0,
451 { &hf_png_ihdr_bitdepth
,
452 { "Bit Depth", "png.ihdr.bitdepth",
453 FT_UINT8
, BASE_DEC
, NULL
, 0,
456 { &hf_png_ihdr_colour_type
,
457 { "Colour Type", "png.ihdr.colour_type",
458 FT_UINT8
, BASE_DEC
, VALS(colour_type_vals
), 0,
461 { &hf_png_ihdr_compression_method
,
462 { "Compression Method", "png.ihdr.compression_method",
463 FT_UINT8
, BASE_DEC
, VALS(compression_method_vals
), 0,
466 { &hf_png_ihdr_filter_method
,
467 { "Filter Method", "png.ihdr.filter_method",
468 FT_UINT8
, BASE_DEC
, VALS(filter_method_vals
), 0,
471 { &hf_png_ihdr_interlace_method
,
472 { "Interlace Method", "png.ihdr.interlace_method",
473 FT_UINT8
, BASE_DEC
, VALS(interlace_method_vals
), 0,
476 { &hf_png_srgb_intent
,
477 { "Intent", "png.srgb.intent",
478 FT_UINT8
, BASE_DEC
, VALS(srgb_intent_vals
), 0,
481 { &hf_png_text_keyword
,
482 { "Keyword", "png.text.keyword",
483 FT_STRING
, BASE_NONE
, NULL
, 0,
486 { &hf_png_text_string
,
487 { "String", "png.text.string",
488 FT_STRING
, BASE_NONE
, NULL
, 0,
492 { "Year", "png.time.year",
493 FT_UINT16
, BASE_DEC
, NULL
, 0,
496 { &hf_png_time_month
,
497 { "Month", "png.time.month",
498 FT_UINT8
, BASE_DEC
, NULL
, 0,
502 { "Day", "png.time.day",
503 FT_UINT8
, BASE_DEC
, NULL
, 0,
507 { "Hour", "png.time.hour",
508 FT_UINT8
, BASE_DEC
, NULL
, 0,
511 { &hf_png_time_minute
,
512 { "Minute", "png.time.minute",
513 FT_UINT8
, BASE_DEC
, NULL
, 0,
516 { &hf_png_time_second
,
517 { "Second", "png.time.second",
518 FT_UINT8
, BASE_DEC
, NULL
, 0,
521 { &hf_png_phys_horiz
,
522 { "Horizontal pixels per unit", "png.phys.horiz",
523 FT_UINT32
, BASE_DEC
, NULL
, 0,
527 { "Vertical pixels per unit", "png.phys.vert",
528 FT_UINT32
, BASE_DEC
, NULL
, 0,
532 { "Unit", "png.phys.unit",
533 FT_UINT8
, BASE_DEC
, VALS(phys_unit_vals
), 0,
536 { &hf_png_bkgd_palette_index
,
537 { "Palette Index", "png.bkgd.palette_index",
538 FT_UINT8
, BASE_DEC
, NULL
, 0,
541 { &hf_png_bkgd_greyscale
,
542 { "Greyscale", "png.bkgd.greyscale",
543 FT_UINT16
, BASE_HEX
, NULL
, 0,
547 { "Red", "png.bkgd.red",
548 FT_UINT16
, BASE_HEX
, NULL
, 0,
551 { &hf_png_bkgd_green
,
552 { "Green", "png.bkgd.green",
553 FT_UINT16
, BASE_HEX
, NULL
, 0,
557 { "Blue", "png.bkgd.blue",
558 FT_UINT16
, BASE_HEX
, NULL
, 0,
561 { &hf_png_chrm_white_x
,
562 { "White X", "png.chrm.white.x",
563 FT_FLOAT
, BASE_NONE
, NULL
, 0,
566 { &hf_png_chrm_white_y
,
567 { "White Y", "png.chrm.white.y",
568 FT_FLOAT
, BASE_NONE
, NULL
, 0,
571 { &hf_png_chrm_red_x
,
572 { "Red X", "png.chrm.red.x",
573 FT_FLOAT
, BASE_NONE
, NULL
, 0,
576 { &hf_png_chrm_red_y
,
577 { "Red Y", "png.chrm.red.y",
578 FT_FLOAT
, BASE_NONE
, NULL
, 0,
581 { &hf_png_chrm_green_x
,
582 { "Green X", "png.chrm.green.x",
583 FT_FLOAT
, BASE_NONE
, NULL
, 0,
586 { &hf_png_chrm_green_y
,
587 { "Green Y", "png.chrm.green.y",
588 FT_FLOAT
, BASE_NONE
, NULL
, 0,
591 { &hf_png_chrm_blue_x
,
592 { "Blue X", "png.chrm.blue.x",
593 FT_FLOAT
, BASE_NONE
, NULL
, 0,
596 { &hf_png_chrm_blue_y
,
597 { "Blue Y", "png.chrm.blue.y",
598 FT_FLOAT
, BASE_NONE
, NULL
, 0,
601 { &hf_png_gama_gamma
,
602 { "Gamma", "png.gama.gamma",
603 FT_FLOAT
, BASE_NONE
, NULL
, 0,
614 static ei_register_info ei
[] = {
615 { &ei_png_chunk_too_large
,
616 { "png.chunk_too_large", PI_PROTOCOL
, PI_WARN
,
617 "chunk size too large, dissection of this chunk is not supported", EXPFILL
}}
619 expert_module_t
*expert_png
;
621 proto_png
= proto_register_protocol("Portable Network Graphics","PNG","png");
622 proto_register_field_array(proto_png
, hf
, array_length(hf
));
623 proto_register_subtree_array(ett
, array_length(ett
));
625 expert_png
= expert_register_protocol(proto_png
);
626 expert_register_field_array(expert_png
, ei
, array_length(ei
));
628 png_handle
= register_dissector("png", dissect_png
, proto_png
);
631 static bool dissect_png_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
633 return dissect_png(tvb
, pinfo
, tree
, data
) > 0;
637 proto_reg_handoff_png(void)
639 dissector_add_string("media_type", "image/png", png_handle
);
640 heur_dissector_add("http", dissect_png_heur
, "PNG file in HTTP", "png_http", proto_png
, HEURISTIC_ENABLE
);
641 heur_dissector_add("wtap_file", dissect_png_heur
, "PNG file in HTTP", "png_wtap", proto_png
, HEURISTIC_ENABLE
);
645 * Editor modelines - https://www.wireshark.org/tools/modelines.html
650 * indent-tabs-mode: nil
653 * vi: set shiftwidth=4 tabstop=8 expandtab:
654 * :indentSize=4:tabSize=8:noTabs=true: