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@lists.wikimedia.org