##// END OF EJS Templates
Hook into the http auth handlers in order to get access to the http request object and use that object to differentiate between an authentication failure and a new request to the same url.
Eric Blood -
r89:651673d1 default
parent child Browse files
Show More
@@ -17,6 +17,7 b' except:'
17 from mercurial.httprepo import passwordmgr
17 from mercurial.httprepo import passwordmgr
18 from mercurial.httprepo import httprepository
18 from mercurial.httprepo import httprepository
19 from mercurial import mail
19 from mercurial import mail
20 from urllib2 import AbstractBasicAuthHandler, AbstractDigestAuthHandler
20
21
21 # mercurial.demandimport incompatibility workaround,
22 # mercurial.demandimport incompatibility workaround,
22 # would cause gnomekeyring, one of the possible
23 # would cause gnomekeyring, one of the possible
@@ -35,9 +36,13 b' KEYRING_SERVICE = "Mercurial"'
35
36
36 ############################################################
37 ############################################################
37
38
38 def monkeypatch_method(cls):
39 def monkeypatch_method(cls,fname=None):
39 def decorator(func):
40 def decorator(func):
40 setattr(cls, func.__name__, func)
41 local_fname = fname
42 if local_fname is None:
43 local_fname = func.__name__
44 setattr(func, "orig", getattr(cls, local_fname, None))
45 setattr(cls, local_fname, func)
41 return func
46 return func
42 return decorator
47 return decorator
43
48
@@ -100,7 +105,7 b' class HTTPPasswordHandler(object):'
100 self.pwd_cache = {}
105 self.pwd_cache = {}
101 self.last_reply = None
106 self.last_reply = None
102
107
103 def find_auth(self, pwmgr, realm, authuri):
108 def find_auth(self, pwmgr, realm, authuri, req):
104 """
109 """
105 Actual implementation of find_user_password - different
110 Actual implementation of find_user_password - different
106 ways of obtaining the username and password.
111 ways of obtaining the username and password.
@@ -113,7 +118,8 b' class HTTPPasswordHandler(object):'
113 # reusing bad password indifinitely).
118 # reusing bad password indifinitely).
114 after_bad_auth = (self.last_reply \
119 after_bad_auth = (self.last_reply \
115 and (self.last_reply['realm'] == realm) \
120 and (self.last_reply['realm'] == realm) \
116 and (self.last_reply['authuri'] == authuri))
121 and (self.last_reply['authuri'] == authuri) \
122 and (self.last_reply['req'] == req))
117 if after_bad_auth:
123 if after_bad_auth:
118 _debug(ui, _("Working after bad authentication, cached passwords not used %s") % str(self.last_reply))
124 _debug(ui, _("Working after bad authentication, cached passwords not used %s") % str(self.last_reply))
119
125
@@ -127,7 +133,7 b' class HTTPPasswordHandler(object):'
127 if user and pwd:
133 if user and pwd:
128 _debug_reply(ui, _("Auth data found in repository URL"),
134 _debug_reply(ui, _("Auth data found in repository URL"),
129 base_url, user, pwd)
135 base_url, user, pwd)
130 self.last_reply = dict(realm=realm,authuri=authuri,user=user)
136 self.last_reply = dict(realm=realm,authuri=authuri,user=user,req=req)
131 return user, pwd
137 return user, pwd
132
138
133 # Loading .hg/hgrc [auth] section contents. If prefix is given,
139 # Loading .hg/hgrc [auth] section contents. If prefix is given,
@@ -147,7 +153,7 b' class HTTPPasswordHandler(object):'
147 user, pwd = cached_auth
153 user, pwd = cached_auth
148 _debug_reply(ui, _("Cached auth data found"),
154 _debug_reply(ui, _("Cached auth data found"),
149 base_url, user, pwd)
155 base_url, user, pwd)
150 self.last_reply = dict(realm=realm,authuri=authuri,user=user)
156 self.last_reply = dict(realm=realm,authuri=authuri,user=user,req=req)
151 return user, pwd
157 return user, pwd
152
158
153 if auth_user:
159 if auth_user:
@@ -158,7 +164,7 b' class HTTPPasswordHandler(object):'
158 self.pwd_cache[cache_key] = user, pwd
164 self.pwd_cache[cache_key] = user, pwd
159 _debug_reply(ui, _("Auth data set in .hg/hgrc"),
165 _debug_reply(ui, _("Auth data set in .hg/hgrc"),
160 base_url, user, pwd)
166 base_url, user, pwd)
161 self.last_reply = dict(realm=realm,authuri=authuri,user=user)
167 self.last_reply = dict(realm=realm,authuri=authuri,user=user,req=req)
162 return user, pwd
168 return user, pwd
163 else:
169 else:
164 _debug(ui, _("Username found in .hg/hgrc: %s") % user)
170 _debug(ui, _("Username found in .hg/hgrc: %s") % user)
@@ -173,7 +179,7 b' class HTTPPasswordHandler(object):'
173 self.pwd_cache[cache_key] = user, pwd
179 self.pwd_cache[cache_key] = user, pwd
174 _debug_reply(ui, _("Keyring password found"),
180 _debug_reply(ui, _("Keyring password found"),
175 base_url, user, pwd)
181 base_url, user, pwd)
176 self.last_reply = dict(realm=realm,authuri=authuri,user=user)
182 self.last_reply = dict(realm=realm,authuri=authuri,user=user,req=req)
177 return user, pwd
183 return user, pwd
178 else:
184 else:
179 _debug(ui, _("Password not present in the keyring"))
185 _debug(ui, _("Password not present in the keyring"))
@@ -209,7 +215,7 b' class HTTPPasswordHandler(object):'
209
215
210 _debug_reply(ui, _("Manually entered password"),
216 _debug_reply(ui, _("Manually entered password"),
211 base_url, user, pwd)
217 base_url, user, pwd)
212 self.last_reply = dict(realm=realm,authuri=authuri,user=user)
218 self.last_reply = dict(realm=realm,authuri=authuri,user=user,req=req)
213 return user, pwd
219 return user, pwd
214
220
215 def load_hgrc_auth(self, ui, base_url, user):
221 def load_hgrc_auth(self, ui, base_url, user):
@@ -312,7 +318,28 b' def find_user_password(self, realm, auth'
312 if not hasattr(self, '_pwd_handler'):
318 if not hasattr(self, '_pwd_handler'):
313 self._pwd_handler = HTTPPasswordHandler()
319 self._pwd_handler = HTTPPasswordHandler()
314
320
315 return self._pwd_handler.find_auth(self, realm, authuri)
321 if hasattr(self, '_http_req'):
322 req = self._http_req
323 else:
324 req = None
325
326 return self._pwd_handler.find_auth(self, realm, authuri, req)
327
328 @monkeypatch_method(AbstractBasicAuthHandler, "http_error_auth_reqed")
329 def basic_http_error_auth_reqed(self, authreq, host, req, headers):
330 self.passwd._http_req = req
331 try:
332 return basic_http_error_auth_reqed.orig(self, authreq, host, req, headers)
333 finally:
334 self.passwd._http_req = None
335
336 @monkeypatch_method(AbstractDigestAuthHandler, "http_error_auth_reqed")
337 def digest_http_error_auth_reqed(self, authreq, host, req, headers):
338 self.passwd._http_req = req
339 try:
340 return digest_http_error_auth_reqed.orig(self, authreq, host, req, headers)
341 finally:
342 self.passwd._http_req = None
316
343
317 ############################################################
344 ############################################################
318
345
General Comments 0
You need to be logged in to leave comments. Login now