qgpgme
dataprovider.cpp
00001 /* dataprovider.cpp 00002 Copyright (C) 2004 Klar�vdalens Datakonsult AB 00003 00004 This file is part of QGPGME. 00005 00006 QGPGME is free software; you can redistribute it and/or modify it 00007 under the terms of the GNU Library General Public License as published 00008 by the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 QGPGME is distributed in the hope that it will be useful, but 00012 WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with QGPGME; see the file COPYING.LIB. If not, write to the 00018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. */ 00020 00021 // -*- c++ -*- 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 // QByteArrayDataProvider 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 //qDebug( "QByteArrayDataProvider::read( %p, %d )", buffer, bufSize ); 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; // EOF 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 //qDebug( "QByteArrayDataProvider::write( %p, %lu )", buffer, static_cast<unsigned long>( bufSize ) ); 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 //qDebug( "QByteArrayDataProvider::seek( %d, %d )", int(offset), whence ); 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 //qDebug( "QByteArrayDataProvider::release()" ); 00126 #endif 00127 mArray = QByteArray(); 00128 } 00129 00130 00131 // 00132 // 00133 // QIODeviceDataProvider 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; // assume EOF (loses error cases :/ ) 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 //qDebug( "QIODeviceDataProvider::read( %p, %lu )", buffer, bufSize ); 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 //workaround: some QIODevices (known example: QProcess) might not return 0 (EOF), but immediately -1 when finished. If no 00199 //errno is set, gpgme doesn't detect the error and loops forever. So return 0 on the very first -1 in case errno is 0 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 //qDebug( "QIODeviceDataProvider::write( %p, %lu )", buffer, static_cast<unsigned long>( bufSize ) ); 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 //qDebug( "QIODeviceDataProvider::seek( %d, %d )", int(offset), whence ); 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 //qDebug( "QIODeviceDataProvider::release()" ); 00260 #endif 00261 mIO->close(); 00262 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:24:58 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:24:58 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.