~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to third-party/qca/qca-gnupg/gpgproc/gpgproc.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-04-14 18:57:30 UTC
  • mfrom: (2.1.9 hardy)
  • Revision ID: james.westby@ubuntu.com-20080414185730-528re3zp0m2hdlhi
Tags: 0.11-8
* added CONFIG -= link_prl to .pro files and removed dependencies
  which are made unnecessary by this change
* Fix segfault when closing last chat tab with qt4.4
  (This is from upstream svn, rev. 1101) (Closes: Bug#476122)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include "gpgproc.h"
 
21
 
 
22
#include "sprocess.h"
 
23
 
 
24
#ifdef Q_OS_MAC
 
25
#define QT_PIPE_HACK
 
26
#endif
 
27
 
 
28
#define QPROC_SIGNAL_RELAY
 
29
 
 
30
using namespace QCA;
 
31
 
 
32
namespace gpgQCAPlugin {
 
33
 
 
34
class QProcessSignalRelay : public QObject
 
35
{
 
36
        Q_OBJECT
 
37
public:
 
38
        QProcessSignalRelay(QProcess *proc, QObject *parent = 0)
 
39
        :QObject(parent)
 
40
        {
 
41
                qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
 
42
                connect(proc, SIGNAL(started()), SLOT(proc_started()), Qt::QueuedConnection);
 
43
                connect(proc, SIGNAL(readyReadStandardOutput()), SLOT(proc_readyReadStandardOutput()), Qt::QueuedConnection);
 
44
                connect(proc, SIGNAL(readyReadStandardError()), SLOT(proc_readyReadStandardError()), Qt::QueuedConnection);
 
45
                connect(proc, SIGNAL(bytesWritten(qint64)), SLOT(proc_bytesWritten(qint64)), Qt::QueuedConnection);
 
46
                connect(proc, SIGNAL(finished(int)), SLOT(proc_finished(int)), Qt::QueuedConnection);
 
47
                connect(proc, SIGNAL(error(QProcess::ProcessError)), SLOT(proc_error(QProcess::ProcessError)), Qt::QueuedConnection);
 
48
        }
 
49
 
 
50
signals:
 
51
        void started();
 
52
        void readyReadStandardOutput();
 
53
        void readyReadStandardError();
 
54
        void bytesWritten(qint64);
 
55
        void finished(int);
 
56
        void error(QProcess::ProcessError);
 
57
 
 
58
public slots:
 
59
        void proc_started()
 
60
        {
 
61
                emit started();
 
62
        }
 
63
 
 
64
        void proc_readyReadStandardOutput()
 
65
        {
 
66
                emit readyReadStandardOutput();
 
67
        }
 
68
 
 
69
        void proc_readyReadStandardError()
 
70
        {
 
71
                emit readyReadStandardError();
 
72
        }
 
73
 
 
74
        void proc_bytesWritten(qint64 x)
 
75
        {
 
76
                emit bytesWritten(x);
 
77
        }
 
78
 
 
79
        void proc_finished(int x)
 
80
        {
 
81
                emit finished(x);
 
82
        }
 
83
 
 
84
        void proc_error(QProcess::ProcessError x)
 
85
        {
 
86
                emit error(x);
 
87
        }
 
88
};
 
89
 
 
90
//----------------------------------------------------------------------------
 
91
// GPGProc
 
92
//----------------------------------------------------------------------------
 
93
enum ResetMode
 
94
{
 
95
        ResetSession        = 0,
 
96
        ResetSessionAndData = 1,
 
97
        ResetAll            = 2
 
98
};
 
99
 
 
100
class GPGProc::Private : public QObject
 
101
{
 
102
        Q_OBJECT
 
103
public:
 
104
        GPGProc *q;
 
105
        QString bin;
 
106
        QStringList args;
 
107
        GPGProc::Mode mode;
 
108
        SProcess *proc;
 
109
#ifdef QPROC_SIGNAL_RELAY
 
110
        QProcessSignalRelay *proc_relay;
 
111
#endif
 
112
        QPipe pipeAux, pipeCommand, pipeStatus;
 
113
        QByteArray statusBuf;
 
114
        QStringList statusLines;
 
115
        GPGProc::Error error;
 
116
        int exitCode;
 
117
        QTimer startTrigger, doneTrigger;
 
118
 
 
119
        QByteArray pre_stdin, pre_aux;
 
120
#ifdef QPIPE_SECURE
 
121
        SecureArray pre_command;
 
122
#else
 
123
        QByteArray pre_command;
 
124
#endif
 
125
        bool pre_stdin_close, pre_aux_close, pre_command_close;
 
126
 
 
127
        bool need_status, fin_process, fin_process_success, fin_status;
 
128
        QByteArray leftover_stdout;
 
129
        QByteArray leftover_stderr;
 
130
 
 
131
        Private(GPGProc *_q) : QObject(_q), q(_q), pipeAux(this), pipeCommand(this), pipeStatus(this), startTrigger(this), doneTrigger(this)
 
132
        {
 
133
                qRegisterMetaType<gpgQCAPlugin::GPGProc::Error>("gpgQCAPlugin::GPGProc::Error");
 
134
 
 
135
                proc = 0;
 
136
#ifdef QPROC_SIGNAL_RELAY
 
137
                proc_relay = 0;
 
138
#endif
 
139
                startTrigger.setSingleShot(true);
 
140
                doneTrigger.setSingleShot(true);
 
141
 
 
142
                connect(&pipeAux.writeEnd(), SIGNAL(bytesWritten(int)), SLOT(aux_written(int)));
 
143
                connect(&pipeAux.writeEnd(), SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(aux_error(QCA::QPipeEnd::Error)));
 
144
                connect(&pipeCommand.writeEnd(), SIGNAL(bytesWritten(int)), SLOT(command_written(int)));
 
145
                connect(&pipeCommand.writeEnd(), SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(command_error(QCA::QPipeEnd::Error)));
 
146
                connect(&pipeStatus.readEnd(), SIGNAL(readyRead()), SLOT(status_read()));
 
147
                connect(&pipeStatus.readEnd(), SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(status_error(QCA::QPipeEnd::Error)));
 
148
                connect(&startTrigger, SIGNAL(timeout()), SLOT(doStart()));
 
149
                connect(&doneTrigger, SIGNAL(timeout()), SLOT(doTryDone()));
 
150
 
 
151
                reset(ResetSessionAndData);
 
152
        }
 
153
 
 
154
        ~Private()
 
155
        {
 
156
                reset(ResetSession);
 
157
        }
 
158
 
 
159
        void closePipes()
 
160
        {
 
161
#ifdef QT_PIPE_HACK
 
162
                pipeAux.readEnd().reset();
 
163
                pipeCommand.readEnd().reset();
 
164
                pipeStatus.writeEnd().reset();
 
165
#endif
 
166
 
 
167
                pipeAux.reset();
 
168
                pipeCommand.reset();
 
169
                pipeStatus.reset();
 
170
        }
 
171
 
 
172
        void reset(ResetMode mode)
 
173
        {
 
174
#ifndef QT_PIPE_HACK
 
175
                closePipes();
 
176
#endif
 
177
 
 
178
                if(proc)
 
179
                {
 
180
                        proc->disconnect(this);
 
181
                        if(proc->state() != QProcess::NotRunning)
 
182
                                proc->terminate();
 
183
                        proc->setParent(0);
 
184
#ifdef QPROC_SIGNAL_RELAY
 
185
                        delete proc_relay;
 
186
                        proc_relay = 0;
 
187
                        delete proc; // should be safe to do thanks to relay
 
188
#else
 
189
                        proc->deleteLater();
 
190
#endif
 
191
                        proc = 0;
 
192
                }
 
193
 
 
194
#ifdef QT_PIPE_HACK
 
195
                closePipes();
 
196
#endif
 
197
 
 
198
                startTrigger.stop();
 
199
                doneTrigger.stop();
 
200
 
 
201
                pre_stdin.clear();
 
202
                pre_aux.clear();
 
203
                pre_command.clear();
 
204
                pre_stdin_close = false;
 
205
                pre_aux_close = false;
 
206
                pre_command_close = false;
 
207
 
 
208
                need_status = false;
 
209
                fin_process = false;
 
210
                fin_status = false;
 
211
 
 
212
                if(mode >= ResetSessionAndData)
 
213
                {
 
214
                        statusBuf.clear();
 
215
                        statusLines.clear();
 
216
                        leftover_stdout.clear();
 
217
                        leftover_stderr.clear();
 
218
                        error = GPGProc::FailedToStart;
 
219
                        exitCode = -1;
 
220
                }
 
221
        }
 
222
 
 
223
        bool setupPipes(bool makeAux)
 
224
        {
 
225
                if(makeAux && !pipeAux.create())
 
226
                {
 
227
                        closePipes();
 
228
                        emit q->debug("Error creating pipeAux");
 
229
                        return false;
 
230
                }
 
231
 
 
232
#ifdef QPIPE_SECURE
 
233
                if(!pipeCommand.create(true)) // secure
 
234
#else
 
235
                if(!pipeCommand.create())
 
236
#endif
 
237
                {
 
238
                        closePipes();
 
239
                        emit q->debug("Error creating pipeCommand");
 
240
                        return false;
 
241
                }
 
242
 
 
243
                if(!pipeStatus.create())
 
244
                {
 
245
                        closePipes();
 
246
                        emit q->debug("Error creating pipeStatus");
 
247
                        return false;
 
248
                }
 
249
 
 
250
                return true;
 
251
        }
 
252
 
 
253
        void setupArguments()
 
254
        {
 
255
                QStringList fullargs;
 
256
                fullargs += "--no-tty";
 
257
 
 
258
                if(mode == ExtendedMode)
 
259
                {
 
260
                        fullargs += "--enable-special-filenames";
 
261
 
 
262
                        fullargs += "--status-fd";
 
263
                        fullargs += QString::number(pipeStatus.writeEnd().idAsInt());
 
264
 
 
265
                        fullargs += "--command-fd";
 
266
                        fullargs += QString::number(pipeCommand.readEnd().idAsInt());
 
267
                }
 
268
 
 
269
                for(int n = 0; n < args.count(); ++n)
 
270
                {
 
271
                        QString a = args[n];
 
272
                        if(mode == ExtendedMode && a == "-&?")
 
273
                                fullargs += QString("-&") + QString::number(pipeAux.readEnd().idAsInt());
 
274
                        else
 
275
                                fullargs += a;
 
276
                }
 
277
 
 
278
                QString fullcmd = fullargs.join(" ");
 
279
                emit q->debug(QString("Running: [") + bin + ' ' + fullcmd + ']');
 
280
 
 
281
                args = fullargs;
 
282
        }
 
283
 
 
284
public slots:
 
285
        void doStart()
 
286
        {
 
287
#ifdef Q_OS_WIN
 
288
                // Note: for unix, inheritability is set in SProcess
 
289
                if(pipeAux.readEnd().isValid())
 
290
                        pipeAux.readEnd().setInheritable(true);
 
291
                if(pipeCommand.readEnd().isValid())
 
292
                        pipeCommand.readEnd().setInheritable(true);
 
293
                if(pipeStatus.writeEnd().isValid())
 
294
                        pipeStatus.writeEnd().setInheritable(true);
 
295
#endif
 
296
 
 
297
                setupArguments();
 
298
 
 
299
                proc->start(bin, args);
 
300
 
 
301
                // FIXME: From reading the source to Qt on both windows
 
302
                //   and unix platforms, we know that fork/CreateProcess
 
303
                //   are called in start.  However this is not guaranteed
 
304
                //   from an API perspective.  We should probably call
 
305
                //   QProcess::waitForStarted() to synchronously ensure
 
306
                //   fork/CreateProcess are called before closing these
 
307
                //   pipes.
 
308
                pipeAux.readEnd().close();
 
309
                pipeCommand.readEnd().close();
 
310
                pipeStatus.writeEnd().close();
 
311
        }
 
312
 
 
313
        void aux_written(int x)
 
314
        {
 
315
                emit q->bytesWrittenAux(x);
 
316
        }
 
317
 
 
318
        void aux_error(QCA::QPipeEnd::Error)
 
319
        {
 
320
                emit q->debug("Aux: Pipe error");
 
321
                reset(ResetSession);
 
322
                emit q->error(GPGProc::ErrorWrite);
 
323
        }
 
324
 
 
325
        void command_written(int x)
 
326
        {
 
327
                emit q->bytesWrittenCommand(x);
 
328
        }
 
329
 
 
330
        void command_error(QCA::QPipeEnd::Error)
 
331
        {
 
332
                emit q->debug("Command: Pipe error");
 
333
                reset(ResetSession);
 
334
                emit q->error(GPGProc::ErrorWrite);
 
335
        }
 
336
 
 
337
        void status_read()
 
338
        {
 
339
                if(readAndProcessStatusData())
 
340
                        emit q->readyReadStatusLines();
 
341
        }
 
342
 
 
343
        void status_error(QCA::QPipeEnd::Error e)
 
344
        {
 
345
                if(e == QPipeEnd::ErrorEOF)
 
346
                        emit q->debug("Status: Closed (EOF)");
 
347
                else
 
348
                        emit q->debug("Status: Closed (gone)");
 
349
 
 
350
                fin_status = true;
 
351
                doTryDone();
 
352
        }
 
353
 
 
354
        void proc_started()
 
355
        {
 
356
                emit q->debug("Process started");
 
357
 
 
358
                // Note: we don't close these here anymore.  instead we
 
359
                //   do it just after calling proc->start().
 
360
                // close these, we don't need them
 
361
                /*pipeAux.readEnd().close();
 
362
                pipeCommand.readEnd().close();
 
363
                pipeStatus.writeEnd().close();*/
 
364
 
 
365
                // do the pre* stuff
 
366
                if(!pre_stdin.isEmpty())
 
367
                {
 
368
                        proc->write(pre_stdin);
 
369
                        pre_stdin.clear();
 
370
                }
 
371
                if(!pre_aux.isEmpty())
 
372
                {
 
373
                        pipeAux.writeEnd().write(pre_aux);
 
374
                        pre_aux.clear();
 
375
                }
 
376
                if(!pre_command.isEmpty())
 
377
                {
 
378
#ifdef QPIPE_SECURE
 
379
                        pipeCommand.writeEnd().writeSecure(pre_command);
 
380
#else
 
381
                        pipeCommand.writeEnd().write(pre_command);
 
382
#endif
 
383
                        pre_command.clear();
 
384
                }
 
385
 
 
386
                if(pre_stdin_close)
 
387
                        proc->closeWriteChannel();
 
388
                if(pre_aux_close)
 
389
                        pipeAux.writeEnd().close();
 
390
                if(pre_command_close)
 
391
                        pipeCommand.writeEnd().close();
 
392
        }
 
393
 
 
394
        void proc_readyReadStandardOutput()
 
395
        {
 
396
                emit q->readyReadStdout();
 
397
        }
 
398
 
 
399
        void proc_readyReadStandardError()
 
400
        {
 
401
                emit q->readyReadStderr();
 
402
        }
 
403
 
 
404
        void proc_bytesWritten(qint64 lx)
 
405
        {
 
406
                int x = (int)lx;
 
407
                emit q->bytesWrittenStdin(x);
 
408
        }
 
409
 
 
410
        void proc_finished(int x)
 
411
        {
 
412
                emit q->debug(QString("Process finished: %1").arg(x));
 
413
                exitCode = x;
 
414
 
 
415
                fin_process = true;
 
416
                fin_process_success = true;
 
417
 
 
418
                if(need_status && !fin_status)
 
419
                {
 
420
                        pipeStatus.readEnd().finalize();
 
421
                        fin_status = true;
 
422
                        if(readAndProcessStatusData())
 
423
                        {
 
424
                                doneTrigger.start();
 
425
                                emit q->readyReadStatusLines();
 
426
                                return;
 
427
                        }
 
428
                }
 
429
 
 
430
                doTryDone();
 
431
        }
 
432
 
 
433
        void proc_error(QProcess::ProcessError x)
 
434
        {
 
435
                QMap<int, QString> errmap;
 
436
                errmap[QProcess::FailedToStart] = "FailedToStart";
 
437
                errmap[QProcess::Crashed]       = "Crashed";
 
438
                errmap[QProcess::Timedout]      = "Timedout";
 
439
                errmap[QProcess::WriteError]    = "WriteError";
 
440
                errmap[QProcess::ReadError]     = "ReadError";
 
441
                errmap[QProcess::UnknownError]  = "UnknownError";
 
442
 
 
443
                emit q->debug(QString("Process error: %1").arg(errmap[x]));
 
444
 
 
445
                if(x == QProcess::FailedToStart)
 
446
                        error = GPGProc::FailedToStart;
 
447
                else if(x == QProcess::WriteError)
 
448
                        error = GPGProc::ErrorWrite;
 
449
                else
 
450
                        error = GPGProc::UnexpectedExit;
 
451
 
 
452
                fin_process = true;
 
453
                fin_process_success = false;
 
454
 
 
455
#ifdef QT_PIPE_HACK
 
456
                // If the process fails to start, then the ends of the pipes
 
457
                // intended for the child process are still open.  Some Mac
 
458
                // users experience a lockup if we close our ends of the pipes
 
459
                // when the child's ends are still open.  If we ensure the
 
460
                // child's ends are closed, we prevent this lockup.  I have no
 
461
                // idea why the problem even happens or why this fix should
 
462
                // work.
 
463
                pipeAux.readEnd().reset();
 
464
                pipeCommand.readEnd().reset();
 
465
                pipeStatus.writeEnd().reset();
 
466
#endif
 
467
 
 
468
                if(need_status && !fin_status)
 
469
                {
 
470
                        pipeStatus.readEnd().finalize();
 
471
                        fin_status = true;
 
472
                        if(readAndProcessStatusData())
 
473
                        {
 
474
                                doneTrigger.start();
 
475
                                emit q->readyReadStatusLines();
 
476
                                return;
 
477
                        }
 
478
                }
 
479
 
 
480
                doTryDone();
 
481
        }
 
482
 
 
483
        void doTryDone()
 
484
        {
 
485
                if(!fin_process)
 
486
                        return;
 
487
 
 
488
                if(need_status && !fin_status)
 
489
                        return;
 
490
 
 
491
                emit q->debug("Done");
 
492
 
 
493
                // get leftover data
 
494
                proc->setReadChannel(QProcess::StandardOutput);
 
495
                leftover_stdout = proc->readAll();
 
496
 
 
497
                proc->setReadChannel(QProcess::StandardError);
 
498
                leftover_stderr = proc->readAll();
 
499
 
 
500
                reset(ResetSession);
 
501
                if(fin_process_success)
 
502
                        emit q->finished(exitCode);
 
503
                else
 
504
                        emit q->error(error);
 
505
        }
 
506
 
 
507
private:
 
508
        bool readAndProcessStatusData()
 
509
        {
 
510
                QByteArray buf = pipeStatus.readEnd().read();
 
511
                if(buf.isEmpty())
 
512
                        return false;
 
513
 
 
514
                return processStatusData(buf);
 
515
        }
 
516
 
 
517
        // return true if there are newly parsed lines available
 
518
        bool processStatusData(const QByteArray &buf)
 
519
        {
 
520
                statusBuf.append(buf);
 
521
 
 
522
                // extract all lines
 
523
                QStringList list;
 
524
                while(1)
 
525
                {
 
526
                        int n = statusBuf.indexOf('\n');
 
527
                        if(n == -1)
 
528
                                break;
 
529
 
 
530
                        // extract the string from statusbuf
 
531
                        ++n;
 
532
                        char *p = (char *)statusBuf.data();
 
533
                        QByteArray cs(p, n);
 
534
                        int newsize = statusBuf.size() - n;
 
535
                        memmove(p, p + n, newsize);
 
536
                        statusBuf.resize(newsize);
 
537
 
 
538
                        // convert to string without newline
 
539
                        QString str = QString::fromUtf8(cs);
 
540
                        str.truncate(str.length() - 1);
 
541
 
 
542
                        // ensure it has a proper header
 
543
                        if(str.left(9) != "[GNUPG:] ")
 
544
                                continue;
 
545
 
 
546
                        // take it off
 
547
                        str = str.mid(9);
 
548
 
 
549
                        // add to the list
 
550
                        list += str;
 
551
                }
 
552
 
 
553
                if(list.isEmpty())
 
554
                        return false;
 
555
 
 
556
                statusLines += list;
 
557
                return true;
 
558
        }
 
559
};
 
560
 
 
561
GPGProc::GPGProc(QObject *parent)
 
562
:QObject(parent)
 
563
{
 
564
        d = new Private(this);
 
565
}
 
566
 
 
567
GPGProc::~GPGProc()
 
568
{
 
569
        delete d;
 
570
}
 
571
 
 
572
void GPGProc::reset()
 
573
{
 
574
        d->reset(ResetAll);
 
575
}
 
576
 
 
577
bool GPGProc::isActive() const
 
578
{
 
579
        return (d->proc ? true : false);
 
580
}
 
581
 
 
582
void GPGProc::start(const QString &bin, const QStringList &args, Mode mode)
 
583
{
 
584
        if(isActive())
 
585
                d->reset(ResetSessionAndData);
 
586
 
 
587
        if(mode == ExtendedMode)
 
588
        {
 
589
                if(!d->setupPipes(args.contains("-&?")))
 
590
                {
 
591
                        d->error = FailedToStart;
 
592
 
 
593
                        // emit later
 
594
                        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(gpgQCAPlugin::GPGProc::Error, d->error));
 
595
                        return;
 
596
                }
 
597
 
 
598
                d->need_status = true;
 
599
 
 
600
                emit debug("Pipe setup complete");
 
601
        }
 
602
 
 
603
        d->proc = new SProcess(d);
 
604
 
 
605
#ifdef Q_OS_UNIX
 
606
        QList<int> plist;
 
607
        if(d->pipeAux.readEnd().isValid())
 
608
                plist += d->pipeAux.readEnd().id();
 
609
        if(d->pipeCommand.readEnd().isValid())
 
610
                plist += d->pipeCommand.readEnd().id();
 
611
        if(d->pipeStatus.writeEnd().isValid())
 
612
                plist += d->pipeStatus.writeEnd().id();
 
613
        d->proc->setInheritPipeList(plist);
 
614
#endif
 
615
 
 
616
        // enable the pipes we want
 
617
        if(d->pipeAux.writeEnd().isValid())
 
618
                d->pipeAux.writeEnd().enable();
 
619
        if(d->pipeCommand.writeEnd().isValid())
 
620
                d->pipeCommand.writeEnd().enable();
 
621
        if(d->pipeStatus.readEnd().isValid())
 
622
                d->pipeStatus.readEnd().enable();
 
623
 
 
624
#ifdef QPROC_SIGNAL_RELAY
 
625
        d->proc_relay = new QProcessSignalRelay(d->proc, d);
 
626
        connect(d->proc_relay, SIGNAL(started()), d, SLOT(proc_started()));
 
627
        connect(d->proc_relay, SIGNAL(readyReadStandardOutput()), d, SLOT(proc_readyReadStandardOutput()));
 
628
        connect(d->proc_relay, SIGNAL(readyReadStandardError()), d, SLOT(proc_readyReadStandardError()));
 
629
        connect(d->proc_relay, SIGNAL(bytesWritten(qint64)), d, SLOT(proc_bytesWritten(qint64)));
 
630
        connect(d->proc_relay, SIGNAL(finished(int)), d, SLOT(proc_finished(int)));
 
631
        connect(d->proc_relay, SIGNAL(error(QProcess::ProcessError)), d, SLOT(proc_error(QProcess::ProcessError)));
 
632
#else
 
633
        connect(d->proc, SIGNAL(started()), d, SLOT(proc_started()));
 
634
        connect(d->proc, SIGNAL(readyReadStandardOutput()), d, SLOT(proc_readyReadStandardOutput()));
 
635
        connect(d->proc, SIGNAL(readyReadStandardError()), d, SLOT(proc_readyReadStandardError()));
 
636
        connect(d->proc, SIGNAL(bytesWritten(qint64)), d, SLOT(proc_bytesWritten(qint64)));
 
637
        connect(d->proc, SIGNAL(finished(int)), d, SLOT(proc_finished(int)));
 
638
        connect(d->proc, SIGNAL(error(QProcess::ProcessError)), d, SLOT(proc_error(QProcess::ProcessError)));
 
639
#endif
 
640
 
 
641
        d->bin = bin;
 
642
        d->args = args;
 
643
        d->mode = mode;
 
644
        d->startTrigger.start();
 
645
}
 
646
 
 
647
QByteArray GPGProc::readStdout()
 
648
{
 
649
        if(d->proc)
 
650
        {
 
651
                d->proc->setReadChannel(QProcess::StandardOutput);
 
652
                return d->proc->readAll();
 
653
        }
 
654
        else
 
655
        {
 
656
                QByteArray a = d->leftover_stdout;
 
657
                d->leftover_stdout.clear();
 
658
                return a;
 
659
        }
 
660
}
 
661
 
 
662
QByteArray GPGProc::readStderr()
 
663
{
 
664
        if(d->proc)
 
665
        {
 
666
                d->proc->setReadChannel(QProcess::StandardError);
 
667
                return d->proc->readAll();
 
668
        }
 
669
        else
 
670
        {
 
671
                QByteArray a = d->leftover_stderr;
 
672
                d->leftover_stderr.clear();
 
673
                return a;
 
674
        }
 
675
}
 
676
 
 
677
QStringList GPGProc::readStatusLines()
 
678
{
 
679
        QStringList out = d->statusLines;
 
680
        d->statusLines.clear();
 
681
        return out;
 
682
}
 
683
 
 
684
void GPGProc::writeStdin(const QByteArray &a)
 
685
{
 
686
        if(!d->proc || a.isEmpty())
 
687
                return;
 
688
 
 
689
        if(d->proc->state() == QProcess::Running)
 
690
                d->proc->write(a);
 
691
        else
 
692
                d->pre_stdin += a;
 
693
}
 
694
 
 
695
void GPGProc::writeAux(const QByteArray &a)
 
696
{
 
697
        if(!d->proc || a.isEmpty())
 
698
                return;
 
699
 
 
700
        if(d->proc->state() == QProcess::Running)
 
701
                d->pipeAux.writeEnd().write(a);
 
702
        else
 
703
                d->pre_aux += a;
 
704
}
 
705
 
 
706
#ifdef QPIPE_SECURE
 
707
void GPGProc::writeCommand(const SecureArray &a)
 
708
#else
 
709
void GPGProc::writeCommand(const QByteArray &a)
 
710
#endif
 
711
{
 
712
        if(!d->proc || a.isEmpty())
 
713
                return;
 
714
 
 
715
        if(d->proc->state() == QProcess::Running)
 
716
#ifdef QPIPE_SECURE
 
717
                d->pipeCommand.writeEnd().writeSecure(a);
 
718
#else
 
719
                d->pipeCommand.writeEnd().write(a);
 
720
#endif
 
721
        else
 
722
                d->pre_command += a;
 
723
}
 
724
 
 
725
void GPGProc::closeStdin()
 
726
{
 
727
        if(!d->proc)
 
728
                return;
 
729
 
 
730
        if(d->proc->state() == QProcess::Running)
 
731
                d->proc->closeWriteChannel();
 
732
        else
 
733
                d->pre_stdin_close = true;
 
734
}
 
735
 
 
736
void GPGProc::closeAux()
 
737
{
 
738
        if(!d->proc)
 
739
                return;
 
740
 
 
741
        if(d->proc->state() == QProcess::Running)
 
742
                d->pipeAux.writeEnd().close();
 
743
        else
 
744
                d->pre_aux_close = true;
 
745
}
 
746
 
 
747
void GPGProc::closeCommand()
 
748
{
 
749
        if(!d->proc)
 
750
                return;
 
751
 
 
752
        if(d->proc->state() == QProcess::Running)
 
753
                d->pipeCommand.writeEnd().close();
 
754
        else
 
755
                d->pre_command_close = true;
 
756
}
 
757
 
 
758
}
 
759
 
 
760
#include "gpgproc.moc"