From ef1035f2ba63b35ccb3036465d69256fc54cf276 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 14 Aug 2014 13:11:13 +0200 Subject: [PATCH] utils.rfc6266: Fix lint --- .../utils/http/test_content_disposition.py | 3 +- qutebrowser/utils/http.py | 2 +- qutebrowser/utils/rfc6266.py | 50 +++++++++++++------ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/qutebrowser/test/utils/http/test_content_disposition.py b/qutebrowser/test/utils/http/test_content_disposition.py index 776f1c79b..5063c0663 100644 --- a/qutebrowser/test/utils/http/test_content_disposition.py +++ b/qutebrowser/test/utils/http/test_content_disposition.py @@ -672,7 +672,8 @@ class CharacterSetTests(AttachmentTestCase): The octet %82 does not represent a valid ISO-8859-1 code point, so the UA should really ignore the parameter. """ - self._check_ignored("attachment; iso-8859-1''foo-%c3%a4-%e2%82%ac.html") + self._check_ignored("attachment; " + "iso-8859-1''foo-%c3%a4-%e2%82%ac.html") def test_attwithfn2231iso_bad(self): """'attachment', specifying a filename of foo-รค.html. diff --git a/qutebrowser/utils/http.py b/qutebrowser/utils/http.py index 47ad87fd6..90b43a18d 100644 --- a/qutebrowser/utils/http.py +++ b/qutebrowser/utils/http.py @@ -45,7 +45,7 @@ def parse_content_disposition(reply): # os.path.basename later. try: content_disposition = rfc6266.parse_headers( - bytes(reply.rawHeader('Content-Disposition')), relaxed=True) + bytes(reply.rawHeader('Content-Disposition'))) filename = content_disposition.filename_unsafe except UnicodeDecodeError as e: logger.warning("Error while getting filename: {}: {}".format( diff --git a/qutebrowser/utils/rfc6266.py b/qutebrowser/utils/rfc6266.py index fece9f8b6..bfd4a3c91 100644 --- a/qutebrowser/utils/rfc6266.py +++ b/qutebrowser/utils/rfc6266.py @@ -1,6 +1,26 @@ +# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: + +# Copyright 2014 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +"""pyPEG parsing for the RFC 6266 (Content-Disposition) header. """ + import pypeg2 as peg -import os.path from collections import namedtuple import urllib.parse import string @@ -37,6 +57,7 @@ token_chars = attr_chars + "*'%" # which might include non-ascii octets. token_re = '[{}]+'.format(re.escape(token_chars)) + class Token(str): """A token (RFC 2616, Section 2.2).""" @@ -61,6 +82,7 @@ qdtext_re = r'[^"{}]'.format(re.escape(ctl_chars)) quoted_pair_re = r'\\[{}]'.format(re.escape( ''.join(chr(i) for i in range(128)))) + class QuotedString(str): """A quoted string (RFC 2616, Section 2.2).""" @@ -120,6 +142,7 @@ class ExtValue(peg.List): grammar = peg.contiguous(Charset, "'", peg.optional(Language), "'", ValueChars) + class ExtToken(peg.Symbol): """A token introducing an extended value (RFC 6266, Section 4.1).""" @@ -206,7 +229,7 @@ class ContentDisposition: in the download case. """ - def __init__(self, disposition='inline', assocs=None, location=None): + def __init__(self, disposition='inline', assocs=None): """This constructor is used internally after parsing the header. Instances should generally be created from a factory @@ -216,7 +239,6 @@ class ContentDisposition: self.disposition = 'inline' else: self.disposition = disposition[0] - self.location = location if assocs is None: self.assocs = {} else: @@ -228,11 +250,7 @@ class ContentDisposition: @property def filename_unsafe(self): - """The filename from the Content-Disposition header. - - If a location was passed at instanciation, the basename - from that may be used as a fallback. Otherwise, this may - be the None value. + """The filename from the Content-Disposition header or None. On safety: This property records the intent of the sender. @@ -249,8 +267,6 @@ class ContentDisposition: elif 'filename' in self.assocs: # XXX Reject non-ascii (parsed via qdtext) here? return self.assocs['filename'] - elif self.location is not None: - return os.path.basename(self.location_path.rstrip('/')) @property def is_inline(self): @@ -263,8 +279,8 @@ class ContentDisposition: return self.disposition.lower() == 'inline' def __repr__(self): - return 'ContentDisposition(%r, %r, %r)' % ( - self.disposition, self.assocs, self.location) + return 'ContentDisposition(%r, %r)' % ( + self.disposition, self.assocs) def normalize_ws(text): @@ -272,8 +288,9 @@ def normalize_ws(text): return ' '.join(text.split()) -def parse_headers(content_disposition, location=None, relaxed=False): +def parse_headers(content_disposition): """Build a ContentDisposition from header values.""" + # pylint: disable=maybe-no-member # We allow non-ascii here (it will only be parsed inside of qdtext, and # rejected by the grammar if it appears in other places), although parsing # it can be ambiguous. Parsing it ensures that a non-ambiguous filename* @@ -292,9 +309,10 @@ def parse_headers(content_disposition, location=None, relaxed=False): try: parsed = peg.parse(content_disposition, ContentDispositionValue) except (SyntaxError, DuplicateParamError, InvalidISO8859Error): - return ContentDisposition(location=location) - return ContentDisposition( - disposition=parsed.dtype, assocs=parsed.params, location=location) + return ContentDisposition() + else: + return ContentDisposition(disposition=parsed.dtype, + assocs=parsed.params) def parse_ext_value(val):