utils.rfc6266: Fix lint
This commit is contained in:
parent
9cf80cf498
commit
ef1035f2ba
@ -672,7 +672,8 @@ class CharacterSetTests(AttachmentTestCase):
|
|||||||
The octet %82 does not represent a valid ISO-8859-1 code point, so the
|
The octet %82 does not represent a valid ISO-8859-1 code point, so the
|
||||||
UA should really ignore the parameter.
|
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):
|
def test_attwithfn2231iso_bad(self):
|
||||||
"""'attachment', specifying a filename of foo-ä.html.
|
"""'attachment', specifying a filename of foo-ä.html.
|
||||||
|
@ -45,7 +45,7 @@ def parse_content_disposition(reply):
|
|||||||
# os.path.basename later.
|
# os.path.basename later.
|
||||||
try:
|
try:
|
||||||
content_disposition = rfc6266.parse_headers(
|
content_disposition = rfc6266.parse_headers(
|
||||||
bytes(reply.rawHeader('Content-Disposition')), relaxed=True)
|
bytes(reply.rawHeader('Content-Disposition')))
|
||||||
filename = content_disposition.filename_unsafe
|
filename = content_disposition.filename_unsafe
|
||||||
except UnicodeDecodeError as e:
|
except UnicodeDecodeError as e:
|
||||||
logger.warning("Error while getting filename: {}: {}".format(
|
logger.warning("Error while getting filename: {}: {}".format(
|
||||||
|
@ -1,6 +1,26 @@
|
|||||||
|
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||||
|
|
||||||
|
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||||
|
#
|
||||||
|
# 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""pyPEG parsing for the RFC 6266 (Content-Disposition) header. """
|
||||||
|
|
||||||
import pypeg2 as peg
|
import pypeg2 as peg
|
||||||
|
|
||||||
import os.path
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import string
|
import string
|
||||||
@ -37,6 +57,7 @@ token_chars = attr_chars + "*'%"
|
|||||||
# which might include non-ascii octets.
|
# which might include non-ascii octets.
|
||||||
token_re = '[{}]+'.format(re.escape(token_chars))
|
token_re = '[{}]+'.format(re.escape(token_chars))
|
||||||
|
|
||||||
|
|
||||||
class Token(str):
|
class Token(str):
|
||||||
|
|
||||||
"""A token (RFC 2616, Section 2.2)."""
|
"""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(
|
quoted_pair_re = r'\\[{}]'.format(re.escape(
|
||||||
''.join(chr(i) for i in range(128))))
|
''.join(chr(i) for i in range(128))))
|
||||||
|
|
||||||
|
|
||||||
class QuotedString(str):
|
class QuotedString(str):
|
||||||
|
|
||||||
"""A quoted string (RFC 2616, Section 2.2)."""
|
"""A quoted string (RFC 2616, Section 2.2)."""
|
||||||
@ -120,6 +142,7 @@ class ExtValue(peg.List):
|
|||||||
grammar = peg.contiguous(Charset, "'", peg.optional(Language), "'",
|
grammar = peg.contiguous(Charset, "'", peg.optional(Language), "'",
|
||||||
ValueChars)
|
ValueChars)
|
||||||
|
|
||||||
|
|
||||||
class ExtToken(peg.Symbol):
|
class ExtToken(peg.Symbol):
|
||||||
|
|
||||||
"""A token introducing an extended value (RFC 6266, Section 4.1)."""
|
"""A token introducing an extended value (RFC 6266, Section 4.1)."""
|
||||||
@ -206,7 +229,7 @@ class ContentDisposition:
|
|||||||
in the download case.
|
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.
|
"""This constructor is used internally after parsing the header.
|
||||||
|
|
||||||
Instances should generally be created from a factory
|
Instances should generally be created from a factory
|
||||||
@ -216,7 +239,6 @@ class ContentDisposition:
|
|||||||
self.disposition = 'inline'
|
self.disposition = 'inline'
|
||||||
else:
|
else:
|
||||||
self.disposition = disposition[0]
|
self.disposition = disposition[0]
|
||||||
self.location = location
|
|
||||||
if assocs is None:
|
if assocs is None:
|
||||||
self.assocs = {}
|
self.assocs = {}
|
||||||
else:
|
else:
|
||||||
@ -228,11 +250,7 @@ class ContentDisposition:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def filename_unsafe(self):
|
def filename_unsafe(self):
|
||||||
"""The filename from the Content-Disposition header.
|
"""The filename from the Content-Disposition header or None.
|
||||||
|
|
||||||
If a location was passed at instanciation, the basename
|
|
||||||
from that may be used as a fallback. Otherwise, this may
|
|
||||||
be the None value.
|
|
||||||
|
|
||||||
On safety:
|
On safety:
|
||||||
This property records the intent of the sender.
|
This property records the intent of the sender.
|
||||||
@ -249,8 +267,6 @@ class ContentDisposition:
|
|||||||
elif 'filename' in self.assocs:
|
elif 'filename' in self.assocs:
|
||||||
# XXX Reject non-ascii (parsed via qdtext) here?
|
# XXX Reject non-ascii (parsed via qdtext) here?
|
||||||
return self.assocs['filename']
|
return self.assocs['filename']
|
||||||
elif self.location is not None:
|
|
||||||
return os.path.basename(self.location_path.rstrip('/'))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_inline(self):
|
def is_inline(self):
|
||||||
@ -263,8 +279,8 @@ class ContentDisposition:
|
|||||||
return self.disposition.lower() == 'inline'
|
return self.disposition.lower() == 'inline'
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'ContentDisposition(%r, %r, %r)' % (
|
return 'ContentDisposition(%r, %r)' % (
|
||||||
self.disposition, self.assocs, self.location)
|
self.disposition, self.assocs)
|
||||||
|
|
||||||
|
|
||||||
def normalize_ws(text):
|
def normalize_ws(text):
|
||||||
@ -272,8 +288,9 @@ def normalize_ws(text):
|
|||||||
return ' '.join(text.split())
|
return ' '.join(text.split())
|
||||||
|
|
||||||
|
|
||||||
def parse_headers(content_disposition, location=None, relaxed=False):
|
def parse_headers(content_disposition):
|
||||||
"""Build a ContentDisposition from header values."""
|
"""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
|
# 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
|
# rejected by the grammar if it appears in other places), although parsing
|
||||||
# it can be ambiguous. Parsing it ensures that a non-ambiguous filename*
|
# 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:
|
try:
|
||||||
parsed = peg.parse(content_disposition, ContentDispositionValue)
|
parsed = peg.parse(content_disposition, ContentDispositionValue)
|
||||||
except (SyntaxError, DuplicateParamError, InvalidISO8859Error):
|
except (SyntaxError, DuplicateParamError, InvalidISO8859Error):
|
||||||
return ContentDisposition(location=location)
|
return ContentDisposition()
|
||||||
return ContentDisposition(
|
else:
|
||||||
disposition=parsed.dtype, assocs=parsed.params, location=location)
|
return ContentDisposition(disposition=parsed.dtype,
|
||||||
|
assocs=parsed.params)
|
||||||
|
|
||||||
|
|
||||||
def parse_ext_value(val):
|
def parse_ext_value(val):
|
||||||
|
Loading…
Reference in New Issue
Block a user