mercurial/url.py
changeset 28883 032c4c2f802a
parent 28861 86db5cb55d46
child 29227 dffe78d80a6c
equal deleted inserted replaced
28882:800ec7c048b0 28883:032c4c2f802a
    11 
    11 
    12 import base64
    12 import base64
    13 import httplib
    13 import httplib
    14 import os
    14 import os
    15 import socket
    15 import socket
    16 import urllib
       
    17 import urllib2
       
    18 
    16 
    19 from .i18n import _
    17 from .i18n import _
    20 from . import (
    18 from . import (
    21     error,
    19     error,
    22     httpconnection as httpconnectionmod,
    20     httpconnection as httpconnectionmod,
    24     sslutil,
    22     sslutil,
    25     util,
    23     util,
    26 )
    24 )
    27 stringio = util.stringio
    25 stringio = util.stringio
    28 
    26 
    29 class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm):
    27 urlerr = util.urlerr
       
    28 urlreq = util.urlreq
       
    29 
       
    30 class passwordmgr(urlreq.httppasswordmgrwithdefaultrealm):
    30     def __init__(self, ui):
    31     def __init__(self, ui):
    31         urllib2.HTTPPasswordMgrWithDefaultRealm.__init__(self)
    32         urlreq.httppasswordmgrwithdefaultrealm.__init__(self)
    32         self.ui = ui
    33         self.ui = ui
    33 
    34 
    34     def find_user_password(self, realm, authuri):
    35     def find_user_password(self, realm, authuri):
    35         authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
    36         authinfo = urlreq.httppasswordmgrwithdefaultrealm.find_user_password(
    36             self, realm, authuri)
    37             self, realm, authuri)
    37         user, passwd = authinfo
    38         user, passwd = authinfo
    38         if user and passwd:
    39         if user and passwd:
    39             self._writedebug(user, passwd)
    40             self._writedebug(user, passwd)
    40             return (user, passwd)
    41             return (user, passwd)
    70     def _writedebug(self, user, passwd):
    71     def _writedebug(self, user, passwd):
    71         msg = _('http auth: user %s, password %s\n')
    72         msg = _('http auth: user %s, password %s\n')
    72         self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
    73         self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
    73 
    74 
    74     def find_stored_password(self, authuri):
    75     def find_stored_password(self, authuri):
    75         return urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
    76         return urlreq.httppasswordmgrwithdefaultrealm.find_user_password(
    76             self, None, authuri)
    77             self, None, authuri)
    77 
    78 
    78 class proxyhandler(urllib2.ProxyHandler):
    79 class proxyhandler(urlreq.proxyhandler):
    79     def __init__(self, ui):
    80     def __init__(self, ui):
    80         proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
    81         proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
    81         # XXX proxyauthinfo = None
    82         # XXX proxyauthinfo = None
    82 
    83 
    83         if proxyurl:
    84         if proxyurl:
   119                     if env in os.environ:
   120                     if env in os.environ:
   120                         del os.environ[env]
   121                         del os.environ[env]
   121                 except OSError:
   122                 except OSError:
   122                     pass
   123                     pass
   123 
   124 
   124         urllib2.ProxyHandler.__init__(self, proxies)
   125         urlreq.proxyhandler.__init__(self, proxies)
   125         self.ui = ui
   126         self.ui = ui
   126 
   127 
   127     def proxy_open(self, req, proxy, type_):
   128     def proxy_open(self, req, proxy, type_):
   128         host = req.get_host().split(':')[0]
   129         host = req.get_host().split(':')[0]
   129         for e in self.no_list:
   130         for e in self.no_list:
   132             if e.startswith('*.') and host.endswith(e[2:]):
   133             if e.startswith('*.') and host.endswith(e[2:]):
   133                 return None
   134                 return None
   134             if e.startswith('.') and host.endswith(e[1:]):
   135             if e.startswith('.') and host.endswith(e[1:]):
   135                 return None
   136                 return None
   136 
   137 
   137         return urllib2.ProxyHandler.proxy_open(self, req, proxy, type_)
   138         return urlreq.proxyhandler.proxy_open(self, req, proxy, type_)
   138 
   139 
   139 def _gen_sendfile(orgsend):
   140 def _gen_sendfile(orgsend):
   140     def _sendfile(self, data):
   141     def _sendfile(self, data):
   141         # send a file
   142         # send a file
   142         if isinstance(data, httpconnectionmod.httpsendfile):
   143         if isinstance(data, httpconnectionmod.httpsendfile):
   146                 orgsend(self, chunk)
   147                 orgsend(self, chunk)
   147         else:
   148         else:
   148             orgsend(self, data)
   149             orgsend(self, data)
   149     return _sendfile
   150     return _sendfile
   150 
   151 
   151 has_https = util.safehasattr(urllib2, 'HTTPSHandler')
   152 has_https = util.safehasattr(urlreq, 'httpshandler')
   152 if has_https:
   153 if has_https:
   153     try:
   154     try:
   154         _create_connection = socket.create_connection
   155         _create_connection = socket.create_connection
   155     except AttributeError:
   156     except AttributeError:
   156         _GLOBAL_DEFAULT_TIMEOUT = object()
   157         _GLOBAL_DEFAULT_TIMEOUT = object()
   355             self.sock = sslutil.wrapsocket(
   356             self.sock = sslutil.wrapsocket(
   356                 self.sock, self.key_file, self.cert_file, serverhostname=host,
   357                 self.sock, self.key_file, self.cert_file, serverhostname=host,
   357                 **sslutil.sslkwargs(self.ui, host))
   358                 **sslutil.sslkwargs(self.ui, host))
   358             sslutil.validator(self.ui, host)(self.sock)
   359             sslutil.validator(self.ui, host)(self.sock)
   359 
   360 
   360     class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler):
   361     class httpshandler(keepalive.KeepAliveHandler, urlreq.httpshandler):
   361         def __init__(self, ui):
   362         def __init__(self, ui):
   362             keepalive.KeepAliveHandler.__init__(self)
   363             keepalive.KeepAliveHandler.__init__(self)
   363             urllib2.HTTPSHandler.__init__(self)
   364             urlreq.httpshandler.__init__(self)
   364             self.ui = ui
   365             self.ui = ui
   365             self.pwmgr = passwordmgr(self.ui)
   366             self.pwmgr = passwordmgr(self.ui)
   366 
   367 
   367         def _start_transaction(self, h, req):
   368         def _start_transaction(self, h, req):
   368             _generic_start_transaction(self, h, req)
   369             _generic_start_transaction(self, h, req)
   401             conn = httpsconnection(host, port, keyfile, certfile, *args,
   402             conn = httpsconnection(host, port, keyfile, certfile, *args,
   402                                    **kwargs)
   403                                    **kwargs)
   403             conn.ui = self.ui
   404             conn.ui = self.ui
   404             return conn
   405             return conn
   405 
   406 
   406 class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler):
   407 class httpdigestauthhandler(urlreq.httpdigestauthhandler):
   407     def __init__(self, *args, **kwargs):
   408     def __init__(self, *args, **kwargs):
   408         urllib2.HTTPDigestAuthHandler.__init__(self, *args, **kwargs)
   409         urlreq.httpdigestauthhandler.__init__(self, *args, **kwargs)
   409         self.retried_req = None
   410         self.retried_req = None
   410 
   411 
   411     def reset_retry_count(self):
   412     def reset_retry_count(self):
   412         # Python 2.6.5 will call this on 401 or 407 errors and thus loop
   413         # Python 2.6.5 will call this on 401 or 407 errors and thus loop
   413         # forever. We disable reset_retry_count completely and reset in
   414         # forever. We disable reset_retry_count completely and reset in
   417     def http_error_auth_reqed(self, auth_header, host, req, headers):
   418     def http_error_auth_reqed(self, auth_header, host, req, headers):
   418         # Reset the retry counter once for each request.
   419         # Reset the retry counter once for each request.
   419         if req is not self.retried_req:
   420         if req is not self.retried_req:
   420             self.retried_req = req
   421             self.retried_req = req
   421             self.retried = 0
   422             self.retried = 0
   422         return urllib2.HTTPDigestAuthHandler.http_error_auth_reqed(
   423         return urlreq.httpdigestauthhandler.http_error_auth_reqed(
   423                     self, auth_header, host, req, headers)
   424                     self, auth_header, host, req, headers)
   424 
   425 
   425 class httpbasicauthhandler(urllib2.HTTPBasicAuthHandler):
   426 class httpbasicauthhandler(urlreq.httpbasicauthhandler):
   426     def __init__(self, *args, **kwargs):
   427     def __init__(self, *args, **kwargs):
   427         self.auth = None
   428         self.auth = None
   428         urllib2.HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
   429         urlreq.httpbasicauthhandler.__init__(self, *args, **kwargs)
   429         self.retried_req = None
   430         self.retried_req = None
   430 
   431 
   431     def http_request(self, request):
   432     def http_request(self, request):
   432         if self.auth:
   433         if self.auth:
   433             request.add_unredirected_header(self.auth_header, self.auth)
   434             request.add_unredirected_header(self.auth_header, self.auth)
   449     def http_error_auth_reqed(self, auth_header, host, req, headers):
   450     def http_error_auth_reqed(self, auth_header, host, req, headers):
   450         # Reset the retry counter once for each request.
   451         # Reset the retry counter once for each request.
   451         if req is not self.retried_req:
   452         if req is not self.retried_req:
   452             self.retried_req = req
   453             self.retried_req = req
   453             self.retried = 0
   454             self.retried = 0
   454         return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed(
   455         return urlreq.httpbasicauthhandler.http_error_auth_reqed(
   455                         self, auth_header, host, req, headers)
   456                         self, auth_header, host, req, headers)
   456 
   457 
   457     def retry_http_basic_auth(self, host, req, realm):
   458     def retry_http_basic_auth(self, host, req, realm):
   458         user, pw = self.passwd.find_user_password(realm, req.get_full_url())
   459         user, pw = self.passwd.find_user_password(realm, req.get_full_url())
   459         if pw is not None:
   460         if pw is not None:
   492                  (user, passwd and '*' * len(passwd) or 'not set'))
   493                  (user, passwd and '*' * len(passwd) or 'not set'))
   493 
   494 
   494     handlers.extend((httpbasicauthhandler(passmgr),
   495     handlers.extend((httpbasicauthhandler(passmgr),
   495                      httpdigestauthhandler(passmgr)))
   496                      httpdigestauthhandler(passmgr)))
   496     handlers.extend([h(ui, passmgr) for h in handlerfuncs])
   497     handlers.extend([h(ui, passmgr) for h in handlerfuncs])
   497     opener = urllib2.build_opener(*handlers)
   498     opener = urlreq.buildopener(*handlers)
   498 
   499 
   499     # 1.0 here is the _protocol_ version
   500     # 1.0 here is the _protocol_ version
   500     opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
   501     opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
   501     opener.addheaders.append(('Accept', 'application/mercurial-0.1'))
   502     opener.addheaders.append(('Accept', 'application/mercurial-0.1'))
   502     return opener
   503     return opener
   506     if u.scheme:
   507     if u.scheme:
   507         u.scheme = u.scheme.lower()
   508         u.scheme = u.scheme.lower()
   508         url_, authinfo = u.authinfo()
   509         url_, authinfo = u.authinfo()
   509     else:
   510     else:
   510         path = util.normpath(os.path.abspath(url_))
   511         path = util.normpath(os.path.abspath(url_))
   511         url_ = 'file://' + urllib.pathname2url(path)
   512         url_ = 'file://' + urlreq.pathname2url(path)
   512         authinfo = None
   513         authinfo = None
   513     return opener(ui, authinfo).open(url_, data)
   514     return opener(ui, authinfo).open(url_, data)