17db96d56Sopenharmony_ci"""Convert a NT pathname to a file URL and vice versa. 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciThis module only exists to provide OS-specific code 47db96d56Sopenharmony_cifor urllib.requests, thus do not use directly. 57db96d56Sopenharmony_ci""" 67db96d56Sopenharmony_ci# Testing is done through test_urllib. 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_cidef url2pathname(url): 97db96d56Sopenharmony_ci """OS-specific conversion from a relative URL of the 'file' scheme 107db96d56Sopenharmony_ci to a file system path; not recommended for general use.""" 117db96d56Sopenharmony_ci # e.g. 127db96d56Sopenharmony_ci # ///C|/foo/bar/spam.foo 137db96d56Sopenharmony_ci # and 147db96d56Sopenharmony_ci # ///C:/foo/bar/spam.foo 157db96d56Sopenharmony_ci # become 167db96d56Sopenharmony_ci # C:\foo\bar\spam.foo 177db96d56Sopenharmony_ci import string, urllib.parse 187db96d56Sopenharmony_ci # Windows itself uses ":" even in URLs. 197db96d56Sopenharmony_ci url = url.replace(':', '|') 207db96d56Sopenharmony_ci if not '|' in url: 217db96d56Sopenharmony_ci # No drive specifier, just convert slashes 227db96d56Sopenharmony_ci if url[:4] == '////': 237db96d56Sopenharmony_ci # path is something like ////host/path/on/remote/host 247db96d56Sopenharmony_ci # convert this to \\host\path\on\remote\host 257db96d56Sopenharmony_ci # (notice halving of slashes at the start of the path) 267db96d56Sopenharmony_ci url = url[2:] 277db96d56Sopenharmony_ci components = url.split('/') 287db96d56Sopenharmony_ci # make sure not to convert quoted slashes :-) 297db96d56Sopenharmony_ci return urllib.parse.unquote('\\'.join(components)) 307db96d56Sopenharmony_ci comp = url.split('|') 317db96d56Sopenharmony_ci if len(comp) != 2 or comp[0][-1] not in string.ascii_letters: 327db96d56Sopenharmony_ci error = 'Bad URL: ' + url 337db96d56Sopenharmony_ci raise OSError(error) 347db96d56Sopenharmony_ci drive = comp[0][-1].upper() 357db96d56Sopenharmony_ci components = comp[1].split('/') 367db96d56Sopenharmony_ci path = drive + ':' 377db96d56Sopenharmony_ci for comp in components: 387db96d56Sopenharmony_ci if comp: 397db96d56Sopenharmony_ci path = path + '\\' + urllib.parse.unquote(comp) 407db96d56Sopenharmony_ci # Issue #11474 - handing url such as |c/| 417db96d56Sopenharmony_ci if path.endswith(':') and url.endswith('/'): 427db96d56Sopenharmony_ci path += '\\' 437db96d56Sopenharmony_ci return path 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_cidef pathname2url(p): 467db96d56Sopenharmony_ci """OS-specific conversion from a file system path to a relative URL 477db96d56Sopenharmony_ci of the 'file' scheme; not recommended for general use.""" 487db96d56Sopenharmony_ci # e.g. 497db96d56Sopenharmony_ci # C:\foo\bar\spam.foo 507db96d56Sopenharmony_ci # becomes 517db96d56Sopenharmony_ci # ///C:/foo/bar/spam.foo 527db96d56Sopenharmony_ci import urllib.parse 537db96d56Sopenharmony_ci # First, clean up some special forms. We are going to sacrifice 547db96d56Sopenharmony_ci # the additional information anyway 557db96d56Sopenharmony_ci if p[:4] == '\\\\?\\': 567db96d56Sopenharmony_ci p = p[4:] 577db96d56Sopenharmony_ci if p[:4].upper() == 'UNC\\': 587db96d56Sopenharmony_ci p = '\\' + p[4:] 597db96d56Sopenharmony_ci elif p[1:2] != ':': 607db96d56Sopenharmony_ci raise OSError('Bad path: ' + p) 617db96d56Sopenharmony_ci if not ':' in p: 627db96d56Sopenharmony_ci # No drive specifier, just convert slashes and quote the name 637db96d56Sopenharmony_ci if p[:2] == '\\\\': 647db96d56Sopenharmony_ci # path is something like \\host\path\on\remote\host 657db96d56Sopenharmony_ci # convert this to ////host/path/on/remote/host 667db96d56Sopenharmony_ci # (notice doubling of slashes at the start of the path) 677db96d56Sopenharmony_ci p = '\\\\' + p 687db96d56Sopenharmony_ci components = p.split('\\') 697db96d56Sopenharmony_ci return urllib.parse.quote('/'.join(components)) 707db96d56Sopenharmony_ci comp = p.split(':', maxsplit=2) 717db96d56Sopenharmony_ci if len(comp) != 2 or len(comp[0]) > 1: 727db96d56Sopenharmony_ci error = 'Bad path: ' + p 737db96d56Sopenharmony_ci raise OSError(error) 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci drive = urllib.parse.quote(comp[0].upper()) 767db96d56Sopenharmony_ci components = comp[1].split('\\') 777db96d56Sopenharmony_ci path = '///' + drive + ':' 787db96d56Sopenharmony_ci for comp in components: 797db96d56Sopenharmony_ci if comp: 807db96d56Sopenharmony_ci path = path + '/' + urllib.parse.quote(comp) 817db96d56Sopenharmony_ci return path 82