diff --git a/code/nel/include/nel/gui/url_parser.h b/code/nel/include/nel/gui/url_parser.h
new file mode 100644
index 000000000..b47e67b37
--- /dev/null
+++ b/code/nel/include/nel/gui/url_parser.h
@@ -0,0 +1,63 @@
+// Ryzom - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+#ifndef CL_URL_PARSER_H
+#define CL_URL_PARSER_H
+
+#include
+
+namespace NLGUI
+{
+ /**
+ * Simple URL parser
+ * \author Meelis Mägi
+ * \date 2015
+ */
+ class CUrlParser
+ {
+ public:
+ CUrlParser(){}
+
+ // parse uri to components
+ CUrlParser(const std::string &url);
+
+ // parse uri to components
+ void parse(std::string uri);
+
+ // serialize URL back to string
+ std::string toString() const;
+
+ // inherit scheme, domain, path from given url
+ void inherit(const std::string &url);
+
+ // if current parts can compose absolute url or not
+ bool isAbsolute() const;
+
+ // resolve relative path like './a/../b' to absolute path '/a/b'
+ static void resolveRelativePath(std::string &path);
+
+ public:
+ std::string scheme;
+ std::string domain;
+ std::string path;
+ std::string query;
+ std::string hash;
+ };
+
+}// namespace
+
+#endif // CL_URL_PARSER_H
+
diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp
index ae1975789..0ec026a1a 100644
--- a/code/nel/src/gui/group_html.cpp
+++ b/code/nel/src/gui/group_html.cpp
@@ -43,7 +43,7 @@
#include "nel/misc/md5.h"
#include "nel/3d/texture_file.h"
#include "nel/misc/big_file.h"
-#include
+#include "nel/gui/url_parser.h"
using namespace std;
using namespace NLMISC;
@@ -4777,20 +4777,13 @@ namespace NLGUI
// ***************************************************************************
std::string CGroupHTML::getAbsoluteUrl(const std::string &url)
{
- if (_URL.size() == 0 || url.find("http://") != std::string::npos || url.find("https://") != std::string::npos)
+ CUrlParser uri(url);
+ if (uri.isAbsolute())
return url;
- xmlChar * uri;
- uri = xmlBuildURI(reinterpret_cast(url.c_str()), reinterpret_cast(_URL.c_str()));
- if (uri)
- {
- std::string ret(reinterpret_cast(uri));
- xmlFree(uri);
+ uri.inherit(_URL);
- return ret;
- }
-
- return url;
+ return uri.toString();
}
// ***************************************************************************
diff --git a/code/nel/src/gui/url_parser.cpp b/code/nel/src/gui/url_parser.cpp
new file mode 100644
index 000000000..68d4f8496
--- /dev/null
+++ b/code/nel/src/gui/url_parser.cpp
@@ -0,0 +1,222 @@
+// Ryzom - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+#include
+#include "nel/misc/types_nl.h"
+#include "nel/gui/url_parser.h"
+
+using namespace std;
+
+
+namespace NLGUI
+{
+ // ***************************************************************************
+ CUrlParser::CUrlParser(const std::string &uri)
+ {
+ parse(uri);
+ }
+
+ // ***************************************************************************
+ void CUrlParser::parse(std::string uri)
+ {
+ const size_t npos = std::string::npos;
+ size_t pos;
+ size_t offset = 0;
+
+ // strip fragment if present
+ pos = uri.find("#");
+ if (pos != npos)
+ {
+ hash = uri.substr(pos + 1);
+ uri = uri.substr(0, pos);
+ }
+
+ // scan for scheme
+ pos = uri.find(":");
+ if (pos != npos && pos >= 1)
+ {
+ for (uint i=0; i 0)
+ {
+ // full or last segment
+ sub = path.substr(pos-1, 4);
+ if (sub == "/../" || sub == "/..")
+ {
+ if (pos > 1)
+ lhp = path.find_last_of("/", pos - 2);
+ else
+ lhp = 0;
+
+ // pos points to first dot in ..
+ // lhp points to start slash (/) of last segment
+ pos += sub.size() - 1;
+ path.replace(lhp, pos - lhp, "/");
+ pos = lhp;
+ }
+ }
+ }// sub == ".."
+ } // path[pos] == '.'
+ pos++;
+ }// while
+ }
+
+ bool CUrlParser::isAbsolute() const
+ {
+ return !scheme.empty() && !domain.empty();
+ }
+
+ // serialize URL back to string
+ std::string CUrlParser::toString() const
+ {
+ std::string result;
+ if (!scheme.empty())
+ result += scheme + ":";
+
+ if (!domain.empty())
+ {
+ result += domain;
+ }
+
+ // path already has leading slash
+ if (!path.empty())
+ result += path;
+
+ if (!query.empty())
+ result += "?" + query;
+
+ if (!hash.empty())
+ result += "#" + hash;
+
+ return result;
+ }
+
+}// namespace
+