1 from mobi.mtld.da.exception.invalid_property_name_exception import InvalidPropertyNameException
2 from mobi.mtld.da.carrier.carrier_data import *
3 from mobi.mtld.da.property import *
4 from struct import unpack
5 from socket import *
8
9 """
10 A list of HTTP headers to choose the original client IP
11 address from. In addition to these the REMOTE_ADDR is
12 also used as a final fallback.
13 """
14 _HEADERS_TO_CHECK = [
15 "x-forwarded-for",
16 "client-ip",
17 "x-client-ip",
18 "rlnclientipaddr",
19 "proxy-client-ip",
20 "wl-proxy-client-ip",
21 "x-Forwarded",
22 "forwarded-for",
23 "forwarded"
24 ]
25
26 _VERSION = "1.0.1"
27
28 _PRIVATE = ([0, 4294967295],
29 [ 2130706432 , 4278190080 ],
30 [ 3232235520 , 4294901760 ],
31 [ 2886729728 , 4293918720 ],
32 [ 167772160 , 4278190080 ],
33 [ 2851995648, 65535])
34
35 _data = None
36
37 _MISSING_DATA_EX = "No data file loaded, load data with load_data_from_file()"
38 _INVALID_PROP_EX = "Property name \"%s\" does not exist"
39
47
54
61
68
70 """
71 Get the Carrier properties for a given IP address.
72 """
73 if(type(ipv4) is dict):
74 ipv4 = self.get_ip(ipv4)
75
76 props = None
77
78 self._dataLoaded()
79
80 if ipv4 != None:
81 props = self._data.getProperties(ipv4)
82
83 return props
84
86 """
87 Try and get a specific property for a given IP address.
88 Note : If mutiple properties are needed for the same IP
89 it is more efficient to call properties() once than
90 repeated calls to property()
91 """
92 if(type(propertyName) != str):
93 propertyName = propertyName.decode("utf-8")
94 if(type(ipv4) is dict):
95 ipv4 = self.get_ip(ipv4)
96
97 self._dataLoaded()
98 self.property_name_exists(propertyName)
99
100 prop = None
101 if ipv4 != None:
102 props = self._data.getProperties(ipv4)
103 if props != None and propertyName in props:
104 prop = props[propertyName]
105
106 return prop
107
109 """
110 A set of all the possible property names.
111 The set contains PropertyName objects that
112 each have a string name and an associated
113 data type.
114 """
115 self._dataLoaded()
116 return self._data.getPropertyNames()
117
124
133
134 @staticmethod
136 """
137 Normalise the keys in the passed in key value map.
138 This lower-cases the keys, replaces "_" with "-"
139 and removes any HTTP_ prefix.
140 """
141 for headerName in keyVals:
142 value = keyVals[headerName]
143 del(keyVals[headerName])
144
145 headerName = headerName.lower()
146 headerName = headerName.replace('_', '-')
147 headerName = headerName.replace('http-', '')
148
149 if type(value) == bytes:
150 value = value.decode("utf-8")
151
152 keyVals[headerName] = value
153
154 return keyVals
155
156 @staticmethod
158 """
159 Extracts and cleans an IP address from the headerValue.
160 Some headers such as "X-Forwarded-For" can contain multiple
161 IP addresses such as:
162 clientIP, proxy1, proxy2...
163 """
164 ip = None
165 keyVals = CarrierApi._normaliseKeys(keyVals)
166
167 if keyVals != None:
168 for headerName in CarrierApi._HEADERS_TO_CHECK:
169 if headerName not in keyVals:
170 continue
171 ip = CarrierApi.extract_ip(headerName, keyVals[headerName])
172 if ip != None:
173 break
174
175 return ip
176
182
183 @staticmethod
185 """
186 An IP address is considered public if it is not
187 in any of the following ranges:
188 1) any local address
189 IP: 0
190
191 2) a local loopback address
192 range: 127/8
193
194 3) a site local address i.e. IP is in any of the ranges:
195 range: 10/8
196 range: 172.16/12
197 range: 192.168/16
198
199 4) a link local address
200 """
201 try:
202 f = unpack("!I", inet_aton(ipv4))[0]
203 except(Exception) as ex:
204 return False
205
206 for rg in CarrierApi._PRIVATE:
207 if f & rg[1] == rg[0]:
208 return False
209
210 return True
211
212 @staticmethod
214 if headerValue != "" and headerValue != None:
215 if headerName.lower() == 'x-forwarded-for':
216 parts = headerValue.split(',')
217 if parts != None:
218 headerValue = parts[0]
219
220 headerValue = headerValue.strip()
221
222 if headerValue != None and CarrierApi.is_public_ip(headerValue):
223 return headerValue
224
225 return None
226