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
|
// 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/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>
using namespace ProjectExplorer;
using namespace Utils;
namespace RemoteLinux::Internal {
class PublicKeyDeploymentDialogPrivate
{
public:
Process m_process;
bool m_done;
};
PublicKeyDeploymentDialog *PublicKeyDeploymentDialog::createDialog(const DeviceConstRef &device)
{
const FilePath dir = device.sshParameters().privateKeyFile.parentDir();
const FilePath publicKeyFileName = FileUtils::getOpenFilePath(
Tr::tr("Choose Public Key File"), dir,
Tr::tr("Public Key Files (*.pub);;All Files (*)"));
if (publicKeyFileName.isEmpty())
return nullptr;
return new PublicKeyDeploymentDialog(device, publicKeyFileName);
}
PublicKeyDeploymentDialog::PublicKeyDeploymentDialog(const DeviceConstRef &device,
const FilePath &publicKeyFileName)
: QProgressDialog(Core::ICore::dialogParent()), d(new PublicKeyDeploymentDialogPrivate)
{
setAutoReset(false);
setAutoClose(false);
setMinimumDuration(0);
setMaximum(1);
d->m_done = false;
setLabelText(Tr::tr("Deploying..."));
setValue(0);
connect(this, &PublicKeyDeploymentDialog::canceled, this,
[this] { d->m_done ? accept() : reject(); });
connect(&d->m_process, &Process::done, this, [this] {
const bool succeeded = d->m_process.result() == ProcessResult::FinishedWithSuccess;
Result result = Result::Ok;
if (!succeeded) {
const QString errorString = d->m_process.errorString();
const QString errorMessage = errorString.isEmpty() ? d->m_process.cleanedStdErr()
: errorString;
result = Result::Error(Utils::joinStrings({Tr::tr("Key deployment failed."),
Utils::trimBack(errorMessage, '\n')}, '\n'));
}
handleDeploymentDone(result);
});
FileReader reader;
if (!reader.fetch(publicKeyFileName)) {
handleDeploymentDone(Result::Error(Tr::tr("Public key error: %1").arg(reader.errorString())));
return;
}
const QString command = "test -d .ssh || mkdir -p ~/.ssh && chmod 0700 .ssh && echo '"
+ QString::fromLocal8Bit(reader.data())
+ "' >> .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().toUrlishString().toLower().contains("/system32/");
const bool useTimeout = (params.timeout != 0) && !isWindows;
Utils::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);
d->m_process.setCommand(cmd);
SshParameters::setupSshEnvironment(&d->m_process);
d->m_process.start();
}
PublicKeyDeploymentDialog::~PublicKeyDeploymentDialog()
{
delete d;
}
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);
d->m_done = true;
}
} // namespace RemoteLinux::Internal
|