- Limited safe chars in encode, added "second pass" flag
authorMarius Tomaschewski <mt@suse.de>
Wed, 18 Jan 2006 18:02:49 +0000 (18:02 +0000)
committerMarius Tomaschewski <mt@suse.de>
Wed, 18 Jan 2006 18:02:49 +0000 (18:02 +0000)
- Added separator checks to split and join functions

zypp/url/UrlUtils.cc
zypp/url/UrlUtils.h

index c186117..ac6aded 100644 (file)
@@ -27,14 +27,22 @@ namespace zypp
 
     // ---------------------------------------------------------------
     std::string
-    encode(const std::string &str, const std::string &safe)
+    encode(const std::string &str, const std::string &safe,
+                                   EEncoding         eflag)
     {
       std::string skip("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                        "abcdefghijklmnopqrstuvwxyz"
-                       "0123456789_.-" + safe);
+                       "0123456789.~_-");
+      std::string more(":/?#[]@!$&'()*+,;=");
       size_t      beg, pos, len;
       std::string out;
 
+      for(size_t i=0; i<safe.size(); i++)
+      {
+        if( more.find(safe.at(i)) != std::string::npos)
+          skip.append(1, safe.at(i));
+      }
+
       len = str.length();
       beg = 0;
       while( beg < len)
@@ -47,8 +55,8 @@ namespace zypp
             out.append(str, beg, pos - beg);
           }
 
-          if( /* detect_encoded && */
-              pos + 2 < len &&
+          if( eflag == E_ENCODED &&
+              pos + 2 < len      &&
               str.at(pos) == '%' &&
               std::isxdigit(str.at(pos + 1)) &&
               std::isxdigit(str.at(pos + 2)))
@@ -154,9 +162,15 @@ namespace zypp
     void
     split(ParamVec          &pvec,
           const std::string &pstr,
-         const std::string &psep)
+               const std::string &psep)
     {
       size_t beg, pos, len;
+      if( psep.empty())
+      {
+        throw std::invalid_argument(
+          "Invalid split separator character."
+        );
+      }
 
       len = pstr.length();
       beg = 0;
@@ -186,10 +200,17 @@ namespace zypp
           const std::string &vsep,
           EEncoding         eflag)
     {
-      ParamVec     pvec;
+      ParamVec                 pvec;
       ParamVec::const_iterator pitr;
-      std::string    k, v;
-      size_t       pos;
+      std::string              k, v;
+      size_t                   pos;
+
+      if( psep.empty() || vsep.empty())
+      {
+        throw std::invalid_argument(
+          "Invalid split separator character."
+        );
+      }
 
       split(pvec, str, psep);
 
@@ -254,31 +275,36 @@ namespace zypp
          const std::string &vsep,
          const std::string &safe)
     {
+      if( psep.empty() || vsep.empty())
+      {
+        throw std::invalid_argument(
+          "Invalid join separator character."
+        );
+      }
+
+      std::string join_safe;
       for(std::string::size_type i=0; i<safe.size(); i++)
       {
-        if( psep.find(safe[i]) != std::string::npos ||
-            vsep.find(safe[i]) != std::string::npos)
+        if( psep.find(safe[i]) == std::string::npos &&
+            vsep.find(safe[i]) == std::string::npos)
         {
-          throw std::invalid_argument(
-            "The encoding safe character list contains a separator character."
-          );
+          join_safe.append(1, safe[i]);
         }
       }
-
-      std::string    str;
+      std::string              str;
       ParamMap::const_iterator i( pmap.begin());
 
       if( i != pmap.end())
       {
-        str = encode(i->first, safe);
+        str = encode(i->first, join_safe);
         if( !i->second.empty())
-          str += vsep + encode(i->second, safe);
+          str += vsep + encode(i->second, join_safe);
 
         while( ++i != pmap.end())
         {
-          str += psep + encode(i->first, safe);
+          str += psep + encode(i->first, join_safe);
           if( !i->second.empty())
-            str +=  vsep + encode(i->second, safe);
+            str +=  vsep + encode(i->second, join_safe);
         }
       }
 
index 14a5c3d..f2a3c5b 100644 (file)
@@ -54,24 +54,32 @@ namespace zypp
     // ---------------------------------------------------------------
     /** Encodes a string using URL percent encoding.
      *
-     * Already encoded characters are detected and will be not encoded a
-     * second time. By default, all characters except of "a-zA-Z0-9_.-"
-     * will be encoded. Additional characters can be specified in the
+     * By default, all characters except of "a-zA-Z0-9_.-" will be encoded.
+     * Additional characters from the set ":/?#[]@!$&'()*+,;=", that are
+     * safe for a URL compoent without encoding, can be specified in the
      * \p safe argument.
      *
+     * If the \p eflag parameter is set to E_ENCODED, then already encoded
+     * substrings will be detected and not encoded a second time.
+     *
      * The following function call will encode the "@" character as "%40",
-     * but skip encoding of the "%" character:
+     * but skip encoding of the "%" character, because the \p eflag is set
+     * to E_ENCODED and "%ba" is detected as a valid encoded character.
      * \code
-     *   zypp::url::encode("foo%bar@localhost", "%");
+     *   zypp::url::encode("foo%bar@localhost", "", E_ENCODED);
      * \endcode
+     * With \p eflag set to E_DECODED, the "%" character would be encoded
+     * as well. The complete encoded string would be "foo%25bar%40localhost".
      *
      * \param str      A string to encode (binary data).
      * \param safe     Characters safe to skip in encoding,
      *                 e.g. "/" for path names.
+     * \param eflag    If to detect and skip already encoded substrings.
      * \return A percent encoded string.
      */
     std::string
-    encode(const std::string &str, const std::string &safe = "");
+    encode(const std::string &str, const std::string &safe = "",
+                                   EEncoding         eflag = E_DECODED);
 
 
     // ---------------------------------------------------------------