Quassel IRC  Pre-Release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
execwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2015 by the Quassel Project *
3  * devel@quassel-irc.org *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) version 3. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19  ***************************************************************************/
20 
21 #include <QFile>
22 #include <QTextCodec>
23 
24 #include "execwrapper.h"
25 
26 #include "client.h"
27 #include "messagemodel.h"
28 #include "quassel.h"
29 
30 ExecWrapper::ExecWrapper(QObject *parent) : QObject(parent)
31 {
32  connect(&_process, SIGNAL(readyReadStandardOutput()), SLOT(processReadStdout()));
33  connect(&_process, SIGNAL(readyReadStandardError()), SLOT(processReadStderr()));
34  connect(&_process, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processFinished(int, QProcess::ExitStatus)));
35  connect(&_process, SIGNAL(error(QProcess::ProcessError)), SLOT(processError(QProcess::ProcessError)));
36 
37  connect(this, SIGNAL(output(QString)), SLOT(postStdout(QString)));
38  connect(this, SIGNAL(error(QString)), SLOT(postStderr(QString)));
39 }
40 
41 
42 void ExecWrapper::start(const BufferInfo &info, const QString &command)
43 {
44  _bufferInfo = info;
45  QString params;
46 
47  QRegExp rx("^\\s*(\\S+)(\\s+(.*))?$");
48  if (!rx.exactMatch(command)) {
49  emit error(tr("Invalid command string for /exec: %1").arg(command));
50  }
51  else {
52  _scriptName = rx.cap(1);
53  params = rx.cap(3);
54  }
55 
56  // Make sure we don't execute something outside a script dir
57  if (_scriptName.contains("../") || _scriptName.contains("..\\"))
58  emit error(tr("Name \"%1\" is invalid: ../ or ..\\ are not allowed!").arg(_scriptName));
59 
60  else {
61  foreach(QString scriptDir, Quassel::scriptDirPaths()) {
62  QString fileName = scriptDir + _scriptName;
63  if (!QFile::exists(fileName))
64  continue;
65  _process.setWorkingDirectory(scriptDir);
66  _process.start('"' + fileName + "\" " + params);
67  return;
68  }
69  emit error(tr("Could not find script \"%1\"").arg(_scriptName));
70  }
71 
72  deleteLater(); // self-destruct
73 }
74 
75 
76 void ExecWrapper::postStdout(const QString &msg)
77 {
78  if (_bufferInfo.isValid())
80 }
81 
82 
83 void ExecWrapper::postStderr(const QString &msg)
84 {
85  if (_bufferInfo.isValid())
87 }
88 
89 
90 void ExecWrapper::processFinished(int exitCode, QProcess::ExitStatus status)
91 {
92  if (status == QProcess::CrashExit) {
93  emit error(tr("Script \"%1\" crashed with exit code %2.").arg(_scriptName).arg(exitCode));
94  }
95 
96  // empty buffers
97  if (!_stdoutBuffer.isEmpty())
98  foreach(QString msg, _stdoutBuffer.split('\n'))
99  emit output(msg);
100  if (!_stderrBuffer.isEmpty())
101  foreach(QString msg, _stderrBuffer.split('\n'))
102  emit error(msg);
103 
104  deleteLater();
105 }
106 
107 
108 void ExecWrapper::processError(QProcess::ProcessError err)
109 {
110  if (err == QProcess::FailedToStart)
111  emit error(tr("Script \"%1\" could not start.").arg(_scriptName));
112  else
113  emit error(tr("Script \"%1\" caused error %2.").arg(_scriptName).arg(err));
114 
115  if (_process.state() != QProcess::Running)
116  deleteLater();
117 }
118 
119 
121 {
122  QString str = QTextCodec::codecForLocale()->toUnicode(_process.readAllStandardOutput());
123  str.replace(QRegExp("\r\n?"), "\n");
124  _stdoutBuffer.append(str);
125  int idx;
126  while ((idx = _stdoutBuffer.indexOf('\n')) >= 0) {
127  emit output(_stdoutBuffer.left(idx));
128  _stdoutBuffer = _stdoutBuffer.mid(idx + 1);
129  }
130 }
131 
132 
134 {
135  QString str = QTextCodec::codecForLocale()->toUnicode(_process.readAllStandardError());
136  str.replace(QRegExp("\r\n?"), "\n");
137  _stderrBuffer.append(str);
138  int idx;
139  while ((idx = _stderrBuffer.indexOf('\n')) >= 0) {
140  emit error(_stderrBuffer.left(idx));
141  _stderrBuffer = _stderrBuffer.mid(idx + 1);
142  }
143 }