From 79acb915cea66d4440d064ddaccd1f52eb826fe7 Mon Sep 17 00:00:00 2001 From: Benjamin Sergeant Date: Fri, 24 Apr 2020 14:08:59 -0700 Subject: [PATCH] merge the 2 url parsing file into one, fix a silly build error --- CMakeLists.txt | 2 - ixwebsocket/IXUrlParser.cpp | 327 +++++++++++++++++++++++++++++++++++- ixwebsocket/LUrlParser.cpp | 280 ------------------------------ ixwebsocket/LUrlParser.h | 84 --------- test/IXUnityBuildsTest.cpp | 5 +- 5 files changed, 329 insertions(+), 369 deletions(-) delete mode 100644 ixwebsocket/LUrlParser.cpp delete mode 100644 ixwebsocket/LUrlParser.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e6a638ed..bf437739 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,6 @@ set( IXWEBSOCKET_SOURCES ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp ixwebsocket/IXWebSocketServer.cpp ixwebsocket/IXWebSocketTransport.cpp - ixwebsocket/LUrlParser.cpp ) set( IXWEBSOCKET_HEADERS @@ -93,7 +92,6 @@ set( IXWEBSOCKET_HEADERS ixwebsocket/IXWebSocketServer.h ixwebsocket/IXWebSocketTransport.h ixwebsocket/IXWebSocketVersion.h - ixwebsocket/LUrlParser.h ) if (UNIX) diff --git a/ixwebsocket/IXUrlParser.cpp b/ixwebsocket/IXUrlParser.cpp index 6e8ba750..6967be89 100644 --- a/ixwebsocket/IXUrlParser.cpp +++ b/ixwebsocket/IXUrlParser.cpp @@ -1,4 +1,29 @@ /* + * Lightweight URL & URI parser (RFC 1738, RFC 3986) + * https://github.com/corporateshark/LUrlParser + * + * The MIT License (MIT) + * + * Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * * IXUrlParser.cpp * Author: Benjamin Sergeant * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. @@ -6,7 +31,305 @@ #include "IXUrlParser.h" -#include "LUrlParser.h" +namespace +{ + enum LUrlParserError + { + LUrlParserError_Ok = 0, + LUrlParserError_Uninitialized = 1, + LUrlParserError_NoUrlCharacter = 2, + LUrlParserError_InvalidSchemeName = 3, + LUrlParserError_NoDoubleSlash = 4, + LUrlParserError_NoAtSign = 5, + LUrlParserError_UnexpectedEndOfLine = 6, + LUrlParserError_NoSlash = 7, + }; + + class clParseURL + { + public: + LUrlParserError m_ErrorCode; + std::string m_Scheme; + std::string m_Host; + std::string m_Port; + std::string m_Path; + std::string m_Query; + std::string m_Fragment; + std::string m_UserName; + std::string m_Password; + + clParseURL() + : m_ErrorCode(LUrlParserError_Uninitialized) + { + } + + /// return 'true' if the parsing was successful + bool IsValid() const + { + return m_ErrorCode == LUrlParserError_Ok; + } + + /// helper to convert the port number to int, return 'true' if the port is valid (within the + /// 0..65535 range) + bool GetPort(int* OutPort) const; + + /// parse the URL + static clParseURL ParseURL(const std::string& URL); + + private: + explicit clParseURL(LUrlParserError ErrorCode) + : m_ErrorCode(ErrorCode) + { + } + }; + + static bool IsSchemeValid(const std::string& SchemeName) + { + for (auto c : SchemeName) + { + if (!isalpha(c) && c != '+' && c != '-' && c != '.') return false; + } + + return true; + } + + bool clParseURL::GetPort(int* OutPort) const + { + if (!IsValid()) + { + return false; + } + + int Port = atoi(m_Port.c_str()); + + if (Port <= 0 || Port > 65535) + { + return false; + } + + if (OutPort) + { + *OutPort = Port; + } + + return true; + } + + // based on RFC 1738 and RFC 3986 + clParseURL clParseURL::ParseURL(const std::string& URL) + { + clParseURL Result; + + const char* CurrentString = URL.c_str(); + + /* + * : + * := [a-z\+\-\.]+ + * For resiliency, programs interpreting URLs should treat upper case letters as equivalent to + *lower case in scheme names + */ + + // try to read scheme + { + const char* LocalString = strchr(CurrentString, ':'); + + if (!LocalString) + { + return clParseURL(LUrlParserError_NoUrlCharacter); + } + + // save the scheme name + Result.m_Scheme = std::string(CurrentString, LocalString - CurrentString); + + if (!IsSchemeValid(Result.m_Scheme)) + { + return clParseURL(LUrlParserError_InvalidSchemeName); + } + + // scheme should be lowercase + std::transform( + Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower); + + // skip ':' + CurrentString = LocalString + 1; + } + + /* + * //:@:/ + * any ":", "@" and "/" must be normalized + */ + + // skip "//" + if (*CurrentString++ != '/') return clParseURL(LUrlParserError_NoDoubleSlash); + if (*CurrentString++ != '/') return clParseURL(LUrlParserError_NoDoubleSlash); + + // check if the user name and password are specified + bool bHasUserName = false; + + const char* LocalString = CurrentString; + + while (*LocalString) + { + if (*LocalString == '@') + { + // user name and password are specified + bHasUserName = true; + break; + } + else if (*LocalString == '/') + { + // end of : specification + bHasUserName = false; + break; + } + + LocalString++; + } + + // user name and password + LocalString = CurrentString; + + if (bHasUserName) + { + // read user name + while (*LocalString && *LocalString != ':' && *LocalString != '@') + LocalString++; + + Result.m_UserName = std::string(CurrentString, LocalString - CurrentString); + + // proceed with the current pointer + CurrentString = LocalString; + + if (*CurrentString == ':') + { + // skip ':' + CurrentString++; + + // read password + LocalString = CurrentString; + + while (*LocalString && *LocalString != '@') + LocalString++; + + Result.m_Password = std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + } + + // skip '@' + if (*CurrentString != '@') + { + return clParseURL(LUrlParserError_NoAtSign); + } + + CurrentString++; + } + + bool bHasBracket = (*CurrentString == '['); + + // go ahead, read the host name + LocalString = CurrentString; + + while (*LocalString) + { + if (bHasBracket && *LocalString == ']') + { + // end of IPv6 address + LocalString++; + break; + } + else if (!bHasBracket && (*LocalString == ':' || *LocalString == '/')) + { + // port number is specified + break; + } + + LocalString++; + } + + Result.m_Host = std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + + // is port number specified? + if (*CurrentString == ':') + { + CurrentString++; + + // read port number + LocalString = CurrentString; + + while (*LocalString && *LocalString != '/') + LocalString++; + + Result.m_Port = std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + } + + // end of string + if (!*CurrentString) + { + Result.m_ErrorCode = LUrlParserError_Ok; + + return Result; + } + + // skip '/' + if (*CurrentString != '/') + { + return clParseURL(LUrlParserError_NoSlash); + } + + CurrentString++; + + // parse the path + LocalString = CurrentString; + + while (*LocalString && *LocalString != '#' && *LocalString != '?') + LocalString++; + + Result.m_Path = std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + + // check for query + if (*CurrentString == '?') + { + // skip '?' + CurrentString++; + + // read query + LocalString = CurrentString; + + while (*LocalString && *LocalString != '#') + LocalString++; + + Result.m_Query = std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + } + + // check for fragment + if (*CurrentString == '#') + { + // skip '#' + CurrentString++; + + // read fragment + LocalString = CurrentString; + + while (*LocalString) + LocalString++; + + Result.m_Fragment = std::string(CurrentString, LocalString - CurrentString); + } + + Result.m_ErrorCode = LUrlParserError_Ok; + + return Result; + } +} namespace ix { @@ -17,7 +340,7 @@ namespace ix std::string& query, int& port) { - LUrlParser::clParseURL res = LUrlParser::clParseURL::ParseURL(url); + clParseURL res = clParseURL::ParseURL(url); if (!res.IsValid()) { diff --git a/ixwebsocket/LUrlParser.cpp b/ixwebsocket/LUrlParser.cpp deleted file mode 100644 index 3589f6cb..00000000 --- a/ixwebsocket/LUrlParser.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Lightweight URL & URI parser (RFC 1738, RFC 3986) - * https://github.com/corporateshark/LUrlParser - * - * The MIT License (MIT) - * - * Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "LUrlParser.h" - -#include -#include -#include - -// check if the scheme name is valid -static bool IsSchemeValid(const std::string& SchemeName) -{ - for (auto c : SchemeName) - { - if (!isalpha(c) && c != '+' && c != '-' && c != '.') return false; - } - - return true; -} - -bool LUrlParser::clParseURL::GetPort(int* OutPort) const -{ - if (!IsValid()) - { - return false; - } - - int Port = atoi(m_Port.c_str()); - - if (Port <= 0 || Port > 65535) - { - return false; - } - - if (OutPort) - { - *OutPort = Port; - } - - return true; -} - -// based on RFC 1738 and RFC 3986 -LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL(const std::string& URL) -{ - LUrlParser::clParseURL Result; - - const char* CurrentString = URL.c_str(); - - /* - * : - * := [a-z\+\-\.]+ - * For resiliency, programs interpreting URLs should treat upper case letters as equivalent to - *lower case in scheme names - */ - - // try to read scheme - { - const char* LocalString = strchr(CurrentString, ':'); - - if (!LocalString) - { - return clParseURL(LUrlParserError_NoUrlCharacter); - } - - // save the scheme name - Result.m_Scheme = std::string(CurrentString, LocalString - CurrentString); - - if (!IsSchemeValid(Result.m_Scheme)) - { - return clParseURL(LUrlParserError_InvalidSchemeName); - } - - // scheme should be lowercase - std::transform( - Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower); - - // skip ':' - CurrentString = LocalString + 1; - } - - /* - * //:@:/ - * any ":", "@" and "/" must be normalized - */ - - // skip "//" - if (*CurrentString++ != '/') return clParseURL(LUrlParserError_NoDoubleSlash); - if (*CurrentString++ != '/') return clParseURL(LUrlParserError_NoDoubleSlash); - - // check if the user name and password are specified - bool bHasUserName = false; - - const char* LocalString = CurrentString; - - while (*LocalString) - { - if (*LocalString == '@') - { - // user name and password are specified - bHasUserName = true; - break; - } - else if (*LocalString == '/') - { - // end of : specification - bHasUserName = false; - break; - } - - LocalString++; - } - - // user name and password - LocalString = CurrentString; - - if (bHasUserName) - { - // read user name - while (*LocalString && *LocalString != ':' && *LocalString != '@') - LocalString++; - - Result.m_UserName = std::string(CurrentString, LocalString - CurrentString); - - // proceed with the current pointer - CurrentString = LocalString; - - if (*CurrentString == ':') - { - // skip ':' - CurrentString++; - - // read password - LocalString = CurrentString; - - while (*LocalString && *LocalString != '@') - LocalString++; - - Result.m_Password = std::string(CurrentString, LocalString - CurrentString); - - CurrentString = LocalString; - } - - // skip '@' - if (*CurrentString != '@') - { - return clParseURL(LUrlParserError_NoAtSign); - } - - CurrentString++; - } - - bool bHasBracket = (*CurrentString == '['); - - // go ahead, read the host name - LocalString = CurrentString; - - while (*LocalString) - { - if (bHasBracket && *LocalString == ']') - { - // end of IPv6 address - LocalString++; - break; - } - else if (!bHasBracket && (*LocalString == ':' || *LocalString == '/')) - { - // port number is specified - break; - } - - LocalString++; - } - - Result.m_Host = std::string(CurrentString, LocalString - CurrentString); - - CurrentString = LocalString; - - // is port number specified? - if (*CurrentString == ':') - { - CurrentString++; - - // read port number - LocalString = CurrentString; - - while (*LocalString && *LocalString != '/') - LocalString++; - - Result.m_Port = std::string(CurrentString, LocalString - CurrentString); - - CurrentString = LocalString; - } - - // end of string - if (!*CurrentString) - { - Result.m_ErrorCode = LUrlParserError_Ok; - - return Result; - } - - // skip '/' - if (*CurrentString != '/') - { - return clParseURL(LUrlParserError_NoSlash); - } - - CurrentString++; - - // parse the path - LocalString = CurrentString; - - while (*LocalString && *LocalString != '#' && *LocalString != '?') - LocalString++; - - Result.m_Path = std::string(CurrentString, LocalString - CurrentString); - - CurrentString = LocalString; - - // check for query - if (*CurrentString == '?') - { - // skip '?' - CurrentString++; - - // read query - LocalString = CurrentString; - - while (*LocalString && *LocalString != '#') - LocalString++; - - Result.m_Query = std::string(CurrentString, LocalString - CurrentString); - - CurrentString = LocalString; - } - - // check for fragment - if (*CurrentString == '#') - { - // skip '#' - CurrentString++; - - // read fragment - LocalString = CurrentString; - - while (*LocalString) - LocalString++; - - Result.m_Fragment = std::string(CurrentString, LocalString - CurrentString); - } - - Result.m_ErrorCode = LUrlParserError_Ok; - - return Result; -} diff --git a/ixwebsocket/LUrlParser.h b/ixwebsocket/LUrlParser.h deleted file mode 100644 index 0298ceb2..00000000 --- a/ixwebsocket/LUrlParser.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Lightweight URL & URI parser (RFC 1738, RFC 3986) - * https://github.com/corporateshark/LUrlParser - * - * The MIT License (MIT) - * - * Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include - -namespace LUrlParser -{ - enum LUrlParserError - { - LUrlParserError_Ok = 0, - LUrlParserError_Uninitialized = 1, - LUrlParserError_NoUrlCharacter = 2, - LUrlParserError_InvalidSchemeName = 3, - LUrlParserError_NoDoubleSlash = 4, - LUrlParserError_NoAtSign = 5, - LUrlParserError_UnexpectedEndOfLine = 6, - LUrlParserError_NoSlash = 7, - }; - - class clParseURL - { - public: - LUrlParserError m_ErrorCode; - std::string m_Scheme; - std::string m_Host; - std::string m_Port; - std::string m_Path; - std::string m_Query; - std::string m_Fragment; - std::string m_UserName; - std::string m_Password; - - clParseURL() - : m_ErrorCode(LUrlParserError_Uninitialized) - { - } - - /// return 'true' if the parsing was successful - bool IsValid() const - { - return m_ErrorCode == LUrlParserError_Ok; - } - - /// helper to convert the port number to int, return 'true' if the port is valid (within the - /// 0..65535 range) - bool GetPort(int* OutPort) const; - - /// parse the URL - static clParseURL ParseURL(const std::string& URL); - - private: - explicit clParseURL(LUrlParserError ErrorCode) - : m_ErrorCode(ErrorCode) - { - } - }; - -} // namespace LUrlParser diff --git a/test/IXUnityBuildsTest.cpp b/test/IXUnityBuildsTest.cpp index f501b8d4..1236ce1a 100644 --- a/test/IXUnityBuildsTest.cpp +++ b/test/IXUnityBuildsTest.cpp @@ -17,6 +17,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -26,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -37,7 +41,6 @@ #include #include #include -#include using namespace ix;