Source

django-flext / django_flext / middleware.py

Full commit
from django.conf import settings
from django.http import HttpResponseRedirect
from django.utils.http import urlquote

import django_flext
import re

MOBILE_DOMAIN_RE = getattr(settings, 'MOBILE_DOMAIN_MATCH', None)

if not MOBILE_DOMAIN_RE:
    MOBILE_DOMAIN_RE = re.compile(r'^(m|mobile)\.')
if isinstance(MOBILE_DOMAIN_RE, basestring):
    MOBILE_DOMAIN_RE = re.compile(MOBILE_DOMAIN_RE)

MOBILE_TEMPLATE_DIRS = getattr(settings, 'MOBILE_TEMPLATE_DIRS', None)


class BaseFlextMiddleware(object):
    """
    A middleware base class that provides the common flext reset methods for
    each request.

    """

    def process_response(self, request, response):
        django_flext.reset()
        return response

    #def process_exception(self, request, exception):
    #    django_flext.reset()


class MobileDomainMiddleware(BaseFlextMiddleware):
    """
    Middleware which adds one or more mobile-only template directories if
    the user is visiting from a mobile domain.
    
    """

    def process_request(self, request):
        if not MOBILE_TEMPLATE_DIRS:
            return
        host = request.get_host()
        if not host:
            return
        if MOBILE_DOMAIN_RE.search(host):
            django_flext.add_dirs(self, MOBILE_TEMPLATE_DIRS)
            request.is_mobile = True


class MobileDetectionMiddleware(object):
    """
    Useful middleware to detect if the user is
    on a mobile device.
    """

    def process_request(self, request):
        is_mobile = False;
        
        if request.META.has_key('HTTP_USER_AGENT'):
            user_agent = request.META['HTTP_USER_AGENT']

            # Test common mobile values.
            pattern = "(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|windows ce|pda|mobile|mini|palm|netfront)"
            prog = re.compile(pattern, re.IGNORECASE)
            match = prog.search(user_agent)

            if match:
                is_mobile = True;
            else:
                # Nokia like test for WAP browsers.
                # http://www.developershome.com/wap/xhtmlmp/xhtml_mp_tutorial.asp?page=mimeTypesFileExtension

                if request.META.has_key('HTTP_ACCEPT'):
                    http_accept = request.META['HTTP_ACCEPT']

                    pattern = "application/vnd\.wap\.xhtml\+xml"
                    prog = re.compile(pattern, re.IGNORECASE)

                    match = prog.search(http_accept)

                    if match:
                        is_mobile = True

            if not is_mobile:
                # Now we test the user_agent from a big list.
                user_agents_test = ("w3c ", "acs-", "alav", "alca", "amoi", "audi",
                                    "avan", "benq", "bird", "blac", "blaz", "brew",
                                    "cell", "cldc", "cmd-", "dang", "doco", "eric",
                                    "hipt", "inno", "ipaq", "java", "jigs", "kddi",
                                    "keji", "leno", "lg-c", "lg-d", "lg-g", "lge-",
                                    "maui", "maxo", "midp", "mits", "mmef", "mobi",
                                    "mot-", "moto", "mwbp", "nec-", "newt", "noki",
                                    "oper", "palm", "pana", "pant", "phil", "play",
                                    "port", "prox", "qwap", "sage", "sams", "sany",
                                    "sch-", "sec-", "send", "seri", "sgh-", "shar",
                                    "sie-", "siem", "smal", "smar", "sony", "sph-",
                                    "symb", "t-mo", "teli", "tim-", "tosh", "tsm-",
                                    "upg1", "upsi", "vk-v", "voda", "wap-", "wapa",
                                    "wapi", "wapp", "wapr", "webc", "winw", "winw",
                                    "xda", "xda-",)

                test = user_agent[0:4].lower()
                if test in user_agents_test:
                    is_mobile = True
                    
            request.is_mobile = is_mobile
            host = request.get_host()
            
            if is_mobile and not MOBILE_DOMAIN_RE.search(host):
                new_uri = '%s://%s%s%s' % (
                    request.is_secure() and 'https' or 'http',
                    settings.MOBILE_DOMAIN,
                    urlquote(request.path),
                    (request.method == 'GET' and len(request.GET) > 0) and '?%s' % request.GET.urlencode() or ''
                )
                return HttpResponseRedirect(new_uri)