os.path.vnormpath

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ben Allfree

    os.path.vnormpath

    Written to normalize web server path names based on a virtual root. I
    propose that something equivalent to this be added to os.path
    -------------------------------------
    import os.path
    import copy

    def vnormpath(root, path):
    """
    Normalize a path based on a virtual root.
    """
    r = copy.deepcopy(r oot)
    p = copy.deepcopy(p ath)

    if os.path.isabs(p ath):
    return root + path
    while os.path.commonp refix([root, os.path.normpat h(os.path.join( r,p))])
    <> root:
    r = os.path.join(r, "junk")
    return os.path.normpat h(os.path.join( r,p))


    if __name__ == "__main__":
    print vnormpath("C:\\ foo\\baz",
    "..\\..\\..\\.. \\foo\\baz\\..\ \..\\..\\frob\\ glop")


  • Peter Otten

    #2
    Re: os.path.vnormpa th

    Ben Allfree wrote:
    [color=blue]
    > Written to normalize web server path names based on a virtual root. I
    > propose that something equivalent to this be added to os.path[/color]

    The purpose remains unclear to me. Maybe you could expand a little.
    For now, I suppose you intend vnormpath() to always return subfolders of
    root.
    [color=blue]
    > -------------------------------------
    > import os.path
    > import copy
    >
    > def vnormpath(root, path):
    > """
    > Normalize a path based on a virtual root.
    > """
    > r = copy.deepcopy(r oot)
    > p = copy.deepcopy(p ath)[/color]

    Strings are "immutable" , i. e. you can't change them once created. You
    therefore need not (I'd rather say must not) copy them.
    [color=blue]
    >
    > if os.path.isabs(p ath):
    > return root + path[/color]

    This can give you funny paths on Windows like "C:/firstC:/second"; on Unix
    you can get anywhere the supplier of *path* wants,
    e. g. vnormpath("/home/peter", "/../ben") returns "/home/peter/../ben" which
    is equivalent to "home/ben".
    [color=blue]
    > while os.path.commonp refix([root,
    > os.path.normpat h(os.path.join( r,p))])
    > <> root:
    > r = os.path.join(r, "junk")
    > return os.path.normpat h(os.path.join( r,p))[/color]

    I tried to break that, too, but must admit I didn't succed so far :-)
    By the way, most pythonistas favour != over <>.
    [color=blue]
    > if __name__ == "__main__":
    > print vnormpath("C:\\ foo\\baz",
    > "..\\..\\..\\.. \\foo\\baz\\..\ \..\\..\\frob\\ glop")[/color]

    The above demo is probably a good start, but try to think of a few more
    use/test cases. For example, should
    vnormpath("/home/ben", "/home/ben/temp") return "/home/ben/home/ben/temp" or
    rather "home/ben/temp"? Also, I would compare vnormpath()'s actual against
    the expected result instead of just printing it out. For production quality
    code, have a look at the unittest module.

    Conclusion: For the moment, be satisfied if you can fix the bugs and your
    function serves *your* needs well. If you want to share the results, put it
    on a web site.
    For your code to make it into the python library, you have to convince
    people that *they* need it badly and I dare say that you may face some
    strong opposition.

    Peter


    Comment

    • Ben Allfree

      #3
      Re: os.path.vnormpa th

      Correct. vnormpath() should enforce the same rules web servers resolves a
      virtual paths on the server side.

      Example:

      Virtual root - C:\foo\baz\wwwr oot
      URL - <a href="..\grop.h tml">

      The above should never resolve to anything higher than
      C:\foo\baz\wwwr oot\grop.html regardless of its position in the web root
      directory.

      vnormpath("C:\\ foo\\baz\\wwwro ot", "..\\grop.html" ) ==
      "C:\\foo\\baz\\ wwwroot\\grop.h tml"

      Likewise (here's a catch):

      Virtual root - C:\foo\baz\wwwr oot
      URL - <a href="\..\..\ba z\wwwroot\grop. html">

      Should resolve to C:\foo\baz\wwwr oot\baz\wwwroot \grop.html

      I hope that make sense. My code is a start at solving the issue.

      "Peter Otten" <__peter__@web. de> wrote in message
      news:bol2ob$1uv $03$1@news.t-online.com...[color=blue]
      > Ben Allfree wrote:
      >[color=green]
      > > Written to normalize web server path names based on a virtual root. I
      > > propose that something equivalent to this be added to os.path[/color]
      >
      > The purpose remains unclear to me. Maybe you could expand a little.
      > For now, I suppose you intend vnormpath() to always return subfolders of
      > root.
      >[color=green]
      > > -------------------------------------
      > > import os.path
      > > import copy
      > >
      > > def vnormpath(root, path):
      > > """
      > > Normalize a path based on a virtual root.
      > > """
      > > r = copy.deepcopy(r oot)
      > > p = copy.deepcopy(p ath)[/color]
      >
      > Strings are "immutable" , i. e. you can't change them once created. You
      > therefore need not (I'd rather say must not) copy them.
      >[color=green]
      > >
      > > if os.path.isabs(p ath):
      > > return root + path[/color]
      >
      > This can give you funny paths on Windows like "C:/firstC:/second"; on Unix
      > you can get anywhere the supplier of *path* wants,
      > e. g. vnormpath("/home/peter", "/../ben") returns "/home/peter/../ben"[/color]
      which[color=blue]
      > is equivalent to "home/ben".
      >[color=green]
      > > while os.path.commonp refix([root,
      > > os.path.normpat h(os.path.join( r,p))])
      > > <> root:
      > > r = os.path.join(r, "junk")
      > > return os.path.normpat h(os.path.join( r,p))[/color]
      >
      > I tried to break that, too, but must admit I didn't succed so far :-)
      > By the way, most pythonistas favour != over <>.
      >[color=green]
      > > if __name__ == "__main__":
      > > print vnormpath("C:\\ foo\\baz",
      > > "..\\..\\..\\.. \\foo\\baz\\..\ \..\\..\\frob\\ glop")[/color]
      >
      > The above demo is probably a good start, but try to think of a few more
      > use/test cases. For example, should
      > vnormpath("/home/ben", "/home/ben/temp") return "/home/ben/home/ben/temp"[/color]
      or[color=blue]
      > rather "home/ben/temp"? Also, I would compare vnormpath()'s actual against
      > the expected result instead of just printing it out. For production[/color]
      quality[color=blue]
      > code, have a look at the unittest module.
      >
      > Conclusion: For the moment, be satisfied if you can fix the bugs and your
      > function serves *your* needs well. If you want to share the results, put[/color]
      it[color=blue]
      > on a web site.
      > For your code to make it into the python library, you have to convince
      > people that *they* need it badly and I dare say that you may face some
      > strong opposition.
      >
      > Peter
      >
      >[/color]


      Comment

      • JanC

        #4
        Re: os.path.vnormpa th

        "Ben Allfree" <benles@bldigit al.com> schreef:
        [color=blue]
        > Virtual root - C:\foo\baz\wwwr oot
        > URL - <a href="\..\..\ba z\wwwroot\grop. html">
        >
        > Should resolve to C:\foo\baz\wwwr oot\baz\wwwroot \grop.html[/color]

        According to RFC-2396 this should resolve to:

        C:\foo\baz\wwwr oot\..\..\baz\w wwroot\grop.htm l

        The ".." above are real path segments/directory names and don't have the
        special "go up 1 level" meaning.

        IMHO for web servers that map URL path segments to local paths this should
        result in an HTTP error (when ".." is not allowed on the local filesystem).

        They also mention that in practice your solution is in use by some parsers,
        so people might not be too surprised by its functioning... ;-)


        <http://www.cs.tut.fi/~jkorpela/rfc/2396/full.html#C>

        --
        JanC

        "Be strict when sending and tolerant when receiving."
        RFC 1958 - Architectural Principles of the Internet - section 3.9

        Comment

        Working...