Repository: zestedesavoir/zds-site

Issue:
Mauvaise redirection sur « zestedesavoir.com/tutoriels/telecharger/html/%3Ftutoriel%3D<n> »
Quand on essaye d'accéder à « http://zestedesavoir.com/tutoriels/telecharger/html/%3Ftutoriel%3D432 », un « / » est automatiquement rajouté à la fin et fait tout planter (ce qui n'est pas le cas avec http://zestedesavoir.com/tutoriels/telecharger/html/?tutoriel=432). Je suppose que ça vient de `APPEND_SLASH` qui est à `True` par défaut (est c'est bien ; https://docs.djangoproject.com/en/dev/ref/settings/#append-slash) mais un certain nombre de personnes ont eu accès à ce lien (dont Google Bot).

Il faudrait vérifier dans `zds/tutorial/views.py` ligne 2904 que `request.GET["tutoriel"]` est bien un int, si c'est pas le cas on check si c'est un int suivit de « / » et on vire le « / » ?

Autre problème : comment à l'heure actuelle 50 personnes ont eu un lien foireux ? Ça concerne plusieurs tutoriels.



Discussion:
C'est pas ngnix qui rajoute le slash ?

> C'est pas ngnix qui rajoute le slash ?

si


Resolving patch:
diff --git a/zds/tutorial/views.py b/zds/tutorial/views.py
--- a/zds/tutorial/views.py
+++ b/zds/tutorial/views.py
@@ -2900,7 +2900,22 @@ def insert_into_zip(zip_file, git_tree):
 
 def download(request):
     """Download a tutorial."""
-    tutorial = get_object_or_404(Tutorial, pk=request.GET["tutoriel"])
+
+    # check if tutoriel is an int
+
+    try:
+        tutorial = get_object_or_404(Tutorial, pk=request.GET['tutoriel'])
+    except ValueError:
+        # if not, check if it's int + '/' (nginx bug ?)
+        try:
+            # chek if "tutoriel" is not empty
+            tuto = request.GET['tutoriel']
+            if tuto != '' and tuto[-1:] == '/':
+                tutorial = get_object_or_404(Tutorial, pk=request.GET['tutoriel'][:-1])
+            else:
+                raise Http404
+        except ValueError:
+            raise Http404
 
     repo_path = os.path.join(settings.ZDS_APP['tutorial']['repo_path'], tutorial.get_phy_slug())
     repo = Repo(repo_path)
@@ -2914,8 +2929,8 @@ def download(request):
     zip_file = zipfile.ZipFile(zip_path, 'w')
     insert_into_zip(zip_file, repo.commit(sha).tree)
     zip_file.close()
-    response = HttpResponse(open(zip_path, "rb").read(), content_type="application/zip")
-    response["Content-Disposition"] = "attachment; filename={0}.zip".format(tutorial.slug)
+    response = HttpResponse(open(zip_path, 'rb').read(), content_type='application/zip')
+    response['Content-Disposition'] = 'attachment; filename={0}.zip'.format(tutorial.slug)
     os.remove(zip_path)
     return response
 


Test patch:
diff --git a/zds/tutorial/tests.py b/zds/tutorial/tests.py
--- a/zds/tutorial/tests.py
+++ b/zds/tutorial/tests.py
@@ -2278,6 +2278,31 @@ def test_workflow_archive_tuto(self):
         f = open(draft_zip_path, 'w')
         f.write(result.content)
         f.close()
+
+        # check if it's OK when we add a '/' at then end of URL
+        result = self.client.get(
+            reverse('zds.tutorial.views.download') +
+            '?tutoriel={0}/'.format(
+                self.bigtuto.pk),
+            follow=False)
+        self.assertEqual(result.status_code, 200)
+
+        # check if 404 when we add a to many chars at then end of URL
+        result = self.client.get(
+            reverse('zds.tutorial.views.download') +
+            '?tutoriel={0}/foo'.format(
+                self.bigtuto.pk),
+            follow=False)
+        self.assertEqual(result.status_code, 404)
+
+        # check if 404 when we add a char != '/' at the end of URL
+        result = self.client.get(
+            reverse('zds.tutorial.views.download') +
+            '?tutoriel={0}a'.format(
+                self.bigtuto.pk),
+            follow=False)
+        self.assertEqual(result.status_code, 404)
+
         # 2. online version :
         result = self.client.get(
             reverse('zds.tutorial.views.download') +