Revision: 7623
Author:   alexsh
Date:     2009-11-10 20:26:02 +0000 (Tue, 10 Nov 2009)

Log Message:
-----------
*family.py: add new variable for get centralauth user name key.
*handle cross-languages and cross-project session usage by SUL. default values 
for wikimedia projects and MediaWiki centralAuth extension.
*login.py: fix badtoken when login on script running.

Modified Paths:
--------------
    trunk/pywikipedia/family.py
    trunk/pywikipedia/login.py
    trunk/pywikipedia/wikipedia.py

Modified: trunk/pywikipedia/family.py
===================================================================
--- trunk/pywikipedia/family.py 2009-11-10 20:12:42 UTC (rev 7622)
+++ trunk/pywikipedia/family.py 2009-11-10 20:26:02 UTC (rev 7623)
@@ -3090,8 +3090,11 @@
         # A list with the name for cross-project cookies.
         # default for wikimedia centralAuth extensions.
         self.cross_projects_cookies = ['centralauth_Session', 
'centralauth_Token', 'centralauth_User']
+        self.cross_projects_cookie_username = 'centralauth_User'
+        
         # A list with the name in the cross-language flag permissions
         self.cross_allowed = []
+        
         # A list with the name of the category containing disambiguation
         # pages for the various languages. Only one category per language,
         # and without the namespace, so add things like:

