Changeset 388 for python/vendor/current/Lib/urllib2.py
- Timestamp:
- Mar 19, 2014, 11:11:30 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
python/vendor/current/Lib/urllib2.py
r2 r388 103 103 import urlparse 104 104 import bisect 105 import warnings 105 106 106 107 try: … … 110 111 111 112 from urllib import (unwrap, unquote, splittype, splithost, quote, 112 addinfourl, splitport, 113 addinfourl, splitport, splittag, toBytes, 113 114 splitattr, ftpwrapper, splituser, splitpasswd, splitvalue) 114 115 … … 167 168 return 'HTTP Error %s: %s' % (self.code, self.msg) 168 169 170 # since URLError specifies a .reason attribute, HTTPError should also 171 # provide this attribute. See issue13211 fo discussion. 172 @property 173 def reason(self): 174 return self.msg 175 176 def info(self): 177 return self.hdrs 178 169 179 # copied from cookielib.py 170 180 _cut_port_re = re.compile(r":\d+$") … … 191 201 # unwrap('<URL:type://host/path>') --> 'type://host/path' 192 202 self.__original = unwrap(url) 203 self.__original, self.__fragment = splittag(self.__original) 193 204 self.type = None 194 205 # self.__r_type is what's left after doing the splittype … … 236 247 237 248 def get_full_url(self): 238 return self.__original 249 if self.__fragment: 250 return '%s#%s' % (self.__original, self.__fragment) 251 else: 252 return self.__original 239 253 240 254 def get_type(self): … … 299 313 client_version = "Python-urllib/%s" % __version__ 300 314 self.addheaders = [('User-agent', client_version)] 315 # self.handlers is retained only for backward compatibility 316 self.handlers = [] 301 317 # manage the individual handlers 302 self.handlers = []303 318 self.handle_open = {} 304 319 self.handle_error = {} … … 350 365 351 366 if added: 352 # the handlers must work in an specific order, the order353 # is specified in a Handler attribute354 367 bisect.insort(self.handlers, handler) 355 368 handler.add_parent(self) … … 450 463 import types 451 464 def isclass(obj): 452 return isinstance(obj, types.ClassType) or hasattr(obj, "__bases__")465 return isinstance(obj, (types.ClassType, type)) 453 466 454 467 opener = OpenerDirector() … … 579 592 newurl = urlparse.urljoin(req.get_full_url(), newurl) 580 593 594 # For security reasons we do not allow redirects to protocols 595 # other than HTTP, HTTPS or FTP. 596 newurl_lower = newurl.lower() 597 if not (newurl_lower.startswith('http://') or 598 newurl_lower.startswith('https://') or 599 newurl_lower.startswith('ftp://')): 600 raise HTTPError(newurl, code, 601 msg + " - Redirection to url '%s' is not allowed" % 602 newurl, 603 headers, fp) 604 581 605 # XXX Probably want to forget about the state of the current 582 606 # request, although that might interact poorly with other … … 809 833 # (single quotes are a violation of the RFC, but appear in the wild) 810 834 rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+' 811 'realm=(["\'] )(.*?)\\2', re.I)835 'realm=(["\']?)([^"\']*)\\2', re.I) 812 836 813 837 # XXX could pre-emptively send auth info already accepted (RFC 2617, … … 820 844 self.passwd = password_mgr 821 845 self.add_password = self.passwd.add_password 846 self.retried = 0 847 848 def reset_retry_count(self): 849 self.retried = 0 822 850 823 851 def http_error_auth_reqed(self, authreq, host, req, headers): … … 826 854 # XXX could be multiple headers 827 855 authreq = headers.get(authreq, None) 856 857 if self.retried > 5: 858 # retry sending the username:password 5 times before failing. 859 raise HTTPError(req.get_full_url(), 401, "basic auth failed", 860 headers, None) 861 else: 862 self.retried += 1 863 828 864 if authreq: 829 865 mo = AbstractBasicAuthHandler.rx.search(authreq) 830 866 if mo: 831 867 scheme, quote, realm = mo.groups() 868 if quote not in ['"', "'"]: 869 warnings.warn("Basic Auth Realm was unquoted", 870 UserWarning, 2) 832 871 if scheme.lower() == 'basic': 833 return self.retry_http_basic_auth(host, req, realm) 872 response = self.retry_http_basic_auth(host, req, realm) 873 if response and response.code != 401: 874 self.retried = 0 875 return response 834 876 835 877 def retry_http_basic_auth(self, host, req, realm): … … 852 894 def http_error_401(self, req, fp, code, msg, headers): 853 895 url = req.get_full_url() 854 return self.http_error_auth_reqed('www-authenticate', 855 url, req, headers) 896 response = self.http_error_auth_reqed('www-authenticate', 897 url, req, headers) 898 self.reset_retry_count() 899 return response 856 900 857 901 … … 866 910 # userinfo. 867 911 authority = req.get_host() 868 re turnself.http_error_auth_reqed('proxy-authenticate',912 response = self.http_error_auth_reqed('proxy-authenticate', 869 913 authority, req, headers) 914 self.reset_retry_count() 915 return response 870 916 871 917 … … 1108 1154 h.set_debuglevel(self._debuglevel) 1109 1155 1110 headers = dict(req.headers) 1111 headers.update(req.unredirected_hdrs) 1156 headers = dict(req.unredirected_hdrs) 1157 headers.update(dict((k, v) for k, v in req.headers.items() 1158 if k not in headers)) 1159 1112 1160 # We want to make an HTTP/1.1 request, but the addinfourl 1113 1161 # class isn't prepared to deal with a persistent connection. … … 1128 1176 # server. 1129 1177 del headers[proxy_auth_hdr] 1130 h. _set_tunnel(req._tunnel_host, headers=tunnel_headers)1178 h.set_tunnel(req._tunnel_host, headers=tunnel_headers) 1131 1179 1132 1180 try: 1133 1181 h.request(req.get_method(), req.get_selector(), req.data, headers) 1134 r = h.getresponse()1135 1182 except socket.error, err: # XXX what error? 1183 h.close() 1136 1184 raise URLError(err) 1185 else: 1186 try: 1187 r = h.getresponse(buffering=True) 1188 except TypeError: # buffering kw not supported 1189 r = h.getresponse() 1137 1190 1138 1191 # Pick apart the HTTPResponse object to get the addinfourl … … 1247 1300 return [part.strip() for part in res] 1248 1301 1302 def _safe_gethostbyname(host): 1303 try: 1304 return socket.gethostbyname(host) 1305 except socket.gaierror: 1306 return None 1307 1249 1308 class FileHandler(BaseHandler): 1250 1309 # Use local file or FTP depending on form of URL 1251 1310 def file_open(self, req): 1252 1311 url = req.get_selector() 1253 if url[:2] == '//' and url[2:3] != '/': 1312 if url[:2] == '//' and url[2:3] != '/' and (req.host and 1313 req.host != 'localhost'): 1254 1314 req.type = 'ftp' 1255 1315 return self.parent.open(req) … … 1274 1334 import mimetypes 1275 1335 host = req.get_host() 1276 file = req.get_selector()1277 localfile = url2pathname(file )1336 filename = req.get_selector() 1337 localfile = url2pathname(filename) 1278 1338 try: 1279 1339 stats = os.stat(localfile) 1280 1340 size = stats.st_size 1281 1341 modified = email.utils.formatdate(stats.st_mtime, usegmt=True) 1282 mtype = mimetypes.guess_type(file )[0]1342 mtype = mimetypes.guess_type(filename)[0] 1283 1343 headers = mimetools.Message(StringIO( 1284 1344 'Content-type: %s\nContent-length: %d\nLast-modified: %s\n' % … … 1287 1347 host, port = splitport(host) 1288 1348 if not host or \ 1289 (not port and socket.gethostbyname(host) in self.get_names()): 1290 return addinfourl(open(localfile, 'rb'), 1291 headers, 'file:'+file) 1349 (not port and _safe_gethostbyname(host) in self.get_names()): 1350 if host: 1351 origurl = 'file://' + host + filename 1352 else: 1353 origurl = 'file://' + filename 1354 return addinfourl(open(localfile, 'rb'), headers, origurl) 1292 1355 except OSError, msg: 1293 1356 # urllib2 users shouldn't expect OSErrors coming from urlopen() … … 1315 1378 passwd = None 1316 1379 host = unquote(host) 1317 user = u nquote(user or '')1318 passwd = unquote(passwd or '')1380 user = user or '' 1381 passwd = passwd or '' 1319 1382 1320 1383 try: … … 1350 1413 1351 1414 def connect_ftp(self, user, passwd, host, port, dirs, timeout): 1352 fw = ftpwrapper(user, passwd, host, port, dirs, timeout) 1415 fw = ftpwrapper(user, passwd, host, port, dirs, timeout, 1416 persistent=False) 1353 1417 ## fw.ftp.set_debuglevel(1) 1354 1418 return fw … … 1399 1463 break 1400 1464 self.soonest = min(self.timeout.values()) 1465 1466 def clear_cache(self): 1467 for conn in self.cache.values(): 1468 conn.close() 1469 self.cache.clear() 1470 self.timeout.clear()
Note:
See TracChangeset
for help on using the changeset viewer.