// ---------------------------------------------------------------
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)
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)))
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;
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);
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);
}
}
// ---------------------------------------------------------------
/** 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);
// ---------------------------------------------------------------