mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-26 18:18:25 +00:00
Add a pretty-viewer for images.
This shows basic image information like dimensions, plus extracted EXIF tags and other metadata.
This commit is contained in:
parent
b6725ee802
commit
a050eeef05
@ -1,5 +1,7 @@
|
|||||||
import re
|
import re, cStringIO
|
||||||
import urwid
|
import urwid
|
||||||
|
from PIL import Image
|
||||||
|
from PIL.ExifTags import TAGS
|
||||||
import common
|
import common
|
||||||
from .. import utils, encoding, flow
|
from .. import utils, encoding, flow
|
||||||
from ..contrib import jsbeautifier
|
from ..contrib import jsbeautifier
|
||||||
@ -22,6 +24,7 @@ VIEW_CONTENT_PRETTY_TYPE_XML = 2
|
|||||||
VIEW_CONTENT_PRETTY_TYPE_URLENCODED = 3
|
VIEW_CONTENT_PRETTY_TYPE_URLENCODED = 3
|
||||||
VIEW_CONTENT_PRETTY_TYPE_MULTIPART = 4
|
VIEW_CONTENT_PRETTY_TYPE_MULTIPART = 4
|
||||||
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT = 5
|
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT = 5
|
||||||
|
VIEW_CONTENT_PRETTY_TYPE_IMAGE = 6
|
||||||
|
|
||||||
CONTENT_PRETTY_NAMES = {
|
CONTENT_PRETTY_NAMES = {
|
||||||
VIEW_CONTENT_PRETTY_TYPE_JSON: "JSON",
|
VIEW_CONTENT_PRETTY_TYPE_JSON: "JSON",
|
||||||
@ -29,6 +32,7 @@ CONTENT_PRETTY_NAMES = {
|
|||||||
VIEW_CONTENT_PRETTY_TYPE_URLENCODED: "URL-encoded",
|
VIEW_CONTENT_PRETTY_TYPE_URLENCODED: "URL-encoded",
|
||||||
VIEW_CONTENT_PRETTY_TYPE_MULTIPART: "Multipart Form",
|
VIEW_CONTENT_PRETTY_TYPE_MULTIPART: "Multipart Form",
|
||||||
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: "JavaScript",
|
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: "JavaScript",
|
||||||
|
VIEW_CONTENT_PRETTY_TYPE_IMAGE: "Image",
|
||||||
}
|
}
|
||||||
|
|
||||||
CONTENT_TYPES_MAP = {
|
CONTENT_TYPES_MAP = {
|
||||||
@ -39,6 +43,11 @@ CONTENT_TYPES_MAP = {
|
|||||||
"application/x-www-form-urlencoded": VIEW_CONTENT_PRETTY_TYPE_URLENCODED,
|
"application/x-www-form-urlencoded": VIEW_CONTENT_PRETTY_TYPE_URLENCODED,
|
||||||
"application/x-javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
|
"application/x-javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
|
||||||
"application/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
|
"application/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
|
||||||
|
"text/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
|
||||||
|
"image/png": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||||
|
"image/jpeg": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||||
|
"image/gif": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||||
|
"image/x-icon": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||||
}
|
}
|
||||||
|
|
||||||
def trailer(clen, txt):
|
def trailer(clen, txt):
|
||||||
@ -164,12 +173,47 @@ def view_javascript(hdrs, content):
|
|||||||
return "JavaScript", _view_text(res)
|
return "JavaScript", _view_text(res)
|
||||||
|
|
||||||
|
|
||||||
|
def view_image(hdrs, content):
|
||||||
|
try:
|
||||||
|
img = Image.open(cStringIO.StringIO(content))
|
||||||
|
except IOError:
|
||||||
|
return None
|
||||||
|
parts = [
|
||||||
|
("Format", str(img.format_description)),
|
||||||
|
("Size", "%s x %s px"%img.size),
|
||||||
|
("Mode", str(img.mode)),
|
||||||
|
]
|
||||||
|
for i in sorted(img.info.keys()):
|
||||||
|
if i != "exif":
|
||||||
|
parts.append(
|
||||||
|
(str(i), str(img.info[i]))
|
||||||
|
)
|
||||||
|
if hasattr(img, "_getexif"):
|
||||||
|
ex = img._getexif()
|
||||||
|
if ex:
|
||||||
|
for i in sorted(ex.keys()):
|
||||||
|
tag = TAGS.get(i, i)
|
||||||
|
parts.append(
|
||||||
|
(str(tag), str(ex[i]))
|
||||||
|
)
|
||||||
|
clean = []
|
||||||
|
for i in parts:
|
||||||
|
clean.append([utils.cleanBin(i[0]), utils.cleanBin(i[1])])
|
||||||
|
fmt = common.format_keyvals(
|
||||||
|
clean,
|
||||||
|
key = "header",
|
||||||
|
val = "text"
|
||||||
|
)
|
||||||
|
return "%s image"%img.format, fmt
|
||||||
|
|
||||||
|
|
||||||
PRETTY_FUNCTION_MAP = {
|
PRETTY_FUNCTION_MAP = {
|
||||||
VIEW_CONTENT_PRETTY_TYPE_XML: view_xmlish,
|
VIEW_CONTENT_PRETTY_TYPE_XML: view_xmlish,
|
||||||
VIEW_CONTENT_PRETTY_TYPE_JSON: view_json,
|
VIEW_CONTENT_PRETTY_TYPE_JSON: view_json,
|
||||||
VIEW_CONTENT_PRETTY_TYPE_URLENCODED: view_urlencoded,
|
VIEW_CONTENT_PRETTY_TYPE_URLENCODED: view_urlencoded,
|
||||||
VIEW_CONTENT_PRETTY_TYPE_MULTIPART: view_multipart,
|
VIEW_CONTENT_PRETTY_TYPE_MULTIPART: view_multipart,
|
||||||
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: view_javascript,
|
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: view_javascript,
|
||||||
|
VIEW_CONTENT_PRETTY_TYPE_IMAGE: view_image,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_view_func(viewmode, pretty_type, hdrs, content):
|
def get_view_func(viewmode, pretty_type, hdrs, content):
|
||||||
|
BIN
test/data/image-err1.jpg
Normal file
BIN
test/data/image-err1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
BIN
test/data/image.gif
Normal file
BIN
test/data/image.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
test/data/image.ico
Normal file
BIN
test/data/image.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
test/data/image.jpg
Normal file
BIN
test/data/image.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
test/data/image.png
Normal file
BIN
test/data/image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
@ -83,6 +83,13 @@ class uContentView(libpry.AutoTree):
|
|||||||
def test_view_raw(self):
|
def test_view_raw(self):
|
||||||
assert cv.view_hex([], "foo")
|
assert cv.view_hex([], "foo")
|
||||||
|
|
||||||
|
def test_view_image(self):
|
||||||
|
assert cv.view_image([], file("data/image.png").read())
|
||||||
|
assert cv.view_image([], file("data/image.gif").read())
|
||||||
|
assert cv.view_image([], file("data/image-err1.jpg").read())
|
||||||
|
assert cv.view_image([], file("data/image.ico").read())
|
||||||
|
assert not cv.view_image([], "flibble")
|
||||||
|
|
||||||
def test_view_multipart(self):
|
def test_view_multipart(self):
|
||||||
v = """
|
v = """
|
||||||
--AaB03x
|
--AaB03x
|
||||||
|
Loading…
Reference in New Issue
Block a user