signal() and init()
authorvb
Sat, 21 Feb 2015 16:55:43 +0100
changeset 62ad5e484720e1
parent 61 475c948f8aa2
child 63 f5b2641f4ae7
signal() and init()
src/cryptotech.c
src/cryptotech.h
src/etpan_mime.c
src/message_api.c
src/mime.c
src/pEpEngine.c
src/pEpEngine.h
src/pEp_internal.h
src/pgp_gpg.c
src/pgp_gpg.h
src/pgp_gpg_internal.h
src/transport.c
     1.1 --- a/src/cryptotech.c	Tue Feb 10 08:27:36 2015 -0500
     1.2 +++ b/src/cryptotech.c	Sat Feb 21 16:55:43 2015 +0100
     1.3 @@ -10,45 +10,47 @@
     1.4  #include <memory.h>
     1.5  #include <assert.h>
     1.6  
     1.7 -PEP_STATUS init_cryptotech(PEP_SESSION session)
     1.8 +PEP_STATUS init_cryptotech(PEP_SESSION session, bool in_first)
     1.9  {
    1.10 -    pEpSession *_session = (pEpSession *) session;
    1.11 -    PEP_cryptotech_t *cryptotech = _session->cryptotech;
    1.12 +    static PEP_cryptotech_t cryptotech[PEP_crypt__count];
    1.13      PEP_STATUS _status;
    1.14  
    1.15      assert(PEP_crypt__count == 2);
    1.16 -    memset(cryptotech, 0, sizeof(PEP_cryptotech_t) * PEP_crypt__count);
    1.17  
    1.18 -    cryptotech[PEP_crypt_none].id = PEP_crypt_none;
    1.19 -    cryptotech[PEP_crypt_none].unconfirmed_comm_type = PEP_ct_no_encryption;
    1.20 -    cryptotech[PEP_crypt_none].confirmed_comm_type = PEP_ct_no_encryption;
    1.21 +    if (in_first) {
    1.22 +        memset(cryptotech, 0, sizeof(PEP_cryptotech_t) * PEP_crypt__count);
    1.23  
    1.24 -    _status = pgp_init(_session);
    1.25 -    assert(_status == PEP_STATUS_OK);
    1.26 -    if (_status != PEP_STATUS_OK) {
    1.27 -        free(_session);
    1.28 -        return _status;
    1.29 +        cryptotech[PEP_crypt_none].id = PEP_crypt_none;
    1.30 +        cryptotech[PEP_crypt_none].unconfirmed_comm_type = PEP_ct_no_encryption;
    1.31 +        cryptotech[PEP_crypt_none].confirmed_comm_type = PEP_ct_no_encryption;
    1.32 +
    1.33 +        cryptotech[PEP_crypt_OpenPGP].id = PEP_crypt_OpenPGP;
    1.34 +        cryptotech[PEP_crypt_OpenPGP].unconfirmed_comm_type = PEP_ct_OpenPGP_unconfirmed;
    1.35 +        cryptotech[PEP_crypt_OpenPGP].confirmed_comm_type = PEP_ct_OpenPGP;
    1.36 +        cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify = pgp_decrypt_and_verify;
    1.37 +        cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign = pgp_encrypt_and_sign;
    1.38 +        cryptotech[PEP_crypt_OpenPGP].verify_text = pgp_verify_text;
    1.39 +        cryptotech[PEP_crypt_OpenPGP].delete_keypair = pgp_delete_keypair;
    1.40 +        cryptotech[PEP_crypt_OpenPGP].export_key = pgp_export_key;
    1.41 +        cryptotech[PEP_crypt_OpenPGP].find_keys = pgp_find_keys;
    1.42 +        cryptotech[PEP_crypt_OpenPGP].generate_keypair = pgp_generate_keypair;
    1.43 +        cryptotech[PEP_crypt_OpenPGP].get_key_rating = pgp_get_key_rating;
    1.44 +        cryptotech[PEP_crypt_OpenPGP].import_key = pgp_import_key;
    1.45 +        cryptotech[PEP_crypt_OpenPGP].recv_key = pgp_recv_key;
    1.46 +        cryptotech[PEP_crypt_OpenPGP].send_key = pgp_send_key;
    1.47      }
    1.48  
    1.49 -    cryptotech[PEP_crypt_OpenPGP].id = PEP_crypt_OpenPGP;
    1.50 -    cryptotech[PEP_crypt_OpenPGP].unconfirmed_comm_type = PEP_ct_OpenPGP_unconfirmed;
    1.51 -    cryptotech[PEP_crypt_OpenPGP].confirmed_comm_type = PEP_ct_OpenPGP;
    1.52 -    cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify = pgp_decrypt_and_verify;
    1.53 -    cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign = pgp_encrypt_and_sign;
    1.54 -    cryptotech[PEP_crypt_OpenPGP].verify_text = pgp_verify_text;
    1.55 -    cryptotech[PEP_crypt_OpenPGP].delete_keypair = pgp_delete_keypair;
    1.56 -    cryptotech[PEP_crypt_OpenPGP].export_key = pgp_export_key;
    1.57 -    cryptotech[PEP_crypt_OpenPGP].find_keys = pgp_find_keys;
    1.58 -    cryptotech[PEP_crypt_OpenPGP].generate_keypair = pgp_generate_keypair;
    1.59 -    cryptotech[PEP_crypt_OpenPGP].get_key_rating = pgp_get_key_rating;
    1.60 -    cryptotech[PEP_crypt_OpenPGP].import_key = pgp_import_key;
    1.61 -    cryptotech[PEP_crypt_OpenPGP].recv_key = pgp_recv_key;
    1.62 -    cryptotech[PEP_crypt_OpenPGP].send_key = pgp_send_key;
    1.63 +    session->cryptotech = cryptotech;
    1.64 +
    1.65 +    _status = pgp_init(session, in_first);
    1.66 +    assert(_status == PEP_STATUS_OK);
    1.67 +    if (_status != PEP_STATUS_OK)
    1.68 +        return _status;
    1.69  
    1.70      return PEP_STATUS_OK;
    1.71  }
    1.72  
    1.73 -void release_cryptotech(PEP_SESSION session)
    1.74 +void release_cryptotech(PEP_SESSION session, bool out_last)
    1.75  {
    1.76 -    pgp_release(session);
    1.77 +    pgp_release(session, out_last);
    1.78  }
     2.1 --- a/src/cryptotech.h	Tue Feb 10 08:27:36 2015 -0500
     2.2 +++ b/src/cryptotech.h	Sat Feb 21 16:55:43 2015 +0100
     2.3 @@ -73,5 +73,5 @@
     2.4  
     2.5  typedef uint64_t cryptotech_mask;
     2.6  
     2.7 -PEP_STATUS init_cryptotech(PEP_SESSION session);
     2.8 -void release_cryptotech(PEP_SESSION session);
     2.9 +PEP_STATUS init_cryptotech(PEP_SESSION session, bool in_first);
    2.10 +void release_cryptotech(PEP_SESSION session, bool out_last);
     3.1 --- a/src/etpan_mime.c	Tue Feb 10 08:27:36 2015 -0500
     3.2 +++ b/src/etpan_mime.c	Sat Feb 21 16:55:43 2015 +0100
     3.3 @@ -3,6 +3,9 @@
     3.4  #include <unistd.h>
     3.5  
     3.6  #include "etpan_mime.h"
     3.7 +#ifndef mailmime_param_new_with_data
     3.8 +#include <libetpan/mailprivacy_tools.h>
     3.9 +#endif
    3.10  
    3.11  #define MAX_MESSAGE_ID 512
    3.12  
     4.1 --- a/src/message_api.c	Tue Feb 10 08:27:36 2015 -0500
     4.2 +++ b/src/message_api.c	Sat Feb 21 16:55:43 2015 +0100
     4.3 @@ -1,16 +1,31 @@
     4.4  #include "message_api.h"
     4.5  #include "keymanagement.h"
     4.6 +#include "mime.h"
     4.7  
     4.8 -#include <libetpan/mailmime.h>
     4.9 -#ifndef mailmime_param_new_with_data
    4.10 -#include <libetpan/mailprivacy_tools.h>
    4.11 -#endif
    4.12  #include <assert.h>
    4.13  #include <string.h>
    4.14  #include <stdlib.h>
    4.15  
    4.16  #define NOT_IMPLEMENTED assert(0);
    4.17  
    4.18 +static char * combine_short_and_long(const message * src)
    4.19 +{
    4.20 +    char * ptext;
    4.21 +    assert(src);
    4.22 +    assert(src->shortmsg && src->longmsg && strcmp(src->shortmsg, "pEp") != 0);
    4.23 +
    4.24 +    ptext = calloc(1, strlen(src->shortmsg) + strlen(src->longmsg)
    4.25 +            + 12);
    4.26 +    if (ptext == NULL)
    4.27 +        return NULL;
    4.28 +
    4.29 +    strcpy(ptext, "subject: ");
    4.30 +    strcat(ptext, src->shortmsg);
    4.31 +    strcat(ptext, "\n\n");
    4.32 +    strcat(ptext, src->longmsg);
    4.33 +
    4.34 +    return ptext;
    4.35 +}
    4.36  
    4.37  DYNAMIC_API PEP_STATUS encrypt_message(
    4.38          PEP_SESSION session,
    4.39 @@ -101,27 +116,64 @@
    4.40  
    4.41          switch (format) {
    4.42          case PEP_enc_MIME_multipart: {
    4.43 -            message *interim;
    4.44 -//            status = mime_encode_parts(src, &interim);
    4.45 -//            assert(status == PEP_STATUS_OK);
    4.46 -//            if (status != PEP_STATUS_OK)
    4.47 -//                break;
    4.48 +            char *resulttext;
    4.49 +            bool free_ptext = false;
    4.50              msg->enc_format = PEP_enc_MIME_multipart;
    4.51 -        }
    4.52  
    4.53 -        case PEP_enc_pieces:
    4.54              if (src->shortmsg && src->longmsg && strcmp(src->shortmsg, "pEp") != 0) {
    4.55 -                ptext = calloc(1, strlen(src->shortmsg) + strlen(src->longmsg)
    4.56 -                        + 12);
    4.57 +                ptext = combine_short_and_long(src);
    4.58                  if (ptext == NULL) {
    4.59                      free_message(msg);
    4.60                      free_stringlist(keys);
    4.61                      return PEP_OUT_OF_MEMORY;
    4.62                  }
    4.63 -                strcpy(ptext, "subject: ");
    4.64 -                strcat(ptext, src->shortmsg);
    4.65 -                strcat(ptext, "\n\n");
    4.66 -                strcat(ptext, src->longmsg);
    4.67 +                free_ptext = true;
    4.68 +            }
    4.69 +            else if (src->longmsg) {
    4.70 +                ptext = src->longmsg;
    4.71 +            }
    4.72 +            else {
    4.73 +                ptext = NULL;
    4.74 +            }
    4.75 +
    4.76 +            // TO EXTEND: we only support HTML yet
    4.77 +            assert(src->format == PEP_format_plain
    4.78 +                    || src->format == PEP_format_html);
    4.79 +
    4.80 +            status = mime_encode_text(ptext, src->longmsg_formatted,
    4.81 +                    src->attachments, &resulttext);
    4.82 +            assert(status == PEP_STATUS_OK);
    4.83 +            if (free_ptext)
    4.84 +                free(ptext);
    4.85 +            assert(resulttext);
    4.86 +            if (resulttext == NULL) {
    4.87 +                free_message(msg);
    4.88 +                free_stringlist(keys);
    4.89 +                return status;
    4.90 +            }
    4.91 +            
    4.92 +            status = encrypt_and_sign(session, keys, resulttext, strlen(resulttext),
    4.93 +                    &ctext, &csize);
    4.94 +            free(resulttext);
    4.95 +            free_stringlist(keys);
    4.96 +            if (ctext) {
    4.97 +                msg->longmsg = strdup(ctext);
    4.98 +                msg->shortmsg = strdup("pEp");
    4.99 +                if (!(msg->longmsg && msg->shortmsg)) {
   4.100 +                    free_message(msg);
   4.101 +                    return PEP_OUT_OF_MEMORY;
   4.102 +                }
   4.103 +            }
   4.104 +        }
   4.105 +
   4.106 +        case PEP_enc_pieces:
   4.107 +            if (src->shortmsg && src->longmsg && strcmp(src->shortmsg, "pEp") != 0) {
   4.108 +                ptext = combine_short_and_long(src);
   4.109 +                if (ptext == NULL) {
   4.110 +                    free_message(msg);
   4.111 +                    free_stringlist(keys);
   4.112 +                    return PEP_OUT_OF_MEMORY;
   4.113 +                }
   4.114                  status = encrypt_and_sign(session, keys, ptext, strlen(ptext),
   4.115                          &ctext, &csize);
   4.116                  free(ptext);
   4.117 @@ -129,12 +181,14 @@
   4.118                      msg->longmsg = strdup(ctext);
   4.119                      msg->shortmsg = strdup("pEp");
   4.120                      if (!(msg->longmsg && msg->shortmsg)) {
   4.121 +                        free_stringlist(keys);
   4.122                          free_message(msg);
   4.123                          return PEP_OUT_OF_MEMORY;
   4.124                      }
   4.125                  }
   4.126                  else {
   4.127                      free_message(msg);
   4.128 +                    free_stringlist(keys);
   4.129                      msg = NULL;
   4.130                  }
   4.131              }
   4.132 @@ -156,6 +210,7 @@
   4.133                      msg->shortmsg = strdup("pEp");
   4.134                      if (!(msg->longmsg && msg->shortmsg)) {
   4.135                          free_message(msg);
   4.136 +                        free_stringlist(keys);
   4.137                          return PEP_OUT_OF_MEMORY;
   4.138                      }
   4.139                  }
     5.1 --- a/src/mime.c	Tue Feb 10 08:27:36 2015 -0500
     5.2 +++ b/src/mime.c	Sat Feb 21 16:55:43 2015 +0100
     5.3 @@ -1,6 +1,6 @@
     5.4  #include "mime.h"
     5.5  
     5.6 -#include <libetpan/libetpan.h>
     5.7 +#include <libetpan/mailmime.h>
     5.8  #include <string.h>
     5.9  #include <stdlib.h>
    5.10  #include <assert.h>
    5.11 @@ -179,8 +179,14 @@
    5.12  
    5.13      errno = 0;
    5.14      rewind(file);
    5.15 +
    5.16      assert(errno == 0);
    5.17 -    clearerr(file);
    5.18 +    switch (errno) {
    5.19 +        case ENOMEM:
    5.20 +            goto enomem;
    5.21 +        default:
    5.22 +            goto err_file;
    5.23 +    }
    5.24  
    5.25      buf = calloc(1, size + 1);
    5.26      assert(buf);
    5.27 @@ -190,15 +196,23 @@
    5.28      char *_buf = buf;
    5.29      size_t rest = size;
    5.30      for (size_t bytes_read = 0; rest > 0; rest -= bytes_read, _buf += rest) {
    5.31 -        assert(feof(file) == 0);
    5.32 +        clearerr(file);
    5.33 +        bytes_read = rest * fread(_buf, rest, 1, file);
    5.34 +
    5.35 +        assert(ferror(file) == 0 || ferror(file) == EINTR);
    5.36 +        if (ferror(file) != 0 && ferror(file) != EINTR)
    5.37 +            goto err_file;
    5.38 +
    5.39 +        assert(!feof(file));
    5.40          if (feof(file))
    5.41              goto err_file;
    5.42 -        bytes_read = rest * fread(_buf, rest, 1, file);
    5.43 -        if (ferror(file))
    5.44 -            goto err_file;
    5.45      }
    5.46  
    5.47 -    fclose(file);
    5.48 +    do {
    5.49 +        r = fclose(file);
    5.50 +    } while (r == -1 && errno == EINTR);
    5.51 +    assert(r == 0);
    5.52 +
    5.53      mailmime_free(mime);
    5.54      *resulttext = buf;
    5.55      return PEP_STATUS_OK;
    5.56 @@ -218,10 +232,18 @@
    5.57      free(buf);
    5.58      free(template);
    5.59  
    5.60 -    if (file)
    5.61 -        fclose(file);
    5.62 -    else if (fd != -1)
    5.63 -        close(fd);
    5.64 +    if (file) {
    5.65 +        do {
    5.66 +            r = fclose(file);
    5.67 +        } while (r == -1 && errno == EINTR);
    5.68 +        assert(r == 0);
    5.69 +    }
    5.70 +    else if (fd != -1) {
    5.71 +        do {
    5.72 +            r = close(fd);
    5.73 +        } while (r == -1 && errno == EINTR);
    5.74 +        assert(r == 0);
    5.75 +    }
    5.76  
    5.77      if (mime)
    5.78          mailmime_free(mime);
     6.1 --- a/src/pEpEngine.c	Tue Feb 10 08:27:36 2015 -0500
     6.2 +++ b/src/pEpEngine.c	Sat Feb 21 16:55:43 2015 +0100
     6.3 @@ -2,21 +2,32 @@
     6.4  #include "cryptotech.h"
     6.5  #include "transport.h"
     6.6  
     6.7 +int init_count = -1;
     6.8 +
     6.9  DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
    6.10  {
    6.11  	int int_result;
    6.12 -	const char *sql_log;
    6.13 -	const char *sql_safeword;
    6.14 -	const char *sql_get_identity;
    6.15 -	const char *sql_set_person;
    6.16 -	const char *sql_set_pgp_keypair;
    6.17 -	const char *sql_set_identity;
    6.18 -	const char *sql_set_trust;
    6.19 -    const char *sql_get_trust;
    6.20 +	static const char *sql_log;
    6.21 +	static const char *sql_safeword;
    6.22 +	static const char *sql_get_identity;
    6.23 +	static const char *sql_set_person;
    6.24 +	static const char *sql_set_pgp_keypair;
    6.25 +	static const char *sql_set_identity;
    6.26 +	static const char *sql_set_trust;
    6.27 +    static const char *sql_get_trust;
    6.28 +    bool in_first = false;
    6.29  
    6.30 -	assert(sqlite3_threadsafe());
    6.31 -	if (!sqlite3_threadsafe())
    6.32 -		return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
    6.33 +    assert(sqlite3_threadsafe());
    6.34 +    if (!sqlite3_threadsafe())
    6.35 +        return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
    6.36 +
    6.37 +    // a little race condition - but still a race condition
    6.38 +    // removed by calling caveat (see documentation)
    6.39 +
    6.40 +    ++init_count;
    6.41 +    if (init_count == 0) {
    6.42 +        in_first = true;
    6.43 +    }
    6.44  
    6.45  	assert(session);
    6.46  	*session = NULL;
    6.47 @@ -25,16 +36,11 @@
    6.48  	assert(_session);
    6.49  	if (_session == NULL)
    6.50  		return PEP_OUT_OF_MEMORY;
    6.51 -	
    6.52 +
    6.53  	_session->version = PEP_ENGINE_VERSION;
    6.54  
    6.55 -    init_cryptotech(_session);
    6.56 -    init_transport_system(_session);
    6.57 -    
    6.58      assert(LOCAL_DB);
    6.59      if (LOCAL_DB == NULL) {
    6.60 -        release_transport_system(_session);
    6.61 -        release_cryptotech(_session);
    6.62          free(_session);
    6.63          return PEP_INIT_CANNOT_OPEN_DB;
    6.64      }
    6.65 @@ -51,8 +57,6 @@
    6.66  
    6.67  	if (int_result != SQLITE_OK) {
    6.68  		sqlite3_close_v2(_session->db);
    6.69 -        release_transport_system(_session);
    6.70 -        release_cryptotech(_session);
    6.71          free(_session);
    6.72  		return PEP_INIT_CANNOT_OPEN_DB;
    6.73  	}
    6.74 @@ -62,8 +66,6 @@
    6.75      assert(SYSTEM_DB);
    6.76      if (SYSTEM_DB == NULL) {
    6.77  		sqlite3_close_v2(_session->db);
    6.78 -        release_transport_system(_session);
    6.79 -        release_cryptotech(_session);
    6.80          free(_session);
    6.81  		return PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
    6.82      }
    6.83 @@ -79,138 +81,148 @@
    6.84  	if (int_result != SQLITE_OK) {
    6.85  		sqlite3_close_v2(_session->system_db);
    6.86  		sqlite3_close_v2(_session->db);
    6.87 -        release_transport_system(_session);
    6.88 -        release_cryptotech(_session);
    6.89          free(_session);
    6.90  		return PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
    6.91  	}
    6.92  
    6.93  	sqlite3_busy_timeout(_session->system_db, 1000);
    6.94  
    6.95 -	int_result = sqlite3_exec(
    6.96 -		_session->db,
    6.97 -			"create table if not exists version_info ("
    6.98 -			"	id integer primary key,"
    6.99 -			"	timestamp integer default (datetime('now')) ,"
   6.100 -			"	version text,"
   6.101 -			"	comment text"
   6.102 -			");"
   6.103 -			"create table if not exists log ("
   6.104 -			"	timestamp integer default (datetime('now')) ,"
   6.105 -			"	title text not null,"
   6.106 -			"	entity text not null,"
   6.107 -			"	description text,"
   6.108 -			"	comment text"
   6.109 -			");"
   6.110 -			"create index if not exists log_timestamp on log ("
   6.111 -			"	timestamp"
   6.112 -			");"
   6.113 -			"create table if not exists pgp_keypair ("
   6.114 -			"	fpr text primary key,"
   6.115 -			"	public_id text unique,"
   6.116 -			"   private_id text,"
   6.117 -			"	created integer,"
   6.118 -			"	expires integer,"
   6.119 -			"	comment text"
   6.120 -			");"
   6.121 -            "create index if not exists pgp_keypair_expires on pgp_keypair ("
   6.122 -			"	expires"
   6.123 -			");"
   6.124 -			"create table if not exists person ("
   6.125 -			"	id text primary key,"
   6.126 -			"	username text not null,"
   6.127 -			"	main_key_id text"
   6.128 -			"		references pgp_keypair (fpr)"
   6.129 -			"		on delete set null,"
   6.130 -			"   lang text,"
   6.131 -			"	comment text"
   6.132 -			");"
   6.133 -			"create table if not exists identity ("
   6.134 -			"	address text primary key,"
   6.135 -			"	user_id text"
   6.136 -			"		references person (id)"
   6.137 -			"		on delete cascade,"
   6.138 -			"	main_key_id text"
   6.139 -			"		references pgp_keypair (fpr)"
   6.140 -			"		on delete set null,"
   6.141 -			"	comment text"
   6.142 -			");"
   6.143 -            "create table if not exists trust ("
   6.144 -            "   user_id text not null"
   6.145 -            "       references person (id)"
   6.146 -			"		on delete cascade,"
   6.147 -            "   pgp_keypair_fpr text not null"
   6.148 -            "       references pgp_keypair (fpr)"
   6.149 -            "       on delete cascade,"
   6.150 -            "   comm_type integer not null,"
   6.151 -			"	comment text"
   6.152 -            ");"
   6.153 -            "create unique index if not exists trust_index on trust ("
   6.154 -            "   user_id,"
   6.155 -            "   pgp_keypair_fpr"
   6.156 -            ");",
   6.157 -		NULL,
   6.158 -		NULL,
   6.159 -		NULL
   6.160 -	);
   6.161 -	assert(int_result == SQLITE_OK);
   6.162 +    if (in_first) {
   6.163 +        int_result = sqlite3_exec(
   6.164 +            _session->db,
   6.165 +                "create table if not exists version_info ("
   6.166 +                "	id integer primary key,"
   6.167 +                "	timestamp integer default (datetime('now')) ,"
   6.168 +                "	version text,"
   6.169 +                "	comment text"
   6.170 +                ");"
   6.171 +                "create table if not exists log ("
   6.172 +                "	timestamp integer default (datetime('now')) ,"
   6.173 +                "	title text not null,"
   6.174 +                "	entity text not null,"
   6.175 +                "	description text,"
   6.176 +                "	comment text"
   6.177 +                ");"
   6.178 +                "create index if not exists log_timestamp on log ("
   6.179 +                "	timestamp"
   6.180 +                ");"
   6.181 +                "create table if not exists pgp_keypair ("
   6.182 +                "	fpr text primary key,"
   6.183 +                "	public_id text unique,"
   6.184 +                "   private_id text,"
   6.185 +                "	created integer,"
   6.186 +                "	expires integer,"
   6.187 +                "	comment text"
   6.188 +                ");"
   6.189 +                "create index if not exists pgp_keypair_expires on pgp_keypair ("
   6.190 +                "	expires"
   6.191 +                ");"
   6.192 +                "create table if not exists person ("
   6.193 +                "	id text primary key,"
   6.194 +                "	username text not null,"
   6.195 +                "	main_key_id text"
   6.196 +                "		references pgp_keypair (fpr)"
   6.197 +                "		on delete set null,"
   6.198 +                "   lang text,"
   6.199 +                "	comment text"
   6.200 +                ");"
   6.201 +                "create table if not exists identity ("
   6.202 +                "	address text primary key,"
   6.203 +                "	user_id text"
   6.204 +                "		references person (id)"
   6.205 +                "		on delete cascade,"
   6.206 +                "	main_key_id text"
   6.207 +                "		references pgp_keypair (fpr)"
   6.208 +                "		on delete set null,"
   6.209 +                "	comment text"
   6.210 +                ");"
   6.211 +                "create table if not exists trust ("
   6.212 +                "   user_id text not null"
   6.213 +                "       references person (id)"
   6.214 +                "		on delete cascade,"
   6.215 +                "   pgp_keypair_fpr text not null"
   6.216 +                "       references pgp_keypair (fpr)"
   6.217 +                "       on delete cascade,"
   6.218 +                "   comm_type integer not null,"
   6.219 +                "	comment text"
   6.220 +                ");"
   6.221 +                "create unique index if not exists trust_index on trust ("
   6.222 +                "   user_id,"
   6.223 +                "   pgp_keypair_fpr"
   6.224 +                ");",
   6.225 +            NULL,
   6.226 +            NULL,
   6.227 +            NULL
   6.228 +        );
   6.229 +        assert(int_result == SQLITE_OK);
   6.230  
   6.231 -	int_result = sqlite3_exec(
   6.232 -		_session->db,
   6.233 -        "insert or replace into version_info (id, version) values (1, '1.0');",
   6.234 -		NULL,
   6.235 -		NULL,
   6.236 -		NULL
   6.237 -	);
   6.238 -	assert(int_result == SQLITE_OK);
   6.239 +        int_result = sqlite3_exec(
   6.240 +            _session->db,
   6.241 +            "insert or replace into version_info (id, version) values (1, '1.0');",
   6.242 +            NULL,
   6.243 +            NULL,
   6.244 +            NULL
   6.245 +        );
   6.246 +        assert(int_result == SQLITE_OK);
   6.247  
   6.248 -	sql_log = "insert into log (title, entity, description, comment)"
   6.249 -			  "values (?1, ?2, ?3, ?4);";
   6.250 +        sql_log = "insert into log (title, entity, description, comment)"
   6.251 +                  "values (?1, ?2, ?3, ?4);";
   6.252 +
   6.253 +        sql_get_identity =	"select fpr, identity.user_id, username, comm_type, lang"
   6.254 +                            "   from identity"
   6.255 +                            "   join person on id = identity.user_id"
   6.256 +                            "   join pgp_keypair on fpr = identity.main_key_id"
   6.257 +                            "   join trust on id = trust.user_id"
   6.258 +                            "       and pgp_keypair_fpr = identity.main_key_id"
   6.259 +                            "   where address = ?1 ;";
   6.260 +
   6.261 +        sql_safeword = "select id, word from wordlist where lang = lower(?1) "
   6.262 +                       "and id = ?2 ;";
   6.263 +
   6.264 +        sql_set_person = "insert or replace into person (id, username, lang) "
   6.265 +                         "values (?1, ?2, ?3) ;";
   6.266 +
   6.267 +        sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
   6.268 +                              "values (?1) ;";
   6.269 +
   6.270 +        sql_set_identity = "insert or replace into identity (address, main_key_id, "
   6.271 +                           "user_id) values (?1, ?2, ?3) ;";
   6.272 +
   6.273 +        sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   6.274 +                        "values (?1, ?2, ?3) ;";
   6.275 +
   6.276 +        sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 "
   6.277 +                        "and pgp_keypair_fpr = ?2 ;";
   6.278 +    }
   6.279 +
   6.280      int_result = sqlite3_prepare_v2(_session->db, sql_log, strlen(sql_log),
   6.281              &_session->log, NULL);
   6.282  	assert(int_result == SQLITE_OK);
   6.283  
   6.284 -	sql_safeword = "select id, word from wordlist where lang = lower(?1)"
   6.285 -                   "and id = ?2 ;";
   6.286      int_result = sqlite3_prepare_v2(_session->system_db, sql_safeword,
   6.287              strlen(sql_safeword), &_session->safeword, NULL);
   6.288  	assert(int_result == SQLITE_OK);
   6.289  
   6.290 -	sql_get_identity =	"select fpr, identity.user_id, username, comm_type, lang"
   6.291 -                        "   from identity"
   6.292 -						"   join person on id = identity.user_id"
   6.293 -						"   join pgp_keypair on fpr = identity.main_key_id"
   6.294 -                        "   join trust on id = trust.user_id"
   6.295 -                        "       and pgp_keypair_fpr = identity.main_key_id"
   6.296 -						"   where address = ?1 ;";
   6.297 -
   6.298      int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
   6.299              strlen(sql_get_identity), &_session->get_identity, NULL);
   6.300  	assert(int_result == SQLITE_OK);
   6.301  
   6.302 -	sql_set_person = "insert or replace into person (id, username, lang)"
   6.303 -                     "values (?1, ?2, ?3) ;";
   6.304 -	sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr)"
   6.305 -                          "values (?1) ;";
   6.306 -    sql_set_identity = "insert or replace into identity (address, main_key_id,"
   6.307 -                       "user_id) values (?1, ?2, ?3) ;";
   6.308 -    sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type)"
   6.309 -                        "values (?1, ?2, ?3) ;";
   6.310 -	
   6.311 -    sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 and pgp_keypair_fpr = ?2 ;";
   6.312 -
   6.313      int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
   6.314              strlen(sql_set_person), &_session->set_person, NULL);
   6.315      assert(int_result == SQLITE_OK);
   6.316 +
   6.317      int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
   6.318              strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, NULL);
   6.319  	assert(int_result == SQLITE_OK);
   6.320 +
   6.321      int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
   6.322              strlen(sql_set_identity), &_session->set_identity, NULL);
   6.323  	assert(int_result == SQLITE_OK);
   6.324 +
   6.325      int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
   6.326              strlen(sql_set_trust), &_session->set_trust, NULL);
   6.327  	assert(int_result == SQLITE_OK);
   6.328 +
   6.329      int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
   6.330              strlen(sql_get_trust), &_session->get_trust, NULL);
   6.331      assert(int_result == SQLITE_OK);
   6.332 @@ -225,14 +237,27 @@
   6.333  	} while (int_result == SQLITE_BUSY);
   6.334      sqlite3_reset(_session->log);
   6.335  
   6.336 +    init_cryptotech(_session, in_first);
   6.337 +    init_transport_system(_session, in_first);
   6.338 +
   6.339  	*session = (void *) _session;
   6.340  	return PEP_STATUS_OK;
   6.341  }
   6.342  
   6.343  DYNAMIC_API void release(PEP_SESSION session)
   6.344  {
   6.345 +    bool out_last = false;
   6.346 +
   6.347 +    assert(init_count >= 0);
   6.348  	assert(session);
   6.349  
   6.350 +    // a small race condition but still a race condition
   6.351 +    // removed by calling caveat (see documentation)
   6.352 +
   6.353 +    if (init_count == 0)
   6.354 +        out_last = true;
   6.355 +    --init_count;
   6.356 +
   6.357  	if (session) {
   6.358  		if (session->db) {
   6.359  			sqlite3_finalize(session->safeword);
   6.360 @@ -247,10 +272,11 @@
   6.361  			sqlite3_close_v2(session->db);
   6.362  			sqlite3_close_v2(session->system_db);
   6.363  		}
   6.364 +    }
   6.365  
   6.366 -        release_transport_system(session);
   6.367 -        release_cryptotech(session);
   6.368 -    }
   6.369 +    release_transport_system(session, out_last);
   6.370 +    release_cryptotech(session, out_last);
   6.371 +
   6.372  	free(session);
   6.373  }
   6.374  
     7.1 --- a/src/pEpEngine.h	Tue Feb 10 08:27:36 2015 -0500
     7.2 +++ b/src/pEpEngine.h	Sat Feb 21 16:55:43 2015 +0100
     7.3 @@ -95,6 +95,9 @@
     7.4  //      the pointer is valid only if the return value is PEP_STATUS_OK
     7.5  //      in other case a NULL pointer will be returned; a valid handle must
     7.6  //      be released using release() when it's no longer needed
     7.7 +//
     7.8 +//      the caller has to guarantee that the first call to this function
     7.9 +//      will succeed before further calls can be done
    7.10  
    7.11  DYNAMIC_API PEP_STATUS init(PEP_SESSION *session);
    7.12  
    7.13 @@ -103,6 +106,10 @@
    7.14  //
    7.15  //  parameters:
    7.16  //		session (in)	session handle to release
    7.17 +//
    7.18 +//	caveat:
    7.19 +//	    the last release() can be called only when all other release() calls
    7.20 +//	    are done
    7.21  
    7.22  DYNAMIC_API void release(PEP_SESSION session);
    7.23  
     8.1 --- a/src/pEp_internal.h	Tue Feb 10 08:27:36 2015 -0500
     8.2 +++ b/src/pEp_internal.h	Sat Feb 21 16:55:43 2015 +0100
     8.3 @@ -62,15 +62,14 @@
     8.4  
     8.5  typedef struct _pEpSession {
     8.6      const char *version;
     8.7 -
     8.8  #ifndef NO_GPG
     8.9      void *gpgme;
    8.10 -    struct gpg_s gpg;
    8.11 +    struct gpg_s *gpg;
    8.12      gpgme_ctx_t ctx;
    8.13  #endif
    8.14  
    8.15 -    PEP_cryptotech_t cryptotech[PEP_crypt__count];
    8.16 -    PEP_transport_t transports[PEP_trans__count];
    8.17 +    PEP_cryptotech_t *cryptotech;
    8.18 +    PEP_transport_t *transports;
    8.19  
    8.20      sqlite3 *db;
    8.21      sqlite3 *system_db;
    8.22 @@ -85,6 +84,6 @@
    8.23      sqlite3_stmt *get_trust;
    8.24  } pEpSession;
    8.25  
    8.26 -PEP_STATUS init_transport_system(PEP_SESSION session);
    8.27 -void release_transport_system(PEP_SESSION session);
    8.28 +PEP_STATUS init_transport_system(PEP_SESSION session, bool in_first);
    8.29 +void release_transport_system(PEP_SESSION session, bool out_last);
    8.30  
     9.1 --- a/src/pgp_gpg.c	Tue Feb 10 08:27:36 2015 -0500
     9.2 +++ b/src/pgp_gpg.c	Sat Feb 21 16:55:43 2015 +0100
     9.3 @@ -1,242 +1,289 @@
     9.4 +#include <errno.h>
     9.5 +
     9.6  #include "pgp_gpg.h"
     9.7  #include "pEp_internal.h"
     9.8  
     9.9 +#include "wrappers.h"
    9.10 +
    9.11  #define _GPGERR(X) ((X) & 0xffffL)
    9.12  
    9.13  static bool ensure_keyserver()
    9.14  {
    9.15      static char buf[MAX_LINELENGTH];
    9.16      int n;
    9.17 -    FILE *f = fopen(gpg_conf(), "r");
    9.18 +    FILE *f;
    9.19 +    int r;
    9.20 +
    9.21 +    f = Fopen(gpg_conf(), "r");
    9.22 +    if (errno == ENOMEM)
    9.23 +        return false;
    9.24  
    9.25      if (f != NULL) {
    9.26 -        while (!feof(f)) {
    9.27 -            char * s = fgets(buf, MAX_LINELENGTH, f);
    9.28 +        do {
    9.29 +            char * s;
    9.30 +
    9.31 +            do {
    9.32 +                s = fgets(buf, MAX_LINELENGTH, f);
    9.33 +            } while (s == NULL && !feof(f) && errno == EINTR);
    9.34 +
    9.35 +            assert(s);
    9.36 +            if (s == NULL)
    9.37 +                return false;
    9.38 +
    9.39              if (s && !feof(f)) {
    9.40                  char * t = strtok(s, " ");
    9.41                  if (t && strcmp(t, "keyserver") == 0) {
    9.42 -                    fclose(f);
    9.43 +                    do {
    9.44 +                        r = fclose(f);
    9.45 +                    } while (r == -1 && errno == EINTR);
    9.46 +                    assert(r == 0);
    9.47                      return true;
    9.48                  }
    9.49              }
    9.50 -        }
    9.51 -        f = freopen(gpg_conf(), "a", f);
    9.52 +        } while (!feof(f));
    9.53 +        do {
    9.54 +            f = freopen(gpg_conf(), "a", f);
    9.55 +        } while (f == NULL && errno == EINTR);
    9.56      }
    9.57      else {
    9.58 -        f = fopen(gpg_conf(), "w");
    9.59 +        do {
    9.60 +            f = fopen(gpg_conf(), "w");
    9.61 +        } while (f == NULL && errno == EINTR);
    9.62      }
    9.63  
    9.64      assert(f);
    9.65      if (f == NULL)
    9.66          return false;
    9.67  
    9.68 -    n = fprintf(f, "keyserver %s\n", DEFAULT_KEYSERVER);
    9.69 +    do {
    9.70 +        n = fprintf(f, "keyserver %s\n", DEFAULT_KEYSERVER);
    9.71 +    } while (n < 0 && errno == EINTR);
    9.72      assert(n >= 0);
    9.73 -    fclose(f);
    9.74 +
    9.75 +    do {
    9.76 +        r = fclose(f);
    9.77 +    } while (r == -1 && errno == EINTR);
    9.78 +    assert(r == 0);
    9.79  
    9.80      return true;
    9.81  }
    9.82  
    9.83 -PEP_STATUS pgp_init(PEP_SESSION session)
    9.84 +PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
    9.85  {
    9.86 +    static struct gpg_s gpg;
    9.87 +    static void *gpgme;
    9.88      gpgme_error_t gpgme_error;
    9.89 -    bool bResult = ensure_keyserver();
    9.90 -    assert(bResult);
    9.91 +    bool bResult;
    9.92 +    
    9.93 +    if (in_first) {
    9.94 +        bResult = ensure_keyserver();
    9.95 +        assert(bResult);
    9.96  
    9.97 -    session->gpgme = dlopen(LIBGPGME, RTLD_LAZY);
    9.98 -    if (session->gpgme == NULL) {
    9.99 -        free(session);
   9.100 -        return PEP_INIT_CANNOT_LOAD_GPGME;
   9.101 +        gpgme = dlopen(LIBGPGME, RTLD_LAZY);
   9.102 +        if (gpgme == NULL) {
   9.103 +            return PEP_INIT_CANNOT_LOAD_GPGME;
   9.104 +        }
   9.105 +
   9.106 +        memset(&gpg, 0, sizeof(struct gpg_s));
   9.107 +
   9.108 +        gpg.gpgme_set_locale
   9.109 +            = (gpgme_set_locale_t) (intptr_t) dlsym(gpgme,
   9.110 +            "gpgme_set_locale");
   9.111 +        assert(gpg.gpgme_set_locale);
   9.112 +
   9.113 +        gpg.gpgme_check
   9.114 +            = (gpgme_check_version_t) (intptr_t) dlsym(gpgme,
   9.115 +            "gpgme_check_version");
   9.116 +        assert(gpg.gpgme_check);
   9.117 +
   9.118 +        gpg.gpgme_new
   9.119 +            = (gpgme_new_t) (intptr_t) dlsym(gpgme, "gpgme_new");
   9.120 +        assert(gpg.gpgme_new);
   9.121 +
   9.122 +        gpg.gpgme_release
   9.123 +            = (gpgme_release_t) (intptr_t) dlsym(gpgme, "gpgme_release");
   9.124 +        assert(gpg.gpgme_release);
   9.125 +
   9.126 +        gpg.gpgme_set_protocol
   9.127 +            = (gpgme_set_protocol_t) (intptr_t) dlsym(gpgme,
   9.128 +            "gpgme_set_protocol");
   9.129 +        assert(gpg.gpgme_set_protocol);
   9.130 +
   9.131 +        gpg.gpgme_set_armor
   9.132 +            = (gpgme_set_armor_t) (intptr_t) dlsym(gpgme,
   9.133 +            "gpgme_set_armor");
   9.134 +        assert(gpg.gpgme_set_armor);
   9.135 +
   9.136 +        gpg.gpgme_data_new
   9.137 +            = (gpgme_data_new_t) (intptr_t) dlsym(gpgme,
   9.138 +            "gpgme_data_new");
   9.139 +        assert(gpg.gpgme_data_new);
   9.140 +
   9.141 +        gpg.gpgme_data_new_from_mem
   9.142 +            = (gpgme_data_new_from_mem_t) (intptr_t) dlsym(gpgme,
   9.143 +            "gpgme_data_new_from_mem");
   9.144 +        assert(gpg.gpgme_data_new_from_mem);
   9.145 +
   9.146 +        gpg.gpgme_data_release
   9.147 +            = (gpgme_data_release_t) (intptr_t) dlsym(gpgme,
   9.148 +            "gpgme_data_release");
   9.149 +        assert(gpg.gpgme_data_release);
   9.150 +
   9.151 +        gpg.gpgme_data_identify
   9.152 +            = (gpgme_data_identify_t) (intptr_t) dlsym(gpgme,
   9.153 +            "gpgme_data_identify");
   9.154 +        assert(gpg.gpgme_data_identify);
   9.155 +
   9.156 +        gpg.gpgme_data_seek
   9.157 +            = (gpgme_data_seek_t) (intptr_t) dlsym(gpgme,
   9.158 +            "gpgme_data_seek");
   9.159 +        assert(gpg.gpgme_data_seek);
   9.160 +
   9.161 +        gpg.gpgme_data_read
   9.162 +            = (gpgme_data_read_t) (intptr_t) dlsym(gpgme,
   9.163 +            "gpgme_data_read");
   9.164 +        assert(gpg.gpgme_data_read);
   9.165 +
   9.166 +        gpg.gpgme_op_decrypt
   9.167 +            = (gpgme_op_decrypt_t) (intptr_t) dlsym(gpgme,
   9.168 +            "gpgme_op_decrypt");
   9.169 +        assert(gpg.gpgme_op_decrypt);
   9.170 +
   9.171 +        gpg.gpgme_op_verify
   9.172 +            = (gpgme_op_verify_t) (intptr_t) dlsym(gpgme,
   9.173 +            "gpgme_op_verify");
   9.174 +        assert(gpg.gpgme_op_verify);
   9.175 +
   9.176 +        gpg.gpgme_op_decrypt_verify
   9.177 +            = (gpgme_op_decrypt_verify_t) (intptr_t) dlsym(gpgme,
   9.178 +            "gpgme_op_decrypt_verify");
   9.179 +        assert(gpg.gpgme_op_decrypt_verify);
   9.180 +
   9.181 +        gpg.gpgme_op_decrypt_result
   9.182 +            = (gpgme_op_decrypt_result_t) (intptr_t) dlsym(gpgme,
   9.183 +            "gpgme_op_decrypt_result");
   9.184 +        assert(gpg.gpgme_op_decrypt_result);
   9.185 +
   9.186 +        gpg.gpgme_op_encrypt_sign
   9.187 +            = (gpgme_op_encrypt_sign_t) (intptr_t) dlsym(gpgme,
   9.188 +            "gpgme_op_encrypt_sign");
   9.189 +        assert(gpg.gpgme_op_encrypt_sign);
   9.190 +
   9.191 +        gpg.gpgme_op_verify_result
   9.192 +            = (gpgme_op_verify_result_t) (intptr_t) dlsym(gpgme,
   9.193 +            "gpgme_op_verify_result");
   9.194 +        assert(gpg.gpgme_op_verify_result);
   9.195 +
   9.196 +        gpg.gpgme_signers_clear
   9.197 +            = (gpgme_signers_clear_t) (intptr_t) dlsym(gpgme,
   9.198 +            "gpgme_signers_clear");
   9.199 +        assert(gpg.gpgme_signers_clear);
   9.200 +
   9.201 +        gpg.gpgme_signers_add
   9.202 +            = (gpgme_signers_add_t) (intptr_t) dlsym(gpgme,
   9.203 +            "gpgme_signers_add");
   9.204 +        assert(gpg.gpgme_signers_add);
   9.205 +
   9.206 +        gpg.gpgme_get_key
   9.207 +            = (gpgme_get_key_t) (intptr_t) dlsym(gpgme, "gpgme_get_key");
   9.208 +        assert(gpg.gpgme_get_key);
   9.209 +
   9.210 +        gpg.gpgme_op_genkey
   9.211 +            = (gpgme_op_genkey_t) (intptr_t) dlsym(gpgme,
   9.212 +            "gpgme_op_genkey");
   9.213 +        assert(gpg.gpgme_op_genkey);
   9.214 +
   9.215 +        gpg.gpgme_op_genkey_result
   9.216 +            = (gpgme_op_genkey_result_t) (intptr_t) dlsym(gpgme,
   9.217 +            "gpgme_op_genkey_result");
   9.218 +        assert(gpg.gpgme_op_genkey_result);
   9.219 +
   9.220 +        gpg.gpgme_op_delete = (gpgme_op_delete_t) (intptr_t)
   9.221 +            dlsym(gpgme, "gpgme_op_delete");
   9.222 +        assert(gpg.gpgme_op_delete);
   9.223 +
   9.224 +        gpg.gpgme_op_import = (gpgme_op_import_t) (intptr_t)
   9.225 +            dlsym(gpgme, "gpgme_op_import");
   9.226 +        assert(gpg.gpgme_op_import);
   9.227 +
   9.228 +        gpg.gpgme_op_export = (gpgme_op_export_t) (intptr_t)
   9.229 +            dlsym(gpgme, "gpgme_op_export");
   9.230 +        assert(gpg.gpgme_op_export);
   9.231 +
   9.232 +        gpg.gpgme_set_keylist_mode = (gpgme_set_keylist_mode_t) (intptr_t)
   9.233 +            dlsym(gpgme, "gpgme_set_keylist_mode");
   9.234 +        assert(gpg.gpgme_set_keylist_mode);
   9.235 +
   9.236 +        gpg.gpgme_get_keylist_mode = (gpgme_get_keylist_mode_t) (intptr_t)
   9.237 +            dlsym(gpgme, "gpgme_get_keylist_mode");
   9.238 +        assert(gpg.gpgme_get_keylist_mode);
   9.239 +
   9.240 +        gpg.gpgme_op_keylist_start = (gpgme_op_keylist_start_t) (intptr_t)
   9.241 +            dlsym(gpgme, "gpgme_op_keylist_start");
   9.242 +        assert(gpg.gpgme_op_keylist_start);
   9.243 +
   9.244 +        gpg.gpgme_op_keylist_next = (gpgme_op_keylist_next_t) (intptr_t)
   9.245 +            dlsym(gpgme, "gpgme_op_keylist_next");
   9.246 +        assert(gpg.gpgme_op_keylist_next);
   9.247 +
   9.248 +        gpg.gpgme_op_keylist_end = (gpgme_op_keylist_end_t) (intptr_t)
   9.249 +            dlsym(gpgme, "gpgme_op_keylist_end");
   9.250 +        assert(gpg.gpgme_op_keylist_end);
   9.251 +
   9.252 +        gpg.gpgme_op_import_keys = (gpgme_op_import_keys_t) (intptr_t)
   9.253 +            dlsym(gpgme, "gpgme_op_import_keys");
   9.254 +        assert(gpg.gpgme_op_import_keys);
   9.255 +
   9.256 +        gpg.gpgme_key_ref = (gpgme_key_ref_t) (intptr_t)
   9.257 +            dlsym(gpgme, "gpgme_key_ref");
   9.258 +        assert(gpg.gpgme_key_ref);
   9.259 +
   9.260 +        gpg.gpgme_key_unref = (gpgme_key_unref_t) (intptr_t)
   9.261 +            dlsym(gpgme, "gpgme_key_unref");
   9.262 +        assert(gpg.gpgme_key_unref);
   9.263 +
   9.264 +        gpg.version = gpg.gpgme_check(NULL);
   9.265 +        
   9.266 +        if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
   9.267 +            setlocale(LC_ALL, "");
   9.268 +
   9.269 +        gpg.gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
   9.270 +#ifdef LC_MESSAGES // Windoze
   9.271 +        gpg.gpgme_set_locale (NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
   9.272 +#endif
   9.273      }
   9.274  
   9.275 -    memset(&(session->gpg), 0, sizeof(struct gpg_s));
   9.276 +    session->gpg = &gpg;
   9.277  
   9.278 -    session->gpg.gpgme_set_locale
   9.279 -        = (gpgme_set_locale_t) (intptr_t) dlsym(session->gpgme,
   9.280 -        "gpgme_set_locale");
   9.281 -    assert(session->gpg.gpgme_set_locale);
   9.282 -
   9.283 -    session->gpg.gpgme_check
   9.284 -        = (gpgme_check_version_t) (intptr_t) dlsym(session->gpgme,
   9.285 -        "gpgme_check_version");
   9.286 -    assert(session->gpg.gpgme_check);
   9.287 -
   9.288 -    session->gpg.gpgme_new
   9.289 -        = (gpgme_new_t) (intptr_t) dlsym(session->gpgme, "gpgme_new");
   9.290 -    assert(session->gpg.gpgme_new);
   9.291 -
   9.292 -    session->gpg.gpgme_release
   9.293 -        = (gpgme_release_t) (intptr_t) dlsym(session->gpgme, "gpgme_release");
   9.294 -    assert(session->gpg.gpgme_release);
   9.295 -
   9.296 -    session->gpg.gpgme_set_protocol
   9.297 -        = (gpgme_set_protocol_t) (intptr_t) dlsym(session->gpgme,
   9.298 -        "gpgme_set_protocol");
   9.299 -    assert(session->gpg.gpgme_set_protocol);
   9.300 -
   9.301 -    session->gpg.gpgme_set_armor
   9.302 -        = (gpgme_set_armor_t) (intptr_t) dlsym(session->gpgme,
   9.303 -        "gpgme_set_armor");
   9.304 -    assert(session->gpg.gpgme_set_armor);
   9.305 -
   9.306 -    session->gpg.gpgme_data_new
   9.307 -        = (gpgme_data_new_t) (intptr_t) dlsym(session->gpgme,
   9.308 -        "gpgme_data_new");
   9.309 -    assert(session->gpg.gpgme_data_new);
   9.310 -
   9.311 -    session->gpg.gpgme_data_new_from_mem
   9.312 -        = (gpgme_data_new_from_mem_t) (intptr_t) dlsym(session->gpgme,
   9.313 -        "gpgme_data_new_from_mem");
   9.314 -    assert(session->gpg.gpgme_data_new_from_mem);
   9.315 -
   9.316 -    session->gpg.gpgme_data_release
   9.317 -        = (gpgme_data_release_t) (intptr_t) dlsym(session->gpgme,
   9.318 -        "gpgme_data_release");
   9.319 -    assert(session->gpg.gpgme_data_release);
   9.320 -
   9.321 -    session->gpg.gpgme_data_identify
   9.322 -        = (gpgme_data_identify_t) (intptr_t) dlsym(session->gpgme,
   9.323 -        "gpgme_data_identify");
   9.324 -    assert(session->gpg.gpgme_data_identify);
   9.325 -
   9.326 -    session->gpg.gpgme_data_seek
   9.327 -        = (gpgme_data_seek_t) (intptr_t) dlsym(session->gpgme,
   9.328 -        "gpgme_data_seek");
   9.329 -    assert(session->gpg.gpgme_data_seek);
   9.330 -
   9.331 -    session->gpg.gpgme_data_read
   9.332 -        = (gpgme_data_read_t) (intptr_t) dlsym(session->gpgme,
   9.333 -        "gpgme_data_read");
   9.334 -    assert(session->gpg.gpgme_data_read);
   9.335 -
   9.336 -    session->gpg.gpgme_op_decrypt
   9.337 -        = (gpgme_op_decrypt_t) (intptr_t) dlsym(session->gpgme,
   9.338 -        "gpgme_op_decrypt");
   9.339 -    assert(session->gpg.gpgme_op_decrypt);
   9.340 -
   9.341 -    session->gpg.gpgme_op_verify
   9.342 -        = (gpgme_op_verify_t) (intptr_t) dlsym(session->gpgme,
   9.343 -        "gpgme_op_verify");
   9.344 -    assert(session->gpg.gpgme_op_verify);
   9.345 -
   9.346 -    session->gpg.gpgme_op_decrypt_verify
   9.347 -        = (gpgme_op_decrypt_verify_t) (intptr_t) dlsym(session->gpgme,
   9.348 -        "gpgme_op_decrypt_verify");
   9.349 -    assert(session->gpg.gpgme_op_decrypt_verify);
   9.350 -
   9.351 -    session->gpg.gpgme_op_decrypt_result
   9.352 -        = (gpgme_op_decrypt_result_t) (intptr_t) dlsym(session->gpgme,
   9.353 -        "gpgme_op_decrypt_result");
   9.354 -    assert(session->gpg.gpgme_op_decrypt_result);
   9.355 -
   9.356 -    session->gpg.gpgme_op_encrypt_sign
   9.357 -        = (gpgme_op_encrypt_sign_t) (intptr_t) dlsym(session->gpgme,
   9.358 -        "gpgme_op_encrypt_sign");
   9.359 -    assert(session->gpg.gpgme_op_encrypt_sign);
   9.360 -
   9.361 -    session->gpg.gpgme_op_verify_result
   9.362 -        = (gpgme_op_verify_result_t) (intptr_t) dlsym(session->gpgme,
   9.363 -        "gpgme_op_verify_result");
   9.364 -    assert(session->gpg.gpgme_op_verify_result);
   9.365 -
   9.366 -    session->gpg.gpgme_signers_clear
   9.367 -        = (gpgme_signers_clear_t) (intptr_t) dlsym(session->gpgme,
   9.368 -        "gpgme_signers_clear");
   9.369 -    assert(session->gpg.gpgme_signers_clear);
   9.370 -
   9.371 -    session->gpg.gpgme_signers_add
   9.372 -        = (gpgme_signers_add_t) (intptr_t) dlsym(session->gpgme,
   9.373 -        "gpgme_signers_add");
   9.374 -    assert(session->gpg.gpgme_signers_add);
   9.375 -
   9.376 -    session->gpg.gpgme_get_key
   9.377 -        = (gpgme_get_key_t) (intptr_t) dlsym(session->gpgme, "gpgme_get_key");
   9.378 -    assert(session->gpg.gpgme_get_key);
   9.379 -
   9.380 -    session->gpg.gpgme_op_genkey
   9.381 -        = (gpgme_op_genkey_t) (intptr_t) dlsym(session->gpgme,
   9.382 -        "gpgme_op_genkey");
   9.383 -    assert(session->gpg.gpgme_op_genkey);
   9.384 -
   9.385 -    session->gpg.gpgme_op_genkey_result
   9.386 -        = (gpgme_op_genkey_result_t) (intptr_t) dlsym(session->gpgme,
   9.387 -        "gpgme_op_genkey_result");
   9.388 -    assert(session->gpg.gpgme_op_genkey_result);
   9.389 -
   9.390 -    session->gpg.gpgme_op_delete = (gpgme_op_delete_t) (intptr_t)
   9.391 -        dlsym(session->gpgme, "gpgme_op_delete");
   9.392 -    assert(session->gpg.gpgme_op_delete);
   9.393 -
   9.394 -    session->gpg.gpgme_op_import = (gpgme_op_import_t) (intptr_t)
   9.395 -        dlsym(session->gpgme, "gpgme_op_import");
   9.396 -    assert(session->gpg.gpgme_op_import);
   9.397 -
   9.398 -    session->gpg.gpgme_op_export = (gpgme_op_export_t) (intptr_t)
   9.399 -        dlsym(session->gpgme, "gpgme_op_export");
   9.400 -    assert(session->gpg.gpgme_op_export);
   9.401 -
   9.402 -    session->gpg.gpgme_set_keylist_mode = (gpgme_set_keylist_mode_t) (intptr_t)
   9.403 -        dlsym(session->gpgme, "gpgme_set_keylist_mode");
   9.404 -    assert(session->gpg.gpgme_set_keylist_mode);
   9.405 -
   9.406 -    session->gpg.gpgme_get_keylist_mode = (gpgme_get_keylist_mode_t) (intptr_t)
   9.407 -        dlsym(session->gpgme, "gpgme_get_keylist_mode");
   9.408 -    assert(session->gpg.gpgme_get_keylist_mode);
   9.409 -
   9.410 -    session->gpg.gpgme_op_keylist_start = (gpgme_op_keylist_start_t) (intptr_t)
   9.411 -        dlsym(session->gpgme, "gpgme_op_keylist_start");
   9.412 -    assert(session->gpg.gpgme_op_keylist_start);
   9.413 -
   9.414 -    session->gpg.gpgme_op_keylist_next = (gpgme_op_keylist_next_t) (intptr_t)
   9.415 -        dlsym(session->gpgme, "gpgme_op_keylist_next");
   9.416 -    assert(session->gpg.gpgme_op_keylist_next);
   9.417 -
   9.418 -    session->gpg.gpgme_op_keylist_end = (gpgme_op_keylist_end_t) (intptr_t)
   9.419 -        dlsym(session->gpgme, "gpgme_op_keylist_end");
   9.420 -    assert(session->gpg.gpgme_op_keylist_end);
   9.421 -
   9.422 -    session->gpg.gpgme_op_import_keys = (gpgme_op_import_keys_t) (intptr_t)
   9.423 -        dlsym(session->gpgme, "gpgme_op_import_keys");
   9.424 -    assert(session->gpg.gpgme_op_import_keys);
   9.425 -
   9.426 -    session->gpg.gpgme_key_ref = (gpgme_key_ref_t) (intptr_t)
   9.427 -        dlsym(session->gpgme, "gpgme_key_ref");
   9.428 -    assert(session->gpg.gpgme_key_ref);
   9.429 -
   9.430 -    session->gpg.gpgme_key_unref = (gpgme_key_unref_t) (intptr_t)
   9.431 -        dlsym(session->gpgme, "gpgme_key_unref");
   9.432 -    assert(session->gpg.gpgme_key_unref);
   9.433 -
   9.434 -    setlocale(LC_ALL, "");
   9.435 -    session->version = session->gpg.gpgme_check(NULL);
   9.436 -    session->gpg.gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
   9.437 -
   9.438 -    gpgme_error = session->gpg.gpgme_new(&session->ctx);
   9.439 +    gpgme_error = gpg.gpgme_new(&session->ctx);
   9.440      gpgme_error = _GPGERR(gpgme_error);
   9.441      if (gpgme_error != GPG_ERR_NO_ERROR) {
   9.442 -        dlclose(session->gpgme);
   9.443 -        free(session);
   9.444          return PEP_INIT_GPGME_INIT_FAILED;
   9.445      }
   9.446      assert(session->ctx);
   9.447  
   9.448 -    gpgme_error = session->gpg.gpgme_set_protocol(session->ctx,
   9.449 -        GPGME_PROTOCOL_OpenPGP);
   9.450 +    gpgme_error = gpg.gpgme_set_protocol(session->ctx, GPGME_PROTOCOL_OpenPGP);
   9.451      gpgme_error = _GPGERR(gpgme_error);
   9.452      assert(gpgme_error == GPG_ERR_NO_ERROR);
   9.453  
   9.454 -    session->gpg.gpgme_set_armor(session->ctx, 1);
   9.455 +    gpg.gpgme_set_armor(session->ctx, 1);
   9.456  
   9.457      return PEP_STATUS_OK;
   9.458  }
   9.459  
   9.460 -void pgp_release(PEP_SESSION session)
   9.461 +void pgp_release(PEP_SESSION session, bool out_last)
   9.462  {
   9.463 -    if (session->ctx)
   9.464 -        session->gpg.gpgme_release(session->ctx);
   9.465 -    session->ctx = NULL;
   9.466 -    memset(&(session->gpg), 0, sizeof(struct gpg_s));
   9.467 -    dlclose(session->gpgme);
   9.468 +    if (session->ctx) {
   9.469 +        session->gpg->gpgme_release(session->ctx);
   9.470 +        session->ctx = NULL;
   9.471 +    }
   9.472 +
   9.473 +    if (out_last) {
   9.474 +        if (session->gpgme) {
   9.475 +            dlclose(session->gpgme);
   9.476 +            session->gpgme = NULL;
   9.477 +        }
   9.478 +    }
   9.479  }
   9.480  
   9.481  PEP_STATUS pgp_decrypt_and_verify(
   9.482 @@ -263,7 +310,7 @@
   9.483      *psize = 0;
   9.484      *keylist = NULL;
   9.485  
   9.486 -    gpgme_error = session->gpg.gpgme_data_new_from_mem(&cipher, ctext, csize, 0);
   9.487 +    gpgme_error = session->gpg->gpgme_data_new_from_mem(&cipher, ctext, csize, 0);
   9.488      gpgme_error = _GPGERR(gpgme_error);
   9.489      assert(gpgme_error == GPG_ERR_NO_ERROR);
   9.490      if (gpgme_error != GPG_ERR_NO_ERROR) {
   9.491 @@ -273,22 +320,22 @@
   9.492              return PEP_UNKNOWN_ERROR;
   9.493      }
   9.494  
   9.495 -    gpgme_error = session->gpg.gpgme_data_new(&plain);
   9.496 +    gpgme_error = session->gpg->gpgme_data_new(&plain);
   9.497      gpgme_error = _GPGERR(gpgme_error);
   9.498      assert(gpgme_error == GPG_ERR_NO_ERROR);
   9.499      if (gpgme_error != GPG_ERR_NO_ERROR) {
   9.500 -        session->gpg.gpgme_data_release(cipher);
   9.501 +        session->gpg->gpgme_data_release(cipher);
   9.502          if (gpgme_error == GPG_ERR_ENOMEM)
   9.503              return PEP_OUT_OF_MEMORY;
   9.504          else
   9.505              return PEP_UNKNOWN_ERROR;
   9.506      }
   9.507  
   9.508 -    dt = session->gpg.gpgme_data_identify(cipher);
   9.509 +    dt = session->gpg->gpgme_data_identify(cipher);
   9.510      switch (dt) {
   9.511      case GPGME_DATA_TYPE_PGP_SIGNED:
   9.512      case GPGME_DATA_TYPE_PGP_OTHER:
   9.513 -        gpgme_error = session->gpg.gpgme_op_decrypt_verify(session->ctx, cipher,
   9.514 +        gpgme_error = session->gpg->gpgme_op_decrypt_verify(session->ctx, cipher,
   9.515              plain);
   9.516          gpgme_error = _GPGERR(gpgme_error);
   9.517          assert(gpgme_error != GPG_ERR_INV_VALUE);
   9.518 @@ -300,11 +347,11 @@
   9.519              gpgme_verify_result_t gpgme_verify_result;
   9.520              char *_buffer = NULL;
   9.521              size_t reading;
   9.522 -            size_t length = session->gpg.gpgme_data_seek(plain, 0, SEEK_END);
   9.523 +            size_t length = session->gpg->gpgme_data_seek(plain, 0, SEEK_END);
   9.524              gpgme_signature_t gpgme_signature;
   9.525  
   9.526              assert(length != -1);
   9.527 -            session->gpg.gpgme_data_seek(plain, 0, SEEK_SET);
   9.528 +            session->gpg->gpgme_data_seek(plain, 0, SEEK_SET);
   9.529  
   9.530              // TODO: make things less memory consuming
   9.531              // the following algorithm allocates memory for the complete
   9.532 @@ -313,16 +360,16 @@
   9.533              _buffer = malloc(length + 1);
   9.534              assert(_buffer);
   9.535              if (_buffer == NULL) {
   9.536 -                session->gpg.gpgme_data_release(plain);
   9.537 -                session->gpg.gpgme_data_release(cipher);
   9.538 +                session->gpg->gpgme_data_release(plain);
   9.539 +                session->gpg->gpgme_data_release(cipher);
   9.540                  return PEP_OUT_OF_MEMORY;
   9.541              }
   9.542  
   9.543 -            reading = session->gpg.gpgme_data_read(plain, _buffer, length);
   9.544 +            reading = session->gpg->gpgme_data_read(plain, _buffer, length);
   9.545              assert(length == reading);
   9.546  
   9.547              gpgme_verify_result =
   9.548 -                session->gpg.gpgme_op_verify_result(session->ctx);
   9.549 +                session->gpg->gpgme_op_verify_result(session->ctx);
   9.550              assert(gpgme_verify_result);
   9.551              gpgme_signature = gpgme_verify_result->signatures;
   9.552  
   9.553 @@ -331,8 +378,8 @@
   9.554                  _keylist = new_stringlist(NULL);
   9.555                  assert(_keylist);
   9.556                  if (_keylist == NULL) {
   9.557 -                    session->gpg.gpgme_data_release(plain);
   9.558 -                    session->gpg.gpgme_data_release(cipher);
   9.559 +                    session->gpg->gpgme_data_release(plain);
   9.560 +                    session->gpg->gpgme_data_release(cipher);
   9.561                      free(_buffer);
   9.562                      return PEP_OUT_OF_MEMORY;
   9.563                  }
   9.564 @@ -388,7 +435,7 @@
   9.565              NOT_IMPLEMENTED;
   9.566          default:
   9.567          {
   9.568 -            gpgme_decrypt_result_t gpgme_decrypt_result = session->gpg.gpgme_op_decrypt_result(session->ctx);
   9.569 +            gpgme_decrypt_result_t gpgme_decrypt_result = session->gpg->gpgme_op_decrypt_result(session->ctx);
   9.570              result = PEP_DECRYPT_NO_KEY;
   9.571  
   9.572              if (gpgme_decrypt_result != NULL) {
   9.573 @@ -423,8 +470,8 @@
   9.574          result = PEP_DECRYPT_WRONG_FORMAT;
   9.575      }
   9.576  
   9.577 -    session->gpg.gpgme_data_release(plain);
   9.578 -    session->gpg.gpgme_data_release(cipher);
   9.579 +    session->gpg->gpgme_data_release(plain);
   9.580 +    session->gpg->gpgme_data_release(cipher);
   9.581      return result;
   9.582  }
   9.583  
   9.584 @@ -447,7 +494,7 @@
   9.585  
   9.586      *keylist = NULL;
   9.587  
   9.588 -    gpgme_error = session->gpg.gpgme_data_new_from_mem(&d_text, text, size, 0);
   9.589 +    gpgme_error = session->gpg->gpgme_data_new_from_mem(&d_text, text, size, 0);
   9.590      gpgme_error = _GPGERR(gpgme_error);
   9.591      assert(gpgme_error == GPG_ERR_NO_ERROR);
   9.592      if (gpgme_error != GPG_ERR_NO_ERROR) {
   9.593 @@ -457,18 +504,18 @@
   9.594              return PEP_UNKNOWN_ERROR;
   9.595      }
   9.596  
   9.597 -    gpgme_error = session->gpg.gpgme_data_new_from_mem(&d_sig, signature, sig_size, 0);
   9.598 +    gpgme_error = session->gpg->gpgme_data_new_from_mem(&d_sig, signature, sig_size, 0);
   9.599      gpgme_error = _GPGERR(gpgme_error);
   9.600      assert(gpgme_error == GPG_ERR_NO_ERROR);
   9.601      if (gpgme_error != GPG_ERR_NO_ERROR) {
   9.602 -        session->gpg.gpgme_data_release(d_text);
   9.603 +        session->gpg->gpgme_data_release(d_text);
   9.604          if (gpgme_error == GPG_ERR_ENOMEM)
   9.605              return PEP_OUT_OF_MEMORY;
   9.606          else
   9.607              return PEP_UNKNOWN_ERROR;
   9.608      }
   9.609  
   9.610 -    gpgme_error = session->gpg.gpgme_op_verify(session->ctx, d_sig, d_text, NULL);
   9.611 +    gpgme_error = session->gpg->gpgme_op_verify(session->ctx, d_sig, d_text, NULL);
   9.612      gpgme_error = _GPGERR(gpgme_error);
   9.613      assert(gpgme_error != GPG_ERR_INV_VALUE);
   9.614  
   9.615 @@ -479,7 +526,7 @@
   9.616          gpgme_signature_t gpgme_signature;
   9.617  
   9.618          gpgme_verify_result =
   9.619 -            session->gpg.gpgme_op_verify_result(session->ctx);
   9.620 +            session->gpg->gpgme_op_verify_result(session->ctx);
   9.621          assert(gpgme_verify_result);
   9.622          gpgme_signature = gpgme_verify_result->signatures;
   9.623  
   9.624 @@ -488,8 +535,8 @@
   9.625              _keylist = new_stringlist(NULL);
   9.626              assert(_keylist);
   9.627              if (_keylist == NULL) {
   9.628 -                session->gpg.gpgme_data_release(d_text);
   9.629 -                session->gpg.gpgme_data_release(d_sig);
   9.630 +                session->gpg->gpgme_data_release(d_text);
   9.631 +                session->gpg->gpgme_data_release(d_sig);
   9.632                  return PEP_OUT_OF_MEMORY;
   9.633              }
   9.634              k = _keylist;
   9.635 @@ -499,8 +546,8 @@
   9.636                  k = stringlist_add(k, gpgme_signature->fpr);
   9.637                  if (k == NULL) {
   9.638                      free_stringlist(_keylist);
   9.639 -                    session->gpg.gpgme_data_release(d_text);
   9.640 -                    session->gpg.gpgme_data_release(d_sig);
   9.641 +                    session->gpg->gpgme_data_release(d_text);
   9.642 +                    session->gpg->gpgme_data_release(d_sig);
   9.643                      return PEP_OUT_OF_MEMORY;
   9.644                  }
   9.645                  if (gpgme_signature->summary & GPGME_SIGSUM_RED) {
   9.646 @@ -553,8 +600,8 @@
   9.647          break;
   9.648      }
   9.649  
   9.650 -    session->gpg.gpgme_data_release(d_text);
   9.651 -    session->gpg.gpgme_data_release(d_sig);
   9.652 +    session->gpg->gpgme_data_release(d_text);
   9.653 +    session->gpg->gpgme_data_release(d_sig);
   9.654  
   9.655      return result;
   9.656  }
   9.657 @@ -582,7 +629,7 @@
   9.658      *ctext = NULL;
   9.659      *csize = 0;
   9.660  
   9.661 -    gpgme_error = session->gpg.gpgme_data_new_from_mem(&plain, ptext, psize, 0);
   9.662 +    gpgme_error = session->gpg->gpgme_data_new_from_mem(&plain, ptext, psize, 0);
   9.663      gpgme_error = _GPGERR(gpgme_error);
   9.664      assert(gpgme_error == GPG_ERR_NO_ERROR);
   9.665      if (gpgme_error != GPG_ERR_NO_ERROR) {
   9.666 @@ -592,11 +639,11 @@
   9.667              return PEP_UNKNOWN_ERROR;
   9.668      }
   9.669  
   9.670 -    gpgme_error = session->gpg.gpgme_data_new(&cipher);
   9.671 +    gpgme_error = session->gpg->gpgme_data_new(&cipher);
   9.672      gpgme_error = _GPGERR(gpgme_error);
   9.673      assert(gpgme_error == GPG_ERR_NO_ERROR);
   9.674      if (gpgme_error != GPG_ERR_NO_ERROR) {
   9.675 -        session->gpg.gpgme_data_release(plain);
   9.676 +        session->gpg->gpgme_data_release(plain);
   9.677          if (gpgme_error == GPG_ERR_ENOMEM)
   9.678              return PEP_OUT_OF_MEMORY;
   9.679          else
   9.680 @@ -607,16 +654,16 @@
   9.681          sizeof(gpgme_key_t));
   9.682      assert(rcpt);
   9.683      if (rcpt == NULL) {
   9.684 -        session->gpg.gpgme_data_release(plain);
   9.685 -        session->gpg.gpgme_data_release(cipher);
   9.686 +        session->gpg->gpgme_data_release(plain);
   9.687 +        session->gpg->gpgme_data_release(cipher);
   9.688          return PEP_OUT_OF_MEMORY;
   9.689      }
   9.690  
   9.691 -    session->gpg.gpgme_signers_clear(session->ctx);
   9.692 +    session->gpg->gpgme_signers_clear(session->ctx);
   9.693  
   9.694      for (_keylist = keylist, i = 0; _keylist != NULL; _keylist = _keylist->next, i++) {
   9.695          assert(_keylist->value);
   9.696 -        gpgme_error = session->gpg.gpgme_get_key(session->ctx, _keylist->value,
   9.697 +        gpgme_error = session->gpg->gpgme_get_key(session->ctx, _keylist->value,
   9.698              &rcpt[i], 0);
   9.699          gpgme_error = _GPGERR(gpgme_error);
   9.700          assert(gpgme_error != GPG_ERR_ENOMEM);
   9.701 @@ -624,39 +671,39 @@
   9.702          switch (gpgme_error) {
   9.703          case GPG_ERR_ENOMEM:
   9.704              for (j = 0; j<i; j++)
   9.705 -                session->gpg.gpgme_key_unref(rcpt[j]);
   9.706 +                session->gpg->gpgme_key_unref(rcpt[j]);
   9.707              free(rcpt);
   9.708 -            session->gpg.gpgme_data_release(plain);
   9.709 -            session->gpg.gpgme_data_release(cipher);
   9.710 +            session->gpg->gpgme_data_release(plain);
   9.711 +            session->gpg->gpgme_data_release(cipher);
   9.712              return PEP_OUT_OF_MEMORY;
   9.713          case GPG_ERR_NO_ERROR:
   9.714              if (i == 0) {
   9.715 -                gpgme_error_t _gpgme_error = session->gpg.gpgme_signers_add(session->ctx, rcpt[0]);
   9.716 +                gpgme_error_t _gpgme_error = session->gpg->gpgme_signers_add(session->ctx, rcpt[0]);
   9.717                  _gpgme_error = _GPGERR(_gpgme_error);
   9.718                  assert(_gpgme_error == GPG_ERR_NO_ERROR);
   9.719              }
   9.720              break;
   9.721          case GPG_ERR_EOF:
   9.722              for (j = 0; j<i; j++)
   9.723 -                session->gpg.gpgme_key_unref(rcpt[j]);
   9.724 +                session->gpg->gpgme_key_unref(rcpt[j]);
   9.725              free(rcpt);
   9.726 -            session->gpg.gpgme_data_release(plain);
   9.727 -            session->gpg.gpgme_data_release(cipher);
   9.728 +            session->gpg->gpgme_data_release(plain);
   9.729 +            session->gpg->gpgme_data_release(cipher);
   9.730              return PEP_KEY_NOT_FOUND;
   9.731          case GPG_ERR_AMBIGUOUS_NAME:
   9.732              for (j = 0; j<i; j++)
   9.733 -                session->gpg.gpgme_key_unref(rcpt[j]);
   9.734 +                session->gpg->gpgme_key_unref(rcpt[j]);
   9.735              free(rcpt);
   9.736 -            session->gpg.gpgme_data_release(plain);
   9.737 -            session->gpg.gpgme_data_release(cipher);
   9.738 +            session->gpg->gpgme_data_release(plain);
   9.739 +            session->gpg->gpgme_data_release(cipher);
   9.740              return PEP_KEY_HAS_AMBIG_NAME;
   9.741          default: // GPG_ERR_INV_VALUE if CTX or R_KEY is not a valid pointer or
   9.742              // FPR is not a fingerprint or key ID
   9.743              for (j = 0; j<i; j++)
   9.744 -                session->gpg.gpgme_key_unref(rcpt[j]);
   9.745 +                session->gpg->gpgme_key_unref(rcpt[j]);
   9.746              free(rcpt);
   9.747 -            session->gpg.gpgme_data_release(plain);
   9.748 -            session->gpg.gpgme_data_release(cipher);
   9.749 +            session->gpg->gpgme_data_release(plain);
   9.750 +            session->gpg->gpgme_data_release(cipher);
   9.751              return PEP_GET_KEY_FAILED;
   9.752          }
   9.753      }
   9.754 @@ -664,7 +711,7 @@
   9.755      // TODO: remove that and replace with proper key management
   9.756      flags = GPGME_ENCRYPT_ALWAYS_TRUST;
   9.757  
   9.758 -    gpgme_error = session->gpg.gpgme_op_encrypt_sign(session->ctx, rcpt, flags,
   9.759 +    gpgme_error = session->gpg->gpgme_op_encrypt_sign(session->ctx, rcpt, flags,
   9.760          plain, cipher);
   9.761      gpgme_error = _GPGERR(gpgme_error);
   9.762      switch (gpgme_error) {
   9.763 @@ -672,9 +719,9 @@
   9.764      {
   9.765          char *_buffer = NULL;
   9.766          size_t reading;
   9.767 -        size_t length = session->gpg.gpgme_data_seek(cipher, 0, SEEK_END);
   9.768 +        size_t length = session->gpg->gpgme_data_seek(cipher, 0, SEEK_END);
   9.769          assert(length != -1);
   9.770 -        session->gpg.gpgme_data_seek(cipher, 0, SEEK_SET);
   9.771 +        session->gpg->gpgme_data_seek(cipher, 0, SEEK_SET);
   9.772  
   9.773          // TODO: make things less memory consuming
   9.774          // the following algorithm allocates a buffer for the complete text
   9.775 @@ -683,14 +730,14 @@
   9.776          assert(_buffer);
   9.777          if (_buffer == NULL) {
   9.778              for (j = 0; j<stringlist_length(keylist); j++)
   9.779 -                session->gpg.gpgme_key_unref(rcpt[j]);
   9.780 +                session->gpg->gpgme_key_unref(rcpt[j]);
   9.781              free(rcpt);
   9.782 -            session->gpg.gpgme_data_release(plain);
   9.783 -            session->gpg.gpgme_data_release(cipher);
   9.784 +            session->gpg->gpgme_data_release(plain);
   9.785 +            session->gpg->gpgme_data_release(cipher);
   9.786              return PEP_OUT_OF_MEMORY;
   9.787          }
   9.788  
   9.789 -        reading = session->gpg.gpgme_data_read(cipher, _buffer, length);
   9.790 +        reading = session->gpg->gpgme_data_read(cipher, _buffer, length);
   9.791          assert(length == reading);
   9.792  
   9.793          *ctext = _buffer;
   9.794 @@ -704,10 +751,10 @@
   9.795      }
   9.796  
   9.797      for (j = 0; j<stringlist_length(keylist); j++)
   9.798 -        session->gpg.gpgme_key_unref(rcpt[j]);
   9.799 +        session->gpg->gpgme_key_unref(rcpt[j]);
   9.800      free(rcpt);
   9.801 -    session->gpg.gpgme_data_release(plain);
   9.802 -    session->gpg.gpgme_data_release(cipher);
   9.803 +    session->gpg->gpgme_data_release(plain);
   9.804 +    session->gpg->gpgme_data_release(cipher);
   9.805      return result;
   9.806  }
   9.807  
   9.808 @@ -748,7 +795,7 @@
   9.809          return PEP_BUFFER_TOO_SMALL;
   9.810      }
   9.811  
   9.812 -    gpgme_error = session->gpg.gpgme_op_genkey(session->ctx, parms, NULL, NULL);
   9.813 +    gpgme_error = session->gpg->gpgme_op_genkey(session->ctx, parms, NULL, NULL);
   9.814      gpgme_error = _GPGERR(gpgme_error);
   9.815      free(parms);
   9.816  
   9.817 @@ -764,7 +811,7 @@
   9.818          return PEP_UNKNOWN_ERROR;
   9.819      }
   9.820  
   9.821 -    gpgme_genkey_result = session->gpg.gpgme_op_genkey_result(session->ctx);
   9.822 +    gpgme_genkey_result = session->gpg->gpgme_op_genkey_result(session->ctx);
   9.823      assert(gpgme_genkey_result);
   9.824      assert(gpgme_genkey_result->fpr);
   9.825  
   9.826 @@ -781,7 +828,7 @@
   9.827      assert(session);
   9.828      assert(fpr);
   9.829  
   9.830 -    gpgme_error = session->gpg.gpgme_get_key(session->ctx, fpr, &key, 0);
   9.831 +    gpgme_error = session->gpg->gpgme_get_key(session->ctx, fpr, &key, 0);
   9.832      gpgme_error = _GPGERR(gpgme_error);
   9.833      assert(gpgme_error != GPG_ERR_ENOMEM);
   9.834      switch (gpgme_error) {
   9.835 @@ -800,9 +847,9 @@
   9.836          return PEP_UNKNOWN_ERROR;
   9.837      }
   9.838  
   9.839 -    gpgme_error = session->gpg.gpgme_op_delete(session->ctx, key, 1);
   9.840 +    gpgme_error = session->gpg->gpgme_op_delete(session->ctx, key, 1);
   9.841      gpgme_error = _GPGERR(gpgme_error);
   9.842 -    session->gpg.gpgme_key_unref(key);
   9.843 +    session->gpg->gpgme_key_unref(key);
   9.844      switch (gpgme_error) {
   9.845      case GPG_ERR_NO_ERROR:
   9.846          break;
   9.847 @@ -831,7 +878,7 @@
   9.848      assert(session);
   9.849      assert(key_data);
   9.850  
   9.851 -    gpgme_error = session->gpg.gpgme_data_new_from_mem(&dh, key_data, size, 0);
   9.852 +    gpgme_error = session->gpg->gpgme_data_new_from_mem(&dh, key_data, size, 0);
   9.853      gpgme_error = _GPGERR(gpgme_error);
   9.854      assert(gpgme_error != GPG_ERR_ENOMEM);
   9.855      switch (gpgme_error) {
   9.856 @@ -847,25 +894,25 @@
   9.857          return PEP_UNKNOWN_ERROR;
   9.858      }
   9.859  
   9.860 -    gpgme_error = session->gpg.gpgme_op_import(session->ctx, dh);
   9.861 +    gpgme_error = session->gpg->gpgme_op_import(session->ctx, dh);
   9.862      gpgme_error = _GPGERR(gpgme_error);
   9.863      switch (gpgme_error) {
   9.864      case GPG_ERR_NO_ERROR:
   9.865          break;
   9.866      case GPG_ERR_INV_VALUE:
   9.867          assert(0);
   9.868 -        session->gpg.gpgme_data_release(dh);
   9.869 +        session->gpg->gpgme_data_release(dh);
   9.870          return PEP_UNKNOWN_ERROR;
   9.871      case GPG_ERR_NO_DATA:
   9.872 -        session->gpg.gpgme_data_release(dh);
   9.873 +        session->gpg->gpgme_data_release(dh);
   9.874          return PEP_ILLEGAL_VALUE;
   9.875      default:
   9.876          assert(0);
   9.877 -        session->gpg.gpgme_data_release(dh);
   9.878 +        session->gpg->gpgme_data_release(dh);
   9.879          return PEP_UNKNOWN_ERROR;
   9.880      }
   9.881  
   9.882 -    session->gpg.gpgme_data_release(dh);
   9.883 +    session->gpg->gpgme_data_release(dh);
   9.884      return PEP_STATUS_OK;
   9.885  }
   9.886  
   9.887 @@ -884,7 +931,7 @@
   9.888      assert(key_data);
   9.889      assert(size);
   9.890  
   9.891 -    gpgme_error = session->gpg.gpgme_data_new(&dh);
   9.892 +    gpgme_error = session->gpg->gpgme_data_new(&dh);
   9.893      gpgme_error = _GPGERR(gpgme_error);
   9.894      assert(gpgme_error != GPG_ERR_ENOMEM);
   9.895      switch (gpgme_error) {
   9.896 @@ -900,37 +947,37 @@
   9.897          return PEP_UNKNOWN_ERROR;
   9.898      }
   9.899  
   9.900 -    gpgme_error = session->gpg.gpgme_op_export(session->ctx, fpr,
   9.901 +    gpgme_error = session->gpg->gpgme_op_export(session->ctx, fpr,
   9.902          GPGME_EXPORT_MODE_MINIMAL, dh);
   9.903      gpgme_error = _GPGERR(gpgme_error);
   9.904      switch (gpgme_error) {
   9.905      case GPG_ERR_NO_ERROR:
   9.906          break;
   9.907      case GPG_ERR_EOF:
   9.908 -        session->gpg.gpgme_data_release(dh);
   9.909 +        session->gpg->gpgme_data_release(dh);
   9.910          return PEP_KEY_NOT_FOUND;
   9.911      case GPG_ERR_INV_VALUE:
   9.912          assert(0);
   9.913 -        session->gpg.gpgme_data_release(dh);
   9.914 +        session->gpg->gpgme_data_release(dh);
   9.915          return PEP_UNKNOWN_ERROR;
   9.916      default:
   9.917          assert(0);
   9.918 -        session->gpg.gpgme_data_release(dh);
   9.919 +        session->gpg->gpgme_data_release(dh);
   9.920          return PEP_UNKNOWN_ERROR;
   9.921      };
   9.922  
   9.923 -    _size = session->gpg.gpgme_data_seek(dh, 0, SEEK_END);
   9.924 +    _size = session->gpg->gpgme_data_seek(dh, 0, SEEK_END);
   9.925      assert(_size != -1);
   9.926 -    session->gpg.gpgme_data_seek(dh, 0, SEEK_SET);
   9.927 +    session->gpg->gpgme_data_seek(dh, 0, SEEK_SET);
   9.928  
   9.929      buffer = malloc(_size + 1);
   9.930      assert(buffer);
   9.931      if (buffer == NULL) {
   9.932 -        session->gpg.gpgme_data_release(dh);
   9.933 +        session->gpg->gpgme_data_release(dh);
   9.934          return PEP_OUT_OF_MEMORY;
   9.935      }
   9.936  
   9.937 -    reading = session->gpg.gpgme_data_read(dh, buffer, _size);
   9.938 +    reading = session->gpg->gpgme_data_read(dh, buffer, _size);
   9.939      assert(_size == reading);
   9.940  
   9.941      // safeguard for the naive user
   9.942 @@ -939,7 +986,7 @@
   9.943      *key_data = buffer;
   9.944      *size = _size;
   9.945  
   9.946 -    session->gpg.gpgme_data_release(dh);
   9.947 +    session->gpg->gpgme_data_release(dh);
   9.948      return PEP_STATUS_OK;
   9.949  }
   9.950  
   9.951 @@ -949,12 +996,12 @@
   9.952      gpgme_error_t gpgme_error;
   9.953      gpgme_keylist_mode_t mode;
   9.954  
   9.955 -    mode = session->gpg.gpgme_get_keylist_mode(session->ctx);
   9.956 +    mode = session->gpg->gpgme_get_keylist_mode(session->ctx);
   9.957  
   9.958      mode &= ~remove_mode;
   9.959      mode |= add_mode;
   9.960  
   9.961 -    gpgme_error = session->gpg.gpgme_set_keylist_mode(session->ctx, mode);
   9.962 +    gpgme_error = session->gpg->gpgme_set_keylist_mode(session->ctx, mode);
   9.963      gpgme_error = _GPGERR(gpgme_error);
   9.964      assert(gpgme_error == GPG_ERR_NO_ERROR);
   9.965  }
   9.966 @@ -969,7 +1016,7 @@
   9.967  
   9.968      _switch_mode(session, GPGME_KEYLIST_MODE_LOCAL, GPGME_KEYLIST_MODE_EXTERN);
   9.969  
   9.970 -    gpgme_error = session->gpg.gpgme_op_keylist_start(session->ctx, pattern, 0);
   9.971 +    gpgme_error = session->gpg->gpgme_op_keylist_start(session->ctx, pattern, 0);
   9.972      gpgme_error = _GPGERR(gpgme_error);
   9.973      switch (gpgme_error) {
   9.974      case GPG_ERR_NO_ERROR:
   9.975 @@ -984,11 +1031,11 @@
   9.976      };
   9.977  
   9.978      gpgme_ctx_t import_ctx;
   9.979 -    gpgme_error = session->gpg.gpgme_new(&import_ctx);
   9.980 +    gpgme_error = session->gpg->gpgme_new(&import_ctx);
   9.981      assert(gpgme_error == GPG_ERR_NO_ERROR);
   9.982  
   9.983      do {
   9.984 -        gpgme_error = session->gpg.gpgme_op_keylist_next(session->ctx, &key);
   9.985 +        gpgme_error = session->gpg->gpgme_op_keylist_next(session->ctx, &key);
   9.986          gpgme_error = _GPGERR(gpgme_error);
   9.987          assert(gpgme_error != GPG_ERR_INV_VALUE);
   9.988          switch (gpgme_error) {
   9.989 @@ -1002,28 +1049,28 @@
   9.990              keys[0] = key;
   9.991              keys[1] = NULL;
   9.992  
   9.993 -            gpgme_error = session->gpg.gpgme_op_import_keys(import_ctx, keys);
   9.994 +            gpgme_error = session->gpg->gpgme_op_import_keys(import_ctx, keys);
   9.995              gpgme_error = _GPGERR(gpgme_error);
   9.996 -            session->gpg.gpgme_key_unref(key);
   9.997 +            session->gpg->gpgme_key_unref(key);
   9.998              assert(gpgme_error != GPG_ERR_INV_VALUE);
   9.999              assert(gpgme_error != GPG_ERR_CONFLICT);
  9.1000          }
  9.1001              break;
  9.1002          case GPG_ERR_ENOMEM:
  9.1003 -            session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1004 -            session->gpg.gpgme_release(import_ctx);
  9.1005 +            session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1006 +            session->gpg->gpgme_release(import_ctx);
  9.1007              _switch_mode(session, GPGME_KEYLIST_MODE_EXTERN, GPGME_KEYLIST_MODE_LOCAL);
  9.1008              return PEP_OUT_OF_MEMORY;
  9.1009          default:
  9.1010 -            session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1011 -            session->gpg.gpgme_release(import_ctx);
  9.1012 +            session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1013 +            session->gpg->gpgme_release(import_ctx);
  9.1014              _switch_mode(session, GPGME_KEYLIST_MODE_EXTERN, GPGME_KEYLIST_MODE_LOCAL);
  9.1015              return PEP_UNKNOWN_ERROR;
  9.1016          };
  9.1017      } while (gpgme_error != GPG_ERR_EOF);
  9.1018  
  9.1019 -    session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1020 -    session->gpg.gpgme_release(import_ctx);
  9.1021 +    session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1022 +    session->gpg->gpgme_release(import_ctx);
  9.1023      _switch_mode(session, GPGME_KEYLIST_MODE_EXTERN, GPGME_KEYLIST_MODE_LOCAL);
  9.1024      return PEP_STATUS_OK;
  9.1025  }
  9.1026 @@ -1043,7 +1090,7 @@
  9.1027  
  9.1028      *keylist = NULL;
  9.1029  
  9.1030 -    gpgme_error = session->gpg.gpgme_op_keylist_start(session->ctx, pattern, 0);
  9.1031 +    gpgme_error = session->gpg->gpgme_op_keylist_start(session->ctx, pattern, 0);
  9.1032      gpgme_error = _GPGERR(gpgme_error);
  9.1033      switch (gpgme_error) {
  9.1034      case GPG_ERR_NO_ERROR:
  9.1035 @@ -1052,7 +1099,7 @@
  9.1036          assert(0);
  9.1037          return PEP_UNKNOWN_ERROR;
  9.1038      default:
  9.1039 -        session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1040 +        session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1041          return PEP_GET_KEY_FAILED;
  9.1042      };
  9.1043  
  9.1044 @@ -1060,7 +1107,7 @@
  9.1045      stringlist_t *_k = _keylist;
  9.1046  
  9.1047      do {
  9.1048 -        gpgme_error = session->gpg.gpgme_op_keylist_next(session->ctx, &key);
  9.1049 +        gpgme_error = session->gpg->gpgme_op_keylist_next(session->ctx, &key);
  9.1050          gpgme_error = _GPGERR(gpgme_error);
  9.1051          assert(gpgme_error != GPG_ERR_INV_VALUE);
  9.1052          switch (gpgme_error) {
  9.1053 @@ -1077,15 +1124,15 @@
  9.1054                  break;
  9.1055          case GPG_ERR_ENOMEM:
  9.1056              free_stringlist(_keylist);
  9.1057 -            session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1058 +            session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1059              return PEP_OUT_OF_MEMORY;
  9.1060          default:
  9.1061 -            session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1062 +            session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1063              return PEP_UNKNOWN_ERROR;
  9.1064          };
  9.1065      } while (gpgme_error != GPG_ERR_EOF);
  9.1066  
  9.1067 -    session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1068 +    session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1069      *keylist = _keylist;
  9.1070      return PEP_STATUS_OK;
  9.1071  }
  9.1072 @@ -1097,7 +1144,7 @@
  9.1073      assert(session);
  9.1074      assert(pattern);
  9.1075  
  9.1076 -    gpgme_error = session->gpg.gpgme_op_export(session->ctx, pattern,
  9.1077 +    gpgme_error = session->gpg->gpgme_op_export(session->ctx, pattern,
  9.1078          GPGME_EXPORT_MODE_EXTERN, NULL);
  9.1079      gpgme_error = _GPGERR(gpgme_error);
  9.1080      assert(gpgme_error != GPG_ERR_INV_VALUE);
  9.1081 @@ -1124,7 +1171,7 @@
  9.1082  
  9.1083      *comm_type = PEP_ct_unknown;
  9.1084  
  9.1085 -    gpgme_error = session->gpg.gpgme_op_keylist_start(session->ctx, fpr, 0);
  9.1086 +    gpgme_error = session->gpg->gpgme_op_keylist_start(session->ctx, fpr, 0);
  9.1087      gpgme_error = _GPGERR(gpgme_error);
  9.1088      switch (gpgme_error) {
  9.1089      case GPG_ERR_NO_ERROR:
  9.1090 @@ -1136,12 +1183,12 @@
  9.1091          return PEP_GET_KEY_FAILED;
  9.1092      };
  9.1093  
  9.1094 -    gpgme_error = session->gpg.gpgme_op_keylist_next(session->ctx, &key);
  9.1095 +    gpgme_error = session->gpg->gpgme_op_keylist_next(session->ctx, &key);
  9.1096      gpgme_error = _GPGERR(gpgme_error);
  9.1097      assert(gpgme_error != GPG_ERR_INV_VALUE);
  9.1098  
  9.1099      if (key == NULL) {
  9.1100 -        session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1101 +        session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1102          return PEP_KEY_NOT_FOUND;
  9.1103      }
  9.1104  
  9.1105 @@ -1155,7 +1202,7 @@
  9.1106          break;
  9.1107      default:
  9.1108          *comm_type = PEP_ct_unknown;
  9.1109 -        session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1110 +        session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1111          return PEP_STATUS_OK;
  9.1112      }
  9.1113  
  9.1114 @@ -1193,15 +1240,15 @@
  9.1115          }
  9.1116          break;
  9.1117      case GPG_ERR_ENOMEM:
  9.1118 -        session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1119 +        session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1120          *comm_type = PEP_ct_unknown;
  9.1121          return PEP_OUT_OF_MEMORY;
  9.1122      default:
  9.1123 -        session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1124 +        session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1125          return PEP_UNKNOWN_ERROR;
  9.1126      };
  9.1127  
  9.1128 -    session->gpg.gpgme_op_keylist_end(session->ctx);
  9.1129 +    session->gpg->gpgme_op_keylist_end(session->ctx);
  9.1130  
  9.1131      return status;
  9.1132  }
    10.1 --- a/src/pgp_gpg.h	Tue Feb 10 08:27:36 2015 -0500
    10.2 +++ b/src/pgp_gpg.h	Sat Feb 21 16:55:43 2015 +0100
    10.3 @@ -2,8 +2,8 @@
    10.4  
    10.5  #include "pEpEngine.h"
    10.6  
    10.7 -PEP_STATUS pgp_init(PEP_SESSION session);
    10.8 -void pgp_release(PEP_SESSION session);
    10.9 +PEP_STATUS pgp_init(PEP_SESSION session, bool in_first);
   10.10 +void pgp_release(PEP_SESSION session, bool out_last);
   10.11  
   10.12  PEP_STATUS pgp_decrypt_and_verify(
   10.13          PEP_SESSION session, const char *ctext, size_t csize,
    11.1 --- a/src/pgp_gpg_internal.h	Tue Feb 10 08:27:36 2015 -0500
    11.2 +++ b/src/pgp_gpg_internal.h	Sat Feb 21 16:55:43 2015 +0100
    11.3 @@ -68,6 +68,7 @@
    11.4  typedef void(*gpgme_key_unref_t)(gpgme_key_t KEY);
    11.5  
    11.6  struct gpg_s {
    11.7 +    const char * version;
    11.8      gpgme_check_version_t gpgme_check;
    11.9      gpgme_set_locale_t gpgme_set_locale;
   11.10      gpgme_new_t gpgme_new;
    12.1 --- a/src/transport.c	Tue Feb 10 08:27:36 2015 -0500
    12.2 +++ b/src/transport.c	Sat Feb 21 16:55:43 2015 +0100
    12.3 @@ -4,24 +4,26 @@
    12.4  #include <memory.h>
    12.5  #include <assert.h>
    12.6  
    12.7 -PEP_STATUS init_transport_system(PEP_SESSION session)
    12.8 +PEP_STATUS init_transport_system(PEP_SESSION session, bool in_first)
    12.9  {
   12.10 +    static PEP_transport_t transports[PEP_trans__count];
   12.11 +    
   12.12      assert(session);
   12.13 +    session->transports = transports;
   12.14  
   12.15 -    pEpSession *_session = (pEpSession *) session;
   12.16 -    PEP_transport_t* transports = _session->transports;
   12.17 +    if (in_first) {
   12.18 +        assert(PEP_trans__count == 1);
   12.19 +        memset(transports, 0, sizeof(PEP_transport_t) * PEP_trans__count);
   12.20  
   12.21 -    assert(PEP_trans__count == 1);
   12.22 -    memset(transports, 0, sizeof(PEP_transport_t) * PEP_trans__count);
   12.23 -
   12.24 -    transports[PEP_trans_auto].id = PEP_trans_auto;
   12.25 -    transports[PEP_trans_auto].sendto = auto_sendto;
   12.26 -    transports[PEP_trans_auto].readnext = auto_readnext;
   12.27 +        transports[PEP_trans_auto].id = PEP_trans_auto;
   12.28 +        transports[PEP_trans_auto].sendto = auto_sendto;
   12.29 +        transports[PEP_trans_auto].readnext = auto_readnext;
   12.30 +    }
   12.31  
   12.32      return PEP_STATUS_OK;
   12.33  }
   12.34  
   12.35 -void release_transport_system(PEP_SESSION session)
   12.36 +void release_transport_system(PEP_SESSION session, bool out_last)
   12.37  {
   12.38      assert(session);
   12.39      // nothing yet