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