Modified: trunk/pywikipedia/login.py
===================================================================
--- trunk/pywikipedia/login.py  2009-11-10 20:12:42 UTC (rev 7622)
+++ trunk/pywikipedia/login.py  2009-11-10 20:26:02 UTC (rev 7623)
@@ -127,8 +127,6 @@
 
         Returns cookie data if succesful, None otherwise.
         """
-        L = []
-        CenL = []
         if api:
             predata = {
                 'action': 'login',
@@ -154,7 +152,7 @@
             address = login_address + '&action=submit'
         
         if api:
-            response, data = query.GetData(predata, self.site, back_response = 
True)
+            response, data = query.GetData(predata, self.site, 
sysop=self.sysop, back_response = True)
             if data['login']['result'] != "Success":
                 faildInfo = data['login']['result']
                 #if faildInfo == "NotExists":
@@ -164,12 +162,8 @@
                 #elif faildInfo == "Throttled":
                 #    
                 return False
-            #L.append('%s_session=%s' % (data['login']['cookieprefix'], 
data['login']['sessionid'])
-            
-            #if __name__ == "__main__":
-            #    wikipedia.output('%s' % data['login'])
         else:
-            response, data = self.site.postData(address, 
self.site.urlEncode(predata))
+            response, data = self.site.postData(address, 
self.site.urlEncode(predata), sysop=self.sysop)
             if self.verbose:
                 fakepredata = predata
                 fakepredata['wpPassword'] = u'XXXXX'
@@ -185,13 +179,9 @@
         Reat=re.compile(': (.*?)=(.*?);')
     
         L = {}
-        CenL = {}
         for eat in response.info().getallmatchingheaders('set-cookie'):
             m = Reat.search(eat)
             if m:
-                #if 'central' in x:
-                #    CenL.append(x)
-                #else:
                 L[m.group(1)] = m.group(2)
     
         got_token = got_user = False
@@ -202,13 +192,23 @@
                 got_user = True
     
         if got_token and got_user:
+            #process the basic information to Site()
             index = self.site._userIndex(self.sysop)
-            self.site._cookies[index] = L
-            try:
+            if api:
+                #API result came back username, token and sessions.
+                self.site._userName[index] = data['login']['lgusername']
                 self.site._token[index] = data['login']['lgtoken'] + "+\\"
-            except:
-                pass
-            return L
+            else:
+                self.site._userName[index] = self.username
+
+            if self.site._cookies[index]:
+                #if user is trying re-login, update the new information
+                self.site.updateCookies(L, self.sysop)
+            else:
+                # clean type login, setup the new cookies files.
+                self.site._setupCookies(L, self.sysop)
+            
+            return True
         elif not captcha:
             solve = self.site.solveCaptcha(data)
             if solve:
@@ -274,7 +274,7 @@
             return self.login(False, retry)
         if cookiedata:
             fn = '%s-%s-%s-login.data' % (self.site.family.name, 
self.site.lang, self.username) 
-            self.storecookiedata(fn,cookiedata)
+            #self.storecookiedata(fn,cookiedata)
             wikipedia.output(u"Should be logged in now")
             # Show a warning according to the local bot policy
             if not self.botAllowed():
@@ -303,14 +303,7 @@
                 flushCk = True
         
         if flushCk:
-            filename = wikipedia.config.datafilepath('login-data',
-                       '%s-%s-%s-login.data' % (self.site.family.name, 
self.site.lang, self.username))
-            try:
-                os.remove(filename)
-            except:
-                pass
-            if __name__ != "__main__":
-                wikipedia.output('%s is logged out.' % self.site)
+            self.site._removeCookies(self.username)
             return True
         
         return False
@@ -365,9 +358,7 @@
                         site = wikipedia.getSite(lang, familyName)
                         loginMan = LoginManager(password, sysop = sysop, site 
= site, verbose=verbose)
                         if clean:
-                            if 
os.path.exists(wikipedia.config.datafilepath('login-data',
-                              '%s-%s-%s-login.data' % (familyName, lang, 
namedict[familyName][lang]))):
-                                loginMan.logout()
+                            loginMan.logout()
                         else:
                             if not forceLogin and site.loggedInAs(sysop = 
sysop):
                                 wikipedia.output(u'Already logged in on %s' % 
site)

Modified: trunk/pywikipedia/wikipedia.py
===================================================================
--- trunk/pywikipedia/wikipedia.py      2009-11-10 20:12:42 UTC (rev 7622)
+++ trunk/pywikipedia/wikipedia.py      2009-11-10 20:26:02 UTC (rev 7623)
@@ -5223,23 +5223,31 @@
             self._cookies[index] = None
             self._isLoggedIn[index] = False
         else:
-            tmp = '%s-%s-%s-login.data' % (self.family.name, self.lang, 
username)
-            fn = config.datafilepath('login-data', tmp)
-            if not os.path.exists(fn):
+            # check central login data if cross_projects is available.
+            localFn = '%s-%s-%s-login.data' % (self.family.name, self.lang, 
username)
+            localPa = config.datafilepath('login-data', localFn)
+            if self.family.cross_projects:
+                for proj in [self.family.name] + self.family.cross_projects:
+                    #find all central data in all cross_projects
+                    centralFn = '%s-%s-central-login.data' % (proj, username)
+                    centralPa = config.datafilepath('login-data', centralFn)
+                    if os.path.exists(centralPa):
+                        self._cookies[index] = self._readCookies(centralFn)
+                        break
+            
+            if os.path.exists(localPa):
+                #read and dump local logindata into self._cookies[index]
+                self._cookies[index] = 
query.CombineParams(self._cookies[index], self._readCookies(localFn))
+            elif not os.path.exists(localPa) and not 
self.family.cross_projects:
+                #keep anonymous mode if not login and centralauth not enable
                 self._cookies[index] = None
                 self._isLoggedIn[index] = False
-            else:
-                f = open(fn)
-                tmp = {}
-                ck = re.compile("(.*?)=(.*?)\n")
-                for x in ck.findall(f.read()):
-                    tmp[ x[0] ] = x[1]
-                self._cookies[index] = tmp
-                f.close()
+                
     
     def _readCookies(self, filename):
+        """read login cookie file and return a dictionary."""
         try:
-            f = open( config.datafilepath('login-data', filename) )
+            f = open( config.datafilepath('login-data', filename), 'r')
             ck = re.compile("(.*?)=(.*?)\n")
             data = dict([(x[0],x[1]) for x in ck.findall(f.read())])
             #data = dict(ck.findall(f.read()))
@@ -5249,22 +5257,71 @@
             return None
     
     def _setupCookies(self, datas, sysop = False):
+        """save the cookie dictionary to files
+           if cross_project enable, files will separate two, centraldata and 
localdata.
+        
+        """
         index = self._userIndex(sysop)
-        filename = '%s-%s-%s-login.data' % (self.family.name, self.lang, 
self.username(sysop) )
-        #if self.family.cross_projects:
-        #    for proj in self.family.cross_projects + self.family.name:
-        #        filename = '%s-%s-central-login.data' % (proj, 
self.username(sysop) )
-                
+        if not self._cookies[index]:
+            self._cookies[index] = datas
+        cache = {0:"",1:""} #0 is central auth, 1 is local.
+        if not self.username(sysop):
+            if not self._cookies[index]:
+                return 
+            elif self.family.cross_projects_cookie_username in 
self._cookies[index]:
+                # Using centralauth to cross login data, it's not necessary to 
forceLogin, but Site() didn't know it.
+                # So we need add centralauth username data into siteattribute
+                self._userName[index] = 
self._cookies[index][self.family.cross_projects_cookie_username]
+
+        
+        for k, v in datas.iteritems():
+            #put key and values into save cache
+            if self.family.cross_projects and k in 
self.family.cross_projects_cookies:
+                cache[0] += "%s=%s\n" % (k,v)
+            else:
+                cache[1] += "%s=%s\n" % (k,v)
+        
+        # write the data.
+        if self.family.cross_projects:
+            filename = '%s-%s-central-login.data' % (self.family.name, 
self.username(sysop))
+            f = open(config.datafilepath('login-data', filename), 'w')
+            f.write(cache[0])
+            f.close()
+            
+        filename = '%s-%s-%s-login.data' % (self.family.name, self.lang, 
self.username(sysop))
+        f = open(config.datafilepath('login-data', filename), 'w')
+        f.write(cache[1])
+        f.close()
+        
     
-    def _removeCookies(self, sysop = False, central = False):
-        #if self.family_cross_projects:
-        #    file = config.datafilepath('login-data', 
'%s-%s-central-login.data' % (self.family.name, self.username(sysop)))
-        #    if os.path.exists(file):
-        #        os.remove( file )
-        file = config.datafilepath('%s-%s-%s-login.data' % (self.family.name, 
self.lang, self.username(sysop)) )
+    def _removeCookies(self, name):
+        # remove cookies.
+        # ToDo: remove all local datas if cross_projects enable.
+        #
+        if self.family.cross_projects:
+            file = config.datafilepath('login-data', 
'%s-%s-central-login.data' % (self.family.name, name))
+            if os.path.exists(file):
+                os.remove( file )
+        file = config.datafilepath('login-data', '%s-%s-%s-login.data' % 
(self.family.name, self.lang, name))
         if os.path.exists(file):
             os.remove(file)
-
+    
+    def updateCookies(self, datas, sysop = False):
+        """Check and update the current cookies datas and save back to 
files."""
+        index = self._userIndex(sysop)
+        if not self._cookies[index]:
+            self._setupCookies(datas, sysop)
+            
+        for k, v in datas.iteritems():
+            if k in self._cookies[index]:
+                if v != self._cookies[index][k]:
+                    self._cookies[index][k] = v
+            else:
+                self._cookies[index][k] = v
+        
+        self._setupCookies(self._cookies[index], sysop)
+        
+    
     def urlEncode(self, query):
         """Encode a query so that it can be sent using an http POST request."""
         if not query:
@@ -5381,6 +5438,7 @@
         
         if compress:
             headers['Accept-encoding'] = 'gzip'
+        #print '%s' % headers
         
         url = '%s://%s%s' % (self.protocol(), self.hostname(), address)
         # Try to retrieve the page until it was successfully loaded (just in
@@ -5416,6 +5474,17 @@
                     continue
                 
                 raise
+        
+        # check cookies return or not, if return, send its to update.
+        if f.info().getallmatchingheaders('set-cookie'):
+            Reat=re.compile(': (.*?)=(.*?);')
+            tmpc = {}
+            for d in f.info().getallmatchingheaders('set-cookie'):
+                m = Reat.search(d)
+                if m: tmpc[m.group(1)] = m.group(2)
+            if self.cookies(sysop):
+                self.updateCookies(tmpc, sysop)
+
         resContentType = headers.get('content-type', '')
         contentEncoding = headers.get('content-encoding', '')
 
@@ -5525,6 +5594,15 @@
                     continue
                 
                 raise
+        # check cookies return or not, if return, send its to update.
+        if not no_hostname and f.info().getallmatchingheaders('set-cookie'):
+            Reat=re.compile(': (.*?)=(.*?);')
+            tmpc = {}
+            for d in f.info().getallmatchingheaders('set-cookie'):
+                m = Reat.search(d)
+                if m: tmpc[m.group(1)] = m.group(2)
+            self.updateCookies(tmpc, sysop)
+        
         if cookie_only:
             return headers.get('set-cookie', '')
         contentType = headers.get('content-type', '')



_______________________________________________
Pywikipedia-svn mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/pywikipedia-svn

Reply via email to