00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifdef ENABLE_SSH
00016
00017 #include <globalsearch/sshconnection_cli.h>
00018
00019 #include <globalsearch/sshmanager_cli.h>
00020
00021 #include <QtCore/QDebug>
00022 #include <QtCore/QProcess>
00023
00024 namespace GlobalSearch {
00025
00026 SSHConnectionCLI::SSHConnectionCLI(SSHManagerCLI *parent)
00027 : SSHConnection(parent)
00028 {
00029 }
00030
00031 SSHConnectionCLI::~SSHConnectionCLI()
00032 {
00033 }
00034
00035 bool SSHConnectionCLI::execute(const QString &command,
00036 QString &stdout_str,
00037 QString &stderr_str,
00038 int &exitcode)
00039 {
00040 return this->executeSSH(command, QStringList(),
00041 &stdout_str, &stderr_str, &exitcode);
00042 }
00043
00044 bool SSHConnectionCLI::copyFileToServer(const QString &localpath,
00045 const QString &remotepath)
00046 {
00047 return this->executeSCPTo(localpath, remotepath);
00048 }
00049
00050 bool SSHConnectionCLI::copyFileFromServer(const QString &remotepath,
00051 const QString &localpath)
00052 {
00053 return this->executeSCPFrom(remotepath, localpath);
00054 }
00055
00056 bool SSHConnectionCLI::readRemoteFile(const QString &filename,
00057 QString &contents)
00058 {
00059 return this->executeSSH("cat", QStringList(filename), &contents);
00060 }
00061
00062 bool SSHConnectionCLI::removeRemoteFile(const QString &filename)
00063 {
00064 return this->executeSSH("rm", QStringList(filename));
00065 }
00066
00067 bool SSHConnectionCLI::copyDirectoryToServer(const QString &localpath,
00068 const QString &remotepath)
00069 {
00070 return this->executeSCPTo(localpath, remotepath, QStringList("-r"));
00071 }
00072
00073 bool SSHConnectionCLI::copyDirectoryFromServer(const QString &remotepath,
00074 const QString &localpath)
00075 {
00076 return this->executeSCPFrom(remotepath, localpath, QStringList("-r"));
00077 }
00078
00079 bool SSHConnectionCLI::readRemoteDirectoryContents(const QString &remotepath,
00080 QStringList &contents)
00081 {
00082 QString contents_str;
00083
00084 QStringList args;
00085 args << remotepath + "/*" << "|" << "xargs" << "ls" << "-Fd";
00086 if (!this->executeSSH("find", args, &contents_str)) {
00087 return false;
00088 }
00089 contents = contents_str.split("\n", QString::SkipEmptyParts);
00090 return true;
00091 }
00092
00093 bool SSHConnectionCLI::removeRemoteDirectory(const QString &remotepath,
00094 bool onlyDeleteContents)
00095 {
00096 if (remotepath.isEmpty() || remotepath == "/") {
00097 qWarning() << QString("Refusing to remove directory \"%1\".")
00098 .arg(remotepath);
00099 return false;
00100 }
00101
00102 QStringList args ("-rf");
00103
00104 if (onlyDeleteContents)
00105 args << remotepath + "/*";
00106 else
00107 args << remotepath;
00108
00109 return this->executeSSH("rm", args);
00110 }
00111
00112 bool SSHConnectionCLI::executeSSH(const QString &command,
00113 const QStringList &args,
00114 QString *stdout_str,
00115 QString *stderr_str, int *ec)
00116 {
00117 QProcess proc;
00118
00119 QStringList fullArgs;
00120
00121
00122 if (!m_user.isEmpty())
00123 fullArgs << "-l" << m_user;
00124
00125
00126 fullArgs << "-p" << QString::number(m_port);
00127
00128
00129 fullArgs << m_host;
00130
00131
00132 fullArgs << command;
00133 fullArgs << args;
00134
00135 proc.start("ssh", fullArgs);
00136 int timeout_ms = 60000;
00137
00138 if (!proc.waitForStarted(timeout_ms)) {
00139 qWarning() << QString("Failed to start ssh command with args \"%1\" "
00140 "after %2 seconds.")
00141 .arg(fullArgs.join(","))
00142 .arg(timeout_ms / 1000);
00143 return false;
00144 }
00145
00146 proc.closeWriteChannel();
00147 if (!proc.waitForFinished(timeout_ms)) {
00148 qWarning() << QString("ssh command with args \"%1\" failed to finish "
00149 "within %2 seconds.")
00150 .arg(fullArgs.join(","))
00151 .arg(timeout_ms / 1000);
00152 return false;
00153 }
00154
00155 if (proc.exitCode() == 255) {
00156 qWarning() << QString("ssh command with args \"%1\" returned an exit "
00157 "code of 255. This usually means that ssh failed "
00158 "to connect, but it may also be a valid exit code"
00159 " for the command which was run. Assuming that "
00160 "ssh has errored. Contact the development team "
00161 "if you believe this is an error.")
00162 .arg(fullArgs.join(","))
00163 << "\nstdout:\n" << QString(proc.readAllStandardOutput())
00164 << "\nstderr:\n" << QString(proc.readAllStandardError());
00165 return false;
00166 }
00167
00168 if (stdout_str != NULL)
00169 *stdout_str = QString(proc.readAllStandardOutput());
00170 if (stderr_str != NULL)
00171 *stderr_str = QString(proc.readAllStandardError());
00172 if (ec != NULL)
00173 *ec = proc.exitCode();
00174
00175 proc.close();
00176
00177 return true;
00178 }
00179
00180 bool SSHConnectionCLI::executeSCPTo(const QString &source,
00181 const QString &dest,
00182 const QStringList &args,
00183 QString *stdout_str,
00184 QString *stderr_str, int *ec)
00185 {
00186 QProcess proc;
00187
00188
00189 QStringList fullArgs (args);
00190
00191
00192 fullArgs << "-P" << QString::number(m_port);
00193
00194
00195 fullArgs << source;
00196
00197
00198 fullArgs << QString("%1%2%3:%4")
00199 .arg(m_user)
00200 .arg(m_user.isEmpty() ? "" : "@")
00201 .arg(m_host)
00202 .arg(dest);
00203
00204 proc.start("scp", fullArgs);
00205 int timeout_ms = 60000;
00206
00207 if (!proc.waitForStarted(timeout_ms)) {
00208 qWarning() << QString("Failed to start scp command with args \"%1\" "
00209 "after %2 seconds.")
00210 .arg(fullArgs.join(","))
00211 .arg(timeout_ms / 1000);
00212 return false;
00213 }
00214
00215 proc.closeWriteChannel();
00216 if (!proc.waitForFinished(timeout_ms)) {
00217 qWarning() << QString("scp command with args \"%1\" failed to finish "
00218 "within %2 seconds.")
00219 .arg(fullArgs.join(","))
00220 .arg(timeout_ms / 1000);
00221 return false;
00222 }
00223
00224 if (proc.exitCode() != 0) {
00225 qWarning() << QString("scp command with args \"%1\" failed with an exit "
00226 "code of %2.")
00227 .arg(fullArgs.join(","))
00228 .arg(proc.exitCode())
00229 << "\nstdout:\n" << QString(proc.readAllStandardOutput())
00230 << "\nstderr:\n" << QString(proc.readAllStandardError());
00231 return false;
00232 }
00233
00234 if (stdout_str != NULL)
00235 *stdout_str = QString(proc.readAllStandardOutput());
00236 if (stderr_str != NULL)
00237 *stderr_str = QString(proc.readAllStandardError());
00238 if (ec != NULL)
00239 *ec = proc.exitCode();
00240
00241 proc.close();
00242
00243 return true;
00244 }
00245
00246 bool SSHConnectionCLI::executeSCPFrom(const QString &source,
00247 const QString &dest,
00248 const QStringList &args,
00249 QString *stdout_str,
00250 QString *stderr_str, int *ec)
00251 {
00252 QProcess proc;
00253
00254
00255 QStringList fullArgs (args);
00256
00257
00258 fullArgs << "-P" << QString::number(m_port);
00259
00260
00261 fullArgs << QString("%1%2%3:%4")
00262 .arg(m_user)
00263 .arg(m_user.isEmpty() ? "" : "@")
00264 .arg(m_host)
00265 .arg(source);
00266
00267
00268 fullArgs << dest;
00269
00270 proc.start("scp", fullArgs);
00271 int timeout_ms = 60000;
00272
00273 if (!proc.waitForStarted(timeout_ms)) {
00274 qWarning() << QString("Failed to start scp command with args \"%1\" "
00275 "after %2 seconds.")
00276 .arg(fullArgs.join(","))
00277 .arg(timeout_ms / 1000);
00278 return false;
00279 }
00280
00281 proc.closeWriteChannel();
00282 if (!proc.waitForFinished(timeout_ms)) {
00283 qWarning() << QString("scp command with args \"%1\" failed to finish "
00284 "within %2 seconds.")
00285 .arg(fullArgs.join(","))
00286 .arg(timeout_ms / 1000);
00287 return false;
00288 }
00289
00290 if (proc.exitCode() != 0) {
00291 qWarning() << QString("scp command with args \"%1\" failed with an exit "
00292 "code of %2.")
00293 .arg(fullArgs.join(","))
00294 .arg(proc.exitCode())
00295 << "\nstdout:\n" << QString(proc.readAllStandardOutput())
00296 << "\nstderr:\n" << QString(proc.readAllStandardError());
00297 return false;
00298 }
00299
00300 if (stdout_str != NULL)
00301 *stdout_str = QString(proc.readAllStandardOutput());
00302 if (stderr_str != NULL)
00303 *stderr_str = QString(proc.readAllStandardError());
00304 if (ec != NULL)
00305 *ec = proc.exitCode();
00306
00307 proc.close();
00308
00309 return true;
00310 }
00311
00312
00313 }
00314
00315 #endif // ENABLE_SSH