16
16
import urllib
17
17
18
18
from django .utils .http import http_date
19
+ from django .utils ._os import safe_join
19
20
20
21
__version__ = "0.1"
21
22
__all__ = ['WSGIServer' ,'WSGIRequestHandler' ]
@@ -621,11 +622,25 @@ def __init__(self, application, media_dir=None):
621
622
self .application = application
622
623
if not media_dir :
623
624
import django
624
- self .media_dir = django .__path__ [0 ] + '/contrib/admin/media'
625
+ self .media_dir = \
626
+ os .path .join (django .__path__ [0 ], 'contrib' , 'admin' , 'media' )
625
627
else :
626
628
self .media_dir = media_dir
627
629
self .media_url = settings .ADMIN_MEDIA_PREFIX
628
630
631
+ def file_path (self , url ):
632
+ """
633
+ Returns the path to the media file on disk for the given URL.
634
+
635
+ The passed URL is assumed to begin with ADMIN_MEDIA_PREFIX. If the
636
+ resultant file path is outside the media directory, then a ValueError
637
+ is raised.
638
+ """
639
+ # Remove ADMIN_MEDIA_PREFIX.
640
+ relative_url = url [len (self .media_url ):]
641
+ relative_path = urllib .url2pathname (relative_url )
642
+ return safe_join (self .media_dir , relative_path )
643
+
629
644
def __call__ (self , environ , start_response ):
630
645
import os .path
631
646
@@ -636,19 +651,25 @@ def __call__(self, environ, start_response):
636
651
return self .application (environ , start_response )
637
652
638
653
# Find the admin file and serve it up, if it exists and is readable.
639
- relative_url = environ ['PATH_INFO' ][len (self .media_url ):]
640
- file_path = os .path .join (self .media_dir , relative_url )
654
+ try :
655
+ file_path = self .file_path (environ ['PATH_INFO' ])
656
+ except ValueError : # Resulting file path was not valid.
657
+ status = '404 NOT FOUND'
658
+ headers = {'Content-type' : 'text/plain' }
659
+ output = ['Page not found: %s' % environ ['PATH_INFO' ]]
660
+ start_response (status , headers .items ())
661
+ return output
641
662
if not os .path .exists (file_path ):
642
663
status = '404 NOT FOUND'
643
664
headers = {'Content-type' : 'text/plain' }
644
- output = ['Page not found: %s' % file_path ]
665
+ output = ['Page not found: %s' % environ [ 'PATH_INFO' ] ]
645
666
else :
646
667
try :
647
668
fp = open (file_path , 'rb' )
648
669
except IOError :
649
670
status = '401 UNAUTHORIZED'
650
671
headers = {'Content-type' : 'text/plain' }
651
- output = ['Permission denied: %s' % file_path ]
672
+ output = ['Permission denied: %s' % environ [ 'PATH_INFO' ] ]
652
673
else :
653
674
# This is a very simple implementation of conditional GET with
654
675
# the Last-Modified header. It makes media files a bit speedier
0 commit comments