merging newest sync branch generate_api
authornk
Fri, 17 May 2019 17:30:57 +0200
branchgenerate_api
changeset 37698f5847c0cd13
parent 3416 a5e50e8ea902
parent 3719 6806be48b327
child 3770 257a31e9b412
merging newest sync branch
.hgignore
default.conf
src/message.h
sync/sync_protocol.txt
sync/sync_ux.txt
     1.1 --- a/.hgtags	Thu Mar 28 15:40:45 2019 +0100
     1.2 +++ b/.hgtags	Fri May 17 17:30:57 2019 +0200
     1.3 @@ -10,3 +10,20 @@
     1.4  43ab5608555e12cb110ccda79cbfb9783e40408b Release 1.1.0
     1.5  084c00652ac9fedcd56e2c316be795ed0ba00b2f Release 1.1.1
     1.6  eace10725457069b5c5bfdb8723e876bfa63d753 Release 1.2.0
     1.7 +9425e2da65e4d4e3febab6725a0a101676386313 1.3.0-RC-default
     1.8 +4d6c07372e3ef7d8768908d17f07a54d74ef291d 1.3.0-RC-sync
     1.9 +1bf48c2e4230d4e7cb2589743182a230aa60691b 1.3.1-RC2-sync
    1.10 +1bf48c2e4230d4e7cb2589743182a230aa60691b 1.3.1-RC2-sync
    1.11 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    1.12 +4d4dbd6be59a35ad107eb334fb0eaf2d5b08c517 add
    1.13 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    1.14 +4d4dbd6be59a35ad107eb334fb0eaf2d5b08c517 1.3.1-RC2-sync
    1.15 +4d4dbd6be59a35ad107eb334fb0eaf2d5b08c517 1.3.1-RC2-sync
    1.16 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    1.17 +4998d60e0fe87847185ee3e99ae1b42074722882 2.0.0-RC
    1.18 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    1.19 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    1.20 +4998d60e0fe87847185ee3e99ae1b42074722882 2.0.0-RC
    1.21 +0000000000000000000000000000000000000000 2.0.0-RC
    1.22 +0000000000000000000000000000000000000000 2.0.0-RC
    1.23 +c4eb9bb2008fbe531f892fd56f8edce53048eb62 2.0.0-RC
     2.1 --- a/Makefile	Thu Mar 28 15:40:45 2019 +0100
     2.2 +++ b/Makefile	Fri May 17 17:30:57 2019 +0200
     2.3 @@ -5,58 +5,61 @@
     2.4  
     2.5  HERE_REL := $(notdir $(CURDIR))
     2.6  
     2.7 -include default.conf
     2.8 +include Makefile.conf
     2.9  
    2.10  ifneq ($(wildcard local.conf),)
    2.11      $(info ================================================)
    2.12 -    $(info Overrides in \`local.conf\` are used.)
    2.13 +    $(info Overrides in `local.conf` are used.)
    2.14      $(info ================================================)
    2.15  endif
    2.16  
    2.17  ifdef BUILD_CONFIG
    2.18      $(info ================================================)
    2.19 -    $(info Overrides in \`$(BUILD_CONFIG)\` are used.)
    2.20 +    $(info Overrides in `$(BUILD_CONFIG)` are used.)
    2.21      $(info ================================================)
    2.22  endif
    2.23  
    2.24 -.PHONY: all
    2.25 -all:
    2.26 +.PHONY: all sync asn1 build install dbinstall uninstall clean tags test package db
    2.27 +
    2.28 +build: asn1
    2.29 +	$(MAKE) -C src
    2.30 +
    2.31 +all: build
    2.32 +	make -C test
    2.33 +
    2.34 +sync:
    2.35  	$(MAKE) -C sync
    2.36 +
    2.37 +asn1: sync
    2.38  	$(MAKE) -C asn.1
    2.39 -	$(MAKE) -C src all
    2.40  
    2.41 -.PHONY: install
    2.42 -install: all
    2.43 +install: build
    2.44  	$(MAKE) -C src install
    2.45  	$(MAKE) -C asn.1 install
    2.46  
    2.47 -.PHONY: uninstall
    2.48 +dbinstall: db
    2.49 +	$(MAKE) -C db install
    2.50 +
    2.51  uninstall:
    2.52  	$(MAKE) -C src uninstall
    2.53  	$(MAKE) -C asn.1 uninstall
    2.54  
    2.55 -.PHONY: clean
    2.56  clean:
    2.57  	$(MAKE) -C src clean
    2.58  	$(MAKE) -C test clean
    2.59  	$(MAKE) -C db clean
    2.60  	$(MAKE) -C sync clean
    2.61  	$(MAKE) -C asn.1 clean
    2.62 -	rm -rf test_home
    2.63  
    2.64 -.PHONY: tags
    2.65  tags:
    2.66  	$(MAKE) -C asn.1 tags
    2.67  	$(MAKE) -C src tags
    2.68  
    2.69 -.PHONY: test
    2.70  test: all
    2.71  	$(MAKE) -C test test
    2.72  
    2.73 -.PHONY: package
    2.74  package: clean
    2.75  	cd .. ; COPYFILE_DISABLE=true tar cjf pEpEngine.tar.bz2 "$(HERE_REL)"
    2.76  
    2.77 -.PHONY: db
    2.78  db:
    2.79  	$(MAKE) -C db db
     3.1 --- a/Makefile.conf	Thu Mar 28 15:40:45 2019 +0100
     3.2 +++ b/Makefile.conf	Fri May 17 17:30:57 2019 +0200
     3.3 @@ -5,107 +5,262 @@
     3.4  
     3.5  # See `doc/build-<your platform>.md` for documentation on how to build, and customize your build.
     3.6  
     3.7 +# This file sets all the make variables that allow you to customize a build.
     3.8 +# There are 3 ways in which you can customize your build:
     3.9 +# 1) Edit the variable assignments in this file (this is a tracked file, so your repository will be dirty)
    3.10 +# 2) Create `local.conf` and fill it with variable assignments.
    3.11 +# 3) Set the environment variable `BUILD_CONFIG` to an absolute path.
    3.12 +#    The variable assignments found in the make file at the path indicated by `BUILD_CONFIG` will be evaluated.
    3.13 +# Customization options are applied in the order given above. Later variable assignments take precedence over earlier ones.
    3.14 +# It is possible to use multiple variants simultaniously.
    3.15 +# If nothing is changed according to these 3 methods, a default configuration for your platform (specified below) will be used for the build.
    3.16 +
    3.17 +
    3.18 +######### Header #########
    3.19 +HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
    3.20 +
    3.21 +
    3.22  ######### General #########
    3.23  # To use (only) system libraries, set all the *_INC and *_LIB variables to the empty string.
    3.24  # All the *_INC and *_LIB variables are command line flags, not paths.
    3.25  # Thus, all *_INC variables' values must start with "-I", and all *_LIB variables' values must start with "-L".
    3.26  
    3.27 -#BUILD_ON:=$(shell uname)
    3.28 +BUILD_ON:=$(shell uname)
    3.29  
    3.30  # This variable specifies the platform that the engine should be cross-compiled for.
    3.31 -#BUILD_FOR=$(BUILD_ON)
    3.32 +BUILD_FOR=$(BUILD_ON)
    3.33 +
    3.34 +# Cross-compiling is currently not supported.
    3.35 +# Maybe you can hack something with `local.conf`.
    3.36 +ifneq ($(BUILD_ON),$(BUILD_FOR))
    3.37 +    $(error I don't know how to build for $(BUILD_FOR) on $(BUILD_ON).)
    3.38 +endif
    3.39  
    3.40  # Installation path prefix for libraries and binaries, except for system.db
    3.41 -#PREFIX=$(HOME)
    3.42 +PREFIX=$(HOME)
    3.43  
    3.44  # Installation path for system.db
    3.45 -#SYSTEM_DB=/usr/local/share/pEp/system.db
    3.46 +SYSTEM_DB=/usr/local/share/pEp/system.db
    3.47  
    3.48  # Filename of the pEpEngine library
    3.49 -#TARGET=libpEpEngine.so
    3.50 +ifeq ($(BUILD_FOR),Linux)
    3.51 +    TARGET=libpEpEngine.so
    3.52 +else ifeq ($(BUILD_FOR),Darwin)
    3.53 +    TARGET=libpEpEngine.dylib
    3.54 +endif
    3.55 +
    3.56 +# If empty, create a release build.
    3.57 +# Otherwise, create a debug build.
    3.58 +# This variable is ineffective when set anywhere else but here.
    3.59 +DEBUG=placeholder
    3.60 +
    3.61 +# If empty, suppress compiler warnings.
    3.62 +# Otherwise, print warnings.
    3.63 +# This variable is ineffective when set anywhere else but here.
    3.64 +WARN=placeholder
    3.65  
    3.66  
    3.67  ######### C and C++ #########
    3.68 -#TARGET_ARCH=
    3.69 +TARGET_ARCH=
    3.70  
    3.71  # The following two variables will be appended to.
    3.72 -# You can thus not set them to a fixed value here.
    3.73 -#LDFLAGS=
    3.74 +# You can thus not set them to a final, fixed value here.
    3.75 +ifeq ($(BUILD_FOR),Linux)
    3.76 +    LDFLAGS=
    3.77 +else ifeq ($(BUILD_FOR),Darwin)
    3.78 +    # "-bind_at_load" helps find symbol resolution errors faster
    3.79 +    LDFLAGS=-bind_at_load
    3.80 +endif
    3.81  
    3.82 -#LDLIBS=
    3.83 +LDLIBS=
    3.84  
    3.85  
    3.86  ######### C #########
    3.87 -#CC=
    3.88 +ifeq ($(BUILD_FOR),Linux)
    3.89 +    CC=gcc -std=c99 -pthread
    3.90 +else ifeq ($(BUILD_FOR),Darwin)
    3.91 +    # clang issues a warning when "-pthread" is used for linking.
    3.92 +    # So, include it in CFLAGS, and not in CC
    3.93 +    CC=clang -std=c99
    3.94 +endif
    3.95  
    3.96 -#CFLAGS=-fPIC -fstrict-aliasing -fdiagnostics-color=always
    3.97 +ifeq ($(BUILD_FOR),Linux)
    3.98 +    CFLAGS=-fPIC -fstrict-aliasing -fdiagnostics-color=always
    3.99 +else ifeq ($(BUILD_FOR),Darwin)
   3.100 +    CFLAGS=-pthread -fPIC -fstrict-aliasing -fcolor-diagnostics
   3.101 +endif
   3.102  
   3.103 -#CPPFLAGS=
   3.104 -
   3.105 -#CFLAGS+= -w -O3 -DNDEBUG
   3.106 +# The flag -DNDEBUG will always be removed from CFLAGS for compiling tests.
   3.107 +# The tests do not work properly, if compiled with -DNDEBUG
   3.108 +ifeq ($(BUILD_FOR),Linux)
   3.109 +    ifdef WARN
   3.110 +        CFLAGS+= -Wall -pedantic -Wstrict-aliasing=3
   3.111 +    else
   3.112 +        CFLAGS+= -w
   3.113 +    endif
   3.114 +    ifdef DEBUG
   3.115 +        CFLAGS+= -g -ggdb -DDEBUG_ERRORSTACK
   3.116 +    else
   3.117 +        CFLAGS+= -O3 -DNDEBUG
   3.118 +    endif
   3.119 +else ifeq ($(BUILD_FOR),Darwin)
   3.120 +    ifdef WARN
   3.121 +        # FIXME Remove 'no-extended-offsetof' after ENGINE-236 is closed.
   3.122 +        CFLAGS+= -Wall -pedantic -Wno-extended-offsetof
   3.123 +    else
   3.124 +        CFLAGS+= -w
   3.125 +    endif
   3.126 +    ifdef DEBUG
   3.127 +        CFLAGS+= -O0 -g -DDEBUG_ERRORSTACK
   3.128 +    else
   3.129 +        CFLAGS+= -O3 -DNDEBUG
   3.130 +    endif
   3.131 +endif
   3.132  
   3.133  # Additional CFLAGS used for compiling ASN1C-generated code
   3.134 -#CFLAGS_GENERATED=-D_DEFAULT_SOURCE
   3.135 +ifeq ($(BUILD_FOR),Linux)
   3.136 +    # The '_DEFAULT_SOURCE' feature test macro is required to suppress the warning
   3.137 +    #   _BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE
   3.138 +    # otherwise printed during the compilation of every asn1c-generated C file.
   3.139 +    # It's a glibc specific warning, only present in few versions around ~2.19.
   3.140 +    # See https://lwn.net/Articles/590381/ for a discussion.
   3.141 +    CFLAGS_GENERATED=-D_DEFAULT_SOURCE
   3.142 +else ifeq ($(BUILD_FOR),Darwin)
   3.143 +    CFLAGS_GENERATED=
   3.144 +endif
   3.145  
   3.146  
   3.147  ######### C++ #########
   3.148 -#CXX=g++ -std=gnu++11 -pthread
   3.149 +ifeq ($(BUILD_FOR),Linux)
   3.150 +    CXX=g++ -std=gnu++11 -pthread
   3.151 +else ifeq ($(BUILD_FOR),Darwin)
   3.152 +    # clang issues a warning when "-pthread" is used for linking. So, include it in CXXFLAGS, and not in CXX
   3.153 +    CXX=clang -std=c++11
   3.154 +endif
   3.155  
   3.156 -#CXXFLAGS=-fdiagnostics-color=always -I../src -I../asn.1 $(ETPAN_INC) -w -O3 -DNDEBUG
   3.157 +# The flag -DNDEBUG will always be removed from CXXFLAGS for compiling tests.
   3.158 +# The tests do not work properly, if compiled with -DNDEBUG
   3.159 +ifeq ($(BUILD_FOR),Linux)
   3.160 +    CXXFLAGS=-fdiagnostics-color=always -I../src -I../asn.1 $(ETPAN_INC)
   3.161 +    ifdef WARN
   3.162 +        CXXFLAGS+=
   3.163 +    else
   3.164 +        CXXFLAGS+= -w
   3.165 +    endif
   3.166 +    ifdef DEBUG
   3.167 +        CXXFLAGS+= -g -ggdb
   3.168 +    else
   3.169 +        CXXFLAGS+= -O3 -DNDEBUG
   3.170 +    endif
   3.171 +else ifeq ($(BUILD_FOR),Darwin)
   3.172 +    CXXFLAGS=-pthread -fcolor-diagnostics -I../src -I../asn.1 $(ETPAN_INC)
   3.173 +    ifdef WARN
   3.174 +        CXXFLAGS+=
   3.175 +    else
   3.176 +        CXXFLAGS+= -w
   3.177 +    endif
   3.178 +    ifdef DEBUG
   3.179 +        CXXFLAGS+= -O0 -g
   3.180 +    else
   3.181 +        CXXFLAGS+= -O3 -DNDEBUG
   3.182 +    endif
   3.183 +endif
   3.184 +
   3.185 +
   3.186 +######### C and C++ #########
   3.187 +CPPFLAGS=
   3.188  
   3.189  
   3.190  ######### YML2 #########
   3.191 -#YML2_PATH=$(HOME)/yml2
   3.192 +YML2_PATH=$(HOME)/yml2
   3.193  
   3.194 -#YML2_PROC=$(YML2_PATH)/yml2proc
   3.195 +YML2_PROC=$(YML2_PATH)/yml2proc $(YML2_OPTS)
   3.196  
   3.197 -#YML2_OPTS=--encoding=utf8
   3.198 +YML2_OPTS=--encoding=utf8
   3.199  
   3.200  
   3.201  ######### asn1c #########
   3.202  # asn1c binary
   3.203 -#ASN1C=asn1c
   3.204 +ASN1C=asn1c
   3.205  
   3.206  # asn1c include search flag
   3.207 +ASN1C_INC=
   3.208  #ASN1C_INC=-I$(HOME)/include
   3.209  
   3.210  
   3.211  ######### libetpan #########
   3.212  # libetpan library search flag
   3.213 -#ETPAN_LIB=-L$(PREFIX)/lib
   3.214 +ETPAN_LIB=
   3.215 +#ETPAN_LIB=-L$(HOME)/lib
   3.216  
   3.217  # libetpan include search flag
   3.218 -#ETPAN_INC=-I$(PREFIX)/include
   3.219 +ETPAN_INC=
   3.220 +#ETPAN_INC=-I$(HOME)/include
   3.221 +
   3.222 +
   3.223 +######### pEp MIME #########
   3.224 +# set this to skip libetpan and use PEP_MIME instead
   3.225 +# PEP_MIME=1
   3.226 +#
   3.227 +# pEp MIME library search flag
   3.228 +PEP_MIME_LIB=
   3.229 +# pEp MIME include search flag
   3.230 +PEP_MIME_INC=
   3.231  
   3.232  
   3.233  ######### sqlite3 #########
   3.234  # If empty (or undefined), compile sqlite3 from the sources shipped with the pEp distribution.
   3.235  # Otherwise, use an sqlite3 implementation found in the OS's include/library paths.
   3.236 -#SQLITE3_FROM_OS=placeholder
   3.237 +SQLITE3_FROM_OS=placeholder
   3.238  
   3.239  
   3.240  ######### OpenPGP #########
   3.241  # Path of GPG binary
   3.242  # gpgconf is not available for old version of GPG, for example GPG 2.0.30. Override this variable, if you compile the engine for such an old version.
   3.243 -#GPG_CMD:=$(shell gpgconf --list-components | awk -F: '/^gpg:/ { print $$3; exit 0; }')
   3.244 +GPG_CMD:=$(shell gpgconf --list-components | awk -F: '/^gpg:/ { print $$3; exit 0; }')
   3.245  
   3.246 -# Selects OpenPGP implementation. must be either `GPG` or `NETPGP`
   3.247 -#OPENPGP=GPG
   3.248 +# Selects OpenPGP implementation. must be either `SEQUOIA`, `GPG` or `NETPGP`
   3.249 +OPENPGP=GPG
   3.250  
   3.251 -# Path of libGPGME binary
   3.252 -#LIBGPGME=libgpgme.so.11
   3.253 +# Sequoia-specific variables
   3.254 +SEQUOIA_CFLAGS=
   3.255 +SEQUOIA_LDFLAGS=
   3.256 +SEQUOIA_LIB=
   3.257 +SEQUOIA_INC=
   3.258 +
   3.259 +# libGPGME filename
   3.260 +ifeq ($(BUILD_FOR),Linux)
   3.261 +    LIBGPGME=libgpgme.so.11
   3.262 +else ifeq ($(BUILD_FOR),Darwin)
   3.263 +    LIBGPGME=libgpgme.11.dylib
   3.264 +endif
   3.265  
   3.266  # libGPGME library search flag
   3.267 -#GPGME_LIB=
   3.268 +GPGME_LIB=
   3.269 +#GPGME_LIB=-L$(HOME)/lib
   3.270  
   3.271  # libGPGME include search flag
   3.272 -#GPGME_INC=
   3.273 +GPGME_INC=
   3.274 +#GPGME_INC=-I$(HOME)/include
   3.275  
   3.276  # NETPGP library search flag
   3.277 -#NETPGP_LIB=-L$(PREFIX)/lib
   3.278 +NETPGP_LIB=
   3.279 +#NETPGP_LIB=-L$(HOME)/lib
   3.280  
   3.281  # libGPGME include search flag
   3.282 -#NETPGP_INC=-I$(PREFIX)/include
   3.283 +NETPGP_INC=
   3.284 +#NETPGP_INC=-I$(HOME)/include
   3.285 +
   3.286 +
   3.287 +
   3.288 +######### CppUnit #########
   3.289 +# CppUnit library search flag
   3.290 +CPPUNIT_LIB=
   3.291 +#CPPUNIT_LIB=-L$(HOME)/local/lib
   3.292 +
   3.293 +# CppUnit include search flag
   3.294 +CPPUNIT_INC=
   3.295 +#CPPUNIT_INC=-I$(HOME)/local/inc
   3.296  
   3.297  
   3.298  ######### Engine internals #########
   3.299 @@ -114,7 +269,38 @@
   3.300  # CRASHDUMP_DEFAULT_LINES - number of log lines to deliver for crashdumps
   3.301  # Example:
   3.302  #    EXTRA_MACROS=-DDEFAULT_KEYSERVER=\"default-server.org\" -DCRASHDUMP_DEFAULT_LINES=23
   3.303 -#EXTRA_MACROS=
   3.304 +EXTRA_MACROS=
   3.305  
   3.306 -# add this for running tests in debugger
   3.307 +
   3.308 +######### Misc #########
   3.309 +# FIXME Maybe include these variables here.
   3.310 +# Check how they are used throughout the project before setting them here
   3.311 +#LLDB_BIN
   3.312 +
   3.313 +# Add this for running tests in debugger
   3.314  #TEST_DEBUGGER=lldb --batch -o r
   3.315 +
   3.316 +# comma-separated list of tests to exclude from gensuite (relevant for running tests only)
   3.317 +EXCLUDE=
   3.318 +
   3.319 +
   3.320 +######### Footer #########
   3.321 +-include $(HERE)/local.conf
   3.322 +
   3.323 +ifdef BUILD_CONFIG
   3.324 +    include $(BUILD_CONFIG)
   3.325 +endif
   3.326 +
   3.327 +######### Post processing assignments ########
   3.328 +# These variables are ineffective when set anywhere else but here.
   3.329 +ifeq ($(OPENPGP),SEQUOIA)
   3.330 +    SEQUOIA_CFLAGS=$(shell pkg-config --cflags-only-other sequoia-openpgp)
   3.331 +    SEQUOIA_LDFLAGS=$(shell pkg-config --libs-only-l --libs-only-other sequoia-openpgp)
   3.332 +    SEQUOIA_LIB=$(shell pkg-config --libs-only-L sequoia-openpgp)
   3.333 +    SEQUOIA_INC=$(shell pkg-config --cflags-only-I sequoia-openpgp)
   3.334 +    CFLAGS+= $(SEQUOIA_CFLAGS)
   3.335 +    LD_FLAGS+= $(SEQUOIA_LDFLAGS)
   3.336 +endif
   3.337 +
   3.338 +# YML_PATH is needed in the environment of every call to a program of the YML2 distribution
   3.339 +export YML_PATH=$(YML2_PATH)
     4.1 --- a/asn.1/Makefile	Thu Mar 28 15:40:45 2019 +0100
     4.2 +++ b/asn.1/Makefile	Fri May 17 17:30:57 2019 +0200
     4.3 @@ -1,30 +1,26 @@
     4.4  # This file is under GNU General Public License 3.0
     4.5  # see LICENSE.txt
     4.6  
     4.7 -include ../default.conf
     4.8 +include ../Makefile.conf
     4.9  
    4.10  ALL_SOURCE=$(subst $(NO_SOURCE),,$(wildcard *.c))
    4.11  ALL_OBJECTS=$(subst .c,.o,$(ALL_SOURCE))
    4.12  
    4.13 -all: generate
    4.14 -	make libasn1.a
    4.15 +.PHONY: all clean install uninstall
    4.16 +
    4.17 +all: Sync.c
    4.18 +	$(MAKE) libasn1.a
    4.19  
    4.20  libasn1.a: $(ALL_OBJECTS)
    4.21 -	ar -rc $@ $(ALL_OBJECTS)
    4.22 -
    4.23 -generate: Sync.c
    4.24 -	rm -f converter-sample.c
    4.25 +	$(AR) -rc $@ $(ALL_OBJECTS)
    4.26  
    4.27  %.o: %.c %.h
    4.28 -	$(CC) $(CFLAGS) $(OPTIMIZE) -I. -I$(ASN1C_INC) -c $< -o $@
    4.29 +	$(CC) $(CFLAGS) $(OPTIMIZE) -I. $(ASN1C_INC) -c $< -o $@
    4.30  
    4.31  Sync.c: sync.asn1 keysync.asn1 pEp.asn1
    4.32  	$(ASN1C) -gen-PER -fincludes-quoted -fcompound-names -pdu=auto pEp.asn1 keysync.asn1 $<
    4.33 -
    4.34 -sync.asn1 keysync.asn1 pEp.asn1:
    4.35 -	cp -f ../sync/generated/*.asn1 ../asn.1
    4.36 -
    4.37 -.PHONY: clean install uninstall tags
    4.38 +	rm -f converter-sample.c
    4.39 +	touch Sync.c
    4.40  
    4.41  clean:
    4.42  	rm -f *.a *.o *.c *.h *.sample sync.asn1 keysync.asn1
    4.43 @@ -33,5 +29,5 @@
    4.44  
    4.45  uninstall:
    4.46  
    4.47 -tags:
    4.48 +tags: $(wildcard *.c) $(wildcard *.h)
    4.49  	ctags *.c *.h
     5.1 --- a/build-android/jni/Android.mk	Thu Mar 28 15:40:45 2019 +0100
     5.2 +++ b/build-android/jni/Android.mk	Fri May 17 17:30:57 2019 +0200
     5.3 @@ -37,7 +37,7 @@
     5.4  $(shell sh $(LOCAL_PATH)/../takeOutHeaderFiles.sh $(LOCAL_PATH)../../)
     5.5  LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)../include
     5.6  
     5.7 -ENGINE_SRC_FILES := $(shell find $(LOCAL_PATH)/../../src/ ! -name "*netpgp*" -name "*.c")
     5.8 +ENGINE_SRC_FILES := $(shell find $(LOCAL_PATH)/../../src/ ! -name "*sequoia*" ! -name "*netpgp*" -name "*.c")
     5.9  #ENGINE_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../src/*.c)
    5.10  ASN1_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../asn.1/*.c)
    5.11  LOCAL_SRC_FILES := $(ENGINE_SRC_FILES:%=%)  $(ASN1_SRC_FILES:$(LOCAL_PATH)/%=%)
     6.1 --- a/build-android/jni/Application.mk	Thu Mar 28 15:40:45 2019 +0100
     6.2 +++ b/build-android/jni/Application.mk	Fri May 17 17:30:57 2019 +0200
     6.3 @@ -1,4 +1,4 @@
     6.4  APP_OPTIM := debug
     6.5  APP_PLATFORM=android-21
     6.6  APP_ABI := armeabi-v7a
     6.7 -NDK_TOOLCHAIN_VERSION = 4.8
     6.8 +NDK_TOOLCHAIN_VERSION = clang
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/build-mac/generated-files-asn1.txt	Fri May 17 17:30:57 2019 +0200
     7.3 @@ -0,0 +1,109 @@
     7.4 +$(SRCROOT)/../asn.1/BIT_STRING.c
     7.5 +$(SRCROOT)/../asn.1/BIT_STRING.h
     7.6 +$(SRCROOT)/../asn.1/BOOLEAN.c
     7.7 +$(SRCROOT)/../asn.1/BOOLEAN.h
     7.8 +$(SRCROOT)/../asn.1/Beacon.c
     7.9 +$(SRCROOT)/../asn.1/Beacon.h
    7.10 +$(SRCROOT)/../asn.1/CommitAccept.c
    7.11 +$(SRCROOT)/../asn.1/CommitAccept.h
    7.12 +$(SRCROOT)/../asn.1/CommitAcceptFirst.c
    7.13 +$(SRCROOT)/../asn.1/CommitAcceptFirst.h
    7.14 +$(SRCROOT)/../asn.1/CommitAcceptForGroup.c
    7.15 +$(SRCROOT)/../asn.1/CommitAcceptForGroup.h
    7.16 +$(SRCROOT)/../asn.1/CommitAcceptSecond.c
    7.17 +$(SRCROOT)/../asn.1/CommitAcceptSecond.h
    7.18 +$(SRCROOT)/../asn.1/CommitReject.c
    7.19 +$(SRCROOT)/../asn.1/CommitReject.h
    7.20 +$(SRCROOT)/../asn.1/GroupKeys.c
    7.21 +$(SRCROOT)/../asn.1/GroupKeys.h
    7.22 +$(SRCROOT)/../asn.1/GroupTrustThisKey.c
    7.23 +$(SRCROOT)/../asn.1/GroupTrustThisKey.h
    7.24 +$(SRCROOT)/../asn.1/Hash.c
    7.25 +$(SRCROOT)/../asn.1/Hash.h
    7.26 +$(SRCROOT)/../asn.1/Hex.c
    7.27 +$(SRCROOT)/../asn.1/Hex.h
    7.28 +$(SRCROOT)/../asn.1/INTEGER.c
    7.29 +$(SRCROOT)/../asn.1/INTEGER.h
    7.30 +$(SRCROOT)/../asn.1/ISO639-1.c
    7.31 +$(SRCROOT)/../asn.1/ISO639-1.h
    7.32 +$(SRCROOT)/../asn.1/Identity.c
    7.33 +$(SRCROOT)/../asn.1/Identity.h
    7.34 +$(SRCROOT)/../asn.1/IdentityList.c
    7.35 +$(SRCROOT)/../asn.1/IdentityList.h
    7.36 +$(SRCROOT)/../asn.1/KeySync.c
    7.37 +$(SRCROOT)/../asn.1/KeySync.h
    7.38 +$(SRCROOT)/../asn.1/NativeEnumerated.c
    7.39 +$(SRCROOT)/../asn.1/NativeEnumerated.h
    7.40 +$(SRCROOT)/../asn.1/NativeInteger.c
    7.41 +$(SRCROOT)/../asn.1/NativeInteger.h
    7.42 +$(SRCROOT)/../asn.1/NegotiationOpen.c
    7.43 +$(SRCROOT)/../asn.1/NegotiationOpen.h
    7.44 +$(SRCROOT)/../asn.1/NegotiationRequest.c
    7.45 +$(SRCROOT)/../asn.1/NegotiationRequest.h
    7.46 +$(SRCROOT)/../asn.1/OCTET_STRING.c
    7.47 +$(SRCROOT)/../asn.1/OCTET_STRING.h
    7.48 +$(SRCROOT)/../asn.1/OwnKeys.c
    7.49 +$(SRCROOT)/../asn.1/OwnKeys.h
    7.50 +$(SRCROOT)/../asn.1/OwnKeysFirst.c
    7.51 +$(SRCROOT)/../asn.1/OwnKeysFirst.h
    7.52 +$(SRCROOT)/../asn.1/OwnKeysSecond.c
    7.53 +$(SRCROOT)/../asn.1/OwnKeysSecond.h
    7.54 +$(SRCROOT)/../asn.1/PString.c
    7.55 +$(SRCROOT)/../asn.1/PString.h
    7.56 +$(SRCROOT)/../asn.1/PrintableString.c
    7.57 +$(SRCROOT)/../asn.1/PrintableString.h
    7.58 +$(SRCROOT)/../asn.1/Rollback.c
    7.59 +$(SRCROOT)/../asn.1/Rollback.h
    7.60 +$(SRCROOT)/../asn.1/Sync.c
    7.61 +$(SRCROOT)/../asn.1/Sync.h
    7.62 +$(SRCROOT)/../asn.1/TID.c
    7.63 +$(SRCROOT)/../asn.1/TID.h
    7.64 +$(SRCROOT)/../asn.1/UTF8String.c
    7.65 +$(SRCROOT)/../asn.1/UTF8String.h
    7.66 +$(SRCROOT)/../asn.1/Version.c
    7.67 +$(SRCROOT)/../asn.1/Version.h
    7.68 +$(SRCROOT)/../asn.1/asn_SEQUENCE_OF.c
    7.69 +$(SRCROOT)/../asn.1/asn_SEQUENCE_OF.h
    7.70 +$(SRCROOT)/../asn.1/asn_SET_OF.c
    7.71 +$(SRCROOT)/../asn.1/asn_SET_OF.h
    7.72 +$(SRCROOT)/../asn.1/asn_application.h
    7.73 +$(SRCROOT)/../asn.1/asn_codecs.h
    7.74 +$(SRCROOT)/../asn.1/asn_codecs_prim.c
    7.75 +$(SRCROOT)/../asn.1/asn_codecs_prim.h
    7.76 +$(SRCROOT)/../asn.1/asn_internal.h
    7.77 +$(SRCROOT)/../asn.1/asn_system.h
    7.78 +$(SRCROOT)/../asn.1/ber_decoder.c
    7.79 +$(SRCROOT)/../asn.1/ber_decoder.h
    7.80 +$(SRCROOT)/../asn.1/ber_tlv_length.c
    7.81 +$(SRCROOT)/../asn.1/ber_tlv_length.h
    7.82 +$(SRCROOT)/../asn.1/ber_tlv_tag.c
    7.83 +$(SRCROOT)/../asn.1/ber_tlv_tag.h
    7.84 +$(SRCROOT)/../asn.1/constr_CHOICE.c
    7.85 +$(SRCROOT)/../asn.1/constr_CHOICE.h
    7.86 +$(SRCROOT)/../asn.1/constr_SEQUENCE.c
    7.87 +$(SRCROOT)/../asn.1/constr_SEQUENCE.h
    7.88 +$(SRCROOT)/../asn.1/constr_SEQUENCE_OF.c
    7.89 +$(SRCROOT)/../asn.1/constr_SEQUENCE_OF.h
    7.90 +$(SRCROOT)/../asn.1/constr_SET_OF.c
    7.91 +$(SRCROOT)/../asn.1/constr_SET_OF.h
    7.92 +$(SRCROOT)/../asn.1/constr_TYPE.c
    7.93 +$(SRCROOT)/../asn.1/constr_TYPE.h
    7.94 +$(SRCROOT)/../asn.1/constraints.c
    7.95 +$(SRCROOT)/../asn.1/constraints.h
    7.96 +$(SRCROOT)/../asn.1/der_encoder.c
    7.97 +$(SRCROOT)/../asn.1/der_encoder.h
    7.98 +$(SRCROOT)/../asn.1/pdu_collection.c
    7.99 +$(SRCROOT)/../asn.1/per_decoder.c
   7.100 +$(SRCROOT)/../asn.1/per_decoder.h
   7.101 +$(SRCROOT)/../asn.1/per_encoder.c
   7.102 +$(SRCROOT)/../asn.1/per_encoder.h
   7.103 +$(SRCROOT)/../asn.1/per_opentype.c
   7.104 +$(SRCROOT)/../asn.1/per_opentype.h
   7.105 +$(SRCROOT)/../asn.1/per_support.c
   7.106 +$(SRCROOT)/../asn.1/per_support.h
   7.107 +$(SRCROOT)/../asn.1/xer_decoder.c
   7.108 +$(SRCROOT)/../asn.1/xer_decoder.h
   7.109 +$(SRCROOT)/../asn.1/xer_encoder.c
   7.110 +$(SRCROOT)/../asn.1/xer_encoder.h
   7.111 +$(SRCROOT)/../asn.1/xer_support.c
   7.112 +$(SRCROOT)/../asn.1/xer_support.h
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/build-mac/generated-files-sync.txt	Fri May 17 17:30:57 2019 +0200
     8.3 @@ -0,0 +1,6 @@
     8.4 +$(SRCROOT)/../src/sync_codec.c
     8.5 +$(SRCROOT)/../src/sync_impl.c
     8.6 +$(SRCROOT)/../src/sync_actions.c
     8.7 +$(SRCROOT)/../src/Sync_func.c
     8.8 +$(SRCROOT)/../src/Sync_event.c
     8.9 +$(SRCROOT)/../src/KeySync_fsm.c
     9.1 --- a/build-mac/pEpEngine.xcodeproj/project.pbxproj	Thu Mar 28 15:40:45 2019 +0100
     9.2 +++ b/build-mac/pEpEngine.xcodeproj/project.pbxproj	Fri May 17 17:30:57 2019 +0200
     9.3 @@ -3,23 +3,62 @@
     9.4  	archiveVersion = 1;
     9.5  	classes = {
     9.6  	};
     9.7 -	objectVersion = 46;
     9.8 +	objectVersion = 51;
     9.9  	objects = {
    9.10  
    9.11  /* Begin PBXBuildFile section */
    9.12 +		1521CEF6225C9AEF00FD2AA2 /* CommitAcceptForGroup.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521CEE9225C9AED00FD2AA2 /* CommitAcceptForGroup.c */; };
    9.13 +		1521CEF7225C9AEF00FD2AA2 /* PString.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEA225C9AEE00FD2AA2 /* PString.h */; };
    9.14 +		1521CEF8225C9AEF00FD2AA2 /* Rollback.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEB225C9AEE00FD2AA2 /* Rollback.h */; };
    9.15 +		1521CEF9225C9AEF00FD2AA2 /* CommitAcceptForGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEC225C9AEE00FD2AA2 /* CommitAcceptForGroup.h */; };
    9.16 +		1521CEFB225C9AEF00FD2AA2 /* CommitAccept.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEE225C9AEE00FD2AA2 /* CommitAccept.h */; };
    9.17 +		1521CEFD225C9AEF00FD2AA2 /* pdu_collection.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521CEF0225C9AEE00FD2AA2 /* pdu_collection.c */; };
    9.18 +		1521CEFE225C9AEF00FD2AA2 /* KeySync.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF1225C9AEE00FD2AA2 /* KeySync.h */; };
    9.19 +		1521CEFF225C9AEF00FD2AA2 /* CommitReject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF2225C9AEE00FD2AA2 /* CommitReject.h */; };
    9.20 +		1521CF00225C9AEF00FD2AA2 /* Sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF3225C9AEE00FD2AA2 /* Sync.h */; };
    9.21 +		1521CF01225C9AEF00FD2AA2 /* TID.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF5225C9AEF00FD2AA2 /* TID.h */; };
    9.22  		430BCC482015EE800077E998 /* pEp_string.h in Headers */ = {isa = PBXBuildFile; fileRef = 430BCC462015EE800077E998 /* pEp_string.h */; };
    9.23  		430BCC492015EE800077E998 /* pEp_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 430BCC472015EE800077E998 /* pEp_string.c */; };
    9.24  		430D258B1C9ED75A00B94535 /* blacklist.c in Sources */ = {isa = PBXBuildFile; fileRef = 430D258A1C9ED75A00B94535 /* blacklist.c */; };
    9.25 +		431F048C2273223600CCE960 /* CommitAcceptSecond.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04862273223600CCE960 /* CommitAcceptSecond.h */; };
    9.26 +		431F048D2273223600CCE960 /* CommitAcceptSecond.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F048B2273223600CCE960 /* CommitAcceptSecond.c */; };
    9.27 +		431F04902273227900CCE960 /* OwnKeysFirst.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F048E2273227900CCE960 /* OwnKeysFirst.h */; };
    9.28 +		431F04912273227900CCE960 /* OwnKeysFirst.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F048F2273227900CCE960 /* OwnKeysFirst.c */; };
    9.29 +		431F0494227322EF00CCE960 /* CommitAcceptFirst.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F0492227322EF00CCE960 /* CommitAcceptFirst.h */; };
    9.30 +		431F0495227322EF00CCE960 /* CommitAcceptFirst.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F0493227322EF00CCE960 /* CommitAcceptFirst.c */; };
    9.31 +		431F04A22273235300CCE960 /* GroupTrustThisKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F049C2273235300CCE960 /* GroupTrustThisKey.h */; };
    9.32 +		431F04A32273235300CCE960 /* GroupTrustThisKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F04A12273235300CCE960 /* GroupTrustThisKey.c */; };
    9.33 +		431F04A6227323A400CCE960 /* OwnKeysSecond.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04A4227323A400CCE960 /* OwnKeysSecond.h */; };
    9.34 +		431F04A7227323A400CCE960 /* OwnKeysSecond.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F04A5227323A400CCE960 /* OwnKeysSecond.c */; };
    9.35 +		431F04AA227323EE00CCE960 /* OwnKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04A8227323EE00CCE960 /* OwnKeys.h */; };
    9.36 +		431F04AB227323EE00CCE960 /* OwnKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F04A9227323EE00CCE960 /* OwnKeys.c */; };
    9.37 +		431F04B722733A7E00CCE960 /* key_reset.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04B222733A7E00CCE960 /* key_reset.h */; };
    9.38  		43370833203C075A004E6547 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 4337082D203C075A004E6547 /* sqlite3.c */; };
    9.39  		43370834203C075A004E6547 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = 43370832203C075A004E6547 /* sqlite3.h */; };
    9.40  		4354FF651D6EDF300033069C /* sync_impl.c in Sources */ = {isa = PBXBuildFile; fileRef = 4354FF641D6EDF300033069C /* sync_impl.c */; };
    9.41 -		4354FF691D6EE1A70033069C /* NULL.c in Sources */ = {isa = PBXBuildFile; fileRef = 4354FF681D6EE1A70033069C /* NULL.c */; };
    9.42 +		438C439B2167582500C7425B /* sync_api.h in Headers */ = {isa = PBXBuildFile; fileRef = 438C43962167582400C7425B /* sync_api.h */; };
    9.43  		438C43B52167752C00C7425B /* labeled_int_list.h in Headers */ = {isa = PBXBuildFile; fileRef = 438C43AF2167752C00C7425B /* labeled_int_list.h */; };
    9.44  		438C43B62167752C00C7425B /* labeled_int_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 438C43B42167752C00C7425B /* labeled_int_list.c */; };
    9.45 -		43BA0F461D7964750059172F /* asn1_helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 43BA0F451D7964750059172F /* asn1_helper.c */; };
    9.46 -		43E9BC6A1DB51A1E00AD2352 /* GroupUpdate.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E9BC691DB51A1E00AD2352 /* GroupUpdate.c */; };
    9.47 -		43E9BC7F1DB6720E00AD2352 /* UpdateRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E9BC7E1DB6720E00AD2352 /* UpdateRequest.c */; };
    9.48 +		43CC349E2276D31A002F77AF /* NegotiationRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CC349C2276D31A002F77AF /* NegotiationRequest.c */; };
    9.49 +		43CC349F2276D31A002F77AF /* NegotiationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CC349D2276D31A002F77AF /* NegotiationRequest.h */; };
    9.50 +		43CC34A22276D34C002F77AF /* NegotiationOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CC34A02276D34B002F77AF /* NegotiationOpen.c */; };
    9.51 +		43CC34A32276D34C002F77AF /* NegotiationOpen.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CC34A12276D34C002F77AF /* NegotiationOpen.h */; };
    9.52  		43F6921D1F164A47009418F5 /* resource_id.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F6921C1F164A47009418F5 /* resource_id.c */; };
    9.53 +		43F73BF02166269200AB4524 /* PString.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BEB2166269200AB4524 /* PString.c */; };
    9.54 +		43F73BF2216626E100AB4524 /* Sync_func.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF1216626E100AB4524 /* Sync_func.c */; };
    9.55 +		43F73BFC216627CC00AB4524 /* CommitAccept.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF5216627CB00AB4524 /* CommitAccept.c */; };
    9.56 +		43F73BFD216627CC00AB4524 /* TID.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF6216627CC00AB4524 /* TID.c */; };
    9.57 +		43F73BFE216627CC00AB4524 /* KeySync.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF7216627CC00AB4524 /* KeySync.c */; };
    9.58 +		43F73C00216627CC00AB4524 /* Rollback.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF9216627CC00AB4524 /* Rollback.c */; };
    9.59 +		43F73C02216627CC00AB4524 /* CommitReject.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BFB216627CC00AB4524 /* CommitReject.c */; };
    9.60 +		43F73C0B2166282C00AB4524 /* openpgp_compat.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C032166282C00AB4524 /* openpgp_compat.c */; };
    9.61 +		43F73C0C2166282C00AB4524 /* Sync_event.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C042166282C00AB4524 /* Sync_event.c */; };
    9.62 +		43F73C0D2166282C00AB4524 /* key_reset.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C052166282C00AB4524 /* key_reset.c */; };
    9.63 +		43F73C0E2166282C00AB4524 /* sync_codec.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C062166282C00AB4524 /* sync_codec.c */; };
    9.64 +		43F73C0F2166282C00AB4524 /* KeySync_fsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C072166282C00AB4524 /* KeySync_fsm.c */; };
    9.65 +		43F73C112166282C00AB4524 /* sync_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C092166282C00AB4524 /* sync_api.c */; };
    9.66 +		43F73C122166282C00AB4524 /* growing_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C0A2166282C00AB4524 /* growing_buf.c */; };
    9.67 +		43F73C14216628CA00AB4524 /* Sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C13216628CA00AB4524 /* Sync.c */; };
    9.68  		6400FB861B8CA1C6005221E3 /* libnetpgp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 645922521B8BD32B00A5AF93 /* libnetpgp.a */; };
    9.69  		6400FB8B1B8CA1CF005221E3 /* libetpan-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64289E371B8B630200FC617B /* libetpan-ios.a */; };
    9.70  		644297C51BE11CE0002BC73B /* system.db in Resources */ = {isa = PBXBuildFile; fileRef = 64951A1B1BE0FCD800B10E71 /* system.db */; };
    9.71 @@ -61,12 +100,8 @@
    9.72  		646C410B1D510CD800C63EFF /* constraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40B61D510CD700C63EFF /* constraints.h */; };
    9.73  		646C410C1D510CD800C63EFF /* der_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40B71D510CD700C63EFF /* der_encoder.c */; };
    9.74  		646C410D1D510CD800C63EFF /* der_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40B81D510CD700C63EFF /* der_encoder.h */; };
    9.75 -		646C410E1D510CD800C63EFF /* DeviceGroup-Protocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40B91D510CD700C63EFF /* DeviceGroup-Protocol.c */; };
    9.76 -		646C410F1D510CD800C63EFF /* DeviceGroup-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40BA1D510CD700C63EFF /* DeviceGroup-Protocol.h */; };
    9.77  		646C41101D510CD800C63EFF /* GroupKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40BB1D510CD700C63EFF /* GroupKeys.c */; };
    9.78  		646C41111D510CD800C63EFF /* GroupKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40BC1D510CD700C63EFF /* GroupKeys.h */; };
    9.79 -		646C41121D510CD800C63EFF /* HandshakeRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40BD1D510CD700C63EFF /* HandshakeRequest.c */; };
    9.80 -		646C41131D510CD800C63EFF /* HandshakeRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40BE1D510CD700C63EFF /* HandshakeRequest.h */; };
    9.81  		646C41141D510CD800C63EFF /* Hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40BF1D510CD700C63EFF /* Hash.c */; };
    9.82  		646C41151D510CD800C63EFF /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40C01D510CD700C63EFF /* Hash.h */; };
    9.83  		646C41181D510CD800C63EFF /* Hex.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40C31D510CD700C63EFF /* Hex.c */; };
    9.84 @@ -95,8 +130,6 @@
    9.85  		646C412F1D510CD800C63EFF /* per_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40DA1D510CD800C63EFF /* per_support.h */; };
    9.86  		646C41301D510CD800C63EFF /* PrintableString.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40DB1D510CD800C63EFF /* PrintableString.c */; };
    9.87  		646C41311D510CD800C63EFF /* PrintableString.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40DC1D510CD800C63EFF /* PrintableString.h */; };
    9.88 -		646C41321D510CD800C63EFF /* Sync-Protocols.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40DE1D510CD800C63EFF /* Sync-Protocols.c */; };
    9.89 -		646C41331D510CD800C63EFF /* Sync-Protocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40DF1D510CD800C63EFF /* Sync-Protocols.h */; };
    9.90  		646C41341D510CD800C63EFF /* UTF8String.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E01D510CD800C63EFF /* UTF8String.c */; };
    9.91  		646C41351D510CD800C63EFF /* UTF8String.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40E11D510CD800C63EFF /* UTF8String.h */; };
    9.92  		646C41361D510CD800C63EFF /* Version.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E21D510CD800C63EFF /* Version.c */; };
    9.93 @@ -108,12 +141,6 @@
    9.94  		646C413C1D510CD800C63EFF /* xer_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E81D510CD800C63EFF /* xer_support.c */; };
    9.95  		646C413D1D510CD800C63EFF /* xer_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40E91D510CD800C63EFF /* xer_support.h */; };
    9.96  		646C41451D510D2C00C63EFF /* sync_actions.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C413E1D510D2C00C63EFF /* sync_actions.c */; };
    9.97 -		646C41461D510D2C00C63EFF /* sync_driver.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C413F1D510D2C00C63EFF /* sync_driver.c */; };
    9.98 -		646C41471D510D2C00C63EFF /* sync_fsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C41401D510D2C00C63EFF /* sync_fsm.c */; };
    9.99 -		646C41481D510D2C00C63EFF /* sync_fsm.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C41411D510D2C00C63EFF /* sync_fsm.h */; };
   9.100 -		646C41491D510D2C00C63EFF /* sync_send_actions.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C41421D510D2C00C63EFF /* sync_send_actions.c */; };
   9.101 -		646C414A1D510D2C00C63EFF /* sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C41431D510D2C00C63EFF /* sync.c */; };
   9.102 -		646C414B1D510D2C00C63EFF /* sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C41441D510D2C00C63EFF /* sync.h */; };
   9.103  		646C414E1D510D8800C63EFF /* baseprotocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C414C1D510D8800C63EFF /* baseprotocol.c */; };
   9.104  		646C414F1D510D8800C63EFF /* baseprotocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C414D1D510D8800C63EFF /* baseprotocol.h */; };
   9.105  		649DE08B1B45C19100912F72 /* libcurl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649DE08A1B45C19100912F72 /* libcurl.a */; };
   9.106 @@ -140,6 +167,13 @@
   9.107  /* End PBXBuildFile section */
   9.108  
   9.109  /* Begin PBXContainerItemProxy section */
   9.110 +		43D47AA0225CC82400E97C5B /* PBXContainerItemProxy */ = {
   9.111 +			isa = PBXContainerItemProxy;
   9.112 +			containerPortal = 64796A371B455AA5004B1C24 /* Project object */;
   9.113 +			proxyType = 1;
   9.114 +			remoteGlobalIDString = 644297BE1BE11C65002BC73B;
   9.115 +			remoteInfo = pEpTrustWords;
   9.116 +		};
   9.117  		64289E321B8B630200FC617B /* PBXContainerItemProxy */ = {
   9.118  			isa = PBXContainerItemProxy;
   9.119  			containerPortal = 64DA24121B832EBA000BEE80 /* libetpan.xcodeproj */;
   9.120 @@ -197,20 +231,60 @@
   9.121  /* End PBXCopyFilesBuildPhase section */
   9.122  
   9.123  /* Begin PBXFileReference section */
   9.124 +		1521CEE9225C9AED00FD2AA2 /* CommitAcceptForGroup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptForGroup.c; path = ../asn.1/CommitAcceptForGroup.c; sourceTree = "<group>"; };
   9.125 +		1521CEEA225C9AEE00FD2AA2 /* PString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PString.h; path = ../asn.1/PString.h; sourceTree = "<group>"; };
   9.126 +		1521CEEB225C9AEE00FD2AA2 /* Rollback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Rollback.h; path = ../asn.1/Rollback.h; sourceTree = "<group>"; };
   9.127 +		1521CEEC225C9AEE00FD2AA2 /* CommitAcceptForGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptForGroup.h; path = ../asn.1/CommitAcceptForGroup.h; sourceTree = "<group>"; };
   9.128 +		1521CEEE225C9AEE00FD2AA2 /* CommitAccept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAccept.h; path = ../asn.1/CommitAccept.h; sourceTree = "<group>"; };
   9.129 +		1521CEF0225C9AEE00FD2AA2 /* pdu_collection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pdu_collection.c; path = ../asn.1/pdu_collection.c; sourceTree = "<group>"; };
   9.130 +		1521CEF1225C9AEE00FD2AA2 /* KeySync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeySync.h; path = ../asn.1/KeySync.h; sourceTree = "<group>"; };
   9.131 +		1521CEF2225C9AEE00FD2AA2 /* CommitReject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitReject.h; path = ../asn.1/CommitReject.h; sourceTree = "<group>"; };
   9.132 +		1521CEF3225C9AEE00FD2AA2 /* Sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sync.h; path = ../asn.1/Sync.h; sourceTree = "<group>"; };
   9.133 +		1521CEF4225C9AEE00FD2AA2 /* sync.asn1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = sync.asn1; path = ../asn.1/sync.asn1; sourceTree = "<group>"; };
   9.134 +		1521CEF5225C9AEF00FD2AA2 /* TID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TID.h; path = ../asn.1/TID.h; sourceTree = "<group>"; };
   9.135  		430BCC462015EE800077E998 /* pEp_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pEp_string.h; path = ../src/pEp_string.h; sourceTree = "<group>"; };
   9.136  		430BCC472015EE800077E998 /* pEp_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pEp_string.c; path = ../src/pEp_string.c; sourceTree = "<group>"; };
   9.137  		430D258A1C9ED75A00B94535 /* blacklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = blacklist.c; path = ../src/blacklist.c; sourceTree = "<group>"; };
   9.138 +		431F04862273223600CCE960 /* CommitAcceptSecond.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptSecond.h; path = ../asn.1/CommitAcceptSecond.h; sourceTree = "<group>"; };
   9.139 +		431F048B2273223600CCE960 /* CommitAcceptSecond.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptSecond.c; path = ../asn.1/CommitAcceptSecond.c; sourceTree = "<group>"; };
   9.140 +		431F048E2273227900CCE960 /* OwnKeysFirst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeysFirst.h; path = ../asn.1/OwnKeysFirst.h; sourceTree = "<group>"; };
   9.141 +		431F048F2273227900CCE960 /* OwnKeysFirst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeysFirst.c; path = ../asn.1/OwnKeysFirst.c; sourceTree = "<group>"; };
   9.142 +		431F0492227322EF00CCE960 /* CommitAcceptFirst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptFirst.h; path = ../asn.1/CommitAcceptFirst.h; sourceTree = "<group>"; };
   9.143 +		431F0493227322EF00CCE960 /* CommitAcceptFirst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptFirst.c; path = ../asn.1/CommitAcceptFirst.c; sourceTree = "<group>"; };
   9.144 +		431F049C2273235300CCE960 /* GroupTrustThisKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupTrustThisKey.h; path = ../asn.1/GroupTrustThisKey.h; sourceTree = "<group>"; };
   9.145 +		431F04A12273235300CCE960 /* GroupTrustThisKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupTrustThisKey.c; path = ../asn.1/GroupTrustThisKey.c; sourceTree = "<group>"; };
   9.146 +		431F04A4227323A400CCE960 /* OwnKeysSecond.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeysSecond.h; path = ../asn.1/OwnKeysSecond.h; sourceTree = "<group>"; };
   9.147 +		431F04A5227323A400CCE960 /* OwnKeysSecond.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeysSecond.c; path = ../asn.1/OwnKeysSecond.c; sourceTree = "<group>"; };
   9.148 +		431F04A8227323EE00CCE960 /* OwnKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeys.h; path = ../asn.1/OwnKeys.h; sourceTree = "<group>"; };
   9.149 +		431F04A9227323EE00CCE960 /* OwnKeys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeys.c; path = ../asn.1/OwnKeys.c; sourceTree = "<group>"; };
   9.150 +		431F04B222733A7E00CCE960 /* key_reset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = key_reset.h; path = ../src/key_reset.h; sourceTree = "<group>"; };
   9.151  		4337082D203C075A004E6547 /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqlite3.c; path = ../src/sqlite3.c; sourceTree = "<group>"; };
   9.152  		43370832203C075A004E6547 /* sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqlite3.h; path = ../src/sqlite3.h; sourceTree = "<group>"; };
   9.153 -		4346F86A1ECB38E700381CBE /* sync_app.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sync_app.h; path = ../src/sync_app.h; sourceTree = "<group>"; };
   9.154  		4354FF641D6EDF300033069C /* sync_impl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_impl.c; path = ../src/sync_impl.c; sourceTree = "<group>"; };
   9.155 -		4354FF681D6EE1A70033069C /* NULL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NULL.c; path = ../asn.1/NULL.c; sourceTree = "<group>"; };
   9.156 +		438C43962167582400C7425B /* sync_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sync_api.h; path = ../src/sync_api.h; sourceTree = "<group>"; };
   9.157  		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>"; };
   9.158  		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>"; };
   9.159 -		43BA0F451D7964750059172F /* asn1_helper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = asn1_helper.c; path = ../src/asn1_helper.c; sourceTree = "<group>"; };
   9.160 -		43E9BC691DB51A1E00AD2352 /* GroupUpdate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupUpdate.c; path = ../asn.1/GroupUpdate.c; sourceTree = "<group>"; };
   9.161 -		43E9BC7E1DB6720E00AD2352 /* UpdateRequest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = UpdateRequest.c; path = ../asn.1/UpdateRequest.c; sourceTree = "<group>"; };
   9.162 +		43CC349C2276D31A002F77AF /* NegotiationRequest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationRequest.c; path = ../asn.1/NegotiationRequest.c; sourceTree = "<group>"; };
   9.163 +		43CC349D2276D31A002F77AF /* NegotiationRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NegotiationRequest.h; path = ../asn.1/NegotiationRequest.h; sourceTree = "<group>"; };
   9.164 +		43CC34A02276D34B002F77AF /* NegotiationOpen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationOpen.c; path = ../asn.1/NegotiationOpen.c; sourceTree = "<group>"; };
   9.165 +		43CC34A12276D34C002F77AF /* NegotiationOpen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NegotiationOpen.h; path = ../asn.1/NegotiationOpen.h; sourceTree = "<group>"; };
   9.166 +		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>"; };
   9.167  		43F6921C1F164A47009418F5 /* resource_id.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = resource_id.c; path = ../src/resource_id.c; sourceTree = "<group>"; };
   9.168 +		43F73BEB2166269200AB4524 /* PString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PString.c; path = ../asn.1/PString.c; sourceTree = "<group>"; };
   9.169 +		43F73BF1216626E100AB4524 /* Sync_func.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_func.c; path = ../src/Sync_func.c; sourceTree = "<group>"; };
   9.170 +		43F73BF5216627CB00AB4524 /* CommitAccept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAccept.c; path = ../asn.1/CommitAccept.c; sourceTree = "<group>"; };
   9.171 +		43F73BF6216627CC00AB4524 /* TID.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = TID.c; path = ../asn.1/TID.c; sourceTree = "<group>"; };
   9.172 +		43F73BF7216627CC00AB4524 /* KeySync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = KeySync.c; path = ../asn.1/KeySync.c; sourceTree = "<group>"; };
   9.173 +		43F73BF9216627CC00AB4524 /* Rollback.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Rollback.c; path = ../asn.1/Rollback.c; sourceTree = "<group>"; };
   9.174 +		43F73BFB216627CC00AB4524 /* CommitReject.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitReject.c; path = ../asn.1/CommitReject.c; sourceTree = "<group>"; };
   9.175 +		43F73C032166282C00AB4524 /* openpgp_compat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = openpgp_compat.c; path = ../src/openpgp_compat.c; sourceTree = "<group>"; };
   9.176 +		43F73C042166282C00AB4524 /* Sync_event.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_event.c; path = ../src/Sync_event.c; sourceTree = "<group>"; };
   9.177 +		43F73C052166282C00AB4524 /* key_reset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = key_reset.c; path = ../src/key_reset.c; sourceTree = "<group>"; };
   9.178 +		43F73C062166282C00AB4524 /* sync_codec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_codec.c; path = ../src/sync_codec.c; sourceTree = "<group>"; };
   9.179 +		43F73C072166282C00AB4524 /* KeySync_fsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = KeySync_fsm.c; path = ../src/KeySync_fsm.c; sourceTree = "<group>"; };
   9.180 +		43F73C092166282C00AB4524 /* sync_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_api.c; path = ../src/sync_api.c; sourceTree = "<group>"; };
   9.181 +		43F73C0A2166282C00AB4524 /* growing_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = growing_buf.c; path = ../src/growing_buf.c; sourceTree = "<group>"; };
   9.182 +		43F73C13216628CA00AB4524 /* Sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync.c; path = ../asn.1/Sync.c; sourceTree = "<group>"; };
   9.183  		644297BF1BE11C65002BC73B /* pEpTrustWords.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = pEpTrustWords.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
   9.184  		644297C11BE11C65002BC73B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
   9.185  		646788871CEB3D120001F54C /* map_asn1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = map_asn1.c; path = ../src/map_asn1.c; sourceTree = "<group>"; };
   9.186 @@ -251,12 +325,8 @@
   9.187  		646C40B61D510CD700C63EFF /* constraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constraints.h; path = ../asn.1/constraints.h; sourceTree = "<group>"; };
   9.188  		646C40B71D510CD700C63EFF /* der_encoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = der_encoder.c; path = ../asn.1/der_encoder.c; sourceTree = "<group>"; };
   9.189  		646C40B81D510CD700C63EFF /* der_encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = der_encoder.h; path = ../asn.1/der_encoder.h; sourceTree = "<group>"; };
   9.190 -		646C40B91D510CD700C63EFF /* DeviceGroup-Protocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "DeviceGroup-Protocol.c"; path = "../asn.1/DeviceGroup-Protocol.c"; sourceTree = "<group>"; };
   9.191 -		646C40BA1D510CD700C63EFF /* DeviceGroup-Protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "DeviceGroup-Protocol.h"; path = "../asn.1/DeviceGroup-Protocol.h"; sourceTree = "<group>"; };
   9.192  		646C40BB1D510CD700C63EFF /* GroupKeys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupKeys.c; path = ../asn.1/GroupKeys.c; sourceTree = "<group>"; };
   9.193  		646C40BC1D510CD700C63EFF /* GroupKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupKeys.h; path = ../asn.1/GroupKeys.h; sourceTree = "<group>"; };
   9.194 -		646C40BD1D510CD700C63EFF /* HandshakeRequest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HandshakeRequest.c; path = ../asn.1/HandshakeRequest.c; sourceTree = "<group>"; };
   9.195 -		646C40BE1D510CD700C63EFF /* HandshakeRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HandshakeRequest.h; path = ../asn.1/HandshakeRequest.h; sourceTree = "<group>"; };
   9.196  		646C40BF1D510CD700C63EFF /* Hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Hash.c; path = ../asn.1/Hash.c; sourceTree = "<group>"; };
   9.197  		646C40C01D510CD700C63EFF /* Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hash.h; path = ../asn.1/Hash.h; sourceTree = "<group>"; };
   9.198  		646C40C31D510CD700C63EFF /* Hex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Hex.c; path = ../asn.1/Hex.c; sourceTree = "<group>"; };
   9.199 @@ -285,9 +355,6 @@
   9.200  		646C40DA1D510CD800C63EFF /* per_support.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = per_support.h; path = ../asn.1/per_support.h; sourceTree = "<group>"; };
   9.201  		646C40DB1D510CD800C63EFF /* PrintableString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PrintableString.c; path = ../asn.1/PrintableString.c; sourceTree = "<group>"; };
   9.202  		646C40DC1D510CD800C63EFF /* PrintableString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrintableString.h; path = ../asn.1/PrintableString.h; sourceTree = "<group>"; };
   9.203 -		646C40DD1D510CD800C63EFF /* protocols.asn1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = protocols.asn1; path = ../asn.1/protocols.asn1; sourceTree = "<group>"; };
   9.204 -		646C40DE1D510CD800C63EFF /* Sync-Protocols.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "Sync-Protocols.c"; path = "../asn.1/Sync-Protocols.c"; sourceTree = "<group>"; };
   9.205 -		646C40DF1D510CD800C63EFF /* Sync-Protocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Sync-Protocols.h"; path = "../asn.1/Sync-Protocols.h"; sourceTree = "<group>"; };
   9.206  		646C40E01D510CD800C63EFF /* UTF8String.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = UTF8String.c; path = ../asn.1/UTF8String.c; sourceTree = "<group>"; };
   9.207  		646C40E11D510CD800C63EFF /* UTF8String.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UTF8String.h; path = ../asn.1/UTF8String.h; sourceTree = "<group>"; };
   9.208  		646C40E21D510CD800C63EFF /* Version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Version.c; path = ../asn.1/Version.c; sourceTree = "<group>"; };
   9.209 @@ -299,12 +366,6 @@
   9.210  		646C40E81D510CD800C63EFF /* xer_support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xer_support.c; path = ../asn.1/xer_support.c; sourceTree = "<group>"; };
   9.211  		646C40E91D510CD800C63EFF /* xer_support.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xer_support.h; path = ../asn.1/xer_support.h; sourceTree = "<group>"; };
   9.212  		646C413E1D510D2C00C63EFF /* sync_actions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_actions.c; path = ../src/sync_actions.c; sourceTree = "<group>"; };
   9.213 -		646C413F1D510D2C00C63EFF /* sync_driver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_driver.c; path = ../src/sync_driver.c; sourceTree = "<group>"; };
   9.214 -		646C41401D510D2C00C63EFF /* sync_fsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_fsm.c; path = ../src/sync_fsm.c; sourceTree = "<group>"; };
   9.215 -		646C41411D510D2C00C63EFF /* sync_fsm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sync_fsm.h; path = ../src/sync_fsm.h; sourceTree = "<group>"; };
   9.216 -		646C41421D510D2C00C63EFF /* sync_send_actions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_send_actions.c; path = ../src/sync_send_actions.c; sourceTree = "<group>"; };
   9.217 -		646C41431D510D2C00C63EFF /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync.c; path = ../src/sync.c; sourceTree = "<group>"; };
   9.218 -		646C41441D510D2C00C63EFF /* sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sync.h; path = ../src/sync.h; sourceTree = "<group>"; };
   9.219  		646C414C1D510D8800C63EFF /* baseprotocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = baseprotocol.c; path = ../src/baseprotocol.c; sourceTree = "<group>"; };
   9.220  		646C414D1D510D8800C63EFF /* baseprotocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = baseprotocol.h; path = ../src/baseprotocol.h; sourceTree = "<group>"; };
   9.221  		64796A3F1B455AA5004B1C24 /* libpEpEngine.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpEpEngine.a; sourceTree = BUILT_PRODUCTS_DIR; };
   9.222 @@ -377,12 +438,50 @@
   9.223  /* End PBXFrameworksBuildPhase section */
   9.224  
   9.225  /* Begin PBXGroup section */
   9.226 +		43D47A89225CC60600E97C5B /* Resources-iPad */ = {
   9.227 +			isa = PBXGroup;
   9.228 +			children = (
   9.229 +			);
   9.230 +			name = "Resources-iPad";
   9.231 +			sourceTree = "<group>";
   9.232 +		};
   9.233  		6406CE811CE382F400C14D77 /* asn.1 */ = {
   9.234  			isa = PBXGroup;
   9.235  			children = (
   9.236 -				43E9BC7E1DB6720E00AD2352 /* UpdateRequest.c */,
   9.237 -				43E9BC691DB51A1E00AD2352 /* GroupUpdate.c */,
   9.238 -				4354FF681D6EE1A70033069C /* NULL.c */,
   9.239 +				43CC34A02276D34B002F77AF /* NegotiationOpen.c */,
   9.240 +				43CC34A12276D34C002F77AF /* NegotiationOpen.h */,
   9.241 +				43CC349C2276D31A002F77AF /* NegotiationRequest.c */,
   9.242 +				43CC349D2276D31A002F77AF /* NegotiationRequest.h */,
   9.243 +				431F04A12273235300CCE960 /* GroupTrustThisKey.c */,
   9.244 +				431F049C2273235300CCE960 /* GroupTrustThisKey.h */,
   9.245 +				431F04A9227323EE00CCE960 /* OwnKeys.c */,
   9.246 +				431F04A8227323EE00CCE960 /* OwnKeys.h */,
   9.247 +				431F048F2273227900CCE960 /* OwnKeysFirst.c */,
   9.248 +				431F048E2273227900CCE960 /* OwnKeysFirst.h */,
   9.249 +				431F04A5227323A400CCE960 /* OwnKeysSecond.c */,
   9.250 +				431F04A4227323A400CCE960 /* OwnKeysSecond.h */,
   9.251 +				431F0493227322EF00CCE960 /* CommitAcceptFirst.c */,
   9.252 +				431F0492227322EF00CCE960 /* CommitAcceptFirst.h */,
   9.253 +				431F048B2273223600CCE960 /* CommitAcceptSecond.c */,
   9.254 +				431F04862273223600CCE960 /* CommitAcceptSecond.h */,
   9.255 +				1521CEEE225C9AEE00FD2AA2 /* CommitAccept.h */,
   9.256 +				1521CEE9225C9AED00FD2AA2 /* CommitAcceptForGroup.c */,
   9.257 +				1521CEEC225C9AEE00FD2AA2 /* CommitAcceptForGroup.h */,
   9.258 +				1521CEF2225C9AEE00FD2AA2 /* CommitReject.h */,
   9.259 +				1521CEF1225C9AEE00FD2AA2 /* KeySync.h */,
   9.260 +				1521CEF0225C9AEE00FD2AA2 /* pdu_collection.c */,
   9.261 +				1521CEEA225C9AEE00FD2AA2 /* PString.h */,
   9.262 +				1521CEEB225C9AEE00FD2AA2 /* Rollback.h */,
   9.263 +				1521CEF4225C9AEE00FD2AA2 /* sync.asn1 */,
   9.264 +				1521CEF3225C9AEE00FD2AA2 /* Sync.h */,
   9.265 +				1521CEF5225C9AEF00FD2AA2 /* TID.h */,
   9.266 +				43F73C13216628CA00AB4524 /* Sync.c */,
   9.267 +				43F73BF5216627CB00AB4524 /* CommitAccept.c */,
   9.268 +				43F73BFB216627CC00AB4524 /* CommitReject.c */,
   9.269 +				43F73BF7216627CC00AB4524 /* KeySync.c */,
   9.270 +				43F73BF9216627CC00AB4524 /* Rollback.c */,
   9.271 +				43F73BF6216627CC00AB4524 /* TID.c */,
   9.272 +				43F73BEB2166269200AB4524 /* PString.c */,
   9.273  				646C40951D510CD700C63EFF /* asn_application.h */,
   9.274  				646C40961D510CD700C63EFF /* asn_codecs_prim.c */,
   9.275  				646C40971D510CD700C63EFF /* asn_codecs_prim.h */,
   9.276 @@ -419,12 +518,8 @@
   9.277  				646C40B61D510CD700C63EFF /* constraints.h */,
   9.278  				646C40B71D510CD700C63EFF /* der_encoder.c */,
   9.279  				646C40B81D510CD700C63EFF /* der_encoder.h */,
   9.280 -				646C40B91D510CD700C63EFF /* DeviceGroup-Protocol.c */,
   9.281 -				646C40BA1D510CD700C63EFF /* DeviceGroup-Protocol.h */,
   9.282  				646C40BB1D510CD700C63EFF /* GroupKeys.c */,
   9.283  				646C40BC1D510CD700C63EFF /* GroupKeys.h */,
   9.284 -				646C40BD1D510CD700C63EFF /* HandshakeRequest.c */,
   9.285 -				646C40BE1D510CD700C63EFF /* HandshakeRequest.h */,
   9.286  				646C40BF1D510CD700C63EFF /* Hash.c */,
   9.287  				646C40C01D510CD700C63EFF /* Hash.h */,
   9.288  				646C40C31D510CD700C63EFF /* Hex.c */,
   9.289 @@ -453,9 +548,6 @@
   9.290  				646C40DA1D510CD800C63EFF /* per_support.h */,
   9.291  				646C40DB1D510CD800C63EFF /* PrintableString.c */,
   9.292  				646C40DC1D510CD800C63EFF /* PrintableString.h */,
   9.293 -				646C40DD1D510CD800C63EFF /* protocols.asn1 */,
   9.294 -				646C40DE1D510CD800C63EFF /* Sync-Protocols.c */,
   9.295 -				646C40DF1D510CD800C63EFF /* Sync-Protocols.h */,
   9.296  				646C40E01D510CD800C63EFF /* UTF8String.c */,
   9.297  				646C40E11D510CD800C63EFF /* UTF8String.h */,
   9.298  				646C40E21D510CD800C63EFF /* Version.c */,
   9.299 @@ -499,6 +591,7 @@
   9.300  		64796A361B455AA5004B1C24 = {
   9.301  			isa = PBXGroup;
   9.302  			children = (
   9.303 +				43D47A89225CC60600E97C5B /* Resources-iPad */,
   9.304  				64951A1B1BE0FCD800B10E71 /* system.db */,
   9.305  				64DA24121B832EBA000BEE80 /* libetpan.xcodeproj */,
   9.306  				64DA240C1B832EA0000BEE80 /* netpgp.xcodeproj */,
   9.307 @@ -507,6 +600,7 @@
   9.308  				64A8264B1B455C5600EECAF0 /* srcref */,
   9.309  				644297C01BE11C65002BC73B /* pEpTrustWords */,
   9.310  				64796A401B455AA5004B1C24 /* Products */,
   9.311 +				43D47A8A225CC60600E97C5B /* pEpTrustWords-Info.plist */,
   9.312  			);
   9.313  			sourceTree = "<group>";
   9.314  		};
   9.315 @@ -526,23 +620,25 @@
   9.316  				C46EBAEC216E445F0042A6A3 /* base64.h */,
   9.317  				438C43B42167752C00C7425B /* labeled_int_list.c */,
   9.318  				438C43AF2167752C00C7425B /* labeled_int_list.h */,
   9.319 +				438C43962167582400C7425B /* sync_api.h */,
   9.320 +				43F73C0A2166282C00AB4524 /* growing_buf.c */,
   9.321 +				431F04B222733A7E00CCE960 /* key_reset.h */,
   9.322 +				43F73C052166282C00AB4524 /* key_reset.c */,
   9.323 +				43F73C072166282C00AB4524 /* KeySync_fsm.c */,
   9.324 +				43F73C032166282C00AB4524 /* openpgp_compat.c */,
   9.325 +				43F73C092166282C00AB4524 /* sync_api.c */,
   9.326 +				43F73C062166282C00AB4524 /* sync_codec.c */,
   9.327 +				43F73C042166282C00AB4524 /* Sync_event.c */,
   9.328 +				43F73BF1216626E100AB4524 /* Sync_func.c */,
   9.329  				4337082D203C075A004E6547 /* sqlite3.c */,
   9.330  				43370832203C075A004E6547 /* sqlite3.h */,
   9.331  				430BCC472015EE800077E998 /* pEp_string.c */,
   9.332  				430BCC462015EE800077E998 /* pEp_string.h */,
   9.333  				43F6921C1F164A47009418F5 /* resource_id.c */,
   9.334 -				43BA0F451D7964750059172F /* asn1_helper.c */,
   9.335  				4354FF641D6EDF300033069C /* sync_impl.c */,
   9.336  				646C414C1D510D8800C63EFF /* baseprotocol.c */,
   9.337  				646C414D1D510D8800C63EFF /* baseprotocol.h */,
   9.338  				646C413E1D510D2C00C63EFF /* sync_actions.c */,
   9.339 -				646C413F1D510D2C00C63EFF /* sync_driver.c */,
   9.340 -				646C41401D510D2C00C63EFF /* sync_fsm.c */,
   9.341 -				646C41411D510D2C00C63EFF /* sync_fsm.h */,
   9.342 -				646C41421D510D2C00C63EFF /* sync_send_actions.c */,
   9.343 -				646C41431D510D2C00C63EFF /* sync.c */,
   9.344 -				646C41441D510D2C00C63EFF /* sync.h */,
   9.345 -				4346F86A1ECB38E700381CBE /* sync_app.h */,
   9.346  				646788871CEB3D120001F54C /* map_asn1.c */,
   9.347  				646788881CEB3D120001F54C /* map_asn1.h */,
   9.348  				430D258A1C9ED75A00B94535 /* blacklist.c */,
   9.349 @@ -598,29 +694,36 @@
   9.350  			buildActionMask = 2147483647;
   9.351  			files = (
   9.352  				646C41031D510CD800C63EFF /* constr_SEQUENCE_OF.h in Headers */,
   9.353 +				1521CEFB225C9AEF00FD2AA2 /* CommitAccept.h in Headers */,
   9.354  				646C40ED1D510CD800C63EFF /* asn_codecs.h in Headers */,
   9.355  				646C41371D510CD800C63EFF /* Version.h in Headers */,
   9.356 +				1521CEF8225C9AEF00FD2AA2 /* Rollback.h in Headers */,
   9.357  				646C412F1D510CD800C63EFF /* per_support.h in Headers */,
   9.358  				646C41111D510CD800C63EFF /* GroupKeys.h in Headers */,
   9.359  				646C40F21D510CD800C63EFF /* asn_SET_OF.h in Headers */,
   9.360  				646C41311D510CD800C63EFF /* PrintableString.h in Headers */,
   9.361 +				431F048C2273223600CCE960 /* CommitAcceptSecond.h in Headers */,
   9.362  				646C40F51D510CD800C63EFF /* Beacon.h in Headers */,
   9.363  				438C43B52167752C00C7425B /* labeled_int_list.h in Headers */,
   9.364  				646C40F71D510CD800C63EFF /* ber_decoder.h in Headers */,
   9.365  				646C41351D510CD800C63EFF /* UTF8String.h in Headers */,
   9.366 +				43CC34A32276D34C002F77AF /* NegotiationOpen.h in Headers */,
   9.367  				646C40EC1D510CD800C63EFF /* asn_codecs_prim.h in Headers */,
   9.368 +				438C439B2167582500C7425B /* sync_api.h in Headers */,
   9.369  				646C40EE1D510CD800C63EFF /* asn_internal.h in Headers */,
   9.370  				646C413B1D510CD800C63EFF /* xer_encoder.h in Headers */,
   9.371 +				431F04A6227323A400CCE960 /* OwnKeysSecond.h in Headers */,
   9.372  				646C40F01D510CD800C63EFF /* asn_SEQUENCE_OF.h in Headers */,
   9.373 +				43CC349F2276D31A002F77AF /* NegotiationRequest.h in Headers */,
   9.374  				646C40FD1D510CD800C63EFF /* BIT_STRING.h in Headers */,
   9.375  				646C411F1D510CD800C63EFF /* INTEGER.h in Headers */,
   9.376  				646C411D1D510CD800C63EFF /* IdentityList.h in Headers */,
   9.377 -				646C41331D510CD800C63EFF /* Sync-Protocols.h in Headers */,
   9.378 +				1521CEFE225C9AEF00FD2AA2 /* KeySync.h in Headers */,
   9.379  				646C41011D510CD800C63EFF /* constr_CHOICE.h in Headers */,
   9.380  				646C40FB1D510CD800C63EFF /* ber_tlv_tag.h in Headers */,
   9.381  				646C414F1D510D8800C63EFF /* baseprotocol.h in Headers */,
   9.382  				6467888D1CEB3D120001F54C /* map_asn1.h in Headers */,
   9.383 -				646C41131D510CD800C63EFF /* HandshakeRequest.h in Headers */,
   9.384 +				1521CEF9225C9AEF00FD2AA2 /* CommitAcceptForGroup.h in Headers */,
   9.385  				646C40F31D510CD800C63EFF /* asn_system.h in Headers */,
   9.386  				43370834203C075A004E6547 /* sqlite3.h in Headers */,
   9.387  				646C410B1D510CD800C63EFF /* constraints.h in Headers */,
   9.388 @@ -629,26 +732,32 @@
   9.389  				646C41391D510CD800C63EFF /* xer_decoder.h in Headers */,
   9.390  				646C40EA1D510CD800C63EFF /* asn_application.h in Headers */,
   9.391  				646C41211D510CD800C63EFF /* ISO639-1.h in Headers */,
   9.392 +				431F04B722733A7E00CCE960 /* key_reset.h in Headers */,
   9.393  				646C412D1D510CD800C63EFF /* per_opentype.h in Headers */,
   9.394  				646C413D1D510CD800C63EFF /* xer_support.h in Headers */,
   9.395  				646C41191D510CD800C63EFF /* Hex.h in Headers */,
   9.396 +				431F04902273227900CCE960 /* OwnKeysFirst.h in Headers */,
   9.397  				646C41051D510CD800C63EFF /* constr_SEQUENCE.h in Headers */,
   9.398 +				1521CF01225C9AEF00FD2AA2 /* TID.h in Headers */,
   9.399  				646C41151D510CD800C63EFF /* Hash.h in Headers */,
   9.400 -				646C410F1D510CD800C63EFF /* DeviceGroup-Protocol.h in Headers */,
   9.401  				646C40FF1D510CD800C63EFF /* BOOLEAN.h in Headers */,
   9.402 -				646C41481D510D2C00C63EFF /* sync_fsm.h in Headers */,
   9.403  				64A8268C1B455D9D00EECAF0 /* pEpEngine.h in Headers */,
   9.404 +				431F04AA227323EE00CCE960 /* OwnKeys.h in Headers */,
   9.405  				646C41091D510CD800C63EFF /* constr_TYPE.h in Headers */,
   9.406 +				431F0494227322EF00CCE960 /* CommitAcceptFirst.h in Headers */,
   9.407  				430BCC482015EE800077E998 /* pEp_string.h in Headers */,
   9.408 +				1521CEFF225C9AEF00FD2AA2 /* CommitReject.h in Headers */,
   9.409  				646C410D1D510CD800C63EFF /* der_encoder.h in Headers */,
   9.410  				646C41231D510CD800C63EFF /* NativeEnumerated.h in Headers */,
   9.411  				646C41071D510CD800C63EFF /* constr_SET_OF.h in Headers */,
   9.412 -				646C414B1D510D2C00C63EFF /* sync.h in Headers */,
   9.413 +				1521CEF7225C9AEF00FD2AA2 /* PString.h in Headers */,
   9.414 +				1521CF00225C9AEF00FD2AA2 /* Sync.h in Headers */,
   9.415  				C46EBAEE216E445F0042A6A3 /* base64.h in Headers */,
   9.416  				646C411B1D510CD800C63EFF /* Identity.h in Headers */,
   9.417  				646C412B1D510CD800C63EFF /* per_encoder.h in Headers */,
   9.418  				646C40F91D510CD800C63EFF /* ber_tlv_length.h in Headers */,
   9.419  				646C41291D510CD800C63EFF /* per_decoder.h in Headers */,
   9.420 +				431F04A22273235300CCE960 /* GroupTrustThisKey.h in Headers */,
   9.421  			);
   9.422  			runOnlyForDeploymentPostprocessing = 0;
   9.423  		};
   9.424 @@ -677,7 +786,7 @@
   9.425  			isa = PBXNativeTarget;
   9.426  			buildConfigurationList = 64796A531B455AA5004B1C24 /* Build configuration list for PBXNativeTarget "pEpEngine" */;
   9.427  			buildPhases = (
   9.428 -				64BDD59B1B7A2E1B00AC43AE /* Run Script */,
   9.429 +				43D47B08225DEBD600E97C5B /* ShellScript */,
   9.430  				64796A3B1B455AA5004B1C24 /* Sources */,
   9.431  				64796A3C1B455AA5004B1C24 /* Frameworks */,
   9.432  				64796A3D1B455AA5004B1C24 /* CopyFiles */,
   9.433 @@ -686,6 +795,7 @@
   9.434  			buildRules = (
   9.435  			);
   9.436  			dependencies = (
   9.437 +				43D47AA1225CC82400E97C5B /* PBXTargetDependency */,
   9.438  				645922541B8BD53F00A5AF93 /* PBXTargetDependency */,
   9.439  				64289E3F1B8B638800FC617B /* PBXTargetDependency */,
   9.440  			);
   9.441 @@ -701,7 +811,7 @@
   9.442  			isa = PBXProject;
   9.443  			attributes = {
   9.444  				LastUpgradeCheck = 0940;
   9.445 -				ORGANIZATIONNAME = "Edouard Tisserant";
   9.446 +				ORGANIZATIONNAME = "p≡p Security S.A.";
   9.447  				TargetAttributes = {
   9.448  					644297BE1BE11C65002BC73B = {
   9.449  						CreatedOnToolsVersion = 7.1;
   9.450 @@ -716,6 +826,7 @@
   9.451  			developmentRegion = English;
   9.452  			hasScannedForEncodings = 0;
   9.453  			knownRegions = (
   9.454 +				English,
   9.455  				en,
   9.456  			);
   9.457  			mainGroup = 64796A361B455AA5004B1C24;
   9.458 @@ -782,6 +893,25 @@
   9.459  /* End PBXResourcesBuildPhase section */
   9.460  
   9.461  /* Begin PBXShellScriptBuildPhase section */
   9.462 +		43D47B08225DEBD600E97C5B /* ShellScript */ = {
   9.463 +			isa = PBXShellScriptBuildPhase;
   9.464 +			buildActionMask = 2147483647;
   9.465 +			files = (
   9.466 +			);
   9.467 +			inputFileListPaths = (
   9.468 +			);
   9.469 +			inputPaths = (
   9.470 +			);
   9.471 +			outputFileListPaths = (
   9.472 +				"$(SRCROOT)/generated-files-asn1.txt",
   9.473 +				"$(SRCROOT)/generated-files-sync.txt",
   9.474 +			);
   9.475 +			outputPaths = (
   9.476 +			);
   9.477 +			runOnlyForDeploymentPostprocessing = 0;
   9.478 +			shellPath = /bin/bash;
   9.479 +			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";
   9.480 +		};
   9.481  		644297C61BE11D00002BC73B /* ShellScript */ = {
   9.482  			isa = PBXShellScriptBuildPhase;
   9.483  			buildActionMask = 2147483647;
   9.484 @@ -793,21 +923,7 @@
   9.485  			);
   9.486  			runOnlyForDeploymentPostprocessing = 0;
   9.487  			shellPath = /bin/sh;
   9.488 -			shellScript = "make -C \"$SRCROOT/../db\" system.db\n";
   9.489 -		};
   9.490 -		64BDD59B1B7A2E1B00AC43AE /* Run Script */ = {
   9.491 -			isa = PBXShellScriptBuildPhase;
   9.492 -			buildActionMask = 2147483647;
   9.493 -			files = (
   9.494 -			);
   9.495 -			inputPaths = (
   9.496 -			);
   9.497 -			name = "Run Script";
   9.498 -			outputPaths = (
   9.499 -			);
   9.500 -			runOnlyForDeploymentPostprocessing = 0;
   9.501 -			shellPath = /bin/sh;
   9.502 -			shellScript = "bash -l -c \"make -C ../asn.1 generate\"\nbash -l -c \"make -C ../asn.1\"\nbash -l -c \"LC_ALL=en_US.UTF-8 YML_PATH=$HOME/yml2 make -C ../sync\"\n";
   9.503 +			shellScript = "cd \"$SRCROOT/..\"\n\nbash -l -c \"make db\"\n";
   9.504  		};
   9.505  /* End PBXShellScriptBuildPhase section */
   9.506  
   9.507 @@ -824,10 +940,15 @@
   9.508  			buildActionMask = 2147483647;
   9.509  			files = (
   9.510  				64A826871B455D0800EECAF0 /* stringpair.c in Sources */,
   9.511 -				43E9BC6A1DB51A1E00AD2352 /* GroupUpdate.c in Sources */,
   9.512 +				43F73C0E2166282C00AB4524 /* sync_codec.c in Sources */,
   9.513 +				1521CEF6225C9AEF00FD2AA2 /* CommitAcceptForGroup.c in Sources */,
   9.514 +				431F04912273227900CCE960 /* OwnKeysFirst.c in Sources */,
   9.515 +				431F04A32273235300CCE960 /* GroupTrustThisKey.c in Sources */,
   9.516  				646C41341D510CD800C63EFF /* UTF8String.c in Sources */,
   9.517  				64A826831B455D0800EECAF0 /* platform_unix.c in Sources */,
   9.518  				646C40F81D510CD800C63EFF /* ber_tlv_length.c in Sources */,
   9.519 +				43F73BF2216626E100AB4524 /* Sync_func.c in Sources */,
   9.520 +				431F04A7227323A400CCE960 /* OwnKeysSecond.c in Sources */,
   9.521  				646C411C1D510CD800C63EFF /* IdentityList.c in Sources */,
   9.522  				646C41301D510CD800C63EFF /* PrintableString.c in Sources */,
   9.523  				64A8267B1B455D0800EECAF0 /* etpan_mime.c in Sources */,
   9.524 @@ -835,74 +956,88 @@
   9.525  				438C43B62167752C00C7425B /* labeled_int_list.c in Sources */,
   9.526  				646C41261D510CD800C63EFF /* OCTET_STRING.c in Sources */,
   9.527  				646C41141D510CD800C63EFF /* Hash.c in Sources */,
   9.528 -				646C410E1D510CD800C63EFF /* DeviceGroup-Protocol.c in Sources */,
   9.529 +				43CC349E2276D31A002F77AF /* NegotiationRequest.c in Sources */,
   9.530 +				43F73BF02166269200AB4524 /* PString.c in Sources */,
   9.531  				64A826861B455D0800EECAF0 /* stringlist.c in Sources */,
   9.532  				4354FF651D6EDF300033069C /* sync_impl.c in Sources */,
   9.533  				64A8267E1B455D0800EECAF0 /* message_api.c in Sources */,
   9.534 -				43E9BC7F1DB6720E00AD2352 /* UpdateRequest.c in Sources */,
   9.535  				646C41361D510CD800C63EFF /* Version.c in Sources */,
   9.536  				646C41081D510CD800C63EFF /* constr_TYPE.c in Sources */,
   9.537  				646C40FE1D510CD800C63EFF /* BOOLEAN.c in Sources */,
   9.538  				646C41001D510CD800C63EFF /* constr_CHOICE.c in Sources */,
   9.539 -				646C41121D510CD800C63EFF /* HandshakeRequest.c in Sources */,
   9.540 -				646C41471D510D2C00C63EFF /* sync_fsm.c in Sources */,
   9.541  				64A826821B455D0800EECAF0 /* pgp_netpgp.c in Sources */,
   9.542  				646C41101D510CD800C63EFF /* GroupKeys.c in Sources */,
   9.543  				646C40EF1D510CD800C63EFF /* asn_SEQUENCE_OF.c in Sources */,
   9.544  				64A826891B455D0800EECAF0 /* trans_auto.c in Sources */,
   9.545  				646C410C1D510CD800C63EFF /* der_encoder.c in Sources */,
   9.546 +				43F73C112166282C00AB4524 /* sync_api.c in Sources */,
   9.547  				646C41381D510CD800C63EFF /* xer_decoder.c in Sources */,
   9.548 +				43F73BFE216627CC00AB4524 /* KeySync.c in Sources */,
   9.549  				646C41181D510CD800C63EFF /* Hex.c in Sources */,
   9.550  				64A8267D1B455D0800EECAF0 /* keymanagement.c in Sources */,
   9.551  				646C40EB1D510CD800C63EFF /* asn_codecs_prim.c in Sources */,
   9.552  				646C41451D510D2C00C63EFF /* sync_actions.c in Sources */,
   9.553  				646C40F61D510CD800C63EFF /* ber_decoder.c in Sources */,
   9.554  				646C40F11D510CD800C63EFF /* asn_SET_OF.c in Sources */,
   9.555 -				4354FF691D6EE1A70033069C /* NULL.c in Sources */,
   9.556  				646C413A1D510CD800C63EFF /* xer_encoder.c in Sources */,
   9.557 +				431F04AB227323EE00CCE960 /* OwnKeys.c in Sources */,
   9.558 +				43F73BFD216627CC00AB4524 /* TID.c in Sources */,
   9.559  				646C41021D510CD800C63EFF /* constr_SEQUENCE_OF.c in Sources */,
   9.560  				646C410A1D510CD800C63EFF /* constraints.c in Sources */,
   9.561 -				646C41461D510D2C00C63EFF /* sync_driver.c in Sources */,
   9.562  				64A8267C1B455D0800EECAF0 /* identity_list.c in Sources */,
   9.563  				646C40FC1D510CD800C63EFF /* BIT_STRING.c in Sources */,
   9.564  				646C40F41D510CD800C63EFF /* Beacon.c in Sources */,
   9.565 +				43F73C0D2166282C00AB4524 /* key_reset.c in Sources */,
   9.566 +				43F73BFC216627CC00AB4524 /* CommitAccept.c in Sources */,
   9.567  				646C411E1D510CD800C63EFF /* INTEGER.c in Sources */,
   9.568  				646C413C1D510CD800C63EFF /* xer_support.c in Sources */,
   9.569  				64A8268A1B455D0800EECAF0 /* transport.c in Sources */,
   9.570 -				646C41491D510D2C00C63EFF /* sync_send_actions.c in Sources */,
   9.571  				646C41201D510CD800C63EFF /* ISO639-1.c in Sources */,
   9.572 -				646C414A1D510D2C00C63EFF /* sync.c in Sources */,
   9.573  				64A826791B455D0800EECAF0 /* cryptotech.c in Sources */,
   9.574 -				43BA0F461D7964750059172F /* asn1_helper.c in Sources */,
   9.575 +				43F73C0F2166282C00AB4524 /* KeySync_fsm.c in Sources */,
   9.576  				646C412A1D510CD800C63EFF /* per_encoder.c in Sources */,
   9.577  				646C412E1D510CD800C63EFF /* per_support.c in Sources */,
   9.578 +				43F73C0C2166282C00AB4524 /* Sync_event.c in Sources */,
   9.579  				64A826781B455D0800EECAF0 /* bloblist.c in Sources */,
   9.580  				C46EBAED216E445F0042A6A3 /* base64.c in Sources */,
   9.581  				430BCC492015EE800077E998 /* pEp_string.c in Sources */,
   9.582 +				43F73C00216627CC00AB4524 /* Rollback.c in Sources */,
   9.583  				646C41041D510CD800C63EFF /* constr_SEQUENCE.c in Sources */,
   9.584 +				43F73C14216628CA00AB4524 /* Sync.c in Sources */,
   9.585 +				43F73C0B2166282C00AB4524 /* openpgp_compat.c in Sources */,
   9.586  				43370833203C075A004E6547 /* sqlite3.c in Sources */,
   9.587 +				43F73C02216627CC00AB4524 /* CommitReject.c in Sources */,
   9.588  				64A826881B455D0800EECAF0 /* timestamp.c in Sources */,
   9.589  				646C41221D510CD800C63EFF /* NativeEnumerated.c in Sources */,
   9.590  				43F6921D1F164A47009418F5 /* resource_id.c in Sources */,
   9.591  				430D258B1C9ED75A00B94535 /* blacklist.c in Sources */,
   9.592 +				431F0495227322EF00CCE960 /* CommitAcceptFirst.c in Sources */,
   9.593  				646C414E1D510D8800C63EFF /* baseprotocol.c in Sources */,
   9.594  				6467888C1CEB3D120001F54C /* map_asn1.c in Sources */,
   9.595  				646C40FA1D510CD800C63EFF /* ber_tlv_tag.c in Sources */,
   9.596  				646C41241D510CD800C63EFF /* NativeInteger.c in Sources */,
   9.597 +				1521CEFD225C9AEF00FD2AA2 /* pdu_collection.c in Sources */,
   9.598  				646C41061D510CD800C63EFF /* constr_SET_OF.c in Sources */,
   9.599 +				43F73C122166282C00AB4524 /* growing_buf.c in Sources */,
   9.600  				646C412C1D510CD800C63EFF /* per_opentype.c in Sources */,
   9.601  				646C41281D510CD800C63EFF /* per_decoder.c in Sources */,
   9.602  				64A826801B455D0800EECAF0 /* mime.c in Sources */,
   9.603 +				431F048D2273223600CCE960 /* CommitAcceptSecond.c in Sources */,
   9.604  				64A8267F1B455D0800EECAF0 /* message.c in Sources */,
   9.605 +				43CC34A22276D34C002F77AF /* NegotiationOpen.c in Sources */,
   9.606  				646C411A1D510CD800C63EFF /* Identity.c in Sources */,
   9.607  				64A826811B455D0800EECAF0 /* pEpEngine.c in Sources */,
   9.608 -				646C41321D510CD800C63EFF /* Sync-Protocols.c in Sources */,
   9.609  			);
   9.610  			runOnlyForDeploymentPostprocessing = 0;
   9.611  		};
   9.612  /* End PBXSourcesBuildPhase section */
   9.613  
   9.614  /* Begin PBXTargetDependency section */
   9.615 +		43D47AA1225CC82400E97C5B /* PBXTargetDependency */ = {
   9.616 +			isa = PBXTargetDependency;
   9.617 +			target = 644297BE1BE11C65002BC73B /* pEpTrustWords */;
   9.618 +			targetProxy = 43D47AA0225CC82400E97C5B /* PBXContainerItemProxy */;
   9.619 +		};
   9.620  		64289E3F1B8B638800FC617B /* PBXTargetDependency */ = {
   9.621  			isa = PBXTargetDependency;
   9.622  			name = "libetpan ios";
   9.623 @@ -990,7 +1125,7 @@
   9.624  					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
   9.625  					"$(SRCROOT)/../asn.1/",
   9.626  				);
   9.627 -				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
   9.628 +				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
   9.629  				MTL_ENABLE_DEBUG_INFO = YES;
   9.630  				ONLY_ACTIVE_ARCH = YES;
   9.631  				OTHER_CFLAGS = "-DSQLITE3_FROM_OS";
   9.632 @@ -1047,7 +1182,7 @@
   9.633  					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
   9.634  					"$(SRCROOT)/../asn.1/",
   9.635  				);
   9.636 -				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
   9.637 +				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
   9.638  				MTL_ENABLE_DEBUG_INFO = NO;
   9.639  				ONLY_ACTIVE_ARCH = NO;
   9.640  				OTHER_CFLAGS = "-DSQLITE3_FROM_OS";
   9.641 @@ -1071,7 +1206,15 @@
   9.642  				OTHER_LDFLAGS = "-ObjC";
   9.643  				PRODUCT_NAME = "$(TARGET_NAME)";
   9.644  				SKIP_INSTALL = YES;
   9.645 -				USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../src $(PROJECT_DIR) $(PROJECT_DIR)/../../netpgp-et/include/ $(PROJECT_DIR)/../../netpgp-et/src/ $(PROJECT_DIR)/../../OpenSSL-for-iPhone/include $(PROJECT_DIR)/../asn.1/ $(inherited)";
   9.646 +				USER_HEADER_SEARCH_PATHS = (
   9.647 +					"$(PROJECT_DIR)/../src",
   9.648 +					"$(PROJECT_DIR)",
   9.649 +					"$(PROJECT_DIR)/../../netpgp-et/include/",
   9.650 +					"$(PROJECT_DIR)/../../netpgp-et/src/",
   9.651 +					"$(PROJECT_DIR)/../../OpenSSL-for-iPhone/include",
   9.652 +					"$(PROJECT_DIR)/../asn.1/",
   9.653 +					"$(inherited)",
   9.654 +				);
   9.655  			};
   9.656  			name = Debug;
   9.657  		};
   9.658 @@ -1088,7 +1231,15 @@
   9.659  				OTHER_LDFLAGS = "-ObjC";
   9.660  				PRODUCT_NAME = "$(TARGET_NAME)";
   9.661  				SKIP_INSTALL = YES;
   9.662 -				USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../src $(PROJECT_DIR) $(PROJECT_DIR)/../../netpgp-et/include/ $(PROJECT_DIR)/../../netpgp-et/src/ $(PROJECT_DIR)/../../OpenSSL-for-iPhone/include $(PROJECT_DIR)/../asn.1/ $(inherited)";
   9.663 +				USER_HEADER_SEARCH_PATHS = (
   9.664 +					"$(PROJECT_DIR)/../src",
   9.665 +					"$(PROJECT_DIR)",
   9.666 +					"$(PROJECT_DIR)/../../netpgp-et/include/",
   9.667 +					"$(PROJECT_DIR)/../../netpgp-et/src/",
   9.668 +					"$(PROJECT_DIR)/../../OpenSSL-for-iPhone/include",
   9.669 +					"$(PROJECT_DIR)/../asn.1/",
   9.670 +					"$(inherited)",
   9.671 +				);
   9.672  			};
   9.673  			name = Release;
   9.674  		};
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/build-mac/pEpTrustWords-Info.plist	Fri May 17 17:30:57 2019 +0200
    10.3 @@ -0,0 +1,28 @@
    10.4 +<?xml version="1.0" encoding="UTF-8"?>
    10.5 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    10.6 +<plist version="1.0">
    10.7 +<dict>
    10.8 +	<key>CFBundleDevelopmentRegion</key>
    10.9 +	<string>en</string>
   10.10 +	<key>CFBundlePackageType</key>
   10.11 +	<string>BNDL</string>
   10.12 +	<key>CFBundleIdentifier</key>
   10.13 +	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
   10.14 +	<key>CFBundleInfoDictionaryVersion</key>
   10.15 +	<string>6.0</string>
   10.16 +	<key>CFBundleName</key>
   10.17 +	<string>$(PRODUCT_NAME)</string>
   10.18 +	<key>CFBundlePackageType</key>
   10.19 +	<string>BNDL</string>
   10.20 +	<key>CFBundleShortVersionString</key>
   10.21 +	<string>1.0</string>
   10.22 +	<key>CFBundleSignature</key>
   10.23 +	<string>????</string>
   10.24 +	<key>CFBundleVersion</key>
   10.25 +	<string>1</string>
   10.26 +	<key>NSHumanReadableCopyright</key>
   10.27 +	<string>Copyright © 2015 Edouard Tisserant. All rights reserved.</string>
   10.28 +	<key>NSPrincipalClass</key>
   10.29 +	<string></string>
   10.30 +</dict>
   10.31 +</plist>
    11.1 --- a/build-windows/libpEpasn1/libpEpasn1.vcxproj	Thu Mar 28 15:40:45 2019 +0100
    11.2 +++ b/build-windows/libpEpasn1/libpEpasn1.vcxproj	Fri May 17 17:30:57 2019 +0200
    11.3 @@ -143,105 +143,10 @@
    11.4      <Text Include="ReadMe.txt" />
    11.5    </ItemGroup>
    11.6    <ItemGroup>
    11.7 -    <ClInclude Include="..\..\asn.1\asn_application.h" />
    11.8 -    <ClInclude Include="..\..\asn.1\asn_codecs.h" />
    11.9 -    <ClInclude Include="..\..\asn.1\asn_codecs_prim.h" />
   11.10 -    <ClInclude Include="..\..\asn.1\asn_internal.h" />
   11.11 -    <ClInclude Include="..\..\asn.1\asn_SEQUENCE_OF.h" />
   11.12 -    <ClInclude Include="..\..\asn.1\asn_SET_OF.h" />
   11.13 -    <ClInclude Include="..\..\asn.1\asn_system.h" />
   11.14 -    <ClInclude Include="..\..\asn.1\Beacon.h" />
   11.15 -    <ClInclude Include="..\..\asn.1\ber_decoder.h" />
   11.16 -    <ClInclude Include="..\..\asn.1\ber_tlv_length.h" />
   11.17 -    <ClInclude Include="..\..\asn.1\ber_tlv_tag.h" />
   11.18 -    <ClInclude Include="..\..\asn.1\BIT_STRING.h" />
   11.19 -    <ClInclude Include="..\..\asn.1\BOOLEAN.h" />
   11.20 -    <ClInclude Include="..\..\asn.1\CommitAccept.h" />
   11.21 -    <ClInclude Include="..\..\asn.1\CommitReject.h" />
   11.22 -    <ClInclude Include="..\..\asn.1\constraints.h" />
   11.23 -    <ClInclude Include="..\..\asn.1\constr_CHOICE.h" />
   11.24 -    <ClInclude Include="..\..\asn.1\constr_SEQUENCE.h" />
   11.25 -    <ClInclude Include="..\..\asn.1\constr_SEQUENCE_OF.h" />
   11.26 -    <ClInclude Include="..\..\asn.1\constr_SET_OF.h" />
   11.27 -    <ClInclude Include="..\..\asn.1\constr_TYPE.h" />
   11.28 -    <ClInclude Include="..\..\asn.1\der_encoder.h" />
   11.29 -    <ClInclude Include="..\..\asn.1\GroupKeys.h" />
   11.30 -    <ClInclude Include="..\..\asn.1\GroupKeysAndClose.h" />
   11.31 -    <ClInclude Include="..\..\asn.1\HandshakeAnswer.h" />
   11.32 -    <ClInclude Include="..\..\asn.1\HandshakeRequest.h" />
   11.33 -    <ClInclude Include="..\..\asn.1\Hash.h" />
   11.34 -    <ClInclude Include="..\..\asn.1\Hex.h" />
   11.35 -    <ClInclude Include="..\..\asn.1\Identity.h" />
   11.36 -    <ClInclude Include="..\..\asn.1\IdentityList.h" />
   11.37 -    <ClInclude Include="..\..\asn.1\INTEGER.h" />
   11.38 -    <ClInclude Include="..\..\asn.1\ISO639-1.h" />
   11.39 -    <ClInclude Include="..\..\asn.1\KeySync.h" />
   11.40 -    <ClInclude Include="..\..\asn.1\NativeEnumerated.h" />
   11.41 -    <ClInclude Include="..\..\asn.1\NativeInteger.h" />
   11.42 -    <ClInclude Include="..\..\asn.1\OCTET_STRING.h" />
   11.43 -    <ClInclude Include="..\..\asn.1\per_decoder.h" />
   11.44 -    <ClInclude Include="..\..\asn.1\per_encoder.h" />
   11.45 -    <ClInclude Include="..\..\asn.1\per_opentype.h" />
   11.46 -    <ClInclude Include="..\..\asn.1\per_support.h" />
   11.47 -    <ClInclude Include="..\..\asn.1\PrintableString.h" />
   11.48 -    <ClInclude Include="..\..\asn.1\PString.h" />
   11.49 -    <ClInclude Include="..\..\asn.1\Rollback.h" />
   11.50 -    <ClInclude Include="..\..\asn.1\Sync.h" />
   11.51 -    <ClInclude Include="..\..\asn.1\TID.h" />
   11.52 -    <ClInclude Include="..\..\asn.1\UTF8String.h" />
   11.53 -    <ClInclude Include="..\..\asn.1\Version.h" />
   11.54 -    <ClInclude Include="..\..\asn.1\xer_decoder.h" />
   11.55 -    <ClInclude Include="..\..\asn.1\xer_encoder.h" />
   11.56 -    <ClInclude Include="..\..\asn.1\xer_support.h" />
   11.57 +    <ClInclude Include="..\..\asn.1\*.h" />
   11.58    </ItemGroup>
   11.59    <ItemGroup>
   11.60 -    <ClCompile Include="..\..\asn.1\asn_codecs_prim.c" />
   11.61 -    <ClCompile Include="..\..\asn.1\asn_SEQUENCE_OF.c" />
   11.62 -    <ClCompile Include="..\..\asn.1\asn_SET_OF.c" />
   11.63 -    <ClCompile Include="..\..\asn.1\Beacon.c" />
   11.64 -    <ClCompile Include="..\..\asn.1\ber_decoder.c" />
   11.65 -    <ClCompile Include="..\..\asn.1\ber_tlv_length.c" />
   11.66 -    <ClCompile Include="..\..\asn.1\ber_tlv_tag.c" />
   11.67 -    <ClCompile Include="..\..\asn.1\BIT_STRING.c" />
   11.68 -    <ClCompile Include="..\..\asn.1\BOOLEAN.c" />
   11.69 -    <ClCompile Include="..\..\asn.1\CommitAccept.c" />
   11.70 -    <ClCompile Include="..\..\asn.1\CommitReject.c" />
   11.71 -    <ClCompile Include="..\..\asn.1\constraints.c" />
   11.72 -    <ClCompile Include="..\..\asn.1\constr_CHOICE.c" />
   11.73 -    <ClCompile Include="..\..\asn.1\constr_SEQUENCE.c" />
   11.74 -    <ClCompile Include="..\..\asn.1\constr_SEQUENCE_OF.c" />
   11.75 -    <ClCompile Include="..\..\asn.1\constr_SET_OF.c" />
   11.76 -    <ClCompile Include="..\..\asn.1\constr_TYPE.c" />
   11.77 -    <ClCompile Include="..\..\asn.1\der_encoder.c" />
   11.78 -    <ClCompile Include="..\..\asn.1\GroupKeys.c" />
   11.79 -    <ClCompile Include="..\..\asn.1\GroupKeysAndClose.c" />
   11.80 -    <ClCompile Include="..\..\asn.1\HandshakeAnswer.c" />
   11.81 -    <ClCompile Include="..\..\asn.1\HandshakeRequest.c" />
   11.82 -    <ClCompile Include="..\..\asn.1\Hash.c" />
   11.83 -    <ClCompile Include="..\..\asn.1\Hex.c" />
   11.84 -    <ClCompile Include="..\..\asn.1\Identity.c" />
   11.85 -    <ClCompile Include="..\..\asn.1\IdentityList.c" />
   11.86 -    <ClCompile Include="..\..\asn.1\INTEGER.c" />
   11.87 -    <ClCompile Include="..\..\asn.1\ISO639-1.c" />
   11.88 -    <ClCompile Include="..\..\asn.1\KeySync.c" />
   11.89 -    <ClCompile Include="..\..\asn.1\NativeEnumerated.c" />
   11.90 -    <ClCompile Include="..\..\asn.1\NativeInteger.c" />
   11.91 -    <ClCompile Include="..\..\asn.1\OCTET_STRING.c" />
   11.92 -    <ClCompile Include="..\..\asn.1\pdu_collection.c" />
   11.93 -    <ClCompile Include="..\..\asn.1\per_decoder.c" />
   11.94 -    <ClCompile Include="..\..\asn.1\per_encoder.c" />
   11.95 -    <ClCompile Include="..\..\asn.1\per_opentype.c" />
   11.96 -    <ClCompile Include="..\..\asn.1\per_support.c" />
   11.97 -    <ClCompile Include="..\..\asn.1\PrintableString.c" />
   11.98 -    <ClCompile Include="..\..\asn.1\PString.c" />
   11.99 -    <ClCompile Include="..\..\asn.1\Rollback.c" />
  11.100 -    <ClCompile Include="..\..\asn.1\Sync.c" />
  11.101 -    <ClCompile Include="..\..\asn.1\TID.c" />
  11.102 -    <ClCompile Include="..\..\asn.1\UTF8String.c" />
  11.103 -    <ClCompile Include="..\..\asn.1\Version.c" />
  11.104 -    <ClCompile Include="..\..\asn.1\xer_decoder.c" />
  11.105 -    <ClCompile Include="..\..\asn.1\xer_encoder.c" />
  11.106 -    <ClCompile Include="..\..\asn.1\xer_support.c" />
  11.107 +    <ClCompile Include="..\..\asn.1\*.c" />
  11.108    </ItemGroup>
  11.109    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  11.110    <ImportGroup Label="ExtensionTargets">
    12.1 --- a/build-windows/libpEpasn1/libpEpasn1.vcxproj.filters	Thu Mar 28 15:40:45 2019 +0100
    12.2 +++ b/build-windows/libpEpasn1/libpEpasn1.vcxproj.filters	Fri May 17 17:30:57 2019 +0200
    12.3 @@ -168,6 +168,27 @@
    12.4      <ClInclude Include="..\..\asn.1\xer_support.h">
    12.5        <Filter>Header Files</Filter>
    12.6      </ClInclude>
    12.7 +    <ClInclude Include="..\..\asn.1\CommitAcceptForGroup.h">
    12.8 +      <Filter>Header Files</Filter>
    12.9 +    </ClInclude>
   12.10 +    <ClInclude Include="..\..\asn.1\GroupTrustThisKey.h">
   12.11 +      <Filter>Header Files</Filter>
   12.12 +    </ClInclude>
   12.13 +    <ClInclude Include="..\..\asn.1\CommitAcceptFirst.h">
   12.14 +      <Filter>Header Files</Filter>
   12.15 +    </ClInclude>
   12.16 +    <ClInclude Include="..\..\asn.1\CommitAcceptSecond.h">
   12.17 +      <Filter>Header Files</Filter>
   12.18 +    </ClInclude>
   12.19 +    <ClInclude Include="..\..\asn.1\OwnKeys.h">
   12.20 +      <Filter>Header Files</Filter>
   12.21 +    </ClInclude>
   12.22 +    <ClInclude Include="..\..\asn.1\OwnKeysFirst.h">
   12.23 +      <Filter>Header Files</Filter>
   12.24 +    </ClInclude>
   12.25 +    <ClInclude Include="..\..\asn.1\OwnKeysSecond.h">
   12.26 +      <Filter>Header Files</Filter>
   12.27 +    </ClInclude>
   12.28    </ItemGroup>
   12.29    <ItemGroup>
   12.30      <ClCompile Include="..\..\asn.1\asn_codecs_prim.c">
   12.31 @@ -227,9 +248,6 @@
   12.32      <ClCompile Include="..\..\asn.1\GroupKeys.c">
   12.33        <Filter>Source Files</Filter>
   12.34      </ClCompile>
   12.35 -    <ClCompile Include="..\..\asn.1\GroupKeysAndClose.c">
   12.36 -      <Filter>Source Files</Filter>
   12.37 -    </ClCompile>
   12.38      <ClCompile Include="..\..\asn.1\HandshakeAnswer.c">
   12.39        <Filter>Source Files</Filter>
   12.40      </ClCompile>
   12.41 @@ -311,5 +329,26 @@
   12.42      <ClCompile Include="..\..\asn.1\xer_support.c">
   12.43        <Filter>Source Files</Filter>
   12.44      </ClCompile>
   12.45 +    <ClCompile Include="..\..\asn.1\CommitAcceptForGroup.c">
   12.46 +      <Filter>Source Files</Filter>
   12.47 +    </ClCompile>
   12.48 +    <ClCompile Include="..\..\asn.1\GroupTrustThisKey.c">
   12.49 +      <Filter>Source Files</Filter>
   12.50 +    </ClCompile>
   12.51 +    <ClCompile Include="..\..\asn.1\CommitAcceptFirst.c">
   12.52 +      <Filter>Source Files</Filter>
   12.53 +    </ClCompile>
   12.54 +    <ClCompile Include="..\..\asn.1\CommitAcceptSecond.c">
   12.55 +      <Filter>Source Files</Filter>
   12.56 +    </ClCompile>
   12.57 +    <ClCompile Include="..\..\asn.1\OwnKeys.c">
   12.58 +      <Filter>Source Files</Filter>
   12.59 +    </ClCompile>
   12.60 +    <ClCompile Include="..\..\asn.1\OwnKeysFirst.c">
   12.61 +      <Filter>Source Files</Filter>
   12.62 +    </ClCompile>
   12.63 +    <ClCompile Include="..\..\asn.1\OwnKeysSecond.c">
   12.64 +      <Filter>Source Files</Filter>
   12.65 +    </ClCompile>
   12.66    </ItemGroup>
   12.67  </Project>
   12.68 \ No newline at end of file
    13.1 --- a/clean_sync_leftovers.sh	Thu Mar 28 15:40:45 2019 +0100
    13.2 +++ b/clean_sync_leftovers.sh	Fri May 17 17:30:57 2019 +0200
    13.3 @@ -4,3 +4,7 @@
    13.4  cd ../asn.1; hg status . | sed '/?\ /!d' | sed 's/?\ //' |  xargs rm
    13.5  cd ../sync; hg status . | sed '/?\ /!d' | sed 's/?\ //' |  xargs rm
    13.6  cd ..
    13.7 +branch=`hg branch`
    13.8 +if [ "$branch" = "sync" ]; then
    13.9 +    rm src/KeySync_fsm.c src/KeySync_fsm.h src/Sync_actions.c src/Sync_event.c src/Sync_event.h src/Sync_func.c src/Sync_func.h src/Sync_impl.c src/Sync_impl.h src/sync_codec.c src/sync_codec.h
   13.10 +fi	
    14.1 --- a/db/Makefile	Thu Mar 28 15:40:45 2019 +0100
    14.2 +++ b/db/Makefile	Fri May 17 17:30:57 2019 +0200
    14.3 @@ -3,7 +3,7 @@
    14.4  # This file may be used under the terms of the GNU General Public License version 3
    14.5  # see LICENSE.txt
    14.6  
    14.7 -include ../default.conf
    14.8 +include ../Makefile.conf
    14.9  
   14.10  .PHONY: db
   14.11  db: system.db
    15.1 --- a/default.conf	Thu Mar 28 15:40:45 2019 +0100
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,280 +0,0 @@
    15.4 -# Copyright 2017, pEp Foundation
    15.5 -# This file is part of pEpEngine
    15.6 -# This file may be used under the terms of the GNU General Public License version 3
    15.7 -# see LICENSE.txt
    15.8 -
    15.9 -# See `doc/build-<your platform>.md` for documentation on how to build, and customize your build.
   15.10 -
   15.11 -# This file sets all the make variables that allow you to customize a build.
   15.12 -# There are 4 ways in which you can customize your build:
   15.13 -# 1) Edit the variable assignments in this file (this is a tracked file, so your repository will be dirty)
   15.14 -# 2) Edit the variable assignments in `Makefile.conf` (which is a tracked file, so your repository will be dirty)
   15.15 -# 3) Create `local.conf` and fill it with variable assignments.
   15.16 -# 4) Set the environment variable `BUILD_CONFIG` to an absolute path.
   15.17 -#    The variable assignments found in the make file at the path indicated by `BUILD_CONFIG` will be evaluated.
   15.18 -# Customization options are applied in the order given above. Later variable assignments take precedence over earlier ones.
   15.19 -# It is possible to use multiple variants simultaniously.
   15.20 -# If nothing is changed according to these 4 methods, a default configuration for your platform (specified below) will be used for the build.
   15.21 -
   15.22 -
   15.23 -######### Header #########
   15.24 -HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
   15.25 -
   15.26 -
   15.27 -######### General #########
   15.28 -# To use (only) system libraries, set all the *_INC and *_LIB variables to the empty string.
   15.29 -# All the *_INC and *_LIB variables are command line flags, not paths.
   15.30 -# Thus, all *_INC variables' values must start with "-I", and all *_LIB variables' values must start with "-L".
   15.31 -
   15.32 -BUILD_ON:=$(shell uname)
   15.33 -
   15.34 -# This variable specifies the platform that the engine should be cross-compiled for.
   15.35 -BUILD_FOR=$(BUILD_ON)
   15.36 -
   15.37 -# Cross-compiling is currently not supported.
   15.38 -# Maybe you can hack something with `local.conf`.
   15.39 -ifneq ($(BUILD_ON),$(BUILD_FOR))
   15.40 -    $(error I don't know how to build for $(BUILD_FOR) on $(BUILD_ON).)
   15.41 -endif
   15.42 -
   15.43 -# Installation path prefix for libraries and binaries, except for system.db
   15.44 -PREFIX=$(HOME)
   15.45 -
   15.46 -# Installation path for system.db
   15.47 -SYSTEM_DB=/usr/local/share/pEp/system.db
   15.48 -
   15.49 -# Filename of the pEpEngine library
   15.50 -ifeq ($(BUILD_FOR),Linux)
   15.51 -    TARGET=libpEpEngine.so
   15.52 -else ifeq ($(BUILD_FOR),Darwin)
   15.53 -    TARGET=libpEpEngine.dylib
   15.54 -endif
   15.55 -
   15.56 -# If empty, create a release build.
   15.57 -# Otherwise, create a debug build.
   15.58 -# This variable is ineffective in your local.conf file.
   15.59 -DEBUG=placeholder
   15.60 -
   15.61 -# If empty, suppress compiler warnings.
   15.62 -# Otherwise, print warnings.
   15.63 -# This variable is ineffective in your local.conf file.
   15.64 -WARN=placeholder
   15.65 -
   15.66 -
   15.67 -######### C and C++ #########
   15.68 -TARGET_ARCH=
   15.69 -# The following two variables will be appended to.
   15.70 -# You can thus not set them to a fixed value here.
   15.71 -ifeq ($(BUILD_FOR),Linux)
   15.72 -    LDFLAGS=
   15.73 -else ifeq ($(BUILD_FOR),Darwin)
   15.74 -    # "-bind_at_load" helps find symbol resolution errors faster
   15.75 -    LDFLAGS=-bind_at_load
   15.76 -endif
   15.77 -
   15.78 -LDLIBS=
   15.79 -
   15.80 -
   15.81 -######### C #########
   15.82 -ifeq ($(BUILD_FOR),Linux)
   15.83 -    CC=gcc -std=c99 -pthread
   15.84 -else ifeq ($(BUILD_FOR),Darwin)
   15.85 -    # clang issues a warning when "-pthread" is used for linking.
   15.86 -    # So, include it in CFLAGS, and not in CC
   15.87 -    CC=clang -std=c99
   15.88 -endif
   15.89 -
   15.90 -ifeq ($(BUILD_FOR),Linux)
   15.91 -    CFLAGS=-fPIC -fstrict-aliasing -fdiagnostics-color=always
   15.92 -else ifeq ($(BUILD_FOR),Darwin)
   15.93 -    CFLAGS=-pthread -fPIC -fstrict-aliasing -fcolor-diagnostics
   15.94 -endif
   15.95 -
   15.96 -CPPFLAGS=
   15.97 -
   15.98 -# The flag -DNDEBUG will always be removed from CFLAGS for compiling tests.
   15.99 -# The tests do not work properly, if compiled with -DNDEBUG
  15.100 -ifeq ($(BUILD_FOR),Linux)
  15.101 -    ifdef WARN
  15.102 -        CFLAGS+= -Wall -pedantic -Wstrict-aliasing=3
  15.103 -    else
  15.104 -        CFLAGS+= -w
  15.105 -    endif
  15.106 -    ifdef DEBUG
  15.107 -        CFLAGS+= -g -ggdb -DDEBUG_ERRORSTACK
  15.108 -    else
  15.109 -        CFLAGS+= -O3 -DNDEBUG
  15.110 -    endif
  15.111 -else ifeq ($(BUILD_FOR),Darwin)
  15.112 -    ifdef WARN
  15.113 -        # FIXME Remove 'no-extended-offsetof' after ENGINE-236 is closed.
  15.114 -        CFLAGS+= -Wall -pedantic -Wno-extended-offsetof
  15.115 -    else
  15.116 -        CFLAGS+= -w
  15.117 -    endif
  15.118 -    ifdef DEBUG
  15.119 -        CFLAGS+= -O0 -g -DDEBUG_ERRORSTACK
  15.120 -    else
  15.121 -        CFLAGS+= -O3 -DNDEBUG
  15.122 -    endif
  15.123 -endif
  15.124 -
  15.125 -# Additional CFLAGS used for compiling ASN1C-generated code
  15.126 -ifeq ($(BUILD_FOR),Linux)
  15.127 -    # The '_DEFAULT_SOURCE' feature test macro is required to suppress the warning
  15.128 -    #   _BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE
  15.129 -    # otherwise printed during the compilation of every asn1c-generated C file.
  15.130 -    # It's a glibc specific warning, only present in few versions around ~2.19.
  15.131 -    # See https://lwn.net/Articles/590381/ for a discussion.
  15.132 -    CFLAGS_GENERATED=-D_DEFAULT_SOURCE
  15.133 -else ifeq ($(BUILD_FOR),Darwin)
  15.134 -    CFLAGS_GENERATED=
  15.135 -endif
  15.136 -
  15.137 -
  15.138 -######### C++ #########
  15.139 -ifeq ($(BUILD_FOR),Linux)
  15.140 -    CXX=g++ -std=gnu++11 -pthread
  15.141 -else ifeq ($(BUILD_FOR),Darwin)
  15.142 -    # clang issues a warning when "-pthread" is used for linking. So, include it in CXXFLAGS, and not in CXX
  15.143 -    CXX=clang -std=c++11
  15.144 -endif
  15.145 -
  15.146 -# The flag -DNDEBUG will always be removed from CXXFLAGS for compiling tests.
  15.147 -# The tests do not work properly, if compiled with -DNDEBUG
  15.148 -ifeq ($(BUILD_FOR),Linux)
  15.149 -    CXXFLAGS=-fdiagnostics-color=always -I../src -I../asn.1 $(ETPAN_INC)
  15.150 -    ifdef WARN
  15.151 -        CXXFLAGS+=
  15.152 -    else
  15.153 -        CXXFLAGS+= -w
  15.154 -    endif
  15.155 -    ifdef DEBUG
  15.156 -        CXXFLAGS+= -g -ggdb
  15.157 -    else
  15.158 -        CXXFLAGS+= -O3 -DNDEBUG
  15.159 -    endif
  15.160 -else ifeq ($(BUILD_FOR),Darwin)
  15.161 -    CXXFLAGS=-pthread -fcolor-diagnostics -I../src -I../asn.1 $(ETPAN_INC)
  15.162 -    ifdef WARN
  15.163 -        CXXFLAGS+=
  15.164 -    else
  15.165 -        CXXFLAGS+= -w
  15.166 -    endif
  15.167 -    ifdef DEBUG
  15.168 -        CXXFLAGS+= -O0 -g
  15.169 -    else
  15.170 -        CXXFLAGS+= -O3 -DNDEBUG
  15.171 -    endif
  15.172 -endif
  15.173 -
  15.174 -
  15.175 -######### YML2 #########
  15.176 -YML2_PATH=$(HOME)/yml2
  15.177 -
  15.178 -YML2_PROC=$(YML2_PATH)/yml2proc
  15.179 -
  15.180 -YML2_OPTS=--encoding=utf8
  15.181 -
  15.182 -
  15.183 -######### asn1c #########
  15.184 -# asn1c binary
  15.185 -ASN1C=asn1c
  15.186 -
  15.187 -# asn1c include search flag
  15.188 -ASN1C_INC=-I$(PREFIX)/include
  15.189 -
  15.190 -
  15.191 -######### libetpan #########
  15.192 -# libetpan library search flag
  15.193 -ETPAN_LIB=-L$(PREFIX)/lib
  15.194 -
  15.195 -# libetpan include search flag
  15.196 -ETPAN_INC=-I$(PREFIX)/include
  15.197 -
  15.198 -
  15.199 -######### sqlite3 #########
  15.200 -# If empty (or undefined), compile sqlite3 from the sources shipped with the pEp distribution.
  15.201 -# Otherwise, use an sqlite3 implementation found in the OS's include/library paths.
  15.202 -SQLITE3_FROM_OS=placeholder
  15.203 -
  15.204 -
  15.205 -######### OpenPGP #########
  15.206 -# Path of GPG binary
  15.207 -# gpgconf is not available for old version of GPG, for example GPG 2.0.30. Override this variable, if you compile the engine for such an old version.
  15.208 -GPG_CMD:=$(shell gpgconf --list-components | awk -F: '/^gpg:/ { print $$3; exit 0; }')
  15.209 -
  15.210 -# Selects OpenPGP implementation. must be either `GPG` or `NETPGP` or `SEQUOIA`
  15.211 -OPENPGP=GPG
  15.212 -
  15.213 -# Path of libGPGME binary
  15.214 -ifeq ($(BUILD_FOR),Linux)
  15.215 -    LIBGPGME=libgpgme.so.11
  15.216 -else ifeq ($(BUILD_FOR),Darwin)
  15.217 -    LIBGPGME=libgpgme.11.dylib
  15.218 -endif
  15.219 -
  15.220 -# libGPGME library search flag
  15.221 -ifeq ($(BUILD_FOR),Linux)
  15.222 -    GPGME_LIB=
  15.223 -else ifeq ($(BUILD_FOR),Darwin)
  15.224 -    GPGME_LIB=-L$(HOME)/lib
  15.225 -endif
  15.226 -
  15.227 -# libGPGME include search flag
  15.228 -ifeq ($(BUILD_FOR),Linux)
  15.229 -    GPGME_INC=
  15.230 -else ifeq ($(BUILD_FOR),Darwin)
  15.231 -    GPGME_INC=-I$(HOME)/include
  15.232 -endif
  15.233 -
  15.234 -# NETPGP library search flag
  15.235 -NETPGP_LIB=
  15.236 -#NETPGP_LIB=-L$(PREFIX)/lib
  15.237 -
  15.238 -# libGPGME include search flag
  15.239 -NETPGP_INC=
  15.240 -#NETPGP_INC=-I$(PREFIX)/include
  15.241 -
  15.242 -SEQUOIA_CFLAGS=$(shell pkg-config --cflags-only-other sequoia)
  15.243 -SEQUOIA_LDFLAGS=$(shell pkg-config --libs-only-L --libs-only-other sequoia)
  15.244 -SEQUOIA_LIB=$(shell pkg-config --libs-only-l sequoia)
  15.245 -SEQUOIA_INC=$(shell pkg-config --cflags-only-I sequoia)
  15.246 -
  15.247 -
  15.248 -######### OpenPGP #########
  15.249 -# CppUnit library search flag
  15.250 -CPPUNIT_LIB=
  15.251 -#CPPUNIT_LIB=-L$(HOME)/local/lib
  15.252 -
  15.253 -# CppUnit include search flag
  15.254 -CPPUNIT_INC=
  15.255 -#CPPUNIT_INC=-I$(HOME)/local/inc
  15.256 -
  15.257 -
  15.258 -######### Engine internals #########
  15.259 -# C macros (not environment variables) that can be overridden:
  15.260 -# DEFAULT_KEYSERVER - string with default keyserver
  15.261 -# CRASHDUMP_DEFAULT_LINES - number of log lines to deliver for crashdumps
  15.262 -# Example:
  15.263 -#    EXTRA_MACROS=-DDEFAULT_KEYSERVER=\"default-server.org\" -DCRASHDUMP_DEFAULT_LINES=23
  15.264 -EXTRA_MACROS=
  15.265 -
  15.266 -
  15.267 -######### Misc #########
  15.268 -# FIXME Maybe include these variables here.
  15.269 -# Check how they are used throughout the project before setting them here
  15.270 -#LLDB_BIN
  15.271 -
  15.272 -
  15.273 -######### Footer #########
  15.274 -include $(HERE)/Makefile.conf
  15.275 -
  15.276 --include $(HERE)/local.conf
  15.277 -
  15.278 -ifdef BUILD_CONFIG
  15.279 -    include $(BUILD_CONFIG)
  15.280 -endif
  15.281 -
  15.282 -# YML_PATH is needed in the environment of every call to a program of the YML2 distribution
  15.283 -export YML_PATH=$(YML2_PATH)
    16.1 --- a/doc/build-debian.md	Thu Mar 28 15:40:45 2019 +0100
    16.2 +++ b/doc/build-debian.md	Fri May 17 17:30:57 2019 +0200
    16.3 @@ -64,11 +64,11 @@
    16.4  mkdir ~/code/pep-engine/build
    16.5  ~~~
    16.6  
    16.7 -Edit the build configuration to your needs in `Makefile.conf`, or create a `local.conf` that sets any of the make variables documented in `Makefile.conf`. All the default values for the build configuration variables on each platform are documented in `default.conf`.
    16.8 +Edit the build configuration to your needs in `Makefile.conf`, or create a `local.conf` that sets any of the make variables documented in `Makefile.conf`. All the default values for the build configuration variables on each platform are documented in `Makefile.conf`.
    16.9  
   16.10  If a dependency is not found in your system's default include or library paths, you will have to specify the according paths in a make variable. Typically, this has to be done at least for YML2, libetpan and asn1c.
   16.11  
   16.12 -For a more detailed explanation of the mechanics of these build configuration files, and overriding defaults, see the comments in `default.conf`.
   16.13 +For a more detailed explanation of the mechanics of these build configuration files, and overriding defaults, see the comments in `Makefile.conf`.
   16.14  
   16.15  Below is a sample `./local.conf` file, for orientation.
   16.16  
    17.1 --- a/doc/build-macos.md	Thu Mar 28 15:40:45 2019 +0100
    17.2 +++ b/doc/build-macos.md	Fri May 17 17:30:57 2019 +0200
    17.3 @@ -105,11 +105,11 @@
    17.4  mkdir ~/code/pep-engine/build
    17.5  ~~~
    17.6  
    17.7 -Edit the build configuration to your needs in `Makefile.conf`, or create a `local.conf` that sets any of the make variables documented in `Makefile.conf`. All the default values for the build configuration variables on each platform are documented in `default.conf`.
    17.8 +Edit the build configuration to your needs in `Makefile.conf`, or create a `local.conf` that sets any of the make variables documented in `Makefile.conf`. All the default values for the build configuration variables on each platform are documented in `Makefile.conf`.
    17.9  
   17.10  If a dependency is not found in your system's default include or library paths, you will have to specify the according paths in a make variable. Typically, this has to be done at least for YML2, and libetpan.
   17.11  
   17.12 -For a more detailed explanation of the mechanics of these build configuration files, and overriding defaults, see the comments in `default.conf`.
   17.13 +For a more detailed explanation of the mechanics of these build configuration files, and overriding defaults, see the comments in `Makefile.conf`.
   17.14  
   17.15  Below is a sample `./local.conf` file, for orientation.
   17.16  
    18.1 --- a/src/Makefile	Thu Mar 28 15:40:45 2019 +0100
    18.2 +++ b/src/Makefile	Fri May 17 17:30:57 2019 +0200
    18.3 @@ -3,29 +3,36 @@
    18.4  # This file may be used under the terms of the GNU General Public License version 3
    18.5  # see LICENSE.txt
    18.6  
    18.7 -include ../default.conf
    18.8 +include ../Makefile.conf
    18.9  
   18.10 -CFLAGS+= $(ETPAN_INC) -I../asn.1 -DSYSTEM_DB=\"$(SYSTEM_DB)\" $(EXTRA_MACROS)
   18.11 -LDFLAGS+= $(ETPAN_LIB) -L../asn.1 -shared
   18.12 -LDLIBS+= -lc -letpan -lasn1
   18.13 +CFLAGS+= $(ETPAN_INC) $(PEP_MIME_INC) -I../asn.1 -DSYSTEM_DB=\"$(SYSTEM_DB)\" $(EXTRA_MACROS)
   18.14 +LDFLAGS+= $(ETPAN_LIB) $(PEP_MIME_LIB) -L../asn.1 -shared
   18.15 +LDLIBS+= -lc -lasn1
   18.16  NO_SOURCE=
   18.17  
   18.18 +ifndef PEP_MIME
   18.19 +LDLIBS+= -letpan
   18.20 +else
   18.21 +LDLIBS+= -lpEpMIME
   18.22 +NO_SOURCE+= etpan_mime.c
   18.23 +endif
   18.24 +
   18.25  ifeq ($(BUILD_ON),Darwin)
   18.26      ifeq ($(BUILD_FOR),Darwin)
   18.27          CFLAGS+= -DSQLITE_THREADSAFE=1
   18.28          LDLIBS+= -lz -liconv
   18.29      else
   18.30 -        $(error I don't know how to make for $(BUILD_FOR) on $(BUILD_ON))
   18.31 +        $(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON))
   18.32      endif
   18.33  else ifeq ($(BUILD_ON),Linux)
   18.34      ifeq ($(BUILD_FOR),Linux)
   18.35          CFLAGS+= -DSQLITE_THREADSAFE=1 -D_GNU_SOURCE
   18.36          LDLIBS+= -ldl -luuid
   18.37      else
   18.38 -        $(error I don't know how to make for $(BUILD_FOR) on $(BUILD_ON))
   18.39 +        $(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON))
   18.40      endif
   18.41  else
   18.42 -    $(error I don't know how to make for $(BUILD_FOR) on $(BUILD_ON))
   18.43 +    $(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON))
   18.44  endif
   18.45  
   18.46  ifdef SQLITE3_FROM_OS
   18.47 @@ -57,7 +64,6 @@
   18.48  DEPENDS=$(subst .c,.d,$(ALL_SOURCE))
   18.49  ALL_OBJECTS=$(subst .c,.o,$(ALL_SOURCE))
   18.50  
   18.51 -.PHONY: all
   18.52  all: $(TARGET)
   18.53  
   18.54  -include Makefile.protocols
   18.55 @@ -74,36 +80,39 @@
   18.56  endif
   18.57  
   18.58  $(TARGET): libpEpEngine.a
   18.59 -	$(CC) $(ALL_OBJECTS) $(LDFLAGS) $(LDLIBS) -o $@
   18.60 +	$(CC) $(CFLAGS) $(ALL_OBJECTS) $(LDFLAGS) $(LDLIBS) -o $@
   18.61  
   18.62 -.PHONY: objects
   18.63 +.PHONY: objects clean install_headers install uninstall
   18.64 +
   18.65  objects: $(ALL_OBJECTS)
   18.66  
   18.67  libpEpEngine.a: $(ALL_OBJECTS)
   18.68 -	ar -rc $@ $^
   18.69 +	$(AR) -rc $@ $^
   18.70  
   18.71 -.PHONY: clean
   18.72  clean:
   18.73  	rm -f *.d *.o *.a $(TARGET) *.dll *.so *.zip *.d.* *.def *~
   18.74  	rm -Rf $(TARGET).dSYM
   18.75 +	rm -f KeySync_fsm.* Sync_actions.c Sync_event.* Sync_func.* Sync_impl.* sync_codec.*
   18.76  
   18.77 -.PHONY: install
   18.78 -install: $(TARGET)
   18.79 +# CAVEAT:
   18.80 +# install_headers is needed for building pEp MIME
   18.81 +
   18.82 +install_headers:
   18.83 +	mkdir -p $(PREFIX)/include/pEp
   18.84 +	cp pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h \
   18.85 +	   timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h \
   18.86 +	   cryptotech.h sync_api.h blacklist.h pEp_string.h openpgp_compat.h \
   18.87 +	   labeled_int_list.h key_reset.h base64.h sync_codec.h status_to_string.h\
   18.88 +	   aux_mime_msg.h ../asn.1/*.h $(PREFIX)/include/pEp/
   18.89 +
   18.90 +install: $(TARGET) install_headers
   18.91  	mkdir -p "$(PREFIX)/lib/"
   18.92  	cp $< $(PREFIX)/lib/
   18.93 -	mkdir -p $(PREFIX)/include/pEp
   18.94 -	cp -v pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h \
   18.95 -	      timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h \
   18.96 -	      cryptotech.h sync_api.h blacklist.h pEp_string.h openpgp_compat.h \
   18.97 -	      labeled_int_list.h key_reset.h base64.h sync_codec.h \
   18.98 -		  ../asn.1/*.h $(PREFIX)/include/pEp/
   18.99  
  18.100 -.PHONY: uninstall
  18.101  uninstall:
  18.102  	rm -f $(PREFIX)/lib/$(TARGET)
  18.103  	rm -rf $(PREFIX)/include/pEp
  18.104  
  18.105 -.PHONY: tags
  18.106 -tags:
  18.107 +tags: $(wildcard *.c) $(wildcard *.h)
  18.108  	ctags *.c *.h
  18.109  
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/aux_mime_msg.c	Fri May 17 17:30:57 2019 +0200
    19.3 @@ -0,0 +1,274 @@
    19.4 +// This file is under GNU General Public License 3.0
    19.5 +// see LICENSE.txt
    19.6 +
    19.7 +#ifdef ENIGMAIL_MAY_USE_THIS
    19.8 +
    19.9 +#include "pEp_internal.h"
   19.10 +#include "message_api.h"
   19.11 +#include "mime.h"
   19.12 +
   19.13 +#include <assert.h>
   19.14 +#include <string.h>
   19.15 +#include <stdlib.h>
   19.16 +
   19.17 +#include "aux_mime_msg.h"
   19.18 +
   19.19 +
   19.20 +static PEP_STATUS update_identity_recip_list(PEP_SESSION session,
   19.21 +                                             identity_list* list) {
   19.22 +
   19.23 +    PEP_STATUS status = PEP_STATUS_OK;
   19.24 +
   19.25 +    if (!session)
   19.26 +        return PEP_UNKNOWN_ERROR;
   19.27 +    
   19.28 +    identity_list* id_list_ptr = NULL;
   19.29 +        
   19.30 +    for (id_list_ptr = list; id_list_ptr; id_list_ptr = id_list_ptr->next) {
   19.31 +        pEp_identity* curr_identity = id_list_ptr->ident;
   19.32 +        if (curr_identity) {
   19.33 +            if (!is_me(session, curr_identity)) {
   19.34 +                char* name_bak = curr_identity->username;
   19.35 +                curr_identity->username = NULL;
   19.36 +                status = update_identity(session, curr_identity);
   19.37 +                if (name_bak && 
   19.38 +                    (EMPTYSTR(curr_identity->username) || strcmp(name_bak, curr_identity->username) != 0)) {
   19.39 +                    free(curr_identity->username);
   19.40 +                    curr_identity->username = name_bak;
   19.41 +                }                        
   19.42 +            }
   19.43 +            else
   19.44 +                status = _myself(session, curr_identity, false, false, true);
   19.45 +        if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
   19.46 +            return status;
   19.47 +        }
   19.48 +    }
   19.49 +    
   19.50 +    return PEP_STATUS_OK;                                  
   19.51 +}
   19.52 +
   19.53 +DYNAMIC_API PEP_STATUS MIME_decrypt_message(
   19.54 +    PEP_SESSION session,
   19.55 +    const char *mimetext,
   19.56 +    size_t size,
   19.57 +    char** mime_plaintext,
   19.58 +    stringlist_t **keylist,
   19.59 +    PEP_rating *rating,
   19.60 +    PEP_decrypt_flags_t *flags,
   19.61 +    char** modified_src
   19.62 +)
   19.63 +{
   19.64 +    assert(mimetext);
   19.65 +    assert(mime_plaintext);
   19.66 +    assert(keylist);
   19.67 +    assert(rating);
   19.68 +    assert(flags);
   19.69 +    assert(modified_src);
   19.70 +
   19.71 +    if (!(mimetext && mime_plaintext && keylist && rating && flags && modified_src))
   19.72 +        return PEP_ILLEGAL_VALUE;
   19.73 +        
   19.74 +    PEP_STATUS status = PEP_STATUS_OK;
   19.75 +    message* tmp_msg = NULL;
   19.76 +    message* dec_msg = NULL;
   19.77 +    *mime_plaintext = NULL;
   19.78 +
   19.79 +    status = mime_decode_message(mimetext, size, &tmp_msg);
   19.80 +    if (status != PEP_STATUS_OK)
   19.81 +        goto pEp_error;
   19.82 +
   19.83 +    tmp_msg->dir = PEP_dir_incoming;
   19.84 +    // MIME decode message delivers only addresses. We need more.
   19.85 +    if (tmp_msg->from) {
   19.86 +        if (!is_me(session, tmp_msg->from))
   19.87 +            status = update_identity(session, (tmp_msg->from));
   19.88 +        else
   19.89 +            status = _myself(session, tmp_msg->from, false, false, true);
   19.90 +
   19.91 +        if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
   19.92 +            goto pEp_error;
   19.93 +    }
   19.94 +
   19.95 +    status = update_identity_recip_list(session, tmp_msg->to);
   19.96 +    if (status != PEP_STATUS_OK)
   19.97 +        goto pEp_error;
   19.98 +
   19.99 +    status = update_identity_recip_list(session, tmp_msg->cc);
  19.100 +    if (status != PEP_STATUS_OK)
  19.101 +        goto pEp_error;
  19.102 +
  19.103 +    status = update_identity_recip_list(session, tmp_msg->bcc);
  19.104 +    if (status != PEP_STATUS_OK)
  19.105 +        goto pEp_error;
  19.106 +
  19.107 +    PEP_STATUS decrypt_status = decrypt_message(session,
  19.108 +                                                tmp_msg,
  19.109 +                                                &dec_msg,
  19.110 +                                                keylist,
  19.111 +                                                rating,
  19.112 +                                                flags);
  19.113 +
  19.114 +
  19.115 +    if (!dec_msg && (decrypt_status == PEP_UNENCRYPTED || decrypt_status == PEP_VERIFIED)) {
  19.116 +        dec_msg = message_dup(tmp_msg);
  19.117 +    }
  19.118 +    
  19.119 +    if (decrypt_status > PEP_CANNOT_DECRYPT_UNKNOWN || !dec_msg)
  19.120 +    {
  19.121 +        status = decrypt_status;
  19.122 +        goto pEp_error;
  19.123 +    }
  19.124 +
  19.125 +    if (*flags & PEP_decrypt_flag_src_modified) {
  19.126 +        _mime_encode_message_internal(tmp_msg, false, modified_src, true);
  19.127 +        if (!modified_src) {
  19.128 +            *flags &= (~PEP_decrypt_flag_src_modified);
  19.129 +            decrypt_status = PEP_CANNOT_REENCRYPT; // Because we couldn't return it, I guess.
  19.130 +        }
  19.131 +    }
  19.132 +
  19.133 +    // FIXME: test with att
  19.134 +    status = _mime_encode_message_internal(dec_msg, false, mime_plaintext, true);
  19.135 +
  19.136 +    if (status == PEP_STATUS_OK)
  19.137 +    {
  19.138 +        free(tmp_msg);
  19.139 +        free(dec_msg);
  19.140 +        return decrypt_status;
  19.141 +    }
  19.142 +    
  19.143 +pEp_error:
  19.144 +    free_message(tmp_msg);
  19.145 +    free_message(dec_msg);
  19.146 +
  19.147 +    return status;
  19.148 +}
  19.149 +
  19.150 +
  19.151 +DYNAMIC_API PEP_STATUS MIME_encrypt_message(
  19.152 +    PEP_SESSION session,
  19.153 +    const char *mimetext,
  19.154 +    size_t size,
  19.155 +    stringlist_t* extra,
  19.156 +    char** mime_ciphertext,
  19.157 +    PEP_enc_format enc_format,
  19.158 +    PEP_encrypt_flags_t flags
  19.159 +)
  19.160 +{
  19.161 +    PEP_STATUS status = PEP_STATUS_OK;
  19.162 +    message* tmp_msg = NULL;
  19.163 +    message* enc_msg = NULL;
  19.164 +
  19.165 +    status = mime_decode_message(mimetext, size, &tmp_msg);
  19.166 +    if (status != PEP_STATUS_OK)
  19.167 +        goto pEp_error;
  19.168 +
  19.169 +    // MIME decode message delivers only addresses. We need more.
  19.170 +    if (tmp_msg->from) {
  19.171 +        char* own_id = NULL;
  19.172 +        status = get_default_own_userid(session, &own_id);
  19.173 +        free(tmp_msg->from->user_id);
  19.174 +        
  19.175 +        if (status != PEP_STATUS_OK || !own_id) {
  19.176 +            tmp_msg->from->user_id = strdup(PEP_OWN_USERID);
  19.177 +        }
  19.178 +        else {
  19.179 +            tmp_msg->from->user_id = own_id; // ownership transfer
  19.180 +        }
  19.181 +            
  19.182 +        status = myself(session, tmp_msg->from);
  19.183 +        if (status != PEP_STATUS_OK)
  19.184 +            goto pEp_error;
  19.185 +    }
  19.186 +    
  19.187 +    // Own identities can be retrieved here where they would otherwise
  19.188 +    // fail because we lack all other information. This is ok and even
  19.189 +    // desired. FIXME: IS it?
  19.190 +    status = update_identity_recip_list(session, tmp_msg->to);
  19.191 +    if (status != PEP_STATUS_OK)
  19.192 +        goto pEp_error;
  19.193 +    
  19.194 +    status = update_identity_recip_list(session, tmp_msg->cc);
  19.195 +    if (status != PEP_STATUS_OK)
  19.196 +        goto pEp_error;
  19.197 +    
  19.198 +    status = update_identity_recip_list(session, tmp_msg->bcc);
  19.199 +    if (status != PEP_STATUS_OK)
  19.200 +        goto pEp_error;
  19.201 +    
  19.202 +    // This isn't incoming, though... so we need to reverse the direction
  19.203 +    tmp_msg->dir = PEP_dir_outgoing;
  19.204 +    status = encrypt_message(session,
  19.205 +                             tmp_msg,
  19.206 +                             extra,
  19.207 +                             &enc_msg,
  19.208 +                             enc_format,
  19.209 +                             flags);
  19.210 +                             
  19.211 +    if (status != PEP_STATUS_OK)
  19.212 +        goto pEp_error;
  19.213 +
  19.214 +
  19.215 +    if (!enc_msg) {
  19.216 +        status = PEP_UNKNOWN_ERROR;
  19.217 +        goto pEp_error;
  19.218 +    }
  19.219 +
  19.220 +    status = _mime_encode_message_internal(enc_msg, false, mime_ciphertext, false);
  19.221 +
  19.222 +pEp_error:
  19.223 +    free_message(tmp_msg);
  19.224 +    free_message(enc_msg);
  19.225 +
  19.226 +    return status;
  19.227 +
  19.228 +}
  19.229 +
  19.230 +DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
  19.231 +    PEP_SESSION session,
  19.232 +    pEp_identity* target_id,
  19.233 +    const char *mimetext,
  19.234 +    size_t size,
  19.235 +    stringlist_t* extra,
  19.236 +    char** mime_ciphertext,
  19.237 +    PEP_enc_format enc_format,
  19.238 +    PEP_encrypt_flags_t flags
  19.239 +)
  19.240 +{
  19.241 +    PEP_STATUS status = PEP_STATUS_OK;
  19.242 +    message* tmp_msg = NULL;
  19.243 +    message* enc_msg = NULL;
  19.244 +
  19.245 +    status = mime_decode_message(mimetext, size, &tmp_msg);
  19.246 +    if (status != PEP_STATUS_OK)
  19.247 +        goto pEp_error;
  19.248 +
  19.249 +    // This isn't incoming, though... so we need to reverse the direction
  19.250 +    tmp_msg->dir = PEP_dir_outgoing;
  19.251 +    status = encrypt_message_for_self(session,
  19.252 +                                      target_id,
  19.253 +                                      tmp_msg,
  19.254 +                                      extra,
  19.255 +                                      &enc_msg,
  19.256 +                                      enc_format,
  19.257 +                                      flags);
  19.258 +    if (status != PEP_STATUS_OK)
  19.259 +        goto pEp_error;
  19.260 + 
  19.261 +    if (!enc_msg) {
  19.262 +        status = PEP_UNKNOWN_ERROR;
  19.263 +        goto pEp_error;
  19.264 +    }
  19.265 +
  19.266 +    status = mime_encode_message(enc_msg, false, mime_ciphertext);
  19.267 +
  19.268 +pEp_error:
  19.269 +    free_message(tmp_msg);
  19.270 +    free_message(enc_msg);
  19.271 +
  19.272 +    return status;
  19.273 +}
  19.274 +#else
  19.275 +const int the_answer_my_friend = 42;
  19.276 +#endif
  19.277 +
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/aux_mime_msg.h	Fri May 17 17:30:57 2019 +0200
    20.3 @@ -0,0 +1,150 @@
    20.4 +// This file is under GNU General Public License 3.0
    20.5 +// see LICENSE.txt
    20.6 +
    20.7 +#pragma once
    20.8 +
    20.9 +#ifdef ENIGMAIL_MAY_USE_THIS
   20.10 +
   20.11 +#include "pEpEngine.h"
   20.12 +#include "keymanagement.h"
   20.13 +#include "message.h"
   20.14 +#include "cryptotech.h"
   20.15 +
   20.16 +#ifdef __cplusplus
   20.17 +extern "C" {
   20.18 +#endif
   20.19 +
   20.20 +// MIME_encrypt_message() - encrypt a MIME message, with MIME output
   20.21 +//
   20.22 +//  parameters:
   20.23 +//      session (in)            session handle
   20.24 +//      mimetext (in)           MIME encoded text to encrypt
   20.25 +//      size (in)               size of input mime text
   20.26 +//      extra (in)              extra keys for encryption
   20.27 +//      mime_ciphertext (out)   encrypted, encoded message
   20.28 +//      enc_format (in)         encrypted format
   20.29 +//      flags (in)              flags to set special encryption features
   20.30 +//
   20.31 +//  return value:
   20.32 +//      PEP_STATUS_OK           if everything worked
   20.33 +//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
   20.34 +//      PEP_CANNOT_CREATE_TEMP_FILE
   20.35 +//                              if there are issues with temp files; in
   20.36 +//                              this case errno will contain the underlying
   20.37 +//                              error
   20.38 +//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
   20.39 +//
   20.40 +//  caveat:
   20.41 +//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
   20.42 +//      will remain in the ownership of the caller
   20.43 +DYNAMIC_API PEP_STATUS MIME_encrypt_message(
   20.44 +    PEP_SESSION session,
   20.45 +    const char *mimetext,
   20.46 +    size_t size,
   20.47 +    stringlist_t* extra,
   20.48 +    char** mime_ciphertext,
   20.49 +    PEP_enc_format enc_format,
   20.50 +    PEP_encrypt_flags_t flags
   20.51 +);
   20.52 +
   20.53 +
   20.54 +// MIME_encrypt_message_for_self() - encrypt MIME message for user's identity only,
   20.55 +//                              ignoring recipients and other identities from
   20.56 +//                              the message, with MIME output
   20.57 +//  parameters:
   20.58 +//      session (in)            session handle
   20.59 +//      target_id (in)          self identity this message should be encrypted for
   20.60 +//      mimetext (in)           MIME encoded text to encrypt
   20.61 +//      size (in)               size of input mime text
   20.62 +//      extra (in)              extra keys for encryption
   20.63 +//      mime_ciphertext (out)   encrypted, encoded message
   20.64 +//      enc_format (in)         encrypted format
   20.65 +//      flags (in)              flags to set special encryption features
   20.66 +//
   20.67 +//  return value:
   20.68 +//      PEP_STATUS_OK           if everything worked
   20.69 +//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
   20.70 +//      PEP_CANNOT_CREATE_TEMP_FILE
   20.71 +//                              if there are issues with temp files; in
   20.72 +//                              this case errno will contain the underlying
   20.73 +//                              error
   20.74 +//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
   20.75 +//
   20.76 +//  caveat:
   20.77 +//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
   20.78 +//      will remain in the ownership of the caller
   20.79 +DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
   20.80 +    PEP_SESSION session,
   20.81 +    pEp_identity* target_id,
   20.82 +    const char *mimetext,
   20.83 +    size_t size,
   20.84 +    stringlist_t* extra,
   20.85 +    char** mime_ciphertext,
   20.86 +    PEP_enc_format enc_format,
   20.87 +    PEP_encrypt_flags_t flags
   20.88 +);
   20.89 +
   20.90 +
   20.91 +
   20.92 +// MIME_decrypt_message() - decrypt a MIME message, with MIME output
   20.93 +//
   20.94 +//  parameters:
   20.95 +//      session (in)            session handle
   20.96 +//      mimetext (in)           MIME encoded text to decrypt
   20.97 +//      size (in)               size of mime text to decode (in order to decrypt)
   20.98 +//      mime_plaintext (out)    decrypted, encoded message
   20.99 +//      keylist (inout)         in: stringlist with additional keyids for reencryption if needed
  20.100 +//                                  (will be freed and replaced with output keylist)
  20.101 +//                              out: stringlist with keyids
  20.102 +//      rating (out)            rating for the message
  20.103 +//      flags (inout)           flags to signal special decryption features (see below)
  20.104 +//      modified_src (out)      modified source string, if decrypt had reason to change it
  20.105 +//
  20.106 +//  return value:
  20.107 +//      decrypt status          if everything worked with MIME encode/decode, 
  20.108 +//                              the status of the decryption is returned 
  20.109 +//                              (PEP_STATUS_OK or decryption error status)
  20.110 +//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
  20.111 +//      PEP_CANNOT_CREATE_TEMP_FILE
  20.112 +//                              if there are issues with temp files; in
  20.113 +//                              this case errno will contain the underlying
  20.114 +//                              error
  20.115 +//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
  20.116 +//
  20.117 +//  flag values:
  20.118 +//      in:
  20.119 +//          PEP_decrypt_flag_untrusted_server
  20.120 +//              used to signal that decrypt function should engage in behaviour
  20.121 +//              specified for when the server storing the source is untrusted.
  20.122 +//      out:
  20.123 +//          PEP_decrypt_flag_own_private_key
  20.124 +//              private key was imported for one of our addresses (NOT trusted
  20.125 +//              or set to be used - handshake/trust is required for that)
  20.126 +//          PEP_decrypt_flag_src_modified
  20.127 +//              indicates that the modified_src field should contain a modified
  20.128 +//              version of the source, at the moment always as a result of the
  20.129 +//              input flags. 
  20.130 +//          PEP_decrypt_flag_consume
  20.131 +//              used by sync 
  20.132 +//          PEP_decrypt_flag_ignore
  20.133 +//              used by sync 
  20.134 +// 
  20.135 +//  caveat:
  20.136 +//      the decrypted, encoded mime text will go to the ownership of the caller; mimetext
  20.137 +//      will remain in the ownership of the caller
  20.138 +DYNAMIC_API PEP_STATUS MIME_decrypt_message(
  20.139 +    PEP_SESSION session,
  20.140 +    const char *mimetext,
  20.141 +    size_t size,
  20.142 +    char** mime_plaintext,
  20.143 +    stringlist_t **keylist,
  20.144 +    PEP_rating *rating,
  20.145 +    PEP_decrypt_flags_t *flags,
  20.146 +    char** modified_src
  20.147 +);
  20.148 +
  20.149 +#ifdef __cplusplus
  20.150 +}
  20.151 +#endif
  20.152 +
  20.153 +#endif
    21.1 --- a/src/baseprotocol.c	Thu Mar 28 15:40:45 2019 +0100
    21.2 +++ b/src/baseprotocol.c	Fri May 17 17:30:57 2019 +0200
    21.3 @@ -9,7 +9,7 @@
    21.4          message *msg,
    21.5          char *payload,
    21.6          size_t size,
    21.7 -        char *fpr
    21.8 +        const char *fpr
    21.9      )
   21.10  {
   21.11      PEP_STATUS status = PEP_STATUS_OK;
   21.12 @@ -39,12 +39,12 @@
   21.13          assert(sign && sign_size);
   21.14  
   21.15          bl = bloblist_add(bl, sign, sign_size,
   21.16 -                "application/pEp.sign", "ignore_this_attachment.pEp");
   21.17 +                "application/pEp.sign", "electronic_signature.asc");
   21.18          if (!bl)
   21.19              goto enomem;
   21.20      }
   21.21  
   21.22 -    return PEP_STATUS_OK;
   21.23 +    return status;
   21.24  
   21.25  enomem:
   21.26      status = PEP_OUT_OF_MEMORY;
   21.27 @@ -59,7 +59,7 @@
   21.28          const pEp_identity *partner,
   21.29          char *payload,
   21.30          size_t size,
   21.31 -        char *fpr,
   21.32 +        const char *fpr,
   21.33          message **result
   21.34      )
   21.35  {
    22.1 --- a/src/baseprotocol.h	Thu Mar 28 15:40:45 2019 +0100
    22.2 +++ b/src/baseprotocol.h	Fri May 17 17:30:57 2019 +0200
    22.3 @@ -31,7 +31,7 @@
    22.4          message *msg,
    22.5          char *payload,
    22.6          size_t size,
    22.7 -        char *fpr
    22.8 +        const char *fpr
    22.9      );
   22.10  
   22.11  
   22.12 @@ -59,7 +59,7 @@
   22.13          const pEp_identity *partner,
   22.14          char *payload,
   22.15          size_t size,
   22.16 -        char *fpr,
   22.17 +        const char *fpr,
   22.18          message **result
   22.19      );
   22.20  
    23.1 --- a/src/cryptotech.c	Thu Mar 28 15:40:45 2019 +0100
    23.2 +++ b/src/cryptotech.c	Fri May 17 17:30:57 2019 +0200
    23.3 @@ -58,6 +58,7 @@
    23.4          cryptotech[PEP_crypt_OpenPGP].key_created = pgp_key_created;
    23.5          cryptotech[PEP_crypt_OpenPGP].contains_priv_key = pgp_contains_priv_key;
    23.6          cryptotech[PEP_crypt_OpenPGP].find_private_keys = pgp_find_private_keys;
    23.7 +        cryptotech[PEP_crypt_OpenPGP].config_cipher_suite = pgp_config_cipher_suite;
    23.8  #ifdef PGP_BINARY_PATH
    23.9          cryptotech[PEP_crypt_OpenPGP].binary_path = PGP_BINARY_PATH;
   23.10  #endif
    24.1 --- a/src/cryptotech.h	Thu Mar 28 15:40:45 2019 +0100
    24.2 +++ b/src/cryptotech.h	Fri May 17 17:30:57 2019 +0200
    24.3 @@ -95,6 +95,9 @@
    24.4      PEP_SESSION session, const char *pattern, stringlist_t **keylist
    24.5  );
    24.6  
    24.7 +typedef PEP_STATUS (*config_cipher_suite_t)(PEP_SESSION session,
    24.8 +        PEP_CIPHER_SUITE suite);
    24.9 +
   24.10  typedef struct _PEP_cryptotech_t {
   24.11      uint8_t id;
   24.12      // the following are default values; comm_type may vary with key length or b0rken crypto
   24.13 @@ -121,6 +124,7 @@
   24.14      binary_path_t binary_path;
   24.15      contains_priv_key_t contains_priv_key;
   24.16      find_private_keys_t find_private_keys;
   24.17 +    config_cipher_suite_t config_cipher_suite;
   24.18  } PEP_cryptotech_t;
   24.19  
   24.20  extern PEP_cryptotech_t cryptotech[PEP_crypt__count];
   24.21 @@ -129,3 +133,4 @@
   24.22  
   24.23  PEP_STATUS init_cryptotech(PEP_SESSION session, bool in_first);
   24.24  void release_cryptotech(PEP_SESSION session, bool out_last);
   24.25 +
    25.1 --- a/src/etpan_mime.c	Thu Mar 28 15:40:45 2019 +0100
    25.2 +++ b/src/etpan_mime.c	Fri May 17 17:30:57 2019 +0200
    25.3 @@ -6,7 +6,11 @@
    25.4  #include <libetpan/mailprivacy_tools.h>
    25.5  #endif
    25.6  
    25.7 +#include "pEp_internal.h"
    25.8  #include "platform.h"
    25.9 +#include "mime.h"
   25.10 +#include "wrappers.h"
   25.11 +#include "resource_id.h"
   25.12  
   25.13  #include <string.h>
   25.14  #include <stdlib.h>
   25.15 @@ -935,3 +939,1767 @@
   25.16      }    
   25.17      return false;
   25.18  }
   25.19 +
   25.20 +#define TMP_TEMPLATE "pEp.XXXXXXXXXXXXXXXXXXXX"
   25.21 +#ifdef _WIN32
   25.22 +#define PATH_SEP '\\'
   25.23 +#else
   25.24 +#define PATH_SEP '/'
   25.25 +#endif
   25.26 +
   25.27 +static PEP_STATUS interpret_MIME(struct mailmime *mime,
   25.28 +                                 message *msg);
   25.29 +
   25.30 +// This function was rewritten to use in-memory buffers instead of
   25.31 +// temporary files when the pgp/mime support was implemented for
   25.32 +// outlook, as the existing code did not work well on windows.
   25.33 +
   25.34 +static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
   25.35 +{
   25.36 +    PEP_STATUS status = PEP_STATUS_OK;
   25.37 +    int col;
   25.38 +    int r;
   25.39 +	size_t len;
   25.40 +	char* buf = NULL;
   25.41 +
   25.42 +	MMAPString* buffer;
   25.43 +
   25.44 +	buffer = mmap_string_new(NULL);
   25.45 +	if (buffer == NULL)
   25.46 +		goto enomem;
   25.47 +	
   25.48 +	col = 0;
   25.49 +	r = mailmime_write_mem(buffer, &col, mime);
   25.50 +	assert(r == MAILIMF_NO_ERROR);
   25.51 +	if (r == MAILIMF_ERROR_MEMORY)
   25.52 +		goto enomem;
   25.53 +	else if (r != MAILIMF_NO_ERROR)
   25.54 +		goto err_file;
   25.55 +
   25.56 +	// we overallocate by 1 byte, so we have a terminating 0.
   25.57 +	len = buffer->len;
   25.58 +	buf = calloc(len + 1, 1);
   25.59 +	if (buf == NULL)
   25.60 +		goto enomem;
   25.61 +
   25.62 +	memcpy(buf, buffer->str, len);
   25.63 +	mmap_string_free(buffer);
   25.64 +
   25.65 +    *mimetext = buf;
   25.66 +    return PEP_STATUS_OK;
   25.67 +
   25.68 +err_file:
   25.69 +    status = PEP_CANNOT_CREATE_TEMP_FILE;
   25.70 +    goto pEp_error;
   25.71 +
   25.72 +enomem:
   25.73 +    status = PEP_OUT_OF_MEMORY;
   25.74 +
   25.75 +pEp_error:
   25.76 +	if (buffer)
   25.77 +		mmap_string_free(buffer);
   25.78 +	if (buf)
   25.79 +		free(buf);
   25.80 +    return status;
   25.81 +}
   25.82 +
   25.83 +static PEP_STATUS mime_attachment(
   25.84 +        bloblist_t *blob,
   25.85 +        struct mailmime **result,
   25.86 +        bool transport_encode
   25.87 +    )
   25.88 +{
   25.89 +    PEP_STATUS status = PEP_STATUS_OK;
   25.90 +    struct mailmime * mime = NULL;
   25.91 +    char * mime_type;
   25.92 +    assert(blob);
   25.93 +    assert(result);
   25.94 +
   25.95 +    *result = NULL;
   25.96 +
   25.97 +// TODO: It seems the pEp COM server adapter sends an empty string here,
   25.98 +// which leads to a crash later. Thus, we workaround here by treating an
   25.99 +// empty string as NULL. We need to check whether the bug really is here,
  25.100 +// or the pEp COM server adapter needs to be changed.
  25.101 +    if (blob->mime_type == NULL || blob->mime_type[0] == '\0')
  25.102 +        mime_type = "application/octet-stream";
  25.103 +    else
  25.104 +        mime_type = blob->mime_type;
  25.105 +
  25.106 +    pEp_rid_list_t* resource = parse_uri(blob->filename);
  25.107 +
  25.108 +    bool already_ascii = !(must_chunk_be_encoded(blob->value, blob->size, true));
  25.109 +
  25.110 +    mime = get_file_part(resource, mime_type, blob->value, blob->size, 
  25.111 +                          (already_ascii ? false : transport_encode));
  25.112 +    free_rid_list(resource);
  25.113 +    
  25.114 +    assert(mime);
  25.115 +    if (mime == NULL)
  25.116 +        goto enomem;
  25.117 +
  25.118 +    *result = mime;
  25.119 +    return PEP_STATUS_OK;
  25.120 +
  25.121 +enomem:
  25.122 +    status = PEP_OUT_OF_MEMORY;
  25.123 +
  25.124 +    if (mime)
  25.125 +        mailmime_free(mime);
  25.126 +
  25.127 +    return status;
  25.128 +}
  25.129 +
  25.130 +static PEP_STATUS mime_html_text(
  25.131 +        const char *plaintext,
  25.132 +        const char *htmltext,
  25.133 +        bloblist_t *attachments,
  25.134 +        struct mailmime **result,
  25.135 +        bool transport_encode
  25.136 +    )
  25.137 +{
  25.138 +    PEP_STATUS status = PEP_STATUS_OK;
  25.139 +    struct mailmime * top_level_html_mime = NULL;
  25.140 +    struct mailmime * mime = NULL;
  25.141 +    struct mailmime * submime = NULL;
  25.142 +    int r;
  25.143 +
  25.144 +    assert(plaintext);
  25.145 +    assert(htmltext);
  25.146 +    assert(result);
  25.147 +
  25.148 +    *result = NULL;
  25.149 +
  25.150 +    mime = part_multiple_new("multipart/alternative");
  25.151 +    assert(mime);
  25.152 +    if (mime == NULL)
  25.153 +        goto enomem;
  25.154 +
  25.155 +    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
  25.156 +    
  25.157 +    int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  25.158 +    submime = get_text_part(NULL, "text/plain", plaintext, strlen(plaintext),
  25.159 +            encoding_type);
  25.160 +    free_rid_list(resource);
  25.161 +    resource = NULL;
  25.162 +    
  25.163 +    assert(submime);
  25.164 +    if (submime == NULL)
  25.165 +        goto enomem;
  25.166 +
  25.167 +    r = mailmime_smart_add_part(mime, submime);
  25.168 +    assert(r == MAILIMF_NO_ERROR);
  25.169 +    if (r == MAILIMF_ERROR_MEMORY) {
  25.170 +        goto enomem;
  25.171 +    }
  25.172 +    else {
  25.173 +        // mailmime_smart_add_part() takes ownership of submime
  25.174 +        submime = NULL;
  25.175 +    }
  25.176 +
  25.177 +    bool inlined_attachments = false;
  25.178 +    
  25.179 +    bloblist_t* traversal_ptr = attachments;
  25.180 +    
  25.181 +    while (traversal_ptr) {
  25.182 +        if (traversal_ptr->disposition == PEP_CONTENT_DISP_INLINE) {
  25.183 +            inlined_attachments = true;
  25.184 +            break;
  25.185 +        }
  25.186 +        traversal_ptr = traversal_ptr->next;
  25.187 +    }
  25.188 +
  25.189 +    if (inlined_attachments) {
  25.190 +        /* Noooooo... dirk, why do you do this to me? */
  25.191 +        submime = part_multiple_new("multipart/related");
  25.192 +        assert(submime);
  25.193 +        if (submime == NULL)
  25.194 +            goto enomem;
  25.195 +
  25.196 +        top_level_html_mime = submime;
  25.197 +        
  25.198 +        r = mailmime_smart_add_part(mime, top_level_html_mime);
  25.199 +        assert(r == MAILIMF_NO_ERROR);
  25.200 +        if (r == MAILIMF_ERROR_MEMORY) {
  25.201 +            goto enomem;
  25.202 +        }
  25.203 +        else {
  25.204 +            // mailmime_smart_add_part() takes ownership of submime
  25.205 +            submime = NULL;
  25.206 +        }
  25.207 +    }
  25.208 +    else {
  25.209 +        top_level_html_mime = mime;
  25.210 +    }
  25.211 +
  25.212 +//    resource = new_rid_node(PEP_RID_FILENAME, "msg.html");
  25.213 +    submime = get_text_part(NULL, "text/html", htmltext, strlen(htmltext),
  25.214 +            encoding_type);
  25.215 +    free_rid_list(resource);
  25.216 +    resource = NULL;
  25.217 +    
  25.218 +    assert(submime);
  25.219 +    if (submime == NULL)
  25.220 +        goto enomem;
  25.221 +
  25.222 +    r = mailmime_smart_add_part(top_level_html_mime, submime);
  25.223 +    assert(r == MAILIMF_NO_ERROR);
  25.224 +    if (r == MAILIMF_ERROR_MEMORY)
  25.225 +        goto enomem;
  25.226 +    else {
  25.227 +        // mailmime_smart_add_part() takes ownership of submime
  25.228 +        submime = NULL;
  25.229 +    }
  25.230 +
  25.231 +    bloblist_t *_a;
  25.232 +    for (_a = attachments; _a != NULL; _a = _a->next) {
  25.233 +        if (_a->disposition != PEP_CONTENT_DISP_INLINE)
  25.234 +            continue;
  25.235 +        status = mime_attachment(_a, &submime, transport_encode);
  25.236 +        if (status != PEP_STATUS_OK)
  25.237 +            return PEP_UNKNOWN_ERROR; // FIXME
  25.238 +
  25.239 +        r = mailmime_smart_add_part(top_level_html_mime, submime);
  25.240 +        assert(r == MAILIMF_NO_ERROR);
  25.241 +        if (r == MAILIMF_ERROR_MEMORY) {
  25.242 +            goto enomem;
  25.243 +        }
  25.244 +        else {
  25.245 +            // mailmime_smart_add_part() takes ownership of submime
  25.246 +            submime = NULL;
  25.247 +        }
  25.248 +    }
  25.249 +
  25.250 +    *result = mime;
  25.251 +    return PEP_STATUS_OK;
  25.252 +
  25.253 +enomem:
  25.254 +    status = PEP_OUT_OF_MEMORY;
  25.255 +
  25.256 +    if (mime)
  25.257 +        mailmime_free(mime);
  25.258 +
  25.259 +    if (submime)
  25.260 +        mailmime_free(submime);
  25.261 +
  25.262 +    return status;
  25.263 +}
  25.264 +
  25.265 +
  25.266 +// FIXME: maybe need to add transport_encode field here
  25.267 +static struct mailimf_mailbox * identity_to_mailbox(const pEp_identity *ident)
  25.268 +{
  25.269 +    char *_username = NULL;
  25.270 +    struct mailimf_mailbox *mb;
  25.271 +
  25.272 +    if (!ident->username)
  25.273 +        _username = strdup("");
  25.274 +    else
  25.275 +        _username = must_field_value_be_encoded(ident->username) ?
  25.276 +                    mailmime_encode_subject_header("utf-8", ident->username, 0) : 
  25.277 +                    strdup(ident->username);
  25.278 +                  
  25.279 +    assert(_username);
  25.280 +    if (_username == NULL)
  25.281 +        goto enomem;
  25.282 +
  25.283 +    mb = mailbox_from_string(_username, ident->address);
  25.284 +    if (mb == NULL)
  25.285 +        goto enomem;
  25.286 +
  25.287 +    free(_username);
  25.288 +    _username = NULL;
  25.289 +
  25.290 +    return mb;
  25.291 +
  25.292 +enomem:
  25.293 +    free(_username);
  25.294 +    return NULL;
  25.295 +}
  25.296 +
  25.297 +static struct mailimf_mailbox_list * identity_to_mbl(
  25.298 +        const pEp_identity *ident)
  25.299 +{
  25.300 +    struct mailimf_mailbox_list *mbl = NULL;
  25.301 +    struct mailimf_mailbox *mb = NULL;
  25.302 +    clist *list = NULL;
  25.303 +    int r;
  25.304 +
  25.305 +    assert(ident);
  25.306 +
  25.307 +    list = clist_new();
  25.308 +    if (list == NULL)
  25.309 +        goto enomem;
  25.310 +
  25.311 +    mb = identity_to_mailbox(ident);
  25.312 +    if (mb == NULL)
  25.313 +        goto enomem;
  25.314 +
  25.315 +    r = clist_append(list, mb);
  25.316 +    if (r)
  25.317 +        goto enomem;
  25.318 +
  25.319 +    mbl = mailimf_mailbox_list_new(list);
  25.320 +    if (mbl == NULL)
  25.321 +        goto enomem;
  25.322 +
  25.323 +    return mbl;
  25.324 +
  25.325 +enomem:
  25.326 +    if (mb)
  25.327 +        mailimf_mailbox_free(mb);
  25.328 +
  25.329 +    if (list)
  25.330 +        clist_free(list);
  25.331 +
  25.332 +    return NULL;
  25.333 +}
  25.334 +
  25.335 +static struct mailimf_address_list * identity_list_to_mal(identity_list *il)
  25.336 +{
  25.337 +    struct mailimf_address_list *mal = NULL;
  25.338 +    struct mailimf_mailbox *mb = NULL;
  25.339 +    struct mailimf_address * addr = NULL;
  25.340 +    clist *list = NULL;
  25.341 +    int r;
  25.342 +
  25.343 +    assert(il);
  25.344 +
  25.345 +    list = clist_new();
  25.346 +    if (list == NULL)
  25.347 +        goto enomem;
  25.348 +
  25.349 +    identity_list *_il;
  25.350 +    for (_il = il; _il && _il->ident; _il = _il->next) {
  25.351 +        mb = identity_to_mailbox(_il->ident);
  25.352 +        if (mb == NULL)
  25.353 +            goto enomem;
  25.354 +
  25.355 +        addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  25.356 +        if (addr == NULL)
  25.357 +            goto enomem;
  25.358 +        mb = NULL;
  25.359 +
  25.360 +        r = clist_append(list, addr);
  25.361 +        if (r)
  25.362 +            goto enomem;
  25.363 +        addr = NULL;
  25.364 +    }
  25.365 +    mal = mailimf_address_list_new(list);
  25.366 +    if (mal == NULL)
  25.367 +        goto enomem;
  25.368 +
  25.369 +    return mal;
  25.370 +
  25.371 +enomem:
  25.372 +    if (mb)
  25.373 +        mailimf_mailbox_free(mb);
  25.374 +
  25.375 +    if (addr)
  25.376 +        mailimf_address_free(addr);
  25.377 +
  25.378 +    if (list)
  25.379 +        clist_free(list);
  25.380 +
  25.381 +    return NULL;
  25.382 +}
  25.383 +
  25.384 +static clist * stringlist_to_clist(stringlist_t *sl, bool transport_encode)
  25.385 +{
  25.386 +    clist * cl = clist_new();
  25.387 +    assert(cl);
  25.388 +    if (cl == NULL)
  25.389 +        return NULL;
  25.390 +
  25.391 +    if (!sl || ((!sl->value || sl->value[0] == '\0') && sl->next == NULL))
  25.392 +        return cl;
  25.393 +        
  25.394 +    stringlist_t *_sl;
  25.395 +    for (_sl = sl; _sl; _sl = _sl->next) {
  25.396 +        int r;
  25.397 +        char * value = ((transport_encode && must_field_value_be_encoded(_sl->value)) ?
  25.398 +                        mailmime_encode_subject_header("utf-8", _sl->value, 0) :
  25.399 +                        strdup(_sl->value));
  25.400 +        assert(value);
  25.401 +        if (value == NULL) {
  25.402 +            clist_free(cl);
  25.403 +            return NULL;
  25.404 +        }
  25.405 +        r = clist_append(cl, value);
  25.406 +        assert(r == 0);
  25.407 +        if (r) {
  25.408 +            free(value);
  25.409 +            clist_free(cl);
  25.410 +            return NULL;
  25.411 +        }
  25.412 +    }
  25.413 +
  25.414 +    return cl;
  25.415 +}
  25.416 +
  25.417 +static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
  25.418 +{
  25.419 +    PEP_STATUS status = PEP_STATUS_OK;
  25.420 +    struct mailimf_fields * fields = NULL;
  25.421 +    int r;
  25.422 +    clist * fields_list = NULL;
  25.423 +    unsigned char pEpstr[] = PEP_SUBJ_STRING; // unsigned due to UTF-8 byte fun
  25.424 +#ifdef WIN32
  25.425 +    char* altstr = "pEp";
  25.426 +#else
  25.427 +    char* altstr = (char*)pEpstr;
  25.428 +#endif        
  25.429 +    char *subject = msg->shortmsg ? msg->shortmsg : altstr;
  25.430 +
  25.431 +    assert(msg);
  25.432 +    assert(result);
  25.433 +
  25.434 +    *result = NULL;
  25.435 +
  25.436 +    fields_list = clist_new();
  25.437 +    assert(fields_list);
  25.438 +    if (fields_list == NULL)
  25.439 +        goto enomem;
  25.440 +
  25.441 +    if (msg->id) {
  25.442 +        char *_msgid = strdup(msg->id);
  25.443 +        assert(_msgid);
  25.444 +        if (_msgid == NULL)
  25.445 +            goto enomem;
  25.446 +
  25.447 +        r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
  25.448 +                (_new_func_t) mailimf_message_id_new, _msgid);
  25.449 +        if (r) {
  25.450 +            free(_msgid);
  25.451 +            goto enomem;
  25.452 +        }
  25.453 +    }
  25.454 +
  25.455 +    if (msg->sent) {
  25.456 +        struct mailimf_date_time * dt = timestamp_to_etpantime(msg->sent);
  25.457 +        if (dt == NULL)
  25.458 +            goto enomem;
  25.459 +
  25.460 +        r = _append_field(fields_list, MAILIMF_FIELD_ORIG_DATE,
  25.461 +                (_new_func_t) mailimf_orig_date_new, dt);
  25.462 +        if (r) {
  25.463 +            mailimf_date_time_free(dt);
  25.464 +            goto enomem;
  25.465 +        }
  25.466 +        dt = NULL;
  25.467 +    }
  25.468 +
  25.469 +     if (msg->from) {
  25.470 +        struct mailimf_mailbox_list *from = identity_to_mbl(msg->from);
  25.471 +        if (from == NULL)
  25.472 +            goto enomem;
  25.473 +
  25.474 +        r = _append_field(fields_list, MAILIMF_FIELD_FROM,
  25.475 +                (_new_func_t) mailimf_from_new, from);
  25.476 +        if (r) {
  25.477 +            mailimf_mailbox_list_free(from);
  25.478 +            goto enomem;
  25.479 +        }
  25.480 +    }
  25.481 +
  25.482 +    if (msg->to) {
  25.483 +        struct mailimf_address_list *to = identity_list_to_mal(msg->to);
  25.484 +        if (to == NULL)
  25.485 +            goto enomem;
  25.486 +
  25.487 +        r = _append_field(fields_list, MAILIMF_FIELD_TO,
  25.488 +                (_new_func_t) mailimf_to_new, to);
  25.489 +        if (r) {
  25.490 +            mailimf_address_list_free(to);
  25.491 +            goto enomem;
  25.492 +        }
  25.493 +    }
  25.494 +
  25.495 +    char* _subject = NULL;
  25.496 +    if (!must_field_value_be_encoded(subject)) {
  25.497 +        _subject = strdup(subject);
  25.498 +        assert(_subject);
  25.499 +    }
  25.500 +    else {
  25.501 +        _subject = mailmime_encode_subject_header("utf-8", subject, 1);
  25.502 +    }
  25.503 +    if (_subject == NULL)
  25.504 +        goto enomem;
  25.505 +
  25.506 +    r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
  25.507 +            (_new_func_t) mailimf_subject_new, _subject);
  25.508 +    if (r) {
  25.509 +        free(_subject);
  25.510 +        goto enomem;
  25.511 +    }
  25.512 +
  25.513 +    if (msg->cc) {
  25.514 +        struct mailimf_address_list *cc = identity_list_to_mal(msg->cc);
  25.515 +        if (cc == NULL)
  25.516 +            goto enomem;
  25.517 +
  25.518 +        r = _append_field(fields_list, MAILIMF_FIELD_CC,
  25.519 +                (_new_func_t) mailimf_cc_new, cc);
  25.520 +        if (r) {
  25.521 +            mailimf_address_list_free(cc);
  25.522 +            goto enomem;
  25.523 +        }
  25.524 +    }
  25.525 +    
  25.526 +    if (msg->bcc) {
  25.527 +        struct mailimf_address_list *bcc = identity_list_to_mal(msg->bcc);
  25.528 +        if (bcc == NULL)
  25.529 +            goto enomem;
  25.530 +
  25.531 +        r = _append_field(fields_list, MAILIMF_FIELD_BCC,
  25.532 +                (_new_func_t) mailimf_bcc_new, bcc);
  25.533 +        if (r) {
  25.534 +            mailimf_address_list_free(bcc);
  25.535 +            goto enomem;
  25.536 +        }
  25.537 +    }
  25.538 +    
  25.539 +    if (msg->reply_to) {
  25.540 +        struct mailimf_address_list *reply_to = identity_list_to_mal(msg->reply_to);
  25.541 +        if (reply_to == NULL)
  25.542 +            goto enomem;
  25.543 +
  25.544 +        r = _append_field(fields_list, MAILIMF_FIELD_REPLY_TO,
  25.545 +                (_new_func_t) mailimf_reply_to_new, reply_to);
  25.546 +        if (r) {
  25.547 +            mailimf_address_list_free(reply_to);
  25.548 +            goto enomem;
  25.549 +        }
  25.550 +    }
  25.551 +
  25.552 +    if (msg->in_reply_to) {
  25.553 +        clist *in_reply_to = stringlist_to_clist(msg->in_reply_to, true);
  25.554 +        if (in_reply_to == NULL)
  25.555 +            goto enomem;
  25.556 +
  25.557 +        r = _append_field(fields_list, MAILIMF_FIELD_IN_REPLY_TO,
  25.558 +                (_new_func_t) mailimf_in_reply_to_new, in_reply_to);
  25.559 +        if (r) {
  25.560 +            clist_free(in_reply_to);
  25.561 +            goto enomem;
  25.562 +        }
  25.563 +    }
  25.564 +
  25.565 +    if (msg->references) {
  25.566 +        clist *references = stringlist_to_clist(msg->references, true);
  25.567 +        if (references == NULL)
  25.568 +            goto enomem;
  25.569 +
  25.570 +        r = _append_field(fields_list, MAILIMF_FIELD_REFERENCES,
  25.571 +                (_new_func_t) mailimf_references_new, references);
  25.572 +        if (r) {
  25.573 +            clist_free(references);
  25.574 +            goto enomem;
  25.575 +        }
  25.576 +    }
  25.577 +
  25.578 +    if (msg->keywords) {
  25.579 +        clist *keywords = stringlist_to_clist(msg->keywords, true);
  25.580 +        if (keywords == NULL)
  25.581 +            goto enomem;
  25.582 +
  25.583 +        r = _append_field(fields_list, MAILIMF_FIELD_KEYWORDS,
  25.584 +                (_new_func_t) mailimf_keywords_new, keywords);
  25.585 +        if (r) {
  25.586 +            clist_free(keywords);
  25.587 +            goto enomem;
  25.588 +        }
  25.589 +    }
  25.590 +
  25.591 +    if (msg->comments) {
  25.592 +        char *comments = NULL;
  25.593 +        if (!must_field_value_be_encoded(msg->comments)) {
  25.594 +            comments = strdup(msg->comments);
  25.595 +            assert(comments);
  25.596 +        }
  25.597 +        else  {
  25.598 +            comments = mailmime_encode_subject_header("utf-8", msg->comments, 0);
  25.599 +        }
  25.600 +        if (comments == NULL)
  25.601 +            goto enomem;
  25.602 +
  25.603 +        r = _append_field(fields_list, MAILIMF_FIELD_COMMENTS,
  25.604 +                (_new_func_t) mailimf_comments_new, comments);
  25.605 +        if (r) {
  25.606 +            free(comments);
  25.607 +            goto enomem;
  25.608 +        }
  25.609 +    }
  25.610 +
  25.611 +    if (msg->opt_fields) {
  25.612 +        stringpair_list_t *_l;
  25.613 +        for (_l = msg->opt_fields; _l && _l->value; _l = _l->next) {
  25.614 +            char *key = _l->value->key;
  25.615 +            char *value = _l->value->value;
  25.616 +            if (key && value) {
  25.617 +                r = _append_optional_field(fields_list, key, value);
  25.618 +
  25.619 +                if (r)
  25.620 +                    goto enomem;
  25.621 +            }
  25.622 +        }
  25.623 +    }
  25.624 +
  25.625 +    fields = mailimf_fields_new(fields_list);
  25.626 +    assert(fields);
  25.627 +    if (fields == NULL)
  25.628 +        goto enomem;
  25.629 +
  25.630 +    *result = fields;
  25.631 +
  25.632 +    return PEP_STATUS_OK;
  25.633 +
  25.634 +enomem:
  25.635 +    status = PEP_OUT_OF_MEMORY;
  25.636 +
  25.637 +    if (fields_list)
  25.638 +        clist_free(fields_list);
  25.639 +
  25.640 +    if (fields)
  25.641 +        mailimf_fields_free(fields);
  25.642 +
  25.643 +    return status;
  25.644 +}
  25.645 +
  25.646 +static bool has_exceptional_extension(char* filename) {
  25.647 +    if (!filename)
  25.648 +        return false;
  25.649 +    int len = strlen(filename);
  25.650 +    if (len < 4)
  25.651 +        return false;
  25.652 +    char* ext_start = filename + (len - 4);
  25.653 +    if (strcmp(ext_start, ".pgp") == 0 || strcmp(ext_start, ".gpg") == 0 ||
  25.654 +        strcmp(ext_start, ".asc") == 0 || strcmp(ext_start, ".pEp") == 0)
  25.655 +        return true;
  25.656 +    return false;
  25.657 +}
  25.658 +
  25.659 +static pEp_rid_list_t* choose_resource_id(pEp_rid_list_t* rid_list) {
  25.660 +    pEp_rid_list_t* retval = rid_list;
  25.661 +    
  25.662 +    /* multiple elements - least common case */
  25.663 +    if (rid_list && rid_list->next) {
  25.664 +        pEp_rid_list_t* rid_list_curr = rid_list;
  25.665 +        retval = rid_list; 
  25.666 +        
  25.667 +        while (rid_list_curr) {
  25.668 +            pEp_resource_id_type rid_type = rid_list_curr->rid_type;
  25.669 +            if (rid_type == PEP_RID_CID)
  25.670 +                retval = rid_list_curr;
  25.671 +            else if (rid_type == PEP_RID_FILENAME && has_exceptional_extension(rid_list_curr->rid))
  25.672 +                return rid_list_curr;
  25.673 +            rid_list_curr = rid_list_curr->next;
  25.674 +        }
  25.675 +    } 
  25.676 +    return retval;
  25.677 +}
  25.678 +
  25.679 +// static void split_inlined_and_attached(bloblist_t** inlined, bloblist_t** attached) {
  25.680 +//     bloblist_t** curr_pp = attached;
  25.681 +//     bloblist_t* curr = *curr_pp;
  25.682 +//     
  25.683 +//     bloblist_t* inline_ret = NULL;
  25.684 +//     bloblist_t** inline_curr_pp = &inline_ret;
  25.685 +//     
  25.686 +//     bloblist_t* att_ret = NULL;
  25.687 +//     bloblist_t** att_curr_pp = &att_ret;
  25.688 +//     
  25.689 +//     while (curr) {
  25.690 +//         if (curr->disposition == PEP_CONTENT_DISP_INLINE) {
  25.691 +//             *inline_curr_pp = curr;
  25.692 +//             inline_curr_pp = &(curr->next);
  25.693 +//         }
  25.694 +//         else {
  25.695 +//             *att_curr_pp = curr;
  25.696 +//             att_curr_pp = &(curr->next);            
  25.697 +//         }
  25.698 +//         *curr_pp = curr->next;
  25.699 +//         curr->next = NULL;
  25.700 +//         curr = *curr_pp;
  25.701 +//     }
  25.702 +//     
  25.703 +//     *inlined = inline_ret;
  25.704 +//     *attached = att_ret;
  25.705 +// }
  25.706 +
  25.707 +
  25.708 +static PEP_STATUS mime_encode_message_plain(
  25.709 +        const message *msg,
  25.710 +        bool omit_fields,
  25.711 +        struct mailmime **result,
  25.712 +        bool transport_encode
  25.713 +    )
  25.714 +{
  25.715 +    struct mailmime * mime = NULL;
  25.716 +    struct mailmime * submime = NULL;
  25.717 +    int r;
  25.718 +    PEP_STATUS status;
  25.719 +    //char *subject;
  25.720 +    char *plaintext;
  25.721 +    char *htmltext;
  25.722 +
  25.723 +    assert(msg);
  25.724 +    assert(result);
  25.725 +    
  25.726 +    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp";  // not used, yet.
  25.727 +    plaintext = (msg->longmsg) ? msg->longmsg : "";
  25.728 +    htmltext = msg->longmsg_formatted;
  25.729 +
  25.730 +    if (htmltext && (htmltext[0] != '\0')) {
  25.731 +        /* first, we need to strip out the inlined attachments to ensure this
  25.732 +           gets set up correctly */
  25.733 +           
  25.734 +        status = mime_html_text(plaintext, htmltext, msg->attachments, &mime,
  25.735 +                                transport_encode);
  25.736 +                
  25.737 +        if (status != PEP_STATUS_OK)
  25.738 +            goto pEp_error;
  25.739 +    }
  25.740 +    else {
  25.741 +        pEp_rid_list_t* resource = NULL;
  25.742 +        if (is_PGP_message_text(plaintext)) {
  25.743 +            resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
  25.744 +            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_7BIT : 0);
  25.745 +            mime = get_text_part(resource, "application/octet-stream", plaintext,
  25.746 +                    strlen(plaintext), encoding_type);
  25.747 +        }
  25.748 +        else {
  25.749 +            resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
  25.750 +            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  25.751 +            mime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
  25.752 +                    encoding_type);
  25.753 +        }
  25.754 +        free_rid_list(resource);
  25.755 +        
  25.756 +        assert(mime);
  25.757 +        if (mime == NULL)
  25.758 +            goto enomem;
  25.759 +    }
  25.760 +
  25.761 +    bool normal_attachments = false;
  25.762 +    
  25.763 +    bloblist_t* traversal_ptr = msg->attachments;
  25.764 +    
  25.765 +    while (traversal_ptr) {
  25.766 +        if (traversal_ptr->disposition != PEP_CONTENT_DISP_INLINE) {
  25.767 +            normal_attachments = true;
  25.768 +            break;
  25.769 +        }
  25.770 +        traversal_ptr = traversal_ptr->next;
  25.771 +    }
  25.772 +
  25.773 +    if (normal_attachments) {
  25.774 +        submime = mime;
  25.775 +        mime = part_multiple_new("multipart/mixed");
  25.776 +        assert(mime);
  25.777 +        if (mime == NULL)
  25.778 +            goto enomem;
  25.779 +
  25.780 +        r = mailmime_smart_add_part(mime, submime);
  25.781 +        assert(r == MAILIMF_NO_ERROR);
  25.782 +        if (r == MAILIMF_ERROR_MEMORY) {
  25.783 +            goto enomem;
  25.784 +        }
  25.785 +        else {
  25.786 +            // mailmime_smart_add_part() takes ownership of submime
  25.787 +            submime = NULL;
  25.788 +        }
  25.789 +
  25.790 +        bloblist_t *_a;
  25.791 +        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
  25.792 +
  25.793 +            if (_a->disposition == PEP_CONTENT_DISP_INLINE)
  25.794 +                continue;
  25.795 +
  25.796 +            status = mime_attachment(_a, &submime, transport_encode);
  25.797 +            if (status != PEP_STATUS_OK)
  25.798 +                goto pEp_error;
  25.799 +
  25.800 +            r = mailmime_smart_add_part(mime, submime);
  25.801 +            assert(r == MAILIMF_NO_ERROR);
  25.802 +            if (r == MAILIMF_ERROR_MEMORY) {
  25.803 +                goto enomem;
  25.804 +            }
  25.805 +            else {
  25.806 +                // mailmime_smart_add_part() takes ownership of submime
  25.807 +                submime = NULL;
  25.808 +            }
  25.809 +        }
  25.810 +    }
  25.811 +
  25.812 +    *result = mime;
  25.813 +    return PEP_STATUS_OK;
  25.814 +
  25.815 +enomem:
  25.816 +    status = PEP_OUT_OF_MEMORY;
  25.817 +
  25.818 +pEp_error:
  25.819 +    if (mime)
  25.820 +        mailmime_free(mime);
  25.821 +
  25.822 +    if (submime)
  25.823 +        mailmime_free(submime);
  25.824 +
  25.825 +    return status;
  25.826 +}
  25.827 +
  25.828 +static PEP_STATUS mime_encode_message_PGP_MIME(
  25.829 +        const message * msg,
  25.830 +        bool omit_fields,
  25.831 +        struct mailmime **result
  25.832 +    )
  25.833 +{
  25.834 +    struct mailmime * mime = NULL;
  25.835 +    struct mailmime * submime = NULL;
  25.836 +	struct mailmime_parameter * param;
  25.837 +    int r;
  25.838 +    PEP_STATUS status;
  25.839 +    char *plaintext;
  25.840 +    size_t plaintext_size;
  25.841 +
  25.842 +    assert(msg->attachments && msg->attachments->next &&
  25.843 +            msg->attachments->next->value);
  25.844 +
  25.845 +    plaintext = msg->attachments->next->value;
  25.846 +    plaintext_size = msg->attachments->next->size;
  25.847 +
  25.848 +    mime = part_multiple_new("multipart/encrypted");
  25.849 +    assert(mime);
  25.850 +    if (mime == NULL)
  25.851 +        goto enomem;
  25.852 +
  25.853 +    param = mailmime_param_new_with_data("protocol", "application/pgp-encrypted");
  25.854 +    clist_append(mime->mm_content_type->ct_parameters, param);
  25.855 +
  25.856 +    submime = get_pgp_encrypted_part();
  25.857 +    assert(submime);
  25.858 +    if (submime == NULL)
  25.859 +        goto enomem;
  25.860 +
  25.861 +    r = mailmime_smart_add_part(mime, submime);
  25.862 +    assert(r == MAILIMF_NO_ERROR);
  25.863 +    if (r == MAILIMF_ERROR_MEMORY) {
  25.864 +        goto enomem;
  25.865 +    }
  25.866 +    else {
  25.867 +        // mailmime_smart_add_part() takes ownership of submime
  25.868 +        submime = NULL;
  25.869 +    }
  25.870 +
  25.871 +    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
  25.872 +    submime = get_text_part(resource, "application/octet-stream", plaintext,
  25.873 +            plaintext_size, MAILMIME_MECHANISM_7BIT);
  25.874 +            
  25.875 +    free_rid_list(resource);
  25.876 +    
  25.877 +    assert(submime);
  25.878 +    if (submime == NULL)
  25.879 +        goto enomem;
  25.880 +
  25.881 +    r = mailmime_smart_add_part(mime, submime);
  25.882 +    assert(r == MAILIMF_NO_ERROR);
  25.883 +    if (r == MAILIMF_ERROR_MEMORY) {
  25.884 +        goto enomem;
  25.885 +    }
  25.886 +    else {
  25.887 +        // mailmime_smart_add_part() takes ownership of submime
  25.888 +        submime = NULL;
  25.889 +    }
  25.890 +
  25.891 +    *result = mime;
  25.892 +    return PEP_STATUS_OK;
  25.893 +
  25.894 +enomem:
  25.895 +    status = PEP_OUT_OF_MEMORY;
  25.896 +
  25.897 +    if (mime)
  25.898 +        mailmime_free(mime);
  25.899 +
  25.900 +    if (submime)
  25.901 +        mailmime_free(submime);
  25.902 +
  25.903 +    return status;
  25.904 +}
  25.905 +
  25.906 +PEP_STATUS _mime_encode_message_internal(
  25.907 +        const message * msg,
  25.908 +        bool omit_fields,
  25.909 +        char **mimetext,
  25.910 +        bool transport_encode
  25.911 +    )
  25.912 +{
  25.913 +    PEP_STATUS status = PEP_STATUS_OK;
  25.914 +    struct mailmime * msg_mime = NULL;
  25.915 +    struct mailmime * mime = NULL;
  25.916 +    struct mailimf_fields * fields = NULL;
  25.917 +    char *buf = NULL;
  25.918 +    int r;
  25.919 +
  25.920 +    assert(msg);
  25.921 +    assert(mimetext);
  25.922 +
  25.923 +    if (!(msg && mimetext))
  25.924 +        return PEP_ILLEGAL_VALUE;
  25.925 +
  25.926 +    *mimetext = NULL;
  25.927 +
  25.928 +    switch (msg->enc_format) {
  25.929 +        case PEP_enc_none:
  25.930 +            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
  25.931 +            break;
  25.932 +
  25.933 +        case PEP_enc_inline:
  25.934 +            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
  25.935 +            break;
  25.936 +
  25.937 +        case PEP_enc_S_MIME:
  25.938 +            NOT_IMPLEMENTED
  25.939 +                
  25.940 +        case PEP_enc_PGP_MIME:
  25.941 +            status = mime_encode_message_PGP_MIME(msg, omit_fields, &mime);
  25.942 +            break;
  25.943 +
  25.944 +        case PEP_enc_PEP:
  25.945 +            NOT_IMPLEMENTED
  25.946 +
  25.947 +        default:
  25.948 +            NOT_IMPLEMENTED
  25.949 +    }
  25.950 +
  25.951 +    if (status != PEP_STATUS_OK)
  25.952 +        goto pEp_error;
  25.953 +
  25.954 +    msg_mime = mailmime_new_message_data(NULL);
  25.955 +    assert(msg_mime);
  25.956 +    if (msg_mime == NULL)
  25.957 +        goto enomem;
  25.958 +
  25.959 +    r = mailmime_add_part(msg_mime, mime);
  25.960 +    if (r) {
  25.961 +        mailmime_free(mime);
  25.962 +        goto enomem;
  25.963 +    }
  25.964 +    mime = NULL;
  25.965 +
  25.966 +    if (!omit_fields) {
  25.967 +        status = build_fields(msg, &fields);
  25.968 +        if (status != PEP_STATUS_OK)
  25.969 +            goto pEp_error;
  25.970 +
  25.971 +        mailmime_set_imf_fields(msg_mime, fields);
  25.972 +    }
  25.973 +
  25.974 +    status = render_mime(msg_mime, &buf);
  25.975 +    if (status != PEP_STATUS_OK)
  25.976 +        goto pEp_error;
  25.977 +
  25.978 +    mailmime_free(msg_mime);
  25.979 +    *mimetext = buf;
  25.980 +
  25.981 +    return PEP_STATUS_OK;
  25.982 +
  25.983 +enomem:
  25.984 +    status = PEP_OUT_OF_MEMORY;
  25.985 +
  25.986 +pEp_error:
  25.987 +    if (msg_mime)
  25.988 +        mailmime_free(msg_mime);
  25.989 +    else
  25.990 +        if (mime)
  25.991 +            mailmime_free(mime);
  25.992 +
  25.993 +    return status;
  25.994 +}
  25.995 +
  25.996 +static pEp_identity *mailbox_to_identity(const struct mailimf_mailbox * mb)
  25.997 +{
  25.998 +    char *username = NULL;
  25.999 +
 25.1000 +    assert(mb);
 25.1001 +    assert(mb->mb_addr_spec);
 25.1002 +
 25.1003 +    if (mb->mb_addr_spec == NULL)
 25.1004 +        return NULL;
 25.1005 +
 25.1006 +    if (mb->mb_display_name) {
 25.1007 +        size_t index = 0;
 25.1008 +        const int r = mailmime_encoded_phrase_parse("utf-8", mb->mb_display_name,
 25.1009 +                strlen(mb->mb_display_name), &index, "utf-8", &username);
 25.1010 +        if (r)
 25.1011 +            goto enomem;
 25.1012 +    }
 25.1013 +
 25.1014 +    pEp_identity *ident = new_identity(mb->mb_addr_spec, NULL, NULL, username);
 25.1015 +    if (ident == NULL)
 25.1016 +        goto enomem;
 25.1017 +    free(username);
 25.1018 +
 25.1019 +    return ident;
 25.1020 +
 25.1021 +enomem:
 25.1022 +    free(username);
 25.1023 +    return NULL;
 25.1024 +}
 25.1025 +
 25.1026 +static pEp_identity * mbl_to_identity(const struct mailimf_mailbox_list * mbl)
 25.1027 +{
 25.1028 +    struct mailimf_mailbox * mb = clist_content(clist_begin(mbl->mb_list));
 25.1029 +    return mailbox_to_identity(mb);
 25.1030 +}
 25.1031 +
 25.1032 +static identity_list * mal_to_identity_list(
 25.1033 +        const struct mailimf_address_list *mal
 25.1034 +    )
 25.1035 +{
 25.1036 +    assert(mal);
 25.1037 +    clist *list = mal->ad_list;
 25.1038 +
 25.1039 +    identity_list *il = new_identity_list(NULL);
 25.1040 +    if (il == NULL)
 25.1041 +        goto enomem;
 25.1042 +
 25.1043 +    identity_list *_il = il;
 25.1044 +    for (clistiter *cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
 25.1045 +        pEp_identity *ident;
 25.1046 +
 25.1047 +        struct mailimf_address *addr = clist_content(cur);
 25.1048 +        switch(addr->ad_type) {
 25.1049 +            case MAILIMF_ADDRESS_MAILBOX:
 25.1050 +                ident = mailbox_to_identity(addr->ad_data.ad_mailbox);
 25.1051 +                if (ident == NULL)
 25.1052 +                    goto enomem;
 25.1053 +                _il = identity_list_add(_il, ident);
 25.1054 +                if (_il == NULL)
 25.1055 +                    goto enomem;
 25.1056 +                break;
 25.1057 +
 25.1058 +            case MAILIMF_ADDRESS_GROUP:
 25.1059 +                {
 25.1060 +                    struct mailimf_mailbox_list * mbl =
 25.1061 +                            addr->ad_data.ad_group->grp_mb_list;
 25.1062 +                    for (clistiter *cur2 = clist_begin(mbl->mb_list); cur2 != NULL;
 25.1063 +                            cur2 = clist_next(cur2)) {
 25.1064 +                        ident = mailbox_to_identity(clist_content(cur));
 25.1065 +                        if (ident == NULL)
 25.1066 +                            goto enomem;
 25.1067 +                        _il = identity_list_add(_il, ident);
 25.1068 +                        if (_il == NULL)
 25.1069 +                            goto enomem;
 25.1070 +                    }
 25.1071 +                }
 25.1072 +                break;
 25.1073 +
 25.1074 +            default:
 25.1075 +                assert(0);
 25.1076 +                goto enomem;
 25.1077 +        }
 25.1078 +    }
 25.1079 +
 25.1080 +    return il;
 25.1081 +
 25.1082 +enomem:
 25.1083 +    free_identity_list(il);
 25.1084 +    return NULL;
 25.1085 +}
 25.1086 +
 25.1087 +static stringlist_t * clist_to_stringlist(const clist *list)
 25.1088 +{
 25.1089 +    char *text = NULL;;
 25.1090 +    stringlist_t * sl = new_stringlist(NULL);
 25.1091 +    if (sl == NULL)
 25.1092 +        return NULL;
 25.1093 +
 25.1094 +    stringlist_t *_sl = sl;
 25.1095 +    for (clistiter *cur = clist_begin(list); cur != NULL; cur = clist_next(cur)) {
 25.1096 +        char *phrase = clist_content(cur);
 25.1097 +        size_t index = 0;
 25.1098 +        
 25.1099 +        const int r = mailmime_encoded_phrase_parse("utf-8", phrase, strlen(phrase),
 25.1100 +                &index, "utf-8", &text);
 25.1101 +        if (r)
 25.1102 +            goto enomem;
 25.1103 +
 25.1104 +        _sl = stringlist_add(_sl, text);
 25.1105 +        if (_sl == NULL)
 25.1106 +            goto enomem;
 25.1107 +
 25.1108 +        free(text);
 25.1109 +        text = NULL;
 25.1110 +    }
 25.1111 +
 25.1112 +    return sl;
 25.1113 +
 25.1114 +enomem:
 25.1115 +    free_stringlist(sl);
 25.1116 +    free(text);
 25.1117 +
 25.1118 +    return NULL;
 25.1119 +}
 25.1120 +
 25.1121 +static PEP_STATUS read_fields(message *msg, clist *fieldlist)
 25.1122 +{
 25.1123 +    PEP_STATUS status = PEP_STATUS_OK;
 25.1124 +    struct mailimf_field * _field;
 25.1125 +    clistiter *cur;
 25.1126 +    size_t index;
 25.1127 +    int r;
 25.1128 +    
 25.1129 +    stringpair_list_t *opt = msg->opt_fields;
 25.1130 +
 25.1131 +    if (!fieldlist)
 25.1132 +        return PEP_STATUS_OK;
 25.1133 +        
 25.1134 +    for (cur = clist_begin(fieldlist); cur != NULL; cur = clist_next(cur)) {
 25.1135 +        _field = clist_content(cur);
 25.1136 +
 25.1137 +        switch (_field->fld_type) {
 25.1138 +            case MAILIMF_FIELD_MESSAGE_ID:
 25.1139 +                {
 25.1140 +                    char * text = _field->fld_data.fld_message_id->mid_value;
 25.1141 +
 25.1142 +                    free(msg->id);
 25.1143 +                    index = 0;
 25.1144 +                    r = mailmime_encoded_phrase_parse("utf-8", text,
 25.1145 +                            strlen(text), &index, "utf-8", &msg->id);
 25.1146 +                    if (r)
 25.1147 +                        goto enomem;
 25.1148 +                }
 25.1149 +                break;
 25.1150 +
 25.1151 +            case MAILIMF_FIELD_SUBJECT:
 25.1152 +                {
 25.1153 +                    char * text = _field->fld_data.fld_subject->sbj_value;
 25.1154 +
 25.1155 +                    free(msg->shortmsg);
 25.1156 +                    index = 0;
 25.1157 +                    r = mailmime_encoded_phrase_parse("utf-8", text,
 25.1158 +                            strlen(text), &index, "utf-8", &msg->shortmsg);
 25.1159 +                    if (r)
 25.1160 +                        goto enomem;
 25.1161 +                }
 25.1162 +                break;
 25.1163 +
 25.1164 +            case MAILIMF_FIELD_ORIG_DATE:
 25.1165 +                {
 25.1166 +                    struct mailimf_date_time *date =
 25.1167 +                        _field->fld_data.fld_orig_date->dt_date_time;
 25.1168 +
 25.1169 +                    free_timestamp(msg->sent);
 25.1170 +                    msg->sent = etpantime_to_timestamp(date);
 25.1171 +                    if (msg->sent == NULL)
 25.1172 +                        goto enomem;
 25.1173 +                }
 25.1174 +                break;
 25.1175 +
 25.1176 +            case MAILIMF_FIELD_FROM:
 25.1177 +                {
 25.1178 +                    struct mailimf_mailbox_list *mbl =
 25.1179 +                            _field->fld_data.fld_from->frm_mb_list;
 25.1180 +                    pEp_identity *ident;
 25.1181 +
 25.1182 +                    ident = mbl_to_identity(mbl);
 25.1183 +                    if (ident == NULL)
 25.1184 +                        goto pEp_error;
 25.1185 +
 25.1186 +                    free_identity(msg->from);
 25.1187 +                    msg->from = ident;
 25.1188 +                }
 25.1189 +                break;
 25.1190 +
 25.1191 +            case MAILIMF_FIELD_TO:
 25.1192 +                {
 25.1193 +                    struct mailimf_address_list *mal =
 25.1194 +                            _field->fld_data.fld_to->to_addr_list;
 25.1195 +                    identity_list *il = mal_to_identity_list(mal);
 25.1196 +                    if (il == NULL)
 25.1197 +                        goto enomem;
 25.1198 +
 25.1199 +                    free_identity_list(msg->to);
 25.1200 +                    msg->to = il;
 25.1201 +                }
 25.1202 +                break;
 25.1203 +
 25.1204 +            case MAILIMF_FIELD_CC:
 25.1205 +                {
 25.1206 +                    struct mailimf_address_list *mal =
 25.1207 +                            _field->fld_data.fld_cc->cc_addr_list;
 25.1208 +                    identity_list *il = mal_to_identity_list(mal);
 25.1209 +                    if (il == NULL)
 25.1210 +                        goto enomem;
 25.1211 +
 25.1212 +                    free_identity_list(msg->cc);
 25.1213 +                    msg->cc = il;
 25.1214 +                }
 25.1215 +                break;
 25.1216 +
 25.1217 +            case MAILIMF_FIELD_BCC:
 25.1218 +                {
 25.1219 +                    struct mailimf_address_list *mal =
 25.1220 +                            _field->fld_data.fld_bcc->bcc_addr_list;
 25.1221 +                    identity_list *il = mal_to_identity_list(mal);
 25.1222 +                    if (il == NULL)
 25.1223 +                        goto enomem;
 25.1224 +
 25.1225 +                    free_identity_list(msg->bcc);
 25.1226 +                    msg->bcc = il;
 25.1227 +                }
 25.1228 +                break;
 25.1229 +
 25.1230 +            case MAILIMF_FIELD_REPLY_TO:
 25.1231 +                {
 25.1232 +                    struct mailimf_address_list *mal =
 25.1233 +                            _field->fld_data.fld_reply_to->rt_addr_list;
 25.1234 +                    identity_list *il = mal_to_identity_list(mal);
 25.1235 +                    if (il == NULL)
 25.1236 +                        goto enomem;
 25.1237 +
 25.1238 +                    free_identity_list(msg->reply_to);
 25.1239 +                    msg->reply_to = il;
 25.1240 +                }
 25.1241 +                break;
 25.1242 +
 25.1243 +            case MAILIMF_FIELD_IN_REPLY_TO:
 25.1244 +                {
 25.1245 +                    clist *list = _field->fld_data.fld_in_reply_to->mid_list;
 25.1246 +                    stringlist_t *sl = clist_to_stringlist(list);
 25.1247 +                    if (sl == NULL)
 25.1248 +                        goto enomem;
 25.1249 +
 25.1250 +                    free_stringlist(msg->in_reply_to);
 25.1251 +                    msg->in_reply_to = sl;
 25.1252 +                }
 25.1253 +                break;
 25.1254 +
 25.1255 +            case MAILIMF_FIELD_REFERENCES:
 25.1256 +                {
 25.1257 +                    clist *list = _field->fld_data.fld_references->mid_list;
 25.1258 +                    stringlist_t *sl = clist_to_stringlist(list);
 25.1259 +                    if (sl == NULL)
 25.1260 +                        goto enomem;
 25.1261 +
 25.1262 +                    free_stringlist(msg->references);
 25.1263 +                    msg->references = sl;
 25.1264 +                }
 25.1265 +                break;
 25.1266 +
 25.1267 +            case MAILIMF_FIELD_KEYWORDS:
 25.1268 +                {
 25.1269 +                    clist *list = _field->fld_data.fld_keywords->kw_list;
 25.1270 +                    stringlist_t *sl = clist_to_stringlist(list);
 25.1271 +                    if (sl == NULL)
 25.1272 +                        goto enomem;
 25.1273 +
 25.1274 +                    free_stringlist(msg->keywords);
 25.1275 +                    msg->keywords = sl;
 25.1276 +                }
 25.1277 +                break;
 25.1278 +
 25.1279 +            case MAILIMF_FIELD_COMMENTS:
 25.1280 +                {
 25.1281 +                    char * text = _field->fld_data.fld_comments->cm_value;
 25.1282 +
 25.1283 +                    free(msg->comments);
 25.1284 +                    index = 0;
 25.1285 +                    r = mailmime_encoded_phrase_parse("utf-8", text,
 25.1286 +                            strlen(text), &index, "utf-8", &msg->comments);
 25.1287 +                    if (r)
 25.1288 +                        goto enomem;
 25.1289 +                }
 25.1290 +                break;
 25.1291 +
 25.1292 +            case MAILIMF_FIELD_OPTIONAL_FIELD:
 25.1293 +                {
 25.1294 +                    char * name =
 25.1295 +                            _field->fld_data.fld_optional_field->fld_name;
 25.1296 +                    char * value =
 25.1297 +                            _field->fld_data.fld_optional_field->fld_value;
 25.1298 +                    char *_value;
 25.1299 +
 25.1300 +                    index = 0;
 25.1301 +                    r = mailmime_encoded_phrase_parse("utf-8", value,
 25.1302 +                            strlen(value), &index, "utf-8", &_value);
 25.1303 +                    if (r)
 25.1304 +                        goto enomem;
 25.1305 +
 25.1306 +                    stringpair_t *pair = new_stringpair(name, _value);
 25.1307 +                    if (pair == NULL)
 25.1308 +                        goto enomem;
 25.1309 +
 25.1310 +                    opt = stringpair_list_add(opt, pair);
 25.1311 +                    free(_value);
 25.1312 +                    if (opt == NULL)
 25.1313 +                        goto enomem;
 25.1314 +
 25.1315 +                    if (msg->opt_fields == NULL)
 25.1316 +                        msg->opt_fields = opt;
 25.1317 +                }
 25.1318 +                break;
 25.1319 +        }
 25.1320 +    }
 25.1321 +    
 25.1322 +    return PEP_STATUS_OK;
 25.1323 +
 25.1324 +enomem:
 25.1325 +    status = PEP_OUT_OF_MEMORY;
 25.1326 +
 25.1327 +pEp_error:
 25.1328 +    return status;
 25.1329 +}
 25.1330 +
 25.1331 +static PEP_STATUS interpret_body(struct mailmime *part, char **longmsg, size_t *size)
 25.1332 +{
 25.1333 +    const char *text;
 25.1334 +    char *_longmsg;
 25.1335 +    size_t length;
 25.1336 +    size_t _size;
 25.1337 +    size_t index;
 25.1338 +    char *type = NULL;
 25.1339 +    char *charset = NULL;
 25.1340 +
 25.1341 +    assert(part);
 25.1342 +    assert(longmsg);
 25.1343 +
 25.1344 +    *longmsg = NULL;
 25.1345 +    if (size)
 25.1346 +        *size = 0;
 25.1347 +
 25.1348 +    if (part->mm_body == NULL)
 25.1349 +        return PEP_ILLEGAL_VALUE;
 25.1350 +
 25.1351 +    text = part->mm_body-> dt_data.dt_text.dt_data;
 25.1352 +    if (text == NULL)
 25.1353 +        return PEP_ILLEGAL_VALUE;
 25.1354 +
 25.1355 +    length = part->mm_body->dt_data.dt_text.dt_length;
 25.1356 +
 25.1357 +    if (part->mm_body->dt_encoded) {
 25.1358 +        int code = part->mm_body->dt_encoding;
 25.1359 +        index = 0;
 25.1360 +        int r = mailmime_part_parse(text, length, &index, code, &_longmsg, &_size);
 25.1361 +        switch (r) {
 25.1362 +            case MAILIMF_NO_ERROR:
 25.1363 +                break;
 25.1364 +            case MAILIMF_ERROR_MEMORY:
 25.1365 +                return PEP_OUT_OF_MEMORY;
 25.1366 +            default:
 25.1367 +                return PEP_ILLEGAL_VALUE;
 25.1368 +        }
 25.1369 +    }
 25.1370 +    else {
 25.1371 +        _size = length + 1;
 25.1372 +        _longmsg = strndup(text, length);
 25.1373 +        if (_longmsg == NULL)
 25.1374 +            return PEP_OUT_OF_MEMORY;
 25.1375 +    }
 25.1376 +
 25.1377 +    if (part->mm_content_type) {
 25.1378 +        if (_get_content_type(part->mm_content_type, &type, &charset) == 0) {
 25.1379 +            if (charset && strncasecmp(charset, "utf-8", 5) != 0) {
 25.1380 +                char * _text;
 25.1381 +                int r = charconv("utf-8", charset, _longmsg, _size, &_text);
 25.1382 +                switch (r) {
 25.1383 +                    case MAILIMF_NO_ERROR:
 25.1384 +                        break;
 25.1385 +                    case MAILIMF_ERROR_MEMORY:
 25.1386 +                        return PEP_OUT_OF_MEMORY;
 25.1387 +                    default:
 25.1388 +                        return PEP_ILLEGAL_VALUE;
 25.1389 +                }
 25.1390 +                free(_longmsg);
 25.1391 +                _longmsg = _text;
 25.1392 +            }
 25.1393 +        }
 25.1394 +    }
 25.1395 +    // FIXME: KG - we now have the text we want.
 25.1396 +    // Now we need to strip sigs and process them if they are there..
 25.1397 +    
 25.1398 +
 25.1399 +    *longmsg = _longmsg;
 25.1400 +    if (size)
 25.1401 +        *size = _size;
 25.1402 +
 25.1403 +    return PEP_STATUS_OK;
 25.1404 +}
 25.1405 +
 25.1406 +// THIS IS A BEST-EFFORT ONLY FUNCTION, AND WE ARE NOT DOING MORE THAN THE
 25.1407 +// SUBJECT FOR NOW.
 25.1408 +static PEP_STATUS interpret_protected_headers(
 25.1409 +        struct mailmime* mime, 
 25.1410 +        message* msg
 25.1411 +    )
 25.1412 +{
 25.1413 +    // N.B. this is *very much* enigmail output specific, and right now,
 25.1414 +    // we only care about subject replacement.
 25.1415 +    const char* header_string = "Content-Type: text/rfc822-headers; protected-headers=\"v1\"\nContent-Disposition: inline\n\n";
 25.1416 +    size_t content_length = mime->mm_length;
 25.1417 +    size_t header_strlen = strlen(header_string);
 25.1418 +    if (header_strlen < content_length) {
 25.1419 +        const char* headerblock = mime->mm_mime_start;
 25.1420 +        size_t subject_len = 0;
 25.1421 +        headerblock = strstr(headerblock, header_string);
 25.1422 +        if (headerblock) {
 25.1423 +            const char* subj_start = "Subject: ";
 25.1424 +            headerblock = strstr(headerblock, subj_start);
 25.1425 +            if (headerblock) {
 25.1426 +                size_t subj_len = strlen(subj_start);
 25.1427 +                headerblock += subj_len;
 25.1428 +                char* end_pt = strstr(headerblock, "\n");
 25.1429 +                if (end_pt) {
 25.1430 +                    if (end_pt != mime->mm_mime_start && *(end_pt - 1) == '\r')
 25.1431 +                        end_pt--;
 25.1432 +                    subject_len = end_pt - headerblock;
 25.1433 +                    char* new_subj = (char*)calloc(subject_len + 1, 1);
 25.1434 +                    if (new_subj) {
 25.1435 +                        strlcpy(new_subj, headerblock, subject_len + 1);
 25.1436 +                        free(msg->shortmsg);
 25.1437 +                        msg->shortmsg = new_subj;
 25.1438 +                    }    
 25.1439 +                } // if there's no endpoint, there's something wrong here so we ignore all
 25.1440 +                  // This is best effort.
 25.1441 +            }
 25.1442 +        }
 25.1443 +    }
 25.1444 +    return PEP_STATUS_OK;
 25.1445 +}
 25.1446 +
 25.1447 +// ONLY for main part!!!
 25.1448 +static PEP_STATUS process_multipart_related(struct mailmime *mime,
 25.1449 +                                            message *msg) {
 25.1450 +    PEP_STATUS status = PEP_STATUS_OK;
 25.1451 +
 25.1452 +    assert(mime);
 25.1453 +    assert(msg);
 25.1454 +
 25.1455 +    clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;                                                
 25.1456 +
 25.1457 +    if (partlist == NULL)
 25.1458 +        return PEP_ILLEGAL_VALUE;
 25.1459 +
 25.1460 +    clistiter *cur = clist_begin(partlist);
 25.1461 +    struct mailmime *part = clist_content(cur);
 25.1462 +    
 25.1463 +    if (part == NULL)
 25.1464 +        return PEP_ILLEGAL_VALUE;
 25.1465 +
 25.1466 +    struct mailmime_content *content = part->mm_content_type;    
 25.1467 +    assert(content);
 25.1468 +    
 25.1469 +    if (content == NULL)
 25.1470 +        return PEP_ILLEGAL_VALUE;
 25.1471 +
 25.1472 +    if (_is_text_part(content, "html")) {
 25.1473 +        status = interpret_body(part, &msg->longmsg_formatted,
 25.1474 +                NULL);
 25.1475 +        if (status)
 25.1476 +            return status;
 25.1477 +    }
 25.1478 +    else {
 25.1479 +        // ???
 25.1480 +        // This is what we would have done before, so... no
 25.1481 +        // worse than the status quo. But FIXME!
 25.1482 +        status = interpret_MIME(part, msg);
 25.1483 +        if (status)
 25.1484 +            return status;
 25.1485 +    }
 25.1486 +    
 25.1487 +    for (cur = clist_next(cur); cur; cur = clist_next(cur)) {
 25.1488 +        part = clist_content(cur);
 25.1489 +        if (part == NULL)
 25.1490 +            return PEP_ILLEGAL_VALUE;
 25.1491 +
 25.1492 +        content = part->mm_content_type;
 25.1493 +        assert(content);
 25.1494 +        if (content == NULL)
 25.1495 +            return PEP_ILLEGAL_VALUE;
 25.1496 +
 25.1497 +        status = interpret_MIME(part, msg);
 25.1498 +        if (status)
 25.1499 +            return status;
 25.1500 +    }
 25.1501 +    return status;
 25.1502 +}
 25.1503 +
 25.1504 +static PEP_STATUS interpret_MIME(
 25.1505 +        struct mailmime *mime,
 25.1506 +        message *msg
 25.1507 +    )
 25.1508 +{
 25.1509 +    PEP_STATUS status = PEP_STATUS_OK;
 25.1510 +
 25.1511 +    assert(mime);
 25.1512 +    assert(msg);
 25.1513 +
 25.1514 +    struct mailmime_content *content = mime->mm_content_type;
 25.1515 +    if (content) {
 25.1516 +        if (_is_multipart(content, "alternative")) {
 25.1517 +            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 25.1518 +            if (partlist == NULL)
 25.1519 +                return PEP_ILLEGAL_VALUE;
 25.1520 +
 25.1521 +            clistiter *cur;
 25.1522 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 25.1523 +                struct mailmime *part = clist_content(cur);
 25.1524 +                if (part == NULL)
 25.1525 +                    return PEP_ILLEGAL_VALUE;
 25.1526 +
 25.1527 +                content = part->mm_content_type;
 25.1528 +                assert(content);
 25.1529 +                if (content == NULL)
 25.1530 +                    return PEP_ILLEGAL_VALUE;
 25.1531 +
 25.1532 +                if (_is_text_part(content, "plain") && msg->longmsg == NULL) {
 25.1533 +                    status = interpret_body(part, &msg->longmsg, NULL);
 25.1534 +                    if (status)
 25.1535 +                        return status;
 25.1536 +                }
 25.1537 +                else if (_is_text_part(content, "rfc822-headers")) {
 25.1538 +                    status = interpret_protected_headers(part, msg);
 25.1539 +                    if (status)
 25.1540 +                        return status;
 25.1541 +                }
 25.1542 +                else if (_is_text_part(content, "html") &&
 25.1543 +                        msg->longmsg_formatted == NULL) {
 25.1544 +                    status = interpret_body(part, &msg->longmsg_formatted,
 25.1545 +                            NULL);
 25.1546 +                    if (status)
 25.1547 +                        return status;
 25.1548 +                }
 25.1549 +                else if (_is_multipart(content, "related") && 
 25.1550 +                    msg->longmsg_formatted == NULL) {
 25.1551 +                    status = process_multipart_related(part, msg);
 25.1552 +                    if (status)
 25.1553 +                        return status;
 25.1554 +                }
 25.1555 +                else /* add as attachment */ {
 25.1556 +                    status = interpret_MIME(part, msg);
 25.1557 +                    if (status)
 25.1558 +                        return status;
 25.1559 +                }
 25.1560 +            }
 25.1561 +        }
 25.1562 +        else if (_is_multipart(content, "encrypted")) {
 25.1563 +            if (msg->longmsg == NULL)
 25.1564 +                msg->longmsg = strdup("");
 25.1565 +            assert(msg->longmsg);
 25.1566 +            if (!msg->longmsg)
 25.1567 +                return PEP_OUT_OF_MEMORY;
 25.1568 +
 25.1569 +            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 25.1570 +            if (partlist == NULL)
 25.1571 +                return PEP_ILLEGAL_VALUE;
 25.1572 +
 25.1573 +            clistiter *cur;
 25.1574 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 25.1575 +                struct mailmime *part= clist_content(cur);
 25.1576 +                if (part == NULL)
 25.1577 +                    return PEP_ILLEGAL_VALUE;
 25.1578 +
 25.1579 +                status = interpret_MIME(part, msg);
 25.1580 +                if (status != PEP_STATUS_OK)
 25.1581 +                    return status;
 25.1582 +            }
 25.1583 +        }
 25.1584 +        else if (_is_multipart(content, NULL)) {
 25.1585 +            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 25.1586 +            if (partlist == NULL)
 25.1587 +                return PEP_ILLEGAL_VALUE;
 25.1588 +
 25.1589 +            clistiter *cur;
 25.1590 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 25.1591 +                struct mailmime *part= clist_content(cur);
 25.1592 +                if (part == NULL)
 25.1593 +                    return PEP_ILLEGAL_VALUE;
 25.1594 +                status = interpret_MIME(part, msg);
 25.1595 +                if (status != PEP_STATUS_OK)
 25.1596 +                    return status;
 25.1597 +            }
 25.1598 +        }
 25.1599 +        else {
 25.1600 +            if (_is_text_part(content, "html") &&
 25.1601 +                msg->longmsg_formatted == NULL &&
 25.1602 +                msg->longmsg == NULL) {
 25.1603 +                status = interpret_body(mime, &msg->longmsg_formatted,
 25.1604 +                                        NULL);
 25.1605 +                if (status)
 25.1606 +                    return status;
 25.1607 +            }
 25.1608 +            else if (_is_text_part(content, "rfc822-headers")) {
 25.1609 +                status = interpret_protected_headers(mime, msg);
 25.1610 +                if (status)
 25.1611 +                    return status;
 25.1612 +            }
 25.1613 +            else if (_is_text_part(content, "plain") && 
 25.1614 +                     msg->longmsg == NULL && msg->longmsg_formatted == NULL) {
 25.1615 +                status = interpret_body(mime, &msg->longmsg, NULL);
 25.1616 +                if (status)
 25.1617 +                    return status;
 25.1618 +            }            
 25.1619 +            else if (_is_text_part(content, NULL) && 
 25.1620 +                     !_is_text_part(content, "plain") &&
 25.1621 +                     msg->longmsg == NULL) {
 25.1622 +                status = interpret_body(mime, &msg->longmsg, NULL);
 25.1623 +                if (status)
 25.1624 +                    return status;
 25.1625 +            }
 25.1626 +            else {
 25.1627 +                char *data = NULL;
 25.1628 +                size_t size = 0;
 25.1629 +                char * mime_type;
 25.1630 +                char * charset;
 25.1631 +                char * filename;
 25.1632 +                int r;
 25.1633 +
 25.1634 +                r = _get_content_type(content, &mime_type, &charset);
 25.1635 +                switch (r) {
 25.1636 +                    case 0:
 25.1637 +                        break;
 25.1638 +                    case EINVAL:
 25.1639 +                        return PEP_ILLEGAL_VALUE;
 25.1640 +                    case ENOMEM:
 25.1641 +                        return PEP_OUT_OF_MEMORY;
 25.1642 +                    default:
 25.1643 +                        return PEP_UNKNOWN_ERROR;
 25.1644 +                }
 25.1645 +
 25.1646 +                assert(mime_type);
 25.1647 +
 25.1648 +                status = interpret_body(mime, &data, &size);
 25.1649 +                if (status)
 25.1650 +                    return status;
 25.1651 +
 25.1652 +                pEp_rid_list_t* resource_id_list = _get_resource_id_list(mime);
 25.1653 +                pEp_rid_list_t* chosen_resource_id = choose_resource_id(resource_id_list);
 25.1654 +                
 25.1655 +                //filename = _get_filename_or_cid(mime);
 25.1656 +                char *_filename = NULL;
 25.1657 +                
 25.1658 +                if (chosen_resource_id) {
 25.1659 +                    filename = chosen_resource_id->rid;
 25.1660 +                    size_t index = 0;
 25.1661 +                    /* NOTA BENE */
 25.1662 +                    /* The prefix we just added shouldn't be a problem - this is about decoding %XX (RFC 2392) */
 25.1663 +                    /* If it becomes one, we have some MESSY fixing to do. :(                                  */
 25.1664 +                    r = mailmime_encoded_phrase_parse("utf-8", filename,
 25.1665 +                            strlen(filename), &index, "utf-8", &_filename);
 25.1666 +                    if (r) {
 25.1667 +                        goto enomem;
 25.1668 +                    }
 25.1669 +                    char* file_prefix = NULL;
 25.1670 +                    
 25.1671 +                    /* in case there are others later */
 25.1672 +                    switch (chosen_resource_id->rid_type) {
 25.1673 +                        case PEP_RID_CID:
 25.1674 +                            file_prefix = "cid";
 25.1675 +                            break;
 25.1676 +                        case PEP_RID_FILENAME:
 25.1677 +                            file_prefix = "file";
 25.1678 +                            break;
 25.1679 +                        default:
 25.1680 +                            break;
 25.1681 +                    }
 25.1682 +
 25.1683 +                    
 25.1684 +                    if (file_prefix) {
 25.1685 +                        filename = build_uri(file_prefix, _filename);
 25.1686 +                        free(_filename);
 25.1687 +                        _filename = filename;
 25.1688 +                    }
 25.1689 +                }
 25.1690 +
 25.1691 +                bloblist_t *_a = bloblist_add(msg->attachments, data, size,
 25.1692 +                        mime_type, _filename);
 25.1693 +                free(_filename);
 25.1694 +                free_rid_list(resource_id_list);
 25.1695 +                resource_id_list = NULL;
 25.1696 +                if (_a == NULL)
 25.1697 +                    return PEP_OUT_OF_MEMORY;
 25.1698 +                if (msg->attachments == NULL)
 25.1699 +                    msg->attachments = _a;
 25.1700 +            }
 25.1701 +        }
 25.1702 +    }
 25.1703 +
 25.1704 +    return PEP_STATUS_OK;
 25.1705 +
 25.1706 +enomem:
 25.1707 +    return PEP_OUT_OF_MEMORY;
 25.1708 +}
 25.1709 +
 25.1710 +DYNAMIC_API PEP_STATUS mime_decode_message(
 25.1711 +        const char *mimetext,
 25.1712 +        size_t size,
 25.1713 +        message **msg
 25.1714 +    )
 25.1715 +{
 25.1716 +    PEP_STATUS status = PEP_STATUS_OK;
 25.1717 +    struct mailmime * mime = NULL;
 25.1718 +    int r;
 25.1719 +    message *_msg = NULL;
 25.1720 +    size_t index;
 25.1721 +
 25.1722 +    assert(mimetext);
 25.1723 +    assert(msg);
 25.1724 +
 25.1725 +    if (!(mimetext && msg))
 25.1726 +        return PEP_ILLEGAL_VALUE;
 25.1727 +
 25.1728 +    *msg = NULL;
 25.1729 +
 25.1730 +    index = 0;
 25.1731 +    r = mailmime_parse(mimetext, size, &index, &mime);
 25.1732 +    assert(r == 0);
 25.1733 +    assert(mime);
 25.1734 +    if (r) {
 25.1735 +        if (r == MAILIMF_ERROR_MEMORY)
 25.1736 +            goto enomem;
 25.1737 +        else
 25.1738 +            goto err_mime;
 25.1739 +    }
 25.1740 +
 25.1741 +    _msg = calloc(1, sizeof(message));
 25.1742 +    assert(_msg);
 25.1743 +    if (_msg == NULL)
 25.1744 +        goto enomem;
 25.1745 +
 25.1746 +    clist * _fieldlist = _get_fields(mime);
 25.1747 +    if (_fieldlist) {
 25.1748 +        status = read_fields(_msg, _fieldlist);
 25.1749 +        if (status != PEP_STATUS_OK)
 25.1750 +            goto pEp_error;
 25.1751 +    }
 25.1752 +
 25.1753 +    struct mailmime_content *content = _get_content(mime);
 25.1754 +
 25.1755 +    if (content) {
 25.1756 +        status = interpret_MIME(mime->mm_data.mm_message.mm_msg_mime,
 25.1757 +                _msg);
 25.1758 +        if (status != PEP_STATUS_OK)
 25.1759 +            goto pEp_error;
 25.1760 +    }
 25.1761 +
 25.1762 +    mailmime_free(mime);
 25.1763 +    *msg = _msg;
 25.1764 +
 25.1765 +    return status;
 25.1766 +
 25.1767 +err_mime:
 25.1768 +    status = PEP_ILLEGAL_VALUE;
 25.1769 +    goto pEp_error;
 25.1770 +
 25.1771 +enomem:
 25.1772 +    status = PEP_OUT_OF_MEMORY;
 25.1773 +
 25.1774 +pEp_error:
 25.1775 +    free_message(_msg);
 25.1776 +
 25.1777 +    if (mime)
 25.1778 +        mailmime_free(mime);
 25.1779 +
 25.1780 +    return status;
 25.1781 +}
 25.1782 +
    26.1 --- a/src/key_reset.c	Thu Mar 28 15:40:45 2019 +0100
    26.2 +++ b/src/key_reset.c	Fri May 17 17:30:57 2019 +0200
    26.3 @@ -323,20 +323,61 @@
    26.4      return status;
    26.5  }
    26.6  
    26.7 -DYNAMIC_API PEP_STATUS key_reset(
    26.8 +DYNAMIC_API PEP_STATUS key_reset_identity(
    26.9 +        PEP_SESSION session,
   26.10 +        pEp_identity* ident,
   26.11 +        const char* fpr        
   26.12 +    )
   26.13 +{
   26.14 +    if (!session || !ident || (ident && (EMPTYSTR(ident->user_id) || EMPTYSTR(ident->address))))
   26.15 +        return PEP_ILLEGAL_VALUE;
   26.16 +    
   26.17 +    return key_reset(session, fpr, ident);    
   26.18 +}
   26.19 +
   26.20 +DYNAMIC_API PEP_STATUS key_reset_user(
   26.21 +        PEP_SESSION session,
   26.22 +        const char* user_id,
   26.23 +        const char* fpr        
   26.24 +    )
   26.25 +{
   26.26 +    if (!session || EMPTYSTR(user_id))
   26.27 +        return PEP_ILLEGAL_VALUE;
   26.28 +
   26.29 +    pEp_identity* input_ident = new_identity(NULL, NULL, user_id, NULL);
   26.30 +    if (!input_ident)
   26.31 +        return PEP_OUT_OF_MEMORY;
   26.32 +        
   26.33 +    if (is_me(session, input_ident) && EMPTYSTR(fpr))
   26.34 +        return PEP_ILLEGAL_VALUE;
   26.35 +        
   26.36 +    PEP_STATUS status = key_reset(session, fpr, input_ident);
   26.37 +    free_identity(input_ident);
   26.38 +    return status;
   26.39 +}
   26.40 +
   26.41 +DYNAMIC_API PEP_STATUS key_reset_all_own_keys(PEP_SESSION session) {
   26.42 +    return key_reset(session, NULL, NULL);
   26.43 +}
   26.44 +
   26.45 +// Notes to integrate into header:
   26.46 +// IF there is an ident, it must have a user_id.
   26.47 +PEP_STATUS key_reset(
   26.48          PEP_SESSION session,
   26.49          const char* key_id,
   26.50          pEp_identity* ident
   26.51      )
   26.52  {
   26.53 -    if (!session)
   26.54 +    if (!session || (ident && EMPTYSTR(ident->user_id)))
   26.55          return PEP_ILLEGAL_VALUE;
   26.56          
   26.57      PEP_STATUS status = PEP_STATUS_OK;
   26.58          
   26.59      char* fpr_copy = NULL;
   26.60      char* own_id = NULL;
   26.61 +    char* user_id = NULL;
   26.62      char* new_key = NULL;
   26.63 +    pEp_identity* tmp_ident = NULL;
   26.64      identity_list* key_idents = NULL;
   26.65      stringlist_t* keys = NULL;
   26.66      
   26.67 @@ -345,133 +386,205 @@
   26.68          if (!fpr_copy)
   26.69              return PEP_OUT_OF_MEMORY;
   26.70      }
   26.71 -        
   26.72 -    if (!ident) {
   26.73 -        // Get list of own identities
   26.74 -        status = get_default_own_userid(session, &own_id);
   26.75 -        if (status != PEP_STATUS_OK)
   26.76 +
   26.77 +    // This is true when we don't have a user_id and address and the fpr isn't specified
   26.78 +    bool reset_all_for_user = !fpr_copy && (!ident || EMPTYSTR(ident->address));
   26.79 +
   26.80 +    // FIXME: does this need to be done everywhere?> I think not.
   26.81 +    if (ident) {
   26.82 +        user_id = strdup(ident->user_id);
   26.83 +        if (!user_id) {
   26.84 +            status = PEP_OUT_OF_MEMORY;
   26.85              goto pEp_free;
   26.86 +        }
   26.87 +    }
   26.88 +    else {
   26.89 +        status = get_default_own_userid(session, &user_id);
   26.90 +        if (status != PEP_STATUS_OK || !user_id)
   26.91 +            goto pEp_free;                    
   26.92 +    }
   26.93 +    
   26.94 +    // FIXME: Make sure this can't result in a double-free in recursive calls
   26.95 +    tmp_ident = (ident ? identity_dup(ident) : new_identity(NULL, NULL, user_id, NULL));
   26.96 +    
   26.97 +    if (reset_all_for_user) {
   26.98 +        status = get_all_keys_for_user(session, user_id, &keys);
   26.99 +        // TODO: free
  26.100 +        if (status == PEP_STATUS_OK) {
  26.101 +            stringlist_t* curr_key;
  26.102              
  26.103 -        if (EMPTYSTR(fpr_copy)) {
  26.104 -            status = get_all_keys_for_user(session, own_id, &keys);
  26.105 -            if (status == PEP_STATUS_OK) {
  26.106 -                stringlist_t* curr_key;
  26.107 -                for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) {
  26.108 -                    status = key_reset(session, curr_key->value, NULL);
  26.109 -                    if (status != PEP_STATUS_OK)
  26.110 -                        break;
  26.111 -                }
  26.112 -            }
  26.113 -            goto pEp_free;
  26.114 -        } // otherwise, we have a specific fpr to process
  26.115 -
  26.116 -        // fpr_copy exists, so... let's go.
  26.117 -        // Process own identities with this fpr
  26.118 -        status = get_identities_by_main_key_id(session, fpr_copy, &key_idents);
  26.119 -        
  26.120 -        if (status == PEP_STATUS_OK) {
  26.121 -            // have ident list, or should
  26.122 -            identity_list* curr_ident;
  26.123 -            for (curr_ident = key_idents; curr_ident && curr_ident->ident; 
  26.124 -                 curr_ident = curr_ident->next) {
  26.125 -                pEp_identity* this_identity = curr_ident->ident;
  26.126 -                status = key_reset(session, fpr_copy, this_identity);
  26.127 +            for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) {
  26.128 +                // FIXME: Is the ident really necessary?
  26.129 +                status = key_reset(session, curr_key->value, tmp_ident);
  26.130                  if (status != PEP_STATUS_OK)
  26.131 -                    break;                    
  26.132 +                    break;
  26.133              }
  26.134          }
  26.135 -        else if (status == PEP_CANNOT_FIND_IDENTITY) // not an error
  26.136 -            status = PEP_STATUS_OK;
  26.137 +        goto pEp_free;
  26.138 +    }                   
  26.139 +    else {
  26.140 +        // tmp_ident => tmp_ident->user_id (was checked)
  26.141 +        //
  26.142 +        // !(EMPTYSTR(fpr) && (!tmp_ident || EMPTYSTR(tmp_ident->address)))
  26.143 +        // => fpr || (tmp_ident && tmp_ident->address)
  26.144 +        //
  26.145 +        // so: We have an fpr or we have an ident with user_id and address
  26.146 +        //     or both
  26.147 +        if (!fpr_copy) {
  26.148 +            // We are guaranteed to have an ident w/ id + addr here.
  26.149 +            // Get the default key.
  26.150 +            pEp_identity* stored_ident = NULL;
  26.151 +            status = get_identity(session, tmp_ident->address, 
  26.152 +                                  tmp_ident->user_id, &stored_ident);
  26.153 +
  26.154 +            // FIXME FIXME FIXME
  26.155 +            if (status == PEP_STATUS_OK) {
  26.156 +                // transfer ownership
  26.157 +                fpr_copy = stored_ident->fpr;
  26.158 +                stored_ident->fpr = NULL;
  26.159 +                free_identity(stored_ident);                
  26.160 +            }
  26.161              
  26.162 -        goto pEp_free;
  26.163 -    }
  26.164 -    else { // an identity was specified.       
  26.165 -        if (is_me(session, ident)) {            
  26.166 -            // FIXME: make sure this IS our fpr?
  26.167 +            if (!fpr_copy || status == PEP_CANNOT_FIND_IDENTITY) {
  26.168 +                // There's no identity default. Try resetting user default
  26.169 +                status = get_user_default_key(session, tmp_ident->user_id, &fpr_copy);
  26.170 +            }            
  26.171              
  26.172 -            // If it got sent in with an empty fpr...
  26.173 -            if (EMPTYSTR(fpr_copy)) {
  26.174 -                //
  26.175 -                // if (!EMPTYSTR(ident->fpr))
  26.176 -                //     fpr_copy = strdup(ident->fpr);
  26.177 -                status = _myself(session, ident, false, true);
  26.178 -                if (status == PEP_STATUS_OK && ident->fpr)
  26.179 -                    fpr_copy = strdup(ident->fpr);
  26.180 -                else {
  26.181 -                    // last resort?
  26.182 -                    // Get list of own identities
  26.183 -                    char* own_id = NULL;
  26.184 -                    status = get_default_own_userid(session, &own_id);
  26.185 -                    if (status == PEP_STATUS_OK)
  26.186 -                        status = get_user_default_key(session, own_id, &fpr_copy);
  26.187 -                    if (status != PEP_STATUS_OK || EMPTYSTR(fpr_copy))  {
  26.188 -                        free(own_id);
  26.189 -                        return (status == PEP_STATUS_OK ? PEP_KEY_NOT_FOUND : status);
  26.190 +            if (!fpr_copy || status != PEP_STATUS_OK) // No default to free. We're done here.
  26.191 +                goto pEp_free;            
  26.192 +        }
  26.193 +        
  26.194 +        // Ok - now we have at least an ident with user_id and an fpr.
  26.195 +        // Now it matters if we're talking about ourselves or a partner.
  26.196 +        bool is_own_private = false;
  26.197 +        if (is_me(session, tmp_ident)) {
  26.198 +            bool own_key = false;            
  26.199 +            status = is_own_key(session, fpr_copy, &own_key);
  26.200 +
  26.201 +            if (status != PEP_STATUS_OK)
  26.202 +                goto pEp_free;
  26.203 +            if (!own_key) {
  26.204 +                status = PEP_ILLEGAL_VALUE;
  26.205 +                goto pEp_free;
  26.206 +            }
  26.207 +
  26.208 +            status = contains_priv_key(session, fpr_copy, &is_own_private);
  26.209 +            if (status != PEP_STATUS_OK && status != PEP_KEY_NOT_FOUND)
  26.210 +                goto pEp_free;
  26.211 +        }
  26.212 +        
  26.213 +        // Up to this point, we haven't cared about whether or not we 
  26.214 +        // had a full identity. Now we have to deal with that in the 
  26.215 +        // case of own identities with private keys.
  26.216 +        
  26.217 +        if (is_own_private) {
  26.218 +            
  26.219 +            // If there's no address, we want to reset this key for every identity 
  26.220 +            // it's a part of. Since this means generating new keys, we have to 
  26.221 +            // grab all the identities associated with it.
  26.222 +            if (EMPTYSTR(tmp_ident->address)) {
  26.223 +                status = get_identities_by_main_key_id(session, fpr_copy, &key_idents);
  26.224 +                
  26.225 +                if (status != PEP_CANNOT_FIND_IDENTITY) {
  26.226 +                    if (status == PEP_STATUS_OK) {
  26.227 +                        // now have ident list, or should
  26.228 +                        identity_list* curr_ident;
  26.229 +                        
  26.230 +                        for (curr_ident = key_idents; curr_ident && curr_ident->ident; 
  26.231 +                                                        curr_ident = curr_ident->next) {
  26.232 +                            
  26.233 +                            pEp_identity* this_identity = curr_ident->ident;
  26.234 +                            // Do the full reset on this identity        
  26.235 +                            status = key_reset(session, fpr_copy, this_identity);
  26.236 +                            
  26.237 +                            // Ident list gets freed below, do not free here!
  26.238 +
  26.239 +                            if (status != PEP_STATUS_OK)
  26.240 +                                break;
  26.241 +                            
  26.242 +                        }
  26.243                      }
  26.244 -                }
  26.245 +                    // Ok, we've either now reset for each own identity with this key, or 
  26.246 +                    // we got an error and want to bail anyway.
  26.247 +                    goto pEp_free;
  26.248 +                }    
  26.249              }
  26.250 -                        
  26.251 -            free(ident->fpr);
  26.252 -            ident->fpr = fpr_copy;            
  26.253 +            
  26.254              // Create revocation
  26.255              status = revoke_key(session, fpr_copy, NULL);
  26.256 -            // generate new key
  26.257 -            if (status == PEP_STATUS_OK) {
  26.258 -                ident->fpr = NULL;
  26.259 -                status = generate_keypair(session, ident);
  26.260 -            }
  26.261 -            if (status == PEP_STATUS_OK) {
  26.262 -                new_key = strdup(ident->fpr);
  26.263 -                status = set_own_key(session, ident, new_key);
  26.264 -            }
  26.265 -            // mistrust fpr from trust
  26.266 -            ident->fpr = fpr_copy;
  26.267              
  26.268 -            ident->comm_type = PEP_ct_mistrusted;
  26.269 -            status = set_trust(session, ident);
  26.270 -            ident->fpr = NULL;
  26.271 -            
  26.272 -            // Done with old use of ident.
  26.273 -            if (status == PEP_STATUS_OK) {
  26.274 -                // Update fpr for outgoing
  26.275 -                status = myself(session, ident);
  26.276 -            }
  26.277 +            // If we have a full identity, we have some cleanup and generation tasks here
  26.278 +            if (!EMPTYSTR(tmp_ident->address)) {
  26.279 +                // generate new key
  26.280 +                if (status == PEP_STATUS_OK) {
  26.281 +                    tmp_ident->fpr = NULL;
  26.282 +                    status = generate_keypair(session, tmp_ident);
  26.283 +                }
  26.284 +                if (status == PEP_STATUS_OK) {
  26.285 +                    new_key = strdup(tmp_ident->fpr);
  26.286 +                    status = set_own_key(session, tmp_ident, new_key);
  26.287 +                }
  26.288 +                // mistrust fpr from trust
  26.289 +                tmp_ident->fpr = fpr_copy;
  26.290 +                
  26.291 +                tmp_ident->comm_type = PEP_ct_mistrusted;
  26.292 +                status = set_trust(session, tmp_ident);
  26.293 +                tmp_ident->fpr = NULL;
  26.294 +                
  26.295 +                // Done with old use of ident.
  26.296 +                if (status == PEP_STATUS_OK) {
  26.297 +                    // Update fpr for outgoing
  26.298 +                    status = myself(session, tmp_ident);
  26.299 +                }
  26.300 +            }    
  26.301              
  26.302              if (status == PEP_STATUS_OK)
  26.303                  // cascade that mistrust for anyone using this key
  26.304                  status = mark_as_compromised(session, fpr_copy);
  26.305 +                
  26.306              if (status == PEP_STATUS_OK)
  26.307                  status = remove_fpr_as_default(session, fpr_copy);
  26.308              if (status == PEP_STATUS_OK)
  26.309                  status = add_mistrusted_key(session, fpr_copy);
  26.310 -            // add to revocation list 
  26.311 -            if (status == PEP_STATUS_OK) 
  26.312 -                status = set_revoked(session, fpr_copy, new_key, time(NULL));            
  26.313 -            // for all active communication partners:
  26.314 -            //      active_send revocation
  26.315 -            if (status == PEP_STATUS_OK)
  26.316 -                status = send_key_reset_to_recents(session, fpr_copy, new_key);
  26.317 -                
  26.318 +
  26.319 +            // If there's a new key, do the DB linkage with the revoked one, and 
  26.320 +            // send the key reset mail opportunistically to recently contacted
  26.321 +            // partners
  26.322 +            if (new_key) {
  26.323 +                // add to revocation list 
  26.324 +                if (status == PEP_STATUS_OK) 
  26.325 +                    status = set_revoked(session, fpr_copy, new_key, time(NULL));            
  26.326 +                // for all active communication partners:
  26.327 +                //      active_send revocation
  26.328 +                if (status == PEP_STATUS_OK)
  26.329 +                    status = send_key_reset_to_recents(session, fpr_copy, new_key);        
  26.330 +            }        
  26.331 +        } // end is_own_private
  26.332 +        else {
  26.333 +            // This is a public key (or a private key that isn't ours, which means
  26.334 +            // we want it gone anyway)
  26.335 +            //
  26.336 +            // Delete this key from the keyring.
  26.337 +            status = delete_keypair(session, fpr_copy);
  26.338          }
  26.339 -        else { // not is_me
  26.340 -            // TODO: Decide what this means. We have a non-own identity, we don't
  26.341 -            //       have an fpr. Do we reset all keys for that identity?
  26.342 -            if (EMPTYSTR(fpr_copy)) {
  26.343 -                NOT_IMPLEMENTED
  26.344 -            }
  26.345 -                
  26.346 -            // remove fpr from all identities
  26.347 -            // remove fpr from all users
  26.348 -            if (status == PEP_STATUS_OK)
  26.349 -                status = remove_fpr_as_default(session, fpr_copy);
  26.350 -            // delete key from DB
  26.351 -            if (status == PEP_STATUS_OK) {
  26.352 -                status = remove_key(session, fpr_copy);
  26.353 -            };
  26.354 +
  26.355 +        // REGARDLESS OF WHO OWNS THE KEY, WE NOW NEED TO REMOVE IT AS A DEFAULT.
  26.356 +        PEP_STATUS cached_status = status;
  26.357 +        // remove fpr from all identities
  26.358 +        // remove fpr from all users
  26.359 +        status = remove_fpr_as_default(session, fpr_copy);
  26.360 +        // delete key from DB - this does NOT touch the keyring!
  26.361 +        // Note: for own priv keys, we cannot do this. But we'll never encrypt to/from it.
  26.362 +        if (status == PEP_STATUS_OK && !is_own_private) {
  26.363 +            status = remove_key(session, fpr_copy);
  26.364          }
  26.365 -    }
  26.366 -    
  26.367 +        if (status == PEP_STATUS_OK)
  26.368 +            status = cached_status;
  26.369 +    }           
  26.370 +        
  26.371  pEp_free:
  26.372 +    if (!ident)
  26.373 +        free_identity(tmp_ident);
  26.374      free(fpr_copy);
  26.375      free(own_id);
  26.376      free_identity_list(key_idents);
    27.1 --- a/src/key_reset.h	Thu Mar 28 15:40:45 2019 +0100
    27.2 +++ b/src/key_reset.h	Fri May 17 17:30:57 2019 +0200
    27.3 @@ -15,13 +15,90 @@
    27.4  extern "C" {
    27.5  #endif
    27.6  
    27.7 +// key_reset_identity() - reset the default database status for the identity / keypair
    27.8 +//                        provided. If this corresponds to an own identity and a private key,
    27.9 +//                        also revoke the key, generate a new one, and communicate the 
   27.10 +//                        reset to recently contacted pEp partners for this identity.
   27.11 +//
   27.12 +//                        If it does not, remove the key from the keyring; the key's 
   27.13 +//                        status is completely fresh on next contact from the partner.
   27.14 +//
   27.15 +//                        If no key is provided, reset the identity default.
   27.16 +//
   27.17 +//                        Note that reset keys will be removed as defaults for all users and identities.
   27.18 +//
   27.19 +//  parameters:
   27.20 +//      session (in)            session handle
   27.21 +//      fpr (in)                fingerprint of key to reset. If NULL, we reset the default key
   27.22 +//                              this identity if there is one, and the user default if not.
   27.23 +//      ident (in)              identity for which the key reset should occur. Must contain 
   27.24 +//                              user_id and address. Must not be NULL.
   27.25 +//
   27.26 +//                              Note: ident->fpr field will be ignored.
   27.27 +//
   27.28 +//
   27.29 +DYNAMIC_API PEP_STATUS key_reset_identity(
   27.30 +        PEP_SESSION session,
   27.31 +        pEp_identity* ident,
   27.32 +        const char* fpr
   27.33 +    );
   27.34 +
   27.35 +// key_reset_user() -  reset the default database status for the user / keypair
   27.36 +//                     provided. This will effectively perform key_reset_identity()
   27.37 +//                     each identity associated with the key and user_id, if a key is
   27.38 +//                     provided, and for each key (and all of their identities) if an fpr 
   27.39 +//                     is not.
   27.40 +//
   27.41 +//                     If the user_id is the own user_id, an fpr MUST be provided.
   27.42 +//                     For a reset of all own user keys, call key_reset_all_own_keys() instead.
   27.43 +//
   27.44 +//                     Note that reset keys will be removed as defaults for all users and identities.
   27.45 +//
   27.46 +//  parameters:
   27.47 +//      session (in)            session handle
   27.48 +//      user_id (in)            user_id for which the key reset should occur. If this 
   27.49 +//                              is the own user_id, fpr MUST NOT be NULL.
   27.50 +//      fpr (in)                fingerprint of key to reset.
   27.51 +//                              If NULL, we reset all default 
   27.52 +//                              keys for this user and all of its identities.
   27.53 +//                              *** However, it is forbidden to use the own user_id 
   27.54 +//                                  here when the fpr is NULL. For this functionality, 
   27.55 +//                                  call key_reset_all_own_keys ***
   27.56 +
   27.57 +//
   27.58 +DYNAMIC_API PEP_STATUS key_reset_user(
   27.59 +        PEP_SESSION session,
   27.60 +        const char* user_id,
   27.61 +        const char* fpr
   27.62 +    );
   27.63 +
   27.64 +// key_reset_all_own_keys() -  revoke and mistrust all own keys, generate new keys for all 
   27.65 +//                             own identities, and opportunistically communicate
   27.66 +//                             key reset information to people we have recently 
   27.67 +//                             contacted. 
   27.68 +//
   27.69 +// caveat: this will return PEP_CANNOT_FIND_IDENTITY if no own user yet exists.
   27.70 +//         HOWEVER, apps and adapters must decide if this is a reasonable state;
   27.71 +//         since the period where no own user exists will necessarily be very short
   27.72 +//         in most implementations, PEP_CANNOT_FIND_IDENTITY may be returned when 
   27.73 +//         there is some sort of DB corruption and we expect there to be an own user.
   27.74 +//         Apps are responsible for deciding whether or not this is an error condition;
   27.75 +//         one would expect that it generally is (rather than the uninitialised DB case)
   27.76 +//                             
   27.77 +//  parameters:
   27.78 +//      session (in)            session handle
   27.79 +//
   27.80 +DYNAMIC_API PEP_STATUS key_reset_all_own_keys(PEP_SESSION session);
   27.81 +
   27.82 +
   27.83  // key_reset() - reset the database status for a key, removing all trust information
   27.84  //               and default database connections. For own keys, also revoke the key
   27.85  //               and communicate the revocation and new key to partners we have sent
   27.86  //               mail to recently from the specific identity (i.e. address/user_id)
   27.87  //               that contacted them. We also in this case set up information so that
   27.88  //               if someone we mail uses the wrong key and wasn't yet contacted,
   27.89 -//               we can send them the reset information from the right address.
   27.90 +//               we can send them the reset information from the right address. 
   27.91 +//               For non-own keys, also remove key from the keyring.
   27.92  //
   27.93  //               Can be called manually or through another protocol.
   27.94  //
   27.95 @@ -32,10 +109,8 @@
   27.96  //                              an own identity, we reset the default key for that
   27.97  //                              identity. If that own identity has no default key, we
   27.98  //                              reset the user default.
   27.99 -//                              if it is NULL and there is a non-own identity, this is
  27.100 -//                              currently undefined and will return an error. Later, we
  27.101 -//                              may decide on semantics for it (e.g. remove all keys
  27.102 -//                              in the DB for that identity)
  27.103 +//                              if it is NULL and there is a non-own identity, we will reset 
  27.104 +//                              the default key for this identity if present, and user if not.
  27.105  //      ident (in)              identity for which the key reset should occur.
  27.106  //                              if NULL and fpr is non-NULL, we'll reset the key for all
  27.107  //                              associated identities. If both ident and fpr are NULL, see 
  27.108 @@ -43,13 +118,17 @@
  27.109  //
  27.110  //      Note: ident->fpr is always ignored
  27.111  //
  27.112 -//
  27.113 -DYNAMIC_API PEP_STATUS key_reset(
  27.114 +// Caveat: this is now used in large part for internal calls.
  27.115 +//         external apps should call key_reset_identity and key_reset_userdata
  27.116 +//         and this function should probably be removed from the dynamic api
  27.117 +PEP_STATUS key_reset(
  27.118          PEP_SESSION session,
  27.119          const char* fpr,
  27.120          pEp_identity* ident
  27.121      );
  27.122  
  27.123 +
  27.124 +
  27.125  PEP_STATUS has_key_reset_been_sent(
  27.126          PEP_SESSION session, 
  27.127          const char* user_id, 
    28.1 --- a/src/keymanagement.c	Thu Mar 28 15:40:45 2019 +0100
    28.2 +++ b/src/keymanagement.c	Fri May 17 17:30:57 2019 +0200
    28.3 @@ -576,9 +576,44 @@
    28.4      char* default_own_id = NULL;
    28.5      status = get_default_own_userid(session, &default_own_id);    
    28.6  
    28.7 -    // Is this me, temporary or not? If so, BAIL.
    28.8 -    if (identity->me || 
    28.9 -       (default_own_id && identity->user_id && (strcmp(default_own_id, identity->user_id) == 0))) 
   28.10 +    bool is_own_user = identity->me;
   28.11 +
   28.12 +    // Is this me, temporary or not? If so, BAIL.    
   28.13 +    if (!is_own_user) {
   28.14 +        if (default_own_id) {
   28.15 +            if (!EMPTYSTR(identity->user_id)) {
   28.16 +                if (strcmp(default_own_id, identity->user_id) == 0) {
   28.17 +                    is_own_user = true;
   28.18 +                }
   28.19 +                else {
   28.20 +                    char* alias = NULL;
   28.21 +                    if (get_userid_alias_default(session, identity->user_id, &alias) == PEP_STATUS_OK) {
   28.22 +                        if (alias && strcmp(default_own_id, alias) == 0)
   28.23 +                            is_own_user = true;
   28.24 +                        free(alias);    
   28.25 +                    }
   28.26 +                }
   28.27 +            }
   28.28 +            else {
   28.29 +                // Check if own address. For now, this is a special case;
   28.30 +                // we try to require apps to send in user_ids, but must prevent
   28.31 +                // writes to an own identity from within THIS function
   28.32 +                // NOTE: These semantics MAY CHANGE.
   28.33 +                bool _own_addr = false;
   28.34 +                is_own_address(session, identity->address, &_own_addr);
   28.35 +                
   28.36 +                // N.B. KB: I would prefer consistent semantics here - that is to say,
   28.37 +                // we also set is_own_user here and force PEP_ILLEGAL_VALUE                
   28.38 +                if (_own_addr) {
   28.39 +                    free(identity->user_id);
   28.40 +                    identity->user_id = strdup(default_own_id);
   28.41 +                    return _myself(session, identity, false, false, true);
   28.42 +                }    
   28.43 +            }
   28.44 +        }
   28.45 +        // Otherwise, we don't even HAVE an own user yet, so we're ok.
   28.46 +    }    
   28.47 +    if (is_own_user)
   28.48      {
   28.49          free(default_own_id);
   28.50          return PEP_ILLEGAL_VALUE;
   28.51 @@ -994,7 +1029,11 @@
   28.52      return status;
   28.53  }
   28.54  
   28.55 -PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags)
   28.56 +PEP_STATUS _myself(PEP_SESSION session, 
   28.57 +                   pEp_identity * identity, 
   28.58 +                   bool do_keygen, 
   28.59 +                   bool ignore_flags,
   28.60 +                   bool read_only)
   28.61  {
   28.62  
   28.63      PEP_STATUS status;
   28.64 @@ -1016,18 +1055,24 @@
   28.65      status = get_default_own_userid(session, &default_own_id);
   28.66  
   28.67      // Deal with non-default user_ids.
   28.68 +    // FIXME: if non-default and read-only, reject totally?
   28.69      if (default_own_id && strcmp(default_own_id, identity->user_id) != 0) {
   28.70 -        
   28.71 -        status = set_userid_alias(session, default_own_id, identity->user_id);
   28.72 -        // Do we want this to be fatal? For now, we'll do it...
   28.73 -        if (status != PEP_STATUS_OK)
   28.74 -            goto pEp_free;
   28.75 -            
   28.76 -        free(identity->user_id);
   28.77 -        identity->user_id = strdup(default_own_id);
   28.78 -        if (identity->user_id == NULL) {
   28.79 -            status = PEP_OUT_OF_MEMORY;
   28.80 -            goto pEp_free;
   28.81 +        if (read_only) {
   28.82 +            free(identity->user_id);
   28.83 +            identity->user_id = strdup(default_own_id);
   28.84 +        }
   28.85 +        else {
   28.86 +            status = set_userid_alias(session, default_own_id, identity->user_id);
   28.87 +            // Do we want this to be fatal? For now, we'll do it...
   28.88 +            if (status != PEP_STATUS_OK)
   28.89 +                goto pEp_free;
   28.90 +                
   28.91 +            free(identity->user_id);
   28.92 +            identity->user_id = strdup(default_own_id);
   28.93 +            if (identity->user_id == NULL) {
   28.94 +                status = PEP_OUT_OF_MEMORY;
   28.95 +                goto pEp_free;
   28.96 +            }
   28.97          }
   28.98      }
   28.99  
  28.100 @@ -1060,7 +1105,7 @@
  28.101      // Set usernames - priority is input username > stored name > address
  28.102      // If there's an input username, we always patch the username with that
  28.103      // input.
  28.104 -    if (EMPTYSTR(identity->username)) {
  28.105 +    if (EMPTYSTR(identity->username) || read_only) {
  28.106          bool stored_uname = (stored_identity && !EMPTYSTR(stored_identity->username));
  28.107          char* uname = (stored_uname ? stored_identity->username : identity->address);
  28.108          free(identity->username);
  28.109 @@ -1079,41 +1124,45 @@
  28.110      }
  28.111  
  28.112      // check stored identity
  28.113 -    if (stored_identity && !EMPTYSTR(stored_identity->fpr)) {
  28.114 -        // Fall back / retrieve
  28.115 -        status = validate_fpr(session, stored_identity, false, true);
  28.116 -        if (status == PEP_OUT_OF_MEMORY)
  28.117 -            goto pEp_free;
  28.118 -        if (status == PEP_STATUS_OK) {
  28.119 -            if (stored_identity->comm_type >= PEP_ct_strong_but_unconfirmed) {
  28.120 -                identity->fpr = strdup(stored_identity->fpr);
  28.121 -                assert(identity->fpr);
  28.122 -                if (!identity->fpr) {
  28.123 -                    status = PEP_OUT_OF_MEMORY;
  28.124 -                    goto pEp_free;
  28.125 -                }
  28.126 -                valid_key_found = true;            
  28.127 -            }
  28.128 -            else {
  28.129 -                bool revoked = false;
  28.130 -                status = key_revoked(session, stored_identity->fpr, &revoked);
  28.131 -                if (status)
  28.132 -                    goto pEp_free;
  28.133 -                if (revoked) {
  28.134 -                    revoked_fpr = strdup(stored_identity->fpr);
  28.135 -                    assert(revoked_fpr);
  28.136 -                    if (!revoked_fpr) {
  28.137 +    if (stored_identity) {
  28.138 +        if (!EMPTYSTR(stored_identity->fpr)) {
  28.139 +            // Fall back / retrieve
  28.140 +            status = validate_fpr(session, stored_identity, false, true);
  28.141 +            if (status == PEP_OUT_OF_MEMORY)
  28.142 +                goto pEp_free;
  28.143 +            if (status == PEP_STATUS_OK) {
  28.144 +                if (stored_identity->comm_type >= PEP_ct_strong_but_unconfirmed) {
  28.145 +                    identity->fpr = strdup(stored_identity->fpr);
  28.146 +                    assert(identity->fpr);
  28.147 +                    if (!identity->fpr) {
  28.148                          status = PEP_OUT_OF_MEMORY;
  28.149                          goto pEp_free;
  28.150                      }
  28.151 +                    valid_key_found = true;            
  28.152 +                }
  28.153 +                else {
  28.154 +                    bool revoked = false;
  28.155 +                    status = key_revoked(session, stored_identity->fpr, &revoked);
  28.156 +                    if (status)
  28.157 +                        goto pEp_free;
  28.158 +                    if (revoked) {
  28.159 +                        revoked_fpr = strdup(stored_identity->fpr);
  28.160 +                        assert(revoked_fpr);
  28.161 +                        if (!revoked_fpr) {
  28.162 +                            status = PEP_OUT_OF_MEMORY;
  28.163 +                            goto pEp_free;
  28.164 +                        }
  28.165 +                    }
  28.166                  }
  28.167              }
  28.168          }
  28.169 +        // reconcile language, flags
  28.170 +        transfer_ident_lang_and_flags(identity, stored_identity);
  28.171      }
  28.172      
  28.173      // Nothing left to do but generate a key
  28.174      if (!valid_key_found) {
  28.175 -        if (!do_keygen)
  28.176 +        if (!do_keygen || read_only)
  28.177              status = PEP_GET_KEY_FAILED;
  28.178          else {
  28.179  // /            DEBUG_LOG("Generating key pair", "debug", identity->address);
  28.180 @@ -1151,12 +1200,14 @@
  28.181      
  28.182      // We want to set an identity in the DB even if a key isn't found, but we have to preserve the status if
  28.183      // it's NOT ok
  28.184 -    PEP_STATUS set_id_status = set_identity(session, identity);
  28.185 -    if (set_id_status == PEP_STATUS_OK)
  28.186 -        set_id_status = set_as_pEp_user(session, identity);
  28.187 +    if (!read_only) {
  28.188 +        PEP_STATUS set_id_status = set_identity(session, identity);
  28.189 +        if (set_id_status == PEP_STATUS_OK)
  28.190 +            set_id_status = set_as_pEp_user(session, identity);
  28.191  
  28.192 -    status = (status == PEP_STATUS_OK ? set_id_status : status);
  28.193 -
  28.194 +        status = (status == PEP_STATUS_OK ? set_id_status : status);
  28.195 +    }
  28.196 +    
  28.197  pEp_free:    
  28.198      free(default_own_id);
  28.199      free(revoked_fpr);                     
  28.200 @@ -1166,7 +1217,7 @@
  28.201  
  28.202  DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
  28.203  {
  28.204 -    return _myself(session, identity, true, false);
  28.205 +    return _myself(session, identity, true, false, false);
  28.206  }
  28.207  
  28.208  DYNAMIC_API PEP_STATUS register_examine_function(
  28.209 @@ -1495,7 +1546,6 @@
  28.210          }
  28.211      }    
  28.212  
  28.213 -pEp_free:
  28.214      free(ident_default_fpr);
  28.215      free(cached_fpr);
  28.216      free_identity(tmp_id);
  28.217 @@ -1610,8 +1660,10 @@
  28.218      unsigned int flags = 0;
  28.219      
  28.220      identity_list *_bl = _own_identities;
  28.221 +
  28.222 +    sqlite3_bind_int(session->own_identities_retrieve, 1, excluded_flags);
  28.223 +
  28.224      do {
  28.225 -        sqlite3_bind_int(session->own_identities_retrieve, 1, excluded_flags);
  28.226          result = sqlite3_step(session->own_identities_retrieve);
  28.227          switch (result) {
  28.228              case SQLITE_ROW:
  28.229 @@ -1685,7 +1737,8 @@
  28.230  PEP_STATUS _own_keys_retrieve(
  28.231          PEP_SESSION session,
  28.232          stringlist_t **keylist,
  28.233 -        identity_flags_t excluded_flags
  28.234 +        identity_flags_t excluded_flags,
  28.235 +        bool private_only
  28.236        )
  28.237  {
  28.238      PEP_STATUS status = PEP_STATUS_OK;
  28.239 @@ -1700,26 +1753,20 @@
  28.240      sqlite3_reset(session->own_keys_retrieve);
  28.241      
  28.242      int result;
  28.243 -    char *fpr = NULL;
  28.244      
  28.245      stringlist_t *_bl = _keylist;
  28.246 -    do {
  28.247 -        sqlite3_bind_int(session->own_keys_retrieve, 1, excluded_flags);
  28.248 +    sqlite3_bind_int(session->own_keys_retrieve, 1, excluded_flags);
  28.249 +
  28.250 +    do {        
  28.251          result = sqlite3_step(session->own_keys_retrieve);
  28.252          switch (result) {
  28.253              case SQLITE_ROW:
  28.254 -                fpr = strdup((const char *) sqlite3_column_text(session->own_keys_retrieve, 0));
  28.255 -                if(fpr == NULL)
  28.256 +                _bl = stringlist_add(_bl, (const char *)
  28.257 +                        sqlite3_column_text(session->own_keys_retrieve, 0));
  28.258 +                if (_bl == NULL)
  28.259                      goto enomem;
  28.260 -
  28.261 -                _bl = stringlist_add(_bl, fpr);
  28.262 -                if (_bl == NULL) {
  28.263 -                    free(fpr);
  28.264 -                    goto enomem;
  28.265 -                }
  28.266                  if (_keylist == NULL)
  28.267                      _keylist = _bl;
  28.268 -                
  28.269                  break;
  28.270                  
  28.271              case SQLITE_DONE:
  28.272 @@ -1732,8 +1779,33 @@
  28.273      } while (result != SQLITE_DONE);
  28.274      
  28.275      sqlite3_reset(session->own_keys_retrieve);
  28.276 -    if (status == PEP_STATUS_OK)
  28.277 +    if (status == PEP_STATUS_OK) {
  28.278 +        dedup_stringlist(_keylist);
  28.279 +        if (private_only) {
  28.280 +            stringlist_t* _kl = _keylist;
  28.281 +            stringlist_t* _kl_prev = NULL;
  28.282 +            while (_kl) {
  28.283 +                bool has_private = false;
  28.284 +                contains_priv_key(session, _kl->value, &has_private);
  28.285 +                if (!has_private) {
  28.286 +                    stringlist_t* _kl_tmp = _kl;
  28.287 +                    if (_kl_prev)
  28.288 +                        _kl_prev->next = _kl->next;
  28.289 +                    else 
  28.290 +                        _keylist = _kl->next;
  28.291 +                        
  28.292 +                    _kl = _kl->next;
  28.293 +                    
  28.294 +                    _kl_tmp->next = NULL;
  28.295 +                    free_stringlist(_kl_tmp);
  28.296 +                    continue;
  28.297 +                }
  28.298 +                _kl_prev = _kl;
  28.299 +                _kl = _kl->next;
  28.300 +            }
  28.301 +        }
  28.302          *keylist = _keylist;
  28.303 +    }
  28.304      else
  28.305          free_stringlist(_keylist);
  28.306      
  28.307 @@ -1749,7 +1821,7 @@
  28.308  
  28.309  DYNAMIC_API PEP_STATUS own_keys_retrieve(PEP_SESSION session, stringlist_t **keylist)
  28.310  {
  28.311 -    return _own_keys_retrieve(session, keylist, 0);
  28.312 +    return _own_keys_retrieve(session, keylist, 0, true);
  28.313  }
  28.314  
  28.315  DYNAMIC_API PEP_STATUS set_own_key(
  28.316 @@ -1770,7 +1842,7 @@
  28.317              EMPTYSTR(me->user_id) || EMPTYSTR(me->username))
  28.318          return PEP_ILLEGAL_VALUE;
  28.319  
  28.320 -    status = _myself(session, me, false, true);
  28.321 +    status = _myself(session, me, false, true, false);
  28.322      // we do not need a valid key but dislike other errors
  28.323      if (status != PEP_STATUS_OK && status != PEP_GET_KEY_FAILED && status != PEP_KEY_UNSUITABLE)
  28.324          return status;
  28.325 @@ -1939,6 +2011,7 @@
  28.326          thing = _pgp_thing_next(thing);
  28.327          switch (thing) {
  28.328              case _pgp_fpr:
  28.329 +                // PEP_OWN_USERID is ok here because this is only run on first use!
  28.330                  identity = new_identity(NULL, NULL, PEP_OWN_USERID, NULL);
  28.331                  if (!identity) {
  28.332                      status = PEP_OUT_OF_MEMORY;
    29.1 --- a/src/keymanagement.h	Thu Mar 28 15:40:45 2019 +0100
    29.2 +++ b/src/keymanagement.h	Fri May 17 17:30:57 2019 +0200
    29.3 @@ -114,7 +114,11 @@
    29.4  
    29.5  DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity);
    29.6  
    29.7 -PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags);
    29.8 +PEP_STATUS _myself(PEP_SESSION session, 
    29.9 +                   pEp_identity * identity, 
   29.10 +                   bool do_keygen, 
   29.11 +                   bool ignore_flags,
   29.12 +                   bool read_only);
   29.13  
   29.14  // retrieve_next_identity() - callback being called by do_keymanagement()
   29.15  //
   29.16 @@ -326,17 +330,19 @@
   29.17  //  parameters:
   29.18  //      session (in)            session to use
   29.19  //      keylist (out)           list of fingerprints
   29.20 -//      excluded_flags (int)    flags to exclude from results
   29.21 -//
   29.22 +//      excluded_flags (in)     flags to exclude from results
   29.23 +//      private_only (in)       if true, return only fprs for
   29.24 +//                              which we have the secret part
   29.25  //  caveat:
   29.26  //      the ownership of the list goes to the caller
   29.27  DYNAMIC_API PEP_STATUS _own_keys_retrieve(
   29.28          PEP_SESSION session,
   29.29          stringlist_t **keylist,
   29.30 -        identity_flags_t excluded_flags
   29.31 +        identity_flags_t excluded_flags,
   29.32 +        bool private_only
   29.33        );
   29.34  
   29.35 -// own_keys_retrieve() - retrieve all flagged keypair fingerprints 
   29.36 +// own_keys_retrieve() - retrieve all flagged public/private keypair fingerprints 
   29.37  //
   29.38  //  parameters:
   29.39  //      session (in)            session to use
   29.40 @@ -344,6 +350,8 @@
   29.41  //
   29.42  //  caveat:
   29.43  //      the ownership of the list goes to the caller
   29.44 +//      this function does not return keys without a private key part
   29.45 +//
   29.46  DYNAMIC_API PEP_STATUS own_keys_retrieve(
   29.47          PEP_SESSION session,
   29.48          stringlist_t **keylist
   29.49 @@ -375,7 +383,7 @@
   29.50                                   stringlist_t** keys);
   29.51  
   29.52  
   29.53 -PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags);
   29.54 +//PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags);
   29.55  
   29.56  PEP_STATUS add_mistrusted_key(PEP_SESSION session, const char* fpr);
   29.57  PEP_STATUS delete_mistrusted_key(PEP_SESSION session, const char* fpr);
    30.1 --- a/src/message.h	Thu Mar 28 15:40:45 2019 +0100
    30.2 +++ b/src/message.h	Fri May 17 17:30:57 2019 +0200
    30.3 @@ -30,7 +30,8 @@
    30.4  
    30.5  typedef enum _PEP_enc_format {
    30.6      PEP_enc_none = 0,                       // message is not encrypted
    30.7 -    PEP_enc_pieces,                         // inline PGP + PGP extensions
    30.8 +    PEP_enc_pieces = 1,                     // inline PGP + PGP extensions, was removed
    30.9 +    PEP_enc_inline = 1,                     // still there
   30.10      PEP_enc_S_MIME,                         // RFC5751
   30.11      PEP_enc_PGP_MIME,                       // RFC3156
   30.12      PEP_enc_PEP,                            // pEp encryption format
    31.1 --- a/src/message_api.c	Thu Mar 28 15:40:45 2019 +0100
    31.2 +++ b/src/message_api.c	Fri May 17 17:30:57 2019 +0200
    31.3 @@ -10,6 +10,7 @@
    31.4  #include "baseprotocol.h"
    31.5  #include "KeySync_fsm.h"
    31.6  #include "base64.h"
    31.7 +#include "resource_id.h"
    31.8  
    31.9  #include <assert.h>
   31.10  #include <string.h>
   31.11 @@ -267,14 +268,6 @@
   31.12          return uri + 3;
   31.13  }
   31.14  
   31.15 -// static bool is_file_uri(char* str) {
   31.16 -//     return(strncmp(str, "file://", 7) == 0);
   31.17 -// }
   31.18 -
   31.19 -static bool is_cid_uri(const char* str) {
   31.20 -    return(strncmp(str, "cid://", 6) == 0);
   31.21 -}
   31.22 -
   31.23  static bool string_equality(const char *s1, const char *s2)
   31.24  {
   31.25      if (s1 == NULL || s2 == NULL)
   31.26 @@ -978,37 +971,57 @@
   31.27      return NULL;    
   31.28  }
   31.29  
   31.30 -static PEP_STATUS update_identity_recip_list(PEP_SESSION session,
   31.31 -                                             identity_list* list) {
   31.32 -
   31.33 -    PEP_STATUS status = PEP_STATUS_OK;
   31.34 -
   31.35 -    if (!session)
   31.36 -        return PEP_UNKNOWN_ERROR;
   31.37 -    
   31.38 -    identity_list* id_list_ptr = NULL;
   31.39 -        
   31.40 -    for (id_list_ptr = list; id_list_ptr; id_list_ptr = id_list_ptr->next) {
   31.41 -        pEp_identity* curr_identity = id_list_ptr->ident;
   31.42 -        if (curr_identity) {
   31.43 -            if (!is_me(session, curr_identity)) {
   31.44 -                char* name_bak = curr_identity->username;
   31.45 -                curr_identity->username = NULL;
   31.46 -                status = update_identity(session, curr_identity);
   31.47 -                if (name_bak && 
   31.48 -                    (EMPTYSTR(curr_identity->username) || strcmp(name_bak, curr_identity->username) != 0)) {
   31.49 -                    free(curr_identity->username);
   31.50 -                    curr_identity->username = name_bak;
   31.51 -                }                        
   31.52 -            }
   31.53 -            else
   31.54 -                status = myself(session, curr_identity);
   31.55 -        if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
   31.56 -            return status;
   31.57 -        }
   31.58 +static PEP_STATUS encrypt_PGP_inline(
   31.59 +        PEP_SESSION session,
   31.60 +        const message *src,
   31.61 +        stringlist_t *keys,
   31.62 +        message *dst,
   31.63 +        PEP_encrypt_flags_t flags
   31.64 +    )
   31.65 +{
   31.66 +    char *ctext = NULL;
   31.67 +    size_t csize = 0;
   31.68 +
   31.69 +    PEP_STATUS status = encrypt_and_sign(session, keys, src->longmsg,
   31.70 +            strlen(src->longmsg), &ctext, &csize);
   31.71 +    if (status)
   31.72 +        return status;
   31.73 +
   31.74 +    dst->enc_format = PEP_enc_inline;
   31.75 +
   31.76 +    // shortmsg is being copied
   31.77 +    if (src->shortmsg) {
   31.78 +        dst->shortmsg = strdup(src->shortmsg);
   31.79 +        assert(dst->shortmsg);
   31.80 +        if (!dst->shortmsg)
   31.81 +            return PEP_OUT_OF_MEMORY;
   31.82      }
   31.83 -    
   31.84 -    return PEP_STATUS_OK;                                  
   31.85 +
   31.86 +    // id is staying the same
   31.87 +    if (src->id) {
   31.88 +        dst->id = strdup(src->id);
   31.89 +        assert(dst->id);
   31.90 +        if (!dst->id)
   31.91 +            return PEP_OUT_OF_MEMORY;
   31.92 +    }
   31.93 +
   31.94 +    char *_ctext = realloc(ctext, csize + 1);
   31.95 +    assert(_ctext);
   31.96 +    if (!_ctext)
   31.97 +        return PEP_OUT_OF_MEMORY;
   31.98 +    _ctext[csize] = 0;
   31.99 +
  31.100 +    dst->longmsg = _ctext;
  31.101 +
  31.102 +    // longmsg_formatted is unsupported
  31.103 +
  31.104 +    // attachments are going unencrypted
  31.105 +    bloblist_t *bl = bloblist_dup(src->attachments);
  31.106 +    if (!bl)
  31.107 +        return PEP_OUT_OF_MEMORY;
  31.108 +    dst->attachments = bl;
  31.109 +
  31.110 +    return PEP_STATUS_OK;
  31.111  }
  31.112  
  31.113  static PEP_STATUS encrypt_PGP_MIME(
  31.114 @@ -1100,6 +1113,19 @@
  31.115      return status;
  31.116  }
  31.117  
  31.118 +static bool _has_PGP_MIME_format(message* msg) {
  31.119 +    if (!msg || !msg->attachments || !msg->attachments->next)
  31.120 +        return false;
  31.121 +    if (msg->attachments->next->next)
  31.122 +        return false;
  31.123 +    if (!msg->attachments->mime_type ||
  31.124 +        strcmp(msg->attachments->mime_type, "application/pgp-encrypted") != 0)    
  31.125 +        return false;
  31.126 +    if (!msg->attachments->next->mime_type || 
  31.127 +        strcmp(msg->attachments->next->mime_type, "application/octet-stream") != 0)        
  31.128 +        return false;
  31.129 +    return true;    
  31.130 +}
  31.131  
  31.132  static PEP_rating _rating(PEP_comm_type ct)
  31.133  {
  31.134 @@ -1306,7 +1332,8 @@
  31.135      if (!is_me(session, ident))
  31.136          status = update_identity(session, ident);
  31.137      else
  31.138 -        status = myself(session, ident);
  31.139 +        // ???
  31.140 +        status = _myself(session, ident, false, false, true);
  31.141  
  31.142      if (status == PEP_STATUS_OK) {
  31.143          if (ident->comm_type == PEP_ct_compromised)
  31.144 @@ -1360,15 +1387,15 @@
  31.145      return comm_type;
  31.146  }
  31.147  
  31.148 -static void free_bl_entry(bloblist_t *bl)
  31.149 -{
  31.150 -    if (bl) {
  31.151 -        free(bl->value);
  31.152 -        free(bl->mime_type);
  31.153 -        free(bl->filename);
  31.154 -        free(bl);
  31.155 -    }
  31.156 -}
  31.157 +// static void free_bl_entry(bloblist_t *bl)
  31.158 +// {
  31.159 +//     if (bl) {
  31.160 +//         free(bl->value);
  31.161 +//         free(bl->mime_type);
  31.162 +//         free(bl->filename);
  31.163 +//         free(bl);
  31.164 +//     }
  31.165 +// }
  31.166  
  31.167  static bool is_key(const bloblist_t *bl)
  31.168  {
  31.169 @@ -1389,33 +1416,52 @@
  31.170             );
  31.171  }
  31.172  
  31.173 -static void remove_attached_keys(message *msg)
  31.174 -{
  31.175 -    if (msg) {
  31.176 -        bloblist_t *last = NULL;
  31.177 -        for (bloblist_t *bl = msg->attachments; bl && bl->value; ) {
  31.178 -            bloblist_t *next = bl->next;
  31.179 -
  31.180 -            if (is_key(bl)) {
  31.181 -                if (last) {
  31.182 -                    last->next = next;
  31.183 -                }
  31.184 -                else {
  31.185 -                    msg->attachments = next;
  31.186 -                }
  31.187 -                free_bl_entry(bl);
  31.188 -            }
  31.189 -            else {
  31.190 -                last = bl;
  31.191 -            }
  31.192 -            bl = next;
  31.193 -        }
  31.194 +// static void remove_attached_keys(message *msg)
  31.195 +// {
  31.196 +//     if (msg) {
  31.197 +//         bloblist_t *last = NULL;
  31.198 +//         for (bloblist_t *bl = msg->attachments; bl && bl->value; ) {
  31.199 +//             bloblist_t *next = bl->next;
  31.200 +// 
  31.201 +//             if (is_key(bl)) {
  31.202 +//                 if (last) {
  31.203 +//                     last->next = next;
  31.204 +//                 }
  31.205 +//                 else {
  31.206 +//                     msg->attachments = next;
  31.207 +//                 }
  31.208 +//                 free_bl_entry(bl);
  31.209 +//             }
  31.210 +//             else {
  31.211 +//                 last = bl;
  31.212 +//             }
  31.213 +//             bl = next;
  31.214 +//         }
  31.215 +//     }
  31.216 +// }
  31.217 +
  31.218 +static bool compare_first_n_bytes(const char* first, const char* second, size_t n) {
  31.219 +    int i;
  31.220 +    for (i = 0; i < n; i++) {
  31.221 +        char num1 = *first;
  31.222 +        char num2 = *second;
  31.223 +
  31.224 +        if (num1 != num2)
  31.225 +            return false;
  31.226 +                    
  31.227 +        if (num1 == '\0') {
  31.228 +            if (num2 == '\0')
  31.229 +                return true;
  31.230 +        }   
  31.231 +        first++;
  31.232 +        second++;                     
  31.233      }
  31.234 +    return true;
  31.235  }
  31.236  
  31.237  bool import_attached_keys(
  31.238          PEP_SESSION session,
  31.239 -        const message *msg,
  31.240 +        message *msg,
  31.241          identity_list **private_idents
  31.242      )
  31.243  {
  31.244 @@ -1428,9 +1474,20 @@
  31.245      bool remove = false;
  31.246  
  31.247      int i = 0;
  31.248 +    
  31.249 +    bloblist_t* prev = NULL;
  31.250 +    
  31.251 +    bool do_not_advance = false;
  31.252 +    const char* pubkey_header = "-----BEGIN PGP PUBLIC KEY BLOCK-----";
  31.253 +    const char* privkey_header = "-----BEGIN PGP PRIVATE KEY BLOCK-----";
  31.254 +    // Hate my magic numbers at your peril, but I don't want a strlen each time
  31.255 +    const size_t PUBKEY_HSIZE = 36;
  31.256 +    const size_t PRIVKEY_HSIZE = 37;
  31.257 +
  31.258      for (bloblist_t *bl = msg->attachments; i < MAX_KEYS_TO_IMPORT && bl && bl->value;
  31.259 -            bl = bl->next, i++)
  31.260 +         i++)
  31.261      {
  31.262 +        do_not_advance = false;
  31.263          if (bl && bl->value && bl->size && bl->size < MAX_KEY_SIZE
  31.264                  && is_key(bl))
  31.265          {
  31.266 @@ -1460,12 +1517,42 @@
  31.267                      // We shouldn't delete it or import it, because we can't
  31.268                      // do the latter.
  31.269                      free(bl_ptext);
  31.270 +                    prev = bl;
  31.271 +                    bl = bl->next;
  31.272                      continue;
  31.273                  }
  31.274              }
  31.275              identity_list *local_private_idents = NULL;
  31.276 -            import_key(session, blob_value, blob_size, &local_private_idents);
  31.277 -            remove = true;
  31.278 +            PEP_STATUS import_status = import_key(session, blob_value, blob_size, &local_private_idents);
  31.279 +            bloblist_t* to_delete = NULL;
  31.280 +            switch (import_status) {
  31.281 +                case PEP_NO_KEY_IMPORTED:
  31.282 +                    break;
  31.283 +                case PEP_KEY_IMPORT_STATUS_UNKNOWN:
  31.284 +                    // We'll delete armoured stuff, at least
  31.285 +                    if (blob_size <= PUBKEY_HSIZE)
  31.286 +                        break;
  31.287 +                    if ((!compare_first_n_bytes(pubkey_header, (const char*)blob_value, PUBKEY_HSIZE)) &&
  31.288 +                       (!compare_first_n_bytes(privkey_header, (const char*)blob_value, PRIVKEY_HSIZE)))
  31.289 +                        break;
  31.290 +                    // else fall through and delete    
  31.291 +                case PEP_KEY_IMPORTED:
  31.292 +                case PEP_STATUS_OK:
  31.293 +                    to_delete = bl;
  31.294 +                    if (prev)
  31.295 +                        prev->next = bl->next;
  31.296 +                    else
  31.297 +                        msg->attachments = bl->next;
  31.298 +                    bl = bl->next;
  31.299 +                    to_delete->next = NULL;
  31.300 +                    free_bloblist(to_delete);
  31.301 +                    do_not_advance = true;
  31.302 +                    remove = true;
  31.303 +                    break;
  31.304 +                default:  
  31.305 +                    // bad stuff, but ok.
  31.306 +                    break;
  31.307 +            }
  31.308              if (private_idents && *private_idents == NULL && local_private_idents != NULL)
  31.309                  *private_idents = local_private_idents;
  31.310              else
  31.311 @@ -1473,6 +1560,10 @@
  31.312              if (free_blobval)
  31.313                  free(blob_value);
  31.314          }
  31.315 +        if (!do_not_advance) {
  31.316 +            prev = bl;
  31.317 +            bl = bl->next;
  31.318 +        }
  31.319      }
  31.320      return remove;
  31.321  }
  31.322 @@ -1537,7 +1628,7 @@
  31.323      assert(msg);
  31.324  
  31.325      if (is_PGP_message_text(msg->longmsg)) {
  31.326 -        msg->enc_format = PEP_enc_pieces;
  31.327 +        msg->enc_format = PEP_enc_inline;
  31.328          return PEP_crypt_OpenPGP;
  31.329      }
  31.330      else if (msg->attachments && msg->attachments->next &&
  31.331 @@ -1569,8 +1660,9 @@
  31.332      char* longmsg = NULL;
  31.333      char* shortmsg = NULL;
  31.334      char* msg_wrap_info = NULL;
  31.335 -    separate_short_and_long(src->longmsg, &shortmsg, &msg_wrap_info,
  31.336 -                            &longmsg);
  31.337 +    if (src->longmsg)
  31.338 +        separate_short_and_long(src->longmsg, &shortmsg, &msg_wrap_info,
  31.339 +                                &longmsg);
  31.340      if (longmsg) {                    
  31.341          free(src->longmsg);
  31.342          free(shortmsg);
  31.343 @@ -1846,7 +1938,7 @@
  31.344      }
  31.345      else {
  31.346          // FIXME - we need to deal with transport types (via flag)
  31.347 -        if ((!force_v_1) && ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp)) {
  31.348 +        if ((enc_format != PEP_enc_inline) && (!force_v_1) && ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp)) {
  31.349              message_wrap_type wrap_type = ((flags & PEP_encrypt_flag_key_reset_only) ? PEP_message_key_reset : PEP_message_default);
  31.350              _src = wrap_message_as_attachment(NULL, src, wrap_type, false);
  31.351              if (!_src)
  31.352 @@ -1854,7 +1946,7 @@
  31.353          }
  31.354          else {
  31.355              // hide subject
  31.356 -            if (!session->unencrypted_subject) {
  31.357 +            if (enc_format != PEP_enc_inline && !session->unencrypted_subject) {
  31.358                  status = replace_subject(_src);
  31.359                  if (status == PEP_OUT_OF_MEMORY)
  31.360                      goto enomem;
  31.361 @@ -1875,9 +1967,9 @@
  31.362                  status = encrypt_PGP_MIME(session, _src, keys, msg, flags);
  31.363                  break;
  31.364  
  31.365 -            /* case PEP_enc_PEP:
  31.366 -                // TODO: implement
  31.367 -                NOT_IMPLEMENTED */
  31.368 +            case PEP_enc_inline:
  31.369 +                status = encrypt_PGP_inline(session, _src, keys, msg, flags);
  31.370 +                break;
  31.371  
  31.372              default:
  31.373                  assert(0);
  31.374 @@ -2210,6 +2302,10 @@
  31.375                  _cleanup_src(src, false);
  31.376              break;
  31.377  
  31.378 +        case PEP_enc_inline:
  31.379 +            status = encrypt_PGP_inline(session, _src, keys, msg, flags);
  31.380 +            break;
  31.381 +
  31.382          default:
  31.383              assert(0);
  31.384              status = PEP_ILLEGAL_VALUE;
  31.385 @@ -2550,7 +2646,7 @@
  31.386      
  31.387      switch (src->enc_format) {
  31.388          case PEP_enc_PGP_MIME:
  31.389 -        case PEP_enc_pieces:
  31.390 +        case PEP_enc_inline:
  31.391          case PEP_enc_PGP_MIME_Outlook1:
  31.392  //        case PEP_enc_none: // FIXME - this is wrong
  31.393  
  31.394 @@ -2642,7 +2738,7 @@
  31.395              *text_size = src->attachments->size;
  31.396              break;
  31.397  
  31.398 -        case PEP_enc_pieces:
  31.399 +        case PEP_enc_inline:
  31.400              *crypto_text = src->longmsg;
  31.401              *text_size = strlen(*crypto_text);
  31.402              break;
  31.403 @@ -2770,6 +2866,15 @@
  31.404                                          
  31.405              free_stringlist(_keylist);
  31.406  
  31.407 +            char* filename_uri = NULL;
  31.408 +
  31.409 +            bool has_uri_prefix = (pgp_filename ? (is_file_uri(pgp_filename) || is_cid_uri(pgp_filename)) :
  31.410 +                                                  (_s->filename ? (is_file_uri(_s->filename) || is_cid_uri(_s->filename)) :
  31.411 +                                                                  false
  31.412 +                                                  )
  31.413 +                                  );
  31.414 +            
  31.415 +
  31.416              if (ptext) {
  31.417                  if (is_encrypted_html_attachment(_s)) {
  31.418                      msg->longmsg_formatted = ptext;
  31.419 @@ -2778,9 +2883,14 @@
  31.420                  else {
  31.421                      static const char * const mime_type = "application/octet-stream";                    
  31.422                      if (pgp_filename) {
  31.423 +                        if (!has_uri_prefix)
  31.424 +                            filename_uri = build_uri("file", pgp_filename);
  31.425 +
  31.426                          _m = bloblist_add(_m, ptext, psize, mime_type,
  31.427 -                             pgp_filename);
  31.428 -                        free(pgp_filename);                        
  31.429 +                             (filename_uri ? filename_uri : pgp_filename));
  31.430 +
  31.431 +                        free(pgp_filename);
  31.432 +                        free(filename_uri);
  31.433                          if (_m == NULL)
  31.434                              return PEP_OUT_OF_MEMORY;
  31.435                      }
  31.436 @@ -2790,9 +2900,13 @@
  31.437                          if (filename == NULL)
  31.438                              return PEP_OUT_OF_MEMORY;
  31.439  
  31.440 +                        if (!has_uri_prefix)
  31.441 +                            filename_uri = build_uri("file", filename);
  31.442 +
  31.443                          _m = bloblist_add(_m, ptext, psize, mime_type,
  31.444 -                            filename);
  31.445 +                             (filename_uri ? filename_uri : filename));
  31.446                          free(filename);
  31.447 +                        free(filename_uri);
  31.448                          if (_m == NULL)
  31.449                              return PEP_OUT_OF_MEMORY;
  31.450                      }
  31.451 @@ -2808,7 +2922,12 @@
  31.452                  if (copy == NULL)
  31.453                      return PEP_OUT_OF_MEMORY;
  31.454                  memcpy(copy, _s->value, _s->size);
  31.455 -                _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
  31.456 +
  31.457 +                if (!has_uri_prefix && _s->filename)
  31.458 +                    filename_uri = build_uri("file", _s->filename);
  31.459 +
  31.460 +                _m = bloblist_add(_m, copy, _s->size, _s->mime_type, 
  31.461 +                        (filename_uri ? filename_uri : _s->filename));
  31.462                  if (_m == NULL)
  31.463                      return PEP_OUT_OF_MEMORY;
  31.464              }
  31.465 @@ -2819,7 +2938,13 @@
  31.466              if (copy == NULL)
  31.467                  return PEP_OUT_OF_MEMORY;
  31.468              memcpy(copy, _s->value, _s->size);
  31.469 -            _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
  31.470 +
  31.471 +            char* filename_uri = NULL;
  31.472 +
  31.473 +            _m = bloblist_add(_m, copy, _s->size, _s->mime_type, 
  31.474 +                    ((_s->filename && !(is_file_uri(_s->filename) || is_cid_uri(_s->filename))) ?
  31.475 +                         (filename_uri = build_uri("file", _s->filename)) : _s->filename));
  31.476 +            free(filename_uri);
  31.477              if (_m == NULL)
  31.478                  return PEP_OUT_OF_MEMORY;
  31.479          }
  31.480 @@ -2829,23 +2954,30 @@
  31.481  }
  31.482  
  31.483  static PEP_STATUS import_priv_keys_from_decrypted_msg(PEP_SESSION session,
  31.484 -                                                      message* src, 
  31.485                                                        message* msg,
  31.486                                                        bool* imported_keys,
  31.487                                                        bool* imported_private,
  31.488 -                                                      identity_list** private_il) {
  31.489 -                                                          
  31.490 +                                                      identity_list** private_il)
  31.491 +{
  31.492 +    assert(msg && imported_keys && imported_private);
  31.493 +    if (!(msg && imported_keys && imported_private))
  31.494 +        return PEP_ILLEGAL_VALUE;
  31.495 +
  31.496      PEP_STATUS status = PEP_STATUS_OK;
  31.497 -    
  31.498 +    *imported_keys = NULL;
  31.499 +    *imported_private = false;
  31.500 +    if (private_il)
  31.501 +        *private_il = NULL;
  31.502 +
  31.503      // check for private key in decrypted message attachment while importing
  31.504      identity_list *_private_il = NULL;
  31.505 -    *imported_keys = import_attached_keys(session, msg, &_private_il);
  31.506 -    
  31.507 -    if (_private_il && identity_list_length(_private_il) == 1 &&
  31.508 -        _private_il->ident->address)
  31.509 -        *imported_private = true;
  31.510 -
  31.511 -    if (private_il && imported_private) {
  31.512 +
  31.513 +    bool _imported_keys = import_attached_keys(session, msg, &_private_il);
  31.514 +    bool _imported_private = false;
  31.515 +    if (_private_il && _private_il->ident && _private_il->ident->address)
  31.516 +        _imported_private = true;
  31.517 +
  31.518 +    if (private_il && _imported_private) {
  31.519          // the private identity list should NOT be subject to myself() or
  31.520          // update_identity() at this point.
  31.521          // If the receiving app wants them to be in the trust DB, it
  31.522 @@ -2855,30 +2987,35 @@
  31.523          char* own_id = NULL;
  31.524          status = get_default_own_userid(session, &own_id);
  31.525          
  31.526 -        if (status != PEP_STATUS_OK) {
  31.527 -            free(own_id);
  31.528 -            own_id = NULL;
  31.529 -        }
  31.530 -        
  31.531 -        identity_list* il = _private_il;
  31.532 -        for ( ; il; il = il->next) {
  31.533 +        for (identity_list* il = _private_il; il; il = il->next) {
  31.534              if (own_id) {
  31.535                  free(il->ident->user_id);
  31.536                  il->ident->user_id = strdup(own_id);
  31.537 +                assert(il->ident->user_id);
  31.538 +                if (!il->ident->user_id) {
  31.539 +                    status = PEP_OUT_OF_MEMORY;
  31.540 +                    break;
  31.541 +                }
  31.542              }
  31.543              il->ident->me = true;
  31.544          }
  31.545 -        *private_il = _private_il;
  31.546 -        
  31.547          free(own_id);
  31.548 +        if (!status)
  31.549 +            *private_il = _private_il;
  31.550      }
  31.551 -    else
  31.552 +    else {
  31.553          free_identity_list(_private_il);
  31.554 +    }
  31.555   
  31.556 -    
  31.557 +    if (!status) {
  31.558 +        *imported_keys = _imported_keys;
  31.559 +        *imported_private = _imported_private;
  31.560 +    }
  31.561 +
  31.562      return status;
  31.563  }
  31.564  
  31.565 +// FIXME: myself ??????
  31.566  static PEP_STATUS update_sender_to_pEp_trust(
  31.567          PEP_SESSION session, 
  31.568          pEp_identity* sender, 
  31.569 @@ -2951,6 +3088,8 @@
  31.570      }
  31.571      
  31.572      resultid->lang[0] = srcid->lang[0];
  31.573 +    resultid->lang[1] = srcid->lang[1];
  31.574 +    resultid->lang[2] = 0;
  31.575      resultid->me = srcid->me;
  31.576      resultid->flags = srcid->flags;
  31.577  
  31.578 @@ -3102,7 +3241,7 @@
  31.579          return false;
  31.580      PEP_STATUS status = import_key(session, the_key->value, the_key->size, NULL);
  31.581      free_bloblist(the_key);
  31.582 -    if (status == PEP_STATUS_OK)
  31.583 +    if (status == PEP_STATUS_OK || status == PEP_KEY_IMPORTED)
  31.584          return true;
  31.585      return false;
  31.586  }
  31.587 @@ -3173,7 +3312,7 @@
  31.588  
  31.589  }
  31.590  
  31.591 -DYNAMIC_API PEP_STATUS _decrypt_message(
  31.592 +static PEP_STATUS _decrypt_message(
  31.593          PEP_SESSION session,
  31.594          message *src,
  31.595          message **dst,
  31.596 @@ -3183,7 +3322,6 @@
  31.597          identity_list **private_il
  31.598      )
  31.599  {
  31.600 -    
  31.601      assert(session);
  31.602      assert(src);
  31.603      assert(dst);
  31.604 @@ -3209,6 +3347,7 @@
  31.605      stringlist_t *_keylist = NULL;
  31.606      char* signer_fpr = NULL;
  31.607      bool is_pEp_msg = is_a_pEpmessage(src);
  31.608 +    bool myself_read_only = (src->dir == PEP_dir_incoming);
  31.609  
  31.610      // Grab input flags
  31.611      bool reencrypt = (((*flags & PEP_decrypt_flag_untrusted_server) > 0) && *keylist && !EMPTYSTR((*keylist)->value));
  31.612 @@ -3258,7 +3397,13 @@
  31.613  
  31.614      /*** Begin Import any attached public keys and update identities accordingly ***/
  31.615      // Private key in unencrypted mail are ignored -> NULL
  31.616 -    bool imported_keys = import_attached_keys(session, src, NULL);
  31.617 +    //
  31.618 +    // This import is from the outermost message.
  31.619 +    // We don't do this for PGP_mime.
  31.620 +    bool imported_keys = false;
  31.621 +    if (!_has_PGP_MIME_format(src))
  31.622 +        imported_keys = import_attached_keys(session, src, NULL);
  31.623 +            
  31.624      import_header_keys(session, src);
  31.625      
  31.626      // FIXME: is this really necessary here?
  31.627 @@ -3266,7 +3411,7 @@
  31.628          if (!is_me(session, src->from))
  31.629              status = update_identity(session, src->from);
  31.630          else
  31.631 -            status = myself(session, src->from);
  31.632 +            status = _myself(session, src->from, false, false, myself_read_only);
  31.633          
  31.634          // We absolutely should NOT be bailing here unless it's a serious error
  31.635          if (status == PEP_OUT_OF_MEMORY)
  31.636 @@ -3295,8 +3440,9 @@
  31.637  
  31.638          *rating = PEP_rating_unencrypted;
  31.639  
  31.640 -        if (imported_keys)
  31.641 -            remove_attached_keys(src);
  31.642 +        // We remove these from the outermost source message
  31.643 +        // if (imported_keys)
  31.644 +        //     remove_attached_keys(src);
  31.645                                      
  31.646          pull_up_attached_main_msg(src);
  31.647          
  31.648 @@ -3346,7 +3492,10 @@
  31.649                  // N.B. Apparently, we always import private keys into the keyring; however,
  31.650                  // we do NOT always allow those to be used for encryption. THAT is controlled
  31.651                  // by setting it as an own identity associated with the key in the DB.
  31.652 -                status = import_priv_keys_from_decrypted_msg(session, src, msg,
  31.653 +                //
  31.654 +                // We are importing from the decrypted outermost message now.
  31.655 +                //
  31.656 +                status = import_priv_keys_from_decrypted_msg(session, msg,
  31.657                                                               &imported_keys,
  31.658                                                               &imported_private_key_address,
  31.659                                                               private_il);
  31.660 @@ -3366,7 +3515,7 @@
  31.661                  }
  31.662                  break;
  31.663  
  31.664 -            case PEP_enc_pieces:
  31.665 +            case PEP_enc_inline:
  31.666                  status = PEP_STATUS_OK;
  31.667                  
  31.668                  _decrypt_in_pieces_status = _decrypt_in_pieces(session, src, &msg, ptext, psize);
  31.669 @@ -3469,9 +3618,11 @@
  31.670                                              // If we have a message 2.0 message, we are ONLY going to be ok with keys
  31.671                                              // we imported from THIS part of the message.
  31.672                                              imported_private_key_address = false;
  31.673 -                                            free(private_il);
  31.674 +                                            free(private_il); 
  31.675                                              private_il = NULL;
  31.676 -                                            status = import_priv_keys_from_decrypted_msg(session, src, inner_message,
  31.677 +                                            
  31.678 +                                            // import keys from decrypted INNER source
  31.679 +                                            status = import_priv_keys_from_decrypted_msg(session, inner_message,
  31.680                                                                                           &imported_keys,
  31.681                                                                                           &imported_private_key_address,
  31.682                                                                                           private_il);
  31.683 @@ -3494,7 +3645,7 @@
  31.684                                                  if (!is_me(session, src->from))
  31.685                                                      update_identity(session, (src->from));
  31.686                                                  else
  31.687 -                                                    myself(session, src->from);
  31.688 +                                                    _myself(session, src->from, false, false, myself_read_only);
  31.689                                              }
  31.690                                              break;        
  31.691                                          }
  31.692 @@ -3576,9 +3727,10 @@
  31.693          
  31.694          /* add pEp-related status flags to header */
  31.695          decorate_message(msg, *rating, _keylist, false, false);
  31.696 -        
  31.697 -        if (imported_keys)
  31.698 -            remove_attached_keys(msg);
  31.699 +
  31.700 +        // Maybe unnecessary
  31.701 +        // if (imported_keys)
  31.702 +        //     remove_attached_keys(msg);
  31.703                      
  31.704          if (calculated_src->id && calculated_src != msg) {
  31.705              msg->id = strdup(calculated_src->id);
  31.706 @@ -3737,22 +3889,17 @@
  31.707  
  31.708      message *msg = *dst ? *dst : src;
  31.709  
  31.710 -    if (session->inject_sync_event && msg && msg->from) {
  31.711 +    if (session->inject_sync_event && msg && msg->from &&
  31.712 +            !(*flags & PEP_decrypt_flag_dont_trigger_sync)) {
  31.713          size_t size;
  31.714          const char *data;
  31.715          char *sync_fpr = NULL;
  31.716 -        status = base_extract_message(session, msg, &size, &data, &sync_fpr);
  31.717 -        if (!status && size && data) {
  31.718 -            pEp_identity *_from = identity_dup(msg->from);
  31.719 -            if (!_from) {
  31.720 -                free_message(*dst);
  31.721 -                *dst = NULL;
  31.722 -                free_stringlist(*keylist);
  31.723 -                *keylist = NULL;
  31.724 -                return PEP_OUT_OF_MEMORY;
  31.725 -            }
  31.726 -            session->sync_state.common.from = _from;
  31.727 -            signal_Sync_message(session, *rating, data, size, sync_fpr);
  31.728 +        PEP_STATUS tmpstatus = base_extract_message(session, msg, &size, &data, &sync_fpr);
  31.729 +        if (!tmpstatus && size && data) {
  31.730 +            if (sync_fpr)
  31.731 +                signal_Sync_message(session, *rating, data, size, msg->from, sync_fpr);
  31.732 +            else if (*keylist)
  31.733 +                signal_Sync_message(session, *rating, data, size, msg->from, (*keylist)->value);
  31.734          }
  31.735          free(sync_fpr);
  31.736      }
  31.737 @@ -3957,8 +4104,10 @@
  31.738      if (!(session && ident && rating))
  31.739          return PEP_ILLEGAL_VALUE;
  31.740  
  31.741 +    *rating = PEP_rating_undefined;
  31.742 +
  31.743      if (ident->me)
  31.744 -        status = _myself(session, ident, false, true);
  31.745 +        status = _myself(session, ident, false, true, true);
  31.746      else
  31.747          status = update_identity(session, ident);
  31.748  
  31.749 @@ -4307,10 +4456,21 @@
  31.750      // Find own identity corresponding to given account address.
  31.751      // In that case we want default key attached to own identity
  31.752      pEp_identity *stored_identity = NULL;
  31.753 +    
  31.754 +    char* own_id = NULL;
  31.755 +    status = get_default_own_userid(session, &own_id);
  31.756 +
  31.757 +    if (!(status == PEP_STATUS_OK && own_id)) {
  31.758 +        free(own_id);
  31.759 +        return PEP_CANNOT_FIND_IDENTITY;
  31.760 +    }
  31.761 +    
  31.762      status = get_identity(session,
  31.763                            received_by->address,
  31.764 -                          PEP_OWN_USERID,
  31.765 +                          own_id,
  31.766                            &stored_identity);
  31.767 +    free(own_id);
  31.768 +    own_id = NULL;                      
  31.769  
  31.770      if (status != PEP_STATUS_OK) {
  31.771          free_identity(stored_identity);
  31.772 @@ -4326,227 +4486,6 @@
  31.773      return status;
  31.774  }
  31.775  
  31.776 -DYNAMIC_API PEP_STATUS MIME_decrypt_message(
  31.777 -    PEP_SESSION session,
  31.778 -    const char *mimetext,
  31.779 -    size_t size,
  31.780 -    char** mime_plaintext,
  31.781 -    stringlist_t **keylist,
  31.782 -    PEP_rating *rating,
  31.783 -    PEP_decrypt_flags_t *flags,
  31.784 -    char** modified_src
  31.785 -)
  31.786 -{
  31.787 -    assert(mimetext);
  31.788 -    assert(mime_plaintext);
  31.789 -    assert(keylist);
  31.790 -    assert(rating);
  31.791 -    assert(flags);
  31.792 -    assert(modified_src);
  31.793 -
  31.794 -    if (!(mimetext && mime_plaintext && keylist && rating && flags && modified_src))
  31.795 -        return PEP_ILLEGAL_VALUE;
  31.796 -        
  31.797 -    PEP_STATUS status = PEP_STATUS_OK;
  31.798 -    message* tmp_msg = NULL;
  31.799 -    message* dec_msg = NULL;
  31.800 -    *mime_plaintext = NULL;
  31.801 -
  31.802 -    status = mime_decode_message(mimetext, size, &tmp_msg);
  31.803 -    if (status != PEP_STATUS_OK)
  31.804 -        goto pEp_error;
  31.805 -
  31.806 -    // MIME decode message delivers only addresses. We need more.
  31.807 -    if (tmp_msg->from) {
  31.808 -        if (!is_me(session, tmp_msg->from))
  31.809 -            status = update_identity(session, (tmp_msg->from));
  31.810 -        else
  31.811 -            status = myself(session, tmp_msg->from);
  31.812 -
  31.813 -        if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
  31.814 -            goto pEp_error;
  31.815 -    }
  31.816 -
  31.817 -    status = update_identity_recip_list(session, tmp_msg->to);
  31.818 -    if (status != PEP_STATUS_OK)
  31.819 -        goto pEp_error;
  31.820 -
  31.821 -    status = update_identity_recip_list(session, tmp_msg->cc);
  31.822 -    if (status != PEP_STATUS_OK)
  31.823 -        goto pEp_error;
  31.824 -
  31.825 -    status = update_identity_recip_list(session, tmp_msg->bcc);
  31.826 -    if (status != PEP_STATUS_OK)
  31.827 -        goto pEp_error;
  31.828 -
  31.829 -    PEP_STATUS decrypt_status = decrypt_message(session,
  31.830 -                                                tmp_msg,
  31.831 -                                                &dec_msg,
  31.832 -                                                keylist,
  31.833 -                                                rating,
  31.834 -                                                flags);
  31.835 -
  31.836 -
  31.837 -    if (!dec_msg && (decrypt_status == PEP_UNENCRYPTED || decrypt_status == PEP_VERIFIED)) {
  31.838 -        dec_msg = message_dup(tmp_msg);
  31.839 -    }
  31.840 -    
  31.841 -    if (decrypt_status > PEP_CANNOT_DECRYPT_UNKNOWN || !dec_msg)
  31.842 -    {
  31.843 -        status = decrypt_status;
  31.844 -        goto pEp_error;
  31.845 -    }
  31.846 -
  31.847 -    if (*flags & PEP_decrypt_flag_src_modified) {
  31.848 -        _mime_encode_message_internal(tmp_msg, false, modified_src, true);
  31.849 -        if (!modified_src) {
  31.850 -            *flags &= (~PEP_decrypt_flag_src_modified);
  31.851 -            decrypt_status = PEP_CANNOT_REENCRYPT; // Because we couldn't return it, I guess.
  31.852 -        }
  31.853 -    }
  31.854 -
  31.855 -    // FIXME: test with att
  31.856 -    status = _mime_encode_message_internal(dec_msg, false, mime_plaintext, true);
  31.857 -
  31.858 -    if (status == PEP_STATUS_OK)
  31.859 -    {
  31.860 -        free(tmp_msg);
  31.861 -        free(dec_msg);
  31.862 -        return decrypt_status;
  31.863 -    }
  31.864 -    
  31.865 -pEp_error:
  31.866 -    free_message(tmp_msg);
  31.867 -    free_message(dec_msg);
  31.868 -
  31.869 -    return status;
  31.870 -}
  31.871 -
  31.872 -
  31.873 -DYNAMIC_API PEP_STATUS MIME_encrypt_message(
  31.874 -    PEP_SESSION session,
  31.875 -    const char *mimetext,
  31.876 -    size_t size,
  31.877 -    stringlist_t* extra,
  31.878 -    char** mime_ciphertext,
  31.879 -    PEP_enc_format enc_format,
  31.880 -    PEP_encrypt_flags_t flags
  31.881 -)
  31.882 -{
  31.883 -    PEP_STATUS status = PEP_STATUS_OK;
  31.884 -    message* tmp_msg = NULL;
  31.885 -    message* enc_msg = NULL;
  31.886 -
  31.887 -    status = mime_decode_message(mimetext, size, &tmp_msg);
  31.888 -    if (status != PEP_STATUS_OK)
  31.889 -        goto pEp_error;
  31.890 -
  31.891 -    // MIME decode message delivers only addresses. We need more.
  31.892 -    if (tmp_msg->from) {
  31.893 -        char* own_id = NULL;
  31.894 -        status = get_default_own_userid(session, &own_id);
  31.895 -        free(tmp_msg->from->user_id);
  31.896 -        
  31.897 -        if (status != PEP_STATUS_OK || !own_id) {
  31.898 -            tmp_msg->from->user_id = strdup(PEP_OWN_USERID);
  31.899 -        }
  31.900 -        else {
  31.901 -            tmp_msg->from->user_id = own_id; // ownership transfer
  31.902 -        }
  31.903 -            
  31.904 -        status = myself(session, tmp_msg->from);
  31.905 -        if (status != PEP_STATUS_OK)
  31.906 -            goto pEp_error;
  31.907 -    }
  31.908 -    
  31.909 -    // Own identities can be retrieved here where they would otherwise
  31.910 -    // fail because we lack all other information. This is ok and even
  31.911 -    // desired. FIXME: IS it?
  31.912 -    status = update_identity_recip_list(session, tmp_msg->to);
  31.913 -    if (status != PEP_STATUS_OK)
  31.914 -        goto pEp_error;
  31.915 -    
  31.916 -    status = update_identity_recip_list(session, tmp_msg->cc);
  31.917 -    if (status != PEP_STATUS_OK)
  31.918 -        goto pEp_error;
  31.919 -    
  31.920 -    status = update_identity_recip_list(session, tmp_msg->bcc);
  31.921 -    if (status != PEP_STATUS_OK)
  31.922 -        goto pEp_error;
  31.923 -    
  31.924 -    // This isn't incoming, though... so we need to reverse the direction
  31.925 -    tmp_msg->dir = PEP_dir_outgoing;
  31.926 -    status = encrypt_message(session,
  31.927 -                             tmp_msg,
  31.928 -                             extra,
  31.929 -                             &enc_msg,
  31.930 -                             enc_format,
  31.931 -                             flags);
  31.932 -                             
  31.933 -    if (status != PEP_STATUS_OK)
  31.934 -        goto pEp_error;
  31.935 -
  31.936 -
  31.937 -    if (!enc_msg) {
  31.938 -        status = PEP_UNKNOWN_ERROR;
  31.939 -        goto pEp_error;
  31.940 -    }
  31.941 -
  31.942 -    status = _mime_encode_message_internal(enc_msg, false, mime_ciphertext, false);
  31.943 -
  31.944 -pEp_error:
  31.945 -    free_message(tmp_msg);
  31.946 -    free_message(enc_msg);
  31.947 -
  31.948 -    return status;
  31.949 -
  31.950 -}
  31.951 -
  31.952 -DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
  31.953 -    PEP_SESSION session,
  31.954 -    pEp_identity* target_id,
  31.955 -    const char *mimetext,
  31.956 -    size_t size,
  31.957 -    stringlist_t* extra,
  31.958 -    char** mime_ciphertext,
  31.959 -    PEP_enc_format enc_format,
  31.960 -    PEP_encrypt_flags_t flags
  31.961 -)
  31.962 -{
  31.963 -    PEP_STATUS status = PEP_STATUS_OK;
  31.964 -    message* tmp_msg = NULL;
  31.965 -    message* enc_msg = NULL;
  31.966 -
  31.967 -    status = mime_decode_message(mimetext, size, &tmp_msg);
  31.968 -    if (status != PEP_STATUS_OK)
  31.969 -        goto pEp_error;
  31.970 -
  31.971 -    // This isn't incoming, though... so we need to reverse the direction
  31.972 -    tmp_msg->dir = PEP_dir_outgoing;
  31.973 -    status = encrypt_message_for_self(session,
  31.974 -                                      target_id,
  31.975 -                                      tmp_msg,
  31.976 -                                      extra,
  31.977 -                                      &enc_msg,
  31.978 -                                      enc_format,
  31.979 -                                      flags);
  31.980 -    if (status != PEP_STATUS_OK)
  31.981 -        goto pEp_error;
  31.982 - 
  31.983 -    if (!enc_msg) {
  31.984 -        status = PEP_UNKNOWN_ERROR;
  31.985 -        goto pEp_error;
  31.986 -    }
  31.987 -
  31.988 -    status = mime_encode_message(enc_msg, false, mime_ciphertext);
  31.989 -
  31.990 -pEp_error:
  31.991 -    free_message(tmp_msg);
  31.992 -    free_message(enc_msg);
  31.993 -
  31.994 -    return status;
  31.995 -}
  31.996 -
  31.997  static PEP_rating string_to_rating(const char * rating)
  31.998  {
  31.999      if (rating == NULL)
 31.1000 @@ -4679,7 +4618,7 @@
 31.1001      if (!is_me(session, msg->from))
 31.1002          status = update_identity(session, msg->from);
 31.1003      else
 31.1004 -        status = myself(session, msg->from);
 31.1005 +        status = _myself(session, msg->from, false, false, true);
 31.1006  
 31.1007      switch (status) {
 31.1008          case PEP_KEY_NOT_FOUND:
 31.1009 @@ -4738,4 +4677,3 @@
 31.1010      free_identity(ident);
 31.1011      return status;
 31.1012  }
 31.1013 -
    32.1 --- a/src/message_api.h	Thu Mar 28 15:40:45 2019 +0100
    32.2 +++ b/src/message_api.h	Fri May 17 17:30:57 2019 +0200
    32.3 @@ -14,7 +14,7 @@
    32.4  
    32.5  bool import_attached_keys(
    32.6          PEP_SESSION session, 
    32.7 -        const message *msg,
    32.8 +        message *msg,
    32.9          identity_list **private_idents
   32.10      );
   32.11  
   32.12 @@ -159,78 +159,6 @@
   32.13          PEP_encrypt_flags_t flags
   32.14      );
   32.15  
   32.16 -
   32.17 -// MIME_encrypt_message() - encrypt a MIME message, with MIME output
   32.18 -//
   32.19 -//  parameters:
   32.20 -//      session (in)            session handle
   32.21 -//      mimetext (in)           MIME encoded text to encrypt
   32.22 -//      size (in)               size of input mime text
   32.23 -//      extra (in)              extra keys for encryption
   32.24 -//      mime_ciphertext (out)   encrypted, encoded message
   32.25 -//      enc_format (in)         encrypted format
   32.26 -//      flags (in)              flags to set special encryption features
   32.27 -//
   32.28 -//  return value:
   32.29 -//      PEP_STATUS_OK           if everything worked
   32.30 -//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
   32.31 -//      PEP_CANNOT_CREATE_TEMP_FILE
   32.32 -//                              if there are issues with temp files; in
   32.33 -//                              this case errno will contain the underlying
   32.34 -//                              error
   32.35 -//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
   32.36 -//
   32.37 -//  caveat:
   32.38 -//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
   32.39 -//      will remain in the ownership of the caller
   32.40 -DYNAMIC_API PEP_STATUS MIME_encrypt_message(
   32.41 -    PEP_SESSION session,
   32.42 -    const char *mimetext,
   32.43 -    size_t size,
   32.44 -    stringlist_t* extra,
   32.45 -    char** mime_ciphertext,
   32.46 -    PEP_enc_format enc_format,
   32.47 -    PEP_encrypt_flags_t flags
   32.48 -);
   32.49 -
   32.50 -
   32.51 -// MIME_encrypt_message_for_self() - encrypt MIME message for user's identity only,
   32.52 -//                              ignoring recipients and other identities from
   32.53 -//                              the message, with MIME output
   32.54 -//  parameters:
   32.55 -//      session (in)            session handle
   32.56 -//      target_id (in)          self identity this message should be encrypted for
   32.57 -//      mimetext (in)           MIME encoded text to encrypt
   32.58 -//      size (in)               size of input mime text
   32.59 -//      extra (in)              extra keys for encryption
   32.60 -//      mime_ciphertext (out)   encrypted, encoded message
   32.61 -//      enc_format (in)         encrypted format
   32.62 -//      flags (in)              flags to set special encryption features
   32.63 -//
   32.64 -//  return value:
   32.65 -//      PEP_STATUS_OK           if everything worked
   32.66 -//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
   32.67 -//      PEP_CANNOT_CREATE_TEMP_FILE
   32.68 -//                              if there are issues with temp files; in
   32.69 -//                              this case errno will contain the underlying
   32.70 -//                              error
   32.71 -//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
   32.72 -//
   32.73 -//  caveat:
   32.74 -//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
   32.75 -//      will remain in the ownership of the caller
   32.76 -DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
   32.77 -    PEP_SESSION session,
   32.78 -    pEp_identity* target_id,
   32.79 -    const char *mimetext,
   32.80 -    size_t size,
   32.81 -    stringlist_t* extra,
   32.82 -    char** mime_ciphertext,
   32.83 -    PEP_enc_format enc_format,
   32.84 -    PEP_encrypt_flags_t flags
   32.85 -);
   32.86 -
   32.87 -
   32.88  typedef enum _PEP_rating {
   32.89      PEP_rating_undefined = 0,
   32.90      PEP_rating_cannot_decrypt,
   32.91 @@ -270,7 +198,8 @@
   32.92      PEP_decrypt_flag_ignore = 0x4,
   32.93      PEP_decrypt_flag_src_modified = 0x8,
   32.94      // input flags    
   32.95 -    PEP_decrypt_flag_untrusted_server = 0x100
   32.96 +    PEP_decrypt_flag_untrusted_server = 0x100,
   32.97 +    PEP_decrypt_flag_dont_trigger_sync = 0x200,
   32.98  } PEP_decrypt_flags; 
   32.99  
  32.100  typedef unsigned int PEP_decrypt_flags_t;
  32.101 @@ -337,65 +266,6 @@
  32.102          PEP_decrypt_flags_t *flags
  32.103  );
  32.104  
  32.105 -
  32.106 -// MIME_decrypt_message() - decrypt a MIME message, with MIME output
  32.107 -//
  32.108 -//  parameters:
  32.109 -//      session (in)            session handle
  32.110 -//      mimetext (in)           MIME encoded text to decrypt
  32.111 -//      size (in)               size of mime text to decode (in order to decrypt)
  32.112 -//      mime_plaintext (out)    decrypted, encoded message
  32.113 -//      keylist (inout)         in: stringlist with additional keyids for reencryption if needed
  32.114 -//                                  (will be freed and replaced with output keylist)
  32.115 -//                              out: stringlist with keyids
  32.116 -//      rating (out)            rating for the message
  32.117 -//      flags (inout)           flags to signal special decryption features (see below)
  32.118 -//      modified_src (out)      modified source string, if decrypt had reason to change it
  32.119 -//
  32.120 -//  return value:
  32.121 -//      decrypt status          if everything worked with MIME encode/decode, 
  32.122 -//                              the status of the decryption is returned 
  32.123 -//                              (PEP_STATUS_OK or decryption error status)
  32.124 -//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
  32.125 -//      PEP_CANNOT_CREATE_TEMP_FILE
  32.126 -//                              if there are issues with temp files; in
  32.127 -//                              this case errno will contain the underlying
  32.128 -//                              error
  32.129 -//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
  32.130 -//
  32.131 -//  flag values:
  32.132 -//      in:
  32.133 -//          PEP_decrypt_flag_untrusted_server
  32.134 -//              used to signal that decrypt function should engage in behaviour
  32.135 -//              specified for when the server storing the source is untrusted.
  32.136 -//      out:
  32.137 -//          PEP_decrypt_flag_own_private_key
  32.138 -//              private key was imported for one of our addresses (NOT trusted
  32.139 -//              or set to be used - handshake/trust is required for that)
  32.140 -//          PEP_decrypt_flag_src_modified
  32.141 -//              indicates that the modified_src field should contain a modified
  32.142 -//              version of the source, at the moment always as a result of the
  32.143 -//              input flags. 
  32.144 -//          PEP_decrypt_flag_consume
  32.145 -//              used by sync 
  32.146 -//          PEP_decrypt_flag_ignore
  32.147 -//              used by sync 
  32.148 -// 
  32.149 -//  caveat:
  32.150 -//      the decrypted, encoded mime text will go to the ownership of the caller; mimetext
  32.151 -//      will remain in the ownership of the caller
  32.152 -DYNAMIC_API PEP_STATUS MIME_decrypt_message(
  32.153 -    PEP_SESSION session,
  32.154 -    const char *mimetext,
  32.155 -    size_t size,
  32.156 -    char** mime_plaintext,
  32.157 -    stringlist_t **keylist,
  32.158 -    PEP_rating *rating,
  32.159 -    PEP_decrypt_flags_t *flags,
  32.160 -    char** modified_src
  32.161 -);
  32.162 -
  32.163 -
  32.164  // own_message_private_key_details() - details on own key in own message
  32.165  //
  32.166  //  parameters:
    33.1 --- a/src/mime.c	Thu Mar 28 15:40:45 2019 +0100
    33.2 +++ b/src/mime.c	Fri May 17 17:30:57 2019 +0200
    33.3 @@ -1,7 +1,7 @@
    33.4  // This file is under GNU General Public License 3.0
    33.5  // see LICENSE.txt
    33.6  
    33.7 -#include "pEp_internal.h"
    33.8 +#define _EXPORT_PEP_ENGINE_DLL
    33.9  #include "mime.h"
   33.10  
   33.11  #include <string.h>
   33.12 @@ -9,10 +9,6 @@
   33.13  #include <assert.h>
   33.14  #include <errno.h>
   33.15  
   33.16 -#include "resource_id.h"
   33.17 -#include "etpan_mime.h"
   33.18 -#include "wrappers.h"
   33.19 -
   33.20  static bool is_whitespace(char c)
   33.21  {
   33.22      switch (c) {
   33.23 @@ -37,889 +33,6 @@
   33.24      return strncmp(text, "-----BEGIN PGP MESSAGE-----", 27) == 0;
   33.25  }
   33.26  
   33.27 -#define TMP_TEMPLATE "pEp.XXXXXXXXXXXXXXXXXXXX"
   33.28 -#ifdef _WIN32
   33.29 -#define PATH_SEP '\\'
   33.30 -#else
   33.31 -#define PATH_SEP '/'
   33.32 -#endif
   33.33 -
   33.34 -// This function was rewritten to use in-memory buffers instead of
   33.35 -// temporary files when the pgp/mime support was implemented for
   33.36 -// outlook, as the existing code did not work well on windows.
   33.37 -
   33.38 -static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
   33.39 -{
   33.40 -    PEP_STATUS status = PEP_STATUS_OK;
   33.41 -    int col;
   33.42 -    int r;
   33.43 -	size_t len;
   33.44 -	char* buf = NULL;
   33.45 -
   33.46 -	MMAPString* buffer;
   33.47 -
   33.48 -	buffer = mmap_string_new(NULL);
   33.49 -	if (buffer == NULL)
   33.50 -		goto enomem;
   33.51 -	
   33.52 -	col = 0;
   33.53 -	r = mailmime_write_mem(buffer, &col, mime);
   33.54 -	assert(r == MAILIMF_NO_ERROR);
   33.55 -	if (r == MAILIMF_ERROR_MEMORY)
   33.56 -		goto enomem;
   33.57 -	else if (r != MAILIMF_NO_ERROR)
   33.58 -		goto err_file;
   33.59 -
   33.60 -	// we overallocate by 1 byte, so we have a terminating 0.
   33.61 -	len = buffer->len;
   33.62 -	buf = calloc(len + 1, 1);
   33.63 -	if (buf == NULL)
   33.64 -		goto enomem;
   33.65 -
   33.66 -	memcpy(buf, buffer->str, len);
   33.67 -	mmap_string_free(buffer);
   33.68 -
   33.69 -    *mimetext = buf;
   33.70 -    return PEP_STATUS_OK;
   33.71 -
   33.72 -err_file:
   33.73 -    status = PEP_CANNOT_CREATE_TEMP_FILE;
   33.74 -    goto pEp_error;
   33.75 -
   33.76 -enomem:
   33.77 -    status = PEP_OUT_OF_MEMORY;
   33.78 -
   33.79 -pEp_error:
   33.80 -	if (buffer)
   33.81 -		mmap_string_free(buffer);
   33.82 -	if (buf)
   33.83 -		free(buf);
   33.84 -    return status;
   33.85 -}
   33.86 -
   33.87 -static PEP_STATUS mime_attachment(
   33.88 -        bloblist_t *blob,
   33.89 -        struct mailmime **result,
   33.90 -        bool transport_encode
   33.91 -    )
   33.92 -{
   33.93 -    PEP_STATUS status = PEP_STATUS_OK;
   33.94 -    struct mailmime * mime = NULL;
   33.95 -    char * mime_type;
   33.96 -    assert(blob);
   33.97 -    assert(result);
   33.98 -
   33.99 -    *result = NULL;
  33.100 -
  33.101 -// TODO: It seems the pEp COM server adapter sends an empty string here,
  33.102 -// which leads to a crash later. Thus, we workaround here by treating an
  33.103 -// empty string as NULL. We need to check whether the bug really is here,
  33.104 -// or the pEp COM server adapter needs to be changed.
  33.105 -    if (blob->mime_type == NULL || blob->mime_type[0] == '\0')
  33.106 -        mime_type = "application/octet-stream";
  33.107 -    else
  33.108 -        mime_type = blob->mime_type;
  33.109 -
  33.110 -    pEp_rid_list_t* resource = parse_uri(blob->filename);
  33.111 -
  33.112 -    bool already_ascii = !(must_chunk_be_encoded(blob->value, blob->size, true));
  33.113 -
  33.114 -    mime = get_file_part(resource, mime_type, blob->value, blob->size, 
  33.115 -                          (already_ascii ? false : transport_encode));
  33.116 -    free_rid_list(resource);
  33.117 -    
  33.118 -    assert(mime);
  33.119 -    if (mime == NULL)
  33.120 -        goto enomem;
  33.121 -
  33.122 -    *result = mime;
  33.123 -    return PEP_STATUS_OK;
  33.124 -
  33.125 -enomem:
  33.126 -    status = PEP_OUT_OF_MEMORY;
  33.127 -
  33.128 -    if (mime)
  33.129 -        mailmime_free(mime);
  33.130 -
  33.131 -    return status;
  33.132 -}
  33.133 -
  33.134 -static PEP_STATUS mime_html_text(
  33.135 -        const char *plaintext,
  33.136 -        const char *htmltext,
  33.137 -        bloblist_t *attachments,
  33.138 -        struct mailmime **result,
  33.139 -        bool transport_encode
  33.140 -    )
  33.141 -{
  33.142 -    PEP_STATUS status = PEP_STATUS_OK;
  33.143 -    struct mailmime * top_level_html_mime = NULL;
  33.144 -    struct mailmime * mime = NULL;
  33.145 -    struct mailmime * submime = NULL;
  33.146 -    int r;
  33.147 -
  33.148 -    assert(plaintext);
  33.149 -    assert(htmltext);
  33.150 -    assert(result);
  33.151 -
  33.152 -    *result = NULL;
  33.153 -
  33.154 -    mime = part_multiple_new("multipart/alternative");
  33.155 -    assert(mime);
  33.156 -    if (mime == NULL)
  33.157 -        goto enomem;
  33.158 -
  33.159 -    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
  33.160 -    
  33.161 -    int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  33.162 -    submime = get_text_part(NULL, "text/plain", plaintext, strlen(plaintext),
  33.163 -            encoding_type);
  33.164 -    free_rid_list(resource);
  33.165 -    resource = NULL;
  33.166 -    
  33.167 -    assert(submime);
  33.168 -    if (submime == NULL)
  33.169 -        goto enomem;
  33.170 -
  33.171 -    r = mailmime_smart_add_part(mime, submime);
  33.172 -    assert(r == MAILIMF_NO_ERROR);
  33.173 -    if (r == MAILIMF_ERROR_MEMORY) {
  33.174 -        goto enomem;
  33.175 -    }
  33.176 -    else {
  33.177 -        // mailmime_smart_add_part() takes ownership of submime
  33.178 -        submime = NULL;
  33.179 -    }
  33.180 -
  33.181 -    bool inlined_attachments = false;
  33.182 -    
  33.183 -    bloblist_t* traversal_ptr = attachments;
  33.184 -    
  33.185 -    while (traversal_ptr) {
  33.186 -        if (traversal_ptr->disposition == PEP_CONTENT_DISP_INLINE) {
  33.187 -            inlined_attachments = true;
  33.188 -            break;
  33.189 -        }
  33.190 -        traversal_ptr = traversal_ptr->next;
  33.191 -    }
  33.192 -
  33.193 -    if (inlined_attachments) {
  33.194 -        /* Noooooo... dirk, why do you do this to me? */
  33.195 -        submime = part_multiple_new("multipart/related");
  33.196 -        assert(submime);
  33.197 -        if (submime == NULL)
  33.198 -            goto enomem;
  33.199 -
  33.200 -        top_level_html_mime = submime;
  33.201 -        
  33.202 -        r = mailmime_smart_add_part(mime, top_level_html_mime);
  33.203 -        assert(r == MAILIMF_NO_ERROR);
  33.204 -        if (r == MAILIMF_ERROR_MEMORY) {
  33.205 -            goto enomem;
  33.206 -        }
  33.207 -        else {
  33.208 -            // mailmime_smart_add_part() takes ownership of submime
  33.209 -            submime = NULL;
  33.210 -        }
  33.211 -    }
  33.212 -    else {
  33.213 -        top_level_html_mime = mime;
  33.214 -    }
  33.215 -
  33.216 -//    resource = new_rid_node(PEP_RID_FILENAME, "msg.html");
  33.217 -    submime = get_text_part(NULL, "text/html", htmltext, strlen(htmltext),
  33.218 -            encoding_type);
  33.219 -    free_rid_list(resource);
  33.220 -    resource = NULL;
  33.221 -    
  33.222 -    assert(submime);
  33.223 -    if (submime == NULL)
  33.224 -        goto enomem;
  33.225 -
  33.226 -    r = mailmime_smart_add_part(top_level_html_mime, submime);
  33.227 -    assert(r == MAILIMF_NO_ERROR);
  33.228 -    if (r == MAILIMF_ERROR_MEMORY)
  33.229 -        goto enomem;
  33.230 -    else {
  33.231 -        // mailmime_smart_add_part() takes ownership of submime
  33.232 -        submime = NULL;
  33.233 -    }
  33.234 -
  33.235 -    bloblist_t *_a;
  33.236 -    for (_a = attachments; _a != NULL; _a = _a->next) {
  33.237 -        if (_a->disposition != PEP_CONTENT_DISP_INLINE)
  33.238 -            continue;
  33.239 -        status = mime_attachment(_a, &submime, transport_encode);
  33.240 -        if (status != PEP_STATUS_OK)
  33.241 -            return PEP_UNKNOWN_ERROR; // FIXME
  33.242 -
  33.243 -        r = mailmime_smart_add_part(top_level_html_mime, submime);
  33.244 -        assert(r == MAILIMF_NO_ERROR);
  33.245 -        if (r == MAILIMF_ERROR_MEMORY) {
  33.246 -            goto enomem;
  33.247 -        }
  33.248 -        else {
  33.249 -            // mailmime_smart_add_part() takes ownership of submime
  33.250 -            submime = NULL;
  33.251 -        }
  33.252 -    }
  33.253 -
  33.254 -    *result = mime;
  33.255 -    return PEP_STATUS_OK;
  33.256 -
  33.257 -enomem:
  33.258 -    status = PEP_OUT_OF_MEMORY;
  33.259 -
  33.260 -    if (mime)
  33.261 -        mailmime_free(mime);
  33.262 -
  33.263 -    if (submime)
  33.264 -        mailmime_free(submime);
  33.265 -
  33.266 -    return status;
  33.267 -}
  33.268 -
  33.269 -
  33.270 -// FIXME: maybe need to add transport_encode field here
  33.271 -static struct mailimf_mailbox * identity_to_mailbox(const pEp_identity *ident)
  33.272 -{
  33.273 -    char *_username = NULL;
  33.274 -    struct mailimf_mailbox *mb;
  33.275 -
  33.276 -    if (!ident->username)
  33.277 -        _username = strdup("");
  33.278 -    else
  33.279 -        _username = must_field_value_be_encoded(ident->username) ?
  33.280 -                    mailmime_encode_subject_header("utf-8", ident->username, 0) : 
  33.281 -                    strdup(ident->username);
  33.282 -                  
  33.283 -    assert(_username);
  33.284 -    if (_username == NULL)
  33.285 -        goto enomem;
  33.286 -
  33.287 -    mb = mailbox_from_string(_username, ident->address);
  33.288 -    if (mb == NULL)
  33.289 -        goto enomem;
  33.290 -
  33.291 -    free(_username);
  33.292 -    _username = NULL;
  33.293 -
  33.294 -    return mb;
  33.295 -
  33.296 -enomem:
  33.297 -    free(_username);
  33.298 -    return NULL;
  33.299 -}
  33.300 -
  33.301 -static struct mailimf_mailbox_list * identity_to_mbl(
  33.302 -        const pEp_identity *ident)
  33.303 -{
  33.304 -    struct mailimf_mailbox_list *mbl = NULL;
  33.305 -    struct mailimf_mailbox *mb = NULL;
  33.306 -    clist *list = NULL;
  33.307 -    int r;
  33.308 -
  33.309 -    assert(ident);
  33.310 -
  33.311 -    list = clist_new();
  33.312 -    if (list == NULL)
  33.313 -        goto enomem;
  33.314 -
  33.315 -    mb = identity_to_mailbox(ident);
  33.316 -    if (mb == NULL)
  33.317 -        goto enomem;
  33.318 -
  33.319 -    r = clist_append(list, mb);
  33.320 -    if (r)
  33.321 -        goto enomem;
  33.322 -
  33.323 -    mbl = mailimf_mailbox_list_new(list);
  33.324 -    if (mbl == NULL)
  33.325 -        goto enomem;
  33.326 -
  33.327 -    return mbl;
  33.328 -
  33.329 -enomem:
  33.330 -    if (mb)
  33.331 -        mailimf_mailbox_free(mb);
  33.332 -
  33.333 -    if (list)
  33.334 -        clist_free(list);
  33.335 -
  33.336 -    return NULL;
  33.337 -}
  33.338 -
  33.339 -static struct mailimf_address_list * identity_list_to_mal(identity_list *il)
  33.340 -{
  33.341 -    struct mailimf_address_list *mal = NULL;
  33.342 -    struct mailimf_mailbox *mb = NULL;
  33.343 -    struct mailimf_address * addr = NULL;
  33.344 -    clist *list = NULL;
  33.345 -    int r;
  33.346 -
  33.347 -    assert(il);
  33.348 -
  33.349 -    list = clist_new();
  33.350 -    if (list == NULL)
  33.351 -        goto enomem;
  33.352 -
  33.353 -    identity_list *_il;
  33.354 -    for (_il = il; _il && _il->ident; _il = _il->next) {
  33.355 -        mb = identity_to_mailbox(_il->ident);
  33.356 -        if (mb == NULL)
  33.357 -            goto enomem;
  33.358 -
  33.359 -        addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  33.360 -        if (addr == NULL)
  33.361 -            goto enomem;
  33.362 -        mb = NULL;
  33.363 -
  33.364 -        r = clist_append(list, addr);
  33.365 -        if (r)
  33.366 -            goto enomem;
  33.367 -        addr = NULL;
  33.368 -    }
  33.369 -    mal = mailimf_address_list_new(list);
  33.370 -    if (mal == NULL)
  33.371 -        goto enomem;
  33.372 -
  33.373 -    return mal;
  33.374 -
  33.375 -enomem:
  33.376 -    if (mb)
  33.377 -        mailimf_mailbox_free(mb);
  33.378 -
  33.379 -    if (addr)
  33.380 -        mailimf_address_free(addr);
  33.381 -
  33.382 -    if (list)
  33.383 -        clist_free(list);
  33.384 -
  33.385 -    return NULL;
  33.386 -}
  33.387 -
  33.388 -static clist * stringlist_to_clist(stringlist_t *sl, bool transport_encode)
  33.389 -{
  33.390 -    clist * cl = clist_new();
  33.391 -    assert(cl);
  33.392 -    if (cl == NULL)
  33.393 -        return NULL;
  33.394 -
  33.395 -    if (!sl || ((!sl->value || sl->value[0] == '\0') && sl->next == NULL))
  33.396 -        return cl;
  33.397 -        
  33.398 -    stringlist_t *_sl;
  33.399 -    for (_sl = sl; _sl; _sl = _sl->next) {
  33.400 -        int r;
  33.401 -        char * value = ((transport_encode && must_field_value_be_encoded(_sl->value)) ?
  33.402 -                        mailmime_encode_subject_header("utf-8", _sl->value, 0) :
  33.403 -                        strdup(_sl->value));
  33.404 -        assert(value);
  33.405 -        if (value == NULL) {
  33.406 -            clist_free(cl);
  33.407 -            return NULL;
  33.408 -        }
  33.409 -        r = clist_append(cl, value);
  33.410 -        assert(r == 0);
  33.411 -        if (r) {
  33.412 -            free(value);
  33.413 -            clist_free(cl);
  33.414 -            return NULL;
  33.415 -        }
  33.416 -    }
  33.417 -
  33.418 -    return cl;
  33.419 -}
  33.420 -
  33.421 -static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
  33.422 -{
  33.423 -    PEP_STATUS status = PEP_STATUS_OK;
  33.424 -    struct mailimf_fields * fields = NULL;
  33.425 -    int r;
  33.426 -    clist * fields_list = NULL;
  33.427 -    unsigned char pEpstr[] = PEP_SUBJ_STRING; // unsigned due to UTF-8 byte fun
  33.428 -#ifdef WIN32
  33.429 -    char* altstr = "pEp";
  33.430 -#else
  33.431 -    char* altstr = (char*)pEpstr;
  33.432 -#endif        
  33.433 -    char *subject = msg->shortmsg ? msg->shortmsg : altstr;
  33.434 -
  33.435 -    assert(msg);
  33.436 -    assert(result);
  33.437 -
  33.438 -    *result = NULL;
  33.439 -
  33.440 -    fields_list = clist_new();
  33.441 -    assert(fields_list);
  33.442 -    if (fields_list == NULL)
  33.443 -        goto enomem;
  33.444 -
  33.445 -    if (msg->id) {
  33.446 -        char *_msgid = strdup(msg->id);
  33.447 -        assert(_msgid);
  33.448 -        if (_msgid == NULL)
  33.449 -            goto enomem;
  33.450 -
  33.451 -        r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
  33.452 -                (_new_func_t) mailimf_message_id_new, _msgid);
  33.453 -        if (r) {
  33.454 -            free(_msgid);
  33.455 -            goto enomem;
  33.456 -        }
  33.457 -    }
  33.458 -
  33.459 -    if (msg->sent) {
  33.460 -        struct mailimf_date_time * dt = timestamp_to_etpantime(msg->sent);
  33.461 -        if (dt == NULL)
  33.462 -            goto enomem;
  33.463 -
  33.464 -        r = _append_field(fields_list, MAILIMF_FIELD_ORIG_DATE,
  33.465 -                (_new_func_t) mailimf_orig_date_new, dt);
  33.466 -        if (r) {
  33.467 -            mailimf_date_time_free(dt);
  33.468 -            goto enomem;
  33.469 -        }
  33.470 -        dt = NULL;
  33.471 -    }
  33.472 -
  33.473 -     if (msg->from) {
  33.474 -        struct mailimf_mailbox_list *from = identity_to_mbl(msg->from);
  33.475 -        if (from == NULL)
  33.476 -            goto enomem;
  33.477 -
  33.478 -        r = _append_field(fields_list, MAILIMF_FIELD_FROM,
  33.479 -                (_new_func_t) mailimf_from_new, from);
  33.480 -        if (r) {
  33.481 -            mailimf_mailbox_list_free(from);
  33.482 -            goto enomem;
  33.483 -        }
  33.484 -    }
  33.485 -
  33.486 -    if (msg->to) {
  33.487 -        struct mailimf_address_list *to = identity_list_to_mal(msg->to);
  33.488 -        if (to == NULL)
  33.489 -            goto enomem;
  33.490 -
  33.491 -        r = _append_field(fields_list, MAILIMF_FIELD_TO,
  33.492 -                (_new_func_t) mailimf_to_new, to);
  33.493 -        if (r) {
  33.494 -            mailimf_address_list_free(to);
  33.495 -            goto enomem;
  33.496 -        }
  33.497 -    }
  33.498 -
  33.499 -    char* _subject = NULL;
  33.500 -    if (!must_field_value_be_encoded(subject)) {
  33.501 -        _subject = strdup(subject);
  33.502 -        assert(_subject);
  33.503 -    }
  33.504 -    else {
  33.505 -        _subject = mailmime_encode_subject_header("utf-8", subject, 1);
  33.506 -    }
  33.507 -    if (_subject == NULL)
  33.508 -        goto enomem;
  33.509 -
  33.510 -    r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
  33.511 -            (_new_func_t) mailimf_subject_new, _subject);
  33.512 -    if (r) {
  33.513 -        free(_subject);
  33.514 -        goto enomem;
  33.515 -    }
  33.516 -
  33.517 -    if (msg->cc) {
  33.518 -        struct mailimf_address_list *cc = identity_list_to_mal(msg->cc);
  33.519 -        if (cc == NULL)
  33.520 -            goto enomem;
  33.521 -
  33.522 -        r = _append_field(fields_list, MAILIMF_FIELD_CC,
  33.523 -                (_new_func_t) mailimf_cc_new, cc);
  33.524 -        if (r) {
  33.525 -            mailimf_address_list_free(cc);
  33.526 -            goto enomem;
  33.527 -        }
  33.528 -    }
  33.529 -    
  33.530 -    if (msg->bcc) {
  33.531 -        struct mailimf_address_list *bcc = identity_list_to_mal(msg->bcc);
  33.532 -        if (bcc == NULL)
  33.533 -            goto enomem;
  33.534 -
  33.535 -        r = _append_field(fields_list, MAILIMF_FIELD_BCC,
  33.536 -                (_new_func_t) mailimf_bcc_new, bcc);
  33.537 -        if (r) {
  33.538 -            mailimf_address_list_free(bcc);
  33.539 -            goto enomem;
  33.540 -        }
  33.541 -    }
  33.542 -    
  33.543 -    if (msg->reply_to) {
  33.544 -        struct mailimf_address_list *reply_to = identity_list_to_mal(msg->reply_to);
  33.545 -        if (reply_to == NULL)
  33.546 -            goto enomem;
  33.547 -
  33.548 -        r = _append_field(fields_list, MAILIMF_FIELD_REPLY_TO,
  33.549 -                (_new_func_t) mailimf_reply_to_new, reply_to);
  33.550 -        if (r) {
  33.551 -            mailimf_address_list_free(reply_to);
  33.552 -            goto enomem;
  33.553 -        }
  33.554 -    }
  33.555 -
  33.556 -    if (msg->in_reply_to) {
  33.557 -        clist *in_reply_to = stringlist_to_clist(msg->in_reply_to, true);
  33.558 -        if (in_reply_to == NULL)
  33.559 -            goto enomem;
  33.560 -
  33.561 -        r = _append_field(fields_list, MAILIMF_FIELD_IN_REPLY_TO,
  33.562 -                (_new_func_t) mailimf_in_reply_to_new, in_reply_to);
  33.563 -        if (r) {
  33.564 -            clist_free(in_reply_to);
  33.565 -            goto enomem;
  33.566 -        }
  33.567 -    }
  33.568 -
  33.569 -    if (msg->references) {
  33.570 -        clist *references = stringlist_to_clist(msg->references, true);
  33.571 -        if (references == NULL)
  33.572 -            goto enomem;
  33.573 -
  33.574 -        r = _append_field(fields_list, MAILIMF_FIELD_REFERENCES,
  33.575 -                (_new_func_t) mailimf_references_new, references);
  33.576 -        if (r) {
  33.577 -            clist_free(references);
  33.578 -            goto enomem;
  33.579 -        }
  33.580 -    }
  33.581 -
  33.582 -    if (msg->keywords) {
  33.583 -        clist *keywords = stringlist_to_clist(msg->keywords, true);
  33.584 -        if (keywords == NULL)
  33.585 -            goto enomem;
  33.586 -
  33.587 -        r = _append_field(fields_list, MAILIMF_FIELD_KEYWORDS,
  33.588 -                (_new_func_t) mailimf_keywords_new, keywords);
  33.589 -        if (r) {
  33.590 -            clist_free(keywords);
  33.591 -            goto enomem;
  33.592 -        }
  33.593 -    }
  33.594 -
  33.595 -    if (msg->comments) {
  33.596 -        char *comments = NULL;
  33.597 -        if (!must_field_value_be_encoded(msg->comments)) {
  33.598 -            comments = strdup(msg->comments);
  33.599 -            assert(comments);
  33.600 -        }
  33.601 -        else  {
  33.602 -            comments = mailmime_encode_subject_header("utf-8", msg->comments, 0);
  33.603 -        }
  33.604 -        if (comments == NULL)
  33.605 -            goto enomem;
  33.606 -
  33.607 -        r = _append_field(fields_list, MAILIMF_FIELD_COMMENTS,
  33.608 -                (_new_func_t) mailimf_comments_new, comments);
  33.609 -        if (r) {
  33.610 -            free(comments);
  33.611 -            goto enomem;
  33.612 -        }
  33.613 -    }
  33.614 -
  33.615 -    if (msg->opt_fields) {
  33.616 -        stringpair_list_t *_l;
  33.617 -        for (_l = msg->opt_fields; _l && _l->value; _l = _l->next) {
  33.618 -            char *key = _l->value->key;
  33.619 -            char *value = _l->value->value;
  33.620 -            if (key && value) {
  33.621 -                r = _append_optional_field(fields_list, key, value);
  33.622 -
  33.623 -                if (r)
  33.624 -                    goto enomem;
  33.625 -            }
  33.626 -        }
  33.627 -    }
  33.628 -
  33.629 -    fields = mailimf_fields_new(fields_list);
  33.630 -    assert(fields);
  33.631 -    if (fields == NULL)
  33.632 -        goto enomem;
  33.633 -
  33.634 -    *result = fields;
  33.635 -
  33.636 -    return PEP_STATUS_OK;
  33.637 -
  33.638 -enomem:
  33.639 -    status = PEP_OUT_OF_MEMORY;
  33.640 -
  33.641 -    if (fields_list)
  33.642 -        clist_free(fields_list);
  33.643 -
  33.644 -    if (fields)
  33.645 -        mailimf_fields_free(fields);
  33.646 -
  33.647 -    return status;
  33.648 -}
  33.649 -
  33.650 -static bool has_exceptional_extension(char* filename) {
  33.651 -    if (!filename)
  33.652 -        return false;
  33.653 -    int len = strlen(filename);
  33.654 -    if (len < 4)
  33.655 -        return false;
  33.656 -    char* ext_start = filename + (len - 4);
  33.657 -    if (strcmp(ext_start, ".pgp") == 0 || strcmp(ext_start, ".gpg") == 0 ||
  33.658 -        strcmp(ext_start, ".asc") == 0 || strcmp(ext_start, ".pEp") == 0)
  33.659 -        return true;
  33.660 -    return false;
  33.661 -}
  33.662 -
  33.663 -static pEp_rid_list_t* choose_resource_id(pEp_rid_list_t* rid_list) {
  33.664 -    pEp_rid_list_t* retval = rid_list;
  33.665 -    
  33.666 -    /* multiple elements - least common case */
  33.667 -    if (rid_list && rid_list->next) {
  33.668 -        pEp_rid_list_t* rid_list_curr = rid_list;
  33.669 -        retval = rid_list; 
  33.670 -        
  33.671 -        while (rid_list_curr) {
  33.672 -            pEp_resource_id_type rid_type = rid_list_curr->rid_type;
  33.673 -            if (rid_type == PEP_RID_CID)
  33.674 -                retval = rid_list_curr;
  33.675 -            else if (rid_type == PEP_RID_FILENAME && has_exceptional_extension(rid_list_curr->rid))
  33.676 -                return rid_list_curr;
  33.677 -            rid_list_curr = rid_list_curr->next;
  33.678 -        }
  33.679 -    } 
  33.680 -    return retval;
  33.681 -}
  33.682 -
  33.683 -// static void split_inlined_and_attached(bloblist_t** inlined, bloblist_t** attached) {
  33.684 -//     bloblist_t** curr_pp = attached;
  33.685 -//     bloblist_t* curr = *curr_pp;
  33.686 -//     
  33.687 -//     bloblist_t* inline_ret = NULL;
  33.688 -//     bloblist_t** inline_curr_pp = &inline_ret;
  33.689 -//     
  33.690 -//     bloblist_t* att_ret = NULL;
  33.691 -//     bloblist_t** att_curr_pp = &att_ret;
  33.692 -//     
  33.693 -//     while (curr) {
  33.694 -//         if (curr->disposition == PEP_CONTENT_DISP_INLINE) {
  33.695 -//             *inline_curr_pp = curr;
  33.696 -//             inline_curr_pp = &(curr->next);
  33.697 -//         }
  33.698 -//         else {
  33.699 -//             *att_curr_pp = curr;
  33.700 -//             att_curr_pp = &(curr->next);            
  33.701 -//         }
  33.702 -//         *curr_pp = curr->next;
  33.703 -//         curr->next = NULL;
  33.704 -//         curr = *curr_pp;
  33.705 -//     }
  33.706 -//     
  33.707 -//     *inlined = inline_ret;
  33.708 -//     *attached = att_ret;
  33.709 -// }
  33.710 -
  33.711 -
  33.712 -static PEP_STATUS mime_encode_message_plain(
  33.713 -        const message *msg,
  33.714 -        bool omit_fields,
  33.715 -        struct mailmime **result,
  33.716 -        bool transport_encode
  33.717 -    )
  33.718 -{
  33.719 -    struct mailmime * mime = NULL;
  33.720 -    struct mailmime * submime = NULL;
  33.721 -    int r;
  33.722 -    PEP_STATUS status;
  33.723 -    //char *subject;
  33.724 -    char *plaintext;
  33.725 -    char *htmltext;
  33.726 -
  33.727 -    assert(msg);
  33.728 -    assert(result);
  33.729 -    
  33.730 -    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp";  // not used, yet.
  33.731 -    plaintext = (msg->longmsg) ? msg->longmsg : "";
  33.732 -    htmltext = msg->longmsg_formatted;
  33.733 -
  33.734 -    if (htmltext && (htmltext[0] != '\0')) {
  33.735 -        /* first, we need to strip out the inlined attachments to ensure this
  33.736 -           gets set up correctly */
  33.737 -           
  33.738 -        status = mime_html_text(plaintext, htmltext, msg->attachments, &mime,
  33.739 -                                transport_encode);
  33.740 -                
  33.741 -        if (status != PEP_STATUS_OK)
  33.742 -            goto pEp_error;
  33.743 -    }
  33.744 -    else {
  33.745 -        pEp_rid_list_t* resource = NULL;
  33.746 -        if (is_PGP_message_text(plaintext)) {
  33.747 -            resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
  33.748 -            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_7BIT : 0);
  33.749 -            mime = get_text_part(resource, "application/octet-stream", plaintext,
  33.750 -                    strlen(plaintext), encoding_type);
  33.751 -        }
  33.752 -        else {
  33.753 -            resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
  33.754 -            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  33.755 -            mime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
  33.756 -                    encoding_type);
  33.757 -        }
  33.758 -        free_rid_list(resource);
  33.759 -        
  33.760 -        assert(mime);
  33.761 -        if (mime == NULL)
  33.762 -            goto enomem;
  33.763 -    }
  33.764 -
  33.765 -    bool normal_attachments = false;
  33.766 -    
  33.767 -    bloblist_t* traversal_ptr = msg->attachments;
  33.768 -    
  33.769 -    while (traversal_ptr) {
  33.770 -        if (traversal_ptr->disposition != PEP_CONTENT_DISP_INLINE) {
  33.771 -            normal_attachments = true;
  33.772 -            break;
  33.773 -        }
  33.774 -        traversal_ptr = traversal_ptr->next;
  33.775 -    }
  33.776 -
  33.777 -    if (normal_attachments) {
  33.778 -        submime = mime;
  33.779 -        mime = part_multiple_new("multipart/mixed");
  33.780 -        assert(mime);
  33.781 -        if (mime == NULL)
  33.782 -            goto enomem;
  33.783 -
  33.784 -        r = mailmime_smart_add_part(mime, submime);
  33.785 -        assert(r == MAILIMF_NO_ERROR);
  33.786 -        if (r == MAILIMF_ERROR_MEMORY) {
  33.787 -            goto enomem;
  33.788 -        }
  33.789 -        else {
  33.790 -            // mailmime_smart_add_part() takes ownership of submime
  33.791 -            submime = NULL;
  33.792 -        }
  33.793 -
  33.794 -        bloblist_t *_a;
  33.795 -        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
  33.796 -
  33.797 -            if (_a->disposition == PEP_CONTENT_DISP_INLINE)
  33.798 -                continue;
  33.799 -
  33.800 -            status = mime_attachment(_a, &submime, transport_encode);
  33.801 -            if (status != PEP_STATUS_OK)
  33.802 -                goto pEp_error;
  33.803 -
  33.804 -            r = mailmime_smart_add_part(mime, submime);
  33.805 -            assert(r == MAILIMF_NO_ERROR);
  33.806 -            if (r == MAILIMF_ERROR_MEMORY) {
  33.807 -                goto enomem;
  33.808 -            }
  33.809 -            else {
  33.810 -                // mailmime_smart_add_part() takes ownership of submime
  33.811 -                submime = NULL;
  33.812 -            }
  33.813 -        }
  33.814 -    }
  33.815 -
  33.816 -    *result = mime;
  33.817 -    return PEP_STATUS_OK;
  33.818 -
  33.819 -enomem:
  33.820 -    status = PEP_OUT_OF_MEMORY;
  33.821 -
  33.822 -pEp_error:
  33.823 -    if (mime)
  33.824 -        mailmime_free(mime);
  33.825 -
  33.826 -    if (submime)
  33.827 -        mailmime_free(submime);
  33.828 -
  33.829 -    return status;
  33.830 -}
  33.831 -
  33.832 -static PEP_STATUS mime_encode_message_PGP_MIME(
  33.833 -        const message * msg,
  33.834 -        bool omit_fields,
  33.835 -        struct mailmime **result
  33.836 -    )
  33.837 -{
  33.838 -    struct mailmime * mime = NULL;
  33.839 -    struct mailmime * submime = NULL;
  33.840 -	struct mailmime_parameter * param;
  33.841 -    int r;
  33.842 -    PEP_STATUS status;
  33.843 -    char *plaintext;
  33.844 -    size_t plaintext_size;
  33.845 -
  33.846 -    assert(msg->attachments && msg->attachments->next &&
  33.847 -            msg->attachments->next->value);
  33.848 -
  33.849 -    plaintext = msg->attachments->next->value;
  33.850 -    plaintext_size = msg->attachments->next->size;
  33.851 -
  33.852 -    mime = part_multiple_new("multipart/encrypted");
  33.853 -    assert(mime);
  33.854 -    if (mime == NULL)
  33.855 -        goto enomem;
  33.856 -
  33.857 -    param = mailmime_param_new_with_data("protocol", "application/pgp-encrypted");
  33.858 -    clist_append(mime->mm_content_type->ct_parameters, param);
  33.859 -
  33.860 -    submime = get_pgp_encrypted_part();
  33.861 -    assert(submime);
  33.862 -    if (submime == NULL)
  33.863 -        goto enomem;
  33.864 -
  33.865 -    r = mailmime_smart_add_part(mime, submime);
  33.866 -    assert(r == MAILIMF_NO_ERROR);
  33.867 -    if (r == MAILIMF_ERROR_MEMORY) {
  33.868 -        goto enomem;
  33.869 -    }
  33.870 -    else {
  33.871 -        // mailmime_smart_add_part() takes ownership of submime
  33.872 -        submime = NULL;
  33.873 -    }
  33.874 -
  33.875 -    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
  33.876 -    submime = get_text_part(resource, "application/octet-stream", plaintext,
  33.877 -            plaintext_size, MAILMIME_MECHANISM_7BIT);
  33.878 -            
  33.879 -    free_rid_list(resource);
  33.880 -    
  33.881 -    assert(submime);
  33.882 -    if (submime == NULL)
  33.883 -        goto enomem;
  33.884 -
  33.885 -    r = mailmime_smart_add_part(mime, submime);
  33.886 -    assert(r == MAILIMF_NO_ERROR);
  33.887 -    if (r == MAILIMF_ERROR_MEMORY) {
  33.888 -        goto enomem;
  33.889 -    }
  33.890 -    else {
  33.891 -        // mailmime_smart_add_part() takes ownership of submime
  33.892 -        submime = NULL;
  33.893 -    }
  33.894 -
  33.895 -    *result = mime;
  33.896 -    return PEP_STATUS_OK;
  33.897 -
  33.898 -enomem:
  33.899 -    status = PEP_OUT_OF_MEMORY;
  33.900 -
  33.901 -    if (mime)
  33.902 -        mailmime_free(mime);
  33.903 -
  33.904 -    if (submime)
  33.905 -        mailmime_free(submime);
  33.906 -
  33.907 -    return status;
  33.908 -}
  33.909 -
  33.910  DYNAMIC_API PEP_STATUS mime_encode_message(
  33.911          const message * msg,
  33.912          bool omit_fields,
  33.913 @@ -929,807 +42,3 @@
  33.914      return _mime_encode_message_internal(msg, omit_fields, mimetext, true);
  33.915  }
  33.916  
  33.917 -PEP_STATUS _mime_encode_message_internal(
  33.918 -        const message * msg,
  33.919 -        bool omit_fields,
  33.920 -        char **mimetext,
  33.921 -        bool transport_encode
  33.922 -    )
  33.923 -{
  33.924 -    PEP_STATUS status = PEP_STATUS_OK;
  33.925 -    struct mailmime * msg_mime = NULL;
  33.926 -    struct mailmime * mime = NULL;
  33.927 -    struct mailimf_fields * fields = NULL;
  33.928 -    char *buf = NULL;
  33.929 -    int r;
  33.930 -
  33.931 -    assert(msg);
  33.932 -    assert(mimetext);
  33.933 -
  33.934 -    if (!(msg && mimetext))
  33.935 -        return PEP_ILLEGAL_VALUE;
  33.936 -
  33.937 -    *mimetext = NULL;
  33.938 -
  33.939 -    switch (msg->enc_format) {
  33.940 -        case PEP_enc_none:
  33.941 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
  33.942 -            break;
  33.943 -
  33.944 -        case PEP_enc_pieces:
  33.945 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
  33.946 -            break;
  33.947 -
  33.948 -        case PEP_enc_S_MIME:
  33.949 -            NOT_IMPLEMENTED
  33.950 -                
  33.951 -        case PEP_enc_PGP_MIME:
  33.952 -            status = mime_encode_message_PGP_MIME(msg, omit_fields, &mime);
  33.953 -            break;
  33.954 -
  33.955 -        case PEP_enc_PEP:
  33.956 -            NOT_IMPLEMENTED
  33.957 -
  33.958 -        default:
  33.959 -            NOT_IMPLEMENTED
  33.960 -    }
  33.961 -
  33.962 -    if (status != PEP_STATUS_OK)
  33.963 -        goto pEp_error;
  33.964 -
  33.965 -    msg_mime = mailmime_new_message_data(NULL);
  33.966 -    assert(msg_mime);
  33.967 -    if (msg_mime == NULL)
  33.968 -        goto enomem;
  33.969 -
  33.970 -    r = mailmime_add_part(msg_mime, mime);
  33.971 -    if (r) {
  33.972 -        mailmime_free(mime);
  33.973 -        goto enomem;
  33.974 -    }
  33.975 -    mime = NULL;
  33.976 -
  33.977 -    if (!omit_fields) {
  33.978 -        status = build_fields(msg, &fields);
  33.979 -        if (status != PEP_STATUS_OK)
  33.980 -            goto pEp_error;
  33.981 -
  33.982 -        mailmime_set_imf_fields(msg_mime, fields);
  33.983 -    }
  33.984 -
  33.985 -    status = render_mime(msg_mime, &buf);
  33.986 -    if (status != PEP_STATUS_OK)
  33.987 -        goto pEp_error;
  33.988 -
  33.989 -    mailmime_free(msg_mime);
  33.990 -    *mimetext = buf;
  33.991 -
  33.992 -    return PEP_STATUS_OK;
  33.993 -
  33.994 -enomem:
  33.995 -    status = PEP_OUT_OF_MEMORY;
  33.996 -
  33.997 -pEp_error:
  33.998 -    if (msg_mime)
  33.999 -        mailmime_free(msg_mime);
 33.1000 -    else
 33.1001 -        if (mime)
 33.1002 -            mailmime_free(mime);
 33.1003 -
 33.1004 -    return status;
 33.1005 -}
 33.1006 -
 33.1007 -static pEp_identity *mailbox_to_identity(const struct mailimf_mailbox * mb)
 33.1008 -{
 33.1009 -    char *username = NULL;
 33.1010 -
 33.1011 -    assert(mb);
 33.1012 -    assert(mb->mb_addr_spec);
 33.1013 -
 33.1014 -    if (mb->mb_addr_spec == NULL)
 33.1015 -        return NULL;
 33.1016 -
 33.1017 -    if (mb->mb_display_name) {
 33.1018 -        size_t index = 0;
 33.1019 -        const int r = mailmime_encoded_phrase_parse("utf-8", mb->mb_display_name,
 33.1020 -                strlen(mb->mb_display_name), &index, "utf-8", &username);
 33.1021 -        if (r)
 33.1022 -            goto enomem;
 33.1023 -    }
 33.1024 -
 33.1025 -    pEp_identity *ident = new_identity(mb->mb_addr_spec, NULL, NULL, username);
 33.1026 -    if (ident == NULL)
 33.1027 -        goto enomem;
 33.1028 -    free(username);
 33.1029 -
 33.1030 -    return ident;
 33.1031 -
 33.1032 -enomem:
 33.1033 -    free(username);
 33.1034 -    return NULL;
 33.1035 -}
 33.1036 -
 33.1037 -static pEp_identity * mbl_to_identity(const struct mailimf_mailbox_list * mbl)
 33.1038 -{
 33.1039 -    struct mailimf_mailbox * mb = clist_content(clist_begin(mbl->mb_list));
 33.1040 -    return mailbox_to_identity(mb);
 33.1041 -}
 33.1042 -
 33.1043 -static identity_list * mal_to_identity_list(
 33.1044 -        const struct mailimf_address_list *mal
 33.1045 -    )
 33.1046 -{
 33.1047 -    assert(mal);
 33.1048 -    clist *list = mal->ad_list;
 33.1049 -
 33.1050 -    identity_list *il = new_identity_list(NULL);
 33.1051 -    if (il == NULL)
 33.1052 -        goto enomem;
 33.1053 -
 33.1054 -    identity_list *_il = il;
 33.1055 -    for (clistiter *cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
 33.1056 -        pEp_identity *ident;
 33.1057 -
 33.1058 -        struct mailimf_address *addr = clist_content(cur);
 33.1059 -        switch(addr->ad_type) {
 33.1060 -            case MAILIMF_ADDRESS_MAILBOX:
 33.1061 -                ident = mailbox_to_identity(addr->ad_data.ad_mailbox);
 33.1062 -                if (ident == NULL)
 33.1063 -                    goto enomem;
 33.1064 -                _il = identity_list_add(_il, ident);
 33.1065 -                if (_il == NULL)
 33.1066 -                    goto enomem;
 33.1067 -                break;
 33.1068 -
 33.1069 -            case MAILIMF_ADDRESS_GROUP:
 33.1070 -                {
 33.1071 -                    struct mailimf_mailbox_list * mbl =
 33.1072 -                            addr->ad_data.ad_group->grp_mb_list;
 33.1073 -                    for (clistiter *cur2 = clist_begin(mbl->mb_list); cur2 != NULL;
 33.1074 -                            cur2 = clist_next(cur2)) {
 33.1075 -                        ident = mailbox_to_identity(clist_content(cur));
 33.1076 -                        if (ident == NULL)
 33.1077 -                            goto enomem;
 33.1078 -                        _il = identity_list_add(_il, ident);
 33.1079 -                        if (_il == NULL)
 33.1080 -                            goto enomem;
 33.1081 -                    }
 33.1082 -                }
 33.1083 -                break;
 33.1084 -
 33.1085 -            default:
 33.1086 -                assert(0);
 33.1087 -                goto enomem;
 33.1088 -        }
 33.1089 -    }
 33.1090 -
 33.1091 -    return il;
 33.1092 -
 33.1093 -enomem:
 33.1094 -    free_identity_list(il);
 33.1095 -    return NULL;
 33.1096 -}
 33.1097 -
 33.1098 -static stringlist_t * clist_to_stringlist(const clist *list)
 33.1099 -{
 33.1100 -    char *text = NULL;;
 33.1101 -    stringlist_t * sl = new_stringlist(NULL);
 33.1102 -    if (sl == NULL)
 33.1103 -        return NULL;
 33.1104 -
 33.1105 -    stringlist_t *_sl = sl;
 33.1106 -    for (clistiter *cur = clist_begin(list); cur != NULL; cur = clist_next(cur)) {
 33.1107 -        char *phrase = clist_content(cur);
 33.1108 -        size_t index = 0;
 33.1109 -        
 33.1110 -        const int r = mailmime_encoded_phrase_parse("utf-8", phrase, strlen(phrase),
 33.1111 -                &index, "utf-8", &text);
 33.1112 -        if (r)
 33.1113 -            goto enomem;
 33.1114 -
 33.1115 -        _sl = stringlist_add(_sl, text);
 33.1116 -        if (_sl == NULL)
 33.1117 -            goto enomem;
 33.1118 -
 33.1119 -        free(text);
 33.1120 -        text = NULL;
 33.1121 -    }
 33.1122 -
 33.1123 -    return sl;
 33.1124 -
 33.1125 -enomem:
 33.1126 -    free_stringlist(sl);
 33.1127 -    free(text);
 33.1128 -
 33.1129 -    return NULL;
 33.1130 -}
 33.1131 -
 33.1132 -static PEP_STATUS read_fields(message *msg, clist *fieldlist)
 33.1133 -{
 33.1134 -    PEP_STATUS status = PEP_STATUS_OK;
 33.1135 -    struct mailimf_field * _field;
 33.1136 -    clistiter *cur;
 33.1137 -    size_t index;
 33.1138 -    int r;
 33.1139 -    
 33.1140 -    stringpair_list_t *opt = msg->opt_fields;
 33.1141 -
 33.1142 -    if (!fieldlist)
 33.1143 -        return PEP_STATUS_OK;
 33.1144 -        
 33.1145 -    for (cur = clist_begin(fieldlist); cur != NULL; cur = clist_next(cur)) {
 33.1146 -        _field = clist_content(cur);
 33.1147 -
 33.1148 -        switch (_field->fld_type) {
 33.1149 -            case MAILIMF_FIELD_MESSAGE_ID:
 33.1150 -                {
 33.1151 -                    char * text = _field->fld_data.fld_message_id->mid_value;
 33.1152 -
 33.1153 -                    free(msg->id);
 33.1154 -                    index = 0;
 33.1155 -                    r = mailmime_encoded_phrase_parse("utf-8", text,
 33.1156 -                            strlen(text), &index, "utf-8", &msg->id);
 33.1157 -                    if (r)
 33.1158 -                        goto enomem;
 33.1159 -                }
 33.1160 -                break;
 33.1161 -
 33.1162 -            case MAILIMF_FIELD_SUBJECT:
 33.1163 -                {
 33.1164 -                    char * text = _field->fld_data.fld_subject->sbj_value;
 33.1165 -
 33.1166 -                    free(msg->shortmsg);
 33.1167 -                    index = 0;
 33.1168 -                    r = mailmime_encoded_phrase_parse("utf-8", text,
 33.1169 -                            strlen(text), &index, "utf-8", &msg->shortmsg);
 33.1170 -                    if (r)
 33.1171 -                        goto enomem;
 33.1172 -                }
 33.1173 -                break;
 33.1174 -
 33.1175 -            case MAILIMF_FIELD_ORIG_DATE:
 33.1176 -                {
 33.1177 -                    struct mailimf_date_time *date =
 33.1178 -                        _field->fld_data.fld_orig_date->dt_date_time;
 33.1179 -
 33.1180 -                    free_timestamp(msg->sent);
 33.1181 -                    msg->sent = etpantime_to_timestamp(date);
 33.1182 -                    if (msg->sent == NULL)
 33.1183 -                        goto enomem;
 33.1184 -                }
 33.1185 -                break;
 33.1186 -
 33.1187 -            case MAILIMF_FIELD_FROM:
 33.1188 -                {
 33.1189 -                    struct mailimf_mailbox_list *mbl =
 33.1190 -                            _field->fld_data.fld_from->frm_mb_list;
 33.1191 -                    pEp_identity *ident;
 33.1192 -
 33.1193 -                    ident = mbl_to_identity(mbl);
 33.1194 -                    if (ident == NULL)
 33.1195 -                        goto pEp_error;
 33.1196 -
 33.1197 -                    free_identity(msg->from);
 33.1198 -                    msg->from = ident;
 33.1199 -                }
 33.1200 -                break;
 33.1201 -
 33.1202 -            case MAILIMF_FIELD_TO:
 33.1203 -                {
 33.1204 -                    struct mailimf_address_list *mal =
 33.1205 -                            _field->fld_data.fld_to->to_addr_list;
 33.1206 -                    identity_list *il = mal_to_identity_list(mal);
 33.1207 -                    if (il == NULL)
 33.1208 -                        goto enomem;
 33.1209 -
 33.1210 -                    free_identity_list(msg->to);
 33.1211 -                    msg->to = il;
 33.1212 -                }
 33.1213 -                break;
 33.1214 -
 33.1215 -            case MAILIMF_FIELD_CC:
 33.1216 -                {
 33.1217 -                    struct mailimf_address_list *mal =
 33.1218 -                            _field->fld_data.fld_cc->cc_addr_list;
 33.1219 -                    identity_list *il = mal_to_identity_list(mal);
 33.1220 -                    if (il == NULL)
 33.1221 -                        goto enomem;
 33.1222 -
 33.1223 -                    free_identity_list(msg->cc);
 33.1224 -                    msg->cc = il;
 33.1225 -                }
 33.1226 -                break;
 33.1227 -
 33.1228 -            case MAILIMF_FIELD_BCC:
 33.1229 -                {
 33.1230 -                    struct mailimf_address_list *mal =
 33.1231 -                            _field->fld_data.fld_bcc->bcc_addr_list;
 33.1232 -                    identity_list *il = mal_to_identity_list(mal);
 33.1233 -                    if (il == NULL)
 33.1234 -                        goto enomem;
 33.1235 -
 33.1236 -                    free_identity_list(msg->bcc);
 33.1237 -                    msg->bcc = il;
 33.1238 -                }
 33.1239 -                break;
 33.1240 -
 33.1241 -            case MAILIMF_FIELD_REPLY_TO:
 33.1242 -                {
 33.1243 -                    struct mailimf_address_list *mal =
 33.1244 -                            _field->fld_data.fld_reply_to->rt_addr_list;
 33.1245 -                    identity_list *il = mal_to_identity_list(mal);
 33.1246 -                    if (il == NULL)
 33.1247 -                        goto enomem;
 33.1248 -
 33.1249 -                    free_identity_list(msg->reply_to);
 33.1250 -                    msg->reply_to = il;
 33.1251 -                }
 33.1252 -                break;
 33.1253 -
 33.1254 -            case MAILIMF_FIELD_IN_REPLY_TO:
 33.1255 -                {
 33.1256 -                    clist *list = _field->fld_data.fld_in_reply_to->mid_list;
 33.1257 -                    stringlist_t *sl = clist_to_stringlist(list);
 33.1258 -                    if (sl == NULL)
 33.1259 -                        goto enomem;
 33.1260 -
 33.1261 -                    free_stringlist(msg->in_reply_to);
 33.1262 -                    msg->in_reply_to = sl;
 33.1263 -                }
 33.1264 -                break;
 33.1265 -
 33.1266 -            case MAILIMF_FIELD_REFERENCES:
 33.1267 -                {
 33.1268 -                    clist *list = _field->fld_data.fld_references->mid_list;
 33.1269 -                    stringlist_t *sl = clist_to_stringlist(list);
 33.1270 -                    if (sl == NULL)
 33.1271 -                        goto enomem;
 33.1272 -
 33.1273 -                    free_stringlist(msg->references);
 33.1274 -                    msg->references = sl;
 33.1275 -                }
 33.1276 -                break;
 33.1277 -
 33.1278 -            case MAILIMF_FIELD_KEYWORDS:
 33.1279 -                {
 33.1280 -                    clist *list = _field->fld_data.fld_keywords->kw_list;
 33.1281 -                    stringlist_t *sl = clist_to_stringlist(list);
 33.1282 -                    if (sl == NULL)
 33.1283 -                        goto enomem;
 33.1284 -
 33.1285 -                    free_stringlist(msg->keywords);
 33.1286 -                    msg->keywords = sl;
 33.1287 -                }
 33.1288 -                break;
 33.1289 -
 33.1290 -            case MAILIMF_FIELD_COMMENTS:
 33.1291 -                {
 33.1292 -                    char * text = _field->fld_data.fld_comments->cm_value;
 33.1293 -
 33.1294 -                    free(msg->comments);
 33.1295 -                    index = 0;
 33.1296 -                    r = mailmime_encoded_phrase_parse("utf-8", text,
 33.1297 -                            strlen(text), &index, "utf-8", &msg->comments);
 33.1298 -                    if (r)
 33.1299 -                        goto enomem;
 33.1300 -                }
 33.1301 -                break;
 33.1302 -
 33.1303 -            case MAILIMF_FIELD_OPTIONAL_FIELD:
 33.1304 -                {
 33.1305 -                    char * name =
 33.1306 -                            _field->fld_data.fld_optional_field->fld_name;
 33.1307 -                    char * value =
 33.1308 -                            _field->fld_data.fld_optional_field->fld_value;
 33.1309 -                    char *_value;
 33.1310 -
 33.1311 -                    index = 0;
 33.1312 -                    r = mailmime_encoded_phrase_parse("utf-8", value,
 33.1313 -                            strlen(value), &index, "utf-8", &_value);
 33.1314 -                    if (r)
 33.1315 -                        goto enomem;
 33.1316 -
 33.1317 -                    stringpair_t *pair = new_stringpair(name, _value);
 33.1318 -                    if (pair == NULL)
 33.1319 -                        goto enomem;
 33.1320 -
 33.1321 -                    opt = stringpair_list_add(opt, pair);
 33.1322 -                    free(_value);
 33.1323 -                    if (opt == NULL)
 33.1324 -                        goto enomem;
 33.1325 -
 33.1326 -                    if (msg->opt_fields == NULL)
 33.1327 -                        msg->opt_fields = opt;
 33.1328 -                }
 33.1329 -                break;
 33.1330 -        }
 33.1331 -    }
 33.1332 -    
 33.1333 -    return PEP_STATUS_OK;
 33.1334 -
 33.1335 -enomem:
 33.1336 -    status = PEP_OUT_OF_MEMORY;
 33.1337 -
 33.1338 -pEp_error:
 33.1339 -    return status;
 33.1340 -}
 33.1341 -
 33.1342 -static PEP_STATUS interpret_body(struct mailmime *part, char **longmsg, size_t *size)
 33.1343 -{
 33.1344 -    const char *text;
 33.1345 -    char *_longmsg;
 33.1346 -    size_t length;
 33.1347 -    size_t _size;
 33.1348 -    size_t index;
 33.1349 -    char *type = NULL;
 33.1350 -    char *charset = NULL;
 33.1351 -
 33.1352 -    assert(part);
 33.1353 -    assert(longmsg);
 33.1354 -
 33.1355 -    *longmsg = NULL;
 33.1356 -    if (size)
 33.1357 -        *size = 0;
 33.1358 -
 33.1359 -    if (part->mm_body == NULL)
 33.1360 -        return PEP_ILLEGAL_VALUE;
 33.1361 -
 33.1362 -    text = part->mm_body-> dt_data.dt_text.dt_data;
 33.1363 -    if (text == NULL)
 33.1364 -        return PEP_ILLEGAL_VALUE;
 33.1365 -
 33.1366 -    length = part->mm_body->dt_data.dt_text.dt_length;
 33.1367 -
 33.1368 -    if (part->mm_body->dt_encoded) {
 33.1369 -        int code = part->mm_body->dt_encoding;
 33.1370 -        index = 0;
 33.1371 -        int r = mailmime_part_parse(text, length, &index, code, &_longmsg, &_size);
 33.1372 -        switch (r) {
 33.1373 -            case MAILIMF_NO_ERROR:
 33.1374 -                break;
 33.1375 -            case MAILIMF_ERROR_MEMORY:
 33.1376 -                return PEP_OUT_OF_MEMORY;
 33.1377 -            default:
 33.1378 -                return PEP_ILLEGAL_VALUE;
 33.1379 -        }
 33.1380 -    }
 33.1381 -    else {
 33.1382 -        _size = length + 1;
 33.1383 -        _longmsg = strndup(text, length);
 33.1384 -        if (_longmsg == NULL)
 33.1385 -            return PEP_OUT_OF_MEMORY;
 33.1386 -    }
 33.1387 -
 33.1388 -    if (part->mm_content_type) {
 33.1389 -        if (_get_content_type(part->mm_content_type, &type, &charset) == 0) {
 33.1390 -            if (charset && strncasecmp(charset, "utf-8", 5) != 0) {
 33.1391 -                char * _text;
 33.1392 -                int r = charconv("utf-8", charset, _longmsg, _size, &_text);
 33.1393 -                switch (r) {
 33.1394 -                    case MAILIMF_NO_ERROR:
 33.1395 -                        break;
 33.1396 -                    case MAILIMF_ERROR_MEMORY:
 33.1397 -                        return PEP_OUT_OF_MEMORY;
 33.1398 -                    default:
 33.1399 -                        return PEP_ILLEGAL_VALUE;
 33.1400 -                }
 33.1401 -                free(_longmsg);
 33.1402 -                _longmsg = _text;
 33.1403 -            }
 33.1404 -        }
 33.1405 -    }
 33.1406 -    // FIXME: KG - we now have the text we want.
 33.1407 -    // Now we need to strip sigs and process them if they are there..
 33.1408 -    
 33.1409 -
 33.1410 -    *longmsg = _longmsg;
 33.1411 -    if (size)
 33.1412 -        *size = _size;
 33.1413 -
 33.1414 -    return PEP_STATUS_OK;
 33.1415 -}
 33.1416 -
 33.1417 -// THIS IS A BEST-EFFORT ONLY FUNCTION, AND WE ARE NOT DOING MORE THAN THE
 33.1418 -// SUBJECT FOR NOW.
 33.1419 -static PEP_STATUS interpret_protected_headers(
 33.1420 -        struct mailmime* mime, 
 33.1421 -        message* msg
 33.1422 -    )
 33.1423 -{
 33.1424 -    // N.B. this is *very much* enigmail output specific, and right now,
 33.1425 -    // we only care about subject replacement.
 33.1426 -    const char* header_string = "Content-Type: text/rfc822-headers; protected-headers=\"v1\"\nContent-Disposition: inline\n\n";
 33.1427 -    size_t content_length = mime->mm_length;
 33.1428 -    size_t header_strlen = strlen(header_string);
 33.1429 -    if (header_strlen < content_length) {
 33.1430 -        const char* headerblock = mime->mm_mime_start;
 33.1431 -        size_t subject_len = 0;
 33.1432 -        headerblock = strstr(headerblock, header_string);
 33.1433 -        if (headerblock) {
 33.1434 -            const char* subj_start = "Subject: ";
 33.1435 -            headerblock = strstr(headerblock, subj_start);
 33.1436 -            if (headerblock) {
 33.1437 -                size_t subj_len = strlen(subj_start);
 33.1438 -                headerblock += subj_len;
 33.1439 -                char* end_pt = strstr(headerblock, "\n");
 33.1440 -                if (end_pt) {
 33.1441 -                    if (end_pt != mime->mm_mime_start && *(end_pt - 1) == '\r')
 33.1442 -                        end_pt--;
 33.1443 -                    subject_len = end_pt - headerblock;
 33.1444 -                    char* new_subj = (char*)calloc(subject_len + 1, 1);
 33.1445 -                    if (new_subj) {
 33.1446 -                        strlcpy(new_subj, headerblock, subject_len + 1);
 33.1447 -                        free(msg->shortmsg);
 33.1448 -                        msg->shortmsg = new_subj;
 33.1449 -                    }    
 33.1450 -                } // if there's no endpoint, there's something wrong here so we ignore all
 33.1451 -                  // This is best effort.
 33.1452 -            }
 33.1453 -        }
 33.1454 -    }
 33.1455 -    return PEP_STATUS_OK;
 33.1456 -}
 33.1457 -
 33.1458 -static PEP_STATUS interpret_MIME(
 33.1459 -        struct mailmime *mime,
 33.1460 -        message *msg
 33.1461 -    )
 33.1462 -{
 33.1463 -    PEP_STATUS status = PEP_STATUS_OK;
 33.1464 -
 33.1465 -    assert(mime);
 33.1466 -    assert(msg);
 33.1467 -
 33.1468 -    struct mailmime_content *content = mime->mm_content_type;
 33.1469 -    if (content) {
 33.1470 -        if (_is_multipart(content, "alternative")) {
 33.1471 -            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 33.1472 -            if (partlist == NULL)
 33.1473 -                return PEP_ILLEGAL_VALUE;
 33.1474 -
 33.1475 -            clistiter *cur;
 33.1476 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 33.1477 -                struct mailmime *part = clist_content(cur);
 33.1478 -                if (part == NULL)
 33.1479 -                    return PEP_ILLEGAL_VALUE;
 33.1480 -
 33.1481 -                content = part->mm_content_type;
 33.1482 -                assert(content);
 33.1483 -                if (content == NULL)
 33.1484 -                    return PEP_ILLEGAL_VALUE;
 33.1485 -
 33.1486 -                if (_is_text_part(content, "plain") && msg->longmsg == NULL) {
 33.1487 -                    status = interpret_body(part, &msg->longmsg, NULL);
 33.1488 -                    if (status)
 33.1489 -                        return status;
 33.1490 -                }
 33.1491 -                else if (_is_text_part(content, "rfc822-headers")) {
 33.1492 -                    status = interpret_protected_headers(part, msg);
 33.1493 -                    if (status)
 33.1494 -                        return status;
 33.1495 -                }
 33.1496 -                else if (_is_text_part(content, "html") &&
 33.1497 -                        msg->longmsg_formatted == NULL) {
 33.1498 -                    status = interpret_body(part, &msg->longmsg_formatted,
 33.1499 -                            NULL);
 33.1500 -                    if (status)
 33.1501 -                        return status;
 33.1502 -                }
 33.1503 -                else /* add as attachment */ {
 33.1504 -                    status = interpret_MIME(part, msg);
 33.1505 -                    if (status)
 33.1506 -                        return status;
 33.1507 -                }
 33.1508 -            }
 33.1509 -        }
 33.1510 -        else if (_is_multipart(content, "encrypted")) {
 33.1511 -            if (msg->longmsg == NULL)
 33.1512 -                msg->longmsg = strdup("");
 33.1513 -            assert(msg->longmsg);
 33.1514 -            if (!msg->longmsg)
 33.1515 -                return PEP_OUT_OF_MEMORY;
 33.1516 -
 33.1517 -            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 33.1518 -            if (partlist == NULL)
 33.1519 -                return PEP_ILLEGAL_VALUE;
 33.1520 -
 33.1521 -            clistiter *cur;
 33.1522 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 33.1523 -                struct mailmime *part= clist_content(cur);
 33.1524 -                if (part == NULL)
 33.1525 -                    return PEP_ILLEGAL_VALUE;
 33.1526 -
 33.1527 -                status = interpret_MIME(part, msg);
 33.1528 -                if (status != PEP_STATUS_OK)
 33.1529 -                    return status;
 33.1530 -            }
 33.1531 -        }
 33.1532 -        else if (_is_multipart(content, NULL)) {
 33.1533 -            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 33.1534 -            if (partlist == NULL)
 33.1535 -                return PEP_ILLEGAL_VALUE;
 33.1536 -
 33.1537 -            clistiter *cur;
 33.1538 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 33.1539 -                struct mailmime *part= clist_content(cur);
 33.1540 -                if (part == NULL)
 33.1541 -                    return PEP_ILLEGAL_VALUE;
 33.1542 -                status = interpret_MIME(part, msg);
 33.1543 -                if (status != PEP_STATUS_OK)
 33.1544 -                    return status;
 33.1545 -            }
 33.1546 -        }
 33.1547 -        else {
 33.1548 -            if (_is_text_part(content, "html") &&
 33.1549 -                msg->longmsg_formatted == NULL) {
 33.1550 -                status = interpret_body(mime, &msg->longmsg_formatted,
 33.1551 -                                        NULL);
 33.1552 -                if (status)
 33.1553 -                    return status;
 33.1554 -            }
 33.1555 -            else if (_is_text_part(content, "rfc822-headers")) {
 33.1556 -                status = interpret_protected_headers(mime, msg);
 33.1557 -                if (status)
 33.1558 -                    return status;
 33.1559 -            }
 33.1560 -            else if (_is_text_part(content, NULL) && msg->longmsg == NULL) {
 33.1561 -                status = interpret_body(mime, &msg->longmsg, NULL);
 33.1562 -                if (status)
 33.1563 -                    return status;
 33.1564 -            }
 33.1565 -            else {
 33.1566 -                char *data = NULL;
 33.1567 -                size_t size = 0;
 33.1568 -                char * mime_type;
 33.1569 -                char * charset;
 33.1570 -                char * filename;
 33.1571 -                int r;
 33.1572 -
 33.1573 -                r = _get_content_type(content, &mime_type, &charset);
 33.1574 -                switch (r) {
 33.1575 -                    case 0:
 33.1576 -                        break;
 33.1577 -                    case EINVAL:
 33.1578 -                        return PEP_ILLEGAL_VALUE;
 33.1579 -                    case ENOMEM:
 33.1580 -                        return PEP_OUT_OF_MEMORY;
 33.1581 -                    default:
 33.1582 -                        return PEP_UNKNOWN_ERROR;
 33.1583 -                }
 33.1584 -
 33.1585 -                assert(mime_type);
 33.1586 -
 33.1587 -                status = interpret_body(mime, &data, &size);
 33.1588 -                if (status)
 33.1589 -                    return status;
 33.1590 -
 33.1591 -                pEp_rid_list_t* resource_id_list = _get_resource_id_list(mime);
 33.1592 -                pEp_rid_list_t* chosen_resource_id = choose_resource_id(resource_id_list);
 33.1593 -                
 33.1594 -                //filename = _get_filename_or_cid(mime);
 33.1595 -                char *_filename = NULL;
 33.1596 -                
 33.1597 -                if (chosen_resource_id) {
 33.1598 -                    filename = chosen_resource_id->rid;
 33.1599 -                    size_t index = 0;
 33.1600 -                    /* NOTA BENE */
 33.1601 -                    /* The prefix we just added shouldn't be a problem - this is about decoding %XX (RFC 2392) */
 33.1602 -                    /* If it becomes one, we have some MESSY fixing to do. :(                                  */
 33.1603 -                    r = mailmime_encoded_phrase_parse("utf-8", filename,
 33.1604 -                            strlen(filename), &index, "utf-8", &_filename);
 33.1605 -                    if (r) {
 33.1606 -                        goto enomem;
 33.1607 -                    }
 33.1608 -                    char* file_prefix = NULL;
 33.1609 -                    
 33.1610 -                    /* in case there are others later */
 33.1611 -                    switch (chosen_resource_id->rid_type) {
 33.1612 -                        case PEP_RID_CID:
 33.1613 -                            file_prefix = "cid";
 33.1614 -                            break;
 33.1615 -                        case PEP_RID_FILENAME:
 33.1616 -                            file_prefix = "file";
 33.1617 -                            break;
 33.1618 -                        default:
 33.1619 -                            break;
 33.1620 -                    }
 33.1621 -
 33.1622 -                    
 33.1623 -                    if (file_prefix) {
 33.1624 -                        filename = build_uri(file_prefix, _filename);
 33.1625 -                        free(_filename);
 33.1626 -                        _filename = filename;
 33.1627 -                    }
 33.1628 -                }
 33.1629 -
 33.1630 -                bloblist_t *_a = bloblist_add(msg->attachments, data, size,
 33.1631 -                        mime_type, _filename);
 33.1632 -                free(_filename);
 33.1633 -                free_rid_list(resource_id_list);
 33.1634 -                resource_id_list = NULL;
 33.1635 -                if (_a == NULL)
 33.1636 -                    return PEP_OUT_OF_MEMORY;
 33.1637 -                if (msg->attachments == NULL)
 33.1638 -                    msg->attachments = _a;
 33.1639 -            }
 33.1640 -        }
 33.1641 -    }
 33.1642 -
 33.1643 -    return PEP_STATUS_OK;
 33.1644 -
 33.1645 -enomem:
 33.1646 -    return PEP_OUT_OF_MEMORY;
 33.1647 -}
 33.1648 -
 33.1649 -DYNAMIC_API PEP_STATUS mime_decode_message(
 33.1650 -        const char *mimetext,
 33.1651 -        size_t size,
 33.1652 -        message **msg
 33.1653 -    )
 33.1654 -{
 33.1655 -    PEP_STATUS status = PEP_STATUS_OK;
 33.1656 -    struct mailmime * mime = NULL;
 33.1657 -    int r;
 33.1658 -    message *_msg = NULL;
 33.1659 -    size_t index;
 33.1660 -
 33.1661 -    assert(mimetext);
 33.1662 -    assert(msg);
 33.1663 -
 33.1664 -    if (!(mimetext && msg))
 33.1665 -        return PEP_ILLEGAL_VALUE;
 33.1666 -
 33.1667 -    *msg = NULL;
 33.1668 -
 33.1669 -    index = 0;
 33.1670 -    r = mailmime_parse(mimetext, size, &index, &mime);
 33.1671 -    assert(r == 0);
 33.1672 -    assert(mime);
 33.1673 -    if (r) {
 33.1674 -        if (r == MAILIMF_ERROR_MEMORY)
 33.1675 -            goto enomem;
 33.1676 -        else
 33.1677 -            goto err_mime;