~ubuntu-branches/ubuntu/oneiric/kdepim/oneiric-updates

« back to all changes in this revision

Viewing changes to kleopatra/libkleopatraclient/core/command.cpp

  • Committer: Package Import Robot
  • Author(s): Philip Muškovac
  • Date: 2011-06-28 19:33:24 UTC
  • mfrom: (0.2.13) (0.1.13 sid)
  • Revision ID: package-import@ubuntu.com-20110628193324-8yvjs8sdv9rdoo6c
Tags: 4:4.7.0-0ubuntu1
* New upstream release
  - update install files
  - add missing kdepim-doc package to control file
  - Fix Vcs lines
  - kontact breaks/replaces korganizer << 4:4.6.80
  - tighten the dependency of kdepim-dev on libkdepim4 to fix lintian error

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
#include <QFile>
40
40
#include <QDebug>
41
41
#include <QDir>
 
42
#include <QProcess>
42
43
 
43
44
#include <assuan.h>
44
45
#include <gpg-error.h>
48
49
 
49
50
#include <algorithm>
50
51
#include <string>
 
52
#include <sstream>
51
53
 
52
54
using namespace KLEOPATRACLIENT_NAMESPACE;
53
55
using namespace boost;
94
96
}
95
97
#endif
96
98
 
97
 
static QByteArray hexencode( const QByteArray & in ) {
 
99
// changed from returning QByteArray to returning std::string
 
100
static std::string hexencode( const QByteArray & in ) {
98
101
    if ( in.isNull() )
99
 
        return QByteArray();
100
 
    const std::string result = hexencode( std::string( in.constData() ) );
101
 
    return QByteArray( result.data(), result.size() );
 
102
        return std::string();
 
103
    return hexencode( std::string( in.data(), in.size() ) );
102
104
}
103
105
// end copied from kleopatra/utils/hex.cpp
104
106
 
188
190
void Command::setOptionValue( const char * name, const QVariant & value, bool critical ) {
189
191
    if ( !name || !*name )
190
192
        return;
191
 
    const QMutexLocker locker( &d->mutex );
192
193
    const Private::Option opt = {
193
194
        value,
194
195
        true,
195
196
        critical
196
197
    };
 
198
    const QMutexLocker locker( &d->mutex );
197
199
    d->inputs.options[name] = opt;
198
200
}
199
201
 
259
261
    return d->inputs.filePaths;
260
262
}
261
263
 
 
264
 
 
265
void Command::setRecipients( const QStringList & recipients, bool informative ) {
 
266
    const QMutexLocker locker( &d->mutex );
 
267
    d->inputs.recipients = recipients;
 
268
    d->inputs.areRecipientsInformative = informative;
 
269
}
 
270
 
 
271
QStringList Command::recipients() const {
 
272
    const QMutexLocker locker( &d->mutex );
 
273
    return d->inputs.recipients;
 
274
}
 
275
 
 
276
bool Command::areRecipientsInformative() const {
 
277
    const QMutexLocker locker( &d->mutex );
 
278
    return d->inputs.areRecipientsInformative;
 
279
}
 
280
 
 
281
 
 
282
void Command::setSenders( const QStringList & senders, bool informative ) {
 
283
    const QMutexLocker locker( &d->mutex );
 
284
    d->inputs.senders = senders;
 
285
    d->inputs.areSendersInformative = informative;
 
286
}
 
287
 
 
288
QStringList Command::senders() const {
 
289
    const QMutexLocker locker( &d->mutex );
 
290
    return d->inputs.senders;
 
291
}
 
292
 
 
293
bool Command::areSendersInformative() const {
 
294
    const QMutexLocker locker( &d->mutex );
 
295
    return d->inputs.areSendersInformative;
 
296
}
 
297
 
 
298
 
 
299
void Command::setInquireData( const char * what, const QByteArray & data ) {
 
300
    const QMutexLocker locker( &d->mutex );
 
301
    d->inputs.inquireData[what] = data;
 
302
}
 
