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', '')