size_t pHelper = url.Find(":");
- if (pHelper == String::NPos) {
- m_Scheme = "";
- } else {
+ if (pHelper != String::NPos) {
if (!ParseScheme(url.SubStr(0, pHelper)))
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid URL Scheme."));
url = url.SubStr(pHelper + 1);
return;
}
- if (*(url.Begin() + 1) != '/')
- m_Authority = "";
- else {
+ if (*(url.Begin() + 1) == '/') {
pHelper = url.Find("/", 2);
if (pHelper == String::NPos)
return m_Path;
}
-const std::map<String,Value>& Url::GetQuery(void) const
+const std::map<String, std::vector<String> >& Url::GetQuery(void) const
{
return m_Query;
}
-Value Url::GetQueryElement(const String& name) const
+String Url::GetQueryElement(const String& name) const
{
- std::map<String, Value>::const_iterator it = m_Query.find(name);
+ std::map<String, std::vector<String> >::const_iterator it = m_Query.find(name);
if (it == m_Query.end())
- return Empty;
+ return String();
- return it->second;
+ return it->second.back();
}
+const std::vector<String>& Url::GetQueryElements(const String& name) const
+{
+ std::map<String, std::vector<String> >::const_iterator it = m_Query.find(name);
+
+ if (it == m_Query.end()) {
+ static std::vector<String> emptyVector;
+ return emptyVector;
+ }
+
+ return it->second;
+}
String Url::GetFragment(void) const
{
String Url::Format(void) const
{
- String url = "";
+ String url;
if (!m_Scheme.IsEmpty())
url += m_Scheme + ":";
}
}
- String param = "";
+ String param;
if (!m_Query.empty()) {
- typedef std::pair<String, Value> kv_pair;
+ typedef std::pair<String, std::vector<String> > kv_pair;
BOOST_FOREACH (const kv_pair& kv, m_Query) {
String key = Utility::EscapeString(kv.first, ACQUERY, false);
param = "?";
else
param += "&";
+
+ String temp;
+ BOOST_FOREACH (const String s, kv.second) {
+ if (!temp.IsEmpty())
+ temp += "&";
- Value val = kv.second;
-
- if (val.IsEmpty())
- param += key;
- else {
- if (val.IsObjectType<Array>()) {
- Array::Ptr arr = val;
- String temp = "";
-
- ObjectLock olock(arr);
- BOOST_FOREACH (const String& sArrIn, arr) {
- if (!temp.IsEmpty())
- temp += "&";
-
- temp += key + "[]=" + Utility::EscapeString(sArrIn, ACQUERY, false);
- }
-
- param += temp;
- } else
- param += key + "=" + Utility::EscapeString(kv.second, ACQUERY, false);
+ temp += key + "[]=" + Utility::EscapeString(s, ACQUERY, false);
}
+ param += temp;
}
}
bool Url::ParseAuthority(const String& authority)
{
- //TODO parse all Authorities
m_Authority = authority.SubStr(2);
- return (ValidateToken(m_Authority, ACHOST));
+ //Just safe the Authority and don't care about the details
+ return (ValidateToken(m_Authority, ACHOST GEN_DELIMS));
}
bool Url::ParsePath(const String& path)
BOOST_FOREACH(const String& token, tokens) {
size_t pHelper = token.Find("=");
+ if (pHelper == 0)
+ // /?foo=bar&=bar == invalid
+ return false;
+
String key = token.SubStr(0, pHelper);
String value = Empty;
- if (pHelper != String::NPos) {
- if (pHelper == token.GetLength() - 1)
- return false;
-
- value = token.SubStr(pHelper + 1);
- if (!ValidateToken(value, ACQUERY))
- return false;
- else
- value = Utility::UnescapeString(value);
- } else
- String key = token;
+ if (pHelper != token.GetLength()-1)
+ value = token.SubStr(pHelper+1);
- if (key.IsEmpty())
+ if (!ValidateToken(value, ACQUERY))
return false;
+
+ value = Utility::UnescapeString(value);
pHelper = key.Find("[]");
- if (pHelper != String::NPos) {
-
- if (key.GetLength() < 3)
- return false;
-
- key = key.SubStr(0, key.GetLength() - 2);
- key = Utility::UnescapeString(key);
+ if (pHelper == 0 || (pHelper != String::NPos && pHelper != key.GetLength()-2))
+ return false;
- if (!ValidateToken(value, ACQUERY))
- return false;
+ key = key.SubStr(0, pHelper);
+
+ if (!ValidateToken(key, ACQUERY))
+ return false;
- std::map<String, Value>::iterator it = m_Query.find(key);
+ key = Utility::UnescapeString(key);
- if (it == m_Query.end()) {
- Array::Ptr tmp = new Array();
- tmp->Add(Utility::UnescapeString(value));
- m_Query[key] = tmp;
- } else if (m_Query[key].IsObjectType<Array>()){
- Array::Ptr arr = it->second;
- arr->Add(Utility::UnescapeString(value));
- } else
- return false;
- } else {
- key = Utility::UnescapeString(key);
+ std::map<String, std::vector<String> >::iterator it = m_Query.find(key);
- if (m_Query.find(key) == m_Query.end() && ValidateToken(key, ACQUERY))
- m_Query[key] = Utility::UnescapeString(value);
- else
- return false;
- }
+ if (it == m_Query.end()) {
+ m_Query[key] = std::vector<String>();
+ m_Query[key].push_back(value);
+ } else
+ m_Query[key].push_back(value);
+
}
return true;
#include "remote/i2-remote.hpp"
#include "base/object.hpp"
#include "base/string.hpp"
+#include "base/array.hpp"
#include "base/value.hpp"
#include <map>
#include <vector>
String GetScheme(void) const;
String GetAuthority(void) const;
const std::vector<String>& GetPath(void) const;
- const std::map<String,Value>& GetQuery(void) const;
- Value GetQueryElement(const String& name) const;
+ const std::map<String, std::vector<String> >& GetQuery(void) const;
+ String GetQueryElement(const String& name) const;
+ const std::vector<String>& GetQueryElements(const String& name) const;
String GetFragment(void) const;
private:
String m_Scheme;
String m_Authority;
std::vector<String> m_Path;
- std::map<String,Value> m_Query;
+ std::map<String, std::vector<String> > m_Query;
String m_Fragment;
bool ParseScheme(const String& scheme);
BOOST_CHECK(url->GetQueryElement("rair") == "robert");
BOOST_CHECK(url->GetQueryElement("rain") == "karl");
- BOOST_CHECK(url->GetQueryElement("foo").IsObjectType<Array>());
- Array::Ptr test = url->GetQueryElement("foo");
- BOOST_CHECK(test->GetLength() == 1);
- BOOST_CHECK(test->Get(0) == "bar");
+ std::vector<String> test = url->GetQueryElements("foo");
+ BOOST_CHECK(test.size() == 1);
+ BOOST_CHECK(test[0] == "bar");
}
BOOST_AUTO_TEST_CASE(format)
BOOST_AUTO_TEST_CASE(illegal_legal_strings)
{
- BOOST_CHECK_THROW(new Url("/?foo=barr&foo[]=bazz"), std::invalid_argument);
+ BOOST_CHECK(new Url("/?foo=barr&foo[]=bazz"));
BOOST_CHECK_THROW(new Url("/?]=gar"), std::invalid_argument);
BOOST_CHECK_THROW(new Url("/#?[]"), std::invalid_argument);
- BOOST_CHECK_THROW(new Url("/?foo=bar&foo=ba"), std::invalid_argument);
+ BOOST_CHECK(new Url("/?foo=bar&foo=ba"));
BOOST_CHECK_THROW(new Url("/?foo=bar&[]=d"), std::invalid_argument);
- BOOST_CHECK_THROW(new Url("/?fo=&bar=garOA"), std::invalid_argument);
+ BOOST_CHECK(new Url("/?fo=&bar=garOA"));
+ BOOST_CHECK(new Url("https://127.0.0.1:5665/demo?type=Service&filter=service.state%3E0"));
BOOST_CHECK(new Url("/?foo=baz??&\?\?=/?"));
BOOST_CHECK(new Url("/"));
BOOST_CHECK(new Url("///////"));