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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/python3
"""
module containing all the little sub routines
"""
from collections import OrderedDict
from datetime import datetime
import json
import socket
import geoip2.database
import geoip2.errors
from ipinfo import settings
# init geoip2 database reader
geo_reader = geoip2.database.Reader(settings.GEOLITE_DB)
def get_ip(request):
"""
gets an ip address, based on a request.
Filters for reverse proxies
"""
# taken from http://stackoverflow.com/a/22936947
route = request.access_route + [request.remote_addr]
return next((addr for addr in reversed(route)
if addr not in settings.TRUSTED_PROXIES), request.remote_addr)
def reverse_ip(ip):
try:
name, alias, addresslist = socket.gethostbyaddr(ip)
return name
except socket.herror:
# could not reverse-resolve this ip
return None
def query_data(request, query):
"""
creates the data dict, based on the query
"""
# populate data
data = OrderedDict()
if not query or 'query' in query:
data['query'] = query
if not query or 'ip' in query:
data['ip'] = get_ip(request)
if not query or 'dns' in query:
ip = data['ip'] if 'ip' in data else get_ip(request)
data['dns'] = reverse_ip(ip)
if not query or 'reqmethod' in query:
data['request-method'] = request.method
if not query or 'useragent' in query:
data['user-agent'] = request.headers.get('User-Agent', None)
if not query or 'time' in query:
data['time'] = datetime.now().isoformat()
if not query or any(k in query for k in ('geo', 'latitude', 'longitude', 'city', 'country', 'country-subdivision', 'continent', 'timezone')):
# acquire geo data
try:
ip = data['ip'] if 'ip' in data else get_ip(request)
# ip = '128.101.101.101' # test ip
location = geo_reader.city(ip)
except geoip2.errors.AddressNotFoundError:
# addr is not in the database
location = None
# check for universal query 'geo'
if query and 'geo' in query:
query.extend(['latitude', 'longitude', 'city', 'country', 'country-subdivision', 'continent', 'timezone'])
if not query or 'latitude' in query:
data['latitude'] = location.location.latitude if location else None
if not query or 'longitude' in query:
data['longitude'] = location.location.longitude if location else None
if not query or 'city' in query:
data['city'] = location.city.name if location and location.city else None
if not query or 'country' in query:
data['country'] = (location.country.name, location.country.iso_code) if location and location.country else None
if not query or 'country-subdivion' in query:
data['country-subdivision'] = (location.subdivisions.most_specific.name, location.subdivisions.most_specific.iso_code) if location and location.subdivisions else None
if not query or 'continent' in query:
data['continent'] = (location.continent.name, location.continent.code) if location and location.continent else None
if not query or 'timezone' in query:
data['timezone'] = location.location.time_zone if location else None
return data
def guess_format(request):
"""
guesses the format based on the Accept header
"""
return 'txt' # TODO
def format_text(data, justify=30):
if isinstance(data, (dict, OrderedDict)):
# data is map
resp = []
for key, value in data.items():
value = format_text(value, justify=justify).split('\n')
resp.append('\n'.join([(key.ljust(justify) + value[0])] + list(map(lambda v: ' '*justify+v, value[1:]))))
return '\n'.join(resp)
elif isinstance(data, (list, tuple)):
# data is in list format
return '\n'.join(data)
else:
# just some random data -> return it as string
return str(data)
def format_json(data, justify=2):
return json.dumps(data, sort_keys=False, indent=justify)