[issue2008] cookielib lacks FileCookieJar class for Safari

Hendrik report at bugs.python.org
Sun Feb 2 12:23:58 CET 2014


Hendrik added the comment:

Ok, i've got it.

--- a/Lib/http/cookiejar.py	Wed Dec 18 15:37:03 2013 -0600
+++ b/Lib/http/cookiejar.py	Sat Feb 01 15:12:01 2014 +0100
@@ -11,17 +11,17 @@
 distributed with the Python standard library, but are available from
 http://wwwsearch.sf.net/):
 
-                        CookieJar____
-                        /     \      \
-            FileCookieJar      \      \
-             /    |   \         \      \
- MozillaCookieJar | LWPCookieJar \      \
-                  |               |      \
-                  |   ---MSIEBase |       \
-                  |  /      |     |        \
-                  | /   MSIEDBCookieJar BSDDBCookieJar
-                  |/
-               MSIECookieJar
+                                     CookieJar____
+                                    /     \      \
+                        FileCookieJar      \      \
+                       /   /  |   \         \      \
+        SafariCookieJar   /   | LWPCookieJar \      \
+                         /    |               |      \
+           MozillaCookieJar   |   ---MSIEBase |       \
+                              |  /      |     |        \
+                              | /   MSIEDBCookieJar BSDDBCookieJar
+                              |/
+                          MSIECookieJar
 
 """
 
@@ -31,8 +31,11 @@
 import copy
 import datetime
 import re
+import getpass
 import time
 import urllib.parse, urllib.request
+import struct
+import io
 try:
     import threading as _threading
 except ImportError:
@@ -40,6 +43,9 @@
 import http.client  # only for the default HTTP port
 from calendar import timegm
 
+import difflib
+#from difflib_data import *
+
 debug = False   # set to True to enable debugging via the logging module
 logger = None
 
@@ -1938,6 +1944,109 @@
             raise LoadError("invalid Set-Cookie3 format file %r: %r" %
                             (filename, line))
 
+class SafariCookieJar(FileCookieJar):
+    """
+    Read Cookies from Safari
+
+    """
+    def load(self, filename=None):
+        if filename == None:
+            username = getpass.getuser()
+            path = '/Users/' + username + '/Library/Cookies/Cookies.binarycookies'
+        else:
+            path = filename
+
+        bf=open(path,mode='rb')
+        scook = bf.read(4).decode("UTF-8")
+        if scook == 'cook':
+            NumberOfPages=struct.unpack('>i',bf.read(4))[0]
+            page_sizes=[]
+            for np in range(NumberOfPages):
+                page_sizes.append(struct.unpack('>i',bf.read(4))[0])
+            pages=[]
+            for ps in page_sizes:
+                pages.append(bf.read(ps))
+
+            for page in pages:
+                page=io.BytesIO(page)
+                page.read(4)
+                num_cookies=struct.unpack('<i',page.read(4))[0]
+                cookie_offsets=[]
+                for nc in range(num_cookies):
+                    cookie_offsets.append(struct.unpack('<i',page.read(4))[0])
+
+                page.read(4)
+
+                cookie=''
+                for offset in cookie_offsets:
+                    page.seek(offset)
+                    cookiesize=struct.unpack('<i',page.read(4))[0]
+                    cookie=io.BytesIO(page.read(cookiesize))
+
+                    cookie.read(4)
+
+                    flags=struct.unpack('<i',cookie.read(4))[0]
+                    cookie_flags=''
+                    if flags==0:
+                        cookie_flags=''
+                    elif flags==1:
+                        cookie_flags='Secure'
+                    elif flags==4:
+                        cookie_flags='HttpOnly'
+                    elif flags==5:
+                        cookie_flags='Secure; HttpOnly'
+                    else:
+                        cookie_flags='Unknown'
+
+                    cookie.read(4)
+
+                    urloffset=struct.unpack('<i',cookie.read(4))[0]
+                    nameoffset=struct.unpack('<i',cookie.read(4))[0]
+                    pathoffset=struct.unpack('<i',cookie.read(4))[0]
+                    valueoffset=struct.unpack('<i',cookie.read(4))[0]
+
+                    endofcookie=cookie.read(8)
+
+                    expiry_date_epoch= struct.unpack('<d',cookie.read(8))[0]+978307200
+                    expiry_date=time.strftime("%a, %d %b %Y ",time.gmtime(expiry_date_epoch))[:-1]
+
+                    create_date_epoch=struct.unpack('<d',cookie.read(8))[0]+978307200
+                    create_date=time.strftime("%a, %d %b %Y ",time.gmtime(create_date_epoch))[:-1]
+
+                    cookie.seek(urloffset-4)
+                    url=''
+                    u=cookie.read(1)
+                    while struct.unpack('<b',u)[0]!=0:
+                        url=url+u.decode('UTF-8')
+                        u=cookie.read(1)
+
+                    cookie.seek(nameoffset-4)
+                    name=''
+                    n=cookie.read(1)
+                    while struct.unpack('<b',n)[0]!=0:
+                        name=name+n.decode('UTF-8')
+                        n=cookie.read(1)
+
+                    cookie.seek(pathoffset-4)
+                    path=''
+                    pa=cookie.read(1)
+                    while struct.unpack('<b',pa)[0]!=0:
+                        path=path+pa.decode('UTF-8')
+                        pa=cookie.read(1)
+
+                    cookie.seek(valueoffset-4)
+                    value=''
+                    va=cookie.read(1)
+                    while struct.unpack('<b',va)[0]!=0:
+                        value=value+va.decode('UTF-8')
+                        va=cookie.read(1)
+
+                    print ('Cookie : '+name+'='+value+'; domain='+url+'; path='+path+'; '+'expires='+expiry_date+'; '+cookie_flags)
+
+            bf.close()
+        else:
+            bf.close()
+            raise LoadError("This is not an cookiefile!")
 
 class MozillaCookieJar(FileCookieJar):
     """
@@ -1979,6 +2088,7 @@
 """
 
     def _really_load(self, f, filename, ignore_discard, ignore_expires):
+
         now = time.time()
 
         magic = f.readline()

this solutions based on code from http://securitylearn.net/wp-content/uploads/tools/iOS/BinaryCookieReader.py

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue2008>
_______________________________________


More information about the Python-bugs-list mailing list