This commit is contained in:
lorenzo.di.fuccia 2025-09-12 23:24:11 +02:00
commit 0585e70caf
4 changed files with 29 additions and 332 deletions

137
Pipfile.lock generated
View file

@ -1,137 +0,0 @@
{
"_meta": {
"hash": {
"sha256": "757b53b537f003a11d2cd5852e5d2e5ee83d6d25452b472e10bba32aadf849e6"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.6"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.python.org/simple",
"verify_ssl": true
}
]
},
"default": {
"certifi": {
"hashes": [
"sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d",
"sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"
],
"markers": "python_version >= '3.6'",
"version": "==2022.6.15"
},
"charset-normalizer": {
"hashes": [
"sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597",
"sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"
],
"markers": "python_version >= '3'",
"version": "==2.0.12"
},
"idna": {
"hashes": [
"sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
"sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
],
"markers": "python_version >= '3'",
"version": "==3.3"
},
"lxml": {
"hashes": [
"sha256:04da965dfebb5dac2619cb90fcf93efdb35b3c6994fea58a157a834f2f94b318",
"sha256:0538747a9d7827ce3e16a8fdd201a99e661c7dee3c96c885d8ecba3c35d1032c",
"sha256:0645e934e940107e2fdbe7c5b6fb8ec6232444260752598bc4d09511bd056c0b",
"sha256:079b68f197c796e42aa80b1f739f058dcee796dc725cc9a1be0cdb08fc45b000",
"sha256:0f3f0059891d3254c7b5fb935330d6db38d6519ecd238ca4fce93c234b4a0f73",
"sha256:10d2017f9150248563bb579cd0d07c61c58da85c922b780060dcc9a3aa9f432d",
"sha256:1355755b62c28950f9ce123c7a41460ed9743c699905cbe664a5bcc5c9c7c7fb",
"sha256:13c90064b224e10c14dcdf8086688d3f0e612db53766e7478d7754703295c7c8",
"sha256:1423631e3d51008871299525b541413c9b6c6423593e89f9c4cfbe8460afc0a2",
"sha256:1436cf0063bba7888e43f1ba8d58824f085410ea2025befe81150aceb123e345",
"sha256:1a7c59c6ffd6ef5db362b798f350e24ab2cfa5700d53ac6681918f314a4d3b94",
"sha256:1e1cf47774373777936c5aabad489fef7b1c087dcd1f426b621fda9dcc12994e",
"sha256:206a51077773c6c5d2ce1991327cda719063a47adc02bd703c56a662cdb6c58b",
"sha256:21fb3d24ab430fc538a96e9fbb9b150029914805d551deeac7d7822f64631dfc",
"sha256:27e590352c76156f50f538dbcebd1925317a0f70540f7dc8c97d2931c595783a",
"sha256:287605bede6bd36e930577c5925fcea17cb30453d96a7b4c63c14a257118dbb9",
"sha256:2aaf6a0a6465d39b5ca69688fce82d20088c1838534982996ec46633dc7ad6cc",
"sha256:32a73c53783becdb7eaf75a2a1525ea8e49379fb7248c3eeefb9412123536387",
"sha256:41fb58868b816c202e8881fd0f179a4644ce6e7cbbb248ef0283a34b73ec73bb",
"sha256:4780677767dd52b99f0af1f123bc2c22873d30b474aa0e2fc3fe5e02217687c7",
"sha256:4878e667ebabe9b65e785ac8da4d48886fe81193a84bbe49f12acff8f7a383a4",
"sha256:487c8e61d7acc50b8be82bda8c8d21d20e133c3cbf41bd8ad7eb1aaeb3f07c97",
"sha256:4beea0f31491bc086991b97517b9683e5cfb369205dac0148ef685ac12a20a67",
"sha256:4cfbe42c686f33944e12f45a27d25a492cc0e43e1dc1da5d6a87cbcaf2e95627",
"sha256:4d5bae0a37af799207140652a700f21a85946f107a199bcb06720b13a4f1f0b7",
"sha256:4e285b5f2bf321fc0857b491b5028c5f276ec0c873b985d58d7748ece1d770dd",
"sha256:57e4d637258703d14171b54203fd6822fda218c6c2658a7d30816b10995f29f3",
"sha256:5974895115737a74a00b321e339b9c3f45c20275d226398ae79ac008d908bff7",
"sha256:5ef87fca280fb15342726bd5f980f6faf8b84a5287fcc2d4962ea8af88b35130",
"sha256:603a464c2e67d8a546ddaa206d98e3246e5db05594b97db844c2f0a1af37cf5b",
"sha256:6653071f4f9bac46fbc30f3c7838b0e9063ee335908c5d61fb7a4a86c8fd2036",
"sha256:6ca2264f341dd81e41f3fffecec6e446aa2121e0b8d026fb5130e02de1402785",
"sha256:6d279033bf614953c3fc4a0aa9ac33a21e8044ca72d4fa8b9273fe75359d5cca",
"sha256:6d949f53ad4fc7cf02c44d6678e7ff05ec5f5552b235b9e136bd52e9bf730b91",
"sha256:6daa662aba22ef3258934105be2dd9afa5bb45748f4f702a3b39a5bf53a1f4dc",
"sha256:6eafc048ea3f1b3c136c71a86db393be36b5b3d9c87b1c25204e7d397cee9536",
"sha256:830c88747dce8a3e7525defa68afd742b4580df6aa2fdd6f0855481e3994d391",
"sha256:86e92728ef3fc842c50a5cb1d5ba2bc66db7da08a7af53fb3da79e202d1b2cd3",
"sha256:8caf4d16b31961e964c62194ea3e26a0e9561cdf72eecb1781458b67ec83423d",
"sha256:8d1a92d8e90b286d491e5626af53afef2ba04da33e82e30744795c71880eaa21",
"sha256:8f0a4d179c9a941eb80c3a63cdb495e539e064f8054230844dcf2fcb812b71d3",
"sha256:9232b09f5efee6a495a99ae6824881940d6447debe272ea400c02e3b68aad85d",
"sha256:927a9dd016d6033bc12e0bf5dee1dde140235fc8d0d51099353c76081c03dc29",
"sha256:93e414e3206779ef41e5ff2448067213febf260ba747fc65389a3ddaa3fb8715",
"sha256:98cafc618614d72b02185ac583c6f7796202062c41d2eeecdf07820bad3295ed",
"sha256:9c3a88d20e4fe4a2a4a84bf439a5ac9c9aba400b85244c63a1ab7088f85d9d25",
"sha256:9f36de4cd0c262dd9927886cc2305aa3f2210db437aa4fed3fb4940b8bf4592c",
"sha256:a60f90bba4c37962cbf210f0188ecca87daafdf60271f4c6948606e4dabf8785",
"sha256:a614e4afed58c14254e67862456d212c4dcceebab2eaa44d627c2ca04bf86837",
"sha256:ae06c1e4bc60ee076292e582a7512f304abdf6c70db59b56745cca1684f875a4",
"sha256:b122a188cd292c4d2fcd78d04f863b789ef43aa129b233d7c9004de08693728b",
"sha256:b570da8cd0012f4af9fa76a5635cd31f707473e65a5a335b186069d5c7121ff2",
"sha256:bcaa1c495ce623966d9fc8a187da80082334236a2a1c7e141763ffaf7a405067",
"sha256:bd34f6d1810d9354dc7e35158aa6cc33456be7706df4420819af6ed966e85448",
"sha256:be9eb06489bc975c38706902cbc6888f39e946b81383abc2838d186f0e8b6a9d",
"sha256:c4b2e0559b68455c085fb0f6178e9752c4be3bba104d6e881eb5573b399d1eb2",
"sha256:c62e8dd9754b7debda0c5ba59d34509c4688f853588d75b53c3791983faa96fc",
"sha256:c852b1530083a620cb0de5f3cd6826f19862bafeaf77586f1aef326e49d95f0c",
"sha256:d9fc0bf3ff86c17348dfc5d322f627d78273eba545db865c3cd14b3f19e57fa5",
"sha256:dad7b164905d3e534883281c050180afcf1e230c3d4a54e8038aa5cfcf312b84",
"sha256:e5f66bdf0976ec667fc4594d2812a00b07ed14d1b44259d19a41ae3fff99f2b8",
"sha256:e8f0c9d65da595cfe91713bc1222af9ecabd37971762cb830dea2fc3b3bb2acf",
"sha256:edffbe3c510d8f4bf8640e02ca019e48a9b72357318383ca60e3330c23aaffc7",
"sha256:eea5d6443b093e1545ad0210e6cf27f920482bfcf5c77cdc8596aec73523bb7e",
"sha256:ef72013e20dd5ba86a8ae1aed7f56f31d3374189aa8b433e7b12ad182c0d2dfb",
"sha256:f05251bbc2145349b8d0b77c0d4e5f3b228418807b1ee27cefb11f69ed3d233b",
"sha256:f1be258c4d3dc609e654a1dc59d37b17d7fef05df912c01fc2e15eb43a9735f3",
"sha256:f9ced82717c7ec65a67667bb05865ffe38af0e835cdd78728f1209c8fffe0cad",
"sha256:fe17d10b97fdf58155f858606bddb4e037b805a60ae023c009f760d8361a4eb8",
"sha256:fe749b052bb7233fe5d072fcb549221a8cb1a16725c47c37e42b0b9cb3ff2c3f"
],
"index": "pypi",
"version": "==4.9.1"
},
"requests": {
"hashes": [
"sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24",
"sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
],
"index": "pypi",
"version": "==2.26.0"
},
"urllib3": {
"hashes": [
"sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4",
"sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"
],
"index": "pypi",
"version": "==1.26.6"
}
},
"develop": {}
}

