kleopatra
echocommand.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <config-kleopatra.h>
00034
00035 #ifdef QT_NO_STL
00036 #undef QT_NO_STL
00037 #undef QT_STL
00038 #define QT_STL
00039 #endif
00040
00041 #include "echocommand.h"
00042
00043 #include <utils/input.h>
00044 #include <utils/output.h>
00045 #include <utils/exception.h>
00046
00047 #include <gpg-error.h>
00048
00049 #include <KLocale>
00050
00051 #include <QVariant>
00052 #include <QByteArray>
00053 #include <QIODevice>
00054 #include <QList>
00055
00056 #include <string>
00057 #include <algorithm>
00058
00059 using namespace Kleo;
00060 using namespace boost;
00061
00062 static const char option_prefix[] = "prefix";
00063
00064 class EchoCommand::Private {
00065 public:
00066 Private() : operationsInFlight( 0 ), buffer() {}
00067
00068 int operationsInFlight;
00069 QByteArray buffer;
00070 };
00071
00072 EchoCommand::EchoCommand()
00073 : QObject(), AssuanCommandMixin<EchoCommand>(), d( new Private ) {}
00074
00075 EchoCommand::~EchoCommand() {}
00076
00077 int EchoCommand::doStart() {
00078
00079 const std::vector< shared_ptr<Input> > in = inputs(), msg = messages();
00080 const std::vector< shared_ptr<Output> > out = outputs();
00081
00082 if ( !in.empty() && out.empty() )
00083 return makeError( GPG_ERR_NOT_SUPPORTED );
00084
00085 if ( !msg.empty() )
00086 return makeError( GPG_ERR_NOT_SUPPORTED );
00087
00088 if ( hasOption( option_prefix ) && !option( option_prefix ).toByteArray().isEmpty() )
00089 return makeError( GPG_ERR_NOT_IMPLEMENTED );
00090
00091 std::string keyword;
00092 if ( hasOption( "inquire" ) ) {
00093 keyword = option("inquire").toString().toStdString();
00094 if ( keyword.empty() )
00095 return makeError( GPG_ERR_INV_ARG );
00096 }
00097
00098 const std::string output = option("text").toString().toStdString();
00099
00100
00101
00102
00103 sendStatus( "ECHO", output.empty() ? "" : output.c_str() );
00104
00105
00106 if ( !keyword.empty() )
00107 if ( const int err = inquire( keyword.c_str(), this,
00108 SLOT(slotInquireData(int,QByteArray)) ) )
00109 return err;
00110 else
00111 ++d->operationsInFlight;
00112
00113
00114 if ( const shared_ptr<QIODevice> i = in.at(0)->ioDevice() ) {
00115 const shared_ptr<QIODevice> o = out.at(0)->ioDevice();
00116
00117 ++d->operationsInFlight;
00118
00119 connect( i.get(), SIGNAL(readyRead()), this, SLOT(slotInputReadyRead()) );
00120 connect( o.get(), SIGNAL(bytesWritten(qint64)), this, SLOT(slotOutputBytesWritten()) );
00121
00122 if ( i->bytesAvailable() )
00123 slotInputReadyRead();
00124 }
00125
00126 if ( !d->operationsInFlight )
00127 done();
00128 return 0;
00129 }
00130
00131 void EchoCommand::doCanceled() {
00132
00133 }
00134
00135 void EchoCommand::slotInquireData( int rc, const QByteArray & data ) {
00136
00137 --d->operationsInFlight;
00138
00139 if ( rc ) {
00140 done( rc );
00141 return;
00142 }
00143
00144 try {
00145 sendStatus( "ECHOINQ", data );
00146 if ( !d->operationsInFlight )
00147 done();
00148 } catch ( const Exception & e ) {
00149 done( e.error(), e.message() );
00150 } catch ( const std::exception & e ) {
00151 done( makeError( GPG_ERR_UNEXPECTED ),
00152 i18n("Caught unexpected exception in SignCommand::Private::slotMicAlgDetermined: %1",
00153 QString::fromLocal8Bit( e.what() ) ) );
00154 } catch ( ... ) {
00155 done( makeError( GPG_ERR_UNEXPECTED ),
00156 i18n("Caught unknown exception in SignCommand::Private::slotMicAlgDetermined") );
00157 }
00158
00159 }
00160
00161 void EchoCommand::slotInputReadyRead() {
00162 const shared_ptr<QIODevice> in = inputs().at(0)->ioDevice();
00163 assert( in );
00164
00165 QByteArray buffer;
00166 buffer.resize( in->bytesAvailable() );
00167 const qint64 read = in->read( buffer.data(), buffer.size() );
00168 if ( read == - 1 ) {
00169 done( makeError( GPG_ERR_EIO ) );
00170 return;
00171 }
00172 if ( read == 0 || !in->isSequential() && read == in->size() )
00173 in->close();
00174
00175 buffer.resize( read );
00176 d->buffer += buffer;
00177
00178 slotOutputBytesWritten();
00179 }
00180
00181
00182 void EchoCommand::slotOutputBytesWritten() {
00183 const shared_ptr<QIODevice> out = outputs().at(0)->ioDevice();
00184 assert( out );
00185
00186 if ( !d->buffer.isEmpty() ) {
00187
00188 if ( out->bytesToWrite() )
00189 return;
00190
00191 const qint64 written = out->write( d->buffer );
00192 if ( written == -1 ) {
00193 done( makeError( GPG_ERR_EIO ) );
00194 return;
00195 }
00196 d->buffer.remove( 0, written );
00197
00198 }
00199
00200 if ( out->isOpen() && d->buffer.isEmpty() && !inputs().at(0)->ioDevice()->isOpen() ) {
00201 out->close();
00202 if ( !--d->operationsInFlight )
00203 done();
00204 }
00205 }
00206
00207 #include "moc_echocommand.cpp"