// This code uses code from the Meatloaf Project: // Meatloaf - A Commodore 64/128 multi-device emulator // https://github.com/idolpx/meatloaf // Copyright(C) 2020 James Johnston // // Meatloaf is free software : you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Meatloaf 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Meatloaf. If not, see . #include "peoples_url_parser.h" #include #include #include #include "../../include/debug.h" #include "string_utils.h" void PeoplesUrlParser::processHostPort(std::string hostPort) { auto byColon = mstr::split(hostPort,':',2); host = byColon[0]; if(byColon.size()>1) { port = byColon[1]; } } void PeoplesUrlParser::processAuthorityPath(std::string authorityPath) { // /path // authority:80/path // authority:100 // authority auto bySlash = mstr::split(authorityPath,'/',2); processHostPort(bySlash[0]); if(bySlash.size()>1) { // hasPath path = bySlash[1]; } } void PeoplesUrlParser::processUserPass(std::string userPass) { // user:pass auto byColon = mstr::split(userPass,':',2); if(byColon.size()==1) { user = byColon[0]; } else { user = byColon[0]; password = byColon[1]; } } void PeoplesUrlParser::processAuthority(std::string pastTheColon) { // //user:password@/path // //user:password@host:80/path // // host:100 // // host:30/path auto byAtSign = mstr::split(pastTheColon,'@', 2); if(byAtSign.size()==1) { // just address, port, path processAuthorityPath(mstr::drop(byAtSign[0],2)); } else { // user:password processUserPass(mstr::drop(byAtSign[0],2)); // address, port, path processAuthorityPath(byAtSign[1]); } } void PeoplesUrlParser::cleanPath() { if(path.size() == 0) return; while(mstr::endsWith(path,"/")) { path=mstr::dropLast(path, 1); } mstr::replaceAll(path, "//", "/"); } void PeoplesUrlParser::processPath() { if(path.size() == 0) return; auto pathParts = mstr::split(path, '/'); auto queryParts = mstr::split(*(--pathParts.end()), '?'); auto fragmentParts = mstr::split(*(--queryParts.end()), '#'); // path if(pathParts.size() > 1) name = *(--pathParts.end()); else name = path; // filename if(queryParts.size() > 1) name = queryParts.front(); auto nameParts = mstr::split(name, '.'); // base name if(nameParts.size() > 1) base_name = nameParts.front(); // extension if(nameParts.size() > 1) extension = *(--nameParts.end()); // query if(queryParts.size() > 1) query = *(fragmentParts.begin()); // fragment if(fragmentParts.size() > 1) fragment = *(--fragmentParts.end()); } std::string PeoplesUrlParser::pathToFile(void) { if (name.size() > 0) return path.substr(0, path.size() - name.size() - 1); else return path; } std::string PeoplesUrlParser::root(void) { // set root URL std::string root; if ( scheme.size() ) root = scheme + ":"; if ( host.size() ) root += "//"; if ( user.size() ) { root += user; if ( password.size() ) root += ':' + password; root += '@'; } root += host; if ( port.size() ) root += ':' + port; //Debug_printv("root[%s]", root.c_str()); return root; } std::string PeoplesUrlParser::base(void) { // set base URL //Debug_printv("base[%s]", (root() + "/" + path).c_str()); if ( !mstr::startsWith(path, "/") ) path = "/" + path; cleanPath(); return root() + pathToFile() ; } uint16_t PeoplesUrlParser::getPort() { return std::stoi(port); } PeoplesUrlParser* PeoplesUrlParser::parseURL(const std::string &u) { PeoplesUrlParser *url = new PeoplesUrlParser; url->resetURL(u); return url; } void PeoplesUrlParser::resetURL(const std::string u) { if ( u.empty() ) return; //Debug_printv("u[%s]", u.c_str()); url = u; //Debug_printv("Before [%s]", url.c_str()); auto byColon = mstr::split(url, ':', 2); scheme = ""; path = ""; user = ""; password = ""; host = ""; port = ""; if(byColon.size()==1) { // no scheme, good old local path path = byColon[0]; } else { scheme = byColon[0]; auto pastTheColon = byColon[1]; // don't visualise! if(pastTheColon[0]=='/' && pastTheColon[1]=='/') { // //user:pass@/path // //user:pass@authority:80/path // //authority:100 // //authority:30/path processAuthority(pastTheColon); } else { // we have just a plain old path // /path // user@server // etc. path = pastTheColon; } } // Clean things up before exiting cleanPath(); processPath(); rebuildURL(); //dump(); return; } std::string PeoplesUrlParser::rebuildURL(void) { // set full URL if ( !mstr::startsWith(path, "/") ) path = "/" + path; cleanPath(); url = root() + path; //Debug_printv("url[%s]", url.c_str()); // url += name; // Debug_printv("url[%s]", url.c_str()); // if ( query.size() ) // url += '?' + query; // if ( fragment.size() ) // url += '#' + fragment; return url; } // void dump() { // printf("scheme: %s\r\n", scheme.c_str()); // printf("user pass: %s -- %s\r\n", user.c_str(), pass.c_str()); // printf("host port: %s -- %s\r\n", host.c_str(), port.c_str()); // printf("path: %s\r\n", path.c_str()); // printf("name: %s\r\n", name.c_str()); // printf("extension: %s\r\n", extension.c_str()); // printf("root: %s\r\n", root().c_str()); // printf("base: %s\r\n", base().c_str()); // printf("pathToFile: %s\r\n", pathToFile().c_str()); // }