pylookyloo 1.27.1__tar.gz → 1.28.1__tar.gz
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 pylookyloo might be problematic. Click here for more details.
- {pylookyloo-1.27.1 → pylookyloo-1.28.1}/PKG-INFO +5 -5
- {pylookyloo-1.27.1 → pylookyloo-1.28.1}/pylookyloo/api.py +37 -1
- {pylookyloo-1.27.1 → pylookyloo-1.28.1}/pyproject.toml +6 -6
- {pylookyloo-1.27.1 → pylookyloo-1.28.1}/LICENSE +0 -0
- {pylookyloo-1.27.1 → pylookyloo-1.28.1}/README.md +0 -0
- {pylookyloo-1.27.1 → pylookyloo-1.28.1}/pylookyloo/__init__.py +0 -0
- {pylookyloo-1.27.1 → pylookyloo-1.28.1}/pylookyloo/py.typed +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pylookyloo
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.28.1
|
|
4
4
|
Summary: Python CLI and module for Lookyloo
|
|
5
|
-
License:
|
|
5
|
+
License: GPL-2.0-or-later
|
|
6
6
|
Author: Raphaël Vinot
|
|
7
7
|
Author-email: raphael.vinot@circl.lu
|
|
8
8
|
Requires-Python: >=3.9
|
|
@@ -11,7 +11,7 @@ Classifier: Environment :: Console
|
|
|
11
11
|
Classifier: Intended Audience :: Information Technology
|
|
12
12
|
Classifier: Intended Audience :: Science/Research
|
|
13
13
|
Classifier: Intended Audience :: Telecommunications Industry
|
|
14
|
-
Classifier: License :: OSI Approved ::
|
|
14
|
+
Classifier: License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)
|
|
15
15
|
Classifier: Operating System :: POSIX :: Linux
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.9
|
|
@@ -23,8 +23,8 @@ Classifier: Topic :: Internet
|
|
|
23
23
|
Classifier: Topic :: Security
|
|
24
24
|
Provides-Extra: docs
|
|
25
25
|
Provides-Extra: examples
|
|
26
|
-
Requires-Dist: Sphinx (>=8.
|
|
27
|
-
Requires-Dist: pylacus (>=1.
|
|
26
|
+
Requires-Dist: Sphinx (>=8.2.3) ; (python_version >= "3.11") and (extra == "docs")
|
|
27
|
+
Requires-Dist: pylacus (>=1.13.2) ; extra == "examples"
|
|
28
28
|
Requires-Dist: requests (>=2.32.3)
|
|
29
29
|
Project-URL: Documentation, https://pylookyloo.readthedocs.io/en/latest/
|
|
30
30
|
Project-URL: Repository, https://github.com/lookyloo/PyLookyloo
|
|
@@ -17,6 +17,29 @@ import requests
|
|
|
17
17
|
|
|
18
18
|
from urllib3.util import Retry
|
|
19
19
|
from requests.adapters import HTTPAdapter
|
|
20
|
+
from requests.sessions import Session
|
|
21
|
+
from requests.status_codes import codes
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SafeRedirectRePOSTSession(Session):
|
|
25
|
+
|
|
26
|
+
def rebuild_method(self, prepared_request: requests.PreparedRequest, response: requests.Response) -> None:
|
|
27
|
+
# This method will resubmit a POST when we have a http -> https redirect
|
|
28
|
+
if response.status_code == codes.moved and prepared_request.method == 'POST':
|
|
29
|
+
# make sure it is just a redirect http->https and we're not going to a different host
|
|
30
|
+
prec_url = urlparse(response.url)
|
|
31
|
+
next_url = urlparse(prepared_request.url)
|
|
32
|
+
|
|
33
|
+
if (prec_url.netloc != next_url.netloc or prec_url.scheme != 'http'
|
|
34
|
+
or next_url.scheme != 'https'):
|
|
35
|
+
super().rebuild_method(prepared_request, response)
|
|
36
|
+
else:
|
|
37
|
+
# For surely good reasons, requests force-remove the body of the redirected requests unless the statuscode is either 307 or 308
|
|
38
|
+
# https://github.com/psf/requests/issues/1084
|
|
39
|
+
# Doing that makes sure we keep it
|
|
40
|
+
response.status_code = 307
|
|
41
|
+
else:
|
|
42
|
+
super().rebuild_method(prepared_request, response)
|
|
20
43
|
|
|
21
44
|
|
|
22
45
|
class PyLookylooError(Exception):
|
|
@@ -39,6 +62,7 @@ class CaptureSettings(TypedDict, total=False):
|
|
|
39
62
|
proxy: str | dict[str, str] | None
|
|
40
63
|
general_timeout_in_sec: int | None
|
|
41
64
|
cookies: list[dict[str, Any]] | None
|
|
65
|
+
storage: str | dict[str, Any] | None
|
|
42
66
|
headers: str | dict[str, str] | None
|
|
43
67
|
http_credentials: dict[str, int] | None
|
|
44
68
|
geolocation: dict[str, float] | None
|
|
@@ -78,7 +102,7 @@ class Lookyloo():
|
|
|
78
102
|
self.root_url = 'http://' + self.root_url
|
|
79
103
|
if not self.root_url.endswith('/'):
|
|
80
104
|
self.root_url += '/'
|
|
81
|
-
self.session =
|
|
105
|
+
self.session = SafeRedirectRePOSTSession()
|
|
82
106
|
self.session.headers['user-agent'] = useragent if useragent else f'PyLookyloo / {version("pylookyloo")}'
|
|
83
107
|
if proxies:
|
|
84
108
|
self.session.proxies.update(proxies)
|
|
@@ -148,6 +172,7 @@ class Lookyloo():
|
|
|
148
172
|
proxy: str | dict[str, str] | None=None,
|
|
149
173
|
general_timeout_in_sec: int | None=None,
|
|
150
174
|
cookies: list[dict[str, Any]] | None=None,
|
|
175
|
+
storage: str | dict[str, Any] | None=None,
|
|
151
176
|
headers: str | dict[str, str] | None=None,
|
|
152
177
|
http_credentials: dict[str, int] | None=None,
|
|
153
178
|
geolocation: dict[str, float] | None=None,
|
|
@@ -172,6 +197,7 @@ class Lookyloo():
|
|
|
172
197
|
proxy: str | dict[str, str] | None=None,
|
|
173
198
|
general_timeout_in_sec: int | None=None,
|
|
174
199
|
cookies: list[dict[str, Any]] | None=None,
|
|
200
|
+
storage: str | dict[str, Any] | None=None,
|
|
175
201
|
headers: str | dict[str, str] | None=None,
|
|
176
202
|
http_credentials: dict[str, int] | None=None,
|
|
177
203
|
geolocation: dict[str, float] | None=None,
|
|
@@ -247,6 +273,8 @@ class Lookyloo():
|
|
|
247
273
|
to_send['general_timeout_in_sec'] = general_timeout_in_sec
|
|
248
274
|
if cookies:
|
|
249
275
|
to_send['cookies'] = cookies
|
|
276
|
+
if storage:
|
|
277
|
+
to_send['storage'] = storage
|
|
250
278
|
if headers:
|
|
251
279
|
to_send['headers'] = headers
|
|
252
280
|
if http_credentials:
|
|
@@ -402,6 +430,14 @@ class Lookyloo():
|
|
|
402
430
|
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('json', capture_uuid, 'cookies'))))
|
|
403
431
|
return r.json()
|
|
404
432
|
|
|
433
|
+
def get_storage(self, capture_uuid: str) -> dict[str, Any]:
|
|
434
|
+
'''Returns the complete storage state.
|
|
435
|
+
|
|
436
|
+
:param capture_uuid: UUID of the capture
|
|
437
|
+
'''
|
|
438
|
+
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('json', capture_uuid, 'storage'))))
|
|
439
|
+
return r.json()
|
|
440
|
+
|
|
405
441
|
def get_html(self, capture_uuid: str) -> StringIO:
|
|
406
442
|
'''Returns the rendered HTML as it would be in the browser after the page loaded.
|
|
407
443
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pylookyloo"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.28.1"
|
|
4
4
|
description = "Python CLI and module for Lookyloo"
|
|
5
5
|
authors = [
|
|
6
6
|
{name="Raphaël Vinot", email="raphael.vinot@circl.lu"}
|
|
7
7
|
]
|
|
8
|
-
license = "
|
|
8
|
+
license = "GPL-2.0-or-later"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
|
|
@@ -36,13 +36,13 @@ classifiers = [
|
|
|
36
36
|
lookyloo = 'pylookyloo:main'
|
|
37
37
|
|
|
38
38
|
[project.optional-dependencies]
|
|
39
|
-
docs = ["Sphinx (>=8.
|
|
40
|
-
examples = ["pylacus (>=1.
|
|
39
|
+
docs = ["Sphinx (>=8.2.3) ; python_version >= \"3.11\""]
|
|
40
|
+
examples = ["pylacus (>=1.13.2)"]
|
|
41
41
|
|
|
42
42
|
[tool.poetry.group.dev.dependencies]
|
|
43
43
|
mypy = "^1.15.0"
|
|
44
|
-
types-requests = "^2.32.0.
|
|
45
|
-
pytest = "^8.3.
|
|
44
|
+
types-requests = "^2.32.0.20250328"
|
|
45
|
+
pytest = "^8.3.5"
|
|
46
46
|
|
|
47
47
|
[build-system]
|
|
48
48
|
requires = ["poetry-core>=2.0"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|