Update HTTP Headers
Add check for subscription expiration
Add a script to register to ORLY
This commit is contained in:
Lorenzo Di Fuccia 2020-04-30 19:02:43 +02:00
commit d8a22bbb31
2 changed files with 163 additions and 8 deletions

153
register_user.py Normal file
View file

@ -0,0 +1,153 @@
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)

View file

@ -299,13 +299,12 @@ class SafariBooks:
"</ncx>"
HEADERS = {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding": "gzip, deflate",
"origin": SAFARI_BASE_URL,
"referer": LOGIN_ENTRY_URL,
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/60.0.3112.113 Safari/537.36"
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate",
"Referer": LOGIN_ENTRY_URL,
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/80.0.3987.163 Safari/537.36"
}
COOKIE_FLOAT_MAX_AGE_PATTERN = re.compile(r'(max-age=\d*\.\d*)', re.IGNORECASE)
@ -522,9 +521,12 @@ class SafariBooks:
if response == 0:
self.display.exit("Login: unable to reach Safari Books Online. Try again...")
if response.status_code != 200:
elif response.status_code != 200:
self.display.exit("Authentication issue: unable to access profile page.")
elif "user_type\":\"Expired" in response.text:
self.display.exit("Authentication issue: account subscription expired.")
self.display.info("Successfully authenticated.", state=True)
def get_book_info(self):