/* **************************************************************************** * Copyright 2019 Open Systems Development BV * * * * 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. * * ***************************************************************************/ #ifndef OSDEV_COMPONENTS_MQTT_URIPARSER_H #define OSDEV_COMPONENTS_MQTT_URIPARSER_H // std #include #include "commondefs.h" namespace osdev { namespace components { namespace mqtt { /** * @brief Helper class to parse, normalize, and replace the port service name by portnumber in a uri. * example: * opc.tcp://user:secret\@processmodel:processmodel/path1/path2?query3=value4#fragment5 * will result in * opc.tcp://user:secret\@processmodel:12345/path1/path2?query3=value4#fragment5 * @note This assumes that the port service name was registered in the etc/services file under protocol tcp. * Lookup of a portnumber for protocols other than tcp are not supported. * * IPv6 addresses in a uri are only parsable when they are wrapped in brackets ([]) (RFC 3986, section 3.2.2) * * @note This class is designed to handle a subset of all possible uris. The scheme and the authority part are * expected not to be empty. The authority part can contain user and password information. * * @note Only scheme, hostname and port are converted to lowercase (see RFC 3986 6.2.2.1. Case Normalization) * * @note Special characters are escaped with percent encoding. This applies to user, password, path, query and fragment parts. * The path and query part is escaped on a per element basis. This means that ParsedUri contains the raw query and path strings. * The decoding is done when the methods parseQuery and parsePath are called. */ class UriParser { public: /** * @brief Parses the specified uri string. * @param uri The uri string to parse. * @return A map containing the parsed uri. * @note The path and query parts can still contain percent encoded special characters. */ static ParsedUri parse(const std::string& uri); /** * @brief Parse the query part of a parsed uri. Percent encoded special characters are decoded. * @param parsedUri A ParsedUri object. * @return key/value map. */ static ParsedQuery parseQuery(const ParsedUri& parsedUri); /** * @brief Parse the path part of a parsed uri. Percent encoded special characters are decoded. * @param parsedUri A ParsedUri object. * @return vector of path elements. */ static ParsedPath parsePath(const ParsedUri& parsedUri); /** * @brief Parses, normalizes, and replaces the port service name by portnumber in the specified uri string. * @param uri The uri string to parse and normalize. * @return The normalized uri string, with the port service name replaced by the portnumber. */ static std::string normalize(const std::string& uri); /** * @brief Converts a parsed uri back to a string. * @param parsedUri The parsed uri to convert to string. * @return The uri as string. */ static std::string toString(const ParsedUri& parsedUri); /** * @brief Get portnumber associated with a service. * @param serviceName Name of the service for which a portnumber is searched. * @param protocolName Name of the protocol for which the portname was registered. * @return portnumber. * @throws InvalidArgumentException when service is unknown. * @throws SystemException when underlying systemcall fails. */ static int getPortnumber(const std::string& serviceName, const std::string& protocolName = "tcp"); }; } // End namespace mqtt } // End namespace components } // End namespace osdev #endif // OSDEV_COMPONENTS_MQTT_URIPARSER_H