diff --git a/libretroshare/src/retroshare/rsinit.h b/libretroshare/src/retroshare/rsinit.h
index c071d4caf..a7cb95b22 100644
--- a/libretroshare/src/retroshare/rsinit.h
+++ b/libretroshare/src/retroshare/rsinit.h
@@ -127,8 +127,9 @@ class RsInit
static std::string RsConfigDirectory();
static std::string RsConfigKeysDirectory();
- static std::string RsProfileConfigDirectory();
- static bool setStartMinimised() ;
+ static std::string RsProfileConfigDirectory();
+ static bool getStartMinimised() ;
+ static std::string getRetroShareLink();
static int getSslPwdLen();
static bool getAutoLogin();
diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc
index f924e8605..4cb8df716 100644
--- a/libretroshare/src/rsserver/rsinit.cc
+++ b/libretroshare/src/rsserver/rsinit.cc
@@ -127,6 +127,8 @@ class RsInitConfig
static std::string load_trustedpeer_file;
static bool udpListenerOnly;
+
+ static std::string RetroShareLink;
};
@@ -160,6 +162,7 @@ std::string RsInitConfig::passwd;
bool RsInitConfig::autoLogin; /* autoLogin allowed */
bool RsInitConfig::startMinimised; /* Icon or Full Window */
+std::string RsInitConfig::RetroShareLink;
/* Win/Unix Differences */
char RsInitConfig::dirSeperator;
@@ -396,7 +399,7 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
/* getopt info: every availiable option is listed here. if it is followed by a ':' it
needs an argument. If it is followed by a '::' the argument is optional.
*/
- while((c = getopt(argc, argv,"hesamui:p:c:w:l:d:U:")) != -1)
+ while((c = getopt(argc, argv,"hesamui:p:c:w:l:d:U:r:")) != -1)
{
switch (c)
{
@@ -466,6 +469,11 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
std::cerr << "Opt for User Id ";
std::cerr << std::endl;
break;
+ case 'r':
+ RsInitConfig::RetroShareLink = optarg;
+ std::cerr << "Opt for RetroShare link";
+ std::cerr << std::endl;
+ break;
case 'h':
std::cerr << "Help: " << std::endl;
std::cerr << "The commandline options are for retroshare-nogui, a headless server in a shell, or systems without QT." << std::endl << std::endl;
@@ -481,14 +489,15 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
std::cerr << "-u Only listen to UDP" << std::endl;
std::cerr << "-e Use a forwarded external Port" << std::endl ;
std::cerr << "-U [User Name/GPG id/SSL id] Sets Account to Use, Useful when Autologin is enabled." << std::endl;
+ std::cerr << "-r link Use RetroShare link." << std::endl;
exit(1);
break;
default:
- if (strictCheck) {
+ if (strictCheck) {
std::cerr << "Unknown Option!" << std::endl;
std::cerr << "Use '-h' for help." << std::endl;
exit(1);
- }
+ }
}
}
@@ -1657,11 +1666,16 @@ std::string RsInit::RsProfileConfigDirectory()
return dir;
}
-bool RsInit::setStartMinimised()
+bool RsInit::getStartMinimised()
{
return RsInitConfig::startMinimised;
}
+std::string RsInit::getRetroShareLink()
+{
+ return RsInitConfig::RetroShareLink;
+}
+
int RsInit::getSslPwdLen(){
return SSLPWD_LEN;
}
diff --git a/retroshare-gui/src/RetroShare.pro b/retroshare-gui/src/RetroShare.pro
index 1f47e1316..058f0d815 100644
--- a/retroshare-gui/src/RetroShare.pro
+++ b/retroshare-gui/src/RetroShare.pro
@@ -246,6 +246,7 @@ HEADERS += rshare.h \
util/PixmapMerging.h \
util/MouseEventFilter.h \
util/EventFilter.h \
+ util/EventReceiver.h \
util/Widget.h \
util/rsversion.h \
util/RsAction.h \
@@ -475,6 +476,7 @@ SOURCES += main.cpp \
util/PixmapMerging.cpp \
util/MouseEventFilter.cpp \
util/EventFilter.cpp \
+ util/EventReceiver.cpp \
util/Widget.cpp \
util/RsAction.cpp \
util/rsversion.cpp \
diff --git a/retroshare-gui/src/gui/settings/GeneralPage.cpp b/retroshare-gui/src/gui/settings/GeneralPage.cpp
index 81300ed86..ffea345d1 100755
--- a/retroshare-gui/src/gui/settings/GeneralPage.cpp
+++ b/retroshare-gui/src/gui/settings/GeneralPage.cpp
@@ -38,6 +38,7 @@ GeneralPage::GeneralPage(QWidget * parent, Qt::WFlags flags)
#ifndef Q_WS_WIN
ui.chkRunRetroshareAtSystemStartup->setVisible(false);
ui.chkRunRetroshareAtSystemStartupMinimized->setVisible(false);
+ ui.enableRetroShareProtocol->setVisible(false);
#endif
}
@@ -55,6 +56,10 @@ bool GeneralPage::save(QString &errmsg)
#ifdef Q_WS_WIN
Settings->setRunRetroshareOnBoot(ui.chkRunRetroshareAtSystemStartup->isChecked(), ui.chkRunRetroshareAtSystemStartupMinimized->isChecked());
+
+ if (ui.enableRetroShareProtocol->isChecked() != Settings->getRetroShareProtocol()) {
+ Settings->setRetroShareProtocol(ui.enableRetroShareProtocol->isChecked());
+ }
#endif
Settings->setMaxTimeBeforeIdle(ui.spinBox->value());
@@ -71,6 +76,8 @@ void GeneralPage::load()
bool minimized;
ui.chkRunRetroshareAtSystemStartup->setChecked(Settings->runRetroshareOnBoot(minimized));
ui.chkRunRetroshareAtSystemStartupMinimized->setChecked(minimized);
+
+ ui.enableRetroShareProtocol->setChecked(Settings->getRetroShareProtocol());
#endif
ui.checkStartMinimized->setChecked(Settings->getStartMinimized());
diff --git a/retroshare-gui/src/gui/settings/GeneralPage.ui b/retroshare-gui/src/gui/settings/GeneralPage.ui
index 87abfdac9..2d677f9bc 100755
--- a/retroshare-gui/src/gui/settings/GeneralPage.ui
+++ b/retroshare-gui/src/gui/settings/GeneralPage.ui
@@ -583,6 +583,13 @@
+ -
+
+
+ Register retroshare:// as url protocol (Restart required)
+
+
+
diff --git a/retroshare-gui/src/gui/settings/rsharesettings.cpp b/retroshare-gui/src/gui/settings/rsharesettings.cpp
index b0131e899..f13f2a182 100644
--- a/retroshare-gui/src/gui/settings/rsharesettings.cpp
+++ b/retroshare-gui/src/gui/settings/rsharesettings.cpp
@@ -37,6 +37,7 @@
#endif // MINIMAL_RSGUI
#include
+#include
#if defined(Q_WS_WIN)
#include
@@ -472,7 +473,56 @@ RshareSettings::setRunRetroshareOnBoot(bool run, bool minimized)
#else
/* Platforms othe rthan windows aren't supported yet */
Q_UNUSED(run);
- return;
+ Q_UNUSED(minimized);
+#endif
+}
+
+static QString getAppPathForProtocol()
+{
+ return "\"" + QDir::convertSeparators(QCoreApplication::applicationFilePath()) + "\" -r \"%1\"";
+}
+
+/** Returns true if retroshare:// is registered as protocol */
+bool RshareSettings::getRetroShareProtocol()
+{
+#if defined(Q_WS_WIN)
+ /* Check key */
+ QSettings retroshare("HKEY_CLASSES_ROOT\\retroshare", QSettings::NativeFormat);
+ if (retroshare.contains("Default")) {
+ /* Check profile */
+ if (retroshare.value("Profile").toString().toStdString() == rsPeers->getOwnId()) {
+ /* Check app path */
+ QSettings command("HKEY_CLASSES_ROOT\\retroshare\\shell\\open\\command", QSettings::NativeFormat);
+ if (command.value("Default").toString() == getAppPathForProtocol()) {
+ return true;
+ }
+ }
+ }
+#else
+ /* Platforms other than windows aren't supported yet */
+ return false;
+#endif
+}
+
+/** Register retroshare:// as protocl */
+void RshareSettings::setRetroShareProtocol(bool value)
+{
+#if defined(Q_WS_WIN)
+ if (value) {
+ QSettings retroshare("HKEY_CLASSES_ROOT\\retroshare", QSettings::NativeFormat);
+ retroshare.setValue("Default", "URL: RetroShare protocol");
+ retroshare.setValue("URL Protocol", "");
+ retroshare.setValue("Profile", QString::fromStdString(rsPeers->getOwnId()));
+
+ QSettings command("HKEY_CLASSES_ROOT\\retroshare\\shell\\open\\command", QSettings::NativeFormat);
+ command.setValue("Default", getAppPathForProtocol());
+ } else {
+ QSettings retroshare("HKEY_CLASSES_ROOT", QSettings::NativeFormat);
+ retroshare.remove("retroshare");
+ }
+#else
+ /* Platforms othe rthan windows aren't supported yet */
+ Q_UNUSED(value);
#endif
}
diff --git a/retroshare-gui/src/gui/settings/rsharesettings.h b/retroshare-gui/src/gui/settings/rsharesettings.h
index be103d4c7..a6bc6393b 100644
--- a/retroshare-gui/src/gui/settings/rsharesettings.h
+++ b/retroshare-gui/src/gui/settings/rsharesettings.h
@@ -109,6 +109,11 @@ public:
/** Set whether to run RetroShare on system boot. */
void setRunRetroshareOnBoot(bool run, bool minimized);
+ /** Returns true if retroshare:// is registered as protocol */
+ bool getRetroShareProtocol();
+ /** Register retroshare:// as protocl */
+ void setRetroShareProtocol(bool value);
+
/* Get the destination log file. */
QString getLogFile();
/** Set the destination log file. */
diff --git a/retroshare-gui/src/lang/retroshare_de.qm b/retroshare-gui/src/lang/retroshare_de.qm
index 2609f8a54..00654f76f 100644
Binary files a/retroshare-gui/src/lang/retroshare_de.qm and b/retroshare-gui/src/lang/retroshare_de.qm differ
diff --git a/retroshare-gui/src/lang/retroshare_de.ts b/retroshare-gui/src/lang/retroshare_de.ts
index 65d988133..ca36a9cea 100644
--- a/retroshare-gui/src/lang/retroshare_de.ts
+++ b/retroshare-gui/src/lang/retroshare_de.ts
@@ -4320,12 +4320,12 @@ Gib Dein GPG Passwort wenn Du gefragt wirst ein, um Deinen neuen Schlüssel zu u
Nicht in den Systemabschnitt minimieren
-
+
seconds
Sekunden
-
+
Start minimized
Minimiert starten
@@ -4335,7 +4335,12 @@ Gib Dein GPG Passwort wenn Du gefragt wirst ein, um Deinen neuen Schlüssel zu u
Starte RetroShare mit dem System
-
+
+ Register retroshare:// as url protocol (Restart required)
+ Registriere retroshare:// als Protokoll (Neustart erforderlich)
+
+
+
Idle
Untätig
@@ -8828,19 +8833,19 @@ p, li { white-space: pre-wrap; }
QObject
-
-
+
+
RetroShare
RetroShare
-
+
Inititialize failed. Wrong or missing installation of gpg.
Initialisierung fehlgeschlagen. GPG fehlt oder es ist eine falsche Version installiert.
-
+
An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.
Ein unerwarteter Fehler ist aufgetreten. Bitte melde 'RsInit::InitRetroShare unexpected return code %1'.
@@ -8971,6 +8976,16 @@ Lockdatei:
Peer details
Nachbar Details
+
+
+ No running instance of RetroShare found.
+ Kein laufendes RetroShare gefunden.
+
+
+
+ Start with a RetroShare link is only supported for Windows.
+ Der Start mit einem RetroShare Link wird nur unter Windows unterstützt.
+
QuickStartWizard
@@ -11073,7 +11088,7 @@ p, li { white-space: pre-wrap; }
Definiere Farben
-
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp
index 66dd28926..4d1b6f1c5 100644
--- a/retroshare-gui/src/main.cpp
+++ b/retroshare-gui/src/main.cpp
@@ -42,6 +42,7 @@
#include "gui/connect/ConfCertDialog.h"
#include "idle/idle.h"
#include "gui/common/Emoticons.h"
+#include "util/EventReceiver.h"
/*** WINDOWS DON'T LIKE THIS - REDEFINES VER numbers.
#include
@@ -107,6 +108,14 @@ int main(int argc, char *argv[])
Rshare rshare(args, argc, argv,
QString::fromStdString(RsInit::RsConfigDirectory()));
+ std::string link = RsInit::getRetroShareLink();
+ if (!link.empty()) {
+ /* start with RetroShare link */
+ EventReceiver eventReceiver;
+ eventReceiver.sendRetroShareLink(QString::fromStdString(link));
+ return 0;
+ }
+
QSplashScreen splashScreen(QPixmap(":/images/splash.png")/* , Qt::WindowStaysOnTopHint*/);
switch (initResult) {
@@ -229,6 +238,15 @@ int main(int argc, char *argv[])
MainWindow *w = MainWindow::Create ();
splashScreen.finish(w);
+ EventReceiver *eventReceiver = NULL;
+ if (Settings->getRetroShareProtocol()) {
+ /* Create event receiver */
+ eventReceiver = new EventReceiver;
+ if (eventReceiver->start()) {
+ QObject::connect(eventReceiver, SIGNAL(linkReceived(const QUrl&)), w, SLOT(linkActivated(const QUrl&)));
+ }
+ }
+
// I'm using a signal to transfer the hashing info to the mainwindow, because Qt schedules signals properly to
// avoid clashes between infos from threads.
//
@@ -268,7 +286,7 @@ int main(int argc, char *argv[])
w->installGroupChatNotifier();
/* only show window, if not startMinimized */
- if (RsInit::setStartMinimised() || Settings->getStartMinimized())
+ if (RsInit::getStartMinimised() || Settings->getStartMinimized())
{
splashScreen.close();
} else {
@@ -286,6 +304,12 @@ int main(int argc, char *argv[])
#ifndef MINIMAL_RSGUI
delete w ;
+ if (eventReceiver) {
+ /* Destroy event receiver */
+ delete eventReceiver;
+ eventReceiver = NULL;
+ }
+
/* cleanup */
PopupChatDialog::cleanupChat();
#endif // MINIMAL_RSGUI
diff --git a/retroshare-gui/src/util/EventReceiver.cpp b/retroshare-gui/src/util/EventReceiver.cpp
new file mode 100644
index 000000000..225ca32c5
--- /dev/null
+++ b/retroshare-gui/src/util/EventReceiver.cpp
@@ -0,0 +1,178 @@
+/****************************************************************
+ * RetroShare is distributed under the following license:
+ *
+ * Copyright (C) 2006, 2007 crypton
+ *
+ * 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; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ****************************************************************/
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include "EventReceiver.h"
+#include "gui/RetroShareLink.h"
+
+#ifdef WINDOWS_SYS
+#include
+#define OP_RETROSHARELINK 12000
+#endif
+
+struct SharedMemoryInfo
+{
+#ifdef WINDOWS_SYS
+ /* Store handle of the event window */
+ WId wid;
+#else
+ long dummy;
+#endif
+};
+
+EventReceiver::EventReceiver()
+{
+#ifdef WINDOWS_SYS
+ setWindowTitle("RetroShare EventReceiver");
+#endif
+
+ /* Build unique name for the running instance */
+ QString name = QString("RetroShare-%1::EventReceiver").arg(QCoreApplication::applicationDirPath());
+ sharedMMemory.setKey(name);
+}
+
+EventReceiver::~EventReceiver()
+{
+ sharedMMemory.detach();
+}
+
+bool EventReceiver::start()
+{
+ if (!sharedMMemory.create(sizeof(SharedMemoryInfo))) {
+ std::cerr << "EventReceiver::start() Cannot create shared memory !" << sharedMMemory.errorString().toStdString() << std::endl;
+ return false;
+ }
+
+ bool result = true;
+
+ if (sharedMMemory.lock()) {
+ SharedMemoryInfo *info = (SharedMemoryInfo*) sharedMMemory.data();
+ if (info) {
+#ifdef WINDOWS_SYS
+ info->wid = winId();
+#else
+ info->dummy = 0;
+#endif
+ } else {
+ result = false;
+ std::cerr << "EventReceiver::start() Shared memory returns a NULL pointer!" << std::endl;
+ }
+
+ sharedMMemory.unlock();
+ } else {
+ result = false;
+ std::cerr << "EventReceiver::start() Cannot lock shared memory !" << std::endl;
+ }
+
+ return result;
+}
+
+void EventReceiver::showNoRunningInstanceFound()
+{
+ QMessageBox mb(QMessageBox::Critical, "RetroShare", QObject::tr("No running instance of RetroShare found."), QMessageBox::Ok);
+ mb.setWindowIcon(QIcon(":/images/rstray3.png"));
+ mb.exec();
+}
+
+bool EventReceiver::sendRetroShareLink(const QString& link)
+{
+ if (!sharedMMemory.attach()) {
+ /* No running instance found */
+ showNoRunningInstanceFound();
+ return false;
+ }
+
+ bool result = true;
+
+ if (sharedMMemory.lock()) {
+ SharedMemoryInfo *info = (SharedMemoryInfo*) sharedMMemory.data();
+ if (info) {
+#ifdef WINDOWS_SYS
+ if (info->wid) {
+ QByteArray linkData = link.toAscii();
+
+ COPYDATASTRUCT send;
+ send.cbData = (link.length() + 1) * sizeof(char);
+ send.dwData = OP_RETROSHARELINK;
+ send.lpData = (void*) linkData.constData();
+
+ SendMessage((HWND) info->wid, WM_COPYDATA, (WPARAM) 0, (LPARAM) (PCOPYDATASTRUCT) &send);
+ } else {
+ showNoRunningInstanceFound();
+ result = false;
+ }
+#else
+ QMessageBox mb(QMessageBox::Critical, "RetroShare", QObject::tr("Start with a RetroShare link is only supported for Windows."), QMessageBox::Ok);
+ mb.setWindowIcon(QIcon(":/images/rstray3.png"));
+ mb.exec();
+
+ result = false;
+#endif
+ } else {
+ result = false;
+ std::cerr << "EventReceiver::sendRetroShareLink() Cannot lock shared memory !" << std::endl;
+ }
+
+ sharedMMemory.unlock();
+ } else {
+ result = false;
+ std::cerr << "EventReceiver::start() Cannot lock shared memory !" << std::endl;
+ }
+
+ sharedMMemory.detach();
+
+ return result;
+}
+
+#ifdef WINDOWS_SYS
+bool EventReceiver::winEvent(MSG* message, long* result)
+{
+ if (message->message == WM_COPYDATA ) {
+ /* Extract the struct from lParam */
+ COPYDATASTRUCT *data = (COPYDATASTRUCT*) message->lParam;
+
+ if (data && data->dwData == OP_RETROSHARELINK) {
+ received(QString::fromAscii((const char*) data->lpData, data->cbData));
+
+ /* Keep the event from Qt */
+ *result = 0;
+ return true;
+ }
+ }
+
+ /* Give the event to Qt */
+ return false;
+}
+#endif
+
+void EventReceiver::received(const QString &url)
+{
+ RetroShareLink link(url);
+ if (link.valid()) {
+ emit linkReceived(link.toUrl());
+ }
+}
diff --git a/retroshare-gui/src/util/EventReceiver.h b/retroshare-gui/src/util/EventReceiver.h
new file mode 100644
index 000000000..410abba7a
--- /dev/null
+++ b/retroshare-gui/src/util/EventReceiver.h
@@ -0,0 +1,61 @@
+/****************************************************************
+ * RetroShare is distributed under the following license:
+ *
+ * Copyright (C) 2006,2007 crypton
+ *
+ * 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; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ****************************************************************/
+
+#ifndef _EVENTRECEIVER_H
+#define _EVENTRECEIVER_H
+
+#include
+#include
+
+class QUrl;
+
+class EventReceiver : public
+#ifdef WINDOWS_SYS
+ QWidget
+#else
+ QObject
+#endif
+{
+ Q_OBJECT
+
+public:
+ EventReceiver();
+ ~EventReceiver();
+
+ bool start();
+ bool sendRetroShareLink(const QString& link);
+
+signals:
+ void linkReceived(const QUrl& url);
+
+private:
+ void showNoRunningInstanceFound();
+ void received(const QString& url);
+
+#ifdef WINDOWS_SYS
+ /* Extend QWidget with a class that will capture the WM_COPYDATA messages */
+ bool winEvent (MSG* message, long* result);
+#endif // WINDOWS_SYS
+
+ QSharedMemory sharedMMemory;
+};
+
+#endif