1# -*- coding: utf-8 -*-
2
3import importlib
4
5from django.core.exceptions import ImproperlyConfigured
6from django.utils.translation import ugettext as _
7
8from cms.utils.conf import get_cms_setting
9
10
11def get_request_ip_resolver():
12    """
13    This is the recommended method for obtaining the specified
14    CMS_REQUEST_IP_RESOLVER as it also does some basic import validation.
15
16    Returns the resolver or raises an ImproperlyConfigured exception.
17    """
18    module, attribute = get_cms_setting('REQUEST_IP_RESOLVER').rsplit('.', 1)
19    try:
20        ip_resolver_module = importlib.import_module(module)
21        ip_resolver = getattr(ip_resolver_module, attribute)
22    except ImportError:
23        raise ImproperlyConfigured(
24            _('Unable to find the specified CMS_REQUEST_IP_RESOLVER module: '
25              '"{0}".').format(module))
26    except AttributeError:
27        raise ImproperlyConfigured(
28            _('Unable to find the specified CMS_REQUEST_IP_RESOLVER function: '
29              '"{0}" in module "{1}".').format(attribute, module))
30    return ip_resolver
31
32
33def default_request_ip_resolver(request):
34    """
35    This is a hybrid request IP resolver that attempts should address most
36    cases. Order is important here. A 'REAL_IP' header supersedes an
37    'X_FORWARDED_FOR' header which supersedes a 'REMOTE_ADDR' header.
38    """
39    return (
40        real_ip(request) or
41        x_forwarded_ip(request) or
42        remote_addr_ip(request)
43    )
44
45
46def real_ip(request):
47    """
48    Returns the IP Address contained in the HTTP_X_REAL_IP headers, if
49    present. Otherwise, `None`.
50
51    Should handle Nginx and some other WSGI servers.
52    """
53    return request.META.get('HTTP_X_REAL_IP')
54
55
56def remote_addr_ip(request):
57    """
58    Returns the IP Address contained in the 'REMOTE_ADDR' header, if
59    present. Otherwise, `None`.
60
61    Should be suitable for local-development servers and some HTTP servers.
62    """
63    return request.META.get('REMOTE_ADDR')
64
65
66def x_forwarded_ip(request):
67    """
68    Returns the IP Address contained in the 'HTTP_X_FORWARDED_FOR' header, if
69    present. Otherwise, `None`.
70
71    Should handle properly configured proxy servers.
72    """
73    ip_address_list = request.META.get('HTTP_X_FORWARDED_FOR')
74    if ip_address_list:
75        ip_address_list = ip_address_list.split(',')
76        return ip_address_list[0]
77