303
 
 
304
void Command::unsetInquireData( const char * what ) {
 
305
    const QMutexLocker locker( &d->mutex );
 
306
    d->inputs.inquireData.erase( what );
 
307
}
 
308
 
 
309
QByteArray Command::inquireData( const char * what ) const {
 
310
    const QMutexLocker locker( &d->mutex );
 
311
    const std::map<std::string,QByteArray>::const_iterator it = d->inputs.inquireData.find( what );
 
312
    if ( it == d->inputs.inquireData.end() )
 
313
        return QByteArray();
 
314
    else
 
315
        return it->second;
 
316
}
 
317
 
 
318
bool Command::isInquireDataSet( const char * what ) const {
 
319
    const QMutexLocker locker( &d->mutex );
 
320
    const std::map<std::string,QByteArray>::const_iterator it = d->inputs.inquireData.find( what );
 
321
    return it != d->inputs.inquireData.end();
 
322
}
 
323
 
 
324
 
262
325
QByteArray Command::receivedData() const {
263
326
    const QMutexLocker locker( &d->mutex );
264
327
    return d->outputs.data;
279
342
// here comes the ugly part
280
343
//
281
344
 
 
345
#ifdef HAVE_ASSUAN2
 
346
static void my_assuan_release( assuan_context_t ctx ) {
 
347
    if ( ctx )
 
348
        assuan_release( ctx );
 
349
}
 
350
#endif
 
351
 
282
352
typedef shared_ptr< remove_pointer<assuan_context_t>::type > AssuanContextBase;
283
353
namespace {
284
354
    struct AssuanClientContext : AssuanContextBase {
285
355
        AssuanClientContext() : AssuanContextBase() {}
 
356
#ifndef HAVE_ASSUAN2
286
357
        explicit AssuanClientContext( assuan_context_t ctx ) : AssuanContextBase( ctx, &assuan_disconnect ) {}
287
358
        void reset( assuan_context_t ctx=0 ) { AssuanContextBase::reset( ctx, &assuan_disconnect ); }
 
359
#else
 
360
        explicit AssuanClientContext( assuan_context_t ctx ) : AssuanContextBase( ctx, &my_assuan_release ) {}
 
361
        void reset( assuan_context_t ctx=0 ) { AssuanContextBase::reset( ctx, &my_assuan_release ); }
 
362
#endif
288
363
    };
289
364
}
290
365
 
 
366
#ifdef HAVE_ASSUAN2
 
367
// compatibility typedef - remove when we require assuan v2...
 
368
typedef gpg_error_t assuan_error_t;
 
369
#endif
 
370
 
291
371
static assuan_error_t
292
372
my_assuan_transact( const AssuanClientContext & ctx,
293
373
                    const char *command,
333
413
    return name;
334
414
}
335
415
 
 
416
static QString uiserver_executable() {
 
417
    return QLatin1String( "kleopatra" );
 
418
}
 
419
 
336
420
static QString start_uiserver() {
337
 
    return Command::tr("start_uiserver: not yet implemented");
 
421
    if ( !QProcess::startDetached( uiserver_executable(), QStringList() << QLatin1String( "--daemon" ) ) )
 
422
        return Command::tr( "Failed to start uiserver %1" ).arg( uiserver_executable() );
 
423
    else
 
424
        return QString();
338
425
}
339
426
 
340
427
static assuan_error_t getinfo_pid_cb( void * opaque, const void * buffer, size_t length ) {
349
436
    return 0;
350
437
}
351
438
 
 
439
namespace {
 
440
    struct inquire_data {
 
441
        const std::map<std::string,QByteArray> * map;
 
442
        const AssuanClientContext * ctx;
 
443
    };
 
444
}
 
445
 
 
446
static assuan_error_t command_inquire_cb( void * opaque, const char * what ) {
 
447
    if ( !opaque )
 
448
        return 0;
 
449
    const inquire_data & id = *static_cast<const inquire_data*>( opaque );
 
450
    const std::map<std::string,QByteArray>::const_iterator it = id.map->find( what );
 
451
    if ( it != id.map->end() ) {
 
452
        const QByteArray & v = it->second;
 
453
        assuan_send_data( id.ctx->get(), v.data(), v.size() );
 
454
    }
 
455
    return 0;
 
456
}
 
457
 
 
458
static inline std::ostream & operator<<( std::ostream & s, const QByteArray & ba ) {
 
459
    return s << std::string( ba.data(), ba.size() );
 
460
}
 
461
 
352
462
static assuan_error_t send_option( const AssuanClientContext & ctx, const char * name, const QVariant & value ) {
 
463
    std::stringstream ss;
 
464
    ss << "OPTION " << name;
353
465
    if ( value.isValid() )
354
 
        return my_assuan_transact( ctx, QString().sprintf( "OPTION %s=%s", name, value.toString().toUtf8().constData() ).toUtf8().constData() );
355
 
    else
356
 
        return my_assuan_transact( ctx, QString().sprintf( "OPTION %s", name ).toUtf8().constData() );
 
466
        ss << '=' << value.toString().toUtf8();
 
467
    return my_assuan_transact( ctx, ss.str().c_str() );
357
468
}
358
469
 
359
470
static assuan_error_t send_file( const AssuanClientContext & ctx, const QString & file ) {
360
 
    return my_assuan_transact( ctx, QString().sprintf( "FILE %s", hexencode( QFile::encodeName( file ) ).constData() ).toUtf8().constData() );
 
471
    std::stringstream ss;
 
472
    ss << "FILE " << hexencode( QFile::encodeName( file ) );
 
473
    return my_assuan_transact( ctx, ss.str().c_str() );
 
474
}
 
475
 
 
476
static assuan_error_t send_recipient( const AssuanClientContext & ctx, const QString & recipient, bool info ) {
 
477
    std::stringstream ss;
 
478
    ss << "RECIPIENT ";
 
479
    if ( info )
 
480
        ss << "--info ";
 
481
    ss << "--" << hexencode( recipient.toUtf8() );
 
482
    return my_assuan_transact( ctx, ss.str().c_str() );
 
483
}
 
484
 
 
485
static assuan_error_t send_sender( const AssuanClientContext & ctx, const QString & sender, bool info ) {
 
486
    std::stringstream ss;
 
487
    ss << "SENDER ";
 
488
    if ( info )
 
489
        ss << "--info ";
 
490
    ss << "--" << hexencode( sender.toUtf8() );
 
491
    return my_assuan_transact( ctx, ss.str().c_str() );
361
492
}
362
493
 
363
494
void Command::Private::run() {
373
504
 
374
505
    out.canceled = false;
375
506
 
376
 
    assuan_error_t err = 0;
 
507
    if ( out.serverLocation.isEmpty() )
 
508
        out.serverLocation = default_socket_name();
377
509
 
 
510
#ifndef HAVE_ASSUAN2
378
511
    assuan_context_t naked_ctx = 0;
 
512
#endif
379
513
    AssuanClientContext ctx;
 
514
    assuan_error_t err = 0;
380
515
 
381
 
    if ( out.serverLocation.isEmpty() )
382
 
        out.serverLocation = default_socket_name();
 
516
    inquire_data id = { &in.inquireData, &ctx };
383
517
 
384
518
    const QString socketName = out.serverLocation;
385
519
    if ( socketName.isEmpty() ) {
387
521
        goto leave;
388
522
    }
389
523
 
 
524
#ifndef HAVE_ASSUAN2
390
525
    err = assuan_socket_connect( &naked_ctx, QFile::encodeName( socketName ).constData(), -1 );
 
526
#else
 
527
    {
 
528
        assuan_context_t naked_ctx = 0;
 
529
        err = assuan_new( &naked_ctx );
 
530
        if ( err ) {
 
531
            out.errorString = tr( "Could not allocate resources to connect to Kleopatra UI server at %1: %2" )
 
532
                .arg( socketName, to_error_string( err ) );
 
533
            goto leave;
 
534
        }
 
535
 
 
536
        ctx.reset( naked_ctx );
 
537
    }
 
538
 
 
539
 
 
540
    err = assuan_socket_connect( ctx.get(), QFile::encodeName( socketName ).constData(), -1, 0 );
 
541
#endif
391
542
    if ( err ) {
392
543
        qDebug( "UI server not running, starting it" );
393
544
        
400
551
        // give it a bit of time to start up and try a couple of times
401
552
        for ( int i = 0 ; err && i < 20 ; ++i ) {
402
553
            msleep( 500 );
 
554
#ifndef HAVE_ASSUAN2
403
555
            err = assuan_socket_connect( &naked_ctx, QFile::encodeName( socketName ).constData(), -1 );
 
556
#else
 
557
            err = assuan_socket_connect( ctx.get(), QFile::encodeName( socketName ).constData(), -1, 0 );
 
558
#endif
404
559
        }
405
560
    }
406
561
 
410
565
        goto leave;
411
566
    }
412
567
 
 
568
#ifndef HAVE_ASSUAN2
413
569
    ctx.reset( naked_ctx );
414
570
    naked_ctx = 0;
 
571
#endif
415
572
 
416
573
    out.serverPid = -1;
417
574
    err = my_assuan_transact( ctx, "GETINFO pid", &getinfo_pid_cb, &out.serverPid );
423
580
 
424
581
    qDebug() << "Server PID =" << out.serverPid;
425
582
 
426
 
#ifdef Q_OS_WIN
 
583
#if defined(Q_OS_WIN) && !defined(_WIN32_WCE) 
427
584
    if ( !AllowSetForegroundWindow( (pid_t)out.serverPid ) )
428
585
        qDebug() << "AllowSetForegroundWindow(" << out.serverPid << ") failed: " << GetLastError();
429
586
#endif
432
589
        goto leave;
433
590
 
434
591
    if ( in.parentWId ) {
435
 
#ifdef Q_OS_WIN32
 
592
#if defined(Q_OS_WIN32) || defined(_WIN32_WCE)
436
593
        err = send_option( ctx, "window-id", QString().sprintf( "%lx", reinterpret_cast<unsigned long>( in.parentWId ) ) );
437
594
#else
438
595
        err = send_option( ctx, "window-id", QString().sprintf( "%lx", static_cast<unsigned long>( in.parentWId ) ) );
459
616
            goto leave;
460
617
        }
461
618
 
 
619
    Q_FOREACH( const QString & sender, in.senders )
 
620
        if ( ( err = send_sender( ctx, sender, in.areSendersInformative ) ) ) {
 
621
            out.errorString = tr("Failed to send sender %1: %2")
 
622
                .arg( sender, to_error_string( err ) );
 
623
            goto leave;
 
624
        }
 
625
 
 
626
    Q_FOREACH( const QString & recipient, in.recipients )
 
627
        if ( ( err = send_recipient( ctx, recipient, in.areRecipientsInformative ) ) ) {
 
628
            out.errorString = tr("Failed to send recipient %1: %2")
 
629
                .arg( recipient, to_error_string( err ) );
 
630
            goto leave;
 
631
        }
 
632
 
462
633
#if 0
463
634
    setup I/O;
464
635
#endif
465
636
 
466
 
    err = my_assuan_transact( ctx, in.command.constData(), &command_data_cb, &out.data );
 
637
    err = my_assuan_transact( ctx, in.command.constData(), &command_data_cb, &out.data, &command_inquire_cb, &id );
467
638
    if ( err ) {
468
639
        if ( gpg_err_code( err ) == GPG_ERR_CANCELED )
469
640
            out.canceled = true;