howler-api 3.0.0.dev351__py3-none-any.whl → 3.0.0.dev363__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of howler-api might be problematic. Click here for more details.
- howler/actions/__init__.py +3 -2
- howler/api/v1/action.py +2 -2
- howler/api/v1/configs.py +4 -1
- howler/api/v1/hit.py +1 -1
- howler/api/v1/user.py +4 -2
- howler/common/README.md +0 -19
- howler/helper/oauth.py +1 -1
- howler/services/config_service.py +1 -1
- howler/services/user_service.py +2 -1
- {howler_api-3.0.0.dev351.dist-info → howler_api-3.0.0.dev363.dist-info}/METADATA +1 -1
- {howler_api-3.0.0.dev351.dist-info → howler_api-3.0.0.dev363.dist-info}/RECORD +13 -15
- howler/common/hexdump.py +0 -48
- howler/common/iprange.py +0 -171
- {howler_api-3.0.0.dev351.dist-info → howler_api-3.0.0.dev363.dist-info}/WHEEL +0 -0
- {howler_api-3.0.0.dev351.dist-info → howler_api-3.0.0.dev363.dist-info}/entry_points.txt +0 -0
howler/actions/__init__.py
CHANGED
|
@@ -74,7 +74,7 @@ def __sanitize_report(report: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
|
74
74
|
def execute(
|
|
75
75
|
operation_id: str,
|
|
76
76
|
query: str,
|
|
77
|
-
user: User,
|
|
77
|
+
user: User | None,
|
|
78
78
|
request_id: Optional[str] = None,
|
|
79
79
|
**kwargs,
|
|
80
80
|
) -> list[dict[str, Any]]:
|
|
@@ -117,7 +117,8 @@ def execute(
|
|
|
117
117
|
}
|
|
118
118
|
]
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
user_roles: set[str] = set(user["type"] if user else [])
|
|
121
|
+
missing_roles = set(operation.specification()["roles"]) - user_roles
|
|
121
122
|
if missing_roles:
|
|
122
123
|
return [
|
|
123
124
|
{
|
howler/api/v1/action.py
CHANGED
|
@@ -237,7 +237,7 @@ def execute_action(id: str, **kwargs) -> Response:
|
|
|
237
237
|
return not_found(err="The specified action does not exist")
|
|
238
238
|
|
|
239
239
|
reports: dict[str, list[dict]] = {}
|
|
240
|
-
current_user = kwargs.get("user", None)
|
|
240
|
+
current_user: User | None = kwargs.get("user", None)
|
|
241
241
|
|
|
242
242
|
for operation in action.operations:
|
|
243
243
|
op_data = json.loads(operation["data_json"])
|
|
@@ -333,7 +333,7 @@ def execute_operations(**kwargs) -> Response:
|
|
|
333
333
|
return bad_request(err="Incorrect data structure!")
|
|
334
334
|
|
|
335
335
|
reports: dict[str, list[dict]] = {}
|
|
336
|
-
current_user = kwargs.get("user", None)
|
|
336
|
+
current_user: User | None = kwargs.get("user", None)
|
|
337
337
|
operations = execute_req["operations"]
|
|
338
338
|
|
|
339
339
|
operation_ids = [o["operation_id"] for o in operations]
|
howler/api/v1/configs.py
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
from typing import cast
|
|
2
|
+
|
|
1
3
|
from flask import request
|
|
2
4
|
|
|
3
5
|
import howler.services.config_service as config_service
|
|
4
6
|
from howler.api import make_subapi_blueprint, ok
|
|
5
7
|
from howler.common.swagger import generate_swagger_docs
|
|
8
|
+
from howler.odm.models.user import User
|
|
6
9
|
from howler.security.utils import get_disco_url
|
|
7
10
|
|
|
8
11
|
SUB_API = "configs"
|
|
@@ -49,7 +52,7 @@ def configs(**kwargs):
|
|
|
49
52
|
"""
|
|
50
53
|
return ok(
|
|
51
54
|
config_service.get_configuration(
|
|
52
|
-
user=kwargs.get("user", None),
|
|
55
|
+
user=cast(User | None, kwargs.get("user", None)),
|
|
53
56
|
discovery_url=get_disco_url(request.environ.get("HTTP_REFERER")),
|
|
54
57
|
)
|
|
55
58
|
)
|
howler/api/v1/hit.py
CHANGED
|
@@ -1072,7 +1072,7 @@ def update_bundle(id, **kwargs):
|
|
|
1072
1072
|
...hit # The updated bundle
|
|
1073
1073
|
}
|
|
1074
1074
|
"""
|
|
1075
|
-
bundle_hit: Hit = kwargs.get("cached_hit", None)
|
|
1075
|
+
bundle_hit: Hit = cast(Hit, kwargs.get("cached_hit", None))
|
|
1076
1076
|
if not bundle_hit:
|
|
1077
1077
|
return not_found(err="This bundle does not exist.")
|
|
1078
1078
|
|
howler/api/v1/user.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from hashlib import sha256
|
|
3
|
-
from typing import Any, Optional
|
|
3
|
+
from typing import Any, Optional, cast
|
|
4
4
|
|
|
5
5
|
from flask import request
|
|
6
6
|
|
|
@@ -128,7 +128,9 @@ def add_user_account(username, **_):
|
|
|
128
128
|
data["name"] = data["uname"]
|
|
129
129
|
|
|
130
130
|
# Add dynamic classification group
|
|
131
|
-
data["classification"] = user_service.get_dynamic_classification(
|
|
131
|
+
data["classification"] = user_service.get_dynamic_classification(
|
|
132
|
+
cast(str | None, data.get("classification", None)), data["email"]
|
|
133
|
+
)
|
|
132
134
|
|
|
133
135
|
# Clear non user account data
|
|
134
136
|
avatar = data.pop("avatar", None)
|
howler/common/README.md
CHANGED
|
@@ -44,25 +44,6 @@ This file provides utility functions to merge dictionaries together, find the di
|
|
|
44
44
|
|
|
45
45
|
Where as the unflatten does the invert by taking the dotted notation and transforming it back to it's original multiple level dictionary.
|
|
46
46
|
|
|
47
|
-
## hexdump.py
|
|
48
|
-
|
|
49
|
-
This file provide functions to take a binary data blob and transform it into and hexadecimal dump of its bytes. The `dump(buf)` function only outputs the bytes where as the `hexdump(buf)` function outputs also the offsets and some trimmed down ascii representation.
|
|
50
|
-
|
|
51
|
-
`dump("HTTP/1.1 404 Not\r\nCont")`
|
|
52
|
-
|
|
53
|
-
48 54 54 50 2F 31 2E 31 20 34 30 34 20 4E 6F 74 20 46 6F 75 6E 64 0D 0A 43 6F 6E 74
|
|
54
|
-
|
|
55
|
-
`hexdump("HTTP/1.1 404 Not\r\nCont")`
|
|
56
|
-
|
|
57
|
-
00000000: 48 54 54 50 2F 31 2E 31 20 34 30 34 20 4E 6F 74 HTTP/1.1 404 Not
|
|
58
|
-
00000010: 20 46 6F 75 6E 64 0D 0A 43 6F 6E 74 Found..Cont
|
|
59
|
-
|
|
60
|
-
## iprange.py
|
|
61
|
-
|
|
62
|
-
This file provides you with a RangeTable class that let's you determine if and IP is part of a certain CIDR definition. It also provides to quick function that let you determine if an IP is in a private CIDR (`is_private(ip)`) or if an IP is in a reserved CIDR (`is_reserved(ip)`).
|
|
63
|
-
|
|
64
|
-
*Note*: only IPV4 IPs are supported.
|
|
65
|
-
|
|
66
47
|
## isotime.py
|
|
67
48
|
|
|
68
49
|
This file provides you which methods to transform date into strings or epoch values. It support local, ISO and epoch time. It also makes sure that the local and ISO time get up to a microsecond precision.
|
howler/helper/oauth.py
CHANGED
|
@@ -61,7 +61,7 @@ def parse_profile(profile: dict[str, Any], provider_config: OAuthProvider) -> di
|
|
|
61
61
|
uname = profile.get("uname", profile.get("preferred_username", email_adr))
|
|
62
62
|
|
|
63
63
|
# Did we default to email?
|
|
64
|
-
if uname is not None and uname.lower() == email_adr.lower():
|
|
64
|
+
if email_adr is not None and uname is not None and uname.lower() == email_adr.lower():
|
|
65
65
|
# 1. Use provided regex matcher
|
|
66
66
|
if provider_config.uid_regex:
|
|
67
67
|
match = re.match(provider_config.uid_regex, uname)
|
howler/services/user_service.py
CHANGED
|
@@ -314,7 +314,7 @@ def save_user_account(username: str, data: dict[str, Any], user: dict[str, Any])
|
|
|
314
314
|
return storage.user.save(username, data)
|
|
315
315
|
|
|
316
316
|
|
|
317
|
-
def get_dynamic_classification(current_c12n: str, email: str) -> str:
|
|
317
|
+
def get_dynamic_classification(current_c12n: str | None, email: str) -> str | None:
|
|
318
318
|
"""Get the classification of the user
|
|
319
319
|
|
|
320
320
|
Args:
|
|
@@ -327,4 +327,5 @@ def get_dynamic_classification(current_c12n: str, email: str) -> str:
|
|
|
327
327
|
if CLASSIFICATION.dynamic_groups and email:
|
|
328
328
|
dyn_group = email.upper().split("@")[1]
|
|
329
329
|
return CLASSIFICATION.build_user_classification(current_c12n, f"{CLASSIFICATION.UNRESTRICTED}//{dyn_group}")
|
|
330
|
+
|
|
330
331
|
return current_c12n
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
howler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
howler/actions/__init__.py,sha256=
|
|
2
|
+
howler/actions/__init__.py,sha256=a9BkzoymVkCi_YciALZz7d9i4jF7AaLyJ3HZmAcsLZ0,5172
|
|
3
3
|
howler/actions/add_label.py,sha256=3Vvjsn3FBPReFLGRANyoJB28xY7ZK31Zm1xIThpbq0s,3270
|
|
4
4
|
howler/actions/add_to_bundle.py,sha256=SY0v5uTns5OLi_BHY50wGCLQmi1zSw1CaErbhOgAq1U,5245
|
|
5
5
|
howler/actions/change_field.py,sha256=wC2n8IzfD7TtgdP3M2Kzws2hu0OuQRq1_QeQ6iNzj8M,2181
|
|
@@ -14,31 +14,29 @@ howler/api/__init__.py,sha256=Z-o_fukNO9wBpx9gLNm8OPZwFOP-4xMtY0V1sfdEn8w,8539
|
|
|
14
14
|
howler/api/base.py,sha256=i--N7f4itJBRNVayDAqOiZYIq9thXwdblRBGfePyP1c,2689
|
|
15
15
|
howler/api/socket.py,sha256=6T_gpyazIbSmA2BheZ-yUWPbdxg9C50az70-rq4o-Rc,3910
|
|
16
16
|
howler/api/v1/__init__.py,sha256=lupGaCMXiiVWJjWrV7AoutAcTvZUrYommD-oUf4SFgU,3857
|
|
17
|
-
howler/api/v1/action.py,sha256=
|
|
17
|
+
howler/api/v1/action.py,sha256=5MPWdOTXtUlhl73cgndkwh9OdY2WDaekNvQjZvsQnFo,11138
|
|
18
18
|
howler/api/v1/analytic.py,sha256=kN7YXSTaXEWusu5DjAC510qlDzAIzsV7j7QjNw1daoY,20146
|
|
19
19
|
howler/api/v1/auth.py,sha256=fj0t6COXesgrShZQlP0zZXR12htjYlzLGGMIDsiX8nM,14069
|
|
20
20
|
howler/api/v1/clue.py,sha256=QaXmk9hTIkt7Cp4oAjCZuhtGeOo_C6yeNmhQY-egVsM,3042
|
|
21
|
-
howler/api/v1/configs.py,sha256=
|
|
21
|
+
howler/api/v1/configs.py,sha256=GWomzxJMG-_llIY-eBspzP4dIchBj8_IIv2HC72wul8,2005
|
|
22
22
|
howler/api/v1/dossier.py,sha256=8mfuoxAHqT9a_0BHRBO9G33KLJUa9xwcfOImb6ax8mU,5816
|
|
23
23
|
howler/api/v1/help.py,sha256=hqBvzW-DYX-I4Q85dbCQgpHsXyWDXp06a1fE9zhFMH4,823
|
|
24
|
-
howler/api/v1/hit.py,sha256=
|
|
24
|
+
howler/api/v1/hit.py,sha256=QNKJaics88vPg5IM0jH45WbwdpbZB2VGERUdAS-FcC8,34042
|
|
25
25
|
howler/api/v1/notebook.py,sha256=-cahdJ9u1lAB_nheztayHKtXvoPZcj04N8nqQ2U-HLo,2015
|
|
26
26
|
howler/api/v1/overview.py,sha256=e-WiHuMvOPy8Y7xIGnceagdI0_jebqlgDxi6GE6tfaA,4999
|
|
27
27
|
howler/api/v1/search.py,sha256=24r1vaYaxDhddzDR-c5dBdRKyag6aIggvHSWPWudqN8,26372
|
|
28
28
|
howler/api/v1/template.py,sha256=oexzUpAMVdgI6IOXITPx0iEfZIVP-kvlExRdFd6QVdk,5769
|
|
29
29
|
howler/api/v1/tool.py,sha256=6CN5LIXgxaAvxEHE6s4IFtAEhQo_zBLtl6ghbM8whjE,6737
|
|
30
|
-
howler/api/v1/user.py,sha256=
|
|
30
|
+
howler/api/v1/user.py,sha256=De7FTPih8U44iyoxnIui9wNkxXwGSzulgbzOTfgXjFw,13880
|
|
31
31
|
howler/api/v1/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
32
|
howler/api/v1/utils/etag.py,sha256=IGB4WUkecHbBt0KKLQFCxCn0mN3T_aSPG0y45l_zT9I,3431
|
|
33
33
|
howler/api/v1/view.py,sha256=VyizfGehsuoPyn7iswGPKCLcbSQoO1ipRsbr91nSDKk,8228
|
|
34
34
|
howler/app.py,sha256=76WSFUM4UKX2UpvDHfgKP8DI3wavLpXGlk2QLHqH1x8,7043
|
|
35
|
-
howler/common/README.md,sha256=
|
|
35
|
+
howler/common/README.md,sha256=8uPpDqh14Ne7Rtn9BwPwE-JpuFkauVsTr2s0s4YG5Bg,5637
|
|
36
36
|
howler/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
37
|
howler/common/classification.py,sha256=AUl33PJX6O9d9XzxHbyyJah2ffD7Q7J2yYqIwz7OqKY,39342
|
|
38
38
|
howler/common/classification.yml,sha256=3VBqzKYkiqz8bCsSuqNvqxeqUPN1NmXBKHusGFO3hbg,4092
|
|
39
39
|
howler/common/exceptions.py,sha256=An8MW-qB8g7EYLTxddnoIiyxNDQAqU9AmH8MrDFfnwQ,5804
|
|
40
|
-
howler/common/hexdump.py,sha256=zo8u0SZp5Z-_0IWWmlWMmQami1FAUlkENrhKeR5nVfM,1407
|
|
41
|
-
howler/common/iprange.py,sha256=h1wdSEalWPX_78cHpKfzxICP_qYTVJqhrk7rwZsjf4U,4258
|
|
42
40
|
howler/common/loader.py,sha256=r_XMh2kZwPnIMPMRR0NUWX5X4S7RaAZpWqetSrtzy_4,5361
|
|
43
41
|
howler/common/logging/__init__.py,sha256=kJ3Wi0TfB1zypeb7u5ReRzip6mxJgLR_SAMQQzvvngU,7855
|
|
44
42
|
howler/common/logging/audit.py,sha256=iR42dJ8hhuXQFN60yyXcms31dPtgZSHBQlHH_VZTEZc,3528
|
|
@@ -80,7 +78,7 @@ howler/helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
80
78
|
howler/helper/azure.py,sha256=Sbm4kpCaU1IcQQS9gtoJEF8myGnqhlAP4Lb_zJSCFvo,1543
|
|
81
79
|
howler/helper/discover.py,sha256=7hSDjjIafokl0INpSeGjp76lrrInC3LC3UsyIAfTZLE,2201
|
|
82
80
|
howler/helper/hit.py,sha256=YX46oxUB5mtlsrcpnmFKsokojGd7mi9mUULAeiEMe0w,7839
|
|
83
|
-
howler/helper/oauth.py,sha256=
|
|
81
|
+
howler/helper/oauth.py,sha256=RRvYCqTEJaVnwqZjl2s6S9gzXWh9xHRdJjCRXE_MH94,9523
|
|
84
82
|
howler/helper/search.py,sha256=cU9bDPQv2LIRNQ2j-8rAqePCYq9CrgOtS76PrziSgG8,2892
|
|
85
83
|
howler/helper/workflow.py,sha256=fsYhjeZo1foM0J8AW3nMjTEJOAnh9R6L0f4ZL12pE4E,4803
|
|
86
84
|
howler/helper/ws.py,sha256=ONxC7DFYGQKpp0AmrFqQLeIyxOMD4nHk5i6lFyWOtqo,15911
|
|
@@ -173,7 +171,7 @@ howler/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
173
171
|
howler/services/action_service.py,sha256=AuNRvZs7sFGUveaoptD8ouzs39jdZJidmsp-fIocZo4,3977
|
|
174
172
|
howler/services/analytic_service.py,sha256=pOJRCDn6I523XSVLBo49fL70Mz5VDgjJ5CBYhemQeBk,4272
|
|
175
173
|
howler/services/auth_service.py,sha256=TX51z-Fu4i3JvxIdU1JsJ3vzgGPVWNL1lNQJMxKpkZ8,11678
|
|
176
|
-
howler/services/config_service.py,sha256=
|
|
174
|
+
howler/services/config_service.py,sha256=XZ-UPxIuDYobWXrf8Q-0_hHZ-HRjj5qiWLyAoLFskuI,4496
|
|
177
175
|
howler/services/dossier_service.py,sha256=5jq7KZMgBNh165rN5pZD_oVuZP-oBsdACHDSV74ps-I,9839
|
|
178
176
|
howler/services/event_service.py,sha256=4PG2iBXjh1V8QnXcbUZSiKJeHs6V9hRWT9SKrzQFIPY,2864
|
|
179
177
|
howler/services/hit_service.py,sha256=VNsEhi6Tcoqkjsw8G71FWBj7xcKwdvET9mITYAKmzsM,32278
|
|
@@ -182,7 +180,7 @@ howler/services/lucene_service.py,sha256=K_tS39hJCXUCfN_zgbIgbfcfM3gaQNheFXrwbV_
|
|
|
182
180
|
howler/services/notebook_service.py,sha256=_MWllCnuVxt7lCcvWghXnaS926FbvBRE3DrBt--zO7U,3968
|
|
183
181
|
howler/services/overview_service.py,sha256=wDIm7DGjQ6Dvt4dNQ-57jbet8v6oGHxM857VezgHf7M,1539
|
|
184
182
|
howler/services/template_service.py,sha256=pwcHtYNoIkDuaXQ1bSXeDgxETP59PF1YCTwGzHsnXkA,1695
|
|
185
|
-
howler/services/user_service.py,sha256=
|
|
183
|
+
howler/services/user_service.py,sha256=x91KLZD43yyvQmZsbdo8mFb_TMHBtqcVTOKh60jQLPE,12084
|
|
186
184
|
howler/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
187
185
|
howler/utils/annotations.py,sha256=GLuDbjbXp8esDji3qhQY_uQyOWVqfIdpF_zs2t0IaMI,878
|
|
188
186
|
howler/utils/chunk.py,sha256=NoVDKzZkO8O92xXk0s0Pny2g7It9BX0PqWbknmnRSFg,895
|
|
@@ -194,7 +192,7 @@ howler/utils/path.py,sha256=DfOU4i4zSs4wchHoE8iE7aWVLkTxiC_JRGepF2hBYBk,690
|
|
|
194
192
|
howler/utils/socket_utils.py,sha256=nz1SklC9xBHUSfHyTJjpq3mbozX1GDf01WzdGxfaUII,2212
|
|
195
193
|
howler/utils/str_utils.py,sha256=HE8Hqh2HlOLaj16w0H9zKOyDJLp-f1LQ50y_WeGZaEk,8389
|
|
196
194
|
howler/utils/uid.py,sha256=p9dsqyvZ-lpiAuzZWCPCeEM99kdk0Ly9czf04HNdSuw,1341
|
|
197
|
-
howler_api-3.0.0.
|
|
198
|
-
howler_api-3.0.0.
|
|
199
|
-
howler_api-3.0.0.
|
|
200
|
-
howler_api-3.0.0.
|
|
195
|
+
howler_api-3.0.0.dev363.dist-info/METADATA,sha256=nimotS0mlPo7Zh9UzTqEr2qEaIoh4rmf5wo_17i4Ers,2804
|
|
196
|
+
howler_api-3.0.0.dev363.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
197
|
+
howler_api-3.0.0.dev363.dist-info/entry_points.txt,sha256=Lu9SBGvwe0wczJHmc-RudC24lmQk7tv3ZBXon9RIihg,259
|
|
198
|
+
howler_api-3.0.0.dev363.dist-info/RECORD,,
|
howler/common/hexdump.py
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import binascii
|
|
2
|
-
|
|
3
|
-
from howler.utils.chunk import chunk
|
|
4
|
-
|
|
5
|
-
FILTER = b"".join([bytes([x]) if x in range(32, 127) else b"." for x in range(256)])
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def dump(binary: bytes, size: int = 2, sep: bytes = b" ") -> bytes:
|
|
9
|
-
"Convert a binary file into a hexadecimal representation"
|
|
10
|
-
hexstr = binascii.hexlify(binary)
|
|
11
|
-
return sep.join(chunk(hexstr, size))
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def hexdump(
|
|
15
|
-
binary: bytes,
|
|
16
|
-
length: int = 16,
|
|
17
|
-
indent: str = "",
|
|
18
|
-
indent_size: int = 0,
|
|
19
|
-
newline: str = "\n",
|
|
20
|
-
prefix_offset: int = 0,
|
|
21
|
-
) -> str:
|
|
22
|
-
"""Create a string buffer that shows the given data in hexdump format.
|
|
23
|
-
|
|
24
|
-
src -> source buffer
|
|
25
|
-
length = 16 -> number of bytes per line
|
|
26
|
-
indent = "" -> indentation before each lines
|
|
27
|
-
indent_size = 0 -> number of time to repeat that indentation
|
|
28
|
-
newline = "\n" -> chars used as newline char
|
|
29
|
-
|
|
30
|
-
Example of output:
|
|
31
|
-
00000000: 48 54 54 50 2F 31 2E 31 20 34 30 34 20 4E 6F 74 HTTP/1.1 404 Not
|
|
32
|
-
00000010: 20 46 6F 75 6E 64 0D 0A 43 6F 6E 74 Found..Cont
|
|
33
|
-
...
|
|
34
|
-
"""
|
|
35
|
-
generator = chunk(binary, length)
|
|
36
|
-
line_frmt = "%%s%%08X: %%-%ss %%s" % ((length * 3) - 1)
|
|
37
|
-
|
|
38
|
-
out = [
|
|
39
|
-
line_frmt
|
|
40
|
-
% (
|
|
41
|
-
indent * indent_size,
|
|
42
|
-
prefix_offset + (addr * length),
|
|
43
|
-
dump(d).decode(),
|
|
44
|
-
d.translate(FILTER).decode(),
|
|
45
|
-
)
|
|
46
|
-
for addr, d in enumerate(generator)
|
|
47
|
-
]
|
|
48
|
-
return newline.join(out)
|
howler/common/iprange.py
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
from math import log
|
|
2
|
-
from socket import inet_aton
|
|
3
|
-
from struct import pack, unpack
|
|
4
|
-
|
|
5
|
-
from howler.common.exceptions import InvalidRangeException
|
|
6
|
-
|
|
7
|
-
# If you are tempted to extend this module to add support for IPv6 (or some
|
|
8
|
-
# similar invasive change) take a look at using PySubnetTree and extending it
|
|
9
|
-
# to allow arbitrary ranges instead.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def _convert(ip):
|
|
13
|
-
return unpack("!I", inet_aton(ip))[0]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def _next(lower, upper):
|
|
17
|
-
size = 2
|
|
18
|
-
while lower + size - 1 <= upper and _valid(lower, lower + size - 1):
|
|
19
|
-
size *= 2
|
|
20
|
-
|
|
21
|
-
return int(size / 2)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def _valid(lower, upper):
|
|
25
|
-
return lower & (upper - lower) == 0
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
# noinspection PyPep8Naming
|
|
29
|
-
class _dict(dict): # noqa: N801
|
|
30
|
-
pass
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def ip_to_int(ip):
|
|
34
|
-
if isinstance(ip, int):
|
|
35
|
-
return ip
|
|
36
|
-
|
|
37
|
-
return _convert(ip)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# noinspection PyTypeChecker
|
|
41
|
-
class RangeTable(object):
|
|
42
|
-
"""Efficient storage of IPv4 ranges and lookup of IPv4 addresses."""
|
|
43
|
-
|
|
44
|
-
def __init__(self):
|
|
45
|
-
self.clear()
|
|
46
|
-
self._trie = _dict()
|
|
47
|
-
|
|
48
|
-
def _add_cidr(self, lower, upper, value):
|
|
49
|
-
if not _valid(lower, upper):
|
|
50
|
-
# The public add_range method should ensure this never happens.
|
|
51
|
-
raise InvalidRangeException("invalid range: %d-%d" % (lower, upper))
|
|
52
|
-
|
|
53
|
-
size = upper - lower
|
|
54
|
-
points = 3 - int(log(size + 1, 256))
|
|
55
|
-
|
|
56
|
-
lower = self._to_path(lower)
|
|
57
|
-
upper = self._to_path(upper)
|
|
58
|
-
|
|
59
|
-
for x in range(lower[points], upper[points] + 1):
|
|
60
|
-
self._add_path(lower[:points] + (x,), value)
|
|
61
|
-
|
|
62
|
-
def _add_path(self, path, value):
|
|
63
|
-
trie = self._trie
|
|
64
|
-
for point in path[:-1]:
|
|
65
|
-
d = trie.get(point, _dict())
|
|
66
|
-
if not isinstance(d, _dict):
|
|
67
|
-
prev = d
|
|
68
|
-
d = _dict()
|
|
69
|
-
d.update({x: prev for x in range(256)})
|
|
70
|
-
trie[point] = d
|
|
71
|
-
trie = d
|
|
72
|
-
trie[path[-1]] = value
|
|
73
|
-
|
|
74
|
-
def _add_range(self, lower, upper, value):
|
|
75
|
-
while lower <= upper:
|
|
76
|
-
size = _next(lower, upper)
|
|
77
|
-
self._add_cidr(lower, lower + size - 1, value)
|
|
78
|
-
lower += size
|
|
79
|
-
|
|
80
|
-
def _follow_path(self, path):
|
|
81
|
-
entry = self._trie
|
|
82
|
-
while isinstance(entry, _dict):
|
|
83
|
-
entry = entry.get(path[0], None)
|
|
84
|
-
path = path[1:]
|
|
85
|
-
return entry
|
|
86
|
-
|
|
87
|
-
@staticmethod
|
|
88
|
-
def _to_path(integer):
|
|
89
|
-
return unpack("B" * 4, pack("!I", integer))
|
|
90
|
-
|
|
91
|
-
def __getitem__(self, key):
|
|
92
|
-
return self._follow_path(self._to_path(ip_to_int(key)))
|
|
93
|
-
|
|
94
|
-
def __setitem__(self, key, value):
|
|
95
|
-
if isinstance(key, int):
|
|
96
|
-
self._add_cidr(key, key, value)
|
|
97
|
-
return
|
|
98
|
-
|
|
99
|
-
span = key.split("-", 1)
|
|
100
|
-
if len(span) == 1:
|
|
101
|
-
span = key.split("/", 1)
|
|
102
|
-
if len(span) == 1:
|
|
103
|
-
span.append(span[0])
|
|
104
|
-
|
|
105
|
-
span[0] = _convert(span[0].strip())
|
|
106
|
-
if span[1].find(".") == -1:
|
|
107
|
-
mask = 2 ** (32 - int(span[1])) - 1
|
|
108
|
-
span[0] -= span[0] & mask
|
|
109
|
-
span[1] = span[0] | mask
|
|
110
|
-
else:
|
|
111
|
-
span[1] = _convert(span[1].strip())
|
|
112
|
-
|
|
113
|
-
self._add_range(span[0], span[1], value)
|
|
114
|
-
|
|
115
|
-
def add_range(self, lower, upper, value):
|
|
116
|
-
lower = ip_to_int(lower)
|
|
117
|
-
upper = ip_to_int(upper)
|
|
118
|
-
|
|
119
|
-
self._add_range(lower, upper, value)
|
|
120
|
-
|
|
121
|
-
while lower <= upper:
|
|
122
|
-
size = _next(lower, upper)
|
|
123
|
-
self._add_cidr(lower, lower + size - 1, value)
|
|
124
|
-
lower += size
|
|
125
|
-
|
|
126
|
-
def clear(self):
|
|
127
|
-
self._trie = _dict() # pylint:disable=W0201
|
|
128
|
-
|
|
129
|
-
def dump(self):
|
|
130
|
-
from pprint import pformat
|
|
131
|
-
|
|
132
|
-
return pformat(self._trie)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
PRIVATE_NETWORKS = [
|
|
136
|
-
"10.0.0.0/8",
|
|
137
|
-
"172.16.0.0/12",
|
|
138
|
-
"192.168.0.0/16",
|
|
139
|
-
]
|
|
140
|
-
|
|
141
|
-
RESERVED_NETWORKS = [
|
|
142
|
-
"0.0.0.0/8",
|
|
143
|
-
"100.64.0.0/10",
|
|
144
|
-
"127.0.0.0/8",
|
|
145
|
-
"169.254.0.0/16",
|
|
146
|
-
"192.0.0.0/24",
|
|
147
|
-
"192.0.2.0/24",
|
|
148
|
-
"192.88.99.0/24",
|
|
149
|
-
"198.18.0.0/15",
|
|
150
|
-
"198.51.100.0/24",
|
|
151
|
-
"203.0.113.0/24",
|
|
152
|
-
"240.0.0.0/4",
|
|
153
|
-
"224.0.0.0/4",
|
|
154
|
-
"255.255.255.255/32",
|
|
155
|
-
]
|
|
156
|
-
|
|
157
|
-
_private_ips = RangeTable()
|
|
158
|
-
for cidr in PRIVATE_NETWORKS:
|
|
159
|
-
_private_ips[cidr] = True
|
|
160
|
-
|
|
161
|
-
_reserved_ips = RangeTable()
|
|
162
|
-
for cidr in RESERVED_NETWORKS:
|
|
163
|
-
_reserved_ips[cidr] = True
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def is_ip_private(ip):
|
|
167
|
-
return _private_ips[ip] or False
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
def is_ip_reserved(ip):
|
|
171
|
-
return _private_ips[ip] or _reserved_ips[ip] or False
|
|
File without changes
|
|
File without changes
|