added certificate generate #4168

This commit is contained in:
XinyuHou 2015-02-11 17:28:56 +00:00
parent 03ee40891e
commit b9c5eb2e6f
16 changed files with 315 additions and 58 deletions

1
.gitignore vendored
View File

@ -13,4 +13,5 @@ config.h
/src/gui/ui_* /src/gui/ui_*
src/gui/gui.pro.user src/gui/gui.pro.user
src/gui/.qmake.stash src/gui/.qmake.stash
src/gui/.rnd
src/setup/win32/synergy.suo src/setup/win32/synergy.suo

View File

@ -17,6 +17,7 @@
#include "PluginManager.h" #include "PluginManager.h"
#include "CommandProcess.h"
#include "DataDownloader.h" #include "DataDownloader.h"
#include "QUtility.h" #include "QUtility.h"
#include "ProcessorArch.h" #include "ProcessorArch.h"
@ -28,6 +29,7 @@
#include <QMessageBox> #include <QMessageBox>
static const char kGetPluginDirArg[] = "--get-plugin-dir"; static const char kGetPluginDirArg[] = "--get-plugin-dir";
static const char kGetProfileDirArg[] = "--get-profile-dir";
static QString kPluginsBaseUrl = "http://synergy-project.org/files/plugins/"; static QString kPluginsBaseUrl = "http://synergy-project.org/files/plugins/";
static const char kWinProcessorArch32[] = "Windows-x86"; static const char kWinProcessorArch32[] = "Windows-x86";
@ -35,8 +37,17 @@ static const char kWinProcessorArch64[] = "Windows-x64";
static const char kMacProcessorArch[] = "MacOSX-i386"; static const char kMacProcessorArch[] = "MacOSX-i386";
static const char kLinuxProcessorArch32[] = "Linux-i686"; static const char kLinuxProcessorArch32[] = "Linux-i686";
static const char kLinuxProcessorArch64[] = "Linux-x86_64"; static const char kLinuxProcessorArch64[] = "Linux-x86_64";
// TODO: use live url
static QString kOpenSSLBaseUrl = "http://ws2/public/openssl/";
static QString kCertificateLifetime = "365";
static QString kCertificateSubjectInfo = "/CN=Synergy";
static QString kCertificateFilename = "Synergy.pem";
static QString kUnixOpenSSLCommand = "openssl";
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
static const char kWinPluginExt[] = ".dll"; static const char kWinPluginExt[] = ".dll";
static const char kWinOpenSSLBinary[] = "openssl.exe";
#elif defined(Q_OS_MAC) #elif defined(Q_OS_MAC)
static const char kMacPluginPrefix[] = "lib"; static const char kMacPluginPrefix[] = "lib";
static const char kMacPluginExt[] = ".dylib"; static const char kMacPluginExt[] = ".dylib";
@ -50,6 +61,17 @@ PluginManager::PluginManager(QStringList pluginList) :
m_DownloadIndex(-1), m_DownloadIndex(-1),
m_pPluginDownloader(NULL) m_pPluginDownloader(NULL)
{ {
QStringList args1(kGetPluginDirArg);
m_PluginDir = getDirViaSyntool(args1);
if (m_PluginDir.isEmpty()) {
emit error(tr("Failed to get plugin directory."));
}
QStringList args2(kGetProfileDirArg);
m_ProfileDir = getDirViaSyntool(args2);
if (m_ProfileDir.isEmpty()) {
emit error(tr("Failed to get profile directory."));
}
} }
PluginManager::~PluginManager() PluginManager::~PluginManager()
@ -77,6 +99,9 @@ void PluginManager::downloadPlugins()
if (m_DownloadIndex < m_PluginList.size()) { if (m_DownloadIndex < m_PluginList.size()) {
QUrl url; QUrl url;
QString pluginUrl = getPluginUrl(m_PluginList.at(m_DownloadIndex)); QString pluginUrl = getPluginUrl(m_PluginList.at(m_DownloadIndex));
if (pluginUrl.isEmpty()) {
return;
}
url.setUrl(pluginUrl); url.setUrl(pluginUrl);
if (m_pPluginDownloader == NULL) { if (m_pPluginDownloader == NULL) {
@ -87,25 +112,64 @@ void PluginManager::downloadPlugins()
} }
} }
void PluginManager::savePlugin() void PluginManager::saveOpenSSLBinary()
{ {
QString pluginDir = getPluginDir(); QDir dir(m_ProfileDir);
if (pluginDir.isEmpty()) { if (!dir.exists()) {
dir.mkpath(".");
}
QString filename = m_ProfileDir;
#if defined(Q_OS_WIN)
filename.append("\\").append(kWinOpenSSLBinary);
#endif
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
emit error(
tr("Failed to download OpenSSl to location: %1")
.arg(m_ProfileDir));
return; return;
} }
QString filename = pluginDir; file.write(m_pPluginDownloader->data());
file.close();
emit openSSLBinaryReady();
}
void PluginManager::generateCertificate()
{
connect(
this,
SIGNAL(openSSLBinaryReady()),
this,
SLOT(doGenerateCertificate()));
downloadOpenSSLBinary();
}
void PluginManager::savePlugin()
{
// create the path if not exist
QDir dir(m_PluginDir);
if (!dir.exists()) {
dir.mkpath(".");
}
QString filename = m_PluginDir;
QString pluginName = m_PluginList.at(m_DownloadIndex); QString pluginName = m_PluginList.at(m_DownloadIndex);
pluginName = getPluginOSSpecificName(pluginName); pluginName = getPluginOSSpecificName(pluginName);
filename.append(QDir::separator()).append(pluginName); filename.append(QDir::separator()).append(pluginName);
QFile file(filename); QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) { if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::warning( emit error(
(QWidget*)parent(), "Synergy",
tr("Failed to download plugin %1 to location: %2") tr("Failed to download plugin %1 to location: %2")
.arg(m_PluginList.at(m_DownloadIndex)) .arg(m_PluginList.at(m_DownloadIndex))
.arg(pluginDir)); .arg(m_PluginDir));
return; return;
} }
@ -114,13 +178,12 @@ void PluginManager::savePlugin()
} }
QString PluginManager::getPluginDir() QString PluginManager::getDirViaSyntool(QStringList& args)
{ {
QString program(QCoreApplication::applicationDirPath() + "/syntool"); QString program(QCoreApplication::applicationDirPath() + "/syntool");
QProcess process; QProcess process;
process.setReadChannel(QProcess::StandardOutput); process.setReadChannel(QProcess::StandardOutput);
QStringList args(kGetPluginDirArg);
process.start(program, args); process.start(program, args);
bool success = process.waitForStarted(); bool success = process.waitForStarted();
@ -143,20 +206,14 @@ QString PluginManager::getPluginDir()
{ {
QMessageBox::critical( QMessageBox::critical(
(QWidget*)parent(), tr("Synergy"), (QWidget*)parent(), tr("Synergy"),
tr("An error occured while trying to get " tr("An error occured while calling syntool "
"plugin directory from syntool. Code: %1\nError: %2") "with the first arg %1. Code: %2\nError: %3")
.arg(args.at(0))
.arg(process.exitCode()) .arg(process.exitCode())
.arg(error.isEmpty() ? "Unknown" : error)); .arg(error.isEmpty() ? "Unknown" : error));
return ""; return "";
} }
// create the path if not exist
// TODO: synergy folder should be hidden
QDir dir(out);
if (!dir.exists()) {
dir.mkpath(".");
}
return out; return out;
} }
@ -182,9 +239,9 @@ QString PluginManager::getPluginUrl(const QString& pluginName)
result.append(kLinuxProcessorArch64); result.append(kLinuxProcessorArch64);
} }
else { else {
QMessageBox::critical( emit error(
(QWidget*)parent(), tr("Synergy"), tr("Failed to get the url of plugin %1 .")
tr("Failed to detect system architecture.")); .arg(pluginName));
return ""; return "";
} }
result.append("/"); result.append("/");
@ -193,6 +250,16 @@ QString PluginManager::getPluginUrl(const QString& pluginName)
return result; return result;
} }
QString PluginManager::getOpenSSLBinaryUrl()
{
QString result;
#if defined(Q_OS_WIN)
result = kOpenSSLBaseUrl.append(kWinOpenSSLBinary);
#endif
return result;
}
QString PluginManager::getPluginOSSpecificName(const QString& pluginName) QString PluginManager::getPluginOSSpecificName(const QString& pluginName)
{ {
QString result = pluginName; QString result = pluginName;
@ -205,3 +272,93 @@ QString PluginManager::getPluginOSSpecificName(const QString& pluginName)
#endif #endif
return result; return result;
} }
bool PluginManager::checkOpenSSLBinary()
{
bool exist = false;
#if defined(Q_OS_WIN)
QString openSSLFilename = m_ProfileDir;
openSSLFilename.append("\\").append(kWinOpenSSLBinary);
QDir dir(openSSLFilename);
if (dir.exists()) {
exist = true;
}
#else
// assume OpenSSL is always installed on both Mac and Linux
exist = true;
#endif
return exist;
}
void PluginManager::downloadOpenSSLBinary()
{
if (checkOpenSSLBinary()) {
emit openSSLBinaryReady();
return;
}
QUrl url;
QString pluginUrl = getOpenSSLBinaryUrl();
url.setUrl(pluginUrl);
disconnect(
m_pPluginDownloader,
SIGNAL(isComplete()),
this,
SLOT(downloadPlugins()));
connect(
m_pPluginDownloader,
SIGNAL(isComplete()),
this,
SLOT(saveOpenSSLBinary()));
m_pPluginDownloader->download(url);
}
void PluginManager::doGenerateCertificate()
{
QString openSSLFilename = m_ProfileDir;
#if defined(Q_OS_WIN)
openSSLFilename.append("\\").append(kWinOpenSSLBinary);
#else
openSSLFilename = kUnixOpenSSLCommand;
#endif
QStringList arguments;
// self signed certificate
arguments.append("req");
arguments.append("-x509");
arguments.append("-nodes");
// valide duration
arguments.append("-days");
arguments.append(kCertificateLifetime);
// subject information
arguments.append("-subj");
QString info(kCertificateSubjectInfo);
arguments.append(info);
// private key
arguments.append("-newkey");
arguments.append("rsa:1024");
// key output filename
arguments.append("-keyout");
QString filename = m_ProfileDir;
filename.append(QDir::separator()).append(kCertificateFilename);
arguments.append(filename);
// certificate output filename
arguments.append("-out");
arguments.append(filename);
// update command and arguments
CommandProcess commandProcess(openSSLFilename, arguments);
commandProcess.run();
emit generateCertificateFinished();
}

