/* This file is part of libravatarserv. * Copyright © 2022 tastytea * * This program 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, version 3. * * This program 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 this program. If not, see . */ #include "request.hpp" #include "hash.hpp" #include "types.hpp" #include #include #include #include #include #include namespace libravatarserv::request { request_t parse(const std::string_view uri) { constexpr std::uint8_t offset{8}; if (uri.substr(0, offset) != "/avatar/" || uri.find("..", offset) != std::string_view::npos) { std::cout << "Status: 400 Bad Request\n\n"; throw std::runtime_error{"Invalid URL"}; } request_t req; req.size = 80; size_t pos{uri.find('?')}; if (pos == std::string_view::npos) { pos = uri.size(); } req.hash.resize(pos - offset); std::transform(uri.begin() + offset, uri.begin() + pos, req.hash.begin(), ::tolower); if (req.hash.size() == 64 && hash::is_valid(req.hash)) { req.algo = algorithm_t::SHA256; } else if (req.hash.size() == 32 && hash::is_valid(req.hash)) { req.algo = algorithm_t::MD5; } else { std::cout << "Status: 400 Bad Request\n\n"; throw std::runtime_error{"Invalid hash"}; } if (pos != uri.size()) { std::string uri_rest; uri_rest.resize(uri.size() - pos); std::transform(uri.begin() + pos, uri.end(), uri_rest.begin(), ::tolower); auto strsize{get_parameter(uri_rest, "s")}; if (strsize.empty()) { strsize = get_parameter(uri_rest, "size"); } if (!strsize.empty()) { try { req.size = static_cast(std::stoul(strsize.data())); if (req.size > 512) { req.size = 512; } else if (req.size < 1) { req.size = 80; } } catch (...) {} } req.fallback = get_parameter(uri_rest, "d"); if (req.fallback.empty()) { req.fallback = get_parameter(uri_rest, "default"); } } return req; } std::string_view get_parameter(const std::string_view uri, const std::string ¶meter) { size_t pos{uri.find("?" + parameter + "=")}; if (pos == std::string_view::npos) { pos = uri.find("&" + parameter + "="); } if (pos != std::string_view::npos) { pos += (2 + parameter.length()); return uri.substr(pos, uri.find('&', pos)); } return {}; } } // namespace libravatarserv::request