diff --git a/README.org b/README.org index ccced8a..101448e 100644 --- a/README.org +++ b/README.org @@ -67,10 +67,14 @@ file: *** Firefox Locate you Firefox profile folder and set: #+begin_src emacs-lisp - (setq overleaf-cookies - (overleaf-read-cookies-from-firefox [optional: :profile ""] )) +(setq overleaf-cookies + (overleaf-read-cookies-from-firefox + [optional: :firefox-folder ""] + [optional: :profile ""])) #+end_src This assumes that you're logged into overleaf in this Firefox profile. +On GNU/Linux, the default == is typically =~/.mozilla/firefox/=. +On macOS, == is typically =~/Library/Application Support/Firefox=. *It is recommended that no Firefox instance using this profile is running while =overleaf.el= is accessing the cookie database. The cookies usually tend to be evicted from the database while Firefox is running and will only be put back upon closure.* diff --git a/overleaf.el b/overleaf.el index 525ff2a..9e05feb 100644 --- a/overleaf.el +++ b/overleaf.el @@ -93,6 +93,24 @@ To be used with `overleaf-cookies'." (insert-file-contents (expand-file-name file)) (read (string-trim (buffer-string)))))) +(defun overleaf--sqlite-select-firefox-overleaf-cookies (dbfile) + "Return Overleaf cookies from Firefox cookie DBFILE. +Returns a list of (host cookie-string expiry)." + (let ((db (sqlite-open dbfile))) + (unwind-protect + (mapcar + (lambda (row) + (pcase-let* ((`(,domain ,name ,value ,expiry) row)) + `(,domain + ,(format "%s=%s" name value) + ,expiry))) + (sqlite-select + db + (concat + "SELECT host, name, value, expiry FROM moz_cookies " + "WHERE name = 'overleaf_session2' OR name = 'overleaf.sid'"))) + (sqlite-close db)))) + ;;;###autoload (cl-defun overleaf-read-cookies-from-firefox (&key (firefox-folder "~/.mozilla/firefox/") (profile nil)) "Make a cookie saving function reading the database at FIREFOX-FOLDER. @@ -118,10 +136,10 @@ profile. Otherwise prompt." (mapcar (lambda (block) (save-match-data (when-let* - ((path (progn (string-match "^Path=\\(.*?\\)$" block) - (match-string 1 block))) - (name (progn (string-match "^Name=\\(.*?\\)$" block) - (match-string 1 block)))) + ((path (and (string-match "^Path=\\(.*?\\)$" block) + (match-string 1 block))) + (name (and (string-match "^Name=\\(.*?\\)$" block) + (match-string 1 block)))) `(:fields (,name) :data ,path)))) profile-blocks))) @@ -137,20 +155,30 @@ profile. Otherwise prompt." (cookie-file (if profile (expand-file-name (concat firefox-folder "/" profile "/cookies.sqlite")) - (user-error "Profile does not exist"))) - (db (sqlite-open cookie-file)) - (result - (mapcar - (lambda (row) - (pcase-let* ((`(,domain ,name ,value ,expiry) row)) - `(,domain - ,(format "%s=%s" name value) - ,expiry))) - (sqlite-select - db "SELECT host, name, value, expiry FROM moz_cookies WHERE name = 'overleaf_session2' OR name = 'overleaf.sid'")))) - - (sqlite-close db) - result) + (user-error "Profile does not exist")))) + (condition-case err + (overleaf--sqlite-select-firefox-overleaf-cookies cookie-file) + (sqlite-error + (condition-case _err + (let* ((temp-dir (make-temp-file "overleaf-firefox-cookies." t)) + (temp-cookie-file (expand-file-name "cookies.sqlite" temp-dir)) + (cookie-file-wal (concat cookie-file "-wal")) + (temp-cookie-file-wal (concat temp-cookie-file "-wal")) + (cookie-file-shm (concat cookie-file "-shm")) + (temp-cookie-file-shm (concat temp-cookie-file "-shm"))) + (unwind-protect + (progn + (copy-file cookie-file temp-cookie-file t t) + (when (file-exists-p cookie-file-wal) + (ignore-errors + (copy-file cookie-file-wal temp-cookie-file-wal t t))) + (when (file-exists-p cookie-file-shm) + (ignore-errors + (copy-file cookie-file-shm temp-cookie-file-shm t t))) + (overleaf--sqlite-select-firefox-overleaf-cookies temp-cookie-file)) + (ignore-errors (delete-directory temp-dir t)))) + (sqlite-error + (signal 'sqlite-error err)))))) (user-error "Sqlite not available!")))) (defvar overleaf-save-cookies (lambda (cookies)