8 """ |
8 """ |
9 |
9 |
10 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer |
10 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer |
11 from types import ListType, StringType |
11 from types import ListType, StringType |
12 import os, re, sys, time, urllib |
12 import os, re, sys, time, urllib |
|
13 |
|
14 from django.utils._os import safe_join |
13 |
15 |
14 __version__ = "0.1" |
16 __version__ = "0.1" |
15 __all__ = ['WSGIServer','WSGIRequestHandler','demo_app'] |
17 __all__ = ['WSGIServer','WSGIRequestHandler','demo_app'] |
16 |
18 |
17 server_version = "WSGIServer/" + __version__ |
19 server_version = "WSGIServer/" + __version__ |
597 def __init__(self, application, media_dir=None): |
599 def __init__(self, application, media_dir=None): |
598 from django.conf import settings |
600 from django.conf import settings |
599 self.application = application |
601 self.application = application |
600 if not media_dir: |
602 if not media_dir: |
601 import django |
603 import django |
602 self.media_dir = django.__path__[0] + '/contrib/admin/media' |
604 self.media_dir = \ |
|
605 os.path.join(django.__path__[0], 'contrib', 'admin', 'media') |
603 else: |
606 else: |
604 self.media_dir = media_dir |
607 self.media_dir = media_dir |
605 self.media_url = settings.ADMIN_MEDIA_PREFIX |
608 self.media_url = settings.ADMIN_MEDIA_PREFIX |
|
609 |
|
610 def file_path(self, url): |
|
611 """ |
|
612 Returns the path to the media file on disk for the given URL. |
|
613 |
|
614 The passed URL is assumed to begin with ADMIN_MEDIA_PREFIX. If the |
|
615 resultant file path is outside the media directory, then a ValueError |
|
616 is raised. |
|
617 """ |
|
618 # Remove ADMIN_MEDIA_PREFIX. |
|
619 relative_url = url[len(self.media_url):] |
|
620 relative_path = urllib.url2pathname(relative_url) |
|
621 return safe_join(self.media_dir, relative_path) |
606 |
622 |
607 def __call__(self, environ, start_response): |
623 def __call__(self, environ, start_response): |
608 import os.path |
624 import os.path |
609 |
625 |
610 # Ignore requests that aren't under ADMIN_MEDIA_PREFIX. Also ignore |
626 # Ignore requests that aren't under ADMIN_MEDIA_PREFIX. Also ignore |
612 if self.media_url.startswith('http://') or self.media_url.startswith('https://') \ |
628 if self.media_url.startswith('http://') or self.media_url.startswith('https://') \ |
613 or not environ['PATH_INFO'].startswith(self.media_url): |
629 or not environ['PATH_INFO'].startswith(self.media_url): |
614 return self.application(environ, start_response) |
630 return self.application(environ, start_response) |
615 |
631 |
616 # Find the admin file and serve it up, if it exists and is readable. |
632 # Find the admin file and serve it up, if it exists and is readable. |
617 relative_url = environ['PATH_INFO'][len(self.media_url):] |
633 try: |
618 file_path = os.path.join(self.media_dir, relative_url) |
634 file_path = self.file_path(environ['PATH_INFO']) |
|
635 except ValueError: # Resulting file path was not valid. |
|
636 status = '404 NOT FOUND' |
|
637 headers = {'Content-type': 'text/plain'} |
|
638 output = ['Page not found: %s' % environ['PATH_INFO']] |
|
639 start_response(status, headers.items()) |
|
640 return output |
619 if not os.path.exists(file_path): |
641 if not os.path.exists(file_path): |
620 status = '404 NOT FOUND' |
642 status = '404 NOT FOUND' |
621 headers = {'Content-type': 'text/plain'} |
643 headers = {'Content-type': 'text/plain'} |
622 output = ['Page not found: %s' % file_path] |
644 output = ['Page not found: %s' % environ['PATH_INFO']] |
623 else: |
645 else: |
624 try: |
646 try: |
625 fp = open(file_path, 'rb') |
647 fp = open(file_path, 'rb') |
626 except IOError: |
648 except IOError: |
627 status = '401 UNAUTHORIZED' |
649 status = '401 UNAUTHORIZED' |
628 headers = {'Content-type': 'text/plain'} |
650 headers = {'Content-type': 'text/plain'} |
629 output = ['Permission denied: %s' % file_path] |
651 output = ['Permission denied: %s' % environ['PATH_INFO']] |
630 else: |
652 else: |
631 status = '200 OK' |
653 status = '200 OK' |
632 headers = {} |
654 headers = {} |
633 output = [fp.read()] |
655 output = [fp.read()] |
634 fp.close() |
656 fp.close() |