00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <qgpgme/dataprovider.h>
00024
00025 #include <gpgme++/error.h>
00026
00027 #include <QIODevice>
00028 #include <QProcess>
00029
00030 #include <cstdio>
00031 #include <cstring>
00032 #include <cassert>
00033
00034 using namespace QGpgME;
00035 using namespace GpgME;
00036
00037
00038
00039
00040
00041
00042
00043 static bool resizeAndInit( QByteArray & ba, size_t newSize ) {
00044 const size_t oldSize = ba.size();
00045 ba.resize( newSize );
00046 const bool ok = ( newSize == static_cast<size_t>( ba.size() ) );
00047 if ( ok )
00048 memset( ba.data() + oldSize, 0, newSize - oldSize );
00049 return ok;
00050 }
00051
00052 QByteArrayDataProvider::QByteArrayDataProvider()
00053 : GpgME::DataProvider(), mOff( 0 ) {}
00054
00055 QByteArrayDataProvider::QByteArrayDataProvider( const QByteArray & initialData )
00056 : GpgME::DataProvider(), mArray( initialData ), mOff( 0 ) {}
00057
00058 QByteArrayDataProvider::~QByteArrayDataProvider() {}
00059
00060 ssize_t QByteArrayDataProvider::read( void * buffer, size_t bufSize ) {
00061 #ifndef NDEBUG
00062
00063 #endif
00064 if ( bufSize == 0 )
00065 return 0;
00066 if ( !buffer ) {
00067 Error::setSystemError( GPG_ERR_EINVAL );
00068 return -1;
00069 }
00070 if ( mOff >= mArray.size() )
00071 return 0;
00072 size_t amount = qMin( bufSize, static_cast<size_t>( mArray.size() - mOff ) );
00073 assert( amount > 0 );
00074 memcpy( buffer, mArray.data() + mOff, amount );
00075 mOff += amount;
00076 return amount;
00077 }
00078
00079 ssize_t QByteArrayDataProvider::write( const void * buffer, size_t bufSize ) {
00080 #ifndef NDEBUG
00081
00082 #endif
00083 if ( bufSize == 0 )
00084 return 0;
00085 if ( !buffer ) {
00086 Error::setSystemError( GPG_ERR_EINVAL );
00087 return -1;
00088 }
00089 if ( mOff >= mArray.size() )
00090 resizeAndInit( mArray, mOff + bufSize );
00091 if ( mOff >= mArray.size() ) {
00092 Error::setSystemError( GPG_ERR_EIO );
00093 return -1;
00094 }
00095 assert( bufSize <= static_cast<size_t>(mArray.size()) - mOff );
00096 memcpy( mArray.data() + mOff, buffer, bufSize );
00097 mOff += bufSize;
00098 return bufSize;
00099 }
00100
00101 off_t QByteArrayDataProvider::seek( off_t offset, int whence ) {
00102 #ifndef NDEBUG
00103
00104 #endif
00105 int newOffset = mOff;
00106 switch ( whence ) {
00107 case SEEK_SET:
00108 newOffset = offset;
00109 break;
00110 case SEEK_CUR:
00111 newOffset += offset;
00112 break;
00113 case SEEK_END:
00114 newOffset = mArray.size() + offset;
00115 break;
00116 default:
00117 Error::setSystemError( GPG_ERR_EINVAL );
00118 return (off_t)-1;
00119 }
00120 return mOff = newOffset;
00121 }
00122
00123 void QByteArrayDataProvider::release() {
00124 #ifndef NDEBUG
00125
00126 #endif
00127 mArray = QByteArray();
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137 QIODeviceDataProvider::QIODeviceDataProvider( const boost::shared_ptr<QIODevice> & io )
00138 : GpgME::DataProvider(),
00139 mIO( io ),
00140 mErrorOccurred( false ),
00141 mHaveQProcess( qobject_cast<QProcess*>( io.get() ) )
00142 {
00143 assert( mIO );
00144 }
00145
00146 QIODeviceDataProvider::~QIODeviceDataProvider() {}
00147
00148 bool QIODeviceDataProvider::isSupported( Operation op ) const {
00149 const QProcess* const proc = qobject_cast<QProcess*>( mIO.get() );
00150 bool canRead = true;
00151 if ( proc ) {
00152 canRead = proc->readChannel() == QProcess::StandardOutput;
00153 }
00154
00155 switch ( op ) {
00156 case Read: return mIO->isReadable() && canRead;
00157 case Write: return mIO->isWritable();
00158 case Seek: return !mIO->isSequential();
00159 case Release: return true;
00160 default: return false;
00161 }
00162 }
00163
00164 static qint64 blocking_read( const boost::shared_ptr<QIODevice> & io, char * buffer, qint64 maxSize ) {
00165 while ( !io->bytesAvailable() ) {
00166 if ( !io->waitForReadyRead( -1 ) ) {
00167 if ( const QProcess * const p = qobject_cast<QProcess*>( io.get() ) ) {
00168 if ( p->error() == QProcess::UnknownError &&
00169 p->exitStatus() == QProcess::NormalExit &&
00170 p->exitCode() == 0 ) {
00171 return 0;
00172 } else {
00173 Error::setSystemError( GPG_ERR_EIO );
00174 return -1;
00175 }
00176 } else {
00177 return 0;
00178 }
00179 }
00180 }
00181 return io->read( buffer, maxSize );
00182 }
00183
00184 ssize_t QIODeviceDataProvider::read( void * buffer, size_t bufSize ) {
00185 #ifndef NDEBUG
00186
00187 #endif
00188 if ( bufSize == 0 )
00189 return 0;
00190 if ( !buffer ) {
00191 Error::setSystemError( GPG_ERR_EINVAL );
00192 return -1;
00193 }
00194 const qint64 numRead = mHaveQProcess
00195 ? blocking_read( mIO, static_cast<char*>(buffer), bufSize )
00196 : mIO->read( static_cast<char*>(buffer), bufSize ) ;
00197
00198
00199
00200
00201 ssize_t rc = numRead;
00202 if ( numRead < 0 && !Error::hasSystemError() ) {
00203 if ( mErrorOccurred )
00204 Error::setSystemError( GPG_ERR_EIO );
00205 else
00206 rc = 0;
00207 }
00208 if ( numRead < 0 )
00209 mErrorOccurred = true;
00210 return rc;
00211 }
00212
00213 ssize_t QIODeviceDataProvider::write( const void * buffer, size_t bufSize ) {
00214 #ifndef NDEBUG
00215
00216 #endif
00217 if ( bufSize == 0 )
00218 return 0;
00219 if ( !buffer ) {
00220 Error::setSystemError( GPG_ERR_EINVAL );
00221 return -1;
00222 }
00223
00224 return mIO->write( static_cast<const char*>(buffer), bufSize );
00225 }
00226
00227 off_t QIODeviceDataProvider::seek( off_t offset, int whence ) {
00228 #ifndef NDEBUG
00229
00230 #endif
00231 if ( mIO->isSequential() ) {
00232 Error::setSystemError( GPG_ERR_ESPIPE );
00233 return (off_t)-1;
00234 }
00235 qint64 newOffset = mIO->pos();
00236 switch ( whence ) {
00237 case SEEK_SET:
00238 newOffset = offset;
00239 break;
00240 case SEEK_CUR:
00241 newOffset += offset;
00242 break;
00243 case SEEK_END:
00244 newOffset = mIO->size() + offset;
00245 break;
00246 default:
00247 Error::setSystemError( GPG_ERR_EINVAL );
00248 return (off_t)-1;
00249 }
00250 if ( !mIO->seek( newOffset ) ) {
00251 Error::setSystemError( GPG_ERR_EINVAL );
00252 return (off_t)-1;
00253 }
00254 return newOffset;
00255 }
00256
00257 void QIODeviceDataProvider::release() {
00258 #ifndef NDEBUG
00259
00260 #endif
00261 mIO->close();
00262 }