/* This file is part of libravatarserv. * Copyright © 2018,2019 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 #include #include #include "libravatarserv.hpp" using std::cout; using std::cerr; using std::endl; using namespace http; const Request http::parse_request(const string &request) { if (request.substr(0, 8) == "/favicon") { cout << "Status: 404 Not Found\n\n"; std::exit(1); } if (request.substr(0, 8) != "/avatar/" || request.find("..", 8) != std::string::npos) { cout << "Status: 400 Bad Request\n\n"; cerr << "Error: Invalid URL.\n"; std::exit(1); } int16_t size = 80; string fallback; string digest = request.substr(8); std::transform(digest.begin(), digest.end(), digest.begin(), ::tolower); std::size_t pos_digest = digest.find('?'); if (pos_digest != std::string::npos) { string answer; { answer = get_parameter(request, "s"); if (!answer.empty()) { try { size = static_cast(std::stoul(answer)); } catch (const std::exception &) {} } else { answer = get_parameter(request, "size"); if (!answer.empty()) { try { size = static_cast(std::stoul(answer)); } catch (const std::exception &) {} } } if (size > 512) { size = 512; } else if (size <= 0) { size = 80; } } { answer = get_parameter(request, "d"); if (!answer.empty()) { fallback = answer; } else { answer = get_parameter(request, "default"); if (!answer.empty()) { fallback = answer; } } } } digest = digest.substr(0, pos_digest); pos_digest = digest.find('.'); if (pos_digest != std::string::npos) { digest = digest.substr(0, pos_digest); } return { digest, size, fallback }; } const string http::get_parameter(const string &request, const string ¶meter) { std::size_t pos = request.find("&" + parameter + "="); if (pos == std::string::npos) { pos = request.find("?" + parameter + "="); } if (pos != std::string::npos) { pos += (2 + parameter.length()); return request.substr(pos, request.find('&', pos)); } return ""; } void http::send_redirect(const Request &request) { const char *env = std::getenv("HTTPS"); string baseurl; if (env != nullptr && env[1] == 'n') { // "on" baseurl = "https://seccdn.libravatar.org"; } else { baseurl = "http://cdn.libravatar.org"; } cout << "Status: 307 Temporary Redirect\n"; cout << "Location: " << baseurl << "/avatar/" << request.digest << "?s=" << request.size << "&d=" << request.fallback << endl << endl; }