From a16d415ee4a4b8a48f01c80919a11a026911c957 Mon Sep 17 00:00:00 2001 From: special Date: Sat, 20 Jan 2007 23:34:42 +0000 Subject: Fixed (rewrote) m_http_client's URL parsing, it is now more flexible and.. actually works. git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@6416 e03df62e-2008-0410-955e-edbf42e46eb7 --- include/hashcomp.h | 5 ++ src/hashcomp.cpp | 5 ++ src/modules/m_http_client.cpp | 112 ++++++++++++++++++++++++------------------ 3 files changed, 73 insertions(+), 49 deletions(-) diff --git a/include/hashcomp.h b/include/hashcomp.h index 2d6be15a9..abcc1e94e 100644 --- a/include/hashcomp.h +++ b/include/hashcomp.h @@ -285,6 +285,11 @@ namespace irc * @return The next token is returned, or an empty string if none remain */ virtual const std::string GetToken(); + + /** Returns true if the end of the stream has been reached + * @return True if the end of the stream has been reached, otherwise false + */ + virtual bool StreamEnd(); }; /** A derived form of sepstream, which seperates on commas diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index 5c9cac7bb..55b3f9b58 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -284,6 +284,11 @@ const std::string irc::sepstream::GetToken() return ""; } +bool irc::sepstream::StreamEnd() +{ + return ((n + 1) == tokens.end()); +} + irc::sepstream::~sepstream() { } diff --git a/src/modules/m_http_client.cpp b/src/modules/m_http_client.cpp index 7e929a8c5..706008104 100644 --- a/src/modules/m_http_client.cpp +++ b/src/modules/m_http_client.cpp @@ -175,65 +175,79 @@ bool HTTPSocket::ParseURL(const std::string &iurl) { url.url = iurl; url.port = 80; + url.protocol = "http"; - Instance->Log(DEBUG,"Parse: "+iurl); + irc::sepstream tokenizer(iurl, '/'); - // Tokenize by slashes (protocol:, blank, domain, request..) - int pos = 0, pstart = 0, pend = 0; - - for (;;) + for (int p = 0;; p++) { - pend = url.url.find('/', pstart); - string part = url.url.substr(pstart, pend); - - switch (pos) + std::string part = tokenizer.GetToken(); + if (part.empty() && tokenizer.StreamEnd()) + break; + + if ((p == 0) && (part[part.length() - 1] == ':')) { - case 0: - Instance->Log(DEBUG,"PART 0: "+part); - // Protocol - if (part[part.length()-1] != ':') - return false; - url.protocol = part.substr(0, part.length() - 1); - break; - case 1: - // Empty, skip - break; - case 2: - Instance->Log(DEBUG,"PART 2: "+part); - // User and password (user:pass@) - string::size_type aend = part.find('@', 0); - if (aend != string::npos) + // Protocol ('http:') + url.protocol = part.substr(0, part.length() - 1); + } + else if ((p == 1) && (part.empty())) + { + continue; + } + else if (url.domain.empty()) + { + // Domain part: [user[:pass]@]domain[:port] + std::string::size_type usrpos = part.find('@'); + if (usrpos != std::string::npos) + { + // Have a user (and possibly password) part + std::string::size_type ppos = part.find(':'); + if ((ppos != std::string::npos) && (ppos < usrpos)) { - // Technically, it is valid to not have a password (username@domain) - string::size_type usrend = part.find(':', 0); - - if ((usrend != string::npos) && (usrend < aend)) - url.password = part.substr(usrend + 1, aend); - else - usrend = aend; - - url.username = part.substr(0, usrend); + // Have password too + url.password = part.substr(ppos + 1, usrpos - ppos - 1); + url.username = part.substr(0, ppos); } else - aend = 0; - - // Port (:port) - string::size_type dend = part.find(':', aend); - if (dend != string::npos) - url.port = atoi(part.substr(dend + 1).c_str()); - - // Domain - url.domain = part.substr(aend + 1, dend); + { + url.username = part.substr(0, usrpos); + } - // The rest of the string is the request - url.request = url.url.substr(pend); - break; + part = part.substr(usrpos + 1); + } + + std::string::size_type popos = part.rfind(':'); + if (popos != std::string::npos) + { + url.port = atoi(part.substr(popos + 1).c_str()); + url.domain = part.substr(0, popos); + } + else + { + url.domain = part; + } } - - if (pos++ == 2) - break; + else + { + // Request (part of it).. + url.request.append("/"); + url.request.append(part); + } + } + + if (url.request.empty()) + url.request = "/"; - pstart = pend + 1; + if ((url.domain.empty()) || (!url.port) || (url.protocol.empty())) + { + Instance->Log(DEFAULT, "Invalid URL (%s): Missing required value", iurl.c_str()); + return false; + } + + if (url.protocol != "http") + { + Instance->Log(DEFAULT, "Invalid URL (%s): Unsupported protocol '%s'", iurl.c_str(), url.protocol.c_str()); + return false; } return true; -- cgit v1.2.3