Show More
@@ -357,6 +357,15 b' def addaliases(ui, cmdtable):' | |||
|
357 | 357 | # but only if they have been defined prior to the current definition. |
|
358 | 358 | for alias, definition in ui.configitems('alias'): |
|
359 | 359 | aliasdef = cmdalias(alias, definition, cmdtable) |
|
360 | ||
|
361 | try: | |
|
362 | olddef = cmdtable[aliasdef.cmd][0] | |
|
363 | if olddef.definition == aliasdef.definition: | |
|
364 | continue | |
|
365 | except (KeyError, AttributeError): | |
|
366 | # definition might not exist or it might not be a cmdalias | |
|
367 | pass | |
|
368 | ||
|
360 | 369 | cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help) |
|
361 | 370 | if aliasdef.norepo: |
|
362 | 371 | commands.norepo += ' %s' % alias |
@@ -58,7 +58,7 b' class httpsendfile(object):' | |||
|
58 | 58 | return self._len |
|
59 | 59 | |
|
60 | 60 | # moved here from url.py to avoid a cycle |
|
61 | def readauthforuri(ui, uri): | |
|
61 | def readauthforuri(ui, uri, user): | |
|
62 | 62 | # Read configuration |
|
63 | 63 | config = dict() |
|
64 | 64 | for key, val in ui.configitems('auth'): |
@@ -72,10 +72,6 b' def readauthforuri(ui, uri):' | |||
|
72 | 72 | gdict[setting] = val |
|
73 | 73 | |
|
74 | 74 | # Find the best match |
|
75 | uri = util.url(uri) | |
|
76 | user = uri.user | |
|
77 | uri.user = uri.password = None | |
|
78 | uri = str(uri) | |
|
79 | 75 | scheme, hostpath = uri.split('://', 1) |
|
80 | 76 | bestuser = None |
|
81 | 77 | bestlen = 0 |
@@ -238,7 +234,11 b' class http2handler(urllib2.HTTPHandler, ' | |||
|
238 | 234 | return self.do_open(HTTPConnection, req, False) |
|
239 | 235 | |
|
240 | 236 | def https_open(self, req): |
|
241 | res = readauthforuri(self.ui, req.get_full_url()) | |
|
237 | # req.get_full_url() does not contain credentials and we may | |
|
238 | # need them to match the certificates. | |
|
239 | url = req.get_full_url() | |
|
240 | user, password = self.pwmgr.find_stored_password(url) | |
|
241 | res = readauthforuri(self.ui, url, user) | |
|
242 | 242 | if res: |
|
243 | 243 | group, auth = res |
|
244 | 244 | self.auth = auth |
@@ -26,7 +26,7 b' class passwordmgr(urllib2.HTTPPasswordMg' | |||
|
26 | 26 | return (user, passwd) |
|
27 | 27 | |
|
28 | 28 | if not user or not passwd: |
|
29 | res = httpconnectionmod.readauthforuri(self.ui, authuri) | |
|
29 | res = httpconnectionmod.readauthforuri(self.ui, authuri, user) | |
|
30 | 30 | if res: |
|
31 | 31 | group, auth = res |
|
32 | 32 | user, passwd = auth.get('username'), auth.get('password') |
@@ -53,6 +53,10 b' class passwordmgr(urllib2.HTTPPasswordMg' | |||
|
53 | 53 | msg = _('http auth: user %s, password %s\n') |
|
54 | 54 | self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set')) |
|
55 | 55 | |
|
56 | def find_stored_password(self, authuri): | |
|
57 | return urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password( | |
|
58 | self, None, authuri) | |
|
59 | ||
|
56 | 60 | class proxyhandler(urllib2.ProxyHandler): |
|
57 | 61 | def __init__(self, ui): |
|
58 | 62 | proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy') |
@@ -342,7 +346,11 b' if has_https:' | |||
|
342 | 346 | return keepalive.KeepAliveHandler._start_transaction(self, h, req) |
|
343 | 347 | |
|
344 | 348 | def https_open(self, req): |
|
345 | res = httpconnectionmod.readauthforuri(self.ui, req.get_full_url()) | |
|
349 | # req.get_full_url() does not contain credentials and we may | |
|
350 | # need them to match the certificates. | |
|
351 | url = req.get_full_url() | |
|
352 | user, password = self.pwmgr.find_stored_password(url) | |
|
353 | res = httpconnectionmod.readauthforuri(self.ui, url, user) | |
|
346 | 354 | if res: |
|
347 | 355 | group, auth = res |
|
348 | 356 | self.auth = auth |
@@ -1468,6 +1468,8 b' class url(object):' | |||
|
1468 | 1468 | path = None |
|
1469 | 1469 | if not self.host: |
|
1470 | 1470 | self.host = None |
|
1471 | # path of file:///d is /d | |
|
1472 | # path of file:///d:/ is d:/, not /d:/ | |
|
1471 | 1473 | if path and not hasdriveletter(path): |
|
1472 | 1474 | path = '/' + path |
|
1473 | 1475 | |
@@ -1587,7 +1589,9 b' class url(object):' | |||
|
1587 | 1589 | self.user, self.passwd = user, passwd |
|
1588 | 1590 | if not self.user: |
|
1589 | 1591 | return (s, None) |
|
1590 | return (s, (None, (str(self), self.host), | |
|
1592 | # authinfo[1] is passed to urllib2 password manager, and its URIs | |
|
1593 | # must not contain credentials. | |
|
1594 | return (s, (None, (s, self.host), | |
|
1591 | 1595 | self.user, self.passwd or '')) |
|
1592 | 1596 | |
|
1593 | 1597 | def isabs(self): |
@@ -1610,11 +1614,6 b' class url(object):' | |||
|
1610 | 1614 | path = self._hostport + '/' + self.path |
|
1611 | 1615 | elif self.host is not None and self.path: |
|
1612 | 1616 | path = '/' + path |
|
1613 | # We also need to handle the case of file:///C:/, which | |
|
1614 | # should return C:/, not /C:/. | |
|
1615 | elif hasdriveletter(path): | |
|
1616 | # Strip leading slash from paths with drive names | |
|
1617 | return path[1:] | |
|
1618 | 1617 | return path |
|
1619 | 1618 | return self._origpath |
|
1620 | 1619 |
@@ -1,4 +1,5 b'' | |||
|
1 | 1 | from mercurial import demandimport; demandimport.enable() |
|
2 | import urllib2 | |
|
2 | 3 | from mercurial import ui, util |
|
3 | 4 | from mercurial import url |
|
4 | 5 | from mercurial.error import Abort |
@@ -36,10 +37,10 b' def test(auth, urls=None):' | |||
|
36 | 37 | print 'URI:', uri |
|
37 | 38 | try: |
|
38 | 39 | pm = url.passwordmgr(ui) |
|
39 |
authinfo = util.url(uri).authinfo() |
|
|
40 | u, authinfo = util.url(uri).authinfo() | |
|
40 | 41 | if authinfo is not None: |
|
41 | 42 | pm.add_password(*authinfo) |
|
42 |
print ' ', pm.find_user_password('test', u |
|
|
43 | print ' ', pm.find_user_password('test', u) | |
|
43 | 44 | except Abort, e: |
|
44 | 45 | print 'abort' |
|
45 | 46 | |
@@ -95,3 +96,12 b" test({'x.prefix': 'http://example.org/fo" | |||
|
95 | 96 | 'y.username': 'y', |
|
96 | 97 | 'y.password': 'ypassword'}, |
|
97 | 98 | urls=['http://y@example.org/foo/bar']) |
|
99 | ||
|
100 | def testauthinfo(fullurl, authurl): | |
|
101 | print 'URIs:', fullurl, authurl | |
|
102 | pm = urllib2.HTTPPasswordMgrWithDefaultRealm() | |
|
103 | pm.add_password(*util.url(fullurl).authinfo()[1]) | |
|
104 | print pm.find_user_password('test', authurl) | |
|
105 | ||
|
106 | print '\n*** Test urllib2 and util.url\n' | |
|
107 | testauthinfo('http://user@example.com:8080/foo', 'http://example.com:8080/foo') |
@@ -189,3 +189,8 b' URI: http://y@example.org/foo' | |||
|
189 | 189 | CFG: {x.password: xpassword, x.prefix: http://example.org/foo/bar, x.username: None, y.password: ypassword, y.prefix: http://example.org/foo, y.username: y} |
|
190 | 190 | URI: http://y@example.org/foo/bar |
|
191 | 191 | ('y', 'xpassword') |
|
192 | ||
|
193 | *** Test urllib2 and util.url | |
|
194 | ||
|
195 | URIs: http://user@example.com:8080/foo http://example.com:8080/foo | |
|
196 | ('user', '') |
@@ -110,6 +110,55 b' clone from invalid URL' | |||
|
110 | 110 | abort: HTTP Error 404: Not Found |
|
111 | 111 | [255] |
|
112 | 112 | |
|
113 | test http authentication | |
|
114 | ||
|
115 | $ cd test | |
|
116 | $ cat << EOT > userpass.py | |
|
117 | > import base64 | |
|
118 | > from mercurial.hgweb import common | |
|
119 | > def perform_authentication(hgweb, req, op): | |
|
120 | > auth = req.env.get('HTTP_AUTHORIZATION') | |
|
121 | > if not auth: | |
|
122 | > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who', | |
|
123 | > [('WWW-Authenticate', 'Basic Realm="mercurial"')]) | |
|
124 | > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']: | |
|
125 | > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no') | |
|
126 | > def extsetup(): | |
|
127 | > common.permhooks.insert(0, perform_authentication) | |
|
128 | > EOT | |
|
129 | $ hg --config extensions.x=userpass.py serve -p $HGPORT2 -d --pid-file=pid | |
|
130 | $ cat pid >> $DAEMON_PIDS | |
|
131 | ||
|
132 | $ hg id http://localhost:$HGPORT2/ | |
|
133 | abort: http authorization required | |
|
134 | [255] | |
|
135 | $ hg id http://user@localhost:$HGPORT2/ | |
|
136 | abort: http authorization required | |
|
137 | [255] | |
|
138 | $ hg id http://user:pass@localhost:$HGPORT2/ | |
|
139 | 5fed3813f7f5 | |
|
140 | $ echo '[auth]' >> .hg/hgrc | |
|
141 | $ echo 'l.schemes=http' >> .hg/hgrc | |
|
142 | $ echo 'l.prefix=lo' >> .hg/hgrc | |
|
143 | $ echo 'l.username=user' >> .hg/hgrc | |
|
144 | $ echo 'l.password=pass' >> .hg/hgrc | |
|
145 | $ hg id http://localhost:$HGPORT2/ | |
|
146 | 5fed3813f7f5 | |
|
147 | $ hg id http://localhost:$HGPORT2/ | |
|
148 | 5fed3813f7f5 | |
|
149 | $ hg id http://user@localhost:$HGPORT2/ | |
|
150 | 5fed3813f7f5 | |
|
151 | $ hg id http://user:pass@localhost:$HGPORT2/ | |
|
152 | 5fed3813f7f5 | |
|
153 | $ hg id http://user2@localhost:$HGPORT2/ | |
|
154 | abort: http authorization required | |
|
155 | [255] | |
|
156 | $ hg id http://user:pass2@localhost:$HGPORT2/ | |
|
157 | abort: HTTP Error 403: no | |
|
158 | [255] | |
|
159 | ||
|
160 | $ cd .. | |
|
161 | ||
|
113 | 162 | check error log |
|
114 | 163 | |
|
115 | 164 | $ cat error.log |
@@ -204,18 +204,32 b' def test_url():' | |||
|
204 | 204 | <url scheme: 'file', path: '/foo/bar/baz'> |
|
205 | 205 | >>> str(u) |
|
206 | 206 | 'file:///foo/bar/baz' |
|
207 | >>> u.localpath() | |
|
208 | '/foo/bar/baz' | |
|
207 | 209 | |
|
208 | 210 | >>> u = url('file:///foo/bar/baz') |
|
209 | 211 | >>> u |
|
210 | 212 | <url scheme: 'file', path: '/foo/bar/baz'> |
|
211 | 213 | >>> str(u) |
|
212 | 214 | 'file:///foo/bar/baz' |
|
215 | >>> u.localpath() | |
|
216 | '/foo/bar/baz' | |
|
217 | ||
|
218 | >>> u = url('file:///f:oo/bar/baz') | |
|
219 | >>> u | |
|
220 | <url scheme: 'file', path: 'f:oo/bar/baz'> | |
|
221 | >>> str(u) | |
|
222 | 'file:f%3Aoo/bar/baz' | |
|
223 | >>> u.localpath() | |
|
224 | 'f:oo/bar/baz' | |
|
213 | 225 | |
|
214 | 226 | >>> u = url('file:foo/bar/baz') |
|
215 | 227 | >>> u |
|
216 | 228 | <url scheme: 'file', path: 'foo/bar/baz'> |
|
217 | 229 | >>> str(u) |
|
218 | 230 | 'file:foo/bar/baz' |
|
231 | >>> u.localpath() | |
|
232 | 'foo/bar/baz' | |
|
219 | 233 | """ |
|
220 | 234 | |
|
221 | 235 | doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE) |
General Comments 0
You need to be logged in to leave comments.
Login now