Bug#761106: web-app: Add support for non-ascii filenames
- To: Orestis Ioannou <orestis@oioannou.com>
- Cc: 761106@bugs.debian.org
- Subject: Bug#761106: web-app: Add support for non-ascii filenames
- From: Stefano Zacchiroli <zack@debian.org>
- Date: Mon, 16 Mar 2015 15:29:44 +0100
- Message-id: <[🔎] 20150316142944.GA32390@upsilon.cc>
- Reply-to: Stefano Zacchiroli <zack@debian.org>, 761106@bugs.debian.org
- In-reply-to: <5506B377.2060908@oioannou.com>
- References: <54FFFFA8.2090106@oioannou.com> <20150312131907.GA26397@upsilon.cc> <5501E4F9.5070606@oioannou.com> <20150313153220.GA29824@upsilon.cc> <5503122A.8080104@oioannou.com> <20150313164503.GA2661@upsilon.cc> <55033080.9050907@oioannou.com> <20150313212247.GA30116@upsilon.cc> <20150315214443.GB10936@upsilon.cc> <5506B377.2060908@oioannou.com>
tags 761106 + patch
thanks
On Mon, Mar 16, 2015 at 11:41:59AM +0100, Orestis Ioannou wrote:
> Subject: [PATCH] web app: Add support for non-ascii filenames and directories
Hey Orestis, thanks for your patch. I'm Cc:-ing the bug log to record
that a patch is available.
However, while it seems to fix the problem on my development machine, it
doesn't seem to be enough to fix it on sources.debian.net.
With your patch applied, sources.d.n still fails with the following
backtrace:
2015-03-16 14:21:00,712 ERROR: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128) [in /srv/debsources/debsources/app/views.py:137]
Traceback (most recent call last):
File "/srv/debsources/debsources/app/views.py", line 193, in dispatch_request
context = self.get_objects(**kwargs)
File "/srv/debsources/debsources/app/sources/views.py", line 330, in get_objects
return self._render_location(package, version, path)
File "/srv/debsources/debsources/app/sources/views.py", line 129, in _render_location
return self._render_directory(location)
File "/srv/debsources/debsources/app/sources/views.py", line 147, in _render_directory
content = directory.get_listing()
File "/srv/debsources/debsources/models.py", line 691, in get_listing
for f in os.listdir(self.sources_path))
File "/srv/debsources/debsources/models.py", line 691, in <genexpr>
for f in os.listdir(self.sources_path))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)
Whereas without your patch it failed with this (note that the backtrace
is indeed different, even though the origin line is the same):
2015-03-16 14:23:48,108 ERROR: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128) [in /srv/debsources/debsources/app/views.py:137]
Traceback (most recent call last):
File "/srv/debsources/debsources/app/views.py", line 193, in dispatch_request
context = self.get_objects(**kwargs)
File "/srv/debsources/debsources/app/sources/views.py", line 330, in get_objects
return self._render_location(package, version, path)
File "/srv/debsources/debsources/app/sources/views.py", line 129, in _render_location
return self._render_directory(location)
File "/srv/debsources/debsources/app/sources/views.py", line 147, in _render_directory
content = directory.get_listing()
File "/srv/debsources/debsources/models.py", line 687, in get_listing
for f in os.listdir(self.sources_path))
File "/srv/debsources/debsources/models.py", line 687, in <genexpr>
for f in os.listdir(self.sources_path))
File "/srv/debsources/debsources/models.py", line 680, in get_type
if os.path.isdir(os.path.join(self.sources_path, f)):
File "/usr/lib/python2.7/posixpath.py", line 78, in join
path += b
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)
Any idea what might be going on here?
TIA,
Cheers.
--
Stefano Zacchiroli . . . . . . . zack@upsilon.cc . . . . o . . . o . o
Maître de conférences . . . . . http://upsilon.cc/zack . . . o . . . o o
Former Debian Project Leader . . @zack on identi.ca . . o o o . . . o .
« the first rule of tautology club is the first rule of tautology club »
>From 994c768d3d1efaa2cddac2e16696cd6ca45f4a90 Mon Sep 17 00:00:00 2001
From: Orestis Ioannou <orestis@oioannou.com>
Date: Mon, 16 Mar 2015 11:38:53 +0100
Subject: [PATCH] web app: support non-ASCII filenames and directories
Closes: #761106
---
.../app/sources/templates/sources/source_folder.html | 4 ++--
debsources/models.py | 11 ++++++++---
debsources/tests/test_webapp.py | 19 +++++++++++++++++++
3 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/debsources/app/sources/templates/sources/source_folder.html b/debsources/app/sources/templates/sources/source_folder.html
index 54d73a1..1c78cc6 100644
--- a/debsources/app/sources/templates/sources/source_folder.html
+++ b/debsources/app/sources/templates/sources/source_folder.html
@@ -42,7 +42,7 @@
{% if config["DIR_LS_LONG"] %}<td class="stat-type"><span>{{ dir.stat.type }}</span></td>{% endif %}
<td class="stat-perms"><span>{{ dir.stat.perms }}</span></td>
{% if config["DIR_LS_LONG"] %}<td class="stat-size"><span>{{ "{:,d}".format(dir.stat.size) }}</span></td>{% endif %}
- <td class="item-name"><a href="{{ url_for('.source', path_to=path+'/'+dir.name) }}">{{ dir.name }}</a>
+ <td class="item-name"><a href="{{ url_for('.source', path_to=path+'/'+dir.name.decode('utf-8')) }}">{{ dir.name.decode('utf-8') }}</a>
{% if config["DIR_LS_LONG"] %}
{% if dir.stat.symlink_dest is not none %}{{ " → " + dir.stat.symlink_dest }}{% endif %}
{% endif %}
@@ -56,7 +56,7 @@
{% if config["DIR_LS_LONG"] %}<td class="stat-type"><span>{{ file_.stat.type }}</span></td>{% endif %}
<td class="stat-perms"><span>{{ file_.stat.perms }}</span></td>
{% if config["DIR_LS_LONG"] %}<td class="stat-size"><span>{{ "{:,d}".format(file_.stat.size) }}</span></td>{% endif %}
- <td class="item-name"><a href="{{ url_for('.source', path_to=path+'/'+file_.name) }}">{{ file_.name }}</a>
+ <td class="item-name"><a href="{{ url_for('.source', path_to=path+'/'+file_.name.decode('utf-8')) }}">{{ file_.name.decode('utf-8') }}</a>
{% if config["DIR_LS_LONG"] %}
{% if file_.stat.symlink_dest is not none %}{{ " → " + file_.stat.symlink_dest }}{% endif %}
{% endif %}
diff --git a/debsources/models.py b/debsources/models.py
index c47094c..3d72589 100644
--- a/debsources/models.py
+++ b/debsources/models.py
@@ -48,6 +48,8 @@ Base = declarative_base()
# used for migrations, see scripts under debsources/migrate/
DB_SCHEMA_VERSION = 8
+PATH_ENCODING = 'utf-8'
+
class PackageName(Base):
""" a source package name """
@@ -682,13 +684,15 @@ class Directory(object):
else:
return "file"
get_stat, join_path = self.location.get_stat, os.path.join
- listing = sorted(dict(name=f, type=get_type(f), hidden=False,
+ listing = sorted(dict(name=f.encode(PATH_ENCODING),
+ type=get_type(f),
+ hidden=False,
stat=get_stat(join_path(self.sources_path, f)))
for f in os.listdir(self.sources_path))
for hidden_file in self.hidden_files:
for f in listing:
- full_path = os.path.join(self.location.sources_path, f['name'])
+ full_path = os.path.join(self.location.sources_path, f['name'].decode('utf-8'))
if f['type'] == "directory":
full_path += "/"
f['hidden'] = (f['hidden']
@@ -725,13 +729,14 @@ class SourceFile(object):
"""
Queries the DB and returns the shasum of the file.
"""
+ path = self.location.path.encode(PATH_ENCODING)
shasum = session.query(Checksum.sha256) \
.filter(Checksum.package_id == Package.id) \
.filter(Package.name_id == PackageName.id) \
.filter(File.id == Checksum.file_id) \
.filter(PackageName.name == self.location.package) \
.filter(Package.version == self.location.version) \
- .filter(File.path == str(self.location.path)) \
+ .filter(File.path == str(path)) \
.first()
# WARNING: in the DB path is binary, and here
# location.path is unicode, because the path comes from
diff --git a/debsources/tests/test_webapp.py b/debsources/tests/test_webapp.py
index 3b4b790..1411cb5 100644
--- a/debsources/tests/test_webapp.py
+++ b/debsources/tests/test_webapp.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
# Copyright (C) 2013 Matthieu Caneill <matthieu.caneill@gmail.com>
# 2015 Stefano Zacchiroli <zack@upsilon.cc>
#
@@ -300,6 +301,20 @@ class DebsourcesTestCase(unittest.TestCase, DbTestFixture):
"symlink_dest": None}
}, rv['content'])
+ def test_api_folder_utf8(self):
+ rv = json.loads(self.app.get('/api/src/cvsnt/2.5.03.2382-3/').data)
+ self.assertEqual(rv['type'], "directory")
+ self.assertEqual(rv['package'], "cvsnt")
+ self.assertEqual(rv['directory'], "2.5.03.2382-3")
+ self.assertIn({"type": "file",
+ "name": u"testáéíóú.txt",
+ "hidden": False,
+ "stat": {u'perms': u'rw-r--r--',
+ u'type': u'-',
+ u'symlink_dest': None,
+ u'size': 5}
+ },rv['content'])
+
def test_api_symlink_dest(self):
rv = json.loads(self.app.get('/api/src/beignet/1.0.0-1/').data)
self.assertIn({"type": "file",
@@ -373,6 +388,10 @@ class DebsourcesTestCase(unittest.TestCase, DbTestFixture):
self.assertIn('<a href="/src/ledit/2.01-6/">parent folder</a>',
rv.data)
+ def test_source_file_utf8(self):
+ rv = self.app.get('src/cvsnt/2.5.03.2382-3/testáéíóú.txt/')
+ self.assertIn('File: testáéíóú.txt', rv.data)
+
def test_source_file_text(self):
rv = self.app.get('/src/ledit/2.01-6/README/')
self.assertIn('<code id="sourcecode" class="no-highlight">', rv.data)
--
2.1.4
Reply to: