Skip to content

Commit

Permalink
Merge branch 'pdewacht-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsensible committed Jun 18, 2014
2 parents 0334cc8 + cffcfbf commit 9885eb5
Show file tree
Hide file tree
Showing 13 changed files with 55 additions and 30 deletions.
2 changes: 1 addition & 1 deletion examples/protected_downloads/download/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from .models import Download


class DownloadAdmin(admin.ModelAdmin):
list_display = ['title', 'file']

admin.site.register(Download, DownloadAdmin)

3 changes: 2 additions & 1 deletion examples/protected_downloads/download/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@

sendfile_storage = FileSystemStorage(location=settings.SENDFILE_ROOT)


class Download(models.Model):
users = models.ManyToManyField(User, blank=True)
is_public = models.BooleanField(default=True)
title = models.CharField(max_length=255)
# files stored in SENDFILE_ROOT directory (which should be protected)
file = models.FileField(upload_to='download', storage=sendfile_storage)

def is_user_allowed(self, user):
return self.users.filter(pk=user.pk).exists()

Expand Down
5 changes: 3 additions & 2 deletions examples/protected_downloads/download/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@

from .models import Download


def download(request, download_id):
download = get_object_or_404(Download, pk=download_id)
if download.is_public:
return sendfile(request, download.file.path)
return _auth_download(request, download)


@login_required
def _auth_download(request, download):
Expand All @@ -29,5 +30,5 @@ def download_list(request):
else:
downloads = downloads.filter(is_public=True)
return render_to_response('download/download_list.html',
{'download_list': downloads},
{'download_list': downloads},
context_instance=RequestContext(request))
5 changes: 4 additions & 1 deletion examples/protected_downloads/manage.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#!/usr/bin/env python

from __future__ import absolute_import

from django.core.management import execute_manager
try:
import settings # Assumed to be in the same directory.
from . import settings # Assumed to be in the same directory.
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
Expand Down
2 changes: 1 addition & 1 deletion examples/protected_downloads/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.load_template_source',
'django.template.loaders.app_directories.load_template_source',
# 'django.template.loaders.eggs.load_template_source',
# 'django.template.loaders.eggs.load_template_source',
)

