qgpgmerefreshkeysjob.cpp
1 /*
2  qgpgmerefreshkeysjob.cpp
3 
4  This file is part of libkleopatra, the KDE keymanagement library
5  Copyright (c) 2004 Klarälvdalens Datakonsult AB
6 
7  Libkleopatra is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of the
10  License, or (at your option) any later version.
11 
12  Libkleopatra is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  In addition, as a special exception, the copyright holders give
22  permission to link the code of this program with any edition of
23  the TQt library by Trolltech AS, Norway (or with modified versions
24  of TQt that use the same license as TQt), and distribute linked
25  combinations including the two. You must obey the GNU General
26  Public License in all respects for all of the code used other than
27  TQt. If you modify this file, you may extend this exception to
28  your version of the file, but you are not obligated to do so. If
29  you do not wish to do so, delete this exception statement from
30  your version.
31 */
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 
37 #include "qgpgmerefreshkeysjob.h"
38 
39 #include "gnupgprocessbase.h"
40 #include "qgpgmeprogresstokenmapper.h"
41 
42 #include <kdebug.h>
43 
44 #include <gpgmepp/context.h>
45 
46 #include <qgpgme/eventloopinteractor.h>
47 
48 #include <tqstringlist.h>
49 
50 #include <gpg-error.h>
51 
52 #include <assert.h>
53 
54 Kleo::QGpgMERefreshKeysJob::QGpgMERefreshKeysJob()
55  : RefreshKeysJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMERefreshKeysJob" ),
56  mProcess( 0 ),
57  mError( 0 )
58 {
59 
60 }
61 
62 Kleo::QGpgMERefreshKeysJob::~QGpgMERefreshKeysJob() {
63 
64 }
65 
66 GpgME::Error Kleo::QGpgMERefreshKeysJob::start( const TQStringList & patterns ) {
67  assert( mPatternsToDo.empty() );
68 
69  mPatternsToDo = patterns;
70  if ( mPatternsToDo.empty() )
71  mPatternsToDo.push_back( " " ); // empty list means all -> mae
72  // sure to fail the first
73  // startAProcess() guard clause
74 
75  return startAProcess();
76 }
77 
78 #if MAX_CMD_LENGTH < 65 + 128
79 #error MAX_CMD_LENGTH is too low
80 #endif
81 
82 GpgME::Error Kleo::QGpgMERefreshKeysJob::startAProcess() {
83  if ( mPatternsToDo.empty() )
84  return 0;
85  // create and start gpgsm process:
86  mProcess = new GnuPGProcessBase( this, "gpgsm -k --with-validation --force-crl-refresh --enable-crl-checks" );
87 
88  // FIXME: obbtain the path to gpgsm from gpgme, so we use the same instance.
89  *mProcess << "gpgsm" << "-k" << "--with-validation" << "--force-crl-refresh"
90  << "--enable-crl-checks";
91  unsigned int commandLineLength = MAX_CMD_LENGTH;
92  commandLineLength -=
93  strlen("gpgsm") + 1 + strlen("-k") + 1 +
94  strlen("--with-validation") + 1 + strlen("--force-crl-refresh") + 1 +
95  strlen("--enable-crl-checks") + 1;
96  while ( !mPatternsToDo.empty() ) {
97  const TQCString pat = mPatternsToDo.front().utf8().stripWhiteSpace();
98  const unsigned int patLength = pat.length();
99  if ( patLength >= commandLineLength )
100  break;
101  mPatternsToDo.pop_front();
102  if ( pat.isEmpty() )
103  continue;
104  *mProcess << pat;
105  commandLineLength -= patLength + 1;
106  }
107 
108  mProcess->setUsetStatusFD( true );
109 
110  connect( mProcess, TQ_SIGNAL(processExited(TDEProcess*)),
111  TQ_SLOT(slotProcessExited(TDEProcess*)) );
112  connect( mProcess, TQ_SIGNAL(receivedStderr(TDEProcess*,char*,int)),
113  TQ_SLOT(slotStderr(TDEProcess*,char*,int)) );
114  connect( mProcess, TQ_SIGNAL(status(Kleo::GnuPGProcessBase*,const TQString&,const TQStringList&)),
115  TQ_SLOT(slotStatus(Kleo::GnuPGProcessBase*,const TQString&,const TQStringList&)) );
116 
117  if ( !mProcess->start( TDEProcess::NotifyOnExit, TDEProcess::Stderr ) ) {
118  mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_ENOENT ); // what else?
119  deleteLater();
120  return mError;
121  } else
122  return 0;
123 }
124 
125 void Kleo::QGpgMERefreshKeysJob::slotCancel() {
126  if ( mProcess )
127  mProcess->kill();
128  mProcess = 0;
129  mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_CANCELED );
130 }
131 
132 void Kleo::QGpgMERefreshKeysJob::slotStatus( GnuPGProcessBase * proc, const TQString & type, const TQStringList & args ) {
133  if ( proc != mProcess )
134  return;
135  TQStringList::const_iterator it = args.begin();
136  bool ok = false;
137 
138  if ( type == "ERROR" ) {
139 
140 
141  if ( args.size() < 2 ) {
142  kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() not recognising ERROR with < 2 args!" << endl;
143  return;
144  }
145  const int source = (*++it).toInt( &ok );
146  if ( !ok ) {
147  kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() expected number for first ERROR arg, got something else" << endl;
148  return;
149  }
150  ok = false;
151  const int code = (*++it).toInt( &ok );
152  if ( !ok ) {
153  kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() expected number for second ERROR arg, got something else" << endl;
154  return;
155  }
156  mError = gpg_err_make( (gpg_err_source_t)source, (gpg_err_code_t)code );
157 
158 
159  } else if ( type == "PROGRESS" ) {
160 
161 
162  if ( args.size() < 4 ) {
163  kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() not recognising PROGRESS with < 4 args!" << endl;
164  return;
165  }
166  const TQString what = *++it;
167  ++it; // don't use "type"...
168  const int cur = (*++it).toInt( &ok );
169  if ( !ok ) {
170  kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() expected number for \"cur\", got something else" << endl;
171  return;
172  }
173  ok = false;
174  const int total = (*++it).toInt( &ok );
175  if ( !ok ) {
176  kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() expected number for \"total\", got something else" << endl;
177  return;
178  }
179  emit progress( QGpgMEProgressTokenMapper::instance()->map( what, 0, cur, total ), cur, total );
180 
181 
182  }
183 }
184 
185 void Kleo::QGpgMERefreshKeysJob::slotStderr( TDEProcess *, char *, int ) {
186  // implement? or not?
187 }
188 
189 void Kleo::QGpgMERefreshKeysJob::slotProcessExited( TDEProcess * proc ) {
190  if ( proc != mProcess )
191  return;
192 
193  if ( !mError && !mPatternsToDo.empty() ) {
194  if ( const GpgME::Error err = startAProcess() ) {
195  mError = err;
196  }
197  else {
198  return;
199  }
200  }
201 
202  emit done();
203  if ( !mError &&
204  ( !mProcess->normalExit() || mProcess->exitStatus() != 0 ) )
205  mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_GENERAL );
206  emit result( mError );
207  deleteLater();
208 }
209 
210 #include "qgpgmerefreshkeysjob.moc"
a base class for GPG and GPGSM processes.