/* * RetroShare Web User Interface * * Copyright (C) 2019 Cyril Soler * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see * * SPDX-FileCopyrightText: 2004-2019 RetroShare Team * SPDX-License-Identifier: AGPL-3.0-only */ #include "p3webui.h" #include #include #include #include #include #include #include "util/rsthreads.h" #include "util/rsdebug.h" #include "retroshare/rswebui.h" #include "rsserver/rsaccounts.h" #include "retroshare/rsjsonapi.h" #define DEBUG_RS_WEBUI 1 /*extern*/ RsWebUi* rsWebUi = new p3WebUI; enum MimeTypeIndex { TEXT_HTML, TEXT_CSS, TEXT_SVG, TEXT_TTF, TEXT_WOFF, APPLICATION_OCTET_STREAM, }; static const constexpr char* const mime_types[] = { "text/html", "text/css", "image/svg+xml", "font/ttf", "font/woff", "application/octet-stream", }; const std::string RsWebUi::DEFAULT_BASE_DIRECTORY = RsAccountsDetail::PathDataDirectory(false) + "/webui/"; static std::string _base_directory = RsWebUi::DEFAULT_BASE_DIRECTORY; template class handler { public: static void get_handler( const std::shared_ptr< restbed::Session > session ) { const auto request = session->get_request( ); const std::string filename = request->get_path_parameter( "filename" ); std::string directory = request->get_path_parameter( "dir" ); if(!directory.empty()) directory += "/"; std::string resource_filename = _base_directory + "/" + directory + filename; RsDbg() << "Reading file: \"" << resource_filename << "\"" << std::endl; std::ifstream stream( resource_filename, std::ifstream::in ); if(stream.is_open()) { const std::string body = std::string( std::istreambuf_iterator(stream), std::istreambuf_iterator() ); RsDbg() << __PRETTY_FUNCTION__ << " body length=" << body.length() << std::endl; const std::multimap headers { { "Content-Type", mime_types[MIME_TYPE_INDEX] }, { "Content-Length", std::to_string(body.length()) } }; session->close(restbed::OK, body, headers); } else { RsErr() << __PRETTY_FUNCTION__ << "Could not open file: " << resource_filename << std::endl; session->close(restbed::NOT_FOUND); } } }; std::vector< std::shared_ptr > p3WebUI::getResources() const { static std::vector< std::shared_ptr > rtab; if(rtab.empty()) { auto resource1 = std::make_shared< restbed::Resource >(); resource1->set_paths( { "/{filename: index.html}", "/{filename: app.js}", } ); resource1->set_method_handler( "GET", handler::get_handler ); auto resource2 = std::make_shared< restbed::Resource >(); resource2->set_paths( { "/{dir: css}/{filename: fontawesome.css}", "/{dir: css}/{filename: solid.css}", "/{filename: app.css}", } ); resource2->set_method_handler( "GET", handler::get_handler ); auto resource3 = std::make_shared< restbed::Resource >(); resource3->set_paths( { "/{dir: data}/{filename: retroshare.svg}", "/{dir: webfonts}/{filename: fa-solid-900.svg}", } ); resource3->set_method_handler( "GET", handler::get_handler ); auto resource4 = std::make_shared< restbed::Resource >(); resource4->set_paths( { "/{dir: webfonts}/{filename: fa-solid-900.ttf}", } ); resource4->set_method_handler( "GET", handler::get_handler ); auto resource5 = std::make_shared< restbed::Resource >(); resource5->set_paths( { "/{dir: webfonts}/{filename: fa-solid-900.woff}", "/{dir: webfonts}/{filename: fa-solid-900.woff2}", } ); resource5->set_method_handler( "GET", handler::get_handler ); auto resource6 = std::make_shared< restbed::Resource >(); resource6->set_paths( { "/{dir: webfonts}/{filename: fa-solid-900.eot}", } ); resource6->set_method_handler( "GET", handler::get_handler ); rtab.push_back(resource1); rtab.push_back(resource2); rtab.push_back(resource3); rtab.push_back(resource4); rtab.push_back(resource5); rtab.push_back(resource6); } return rtab; } void p3WebUI::setHtmlFilesDirectory(const std::string& html_dir) { _base_directory = html_dir; } bool p3WebUI::isRunning() const { return rsJsonApi->isRunning() && rsJsonApi->hasResourceProvider(*this); } void p3WebUI::setUserPassword(const std::string& passwd) { RsDbg() << __PRETTY_FUNCTION__ << " Updating webui token with new passwd \"" << passwd << "\"" << std::endl; if(!rsJsonApi->authorizeUser("webui",passwd)) std::cerr << "(EE) Cannot register webui token. Some error occurred when calling authorizeUser()" << std::endl; } bool p3WebUI::restart() { rsJsonApi->registerResourceProvider(*this); rsJsonApi->restart(); return true; } bool p3WebUI::stop() { rsJsonApi->unregisterResourceProvider(*this); rsJsonApi->restart(); return true; }