View file

@ -1,153 +0,0 @@
import re
import requests
import safaribooks
REGISTER_URL = safaribooks.SAFARI_BASE_URL + "/register/"
CHECK_EMAIL = safaribooks.SAFARI_BASE_URL + "/check-email-availability/"
CHECK_PWD = safaribooks.SAFARI_BASE_URL + "/check-password/"
# DEBUG
USE_PROXY = False
PROXIES = {"https": "https://127.0.0.1:8080"}
CSRF_TOKEN_RE = re.compile(r"(?<=name='csrfmiddlewaretoken' value=')([^']+)")
class Register:
def __init__(self, email, password, first_name, second_name, country="US", referrer="podcast"):
self.email = email
self.password = password
self.first_name = first_name
self.second_name = second_name
self.country = country
self.referrer = referrer
self.csrf = None
self.session = requests.Session()
if USE_PROXY: # DEBUG
self.session.proxies = PROXIES
self.session.verify = False
self.session.headers.update(safaribooks.SafariBooks.HEADERS)
self.session.headers.update({
"X-Requested-With": "XMLHttpRequest",
"Referer": REGISTER_URL
})
self.register()
def handle_cookie_update(self, set_cookie_headers):
for morsel in set_cookie_headers:
# Handle Float 'max-age' Cookie
if safaribooks.SafariBooks.COOKIE_FLOAT_MAX_AGE_PATTERN.search(morsel):
cookie_key, cookie_value = morsel.split(";")[0].split("=")
self.session.cookies.set(cookie_key, cookie_value)
def requests_provider(self, url, is_post=False, data=None, perform_redirect=True, check_200=True, **kwargs):
try:
response = getattr(self.session, "post" if is_post else "get")(
url,
data=data,
allow_redirects=False,
**kwargs
)
self.handle_cookie_update(response.raw.headers.getlist("Set-Cookie"))
except (requests.ConnectionError, requests.ConnectTimeout, requests.RequestException) as request_exception:
print("Error: ", str(request_exception))
return 0
if response.is_redirect and perform_redirect:
return self.requests_provider(response.next.url, is_post, None, perform_redirect, check_200, **kwargs)
if check_200 and response.status_code != 200:
print("Invalid response code:\n", response.text)
return 0
return response
def register(self):
# Take first cookie + csrf
response = self.requests_provider(REGISTER_URL)
if response == 0:
print("Error 0x1: unable to reach registration page!")
exit(1)
if "csrfmiddlewaretoken' value='" not in response.text:
print("Error 0x2: CSRF token not present")
exit(1)
csrf_search = CSRF_TOKEN_RE.findall(response.text)
if not len(csrf_search):
print("Error 0x3: CSRF token RE error")
exit(1)
self.csrf = csrf_search[0]
# Check user validity
response = self.requests_provider(CHECK_EMAIL, params={"email": self.email})
if response == 0:
print("Error 0x4: unable to check email!")
exit(1)
response_dict = response.json()
if not response_dict["success"]:
print("Error 0x5:", response_dict["message"])
exit(1)
# Check password validity
response = self.requests_provider(CHECK_PWD, is_post=True, data={
"csrfmiddlewaretoken": self.csrf,
"password1": self.password,
"field_name": "password1"
})
if response == 0:
print("Error 0x6: unable to check password!")
exit(1)
response_dict = response.json()
if not response_dict["valid"]:
print("Error 0x7:", response_dict["msg"])
exit(1)
# Register
response = self.requests_provider(REGISTER_URL, is_post=True, data={
"next": "",
"trial_length": 10,
"csrfmiddlewaretoken": self.csrf,
"first_name": self.first_name,
"last_name": self.second_name,
"email": self.email,
"password1": self.password,
"country": self.country,
"referrer": "podcast",
"recently_viewed_bits": "[]"
}, check_200=False)
if response == 0:
print("Error 0x8: unable to register!")
exit(1)
elif response.status_code != 201:
print("Error: 0x9: invalid status code while registering!")
exit(1)
print("[*] Account registered: \nEMAIL: %s\nPASSWORD: %s" % (self.email, self.password))
return
if __name__ == "__main__":
import sys
if len(sys.argv) < 3:
print("[!] Error: too few arguments.\nRun `register_user.py EMAIL PASSWORD`.")
exit(1)
elif len(sys.argv) > 3:
print("[!] Error: too much arguments, try to enclose the string with quote '\"'.")
exit(1)
FIRST_NAME = "Safari"
SECOND_NAME = "Download"
Register(sys.argv[1], sys.argv[2], FIRST_NAME, SECOND_NAME)

