- Refined cleanupPathName to encode the second slash only
authorMarius Tomaschewski <mt@suse.de>
Mon, 3 Apr 2006 18:10:15 +0000 (18:10 +0000)
committerMarius Tomaschewski <mt@suse.de>
Mon, 3 Apr 2006 18:10:15 +0000 (18:10 +0000)
  (minimal and sufficient), added decoding of first slash.
- Refined setPathName to allow first slash to be encoded
  if we get an encoded path (cleanupPathName will fix this);
  needed to be consistent with case where no host is present
  (relative path allowed) and we can't check the path begin.

zypp/url/UrlBase.cc
zypp/url/UrlBase.h

index f887334..b29e9a3 100644 (file)
@@ -1077,24 +1077,36 @@ namespace zypp
         if(eflag == zypp::url::E_ENCODED)
         {
           checkUrlData(path, "path name", config("rx_pathname"));
-        }
 
-        if( !getHost(zypp::url::E_ENCODED).empty())
-        {
-          if(path.at(0) != '/')
+          if( !getHost(zypp::url::E_ENCODED).empty())
           {
-            ZYPP_THROW(UrlNotAllowedException(
-              std::string("Relative path not allowed if authority exists")
-            ));
+            // has to begin with a "/". For consistency with
+            // setPathName while the host is empty, we allow
+            // it in encoded ("%2f") form - cleanupPathName()
+            // will fix / decode the first slash if needed.
+            if(!(path.at(0) == '/' || (path.size() >= 3 &&
+                 str::toLower(path.substr(0, 3)) == "%2f")))
+            {
+              ZYPP_THROW(UrlNotAllowedException(
+                std::string("Relative path not allowed if authority exists")
+              ));
+            }
           }
-        }
 
-        if(eflag == zypp::url::E_ENCODED)
-        {
           m_data->pathname = cleanupPathName(path);
         }
-        else
+        else //     zypp::url::E_DECODED
         {
+          if( !getHost(zypp::url::E_ENCODED).empty())
+          {
+            if(path.at(0) != '/')
+            {
+              ZYPP_THROW(UrlNotAllowedException(
+                std::string("Relative path not allowed if authority exists")
+              ));
+            }
+          }
+
           m_data->pathname = cleanupPathName(
             zypp::url::encode(
               path, config("safe_pathname")
@@ -1216,18 +1228,20 @@ namespace zypp
     UrlBase::cleanupPathName(const std::string &path)
     {
       std::string copy( path);
-      size_t      size( copy.size());
 
-      if( size >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
+      if( copy.size() >= 3 && str::toLower(copy.substr(0, 3)) == "%2f")
+      {
+        // decode the first slash if it is encoded ...
+        copy.replace(0, 3, "/");
+      }
+
+      if( copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/')
       {
-        size_t pos = 1;
-        // path begins with a double slash ("//"); encode second
-        // and further slashes before the first segment-nz (non
-        // zero), to fulfill the path-absolute rule of RFC 3986.
-        do {
-          copy.replace(pos, 1, "%2F");
-          pos += 3; // go behind "%2F"
-        } while( pos < size && copy.at(pos) == '/');
+        // path begins with a double slash ("//"); encode the second
+        // [minimal and IMO sufficient] slash before the first path
+        // segment, to fulfill the path-absolute rule of RFC 3986
+        // disallowing a "//" if no authority is present.
+        copy.replace(1, 1, "%2F");
       }
       return copy;
     }
index 85e93f5..54542f5 100644 (file)
@@ -988,12 +988,14 @@ namespace zypp
 
     protected:
       /**
-       * Utility method to cleanup a path name.
+       * Utility method to cleanup an encoded path name.
        *
-       * By default, this method encodes the second and further
-       * slashes before the first (non-zero) path segment of an
-       * already encoded path name. For example, it modifies a
-       * "ftp://host///aaa//bbb" to "ftp://host/%2F%2Faaa//bbb".
+       * By default, this method makes sure, that the first slash
+       * in the path is not encoded, and that the second slash
+       * before the first path segment, is encoded (to "%2F").
+       * It modifies the path in the url, for example:
+       *   "ftp://host//aaa//bbb" to "ftp://host/%2Faaa//bbb"
+       * or as encoded path only also "%2f/name" to "/%2fname".
        *
        * This operation is required to fulfill the path-absolute
        * rule of RFC3986, if there is no authority. It avoids the
@@ -1005,8 +1007,8 @@ namespace zypp
        *
        * We apply this operation in both cases (for all paths).
        *
-       * \param path   Encoded path name to cleanup.
-       * \return A path begining with at most one "/" character.
+       * \param path   The encoded path name to cleanup.
+       * \return A modified encoded path.
        */
       virtual std::string
       cleanupPathName(const std::string &path);