レポジトリ種類: Mercurial
#include <string>
#include <iostream>
#include <filesystem>
#include <fstream>
#include <sstream>
#include "crow.h"
std::string escapeHtml(const std::string &input) {
std::string escaped;
for (char c : input) {
switch (c) {
case '&': escaped += "&"; break;
case '<': escaped += "<"; break;
case '>': escaped += ">"; break;
case '"': escaped += """; break;
case '\'': escaped += "'"; break;
default: escaped += c; break;
}
}
return escaped;
}
std::string generateBreadcrumb(const std::string &urlpath) {
std::stringstream breadcrumb;
breadcrumb << "<nav><ul style=\"display: inline;\">"
"<li style=\"display: inline; margin-right: 8px;\">"
"<a href=\"/\">トップ</a> / </li>";
std::string currentPath = "";
size_t start = 0, end = 0;
while ((end = urlpath.find('/', start)) != std::string::npos) {
std::string part = urlpath.substr(start, end - start);
currentPath += part + "/";
breadcrumb << "<li style=\"display: inline; margin-right: 8px;\">"
<< "<a href=\"/" << currentPath.substr(0, currentPath.size() - 1)
<< "\">"
<< part << "</a> / "
<< "</li>";
start = end + 1;
}
std::string lastPart = urlpath.substr(start);
currentPath += lastPart;
breadcrumb << "<li style=\"display: inline;\">" << lastPart << "</li>";
breadcrumb << "</ul></nav>";
return breadcrumb.str();
}
bool isImage(const std::string &path) {
const std::string extensions[] = {".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp"};
for (const auto &ext : extensions) {
if (path.size() >= ext.size() &&
path.compare(path.size() - ext.size(), ext.size(), ext) == 0) {
return true;
}
}
return false;
}
int main() {
std::string path = "/home/suwako/open-repos/";
std::string repotype = "";
crow::SimpleApp website;
CROW_ROUTE(website, "/")([&]() -> crow::response {
repotype = "";
std::string res = "<html><head><meta content=\"text/html; charset=utf-8\" "
"http-equiv=\"content-type\" />"
"<style>html { color: #fcfcfc; background-color: #232023; } "
"a { color: #ea79d8; }</style>"
"</head><body>";
res += "<h1>/</h1>";
res += "<ul>";
res += "<li><a href=\"/game\">ゲーム</a></li>";
res += "<li><a href=\"/soft\">ソフト</a></li>";
res += "<li><a href=\"/web\">ウェブ</a></li>";
res += "</ul>";
res += "</body></html>";
crow::response out(200, res);
out.add_header("Content-Type", "text/html; charset=utf-8");
return out;
});
CROW_ROUTE(website, "/<path>")([&](const crow::request &req, std::string urlpath)
-> crow::response {
std::string lspath = path + urlpath;
std::cout << "FUCK " << urlpath << std::endl;
if (urlpath == "soft" || urlpath == "game" || urlpath == "web") {
repotype = "";
}
std::string title = "";
std::vector<std::string> ret;
std::string res = "<html><head><meta content=\"text/html; charset=utf-8\" "
"http-equiv=\"content-type\" />"
"<style>html { color: #fcfcfc; background-color: #232023; } "
"a { color: #ea79d8; }</style>"
"</head><body>";
if (lspath.find(".svn") != std::string::npos ||
lspath.find(".git") != std::string::npos ||
lspath.find(".hg") != std::string::npos) {
std::cerr << "アクセス禁止: " << lspath << std::endl;
res += "<p>馬鹿野郎、ここは立入禁止だろう!</p>";
res += "</body></html>";
crow::response out(403, res);
out.add_header("Content-Type", "text/html; charset=utf-8");
return out;
}
try {
if (!std::filesystem::exists(lspath)) {
std::cerr << "見つかりません: " << lspath << std::endl;
res += "<p>見つかりません。</p></body></html>";
crow::response out(404, res);
out.add_header("Content-Type", "text/html; charset=utf-8");
return out;
}
if (std::filesystem::is_regular_file(lspath)) {
if (isImage(lspath)) {
crow::response imageResponse;
std::ifstream file(lspath, std::ios::binary);
if (!file.is_open()) {
std::cerr << "エラー: ファイルを開くに失敗: " << lspath << std::endl;
res += "<p>エラー: ファイルを開くに失敗。</p></body></html>";
crow::response out(500, res);
out.add_header("Content-Type", "text/html; charset=utf-8");
return out;
}
std::ostringstream buffer;
buffer << file.rdbuf();
file.close();
std::string contentType = "image/";
if (lspath.ends_with(".jpg") || lspath.ends_with(".jpeg")) contentType += "jpeg";
else if (lspath.ends_with(".png")) contentType += "png";
else if (lspath.ends_with(".gif")) contentType += "gif";
else if (lspath.ends_with(".bmp")) contentType += "bmp";
else if (lspath.ends_with(".webp")) contentType += "webp";
imageResponse.add_header("Content-Type", contentType);
imageResponse.write(buffer.str());
return imageResponse;
}
std::ifstream file(lspath);
if (!file.is_open()) {
std::cerr << "エラー: ファイルを開くに失敗: " << lspath << std::endl;
res += "<p>エラー: ファイルを開くに失敗。</p></body></html>";
crow::response out(500, res);
out.add_header("Content-Type", "text/html; charset=utf-8");
return out;
}
std::stringstream buffer;
buffer << file.rdbuf();
file.close();
std::string content = escapeHtml(buffer.str());
res += "<h1>" + title + "</h1>";
res += generateBreadcrumb(urlpath);
if (!repotype.empty()) res += "<h2>レポジトリ種類: " + repotype + "</h2>";
res += "<pre><code>" + content + "</code></pre>";
res += "</body></html>";
crow::response out(200, res);
out.add_header("Content-Type", "text/html; charset=utf-8");
return out;
}
if (!lspath.empty() && lspath.back() != '/') lspath += '/';
if (!std::filesystem::exists(lspath)) {
std::cerr << "ディレクトリが見つかりません: " << lspath << std::endl;
res += "<p>ディレクトリが見つかりません。</p></body></html>";
crow::response out(404, res);
out.add_header("Content-Type", "text/html; charset=utf-8");
return out;
}
for (const auto &entry : std::filesystem::directory_iterator(lspath)) {
std::string fullpath = entry.path().string();
std::string showpath = fullpath.substr(lspath.length());
if (showpath == ".hg") {
repotype = "Mercurial";
continue;
}
if (showpath == ".git") {
repotype = "Git";
continue;
}
if (showpath == ".svn") {
repotype = "SVN";
continue;
}
std::string outpath = "<a href=\"/" + urlpath + "/" + showpath + "\">"
+ showpath + "</a>";
ret.push_back(outpath);
}
} catch (const std::filesystem::filesystem_error &e) {
std::cerr << "エラーが発生しました: " << e.what() << std::endl;
res += "<p>エラーが発生しました。</p></body></html>";
crow::response out(500, res);
out.add_header("Content-Type", "text/html; charset=utf-8");
return out;
}
res += "<h1>" + title + "</h1>";
res += generateBreadcrumb(urlpath);
if (!repotype.empty()) res += "<h2>レポジトリ種類: " + repotype + "</h2>";
res += "<ul>";
for (const auto &line : ret) {
res += "<li>" + line + "</li>";
}
res += "</ul>";
res += "</body></html>";
crow::response out(200, res);
out.add_header("Content-Type", "text/html; charset=utf-8");
return out;
});
website.port(8040).run();
}