1 /*
2  * Copyright (C) 2003-2007  Justin Karneges <justin@affinix.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
17  *
18  */
19 
20 #pragma once
21 
22 #include "gpgproc.h"
23 #include "qpipe.h"
24 #include "sprocess.h"
25 #include <QObject>
26 
27 namespace gpgQCAPlugin {
28 
29 class QProcessSignalRelay : public QObject
30 {
31     Q_OBJECT
32 public:
33     QProcessSignalRelay(QProcess *proc, QObject *parent = nullptr)
QObject(parent)34         : QObject(parent)
35     {
36         qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
37         connect(proc, &QProcess::started, this, &QProcessSignalRelay::proc_started, Qt::QueuedConnection);
38         connect(proc,
39                 &QProcess::readyReadStandardOutput,
40                 this,
41                 &QProcessSignalRelay::proc_readyReadStandardOutput,
42                 Qt::QueuedConnection);
43         connect(proc,
44                 &QProcess::readyReadStandardError,
45                 this,
46                 &QProcessSignalRelay::proc_readyReadStandardError,
47                 Qt::QueuedConnection);
48         connect(proc, &QProcess::bytesWritten, this, &QProcessSignalRelay::proc_bytesWritten, Qt::QueuedConnection);
49         connect(proc,
50                 QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
51                 this,
52                 &QProcessSignalRelay::proc_finished,
53                 Qt::QueuedConnection);
54         connect(proc, &QProcess::errorOccurred, this, &QProcessSignalRelay::proc_error, Qt::QueuedConnection);
55     }
56 
57 Q_SIGNALS:
58     void started();
59     void readyReadStandardOutput();
60     void readyReadStandardError();
61     void bytesWritten(qint64);
62     void finished(int);
63     void error(QProcess::ProcessError);
64 
65 public Q_SLOTS:
proc_started()66     void proc_started()
67     {
68         emit started();
69     }
70 
proc_readyReadStandardOutput()71     void proc_readyReadStandardOutput()
72     {
73         emit readyReadStandardOutput();
74     }
75 
proc_readyReadStandardError()76     void proc_readyReadStandardError()
77     {
78         emit readyReadStandardError();
79     }
80 
proc_bytesWritten(qint64 x)81     void proc_bytesWritten(qint64 x)
82     {
83         emit bytesWritten(x);
84     }
85 
proc_finished(int x)86     void proc_finished(int x)
87     {
88         emit finished(x);
89     }
90 
proc_error(QProcess::ProcessError x)91     void proc_error(QProcess::ProcessError x)
92     {
93         emit error(x);
94     }
95 };
96 
97 enum ResetMode
98 {
99     ResetSession        = 0,
100     ResetSessionAndData = 1,
101     ResetAll            = 2
102 };
103 
104 class GPGProc::Private : public QObject
105 {
106     Q_OBJECT
107 public:
108     GPGProc *            q;
109     QString              bin;
110     QStringList          args;
111     GPGProc::Mode        mode;
112     SProcess *           proc;
113     QProcessSignalRelay *proc_relay;
114     QCA::QPipe           pipeAux, pipeCommand, pipeStatus;
115     QByteArray           statusBuf;
116     QStringList          statusLines;
117     GPGProc::Error       error;
118     int                  exitCode;
119     QCA::SafeTimer       startTrigger, doneTrigger;
120 
121     QByteArray pre_stdin, pre_aux;
122 #ifdef QPIPE_SECURE
123     QCA::SecureArray pre_command;
124 #else
125     QByteArray pre_command;
126 #endif
127     bool pre_stdin_close, pre_aux_close, pre_command_close;
128 
129     bool       need_status, fin_process, fin_process_success, fin_status;
130     QByteArray leftover_stdout;
131     QByteArray leftover_stderr;
132 
133     Private(GPGProc *_q);
134     ~Private() override;
135     void closePipes();
136     void reset(ResetMode mode);
137     bool setupPipes(bool makeAux);
138     void setupArguments();
139 
140 public Q_SLOTS:
141     void doStart();
142     void aux_written(int x);
143     void aux_error(QCA::QPipeEnd::Error);
144     void command_written(int x);
145     void command_error(QCA::QPipeEnd::Error);
146     void status_read();
147     void status_error(QCA::QPipeEnd::Error e);
148     void proc_started();
149     void proc_readyReadStandardOutput();
150     void proc_readyReadStandardError();
151     void proc_bytesWritten(qint64 lx);
152     void proc_finished(int x);
153     void proc_error(QProcess::ProcessError x);
154     void doTryDone();
155 
156 private:
157     bool readAndProcessStatusData();
158     // return true if there are newly parsed lines available
159     bool processStatusData(const QByteArray &buf);
160 };
161 
162 } // end namespace gpgQCAPlugin
163