• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

qgpgme

  • sources
  • kde-4.14
  • kdepimlibs
  • qgpgme
dataprovider.cpp
1 /* dataprovider.cpp
2  Copyright (C) 2004 Klar�vdalens Datakonsult AB
3 
4  This file is part of QGPGME.
5 
6  QGPGME is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Library General Public License as published
8  by the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  QGPGME is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with QGPGME; see the file COPYING.LIB. If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA. */
20 
21 // -*- c++ -*-
22 
23 #include <qgpgme/dataprovider.h>
24 
25 #include <gpgme++/error.h>
26 
27 #include <QIODevice>
28 #include <QProcess>
29 
30 #include <cstdio>
31 #include <cstring>
32 #include <cassert>
33 
34 using namespace QGpgME;
35 using namespace GpgME;
36 
37 //
38 //
39 // QByteArrayDataProvider
40 //
41 //
42 
43 static bool resizeAndInit( QByteArray & ba, size_t newSize ) {
44  const size_t oldSize = ba.size();
45  ba.resize( newSize );
46  const bool ok = ( newSize == static_cast<size_t>( ba.size() ) );
47  if ( ok ) {
48  memset( ba.data() + oldSize, 0, newSize - oldSize );
49  }
50  return ok;
51 }
52 
53 QByteArrayDataProvider::QByteArrayDataProvider()
54  : GpgME::DataProvider(), mOff( 0 ) {}
55 
56 QByteArrayDataProvider::QByteArrayDataProvider( const QByteArray & initialData )
57  : GpgME::DataProvider(), mArray( initialData ), mOff( 0 ) {}
58 
59 QByteArrayDataProvider::~QByteArrayDataProvider() {}
60 
61 ssize_t QByteArrayDataProvider::read( void * buffer, size_t bufSize ) {
62 #ifndef NDEBUG
63  //qDebug( "QByteArrayDataProvider::read( %p, %d )", buffer, bufSize );
64 #endif
65  if ( bufSize == 0 ) {
66  return 0;
67  }
68  if ( !buffer ) {
69  Error::setSystemError( GPG_ERR_EINVAL );
70  return -1;
71  }
72  if ( mOff >= mArray.size() ) {
73  return 0; // EOF
74  }
75  size_t amount = qMin( bufSize, static_cast<size_t>( mArray.size() - mOff ) );
76  assert( amount > 0 );
77  memcpy( buffer, mArray.data() + mOff, amount );
78  mOff += amount;
79  return amount;
80 }
81 
82 ssize_t QByteArrayDataProvider::write( const void * buffer, size_t bufSize ) {
83 #ifndef NDEBUG
84  //qDebug( "QByteArrayDataProvider::write( %p, %lu )", buffer, static_cast<unsigned long>( bufSize ) );
85 #endif
86  if ( bufSize == 0 ) {
87  return 0;
88  }
89  if ( !buffer ) {
90  Error::setSystemError( GPG_ERR_EINVAL );
91  return -1;
92  }
93  if ( mOff >= mArray.size() ) {
94  resizeAndInit( mArray, mOff + bufSize );
95  }
96  if ( mOff >= mArray.size() ) {
97  Error::setSystemError( GPG_ERR_EIO );
98  return -1;
99  }
100  assert( bufSize <= static_cast<size_t>( mArray.size() ) - mOff );
101  memcpy( mArray.data() + mOff, buffer, bufSize );
102  mOff += bufSize;
103  return bufSize;
104 }
105 
106 off_t QByteArrayDataProvider::seek( off_t offset, int whence ) {
107 #ifndef NDEBUG
108  //qDebug( "QByteArrayDataProvider::seek( %d, %d )", int(offset), whence );
109 #endif
110  int newOffset = mOff;
111  switch ( whence ) {
112  case SEEK_SET:
113  newOffset = offset;
114  break;
115  case SEEK_CUR:
116  newOffset += offset;
117  break;
118  case SEEK_END:
119  newOffset = mArray.size() + offset;
120  break;
121  default:
122  Error::setSystemError( GPG_ERR_EINVAL );
123  return (off_t)-1;
124  }
125  return mOff = newOffset;
126 }
127 
128 void QByteArrayDataProvider::release() {
129 #ifndef NDEBUG
130  //qDebug( "QByteArrayDataProvider::release()" );
131 #endif
132  mArray = QByteArray();
133 }
134 
135 
136 //
137 //
138 // QIODeviceDataProvider
139 //
140 //
141 
142 QIODeviceDataProvider::QIODeviceDataProvider( const boost::shared_ptr<QIODevice> & io )
143  : GpgME::DataProvider(),
144  mIO( io ),
145  mErrorOccurred( false ),
146  mHaveQProcess( qobject_cast<QProcess*>( io.get() ) )
147 {
148  assert( mIO );
149 }
150 
151 QIODeviceDataProvider::~QIODeviceDataProvider() {}
152 
153 bool QIODeviceDataProvider::isSupported( Operation op ) const {
154  const QProcess* const proc = qobject_cast<QProcess*>( mIO.get() );
155  bool canRead = true;
156  if ( proc ) {
157  canRead = proc->readChannel() == QProcess::StandardOutput;
158  }
159 
160  switch ( op ) {
161  case Read: return mIO->isReadable() && canRead;
162  case Write: return mIO->isWritable();
163  case Seek: return !mIO->isSequential();
164  case Release: return true;
165  default: return false;
166  }
167 }
168 
169 static qint64 blocking_read( const boost::shared_ptr<QIODevice> & io, char * buffer, qint64 maxSize ) {
170  while ( !io->bytesAvailable() ) {
171  if ( !io->waitForReadyRead( -1 ) ) {
172  if ( const QProcess * const p = qobject_cast<QProcess*>( io.get() ) ) {
173  if ( p->error() == QProcess::UnknownError &&
174  p->exitStatus() == QProcess::NormalExit &&
175  p->exitCode() == 0 ) {
176  return 0;
177  } else {
178  Error::setSystemError( GPG_ERR_EIO );
179  return -1;
180  }
181  } else {
182  return 0; // assume EOF (loses error cases :/ )
183  }
184  }
185  }
186  return io->read( buffer, maxSize );
187 }
188 
189 ssize_t QIODeviceDataProvider::read( void * buffer, size_t bufSize ) {
190 #ifndef NDEBUG
191  //qDebug( "QIODeviceDataProvider::read( %p, %lu )", buffer, bufSize );
192 #endif
193  if ( bufSize == 0 ) {
194  return 0;
195  }
196  if ( !buffer ) {
197  Error::setSystemError( GPG_ERR_EINVAL );
198  return -1;
199  }
200  const qint64 numRead = mHaveQProcess
201  ? blocking_read( mIO, static_cast<char*>( buffer ), bufSize )
202  : mIO->read( static_cast<char*>( buffer ), bufSize );
203 
204  //workaround: some QIODevices (known example: QProcess) might not return 0 (EOF), but immediately -1 when finished. If no
205  //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
206 
207  ssize_t rc = numRead;
208  if ( numRead < 0 && !Error::hasSystemError() ) {
209  if ( mErrorOccurred ) {
210  Error::setSystemError( GPG_ERR_EIO );
211  } else {
212  rc = 0;
213  }
214  }
215  if ( numRead < 0 ) {
216  mErrorOccurred = true;
217  }
218  return rc;
219 }
220 
221 ssize_t QIODeviceDataProvider::write( const void * buffer, size_t bufSize ) {
222 #ifndef NDEBUG
223  //qDebug( "QIODeviceDataProvider::write( %p, %lu )", buffer, static_cast<unsigned long>( bufSize ) );
224 #endif
225  if ( bufSize == 0 ) {
226  return 0;
227  }
228  if ( !buffer ) {
229  Error::setSystemError( GPG_ERR_EINVAL );
230  return -1;
231  }
232 
233  return mIO->write( static_cast<const char*>( buffer ), bufSize );
234 }
235 
236 off_t QIODeviceDataProvider::seek( off_t offset, int whence ) {
237 #ifndef NDEBUG
238  //qDebug( "QIODeviceDataProvider::seek( %d, %d )", int(offset), whence );
239 #endif
240  if ( mIO->isSequential() ) {
241  Error::setSystemError( GPG_ERR_ESPIPE );
242  return (off_t)-1;
243  }
244  qint64 newOffset = mIO->pos();
245  switch ( whence ) {
246  case SEEK_SET:
247  newOffset = offset;
248  break;
249  case SEEK_CUR:
250  newOffset += offset;
251  break;
252  case SEEK_END:
253  newOffset = mIO->size() + offset;
254  break;
255  default:
256  Error::setSystemError( GPG_ERR_EINVAL );
257  return (off_t)-1;
258  }
259  if ( !mIO->seek( newOffset ) ) {
260  Error::setSystemError( GPG_ERR_EINVAL );
261  return (off_t)-1;
262  }
263  return newOffset;
264 }
265 
266 void QIODeviceDataProvider::release() {
267 #ifndef NDEBUG
268  //qDebug( "QIODeviceDataProvider::release()" );
269 #endif
270  mIO->close();
271 }
QByteArray
QByteArray::resize
void resize(int size)
QProcess
QProcess::readChannel
ProcessChannel readChannel() const
QByteArray::data
char * data()
QByteArray::size
int size() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:43 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

qgpgme

Skip menu "qgpgme"
  • Main Page
  • File List

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal