/* 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 "config.hpp" #include "fs-compat.hpp" #include "hash.hpp" #include "helpers.hpp" #include "image.hpp" #include "request.hpp" #include "version.hpp" #include #include #include #include #include #include int main(int /*argc*/, char * /*argv*/[]) { using namespace libravatarserv; std::cout << "Server: libravatarserv/" << version << '\n'; try { const std::string uri{read_env("REQUEST_URI")}; if (uri.empty()) { std::cout << "Status: 400 Bad Request\n\n"; throw std::runtime_error{"REQUEST_URI is empty"}; } auto cfg{config::read()}; auto req{request::parse(uri)}; std::string email{hash::find_email(req, cfg.avatar_dir)}; Magick::Image img; if (!email.empty()) { try { img = image::get(cfg.avatar_dir / email, static_cast(req.size)); } catch (const Magick::Exception &e) { std::cout << "Status: 500 Internal Server Error\n\n"; std::cerr << "ERROR: " << e.what() << '\n'; return 1; } } else { if (cfg.redirect) { std::cout << "Status: 307 Temporary Redirect\n"; std::cout << "Location: https://seccdn.libravatar.org/avatar/" << req.hash << "?s=" << req.size << "&d=" << req.fallback << "\n\n"; return 0; } if (req.fallback.empty()) { req.fallback = cfg.default_fallback; } if (req.fallback == "404") { std::cout << "Status: 404 Not Found\n\n"; return 0; } if (req.fallback == "mp" || req.fallback == "mm") { if (!fs::exists(cfg.avatar_dir / "mp")) { std::cout << "Status: 404 Not Found\n\n"; return 0; } email = "mp"; } else if (req.fallback == "identicon" || req.fallback == "retro") { try { img = image::generate_identicon(req); } catch (const std::exception &e) { std::cout << "Status: 500 Internal Server Error\n\n"; std::cerr << "ERROR: could not generate identicon: " << e.what() << "\n"; return 1; } } else { std::cout << "Status: 501 Not Implemented\n\n"; } } image::write(img); } catch (const std::runtime_error &e) { if (std::strlen(e.what()) != 0) { std::cerr << "ERROR: " << e.what() << '\n'; } return 1; } return 0; }