1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "publickeydeploymentdialog.h"
#include "remotelinuxtr.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/devicesupport/sshparameters.h>
#include <projectexplorer/devicesupport/sshsettings.h>
#include <utils/filepath.h>
#include <utils/fileutils.h>
#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <utils/theme/theme.h>
#include <QProgressDialog>
using namespace ProjectExplorer;
using namespace Utils;
namespace RemoteLinux::Internal {
class PublicKeyDeploymentDialog : public QProgressDialog
{
public:
PublicKeyDeploymentDialog(const DeviceConstRef &device, const FilePath &publicKeyFileName);
private:
void handleDeploymentDone(const Result<> &result);
Process m_process;
bool m_done = false;
};
PublicKeyDeploymentDialog::PublicKeyDeploymentDialog(const DeviceConstRef &device,
const FilePath &publicKeyFileName)
: QProgressDialog(Core::ICore::dialogParent())
{
setAutoReset(false);
setAutoClose(false);
setMinimumDuration(0);
setMaximum(1);
setLabelText(Tr::tr("Deploying..."));
setValue(0);
connect(this, &PublicKeyDeploymentDialog::canceled, this,
[this] { m_done ? accept() : reject(); });
connect(&m_process, &Process::done, this, [this] {
const bool succeeded = m_process.result() == ProcessResult::FinishedWithSuccess;
Result<> result = ResultOk;
if (!succeeded) {
const QString errorMessage = m_process.exitMessage(
Process::FailureMessageFormat::WithStdErr);
result = ResultError(Utils::joinStrings({Tr::tr("Key deployment failed."),
Utils::trimBack(errorMessage, '\n')}, '\n'));
}
handleDeploymentDone(result);
});
const Result<QByteArray> publicKey = publicKeyFileName.fileContents();
if (!publicKey) {
handleDeploymentDone(ResultError(Tr::tr("Public key error: %1").arg(publicKey.error())));
return;
}
const QString command = "test -d .ssh || mkdir -p ~/.ssh && chmod 0700 .ssh && echo '"
+ QString::fromLocal8Bit(publicKey.value())
+ "' >> .ssh/authorized_keys && chmod 0600 .ssh/authorized_keys";
const SshParameters params = device.sshParameters();
const QString hostKeyCheckingString = params.hostKeyCheckingMode() == SshHostKeyCheckingStrict
? QLatin1String("yes") : QLatin1String("no");
const bool isWindows = HostOsInfo::isWindowsHost()
&& sshSettings().sshFilePath().path().toLower().contains("/system32/");
const bool useTimeout = (params.timeout() != 0) && !isWindows;
CommandLine cmd{sshSettings().sshFilePath()};
QStringList args{"-q",
"-o", "StrictHostKeyChecking=" + hostKeyCheckingString,
"-o", "Port=" + QString::number(params.port())};
if (!params.userName().isEmpty())
args << "-o" << "User=" + params.userName();
args << "-o" << "BatchMode=no";
if (useTimeout)
args << "-o" << "ConnectTimeout=" + QString::number(params.timeout());
args << params.host();
cmd.addArgs(args);
QString execCommandString("exec /bin/sh -c");
ProcessArgs::addArg(&execCommandString, command, OsType::OsTypeLinux);
cmd.addArg(execCommandString);
m_process.setCommand(cmd);
SshParameters::setupSshEnvironment(&m_process);
m_process.start();
}
void PublicKeyDeploymentDialog::handleDeploymentDone(const Result<> &result)
{
QString buttonText = result ? Tr::tr("Deployment finished successfully.") : result.error();
const QString textColor = creatorColor(
result ? Theme::TextColorNormal : Theme::TextColorError).name();
setLabelText(QString::fromLatin1("<font color=\"%1\">%2</font>")
.arg(textColor, buttonText.replace("\n", "<br/>")));
setCancelButtonText(Tr::tr("Close"));
if (!result)
return;
setValue(1);
m_done = true;
}
bool runPublicKeyDeploymentDialog(const DeviceConstRef &device, const FilePath &publicKeyFilePath)
{
FilePath keyPath = publicKeyFilePath;
if (keyPath.isEmpty()) {
const FilePath dir = device.sshParameters().privateKeyFile().parentDir();
keyPath = FileUtils::getOpenFilePath(
Tr::tr("Choose Public Key File"),
dir,
Tr::tr("Public Key Files (*.pub)") + ";;"
+ Core::DocumentManager::allFilesFilterString());
}
if (keyPath.isEmpty())
return false;
PublicKeyDeploymentDialog dialog(device, keyPath);
return dialog.exec() == QDialog::Accepted;
}
} // namespace RemoteLinux::Internal
|