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/gui.pro.user
src/gui/.qmake.stash
src/gui/.rnd
src/setup/win32/synergy.suo

View File

@ -17,6 +17,7 @@
#include "PluginManager.h"
#include "CommandProcess.h"
#include "DataDownloader.h"
#include "QUtility.h"
#include "ProcessorArch.h"
@ -28,6 +29,7 @@
#include <QMessageBox>
static const char kGetPluginDirArg[] = "--get-plugin-dir";
static const char kGetProfileDirArg[] = "--get-profile-dir";
static QString kPluginsBaseUrl = "http://synergy-project.org/files/plugins/";
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 kLinuxProcessorArch32[] = "Linux-i686";
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)
static const char kWinPluginExt[] = ".dll";
static const char kWinOpenSSLBinary[] = "openssl.exe";
#elif defined(Q_OS_MAC)
static const char kMacPluginPrefix[] = "lib";
static const char kMacPluginExt[] = ".dylib";
@ -50,6 +61,17 @@ PluginManager::PluginManager(QStringList pluginList) :
m_DownloadIndex(-1),
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()
@ -77,6 +99,9 @@ void PluginManager::downloadPlugins()
if (m_DownloadIndex < m_PluginList.size()) {
QUrl url;
QString pluginUrl = getPluginUrl(m_PluginList.at(m_DownloadIndex));
if (pluginUrl.isEmpty()) {
return;
}
url.setUrl(pluginUrl);
if (m_pPluginDownloader == NULL) {
@ -87,25 +112,64 @@ void PluginManager::downloadPlugins()
}
}
void PluginManager::savePlugin()
void PluginManager::saveOpenSSLBinary()
{
QString pluginDir = getPluginDir();
if (pluginDir.isEmpty()) {
QDir dir(m_ProfileDir);
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;
}
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);
pluginName = getPluginOSSpecificName(pluginName);
filename.append(QDir::separator()).append(pluginName);
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::warning(
(QWidget*)parent(), "Synergy",
tr("Failed to download plugin %1 to location: %2")
.arg(m_PluginList.at(m_DownloadIndex))
.arg(pluginDir));
emit error(
tr("Failed to download plugin %1 to location: %2")
.arg(m_PluginList.at(m_DownloadIndex))
.arg(m_PluginDir));
return;
}
@ -114,13 +178,12 @@ void PluginManager::savePlugin()
}
QString PluginManager::getPluginDir()
QString PluginManager::getDirViaSyntool(QStringList& args)
{
QString program(QCoreApplication::applicationDirPath() + "/syntool");
QProcess process;
process.setReadChannel(QProcess::StandardOutput);
QStringList args(kGetPluginDirArg);
process.start(program, args);
bool success = process.waitForStarted();
@ -143,20 +206,14 @@ QString PluginManager::getPluginDir()
{
QMessageBox::critical(
(QWidget*)parent(), tr("Synergy"),
tr("An error occured while trying to get "
"plugin directory from syntool. Code: %1\nError: %2")
tr("An error occured while calling syntool "
"with the first arg %1. Code: %2\nError: %3")
.arg(args.at(0))
.arg(process.exitCode())
.arg(error.isEmpty() ? "Unknown" : error));
return "";
}
// create the path if not exist
// TODO: synergy folder should be hidden
QDir dir(out);
if (!dir.exists()) {
dir.mkpath(".");
}
return out;
}
@ -182,9 +239,9 @@ QString PluginManager::getPluginUrl(const QString& pluginName)
result.append(kLinuxProcessorArch64);
}
else {
QMessageBox::critical(
(QWidget*)parent(), tr("Synergy"),
tr("Failed to detect system architecture."));
emit error(
tr("Failed to get the url of plugin %1 .")
.arg(pluginName));
return "";
}
result.append("/");
@ -193,6 +250,16 @@ QString PluginManager::getPluginUrl(const QString& pluginName)
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 result = pluginName;
@ -205,3 +272,93 @@ QString PluginManager::getPluginOSSpecificName(const QString& pluginName)
#endif
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:
void downloadPlugins();
void saveOpenSSLBinary();
void generateCertificate();
void doGenerateCertificate();
private:
void savePlugin();
QString getPluginDir();
QString getDirViaSyntool(QStringList& args);
QString getPluginUrl(const QString& pluginName);
QString getOpenSSLBinaryUrl();
QString getPluginOSSpecificName(const QString& pluginName);
bool checkOpenSSLBinary();
void downloadOpenSSLBinary();
signals:
void error(QString e);
void downloadNext();
void downloadFinished();
void openSSLBinaryReady();
void generateCertificateFinished();
private:
QStringList m_PluginList;
QString m_PluginDir;
QString m_ProfileDir;
int m_DownloadIndex;
DataDownloader* m_pPluginDownloader;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -108,9 +108,19 @@ std::string
ArchFileUnix::getPluginDirectory()
{
#if WINAPI_XWINDOWS
return getUserDirectory().append("/.synergy/plugins");
return getProfileDirectory().append("/plugins");
#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
}

View File

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

View File

@ -142,8 +142,24 @@ ArchFileWindows::getLogDirectory()
std::string
ArchFileWindows::getPluginDirectory()
{
std::string dir = getUserDirectory();
dir.append("\\Synergy\\Plugins");
std::string dir = getProfileDirectory();
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;
}

View File

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

View File

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

View File

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

View File

@ -21,6 +21,7 @@ ToolArgs::ToolArgs() :
m_printActiveDesktopName(false),
m_loginAuthenticate(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_getPluginList;
bool m_getPluginDir;
bool m_getProfileDir;
};