/* This file is part of libravatarserv. * Copyright © 2018 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 #include #include #include #include "libravatarserv.hpp" using std::cout; using std::cerr; using std::endl; using namespace image; const Image image::get(const string &digest, const uint16_t size) { uint8_t error = 0; Magick::Image img; fs::path filename; const auto &entry = hash::table.find(digest); if (entry == hash::table.end()) { filename = settings::avatar_dir / "default"; if (!fs::is_regular_file(filename)) { cerr << "Warning: User not found and no default image set.\n"; return { 2, img }; } } else { filename = settings::avatar_dir / entry->second; } try { img.read(filename); img.resize(Magick::Geometry(size, size)); } catch (const Magick::Exception &e) { cerr << "Error: " << e.what() << endl; error = 2; } catch (const std::exception &e) { cerr << "Error: " << e.what() << endl; error = 5; } return { error, img }; } void image::write(Image &image) { string magick = image.image.magick(); std::transform(magick.begin(), magick.end(), magick.begin(), ::tolower); cout << "Content-Type: image/" << magick << endl << endl; cout.flush(); // We need to flush before we use /dev/stdout directly. image.image.write("/dev/stdout"); } Image image::identicon(const string &digest) { const string sha256 = hash::sha256(digest); Magick::Image img(Magick::Geometry(4, 4), Magick::Color("white")); // The 16 named colors specified in HTML 4.01 minus white, silver and gray. const std::array colors = { Magick::Color("black"), Magick::Color("red"), Magick::Color("maroon"), Magick::Color("yellow"), Magick::Color("olive"), Magick::Color("lime"), Magick::Color("green"), Magick::Color("aqua"), Magick::Color("teal"), Magick::Color("blue"), Magick::Color("navy"), Magick::Color("fuchsia"), Magick::Color("purple") }; try { std::uint64_t random = 0xffffffffffffffff; for (uint64_t chunk = 0; chunk < 4; ++chunk) { std::stringstream ss; ss << std::hex << sha256.substr(chunk * 16, 16); random = (random / 2) + (static_cast(ss.get()) / 2); } Magick::Color dotcolor = colors[random % 13]; for (uint8_t row = 0; row < 4; ++row) { for (uint8_t column = 0; column < 4; ++column) { std::stringstream ss; uint16_t px; ss << std::hex << sha256.substr(row * 4 + column, 4); ss >> px; if (px > 0x8000) { img.pixelColor(column, row, dotcolor); } } } } catch (const std::exception &e) { cerr << "Error: " << e.what() << endl; return { 5, img }; } img.magick("png"); return { 0, img }; }