29
retrieve_cookies.py Normal file
View file

@ -0,0 +1,29 @@
import json
# See: https://github.com/lorenzodifuccia/safaribooks/issues/358
try:
from safaribooks import COOKIES_FILE
except ImportError:
COOKIES_FILE = "cookies.json"
try:
import browser_cookie3
except ImportError:
raise ImportError("Please run this program via: uv run --with browser_cookie3 python retrieve_cookies.py")
def get_oreilly_cookies():
cj = browser_cookie3.load()
cookies = {}
for c in cj:
cookies[c.name] = c.value
return cookies
def main():
cookies = get_oreilly_cookies()
with open(COOKIES_FILE, "w") as f:
json.dump(cookies, f)
print(f"Cookies saved to {COOKIES_FILE}")
if __name__ == "__main__":
main()

View file

@ -1,42 +0,0 @@
"""
Script for SSO support, saves and converts the cookie string retrieved by the browser.
Please follow:
- https://github.com/lorenzodifuccia/safaribooks/issues/26
- https://github.com/lorenzodifuccia/safaribooks/issues/150#issuecomment-555423085
- https://github.com/lorenzodifuccia/safaribooks/issues/2#issuecomment-367726544
Thanks: @elrob, @noxymon
"""
import json
import safaribooks
def transform(cookies_string):
cookies = {}
for cookie in cookies_string.split("; "):
key, value = cookie.split("=", 1)
cookies[key] = value
print(cookies)
json.dump(cookies, open(safaribooks.COOKIES_FILE, 'w'))
print("\n\nDone! Cookie Jar saved into `cookies.json`. "
"Now you can run `safaribooks.py` without the `--cred` argument...")
USAGE = "\n\n[*] Please use this command putting as argument the cookies retrieved by your browser.\n" + \
"[+] In order to do so, please follow these steps: \n" + \
"https://github.com/lorenzodifuccia/safaribooks/issues/150#issuecomment-555423085\n"
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("[!] Error: too few arguments." + USAGE)
exit(1)
elif len(sys.argv) > 2:
print("[!] Error: too much arguments, try to enclose the string with quote '\"'." + USAGE)
exit(1)
transform(sys.argv[1])