mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-23 08:11:00 +00:00
Add png parser
This commit is contained in:
parent
79aa994275
commit
6202958048
@ -23,8 +23,9 @@ from mitmproxy.net import http
|
|||||||
from mitmproxy.utils import strutils
|
from mitmproxy.utils import strutils
|
||||||
from . import (
|
from . import (
|
||||||
auto, raw, hex, json, xml_html, html_outline, wbxml, javascript, css,
|
auto, raw, hex, json, xml_html, html_outline, wbxml, javascript, css,
|
||||||
urlencoded, multipart, image, query, protobuf
|
urlencoded, multipart, query, protobuf
|
||||||
)
|
)
|
||||||
|
from .image import pillow
|
||||||
from .base import View, VIEW_CUTOFF, KEY_MAX, format_text, format_dict
|
from .base import View, VIEW_CUTOFF, KEY_MAX, format_text, format_dict
|
||||||
|
|
||||||
views = [] # type: List[View]
|
views = [] # type: List[View]
|
||||||
@ -170,7 +171,7 @@ add(javascript.ViewJavaScript())
|
|||||||
add(css.ViewCSS())
|
add(css.ViewCSS())
|
||||||
add(urlencoded.ViewURLEncoded())
|
add(urlencoded.ViewURLEncoded())
|
||||||
add(multipart.ViewMultipart())
|
add(multipart.ViewMultipart())
|
||||||
add(image.ViewImage())
|
add(pillow.ViewImage())
|
||||||
add(query.ViewQuery())
|
add(query.ViewQuery())
|
||||||
|
|
||||||
if protobuf.ViewProtobuf.is_available():
|
if protobuf.ViewProtobuf.is_available():
|
||||||
|
0
mitmproxy/contentviews/image/__init__.py
Normal file
0
mitmproxy/contentviews/image/__init__.py
Normal file
34
mitmproxy/contentviews/image/image_parser.py
Normal file
34
mitmproxy/contentviews/image/image_parser.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from kaitaistruct import KaitaiStream
|
||||||
|
|
||||||
|
from . import png
|
||||||
|
|
||||||
|
def get_png(data):
|
||||||
|
img = png.Png(KaitaiStream(data))
|
||||||
|
parts = {'format': 'Portable network graphics'}
|
||||||
|
f = 'PNG'
|
||||||
|
width = img.ihdr.width
|
||||||
|
height = img.ihdr.height
|
||||||
|
parts["width"] = width
|
||||||
|
parts["height"] = height
|
||||||
|
for i in range(0, len(img.chunks)):
|
||||||
|
chunk = img.chunks[i]
|
||||||
|
if chunk.type == 'gAMA':
|
||||||
|
gamma = chunk.gamma_int / 100000
|
||||||
|
parts['gamma'] = gamma
|
||||||
|
elif chunk.type == 'pHYs':
|
||||||
|
aspectx = chunk.pixels_per_unit_x
|
||||||
|
aspecty = chunk.pixels_per_unit_y
|
||||||
|
parts["aspectx"] = aspectx
|
||||||
|
parts["aspecty"] = aspecty
|
||||||
|
return f, parts
|
||||||
|
|
||||||
|
def format_contentviews(parts):
|
||||||
|
ret = []
|
||||||
|
ret.append(tuple(['Format', parts["format"]]))
|
||||||
|
if "width" in parts:
|
||||||
|
ret.append(tuple(['Size', str(parts["width"]) + " x " + str(parts["height"]) + " px"]))
|
||||||
|
if "aspectx" in parts:
|
||||||
|
ret.append(tuple(['aspect', '(' + str(parts["aspectx"]) + ', ' + str(parts["aspecty"]) + ')']))
|
||||||
|
if "gamma" in parts:
|
||||||
|
ret.append(tuple(['gamma', str(parts["gamma"])]))
|
||||||
|
return ret
|
@ -1,10 +1,13 @@
|
|||||||
import io
|
import io, imghdr
|
||||||
|
|
||||||
from PIL import ExifTags
|
from PIL import ExifTags
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from mitmproxy.types import multidict
|
from mitmproxy.types import multidict
|
||||||
from . import base
|
from . import image_parser
|
||||||
|
|
||||||
|
from mitmproxy.contentviews import base
|
||||||
|
from kaitaistruct import KaitaiStream
|
||||||
|
|
||||||
|
|
||||||
class ViewImage(base.View):
|
class ViewImage(base.View):
|
||||||
@ -19,6 +22,11 @@ class ViewImage(base.View):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def __call__(self, data, **metadata):
|
def __call__(self, data, **metadata):
|
||||||
|
if imghdr.what('', h=data) == 'png':
|
||||||
|
f, parts = image_parser.get_png(io.BytesIO(data))
|
||||||
|
parts = image_parser.format_contentviews(parts)
|
||||||
|
fmt = base.format_dict(multidict.MultiDict(parts))
|
||||||
|
return "%s image" % f, fmt
|
||||||
try:
|
try:
|
||||||
img = Image.open(io.BytesIO(data))
|
img = Image.open(io.BytesIO(data))
|
||||||
except IOError:
|
except IOError:
|
257
mitmproxy/contentviews/image/png.py
Normal file
257
mitmproxy/contentviews/image/png.py
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
||||||
|
# The source was png.ksy from here - https://github.com/kaitai-io/kaitai_struct_formats/tree/master/image
|
||||||
|
|
||||||
|
import array
|
||||||
|
import struct
|
||||||
|
import zlib
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
|
||||||
|
|
||||||
|
|
||||||
|
class Png(KaitaiStruct):
|
||||||
|
|
||||||
|
class ColorType(Enum):
|
||||||
|
greyscale = 0
|
||||||
|
truecolor = 2
|
||||||
|
indexed = 3
|
||||||
|
greyscale_alpha = 4
|
||||||
|
truecolor_alpha = 6
|
||||||
|
|
||||||
|
class PhysUnit(Enum):
|
||||||
|
unknown = 0
|
||||||
|
meter = 1
|
||||||
|
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(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.ihdr = self._root.IhdrChunk(self._io, self, self._root)
|
||||||
|
self.ihdr_crc = self._io.read_bytes(4)
|
||||||
|
self.chunks = []
|
||||||
|
while not self._io.is_eof():
|
||||||
|
self.chunks.append(self._root.Chunk(self._io, self, self._root))
|
||||||
|
|
||||||
|
|
||||||
|
class Rgb(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.r = self._io.read_u1()
|
||||||
|
self.g = self._io.read_u1()
|
||||||
|
self.b = self._io.read_u1()
|
||||||
|
|
||||||
|
|
||||||
|
class Chunk(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.len = self._io.read_u4be()
|
||||||
|
self.type = self._io.read_str_byte_limit(4, "UTF-8")
|
||||||
|
_on = self.type
|
||||||
|
if _on == u"gAMA":
|
||||||
|
self._raw_body = self._io.read_bytes(self.len)
|
||||||
|
io = KaitaiStream(BytesIO(self._raw_body))
|
||||||
|
self.body = self._root.GamaChunk(io, self, self._root)
|
||||||
|
elif _on == u"tIME":
|
||||||
|
self._raw_body = self._io.read_bytes(self.len)
|
||||||
|
io = KaitaiStream(BytesIO(self._raw_body))
|
||||||
|
self.body = self._root.TimeChunk(io, self, self._root)
|
||||||
|
elif _on == u"PLTE":
|
||||||
|
self._raw_body = self._io.read_bytes(self.len)
|
||||||
|
io = KaitaiStream(BytesIO(self._raw_body))
|
||||||
|
self.body = self._root.PlteChunk(io, self, self._root)
|
||||||
|
elif _on == u"bKGD":
|
||||||
|
self._raw_body = self._io.read_bytes(self.len)
|
||||||
|
io = KaitaiStream(BytesIO(self._raw_body))
|
||||||
|
self.body = self._root.BkgdChunk(io, self, self._root)
|
||||||
|
elif _on == u"pHYs":
|
||||||
|
self._raw_body = self._io.read_bytes(self.len)
|
||||||
|
io = KaitaiStream(BytesIO(self._raw_body))
|
||||||
|
self.body = self._root.PhysChunk(io, self, self._root)
|
||||||
|
elif _on == u"tEXt":
|
||||||
|
self._raw_body = self._io.read_bytes(self.len)
|
||||||
|
io = KaitaiStream(BytesIO(self._raw_body))
|
||||||
|
self.body = self._root.TextChunk(io, self, self._root)
|
||||||
|
elif _on == u"cHRM":
|
||||||
|
self._raw_body = self._io.read_bytes(self.len)
|
||||||
|
io = KaitaiStream(BytesIO(self._raw_body))
|
||||||
|
self.body = self._root.ChrmChunk(io, self, self._root)
|
||||||
|
elif _on == u"sRGB":
|
||||||
|
self._raw_body = self._io.read_bytes(self.len)
|
||||||
|
io = KaitaiStream(BytesIO(self._raw_body))
|
||||||
|
self.body = self._root.SrgbChunk(io, self, self._root)
|
||||||
|
else:
|
||||||
|
self.body = self._io.read_bytes(self.len)
|
||||||
|
self.crc = self._io.read_bytes(4)
|
||||||
|
|
||||||
|
|
||||||
|
class BkgdIndexed(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.palette_index = self._io.read_u1()
|
||||||
|
|
||||||
|
|
||||||
|
class Point(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.x_int = self._io.read_u4be()
|
||||||
|
self.y_int = self._io.read_u4be()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def x(self):
|
||||||
|
if hasattr(self, '_m_x'):
|
||||||
|
return self._m_x
|
||||||
|
|
||||||
|
self._m_x = (self.x_int / 100000.0)
|
||||||
|
return self._m_x
|
||||||
|
|
||||||
|
@property
|
||||||
|
def y(self):
|
||||||
|
if hasattr(self, '_m_y'):
|
||||||
|
return self._m_y
|
||||||
|
|
||||||
|
self._m_y = (self.y_int / 100000.0)
|
||||||
|
return self._m_y
|
||||||
|
|
||||||
|
|
||||||
|
class BkgdGreyscale(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.value = self._io.read_u2be()
|
||||||
|
|
||||||
|
|
||||||
|
class ChrmChunk(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.white_point = self._root.Point(self._io, self, self._root)
|
||||||
|
self.red = self._root.Point(self._io, self, self._root)
|
||||||
|
self.green = self._root.Point(self._io, self, self._root)
|
||||||
|
self.blue = self._root.Point(self._io, self, self._root)
|
||||||
|
|
||||||
|
|
||||||
|
class IhdrChunk(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.width = self._io.read_u4be()
|
||||||
|
self.height = self._io.read_u4be()
|
||||||
|
self.bit_depth = self._io.read_u1()
|
||||||
|
self.color_type = self._root.ColorType(self._io.read_u1())
|
||||||
|
self.compression_method = self._io.read_u1()
|
||||||
|
self.filter_method = self._io.read_u1()
|
||||||
|
self.interlace_method = self._io.read_u1()
|
||||||
|
|
||||||
|
|
||||||
|
class PlteChunk(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.entries = []
|
||||||
|
while not self._io.is_eof():
|
||||||
|
self.entries.append(self._root.Rgb(self._io, self, self._root))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SrgbChunk(KaitaiStruct):
|
||||||
|
|
||||||
|
class Intent(Enum):
|
||||||
|
perceptual = 0
|
||||||
|
relative_colorimetric = 1
|
||||||
|
saturation = 2
|
||||||
|
absolute_colorimetric = 3
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.render_intent = self._root.Intent(self._io.read_u1())
|
||||||
|
|
||||||
|
|
||||||
|
class BkgdTruecolor(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.red = self._io.read_u2be()
|
||||||
|
self.green = self._io.read_u2be()
|
||||||
|
self.blue = self._io.read_u2be()
|
||||||
|
|
||||||
|
|
||||||
|
class GamaChunk(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.gamma_int = self._io.read_u4be()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gamma_ratio(self):
|
||||||
|
if hasattr(self, '_m_gamma_ratio'):
|
||||||
|
return self._m_gamma_ratio
|
||||||
|
|
||||||
|
self._m_gamma_ratio = (100000.0 / self.gamma_int)
|
||||||
|
return self._m_gamma_ratio
|
||||||
|
|
||||||
|
|
||||||
|
class BkgdChunk(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
_on = self._root.ihdr.color_type
|
||||||
|
if _on == self._root.ColorType.greyscale_alpha:
|
||||||
|
self.bkgd = self._root.BkgdGreyscale(self._io, self, self._root)
|
||||||
|
elif _on == self._root.ColorType.indexed:
|
||||||
|
self.bkgd = self._root.BkgdIndexed(self._io, self, self._root)
|
||||||
|
elif _on == self._root.ColorType.greyscale:
|
||||||
|
self.bkgd = self._root.BkgdGreyscale(self._io, self, self._root)
|
||||||
|
elif _on == self._root.ColorType.truecolor_alpha:
|
||||||
|
self.bkgd = self._root.BkgdTruecolor(self._io, self, self._root)
|
||||||
|
elif _on == self._root.ColorType.truecolor:
|
||||||
|
self.bkgd = self._root.BkgdTruecolor(self._io, self, self._root)
|
||||||
|
|
||||||
|
|
||||||
|
class PhysChunk(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.pixels_per_unit_x = self._io.read_u4be()
|
||||||
|
self.pixels_per_unit_y = self._io.read_u4be()
|
||||||
|
self.unit = self._root.PhysUnit(self._io.read_u1())
|
||||||
|
|
||||||
|
|
||||||
|
class TextChunk(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.keyword = self._io.read_strz("iso8859-1", 0, False, True, True)
|
||||||
|
self.text = self._io.read_str_eos("iso8859-1")
|
||||||
|
|
||||||
|
|
||||||
|
class TimeChunk(KaitaiStruct):
|
||||||
|
def __init__(self, _io, _parent=None, _root=None):
|
||||||
|
self._io = _io
|
||||||
|
self._parent = _parent
|
||||||
|
self._root = _root if _root else self
|
||||||
|
self.year = self._io.read_u2be()
|
||||||
|
self.month = self._io.read_u1()
|
||||||
|
self.day = self._io.read_u1()
|
||||||
|
self.hour = self._io.read_u1()
|
||||||
|
self.minute = self._io.read_u1()
|
||||||
|
self.second = self._io.read_u1()
|
@ -1,10 +1,10 @@
|
|||||||
from mitmproxy.contentviews import image
|
from mitmproxy.contentviews.image import pillow
|
||||||
from mitmproxy.test import tutils
|
from mitmproxy.test import tutils
|
||||||
from . import full_eval
|
from . import full_eval
|
||||||
|
|
||||||
|
|
||||||
def test_view_image():
|
def test_view_image():
|
||||||
v = full_eval(image.ViewImage())
|
v = full_eval(pillow.ViewImage())
|
||||||
for img in [
|
for img in [
|
||||||
"mitmproxy/data/image.png",
|
"mitmproxy/data/image.png",
|
||||||
"mitmproxy/data/image.gif",
|
"mitmproxy/data/image.gif",
|
||||||
|
14
test/mitmproxy/contentviews/test_image_parser.py
Normal file
14
test/mitmproxy/contentviews/test_image_parser.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import io
|
||||||
|
|
||||||
|
from mitmproxy.contentviews.image import image_parser
|
||||||
|
from mitmproxy.test import tutils
|
||||||
|
|
||||||
|
def test_png_parser():
|
||||||
|
img = "mitmproxy/data/image.png"
|
||||||
|
with open(tutils.test_data.path(img), "rb") as f:
|
||||||
|
fmt, parts = image_parser.get_png(io.BytesIO(f.read()))
|
||||||
|
assert fmt == "PNG"
|
||||||
|
assert parts
|
||||||
|
assert parts["width"] == 174
|
||||||
|
assert parts["height"] == 174
|
||||||
|
assert parts["format"] == "Portable network graphics"
|
Loading…
Reference in New Issue
Block a user