diff --git a/libmproxy/console/contentview.py b/libmproxy/console/contentview.py index 8dd8ad1d3..b03d06c58 100644 --- a/libmproxy/console/contentview.py +++ b/libmproxy/console/contentview.py @@ -1,3 +1,4 @@ +import logging import re, cStringIO, traceback, json import urwid @@ -19,6 +20,18 @@ try: except ImportError: # pragma nocover pyamf = None +try: + import cssutils +except ImportError: # pragma nocover + cssutils = None +else: + cssutils.log.setLevel(logging.CRITICAL) + + cssutils.ser.prefs.keepComments = True + cssutils.ser.prefs.omitLastSemicolon = False + cssutils.ser.prefs.indentClosingBrace = False + cssutils.ser.prefs.validOnly = False + VIEW_CUTOFF = 1024*50 @@ -318,7 +331,23 @@ class ViewJavaScript: opts = jsbeautifier.default_options() opts.indent_size = 2 res = jsbeautifier.beautify(content[:limit], opts) - return "JavaScript", _view_text(res, len(content), limit) + return "JavaScript", _view_text(res, len(res), limit) + +class ViewCSS: + name = "CSS" + prompt = ("css", "c") + content_types = [ + "text/css" + ] + + def __call__(self, hdrs, content, limit): + if cssutils: + sheet = cssutils.parseString(content) + beautified = sheet.cssText + else: + beautified = content + + return "CSS", _view_text(beautified, len(beautified), limit) class ViewImage: @@ -409,6 +438,7 @@ views = [ ViewHTML(), ViewHTMLOutline(), ViewJavaScript(), + ViewCSS(), ViewURLEncoded(), ViewMultipart(), ViewImage(), diff --git a/libmproxy/console/help.py b/libmproxy/console/help.py index f8be6605b..0d01ac6f7 100644 --- a/libmproxy/console/help.py +++ b/libmproxy/console/help.py @@ -61,6 +61,10 @@ class HelpView(urwid.ListBox): common.highlight_key("json", "s") + [("text", ": JSON")] ), + (None, + common.highlight_key("css", "c") + + [("text", ": CSS")] + ), (None, common.highlight_key("urlencoded", "u") + [("text", ": URL-encoded data")] diff --git a/requirements.txt b/requirements.txt index ff149240d..db34e4b6b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,5 @@ pyasn1>=0.1.7 requests>=1.2.2 urwid>=1.1.1 wsgiref>=0.1.2 -jsbeautifier>=1.4.0 \ No newline at end of file +jsbeautifier>=1.4.0 +cssutils>=1.0,<1.1 diff --git a/test/data/1.css b/test/data/1.css new file mode 100644 index 000000000..33387ca79 --- /dev/null +++ b/test/data/1.css @@ -0,0 +1 @@ +body,html{height:100%}body{font-family:'Open Sans',sans-serif;font-size:1.5em;padding-top:80px} diff --git a/test/test_console_contentview.py b/test/test_console_contentview.py index ef44f8349..b982aff30 100644 --- a/test/test_console_contentview.py +++ b/test/test_console_contentview.py @@ -13,6 +13,11 @@ try: except ImportError: pyamf = None +try: + import cssutils +except: + cssutils = None + class TestContentView: def test_trailer(self): @@ -112,6 +117,26 @@ class TestContentView: assert v([], "[1, 2, 3", 100) assert v([], "function(a){[1, 2, 3]}", 100) + def test_view_css(self): + v = cv.ViewCSS() + + with open('./test/data/1.css', 'r') as fp: + fixture_1 = fp.read() + + result = v([], 'a', 100) + + if cssutils: + assert len(result[1]) == 0 + else: + assert len(result[1]) == 1 + + result = v([], fixture_1, 100) + + if cssutils: + assert len(result[1]) > 1 + else: + assert len(result[1]) == 1 + def test_view_hex(self): v = cv.ViewHex() assert v([], "foo", 1000)