From 5dd54ef012c95c6b20899f3d94b2dc65f634636d Mon Sep 17 00:00:00 2001 From: Sachin Kelkar Date: Wed, 8 Feb 2017 21:16:17 +0530 Subject: Update kaitaistruct version to 0.6 --- mitmproxy/contrib/kaitaistruct/gif.py | 38 +++++++++++++++++------------------ mitmproxy/contrib/kaitaistruct/png.py | 20 +++++++++--------- setup.py | 2 +- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/mitmproxy/contrib/kaitaistruct/gif.py b/mitmproxy/contrib/kaitaistruct/gif.py index 3a847d54..61499cc7 100644 --- a/mitmproxy/contrib/kaitaistruct/gif.py +++ b/mitmproxy/contrib/kaitaistruct/gif.py @@ -69,18 +69,18 @@ class Gif(KaitaiStruct): @property def has_color_table(self): if hasattr(self, '_m_has_color_table'): - return self._m_has_color_table + return self._m_has_color_table if hasattr(self, '_m_has_color_table') else None self._m_has_color_table = (self.flags & 128) != 0 - return self._m_has_color_table + return self._m_has_color_table if hasattr(self, '_m_has_color_table') else None @property def color_table_size(self): if hasattr(self, '_m_color_table_size'): - return self._m_color_table_size + return self._m_color_table_size if hasattr(self, '_m_color_table_size') else None self._m_color_table_size = (2 << (self.flags & 7)) - return self._m_color_table_size + return self._m_color_table_size if hasattr(self, '_m_color_table_size') else None class LocalImageDescriptor(KaitaiStruct): @@ -103,34 +103,34 @@ class Gif(KaitaiStruct): @property def has_color_table(self): if hasattr(self, '_m_has_color_table'): - return self._m_has_color_table + return self._m_has_color_table if hasattr(self, '_m_has_color_table') else None self._m_has_color_table = (self.flags & 128) != 0 - return self._m_has_color_table + return self._m_has_color_table if hasattr(self, '_m_has_color_table') else None @property def has_interlace(self): if hasattr(self, '_m_has_interlace'): - return self._m_has_interlace + return self._m_has_interlace if hasattr(self, '_m_has_interlace') else None self._m_has_interlace = (self.flags & 64) != 0 - return self._m_has_interlace + return self._m_has_interlace if hasattr(self, '_m_has_interlace') else None @property def has_sorted_color_table(self): if hasattr(self, '_m_has_sorted_color_table'): - return self._m_has_sorted_color_table + return self._m_has_sorted_color_table if hasattr(self, '_m_has_sorted_color_table') else None self._m_has_sorted_color_table = (self.flags & 32) != 0 - return self._m_has_sorted_color_table + return self._m_has_sorted_color_table if hasattr(self, '_m_has_sorted_color_table') else None @property def color_table_size(self): if hasattr(self, '_m_color_table_size'): - return self._m_color_table_size + return self._m_color_table_size if hasattr(self, '_m_color_table_size') else None self._m_color_table_size = (2 << (self.flags & 7)) - return self._m_color_table_size + return self._m_color_table_size if hasattr(self, '_m_color_table_size') else None class Block(KaitaiStruct): @@ -162,7 +162,7 @@ class Gif(KaitaiStruct): self._io = _io self._parent = _parent self._root = _root if _root else self - self.magic = self._io.ensure_fixed_contents(3, struct.pack('3b', 71, 73, 70)) + self.magic = self._io.ensure_fixed_contents(struct.pack('3b', 71, 73, 70)) self.version = self._io.read_bytes(3) @@ -171,27 +171,27 @@ class Gif(KaitaiStruct): self._io = _io self._parent = _parent self._root = _root if _root else self - self.block_size = self._io.ensure_fixed_contents(1, struct.pack('1b', 4)) + self.block_size = self._io.ensure_fixed_contents(struct.pack('1b', 4)) self.flags = self._io.read_u1() self.delay_time = self._io.read_u2le() self.transparent_idx = self._io.read_u1() - self.terminator = self._io.ensure_fixed_contents(1, struct.pack('1b', 0)) + self.terminator = self._io.ensure_fixed_contents(struct.pack('1b', 0)) @property def transparent_color_flag(self): if hasattr(self, '_m_transparent_color_flag'): - return self._m_transparent_color_flag + return self._m_transparent_color_flag if hasattr(self, '_m_transparent_color_flag') else None self._m_transparent_color_flag = (self.flags & 1) != 0 - return self._m_transparent_color_flag + return self._m_transparent_color_flag if hasattr(self, '_m_transparent_color_flag') else None @property def user_input_flag(self): if hasattr(self, '_m_user_input_flag'): - return self._m_user_input_flag + return self._m_user_input_flag if hasattr(self, '_m_user_input_flag') else None self._m_user_input_flag = (self.flags & 2) != 0 - return self._m_user_input_flag + return self._m_user_input_flag if hasattr(self, '_m_user_input_flag') else None class Subblock(KaitaiStruct): diff --git a/mitmproxy/contrib/kaitaistruct/png.py b/mitmproxy/contrib/kaitaistruct/png.py index 5b0e3ca3..2f3c1a5c 100644 --- a/mitmproxy/contrib/kaitaistruct/png.py +++ b/mitmproxy/contrib/kaitaistruct/png.py @@ -25,9 +25,9 @@ class Png(KaitaiStruct): self._io = _io self._parent = _parent self._root = _root if _root else self - self.magic = self._io.ensure_fixed_contents(8, struct.pack('8b', -119, 80, 78, 71, 13, 10, 26, 10)) - self.ihdr_len = self._io.ensure_fixed_contents(4, struct.pack('4b', 0, 0, 0, 13)) - self.ihdr_type = self._io.ensure_fixed_contents(4, struct.pack('4b', 73, 72, 68, 82)) + self.magic = self._io.ensure_fixed_contents(struct.pack('8b', -119, 80, 78, 71, 13, 10, 26, 10)) + self.ihdr_len = self._io.ensure_fixed_contents(struct.pack('4b', 0, 0, 0, 13)) + self.ihdr_type = self._io.ensure_fixed_contents(struct.pack('4b', 73, 72, 68, 82)) self.ihdr = self._root.IhdrChunk(self._io, self, self._root) self.ihdr_crc = self._io.read_bytes(4) self.chunks = [] @@ -117,18 +117,18 @@ class Png(KaitaiStruct): @property def x(self): if hasattr(self, '_m_x'): - return self._m_x + return self._m_x if hasattr(self, '_m_x') else None self._m_x = (self.x_int / 100000.0) - return self._m_x + return self._m_x if hasattr(self, '_m_x') else None @property def y(self): if hasattr(self, '_m_y'): - return self._m_y + return self._m_y if hasattr(self, '_m_y') else None self._m_y = (self.y_int / 100000.0) - return self._m_y + return self._m_y if hasattr(self, '_m_y') else None class BkgdGreyscale(KaitaiStruct): @@ -186,7 +186,7 @@ class Png(KaitaiStruct): self._io = _io self._parent = _parent self._root = _root if _root else self - self.render_intent = self._root.Intent(self._io.read_u1()) + self.render_intent = self._root.SrgbChunk.Intent(self._io.read_u1()) class CompressedTextChunk(KaitaiStruct): @@ -220,10 +220,10 @@ class Png(KaitaiStruct): @property def gamma_ratio(self): if hasattr(self, '_m_gamma_ratio'): - return self._m_gamma_ratio + return self._m_gamma_ratio if hasattr(self, '_m_gamma_ratio') else None self._m_gamma_ratio = (100000.0 / self.gamma_int) - return self._m_gamma_ratio + return self._m_gamma_ratio if hasattr(self, '_m_gamma_ratio') else None class BkgdChunk(KaitaiStruct): diff --git a/setup.py b/setup.py index 406f9e6a..cff9984b 100644 --- a/setup.py +++ b/setup.py @@ -71,7 +71,7 @@ setup( "html2text>=2016.1.8, <=2016.9.19", "hyperframe>=4.0.1, <5", "jsbeautifier>=1.6.3, <1.7", - "kaitaistruct>=0.5, <0.6", + "kaitaistruct>=0.6, <0.7", "Pillow>=3.2, <4.1", "passlib>=1.6.5, <1.8", "pyasn1>=0.1.9, <0.2", -- cgit v1.2.3 From c4e141a00087edb457df342884d147c5be8168a9 Mon Sep 17 00:00:00 2001 From: Sachin Kelkar Date: Fri, 10 Feb 2017 10:56:50 +0530 Subject: Add jpeg app0 sof0 com parsing --- mitmproxy/contentviews/image/image_parser.py | 18 + mitmproxy/contentviews/image/view.py | 5 + mitmproxy/contrib/kaitaistruct/exif.py | 573 +++++++++++++++++++++++ mitmproxy/contrib/kaitaistruct/jpeg.py | 191 ++++++++ test/mitmproxy/contentviews/test_image_parser.py | 24 + test/mitmproxy/data/image_parser/comment.jpg | Bin 0 -> 1779 bytes test/mitmproxy/data/image_parser/example.jpg | Bin 0 -> 1755 bytes 7 files changed, 811 insertions(+) create mode 100644 mitmproxy/contrib/kaitaistruct/exif.py create mode 100644 mitmproxy/contrib/kaitaistruct/jpeg.py create mode 100644 test/mitmproxy/data/image_parser/comment.jpg create mode 100644 test/mitmproxy/data/image_parser/example.jpg diff --git a/mitmproxy/contentviews/image/image_parser.py b/mitmproxy/contentviews/image/image_parser.py index b104d105..dd47c11d 100644 --- a/mitmproxy/contentviews/image/image_parser.py +++ b/mitmproxy/contentviews/image/image_parser.py @@ -5,6 +5,7 @@ from kaitaistruct import KaitaiStream from mitmproxy.contrib.kaitaistruct import png from mitmproxy.contrib.kaitaistruct import gif +from mitmproxy.contrib.kaitaistruct import jpeg Metadata = typing.List[typing.Tuple[str, str]] @@ -55,3 +56,20 @@ def parse_gif(data: bytes) -> Metadata: if comment is not b'': parts.append(('comment', str(comment))) return parts + + +def parse_jpeg(data: bytes) -> Metadata: + img = jpeg.Jpeg(KaitaiStream(io.BytesIO(data))) + parts = [ + ('Format', 'JPEG (ISO 10918)') + ] + for segment in img.segments: + if segment.marker._name_ == 'sof0': + parts.append(('Size', "{0} x {1} px".format(segment.data.image_width, segment.data.image_height))) + if segment.marker._name_ == 'app0': + parts.append(('jfif_version', "({0}, {1})".format(segment.data.version_major, segment.data.version_minor))) + parts.append(('jfif_density', "({0}, {1})".format(segment.data.density_x, segment.data.density_y))) + parts.append(('jfif_unit', str(segment.data.density_units._value_))) + if segment.marker._name_ == 'com': + parts.append(('comment', str(segment.data))) + return parts diff --git a/mitmproxy/contentviews/image/view.py b/mitmproxy/contentviews/image/view.py index 9caf9a6c..e3c9bbd3 100644 --- a/mitmproxy/contentviews/image/view.py +++ b/mitmproxy/contentviews/image/view.py @@ -33,6 +33,11 @@ class ViewImage(base.View): parts = image_parser.parse_gif(data) fmt = base.format_dict(multidict.MultiDict(parts)) return "%s image" % f, fmt + elif image_type == 'jpeg': + f = "JPEG" + parts = image_parser.parse_jpeg(data) + fmt = base.format_dict(multidict.MultiDict(parts)) + return "%s image" % f, fmt try: img = Image.open(io.BytesIO(data)) except IOError: diff --git a/mitmproxy/contrib/kaitaistruct/exif.py b/mitmproxy/contrib/kaitaistruct/exif.py new file mode 100644 index 00000000..f2356f42 --- /dev/null +++ b/mitmproxy/contrib/kaitaistruct/exif.py @@ -0,0 +1,573 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +import array +import struct +import zlib +from enum import Enum + +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO + + +class Exif(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.endianness = self._io.read_bytes(2) + self.version = self._io.read_u2be() + self.ifd0_ofs = self._io.read_u4be() + + class Ifd(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.num_fields = self._io.read_u2be() + self.fields = [None] * (self.num_fields) + for i in range(self.num_fields): + self.fields[i] = self._root.IfdField(self._io, self, self._root) + + self.next_ifd_ofs = self._io.read_u4be() + + @property + def next_ifd(self): + if hasattr(self, '_m_next_ifd'): + return self._m_next_ifd if hasattr(self, '_m_next_ifd') else None + + if self.next_ifd_ofs != 0: + _pos = self._io.pos() + self._io.seek(self.next_ifd_ofs) + self._m_next_ifd = self._root.Ifd(self._io, self, self._root) + self._io.seek(_pos) + + return self._m_next_ifd if hasattr(self, '_m_next_ifd') else None + + + class IfdField(KaitaiStruct): + + class FieldTypeEnum(Enum): + byte = 1 + ascii_string = 2 + word = 3 + dword = 4 + rational = 5 + + class TagEnum(Enum): + image_width = 256 + image_height = 257 + bits_per_sample = 258 + compression = 259 + photometric_interpretation = 262 + thresholding = 263 + cell_width = 264 + cell_length = 265 + fill_order = 266 + document_name = 269 + image_description = 270 + make = 271 + model = 272 + strip_offsets = 273 + orientation = 274 + samples_per_pixel = 277 + rows_per_strip = 278 + strip_byte_counts = 279 + min_sample_value = 280 + max_sample_value = 281 + x_resolution = 282 + y_resolution = 283 + planar_configuration = 284 + page_name = 285 + x_position = 286 + y_position = 287 + free_offsets = 288 + free_byte_counts = 289 + gray_response_unit = 290 + gray_response_curve = 291 + t4_options = 292 + t6_options = 293 + resolution_unit = 296 + page_number = 297 + color_response_unit = 300 + transfer_function = 301 + software = 305 + modify_date = 306 + artist = 315 + host_computer = 316 + predictor = 317 + white_point = 318 + primary_chromaticities = 319 + color_map = 320 + halftone_hints = 321 + tile_width = 322 + tile_length = 323 + tile_offsets = 324 + tile_byte_counts = 325 + bad_fax_lines = 326 + clean_fax_data = 327 + consecutive_bad_fax_lines = 328 + sub_ifd = 330 + ink_set = 332 + ink_names = 333 + numberof_inks = 334 + dot_range = 336 + target_printer = 337 + extra_samples = 338 + sample_format = 339 + s_min_sample_value = 340 + s_max_sample_value = 341 + transfer_range = 342 + clip_path = 343 + x_clip_path_units = 344 + y_clip_path_units = 345 + indexed = 346 + jpeg_tables = 347 + opi_proxy = 351 + global_parameters_ifd = 400 + profile_type = 401 + fax_profile = 402 + coding_methods = 403 + version_year = 404 + mode_number = 405 + decode = 433 + default_image_color = 434 + t82_options = 435 + jpeg_tables2 = 437 + jpeg_proc = 512 + thumbnail_offset = 513 + thumbnail_length = 514 + jpeg_restart_interval = 515 + jpeg_lossless_predictors = 517 + jpeg_point_transforms = 518 + jpegq_tables = 519 + jpegdc_tables = 520 + jpegac_tables = 521 + y_cb_cr_coefficients = 529 + y_cb_cr_sub_sampling = 530 + y_cb_cr_positioning = 531 + reference_black_white = 532 + strip_row_counts = 559 + application_notes = 700 + uspto_miscellaneous = 999 + related_image_file_format = 4096 + related_image_width = 4097 + related_image_height = 4098 + rating = 18246 + xp_dip_xml = 18247 + stitch_info = 18248 + rating_percent = 18249 + sony_raw_file_type = 28672 + light_falloff_params = 28722 + chromatic_aberration_corr_params = 28725 + distortion_corr_params = 28727 + image_id = 32781 + wang_tag1 = 32931 + wang_annotation = 32932 + wang_tag3 = 32933 + wang_tag4 = 32934 + image_reference_points = 32953 + region_xform_tack_point = 32954 + warp_quadrilateral = 32955 + affine_transform_mat = 32956 + matteing = 32995 + data_type = 32996 + image_depth = 32997 + tile_depth = 32998 + image_full_width = 33300 + image_full_height = 33301 + texture_format = 33302 + wrap_modes = 33303 + fov_cot = 33304 + matrix_world_to_screen = 33305 + matrix_world_to_camera = 33306 + model2 = 33405 + cfa_repeat_pattern_dim = 33421 + cfa_pattern2 = 33422 + battery_level = 33423 + kodak_ifd = 33424 + copyright = 33432 + exposure_time = 33434 + f_number = 33437 + md_file_tag = 33445 + md_scale_pixel = 33446 + md_color_table = 33447 + md_lab_name = 33448 + md_sample_info = 33449 + md_prep_date = 33450 + md_prep_time = 33451 + md_file_units = 33452 + pixel_scale = 33550 + advent_scale = 33589 + advent_revision = 33590 + uic1_tag = 33628 + uic2_tag = 33629 + uic3_tag = 33630 + uic4_tag = 33631 + iptc_naa = 33723 + intergraph_packet_data = 33918 + intergraph_flag_registers = 33919 + intergraph_matrix = 33920 + ingr_reserved = 33921 + model_tie_point = 33922 + site = 34016 + color_sequence = 34017 + it8_header = 34018 + raster_padding = 34019 + bits_per_run_length = 34020 + bits_per_extended_run_length = 34021 + color_table = 34022 + image_color_indicator = 34023 + background_color_indicator = 34024 + image_color_value = 34025 + background_color_value = 34026 + pixel_intensity_range = 34027 + transparency_indicator = 34028 + color_characterization = 34029 + hc_usage = 34030 + trap_indicator = 34031 + cmyk_equivalent = 34032 + sem_info = 34118 + afcp_iptc = 34152 + pixel_magic_jbig_options = 34232 + jpl_carto_ifd = 34263 + model_transform = 34264 + wb_grgb_levels = 34306 + leaf_data = 34310 + photoshop_settings = 34377 + exif_offset = 34665 + icc_profile = 34675 + tiff_fx_extensions = 34687 + multi_profiles = 34688 + shared_data = 34689 + t88_options = 34690 + image_layer = 34732 + geo_tiff_directory = 34735 + geo_tiff_double_params = 34736 + geo_tiff_ascii_params = 34737 + jbig_options = 34750 + exposure_program = 34850 + spectral_sensitivity = 34852 + gps_info = 34853 + iso = 34855 + opto_electric_conv_factor = 34856 + interlace = 34857 + time_zone_offset = 34858 + self_timer_mode = 34859 + sensitivity_type = 34864 + standard_output_sensitivity = 34865 + recommended_exposure_index = 34866 + iso_speed = 34867 + iso_speed_latitudeyyy = 34868 + iso_speed_latitudezzz = 34869 + fax_recv_params = 34908 + fax_sub_address = 34909 + fax_recv_time = 34910 + fedex_edr = 34929 + leaf_sub_ifd = 34954 + exif_version = 36864 + date_time_original = 36867 + create_date = 36868 + google_plus_upload_code = 36873 + offset_time = 36880 + offset_time_original = 36881 + offset_time_digitized = 36882 + components_configuration = 37121 + compressed_bits_per_pixel = 37122 + shutter_speed_value = 37377 + aperture_value = 37378 + brightness_value = 37379 + exposure_compensation = 37380 + max_aperture_value = 37381 + subject_distance = 37382 + metering_mode = 37383 + light_source = 37384 + flash = 37385 + focal_length = 37386 + flash_energy = 37387 + spatial_frequency_response = 37388 + noise = 37389 + focal_plane_x_resolution = 37390 + focal_plane_y_resolution = 37391 + focal_plane_resolution_unit = 37392 + image_number = 37393 + security_classification = 37394 + image_history = 37395 + subject_area = 37396 + exposure_index = 37397 + tiff_ep_standard_id = 37398 + sensing_method = 37399 + cip3_data_file = 37434 + cip3_sheet = 37435 + cip3_side = 37436 + sto_nits = 37439 + maker_note = 37500 + user_comment = 37510 + sub_sec_time = 37520 + sub_sec_time_original = 37521 + sub_sec_time_digitized = 37522 + ms_document_text = 37679 + ms_property_set_storage = 37680 + ms_document_text_position = 37681 + image_source_data = 37724 + ambient_temperature = 37888 + humidity = 37889 + pressure = 37890 + water_depth = 37891 + acceleration = 37892 + camera_elevation_angle = 37893 + xp_title = 40091 + xp_comment = 40092 + xp_author = 40093 + xp_keywords = 40094 + xp_subject = 40095 + flashpix_version = 40960 + color_space = 40961 + exif_image_width = 40962 + exif_image_height = 40963 + related_sound_file = 40964 + interop_offset = 40965 + samsung_raw_pointers_offset = 40976 + samsung_raw_pointers_length = 40977 + samsung_raw_byte_order = 41217 + samsung_raw_unknown = 41218 + flash_energy2 = 41483 + spatial_frequency_response2 = 41484 + noise2 = 41485 + focal_plane_x_resolution2 = 41486 + focal_plane_y_resolution2 = 41487 + focal_plane_resolution_unit2 = 41488 + image_number2 = 41489 + security_classification2 = 41490 + image_history2 = 41491 + subject_location = 41492 + exposure_index2 = 41493 + tiff_ep_standard_id2 = 41494 + sensing_method2 = 41495 + file_source = 41728 + scene_type = 41729 + cfa_pattern = 41730 + custom_rendered = 41985 + exposure_mode = 41986 + white_balance = 41987 + digital_zoom_ratio = 41988 + focal_length_in35mm_format = 41989 + scene_capture_type = 41990 + gain_control = 41991 + contrast = 41992 + saturation = 41993 + sharpness = 41994 + device_setting_description = 41995 + subject_distance_range = 41996 + image_unique_id = 42016 + owner_name = 42032 + serial_number = 42033 + lens_info = 42034 + lens_make = 42035 + lens_model = 42036 + lens_serial_number = 42037 + gdal_metadata = 42112 + gdal_no_data = 42113 + gamma = 42240 + expand_software = 44992 + expand_lens = 44993 + expand_film = 44994 + expand_filter_lens = 44995 + expand_scanner = 44996 + expand_flash_lamp = 44997 + pixel_format = 48129 + transformation = 48130 + uncompressed = 48131 + image_type = 48132 + image_width2 = 48256 + image_height2 = 48257 + width_resolution = 48258 + height_resolution = 48259 + image_offset = 48320 + image_byte_count = 48321 + alpha_offset = 48322 + alpha_byte_count = 48323 + image_data_discard = 48324 + alpha_data_discard = 48325 + oce_scanjob_desc = 50215 + oce_application_selector = 50216 + oce_id_number = 50217 + oce_image_logic = 50218 + annotations = 50255 + print_im = 50341 + original_file_name = 50547 + uspto_original_content_type = 50560 + dng_version = 50706 + dng_backward_version = 50707 + unique_camera_model = 50708 + localized_camera_model = 50709 + cfa_plane_color = 50710 + cfa_layout = 50711 + linearization_table = 50712 + black_level_repeat_dim = 50713 + black_level = 50714 + black_level_delta_h = 50715 + black_level_delta_v = 50716 + white_level = 50717 + default_scale = 50718 + default_crop_origin = 50719 + default_crop_size = 50720 + color_matrix1 = 50721 + color_matrix2 = 50722 + camera_calibration1 = 50723 + camera_calibration2 = 50724 + reduction_matrix1 = 50725 + reduction_matrix2 = 50726 + analog_balance = 50727 + as_shot_neutral = 50728 + as_shot_white_xy = 50729 + baseline_exposure = 50730 + baseline_noise = 50731 + baseline_sharpness = 50732 + bayer_green_split = 50733 + linear_response_limit = 50734 + camera_serial_number = 50735 + dng_lens_info = 50736 + chroma_blur_radius = 50737 + anti_alias_strength = 50738 + shadow_scale = 50739 + sr2_private = 50740 + maker_note_safety = 50741 + raw_image_segmentation = 50752 + calibration_illuminant1 = 50778 + calibration_illuminant2 = 50779 + best_quality_scale = 50780 + raw_data_unique_id = 50781 + alias_layer_metadata = 50784 + original_raw_file_name = 50827 + original_raw_file_data = 50828 + active_area = 50829 + masked_areas = 50830 + as_shot_icc_profile = 50831 + as_shot_pre_profile_matrix = 50832 + current_icc_profile = 50833 + current_pre_profile_matrix = 50834 + colorimetric_reference = 50879 + s_raw_type = 50885 + panasonic_title = 50898 + panasonic_title2 = 50899 + camera_calibration_sig = 50931 + profile_calibration_sig = 50932 + profile_ifd = 50933 + as_shot_profile_name = 50934 + noise_reduction_applied = 50935 + profile_name = 50936 + profile_hue_sat_map_dims = 50937 + profile_hue_sat_map_data1 = 50938 + profile_hue_sat_map_data2 = 50939 + profile_tone_curve = 50940 + profile_embed_policy = 50941 + profile_copyright = 50942 + forward_matrix1 = 50964 + forward_matrix2 = 50965 + preview_application_name = 50966 + preview_application_version = 50967 + preview_settings_name = 50968 + preview_settings_digest = 50969 + preview_color_space = 50970 + preview_date_time = 50971 + raw_image_digest = 50972 + original_raw_file_digest = 50973 + sub_tile_block_size = 50974 + row_interleave_factor = 50975 + profile_look_table_dims = 50981 + profile_look_table_data = 50982 + opcode_list1 = 51008 + opcode_list2 = 51009 + opcode_list3 = 51022 + noise_profile = 51041 + time_codes = 51043 + frame_rate = 51044 + t_stop = 51058 + reel_name = 51081 + original_default_final_size = 51089 + original_best_quality_size = 51090 + original_default_crop_size = 51091 + camera_label = 51105 + profile_hue_sat_map_encoding = 51107 + profile_look_table_encoding = 51108 + baseline_exposure_offset = 51109 + default_black_render = 51110 + new_raw_image_digest = 51111 + raw_to_preview_gain = 51112 + default_user_crop = 51125 + padding = 59932 + offset_schema = 59933 + owner_name2 = 65000 + serial_number2 = 65001 + lens = 65002 + kdc_ifd = 65024 + raw_file = 65100 + converter = 65101 + white_balance2 = 65102 + exposure = 65105 + shadows = 65106 + brightness = 65107 + contrast2 = 65108 + saturation2 = 65109 + sharpness2 = 65110 + smoothness = 65111 + moire_filter = 65112 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.tag = self._root.IfdField.TagEnum(self._io.read_u2be()) + self.field_type = self._root.IfdField.FieldTypeEnum(self._io.read_u2be()) + self.length = self._io.read_u4be() + self.ofs_or_data = self._io.read_u4be() + + @property + def type_byte_length(self): + if hasattr(self, '_m_type_byte_length'): + return self._m_type_byte_length if hasattr(self, '_m_type_byte_length') else None + + self._m_type_byte_length = (2 if self.field_type == self._root.IfdField.FieldTypeEnum.word else (4 if self.field_type == self._root.IfdField.FieldTypeEnum.dword else 1)) + return self._m_type_byte_length if hasattr(self, '_m_type_byte_length') else None + + @property + def byte_length(self): + if hasattr(self, '_m_byte_length'): + return self._m_byte_length if hasattr(self, '_m_byte_length') else None + + self._m_byte_length = (self.length * self.type_byte_length) + return self._m_byte_length if hasattr(self, '_m_byte_length') else None + + @property + def is_immediate_data(self): + if hasattr(self, '_m_is_immediate_data'): + return self._m_is_immediate_data if hasattr(self, '_m_is_immediate_data') else None + + self._m_is_immediate_data = self.byte_length <= 4 + return self._m_is_immediate_data if hasattr(self, '_m_is_immediate_data') else None + + @property + def data(self): + if hasattr(self, '_m_data'): + return self._m_data if hasattr(self, '_m_data') else None + + if not self.is_immediate_data: + io = self._root._io + _pos = io.pos() + io.seek(self.ofs_or_data) + self._m_data = io.read_bytes(self.byte_length) + io.seek(_pos) + + return self._m_data if hasattr(self, '_m_data') else None + + + @property + def ifd0(self): + if hasattr(self, '_m_ifd0'): + return self._m_ifd0 if hasattr(self, '_m_ifd0') else None + + _pos = self._io.pos() + self._io.seek(self.ifd0_ofs) + self._m_ifd0 = self._root.Ifd(self._io, self, self._root) + self._io.seek(_pos) + return self._m_ifd0 if hasattr(self, '_m_ifd0') else None + + diff --git a/mitmproxy/contrib/kaitaistruct/jpeg.py b/mitmproxy/contrib/kaitaistruct/jpeg.py new file mode 100644 index 00000000..ca846a1e --- /dev/null +++ b/mitmproxy/contrib/kaitaistruct/jpeg.py @@ -0,0 +1,191 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +import array +import struct +import zlib +from enum import Enum + +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO + + +from .exif import Exif +class Jpeg(KaitaiStruct): + + class ComponentId(Enum): + y = 1 + cb = 2 + cr = 3 + i = 4 + q = 5 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.segments = [] + while not self._io.is_eof(): + self.segments.append(self._root.Segment(self._io, self, self._root)) + + + class Segment(KaitaiStruct): + + class MarkerEnum(Enum): + tem = 1 + sof0 = 192 + sof1 = 193 + sof2 = 194 + sof3 = 195 + dht = 196 + sof5 = 197 + sof6 = 198 + sof7 = 199 + soi = 216 + eoi = 217 + sos = 218 + dqt = 219 + dnl = 220 + dri = 221 + app0 = 224 + app1 = 225 + app2 = 226 + com = 254 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.magic = self._io.ensure_fixed_contents(struct.pack('1b', -1)) + self.marker = self._root.Segment.MarkerEnum(self._io.read_u1()) + if ((self.marker != self._root.Segment.MarkerEnum.soi) and (self.marker != self._root.Segment.MarkerEnum.eoi)) : + self.length = self._io.read_u2be() + + if ((self.marker != self._root.Segment.MarkerEnum.soi) and (self.marker != self._root.Segment.MarkerEnum.eoi)) : + _on = self.marker + if _on == self._root.Segment.MarkerEnum.sos: + self._raw_data = self._io.read_bytes((self.length - 2)) + io = KaitaiStream(BytesIO(self._raw_data)) + self.data = self._root.SegmentSos(io, self, self._root) + elif _on == self._root.Segment.MarkerEnum.app1: + self._raw_data = self._io.read_bytes((self.length - 2)) + io = KaitaiStream(BytesIO(self._raw_data)) + self.data = self._root.SegmentApp1(io, self, self._root) + elif _on == self._root.Segment.MarkerEnum.sof0: + self._raw_data = self._io.read_bytes((self.length - 2)) + io = KaitaiStream(BytesIO(self._raw_data)) + self.data = self._root.SegmentSof0(io, self, self._root) + elif _on == self._root.Segment.MarkerEnum.app0: + self._raw_data = self._io.read_bytes((self.length - 2)) + io = KaitaiStream(BytesIO(self._raw_data)) + self.data = self._root.SegmentApp0(io, self, self._root) + else: + self.data = self._io.read_bytes((self.length - 2)) + + if self.marker == self._root.Segment.MarkerEnum.sos: + self.image_data = self._io.read_bytes_full() + + + + class SegmentSos(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.num_components = self._io.read_u1() + self.components = [None] * (self.num_components) + for i in range(self.num_components): + self.components[i] = self._root.SegmentSos.Component(self._io, self, self._root) + + self.start_spectral_selection = self._io.read_u1() + self.end_spectral = self._io.read_u1() + self.appr_bit_pos = self._io.read_u1() + + class Component(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.id = self._root.ComponentId(self._io.read_u1()) + self.huffman_table = self._io.read_u1() + + + + class SegmentApp1(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.magic = self._io.read_strz("ASCII", 0, False, True, True) + _on = self.magic + if _on == u"Exif": + self.body = self._root.ExifInJpeg(self._io, self, self._root) + + + class SegmentSof0(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.bits_per_sample = self._io.read_u1() + self.image_height = self._io.read_u2be() + self.image_width = self._io.read_u2be() + self.num_components = self._io.read_u1() + self.components = [None] * (self.num_components) + for i in range(self.num_components): + self.components[i] = self._root.SegmentSof0.Component(self._io, self, self._root) + + + class Component(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.id = self._root.ComponentId(self._io.read_u1()) + self.sampling_factors = self._io.read_u1() + self.quantization_table_id = self._io.read_u1() + + @property + def sampling_x(self): + if hasattr(self, '_m_sampling_x'): + return self._m_sampling_x if hasattr(self, '_m_sampling_x') else None + + self._m_sampling_x = ((self.sampling_factors & 240) >> 4) + return self._m_sampling_x if hasattr(self, '_m_sampling_x') else None + + @property + def sampling_y(self): + if hasattr(self, '_m_sampling_y'): + return self._m_sampling_y if hasattr(self, '_m_sampling_y') else None + + self._m_sampling_y = (self.sampling_factors & 15) + return self._m_sampling_y if hasattr(self, '_m_sampling_y') else None + + + + class ExifInJpeg(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.extra_zero = self._io.ensure_fixed_contents(struct.pack('1b', 0)) + self._raw_data = self._io.read_bytes_full() + io = KaitaiStream(BytesIO(self._raw_data)) + self.data = Exif(io) + + + class SegmentApp0(KaitaiStruct): + + class DensityUnit(Enum): + no_units = 0 + pixels_per_inch = 1 + pixels_per_cm = 2 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.magic = self._io.read_str_byte_limit(5, "ASCII") + self.version_major = self._io.read_u1() + self.version_minor = self._io.read_u1() + self.density_units = self._root.SegmentApp0.DensityUnit(self._io.read_u1()) + self.density_x = self._io.read_u2be() + self.density_y = self._io.read_u2be() + self.thumbnail_x = self._io.read_u1() + self.thumbnail_y = self._io.read_u1() + self.thumbnail = self._io.read_bytes(((self.thumbnail_x * self.thumbnail_y) * 3)) diff --git a/test/mitmproxy/contentviews/test_image_parser.py b/test/mitmproxy/contentviews/test_image_parser.py index 4241a1bb..6c78c07b 100644 --- a/test/mitmproxy/contentviews/test_image_parser.py +++ b/test/mitmproxy/contentviews/test_image_parser.py @@ -104,3 +104,27 @@ def test_parse_png(filename, metadata): def test_parse_gif(filename, metadata): with open(tutils.test_data.path(filename), 'rb') as f: assert metadata == image_parser.parse_gif(f.read()) + + +@pytest.mark.parametrize("filename, metadata", { + # check app0 + "mitmproxy/data/image_parser/example.jpg": [ + ('Format', 'JPEG (ISO 10918)'), + ('jfif_version', '(1, 1)'), + ('jfif_density', '(96, 96)'), + ('jfif_unit', '1'), + ('Size', '256 x 256 px') + ], + # check com + "mitmproxy/data/image_parser/comment.jpg": [ + ('Format', 'JPEG (ISO 10918)'), + ('jfif_version', '(1, 1)'), + ('jfif_density', '(96, 96)'), + ('jfif_unit', '1'), + ('comment', "b'mitmproxy test image'"), + ('Size', '256 x 256 px') + ], +}.items()) +def test_parse_jpeg(filename, metadata): + with open(tutils.test_data.path(filename), 'rb') as f: + assert metadata == image_parser.parse_jpeg(f.read()) diff --git a/test/mitmproxy/data/image_parser/comment.jpg b/test/mitmproxy/data/image_parser/comment.jpg new file mode 100644 index 00000000..74d443dd Binary files /dev/null and b/test/mitmproxy/data/image_parser/comment.jpg differ diff --git a/test/mitmproxy/data/image_parser/example.jpg b/test/mitmproxy/data/image_parser/example.jpg new file mode 100644 index 00000000..415ee4b2 Binary files /dev/null and b/test/mitmproxy/data/image_parser/example.jpg differ -- cgit v1.2.3 From 8eb1d34644c454a79c168f6d68fc0ae45bbc4d1a Mon Sep 17 00:00:00 2001 From: Sachin Kelkar Date: Fri, 10 Feb 2017 22:40:19 +0530 Subject: Add app1 marker and tests --- mitmproxy/contentviews/image/image_parser.py | 7 + mitmproxy/contrib/kaitaistruct/exif.py | 567 +--------------------- mitmproxy/contrib/kaitaistruct/exif_be.py | 571 +++++++++++++++++++++++ mitmproxy/contrib/kaitaistruct/exif_le.py | 571 +++++++++++++++++++++++ mitmproxy/contrib/kaitaistruct/jpeg.py | 15 + test/mitmproxy/contentviews/test_image_parser.py | 23 + test/mitmproxy/data/image_parser/app1.jpeg | Bin 0 -> 82670 bytes test/mitmproxy/data/image_parser/image-err1.jpg | Bin 0 -> 82674 bytes 8 files changed, 1196 insertions(+), 558 deletions(-) create mode 100644 mitmproxy/contrib/kaitaistruct/exif_be.py create mode 100644 mitmproxy/contrib/kaitaistruct/exif_le.py create mode 100644 test/mitmproxy/data/image_parser/app1.jpeg create mode 100644 test/mitmproxy/data/image_parser/image-err1.jpg diff --git a/mitmproxy/contentviews/image/image_parser.py b/mitmproxy/contentviews/image/image_parser.py index dd47c11d..bcae0566 100644 --- a/mitmproxy/contentviews/image/image_parser.py +++ b/mitmproxy/contentviews/image/image_parser.py @@ -72,4 +72,11 @@ def parse_jpeg(data: bytes) -> Metadata: parts.append(('jfif_unit', str(segment.data.density_units._value_))) if segment.marker._name_ == 'com': parts.append(('comment', str(segment.data))) + if segment.marker._name_ == 'app1': + try: + for field in segment.data.body.data.body.ifd0.fields: + if field.data is not None: + parts.append((field.tag._name_, field.data.decode('UTF-8').strip('\x00'))) + except AttributeError: + pass return parts diff --git a/mitmproxy/contrib/kaitaistruct/exif.py b/mitmproxy/contrib/kaitaistruct/exif.py index f2356f42..6236a708 100644 --- a/mitmproxy/contrib/kaitaistruct/exif.py +++ b/mitmproxy/contrib/kaitaistruct/exif.py @@ -1,4 +1,5 @@ # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild +# The source was exif.ksy from here - https://github.com/kaitai-io/kaitai_struct_formats/blob/24e2d00048b8084ceec30a187a79cb87a79a48ba/image/exif.ksy import array import struct @@ -8,566 +9,16 @@ from enum import Enum from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO +from .exif_le import ExifLe +from .exif_be import ExifBe class Exif(KaitaiStruct): def __init__(self, _io, _parent=None, _root=None): self._io = _io self._parent = _parent self._root = _root if _root else self - self.endianness = self._io.read_bytes(2) - self.version = self._io.read_u2be() - self.ifd0_ofs = self._io.read_u4be() - - class Ifd(KaitaiStruct): - def __init__(self, _io, _parent=None, _root=None): - self._io = _io - self._parent = _parent - self._root = _root if _root else self - self.num_fields = self._io.read_u2be() - self.fields = [None] * (self.num_fields) - for i in range(self.num_fields): - self.fields[i] = self._root.IfdField(self._io, self, self._root) - - self.next_ifd_ofs = self._io.read_u4be() - - @property - def next_ifd(self): - if hasattr(self, '_m_next_ifd'): - return self._m_next_ifd if hasattr(self, '_m_next_ifd') else None - - if self.next_ifd_ofs != 0: - _pos = self._io.pos() - self._io.seek(self.next_ifd_ofs) - self._m_next_ifd = self._root.Ifd(self._io, self, self._root) - self._io.seek(_pos) - - return self._m_next_ifd if hasattr(self, '_m_next_ifd') else None - - - class IfdField(KaitaiStruct): - - class FieldTypeEnum(Enum): - byte = 1 - ascii_string = 2 - word = 3 - dword = 4 - rational = 5 - - class TagEnum(Enum): - image_width = 256 - image_height = 257 - bits_per_sample = 258 - compression = 259 - photometric_interpretation = 262 - thresholding = 263 - cell_width = 264 - cell_length = 265 - fill_order = 266 - document_name = 269 - image_description = 270 - make = 271 - model = 272 - strip_offsets = 273 - orientation = 274 - samples_per_pixel = 277 - rows_per_strip = 278 - strip_byte_counts = 279 - min_sample_value = 280 - max_sample_value = 281 - x_resolution = 282 - y_resolution = 283 - planar_configuration = 284 - page_name = 285 - x_position = 286 - y_position = 287 - free_offsets = 288 - free_byte_counts = 289 - gray_response_unit = 290 - gray_response_curve = 291 - t4_options = 292 - t6_options = 293 - resolution_unit = 296 - page_number = 297 - color_response_unit = 300 - transfer_function = 301 - software = 305 - modify_date = 306 - artist = 315 - host_computer = 316 - predictor = 317 - white_point = 318 - primary_chromaticities = 319 - color_map = 320 - halftone_hints = 321 - tile_width = 322 - tile_length = 323 - tile_offsets = 324 - tile_byte_counts = 325 - bad_fax_lines = 326 - clean_fax_data = 327 - consecutive_bad_fax_lines = 328 - sub_ifd = 330 - ink_set = 332 - ink_names = 333 - numberof_inks = 334 - dot_range = 336 - target_printer = 337 - extra_samples = 338 - sample_format = 339 - s_min_sample_value = 340 - s_max_sample_value = 341 - transfer_range = 342 - clip_path = 343 - x_clip_path_units = 344 - y_clip_path_units = 345 - indexed = 346 - jpeg_tables = 347 - opi_proxy = 351 - global_parameters_ifd = 400 - profile_type = 401 - fax_profile = 402 - coding_methods = 403 - version_year = 404 - mode_number = 405 - decode = 433 - default_image_color = 434 - t82_options = 435 - jpeg_tables2 = 437 - jpeg_proc = 512 - thumbnail_offset = 513 - thumbnail_length = 514 - jpeg_restart_interval = 515 - jpeg_lossless_predictors = 517 - jpeg_point_transforms = 518 - jpegq_tables = 519 - jpegdc_tables = 520 - jpegac_tables = 521 - y_cb_cr_coefficients = 529 - y_cb_cr_sub_sampling = 530 - y_cb_cr_positioning = 531 - reference_black_white = 532 - strip_row_counts = 559 - application_notes = 700 - uspto_miscellaneous = 999 - related_image_file_format = 4096 - related_image_width = 4097 - related_image_height = 4098 - rating = 18246 - xp_dip_xml = 18247 - stitch_info = 18248 - rating_percent = 18249 - sony_raw_file_type = 28672 - light_falloff_params = 28722 - chromatic_aberration_corr_params = 28725 - distortion_corr_params = 28727 - image_id = 32781 - wang_tag1 = 32931 - wang_annotation = 32932 - wang_tag3 = 32933 - wang_tag4 = 32934 - image_reference_points = 32953 - region_xform_tack_point = 32954 - warp_quadrilateral = 32955 - affine_transform_mat = 32956 - matteing = 32995 - data_type = 32996 - image_depth = 32997 - tile_depth = 32998 - image_full_width = 33300 - image_full_height = 33301 - texture_format = 33302 - wrap_modes = 33303 - fov_cot = 33304 - matrix_world_to_screen = 33305 - matrix_world_to_camera = 33306 - model2 = 33405 - cfa_repeat_pattern_dim = 33421 - cfa_pattern2 = 33422 - battery_level = 33423 - kodak_ifd = 33424 - copyright = 33432 - exposure_time = 33434 - f_number = 33437 - md_file_tag = 33445 - md_scale_pixel = 33446 - md_color_table = 33447 - md_lab_name = 33448 - md_sample_info = 33449 - md_prep_date = 33450 - md_prep_time = 33451 - md_file_units = 33452 - pixel_scale = 33550 - advent_scale = 33589 - advent_revision = 33590 - uic1_tag = 33628 - uic2_tag = 33629 - uic3_tag = 33630 - uic4_tag = 33631 - iptc_naa = 33723 - intergraph_packet_data = 33918 - intergraph_flag_registers = 33919 - intergraph_matrix = 33920 - ingr_reserved = 33921 - model_tie_point = 33922 - site = 34016 - color_sequence = 34017 - it8_header = 34018 - raster_padding = 34019 - bits_per_run_length = 34020 - bits_per_extended_run_length = 34021 - color_table = 34022 - image_color_indicator = 34023 - background_color_indicator = 34024 - image_color_value = 34025 - background_color_value = 34026 - pixel_intensity_range = 34027 - transparency_indicator = 34028 - color_characterization = 34029 - hc_usage = 34030 - trap_indicator = 34031 - cmyk_equivalent = 34032 - sem_info = 34118 - afcp_iptc = 34152 - pixel_magic_jbig_options = 34232 - jpl_carto_ifd = 34263 - model_transform = 34264 - wb_grgb_levels = 34306 - leaf_data = 34310 - photoshop_settings = 34377 - exif_offset = 34665 - icc_profile = 34675 - tiff_fx_extensions = 34687 - multi_profiles = 34688 - shared_data = 34689 - t88_options = 34690 - image_layer = 34732 - geo_tiff_directory = 34735 - geo_tiff_double_params = 34736 - geo_tiff_ascii_params = 34737 - jbig_options = 34750 - exposure_program = 34850 - spectral_sensitivity = 34852 - gps_info = 34853 - iso = 34855 - opto_electric_conv_factor = 34856 - interlace = 34857 - time_zone_offset = 34858 - self_timer_mode = 34859 - sensitivity_type = 34864 - standard_output_sensitivity = 34865 - recommended_exposure_index = 34866 - iso_speed = 34867 - iso_speed_latitudeyyy = 34868 - iso_speed_latitudezzz = 34869 - fax_recv_params = 34908 - fax_sub_address = 34909 - fax_recv_time = 34910 - fedex_edr = 34929 - leaf_sub_ifd = 34954 - exif_version = 36864 - date_time_original = 36867 - create_date = 36868 - google_plus_upload_code = 36873 - offset_time = 36880 - offset_time_original = 36881 - offset_time_digitized = 36882 - components_configuration = 37121 - compressed_bits_per_pixel = 37122 - shutter_speed_value = 37377 - aperture_value = 37378 - brightness_value = 37379 - exposure_compensation = 37380 - max_aperture_value = 37381 - subject_distance = 37382 - metering_mode = 37383 - light_source = 37384 - flash = 37385 - focal_length = 37386 - flash_energy = 37387 - spatial_frequency_response = 37388 - noise = 37389 - focal_plane_x_resolution = 37390 - focal_plane_y_resolution = 37391 - focal_plane_resolution_unit = 37392 - image_number = 37393 - security_classification = 37394 - image_history = 37395 - subject_area = 37396 - exposure_index = 37397 - tiff_ep_standard_id = 37398 - sensing_method = 37399 - cip3_data_file = 37434 - cip3_sheet = 37435 - cip3_side = 37436 - sto_nits = 37439 - maker_note = 37500 - user_comment = 37510 - sub_sec_time = 37520 - sub_sec_time_original = 37521 - sub_sec_time_digitized = 37522 - ms_document_text = 37679 - ms_property_set_storage = 37680 - ms_document_text_position = 37681 - image_source_data = 37724 - ambient_temperature = 37888 - humidity = 37889 - pressure = 37890 - water_depth = 37891 - acceleration = 37892 - camera_elevation_angle = 37893 - xp_title = 40091 - xp_comment = 40092 - xp_author = 40093 - xp_keywords = 40094 - xp_subject = 40095 - flashpix_version = 40960 - color_space = 40961 - exif_image_width = 40962 - exif_image_height = 40963 - related_sound_file = 40964 - interop_offset = 40965 - samsung_raw_pointers_offset = 40976 - samsung_raw_pointers_length = 40977 - samsung_raw_byte_order = 41217 - samsung_raw_unknown = 41218 - flash_energy2 = 41483 - spatial_frequency_response2 = 41484 - noise2 = 41485 - focal_plane_x_resolution2 = 41486 - focal_plane_y_resolution2 = 41487 - focal_plane_resolution_unit2 = 41488 - image_number2 = 41489 - security_classification2 = 41490 - image_history2 = 41491 - subject_location = 41492 - exposure_index2 = 41493 - tiff_ep_standard_id2 = 41494 - sensing_method2 = 41495 - file_source = 41728 - scene_type = 41729 - cfa_pattern = 41730 - custom_rendered = 41985 - exposure_mode = 41986 - white_balance = 41987 - digital_zoom_ratio = 41988 - focal_length_in35mm_format = 41989 - scene_capture_type = 41990 - gain_control = 41991 - contrast = 41992 - saturation = 41993 - sharpness = 41994 - device_setting_description = 41995 - subject_distance_range = 41996 - image_unique_id = 42016 - owner_name = 42032 - serial_number = 42033 - lens_info = 42034 - lens_make = 42035 - lens_model = 42036 - lens_serial_number = 42037 - gdal_metadata = 42112 - gdal_no_data = 42113 - gamma = 42240 - expand_software = 44992 - expand_lens = 44993 - expand_film = 44994 - expand_filter_lens = 44995 - expand_scanner = 44996 - expand_flash_lamp = 44997 - pixel_format = 48129 - transformation = 48130 - uncompressed = 48131 - image_type = 48132 - image_width2 = 48256 - image_height2 = 48257 - width_resolution = 48258 - height_resolution = 48259 - image_offset = 48320 - image_byte_count = 48321 - alpha_offset = 48322 - alpha_byte_count = 48323 - image_data_discard = 48324 - alpha_data_discard = 48325 - oce_scanjob_desc = 50215 - oce_application_selector = 50216 - oce_id_number = 50217 - oce_image_logic = 50218 - annotations = 50255 - print_im = 50341 - original_file_name = 50547 - uspto_original_content_type = 50560 - dng_version = 50706 - dng_backward_version = 50707 - unique_camera_model = 50708 - localized_camera_model = 50709 - cfa_plane_color = 50710 - cfa_layout = 50711 - linearization_table = 50712 - black_level_repeat_dim = 50713 - black_level = 50714 - black_level_delta_h = 50715 - black_level_delta_v = 50716 - white_level = 50717 - default_scale = 50718 - default_crop_origin = 50719 - default_crop_size = 50720 - color_matrix1 = 50721 - color_matrix2 = 50722 - camera_calibration1 = 50723 - camera_calibration2 = 50724 - reduction_matrix1 = 50725 - reduction_matrix2 = 50726 - analog_balance = 50727 - as_shot_neutral = 50728 - as_shot_white_xy = 50729 - baseline_exposure = 50730 - baseline_noise = 50731 - baseline_sharpness = 50732 - bayer_green_split = 50733 - linear_response_limit = 50734 - camera_serial_number = 50735 - dng_lens_info = 50736 - chroma_blur_radius = 50737 - anti_alias_strength = 50738 - shadow_scale = 50739 - sr2_private = 50740 - maker_note_safety = 50741 - raw_image_segmentation = 50752 - calibration_illuminant1 = 50778 - calibration_illuminant2 = 50779 - best_quality_scale = 50780 - raw_data_unique_id = 50781 - alias_layer_metadata = 50784 - original_raw_file_name = 50827 - original_raw_file_data = 50828 - active_area = 50829 - masked_areas = 50830 - as_shot_icc_profile = 50831 - as_shot_pre_profile_matrix = 50832 - current_icc_profile = 50833 - current_pre_profile_matrix = 50834 - colorimetric_reference = 50879 - s_raw_type = 50885 - panasonic_title = 50898 - panasonic_title2 = 50899 - camera_calibration_sig = 50931 - profile_calibration_sig = 50932 - profile_ifd = 50933 - as_shot_profile_name = 50934 - noise_reduction_applied = 50935 - profile_name = 50936 - profile_hue_sat_map_dims = 50937 - profile_hue_sat_map_data1 = 50938 - profile_hue_sat_map_data2 = 50939 - profile_tone_curve = 50940 - profile_embed_policy = 50941 - profile_copyright = 50942 - forward_matrix1 = 50964 - forward_matrix2 = 50965 - preview_application_name = 50966 - preview_application_version = 50967 - preview_settings_name = 50968 - preview_settings_digest = 50969 - preview_color_space = 50970 - preview_date_time = 50971 - raw_image_digest = 50972 - original_raw_file_digest = 50973 - sub_tile_block_size = 50974 - row_interleave_factor = 50975 - profile_look_table_dims = 50981 - profile_look_table_data = 50982 - opcode_list1 = 51008 - opcode_list2 = 51009 - opcode_list3 = 51022 - noise_profile = 51041 - time_codes = 51043 - frame_rate = 51044 - t_stop = 51058 - reel_name = 51081 - original_default_final_size = 51089 - original_best_quality_size = 51090 - original_default_crop_size = 51091 - camera_label = 51105 - profile_hue_sat_map_encoding = 51107 - profile_look_table_encoding = 51108 - baseline_exposure_offset = 51109 - default_black_render = 51110 - new_raw_image_digest = 51111 - raw_to_preview_gain = 51112 - default_user_crop = 51125 - padding = 59932 - offset_schema = 59933 - owner_name2 = 65000 - serial_number2 = 65001 - lens = 65002 - kdc_ifd = 65024 - raw_file = 65100 - converter = 65101 - white_balance2 = 65102 - exposure = 65105 - shadows = 65106 - brightness = 65107 - contrast2 = 65108 - saturation2 = 65109 - sharpness2 = 65110 - smoothness = 65111 - moire_filter = 65112 - def __init__(self, _io, _parent=None, _root=None): - self._io = _io - self._parent = _parent - self._root = _root if _root else self - self.tag = self._root.IfdField.TagEnum(self._io.read_u2be()) - self.field_type = self._root.IfdField.FieldTypeEnum(self._io.read_u2be()) - self.length = self._io.read_u4be() - self.ofs_or_data = self._io.read_u4be() - - @property - def type_byte_length(self): - if hasattr(self, '_m_type_byte_length'): - return self._m_type_byte_length if hasattr(self, '_m_type_byte_length') else None - - self._m_type_byte_length = (2 if self.field_type == self._root.IfdField.FieldTypeEnum.word else (4 if self.field_type == self._root.IfdField.FieldTypeEnum.dword else 1)) - return self._m_type_byte_length if hasattr(self, '_m_type_byte_length') else None - - @property - def byte_length(self): - if hasattr(self, '_m_byte_length'): - return self._m_byte_length if hasattr(self, '_m_byte_length') else None - - self._m_byte_length = (self.length * self.type_byte_length) - return self._m_byte_length if hasattr(self, '_m_byte_length') else None - - @property - def is_immediate_data(self): - if hasattr(self, '_m_is_immediate_data'): - return self._m_is_immediate_data if hasattr(self, '_m_is_immediate_data') else None - - self._m_is_immediate_data = self.byte_length <= 4 - return self._m_is_immediate_data if hasattr(self, '_m_is_immediate_data') else None - - @property - def data(self): - if hasattr(self, '_m_data'): - return self._m_data if hasattr(self, '_m_data') else None - - if not self.is_immediate_data: - io = self._root._io - _pos = io.pos() - io.seek(self.ofs_or_data) - self._m_data = io.read_bytes(self.byte_length) - io.seek(_pos) - - return self._m_data if hasattr(self, '_m_data') else None - - - @property - def ifd0(self): - if hasattr(self, '_m_ifd0'): - return self._m_ifd0 if hasattr(self, '_m_ifd0') else None - - _pos = self._io.pos() - self._io.seek(self.ifd0_ofs) - self._m_ifd0 = self._root.Ifd(self._io, self, self._root) - self._io.seek(_pos) - return self._m_ifd0 if hasattr(self, '_m_ifd0') else None - - + self.endianness = self._io.read_u2le() + _on = self.endianness + if _on == 18761: + self.body = ExifLe(self._io) + elif _on == 19789: + self.body = ExifBe(self._io) diff --git a/mitmproxy/contrib/kaitaistruct/exif_be.py b/mitmproxy/contrib/kaitaistruct/exif_be.py new file mode 100644 index 00000000..7980a9e8 --- /dev/null +++ b/mitmproxy/contrib/kaitaistruct/exif_be.py @@ -0,0 +1,571 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild +# The source was exif_be.ksy from here - https://github.com/kaitai-io/kaitai_struct_formats/blob/24e2d00048b8084ceec30a187a79cb87a79a48ba/image/exif_be.ksy + +import array +import struct +import zlib +from enum import Enum + +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO + + +class ExifBe(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.version = self._io.read_u2be() + self.ifd0_ofs = self._io.read_u4be() + + class Ifd(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.num_fields = self._io.read_u2be() + self.fields = [None] * (self.num_fields) + for i in range(self.num_fields): + self.fields[i] = self._root.IfdField(self._io, self, self._root) + + self.next_ifd_ofs = self._io.read_u4be() + + @property + def next_ifd(self): + if hasattr(self, '_m_next_ifd'): + return self._m_next_ifd if hasattr(self, '_m_next_ifd') else None + + if self.next_ifd_ofs != 0: + _pos = self._io.pos() + self._io.seek(self.next_ifd_ofs) + self._m_next_ifd = self._root.Ifd(self._io, self, self._root) + self._io.seek(_pos) + + return self._m_next_ifd if hasattr(self, '_m_next_ifd') else None + + + class IfdField(KaitaiStruct): + + class FieldTypeEnum(Enum): + byte = 1 + ascii_string = 2 + word = 3 + dword = 4 + rational = 5 + + class TagEnum(Enum): + image_width = 256 + image_height = 257 + bits_per_sample = 258 + compression = 259 + photometric_interpretation = 262 + thresholding = 263 + cell_width = 264 + cell_length = 265 + fill_order = 266 + document_name = 269 + image_description = 270 + make = 271 + model = 272 + strip_offsets = 273 + orientation = 274 + samples_per_pixel = 277 + rows_per_strip = 278 + strip_byte_counts = 279 + min_sample_value = 280 + max_sample_value = 281 + x_resolution = 282 + y_resolution = 283 + planar_configuration = 284 + page_name = 285 + x_position = 286 + y_position = 287 + free_offsets = 288 + free_byte_counts = 289 + gray_response_unit = 290 + gray_response_curve = 291 + t4_options = 292 + t6_options = 293 + resolution_unit = 296 + page_number = 297 + color_response_unit = 300 + transfer_function = 301 + software = 305 + modify_date = 306 + artist = 315 + host_computer = 316 + predictor = 317 + white_point = 318 + primary_chromaticities = 319 + color_map = 320 + halftone_hints = 321 + tile_width = 322 + tile_length = 323 + tile_offsets = 324 + tile_byte_counts = 325 + bad_fax_lines = 326 + clean_fax_data = 327 + consecutive_bad_fax_lines = 328 + sub_ifd = 330 + ink_set = 332 + ink_names = 333 + numberof_inks = 334 + dot_range = 336 + target_printer = 337 + extra_samples = 338 + sample_format = 339 + s_min_sample_value = 340 + s_max_sample_value = 341 + transfer_range = 342 + clip_path = 343 + x_clip_path_units = 344 + y_clip_path_units = 345 + indexed = 346 + jpeg_tables = 347 + opi_proxy = 351 + global_parameters_ifd = 400 + profile_type = 401 + fax_profile = 402 + coding_methods = 403 + version_year = 404 + mode_number = 405 + decode = 433 + default_image_color = 434 + t82_options = 435 + jpeg_tables2 = 437 + jpeg_proc = 512 + thumbnail_offset = 513 + thumbnail_length = 514 + jpeg_restart_interval = 515 + jpeg_lossless_predictors = 517 + jpeg_point_transforms = 518 + jpegq_tables = 519 + jpegdc_tables = 520 + jpegac_tables = 521 + y_cb_cr_coefficients = 529 + y_cb_cr_sub_sampling = 530 + y_cb_cr_positioning = 531 + reference_black_white = 532 + strip_row_counts = 559 + application_notes = 700 + uspto_miscellaneous = 999 + related_image_file_format = 4096 + related_image_width = 4097 + related_image_height = 4098 + rating = 18246 + xp_dip_xml = 18247 + stitch_info = 18248 + rating_percent = 18249 + sony_raw_file_type = 28672 + light_falloff_params = 28722 + chromatic_aberration_corr_params = 28725 + distortion_corr_params = 28727 + image_id = 32781 + wang_tag1 = 32931 + wang_annotation = 32932 + wang_tag3 = 32933 + wang_tag4 = 32934 + image_reference_points = 32953 + region_xform_tack_point = 32954 + warp_quadrilateral = 32955 + affine_transform_mat = 32956 + matteing = 32995 + data_type = 32996 + image_depth = 32997 + tile_depth = 32998 + image_full_width = 33300 + image_full_height = 33301 + texture_format = 33302 + wrap_modes = 33303 + fov_cot = 33304 + matrix_world_to_screen = 33305 + matrix_world_to_camera = 33306 + model2 = 33405 + cfa_repeat_pattern_dim = 33421 + cfa_pattern2 = 33422 + battery_level = 33423 + kodak_ifd = 33424 + copyright = 33432 + exposure_time = 33434 + f_number = 33437 + md_file_tag = 33445 + md_scale_pixel = 33446 + md_color_table = 33447 + md_lab_name = 33448 + md_sample_info = 33449 + md_prep_date = 33450 + md_prep_time = 33451 + md_file_units = 33452 + pixel_scale = 33550 + advent_scale = 33589 + advent_revision = 33590 + uic1_tag = 33628 + uic2_tag = 33629 + uic3_tag = 33630 + uic4_tag = 33631 + iptc_naa = 33723 + intergraph_packet_data = 33918 + intergraph_flag_registers = 33919 + intergraph_matrix = 33920 + ingr_reserved = 33921 + model_tie_point = 33922 + site = 34016 + color_sequence = 34017 + it8_header = 34018 + raster_padding = 34019 + bits_per_run_length = 34020 + bits_per_extended_run_length = 34021 + color_table = 34022 + image_color_indicator = 34023 + background_color_indicator = 34024 + image_color_value = 34025 + background_color_value = 34026 + pixel_intensity_range = 34027 + transparency_indicator = 34028 + color_characterization = 34029 + hc_usage = 34030 + trap_indicator = 34031 + cmyk_equivalent = 34032 + sem_info = 34118 + afcp_iptc = 34152 + pixel_magic_jbig_options = 34232 + jpl_carto_ifd = 34263 + model_transform = 34264 + wb_grgb_levels = 34306 + leaf_data = 34310 + photoshop_settings = 34377 + exif_offset = 34665 + icc_profile = 34675 + tiff_fx_extensions = 34687 + multi_profiles = 34688 + shared_data = 34689 + t88_options = 34690 + image_layer = 34732 + geo_tiff_directory = 34735 + geo_tiff_double_params = 34736 + geo_tiff_ascii_params = 34737 + jbig_options = 34750 + exposure_program = 34850 + spectral_sensitivity = 34852 + gps_info = 34853 + iso = 34855 + opto_electric_conv_factor = 34856 + interlace = 34857 + time_zone_offset = 34858 + self_timer_mode = 34859 + sensitivity_type = 34864 + standard_output_sensitivity = 34865 + recommended_exposure_index = 34866 + iso_speed = 34867 + iso_speed_latitudeyyy = 34868 + iso_speed_latitudezzz = 34869 + fax_recv_params = 34908 + fax_sub_address = 34909 + fax_recv_time = 34910 + fedex_edr = 34929 + leaf_sub_ifd = 34954 + exif_version = 36864 + date_time_original = 36867 + create_date = 36868 + google_plus_upload_code = 36873 + offset_time = 36880 + offset_time_original = 36881 + offset_time_digitized = 36882 + components_configuration = 37121 + compressed_bits_per_pixel = 37122 + shutter_speed_value = 37377 + aperture_value = 37378 + brightness_value = 37379 + exposure_compensation = 37380 + max_aperture_value = 37381 + subject_distance = 37382 + metering_mode = 37383 + light_source = 37384 + flash = 37385 + focal_length = 37386 + flash_energy = 37387 + spatial_frequency_response = 37388 + noise = 37389 + focal_plane_x_resolution = 37390 + focal_plane_y_resolution = 37391 + focal_plane_resolution_unit = 37392 + image_number = 37393 + security_classification = 37394 + image_history = 37395 + subject_area = 37396 + exposure_index = 37397 + tiff_ep_standard_id = 37398 + sensing_method = 37399 + cip3_data_file = 37434 + cip3_sheet = 37435 + cip3_side = 37436 + sto_nits = 37439 + maker_note = 37500 + user_comment = 37510 + sub_sec_time = 37520 + sub_sec_time_original = 37521 + sub_sec_time_digitized = 37522 + ms_document_text = 37679 + ms_property_set_storage = 37680 + ms_document_text_position = 37681 + image_source_data = 37724 + ambient_temperature = 37888 + humidity = 37889 + pressure = 37890 + water_depth = 37891 + acceleration = 37892 + camera_elevation_angle = 37893 + xp_title = 40091 + xp_comment = 40092 + xp_author = 40093 + xp_keywords = 40094 + xp_subject = 40095 + flashpix_version = 40960 + color_space = 40961 + exif_image_width = 40962 + exif_image_height = 40963 + related_sound_file = 40964 + interop_offset = 40965 + samsung_raw_pointers_offset = 40976 + samsung_raw_pointers_length = 40977 + samsung_raw_byte_order = 41217 + samsung_raw_unknown = 41218 + flash_energy2 = 41483 + spatial_frequency_response2 = 41484 + noise2 = 41485 + focal_plane_x_resolution2 = 41486 + focal_plane_y_resolution2 = 41487 + focal_plane_resolution_unit2 = 41488 + image_number2 = 41489 + security_classification2 = 41490 + image_history2 = 41491 + subject_location = 41492 + exposure_index2 = 41493 + tiff_ep_standard_id2 = 41494 + sensing_method2 = 41495 + file_source = 41728 + scene_type = 41729 + cfa_pattern = 41730 + custom_rendered = 41985 + exposure_mode = 41986 + white_balance = 41987 + digital_zoom_ratio = 41988 + focal_length_in35mm_format = 41989 + scene_capture_type = 41990 + gain_control = 41991 + contrast = 41992 + saturation = 41993 + sharpness = 41994 + device_setting_description = 41995 + subject_distance_range = 41996 + image_unique_id = 42016 + owner_name = 42032 + serial_number = 42033 + lens_info = 42034 + lens_make = 42035 + lens_model = 42036 + lens_serial_number = 42037 + gdal_metadata = 42112 + gdal_no_data = 42113 + gamma = 42240 + expand_software = 44992 + expand_lens = 44993 + expand_film = 44994 + expand_filter_lens = 44995 + expand_scanner = 44996 + expand_flash_lamp = 44997 + pixel_format = 48129 + transformation = 48130 + uncompressed = 48131 + image_type = 48132 + image_width2 = 48256 + image_height2 = 48257 + width_resolution = 48258 + height_resolution = 48259 + image_offset = 48320 + image_byte_count = 48321 + alpha_offset = 48322 + alpha_byte_count = 48323 + image_data_discard = 48324 + alpha_data_discard = 48325 + oce_scanjob_desc = 50215 + oce_application_selector = 50216 + oce_id_number = 50217 + oce_image_logic = 50218 + annotations = 50255 + print_im = 50341 + original_file_name = 50547 + uspto_original_content_type = 50560 + dng_version = 50706 + dng_backward_version = 50707 + unique_camera_model = 50708 + localized_camera_model = 50709 + cfa_plane_color = 50710 + cfa_layout = 50711 + linearization_table = 50712 + black_level_repeat_dim = 50713 + black_level = 50714 + black_level_delta_h = 50715 + black_level_delta_v = 50716 + white_level = 50717 + default_scale = 50718 + default_crop_origin = 50719 + default_crop_size = 50720 + color_matrix1 = 50721 + color_matrix2 = 50722 + camera_calibration1 = 50723 + camera_calibration2 = 50724 + reduction_matrix1 = 50725 + reduction_matrix2 = 50726 + analog_balance = 50727 + as_shot_neutral = 50728 + as_shot_white_xy = 50729 + baseline_exposure = 50730 + baseline_noise = 50731 + baseline_sharpness = 50732 + bayer_green_split = 50733 + linear_response_limit = 50734 + camera_serial_number = 50735 + dng_lens_info = 50736 + chroma_blur_radius = 50737 + anti_alias_strength = 50738 + shadow_scale = 50739 + sr2_private = 50740 + maker_note_safety = 50741 + raw_image_segmentation = 50752 + calibration_illuminant1 = 50778 + calibration_illuminant2 = 50779 + best_quality_scale = 50780 + raw_data_unique_id = 50781 + alias_layer_metadata = 50784 + original_raw_file_name = 50827 + original_raw_file_data = 50828 + active_area = 50829 + masked_areas = 50830 + as_shot_icc_profile = 50831 + as_shot_pre_profile_matrix = 50832 + current_icc_profile = 50833 + current_pre_profile_matrix = 50834 + colorimetric_reference = 50879 + s_raw_type = 50885 + panasonic_title = 50898 + panasonic_title2 = 50899 + camera_calibration_sig = 50931 + profile_calibration_sig = 50932 + profile_ifd = 50933 + as_shot_profile_name = 50934 + noise_reduction_applied = 50935 + profile_name = 50936 + profile_hue_sat_map_dims = 50937 + profile_hue_sat_map_data1 = 50938 + profile_hue_sat_map_data2 = 50939 + profile_tone_curve = 50940 + profile_embed_policy = 50941 + profile_copyright = 50942 + forward_matrix1 = 50964 + forward_matrix2 = 50965 + preview_application_name = 50966 + preview_application_version = 50967 + preview_settings_name = 50968 + preview_settings_digest = 50969 + preview_color_space = 50970 + preview_date_time = 50971 + raw_image_digest = 50972 + original_raw_file_digest = 50973 + sub_tile_block_size = 50974 + row_interleave_factor = 50975 + profile_look_table_dims = 50981 + profile_look_table_data = 50982 + opcode_list1 = 51008 + opcode_list2 = 51009 + opcode_list3 = 51022 + noise_profile = 51041 + time_codes = 51043 + frame_rate = 51044 + t_stop = 51058 + reel_name = 51081 + original_default_final_size = 51089 + original_best_quality_size = 51090 + original_default_crop_size = 51091 + camera_label = 51105 + profile_hue_sat_map_encoding = 51107 + profile_look_table_encoding = 51108 + baseline_exposure_offset = 51109 + default_black_render = 51110 + new_raw_image_digest = 51111 + raw_to_preview_gain = 51112 + default_user_crop = 51125 + padding = 59932 + offset_schema = 59933 + owner_name2 = 65000 + serial_number2 = 65001 + lens = 65002 + kdc_ifd = 65024 + raw_file = 65100 + converter = 65101 + white_balance2 = 65102 + exposure = 65105 + shadows = 65106 + brightness = 65107 + contrast2 = 65108 + saturation2 = 65109 + sharpness2 = 65110 + smoothness = 65111 + moire_filter = 65112 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.tag = self._root.IfdField.TagEnum(self._io.read_u2be()) + self.field_type = self._root.IfdField.FieldTypeEnum(self._io.read_u2be()) + self.length = self._io.read_u4be() + self.ofs_or_data = self._io.read_u4be() + + @property + def type_byte_length(self): + if hasattr(self, '_m_type_byte_length'): + return self._m_type_byte_length if hasattr(self, '_m_type_byte_length') else None + + self._m_type_byte_length = (2 if self.field_type == self._root.IfdField.FieldTypeEnum.word else (4 if self.field_type == self._root.IfdField.FieldTypeEnum.dword else 1)) + return self._m_type_byte_length if hasattr(self, '_m_type_byte_length') else None + + @property + def byte_length(self): + if hasattr(self, '_m_byte_length'): + return self._m_byte_length if hasattr(self, '_m_byte_length') else None + + self._m_byte_length = (self.length * self.type_byte_length) + return self._m_byte_length if hasattr(self, '_m_byte_length') else None + + @property + def is_immediate_data(self): + if hasattr(self, '_m_is_immediate_data'): + return self._m_is_immediate_data if hasattr(self, '_m_is_immediate_data') else None + + self._m_is_immediate_data = self.byte_length <= 4 + return self._m_is_immediate_data if hasattr(self, '_m_is_immediate_data') else None + + @property + def data(self): + if hasattr(self, '_m_data'): + return self._m_data if hasattr(self, '_m_data') else None + + if not self.is_immediate_data: + io = self._root._io + _pos = io.pos() + io.seek(self.ofs_or_data) + self._m_data = io.read_bytes(self.byte_length) + io.seek(_pos) + + return self._m_data if hasattr(self, '_m_data') else None + + + @property + def ifd0(self): + if hasattr(self, '_m_ifd0'): + return self._m_ifd0 if hasattr(self, '_m_ifd0') else None + + _pos = self._io.pos() + self._io.seek(self.ifd0_ofs) + self._m_ifd0 = self._root.Ifd(self._io, self, self._root) + self._io.seek(_pos) + return self._m_ifd0 if hasattr(self, '_m_ifd0') else None diff --git a/mitmproxy/contrib/kaitaistruct/exif_le.py b/mitmproxy/contrib/kaitaistruct/exif_le.py new file mode 100644 index 00000000..207b3beb --- /dev/null +++ b/mitmproxy/contrib/kaitaistruct/exif_le.py @@ -0,0 +1,571 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild +# The source was exif_le.ksy from here - https://github.com/kaitai-io/kaitai_struct_formats/blob/24e2d00048b8084ceec30a187a79cb87a79a48ba/image/exif_le.ksy + +import array +import struct +import zlib +from enum import Enum + +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO + + +class ExifLe(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.version = self._io.read_u2le() + self.ifd0_ofs = self._io.read_u4le() + + class Ifd(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.num_fields = self._io.read_u2le() + self.fields = [None] * (self.num_fields) + for i in range(self.num_fields): + self.fields[i] = self._root.IfdField(self._io, self, self._root) + + self.next_ifd_ofs = self._io.read_u4le() + + @property + def next_ifd(self): + if hasattr(self, '_m_next_ifd'): + return self._m_next_ifd if hasattr(self, '_m_next_ifd') else None + + if self.next_ifd_ofs != 0: + _pos = self._io.pos() + self._io.seek(self.next_ifd_ofs) + self._m_next_ifd = self._root.Ifd(self._io, self, self._root) + self._io.seek(_pos) + + return self._m_next_ifd if hasattr(self, '_m_next_ifd') else None + + + class IfdField(KaitaiStruct): + + class FieldTypeEnum(Enum): + byte = 1 + ascii_string = 2 + word = 3 + dword = 4 + rational = 5 + + class TagEnum(Enum): + image_width = 256 + image_height = 257 + bits_per_sample = 258 + compression = 259 + photometric_interpretation = 262 + thresholding = 263 + cell_width = 264 + cell_length = 265 + fill_order = 266 + document_name = 269 + image_description = 270 + make = 271 + model = 272 + strip_offsets = 273 + orientation = 274 + samples_per_pixel = 277 + rows_per_strip = 278 + strip_byte_counts = 279 + min_sample_value = 280 + max_sample_value = 281 + x_resolution = 282 + y_resolution = 283 + planar_configuration = 284 + page_name = 285 + x_position = 286 + y_position = 287 + free_offsets = 288 + free_byte_counts = 289 + gray_response_unit = 290 + gray_response_curve = 291 + t4_options = 292 + t6_options = 293 + resolution_unit = 296 + page_number = 297 + color_response_unit = 300 + transfer_function = 301 + software = 305 + modify_date = 306 + artist = 315 + host_computer = 316 + predictor = 317 + white_point = 318 + primary_chromaticities = 319 + color_map = 320 + halftone_hints = 321 + tile_width = 322 + tile_length = 323 + tile_offsets = 324 + tile_byte_counts = 325 + bad_fax_lines = 326 + clean_fax_data = 327 + consecutive_bad_fax_lines = 328 + sub_ifd = 330 + ink_set = 332 + ink_names = 333 + numberof_inks = 334 + dot_range = 336 + target_printer = 337 + extra_samples = 338 + sample_format = 339 + s_min_sample_value = 340 + s_max_sample_value = 341 + transfer_range = 342 + clip_path = 343 + x_clip_path_units = 344 + y_clip_path_units = 345 + indexed = 346 + jpeg_tables = 347 + opi_proxy = 351 + global_parameters_ifd = 400 + profile_type = 401 + fax_profile = 402 + coding_methods = 403 + version_year = 404 + mode_number = 405 + decode = 433 + default_image_color = 434 + t82_options = 435 + jpeg_tables2 = 437 + jpeg_proc = 512 + thumbnail_offset = 513 + thumbnail_length = 514 + jpeg_restart_interval = 515 + jpeg_lossless_predictors = 517 + jpeg_point_transforms = 518 + jpegq_tables = 519 + jpegdc_tables = 520 + jpegac_tables = 521 + y_cb_cr_coefficients = 529 + y_cb_cr_sub_sampling = 530 + y_cb_cr_positioning = 531 + reference_black_white = 532 + strip_row_counts = 559 + application_notes = 700 + uspto_miscellaneous = 999 + related_image_file_format = 4096 + related_image_width = 4097 + related_image_height = 4098 + rating = 18246 + xp_dip_xml = 18247 + stitch_info = 18248 + rating_percent = 18249 + sony_raw_file_type = 28672 + light_falloff_params = 28722 + chromatic_aberration_corr_params = 28725 + distortion_corr_params = 28727 + image_id = 32781 + wang_tag1 = 32931 + wang_annotation = 32932 + wang_tag3 = 32933 + wang_tag4 = 32934 + image_reference_points = 32953 + region_xform_tack_point = 32954 + warp_quadrilateral = 32955 + affine_transform_mat = 32956 + matteing = 32995 + data_type = 32996 + image_depth = 32997 + tile_depth = 32998 + image_full_width = 33300 + image_full_height = 33301 + texture_format = 33302 + wrap_modes = 33303 + fov_cot = 33304 + matrix_world_to_screen = 33305 + matrix_world_to_camera = 33306 + model2 = 33405 + cfa_repeat_pattern_dim = 33421 + cfa_pattern2 = 33422 + battery_level = 33423 + kodak_ifd = 33424 + copyright = 33432 + exposure_time = 33434 + f_number = 33437 + md_file_tag = 33445 + md_scale_pixel = 33446 + md_color_table = 33447 + md_lab_name = 33448 + md_sample_info = 33449 + md_prep_date = 33450 + md_prep_time = 33451 + md_file_units = 33452 + pixel_scale = 33550 + advent_scale = 33589 + advent_revision = 33590 + uic1_tag = 33628 + uic2_tag = 33629 + uic3_tag = 33630 + uic4_tag = 33631 + iptc_naa = 33723 + intergraph_packet_data = 33918 + intergraph_flag_registers = 33919 + intergraph_matrix = 33920 + ingr_reserved = 33921 + model_tie_point = 33922 + site = 34016 + color_sequence = 34017 + it8_header = 34018 + raster_padding = 34019 + bits_per_run_length = 34020 + bits_per_extended_run_length = 34021 + color_table = 34022 + image_color_indicator = 34023 + background_color_indicator = 34024 + image_color_value = 34025 + background_color_value = 34026 + pixel_intensity_range = 34027 + transparency_indicator = 34028 + color_characterization = 34029 + hc_usage = 34030 + trap_indicator = 34031 + cmyk_equivalent = 34032 + sem_info = 34118 + afcp_iptc = 34152 + pixel_magic_jbig_options = 34232 + jpl_carto_ifd = 34263 + model_transform = 34264 + wb_grgb_levels = 34306 + leaf_data = 34310 + photoshop_settings = 34377 + exif_offset = 34665 + icc_profile = 34675 + tiff_fx_extensions = 34687 + multi_profiles = 34688 + shared_data = 34689 + t88_options = 34690 + image_layer = 34732 + geo_tiff_directory = 34735 + geo_tiff_double_params = 34736 + geo_tiff_ascii_params = 34737 + jbig_options = 34750 + exposure_program = 34850 + spectral_sensitivity = 34852 + gps_info = 34853 + iso = 34855 + opto_electric_conv_factor = 34856 + interlace = 34857 + time_zone_offset = 34858 + self_timer_mode = 34859 + sensitivity_type = 34864 + standard_output_sensitivity = 34865 + recommended_exposure_index = 34866 + iso_speed = 34867 + iso_speed_latitudeyyy = 34868 + iso_speed_latitudezzz = 34869 + fax_recv_params = 34908 + fax_sub_address = 34909 + fax_recv_time = 34910 + fedex_edr = 34929 + leaf_sub_ifd = 34954 + exif_version = 36864 + date_time_original = 36867 + create_date = 36868 + google_plus_upload_code = 36873 + offset_time = 36880 + offset_time_original = 36881 + offset_time_digitized = 36882 + components_configuration = 37121 + compressed_bits_per_pixel = 37122 + shutter_speed_value = 37377 + aperture_value = 37378 + brightness_value = 37379 + exposure_compensation = 37380 + max_aperture_value = 37381 + subject_distance = 37382 + metering_mode = 37383 + light_source = 37384 + flash = 37385 + focal_length = 37386 + flash_energy = 37387 + spatial_frequency_response = 37388 + noise = 37389 + focal_plane_x_resolution = 37390 + focal_plane_y_resolution = 37391 + focal_plane_resolution_unit = 37392 + image_number = 37393 + security_classification = 37394 + image_history = 37395 + subject_area = 37396 + exposure_index = 37397 + tiff_ep_standard_id = 37398 + sensing_method = 37399 + cip3_data_file = 37434 + cip3_sheet = 37435 + cip3_side = 37436 + sto_nits = 37439 + maker_note = 37500 + user_comment = 37510 + sub_sec_time = 37520 + sub_sec_time_original = 37521 + sub_sec_time_digitized = 37522 + ms_document_text = 37679 + ms_property_set_storage = 37680 + ms_document_text_position = 37681 + image_source_data = 37724 + ambient_temperature = 37888 + humidity = 37889 + pressure = 37890 + water_depth = 37891 + acceleration = 37892 + camera_elevation_angle = 37893 + xp_title = 40091 + xp_comment = 40092 + xp_author = 40093 + xp_keywords = 40094 + xp_subject = 40095 + flashpix_version = 40960 + color_space = 40961 + exif_image_width = 40962 + exif_image_height = 40963 + related_sound_file = 40964 + interop_offset = 40965 + samsung_raw_pointers_offset = 40976 + samsung_raw_pointers_length = 40977 + samsung_raw_byte_order = 41217 + samsung_raw_unknown = 41218 + flash_energy2 = 41483 + spatial_frequency_response2 = 41484 + noise2 = 41485 + focal_plane_x_resolution2 = 41486 + focal_plane_y_resolution2 = 41487 + focal_plane_resolution_unit2 = 41488 + image_number2 = 41489 + security_classification2 = 41490 + image_history2 = 41491 + subject_location = 41492 + exposure_index2 = 41493 + tiff_ep_standard_id2 = 41494 + sensing_method2 = 41495 + file_source = 41728 + scene_type = 41729 + cfa_pattern = 41730 + custom_rendered = 41985 + exposure_mode = 41986 + white_balance = 41987 + digital_zoom_ratio = 41988 + focal_length_in35mm_format = 41989 + scene_capture_type = 41990 + gain_control = 41991 + contrast = 41992 + saturation = 41993 + sharpness = 41994 + device_setting_description = 41995 + subject_distance_range = 41996 + image_unique_id = 42016 + owner_name = 42032 + serial_number = 42033 + lens_info = 42034 + lens_make = 42035 + lens_model = 42036 + lens_serial_number = 42037 + gdal_metadata = 42112 + gdal_no_data = 42113 + gamma = 42240 + expand_software = 44992 + expand_lens = 44993 + expand_film = 44994 + expand_filter_lens = 44995 + expand_scanner = 44996 + expand_flash_lamp = 44997 + pixel_format = 48129 + transformation = 48130 + uncompressed = 48131 + image_type = 48132 + image_width2 = 48256 + image_height2 = 48257 + width_resolution = 48258 + height_resolution = 48259 + image_offset = 48320 + image_byte_count = 48321 + alpha_offset = 48322 + alpha_byte_count = 48323 + image_data_discard = 48324 + alpha_data_discard = 48325 + oce_scanjob_desc = 50215 + oce_application_selector = 50216 + oce_id_number = 50217 + oce_image_logic = 50218 + annotations = 50255 + print_im = 50341 + original_file_name = 50547 + uspto_original_content_type = 50560 + dng_version = 50706 + dng_backward_version = 50707 + unique_camera_model = 50708 + localized_camera_model = 50709 + cfa_plane_color = 50710 + cfa_layout = 50711 + linearization_table = 50712 + black_level_repeat_dim = 50713 + black_level = 50714 + black_level_delta_h = 50715 + black_level_delta_v = 50716 + white_level = 50717 + default_scale = 50718 + default_crop_origin = 50719 + default_crop_size = 50720 + color_matrix1 = 50721 + color_matrix2 = 50722 + camera_calibration1 = 50723 + camera_calibration2 = 50724 + reduction_matrix1 = 50725 + reduction_matrix2 = 50726 + analog_balance = 50727 + as_shot_neutral = 50728 + as_shot_white_xy = 50729 + baseline_exposure = 50730 + baseline_noise = 50731 + baseline_sharpness = 50732 + bayer_green_split = 50733 + linear_response_limit = 50734 + camera_serial_number = 50735 + dng_lens_info = 50736 + chroma_blur_radius = 50737 + anti_alias_strength = 50738 + shadow_scale = 50739 + sr2_private = 50740 + maker_note_safety = 50741 + raw_image_segmentation = 50752 + calibration_illuminant1 = 50778 + calibration_illuminant2 = 50779 + best_quality_scale = 50780 + raw_data_unique_id = 50781 + alias_layer_metadata = 50784 + original_raw_file_name = 50827 + original_raw_file_data = 50828 + active_area = 50829 + masked_areas = 50830 + as_shot_icc_profile = 50831 + as_shot_pre_profile_matrix = 50832 + current_icc_profile = 50833 + current_pre_profile_matrix = 50834 + colorimetric_reference = 50879 + s_raw_type = 50885 + panasonic_title = 50898 + panasonic_title2 = 50899 + camera_calibration_sig = 50931 + profile_calibration_sig = 50932 + profile_ifd = 50933 + as_shot_profile_name = 50934 + noise_reduction_applied = 50935 + profile_name = 50936 + profile_hue_sat_map_dims = 50937 + profile_hue_sat_map_data1 = 50938 + profile_hue_sat_map_data2 = 50939 + profile_tone_curve = 50940 + profile_embed_policy = 50941 + profile_copyright = 50942 + forward_matrix1 = 50964 + forward_matrix2 = 50965 + preview_application_name = 50966 + preview_application_version = 50967 + preview_settings_name = 50968 + preview_settings_digest = 50969 + preview_color_space = 50970 + preview_date_time = 50971 + raw_image_digest = 50972 + original_raw_file_digest = 50973 + sub_tile_block_size = 50974 + row_interleave_factor = 50975 + profile_look_table_dims = 50981 + profile_look_table_data = 50982 + opcode_list1 = 51008 + opcode_list2 = 51009 + opcode_list3 = 51022 + noise_profile = 51041 + time_codes = 51043 + frame_rate = 51044 + t_stop = 51058 + reel_name = 51081 + original_default_final_size = 51089 + original_best_quality_size = 51090 + original_default_crop_size = 51091 + camera_label = 51105 + profile_hue_sat_map_encoding = 51107 + profile_look_table_encoding = 51108 + baseline_exposure_offset = 51109 + default_black_render = 51110 + new_raw_image_digest = 51111 + raw_to_preview_gain = 51112 + default_user_crop = 51125 + padding = 59932 + offset_schema = 59933 + owner_name2 = 65000 + serial_number2 = 65001 + lens = 65002 + kdc_ifd = 65024 + raw_file = 65100 + converter = 65101 + white_balance2 = 65102 + exposure = 65105 + shadows = 65106 + brightness = 65107 + contrast2 = 65108 + saturation2 = 65109 + sharpness2 = 65110 + smoothness = 65111 + moire_filter = 65112 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self.tag = self._root.IfdField.TagEnum(self._io.read_u2le()) + self.field_type = self._root.IfdField.FieldTypeEnum(self._io.read_u2le()) + self.length = self._io.read_u4le() + self.ofs_or_data = self._io.read_u4le() + + @property + def type_byte_length(self): + if hasattr(self, '_m_type_byte_length'): + return self._m_type_byte_length if hasattr(self, '_m_type_byte_length') else None + + self._m_type_byte_length = (2 if self.field_type == self._root.IfdField.FieldTypeEnum.word else (4 if self.field_type == self._root.IfdField.FieldTypeEnum.dword else 1)) + return self._m_type_byte_length if hasattr(self, '_m_type_byte_length') else None + + @property + def byte_length(self): + if hasattr(self, '_m_byte_length'): + return self._m_byte_length if hasattr(self, '_m_byte_length') else None + + self._m_byte_length = (self.length * self.type_byte_length) + return self._m_byte_length if hasattr(self, '_m_byte_length') else None + + @property + def is_immediate_data(self): + if hasattr(self, '_m_is_immediate_data'): + return self._m_is_immediate_data if hasattr(self, '_m_is_immediate_data') else None + + self._m_is_immediate_data = self.byte_length <= 4 + return self._m_is_immediate_data if hasattr(self, '_m_is_immediate_data') else None + + @property + def data(self): + if hasattr(self, '_m_data'): + return self._m_data if hasattr(self, '_m_data') else None + + if not self.is_immediate_data: + io = self._root._io + _pos = io.pos() + io.seek(self.ofs_or_data) + self._m_data = io.read_bytes(self.byte_length) + io.seek(_pos) + + return self._m_data if hasattr(self, '_m_data') else None + + + @property + def ifd0(self): + if hasattr(self, '_m_ifd0'): + return self._m_ifd0 if hasattr(self, '_m_ifd0') else None + + _pos = self._io.pos() + self._io.seek(self.ifd0_ofs) + self._m_ifd0 = self._root.Ifd(self._io, self, self._root) + self._io.seek(_pos) + return self._m_ifd0 if hasattr(self, '_m_ifd0') else None diff --git a/mitmproxy/contrib/kaitaistruct/jpeg.py b/mitmproxy/contrib/kaitaistruct/jpeg.py index ca846a1e..08e382a9 100644 --- a/mitmproxy/contrib/kaitaistruct/jpeg.py +++ b/mitmproxy/contrib/kaitaistruct/jpeg.py @@ -1,4 +1,5 @@ # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild +# The source was jpeg.ksy from here - https://github.com/kaitai-io/kaitai_struct_formats/blob/24e2d00048b8084ceec30a187a79cb87a79a48ba/image/jpeg.ksy import array import struct @@ -44,9 +45,23 @@ class Jpeg(KaitaiStruct): dqt = 219 dnl = 220 dri = 221 + dhp = 222 app0 = 224 app1 = 225 app2 = 226 + app3 = 227 + app4 = 228 + app5 = 229 + app6 = 230 + app7 = 231 + app8 = 232 + app9 = 233 + app10 = 234 + app11 = 235 + app12 = 236 + app13 = 237 + app14 = 238 + app15 = 239 com = 254 def __init__(self, _io, _parent=None, _root=None): self._io = _io diff --git a/test/mitmproxy/contentviews/test_image_parser.py b/test/mitmproxy/contentviews/test_image_parser.py index 6c78c07b..1595bba5 100644 --- a/test/mitmproxy/contentviews/test_image_parser.py +++ b/test/mitmproxy/contentviews/test_image_parser.py @@ -124,6 +124,29 @@ def test_parse_gif(filename, metadata): ('comment', "b'mitmproxy test image'"), ('Size', '256 x 256 px') ], + # check app1 + "mitmproxy/data/image_parser/app1.jpeg": [ + ('Format', 'JPEG (ISO 10918)'), + ('jfif_version', '(1, 1)'), + ('jfif_density', '(72, 72)'), + ('jfif_unit', '1'), + ('make', 'Canon'), + ('model', 'Canon PowerShot A60'), + ('modify_date', '2004:07:16 18:46:04'), + ('Size', '717 x 558 px') + ], + # check multiple segments + "mitmproxy/data/image_parser/image-err1.jpg": [ + ('Format', 'JPEG (ISO 10918)'), + ('jfif_version', '(1, 1)'), + ('jfif_density', '(72, 72)'), + ('jfif_unit', '1'), + ('image_description', '<> on December 4, 2009 in Washington, DC.'), + ('make', 'Canon'), ('model', 'Canon EOS-1D Mark III'), + ('artist', 'Alex Wong'), + ('primary_chromaticities', '@\x00\x00\x00d'), + ('copyright', '2009 Getty Images') + ], }.items()) def test_parse_jpeg(filename, metadata): with open(tutils.test_data.path(filename), 'rb') as f: diff --git a/test/mitmproxy/data/image_parser/app1.jpeg b/test/mitmproxy/data/image_parser/app1.jpeg new file mode 100644 index 00000000..baa77dfe Binary files /dev/null and b/test/mitmproxy/data/image_parser/app1.jpeg differ diff --git a/test/mitmproxy/data/image_parser/image-err1.jpg b/test/mitmproxy/data/image_parser/image-err1.jpg new file mode 100644 index 00000000..1b251e6e Binary files /dev/null and b/test/mitmproxy/data/image_parser/image-err1.jpg differ -- cgit v1.2.3 From ccca04b45083ecbde8a05ed709e4062024ab9f8d Mon Sep 17 00:00:00 2001 From: Sachin Kelkar Date: Sat, 11 Feb 2017 14:48:03 +0530 Subject: Fix coverage --- mitmproxy/contentviews/image/view.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/mitmproxy/contentviews/image/view.py b/mitmproxy/contentviews/image/view.py index e3c9bbd3..8fdb26e9 100644 --- a/mitmproxy/contentviews/image/view.py +++ b/mitmproxy/contentviews/image/view.py @@ -1,7 +1,6 @@ import io import imghdr -from PIL import ExifTags from PIL import Image from mitmproxy.types import multidict @@ -52,13 +51,5 @@ class ViewImage(base.View): parts.append( (str(i), str(img.info[i])) ) - if hasattr(img, "_getexif"): - ex = img._getexif() - if ex: - for i in sorted(ex.keys()): - tag = ExifTags.TAGS.get(i, i) - parts.append( - (str(tag), str(ex[i])) - ) fmt = base.format_dict(multidict.MultiDict(parts)) return "%s image" % img.format, fmt -- cgit v1.2.3 From 245e24dcf3327e46b7ce2ea4a4b667c0d90bd1c0 Mon Sep 17 00:00:00 2001 From: Sachin Kelkar Date: Sun, 12 Feb 2017 01:19:36 +0530 Subject: Add sources of images, remove copyrighted image --- mitmproxy/contentviews/image/image_parser.py | 4 +-- test/mitmproxy/contentviews/test_image.py | 2 +- test/mitmproxy/contentviews/test_image_parser.py | 30 +++++++++++++++++------ test/mitmproxy/data/all.jpeg | Bin 0 -> 230334 bytes test/mitmproxy/data/image-err1.jpg | Bin 82674 -> 0 bytes test/mitmproxy/data/image_parser/README.md | 17 +++++++++++++ test/mitmproxy/data/image_parser/all.jpeg | Bin 0 -> 230334 bytes test/mitmproxy/data/image_parser/image-err1.jpg | Bin 82674 -> 0 bytes 8 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 test/mitmproxy/data/all.jpeg delete mode 100644 test/mitmproxy/data/image-err1.jpg create mode 100644 test/mitmproxy/data/image_parser/README.md create mode 100644 test/mitmproxy/data/image_parser/all.jpeg delete mode 100644 test/mitmproxy/data/image_parser/image-err1.jpg diff --git a/mitmproxy/contentviews/image/image_parser.py b/mitmproxy/contentviews/image/image_parser.py index bcae0566..1ff3cff7 100644 --- a/mitmproxy/contentviews/image/image_parser.py +++ b/mitmproxy/contentviews/image/image_parser.py @@ -73,10 +73,8 @@ def parse_jpeg(data: bytes) -> Metadata: if segment.marker._name_ == 'com': parts.append(('comment', str(segment.data))) if segment.marker._name_ == 'app1': - try: + if hasattr(segment.data, 'body'): for field in segment.data.body.data.body.ifd0.fields: if field.data is not None: parts.append((field.tag._name_, field.data.decode('UTF-8').strip('\x00'))) - except AttributeError: - pass return parts diff --git a/test/mitmproxy/contentviews/test_image.py b/test/mitmproxy/contentviews/test_image.py index 9e7e28f5..e3dfb714 100644 --- a/test/mitmproxy/contentviews/test_image.py +++ b/test/mitmproxy/contentviews/test_image.py @@ -8,7 +8,7 @@ def test_view_image(): for img in [ "mitmproxy/data/image.png", "mitmproxy/data/image.gif", - "mitmproxy/data/image-err1.jpg", + "mitmproxy/data/all.jpeg", "mitmproxy/data/image.ico" ]: with open(tutils.test_data.path(img), "rb") as f: diff --git a/test/mitmproxy/contentviews/test_image_parser.py b/test/mitmproxy/contentviews/test_image_parser.py index 1595bba5..3c8bfdf7 100644 --- a/test/mitmproxy/contentviews/test_image_parser.py +++ b/test/mitmproxy/contentviews/test_image_parser.py @@ -136,16 +136,32 @@ def test_parse_gif(filename, metadata): ('Size', '717 x 558 px') ], # check multiple segments - "mitmproxy/data/image_parser/image-err1.jpg": [ + "mitmproxy/data/image_parser/all.jpeg": [ ('Format', 'JPEG (ISO 10918)'), ('jfif_version', '(1, 1)'), - ('jfif_density', '(72, 72)'), + ('jfif_density', '(300, 300)'), ('jfif_unit', '1'), - ('image_description', '<> on December 4, 2009 in Washington, DC.'), - ('make', 'Canon'), ('model', 'Canon EOS-1D Mark III'), - ('artist', 'Alex Wong'), - ('primary_chromaticities', '@\x00\x00\x00d'), - ('copyright', '2009 Getty Images') + ('comment', 'b\'BARTOLOMEO DI FRUOSINO\\r\\n(b. ca. 1366, Firenze, d. 1441, ' + 'Firenze)\\r\\n\\r\\nInferno, from the Divine Comedy by Dante (Folio 1v)' + '\\r\\n1430-35\\r\\nTempera, gold, and silver on parchment, 365 x 265 mm' + '\\r\\nBiblioth\\xe8que Nationale, Paris\\r\\n\\r\\nThe codex in Paris ' + 'contains the text of the Inferno, the first of three books of the Divine ' + 'Comedy, the masterpiece of the Florentine poet Dante Alighieri (1265-1321).' + ' The codex begins with two full-page illuminations. On folio 1v Dante and ' + 'Virgil stand within the doorway of Hell at the upper left and observe its ' + 'nine different zones. Dante and Virgil are to wade through successive ' + 'circles teeming with images of the damned. The gates of Hell appear in ' + 'the middle, a scarlet row of open sarcophagi before them. Devils orchestrate' + ' the movements of the wretched souls.\\r\\n\\r\\nThe vision of the fiery ' + 'inferno follows a convention established by ' + 'Nardo di Cione\\\'s fresco in the church of Santa Maria Novella, Florence.' + ' Of remarkable vivacity and intensity of expression, the illumination is ' + 'executed in Bartolomeo\\\'s late style.\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n' + '--- Keywords: --------------\\r\\n\\r\\nAuthor: BARTOLOMEO DI FRUOSINO' + '\\r\\nTitle: Inferno, from the Divine Comedy by Dante (Folio 1v)\\r\\nTime-line:' + ' 1401-1450\\r\\nSchool: Italian\\r\\nForm: illumination\\r\\nType: other\\r\\n\''), + ('Size', '750 x 1055 px') ], }.items()) def test_parse_jpeg(filename, metadata): diff --git a/test/mitmproxy/data/all.jpeg b/test/mitmproxy/data/all.jpeg new file mode 100644 index 00000000..ea5d8d0f Binary files /dev/null and b/test/mitmproxy/data/all.jpeg differ diff --git a/test/mitmproxy/data/image-err1.jpg b/test/mitmproxy/data/image-err1.jpg deleted file mode 100644 index 1b251e6e..00000000 Binary files a/test/mitmproxy/data/image-err1.jpg and /dev/null differ diff --git a/test/mitmproxy/data/image_parser/README.md b/test/mitmproxy/data/image_parser/README.md new file mode 100644 index 00000000..c23409bf --- /dev/null +++ b/test/mitmproxy/data/image_parser/README.md @@ -0,0 +1,17 @@ +# Sources of the images used + +## PNG + +`aspect.png` - http://pngimg.com/upload/water_PNG3290.png +All other PNGs are from the [PNGTestSuite](http://www.schaik.com/pngsuite/) + +# GIF + +All the GIFs are from the Pillow repository [here](https://github.com/python-pillow/Pillow/tree/master/Tests/images) + +# JPEG + +`app1.jpeg` - https://commons.wikimedia.org/wiki/File:PT05_ubt.jpeg +`all.jpeg` - https://commons.wikimedia.org/wiki/Category:Dante's_Inferno#/media/File:Bartolomeo_Di_Fruosino_-_Inferno,_from_the_Divine_Comedy_by_Dante_(Folio_1v)_-_WGA01339.jpg +`comment.jpg` has been taken from [here](https://commons.wikimedia.org/wiki/File:JPEG_example_image.jpg) and has a comment added locally +All other JPEGs are from the Pillow repository [here](https://github.com/python-pillow/Pillow/tree/master/Tests/images) diff --git a/test/mitmproxy/data/image_parser/all.jpeg b/test/mitmproxy/data/image_parser/all.jpeg new file mode 100644 index 00000000..ea5d8d0f Binary files /dev/null and b/test/mitmproxy/data/image_parser/all.jpeg differ diff --git a/test/mitmproxy/data/image_parser/image-err1.jpg b/test/mitmproxy/data/image_parser/image-err1.jpg deleted file mode 100644 index 1b251e6e..00000000 Binary files a/test/mitmproxy/data/image_parser/image-err1.jpg and /dev/null differ -- cgit v1.2.3