View File

@ -36,19 +36,30 @@ public:
public slots: public slots:
void downloadPlugins(); void downloadPlugins();
void saveOpenSSLBinary();
void generateCertificate();
void doGenerateCertificate();
private: private:
void savePlugin(); void savePlugin();
QString getPluginDir(); QString getDirViaSyntool(QStringList& args);
QString getPluginUrl(const QString& pluginName); QString getPluginUrl(const QString& pluginName);
QString getOpenSSLBinaryUrl();
QString getPluginOSSpecificName(const QString& pluginName); QString getPluginOSSpecificName(const QString& pluginName);
bool checkOpenSSLBinary();
void downloadOpenSSLBinary();
signals: signals:
void error(QString e);
void downloadNext(); void downloadNext();
void downloadFinished(); void downloadFinished();
void openSSLBinaryReady();
void generateCertificateFinished();
private: private:
QStringList m_PluginList; QStringList m_PluginList;
QString m_PluginDir;
QString m_ProfileDir;
int m_DownloadIndex; int m_DownloadIndex;
DataDownloader* m_pPluginDownloader; DataDownloader* m_pPluginDownloader;
}; };

View File

@ -43,16 +43,22 @@ void PluginWizardPage::changeEvent(QEvent *e)
} }
} }
void PluginWizardPage::showError(QString error)
{
updateStatus(error);
stopSpinning();
m_Finished = true;
emit completeChanged();
}
void PluginWizardPage::queryPluginDone() void PluginWizardPage::queryPluginDone()
{ {
QStringList pluginList = m_pWebClient->getPluginList(); QStringList pluginList = m_pWebClient->getPluginList();
if (pluginList.isEmpty()) { if (pluginList.isEmpty()) {
if (!m_pWebClient->getLastError().isEmpty()) { updateStatus("No plugin available.");
updateStatus(m_pWebClient->getLastError());
m_Finished = true; m_Finished = true;
emit completeChanged(); emit completeChanged();
} }
}
else { else {
downloadPlugins(); downloadPlugins();
} }
@ -77,6 +83,26 @@ void PluginWizardPage::finished()
emit completeChanged(); emit completeChanged();
} }
void PluginWizardPage::generateCertificate()
{
connect(m_pPluginManager,
SIGNAL(generateCertificateFinished()),
this,
SLOT(finished()));
connect(m_pPluginManager,
SIGNAL(generateCertificateFinished()),
m_pPluginManagerThread,
SLOT(quit()));
updateStatus(tr("Generating certificate..."));
QMetaObject::invokeMethod(
m_pPluginManager,
"generateCertificate",
Qt::QueuedConnection);
}
void PluginWizardPage::updateStatus(QString info) void PluginWizardPage::updateStatus(QString info)
{ {
m_pLabelStatus->setText(info); m_pLabelStatus->setText(info);
@ -86,7 +112,12 @@ void PluginWizardPage::downloadPlugins()
{ {
QStringList pluginList = m_pWebClient->getPluginList(); QStringList pluginList = m_pWebClient->getPluginList();
m_pPluginManager = new PluginManager(pluginList); m_pPluginManager = new PluginManager(pluginList);
QThread* thread = new QThread; m_pPluginManagerThread = new QThread;
connect(m_pPluginManager,
SIGNAL(error(QString)),
this,
SLOT(showError(QString)));
connect(m_pPluginManager, connect(m_pPluginManager,
SIGNAL(downloadNext()), SIGNAL(downloadNext()),
@ -96,16 +127,16 @@ void PluginWizardPage::downloadPlugins()
connect(m_pPluginManager, connect(m_pPluginManager,
SIGNAL(downloadFinished()), SIGNAL(downloadFinished()),
this, this,
SLOT(finished())); SLOT(generateCertificate()));
connect(m_pPluginManager, connect(m_pPluginManager,
SIGNAL(downloadFinished()), SIGNAL(error(QString)),
thread, m_pPluginManagerThread,
SLOT(quit())); SLOT(quit()));
connect(thread, connect(m_pPluginManagerThread,
SIGNAL(finished()), SIGNAL(finished()),
thread, m_pPluginManagerThread,
SLOT(deleteLater())); SLOT(deleteLater()));
updateStatus( updateStatus(
@ -113,7 +144,13 @@ void PluginWizardPage::downloadPlugins()
.arg(pluginList.at(0)) .arg(pluginList.at(0))
.arg(pluginList.size())); .arg(pluginList.size()));
QMetaObject::invokeMethod(m_pPluginManager, "downloadPlugins", Qt::QueuedConnection); m_pPluginManager->moveToThread(m_pPluginManagerThread);
m_pPluginManagerThread->start();
QMetaObject::invokeMethod(
m_pPluginManager,
"downloadPlugins",
Qt::QueuedConnection);
} }
void PluginWizardPage::stopSpinning() void PluginWizardPage::stopSpinning()
@ -147,6 +184,12 @@ void PluginWizardPage::initializePage()
m_pWebClient->setPassword(m_Password); m_pWebClient->setPassword(m_Password);
QThread* thread = new QThread; QThread* thread = new QThread;
connect(m_pWebClient,
SIGNAL(error(QString)),
this,
SLOT(showError(QString)));
connect(m_pWebClient, connect(m_pWebClient,
SIGNAL(queryPluginDone()), SIGNAL(queryPluginDone()),
this, this,
@ -157,6 +200,11 @@ void PluginWizardPage::initializePage()
thread, thread,
SLOT(quit())); SLOT(quit()));
connect(m_pWebClient,
SIGNAL(error(QString)),
thread,
SLOT(quit()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
m_pWebClient->moveToThread(thread); m_pWebClient->moveToThread(thread);

View File

@ -26,9 +26,11 @@ protected:
void changeEvent(QEvent *e); void changeEvent(QEvent *e);
protected slots: protected slots:
void showError(QString error);
void queryPluginDone(); void queryPluginDone();
void updateDownloadStatus(); void updateDownloadStatus();
void finished(); void finished();
void generateCertificate();
private: private:
void updateStatus(QString info); void updateStatus(QString info);
@ -41,5 +43,6 @@ private:
QString m_Password; QString m_Password;
WebClient* m_pWebClient; WebClient* m_pWebClient;
PluginManager* m_pPluginManager; PluginManager* m_pPluginManager;
QThread* m_pPluginManagerThread;
}; };
#endif // PLUGINWIZARDPAGE_H #endif // PLUGINWIZARDPAGE_H

View File

@ -98,10 +98,9 @@ void WebClient::queryPluginList()
} }
catch (std::exception& e) catch (std::exception& e)
{ {
m_Error = tr("An error occured while trying to query the " emit error(tr("An error occured while trying to query the "
"plugin list. Please contact the help desk, and provide " "plugin list. Please contact the help desk, and "
"the following details.\n\n%1").arg(e.what()); "provide the following details.\n\n%1").arg(e.what()));
emit queryPluginDone();
return; return;
} }
@ -113,15 +112,13 @@ void WebClient::queryPluginList()
if (editionRegex.exactMatch(responseJson)) { if (editionRegex.exactMatch(responseJson)) {
QString e = editionRegex.cap(1); QString e = editionRegex.cap(1);
m_PluginList = e.split(","); m_PluginList = e.split(",");
m_Error.clear();
emit queryPluginDone(); emit queryPluginDone();
return; return;
} }
} }
else if (boolString == "false") { else if (boolString == "false") {
m_Error = tr("Get plugin list failed, invalid user email " emit error(tr("Get plugin list failed, invalid user email "
"or password."); "or password."));
emit queryPluginDone();
return; return;
} }
} }
@ -130,17 +127,15 @@ void WebClient::queryPluginList()
if (errorRegex.exactMatch(responseJson)) { if (errorRegex.exactMatch(responseJson)) {
// replace "\n" with real new lines. // replace "\n" with real new lines.
QString error = errorRegex.cap(1).replace("\\n", "\n"); QString e = errorRegex.cap(1).replace("\\n", "\n");
m_Error = tr("Get plugin list failed, an error occurred." emit error(tr("Get plugin list failed, an error occurred."
"\n\n%1").arg(error); "\n\n%1").arg(e));
emit queryPluginDone();
return; return;
} }
} }
m_Error = tr("Get plugin list failed, an error occurred.\n\n" emit error(tr("Get plugin list failed, an error occurred.\n\n"
"Server response:\n\n%1").arg(responseJson); "Server response:\n\n%1").arg(responseJson));
emit queryPluginDone();
return; return;
} }

