From d69cacc890fde8a813cf28cf1f52a54a7acbd78c Mon Sep 17 00:00:00 2001 From: David E Date: Fri, 30 Oct 2020 16:06:59 +0100 Subject: [PATCH 1/3] Fix for different Cookienames in CE-Edition --- olsync/olclient.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/olsync/olclient.py b/olsync/olclient.py index f9d1602..b9307c8 100644 --- a/olsync/olclient.py +++ b/olsync/olclient.py @@ -57,12 +57,13 @@ def login(self, username, password): # On a successful authentication the Overleaf API returns a new authenticated cookie. # If the cookie is different than the cookie of the GET request the authentication was successful - if post_login.status_code == 200 and get_login.cookies["overleaf_session2"] != post_login.cookies[ - "overleaf_session2"]: + if post_login.status_code == 200 and get_login.cookies["sharelatex.sid"] != post_login.cookies[ + "sharelatex.sid"]: + self._cookie = post_login.cookies # Enrich cookie with gke-route cookie from GET request above - self._cookie['gke-route'] = get_login.cookies['gke-route'] + #self._cookie['gke-route'] = get_login.cookies['gke-route'] return {"cookie": self._cookie, "csrf": self._csrf} @@ -144,10 +145,9 @@ def set_project_infos(a, project_infos_dict, c, d): project_infos = project_infos_dict # Convert cookie from CookieJar to string - cookie = "gke-route={}; overleaf_session2={}" \ + cookie = "sharelatex.sid={}" \ .format( - reqs.utils.dict_from_cookiejar(self._cookie)["gke-route"], - reqs.utils.dict_from_cookiejar(self._cookie)["overleaf_session2"] + reqs.utils.dict_from_cookiejar(self._cookie)["sharelatex.sid"] ) # Connect to Overleaf Socket.IO, send a time parameter and the cookies From b2f3adac1dc41b96dd4fd111adef65d15af28d7e Mon Sep 17 00:00:00 2001 From: David E Date: Fri, 30 Oct 2020 16:57:56 +0100 Subject: [PATCH 2/3] Support for local CE install over .olce file --- olsync/olclient.py | 69 ++++++++++++++++++++++++++++------------------ olsync/olsync.py | 16 ++++++++++- 2 files changed, 57 insertions(+), 28 deletions(-) diff --git a/olsync/olclient.py b/olsync/olclient.py index b9307c8..f147214 100644 --- a/olsync/olclient.py +++ b/olsync/olclient.py @@ -16,27 +16,32 @@ from socketIO_client import SocketIO import time -# Where to get the CSRF Token and where to send the login request to -LOGIN_URL = "https://www.overleaf.com/login" -PROJECT_URL = "https://www.overleaf.com/project" # The dashboard URL -# The URL to download all the files in zip format -DOWNLOAD_URL = "https://www.overleaf.com/project/{}/download/zip" -UPLOAD_URL = "https://www.overleaf.com/project/{}/upload" # The URL to upload files -FOLDER_URL = "https://www.overleaf.com/project/{}/folder" # The URL to create folders -BASE_URL = "https://www.overleaf.com" # The Overleaf Base URL - - class OverleafClient(object): """ Overleaf API Wrapper Supports login, querying all projects, querying a specific project, downloading a project and uploading a file to a project. """ + _ce = False - def __init__(self, cookie=None, csrf=None): + def __init__(self, cookie=None, csrf=None, ce_url=None): self._cookie = cookie # Store the cookie for authenticated requests self._csrf = csrf # Store the CSRF token since it is needed for some requests + # Where to get the CSRF Token and where to send the login request to + if ce_url != None: + self._ce = True + self._BASE_URL = ce_url + else: + self._BASE_URL = "https://www.overleaf.com" # The Overleaf Base URL + + self._LOGIN_URL = self._BASE_URL + "/login" + self._PROJECT_URL = self._BASE_URL + "/project" # The dashboard URL + # The URL to download all the files in zip format + self._DOWNLOAD_URL = self._BASE_URL + "/project/{}/download/zip" + self._UPLOAD_URL = self._BASE_URL + "/project/{}/upload" # The URL to upload files + self._FOLDER_URL = self._BASE_URL + "/project/{}/folder" # The URL to create folders + def login(self, username, password): """ Login to the Overleaf Service with a username and a password @@ -44,7 +49,7 @@ def login(self, username, password): Returns: Dict of cookie and CSRF """ - get_login = reqs.get(LOGIN_URL) + get_login = reqs.get(self._LOGIN_URL) self._csrf = BeautifulSoup(get_login.content, 'html.parser').find( 'input', {'name': '_csrf'}).get('value') login_json = { @@ -52,18 +57,20 @@ def login(self, username, password): "email": username, "password": password } - post_login = reqs.post(LOGIN_URL, json=login_json, + post_login = reqs.post(self._LOGIN_URL, json=login_json, cookies=get_login.cookies) # On a successful authentication the Overleaf API returns a new authenticated cookie. # If the cookie is different than the cookie of the GET request the authentication was successful - if post_login.status_code == 200 and get_login.cookies["sharelatex.sid"] != post_login.cookies[ - "sharelatex.sid"]: + if post_login.status_code == 200 and ((self._ce and get_login.cookies["sharelatex.sid"] != post_login.cookies[ + "sharelatex.sid"]) or get_login.cookies["overleaf_session2"] != post_login.cookies[ + "overleaf_session2"]): self._cookie = post_login.cookies - # Enrich cookie with gke-route cookie from GET request above - #self._cookie['gke-route'] = get_login.cookies['gke-route'] + if not self._ce: + # Enrich cookie with gke-route cookie from GET request above + self._cookie['gke-route'] = get_login.cookies['gke-route'] return {"cookie": self._cookie, "csrf": self._csrf} @@ -72,7 +79,7 @@ def all_projects(self): Get all of a user's active projects (= not archived) Returns: List of project objects """ - projects_page = reqs.get(PROJECT_URL, cookies=self._cookie) + projects_page = reqs.get(self._PROJECT_URL, cookies=self._cookie) json_content = json.loads( BeautifulSoup(projects_page.content, 'html.parser').find('script', {'id': 'data'}).contents[0]) return list(filter(lambda x: not x.get("archived"), json_content.get("projects"))) @@ -84,7 +91,7 @@ def get_project(self, project_name): Returns: project object """ - projects_page = reqs.get(PROJECT_URL, cookies=self._cookie) + projects_page = reqs.get(self._PROJECT_URL, cookies=self._cookie) json_content = json.loads( BeautifulSoup(projects_page.content, 'html.parser').find('script', {'id': 'data'}).contents[0]) return next( @@ -97,7 +104,7 @@ def download_project(self, project_id): Params: project_id, the id of the project Returns: bytes string (zip file) """ - r = reqs.get(DOWNLOAD_URL.format(project_id), + r = reqs.get(self._DOWNLOAD_URL.format(project_id), stream=True, cookies=self._cookie) return r.content @@ -118,7 +125,7 @@ def create_folder(self, project_id, parent_folder_id, folder_name): "_csrf": self._csrf, "name": folder_name } - r = reqs.post(FOLDER_URL.format(project_id), + r = reqs.post(self._FOLDER_URL.format(project_id), cookies=self._cookie, json=params) if r.ok: @@ -145,14 +152,22 @@ def set_project_infos(a, project_infos_dict, c, d): project_infos = project_infos_dict # Convert cookie from CookieJar to string - cookie = "sharelatex.sid={}" \ - .format( - reqs.utils.dict_from_cookiejar(self._cookie)["sharelatex.sid"] - ) + cookie = None + if self._ce: + cookie = "sharelatex.sid={}" \ + .format( + reqs.utils.dict_from_cookiejar(self._cookie)["sharelatex.sid"] + ) + else: + cookie = "gke-route={}; overleaf_session2={}" \ + .format( + reqs.utils.dict_from_cookiejar(self._cookie)["gke-route"], + reqs.utils.dict_from_cookiejar(self._cookie)["overleaf_session2"] + ) # Connect to Overleaf Socket.IO, send a time parameter and the cookies socket_io = SocketIO( - BASE_URL, + self._BASE_URL, params={'t': int(time.time())}, headers={'Cookie': cookie} ) @@ -217,6 +232,6 @@ def upload_file(self, project_id, project_infos, file_name, file_size, file): } # Upload the file to the predefined folder - r = reqs.post(UPLOAD_URL.format(project_id), cookies=self._cookie, params=params, files=files) + r = reqs.post(self._UPLOAD_URL.format(project_id), cookies=self._cookie, params=params, files=files) return r.status_code == str(200) and json.loads(r.content)["success"] diff --git a/olsync/olsync.py b/olsync/olsync.py index b91f9a3..491d94c 100644 --- a/olsync/olsync.py +++ b/olsync/olsync.py @@ -48,7 +48,21 @@ def main(ctx, local, remote, cookie_path, sync_path, olignore_path): with open(cookie_path, 'rb') as f: store = pickle.load(f) - overleaf_client = OverleafClient(store["cookie"], store["csrf"]) + #Read .olce file for URL to local installation of Overleaf/Sharelatex + olce_file = os.path.join(sync_path, ".olce") + click.echo("=" * 40) + ce_url = None + if not os.path.isfile(olce_file): + click.echo("\nNotice: .olce file does not exist, will sync with overleaf.com.") + else: + + with open(olce_file, 'r') as f: + ce_url = f.readline() + f.close() + + click.echo("\n.olce: using %s as CE server" % ce_url) + + overleaf_client = OverleafClient(store["cookie"], store["csrf"], ce_url) project = execute_action( lambda: overleaf_client.get_project( From 079f2d19702c218036675151148c44b9177cf6ca Mon Sep 17 00:00:00 2001 From: David E Date: Fri, 20 Nov 2020 15:58:07 +0100 Subject: [PATCH 3/3] Fix for loging in on CE-Server --- olsync/olsync.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/olsync/olsync.py b/olsync/olsync.py index 491d94c..5f836cf 100644 --- a/olsync/olsync.py +++ b/olsync/olsync.py @@ -48,19 +48,7 @@ def main(ctx, local, remote, cookie_path, sync_path, olignore_path): with open(cookie_path, 'rb') as f: store = pickle.load(f) - #Read .olce file for URL to local installation of Overleaf/Sharelatex - olce_file = os.path.join(sync_path, ".olce") - click.echo("=" * 40) - ce_url = None - if not os.path.isfile(olce_file): - click.echo("\nNotice: .olce file does not exist, will sync with overleaf.com.") - else: - - with open(olce_file, 'r') as f: - ce_url = f.readline() - f.close() - - click.echo("\n.olce: using %s as CE server" % ce_url) + ce_url = olceChecker(sync_path) overleaf_client = OverleafClient(store["cookie"], store["csrf"], ce_url) @@ -133,7 +121,7 @@ def login(username, password, cookie_path): def login_handler(username, password, path): - overleaf_client = OverleafClient() + overleaf_client = OverleafClient(None, None, olceChecker()) store = overleaf_client.login(username, password) if store is None: return False @@ -247,6 +235,24 @@ def olignore_keep_list(sync_path, olignore_path): keep_list = [item for item in keep_list if not os.path.isdir(item)] return keep_list +def olceChecker(sync_path = ""): + + # Read .olce file for URL to local installation of Overleaf/Sharelatex + olce_file = os.path.join(sync_path, ".olce") + + click.echo("=" * 40) + ce_url = None + if not os.path.isfile(olce_file): + click.echo("\nNotice: .olce file does not exist, will sync with overleaf.com.") + else: + + with open(olce_file, 'r') as f: + ce_url = f.readline() + f.close() + + click.echo("\n.olce: using %s as CE server" % ce_url) + + return ce_url if __name__ == "__main__": main()