added web interface to retroshare-gui

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@8165 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
electron128 2015-04-24 14:31:13 +00:00
parent 1b0f59d746
commit 127c104e5e
16 changed files with 362 additions and 13 deletions

View File

@ -7,7 +7,7 @@ SUBDIRS += \
supportlibs/pegmarkdown/pegmarkdown.pro \ supportlibs/pegmarkdown/pegmarkdown.pro \
libbitdht/src/libbitdht.pro \ libbitdht/src/libbitdht.pro \
libretroshare/src/libretroshare.pro \ libretroshare/src/libretroshare.pro \
retroshare-gui/src/retroshare-gui.pro \
libresapi/src/libresapi.pro \ libresapi/src/libresapi.pro \
retroshare-gui/src/retroshare-gui.pro \
retroshare-nogui/src/retroshare-nogui.pro \ retroshare-nogui/src/retroshare-nogui.pro \
plugins/plugins.pro plugins/plugins.pro

View File

@ -8,6 +8,9 @@
// for filestreamer // for filestreamer
#include <retroshare/rsfiles.h> #include <retroshare/rsfiles.h>
// to determine default docroot
#include <retroshare/rsinit.h>
#include "JsonStream.h" #include "JsonStream.h"
#include "ApiServer.h" #include "ApiServer.h"
@ -58,6 +61,11 @@ struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
namespace resource_api{ namespace resource_api{
std::string getDefaultDocroot()
{
return RsAccounts::DataDirectory() + "/webui";
}
const char* API_ENTRY_PATH = "/api/v2"; const char* API_ENTRY_PATH = "/api/v2";
const char* FILESTREAMER_ENTRY_PATH = "/fstream/"; const char* FILESTREAMER_ENTRY_PATH = "/fstream/";
const char* STATIC_FILES_ENTRY_PATH = "/static/"; const char* STATIC_FILES_ENTRY_PATH = "/static/";
@ -509,11 +517,9 @@ int ApiServerMHD::accessHandlerCallback(MHD_Connection *connection,
FILE* fd = fopen(filename.c_str(), "rb"); FILE* fd = fopen(filename.c_str(), "rb");
if(fd == 0) if(fd == 0)
{ {
const char *error = "<html><body><p>Error: can't open the requested file.</p></body></html>"; #warning sending untrusted string to the browser
struct MHD_Response* resp = MHD_create_response_from_data(strlen(error), (void*)error, 0, 1); std::string msg = "<html><body><p>Error: can't open the requested file. Path is &quot;"+filename+"&quot;</p></body></html>";
MHD_add_response_header(resp, "Content-Type", "text/html"); sendMessage(connection, MHD_HTTP_NOT_FOUND, msg);
secure_queue_response(connection, MHD_HTTP_NOT_FOUND, resp);
MHD_destroy_response(resp);
return MHD_YES; return MHD_YES;
} }

View File

@ -14,6 +14,10 @@
namespace resource_api{ namespace resource_api{
class ApiServer; class ApiServer;
// returns the default docroot path
// (it is differen on different operating systems)
std::string getDefaultDocroot();
class ApiServerMHD class ApiServerMHD
{ {
public: public:

View File

@ -132,7 +132,7 @@ namespace RsAccounts
{ {
// Directories. // Directories.
std::string ConfigDirectory(); // aka Base Directory. (normally ~/.retroshare) std::string ConfigDirectory(); // aka Base Directory. (normally ~/.retroshare)
std::string DataDirectory(); std::string DataDirectory(); // you can call this method even before initialisation (you can't with the other methods)
std::string PGPDirectory(); std::string PGPDirectory();
std::string AccountDirectory(); std::string AccountDirectory();

View File

@ -717,7 +717,7 @@ static bool checkAccount(std::string accountdir, AccountDetails &account,std::ma
//#include <CFBundle.h> //#include <CFBundle.h>
#endif #endif
std::string RsAccountsDetail::PathDataDirectory() /*static*/ std::string RsAccountsDetail::PathDataDirectory()
{ {
std::string dataDirectory; std::string dataDirectory;
@ -1227,7 +1227,7 @@ bool RsInit::LoadPassword(const std::string& id, const std::string& inPwd)
// Directories. // Directories.
std::string RsAccounts::ConfigDirectory() { return rsAccounts->PathBaseDirectory(); } std::string RsAccounts::ConfigDirectory() { return rsAccounts->PathBaseDirectory(); }
std::string RsAccounts::DataDirectory() { return rsAccounts->PathDataDirectory(); } std::string RsAccounts::DataDirectory() { return RsAccountsDetail::PathDataDirectory(); }
std::string RsAccounts::PGPDirectory() { return rsAccounts->PathPGPDirectory(); } std::string RsAccounts::PGPDirectory() { return rsAccounts->PathPGPDirectory(); }
std::string RsAccounts::AccountDirectory() { return rsAccounts->PathAccountDirectory(); } std::string RsAccounts::AccountDirectory() { return rsAccounts->PathAccountDirectory(); }

View File

@ -73,7 +73,7 @@ class RsAccountsDetail
void unlockPreferredAccount(); void unlockPreferredAccount();
// Paths. // Paths.
std::string PathDataDirectory(); static std::string PathDataDirectory();
std::string PathBaseDirectory(); std::string PathBaseDirectory();
// PGP Path is only dependent on BaseDirectory. // PGP Path is only dependent on BaseDirectory.

View File

@ -719,5 +719,6 @@
<file>images/btn_red.png</file> <file>images/btn_red.png</file>
<file>images/view-feeds.png</file> <file>images/view-feeds.png</file>
<file>images/view-files.png</file> <file>images/view-files.png</file>
<file>images/emblem-web.png</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,136 @@
#include "WebuiPage.h"
#include <iostream>
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
#include "api/ApiServer.h"
#include "api/ApiServerMHD.h"
#include "api/RsControlModule.h"
#include "api/GetPluginInterfaces.h"
#include "rsharesettings.h"
resource_api::ApiServer* WebuiPage::apiServer = 0;
resource_api::ApiServerMHD* WebuiPage::apiServerMHD = 0;
resource_api::RsControlModule* WebuiPage::controlModule = 0;
WebuiPage::WebuiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/)
{
ui.setupUi(this);
connect(ui.enableWebUI_CB, SIGNAL(clicked(bool)), this, SLOT(onEnableCBClicked(bool)));
connect(ui.applyStartBrowser_PB, SIGNAL(clicked()), this, SLOT(onApplyClicked()));
}
WebuiPage::~WebuiPage()
{
}
bool WebuiPage::save(QString &errmsg)
{
std::cerr << "WebuiPage::save()" << std::endl;
bool ok = true;
bool changed = false;
if(ui.enableWebUI_CB->isChecked() != Settings->getWebinterfaceEnabled())
changed = true;
if(ui.port_SB->value() != Settings->getWebinterfacePort())
changed = true;
if(ui.allIp_CB->isChecked() != Settings->getWebinterfaceAllowAllIps())
changed = true;
if(changed)
{
// store config
Settings->setWebinterfaceEnabled(ui.enableWebUI_CB->isChecked());
Settings->setWebinterfacePort(ui.port_SB->value());
Settings->setWebinterfaceAllowAllIps(ui.allIp_CB->isChecked());
// apply config
checkShutdownWebui();
ok = checkStartWebui();
}
if(!ok)
errmsg = "Could not start webinterface.";
return ok;
}
void WebuiPage::load()
{
std::cerr << "WebuiPage::load()" << std::endl;
ui.enableWebUI_CB->setChecked(Settings->getWebinterfaceEnabled());
onEnableCBClicked(Settings->getWebinterfaceEnabled());
ui.port_SB->setValue(Settings->getWebinterfacePort());
ui.allIp_CB->setChecked(Settings->getWebinterfaceAllowAllIps());
}
QString WebuiPage::helpText() const
{
return tr("<h1><img width=\"24\" src=\":/images/64px_help.png\">&nbsp;&nbsp;Webinterface</h1> \
<p>The webinterface allows to control Retroshare from the browser. Multiple devices can share control over one Retroshare instance. So you could start a conversation on a tablet omputer and later use a desktop computer to continue it.</p>\
<p>Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.</p>");
}
/*static*/ bool WebuiPage::checkStartWebui()
{
if(!Settings->getWebinterfaceEnabled())
return true;
if(apiServer || apiServerMHD || controlModule)
return true;
apiServer = new resource_api::ApiServer();
controlModule = new resource_api::RsControlModule(0, 0, apiServer->getStateTokenServer(), apiServer, false);
apiServer->addResourceHandler("control", dynamic_cast<resource_api::ResourceRouter*>(controlModule), &resource_api::RsControlModule::handleRequest);
RsPlugInInterfaces ifaces;
resource_api::getPluginInterfaces(ifaces);
apiServer->loadMainModules(ifaces);
apiServerMHD = new resource_api::ApiServerMHD(apiServer);
bool ok = apiServerMHD->configure(resource_api::getDefaultDocroot(),
Settings->getWebinterfacePort(),
"",
Settings->getWebinterfaceAllowAllIps());
apiServerMHD->start();
return ok;
}
/*static*/ void WebuiPage::checkShutdownWebui()
{
if(apiServer || apiServerMHD)
{
apiServerMHD->stop();
delete apiServerMHD;
apiServerMHD = 0;
delete apiServer;
apiServer = 0;
delete controlModule;
controlModule = 0;
}
}
void WebuiPage::onEnableCBClicked(bool checked)
{
if(checked)
{
ui.params_GB->setEnabled(true);
ui.applyStartBrowser_PB->setEnabled(true);
}
else
{
ui.params_GB->setEnabled(false);
ui.applyStartBrowser_PB->setEnabled(false);
}
}
void WebuiPage::onApplyClicked()
{
QString errmsg;
bool ok = save(errmsg);
if(!ok)
{
QMessageBox::warning(0, tr("failed to start Webinterface"), "Failed to start the webinterface.");
return;
}
QDesktopServices::openUrl(QUrl(QString("http://localhost:")+QString::number(ui.port_SB->value())));
}

View File

@ -0,0 +1,49 @@
#pragma once
#include <retroshare-gui/configpage.h>
#include "ui_WebuiPage.h"
namespace resource_api{
class ApiServer;
class ApiServerMHD;
class RsControlModule;
}
class WebuiPage : public ConfigPage
{
Q_OBJECT
public:
/** Default Constructor */
WebuiPage(QWidget * parent = 0, Qt::WindowFlags flags = 0);
/** Default Destructor */
~WebuiPage();
/** Saves the changes on this page */
virtual bool save(QString &errmsg);
/** Loads the settings for this page */
virtual void load();
virtual QPixmap iconPixmap() const { return QPixmap(":/images/emblem-web.png") ; }
virtual QString pageName() const { return tr("Webinterface") ; }
virtual QString helpText() const;
// call this after start of libretroshare/Retroshare
// checks the settings and starts the webinterface if required
static bool checkStartWebui();
// call this before shutdown of libretroshare
// it stops the webinterface if its running
static void checkShutdownWebui();
public slots:
void onEnableCBClicked(bool checked);
void onApplyClicked();
private:
/** Qt Designer generated object */
Ui::WebuiPage ui;
static resource_api::ApiServer* apiServer;
static resource_api::ApiServerMHD* apiServerMHD;
static resource_api::RsControlModule* controlModule;
};

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WebuiPage</class>
<widget class="QWidget" name="WebuiPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>442</width>
<height>404</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="enableWebUI_CB">
<property name="text">
<string>Enable Retroshare WEB Interface</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="params_GB">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string>Web parameters</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QSpinBox" name="port_SB">
<property name="minimum">
<number>1024</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Port :</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="allIp_CB">
<property name="text">
<string>allow access from all IP adresses (Default: localhost only)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="applyStartBrowser_PB">
<property name="text">
<string>apply setting and start browser</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Note: these settings do not affect retroshare-nogui. retroshare-nogui has a command line switch to active the webinterface.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -41,6 +41,7 @@
#include "PostedPage.h" #include "PostedPage.h"
#include "PluginsPage.h" #include "PluginsPage.h"
#include "ServicePermissionsPage.h" #include "ServicePermissionsPage.h"
#include "WebuiPage.h"
#include "rsharesettings.h" #include "rsharesettings.h"
#include "gui/notifyqt.h" #include "gui/notifyqt.h"
#include "gui/common/FloatingHelpBrowser.h" #include "gui/common/FloatingHelpBrowser.h"
@ -149,6 +150,7 @@ RSettingsWin::initStackedWidget()
addPage(new AppearancePage()); addPage(new AppearancePage());
addPage(new SoundPage() ); addPage(new SoundPage() );
addPage(new ServicePermissionsPage() ); addPage(new ServicePermissionsPage() );
addPage(new WebuiPage() );
// add widgets from plugins // add widgets from plugins

View File

@ -1040,3 +1040,33 @@ void RshareSettings::setMaxTimeBeforeIdle(uint nValue)
m_maxTimeBeforeIdle = nValue; m_maxTimeBeforeIdle = nValue;
setValue("maxTimeBeforeIdle", nValue); setValue("maxTimeBeforeIdle", nValue);
} }
bool RshareSettings::getWebinterfaceEnabled()
{
return valueFromGroup("Webinterface", "enabled", false).toBool();
}
void RshareSettings::setWebinterfaceEnabled(bool enabled)
{
setValueToGroup("Webinterface", "enabled", enabled);
}
uint16_t RshareSettings::getWebinterfacePort()
{
return valueFromGroup("Webinterface", "port", 9090).toUInt();
}
void RshareSettings::setWebinterfacePort(uint16_t port)
{
setValueToGroup("Webinterface", "port", port);
}
bool RshareSettings::getWebinterfaceAllowAllIps()
{
return valueFromGroup("Webinterface", "allowAllIps", false).toBool();
}
void RshareSettings::setWebinterfaceAllowAllIps(bool allow_all)
{
setValueToGroup("Webinterface", "allowAllIps", allow_all);
}

View File

@ -304,6 +304,16 @@ public:
uint getMaxTimeBeforeIdle(); uint getMaxTimeBeforeIdle();
void setMaxTimeBeforeIdle(uint value); void setMaxTimeBeforeIdle(uint value);
// webinterface
bool getWebinterfaceEnabled();
void setWebinterfaceEnabled(bool enabled);
uint16_t getWebinterfacePort();
void setWebinterfacePort(uint16_t port);
bool getWebinterfaceAllowAllIps();
void setWebinterfaceAllowAllIps(bool allow_all);
protected: protected:
/** Default constructor. */ /** Default constructor. */
RshareSettings(); RshareSettings();

View File

@ -46,6 +46,7 @@
#include "gui/NetworkView.h" #include "gui/NetworkView.h"
#include "lang/languagesupport.h" #include "lang/languagesupport.h"
#include "util/RsGxsUpdateBroadcast.h" #include "util/RsGxsUpdateBroadcast.h"
#include "gui/settings/WebuiPage.h"
#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0)
#ifdef WINDOWS_SYS #ifdef WINDOWS_SYS
@ -415,10 +416,14 @@ int main(int argc, char *argv[])
notify->enable() ; // enable notification system after GUI creation, to avoid data races in Qt. notify->enable() ; // enable notification system after GUI creation, to avoid data races in Qt.
WebuiPage::checkStartWebui();
/* dive into the endless loop */ /* dive into the endless loop */
int ti = rshare.exec(); int ti = rshare.exec();
delete w ; delete w ;
WebuiPage::checkShutdownWebui();
if (eventReceiver) { if (eventReceiver) {
/* Destroy event receiver */ /* Destroy event receiver */
delete eventReceiver; delete eventReceiver;

View File

@ -210,6 +210,9 @@ win32 {
DEPENDPATH += . DEPENDPATH += .
INCLUDEPATH += . INCLUDEPATH += .
DEPENDPATH += $$LIBS_DIR/include
INCLUDEPATH += $$LIBS_DIR/include
greaterThan(QT_MAJOR_VERSION, 4) { greaterThan(QT_MAJOR_VERSION, 4) {
# Qt 5 # Qt 5
RC_INCLUDEPATH += $$_PRO_FILE_PWD_/../../libretroshare/src RC_INCLUDEPATH += $$_PRO_FILE_PWD_/../../libretroshare/src
@ -304,6 +307,12 @@ win32 {
DEPENDPATH += . ../../libretroshare/src/ DEPENDPATH += . ../../libretroshare/src/
INCLUDEPATH += ../../libretroshare/src/ INCLUDEPATH += ../../libretroshare/src/
# webinterface
DEPENDPATH += ../../libresapi/src
INCLUDEPATH += ../../libresapi/src
PRE_TARGETDEPS *= ../../libresapi/src/lib/libresapi.a
LIBS += ../../libresapi/src/lib/libresapi.a -lmicrohttpd
# Input # Input
HEADERS += rshare.h \ HEADERS += rshare.h \
retroshare-gui/configpage.h \ retroshare-gui/configpage.h \
@ -530,6 +539,7 @@ HEADERS += rshare.h \
gui/statistics/BwCtrlWindow.h \ gui/statistics/BwCtrlWindow.h \
gui/statistics/RttStatistics.h \ gui/statistics/RttStatistics.h \
gui/statistics/OutQueueStatistics.h \ gui/statistics/OutQueueStatistics.h \
gui/settings/WebuiPage.h
# gui/ForumsDialog.h \ # gui/ForumsDialog.h \
# gui/forums/ForumDetails.h \ # gui/forums/ForumDetails.h \
@ -642,6 +652,7 @@ FORMS += gui/StartDialog.ui \
gui/statistics/BwCtrlWindow.ui \ gui/statistics/BwCtrlWindow.ui \
gui/statistics/RttStatistics.ui \ gui/statistics/RttStatistics.ui \
gui/GetStartedDialog.ui \ gui/GetStartedDialog.ui \
gui/settings/WebuiPage.ui
# gui/ForumsDialog.ui \ # gui/ForumsDialog.ui \
# gui/forums/CreateForum.ui \ # gui/forums/CreateForum.ui \
@ -865,6 +876,7 @@ SOURCES += main.cpp \
gui/statistics/StatisticsWindow.cpp \ gui/statistics/StatisticsWindow.cpp \
gui/statistics/BwCtrlWindow.cpp \ gui/statistics/BwCtrlWindow.cpp \
gui/statistics/RttStatistics.cpp \ gui/statistics/RttStatistics.cpp \
gui/settings/WebuiPage.cpp
# gui/ForumsDialog.cpp \ # gui/ForumsDialog.cpp \
# gui/forums/ForumDetails.cpp \ # gui/forums/ForumDetails.cpp \