View File

@ -38,12 +38,12 @@ public:
void setEmail(QString& e) { m_Email = e; } void setEmail(QString& e) { m_Email = e; }
void setPassword(QString& p) { m_Password = p; } void setPassword(QString& p) { m_Password = p; }
QStringList& getPluginList() { return m_PluginList; } QStringList& getPluginList() { return m_PluginList; }
QString& getLastError() { return m_Error; }
public slots: public slots:
void queryPluginList(); void queryPluginList();
signals: signals:
void error(QString e);
void queryPluginDone(); void queryPluginDone();
private: private:
@ -55,7 +55,6 @@ private:
QString m_Email; QString m_Email;
QString m_Password; QString m_Password;
QStringList m_PluginList; QStringList m_PluginList;
QString m_Error;
}; };
#endif // WEBCLIENT_H #endif // WEBCLIENT_H

View File

@ -68,6 +68,12 @@ public:
*/ */
virtual std::string getPluginDirectory() = 0; virtual std::string getPluginDirectory() = 0;
//! Get local profile directory
/*!
Returns the local profile directory.
*/
virtual std::string getProfileDirectory() = 0;
//! Concatenate path components //! Concatenate path components
/*! /*!
Concatenate pathname components with a directory separator Concatenate pathname components with a directory separator

View File

@ -108,9 +108,19 @@ std::string
ArchFileUnix::getPluginDirectory() ArchFileUnix::getPluginDirectory()
{ {
#if WINAPI_XWINDOWS #if WINAPI_XWINDOWS
return getUserDirectory().append("/.synergy/plugins"); return getProfileDirectory().append("/plugins");
#else #else
return getUserDirectory().append("/Libraries/Synergy/Plugins"); return getProfileDirectory().append("/Plugins");
#endif
}
std::string
ArchFileUnix::getProfileDirectory()
{
#if WINAPI_XWINDOWS
return getUserDirectory().append("/.synergy");
#else
return getUserDirectory().append("/Libraries/Synergy");
#endif #endif
} }

View File

@ -35,6 +35,7 @@ public:
virtual std::string getInstalledDirectory(); virtual std::string getInstalledDirectory();
virtual std::string getLogDirectory(); virtual std::string getLogDirectory();
virtual std::string getPluginDirectory(); virtual std::string getPluginDirectory();
virtual std::string getProfileDirectory();
virtual std::string concatPath(const std::string& prefix, virtual std::string concatPath(const std::string& prefix,
const std::string& suffix); const std::string& suffix);
}; };

View File

@ -142,8 +142,24 @@ ArchFileWindows::getLogDirectory()
std::string std::string
ArchFileWindows::getPluginDirectory() ArchFileWindows::getPluginDirectory()
{ {
std::string dir = getUserDirectory(); std::string dir = getProfileDirectory();
dir.append("\\Synergy\\Plugins"); dir.append("\\Plugins");
return dir;
}
std::string
ArchFileWindows::getProfileDirectory()
{
TCHAR result[MAX_PATH];
std::string dir;
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, result))) {
dir = result;
}
else {
dir = getUserDirectory();
}
dir.append("\\Synergy");
return dir; return dir;
} }

View File

@ -35,6 +35,7 @@ public:
virtual std::string getInstalledDirectory(); virtual std::string getInstalledDirectory();
virtual std::string getLogDirectory(); virtual std::string getLogDirectory();
virtual std::string getPluginDirectory(); virtual std::string getPluginDirectory();
virtual std::string getProfileDirectory();
virtual std::string concatPath(const std::string& prefix, virtual std::string concatPath(const std::string& prefix,
const std::string& suffix); const std::string& suffix);
}; };

View File

@ -177,6 +177,10 @@ ArgParser::parseToolArgs(ToolArgs& args, int argc, const char* const* argv)
args.m_getPluginDir = true; args.m_getPluginDir = true;
return true; return true;
} }
if (isArg(i, argc, argv, NULL, "--get-profile-dir", 0)) {
args.m_getProfileDir = true;
return true;
}
else { else {
return false; return false;
} }

View File

@ -76,6 +76,9 @@ ToolApp::run(int argc, char** argv)
else if (m_args.m_getPluginDir) { else if (m_args.m_getPluginDir) {
std::cout << ARCH->getPluginDirectory() << std::endl; std::cout << ARCH->getPluginDirectory() << std::endl;
} }
else if (m_args.m_getProfileDir) {
std::cout << ARCH->getProfileDirectory() << std::endl;
}
else { else {
throw XSynergy("Nothing to do"); throw XSynergy("Nothing to do");
} }

View File

@ -21,6 +21,7 @@ ToolArgs::ToolArgs() :
m_printActiveDesktopName(false), m_printActiveDesktopName(false),
m_loginAuthenticate(false), m_loginAuthenticate(false),
m_getPluginList(false), m_getPluginList(false),
m_getPluginDir(false) m_getPluginDir(false),
m_getProfileDir(false)
{ {
} }

View File

@ -28,4 +28,5 @@ public:
bool m_loginAuthenticate; bool m_loginAuthenticate;
bool m_getPluginList; bool m_getPluginList;
bool m_getPluginDir; bool m_getPluginDir;
bool m_getProfileDir;
}; };