Added parameter support to 'utility::url'.

This commit is contained in:
Vincent Richard 2005-04-28 16:35:37 +00:00
parent 38a8632828
commit 4bf0542857
4 changed files with 150 additions and 2 deletions

View File

@ -69,6 +69,8 @@ url& url::operator=(const url& u)
m_path = u.m_path;
m_params = u.m_params;
return (*this);
}
@ -120,6 +122,29 @@ const string url::build() const
oss << urlUtils::encode(m_path);
}
const std::vector <const propertySet::property*> params
= m_params.getPropertyList();
if (!params.empty())
{
if (m_path.empty())
oss << "/";
oss << "?";
for (unsigned int i = 0 ; i < params.size() ; ++i)
{
const propertySet::property* prop = params[i];
if (i != 0)
oss << "&";
oss << urlUtils::encode(prop->getName());
oss << "=";
oss << urlUtils::encode(prop->getValue());
}
}
return (oss.str());
}
@ -191,6 +216,15 @@ void url::parse(const string& str)
// Path
string path = utility::stringUtils::trim(string(str.begin() + slashPos, str.end()));
string params;
string::size_type paramSep = path.find_first_of('?');
if (paramSep != string::npos)
{
params = string(path.begin() + paramSep + 1, path.end());
path.erase(path.begin() + paramSep, path.end());
}
if (path == "/")
path.clear();
@ -224,6 +258,48 @@ void url::parse(const string& str)
if (portNum == 0)
portNum = UNSPECIFIED_PORT;
// Extract parameters
m_params.removeAllProperties();
if (!params.empty())
{
string::size_type pos = 0;
do
{
const string::size_type start = pos;
pos = params.find_first_of('&', pos);
const string::size_type equal = params.find_first_of('=', start);
const string::size_type end =
(pos == string::npos ? params.length() : pos);
string name;
string value;
if (equal == string::npos || equal > pos) // no value
{
name = string(params.begin() + start, params.begin() + end);
value = name;
}
else
{
name = string(params.begin() + start, params.begin() + equal);
value = string(params.begin() + equal + 1, params.begin() + end);
}
name = urlUtils::decode(name);
value = urlUtils::decode(value);
m_params.setProperty(name, value);
if (pos != string::npos)
++pos;
}
while (pos != string::npos);
}
// Now, save URL parts
m_protocol = proto;
@ -309,5 +385,17 @@ void url::setPath(const string& path)
}
const propertySet& url::getParams() const
{
return (m_params);
}
propertySet& url::getParams()
{
return (m_params);
}
} // utility
} // vmime

View File

@ -34,7 +34,8 @@ const string urlUtils::encode(const string& s)
{
const char_t c = *it;
if (parserHelpers::isPrint(c) && !parserHelpers::isSpace(c) && c != '%')
if (parserHelpers::isPrint(c) && !parserHelpers::isSpace(c) &&
c != '%' && c != '=' && c != '?' && c != '&')
{
result += c;
}

View File

@ -149,13 +149,57 @@ namespace
assert_eq("1.7", "/pa\xabth/", u1.getPath());
}
void testParse4()
{
// Test parameters
vmime::utility::url u1("", "");
assert_eq("1.1", true, parseHelper(u1, "proto://host/path?p1=v1&p2=v2"));
assert_eq("1.2", "v1", u1.getParams().getProperty <vmime::string>("p1"));
assert_eq("1.3", "v2", u1.getParams().getProperty <vmime::string>("p2"));
assert_eq("1.4", "/path", u1.getPath());
vmime::utility::url u2("", "");
assert_eq("2.1", true, parseHelper(u2, "proto://host/path?p1=v1&p2"));
assert_eq("2.2", "v1", u2.getParams().getProperty <vmime::string>("p1"));
assert_eq("2.3", "p2", u2.getParams().getProperty <vmime::string>("p2"));
assert_eq("2.4", "/path", u2.getPath());
vmime::utility::url u3("", "");
assert_eq("3.1", true, parseHelper(u3, "proto://host/?p1=v1&p2=v2"));
assert_eq("3.2", "v1", u3.getParams().getProperty <vmime::string>("p1"));
assert_eq("3.3", "v2", u3.getParams().getProperty <vmime::string>("p2"));
assert_eq("3.4", "", u3.getPath());
vmime::utility::url u4("", "");
assert_eq("4.1", true, parseHelper(u4, "proto://host/path?p1=%3D&%3D=v2"));
assert_eq("4.2", "=", u4.getParams().getProperty <vmime::string>("p1"));
assert_eq("4.3", "v2", u4.getParams().getProperty <vmime::string>("="));
assert_eq("4.4", "/path", u4.getPath());
}
void testGenerate()
{
vmime::utility::url u1("proto", "host", 12345, "path", "user", "password");
assert_eq("1", "proto://user:password@host:12345/path",
static_cast <vmime::string>(u1));
// TODO: more tests
vmime::utility::url u2("proto", "host");
assert_eq("2", "proto://host", static_cast <vmime::string>(u2));
vmime::utility::url u3("proto", "host");
u3.getParams().setProperty("p1", "v1");
assert_eq("3.1", "proto://host/?p1=v1",
static_cast <vmime::string>(u3));
u3.getParams().setProperty("p2", "v2");
assert_eq("3.2", "proto://host/?p1=v1&p2=v2",
static_cast <vmime::string>(u3));
u3.getParams().setProperty("&", "=");
assert_eq("3.3", "proto://host/?p1=v1&p2=v2&%26=%3D",
static_cast <vmime::string>(u3));
}
void testUtilsEncode()
@ -196,6 +240,7 @@ namespace
add("Parse1", testcase(this, "Parse1", &urlTest::testParse1));
add("Parse2", testcase(this, "Parse2", &urlTest::testParse2));
add("Parse3", testcase(this, "Parse3", &urlTest::testParse3));
add("Parse4", testcase(this, "Parse4", &urlTest::testParse4));
add("Generate", testcase(this, "Generate", &urlTest::testGenerate));
add("UtilsEncode", testcase(this, "UtilsEncode", &urlTest::testUtilsEncode));
add("UtilsDecode", testcase(this, "UtilsDecode", &urlTest::testUtilsDecode));

View File

@ -23,6 +23,7 @@
#include "vmime/types.hpp"
#include "vmime/base.hpp"
#include "vmime/propertySet.hpp"
namespace vmime {
@ -153,6 +154,17 @@ public:
*/
void setPath(const string& path);
/** Return the parameters of the URL (read-only).
*
* @return parameters
*/
const propertySet& getParams() const;
/** Return the parameters of the URL.
*
* @return parameters
*/
propertySet& getParams();
/** Build a string URL from this object.
*/
@ -179,6 +191,8 @@ private:
port_t m_port;
string m_path;
propertySet m_params;
};