ENGINE-276: merged from default test_diphoton
authorKrista Bennett <krista@pep-project.org>
Tue, 17 Oct 2017 14:20:12 +0200
branchtest_diphoton
changeset 21664c7f95dacc6a
parent 2144 3e4507b639b1
parent 2165 51f21ed71b87
child 2172 572725ae6471
ENGINE-276: merged from default
Makefile.conf
src/keymanagement.c
src/message_api.c
src/pEpEngine.c
src/pEp_internal.h
     1.1 --- a/Makefile	Fri Oct 06 15:51:35 2017 +0200
     1.2 +++ b/Makefile	Tue Oct 17 14:20:12 2017 +0200
     1.3 @@ -7,9 +7,6 @@
     1.4  
     1.5  include Makefile.conf
     1.6  
     1.7 -# YML_PATH is needed in the environment of every call to a program of the YML2 distribution
     1.8 -export YML_PATH=$(YML2_PATH)
     1.9 -
    1.10  .PHONY: all
    1.11  all: _override_info
    1.12  	$(MAKE) -C asn.1 generate
     2.1 --- a/Makefile.conf	Fri Oct 06 15:51:35 2017 +0200
     2.2 +++ b/Makefile.conf	Tue Oct 17 14:20:12 2017 +0200
     2.3 @@ -45,12 +45,12 @@
     2.4  
     2.5  # If empty, create a release build.
     2.6  # Otherwise, create a debug build.
     2.7 -# This variable is ineffective in your override.conf file.
     2.8 -DEBUG=
     2.9 +# This variable is ineffective in your local.conf file.
    2.10 +DEBUG=YES
    2.11  
    2.12  # If empty, suppress compiler warnings.
    2.13  # Otherwise, print warnings.
    2.14 -# This variable is ineffective in your override.conf file.
    2.15 +# This variable is ineffective in your local.conf file.
    2.16  WARN=placeholder
    2.17  
    2.18  
    2.19 @@ -98,7 +98,7 @@
    2.20      else
    2.21          CFLAGS+= -O3 -DNDEBUG
    2.22      endif
    2.23 -else ifeq ($(BUILD_FOR),Darwin)    
    2.24 +else ifeq ($(BUILD_FOR),Darwin)
    2.25      ifdef WARN
    2.26          # FIXME Remove 'no-extended-offsetof' after ENGINE-236 is closed.
    2.27          CFLAGS+= -Wall -pedantic -Wno-extended-offsetof
    2.28 @@ -196,6 +196,7 @@
    2.29  
    2.30  ######### OpenPGP #########
    2.31  # Path of GPG binary
    2.32 +# gpgconf is not available for old version of GPG, for example GPG 2.0.30. Override this variable, if you compile the engine for such an old version.
    2.33  GPG_CMD:=$(shell gpgconf --list-components | awk -F: '/^gpg:/ { print $$3; exit 0; }')
    2.34  
    2.35  # Selects OpenPGP implementation. must be either `GPG` or `NETPGP`
     3.1 --- a/build-mac/pEpEngine.xcodeproj/project.pbxproj	Fri Oct 06 15:51:35 2017 +0200
     3.2 +++ b/build-mac/pEpEngine.xcodeproj/project.pbxproj	Tue Oct 17 14:20:12 2017 +0200
     3.3 @@ -123,7 +123,6 @@
     3.4  		64A826811B455D0800EECAF0 /* pEpEngine.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826601B455D0800EECAF0 /* pEpEngine.c */; };
     3.5  		64A826821B455D0800EECAF0 /* pgp_netpgp.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826631B455D0800EECAF0 /* pgp_netpgp.c */; };
     3.6  		64A826831B455D0800EECAF0 /* platform_unix.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826651B455D0800EECAF0 /* platform_unix.c */; };
     3.7 -		64A826851B455D0800EECAF0 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8266B1B455D0800EECAF0 /* sqlite3.c */; };
     3.8  		64A826861B455D0800EECAF0 /* stringlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8266D1B455D0800EECAF0 /* stringlist.c */; };
     3.9  		64A826871B455D0800EECAF0 /* stringpair.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8266F1B455D0800EECAF0 /* stringpair.c */; };
    3.10  		64A826881B455D0800EECAF0 /* timestamp.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826711B455D0800EECAF0 /* timestamp.c */; };
    3.11 @@ -815,7 +814,6 @@
    3.12  				64A826861B455D0800EECAF0 /* stringlist.c in Sources */,
    3.13  				4354FF651D6EDF300033069C /* sync_impl.c in Sources */,
    3.14  				64A8267E1B455D0800EECAF0 /* message_api.c in Sources */,
    3.15 -				64A826851B455D0800EECAF0 /* sqlite3.c in Sources */,
    3.16  				43E9BC7F1DB6720E00AD2352 /* UpdateRequest.c in Sources */,
    3.17  				646C41361D510CD800C63EFF /* Version.c in Sources */,
    3.18  				646C41081D510CD800C63EFF /* constr_TYPE.c in Sources */,
    3.19 @@ -959,6 +957,7 @@
    3.20  				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
    3.21  				MTL_ENABLE_DEBUG_INFO = YES;
    3.22  				ONLY_ACTIVE_ARCH = YES;
    3.23 +				OTHER_CFLAGS = "-DSQLITE3_FROM_OS";
    3.24  				SDKROOT = iphoneos;
    3.25  			};
    3.26  			name = Debug;
    3.27 @@ -1006,6 +1005,7 @@
    3.28  				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
    3.29  				MTL_ENABLE_DEBUG_INFO = NO;
    3.30  				ONLY_ACTIVE_ARCH = NO;
    3.31 +				OTHER_CFLAGS = "-DSQLITE3_FROM_OS";
    3.32  				SDKROOT = iphoneos;
    3.33  				VALIDATE_PRODUCT = YES;
    3.34  			};
     4.1 --- a/doc/build-debian.md	Fri Oct 06 15:51:35 2017 +0200
     4.2 +++ b/doc/build-debian.md	Tue Oct 17 14:20:12 2017 +0200
     4.3 @@ -17,7 +17,7 @@
     4.4  # asn1c
     4.5  apt install -y git build-essential automake libtool
     4.6  # engine
     4.7 -apt install -y uuid-dev libgpgme11-dev libsqlite3-dev sqlite3
     4.8 +apt install -y uuid-dev libgpgme-dev libsqlite3-dev sqlite3
     4.9  ~~~
    4.10  
    4.11  # Installing unpackaged dependencies
     5.1 --- a/src/keymanagement.c	Fri Oct 06 15:51:35 2017 +0200
     5.2 +++ b/src/keymanagement.c	Tue Oct 17 14:20:12 2017 +0200
     5.3 @@ -736,12 +736,38 @@
     5.4      }
     5.5      else
     5.6      {
     5.7 +        // for undo
     5.8 +        if (session->cached_mistrusted)
     5.9 +            free(session->cached_mistrusted);
    5.10 +        session->cached_mistrusted = identity_dup(ident);
    5.11          status = mark_as_compromized(session, ident->fpr);
    5.12      }
    5.13  
    5.14      return status;
    5.15  }
    5.16  
    5.17 +DYNAMIC_API PEP_STATUS undo_last_mistrust(PEP_SESSION session) {
    5.18 +    assert(session);
    5.19 +    
    5.20 +    if (!session)
    5.21 +        return PEP_ILLEGAL_VALUE;
    5.22 +    
    5.23 +    PEP_STATUS status = PEP_STATUS_OK;
    5.24 +        
    5.25 +    pEp_identity* cached_ident = session->cached_mistrusted;
    5.26 +    
    5.27 +    if (!cached_ident)
    5.28 +        status = PEP_CANNOT_FIND_IDENTITY;
    5.29 +    else {
    5.30 +        status = set_identity(session, cached_ident);            
    5.31 +        free_identity(session->cached_mistrusted);
    5.32 +    }
    5.33 +    
    5.34 +    session->cached_mistrusted = NULL;
    5.35 +
    5.36 +    return status;
    5.37 +}
    5.38 +
    5.39  DYNAMIC_API PEP_STATUS key_reset_trust(
    5.40          PEP_SESSION session,
    5.41          pEp_identity *ident
     6.1 --- a/src/keymanagement.h	Fri Oct 06 15:51:35 2017 +0200
     6.2 +++ b/src/keymanagement.h	Tue Oct 17 14:20:12 2017 +0200
     6.3 @@ -125,17 +125,35 @@
     6.4      );
     6.5  
     6.6  
     6.7 -// key_mistrusted() - mark key as being compromized
     6.8 +// key_mistrusted() - mark key as being compromised
     6.9  //
    6.10  //  parameters:
    6.11  //      session (in)        session to use
    6.12 -//      ident (in)          person and key which was compromized
    6.13 +//      ident (in)          person and key which was compromised
    6.14  
    6.15  DYNAMIC_API PEP_STATUS key_mistrusted(
    6.16          PEP_SESSION session,
    6.17          pEp_identity *ident
    6.18      );
    6.19  
    6.20 +// undo_last_mistrust() - reset identity and trust status for the last
    6.21 +//                        identity in this session marked as mistrusted
    6.22 +//                        to their cached values from the time of mistrust
    6.23 +//  parameters:
    6.24 +//      session (in)        session to use
    6.25 +//
    6.26 +//  return value:
    6.27 +//      PEP_STATUS_OK if identity and trust were successfully restored.
    6.28 +//      Otherwise, error status from attempts to set.
    6.29 +//
    6.30 +//  caveat:
    6.31 +//      only works for this session, and only once. cache is invalidated
    6.32 +//      upon use.
    6.33 +//
    6.34 +//      WILL NOT WORK ON MISTRUSTED OWN KEY
    6.35 +
    6.36 +DYNAMIC_API PEP_STATUS undo_last_mistrust(PEP_SESSION session);
    6.37 +
    6.38  
    6.39  // trust_personal_key() - mark a key as trusted with a person
    6.40  //
     7.1 --- a/src/message.h	Fri Oct 06 15:51:35 2017 +0200
     7.2 +++ b/src/message.h	Tue Oct 17 14:20:12 2017 +0200
     7.3 @@ -163,4 +163,3 @@
     7.4  #ifdef __cplusplus
     7.5  }
     7.6  #endif
     7.7 -
     8.1 --- a/src/message_api.c	Fri Oct 06 15:51:35 2017 +0200
     8.2 +++ b/src/message_api.c	Tue Oct 17 14:20:12 2017 +0200
     8.3 @@ -20,628 +20,27 @@
     8.4  #define _MAX(A, B) ((B) > (A) ? (B) : (A))
     8.5  #endif
     8.6  
     8.7 -static char* _get_resource_ptr_noown(char* uri) {
     8.8 -    char* uri_delim = strstr(uri, "://");
     8.9 -    if (!uri_delim)
    8.10 -        return uri;
    8.11 -    else
    8.12 -        return uri + 3;
    8.13 -}
    8.14 -
    8.15 -static bool is_file_uri(char* str) {
    8.16 -    return(strncmp(str, "file://", 7) == 0);
    8.17 -}
    8.18 -
    8.19 -static bool is_cid_uri(const char* str) {
    8.20 -    return(strncmp(str, "cid://", 6) == 0);
    8.21 -}
    8.22 -
    8.23 -static bool string_equality(const char *s1, const char *s2)
    8.24 -{
    8.25 -    if (s1 == NULL || s2 == NULL)
    8.26 -        return false;
    8.27 -
    8.28 -    assert(s1 && s2);
    8.29 -
    8.30 -    return strcmp(s1, s2) == 0;
    8.31 -}
    8.32 -
    8.33 -static bool is_mime_type(const bloblist_t *bl, const char *mt)
    8.34 -{
    8.35 -    assert(mt);
    8.36 -
    8.37 -    return bl && string_equality(bl->mime_type, mt);
    8.38 -}
    8.39 -
    8.40 -//
    8.41 -// This function presumes the file ending is a proper substring of the
    8.42 -// filename (i.e. if bl->filename is "a.pgp" and fe is ".pgp", it will
    8.43 -// return true, but if bl->filename is ".pgp" and fe is ".pgp", it will
    8.44 -// return false. This is desired behaviour.
    8.45 -//
    8.46 -static bool is_fileending(const bloblist_t *bl, const char *fe)
    8.47 -{
    8.48 -    assert(fe);
    8.49 -
    8.50 -    if (bl == NULL || bl->filename == NULL || fe == NULL || is_cid_uri(bl->filename))
    8.51 -        return false;
    8.52 -
    8.53 -    assert(bl && bl->filename);
    8.54 -
    8.55 -    size_t fe_len = strlen(fe);
    8.56 -    size_t fn_len = strlen(bl->filename);
    8.57 -
    8.58 -    if (fn_len <= fe_len)
    8.59 -        return false;
    8.60 -
    8.61 -    assert(fn_len > fe_len);
    8.62 -
    8.63 -    return strcmp(bl->filename + (fn_len - fe_len), fe) == 0;
    8.64 -}
    8.65 -
    8.66 -void add_opt_field(message *msg, const char *name, const char *value)
    8.67 -{
    8.68 -    assert(msg && name && value);
    8.69 -
    8.70 -    if (msg && name && value) {
    8.71 -        stringpair_t *pair = new_stringpair(name, value);
    8.72 -        if (pair == NULL)
    8.73 -            return;
    8.74 -
    8.75 -        stringpair_list_t *field = stringpair_list_add(msg->opt_fields, pair);
    8.76 -        if (field == NULL)
    8.77 -        {
    8.78 -            free_stringpair(pair);
    8.79 -            return;
    8.80 -        }
    8.81 -
    8.82 -        if (msg->opt_fields == NULL)
    8.83 -            msg->opt_fields = field;
    8.84 -    }
    8.85 -}
    8.86 -
    8.87 -static char * combine_short_and_long(const char *shortmsg, const char *longmsg)
    8.88 -{
    8.89 -    assert(shortmsg);
    8.90 -    
    8.91 -    unsigned char pepstr[] = PEP_SUBJ_STRING;
    8.92 -    assert(strcmp(shortmsg, "pEp") != 0 && _unsigned_signed_strcmp(pepstr, shortmsg, PEP_SUBJ_BYTELEN) != 0); 
    8.93 -    
    8.94 -    if (!shortmsg || strcmp(shortmsg, "pEp") == 0 || 
    8.95 -                     _unsigned_signed_strcmp(pepstr, shortmsg, PEP_SUBJ_BYTELEN) == 0) {
    8.96 -        if (!longmsg) {
    8.97 -            return NULL;
    8.98 -        }
    8.99 -        else {
   8.100 -            char *result = strdup(longmsg);
   8.101 -            assert(result);
   8.102 -            return result;
   8.103 -        }
   8.104 -    }
   8.105 -
   8.106 -    if (longmsg == NULL)
   8.107 -        longmsg = "";
   8.108 -
   8.109 -    const char * const subject = "Subject: ";
   8.110 -    const size_t SUBJ_LEN = 9;
   8.111 -    const char * const newlines = "\n\n";
   8.112 -    const size_t NL_LEN = 2;
   8.113 -
   8.114 -    const size_t bufsize = SUBJ_LEN + strlen(shortmsg) + NL_LEN + strlen(longmsg) + 1;
   8.115 -    char * ptext = calloc(1, bufsize);
   8.116 -    assert(ptext);
   8.117 -    if (ptext == NULL)
   8.118 -        return NULL;
   8.119 -
   8.120 -    strlcpy(ptext, subject, bufsize);
   8.121 -    strlcat(ptext, shortmsg, bufsize);
   8.122 -    strlcat(ptext, newlines, bufsize);
   8.123 -    strlcat(ptext, longmsg, bufsize);
   8.124 -
   8.125 -    return ptext;
   8.126 -}
   8.127 -
   8.128 -static int separate_short_and_long(const char *src, char **shortmsg, char **longmsg)
   8.129 -{
   8.130 -    char *_shortmsg = NULL;
   8.131 -    char *_longmsg = NULL;
   8.132 -
   8.133 -    assert(src);
   8.134 -    assert(shortmsg);
   8.135 -    assert(longmsg);
   8.136 -
   8.137 -    if (src == NULL || shortmsg == NULL || longmsg == NULL)
   8.138 -        return -1;
   8.139 -
   8.140 -    *shortmsg = NULL;
   8.141 -    *longmsg = NULL;
   8.142 -
   8.143 -    if (strncasecmp(src, "subject: ", 9) == 0) {
   8.144 -        char *line_end = strchr(src, '\n');
   8.145 -
   8.146 -        if (line_end == NULL) {
   8.147 -            _shortmsg = strdup(src + 9);
   8.148 -            assert(_shortmsg);
   8.149 -            if (_shortmsg == NULL)
   8.150 -                goto enomem;
   8.151 -            // _longmsg = NULL;
   8.152 -        }
   8.153 -        else {
   8.154 -            size_t n = line_end - src;
   8.155 -
   8.156 -            if (*(line_end - 1) == '\r')
   8.157 -                _shortmsg = strndup(src + 9, n - 10);
   8.158 -            else
   8.159 -                _shortmsg = strndup(src + 9, n - 9);
   8.160 -            assert(_shortmsg);
   8.161 -            if (_shortmsg == NULL)
   8.162 -                goto enomem;
   8.163 -
   8.164 -            while (*(src + n) && (*(src + n) == '\n' || *(src + n) == '\r'))
   8.165 -                ++n;
   8.166 -
   8.167 -            if (*(src + n)) {
   8.168 -                _longmsg = strdup(src + n);
   8.169 -                assert(_longmsg);
   8.170 -                if (_longmsg == NULL)
   8.171 -                    goto enomem;
   8.172 -            }
   8.173 -        }
   8.174 -        *shortmsg = _shortmsg;
   8.175 -    }
   8.176 -    else {
   8.177 -        // If there's no "Subject: " and the shortmsg is
   8.178 -        // pEp (or anything else), then we shouldn't be replacing it.
   8.179 -        // Chances are that the message wasn't encrypted
   8.180 -        // using pEp and that the actually subject IS pEp. In any event,
   8.181 -        // erasing the subject line when we don't have one in the plaintext
   8.182 -        // isn't the right behaviour.
   8.183 -        // _shortmsg = strdup("");
   8.184 -        _longmsg = strdup(src);
   8.185 -        assert(_longmsg);
   8.186 -        if (_longmsg == NULL)
   8.187 -            goto enomem;
   8.188 -    }
   8.189 -    
   8.190 -    *longmsg = _longmsg;
   8.191 -
   8.192 -    return 0;
   8.193 -
   8.194 -enomem:
   8.195 -    free(_shortmsg);
   8.196 -    free(_longmsg);
   8.197 -
   8.198 -    return -1;
   8.199 -}
   8.200 -
   8.201 -static PEP_STATUS copy_fields(message *dst, const message *src)
   8.202 -{
   8.203 -    assert(dst);
   8.204 -    assert(src);
   8.205 -
   8.206 -    if(!(dst && src))
   8.207 -        return PEP_ILLEGAL_VALUE;
   8.208 -
   8.209 -    free_timestamp(dst->sent);
   8.210 -    dst->sent = NULL;
   8.211 -    if (src->sent) {
   8.212 -        dst->sent = timestamp_dup(src->sent);
   8.213 -        if (dst->sent == NULL)
   8.214 -            return PEP_OUT_OF_MEMORY;
   8.215 -    }
   8.216 -
   8.217 -    free_timestamp(dst->recv);
   8.218 -    dst->recv = NULL;
   8.219 -    if (src->recv) {
   8.220 -        dst->recv = timestamp_dup(src->recv);
   8.221 -        if (dst->recv == NULL)
   8.222 -            return PEP_OUT_OF_MEMORY;
   8.223 -    }
   8.224 -
   8.225 -    free_identity(dst->from);
   8.226 -    dst->from = NULL;
   8.227 -    if (src->from) {
   8.228 -        dst->from = identity_dup(src->from);
   8.229 -        if (dst->from == NULL)
   8.230 -            return PEP_OUT_OF_MEMORY;
   8.231 -    }
   8.232 -
   8.233 -    free_identity_list(dst->to);
   8.234 -    dst->to = NULL;
   8.235 -    if (src->to && src->to->ident) {
   8.236 -        dst->to = identity_list_dup(src->to);
   8.237 -        if (dst->to == NULL)
   8.238 -            return PEP_OUT_OF_MEMORY;
   8.239 -    }
   8.240 -
   8.241 -    free_identity(dst->recv_by);
   8.242 -    dst->recv_by = NULL;
   8.243 -    if (src->recv_by) {
   8.244 -        dst->recv_by = identity_dup(src->recv_by);
   8.245 -        if (dst->recv_by == NULL)
   8.246 -            return PEP_OUT_OF_MEMORY;
   8.247 -    }
   8.248 -
   8.249 -    free_identity_list(dst->cc);
   8.250 -    dst->cc = NULL;
   8.251 -    if (src->cc && src->cc->ident) {
   8.252 -        dst->cc = identity_list_dup(src->cc);
   8.253 -        if (dst->cc == NULL)
   8.254 -            return PEP_OUT_OF_MEMORY;
   8.255 -    }
   8.256 -
   8.257 -    free_identity_list(dst->bcc);
   8.258 -    dst->bcc = NULL;
   8.259 -    if (src->bcc && src->bcc->ident) {
   8.260 -        dst->bcc = identity_list_dup(src->bcc);
   8.261 -        if (dst->bcc == NULL)
   8.262 -            return PEP_OUT_OF_MEMORY;
   8.263 -    }
   8.264 -
   8.265 -    free_identity_list(dst->reply_to);
   8.266 -    dst->reply_to = NULL;
   8.267 -    if (src->reply_to && src->reply_to->ident) {
   8.268 -        dst->reply_to = identity_list_dup(src->reply_to);
   8.269 -        if (dst->reply_to == NULL)
   8.270 -            return PEP_OUT_OF_MEMORY;
   8.271 -    }
   8.272 -
   8.273 -    free_stringlist(dst->in_reply_to);
   8.274 -    dst->in_reply_to = NULL;
   8.275 -    if (src->in_reply_to && src->in_reply_to->value) {
   8.276 -        dst->in_reply_to = stringlist_dup(src->in_reply_to);
   8.277 -        if (dst->in_reply_to == NULL)
   8.278 -            return PEP_OUT_OF_MEMORY;
   8.279 -    }
   8.280 -
   8.281 -    free_stringlist(dst->references);
   8.282 -    dst->references = NULL;
   8.283 -    if (src->references) {
   8.284 -        dst->references = stringlist_dup(src->references);
   8.285 -        if (dst->references == NULL)
   8.286 -            return PEP_OUT_OF_MEMORY;
   8.287 -    }
   8.288 -
   8.289 -    free_stringlist(dst->keywords);
   8.290 -    dst->keywords = NULL;
   8.291 -    if (src->keywords && src->keywords->value) {
   8.292 -        dst->keywords = stringlist_dup(src->keywords);
   8.293 -        if (dst->keywords == NULL)
   8.294 -            return PEP_OUT_OF_MEMORY;
   8.295 -    }
   8.296 -
   8.297 -    free(dst->comments);
   8.298 -    dst->comments = NULL;
   8.299 -    if (src->comments) {
   8.300 -        dst->comments = strdup(src->comments);
   8.301 -        assert(dst->comments);
   8.302 -        if (dst->comments == NULL)
   8.303 -            return PEP_OUT_OF_MEMORY;
   8.304 -    }
   8.305 -
   8.306 -    free_stringpair_list(dst->opt_fields);
   8.307 -    dst->opt_fields = NULL;
   8.308 -    if (src->opt_fields) {
   8.309 -        dst->opt_fields = stringpair_list_dup(src->opt_fields);
   8.310 -        if (dst->opt_fields == NULL)
   8.311 -            return PEP_OUT_OF_MEMORY;
   8.312 -    }
   8.313 -
   8.314 -    return PEP_STATUS_OK;
   8.315 -}
   8.316 -
   8.317 -static message * clone_to_empty_message(const message * src)
   8.318 -{
   8.319 -    PEP_STATUS status;
   8.320 -    message * msg = NULL;
   8.321 -
   8.322 -    assert(src);
   8.323 -    if (src == NULL)
   8.324 -        return NULL;
   8.325 -
   8.326 -    msg = calloc(1, sizeof(message));
   8.327 -    assert(msg);
   8.328 -    if (msg == NULL)
   8.329 -        goto enomem;
   8.330 -
   8.331 -    msg->dir = src->dir;
   8.332 -
   8.333 -    status = copy_fields(msg, src);
   8.334 -    if (status != PEP_STATUS_OK)
   8.335 -        goto enomem;
   8.336 -
   8.337 -    return msg;
   8.338 -
   8.339 -enomem:
   8.340 -    free_message(msg);
   8.341 -    return NULL;
   8.342 -}
   8.343 -
   8.344 -static PEP_STATUS encrypt_PGP_MIME(
   8.345 -    PEP_SESSION session,
   8.346 -    const message *src,
   8.347 -    stringlist_t *keys,
   8.348 -    message *dst,
   8.349 -    PEP_encrypt_flags_t flags
   8.350 -    )
   8.351 -{
   8.352 -    PEP_STATUS status = PEP_STATUS_OK;
   8.353 -    bool free_ptext = false;
   8.354 -    char *ptext = NULL;
   8.355 -    char *ctext = NULL;
   8.356 -    char *mimetext = NULL;
   8.357 -    size_t csize;
   8.358 -    assert(dst->longmsg == NULL);
   8.359 -    dst->enc_format = PEP_enc_PGP_MIME;
   8.360 -    unsigned char pepstr[] = PEP_SUBJ_STRING;
   8.361 -
   8.362 -    if (src->shortmsg && strcmp(src->shortmsg, "pEp") != 0 
   8.363 -                      && _unsigned_signed_strcmp(pepstr, src->shortmsg, PEP_SUBJ_BYTELEN) != 0) {
   8.364 -        if (session->unencrypted_subject) {
   8.365 -            dst->shortmsg = strdup(src->shortmsg);
   8.366 -            assert(dst->shortmsg);
   8.367 -            if (dst->shortmsg == NULL)
   8.368 -                goto enomem;
   8.369 -            ptext = src->longmsg;
   8.370 -        }
   8.371 -        else {
   8.372 -            ptext = combine_short_and_long(src->shortmsg, src->longmsg);
   8.373 -            if (ptext == NULL)
   8.374 -                goto enomem;
   8.375 -            free_ptext = true;
   8.376 -        }
   8.377 -    }
   8.378 -    else if (src->longmsg) {
   8.379 -        ptext = src->longmsg;
   8.380 -    }
   8.381 -    else {
   8.382 -        ptext = (char*)pepstr;
   8.383 -    }
   8.384 -
   8.385 -    message *_src = calloc(1, sizeof(message));
   8.386 -    assert(_src);
   8.387 -    if (_src == NULL)
   8.388 -        goto enomem;
   8.389 -    _src->longmsg = ptext;
   8.390 -    _src->longmsg_formatted = src->longmsg_formatted;
   8.391 -    _src->attachments = src->attachments;
   8.392 -    _src->enc_format = PEP_enc_none;
   8.393 -    status = mime_encode_message(_src, true, &mimetext);
   8.394 -    assert(status == PEP_STATUS_OK);
   8.395 -    if (status != PEP_STATUS_OK)
   8.396 -        goto pep_error;
   8.397 -
   8.398 -    if (free_ptext){
   8.399 -        free(ptext);
   8.400 -        free_ptext=0;
   8.401 -    }
   8.402 -    free(_src);
   8.403 -    assert(mimetext);
   8.404 -    if (mimetext == NULL)
   8.405 -        goto pep_error;
   8.406 -
   8.407 -    if (flags & PEP_encrypt_flag_force_unsigned)
   8.408 -        status = encrypt_only(session, keys, mimetext, strlen(mimetext),
   8.409 -            &ctext, &csize);
   8.410 -    else
   8.411 -        status = encrypt_and_sign(session, keys, mimetext, strlen(mimetext),
   8.412 -            &ctext, &csize);
   8.413 -    free(mimetext);
   8.414 -    if (ctext == NULL)
   8.415 -        goto pep_error;
   8.416 -
   8.417 -    dst->longmsg = strdup("this message was encrypted with p≡p "
   8.418 -        "https://pEp-project.org");
   8.419 -    assert(dst->longmsg);
   8.420 -    if (dst->longmsg == NULL)
   8.421 -        goto enomem;
   8.422 -
   8.423 -    char *v = strdup("Version: 1");
   8.424 -    assert(v);
   8.425 -    if (v == NULL)
   8.426 -        goto enomem;
   8.427 -
   8.428 -    bloblist_t *_a = new_bloblist(v, strlen(v), "application/pgp-encrypted", NULL);
   8.429 -    if (_a == NULL)
   8.430 -        goto enomem;
   8.431 -    dst->attachments = _a;
   8.432 -
   8.433 -    _a = bloblist_add(_a, ctext, csize, "application/octet-stream",
   8.434 -        "file://msg.asc");
   8.435 -    if (_a == NULL)
   8.436 -        goto enomem;
   8.437 -
   8.438 -    return PEP_STATUS_OK;
   8.439 -
   8.440 -enomem:
   8.441 -    status = PEP_OUT_OF_MEMORY;
   8.442 -
   8.443 -pep_error:
   8.444 -    if (free_ptext)
   8.445 -        free(ptext);
   8.446 -    free(ctext);
   8.447 -    return status;
   8.448 -}
   8.449 -
   8.450 -static PEP_STATUS encrypt_PGP_in_pieces(
   8.451 -    PEP_SESSION session,
   8.452 -    const message *src,
   8.453 -    stringlist_t *keys,
   8.454 -    message *dst,
   8.455 -    PEP_encrypt_flags_t flags
   8.456 -    )
   8.457 -{
   8.458 -    PEP_STATUS status = PEP_STATUS_OK;
   8.459 -    char *ctext = NULL;
   8.460 -    size_t csize;
   8.461 -    char *ptext = NULL;
   8.462 -    bool free_ptext = false;
   8.463 -    unsigned char pepstr[] = PEP_SUBJ_STRING;
   8.464 -    
   8.465 -    assert(dst->longmsg == NULL);
   8.466 -    assert(dst->attachments == NULL);
   8.467 -
   8.468 -    dst->enc_format = PEP_enc_pieces;
   8.469 -
   8.470 -    bool nosign = (flags & PEP_encrypt_flag_force_unsigned);
   8.471 -
   8.472 -    if (src->shortmsg && src->shortmsg[0] && strcmp(src->shortmsg, "pEp") != 0 && 
   8.473 -        _unsigned_signed_strcmp(pepstr, src->shortmsg, PEP_SUBJ_BYTELEN) != 0) {
   8.474 -        if (session->unencrypted_subject) {
   8.475 -            dst->shortmsg = strdup(src->shortmsg);
   8.476 -            assert(dst->shortmsg);
   8.477 -            if (dst->shortmsg == NULL)
   8.478 -                goto enomem;
   8.479 -            ptext = src->longmsg;
   8.480 -        }
   8.481 -        else {
   8.482 -            ptext = combine_short_and_long(src->shortmsg, src->longmsg);
   8.483 -            if (ptext == NULL)
   8.484 -                goto enomem;
   8.485 -            free_ptext = true;
   8.486 -        }
   8.487 -
   8.488 -        if (nosign)
   8.489 -            status = encrypt_only(session, keys, ptext, strlen(ptext), &ctext,
   8.490 -                &csize);
   8.491 -        else 
   8.492 -            status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
   8.493 -                &csize);
   8.494 -        if (free_ptext)
   8.495 -            free(ptext);
   8.496 -        free_ptext = false;
   8.497 -        if (ctext) {
   8.498 -            dst->longmsg = ctext;
   8.499 -        }
   8.500 -        else {
   8.501 -            goto pep_error;
   8.502 -        }
   8.503 -    }
   8.504 -    else if (src->longmsg && src->longmsg[0]) {
   8.505 -        ptext = src->longmsg;
   8.506 -        if (nosign)
   8.507 -            status = encrypt_only(session, keys, ptext, strlen(ptext), &ctext,
   8.508 -                &csize);
   8.509 -        else 
   8.510 -            status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
   8.511 -                &csize);
   8.512 -        if (ctext) {
   8.513 -            dst->longmsg = ctext;
   8.514 -        }
   8.515 -        else {
   8.516 -            goto pep_error;
   8.517 -        }
   8.518 -    }
   8.519 -    else {
   8.520 -        dst->longmsg = strdup("");
   8.521 -        assert(dst->longmsg);
   8.522 -        if (dst->longmsg == NULL)
   8.523 -            goto enomem;
   8.524 -    }
   8.525 -
   8.526 -    if (src->longmsg_formatted && src->longmsg_formatted[0]) {
   8.527 -        ptext = src->longmsg_formatted;
   8.528 -        if (nosign)
   8.529 -            status = encrypt_only(session, keys, ptext, strlen(ptext), &ctext,
   8.530 -                &csize);
   8.531 -        else 
   8.532 -            status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
   8.533 -                &csize);
   8.534 -        if (ctext) {
   8.535 -
   8.536 -            bloblist_t *_a = bloblist_add(dst->attachments, ctext, csize,
   8.537 -                "application/octet-stream", "file://PGPexch.htm.pgp");
   8.538 -            if (_a == NULL)
   8.539 -                goto enomem;
   8.540 -            if (dst->attachments == NULL)
   8.541 -                dst->attachments = _a;
   8.542 -        }
   8.543 -        else {
   8.544 -            goto pep_error;
   8.545 -        }
   8.546 -    }
   8.547 -
   8.548 -    if (src->attachments) {
   8.549 -        if (dst->attachments == NULL) {
   8.550 -            dst->attachments = new_bloblist(NULL, 0, NULL, NULL);
   8.551 -            if (dst->attachments == NULL)
   8.552 -                goto enomem;
   8.553 -        }
   8.554 -
   8.555 -        bloblist_t *_s = src->attachments;
   8.556 -        bloblist_t *_d = dst->attachments;
   8.557 -
   8.558 -        for (int n = 0; _s; _s = _s->next) {
   8.559 -            if (_s->value == NULL && _s->size == 0) {
   8.560 -                _d = bloblist_add(_d, NULL, 0, _s->mime_type, _s->filename);
   8.561 -                if (_d == NULL)
   8.562 -                    goto enomem;
   8.563 -            }
   8.564 -            else {
   8.565 -                size_t psize = _s->size;
   8.566 -                ptext = _s->value;
   8.567 -                if (nosign)
   8.568 -                    status = encrypt_only(session, keys, ptext, psize, &ctext,
   8.569 -                        &csize);
   8.570 -                else 
   8.571 -                    status = encrypt_and_sign(session, keys, ptext, psize, &ctext,
   8.572 -                        &csize);
   8.573 -                if (ctext) {
   8.574 -                    char *filename = NULL;
   8.575 -
   8.576 -                    char *attach_fn = _s->filename;
   8.577 -                    if (attach_fn && !is_cid_uri(attach_fn)) {
   8.578 -                        size_t len = strlen(_s->filename);
   8.579 -                        size_t bufsize = len + 5; // length of .pgp extension + NUL
   8.580 -                        bool already_uri = false;
   8.581 -                        if (is_file_uri(attach_fn))
   8.582 -                            already_uri = true;
   8.583 -                        else
   8.584 -                            bufsize += 7; // length of file://
   8.585 -                            
   8.586 -                        filename = calloc(1, bufsize);
   8.587 -                        if (filename == NULL)
   8.588 -                            goto enomem;
   8.589 -
   8.590 -                        if (!already_uri)
   8.591 -                            strlcpy(filename, "file://", bufsize);
   8.592 -                        // First char is NUL, so we're ok, even if not copying above. (calloc)
   8.593 -                        strlcat(filename, _s->filename, bufsize);
   8.594 -                        strlcat(filename, ".pgp", bufsize);
   8.595 -                    }
   8.596 -                    else {
   8.597 -                        filename = calloc(1, 27);
   8.598 -                        if (filename == NULL)
   8.599 -                            goto enomem;
   8.600 -
   8.601 -                        ++n;
   8.602 -                        n &= 0xffff;
   8.603 -                        snprintf(filename, 20, "file://Attachment%d.pgp", n);
   8.604 -                    }
   8.605 -
   8.606 -                    _d = bloblist_add(_d, ctext, csize, "application/octet-stream",
   8.607 -                        filename);
   8.608 -                    free(filename);
   8.609 -                    if (_d == NULL)
   8.610 -                        goto enomem;
   8.611 -                }
   8.612 -                else {
   8.613 -                    goto pep_error;
   8.614 -                }
   8.615 -            }
   8.616 -        }
   8.617 -    }
   8.618 -
   8.619 -    return PEP_STATUS_OK;
   8.620 -
   8.621 -enomem:
   8.622 -    status = PEP_OUT_OF_MEMORY;
   8.623 -
   8.624 -pep_error:
   8.625 -    if (free_ptext)
   8.626 -        free(ptext);
   8.627 -    return status;
   8.628 -}
   8.629 +// static const char* search_opt_fields(message* src, char* key) {
   8.630 +//     assert(src);
   8.631 +//     assert(key);
   8.632 +//     if (src && key) {
   8.633 +//         stringpair_list_t opt_fields = src->opt_fields;
   8.634 +//         while (opt_fields) {
   8.635 +//             char* currkey = opt_fields->value->key;
   8.636 +//             if (strcmp(currkey, key) == 0) {
   8.637 +//                 return opt_fields->value->value;
   8.638 +//             }
   8.639 +//             opt_fields = opt_fields->next;
   8.640 +//         }
   8.641 +//     }
   8.642 +//     return NULL;
   8.643 +// }
   8.644 +// 
   8.645 +// static const char* get_message_version_string(message* src) {
   8.646 +//     const char* version_key = "X-pEp-Version";
   8.647 +//     return(search_opt_fields(src, version_key));
   8.648 +// }
   8.649 +
   8.650  
   8.651  static char * keylist_to_string(const stringlist_t *keylist)
   8.652  {
   8.653 @@ -703,6 +102,56 @@
   8.654      }
   8.655  }
   8.656  
   8.657 +void add_opt_field(message *msg, const char *name, const char *value)
   8.658 +{
   8.659 +    assert(msg && name && value);
   8.660 +
   8.661 +    if (msg && name && value) {
   8.662 +        stringpair_t *pair = new_stringpair(name, value);
   8.663 +        if (pair == NULL)
   8.664 +            return;
   8.665 +
   8.666 +        stringpair_list_t *field = stringpair_list_add(msg->opt_fields, pair);
   8.667 +        if (field == NULL)
   8.668 +        {
   8.669 +            free_stringpair(pair);
   8.670 +            return;
   8.671 +        }
   8.672 +
   8.673 +        if (msg->opt_fields == NULL)
   8.674 +            msg->opt_fields = field;
   8.675 +    }
   8.676 +}
   8.677 +
   8.678 +void replace_opt_field(message *msg, const char *name, const char *value)
   8.679 +{
   8.680 +    assert(msg && name && value);
   8.681 +    
   8.682 +    if (msg && name && value) {
   8.683 +        stringpair_list_t* opt_fields = msg->opt_fields;
   8.684 +        stringpair_t* pair = NULL;
   8.685 +        if (opt_fields) {
   8.686 +            while (opt_fields) {
   8.687 +                pair = opt_fields->value;
   8.688 +                if (pair && (strcmp(name, pair->key) == 0))
   8.689 +                    break;
   8.690 +                    
   8.691 +                pair = NULL;
   8.692 +                opt_fields = opt_fields->next;
   8.693 +            }
   8.694 +        }
   8.695 +        
   8.696 +        if (pair) {
   8.697 +            free(pair->value);
   8.698 +            pair->value = strdup(value);
   8.699 +        }
   8.700 +        else {
   8.701 +            add_opt_field(msg, name, value);
   8.702 +        }
   8.703 +    }
   8.704 +}
   8.705 +
   8.706 +
   8.707  static void decorate_message(
   8.708      message *msg,
   8.709      PEP_rating rating,
   8.710 @@ -711,18 +160,595 @@
   8.711  {
   8.712      assert(msg);
   8.713  
   8.714 -    add_opt_field(msg, "X-pEp-Version", PEP_VERSION);
   8.715 +    replace_opt_field(msg, "X-pEp-Version", PEP_VERSION);
   8.716  
   8.717      if (rating != PEP_rating_undefined)
   8.718 -        add_opt_field(msg, "X-EncStatus", rating_to_string(rating));
   8.719 +        replace_opt_field(msg, "X-EncStatus", rating_to_string(rating));
   8.720  
   8.721      if (keylist) {
   8.722          char *_keylist = keylist_to_string(keylist);
   8.723 -        add_opt_field(msg, "X-KeyList", _keylist);
   8.724 +        replace_opt_field(msg, "X-KeyList", _keylist);
   8.725          free(_keylist);
   8.726      }
   8.727  }
   8.728  
   8.729 +static char* _get_resource_ptr_noown(char* uri) {
   8.730 +    char* uri_delim = strstr(uri, "://");
   8.731 +    if (!uri_delim)
   8.732 +        return uri;
   8.733 +    else
   8.734 +        return uri + 3;
   8.735 +}
   8.736 +
   8.737 +static bool is_file_uri(char* str) {
   8.738 +    return(strncmp(str, "file://", 7) == 0);
   8.739 +}
   8.740 +
   8.741 +static bool is_cid_uri(const char* str) {
   8.742 +    return(strncmp(str, "cid://", 6) == 0);
   8.743 +}
   8.744 +
   8.745 +static bool string_equality(const char *s1, const char *s2)
   8.746 +{
   8.747 +    if (s1 == NULL || s2 == NULL)
   8.748 +        return false;
   8.749 +
   8.750 +    assert(s1 && s2);
   8.751 +
   8.752 +    return strcmp(s1, s2) == 0;
   8.753 +}
   8.754 +
   8.755 +static bool is_mime_type(const bloblist_t *bl, const char *mt)
   8.756 +{
   8.757 +    assert(mt);
   8.758 +
   8.759 +    return bl && string_equality(bl->mime_type, mt);
   8.760 +}
   8.761 +
   8.762 +//
   8.763 +// This function presumes the file ending is a proper substring of the
   8.764 +// filename (i.e. if bl->filename is "a.pgp" and fe is ".pgp", it will
   8.765 +// return true, but if bl->filename is ".pgp" and fe is ".pgp", it will
   8.766 +// return false. This is desired behaviour.
   8.767 +//
   8.768 +static bool is_fileending(const bloblist_t *bl, const char *fe)
   8.769 +{
   8.770 +    assert(fe);
   8.771 +
   8.772 +    if (bl == NULL || bl->filename == NULL || fe == NULL || is_cid_uri(bl->filename))
   8.773 +        return false;
   8.774 +
   8.775 +    assert(bl && bl->filename);
   8.776 +
   8.777 +    size_t fe_len = strlen(fe);
   8.778 +    size_t fn_len = strlen(bl->filename);
   8.779 +
   8.780 +    if (fn_len <= fe_len)
   8.781 +        return false;
   8.782 +
   8.783 +    assert(fn_len > fe_len);
   8.784 +
   8.785 +    return strcmp(bl->filename + (fn_len - fe_len), fe) == 0;
   8.786 +}
   8.787 +
   8.788 +
   8.789 +static char * encapsulate_message_wrap_info(const char *msg_wrap_info, const char *longmsg)
   8.790 +{
   8.791 +    assert(msg_wrap_info);
   8.792 +    
   8.793 +    if (!msg_wrap_info) {
   8.794 +        if (!longmsg)
   8.795 +            return NULL;
   8.796 +        else {
   8.797 +            char *result = strdup(longmsg);
   8.798 +            assert(result);
   8.799 +            return result;            
   8.800 +        }    
   8.801 +    }
   8.802 +    
   8.803 +    if (longmsg == NULL)
   8.804 +        longmsg = "";
   8.805 +        
   8.806 +    const char * const newlines = "\n\n";
   8.807 +    const size_t NL_LEN = 2;
   8.808 +        
   8.809 +    const size_t bufsize = PEP_MSG_WRAP_KEY_LEN + strlen(msg_wrap_info) + NL_LEN + strlen(longmsg) + 1;
   8.810 +    char * ptext = calloc(1, bufsize);
   8.811 +    assert(ptext);
   8.812 +    if (ptext == NULL)
   8.813 +        return NULL;
   8.814 +
   8.815 +    strlcpy(ptext, PEP_MSG_WRAP_KEY, bufsize);
   8.816 +    strlcat(ptext, msg_wrap_info, bufsize);
   8.817 +    strlcat(ptext, newlines, bufsize);
   8.818 +    strlcat(ptext, longmsg, bufsize);
   8.819 +
   8.820 +    return ptext;
   8.821 +}
   8.822 +
   8.823 +static char * combine_short_and_long(const char *shortmsg, const char *longmsg)
   8.824 +{
   8.825 +    assert(shortmsg);
   8.826 +    
   8.827 +    unsigned char pepstr[] = PEP_SUBJ_STRING;
   8.828 +    assert(strcmp(shortmsg, "pEp") != 0 && _unsigned_signed_strcmp(pepstr, shortmsg, PEP_SUBJ_BYTELEN) != 0); 
   8.829 +    
   8.830 +    if (!shortmsg || strcmp(shortmsg, "pEp") == 0 || 
   8.831 +                     _unsigned_signed_strcmp(pepstr, shortmsg, PEP_SUBJ_BYTELEN) == 0) {
   8.832 +        if (!longmsg) {
   8.833 +            return NULL;
   8.834 +        }
   8.835 +        else {
   8.836 +            char *result = strdup(longmsg);
   8.837 +            assert(result);
   8.838 +            return result;
   8.839 +        }
   8.840 +    }
   8.841 +
   8.842 +    if (longmsg == NULL)
   8.843 +        longmsg = "";
   8.844 +
   8.845 +    const char * const newlines = "\n\n";
   8.846 +    const size_t NL_LEN = 2;
   8.847 +
   8.848 +    const size_t bufsize = PEP_SUBJ_KEY_LEN + strlen(shortmsg) + NL_LEN + strlen(longmsg) + 1;
   8.849 +    char * ptext = calloc(1, bufsize);
   8.850 +    assert(ptext);
   8.851 +    if (ptext == NULL)
   8.852 +        return NULL;
   8.853 +
   8.854 +    strlcpy(ptext, PEP_SUBJ_KEY, bufsize);
   8.855 +    strlcat(ptext, shortmsg, bufsize);
   8.856 +    strlcat(ptext, newlines, bufsize);
   8.857 +    strlcat(ptext, longmsg, bufsize);
   8.858 +
   8.859 +    return ptext;
   8.860 +}
   8.861 +
   8.862 +static PEP_STATUS replace_subject(message* msg) {
   8.863 +    unsigned char pepstr[] = PEP_SUBJ_STRING;
   8.864 +    if (msg->shortmsg && *(msg->shortmsg) != '\0') {
   8.865 +        char* longmsg = combine_short_and_long(msg->shortmsg, msg->longmsg);
   8.866 +        if (!longmsg)
   8.867 +            return PEP_OUT_OF_MEMORY;
   8.868 +        else {
   8.869 +            free(msg->longmsg);
   8.870 +            msg->longmsg = longmsg;
   8.871 +        }
   8.872 +    }
   8.873 +    free(msg->shortmsg);
   8.874 +    msg->shortmsg = strdup((char*)pepstr);
   8.875 +    
   8.876 +    if (!msg->shortmsg)
   8.877 +        return PEP_OUT_OF_MEMORY;
   8.878 +    
   8.879 +    return PEP_STATUS_OK;
   8.880 +}
   8.881 +
   8.882 +/* 
   8.883 +   WARNING: For the moment, this only works for the first line of decrypted
   8.884 +   plaintext because we don't need more. IF WE DO, THIS MUST BE EXPANDED, or
   8.885 +   we need a delineated section to parse separately
   8.886 +   
   8.887 +   Does case-insensitive compare of keys, so sending in a lower-cased
   8.888 +   string constant saves a bit of computation
   8.889 + */
   8.890 +static PEP_STATUS get_data_from_encapsulated_line(const char* plaintext, const char* key, 
   8.891 +                                                  const size_t keylen, char** data, 
   8.892 +                                                  char** modified_msg) {
   8.893 +    char* _data = NULL;
   8.894 +    char* _modified = NULL;
   8.895 +    
   8.896 +    if (strncasecmp(plaintext, key, keylen) == 0) {
   8.897 +        const char *line_end = strchr(plaintext, '\n');
   8.898 +
   8.899 +        if (line_end == NULL) {
   8.900 +            _data = strdup(plaintext + keylen);
   8.901 +            assert(_data);
   8.902 +            if (_data == NULL)
   8.903 +                return PEP_OUT_OF_MEMORY;
   8.904 +        }
   8.905 +        else {
   8.906 +            size_t n = line_end - plaintext;
   8.907 +
   8.908 +            if (*(line_end - 1) == '\r')
   8.909 +                _data = strndup(plaintext + keylen, n - (keylen + 1));
   8.910 +            else
   8.911 +                _data = strndup(plaintext + keylen, n - keylen);
   8.912 +            assert(_data);
   8.913 +            if (_data == NULL)
   8.914 +                return PEP_OUT_OF_MEMORY;
   8.915 +
   8.916 +            while (*(plaintext + n) && (*(plaintext + n) == '\n' || *(plaintext + n) == '\r'))
   8.917 +                ++n;
   8.918 +
   8.919 +            if (*(plaintext + n)) {
   8.920 +                _modified = strdup(plaintext + n);
   8.921 +                assert(_modified);
   8.922 +                if (_modified == NULL)
   8.923 +                    return PEP_OUT_OF_MEMORY;
   8.924 +            }
   8.925 +        }
   8.926 +    }
   8.927 +    *data = _data;
   8.928 +    *modified_msg = _modified;
   8.929 +    return PEP_STATUS_OK;
   8.930 +}
   8.931 +
   8.932 +
   8.933 +static int separate_short_and_long(const char *src, char **shortmsg, char** msg_wrap_info, char **longmsg)
   8.934 +{
   8.935 +    char *_shortmsg = NULL;
   8.936 +    char *_msg_wrap_info = NULL;
   8.937 +    char *_longmsg = NULL;
   8.938 +
   8.939 +    assert(src);
   8.940 +    assert(shortmsg);
   8.941 +    assert(msg_wrap_info);
   8.942 +    assert(longmsg);
   8.943 +
   8.944 +    if (src == NULL || shortmsg == NULL || msg_wrap_info == NULL || longmsg == NULL)
   8.945 +        return -1;
   8.946 +
   8.947 +    *shortmsg = NULL;
   8.948 +    *longmsg = NULL;
   8.949 +    *msg_wrap_info = NULL;
   8.950 +
   8.951 +    // We generated the input here. If we ever need more than one header value to be
   8.952 +    // encapsulated and hidden in the encrypted text, we will have to modify this.
   8.953 +    // As is, we're either doing this with a version 1.0 client, in which case
   8.954 +    // the only encapsulated header value is subject, or 2.0+, in which the
   8.955 +    // message wrap info is the only encapsulated header value. If we need this
   8.956 +    // to be more complex, we're going to have to do something more elegant
   8.957 +    // and efficient.    
   8.958 +    PEP_STATUS status = get_data_from_encapsulated_line(src, PEP_SUBJ_KEY_LC, 
   8.959 +                                                        PEP_SUBJ_KEY_LEN, 
   8.960 +                                                        &_shortmsg, &_longmsg);
   8.961 +                                                        
   8.962 +    if (_shortmsg) {
   8.963 +        if (status == PEP_STATUS_OK)
   8.964 +            *shortmsg = _shortmsg;
   8.965 +        else
   8.966 +            goto enomem;
   8.967 +    }
   8.968 +    else {
   8.969 +        status = get_data_from_encapsulated_line(src, PEP_MSG_WRAP_KEY_LC, 
   8.970 +                                                 PEP_MSG_WRAP_KEY_LEN, 
   8.971 +                                                 &_msg_wrap_info, &_longmsg);
   8.972 +        if (_msg_wrap_info) {
   8.973 +            if (status == PEP_STATUS_OK)
   8.974 +                *msg_wrap_info = _msg_wrap_info;
   8.975 +            else
   8.976 +                goto enomem;
   8.977 +        }
   8.978 +    }
   8.979 +    
   8.980 +    // If there was no secret data hiding in the first line...
   8.981 +    if (!_shortmsg && !_msg_wrap_info) {
   8.982 +        _longmsg = strdup(src);
   8.983 +        assert(_longmsg);
   8.984 +        if (_longmsg == NULL)
   8.985 +            goto enomem;
   8.986 +    }
   8.987 +    
   8.988 +    *longmsg = _longmsg;
   8.989 +
   8.990 +    return 0;
   8.991 +
   8.992 +enomem:
   8.993 +    free(_shortmsg);
   8.994 +    free(_msg_wrap_info);
   8.995 +    free(_longmsg);
   8.996 +
   8.997 +    return -1;
   8.998 +}
   8.999 +
  8.1000 +static PEP_STATUS copy_fields(message *dst, const message *src)
  8.1001 +{
  8.1002 +    assert(dst);
  8.1003 +    assert(src);
  8.1004 +
  8.1005 +    if(!(dst && src))
  8.1006 +        return PEP_ILLEGAL_VALUE;
  8.1007 +
  8.1008 +    free_timestamp(dst->sent);
  8.1009 +    dst->sent = NULL;
  8.1010 +    if (src->sent) {
  8.1011 +        dst->sent = timestamp_dup(src->sent);
  8.1012 +        if (dst->sent == NULL)
  8.1013 +            return PEP_OUT_OF_MEMORY;
  8.1014 +    }
  8.1015 +
  8.1016 +    free_timestamp(dst->recv);
  8.1017 +    dst->recv = NULL;
  8.1018 +    if (src->recv) {
  8.1019 +        dst->recv = timestamp_dup(src->recv);
  8.1020 +        if (dst->recv == NULL)
  8.1021 +            return PEP_OUT_OF_MEMORY;
  8.1022 +    }
  8.1023 +
  8.1024 +    free_identity(dst->from);
  8.1025 +    dst->from = NULL;
  8.1026 +    if (src->from) {
  8.1027 +        dst->from = identity_dup(src->from);
  8.1028 +        if (dst->from == NULL)
  8.1029 +            return PEP_OUT_OF_MEMORY;
  8.1030 +    }
  8.1031 +
  8.1032 +    free_identity_list(dst->to);
  8.1033 +    dst->to = NULL;
  8.1034 +    if (src->to && src->to->ident) {
  8.1035 +        dst->to = identity_list_dup(src->to);
  8.1036 +        if (dst->to == NULL)
  8.1037 +            return PEP_OUT_OF_MEMORY;
  8.1038 +    }
  8.1039 +
  8.1040 +    free_identity(dst->recv_by);
  8.1041 +    dst->recv_by = NULL;
  8.1042 +    if (src->recv_by) {
  8.1043 +        dst->recv_by = identity_dup(src->recv_by);
  8.1044 +        if (dst->recv_by == NULL)
  8.1045 +            return PEP_OUT_OF_MEMORY;
  8.1046 +    }
  8.1047 +
  8.1048 +    free_identity_list(dst->cc);
  8.1049 +    dst->cc = NULL;
  8.1050 +    if (src->cc && src->cc->ident) {
  8.1051 +        dst->cc = identity_list_dup(src->cc);
  8.1052 +        if (dst->cc == NULL)
  8.1053 +            return PEP_OUT_OF_MEMORY;
  8.1054 +    }
  8.1055 +
  8.1056 +    free_identity_list(dst->bcc);
  8.1057 +    dst->bcc = NULL;
  8.1058 +    if (src->bcc && src->bcc->ident) {
  8.1059 +        dst->bcc = identity_list_dup(src->bcc);
  8.1060 +        if (dst->bcc == NULL)
  8.1061 +            return PEP_OUT_OF_MEMORY;
  8.1062 +    }
  8.1063 +
  8.1064 +    free_identity_list(dst->reply_to);
  8.1065 +    dst->reply_to = NULL;
  8.1066 +    if (src->reply_to && src->reply_to->ident) {
  8.1067 +        dst->reply_to = identity_list_dup(src->reply_to);
  8.1068 +        if (dst->reply_to == NULL)
  8.1069 +            return PEP_OUT_OF_MEMORY;
  8.1070 +    }
  8.1071 +
  8.1072 +    free_stringlist(dst->in_reply_to);
  8.1073 +    dst->in_reply_to = NULL;
  8.1074 +    if (src->in_reply_to && src->in_reply_to->value) {
  8.1075 +        dst->in_reply_to = stringlist_dup(src->in_reply_to);
  8.1076 +        if (dst->in_reply_to == NULL)
  8.1077 +            return PEP_OUT_OF_MEMORY;
  8.1078 +    }
  8.1079 +
  8.1080 +    free_stringlist(dst->references);
  8.1081 +    dst->references = NULL;
  8.1082 +    if (src->references) {
  8.1083 +        dst->references = stringlist_dup(src->references);
  8.1084 +        if (dst->references == NULL)
  8.1085 +            return PEP_OUT_OF_MEMORY;
  8.1086 +    }
  8.1087 +
  8.1088 +    free_stringlist(dst->keywords);
  8.1089 +    dst->keywords = NULL;
  8.1090 +    if (src->keywords && src->keywords->value) {
  8.1091 +        dst->keywords = stringlist_dup(src->keywords);
  8.1092 +        if (dst->keywords == NULL)
  8.1093 +            return PEP_OUT_OF_MEMORY;
  8.1094 +    }
  8.1095 +
  8.1096 +    free(dst->comments);
  8.1097 +    dst->comments = NULL;
  8.1098 +    if (src->comments) {
  8.1099 +        dst->comments = strdup(src->comments);
  8.1100 +        assert(dst->comments);
  8.1101 +        if (dst->comments == NULL)
  8.1102 +            return PEP_OUT_OF_MEMORY;
  8.1103 +    }
  8.1104 +
  8.1105 +    free_stringpair_list(dst->opt_fields);
  8.1106 +    dst->opt_fields = NULL;
  8.1107 +    if (src->opt_fields) {
  8.1108 +        dst->opt_fields = stringpair_list_dup(src->opt_fields);
  8.1109 +        if (dst->opt_fields == NULL)
  8.1110 +            return PEP_OUT_OF_MEMORY;
  8.1111 +    }
  8.1112 +
  8.1113 +    return PEP_STATUS_OK;
  8.1114 +}
  8.1115 +
  8.1116 +
  8.1117 +static message* extract_minimal_envelope(const message* src, 
  8.1118 +                                         PEP_msg_direction direct) {
  8.1119 +                                                 
  8.1120 +    message* envelope = new_message(direct);
  8.1121 +    if (!envelope)
  8.1122 +        return NULL;
  8.1123 +        
  8.1124 +    envelope->shortmsg = _pep_subj_copy();
  8.1125 +    if (!envelope->shortmsg)
  8.1126 +        return NULL;
  8.1127 +
  8.1128 +    if (src->from) {
  8.1129 +        envelope->from = identity_dup(src->from);
  8.1130 +        if (!envelope->from)
  8.1131 +            return NULL;
  8.1132 +    }
  8.1133 +
  8.1134 +    if (src->to) {
  8.1135 +        envelope->to = identity_list_dup(src->to);
  8.1136 +        if (!envelope->to)
  8.1137 +            return NULL;
  8.1138 +    }
  8.1139 +
  8.1140 +    if (src->cc) {
  8.1141 +        envelope->cc = identity_list_dup(src->cc);
  8.1142 +        if (!envelope->cc)
  8.1143 +            return NULL;
  8.1144 +    }
  8.1145 +
  8.1146 +    if (src->bcc) {
  8.1147 +        envelope->bcc = identity_list_dup(src->bcc);
  8.1148 +        if (!envelope->bcc)
  8.1149 +            return NULL;
  8.1150 +    }
  8.1151 +
  8.1152 +    envelope->enc_format = src->enc_format;        
  8.1153 +    
  8.1154 +    return envelope;
  8.1155 +}
  8.1156 +
  8.1157 +static message * clone_to_empty_message(const message * src)
  8.1158 +{
  8.1159 +    PEP_STATUS status;
  8.1160 +    message * msg = NULL;
  8.1161 +
  8.1162 +    assert(src);
  8.1163 +    if (src == NULL)
  8.1164 +        return NULL;
  8.1165 +
  8.1166 +    msg = calloc(1, sizeof(message));
  8.1167 +    assert(msg);
  8.1168 +    if (msg == NULL)
  8.1169 +        goto enomem;
  8.1170 +
  8.1171 +    msg->dir = src->dir;
  8.1172 +
  8.1173 +    status = copy_fields(msg, src);
  8.1174 +    if (status != PEP_STATUS_OK)
  8.1175 +        goto enomem;
  8.1176 +
  8.1177 +    return msg;
  8.1178 +
  8.1179 +enomem:
  8.1180 +    free_message(msg);
  8.1181 +    return NULL;
  8.1182 +}
  8.1183 +
  8.1184 +static message* wrap_message_as_attachment(message* envelope, 
  8.1185 +    message* attachment) {
  8.1186 +    
  8.1187 +    message* _envelope = envelope;
  8.1188 +
  8.1189 +    replace_opt_field(attachment, "X-pEp-Version", PEP_VERSION);
  8.1190 +
  8.1191 +    if (!_envelope) {
  8.1192 +        _envelope = extract_minimal_envelope(attachment, PEP_dir_outgoing);
  8.1193 +        attachment->longmsg = encapsulate_message_wrap_info("INNER", attachment->longmsg);
  8.1194 +        _envelope->longmsg = encapsulate_message_wrap_info("OUTER", _envelope->longmsg);
  8.1195 +    }
  8.1196 +    else {
  8.1197 +        _envelope->longmsg = encapsulate_message_wrap_info("TRANSPORT", _envelope->longmsg);
  8.1198 +    }
  8.1199 +    char* message_text = NULL;
  8.1200 +    /* Turn message into a MIME-blob */
  8.1201 +    //attachment->enc_format = PEP_enc_none;
  8.1202 +    PEP_STATUS status = mime_encode_message(attachment, false, &message_text);
  8.1203 +    
  8.1204 +    if (status != PEP_STATUS_OK) {
  8.1205 +        free(_envelope);
  8.1206 +        return NULL;
  8.1207 +    }
  8.1208 +    
  8.1209 +    size_t message_len = strlen(message_text);
  8.1210 +    
  8.1211 +    bloblist_t* message_blob = new_bloblist(message_text, message_len,
  8.1212 +                                            "message/rfc822", NULL);
  8.1213 +    
  8.1214 +    _envelope->attachments = message_blob;
  8.1215 +    
  8.1216 +    return _envelope;
  8.1217 +}
  8.1218 +
  8.1219 +static PEP_STATUS encrypt_PGP_MIME(
  8.1220 +    PEP_SESSION session,
  8.1221 +    const message *src,
  8.1222 +    stringlist_t *keys,
  8.1223 +    message *dst,
  8.1224 +    PEP_encrypt_flags_t flags
  8.1225 +    )
  8.1226 +{
  8.1227 +    PEP_STATUS status = PEP_STATUS_OK;
  8.1228 +    bool free_ptext = false;
  8.1229 +    char *ptext = NULL;
  8.1230 +    char *ctext = NULL;
  8.1231 +    char *mimetext = NULL;
  8.1232 +    size_t csize;
  8.1233 +    assert(dst->longmsg == NULL);
  8.1234 +    dst->enc_format = PEP_enc_PGP_MIME;
  8.1235 +
  8.1236 +    if (src->shortmsg)
  8.1237 +        dst->shortmsg = strdup(src->shortmsg);
  8.1238 +        
  8.1239 +    message *_src = calloc(1, sizeof(message));
  8.1240 +    assert(_src);
  8.1241 +    if (_src == NULL)
  8.1242 +        goto enomem;
  8.1243 +//    _src->longmsg = ptext;
  8.1244 +    _src->longmsg = src->longmsg;
  8.1245 +    _src->longmsg_formatted = src->longmsg_formatted;
  8.1246 +    _src->attachments = src->attachments;
  8.1247 +    _src->enc_format = PEP_enc_none;
  8.1248 +    status = mime_encode_message(_src, true, &mimetext);
  8.1249 +    assert(status == PEP_STATUS_OK);
  8.1250 +    if (status != PEP_STATUS_OK)
  8.1251 +        goto pep_error;
  8.1252 +
  8.1253 +    if (free_ptext){
  8.1254 +        free(ptext);
  8.1255 +        free_ptext=0;
  8.1256 +    }
  8.1257 +    free(_src);
  8.1258 +    assert(mimetext);
  8.1259 +    if (mimetext == NULL)
  8.1260 +        goto pep_error;
  8.1261 +
  8.1262 +    if (flags & PEP_encrypt_flag_force_unsigned)
  8.1263 +        status = encrypt_only(session, keys, mimetext, strlen(mimetext),
  8.1264 +            &ctext, &csize);
  8.1265 +    else
  8.1266 +        status = encrypt_and_sign(session, keys, mimetext, strlen(mimetext),
  8.1267 +            &ctext, &csize);
  8.1268 +    free(mimetext);
  8.1269 +    if (ctext == NULL)
  8.1270 +        goto pep_error;
  8.1271 +
  8.1272 +    dst->longmsg = strdup("this message was encrypted with p≡p "
  8.1273 +        "https://pEp-project.org");
  8.1274 +    assert(dst->longmsg);
  8.1275 +    if (dst->longmsg == NULL)
  8.1276 +        goto enomem;
  8.1277 +
  8.1278 +    char *v = strdup("Version: 1");
  8.1279 +    assert(v);
  8.1280 +    if (v == NULL)
  8.1281 +        goto enomem;
  8.1282 +
  8.1283 +    bloblist_t *_a = new_bloblist(v, strlen(v), "application/pgp-encrypted", NULL);
  8.1284 +    if (_a == NULL)
  8.1285 +        goto enomem;
  8.1286 +    dst->attachments = _a;
  8.1287 +
  8.1288 +    _a = bloblist_add(_a, ctext, csize, "application/octet-stream",
  8.1289 +        "file://msg.asc");
  8.1290 +    if (_a == NULL)
  8.1291 +        goto enomem;
  8.1292 +
  8.1293 +    return PEP_STATUS_OK;
  8.1294 +
  8.1295 +enomem:
  8.1296 +    status = PEP_OUT_OF_MEMORY;
  8.1297 +
  8.1298 +pep_error:
  8.1299 +    if (free_ptext)
  8.1300 +        free(ptext);
  8.1301 +    free(ctext);
  8.1302 +    return status;
  8.1303 +}
  8.1304 +
  8.1305 +
  8.1306  static PEP_rating _rating(PEP_comm_type ct, PEP_rating rating)
  8.1307  {
  8.1308      if (ct == PEP_ct_unknown)
  8.1309 @@ -1127,7 +1153,8 @@
  8.1310      PEP_STATUS status = PEP_STATUS_OK;
  8.1311      message * msg = NULL;
  8.1312      stringlist_t * keys = NULL;
  8.1313 -
  8.1314 +    message* _src = src;
  8.1315 +    
  8.1316      assert(session);
  8.1317      assert(src);
  8.1318      assert(dst);
  8.1319 @@ -1254,31 +1281,41 @@
  8.1320          return ADD_TO_LOG(PEP_UNENCRYPTED);
  8.1321      }
  8.1322      else {
  8.1323 -        msg = clone_to_empty_message(src);
  8.1324 +        // FIXME - we need to deal with transport types (via flag)
  8.1325 +        if ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp) {
  8.1326 +            _src = wrap_message_as_attachment(NULL, src);
  8.1327 +        }
  8.1328 +        else {
  8.1329 +            // hide subject
  8.1330 +            status = replace_subject(_src);
  8.1331 +            if (status == PEP_OUT_OF_MEMORY)
  8.1332 +                goto enomem;
  8.1333 +        }
  8.1334 +        if (!(flags & PEP_encrypt_flag_force_no_attached_key))
  8.1335 +            attach_own_key(session, _src);
  8.1336 +
  8.1337 +        msg = clone_to_empty_message(_src);
  8.1338          if (msg == NULL)
  8.1339              goto enomem;
  8.1340  
  8.1341 -        if (!(flags & PEP_encrypt_flag_force_no_attached_key))
  8.1342 -            attach_own_key(session, src);
  8.1343 -
  8.1344          switch (enc_format) {
  8.1345 -        case PEP_enc_PGP_MIME:
  8.1346 -        case PEP_enc_PEP: // BUG: should be implemented extra
  8.1347 -            status = encrypt_PGP_MIME(session, src, keys, msg, flags);
  8.1348 -            break;
  8.1349 -
  8.1350 -        case PEP_enc_pieces:
  8.1351 -            status = encrypt_PGP_in_pieces(session, src, keys, msg, flags);
  8.1352 -            break;
  8.1353 -
  8.1354 -        /* case PEP_enc_PEP:
  8.1355 -            // TODO: implement
  8.1356 -            NOT_IMPLEMENTED */
  8.1357 -
  8.1358 -        default:
  8.1359 -            assert(0);
  8.1360 -            status = PEP_ILLEGAL_VALUE;
  8.1361 -            GOTO(pep_error);
  8.1362 +            case PEP_enc_PGP_MIME:
  8.1363 +            case PEP_enc_PEP: // BUG: should be implemented extra
  8.1364 +                status = encrypt_PGP_MIME(session, _src, keys, msg, flags);
  8.1365 +                break;
  8.1366 +
  8.1367 +            // case PEP_enc_pieces:
  8.1368 +            //     status = encrypt_PGP_in_pieces(session, src, keys, msg, flags);
  8.1369 +            //     break;
  8.1370 +
  8.1371 +            /* case PEP_enc_PEP:
  8.1372 +                // TODO: implement
  8.1373 +                NOT_IMPLEMENTED */
  8.1374 +
  8.1375 +            default:
  8.1376 +                assert(0);
  8.1377 +                status = PEP_ILLEGAL_VALUE;
  8.1378 +                GOTO(pep_error);
  8.1379          }
  8.1380  
  8.1381          if (status == PEP_OUT_OF_MEMORY)
  8.1382 @@ -1291,7 +1328,7 @@
  8.1383      free_stringlist(keys);
  8.1384  
  8.1385      if (msg && msg->shortmsg == NULL) {
  8.1386 -        msg->shortmsg = _pep_subj_copy();
  8.1387 +        msg->shortmsg = strdup("");
  8.1388          assert(msg->shortmsg);
  8.1389          if (msg->shortmsg == NULL)
  8.1390              goto enomem;
  8.1391 @@ -1308,6 +1345,12 @@
  8.1392      }
  8.1393  
  8.1394      *dst = msg;
  8.1395 +    
  8.1396 +    // ??? FIXME: Check to be sure we don't have references btw _src and msg. 
  8.1397 +    // I don't think we do.
  8.1398 +    if (_src && _src != src)
  8.1399 +        free_message(_src);
  8.1400 +        
  8.1401      return ADD_TO_LOG(status);
  8.1402  
  8.1403  enomem:
  8.1404 @@ -1316,10 +1359,14 @@
  8.1405  pep_error:
  8.1406      free_stringlist(keys);
  8.1407      free_message(msg);
  8.1408 +    if (_src && _src != src)
  8.1409 +        free_message(_src);
  8.1410  
  8.1411      return ADD_TO_LOG(status);
  8.1412  }
  8.1413  
  8.1414 +
  8.1415 +// FIXME: Update if needed for the wrapped fun bits
  8.1416  DYNAMIC_API PEP_STATUS encrypt_message_for_self(
  8.1417          PEP_SESSION session,
  8.1418          pEp_identity* target_id,
  8.1419 @@ -1381,9 +1428,9 @@
  8.1420              status = encrypt_PGP_MIME(session, src, keys, msg, flags);
  8.1421              break;
  8.1422  
  8.1423 -        case PEP_enc_pieces:
  8.1424 -            status = encrypt_PGP_in_pieces(session, src, keys, msg, flags);
  8.1425 -            break;
  8.1426 +        // case PEP_enc_pieces:
  8.1427 +        //     status = encrypt_PGP_in_pieces(session, src, keys, msg, flags);
  8.1428 +        //     break;
  8.1429  
  8.1430          /* case PEP_enc_PEP:
  8.1431              NOT_IMPLEMENTED */
  8.1432 @@ -1464,7 +1511,8 @@
  8.1433  }
  8.1434  
  8.1435  
  8.1436 -PEP_STATUS _get_detached_signature(message* msg, bloblist_t** signature_blob) {
  8.1437 +static PEP_STATUS _get_detached_signature(message* msg, 
  8.1438 +                                          bloblist_t** signature_blob) {
  8.1439      bloblist_t* attach_curr = msg->attachments;
  8.1440  
  8.1441      *signature_blob = NULL;
  8.1442 @@ -1480,8 +1528,8 @@
  8.1443      return PEP_STATUS_OK;
  8.1444  }
  8.1445  
  8.1446 -PEP_STATUS _get_signed_text(const char* ptext, const size_t psize,
  8.1447 -                            char** stext, size_t* ssize) {
  8.1448 +static PEP_STATUS _get_signed_text(const char* ptext, const size_t psize,
  8.1449 +                                   char** stext, size_t* ssize) {
  8.1450  
  8.1451      char* signed_boundary = NULL;
  8.1452      char* signpost = strstr(ptext, "Content-Type: multipart/signed");
  8.1453 @@ -1551,9 +1599,9 @@
  8.1454      return PEP_STATUS_OK;
  8.1455  }
  8.1456  
  8.1457 -PEP_STATUS combine_keylists(PEP_SESSION session, stringlist_t** verify_in, 
  8.1458 -                            stringlist_t** keylist_in_out, 
  8.1459 -                            pEp_identity* from) {
  8.1460 +static PEP_STATUS combine_keylists(PEP_SESSION session, stringlist_t** verify_in, 
  8.1461 +                                   stringlist_t** keylist_in_out, 
  8.1462 +                                   pEp_identity* from) {
  8.1463      
  8.1464      if (!verify_in || !(*verify_in)) // this isn't really a problem.
  8.1465          return PEP_STATUS_OK;
  8.1466 @@ -1628,11 +1676,11 @@
  8.1467      return status;
  8.1468  }
  8.1469  
  8.1470 -PEP_STATUS amend_rating_according_to_sender_and_recipients(
  8.1471 -    PEP_SESSION session,
  8.1472 -    PEP_rating *rating,
  8.1473 -    pEp_identity *sender,
  8.1474 -    stringlist_t *recipients) {
  8.1475 +static PEP_STATUS amend_rating_according_to_sender_and_recipients(
  8.1476 +       PEP_SESSION session,
  8.1477 +       PEP_rating *rating,
  8.1478 +       pEp_identity *sender,
  8.1479 +       stringlist_t *recipients) {
  8.1480      
  8.1481      PEP_STATUS status = PEP_STATUS_OK;
  8.1482  
  8.1483 @@ -1668,6 +1716,350 @@
  8.1484      return status;
  8.1485  }
  8.1486  
  8.1487 +static PEP_STATUS check_for_sync_msg(PEP_SESSION session, 
  8.1488 +                                     message* src,
  8.1489 +                                     PEP_rating* rating, 
  8.1490 +                                     PEP_decrypt_flags_t* flags,
  8.1491 +                                     stringlist_t** keylist) {
  8.1492 +    assert(session);
  8.1493 +    assert(src);
  8.1494 +    assert(rating);
  8.1495 +    assert(keylist);
  8.1496 +    
  8.1497 +    if (session->sync_session->inject_sync_msg){
  8.1498 +        PEP_STATUS status = receive_DeviceState_msg(session, src, *rating, *keylist);
  8.1499 +        if (status == PEP_MESSAGE_CONSUME ||
  8.1500 +            status == PEP_MESSAGE_IGNORE) {
  8.1501 +            *flags |= (status == PEP_MESSAGE_IGNORE) ?
  8.1502 +                        PEP_decrypt_flag_ignore :
  8.1503 +                        PEP_decrypt_flag_consume;
  8.1504 +        }
  8.1505 +        else if (status != PEP_STATUS_OK) {
  8.1506 +            return ADD_TO_LOG(status);
  8.1507 +        }
  8.1508 +    }
  8.1509 +    return PEP_STATUS_OK;
  8.1510 +}
  8.1511 +
  8.1512 +static PEP_STATUS sync_if_no_key(PEP_STATUS decrypt_status, PEP_SESSION session) {
  8.1513 +    if (decrypt_status == PEP_DECRYPT_NO_KEY) {
  8.1514 +        PEP_STATUS sync_status = inject_DeviceState_event(session, CannotDecrypt, NULL, NULL);
  8.1515 +        if (sync_status == PEP_OUT_OF_MEMORY){
  8.1516 +            return PEP_OUT_OF_MEMORY;
  8.1517 +        }
  8.1518 +    }
  8.1519 +    return PEP_STATUS_OK;
  8.1520 +}
  8.1521 +
  8.1522 +// FIXME: Do we need to remove the attachment? I think we do...
  8.1523 +static bool pull_up_attached_main_msg(message* src) {
  8.1524 +    char* slong = src->longmsg;
  8.1525 +    char* sform = src->longmsg_formatted;
  8.1526 +    bloblist_t* satt = src->attachments;
  8.1527 +    
  8.1528 +    if ((!slong || slong[0] == '\0')
  8.1529 +         && (!sform || sform[0] == '\0')) {
  8.1530 +        if (satt) {
  8.1531 +            const char* inner_mime_type = satt->mime_type;
  8.1532 +            if (strcasecmp(inner_mime_type, "text/plain") == 0) {
  8.1533 +                free(slong); /* in case of "" */
  8.1534 +                src->longmsg = strndup(satt->value, satt->size); 
  8.1535 +                
  8.1536 +                bloblist_t* next_node = satt->next;
  8.1537 +                if (next_node) {
  8.1538 +                    inner_mime_type = next_node->mime_type;
  8.1539 +                    if (strcasecmp(inner_mime_type, "text/html") == 0) {
  8.1540 +                        free(sform);
  8.1541 +                        src->longmsg_formatted = strndup(next_node->value, next_node->size);
  8.1542 +                    }
  8.1543 +                }
  8.1544 +            }
  8.1545 +            else if (strcasecmp(inner_mime_type, "text/html") == 0) {
  8.1546 +                free(sform);
  8.1547 +                src->longmsg_formatted = strndup(satt->value, satt->size);
  8.1548 +            }
  8.1549 +        }
  8.1550 +        return true;
  8.1551 +    }
  8.1552 +    return false;
  8.1553 +}
  8.1554 +
  8.1555 +static PEP_STATUS unencapsulate_hidden_fields(message* src, message* msg,
  8.1556 +                                              char** msg_wrap_info) {
  8.1557 +    if (!src)
  8.1558 +        return PEP_ILLEGAL_VALUE;
  8.1559 +    unsigned char pepstr[] = PEP_SUBJ_STRING;
  8.1560 +    PEP_STATUS status = PEP_STATUS_OK;
  8.1561 +
  8.1562 +    bool change_source_in_place = (msg ? false : true);
  8.1563 +    
  8.1564 +    if (change_source_in_place)
  8.1565 +        msg = src;
  8.1566 +        
  8.1567 +//    const char* version_string = get_message_version_string(src);
  8.1568 +    
  8.1569 +    switch (src->enc_format) {
  8.1570 +        case PEP_enc_PGP_MIME:
  8.1571 +        case PEP_enc_pieces:
  8.1572 +        case PEP_enc_PGP_MIME_Outlook1:
  8.1573 +//        case PEP_enc_none: // FIXME - this is wrong
  8.1574 +
  8.1575 +            if (!change_source_in_place)
  8.1576 +                status = copy_fields(msg, src);
  8.1577 +                
  8.1578 +            if (status != PEP_STATUS_OK)
  8.1579 +                return status;
  8.1580 +                
  8.1581 +            // FIXME: This is a mess. Talk with VB about how far we go to identify
  8.1582 +            if (is_a_pEpmessage(src) || (src->shortmsg == NULL || strcmp(src->shortmsg, "pEp") == 0 ||
  8.1583 +                _unsigned_signed_strcmp(pepstr, src->shortmsg, PEP_SUBJ_BYTELEN) == 0))
  8.1584 +            {
  8.1585 +                char * shortmsg = NULL;
  8.1586 +                char * longmsg = NULL;
  8.1587 +        
  8.1588 +                if (msg->longmsg) {
  8.1589 +                    int r = separate_short_and_long(msg->longmsg, 
  8.1590 +                                                    &shortmsg, 
  8.1591 +                                                    msg_wrap_info,
  8.1592 +                                                    &longmsg);
  8.1593 +                
  8.1594 +                    if (r == -1)
  8.1595 +                        return PEP_OUT_OF_MEMORY;
  8.1596 +                }
  8.1597 +
  8.1598 +                // We only use the shortmsg in version 1.0 messages; if it occurs where we
  8.1599 +                // didn't replace the subject, we ignore this all
  8.1600 +                if (!(*msg_wrap_info || change_source_in_place)) {
  8.1601 +                    if (!shortmsg || 
  8.1602 +                        (src->shortmsg != NULL && strcmp(src->shortmsg, "pEp") != 0 &&
  8.1603 +                         _unsigned_signed_strcmp(pepstr, src->shortmsg, PEP_SUBJ_BYTELEN) != 0)) {
  8.1604 +                             
  8.1605 +                        if (shortmsg != NULL)
  8.1606 +                            free(shortmsg);                        
  8.1607 +                            
  8.1608 +                        if (src->shortmsg == NULL) {
  8.1609 +                            shortmsg = strdup("");
  8.1610 +                        }
  8.1611 +                        else {
  8.1612 +                            // FIXME: is msg->shortmsg always a copy of
  8.1613 +                            // src->shortmsg already?
  8.1614 +                            // if so, we need to change the logic so
  8.1615 +                            // that in this case, we don't free msg->shortmsg
  8.1616 +                            // and do this strdup, etc
  8.1617 +                            shortmsg = strdup(src->shortmsg);
  8.1618 +                        }        
  8.1619 +                    }
  8.1620 +                    free(msg->shortmsg);
  8.1621 +                    msg->shortmsg = shortmsg;
  8.1622 +                }
  8.1623 +                
  8.1624 +                free(msg->longmsg);
  8.1625 +
  8.1626 +                msg->longmsg = longmsg;
  8.1627 +            }
  8.1628 +            else {
  8.1629 +                if (!change_source_in_place) {
  8.1630 +                    msg->shortmsg = strdup(src->shortmsg);
  8.1631 +                    assert(msg->shortmsg);
  8.1632 +                    if (msg->shortmsg == NULL)
  8.1633 +                        return PEP_OUT_OF_MEMORY;
  8.1634 +                }
  8.1635 +            }
  8.1636 +            break;
  8.1637 +        default:
  8.1638 +                // BUG: must implement more
  8.1639 +                NOT_IMPLEMENTED
  8.1640 +    }
  8.1641 +    return PEP_STATUS_OK;
  8.1642 +
  8.1643 +}
  8.1644 +
  8.1645 +static PEP_STATUS verify_decrypted(PEP_SESSION session,
  8.1646 +                                   message* msg, 
  8.1647 +                                   pEp_identity* sender,
  8.1648 +                                   char* plaintext, 
  8.1649 +                                   size_t plaintext_size,
  8.1650 +                                   stringlist_t** keylist,
  8.1651 +                                   PEP_STATUS* decrypt_status,
  8.1652 +                                   PEP_cryptotech crypto) {
  8.1653 +    bloblist_t* detached_sig = NULL;
  8.1654 +    PEP_STATUS status = _get_detached_signature(msg, &detached_sig);
  8.1655 +    
  8.1656 +    if (detached_sig) {
  8.1657 +        char* dsig_text = detached_sig->value;
  8.1658 +        size_t dsig_size = detached_sig->size;
  8.1659 +        size_t ssize = 0;
  8.1660 +        char* stext = NULL;
  8.1661 +
  8.1662 +        status = _get_signed_text(plaintext, plaintext_size, &stext, &ssize);
  8.1663 +        stringlist_t *verify_keylist = NULL;
  8.1664 +
  8.1665 +        if (ssize > 0 && stext) {
  8.1666 +            status = cryptotech[crypto].verify_text(session, stext,
  8.1667 +                                                    ssize, dsig_text, dsig_size,
  8.1668 +                                                    &verify_keylist);
  8.1669 +
  8.1670 +            if (status == PEP_VERIFIED || status == PEP_VERIFIED_AND_TRUSTED)
  8.1671 +            {
  8.1672 +                *decrypt_status = PEP_DECRYPTED_AND_VERIFIED;
  8.1673 +            
  8.1674 +                status = combine_keylists(session, &verify_keylist, keylist, sender);
  8.1675 +            }
  8.1676 +        }
  8.1677 +    }
  8.1678 +    return status;
  8.1679 +}
  8.1680 +
  8.1681 +static PEP_STATUS _decrypt_in_pieces(PEP_SESSION session, 
  8.1682 +                                     message* src, 
  8.1683 +                                     message** msg_ptr, 
  8.1684 +                                     char* ptext,
  8.1685 +                                     size_t psize) {
  8.1686 +                            
  8.1687 +    PEP_STATUS status = PEP_UNKNOWN_ERROR;
  8.1688 +    
  8.1689 +    *msg_ptr = clone_to_empty_message(src);
  8.1690 +
  8.1691 +    if (*msg_ptr == NULL)
  8.1692 +        return PEP_OUT_OF_MEMORY;
  8.1693 +
  8.1694 +    message* msg = *msg_ptr;
  8.1695 +
  8.1696 +    msg->longmsg = ptext;
  8.1697 +    ptext = NULL;
  8.1698 +
  8.1699 +    bloblist_t *_m = msg->attachments;
  8.1700 +    if (_m == NULL && src->attachments && src->attachments->value) {
  8.1701 +        msg->attachments = new_bloblist(NULL, 0, NULL, NULL);
  8.1702 +        _m = msg->attachments;
  8.1703 +    }
  8.1704 +
  8.1705 +    bloblist_t *_s;
  8.1706 +    for (_s = src->attachments; _s; _s = _s->next) {
  8.1707 +        if (_s->value == NULL && _s->size == 0){
  8.1708 +            _m = bloblist_add(_m, NULL, 0, _s->mime_type, _s->filename);
  8.1709 +            if (_m == NULL)
  8.1710 +                return PEP_OUT_OF_MEMORY;
  8.1711 +
  8.1712 +        }
  8.1713 +        else if (is_encrypted_attachment(_s)) {
  8.1714 +            stringlist_t *_keylist = NULL;
  8.1715 +            char *attctext  = _s->value;
  8.1716 +            size_t attcsize = _s->size;
  8.1717 +
  8.1718 +            free(ptext);
  8.1719 +            ptext = NULL;
  8.1720 +
  8.1721 +            // FIXME: What about attachments with separate sigs???
  8.1722 +            status = decrypt_and_verify(session, attctext, attcsize,
  8.1723 +                                        NULL, 0,
  8.1724 +                                        &ptext, &psize, &_keylist);
  8.1725 +            free_stringlist(_keylist); // FIXME: Why do we do this?
  8.1726 +
  8.1727 +            if (ptext) {
  8.1728 +                if (is_encrypted_html_attachment(_s)) {
  8.1729 +                    msg->longmsg_formatted = ptext;
  8.1730 +                    ptext = NULL;
  8.1731 +                }
  8.1732 +                else {
  8.1733 +                    static const char * const mime_type = "application/octet-stream";
  8.1734 +                    char * const filename =
  8.1735 +                        without_double_ending(_s->filename);
  8.1736 +                    if (filename == NULL)
  8.1737 +                        return PEP_OUT_OF_MEMORY;
  8.1738 +
  8.1739 +                    _m = bloblist_add(_m, ptext, psize, mime_type,
  8.1740 +                        filename);
  8.1741 +                    free(filename);
  8.1742 +                    if (_m == NULL)
  8.1743 +                        return PEP_OUT_OF_MEMORY;
  8.1744 +
  8.1745 +                    ptext = NULL;
  8.1746 +
  8.1747 +                    if (msg->attachments == NULL)
  8.1748 +                        msg->attachments = _m;
  8.1749 +                }
  8.1750 +            }
  8.1751 +            else {
  8.1752 +                char *copy = malloc(_s->size);
  8.1753 +                assert(copy);
  8.1754 +                if (copy == NULL)
  8.1755 +                    return PEP_OUT_OF_MEMORY;
  8.1756 +                memcpy(copy, _s->value, _s->size);
  8.1757 +                _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
  8.1758 +                if (_m == NULL)
  8.1759 +                    return PEP_OUT_OF_MEMORY;
  8.1760 +            }
  8.1761 +        }
  8.1762 +        else {
  8.1763 +            char *copy = malloc(_s->size);
  8.1764 +            assert(copy);
  8.1765 +            if (copy == NULL)
  8.1766 +                return PEP_OUT_OF_MEMORY;
  8.1767 +            memcpy(copy, _s->value, _s->size);
  8.1768 +            _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
  8.1769 +            if (_m == NULL)
  8.1770 +                return PEP_OUT_OF_MEMORY;
  8.1771 +        }
  8.1772 +    }
  8.1773 +    return status;
  8.1774 +}
  8.1775 +
  8.1776 +static PEP_STATUS get_crypto_text(message* src, char** crypto_text, size_t* text_size) {
  8.1777 +                
  8.1778 +    // this is only here because of how NOT_IMPLEMENTED works            
  8.1779 +    PEP_STATUS status = PEP_STATUS_OK;
  8.1780 +                    
  8.1781 +    switch (src->enc_format) {
  8.1782 +        case PEP_enc_PGP_MIME:
  8.1783 +            *crypto_text = src->attachments->next->value;
  8.1784 +            *text_size = src->attachments->next->size;
  8.1785 +            break;
  8.1786 +
  8.1787 +        case PEP_enc_PGP_MIME_Outlook1:
  8.1788 +            *crypto_text = src->attachments->value;
  8.1789 +            *text_size = src->attachments->size;
  8.1790 +            break;
  8.1791 +
  8.1792 +        case PEP_enc_pieces:
  8.1793 +            *crypto_text = src->longmsg;
  8.1794 +            *text_size = strlen(*crypto_text);
  8.1795 +            break;
  8.1796 +
  8.1797 +        default:
  8.1798 +            NOT_IMPLEMENTED
  8.1799 +    }
  8.1800 +    
  8.1801 +    return status;
  8.1802 +}
  8.1803 +
  8.1804 +static PEP_STATUS import_priv_keys_from_decrypted_msg(PEP_SESSION session,
  8.1805 +                                                      message* src, 
  8.1806 +                                                      message* msg,
  8.1807 +                                                      bool* imported_keys,
  8.1808 +                                                      bool* imported_private,
  8.1809 +                                                      identity_list** private_il) {
  8.1810 +                                                          
  8.1811 +    PEP_STATUS status = PEP_STATUS_OK;
  8.1812 +    
  8.1813 +    // check for private key in decrypted message attachment while importing
  8.1814 +    identity_list *_private_il = NULL;
  8.1815 +    *imported_keys = import_attached_keys(session, msg, &_private_il);
  8.1816 +    
  8.1817 +    if (_private_il && identity_list_length(_private_il) == 1 &&
  8.1818 +        _private_il->ident->address)
  8.1819 +        *imported_private = true;
  8.1820 +
  8.1821 +    if (private_il && imported_private)
  8.1822 +        *private_il = _private_il;
  8.1823 +    else
  8.1824 +        free_identity_list(_private_il);
  8.1825 +
  8.1826 +    if (imported_keys)
  8.1827 +        status = _update_identity_for_incoming_message(session, src);
  8.1828 +        
  8.1829 +    return status;
  8.1830 +}
  8.1831  
  8.1832  DYNAMIC_API PEP_STATUS _decrypt_message(
  8.1833          PEP_SESSION session,
  8.1834 @@ -1679,6 +2071,18 @@
  8.1835          identity_list **private_il
  8.1836      )
  8.1837  {
  8.1838 +    
  8.1839 +    assert(session);
  8.1840 +    assert(src);
  8.1841 +    assert(dst);
  8.1842 +    assert(keylist);
  8.1843 +    assert(rating);
  8.1844 +    assert(flags);
  8.1845 +
  8.1846 +    if (!(session && src && dst && keylist && rating && flags))
  8.1847 +        return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
  8.1848 +
  8.1849 +    /*** Begin init ***/
  8.1850      PEP_STATUS status = PEP_STATUS_OK;
  8.1851      PEP_STATUS decrypt_status = PEP_CANNOT_DECRYPT_UNKNOWN;
  8.1852      message *msg = NULL;
  8.1853 @@ -1687,19 +2091,15 @@
  8.1854      char *ptext = NULL;
  8.1855      size_t psize;
  8.1856      stringlist_t *_keylist = NULL;
  8.1857 -    unsigned char pepstr[] = PEP_SUBJ_STRING;
  8.1858 -
  8.1859 -    assert(session);
  8.1860 -    assert(src);
  8.1861 -    assert(dst);
  8.1862 -    assert(keylist);
  8.1863 -    assert(rating);
  8.1864 -    assert(flags);
  8.1865 -
  8.1866 -    if (!(session && src && dst && keylist && rating && flags))
  8.1867 -        return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
  8.1868 +
  8.1869 +    *dst = NULL;
  8.1870 +    *keylist = NULL;
  8.1871 +    *rating = PEP_rating_undefined;
  8.1872  
  8.1873      *flags = 0;
  8.1874 +    /*** End init ***/
  8.1875 +
  8.1876 +    /*** Begin Import any attached public keys and update identities accordingly ***/
  8.1877  
  8.1878      // Private key in unencrypted mail are ignored -> NULL
  8.1879      bool imported_keys = import_attached_keys(session, src, NULL);
  8.1880 @@ -1710,6 +2110,9 @@
  8.1881      if(status != PEP_STATUS_OK)
  8.1882          return ADD_TO_LOG(status);
  8.1883  
  8.1884 +    /*** End Import any attached public keys and update identities accordingly ***/
  8.1885 +    
  8.1886 +    /*** Begin get detached signatures that are attached to the encrypted message ***/
  8.1887      // Get detached signature, if any
  8.1888      bloblist_t* detached_sig = NULL;
  8.1889      char* dsig_text = NULL;
  8.1890 @@ -1719,250 +2122,93 @@
  8.1891          dsig_text = detached_sig->value;
  8.1892          dsig_size = detached_sig->size;
  8.1893      }
  8.1894 -
  8.1895 +    /*** End get detached signatures that are attached to the encrypted message ***/
  8.1896 +
  8.1897 +    /*** Determine encryption format ***/
  8.1898      PEP_cryptotech crypto = determine_encryption_format(src);
  8.1899  
  8.1900 -    *dst = NULL;
  8.1901 -    *keylist = NULL;
  8.1902 -    *rating = PEP_rating_undefined;
  8.1903 -
  8.1904 -    switch (src->enc_format) {
  8.1905 -        case PEP_enc_none:
  8.1906 -            *rating = PEP_rating_unencrypted;
  8.1907 -            if (imported_keys)
  8.1908 -                remove_attached_keys(src);
  8.1909 -            if(session->sync_session->inject_sync_msg){
  8.1910 -                status = receive_DeviceState_msg(session, src, *rating, *keylist);
  8.1911 -                if (status == PEP_MESSAGE_CONSUME ||
  8.1912 -                    status == PEP_MESSAGE_IGNORE) {
  8.1913 -                    free_message(msg);
  8.1914 -                    msg = NULL;
  8.1915 -                    *flags |= (status == PEP_MESSAGE_IGNORE) ?
  8.1916 -                                PEP_decrypt_flag_ignore :
  8.1917 -                                PEP_decrypt_flag_consume;
  8.1918 -                }
  8.1919 -                else if (status != PEP_STATUS_OK) {
  8.1920 -                    return ADD_TO_LOG(status);
  8.1921 -                }
  8.1922 -            }
  8.1923 -            
  8.1924 -            char* slong = src->longmsg;
  8.1925 -            char* sform = src->longmsg_formatted;
  8.1926 -            bloblist_t* satt = src->attachments;
  8.1927 -            
  8.1928 -            if ((!slong || slong[0] == '\0')
  8.1929 -                 && (!sform || sform[0] == '\0')) {
  8.1930 -                if (satt) {
  8.1931 -                    const char* inner_mime_type = satt->mime_type;
  8.1932 -                    if (strcasecmp(inner_mime_type, "text/plain") == 0) {
  8.1933 -                        free(slong); /* in case of "" */
  8.1934 -                        src->longmsg = strndup(satt->value, satt->size); // N.B.: longmsg might be shorter, if attachment contains NUL bytes which are not allowed in text/plain!
  8.1935 -                        
  8.1936 -                        bloblist_t* next_node = satt->next;
  8.1937 -                        if (next_node) {
  8.1938 -                            inner_mime_type = next_node->mime_type;
  8.1939 -                            if (strcasecmp(inner_mime_type, "text/html") == 0) {
  8.1940 -                                free(sform);
  8.1941 -                                src->longmsg_formatted = strndup(next_node->value, next_node->size);  // N.B.: longmsg might be shorter, if attachment contains NUL bytes which are not allowed in text/plain!
  8.1942 -                            }
  8.1943 -                        }
  8.1944 -                    }
  8.1945 -                    else if (strcasecmp(inner_mime_type, "text/html") == 0) {
  8.1946 -                        free(sform);
  8.1947 -                        src->longmsg_formatted = strndup(satt->value, satt->size);  // N.B.: longmsg might be shorter, if attachment contains NUL bytes which are not allowed in text/plain!
  8.1948 -                    }
  8.1949 -                }
  8.1950 -            }
  8.1951 -            
  8.1952 -            return ADD_TO_LOG(PEP_UNENCRYPTED);
  8.1953 -
  8.1954 -        case PEP_enc_PGP_MIME:
  8.1955 -            ctext = src->attachments->next->value;
  8.1956 -            csize = src->attachments->next->size;
  8.1957 -            break;
  8.1958 -
  8.1959 -        case PEP_enc_PGP_MIME_Outlook1:
  8.1960 -            ctext = src->attachments->value;
  8.1961 -            csize = src->attachments->size;
  8.1962 -            break;
  8.1963 -
  8.1964 -        case PEP_enc_pieces:
  8.1965 -            ctext = src->longmsg;
  8.1966 -            csize = strlen(ctext);
  8.1967 -            break;
  8.1968 -
  8.1969 -        default:
  8.1970 -            NOT_IMPLEMENTED
  8.1971 +    // Check for and deal with unencrypted messages
  8.1972 +    if (src->enc_format == PEP_enc_none) {
  8.1973 +
  8.1974 +        *rating = PEP_rating_unencrypted;
  8.1975 +
  8.1976 +        if (imported_keys)
  8.1977 +            remove_attached_keys(src);
  8.1978 +
  8.1979 +        status = check_for_sync_msg(session, src, rating, flags, keylist);
  8.1980 +        
  8.1981 +        if (status != PEP_STATUS_OK)
  8.1982 +            return ADD_TO_LOG(status);
  8.1983 +                                    
  8.1984 +        pull_up_attached_main_msg(src);
  8.1985 +        
  8.1986 +        return ADD_TO_LOG(PEP_UNENCRYPTED);
  8.1987      }
  8.1988 +
  8.1989 +    status = get_crypto_text(src, &ctext, &csize);
  8.1990 +    if (status != PEP_STATUS_OK)
  8.1991 +        return status;
  8.1992 +    
  8.1993 +    /** Ok, we should be ready to decrypt. Try decrypt and verify first! **/
  8.1994      status = cryptotech[crypto].decrypt_and_verify(session, ctext,
  8.1995                                                     csize, dsig_text, dsig_size,
  8.1996                                                     &ptext, &psize, &_keylist);
  8.1997 -    if (status > PEP_CANNOT_DECRYPT_UNKNOWN){
  8.1998 +
  8.1999 +    if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
  8.2000          GOTO(pep_error);
  8.2001 -    }
  8.2002  
  8.2003      decrypt_status = status;
  8.2004 -
  8.2005 -    if (status == PEP_DECRYPT_NO_KEY){
  8.2006 -        PEP_STATUS sync_status = inject_DeviceState_event(session, CannotDecrypt, NULL, NULL);
  8.2007 -        if (sync_status == PEP_OUT_OF_MEMORY){
  8.2008 -            status = PEP_OUT_OF_MEMORY;
  8.2009 -            goto pep_error;
  8.2010 -        }
  8.2011 -    }
  8.2012 +    
  8.2013 +    /* inject appropriate sync message if we couldn't decrypt due to no key */
  8.2014 +    if (sync_if_no_key(decrypt_status, session) == PEP_OUT_OF_MEMORY)
  8.2015 +        goto pep_error;
  8.2016  
  8.2017      bool imported_private_key_address = false;
  8.2018  
  8.2019 -    if (ptext) {
  8.2020 +    if (ptext) { 
  8.2021 +        /* we got a plaintext from decryption */
  8.2022          switch (src->enc_format) {
  8.2023 +            
  8.2024              case PEP_enc_PGP_MIME:
  8.2025              case PEP_enc_PGP_MIME_Outlook1:
  8.2026 +            
  8.2027                  status = mime_decode_message(ptext, psize, &msg);
  8.2028                  if (status != PEP_STATUS_OK)
  8.2029                      goto pep_error;
  8.2030                  
  8.2031 -                char* mlong = msg->longmsg;
  8.2032 -                char* mform = msg->longmsg_formatted;
  8.2033 -                bloblist_t* matt = msg->attachments;
  8.2034 -                
  8.2035 -                if ((!mlong || mlong[0] == '\0')
  8.2036 -                     && (!mform || mform[0] == '\0')) {
  8.2037 -                    if (matt) {
  8.2038 -                        const char* inner_mime_type = matt->mime_type;
  8.2039 -                        if (strcasecmp(inner_mime_type, "text/plain") == 0) {
  8.2040 -                            free(mlong); /* in case of "" */
  8.2041 -                            msg->longmsg = strndup(matt->value, matt->size);
  8.2042 -                            
  8.2043 -                            bloblist_t* next_node = matt->next;
  8.2044 -                            if (next_node) {
  8.2045 -                                inner_mime_type = next_node->mime_type;
  8.2046 -                                if (strcasecmp(inner_mime_type, "text/html") == 0) {
  8.2047 -                                    free(mform);
  8.2048 -                                    msg->longmsg_formatted = strndup(next_node->value, next_node->size);
  8.2049 -                                }
  8.2050 -                            }
  8.2051 -                        }
  8.2052 -                        else if (strcasecmp(inner_mime_type, "text/html") == 0) {
  8.2053 -                            free(mform);
  8.2054 -                            msg->longmsg_formatted = strndup(matt->value, matt->size);
  8.2055 -                        }
  8.2056 -                    }
  8.2057 -                    if (msg->shortmsg) {
  8.2058 -                        free(src->shortmsg);
  8.2059 -                        src->shortmsg = strdup(msg->shortmsg);
  8.2060 -                    }
  8.2061 +                /* Ensure messages whose maintext is in the attachments
  8.2062 +                   move main text into message struct longmsg et al */
  8.2063 +                if (pull_up_attached_main_msg(msg) && msg->shortmsg) {
  8.2064 +                    free(src->shortmsg);
  8.2065 +                    src->shortmsg = strdup(msg->shortmsg);
  8.2066                  }
  8.2067  
  8.2068 -                if (decrypt_status != PEP_DECRYPTED_AND_VERIFIED) {
  8.2069 -                    status = _get_detached_signature(msg, &detached_sig);
  8.2070 -                    if (decrypt_status == PEP_DECRYPTED && detached_sig) {
  8.2071 -                        dsig_text = detached_sig->value;
  8.2072 -                        dsig_size = detached_sig->size;
  8.2073 -                        size_t ssize = 0;
  8.2074 -                        char* stext = NULL;
  8.2075 -
  8.2076 -                        status = _get_signed_text(ptext, psize, &stext, &ssize);
  8.2077 -                        stringlist_t *_verify_keylist = NULL;
  8.2078 -
  8.2079 -                        if (ssize > 0 && stext) {
  8.2080 -                            status = cryptotech[crypto].verify_text(session, stext,
  8.2081 -                                                                    ssize, dsig_text, dsig_size,
  8.2082 -                                                                    &_verify_keylist);
  8.2083 -
  8.2084 -                            if (status == PEP_VERIFIED || status == PEP_VERIFIED_AND_TRUSTED)
  8.2085 -                            {
  8.2086 -                                decrypt_status = PEP_DECRYPTED_AND_VERIFIED;
  8.2087 -                            
  8.2088 -                                status = combine_keylists(session, &_verify_keylist, &_keylist, src->from);
  8.2089 -                            }
  8.2090 -                        }
  8.2091 -                    }
  8.2092 +                /* if decrypted, but not verified... */
  8.2093 +                if (decrypt_status == PEP_DECRYPTED) {
  8.2094 +                    
  8.2095 +                    // check for private key in decrypted message attachment while importing
  8.2096 +                    status = import_priv_keys_from_decrypted_msg(session, src, msg,
  8.2097 +                                                                 &imported_keys,
  8.2098 +                                                                 &imported_private_key_address,
  8.2099 +                                                                 private_il);
  8.2100 +                    if (status != PEP_STATUS_OK)
  8.2101 +                        GOTO(pep_error);            
  8.2102 +                                                                 
  8.2103 +                    status = verify_decrypted(session,
  8.2104 +                                              msg, src->from,
  8.2105 +                                              ptext, psize,
  8.2106 +                                              &_keylist,
  8.2107 +                                              &decrypt_status,
  8.2108 +                                              crypto);
  8.2109                  }
  8.2110                  break;
  8.2111  
  8.2112              case PEP_enc_pieces:
  8.2113 -                msg = clone_to_empty_message(src);
  8.2114 -                if (msg == NULL)
  8.2115 +                status = _decrypt_in_pieces(session, src, &msg, ptext, psize);
  8.2116 +            
  8.2117 +                if (status == PEP_OUT_OF_MEMORY)
  8.2118                      goto enomem;
  8.2119  
  8.2120 -                msg->longmsg = ptext;
  8.2121 -                ptext = NULL;
  8.2122 -
  8.2123 -                bloblist_t *_m = msg->attachments;
  8.2124 -                if (_m == NULL && src->attachments && src->attachments->value) {
  8.2125 -                    msg->attachments = new_bloblist(NULL, 0, NULL, NULL);
  8.2126 -                    _m = msg->attachments;
  8.2127 -                }
  8.2128 -
  8.2129 -                bloblist_t *_s;
  8.2130 -                for (_s = src->attachments; _s; _s = _s->next) {
  8.2131 -                    if (_s->value == NULL && _s->size == 0){
  8.2132 -                        _m = bloblist_add(_m, NULL, 0, _s->mime_type, _s->filename);
  8.2133 -                        if (_m == NULL)
  8.2134 -                            goto enomem;
  8.2135 -
  8.2136 -                    }
  8.2137 -                    else if (is_encrypted_attachment(_s)) {
  8.2138 -                        stringlist_t *_keylist = NULL;
  8.2139 -                        char *attctext  = _s->value;
  8.2140 -                        size_t attcsize = _s->size;
  8.2141 -
  8.2142 -                        free(ptext);
  8.2143 -                        ptext = NULL;
  8.2144 -
  8.2145 -                        // FIXME: What about attachments with separate sigs???
  8.2146 -                        status = decrypt_and_verify(session, attctext, attcsize,
  8.2147 -                                                    NULL, 0,
  8.2148 -                                                    &ptext, &psize, &_keylist);
  8.2149 -                        free_stringlist(_keylist); // FIXME: Why do we do this?
  8.2150 -
  8.2151 -                        if (ptext) {
  8.2152 -                            if (is_encrypted_html_attachment(_s)) {
  8.2153 -                                msg->longmsg_formatted = ptext;
  8.2154 -                                ptext = NULL;
  8.2155 -                            }
  8.2156 -                            else {
  8.2157 -                                static const char * const mime_type = "application/octet-stream";
  8.2158 -                                char * const filename =
  8.2159 -                                    without_double_ending(_s->filename);
  8.2160 -                                if (filename == NULL)
  8.2161 -                                    goto enomem;
  8.2162 -
  8.2163 -                                _m = bloblist_add(_m, ptext, psize, mime_type,
  8.2164 -                                    filename);
  8.2165 -                                free(filename);
  8.2166 -                                if (_m == NULL)
  8.2167 -                                    goto enomem;
  8.2168 -
  8.2169 -                                ptext = NULL;
  8.2170 -
  8.2171 -                                if (msg->attachments == NULL)
  8.2172 -                                    msg->attachments = _m;
  8.2173 -                            }
  8.2174 -                        }
  8.2175 -                        else {
  8.2176 -                            char *copy = malloc(_s->size);
  8.2177 -                            assert(copy);
  8.2178 -                            if (copy == NULL)
  8.2179 -                                goto enomem;
  8.2180 -                            memcpy(copy, _s->value, _s->size);
  8.2181 -                            _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
  8.2182 -                            if (_m == NULL)
  8.2183 -                                goto enomem;
  8.2184 -                        }
  8.2185 -                    }
  8.2186 -                    else {
  8.2187 -                        char *copy = malloc(_s->size);
  8.2188 -                        assert(copy);
  8.2189 -                        if (copy == NULL)
  8.2190 -                            goto enomem;
  8.2191 -                        memcpy(copy, _s->value, _s->size);
  8.2192 -                        _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
  8.2193 -                        if (_m == NULL)
  8.2194 -                            goto enomem;
  8.2195 -                    }
  8.2196 -                }
  8.2197 -
  8.2198                  break;
  8.2199  
  8.2200              default:
  8.2201 @@ -1970,117 +2216,91 @@
  8.2202                  NOT_IMPLEMENTED
  8.2203          }
  8.2204  
  8.2205 -        switch (src->enc_format) {
  8.2206 -            case PEP_enc_PGP_MIME:
  8.2207 -            case PEP_enc_pieces:
  8.2208 -            case PEP_enc_PGP_MIME_Outlook1:
  8.2209 -                status = copy_fields(msg, src);
  8.2210 -                if (status != PEP_STATUS_OK)
  8.2211 -                {
  8.2212 -                    GOTO(pep_error);
  8.2213 +        if (status == PEP_OUT_OF_MEMORY)
  8.2214 +            goto enomem;
  8.2215 +            
  8.2216 +        if (status != PEP_STATUS_OK)
  8.2217 +            goto pep_error;
  8.2218 +
  8.2219 +        if (decrypt_status == PEP_DECRYPTED || decrypt_status == PEP_DECRYPTED_AND_VERIFIED) {
  8.2220 +            char* wrap_info = NULL;
  8.2221 +            status = unencapsulate_hidden_fields(src, msg, &wrap_info);
  8.2222 +
  8.2223 +            bool is_transport_wrapper = false;
  8.2224 +            
  8.2225 +            // FIXME: replace with enums, check status
  8.2226 +            if (wrap_info) {
  8.2227 +                if (strcmp(wrap_info, "OUTER") == 0) {
  8.2228 +                    // this only occurs in with a direct outer wrapper
  8.2229 +                    // where the actual content is in the inner wrapper
  8.2230 +                    message* inner_message = NULL;                    
  8.2231 +                    bloblist_t* actual_message = msg->attachments;
  8.2232 +                    
  8.2233 +                    while (actual_message) {
  8.2234 +                        char* mime_type = actual_message->mime_type;
  8.2235 +                        if (mime_type) {
  8.2236 +                            
  8.2237 +                            // libetpan appears to change the mime_type on this one.
  8.2238 +                            // *growl*
  8.2239 +                            if (strcmp("message/rfc822", mime_type) == 0 ||
  8.2240 +                                strcmp("text/rfc822", mime_type) == 0) {
  8.2241 +                                    
  8.2242 +                                status = mime_decode_message(actual_message->value, 
  8.2243 +                                                             actual_message->size, 
  8.2244 +                                                             &inner_message);
  8.2245 +                                if (status != PEP_STATUS_OK)
  8.2246 +                                    GOTO(pep_error);
  8.2247 +                                
  8.2248 +                                if (inner_message) {
  8.2249 +                                    // Though this will strip any message info on the
  8.2250 +                                    // attachment, this is safe, as we do not
  8.2251 +                                    // produce more than one attachment-as-message,
  8.2252 +                                    // and those are the only ones with such info.
  8.2253 +                                    // Since we capture the information, this is ok.
  8.2254 +                                    wrap_info = NULL;
  8.2255 +                                    inner_message->enc_format = src->enc_format;
  8.2256 +                                    // FIXME
  8.2257 +                                    status = unencapsulate_hidden_fields(inner_message, NULL, &wrap_info);
  8.2258 +                                    if (wrap_info) {
  8.2259 +                                        // useless check, but just in case we screw up?
  8.2260 +                                        if (strcmp(wrap_info, "INNER") == 0) {
  8.2261 +                                            // THIS is our message
  8.2262 +                                            // FIXME: free msg, but check references
  8.2263 +                                            src = msg = inner_message;
  8.2264 +                                            
  8.2265 +                                            if (src->from)
  8.2266 +                                                update_identity(session, src->from);
  8.2267 +                                            break;        
  8.2268 +                                        }
  8.2269 +                                        else { // should never happen
  8.2270 +                                            status = PEP_UNKNOWN_ERROR;
  8.2271 +                                            free_message(inner_message);
  8.2272 +                                            GOTO(pep_error);
  8.2273 +                                        }
  8.2274 +                                    }
  8.2275 +                                    inner_message->enc_format = PEP_enc_none;
  8.2276 +                                }
  8.2277 +                                else { // forwarded message, leave it alone
  8.2278 +                                    free_message(inner_message);
  8.2279 +                                }
  8.2280 +                            }
  8.2281 +                        }
  8.2282 +                        actual_message = actual_message->next;
  8.2283 +                    }                    
  8.2284                  }
  8.2285 -
  8.2286 -                // added p=p because outlook is on crack.
  8.2287 -                if (src->shortmsg == NULL || strcmp(src->shortmsg, "pEp") == 0 ||
  8.2288 -                    strcmp(src->shortmsg, "p=p") == 0 ||
  8.2289 -                    _unsigned_signed_strcmp(pepstr, src->shortmsg, PEP_SUBJ_BYTELEN) == 0)
  8.2290 -                {
  8.2291 -                    char * shortmsg = NULL;
  8.2292 -                    char * longmsg = NULL;
  8.2293 -
  8.2294 -                    if (msg->longmsg) {
  8.2295 -                        int r = separate_short_and_long(msg->longmsg, &shortmsg,
  8.2296 -                                &longmsg);
  8.2297 -                    
  8.2298 -                        if (r == -1)
  8.2299 -                            goto enomem;
  8.2300 -                    }
  8.2301 -
  8.2302 -                    if (shortmsg == NULL) {
  8.2303 -                        if (src->shortmsg == NULL)
  8.2304 -                            shortmsg = strdup("");
  8.2305 -                        else {
  8.2306 -                            // FIXME: is msg->shortmsg always a copy of
  8.2307 -                            // src->shortmsg already?
  8.2308 -                            // if so, we need to change the logic so
  8.2309 -                            // that in this case, we don't free msg->shortmsg
  8.2310 -                            // and do this strdup, etc.
  8.2311 -                            shortmsg = strdup(src->shortmsg);
  8.2312 -                        }
  8.2313 -                    }
  8.2314 -
  8.2315 -
  8.2316 -                    free(msg->shortmsg);
  8.2317 -                    free(msg->longmsg);
  8.2318 -
  8.2319 -                    msg->shortmsg = shortmsg;
  8.2320 -                    msg->longmsg = longmsg;
  8.2321 +                else if (strcmp(wrap_info, "TRANSPORT") == 0) {
  8.2322 +                    // FIXME: this gets even messier.
  8.2323 +                    // (TBI in ENGINE-278)
  8.2324                  }
  8.2325 -                else {
  8.2326 -                    msg->shortmsg = strdup(src->shortmsg);
  8.2327 -                    assert(msg->shortmsg);
  8.2328 -                    if (msg->shortmsg == NULL)
  8.2329 -                        goto enomem;
  8.2330 -                }
  8.2331 -                break;
  8.2332 -            default:
  8.2333 -                    // BUG: must implement more
  8.2334 -                    NOT_IMPLEMENTED
  8.2335 +                else {} // shouldn't be anything to be done here
  8.2336 +            }
  8.2337          }
  8.2338 -
  8.2339 -        // check for private key in decrypted message attachement while inporting
  8.2340 -        identity_list *_private_il = NULL;
  8.2341 -        imported_keys = import_attached_keys(session, msg, &_private_il);
  8.2342 -        if (_private_il &&
  8.2343 -            identity_list_length(_private_il) == 1 &&
  8.2344 -            _private_il->ident->address)
  8.2345 -        {
  8.2346 -            imported_private_key_address = true;
  8.2347 -        }
  8.2348 -
  8.2349 -        if(private_il && imported_private_key_address){
  8.2350 -            *private_il = _private_il;
  8.2351 -        }else{
  8.2352 -            free_identity_list(_private_il);
  8.2353 -        }
  8.2354 -
  8.2355 -        if(decrypt_status == PEP_DECRYPTED){
  8.2356 -
  8.2357 -            // TODO optimize if import_attached_keys didn't import any key
  8.2358 -
  8.2359 -            // In case message did decrypt, but no valid signature could be found
  8.2360 -            // then retry decrypt+verify after importing key.
  8.2361 -
  8.2362 -            // Update msg->from in case we just imported a key
  8.2363 -            // we would need to check signature
  8.2364 -
  8.2365 -            status = _update_identity_for_incoming_message(session, src);
  8.2366 -            if(status != PEP_STATUS_OK)
  8.2367 -            {
  8.2368 -                GOTO(pep_error);
  8.2369 -            }
  8.2370 -
  8.2371 -            char *re_ptext = NULL;
  8.2372 -            size_t re_psize;
  8.2373 -
  8.2374 -            free_stringlist(_keylist);
  8.2375 -            _keylist = NULL;
  8.2376 -
  8.2377 -            status = cryptotech[crypto].decrypt_and_verify(session, ctext,
  8.2378 -                csize, dsig_text, dsig_size, &re_ptext, &re_psize, &_keylist);
  8.2379 -
  8.2380 -            free(re_ptext);
  8.2381 -
  8.2382 -            if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
  8.2383 -            {
  8.2384 -                GOTO(pep_error);
  8.2385 -            }
  8.2386 -
  8.2387 -            decrypt_status = status;
  8.2388 -        }
  8.2389 -
  8.2390 +        
  8.2391          *rating = decrypt_rating(decrypt_status);
  8.2392  
  8.2393 +        /* Ok, now we have a keylist used for decryption/verification.
  8.2394 +           now we need to update the message rating with the 
  8.2395 +           sender and recipients in mind */
  8.2396          status = amend_rating_according_to_sender_and_recipients(session,
  8.2397                                                                   rating,
  8.2398                                                                   src->from,
  8.2399 @@ -2088,55 +2308,54 @@
  8.2400  
  8.2401          if (status != PEP_STATUS_OK)
  8.2402              GOTO(pep_error);
  8.2403 -    }
  8.2404 -    else
  8.2405 -    {
  8.2406 +            
  8.2407 +    } 
  8.2408 +    else {
  8.2409 +        // We did not get a plaintext out of the decryption process.
  8.2410 +        // Abort and return error.
  8.2411          *rating = decrypt_rating(decrypt_status);
  8.2412          goto pep_error;
  8.2413      }
  8.2414  
  8.2415 -    // Case of own key imported from own trusted message
  8.2416 -    if (// Message have been reliably decrypted
  8.2417 -        msg &&
  8.2418 -        *rating >= PEP_rating_trusted &&
  8.2419 -        imported_private_key_address &&
  8.2420 -        // to is [own]
  8.2421 +    /* 
  8.2422 +       Ok, at this point, we know we have a reliably decrypted message.
  8.2423 +       Prepare the output message for return.
  8.2424 +    */
  8.2425 +    
  8.2426 +    // 1. Check to see if this message is to us and contains an own key imported 
  8.2427 +    // from own trusted message 
  8.2428 +    if (msg && *rating >= PEP_rating_trusted && imported_private_key_address &&
  8.2429          msg->to->ident->user_id &&
  8.2430 -        strcmp(msg->to->ident->user_id, PEP_OWN_USERID) == 0
  8.2431 -        )
  8.2432 -    {
  8.2433 +        strcmp(msg->to->ident->user_id, PEP_OWN_USERID) == 0) {
  8.2434 +
  8.2435 +        // flag it as such
  8.2436          *flags |= PEP_decrypt_flag_own_private_key;
  8.2437      }
  8.2438  
  8.2439 +    // 2. Clean up message and prepare for return 
  8.2440      if (msg) {
  8.2441 +        
  8.2442 +        /* add pEp-related status flags to header */
  8.2443          decorate_message(msg, *rating, _keylist);
  8.2444 +        
  8.2445          if (imported_keys)
  8.2446              remove_attached_keys(msg);
  8.2447 -        if (*rating >= PEP_rating_reliable &&
  8.2448 -            session->sync_session->inject_sync_msg) {
  8.2449 -            status = receive_DeviceState_msg(session, msg, *rating, _keylist);
  8.2450 -            if (status == PEP_MESSAGE_CONSUME ||
  8.2451 -                status == PEP_MESSAGE_IGNORE) {
  8.2452 -                free_message(msg);
  8.2453 -                msg = NULL;
  8.2454 -                *flags |= (status == PEP_MESSAGE_IGNORE) ?
  8.2455 -                            PEP_decrypt_flag_ignore :
  8.2456 -                            PEP_decrypt_flag_consume;
  8.2457 -
  8.2458 -            }
  8.2459 -            else if (status != PEP_STATUS_OK){
  8.2460 +            
  8.2461 +        if (*rating >= PEP_rating_reliable) { 
  8.2462 +            status = check_for_sync_msg(session, src, rating, flags, &_keylist);
  8.2463 +        
  8.2464 +            if (status != PEP_STATUS_OK)
  8.2465                  goto pep_error;
  8.2466 -            }
  8.2467          }
  8.2468 -    }
  8.2469 -    if (msg) {
  8.2470 -        if (src->id) {
  8.2471 +        
  8.2472 +        // copy message id to output message        
  8.2473 +        if (src->id && src != msg) {
  8.2474              msg->id = strdup(src->id);
  8.2475              assert(msg->id);
  8.2476              if (msg->id == NULL)
  8.2477                  goto enomem;
  8.2478          }
  8.2479 -    }
  8.2480 +    } // End prepare output message for return
  8.2481  
  8.2482      *dst = msg;
  8.2483      *keylist = _keylist;
  8.2484 @@ -2675,6 +2894,7 @@
  8.2485          GOTO(pep_error);
  8.2486      }
  8.2487  
  8.2488 +    dec_msg->enc_format = PEP_enc_none; // is this the right thing to do? FIXME
  8.2489      status = mime_encode_message(dec_msg, false, mime_plaintext);
  8.2490  
  8.2491      if (status == PEP_STATUS_OK)
  8.2492 @@ -2727,6 +2947,9 @@
  8.2493          GOTO(pep_error);
  8.2494      }
  8.2495  
  8.2496 +    // Clear the encryption status, or mime_encode will ignore
  8.2497 +    // the plaintext and do all sorts of other stupid things
  8.2498 +    enc_msg->enc_format = PEP_enc_none;
  8.2499      status = mime_encode_message(enc_msg, false, mime_ciphertext);
  8.2500  
  8.2501  pep_error:
     9.1 --- a/src/message_api.h	Fri Oct 06 15:51:35 2017 +0200
     9.2 +++ b/src/message_api.h	Tue Oct 17 14:20:12 2017 +0200
     9.3 @@ -33,7 +33,11 @@
     9.4      // This flag is for special use cases and should not be used
     9.5      // by normal pEp clients!
     9.6      PEP_encrypt_flag_force_unsigned = 0x2,
     9.7 -    PEP_encrypt_flag_force_no_attached_key = 0x4
     9.8 +    PEP_encrypt_flag_force_no_attached_key = 0x4,
     9.9 +    
    9.10 +    // This is used for outer messages (used to wrap the real message)
    9.11 +    // This is only used internally and (eventually) by transport functions
    9.12 +    PEP_encrypt_flag_inner_message = 0x8
    9.13  } PEP_encrypt_flags; 
    9.14  
    9.15  typedef unsigned int PEP_encrypt_flags_t;
    10.1 --- a/src/mime.c	Fri Oct 06 15:51:35 2017 +0200
    10.2 +++ b/src/mime.c	Tue Oct 17 14:20:12 2017 +0200
    10.3 @@ -819,14 +819,12 @@
    10.4  	struct mailmime_parameter * param;
    10.5      int r;
    10.6      PEP_STATUS status;
    10.7 -    //char *subject;
    10.8      char *plaintext;
    10.9      size_t plaintext_size;
   10.10  
   10.11      assert(msg->attachments && msg->attachments->next &&
   10.12              msg->attachments->next->value);
   10.13  
   10.14 -    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp"; // not used, yet.
   10.15      plaintext = msg->attachments->next->value;
   10.16      plaintext_size = msg->attachments->next->size;
   10.17  
    11.1 --- a/src/mime.h	Fri Oct 06 15:51:35 2017 +0200
    11.2 +++ b/src/mime.h	Tue Oct 17 14:20:12 2017 +0200
    11.3 @@ -40,6 +40,10 @@
    11.4  //      the resulttext will go to the ownership of the caller
    11.5  //      the message will remain in the ownership of the caller
    11.6  //      omit_fields is true for payload of PGP/MIME messages
    11.7 +//
    11.8 +//      also: note that the encryption type will be used to determine what
    11.9 +//      gets encoded from the message struct, so if using this on an 
   11.10 +//      already-encrypted message, set the enc_format of the msg to PEP_enc_none.
   11.11  
   11.12  DYNAMIC_API PEP_STATUS mime_encode_message(
   11.13          const message * msg,
    12.1 --- a/src/pEpEngine.c	Fri Oct 06 15:51:35 2017 +0200
    12.2 +++ b/src/pEpEngine.c	Tue Oct 17 14:20:12 2017 +0200
    12.3 @@ -8,7 +8,7 @@
    12.4  #include "blacklist.h"
    12.5  #include "sync_fsm.h"
    12.6  
    12.7 -static int init_count = -1;
    12.8 +static volatile int init_count = -1;
    12.9  
   12.10  // sql overloaded functions - modified from sqlite3.c
   12.11  static void _sql_lower(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
   12.12 @@ -264,9 +264,25 @@
   12.13      // a little race condition - but still a race condition
   12.14      // mitigated by calling caveat (see documentation)
   12.15  
   12.16 -    ++init_count;
   12.17 -    if (init_count == 0)
   12.18 +    // this increment is made atomic IN THE ADAPTERS by
   12.19 +    // guarding the call to init with the appropriate mutex.
   12.20 +    int _count = ++init_count;
   12.21 +    if (_count == 0)
   12.22          in_first = true;
   12.23 +    
   12.24 +    // Race contition mitigated by calling caveat starts here :
   12.25 +    // If another call to init() preempts right now, then preemptive call
   12.26 +    // will have in_first false, will not create SQL tables, and following
   12.27 +    // calls relying on those tables will fail.
   12.28 +    //
   12.29 +    // Therefore, as above, adapters MUST guard init() with a mutex.
   12.30 +    // 
   12.31 +    // Therefore, first session
   12.32 +    // is to be created and last session to be deleted alone, and not
   12.33 +    // concurently to other sessions creation or deletion.
   12.34 +    // We expect adapters to enforce this either by implicitely creating a
   12.35 +    // client session, or by using synchronization primitive to protect
   12.36 +    // creation/deletion of first/last session from the app.
   12.37  
   12.38      assert(session);
   12.39      if (session == NULL)
   12.40 @@ -306,6 +322,15 @@
   12.41          goto pep_error;
   12.42      }
   12.43  
   12.44 +    int_result = sqlite3_exec(
   12.45 +            _session->db,
   12.46 +            "PRAGMA journal_mode=WAL;\n",
   12.47 +            NULL,
   12.48 +            NULL,
   12.49 +            NULL
   12.50 +        );
   12.51 +
   12.52 +
   12.53      sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
   12.54  
   12.55      assert(SYSTEM_DB);
   12.56 @@ -772,19 +797,19 @@
   12.57  DYNAMIC_API void release(PEP_SESSION session)
   12.58  {
   12.59      bool out_last = false;
   12.60 -
   12.61 -    assert(init_count >= 0);
   12.62 +    int _count = --init_count;
   12.63 +    
   12.64 +    assert(_count >= -1);
   12.65      assert(session);
   12.66  
   12.67 -    if (!((init_count >= 0) && session))
   12.68 +    if (!((_count >= -1) && session))
   12.69          return;
   12.70  
   12.71      // a small race condition but still a race condition
   12.72      // mitigated by calling caveat (see documentation)
   12.73 -
   12.74 -    if (init_count == 0)
   12.75 +    // (release() is to be guarded by a mutex by the caller)
   12.76 +    if (_count == -1)
   12.77          out_last = true;
   12.78 -    --init_count;
   12.79  
   12.80      if (session) {
   12.81          if (session->sync_state != DeviceState_state_NONE)
    13.1 --- a/src/pEpEngine.h	Fri Oct 06 15:51:35 2017 +0200
    13.2 +++ b/src/pEpEngine.h	Tue Oct 17 14:20:12 2017 +0200
    13.3 @@ -16,7 +16,7 @@
    13.4  #include "stringpair.h"    
    13.5  #include "timestamp.h"
    13.6  
    13.7 -#define PEP_VERSION "1.0" // protocol version
    13.8 +#define PEP_VERSION "2.0" // protocol version
    13.9  
   13.10  #define PEP_OWN_USERID "pEp_own_userId"
   13.11      
   13.12 @@ -129,6 +129,9 @@
   13.13  //                                            opened
   13.14  //
   13.15  //  caveat:
   13.16 +//      THE CALLER MUST GUARD THIS CALL EXTERNALLY WITH A MUTEX. release() should
   13.17 +//      be similarly guarded.
   13.18 +//
   13.19  //      the pointer is valid only if the return value is PEP_STATUS_OK
   13.20  //      in other case a NULL pointer will be returned; a valid handle must
   13.21  //      be released using release() when it's no longer needed
   13.22 @@ -145,6 +148,9 @@
   13.23  //        session (in)    session handle to release
   13.24  //
   13.25  //    caveat:
   13.26 +//        THE CALLER MUST GUARD THIS CALL EXTERNALLY WITH A MUTEX. init() should
   13.27 +//        be similarly guarded.
   13.28 +//       
   13.29  //        the last release() can be called only when all other release() calls
   13.30  //        are done
   13.31  
   13.32 @@ -856,6 +862,7 @@
   13.33  
   13.34  DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity);
   13.35  
   13.36 +
   13.37  PEP_STATUS set_trust(PEP_SESSION session, 
   13.38                              const char* user_id,
   13.39                              const char* fpr, 
    14.1 --- a/src/pEp_internal.h	Fri Oct 06 15:51:35 2017 +0200
    14.2 +++ b/src/pEp_internal.h	Tue Oct 17 14:20:12 2017 +0200
    14.3 @@ -1,7 +1,7 @@
    14.4  // This file is under GNU General Public License 3.0
    14.5  // see LICENSE.txt
    14.6  
    14.7 -#define PEP_ENGINE_VERSION "0.8.0"
    14.8 +#define PEP_ENGINE_VERSION "0.9.0"
    14.9  
   14.10  // maximum attachment size to import as key 1MB, maximum of 20 attachments
   14.11  
   14.12 @@ -37,6 +37,19 @@
   14.13  #define PEP_SUBJ_BYTELEN 5
   14.14  #endif
   14.15  
   14.16 +#ifndef PEP_SUBJ_KEY
   14.17 +#define PEP_SUBJ_KEY "Subject: "
   14.18 +#define PEP_SUBJ_KEY_LC "subject: "
   14.19 +#define PEP_SUBJ_KEY_LEN 9
   14.20 +#endif
   14.21 +
   14.22 +#ifndef PEP_MSG_WRAP_KEY
   14.23 +#define PEP_MSG_WRAP_KEY "pEp-Wrapped-Message-Info: "
   14.24 +#define PEP_MSG_WRAP_KEY_LC "pep-wrapped-message-info: "
   14.25 +#define PEP_MSG_WRAP_KEY_LEN 26
   14.26 +#endif
   14.27 +
   14.28 +
   14.29  #include "platform.h"
   14.30  
   14.31  #ifdef WIN32
   14.32 @@ -173,6 +186,9 @@
   14.33      bool unencrypted_subject;
   14.34      bool keep_sync_msg;
   14.35      bool service_log;
   14.36 +
   14.37 +    // mistrust undo cache
   14.38 +    pEp_identity* cached_mistrusted;
   14.39      
   14.40  #ifdef DEBUG_ERRORSTACK
   14.41      stringlist_t* errorstack;
    15.1 --- a/src/pgp_gpg.c	Fri Oct 06 15:51:35 2017 +0200
    15.2 +++ b/src/pgp_gpg.c	Tue Oct 17 14:20:12 2017 +0200
    15.3 @@ -1833,22 +1833,24 @@
    15.4      } while (gpgme_error != GPG_ERR_EOF);
    15.5  
    15.6      gpg.gpgme_op_keylist_end(session->ctx);
    15.7 -    if (_keylist->value == NULL && pattern != NULL) {
    15.8 +    if (_keylist->value == NULL) {
    15.9          free_stringlist(_keylist);
   15.10          _keylist = NULL;
   15.11          
   15.12 -        // If match failed, check to see if we've got a dotted address in the pattern.
   15.13 -        // (last chance of the heuristic, really)
   15.14 -        // If so, try again without any dots.
   15.15 -        const char* dotpos = strstr(pattern, ".");
   15.16 -        const char* atpos = strstr(pattern, "@");
   15.17 -        if (dotpos && atpos && (dotpos < atpos)) {
   15.18 -            char* undotted = _undot_address(pattern);
   15.19 -            if (undotted) {
   15.20 -                PEP_STATUS status = _pgp_search_keys(session, undotted,
   15.21 -                                                     keylist, private_only);
   15.22 -                free(undotted);
   15.23 -                return status;
   15.24 +        if (pattern != NULL) {
   15.25 +            // If match failed, check to see if we've got a dotted address in the pattern.
   15.26 +            // (last chance of the heuristic, really)
   15.27 +            // If so, try again without any dots.
   15.28 +            const char* dotpos = strstr(pattern, ".");
   15.29 +            const char* atpos = strstr(pattern, "@");
   15.30 +            if (dotpos && atpos && (dotpos < atpos)) {
   15.31 +                char* undotted = _undot_address(pattern);
   15.32 +                if (undotted) {
   15.33 +                    PEP_STATUS status = _pgp_search_keys(session, undotted,
   15.34 +                                                         keylist, private_only);
   15.35 +                    free(undotted);
   15.36 +                    return status;
   15.37 +                }
   15.38              }
   15.39          }
   15.40      }    
    16.1 --- a/src/platform_unix.c	Fri Oct 06 15:51:35 2017 +0200
    16.2 +++ b/src/platform_unix.c	Tue Oct 17 14:20:12 2017 +0200
    16.3 @@ -297,8 +297,14 @@
    16.4              fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
    16.5  
    16.6              if(fd>0) {
    16.7 -                write(fd, gpg_conf_empty, strlen(gpg_conf_empty));
    16.8 +                ssize_t res;
    16.9 +                len = strlen(gpg_conf_empty);
   16.10 +                res = write(fd, gpg_conf_empty, len);
   16.11                  close(fd);
   16.12 +                if(res < len) {
   16.13 +                    assert(0);
   16.14 +                    return false;
   16.15 +                }
   16.16              }
   16.17          }
   16.18  
   16.19 @@ -344,8 +350,14 @@
   16.20              fd = open(agent_path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
   16.21  
   16.22              if(fd>0) {
   16.23 -                write(fd, gpg_conf_empty, strlen(gpg_conf_empty));
   16.24 +                ssize_t res;
   16.25 +                len = strlen(gpg_conf_empty);
   16.26 +                res = write(fd, gpg_conf_empty, len);
   16.27                  close(fd);
   16.28 +                if(res < len) {
   16.29 +                    assert(0);
   16.30 +                    return false;
   16.31 +                }
   16.32              }
   16.33          }
   16.34          done = true;
    17.1 --- a/test/external_revoke_test.cc	Fri Oct 06 15:51:35 2017 +0200
    17.2 +++ b/test/external_revoke_test.cc	Tue Oct 17 14:20:12 2017 +0200
    17.3 @@ -247,6 +247,9 @@
    17.4      
    17.5      // encrypt something to the key
    17.6      cout << "Creating message…\n";
    17.7 +    
    17.8 +    // cout << "First, update identity though!\n";
    17.9 +    // status = update_identity(session, recip1);
   17.10      to_list = new_identity_list(identity_dup(recip1)); // to bob
   17.11      outgoing_msg = new_message(PEP_dir_outgoing);
   17.12      assert(outgoing_msg);
   17.13 @@ -258,8 +261,8 @@
   17.14      cout << "Message created.\n";
   17.15  
   17.16      status = encrypt_message(session, outgoing_msg, NULL, &encrypted_outgoing_msg, PEP_enc_PGP_MIME, 0);
   17.17 -
   17.18      ct = (encrypted_outgoing_msg ? encrypted_outgoing_msg->to->ident->comm_type : outgoing_msg->to->ident->comm_type);
   17.19 +    
   17.20  
   17.21      // CHECK STATUS???
   17.22      cout << "Encryption returns with status " << tl_status_string(status) << endl;
   17.23 @@ -285,11 +288,13 @@
   17.24      status = decrypt_message(session, encrypted_outgoing_msg, &decrypted_msg, &keylist, &rating, &flags);
   17.25      cout << "Decryption returns with status " << tl_status_string(status) << endl;
   17.26      assert(status == PEP_STATUS_OK);
   17.27 -
   17.28 +    assert(decrypted_msg);
   17.29 +    
   17.30      // check rating
   17.31      cout << "Rating of decrypted message to trusted recip: " << tl_rating_string(rating) << endl;
   17.32      assert(rating == PEP_rating_reliable);
   17.33  
   17.34 +    status = update_identity(session, decrypted_msg->to->ident);
   17.35      ct = (decrypted_msg ? decrypted_msg->to->ident->comm_type : outgoing_msg->to->ident->comm_type);
   17.36  
   17.37      cout << "comm_type: " << tl_ct_string(ct) << endl;
    18.1 --- a/test/mime_test.cc	Fri Oct 06 15:51:35 2017 +0200
    18.2 +++ b/test/mime_test.cc	Tue Oct 17 14:20:12 2017 +0200
    18.3 @@ -102,4 +102,3 @@
    18.4      release(session);
    18.5      return 0;
    18.6  }
    18.7 -
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/test/mistrust_undo_test.cc	Tue Oct 17 14:20:12 2017 +0200
    19.3 @@ -0,0 +1,75 @@
    19.4 +// This file is under GNU General Public License 3.0
    19.5 +// see LICENSE.txt
    19.6 +
    19.7 +#include <stdlib.h>
    19.8 +#include <string.h>
    19.9 +#include <time.h>
   19.10 +#include "platform.h"
   19.11 +#include <iostream>
   19.12 +#include <fstream>
   19.13 +#include <assert.h>
   19.14 +#include "mime.h"
   19.15 +#include "message_api.h"
   19.16 +#include "test_util.h"
   19.17 +
   19.18 +using namespace std;
   19.19 +
   19.20 +int main() {
   19.21 +    cout << "\n*** mistrust_undo_test ***\n\n";
   19.22 +
   19.23 +    PEP_SESSION session;
   19.24 +    
   19.25 +    cout << "calling init()\n";
   19.26 +    PEP_STATUS status = init(&session);   
   19.27 +    assert(status == PEP_STATUS_OK);
   19.28 +    assert(session);
   19.29 +    cout << "init() completed.\n";
   19.30 +
   19.31 +    cout << "importing key 0x39E5DAB5." << endl;
   19.32 +    const string pub_key = slurp("test_keys/pub/mistrust.undo.test-0x39E5DAB5_pub.asc");
   19.33 +
   19.34 +    assert(pub_key.length() != 0);
   19.35 +    
   19.36 +    PEP_STATUS statuspub = import_key(session, pub_key.c_str(), pub_key.length(), NULL);
   19.37 +    assert(statuspub == PEP_STATUS_OK);
   19.38 +    cout << "Key imported." << endl << endl;
   19.39 +    
   19.40 +    cout << "Setting up identity for mistrust.undo.test@pep-project.org and making comm_type PEP_ct_pEp."  << endl;
   19.41 +    pEp_identity* recip1 = new_identity("mistrust.undo.test@pep-project.org", NULL, "TOFU_mistrust.undo.test@pep-project.org", "Mistrust Undo");
   19.42 +    status = update_identity(session,recip1);
   19.43 +    assert(status == PEP_STATUS_OK);
   19.44 +    assert(strcmp(recip1->fpr, "BACC7A60A88A39A25D99B4A545D7542F39E5DAB5") == 0);
   19.45 +    
   19.46 +    // This is not an external function. We use it to expedite the test since we don't do a sync exchange here.
   19.47 +    status = update_trust_for_fpr(session, recip1->fpr, PEP_ct_pEp);
   19.48 +    status = update_identity(session,recip1);
   19.49 +    assert(status == PEP_STATUS_OK);
   19.50 +    assert(recip1->comm_type == PEP_ct_pEp);
   19.51 +    assert(strcmp(recip1->fpr, "BACC7A60A88A39A25D99B4A545D7542F39E5DAB5") == 0);
   19.52 +    cout << "mistrust.undo.test@pep-project.org set up and comm_type is PEP_ct_pEp."  << endl << endl;
   19.53 +
   19.54 +    // Ok, mistrust away
   19.55 +    cout << "Mistrusting mistrust.undo.test@pep-project.org (BACC7A60A88A39A25D99B4A545D7542F39E5DAB5)."  << endl;   
   19.56 +    status = key_mistrusted(session, recip1);
   19.57 +    assert(status == PEP_STATUS_OK);
   19.58 +    status = update_identity(session,recip1);
   19.59 +    assert(status == PEP_STATUS_OK);
   19.60 +    assert(recip1->comm_type == PEP_ct_mistrusted);
   19.61 +    cout << "Mistrusted mistrust.undo.test@pep-project.org (BACC7A60A88A39A25D99B4A545D7542F39E5DAB5) and comm_type set to PEP_ct_mistrusted)." << endl  << endl;    
   19.62 +    
   19.63 +    cout << "Undo mistrust (restore identity and trust in DB)" << endl;
   19.64 +    // Undo it
   19.65 +    status = undo_last_mistrust(session);
   19.66 +    assert(status == PEP_STATUS_OK);
   19.67 +    status = update_identity(session, recip1);
   19.68 +    assert(recip1->comm_type == PEP_ct_pEp);
   19.69 +    assert(strcmp(recip1->fpr, "BACC7A60A88A39A25D99B4A545D7542F39E5DAB5") == 0);
   19.70 +    cout << "Undo mistrust (restore identity and trust in DB) - trust is now PEP_ct_pEp." << endl << endl;
   19.71 +
   19.72 +    cout << "Success!!!" << endl << endl;
   19.73 +    
   19.74 +    free_identity(recip1);
   19.75 +    release(session);
   19.76 +
   19.77 +    return 0;
   19.78 +}
    20.1 --- a/test/pEpEngineTest.cc	Fri Oct 06 15:51:35 2017 +0200
    20.2 +++ b/test/pEpEngineTest.cc	Tue Oct 17 14:20:12 2017 +0200
    20.3 @@ -9,15 +9,29 @@
    20.4  
    20.5  #include <assert.h>
    20.6  #include <string.h>
    20.7 +#include <sstream>
    20.8 +
    20.9  
   20.10  #include "../src/pEpEngine.h"
   20.11  #include "../src/keymanagement.h"
   20.12  
   20.13 -
   20.14  using namespace std;
   20.15  
   20.16  typedef std::string Buffer;
   20.17  
   20.18 +std::string slurp(const std::string& filename)
   20.19 +{
   20.20 +        std::ifstream input(filename.c_str());
   20.21 +        if(!input)
   20.22 +        {
   20.23 +                throw std::runtime_error("Cannot read file \"" + filename + "\"! ");
   20.24 +        }
   20.25 +
   20.26 +        std::stringstream sstr;
   20.27 +        sstr << input.rdbuf();
   20.28 +        return sstr.str();
   20.29 +}
   20.30 +
   20.31  // no C++11, yet? So do our own implementation:
   20.32  namespace{
   20.33      std::string to_string(unsigned long u)
   20.34 @@ -96,6 +110,35 @@
   20.35      cout << "dropping second session\n";
   20.36      release(second_session);
   20.37  
   20.38 +    cout << "Importing keys...";
   20.39 +    string pub_key = slurp("test_keys/pub/pep-test-alice-0x6FF00E97_pub.asc");
   20.40 +    string priv_key = slurp("test_keys/priv/pep-test-alice-0x6FF00E97_priv.asc");
   20.41 +
   20.42 +    PEP_STATUS statuspub = import_key(session, pub_key.c_str(), pub_key.length(), NULL);
   20.43 +    PEP_STATUS statuspriv = import_key(session, priv_key.c_str(), priv_key.length(), NULL);
   20.44 +    assert(statuspub == PEP_STATUS_OK);
   20.45 +    assert(statuspriv == PEP_STATUS_OK);
   20.46 +
   20.47 +    pub_key = slurp("test_keys/pub/pep-test-john-0x70DCF575_pub.asc");
   20.48 +    priv_key = slurp("test_keys/priv/pep-test-john-0x70DCF575_priv.asc");
   20.49 +
   20.50 +    statuspub = import_key(session, pub_key.c_str(), pub_key.length(), NULL);
   20.51 +    statuspriv = import_key(session, priv_key.c_str(), priv_key.length(), NULL);
   20.52 +    assert(statuspub == PEP_STATUS_OK);
   20.53 +    assert(statuspriv == PEP_STATUS_OK);
   20.54 +
   20.55 +    pub_key = slurp("test_keys/pub/pep-test-bob-0xC9C2EE39_pub.asc");
   20.56 +
   20.57 +    statuspub = import_key(session, pub_key.c_str(), pub_key.length(), NULL);
   20.58 +    assert(statuspub == PEP_STATUS_OK);
   20.59 +    assert(statuspriv == PEP_STATUS_OK);
   20.60 +
   20.61 +
   20.62 +    cout << "creating message…\n";
   20.63 +    pEp_identity* alice = new_identity("pep.test.alice@pep-project.org", "4ABE3AAF59AC32CFE4F86500A9411D176FF00E97", PEP_OWN_USERID, "Alice Test");
   20.64 +    pEp_identity* bob = new_identity("pep.test.bob@pep-project.org", NULL, "42", "Bob Test");
   20.65 +
   20.66 +
   20.67      cout << "logging test\n";
   20.68      log_event(session, "log test", "pEp Engine Test", "This is a logging test sample.", "please ignore this line");
   20.69  
    21.1 --- a/test/revoke_regen_attach_test.cc	Fri Oct 06 15:51:35 2017 +0200
    21.2 +++ b/test/revoke_regen_attach_test.cc	Tue Oct 17 14:20:12 2017 +0200
    21.3 @@ -61,7 +61,6 @@
    21.4      message *enc_msg;
    21.5      cout << "calling encrypt_message()\n";
    21.6      status = encrypt_message(session, msg, NULL, &enc_msg, PEP_enc_PGP_MIME, 0);
    21.7 -    cout << status;
    21.8      assert(status == PEP_STATUS_OK);
    21.9      assert(enc_msg);
   21.10      cout << "message encrypted.\n";
   21.11 @@ -71,7 +70,7 @@
   21.12      assert(strcmp(msg->attachments->filename, "file://pEpkey.asc") == 0);
   21.13      assert(strcmp(msg->attachments->next->filename, "file://pEpkey.asc") == 0);
   21.14  
   21.15 -    cout << "message contains 2 key attachements.\n";
   21.16 +    cout << "message contains 2 key attachments.\n";
   21.17  
   21.18      free_message(msg);
   21.19      free_message(enc_msg);
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/test/test_keys/priv/mistrust.undo.test-0x39E5DAB5_priv.asc	Tue Oct 17 14:20:12 2017 +0200
    22.3 @@ -0,0 +1,57 @@
    22.4 +-----BEGIN PGP PRIVATE KEY BLOCK-----
    22.5 +
    22.6 +lQOYBFnTjWIBCAC78lI82/kYpsd/bQ7iUkQyKlOhT4e2MdnaaiTOSJf6N0liSjnt
    22.7 +Ah49e5+qus4Z3zAHgDWOZxSa7fOSPlVSAj35yM2X2Xn1nDJ5CxTYNCqluK5f811a
    22.8 +cUmvC166ZTsjdjmgNDAwzNpwmjbAEhKyibxnTd2vpJlW3+nVCCXg9JHMfuSj71t8
    22.9 +0OpZNZ3uqVqAekcY7SvMcaCQ41A44IkN/gAOK3Z/Cml62mRpsaKss85ZBJKXP7n+
   22.10 +61mKvT7EK1zc5dD2pdxROnjxDYaAGuJKtLwzoSm2/syvMY2VpTrh2rSQVI7gR+ep
   22.11 +WcGkT4kTFFP5mSrOYL5bKnUjfaybk/26G8TFABEBAAEAB/4lOJlGyj2rvyPVPZDs
   22.12 +C2TMFovXb3ut/nNpiQne/It0l0xmNdMA+CFrBbeaRUKZ5xSI98AjgpCXGjbZqJSX
   22.13 +GDCT7kuhHgXEOXnZdPNc2f/0L/4ArJ65UaRJEVRiT7gFjt1ct9kvYPKFyFS9dxbS
   22.14 +2uo//zC/Hzbq+I9DjEiMI4NYXxW9jh93UB0CpJ+mbEb1F58Yh9GfXTwZbResO2ET
   22.15 +Ws6Puhm71/EHOAHZoKjNTND2oz1Aoy4IyXrJ1M0sFJNvfHLfOfvg5GL1Q0CC1pFY
   22.16 +X0Ap60Odj/8cRR3S5l327ZZZwl+2xheCP4M9ypHBlGC0z+4iNRXJQ71fFZRIRDSQ
   22.17 +vb8FBADHjrH66y+tMkRnbvm+bjmncFkHjx6H1nojBVj6SfMsTCqCd9ZAhbhH7F2c
   22.18 +/2jO3Od8uYdHvg0ze4eR8XlbkwFNwXNxOZvvqmUO+rlJP7Ks8zN8XBxwOazE7d48
   22.19 +urzL7BV6kw2xjaWbuxXi25rG+VpYsSNW+5aErjxUZvIapGVTBwQA8RrsSm4EKz9U
   22.20 +GqW3Mio5wYWcAiwbs7UpEjFHqj8uvx2mHUXBaETbjnuVGnyZ/POAARlWj80EgDZj
   22.21 +1F9QXDdBbRBf8IxmnwTapk4St53cykDQgSMIdHpTsEGaM62qCyHgBOn1n/YMwlZh
   22.22 +6k01TK07yMgvVzFQeFdfxY83QvIBetMD/0+uk1tum1ZTw5iA+vJaxggVQDJeC0SD
   22.23 +lVZnAqXrG52Cu9yvCN2+PzNB2Zxcxds426EGokV/JdDMDe7FuLLjFckNKVwrN/qg
   22.24 +wRi0eS00JOhuPXye0cmEyhIb0NenGDNT92n2ePUo5cIG5654pK2s9OwtaLj83rUg
   22.25 +/PVeg+dAPxsHPeC0P01pc3RydXN0IFVuZG8gKERPIE5PVCBVU0UpIDxtaXN0cnVz
   22.26 +dC51bmRvLnRlc3RAcGVwLXByb2plY3Qub3JnPokBOAQTAQgAIgUCWdONYgIbAwYL
   22.27 +CQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQRddULznl2rUL3ggAlg6bnLr+Cw7e
   22.28 +/yYDk3Mdo0M5hN8cmeMC95CY4iwiiDjbCK2AsSCjhTGWM59hJ3pSA8x+GGBBeFCi
   22.29 +Gu0GLciEKuBPoJ1C4OFTUq5goDxvyysGHZ6OwRyfnHLl4mSEW86op0fkSHle25V9
   22.30 +lO/WjuWNwjoi9hLoW8IoN51dY0PZK69EeKuaX588nGJrOJeuZr3zLlziu9Km24Y5
   22.31 +El6M3GIZkaQcbiW2nbM/WkkRNDgRJbCp1wZIHledC6hgTjObaae1iXHzByM/62t1
   22.32 +u/GzixLaccfC5GAFGBtFI338pWaLarfSRVVbT6YBEMDJhrIcKtDWBi22yjRGxg/7
   22.33 +2Gz+mj0lLZ0DmARZ041iAQgAz34Vh5+c8qRa11f5nbWDssmC/2jxZdsX0cqSSozX
   22.34 +xuJ4l5lor/2dfqq2WCNWzdj+n8JGJrFVmpEL9rVTAARkUbNHzWv5pAe353JWkuTM
   22.35 +LIVFzdNIXymHyKck7S4QSohpoT/UA6gTtQD6kLbSFqycfkRlRWw0qYpPJEYiIdCz
   22.36 +lwEMffpu6ltzCXi3He6K7+S/XA5DXTIdArx3UMB/rJ69WCeEh77S7i5l223MmZLj
   22.37 +FIM9VRLP7SyIaOxnn1LlLCjbgT7gAX7S9aYeAWi8aZqtBcQ/wrSlvKPNYElEvFsG
   22.38 +kxrUCKYg6T1cWfU1ch4uCDqrrKdNQFpRF4NgUuFIOcnt8QARAQABAAf/YE0jjvO8
   22.39 +sz0m0EWLm+/P9R3jx8kcKOr77im3phQiXbNkxu+zj+MEwvJWeSfFtPpeiyVuy6yI
   22.40 +j5l8VP+pSxu+t9Cepa/UiJXwe+IsXjcEsDEWycWjFE/BLpas48v6Ua1oYSevrhbH
   22.41 +Nr4CjUHc1hs88rmpywPCmWGRA8PtOYaUo6NJMmTJYeDW4xqTvHu5R38iWUwAXwwP
   22.42 +JZIV7qm6ruzdfhLWYlRFGaiijPjSO6tkuP0EuYnqcD8ETgXg+zyNRdTCcBw1T6Z/
   22.43 +lVvx+LwG0f4ZmNdzN4InUEd63kPkxSXYNSEwlFPMX7iWkIjYg6DT0kLxqoMGrZQg
   22.44 +I27EQXlBLS3wNQQA0upHKHsDnCDIiZw7zxxbISTWgoclpSn1kXgS9MpriNBMITEf
   22.45 +DS3rVKnw9YteKFGnhBoI5UebdoDL1O/SjXH+a93u6mnTitYkW1W5EVybZMC3GzYc
   22.46 +HQbb98uhWi+wmz/3mS7yHc2p9LnBuMJr25Mb3ruSbd6DjFhRUoLrkURP9MMEAPvY
   22.47 +gzHGj1JvphioqXgj5LN2nXwD599Lku5bgSKMjyAA9P7A0xEE3agm9s7alU/t5Kws
   22.48 +E9bzfWNNB34Dl82cm3chLGFBa4JU68UbDSKsERpo2H1XjYs0wn9BoXPAnVh9O5sn
   22.49 +gC2qMOw3Qz32tfiUHqQpIxHB4SgdLFms3ibgNRc7A/4/xxamL2OJW9ujcBXwnX5a
   22.50 +n4mhQ2rRBnJw8vTYukJyJCZ4lN3ODUp9fKDHR5b9nddn+N89mO+AWVEm5ChjNGyT
   22.51 +hy+8AttETE9+2NtkCJVTIC49V9PBqMrYpnXz2SG4hW/koPB/rRz0ubFBAIi2M1aI
   22.52 +kB5KjFUNK/4BuGnpT69pAEeniQEfBBgBCAAJBQJZ041iAhsMAAoJEEXXVC855dq1
   22.53 +RHAH/iogJhtuUKPaec9Mu+W9g3+lcfh+QAHvqeIuzo6ff0OJn1hQXkG8lfclhHhD
   22.54 +w0dngLaxeTV3ZOYy08ScRWxWIz01BKeWXXM47MO2+qOpZsdZLwwpFb1FG7wOdsfr
   22.55 +QWGWxfJ7bew7HZOL8jG3xvWeCbXSt1BJGjA0hN1Oa9x02lwL5M/ALyYOGD0Z/F/8
   22.56 +FG8gyQnykuAnoT8zifzsv7keQDiJ+xQSrvWPAcsDsJ9XZxPd+jZ2b1q/xvMWD2WD
   22.57 +UU4FB91uKruSXnEOMo+/mr6NoSqKrkfvoQOep8Uz/2rr7Z5qwvRfV4aMtrz4aGh4
   22.58 +u/rtL+cuYZ38+YOc2vW35FVeMhU=
   22.59 +=pD3o
   22.60 +-----END PGP PRIVATE KEY BLOCK-----
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/test/test_keys/pub/mistrust.undo.test-0x39E5DAB5_pub.asc	Tue Oct 17 14:20:12 2017 +0200
    23.3 @@ -0,0 +1,30 @@
    23.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    23.5 +
    23.6 +mQENBFnTjWIBCAC78lI82/kYpsd/bQ7iUkQyKlOhT4e2MdnaaiTOSJf6N0liSjnt
    23.7 +Ah49e5+qus4Z3zAHgDWOZxSa7fOSPlVSAj35yM2X2Xn1nDJ5CxTYNCqluK5f811a
    23.8 +cUmvC166ZTsjdjmgNDAwzNpwmjbAEhKyibxnTd2vpJlW3+nVCCXg9JHMfuSj71t8
    23.9 +0OpZNZ3uqVqAekcY7SvMcaCQ41A44IkN/gAOK3Z/Cml62mRpsaKss85ZBJKXP7n+
   23.10 +61mKvT7EK1zc5dD2pdxROnjxDYaAGuJKtLwzoSm2/syvMY2VpTrh2rSQVI7gR+ep
   23.11 +WcGkT4kTFFP5mSrOYL5bKnUjfaybk/26G8TFABEBAAG0P01pc3RydXN0IFVuZG8g
   23.12 +KERPIE5PVCBVU0UpIDxtaXN0cnVzdC51bmRvLnRlc3RAcGVwLXByb2plY3Qub3Jn
   23.13 +PokBOAQTAQgAIgUCWdONYgIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ
   23.14 +RddULznl2rUL3ggAlg6bnLr+Cw7e/yYDk3Mdo0M5hN8cmeMC95CY4iwiiDjbCK2A
   23.15 +sSCjhTGWM59hJ3pSA8x+GGBBeFCiGu0GLciEKuBPoJ1C4OFTUq5goDxvyysGHZ6O
   23.16 +wRyfnHLl4mSEW86op0fkSHle25V9lO/WjuWNwjoi9hLoW8IoN51dY0PZK69EeKua
   23.17 +X588nGJrOJeuZr3zLlziu9Km24Y5El6M3GIZkaQcbiW2nbM/WkkRNDgRJbCp1wZI
   23.18 +HledC6hgTjObaae1iXHzByM/62t1u/GzixLaccfC5GAFGBtFI338pWaLarfSRVVb
   23.19 +T6YBEMDJhrIcKtDWBi22yjRGxg/72Gz+mj0lLbkBDQRZ041iAQgAz34Vh5+c8qRa
   23.20 +11f5nbWDssmC/2jxZdsX0cqSSozXxuJ4l5lor/2dfqq2WCNWzdj+n8JGJrFVmpEL
   23.21 +9rVTAARkUbNHzWv5pAe353JWkuTMLIVFzdNIXymHyKck7S4QSohpoT/UA6gTtQD6
   23.22 +kLbSFqycfkRlRWw0qYpPJEYiIdCzlwEMffpu6ltzCXi3He6K7+S/XA5DXTIdArx3
   23.23 +UMB/rJ69WCeEh77S7i5l223MmZLjFIM9VRLP7SyIaOxnn1LlLCjbgT7gAX7S9aYe
   23.24 +AWi8aZqtBcQ/wrSlvKPNYElEvFsGkxrUCKYg6T1cWfU1ch4uCDqrrKdNQFpRF4Ng
   23.25 +UuFIOcnt8QARAQABiQEfBBgBCAAJBQJZ041iAhsMAAoJEEXXVC855dq1RHAH/iog
   23.26 +JhtuUKPaec9Mu+W9g3+lcfh+QAHvqeIuzo6ff0OJn1hQXkG8lfclhHhDw0dngLax
   23.27 +eTV3ZOYy08ScRWxWIz01BKeWXXM47MO2+qOpZsdZLwwpFb1FG7wOdsfrQWGWxfJ7
   23.28 +bew7HZOL8jG3xvWeCbXSt1BJGjA0hN1Oa9x02lwL5M/ALyYOGD0Z/F/8FG8gyQny
   23.29 +kuAnoT8zifzsv7keQDiJ+xQSrvWPAcsDsJ9XZxPd+jZ2b1q/xvMWD2WDUU4FB91u
   23.30 +KruSXnEOMo+/mr6NoSqKrkfvoQOep8Uz/2rr7Z5qwvRfV4aMtrz4aGh4u/rtL+cu
   23.31 +YZ38+YOc2vW35FVeMhU=
   23.32 +=cCkg
   23.33 +-----END PGP PUBLIC KEY BLOCK-----