Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
rfc6266
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
rfc6266
Commits
b98dcd40
Commit
b98dcd40
authored
Jan 30, 2012
by
Gabriel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify the API.
parent
fefcfd32
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
65 additions
and
56 deletions
+65
-56
rfc6266.py
+65
-56
No files found.
rfc6266.py
View file @
b98dcd40
...
@@ -2,8 +2,11 @@
...
@@ -2,8 +2,11 @@
"""Implements RFC 6266, the Content-Disposition HTTP header.
"""Implements RFC 6266, the Content-Disposition HTTP header.
ContentDisposition handles the receiver side,
parse_headers (and variant parse_httplib2_response) handles the receiver side.
header_for_filename handles the sender side.
It returns a ContentDisposition object with attributes like is_inline,
filename_unsafe, filename_sanitized.
build_header handles the sender side.
"""
"""
from
lepl
import
*
from
lepl
import
*
...
@@ -15,7 +18,12 @@ import os.path
...
@@ -15,7 +18,12 @@ import os.path
import
re
import
re
__all__
=
(
'ContentDisposition'
,
'header_for_filename'
,
)
__all__
=
(
'ContentDisposition'
,
'parse_headers'
,
'parse_httplib2_response'
,
'build_header'
,
)
LangTagged
=
namedtuple
(
'LangTagged'
,
'string langtag'
)
LangTagged
=
namedtuple
(
'LangTagged'
,
'string langtag'
)
...
@@ -33,8 +41,8 @@ class ContentDisposition(object):
...
@@ -33,8 +41,8 @@ class ContentDisposition(object):
def
__init__
(
self
,
disposition
=
'inline'
,
assocs
=
None
,
location
=
None
):
def
__init__
(
self
,
disposition
=
'inline'
,
assocs
=
None
,
location
=
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
class
Instances should generally be created from a factory
method, such as from_headers and from
_httplib2_response.
function, such as parse_headers and parse
_httplib2_response.
"""
"""
self
.
disposition
=
disposition
self
.
disposition
=
disposition
...
@@ -122,50 +130,52 @@ class ContentDisposition(object):
...
@@ -122,50 +130,52 @@ class ContentDisposition(object):
return
'ContentDisposition(
%
r,
%
r,
%
r)'
%
(
return
'ContentDisposition(
%
r,
%
r,
%
r)'
%
(
self
.
disposition
,
self
.
assocs
,
self
.
location
)
self
.
disposition
,
self
.
assocs
,
self
.
location
)
@classmethod
def
from_headers
(
cls
,
content_disposition
,
location
=
None
):
"""Build a ContentDisposition from header values.
"""
if
content_disposition
is
None
:
def
parse_headers
(
content_disposition
,
location
=
None
):
return
cls
(
location
=
location
)
"""Build a ContentDisposition from header values.
"""
# Both alternatives seem valid.
if
content_disposition
is
None
:
if
False
:
return
ContentDisposition
(
location
=
location
)
# Require content_disposition to be ascii bytes (0-127),
# or characters in the ascii range
# Both alternatives seem valid.
content_disposition
=
content_disposition
.
encode
(
'ascii'
)
if
False
:
else
:
# Require content_disposition to be ascii bytes (0-127),
# We allow non-ascii here (it will only be parsed inside of
# or characters in the ascii range
# qdtext, and rejected by the grammar if it appears in
content_disposition
=
content_disposition
.
encode
(
'ascii'
)
# other places), although parsing it can be ambiguous.
else
:
# Parsing it ensures that a non-ambiguous filename* value
# We allow non-ascii here (it will only be parsed inside of
# won't get dismissed because of an unrelated ambiguity
# qdtext, and rejected by the grammar if it appears in
# in the filename parameter. But it does mean we occasionally
# other places), although parsing it can be ambiguous.
# give less-than-certain values for some legacy senders.
# Parsing it ensures that a non-ambiguous filename* value
content_disposition
=
content_disposition
.
encode
(
'iso-8859-1'
)
# won't get dismissed because of an unrelated ambiguity
# Check the caller already did LWS-folding (normally done
# in the filename parameter. But it does mean we occasionally
# when separating header names and values; RFC 2616 section 2.2
# give less-than-certain values for some legacy senders.
# says it should be done before interpretation at any rate).
content_disposition
=
content_disposition
.
encode
(
'iso-8859-1'
)
# Since this is ascii the definition of space is known; I don't know
# what Python's definition of space chars will be if we allow
# Check the caller already did LWS-folding (normally done
# iso-8859-1.
# when separating header names and values; RFC 2616 section 2.2
# This check is a bit stronger that LWS folding, it will
# says it should be done before interpretation at any rate).
# remove CR and LF even if they aren't part of a CRLF.
# Since this is ascii the definition of space is known; I don't know
# However http doesn't allow isolated CR and LF in headers outside
# what Python's definition of space chars will be if we allow
# of LWS.
# iso-8859-1.
assert
is_lws_safe
(
content_disposition
)
# This check is a bit stronger that LWS folding, it will
parsed
=
content_disposition_value
.
parse
(
content_disposition
)
# remove CR and LF even if they aren't part of a CRLF.
return
ContentDisposition
(
# However http doesn't allow isolated CR and LF in headers outside
disposition
=
parsed
[
0
],
assocs
=
parsed
[
1
:],
location
=
location
)
# of LWS.
assert
is_lws_safe
(
content_disposition
)
@classmethod
def
from_httplib2_response
(
cls
,
response
):
parsed
=
content_disposition_value
.
parse
(
content_disposition
)
"""Build a ContentDisposition from an httplib2 response.
return
ContentDisposition
(
"""
disposition
=
parsed
[
0
],
assocs
=
parsed
[
1
:],
location
=
location
)
def
parse_httplib2_response
(
response
):
"""Build a ContentDisposition from an httplib2 response.
"""
return
cls
.
from
_headers
(
return
parse
_headers
(
response
[
'content-disposition'
],
response
[
'content-location'
])
response
[
'content-disposition'
],
response
[
'content-location'
])
def
parse_ext_value
(
val
):
def
parse_ext_value
(
val
):
...
@@ -298,7 +308,7 @@ def qd_quote(text):
...
@@ -298,7 +308,7 @@ def qd_quote(text):
return
text
.
replace
(
'
\\
'
,
'
\\\\
'
)
.
replace
(
'"'
,
'
\\
"'
)
return
text
.
replace
(
'
\\
'
,
'
\\\\
'
)
.
replace
(
'"'
,
'
\\
"'
)
def
header_for_filename
(
def
build_header
(
filename
,
disposition
=
'attachment'
,
filename_compat
=
None
filename
,
disposition
=
'attachment'
,
filename_compat
=
None
):
):
"""Generate a Content-Disposition header for a given filename.
"""Generate a Content-Disposition header for a given filename.
...
@@ -357,17 +367,17 @@ def header_for_filename(
...
@@ -357,17 +367,17 @@ def header_for_filename(
def
test_parsing
():
def
test_parsing
():
cdfh
=
ContentDisposition
.
from_headers
assert
parse_headers
(
None
)
.
disposition
==
'inline'
assert
ContentDisposition
()
.
disposition
==
'inline
'
assert
parse_headers
(
'attachment'
)
.
disposition
==
'attachment
'
assert
cdfh
(
'attachment'
)
.
disposition
==
'attachment
'
assert
parse_headers
(
'attachment; key=val'
)
.
assocs
[
'key'
]
==
'val
'
assert
cdfh
(
'attachment; key=val'
)
.
assocs
[
'key'
]
==
'val'
assert
parse_headers
(
assert
cdfh
(
'attachment; filename=simple'
)
.
filename_unsafe
==
'simple'
'attachment; filename=simple'
)
.
filename_unsafe
==
'simple'
# test ISO-8859-1
# test ISO-8859-1
fname
=
cdfh
(
u'attachment; filename="oyé"'
)
.
filename_unsafe
fname
=
parse_headers
(
u'attachment; filename="oyé"'
)
.
filename_unsafe
assert
fname
==
u'oyé'
,
repr
(
fname
)
assert
fname
==
u'oyé'
,
repr
(
fname
)
cd
=
cdfh
(
cd
=
parse_headers
(
'attachment; filename="EURO rates";'
'attachment; filename="EURO rates";'
' filename*=utf-8
\'\'
%
e2
%82%
ac
%20
rates'
)
' filename*=utf-8
\'\'
%
e2
%82%
ac
%20
rates'
)
assert
cd
.
filename_unsafe
==
u'€ rates'
assert
cd
.
filename_unsafe
==
u'€ rates'
...
@@ -375,8 +385,7 @@ def test_parsing():
...
@@ -375,8 +385,7 @@ def test_parsing():
def
test_roundtrip
():
def
test_roundtrip
():
def
roundtrip
(
filename
):
def
roundtrip
(
filename
):
return
ContentDisposition
.
from_headers
(
return
parse_headers
(
build_header
(
filename
))
.
filename_unsafe
header_for_filename
(
filename
))
.
filename_unsafe
def
assert_roundtrip
(
filename
):
def
assert_roundtrip
(
filename
):
assert
roundtrip
(
filename
)
==
filename
assert
roundtrip
(
filename
)
==
filename
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment