def test_relaxed(): assert parse_headers('attachment;', relaxed=True).disposition == 'attachment' assert parse_headers('attachment; key=val;', relaxed=True).disposition == 'attachment' cd = parse_headers('attachment; filename="spa ced";', relaxed=True) assert cd.filename_unsafe == 'spa ced'
def test_location_fallback(): assert parse_headers( None, location='https://foo/bar%c3%a9.py').filename_unsafe == 'baré.py' assert parse_headers(None, location='https://foo/').filename_unsafe == '' assert parse_headers( None, location='https://foo/%C3%A9toil%C3%A9/').filename_unsafe == 'étoilé'
def test_strict(): # Trailing ; means the header is rejected assert parse_headers('attachment;').disposition == 'inline' assert parse_headers('attachment; key=val;').disposition == 'inline' try: cd = parse_headers('attachment; filename="spa ced";') except ValueError: assert True else: assert False, cd
def test_parsing(): assert parse_headers(None).disposition == 'inline' assert parse_headers('attachment').disposition == 'attachment' assert parse_headers('attachment; key=val').assocs['key'] == 'val' assert parse_headers( 'attachment; filename=simple').filename_unsafe == 'simple' # test ISO-8859-1 fname = parse_headers('attachment; filename="oyé"').filename_unsafe assert fname == 'oyé', repr(fname) cd = parse_headers('attachment; filename="EURO rates";' ' filename*=utf-8\'\'%e2%82%ac%20rates') assert cd.filename_unsafe == '€ rates'
def test_parsing(): assert parse_headers(None).disposition == 'inline' assert parse_headers('attachment').disposition == 'attachment' assert parse_headers('attachment; key=val').assocs['key'] == 'val' assert parse_headers( 'attachment; filename=simple').filename_unsafe == 'simple' fname = parse_headers( b'attachment; filename="oy\xe9"'.decode('latin-1')).filename_unsafe assert fname == u'oyé', repr(fname) cd = parse_headers('attachment; filename="EURO rates";' ' filename*=utf-8\'\'%e2%82%ac%20rates') assert cd.filename_unsafe == u'€ rates'
def generate_blob_download_url(self, blob: Blob, expires: int = 3600, method: str = 'GET', content_disposition: str = None, extra: ExtraOptions = None) -> str: if extra: logger.info(option_not_supported % 'extra') key = self._get_temp_url_key() storage_public_url = self._get_server_public_url('cloudFiles') url = '%s/%s' % (storage_public_url, quote(blob.path)) base_url, object_path = url.split('/v1/') object_path = '/v1/' + object_path # Time must be in UNIX epoch format. expires_in = int(time() + expires) hmac_body = '%s\n%s\n%s' % (method.upper(), expires_in, object_path) signature = hmac.new(key.encode('utf-8'), hmac_body.encode('utf-8'), hashlib.sha1).hexdigest() parameters = { 'temp_url_sig': signature, 'temp_url_expires': expires_in, } # Rackspace uses query params: filename (attachment) and inline if content_disposition: disposition_parsed = parse_headers(content_disposition) if disposition_parsed.filename_unsafe: parameters['filename'] = disposition_parsed.filename_unsafe else: parameters['filename'] = blob.name if disposition_parsed.disposition == 'inline': parameters['inline'] = '' return '%s%s?%s' % (base_url, object_path, urlencode(parameters))
def test_blob_generate_download_url(binary_blob, temp_file): content_disposition = BINARY_OPTIONS.get('content_disposition') download_url = binary_blob.generate_download_url( content_disposition=content_disposition) assert uri_validator(download_url) response = requests.get(download_url) assert response.status_code == HTTPStatus.OK, response.text # Rackspace adds extra garbage to the header # 'attachment; filename=avatar-attachment.png; # filename*=UTF-8\\'\\'avatar-attachment.png' parsed_disposition = parse_headers(response.headers['content-disposition']) response_disposition = '{}; filename={}'.format( parsed_disposition.disposition, parsed_disposition.filename_unsafe) assert response_disposition == content_disposition with open(temp_file, 'wb') as f: for chunk in response.iter_content(chunk_size=128): f.write(chunk) hash_type = binary_blob.driver.hash_type download_hash = file_checksum(temp_file, hash_type=hash_type) assert download_hash == BINARY_MD5_CHECKSUM
def roundtrip(filename): return parse_headers(build_header(filename)).filename_unsafe
def static_file(self, urlpath, response=None): root = os.path.abspath(self._cmd.root) + os.sep res = HttpResponse() mimetype = None disposition = None if isinstance(self._cmd.name, RePatternType) and self._cmd.replacement: # pylint: disable=protected-access filename = self._cmd.name.sub(self._cmd.replacement, urlpath) else: filename = urlpath filename = os.path.abspath(os.path.join(root, filename.strip('/\\'))) if not filename.startswith(root): raise self.req_error(403, "Access denied.") if not os.path.exists(filename) or not os.path.isfile(filename): raise self.req_error(404, "File does not exist.") if not os.access(filename, os.R_OK): raise self.req_error(403, "You do not have permission to access this file.") if self._cmd.content_type: mimetype = self._cmd.content_type if isinstance(response, HttpResponse): res = response if not mimetype: mimetype = res.get_header('Content-type') disposition = res.get_header('Content-disposition') if not mimetype or mimetype == '__MAGIC__': try: mime = magic.open(magic.MAGIC_MIME_TYPE) mime.load() mimetype = mime.file(filename) except AttributeError: mimetype = magic.from_file(filename, mime = True) if mimetype == 'image/svg': mimetype += '+xml' if mimetype: res.add_header('Content-type', mimetype) else: mimetype = mimetype.lower() if mimetype.startswith('text/') \ and self._cmd.charset \ and mimetype.find('charset') == -1: res.add_header('Content-type', "%s; charset=%s" % (mimetype, self._cmd.charset)) else: res.add_header('Content-type', mimetype) if disposition: attachment = parse_headers(disposition) if attachment.disposition == 'attachment' \ and not attachment.filename_unsafe: res.add_header('Content-disposition', build_header(os.path.basename(filename))) stats = os.stat(filename) res.add_header('Last-Modified', time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(stats.st_mtime))) if_modified = self.headers.get('If-Modified-Since') if if_modified: if_modified = self.parse_date(if_modified.split(';')[0].strip()) if if_modified >= int(stats.st_mtime): return res.set_code(304).set_send_body(False) f = None body = binary_type() if self.command != 'HEAD': with open(filename, 'rb') as f: while True: buf = f.read(BUFFER_SIZE) if not buf: break body += buf if f: f.close() return res.set_code(200).add_data(body)
def test_roundtrip(name): header = build_header(name) header = parse_headers(header) assert header.filename_unsafe == name