merged in current ENGINE-551 ENGINE-552
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Wed, 07 Aug 2019 14:17:27 +0200
branchENGINE-552
changeset 39629bf0c18c719c
parent 3715 8fa67f8b2c22
parent 3960 932e02830434
merged in current ENGINE-551
src/message_api.c
test/src/engine_tests/SyncTests.cc.b0rken
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/build-android/enable_address_sanitizer.patch	Wed Aug 07 14:17:27 2019 +0200
     1.3 @@ -0,0 +1,92 @@
     1.4 +diff --git a/build-android/jni/Android.mk b/build-android/jni/Android.mk
     1.5 +--- a/build-android/jni/Android.mk
     1.6 ++++ b/build-android/jni/Android.mk
     1.7 +@@ -14,7 +14,9 @@
     1.8 + 
     1.9 + LOCAL_MODULE    := pEpEngine
    1.10 + LOCAL_CFLAGS    += -std=c99
    1.11 +-
    1.12 ++#LOCAL_CFLAGS    += -fsanitize=address -fno-omit-frame-pointer
    1.13 ++#LOCAL_LDFLAGS   += -fsanitize=address
    1.14 ++#LOCAL_ARM_MODE := arm
    1.15 + # from http://www.sqlite.org/android/finfo?name=jni/sqlite/Android.mk 
    1.16 + #      http://www.sqlite.org/android/artifact/e8ed354b3e58c835
    1.17 + 
    1.18 +@@ -28,6 +30,7 @@
    1.19 +                     $(GPGME_INCLUDE_PATH) \
    1.20 +                     $(LIBETPAN_PATH)/include
    1.21 + LOCAL_C_INCLUDES += $(GPGBUILD)/$(TARGET_ARCH_ABI)/app_opt/include
    1.22 ++LOCAL_C_INCLUDES += /home/huss/src/test/sequoia/openpgp-ffi/include
    1.23 + 
    1.24 + $(shell sh $(LOCAL_PATH)/../takeOutHeaderFiles.sh $(LOCAL_PATH)../../)
    1.25 + LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)../include
    1.26 +@@ -38,5 +41,6 @@
    1.27 + ASN1_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../asn.1/*.c)
    1.28 + LOCAL_SRC_FILES := $(ENGINE_SRC_FILES:%=%)  $(ASN1_SRC_FILES:$(LOCAL_PATH)/%=%)
    1.29 + 
    1.30 ++#LOCAL_ADDRESS_SANITIZER:=true
    1.31 + 
    1.32 + include $(BUILD_STATIC_LIBRARY)
    1.33 +diff --git a/src/pEpEngine.c b/src/pEpEngine.c
    1.34 +--- a/src/pEpEngine.c
    1.35 ++++ b/src/pEpEngine.c
    1.36 +@@ -2015,7 +2015,7 @@
    1.37 + // N.B. If testing (so NDEBUG not defined) but this message is spam,
    1.38 + //      put -D_PEP_SERVICE_LOG_OFF into CFLAGS/CXXFLAGS     
    1.39 + #if !defined(NDEBUG) && !defined(_PEP_SERVICE_LOG_OFF)
    1.40 +-    fprintf(stdout, "\n*** %s %s %s %s\n", title, entity, description, comment);
    1.41 ++    __android_log_print(ANDROID_LOG_DEBUG, "pEpEngine", " %s :: %s :: %s :: %s ", title, entity, description, comment);
    1.42 +     session->service_log = true;
    1.43 + #endif
    1.44 + 
    1.45 +diff --git a/sync/gen_dot.ysl2 b/sync/gen_dot.ysl2
    1.46 +--- a/sync/gen_dot.ysl2
    1.47 ++++ b/sync/gen_dot.ysl2
    1.48 +@@ -9,7 +9,7 @@
    1.49 +     digraph finite_state_machine {
    1.50 +         rankdir=LR;
    1.51 +         node [shape = doublecircle];
    1.52 +-        `apply "state[@end='1']" mode=end`;
    1.53 ++        `apply "state[@timeout='off']" mode=end`;
    1.54 +         node [shape = circle];
    1.55 + 
    1.56 +         `` apply "state" mode=do
    1.57 +diff --git a/sync/sync.fsm b/sync/sync.fsm
    1.58 +--- a/sync/sync.fsm
    1.59 ++++ b/sync/sync.fsm
    1.60 +@@ -155,7 +155,7 @@
    1.61 +                 go HandshakingNewPhase2Second;
    1.62 +         }
    1.63 + 
    1.64 +-        state HandshakingNewPhase1First {
    1.65 ++        state HandshakingNewPhase1First timeout=300 {
    1.66 +             on Rollback if sameTransactionAndPartner {
    1.67 +                 do untrustThisKey;
    1.68 +                 go Sole;
    1.69 +@@ -172,7 +172,7 @@
    1.70 +             }
    1.71 +         }
    1.72 + 
    1.73 +-        state HandshakingNewPhase1Second {
    1.74 ++        state HandshakingNewPhase1Second timeout=300 {
    1.75 +             on Rollback if sameTransactionAndPartner {
    1.76 +                 do untrustThisKey;
    1.77 +                 go Sole;
    1.78 +@@ -189,7 +189,7 @@
    1.79 +             }
    1.80 +         }
    1.81 + 
    1.82 +-        state HandshakingNewPhase2First {
    1.83 ++        state HandshakingNewPhase2First timeout=300 {
    1.84 +             on Cancel {
    1.85 +                 send Rollback;
    1.86 +                 go Sole;
    1.87 +@@ -208,7 +208,7 @@
    1.88 +             }
    1.89 +         }
    1.90 + 
    1.91 +-        state HandshakingNewPhase2Second {
    1.92 ++        state HandshakingNewPhase2Second timeout=300 {
    1.93 +             on Cancel {
    1.94 +                 send Rollback;
    1.95 +                 go Sole;
     2.1 --- a/build-android/jni/Android.mk	Thu May 16 17:55:58 2019 +0200
     2.2 +++ b/build-android/jni/Android.mk	Wed Aug 07 14:17:27 2019 +0200
     2.3 @@ -5,7 +5,6 @@
     2.4  LOCAL_PATH := $(call my-dir)
     2.5  
     2.6  LIBETPAN_PATH:=  $(LOCAL_PATH)/../../../pEpJNIAdapter/android/external/libetpan/build-android
     2.7 -GPGME_INCLUDE_PATH:=  $(LOCAL_PATH)/../../../pEpJNIAdapter/android/external/data/data/pep.android.k9/app_opt/include
     2.8  
     2.9  include $(CLEAR_VARS)
    2.10  
    2.11 @@ -13,10 +12,6 @@
    2.12  $(error LIBETPAN_PATH must be set)
    2.13  endif
    2.14  
    2.15 -ifeq ($(GPGME_INCLUDE_PATH),)
    2.16 -$(error GPGME_INCLUDE_PATH must be set)
    2.17 -endif
    2.18 -
    2.19  LOCAL_MODULE    := pEpEngine
    2.20  LOCAL_CFLAGS    += -std=c99
    2.21  
    2.22 @@ -27,17 +22,18 @@
    2.23  # Android has no globally writable temp directory, if this is not defined the
    2.24  # application throws an exception when it tries to create a temp file.
    2.25  #
    2.26 -LOCAL_CFLAGS    += -DSQLITE_TEMP_STORE=3
    2.27 +LOCAL_CFLAGS    += -DSQLITE_TEMP_STORE=3 -DUSE_SEQUOIA
    2.28  
    2.29  LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../asn.1 \
    2.30                      $(GPGME_INCLUDE_PATH) \
    2.31                      $(LIBETPAN_PATH)/include
    2.32 -LOCAL_C_INCLUDES += $(GPGBUILD)/include
    2.33 +LOCAL_C_INCLUDES += $(GPGBUILD)/$(TARGET_ARCH_ABI)/app_opt/include
    2.34  
    2.35  $(shell sh $(LOCAL_PATH)/../takeOutHeaderFiles.sh $(LOCAL_PATH)../../)
    2.36  LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)../include
    2.37  
    2.38 -ENGINE_SRC_FILES := $(shell find $(LOCAL_PATH)/../../src/ ! -name "*sequoia*" ! -name "*netpgp*" -name "*.c")
    2.39 +#ENGINE_SRC_FILES := $(shell find $(LOCAL_PATH)/../../src/ ! -name "*sequoia*" ! -name "*netpgp*" -name "*.c")
    2.40 +ENGINE_SRC_FILES := $(shell find $(LOCAL_PATH)/../../src/ ! -name "*gpg*" ! -name "*netpgp*" -name "*.c")
    2.41  #ENGINE_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../src/*.c)
    2.42  ASN1_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../asn.1/*.c)
    2.43  LOCAL_SRC_FILES := $(ENGINE_SRC_FILES:%=%)  $(ASN1_SRC_FILES:$(LOCAL_PATH)/%=%)
     3.1 --- a/build-android/jni/Application.mk	Thu May 16 17:55:58 2019 +0200
     3.2 +++ b/build-android/jni/Application.mk	Wed Aug 07 14:17:27 2019 +0200
     3.3 @@ -1,4 +1,4 @@
     3.4  APP_OPTIM := debug
     3.5  APP_PLATFORM=android-21
     3.6 -APP_ABI := armeabi-v7a
     3.7 +APP_ABI := arm64-v8a
     3.8  NDK_TOOLCHAIN_VERSION = clang
     4.1 --- a/build-mac/pEpEngine.xcodeproj/project.pbxproj	Thu May 16 17:55:58 2019 +0200
     4.2 +++ b/build-mac/pEpEngine.xcodeproj/project.pbxproj	Wed Aug 07 14:17:27 2019 +0200
     4.3 @@ -7,143 +7,159 @@
     4.4  	objects = {
     4.5  
     4.6  /* Begin PBXBuildFile section */
     4.7 -		1521CEF6225C9AEF00FD2AA2 /* CommitAcceptForGroup.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521CEE9225C9AED00FD2AA2 /* CommitAcceptForGroup.c */; };
     4.8 -		1521CEF7225C9AEF00FD2AA2 /* PString.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEA225C9AEE00FD2AA2 /* PString.h */; };
     4.9 -		1521CEF8225C9AEF00FD2AA2 /* Rollback.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEB225C9AEE00FD2AA2 /* Rollback.h */; };
    4.10 -		1521CEF9225C9AEF00FD2AA2 /* CommitAcceptForGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEC225C9AEE00FD2AA2 /* CommitAcceptForGroup.h */; };
    4.11 -		1521CEFB225C9AEF00FD2AA2 /* CommitAccept.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEE225C9AEE00FD2AA2 /* CommitAccept.h */; };
    4.12 -		1521CEFD225C9AEF00FD2AA2 /* pdu_collection.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521CEF0225C9AEE00FD2AA2 /* pdu_collection.c */; };
    4.13 -		1521CEFE225C9AEF00FD2AA2 /* KeySync.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF1225C9AEE00FD2AA2 /* KeySync.h */; };
    4.14 -		1521CEFF225C9AEF00FD2AA2 /* CommitReject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF2225C9AEE00FD2AA2 /* CommitReject.h */; };
    4.15 -		1521CF00225C9AEF00FD2AA2 /* Sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF3225C9AEE00FD2AA2 /* Sync.h */; };
    4.16 -		1521CF01225C9AEF00FD2AA2 /* TID.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF5225C9AEF00FD2AA2 /* TID.h */; };
    4.17 +		154917FD22B926700091B6D6 /* libnettle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 154917F922B9266F0091B6D6 /* libnettle.a */; };
    4.18 +		154917FE22B926700091B6D6 /* libsequoia_openpgp_ffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 154917FA22B926700091B6D6 /* libsequoia_openpgp_ffi.a */; };
    4.19 +		154917FF22B926700091B6D6 /* libhogweed.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 154917FB22B926700091B6D6 /* libhogweed.a */; };
    4.20 +		1549180022B926700091B6D6 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 154917FC22B926700091B6D6 /* libgmp.a */; };
    4.21 +		1549181222B92EA20091B6D6 /* libiconv.2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 1549180D22B92EA20091B6D6 /* libiconv.2.tbd */; };
    4.22 +		154918AB22B940200091B6D6 /* fsm_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 1549189222B9401D0091B6D6 /* fsm_common.h */; };
    4.23 +		154918AC22B940200091B6D6 /* status_to_string.h in Headers */ = {isa = PBXBuildFile; fileRef = 1549189322B9401E0091B6D6 /* status_to_string.h */; };
    4.24 +		154918AF22B940200091B6D6 /* KeySync_fsm.h in Headers */ = {isa = PBXBuildFile; fileRef = 1549189622B9401E0091B6D6 /* KeySync_fsm.h */; };
    4.25 +		154918B022B940200091B6D6 /* KeySync_fsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 1549189722B9401E0091B6D6 /* KeySync_fsm.c */; };
    4.26 +		154918B122B940200091B6D6 /* Sync_actions.c in Sources */ = {isa = PBXBuildFile; fileRef = 1549189822B9401E0091B6D6 /* Sync_actions.c */; };
    4.27 +		154918B222B940200091B6D6 /* aux_mime_msg.h in Headers */ = {isa = PBXBuildFile; fileRef = 1549189922B9401E0091B6D6 /* aux_mime_msg.h */; };
    4.28 +		154918B322B940200091B6D6 /* Sync_impl.c in Sources */ = {isa = PBXBuildFile; fileRef = 1549189A22B9401E0091B6D6 /* Sync_impl.c */; };
    4.29 +		154918B522B940200091B6D6 /* sync_codec.c in Sources */ = {isa = PBXBuildFile; fileRef = 1549189C22B9401E0091B6D6 /* sync_codec.c */; };
    4.30 +		154918B622B940200091B6D6 /* Sync_event.h in Headers */ = {isa = PBXBuildFile; fileRef = 1549189D22B9401F0091B6D6 /* Sync_event.h */; };
    4.31 +		154918B722B940200091B6D6 /* Sync_event.c in Sources */ = {isa = PBXBuildFile; fileRef = 1549189E22B9401F0091B6D6 /* Sync_event.c */; };
    4.32 +		154918B922B940200091B6D6 /* Sync_func.c in Sources */ = {isa = PBXBuildFile; fileRef = 154918A022B9401F0091B6D6 /* Sync_func.c */; };
    4.33 +		154918BA22B940200091B6D6 /* resource_id.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A122B9401F0091B6D6 /* resource_id.h */; };
    4.34 +		154918BB22B940200091B6D6 /* aux_mime_msg.c in Sources */ = {isa = PBXBuildFile; fileRef = 154918A222B9401F0091B6D6 /* aux_mime_msg.c */; };
    4.35 +		154918BC22B940200091B6D6 /* openpgp_compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A322B9401F0091B6D6 /* openpgp_compat.h */; };
    4.36 +		154918BD22B940200091B6D6 /* growing_buf.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A422B9401F0091B6D6 /* growing_buf.h */; };
    4.37 +		154918BF22B940200091B6D6 /* sync_codec.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A622B9401F0091B6D6 /* sync_codec.h */; };
    4.38 +		154918C022B940200091B6D6 /* Sync_func.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A722B940200091B6D6 /* Sync_func.h */; };
    4.39 +		154918C222B940200091B6D6 /* Sync_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918A922B940200091B6D6 /* Sync_impl.h */; };
    4.40 +		154918C322B940200091B6D6 /* blacklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 154918AA22B940200091B6D6 /* blacklist.h */; };
    4.41 +		159EF42722B6D3E900149C0C /* pgp_sequoia.c in Sources */ = {isa = PBXBuildFile; fileRef = 159EF42422B6D3E900149C0C /* pgp_sequoia.c */; };
    4.42 +		159EF42822B6D3E900149C0C /* pgp_sequoia.h in Headers */ = {isa = PBXBuildFile; fileRef = 159EF42522B6D3E900149C0C /* pgp_sequoia.h */; };
    4.43 +		159EF42922B6D3E900149C0C /* pgp_sequoia_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 159EF42622B6D3E900149C0C /* pgp_sequoia_internal.h */; };
    4.44 +		15B037AA22B2B822002D664C /* ber_tlv_length.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0373F22B2B816002D664C /* ber_tlv_length.c */; };
    4.45 +		15B037AB22B2B822002D664C /* GroupKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374022B2B817002D664C /* GroupKeys.h */; };
    4.46 +		15B037AC22B2B822002D664C /* CommitAccept.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374122B2B817002D664C /* CommitAccept.c */; };
    4.47 +		15B037AD22B2B822002D664C /* Rollback.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374222B2B817002D664C /* Rollback.h */; };
    4.48 +		15B037AE22B2B822002D664C /* NegotiationOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374322B2B817002D664C /* NegotiationOpen.c */; };
    4.49 +		15B037AF22B2B822002D664C /* constr_SEQUENCE.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374422B2B817002D664C /* constr_SEQUENCE.c */; };
    4.50 +		15B037B022B2B822002D664C /* UTF8String.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374522B2B817002D664C /* UTF8String.c */; };
    4.51 +		15B037B122B2B822002D664C /* NegotiationRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374622B2B817002D664C /* NegotiationRequest.c */; };
    4.52 +		15B037B222B2B822002D664C /* Identity.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374722B2B817002D664C /* Identity.h */; };
    4.53 +		15B037B322B2B822002D664C /* Beacon.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374822B2B817002D664C /* Beacon.c */; };
    4.54 +		15B037B422B2B822002D664C /* PString.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374922B2B817002D664C /* PString.h */; };
    4.55 +		15B037B522B2B822002D664C /* OCTET_STRING.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374A22B2B817002D664C /* OCTET_STRING.c */; };
    4.56 +		15B037B622B2B822002D664C /* IdentityList.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374B22B2B817002D664C /* IdentityList.h */; };
    4.57 +		15B037B722B2B822002D664C /* Sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374C22B2B818002D664C /* Sync.c */; };
    4.58 +		15B037B822B2B822002D664C /* NativeInteger.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374D22B2B818002D664C /* NativeInteger.h */; };
    4.59 +		15B037B922B2B822002D664C /* NativeEnumerated.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0374E22B2B818002D664C /* NativeEnumerated.c */; };
    4.60 +		15B037BA22B2B822002D664C /* asn_system.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0374F22B2B818002D664C /* asn_system.h */; };
    4.61 +		15B037BB22B2B822002D664C /* der_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375022B2B818002D664C /* der_encoder.c */; };
    4.62 +		15B037BC22B2B822002D664C /* OwnKeysRequester.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375122B2B818002D664C /* OwnKeysRequester.c */; };
    4.63 +		15B037BD22B2B822002D664C /* CommitAcceptOfferer.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375222B2B818002D664C /* CommitAcceptOfferer.h */; };
    4.64 +		15B037BE22B2B822002D664C /* ber_tlv_tag.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375322B2B818002D664C /* ber_tlv_tag.c */; };
    4.65 +		15B037BF22B2B822002D664C /* BOOLEAN.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375422B2B818002D664C /* BOOLEAN.h */; };
    4.66 +		15B037C022B2B822002D664C /* per_opentype.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375522B2B819002D664C /* per_opentype.h */; };
    4.67 +		15B037C122B2B822002D664C /* Identity.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375622B2B819002D664C /* Identity.c */; };
    4.68 +		15B037C222B2B822002D664C /* asn_SEQUENCE_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375722B2B819002D664C /* asn_SEQUENCE_OF.c */; };
    4.69 +		15B037C322B2B822002D664C /* constr_SEQUENCE_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375822B2B819002D664C /* constr_SEQUENCE_OF.c */; };
    4.70 +		15B037C422B2B822002D664C /* pdu_collection.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375922B2B819002D664C /* pdu_collection.c */; };
    4.71 +		15B037C522B2B822002D664C /* Beacon.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375A22B2B819002D664C /* Beacon.h */; };
    4.72 +		15B037C622B2B822002D664C /* xer_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375B22B2B819002D664C /* xer_support.c */; };
    4.73 +		15B037C722B2B822002D664C /* per_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0375C22B2B819002D664C /* per_decoder.c */; };
    4.74 +		15B037C822B2B822002D664C /* ISO639-1.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375D22B2B819002D664C /* ISO639-1.h */; };
    4.75 +		15B037C922B2B822002D664C /* xer_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375E22B2B81A002D664C /* xer_decoder.h */; };
    4.76 +		15B037CA22B2B822002D664C /* PrintableString.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0375F22B2B81A002D664C /* PrintableString.h */; };
    4.77 +		15B037CB22B2B822002D664C /* ISO639-1.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0376022B2B81A002D664C /* ISO639-1.c */; };
    4.78 +		15B037CC22B2B822002D664C /* ber_tlv_tag.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376122B2B81A002D664C /* ber_tlv_tag.h */; };
    4.79 +		15B037CD22B2B822002D664C /* PString.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0376222B2B81A002D664C /* PString.c */; };
    4.80 +		15B037CE22B2B822002D664C /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376322B2B81A002D664C /* Hash.h */; };
    4.81 +		15B037CF22B2B822002D664C /* NativeEnumerated.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376422B2B81A002D664C /* NativeEnumerated.h */; };
    4.82 +		15B037D022B2B822002D664C /* constr_TYPE.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376522B2B81A002D664C /* constr_TYPE.h */; };
    4.83 +		15B037D122B2B822002D664C /* per_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0376622B2B81B002D664C /* per_encoder.c */; };
    4.84 +		15B037D222B2B822002D664C /* CommitAcceptRequester.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0376722B2B81B002D664C /* CommitAcceptRequester.c */; };
    4.85 +		15B037D322B2B822002D664C /* CommitReject.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376822B2B81B002D664C /* CommitReject.h */; };
    4.86 +		15B037D422B2B822002D664C /* NegotiationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376922B2B81B002D664C /* NegotiationRequest.h */; };
    4.87 +		15B037D522B2B822002D664C /* TID.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376A22B2B81B002D664C /* TID.h */; };
    4.88 +		15B037D622B2B822002D664C /* KeySync.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376B22B2B81B002D664C /* KeySync.h */; };
    4.89 +		15B037D722B2B822002D664C /* UTF8String.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376C22B2B81B002D664C /* UTF8String.h */; };
    4.90 +		15B037D822B2B822002D664C /* Version.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376D22B2B81C002D664C /* Version.h */; };
    4.91 +		15B037D922B2B822002D664C /* xer_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376E22B2B81C002D664C /* xer_encoder.h */; };
    4.92 +		15B037DA22B2B822002D664C /* asn_SET_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0376F22B2B81C002D664C /* asn_SET_OF.h */; };
    4.93 +		15B037DB22B2B822002D664C /* asn_codecs_prim.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377022B2B81C002D664C /* asn_codecs_prim.h */; };
    4.94 +		15B037DC22B2B822002D664C /* constraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377122B2B81C002D664C /* constraints.h */; };
    4.95 +		15B037DD22B2B822002D664C /* Rollback.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377222B2B81C002D664C /* Rollback.c */; };
    4.96 +		15B037DE22B2B822002D664C /* KeySync.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377322B2B81C002D664C /* KeySync.c */; };
    4.97 +		15B037DF22B2B822002D664C /* IdentityList.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377422B2B81C002D664C /* IdentityList.c */; };
    4.98 +		15B037E022B2B822002D664C /* TID.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377522B2B81D002D664C /* TID.c */; };
    4.99 +		15B037E122B2B822002D664C /* GroupTrustThisKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377622B2B81D002D664C /* GroupTrustThisKey.c */; };
   4.100 +		15B037E222B2B822002D664C /* per_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377722B2B81D002D664C /* per_encoder.h */; };
   4.101 +		15B037E322B2B822002D664C /* GroupKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377822B2B81D002D664C /* GroupKeys.c */; };
   4.102 +		15B037E422B2B822002D664C /* xer_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377922B2B81D002D664C /* xer_decoder.c */; };
   4.103 +		15B037E522B2B822002D664C /* constr_SEQUENCE.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377A22B2B81D002D664C /* constr_SEQUENCE.h */; };
   4.104 +		15B037E622B2B822002D664C /* constr_CHOICE.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377B22B2B81D002D664C /* constr_CHOICE.h */; };
   4.105 +		15B037E722B2B822002D664C /* GroupTrustThisKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0377C22B2B81D002D664C /* GroupTrustThisKey.h */; };
   4.106 +		15B037E822B2B822002D664C /* constr_TYPE.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377D22B2B81D002D664C /* constr_TYPE.c */; };
   4.107 +		15B037E922B2B822002D664C /* CommitAcceptOfferer.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377E22B2B81D002D664C /* CommitAcceptOfferer.c */; };
   4.108 +		15B037EA22B2B822002D664C /* BIT_STRING.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0377F22B2B81E002D664C /* BIT_STRING.c */; };
   4.109 +		15B037EB22B2B822002D664C /* constr_SET_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378022B2B81E002D664C /* constr_SET_OF.c */; };
   4.110 +		15B037EC22B2B822002D664C /* constraints.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378122B2B81E002D664C /* constraints.c */; };
   4.111 +		15B037ED22B2B822002D664C /* BIT_STRING.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378222B2B81E002D664C /* BIT_STRING.h */; };
   4.112 +		15B037EE22B2B822002D664C /* der_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378322B2B81E002D664C /* der_encoder.h */; };
   4.113 +		15B037EF22B2B822002D664C /* ber_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378422B2B81E002D664C /* ber_decoder.h */; };
   4.114 +		15B037F022B2B822002D664C /* NegotiationOpen.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378522B2B81E002D664C /* NegotiationOpen.h */; };
   4.115 +		15B037F122B2B822002D664C /* OCTET_STRING.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378622B2B81E002D664C /* OCTET_STRING.h */; };
   4.116 +		15B037F222B2B822002D664C /* constr_SEQUENCE_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378722B2B81E002D664C /* constr_SEQUENCE_OF.h */; };
   4.117 +		15B037F322B2B822002D664C /* CommitAccept.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378822B2B81F002D664C /* CommitAccept.h */; };
   4.118 +		15B037F422B2B822002D664C /* ber_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378922B2B81F002D664C /* ber_decoder.c */; };
   4.119 +		15B037F522B2B822002D664C /* INTEGER.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378A22B2B81F002D664C /* INTEGER.c */; };
   4.120 +		15B037F622B2B822002D664C /* Version.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378B22B2B81F002D664C /* Version.c */; };
   4.121 +		15B037F722B2B822002D664C /* per_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378C22B2B81F002D664C /* per_decoder.h */; };
   4.122 +		15B037F822B2B822002D664C /* OwnKeysOfferer.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0378D22B2B81F002D664C /* OwnKeysOfferer.c */; };
   4.123 +		15B037F922B2B822002D664C /* per_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378E22B2B81F002D664C /* per_support.h */; };
   4.124 +		15B037FA22B2B822002D664C /* INTEGER.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0378F22B2B81F002D664C /* INTEGER.h */; };
   4.125 +		15B037FB22B2B822002D664C /* Hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379022B2B81F002D664C /* Hash.c */; };
   4.126 +		15B037FC22B2B822002D664C /* Hex.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379122B2B820002D664C /* Hex.c */; };
   4.127 +		15B037FD22B2B822002D664C /* Hex.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379222B2B820002D664C /* Hex.h */; };
   4.128 +		15B037FE22B2B822002D664C /* xer_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379322B2B820002D664C /* xer_encoder.c */; };
   4.129 +		15B037FF22B2B822002D664C /* per_opentype.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379422B2B820002D664C /* per_opentype.c */; };
   4.130 +		15B0380022B2B822002D664C /* xer_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379522B2B820002D664C /* xer_support.h */; };
   4.131 +		15B0380122B2B822002D664C /* asn_SET_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379622B2B820002D664C /* asn_SET_OF.c */; };
   4.132 +		15B0380222B2B822002D664C /* ber_tlv_length.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379722B2B820002D664C /* ber_tlv_length.h */; };
   4.133 +		15B0380322B2B822002D664C /* OwnKeysRequester.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379822B2B820002D664C /* OwnKeysRequester.h */; };
   4.134 +		15B0380422B2B822002D664C /* constr_SET_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379922B2B821002D664C /* constr_SET_OF.h */; };
   4.135 +		15B0380522B2B822002D664C /* asn_codecs_prim.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379A22B2B821002D664C /* asn_codecs_prim.c */; };
   4.136 +		15B0380622B2B822002D664C /* CommitAcceptForGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379B22B2B821002D664C /* CommitAcceptForGroup.h */; };
   4.137 +		15B0380722B2B822002D664C /* constr_CHOICE.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379C22B2B821002D664C /* constr_CHOICE.c */; };
   4.138 +		15B0380822B2B822002D664C /* asn_codecs.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379D22B2B821002D664C /* asn_codecs.h */; };
   4.139 +		15B0380922B2B822002D664C /* per_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B0379E22B2B821002D664C /* per_support.c */; };
   4.140 +		15B0380A22B2B822002D664C /* asn_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B0379F22B2B821002D664C /* asn_internal.h */; };
   4.141 +		15B0380B22B2B822002D664C /* NativeInteger.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A022B2B821002D664C /* NativeInteger.c */; };
   4.142 +		15B0380C22B2B822002D664C /* BOOLEAN.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A122B2B821002D664C /* BOOLEAN.c */; };
   4.143 +		15B0380D22B2B822002D664C /* CommitReject.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A222B2B822002D664C /* CommitReject.c */; };
   4.144 +		15B0380E22B2B822002D664C /* PrintableString.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A322B2B822002D664C /* PrintableString.c */; };
   4.145 +		15B0380F22B2B823002D664C /* Sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A422B2B822002D664C /* Sync.h */; };
   4.146 +		15B0381022B2B823002D664C /* CommitAcceptRequester.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A522B2B822002D664C /* CommitAcceptRequester.h */; };
   4.147 +		15B0381122B2B823002D664C /* CommitAcceptForGroup.c in Sources */ = {isa = PBXBuildFile; fileRef = 15B037A622B2B822002D664C /* CommitAcceptForGroup.c */; };
   4.148 +		15B0381222B2B823002D664C /* OwnKeysOfferer.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A722B2B822002D664C /* OwnKeysOfferer.h */; };
   4.149 +		15B0381322B2B823002D664C /* asn_application.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A822B2B822002D664C /* asn_application.h */; };
   4.150 +		15B0381422B2B823002D664C /* asn_SEQUENCE_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 15B037A922B2B822002D664C /* asn_SEQUENCE_OF.h */; };
   4.151  		430BCC482015EE800077E998 /* pEp_string.h in Headers */ = {isa = PBXBuildFile; fileRef = 430BCC462015EE800077E998 /* pEp_string.h */; };
   4.152  		430BCC492015EE800077E998 /* pEp_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 430BCC472015EE800077E998 /* pEp_string.c */; };
   4.153  		430D258B1C9ED75A00B94535 /* blacklist.c in Sources */ = {isa = PBXBuildFile; fileRef = 430D258A1C9ED75A00B94535 /* blacklist.c */; };
   4.154 -		431F048C2273223600CCE960 /* CommitAcceptSecond.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04862273223600CCE960 /* CommitAcceptSecond.h */; };
   4.155 -		431F048D2273223600CCE960 /* CommitAcceptSecond.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F048B2273223600CCE960 /* CommitAcceptSecond.c */; };
   4.156 -		431F04902273227900CCE960 /* OwnKeysFirst.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F048E2273227900CCE960 /* OwnKeysFirst.h */; };
   4.157 -		431F04912273227900CCE960 /* OwnKeysFirst.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F048F2273227900CCE960 /* OwnKeysFirst.c */; };
   4.158 -		431F0494227322EF00CCE960 /* CommitAcceptFirst.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F0492227322EF00CCE960 /* CommitAcceptFirst.h */; };
   4.159 -		431F0495227322EF00CCE960 /* CommitAcceptFirst.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F0493227322EF00CCE960 /* CommitAcceptFirst.c */; };
   4.160 -		431F04A22273235300CCE960 /* GroupTrustThisKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F049C2273235300CCE960 /* GroupTrustThisKey.h */; };
   4.161 -		431F04A32273235300CCE960 /* GroupTrustThisKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F04A12273235300CCE960 /* GroupTrustThisKey.c */; };
   4.162 -		431F04A6227323A400CCE960 /* OwnKeysSecond.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04A4227323A400CCE960 /* OwnKeysSecond.h */; };
   4.163 -		431F04A7227323A400CCE960 /* OwnKeysSecond.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F04A5227323A400CCE960 /* OwnKeysSecond.c */; };
   4.164 -		431F04AA227323EE00CCE960 /* OwnKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04A8227323EE00CCE960 /* OwnKeys.h */; };
   4.165 -		431F04AB227323EE00CCE960 /* OwnKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F04A9227323EE00CCE960 /* OwnKeys.c */; };
   4.166  		431F04B722733A7E00CCE960 /* key_reset.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04B222733A7E00CCE960 /* key_reset.h */; };
   4.167  		43370833203C075A004E6547 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 4337082D203C075A004E6547 /* sqlite3.c */; };
   4.168  		43370834203C075A004E6547 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = 43370832203C075A004E6547 /* sqlite3.h */; };
   4.169 -		4354FF651D6EDF300033069C /* sync_impl.c in Sources */ = {isa = PBXBuildFile; fileRef = 4354FF641D6EDF300033069C /* sync_impl.c */; };
   4.170 -		438C439B2167582500C7425B /* sync_api.h in Headers */ = {isa = PBXBuildFile; fileRef = 438C43962167582400C7425B /* sync_api.h */; };
   4.171  		438C43B52167752C00C7425B /* labeled_int_list.h in Headers */ = {isa = PBXBuildFile; fileRef = 438C43AF2167752C00C7425B /* labeled_int_list.h */; };
   4.172  		438C43B62167752C00C7425B /* labeled_int_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 438C43B42167752C00C7425B /* labeled_int_list.c */; };
   4.173 -		43CC349E2276D31A002F77AF /* NegotiationRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CC349C2276D31A002F77AF /* NegotiationRequest.c */; };
   4.174 -		43CC349F2276D31A002F77AF /* NegotiationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CC349D2276D31A002F77AF /* NegotiationRequest.h */; };
   4.175 -		43CC34A22276D34C002F77AF /* NegotiationOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CC34A02276D34B002F77AF /* NegotiationOpen.c */; };
   4.176 -		43CC34A32276D34C002F77AF /* NegotiationOpen.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CC34A12276D34C002F77AF /* NegotiationOpen.h */; };
   4.177  		43F6921D1F164A47009418F5 /* resource_id.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F6921C1F164A47009418F5 /* resource_id.c */; };
   4.178 -		43F73BF02166269200AB4524 /* PString.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BEB2166269200AB4524 /* PString.c */; };
   4.179 -		43F73BF2216626E100AB4524 /* Sync_func.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF1216626E100AB4524 /* Sync_func.c */; };
   4.180 -		43F73BFC216627CC00AB4524 /* CommitAccept.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF5216627CB00AB4524 /* CommitAccept.c */; };
   4.181 -		43F73BFD216627CC00AB4524 /* TID.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF6216627CC00AB4524 /* TID.c */; };
   4.182 -		43F73BFE216627CC00AB4524 /* KeySync.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF7216627CC00AB4524 /* KeySync.c */; };
   4.183 -		43F73C00216627CC00AB4524 /* Rollback.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF9216627CC00AB4524 /* Rollback.c */; };
   4.184 -		43F73C02216627CC00AB4524 /* CommitReject.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BFB216627CC00AB4524 /* CommitReject.c */; };
   4.185  		43F73C0B2166282C00AB4524 /* openpgp_compat.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C032166282C00AB4524 /* openpgp_compat.c */; };
   4.186 -		43F73C0C2166282C00AB4524 /* Sync_event.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C042166282C00AB4524 /* Sync_event.c */; };
   4.187  		43F73C0D2166282C00AB4524 /* key_reset.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C052166282C00AB4524 /* key_reset.c */; };
   4.188 -		43F73C0E2166282C00AB4524 /* sync_codec.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C062166282C00AB4524 /* sync_codec.c */; };
   4.189 -		43F73C0F2166282C00AB4524 /* KeySync_fsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C072166282C00AB4524 /* KeySync_fsm.c */; };
   4.190  		43F73C112166282C00AB4524 /* sync_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C092166282C00AB4524 /* sync_api.c */; };
   4.191  		43F73C122166282C00AB4524 /* growing_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C0A2166282C00AB4524 /* growing_buf.c */; };
   4.192 -		43F73C14216628CA00AB4524 /* Sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C13216628CA00AB4524 /* Sync.c */; };
   4.193 -		6400FB861B8CA1C6005221E3 /* libnetpgp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 645922521B8BD32B00A5AF93 /* libnetpgp.a */; };
   4.194  		6400FB8B1B8CA1CF005221E3 /* libetpan-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64289E371B8B630200FC617B /* libetpan-ios.a */; };
   4.195  		644297C51BE11CE0002BC73B /* system.db in Resources */ = {isa = PBXBuildFile; fileRef = 64951A1B1BE0FCD800B10E71 /* system.db */; };
   4.196  		6467888C1CEB3D120001F54C /* map_asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = 646788871CEB3D120001F54C /* map_asn1.c */; };
   4.197  		6467888D1CEB3D120001F54C /* map_asn1.h in Headers */ = {isa = PBXBuildFile; fileRef = 646788881CEB3D120001F54C /* map_asn1.h */; };
   4.198 -		646C40EA1D510CD800C63EFF /* asn_application.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40951D510CD700C63EFF /* asn_application.h */; };
   4.199 -		646C40EB1D510CD800C63EFF /* asn_codecs_prim.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40961D510CD700C63EFF /* asn_codecs_prim.c */; };
   4.200 -		646C40EC1D510CD800C63EFF /* asn_codecs_prim.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40971D510CD700C63EFF /* asn_codecs_prim.h */; };
   4.201 -		646C40ED1D510CD800C63EFF /* asn_codecs.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40981D510CD700C63EFF /* asn_codecs.h */; };
   4.202 -		646C40EE1D510CD800C63EFF /* asn_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40991D510CD700C63EFF /* asn_internal.h */; };
   4.203 -		646C40EF1D510CD800C63EFF /* asn_SEQUENCE_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C409A1D510CD700C63EFF /* asn_SEQUENCE_OF.c */; };
   4.204 -		646C40F01D510CD800C63EFF /* asn_SEQUENCE_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C409B1D510CD700C63EFF /* asn_SEQUENCE_OF.h */; };
   4.205 -		646C40F11D510CD800C63EFF /* asn_SET_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C409C1D510CD700C63EFF /* asn_SET_OF.c */; };
   4.206 -		646C40F21D510CD800C63EFF /* asn_SET_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C409D1D510CD700C63EFF /* asn_SET_OF.h */; };
   4.207 -		646C40F31D510CD800C63EFF /* asn_system.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C409E1D510CD700C63EFF /* asn_system.h */; };
   4.208 -		646C40F41D510CD800C63EFF /* Beacon.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C409F1D510CD700C63EFF /* Beacon.c */; };
   4.209 -		646C40F51D510CD800C63EFF /* Beacon.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40A01D510CD700C63EFF /* Beacon.h */; };
   4.210 -		646C40F61D510CD800C63EFF /* ber_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40A11D510CD700C63EFF /* ber_decoder.c */; };
   4.211 -		646C40F71D510CD800C63EFF /* ber_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40A21D510CD700C63EFF /* ber_decoder.h */; };
   4.212 -		646C40F81D510CD800C63EFF /* ber_tlv_length.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40A31D510CD700C63EFF /* ber_tlv_length.c */; };
   4.213 -		646C40F91D510CD800C63EFF /* ber_tlv_length.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40A41D510CD700C63EFF /* ber_tlv_length.h */; };
   4.214 -		646C40FA1D510CD800C63EFF /* ber_tlv_tag.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40A51D510CD700C63EFF /* ber_tlv_tag.c */; };
   4.215 -		646C40FB1D510CD800C63EFF /* ber_tlv_tag.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40A61D510CD700C63EFF /* ber_tlv_tag.h */; };
   4.216 -		646C40FC1D510CD800C63EFF /* BIT_STRING.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40A71D510CD700C63EFF /* BIT_STRING.c */; };
   4.217 -		646C40FD1D510CD800C63EFF /* BIT_STRING.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40A81D510CD700C63EFF /* BIT_STRING.h */; };
   4.218 -		646C40FE1D510CD800C63EFF /* BOOLEAN.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40A91D510CD700C63EFF /* BOOLEAN.c */; };
   4.219 -		646C40FF1D510CD800C63EFF /* BOOLEAN.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40AA1D510CD700C63EFF /* BOOLEAN.h */; };
   4.220 -		646C41001D510CD800C63EFF /* constr_CHOICE.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40AB1D510CD700C63EFF /* constr_CHOICE.c */; };
   4.221 -		646C41011D510CD800C63EFF /* constr_CHOICE.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40AC1D510CD700C63EFF /* constr_CHOICE.h */; };
   4.222 -		646C41021D510CD800C63EFF /* constr_SEQUENCE_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40AD1D510CD700C63EFF /* constr_SEQUENCE_OF.c */; };
   4.223 -		646C41031D510CD800C63EFF /* constr_SEQUENCE_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40AE1D510CD700C63EFF /* constr_SEQUENCE_OF.h */; };
   4.224 -		646C41041D510CD800C63EFF /* constr_SEQUENCE.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40AF1D510CD700C63EFF /* constr_SEQUENCE.c */; };
   4.225 -		646C41051D510CD800C63EFF /* constr_SEQUENCE.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40B01D510CD700C63EFF /* constr_SEQUENCE.h */; };
   4.226 -		646C41061D510CD800C63EFF /* constr_SET_OF.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40B11D510CD700C63EFF /* constr_SET_OF.c */; };
   4.227 -		646C41071D510CD800C63EFF /* constr_SET_OF.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40B21D510CD700C63EFF /* constr_SET_OF.h */; };
   4.228 -		646C41081D510CD800C63EFF /* constr_TYPE.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40B31D510CD700C63EFF /* constr_TYPE.c */; };
   4.229 -		646C41091D510CD800C63EFF /* constr_TYPE.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40B41D510CD700C63EFF /* constr_TYPE.h */; };
   4.230 -		646C410A1D510CD800C63EFF /* constraints.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40B51D510CD700C63EFF /* constraints.c */; };
   4.231 -		646C410B1D510CD800C63EFF /* constraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40B61D510CD700C63EFF /* constraints.h */; };
   4.232 -		646C410C1D510CD800C63EFF /* der_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40B71D510CD700C63EFF /* der_encoder.c */; };
   4.233 -		646C410D1D510CD800C63EFF /* der_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40B81D510CD700C63EFF /* der_encoder.h */; };
   4.234 -		646C41101D510CD800C63EFF /* GroupKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40BB1D510CD700C63EFF /* GroupKeys.c */; };
   4.235 -		646C41111D510CD800C63EFF /* GroupKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40BC1D510CD700C63EFF /* GroupKeys.h */; };
   4.236 -		646C41141D510CD800C63EFF /* Hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40BF1D510CD700C63EFF /* Hash.c */; };
   4.237 -		646C41151D510CD800C63EFF /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40C01D510CD700C63EFF /* Hash.h */; };
   4.238 -		646C41181D510CD800C63EFF /* Hex.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40C31D510CD700C63EFF /* Hex.c */; };
   4.239 -		646C41191D510CD800C63EFF /* Hex.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40C41D510CD700C63EFF /* Hex.h */; };
   4.240 -		646C411A1D510CD800C63EFF /* Identity.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40C51D510CD700C63EFF /* Identity.c */; };
   4.241 -		646C411B1D510CD800C63EFF /* Identity.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40C61D510CD700C63EFF /* Identity.h */; };
   4.242 -		646C411C1D510CD800C63EFF /* IdentityList.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40C71D510CD700C63EFF /* IdentityList.c */; };
   4.243 -		646C411D1D510CD800C63EFF /* IdentityList.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40C81D510CD800C63EFF /* IdentityList.h */; };
   4.244 -		646C411E1D510CD800C63EFF /* INTEGER.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40C91D510CD800C63EFF /* INTEGER.c */; };
   4.245 -		646C411F1D510CD800C63EFF /* INTEGER.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40CA1D510CD800C63EFF /* INTEGER.h */; };
   4.246 -		646C41201D510CD800C63EFF /* ISO639-1.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40CB1D510CD800C63EFF /* ISO639-1.c */; };
   4.247 -		646C41211D510CD800C63EFF /* ISO639-1.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40CC1D510CD800C63EFF /* ISO639-1.h */; };
   4.248 -		646C41221D510CD800C63EFF /* NativeEnumerated.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40CD1D510CD800C63EFF /* NativeEnumerated.c */; };
   4.249 -		646C41231D510CD800C63EFF /* NativeEnumerated.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40CE1D510CD800C63EFF /* NativeEnumerated.h */; };
   4.250 -		646C41241D510CD800C63EFF /* NativeInteger.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40CF1D510CD800C63EFF /* NativeInteger.c */; };
   4.251 -		646C41251D510CD800C63EFF /* NativeInteger.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40D01D510CD800C63EFF /* NativeInteger.h */; };
   4.252 -		646C41261D510CD800C63EFF /* OCTET_STRING.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40D11D510CD800C63EFF /* OCTET_STRING.c */; };
   4.253 -		646C41271D510CD800C63EFF /* OCTET_STRING.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40D21D510CD800C63EFF /* OCTET_STRING.h */; };
   4.254 -		646C41281D510CD800C63EFF /* per_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40D31D510CD800C63EFF /* per_decoder.c */; };
   4.255 -		646C41291D510CD800C63EFF /* per_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40D41D510CD800C63EFF /* per_decoder.h */; };
   4.256 -		646C412A1D510CD800C63EFF /* per_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40D51D510CD800C63EFF /* per_encoder.c */; };
   4.257 -		646C412B1D510CD800C63EFF /* per_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40D61D510CD800C63EFF /* per_encoder.h */; };
   4.258 -		646C412C1D510CD800C63EFF /* per_opentype.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40D71D510CD800C63EFF /* per_opentype.c */; };
   4.259 -		646C412D1D510CD800C63EFF /* per_opentype.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40D81D510CD800C63EFF /* per_opentype.h */; };
   4.260 -		646C412E1D510CD800C63EFF /* per_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40D91D510CD800C63EFF /* per_support.c */; };
   4.261 -		646C412F1D510CD800C63EFF /* per_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40DA1D510CD800C63EFF /* per_support.h */; };
   4.262 -		646C41301D510CD800C63EFF /* PrintableString.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40DB1D510CD800C63EFF /* PrintableString.c */; };
   4.263 -		646C41311D510CD800C63EFF /* PrintableString.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40DC1D510CD800C63EFF /* PrintableString.h */; };
   4.264 -		646C41341D510CD800C63EFF /* UTF8String.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E01D510CD800C63EFF /* UTF8String.c */; };
   4.265 -		646C41351D510CD800C63EFF /* UTF8String.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40E11D510CD800C63EFF /* UTF8String.h */; };
   4.266 -		646C41361D510CD800C63EFF /* Version.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E21D510CD800C63EFF /* Version.c */; };
   4.267 -		646C41371D510CD800C63EFF /* Version.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40E31D510CD800C63EFF /* Version.h */; };
   4.268 -		646C41381D510CD800C63EFF /* xer_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E41D510CD800C63EFF /* xer_decoder.c */; };
   4.269 -		646C41391D510CD800C63EFF /* xer_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40E51D510CD800C63EFF /* xer_decoder.h */; };
   4.270 -		646C413A1D510CD800C63EFF /* xer_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E61D510CD800C63EFF /* xer_encoder.c */; };
   4.271 -		646C413B1D510CD800C63EFF /* xer_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40E71D510CD800C63EFF /* xer_encoder.h */; };
   4.272 -		646C413C1D510CD800C63EFF /* xer_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E81D510CD800C63EFF /* xer_support.c */; };
   4.273 -		646C413D1D510CD800C63EFF /* xer_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40E91D510CD800C63EFF /* xer_support.h */; };
   4.274 -		646C41451D510D2C00C63EFF /* sync_actions.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C413E1D510D2C00C63EFF /* sync_actions.c */; };
   4.275  		646C414E1D510D8800C63EFF /* baseprotocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C414C1D510D8800C63EFF /* baseprotocol.c */; };
   4.276  		646C414F1D510D8800C63EFF /* baseprotocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C414D1D510D8800C63EFF /* baseprotocol.h */; };
   4.277 -		649DE08B1B45C19100912F72 /* libcurl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649DE08A1B45C19100912F72 /* libcurl.a */; };
   4.278  		64A826781B455D0800EECAF0 /* bloblist.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8264C1B455D0800EECAF0 /* bloblist.c */; };
   4.279  		64A826791B455D0800EECAF0 /* cryptotech.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8264E1B455D0800EECAF0 /* cryptotech.c */; };
   4.280  		64A8267A1B455D0800EECAF0 /* email.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826511B455D0800EECAF0 /* email.c */; };
   4.281 @@ -154,7 +170,6 @@
   4.282  		64A8267F1B455D0800EECAF0 /* message.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8265B1B455D0800EECAF0 /* message.c */; };
   4.283  		64A826801B455D0800EECAF0 /* mime.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8265D1B455D0800EECAF0 /* mime.c */; };
   4.284  		64A826811B455D0800EECAF0 /* pEpEngine.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826601B455D0800EECAF0 /* pEpEngine.c */; };
   4.285 -		64A826821B455D0800EECAF0 /* pgp_netpgp.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826631B455D0800EECAF0 /* pgp_netpgp.c */; };
   4.286  		64A826831B455D0800EECAF0 /* platform_unix.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A826651B455D0800EECAF0 /* platform_unix.c */; };
   4.287  		64A826861B455D0800EECAF0 /* stringlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8266D1B455D0800EECAF0 /* stringlist.c */; };
   4.288  		64A826871B455D0800EECAF0 /* stringpair.c in Sources */ = {isa = PBXBuildFile; fileRef = 64A8266F1B455D0800EECAF0 /* stringpair.c */; };
   4.289 @@ -202,20 +217,6 @@
   4.290  			remoteGlobalIDString = C682E21815B315EF00BE9DA7;
   4.291  			remoteInfo = "libetpan ios";
   4.292  		};
   4.293 -		645922511B8BD32B00A5AF93 /* PBXContainerItemProxy */ = {
   4.294 -			isa = PBXContainerItemProxy;
   4.295 -			containerPortal = 64DA240C1B832EA0000BEE80 /* netpgp.xcodeproj */;
   4.296 -			proxyType = 2;
   4.297 -			remoteGlobalIDString = 64AA9C201B45686800D0F542;
   4.298 -			remoteInfo = netpgp;
   4.299 -		};
   4.300 -		645922531B8BD53F00A5AF93 /* PBXContainerItemProxy */ = {
   4.301 -			isa = PBXContainerItemProxy;
   4.302 -			containerPortal = 64DA240C1B832EA0000BEE80 /* netpgp.xcodeproj */;
   4.303 -			proxyType = 1;
   4.304 -			remoteGlobalIDString = 64AA9C1F1B45686800D0F542;
   4.305 -			remoteInfo = netpgp;
   4.306 -		};
   4.307  /* End PBXContainerItemProxy section */
   4.308  
   4.309  /* Begin PBXCopyFilesBuildPhase section */
   4.310 @@ -231,146 +232,164 @@
   4.311  /* End PBXCopyFilesBuildPhase section */
   4.312  
   4.313  /* Begin PBXFileReference section */
   4.314 -		1521CEE9225C9AED00FD2AA2 /* CommitAcceptForGroup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptForGroup.c; path = ../asn.1/CommitAcceptForGroup.c; sourceTree = "<group>"; };
   4.315 -		1521CEEA225C9AEE00FD2AA2 /* PString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PString.h; path = ../asn.1/PString.h; sourceTree = "<group>"; };
   4.316 -		1521CEEB225C9AEE00FD2AA2 /* Rollback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Rollback.h; path = ../asn.1/Rollback.h; sourceTree = "<group>"; };
   4.317 -		1521CEEC225C9AEE00FD2AA2 /* CommitAcceptForGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptForGroup.h; path = ../asn.1/CommitAcceptForGroup.h; sourceTree = "<group>"; };
   4.318 -		1521CEEE225C9AEE00FD2AA2 /* CommitAccept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAccept.h; path = ../asn.1/CommitAccept.h; sourceTree = "<group>"; };
   4.319 -		1521CEF0225C9AEE00FD2AA2 /* pdu_collection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pdu_collection.c; path = ../asn.1/pdu_collection.c; sourceTree = "<group>"; };
   4.320 -		1521CEF1225C9AEE00FD2AA2 /* KeySync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeySync.h; path = ../asn.1/KeySync.h; sourceTree = "<group>"; };
   4.321 -		1521CEF2225C9AEE00FD2AA2 /* CommitReject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitReject.h; path = ../asn.1/CommitReject.h; sourceTree = "<group>"; };
   4.322 -		1521CEF3225C9AEE00FD2AA2 /* Sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sync.h; path = ../asn.1/Sync.h; sourceTree = "<group>"; };
   4.323 -		1521CEF4225C9AEE00FD2AA2 /* sync.asn1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = sync.asn1; path = ../asn.1/sync.asn1; sourceTree = "<group>"; };
   4.324 -		1521CEF5225C9AEF00FD2AA2 /* TID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TID.h; path = ../asn.1/TID.h; sourceTree = "<group>"; };
   4.325 +		154917F922B9266F0091B6D6 /* libnettle.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libnettle.a; path = ../../sequoia4ios/build/lib/libnettle.a; sourceTree = "<group>"; };
   4.326 +		154917FA22B926700091B6D6 /* libsequoia_openpgp_ffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsequoia_openpgp_ffi.a; path = ../../sequoia4ios/build/lib/libsequoia_openpgp_ffi.a; sourceTree = "<group>"; };
   4.327 +		154917FB22B926700091B6D6 /* libhogweed.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhogweed.a; path = ../../sequoia4ios/build/lib/libhogweed.a; sourceTree = "<group>"; };
   4.328 +		154917FC22B926700091B6D6 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgmp.a; path = ../../sequoia4ios/build/lib/libgmp.a; sourceTree = "<group>"; };
   4.329 +		1549180D22B92EA20091B6D6 /* libiconv.2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.2.tbd; path = usr/lib/libiconv.2.tbd; sourceTree = SDKROOT; };
   4.330 +		1549181322B92EA50091B6D6 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
   4.331 +		1549189222B9401D0091B6D6 /* fsm_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fsm_common.h; path = ../src/fsm_common.h; sourceTree = "<group>"; };
   4.332 +		1549189322B9401E0091B6D6 /* status_to_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = status_to_string.h; path = ../src/status_to_string.h; sourceTree = "<group>"; };
   4.333 +		1549189622B9401E0091B6D6 /* KeySync_fsm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeySync_fsm.h; path = ../src/KeySync_fsm.h; sourceTree = "<group>"; };
   4.334 +		1549189722B9401E0091B6D6 /* KeySync_fsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = KeySync_fsm.c; path = ../src/KeySync_fsm.c; sourceTree = "<group>"; };
   4.335 +		1549189822B9401E0091B6D6 /* Sync_actions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_actions.c; path = ../src/Sync_actions.c; sourceTree = "<group>"; };
   4.336 +		1549189922B9401E0091B6D6 /* aux_mime_msg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = aux_mime_msg.h; path = ../src/aux_mime_msg.h; sourceTree = "<group>"; };
   4.337 +		1549189A22B9401E0091B6D6 /* Sync_impl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_impl.c; path = ../src/Sync_impl.c; sourceTree = "<group>"; };
   4.338 +		1549189C22B9401E0091B6D6 /* sync_codec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_codec.c; path = ../src/sync_codec.c; sourceTree = "<group>"; };
   4.339 +		1549189D22B9401F0091B6D6 /* Sync_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sync_event.h; path = ../src/Sync_event.h; sourceTree = "<group>"; };
   4.340 +		1549189E22B9401F0091B6D6 /* Sync_event.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_event.c; path = ../src/Sync_event.c; sourceTree = "<group>"; };
   4.341 +		154918A022B9401F0091B6D6 /* Sync_func.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_func.c; path = ../src/Sync_func.c; sourceTree = "<group>"; };
   4.342 +		154918A122B9401F0091B6D6 /* resource_id.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = resource_id.h; path = ../src/resource_id.h; sourceTree = "<group>"; };
   4.343 +		154918A222B9401F0091B6D6 /* aux_mime_msg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = aux_mime_msg.c; path = ../src/aux_mime_msg.c; sourceTree = "<group>"; };
   4.344 +		154918A322B9401F0091B6D6 /* openpgp_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = openpgp_compat.h; path = ../src/openpgp_compat.h; sourceTree = "<group>"; };
   4.345 +		154918A422B9401F0091B6D6 /* growing_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = growing_buf.h; path = ../src/growing_buf.h; sourceTree = "<group>"; };
   4.346 +		154918A622B9401F0091B6D6 /* sync_codec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sync_codec.h; path = ../src/sync_codec.h; sourceTree = "<group>"; };
   4.347 +		154918A722B940200091B6D6 /* Sync_func.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sync_func.h; path = ../src/Sync_func.h; sourceTree = "<group>"; };
   4.348 +		154918A922B940200091B6D6 /* Sync_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sync_impl.h; path = ../src/Sync_impl.h; sourceTree = "<group>"; };
   4.349 +		154918AA22B940200091B6D6 /* blacklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = blacklist.h; path = ../src/blacklist.h; sourceTree = "<group>"; };
   4.350 +		159EF42422B6D3E900149C0C /* pgp_sequoia.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pgp_sequoia.c; path = ../src/pgp_sequoia.c; sourceTree = "<group>"; };
   4.351 +		159EF42522B6D3E900149C0C /* pgp_sequoia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pgp_sequoia.h; path = ../src/pgp_sequoia.h; sourceTree = "<group>"; };
   4.352 +		159EF42622B6D3E900149C0C /* pgp_sequoia_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pgp_sequoia_internal.h; path = ../src/pgp_sequoia_internal.h; sourceTree = "<group>"; };
   4.353 +		15B0373F22B2B816002D664C /* ber_tlv_length.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ber_tlv_length.c; path = ../asn.1/ber_tlv_length.c; sourceTree = "<group>"; };
   4.354 +		15B0374022B2B817002D664C /* GroupKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupKeys.h; path = ../asn.1/GroupKeys.h; sourceTree = "<group>"; };
   4.355 +		15B0374122B2B817002D664C /* CommitAccept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAccept.c; path = ../asn.1/CommitAccept.c; sourceTree = "<group>"; };
   4.356 +		15B0374222B2B817002D664C /* Rollback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Rollback.h; path = ../asn.1/Rollback.h; sourceTree = "<group>"; };
   4.357 +		15B0374322B2B817002D664C /* NegotiationOpen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationOpen.c; path = ../asn.1/NegotiationOpen.c; sourceTree = "<group>"; };
   4.358 +		15B0374422B2B817002D664C /* constr_SEQUENCE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_SEQUENCE.c; path = ../asn.1/constr_SEQUENCE.c; sourceTree = "<group>"; };
   4.359 +		15B0374522B2B817002D664C /* UTF8String.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = UTF8String.c; path = ../asn.1/UTF8String.c; sourceTree = "<group>"; };
   4.360 +		15B0374622B2B817002D664C /* NegotiationRequest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationRequest.c; path = ../asn.1/NegotiationRequest.c; sourceTree = "<group>"; };
   4.361 +		15B0374722B2B817002D664C /* Identity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Identity.h; path = ../asn.1/Identity.h; sourceTree = "<group>"; };
   4.362 +		15B0374822B2B817002D664C /* Beacon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Beacon.c; path = ../asn.1/Beacon.c; sourceTree = "<group>"; };
   4.363 +		15B0374922B2B817002D664C /* PString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PString.h; path = ../asn.1/PString.h; sourceTree = "<group>"; };
   4.364 +		15B0374A22B2B817002D664C /* OCTET_STRING.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OCTET_STRING.c; path = ../asn.1/OCTET_STRING.c; sourceTree = "<group>"; };
   4.365 +		15B0374B22B2B817002D664C /* IdentityList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IdentityList.h; path = ../asn.1/IdentityList.h; sourceTree = "<group>"; };
   4.366 +		15B0374C22B2B818002D664C /* Sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync.c; path = ../asn.1/Sync.c; sourceTree = "<group>"; };
   4.367 +		15B0374D22B2B818002D664C /* NativeInteger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeInteger.h; path = ../asn.1/NativeInteger.h; sourceTree = "<group>"; };
   4.368 +		15B0374E22B2B818002D664C /* NativeEnumerated.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NativeEnumerated.c; path = ../asn.1/NativeEnumerated.c; sourceTree = "<group>"; };
   4.369 +		15B0374F22B2B818002D664C /* asn_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_system.h; path = ../asn.1/asn_system.h; sourceTree = "<group>"; };
   4.370 +		15B0375022B2B818002D664C /* der_encoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = der_encoder.c; path = ../asn.1/der_encoder.c; sourceTree = "<group>"; };
   4.371 +		15B0375122B2B818002D664C /* OwnKeysRequester.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeysRequester.c; path = ../asn.1/OwnKeysRequester.c; sourceTree = "<group>"; };
   4.372 +		15B0375222B2B818002D664C /* CommitAcceptOfferer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptOfferer.h; path = ../asn.1/CommitAcceptOfferer.h; sourceTree = "<group>"; };
   4.373 +		15B0375322B2B818002D664C /* ber_tlv_tag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ber_tlv_tag.c; path = ../asn.1/ber_tlv_tag.c; sourceTree = "<group>"; };
   4.374 +		15B0375422B2B818002D664C /* BOOLEAN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BOOLEAN.h; path = ../asn.1/BOOLEAN.h; sourceTree = "<group>"; };
   4.375 +		15B0375522B2B819002D664C /* per_opentype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = per_opentype.h; path = ../asn.1/per_opentype.h; sourceTree = "<group>"; };
   4.376 +		15B0375622B2B819002D664C /* Identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Identity.c; path = ../asn.1/Identity.c; sourceTree = "<group>"; };
   4.377 +		15B0375722B2B819002D664C /* asn_SEQUENCE_OF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = asn_SEQUENCE_OF.c; path = ../asn.1/asn_SEQUENCE_OF.c; sourceTree = "<group>"; };
   4.378 +		15B0375822B2B819002D664C /* constr_SEQUENCE_OF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_SEQUENCE_OF.c; path = ../asn.1/constr_SEQUENCE_OF.c; sourceTree = "<group>"; };
   4.379 +		15B0375922B2B819002D664C /* pdu_collection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pdu_collection.c; path = ../asn.1/pdu_collection.c; sourceTree = "<group>"; };
   4.380 +		15B0375A22B2B819002D664C /* Beacon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Beacon.h; path = ../asn.1/Beacon.h; sourceTree = "<group>"; };
   4.381 +		15B0375B22B2B819002D664C /* xer_support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xer_support.c; path = ../asn.1/xer_support.c; sourceTree = "<group>"; };
   4.382 +		15B0375C22B2B819002D664C /* per_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = per_decoder.c; path = ../asn.1/per_decoder.c; sourceTree = "<group>"; };
   4.383 +		15B0375D22B2B819002D664C /* ISO639-1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ISO639-1.h"; path = "../asn.1/ISO639-1.h"; sourceTree = "<group>"; };
   4.384 +		15B0375E22B2B81A002D664C /* xer_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xer_decoder.h; path = ../asn.1/xer_decoder.h; sourceTree = "<group>"; };
   4.385 +		15B0375F22B2B81A002D664C /* PrintableString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrintableString.h; path = ../asn.1/PrintableString.h; sourceTree = "<group>"; };
   4.386 +		15B0376022B2B81A002D664C /* ISO639-1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ISO639-1.c"; path = "../asn.1/ISO639-1.c"; sourceTree = "<group>"; };
   4.387 +		15B0376122B2B81A002D664C /* ber_tlv_tag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ber_tlv_tag.h; path = ../asn.1/ber_tlv_tag.h; sourceTree = "<group>"; };
   4.388 +		15B0376222B2B81A002D664C /* PString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PString.c; path = ../asn.1/PString.c; sourceTree = "<group>"; };
   4.389 +		15B0376322B2B81A002D664C /* Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hash.h; path = ../asn.1/Hash.h; sourceTree = "<group>"; };
   4.390 +		15B0376422B2B81A002D664C /* NativeEnumerated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeEnumerated.h; path = ../asn.1/NativeEnumerated.h; sourceTree = "<group>"; };
   4.391 +		15B0376522B2B81A002D664C /* constr_TYPE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_TYPE.h; path = ../asn.1/constr_TYPE.h; sourceTree = "<group>"; };
   4.392 +		15B0376622B2B81B002D664C /* per_encoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = per_encoder.c; path = ../asn.1/per_encoder.c; sourceTree = "<group>"; };
   4.393 +		15B0376722B2B81B002D664C /* CommitAcceptRequester.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptRequester.c; path = ../asn.1/CommitAcceptRequester.c; sourceTree = "<group>"; };
   4.394 +		15B0376822B2B81B002D664C /* CommitReject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitReject.h; path = ../asn.1/CommitReject.h; sourceTree = "<group>"; };
   4.395 +		15B0376922B2B81B002D664C /* NegotiationRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NegotiationRequest.h; path = ../asn.1/NegotiationRequest.h; sourceTree = "<group>"; };
   4.396 +		15B0376A22B2B81B002D664C /* TID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TID.h; path = ../asn.1/TID.h; sourceTree = "<group>"; };
   4.397 +		15B0376B22B2B81B002D664C /* KeySync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeySync.h; path = ../asn.1/KeySync.h; sourceTree = "<group>"; };
   4.398 +		15B0376C22B2B81B002D664C /* UTF8String.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UTF8String.h; path = ../asn.1/UTF8String.h; sourceTree = "<group>"; };
   4.399 +		15B0376D22B2B81C002D664C /* Version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Version.h; path = ../asn.1/Version.h; sourceTree = "<group>"; };
   4.400 +		15B0376E22B2B81C002D664C /* xer_encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xer_encoder.h; path = ../asn.1/xer_encoder.h; sourceTree = "<group>"; };
   4.401 +		15B0376F22B2B81C002D664C /* asn_SET_OF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_SET_OF.h; path = ../asn.1/asn_SET_OF.h; sourceTree = "<group>"; };
   4.402 +		15B0377022B2B81C002D664C /* asn_codecs_prim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_codecs_prim.h; path = ../asn.1/asn_codecs_prim.h; sourceTree = "<group>"; };
   4.403 +		15B0377122B2B81C002D664C /* constraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constraints.h; path = ../asn.1/constraints.h; sourceTree = "<group>"; };
   4.404 +		15B0377222B2B81C002D664C /* Rollback.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Rollback.c; path = ../asn.1/Rollback.c; sourceTree = "<group>"; };
   4.405 +		15B0377322B2B81C002D664C /* KeySync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = KeySync.c; path = ../asn.1/KeySync.c; sourceTree = "<group>"; };
   4.406 +		15B0377422B2B81C002D664C /* IdentityList.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IdentityList.c; path = ../asn.1/IdentityList.c; sourceTree = "<group>"; };
   4.407 +		15B0377522B2B81D002D664C /* TID.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = TID.c; path = ../asn.1/TID.c; sourceTree = "<group>"; };
   4.408 +		15B0377622B2B81D002D664C /* GroupTrustThisKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupTrustThisKey.c; path = ../asn.1/GroupTrustThisKey.c; sourceTree = "<group>"; };
   4.409 +		15B0377722B2B81D002D664C /* per_encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = per_encoder.h; path = ../asn.1/per_encoder.h; sourceTree = "<group>"; };
   4.410 +		15B0377822B2B81D002D664C /* GroupKeys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupKeys.c; path = ../asn.1/GroupKeys.c; sourceTree = "<group>"; };
   4.411 +		15B0377922B2B81D002D664C /* xer_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xer_decoder.c; path = ../asn.1/xer_decoder.c; sourceTree = "<group>"; };
   4.412 +		15B0377A22B2B81D002D664C /* constr_SEQUENCE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_SEQUENCE.h; path = ../asn.1/constr_SEQUENCE.h; sourceTree = "<group>"; };
   4.413 +		15B0377B22B2B81D002D664C /* constr_CHOICE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_CHOICE.h; path = ../asn.1/constr_CHOICE.h; sourceTree = "<group>"; };
   4.414 +		15B0377C22B2B81D002D664C /* GroupTrustThisKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupTrustThisKey.h; path = ../asn.1/GroupTrustThisKey.h; sourceTree = "<group>"; };
   4.415 +		15B0377D22B2B81D002D664C /* constr_TYPE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_TYPE.c; path = ../asn.1/constr_TYPE.c; sourceTree = "<group>"; };
   4.416 +		15B0377E22B2B81D002D664C /* CommitAcceptOfferer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptOfferer.c; path = ../asn.1/CommitAcceptOfferer.c; sourceTree = "<group>"; };
   4.417 +		15B0377F22B2B81E002D664C /* BIT_STRING.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = BIT_STRING.c; path = ../asn.1/BIT_STRING.c; sourceTree = "<group>"; };
   4.418 +		15B0378022B2B81E002D664C /* constr_SET_OF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_SET_OF.c; path = ../asn.1/constr_SET_OF.c; sourceTree = "<group>"; };
   4.419 +		15B0378122B2B81E002D664C /* constraints.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constraints.c; path = ../asn.1/constraints.c; sourceTree = "<group>"; };
   4.420 +		15B0378222B2B81E002D664C /* BIT_STRING.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BIT_STRING.h; path = ../asn.1/BIT_STRING.h; sourceTree = "<group>"; };
   4.421 +		15B0378322B2B81E002D664C /* der_encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = der_encoder.h; path = ../asn.1/der_encoder.h; sourceTree = "<group>"; };
   4.422 +		15B0378422B2B81E002D664C /* ber_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ber_decoder.h; path = ../asn.1/ber_decoder.h; sourceTree = "<group>"; };
   4.423 +		15B0378522B2B81E002D664C /* NegotiationOpen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NegotiationOpen.h; path = ../asn.1/NegotiationOpen.h; sourceTree = "<group>"; };
   4.424 +		15B0378622B2B81E002D664C /* OCTET_STRING.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OCTET_STRING.h; path = ../asn.1/OCTET_STRING.h; sourceTree = "<group>"; };
   4.425 +		15B0378722B2B81E002D664C /* constr_SEQUENCE_OF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_SEQUENCE_OF.h; path = ../asn.1/constr_SEQUENCE_OF.h; sourceTree = "<group>"; };
   4.426 +		15B0378822B2B81F002D664C /* CommitAccept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAccept.h; path = ../asn.1/CommitAccept.h; sourceTree = "<group>"; };
   4.427 +		15B0378922B2B81F002D664C /* ber_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ber_decoder.c; path = ../asn.1/ber_decoder.c; sourceTree = "<group>"; };
   4.428 +		15B0378A22B2B81F002D664C /* INTEGER.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = INTEGER.c; path = ../asn.1/INTEGER.c; sourceTree = "<group>"; };
   4.429 +		15B0378B22B2B81F002D664C /* Version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Version.c; path = ../asn.1/Version.c; sourceTree = "<group>"; };
   4.430 +		15B0378C22B2B81F002D664C /* per_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = per_decoder.h; path = ../asn.1/per_decoder.h; sourceTree = "<group>"; };
   4.431 +		15B0378D22B2B81F002D664C /* OwnKeysOfferer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeysOfferer.c; path = ../asn.1/OwnKeysOfferer.c; sourceTree = "<group>"; };
   4.432 +		15B0378E22B2B81F002D664C /* per_support.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = per_support.h; path = ../asn.1/per_support.h; sourceTree = "<group>"; };
   4.433 +		15B0378F22B2B81F002D664C /* INTEGER.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INTEGER.h; path = ../asn.1/INTEGER.h; sourceTree = "<group>"; };
   4.434 +		15B0379022B2B81F002D664C /* Hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Hash.c; path = ../asn.1/Hash.c; sourceTree = "<group>"; };
   4.435 +		15B0379122B2B820002D664C /* Hex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Hex.c; path = ../asn.1/Hex.c; sourceTree = "<group>"; };
   4.436 +		15B0379222B2B820002D664C /* Hex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hex.h; path = ../asn.1/Hex.h; sourceTree = "<group>"; };
   4.437 +		15B0379322B2B820002D664C /* xer_encoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xer_encoder.c; path = ../asn.1/xer_encoder.c; sourceTree = "<group>"; };
   4.438 +		15B0379422B2B820002D664C /* per_opentype.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = per_opentype.c; path = ../asn.1/per_opentype.c; sourceTree = "<group>"; };
   4.439 +		15B0379522B2B820002D664C /* xer_support.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xer_support.h; path = ../asn.1/xer_support.h; sourceTree = "<group>"; };
   4.440 +		15B0379622B2B820002D664C /* asn_SET_OF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = asn_SET_OF.c; path = ../asn.1/asn_SET_OF.c; sourceTree = "<group>"; };
   4.441 +		15B0379722B2B820002D664C /* ber_tlv_length.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ber_tlv_length.h; path = ../asn.1/ber_tlv_length.h; sourceTree = "<group>"; };
   4.442 +		15B0379822B2B820002D664C /* OwnKeysRequester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeysRequester.h; path = ../asn.1/OwnKeysRequester.h; sourceTree = "<group>"; };
   4.443 +		15B0379922B2B821002D664C /* constr_SET_OF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_SET_OF.h; path = ../asn.1/constr_SET_OF.h; sourceTree = "<group>"; };
   4.444 +		15B0379A22B2B821002D664C /* asn_codecs_prim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = asn_codecs_prim.c; path = ../asn.1/asn_codecs_prim.c; sourceTree = "<group>"; };
   4.445 +		15B0379B22B2B821002D664C /* CommitAcceptForGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptForGroup.h; path = ../asn.1/CommitAcceptForGroup.h; sourceTree = "<group>"; };
   4.446 +		15B0379C22B2B821002D664C /* constr_CHOICE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_CHOICE.c; path = ../asn.1/constr_CHOICE.c; sourceTree = "<group>"; };
   4.447 +		15B0379D22B2B821002D664C /* asn_codecs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_codecs.h; path = ../asn.1/asn_codecs.h; sourceTree = "<group>"; };
   4.448 +		15B0379E22B2B821002D664C /* per_support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = per_support.c; path = ../asn.1/per_support.c; sourceTree = "<group>"; };
   4.449 +		15B0379F22B2B821002D664C /* asn_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_internal.h; path = ../asn.1/asn_internal.h; sourceTree = "<group>"; };
   4.450 +		15B037A022B2B821002D664C /* NativeInteger.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NativeInteger.c; path = ../asn.1/NativeInteger.c; sourceTree = "<group>"; };
   4.451 +		15B037A122B2B821002D664C /* BOOLEAN.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = BOOLEAN.c; path = ../asn.1/BOOLEAN.c; sourceTree = "<group>"; };
   4.452 +		15B037A222B2B822002D664C /* CommitReject.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitReject.c; path = ../asn.1/CommitReject.c; sourceTree = "<group>"; };
   4.453 +		15B037A322B2B822002D664C /* PrintableString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PrintableString.c; path = ../asn.1/PrintableString.c; sourceTree = "<group>"; };
   4.454 +		15B037A422B2B822002D664C /* Sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sync.h; path = ../asn.1/Sync.h; sourceTree = "<group>"; };
   4.455 +		15B037A522B2B822002D664C /* CommitAcceptRequester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptRequester.h; path = ../asn.1/CommitAcceptRequester.h; sourceTree = "<group>"; };
   4.456 +		15B037A622B2B822002D664C /* CommitAcceptForGroup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptForGroup.c; path = ../asn.1/CommitAcceptForGroup.c; sourceTree = "<group>"; };
   4.457 +		15B037A722B2B822002D664C /* OwnKeysOfferer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeysOfferer.h; path = ../asn.1/OwnKeysOfferer.h; sourceTree = "<group>"; };
   4.458 +		15B037A822B2B822002D664C /* asn_application.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_application.h; path = ../asn.1/asn_application.h; sourceTree = "<group>"; };
   4.459 +		15B037A922B2B822002D664C /* asn_SEQUENCE_OF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_SEQUENCE_OF.h; path = ../asn.1/asn_SEQUENCE_OF.h; sourceTree = "<group>"; };
   4.460  		430BCC462015EE800077E998 /* pEp_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pEp_string.h; path = ../src/pEp_string.h; sourceTree = "<group>"; };
   4.461  		430BCC472015EE800077E998 /* pEp_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pEp_string.c; path = ../src/pEp_string.c; sourceTree = "<group>"; };
   4.462  		430D258A1C9ED75A00B94535 /* blacklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = blacklist.c; path = ../src/blacklist.c; sourceTree = "<group>"; };
   4.463 -		431F04862273223600CCE960 /* CommitAcceptSecond.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptSecond.h; path = ../asn.1/CommitAcceptSecond.h; sourceTree = "<group>"; };
   4.464 -		431F048B2273223600CCE960 /* CommitAcceptSecond.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptSecond.c; path = ../asn.1/CommitAcceptSecond.c; sourceTree = "<group>"; };
   4.465 -		431F048E2273227900CCE960 /* OwnKeysFirst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeysFirst.h; path = ../asn.1/OwnKeysFirst.h; sourceTree = "<group>"; };
   4.466 -		431F048F2273227900CCE960 /* OwnKeysFirst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeysFirst.c; path = ../asn.1/OwnKeysFirst.c; sourceTree = "<group>"; };
   4.467 -		431F0492227322EF00CCE960 /* CommitAcceptFirst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptFirst.h; path = ../asn.1/CommitAcceptFirst.h; sourceTree = "<group>"; };
   4.468 -		431F0493227322EF00CCE960 /* CommitAcceptFirst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptFirst.c; path = ../asn.1/CommitAcceptFirst.c; sourceTree = "<group>"; };
   4.469 -		431F049C2273235300CCE960 /* GroupTrustThisKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupTrustThisKey.h; path = ../asn.1/GroupTrustThisKey.h; sourceTree = "<group>"; };
   4.470 -		431F04A12273235300CCE960 /* GroupTrustThisKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupTrustThisKey.c; path = ../asn.1/GroupTrustThisKey.c; sourceTree = "<group>"; };
   4.471 -		431F04A4227323A400CCE960 /* OwnKeysSecond.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeysSecond.h; path = ../asn.1/OwnKeysSecond.h; sourceTree = "<group>"; };
   4.472 -		431F04A5227323A400CCE960 /* OwnKeysSecond.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeysSecond.c; path = ../asn.1/OwnKeysSecond.c; sourceTree = "<group>"; };
   4.473 -		431F04A8227323EE00CCE960 /* OwnKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeys.h; path = ../asn.1/OwnKeys.h; sourceTree = "<group>"; };
   4.474 -		431F04A9227323EE00CCE960 /* OwnKeys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeys.c; path = ../asn.1/OwnKeys.c; sourceTree = "<group>"; };
   4.475  		431F04B222733A7E00CCE960 /* key_reset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = key_reset.h; path = ../src/key_reset.h; sourceTree = "<group>"; };
   4.476  		4337082D203C075A004E6547 /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqlite3.c; path = ../src/sqlite3.c; sourceTree = "<group>"; };
   4.477  		43370832203C075A004E6547 /* sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqlite3.h; path = ../src/sqlite3.h; sourceTree = "<group>"; };
   4.478 -		4354FF641D6EDF300033069C /* sync_impl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_impl.c; path = ../src/sync_impl.c; sourceTree = "<group>"; };
   4.479  		438C43962167582400C7425B /* sync_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sync_api.h; path = ../src/sync_api.h; sourceTree = "<group>"; };
   4.480  		438C43AF2167752C00C7425B /* labeled_int_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = labeled_int_list.h; path = ../src/labeled_int_list.h; sourceTree = "<group>"; };
   4.481  		438C43B42167752C00C7425B /* labeled_int_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = labeled_int_list.c; path = ../src/labeled_int_list.c; sourceTree = "<group>"; };
   4.482 -		43CC349C2276D31A002F77AF /* NegotiationRequest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationRequest.c; path = ../asn.1/NegotiationRequest.c; sourceTree = "<group>"; };
   4.483 -		43CC349D2276D31A002F77AF /* NegotiationRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NegotiationRequest.h; path = ../asn.1/NegotiationRequest.h; sourceTree = "<group>"; };
   4.484 -		43CC34A02276D34B002F77AF /* NegotiationOpen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationOpen.c; path = ../asn.1/NegotiationOpen.c; sourceTree = "<group>"; };
   4.485 -		43CC34A12276D34C002F77AF /* NegotiationOpen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NegotiationOpen.h; path = ../asn.1/NegotiationOpen.h; sourceTree = "<group>"; };
   4.486  		43D47A8A225CC60600E97C5B /* pEpTrustWords-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "pEpTrustWords-Info.plist"; path = "/Users/dirk/projects/pEp/pEpEngine/build-mac/pEpTrustWords-Info.plist"; sourceTree = "<absolute>"; };
   4.487  		43F6921C1F164A47009418F5 /* resource_id.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = resource_id.c; path = ../src/resource_id.c; sourceTree = "<group>"; };
   4.488 -		43F73BEB2166269200AB4524 /* PString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PString.c; path = ../asn.1/PString.c; sourceTree = "<group>"; };
   4.489 -		43F73BF1216626E100AB4524 /* Sync_func.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_func.c; path = ../src/Sync_func.c; sourceTree = "<group>"; };
   4.490 -		43F73BF5216627CB00AB4524 /* CommitAccept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAccept.c; path = ../asn.1/CommitAccept.c; sourceTree = "<group>"; };
   4.491 -		43F73BF6216627CC00AB4524 /* TID.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = TID.c; path = ../asn.1/TID.c; sourceTree = "<group>"; };
   4.492 -		43F73BF7216627CC00AB4524 /* KeySync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = KeySync.c; path = ../asn.1/KeySync.c; sourceTree = "<group>"; };
   4.493 -		43F73BF9216627CC00AB4524 /* Rollback.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Rollback.c; path = ../asn.1/Rollback.c; sourceTree = "<group>"; };
   4.494 -		43F73BFB216627CC00AB4524 /* CommitReject.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitReject.c; path = ../asn.1/CommitReject.c; sourceTree = "<group>"; };
   4.495  		43F73C032166282C00AB4524 /* openpgp_compat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = openpgp_compat.c; path = ../src/openpgp_compat.c; sourceTree = "<group>"; };
   4.496 -		43F73C042166282C00AB4524 /* Sync_event.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_event.c; path = ../src/Sync_event.c; sourceTree = "<group>"; };
   4.497  		43F73C052166282C00AB4524 /* key_reset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = key_reset.c; path = ../src/key_reset.c; sourceTree = "<group>"; };
   4.498 -		43F73C062166282C00AB4524 /* sync_codec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_codec.c; path = ../src/sync_codec.c; sourceTree = "<group>"; };
   4.499 -		43F73C072166282C00AB4524 /* KeySync_fsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = KeySync_fsm.c; path = ../src/KeySync_fsm.c; sourceTree = "<group>"; };
   4.500  		43F73C092166282C00AB4524 /* sync_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_api.c; path = ../src/sync_api.c; sourceTree = "<group>"; };
   4.501  		43F73C0A2166282C00AB4524 /* growing_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = growing_buf.c; path = ../src/growing_buf.c; sourceTree = "<group>"; };
   4.502 -		43F73C13216628CA00AB4524 /* Sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync.c; path = ../asn.1/Sync.c; sourceTree = "<group>"; };
   4.503  		644297BF1BE11C65002BC73B /* pEpTrustWords.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = pEpTrustWords.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
   4.504  		644297C11BE11C65002BC73B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
   4.505  		646788871CEB3D120001F54C /* map_asn1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = map_asn1.c; path = ../src/map_asn1.c; sourceTree = "<group>"; };
   4.506  		646788881CEB3D120001F54C /* map_asn1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = map_asn1.h; path = ../src/map_asn1.h; sourceTree = "<group>"; };
   4.507 -		646C40951D510CD700C63EFF /* asn_application.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_application.h; path = ../asn.1/asn_application.h; sourceTree = "<group>"; };
   4.508 -		646C40961D510CD700C63EFF /* asn_codecs_prim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = asn_codecs_prim.c; path = ../asn.1/asn_codecs_prim.c; sourceTree = "<group>"; };
   4.509 -		646C40971D510CD700C63EFF /* asn_codecs_prim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_codecs_prim.h; path = ../asn.1/asn_codecs_prim.h; sourceTree = "<group>"; };
   4.510 -		646C40981D510CD700C63EFF /* asn_codecs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_codecs.h; path = ../asn.1/asn_codecs.h; sourceTree = "<group>"; };
   4.511 -		646C40991D510CD700C63EFF /* asn_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_internal.h; path = ../asn.1/asn_internal.h; sourceTree = "<group>"; };
   4.512 -		646C409A1D510CD700C63EFF /* asn_SEQUENCE_OF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = asn_SEQUENCE_OF.c; path = ../asn.1/asn_SEQUENCE_OF.c; sourceTree = "<group>"; };
   4.513 -		646C409B1D510CD700C63EFF /* asn_SEQUENCE_OF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_SEQUENCE_OF.h; path = ../asn.1/asn_SEQUENCE_OF.h; sourceTree = "<group>"; };
   4.514 -		646C409C1D510CD700C63EFF /* asn_SET_OF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = asn_SET_OF.c; path = ../asn.1/asn_SET_OF.c; sourceTree = "<group>"; };
   4.515 -		646C409D1D510CD700C63EFF /* asn_SET_OF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_SET_OF.h; path = ../asn.1/asn_SET_OF.h; sourceTree = "<group>"; };
   4.516 -		646C409E1D510CD700C63EFF /* asn_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn_system.h; path = ../asn.1/asn_system.h; sourceTree = "<group>"; };
   4.517 -		646C409F1D510CD700C63EFF /* Beacon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Beacon.c; path = ../asn.1/Beacon.c; sourceTree = "<group>"; };
   4.518 -		646C40A01D510CD700C63EFF /* Beacon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Beacon.h; path = ../asn.1/Beacon.h; sourceTree = "<group>"; };
   4.519 -		646C40A11D510CD700C63EFF /* ber_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ber_decoder.c; path = ../asn.1/ber_decoder.c; sourceTree = "<group>"; };
   4.520 -		646C40A21D510CD700C63EFF /* ber_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ber_decoder.h; path = ../asn.1/ber_decoder.h; sourceTree = "<group>"; };
   4.521 -		646C40A31D510CD700C63EFF /* ber_tlv_length.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ber_tlv_length.c; path = ../asn.1/ber_tlv_length.c; sourceTree = "<group>"; };
   4.522 -		646C40A41D510CD700C63EFF /* ber_tlv_length.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ber_tlv_length.h; path = ../asn.1/ber_tlv_length.h; sourceTree = "<group>"; };
   4.523 -		646C40A51D510CD700C63EFF /* ber_tlv_tag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ber_tlv_tag.c; path = ../asn.1/ber_tlv_tag.c; sourceTree = "<group>"; };
   4.524 -		646C40A61D510CD700C63EFF /* ber_tlv_tag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ber_tlv_tag.h; path = ../asn.1/ber_tlv_tag.h; sourceTree = "<group>"; };
   4.525 -		646C40A71D510CD700C63EFF /* BIT_STRING.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = BIT_STRING.c; path = ../asn.1/BIT_STRING.c; sourceTree = "<group>"; };
   4.526 -		646C40A81D510CD700C63EFF /* BIT_STRING.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BIT_STRING.h; path = ../asn.1/BIT_STRING.h; sourceTree = "<group>"; };
   4.527 -		646C40A91D510CD700C63EFF /* BOOLEAN.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = BOOLEAN.c; path = ../asn.1/BOOLEAN.c; sourceTree = "<group>"; };
   4.528 -		646C40AA1D510CD700C63EFF /* BOOLEAN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BOOLEAN.h; path = ../asn.1/BOOLEAN.h; sourceTree = "<group>"; };
   4.529 -		646C40AB1D510CD700C63EFF /* constr_CHOICE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_CHOICE.c; path = ../asn.1/constr_CHOICE.c; sourceTree = "<group>"; };
   4.530 -		646C40AC1D510CD700C63EFF /* constr_CHOICE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_CHOICE.h; path = ../asn.1/constr_CHOICE.h; sourceTree = "<group>"; };
   4.531 -		646C40AD1D510CD700C63EFF /* constr_SEQUENCE_OF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_SEQUENCE_OF.c; path = ../asn.1/constr_SEQUENCE_OF.c; sourceTree = "<group>"; };
   4.532 -		646C40AE1D510CD700C63EFF /* constr_SEQUENCE_OF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_SEQUENCE_OF.h; path = ../asn.1/constr_SEQUENCE_OF.h; sourceTree = "<group>"; };
   4.533 -		646C40AF1D510CD700C63EFF /* constr_SEQUENCE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_SEQUENCE.c; path = ../asn.1/constr_SEQUENCE.c; sourceTree = "<group>"; };
   4.534 -		646C40B01D510CD700C63EFF /* constr_SEQUENCE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_SEQUENCE.h; path = ../asn.1/constr_SEQUENCE.h; sourceTree = "<group>"; };
   4.535 -		646C40B11D510CD700C63EFF /* constr_SET_OF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_SET_OF.c; path = ../asn.1/constr_SET_OF.c; sourceTree = "<group>"; };
   4.536 -		646C40B21D510CD700C63EFF /* constr_SET_OF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_SET_OF.h; path = ../asn.1/constr_SET_OF.h; sourceTree = "<group>"; };
   4.537 -		646C40B31D510CD700C63EFF /* constr_TYPE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constr_TYPE.c; path = ../asn.1/constr_TYPE.c; sourceTree = "<group>"; };
   4.538 -		646C40B41D510CD700C63EFF /* constr_TYPE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constr_TYPE.h; path = ../asn.1/constr_TYPE.h; sourceTree = "<group>"; };
   4.539 -		646C40B51D510CD700C63EFF /* constraints.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = constraints.c; path = ../asn.1/constraints.c; sourceTree = "<group>"; };
   4.540 -		646C40B61D510CD700C63EFF /* constraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constraints.h; path = ../asn.1/constraints.h; sourceTree = "<group>"; };
   4.541 -		646C40B71D510CD700C63EFF /* der_encoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = der_encoder.c; path = ../asn.1/der_encoder.c; sourceTree = "<group>"; };
   4.542 -		646C40B81D510CD700C63EFF /* der_encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = der_encoder.h; path = ../asn.1/der_encoder.h; sourceTree = "<group>"; };
   4.543 -		646C40BB1D510CD700C63EFF /* GroupKeys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupKeys.c; path = ../asn.1/GroupKeys.c; sourceTree = "<group>"; };
   4.544 -		646C40BC1D510CD700C63EFF /* GroupKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupKeys.h; path = ../asn.1/GroupKeys.h; sourceTree = "<group>"; };
   4.545 -		646C40BF1D510CD700C63EFF /* Hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Hash.c; path = ../asn.1/Hash.c; sourceTree = "<group>"; };
   4.546 -		646C40C01D510CD700C63EFF /* Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hash.h; path = ../asn.1/Hash.h; sourceTree = "<group>"; };
   4.547 -		646C40C31D510CD700C63EFF /* Hex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Hex.c; path = ../asn.1/Hex.c; sourceTree = "<group>"; };
   4.548 -		646C40C41D510CD700C63EFF /* Hex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hex.h; path = ../asn.1/Hex.h; sourceTree = "<group>"; };
   4.549 -		646C40C51D510CD700C63EFF /* Identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Identity.c; path = ../asn.1/Identity.c; sourceTree = "<group>"; };
   4.550 -		646C40C61D510CD700C63EFF /* Identity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Identity.h; path = ../asn.1/Identity.h; sourceTree = "<group>"; };
   4.551 -		646C40C71D510CD700C63EFF /* IdentityList.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IdentityList.c; path = ../asn.1/IdentityList.c; sourceTree = "<group>"; };
   4.552 -		646C40C81D510CD800C63EFF /* IdentityList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IdentityList.h; path = ../asn.1/IdentityList.h; sourceTree = "<group>"; };
   4.553 -		646C40C91D510CD800C63EFF /* INTEGER.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = INTEGER.c; path = ../asn.1/INTEGER.c; sourceTree = "<group>"; };
   4.554 -		646C40CA1D510CD800C63EFF /* INTEGER.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INTEGER.h; path = ../asn.1/INTEGER.h; sourceTree = "<group>"; };
   4.555 -		646C40CB1D510CD800C63EFF /* ISO639-1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "ISO639-1.c"; path = "../asn.1/ISO639-1.c"; sourceTree = "<group>"; };
   4.556 -		646C40CC1D510CD800C63EFF /* ISO639-1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ISO639-1.h"; path = "../asn.1/ISO639-1.h"; sourceTree = "<group>"; };
   4.557 -		646C40CD1D510CD800C63EFF /* NativeEnumerated.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NativeEnumerated.c; path = ../asn.1/NativeEnumerated.c; sourceTree = "<group>"; };
   4.558 -		646C40CE1D510CD800C63EFF /* NativeEnumerated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeEnumerated.h; path = ../asn.1/NativeEnumerated.h; sourceTree = "<group>"; };
   4.559 -		646C40CF1D510CD800C63EFF /* NativeInteger.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NativeInteger.c; path = ../asn.1/NativeInteger.c; sourceTree = "<group>"; };
   4.560 -		646C40D01D510CD800C63EFF /* NativeInteger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeInteger.h; path = ../asn.1/NativeInteger.h; sourceTree = "<group>"; };
   4.561 -		646C40D11D510CD800C63EFF /* OCTET_STRING.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OCTET_STRING.c; path = ../asn.1/OCTET_STRING.c; sourceTree = "<group>"; };
   4.562 -		646C40D21D510CD800C63EFF /* OCTET_STRING.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OCTET_STRING.h; path = ../asn.1/OCTET_STRING.h; sourceTree = "<group>"; };
   4.563 -		646C40D31D510CD800C63EFF /* per_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = per_decoder.c; path = ../asn.1/per_decoder.c; sourceTree = "<group>"; };
   4.564 -		646C40D41D510CD800C63EFF /* per_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = per_decoder.h; path = ../asn.1/per_decoder.h; sourceTree = "<group>"; };
   4.565 -		646C40D51D510CD800C63EFF /* per_encoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = per_encoder.c; path = ../asn.1/per_encoder.c; sourceTree = "<group>"; };
   4.566 -		646C40D61D510CD800C63EFF /* per_encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = per_encoder.h; path = ../asn.1/per_encoder.h; sourceTree = "<group>"; };
   4.567 -		646C40D71D510CD800C63EFF /* per_opentype.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = per_opentype.c; path = ../asn.1/per_opentype.c; sourceTree = "<group>"; };
   4.568 -		646C40D81D510CD800C63EFF /* per_opentype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = per_opentype.h; path = ../asn.1/per_opentype.h; sourceTree = "<group>"; };
   4.569 -		646C40D91D510CD800C63EFF /* per_support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = per_support.c; path = ../asn.1/per_support.c; sourceTree = "<group>"; };
   4.570 -		646C40DA1D510CD800C63EFF /* per_support.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = per_support.h; path = ../asn.1/per_support.h; sourceTree = "<group>"; };
   4.571 -		646C40DB1D510CD800C63EFF /* PrintableString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PrintableString.c; path = ../asn.1/PrintableString.c; sourceTree = "<group>"; };
   4.572 -		646C40DC1D510CD800C63EFF /* PrintableString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrintableString.h; path = ../asn.1/PrintableString.h; sourceTree = "<group>"; };
   4.573 -		646C40E01D510CD800C63EFF /* UTF8String.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = UTF8String.c; path = ../asn.1/UTF8String.c; sourceTree = "<group>"; };
   4.574 -		646C40E11D510CD800C63EFF /* UTF8String.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UTF8String.h; path = ../asn.1/UTF8String.h; sourceTree = "<group>"; };
   4.575 -		646C40E21D510CD800C63EFF /* Version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Version.c; path = ../asn.1/Version.c; sourceTree = "<group>"; };
   4.576 -		646C40E31D510CD800C63EFF /* Version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Version.h; path = ../asn.1/Version.h; sourceTree = "<group>"; };
   4.577 -		646C40E41D510CD800C63EFF /* xer_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xer_decoder.c; path = ../asn.1/xer_decoder.c; sourceTree = "<group>"; };
   4.578 -		646C40E51D510CD800C63EFF /* xer_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xer_decoder.h; path = ../asn.1/xer_decoder.h; sourceTree = "<group>"; };
   4.579 -		646C40E61D510CD800C63EFF /* xer_encoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xer_encoder.c; path = ../asn.1/xer_encoder.c; sourceTree = "<group>"; };
   4.580 -		646C40E71D510CD800C63EFF /* xer_encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xer_encoder.h; path = ../asn.1/xer_encoder.h; sourceTree = "<group>"; };
   4.581 -		646C40E81D510CD800C63EFF /* xer_support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xer_support.c; path = ../asn.1/xer_support.c; sourceTree = "<group>"; };
   4.582 -		646C40E91D510CD800C63EFF /* xer_support.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xer_support.h; path = ../asn.1/xer_support.h; sourceTree = "<group>"; };
   4.583 -		646C413E1D510D2C00C63EFF /* sync_actions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_actions.c; path = ../src/sync_actions.c; sourceTree = "<group>"; };
   4.584  		646C414C1D510D8800C63EFF /* baseprotocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = baseprotocol.c; path = ../src/baseprotocol.c; sourceTree = "<group>"; };
   4.585  		646C414D1D510D8800C63EFF /* baseprotocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = baseprotocol.h; path = ../src/baseprotocol.h; sourceTree = "<group>"; };
   4.586  		64796A3F1B455AA5004B1C24 /* libpEpEngine.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpEpEngine.a; sourceTree = BUILT_PRODUCTS_DIR; };
   4.587  		64951A1B1BE0FCD800B10E71 /* system.db */ = {isa = PBXFileReference; lastKnownFileType = text; name = system.db; path = ../db/system.db; sourceTree = "<group>"; };
   4.588 -		649DE08A1B45C19100912F72 /* libcurl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libcurl.a; sourceTree = "<group>"; };
   4.589  		64A8264C1B455D0800EECAF0 /* bloblist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bloblist.c; path = ../src/bloblist.c; sourceTree = "<group>"; };
   4.590  		64A8264D1B455D0800EECAF0 /* bloblist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bloblist.h; path = ../src/bloblist.h; sourceTree = "<group>"; };
   4.591  		64A8264E1B455D0800EECAF0 /* cryptotech.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cryptotech.c; path = ../src/cryptotech.c; sourceTree = "<group>"; };
   4.592 @@ -393,9 +412,6 @@
   4.593  		64A8265F1B455D0800EECAF0 /* pEp_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pEp_internal.h; path = ../src/pEp_internal.h; sourceTree = "<group>"; };
   4.594  		64A826601B455D0800EECAF0 /* pEpEngine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pEpEngine.c; path = ../src/pEpEngine.c; sourceTree = "<group>"; };
   4.595  		64A826611B455D0800EECAF0 /* pEpEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pEpEngine.h; path = ../src/pEpEngine.h; sourceTree = "<group>"; };
   4.596 -		64A826621B455D0800EECAF0 /* pgp_netpgp_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pgp_netpgp_internal.h; path = ../src/pgp_netpgp_internal.h; sourceTree = "<group>"; };
   4.597 -		64A826631B455D0800EECAF0 /* pgp_netpgp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pgp_netpgp.c; path = ../src/pgp_netpgp.c; sourceTree = "<group>"; };
   4.598 -		64A826641B455D0800EECAF0 /* pgp_netpgp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pgp_netpgp.h; path = ../src/pgp_netpgp.h; sourceTree = "<group>"; };
   4.599  		64A826651B455D0800EECAF0 /* platform_unix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = platform_unix.c; path = ../src/platform_unix.c; sourceTree = "<group>"; };
   4.600  		64A826661B455D0800EECAF0 /* platform_unix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = platform_unix.h; path = ../src/platform_unix.h; sourceTree = "<group>"; };
   4.601  		64A826691B455D0800EECAF0 /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = platform.h; path = ../src/platform.h; sourceTree = "<group>"; };
   4.602 @@ -411,7 +427,6 @@
   4.603  		64A826751B455D0800EECAF0 /* transport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = transport.c; path = ../src/transport.c; sourceTree = "<group>"; };
   4.604  		64A826761B455D0800EECAF0 /* transport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = transport.h; path = ../src/transport.h; sourceTree = "<group>"; };
   4.605  		64A826771B455D0800EECAF0 /* wrappers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wrappers.h; path = ../src/wrappers.h; sourceTree = "<group>"; };
   4.606 -		64DA240C1B832EA0000BEE80 /* netpgp.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = netpgp.xcodeproj; path = "../../netpgp-et/netpgp-xcode/netpgp.xcodeproj"; sourceTree = "<group>"; };
   4.607  		64DA24121B832EBA000BEE80 /* libetpan.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libetpan.xcodeproj; path = "../../libetpan/build-mac/libetpan.xcodeproj"; sourceTree = "<group>"; };
   4.608  		C46EBAE7216E445F0042A6A3 /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = base64.c; path = ../src/base64.c; sourceTree = "<group>"; };
   4.609  		C46EBAEC216E445F0042A6A3 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = base64.h; path = ../src/base64.h; sourceTree = "<group>"; };
   4.610 @@ -422,6 +437,7 @@
   4.611  			isa = PBXFrameworksBuildPhase;
   4.612  			buildActionMask = 2147483647;
   4.613  			files = (
   4.614 +				1549181222B92EA20091B6D6 /* libiconv.2.tbd in Frameworks */,
   4.615  			);
   4.616  			runOnlyForDeploymentPostprocessing = 0;
   4.617  		};
   4.618 @@ -430,134 +446,145 @@
   4.619  			buildActionMask = 2147483647;
   4.620  			files = (
   4.621  				6400FB8B1B8CA1CF005221E3 /* libetpan-ios.a in Frameworks */,
   4.622 -				6400FB861B8CA1C6005221E3 /* libnetpgp.a in Frameworks */,
   4.623 -				649DE08B1B45C19100912F72 /* libcurl.a in Frameworks */,
   4.624 +				1549180022B926700091B6D6 /* libgmp.a in Frameworks */,
   4.625 +				154917FF22B926700091B6D6 /* libhogweed.a in Frameworks */,
   4.626 +				154917FE22B926700091B6D6 /* libsequoia_openpgp_ffi.a in Frameworks */,
   4.627 +				154917FD22B926700091B6D6 /* libnettle.a in Frameworks */,
   4.628  			);
   4.629  			runOnlyForDeploymentPostprocessing = 0;
   4.630  		};
   4.631  /* End PBXFrameworksBuildPhase section */
   4.632  
   4.633  /* Begin PBXGroup section */
   4.634 -		43D47A89225CC60600E97C5B /* Resources-iPad */ = {
   4.635 +		154917EB22B926080091B6D6 /* Frameworks */ = {
   4.636  			isa = PBXGroup;
   4.637  			children = (
   4.638 +				154917F422B926420091B6D6 /* sequoia4ios */,
   4.639  			);
   4.640 -			name = "Resources-iPad";
   4.641 +			name = Frameworks;
   4.642 +			sourceTree = "<group>";
   4.643 +		};
   4.644 +		154917F422B926420091B6D6 /* sequoia4ios */ = {
   4.645 +			isa = PBXGroup;
   4.646 +			children = (
   4.647 +				154917FC22B926700091B6D6 /* libgmp.a */,
   4.648 +				154917FB22B926700091B6D6 /* libhogweed.a */,
   4.649 +				154917F922B9266F0091B6D6 /* libnettle.a */,
   4.650 +				154917FA22B926700091B6D6 /* libsequoia_openpgp_ffi.a */,
   4.651 +			);
   4.652 +			name = sequoia4ios;
   4.653  			sourceTree = "<group>";
   4.654  		};
   4.655  		6406CE811CE382F400C14D77 /* asn.1 */ = {
   4.656  			isa = PBXGroup;
   4.657  			children = (
   4.658 -				43CC34A02276D34B002F77AF /* NegotiationOpen.c */,
   4.659 -				43CC34A12276D34C002F77AF /* NegotiationOpen.h */,
   4.660 -				43CC349C2276D31A002F77AF /* NegotiationRequest.c */,
   4.661 -				43CC349D2276D31A002F77AF /* NegotiationRequest.h */,
   4.662 -				431F04A12273235300CCE960 /* GroupTrustThisKey.c */,
   4.663 -				431F049C2273235300CCE960 /* GroupTrustThisKey.h */,
   4.664 -				431F04A9227323EE00CCE960 /* OwnKeys.c */,
   4.665 -				431F04A8227323EE00CCE960 /* OwnKeys.h */,
   4.666 -				431F048F2273227900CCE960 /* OwnKeysFirst.c */,
   4.667 -				431F048E2273227900CCE960 /* OwnKeysFirst.h */,
   4.668 -				431F04A5227323A400CCE960 /* OwnKeysSecond.c */,
   4.669 -				431F04A4227323A400CCE960 /* OwnKeysSecond.h */,
   4.670 -				431F0493227322EF00CCE960 /* CommitAcceptFirst.c */,
   4.671 -				431F0492227322EF00CCE960 /* CommitAcceptFirst.h */,
   4.672 -				431F048B2273223600CCE960 /* CommitAcceptSecond.c */,
   4.673 -				431F04862273223600CCE960 /* CommitAcceptSecond.h */,
   4.674 -				1521CEEE225C9AEE00FD2AA2 /* CommitAccept.h */,
   4.675 -				1521CEE9225C9AED00FD2AA2 /* CommitAcceptForGroup.c */,
   4.676 -				1521CEEC225C9AEE00FD2AA2 /* CommitAcceptForGroup.h */,
   4.677 -				1521CEF2225C9AEE00FD2AA2 /* CommitReject.h */,
   4.678 -				1521CEF1225C9AEE00FD2AA2 /* KeySync.h */,
   4.679 -				1521CEF0225C9AEE00FD2AA2 /* pdu_collection.c */,
   4.680 -				1521CEEA225C9AEE00FD2AA2 /* PString.h */,
   4.681 -				1521CEEB225C9AEE00FD2AA2 /* Rollback.h */,
   4.682 -				1521CEF4225C9AEE00FD2AA2 /* sync.asn1 */,
   4.683 -				1521CEF3225C9AEE00FD2AA2 /* Sync.h */,
   4.684 -				1521CEF5225C9AEF00FD2AA2 /* TID.h */,
   4.685 -				43F73C13216628CA00AB4524 /* Sync.c */,
   4.686 -				43F73BF5216627CB00AB4524 /* CommitAccept.c */,
   4.687 -				43F73BFB216627CC00AB4524 /* CommitReject.c */,
   4.688 -				43F73BF7216627CC00AB4524 /* KeySync.c */,
   4.689 -				43F73BF9216627CC00AB4524 /* Rollback.c */,
   4.690 -				43F73BF6216627CC00AB4524 /* TID.c */,
   4.691 -				43F73BEB2166269200AB4524 /* PString.c */,
   4.692 -				646C40951D510CD700C63EFF /* asn_application.h */,
   4.693 -				646C40961D510CD700C63EFF /* asn_codecs_prim.c */,
   4.694 -				646C40971D510CD700C63EFF /* asn_codecs_prim.h */,
   4.695 -				646C40981D510CD700C63EFF /* asn_codecs.h */,
   4.696 -				646C40991D510CD700C63EFF /* asn_internal.h */,
   4.697 -				646C409A1D510CD700C63EFF /* asn_SEQUENCE_OF.c */,
   4.698 -				646C409B1D510CD700C63EFF /* asn_SEQUENCE_OF.h */,
   4.699 -				646C409C1D510CD700C63EFF /* asn_SET_OF.c */,
   4.700 -				646C409D1D510CD700C63EFF /* asn_SET_OF.h */,
   4.701 -				646C409E1D510CD700C63EFF /* asn_system.h */,
   4.702 -				646C409F1D510CD700C63EFF /* Beacon.c */,
   4.703 -				646C40A01D510CD700C63EFF /* Beacon.h */,
   4.704 -				646C40A11D510CD700C63EFF /* ber_decoder.c */,
   4.705 -				646C40A21D510CD700C63EFF /* ber_decoder.h */,
   4.706 -				646C40A31D510CD700C63EFF /* ber_tlv_length.c */,
   4.707 -				646C40A41D510CD700C63EFF /* ber_tlv_length.h */,
   4.708 -				646C40A51D510CD700C63EFF /* ber_tlv_tag.c */,
   4.709 -				646C40A61D510CD700C63EFF /* ber_tlv_tag.h */,
   4.710 -				646C40A71D510CD700C63EFF /* BIT_STRING.c */,
   4.711 -				646C40A81D510CD700C63EFF /* BIT_STRING.h */,
   4.712 -				646C40A91D510CD700C63EFF /* BOOLEAN.c */,
   4.713 -				646C40AA1D510CD700C63EFF /* BOOLEAN.h */,
   4.714 -				646C40AB1D510CD700C63EFF /* constr_CHOICE.c */,
   4.715 -				646C40AC1D510CD700C63EFF /* constr_CHOICE.h */,
   4.716 -				646C40AD1D510CD700C63EFF /* constr_SEQUENCE_OF.c */,
   4.717 -				646C40AE1D510CD700C63EFF /* constr_SEQUENCE_OF.h */,
   4.718 -				646C40AF1D510CD700C63EFF /* constr_SEQUENCE.c */,
   4.719 -				646C40B01D510CD700C63EFF /* constr_SEQUENCE.h */,
   4.720 -				646C40B11D510CD700C63EFF /* constr_SET_OF.c */,
   4.721 -				646C40B21D510CD700C63EFF /* constr_SET_OF.h */,
   4.722 -				646C40B31D510CD700C63EFF /* constr_TYPE.c */,
   4.723 -				646C40B41D510CD700C63EFF /* constr_TYPE.h */,
   4.724 -				646C40B51D510CD700C63EFF /* constraints.c */,
   4.725 -				646C40B61D510CD700C63EFF /* constraints.h */,
   4.726 -				646C40B71D510CD700C63EFF /* der_encoder.c */,
   4.727 -				646C40B81D510CD700C63EFF /* der_encoder.h */,
   4.728 -				646C40BB1D510CD700C63EFF /* GroupKeys.c */,
   4.729 -				646C40BC1D510CD700C63EFF /* GroupKeys.h */,
   4.730 -				646C40BF1D510CD700C63EFF /* Hash.c */,
   4.731 -				646C40C01D510CD700C63EFF /* Hash.h */,
   4.732 -				646C40C31D510CD700C63EFF /* Hex.c */,
   4.733 -				646C40C41D510CD700C63EFF /* Hex.h */,
   4.734 -				646C40C51D510CD700C63EFF /* Identity.c */,
   4.735 -				646C40C61D510CD700C63EFF /* Identity.h */,
   4.736 -				646C40C71D510CD700C63EFF /* IdentityList.c */,
   4.737 -				646C40C81D510CD800C63EFF /* IdentityList.h */,
   4.738 -				646C40C91D510CD800C63EFF /* INTEGER.c */,
   4.739 -				646C40CA1D510CD800C63EFF /* INTEGER.h */,
   4.740 -				646C40CB1D510CD800C63EFF /* ISO639-1.c */,
   4.741 -				646C40CC1D510CD800C63EFF /* ISO639-1.h */,
   4.742 -				646C40CD1D510CD800C63EFF /* NativeEnumerated.c */,
   4.743 -				646C40CE1D510CD800C63EFF /* NativeEnumerated.h */,
   4.744 -				646C40CF1D510CD800C63EFF /* NativeInteger.c */,
   4.745 -				646C40D01D510CD800C63EFF /* NativeInteger.h */,
   4.746 -				646C40D11D510CD800C63EFF /* OCTET_STRING.c */,
   4.747 -				646C40D21D510CD800C63EFF /* OCTET_STRING.h */,
   4.748 -				646C40D31D510CD800C63EFF /* per_decoder.c */,
   4.749 -				646C40D41D510CD800C63EFF /* per_decoder.h */,
   4.750 -				646C40D51D510CD800C63EFF /* per_encoder.c */,
   4.751 -				646C40D61D510CD800C63EFF /* per_encoder.h */,
   4.752 -				646C40D71D510CD800C63EFF /* per_opentype.c */,
   4.753 -				646C40D81D510CD800C63EFF /* per_opentype.h */,
   4.754 -				646C40D91D510CD800C63EFF /* per_support.c */,
   4.755 -				646C40DA1D510CD800C63EFF /* per_support.h */,
   4.756 -				646C40DB1D510CD800C63EFF /* PrintableString.c */,
   4.757 -				646C40DC1D510CD800C63EFF /* PrintableString.h */,
   4.758 -				646C40E01D510CD800C63EFF /* UTF8String.c */,
   4.759 -				646C40E11D510CD800C63EFF /* UTF8String.h */,
   4.760 -				646C40E21D510CD800C63EFF /* Version.c */,
   4.761 -				646C40E31D510CD800C63EFF /* Version.h */,
   4.762 -				646C40E41D510CD800C63EFF /* xer_decoder.c */,
   4.763 -				646C40E51D510CD800C63EFF /* xer_decoder.h */,
   4.764 -				646C40E61D510CD800C63EFF /* xer_encoder.c */,
   4.765 -				646C40E71D510CD800C63EFF /* xer_encoder.h */,
   4.766 -				646C40E81D510CD800C63EFF /* xer_support.c */,
   4.767 -				646C40E91D510CD800C63EFF /* xer_support.h */,
   4.768 +				15B037A822B2B822002D664C /* asn_application.h */,
   4.769 +				15B0379A22B2B821002D664C /* asn_codecs_prim.c */,
   4.770 +				15B0377022B2B81C002D664C /* asn_codecs_prim.h */,
   4.771 +				15B0379D22B2B821002D664C /* asn_codecs.h */,
   4.772 +				15B0379F22B2B821002D664C /* asn_internal.h */,
   4.773 +				15B0375722B2B819002D664C /* asn_SEQUENCE_OF.c */,
   4.774 +				15B037A922B2B822002D664C /* asn_SEQUENCE_OF.h */,
   4.775 +				15B0379622B2B820002D664C /* asn_SET_OF.c */,
   4.776 +				15B0376F22B2B81C002D664C /* asn_SET_OF.h */,
   4.777 +				15B0374F22B2B818002D664C /* asn_system.h */,
   4.778 +				15B0374822B2B817002D664C /* Beacon.c */,
   4.779 +				15B0375A22B2B819002D664C /* Beacon.h */,
   4.780 +				15B0378922B2B81F002D664C /* ber_decoder.c */,
   4.781 +				15B0378422B2B81E002D664C /* ber_decoder.h */,
   4.782 +				15B0373F22B2B816002D664C /* ber_tlv_length.c */,
   4.783 +				15B0379722B2B820002D664C /* ber_tlv_length.h */,
   4.784 +				15B0375322B2B818002D664C /* ber_tlv_tag.c */,
   4.785 +				15B0376122B2B81A002D664C /* ber_tlv_tag.h */,
   4.786 +				15B0377F22B2B81E002D664C /* BIT_STRING.c */,
   4.787 +				15B0378222B2B81E002D664C /* BIT_STRING.h */,
   4.788 +				15B037A122B2B821002D664C /* BOOLEAN.c */,
   4.789 +				15B0375422B2B818002D664C /* BOOLEAN.h */,
   4.790 +				15B0374122B2B817002D664C /* CommitAccept.c */,
   4.791 +				15B0378822B2B81F002D664C /* CommitAccept.h */,
   4.792 +				15B037A622B2B822002D664C /* CommitAcceptForGroup.c */,
   4.793 +				15B0379B22B2B821002D664C /* CommitAcceptForGroup.h */,
   4.794 +				15B0377E22B2B81D002D664C /* CommitAcceptOfferer.c */,
   4.795 +				15B0375222B2B818002D664C /* CommitAcceptOfferer.h */,
   4.796 +				15B0376722B2B81B002D664C /* CommitAcceptRequester.c */,
   4.797 +				15B037A522B2B822002D664C /* CommitAcceptRequester.h */,
   4.798 +				15B037A222B2B822002D664C /* CommitReject.c */,
   4.799 +				15B0376822B2B81B002D664C /* CommitReject.h */,
   4.800 +				15B0379C22B2B821002D664C /* constr_CHOICE.c */,
   4.801 +				15B0377B22B2B81D002D664C /* constr_CHOICE.h */,
   4.802 +				15B0375822B2B819002D664C /* constr_SEQUENCE_OF.c */,
   4.803 +				15B0378722B2B81E002D664C /* constr_SEQUENCE_OF.h */,
   4.804 +				15B0374422B2B817002D664C /* constr_SEQUENCE.c */,
   4.805 +				15B0377A22B2B81D002D664C /* constr_SEQUENCE.h */,
   4.806 +				15B0378022B2B81E002D664C /* constr_SET_OF.c */,
   4.807 +				15B0379922B2B821002D664C /* constr_SET_OF.h */,
   4.808 +				15B0377D22B2B81D002D664C /* constr_TYPE.c */,
   4.809 +				15B0376522B2B81A002D664C /* constr_TYPE.h */,
   4.810 +				15B0378122B2B81E002D664C /* constraints.c */,
   4.811 +				15B0377122B2B81C002D664C /* constraints.h */,
   4.812 +				15B0375022B2B818002D664C /* der_encoder.c */,
   4.813 +				15B0378322B2B81E002D664C /* der_encoder.h */,
   4.814 +				15B0377822B2B81D002D664C /* GroupKeys.c */,
   4.815 +				15B0374022B2B817002D664C /* GroupKeys.h */,
   4.816 +				15B0377622B2B81D002D664C /* GroupTrustThisKey.c */,
   4.817 +				15B0377C22B2B81D002D664C /* GroupTrustThisKey.h */,
   4.818 +				15B0379022B2B81F002D664C /* Hash.c */,
   4.819 +				15B0376322B2B81A002D664C /* Hash.h */,
   4.820 +				15B0379122B2B820002D664C /* Hex.c */,
   4.821 +				15B0379222B2B820002D664C /* Hex.h */,
   4.822 +				15B0375622B2B819002D664C /* Identity.c */,
   4.823 +				15B0374722B2B817002D664C /* Identity.h */,
   4.824 +				15B0377422B2B81C002D664C /* IdentityList.c */,
   4.825 +				15B0374B22B2B817002D664C /* IdentityList.h */,
   4.826 +				15B0378A22B2B81F002D664C /* INTEGER.c */,
   4.827 +				15B0378F22B2B81F002D664C /* INTEGER.h */,
   4.828 +				15B0376022B2B81A002D664C /* ISO639-1.c */,
   4.829 +				15B0375D22B2B819002D664C /* ISO639-1.h */,
   4.830 +				15B0377322B2B81C002D664C /* KeySync.c */,
   4.831 +				15B0376B22B2B81B002D664C /* KeySync.h */,
   4.832 +				15B0374E22B2B818002D664C /* NativeEnumerated.c */,
   4.833 +				15B0376422B2B81A002D664C /* NativeEnumerated.h */,
   4.834 +				15B037A022B2B821002D664C /* NativeInteger.c */,
   4.835 +				15B0374D22B2B818002D664C /* NativeInteger.h */,
   4.836 +				15B0374322B2B817002D664C /* NegotiationOpen.c */,
   4.837 +				15B0378522B2B81E002D664C /* NegotiationOpen.h */,
   4.838 +				15B0374622B2B817002D664C /* NegotiationRequest.c */,
   4.839 +				15B0376922B2B81B002D664C /* NegotiationRequest.h */,
   4.840 +				15B0374A22B2B817002D664C /* OCTET_STRING.c */,
   4.841 +				15B0378622B2B81E002D664C /* OCTET_STRING.h */,
   4.842 +				15B0378D22B2B81F002D664C /* OwnKeysOfferer.c */,
   4.843 +				15B037A722B2B822002D664C /* OwnKeysOfferer.h */,
   4.844 +				15B0375122B2B818002D664C /* OwnKeysRequester.c */,
   4.845 +				15B0379822B2B820002D664C /* OwnKeysRequester.h */,
   4.846 +				15B0375922B2B819002D664C /* pdu_collection.c */,
   4.847 +				15B0375C22B2B819002D664C /* per_decoder.c */,
   4.848 +				15B0378C22B2B81F002D664C /* per_decoder.h */,
   4.849 +				15B0376622B2B81B002D664C /* per_encoder.c */,
   4.850 +				15B0377722B2B81D002D664C /* per_encoder.h */,
   4.851 +				15B0379422B2B820002D664C /* per_opentype.c */,
   4.852 +				15B0375522B2B819002D664C /* per_opentype.h */,
   4.853 +				15B0379E22B2B821002D664C /* per_support.c */,
   4.854 +				15B0378E22B2B81F002D664C /* per_support.h */,
   4.855 +				15B037A322B2B822002D664C /* PrintableString.c */,
   4.856 +				15B0375F22B2B81A002D664C /* PrintableString.h */,
   4.857 +				15B0376222B2B81A002D664C /* PString.c */,
   4.858 +				15B0374922B2B817002D664C /* PString.h */,
   4.859 +				15B0377222B2B81C002D664C /* Rollback.c */,
   4.860 +				15B0374222B2B817002D664C /* Rollback.h */,
   4.861 +				15B0374C22B2B818002D664C /* Sync.c */,
   4.862 +				15B037A422B2B822002D664C /* Sync.h */,
   4.863 +				15B0377522B2B81D002D664C /* TID.c */,
   4.864 +				15B0376A22B2B81B002D664C /* TID.h */,
   4.865 +				15B0374522B2B817002D664C /* UTF8String.c */,
   4.866 +				15B0376C22B2B81B002D664C /* UTF8String.h */,
   4.867 +				15B0378B22B2B81F002D664C /* Version.c */,
   4.868 +				15B0376D22B2B81C002D664C /* Version.h */,
   4.869 +				15B0377922B2B81D002D664C /* xer_decoder.c */,
   4.870 +				15B0375E22B2B81A002D664C /* xer_decoder.h */,
   4.871 +				15B0379322B2B820002D664C /* xer_encoder.c */,
   4.872 +				15B0376E22B2B81C002D664C /* xer_encoder.h */,
   4.873 +				15B0375B22B2B819002D664C /* xer_support.c */,
   4.874 +				15B0379522B2B820002D664C /* xer_support.h */,
   4.875  			);
   4.876  			name = asn.1;
   4.877  			sourceTree = "<group>";
   4.878 @@ -580,27 +607,19 @@
   4.879  			path = pEpTrustWords;
   4.880  			sourceTree = "<group>";
   4.881  		};
   4.882 -		6459224E1B8BD32B00A5AF93 /* Products */ = {
   4.883 -			isa = PBXGroup;
   4.884 -			children = (
   4.885 -				645922521B8BD32B00A5AF93 /* libnetpgp.a */,
   4.886 -			);
   4.887 -			name = Products;
   4.888 -			sourceTree = "<group>";
   4.889 -		};
   4.890  		64796A361B455AA5004B1C24 = {
   4.891  			isa = PBXGroup;
   4.892  			children = (
   4.893 -				43D47A89225CC60600E97C5B /* Resources-iPad */,
   4.894 +				1549180D22B92EA20091B6D6 /* libiconv.2.tbd */,
   4.895 +				1549181322B92EA50091B6D6 /* libz.dylib */,
   4.896  				64951A1B1BE0FCD800B10E71 /* system.db */,
   4.897  				64DA24121B832EBA000BEE80 /* libetpan.xcodeproj */,
   4.898 -				64DA240C1B832EA0000BEE80 /* netpgp.xcodeproj */,
   4.899 -				649DE08A1B45C19100912F72 /* libcurl.a */,
   4.900  				6406CE811CE382F400C14D77 /* asn.1 */,
   4.901  				64A8264B1B455C5600EECAF0 /* srcref */,
   4.902  				644297C01BE11C65002BC73B /* pEpTrustWords */,
   4.903  				64796A401B455AA5004B1C24 /* Products */,
   4.904  				43D47A8A225CC60600E97C5B /* pEpTrustWords-Info.plist */,
   4.905 +				154917EB22B926080091B6D6 /* Frameworks */,
   4.906  			);
   4.907  			sourceTree = "<group>";
   4.908  		};
   4.909 @@ -616,6 +635,28 @@
   4.910  		64A8264B1B455C5600EECAF0 /* srcref */ = {
   4.911  			isa = PBXGroup;
   4.912  			children = (
   4.913 +				154918A222B9401F0091B6D6 /* aux_mime_msg.c */,
   4.914 +				1549189922B9401E0091B6D6 /* aux_mime_msg.h */,
   4.915 +				154918AA22B940200091B6D6 /* blacklist.h */,
   4.916 +				1549189222B9401D0091B6D6 /* fsm_common.h */,
   4.917 +				154918A422B9401F0091B6D6 /* growing_buf.h */,
   4.918 +				1549189722B9401E0091B6D6 /* KeySync_fsm.c */,
   4.919 +				1549189622B9401E0091B6D6 /* KeySync_fsm.h */,
   4.920 +				154918A322B9401F0091B6D6 /* openpgp_compat.h */,
   4.921 +				154918A122B9401F0091B6D6 /* resource_id.h */,
   4.922 +				1549189322B9401E0091B6D6 /* status_to_string.h */,
   4.923 +				1549189822B9401E0091B6D6 /* Sync_actions.c */,
   4.924 +				1549189C22B9401E0091B6D6 /* sync_codec.c */,
   4.925 +				154918A622B9401F0091B6D6 /* sync_codec.h */,
   4.926 +				1549189E22B9401F0091B6D6 /* Sync_event.c */,
   4.927 +				1549189D22B9401F0091B6D6 /* Sync_event.h */,
   4.928 +				154918A022B9401F0091B6D6 /* Sync_func.c */,
   4.929 +				154918A722B940200091B6D6 /* Sync_func.h */,
   4.930 +				1549189A22B9401E0091B6D6 /* Sync_impl.c */,
   4.931 +				154918A922B940200091B6D6 /* Sync_impl.h */,
   4.932 +				159EF42622B6D3E900149C0C /* pgp_sequoia_internal.h */,
   4.933 +				159EF42422B6D3E900149C0C /* pgp_sequoia.c */,
   4.934 +				159EF42522B6D3E900149C0C /* pgp_sequoia.h */,
   4.935  				C46EBAE7216E445F0042A6A3 /* base64.c */,
   4.936  				C46EBAEC216E445F0042A6A3 /* base64.h */,
   4.937  				438C43B42167752C00C7425B /* labeled_int_list.c */,
   4.938 @@ -624,21 +665,15 @@
   4.939  				43F73C0A2166282C00AB4524 /* growing_buf.c */,
   4.940  				431F04B222733A7E00CCE960 /* key_reset.h */,
   4.941  				43F73C052166282C00AB4524 /* key_reset.c */,
   4.942 -				43F73C072166282C00AB4524 /* KeySync_fsm.c */,
   4.943  				43F73C032166282C00AB4524 /* openpgp_compat.c */,
   4.944  				43F73C092166282C00AB4524 /* sync_api.c */,
   4.945 -				43F73C062166282C00AB4524 /* sync_codec.c */,
   4.946 -				43F73C042166282C00AB4524 /* Sync_event.c */,
   4.947 -				43F73BF1216626E100AB4524 /* Sync_func.c */,
   4.948  				4337082D203C075A004E6547 /* sqlite3.c */,
   4.949  				43370832203C075A004E6547 /* sqlite3.h */,
   4.950  				430BCC472015EE800077E998 /* pEp_string.c */,
   4.951  				430BCC462015EE800077E998 /* pEp_string.h */,
   4.952  				43F6921C1F164A47009418F5 /* resource_id.c */,
   4.953 -				4354FF641D6EDF300033069C /* sync_impl.c */,
   4.954  				646C414C1D510D8800C63EFF /* baseprotocol.c */,
   4.955  				646C414D1D510D8800C63EFF /* baseprotocol.h */,
   4.956 -				646C413E1D510D2C00C63EFF /* sync_actions.c */,
   4.957  				646788871CEB3D120001F54C /* map_asn1.c */,
   4.958  				646788881CEB3D120001F54C /* map_asn1.h */,
   4.959  				430D258A1C9ED75A00B94535 /* blacklist.c */,
   4.960 @@ -664,9 +699,6 @@
   4.961  				64A8265F1B455D0800EECAF0 /* pEp_internal.h */,
   4.962  				64A826601B455D0800EECAF0 /* pEpEngine.c */,
   4.963  				64A826611B455D0800EECAF0 /* pEpEngine.h */,
   4.964 -				64A826621B455D0800EECAF0 /* pgp_netpgp_internal.h */,
   4.965 -				64A826631B455D0800EECAF0 /* pgp_netpgp.c */,
   4.966 -				64A826641B455D0800EECAF0 /* pgp_netpgp.h */,
   4.967  				64A826651B455D0800EECAF0 /* platform_unix.c */,
   4.968  				64A826661B455D0800EECAF0 /* platform_unix.h */,
   4.969  				64A826691B455D0800EECAF0 /* platform.h */,
   4.970 @@ -693,71 +725,83 @@
   4.971  			isa = PBXHeadersBuildPhase;
   4.972  			buildActionMask = 2147483647;
   4.973  			files = (
   4.974 -				646C41031D510CD800C63EFF /* constr_SEQUENCE_OF.h in Headers */,
   4.975 -				1521CEFB225C9AEF00FD2AA2 /* CommitAccept.h in Headers */,
   4.976 -				646C40ED1D510CD800C63EFF /* asn_codecs.h in Headers */,
   4.977 -				646C41371D510CD800C63EFF /* Version.h in Headers */,
   4.978 -				1521CEF8225C9AEF00FD2AA2 /* Rollback.h in Headers */,
   4.979 -				646C412F1D510CD800C63EFF /* per_support.h in Headers */,
   4.980 -				646C41111D510CD800C63EFF /* GroupKeys.h in Headers */,
   4.981 -				646C40F21D510CD800C63EFF /* asn_SET_OF.h in Headers */,
   4.982 -				646C41311D510CD800C63EFF /* PrintableString.h in Headers */,
   4.983 -				431F048C2273223600CCE960 /* CommitAcceptSecond.h in Headers */,
   4.984 -				646C40F51D510CD800C63EFF /* Beacon.h in Headers */,
   4.985 +				15B037D722B2B822002D664C /* UTF8String.h in Headers */,
   4.986 +				15B037EF22B2B822002D664C /* ber_decoder.h in Headers */,
   4.987 +				15B037B822B2B822002D664C /* NativeInteger.h in Headers */,
   4.988  				438C43B52167752C00C7425B /* labeled_int_list.h in Headers */,
   4.989 -				646C40F71D510CD800C63EFF /* ber_decoder.h in Headers */,
   4.990 -				646C41351D510CD800C63EFF /* UTF8String.h in Headers */,
   4.991 -				43CC34A32276D34C002F77AF /* NegotiationOpen.h in Headers */,
   4.992 -				646C40EC1D510CD800C63EFF /* asn_codecs_prim.h in Headers */,
   4.993 -				438C439B2167582500C7425B /* sync_api.h in Headers */,
   4.994 -				646C40EE1D510CD800C63EFF /* asn_internal.h in Headers */,
   4.995 -				646C413B1D510CD800C63EFF /* xer_encoder.h in Headers */,
   4.996 -				431F04A6227323A400CCE960 /* OwnKeysSecond.h in Headers */,
   4.997 -				646C40F01D510CD800C63EFF /* asn_SEQUENCE_OF.h in Headers */,
   4.998 -				43CC349F2276D31A002F77AF /* NegotiationRequest.h in Headers */,
   4.999 -				646C40FD1D510CD800C63EFF /* BIT_STRING.h in Headers */,
  4.1000 -				646C411F1D510CD800C63EFF /* INTEGER.h in Headers */,
  4.1001 -				646C411D1D510CD800C63EFF /* IdentityList.h in Headers */,
  4.1002 -				1521CEFE225C9AEF00FD2AA2 /* KeySync.h in Headers */,
  4.1003 -				646C41011D510CD800C63EFF /* constr_CHOICE.h in Headers */,
  4.1004 -				646C40FB1D510CD800C63EFF /* ber_tlv_tag.h in Headers */,
  4.1005 +				159EF42822B6D3E900149C0C /* pgp_sequoia.h in Headers */,
  4.1006 +				15B037E222B2B822002D664C /* per_encoder.h in Headers */,
  4.1007 +				15B0380F22B2B823002D664C /* Sync.h in Headers */,
  4.1008 +				15B0380422B2B822002D664C /* constr_SET_OF.h in Headers */,
  4.1009 +				15B0381322B2B823002D664C /* asn_application.h in Headers */,
  4.1010 +				15B0380322B2B822002D664C /* OwnKeysRequester.h in Headers */,
  4.1011 +				154918AB22B940200091B6D6 /* fsm_common.h in Headers */,
  4.1012 +				15B037E722B2B822002D664C /* GroupTrustThisKey.h in Headers */,
  4.1013 +				15B037C522B2B822002D664C /* Beacon.h in Headers */,
  4.1014 +				15B0380622B2B822002D664C /* CommitAcceptForGroup.h in Headers */,
  4.1015 +				15B037D622B2B822002D664C /* KeySync.h in Headers */,
  4.1016 +				15B037FD22B2B822002D664C /* Hex.h in Headers */,
  4.1017 +				15B0381222B2B823002D664C /* OwnKeysOfferer.h in Headers */,
  4.1018 +				15B037ED22B2B822002D664C /* BIT_STRING.h in Headers */,
  4.1019 +				15B037DC22B2B822002D664C /* constraints.h in Headers */,
  4.1020 +				154918B622B940200091B6D6 /* Sync_event.h in Headers */,
  4.1021 +				15B037F222B2B822002D664C /* constr_SEQUENCE_OF.h in Headers */,
  4.1022 +				15B0380022B2B822002D664C /* xer_support.h in Headers */,
  4.1023 +				154918C022B940200091B6D6 /* Sync_func.h in Headers */,
  4.1024 +				15B037CC22B2B822002D664C /* ber_tlv_tag.h in Headers */,
  4.1025 +				154918BC22B940200091B6D6 /* openpgp_compat.h in Headers */,
  4.1026 +				154918B222B940200091B6D6 /* aux_mime_msg.h in Headers */,
  4.1027 +				15B0381422B2B823002D664C /* asn_SEQUENCE_OF.h in Headers */,
  4.1028 +				15B037FA22B2B822002D664C /* INTEGER.h in Headers */,
  4.1029 +				15B037F322B2B822002D664C /* CommitAccept.h in Headers */,
  4.1030 +				15B037CF22B2B822002D664C /* NativeEnumerated.h in Headers */,
  4.1031 +				15B037D822B2B822002D664C /* Version.h in Headers */,
  4.1032 +				15B037D022B2B822002D664C /* constr_TYPE.h in Headers */,
  4.1033 +				15B037B422B2B822002D664C /* PString.h in Headers */,
  4.1034 +				15B037F922B2B822002D664C /* per_support.h in Headers */,
  4.1035 +				15B037C022B2B822002D664C /* per_opentype.h in Headers */,
  4.1036 +				15B0380222B2B822002D664C /* ber_tlv_length.h in Headers */,
  4.1037 +				15B037AB22B2B822002D664C /* GroupKeys.h in Headers */,
  4.1038 +				15B037B622B2B822002D664C /* IdentityList.h in Headers */,
  4.1039 +				15B037E622B2B822002D664C /* constr_CHOICE.h in Headers */,
  4.1040  				646C414F1D510D8800C63EFF /* baseprotocol.h in Headers */,
  4.1041 +				15B0381022B2B823002D664C /* CommitAcceptRequester.h in Headers */,
  4.1042 +				15B0380A22B2B822002D664C /* asn_internal.h in Headers */,
  4.1043 +				15B037D922B2B822002D664C /* xer_encoder.h in Headers */,
  4.1044 +				154918C322B940200091B6D6 /* blacklist.h in Headers */,
  4.1045 +				15B037BF22B2B822002D664C /* BOOLEAN.h in Headers */,
  4.1046  				6467888D1CEB3D120001F54C /* map_asn1.h in Headers */,
  4.1047 -				1521CEF9225C9AEF00FD2AA2 /* CommitAcceptForGroup.h in Headers */,
  4.1048 -				646C40F31D510CD800C63EFF /* asn_system.h in Headers */,
  4.1049 +				154918BA22B940200091B6D6 /* resource_id.h in Headers */,
  4.1050 +				15B037BA22B2B822002D664C /* asn_system.h in Headers */,
  4.1051 +				15B037E522B2B822002D664C /* constr_SEQUENCE.h in Headers */,
  4.1052 +				15B037C822B2B822002D664C /* ISO639-1.h in Headers */,
  4.1053 +				15B037C922B2B822002D664C /* xer_decoder.h in Headers */,
  4.1054  				43370834203C075A004E6547 /* sqlite3.h in Headers */,
  4.1055 -				646C410B1D510CD800C63EFF /* constraints.h in Headers */,
  4.1056 -				646C41251D510CD800C63EFF /* NativeInteger.h in Headers */,
  4.1057 -				646C41271D510CD800C63EFF /* OCTET_STRING.h in Headers */,
  4.1058 -				646C41391D510CD800C63EFF /* xer_decoder.h in Headers */,
  4.1059 -				646C40EA1D510CD800C63EFF /* asn_application.h in Headers */,
  4.1060 -				646C41211D510CD800C63EFF /* ISO639-1.h in Headers */,
  4.1061 +				15B037D522B2B822002D664C /* TID.h in Headers */,
  4.1062 +				15B037AD22B2B822002D664C /* Rollback.h in Headers */,
  4.1063 +				154918BF22B940200091B6D6 /* sync_codec.h in Headers */,
  4.1064 +				15B037DB22B2B822002D664C /* asn_codecs_prim.h in Headers */,
  4.1065  				431F04B722733A7E00CCE960 /* key_reset.h in Headers */,
  4.1066 -				646C412D1D510CD800C63EFF /* per_opentype.h in Headers */,
  4.1067 -				646C413D1D510CD800C63EFF /* xer_support.h in Headers */,
  4.1068 -				646C41191D510CD800C63EFF /* Hex.h in Headers */,
  4.1069 -				431F04902273227900CCE960 /* OwnKeysFirst.h in Headers */,
  4.1070 -				646C41051D510CD800C63EFF /* constr_SEQUENCE.h in Headers */,
  4.1071 -				1521CF01225C9AEF00FD2AA2 /* TID.h in Headers */,
  4.1072 -				646C41151D510CD800C63EFF /* Hash.h in Headers */,
  4.1073 -				646C40FF1D510CD800C63EFF /* BOOLEAN.h in Headers */,
  4.1074  				64A8268C1B455D9D00EECAF0 /* pEpEngine.h in Headers */,
  4.1075 -				431F04AA227323EE00CCE960 /* OwnKeys.h in Headers */,
  4.1076 -				646C41091D510CD800C63EFF /* constr_TYPE.h in Headers */,
  4.1077 -				431F0494227322EF00CCE960 /* CommitAcceptFirst.h in Headers */,
  4.1078 +				154918AC22B940200091B6D6 /* status_to_string.h in Headers */,
  4.1079 +				15B037DA22B2B822002D664C /* asn_SET_OF.h in Headers */,
  4.1080 +				154918C222B940200091B6D6 /* Sync_impl.h in Headers */,
  4.1081 +				15B037D422B2B822002D664C /* NegotiationRequest.h in Headers */,
  4.1082  				430BCC482015EE800077E998 /* pEp_string.h in Headers */,
  4.1083 -				1521CEFF225C9AEF00FD2AA2 /* CommitReject.h in Headers */,
  4.1084 -				646C410D1D510CD800C63EFF /* der_encoder.h in Headers */,
  4.1085 -				646C41231D510CD800C63EFF /* NativeEnumerated.h in Headers */,
  4.1086 -				646C41071D510CD800C63EFF /* constr_SET_OF.h in Headers */,
  4.1087 -				1521CEF7225C9AEF00FD2AA2 /* PString.h in Headers */,
  4.1088 -				1521CF00225C9AEF00FD2AA2 /* Sync.h in Headers */,
  4.1089 +				15B037F122B2B822002D664C /* OCTET_STRING.h in Headers */,
  4.1090 +				15B037CE22B2B822002D664C /* Hash.h in Headers */,
  4.1091 +				15B037EE22B2B822002D664C /* der_encoder.h in Headers */,
  4.1092 +				159EF42922B6D3E900149C0C /* pgp_sequoia_internal.h in Headers */,
  4.1093 +				15B037BD22B2B822002D664C /* CommitAcceptOfferer.h in Headers */,
  4.1094 +				15B037CA22B2B822002D664C /* PrintableString.h in Headers */,
  4.1095 +				15B037B222B2B822002D664C /* Identity.h in Headers */,
  4.1096 +				154918BD22B940200091B6D6 /* growing_buf.h in Headers */,
  4.1097 +				15B037D322B2B822002D664C /* CommitReject.h in Headers */,
  4.1098 +				15B0380822B2B822002D664C /* asn_codecs.h in Headers */,
  4.1099 +				154918AF22B940200091B6D6 /* KeySync_fsm.h in Headers */,
  4.1100  				C46EBAEE216E445F0042A6A3 /* base64.h in Headers */,
  4.1101 -				646C411B1D510CD800C63EFF /* Identity.h in Headers */,
  4.1102 -				646C412B1D510CD800C63EFF /* per_encoder.h in Headers */,
  4.1103 -				646C40F91D510CD800C63EFF /* ber_tlv_length.h in Headers */,
  4.1104 -				646C41291D510CD800C63EFF /* per_decoder.h in Headers */,
  4.1105 -				431F04A22273235300CCE960 /* GroupTrustThisKey.h in Headers */,
  4.1106 +				15B037F722B2B822002D664C /* per_decoder.h in Headers */,
  4.1107 +				15B037F022B2B822002D664C /* NegotiationOpen.h in Headers */,
  4.1108  			);
  4.1109  			runOnlyForDeploymentPostprocessing = 0;
  4.1110  		};
  4.1111 @@ -796,7 +840,6 @@
  4.1112  			);
  4.1113  			dependencies = (
  4.1114  				43D47AA1225CC82400E97C5B /* PBXTargetDependency */,
  4.1115 -				645922541B8BD53F00A5AF93 /* PBXTargetDependency */,
  4.1116  				64289E3F1B8B638800FC617B /* PBXTargetDependency */,
  4.1117  			);
  4.1118  			name = pEpEngine;
  4.1119 @@ -810,7 +853,7 @@
  4.1120  		64796A371B455AA5004B1C24 /* Project object */ = {
  4.1121  			isa = PBXProject;
  4.1122  			attributes = {
  4.1123 -				LastUpgradeCheck = 0940;
  4.1124 +				LastUpgradeCheck = 1020;
  4.1125  				ORGANIZATIONNAME = "p≡p Security S.A.";
  4.1126  				TargetAttributes = {
  4.1127  					644297BE1BE11C65002BC73B = {
  4.1128 @@ -837,10 +880,6 @@
  4.1129  					ProductGroup = 64289E2B1B8B630200FC617B /* Products */;
  4.1130  					ProjectRef = 64DA24121B832EBA000BEE80 /* libetpan.xcodeproj */;
  4.1131  				},
  4.1132 -				{
  4.1133 -					ProductGroup = 6459224E1B8BD32B00A5AF93 /* Products */;
  4.1134 -					ProjectRef = 64DA240C1B832EA0000BEE80 /* netpgp.xcodeproj */;
  4.1135 -				},
  4.1136  			);
  4.1137  			projectRoot = "";
  4.1138  			targets = (
  4.1139 @@ -872,13 +911,6 @@
  4.1140  			remoteRef = 64289E361B8B630200FC617B /* PBXContainerItemProxy */;
  4.1141  			sourceTree = BUILT_PRODUCTS_DIR;
  4.1142  		};
  4.1143 -		645922521B8BD32B00A5AF93 /* libnetpgp.a */ = {
  4.1144 -			isa = PBXReferenceProxy;
  4.1145 -			fileType = archive.ar;
  4.1146 -			path = libnetpgp.a;
  4.1147 -			remoteRef = 645922511B8BD32B00A5AF93 /* PBXContainerItemProxy */;
  4.1148 -			sourceTree = BUILT_PRODUCTS_DIR;
  4.1149 -		};
  4.1150  /* End PBXReferenceProxy section */
  4.1151  
  4.1152  /* Begin PBXResourcesBuildPhase section */
  4.1153 @@ -910,7 +942,7 @@
  4.1154  			);
  4.1155  			runOnlyForDeploymentPostprocessing = 0;
  4.1156  			shellPath = /bin/bash;
  4.1157 -			shellScript = "export LANG=en_US.UTF-8\n\necho \"warning: ***************************************\"\necho \"warning: *** Generate files: ACTION: $ACTION ***\"\necho \"warning: ***************************************\"\n\ncd \"$SRCROOT/..\"\n\nbash -l -c \"gmake -C sync\"\nbash -l -c \"gmake -C asn.1 Sync.c\"\n";
  4.1158 +			shellScript = "export LANG=en_US.UTF-8\n\necho \"***************************************\"\necho \"*** Generate files: ACTION: $ACTION ***\"\necho \"***************************************\"\n\ncd \"$SRCROOT/..\"\n\nbash -l -c \"gmake -C sync\"\nbash -l -c \"gmake -C asn.1 Sync.c\"\n";
  4.1159  		};
  4.1160  		644297C61BE11D00002BC73B /* ShellScript */ = {
  4.1161  			isa = PBXShellScriptBuildPhase;
  4.1162 @@ -940,93 +972,93 @@
  4.1163  			buildActionMask = 2147483647;
  4.1164  			files = (
  4.1165  				64A826871B455D0800EECAF0 /* stringpair.c in Sources */,
  4.1166 -				43F73C0E2166282C00AB4524 /* sync_codec.c in Sources */,
  4.1167 -				1521CEF6225C9AEF00FD2AA2 /* CommitAcceptForGroup.c in Sources */,
  4.1168 -				431F04912273227900CCE960 /* OwnKeysFirst.c in Sources */,
  4.1169 -				431F04A32273235300CCE960 /* GroupTrustThisKey.c in Sources */,
  4.1170 -				646C41341D510CD800C63EFF /* UTF8String.c in Sources */,
  4.1171 +				15B037C122B2B822002D664C /* Identity.c in Sources */,
  4.1172 +				15B037B522B2B822002D664C /* OCTET_STRING.c in Sources */,
  4.1173  				64A826831B455D0800EECAF0 /* platform_unix.c in Sources */,
  4.1174 -				646C40F81D510CD800C63EFF /* ber_tlv_length.c in Sources */,
  4.1175 -				43F73BF2216626E100AB4524 /* Sync_func.c in Sources */,
  4.1176 -				431F04A7227323A400CCE960 /* OwnKeysSecond.c in Sources */,
  4.1177 -				646C411C1D510CD800C63EFF /* IdentityList.c in Sources */,
  4.1178 -				646C41301D510CD800C63EFF /* PrintableString.c in Sources */,
  4.1179 +				15B0380D22B2B822002D664C /* CommitReject.c in Sources */,
  4.1180 +				15B0380B22B2B822002D664C /* NativeInteger.c in Sources */,
  4.1181 +				154918B322B940200091B6D6 /* Sync_impl.c in Sources */,
  4.1182 +				15B037E322B2B822002D664C /* GroupKeys.c in Sources */,
  4.1183 +				15B037B122B2B822002D664C /* NegotiationRequest.c in Sources */,
  4.1184 +				15B037FC22B2B822002D664C /* Hex.c in Sources */,
  4.1185 +				15B0380722B2B822002D664C /* constr_CHOICE.c in Sources */,
  4.1186 +				15B037B922B2B822002D664C /* NativeEnumerated.c in Sources */,
  4.1187 +				15B037B022B2B822002D664C /* UTF8String.c in Sources */,
  4.1188 +				15B037BE22B2B822002D664C /* ber_tlv_tag.c in Sources */,
  4.1189 +				15B037FE22B2B822002D664C /* xer_encoder.c in Sources */,
  4.1190 +				159EF42722B6D3E900149C0C /* pgp_sequoia.c in Sources */,
  4.1191  				64A8267B1B455D0800EECAF0 /* etpan_mime.c in Sources */,
  4.1192 +				15B037AC22B2B822002D664C /* CommitAccept.c in Sources */,
  4.1193  				64A8267A1B455D0800EECAF0 /* email.c in Sources */,
  4.1194 +				15B037C422B2B822002D664C /* pdu_collection.c in Sources */,
  4.1195 +				15B037E422B2B822002D664C /* xer_decoder.c in Sources */,
  4.1196 +				15B037BC22B2B822002D664C /* OwnKeysRequester.c in Sources */,
  4.1197  				438C43B62167752C00C7425B /* labeled_int_list.c in Sources */,
  4.1198 -				646C41261D510CD800C63EFF /* OCTET_STRING.c in Sources */,
  4.1199 -				646C41141D510CD800C63EFF /* Hash.c in Sources */,
  4.1200 -				43CC349E2276D31A002F77AF /* NegotiationRequest.c in Sources */,
  4.1201 -				43F73BF02166269200AB4524 /* PString.c in Sources */,
  4.1202 +				15B037E822B2B822002D664C /* constr_TYPE.c in Sources */,
  4.1203  				64A826861B455D0800EECAF0 /* stringlist.c in Sources */,
  4.1204 -				4354FF651D6EDF300033069C /* sync_impl.c in Sources */,
  4.1205 +				15B037FB22B2B822002D664C /* Hash.c in Sources */,
  4.1206 +				154918BB22B940200091B6D6 /* aux_mime_msg.c in Sources */,
  4.1207 +				15B037CD22B2B822002D664C /* PString.c in Sources */,
  4.1208 +				15B037F622B2B822002D664C /* Version.c in Sources */,
  4.1209 +				15B037C622B2B822002D664C /* xer_support.c in Sources */,
  4.1210 +				15B037EC22B2B822002D664C /* constraints.c in Sources */,
  4.1211 +				15B0380522B2B822002D664C /* asn_codecs_prim.c in Sources */,
  4.1212  				64A8267E1B455D0800EECAF0 /* message_api.c in Sources */,
  4.1213 -				646C41361D510CD800C63EFF /* Version.c in Sources */,
  4.1214 -				646C41081D510CD800C63EFF /* constr_TYPE.c in Sources */,
  4.1215 -				646C40FE1D510CD800C63EFF /* BOOLEAN.c in Sources */,
  4.1216 -				646C41001D510CD800C63EFF /* constr_CHOICE.c in Sources */,
  4.1217 -				64A826821B455D0800EECAF0 /* pgp_netpgp.c in Sources */,
  4.1218 -				646C41101D510CD800C63EFF /* GroupKeys.c in Sources */,
  4.1219 -				646C40EF1D510CD800C63EFF /* asn_SEQUENCE_OF.c in Sources */,
  4.1220 +				15B037D122B2B822002D664C /* per_encoder.c in Sources */,
  4.1221 +				15B037CB22B2B822002D664C /* ISO639-1.c in Sources */,
  4.1222 +				15B037AF22B2B822002D664C /* constr_SEQUENCE.c in Sources */,
  4.1223 +				15B037B722B2B822002D664C /* Sync.c in Sources */,
  4.1224  				64A826891B455D0800EECAF0 /* trans_auto.c in Sources */,
  4.1225 -				646C410C1D510CD800C63EFF /* der_encoder.c in Sources */,
  4.1226 +				15B0380922B2B822002D664C /* per_support.c in Sources */,
  4.1227 +				15B037D222B2B822002D664C /* CommitAcceptRequester.c in Sources */,
  4.1228 +				15B037E122B2B822002D664C /* GroupTrustThisKey.c in Sources */,
  4.1229  				43F73C112166282C00AB4524 /* sync_api.c in Sources */,
  4.1230 -				646C41381D510CD800C63EFF /* xer_decoder.c in Sources */,
  4.1231 -				43F73BFE216627CC00AB4524 /* KeySync.c in Sources */,
  4.1232 -				646C41181D510CD800C63EFF /* Hex.c in Sources */,
  4.1233  				64A8267D1B455D0800EECAF0 /* keymanagement.c in Sources */,
  4.1234 -				646C40EB1D510CD800C63EFF /* asn_codecs_prim.c in Sources */,
  4.1235 -				646C41451D510D2C00C63EFF /* sync_actions.c in Sources */,
  4.1236 -				646C40F61D510CD800C63EFF /* ber_decoder.c in Sources */,
  4.1237 -				646C40F11D510CD800C63EFF /* asn_SET_OF.c in Sources */,
  4.1238 -				646C413A1D510CD800C63EFF /* xer_encoder.c in Sources */,
  4.1239 -				431F04AB227323EE00CCE960 /* OwnKeys.c in Sources */,
  4.1240 -				43F73BFD216627CC00AB4524 /* TID.c in Sources */,
  4.1241 -				646C41021D510CD800C63EFF /* constr_SEQUENCE_OF.c in Sources */,
  4.1242 -				646C410A1D510CD800C63EFF /* constraints.c in Sources */,
  4.1243  				64A8267C1B455D0800EECAF0 /* identity_list.c in Sources */,
  4.1244 -				646C40FC1D510CD800C63EFF /* BIT_STRING.c in Sources */,
  4.1245 -				646C40F41D510CD800C63EFF /* Beacon.c in Sources */,
  4.1246  				43F73C0D2166282C00AB4524 /* key_reset.c in Sources */,
  4.1247 -				43F73BFC216627CC00AB4524 /* CommitAccept.c in Sources */,
  4.1248 -				646C411E1D510CD800C63EFF /* INTEGER.c in Sources */,
  4.1249 -				646C413C1D510CD800C63EFF /* xer_support.c in Sources */,
  4.1250 +				15B0380C22B2B822002D664C /* BOOLEAN.c in Sources */,
  4.1251  				64A8268A1B455D0800EECAF0 /* transport.c in Sources */,
  4.1252 -				646C41201D510CD800C63EFF /* ISO639-1.c in Sources */,
  4.1253 +				15B037EA22B2B822002D664C /* BIT_STRING.c in Sources */,
  4.1254 +				15B037F522B2B822002D664C /* INTEGER.c in Sources */,
  4.1255 +				15B037C222B2B822002D664C /* asn_SEQUENCE_OF.c in Sources */,
  4.1256  				64A826791B455D0800EECAF0 /* cryptotech.c in Sources */,
  4.1257 -				43F73C0F2166282C00AB4524 /* KeySync_fsm.c in Sources */,
  4.1258 -				646C412A1D510CD800C63EFF /* per_encoder.c in Sources */,
  4.1259 -				646C412E1D510CD800C63EFF /* per_support.c in Sources */,
  4.1260 -				43F73C0C2166282C00AB4524 /* Sync_event.c in Sources */,
  4.1261  				64A826781B455D0800EECAF0 /* bloblist.c in Sources */,
  4.1262 +				15B0381122B2B823002D664C /* CommitAcceptForGroup.c in Sources */,
  4.1263  				C46EBAED216E445F0042A6A3 /* base64.c in Sources */,
  4.1264  				430BCC492015EE800077E998 /* pEp_string.c in Sources */,
  4.1265 -				43F73C00216627CC00AB4524 /* Rollback.c in Sources */,
  4.1266 -				646C41041D510CD800C63EFF /* constr_SEQUENCE.c in Sources */,
  4.1267 -				43F73C14216628CA00AB4524 /* Sync.c in Sources */,
  4.1268 +				15B037EB22B2B822002D664C /* constr_SET_OF.c in Sources */,
  4.1269 +				15B037DD22B2B822002D664C /* Rollback.c in Sources */,
  4.1270  				43F73C0B2166282C00AB4524 /* openpgp_compat.c in Sources */,
  4.1271 +				15B037F422B2B822002D664C /* ber_decoder.c in Sources */,
  4.1272 +				154918B022B940200091B6D6 /* KeySync_fsm.c in Sources */,
  4.1273  				43370833203C075A004E6547 /* sqlite3.c in Sources */,
  4.1274 -				43F73C02216627CC00AB4524 /* CommitReject.c in Sources */,
  4.1275 +				15B0380122B2B822002D664C /* asn_SET_OF.c in Sources */,
  4.1276 +				154918B522B940200091B6D6 /* sync_codec.c in Sources */,
  4.1277 +				15B037DE22B2B822002D664C /* KeySync.c in Sources */,
  4.1278 +				15B037C322B2B822002D664C /* constr_SEQUENCE_OF.c in Sources */,
  4.1279 +				15B037DF22B2B822002D664C /* IdentityList.c in Sources */,
  4.1280 +				15B037AE22B2B822002D664C /* NegotiationOpen.c in Sources */,
  4.1281 +				154918B122B940200091B6D6 /* Sync_actions.c in Sources */,
  4.1282 +				15B037B322B2B822002D664C /* Beacon.c in Sources */,
  4.1283  				64A826881B455D0800EECAF0 /* timestamp.c in Sources */,
  4.1284 -				646C41221D510CD800C63EFF /* NativeEnumerated.c in Sources */,
  4.1285 +				15B037BB22B2B822002D664C /* der_encoder.c in Sources */,
  4.1286 +				15B037E022B2B822002D664C /* TID.c in Sources */,
  4.1287 +				154918B722B940200091B6D6 /* Sync_event.c in Sources */,
  4.1288  				43F6921D1F164A47009418F5 /* resource_id.c in Sources */,
  4.1289 +				15B037AA22B2B822002D664C /* ber_tlv_length.c in Sources */,
  4.1290 +				15B037F822B2B822002D664C /* OwnKeysOfferer.c in Sources */,
  4.1291  				430D258B1C9ED75A00B94535 /* blacklist.c in Sources */,
  4.1292 -				431F0495227322EF00CCE960 /* CommitAcceptFirst.c in Sources */,
  4.1293 +				15B0380E22B2B822002D664C /* PrintableString.c in Sources */,
  4.1294 +				15B037E922B2B822002D664C /* CommitAcceptOfferer.c in Sources */,
  4.1295 +				154918B922B940200091B6D6 /* Sync_func.c in Sources */,
  4.1296  				646C414E1D510D8800C63EFF /* baseprotocol.c in Sources */,
  4.1297 +				15B037C722B2B822002D664C /* per_decoder.c in Sources */,
  4.1298  				6467888C1CEB3D120001F54C /* map_asn1.c in Sources */,
  4.1299 -				646C40FA1D510CD800C63EFF /* ber_tlv_tag.c in Sources */,
  4.1300 -				646C41241D510CD800C63EFF /* NativeInteger.c in Sources */,
  4.1301 -				1521CEFD225C9AEF00FD2AA2 /* pdu_collection.c in Sources */,
  4.1302 -				646C41061D510CD800C63EFF /* constr_SET_OF.c in Sources */,
  4.1303  				43F73C122166282C00AB4524 /* growing_buf.c in Sources */,
  4.1304 -				646C412C1D510CD800C63EFF /* per_opentype.c in Sources */,
  4.1305 -				646C41281D510CD800C63EFF /* per_decoder.c in Sources */,
  4.1306  				64A826801B455D0800EECAF0 /* mime.c in Sources */,
  4.1307 -				431F048D2273223600CCE960 /* CommitAcceptSecond.c in Sources */,
  4.1308  				64A8267F1B455D0800EECAF0 /* message.c in Sources */,
  4.1309 -				43CC34A22276D34C002F77AF /* NegotiationOpen.c in Sources */,
  4.1310 -				646C411A1D510CD800C63EFF /* Identity.c in Sources */,
  4.1311  				64A826811B455D0800EECAF0 /* pEpEngine.c in Sources */,
  4.1312 +				15B037FF22B2B822002D664C /* per_opentype.c in Sources */,
  4.1313  			);
  4.1314  			runOnlyForDeploymentPostprocessing = 0;
  4.1315  		};
  4.1316 @@ -1043,11 +1075,6 @@
  4.1317  			name = "libetpan ios";
  4.1318  			targetProxy = 64289E3E1B8B638800FC617B /* PBXContainerItemProxy */;
  4.1319  		};
  4.1320 -		645922541B8BD53F00A5AF93 /* PBXTargetDependency */ = {
  4.1321 -			isa = PBXTargetDependency;
  4.1322 -			name = netpgp;
  4.1323 -			targetProxy = 645922531B8BD53F00A5AF93 /* PBXContainerItemProxy */;
  4.1324 -		};
  4.1325  /* End PBXTargetDependency section */
  4.1326  
  4.1327  /* Begin XCBuildConfiguration section */
  4.1328 @@ -1075,6 +1102,7 @@
  4.1329  			isa = XCBuildConfiguration;
  4.1330  			buildSettings = {
  4.1331  				ALWAYS_SEARCH_USER_PATHS = NO;
  4.1332 +				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
  4.1333  				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  4.1334  				CLANG_CXX_LIBRARY = "libc++";
  4.1335  				CLANG_ENABLE_MODULES = YES;
  4.1336 @@ -1100,19 +1128,18 @@
  4.1337  				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  4.1338  				COPY_PHASE_STRIP = NO;
  4.1339  				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
  4.1340 +				ENABLE_BITCODE = NO;
  4.1341  				ENABLE_STRICT_OBJC_MSGSEND = YES;
  4.1342  				ENABLE_TESTABILITY = YES;
  4.1343  				GCC_C_LANGUAGE_STANDARD = gnu99;
  4.1344  				GCC_DYNAMIC_NO_PIC = NO;
  4.1345  				GCC_NO_COMMON_BLOCKS = YES;
  4.1346  				GCC_OPTIMIZATION_LEVEL = 0;
  4.1347 -				GCC_PREPROCESSOR_DEFINITIONS = (
  4.1348 -					"DEBUG=1",
  4.1349 -					"USE_NETPGP=1",
  4.1350 -				);
  4.1351 +				GCC_PREPROCESSOR_DEFINITIONS = "USE_SEQUOIA=1";
  4.1352  				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
  4.1353  				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  4.1354  				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  4.1355 +				GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
  4.1356  				GCC_WARN_UNDECLARED_SELECTOR = YES;
  4.1357  				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  4.1358  				GCC_WARN_UNUSED_FUNCTION = YES;
  4.1359 @@ -1120,17 +1147,16 @@
  4.1360  				HEADER_SEARCH_PATHS = (
  4.1361  					"$(inherited)",
  4.1362  					"$(SRCROOT)",
  4.1363 -					"$(SRCROOT)/../../netpgp-et/include/",
  4.1364 -					"$(SRCROOT)/../../netpgp-et/src/",
  4.1365  					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
  4.1366  					"$(SRCROOT)/../asn.1/",
  4.1367 +					"$(PROJECT_DIR)/../../sequoia4ios/build/include",
  4.1368  				);
  4.1369  				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
  4.1370  				MTL_ENABLE_DEBUG_INFO = YES;
  4.1371  				ONLY_ACTIVE_ARCH = YES;
  4.1372  				OTHER_CFLAGS = "-DSQLITE3_FROM_OS";
  4.1373  				SDKROOT = iphoneos;
  4.1374 -				VALID_ARCHS = "arm64 armv7s armv7";
  4.1375 +				VALID_ARCHS = "$(VALID_ARCHS) x86_64";
  4.1376  			};
  4.1377  			name = Debug;
  4.1378  		};
  4.1379 @@ -1138,6 +1164,7 @@
  4.1380  			isa = XCBuildConfiguration;
  4.1381  			buildSettings = {
  4.1382  				ALWAYS_SEARCH_USER_PATHS = NO;
  4.1383 +				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
  4.1384  				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  4.1385  				CLANG_CXX_LIBRARY = "libc++";
  4.1386  				CLANG_ENABLE_MODULES = YES;
  4.1387 @@ -1163,13 +1190,18 @@
  4.1388  				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  4.1389  				COPY_PHASE_STRIP = NO;
  4.1390  				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
  4.1391 +				ENABLE_BITCODE = NO;
  4.1392  				ENABLE_NS_ASSERTIONS = NO;
  4.1393  				ENABLE_STRICT_OBJC_MSGSEND = YES;
  4.1394  				GCC_C_LANGUAGE_STANDARD = gnu99;
  4.1395  				GCC_NO_COMMON_BLOCKS = YES;
  4.1396 -				GCC_PREPROCESSOR_DEFINITIONS = "USE_NETPGP=1";
  4.1397 +				GCC_PREPROCESSOR_DEFINITIONS = (
  4.1398 +					"USE_SEQUOIA=1",
  4.1399 +					NDEBUG,
  4.1400 +				);
  4.1401  				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  4.1402  				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  4.1403 +				GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
  4.1404  				GCC_WARN_UNDECLARED_SELECTOR = YES;
  4.1405  				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  4.1406  				GCC_WARN_UNUSED_FUNCTION = YES;
  4.1407 @@ -1177,10 +1209,9 @@
  4.1408  				HEADER_SEARCH_PATHS = (
  4.1409  					"$(inherited)",
  4.1410  					"$(SRCROOT)",
  4.1411 -					"$(SRCROOT)/../../netpgp-et/include/",
  4.1412 -					"$(SRCROOT)/../../netpgp-et/src/",
  4.1413  					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
  4.1414  					"$(SRCROOT)/../asn.1/",
  4.1415 +					"$(PROJECT_DIR)/../../sequoia4ios/build/include",
  4.1416  				);
  4.1417  				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
  4.1418  				MTL_ENABLE_DEBUG_INFO = NO;
  4.1419 @@ -1188,18 +1219,22 @@
  4.1420  				OTHER_CFLAGS = "-DSQLITE3_FROM_OS";
  4.1421  				SDKROOT = iphoneos;
  4.1422  				VALIDATE_PRODUCT = YES;
  4.1423 -				VALID_ARCHS = "arm64 armv7s armv7";
  4.1424 +				VALID_ARCHS = "$(VALID_ARCHS) x86_64";
  4.1425  			};
  4.1426  			name = Release;
  4.1427  		};
  4.1428  		64796A541B455AA5004B1C24 /* Debug */ = {
  4.1429  			isa = XCBuildConfiguration;
  4.1430  			buildSettings = {
  4.1431 +				GCC_PREPROCESSOR_DEFINITIONS = (
  4.1432 +					"$(inherited)",
  4.1433 +					"DEBUG=1",
  4.1434 +				);
  4.1435  				HEADER_SEARCH_PATHS = "$(inherited)";
  4.1436  				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
  4.1437  				LIBRARY_SEARCH_PATHS = (
  4.1438  					"$(inherited)",
  4.1439 -					"$(PROJECT_DIR)",
  4.1440 +					"$(PROJECT_DIR)/../../Sequoia4iOS/build/lib",
  4.1441  				);
  4.1442  				New_Setting = "";
  4.1443  				ONLY_ACTIVE_ARCH = NO;
  4.1444 @@ -1209,8 +1244,6 @@
  4.1445  				USER_HEADER_SEARCH_PATHS = (
  4.1446  					"$(PROJECT_DIR)/../src",
  4.1447  					"$(PROJECT_DIR)",
  4.1448 -					"$(PROJECT_DIR)/../../netpgp-et/include/",
  4.1449 -					"$(PROJECT_DIR)/../../netpgp-et/src/",
  4.1450  					"$(PROJECT_DIR)/../../OpenSSL-for-iPhone/include",
  4.1451  					"$(PROJECT_DIR)/../asn.1/",
  4.1452  					"$(inherited)",
  4.1453 @@ -1221,11 +1254,12 @@
  4.1454  		64796A551B455AA5004B1C24 /* Release */ = {
  4.1455  			isa = XCBuildConfiguration;
  4.1456  			buildSettings = {
  4.1457 +				GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
  4.1458  				HEADER_SEARCH_PATHS = "$(inherited)";
  4.1459  				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
  4.1460  				LIBRARY_SEARCH_PATHS = (
  4.1461  					"$(inherited)",
  4.1462 -					"$(PROJECT_DIR)",
  4.1463 +					"$(PROJECT_DIR)/../../Sequoia4iOS/build/lib",
  4.1464  				);
  4.1465  				New_Setting = "";
  4.1466  				OTHER_LDFLAGS = "-ObjC";
  4.1467 @@ -1234,8 +1268,6 @@
  4.1468  				USER_HEADER_SEARCH_PATHS = (
  4.1469  					"$(PROJECT_DIR)/../src",
  4.1470  					"$(PROJECT_DIR)",
  4.1471 -					"$(PROJECT_DIR)/../../netpgp-et/include/",
  4.1472 -					"$(PROJECT_DIR)/../../netpgp-et/src/",
  4.1473  					"$(PROJECT_DIR)/../../OpenSSL-for-iPhone/include",
  4.1474  					"$(PROJECT_DIR)/../asn.1/",
  4.1475  					"$(inherited)",
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/build-mac/pEpEngine.xcodeproj/xcshareddata/xcschemes/pEpEngine.xcscheme	Wed Aug 07 14:17:27 2019 +0200
     5.3 @@ -0,0 +1,103 @@
     5.4 +<?xml version="1.0" encoding="UTF-8"?>
     5.5 +<Scheme
     5.6 +   LastUpgradeVersion = "1020"
     5.7 +   version = "1.3">
     5.8 +   <BuildAction
     5.9 +      parallelizeBuildables = "NO"
    5.10 +      buildImplicitDependencies = "YES">
    5.11 +      <BuildActionEntries>
    5.12 +         <BuildActionEntry
    5.13 +            buildForTesting = "YES"
    5.14 +            buildForRunning = "YES"
    5.15 +            buildForProfiling = "YES"
    5.16 +            buildForArchiving = "YES"
    5.17 +            buildForAnalyzing = "YES">
    5.18 +            <BuildableReference
    5.19 +               BuildableIdentifier = "primary"
    5.20 +               BlueprintIdentifier = "159EF1E022B6AB0700149C0C"
    5.21 +               BuildableName = "sequoia.framework"
    5.22 +               BlueprintName = "sequoia"
    5.23 +               ReferencedContainer = "container:../../Sequoia4iOS/Sequoia4iOS.xcodeproj">
    5.24 +            </BuildableReference>
    5.25 +         </BuildActionEntry>
    5.26 +         <BuildActionEntry
    5.27 +            buildForTesting = "YES"
    5.28 +            buildForRunning = "YES"
    5.29 +            buildForProfiling = "YES"
    5.30 +            buildForArchiving = "YES"
    5.31 +            buildForAnalyzing = "YES">
    5.32 +            <BuildableReference
    5.33 +               BuildableIdentifier = "primary"
    5.34 +               BlueprintIdentifier = "64796A3E1B455AA5004B1C24"
    5.35 +               BuildableName = "libpEpEngine.a"
    5.36 +               BlueprintName = "pEpEngine"
    5.37 +               ReferencedContainer = "container:pEpEngine.xcodeproj">
    5.38 +            </BuildableReference>
    5.39 +         </BuildActionEntry>
    5.40 +      </BuildActionEntries>
    5.41 +   </BuildAction>
    5.42 +   <TestAction
    5.43 +      buildConfiguration = "Debug"
    5.44 +      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
    5.45 +      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
    5.46 +      shouldUseLaunchSchemeArgsEnv = "YES">
    5.47 +      <Testables>
    5.48 +      </Testables>
    5.49 +      <MacroExpansion>
    5.50 +         <BuildableReference
    5.51 +            BuildableIdentifier = "primary"
    5.52 +            BlueprintIdentifier = "64796A3E1B455AA5004B1C24"
    5.53 +            BuildableName = "libpEpEngine.a"
    5.54 +            BlueprintName = "pEpEngine"
    5.55 +            ReferencedContainer = "container:pEpEngine.xcodeproj">
    5.56 +         </BuildableReference>
    5.57 +      </MacroExpansion>
    5.58 +      <AdditionalOptions>
    5.59 +      </AdditionalOptions>
    5.60 +   </TestAction>
    5.61 +   <LaunchAction
    5.62 +      buildConfiguration = "Debug"
    5.63 +      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
    5.64 +      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
    5.65 +      launchStyle = "0"
    5.66 +      useCustomWorkingDirectory = "NO"
    5.67 +      ignoresPersistentStateOnLaunch = "NO"
    5.68 +      debugDocumentVersioning = "YES"
    5.69 +      debugServiceExtension = "internal"
    5.70 +      allowLocationSimulation = "YES">
    5.71 +      <MacroExpansion>
    5.72 +         <BuildableReference
    5.73 +            BuildableIdentifier = "primary"
    5.74 +            BlueprintIdentifier = "64796A3E1B455AA5004B1C24"
    5.75 +            BuildableName = "libpEpEngine.a"
    5.76 +            BlueprintName = "pEpEngine"
    5.77 +            ReferencedContainer = "container:pEpEngine.xcodeproj">
    5.78 +         </BuildableReference>
    5.79 +      </MacroExpansion>
    5.80 +      <AdditionalOptions>
    5.81 +      </AdditionalOptions>
    5.82 +   </LaunchAction>
    5.83 +   <ProfileAction
    5.84 +      buildConfiguration = "Release"
    5.85 +      shouldUseLaunchSchemeArgsEnv = "YES"
    5.86 +      savedToolIdentifier = ""
    5.87 +      useCustomWorkingDirectory = "NO"
    5.88 +      debugDocumentVersioning = "YES">
    5.89 +      <MacroExpansion>
    5.90 +         <BuildableReference
    5.91 +            BuildableIdentifier = "primary"
    5.92 +            BlueprintIdentifier = "64796A3E1B455AA5004B1C24"
    5.93 +            BuildableName = "libpEpEngine.a"
    5.94 +            BlueprintName = "pEpEngine"
    5.95 +            ReferencedContainer = "container:pEpEngine.xcodeproj">
    5.96 +         </BuildableReference>
    5.97 +      </MacroExpansion>
    5.98 +   </ProfileAction>
    5.99 +   <AnalyzeAction
   5.100 +      buildConfiguration = "Debug">
   5.101 +   </AnalyzeAction>
   5.102 +   <ArchiveAction
   5.103 +      buildConfiguration = "Release"
   5.104 +      revealArchiveInOrganizer = "YES">
   5.105 +   </ArchiveAction>
   5.106 +</Scheme>
     6.1 --- a/src/aux_mime_msg.c	Thu May 16 17:55:58 2019 +0200
     6.2 +++ b/src/aux_mime_msg.c	Wed Aug 07 14:17:27 2019 +0200
     6.3 @@ -73,7 +73,7 @@
     6.4      message* dec_msg = NULL;
     6.5      *mime_plaintext = NULL;
     6.6  
     6.7 -    status = mime_decode_message(mimetext, size, &tmp_msg);
     6.8 +    status = mime_decode_message(mimetext, size, &tmp_msg, NULL);
     6.9      if (status != PEP_STATUS_OK)
    6.10          goto pEp_error;
    6.11  
    6.12 @@ -120,7 +120,7 @@
    6.13      }
    6.14  
    6.15      if (*flags & PEP_decrypt_flag_src_modified) {
    6.16 -        _mime_encode_message_internal(tmp_msg, false, modified_src, true);
    6.17 +        _mime_encode_message_internal(tmp_msg, false, modified_src, true, false);
    6.18          if (!modified_src) {
    6.19              *flags &= (~PEP_decrypt_flag_src_modified);
    6.20              decrypt_status = PEP_CANNOT_REENCRYPT; // Because we couldn't return it, I guess.
    6.21 @@ -128,7 +128,7 @@
    6.22      }
    6.23  
    6.24      // FIXME: test with att
    6.25 -    status = _mime_encode_message_internal(dec_msg, false, mime_plaintext, true);
    6.26 +    status = _mime_encode_message_internal(dec_msg, false, mime_plaintext, true, false);
    6.27  
    6.28      if (status == PEP_STATUS_OK)
    6.29      {
    6.30 @@ -159,7 +159,7 @@
    6.31      message* tmp_msg = NULL;
    6.32      message* enc_msg = NULL;
    6.33  
    6.34 -    status = mime_decode_message(mimetext, size, &tmp_msg);
    6.35 +    status = mime_decode_message(mimetext, size, &tmp_msg, NULL);
    6.36      if (status != PEP_STATUS_OK)
    6.37          goto pEp_error;
    6.38  
    6.39 @@ -214,7 +214,7 @@
    6.40          goto pEp_error;
    6.41      }
    6.42  
    6.43 -    status = _mime_encode_message_internal(enc_msg, false, mime_ciphertext, false);
    6.44 +    status = _mime_encode_message_internal(enc_msg, false, mime_ciphertext, false, false);
    6.45  
    6.46  pEp_error:
    6.47      free_message(tmp_msg);
    6.48 @@ -239,7 +239,7 @@
    6.49      message* tmp_msg = NULL;
    6.50      message* enc_msg = NULL;
    6.51  
    6.52 -    status = mime_decode_message(mimetext, size, &tmp_msg);
    6.53 +    status = mime_decode_message(mimetext, size, &tmp_msg, NULL);
    6.54      if (status != PEP_STATUS_OK)
    6.55          goto pEp_error;
    6.56  
    6.57 @@ -271,4 +271,3 @@
    6.58  #else
    6.59  const int the_answer_my_friend = 42;
    6.60  #endif
    6.61 -
     7.1 --- a/src/baseprotocol.c	Thu May 16 17:55:58 2019 +0200
     7.2 +++ b/src/baseprotocol.c	Wed Aug 07 14:17:27 2019 +0200
     7.3 @@ -164,7 +164,7 @@
     7.4      char *_fpr = NULL;
     7.5      if (_sign) {
     7.6          status = verify_text(session, _payload, _payload_size, _sign, _sign_size, &keylist);
     7.7 -        if (status != PEP_VERIFIED || !keylist || !keylist->value) {
     7.8 +        if (!(status == PEP_VERIFIED || status == PEP_VERIFIED_AND_TRUSTED) || !keylist || !keylist->value) {
     7.9              // signature invalid or does not match; ignore sync message
    7.10              status = PEP_STATUS_OK;
    7.11              goto the_end;
    7.12 @@ -187,4 +187,3 @@
    7.13      free_stringlist(keylist);
    7.14      return status;
    7.15  }
    7.16 -
     8.1 --- a/src/blacklist.c	Thu May 16 17:55:58 2019 +0200
     8.2 +++ b/src/blacklist.c	Wed Aug 07 14:17:27 2019 +0200
     8.3 @@ -20,7 +20,7 @@
     8.4  
     8.5      int result;
     8.6  
     8.7 -    result = sqlite3_step(session->blacklist_add);
     8.8 +    result = Sqlite3_step(session->blacklist_add);
     8.9      switch (result) {
    8.10      case SQLITE_DONE:
    8.11          status = PEP_STATUS_OK;
    8.12 @@ -50,7 +50,7 @@
    8.13  
    8.14      int result;
    8.15  
    8.16 -    result = sqlite3_step(session->blacklist_delete);
    8.17 +    result = Sqlite3_step(session->blacklist_delete);
    8.18      switch (result) {
    8.19      case SQLITE_DONE:
    8.20          status = PEP_STATUS_OK;
    8.21 @@ -85,7 +85,7 @@
    8.22  
    8.23      int result;
    8.24  
    8.25 -    result = sqlite3_step(session->blacklist_is_listed);
    8.26 +    result = Sqlite3_step(session->blacklist_is_listed);
    8.27      switch (result) {
    8.28      case SQLITE_ROW:
    8.29          count = sqlite3_column_int(session->blacklist_is_listed, 0);
    8.30 @@ -125,7 +125,7 @@
    8.31  
    8.32      stringlist_t *_bl = _blacklist;
    8.33      do {
    8.34 -        result = sqlite3_step(session->blacklist_retrieve);
    8.35 +        result = Sqlite3_step(session->blacklist_retrieve);
    8.36          switch (result) {
    8.37          case SQLITE_ROW:
    8.38          {
     9.1 --- a/src/etpan_mime.c	Thu May 16 17:55:58 2019 +0200
     9.2 +++ b/src/etpan_mime.c	Wed Aug 07 14:17:27 2019 +0200
     9.3 @@ -38,6 +38,7 @@
     9.4  struct mailmime * part_new_empty(
     9.5          struct mailmime_content * content,
     9.6          struct mailmime_fields * mime_fields,
     9.7 +        stringpair_list_t* param_keyvals,
     9.8          int force_single
     9.9      )
    9.10  {
    9.11 @@ -127,6 +128,40 @@
    9.12          if (content->ct_parameters == NULL)
    9.13              content->ct_parameters = parameters;
    9.14      }
    9.15 +    
    9.16 +    if (param_keyvals) {
    9.17 +        stringpair_list_t* cur;
    9.18 +        for (cur = param_keyvals; cur; cur = cur->next) {
    9.19 +            attr_name = strdup(cur->value->key);
    9.20 +            attr_value = strdup(cur->value->value);
    9.21 +            
    9.22 +            param = mailmime_parameter_new(attr_name, attr_value);
    9.23 +            assert(param);
    9.24 +            if (param == NULL)
    9.25 +                goto enomem;
    9.26 +                
    9.27 +            attr_name = NULL;
    9.28 +            attr_value = NULL;
    9.29 +
    9.30 +            if (content->ct_parameters == NULL) {
    9.31 +                parameters = clist_new();
    9.32 +                assert(parameters);
    9.33 +                if (parameters == NULL)
    9.34 +                    goto enomem;
    9.35 +            }
    9.36 +            else {
    9.37 +                parameters = content->ct_parameters;
    9.38 +            }
    9.39 +
    9.40 +            r = clist_append(parameters, param);
    9.41 +            if (r)
    9.42 +                goto enomem;
    9.43 +            param = NULL;
    9.44 +
    9.45 +            if (content->ct_parameters == NULL)
    9.46 +                content->ct_parameters = parameters;            
    9.47 +        }
    9.48 +    }
    9.49  
    9.50      build_info = mailmime_new(mime_type, NULL, 0, mime_fields, content, NULL,
    9.51              NULL, NULL, list, NULL, NULL);
    9.52 @@ -163,7 +198,7 @@
    9.53      if (mime_fields == NULL)
    9.54          goto enomem;
    9.55  
    9.56 -    mime = part_new_empty(content, mime_fields, 1);
    9.57 +    mime = part_new_empty(content, mime_fields, NULL, 1);
    9.58      if (mime == NULL)
    9.59          goto enomem;
    9.60      mime_fields = NULL;
    9.61 @@ -252,7 +287,7 @@
    9.62              goto enomem;
    9.63      }
    9.64  
    9.65 -    mime = part_new_empty(content, mime_fields, 1);
    9.66 +    mime = part_new_empty(content, mime_fields, NULL, 1);
    9.67      if (mime == NULL)
    9.68          goto enomem;
    9.69      content = NULL;
    9.70 @@ -289,7 +324,8 @@
    9.71          const char * mime_type,
    9.72          char * data,
    9.73          size_t length,
    9.74 -        bool transport_encode
    9.75 +        bool transport_encode,
    9.76 +        bool set_attachment_forward_comment
    9.77      )
    9.78  {
    9.79      char * disposition_name = NULL;
    9.80 @@ -351,7 +387,13 @@
    9.81      encoding = NULL;
    9.82      disposition = NULL;
    9.83  
    9.84 -    mime = part_new_empty(content, mime_fields, 1);
    9.85 +    stringpair_list_t* extra_params = NULL;
    9.86 +    
    9.87 +    if (set_attachment_forward_comment)
    9.88 +        extra_params = new_stringpair_list(new_stringpair("forwarded", "no"));
    9.89 +    
    9.90 +    mime = part_new_empty(content, mime_fields, extra_params, 1);
    9.91 +    free_stringpair_list(extra_params);
    9.92      if (mime == NULL)
    9.93          goto enomem;
    9.94      content = NULL;
    9.95 @@ -396,7 +438,7 @@
    9.96      if (content == NULL)
    9.97          goto enomem;
    9.98      
    9.99 -    mp = part_new_empty(content, mime_fields, 0);
   9.100 +    mp = part_new_empty(content, mime_fields, NULL, 0);
   9.101      if (mp == NULL)
   9.102          goto enomem;
   9.103      
   9.104 @@ -815,6 +857,22 @@
   9.105      return false;
   9.106  }
   9.107  
   9.108 +bool _is_message_part(struct mailmime_content *content, const char* subtype) {
   9.109 +    assert(content);
   9.110 +    if (content->ct_type && content->ct_type->tp_type == MAILMIME_TYPE_COMPOSITE_TYPE &&
   9.111 +            content->ct_type->tp_data.tp_composite_type &&
   9.112 +            content->ct_type->tp_data.tp_composite_type->ct_type ==
   9.113 +            MAILMIME_COMPOSITE_TYPE_MESSAGE) {
   9.114 +        if (subtype)
   9.115 +            return content->ct_subtype &&
   9.116 +                    strcasecmp(content->ct_subtype, subtype) == 0;
   9.117 +        else
   9.118 +            return true;                
   9.119 +    }
   9.120 +    
   9.121 +    return false;
   9.122 +}
   9.123 +
   9.124  int _get_content_type(
   9.125          const struct mailmime_content *content,
   9.126          char **type,
   9.127 @@ -948,7 +1006,8 @@
   9.128  #endif
   9.129  
   9.130  static PEP_STATUS interpret_MIME(struct mailmime *mime,
   9.131 -                                 message *msg);
   9.132 +                                 message *msg,
   9.133 +                                 bool* raise_msg_attachment);
   9.134  
   9.135  // This function was rewritten to use in-memory buffers instead of
   9.136  // temporary files when the pgp/mime support was implemented for
   9.137 @@ -1006,7 +1065,8 @@
   9.138  static PEP_STATUS mime_attachment(
   9.139          bloblist_t *blob,
   9.140          struct mailmime **result,
   9.141 -        bool transport_encode
   9.142 +        bool transport_encode,
   9.143 +        bool set_attachment_forward_comment
   9.144      )
   9.145  {
   9.146      PEP_STATUS status = PEP_STATUS_OK;
   9.147 @@ -1031,7 +1091,8 @@
   9.148      bool already_ascii = !(must_chunk_be_encoded(blob->value, blob->size, true));
   9.149  
   9.150      mime = get_file_part(resource, mime_type, blob->value, blob->size, 
   9.151 -                          (already_ascii ? false : transport_encode));
   9.152 +                          (already_ascii ? false : transport_encode),
   9.153 +                          set_attachment_forward_comment);
   9.154      free_rid_list(resource);
   9.155      
   9.156      assert(mime);
   9.157 @@ -1155,7 +1216,7 @@
   9.158      for (_a = attachments; _a != NULL; _a = _a->next) {
   9.159          if (_a->disposition != PEP_CONTENT_DISP_INLINE)
   9.160              continue;
   9.161 -        status = mime_attachment(_a, &submime, transport_encode);
   9.162 +        status = mime_attachment(_a, &submime, transport_encode, false);
   9.163          if (status != PEP_STATUS_OK)
   9.164              return PEP_UNKNOWN_ERROR; // FIXME
   9.165  
   9.166 @@ -1632,7 +1693,8 @@
   9.167          const message *msg,
   9.168          bool omit_fields,
   9.169          struct mailmime **result,
   9.170 -        bool transport_encode
   9.171 +        bool transport_encode,
   9.172 +        bool set_attachment_forward_comment
   9.173      )
   9.174  {
   9.175      struct mailmime * mime = NULL;
   9.176 @@ -1711,14 +1773,19 @@
   9.177          }
   9.178  
   9.179          bloblist_t *_a;
   9.180 +        bool first_one = true;
   9.181 +        
   9.182          for (_a = msg->attachments; _a != NULL; _a = _a->next) {
   9.183  
   9.184              if (_a->disposition == PEP_CONTENT_DISP_INLINE)
   9.185                  continue;
   9.186  
   9.187 -            status = mime_attachment(_a, &submime, transport_encode);
   9.188 +            status = mime_attachment(_a, &submime, transport_encode,
   9.189 +                                     (first_one && set_attachment_forward_comment));                         
   9.190              if (status != PEP_STATUS_OK)
   9.191                  goto pEp_error;
   9.192 +            
   9.193 +            first_one = false;    
   9.194  
   9.195              r = mailmime_smart_add_part(mime, submime);
   9.196              assert(r == MAILIMF_NO_ERROR);
   9.197 @@ -1830,7 +1897,8 @@
   9.198          const message * msg,
   9.199          bool omit_fields,
   9.200          char **mimetext,
   9.201 -        bool transport_encode
   9.202 +        bool transport_encode,
   9.203 +        bool set_attachment_forward_comment
   9.204      )
   9.205  {
   9.206      PEP_STATUS status = PEP_STATUS_OK;
   9.207 @@ -1850,11 +1918,12 @@
   9.208  
   9.209      switch (msg->enc_format) {
   9.210          case PEP_enc_none:
   9.211 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
   9.212 +            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode, set_attachment_forward_comment);
   9.213              break;
   9.214  
   9.215 +        // I'm presuming we should hardcore ignoring set_attachment_forward_comment here...
   9.216          case PEP_enc_inline:
   9.217 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
   9.218 +            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode, false);
   9.219              break;
   9.220  
   9.221          case PEP_enc_S_MIME:
   9.222 @@ -2402,7 +2471,7 @@
   9.223          // ???
   9.224          // This is what we would have done before, so... no
   9.225          // worse than the status quo. But FIXME!
   9.226 -        status = interpret_MIME(part, msg);
   9.227 +        status = interpret_MIME(part, msg, NULL);
   9.228          if (status)
   9.229              return status;
   9.230      }
   9.231 @@ -2417,7 +2486,7 @@
   9.232          if (content == NULL)
   9.233              return PEP_ILLEGAL_VALUE;
   9.234  
   9.235 -        status = interpret_MIME(part, msg);
   9.236 +        status = interpret_MIME(part, msg, NULL);
   9.237          if (status)
   9.238              return status;
   9.239      }
   9.240 @@ -2426,7 +2495,8 @@
   9.241  
   9.242  static PEP_STATUS interpret_MIME(
   9.243          struct mailmime *mime,
   9.244 -        message *msg
   9.245 +        message *msg,
   9.246 +        bool* raise_msg_attachment
   9.247      )
   9.248  {
   9.249      PEP_STATUS status = PEP_STATUS_OK;
   9.250 @@ -2476,7 +2546,7 @@
   9.251                          return status;
   9.252                  }
   9.253                  else /* add as attachment */ {
   9.254 -                    status = interpret_MIME(part, msg);
   9.255 +                    status = interpret_MIME(part, msg, NULL);
   9.256                      if (status)
   9.257                          return status;
   9.258                  }
   9.259 @@ -2499,7 +2569,7 @@
   9.260                  if (part == NULL)
   9.261                      return PEP_ILLEGAL_VALUE;
   9.262  
   9.263 -                status = interpret_MIME(part, msg);
   9.264 +                status = interpret_MIME(part, msg, NULL);
   9.265                  if (status != PEP_STATUS_OK)
   9.266                      return status;
   9.267              }
   9.268 @@ -2510,11 +2580,13 @@
   9.269                  return PEP_ILLEGAL_VALUE;
   9.270  
   9.271              clistiter *cur;
   9.272 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
   9.273 +            // only add raise_msg_attachment on 2nd part!
   9.274 +            int _att_count = 0;
   9.275 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur), _att_count++) {
   9.276                  struct mailmime *part= clist_content(cur);
   9.277                  if (part == NULL)
   9.278                      return PEP_ILLEGAL_VALUE;
   9.279 -                status = interpret_MIME(part, msg);
   9.280 +                status = interpret_MIME(part, msg, _att_count == 1 ? raise_msg_attachment : NULL);
   9.281                  if (status != PEP_STATUS_OK)
   9.282                      return status;
   9.283              }
   9.284 @@ -2547,6 +2619,25 @@
   9.285                      return status;
   9.286              }
   9.287              else {
   9.288 +                // Fixme - we need a control on recursion level here - KG: maybe NOT. We only go to depth 1.
   9.289 +                if (raise_msg_attachment != NULL) {
   9.290 +                    bool is_msg = (_is_message_part(content, "rfc822") || _is_text_part(content, "rfc822"));
   9.291 +                    if (is_msg) {
   9.292 +                        if (content->ct_parameters) {
   9.293 +                            clistiter *cur;
   9.294 +                            for (cur = clist_begin(content->ct_parameters); cur; cur =
   9.295 +                                 clist_next(cur)) {
   9.296 +                                struct mailmime_parameter * param = clist_content(cur);
   9.297 +                                if (param && param->pa_name && strcasecmp(param->pa_name, "forwarded") == 0) {
   9.298 +                                    if (param->pa_value && strcasecmp(param->pa_value, "no") == 0) {
   9.299 +                                        *raise_msg_attachment = true;
   9.300 +                                        break;
   9.301 +                                    }
   9.302 +                                }
   9.303 +                            }
   9.304 +                        }
   9.305 +                    }
   9.306 +                }
   9.307                  char *data = NULL;
   9.308                  size_t size = 0;
   9.309                  char * mime_type;
   9.310 @@ -2633,7 +2724,8 @@
   9.311  DYNAMIC_API PEP_STATUS mime_decode_message(
   9.312          const char *mimetext,
   9.313          size_t size,
   9.314 -        message **msg
   9.315 +        message **msg,
   9.316 +        bool* raise_msg_attachment
   9.317      )
   9.318  {
   9.319      PEP_STATUS status = PEP_STATUS_OK;
   9.320 @@ -2677,7 +2769,7 @@
   9.321  
   9.322      if (content) {
   9.323          status = interpret_MIME(mime->mm_data.mm_message.mm_msg_mime,
   9.324 -                _msg);
   9.325 +                _msg, raise_msg_attachment);
   9.326          if (status != PEP_STATUS_OK)
   9.327              goto pEp_error;
   9.328      }
   9.329 @@ -2702,4 +2794,3 @@
   9.330  
   9.331      return status;
   9.332  }
   9.333 -
    10.1 --- a/src/etpan_mime.h	Thu May 16 17:55:58 2019 +0200
    10.2 +++ b/src/etpan_mime.h	Wed Aug 07 14:17:27 2019 +0200
    10.3 @@ -8,10 +8,12 @@
    10.4  #include <libetpan/mailmime_encode.h>
    10.5  
    10.6  #include "resource_id.h"
    10.7 +#include "stringpair.h"
    10.8  
    10.9  struct mailmime * part_new_empty(
   10.10          struct mailmime_content * content,
   10.11          struct mailmime_fields * mime_fields,
   10.12 +        stringpair_list_t* param_keyvals,        
   10.13          int force_single
   10.14      );
   10.15  
   10.16 @@ -30,7 +32,8 @@
   10.17          const char * mime_type,
   10.18          char * data,
   10.19          size_t length,
   10.20 -        bool transport_encode
   10.21 +        bool transport_encode,
   10.22 +        bool set_attachment_forward_comment
   10.23      );
   10.24  
   10.25  struct mailmime * part_multiple_new(const char *type);
    11.1 --- a/src/identity_list.c	Thu May 16 17:55:58 2019 +0200
    11.2 +++ b/src/identity_list.c	Wed Aug 07 14:17:27 2019 +0200
    11.3 @@ -108,6 +108,23 @@
    11.4      return list_curr->next;
    11.5  }
    11.6  
    11.7 +// returns *head* of list
    11.8 +DYNAMIC_API identity_list* identity_list_join(identity_list *first_list, identity_list *second_list) {
    11.9 +    if (!first_list) {
   11.10 +        if (!second_list)
   11.11 +            return NULL;
   11.12 +        return second_list;
   11.13 +    }
   11.14 +    if (second_list) {
   11.15 +        identity_list* list_curr = first_list;
   11.16 +        while (list_curr->next)
   11.17 +            list_curr = list_curr->next;    
   11.18 +            
   11.19 +        list_curr->next = second_list;
   11.20 +    }        
   11.21 +    return first_list;    
   11.22 +}
   11.23 +
   11.24  DYNAMIC_API int identity_list_length(const identity_list *id_list)
   11.25  {
   11.26      int len = 0;
    12.1 --- a/src/identity_list.h	Thu May 16 17:55:58 2019 +0200
    12.2 +++ b/src/identity_list.h	Wed Aug 07 14:17:27 2019 +0200
    12.3 @@ -63,6 +63,16 @@
    12.4  
    12.5  DYNAMIC_API identity_list *identity_list_add(identity_list *id_list, pEp_identity *ident);
    12.6  
    12.7 +// identity_list_add - join second identity_list to the first.
    12.8 +//
    12.9 +//  parameters:
   12.10 +//      first_list (in)             identity_list to add to
   12.11 +//      second_list (in)            identity list to add
   12.12 +//
   12.13 +//  return value:
   12.14 +//      pointer to the HEAD of the new list, or NULL if both lists are empty.
   12.15 +//
   12.16 +DYNAMIC_API identity_list *identity_list_join(identity_list *first_list, identity_list* second_list);
   12.17  
   12.18  // identity_list_length() - get length of identity_list
   12.19  //
   12.20 @@ -73,9 +83,7 @@
   12.21  //      length of identity_list in number of elements
   12.22  
   12.23  DYNAMIC_API int identity_list_length(const identity_list *id_list);
   12.24 -
   12.25 -
   12.26 +    
   12.27  #ifdef __cplusplus
   12.28  }
   12.29  #endif
   12.30 -
    13.1 --- a/src/key_reset.c	Thu May 16 17:55:58 2019 +0200
    13.2 +++ b/src/key_reset.c	Wed Aug 07 14:17:27 2019 +0200
    13.3 @@ -39,7 +39,7 @@
    13.4              SQLITE_STATIC);
    13.5      sqlite3_bind_text(session->was_id_for_revoke_contacted, 2, user_id, -1,
    13.6              SQLITE_STATIC);        
    13.7 -    int result = sqlite3_step(session->was_id_for_revoke_contacted);
    13.8 +    int result = Sqlite3_step(session->was_id_for_revoke_contacted);
    13.9      switch (result) {
   13.10          case SQLITE_ROW: {
   13.11              *contacted = (sqlite3_column_int(session->was_id_for_revoke_contacted, 0) != 0);
   13.12 @@ -79,7 +79,7 @@
   13.13  
   13.14      int result;
   13.15      
   13.16 -    result = sqlite3_step(session->set_revoke_contact_as_notified);
   13.17 +    result = Sqlite3_step(session->set_revoke_contact_as_notified);
   13.18      switch (result) {
   13.19          case SQLITE_DONE:
   13.20              status = PEP_STATUS_OK;
    14.1 --- a/src/keymanagement.c	Thu May 16 17:55:58 2019 +0200
    14.2 +++ b/src/keymanagement.c	Wed Aug 07 14:17:27 2019 +0200
    14.3 @@ -282,7 +282,7 @@
    14.4  
    14.5      int result = -1;
    14.6      
    14.7 -    while ((result = sqlite3_step(session->get_all_keys_for_user)) == SQLITE_ROW) {
    14.8 +    while ((result = Sqlite3_step(session->get_all_keys_for_user)) == SQLITE_ROW) {
    14.9          const char* keyres = (const char *) sqlite3_column_text(session->get_all_keys_for_user, 0);
   14.10          if (keyres) {
   14.11              if (_kl)
   14.12 @@ -317,7 +317,7 @@
   14.13      sqlite3_bind_text(session->get_user_default_key, 1, user_id, 
   14.14                        -1, SQLITE_STATIC);
   14.15      
   14.16 -    const int result = sqlite3_step(session->get_user_default_key);
   14.17 +    const int result = Sqlite3_step(session->get_user_default_key);
   14.18      char* user_fpr = NULL;
   14.19      if (result == SQLITE_ROW) {
   14.20          const char* u_fpr =
   14.21 @@ -454,7 +454,11 @@
   14.22      
   14.23      if (pEp_user) {
   14.24          PEP_comm_type confirmation_status = identity->comm_type & PEP_ct_confirmed;
   14.25 -        identity->comm_type = PEP_ct_pEp_unconfirmed | confirmation_status;    
   14.26 +        identity->comm_type = PEP_ct_pEp_unconfirmed | confirmation_status;
   14.27 +        if (identity->major_ver == 0) {
   14.28 +            identity->major_ver = 2;
   14.29 +            identity->minor_ver = 0;
   14.30 +        }    
   14.31      }
   14.32  }
   14.33  
   14.34 @@ -470,6 +474,8 @@
   14.35      PEP_STATUS status;
   14.36      
   14.37      bool is_identity_default, is_user_default, is_address_default;
   14.38 +    bool no_stored_default = EMPTYSTR(stored_ident->fpr);
   14.39 +    
   14.40      status = get_valid_pubkey(session, stored_ident,
   14.41                                  &is_identity_default,
   14.42                                  &is_user_default,
   14.43 @@ -488,7 +494,12 @@
   14.44              stored_ident->comm_type = ct;
   14.45          }
   14.46      }
   14.47 -    else {
   14.48 +    else if (status != PEP_STATUS_OK) {
   14.49 +        free(stored_ident->fpr);
   14.50 +        stored_ident->fpr = NULL;
   14.51 +        stored_ident->comm_type = PEP_ct_key_not_found;        
   14.52 +    }
   14.53 +    else { // no key returned, but status ok?
   14.54          if (stored_ident->comm_type == PEP_ct_unknown)
   14.55              stored_ident->comm_type = PEP_ct_key_not_found;
   14.56      }
   14.57 @@ -521,6 +532,9 @@
   14.58      
   14.59      return_id->me = stored_ident->me;
   14.60      
   14.61 +    return_id->major_ver = stored_ident->major_ver;
   14.62 +    return_id->minor_ver = stored_ident->minor_ver;
   14.63 +
   14.64      // FIXME: Do we ALWAYS do this? We probably should...
   14.65      if (EMPTYSTR(return_id->user_id)) {
   14.66          free(return_id->user_id);
   14.67 @@ -536,8 +550,17 @@
   14.68           // or identity AND is valid for this address, set in DB
   14.69           // as default
   14.70           status = set_identity(session, return_id);
   14.71 +    } 
   14.72 +    else if (no_stored_default && !EMPTYSTR(return_id->fpr) 
   14.73 +             && return_id->comm_type != PEP_ct_key_revoked
   14.74 +             && return_id->comm_type != PEP_ct_key_expired
   14.75 +             && return_id->comm_type != PEP_ct_key_expired_but_confirmed
   14.76 +             && return_id->comm_type != PEP_ct_mistrusted 
   14.77 +             && return_id->comm_type != PEP_ct_key_b0rken) { 
   14.78 +        // We would have stored this anyway for a first-time elected key. We just have an ident w/ no default already.
   14.79 +        status = set_identity(session, return_id);
   14.80      }
   14.81 -    else {
   14.82 +    else { // this is a key other than the default, but there IS a default (FIXME: fdik, do we really want behaviour below?)
   14.83          // Store without default fpr/ct, but return the fpr and ct 
   14.84          // for current use
   14.85          char* save_fpr = return_id->fpr;
   14.86 @@ -553,7 +576,7 @@
   14.87      }
   14.88      
   14.89      transfer_ident_lang_and_flags(return_id, stored_ident);
   14.90 -    
   14.91 +        
   14.92      if (return_id->comm_type == PEP_ct_unknown)
   14.93          return_id->comm_type = PEP_ct_key_not_found;
   14.94      
   14.95 @@ -1060,6 +1083,9 @@
   14.96          if (read_only) {
   14.97              free(identity->user_id);
   14.98              identity->user_id = strdup(default_own_id);
   14.99 +            assert(identity->user_id);
  14.100 +            if (!identity->user_id)
  14.101 +                return PEP_OUT_OF_MEMORY;
  14.102          }
  14.103          else {
  14.104              status = set_userid_alias(session, default_own_id, identity->user_id);
  14.105 @@ -1069,6 +1095,7 @@
  14.106                  
  14.107              free(identity->user_id);
  14.108              identity->user_id = strdup(default_own_id);
  14.109 +            assert(identity->user_id);
  14.110              if (identity->user_id == NULL) {
  14.111                  status = PEP_OUT_OF_MEMORY;
  14.112                  goto pEp_free;
  14.113 @@ -1108,11 +1135,14 @@
  14.114      if (EMPTYSTR(identity->username) || read_only) {
  14.115          bool stored_uname = (stored_identity && !EMPTYSTR(stored_identity->username));
  14.116          char* uname = (stored_uname ? stored_identity->username : identity->address);
  14.117 -        free(identity->username);
  14.118 -        identity->username = strdup(uname);
  14.119 -        if (identity->username == NULL) {
  14.120 -            status = PEP_OUT_OF_MEMORY;
  14.121 -            goto pEp_free;
  14.122 +        if (uname) {
  14.123 +            free(identity->username);
  14.124 +            identity->username = strdup(uname);
  14.125 +            assert(identity->username);
  14.126 +            if (identity->username == NULL) {
  14.127 +                status = PEP_OUT_OF_MEMORY;
  14.128 +                goto pEp_free;
  14.129 +            }
  14.130          }
  14.131      }
  14.132  
  14.133 @@ -1198,6 +1228,12 @@
  14.134          identity->comm_type = PEP_ct_unknown;
  14.135      }
  14.136      
  14.137 +    int major_ver = 0;
  14.138 +    int minor_ver = 0;
  14.139 +    pEp_version_major_minor(PEP_VERSION, &major_ver, &minor_ver);
  14.140 +    identity->major_ver = major_ver;
  14.141 +    identity->minor_ver = minor_ver;
  14.142 +    
  14.143      // We want to set an identity in the DB even if a key isn't found, but we have to preserve the status if
  14.144      // it's NOT ok
  14.145      if (!read_only) {
  14.146 @@ -1614,7 +1650,7 @@
  14.147      
  14.148      int result;
  14.149      
  14.150 -    result = sqlite3_step(session->own_key_is_listed);
  14.151 +    result = Sqlite3_step(session->own_key_is_listed);
  14.152      switch (result) {
  14.153          case SQLITE_ROW:
  14.154              count = sqlite3_column_int(session->own_key_is_listed, 0);
  14.155 @@ -1664,7 +1700,7 @@
  14.156      sqlite3_bind_int(session->own_identities_retrieve, 1, excluded_flags);
  14.157  
  14.158      do {
  14.159 -        result = sqlite3_step(session->own_identities_retrieve);
  14.160 +        result = Sqlite3_step(session->own_identities_retrieve);
  14.161          switch (result) {
  14.162              case SQLITE_ROW:
  14.163                  address = (const char *)
  14.164 @@ -1758,7 +1794,7 @@
  14.165      sqlite3_bind_int(session->own_keys_retrieve, 1, excluded_flags);
  14.166  
  14.167      do {        
  14.168 -        result = sqlite3_step(session->own_keys_retrieve);
  14.169 +        result = Sqlite3_step(session->own_keys_retrieve);
  14.170          switch (result) {
  14.171              case SQLITE_ROW:
  14.172                  _bl = stringlist_add(_bl, (const char *)
  14.173 @@ -1899,7 +1935,7 @@
  14.174      sqlite3_bind_text(session->add_mistrusted_key, 1, fpr, -1,
  14.175              SQLITE_STATIC);
  14.176  
  14.177 -    result = sqlite3_step(session->add_mistrusted_key);
  14.178 +    result = Sqlite3_step(session->add_mistrusted_key);
  14.179      sqlite3_reset(session->add_mistrusted_key);
  14.180  
  14.181      if (result != SQLITE_DONE)
  14.182 @@ -1921,7 +1957,7 @@
  14.183      sqlite3_bind_text(session->delete_mistrusted_key, 1, fpr, -1,
  14.184              SQLITE_STATIC);
  14.185  
  14.186 -    result = sqlite3_step(session->delete_mistrusted_key);
  14.187 +    result = Sqlite3_step(session->delete_mistrusted_key);
  14.188      sqlite3_reset(session->delete_mistrusted_key);
  14.189  
  14.190      if (result != SQLITE_DONE)
  14.191 @@ -1948,7 +1984,7 @@
  14.192  
  14.193      int result;
  14.194  
  14.195 -    result = sqlite3_step(session->is_mistrusted_key);
  14.196 +    result = Sqlite3_step(session->is_mistrusted_key);
  14.197      switch (result) {
  14.198      case SQLITE_ROW:
  14.199          *mistrusted = sqlite3_column_int(session->is_mistrusted_key, 0);
    15.1 --- a/src/map_asn1.c	Thu May 16 17:55:58 2019 +0200
    15.2 +++ b/src/map_asn1.c	Wed Aug 07 14:17:27 2019 +0200
    15.3 @@ -134,11 +134,15 @@
    15.4      if (!list)
    15.5          return NULL;
    15.6  
    15.7 -    if (allocated)
    15.8 +    if (allocated) {
    15.9          result = (IdentityList_t *) calloc(1, sizeof(IdentityList_t));
   15.10 -    assert(result);
   15.11 -    if (!result)
   15.12 -        return NULL;
   15.13 +        assert(result);
   15.14 +        if (!result)
   15.15 +            return NULL;
   15.16 +    }
   15.17 +    else {
   15.18 +        asn_sequence_empty(result);
   15.19 +    }
   15.20  
   15.21      for (const identity_list *l = list; l && l->ident; l=l->next) {
   15.22          Identity_t *ident = Identity_from_Struct(l->ident, NULL);
    16.1 --- a/src/message.c	Thu May 16 17:55:58 2019 +0200
    16.2 +++ b/src/message.c	Wed Aug 07 14:17:27 2019 +0200
    16.3 @@ -44,6 +44,7 @@
    16.4          free_stringlist(msg->keywords);
    16.5          free(msg->comments);
    16.6          free_stringpair_list(msg->opt_fields);
    16.7 +        free(msg->_sender_fpr);
    16.8          free(msg);
    16.9      }
   16.10  }
   16.11 @@ -185,6 +186,12 @@
   16.12              goto enomem;
   16.13      }
   16.14  
   16.15 +    if (src->_sender_fpr) {
   16.16 +        msg->_sender_fpr = strdup(src->_sender_fpr);
   16.17 +        if (msg->_sender_fpr == NULL)
   16.18 +            goto enomem;
   16.19 +    }
   16.20 +    
   16.21      msg->enc_format = src->enc_format;
   16.22  
   16.23      return msg;
   16.24 @@ -218,13 +225,15 @@
   16.25      free(dst->longmsg);
   16.26      free(dst->longmsg_formatted);
   16.27      free(dst->comments);
   16.28 +    free(dst->_sender_fpr);
   16.29      dst->id = src->id;
   16.30      dst->shortmsg = src->shortmsg;
   16.31      dst->longmsg = src->longmsg;
   16.32      dst->longmsg_formatted = src->longmsg_formatted;
   16.33      dst->comments = src->comments;    
   16.34 +    dst->_sender_fpr = src->_sender_fpr;
   16.35      src->id = src->shortmsg = src->longmsg = src->longmsg_formatted = NULL;
   16.36 -    src->comments = NULL;
   16.37 +    src->comments = src->_sender_fpr = NULL;
   16.38      
   16.39      /* bloblists */
   16.40      free_bloblist(dst->attachments);
    17.1 --- a/src/message_api.c	Thu May 16 17:55:58 2019 +0200
    17.2 +++ b/src/message_api.c	Wed Aug 07 14:17:27 2019 +0200
    17.3 @@ -33,58 +33,6 @@
    17.4      return false;
    17.5  }
    17.6  
    17.7 -static bool is_wrapper(message* src)
    17.8 -{
    17.9 -    bool retval = false;
   17.10 -    
   17.11 -    if (src) {
   17.12 -        unsigned char pEpstr[] = PEP_SUBJ_STRING;
   17.13 -        if (is_a_pEpmessage(src) || (src->shortmsg == NULL || strcmp(src->shortmsg, "pEp") == 0 ||
   17.14 -            _unsigned_signed_strcmp(pEpstr, src->shortmsg, PEP_SUBJ_BYTELEN) == 0) ||
   17.15 -            (strcmp(src->shortmsg, "p=p") == 0)) {
   17.16 -            char* plaintext = src->longmsg;
   17.17 -            if (plaintext) {
   17.18 -                const char *line_end = strchr(plaintext, '\n');
   17.19 -
   17.20 -                if (line_end != NULL) {
   17.21 -                    size_t n = line_end - plaintext;
   17.22 -                    
   17.23 -                    char* copycat = calloc(n + 1, 1);
   17.24 -                    
   17.25 -                    if (copycat) {
   17.26 -                        strlcpy(copycat, plaintext, n+1);
   17.27 -                        
   17.28 -                        if (strstr(copycat, PEP_MSG_WRAP_KEY) && strstr(copycat, "OUTER"))
   17.29 -                            retval = true;
   17.30 -                        
   17.31 -                        free(copycat);
   17.32 -                    }
   17.33 -                }
   17.34 -            }
   17.35 -        }
   17.36 -    }
   17.37 -    return retval;
   17.38 -}
   17.39 -
   17.40 -
   17.41 -/*
   17.42 - * static stringpair_t* search_optfields(const message* msg, const char* key) {
   17.43 - *     if (msg && key) {
   17.44 - *         stringpair_list_t* opt_fields = msg->opt_fields;
   17.45 - *         
   17.46 - *         const stringpair_list_t* curr;
   17.47 - *         
   17.48 - *         for (curr = opt_fields; curr && curr->value; curr = curr->next) {
   17.49 - *             if (curr->value->key) {
   17.50 - *                 if (strcasecmp(curr->value->key, key) == 0)
   17.51 - *                     return curr->value;
   17.52 - *             }
   17.53 - *         } 
   17.54 - *     }
   17.55 - *     return NULL;
   17.56 - * }
   17.57 - */
   17.58 -
   17.59  static char * keylist_to_string(const stringlist_t *keylist)
   17.60  {
   17.61      if (keylist) {
   17.62 @@ -890,7 +838,7 @@
   17.63  }
   17.64  
   17.65  static message* wrap_message_as_attachment(message* envelope, 
   17.66 -    message* attachment, message_wrap_type wrap_type, bool keep_orig_subject) {
   17.67 +    message* attachment, message_wrap_type wrap_type, bool keep_orig_subject, unsigned int max_major, unsigned int max_minor) {
   17.68      
   17.69      if (!attachment)
   17.70          return NULL;
   17.71 @@ -916,10 +864,22 @@
   17.72              default:
   17.73                  inner_type_string = "INNER";
   17.74          }
   17.75 -        attachment->longmsg = encapsulate_message_wrap_info(inner_type_string, attachment->longmsg);
   17.76 -        _envelope->longmsg = encapsulate_message_wrap_info("OUTER", _envelope->longmsg);
   17.77 +        if (max_major < 2 || (max_major == 2 && max_minor == 0)) {
   17.78 +            attachment->longmsg = encapsulate_message_wrap_info(inner_type_string, attachment->longmsg);        
   17.79 +            _envelope->longmsg = encapsulate_message_wrap_info("OUTER", _envelope->longmsg);
   17.80 +        }
   17.81 +        else {
   17.82 +            _envelope->longmsg = strdup(
   17.83 +                "This message was encrypted with p≡p (https://pep.software). If you are seeing this message,\n" 
   17.84 +                "your client does not support raising message attachments. Please click on the message attachment to\n"
   17.85 +                "to view it, or better yet, consider using p≡p!\n"
   17.86 +            );
   17.87 +        }
   17.88 +        // 2.1, to replace the above
   17.89 +        add_opt_field(attachment, X_PEP_MSG_WRAP_KEY, inner_type_string); 
   17.90      }
   17.91      else if (_envelope) {
   17.92 +        // 2.1 - how do we peel this particular union when we get there?
   17.93          _envelope->longmsg = encapsulate_message_wrap_info("TRANSPORT", _envelope->longmsg);
   17.94      }
   17.95      else {
   17.96 @@ -955,7 +915,7 @@
   17.97                );
   17.98              
   17.99      /* Turn message into a MIME-blob */
  17.100 -    status = _mime_encode_message_internal(attachment, false, &message_text, true);
  17.101 +    status = _mime_encode_message_internal(attachment, false, &message_text, true, false);
  17.102          
  17.103      if (status != PEP_STATUS_OK)
  17.104          goto enomem;
  17.105 @@ -1035,7 +995,8 @@
  17.106      const message *src,
  17.107      stringlist_t *keys,
  17.108      message *dst,
  17.109 -    PEP_encrypt_flags_t flags
  17.110 +    PEP_encrypt_flags_t flags,
  17.111 +    message_wrap_type wrap_type
  17.112      )
  17.113  {
  17.114      PEP_STATUS status = PEP_STATUS_OK;
  17.115 @@ -1059,8 +1020,11 @@
  17.116      _src->longmsg_formatted = src->longmsg_formatted;
  17.117      _src->attachments = src->attachments;
  17.118      _src->enc_format = PEP_enc_none;
  17.119 -    bool mime_encode = !is_wrapper(_src);
  17.120 -    status = _mime_encode_message_internal(_src, true, &mimetext, mime_encode);
  17.121 +    
  17.122 +    // These vars are here to be clear, and because I don't know how this may change in the near future.
  17.123 +    bool wrapped = (wrap_type != PEP_message_unwrapped);
  17.124 +    bool mime_encode = !wrapped;
  17.125 +    status = _mime_encode_message_internal(_src, true, &mimetext, mime_encode, wrapped);
  17.126      assert(status == PEP_STATUS_OK);
  17.127      if (status != PEP_STATUS_OK)
  17.128          goto pEp_error;
  17.129 @@ -1124,8 +1088,9 @@
  17.130          return false;
  17.131      if (msg->attachments->next->next)
  17.132          return false;
  17.133 -    if (!msg->attachments->mime_type ||
  17.134 -        strcmp(msg->attachments->mime_type, "application/pgp-encrypted") != 0)    
  17.135 +    if (!msg->attachments->mime_type)
  17.136 +        return false;        
  17.137 +    if (strcmp(msg->attachments->mime_type, "application/pgp-encrypted") != 0)    
  17.138          return false;
  17.139      if (!msg->attachments->next->mime_type || 
  17.140          strcmp(msg->attachments->next->mime_type, "application/octet-stream") != 0)        
  17.141 @@ -1578,7 +1543,7 @@
  17.142  PEP_STATUS _attach_key(PEP_SESSION session, const char* fpr, message *msg)
  17.143  {
  17.144      char *keydata = NULL;
  17.145 -    size_t size;
  17.146 +    size_t size = 0;
  17.147  
  17.148      PEP_STATUS status = export_key(session, fpr, &keydata, &size);
  17.149      assert(status == PEP_STATUS_OK);
  17.150 @@ -1586,7 +1551,7 @@
  17.151          return status;
  17.152      assert(size);
  17.153  
  17.154 -     bloblist_t *bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
  17.155 +    bloblist_t *bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
  17.156                        "file://pEpkey.asc");
  17.157  
  17.158      if (msg->attachments == NULL && bl)
  17.159 @@ -1755,7 +1720,10 @@
  17.160      bool has_pEp_user = false;
  17.161      
  17.162      PEP_comm_type max_comm_type = PEP_ct_pEp;
  17.163 -
  17.164 +    unsigned int max_version_major = 0;
  17.165 +    unsigned int max_version_minor = 0;
  17.166 +    pEp_version_major_minor(PEP_VERSION, &max_version_major, &max_version_minor);
  17.167 +    
  17.168      identity_list * _il = NULL;
  17.169  
  17.170      if (enc_format != PEP_enc_none && (_il = src->bcc) && _il->ident)
  17.171 @@ -1763,7 +1731,6 @@
  17.172      {
  17.173          //     - App splits mails with BCC in multiple mails.
  17.174          //     - Each email is encrypted separately
  17.175 -
  17.176          if(_il->next || (src->to && src->to->ident) || (src->cc && src->cc->ident))
  17.177          {
  17.178              // Only one Bcc with no other recipient allowed for now
  17.179 @@ -1777,6 +1744,12 @@
  17.180                  _il->ident->comm_type = PEP_ct_key_not_found;
  17.181                  _status = PEP_STATUS_OK;
  17.182              }
  17.183 +            // 0 unless set, so safe.
  17.184 +            
  17.185 +            set_min_version( _il->ident->major_ver, _il->ident->minor_ver, 
  17.186 +                             max_version_major, max_version_minor,
  17.187 +                             &max_version_major, &max_version_minor);
  17.188 +
  17.189              bool is_blacklisted = false;
  17.190              if (_il->ident->fpr && IS_PGP_CT(_il->ident->comm_type)) {
  17.191                  _status = blacklist_is_listed(session, _il->ident->fpr, &is_blacklisted);
  17.192 @@ -1802,6 +1775,7 @@
  17.193          }
  17.194          else
  17.195              _status = myself(session, _il->ident);
  17.196 +        
  17.197          if (_status != PEP_STATUS_OK) {
  17.198              status = PEP_UNENCRYPTED;
  17.199              goto pEp_error;
  17.200 @@ -1829,6 +1803,11 @@
  17.201                      _il->ident->comm_type = PEP_ct_key_not_found;
  17.202                      _status = PEP_STATUS_OK;
  17.203                  }
  17.204 +                // 0 unless set, so safe.
  17.205 +                set_min_version( _il->ident->major_ver, _il->ident->minor_ver, 
  17.206 +                                 max_version_major, max_version_minor,
  17.207 +                                 &max_version_major, &max_version_minor);
  17.208 +                
  17.209                  bool is_blacklisted = false;
  17.210                  if (_il->ident->fpr && IS_PGP_CT(_il->ident->comm_type)) {
  17.211                      _status = blacklist_is_listed(session, _il->ident->fpr, &is_blacklisted);
  17.212 @@ -1931,6 +1910,9 @@
  17.213              }
  17.214          }
  17.215      }
  17.216 +    
  17.217 +    if (max_version_major == 1)
  17.218 +        force_v_1 = true;
  17.219          
  17.220      if (enc_format == PEP_enc_none || !dest_keys_found ||
  17.221          stringlist_length(keys)  == 0 ||
  17.222 @@ -1947,9 +1929,10 @@
  17.223      }
  17.224      else {
  17.225          // FIXME - we need to deal with transport types (via flag)
  17.226 +        message_wrap_type wrap_type = PEP_message_unwrapped;
  17.227          if ((enc_format != PEP_enc_inline) && (!force_v_1) && ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp)) {
  17.228 -            message_wrap_type wrap_type = ((flags & PEP_encrypt_flag_key_reset_only) ? PEP_message_key_reset : PEP_message_default);
  17.229 -            _src = wrap_message_as_attachment(NULL, src, wrap_type, false);
  17.230 +            wrap_type = ((flags & PEP_encrypt_flag_key_reset_only) ? PEP_message_key_reset : PEP_message_default);
  17.231 +            _src = wrap_message_as_attachment(NULL, src, wrap_type, false, max_version_major, max_version_minor);
  17.232              if (!_src)
  17.233                  goto pEp_error;
  17.234          }
  17.235 @@ -1973,7 +1956,7 @@
  17.236          switch (enc_format) {
  17.237              case PEP_enc_PGP_MIME:
  17.238              case PEP_enc_PEP: // BUG: should be implemented extra
  17.239 -                status = encrypt_PGP_MIME(session, _src, keys, msg, flags);
  17.240 +                status = encrypt_PGP_MIME(session, _src, keys, msg, flags, wrap_type);
  17.241                  break;
  17.242  
  17.243              case PEP_enc_inline:
  17.244 @@ -2295,7 +2278,9 @@
  17.245      // if (!(flags & PEP_encrypt_flag_force_no_attached_key))
  17.246      //     _attach_key(session, target_fpr, src);
  17.247  
  17.248 -    _src = wrap_message_as_attachment(NULL, src, PEP_message_default, false);
  17.249 +    unsigned int major_ver, minor_ver;
  17.250 +    pEp_version_major_minor(PEP_VERSION, &major_ver, &minor_ver);
  17.251 +    _src = wrap_message_as_attachment(NULL, src, PEP_message_default, false, major_ver, minor_ver);
  17.252      if (!_src)
  17.253          goto pEp_error;
  17.254  
  17.255 @@ -2306,7 +2291,7 @@
  17.256      switch (enc_format) {
  17.257          case PEP_enc_PGP_MIME:
  17.258          case PEP_enc_PEP: // BUG: should be implemented extra
  17.259 -            status = encrypt_PGP_MIME(session, _src, keys, msg, flags);
  17.260 +            status = encrypt_PGP_MIME(session, _src, keys, msg, flags, PEP_message_default);
  17.261              if (status == PEP_STATUS_OK || (src->longmsg && strstr(src->longmsg, "INNER")))
  17.262                  _cleanup_src(src, false);
  17.263              break;
  17.264 @@ -2613,8 +2598,8 @@
  17.265      
  17.266      if ((!slong || slong[0] == '\0')
  17.267           && (!sform || sform[0] == '\0')) {
  17.268 -        if (satt) {
  17.269 -            const char* inner_mime_type = satt->mime_type;
  17.270 +        const char* inner_mime_type = (satt ? satt->mime_type : NULL);     
  17.271 +        if (inner_mime_type) {
  17.272              if (strcasecmp(inner_mime_type, "text/plain") == 0) {
  17.273                  free(slong); /* in case of "" */
  17.274                  src->longmsg = strndup(satt->value, satt->size); 
  17.275 @@ -3024,11 +3009,28 @@
  17.276      return status;
  17.277  }
  17.278  
  17.279 +// ident is in_only and should have been updated
  17.280 +static PEP_STATUS pEp_version_upgrade_or_ignore(
  17.281 +        PEP_SESSION session,
  17.282 +        pEp_identity* ident,
  17.283 +        unsigned int major,
  17.284 +        unsigned int minor) {
  17.285 +            
  17.286 +    PEP_STATUS status = PEP_STATUS_OK;        
  17.287 +    int ver_compare = compare_versions(major, minor, ident->major_ver, ident->minor_ver);
  17.288 +    if (ver_compare > 0)
  17.289 +        status = set_pEp_version(session, ident, major, minor);        
  17.290 +    
  17.291 +    return status;    
  17.292 +}
  17.293 +
  17.294  // FIXME: myself ??????
  17.295  static PEP_STATUS update_sender_to_pEp_trust(
  17.296          PEP_SESSION session, 
  17.297          pEp_identity* sender, 
  17.298 -        stringlist_t* keylist) 
  17.299 +        stringlist_t* keylist,
  17.300 +        unsigned int major,
  17.301 +        unsigned int minor) 
  17.302  {
  17.303      assert(session);
  17.304      assert(sender);
  17.305 @@ -3039,9 +3041,11 @@
  17.306          
  17.307      free(sender->fpr);
  17.308      sender->fpr = NULL;
  17.309 -    
  17.310 -    PEP_STATUS status = 
  17.311 -            is_me(session, sender) ? myself(session, sender) : update_identity(session, sender);
  17.312 +
  17.313 +    PEP_STATUS status = PEP_STATUS_OK;
  17.314 +
  17.315 +    // Seems status doesn't matter
  17.316 +    is_me(session, sender) ? myself(session, sender) : update_identity(session, sender);
  17.317  
  17.318      if (EMPTYSTR(sender->fpr) || strcmp(sender->fpr, keylist->value) != 0) {
  17.319          free(sender->fpr);
  17.320 @@ -3066,11 +3070,21 @@
  17.321      
  17.322      // Could be done elegantly, but we do this explicitly here for readability.
  17.323      // This file's code is difficult enough to parse. But change at will.
  17.324 -    switch (sender->comm_type) {
  17.325 +    switch (sender->comm_type) {            
  17.326          case PEP_ct_OpenPGP_unconfirmed:
  17.327          case PEP_ct_OpenPGP:
  17.328              sender->comm_type = PEP_ct_pEp_unconfirmed | (sender->comm_type & PEP_ct_confirmed);
  17.329              status = set_trust(session, sender);
  17.330 +            if (status != PEP_STATUS_OK)
  17.331 +                break;
  17.332 +        case PEP_ct_pEp:
  17.333 +        case PEP_ct_pEp_unconfirmed:
  17.334 +            // set version
  17.335 +            if (major == 0) {
  17.336 +                major = 2;
  17.337 +                minor = 0;
  17.338 +            }
  17.339 +            status = pEp_version_upgrade_or_ignore(session, sender, major, minor);    
  17.340              break;
  17.341          default:
  17.342              status = PEP_CANNOT_SET_TRUST;
  17.343 @@ -3134,6 +3148,19 @@
  17.344      return status;    
  17.345  }
  17.346  
  17.347 +static PEP_STATUS reconcile_sent_and_recv_info(message* src, message* inner_message) {
  17.348 +    if (!src || !inner_message)
  17.349 +        return PEP_ILLEGAL_VALUE;
  17.350 +        
  17.351 +    if (!inner_message->sent)
  17.352 +        inner_message->sent = timestamp_dup(src->sent);
  17.353 +        
  17.354 +    // This will never be set otherwise, since it's a transport header on the outside    
  17.355 +    inner_message->recv = timestamp_dup(src->recv);
  17.356 +    
  17.357 +    return PEP_STATUS_OK;
  17.358 +}
  17.359 +
  17.360  static PEP_STATUS reconcile_src_and_inner_messages(message* src, 
  17.361                                               message* inner_message) {
  17.362  
  17.363 @@ -3151,6 +3178,9 @@
  17.364      if (status == PEP_STATUS_OK && inner_message->bcc)
  17.365          status = reconcile_identity_lists(src->bcc, inner_message->bcc);
  17.366  
  17.367 +    if (status == PEP_STATUS_OK)
  17.368 +        status = reconcile_sent_and_recv_info(src, inner_message);
  17.369 +        
  17.370      return status;
  17.371      // FIXME - are there any flags or anything else we need to be sure are carried?
  17.372  }
  17.373 @@ -3357,7 +3387,9 @@
  17.374      char* signer_fpr = NULL;
  17.375      bool is_pEp_msg = is_a_pEpmessage(src);
  17.376      bool myself_read_only = (src->dir == PEP_dir_incoming);
  17.377 -
  17.378 +    unsigned int major_ver;
  17.379 +    unsigned int minor_ver;
  17.380 +    
  17.381      // Grab input flags
  17.382      bool reencrypt = (((*flags & PEP_decrypt_flag_untrusted_server) > 0) && *keylist && !EMPTYSTR((*keylist)->value));
  17.383      
  17.384 @@ -3373,34 +3405,39 @@
  17.385      *keylist = NULL;
  17.386      *rating = PEP_rating_undefined;
  17.387  //    *flags = 0;
  17.388 -    
  17.389 +
  17.390      /*** End init ***/
  17.391  
  17.392 -    // Ok, before we do anything, if it's a pEp message, regardless of whether it's
  17.393 +    // KB: FIXME - we should do this once we've seen an inner message in the case 
  17.394 +    // of pEp users. Since we've not used 1.0 in a billion years (but will receive 
  17.395 +    // 1.0 messages from pEp users who don't yet know WE are pEp users), we should 
  17.396 +    // sort this out sanely, not upfront.
  17.397 +    //
  17.398 +    // Was: Ok, before we do anything, if it's a pEp message, regardless of whether it's
  17.399      // encrypted or not, we set the sender as a pEp user. This has NOTHING to do
  17.400      // with the key.
  17.401 -    if (src->from && !(is_me(session, src->from))) {
  17.402 -        if (is_pEp_msg) {
  17.403 -            pEp_identity* tmp_from = src->from;
  17.404 -            
  17.405 -            // Ensure there's a user id
  17.406 -            if (EMPTYSTR(tmp_from->user_id) && tmp_from->address) {
  17.407 -                status = update_identity(session, tmp_from);
  17.408 -                if (status == PEP_CANNOT_FIND_IDENTITY) {
  17.409 -                    tmp_from->user_id = calloc(1, strlen(tmp_from->address) + 6);
  17.410 -                    if (!tmp_from->user_id)
  17.411 -                        return PEP_OUT_OF_MEMORY;
  17.412 -                    snprintf(tmp_from->user_id, strlen(tmp_from->address) + 6,
  17.413 -                             "TOFU_%s", tmp_from->address);        
  17.414 -                    status = PEP_STATUS_OK;
  17.415 -                }
  17.416 -            }
  17.417 -            if (status == PEP_STATUS_OK) {
  17.418 -                // Now set user as PEP (may also create an identity if none existed yet)
  17.419 -                status = set_as_pEp_user(session, tmp_from);
  17.420 -            }
  17.421 -        }
  17.422 -    }
  17.423 +    // if (src->from && !(is_me(session, src->from))) {
  17.424 +    //     if (is_pEp_msg) {
  17.425 +    //         pEp_identity* tmp_from = src->from;
  17.426 +    // 
  17.427 +    //         // Ensure there's a user id
  17.428 +    //         if (EMPTYSTR(tmp_from->user_id) && tmp_from->address) {
  17.429 +    //             status = update_identity(session, tmp_from);
  17.430 +    //             if (status == PEP_CANNOT_FIND_IDENTITY) {
  17.431 +    //                 tmp_from->user_id = calloc(1, strlen(tmp_from->address) + 6);
  17.432 +    //                 if (!tmp_from->user_id)
  17.433 +    //                     return PEP_OUT_OF_MEMORY;
  17.434 +    //                 snprintf(tmp_from->user_id, strlen(tmp_from->address) + 6,
  17.435 +    //                          "TOFU_%s", tmp_from->address);        
  17.436 +    //                 status = PEP_STATUS_OK;
  17.437 +    //             }
  17.438 +    //         }
  17.439 +    //         if (status == PEP_STATUS_OK) {
  17.440 +    //             // Now set user as PEP (may also create an identity if none existed yet)
  17.441 +    //             status = set_as_pEp_user(session, tmp_from);
  17.442 +    //         }
  17.443 +    //     }
  17.444 +    // }
  17.445      // We really need key used in signing to do anything further on the pEp comm_type.
  17.446      // So we can't adjust the rating of the sender just yet.
  17.447  
  17.448 @@ -3410,22 +3447,23 @@
  17.449      // This import is from the outermost message.
  17.450      // We don't do this for PGP_mime.
  17.451      bool imported_keys = false;
  17.452 -    if (!_has_PGP_MIME_format(src))
  17.453 +    PEP_cryptotech enc_type = determine_encryption_format(src);
  17.454 +    if (enc_type != PEP_crypt_OpenPGP || !(src->enc_format == PEP_enc_PGP_MIME || src->enc_format == PEP_enc_PGP_MIME_Outlook1))
  17.455          imported_keys = import_attached_keys(session, src, NULL);
  17.456              
  17.457      import_header_keys(session, src);
  17.458      
  17.459      // FIXME: is this really necessary here?
  17.460 -    if (src->from) {
  17.461 -        if (!is_me(session, src->from))
  17.462 -            status = update_identity(session, src->from);
  17.463 -        else
  17.464 -            status = _myself(session, src->from, false, false, myself_read_only);
  17.465 -        
  17.466 -        // We absolutely should NOT be bailing here unless it's a serious error
  17.467 -        if (status == PEP_OUT_OF_MEMORY)
  17.468 -            return status;
  17.469 -    }
  17.470 +    // if (src->from) {
  17.471 +    //     if (!is_me(session, src->from))
  17.472 +    //         status = update_identity(session, src->from);
  17.473 +    //     else
  17.474 +    //         status = _myself(session, src->from, false, false, myself_read_only);
  17.475 +    // 
  17.476 +    //     // We absolutely should NOT be bailing here unless it's a serious error
  17.477 +    //     if (status == PEP_OUT_OF_MEMORY)
  17.478 +    //         return status;
  17.479 +    // }
  17.480      
  17.481      /*** End Import any attached public keys and update identities accordingly ***/
  17.482      
  17.483 @@ -3474,6 +3512,7 @@
  17.484      decrypt_status = status;
  17.485      
  17.486      bool imported_private_key_address = false;
  17.487 +    bool has_inner = false;
  17.488  
  17.489      if (ptext) { 
  17.490          /* we got a plaintext from decryption */
  17.491 @@ -3482,7 +3521,7 @@
  17.492              case PEP_enc_PGP_MIME:
  17.493              case PEP_enc_PGP_MIME_Outlook1:
  17.494              
  17.495 -                status = mime_decode_message(ptext, psize, &msg);
  17.496 +                status = mime_decode_message(ptext, psize, &msg, &has_inner);
  17.497                  if (status != PEP_STATUS_OK)
  17.498                      goto pEp_error;
  17.499                  
  17.500 @@ -3558,154 +3597,212 @@
  17.501          if (decrypt_status == PEP_DECRYPTED || decrypt_status == PEP_DECRYPTED_AND_VERIFIED) {
  17.502              char* wrap_info = NULL;
  17.503              
  17.504 -            status = unencapsulate_hidden_fields(src, msg, &wrap_info);
  17.505 +            if (!has_inner) {
  17.506 +                status = unencapsulate_hidden_fields(src, msg, &wrap_info);
  17.507 +                if (status == PEP_OUT_OF_MEMORY)
  17.508 +                    goto enomem;                
  17.509 +                if (status != PEP_STATUS_OK)
  17.510 +                    goto pEp_error;
  17.511 +            }        
  17.512  
  17.513  //            bool is_transport_wrapper = false;
  17.514              
  17.515 +        
  17.516              // FIXME: replace with enums, check status
  17.517 -            if (wrap_info) {
  17.518 -                if (strcmp(wrap_info, "OUTER") == 0) {
  17.519 -                    // this only occurs in with a direct outer wrapper
  17.520 -                    // where the actual content is in the inner wrapper
  17.521 -                    message* inner_message = NULL;                    
  17.522 +            if (has_inner || wrap_info) { // Given that only wrap_info OUTER happens as of the end of wrap_info use, we don't need to strcmp it
  17.523 +                // if (strcmp(wrap_info, "OUTER") == 0) {
  17.524 +                //     // this only occurs in with a direct outer wrapper
  17.525 +                //     // where the actual content is in the inner wrapper
  17.526 +                message* inner_message = NULL;
  17.527 +                    
  17.528 +                // For a wrapped message, this is ALWAYS the second attachment; the 
  17.529 +                // mime tree is:
  17.530 +                // multipart/mixed
  17.531 +                //     |
  17.532 +                //     |----- text/plain 
  17.533 +                //     |----- message/rfc822
  17.534 +                //     |----- ...
  17.535 +                //
  17.536 +                // We leave this in below, but once we're rid of 2.0 format,
  17.537 +                // we can dispense with the loop, as has_inner -> 1st message struct attachment is message/rfc822
  17.538 +                //                   
  17.539 +
  17.540 +                bloblist_t* message_blob = msg->attachments;
  17.541 +                                    
  17.542 +                if (msg->attachments) {
  17.543 +                    message_blob = msg->attachments;
  17.544 +                    if (!has_inner && strcmp(message_blob->mime_type, "message/rfc822") != 0
  17.545 +                                   && strcmp(message_blob->mime_type, "text/rfc822") != 0)
  17.546 +                        message_blob = NULL;
  17.547 +                }
  17.548 +                    
  17.549 +                if (!message_blob) {
  17.550                      bloblist_t* actual_message = msg->attachments;
  17.551 -                    
  17.552 +                
  17.553                      while (actual_message) {
  17.554                          char* mime_type = actual_message->mime_type;
  17.555                          if (mime_type) {
  17.556 -                            
  17.557 +                        
  17.558                              // libetpan appears to change the mime_type on this one.
  17.559                              // *growl*
  17.560                              if (strcmp("message/rfc822", mime_type) == 0 ||
  17.561                                  strcmp("text/rfc822", mime_type) == 0) {
  17.562 -                                    
  17.563 -                                status = mime_decode_message(actual_message->value, 
  17.564 -                                                             actual_message->size, 
  17.565 -                                                             &inner_message);
  17.566 -                                if (status != PEP_STATUS_OK)
  17.567 -                                    goto pEp_error;
  17.568 -                                
  17.569 -                                if (inner_message) {
  17.570 -                                    // Though this will strip any message info on the
  17.571 -                                    // attachment, this is safe, as we do not
  17.572 -                                    // produce more than one attachment-as-message,
  17.573 -                                    // and those are the only ones with such info.
  17.574 -                                    // Since we capture the information, this is ok.
  17.575 -                                    wrap_info = NULL;
  17.576 -                                    inner_message->enc_format = src->enc_format;
  17.577 -
  17.578 -                                    const stringpair_list_t* pEp_protocol_version = NULL;
  17.579 -                                    const stringpair_list_t* sender_fpr = NULL;
  17.580 -                                    pEp_protocol_version = stringpair_list_find(inner_message->opt_fields, "X-pEp-Version");
  17.581 -                                    unsigned int pEp_v_major = 0;
  17.582 -                                    unsigned int pEp_v_minor = 0;
  17.583 -                                    if (pEp_protocol_version && !EMPTYSTR(pEp_protocol_version->value->value)) {
  17.584 -                                        // Roker is of course right. Meh :)
  17.585 -                                        if (sscanf(pEp_protocol_version->value->value, "%u.%u", &pEp_v_major, &pEp_v_minor) != 2) {
  17.586 -                                            pEp_v_major = 0;
  17.587 -                                            pEp_v_minor = 0;
  17.588 -                                        }
  17.589 -                                    }
  17.590 -                                    
  17.591 -                                    if (((pEp_v_major == 2) && (pEp_v_minor > 0)) || (pEp_v_major > 2))                              
  17.592 -                                        sender_fpr = stringpair_list_find(inner_message->opt_fields, "X-pEp-Sender-FPR");
  17.593 -
  17.594 -                                    // FIXME - Message 2.1                                    
  17.595 -                                    status = unencapsulate_hidden_fields(inner_message, NULL, &wrap_info);
  17.596 -                                    
  17.597 -                                    
  17.598 -                                    // ?
  17.599 -                                    if (status != PEP_STATUS_OK) {
  17.600 -                                        free_message(inner_message);
  17.601 -                                        goto pEp_error;
  17.602 -                                    }
  17.603 -    
  17.604 -                                    if (wrap_info) {
  17.605 -                                        bool is_inner = (strcmp(wrap_info, "INNER") == 0);
  17.606 -                                        bool is_key_reset = (strcmp(wrap_info, "KEY_RESET") == 0);
  17.607 -
  17.608 -                                        if (is_key_reset) {
  17.609 -                                            if (decrypt_status == PEP_DECRYPTED || decrypt_status == PEP_DECRYPTED_AND_VERIFIED) {
  17.610 -                                                status = receive_key_reset(session,
  17.611 -                                                                           inner_message);
  17.612 -                                                if (status != PEP_STATUS_OK) {
  17.613 -                                                    free_message(inner_message);
  17.614 -                                                    goto pEp_error;
  17.615 -                                                }
  17.616 -                                                *flags |= PEP_decrypt_flag_consume;
  17.617 -                                            }
  17.618 -                                        }
  17.619 -                                        else if (is_inner) {
  17.620 -
  17.621 -                                            // check for private key in decrypted message attachment while importing
  17.622 -                                            // N.B. Apparently, we always import private keys into the keyring; however,
  17.623 -                                            // we do NOT always allow those to be used for encryption. THAT is controlled
  17.624 -                                            // by setting it as an own identity associated with the key in the DB.
  17.625 -                                            
  17.626 -                                            // If we have a message 2.0 message, we are ONLY going to be ok with keys
  17.627 -                                            // we imported from THIS part of the message.
  17.628 -                                            imported_private_key_address = false;
  17.629 -                                            free(private_il); 
  17.630 -                                            private_il = NULL;
  17.631 -                                            
  17.632 -                                            // import keys from decrypted INNER source
  17.633 -                                            status = import_priv_keys_from_decrypted_msg(session, inner_message,
  17.634 -                                                                                         &imported_keys,
  17.635 -                                                                                         &imported_private_key_address,
  17.636 -                                                                                         private_il);
  17.637 -                                            if (status != PEP_STATUS_OK)
  17.638 -                                                goto pEp_error;            
  17.639 -
  17.640 -                                            // THIS is our message
  17.641 -                                            // Now, let's make sure we've copied in 
  17.642 -                                            // any information sent in by the app if
  17.643 -                                            // needed...
  17.644 -                                            reconcile_src_and_inner_messages(src, inner_message);
  17.645 -                                            
  17.646 -
  17.647 -                                            // FIXME: free msg, but check references
  17.648 -                                            //src = msg = inner_message;
  17.649 -                                            calculated_src = msg = inner_message;
  17.650 -                                            
  17.651 -                                            // FIXME: should this be msg???
  17.652 -                                            if (src->from) {
  17.653 -                                                if (!is_me(session, src->from))
  17.654 -                                                    update_identity(session, (src->from));
  17.655 -                                                else
  17.656 -                                                    _myself(session, src->from, false, false, myself_read_only);
  17.657 -                                            }
  17.658 -                                            break;        
  17.659 -                                        }
  17.660 -                                        else { // should never happen
  17.661 -                                            status = PEP_UNKNOWN_ERROR;
  17.662 -                                            free_message(inner_message);
  17.663 -                                            goto pEp_error;
  17.664 -                                        }
  17.665 -                                    }
  17.666 -                                    inner_message->enc_format = PEP_enc_none;
  17.667 -                                }
  17.668 -                                else { // forwarded message, leave it alone
  17.669 -                                    free_message(inner_message);
  17.670 -                                }
  17.671 +                                message_blob = actual_message;
  17.672 +                                break;
  17.673                              }
  17.674                          }
  17.675                          actual_message = actual_message->next;
  17.676 -                    }                    
  17.677 +                    }        
  17.678 +                }    
  17.679 +                if (message_blob) {              
  17.680 +                    status = mime_decode_message(message_blob->value, 
  17.681 +                                                 message_blob->size, 
  17.682 +                                                 &inner_message,
  17.683 +                                                 NULL);
  17.684 +                    if (status != PEP_STATUS_OK)
  17.685 +                        goto pEp_error;
  17.686 +                                
  17.687 +                    if (inner_message) {
  17.688 +                        is_pEp_msg = is_a_pEpmessage(inner_message);
  17.689 +                        
  17.690 +                        // Though this will strip any message info on the
  17.691 +                        // attachment, this is safe, as we do not
  17.692 +                        // produce more than one attachment-as-message,
  17.693 +                        // and those are the only ones with such info.
  17.694 +                        // Since we capture the information, this is ok.
  17.695 +                        wrap_info = NULL;
  17.696 +                        inner_message->enc_format = src->enc_format;
  17.697 +
  17.698 +                        const stringpair_list_t* pEp_protocol_version = NULL;
  17.699 +                        pEp_protocol_version = stringpair_list_find(inner_message->opt_fields, "X-pEp-Version");
  17.700 +                        
  17.701 +                        if (pEp_protocol_version && pEp_protocol_version->value)
  17.702 +                            pEp_version_major_minor(pEp_protocol_version->value->value, &major_ver, &minor_ver);
  17.703 +
  17.704 +                        // Sort out pEp user status and version number based on INNER message.
  17.705 +                        
  17.706 +                        bool is_inner = false;
  17.707 +                        bool is_key_reset = false;
  17.708 +
  17.709 +                        // Deal with plaintext modification in 1.0 and 2.0 messages
  17.710 +                        status = unencapsulate_hidden_fields(inner_message, NULL, &wrap_info);   
  17.711 +                        
  17.712 +                        if (status == PEP_OUT_OF_MEMORY)
  17.713 +                            goto enomem;                
  17.714 +                        if (status != PEP_STATUS_OK)
  17.715 +                            goto pEp_error;                                         
  17.716 +                            
  17.717 +                        if (major_ver > 2 || (major_ver == 2 && minor_ver > 0)) {
  17.718 +                            stringpair_list_t* searched = stringpair_list_find(inner_message->opt_fields, "X-pEp-Sender-FPR");                             
  17.719 +                            inner_message->_sender_fpr = ((searched && searched->value && searched->value->value) ? strdup(searched->value->value) : NULL);
  17.720 +                            searched = stringpair_list_find(inner_message->opt_fields, X_PEP_MSG_WRAP_KEY);
  17.721 +                            if (searched && searched->value && searched->value->value) {
  17.722 +                                is_inner = (strcmp(searched->value->value, "INNER") == 0);
  17.723 +                                if (!is_inner)
  17.724 +                                    is_key_reset = (strcmp(searched->value->value, "KEY_RESET") == 0);
  17.725 +                                if (is_inner || is_key_reset)
  17.726 +                                    inner_message->opt_fields = stringpair_list_delete_by_key(inner_message->opt_fields, X_PEP_MSG_WRAP_KEY);
  17.727 +                            }
  17.728 +                        }
  17.729 +                        else {
  17.730 +                            is_inner = (strcmp(wrap_info, "INNER") == 0);
  17.731 +                            if (!is_inner)
  17.732 +                                is_key_reset = (strcmp(wrap_info, "KEY_RESET") == 0);
  17.733 +                        }
  17.734 +                            
  17.735 +
  17.736 +                        if (is_key_reset) {
  17.737 +                            if (decrypt_status == PEP_DECRYPTED || decrypt_status == PEP_DECRYPTED_AND_VERIFIED) {
  17.738 +                                status = receive_key_reset(session,
  17.739 +                                                           inner_message);
  17.740 +                                if (status != PEP_STATUS_OK) {
  17.741 +                                    free_message(inner_message);
  17.742 +                                    goto pEp_error;
  17.743 +                                }
  17.744 +                                *flags |= PEP_decrypt_flag_consume;
  17.745 +                            }
  17.746 +                        }
  17.747 +                        else if (is_inner) {
  17.748 +
  17.749 +                            // check for private key in decrypted message attachment while importing
  17.750 +                            // N.B. Apparently, we always import private keys into the keyring; however,
  17.751 +                            // we do NOT always allow those to be used for encryption. THAT is controlled
  17.752 +                            // by setting it as an own identity associated with the key in the DB.
  17.753 +                            
  17.754 +                            // If we have a message 2.0 message, we are ONLY going to be ok with keys
  17.755 +                            // we imported from THIS part of the message.
  17.756 +                            imported_private_key_address = false;
  17.757 +                            free(private_il); 
  17.758 +                            private_il = NULL;
  17.759 +                            
  17.760 +                            // import keys from decrypted INNER source
  17.761 +                            status = import_priv_keys_from_decrypted_msg(session, inner_message,
  17.762 +                                                                         &imported_keys,
  17.763 +                                                                         &imported_private_key_address,
  17.764 +                                                                         private_il);
  17.765 +                            if (status != PEP_STATUS_OK)
  17.766 +                                goto pEp_error;            
  17.767 +
  17.768 +                            // THIS is our message
  17.769 +                            // Now, let's make sure we've copied in 
  17.770 +                            // any information sent in by the app if
  17.771 +                            // needed...
  17.772 +                            reconcile_src_and_inner_messages(src, inner_message);
  17.773 +                            
  17.774 +
  17.775 +                            // FIXME: free msg, but check references
  17.776 +                            //src = msg = inner_message;
  17.777 +                            calculated_src = msg = inner_message;
  17.778 +                            
  17.779 +                        }
  17.780 +                        else { // should never happen
  17.781 +                            status = PEP_UNKNOWN_ERROR;
  17.782 +                            free_message(inner_message);
  17.783 +                            goto pEp_error;
  17.784 +                        }
  17.785 +                        inner_message->enc_format = PEP_enc_none;
  17.786 +                    }
  17.787 +                    else { // forwarded message, leave it alone
  17.788 +                        free_message(inner_message);
  17.789 +                    }
  17.790 +                } // end if (message_blob)
  17.791 +                
  17.792 +                //  else if (strcmp(wrap_info, "TRANSPORT") == 0) {
  17.793 +                //      // FIXME: this gets even messier.
  17.794 +                //      // (TBI in ENGINE-278)
  17.795 +                //  }
  17.796 +                //  else {} // shouldn't be anything to be done here
  17.797 +    
  17.798 +            } // end if (has_inner || wrap_info)
  17.799 +            else {
  17.800 +                
  17.801 +            } // this we do if this isn't an inner message
  17.802 +            
  17.803 +            pEp_identity* cs_from = calculated_src->from;
  17.804 +            if (cs_from && !EMPTYSTR(cs_from->address)) {
  17.805 +                if (!is_me(session, cs_from)) {
  17.806 +                    status = update_identity(session, cs_from);
  17.807 +                    if (status == PEP_CANNOT_FIND_IDENTITY) {
  17.808 +                        cs_from->user_id = calloc(1, strlen(cs_from->address) + 6);
  17.809 +                        if (!cs_from->user_id)
  17.810 +                            return PEP_OUT_OF_MEMORY;
  17.811 +                        snprintf(cs_from->user_id, strlen(cs_from->address) + 6,
  17.812 +                                 "TOFU_%s", cs_from->address);        
  17.813 +                        status = PEP_STATUS_OK;
  17.814 +                    }
  17.815                  }
  17.816 -                else if (strcmp(wrap_info, "TRANSPORT") == 0) {
  17.817 -                    // FIXME: this gets even messier.
  17.818 -                    // (TBI in ENGINE-278)
  17.819 -                }
  17.820 -                else {} // shouldn't be anything to be done here
  17.821 -            }
  17.822 -        }
  17.823 +                else
  17.824 +                    status = _myself(session, cs_from, false, false, myself_read_only);
  17.825 +            }                                                                        
  17.826 +        } // end if (decrypt_status == PEP_DECRYPTED || decrypt_status == PEP_DECRYPTED_AND_VERIFIED)
  17.827          
  17.828          *rating = decrypt_rating(decrypt_status);
  17.829          
  17.830          // Ok, so if it was signed and it's all verified, we can update
  17.831          // eligible signer comm_types to PEP_ct_pEp_*
  17.832 +        // This also sets and upgrades pEp version
  17.833          if (decrypt_status == PEP_DECRYPTED_AND_VERIFIED && is_pEp_msg && calculated_src->from)
  17.834 -            status = update_sender_to_pEp_trust(session, calculated_src->from, _keylist);
  17.835 +            status = update_sender_to_pEp_trust(session, calculated_src->from, _keylist, major_ver, minor_ver);
  17.836  
  17.837          /* Ok, now we have a keylist used for decryption/verification.
  17.838             now we need to update the message rating with the 
  17.839 @@ -3920,15 +4017,16 @@
  17.840              !(*flags & PEP_decrypt_flag_dont_trigger_sync)) {
  17.841          size_t size;
  17.842          const char *data;
  17.843 -        char *sync_fpr = NULL;
  17.844 -        PEP_STATUS tmpstatus = base_extract_message(session, msg, &size, &data, &sync_fpr);
  17.845 +        char *sender_fpr = NULL;
  17.846 +        PEP_STATUS tmpstatus = base_extract_message(session, msg, &size, &data, &sender_fpr);
  17.847          if (!tmpstatus && size && data) {
  17.848 -            if (sync_fpr)
  17.849 -                signal_Sync_message(session, *rating, data, size, msg->from, sync_fpr);
  17.850 +            if (sender_fpr)
  17.851 +                signal_Sync_message(session, *rating, data, size, msg->from, sender_fpr);
  17.852 +            // FIXME: this must be changed to sender_fpr
  17.853              else if (*keylist)
  17.854                  signal_Sync_message(session, *rating, data, size, msg->from, (*keylist)->value);
  17.855          }
  17.856 -        free(sync_fpr);
  17.857 +        free(sender_fpr);
  17.858      }
  17.859  
  17.860      return status;
  17.861 @@ -4076,7 +4174,7 @@
  17.862          *rating = PEP_rating_undefined;
  17.863      }
  17.864      else
  17.865 -        *rating = MAX(_rating(max_comm_type), PEP_rating_unencrypted);
  17.866 +        *rating = _MAX(_rating(max_comm_type), PEP_rating_unencrypted);
  17.867  
  17.868      return PEP_STATUS_OK;
  17.869  }
  17.870 @@ -4234,7 +4332,7 @@
  17.871      return num_to_asciihex(xor_num);
  17.872  }
  17.873  
  17.874 -static char* skip_separators(char* current, char* begin) {
  17.875 +static const char* skip_separators(const char* current, const char* begin) {
  17.876      while (current >= begin) {
  17.877          /* .:,;-_ ' ' - [2c-2e] [3a-3b] [20] [5f] */
  17.878          char check_char = *current;
  17.879 @@ -4272,71 +4370,73 @@
  17.880  }
  17.881  
  17.882  DYNAMIC_API PEP_STATUS get_trustwords(
  17.883 -    PEP_SESSION session, const pEp_identity* id1, const pEp_identity* id2,
  17.884 -    const char* lang, char **words, size_t *wsize, bool full
  17.885 -)
  17.886 +        PEP_SESSION session, const pEp_identity* id1, const pEp_identity* id2,
  17.887 +        const char* lang, char **words, size_t *wsize, bool full
  17.888 +    )
  17.889  {
  17.890 -    assert(session);
  17.891 -    assert(id1);
  17.892 -    assert(id2);
  17.893 -    assert(id1->fpr);
  17.894 -    assert(id2->fpr);
  17.895 -    assert(words);
  17.896 -    assert(wsize);
  17.897 -
  17.898 -    int SHORT_NUM_TWORDS = 5; 
  17.899 -    
  17.900 +    assert(session && id1 && id1->fpr && id2 && id2->fpr&& lang && words &&
  17.901 +            wsize);
  17.902 +    if (!(session && id1 && id1->fpr && id2 && id2->fpr&& lang && words &&
  17.903 +                wsize))
  17.904 +        return PEP_ILLEGAL_VALUE;
  17.905 +
  17.906 +    return get_trustwords_for_fprs(session, id1->fpr, id2->fpr, lang, words,
  17.907 +            wsize, full);
  17.908 +}
  17.909 +
  17.910 +DYNAMIC_API PEP_STATUS get_trustwords_for_fprs(
  17.911 +        PEP_SESSION session, const char* fpr1, const char* fpr2,
  17.912 +        const char* lang, char **words, size_t *wsize, bool full
  17.913 +    )
  17.914 +{
  17.915 +    assert(session && fpr1 && fpr2 && words && wsize);
  17.916 +    if (!(session && fpr1 && fpr2 && words && wsize))
  17.917 +        return PEP_ILLEGAL_VALUE;
  17.918 +
  17.919 +    const int SHORT_NUM_TWORDS = 5; 
  17.920      PEP_STATUS status = PEP_STATUS_OK;
  17.921      
  17.922 -    if (!(session && id1 && id2 && words && wsize) ||
  17.923 -        !(id1->fpr) || (!id2->fpr))
  17.924 -        return PEP_ILLEGAL_VALUE;
  17.925 -
  17.926 -    char *source1 = id1->fpr;
  17.927 -    char *source2 = id2->fpr;
  17.928 -
  17.929 -    int source1_len = strlen(source1);
  17.930 -    int source2_len = strlen(source2);
  17.931 -    int max_len;
  17.932 -        
  17.933      *words = NULL;    
  17.934      *wsize = 0;
  17.935  
  17.936 -    max_len = (source1_len > source2_len ? source1_len : source2_len);
  17.937 +    int fpr1_len = strlen(fpr1);
  17.938 +    int fpr2_len = strlen(fpr2);
  17.939 +        
  17.940 +    int max_len = (fpr1_len > fpr2_len ? fpr1_len : fpr2_len);
  17.941      
  17.942      char* XORed_fpr = (char*)(calloc(max_len + 1, 1));
  17.943      *(XORed_fpr + max_len) = '\0';
  17.944      char* result_curr = XORed_fpr + max_len - 1;
  17.945 -    char* source1_curr = source1 + source1_len - 1;
  17.946 -    char* source2_curr = source2 + source2_len - 1;
  17.947 -
  17.948 -    while (source1 <= source1_curr && source2 <= source2_curr) {
  17.949 -        source1_curr = skip_separators(source1_curr, source1);
  17.950 -        source2_curr = skip_separators(source2_curr, source2);
  17.951 +    const char* fpr1_curr = fpr1 + fpr1_len - 1;
  17.952 +    const char* fpr2_curr = fpr2 + fpr2_len - 1;
  17.953 +
  17.954 +    while (fpr1 <= fpr1_curr && fpr2 <= fpr2_curr) {
  17.955 +        fpr1_curr = skip_separators(fpr1_curr, fpr1);
  17.956 +        fpr2_curr = skip_separators(fpr2_curr, fpr2);
  17.957          
  17.958 -        if (source1_curr < source1 || source2_curr < source2)
  17.959 +        if (fpr1_curr < fpr1 || fpr2_curr < fpr2)
  17.960              break;
  17.961              
  17.962 -        char xor_hex = xor_hex_chars(*source1_curr, *source2_curr);
  17.963 +        char xor_hex = xor_hex_chars(*fpr1_curr, *fpr2_curr);
  17.964          if (xor_hex == '\0') {
  17.965              status = PEP_ILLEGAL_VALUE;
  17.966              goto error_release;
  17.967          }
  17.968          
  17.969          *result_curr = xor_hex;
  17.970 -        result_curr--; source1_curr--; source2_curr--;
  17.971 +        result_curr--; fpr1_curr--; fpr2_curr--;
  17.972      }
  17.973  
  17.974 -    char* remainder_start = NULL;
  17.975 -    char* remainder_curr = NULL;
  17.976 +    const char* remainder_start = NULL;
  17.977 +    const char* remainder_curr = NULL;
  17.978      
  17.979 -    if (source1 <= source1_curr) {
  17.980 -        remainder_start = source1;
  17.981 -        remainder_curr = source1_curr;
  17.982 +    if (fpr1 <= fpr1_curr) {
  17.983 +        remainder_start = fpr1;
  17.984 +        remainder_curr = fpr1_curr;
  17.985      }
  17.986 -    else if (source2 <= source2_curr) {
  17.987 -        remainder_start = source2;
  17.988 -        remainder_curr = source2_curr;
  17.989 +    else if (fpr2 <= fpr2_curr) {
  17.990 +        remainder_start = fpr2;
  17.991 +        remainder_curr = fpr2_curr;
  17.992      }
  17.993      if (remainder_curr) {
  17.994          while (remainder_start <= remainder_curr) {
    18.1 --- a/src/message_api.h	Thu May 16 17:55:58 2019 +0200
    18.2 +++ b/src/message_api.h	Wed Aug 07 14:17:27 2019 +0200
    18.3 @@ -49,6 +49,7 @@
    18.4  typedef unsigned int PEP_encrypt_flags_t;
    18.5  
    18.6  typedef enum _message_wrap_type {
    18.7 +    PEP_message_unwrapped,  // 1.0 or anything we don't wrap    
    18.8      PEP_message_default,    // typical inner/outer message 2.0
    18.9      PEP_message_transport,  // e.g. for onion layers
   18.10      PEP_message_key_reset   // for wrapped key reset information
   18.11 @@ -388,9 +389,9 @@
   18.12  //        the caller is responsible to free() it (on Windoze use pEp_free())
   18.13  //
   18.14  DYNAMIC_API PEP_STATUS get_trustwords(
   18.15 -    PEP_SESSION session, const pEp_identity* id1, const pEp_identity* id2,
   18.16 -    const char* lang, char **words, size_t *wsize, bool full
   18.17 -);
   18.18 +        PEP_SESSION session, const pEp_identity* id1, const pEp_identity* id2,
   18.19 +        const char* lang, char **words, size_t *wsize, bool full
   18.20 +    );
   18.21  
   18.22  
   18.23  // get_message_trustwords() - get full trustwords string for message sender and reciever identities 
   18.24 @@ -421,12 +422,42 @@
   18.25  //        the caller is responsible to free() it (on Windoze use pEp_free())
   18.26  //
   18.27  DYNAMIC_API PEP_STATUS get_message_trustwords(
   18.28 -    PEP_SESSION session, 
   18.29 -    message *msg,
   18.30 -    stringlist_t *keylist,
   18.31 -    pEp_identity* received_by,
   18.32 -    const char* lang, char **words, bool full
   18.33 -);
   18.34 +        PEP_SESSION session, 
   18.35 +        message *msg,
   18.36 +        stringlist_t *keylist,
   18.37 +        pEp_identity* received_by,
   18.38 +        const char* lang, char **words, bool full
   18.39 +    );
   18.40 +
   18.41 +// get_trustwords_for_fprs() - get full trustwords string for a pair of fingerprints
   18.42 +//
   18.43 +//    parameters:
   18.44 +//        session (in)        session handle
   18.45 +//        fpr1 (in)           fingerprint 1
   18.46 +//        fpr2 (in)           fingerprint 2
   18.47 +//        lang (in)           C string with ISO 639-1 language code
   18.48 +//        words (out)         pointer to C string with all trustwords UTF-8 encoded,
   18.49 +//                            separated by a blank each
   18.50 +//                            NULL if language is not supported or trustword
   18.51 +//                            wordlist is damaged or unavailable
   18.52 +//        wsize (out)         length of full trustwords string
   18.53 +//        full (in)           if true, generate ALL trustwords for these identities.
   18.54 +//                            else, generate a fixed-size subset. (TODO: fixed-minimum-entropy
   18.55 +//                            subset in next version)
   18.56 +//
   18.57 +//    return value:
   18.58 +//        PEP_STATUS_OK            trustwords retrieved
   18.59 +//        PEP_OUT_OF_MEMORY        out of memory
   18.60 +//        PEP_TRUSTWORD_NOT_FOUND  at least one trustword not found
   18.61 +//
   18.62 +//    caveat:
   18.63 +//        the word pointer goes to the ownership of the caller
   18.64 +//        the caller is responsible to free() it (on Windoze use pEp_free())
   18.65 +//
   18.66 +DYNAMIC_API PEP_STATUS get_trustwords_for_fprs(
   18.67 +        PEP_SESSION session, const char* fpr1, const char* fpr2,
   18.68 +        const char* lang, char **words, size_t *wsize, bool full
   18.69 +    );
   18.70  
   18.71  // re_evaluate_message_rating() - re-evaluate already decrypted message rating
   18.72  //
    19.1 --- a/src/mime.c	Thu May 16 17:55:58 2019 +0200
    19.2 +++ b/src/mime.c	Wed Aug 07 14:17:27 2019 +0200
    19.3 @@ -39,6 +39,5 @@
    19.4          char **mimetext
    19.5      )
    19.6  {
    19.7 -    return _mime_encode_message_internal(msg, omit_fields, mimetext, true);
    19.8 +    return _mime_encode_message_internal(msg, omit_fields, mimetext, true, false);
    19.9  }
   19.10 -
    20.1 --- a/src/mime.h	Thu May 16 17:55:58 2019 +0200
    20.2 +++ b/src/mime.h	Wed Aug 07 14:17:27 2019 +0200
    20.3 @@ -55,9 +55,10 @@
    20.4  // mime_decode_message() - decode a MIME message
    20.5  //
    20.6  //  parameters:
    20.7 -//      mimetext (in)           MIME encoded text to decode
    20.8 -//      size (in)               size of text to decode
    20.9 -//      msg (out)               decoded message
   20.10 +//      mimetext (in)           	MIME encoded text to decode
   20.11 +//      size (in)               	size of text to decode
   20.12 +//      msg (out)               	decoded message
   20.13 +//      raise_msg_attachment (out)		
   20.14  //
   20.15  //  return value:
   20.16  //      PEP_STATUS_OK           if everything worked
   20.17 @@ -75,7 +76,8 @@
   20.18  DYNAMIC_API PEP_STATUS mime_decode_message(
   20.19          const char *mimetext,
   20.20          size_t size,
   20.21 -        message **msg
   20.22 +        message **msg,
   20.23 +        bool* raise_msg_attachment
   20.24      );
   20.25  
   20.26  /* sometimes we don't want to transport encode */
   20.27 @@ -83,7 +85,8 @@
   20.28          const message * msg,
   20.29          bool omit_fields,
   20.30          char **mimetext,
   20.31 -        bool transport_encode
   20.32 +        bool transport_encode,
   20.33 +        bool set_attachment_forward_comment        
   20.34      );
   20.35  
   20.36  
    21.1 --- a/src/pEpEngine.c	Thu May 16 17:55:58 2019 +0200
    21.2 +++ b/src/pEpEngine.c	Wed Aug 07 14:17:27 2019 +0200
    21.3 @@ -83,7 +83,7 @@
    21.4  static const char *sql_get_identity =  
    21.5      "select fpr, username, comm_type, lang,"
    21.6      "   identity.flags | pgp_keypair.flags,"
    21.7 -    "   is_own"
    21.8 +    "   is_own, pEp_version_major, pEp_version_minor"
    21.9      "   from identity"
   21.10      "   join person on id = identity.user_id"
   21.11      "   join pgp_keypair on fpr = identity.main_key_id"
   21.12 @@ -101,7 +101,7 @@
   21.13  static const char *sql_get_identities_by_main_key_id =  
   21.14      "select address, identity.user_id, username, comm_type, lang,"
   21.15      "   identity.flags | pgp_keypair.flags,"
   21.16 -    "   is_own"
   21.17 +    "   is_own, pEp_version_major, pEp_version_minor"
   21.18      "   from identity"
   21.19      "   join person on id = identity.user_id"
   21.20      "   join pgp_keypair on fpr = identity.main_key_id"
   21.21 @@ -113,7 +113,7 @@
   21.22  
   21.23  static const char *sql_get_identity_without_trust_check =  
   21.24      "select identity.main_key_id, username, lang,"
   21.25 -    "   identity.flags, is_own"
   21.26 +    "   identity.flags, is_own, pEp_version_major, pEp_version_minor"
   21.27      "   from identity"
   21.28      "   join person on id = identity.user_id"
   21.29      "   where (case when (address = ?1) then (1)"
   21.30 @@ -127,7 +127,7 @@
   21.31  
   21.32  static const char *sql_get_identities_by_address =  
   21.33      "select user_id, identity.main_key_id, username, lang,"
   21.34 -    "   identity.flags, is_own"
   21.35 +    "   identity.flags, is_own, pEp_version_major, pEp_version_minor"
   21.36      "   from identity"
   21.37      "   join person on id = identity.user_id"
   21.38      "   where (case when (address = ?1) then (1)"
   21.39 @@ -141,7 +141,7 @@
   21.40  static const char *sql_get_identities_by_userid =  
   21.41      "select address, fpr, username, comm_type, lang,"
   21.42      "   identity.flags | pgp_keypair.flags,"
   21.43 -    "   is_own"
   21.44 +    "   is_own, pEp_version_major, pEp_version_minor"
   21.45      "   from identity"
   21.46      "   join person on id = identity.user_id"
   21.47      "   join pgp_keypair on fpr = identity.main_key_id"
   21.48 @@ -239,20 +239,25 @@
   21.49  static const char *sql_set_identity_entry = 
   21.50      "insert into identity ("
   21.51      "       address, main_key_id, "
   21.52 -    "       user_id, flags, is_own"
   21.53 +    "       user_id, flags, is_own,"
   21.54 +    "       pEp_version_major, pEp_version_minor"
   21.55      "   ) values ("
   21.56      "       ?1,"
   21.57      "       upper(replace(?2,' ','')),"
   21.58      "       ?3,"
   21.59      "       ?4,"
   21.60 -    "       ?5"
   21.61 +    "       ?5,"
   21.62 +    "       ?6,"
   21.63 +    "       ?7"
   21.64      "   );";
   21.65      
   21.66  static const char* sql_update_identity_entry =    
   21.67      "update identity "
   21.68      "   set main_key_id = upper(replace(?2,' ','')), "
   21.69      "       flags = ?4, " 
   21.70 -    "       is_own = ?5 "
   21.71 +    "       is_own = ?5, "
   21.72 +    "       pEp_version_major = ?6, "
   21.73 +    "       pEp_version_major = ?7 "    
   21.74      "   where (case when (address = ?1) then (1)"
   21.75      "               when (lower(address) = lower(?1)) then (1)"
   21.76      "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1) "
   21.77 @@ -301,6 +306,28 @@
   21.78      "          end) = 1"
   21.79      "          and user_id = ?3 ;";
   21.80  
   21.81 +static const char *sql_set_pEp_version =
   21.82 +    "update identity "
   21.83 +    "   set pEp_version_major = ?1, "
   21.84 +    "       pEp_version_minor = ?2 "
   21.85 +    "   where (case when (address = ?3) then (1)"
   21.86 +    "               when (lower(address) = lower(?3)) then (1)"
   21.87 +    "               when (replace(lower(address),'.','') = replace(lower(?3),'.','')) then (1) "
   21.88 +    "               else 0 "
   21.89 +    "          end) = 1 "
   21.90 +    "          and user_id = ?4 ;";
   21.91 +
   21.92 +static const char *sql_upgrade_pEp_version_by_user_id =
   21.93 +    "update identity "
   21.94 +    "   set pEp_version_major = ?1, "
   21.95 +    "       pEp_version_minor = ?2 "
   21.96 +    "       where user_id = ?3 "
   21.97 +    "           and (case when (pEp_version_major < ?1) then (1)"
   21.98 +    "                     when (pEp_version_major > ?1) then (0)"
   21.99 +    "                     when (pEp_version_minor < ?2) then (1)"
  21.100 +    "                     else 0 "
  21.101 +    "           end) = 1 ;";
  21.102 +
  21.103  static const char *sql_set_trust =
  21.104      "insert into trust (user_id, pgp_keypair_fpr, comm_type) "
  21.105      "values (?1, upper(replace(?2,' ','')), ?3) ;";
  21.106 @@ -353,7 +380,7 @@
  21.107  
  21.108  static const char *sql_i18n_token = 
  21.109      "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;";
  21.110 -
  21.111 +    
  21.112  // blacklist
  21.113  static const char *sql_blacklist_add = 
  21.114      "insert or ignore into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;"
  21.115 @@ -393,7 +420,7 @@
  21.116  
  21.117  static const char *sql_own_identities_retrieve =  
  21.118      "select address, fpr, identity.user_id, username,"
  21.119 -    "   lang, identity.flags | pgp_keypair.flags"
  21.120 +    "   lang, identity.flags | pgp_keypair.flags, pEp_version_major, pEp_version_minor"
  21.121      "   from identity"
  21.122      "   join person on id = identity.user_id"
  21.123      "   join pgp_keypair on fpr = identity.main_key_id"
  21.124 @@ -533,7 +560,7 @@
  21.125  
  21.126      int retval = 0;
  21.127  
  21.128 -    int rc = sqlite3_step(stmt);  
  21.129 +    int rc = Sqlite3_step(stmt);  
  21.130      if (rc == SQLITE_DONE || rc == SQLITE_OK || rc == SQLITE_ROW) {
  21.131          retval = 1;
  21.132      }
  21.133 @@ -584,7 +611,7 @@
  21.134  
  21.135      int retval = 0;
  21.136  
  21.137 -    int rc = sqlite3_step(stmt);  
  21.138 +    int rc = Sqlite3_step(stmt);  
  21.139      if (rc == SQLITE_DONE || rc == SQLITE_OK || rc == SQLITE_ROW) {
  21.140          retval = 1;
  21.141      }
  21.142 @@ -607,7 +634,7 @@
  21.143      sqlite3_prepare_v2(session->db, sql_query, -1, &stmt, NULL);
  21.144      int i = 0;
  21.145      int int_result = 0;
  21.146 -    while ((int_result = sqlite3_step(stmt)) == SQLITE_ROW && i < _PEP_MAX_AFFECTED) {
  21.147 +    while ((int_result = Sqlite3_step(stmt)) == SQLITE_ROW && i < _PEP_MAX_AFFECTED) {
  21.148          table_names[i++] = strdup((const char*)(sqlite3_column_text(stmt, 0)));
  21.149      }
  21.150      
  21.151 @@ -965,9 +992,12 @@
  21.152                  "   comment text,\n"
  21.153                  "   flags integer default 0,\n"
  21.154                  "   is_own integer default 0,\n"
  21.155 +                "   pEp_version_major integer default 0,\n"
  21.156 +                "   pEp_version_minor integer default 0,\n"                
  21.157                  "   timestamp integer default (datetime('now')),\n"
  21.158                  "   primary key (address, user_id)\n"
  21.159                  ");\n"
  21.160 +                "create index if not exists identity_userid_addr on identity(address, user_id);\n"
  21.161                  "create table if not exists trust (\n"
  21.162                  "   user_id text not null\n"
  21.163                  "       references person (id)\n"
  21.164 @@ -1070,7 +1100,10 @@
  21.165          // Sometimes the user_version wasn't set correctly. 
  21.166          if (version == 1) {
  21.167              bool version_changed = true;
  21.168 -            if (db_contains_table(_session, "social_graph") > 0) {
  21.169 +            if (table_contains_column(_session, "identity", "pEp_version_major")) {
  21.170 +                version = 12;
  21.171 +            }
  21.172 +            else if (db_contains_table(_session, "social_graph") > 0) {
  21.173                  if (!table_contains_column(_session, "person", "device_group"))
  21.174                      version = 10;
  21.175                  else
  21.176 @@ -1423,6 +1456,81 @@
  21.177                  if (status != PEP_STATUS_OK)
  21.178                      return status;
  21.179              }
  21.180 +            if (version < 12) {
  21.181 +                int_result = sqlite3_exec(
  21.182 +                    _session->db,
  21.183 +                    "create index if not exists identity_userid_addr on identity(address, user_id);\n"
  21.184 +                    ,
  21.185 +                    NULL,
  21.186 +                    NULL,
  21.187 +                    NULL
  21.188 +                );
  21.189 +                assert(int_result == SQLITE_OK);
  21.190 +                
  21.191 +                int_result = sqlite3_exec(
  21.192 +                    _session->db,
  21.193 +                    "alter table identity\n"
  21.194 +                    "   add column pEp_version_major integer default 0;\n"
  21.195 +                    "alter table identity\n"
  21.196 +                    "   add column pEp_version_minor integer default 0;\n",                    
  21.197 +                    NULL,
  21.198 +                    NULL,
  21.199 +                    NULL
  21.200 +                );
  21.201 +                if (status != PEP_STATUS_OK)
  21.202 +                    return status;  
  21.203 +      
  21.204 +                int_result = sqlite3_exec(
  21.205 +                    _session->db,
  21.206 +                    "update identity\n"
  21.207 +                    "   set pEp_version_major = 2\n"
  21.208 +                    "   where exists (select * from person\n"
  21.209 +                    "                     where identity.user_id = person.id\n"
  21.210 +                    "                     and identity.is_own = 0\n"
  21.211 +                    "                     and person.is_pEp_user = 1);\n",
  21.212 +                    NULL,
  21.213 +                    NULL,
  21.214 +                    NULL
  21.215 +                );
  21.216 +                if (status != PEP_STATUS_OK)
  21.217 +                    return status;  
  21.218 +                
  21.219 +                // N.B. WE DEFINE PEP_VERSION - IF WE'RE AT 9-DIGIT MAJOR OR MINOR VERSIONS, ER, BAD.
  21.220 +                char major_buf[10];
  21.221 +                char minor_buf[10];
  21.222 +                if (sscanf("%s.%s", major_buf, minor_buf) != 2)
  21.223 +                    return PEP_UNKNOWN_ERROR; // DO BETTER
  21.224 +                size_t major_len = strlen(major_buf);
  21.225 +                size_t minor_len = strlen(minor_buf);
  21.226 +                    
  21.227 +                const char* _ver_12_startstr =                     
  21.228 +                    "update identity\n"
  21.229 +                    "    set pEp_version_major = ";
  21.230 +                const char* _ver_12_midstr = ",\n"
  21.231 +                    "        pEp_version_minor = ";
  21.232 +                const char* _ver_12_endstr =     
  21.233 +                    "\n"
  21.234 +                    "    where identity.is_own = 1;\n";
  21.235 +                    
  21.236 +                size_t new_stringlen = strlen(_ver_12_startstr) + major_len +
  21.237 +                                       strlen(_ver_12_midstr) + minor_len +
  21.238 +                                       strlen(_ver_12_endstr);
  21.239 +                                       
  21.240 +                char* _ver_12_stmt = calloc(new_stringlen + 1, 1);
  21.241 +                snprintf(_ver_12_stmt, new_stringlen + 1, "%s%s%s%s%s",
  21.242 +                         _ver_12_startstr, major_buf, _ver_12_midstr, minor_buf, _ver_12_endstr);
  21.243 +                
  21.244 +                int_result = sqlite3_exec(
  21.245 +                    _session->db,
  21.246 +                    _ver_12_stmt,
  21.247 +                    NULL,
  21.248 +                    NULL,
  21.249 +                    NULL
  21.250 +                );
  21.251 +                free(_ver_12_stmt);
  21.252 +                if (status != PEP_STATUS_OK)
  21.253 +                    return status;                      
  21.254 +            }
  21.255          }        
  21.256          else { 
  21.257              // Version from DB was 0, it means this is initial setup.
  21.258 @@ -1621,6 +1729,16 @@
  21.259              NULL);
  21.260      assert(int_result == SQLITE_OK);
  21.261  
  21.262 +    int_result = sqlite3_prepare_v2(_session->db, sql_set_pEp_version,
  21.263 +            (int)strlen(sql_set_pEp_version), &_session->set_pEp_version,
  21.264 +            NULL);
  21.265 +    assert(int_result == SQLITE_OK);
  21.266 +    
  21.267 +    int_result = sqlite3_prepare_v2(_session->db, sql_upgrade_pEp_version_by_user_id,
  21.268 +            (int)strlen(sql_upgrade_pEp_version_by_user_id), &_session->upgrade_pEp_version_by_user_id,
  21.269 +            NULL);
  21.270 +    assert(int_result == SQLITE_OK);
  21.271 +
  21.272      int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
  21.273              (int)strlen(sql_set_trust), &_session->set_trust, NULL);
  21.274      assert(int_result == SQLITE_OK);
  21.275 @@ -1861,6 +1979,8 @@
  21.276                  sqlite3_finalize(session->delete_person);                
  21.277              if (session->set_as_pEp_user)
  21.278                  sqlite3_finalize(session->set_as_pEp_user);
  21.279 +            if (session->upgrade_pEp_version_by_user_id)
  21.280 +                sqlite3_finalize(session->upgrade_pEp_version_by_user_id);
  21.281              if (session->is_pEp_user)
  21.282                  sqlite3_finalize(session->is_pEp_user);
  21.283              if (session->exists_person)
  21.284 @@ -1889,6 +2009,8 @@
  21.285                  sqlite3_finalize(session->set_identity_flags);
  21.286              if (session->unset_identity_flags)
  21.287                  sqlite3_finalize(session->unset_identity_flags);
  21.288 +            if (session->set_pEp_version)
  21.289 +                sqlite3_finalize(session->set_pEp_version);                
  21.290              if (session->exists_trust_entry)
  21.291                  sqlite3_finalize(session->exists_trust_entry);                                
  21.292              if (session->set_trust)
  21.293 @@ -2017,32 +2139,31 @@
  21.294  #if !defined(NDEBUG) && !defined(_PEP_SERVICE_LOG_OFF)
  21.295      fprintf(stdout, "\n*** %s %s %s %s\n", title, entity, description, comment);
  21.296      session->service_log = true;
  21.297 +
  21.298 +    int result;
  21.299 +    
  21.300 +    assert(session);
  21.301 +    assert(title);
  21.302 +    assert(entity);
  21.303 +    
  21.304 +    if (!(session && title && entity))
  21.305 +        return PEP_ILLEGAL_VALUE;
  21.306 +    
  21.307 +    sqlite3_reset(session->log);
  21.308 +    sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
  21.309 +    sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
  21.310 +    if (description)
  21.311 +        sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
  21.312 +    else
  21.313 +        sqlite3_bind_null(session->log, 3);
  21.314 +    if (comment)
  21.315 +        sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
  21.316 +    else
  21.317 +        sqlite3_bind_null(session->log, 4);
  21.318 +    result = Sqlite3_step(session->log);
  21.319 +    sqlite3_reset(session->log);
  21.320 +    
  21.321  #endif
  21.322 -
  21.323 -    // PEP_STATUS status = PEP_STATUS_OK;
  21.324 -    // int result;
  21.325 -    // 
  21.326 -    // assert(session);
  21.327 -    // assert(title);
  21.328 -    // assert(entity);
  21.329 -    // 
  21.330 -    // if (!(session && title && entity))
  21.331 -    //     return PEP_ILLEGAL_VALUE;
  21.332 -    // 
  21.333 -    // sqlite3_reset(session->log);
  21.334 -    // sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
  21.335 -    // sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
  21.336 -    // if (description)
  21.337 -    //     sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
  21.338 -    // else
  21.339 -    //     sqlite3_bind_null(session->log, 3);
  21.340 -    // if (comment)
  21.341 -    //     sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
  21.342 -    // else
  21.343 -    //     sqlite3_bind_null(session->log, 4);
  21.344 -    // result = sqlite3_step(session->log);
  21.345 -    // sqlite3_reset(session->log);
  21.346 -    // 
  21.347      return PEP_STATUS_OK; // We ignore errors for this function.
  21.348  }
  21.349  
  21.350 @@ -2094,7 +2215,7 @@
  21.351      sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
  21.352      sqlite3_bind_int(session->trustword, 2, value);
  21.353  
  21.354 -    const int result = sqlite3_step(session->trustword);
  21.355 +    const int result = Sqlite3_step(session->trustword);
  21.356      if (result == SQLITE_ROW) {
  21.357          *word = strdup((const char *) sqlite3_column_text(session->trustword,
  21.358                      1));
  21.359 @@ -2258,6 +2379,8 @@
  21.360      dup->lang[2] = 0;
  21.361      dup->flags = src->flags;
  21.362      dup->me = src->me;
  21.363 +    dup->major_ver = src->major_ver;
  21.364 +    dup->minor_ver = src->minor_ver;
  21.365      
  21.366      return dup;
  21.367  }
  21.368 @@ -2289,7 +2412,7 @@
  21.369      
  21.370      sqlite3_reset(session->get_default_own_userid);
  21.371  
  21.372 -    const int result = sqlite3_step(session->get_default_own_userid);
  21.373 +    const int result = Sqlite3_step(session->get_default_own_userid);
  21.374      const char* id;
  21.375      
  21.376      switch (result) {
  21.377 @@ -2338,7 +2461,7 @@
  21.378  
  21.379      const char* tempid;
  21.380      
  21.381 -    const int result = sqlite3_step(session->get_userid_alias_default);
  21.382 +    const int result = Sqlite3_step(session->get_userid_alias_default);
  21.383      switch (result) {
  21.384      case SQLITE_ROW:
  21.385          tempid = (const char *) sqlite3_column_text(session->get_userid_alias_default, 0);
  21.386 @@ -2383,7 +2506,7 @@
  21.387      sqlite3_bind_text(session->add_userid_alias, 2, alias_id, -1,
  21.388              SQLITE_STATIC);
  21.389          
  21.390 -    result = sqlite3_step(session->add_userid_alias);
  21.391 +    result = Sqlite3_step(session->add_userid_alias);
  21.392  
  21.393      sqlite3_reset(session->add_userid_alias);
  21.394      if (result != SQLITE_DONE) {
  21.395 @@ -2404,7 +2527,7 @@
  21.396      )
  21.397  {
  21.398      PEP_STATUS status = PEP_STATUS_OK;
  21.399 -    static pEp_identity *_identity;
  21.400 +    pEp_identity *_identity = NULL;
  21.401  
  21.402      assert(session);
  21.403      assert(address);
  21.404 @@ -2420,7 +2543,7 @@
  21.405      sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
  21.406      sqlite3_bind_text(session->get_identity, 2, user_id, -1, SQLITE_STATIC);
  21.407  
  21.408 -    const int result = sqlite3_step(session->get_identity);
  21.409 +    const int result = Sqlite3_step(session->get_identity);
  21.410      switch (result) {
  21.411      case SQLITE_ROW:
  21.412          _identity = new_identity(
  21.413 @@ -2451,6 +2574,10 @@
  21.414              sqlite3_column_int(session->get_identity, 4);
  21.415          _identity->me = (unsigned int)
  21.416              sqlite3_column_int(session->get_identity, 5);
  21.417 +        _identity->major_ver =
  21.418 +            sqlite3_column_int(session->get_identity, 6);
  21.419 +        _identity->minor_ver =
  21.420 +            sqlite3_column_int(session->get_identity, 7);
  21.421      
  21.422          *identity = _identity;
  21.423          break;
  21.424 @@ -2483,7 +2610,7 @@
  21.425      sqlite3_bind_text(session->get_identities_by_userid, 1, user_id, -1, SQLITE_STATIC);
  21.426  
  21.427      int result = -1;
  21.428 -    while ((result = sqlite3_step(session->get_identities_by_userid)) == SQLITE_ROW) {
  21.429 +    while ((result = Sqlite3_step(session->get_identities_by_userid)) == SQLITE_ROW) {
  21.430              // "select address, fpr, username, comm_type, lang,"
  21.431              // "   identity.flags | pgp_keypair.flags,"
  21.432              // "   is_own"
  21.433 @@ -2525,6 +2652,10 @@
  21.434              sqlite3_column_int(session->get_identities_by_userid, 5);
  21.435          ident->me = (unsigned int)
  21.436              sqlite3_column_int(session->get_identities_by_userid, 6);
  21.437 +        ident->major_ver =
  21.438 +            sqlite3_column_int(session->get_identities_by_userid, 7);
  21.439 +        ident->minor_ver =
  21.440 +            sqlite3_column_int(session->get_identities_by_userid, 8);
  21.441      
  21.442          identity_list_add(*identities, ident);
  21.443          ident = NULL;
  21.444 @@ -2561,7 +2692,7 @@
  21.445  
  21.446      int result = -1;
  21.447      
  21.448 -    while ((result = sqlite3_step(session->get_identities_by_main_key_id)) == SQLITE_ROW) {
  21.449 +    while ((result = Sqlite3_step(session->get_identities_by_main_key_id)) == SQLITE_ROW) {
  21.450          ident = new_identity(
  21.451                      (const char *) sqlite3_column_text(session->get_identities_by_main_key_id, 0),
  21.452                      fpr,
  21.453 @@ -2591,6 +2722,10 @@
  21.454              sqlite3_column_int(session->get_identities_by_main_key_id, 5);
  21.455          ident->me = (unsigned int)
  21.456              sqlite3_column_int(session->get_identities_by_main_key_id, 6);
  21.457 +        ident->major_ver =
  21.458 +            sqlite3_column_int(session->get_identities_by_main_key_id, 7);
  21.459 +        ident->minor_ver =
  21.460 +            sqlite3_column_int(session->get_identities_by_main_key_id, 8);
  21.461      
  21.462          identity_list_add(*identities, ident);
  21.463          ident = NULL;
  21.464 @@ -2615,7 +2750,7 @@
  21.465      )
  21.466  {
  21.467      PEP_STATUS status = PEP_STATUS_OK;
  21.468 -    static pEp_identity *_identity;
  21.469 +    pEp_identity *_identity = NULL;
  21.470  
  21.471      assert(session);
  21.472      assert(address);
  21.473 @@ -2631,7 +2766,7 @@
  21.474      sqlite3_bind_text(session->get_identity_without_trust_check, 1, address, -1, SQLITE_STATIC);
  21.475      sqlite3_bind_text(session->get_identity_without_trust_check, 2, user_id, -1, SQLITE_STATIC);
  21.476  
  21.477 -    const int result = sqlite3_step(session->get_identity_without_trust_check);
  21.478 +    const int result = Sqlite3_step(session->get_identity_without_trust_check);
  21.479      switch (result) {
  21.480      case SQLITE_ROW:
  21.481          _identity = new_identity(
  21.482 @@ -2661,6 +2796,10 @@
  21.483              sqlite3_column_int(session->get_identity_without_trust_check, 3);
  21.484          _identity->me = (unsigned int)
  21.485              sqlite3_column_int(session->get_identity_without_trust_check, 4);
  21.486 +        _identity->major_ver =
  21.487 +            sqlite3_column_int(session->get_identity_without_trust_check, 5);
  21.488 +        _identity->minor_ver =
  21.489 +            sqlite3_column_int(session->get_identity_without_trust_check, 6);
  21.490      
  21.491          *identity = _identity;
  21.492          break;
  21.493 @@ -2695,7 +2834,7 @@
  21.494      sqlite3_bind_text(session->get_identities_by_address, 1, address, -1, SQLITE_STATIC);
  21.495      int result;
  21.496  
  21.497 -    while ((result = sqlite3_step(session->get_identities_by_address)) == SQLITE_ROW) {
  21.498 +    while ((result = Sqlite3_step(session->get_identities_by_address)) == SQLITE_ROW) {
  21.499          //"select user_id, main_key_id, username, comm_type, lang,"
  21.500          //"   identity.flags, is_own"
  21.501          pEp_identity *ident = new_identity(
  21.502 @@ -2726,6 +2865,10 @@
  21.503              sqlite3_column_int(session->get_identities_by_address, 4);
  21.504          ident->me = (unsigned int)
  21.505              sqlite3_column_int(session->get_identities_by_address, 5);
  21.506 +        ident->major_ver =
  21.507 +            sqlite3_column_int(session->get_identities_by_address, 6);
  21.508 +        ident->minor_ver =
  21.509 +            sqlite3_column_int(session->get_identities_by_address, 7);
  21.510      
  21.511          if (ident_list)
  21.512              identity_list_add(ident_list, ident);
  21.513 @@ -2762,7 +2905,7 @@
  21.514      sqlite3_bind_text(session->exists_identity_entry, 2, identity->user_id, -1,
  21.515                        SQLITE_STATIC);
  21.516                    
  21.517 -    int result = sqlite3_step(session->exists_identity_entry);
  21.518 +    int result = Sqlite3_step(session->exists_identity_entry);
  21.519  
  21.520      switch (result) {
  21.521          case SQLITE_ROW: {
  21.522 @@ -2797,7 +2940,7 @@
  21.523      sqlite3_bind_text(session->exists_trust_entry, 2, identity->fpr, -1,
  21.524                        SQLITE_STATIC);
  21.525                    
  21.526 -    int result = sqlite3_step(session->exists_trust_entry);
  21.527 +    int result = Sqlite3_step(session->exists_trust_entry);
  21.528      switch (result) {
  21.529          case SQLITE_ROW: {
  21.530              // yeah yeah, I know, we could be lazy here, but it looks bad.
  21.531 @@ -2821,7 +2964,7 @@
  21.532      sqlite3_reset(session->set_pgp_keypair);
  21.533      sqlite3_bind_text(session->set_pgp_keypair, 1, fpr, -1,
  21.534              SQLITE_STATIC);
  21.535 -    result = sqlite3_step(session->set_pgp_keypair);
  21.536 +    result = Sqlite3_step(session->set_pgp_keypair);
  21.537      sqlite3_reset(session->set_pgp_keypair);
  21.538      if (result != SQLITE_DONE) {
  21.539          return PEP_CANNOT_SET_PGP_KEYPAIR;
  21.540 @@ -2854,7 +2997,7 @@
  21.541      sqlite3_bind_text(set_or_update, 2, identity->fpr, -1,
  21.542              SQLITE_STATIC);
  21.543      sqlite3_bind_int(set_or_update, 3, identity->comm_type);
  21.544 -    result = sqlite3_step(set_or_update);
  21.545 +    result = Sqlite3_step(set_or_update);
  21.546      assert(result == SQLITE_DONE);
  21.547      sqlite3_reset(set_or_update);
  21.548      if (result != SQLITE_DONE)
  21.549 @@ -2882,7 +3025,10 @@
  21.550              SQLITE_STATIC);
  21.551      sqlite3_bind_int(set_or_update, 4, identity->flags);
  21.552      sqlite3_bind_int(set_or_update, 5, identity->me);
  21.553 -    int result = sqlite3_step(set_or_update);
  21.554 +    sqlite3_bind_int(set_or_update, 6, identity->major_ver);
  21.555 +    sqlite3_bind_int(set_or_update, 7, identity->minor_ver);
  21.556 +        
  21.557 +    int result = Sqlite3_step(set_or_update);
  21.558      sqlite3_reset(set_or_update);
  21.559      if (result != SQLITE_DONE)
  21.560          return PEP_CANNOT_SET_IDENTITY;
  21.561 @@ -2912,7 +3058,7 @@
  21.562          sqlite3_bind_null(set_or_update, 3);
  21.563      sqlite3_bind_text(set_or_update, 4, identity->fpr, -1,
  21.564                        SQLITE_STATIC);
  21.565 -    int result = sqlite3_step(set_or_update);
  21.566 +    int result = Sqlite3_step(set_or_update);
  21.567      sqlite3_reset(set_or_update);
  21.568      
  21.569      if (result != SQLITE_DONE)
  21.570 @@ -2995,7 +3141,7 @@
  21.571                                         guard_transaction);
  21.572  }
  21.573  
  21.574 -// This will NOT call set_as_pEp_user; you have to do that separately.
  21.575 +// This will NOT call set_as_pEp_user, nor set_pEp_version; you have to do that separately.
  21.576  DYNAMIC_API PEP_STATUS set_identity(
  21.577          PEP_SESSION session, const pEp_identity *identity
  21.578      )
  21.579 @@ -3028,7 +3174,7 @@
  21.580          sqlite3_reset(session->set_pgp_keypair);
  21.581          sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
  21.582                  SQLITE_STATIC);
  21.583 -        result = sqlite3_step(session->set_pgp_keypair);
  21.584 +        result = Sqlite3_step(session->set_pgp_keypair);
  21.585          sqlite3_reset(session->set_pgp_keypair);
  21.586          if (result != SQLITE_DONE) {
  21.587              sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  21.588 @@ -3062,6 +3208,12 @@
  21.589          }
  21.590      }
  21.591      
  21.592 +    status = set_pEp_version(session, ident_copy, ident_copy->major_ver, ident_copy->minor_ver);
  21.593 +    if (status != PEP_STATUS_OK) {
  21.594 +        sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  21.595 +        goto pEp_free;            
  21.596 +    }
  21.597 +    
  21.598      result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  21.599      if (result == SQLITE_OK)
  21.600          status = PEP_STATUS_OK;
  21.601 @@ -3081,12 +3233,14 @@
  21.602      sqlite3_reset(session->update_trust_to_pEp);
  21.603      sqlite3_bind_text(session->update_trust_to_pEp, 1, user->user_id, -1,
  21.604              SQLITE_STATIC);
  21.605 -    int result = sqlite3_step(session->update_trust_to_pEp);
  21.606 +    int result = Sqlite3_step(session->update_trust_to_pEp);
  21.607      sqlite3_reset(session->update_trust_to_pEp);
  21.608      if (result != SQLITE_DONE)
  21.609          return PEP_CANNOT_SET_TRUST;
  21.610  
  21.611 -    return PEP_STATUS_OK;
  21.612 +    PEP_STATUS status = upgrade_pEp_version_by_user_id(session, user, 2, 0);
  21.613 +    
  21.614 +    return status;
  21.615  }
  21.616  
  21.617  
  21.618 @@ -3116,7 +3270,7 @@
  21.619      sqlite3_reset(session->set_as_pEp_user);
  21.620      sqlite3_bind_text(session->set_as_pEp_user, 1, user->user_id, -1,
  21.621              SQLITE_STATIC);
  21.622 -    int result = sqlite3_step(session->set_as_pEp_user);
  21.623 +    int result = Sqlite3_step(session->set_as_pEp_user);
  21.624      sqlite3_reset(session->set_as_pEp_user);
  21.625      
  21.626      if (result != SQLITE_DONE)
  21.627 @@ -3127,6 +3281,54 @@
  21.628      return status;
  21.629  }
  21.630  
  21.631 +// This ONLY sets the version flag. Must be called outside of a transaction.
  21.632 +PEP_STATUS set_pEp_version(PEP_SESSION session, pEp_identity* ident, unsigned int new_ver_major, unsigned int new_ver_minor) {
  21.633 +    assert(session);
  21.634 +    assert(!EMPTYSTR(ident->user_id));
  21.635 +    assert(!EMPTYSTR(ident->address));
  21.636 +    
  21.637 +    sqlite3_reset(session->set_pEp_version);
  21.638 +    sqlite3_bind_double(session->set_pEp_version, 1, new_ver_major);
  21.639 +    sqlite3_bind_double(session->set_pEp_version, 2, new_ver_minor);    
  21.640 +    sqlite3_bind_text(session->set_pEp_version, 3, ident->address, -1,
  21.641 +            SQLITE_STATIC);
  21.642 +    sqlite3_bind_text(session->set_pEp_version, 4, ident->user_id, -1,
  21.643 +            SQLITE_STATIC);
  21.644 +    
  21.645 +    int result = Sqlite3_step(session->set_pEp_version);
  21.646 +    sqlite3_reset(session->set_pEp_version);
  21.647 +        
  21.648 +    if (result != SQLITE_DONE)
  21.649 +        return PEP_CANNOT_SET_PEP_VERSION;
  21.650 +    
  21.651 +    return PEP_STATUS_OK;
  21.652 +}
  21.653 +
  21.654 +// Generally ONLY called by set_as_pEp_user, and ONLY from < 2.0 to 2.0.
  21.655 +PEP_STATUS upgrade_pEp_version_by_user_id(PEP_SESSION session, 
  21.656 +        pEp_identity* ident, 
  21.657 +        unsigned int new_ver_major,
  21.658 +        unsigned int new_ver_minor
  21.659 +    ) 
  21.660 +{
  21.661 +    assert(session);
  21.662 +    assert(!EMPTYSTR(ident->user_id));
  21.663 +    
  21.664 +    sqlite3_reset(session->upgrade_pEp_version_by_user_id);
  21.665 +    sqlite3_bind_int(session->upgrade_pEp_version_by_user_id, 1, new_ver_major);
  21.666 +    sqlite3_bind_int(session->upgrade_pEp_version_by_user_id, 2, new_ver_minor);    
  21.667 +    sqlite3_bind_text(session->upgrade_pEp_version_by_user_id, 3, ident->user_id, -1,
  21.668 +            SQLITE_STATIC);
  21.669 +    
  21.670 +    int result = Sqlite3_step(session->upgrade_pEp_version_by_user_id);
  21.671 +    sqlite3_reset(session->upgrade_pEp_version_by_user_id);
  21.672 +        
  21.673 +    if (result != SQLITE_DONE)
  21.674 +        return PEP_CANNOT_SET_PEP_VERSION;
  21.675 +    
  21.676 +    return PEP_STATUS_OK;    
  21.677 +}
  21.678 +
  21.679  PEP_STATUS exists_person(PEP_SESSION session, pEp_identity* identity,
  21.680                           bool* exists) {            
  21.681      
  21.682 @@ -3151,7 +3353,7 @@
  21.683          sqlite3_reset(session->exists_person);
  21.684          sqlite3_bind_text(session->exists_person, 1, user_id, -1,
  21.685                  SQLITE_STATIC);
  21.686 -        int result = sqlite3_step(session->exists_person);
  21.687 +        int result = Sqlite3_step(session->exists_person);
  21.688          switch (result) {
  21.689              case SQLITE_ROW: {
  21.690                  // yeah yeah, I know, we could be lazy here, but it looks bad.
  21.691 @@ -3189,7 +3391,7 @@
  21.692      sqlite3_bind_text(session->delete_person, 1, user_id, -1,
  21.693                        SQLITE_STATIC);
  21.694                        
  21.695 -    int result = sqlite3_step(session->delete_person);
  21.696 +    int result = Sqlite3_step(session->delete_person);
  21.697      
  21.698      if (result != SQLITE_DONE)
  21.699          status = PEP_UNKNOWN_ERROR;
  21.700 @@ -3224,7 +3426,7 @@
  21.701      sqlite3_reset(session->is_pEp_user);
  21.702      sqlite3_bind_text(session->is_pEp_user, 1, user_id, -1,
  21.703              SQLITE_STATIC);
  21.704 -    int result = sqlite3_step(session->is_pEp_user);
  21.705 +    int result = Sqlite3_step(session->is_pEp_user);
  21.706      switch (result) {
  21.707          case SQLITE_ROW: {
  21.708              // yeah yeah, I know, we could be lazy here, but it looks bad.
  21.709 @@ -3260,7 +3462,7 @@
  21.710      sqlite3_reset(session->is_own_address);
  21.711      sqlite3_bind_text(session->is_own_address, 1, address, -1,
  21.712              SQLITE_STATIC);
  21.713 -    int result = sqlite3_step(session->is_own_address);
  21.714 +    int result = Sqlite3_step(session->is_own_address);
  21.715      switch (result) {
  21.716          case SQLITE_ROW: {
  21.717              // yeah yeah, I know, we could be lazy here, but it looks bad.
  21.718 @@ -3292,7 +3494,7 @@
  21.719      sqlite3_bind_text(session->add_into_social_graph, 3, contact_ident->user_id, -1,
  21.720              SQLITE_STATIC);
  21.721          
  21.722 -    int result = sqlite3_step(session->add_into_social_graph);
  21.723 +    int result = Sqlite3_step(session->add_into_social_graph);
  21.724      sqlite3_reset(session->add_into_social_graph);
  21.725      
  21.726      if (result != SQLITE_DONE)
  21.727 @@ -3321,7 +3523,7 @@
  21.728      sqlite3_bind_text(session->get_own_address_binding_from_contact, 2, contact->user_id, -1,
  21.729              SQLITE_STATIC);
  21.730  
  21.731 -    int result = sqlite3_step(session->get_own_address_binding_from_contact);
  21.732 +    int result = Sqlite3_step(session->get_own_address_binding_from_contact);
  21.733      
  21.734      const char* own_address = NULL;
  21.735      
  21.736 @@ -3357,7 +3559,7 @@
  21.737      sqlite3_bind_text(session->remove_fpr_as_default, 1, fpr, -1,
  21.738                        SQLITE_STATIC);
  21.739  
  21.740 -    int result = sqlite3_step(session->remove_fpr_as_default);
  21.741 +    int result = Sqlite3_step(session->remove_fpr_as_default);
  21.742      sqlite3_reset(session->remove_fpr_as_default);
  21.743      
  21.744      if (result != SQLITE_DONE)
  21.745 @@ -3383,7 +3585,7 @@
  21.746      sqlite3_bind_text(session->replace_identities_fpr, 2, old_fpr, -1,
  21.747                        SQLITE_STATIC);
  21.748  
  21.749 -    int result = sqlite3_step(session->replace_identities_fpr);
  21.750 +    int result = Sqlite3_step(session->replace_identities_fpr);
  21.751      sqlite3_reset(session->replace_identities_fpr);
  21.752      
  21.753      if (result != SQLITE_DONE)
  21.754 @@ -3403,7 +3605,7 @@
  21.755      sqlite3_bind_int(session->update_trust_for_fpr, 1, comm_type);
  21.756      sqlite3_bind_text(session->update_trust_for_fpr, 2, fpr, -1,
  21.757              SQLITE_STATIC);
  21.758 -    int result = sqlite3_step(session->update_trust_for_fpr);
  21.759 +    int result = Sqlite3_step(session->update_trust_for_fpr);
  21.760      sqlite3_reset(session->update_trust_for_fpr);
  21.761      if (result != SQLITE_DONE) {
  21.762          return PEP_CANNOT_SET_TRUST;
  21.763 @@ -3435,7 +3637,7 @@
  21.764      sqlite3_bind_text(session->set_identity_flags, 3, identity->user_id, -1,
  21.765          SQLITE_STATIC);
  21.766          
  21.767 -    result = sqlite3_step(session->set_identity_flags);
  21.768 +    result = Sqlite3_step(session->set_identity_flags);
  21.769  
  21.770      sqlite3_reset(session->set_identity_flags);
  21.771      if (result != SQLITE_DONE)
  21.772 @@ -3467,7 +3669,7 @@
  21.773              SQLITE_STATIC);
  21.774      sqlite3_bind_text(session->unset_identity_flags, 3, identity->user_id, -1,
  21.775              SQLITE_STATIC);
  21.776 -    result = sqlite3_step(session->unset_identity_flags);
  21.777 +    result = Sqlite3_step(session->unset_identity_flags);
  21.778      sqlite3_reset(session->unset_identity_flags);
  21.779      if (result != SQLITE_DONE)
  21.780          return PEP_CANNOT_SET_IDENTITY;
  21.781 @@ -3491,7 +3693,7 @@
  21.782      sqlite3_reset(session->get_trust_by_userid);
  21.783      sqlite3_bind_text(session->get_trust_by_userid, 1, user_id, -1, SQLITE_STATIC);
  21.784  
  21.785 -    while ((result = sqlite3_step(session->get_trust_by_userid)) == SQLITE_ROW) {
  21.786 +    while ((result = Sqlite3_step(session->get_trust_by_userid)) == SQLITE_ROW) {
  21.787          if (!t_list)
  21.788              t_list = new_labeled_int_list(sqlite3_column_int(session->get_trust_by_userid, 1),
  21.789                                           (const char *) sqlite3_column_text(session->get_trust_by_userid, 0));
  21.790 @@ -3822,7 +4024,7 @@
  21.791              SQLITE_STATIC);
  21.792      sqlite3_bind_text(session->replace_userid, 2, old_uid, -1,
  21.793              SQLITE_STATIC);
  21.794 -    result = sqlite3_step(session->replace_userid);
  21.795 +    result = Sqlite3_step(session->replace_userid);
  21.796  #ifndef NDEBUG
  21.797      if (result) {
  21.798          const char *errmsg = sqlite3_errmsg(session->db);
  21.799 @@ -3848,7 +4050,7 @@
  21.800      sqlite3_reset(session->delete_key);
  21.801      sqlite3_bind_text(session->delete_key, 1, fpr, -1,
  21.802              SQLITE_STATIC);
  21.803 -    result = sqlite3_step(session->delete_key);
  21.804 +    result = Sqlite3_step(session->delete_key);
  21.805      sqlite3_reset(session->delete_key);
  21.806      if (result != SQLITE_DONE)
  21.807          return PEP_CANNOT_SET_PGP_KEYPAIR;
  21.808 @@ -3869,7 +4071,7 @@
  21.809      sqlite3_reset(session->refresh_userid_default_key);
  21.810      sqlite3_bind_text(session->refresh_userid_default_key, 1, user_id, -1,
  21.811              SQLITE_STATIC);
  21.812 -    result = sqlite3_step(session->refresh_userid_default_key);
  21.813 +    result = Sqlite3_step(session->refresh_userid_default_key);
  21.814      sqlite3_reset(session->refresh_userid_default_key);
  21.815      if (result != SQLITE_DONE)
  21.816          return PEP_CANNOT_SET_PERSON;
  21.817 @@ -3893,7 +4095,7 @@
  21.818              SQLITE_STATIC);
  21.819      sqlite3_bind_text(session->replace_main_user_fpr, 2, user_id, -1,
  21.820              SQLITE_STATIC);
  21.821 -    result = sqlite3_step(session->replace_main_user_fpr);
  21.822 +    result = Sqlite3_step(session->replace_main_user_fpr);
  21.823      sqlite3_reset(session->replace_main_user_fpr);
  21.824      if (result != SQLITE_DONE)
  21.825          return PEP_CANNOT_SET_PERSON;
  21.826 @@ -3920,7 +4122,7 @@
  21.827      sqlite3_reset(session->get_main_user_fpr);
  21.828      sqlite3_bind_text(session->get_main_user_fpr, 1, user_id, -1,
  21.829                        SQLITE_STATIC);
  21.830 -    result = sqlite3_step(session->get_main_user_fpr);
  21.831 +    result = Sqlite3_step(session->get_main_user_fpr);
  21.832      switch (result) {
  21.833      case SQLITE_ROW: {
  21.834          const char* _fpr = 
  21.835 @@ -3968,7 +4170,7 @@
  21.836      sqlite3_reset(session->mark_compromised);
  21.837      sqlite3_bind_text(session->mark_compromised, 1, fpr, -1,
  21.838              SQLITE_STATIC);
  21.839 -    result = sqlite3_step(session->mark_compromised);
  21.840 +    result = Sqlite3_step(session->mark_compromised);
  21.841      sqlite3_reset(session->mark_compromised);
  21.842  
  21.843      if (result != SQLITE_DONE)
  21.844 @@ -4008,7 +4210,7 @@
  21.845              SQLITE_STATIC);
  21.846      sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
  21.847  
  21.848 -    result = sqlite3_step(session->get_trust);
  21.849 +    result = Sqlite3_step(session->get_trust);
  21.850      switch (result) {
  21.851      case SQLITE_ROW: {
  21.852          int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust,
  21.853 @@ -4047,7 +4249,7 @@
  21.854      sqlite3_reset(session->least_trust);
  21.855      sqlite3_bind_text(session->least_trust, 1, fpr, -1, SQLITE_STATIC);
  21.856  
  21.857 -    result = sqlite3_step(session->least_trust);
  21.858 +    result = Sqlite3_step(session->least_trust);
  21.859      switch (result) {
  21.860          case SQLITE_ROW: {
  21.861              int _comm_type = sqlite3_column_int(session->least_trust, 0);
  21.862 @@ -4256,9 +4458,33 @@
  21.863              identity->username))
  21.864          return PEP_ILLEGAL_VALUE;
  21.865  
  21.866 +    char* saved_username = NULL;
  21.867 +    char* at = NULL;
  21.868 +    size_t uname_len = strlen(identity->username);
  21.869 +    
  21.870 +    if (uname_len > 0)
  21.871 +        at = strstr(identity->username, "@"); 
  21.872 +    
  21.873 +    if (at) {
  21.874 +        saved_username = identity->username;
  21.875 +        identity->username = calloc(uname_len + 3, 1);
  21.876 +        if (!identity->username) {
  21.877 +            identity->username = saved_username;
  21.878 +            return PEP_OUT_OF_MEMORY;
  21.879 +        }
  21.880 +        identity->username[0] = '"';
  21.881 +        strlcpy((identity->username) + 1, saved_username, uname_len + 1);
  21.882 +        identity->username[uname_len + 1] = '"';        
  21.883 +    }
  21.884 +
  21.885      PEP_STATUS status =
  21.886          session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session,
  21.887                  identity);
  21.888 +                
  21.889 +    if (saved_username) {
  21.890 +        free(identity->username);
  21.891 +        identity->username = saved_username;
  21.892 +    }            
  21.893      if (status != PEP_STATUS_OK)
  21.894          return status;
  21.895  
  21.896 @@ -4478,7 +4704,7 @@
  21.897      int result;
  21.898  
  21.899      do {
  21.900 -        result = sqlite3_step(session->crashdump);
  21.901 +        result = Sqlite3_step(session->crashdump);
  21.902          switch (result) {
  21.903          case SQLITE_ROW:
  21.904              timestamp = (const char *) sqlite3_column_text(session->crashdump,
  21.905 @@ -4570,7 +4796,7 @@
  21.906      int result;
  21.907  
  21.908      do {
  21.909 -        result = sqlite3_step(session->languagelist);
  21.910 +        result = Sqlite3_step(session->languagelist);
  21.911          switch (result) {
  21.912          case SQLITE_ROW:
  21.913              lang = (const char *) sqlite3_column_text(session->languagelist,
  21.914 @@ -4638,7 +4864,7 @@
  21.915      const char *_phrase = NULL;
  21.916      int result;
  21.917  
  21.918 -    result = sqlite3_step(session->i18n_token);
  21.919 +    result = Sqlite3_step(session->i18n_token);
  21.920      switch (result) {
  21.921      case SQLITE_ROW:
  21.922          _phrase = (const char *) sqlite3_column_text(session->i18n_token, 0);
  21.923 @@ -4680,7 +4906,7 @@
  21.924      sqlite3_reset(session->sequence_value2);
  21.925      sqlite3_bind_text(session->sequence_value2, 1, name, -1,
  21.926              SQLITE_STATIC);
  21.927 -    int result = sqlite3_step(session->sequence_value2);
  21.928 +    int result = Sqlite3_step(session->sequence_value2);
  21.929      switch (result) {
  21.930          case SQLITE_ROW: {
  21.931              int32_t _value = (int32_t)
  21.932 @@ -4708,7 +4934,7 @@
  21.933  
  21.934      sqlite3_reset(session->sequence_value1);
  21.935      sqlite3_bind_text(session->sequence_value1, 1, name, -1, SQLITE_STATIC);
  21.936 -    int result = sqlite3_step(session->sequence_value1);
  21.937 +    int result = Sqlite3_step(session->sequence_value1);
  21.938      assert(result == SQLITE_DONE);
  21.939      sqlite3_reset(session->sequence_value1);
  21.940      if (result == SQLITE_DONE)
  21.941 @@ -4769,7 +4995,7 @@
  21.942      
  21.943      sqlite3_bind_text(session->own_key_is_listed, 1, fpr, -1,
  21.944              SQLITE_STATIC);
  21.945 -    int result = sqlite3_step(session->own_key_is_listed);
  21.946 +    int result = Sqlite3_step(session->own_key_is_listed);
  21.947      switch (result) {
  21.948          case SQLITE_ROW: {
  21.949              *own_key = (sqlite3_column_int(session->own_key_is_listed, 0) != 0);
  21.950 @@ -4813,7 +5039,7 @@
  21.951  
  21.952      int result;
  21.953      
  21.954 -    result = sqlite3_step(session->set_revoked);
  21.955 +    result = Sqlite3_step(session->set_revoked);
  21.956      switch (result) {
  21.957          case SQLITE_DONE:
  21.958              status = PEP_STATUS_OK;
  21.959 @@ -4855,7 +5081,7 @@
  21.960  
  21.961      int result;
  21.962      
  21.963 -    result = sqlite3_step(session->get_revoked);
  21.964 +    result = Sqlite3_step(session->get_revoked);
  21.965      switch (result) {
  21.966          case SQLITE_ROW: {
  21.967              *revoked_fpr = strdup((const char *)
  21.968 @@ -4899,7 +5125,7 @@
  21.969  
  21.970      int result;
  21.971      
  21.972 -    result = sqlite3_step(session->get_replacement_fpr);
  21.973 +    result = Sqlite3_step(session->get_replacement_fpr);
  21.974      switch (result) {
  21.975          case SQLITE_ROW: {
  21.976              *revoked_fpr = strdup((const char *)
  21.977 @@ -4938,7 +5164,7 @@
  21.978      sqlite3_reset(session->get_last_contacted);
  21.979      int result;
  21.980  
  21.981 -    while ((result = sqlite3_step(session->get_last_contacted)) == SQLITE_ROW) {
  21.982 +    while ((result = Sqlite3_step(session->get_last_contacted)) == SQLITE_ROW) {
  21.983          pEp_identity *ident = new_identity(
  21.984                  (const char *) sqlite3_column_text(session->get_last_contacted, 1),
  21.985                  NULL,
  21.986 @@ -4997,6 +5223,9 @@
  21.987      return PEP_ENGINE_VERSION;
  21.988  }
  21.989  
  21.990 +DYNAMIC_API const char* get_protocol_version() {
  21.991 +    return PEP_VERSION;
  21.992 +}
  21.993  
  21.994  DYNAMIC_API PEP_STATUS reset_pEptest_hack(PEP_SESSION session)
  21.995  {
  21.996 @@ -5068,3 +5297,17 @@
  21.997  }
  21.998  
  21.999  #endif
 21.1000 +
 21.1001 +DYNAMIC_API void _service_error_log(PEP_SESSION session, const char *entity,
 21.1002 +        PEP_STATUS status, const char *where)
 21.1003 +{
 21.1004 +    char buffer[128];
 21.1005 +    static const size_t size = 127;
 21.1006 +    memset(buffer, 0, size+1);
 21.1007 +#ifdef PEP_STATUS_TO_STRING
 21.1008 +    snprintf(buffer, size, "%s %.4x", pEp_status_to_string(status), status);
 21.1009 +#else
 21.1010 +    snprintf(buffer, size, "error %.4x", status);
 21.1011 +#endif
 21.1012 +    log_service(session, "### service error log ###", entity, buffer, where);
 21.1013 +}
    22.1 --- a/src/pEpEngine.h	Thu May 16 17:55:58 2019 +0200
    22.2 +++ b/src/pEpEngine.h	Wed Aug 07 14:17:27 2019 +0200
    22.3 @@ -60,6 +60,7 @@
    22.4      PEP_KEY_IMPORTED                                = 0x0220,
    22.5      PEP_NO_KEY_IMPORTED                             = 0x0221,
    22.6      PEP_KEY_IMPORT_STATUS_UNKNOWN                   = 0x0222,
    22.7 +    PEP_SOME_KEYS_IMPORTED                          = 0x0223,
    22.8      
    22.9      PEP_CANNOT_FIND_IDENTITY                        = 0x0301,
   22.10      PEP_CANNOT_SET_PERSON                           = 0x0381,
   22.11 @@ -68,6 +69,7 @@
   22.12      PEP_CANNOT_SET_TRUST                            = 0x0384,
   22.13      PEP_KEY_BLACKLISTED                             = 0x0385,
   22.14      PEP_CANNOT_FIND_PERSON                          = 0x0386,
   22.15 +    PEP_CANNOT_SET_PEP_VERSION                      = 0X0387,
   22.16      
   22.17      PEP_CANNOT_FIND_ALIAS                           = 0x0391,
   22.18      PEP_CANNOT_SET_ALIAS                            = 0x0392,
   22.19 @@ -103,6 +105,7 @@
   22.20      PEP_SYNC_NO_CHANNEL                             = 0x0904,
   22.21      PEP_SYNC_CANNOT_ENCRYPT                         = 0x0905,
   22.22      PEP_SYNC_NO_MESSAGE_SEND_CALLBACK               = 0x0906,
   22.23 +    PEP_SYNC_CANNOT_START                           = 0x0907,
   22.24  
   22.25      PEP_CANNOT_INCREASE_SEQUENCE                    = 0x0971,
   22.26  
   22.27 @@ -437,6 +440,11 @@
   22.28  #define SERVICE_LOG(session, title, entity, desc) \
   22.29      log_service((session), (title), (entity), (desc), "service " __FILE__ ":" S_LINE)
   22.30  
   22.31 +DYNAMIC_API void _service_error_log(PEP_SESSION session, const char *entity,
   22.32 +        PEP_STATUS status, const char *where);
   22.33 +
   22.34 +#define SERVICE_ERROR_LOG(session, entity, status) \
   22.35 +    _service_error_log((session), (entity), (status), __FILE__ ":" S_LINE)
   22.36  
   22.37  // trustword() - get the corresponding trustword for a 16 bit value
   22.38  //
   22.39 @@ -562,47 +570,6 @@
   22.40      PEP_ct_pEp = 0xff
   22.41  } PEP_comm_type;
   22.42  
   22.43 -static inline const char *pep_comm_type_to_string(PEP_comm_type ct) {
   22.44 -    switch (ct) {
   22.45 -    case PEP_ct_unknown: return "unknown";
   22.46 -    case PEP_ct_no_encryption: return "no_encryption";
   22.47 -    case PEP_ct_no_encrypted_channel: return "no_encrypted_channel";
   22.48 -    case PEP_ct_key_not_found: return "key_not_found";
   22.49 -    case PEP_ct_key_expired: return "key_expired";
   22.50 -    case PEP_ct_key_revoked: return "key_revoked";
   22.51 -    case PEP_ct_key_b0rken: return "key_b0rken";
   22.52 -    case PEP_ct_my_key_not_included: return "my_key_not_included";
   22.53 -    case PEP_ct_security_by_obscurity: return "security_by_obscurity";
   22.54 -    case PEP_ct_b0rken_crypto: return "b0rken_crypto";
   22.55 -    case PEP_ct_key_too_short: return "key_too_short";
   22.56 -    case PEP_ct_compromised: return "compromised";
   22.57 -    case PEP_ct_mistrusted: return "mistrusted";
   22.58 -    case PEP_ct_unconfirmed_encryption: return "unconfirmed_encryption";
   22.59 -    case PEP_ct_OpenPGP_weak_unconfirmed: return "OpenPGP_weak_unconfirmed";
   22.60 -    case PEP_ct_to_be_checked: return "to_be_checked";
   22.61 -    case PEP_ct_SMIME_unconfirmed: return "SMIME_unconfirmed";
   22.62 -    case PEP_ct_CMS_unconfirmed: return "CMS_unconfirmed";
   22.63 -    case PEP_ct_strong_but_unconfirmed: return "strong_but_unconfirmed";
   22.64 -    case PEP_ct_OpenPGP_unconfirmed: return "OpenPGP_unconfirmed";
   22.65 -    case PEP_ct_OTR_unconfirmed: return "OTR_unconfirmed";
   22.66 -    case PEP_ct_unconfirmed_enc_anon: return "unconfirmed_enc_anon";
   22.67 -    case PEP_ct_pEp_unconfirmed: return "pEp_unconfirmed";
   22.68 -    case PEP_ct_confirmed: return "confirmed";
   22.69 -    case PEP_ct_confirmed_encryption: return "confirmed_encryption";
   22.70 -    case PEP_ct_OpenPGP_weak: return "OpenPGP_weak";
   22.71 -    case PEP_ct_to_be_checked_confirmed: return "to_be_checked_confirmed";
   22.72 -    case PEP_ct_SMIME: return "SMIME";
   22.73 -    case PEP_ct_CMS: return "CMS";
   22.74 -    case PEP_ct_strong_encryption: return "strong_encryption";
   22.75 -    case PEP_ct_OpenPGP: return "OpenPGP";
   22.76 -    case PEP_ct_OTR: return "OTR";
   22.77 -    case PEP_ct_confirmed_enc_anon: return "confirmed_enc_anon";
   22.78 -    case PEP_ct_pEp: return "pEp";
   22.79 -    default: return "invalid comm type";
   22.80 -    }
   22.81 -}
   22.82 -
   22.83 -
   22.84  typedef enum _identity_flags {
   22.85      // the first octet flags are app defined settings
   22.86      PEP_idf_not_for_sync = 0x0001,   // don't use this identity for sync
   22.87 @@ -631,6 +598,8 @@
   22.88      char lang[3];               // language of conversation
   22.89                                  // ISO 639-1 ALPHA-2, last byte is 0
   22.90      bool me;                    // if this is the local user herself/himself
   22.91 +    int major_ver;              // highest version of pEp message received, if any
   22.92 +    int minor_ver;              // highest version of pEp message received, if any
   22.93      identity_flags_t flags;     // identity_flag1 | identity_flag2 | ...
   22.94  } pEp_identity;
   22.95  
   22.96 @@ -1300,6 +1269,10 @@
   22.97  //
   22.98  DYNAMIC_API const char* get_engine_version();
   22.99  
  22.100 +// get_protocol_version() - returns the pEp protocol version
  22.101 +
  22.102 +DYNAMIC_API const char *get_protocol_version();
  22.103 +
  22.104  // is_pEp_user() - returns true if the USER corresponding to this identity 
  22.105  //                 has been listed in the *person* table as a pEp user. 
  22.106  //
  22.107 @@ -1384,6 +1357,15 @@
  22.108  
  22.109  PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr);
  22.110  
  22.111 +PEP_STATUS set_pEp_version(PEP_SESSION session, pEp_identity* ident, unsigned int new_ver_major, unsigned int new_ver_minor);
  22.112 +
  22.113 +// Generally ONLY called by set_as_pEp_user, and ONLY from < 2.0 to 2.0.
  22.114 +PEP_STATUS upgrade_pEp_version_by_user_id(PEP_SESSION session, 
  22.115 +        pEp_identity* ident, 
  22.116 +        unsigned int new_ver_major,
  22.117 +        unsigned int new_ver_minor
  22.118 +    );
  22.119 +     
  22.120  // exposed for testing
  22.121  PEP_STATUS set_person(PEP_SESSION session, pEp_identity* identity,
  22.122                        bool guard_transaction);
    23.1 --- a/src/pEp_internal.h	Thu May 16 17:55:58 2019 +0200
    23.2 +++ b/src/pEp_internal.h	Wed Aug 07 14:17:27 2019 +0200
    23.3 @@ -51,7 +51,14 @@
    23.4  #define PEP_MSG_WRAP_KEY_LEN 26
    23.5  #endif
    23.6  
    23.7 +#ifndef X_PEP_MSG_WRAP_KEY
    23.8 +#define X_PEP_MSG_WRAP_KEY "X-pEp-Wrapped-Message-Info"
    23.9 +#endif
   23.10  
   23.11 +#ifndef X_PEP_SNDR_FPR_KEY
   23.12 +#define X_PEP_SNDR_FPR_KEY "X-pEp-Sender-FPR"
   23.13 +#endif
   23.14 + 
   23.15  #include "platform.h"
   23.16  
   23.17  #ifdef WIN32
   23.18 @@ -144,6 +151,7 @@
   23.19          sqlite3_stmt *tpk_save_insert_primary;
   23.20          sqlite3_stmt *tpk_save_insert_subkeys;
   23.21          sqlite3_stmt *tpk_save_insert_userids;
   23.22 +        sqlite3_stmt *delete_keypair;
   23.23      } sq_sql;
   23.24  #endif
   23.25  
   23.26 @@ -174,6 +182,7 @@
   23.27      sqlite3_stmt *exists_person;    
   23.28      sqlite3_stmt *set_as_pEp_user;
   23.29      sqlite3_stmt *is_pEp_user;
   23.30 +    sqlite3_stmt *upgrade_pEp_version_by_user_id;
   23.31      sqlite3_stmt *add_into_social_graph;
   23.32      sqlite3_stmt *get_own_address_binding_from_contact;
   23.33      sqlite3_stmt *set_revoke_contact_as_notified;
   23.34 @@ -188,6 +197,7 @@
   23.35      sqlite3_stmt *exists_identity_entry;        
   23.36      sqlite3_stmt *set_identity_flags;
   23.37      sqlite3_stmt *unset_identity_flags;
   23.38 +    sqlite3_stmt *set_pEp_version;    
   23.39      sqlite3_stmt *set_trust;
   23.40      sqlite3_stmt *update_trust;
   23.41      sqlite3_stmt *exists_trust_entry;
   23.42 @@ -251,7 +261,6 @@
   23.43      void *sync_management;
   23.44      void *sync_obj;
   23.45      struct Sync_state_s sync_state;
   23.46 -    struct own_Sync_state_s own_sync_state;
   23.47  
   23.48  //     void* sync_state_payload;
   23.49  //     char sync_uuid[37];
   23.50 @@ -449,6 +458,68 @@
   23.51      return retval;
   23.52  }
   23.53  
   23.54 +static inline float pEp_version_numeric(const char* version_str) {
   23.55 +    float retval = 0;    
   23.56 +        
   23.57 +    if (!version_str || sscanf(version_str, "%f", &retval) != 1)
   23.58 +        return 0;
   23.59 +        
   23.60 +    return retval;    
   23.61 +}
   23.62 +
   23.63 +static inline void pEp_version_major_minor(const char* version_str, unsigned int* major, unsigned int* minor) {
   23.64 +    if (!major || !minor)
   23.65 +        return;
   23.66 +                
   23.67 +    if (!version_str || sscanf(version_str, "%u.%u", major, minor) != 2) {
   23.68 +        *major = 0;
   23.69 +        *minor = 0;
   23.70 +    }
   23.71 +        
   23.72 +    return;    
   23.73 +}
   23.74 +
   23.75 +static inline int compare_versions(unsigned int first_maj, unsigned int first_min,
   23.76 +                                   unsigned int second_maj, unsigned int second_min) {
   23.77 +    if (first_maj > second_maj)
   23.78 +        return 1;
   23.79 +    if (first_maj < second_maj)
   23.80 +        return -1;
   23.81 +    if (first_min > second_min)
   23.82 +        return 1;
   23.83 +    if (first_min < second_min)
   23.84 +        return -1;
   23.85 +    return 0;    
   23.86 +}
   23.87 +
   23.88 +static inline void set_min_version(unsigned int first_maj, unsigned int first_minor,
   23.89 +                                   unsigned int second_maj, unsigned int second_minor,
   23.90 +                                   unsigned int* result_maj, unsigned int* result_minor) {
   23.91 +    int result = compare_versions(first_maj, first_minor, second_maj, second_minor);
   23.92 +    if (result < 0) {
   23.93 +        *result_maj = first_maj;
   23.94 +        *result_minor = first_minor;
   23.95 +    }
   23.96 +    else {
   23.97 +        *result_maj = second_maj;
   23.98 +        *result_minor = second_minor;
   23.99 +    }    
  23.100 +}
  23.101 +
  23.102 +static inline void set_max_version(unsigned int first_maj, unsigned int first_minor,
  23.103 +                                   unsigned int second_maj, unsigned int second_minor,
  23.104 +                                   unsigned int* result_maj, unsigned int* result_minor) {
  23.105 +    int result = compare_versions(first_maj, first_minor, second_maj, second_minor);
  23.106 +    if (result > 0) {
  23.107 +        *result_maj = first_maj;
  23.108 +        *result_minor = first_minor;
  23.109 +    }
  23.110 +    else {
  23.111 +        *result_maj = second_maj;
  23.112 +        *result_minor = second_minor;
  23.113 +    }    
  23.114 +}
  23.115 +
  23.116  #ifndef EMPTYSTR
  23.117  #define EMPTYSTR(STR) ((STR) == NULL || (STR)[0] == '\0')
  23.118  #endif
  23.119 @@ -464,7 +535,6 @@
  23.120  #define _MAX(A, B) ((B) > (A) ? (B) : (A))
  23.121  #endif
  23.122  
  23.123 -
  23.124  // These are globals used in generating message IDs and should only be
  23.125  // computed once, as they're either really constants or OS-dependent
  23.126  
  23.127 @@ -475,3 +545,15 @@
  23.128      _pEp_rand_max_bits = (int) ceil(log2((double) RAND_MAX));
  23.129      _pEp_log2_36 = log2(36);
  23.130  }
  23.131 +
  23.132 +// spinlock implementation
  23.133 +
  23.134 +static inline int Sqlite3_step(sqlite3_stmt* stmt)
  23.135 +{
  23.136 +    int rc;
  23.137 +    do {
  23.138 +        rc = sqlite3_step(stmt);
  23.139 +    } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
  23.140 +    return rc;
  23.141 +}
  23.142 +
    24.1 --- a/src/pgp_netpgp.h	Thu May 16 17:55:58 2019 +0200
    24.2 +++ b/src/pgp_netpgp.h	Wed Aug 07 14:17:27 2019 +0200
    24.3 @@ -108,3 +108,11 @@
    24.4  
    24.5  // Stub - just returns PEP_STATUS_OK, as netpgp isn't sufficient to do this.
    24.6  PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session);
    24.7 +
    24.8 +PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session, PEP_CIPHER_SUITE suite) {
    24.9 +    if (suite == PEP_CIPHER_SUITE_DEFAULT) {
   24.10 +        return PEP_STATUS_OK;
   24.11 +    } else {
   24.12 +        return PEP_CANNOT_CONFIG;
   24.13 +    }
   24.14 +}
    25.1 --- a/src/pgp_sequoia.c	Thu May 16 17:55:58 2019 +0200
    25.2 +++ b/src/pgp_sequoia.c	Wed Aug 07 14:17:27 2019 +0200
    25.3 @@ -141,9 +141,13 @@
    25.4  
    25.5      char *a_address = NULL;
    25.6      pgp_user_id_address_normalized(NULL, a_userid, &a_address);
    25.7 +    if (!a_address)
    25.8 +        pgp_user_id_other(NULL, a_userid, &a_address);
    25.9  
   25.10      char *b_address = NULL;
   25.11      pgp_user_id_address_normalized(NULL, b_userid, &b_address);
   25.12 +    if (!b_address)
   25.13 +        pgp_user_id_other(NULL, b_userid, &b_address);
   25.14  
   25.15      pgp_packet_free(a_userid);
   25.16      pgp_packet_free(b_userid);
   25.17 @@ -396,6 +400,12 @@
   25.18                               -1, &session->sq_sql.tpk_save_insert_userids, NULL);
   25.19      assert(sqlite_result == SQLITE_OK);
   25.20  
   25.21 +    sqlite_result
   25.22 +        = sqlite3_prepare_v2(session->key_db,
   25.23 +                             "DELETE FROM keys WHERE primary_key = ?",
   25.24 +                             -1, &session->sq_sql.delete_keypair, NULL);
   25.25 +    assert(sqlite_result == SQLITE_OK);
   25.26 +
   25.27   out:
   25.28      if (status != PEP_STATUS_OK)
   25.29          pgp_release(session, in_first);
   25.30 @@ -421,8 +431,6 @@
   25.31      }
   25.32  }
   25.33  
   25.34 -/* commented out to omit compiler warning about unused function
   25.35 -
   25.36  // Ensures that a fingerprint is in canonical form.  A canonical
   25.37  // fingerprint doesn't contain any white space.
   25.38  //
   25.39 @@ -437,8 +445,6 @@
   25.40      return fpr_canonicalized;
   25.41  }
   25.42  
   25.43 -*/
   25.44 -
   25.45  // step statement and load the tpk and secret.
   25.46  static PEP_STATUS key_load(PEP_SESSION, sqlite3_stmt *, pgp_tpk_t *, int *)
   25.47      __attribute__((nonnull(1, 2)));
   25.48 @@ -446,7 +452,7 @@
   25.49                             pgp_tpk_t *tpkp, int *secretp)
   25.50  {
   25.51      PEP_STATUS status = PEP_STATUS_OK;
   25.52 -    int sqlite_result = sqlite3_step(stmt);
   25.53 +    int sqlite_result = Sqlite3_step(stmt);
   25.54      switch (sqlite_result) {
   25.55      case SQLITE_ROW:
   25.56          if (tpkp) {
   25.57 @@ -692,7 +698,7 @@
   25.58      char *name = NULL;
   25.59  
   25.60      sqlite3_stmt *stmt = session->sq_sql.begin_transaction;
   25.61 -    int sqlite_result = sqlite3_step(stmt);
   25.62 +    int sqlite_result = Sqlite3_step(stmt);
   25.63      sqlite3_reset(stmt);
   25.64      if (sqlite_result != SQLITE_DONE)
   25.65          ERROR_OUT(NULL, PEP_UNKNOWN_ERROR,
   25.66 @@ -738,7 +744,7 @@
   25.67      sqlite3_bind_int(stmt, 2, is_tsk);
   25.68      sqlite3_bind_blob(stmt, 3, tsk_buffer, tsk_buffer_len, SQLITE_STATIC);
   25.69  
   25.70 -    sqlite_result = sqlite3_step(stmt);
   25.71 +    sqlite_result = Sqlite3_step(stmt);
   25.72      sqlite3_reset(stmt);
   25.73      if (sqlite_result != SQLITE_DONE)
   25.74          ERROR_OUT(NULL, PEP_UNKNOWN_ERROR,
   25.75 @@ -756,7 +762,7 @@
   25.76          sqlite3_bind_text(stmt, 1, keyid_hex, -1, SQLITE_STATIC);
   25.77          sqlite3_bind_text(stmt, 2, fpr, -1, SQLITE_STATIC);
   25.78  
   25.79 -        sqlite_result = sqlite3_step(stmt);
   25.80 +        sqlite_result = Sqlite3_step(stmt);
   25.81          sqlite3_reset(stmt);
   25.82          free(keyid_hex);
   25.83          pgp_keyid_free(keyid);
   25.84 @@ -793,50 +799,7 @@
   25.85  
   25.86          pgp_packet_t userid = pgp_user_id_new (user_id_value);
   25.87          pgp_user_id_name(NULL, userid, &name);
   25.88 -        pgp_user_id_address(NULL, userid, &email);
   25.89 -                
   25.90 -        if (!email || email[0] == '\0') {
   25.91 -            size_t uid_value_len;
   25.92 -            const char* uid_value = (const char*)pgp_user_id_value(userid, &uid_value_len);
   25.93 -            if (!uid_value) {
   25.94 -                // We need some kind of an error here, maybe?
   25.95 -                 
   25.96 -            }
   25.97 -            else {
   25.98 -                const char* split = strstr(uid_value, "<");
   25.99 -                if (split != uid_value) {       
  25.100 -                    while (split) {
  25.101 -                        if (isspace(*(split - 1)))
  25.102 -                            break;
  25.103 -                        split = strstr(split + 1, "<");
  25.104 -                    }
  25.105 -                }
  25.106 -                if (split) {
  25.107 -                    char* stopchr = strrchr(split, '>');
  25.108 -                    if (stopchr) {
  25.109 -                        int email_len = stopchr - split - 1;
  25.110 -                        email = calloc(email_len + 1, 1); 
  25.111 -                        strlcpy(email, split + 1, email_len + 1);
  25.112 -                        const char* last = NULL;
  25.113 -                        if (split != uid_value) {
  25.114 -                            for (last = split - 1; last > uid_value; last--) {
  25.115 -                                if (!isspace(*last))
  25.116 -                                    break;
  25.117 -                            }
  25.118 -                            int name_len = (last - uid_value) + 1;
  25.119 -                            name = calloc(name_len + 1, 1);
  25.120 -                            strlcpy(name, uid_value, name_len + 1);
  25.121 -                        }
  25.122 -                    }
  25.123 -                    else  
  25.124 -                        split = NULL;
  25.125 -                }
  25.126 -                if (split == NULL) {
  25.127 -                    email = strdup(uid_value);
  25.128 -                }
  25.129 -            }
  25.130 -        }
  25.131 -        
  25.132 +        pgp_user_id_address_or_other(NULL, userid, &email);
  25.133          pgp_packet_free(userid);
  25.134          free(user_id_value);
  25.135  
  25.136 @@ -846,7 +809,7 @@
  25.137              sqlite3_bind_text(stmt, 1, email, -1, SQLITE_STATIC);
  25.138              sqlite3_bind_text(stmt, 2, fpr, -1, SQLITE_STATIC);
  25.139  
  25.140 -            sqlite_result = sqlite3_step(stmt);
  25.141 +            sqlite_result = Sqlite3_step(stmt);
  25.142              sqlite3_reset(stmt);
  25.143  
  25.144              if (sqlite_result != SQLITE_DONE) {
  25.145 @@ -880,7 +843,7 @@
  25.146          stmt = status == PEP_STATUS_OK
  25.147              ? session->sq_sql.commit_transaction
  25.148              : session->sq_sql.rollback_transaction;
  25.149 -        int sqlite_result = sqlite3_step(stmt);
  25.150 +        int sqlite_result = Sqlite3_step(stmt);
  25.151          sqlite3_reset(stmt);
  25.152          if (sqlite_result != SQLITE_DONE)
  25.153              ERROR_OUT(NULL, PEP_UNKNOWN_ERROR,
  25.154 @@ -893,15 +856,12 @@
  25.155  
  25.156      free(email);
  25.157      free(name);
  25.158 -    if (user_id_iter)
  25.159 -        pgp_user_id_binding_iter_free(user_id_iter);
  25.160 -    if (key_iter)
  25.161 -        pgp_tpk_key_iter_free(key_iter);
  25.162 +    pgp_user_id_binding_iter_free(user_id_iter);
  25.163 +    pgp_tpk_key_iter_free(key_iter);
  25.164      if (stmt)
  25.165        sqlite3_reset(stmt);
  25.166      free(tsk_buffer);
  25.167 -    if (tpk)
  25.168 -        pgp_tpk_free(tpk);
  25.169 +    pgp_tpk_free(tpk);
  25.170      free(fpr);
  25.171      pgp_fingerprint_free(pgp_fpr);
  25.172  
  25.173 @@ -1053,13 +1013,10 @@
  25.174          cookie->decrypted = 1;
  25.175  
  25.176      eol:
  25.177 -        if (sk)
  25.178 -            pgp_session_key_free (sk);
  25.179 +        pgp_session_key_free (sk);
  25.180          free(keyid_str);
  25.181 -        if (key_iter)
  25.182 -            pgp_tpk_key_iter_free(key_iter);
  25.183 -        if (tpk)
  25.184 -            pgp_tpk_free(tpk);
  25.185 +        pgp_tpk_key_iter_free(key_iter);
  25.186 +        pgp_tpk_free(tpk);
  25.187      }
  25.188  
  25.189      // Consider wildcard recipients.
  25.190 @@ -1132,11 +1089,9 @@
  25.191              key_iter = NULL;
  25.192          }
  25.193      eol2:
  25.194 -        if (sk)
  25.195 -            pgp_session_key_free (sk);
  25.196 +        pgp_session_key_free (sk);
  25.197          free(keyid_str);
  25.198 -        if (key_iter)
  25.199 -            pgp_tpk_key_iter_free(key_iter);
  25.200 +        pgp_tpk_key_iter_free(key_iter);
  25.201      }
  25.202  
  25.203      if (tsks) {
  25.204 @@ -1470,12 +1425,9 @@
  25.205          free(*ptext);
  25.206      }
  25.207  
  25.208 -    if (reader)
  25.209 -        pgp_reader_free(reader);
  25.210 -    if (decryptor)
  25.211 -        pgp_reader_free(decryptor);
  25.212 -    if (writer)
  25.213 -        pgp_writer_free(writer);
  25.214 +    pgp_reader_free(reader);
  25.215 +    pgp_reader_free(decryptor);
  25.216 +    pgp_writer_free(writer);
  25.217  
  25.218      T("-> %s", pEp_status_to_string(status));
  25.219      return status;
  25.220 @@ -1495,6 +1447,33 @@
  25.221      if (size == 0 || sig_size == 0)
  25.222          return PEP_DECRYPT_WRONG_FORMAT;
  25.223  
  25.224 +#if TRACING > 0
  25.225 +    {
  25.226 +        int cr = 0;
  25.227 +        int crlf = 0;
  25.228 +        int lf = 0;
  25.229 +
  25.230 +        for (int i = 0; i < size; i ++) {
  25.231 +            // CR
  25.232 +            if (text[i] == '\r') {
  25.233 +                cr ++;
  25.234 +            }
  25.235 +            // LF
  25.236 +            if (text[i] == '\n') {
  25.237 +                if (i > 0 && text[i - 1] == '\r') {
  25.238 +                    cr --;
  25.239 +                    crlf ++;
  25.240 +                } else {
  25.241 +                    lf ++;
  25.242 +                }
  25.243 +            }
  25.244 +        }
  25.245 +
  25.246 +        T("Text to verify: %zd bytes with %d crlfs, %d bare crs and %d bare lfs",
  25.247 +          size, crlf, cr, lf);
  25.248 +    }
  25.249 +#endif
  25.250 +
  25.251      cookie.recipient_keylist = new_stringlist(NULL);
  25.252      if (!cookie.recipient_keylist)
  25.253          ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
  25.254 @@ -1569,12 +1548,9 @@
  25.255          free_stringlist(cookie.signer_keylist);
  25.256      }
  25.257  
  25.258 -    if (verifier)
  25.259 -        pgp_reader_free(verifier);
  25.260 -    if (reader)
  25.261 -        pgp_reader_free(reader);
  25.262 -    if (dsig_reader)
  25.263 -        pgp_reader_free(dsig_reader);
  25.264 +    pgp_reader_free(verifier);
  25.265 +    pgp_reader_free(reader);
  25.266 +    pgp_reader_free(dsig_reader);
  25.267  
  25.268      T("-> %s", pEp_status_to_string(status));
  25.269      return status;
  25.270 @@ -1643,6 +1619,11 @@
  25.271      if (write_status != 0)
  25.272          ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Encrypting message");
  25.273  
  25.274 +    pgp_status_t pgp_status = pgp_writer_stack_finalize (&err, ws);
  25.275 +    ws = NULL;
  25.276 +    if (pgp_status != 0)
  25.277 +        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Flushing writer");
  25.278 +
  25.279      // Add a terminating NUL for naive users
  25.280      void *t = realloc(*stext, *ssize + 1);
  25.281      if (! t)
  25.282 @@ -1651,21 +1632,10 @@
  25.283      (*stext)[*ssize] = 0;
  25.284  
  25.285   out:
  25.286 -    if (ws) {
  25.287 -        pgp_status_t pgp_status = pgp_writer_stack_finalize (&err, ws);
  25.288 -        ws = NULL;
  25.289 -        if (pgp_status != 0)
  25.290 -            ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Flushing writer");
  25.291 -    }
  25.292 -
  25.293 -    if (signer)
  25.294 -        pgp_signer_free (signer);
  25.295 -    if (signing_keypair)
  25.296 -        pgp_key_pair_free (signing_keypair);
  25.297 -    if (iter)
  25.298 -        pgp_tpk_key_iter_free (iter);
  25.299 -    if (signer_tpk)
  25.300 -        pgp_tpk_free(signer_tpk);
  25.301 +    pgp_signer_free (signer);
  25.302 +    pgp_key_pair_free (signing_keypair);
  25.303 +    pgp_tpk_key_iter_free (iter);
  25.304 +    pgp_tpk_free(signer_tpk);
  25.305  
  25.306      T("(%s)-> %s", fpr, pEp_status_to_string(status));
  25.307      return status;
  25.308 @@ -1763,29 +1733,26 @@
  25.309      if (write_status != 0)
  25.310          ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Encrypting message");
  25.311  
  25.312 +    pgp_status_t pgp_status = pgp_writer_stack_finalize (&err, ws);
  25.313 +    ws = NULL;
  25.314 +    if (pgp_status != 0)
  25.315 +        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Flushing writer");
  25.316 +
  25.317      // Add a terminating NUL for naive users
  25.318      void *t = realloc(*ctext, *csize + 1);
  25.319 -    if (! t)
  25.320 +    if (! t) {
  25.321 +        free(*ctext);
  25.322 +        *ctext = NULL;
  25.323          ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
  25.324 +    }
  25.325      *ctext = t;
  25.326      (*ctext)[*csize] = 0;
  25.327  
  25.328   out:
  25.329 -    if (ws) {
  25.330 -        pgp_status_t pgp_status = pgp_writer_stack_finalize (&err, ws);
  25.331 -        ws = NULL;
  25.332 -        if (pgp_status != 0)
  25.333 -            ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Flushing writer");
  25.334 -    }
  25.335 -
  25.336 -    if (signer)
  25.337 -        pgp_signer_free (signer);
  25.338 -    if (signing_keypair)
  25.339 -        pgp_key_pair_free (signing_keypair);
  25.340 -    if (iter)
  25.341 -        pgp_tpk_key_iter_free (iter);
  25.342 -    if (signer_tpk)
  25.343 -        pgp_tpk_free(signer_tpk);
  25.344 +    pgp_signer_free (signer);
  25.345 +    pgp_key_pair_free (signing_keypair);
  25.346 +    pgp_tpk_key_iter_free (iter);
  25.347 +    pgp_tpk_free(signer_tpk);
  25.348  
  25.349      for (int i = 0; i < keys_count; i ++)
  25.350          pgp_tpk_free(keys[i]);
  25.351 @@ -1816,6 +1783,7 @@
  25.352  {
  25.353      PEP_STATUS status = PEP_STATUS_OK;
  25.354      pgp_error_t err = NULL;
  25.355 +    pgp_packet_t userid_packet = NULL;
  25.356      char *userid = NULL;
  25.357      pgp_tpk_t tpk = NULL;
  25.358      pgp_fingerprint_t pgp_fpr = NULL;
  25.359 @@ -1827,16 +1795,22 @@
  25.360      assert(identity->fpr == NULL || identity->fpr[0] == 0);
  25.361      assert(identity->username);
  25.362  
  25.363 -    size_t userid_size = strlen(identity->username)+strlen(identity->address)+3+1;
  25.364 -    userid = (char *) calloc(1, userid_size);
  25.365 -    assert(userid);
  25.366 +    userid_packet = pgp_user_id_from_unchecked_address(&err,
  25.367 +                                                       identity->username, NULL,
  25.368 +                                                       identity->address);
  25.369 +    if (!userid_packet)
  25.370 +        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_user_id_from_other_address");
  25.371 +
  25.372 +    size_t userid_len = 0;
  25.373 +    const uint8_t *raw = pgp_user_id_value(userid_packet, &userid_len);
  25.374 +
  25.375 +    // NUL terminate it.
  25.376 +    userid = malloc(userid_len + 1);
  25.377      if (!userid)
  25.378          ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
  25.379  
  25.380 -    int r = snprintf(userid, userid_size, "%s <%s>", identity->username, identity->address);
  25.381 -    assert(r >= 0 && r < userid_size);
  25.382 -    if (r < 0)
  25.383 -        ERROR_OUT(NULL, PEP_UNKNOWN_ERROR, "snprintf");
  25.384 +    memcpy(userid, raw, userid_len);
  25.385 +    userid[userid_len] = 0;
  25.386  
  25.387      T("(%s)", userid);
  25.388  
  25.389 @@ -1864,54 +1838,70 @@
  25.390      fpr = NULL;
  25.391  
  25.392   out:
  25.393 -    if (pgp_fpr)
  25.394 -        pgp_fingerprint_free(pgp_fpr);
  25.395 +    pgp_fingerprint_free(pgp_fpr);
  25.396      free(fpr);
  25.397 -    if (tpk)
  25.398 -        pgp_tpk_free(tpk);
  25.399 +    pgp_tpk_free(tpk);
  25.400      free(userid);
  25.401 +    pgp_packet_free(userid_packet);
  25.402  
  25.403      T("-> %s", pEp_status_to_string(status));
  25.404      return status;
  25.405  }
  25.406  
  25.407 -#define SQL_DELETE "DELETE FROM keys WHERE primary_key = '%s' ;"
  25.408 -static const char *sql_delete = SQL_DELETE;
  25.409 -static const size_t sql_delete_size = sizeof(SQL_DELETE);
  25.410 -
  25.411 -// FIXME: this is deleting the key from the index but not the key data
  25.412 -
  25.413 -PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr)
  25.414 +PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr_raw)
  25.415  {
  25.416 -    assert(session && fpr && fpr[0]);
  25.417 -    if (!(session && fpr && fpr[0]))
  25.418 -        return PEP_ILLEGAL_VALUE;
  25.419 -
  25.420 -    size_t sql_size = sql_delete_size + strlen(fpr);
  25.421 -    char *sql = calloc(1, sql_size);
  25.422 -    assert(sql);
  25.423 -    if (!sql)
  25.424 -        return PEP_OUT_OF_MEMORY;
  25.425 -
  25.426 -    int r = snprintf(sql, sql_size, sql_delete, fpr);
  25.427 -    assert(r > 0 && r < sql_size);
  25.428 -    if (r < 0)
  25.429 -        return PEP_UNKNOWN_ERROR;
  25.430 -
  25.431 -    int sqlite_result = sqlite3_exec(session->key_db, sql, NULL, NULL, NULL);
  25.432 -    assert(sqlite_result == SQLITE_OK);
  25.433 -    if (sqlite_result != SQLITE_OK)
  25.434 -        return PEP_CANNOT_DELETE_KEY;
  25.435 +    PEP_STATUS status = PEP_STATUS_OK;
  25.436 +
  25.437 +    assert(session && fpr_raw && fpr_raw[0]);
  25.438 +    if (!(session && fpr_raw && fpr_raw[0]))
  25.439 +        ERROR_OUT(NULL, PEP_ILLEGAL_VALUE, "invalid arguments");
  25.440 +
  25.441 +    char *fpr = pgp_fingerprint_canonicalize(fpr_raw);
  25.442 +    if (! fpr)
  25.443 +        ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
  25.444 +
  25.445 +    T("Deleting %s", fpr);
  25.446 +
  25.447 +    sqlite3_stmt *stmt = session->sq_sql.delete_keypair;
  25.448 +    sqlite3_bind_text(stmt, 1, fpr, -1, free);
  25.449 +
  25.450 +    int sqlite_result = Sqlite3_step(stmt);
  25.451 +    sqlite3_reset(stmt);
  25.452 +    if (sqlite_result != SQLITE_DONE)
  25.453 +        ERROR_OUT(NULL, PEP_CANNOT_DELETE_KEY,
  25.454 +                  "deletion failed: %s", sqlite3_errmsg(session->key_db));
  25.455  
  25.456      sqlite_result = sqlite3_changes(session->key_db);
  25.457      assert(sqlite_result >= 0 && sqlite_result < 2);
  25.458      if (sqlite_result < 1)
  25.459 -        return PEP_KEY_NOT_FOUND;
  25.460 -
  25.461 -    return PEP_STATUS_OK;
  25.462 +        ERROR_OUT(NULL, PEP_KEY_NOT_FOUND,
  25.463 +                  "attempt to delete non-existent key: %s", fpr_raw);
  25.464 +
  25.465 + out:
  25.466 +    return status;
  25.467  }
  25.468  
  25.469 -PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
  25.470 +static unsigned int count_keydata_parts(const char* key_data, size_t size) {
  25.471 +    unsigned int retval = 0;
  25.472 +    
  25.473 +    const char* pgp_begin = "-----BEGIN PGP";
  25.474 +    size_t prefix_len = strlen(pgp_begin);
  25.475 +    size_t size_remaining = size;
  25.476 +    
  25.477 +    while (key_data) {
  25.478 +        if (size_remaining <= prefix_len || key_data[0] == '\0')
  25.479 +            break;
  25.480 +        key_data = strnstr(key_data, pgp_begin, size_remaining);
  25.481 +        if (key_data) {
  25.482 +            retval++;
  25.483 +            key_data += prefix_len;
  25.484 +            size_remaining -= prefix_len;
  25.485 +        }
  25.486 +    }
  25.487 +    return retval;
  25.488 + }
  25.489 +
  25.490 +PEP_STATUS _pgp_import_keydata(PEP_SESSION session, const char *key_data,
  25.491                                size_t size, identity_list **private_idents)
  25.492  {
  25.493      PEP_STATUS status = PEP_NO_KEY_IMPORTED;
  25.494 @@ -2025,14 +2015,96 @@
  25.495          break;
  25.496      }
  25.497  
  25.498 +    int int_result = sqlite3_exec(
  25.499 +        session->key_db,
  25.500 +        "PRAGMA wal_checkpoint(FULL);\n"
  25.501 +        ,
  25.502 +        NULL,
  25.503 +        NULL,
  25.504 +        NULL
  25.505 +    );
  25.506 +    if (int_result != SQLITE_OK)
  25.507 +        status = PEP_UNKNOWN_DB_ERROR;
  25.508 +
  25.509   out:
  25.510 -    if (parser)
  25.511 -        pgp_tpk_parser_free(parser);
  25.512 +    pgp_tpk_parser_free(parser);
  25.513  
  25.514      T("-> %s", pEp_status_to_string(status));
  25.515      return status;
  25.516  }
  25.517  
  25.518 +PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
  25.519 +                              size_t size, identity_list **private_idents)
  25.520 +{
  25.521 +    unsigned int keycount = count_keydata_parts(key_data, size);
  25.522 +    if (keycount < 2)
  25.523 +        return(_pgp_import_keydata(session, key_data, size, private_idents));
  25.524 +
  25.525 +    const char* pgp_begin = "-----BEGIN PGP";
  25.526 +    size_t prefix_len = strlen(pgp_begin);
  25.527 +        
  25.528 +    unsigned int i;
  25.529 +    const char* curr_begin;
  25.530 +    size_t curr_size;
  25.531 +    
  25.532 +    identity_list* collected_idents = NULL;        
  25.533 +    
  25.534 +    PEP_STATUS retval = PEP_KEY_IMPORTED;
  25.535 +    
  25.536 +    for (i = 0, curr_begin = key_data; i < keycount; i++) {
  25.537 +        const char* next_begin = NULL;
  25.538 +
  25.539 +        // This is assured to be OK because the count function above 
  25.540 +        // made sure that THIS round contains at least prefix_len chars
  25.541 +        // We used strnstr to count, so we know that strstr will be ok.
  25.542 +        if (strlen(curr_begin + prefix_len) > prefix_len)
  25.543 +            next_begin = strstr(curr_begin + prefix_len, pgp_begin);
  25.544 +
  25.545 +        if (next_begin)
  25.546 +            curr_size = next_begin - curr_begin;
  25.547 +        else
  25.548 +            curr_size = (key_data + size) - curr_begin;
  25.549 +        
  25.550 +        PEP_STATUS curr_status = _pgp_import_keydata(session, curr_begin, curr_size, private_idents);
  25.551 +        if (private_idents && *private_idents) {
  25.552 +            if (!collected_idents)
  25.553 +                collected_idents = *private_idents;
  25.554 +            else 
  25.555 +                identity_list_join(collected_idents, *private_idents);
  25.556 +            *private_idents = NULL;    
  25.557 +        }
  25.558 +        
  25.559 +        if (curr_status != retval) {
  25.560 +            switch (curr_status) {
  25.561 +                case PEP_NO_KEY_IMPORTED:
  25.562 +                case PEP_KEY_NOT_FOUND:
  25.563 +                case PEP_UNKNOWN_ERROR:
  25.564 +                    switch (retval) {
  25.565 +                        case PEP_KEY_IMPORTED:
  25.566 +                            retval = PEP_SOME_KEYS_IMPORTED;
  25.567 +                            break;
  25.568 +                        case PEP_UNKNOWN_ERROR:
  25.569 +                            retval = curr_status;
  25.570 +                            break;
  25.571 +                        default:
  25.572 +                            break;
  25.573 +                    }
  25.574 +                    break;
  25.575 +                case PEP_KEY_IMPORTED:
  25.576 +                    retval = PEP_SOME_KEYS_IMPORTED;
  25.577 +                default:
  25.578 +                    break;
  25.579 +            }        
  25.580 +        }        
  25.581 +        curr_begin = next_begin;     
  25.582 +    }
  25.583 +    
  25.584 +    if (private_idents)
  25.585 +        *private_idents = collected_idents;
  25.586 +    
  25.587 +    return retval;    
  25.588 +}
  25.589 +
  25.590  PEP_STATUS pgp_export_keydata(
  25.591          PEP_SESSION session, const char *fpr, char **key_data, size_t *size,
  25.592          bool secret)
  25.593 @@ -2041,6 +2113,7 @@
  25.594      pgp_error_t err = NULL;
  25.595      pgp_tpk_t tpk = NULL;
  25.596      pgp_writer_t armor_writer = NULL;
  25.597 +    pgp_writer_t memory_writer = NULL;
  25.598  
  25.599      assert(session);
  25.600      assert(fpr);
  25.601 @@ -2057,13 +2130,12 @@
  25.602      status = tpk_find_by_fpr_hex(session, fpr, secret, &tpk, NULL);
  25.603      ERROR_OUT(NULL, status, "Looking up TSK for %s", fpr);
  25.604  
  25.605 -    pgp_writer_t memory_writer = pgp_writer_alloc((void **) key_data, size);
  25.606 +    memory_writer = pgp_writer_alloc((void **) key_data, size);
  25.607      if (! memory_writer)
  25.608          ERROR_OUT(NULL, PEP_UNKNOWN_ERROR, "creating memory writer");
  25.609      armor_writer = pgp_armor_writer_new(&err, memory_writer,
  25.610                                          PGP_ARMOR_KIND_PUBLICKEY, NULL, 0);
  25.611      if (! armor_writer) {
  25.612 -        pgp_writer_free(memory_writer);
  25.613          ERROR_OUT(err, PEP_UNKNOWN_ERROR, "creating armored writer");
  25.614      }
  25.615  
  25.616 @@ -2081,19 +2153,30 @@
  25.617      if (armor_writer)
  25.618          pgp_writer_free(armor_writer);
  25.619  
  25.620 +    if (memory_writer) {
  25.621 +        if (status == PEP_STATUS_OK) {
  25.622 +            // Add a trailing NUL.
  25.623 +            pgp_writer_write(NULL, memory_writer, (const uint8_t *) "", 1);
  25.624 +        }
  25.625 +
  25.626 +        pgp_writer_free(memory_writer);
  25.627 +    }
  25.628 +
  25.629      if (tpk)
  25.630          pgp_tpk_free(tpk);
  25.631  
  25.632 +    (*size)--;  // Sequoia is delivering the 0 byte at the end with size, but
  25.633 +                // pEp is expecting it without
  25.634      T("(%s) -> %s", fpr, pEp_status_to_string(status));
  25.635      return status;
  25.636  }
  25.637  
  25.638 -char* _undot_address(const char* address) {
  25.639 +static char *_undot_address(const char* address) {
  25.640      if (!address)
  25.641          return NULL;
  25.642  
  25.643      int addr_len = strlen(address);
  25.644 -    const char* at = strstr(address, "@");
  25.645 +    const char* at = memchr(address, '@', addr_len);
  25.646  
  25.647      if (!at)
  25.648          at = address + addr_len;
  25.649 @@ -2242,10 +2325,8 @@
  25.650      }
  25.651  
  25.652   out:
  25.653 -    if (tpk)
  25.654 -        pgp_tpk_free(tpk);
  25.655 -    if (fpr)
  25.656 -        pgp_fingerprint_free(fpr);
  25.657 +    pgp_tpk_free(tpk);
  25.658 +    pgp_fingerprint_free(fpr);
  25.659  
  25.660      if (status == PEP_KEY_NOT_FOUND)
  25.661          status = PEP_STATUS_OK;
  25.662 @@ -2312,6 +2393,245 @@
  25.663      return PEP_UNKNOWN_ERROR;
  25.664  }
  25.665  
  25.666 +
  25.667 +PEP_STATUS pgp_renew_key(
  25.668 +    PEP_SESSION session, const char *fpr, const timestamp *ts)
  25.669 +{
  25.670 +    PEP_STATUS status = PEP_STATUS_OK;
  25.671 +    pgp_error_t err = NULL;
  25.672 +    pgp_tpk_t tpk = NULL;
  25.673 +    pgp_tpk_key_iter_t iter = NULL;
  25.674 +    pgp_key_pair_t keypair = NULL;
  25.675 +    pgp_signer_t signer = NULL;
  25.676 +    time_t t = mktime((struct tm *) ts);
  25.677 +
  25.678 +    T("(%s)", fpr);
  25.679 +
  25.680 +    status = tpk_find_by_fpr_hex(session, fpr, true, &tpk, NULL);
  25.681 +    ERROR_OUT(NULL, status, "Looking up '%s'", fpr);
  25.682 +
  25.683 +    uint32_t creation_time = pgp_key_creation_time(pgp_tpk_primary(tpk));
  25.684 +    if (creation_time > t)
  25.685 +        // The creation time is after the expiration time!
  25.686 +        ERROR_OUT(NULL, PEP_UNKNOWN_ERROR,
  25.687 +                  "creation time can't be after expiration time");
  25.688 +
  25.689 +    uint32_t delta = t - creation_time;
  25.690 +
  25.691 +
  25.692 +    iter = pgp_tpk_key_iter_valid(tpk);
  25.693 +    pgp_tpk_key_iter_certification_capable (iter);
  25.694 +    pgp_tpk_key_iter_unencrypted_secret (iter, true);
  25.695 +
  25.696 +    // If there are multiple certification capable subkeys, we just
  25.697 +    // take the first one, whichever one that happens to be.
  25.698 +    pgp_key_t key = pgp_tpk_key_iter_next (iter, NULL, NULL);
  25.699 +    if (! key)
  25.700 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR,
  25.701 +                   "%s has no usable certification capable key", fpr);
  25.702 +
  25.703 +    keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
  25.704 +    if (! keypair)
  25.705 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
  25.706 +
  25.707 +    signer = pgp_key_pair_as_signer (keypair);
  25.708 +    if (! signer)
  25.709 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
  25.710 +
  25.711 +    tpk = pgp_tpk_set_expiry(&err, tpk, signer, delta);
  25.712 +    if (! tpk)
  25.713 +        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration");
  25.714 +
  25.715 +    status = tpk_save(session, tpk, NULL);
  25.716 +    tpk = NULL;
  25.717 +    ERROR_OUT(NULL, status, "Saving %s", fpr);
  25.718 +
  25.719 + out:
  25.720 +    pgp_signer_free (signer);
  25.721 +    pgp_key_pair_free (keypair);
  25.722 +    pgp_tpk_key_iter_free (iter);
  25.723 +    pgp_tpk_free(tpk);
  25.724 +
  25.725 +    T("(%s) -> %s", fpr, pEp_status_to_string(status));
  25.726 +    return status;
  25.727 +}
  25.728 +
  25.729 +PEP_STATUS pgp_revoke_key(
  25.730 +    PEP_SESSION session, const char *fpr, const char *reason)
  25.731 +{
  25.732 +    PEP_STATUS status = PEP_STATUS_OK;
  25.733 +    pgp_error_t err = NULL;
  25.734 +    pgp_tpk_t tpk = NULL;
  25.735 +    pgp_tpk_key_iter_t iter = NULL;
  25.736 +    pgp_key_pair_t keypair = NULL;
  25.737 +    pgp_signer_t signer = NULL;
  25.738 +
  25.739 +    T("(%s)", fpr);
  25.740 +
  25.741 +    status = tpk_find_by_fpr_hex(session, fpr, true, &tpk, NULL);
  25.742 +    ERROR_OUT(NULL, status, "Looking up %s", fpr);
  25.743 +
  25.744 +    iter = pgp_tpk_key_iter_valid(tpk);
  25.745 +    pgp_tpk_key_iter_certification_capable (iter);
  25.746 +    pgp_tpk_key_iter_unencrypted_secret (iter, true);
  25.747 +
  25.748 +    // If there are multiple certification capable subkeys, we just
  25.749 +    // take the first one, whichever one that happens to be.
  25.750 +    pgp_key_t key = pgp_tpk_key_iter_next (iter, NULL, NULL);
  25.751 +    if (! key)
  25.752 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR,
  25.753 +                   "%s has no usable certification capable key", fpr);
  25.754 +
  25.755 +    keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
  25.756 +    if (! keypair)
  25.757 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
  25.758 +
  25.759 +    signer = pgp_key_pair_as_signer (keypair);
  25.760 +    if (! signer)
  25.761 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
  25.762 +
  25.763 +    tpk = pgp_tpk_revoke_in_place(&err, tpk, signer,
  25.764 +                                  PGP_REASON_FOR_REVOCATION_UNSPECIFIED,
  25.765 +                                  reason);
  25.766 +    if (! tpk)
  25.767 +        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration");
  25.768 +
  25.769 +    assert(pgp_revocation_status_variant(pgp_tpk_revocation_status(tpk))
  25.770 +           == PGP_REVOCATION_STATUS_REVOKED);
  25.771 +
  25.772 +    status = tpk_save(session, tpk, NULL);
  25.773 +    tpk = NULL;
  25.774 +    ERROR_OUT(NULL, status, "Saving %s", fpr);
  25.775 +
  25.776 + out:
  25.777 +    pgp_signer_free (signer);
  25.778 +    pgp_key_pair_free (keypair);
  25.779 +    pgp_tpk_key_iter_free (iter);
  25.780 +    pgp_tpk_free(tpk);
  25.781 +
  25.782 +    T("(%s) -> %s", fpr, pEp_status_to_string(status));
  25.783 +    return status;
  25.784 +}
  25.785 +
  25.786 +static void _pgp_key_expired(pgp_tpk_t tpk, const time_t when, bool* expired)
  25.787 +{
  25.788 +    // Is the TPK live?
  25.789 +    *expired = !pgp_tpk_alive_at(tpk, when);
  25.790 +
  25.791 +#ifdef TRACING
  25.792 +    {
  25.793 +        char buffer[26];
  25.794 +        time_t now = time(NULL);
  25.795 +
  25.796 +        if (when == now || when == now - 1) {
  25.797 +            sprintf(buffer, "now");
  25.798 +        } else {
  25.799 +            struct tm tm;
  25.800 +            gmtime_r(&when, &tm);
  25.801 +            strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm);
  25.802 +        }
  25.803 +
  25.804 +        T("TPK is %slive as of %s", *expired ? "not " : "", buffer);
  25.805 +    }
  25.806 +#endif
  25.807 +    if (*expired)
  25.808 +        goto out;
  25.809 +
  25.810 +    // Are there at least one certification subkey, one signing subkey
  25.811 +    // and one encryption subkey that are live?
  25.812 +    //    int can_certify = 0, can_encrypt = 0, can_sign = 0;
  25.813 +    int can_encrypt = 0, can_sign = 0;
  25.814 +
  25.815 +    pgp_tpk_key_iter_t key_iter = pgp_tpk_key_iter_valid(tpk);
  25.816 +    pgp_key_t key;
  25.817 +    pgp_signature_t sig;
  25.818 +    pgp_revocation_status_t rev;
  25.819 +    while ((key = pgp_tpk_key_iter_next(key_iter, &sig, &rev))) {
  25.820 +        if (! sig)
  25.821 +            continue;
  25.822 +
  25.823 +        if (pgp_signature_can_encrypt_for_transport(sig)
  25.824 +            || pgp_signature_can_encrypt_at_rest(sig))
  25.825 +            can_encrypt = 1;
  25.826 +        if (pgp_signature_can_sign(sig))
  25.827 +            can_sign = 1;
  25.828 +        // if (pgp_signature_can_certify(sig))
  25.829 +        //     can_certify = 1;
  25.830 +
  25.831 +//        if (can_encrypt && can_sign && can_certify)
  25.832 +        if (can_encrypt && can_sign)
  25.833 +            break;
  25.834 +    }
  25.835 +    pgp_tpk_key_iter_free(key_iter);
  25.836 +
  25.837 +//    *expired = !(can_encrypt && can_sign && can_certify);
  25.838 +    *expired = !(can_encrypt && can_sign);
  25.839 +
  25.840 +    T("Key can%s encrypt, can%s sign, can%s certify => %sexpired",
  25.841 +      can_encrypt ? "" : "not",
  25.842 +      can_sign ? "" : "not",
  25.843 +      // can_certify ? "" : "not",
  25.844 +      *expired ? "" : "not ");
  25.845 +      
  25.846 +out:
  25.847 +    // Er, this might be problematic in terms of internal vs. external in log. FIXME?
  25.848 +    T("(%s) -> %s (expired: %d)", fpr, pEp_status_to_string(status), *expired);
  25.849 +    return;
  25.850 +}
  25.851 +                            
  25.852 +PEP_STATUS pgp_key_expired(PEP_SESSION session, const char *fpr,
  25.853 +                           const time_t when, bool *expired)
  25.854 +{
  25.855 +    PEP_STATUS status = PEP_STATUS_OK;
  25.856 +    pgp_tpk_t tpk = NULL;
  25.857 +    T("(%s)", fpr);
  25.858 +
  25.859 +    assert(session);
  25.860 +    assert(fpr);
  25.861 +    assert(expired);
  25.862 +
  25.863 +    *expired = false;
  25.864 +
  25.865 +    pgp_fingerprint_t pgp_fpr = pgp_fingerprint_from_hex(fpr);
  25.866 +    status = tpk_find_by_fpr(session, pgp_fpr, false, &tpk, NULL);
  25.867 +    pgp_fingerprint_free(pgp_fpr);
  25.868 +    ERROR_OUT(NULL, status, "Looking up %s", fpr);
  25.869 +
  25.870 +    _pgp_key_expired(tpk, when, expired);
  25.871 + out:
  25.872 +    pgp_tpk_free(tpk);
  25.873 +    T("(%s) -> %s (expired: %d)", fpr, pEp_status_to_string(status), *expired);
  25.874 +    return status;
  25.875 +}
  25.876 +
  25.877 +PEP_STATUS pgp_key_revoked(PEP_SESSION session, const char *fpr, bool *revoked)
  25.878 +{
  25.879 +    PEP_STATUS status = PEP_STATUS_OK;
  25.880 +    pgp_tpk_t tpk;
  25.881 +
  25.882 +    T("(%s)", fpr);
  25.883 +
  25.884 +    assert(session);
  25.885 +    assert(fpr);
  25.886 +    assert(revoked);
  25.887 +
  25.888 +    *revoked = false;
  25.889 +
  25.890 +    pgp_fingerprint_t pgp_fpr = pgp_fingerprint_from_hex(fpr);
  25.891 +    status = tpk_find_by_fpr(session, pgp_fpr, false, &tpk, NULL);
  25.892 +    pgp_fingerprint_free(pgp_fpr);
  25.893 +    ERROR_OUT(NULL, status, "Looking up %s", fpr);
  25.894 +
  25.895 +    pgp_revocation_status_t rs = pgp_tpk_revocation_status(tpk);
  25.896 +    *revoked = pgp_revocation_status_variant(rs) == PGP_REVOCATION_STATUS_REVOKED;
  25.897 +    pgp_revocation_status_free (rs);
  25.898 +    pgp_tpk_free(tpk);
  25.899 +
  25.900 + out:
  25.901 +    T("(%s) -> %s", fpr, pEp_status_to_string(status));
  25.902 +    return status;
  25.903 +}
  25.904 +
  25.905  PEP_STATUS pgp_get_key_rating(
  25.906      PEP_SESSION session, const char *fpr, PEP_comm_type *comm_type)
  25.907  {
  25.908 @@ -2331,10 +2651,20 @@
  25.909  
  25.910      *comm_type = PEP_ct_OpenPGP_unconfirmed;
  25.911  
  25.912 -    if (pgp_tpk_expired(tpk)) {
  25.913 +    bool expired = false;
  25.914 +    
  25.915 +    // MUST guarantee the same behaviour.
  25.916 +    _pgp_key_expired(tpk, time(NULL), &expired);
  25.917 +    
  25.918 +    if (expired) {
  25.919          *comm_type = PEP_ct_key_expired;
  25.920 -        goto out;
  25.921 +        goto out;        
  25.922      }
  25.923 +    
  25.924 +    // if (pgp_tpk_expired(tpk)) {
  25.925 +    //     *comm_type = PEP_ct_key_expired;
  25.926 +    //     goto out;
  25.927 +    // }
  25.928  
  25.929      pgp_revocation_status_t rs = pgp_tpk_revocation_status(tpk);
  25.930      pgp_revocation_status_variant_t rsv = pgp_revocation_status_variant(rs);
  25.931 @@ -2390,226 +2720,13 @@
  25.932      }
  25.933  
  25.934   out:
  25.935 -    if (tpk)
  25.936 -        pgp_tpk_free(tpk);
  25.937 -
  25.938 -    T("(%s) -> %s", fpr, pep_comm_type_to_string(*comm_type));
  25.939 +    pgp_tpk_free(tpk);
  25.940 +
  25.941 +    T("(%s) -> %s", fpr, pEp_comm_type_to_string(*comm_type));
  25.942      return status;
  25.943  }
  25.944  
  25.945  
  25.946 -PEP_STATUS pgp_renew_key(
  25.947 -    PEP_SESSION session, const char *fpr, const timestamp *ts)
  25.948 -{
  25.949 -    PEP_STATUS status = PEP_STATUS_OK;
  25.950 -    pgp_error_t err = NULL;
  25.951 -    pgp_tpk_t tpk = NULL;
  25.952 -    pgp_tpk_key_iter_t iter = NULL;
  25.953 -    pgp_key_pair_t keypair = NULL;
  25.954 -    pgp_signer_t signer = NULL;
  25.955 -    time_t t = mktime((struct tm *) ts);
  25.956 -
  25.957 -    T("(%s)", fpr);
  25.958 -
  25.959 -    status = tpk_find_by_fpr_hex(session, fpr, true, &tpk, NULL);
  25.960 -    ERROR_OUT(NULL, status, "Looking up '%s'", fpr);
  25.961 -
  25.962 -    uint32_t creation_time = pgp_key_creation_time(pgp_tpk_primary(tpk));
  25.963 -    if (creation_time > t)
  25.964 -        // The creation time is after the expiration time!
  25.965 -        ERROR_OUT(NULL, PEP_UNKNOWN_ERROR,
  25.966 -                  "creation time can't be after expiration time");
  25.967 -
  25.968 -    uint32_t delta = t - creation_time;
  25.969 -
  25.970 -
  25.971 -    iter = pgp_tpk_key_iter_valid(tpk);
  25.972 -    pgp_tpk_key_iter_certification_capable (iter);
  25.973 -    pgp_tpk_key_iter_unencrypted_secret (iter, true);
  25.974 -
  25.975 -    // If there are multiple certification capable subkeys, we just
  25.976 -    // take the first one, whichever one that happens to be.
  25.977 -    pgp_key_t key = pgp_tpk_key_iter_next (iter, NULL, NULL);
  25.978 -    if (! key)
  25.979 -        ERROR_OUT (err, PEP_UNKNOWN_ERROR,
  25.980 -                   "%s has no usable certification capable key", fpr);
  25.981 -
  25.982 -    keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
  25.983 -    if (! keypair)
  25.984 -        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
  25.985 -
  25.986 -    signer = pgp_key_pair_as_signer (keypair);
  25.987 -    if (! signer)
  25.988 -        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
  25.989 -
  25.990 -    tpk = pgp_tpk_set_expiry(&err, tpk, signer, delta);
  25.991 -    if (! tpk)
  25.992 -        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration");
  25.993 -
  25.994 -    status = tpk_save(session, tpk, NULL);
  25.995 -    tpk = NULL;
  25.996 -    ERROR_OUT(NULL, status, "Saving %s", fpr);
  25.997 -
  25.998 - out:
  25.999 -    if (signer)
 25.1000 -        pgp_signer_free (signer);
 25.1001 -    if (keypair)
 25.1002 -        pgp_key_pair_free (keypair);
 25.1003 -    if (iter)
 25.1004 -        pgp_tpk_key_iter_free (iter);
 25.1005 -    if (tpk)
 25.1006 -        pgp_tpk_free(tpk);
 25.1007 -
 25.1008 -    T("(%s) -> %s", fpr, pEp_status_to_string(status));
 25.1009 -    return status;
 25.1010 -}
 25.1011 -
 25.1012 -PEP_STATUS pgp_revoke_key(
 25.1013 -    PEP_SESSION session, const char *fpr, const char *reason)
 25.1014 -{
 25.1015 -    PEP_STATUS status = PEP_STATUS_OK;
 25.1016 -    pgp_error_t err = NULL;
 25.1017 -    pgp_tpk_t tpk = NULL;
 25.1018 -    pgp_tpk_key_iter_t iter = NULL;
 25.1019 -    pgp_key_pair_t keypair = NULL;
 25.1020 -    pgp_signer_t signer = NULL;
 25.1021 -
 25.1022 -    T("(%s)", fpr);
 25.1023 -
 25.1024 -    status = tpk_find_by_fpr_hex(session, fpr, true, &tpk, NULL);
 25.1025 -    ERROR_OUT(NULL, status, "Looking up %s", fpr);
 25.1026 -
 25.1027 -    iter = pgp_tpk_key_iter_valid(tpk);
 25.1028 -    pgp_tpk_key_iter_certification_capable (iter);
 25.1029 -    pgp_tpk_key_iter_unencrypted_secret (iter, true);
 25.1030 -
 25.1031 -    // If there are multiple certification capable subkeys, we just
 25.1032 -    // take the first one, whichever one that happens to be.
 25.1033 -    pgp_key_t key = pgp_tpk_key_iter_next (iter, NULL, NULL);
 25.1034 -    if (! key)
 25.1035 -        ERROR_OUT (err, PEP_UNKNOWN_ERROR,
 25.1036 -                   "%s has no usable certification capable key", fpr);
 25.1037 -
 25.1038 -    keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
 25.1039 -    if (! keypair)
 25.1040 -        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
 25.1041 -
 25.1042 -    signer = pgp_key_pair_as_signer (keypair);
 25.1043 -    if (! signer)
 25.1044 -        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
 25.1045 -
 25.1046 -    tpk = pgp_tpk_revoke_in_place(&err, tpk, signer,
 25.1047 -                                  PGP_REASON_FOR_REVOCATION_UNSPECIFIED,
 25.1048 -                                  reason);
 25.1049 -    if (! tpk)
 25.1050 -        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration");
 25.1051 -
 25.1052 -    assert(pgp_revocation_status_variant(pgp_tpk_revocation_status(tpk))
 25.1053 -           == PGP_REVOCATION_STATUS_REVOKED);
 25.1054 -
 25.1055 -    status = tpk_save(session, tpk, NULL);
 25.1056 -    tpk = NULL;
 25.1057 -    ERROR_OUT(NULL, status, "Saving %s", fpr);
 25.1058 -
 25.1059 - out:
 25.1060 -    if (signer)
 25.1061 -        pgp_signer_free (signer);
 25.1062 -    if (keypair)
 25.1063 -        pgp_key_pair_free (keypair);
 25.1064 -    if (iter)
 25.1065 -        pgp_tpk_key_iter_free (iter);
 25.1066 -    if (tpk)
 25.1067 -        pgp_tpk_free(tpk);
 25.1068 -
 25.1069 -    T("(%s) -> %s", fpr, pEp_status_to_string(status));
 25.1070 -    return status;
 25.1071 -}
 25.1072 -
 25.1073 -PEP_STATUS pgp_key_expired(PEP_SESSION session, const char *fpr,
 25.1074 -                           const time_t when, bool *expired)
 25.1075 -{
 25.1076 -    PEP_STATUS status = PEP_STATUS_OK;
 25.1077 -    pgp_tpk_t tpk = NULL;
 25.1078 -    T("(%s)", fpr);
 25.1079 -
 25.1080 -    assert(session);
 25.1081 -    assert(fpr);
 25.1082 -    assert(expired);
 25.1083 -
 25.1084 -    *expired = false;
 25.1085 -
 25.1086 -    pgp_fingerprint_t pgp_fpr = pgp_fingerprint_from_hex(fpr);
 25.1087 -    status = tpk_find_by_fpr(session, pgp_fpr, false, &tpk, NULL);
 25.1088 -    pgp_fingerprint_free(pgp_fpr);
 25.1089 -    ERROR_OUT(NULL, status, "Looking up %s", fpr);
 25.1090 -
 25.1091 -    // Is the TPK live?
 25.1092 -    *expired = !pgp_tpk_alive_at(tpk, when);
 25.1093 -    if (*expired)
 25.1094 -        goto out;
 25.1095 -
 25.1096 -    // Are there at least one certification subkey, one signing subkey
 25.1097 -    // and one encryption subkey that are live?
 25.1098 -    int can_certify = 0, can_encrypt = 0, can_sign = 0;
 25.1099 -
 25.1100 -    pgp_tpk_key_iter_t key_iter = pgp_tpk_key_iter_valid(tpk);
 25.1101 -    pgp_key_t key;
 25.1102 -    pgp_signature_t sig;
 25.1103 -    pgp_revocation_status_t rev;
 25.1104 -    while ((key = pgp_tpk_key_iter_next(key_iter, &sig, &rev))) {
 25.1105 -        if (! sig)
 25.1106 -            continue;
 25.1107 -
 25.1108 -        if (pgp_signature_can_encrypt_for_transport(sig)
 25.1109 -            || pgp_signature_can_encrypt_at_rest(sig))
 25.1110 -            can_encrypt = 1;
 25.1111 -        if (pgp_signature_can_sign(sig))
 25.1112 -            can_sign = 1;
 25.1113 -        if (pgp_signature_can_certify(sig))
 25.1114 -            can_certify = 1;
 25.1115 -
 25.1116 -        if (can_encrypt && can_sign && can_certify)
 25.1117 -            break;
 25.1118 -    }
 25.1119 -    pgp_tpk_key_iter_free(key_iter);
 25.1120 -
 25.1121 -    *expired = !(can_encrypt && can_sign && can_certify);
 25.1122 -
 25.1123 - out:
 25.1124 -    if (tpk)
 25.1125 -        pgp_tpk_free(tpk);
 25.1126 -    T("(%s) -> %s", fpr, pEp_status_to_string(status));
 25.1127 -    return status;
 25.1128 -}
 25.1129 -
 25.1130 -PEP_STATUS pgp_key_revoked(PEP_SESSION session, const char *fpr, bool *revoked)
 25.1131 -{
 25.1132 -    PEP_STATUS status = PEP_STATUS_OK;
 25.1133 -    pgp_tpk_t tpk;
 25.1134 -
 25.1135 -    T("(%s)", fpr);
 25.1136 -
 25.1137 -    assert(session);
 25.1138 -    assert(fpr);
 25.1139 -    assert(revoked);
 25.1140 -
 25.1141 -    *revoked = false;
 25.1142 -
 25.1143 -    pgp_fingerprint_t pgp_fpr = pgp_fingerprint_from_hex(fpr);
 25.1144 -    status = tpk_find_by_fpr(session, pgp_fpr, false, &tpk, NULL);
 25.1145 -    pgp_fingerprint_free(pgp_fpr);
 25.1146 -    ERROR_OUT(NULL, status, "Looking up %s", fpr);
 25.1147 -
 25.1148 -    pgp_revocation_status_t rs = pgp_tpk_revocation_status(tpk);
 25.1149 -    *revoked = pgp_revocation_status_variant(rs) == PGP_REVOCATION_STATUS_REVOKED;
 25.1150 -    pgp_revocation_status_free (rs);
 25.1151 -    pgp_tpk_free(tpk);
 25.1152 -
 25.1153 - out:
 25.1154 -    T("(%s) -> %s", fpr, pEp_status_to_string(status));
 25.1155 -    return status;
 25.1156 -}
 25.1157 -
 25.1158  PEP_STATUS pgp_key_created(PEP_SESSION session, const char *fpr, time_t *created)
 25.1159  {
 25.1160      PEP_STATUS status = PEP_STATUS_OK;
 25.1161 @@ -2655,4 +2772,3 @@
 25.1162        fpr, *has_private ? "priv" : "pub", pEp_status_to_string(status));
 25.1163      return status;
 25.1164  }
 25.1165 -
    26.1 --- a/src/platform_unix.c	Thu May 16 17:55:58 2019 +0200
    26.2 +++ b/src/platform_unix.c	Wed Aug 07 14:17:27 2019 +0200
    26.3 @@ -198,6 +198,43 @@
    26.4      return retval;
    26.5  }
    26.6  
    26.7 +char *strnstr(const char *big, const char *little, size_t len) {
    26.8 +    if (big == NULL || little == NULL)
    26.9 +        return NULL;
   26.10 +        
   26.11 +    if (*little == '\0')
   26.12 +        return (char*)big;
   26.13 +        
   26.14 +    const char* curr_big = big;
   26.15 +    
   26.16 +    size_t little_len = strlen(little);
   26.17 +    size_t remaining = len;
   26.18 +
   26.19 +    const char* retval = NULL;
   26.20 +    
   26.21 +    for (remaining = len; remaining >= little_len && *curr_big != '\0'; remaining--, curr_big++) {
   26.22 +        // find first-char match
   26.23 +        if (*curr_big != *little) {
   26.24 +            continue;
   26.25 +        }
   26.26 +        retval = curr_big;
   26.27 +
   26.28 +        const char* inner_big = retval + 1;
   26.29 +        const char* curr_little = little + 1;
   26.30 +        int j;
   26.31 +        for (j = 1; j < little_len; j++, inner_big++, curr_little++) {
   26.32 +            if (*inner_big != *curr_little) {
   26.33 +                retval = NULL;
   26.34 +                break;
   26.35 +            }    
   26.36 +        }
   26.37 +        if (retval)
   26.38 +            break;
   26.39 +    }
   26.40 +    return (char*)retval;
   26.41 +}
   26.42 +
   26.43 +
   26.44  #ifdef USE_NETPGP
   26.45  // FIXME: This may cause problems - this is a quick compatibility fix for netpgp code
   26.46  int regnexec(const regex_t* preg, const char* string,
   26.47 @@ -449,4 +486,3 @@
   26.48      return NULL;
   26.49  }
   26.50  #endif
   26.51 -
    27.1 --- a/src/platform_unix.h	Thu May 16 17:55:58 2019 +0200
    27.2 +++ b/src/platform_unix.h	Wed Aug 07 14:17:27 2019 +0200
    27.3 @@ -67,6 +67,7 @@
    27.4  #if !defined(BSD) && !defined(__APPLE__)
    27.5  size_t strlcpy(char* dst, const	char* src, size_t size);
    27.6  size_t strlcat(char* dst, const	char* src, size_t size);
    27.7 +char *strnstr(const char *big, const char *little, size_t len);
    27.8  
    27.9  // N.B. This is ifdef'd out because NDK users sometimes have trouble finding regex functions in
   27.10  //      the library in spite of the inclusion of regex.h - this is a FIXME, but since iOS is
    28.1 --- a/src/platform_windows.cpp	Thu May 16 17:55:58 2019 +0200
    28.2 +++ b/src/platform_windows.cpp	Wed Aug 07 14:17:27 2019 +0200
    28.3 @@ -283,6 +283,41 @@
    28.4      dst[start_len + size_to_copy] = '\0';
    28.5      return retval;
    28.6  }
    28.7 +char *strnstr(const char *big, const char *little, size_t len) {
    28.8 +    if (big == NULL || little == NULL)
    28.9 +        return NULL;
   28.10 +        
   28.11 +    if (*little == '\0')
   28.12 +        return (char*)big;
   28.13 +        
   28.14 +    const char* curr_big = big;
   28.15 +    
   28.16 +    size_t little_len = strlen(little);
   28.17 +    size_t remaining = len;
   28.18 +
   28.19 +    const char* retval = NULL;
   28.20 +    
   28.21 +    for (remaining = len; remaining >= little_len && *curr_big != '\0'; remaining--, curr_big++) {
   28.22 +        // find first-char match
   28.23 +        if (*curr_big != *little) {
   28.24 +            continue;
   28.25 +        }
   28.26 +        retval = curr_big;
   28.27 +
   28.28 +        const char* inner_big = retval + 1;
   28.29 +        const char* curr_little = little + 1;
   28.30 +        int j;
   28.31 +        for (j = 1; j < little_len; j++, inner_big++, curr_little++) {
   28.32 +            if (*inner_big != *curr_little) {
   28.33 +                retval = NULL;
   28.34 +                break;
   28.35 +            }    
   28.36 +        }
   28.37 +        if (retval)
   28.38 +            break;
   28.39 +    }
   28.40 +    return (char*)retval;
   28.41 +}
   28.42  
   28.43  int mkstemp(char *templ)
   28.44  {
    29.1 --- a/src/platform_windows.h	Thu May 16 17:55:58 2019 +0200
    29.2 +++ b/src/platform_windows.h	Wed Aug 07 14:17:27 2019 +0200
    29.3 @@ -74,6 +74,8 @@
    29.4  
    29.5  size_t strlcpy(char* dst, const	char* src, size_t size);
    29.6  size_t strlcat(char* dst, const	char* src, size_t size);
    29.7 +char *strnstr(const char *big, const char *little, size_t len);
    29.8 +
    29.9  
   29.10  const char *windoze_local_db(void);
   29.11  const char *windoze_system_db(void);
    30.1 --- a/src/status_to_string.h	Thu May 16 17:55:58 2019 +0200
    30.2 +++ b/src/status_to_string.h	Wed Aug 07 14:17:27 2019 +0200
    30.3 @@ -4,6 +4,10 @@
    30.4  extern "C" {
    30.5  #endif
    30.6  
    30.7 +#ifndef PEP_STATUS_TO_STRING
    30.8 +#define PEP_STATUS_TO_STRING
    30.9 +#endif
   30.10 +
   30.11  static inline const char *pEp_status_to_string(PEP_STATUS status) {
   30.12      switch (status) {
   30.13      case PEP_STATUS_OK: return "PEP_STATUS_OK";
   30.14 @@ -31,6 +35,7 @@
   30.15      case PEP_KEY_IMPORTED: return "PEP_KEY_IMPORTED";
   30.16      case PEP_NO_KEY_IMPORTED: return "PEP_NO_KEY_IMPORTED";
   30.17      case PEP_KEY_IMPORT_STATUS_UNKNOWN: return "PEP_KEY_IMPORT_STATUS_UNKNOWN";
   30.18 +    case PEP_SOME_KEYS_IMPORTED: return "PEP_SOME_KEYS_IMPORTED";
   30.19      
   30.20      case PEP_CANNOT_FIND_IDENTITY: return "PEP_CANNOT_FIND_IDENTITY";
   30.21      case PEP_CANNOT_SET_PERSON: return "PEP_CANNOT_SET_PERSON";
   30.22 @@ -74,6 +79,7 @@
   30.23      case PEP_SYNC_NO_CHANNEL: return "PEP_SYNC_NO_CHANNEL";
   30.24      case PEP_SYNC_CANNOT_ENCRYPT: return "PEP_SYNC_CANNOT_ENCRYPT";
   30.25      case PEP_SYNC_NO_MESSAGE_SEND_CALLBACK: return "PEP_SYNC_NO_MESSAGE_SEND_CALLBACK";
   30.26 +    case PEP_SYNC_CANNOT_START: return "PEP_SYNC_CANNOT_START";
   30.27  
   30.28      case PEP_CANNOT_INCREASE_SEQUENCE: return "PEP_CANNOT_INCREASE_SEQUENCE";
   30.29  
   30.30 @@ -103,6 +109,46 @@
   30.31      }
   30.32  }
   30.33  
   30.34 +static inline const char *pEp_comm_type_to_string(PEP_comm_type ct) {
   30.35 +    switch (ct) {
   30.36 +    case PEP_ct_unknown: return "unknown";
   30.37 +    case PEP_ct_no_encryption: return "no_encryption";
   30.38 +    case PEP_ct_no_encrypted_channel: return "no_encrypted_channel";
   30.39 +    case PEP_ct_key_not_found: return "key_not_found";
   30.40 +    case PEP_ct_key_expired: return "key_expired";
   30.41 +    case PEP_ct_key_revoked: return "key_revoked";
   30.42 +    case PEP_ct_key_b0rken: return "key_b0rken";
   30.43 +    case PEP_ct_my_key_not_included: return "my_key_not_included";
   30.44 +    case PEP_ct_security_by_obscurity: return "security_by_obscurity";
   30.45 +    case PEP_ct_b0rken_crypto: return "b0rken_crypto";
   30.46 +    case PEP_ct_key_too_short: return "key_too_short";
   30.47 +    case PEP_ct_compromised: return "compromised";
   30.48 +    case PEP_ct_mistrusted: return "mistrusted";
   30.49 +    case PEP_ct_unconfirmed_encryption: return "unconfirmed_encryption";
   30.50 +    case PEP_ct_OpenPGP_weak_unconfirmed: return "OpenPGP_weak_unconfirmed";
   30.51 +    case PEP_ct_to_be_checked: return "to_be_checked";
   30.52 +    case PEP_ct_SMIME_unconfirmed: return "SMIME_unconfirmed";
   30.53 +    case PEP_ct_CMS_unconfirmed: return "CMS_unconfirmed";
   30.54 +    case PEP_ct_strong_but_unconfirmed: return "strong_but_unconfirmed";
   30.55 +    case PEP_ct_OpenPGP_unconfirmed: return "OpenPGP_unconfirmed";
   30.56 +    case PEP_ct_OTR_unconfirmed: return "OTR_unconfirmed";
   30.57 +    case PEP_ct_unconfirmed_enc_anon: return "unconfirmed_enc_anon";
   30.58 +    case PEP_ct_pEp_unconfirmed: return "pEp_unconfirmed";
   30.59 +    case PEP_ct_confirmed: return "confirmed";
   30.60 +    case PEP_ct_confirmed_encryption: return "confirmed_encryption";
   30.61 +    case PEP_ct_OpenPGP_weak: return "OpenPGP_weak";
   30.62 +    case PEP_ct_to_be_checked_confirmed: return "to_be_checked_confirmed";
   30.63 +    case PEP_ct_SMIME: return "SMIME";
   30.64 +    case PEP_ct_CMS: return "CMS";
   30.65 +    case PEP_ct_strong_encryption: return "strong_encryption";
   30.66 +    case PEP_ct_OpenPGP: return "OpenPGP";
   30.67 +    case PEP_ct_OTR: return "OTR";
   30.68 +    case PEP_ct_confirmed_enc_anon: return "confirmed_enc_anon";
   30.69 +    case PEP_ct_pEp: return "pEp";
   30.70 +    default: return "invalid comm type";
   30.71 +    }
   30.72 +}
   30.73 +
   30.74  #ifdef __cplusplus
   30.75  } // "C"
   30.76  #endif
    31.1 --- a/src/stringpair.c	Thu May 16 17:55:58 2019 +0200
    31.2 +++ b/src/stringpair.c	Wed Aug 07 14:17:27 2019 +0200
    31.3 @@ -194,6 +194,41 @@
    31.4      }
    31.5  }
    31.6  
    31.7 +// ONLY DELETES ONE.
    31.8 +DYNAMIC_API stringpair_list_t *stringpair_list_delete_by_key(
    31.9 +        stringpair_list_t *sp_list,
   31.10 +        const char *key
   31.11 +    )
   31.12 +{
   31.13 +    assert(sp_list);
   31.14 +    assert(key);
   31.15 +
   31.16 +    if (sp_list->value == NULL) {
   31.17 +        free_stringpair_list(sp_list);
   31.18 +        return NULL;
   31.19 +    }
   31.20 +
   31.21 +    if (key == NULL)
   31.22 +        return sp_list;
   31.23 +
   31.24 +    stringpair_list_t *_sl;
   31.25 +    stringpair_list_t *last = NULL;
   31.26 +    for (_sl = sp_list; _sl && _sl->value && _sl->value->key; _sl = _sl->next) {
   31.27 +        if (strcmp(_sl->value->key, key) == 0) {
   31.28 +            if (last == NULL)
   31.29 +                sp_list = sp_list->next;
   31.30 +            else
   31.31 +                last->next = _sl->next;
   31.32 +            _sl->next = NULL;
   31.33 +            free_stringpair_list(_sl);
   31.34 +            break;
   31.35 +        }
   31.36 +        last = _sl;
   31.37 +    }
   31.38 +    return sp_list;
   31.39 +}
   31.40 +
   31.41 +
   31.42  DYNAMIC_API stringpair_list_t *stringpair_list_find(
   31.43          stringpair_list_t *stringpair_list,
   31.44          const char *key
    32.1 --- a/src/stringpair.h	Thu May 16 17:55:58 2019 +0200
    32.2 +++ b/src/stringpair.h	Wed Aug 07 14:17:27 2019 +0200
    32.3 @@ -159,8 +159,13 @@
    32.4          const char *key
    32.5      );
    32.6  
    32.7 +// ONLY DELETES ONE.
    32.8 +DYNAMIC_API stringpair_list_t *stringpair_list_delete_by_key(
    32.9 +        stringpair_list_t *sp_list,
   32.10 +        const char *key
   32.11 +    );
   32.12 +
   32.13  
   32.14  #ifdef __cplusplus
   32.15  }
   32.16  #endif
   32.17 -
    33.1 --- a/src/sync_api.c	Thu May 16 17:55:58 2019 +0200
    33.2 +++ b/src/sync_api.c	Wed Aug 07 14:17:27 2019 +0200
    33.3 @@ -19,6 +19,15 @@
    33.4      if (!(session && notifyHandshake && retrieve_next_sync_event))
    33.5          return PEP_ILLEGAL_VALUE;
    33.6  
    33.7 +    identity_list *own_identities = NULL;
    33.8 +    PEP_STATUS status = own_identities_retrieve(session, &own_identities);
    33.9 +    if (status)
   33.10 +        return status;
   33.11 +    bool own_identities_available = own_identities && own_identities->ident;
   33.12 +    free_identity_list(own_identities);
   33.13 +    if (!own_identities_available)
   33.14 +        return PEP_SYNC_CANNOT_START;
   33.15 +
   33.16      session->sync_management = management;
   33.17      session->notifyHandshake = notifyHandshake;
   33.18      session->retrieve_next_sync_event = retrieve_next_sync_event;
    34.1 --- a/src/timestamp.c	Thu May 16 17:55:58 2019 +0200
    34.2 +++ b/src/timestamp.c	Wed Aug 07 14:17:27 2019 +0200
    34.3 @@ -30,7 +30,6 @@
    34.4  
    34.5  DYNAMIC_API timestamp * timestamp_dup(const timestamp *src)
    34.6  {
    34.7 -    assert(src);
    34.8      if (!src)
    34.9          return NULL;
   34.10  
   34.11 @@ -42,4 +41,3 @@
   34.12      memcpy(dst, src, sizeof(timestamp));
   34.13      return dst;
   34.14  }
   34.15 -
    35.1 --- a/sync/cond_act_sync.yml2	Thu May 16 17:55:58 2019 +0200
    35.2 +++ b/sync/cond_act_sync.yml2	Wed Aug 07 14:17:27 2019 +0200
    35.3 @@ -18,10 +18,10 @@
    35.4      |> *result = _result > 0;
    35.5  }
    35.6  
    35.7 -condition weAreFirst
    35.8 +condition weAreOfferer
    35.9  ||
   35.10      TID_t *t1 = &session->sync_state.keysync.challenge;
   35.11 -    TID_t *t2 = &session->own_sync_state.challenge;
   35.12 +    TID_t *t2 = &session->sync_state.own.challenge;
   35.13  
   35.14      *result = _TID_greater(t1, t2);
   35.15  ||
   35.16 @@ -29,38 +29,30 @@
   35.17  condition partnerIsGrouped
   35.18  |> *result = session->sync_state.keysync.is_group;
   35.19  
   35.20 -condition challengeAccepted
   35.21 +condition sameChallenge
   35.22  ||
   35.23      TID_t *t1 = &session->sync_state.keysync.challenge;
   35.24 -    TID_t *t2 = &session->own_sync_state.challenge;
   35.25 +    TID_t *t2 = &session->sync_state.own.challenge;
   35.26  
   35.27      *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
   35.28  ||
   35.29  
   35.30 -condition sameChallenge
   35.31 -||
   35.32 -    TID_t *t1 = &session->sync_state.keysync.challenge;
   35.33 -    TID_t *t2 = &session->own_sync_state.challenge;
   35.34 -
   35.35 -    *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
   35.36 -||
   35.37 -
   35.38 -condition sameTransaction
   35.39 +condition sameNegotiation
   35.40  ||
   35.41      TID_t *t1 = &session->sync_state.keysync.negotiation;
   35.42 -    TID_t *t2 = &session->own_sync_state.negotiation;
   35.43 +    TID_t *t2 = &session->sync_state.comm_partner.negotiation;
   35.44  
   35.45      // test if TID is identical
   35.46      *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
   35.47  ||
   35.48  
   35.49 -condition sameTransactionAndPartner
   35.50 +condition sameNegotiationAndPartner
   35.51  ||
   35.52      TID_t *t1 = &session->sync_state.keysync.negotiation;
   35.53 -    TID_t *t2 = &session->own_sync_state.negotiation;
   35.54 +    TID_t *t2 = &session->sync_state.comm_partner.negotiation;
   35.55  
   35.56 -    const char *s1 = session->sync_state.common.signature_fpr;
   35.57 -    const char *s2 = session->own_sync_state.signature_fpr;
   35.58 +    const char *s1 = session->sync_state.comm_partner.sender_fpr;
   35.59 +    const char *s2 = session->sync_state.transport.sender_fpr;
   35.60  
   35.61      // test if TID is identical
   35.62      *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0
   35.63 @@ -70,8 +62,8 @@
   35.64  
   35.65  condition keyElectionWon
   35.66  ||
   35.67 -    pEp_identity *from = session->sync_state.common.from;
   35.68 -    char *signature_fpr = session->sync_state.common.signature_fpr;
   35.69 +    pEp_identity *from = session->sync_state.transport.from;
   35.70 +    char *sender_fpr = session->sync_state.comm_partner.sender_fpr;
   35.71  
   35.72      assert(from && from->address && from->address[0] && from->user_id &&
   35.73              from->user_id[0]);
   35.74 @@ -91,8 +83,8 @@
   35.75          return PEP_ILLEGAL_VALUE;
   35.76      }
   35.77  
   35.78 -    size_t len = MIN(strlen(signature_fpr), strlen(me->fpr));
   35.79 -    *result = strncasecmp(signature_fpr, me->fpr, len) > 0;
   35.80 +    size_t len = MIN(strlen(sender_fpr), strlen(me->fpr));
   35.81 +    *result = strncasecmp(sender_fpr, me->fpr, len) > 0;
   35.82      free_identity(me);
   35.83  ||
   35.84  
   35.85 @@ -101,10 +93,12 @@
   35.86  function "new_UUID" {
   35.87      param "dst";
   35.88      ||
   35.89 -        pEpUUID c;
   35.90 -        uuid_generate_random(c);
   35.91 +        {
   35.92 +            pEpUUID c;
   35.93 +            uuid_generate_random(c);
   35.94  
   35.95 -        OCTET_STRING_fromBuf(«$dst», (char *) c, 16);
   35.96 +            OCTET_STRING_fromBuf(«$dst», (char *) c, 16);
   35.97 +        }
   35.98      ||
   35.99  }
  35.100  
  35.101 @@ -141,75 +135,98 @@
  35.102      ||
  35.103  }
  35.104  
  35.105 -action newChallenge {
  35.106 +action newChallengeAndNegotiationBase {
  35.107      // random new challenge
  35.108 -    call "new_UUID" with "dst" > &session->own_sync_state.challenge
  35.109 -    // store a copy of this challenge
  35.110 +    call "new_UUID" with "dst" > &session->sync_state.own.challenge
  35.111      call "copy_UUID" {
  35.112 -        with "src" > &session->own_sync_state.challenge
  35.113 -        with "dst" > &session->sync_state.common.challenge
  35.114 +        with "src" > &session->sync_state.own.challenge
  35.115 +        with "dst" > &session->sync_state.keysync.challenge
  35.116 +    }
  35.117 +
  35.118 +    // this is the random data we are using as a base
  35.119 +    call "new_UUID" with "dst" > &session->sync_state.own.negotiation
  35.120 +||
  35.121 +    memset(session->sync_state.keysync.negotiation.buf, 0,
  35.122 +            session->sync_state.keysync.negotiation.size);
  35.123 +    memset(session->sync_state.comm_partner.negotiation.buf, 0,
  35.124 +            session->sync_state.comm_partner.negotiation.size);
  35.125 +||
  35.126 +}
  35.127 +
  35.128 +action useOwnChallenge call "copy_UUID" {
  35.129 +    with "src" > &session->sync_state.own.challenge
  35.130 +    with "dst" > &session->sync_state.keysync.challenge
  35.131 +}
  35.132 +
  35.133 +action openNegotiation {
  35.134 +||
  35.135 +    // sender key must be stable while transaction
  35.136 +
  35.137 +    // we take the actual signature of the last message and store it in our
  35.138 +    // state for the comm partner
  35.139 +    assert(session->sync_state.transport.sender_fpr);
  35.140 +
  35.141 +    free(session->sync_state.comm_partner.sender_fpr);
  35.142 +
  35.143 +    session->sync_state.comm_partner.sender_fpr
  35.144 +            = strdup(session->sync_state.transport.sender_fpr);
  35.145 +    assert(session->sync_state.comm_partner.sender_fpr);
  35.146 +    if (!session->sync_state.comm_partner.sender_fpr)
  35.147 +        return PEP_OUT_OF_MEMORY;
  35.148 +
  35.149 +    // we need a unique TID for the Negotiation with each single comm_partner
  35.150 +    // we identify the comm_partners by their Challenge
  35.151 +    // we derive the actual Negotiation TID by having random data and XORing it
  35.152 +    // with comm_partner's Challenge
  35.153 +
  35.154 +    // copy Negotiation base into buffer
  35.155 +
  35.156 +||
  35.157 +    call "copy_UUID" {
  35.158 +        with "src" > &session->sync_state.own.negotiation
  35.159 +        with "dst" > &session->sync_state.keysync.negotiation
  35.160 +    }
  35.161 +||
  35.162 +
  35.163 +    // we're XORing this with the challenge of the comm_partner, which is in
  35.164 +    // the buffer already
  35.165 +
  35.166 +||
  35.167 +    call "xor_UUID" {
  35.168 +        with "src" > &session->sync_state.keysync.challenge
  35.169 +        with "dst" > &session->sync_state.keysync.negotiation
  35.170 +    }
  35.171 +||
  35.172 +
  35.173 +    // this is the Negotiation's TID for this comm_partner
  35.174 +
  35.175 +||
  35.176 +    call "copy_UUID" {
  35.177 +        with "src" > &session->sync_state.keysync.negotiation
  35.178 +        with "dst" > &session->sync_state.comm_partner.negotiation
  35.179      }
  35.180  }
  35.181  
  35.182 -action replyChallenge call "copy_UUID" {
  35.183 -    with "src" > &session->sync_state.keysync.challenge
  35.184 -    with "dst" > &session->own_sync_state.challenge
  35.185 -}
  35.186 -
  35.187 -action useOwnChallenge call "copy_UUID" {
  35.188 -    with "src" > &session->sync_state.common.challenge
  35.189 -    with "dst" > &session->own_sync_state.challenge
  35.190 -}
  35.191 -
  35.192 -action newTransaction {
  35.193 +action storeNegotiation {
  35.194  ||
  35.195      // sender key must be stable while transaction
  35.196 -    assert(session->sync_state.common.signature_fpr);
  35.197 -    free(session->own_sync_state.signature_fpr);
  35.198 -    session->own_sync_state.signature_fpr
  35.199 -            = strdup(session->sync_state.common.signature_fpr);
  35.200 -    assert(session->own_sync_state.signature_fpr);
  35.201 -    if (!session->own_sync_state.signature_fpr)
  35.202 -        return PEP_OUT_OF_MEMORY;
  35.203  
  35.204 -||
  35.205 -    call "copy_UUID" {
  35.206 -        with "src" > &session->sync_state.keysync.challenge
  35.207 -        with "dst" > &session->sync_state.keysync.negotiation
  35.208 -    }
  35.209 -    call "xor_UUID" {
  35.210 -        with "src" > &session->own_sync_state.challenge
  35.211 -        with "dst" > &session->sync_state.keysync.negotiation
  35.212 -    }
  35.213 -    call "copy_UUID" {
  35.214 -        with "src" > &session->sync_state.keysync.negotiation
  35.215 -        with "dst" > &session->own_sync_state.negotiation
  35.216 -    }
  35.217 -}
  35.218 +    // we take the actual signature of the last message and store it in our
  35.219 +    // state for the comm partner
  35.220 +    assert(session->sync_state.transport.sender_fpr);
  35.221  
  35.222 -action closeTransaction
  35.223 -||
  35.224 -    memset(session->sync_state.keysync.negotiation.buf, 0,
  35.225 -            session->sync_state.keysync.negotiation.size);
  35.226 -    memset(session->own_sync_state.negotiation.buf, 0,
  35.227 -            session->own_sync_state.negotiation.size);
  35.228 -||
  35.229 +    free(session->sync_state.comm_partner.sender_fpr);
  35.230  
  35.231 -action storeTransaction {
  35.232 -||
  35.233 -    // sender key must be stable while transaction
  35.234 -    assert(session->sync_state.common.signature_fpr);
  35.235 -    free(session->own_sync_state.signature_fpr);
  35.236 -    session->own_sync_state.signature_fpr
  35.237 -            = strdup(session->sync_state.common.signature_fpr);
  35.238 -    assert(session->own_sync_state.signature_fpr);
  35.239 -    if (!session->own_sync_state.signature_fpr)
  35.240 +    session->sync_state.comm_partner.sender_fpr
  35.241 +            = strdup(session->sync_state.transport.sender_fpr);
  35.242 +    assert(session->sync_state.comm_partner.sender_fpr);
  35.243 +    if (!session->sync_state.comm_partner.sender_fpr)
  35.244          return PEP_OUT_OF_MEMORY;
  35.245  
  35.246  ||
  35.247      call "copy_UUID" {
  35.248          with "src" > &session->sync_state.keysync.negotiation
  35.249 -        with "dst" > &session->own_sync_state.negotiation
  35.250 +        with "dst" > &session->sync_state.comm_partner.negotiation
  35.251      }
  35.252  }
  35.253  
  35.254 @@ -222,34 +239,20 @@
  35.255       
  35.256      ||
  35.257      choose {
  35.258 -    when "$type = 'SYNC_NOTIFY_TIMEOUT' or $type = 'SYNC_NOTIFY_SOLE' or $type = 'SYNC_NOTIFY_IN_GROUP'"
  35.259 +    when "$type = 'SYNC_NOTIFY_INIT_ADD_OUR_DEVICE' or $type = 'SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE' or $type = 'SYNC_NOTIFY_INIT_FORM_GROUP'"
  35.260      ||
  35.261 -        pEp_identity *me = new_identity(NULL, NULL, NULL, NULL);
  35.262 -        pEp_identity *partner = new_identity(NULL, NULL, NULL, NULL);
  35.263 -        assert(me && partner);
  35.264 -        if (!(me && partner)) {
  35.265 -            free_identity(me);
  35.266 -            free_identity(partner);
  35.267 -            return PEP_OUT_OF_MEMORY;
  35.268 -        }
  35.269 -
  35.270 -        PEP_STATUS status = session->notifyHandshake(me, partner, «$type»);
  35.271 -        if (status)
  35.272 -            return status;
  35.273 -    ||
  35.274 -    otherwise
  35.275 -    ||
  35.276 -        assert(session->sync_state.common.from);
  35.277 -        if (!session->sync_state.common.from)
  35.278 +        assert(session->sync_state.transport.from);
  35.279 +        if (!session->sync_state.transport.from)
  35.280              return PEP_ILLEGAL_VALUE;
  35.281  
  35.282 -        pEp_identity *from = session->sync_state.common.from;
  35.283 +        pEp_identity *from = session->sync_state.transport.from;
  35.284          pEp_identity *me = NULL;
  35.285          PEP_STATUS status = get_identity(session, from->address, from->user_id, &me);
  35.286          assert(status == PEP_STATUS_OK);
  35.287          if (status)
  35.288              return status;
  35.289 -
  35.290 +        assert(strcmp(me->fpr, session->sync_state.comm_partner.sender_fpr) != 0);
  35.291 +        
  35.292          assert(me->fpr && me->fpr[0]);
  35.293          if (!(me->fpr && me->fpr[0])) {
  35.294              free_identity(me);
  35.295 @@ -262,10 +265,11 @@
  35.296              return PEP_OUT_OF_MEMORY;
  35.297          }
  35.298  
  35.299 -        assert(session->sync_state.common.signature_fpr);
  35.300 -        if (session->sync_state.common.signature_fpr) {
  35.301 +        assert(session->sync_state.comm_partner.sender_fpr);
  35.302 +        if (session->sync_state.comm_partner.sender_fpr) {
  35.303              free(partner->fpr);
  35.304 -            partner->fpr = strdup(session->sync_state.common.signature_fpr);
  35.305 +            partner->fpr = strdup(session->sync_state.comm_partner.sender_fpr);
  35.306 +            assert(partner->fpr);
  35.307              if (!partner->fpr) {
  35.308                  free_identity(me);
  35.309                  free_identity(partner);
  35.310 @@ -273,10 +277,35 @@
  35.311              }
  35.312          }
  35.313  
  35.314 +        free(partner->user_id);
  35.315 +        partner->user_id = strdup("#NV");
  35.316 +        assert(partner->user_id);
  35.317 +        if (!partner->user_id) {
  35.318 +            free_identity(me);
  35.319 +            free_identity(partner);
  35.320 +            return PEP_OUT_OF_MEMORY;
  35.321 +        }
  35.322 +
  35.323 +        assert(strcmp(me->fpr, partner->fpr) != 0);
  35.324          status = session->notifyHandshake(me, partner, «$type»);
  35.325          if (status)
  35.326              return status;
  35.327      ||
  35.328 +    otherwise
  35.329 +    ||
  35.330 +        pEp_identity *me = new_identity(NULL, NULL, NULL, NULL);
  35.331 +        pEp_identity *partner = new_identity(NULL, NULL, NULL, NULL);
  35.332 +        assert(me && partner);
  35.333 +        if (!(me && partner)) {
  35.334 +            free_identity(me);
  35.335 +            free_identity(partner);
  35.336 +            return PEP_OUT_OF_MEMORY;
  35.337 +        }
  35.338 +
  35.339 +        PEP_STATUS status = session->notifyHandshake(me, partner, «$type»);
  35.340 +        if (status)
  35.341 +            return status;
  35.342 +    ||
  35.343      }
  35.344  }
  35.345  
  35.346 @@ -314,9 +343,9 @@
  35.347      if (status)
  35.348          return status;
  35.349  
  35.350 -    if (session->own_sync_state.own_keys)
  35.351 -        free_stringlist(session->own_sync_state.own_keys);
  35.352 -    session->own_sync_state.own_keys = own_keys;
  35.353 +    if (session->sync_state.own.keys)
  35.354 +        free_stringlist(session->sync_state.own.keys);
  35.355 +    session->sync_state.own.keys = own_keys;
  35.356  
  35.357      identity_list *il;
  35.358      status = _own_identities_retrieve(session, &il, PEP_idf_not_for_sync);
  35.359 @@ -329,28 +358,70 @@
  35.360  
  35.361  action saveGroupKeys
  35.362  ||
  35.363 +    char *user_id = NULL;
  35.364 +    PEP_STATUS status = get_default_own_userid(session, &user_id);
  35.365 +    if (status)
  35.366 +        return status;
  35.367 +
  35.368      identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
  35.369 -    if (!il)
  35.370 +    if (!il) {
  35.371 +        free(user_id);
  35.372          return PEP_OUT_OF_MEMORY;
  35.373 +    }
  35.374      
  35.375 +    identity_list *oil = session->sync_state.own.identities;
  35.376 +
  35.377      // BUG: this should be a transaction and been rolled back completely on error
  35.378      for (identity_list *_il = il; _il && _il->ident; _il = _il->next) {
  35.379 -        PEP_STATUS status = set_identity(session, _il->ident);
  35.380 +        pEp_identity *ident = _il->ident;
  35.381 +        bool is_own_already = false;
  35.382 +
  35.383 +        status = is_own_address(session, ident->address, &is_own_already);
  35.384          if (status) {
  35.385              free_identity_list(il);
  35.386 +            free(user_id);
  35.387 +            return status;
  35.388 +        }
  35.389 +
  35.390 +        free(ident->user_id);
  35.391 +        ident->user_id = strdup(user_id);
  35.392 +        assert(ident->user_id);
  35.393 +        if (!ident->user_id) {
  35.394 +            free_identity_list(il);
  35.395 +            free(user_id);
  35.396 +            return PEP_OUT_OF_MEMORY;
  35.397 +        }
  35.398 +
  35.399 +        if (is_own_already) {
  35.400 +            ident->comm_type = PEP_ct_pEp;
  35.401 +            status = set_trust(session, ident);
  35.402 +        }
  35.403 +        else {
  35.404 +            oil = identity_list_add(oil, ident);
  35.405 +            if (!oil) {
  35.406 +                free_identity_list(il);
  35.407 +                free(user_id);
  35.408 +                return PEP_OUT_OF_MEMORY;
  35.409 +            }
  35.410 +            status = myself(session, ident);
  35.411 +        }
  35.412 +        if (status) {
  35.413 +            free_identity_list(il);
  35.414 +            free(user_id);
  35.415              return status;
  35.416          }
  35.417      }
  35.418  
  35.419 +    free(user_id);
  35.420      free_identity_list(il);
  35.421  ||
  35.422  
  35.423 -action ownKeysAreGroupKeys
  35.424 +action ownKeysAreDefaultKeys
  35.425  ||
  35.426      PEP_STATUS status = PEP_STATUS_OK;
  35.427  
  35.428 -    // set flag for current keys
  35.429 -    for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
  35.430 +    // set flag for all keys; don't change anything else
  35.431 +    for (identity_list *il = session->sync_state.own.identities; il && il->ident ; il = il->next) {
  35.432          if (!(il->ident->flags && PEP_idf_not_for_sync)) {
  35.433              status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
  35.434              if (status)
  35.435 @@ -359,77 +430,89 @@
  35.436      }
  35.437  ||
  35.438  
  35.439 -action receivedKeysAreGroupKeys
  35.440 +action receivedKeysAreDefaultKeys
  35.441  ||
  35.442      PEP_STATUS status = PEP_STATUS_OK;
  35.443 -
  35.444 -    // set flag for current keys
  35.445 -    for (identity_list *il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
  35.446 +    // set flag for all keys
  35.447 +    for (identity_list *il = session->sync_state.own.identities; il && il->ident ; il = il->next) {
  35.448          if (!(il->ident->flags && PEP_idf_not_for_sync)) {
  35.449 +            
  35.450              status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
  35.451              if (status)
  35.452                  return status;
  35.453          }
  35.454      }
  35.455  
  35.456 +    char *user_id = NULL;
  35.457 +    status = get_default_own_userid(session, &user_id);
  35.458 +    if (status)
  35.459 +        return status;
  35.460 +
  35.461      identity_list *il = IdentityList_to_identity_list(&session->sync_state.keysync.ownIdentities, NULL);
  35.462      if (!il)
  35.463          return PEP_OUT_OF_MEMORY;
  35.464  
  35.465 -    for (il = session->own_sync_state.own_identities; il && il->ident ; il = il->next) {
  35.466 +    for (identity_list *_il = il; _il && _il->ident ; _il = _il->next) {
  35.467          // replace partner's user_id with own user_id
  35.468 -        free(il->ident->user_id);
  35.469 -        il->ident->user_id = strdup(session->sync_state.common.from->user_id);
  35.470 -        if (!il->ident->user_id) {
  35.471 +        free(_il->ident->user_id);
  35.472 +        _il->ident->user_id = strdup(user_id);
  35.473 +        assert(_il->ident->user_id);
  35.474 +        if (!_il->ident->user_id) {
  35.475              free_identity_list(il);
  35.476 +            free(user_id);
  35.477              return PEP_OUT_OF_MEMORY;
  35.478          }
  35.479 -
  35.480 -        status = myself(session, il->ident);
  35.481 +    
  35.482 +        const char *own_key = _il->ident->fpr;
  35.483 +        _il->ident->fpr = NULL;
  35.484 +        status = set_own_key(session, _il->ident, own_key);
  35.485          if (status) {
  35.486              free_identity_list(il);
  35.487 -            return status;
  35.488 -        }
  35.489 -
  35.490 -        status = set_identity_flags(session, il->ident, PEP_idf_devicegroup);
  35.491 -        if (status) {
  35.492 -            free_identity_list(il);
  35.493 +            free(user_id);
  35.494              return status;
  35.495          }
  35.496      }
  35.497  
  35.498      free_identity_list(il);
  35.499 +    free(user_id);
  35.500  ||
  35.501  
  35.502  action trustThisKey
  35.503  ||
  35.504 -    assert(session->sync_state.common.from && session->sync_state.common.signature_fpr);
  35.505 -    if (!(session->sync_state.common.from && session->sync_state.common.signature_fpr))
  35.506 +    assert(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr);
  35.507 +    if (!(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr))
  35.508          return PEP_ILLEGAL_VALUE;
  35.509  
  35.510 -    pEp_identity *ident = session->sync_state.common.from;
  35.511 +    pEp_identity *ident = identity_dup(session->sync_state.transport.from);
  35.512 +    if (!ident)
  35.513 +        return PEP_OUT_OF_MEMORY;
  35.514      free(ident->fpr);
  35.515 -    ident->fpr = strdup(session->sync_state.common.signature_fpr);
  35.516 +    ident->fpr = strdup(session->sync_state.comm_partner.sender_fpr);
  35.517      assert(ident->fpr);
  35.518 -    if (!ident->fpr)
  35.519 +    if (!ident->fpr) {
  35.520 +        free_identity(ident);
  35.521          return PEP_OUT_OF_MEMORY;
  35.522 +    }
  35.523  
  35.524      PEP_STATUS status = trust_own_key(session, ident);
  35.525 -    if (status)
  35.526 +    if (status) {
  35.527 +        free_identity(ident);
  35.528          return status;
  35.529 +    }
  35.530  
  35.531      OCTET_STRING_fromBuf(&session->sync_state.keysync.key, ident->fpr, strlen(ident->fpr));
  35.532 +    free_identity(ident);
  35.533  ||
  35.534  
  35.535  action untrustThisKey
  35.536  ||
  35.537 -    assert(session->sync_state.common.from && session->sync_state.common.signature_fpr);
  35.538 -    if (!(session->sync_state.common.from && session->sync_state.common.signature_fpr))
  35.539 +    assert(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr);
  35.540 +    if (!(session->sync_state.transport.from && session->sync_state.comm_partner.sender_fpr))
  35.541          return PEP_ILLEGAL_VALUE;
  35.542  
  35.543 -    pEp_identity *ident = session->sync_state.common.from;
  35.544 +    pEp_identity *ident = session->sync_state.transport.from;
  35.545      free(ident->fpr);
  35.546 -    ident->fpr = strdup(session->sync_state.common.signature_fpr);
  35.547 +    ident->fpr = strdup(session->sync_state.comm_partner.sender_fpr);
  35.548      assert(ident->fpr);
  35.549      if (!ident->fpr)
  35.550          return PEP_OUT_OF_MEMORY;
  35.551 @@ -452,4 +535,3 @@
  35.552  ||
  35.553  
  35.554  action disable;
  35.555 -
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/sync/gen_doc.yml2	Wed Aug 07 14:17:27 2019 +0200
    36.3 @@ -0,0 +1,44 @@
    36.4 +include yslt.yml2
    36.5 +
    36.6 +tstylesheet {
    36.7 +    template "/protocol" {
    36.8 +        | protocol «@name»
    36.9 +        apply "fsm" sort "@name";
   36.10 +    }
   36.11 +    template "fsm" {
   36.12 +        | fsm «@name»
   36.13 +        apply "state" sort "@name";
   36.14 +        |
   36.15 +        for "set:distinct(*/event/@name)" {
   36.16 +            sort ".";
   36.17 +            |> event «.»
   36.18 +        }
   36.19 +        |
   36.20 +        for "set:distinct(descendant::action/@name)" {
   36.21 +            sort ".";
   36.22 +            |> action «.»
   36.23 +        }
   36.24 +        |
   36.25 +        for "set:distinct(descendant::condition/@name)" {
   36.26 +            sort ".";
   36.27 +            |> condition «.»
   36.28 +        }
   36.29 +        |
   36.30 +        apply "descendant::transition"
   36.31 +            sort "ancestor::state/@name",
   36.32 +            sort "@target",
   36.33 +            sort "ancestor::event/@name";
   36.34 +        |
   36.35 +        apply "message" sort "@name";
   36.36 +        |
   36.37 +        for "set:distinct(message/field/@name)" {
   36.38 +            sort ".";
   36.39 +            |> field «.»
   36.40 +        }
   36.41 +    }
   36.42 +    template "state" | state «@name»
   36.43 +    template "transition"
   36.44 +        | transition from «ancestor::state/@name» to «@target» on event «ancestor::event/@name»
   36.45 +    template "message" | message «@name»
   36.46 +}
   36.47 +
    37.1 --- a/sync/gen_dot.ysl2	Thu May 16 17:55:58 2019 +0200
    37.2 +++ b/sync/gen_dot.ysl2	Wed Aug 07 14:17:27 2019 +0200
    37.3 @@ -8,34 +8,24 @@
    37.4      ||
    37.5      digraph finite_state_machine {
    37.6          rankdir=LR;
    37.7 -        node [shape = doublecircle];
    37.8 -        `apply "state[@end='1']" mode=end`;
    37.9 -        node [shape = circle];
   37.10 +        node [shape=point];
   37.11 +        InitState;
   37.12 +        node [shape=doublecircle];
   37.13 +        End;
   37.14 +        node [shape=circle, style=filled, fillcolor=lightgrey];
   37.15  
   37.16 -        `` apply "state" mode=do
   37.17 +        `` apply "descendant::transition";
   37.18      }
   37.19      ||
   37.20  
   37.21 -    template "state", mode=end > «@name» 
   37.22 -    template "state", mode=do apply "event", 0 with "state", "@name";
   37.23 -
   37.24 -    template "event" {
   37.25 -        param "state";
   37.26 +    template "transition" {
   37.27 +        const "event", "ancestor::event/@name";
   37.28          choose {
   37.29 -            when "count(transition) > 0"
   37.30 -                apply "transition|condition/transition", 0
   37.31 -                    with "state", "$state", with "event", "@name";
   37.32 +            when "ancestor::fsm/message[@name=$event]"
   37.33 +                | «ancestor::state/@name» -> «@target» [ label="«ancestor::event/@name»", color=blue ];
   37.34              otherwise
   37.35 -                if "@name != 'Init'"
   37.36 -                    | «$state» -> «$state» [ label="«@name»" ];
   37.37 +                | «ancestor::state/@name» -> «@target» [ label="«ancestor::event/@name»", color=red ];
   37.38          }
   37.39      }
   37.40 -
   37.41 -    template "transition" {
   37.42 -        param "state";
   37.43 -        param "event";
   37.44 -
   37.45 -        | «$state» -> «@target» [ label ="«$event»" ];
   37.46 -    }
   37.47  }
   37.48  
    38.1 --- a/sync/gen_message_func.ysl2	Thu May 16 17:55:58 2019 +0200
    38.2 +++ b/sync/gen_message_func.ysl2	Wed Aug 07 14:17:27 2019 +0200
    38.3 @@ -39,32 +39,36 @@
    38.4  // state
    38.5  
    38.6  struct «@name»_state_s {
    38.7 -    // common buffer for all types of «@name» messages
    38.8 +    // own state
    38.9  
   38.10 -    struct common_state_s {
   38.11 -        // intermediate store own challenge
   38.12 -        TID_t challenge;
   38.13 +    struct own_«@name»_state_s {
   38.14 +        stringlist_t *keys;
   38.15 +        identity_list *identities;
   38.16  
   38.17 -        // transport data
   38.18 +        // TIDs we're using ourselves
   38.19 +        `` for "func:distinctName(fsm/message/field[@type='TID'])" |>> «func:ctype()» «@name»;
   38.20 +    } own;
   38.21 +
   38.22 +    // state we learned about our communication partner
   38.23 +
   38.24 +    struct comm_partner_state_s {
   38.25 +        // transport data we expect
   38.26 +        char *sender_fpr;
   38.27 +
   38.28 +        // TIDs our comm partner wants to have
   38.29 +        `` for "func:distinctName(fsm/message/field[@type='TID'])" |>> «func:ctype()» «@name»;
   38.30 +    } comm_partner;
   38.31 +
   38.32 +    // input buffer for actual transport data coming in
   38.33 +
   38.34 +    struct transport_data_s {
   38.35 +        // transport data we got
   38.36          pEp_identity *from;
   38.37 -        char *signature_fpr;
   38.38 -    } common;
   38.39 +        char *sender_fpr;
   38.40 +    } transport;
   38.41      `` apply "fsm", mode=state
   38.42  };
   38.43  
   38.44 -// own state
   38.45 -
   38.46 -struct own_«@name»_state_s {
   38.47 -    stringlist_t *own_keys;
   38.48 -    identity_list *own_identities;
   38.49 -
   38.50 -    `` if "func:distinctName(fsm/message/field[@type='TID'])" |> // active TIDs
   38.51 -    `` for "func:distinctName(fsm/message/field[@type='TID'])" |> «func:ctype()» «@name»;
   38.52 -
   38.53 -    // transport data
   38.54 -    char *signature_fpr;
   38.55 -};
   38.56 -
   38.57  void free_«@name»_state(PEP_SESSION session);
   38.58  
   38.59  // functions for protocol «@name»
   38.60 @@ -86,7 +90,7 @@
   38.61  template "fsm", mode=state
   38.62  ||
   38.63  
   38.64 -// buffer for «@name» messages
   38.65 +// input/output buffer for «@name» messages
   38.66  
   38.67  struct _«@name»_state_s {
   38.68      int state;
   38.69 @@ -113,21 +117,46 @@
   38.70      if (!session)
   38.71          return;
   38.72  
   38.73 -    free_identity(session->«yml:lcase(@name)»_state.common.from);
   38.74 -    free(session->«yml:lcase(@name)»_state.common.signature_fpr);
   38.75 -    free_stringlist(session->own_«yml:lcase(@name)»_state.own_keys);
   38.76 -    free_identity_list(session->own_«yml:lcase(@name)»_state.own_identities);
   38.77 -    session->own_«yml:lcase(@name)»_state.own_keys = NULL;
   38.78 -    session->own_«yml:lcase(@name)»_state.own_identities = NULL;
   38.79 +    // own state
   38.80 +
   38.81 +    free_stringlist(session->«yml:lcase(@name)»_state.own.keys);
   38.82 +    session->«yml:lcase(@name)»_state.own.keys = NULL;
   38.83 +    free_identity_list(session->«yml:lcase(@name)»_state.own.identities);
   38.84 +    session->«yml:lcase(@name)»_state.own.identities = NULL;
   38.85 +
   38.86 +    // TIDs we're using ourselves
   38.87 +||
   38.88 +    for "func:distinctName(fsm/message/field[@type='TID'])"
   38.89 +        |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.own.«@name»);
   38.90 +||
   38.91 +
   38.92 +    // state we learned about our communication partner
   38.93 +
   38.94 +    free(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
   38.95 +    session->«yml:lcase(@name)»_state.comm_partner.sender_fpr = NULL;
   38.96 +
   38.97 +    // TIDs our comm partner wants to have
   38.98 +||
   38.99 +    for "func:distinctName(fsm/message/field[@type='TID'])"
  38.100 +        |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.comm_partner.«@name»);
  38.101 +||
  38.102 +
  38.103 +    // buffer for transport data
  38.104 +
  38.105 +    free_identity(session->«yml:lcase(@name)»_state.transport.from);
  38.106 +    session->«yml:lcase(@name)»_state.transport.from = NULL;
  38.107 +    free(session->«yml:lcase(@name)»_state.transport.sender_fpr);
  38.108 +    session->«yml:lcase(@name)»_state.transport.sender_fpr = NULL;
  38.109 +
  38.110 +    // message buffers
  38.111  
  38.112  ||
  38.113 -for "fsm"
  38.114 -    for "func:distinctName(message/field[not(func:basicType())])"
  38.115 -        |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
  38.116 -for "func:distinctName(fsm/message/field[@type='TID'])"
  38.117 -    |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->own_«yml:lcase(../../../@name)»_state.«@name»);
  38.118 +    for "fsm" {
  38.119 +        for "func:distinctName(message/field[not(substring(@type,1,1)=yml:lcase(substring(@type,1,1)))])"
  38.120 +            |> ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_«@type», &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
  38.121 +        |
  38.122 +    }
  38.123  ||
  38.124 -
  38.125      memset(&session->«yml:lcase(@name)»_state, 0, sizeof(session->«yml:lcase(@name)»_state));
  38.126  }
  38.127  
  38.128 @@ -259,12 +288,7 @@
  38.129  
  38.130  template "field", mode=update_message {
  38.131      const "message_name", "yml:mixedCase(../@name)";
  38.132 -    const "state" choose {
  38.133 -        when "@type='TID'"
  38.134 -            > own_«yml:lcase(ancestor::protocol/@name)»_state
  38.135 -        otherwise
  38.136 -            > «yml:lcase(ancestor::protocol/@name)»_state.«yml:lcase(ancestor::fsm/@name)»
  38.137 -    }
  38.138 +    const "state" > «yml:lcase(ancestor::protocol/@name)»_state.«yml:lcase(ancestor::fsm/@name)»
  38.139  
  38.140      choose {
  38.141          when "func:basicType()" // copyable
  38.142 @@ -273,6 +297,20 @@
  38.143                   = session->«$state».«@name»;
  38.144  
  38.145          ||
  38.146 +        when "@type='Identity'"
  38.147 +        ||
  38.148 +        {
  38.149 +            pEp_identity *ident = Identity_to_Struct(&session->«$state».«@name», NULL);
  38.150 +            if (!ident)
  38.151 +                return PEP_OUT_OF_MEMORY;
  38.152 +            Identity_t *_ident = Identity_from_Struct(ident,
  38.153 +                    &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name»);
  38.154 +            free_identity(ident);
  38.155 +            if (!_ident)
  38.156 +                return PEP_OUT_OF_MEMORY;
  38.157 +        }
  38.158 +
  38.159 +        ||
  38.160          when "@type='IdentityList'"
  38.161          ||
  38.162          {
  38.163 @@ -338,6 +376,21 @@
  38.164                  .choice.«$message_name».«@name»;
  38.165  
  38.166          ||
  38.167 +        when "@type='Identity'"
  38.168 +        ||
  38.169 +        {
  38.170 +            pEp_identity *ident = Identity_to_Struct(
  38.171 +                    &msg->choice.«yml:lcase(../../@name)».choice.«$message_name».«@name», NULL);
  38.172 +            if (!ident)
  38.173 +                return PEP_OUT_OF_MEMORY;
  38.174 +            Identity_t *_ident = Identity_from_Struct(ident,
  38.175 +                    &session->«yml:lcase(../../../@name)»_state.«yml:lcase(../../@name)».«@name»);
  38.176 +            free_identity(ident);
  38.177 +            if (!_ident)
  38.178 +                return PEP_OUT_OF_MEMORY;
  38.179 +        }
  38.180 +
  38.181 +        ||
  38.182          when "@type='IdentityList'"
  38.183          ||
  38.184          {
    39.1 --- a/sync/gen_statemachine.ysl2	Thu May 16 17:55:58 2019 +0200
    39.2 +++ b/sync/gen_statemachine.ysl2	Wed Aug 07 14:17:27 2019 +0200
    39.3 @@ -38,7 +38,7 @@
    39.4  
    39.5              // transport data
    39.6              pEp_identity *from;
    39.7 -            char *signature_fpr;
    39.8 +            char *sender_fpr;
    39.9  
   39.10              identity_list *own_identities;
   39.11          } «@name»_event_t;
   39.12 @@ -119,7 +119,7 @@
   39.13                  free_identity_list(ev->own_identities);
   39.14                  free_«@name»_message(ev->msg);
   39.15                  free_identity(ev->from);
   39.16 -                free(ev->signature_fpr);
   39.17 +                free(ev->sender_fpr);
   39.18                  free(ev);
   39.19              }
   39.20          }
   39.21 @@ -211,7 +211,7 @@
   39.22                      const char *data,
   39.23                      size_t size,
   39.24                      const pEp_identity *from,
   39.25 -                    const char *signature_fpr
   39.26 +                    const char *sender_fpr
   39.27                  );
   39.28  
   39.29              #ifdef __cplusplus
   39.30 @@ -328,7 +328,7 @@
   39.31                      const char *data,
   39.32                      size_t size,
   39.33                      const pEp_identity *from,
   39.34 -                    const char *signature_fpr
   39.35 +                    const char *sender_fpr
   39.36                  )
   39.37              {
   39.38                  assert(session && data && size);
   39.39 @@ -373,10 +373,10 @@
   39.40                      }
   39.41                  }
   39.42  
   39.43 -                if (signature_fpr) {
   39.44 -                    ev->signature_fpr = strdup(signature_fpr);
   39.45 -                    assert(ev->signature_fpr);
   39.46 -                    if (!ev->signature_fpr) {
   39.47 +                if (sender_fpr) {
   39.48 +                    ev->sender_fpr = strdup(sender_fpr);
   39.49 +                    assert(ev->sender_fpr);
   39.50 +                    if (!ev->sender_fpr) {
   39.51                          status = PEP_OUT_OF_MEMORY;
   39.52                          goto the_end;
   39.53                      }
   39.54 @@ -447,8 +447,8 @@
   39.55  
   39.56                      // these go anycast; previously used address is sticky (unicast)
   39.57                      `` for "fsm/message[@type='anycast']" |>> case «../@name»_PR_«yml:mixedCase(@name)»:
   39.58 -                        if (!session->«yml:lcase(@name)»_state.common.from `> |`|
   39.59 -                            (session->«yml:lcase(@name)»_state.common.from->flags &
   39.60 +                        if (!session->«yml:lcase(@name)»_state.transport.from `> |`|
   39.61 +                            (session->«yml:lcase(@name)»_state.transport.from->flags &
   39.62                              PEP_idf_not_for_«yml:lcase(@name)»)) {
   39.63  
   39.64                              // no address available yet, try to find one
   39.65 @@ -468,7 +468,7 @@
   39.66                              }
   39.67                          }
   39.68                          else {
   39.69 -                            pEp_identity *channel = identity_dup(session->«yml:lcase(@name)»_state.common.from);
   39.70 +                            pEp_identity *channel = identity_dup(session->«yml:lcase(@name)»_state.transport.from);
   39.71                              if (!channel) {
   39.72                                  status = PEP_OUT_OF_MEMORY;
   39.73                                  goto the_end;
   39.74 @@ -521,13 +521,13 @@
   39.75                      `` for "fsm/message[@security='untrusted']" |>>> case «../@name»_PR_«yml:mixedCase(@name)»:
   39.76                              // add fpr of key of comm partner
   39.77  
   39.78 -                            assert(session->«yml:lcase(@name)»_state.common.signature_fpr);
   39.79 -                            if (!session->«yml:lcase(@name)»_state.common.signature_fpr) {
   39.80 +                            assert(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
   39.81 +                            if (!session->«yml:lcase(@name)»_state.comm_partner.sender_fpr) {
   39.82                                  status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
   39.83                                  goto the_end;
   39.84                              }
   39.85  
   39.86 -                            extra = new_stringlist(session->«yml:lcase(@name)»_state.common.signature_fpr);
   39.87 +                            extra = new_stringlist(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
   39.88                              if (!extra) {
   39.89                                  status = PEP_OUT_OF_MEMORY;
   39.90                                  goto the_end;
   39.91 @@ -552,15 +552,16 @@
   39.92                                  status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
   39.93                                  goto the_end;
   39.94                              }
   39.95 +                            add_opt_field(m, "pEp-auto-consume", "yes");
   39.96                              free_message(_m);
   39.97                              break;
   39.98  
   39.99                      `` for "fsm/message[@security='attach_own_keys']" |>>> case «../@name»_PR_«yml:mixedCase(@name)»:
  39.100 -                            // check if this is the key of a former negotiation
  39.101 +                            // check if we had a former negotiation
  39.102  
  39.103                              transaction = false;
  39.104 -                            for (int i=0; i < session->own_«yml:lcase(@name)»_state.negotiation.size; i++) {
  39.105 -                                if (session->own_«yml:lcase(@name)»_state.negotiation.buf[i]) {
  39.106 +                            for (int i=0; i < session->«yml:lcase(@name)»_state.own.negotiation.size; i++) {
  39.107 +                                if (session->«yml:lcase(@name)»_state.own.negotiation.buf[i]) {
  39.108                                      transaction = true;
  39.109                                      break;
  39.110                                  }
  39.111 @@ -573,12 +574,12 @@
  39.112                              // secret keys
  39.113  
  39.114                              if (transaction) {
  39.115 -                                assert(session->own_«yml:lcase(@name)»_state.signature_fpr &&
  39.116 -                                    session->«yml:lcase(@name)»_state.common.from &&
  39.117 -                                    session->«yml:lcase(@name)»_state.common.from->user_id);
  39.118 -                                if (!(session->own_«yml:lcase(@name)»_state.signature_fpr &&
  39.119 -                                        session->«yml:lcase(@name)»_state.common.from &&
  39.120 -                                        session->«yml:lcase(@name)»_state.common.from->user_id))
  39.121 +                                assert(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr &&
  39.122 +                                    session->«yml:lcase(@name)»_state.transport.from &&
  39.123 +                                    session->«yml:lcase(@name)»_state.transport.from->user_id);
  39.124 +                                if (!(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr &&
  39.125 +                                        session->«yml:lcase(@name)»_state.transport.from &&
  39.126 +                                        session->«yml:lcase(@name)»_state.transport.from->user_id))
  39.127                                  {
  39.128                                      status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
  39.129                                      goto the_end;
  39.130 @@ -587,8 +588,8 @@
  39.131                                  // test if this is a green channel
  39.132  
  39.133                                  pEp_identity *ident = new_identity(NULL,
  39.134 -                                        session->own_«yml:lcase(@name)»_state.signature_fpr,
  39.135 -                                        session->«yml:lcase(@name)»_state.common.from->user_id,
  39.136 +                                        session->«yml:lcase(@name)»_state.comm_partner.sender_fpr,
  39.137 +                                        session->«yml:lcase(@name)»_state.transport.from->user_id,
  39.138                                          NULL
  39.139                                      );
  39.140                                  if (!ident) {
  39.141 @@ -612,7 +613,7 @@
  39.142  
  39.143                                  bool is_own_key = false;
  39.144                                  status = own_key_is_listed(session,
  39.145 -                                        session->own_«yml:lcase(@name)»_state.signature_fpr,
  39.146 +                                        session->«yml:lcase(@name)»_state.comm_partner.sender_fpr,
  39.147                                          &is_own_key);
  39.148                                  assert(!status);
  39.149                                  if (status)
  39.150 @@ -625,7 +626,7 @@
  39.151  
  39.152                                  // if so add key of comm partner to extra keys
  39.153  
  39.154 -                                extra = new_stringlist(session->own_«yml:lcase(@name)»_state.signature_fpr);
  39.155 +                                extra = new_stringlist(session->«yml:lcase(@name)»_state.comm_partner.sender_fpr);
  39.156                                  if (!extra) {
  39.157                                      status = PEP_OUT_OF_MEMORY;
  39.158                                      goto the_end;
  39.159 @@ -660,7 +661,7 @@
  39.160                                                 // if we include this in the size, libetpan will null terminate and 
  39.161                                                 // go bananas. We can't have a NUL in the mime text.
  39.162  
  39.163 -                            for (stringlist_t *sl = session->own_«yml:lcase(@name)»_state.own_keys;
  39.164 +                            for (stringlist_t *sl = session->«yml:lcase(@name)»_state.own.keys;
  39.165                                      sl && sl->value ; sl = sl->next)
  39.166                              {
  39.167                                  char *_key_data = NULL;
  39.168 @@ -729,6 +730,7 @@
  39.169                                  status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
  39.170                                  goto the_end;
  39.171                              }
  39.172 +                            add_opt_field(m, "pEp-auto-consume", "yes");
  39.173                              free_message(_m);
  39.174                              break;
  39.175  
  39.176 @@ -752,6 +754,7 @@
  39.177                                  status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
  39.178                                  goto the_end;
  39.179                              }
  39.180 +                            add_opt_field(m, "pEp-auto-consume", "yes");
  39.181                              free_message(_m);
  39.182                      }
  39.183  
  39.184 @@ -766,6 +769,8 @@
  39.185                  free(data);
  39.186                  free(key_data);
  39.187                  free_«@name»_message(msg);
  39.188 +                if (status)
  39.189 +                    SERVICE_ERROR_LOG(session, "send_«@name»_message()", status);
  39.190                  return status;
  39.191              }
  39.192  
  39.193 @@ -806,22 +811,22 @@
  39.194                  // update transport data
  39.195  
  39.196                  if (ev->from) {
  39.197 -                    free_identity(session->«yml:lcase(@name)»_state.common.from);
  39.198 -                    session->«yml:lcase(@name)»_state.common.from = ev->from;
  39.199 +                    free_identity(session->«yml:lcase(@name)»_state.transport.from);
  39.200 +                    session->«yml:lcase(@name)»_state.transport.from = ev->from;
  39.201                      ev->from = NULL;
  39.202                  }
  39.203  
  39.204 -                if (ev->signature_fpr) {
  39.205 -                    free(session->«yml:lcase(@name)»_state.common.signature_fpr);
  39.206 -                    session->«yml:lcase(@name)»_state.common.signature_fpr = ev->signature_fpr;
  39.207 -                    ev->signature_fpr = NULL;
  39.208 +                if (ev->sender_fpr) {
  39.209 +                    free(session->«yml:lcase(@name)»_state.transport.sender_fpr);
  39.210 +                    session->«yml:lcase(@name)»_state.transport.sender_fpr = ev->sender_fpr;
  39.211 +                    ev->sender_fpr = NULL;
  39.212                  }
  39.213  
  39.214                  // update own identities
  39.215  
  39.216                  if (ev->own_identities && ev->own_identities->ident) {
  39.217 -                    free_identity_list(session->own_«yml:lcase(@name)»_state.own_identities);
  39.218 -                    session->own_«yml:lcase(@name)»_state.own_identities = ev->own_identities;
  39.219 +                    free_identity_list(session->«yml:lcase(@name)»_state.own.identities);
  39.220 +                    session->«yml:lcase(@name)»_state.own.identities = ev->own_identities;
  39.221                      ev->own_identities = NULL;
  39.222                  }
  39.223  
  39.224 @@ -899,7 +904,7 @@
  39.225          if "position()=1" |>> // these messages require a detached signature
  39.226          ||
  39.227                  case «../@name»_PR_«yml:mixedCase(@name)»:
  39.228 -                    if (!signature_fpr) {
  39.229 +                    if (!sender_fpr) {
  39.230                          status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
  39.231                          goto the_end;
  39.232                      }
  39.233 @@ -929,7 +934,7 @@
  39.234                          status = PEP_«yml:ucase(ancestor::protocol/@name)»_ILLEGAL_MESSAGE;
  39.235                          goto the_end;
  39.236                      }
  39.237 -                    status = own_key_is_listed(session, signature_fpr, &is_own_key);
  39.238 +                    status = own_key_is_listed(session, sender_fpr, &is_own_key);
  39.239                      if (status)
  39.240                          goto the_end;
  39.241                      if (!is_own_key) {
  39.242 @@ -1044,8 +1049,10 @@
  39.243  
  39.244          // state machine
  39.245  
  39.246 +        #ifndef NDEBUG
  39.247          const char *«@name»_state_name(int state);
  39.248          const char *«@name»_event_name(int event);
  39.249 +        #endif
  39.250  
  39.251          // the state machine function is returning the next state in case of a
  39.252          // transition or None for staying
  39.253 @@ -1071,6 +1078,9 @@
  39.254          #include "«@name»_fsm.h"
  39.255          #include <stdlib.h>
  39.256  
  39.257 +        #ifdef NDEBUG
  39.258 +        static
  39.259 +        #endif
  39.260          const char *«@name»_state_name(int state)
  39.261          {
  39.262              switch (state) {
  39.263 @@ -1091,6 +1101,9 @@
  39.264              }
  39.265          }
  39.266  
  39.267 +        #ifdef NDEBUG
  39.268 +        static
  39.269 +        #endif
  39.270          const char *«@name»_event_name(int event)
  39.271          {
  39.272              switch (event) {
  39.273 @@ -1156,7 +1169,7 @@
  39.274              switch (state) {
  39.275                  `` apply "state", 2, mode=fsm
  39.276                  default:
  39.277 -                    «@name»_ERR_LOG_INT("invalid state", state);
  39.278 +                    «@name»_ERR_LOG("invalid state", «@name»_state_name(state));
  39.279                      return invalid_state;
  39.280              }
  39.281              
    40.1 --- a/sync/sql_func.yml2	Thu May 16 17:55:58 2019 +0200
    40.2 +++ b/sync/sql_func.yml2	Wed Aug 07 14:17:27 2019 +0200
    40.3 @@ -31,7 +31,7 @@
    40.4      call "init_sql" with "sql", "$sql";
    40.5      ||
    40.6          int _result = 0;
    40.7 -        int_result = sqlite3_step(_sql);
    40.8 +        int_result = Sqlite3_step(_sql);
    40.9          assert(int_result == SQLITE_ROW);
   40.10          if (int_result == SQLITE_ROW)
   40.11              _result = sqlite3_column_int(_sql, 0);
    41.1 --- a/sync/sync.fsm	Thu May 16 17:55:58 2019 +0200
    41.2 +++ b/sync/sync.fsm	Wed Aug 07 14:17:27 2019 +0200
    41.3 @@ -10,7