This file is indexed.

/usr/lib/python2.7/dist-packages/ratelimit/helpers.py is in python-django-ratelimit 0.4.0+8+gd58c489-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import hashlib
import re

from django.conf import settings
from django.core.cache import get_cache


__all__ = ['is_ratelimited']

RATELIMIT_ENABLE = getattr(settings, 'RATELIMIT_ENABLE', True)
CACHE_PREFIX = getattr(settings, 'RATELIMIT_CACHE_PREFIX', 'rl:')

_PERIODS = {
    's': 1,
    'm': 60,
    'h': 60 * 60,
    'd': 24 * 60 * 60,
}

rate_re = re.compile('([\d]+)/([\d]*)([smhd])')


def _method_match(request, method=None):
    if method is None:
        return True
    if not isinstance(method, (list, tuple)):
        method = [method]
    return request.method in [m.upper() for m in method]


def _split_rate(rate):
    count, multi, period = rate_re.match(rate).groups()
    count = int(count)
    time = _PERIODS[period.lower()]
    if multi:
        time = time * int(multi)
    return count, time


def _get_keys(request, ip=True, field=None, keyfuncs=None):
    keys = []
    if ip:
        keys.append('ip:' + request.META['REMOTE_ADDR'])
    if field is not None:
        if not isinstance(field, (list, tuple)):
            field = [field]
        for f in field:
            val = getattr(request, request.method).get(f, '').encode('utf-8')
            val = hashlib.sha1(val).hexdigest()
            keys.append(u'field:%s:%s' % (f, val))
    if keyfuncs:
        if not isinstance(keyfuncs, (list, tuple)):
            keyfuncs = [keyfuncs]
        for k in keyfuncs:
            keys.append(k(request))
    return [CACHE_PREFIX + k for k in keys]


def _incr(cache, keys, timeout=60):
    # Yes, this is a race condition, but memcached.incr doesn't reset the
    # timeout.
    counts = cache.get_many(keys)
    for key in keys:
        if key in counts:
            counts[key] += 1
        else:
            counts[key] = 1
    cache.set_many(counts, timeout=timeout)
    return counts


def _get(cache, keys):
    counts = cache.get_many(keys)
    for key in keys:
        if key in counts:
            counts[key] += 1
        else:
            counts[key] = 1
    return counts


def is_ratelimited(request, increment=False, ip=True, method=['POST'],
                   field=None, rate='5/m', keys=None):
    count, period = _split_rate(rate)
    cache = getattr(settings, 'RATELIMIT_USE_CACHE', 'default')
    cache = get_cache(cache)

    request.limited = getattr(request, 'limited', False)
    if (not request.limited and RATELIMIT_ENABLE and
            _method_match(request, method)):
        _keys = _get_keys(request, ip, field, keys)
        if increment:
            counts = _incr(cache, _keys, period)
        else:
            counts = _get(cache, _keys)
        if any([c > count for c in counts.values()]):
            request.limited = True

    return request.limited