MIDDLEWARE_CLASSES = (
Expand Down
7 changes: 4 additions & 3 deletions sendfile/backends/_internalredirect.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from django.conf import settings
from django.utils.http import urlquote
import os.path


def _convert_file_to_url(filename):
relpath = os.path.relpath(filename, settings.SENDFILE_ROOT)

url = [settings.SENDFILE_URL]

while relpath:
relpath, head = os.path.split(relpath)
url.insert(1, head)

return u'/'.join(url)

return urlquote(u'/'.join(url))
1 change: 1 addition & 0 deletions sendfile/backends/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import os.path


def sendfile(request, filename, **kwargs):
'''
Send file using django dev static file server.
Expand Down
6 changes: 4 additions & 2 deletions sendfile/backends/mod_wsgi.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from __future__ import absolute_import

from django.http import HttpResponse

from _internalredirect import _convert_file_to_url
from ._internalredirect import _convert_file_to_url


def sendfile(request, filename, **kwargs):
response = HttpResponse()
Expand All @@ -11,4 +14,3 @@ def sendfile(request, filename, **kwargs):
request.get_host = lambda: ''

return response

7 changes: 5 additions & 2 deletions sendfile/backends/nginx.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from __future__ import absolute_import

from django.http import HttpResponse

from _internalredirect import _convert_file_to_url
from ._internalredirect import _convert_file_to_url


def sendfile(request, filename, **kwargs):
response = HttpResponse()
url = _convert_file_to_url(filename)
response['X-Accel-Redirect'] = url.encode('utf-8')
response['X-Accel-Redirect'] = url

return response
15 changes: 9 additions & 6 deletions sendfile/backends/simple.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import os
import stat
import re
from email.Utils import parsedate_tz, mktime_tz
try:
from email.utils import parsedate_tz, mktime_tz
except ImportError:
from email.Utils import parsedate_tz, mktime_tz

from django.core.files.base import File
from django.http import HttpResponse, HttpResponseNotModified
from django.utils.http import http_date


def sendfile(request, filename, **kwargs):
# Respect the If-Modified-Since header.
statobj = os.stat(filename)

if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]):
return HttpResponseNotModified()


response = HttpResponse(File(file(filename, 'rb')))

response = HttpResponse(File(open(filename, 'rb')).chunks())

response["Last-Modified"] = http_date(statobj[stat.ST_MTIME])
return response



def was_modified_since(header=None, mtime=0, size=0):
"""
Was something modified since the user last downloaded it?
Expand Down Expand Up @@ -52,4 +56,3 @@ def was_modified_since(header=None, mtime=0, size=0):
except (AttributeError, ValueError, OverflowError):
return True
return False

5 changes: 3 additions & 2 deletions sendfile/backends/xsendfile.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from django.http import HttpResponse
from django.utils.encoding import smart_str


def sendfile(request, filename, **kwargs):
response = HttpResponse()
response['X-Sendfile'] = unicode(filename).encode('utf-8')
response['X-Sendfile'] = smart_str(unicode(filename))

return response

11 changes: 6 additions & 5 deletions sendfile/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.conf import settings
from django.test import TestCase
from django.http import HttpResponse, Http404, HttpRequest
from django.utils.encoding import smart_str
import os.path
from tempfile import mkdtemp
import shutil
Expand All @@ -20,7 +21,7 @@ class TempFileTestCase(TestCase):
def setUp(self):
super(TempFileTestCase, self).setUp()
self.TEMP_FILE_ROOT = mkdtemp()

def tearDown(self):
super(TempFileTestCase, self).tearDown()
if os.path.exists(self.TEMP_FILE_ROOT):
Expand All @@ -40,7 +41,7 @@ def setUp(self):
# set ourselves to be the sendfile backend
settings.SENDFILE_BACKEND = 'sendfile.tests'
_get_sendfile.clear()

def _get_readme(self):
return self.ensure_file('testfile.txt')

Expand All @@ -54,7 +55,7 @@ def test_sendfile(self):
response = real_sendfile(HttpRequest(), self._get_readme())
self.assertTrue(response is not None)
self.assertEqual('text/plain', response['Content-Type'])
self.assertEqual(self._get_readme(), response.content)
self.assertEqual(self._get_readme(), smart_str(response.content))

def test_set_mimetype(self):
response = real_sendfile(HttpRequest(), self._get_readme(), mimetype='text/plain')
Expand Down Expand Up @@ -104,7 +105,7 @@ def test_xsendfile_header_containing_unicode(self):
filepath = self.ensure_file(u'péter_là_gueule.txt')
response = real_sendfile(HttpRequest(), filepath)
self.assertTrue(response is not None)
self.assertEqual(filepath, response['X-Sendfile'].decode('utf-8'))
self.assertEqual(smart_str(filepath), response['X-Sendfile'])


class TestNginxBackend(TempFileTestCase):
Expand All @@ -126,4 +127,4 @@ def test_xaccelredirect_header_containing_unicode(self):
filepath = self.ensure_file(u'péter_là_gueule.txt')
response = real_sendfile(HttpRequest(), filepath)
self.assertTrue(response is not None)
self.assertEqual(u'/private/péter_là_gueule.txt', response['X-Accel-Redirect'].decode('utf-8'))
self.assertEqual('/private/p%C3%A9ter_l%C3%A0_gueule.txt', response['X-Accel-Redirect'])
16 changes: 12 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from distutils.core import setup

version=__import__('sendfile').__version__
try:
from distutils.command.build_py import build_py_2to3 as build_py
except ImportError:
from distutils.command.build_py import build_py


version = __import__('sendfile').__version__


setup(
Expand All @@ -12,7 +18,7 @@
author_email='john@sensibledevelopment.com',
url='https://github.com/johnsensible/django-sendfile',
license='BSD',

requires=['Django (>=1.3)', 'Unidecode'],
install_requires=['Django>=1.3', 'Unidecode'],

Expand All @@ -21,10 +27,10 @@
'sendfile': 'sendfile',
'sendfile.backends': 'sendfile/backends',
},
package_data = {
package_data={
'sendfile': ['testfile.txt'],
},

zip_safe=True,
classifiers=[
'Development Status :: 4 - Beta',
Expand All @@ -36,4 +42,6 @@
'Programming Language :: Python',
'Topic :: Software Development :: Libraries :: Python Modules',
],

cmdclass={'build_py': build_py},
)

0 comments on commit 9885eb5

Please sign in to comment.