ledag - gemini gtk client
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

113 lines
3.3 KiB

// vim: expandtab:ts=2:sts=2:sw=2
/*
* This file is part of ledag.
*
* ledag 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.
*
* ledag 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 ledag. If not, see <http://www.gnu.org/licenses/>.
*/
#include "url.hpp"
#include <assert.h>
#include <iostream>
#include <regex>
#define URL_PROTOCOL "[[:alnum:]]+:"
#define URL_HOSTNAME "[[:alnum:]]+(\\.[[:alnum:]]+)*"
#define URL_PORT "(:[0-9]+)?"
#define URL_USER "([[:alnum:]]+([[:alnum:]])@)?"
#define URL_PATH "((/[[:alnum:]\\.]*)+)?"
#define URL_REGEX URL_PROTOCOL "//" URL_USER URL_HOSTNAME URL_PORT URL_PATH
URL::URL(std::string url) : raw(url)
{
const std::regex url_pattern(URL_REGEX, std::regex::extended);
if (!std::regex_match(raw, url_pattern)) {
throw std::invalid_argument("url is not a URL pattern");
}
// The tmp string will be used to split the url
// into the separated parts of the URL.
std::string tmp(raw);
// Split and remove protocol
std::string token;
std::string delimiter("://");
std::string::size_type pos_of_delimiter;
pos_of_delimiter = tmp.find(delimiter);
token = tmp.substr(0, pos_of_delimiter);
tmp.erase(0, pos_of_delimiter + delimiter.length());
proto = token;
// Find host-path delimiter
delimiter = "/";
pos_of_delimiter = tmp.find(delimiter);
token = tmp.substr(0, pos_of_delimiter);
tmp.erase(0, pos_of_delimiter + delimiter.length());
host = token;
// find user in host-part.
delimiter = "@";
pos_of_delimiter = host.find(delimiter);
if (pos_of_delimiter != std::string::npos) {
token = host.substr(0, pos_of_delimiter);
host.erase(0, pos_of_delimiter + delimiter.length());
user = token;
}
// find the last occurrence of :
// save the port behind : and remove from hostname
delimiter = ":";
pos_of_delimiter = host.rfind(delimiter);
if (pos_of_delimiter != std::string::npos) {
port = host.substr(pos_of_delimiter + 1, host.length());
host.erase(pos_of_delimiter, host.length());
}
// Split path
std::regex word_regex("[^\\s/]+");
auto words_begin = std::sregex_iterator(tmp.begin(), tmp.end(), word_regex);
auto words_end = std::sregex_iterator();
for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
std::smatch match = *i;
std::string match_str = match.str();
paths.push_back(match_str);
}
}
std::string
URL::url()
{
std::string u;
u.append(proto);
u.append("://");
if (!user.empty()) {
u.append(user);
u.append("@");
}
u.append(host);
if (!port.empty()) {
u.append(":");
u.append(port);
}
for (unsigned i = 0; i < paths.size(); i++) {
u.append("/");
u.append(paths[i]);
}
return u;
}