@@ -1448,16 +1448,6 @@ def parse_http_list(s):
1448
1448
return [part .strip () for part in res ]
1449
1449
1450
1450
class FileHandler (BaseHandler ):
1451
- # Use local file or FTP depending on form of URL
1452
- def file_open (self , req ):
1453
- url = req .selector
1454
- if url [:2 ] == '//' and url [2 :3 ] != '/' and (req .host and
1455
- req .host != 'localhost' ):
1456
- if not req .host in self .get_names ():
1457
- raise URLError ("file:// scheme is supported only on localhost" )
1458
- else :
1459
- return self .open_local_file (req )
1460
-
1461
1451
# names for the localhost
1462
1452
names = None
1463
1453
def get_names (self ):
@@ -1474,9 +1464,8 @@ def get_names(self):
1474
1464
def open_local_file (self , req ):
1475
1465
import email .utils
1476
1466
import mimetypes
1477
- host = req .host
1478
- filename = req .selector
1479
- localfile = url2pathname (filename )
1467
+ filename = req .full_url
1468
+ localfile = url2pathname (filename .removeprefix ('file:' ))
1480
1469
try :
1481
1470
stats = os .stat (localfile )
1482
1471
size = stats .st_size
@@ -1485,24 +1474,20 @@ def open_local_file(self, req):
1485
1474
headers = email .message_from_string (
1486
1475
'Content-type: %s\n Content-length: %d\n Last-modified: %s\n ' %
1487
1476
(mtype or 'text/plain' , size , modified ))
1488
- if host :
1489
- host , port = _splitport (host )
1490
- if not host or \
1491
- (not port and _safe_gethostbyname (host ) in self .get_names ()):
1492
- if host :
1493
- origurl = 'file://' + host + filename
1494
- else :
1495
- origurl = 'file://' + filename
1496
- return addinfourl (open (localfile , 'rb' ), headers , origurl )
1477
+ return addinfourl (open (localfile , 'rb' ), headers , filename )
1497
1478
except OSError as exp :
1498
1479
raise URLError (exp )
1499
- raise URLError ('file not on local host' )
1500
1480
1501
- def _safe_gethostbyname (host ):
1481
+ file_open = open_local_file
1482
+
1483
+ def _is_local_host (host ):
1484
+ if not host or host == 'localhost' :
1485
+ return True
1502
1486
try :
1503
- return socket .gethostbyname (host )
1487
+ name = socket .gethostbyname (host )
1504
1488
except socket .gaierror :
1505
- return None
1489
+ return False
1490
+ return name in FileHandler ().get_names ()
1506
1491
1507
1492
class FTPHandler (BaseHandler ):
1508
1493
def ftp_open (self , req ):
@@ -1653,13 +1638,12 @@ def data_open(self, req):
1653
1638
if os .name == 'nt' :
1654
1639
from nturl2path import url2pathname , pathname2url
1655
1640
else :
1656
- def url2pathname (pathname ):
1641
+ def url2pathname (url ):
1657
1642
"""OS-specific conversion from a relative URL of the 'file' scheme
1658
1643
to a file system path; not recommended for general use."""
1659
- if pathname [:3 ] == '///' :
1660
- # URL has an empty authority section, so the path begins on the
1661
- # third character.
1662
- pathname = pathname [2 :]
1644
+ authority , pathname = urlsplit (f'file:{ url } ' )[1 :3 ]
1645
+ if not _is_local_host (authority ):
1646
+ raise URLError (f'URL { url !r} uses non-local authority { authority !r} ' )
1663
1647
return unquote (pathname )
1664
1648
1665
1649
def pathname2url (pathname ):
0 commit comments