Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

send_file doesn't urlencode ':/' in unicode attachment_filename #3074

Closed
i-akhmadullin opened this issue Jan 15, 2019 · 5 comments
Closed

send_file doesn't urlencode ':/' in unicode attachment_filename #3074

i-akhmadullin opened this issue Jan 15, 2019 · 5 comments
Milestone

Comments

@i-akhmadullin
Copy link

@i-akhmadullin i-akhmadullin commented Jan 15, 2019

Expected Behavior

When sending files with unicode filename (with : or /) they should be downloaded with name from filename* field.

# -*- coding: utf-8 -*-
import os
from flask import Flask, send_from_directory
app = Flask(__name__)
@app.route('/test/', methods=['GET'])
def test_route():
    tmp_dir = os.getcwd()
    tmp_filename = __file__
    attachment_filename = u'тест:тест_тест.py'
    return send_from_directory(
        tmp_dir,
        tmp_filename,
        as_attachment=True,
        attachment_filename=attachment_filename
    )
if __name__ == '__main__':
    app.run(host='::', port=5000)

Actual Behavior

Some browsers (Chrome-based/Safari) ignore filename* field when it contains colon or slash. For example file тест:тест_тест.py gets downloaded in Chrome/Safari as __.py but in Firefox as тест_тест_тест.py which is acceptable in my opinion.

Flask response:
Content-Disposition: attachment; filename*="UTF-8''%D1%82%D0%B5%D1%81%D1%82:%D1%82%D0%B5%D1%81%D1%82_%D1%82%D0%B5%D1%81%D1%82.py"; filename=":_.py"

Environment

  • Python version: 2.7.15
  • Flask version: 1.0.2
  • Werkzeug version: 0.14.1
@eladm26
Copy link
Contributor

@eladm26 eladm26 commented Feb 19, 2019

Hi @i-akhmadullin
according to the RFC: both "filename" and "filename*" are present in a single header field value, recipients SHOULD pick "filename*" and ignore "filename"
So it seems like an issue of chrome rather than flask.

Loading

@davidism
Copy link
Member

@davidism davidism commented Feb 19, 2019

This was working in Chrome when I implemented this. If they're changing behavior, that's incorrect and needs to be reported to them. I don't think Flask can do anything about it because it still needs to send both for compatibility with other clients.

Loading

@i-akhmadullin
Copy link
Author

@i-akhmadullin i-akhmadullin commented Feb 19, 2019

This issue is about encoding colon and slash in attachment filename, not about filename/filename*.
If we encode colon and slash characters then file gets downloaded with a utf8-name, but with underscores instead colons and slashes. But otherwise this is a lot better result than ascii-only filename (тест_тест_тест.py vs _.py).

Flask uses url_quote from werkzeug where :/ are listed as safe characters, so maybe it just an oversight that they are not escaped.

'filename*': "UTF-8''%s" % url_quote(attachment_filename),

https://github.com/pallets/werkzeug/blob/master/werkzeug/urls.py#L518

Loading

@davidism
Copy link
Member

@davidism davidism commented Feb 19, 2019

Your description in "actual behavior" makes no mention of how ":/" relate to the issue, it just mentions "filename" and "filename*". Could you review and make sure the issue accurately represents what you're trying to describe?

Loading

@i-akhmadullin
Copy link
Author

@i-akhmadullin i-akhmadullin commented Feb 19, 2019

@davidism sorry for the confusion, should be clearer now

Loading

@davidism davidism added this to the 1.0.4 milestone Jun 27, 2019
@davidism davidism closed this Jun 27, 2019
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants