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
     2.1 --- a/.hgtags	Thu Mar 28 15:40:45 2019 +0100
     2.2 +++ b/.hgtags	Fri May 17 17:30:57 2019 +0200
     2.3 @@ -10,3 +10,20 @@
     2.4  43ab5608555e12cb110ccda79cbfb9783e40408b Release 1.1.0
     2.5  084c00652ac9fedcd56e2c316be795ed0ba00b2f Release 1.1.1
     2.6  eace10725457069b5c5bfdb8723e876bfa63d753 Release 1.2.0
     2.7 +9425e2da65e4d4e3febab6725a0a101676386313 1.3.0-RC-default
     2.8 +4d6c07372e3ef7d8768908d17f07a54d74ef291d 1.3.0-RC-sync
     2.9 +1bf48c2e4230d4e7cb2589743182a230aa60691b 1.3.1-RC2-sync
    2.10 +1bf48c2e4230d4e7cb2589743182a230aa60691b 1.3.1-RC2-sync
    2.11 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    2.12 +4d4dbd6be59a35ad107eb334fb0eaf2d5b08c517 add
    2.13 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    2.14 +4d4dbd6be59a35ad107eb334fb0eaf2d5b08c517 1.3.1-RC2-sync
    2.15 +4d4dbd6be59a35ad107eb334fb0eaf2d5b08c517 1.3.1-RC2-sync
    2.16 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    2.17 +4998d60e0fe87847185ee3e99ae1b42074722882 2.0.0-RC
    2.18 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    2.19 +0000000000000000000000000000000000000000 1.3.1-RC2-sync
    2.20 +4998d60e0fe87847185ee3e99ae1b42074722882 2.0.0-RC
    2.21 +0000000000000000000000000000000000000000 2.0.0-RC
    2.22 +0000000000000000000000000000000000000000 2.0.0-RC
    2.23 +c4eb9bb2008fbe531f892fd56f8edce53048eb62 2.0.0-RC
     3.1 --- a/Makefile	Thu Mar 28 15:40:45 2019 +0100
     3.2 +++ b/Makefile	Fri May 17 17:30:57 2019 +0200
     3.3 @@ -5,58 +5,61 @@
     3.4  
     3.5  HERE_REL := $(notdir $(CURDIR))
     3.6  
     3.7 -include default.conf
     3.8 +include Makefile.conf
     3.9  
    3.10  ifneq ($(wildcard local.conf),)
    3.11      $(info ================================================)
    3.12 -    $(info Overrides in \`local.conf\` are used.)
    3.13 +    $(info Overrides in `local.conf` are used.)
    3.14      $(info ================================================)
    3.15  endif
    3.16  
    3.17  ifdef BUILD_CONFIG
    3.18      $(info ================================================)
    3.19 -    $(info Overrides in \`$(BUILD_CONFIG)\` are used.)
    3.20 +    $(info Overrides in `$(BUILD_CONFIG)` are used.)
    3.21      $(info ================================================)
    3.22  endif
    3.23  
    3.24 -.PHONY: all
    3.25 -all:
    3.26 +.PHONY: all sync asn1 build install dbinstall uninstall clean tags test package db
    3.27 +
    3.28 +build: asn1
    3.29 +	$(MAKE) -C src
    3.30 +
    3.31 +all: build
    3.32 +	make -C test
    3.33 +
    3.34 +sync:
    3.35  	$(MAKE) -C sync
    3.36 +
    3.37 +asn1: sync
    3.38  	$(MAKE) -C asn.1
    3.39 -	$(MAKE) -C src all
    3.40  
    3.41 -.PHONY: install
    3.42 -install: all
    3.43 +install: build
    3.44  	$(MAKE) -C src install
    3.45  	$(MAKE) -C asn.1 install
    3.46  
    3.47 -.PHONY: uninstall
    3.48 +dbinstall: db
    3.49 +	$(MAKE) -C db install
    3.50 +
    3.51  uninstall:
    3.52  	$(MAKE) -C src uninstall
    3.53  	$(MAKE) -C asn.1 uninstall
    3.54  
    3.55 -.PHONY: clean
    3.56  clean:
    3.57  	$(MAKE) -C src clean
    3.58  	$(MAKE) -C test clean
    3.59  	$(MAKE) -C db clean
    3.60  	$(MAKE) -C sync clean
    3.61  	$(MAKE) -C asn.1 clean
    3.62 -	rm -rf test_home
    3.63  
    3.64 -.PHONY: tags
    3.65  tags:
    3.66  	$(MAKE) -C asn.1 tags
    3.67  	$(MAKE) -C src tags
    3.68  
    3.69 -.PHONY: test
    3.70  test: all
    3.71  	$(MAKE) -C test test
    3.72  
    3.73 -.PHONY: package
    3.74  package: clean
    3.75  	cd .. ; COPYFILE_DISABLE=true tar cjf pEpEngine.tar.bz2 "$(HERE_REL)"
    3.76  
    3.77 -.PHONY: db
    3.78  db:
    3.79  	$(MAKE) -C db db
     4.1 --- a/Makefile.conf	Thu Mar 28 15:40:45 2019 +0100
     4.2 +++ b/Makefile.conf	Fri May 17 17:30:57 2019 +0200
     4.3 @@ -5,107 +5,262 @@
     4.4  
     4.5  # See `doc/build-<your platform>.md` for documentation on how to build, and customize your build.
     4.6  
     4.7 +# This file sets all the make variables that allow you to customize a build.
     4.8 +# There are 3 ways in which you can customize your build:
     4.9 +# 1) Edit the variable assignments in this file (this is a tracked file, so your repository will be dirty)
    4.10 +# 2) Create `local.conf` and fill it with variable assignments.
    4.11 +# 3) Set the environment variable `BUILD_CONFIG` to an absolute path.
    4.12 +#    The variable assignments found in the make file at the path indicated by `BUILD_CONFIG` will be evaluated.
    4.13 +# Customization options are applied in the order given above. Later variable assignments take precedence over earlier ones.
    4.14 +# It is possible to use multiple variants simultaniously.
    4.15 +# If nothing is changed according to these 3 methods, a default configuration for your platform (specified below) will be used for the build.
    4.16 +
    4.17 +
    4.18 +######### Header #########
    4.19 +HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
    4.20 +
    4.21 +
    4.22  ######### General #########
    4.23  # To use (only) system libraries, set all the *_INC and *_LIB variables to the empty string.
    4.24  # All the *_INC and *_LIB variables are command line flags, not paths.
    4.25  # Thus, all *_INC variables' values must start with "-I", and all *_LIB variables' values must start with "-L".
    4.26  
    4.27 -#BUILD_ON:=$(shell uname)
    4.28 +BUILD_ON:=$(shell uname)
    4.29  
    4.30  # This variable specifies the platform that the engine should be cross-compiled for.
    4.31 -#BUILD_FOR=$(BUILD_ON)
    4.32 +BUILD_FOR=$(BUILD_ON)
    4.33 +
    4.34 +# Cross-compiling is currently not supported.
    4.35 +# Maybe you can hack something with `local.conf`.
    4.36 +ifneq ($(BUILD_ON),$(BUILD_FOR))
    4.37 +    $(error I don't know how to build for $(BUILD_FOR) on $(BUILD_ON).)
    4.38 +endif
    4.39  
    4.40  # Installation path prefix for libraries and binaries, except for system.db
    4.41 -#PREFIX=$(HOME)
    4.42 +PREFIX=$(HOME)
    4.43  
    4.44  # Installation path for system.db
    4.45 -#SYSTEM_DB=/usr/local/share/pEp/system.db
    4.46 +SYSTEM_DB=/usr/local/share/pEp/system.db
    4.47  
    4.48  # Filename of the pEpEngine library
    4.49 -#TARGET=libpEpEngine.so
    4.50 +ifeq ($(BUILD_FOR),Linux)
    4.51 +    TARGET=libpEpEngine.so
    4.52 +else ifeq ($(BUILD_FOR),Darwin)
    4.53 +    TARGET=libpEpEngine.dylib
    4.54 +endif
    4.55 +
    4.56 +# If empty, create a release build.
    4.57 +# Otherwise, create a debug build.
    4.58 +# This variable is ineffective when set anywhere else but here.
    4.59 +DEBUG=placeholder
    4.60 +
    4.61 +# If empty, suppress compiler warnings.
    4.62 +# Otherwise, print warnings.
    4.63 +# This variable is ineffective when set anywhere else but here.
    4.64 +WARN=placeholder
    4.65  
    4.66  
    4.67  ######### C and C++ #########
    4.68 -#TARGET_ARCH=
    4.69 +TARGET_ARCH=
    4.70  
    4.71  # The following two variables will be appended to.
    4.72 -# You can thus not set them to a fixed value here.
    4.73 -#LDFLAGS=
    4.74 +# You can thus not set them to a final, fixed value here.
    4.75 +ifeq ($(BUILD_FOR),Linux)
    4.76 +    LDFLAGS=
    4.77 +else ifeq ($(BUILD_FOR),Darwin)
    4.78 +    # "-bind_at_load" helps find symbol resolution errors faster
    4.79 +    LDFLAGS=-bind_at_load
    4.80 +endif
    4.81  
    4.82 -#LDLIBS=
    4.83 +LDLIBS=
    4.84  
    4.85  
    4.86  ######### C #########
    4.87 -#CC=
    4.88 +ifeq ($(BUILD_FOR),Linux)
    4.89 +    CC=gcc -std=c99 -pthread
    4.90 +else ifeq ($(BUILD_FOR),Darwin)
    4.91 +    # clang issues a warning when "-pthread" is used for linking.
    4.92 +    # So, include it in CFLAGS, and not in CC
    4.93 +    CC=clang -std=c99
    4.94 +endif
    4.95  
    4.96 -#CFLAGS=-fPIC -fstrict-aliasing -fdiagnostics-color=always
    4.97 +ifeq ($(BUILD_FOR),Linux)
    4.98 +    CFLAGS=-fPIC -fstrict-aliasing -fdiagnostics-color=always
    4.99 +else ifeq ($(BUILD_FOR),Darwin)
   4.100 +    CFLAGS=-pthread -fPIC -fstrict-aliasing -fcolor-diagnostics
   4.101 +endif
   4.102  
   4.103 -#CPPFLAGS=
   4.104 -
   4.105 -#CFLAGS+= -w -O3 -DNDEBUG
   4.106 +# The flag -DNDEBUG will always be removed from CFLAGS for compiling tests.
   4.107 +# The tests do not work properly, if compiled with -DNDEBUG
   4.108 +ifeq ($(BUILD_FOR),Linux)
   4.109 +    ifdef WARN
   4.110 +        CFLAGS+= -Wall -pedantic -Wstrict-aliasing=3
   4.111 +    else
   4.112 +        CFLAGS+= -w
   4.113 +    endif
   4.114 +    ifdef DEBUG
   4.115 +        CFLAGS+= -g -ggdb -DDEBUG_ERRORSTACK
   4.116 +    else
   4.117 +        CFLAGS+= -O3 -DNDEBUG
   4.118 +    endif
   4.119 +else ifeq ($(BUILD_FOR),Darwin)
   4.120 +    ifdef WARN
   4.121 +        # FIXME Remove 'no-extended-offsetof' after ENGINE-236 is closed.
   4.122 +        CFLAGS+= -Wall -pedantic -Wno-extended-offsetof
   4.123 +    else
   4.124 +        CFLAGS+= -w
   4.125 +    endif
   4.126 +    ifdef DEBUG
   4.127 +        CFLAGS+= -O0 -g -DDEBUG_ERRORSTACK
   4.128 +    else
   4.129 +        CFLAGS+= -O3 -DNDEBUG
   4.130 +    endif
   4.131 +endif
   4.132  
   4.133  # Additional CFLAGS used for compiling ASN1C-generated code
   4.134 -#CFLAGS_GENERATED=-D_DEFAULT_SOURCE
   4.135 +ifeq ($(BUILD_FOR),Linux)
   4.136 +    # The '_DEFAULT_SOURCE' feature test macro is required to suppress the warning
   4.137 +    #   _BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE
   4.138 +    # otherwise printed during the compilation of every asn1c-generated C file.
   4.139 +    # It's a glibc specific warning, only present in few versions around ~2.19.
   4.140 +    # See https://lwn.net/Articles/590381/ for a discussion.
   4.141 +    CFLAGS_GENERATED=-D_DEFAULT_SOURCE
   4.142 +else ifeq ($(BUILD_FOR),Darwin)
   4.143 +    CFLAGS_GENERATED=
   4.144 +endif
   4.145  
   4.146  
   4.147  ######### C++ #########
   4.148 -#CXX=g++ -std=gnu++11 -pthread
   4.149 +ifeq ($(BUILD_FOR),Linux)
   4.150 +    CXX=g++ -std=gnu++11 -pthread
   4.151 +else ifeq ($(BUILD_FOR),Darwin)
   4.152 +    # clang issues a warning when "-pthread" is used for linking. So, include it in CXXFLAGS, and not in CXX
   4.153 +    CXX=clang -std=c++11
   4.154 +endif
   4.155  
   4.156 -#CXXFLAGS=-fdiagnostics-color=always -I../src -I../asn.1 $(ETPAN_INC) -w -O3 -DNDEBUG
   4.157 +# The flag -DNDEBUG will always be removed from CXXFLAGS for compiling tests.
   4.158 +# The tests do not work properly, if compiled with -DNDEBUG
   4.159 +ifeq ($(BUILD_FOR),Linux)
   4.160 +    CXXFLAGS=-fdiagnostics-color=always -I../src -I../asn.1 $(ETPAN_INC)
   4.161 +    ifdef WARN
   4.162 +        CXXFLAGS+=
   4.163 +    else
   4.164 +        CXXFLAGS+= -w
   4.165 +    endif
   4.166 +    ifdef DEBUG
   4.167 +        CXXFLAGS+= -g -ggdb
   4.168 +    else
   4.169 +        CXXFLAGS+= -O3 -DNDEBUG
   4.170 +    endif
   4.171 +else ifeq ($(BUILD_FOR),Darwin)
   4.172 +    CXXFLAGS=-pthread -fcolor-diagnostics -I../src -I../asn.1 $(ETPAN_INC)
   4.173 +    ifdef WARN
   4.174 +        CXXFLAGS+=
   4.175 +    else
   4.176 +        CXXFLAGS+= -w
   4.177 +    endif
   4.178 +    ifdef DEBUG
   4.179 +        CXXFLAGS+= -O0 -g
   4.180 +    else
   4.181 +        CXXFLAGS+= -O3 -DNDEBUG
   4.182 +    endif
   4.183 +endif
   4.184 +
   4.185 +
   4.186 +######### C and C++ #########
   4.187 +CPPFLAGS=
   4.188  
   4.189  
   4.190  ######### YML2 #########
   4.191 -#YML2_PATH=$(HOME)/yml2
   4.192 +YML2_PATH=$(HOME)/yml2
   4.193  
   4.194 -#YML2_PROC=$(YML2_PATH)/yml2proc
   4.195 +YML2_PROC=$(YML2_PATH)/yml2proc $(YML2_OPTS)
   4.196  
   4.197 -#YML2_OPTS=--encoding=utf8
   4.198 +YML2_OPTS=--encoding=utf8
   4.199  
   4.200  
   4.201  ######### asn1c #########
   4.202  # asn1c binary
   4.203 -#ASN1C=asn1c
   4.204 +ASN1C=asn1c
   4.205  
   4.206  # asn1c include search flag
   4.207 +ASN1C_INC=
   4.208  #ASN1C_INC=-I$(HOME)/include
   4.209  
   4.210  
   4.211  ######### libetpan #########
   4.212  # libetpan library search flag
   4.213 -#ETPAN_LIB=-L$(PREFIX)/lib
   4.214 +ETPAN_LIB=
   4.215 +#ETPAN_LIB=-L$(HOME)/lib
   4.216  
   4.217  # libetpan include search flag
   4.218 -#ETPAN_INC=-I$(PREFIX)/include
   4.219 +ETPAN_INC=
   4.220 +#ETPAN_INC=-I$(HOME)/include
   4.221 +
   4.222 +
   4.223 +######### pEp MIME #########
   4.224 +# set this to skip libetpan and use PEP_MIME instead
   4.225 +# PEP_MIME=1
   4.226 +#
   4.227 +# pEp MIME library search flag
   4.228 +PEP_MIME_LIB=
   4.229 +# pEp MIME include search flag
   4.230 +PEP_MIME_INC=
   4.231  
   4.232  
   4.233  ######### sqlite3 #########
   4.234  # If empty (or undefined), compile sqlite3 from the sources shipped with the pEp distribution.
   4.235  # Otherwise, use an sqlite3 implementation found in the OS's include/library paths.
   4.236 -#SQLITE3_FROM_OS=placeholder
   4.237 +SQLITE3_FROM_OS=placeholder
   4.238  
   4.239  
   4.240  ######### OpenPGP #########
   4.241  # Path of GPG binary
   4.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.
   4.243 -#GPG_CMD:=$(shell gpgconf --list-components | awk -F: '/^gpg:/ { print $$3; exit 0; }')
   4.244 +GPG_CMD:=$(shell gpgconf --list-components | awk -F: '/^gpg:/ { print $$3; exit 0; }')
   4.245 +
   4.246 +# Selects OpenPGP implementation. must be either `SEQUOIA`, `GPG` or `NETPGP`
   4.247 +OPENPGP=GPG
   4.248  
   4.249 -# Selects OpenPGP implementation. must be either `GPG` or `NETPGP`
   4.250 -#OPENPGP=GPG
   4.251 +# Sequoia-specific variables
   4.252 +SEQUOIA_CFLAGS=
   4.253 +SEQUOIA_LDFLAGS=
   4.254 +SEQUOIA_LIB=
   4.255 +SEQUOIA_INC=
   4.256  
   4.257 -# Path of libGPGME binary
   4.258 -#LIBGPGME=libgpgme.so.11
   4.259 +# libGPGME filename
   4.260 +ifeq ($(BUILD_FOR),Linux)
   4.261 +    LIBGPGME=libgpgme.so.11
   4.262 +else ifeq ($(BUILD_FOR),Darwin)
   4.263 +    LIBGPGME=libgpgme.11.dylib
   4.264 +endif
   4.265  
   4.266  # libGPGME library search flag
   4.267 -#GPGME_LIB=
   4.268 +GPGME_LIB=
   4.269 +#GPGME_LIB=-L$(HOME)/lib
   4.270 +
   4.271 +# libGPGME include search flag
   4.272 +GPGME_INC=
   4.273 +#GPGME_INC=-I$(HOME)/include
   4.274 +
   4.275 +# NETPGP library search flag
   4.276 +NETPGP_LIB=
   4.277 +#NETPGP_LIB=-L$(HOME)/lib
   4.278  
   4.279  # libGPGME include search flag
   4.280 -#GPGME_INC=
   4.281 +NETPGP_INC=
   4.282 +#NETPGP_INC=-I$(HOME)/include
   4.283 +
   4.284 +
   4.285  
   4.286 -# NETPGP library search flag
   4.287 -#NETPGP_LIB=-L$(PREFIX)/lib
   4.288 +######### CppUnit #########
   4.289 +# CppUnit library search flag
   4.290 +CPPUNIT_LIB=
   4.291 +#CPPUNIT_LIB=-L$(HOME)/local/lib
   4.292  
   4.293 -# libGPGME include search flag
   4.294 -#NETPGP_INC=-I$(PREFIX)/include
   4.295 +# CppUnit include search flag
   4.296 +CPPUNIT_INC=
   4.297 +#CPPUNIT_INC=-I$(HOME)/local/inc
   4.298  
   4.299  
   4.300  ######### Engine internals #########
   4.301 @@ -114,7 +269,38 @@
   4.302  # CRASHDUMP_DEFAULT_LINES - number of log lines to deliver for crashdumps
   4.303  # Example:
   4.304  #    EXTRA_MACROS=-DDEFAULT_KEYSERVER=\"default-server.org\" -DCRASHDUMP_DEFAULT_LINES=23
   4.305 -#EXTRA_MACROS=
   4.306 +EXTRA_MACROS=
   4.307 +
   4.308 +
   4.309 +######### Misc #########
   4.310 +# FIXME Maybe include these variables here.
   4.311 +# Check how they are used throughout the project before setting them here
   4.312 +#LLDB_BIN
   4.313 +
   4.314 +# Add this for running tests in debugger
   4.315 +#TEST_DEBUGGER=lldb --batch -o r
   4.316 +
   4.317 +# comma-separated list of tests to exclude from gensuite (relevant for running tests only)
   4.318 +EXCLUDE=
   4.319 +
   4.320 +
   4.321 +######### Footer #########
   4.322 +-include $(HERE)/local.conf
   4.323  
   4.324 -# add this for running tests in debugger
   4.325 -#TEST_DEBUGGER=lldb --batch -o r
   4.326 +ifdef BUILD_CONFIG
   4.327 +    include $(BUILD_CONFIG)
   4.328 +endif
   4.329 +
   4.330 +######### Post processing assignments ########
   4.331 +# These variables are ineffective when set anywhere else but here.
   4.332 +ifeq ($(OPENPGP),SEQUOIA)
   4.333 +    SEQUOIA_CFLAGS=$(shell pkg-config --cflags-only-other sequoia-openpgp)
   4.334 +    SEQUOIA_LDFLAGS=$(shell pkg-config --libs-only-l --libs-only-other sequoia-openpgp)
   4.335 +    SEQUOIA_LIB=$(shell pkg-config --libs-only-L sequoia-openpgp)
   4.336 +    SEQUOIA_INC=$(shell pkg-config --cflags-only-I sequoia-openpgp)
   4.337 +    CFLAGS+= $(SEQUOIA_CFLAGS)
   4.338 +    LD_FLAGS+= $(SEQUOIA_LDFLAGS)
   4.339 +endif
   4.340 +
   4.341 +# YML_PATH is needed in the environment of every call to a program of the YML2 distribution
   4.342 +export YML_PATH=$(YML2_PATH)
     5.1 --- a/asn.1/Makefile	Thu Mar 28 15:40:45 2019 +0100
     5.2 +++ b/asn.1/Makefile	Fri May 17 17:30:57 2019 +0200
     5.3 @@ -1,30 +1,26 @@
     5.4  # This file is under GNU General Public License 3.0
     5.5  # see LICENSE.txt
     5.6  
     5.7 -include ../default.conf
     5.8 +include ../Makefile.conf
     5.9  
    5.10  ALL_SOURCE=$(subst $(NO_SOURCE),,$(wildcard *.c))
    5.11  ALL_OBJECTS=$(subst .c,.o,$(ALL_SOURCE))
    5.12  
    5.13 -all: generate
    5.14 -	make libasn1.a
    5.15 +.PHONY: all clean install uninstall
    5.16 +
    5.17 +all: Sync.c
    5.18 +	$(MAKE) libasn1.a
    5.19  
    5.20  libasn1.a: $(ALL_OBJECTS)
    5.21 -	ar -rc $@ $(ALL_OBJECTS)
    5.22 -
    5.23 -generate: Sync.c
    5.24 -	rm -f converter-sample.c
    5.25 +	$(AR) -rc $@ $(ALL_OBJECTS)
    5.26  
    5.27  %.o: %.c %.h
    5.28 -	$(CC) $(CFLAGS) $(OPTIMIZE) -I. -I$(ASN1C_INC) -c $< -o $@
    5.29 +	$(CC) $(CFLAGS) $(OPTIMIZE) -I. $(ASN1C_INC) -c $< -o $@
    5.30  
    5.31  Sync.c: sync.asn1 keysync.asn1 pEp.asn1
    5.32  	$(ASN1C) -gen-PER -fincludes-quoted -fcompound-names -pdu=auto pEp.asn1 keysync.asn1 $<
    5.33 -
    5.34 -sync.asn1 keysync.asn1 pEp.asn1:
    5.35 -	cp -f ../sync/generated/*.asn1 ../asn.1
    5.36 -
    5.37 -.PHONY: clean install uninstall tags
    5.38 +	rm -f converter-sample.c
    5.39 +	touch Sync.c
    5.40  
    5.41  clean:
    5.42  	rm -f *.a *.o *.c *.h *.sample sync.asn1 keysync.asn1
    5.43 @@ -33,5 +29,5 @@
    5.44  
    5.45  uninstall:
    5.46  
    5.47 -tags:
    5.48 +tags: $(wildcard *.c) $(wildcard *.h)
    5.49  	ctags *.c *.h
     6.1 --- a/build-android/jni/Android.mk	Thu Mar 28 15:40:45 2019 +0100
     6.2 +++ b/build-android/jni/Android.mk	Fri May 17 17:30:57 2019 +0200
     6.3 @@ -37,7 +37,7 @@
     6.4  $(shell sh $(LOCAL_PATH)/../takeOutHeaderFiles.sh $(LOCAL_PATH)../../)
     6.5  LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)../include
     6.6  
     6.7 -ENGINE_SRC_FILES := $(shell find $(LOCAL_PATH)/../../src/ ! -name "*netpgp*" -name "*.c")
     6.8 +ENGINE_SRC_FILES := $(shell find $(LOCAL_PATH)/../../src/ ! -name "*sequoia*" ! -name "*netpgp*" -name "*.c")
     6.9  #ENGINE_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../src/*.c)
    6.10  ASN1_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../asn.1/*.c)
    6.11  LOCAL_SRC_FILES := $(ENGINE_SRC_FILES:%=%)  $(ASN1_SRC_FILES:$(LOCAL_PATH)/%=%)
     7.1 --- a/build-android/jni/Application.mk	Thu Mar 28 15:40:45 2019 +0100
     7.2 +++ b/build-android/jni/Application.mk	Fri May 17 17:30:57 2019 +0200
     7.3 @@ -1,4 +1,4 @@
     7.4  APP_OPTIM := debug
     7.5  APP_PLATFORM=android-21
     7.6  APP_ABI := armeabi-v7a
     7.7 -NDK_TOOLCHAIN_VERSION = 4.8
     7.8 +NDK_TOOLCHAIN_VERSION = clang
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/build-mac/generated-files-asn1.txt	Fri May 17 17:30:57 2019 +0200
     8.3 @@ -0,0 +1,109 @@
     8.4 +$(SRCROOT)/../asn.1/BIT_STRING.c
     8.5 +$(SRCROOT)/../asn.1/BIT_STRING.h
     8.6 +$(SRCROOT)/../asn.1/BOOLEAN.c
     8.7 +$(SRCROOT)/../asn.1/BOOLEAN.h
     8.8 +$(SRCROOT)/../asn.1/Beacon.c
     8.9 +$(SRCROOT)/../asn.1/Beacon.h
    8.10 +$(SRCROOT)/../asn.1/CommitAccept.c
    8.11 +$(SRCROOT)/../asn.1/CommitAccept.h
    8.12 +$(SRCROOT)/../asn.1/CommitAcceptFirst.c
    8.13 +$(SRCROOT)/../asn.1/CommitAcceptFirst.h
    8.14 +$(SRCROOT)/../asn.1/CommitAcceptForGroup.c
    8.15 +$(SRCROOT)/../asn.1/CommitAcceptForGroup.h
    8.16 +$(SRCROOT)/../asn.1/CommitAcceptSecond.c
    8.17 +$(SRCROOT)/../asn.1/CommitAcceptSecond.h
    8.18 +$(SRCROOT)/../asn.1/CommitReject.c
    8.19 +$(SRCROOT)/../asn.1/CommitReject.h
    8.20 +$(SRCROOT)/../asn.1/GroupKeys.c
    8.21 +$(SRCROOT)/../asn.1/GroupKeys.h
    8.22 +$(SRCROOT)/../asn.1/GroupTrustThisKey.c
    8.23 +$(SRCROOT)/../asn.1/GroupTrustThisKey.h
    8.24 +$(SRCROOT)/../asn.1/Hash.c
    8.25 +$(SRCROOT)/../asn.1/Hash.h
    8.26 +$(SRCROOT)/../asn.1/Hex.c
    8.27 +$(SRCROOT)/../asn.1/Hex.h
    8.28 +$(SRCROOT)/../asn.1/INTEGER.c
    8.29 +$(SRCROOT)/../asn.1/INTEGER.h
    8.30 +$(SRCROOT)/../asn.1/ISO639-1.c
    8.31 +$(SRCROOT)/../asn.1/ISO639-1.h
    8.32 +$(SRCROOT)/../asn.1/Identity.c
    8.33 +$(SRCROOT)/../asn.1/Identity.h
    8.34 +$(SRCROOT)/../asn.1/IdentityList.c
    8.35 +$(SRCROOT)/../asn.1/IdentityList.h
    8.36 +$(SRCROOT)/../asn.1/KeySync.c
    8.37 +$(SRCROOT)/../asn.1/KeySync.h
    8.38 +$(SRCROOT)/../asn.1/NativeEnumerated.c
    8.39 +$(SRCROOT)/../asn.1/NativeEnumerated.h
    8.40 +$(SRCROOT)/../asn.1/NativeInteger.c
    8.41 +$(SRCROOT)/../asn.1/NativeInteger.h
    8.42 +$(SRCROOT)/../asn.1/NegotiationOpen.c
    8.43 +$(SRCROOT)/../asn.1/NegotiationOpen.h
    8.44 +$(SRCROOT)/../asn.1/NegotiationRequest.c
    8.45 +$(SRCROOT)/../asn.1/NegotiationRequest.h
    8.46 +$(SRCROOT)/../asn.1/OCTET_STRING.c
    8.47 +$(SRCROOT)/../asn.1/OCTET_STRING.h
    8.48 +$(SRCROOT)/../asn.1/OwnKeys.c
    8.49 +$(SRCROOT)/../asn.1/OwnKeys.h
    8.50 +$(SRCROOT)/../asn.1/OwnKeysFirst.c
    8.51 +$(SRCROOT)/../asn.1/OwnKeysFirst.h
    8.52 +$(SRCROOT)/../asn.1/OwnKeysSecond.c
    8.53 +$(SRCROOT)/../asn.1/OwnKeysSecond.h
    8.54 +$(SRCROOT)/../asn.1/PString.c
    8.55 +$(SRCROOT)/../asn.1/PString.h
    8.56 +$(SRCROOT)/../asn.1/PrintableString.c
    8.57 +$(SRCROOT)/../asn.1/PrintableString.h
    8.58 +$(SRCROOT)/../asn.1/Rollback.c
    8.59 +$(SRCROOT)/../asn.1/Rollback.h
    8.60 +$(SRCROOT)/../asn.1/Sync.c
    8.61 +$(SRCROOT)/../asn.1/Sync.h
    8.62 +$(SRCROOT)/../asn.1/TID.c
    8.63 +$(SRCROOT)/../asn.1/TID.h
    8.64 +$(SRCROOT)/../asn.1/UTF8String.c
    8.65 +$(SRCROOT)/../asn.1/UTF8String.h
    8.66 +$(SRCROOT)/../asn.1/Version.c
    8.67 +$(SRCROOT)/../asn.1/Version.h
    8.68 +$(SRCROOT)/../asn.1/asn_SEQUENCE_OF.c
    8.69 +$(SRCROOT)/../asn.1/asn_SEQUENCE_OF.h
    8.70 +$(SRCROOT)/../asn.1/asn_SET_OF.c
    8.71 +$(SRCROOT)/../asn.1/asn_SET_OF.h
    8.72 +$(SRCROOT)/../asn.1/asn_application.h
    8.73 +$(SRCROOT)/../asn.1/asn_codecs.h
    8.74 +$(SRCROOT)/../asn.1/asn_codecs_prim.c
    8.75 +$(SRCROOT)/../asn.1/asn_codecs_prim.h
    8.76 +$(SRCROOT)/../asn.1/asn_internal.h
    8.77 +$(SRCROOT)/../asn.1/asn_system.h
    8.78 +$(SRCROOT)/../asn.1/ber_decoder.c
    8.79 +$(SRCROOT)/../asn.1/ber_decoder.h
    8.80 +$(SRCROOT)/../asn.1/ber_tlv_length.c
    8.81 +$(SRCROOT)/../asn.1/ber_tlv_length.h
    8.82 +$(SRCROOT)/../asn.1/ber_tlv_tag.c
    8.83 +$(SRCROOT)/../asn.1/ber_tlv_tag.h
    8.84 +$(SRCROOT)/../asn.1/constr_CHOICE.c
    8.85 +$(SRCROOT)/../asn.1/constr_CHOICE.h
    8.86 +$(SRCROOT)/../asn.1/constr_SEQUENCE.c
    8.87 +$(SRCROOT)/../asn.1/constr_SEQUENCE.h
    8.88 +$(SRCROOT)/../asn.1/constr_SEQUENCE_OF.c
    8.89 +$(SRCROOT)/../asn.1/constr_SEQUENCE_OF.h
    8.90 +$(SRCROOT)/../asn.1/constr_SET_OF.c
    8.91 +$(SRCROOT)/../asn.1/constr_SET_OF.h
    8.92 +$(SRCROOT)/../asn.1/constr_TYPE.c
    8.93 +$(SRCROOT)/../asn.1/constr_TYPE.h
    8.94 +$(SRCROOT)/../asn.1/constraints.c
    8.95 +$(SRCROOT)/../asn.1/constraints.h
    8.96 +$(SRCROOT)/../asn.1/der_encoder.c
    8.97 +$(SRCROOT)/../asn.1/der_encoder.h
    8.98 +$(SRCROOT)/../asn.1/pdu_collection.c
    8.99 +$(SRCROOT)/../asn.1/per_decoder.c
   8.100 +$(SRCROOT)/../asn.1/per_decoder.h
   8.101 +$(SRCROOT)/../asn.1/per_encoder.c
   8.102 +$(SRCROOT)/../asn.1/per_encoder.h
   8.103 +$(SRCROOT)/../asn.1/per_opentype.c
   8.104 +$(SRCROOT)/../asn.1/per_opentype.h
   8.105 +$(SRCROOT)/../asn.1/per_support.c
   8.106 +$(SRCROOT)/../asn.1/per_support.h
   8.107 +$(SRCROOT)/../asn.1/xer_decoder.c
   8.108 +$(SRCROOT)/../asn.1/xer_decoder.h
   8.109 +$(SRCROOT)/../asn.1/xer_encoder.c
   8.110 +$(SRCROOT)/../asn.1/xer_encoder.h
   8.111 +$(SRCROOT)/../asn.1/xer_support.c
   8.112 +$(SRCROOT)/../asn.1/xer_support.h
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/build-mac/generated-files-sync.txt	Fri May 17 17:30:57 2019 +0200
     9.3 @@ -0,0 +1,6 @@
     9.4 +$(SRCROOT)/../src/sync_codec.c
     9.5 +$(SRCROOT)/../src/sync_impl.c
     9.6 +$(SRCROOT)/../src/sync_actions.c
     9.7 +$(SRCROOT)/../src/Sync_func.c
     9.8 +$(SRCROOT)/../src/Sync_event.c
     9.9 +$(SRCROOT)/../src/KeySync_fsm.c
    10.1 --- a/build-mac/pEpEngine.xcodeproj/project.pbxproj	Thu Mar 28 15:40:45 2019 +0100
    10.2 +++ b/build-mac/pEpEngine.xcodeproj/project.pbxproj	Fri May 17 17:30:57 2019 +0200
    10.3 @@ -3,23 +3,62 @@
    10.4  	archiveVersion = 1;
    10.5  	classes = {
    10.6  	};
    10.7 -	objectVersion = 46;
    10.8 +	objectVersion = 51;
    10.9  	objects = {
   10.10  
   10.11  /* Begin PBXBuildFile section */
   10.12 +		1521CEF6225C9AEF00FD2AA2 /* CommitAcceptForGroup.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521CEE9225C9AED00FD2AA2 /* CommitAcceptForGroup.c */; };
   10.13 +		1521CEF7225C9AEF00FD2AA2 /* PString.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEA225C9AEE00FD2AA2 /* PString.h */; };
   10.14 +		1521CEF8225C9AEF00FD2AA2 /* Rollback.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEB225C9AEE00FD2AA2 /* Rollback.h */; };
   10.15 +		1521CEF9225C9AEF00FD2AA2 /* CommitAcceptForGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEC225C9AEE00FD2AA2 /* CommitAcceptForGroup.h */; };
   10.16 +		1521CEFB225C9AEF00FD2AA2 /* CommitAccept.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEEE225C9AEE00FD2AA2 /* CommitAccept.h */; };
   10.17 +		1521CEFD225C9AEF00FD2AA2 /* pdu_collection.c in Sources */ = {isa = PBXBuildFile; fileRef = 1521CEF0225C9AEE00FD2AA2 /* pdu_collection.c */; };
   10.18 +		1521CEFE225C9AEF00FD2AA2 /* KeySync.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF1225C9AEE00FD2AA2 /* KeySync.h */; };
   10.19 +		1521CEFF225C9AEF00FD2AA2 /* CommitReject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF2225C9AEE00FD2AA2 /* CommitReject.h */; };
   10.20 +		1521CF00225C9AEF00FD2AA2 /* Sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF3225C9AEE00FD2AA2 /* Sync.h */; };
   10.21 +		1521CF01225C9AEF00FD2AA2 /* TID.h in Headers */ = {isa = PBXBuildFile; fileRef = 1521CEF5225C9AEF00FD2AA2 /* TID.h */; };
   10.22  		430BCC482015EE800077E998 /* pEp_string.h in Headers */ = {isa = PBXBuildFile; fileRef = 430BCC462015EE800077E998 /* pEp_string.h */; };
   10.23  		430BCC492015EE800077E998 /* pEp_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 430BCC472015EE800077E998 /* pEp_string.c */; };
   10.24  		430D258B1C9ED75A00B94535 /* blacklist.c in Sources */ = {isa = PBXBuildFile; fileRef = 430D258A1C9ED75A00B94535 /* blacklist.c */; };
   10.25 +		431F048C2273223600CCE960 /* CommitAcceptSecond.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04862273223600CCE960 /* CommitAcceptSecond.h */; };
   10.26 +		431F048D2273223600CCE960 /* CommitAcceptSecond.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F048B2273223600CCE960 /* CommitAcceptSecond.c */; };
   10.27 +		431F04902273227900CCE960 /* OwnKeysFirst.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F048E2273227900CCE960 /* OwnKeysFirst.h */; };
   10.28 +		431F04912273227900CCE960 /* OwnKeysFirst.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F048F2273227900CCE960 /* OwnKeysFirst.c */; };
   10.29 +		431F0494227322EF00CCE960 /* CommitAcceptFirst.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F0492227322EF00CCE960 /* CommitAcceptFirst.h */; };
   10.30 +		431F0495227322EF00CCE960 /* CommitAcceptFirst.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F0493227322EF00CCE960 /* CommitAcceptFirst.c */; };
   10.31 +		431F04A22273235300CCE960 /* GroupTrustThisKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F049C2273235300CCE960 /* GroupTrustThisKey.h */; };
   10.32 +		431F04A32273235300CCE960 /* GroupTrustThisKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F04A12273235300CCE960 /* GroupTrustThisKey.c */; };
   10.33 +		431F04A6227323A400CCE960 /* OwnKeysSecond.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04A4227323A400CCE960 /* OwnKeysSecond.h */; };
   10.34 +		431F04A7227323A400CCE960 /* OwnKeysSecond.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F04A5227323A400CCE960 /* OwnKeysSecond.c */; };
   10.35 +		431F04AA227323EE00CCE960 /* OwnKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04A8227323EE00CCE960 /* OwnKeys.h */; };
   10.36 +		431F04AB227323EE00CCE960 /* OwnKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 431F04A9227323EE00CCE960 /* OwnKeys.c */; };
   10.37 +		431F04B722733A7E00CCE960 /* key_reset.h in Headers */ = {isa = PBXBuildFile; fileRef = 431F04B222733A7E00CCE960 /* key_reset.h */; };
   10.38  		43370833203C075A004E6547 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 4337082D203C075A004E6547 /* sqlite3.c */; };
   10.39  		43370834203C075A004E6547 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = 43370832203C075A004E6547 /* sqlite3.h */; };
   10.40  		4354FF651D6EDF300033069C /* sync_impl.c in Sources */ = {isa = PBXBuildFile; fileRef = 4354FF641D6EDF300033069C /* sync_impl.c */; };
   10.41 -		4354FF691D6EE1A70033069C /* NULL.c in Sources */ = {isa = PBXBuildFile; fileRef = 4354FF681D6EE1A70033069C /* NULL.c */; };
   10.42 +		438C439B2167582500C7425B /* sync_api.h in Headers */ = {isa = PBXBuildFile; fileRef = 438C43962167582400C7425B /* sync_api.h */; };
   10.43  		438C43B52167752C00C7425B /* labeled_int_list.h in Headers */ = {isa = PBXBuildFile; fileRef = 438C43AF2167752C00C7425B /* labeled_int_list.h */; };
   10.44  		438C43B62167752C00C7425B /* labeled_int_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 438C43B42167752C00C7425B /* labeled_int_list.c */; };
   10.45 -		43BA0F461D7964750059172F /* asn1_helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 43BA0F451D7964750059172F /* asn1_helper.c */; };
   10.46 -		43E9BC6A1DB51A1E00AD2352 /* GroupUpdate.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E9BC691DB51A1E00AD2352 /* GroupUpdate.c */; };
   10.47 -		43E9BC7F1DB6720E00AD2352 /* UpdateRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E9BC7E1DB6720E00AD2352 /* UpdateRequest.c */; };
   10.48 +		43CC349E2276D31A002F77AF /* NegotiationRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CC349C2276D31A002F77AF /* NegotiationRequest.c */; };
   10.49 +		43CC349F2276D31A002F77AF /* NegotiationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CC349D2276D31A002F77AF /* NegotiationRequest.h */; };
   10.50 +		43CC34A22276D34C002F77AF /* NegotiationOpen.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CC34A02276D34B002F77AF /* NegotiationOpen.c */; };
   10.51 +		43CC34A32276D34C002F77AF /* NegotiationOpen.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CC34A12276D34C002F77AF /* NegotiationOpen.h */; };
   10.52  		43F6921D1F164A47009418F5 /* resource_id.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F6921C1F164A47009418F5 /* resource_id.c */; };
   10.53 +		43F73BF02166269200AB4524 /* PString.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BEB2166269200AB4524 /* PString.c */; };
   10.54 +		43F73BF2216626E100AB4524 /* Sync_func.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF1216626E100AB4524 /* Sync_func.c */; };
   10.55 +		43F73BFC216627CC00AB4524 /* CommitAccept.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF5216627CB00AB4524 /* CommitAccept.c */; };
   10.56 +		43F73BFD216627CC00AB4524 /* TID.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF6216627CC00AB4524 /* TID.c */; };
   10.57 +		43F73BFE216627CC00AB4524 /* KeySync.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF7216627CC00AB4524 /* KeySync.c */; };
   10.58 +		43F73C00216627CC00AB4524 /* Rollback.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BF9216627CC00AB4524 /* Rollback.c */; };
   10.59 +		43F73C02216627CC00AB4524 /* CommitReject.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73BFB216627CC00AB4524 /* CommitReject.c */; };
   10.60 +		43F73C0B2166282C00AB4524 /* openpgp_compat.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C032166282C00AB4524 /* openpgp_compat.c */; };
   10.61 +		43F73C0C2166282C00AB4524 /* Sync_event.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C042166282C00AB4524 /* Sync_event.c */; };
   10.62 +		43F73C0D2166282C00AB4524 /* key_reset.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C052166282C00AB4524 /* key_reset.c */; };
   10.63 +		43F73C0E2166282C00AB4524 /* sync_codec.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C062166282C00AB4524 /* sync_codec.c */; };
   10.64 +		43F73C0F2166282C00AB4524 /* KeySync_fsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C072166282C00AB4524 /* KeySync_fsm.c */; };
   10.65 +		43F73C112166282C00AB4524 /* sync_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C092166282C00AB4524 /* sync_api.c */; };
   10.66 +		43F73C122166282C00AB4524 /* growing_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C0A2166282C00AB4524 /* growing_buf.c */; };
   10.67 +		43F73C14216628CA00AB4524 /* Sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F73C13216628CA00AB4524 /* Sync.c */; };
   10.68  		6400FB861B8CA1C6005221E3 /* libnetpgp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 645922521B8BD32B00A5AF93 /* libnetpgp.a */; };
   10.69  		6400FB8B1B8CA1CF005221E3 /* libetpan-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64289E371B8B630200FC617B /* libetpan-ios.a */; };
   10.70  		644297C51BE11CE0002BC73B /* system.db in Resources */ = {isa = PBXBuildFile; fileRef = 64951A1B1BE0FCD800B10E71 /* system.db */; };
   10.71 @@ -61,12 +100,8 @@
   10.72  		646C410B1D510CD800C63EFF /* constraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40B61D510CD700C63EFF /* constraints.h */; };
   10.73  		646C410C1D510CD800C63EFF /* der_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40B71D510CD700C63EFF /* der_encoder.c */; };
   10.74  		646C410D1D510CD800C63EFF /* der_encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40B81D510CD700C63EFF /* der_encoder.h */; };
   10.75 -		646C410E1D510CD800C63EFF /* DeviceGroup-Protocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40B91D510CD700C63EFF /* DeviceGroup-Protocol.c */; };
   10.76 -		646C410F1D510CD800C63EFF /* DeviceGroup-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40BA1D510CD700C63EFF /* DeviceGroup-Protocol.h */; };
   10.77  		646C41101D510CD800C63EFF /* GroupKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40BB1D510CD700C63EFF /* GroupKeys.c */; };
   10.78  		646C41111D510CD800C63EFF /* GroupKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40BC1D510CD700C63EFF /* GroupKeys.h */; };
   10.79 -		646C41121D510CD800C63EFF /* HandshakeRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40BD1D510CD700C63EFF /* HandshakeRequest.c */; };
   10.80 -		646C41131D510CD800C63EFF /* HandshakeRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40BE1D510CD700C63EFF /* HandshakeRequest.h */; };
   10.81  		646C41141D510CD800C63EFF /* Hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40BF1D510CD700C63EFF /* Hash.c */; };
   10.82  		646C41151D510CD800C63EFF /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40C01D510CD700C63EFF /* Hash.h */; };
   10.83  		646C41181D510CD800C63EFF /* Hex.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40C31D510CD700C63EFF /* Hex.c */; };
   10.84 @@ -95,8 +130,6 @@
   10.85  		646C412F1D510CD800C63EFF /* per_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40DA1D510CD800C63EFF /* per_support.h */; };
   10.86  		646C41301D510CD800C63EFF /* PrintableString.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40DB1D510CD800C63EFF /* PrintableString.c */; };
   10.87  		646C41311D510CD800C63EFF /* PrintableString.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40DC1D510CD800C63EFF /* PrintableString.h */; };
   10.88 -		646C41321D510CD800C63EFF /* Sync-Protocols.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40DE1D510CD800C63EFF /* Sync-Protocols.c */; };
   10.89 -		646C41331D510CD800C63EFF /* Sync-Protocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40DF1D510CD800C63EFF /* Sync-Protocols.h */; };
   10.90  		646C41341D510CD800C63EFF /* UTF8String.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E01D510CD800C63EFF /* UTF8String.c */; };
   10.91  		646C41351D510CD800C63EFF /* UTF8String.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40E11D510CD800C63EFF /* UTF8String.h */; };
   10.92  		646C41361D510CD800C63EFF /* Version.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E21D510CD800C63EFF /* Version.c */; };
   10.93 @@ -108,12 +141,6 @@
   10.94  		646C413C1D510CD800C63EFF /* xer_support.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C40E81D510CD800C63EFF /* xer_support.c */; };
   10.95  		646C413D1D510CD800C63EFF /* xer_support.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C40E91D510CD800C63EFF /* xer_support.h */; };
   10.96  		646C41451D510D2C00C63EFF /* sync_actions.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C413E1D510D2C00C63EFF /* sync_actions.c */; };
   10.97 -		646C41461D510D2C00C63EFF /* sync_driver.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C413F1D510D2C00C63EFF /* sync_driver.c */; };
   10.98 -		646C41471D510D2C00C63EFF /* sync_fsm.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C41401D510D2C00C63EFF /* sync_fsm.c */; };
   10.99 -		646C41481D510D2C00C63EFF /* sync_fsm.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C41411D510D2C00C63EFF /* sync_fsm.h */; };
  10.100 -		646C41491D510D2C00C63EFF /* sync_send_actions.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C41421D510D2C00C63EFF /* sync_send_actions.c */; };
  10.101 -		646C414A1D510D2C00C63EFF /* sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C41431D510D2C00C63EFF /* sync.c */; };
  10.102 -		646C414B1D510D2C00C63EFF /* sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C41441D510D2C00C63EFF /* sync.h */; };
  10.103  		646C414E1D510D8800C63EFF /* baseprotocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 646C414C1D510D8800C63EFF /* baseprotocol.c */; };
  10.104  		646C414F1D510D8800C63EFF /* baseprotocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 646C414D1D510D8800C63EFF /* baseprotocol.h */; };
  10.105  		649DE08B1B45C19100912F72 /* libcurl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649DE08A1B45C19100912F72 /* libcurl.a */; };
  10.106 @@ -140,6 +167,13 @@
  10.107  /* End PBXBuildFile section */
  10.108  
  10.109  /* Begin PBXContainerItemProxy section */
  10.110 +		43D47AA0225CC82400E97C5B /* PBXContainerItemProxy */ = {
  10.111 +			isa = PBXContainerItemProxy;
  10.112 +			containerPortal = 64796A371B455AA5004B1C24 /* Project object */;
  10.113 +			proxyType = 1;
  10.114 +			remoteGlobalIDString = 644297BE1BE11C65002BC73B;
  10.115 +			remoteInfo = pEpTrustWords;
  10.116 +		};
  10.117  		64289E321B8B630200FC617B /* PBXContainerItemProxy */ = {
  10.118  			isa = PBXContainerItemProxy;
  10.119  			containerPortal = 64DA24121B832EBA000BEE80 /* libetpan.xcodeproj */;
  10.120 @@ -197,20 +231,60 @@
  10.121  /* End PBXCopyFilesBuildPhase section */
  10.122  
  10.123  /* Begin PBXFileReference section */
  10.124 +		1521CEE9225C9AED00FD2AA2 /* CommitAcceptForGroup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptForGroup.c; path = ../asn.1/CommitAcceptForGroup.c; sourceTree = "<group>"; };
  10.125 +		1521CEEA225C9AEE00FD2AA2 /* PString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PString.h; path = ../asn.1/PString.h; sourceTree = "<group>"; };
  10.126 +		1521CEEB225C9AEE00FD2AA2 /* Rollback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Rollback.h; path = ../asn.1/Rollback.h; sourceTree = "<group>"; };
  10.127 +		1521CEEC225C9AEE00FD2AA2 /* CommitAcceptForGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptForGroup.h; path = ../asn.1/CommitAcceptForGroup.h; sourceTree = "<group>"; };
  10.128 +		1521CEEE225C9AEE00FD2AA2 /* CommitAccept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAccept.h; path = ../asn.1/CommitAccept.h; sourceTree = "<group>"; };
  10.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>"; };
  10.130 +		1521CEF1225C9AEE00FD2AA2 /* KeySync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeySync.h; path = ../asn.1/KeySync.h; sourceTree = "<group>"; };
  10.131 +		1521CEF2225C9AEE00FD2AA2 /* CommitReject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitReject.h; path = ../asn.1/CommitReject.h; sourceTree = "<group>"; };
  10.132 +		1521CEF3225C9AEE00FD2AA2 /* Sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sync.h; path = ../asn.1/Sync.h; sourceTree = "<group>"; };
  10.133 +		1521CEF4225C9AEE00FD2AA2 /* sync.asn1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = sync.asn1; path = ../asn.1/sync.asn1; sourceTree = "<group>"; };
  10.134 +		1521CEF5225C9AEF00FD2AA2 /* TID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TID.h; path = ../asn.1/TID.h; sourceTree = "<group>"; };
  10.135  		430BCC462015EE800077E998 /* pEp_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pEp_string.h; path = ../src/pEp_string.h; sourceTree = "<group>"; };
  10.136  		430BCC472015EE800077E998 /* pEp_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pEp_string.c; path = ../src/pEp_string.c; sourceTree = "<group>"; };
  10.137  		430D258A1C9ED75A00B94535 /* blacklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = blacklist.c; path = ../src/blacklist.c; sourceTree = "<group>"; };
  10.138 +		431F04862273223600CCE960 /* CommitAcceptSecond.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptSecond.h; path = ../asn.1/CommitAcceptSecond.h; sourceTree = "<group>"; };
  10.139 +		431F048B2273223600CCE960 /* CommitAcceptSecond.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptSecond.c; path = ../asn.1/CommitAcceptSecond.c; sourceTree = "<group>"; };
  10.140 +		431F048E2273227900CCE960 /* OwnKeysFirst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeysFirst.h; path = ../asn.1/OwnKeysFirst.h; sourceTree = "<group>"; };
  10.141 +		431F048F2273227900CCE960 /* OwnKeysFirst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeysFirst.c; path = ../asn.1/OwnKeysFirst.c; sourceTree = "<group>"; };
  10.142 +		431F0492227322EF00CCE960 /* CommitAcceptFirst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommitAcceptFirst.h; path = ../asn.1/CommitAcceptFirst.h; sourceTree = "<group>"; };
  10.143 +		431F0493227322EF00CCE960 /* CommitAcceptFirst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAcceptFirst.c; path = ../asn.1/CommitAcceptFirst.c; sourceTree = "<group>"; };
  10.144 +		431F049C2273235300CCE960 /* GroupTrustThisKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupTrustThisKey.h; path = ../asn.1/GroupTrustThisKey.h; sourceTree = "<group>"; };
  10.145 +		431F04A12273235300CCE960 /* GroupTrustThisKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupTrustThisKey.c; path = ../asn.1/GroupTrustThisKey.c; sourceTree = "<group>"; };
  10.146 +		431F04A4227323A400CCE960 /* OwnKeysSecond.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeysSecond.h; path = ../asn.1/OwnKeysSecond.h; sourceTree = "<group>"; };
  10.147 +		431F04A5227323A400CCE960 /* OwnKeysSecond.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeysSecond.c; path = ../asn.1/OwnKeysSecond.c; sourceTree = "<group>"; };
  10.148 +		431F04A8227323EE00CCE960 /* OwnKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OwnKeys.h; path = ../asn.1/OwnKeys.h; sourceTree = "<group>"; };
  10.149 +		431F04A9227323EE00CCE960 /* OwnKeys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OwnKeys.c; path = ../asn.1/OwnKeys.c; sourceTree = "<group>"; };
  10.150 +		431F04B222733A7E00CCE960 /* key_reset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = key_reset.h; path = ../src/key_reset.h; sourceTree = "<group>"; };
  10.151  		4337082D203C075A004E6547 /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sqlite3.c; path = ../src/sqlite3.c; sourceTree = "<group>"; };
  10.152  		43370832203C075A004E6547 /* sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sqlite3.h; path = ../src/sqlite3.h; sourceTree = "<group>"; };
  10.153 -		4346F86A1ECB38E700381CBE /* sync_app.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sync_app.h; path = ../src/sync_app.h; sourceTree = "<group>"; };
  10.154  		4354FF641D6EDF300033069C /* sync_impl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_impl.c; path = ../src/sync_impl.c; sourceTree = "<group>"; };
  10.155 -		4354FF681D6EE1A70033069C /* NULL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NULL.c; path = ../asn.1/NULL.c; sourceTree = "<group>"; };
  10.156 +		438C43962167582400C7425B /* sync_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sync_api.h; path = ../src/sync_api.h; sourceTree = "<group>"; };
  10.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>"; };
  10.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>"; };
  10.159 -		43BA0F451D7964750059172F /* asn1_helper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = asn1_helper.c; path = ../src/asn1_helper.c; sourceTree = "<group>"; };
  10.160 -		43E9BC691DB51A1E00AD2352 /* GroupUpdate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupUpdate.c; path = ../asn.1/GroupUpdate.c; sourceTree = "<group>"; };
  10.161 -		43E9BC7E1DB6720E00AD2352 /* UpdateRequest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = UpdateRequest.c; path = ../asn.1/UpdateRequest.c; sourceTree = "<group>"; };
  10.162 +		43CC349C2276D31A002F77AF /* NegotiationRequest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationRequest.c; path = ../asn.1/NegotiationRequest.c; sourceTree = "<group>"; };
  10.163 +		43CC349D2276D31A002F77AF /* NegotiationRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NegotiationRequest.h; path = ../asn.1/NegotiationRequest.h; sourceTree = "<group>"; };
  10.164 +		43CC34A02276D34B002F77AF /* NegotiationOpen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationOpen.c; path = ../asn.1/NegotiationOpen.c; sourceTree = "<group>"; };
  10.165 +		43CC34A12276D34C002F77AF /* NegotiationOpen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NegotiationOpen.h; path = ../asn.1/NegotiationOpen.h; sourceTree = "<group>"; };
  10.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>"; };
  10.167  		43F6921C1F164A47009418F5 /* resource_id.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = resource_id.c; path = ../src/resource_id.c; sourceTree = "<group>"; };
  10.168 +		43F73BEB2166269200AB4524 /* PString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PString.c; path = ../asn.1/PString.c; sourceTree = "<group>"; };
  10.169 +		43F73BF1216626E100AB4524 /* Sync_func.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_func.c; path = ../src/Sync_func.c; sourceTree = "<group>"; };
  10.170 +		43F73BF5216627CB00AB4524 /* CommitAccept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitAccept.c; path = ../asn.1/CommitAccept.c; sourceTree = "<group>"; };
  10.171 +		43F73BF6216627CC00AB4524 /* TID.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = TID.c; path = ../asn.1/TID.c; sourceTree = "<group>"; };
  10.172 +		43F73BF7216627CC00AB4524 /* KeySync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = KeySync.c; path = ../asn.1/KeySync.c; sourceTree = "<group>"; };
  10.173 +		43F73BF9216627CC00AB4524 /* Rollback.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Rollback.c; path = ../asn.1/Rollback.c; sourceTree = "<group>"; };
  10.174 +		43F73BFB216627CC00AB4524 /* CommitReject.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CommitReject.c; path = ../asn.1/CommitReject.c; sourceTree = "<group>"; };
  10.175 +		43F73C032166282C00AB4524 /* openpgp_compat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = openpgp_compat.c; path = ../src/openpgp_compat.c; sourceTree = "<group>"; };
  10.176 +		43F73C042166282C00AB4524 /* Sync_event.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync_event.c; path = ../src/Sync_event.c; sourceTree = "<group>"; };
  10.177 +		43F73C052166282C00AB4524 /* key_reset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = key_reset.c; path = ../src/key_reset.c; sourceTree = "<group>"; };
  10.178 +		43F73C062166282C00AB4524 /* sync_codec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_codec.c; path = ../src/sync_codec.c; sourceTree = "<group>"; };
  10.179 +		43F73C072166282C00AB4524 /* KeySync_fsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = KeySync_fsm.c; path = ../src/KeySync_fsm.c; sourceTree = "<group>"; };
  10.180 +		43F73C092166282C00AB4524 /* sync_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_api.c; path = ../src/sync_api.c; sourceTree = "<group>"; };
  10.181 +		43F73C0A2166282C00AB4524 /* growing_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = growing_buf.c; path = ../src/growing_buf.c; sourceTree = "<group>"; };
  10.182 +		43F73C13216628CA00AB4524 /* Sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Sync.c; path = ../asn.1/Sync.c; sourceTree = "<group>"; };
  10.183  		644297BF1BE11C65002BC73B /* pEpTrustWords.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = pEpTrustWords.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
  10.184  		644297C11BE11C65002BC73B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
  10.185  		646788871CEB3D120001F54C /* map_asn1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = map_asn1.c; path = ../src/map_asn1.c; sourceTree = "<group>"; };
  10.186 @@ -251,12 +325,8 @@
  10.187  		646C40B61D510CD700C63EFF /* constraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constraints.h; path = ../asn.1/constraints.h; sourceTree = "<group>"; };
  10.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>"; };
  10.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>"; };
  10.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>"; };
  10.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>"; };
  10.192  		646C40BB1D510CD700C63EFF /* GroupKeys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupKeys.c; path = ../asn.1/GroupKeys.c; sourceTree = "<group>"; };
  10.193  		646C40BC1D510CD700C63EFF /* GroupKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GroupKeys.h; path = ../asn.1/GroupKeys.h; sourceTree = "<group>"; };
  10.194 -		646C40BD1D510CD700C63EFF /* HandshakeRequest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HandshakeRequest.c; path = ../asn.1/HandshakeRequest.c; sourceTree = "<group>"; };
  10.195 -		646C40BE1D510CD700C63EFF /* HandshakeRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HandshakeRequest.h; path = ../asn.1/HandshakeRequest.h; sourceTree = "<group>"; };
  10.196  		646C40BF1D510CD700C63EFF /* Hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Hash.c; path = ../asn.1/Hash.c; sourceTree = "<group>"; };
  10.197  		646C40C01D510CD700C63EFF /* Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hash.h; path = ../asn.1/Hash.h; sourceTree = "<group>"; };
  10.198  		646C40C31D510CD700C63EFF /* Hex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Hex.c; path = ../asn.1/Hex.c; sourceTree = "<group>"; };
  10.199 @@ -285,9 +355,6 @@
  10.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>"; };
  10.201  		646C40DB1D510CD800C63EFF /* PrintableString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PrintableString.c; path = ../asn.1/PrintableString.c; sourceTree = "<group>"; };
  10.202  		646C40DC1D510CD800C63EFF /* PrintableString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrintableString.h; path = ../asn.1/PrintableString.h; sourceTree = "<group>"; };
  10.203 -		646C40DD1D510CD800C63EFF /* protocols.asn1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = protocols.asn1; path = ../asn.1/protocols.asn1; sourceTree = "<group>"; };
  10.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>"; };
  10.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>"; };
  10.206  		646C40E01D510CD800C63EFF /* UTF8String.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = UTF8String.c; path = ../asn.1/UTF8String.c; sourceTree = "<group>"; };
  10.207  		646C40E11D510CD800C63EFF /* UTF8String.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UTF8String.h; path = ../asn.1/UTF8String.h; sourceTree = "<group>"; };
  10.208  		646C40E21D510CD800C63EFF /* Version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Version.c; path = ../asn.1/Version.c; sourceTree = "<group>"; };
  10.209 @@ -299,12 +366,6 @@
  10.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>"; };
  10.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>"; };
  10.212  		646C413E1D510D2C00C63EFF /* sync_actions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_actions.c; path = ../src/sync_actions.c; sourceTree = "<group>"; };
  10.213 -		646C413F1D510D2C00C63EFF /* sync_driver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_driver.c; path = ../src/sync_driver.c; sourceTree = "<group>"; };
  10.214 -		646C41401D510D2C00C63EFF /* sync_fsm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync_fsm.c; path = ../src/sync_fsm.c; sourceTree = "<group>"; };
  10.215 -		646C41411D510D2C00C63EFF /* sync_fsm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sync_fsm.h; path = ../src/sync_fsm.h; sourceTree = "<group>"; };
  10.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>"; };
  10.217 -		646C41431D510D2C00C63EFF /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sync.c; path = ../src/sync.c; sourceTree = "<group>"; };
  10.218 -		646C41441D510D2C00C63EFF /* sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sync.h; path = ../src/sync.h; sourceTree = "<group>"; };
  10.219  		646C414C1D510D8800C63EFF /* baseprotocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = baseprotocol.c; path = ../src/baseprotocol.c; sourceTree = "<group>"; };
  10.220  		646C414D1D510D8800C63EFF /* baseprotocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = baseprotocol.h; path = ../src/baseprotocol.h; sourceTree = "<group>"; };
  10.221  		64796A3F1B455AA5004B1C24 /* libpEpEngine.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpEpEngine.a; sourceTree = BUILT_PRODUCTS_DIR; };
  10.222 @@ -377,12 +438,50 @@
  10.223  /* End PBXFrameworksBuildPhase section */
  10.224  
  10.225  /* Begin PBXGroup section */
  10.226 +		43D47A89225CC60600E97C5B /* Resources-iPad */ = {
  10.227 +			isa = PBXGroup;
  10.228 +			children = (
  10.229 +			);
  10.230 +			name = "Resources-iPad";
  10.231 +			sourceTree = "<group>";
  10.232 +		};
  10.233  		6406CE811CE382F400C14D77 /* asn.1 */ = {
  10.234  			isa = PBXGroup;
  10.235  			children = (
  10.236 -				43E9BC7E1DB6720E00AD2352 /* UpdateRequest.c */,
  10.237 -				43E9BC691DB51A1E00AD2352 /* GroupUpdate.c */,
  10.238 -				4354FF681D6EE1A70033069C /* NULL.c */,
  10.239 +				43CC34A02276D34B002F77AF /* NegotiationOpen.c */,
  10.240 +				43CC34A12276D34C002F77AF /* NegotiationOpen.h */,
  10.241 +				43CC349C2276D31A002F77AF /* NegotiationRequest.c */,
  10.242 +				43CC349D2276D31A002F77AF /* NegotiationRequest.h */,
  10.243 +				431F04A12273235300CCE960 /* GroupTrustThisKey.c */,
  10.244 +				431F049C2273235300CCE960 /* GroupTrustThisKey.h */,
  10.245 +				431F04A9227323EE00CCE960 /* OwnKeys.c */,
  10.246 +				431F04A8227323EE00CCE960 /* OwnKeys.h */,
  10.247 +				431F048F2273227900CCE960 /* OwnKeysFirst.c */,
  10.248 +				431F048E2273227900CCE960 /* OwnKeysFirst.h */,
  10.249 +				431F04A5227323A400CCE960 /* OwnKeysSecond.c */,
  10.250 +				431F04A4227323A400CCE960 /* OwnKeysSecond.h */,
  10.251 +				431F0493227322EF00CCE960 /* CommitAcceptFirst.c */,
  10.252 +				431F0492227322EF00CCE960 /* CommitAcceptFirst.h */,
  10.253 +				431F048B2273223600CCE960 /* CommitAcceptSecond.c */,
  10.254 +				431F04862273223600CCE960 /* CommitAcceptSecond.h */,
  10.255 +				1521CEEE225C9AEE00FD2AA2 /* CommitAccept.h */,
  10.256 +				1521CEE9225C9AED00FD2AA2 /* CommitAcceptForGroup.c */,
  10.257 +				1521CEEC225C9AEE00FD2AA2 /* CommitAcceptForGroup.h */,
  10.258 +				1521CEF2225C9AEE00FD2AA2 /* CommitReject.h */,
  10.259 +				1521CEF1225C9AEE00FD2AA2 /* KeySync.h */,
  10.260 +				1521CEF0225C9AEE00FD2AA2 /* pdu_collection.c */,
  10.261 +				1521CEEA225C9AEE00FD2AA2 /* PString.h */,
  10.262 +				1521CEEB225C9AEE00FD2AA2 /* Rollback.h */,
  10.263 +				1521CEF4225C9AEE00FD2AA2 /* sync.asn1 */,
  10.264 +				1521CEF3225C9AEE00FD2AA2 /* Sync.h */,
  10.265 +				1521CEF5225C9AEF00FD2AA2 /* TID.h */,
  10.266 +				43F73C13216628CA00AB4524 /* Sync.c */,
  10.267 +				43F73BF5216627CB00AB4524 /* CommitAccept.c */,
  10.268 +				43F73BFB216627CC00AB4524 /* CommitReject.c */,
  10.269 +				43F73BF7216627CC00AB4524 /* KeySync.c */,
  10.270 +				43F73BF9216627CC00AB4524 /* Rollback.c */,
  10.271 +				43F73BF6216627CC00AB4524 /* TID.c */,
  10.272 +				43F73BEB2166269200AB4524 /* PString.c */,
  10.273  				646C40951D510CD700C63EFF /* asn_application.h */,
  10.274  				646C40961D510CD700C63EFF /* asn_codecs_prim.c */,
  10.275  				646C40971D510CD700C63EFF /* asn_codecs_prim.h */,
  10.276 @@ -419,12 +518,8 @@
  10.277  				646C40B61D510CD700C63EFF /* constraints.h */,
  10.278  				646C40B71D510CD700C63EFF /* der_encoder.c */,
  10.279  				646C40B81D510CD700C63EFF /* der_encoder.h */,
  10.280 -				646C40B91D510CD700C63EFF /* DeviceGroup-Protocol.c */,
  10.281 -				646C40BA1D510CD700C63EFF /* DeviceGroup-Protocol.h */,
  10.282  				646C40BB1D510CD700C63EFF /* GroupKeys.c */,
  10.283  				646C40BC1D510CD700C63EFF /* GroupKeys.h */,
  10.284 -				646C40BD1D510CD700C63EFF /* HandshakeRequest.c */,
  10.285 -				646C40BE1D510CD700C63EFF /* HandshakeRequest.h */,
  10.286  				646C40BF1D510CD700C63EFF /* Hash.c */,
  10.287  				646C40C01D510CD700C63EFF /* Hash.h */,
  10.288  				646C40C31D510CD700C63EFF /* Hex.c */,
  10.289 @@ -453,9 +548,6 @@
  10.290  				646C40DA1D510CD800C63EFF /* per_support.h */,
  10.291  				646C40DB1D510CD800C63EFF /* PrintableString.c */,
  10.292  				646C40DC1D510CD800C63EFF /* PrintableString.h */,
  10.293 -				646C40DD1D510CD800C63EFF /* protocols.asn1 */,
  10.294 -				646C40DE1D510CD800C63EFF /* Sync-Protocols.c */,
  10.295 -				646C40DF1D510CD800C63EFF /* Sync-Protocols.h */,
  10.296  				646C40E01D510CD800C63EFF /* UTF8String.c */,
  10.297  				646C40E11D510CD800C63EFF /* UTF8String.h */,
  10.298  				646C40E21D510CD800C63EFF /* Version.c */,
  10.299 @@ -499,6 +591,7 @@
  10.300  		64796A361B455AA5004B1C24 = {
  10.301  			isa = PBXGroup;
  10.302  			children = (
  10.303 +				43D47A89225CC60600E97C5B /* Resources-iPad */,
  10.304  				64951A1B1BE0FCD800B10E71 /* system.db */,
  10.305  				64DA24121B832EBA000BEE80 /* libetpan.xcodeproj */,
  10.306  				64DA240C1B832EA0000BEE80 /* netpgp.xcodeproj */,
  10.307 @@ -507,6 +600,7 @@
  10.308  				64A8264B1B455C5600EECAF0 /* srcref */,
  10.309  				644297C01BE11C65002BC73B /* pEpTrustWords */,
  10.310  				64796A401B455AA5004B1C24 /* Products */,
  10.311 +				43D47A8A225CC60600E97C5B /* pEpTrustWords-Info.plist */,
  10.312  			);
  10.313  			sourceTree = "<group>";
  10.314  		};
  10.315 @@ -526,23 +620,25 @@
  10.316  				C46EBAEC216E445F0042A6A3 /* base64.h */,
  10.317  				438C43B42167752C00C7425B /* labeled_int_list.c */,
  10.318  				438C43AF2167752C00C7425B /* labeled_int_list.h */,
  10.319 +				438C43962167582400C7425B /* sync_api.h */,
  10.320 +				43F73C0A2166282C00AB4524 /* growing_buf.c */,
  10.321 +				431F04B222733A7E00CCE960 /* key_reset.h */,
  10.322 +				43F73C052166282C00AB4524 /* key_reset.c */,
  10.323 +				43F73C072166282C00AB4524 /* KeySync_fsm.c */,
  10.324 +				43F73C032166282C00AB4524 /* openpgp_compat.c */,
  10.325 +				43F73C092166282C00AB4524 /* sync_api.c */,
  10.326 +				43F73C062166282C00AB4524 /* sync_codec.c */,
  10.327 +				43F73C042166282C00AB4524 /* Sync_event.c */,
  10.328 +				43F73BF1216626E100AB4524 /* Sync_func.c */,
  10.329  				4337082D203C075A004E6547 /* sqlite3.c */,
  10.330  				43370832203C075A004E6547 /* sqlite3.h */,
  10.331  				430BCC472015EE800077E998 /* pEp_string.c */,
  10.332  				430BCC462015EE800077E998 /* pEp_string.h */,
  10.333  				43F6921C1F164A47009418F5 /* resource_id.c */,
  10.334 -				43BA0F451D7964750059172F /* asn1_helper.c */,
  10.335  				4354FF641D6EDF300033069C /* sync_impl.c */,
  10.336  				646C414C1D510D8800C63EFF /* baseprotocol.c */,
  10.337  				646C414D1D510D8800C63EFF /* baseprotocol.h */,
  10.338  				646C413E1D510D2C00C63EFF /* sync_actions.c */,
  10.339 -				646C413F1D510D2C00C63EFF /* sync_driver.c */,
  10.340 -				646C41401D510D2C00C63EFF /* sync_fsm.c */,
  10.341 -				646C41411D510D2C00C63EFF /* sync_fsm.h */,
  10.342 -				646C41421D510D2C00C63EFF /* sync_send_actions.c */,
  10.343 -				646C41431D510D2C00C63EFF /* sync.c */,
  10.344 -				646C41441D510D2C00C63EFF /* sync.h */,
  10.345 -				4346F86A1ECB38E700381CBE /* sync_app.h */,
  10.346  				646788871CEB3D120001F54C /* map_asn1.c */,
  10.347  				646788881CEB3D120001F54C /* map_asn1.h */,
  10.348  				430D258A1C9ED75A00B94535 /* blacklist.c */,
  10.349 @@ -598,29 +694,36 @@
  10.350  			buildActionMask = 2147483647;
  10.351  			files = (
  10.352  				646C41031D510CD800C63EFF /* constr_SEQUENCE_OF.h in Headers */,
  10.353 +				1521CEFB225C9AEF00FD2AA2 /* CommitAccept.h in Headers */,
  10.354  				646C40ED1D510CD800C63EFF /* asn_codecs.h in Headers */,
  10.355  				646C41371D510CD800C63EFF /* Version.h in Headers */,
  10.356 +				1521CEF8225C9AEF00FD2AA2 /* Rollback.h in Headers */,
  10.357  				646C412F1D510CD800C63EFF /* per_support.h in Headers */,
  10.358  				646C41111D510CD800C63EFF /* GroupKeys.h in Headers */,
  10.359  				646C40F21D510CD800C63EFF /* asn_SET_OF.h in Headers */,
  10.360  				646C41311D510CD800C63EFF /* PrintableString.h in Headers */,
  10.361 +				431F048C2273223600CCE960 /* CommitAcceptSecond.h in Headers */,
  10.362  				646C40F51D510CD800C63EFF /* Beacon.h in Headers */,
  10.363  				438C43B52167752C00C7425B /* labeled_int_list.h in Headers */,
  10.364  				646C40F71D510CD800C63EFF /* ber_decoder.h in Headers */,
  10.365  				646C41351D510CD800C63EFF /* UTF8String.h in Headers */,
  10.366 +				43CC34A32276D34C002F77AF /* NegotiationOpen.h in Headers */,
  10.367  				646C40EC1D510CD800C63EFF /* asn_codecs_prim.h in Headers */,
  10.368 +				438C439B2167582500C7425B /* sync_api.h in Headers */,
  10.369  				646C40EE1D510CD800C63EFF /* asn_internal.h in Headers */,
  10.370  				646C413B1D510CD800C63EFF /* xer_encoder.h in Headers */,
  10.371 +				431F04A6227323A400CCE960 /* OwnKeysSecond.h in Headers */,
  10.372  				646C40F01D510CD800C63EFF /* asn_SEQUENCE_OF.h in Headers */,
  10.373 +				43CC349F2276D31A002F77AF /* NegotiationRequest.h in Headers */,
  10.374  				646C40FD1D510CD800C63EFF /* BIT_STRING.h in Headers */,
  10.375  				646C411F1D510CD800C63EFF /* INTEGER.h in Headers */,
  10.376  				646C411D1D510CD800C63EFF /* IdentityList.h in Headers */,
  10.377 -				646C41331D510CD800C63EFF /* Sync-Protocols.h in Headers */,
  10.378 +				1521CEFE225C9AEF00FD2AA2 /* KeySync.h in Headers */,
  10.379  				646C41011D510CD800C63EFF /* constr_CHOICE.h in Headers */,
  10.380  				646C40FB1D510CD800C63EFF /* ber_tlv_tag.h in Headers */,
  10.381  				646C414F1D510D8800C63EFF /* baseprotocol.h in Headers */,
  10.382  				6467888D1CEB3D120001F54C /* map_asn1.h in Headers */,
  10.383 -				646C41131D510CD800C63EFF /* HandshakeRequest.h in Headers */,
  10.384 +				1521CEF9225C9AEF00FD2AA2 /* CommitAcceptForGroup.h in Headers */,
  10.385  				646C40F31D510CD800C63EFF /* asn_system.h in Headers */,
  10.386  				43370834203C075A004E6547 /* sqlite3.h in Headers */,
  10.387  				646C410B1D510CD800C63EFF /* constraints.h in Headers */,
  10.388 @@ -629,26 +732,32 @@
  10.389  				646C41391D510CD800C63EFF /* xer_decoder.h in Headers */,
  10.390  				646C40EA1D510CD800C63EFF /* asn_application.h in Headers */,
  10.391  				646C41211D510CD800C63EFF /* ISO639-1.h in Headers */,
  10.392 +				431F04B722733A7E00CCE960 /* key_reset.h in Headers */,
  10.393  				646C412D1D510CD800C63EFF /* per_opentype.h in Headers */,
  10.394  				646C413D1D510CD800C63EFF /* xer_support.h in Headers */,
  10.395  				646C41191D510CD800C63EFF /* Hex.h in Headers */,
  10.396 +				431F04902273227900CCE960 /* OwnKeysFirst.h in Headers */,
  10.397  				646C41051D510CD800C63EFF /* constr_SEQUENCE.h in Headers */,
  10.398 +				1521CF01225C9AEF00FD2AA2 /* TID.h in Headers */,
  10.399  				646C41151D510CD800C63EFF /* Hash.h in Headers */,
  10.400 -				646C410F1D510CD800C63EFF /* DeviceGroup-Protocol.h in Headers */,
  10.401  				646C40FF1D510CD800C63EFF /* BOOLEAN.h in Headers */,
  10.402 -				646C41481D510D2C00C63EFF /* sync_fsm.h in Headers */,
  10.403  				64A8268C1B455D9D00EECAF0 /* pEpEngine.h in Headers */,
  10.404 +				431F04AA227323EE00CCE960 /* OwnKeys.h in Headers */,
  10.405  				646C41091D510CD800C63EFF /* constr_TYPE.h in Headers */,
  10.406 +				431F0494227322EF00CCE960 /* CommitAcceptFirst.h in Headers */,
  10.407  				430BCC482015EE800077E998 /* pEp_string.h in Headers */,
  10.408 +				1521CEFF225C9AEF00FD2AA2 /* CommitReject.h in Headers */,
  10.409  				646C410D1D510CD800C63EFF /* der_encoder.h in Headers */,
  10.410  				646C41231D510CD800C63EFF /* NativeEnumerated.h in Headers */,
  10.411  				646C41071D510CD800C63EFF /* constr_SET_OF.h in Headers */,
  10.412 -				646C414B1D510D2C00C63EFF /* sync.h in Headers */,
  10.413 +				1521CEF7225C9AEF00FD2AA2 /* PString.h in Headers */,
  10.414 +				1521CF00225C9AEF00FD2AA2 /* Sync.h in Headers */,
  10.415  				C46EBAEE216E445F0042A6A3 /* base64.h in Headers */,
  10.416  				646C411B1D510CD800C63EFF /* Identity.h in Headers */,
  10.417  				646C412B1D510CD800C63EFF /* per_encoder.h in Headers */,
  10.418  				646C40F91D510CD800C63EFF /* ber_tlv_length.h in Headers */,
  10.419  				646C41291D510CD800C63EFF /* per_decoder.h in Headers */,
  10.420 +				431F04A22273235300CCE960 /* GroupTrustThisKey.h in Headers */,
  10.421  			);
  10.422  			runOnlyForDeploymentPostprocessing = 0;
  10.423  		};
  10.424 @@ -677,7 +786,7 @@
  10.425  			isa = PBXNativeTarget;
  10.426  			buildConfigurationList = 64796A531B455AA5004B1C24 /* Build configuration list for PBXNativeTarget "pEpEngine" */;
  10.427  			buildPhases = (
  10.428 -				64BDD59B1B7A2E1B00AC43AE /* Run Script */,
  10.429 +				43D47B08225DEBD600E97C5B /* ShellScript */,
  10.430  				64796A3B1B455AA5004B1C24 /* Sources */,
  10.431  				64796A3C1B455AA5004B1C24 /* Frameworks */,
  10.432  				64796A3D1B455AA5004B1C24 /* CopyFiles */,
  10.433 @@ -686,6 +795,7 @@
  10.434  			buildRules = (
  10.435  			);
  10.436  			dependencies = (
  10.437 +				43D47AA1225CC82400E97C5B /* PBXTargetDependency */,
  10.438  				645922541B8BD53F00A5AF93 /* PBXTargetDependency */,
  10.439  				64289E3F1B8B638800FC617B /* PBXTargetDependency */,
  10.440  			);
  10.441 @@ -701,7 +811,7 @@
  10.442  			isa = PBXProject;
  10.443  			attributes = {
  10.444  				LastUpgradeCheck = 0940;
  10.445 -				ORGANIZATIONNAME = "Edouard Tisserant";
  10.446 +				ORGANIZATIONNAME = "p≡p Security S.A.";
  10.447  				TargetAttributes = {
  10.448  					644297BE1BE11C65002BC73B = {
  10.449  						CreatedOnToolsVersion = 7.1;
  10.450 @@ -716,6 +826,7 @@
  10.451  			developmentRegion = English;
  10.452  			hasScannedForEncodings = 0;
  10.453  			knownRegions = (
  10.454 +				English,
  10.455  				en,
  10.456  			);
  10.457  			mainGroup = 64796A361B455AA5004B1C24;
  10.458 @@ -782,6 +893,25 @@
  10.459  /* End PBXResourcesBuildPhase section */
  10.460  
  10.461  /* Begin PBXShellScriptBuildPhase section */
  10.462 +		43D47B08225DEBD600E97C5B /* ShellScript */ = {
  10.463 +			isa = PBXShellScriptBuildPhase;
  10.464 +			buildActionMask = 2147483647;
  10.465 +			files = (
  10.466 +			);
  10.467 +			inputFileListPaths = (
  10.468 +			);
  10.469 +			inputPaths = (
  10.470 +			);
  10.471 +			outputFileListPaths = (
  10.472 +				"$(SRCROOT)/generated-files-asn1.txt",
  10.473 +				"$(SRCROOT)/generated-files-sync.txt",
  10.474 +			);
  10.475 +			outputPaths = (
  10.476 +			);
  10.477 +			runOnlyForDeploymentPostprocessing = 0;
  10.478 +			shellPath = /bin/bash;
  10.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";
  10.480 +		};
  10.481  		644297C61BE11D00002BC73B /* ShellScript */ = {
  10.482  			isa = PBXShellScriptBuildPhase;
  10.483  			buildActionMask = 2147483647;
  10.484 @@ -793,21 +923,7 @@
  10.485  			);
  10.486  			runOnlyForDeploymentPostprocessing = 0;
  10.487  			shellPath = /bin/sh;
  10.488 -			shellScript = "make -C \"$SRCROOT/../db\" system.db\n";
  10.489 -		};
  10.490 -		64BDD59B1B7A2E1B00AC43AE /* Run Script */ = {
  10.491 -			isa = PBXShellScriptBuildPhase;
  10.492 -			buildActionMask = 2147483647;
  10.493 -			files = (
  10.494 -			);
  10.495 -			inputPaths = (
  10.496 -			);
  10.497 -			name = "Run Script";
  10.498 -			outputPaths = (
  10.499 -			);
  10.500 -			runOnlyForDeploymentPostprocessing = 0;
  10.501 -			shellPath = /bin/sh;
  10.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";
  10.503 +			shellScript = "cd \"$SRCROOT/..\"\n\nbash -l -c \"make db\"\n";
  10.504  		};
  10.505  /* End PBXShellScriptBuildPhase section */
  10.506  
  10.507 @@ -824,10 +940,15 @@
  10.508  			buildActionMask = 2147483647;
  10.509  			files = (
  10.510  				64A826871B455D0800EECAF0 /* stringpair.c in Sources */,
  10.511 -				43E9BC6A1DB51A1E00AD2352 /* GroupUpdate.c in Sources */,
  10.512 +				43F73C0E2166282C00AB4524 /* sync_codec.c in Sources */,
  10.513 +				1521CEF6225C9AEF00FD2AA2 /* CommitAcceptForGroup.c in Sources */,
  10.514 +				431F04912273227900CCE960 /* OwnKeysFirst.c in Sources */,
  10.515 +				431F04A32273235300CCE960 /* GroupTrustThisKey.c in Sources */,
  10.516  				646C41341D510CD800C63EFF /* UTF8String.c in Sources */,
  10.517  				64A826831B455D0800EECAF0 /* platform_unix.c in Sources */,
  10.518  				646C40F81D510CD800C63EFF /* ber_tlv_length.c in Sources */,
  10.519 +				43F73BF2216626E100AB4524 /* Sync_func.c in Sources */,
  10.520 +				431F04A7227323A400CCE960 /* OwnKeysSecond.c in Sources */,
  10.521  				646C411C1D510CD800C63EFF /* IdentityList.c in Sources */,
  10.522  				646C41301D510CD800C63EFF /* PrintableString.c in Sources */,
  10.523  				64A8267B1B455D0800EECAF0 /* etpan_mime.c in Sources */,
  10.524 @@ -835,74 +956,88 @@
  10.525  				438C43B62167752C00C7425B /* labeled_int_list.c in Sources */,
  10.526  				646C41261D510CD800C63EFF /* OCTET_STRING.c in Sources */,
  10.527  				646C41141D510CD800C63EFF /* Hash.c in Sources */,
  10.528 -				646C410E1D510CD800C63EFF /* DeviceGroup-Protocol.c in Sources */,
  10.529 +				43CC349E2276D31A002F77AF /* NegotiationRequest.c in Sources */,
  10.530 +				43F73BF02166269200AB4524 /* PString.c in Sources */,
  10.531  				64A826861B455D0800EECAF0 /* stringlist.c in Sources */,
  10.532  				4354FF651D6EDF300033069C /* sync_impl.c in Sources */,
  10.533  				64A8267E1B455D0800EECAF0 /* message_api.c in Sources */,
  10.534 -				43E9BC7F1DB6720E00AD2352 /* UpdateRequest.c in Sources */,
  10.535  				646C41361D510CD800C63EFF /* Version.c in Sources */,
  10.536  				646C41081D510CD800C63EFF /* constr_TYPE.c in Sources */,
  10.537  				646C40FE1D510CD800C63EFF /* BOOLEAN.c in Sources */,
  10.538  				646C41001D510CD800C63EFF /* constr_CHOICE.c in Sources */,
  10.539 -				646C41121D510CD800C63EFF /* HandshakeRequest.c in Sources */,
  10.540 -				646C41471D510D2C00C63EFF /* sync_fsm.c in Sources */,
  10.541  				64A826821B455D0800EECAF0 /* pgp_netpgp.c in Sources */,
  10.542  				646C41101D510CD800C63EFF /* GroupKeys.c in Sources */,
  10.543  				646C40EF1D510CD800C63EFF /* asn_SEQUENCE_OF.c in Sources */,
  10.544  				64A826891B455D0800EECAF0 /* trans_auto.c in Sources */,
  10.545  				646C410C1D510CD800C63EFF /* der_encoder.c in Sources */,
  10.546 +				43F73C112166282C00AB4524 /* sync_api.c in Sources */,
  10.547  				646C41381D510CD800C63EFF /* xer_decoder.c in Sources */,
  10.548 +				43F73BFE216627CC00AB4524 /* KeySync.c in Sources */,
  10.549  				646C41181D510CD800C63EFF /* Hex.c in Sources */,
  10.550  				64A8267D1B455D0800EECAF0 /* keymanagement.c in Sources */,
  10.551  				646C40EB1D510CD800C63EFF /* asn_codecs_prim.c in Sources */,
  10.552  				646C41451D510D2C00C63EFF /* sync_actions.c in Sources */,
  10.553  				646C40F61D510CD800C63EFF /* ber_decoder.c in Sources */,
  10.554  				646C40F11D510CD800C63EFF /* asn_SET_OF.c in Sources */,
  10.555 -				4354FF691D6EE1A70033069C /* NULL.c in Sources */,
  10.556  				646C413A1D510CD800C63EFF /* xer_encoder.c in Sources */,
  10.557 +				431F04AB227323EE00CCE960 /* OwnKeys.c in Sources */,
  10.558 +				43F73BFD216627CC00AB4524 /* TID.c in Sources */,
  10.559  				646C41021D510CD800C63EFF /* constr_SEQUENCE_OF.c in Sources */,
  10.560  				646C410A1D510CD800C63EFF /* constraints.c in Sources */,
  10.561 -				646C41461D510D2C00C63EFF /* sync_driver.c in Sources */,
  10.562  				64A8267C1B455D0800EECAF0 /* identity_list.c in Sources */,
  10.563  				646C40FC1D510CD800C63EFF /* BIT_STRING.c in Sources */,
  10.564  				646C40F41D510CD800C63EFF /* Beacon.c in Sources */,
  10.565 +				43F73C0D2166282C00AB4524 /* key_reset.c in Sources */,
  10.566 +				43F73BFC216627CC00AB4524 /* CommitAccept.c in Sources */,
  10.567  				646C411E1D510CD800C63EFF /* INTEGER.c in Sources */,
  10.568  				646C413C1D510CD800C63EFF /* xer_support.c in Sources */,
  10.569  				64A8268A1B455D0800EECAF0 /* transport.c in Sources */,
  10.570 -				646C41491D510D2C00C63EFF /* sync_send_actions.c in Sources */,
  10.571  				646C41201D510CD800C63EFF /* ISO639-1.c in Sources */,
  10.572 -				646C414A1D510D2C00C63EFF /* sync.c in Sources */,
  10.573  				64A826791B455D0800EECAF0 /* cryptotech.c in Sources */,
  10.574 -				43BA0F461D7964750059172F /* asn1_helper.c in Sources */,
  10.575 +				43F73C0F2166282C00AB4524 /* KeySync_fsm.c in Sources */,
  10.576  				646C412A1D510CD800C63EFF /* per_encoder.c in Sources */,
  10.577  				646C412E1D510CD800C63EFF /* per_support.c in Sources */,
  10.578 +				43F73C0C2166282C00AB4524 /* Sync_event.c in Sources */,
  10.579  				64A826781B455D0800EECAF0 /* bloblist.c in Sources */,
  10.580  				C46EBAED216E445F0042A6A3 /* base64.c in Sources */,
  10.581  				430BCC492015EE800077E998 /* pEp_string.c in Sources */,
  10.582 +				43F73C00216627CC00AB4524 /* Rollback.c in Sources */,
  10.583  				646C41041D510CD800C63EFF /* constr_SEQUENCE.c in Sources */,
  10.584 +				43F73C14216628CA00AB4524 /* Sync.c in Sources */,
  10.585 +				43F73C0B2166282C00AB4524 /* openpgp_compat.c in Sources */,
  10.586  				43370833203C075A004E6547 /* sqlite3.c in Sources */,
  10.587 +				43F73C02216627CC00AB4524 /* CommitReject.c in Sources */,
  10.588  				64A826881B455D0800EECAF0 /* timestamp.c in Sources */,
  10.589  				646C41221D510CD800C63EFF /* NativeEnumerated.c in Sources */,
  10.590  				43F6921D1F164A47009418F5 /* resource_id.c in Sources */,
  10.591  				430D258B1C9ED75A00B94535 /* blacklist.c in Sources */,
  10.592 +				431F0495227322EF00CCE960 /* CommitAcceptFirst.c in Sources */,
  10.593  				646C414E1D510D8800C63EFF /* baseprotocol.c in Sources */,
  10.594  				6467888C1CEB3D120001F54C /* map_asn1.c in Sources */,
  10.595  				646C40FA1D510CD800C63EFF /* ber_tlv_tag.c in Sources */,
  10.596  				646C41241D510CD800C63EFF /* NativeInteger.c in Sources */,
  10.597 +				1521CEFD225C9AEF00FD2AA2 /* pdu_collection.c in Sources */,
  10.598  				646C41061D510CD800C63EFF /* constr_SET_OF.c in Sources */,
  10.599 +				43F73C122166282C00AB4524 /* growing_buf.c in Sources */,
  10.600  				646C412C1D510CD800C63EFF /* per_opentype.c in Sources */,
  10.601  				646C41281D510CD800C63EFF /* per_decoder.c in Sources */,
  10.602  				64A826801B455D0800EECAF0 /* mime.c in Sources */,
  10.603 +				431F048D2273223600CCE960 /* CommitAcceptSecond.c in Sources */,
  10.604  				64A8267F1B455D0800EECAF0 /* message.c in Sources */,
  10.605 +				43CC34A22276D34C002F77AF /* NegotiationOpen.c in Sources */,
  10.606  				646C411A1D510CD800C63EFF /* Identity.c in Sources */,
  10.607  				64A826811B455D0800EECAF0 /* pEpEngine.c in Sources */,
  10.608 -				646C41321D510CD800C63EFF /* Sync-Protocols.c in Sources */,
  10.609  			);
  10.610  			runOnlyForDeploymentPostprocessing = 0;
  10.611  		};
  10.612  /* End PBXSourcesBuildPhase section */
  10.613  
  10.614  /* Begin PBXTargetDependency section */
  10.615 +		43D47AA1225CC82400E97C5B /* PBXTargetDependency */ = {
  10.616 +			isa = PBXTargetDependency;
  10.617 +			target = 644297BE1BE11C65002BC73B /* pEpTrustWords */;
  10.618 +			targetProxy = 43D47AA0225CC82400E97C5B /* PBXContainerItemProxy */;
  10.619 +		};
  10.620  		64289E3F1B8B638800FC617B /* PBXTargetDependency */ = {
  10.621  			isa = PBXTargetDependency;
  10.622  			name = "libetpan ios";
  10.623 @@ -990,7 +1125,7 @@
  10.624  					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
  10.625  					"$(SRCROOT)/../asn.1/",
  10.626  				);
  10.627 -				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
  10.628 +				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
  10.629  				MTL_ENABLE_DEBUG_INFO = YES;
  10.630  				ONLY_ACTIVE_ARCH = YES;
  10.631  				OTHER_CFLAGS = "-DSQLITE3_FROM_OS";
  10.632 @@ -1047,7 +1182,7 @@
  10.633  					"$(SRCROOT)/../../OpenSSL-for-iPhone/include",
  10.634  					"$(SRCROOT)/../asn.1/",
  10.635  				);
  10.636 -				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
  10.637 +				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
  10.638  				MTL_ENABLE_DEBUG_INFO = NO;
  10.639  				ONLY_ACTIVE_ARCH = NO;
  10.640  				OTHER_CFLAGS = "-DSQLITE3_FROM_OS";
  10.641 @@ -1071,7 +1206,15 @@
  10.642  				OTHER_LDFLAGS = "-ObjC";
  10.643  				PRODUCT_NAME = "$(TARGET_NAME)";
  10.644  				SKIP_INSTALL = YES;
  10.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)";
  10.646 +				USER_HEADER_SEARCH_PATHS = (
  10.647 +					"$(PROJECT_DIR)/../src",
  10.648 +					"$(PROJECT_DIR)",
  10.649 +					"$(PROJECT_DIR)/../../netpgp-et/include/",
  10.650 +					"$(PROJECT_DIR)/../../netpgp-et/src/",
  10.651 +					"$(PROJECT_DIR)/../../OpenSSL-for-iPhone/include",
  10.652 +					"$(PROJECT_DIR)/../asn.1/",
  10.653 +					"$(inherited)",
  10.654 +				);
  10.655  			};
  10.656  			name = Debug;
  10.657  		};
  10.658 @@ -1088,7 +1231,15 @@
  10.659  				OTHER_LDFLAGS = "-ObjC";
  10.660  				PRODUCT_NAME = "$(TARGET_NAME)";
  10.661  				SKIP_INSTALL = YES;
  10.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)";
  10.663 +				USER_HEADER_SEARCH_PATHS = (
  10.664 +					"$(PROJECT_DIR)/../src",
  10.665 +					"$(PROJECT_DIR)",
  10.666 +					"$(PROJECT_DIR)/../../netpgp-et/include/",
  10.667 +					"$(PROJECT_DIR)/../../netpgp-et/src/",
  10.668 +					"$(PROJECT_DIR)/../../OpenSSL-for-iPhone/include",
  10.669 +					"$(PROJECT_DIR)/../asn.1/",
  10.670 +					"$(inherited)",
  10.671 +				);
  10.672  			};
  10.673  			name = Release;
  10.674  		};
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/build-mac/pEpTrustWords-Info.plist	Fri May 17 17:30:57 2019 +0200
    11.3 @@ -0,0 +1,28 @@
    11.4 +<?xml version="1.0" encoding="UTF-8"?>
    11.5 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    11.6 +<plist version="1.0">
    11.7 +<dict>
    11.8 +	<key>CFBundleDevelopmentRegion</key>
    11.9 +	<string>en</string>
   11.10 +	<key>CFBundlePackageType</key>
   11.11 +	<string>BNDL</string>
   11.12 +	<key>CFBundleIdentifier</key>
   11.13 +	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
   11.14 +	<key>CFBundleInfoDictionaryVersion</key>
   11.15 +	<string>6.0</string>
   11.16 +	<key>CFBundleName</key>
   11.17 +	<string>$(PRODUCT_NAME)</string>
   11.18 +	<key>CFBundlePackageType</key>
   11.19 +	<string>BNDL</string>
   11.20 +	<key>CFBundleShortVersionString</key>
   11.21 +	<string>1.0</string>
   11.22 +	<key>CFBundleSignature</key>
   11.23 +	<string>????</string>
   11.24 +	<key>CFBundleVersion</key>
   11.25 +	<string>1</string>
   11.26 +	<key>NSHumanReadableCopyright</key>
   11.27 +	<string>Copyright © 2015 Edouard Tisserant. All rights reserved.</string>
   11.28 +	<key>NSPrincipalClass</key>
   11.29 +	<string></string>
   11.30 +</dict>
   11.31 +</plist>
    12.1 --- a/build-windows/libpEpasn1/libpEpasn1.vcxproj	Thu Mar 28 15:40:45 2019 +0100
    12.2 +++ b/build-windows/libpEpasn1/libpEpasn1.vcxproj	Fri May 17 17:30:57 2019 +0200
    12.3 @@ -143,105 +143,10 @@
    12.4      <Text Include="ReadMe.txt" />
    12.5    </ItemGroup>
    12.6    <ItemGroup>
    12.7 -    <ClInclude Include="..\..\asn.1\asn_application.h" />
    12.8 -    <ClInclude Include="..\..\asn.1\asn_codecs.h" />
    12.9 -    <ClInclude Include="..\..\asn.1\asn_codecs_prim.h" />
   12.10 -    <ClInclude Include="..\..\asn.1\asn_internal.h" />
   12.11 -    <ClInclude Include="..\..\asn.1\asn_SEQUENCE_OF.h" />
   12.12 -    <ClInclude Include="..\..\asn.1\asn_SET_OF.h" />
   12.13 -    <ClInclude Include="..\..\asn.1\asn_system.h" />
   12.14 -    <ClInclude Include="..\..\asn.1\Beacon.h" />
   12.15 -    <ClInclude Include="..\..\asn.1\ber_decoder.h" />
   12.16 -    <ClInclude Include="..\..\asn.1\ber_tlv_length.h" />
   12.17 -    <ClInclude Include="..\..\asn.1\ber_tlv_tag.h" />
   12.18 -    <ClInclude Include="..\..\asn.1\BIT_STRING.h" />
   12.19 -    <ClInclude Include="..\..\asn.1\BOOLEAN.h" />
   12.20 -    <ClInclude Include="..\..\asn.1\CommitAccept.h" />
   12.21 -    <ClInclude Include="..\..\asn.1\CommitReject.h" />
   12.22 -    <ClInclude Include="..\..\asn.1\constraints.h" />
   12.23 -    <ClInclude Include="..\..\asn.1\constr_CHOICE.h" />
   12.24 -    <ClInclude Include="..\..\asn.1\constr_SEQUENCE.h" />
   12.25 -    <ClInclude Include="..\..\asn.1\constr_SEQUENCE_OF.h" />
   12.26 -    <ClInclude Include="..\..\asn.1\constr_SET_OF.h" />
   12.27 -    <ClInclude Include="..\..\asn.1\constr_TYPE.h" />
   12.28 -    <ClInclude Include="..\..\asn.1\der_encoder.h" />
   12.29 -    <ClInclude Include="..\..\asn.1\GroupKeys.h" />
   12.30 -    <ClInclude Include="..\..\asn.1\GroupKeysAndClose.h" />
   12.31 -    <ClInclude Include="..\..\asn.1\HandshakeAnswer.h" />
   12.32 -    <ClInclude Include="..\..\asn.1\HandshakeRequest.h" />
   12.33 -    <ClInclude Include="..\..\asn.1\Hash.h" />
   12.34 -    <ClInclude Include="..\..\asn.1\Hex.h" />
   12.35 -    <ClInclude Include="..\..\asn.1\Identity.h" />
   12.36 -    <ClInclude Include="..\..\asn.1\IdentityList.h" />
   12.37 -    <ClInclude Include="..\..\asn.1\INTEGER.h" />
   12.38 -    <ClInclude Include="..\..\asn.1\ISO639-1.h" />
   12.39 -    <ClInclude Include="..\..\asn.1\KeySync.h" />
   12.40 -    <ClInclude Include="..\..\asn.1\NativeEnumerated.h" />
   12.41 -    <ClInclude Include="..\..\asn.1\NativeInteger.h" />
   12.42 -    <ClInclude Include="..\..\asn.1\OCTET_STRING.h" />
   12.43 -    <ClInclude Include="..\..\asn.1\per_decoder.h" />
   12.44 -    <ClInclude Include="..\..\asn.1\per_encoder.h" />
   12.45 -    <ClInclude Include="..\..\asn.1\per_opentype.h" />
   12.46 -    <ClInclude Include="..\..\asn.1\per_support.h" />
   12.47 -    <ClInclude Include="..\..\asn.1\PrintableString.h" />
   12.48 -    <ClInclude Include="..\..\asn.1\PString.h" />
   12.49 -    <ClInclude Include="..\..\asn.1\Rollback.h" />
   12.50 -    <ClInclude Include="..\..\asn.1\Sync.h" />
   12.51 -    <ClInclude Include="..\..\asn.1\TID.h" />
   12.52 -    <ClInclude Include="..\..\asn.1\UTF8String.h" />
   12.53 -    <ClInclude Include="..\..\asn.1\Version.h" />
   12.54 -    <ClInclude Include="..\..\asn.1\xer_decoder.h" />
   12.55 -    <ClInclude Include="..\..\asn.1\xer_encoder.h" />
   12.56 -    <ClInclude Include="..\..\asn.1\xer_support.h" />
   12.57 +    <ClInclude Include="..\..\asn.1\*.h" />
   12.58    </ItemGroup>
   12.59    <ItemGroup>
   12.60 -    <ClCompile Include="..\..\asn.1\asn_codecs_prim.c" />
   12.61 -    <ClCompile Include="..\..\asn.1\asn_SEQUENCE_OF.c" />
   12.62 -    <ClCompile Include="..\..\asn.1\asn_SET_OF.c" />
   12.63 -    <ClCompile Include="..\..\asn.1\Beacon.c" />
   12.64 -    <ClCompile Include="..\..\asn.1\ber_decoder.c" />
   12.65 -    <ClCompile Include="..\..\asn.1\ber_tlv_length.c" />
   12.66 -    <ClCompile Include="..\..\asn.1\ber_tlv_tag.c" />
   12.67 -    <ClCompile Include="..\..\asn.1\BIT_STRING.c" />
   12.68 -    <ClCompile Include="..\..\asn.1\BOOLEAN.c" />
   12.69 -    <ClCompile Include="..\..\asn.1\CommitAccept.c" />
   12.70 -    <ClCompile Include="..\..\asn.1\CommitReject.c" />
   12.71 -    <ClCompile Include="..\..\asn.1\constraints.c" />
   12.72 -    <ClCompile Include="..\..\asn.1\constr_CHOICE.c" />
   12.73 -    <ClCompile Include="..\..\asn.1\constr_SEQUENCE.c" />
   12.74 -    <ClCompile Include="..\..\asn.1\constr_SEQUENCE_OF.c" />
   12.75 -    <ClCompile Include="..\..\asn.1\constr_SET_OF.c" />
   12.76 -    <ClCompile Include="..\..\asn.1\constr_TYPE.c" />
   12.77 -    <ClCompile Include="..\..\asn.1\der_encoder.c" />
   12.78 -    <ClCompile Include="..\..\asn.1\GroupKeys.c" />
   12.79 -    <ClCompile Include="..\..\asn.1\GroupKeysAndClose.c" />
   12.80 -    <ClCompile Include="..\..\asn.1\HandshakeAnswer.c" />
   12.81 -    <ClCompile Include="..\..\asn.1\HandshakeRequest.c" />
   12.82 -    <ClCompile Include="..\..\asn.1\Hash.c" />
   12.83 -    <ClCompile Include="..\..\asn.1\Hex.c" />
   12.84 -    <ClCompile Include="..\..\asn.1\Identity.c" />
   12.85 -    <ClCompile Include="..\..\asn.1\IdentityList.c" />
   12.86 -    <ClCompile Include="..\..\asn.1\INTEGER.c" />
   12.87 -    <ClCompile Include="..\..\asn.1\ISO639-1.c" />
   12.88 -    <ClCompile Include="..\..\asn.1\KeySync.c" />
   12.89 -    <ClCompile Include="..\..\asn.1\NativeEnumerated.c" />
   12.90 -    <ClCompile Include="..\..\asn.1\NativeInteger.c" />
   12.91 -    <ClCompile Include="..\..\asn.1\OCTET_STRING.c" />
   12.92 -    <ClCompile Include="..\..\asn.1\pdu_collection.c" />
   12.93 -    <ClCompile Include="..\..\asn.1\per_decoder.c" />
   12.94 -    <ClCompile Include="..\..\asn.1\per_encoder.c" />
   12.95 -    <ClCompile Include="..\..\asn.1\per_opentype.c" />
   12.96 -    <ClCompile Include="..\..\asn.1\per_support.c" />
   12.97 -    <ClCompile Include="..\..\asn.1\PrintableString.c" />
   12.98 -    <ClCompile Include="..\..\asn.1\PString.c" />
   12.99 -    <ClCompile Include="..\..\asn.1\Rollback.c" />
  12.100 -    <ClCompile Include="..\..\asn.1\Sync.c" />
  12.101 -    <ClCompile Include="..\..\asn.1\TID.c" />
  12.102 -    <ClCompile Include="..\..\asn.1\UTF8String.c" />
  12.103 -    <ClCompile Include="..\..\asn.1\Version.c" />
  12.104 -    <ClCompile Include="..\..\asn.1\xer_decoder.c" />
  12.105 -    <ClCompile Include="..\..\asn.1\xer_encoder.c" />
  12.106 -    <ClCompile Include="..\..\asn.1\xer_support.c" />
  12.107 +    <ClCompile Include="..\..\asn.1\*.c" />
  12.108    </ItemGroup>
  12.109    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  12.110    <ImportGroup Label="ExtensionTargets">
    13.1 --- a/build-windows/libpEpasn1/libpEpasn1.vcxproj.filters	Thu Mar 28 15:40:45 2019 +0100
    13.2 +++ b/build-windows/libpEpasn1/libpEpasn1.vcxproj.filters	Fri May 17 17:30:57 2019 +0200
    13.3 @@ -168,6 +168,27 @@
    13.4      <ClInclude Include="..\..\asn.1\xer_support.h">
    13.5        <Filter>Header Files</Filter>
    13.6      </ClInclude>
    13.7 +    <ClInclude Include="..\..\asn.1\CommitAcceptForGroup.h">
    13.8 +      <Filter>Header Files</Filter>
    13.9 +    </ClInclude>
   13.10 +    <ClInclude Include="..\..\asn.1\GroupTrustThisKey.h">
   13.11 +      <Filter>Header Files</Filter>
   13.12 +    </ClInclude>
   13.13 +    <ClInclude Include="..\..\asn.1\CommitAcceptFirst.h">
   13.14 +      <Filter>Header Files</Filter>
   13.15 +    </ClInclude>
   13.16 +    <ClInclude Include="..\..\asn.1\CommitAcceptSecond.h">
   13.17 +      <Filter>Header Files</Filter>
   13.18 +    </ClInclude>
   13.19 +    <ClInclude Include="..\..\asn.1\OwnKeys.h">
   13.20 +      <Filter>Header Files</Filter>
   13.21 +    </ClInclude>
   13.22 +    <ClInclude Include="..\..\asn.1\OwnKeysFirst.h">
   13.23 +      <Filter>Header Files</Filter>
   13.24 +    </ClInclude>
   13.25 +    <ClInclude Include="..\..\asn.1\OwnKeysSecond.h">
   13.26 +      <Filter>Header Files</Filter>
   13.27 +    </ClInclude>
   13.28    </ItemGroup>
   13.29    <ItemGroup>
   13.30      <ClCompile Include="..\..\asn.1\asn_codecs_prim.c">
   13.31 @@ -227,9 +248,6 @@
   13.32      <ClCompile Include="..\..\asn.1\GroupKeys.c">
   13.33        <Filter>Source Files</Filter>
   13.34      </ClCompile>
   13.35 -    <ClCompile Include="..\..\asn.1\GroupKeysAndClose.c">
   13.36 -      <Filter>Source Files</Filter>
   13.37 -    </ClCompile>
   13.38      <ClCompile Include="..\..\asn.1\HandshakeAnswer.c">
   13.39        <Filter>Source Files</Filter>
   13.40      </ClCompile>
   13.41 @@ -311,5 +329,26 @@
   13.42      <ClCompile Include="..\..\asn.1\xer_support.c">
   13.43        <Filter>Source Files</Filter>
   13.44      </ClCompile>
   13.45 +    <ClCompile Include="..\..\asn.1\CommitAcceptForGroup.c">
   13.46 +      <Filter>Source Files</Filter>
   13.47 +    </ClCompile>
   13.48 +    <ClCompile Include="..\..\asn.1\GroupTrustThisKey.c">
   13.49 +      <Filter>Source Files</Filter>
   13.50 +    </ClCompile>
   13.51 +    <ClCompile Include="..\..\asn.1\CommitAcceptFirst.c">
   13.52 +      <Filter>Source Files</Filter>
   13.53 +    </ClCompile>
   13.54 +    <ClCompile Include="..\..\asn.1\CommitAcceptSecond.c">
   13.55 +      <Filter>Source Files</Filter>
   13.56 +    </ClCompile>
   13.57 +    <ClCompile Include="..\..\asn.1\OwnKeys.c">
   13.58 +      <Filter>Source Files</Filter>
   13.59 +    </ClCompile>
   13.60 +    <ClCompile Include="..\..\asn.1\OwnKeysFirst.c">
   13.61 +      <Filter>Source Files</Filter>
   13.62 +    </ClCompile>
   13.63 +    <ClCompile Include="..\..\asn.1\OwnKeysSecond.c">
   13.64 +      <Filter>Source Files</Filter>
   13.65 +    </ClCompile>
   13.66    </ItemGroup>
   13.67  </Project>
   13.68 \ No newline at end of file
    14.1 --- a/clean_sync_leftovers.sh	Thu Mar 28 15:40:45 2019 +0100
    14.2 +++ b/clean_sync_leftovers.sh	Fri May 17 17:30:57 2019 +0200
    14.3 @@ -4,3 +4,7 @@
    14.4  cd ../asn.1; hg status . | sed '/?\ /!d' | sed 's/?\ //' |  xargs rm
    14.5  cd ../sync; hg status . | sed '/?\ /!d' | sed 's/?\ //' |  xargs rm
    14.6  cd ..
    14.7 +branch=`hg branch`
    14.8 +if [ "$branch" = "sync" ]; then
    14.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
   14.10 +fi	
    15.1 --- a/db/Makefile	Thu Mar 28 15:40:45 2019 +0100
    15.2 +++ b/db/Makefile	Fri May 17 17:30:57 2019 +0200
    15.3 @@ -3,7 +3,7 @@
    15.4  # This file may be used under the terms of the GNU General Public License version 3
    15.5  # see LICENSE.txt
    15.6  
    15.7 -include ../default.conf
    15.8 +include ../Makefile.conf
    15.9  
   15.10  .PHONY: db
   15.11  db: system.db
    16.1 --- a/default.conf	Thu Mar 28 15:40:45 2019 +0100
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,280 +0,0 @@
    16.4 -# Copyright 2017, pEp Foundation
    16.5 -# This file is part of pEpEngine
    16.6 -# This file may be used under the terms of the GNU General Public License version 3
    16.7 -# see LICENSE.txt
    16.8 -
    16.9 -# See `doc/build-<your platform>.md` for documentation on how to build, and customize your build.
   16.10 -
   16.11 -# This file sets all the make variables that allow you to customize a build.
   16.12 -# There are 4 ways in which you can customize your build:
   16.13 -# 1) Edit the variable assignments in this file (this is a tracked file, so your repository will be dirty)
   16.14 -# 2) Edit the variable assignments in `Makefile.conf` (which is a tracked file, so your repository will be dirty)
   16.15 -# 3) Create `local.conf` and fill it with variable assignments.
   16.16 -# 4) Set the environment variable `BUILD_CONFIG` to an absolute path.
   16.17 -#    The variable assignments found in the make file at the path indicated by `BUILD_CONFIG` will be evaluated.
   16.18 -# Customization options are applied in the order given above. Later variable assignments take precedence over earlier ones.
   16.19 -# It is possible to use multiple variants simultaniously.
   16.20 -# If nothing is changed according to these 4 methods, a default configuration for your platform (specified below) will be used for the build.
   16.21 -
   16.22 -
   16.23 -######### Header #########
   16.24 -HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
   16.25 -
   16.26 -
   16.27 -######### General #########
   16.28 -# To use (only) system libraries, set all the *_INC and *_LIB variables to the empty string.
   16.29 -# All the *_INC and *_LIB variables are command line flags, not paths.
   16.30 -# Thus, all *_INC variables' values must start with "-I", and all *_LIB variables' values must start with "-L".
   16.31 -
   16.32 -BUILD_ON:=$(shell uname)
   16.33 -
   16.34 -# This variable specifies the platform that the engine should be cross-compiled for.
   16.35 -BUILD_FOR=$(BUILD_ON)
   16.36 -
   16.37 -# Cross-compiling is currently not supported.
   16.38 -# Maybe you can hack something with `local.conf`.
   16.39 -ifneq ($(BUILD_ON),$(BUILD_FOR))
   16.40 -    $(error I don't know how to build for $(BUILD_FOR) on $(BUILD_ON).)
   16.41 -endif
   16.42 -
   16.43 -# Installation path prefix for libraries and binaries, except for system.db
   16.44 -PREFIX=$(HOME)
   16.45 -
   16.46 -# Installation path for system.db
   16.47 -SYSTEM_DB=/usr/local/share/pEp/system.db
   16.48 -
   16.49 -# Filename of the pEpEngine library
   16.50 -ifeq ($(BUILD_FOR),Linux)
   16.51 -    TARGET=libpEpEngine.so
   16.52 -else ifeq ($(BUILD_FOR),Darwin)
   16.53 -    TARGET=libpEpEngine.dylib
   16.54 -endif
   16.55 -
   16.56 -# If empty, create a release build.
   16.57 -# Otherwise, create a debug build.
   16.58 -# This variable is ineffective in your local.conf file.
   16.59 -DEBUG=placeholder
   16.60 -
   16.61 -# If empty, suppress compiler warnings.
   16.62 -# Otherwise, print warnings.
   16.63 -# This variable is ineffective in your local.conf file.
   16.64 -WARN=placeholder
   16.65 -
   16.66 -
   16.67 -######### C and C++ #########
   16.68 -TARGET_ARCH=
   16.69 -# The following two variables will be appended to.
   16.70 -# You can thus not set them to a fixed value here.
   16.71 -ifeq ($(BUILD_FOR),Linux)
   16.72 -    LDFLAGS=
   16.73 -else ifeq ($(BUILD_FOR),Darwin)
   16.74 -    # "-bind_at_load" helps find symbol resolution errors faster
   16.75 -    LDFLAGS=-bind_at_load
   16.76 -endif
   16.77 -
   16.78 -LDLIBS=
   16.79 -
   16.80 -
   16.81 -######### C #########
   16.82 -ifeq ($(BUILD_FOR),Linux)
   16.83 -    CC=gcc -std=c99 -pthread
   16.84 -else ifeq ($(BUILD_FOR),Darwin)
   16.85 -    # clang issues a warning when "-pthread" is used for linking.
   16.86 -    # So, include it in CFLAGS, and not in CC
   16.87 -    CC=clang -std=c99
   16.88 -endif
   16.89 -
   16.90 -ifeq ($(BUILD_FOR),Linux)
   16.91 -    CFLAGS=-fPIC -fstrict-aliasing -fdiagnostics-color=always
   16.92 -else ifeq ($(BUILD_FOR),Darwin)
   16.93 -    CFLAGS=-pthread -fPIC -fstrict-aliasing -fcolor-diagnostics
   16.94 -endif
   16.95 -
   16.96 -CPPFLAGS=
   16.97 -
   16.98 -# The flag -DNDEBUG will always be removed from CFLAGS for compiling tests.
   16.99 -# The tests do not work properly, if compiled with -DNDEBUG
  16.100 -ifeq ($(BUILD_FOR),Linux)
  16.101 -    ifdef WARN
  16.102 -        CFLAGS+= -Wall -pedantic -Wstrict-aliasing=3
  16.103 -    else
  16.104 -        CFLAGS+= -w
  16.105 -    endif
  16.106 -    ifdef DEBUG
  16.107 -        CFLAGS+= -g -ggdb -DDEBUG_ERRORSTACK
  16.108 -    else
  16.109 -        CFLAGS+= -O3 -DNDEBUG
  16.110 -    endif
  16.111 -else ifeq ($(BUILD_FOR),Darwin)
  16.112 -    ifdef WARN
  16.113 -        # FIXME Remove 'no-extended-offsetof' after ENGINE-236 is closed.
  16.114 -        CFLAGS+= -Wall -pedantic -Wno-extended-offsetof
  16.115 -    else
  16.116 -        CFLAGS+= -w
  16.117 -    endif
  16.118 -    ifdef DEBUG
  16.119 -        CFLAGS+= -O0 -g -DDEBUG_ERRORSTACK
  16.120 -    else
  16.121 -        CFLAGS+= -O3 -DNDEBUG
  16.122 -    endif
  16.123 -endif
  16.124 -
  16.125 -# Additional CFLAGS used for compiling ASN1C-generated code
  16.126 -ifeq ($(BUILD_FOR),Linux)
  16.127 -    # The '_DEFAULT_SOURCE' feature test macro is required to suppress the warning
  16.128 -    #   _BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE
  16.129 -    # otherwise printed during the compilation of every asn1c-generated C file.
  16.130 -    # It's a glibc specific warning, only present in few versions around ~2.19.
  16.131 -    # See https://lwn.net/Articles/590381/ for a discussion.
  16.132 -    CFLAGS_GENERATED=-D_DEFAULT_SOURCE
  16.133 -else ifeq ($(BUILD_FOR),Darwin)
  16.134 -    CFLAGS_GENERATED=
  16.135 -endif
  16.136 -
  16.137 -
  16.138 -######### C++ #########
  16.139 -ifeq ($(BUILD_FOR),Linux)
  16.140 -    CXX=g++ -std=gnu++11 -pthread
  16.141 -else ifeq ($(BUILD_FOR),Darwin)
  16.142 -    # clang issues a warning when "-pthread" is used for linking. So, include it in CXXFLAGS, and not in CXX
  16.143 -    CXX=clang -std=c++11
  16.144 -endif
  16.145 -
  16.146 -# The flag -DNDEBUG will always be removed from CXXFLAGS for compiling tests.
  16.147 -# The tests do not work properly, if compiled with -DNDEBUG
  16.148 -ifeq ($(BUILD_FOR),Linux)
  16.149 -    CXXFLAGS=-fdiagnostics-color=always -I../src -I../asn.1 $(ETPAN_INC)
  16.150 -    ifdef WARN
  16.151 -        CXXFLAGS+=
  16.152 -    else
  16.153 -        CXXFLAGS+= -w
  16.154 -    endif
  16.155 -    ifdef DEBUG
  16.156 -        CXXFLAGS+= -g -ggdb
  16.157 -    else
  16.158 -        CXXFLAGS+= -O3 -DNDEBUG
  16.159 -    endif
  16.160 -else ifeq ($(BUILD_FOR),Darwin)
  16.161 -    CXXFLAGS=-pthread -fcolor-diagnostics -I../src -I../asn.1 $(ETPAN_INC)
  16.162 -    ifdef WARN
  16.163 -        CXXFLAGS+=
  16.164 -    else
  16.165 -        CXXFLAGS+= -w
  16.166 -    endif
  16.167 -    ifdef DEBUG
  16.168 -        CXXFLAGS+= -O0 -g
  16.169 -    else
  16.170 -        CXXFLAGS+= -O3 -DNDEBUG
  16.171 -    endif
  16.172 -endif
  16.173 -
  16.174 -
  16.175 -######### YML2 #########
  16.176 -YML2_PATH=$(HOME)/yml2
  16.177 -
  16.178 -YML2_PROC=$(YML2_PATH)/yml2proc
  16.179 -
  16.180 -YML2_OPTS=--encoding=utf8
  16.181 -
  16.182 -
  16.183 -######### asn1c #########
  16.184 -# asn1c binary
  16.185 -ASN1C=asn1c
  16.186 -
  16.187 -# asn1c include search flag
  16.188 -ASN1C_INC=-I$(PREFIX)/include
  16.189 -
  16.190 -
  16.191 -######### libetpan #########
  16.192 -# libetpan library search flag
  16.193 -ETPAN_LIB=-L$(PREFIX)/lib
  16.194 -
  16.195 -# libetpan include search flag
  16.196 -ETPAN_INC=-I$(PREFIX)/include
  16.197 -
  16.198 -
  16.199 -######### sqlite3 #########
  16.200 -# If empty (or undefined), compile sqlite3 from the sources shipped with the pEp distribution.
  16.201 -# Otherwise, use an sqlite3 implementation found in the OS's include/library paths.
  16.202 -SQLITE3_FROM_OS=placeholder
  16.203 -
  16.204 -
  16.205 -######### OpenPGP #########
  16.206 -# Path of GPG binary
  16.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.
  16.208 -GPG_CMD:=$(shell gpgconf --list-components | awk -F: '/^gpg:/ { print $$3; exit 0; }')
  16.209 -
  16.210 -# Selects OpenPGP implementation. must be either `GPG` or `NETPGP` or `SEQUOIA`
  16.211 -OPENPGP=GPG
  16.212 -
  16.213 -# Path of libGPGME binary
  16.214 -ifeq ($(BUILD_FOR),Linux)
  16.215 -    LIBGPGME=libgpgme.so.11
  16.216 -else ifeq ($(BUILD_FOR),Darwin)
  16.217 -    LIBGPGME=libgpgme.11.dylib
  16.218 -endif
  16.219 -
  16.220 -# libGPGME library search flag
  16.221 -ifeq ($(BUILD_FOR),Linux)
  16.222 -    GPGME_LIB=
  16.223 -else ifeq ($(BUILD_FOR),Darwin)
  16.224 -    GPGME_LIB=-L$(HOME)/lib
  16.225 -endif
  16.226 -
  16.227 -# libGPGME include search flag
  16.228 -ifeq ($(BUILD_FOR),Linux)
  16.229 -    GPGME_INC=
  16.230 -else ifeq ($(BUILD_FOR),Darwin)
  16.231 -    GPGME_INC=-I$(HOME)/include
  16.232 -endif
  16.233 -
  16.234 -# NETPGP library search flag
  16.235 -NETPGP_LIB=
  16.236 -#NETPGP_LIB=-L$(PREFIX)/lib
  16.237 -
  16.238 -# libGPGME include search flag
  16.239 -NETPGP_INC=
  16.240 -#NETPGP_INC=-I$(PREFIX)/include
  16.241 -
  16.242 -SEQUOIA_CFLAGS=$(shell pkg-config --cflags-only-other sequoia)
  16.243 -SEQUOIA_LDFLAGS=$(shell pkg-config --libs-only-L --libs-only-other sequoia)
  16.244 -SEQUOIA_LIB=$(shell pkg-config --libs-only-l sequoia)
  16.245 -SEQUOIA_INC=$(shell pkg-config --cflags-only-I sequoia)
  16.246 -
  16.247 -
  16.248 -######### OpenPGP #########
  16.249 -# CppUnit library search flag
  16.250 -CPPUNIT_LIB=
  16.251 -#CPPUNIT_LIB=-L$(HOME)/local/lib
  16.252 -
  16.253 -# CppUnit include search flag
  16.254 -CPPUNIT_INC=
  16.255 -#CPPUNIT_INC=-I$(HOME)/local/inc
  16.256 -
  16.257 -
  16.258 -######### Engine internals #########
  16.259 -# C macros (not environment variables) that can be overridden:
  16.260 -# DEFAULT_KEYSERVER - string with default keyserver
  16.261 -# CRASHDUMP_DEFAULT_LINES - number of log lines to deliver for crashdumps
  16.262 -# Example:
  16.263 -#    EXTRA_MACROS=-DDEFAULT_KEYSERVER=\"default-server.org\" -DCRASHDUMP_DEFAULT_LINES=23
  16.264 -EXTRA_MACROS=
  16.265 -
  16.266 -
  16.267 -######### Misc #########
  16.268 -# FIXME Maybe include these variables here.
  16.269 -# Check how they are used throughout the project before setting them here
  16.270 -#LLDB_BIN
  16.271 -
  16.272 -
  16.273 -######### Footer #########
  16.274 -include $(HERE)/Makefile.conf
  16.275 -
  16.276 --include $(HERE)/local.conf
  16.277 -
  16.278 -ifdef BUILD_CONFIG
  16.279 -    include $(BUILD_CONFIG)
  16.280 -endif
  16.281 -
  16.282 -# YML_PATH is needed in the environment of every call to a program of the YML2 distribution
  16.283 -export YML_PATH=$(YML2_PATH)
    17.1 --- a/doc/build-debian.md	Thu Mar 28 15:40:45 2019 +0100
    17.2 +++ b/doc/build-debian.md	Fri May 17 17:30:57 2019 +0200
    17.3 @@ -64,11 +64,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, libetpan and asn1c.
   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/doc/build-macos.md	Thu Mar 28 15:40:45 2019 +0100
    18.2 +++ b/doc/build-macos.md	Fri May 17 17:30:57 2019 +0200
    18.3 @@ -105,11 +105,11 @@
    18.4  mkdir ~/code/pep-engine/build
    18.5  ~~~
    18.6  
    18.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`.
    18.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`.
    18.9  
   18.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.
   18.11  
   18.12 -For a more detailed explanation of the mechanics of these build configuration files, and overriding defaults, see the comments in `default.conf`.
   18.13 +For a more detailed explanation of the mechanics of these build configuration files, and overriding defaults, see the comments in `Makefile.conf`.
   18.14  
   18.15  Below is a sample `./local.conf` file, for orientation.
   18.16  
    19.1 --- a/src/Makefile	Thu Mar 28 15:40:45 2019 +0100
    19.2 +++ b/src/Makefile	Fri May 17 17:30:57 2019 +0200
    19.3 @@ -3,29 +3,36 @@
    19.4  # This file may be used under the terms of the GNU General Public License version 3
    19.5  # see LICENSE.txt
    19.6  
    19.7 -include ../default.conf
    19.8 +include ../Makefile.conf
    19.9 +
   19.10 +CFLAGS+= $(ETPAN_INC) $(PEP_MIME_INC) -I../asn.1 -DSYSTEM_DB=\"$(SYSTEM_DB)\" $(EXTRA_MACROS)
   19.11 +LDFLAGS+= $(ETPAN_LIB) $(PEP_MIME_LIB) -L../asn.1 -shared
   19.12 +LDLIBS+= -lc -lasn1
   19.13 +NO_SOURCE=
   19.14  
   19.15 -CFLAGS+= $(ETPAN_INC) -I../asn.1 -DSYSTEM_DB=\"$(SYSTEM_DB)\" $(EXTRA_MACROS)
   19.16 -LDFLAGS+= $(ETPAN_LIB) -L../asn.1 -shared
   19.17 -LDLIBS+= -lc -letpan -lasn1
   19.18 -NO_SOURCE=
   19.19 +ifndef PEP_MIME
   19.20 +LDLIBS+= -letpan
   19.21 +else
   19.22 +LDLIBS+= -lpEpMIME
   19.23 +NO_SOURCE+= etpan_mime.c
   19.24 +endif
   19.25  
   19.26  ifeq ($(BUILD_ON),Darwin)
   19.27      ifeq ($(BUILD_FOR),Darwin)
   19.28          CFLAGS+= -DSQLITE_THREADSAFE=1
   19.29          LDLIBS+= -lz -liconv
   19.30      else
   19.31 -        $(error I don't know how to make for $(BUILD_FOR) on $(BUILD_ON))
   19.32 +        $(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON))
   19.33      endif
   19.34  else ifeq ($(BUILD_ON),Linux)
   19.35      ifeq ($(BUILD_FOR),Linux)
   19.36          CFLAGS+= -DSQLITE_THREADSAFE=1 -D_GNU_SOURCE
   19.37          LDLIBS+= -ldl -luuid
   19.38      else
   19.39 -        $(error I don't know how to make for $(BUILD_FOR) on $(BUILD_ON))
   19.40 +        $(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON))
   19.41      endif
   19.42  else
   19.43 -    $(error I don't know how to make for $(BUILD_FOR) on $(BUILD_ON))
   19.44 +    $(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON))
   19.45  endif
   19.46  
   19.47  ifdef SQLITE3_FROM_OS
   19.48 @@ -57,7 +64,6 @@
   19.49  DEPENDS=$(subst .c,.d,$(ALL_SOURCE))
   19.50  ALL_OBJECTS=$(subst .c,.o,$(ALL_SOURCE))
   19.51  
   19.52 -.PHONY: all
   19.53  all: $(TARGET)
   19.54  
   19.55  -include Makefile.protocols
   19.56 @@ -74,36 +80,39 @@
   19.57  endif
   19.58  
   19.59  $(TARGET): libpEpEngine.a
   19.60 -	$(CC) $(ALL_OBJECTS) $(LDFLAGS) $(LDLIBS) -o $@
   19.61 +	$(CC) $(CFLAGS) $(ALL_OBJECTS) $(LDFLAGS) $(LDLIBS) -o $@
   19.62  
   19.63 -.PHONY: objects
   19.64 +.PHONY: objects clean install_headers install uninstall
   19.65 +
   19.66  objects: $(ALL_OBJECTS)
   19.67  
   19.68  libpEpEngine.a: $(ALL_OBJECTS)
   19.69 -	ar -rc $@ $^
   19.70 +	$(AR) -rc $@ $^
   19.71  
   19.72 -.PHONY: clean
   19.73  clean:
   19.74  	rm -f *.d *.o *.a $(TARGET) *.dll *.so *.zip *.d.* *.def *~
   19.75  	rm -Rf $(TARGET).dSYM
   19.76 +	rm -f KeySync_fsm.* Sync_actions.c Sync_event.* Sync_func.* Sync_impl.* sync_codec.*
   19.77  
   19.78 -.PHONY: install
   19.79 -install: $(TARGET)
   19.80 +# CAVEAT:
   19.81 +# install_headers is needed for building pEp MIME
   19.82 +
   19.83 +install_headers:
   19.84 +	mkdir -p $(PREFIX)/include/pEp
   19.85 +	cp pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h \
   19.86 +	   timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h \
   19.87 +	   cryptotech.h sync_api.h blacklist.h pEp_string.h openpgp_compat.h \
   19.88 +	   labeled_int_list.h key_reset.h base64.h sync_codec.h status_to_string.h\
   19.89 +	   aux_mime_msg.h ../asn.1/*.h $(PREFIX)/include/pEp/
   19.90 +
   19.91 +install: $(TARGET) install_headers
   19.92  	mkdir -p "$(PREFIX)/lib/"
   19.93  	cp $< $(PREFIX)/lib/
   19.94 -	mkdir -p $(PREFIX)/include/pEp
   19.95 -	cp -v pEpEngine.h keymanagement.h message_api.h dynamic_api.h stringlist.h \
   19.96 -	      timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h \
   19.97 -	      cryptotech.h sync_api.h blacklist.h pEp_string.h openpgp_compat.h \
   19.98 -	      labeled_int_list.h key_reset.h base64.h sync_codec.h \
   19.99 -		  ../asn.1/*.h $(PREFIX)/include/pEp/
  19.100  
  19.101 -.PHONY: uninstall
  19.102  uninstall:
  19.103  	rm -f $(PREFIX)/lib/$(TARGET)
  19.104  	rm -rf $(PREFIX)/include/pEp
  19.105  
  19.106 -.PHONY: tags
  19.107 -tags:
  19.108 +tags: $(wildcard *.c) $(wildcard *.h)
  19.109  	ctags *.c *.h
  19.110  
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/aux_mime_msg.c	Fri May 17 17:30:57 2019 +0200
    20.3 @@ -0,0 +1,274 @@
    20.4 +// This file is under GNU General Public License 3.0
    20.5 +// see LICENSE.txt
    20.6 +
    20.7 +#ifdef ENIGMAIL_MAY_USE_THIS
    20.8 +
    20.9 +#include "pEp_internal.h"
   20.10 +#include "message_api.h"
   20.11 +#include "mime.h"
   20.12 +
   20.13 +#include <assert.h>
   20.14 +#include <string.h>
   20.15 +#include <stdlib.h>
   20.16 +
   20.17 +#include "aux_mime_msg.h"
   20.18 +
   20.19 +
   20.20 +static PEP_STATUS update_identity_recip_list(PEP_SESSION session,
   20.21 +                                             identity_list* list) {
   20.22 +
   20.23 +    PEP_STATUS status = PEP_STATUS_OK;
   20.24 +
   20.25 +    if (!session)
   20.26 +        return PEP_UNKNOWN_ERROR;
   20.27 +    
   20.28 +    identity_list* id_list_ptr = NULL;
   20.29 +        
   20.30 +    for (id_list_ptr = list; id_list_ptr; id_list_ptr = id_list_ptr->next) {
   20.31 +        pEp_identity* curr_identity = id_list_ptr->ident;
   20.32 +        if (curr_identity) {
   20.33 +            if (!is_me(session, curr_identity)) {
   20.34 +                char* name_bak = curr_identity->username;
   20.35 +                curr_identity->username = NULL;
   20.36 +                status = update_identity(session, curr_identity);
   20.37 +                if (name_bak && 
   20.38 +                    (EMPTYSTR(curr_identity->username) || strcmp(name_bak, curr_identity->username) != 0)) {
   20.39 +                    free(curr_identity->username);
   20.40 +                    curr_identity->username = name_bak;
   20.41 +                }                        
   20.42 +            }
   20.43 +            else
   20.44 +                status = _myself(session, curr_identity, false, false, true);
   20.45 +        if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
   20.46 +            return status;
   20.47 +        }
   20.48 +    }
   20.49 +    
   20.50 +    return PEP_STATUS_OK;                                  
   20.51 +}
   20.52 +
   20.53 +DYNAMIC_API PEP_STATUS MIME_decrypt_message(
   20.54 +    PEP_SESSION session,
   20.55 +    const char *mimetext,
   20.56 +    size_t size,
   20.57 +    char** mime_plaintext,
   20.58 +    stringlist_t **keylist,
   20.59 +    PEP_rating *rating,
   20.60 +    PEP_decrypt_flags_t *flags,
   20.61 +    char** modified_src
   20.62 +)
   20.63 +{
   20.64 +    assert(mimetext);
   20.65 +    assert(mime_plaintext);
   20.66 +    assert(keylist);
   20.67 +    assert(rating);
   20.68 +    assert(flags);
   20.69 +    assert(modified_src);
   20.70 +
   20.71 +    if (!(mimetext && mime_plaintext && keylist && rating && flags && modified_src))
   20.72 +        return PEP_ILLEGAL_VALUE;
   20.73 +        
   20.74 +    PEP_STATUS status = PEP_STATUS_OK;
   20.75 +    message* tmp_msg = NULL;
   20.76 +    message* dec_msg = NULL;
   20.77 +    *mime_plaintext = NULL;
   20.78 +
   20.79 +    status = mime_decode_message(mimetext, size, &tmp_msg);
   20.80 +    if (status != PEP_STATUS_OK)
   20.81 +        goto pEp_error;
   20.82 +
   20.83 +    tmp_msg->dir = PEP_dir_incoming;
   20.84 +    // MIME decode message delivers only addresses. We need more.
   20.85 +    if (tmp_msg->from) {
   20.86 +        if (!is_me(session, tmp_msg->from))
   20.87 +            status = update_identity(session, (tmp_msg->from));
   20.88 +        else
   20.89 +            status = _myself(session, tmp_msg->from, false, false, true);
   20.90 +
   20.91 +        if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
   20.92 +            goto pEp_error;
   20.93 +    }
   20.94 +
   20.95 +    status = update_identity_recip_list(session, tmp_msg->to);
   20.96 +    if (status != PEP_STATUS_OK)
   20.97 +        goto pEp_error;
   20.98 +
   20.99 +    status = update_identity_recip_list(session, tmp_msg->cc);
  20.100 +    if (status != PEP_STATUS_OK)
  20.101 +        goto pEp_error;
  20.102 +
  20.103 +    status = update_identity_recip_list(session, tmp_msg->bcc);
  20.104 +    if (status != PEP_STATUS_OK)
  20.105 +        goto pEp_error;
  20.106 +
  20.107 +    PEP_STATUS decrypt_status = decrypt_message(session,
  20.108 +                                                tmp_msg,
  20.109 +                                                &dec_msg,
  20.110 +                                                keylist,
  20.111 +                                                rating,
  20.112 +                                                flags);
  20.113 +
  20.114 +
  20.115 +    if (!dec_msg && (decrypt_status == PEP_UNENCRYPTED || decrypt_status == PEP_VERIFIED)) {
  20.116 +        dec_msg = message_dup(tmp_msg);
  20.117 +    }
  20.118 +    
  20.119 +    if (decrypt_status > PEP_CANNOT_DECRYPT_UNKNOWN || !dec_msg)
  20.120 +    {
  20.121 +        status = decrypt_status;
  20.122 +        goto pEp_error;
  20.123 +    }
  20.124 +
  20.125 +    if (*flags & PEP_decrypt_flag_src_modified) {
  20.126 +        _mime_encode_message_internal(tmp_msg, false, modified_src, true);
  20.127 +        if (!modified_src) {
  20.128 +            *flags &= (~PEP_decrypt_flag_src_modified);
  20.129 +            decrypt_status = PEP_CANNOT_REENCRYPT; // Because we couldn't return it, I guess.
  20.130 +        }
  20.131 +    }
  20.132 +
  20.133 +    // FIXME: test with att
  20.134 +    status = _mime_encode_message_internal(dec_msg, false, mime_plaintext, true);
  20.135 +
  20.136 +    if (status == PEP_STATUS_OK)
  20.137 +    {
  20.138 +        free(tmp_msg);
  20.139 +        free(dec_msg);
  20.140 +        return decrypt_status;
  20.141 +    }
  20.142 +    
  20.143 +pEp_error:
  20.144 +    free_message(tmp_msg);
  20.145 +    free_message(dec_msg);
  20.146 +
  20.147 +    return status;
  20.148 +}
  20.149 +
  20.150 +
  20.151 +DYNAMIC_API PEP_STATUS MIME_encrypt_message(
  20.152 +    PEP_SESSION session,
  20.153 +    const char *mimetext,
  20.154 +    size_t size,
  20.155 +    stringlist_t* extra,
  20.156 +    char** mime_ciphertext,
  20.157 +    PEP_enc_format enc_format,
  20.158 +    PEP_encrypt_flags_t flags
  20.159 +)
  20.160 +{
  20.161 +    PEP_STATUS status = PEP_STATUS_OK;
  20.162 +    message* tmp_msg = NULL;
  20.163 +    message* enc_msg = NULL;
  20.164 +
  20.165 +    status = mime_decode_message(mimetext, size, &tmp_msg);
  20.166 +    if (status != PEP_STATUS_OK)
  20.167 +        goto pEp_error;
  20.168 +
  20.169 +    // MIME decode message delivers only addresses. We need more.
  20.170 +    if (tmp_msg->from) {
  20.171 +        char* own_id = NULL;
  20.172 +        status = get_default_own_userid(session, &own_id);
  20.173 +        free(tmp_msg->from->user_id);
  20.174 +        
  20.175 +        if (status != PEP_STATUS_OK || !own_id) {
  20.176 +            tmp_msg->from->user_id = strdup(PEP_OWN_USERID);
  20.177 +        }
  20.178 +        else {
  20.179 +            tmp_msg->from->user_id = own_id; // ownership transfer
  20.180 +        }
  20.181 +            
  20.182 +        status = myself(session, tmp_msg->from);
  20.183 +        if (status != PEP_STATUS_OK)
  20.184 +            goto pEp_error;
  20.185 +    }
  20.186 +    
  20.187 +    // Own identities can be retrieved here where they would otherwise
  20.188 +    // fail because we lack all other information. This is ok and even
  20.189 +    // desired. FIXME: IS it?
  20.190 +    status = update_identity_recip_list(session, tmp_msg->to);
  20.191 +    if (status != PEP_STATUS_OK)
  20.192 +        goto pEp_error;
  20.193 +    
  20.194 +    status = update_identity_recip_list(session, tmp_msg->cc);
  20.195 +    if (status != PEP_STATUS_OK)
  20.196 +        goto pEp_error;
  20.197 +    
  20.198 +    status = update_identity_recip_list(session, tmp_msg->bcc);
  20.199 +    if (status != PEP_STATUS_OK)
  20.200 +        goto pEp_error;
  20.201 +    
  20.202 +    // This isn't incoming, though... so we need to reverse the direction
  20.203 +    tmp_msg->dir = PEP_dir_outgoing;
  20.204 +    status = encrypt_message(session,
  20.205 +                             tmp_msg,
  20.206 +                             extra,
  20.207 +                             &enc_msg,
  20.208 +                             enc_format,
  20.209 +                             flags);
  20.210 +                             
  20.211 +    if (status != PEP_STATUS_OK)
  20.212 +        goto pEp_error;
  20.213 +
  20.214 +
  20.215 +    if (!enc_msg) {
  20.216 +        status = PEP_UNKNOWN_ERROR;
  20.217 +        goto pEp_error;
  20.218 +    }
  20.219 +
  20.220 +    status = _mime_encode_message_internal(enc_msg, false, mime_ciphertext, false);
  20.221 +
  20.222 +pEp_error:
  20.223 +    free_message(tmp_msg);
  20.224 +    free_message(enc_msg);
  20.225 +
  20.226 +    return status;
  20.227 +
  20.228 +}
  20.229 +
  20.230 +DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
  20.231 +    PEP_SESSION session,
  20.232 +    pEp_identity* target_id,
  20.233 +    const char *mimetext,
  20.234 +    size_t size,
  20.235 +    stringlist_t* extra,
  20.236 +    char** mime_ciphertext,
  20.237 +    PEP_enc_format enc_format,
  20.238 +    PEP_encrypt_flags_t flags
  20.239 +)
  20.240 +{
  20.241 +    PEP_STATUS status = PEP_STATUS_OK;
  20.242 +    message* tmp_msg = NULL;
  20.243 +    message* enc_msg = NULL;
  20.244 +
  20.245 +    status = mime_decode_message(mimetext, size, &tmp_msg);
  20.246 +    if (status != PEP_STATUS_OK)
  20.247 +        goto pEp_error;
  20.248 +
  20.249 +    // This isn't incoming, though... so we need to reverse the direction
  20.250 +    tmp_msg->dir = PEP_dir_outgoing;
  20.251 +    status = encrypt_message_for_self(session,
  20.252 +                                      target_id,
  20.253 +                                      tmp_msg,
  20.254 +                                      extra,
  20.255 +                                      &enc_msg,
  20.256 +                                      enc_format,
  20.257 +                                      flags);
  20.258 +    if (status != PEP_STATUS_OK)
  20.259 +        goto pEp_error;
  20.260 + 
  20.261 +    if (!enc_msg) {
  20.262 +        status = PEP_UNKNOWN_ERROR;
  20.263 +        goto pEp_error;
  20.264 +    }
  20.265 +
  20.266 +    status = mime_encode_message(enc_msg, false, mime_ciphertext);
  20.267 +
  20.268 +pEp_error:
  20.269 +    free_message(tmp_msg);
  20.270 +    free_message(enc_msg);
  20.271 +
  20.272 +    return status;
  20.273 +}
  20.274 +#else
  20.275 +const int the_answer_my_friend = 42;
  20.276 +#endif
  20.277 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/aux_mime_msg.h	Fri May 17 17:30:57 2019 +0200
    21.3 @@ -0,0 +1,150 @@
    21.4 +// This file is under GNU General Public License 3.0
    21.5 +// see LICENSE.txt
    21.6 +
    21.7 +#pragma once
    21.8 +
    21.9 +#ifdef ENIGMAIL_MAY_USE_THIS
   21.10 +
   21.11 +#include "pEpEngine.h"
   21.12 +#include "keymanagement.h"
   21.13 +#include "message.h"
   21.14 +#include "cryptotech.h"
   21.15 +
   21.16 +#ifdef __cplusplus
   21.17 +extern "C" {
   21.18 +#endif
   21.19 +
   21.20 +// MIME_encrypt_message() - encrypt a MIME message, with MIME output
   21.21 +//
   21.22 +//  parameters:
   21.23 +//      session (in)            session handle
   21.24 +//      mimetext (in)           MIME encoded text to encrypt
   21.25 +//      size (in)               size of input mime text
   21.26 +//      extra (in)              extra keys for encryption
   21.27 +//      mime_ciphertext (out)   encrypted, encoded message
   21.28 +//      enc_format (in)         encrypted format
   21.29 +//      flags (in)              flags to set special encryption features
   21.30 +//
   21.31 +//  return value:
   21.32 +//      PEP_STATUS_OK           if everything worked
   21.33 +//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
   21.34 +//      PEP_CANNOT_CREATE_TEMP_FILE
   21.35 +//                              if there are issues with temp files; in
   21.36 +//                              this case errno will contain the underlying
   21.37 +//                              error
   21.38 +//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
   21.39 +//
   21.40 +//  caveat:
   21.41 +//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
   21.42 +//      will remain in the ownership of the caller
   21.43 +DYNAMIC_API PEP_STATUS MIME_encrypt_message(
   21.44 +    PEP_SESSION session,
   21.45 +    const char *mimetext,
   21.46 +    size_t size,
   21.47 +    stringlist_t* extra,
   21.48 +    char** mime_ciphertext,
   21.49 +    PEP_enc_format enc_format,
   21.50 +    PEP_encrypt_flags_t flags
   21.51 +);
   21.52 +
   21.53 +
   21.54 +// MIME_encrypt_message_for_self() - encrypt MIME message for user's identity only,
   21.55 +//                              ignoring recipients and other identities from
   21.56 +//                              the message, with MIME output
   21.57 +//  parameters:
   21.58 +//      session (in)            session handle
   21.59 +//      target_id (in)          self identity this message should be encrypted for
   21.60 +//      mimetext (in)           MIME encoded text to encrypt
   21.61 +//      size (in)               size of input mime text
   21.62 +//      extra (in)              extra keys for encryption
   21.63 +//      mime_ciphertext (out)   encrypted, encoded message
   21.64 +//      enc_format (in)         encrypted format
   21.65 +//      flags (in)              flags to set special encryption features
   21.66 +//
   21.67 +//  return value:
   21.68 +//      PEP_STATUS_OK           if everything worked
   21.69 +//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
   21.70 +//      PEP_CANNOT_CREATE_TEMP_FILE
   21.71 +//                              if there are issues with temp files; in
   21.72 +//                              this case errno will contain the underlying
   21.73 +//                              error
   21.74 +//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
   21.75 +//
   21.76 +//  caveat:
   21.77 +//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
   21.78 +//      will remain in the ownership of the caller
   21.79 +DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
   21.80 +    PEP_SESSION session,
   21.81 +    pEp_identity* target_id,
   21.82 +    const char *mimetext,
   21.83 +    size_t size,
   21.84 +    stringlist_t* extra,
   21.85 +    char** mime_ciphertext,
   21.86 +    PEP_enc_format enc_format,
   21.87 +    PEP_encrypt_flags_t flags
   21.88 +);
   21.89 +
   21.90 +
   21.91 +
   21.92 +// MIME_decrypt_message() - decrypt a MIME message, with MIME output
   21.93 +//
   21.94 +//  parameters:
   21.95 +//      session (in)            session handle
   21.96 +//      mimetext (in)           MIME encoded text to decrypt
   21.97 +//      size (in)               size of mime text to decode (in order to decrypt)
   21.98 +//      mime_plaintext (out)    decrypted, encoded message
   21.99 +//      keylist (inout)         in: stringlist with additional keyids for reencryption if needed
  21.100 +//                                  (will be freed and replaced with output keylist)
  21.101 +//                              out: stringlist with keyids
  21.102 +//      rating (out)            rating for the message
  21.103 +//      flags (inout)           flags to signal special decryption features (see below)
  21.104 +//      modified_src (out)      modified source string, if decrypt had reason to change it
  21.105 +//
  21.106 +//  return value:
  21.107 +//      decrypt status          if everything worked with MIME encode/decode, 
  21.108 +//                              the status of the decryption is returned 
  21.109 +//                              (PEP_STATUS_OK or decryption error status)
  21.110 +//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
  21.111 +//      PEP_CANNOT_CREATE_TEMP_FILE
  21.112 +//                              if there are issues with temp files; in
  21.113 +//                              this case errno will contain the underlying
  21.114 +//                              error
  21.115 +//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
  21.116 +//
  21.117 +//  flag values:
  21.118 +//      in:
  21.119 +//          PEP_decrypt_flag_untrusted_server
  21.120 +//              used to signal that decrypt function should engage in behaviour
  21.121 +//              specified for when the server storing the source is untrusted.
  21.122 +//      out:
  21.123 +//          PEP_decrypt_flag_own_private_key
  21.124 +//              private key was imported for one of our addresses (NOT trusted
  21.125 +//              or set to be used - handshake/trust is required for that)
  21.126 +//          PEP_decrypt_flag_src_modified
  21.127 +//              indicates that the modified_src field should contain a modified
  21.128 +//              version of the source, at the moment always as a result of the
  21.129 +//              input flags. 
  21.130 +//          PEP_decrypt_flag_consume
  21.131 +//              used by sync 
  21.132 +//          PEP_decrypt_flag_ignore
  21.133 +//              used by sync 
  21.134 +// 
  21.135 +//  caveat:
  21.136 +//      the decrypted, encoded mime text will go to the ownership of the caller; mimetext
  21.137 +//      will remain in the ownership of the caller
  21.138 +DYNAMIC_API PEP_STATUS MIME_decrypt_message(
  21.139 +    PEP_SESSION session,
  21.140 +    const char *mimetext,
  21.141 +    size_t size,
  21.142 +    char** mime_plaintext,
  21.143 +    stringlist_t **keylist,
  21.144 +    PEP_rating *rating,
  21.145 +    PEP_decrypt_flags_t *flags,
  21.146 +    char** modified_src
  21.147 +);
  21.148 +
  21.149 +#ifdef __cplusplus
  21.150 +}
  21.151 +#endif
  21.152 +
  21.153 +#endif
    22.1 --- a/src/baseprotocol.c	Thu Mar 28 15:40:45 2019 +0100
    22.2 +++ b/src/baseprotocol.c	Fri May 17 17:30:57 2019 +0200
    22.3 @@ -9,7 +9,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      PEP_STATUS status = PEP_STATUS_OK;
   22.12 @@ -39,12 +39,12 @@
   22.13          assert(sign && sign_size);
   22.14  
   22.15          bl = bloblist_add(bl, sign, sign_size,
   22.16 -                "application/pEp.sign", "ignore_this_attachment.pEp");
   22.17 +                "application/pEp.sign", "electronic_signature.asc");
   22.18          if (!bl)
   22.19              goto enomem;
   22.20      }
   22.21  
   22.22 -    return PEP_STATUS_OK;
   22.23 +    return status;
   22.24  
   22.25  enomem:
   22.26      status = PEP_OUT_OF_MEMORY;
   22.27 @@ -59,7 +59,7 @@
   22.28          const pEp_identity *partner,
   22.29          char *payload,
   22.30          size_t size,
   22.31 -        char *fpr,
   22.32 +        const char *fpr,
   22.33          message **result
   22.34      )
   22.35  {
    23.1 --- a/src/baseprotocol.h	Thu Mar 28 15:40:45 2019 +0100
    23.2 +++ b/src/baseprotocol.h	Fri May 17 17:30:57 2019 +0200
    23.3 @@ -31,7 +31,7 @@
    23.4          message *msg,
    23.5          char *payload,
    23.6          size_t size,
    23.7 -        char *fpr
    23.8 +        const char *fpr
    23.9      );
   23.10  
   23.11  
   23.12 @@ -59,7 +59,7 @@
   23.13          const pEp_identity *partner,
   23.14          char *payload,
   23.15          size_t size,
   23.16 -        char *fpr,
   23.17 +        const char *fpr,
   23.18          message **result
   23.19      );
   23.20  
    24.1 --- a/src/cryptotech.c	Thu Mar 28 15:40:45 2019 +0100
    24.2 +++ b/src/cryptotech.c	Fri May 17 17:30:57 2019 +0200
    24.3 @@ -58,6 +58,7 @@
    24.4          cryptotech[PEP_crypt_OpenPGP].key_created = pgp_key_created;
    24.5          cryptotech[PEP_crypt_OpenPGP].contains_priv_key = pgp_contains_priv_key;
    24.6          cryptotech[PEP_crypt_OpenPGP].find_private_keys = pgp_find_private_keys;
    24.7 +        cryptotech[PEP_crypt_OpenPGP].config_cipher_suite = pgp_config_cipher_suite;
    24.8  #ifdef PGP_BINARY_PATH
    24.9          cryptotech[PEP_crypt_OpenPGP].binary_path = PGP_BINARY_PATH;
   24.10  #endif
    25.1 --- a/src/cryptotech.h	Thu Mar 28 15:40:45 2019 +0100
    25.2 +++ b/src/cryptotech.h	Fri May 17 17:30:57 2019 +0200
    25.3 @@ -95,6 +95,9 @@
    25.4      PEP_SESSION session, const char *pattern, stringlist_t **keylist
    25.5  );
    25.6  
    25.7 +typedef PEP_STATUS (*config_cipher_suite_t)(PEP_SESSION session,
    25.8 +        PEP_CIPHER_SUITE suite);
    25.9 +
   25.10  typedef struct _PEP_cryptotech_t {
   25.11      uint8_t id;
   25.12      // the following are default values; comm_type may vary with key length or b0rken crypto
   25.13 @@ -121,6 +124,7 @@
   25.14      binary_path_t binary_path;
   25.15      contains_priv_key_t contains_priv_key;
   25.16      find_private_keys_t find_private_keys;
   25.17 +    config_cipher_suite_t config_cipher_suite;
   25.18  } PEP_cryptotech_t;
   25.19  
   25.20  extern PEP_cryptotech_t cryptotech[PEP_crypt__count];
   25.21 @@ -129,3 +133,4 @@
   25.22  
   25.23  PEP_STATUS init_cryptotech(PEP_SESSION session, bool in_first);
   25.24  void release_cryptotech(PEP_SESSION session, bool out_last);
   25.25 +
    26.1 --- a/src/etpan_mime.c	Thu Mar 28 15:40:45 2019 +0100
    26.2 +++ b/src/etpan_mime.c	Fri May 17 17:30:57 2019 +0200
    26.3 @@ -6,7 +6,11 @@
    26.4  #include <libetpan/mailprivacy_tools.h>
    26.5  #endif
    26.6  
    26.7 +#include "pEp_internal.h"
    26.8  #include "platform.h"
    26.9 +#include "mime.h"
   26.10 +#include "wrappers.h"
   26.11 +#include "resource_id.h"
   26.12  
   26.13  #include <string.h>
   26.14  #include <stdlib.h>
   26.15 @@ -935,3 +939,1767 @@
   26.16      }    
   26.17      return false;
   26.18  }
   26.19 +
   26.20 +#define TMP_TEMPLATE "pEp.XXXXXXXXXXXXXXXXXXXX"
   26.21 +#ifdef _WIN32
   26.22 +#define PATH_SEP '\\'
   26.23 +#else
   26.24 +#define PATH_SEP '/'
   26.25 +#endif
   26.26 +
   26.27 +static PEP_STATUS interpret_MIME(struct mailmime *mime,
   26.28 +                                 message *msg);
   26.29 +
   26.30 +// This function was rewritten to use in-memory buffers instead of
   26.31 +// temporary files when the pgp/mime support was implemented for
   26.32 +// outlook, as the existing code did not work well on windows.
   26.33 +
   26.34 +static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
   26.35 +{
   26.36 +    PEP_STATUS status = PEP_STATUS_OK;
   26.37 +    int col;
   26.38 +    int r;
   26.39 +	size_t len;
   26.40 +	char* buf = NULL;
   26.41 +
   26.42 +	MMAPString* buffer;
   26.43 +
   26.44 +	buffer = mmap_string_new(NULL);
   26.45 +	if (buffer == NULL)
   26.46 +		goto enomem;
   26.47 +	
   26.48 +	col = 0;
   26.49 +	r = mailmime_write_mem(buffer, &col, mime);
   26.50 +	assert(r == MAILIMF_NO_ERROR);
   26.51 +	if (r == MAILIMF_ERROR_MEMORY)
   26.52 +		goto enomem;
   26.53 +	else if (r != MAILIMF_NO_ERROR)
   26.54 +		goto err_file;
   26.55 +
   26.56 +	// we overallocate by 1 byte, so we have a terminating 0.
   26.57 +	len = buffer->len;
   26.58 +	buf = calloc(len + 1, 1);
   26.59 +	if (buf == NULL)
   26.60 +		goto enomem;
   26.61 +
   26.62 +	memcpy(buf, buffer->str, len);
   26.63 +	mmap_string_free(buffer);
   26.64 +
   26.65 +    *mimetext = buf;
   26.66 +    return PEP_STATUS_OK;
   26.67 +
   26.68 +err_file:
   26.69 +    status = PEP_CANNOT_CREATE_TEMP_FILE;
   26.70 +    goto pEp_error;
   26.71 +
   26.72 +enomem:
   26.73 +    status = PEP_OUT_OF_MEMORY;
   26.74 +
   26.75 +pEp_error:
   26.76 +	if (buffer)
   26.77 +		mmap_string_free(buffer);
   26.78 +	if (buf)
   26.79 +		free(buf);
   26.80 +    return status;
   26.81 +}
   26.82 +
   26.83 +static PEP_STATUS mime_attachment(
   26.84 +        bloblist_t *blob,
   26.85 +        struct mailmime **result,
   26.86 +        bool transport_encode
   26.87 +    )
   26.88 +{
   26.89 +    PEP_STATUS status = PEP_STATUS_OK;
   26.90 +    struct mailmime * mime = NULL;
   26.91 +    char * mime_type;
   26.92 +    assert(blob);
   26.93 +    assert(result);
   26.94 +
   26.95 +    *result = NULL;
   26.96 +
   26.97 +// TODO: It seems the pEp COM server adapter sends an empty string here,
   26.98 +// which leads to a crash later. Thus, we workaround here by treating an
   26.99 +// empty string as NULL. We need to check whether the bug really is here,
  26.100 +// or the pEp COM server adapter needs to be changed.
  26.101 +    if (blob->mime_type == NULL || blob->mime_type[0] == '\0')
  26.102 +        mime_type = "application/octet-stream";
  26.103 +    else
  26.104 +        mime_type = blob->mime_type;
  26.105 +
  26.106 +    pEp_rid_list_t* resource = parse_uri(blob->filename);
  26.107 +
  26.108 +    bool already_ascii = !(must_chunk_be_encoded(blob->value, blob->size, true));
  26.109 +
  26.110 +    mime = get_file_part(resource, mime_type, blob->value, blob->size, 
  26.111 +                          (already_ascii ? false : transport_encode));
  26.112 +    free_rid_list(resource);
  26.113 +    
  26.114 +    assert(mime);
  26.115 +    if (mime == NULL)
  26.116 +        goto enomem;
  26.117 +
  26.118 +    *result = mime;
  26.119 +    return PEP_STATUS_OK;
  26.120 +
  26.121 +enomem:
  26.122 +    status = PEP_OUT_OF_MEMORY;
  26.123 +
  26.124 +    if (mime)
  26.125 +        mailmime_free(mime);
  26.126 +
  26.127 +    return status;
  26.128 +}
  26.129 +
  26.130 +static PEP_STATUS mime_html_text(
  26.131 +        const char *plaintext,
  26.132 +        const char *htmltext,
  26.133 +        bloblist_t *attachments,
  26.134 +        struct mailmime **result,
  26.135 +        bool transport_encode
  26.136 +    )
  26.137 +{
  26.138 +    PEP_STATUS status = PEP_STATUS_OK;
  26.139 +    struct mailmime * top_level_html_mime = NULL;
  26.140 +    struct mailmime * mime = NULL;
  26.141 +    struct mailmime * submime = NULL;
  26.142 +    int r;
  26.143 +
  26.144 +    assert(plaintext);
  26.145 +    assert(htmltext);
  26.146 +    assert(result);
  26.147 +
  26.148 +    *result = NULL;
  26.149 +
  26.150 +    mime = part_multiple_new("multipart/alternative");
  26.151 +    assert(mime);
  26.152 +    if (mime == NULL)
  26.153 +        goto enomem;
  26.154 +
  26.155 +    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
  26.156 +    
  26.157 +    int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  26.158 +    submime = get_text_part(NULL, "text/plain", plaintext, strlen(plaintext),
  26.159 +            encoding_type);
  26.160 +    free_rid_list(resource);
  26.161 +    resource = NULL;
  26.162 +    
  26.163 +    assert(submime);
  26.164 +    if (submime == NULL)
  26.165 +        goto enomem;
  26.166 +
  26.167 +    r = mailmime_smart_add_part(mime, submime);
  26.168 +    assert(r == MAILIMF_NO_ERROR);
  26.169 +    if (r == MAILIMF_ERROR_MEMORY) {
  26.170 +        goto enomem;
  26.171 +    }
  26.172 +    else {
  26.173 +        // mailmime_smart_add_part() takes ownership of submime
  26.174 +        submime = NULL;
  26.175 +    }
  26.176 +
  26.177 +    bool inlined_attachments = false;
  26.178 +    
  26.179 +    bloblist_t* traversal_ptr = attachments;
  26.180 +    
  26.181 +    while (traversal_ptr) {
  26.182 +        if (traversal_ptr->disposition == PEP_CONTENT_DISP_INLINE) {
  26.183 +            inlined_attachments = true;
  26.184 +            break;
  26.185 +        }
  26.186 +        traversal_ptr = traversal_ptr->next;
  26.187 +    }
  26.188 +
  26.189 +    if (inlined_attachments) {
  26.190 +        /* Noooooo... dirk, why do you do this to me? */
  26.191 +        submime = part_multiple_new("multipart/related");
  26.192 +        assert(submime);
  26.193 +        if (submime == NULL)
  26.194 +            goto enomem;
  26.195 +
  26.196 +        top_level_html_mime = submime;
  26.197 +        
  26.198 +        r = mailmime_smart_add_part(mime, top_level_html_mime);
  26.199 +        assert(r == MAILIMF_NO_ERROR);
  26.200 +        if (r == MAILIMF_ERROR_MEMORY) {
  26.201 +            goto enomem;
  26.202 +        }
  26.203 +        else {
  26.204 +            // mailmime_smart_add_part() takes ownership of submime
  26.205 +            submime = NULL;
  26.206 +        }
  26.207 +    }
  26.208 +    else {
  26.209 +        top_level_html_mime = mime;
  26.210 +    }
  26.211 +
  26.212 +//    resource = new_rid_node(PEP_RID_FILENAME, "msg.html");
  26.213 +    submime = get_text_part(NULL, "text/html", htmltext, strlen(htmltext),
  26.214 +            encoding_type);
  26.215 +    free_rid_list(resource);
  26.216 +    resource = NULL;
  26.217 +    
  26.218 +    assert(submime);
  26.219 +    if (submime == NULL)
  26.220 +        goto enomem;
  26.221 +
  26.222 +    r = mailmime_smart_add_part(top_level_html_mime, submime);
  26.223 +    assert(r == MAILIMF_NO_ERROR);
  26.224 +    if (r == MAILIMF_ERROR_MEMORY)
  26.225 +        goto enomem;
  26.226 +    else {
  26.227 +        // mailmime_smart_add_part() takes ownership of submime
  26.228 +        submime = NULL;
  26.229 +    }
  26.230 +
  26.231 +    bloblist_t *_a;
  26.232 +    for (_a = attachments; _a != NULL; _a = _a->next) {
  26.233 +        if (_a->disposition != PEP_CONTENT_DISP_INLINE)
  26.234 +            continue;
  26.235 +        status = mime_attachment(_a, &submime, transport_encode);
  26.236 +        if (status != PEP_STATUS_OK)
  26.237 +            return PEP_UNKNOWN_ERROR; // FIXME
  26.238 +
  26.239 +        r = mailmime_smart_add_part(top_level_html_mime, submime);
  26.240 +        assert(r == MAILIMF_NO_ERROR);
  26.241 +        if (r == MAILIMF_ERROR_MEMORY) {
  26.242 +            goto enomem;
  26.243 +        }
  26.244 +        else {
  26.245 +            // mailmime_smart_add_part() takes ownership of submime
  26.246 +            submime = NULL;
  26.247 +        }
  26.248 +    }
  26.249 +
  26.250 +    *result = mime;
  26.251 +    return PEP_STATUS_OK;
  26.252 +
  26.253 +enomem:
  26.254 +    status = PEP_OUT_OF_MEMORY;
  26.255 +
  26.256 +    if (mime)
  26.257 +        mailmime_free(mime);
  26.258 +
  26.259 +    if (submime)
  26.260 +        mailmime_free(submime);
  26.261 +
  26.262 +    return status;
  26.263 +}
  26.264 +
  26.265 +
  26.266 +// FIXME: maybe need to add transport_encode field here
  26.267 +static struct mailimf_mailbox * identity_to_mailbox(const pEp_identity *ident)
  26.268 +{
  26.269 +    char *_username = NULL;
  26.270 +    struct mailimf_mailbox *mb;
  26.271 +
  26.272 +    if (!ident->username)
  26.273 +        _username = strdup("");
  26.274 +    else
  26.275 +        _username = must_field_value_be_encoded(ident->username) ?
  26.276 +                    mailmime_encode_subject_header("utf-8", ident->username, 0) : 
  26.277 +                    strdup(ident->username);
  26.278 +                  
  26.279 +    assert(_username);
  26.280 +    if (_username == NULL)
  26.281 +        goto enomem;
  26.282 +
  26.283 +    mb = mailbox_from_string(_username, ident->address);
  26.284 +    if (mb == NULL)
  26.285 +        goto enomem;
  26.286 +
  26.287 +    free(_username);
  26.288 +    _username = NULL;
  26.289 +
  26.290 +    return mb;
  26.291 +
  26.292 +enomem:
  26.293 +    free(_username);
  26.294 +    return NULL;
  26.295 +}
  26.296 +
  26.297 +static struct mailimf_mailbox_list * identity_to_mbl(
  26.298 +        const pEp_identity *ident)
  26.299 +{
  26.300 +    struct mailimf_mailbox_list *mbl = NULL;
  26.301 +    struct mailimf_mailbox *mb = NULL;
  26.302 +    clist *list = NULL;
  26.303 +    int r;
  26.304 +
  26.305 +    assert(ident);
  26.306 +
  26.307 +    list = clist_new();
  26.308 +    if (list == NULL)
  26.309 +        goto enomem;
  26.310 +
  26.311 +    mb = identity_to_mailbox(ident);
  26.312 +    if (mb == NULL)
  26.313 +        goto enomem;
  26.314 +
  26.315 +    r = clist_append(list, mb);
  26.316 +    if (r)
  26.317 +        goto enomem;
  26.318 +
  26.319 +    mbl = mailimf_mailbox_list_new(list);
  26.320 +    if (mbl == NULL)
  26.321 +        goto enomem;
  26.322 +
  26.323 +    return mbl;
  26.324 +
  26.325 +enomem:
  26.326 +    if (mb)
  26.327 +        mailimf_mailbox_free(mb);
  26.328 +
  26.329 +    if (list)
  26.330 +        clist_free(list);
  26.331 +
  26.332 +    return NULL;
  26.333 +}
  26.334 +
  26.335 +static struct mailimf_address_list * identity_list_to_mal(identity_list *il)
  26.336 +{
  26.337 +    struct mailimf_address_list *mal = NULL;
  26.338 +    struct mailimf_mailbox *mb = NULL;
  26.339 +    struct mailimf_address * addr = NULL;
  26.340 +    clist *list = NULL;
  26.341 +    int r;
  26.342 +
  26.343 +    assert(il);
  26.344 +
  26.345 +    list = clist_new();
  26.346 +    if (list == NULL)
  26.347 +        goto enomem;
  26.348 +
  26.349 +    identity_list *_il;
  26.350 +    for (_il = il; _il && _il->ident; _il = _il->next) {
  26.351 +        mb = identity_to_mailbox(_il->ident);
  26.352 +        if (mb == NULL)
  26.353 +            goto enomem;
  26.354 +
  26.355 +        addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  26.356 +        if (addr == NULL)
  26.357 +            goto enomem;
  26.358 +        mb = NULL;
  26.359 +
  26.360 +        r = clist_append(list, addr);
  26.361 +        if (r)
  26.362 +            goto enomem;
  26.363 +        addr = NULL;
  26.364 +    }
  26.365 +    mal = mailimf_address_list_new(list);
  26.366 +    if (mal == NULL)
  26.367 +        goto enomem;
  26.368 +
  26.369 +    return mal;
  26.370 +
  26.371 +enomem:
  26.372 +    if (mb)
  26.373 +        mailimf_mailbox_free(mb);
  26.374 +
  26.375 +    if (addr)
  26.376 +        mailimf_address_free(addr);
  26.377 +
  26.378 +    if (list)
  26.379 +        clist_free(list);
  26.380 +
  26.381 +    return NULL;
  26.382 +}
  26.383 +
  26.384 +static clist * stringlist_to_clist(stringlist_t *sl, bool transport_encode)
  26.385 +{
  26.386 +    clist * cl = clist_new();
  26.387 +    assert(cl);
  26.388 +    if (cl == NULL)
  26.389 +        return NULL;
  26.390 +
  26.391 +    if (!sl || ((!sl->value || sl->value[0] == '\0') && sl->next == NULL))
  26.392 +        return cl;
  26.393 +        
  26.394 +    stringlist_t *_sl;
  26.395 +    for (_sl = sl; _sl; _sl = _sl->next) {
  26.396 +        int r;
  26.397 +        char * value = ((transport_encode && must_field_value_be_encoded(_sl->value)) ?
  26.398 +                        mailmime_encode_subject_header("utf-8", _sl->value, 0) :
  26.399 +                        strdup(_sl->value));
  26.400 +        assert(value);
  26.401 +        if (value == NULL) {
  26.402 +            clist_free(cl);
  26.403 +            return NULL;
  26.404 +        }
  26.405 +        r = clist_append(cl, value);
  26.406 +        assert(r == 0);
  26.407 +        if (r) {
  26.408 +            free(value);
  26.409 +            clist_free(cl);
  26.410 +            return NULL;
  26.411 +        }
  26.412 +    }
  26.413 +
  26.414 +    return cl;
  26.415 +}
  26.416 +
  26.417 +static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
  26.418 +{
  26.419 +    PEP_STATUS status = PEP_STATUS_OK;
  26.420 +    struct mailimf_fields * fields = NULL;
  26.421 +    int r;
  26.422 +    clist * fields_list = NULL;
  26.423 +    unsigned char pEpstr[] = PEP_SUBJ_STRING; // unsigned due to UTF-8 byte fun
  26.424 +#ifdef WIN32
  26.425 +    char* altstr = "pEp";
  26.426 +#else
  26.427 +    char* altstr = (char*)pEpstr;
  26.428 +#endif        
  26.429 +    char *subject = msg->shortmsg ? msg->shortmsg : altstr;
  26.430 +
  26.431 +    assert(msg);
  26.432 +    assert(result);
  26.433 +
  26.434 +    *result = NULL;
  26.435 +
  26.436 +    fields_list = clist_new();
  26.437 +    assert(fields_list);
  26.438 +    if (fields_list == NULL)
  26.439 +        goto enomem;
  26.440 +
  26.441 +    if (msg->id) {
  26.442 +        char *_msgid = strdup(msg->id);
  26.443 +        assert(_msgid);
  26.444 +        if (_msgid == NULL)
  26.445 +            goto enomem;
  26.446 +
  26.447 +        r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
  26.448 +                (_new_func_t) mailimf_message_id_new, _msgid);
  26.449 +        if (r) {
  26.450 +            free(_msgid);
  26.451 +            goto enomem;
  26.452 +        }
  26.453 +    }
  26.454 +
  26.455 +    if (msg->sent) {
  26.456 +        struct mailimf_date_time * dt = timestamp_to_etpantime(msg->sent);
  26.457 +        if (dt == NULL)
  26.458 +            goto enomem;
  26.459 +
  26.460 +        r = _append_field(fields_list, MAILIMF_FIELD_ORIG_DATE,
  26.461 +                (_new_func_t) mailimf_orig_date_new, dt);
  26.462 +        if (r) {
  26.463 +            mailimf_date_time_free(dt);
  26.464 +            goto enomem;
  26.465 +        }
  26.466 +        dt = NULL;
  26.467 +    }
  26.468 +
  26.469 +     if (msg->from) {
  26.470 +        struct mailimf_mailbox_list *from = identity_to_mbl(msg->from);
  26.471 +        if (from == NULL)
  26.472 +            goto enomem;
  26.473 +
  26.474 +        r = _append_field(fields_list, MAILIMF_FIELD_FROM,
  26.475 +                (_new_func_t) mailimf_from_new, from);
  26.476 +        if (r) {
  26.477 +            mailimf_mailbox_list_free(from);
  26.478 +            goto enomem;
  26.479 +        }
  26.480 +    }
  26.481 +
  26.482 +    if (msg->to) {
  26.483 +        struct mailimf_address_list *to = identity_list_to_mal(msg->to);
  26.484 +        if (to == NULL)
  26.485 +            goto enomem;
  26.486 +
  26.487 +        r = _append_field(fields_list, MAILIMF_FIELD_TO,
  26.488 +                (_new_func_t) mailimf_to_new, to);
  26.489 +        if (r) {
  26.490 +            mailimf_address_list_free(to);
  26.491 +            goto enomem;
  26.492 +        }
  26.493 +    }
  26.494 +
  26.495 +    char* _subject = NULL;
  26.496 +    if (!must_field_value_be_encoded(subject)) {
  26.497 +        _subject = strdup(subject);
  26.498 +        assert(_subject);
  26.499 +    }
  26.500 +    else {
  26.501 +        _subject = mailmime_encode_subject_header("utf-8", subject, 1);
  26.502 +    }
  26.503 +    if (_subject == NULL)
  26.504 +        goto enomem;
  26.505 +
  26.506 +    r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
  26.507 +            (_new_func_t) mailimf_subject_new, _subject);
  26.508 +    if (r) {
  26.509 +        free(_subject);
  26.510 +        goto enomem;
  26.511 +    }
  26.512 +
  26.513 +    if (msg->cc) {
  26.514 +        struct mailimf_address_list *cc = identity_list_to_mal(msg->cc);
  26.515 +        if (cc == NULL)
  26.516 +            goto enomem;
  26.517 +
  26.518 +        r = _append_field(fields_list, MAILIMF_FIELD_CC,
  26.519 +                (_new_func_t) mailimf_cc_new, cc);
  26.520 +        if (r) {
  26.521 +            mailimf_address_list_free(cc);
  26.522 +            goto enomem;
  26.523 +        }
  26.524 +    }
  26.525 +    
  26.526 +    if (msg->bcc) {
  26.527 +        struct mailimf_address_list *bcc = identity_list_to_mal(msg->bcc);
  26.528 +        if (bcc == NULL)
  26.529 +            goto enomem;
  26.530 +
  26.531 +        r = _append_field(fields_list, MAILIMF_FIELD_BCC,
  26.532 +                (_new_func_t) mailimf_bcc_new, bcc);
  26.533 +        if (r) {
  26.534 +            mailimf_address_list_free(bcc);
  26.535 +            goto enomem;
  26.536 +        }
  26.537 +    }
  26.538 +    
  26.539 +    if (msg->reply_to) {
  26.540 +        struct mailimf_address_list *reply_to = identity_list_to_mal(msg->reply_to);
  26.541 +        if (reply_to == NULL)
  26.542 +            goto enomem;
  26.543 +
  26.544 +        r = _append_field(fields_list, MAILIMF_FIELD_REPLY_TO,
  26.545 +                (_new_func_t) mailimf_reply_to_new, reply_to);
  26.546 +        if (r) {
  26.547 +            mailimf_address_list_free(reply_to);
  26.548 +            goto enomem;
  26.549 +        }
  26.550 +    }
  26.551 +
  26.552 +    if (msg->in_reply_to) {
  26.553 +        clist *in_reply_to = stringlist_to_clist(msg->in_reply_to, true);
  26.554 +        if (in_reply_to == NULL)
  26.555 +            goto enomem;
  26.556 +
  26.557 +        r = _append_field(fields_list, MAILIMF_FIELD_IN_REPLY_TO,
  26.558 +                (_new_func_t) mailimf_in_reply_to_new, in_reply_to);
  26.559 +        if (r) {
  26.560 +            clist_free(in_reply_to);
  26.561 +            goto enomem;
  26.562 +        }
  26.563 +    }
  26.564 +
  26.565 +    if (msg->references) {
  26.566 +        clist *references = stringlist_to_clist(msg->references, true);
  26.567 +        if (references == NULL)
  26.568 +            goto enomem;
  26.569 +
  26.570 +        r = _append_field(fields_list, MAILIMF_FIELD_REFERENCES,
  26.571 +                (_new_func_t) mailimf_references_new, references);
  26.572 +        if (r) {
  26.573 +            clist_free(references);
  26.574 +            goto enomem;
  26.575 +        }
  26.576 +    }
  26.577 +
  26.578 +    if (msg->keywords) {
  26.579 +        clist *keywords = stringlist_to_clist(msg->keywords, true);
  26.580 +        if (keywords == NULL)
  26.581 +            goto enomem;
  26.582 +
  26.583 +        r = _append_field(fields_list, MAILIMF_FIELD_KEYWORDS,
  26.584 +                (_new_func_t) mailimf_keywords_new, keywords);
  26.585 +        if (r) {
  26.586 +            clist_free(keywords);
  26.587 +            goto enomem;
  26.588 +        }
  26.589 +    }
  26.590 +
  26.591 +    if (msg->comments) {
  26.592 +        char *comments = NULL;
  26.593 +        if (!must_field_value_be_encoded(msg->comments)) {
  26.594 +            comments = strdup(msg->comments);
  26.595 +            assert(comments);
  26.596 +        }
  26.597 +        else  {
  26.598 +            comments = mailmime_encode_subject_header("utf-8", msg->comments, 0);
  26.599 +        }
  26.600 +        if (comments == NULL)
  26.601 +            goto enomem;
  26.602 +
  26.603 +        r = _append_field(fields_list, MAILIMF_FIELD_COMMENTS,
  26.604 +                (_new_func_t) mailimf_comments_new, comments);
  26.605 +        if (r) {
  26.606 +            free(comments);
  26.607 +            goto enomem;
  26.608 +        }
  26.609 +    }
  26.610 +
  26.611 +    if (msg->opt_fields) {
  26.612 +        stringpair_list_t *_l;
  26.613 +        for (_l = msg->opt_fields; _l && _l->value; _l = _l->next) {
  26.614 +            char *key = _l->value->key;
  26.615 +            char *value = _l->value->value;
  26.616 +            if (key && value) {
  26.617 +                r = _append_optional_field(fields_list, key, value);
  26.618 +
  26.619 +                if (r)
  26.620 +                    goto enomem;
  26.621 +            }
  26.622 +        }
  26.623 +    }
  26.624 +
  26.625 +    fields = mailimf_fields_new(fields_list);
  26.626 +    assert(fields);
  26.627 +    if (fields == NULL)
  26.628 +        goto enomem;
  26.629 +
  26.630 +    *result = fields;
  26.631 +
  26.632 +    return PEP_STATUS_OK;
  26.633 +
  26.634 +enomem:
  26.635 +    status = PEP_OUT_OF_MEMORY;
  26.636 +
  26.637 +    if (fields_list)
  26.638 +        clist_free(fields_list);
  26.639 +
  26.640 +    if (fields)
  26.641 +        mailimf_fields_free(fields);
  26.642 +
  26.643 +    return status;
  26.644 +}
  26.645 +
  26.646 +static bool has_exceptional_extension(char* filename) {
  26.647 +    if (!filename)
  26.648 +        return false;
  26.649 +    int len = strlen(filename);
  26.650 +    if (len < 4)
  26.651 +        return false;
  26.652 +    char* ext_start = filename + (len - 4);
  26.653 +    if (strcmp(ext_start, ".pgp") == 0 || strcmp(ext_start, ".gpg") == 0 ||
  26.654 +        strcmp(ext_start, ".asc") == 0 || strcmp(ext_start, ".pEp") == 0)
  26.655 +        return true;
  26.656 +    return false;
  26.657 +}
  26.658 +
  26.659 +static pEp_rid_list_t* choose_resource_id(pEp_rid_list_t* rid_list) {
  26.660 +    pEp_rid_list_t* retval = rid_list;
  26.661 +    
  26.662 +    /* multiple elements - least common case */
  26.663 +    if (rid_list && rid_list->next) {
  26.664 +        pEp_rid_list_t* rid_list_curr = rid_list;
  26.665 +        retval = rid_list; 
  26.666 +        
  26.667 +        while (rid_list_curr) {
  26.668 +            pEp_resource_id_type rid_type = rid_list_curr->rid_type;
  26.669 +            if (rid_type == PEP_RID_CID)
  26.670 +                retval = rid_list_curr;
  26.671 +            else if (rid_type == PEP_RID_FILENAME && has_exceptional_extension(rid_list_curr->rid))
  26.672 +                return rid_list_curr;
  26.673 +            rid_list_curr = rid_list_curr->next;
  26.674 +        }
  26.675 +    } 
  26.676 +    return retval;
  26.677 +}
  26.678 +
  26.679 +// static void split_inlined_and_attached(bloblist_t** inlined, bloblist_t** attached) {
  26.680 +//     bloblist_t** curr_pp = attached;
  26.681 +//     bloblist_t* curr = *curr_pp;
  26.682 +//     
  26.683 +//     bloblist_t* inline_ret = NULL;
  26.684 +//     bloblist_t** inline_curr_pp = &inline_ret;
  26.685 +//     
  26.686 +//     bloblist_t* att_ret = NULL;
  26.687 +//     bloblist_t** att_curr_pp = &att_ret;
  26.688 +//     
  26.689 +//     while (curr) {
  26.690 +//         if (curr->disposition == PEP_CONTENT_DISP_INLINE) {
  26.691 +//             *inline_curr_pp = curr;
  26.692 +//             inline_curr_pp = &(curr->next);
  26.693 +//         }
  26.694 +//         else {
  26.695 +//             *att_curr_pp = curr;
  26.696 +//             att_curr_pp = &(curr->next);            
  26.697 +//         }
  26.698 +//         *curr_pp = curr->next;
  26.699 +//         curr->next = NULL;
  26.700 +//         curr = *curr_pp;
  26.701 +//     }
  26.702 +//     
  26.703 +//     *inlined = inline_ret;
  26.704 +//     *attached = att_ret;
  26.705 +// }
  26.706 +
  26.707 +
  26.708 +static PEP_STATUS mime_encode_message_plain(
  26.709 +        const message *msg,
  26.710 +        bool omit_fields,
  26.711 +        struct mailmime **result,
  26.712 +        bool transport_encode
  26.713 +    )
  26.714 +{
  26.715 +    struct mailmime * mime = NULL;
  26.716 +    struct mailmime * submime = NULL;
  26.717 +    int r;
  26.718 +    PEP_STATUS status;
  26.719 +    //char *subject;
  26.720 +    char *plaintext;
  26.721 +    char *htmltext;
  26.722 +
  26.723 +    assert(msg);
  26.724 +    assert(result);
  26.725 +    
  26.726 +    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp";  // not used, yet.
  26.727 +    plaintext = (msg->longmsg) ? msg->longmsg : "";
  26.728 +    htmltext = msg->longmsg_formatted;
  26.729 +
  26.730 +    if (htmltext && (htmltext[0] != '\0')) {
  26.731 +        /* first, we need to strip out the inlined attachments to ensure this
  26.732 +           gets set up correctly */
  26.733 +           
  26.734 +        status = mime_html_text(plaintext, htmltext, msg->attachments, &mime,
  26.735 +                                transport_encode);
  26.736 +                
  26.737 +        if (status != PEP_STATUS_OK)
  26.738 +            goto pEp_error;
  26.739 +    }
  26.740 +    else {
  26.741 +        pEp_rid_list_t* resource = NULL;
  26.742 +        if (is_PGP_message_text(plaintext)) {
  26.743 +            resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
  26.744 +            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_7BIT : 0);
  26.745 +            mime = get_text_part(resource, "application/octet-stream", plaintext,
  26.746 +                    strlen(plaintext), encoding_type);
  26.747 +        }
  26.748 +        else {
  26.749 +            resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
  26.750 +            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  26.751 +            mime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
  26.752 +                    encoding_type);
  26.753 +        }
  26.754 +        free_rid_list(resource);
  26.755 +        
  26.756 +        assert(mime);
  26.757 +        if (mime == NULL)
  26.758 +            goto enomem;
  26.759 +    }
  26.760 +
  26.761 +    bool normal_attachments = false;
  26.762 +    
  26.763 +    bloblist_t* traversal_ptr = msg->attachments;
  26.764 +    
  26.765 +    while (traversal_ptr) {
  26.766 +        if (traversal_ptr->disposition != PEP_CONTENT_DISP_INLINE) {
  26.767 +            normal_attachments = true;
  26.768 +            break;
  26.769 +        }
  26.770 +        traversal_ptr = traversal_ptr->next;
  26.771 +    }
  26.772 +
  26.773 +    if (normal_attachments) {
  26.774 +        submime = mime;
  26.775 +        mime = part_multiple_new("multipart/mixed");
  26.776 +        assert(mime);
  26.777 +        if (mime == NULL)
  26.778 +            goto enomem;
  26.779 +
  26.780 +        r = mailmime_smart_add_part(mime, submime);
  26.781 +        assert(r == MAILIMF_NO_ERROR);
  26.782 +        if (r == MAILIMF_ERROR_MEMORY) {
  26.783 +            goto enomem;
  26.784 +        }
  26.785 +        else {
  26.786 +            // mailmime_smart_add_part() takes ownership of submime
  26.787 +            submime = NULL;
  26.788 +        }
  26.789 +
  26.790 +        bloblist_t *_a;
  26.791 +        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
  26.792 +
  26.793 +            if (_a->disposition == PEP_CONTENT_DISP_INLINE)
  26.794 +                continue;
  26.795 +
  26.796 +            status = mime_attachment(_a, &submime, transport_encode);
  26.797 +            if (status != PEP_STATUS_OK)
  26.798 +                goto pEp_error;
  26.799 +
  26.800 +            r = mailmime_smart_add_part(mime, submime);
  26.801 +            assert(r == MAILIMF_NO_ERROR);
  26.802 +            if (r == MAILIMF_ERROR_MEMORY) {
  26.803 +                goto enomem;
  26.804 +            }
  26.805 +            else {
  26.806 +                // mailmime_smart_add_part() takes ownership of submime
  26.807 +                submime = NULL;
  26.808 +            }
  26.809 +        }
  26.810 +    }
  26.811 +
  26.812 +    *result = mime;
  26.813 +    return PEP_STATUS_OK;
  26.814 +
  26.815 +enomem:
  26.816 +    status = PEP_OUT_OF_MEMORY;
  26.817 +
  26.818 +pEp_error:
  26.819 +    if (mime)
  26.820 +        mailmime_free(mime);
  26.821 +
  26.822 +    if (submime)
  26.823 +        mailmime_free(submime);
  26.824 +
  26.825 +    return status;
  26.826 +}
  26.827 +
  26.828 +static PEP_STATUS mime_encode_message_PGP_MIME(
  26.829 +        const message * msg,
  26.830 +        bool omit_fields,
  26.831 +        struct mailmime **result
  26.832 +    )
  26.833 +{
  26.834 +    struct mailmime * mime = NULL;
  26.835 +    struct mailmime * submime = NULL;
  26.836 +	struct mailmime_parameter * param;
  26.837 +    int r;
  26.838 +    PEP_STATUS status;
  26.839 +    char *plaintext;
  26.840 +    size_t plaintext_size;
  26.841 +
  26.842 +    assert(msg->attachments && msg->attachments->next &&
  26.843 +            msg->attachments->next->value);
  26.844 +
  26.845 +    plaintext = msg->attachments->next->value;
  26.846 +    plaintext_size = msg->attachments->next->size;
  26.847 +
  26.848 +    mime = part_multiple_new("multipart/encrypted");
  26.849 +    assert(mime);
  26.850 +    if (mime == NULL)
  26.851 +        goto enomem;
  26.852 +
  26.853 +    param = mailmime_param_new_with_data("protocol", "application/pgp-encrypted");
  26.854 +    clist_append(mime->mm_content_type->ct_parameters, param);
  26.855 +
  26.856 +    submime = get_pgp_encrypted_part();
  26.857 +    assert(submime);
  26.858 +    if (submime == NULL)
  26.859 +        goto enomem;
  26.860 +
  26.861 +    r = mailmime_smart_add_part(mime, submime);
  26.862 +    assert(r == MAILIMF_NO_ERROR);
  26.863 +    if (r == MAILIMF_ERROR_MEMORY) {
  26.864 +        goto enomem;
  26.865 +    }
  26.866 +    else {
  26.867 +        // mailmime_smart_add_part() takes ownership of submime
  26.868 +        submime = NULL;
  26.869 +    }
  26.870 +
  26.871 +    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
  26.872 +    submime = get_text_part(resource, "application/octet-stream", plaintext,
  26.873 +            plaintext_size, MAILMIME_MECHANISM_7BIT);
  26.874 +            
  26.875 +    free_rid_list(resource);
  26.876 +    
  26.877 +    assert(submime);
  26.878 +    if (submime == NULL)
  26.879 +        goto enomem;
  26.880 +
  26.881 +    r = mailmime_smart_add_part(mime, submime);
  26.882 +    assert(r == MAILIMF_NO_ERROR);
  26.883 +    if (r == MAILIMF_ERROR_MEMORY) {
  26.884 +        goto enomem;
  26.885 +    }
  26.886 +    else {
  26.887 +        // mailmime_smart_add_part() takes ownership of submime
  26.888 +        submime = NULL;
  26.889 +    }
  26.890 +
  26.891 +    *result = mime;
  26.892 +    return PEP_STATUS_OK;
  26.893 +
  26.894 +enomem:
  26.895 +    status = PEP_OUT_OF_MEMORY;
  26.896 +
  26.897 +    if (mime)
  26.898 +        mailmime_free(mime);
  26.899 +
  26.900 +    if (submime)
  26.901 +        mailmime_free(submime);
  26.902 +
  26.903 +    return status;
  26.904 +}
  26.905 +
  26.906 +PEP_STATUS _mime_encode_message_internal(
  26.907 +        const message * msg,
  26.908 +        bool omit_fields,
  26.909 +        char **mimetext,
  26.910 +        bool transport_encode
  26.911 +    )
  26.912 +{
  26.913 +    PEP_STATUS status = PEP_STATUS_OK;
  26.914 +    struct mailmime * msg_mime = NULL;
  26.915 +    struct mailmime * mime = NULL;
  26.916 +    struct mailimf_fields * fields = NULL;
  26.917 +    char *buf = NULL;
  26.918 +    int r;
  26.919 +
  26.920 +    assert(msg);
  26.921 +    assert(mimetext);
  26.922 +
  26.923 +    if (!(msg && mimetext))
  26.924 +        return PEP_ILLEGAL_VALUE;
  26.925 +
  26.926 +    *mimetext = NULL;
  26.927 +
  26.928 +    switch (msg->enc_format) {
  26.929 +        case PEP_enc_none:
  26.930 +            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
  26.931 +            break;
  26.932 +
  26.933 +        case PEP_enc_inline:
  26.934 +            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
  26.935 +            break;
  26.936 +
  26.937 +        case PEP_enc_S_MIME:
  26.938 +            NOT_IMPLEMENTED
  26.939 +                
  26.940 +        case PEP_enc_PGP_MIME:
  26.941 +            status = mime_encode_message_PGP_MIME(msg, omit_fields, &mime);
  26.942 +            break;
  26.943 +
  26.944 +        case PEP_enc_PEP:
  26.945 +            NOT_IMPLEMENTED
  26.946 +
  26.947 +        default:
  26.948 +            NOT_IMPLEMENTED
  26.949 +    }
  26.950 +
  26.951 +    if (status != PEP_STATUS_OK)
  26.952 +        goto pEp_error;
  26.953 +
  26.954 +    msg_mime = mailmime_new_message_data(NULL);
  26.955 +    assert(msg_mime);
  26.956 +    if (msg_mime == NULL)
  26.957 +        goto enomem;
  26.958 +
  26.959 +    r = mailmime_add_part(msg_mime, mime);
  26.960 +    if (r) {
  26.961 +        mailmime_free(mime);
  26.962 +        goto enomem;
  26.963 +    }
  26.964 +    mime = NULL;
  26.965 +
  26.966 +    if (!omit_fields) {
  26.967 +        status = build_fields(msg, &fields);
  26.968 +        if (status != PEP_STATUS_OK)
  26.969 +            goto pEp_error;
  26.970 +
  26.971 +        mailmime_set_imf_fields(msg_mime, fields);
  26.972 +    }
  26.973 +
  26.974 +    status = render_mime(msg_mime, &buf);
  26.975 +    if (status != PEP_STATUS_OK)
  26.976 +        goto pEp_error;
  26.977 +
  26.978 +    mailmime_free(msg_mime);
  26.979 +    *mimetext = buf;
  26.980 +
  26.981 +    return PEP_STATUS_OK;
  26.982 +
  26.983 +enomem:
  26.984 +    status = PEP_OUT_OF_MEMORY;
  26.985 +
  26.986 +pEp_error:
  26.987 +    if (msg_mime)
  26.988 +        mailmime_free(msg_mime);
  26.989 +    else
  26.990 +        if (mime)
  26.991 +            mailmime_free(mime);
  26.992 +
  26.993 +    return status;
  26.994 +}
  26.995 +
  26.996 +static pEp_identity *mailbox_to_identity(const struct mailimf_mailbox * mb)
  26.997 +{
  26.998 +    char *username = NULL;
  26.999 +
 26.1000 +    assert(mb);
 26.1001 +    assert(mb->mb_addr_spec);
 26.1002 +
 26.1003 +    if (mb->mb_addr_spec == NULL)
 26.1004 +        return NULL;
 26.1005 +
 26.1006 +    if (mb->mb_display_name) {
 26.1007 +        size_t index = 0;
 26.1008 +        const int r = mailmime_encoded_phrase_parse("utf-8", mb->mb_display_name,
 26.1009 +                strlen(mb->mb_display_name), &index, "utf-8", &username);
 26.1010 +        if (r)
 26.1011 +            goto enomem;
 26.1012 +    }
 26.1013 +
 26.1014 +    pEp_identity *ident = new_identity(mb->mb_addr_spec, NULL, NULL, username);
 26.1015 +    if (ident == NULL)
 26.1016 +        goto enomem;
 26.1017 +    free(username);
 26.1018 +
 26.1019 +    return ident;
 26.1020 +
 26.1021 +enomem:
 26.1022 +    free(username);
 26.1023 +    return NULL;
 26.1024 +}
 26.1025 +
 26.1026 +static pEp_identity * mbl_to_identity(const struct mailimf_mailbox_list * mbl)
 26.1027 +{
 26.1028 +    struct mailimf_mailbox * mb = clist_content(clist_begin(mbl->mb_list));
 26.1029 +    return mailbox_to_identity(mb);
 26.1030 +}
 26.1031 +
 26.1032 +static identity_list * mal_to_identity_list(
 26.1033 +        const struct mailimf_address_list *mal
 26.1034 +    )
 26.1035 +{
 26.1036 +    assert(mal);
 26.1037 +    clist *list = mal->ad_list;
 26.1038 +
 26.1039 +    identity_list *il = new_identity_list(NULL);
 26.1040 +    if (il == NULL)
 26.1041 +        goto enomem;
 26.1042 +
 26.1043 +    identity_list *_il = il;
 26.1044 +    for (clistiter *cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
 26.1045 +        pEp_identity *ident;
 26.1046 +
 26.1047 +        struct mailimf_address *addr = clist_content(cur);
 26.1048 +        switch(addr->ad_type) {
 26.1049 +            case MAILIMF_ADDRESS_MAILBOX:
 26.1050 +                ident = mailbox_to_identity(addr->ad_data.ad_mailbox);
 26.1051 +                if (ident == NULL)
 26.1052 +                    goto enomem;
 26.1053 +                _il = identity_list_add(_il, ident);
 26.1054 +                if (_il == NULL)
 26.1055 +                    goto enomem;
 26.1056 +                break;
 26.1057 +
 26.1058 +            case MAILIMF_ADDRESS_GROUP:
 26.1059 +                {
 26.1060 +                    struct mailimf_mailbox_list * mbl =
 26.1061 +                            addr->ad_data.ad_group->grp_mb_list;
 26.1062 +                    for (clistiter *cur2 = clist_begin(mbl->mb_list); cur2 != NULL;
 26.1063 +                            cur2 = clist_next(cur2)) {
 26.1064 +                        ident = mailbox_to_identity(clist_content(cur));
 26.1065 +                        if (ident == NULL)
 26.1066 +                            goto enomem;
 26.1067 +                        _il = identity_list_add(_il, ident);
 26.1068 +                        if (_il == NULL)
 26.1069 +                            goto enomem;
 26.1070 +                    }
 26.1071 +                }
 26.1072 +                break;
 26.1073 +
 26.1074 +            default:
 26.1075 +                assert(0);
 26.1076 +                goto enomem;
 26.1077 +        }
 26.1078 +    }
 26.1079 +
 26.1080 +    return il;
 26.1081 +
 26.1082 +enomem:
 26.1083 +    free_identity_list(il);
 26.1084 +    return NULL;
 26.1085 +}
 26.1086 +
 26.1087 +static stringlist_t * clist_to_stringlist(const clist *list)
 26.1088 +{
 26.1089 +    char *text = NULL;;
 26.1090 +    stringlist_t * sl = new_stringlist(NULL);
 26.1091 +    if (sl == NULL)
 26.1092 +        return NULL;
 26.1093 +
 26.1094 +    stringlist_t *_sl = sl;
 26.1095 +    for (clistiter *cur = clist_begin(list); cur != NULL; cur = clist_next(cur)) {
 26.1096 +        char *phrase = clist_content(cur);
 26.1097 +        size_t index = 0;
 26.1098 +        
 26.1099 +        const int r = mailmime_encoded_phrase_parse("utf-8", phrase, strlen(phrase),
 26.1100 +                &index, "utf-8", &text);
 26.1101 +        if (r)
 26.1102 +            goto enomem;
 26.1103 +
 26.1104 +        _sl = stringlist_add(_sl, text);
 26.1105 +        if (_sl == NULL)
 26.1106 +            goto enomem;
 26.1107 +
 26.1108 +        free(text);
 26.1109 +        text = NULL;
 26.1110 +    }
 26.1111 +
 26.1112 +    return sl;
 26.1113 +
 26.1114 +enomem:
 26.1115 +    free_stringlist(sl);
 26.1116 +    free(text);
 26.1117 +
 26.1118 +    return NULL;
 26.1119 +}
 26.1120 +
 26.1121 +static PEP_STATUS read_fields(message *msg, clist *fieldlist)
 26.1122 +{
 26.1123 +    PEP_STATUS status = PEP_STATUS_OK;
 26.1124 +    struct mailimf_field * _field;
 26.1125 +    clistiter *cur;
 26.1126 +    size_t index;
 26.1127 +    int r;
 26.1128 +    
 26.1129 +    stringpair_list_t *opt = msg->opt_fields;
 26.1130 +
 26.1131 +    if (!fieldlist)
 26.1132 +        return PEP_STATUS_OK;
 26.1133 +        
 26.1134 +    for (cur = clist_begin(fieldlist); cur != NULL; cur = clist_next(cur)) {
 26.1135 +        _field = clist_content(cur);
 26.1136 +
 26.1137 +        switch (_field->fld_type) {
 26.1138 +            case MAILIMF_FIELD_MESSAGE_ID:
 26.1139 +                {
 26.1140 +                    char * text = _field->fld_data.fld_message_id->mid_value;
 26.1141 +
 26.1142 +                    free(msg->id);
 26.1143 +                    index = 0;
 26.1144 +                    r = mailmime_encoded_phrase_parse("utf-8", text,
 26.1145 +                            strlen(text), &index, "utf-8", &msg->id);
 26.1146 +                    if (r)
 26.1147 +                        goto enomem;
 26.1148 +                }
 26.1149 +                break;
 26.1150 +
 26.1151 +            case MAILIMF_FIELD_SUBJECT:
 26.1152 +                {
 26.1153 +                    char * text = _field->fld_data.fld_subject->sbj_value;
 26.1154 +
 26.1155 +                    free(msg->shortmsg);
 26.1156 +                    index = 0;
 26.1157 +                    r = mailmime_encoded_phrase_parse("utf-8", text,
 26.1158 +                            strlen(text), &index, "utf-8", &msg->shortmsg);
 26.1159 +                    if (r)
 26.1160 +                        goto enomem;
 26.1161 +                }
 26.1162 +                break;
 26.1163 +
 26.1164 +            case MAILIMF_FIELD_ORIG_DATE:
 26.1165 +                {
 26.1166 +                    struct mailimf_date_time *date =
 26.1167 +                        _field->fld_data.fld_orig_date->dt_date_time;
 26.1168 +
 26.1169 +                    free_timestamp(msg->sent);
 26.1170 +                    msg->sent = etpantime_to_timestamp(date);
 26.1171 +                    if (msg->sent == NULL)
 26.1172 +                        goto enomem;
 26.1173 +                }
 26.1174 +                break;
 26.1175 +
 26.1176 +            case MAILIMF_FIELD_FROM:
 26.1177 +                {
 26.1178 +                    struct mailimf_mailbox_list *mbl =
 26.1179 +                            _field->fld_data.fld_from->frm_mb_list;
 26.1180 +                    pEp_identity *ident;
 26.1181 +
 26.1182 +                    ident = mbl_to_identity(mbl);
 26.1183 +                    if (ident == NULL)
 26.1184 +                        goto pEp_error;
 26.1185 +
 26.1186 +                    free_identity(msg->from);
 26.1187 +                    msg->from = ident;
 26.1188 +                }
 26.1189 +                break;
 26.1190 +
 26.1191 +            case MAILIMF_FIELD_TO:
 26.1192 +                {
 26.1193 +                    struct mailimf_address_list *mal =
 26.1194 +                            _field->fld_data.fld_to->to_addr_list;
 26.1195 +                    identity_list *il = mal_to_identity_list(mal);
 26.1196 +                    if (il == NULL)
 26.1197 +                        goto enomem;
 26.1198 +
 26.1199 +                    free_identity_list(msg->to);
 26.1200 +                    msg->to = il;
 26.1201 +                }
 26.1202 +                break;
 26.1203 +
 26.1204 +            case MAILIMF_FIELD_CC:
 26.1205 +                {
 26.1206 +                    struct mailimf_address_list *mal =
 26.1207 +                            _field->fld_data.fld_cc->cc_addr_list;
 26.1208 +                    identity_list *il = mal_to_identity_list(mal);
 26.1209 +                    if (il == NULL)
 26.1210 +                        goto enomem;
 26.1211 +
 26.1212 +                    free_identity_list(msg->cc);
 26.1213 +                    msg->cc = il;
 26.1214 +                }
 26.1215 +                break;
 26.1216 +
 26.1217 +            case MAILIMF_FIELD_BCC:
 26.1218 +                {
 26.1219 +                    struct mailimf_address_list *mal =
 26.1220 +                            _field->fld_data.fld_bcc->bcc_addr_list;
 26.1221 +                    identity_list *il = mal_to_identity_list(mal);
 26.1222 +                    if (il == NULL)
 26.1223 +                        goto enomem;
 26.1224 +
 26.1225 +                    free_identity_list(msg->bcc);
 26.1226 +                    msg->bcc = il;
 26.1227 +                }
 26.1228 +                break;
 26.1229 +
 26.1230 +            case MAILIMF_FIELD_REPLY_TO:
 26.1231 +                {
 26.1232 +                    struct mailimf_address_list *mal =
 26.1233 +                            _field->fld_data.fld_reply_to->rt_addr_list;
 26.1234 +                    identity_list *il = mal_to_identity_list(mal);
 26.1235 +                    if (il == NULL)
 26.1236 +                        goto enomem;
 26.1237 +
 26.1238 +                    free_identity_list(msg->reply_to);
 26.1239 +                    msg->reply_to = il;
 26.1240 +                }
 26.1241 +                break;
 26.1242 +
 26.1243 +            case MAILIMF_FIELD_IN_REPLY_TO:
 26.1244 +                {
 26.1245 +                    clist *list = _field->fld_data.fld_in_reply_to->mid_list;
 26.1246 +                    stringlist_t *sl = clist_to_stringlist(list);
 26.1247 +                    if (sl == NULL)
 26.1248 +                        goto enomem;
 26.1249 +
 26.1250 +                    free_stringlist(msg->in_reply_to);
 26.1251 +                    msg->in_reply_to = sl;
 26.1252 +                }
 26.1253 +                break;
 26.1254 +
 26.1255 +            case MAILIMF_FIELD_REFERENCES:
 26.1256 +                {
 26.1257 +                    clist *list = _field->fld_data.fld_references->mid_list;
 26.1258 +                    stringlist_t *sl = clist_to_stringlist(list);
 26.1259 +                    if (sl == NULL)
 26.1260 +                        goto enomem;
 26.1261 +
 26.1262 +                    free_stringlist(msg->references);
 26.1263 +                    msg->references = sl;
 26.1264 +                }
 26.1265 +                break;
 26.1266 +
 26.1267 +            case MAILIMF_FIELD_KEYWORDS:
 26.1268 +                {
 26.1269 +                    clist *list = _field->fld_data.fld_keywords->kw_list;
 26.1270 +                    stringlist_t *sl = clist_to_stringlist(list);
 26.1271 +                    if (sl == NULL)
 26.1272 +                        goto enomem;
 26.1273 +
 26.1274 +                    free_stringlist(msg->keywords);
 26.1275 +                    msg->keywords = sl;
 26.1276 +                }
 26.1277 +                break;
 26.1278 +
 26.1279 +            case MAILIMF_FIELD_COMMENTS:
 26.1280 +                {
 26.1281 +                    char * text = _field->fld_data.fld_comments->cm_value;
 26.1282 +
 26.1283 +                    free(msg->comments);
 26.1284 +                    index = 0;
 26.1285 +                    r = mailmime_encoded_phrase_parse("utf-8", text,
 26.1286 +                            strlen(text), &index, "utf-8", &msg->comments);
 26.1287 +                    if (r)
 26.1288 +                        goto enomem;
 26.1289 +                }
 26.1290 +                break;
 26.1291 +
 26.1292 +            case MAILIMF_FIELD_OPTIONAL_FIELD:
 26.1293 +                {
 26.1294 +                    char * name =
 26.1295 +                            _field->fld_data.fld_optional_field->fld_name;
 26.1296 +                    char * value =
 26.1297 +                            _field->fld_data.fld_optional_field->fld_value;
 26.1298 +                    char *_value;
 26.1299 +
 26.1300 +                    index = 0;
 26.1301 +                    r = mailmime_encoded_phrase_parse("utf-8", value,
 26.1302 +                            strlen(value), &index, "utf-8", &_value);
 26.1303 +                    if (r)
 26.1304 +                        goto enomem;
 26.1305 +
 26.1306 +                    stringpair_t *pair = new_stringpair(name, _value);
 26.1307 +                    if (pair == NULL)
 26.1308 +                        goto enomem;
 26.1309 +
 26.1310 +                    opt = stringpair_list_add(opt, pair);
 26.1311 +                    free(_value);
 26.1312 +                    if (opt == NULL)
 26.1313 +                        goto enomem;
 26.1314 +
 26.1315 +                    if (msg->opt_fields == NULL)
 26.1316 +                        msg->opt_fields = opt;
 26.1317 +                }
 26.1318 +                break;
 26.1319 +        }
 26.1320 +    }
 26.1321 +    
 26.1322 +    return PEP_STATUS_OK;
 26.1323 +
 26.1324 +enomem:
 26.1325 +    status = PEP_OUT_OF_MEMORY;
 26.1326 +
 26.1327 +pEp_error:
 26.1328 +    return status;
 26.1329 +}
 26.1330 +
 26.1331 +static PEP_STATUS interpret_body(struct mailmime *part, char **longmsg, size_t *size)
 26.1332 +{
 26.1333 +    const char *text;
 26.1334 +    char *_longmsg;
 26.1335 +    size_t length;
 26.1336 +    size_t _size;
 26.1337 +    size_t index;
 26.1338 +    char *type = NULL;
 26.1339 +    char *charset = NULL;
 26.1340 +
 26.1341 +    assert(part);
 26.1342 +    assert(longmsg);
 26.1343 +
 26.1344 +    *longmsg = NULL;
 26.1345 +    if (size)
 26.1346 +        *size = 0;
 26.1347 +
 26.1348 +    if (part->mm_body == NULL)
 26.1349 +        return PEP_ILLEGAL_VALUE;
 26.1350 +
 26.1351 +    text = part->mm_body-> dt_data.dt_text.dt_data;
 26.1352 +    if (text == NULL)
 26.1353 +        return PEP_ILLEGAL_VALUE;
 26.1354 +
 26.1355 +    length = part->mm_body->dt_data.dt_text.dt_length;
 26.1356 +
 26.1357 +    if (part->mm_body->dt_encoded) {
 26.1358 +        int code = part->mm_body->dt_encoding;
 26.1359 +        index = 0;
 26.1360 +        int r = mailmime_part_parse(text, length, &index, code, &_longmsg, &_size);
 26.1361 +        switch (r) {
 26.1362 +            case MAILIMF_NO_ERROR:
 26.1363 +                break;
 26.1364 +            case MAILIMF_ERROR_MEMORY:
 26.1365 +                return PEP_OUT_OF_MEMORY;
 26.1366 +            default:
 26.1367 +                return PEP_ILLEGAL_VALUE;
 26.1368 +        }
 26.1369 +    }
 26.1370 +    else {
 26.1371 +        _size = length + 1;
 26.1372 +        _longmsg = strndup(text, length);
 26.1373 +        if (_longmsg == NULL)
 26.1374 +            return PEP_OUT_OF_MEMORY;
 26.1375 +    }
 26.1376 +
 26.1377 +    if (part->mm_content_type) {
 26.1378 +        if (_get_content_type(part->mm_content_type, &type, &charset) == 0) {
 26.1379 +            if (charset && strncasecmp(charset, "utf-8", 5) != 0) {
 26.1380 +                char * _text;
 26.1381 +                int r = charconv("utf-8", charset, _longmsg, _size, &_text);
 26.1382 +                switch (r) {
 26.1383 +                    case MAILIMF_NO_ERROR:
 26.1384 +                        break;
 26.1385 +                    case MAILIMF_ERROR_MEMORY:
 26.1386 +                        return PEP_OUT_OF_MEMORY;
 26.1387 +                    default:
 26.1388 +                        return PEP_ILLEGAL_VALUE;
 26.1389 +                }
 26.1390 +                free(_longmsg);
 26.1391 +                _longmsg = _text;
 26.1392 +            }
 26.1393 +        }
 26.1394 +    }
 26.1395 +    // FIXME: KG - we now have the text we want.
 26.1396 +    // Now we need to strip sigs and process them if they are there..
 26.1397 +    
 26.1398 +
 26.1399 +    *longmsg = _longmsg;
 26.1400 +    if (size)
 26.1401 +        *size = _size;
 26.1402 +
 26.1403 +    return PEP_STATUS_OK;
 26.1404 +}
 26.1405 +
 26.1406 +// THIS IS A BEST-EFFORT ONLY FUNCTION, AND WE ARE NOT DOING MORE THAN THE
 26.1407 +// SUBJECT FOR NOW.
 26.1408 +static PEP_STATUS interpret_protected_headers(
 26.1409 +        struct mailmime* mime, 
 26.1410 +        message* msg
 26.1411 +    )
 26.1412 +{
 26.1413 +    // N.B. this is *very much* enigmail output specific, and right now,
 26.1414 +    // we only care about subject replacement.
 26.1415 +    const char* header_string = "Content-Type: text/rfc822-headers; protected-headers=\"v1\"\nContent-Disposition: inline\n\n";
 26.1416 +    size_t content_length = mime->mm_length;
 26.1417 +    size_t header_strlen = strlen(header_string);
 26.1418 +    if (header_strlen < content_length) {
 26.1419 +        const char* headerblock = mime->mm_mime_start;
 26.1420 +        size_t subject_len = 0;
 26.1421 +        headerblock = strstr(headerblock, header_string);
 26.1422 +        if (headerblock) {
 26.1423 +            const char* subj_start = "Subject: ";
 26.1424 +            headerblock = strstr(headerblock, subj_start);
 26.1425 +            if (headerblock) {
 26.1426 +                size_t subj_len = strlen(subj_start);
 26.1427 +                headerblock += subj_len;
 26.1428 +                char* end_pt = strstr(headerblock, "\n");
 26.1429 +                if (end_pt) {
 26.1430 +                    if (end_pt != mime->mm_mime_start && *(end_pt - 1) == '\r')
 26.1431 +                        end_pt--;
 26.1432 +                    subject_len = end_pt - headerblock;
 26.1433 +                    char* new_subj = (char*)calloc(subject_len + 1, 1);
 26.1434 +                    if (new_subj) {
 26.1435 +                        strlcpy(new_subj, headerblock, subject_len + 1);
 26.1436 +                        free(msg->shortmsg);
 26.1437 +                        msg->shortmsg = new_subj;
 26.1438 +                    }    
 26.1439 +                } // if there's no endpoint, there's something wrong here so we ignore all
 26.1440 +                  // This is best effort.
 26.1441 +            }
 26.1442 +        }
 26.1443 +    }
 26.1444 +    return PEP_STATUS_OK;
 26.1445 +}
 26.1446 +
 26.1447 +// ONLY for main part!!!
 26.1448 +static PEP_STATUS process_multipart_related(struct mailmime *mime,
 26.1449 +                                            message *msg) {
 26.1450 +    PEP_STATUS status = PEP_STATUS_OK;
 26.1451 +
 26.1452 +    assert(mime);
 26.1453 +    assert(msg);
 26.1454 +
 26.1455 +    clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;                                                
 26.1456 +
 26.1457 +    if (partlist == NULL)
 26.1458 +        return PEP_ILLEGAL_VALUE;
 26.1459 +
 26.1460 +    clistiter *cur = clist_begin(partlist);
 26.1461 +    struct mailmime *part = clist_content(cur);
 26.1462 +    
 26.1463 +    if (part == NULL)
 26.1464 +        return PEP_ILLEGAL_VALUE;
 26.1465 +
 26.1466 +    struct mailmime_content *content = part->mm_content_type;    
 26.1467 +    assert(content);
 26.1468 +    
 26.1469 +    if (content == NULL)
 26.1470 +        return PEP_ILLEGAL_VALUE;
 26.1471 +
 26.1472 +    if (_is_text_part(content, "html")) {
 26.1473 +        status = interpret_body(part, &msg->longmsg_formatted,
 26.1474 +                NULL);
 26.1475 +        if (status)
 26.1476 +            return status;
 26.1477 +    }
 26.1478 +    else {
 26.1479 +        // ???
 26.1480 +        // This is what we would have done before, so... no
 26.1481 +        // worse than the status quo. But FIXME!
 26.1482 +        status = interpret_MIME(part, msg);
 26.1483 +        if (status)
 26.1484 +            return status;
 26.1485 +    }
 26.1486 +    
 26.1487 +    for (cur = clist_next(cur); cur; cur = clist_next(cur)) {
 26.1488 +        part = clist_content(cur);
 26.1489 +        if (part == NULL)
 26.1490 +            return PEP_ILLEGAL_VALUE;
 26.1491 +
 26.1492 +        content = part->mm_content_type;
 26.1493 +        assert(content);
 26.1494 +        if (content == NULL)
 26.1495 +            return PEP_ILLEGAL_VALUE;
 26.1496 +
 26.1497 +        status = interpret_MIME(part, msg);
 26.1498 +        if (status)
 26.1499 +            return status;
 26.1500 +    }
 26.1501 +    return status;
 26.1502 +}
 26.1503 +
 26.1504 +static PEP_STATUS interpret_MIME(
 26.1505 +        struct mailmime *mime,
 26.1506 +        message *msg
 26.1507 +    )
 26.1508 +{
 26.1509 +    PEP_STATUS status = PEP_STATUS_OK;
 26.1510 +
 26.1511 +    assert(mime);
 26.1512 +    assert(msg);
 26.1513 +
 26.1514 +    struct mailmime_content *content = mime->mm_content_type;
 26.1515 +    if (content) {
 26.1516 +        if (_is_multipart(content, "alternative")) {
 26.1517 +            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 26.1518 +            if (partlist == NULL)
 26.1519 +                return PEP_ILLEGAL_VALUE;
 26.1520 +
 26.1521 +            clistiter *cur;
 26.1522 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 26.1523 +                struct mailmime *part = clist_content(cur);
 26.1524 +                if (part == NULL)
 26.1525 +                    return PEP_ILLEGAL_VALUE;
 26.1526 +
 26.1527 +                content = part->mm_content_type;
 26.1528 +                assert(content);
 26.1529 +                if (content == NULL)
 26.1530 +                    return PEP_ILLEGAL_VALUE;
 26.1531 +
 26.1532 +                if (_is_text_part(content, "plain") && msg->longmsg == NULL) {
 26.1533 +                    status = interpret_body(part, &msg->longmsg, NULL);
 26.1534 +                    if (status)
 26.1535 +                        return status;
 26.1536 +                }
 26.1537 +                else if (_is_text_part(content, "rfc822-headers")) {
 26.1538 +                    status = interpret_protected_headers(part, msg);
 26.1539 +                    if (status)
 26.1540 +                        return status;
 26.1541 +                }
 26.1542 +                else if (_is_text_part(content, "html") &&
 26.1543 +                        msg->longmsg_formatted == NULL) {
 26.1544 +                    status = interpret_body(part, &msg->longmsg_formatted,
 26.1545 +                            NULL);
 26.1546 +                    if (status)
 26.1547 +                        return status;
 26.1548 +                }
 26.1549 +                else if (_is_multipart(content, "related") && 
 26.1550 +                    msg->longmsg_formatted == NULL) {
 26.1551 +                    status = process_multipart_related(part, msg);
 26.1552 +                    if (status)
 26.1553 +                        return status;
 26.1554 +                }
 26.1555 +                else /* add as attachment */ {
 26.1556 +                    status = interpret_MIME(part, msg);
 26.1557 +                    if (status)
 26.1558 +                        return status;
 26.1559 +                }
 26.1560 +            }
 26.1561 +        }
 26.1562 +        else if (_is_multipart(content, "encrypted")) {
 26.1563 +            if (msg->longmsg == NULL)
 26.1564 +                msg->longmsg = strdup("");
 26.1565 +            assert(msg->longmsg);
 26.1566 +            if (!msg->longmsg)
 26.1567 +                return PEP_OUT_OF_MEMORY;
 26.1568 +
 26.1569 +            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 26.1570 +            if (partlist == NULL)
 26.1571 +                return PEP_ILLEGAL_VALUE;
 26.1572 +
 26.1573 +            clistiter *cur;
 26.1574 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 26.1575 +                struct mailmime *part= clist_content(cur);
 26.1576 +                if (part == NULL)
 26.1577 +                    return PEP_ILLEGAL_VALUE;
 26.1578 +
 26.1579 +                status = interpret_MIME(part, msg);
 26.1580 +                if (status != PEP_STATUS_OK)
 26.1581 +                    return status;
 26.1582 +            }
 26.1583 +        }
 26.1584 +        else if (_is_multipart(content, NULL)) {
 26.1585 +            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 26.1586 +            if (partlist == NULL)
 26.1587 +                return PEP_ILLEGAL_VALUE;
 26.1588 +
 26.1589 +            clistiter *cur;
 26.1590 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 26.1591 +                struct mailmime *part= clist_content(cur);
 26.1592 +                if (part == NULL)
 26.1593 +                    return PEP_ILLEGAL_VALUE;
 26.1594 +                status = interpret_MIME(part, msg);
 26.1595 +                if (status != PEP_STATUS_OK)
 26.1596 +                    return status;
 26.1597 +            }
 26.1598 +        }
 26.1599 +        else {
 26.1600 +            if (_is_text_part(content, "html") &&
 26.1601 +                msg->longmsg_formatted == NULL &&
 26.1602 +                msg->longmsg == NULL) {
 26.1603 +                status = interpret_body(mime, &msg->longmsg_formatted,
 26.1604 +                                        NULL);
 26.1605 +                if (status)
 26.1606 +                    return status;
 26.1607 +            }
 26.1608 +            else if (_is_text_part(content, "rfc822-headers")) {
 26.1609 +                status = interpret_protected_headers(mime, msg);
 26.1610 +                if (status)
 26.1611 +                    return status;
 26.1612 +            }
 26.1613 +            else if (_is_text_part(content, "plain") && 
 26.1614 +                     msg->longmsg == NULL && msg->longmsg_formatted == NULL) {
 26.1615 +                status = interpret_body(mime, &msg->longmsg, NULL);
 26.1616 +                if (status)
 26.1617 +                    return status;
 26.1618 +            }            
 26.1619 +            else if (_is_text_part(content, NULL) && 
 26.1620 +                     !_is_text_part(content, "plain") &&
 26.1621 +                     msg->longmsg == NULL) {
 26.1622 +                status = interpret_body(mime, &msg->longmsg, NULL);
 26.1623 +                if (status)
 26.1624 +                    return status;
 26.1625 +            }
 26.1626 +            else {
 26.1627 +                char *data = NULL;
 26.1628 +                size_t size = 0;
 26.1629 +                char * mime_type;
 26.1630 +                char * charset;
 26.1631 +                char * filename;
 26.1632 +                int r;
 26.1633 +
 26.1634 +                r = _get_content_type(content, &mime_type, &charset);
 26.1635 +                switch (r) {
 26.1636 +                    case 0:
 26.1637 +                        break;
 26.1638 +                    case EINVAL:
 26.1639 +                        return PEP_ILLEGAL_VALUE;
 26.1640 +                    case ENOMEM:
 26.1641 +                        return PEP_OUT_OF_MEMORY;
 26.1642 +                    default:
 26.1643 +                        return PEP_UNKNOWN_ERROR;
 26.1644 +                }
 26.1645 +
 26.1646 +                assert(mime_type);
 26.1647 +
 26.1648 +                status = interpret_body(mime, &data, &size);
 26.1649 +                if (status)
 26.1650 +                    return status;
 26.1651 +
 26.1652 +                pEp_rid_list_t* resource_id_list = _get_resource_id_list(mime);
 26.1653 +                pEp_rid_list_t* chosen_resource_id = choose_resource_id(resource_id_list);
 26.1654 +                
 26.1655 +                //filename = _get_filename_or_cid(mime);
 26.1656 +                char *_filename = NULL;
 26.1657 +                
 26.1658 +                if (chosen_resource_id) {
 26.1659 +                    filename = chosen_resource_id->rid;
 26.1660 +                    size_t index = 0;
 26.1661 +                    /* NOTA BENE */
 26.1662 +                    /* The prefix we just added shouldn't be a problem - this is about decoding %XX (RFC 2392) */
 26.1663 +                    /* If it becomes one, we have some MESSY fixing to do. :(                                  */
 26.1664 +                    r = mailmime_encoded_phrase_parse("utf-8", filename,
 26.1665 +                            strlen(filename), &index, "utf-8", &_filename);
 26.1666 +                    if (r) {
 26.1667 +                        goto enomem;
 26.1668 +                    }
 26.1669 +                    char* file_prefix = NULL;
 26.1670 +                    
 26.1671 +                    /* in case there are others later */
 26.1672 +                    switch (chosen_resource_id->rid_type) {
 26.1673 +                        case PEP_RID_CID:
 26.1674 +                            file_prefix = "cid";
 26.1675 +                            break;
 26.1676 +                        case PEP_RID_FILENAME:
 26.1677 +                            file_prefix = "file";
 26.1678 +                            break;
 26.1679 +                        default:
 26.1680 +                            break;
 26.1681 +                    }
 26.1682 +
 26.1683 +                    
 26.1684 +                    if (file_prefix) {
 26.1685 +                        filename = build_uri(file_prefix, _filename);
 26.1686 +                        free(_filename);
 26.1687 +                        _filename = filename;
 26.1688 +                    }
 26.1689 +                }
 26.1690 +
 26.1691 +                bloblist_t *_a = bloblist_add(msg->attachments, data, size,
 26.1692 +                        mime_type, _filename);
 26.1693 +                free(_filename);
 26.1694 +                free_rid_list(resource_id_list);
 26.1695 +                resource_id_list = NULL;
 26.1696 +                if (_a == NULL)
 26.1697 +                    return PEP_OUT_OF_MEMORY;
 26.1698 +                if (msg->attachments == NULL)
 26.1699 +                    msg->attachments = _a;
 26.1700 +            }
 26.1701 +        }
 26.1702 +    }
 26.1703 +
 26.1704 +    return PEP_STATUS_OK;
 26.1705 +
 26.1706 +enomem:
 26.1707 +    return PEP_OUT_OF_MEMORY;
 26.1708 +}
 26.1709 +
 26.1710 +DYNAMIC_API PEP_STATUS mime_decode_message(
 26.1711 +        const char *mimetext,
 26.1712 +        size_t size,
 26.1713 +        message **msg
 26.1714 +    )
 26.1715 +{
 26.1716 +    PEP_STATUS status = PEP_STATUS_OK;
 26.1717 +    struct mailmime * mime = NULL;
 26.1718 +    int r;
 26.1719 +    message *_msg = NULL;
 26.1720 +    size_t index;
 26.1721 +
 26.1722 +    assert(mimetext);
 26.1723 +    assert(msg);
 26.1724 +
 26.1725 +    if (!(mimetext && msg))
 26.1726 +        return PEP_ILLEGAL_VALUE;
 26.1727 +
 26.1728 +    *msg = NULL;
 26.1729 +
 26.1730 +    index = 0;
 26.1731 +    r = mailmime_parse(mimetext, size, &index, &mime);
 26.1732 +    assert(r == 0);
 26.1733 +    assert(mime);
 26.1734 +    if (r) {
 26.1735 +        if (r == MAILIMF_ERROR_MEMORY)
 26.1736 +            goto enomem;
 26.1737 +        else
 26.1738 +            goto err_mime;
 26.1739 +    }
 26.1740 +
 26.1741 +    _msg = calloc(1, sizeof(message));
 26.1742 +    assert(_msg);
 26.1743 +    if (_msg == NULL)
 26.1744 +        goto enomem;
 26.1745 +
 26.1746 +    clist * _fieldlist = _get_fields(mime);
 26.1747 +    if (_fieldlist) {
 26.1748 +        status = read_fields(_msg, _fieldlist);
 26.1749 +        if (status != PEP_STATUS_OK)
 26.1750 +            goto pEp_error;
 26.1751 +    }
 26.1752 +
 26.1753 +    struct mailmime_content *content = _get_content(mime);
 26.1754 +
 26.1755 +    if (content) {
 26.1756 +        status = interpret_MIME(mime->mm_data.mm_message.mm_msg_mime,
 26.1757 +                _msg);
 26.1758 +        if (status != PEP_STATUS_OK)
 26.1759 +            goto pEp_error;
 26.1760 +    }
 26.1761 +
 26.1762 +    mailmime_free(mime);
 26.1763 +    *msg = _msg;
 26.1764 +
 26.1765 +    return status;
 26.1766 +
 26.1767 +err_mime:
 26.1768 +    status = PEP_ILLEGAL_VALUE;
 26.1769 +    goto pEp_error;
 26.1770 +
 26.1771 +enomem:
 26.1772 +    status = PEP_OUT_OF_MEMORY;
 26.1773 +
 26.1774 +pEp_error:
 26.1775 +    free_message(_msg);
 26.1776 +
 26.1777 +    if (mime)
 26.1778 +        mailmime_free(mime);
 26.1779 +
 26.1780 +    return status;
 26.1781 +}
 26.1782 +
    27.1 --- a/src/key_reset.c	Thu Mar 28 15:40:45 2019 +0100
    27.2 +++ b/src/key_reset.c	Fri May 17 17:30:57 2019 +0200
    27.3 @@ -323,20 +323,61 @@
    27.4      return status;
    27.5  }
    27.6  
    27.7 -DYNAMIC_API PEP_STATUS key_reset(
    27.8 +DYNAMIC_API PEP_STATUS key_reset_identity(
    27.9 +        PEP_SESSION session,
   27.10 +        pEp_identity* ident,
   27.11 +        const char* fpr        
   27.12 +    )
   27.13 +{
   27.14 +    if (!session || !ident || (ident && (EMPTYSTR(ident->user_id) || EMPTYSTR(ident->address))))
   27.15 +        return PEP_ILLEGAL_VALUE;
   27.16 +    
   27.17 +    return key_reset(session, fpr, ident);    
   27.18 +}
   27.19 +
   27.20 +DYNAMIC_API PEP_STATUS key_reset_user(
   27.21 +        PEP_SESSION session,
   27.22 +        const char* user_id,
   27.23 +        const char* fpr        
   27.24 +    )
   27.25 +{
   27.26 +    if (!session || EMPTYSTR(user_id))
   27.27 +        return PEP_ILLEGAL_VALUE;
   27.28 +
   27.29 +    pEp_identity* input_ident = new_identity(NULL, NULL, user_id, NULL);
   27.30 +    if (!input_ident)
   27.31 +        return PEP_OUT_OF_MEMORY;
   27.32 +        
   27.33 +    if (is_me(session, input_ident) && EMPTYSTR(fpr))
   27.34 +        return PEP_ILLEGAL_VALUE;
   27.35 +        
   27.36 +    PEP_STATUS status = key_reset(session, fpr, input_ident);
   27.37 +    free_identity(input_ident);
   27.38 +    return status;
   27.39 +}
   27.40 +
   27.41 +DYNAMIC_API PEP_STATUS key_reset_all_own_keys(PEP_SESSION session) {
   27.42 +    return key_reset(session, NULL, NULL);
   27.43 +}
   27.44 +
   27.45 +// Notes to integrate into header:
   27.46 +// IF there is an ident, it must have a user_id.
   27.47 +PEP_STATUS key_reset(
   27.48          PEP_SESSION session,
   27.49          const char* key_id,
   27.50          pEp_identity* ident
   27.51      )
   27.52  {
   27.53 -    if (!session)
   27.54 +    if (!session || (ident && EMPTYSTR(ident->user_id)))
   27.55          return PEP_ILLEGAL_VALUE;
   27.56          
   27.57      PEP_STATUS status = PEP_STATUS_OK;
   27.58          
   27.59      char* fpr_copy = NULL;
   27.60      char* own_id = NULL;
   27.61 +    char* user_id = NULL;
   27.62      char* new_key = NULL;
   27.63 +    pEp_identity* tmp_ident = NULL;
   27.64      identity_list* key_idents = NULL;
   27.65      stringlist_t* keys = NULL;
   27.66      
   27.67 @@ -345,133 +386,205 @@
   27.68          if (!fpr_copy)
   27.69              return PEP_OUT_OF_MEMORY;
   27.70      }
   27.71 -        
   27.72 -    if (!ident) {
   27.73 -        // Get list of own identities
   27.74 -        status = get_default_own_userid(session, &own_id);
   27.75 -        if (status != PEP_STATUS_OK)
   27.76 +
   27.77 +    // This is true when we don't have a user_id and address and the fpr isn't specified
   27.78 +    bool reset_all_for_user = !fpr_copy && (!ident || EMPTYSTR(ident->address));
   27.79 +
   27.80 +    // FIXME: does this need to be done everywhere?> I think not.
   27.81 +    if (ident) {
   27.82 +        user_id = strdup(ident->user_id);
   27.83 +        if (!user_id) {
   27.84 +            status = PEP_OUT_OF_MEMORY;
   27.85              goto pEp_free;
   27.86 +        }
   27.87 +    }
   27.88 +    else {
   27.89 +        status = get_default_own_userid(session, &user_id);
   27.90 +        if (status != PEP_STATUS_OK || !user_id)
   27.91 +            goto pEp_free;                    
   27.92 +    }
   27.93 +    
   27.94 +    // FIXME: Make sure this can't result in a double-free in recursive calls
   27.95 +    tmp_ident = (ident ? identity_dup(ident) : new_identity(NULL, NULL, user_id, NULL));
   27.96 +    
   27.97 +    if (reset_all_for_user) {
   27.98 +        status = get_all_keys_for_user(session, user_id, &keys);
   27.99 +        // TODO: free
  27.100 +        if (status == PEP_STATUS_OK) {
  27.101 +            stringlist_t* curr_key;
  27.102              
  27.103 -        if (EMPTYSTR(fpr_copy)) {
  27.104 -            status = get_all_keys_for_user(session, own_id, &keys);
  27.105 -            if (status == PEP_STATUS_OK) {
  27.106 -                stringlist_t* curr_key;
  27.107 -                for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) {
  27.108 -                    status = key_reset(session, curr_key->value, NULL);
  27.109 -                    if (status != PEP_STATUS_OK)
  27.110 -                        break;
  27.111 -                }
  27.112 -            }
  27.113 -            goto pEp_free;
  27.114 -        } // otherwise, we have a specific fpr to process
  27.115 -
  27.116 -        // fpr_copy exists, so... let's go.
  27.117 -        // Process own identities with this fpr
  27.118 -        status = get_identities_by_main_key_id(session, fpr_copy, &key_idents);
  27.119 -        
  27.120 -        if (status == PEP_STATUS_OK) {
  27.121 -            // have ident list, or should
  27.122 -            identity_list* curr_ident;
  27.123 -            for (curr_ident = key_idents; curr_ident && curr_ident->ident; 
  27.124 -                 curr_ident = curr_ident->next) {
  27.125 -                pEp_identity* this_identity = curr_ident->ident;
  27.126 -                status = key_reset(session, fpr_copy, this_identity);
  27.127 +            for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) {
  27.128 +                // FIXME: Is the ident really necessary?
  27.129 +                status = key_reset(session, curr_key->value, tmp_ident);
  27.130                  if (status != PEP_STATUS_OK)
  27.131 -                    break;                    
  27.132 +                    break;
  27.133              }
  27.134          }
  27.135 -        else if (status == PEP_CANNOT_FIND_IDENTITY) // not an error
  27.136 -            status = PEP_STATUS_OK;
  27.137 +        goto pEp_free;
  27.138 +    }                   
  27.139 +    else {
  27.140 +        // tmp_ident => tmp_ident->user_id (was checked)
  27.141 +        //
  27.142 +        // !(EMPTYSTR(fpr) && (!tmp_ident || EMPTYSTR(tmp_ident->address)))
  27.143 +        // => fpr || (tmp_ident && tmp_ident->address)
  27.144 +        //
  27.145 +        // so: We have an fpr or we have an ident with user_id and address
  27.146 +        //     or both
  27.147 +        if (!fpr_copy) {
  27.148 +            // We are guaranteed to have an ident w/ id + addr here.
  27.149 +            // Get the default key.
  27.150 +            pEp_identity* stored_ident = NULL;
  27.151 +            status = get_identity(session, tmp_ident->address, 
  27.152 +                                  tmp_ident->user_id, &stored_ident);
  27.153 +
  27.154 +            // FIXME FIXME FIXME
  27.155 +            if (status == PEP_STATUS_OK) {
  27.156 +                // transfer ownership
  27.157 +                fpr_copy = stored_ident->fpr;
  27.158 +                stored_ident->fpr = NULL;
  27.159 +                free_identity(stored_ident);                
  27.160 +            }
  27.161              
  27.162 -        goto pEp_free;
  27.163 -    }
  27.164 -    else { // an identity was specified.       
  27.165 -        if (is_me(session, ident)) {            
  27.166 -            // FIXME: make sure this IS our fpr?
  27.167 +            if (!fpr_copy || status == PEP_CANNOT_FIND_IDENTITY) {
  27.168 +                // There's no identity default. Try resetting user default
  27.169 +                status = get_user_default_key(session, tmp_ident->user_id, &fpr_copy);
  27.170 +            }            
  27.171              
  27.172 -            // If it got sent in with an empty fpr...
  27.173 -            if (EMPTYSTR(fpr_copy)) {
  27.174 -                //
  27.175 -                // if (!EMPTYSTR(ident->fpr))
  27.176 -                //     fpr_copy = strdup(ident->fpr);
  27.177 -                status = _myself(session, ident, false, true);
  27.178 -                if (status == PEP_STATUS_OK && ident->fpr)
  27.179 -                    fpr_copy = strdup(ident->fpr);
  27.180 -                else {
  27.181 -                    // last resort?
  27.182 -                    // Get list of own identities
  27.183 -                    char* own_id = NULL;
  27.184 -                    status = get_default_own_userid(session, &own_id);
  27.185 -                    if (status == PEP_STATUS_OK)
  27.186 -                        status = get_user_default_key(session, own_id, &fpr_copy);
  27.187 -                    if (status != PEP_STATUS_OK || EMPTYSTR(fpr_copy))  {
  27.188 -                        free(own_id);
  27.189 -                        return (status == PEP_STATUS_OK ? PEP_KEY_NOT_FOUND : status);
  27.190 +            if (!fpr_copy || status != PEP_STATUS_OK) // No default to free. We're done here.
  27.191 +                goto pEp_free;            
  27.192 +        }
  27.193 +        
  27.194 +        // Ok - now we have at least an ident with user_id and an fpr.
  27.195 +        // Now it matters if we're talking about ourselves or a partner.
  27.196 +        bool is_own_private = false;
  27.197 +        if (is_me(session, tmp_ident)) {
  27.198 +            bool own_key = false;            
  27.199 +            status = is_own_key(session, fpr_copy, &own_key);
  27.200 +
  27.201 +            if (status != PEP_STATUS_OK)
  27.202 +                goto pEp_free;
  27.203 +            if (!own_key) {
  27.204 +                status = PEP_ILLEGAL_VALUE;
  27.205 +                goto pEp_free;
  27.206 +            }
  27.207 +
  27.208 +            status = contains_priv_key(session, fpr_copy, &is_own_private);
  27.209 +            if (status != PEP_STATUS_OK && status != PEP_KEY_NOT_FOUND)
  27.210 +                goto pEp_free;
  27.211 +        }
  27.212 +        
  27.213 +        // Up to this point, we haven't cared about whether or not we 
  27.214 +        // had a full identity. Now we have to deal with that in the 
  27.215 +        // case of own identities with private keys.
  27.216 +        
  27.217 +        if (is_own_private) {
  27.218 +            
  27.219 +            // If there's no address, we want to reset this key for every identity 
  27.220 +            // it's a part of. Since this means generating new keys, we have to 
  27.221 +            // grab all the identities associated with it.
  27.222 +            if (EMPTYSTR(tmp_ident->address)) {
  27.223 +                status = get_identities_by_main_key_id(session, fpr_copy, &key_idents);
  27.224 +                
  27.225 +                if (status != PEP_CANNOT_FIND_IDENTITY) {
  27.226 +                    if (status == PEP_STATUS_OK) {
  27.227 +                        // now have ident list, or should
  27.228 +                        identity_list* curr_ident;
  27.229 +                        
  27.230 +                        for (curr_ident = key_idents; curr_ident && curr_ident->ident; 
  27.231 +                                                        curr_ident = curr_ident->next) {
  27.232 +                            
  27.233 +                            pEp_identity* this_identity = curr_ident->ident;
  27.234 +                            // Do the full reset on this identity        
  27.235 +                            status = key_reset(session, fpr_copy, this_identity);
  27.236 +                            
  27.237 +                            // Ident list gets freed below, do not free here!
  27.238 +
  27.239 +                            if (status != PEP_STATUS_OK)
  27.240 +                                break;
  27.241 +                            
  27.242 +                        }
  27.243                      }
  27.244 -                }
  27.245 +                    // Ok, we've either now reset for each own identity with this key, or 
  27.246 +                    // we got an error and want to bail anyway.
  27.247 +                    goto pEp_free;
  27.248 +                }    
  27.249              }
  27.250 -                        
  27.251 -            free(ident->fpr);
  27.252 -            ident->fpr = fpr_copy;            
  27.253 +            
  27.254              // Create revocation
  27.255              status = revoke_key(session, fpr_copy, NULL);
  27.256 -            // generate new key
  27.257 -            if (status == PEP_STATUS_OK) {
  27.258 -                ident->fpr = NULL;
  27.259 -                status = generate_keypair(session, ident);
  27.260 -            }
  27.261 -            if (status == PEP_STATUS_OK) {
  27.262 -                new_key = strdup(ident->fpr);
  27.263 -                status = set_own_key(session, ident, new_key);
  27.264 -            }
  27.265 -            // mistrust fpr from trust
  27.266 -            ident->fpr = fpr_copy;
  27.267              
  27.268 -            ident->comm_type = PEP_ct_mistrusted;
  27.269 -            status = set_trust(session, ident);
  27.270 -            ident->fpr = NULL;
  27.271 -            
  27.272 -            // Done with old use of ident.
  27.273 -            if (status == PEP_STATUS_OK) {
  27.274 -                // Update fpr for outgoing
  27.275 -                status = myself(session, ident);
  27.276 -            }
  27.277 +            // If we have a full identity, we have some cleanup and generation tasks here
  27.278 +            if (!EMPTYSTR(tmp_ident->address)) {
  27.279 +                // generate new key
  27.280 +                if (status == PEP_STATUS_OK) {
  27.281 +                    tmp_ident->fpr = NULL;
  27.282 +                    status = generate_keypair(session, tmp_ident);
  27.283 +                }
  27.284 +                if (status == PEP_STATUS_OK) {
  27.285 +                    new_key = strdup(tmp_ident->fpr);
  27.286 +                    status = set_own_key(session, tmp_ident, new_key);
  27.287 +                }
  27.288 +                // mistrust fpr from trust
  27.289 +                tmp_ident->fpr = fpr_copy;
  27.290 +                
  27.291 +                tmp_ident->comm_type = PEP_ct_mistrusted;
  27.292 +                status = set_trust(session, tmp_ident);
  27.293 +                tmp_ident->fpr = NULL;
  27.294 +                
  27.295 +                // Done with old use of ident.
  27.296 +                if (status == PEP_STATUS_OK) {
  27.297 +                    // Update fpr for outgoing
  27.298 +                    status = myself(session, tmp_ident);
  27.299 +                }
  27.300 +            }    
  27.301              
  27.302              if (status == PEP_STATUS_OK)
  27.303                  // cascade that mistrust for anyone using this key
  27.304                  status = mark_as_compromised(session, fpr_copy);
  27.305 +                
  27.306              if (status == PEP_STATUS_OK)
  27.307                  status = remove_fpr_as_default(session, fpr_copy);
  27.308              if (status == PEP_STATUS_OK)
  27.309                  status = add_mistrusted_key(session, fpr_copy);
  27.310 -            // add to revocation list 
  27.311 -            if (status == PEP_STATUS_OK) 
  27.312 -                status = set_revoked(session, fpr_copy, new_key, time(NULL));            
  27.313 -            // for all active communication partners:
  27.314 -            //      active_send revocation
  27.315 -            if (status == PEP_STATUS_OK)
  27.316 -                status = send_key_reset_to_recents(session, fpr_copy, new_key);
  27.317 -                
  27.318 +
  27.319 +            // If there's a new key, do the DB linkage with the revoked one, and 
  27.320 +            // send the key reset mail opportunistically to recently contacted
  27.321 +            // partners
  27.322 +            if (new_key) {
  27.323 +                // add to revocation list 
  27.324 +                if (status == PEP_STATUS_OK) 
  27.325 +                    status = set_revoked(session, fpr_copy, new_key, time(NULL));            
  27.326 +                // for all active communication partners:
  27.327 +                //      active_send revocation
  27.328 +                if (status == PEP_STATUS_OK)
  27.329 +                    status = send_key_reset_to_recents(session, fpr_copy, new_key);        
  27.330 +            }        
  27.331 +        } // end is_own_private
  27.332 +        else {
  27.333 +            // This is a public key (or a private key that isn't ours, which means
  27.334 +            // we want it gone anyway)
  27.335 +            //
  27.336 +            // Delete this key from the keyring.
  27.337 +            status = delete_keypair(session, fpr_copy);
  27.338          }
  27.339 -        else { // not is_me
  27.340 -            // TODO: Decide what this means. We have a non-own identity, we don't
  27.341 -            //       have an fpr. Do we reset all keys for that identity?
  27.342 -            if (EMPTYSTR(fpr_copy)) {
  27.343 -                NOT_IMPLEMENTED
  27.344 -            }
  27.345 -                
  27.346 -            // remove fpr from all identities
  27.347 -            // remove fpr from all users
  27.348 -            if (status == PEP_STATUS_OK)
  27.349 -                status = remove_fpr_as_default(session, fpr_copy);
  27.350 -            // delete key from DB
  27.351 -            if (status == PEP_STATUS_OK) {
  27.352 -                status = remove_key(session, fpr_copy);
  27.353 -            };
  27.354 +
  27.355 +        // REGARDLESS OF WHO OWNS THE KEY, WE NOW NEED TO REMOVE IT AS A DEFAULT.
  27.356 +        PEP_STATUS cached_status = status;
  27.357 +        // remove fpr from all identities
  27.358 +        // remove fpr from all users
  27.359 +        status = remove_fpr_as_default(session, fpr_copy);
  27.360 +        // delete key from DB - this does NOT touch the keyring!
  27.361 +        // Note: for own priv keys, we cannot do this. But we'll never encrypt to/from it.
  27.362 +        if (status == PEP_STATUS_OK && !is_own_private) {
  27.363 +            status = remove_key(session, fpr_copy);
  27.364          }
  27.365 -    }
  27.366 -    
  27.367 +        if (status == PEP_STATUS_OK)
  27.368 +            status = cached_status;
  27.369 +    }           
  27.370 +        
  27.371  pEp_free:
  27.372 +    if (!ident)
  27.373 +        free_identity(tmp_ident);
  27.374      free(fpr_copy);
  27.375      free(own_id);
  27.376      free_identity_list(key_idents);
    28.1 --- a/src/key_reset.h	Thu Mar 28 15:40:45 2019 +0100
    28.2 +++ b/src/key_reset.h	Fri May 17 17:30:57 2019 +0200
    28.3 @@ -15,13 +15,90 @@
    28.4  extern "C" {
    28.5  #endif
    28.6  
    28.7 +// key_reset_identity() - reset the default database status for the identity / keypair
    28.8 +//                        provided. If this corresponds to an own identity and a private key,
    28.9 +//                        also revoke the key, generate a new one, and communicate the 
   28.10 +//                        reset to recently contacted pEp partners for this identity.
   28.11 +//
   28.12 +//                        If it does not, remove the key from the keyring; the key's 
   28.13 +//                        status is completely fresh on next contact from the partner.
   28.14 +//
   28.15 +//                        If no key is provided, reset the identity default.
   28.16 +//
   28.17 +//                        Note that reset keys will be removed as defaults for all users and identities.
   28.18 +//
   28.19 +//  parameters:
   28.20 +//      session (in)            session handle
   28.21 +//      fpr (in)                fingerprint of key to reset. If NULL, we reset the default key
   28.22 +//                              this identity if there is one, and the user default if not.
   28.23 +//      ident (in)              identity for which the key reset should occur. Must contain 
   28.24 +//                              user_id and address. Must not be NULL.
   28.25 +//
   28.26 +//                              Note: ident->fpr field will be ignored.
   28.27 +//
   28.28 +//
   28.29 +DYNAMIC_API PEP_STATUS key_reset_identity(
   28.30 +        PEP_SESSION session,
   28.31 +        pEp_identity* ident,
   28.32 +        const char* fpr
   28.33 +    );
   28.34 +
   28.35 +// key_reset_user() -  reset the default database status for the user / keypair
   28.36 +//                     provided. This will effectively perform key_reset_identity()
   28.37 +//                     each identity associated with the key and user_id, if a key is
   28.38 +//                     provided, and for each key (and all of their identities) if an fpr 
   28.39 +//                     is not.
   28.40 +//
   28.41 +//                     If the user_id is the own user_id, an fpr MUST be provided.
   28.42 +//                     For a reset of all own user keys, call key_reset_all_own_keys() instead.
   28.43 +//
   28.44 +//                     Note that reset keys will be removed as defaults for all users and identities.
   28.45 +//
   28.46 +//  parameters:
   28.47 +//      session (in)            session handle
   28.48 +//      user_id (in)            user_id for which the key reset should occur. If this 
   28.49 +//                              is the own user_id, fpr MUST NOT be NULL.
   28.50 +//      fpr (in)                fingerprint of key to reset.
   28.51 +//                              If NULL, we reset all default 
   28.52 +//                              keys for this user and all of its identities.
   28.53 +//                              *** However, it is forbidden to use the own user_id 
   28.54 +//                                  here when the fpr is NULL. For this functionality, 
   28.55 +//                                  call key_reset_all_own_keys ***
   28.56 +
   28.57 +//
   28.58 +DYNAMIC_API PEP_STATUS key_reset_user(
   28.59 +        PEP_SESSION session,
   28.60 +        const char* user_id,
   28.61 +        const char* fpr
   28.62 +    );
   28.63 +
   28.64 +// key_reset_all_own_keys() -  revoke and mistrust all own keys, generate new keys for all 
   28.65 +//                             own identities, and opportunistically communicate
   28.66 +//                             key reset information to people we have recently 
   28.67 +//                             contacted. 
   28.68 +//
   28.69 +// caveat: this will return PEP_CANNOT_FIND_IDENTITY if no own user yet exists.
   28.70 +//         HOWEVER, apps and adapters must decide if this is a reasonable state;
   28.71 +//         since the period where no own user exists will necessarily be very short
   28.72 +//         in most implementations, PEP_CANNOT_FIND_IDENTITY may be returned when 
   28.73 +//         there is some sort of DB corruption and we expect there to be an own user.
   28.74 +//         Apps are responsible for deciding whether or not this is an error condition;
   28.75 +//         one would expect that it generally is (rather than the uninitialised DB case)
   28.76 +//                             
   28.77 +//  parameters:
   28.78 +//      session (in)            session handle
   28.79 +//
   28.80 +DYNAMIC_API PEP_STATUS key_reset_all_own_keys(PEP_SESSION session);
   28.81 +
   28.82 +
   28.83  // key_reset() - reset the database status for a key, removing all trust information
   28.84  //               and default database connections. For own keys, also revoke the key
   28.85  //               and communicate the revocation and new key to partners we have sent
   28.86  //               mail to recently from the specific identity (i.e. address/user_id)
   28.87  //               that contacted them. We also in this case set up information so that
   28.88  //               if someone we mail uses the wrong key and wasn't yet contacted,
   28.89 -//               we can send them the reset information from the right address.
   28.90 +//               we can send them the reset information from the right address. 
   28.91 +//               For non-own keys, also remove key from the keyring.
   28.92  //
   28.93  //               Can be called manually or through another protocol.
   28.94  //
   28.95 @@ -32,10 +109,8 @@
   28.96  //                              an own identity, we reset the default key for that
   28.97  //                              identity. If that own identity has no default key, we
   28.98  //                              reset the user default.
   28.99 -//                              if it is NULL and there is a non-own identity, this is
  28.100 -//                              currently undefined and will return an error. Later, we
  28.101 -//                              may decide on semantics for it (e.g. remove all keys
  28.102 -//                              in the DB for that identity)
  28.103 +//                              if it is NULL and there is a non-own identity, we will reset 
  28.104 +//                              the default key for this identity if present, and user if not.
  28.105  //      ident (in)              identity for which the key reset should occur.
  28.106  //                              if NULL and fpr is non-NULL, we'll reset the key for all
  28.107  //                              associated identities. If both ident and fpr are NULL, see 
  28.108 @@ -43,13 +118,17 @@
  28.109  //
  28.110  //      Note: ident->fpr is always ignored
  28.111  //
  28.112 -//
  28.113 -DYNAMIC_API PEP_STATUS key_reset(
  28.114 +// Caveat: this is now used in large part for internal calls.
  28.115 +//         external apps should call key_reset_identity and key_reset_userdata
  28.116 +//         and this function should probably be removed from the dynamic api
  28.117 +PEP_STATUS key_reset(
  28.118          PEP_SESSION session,
  28.119          const char* fpr,
  28.120          pEp_identity* ident
  28.121      );
  28.122  
  28.123 +
  28.124 +
  28.125  PEP_STATUS has_key_reset_been_sent(
  28.126          PEP_SESSION session, 
  28.127          const char* user_id, 
    29.1 --- a/src/keymanagement.c	Thu Mar 28 15:40:45 2019 +0100
    29.2 +++ b/src/keymanagement.c	Fri May 17 17:30:57 2019 +0200
    29.3 @@ -576,9 +576,44 @@
    29.4      char* default_own_id = NULL;
    29.5      status = get_default_own_userid(session, &default_own_id);    
    29.6  
    29.7 -    // Is this me, temporary or not? If so, BAIL.
    29.8 -    if (identity->me || 
    29.9 -       (default_own_id && identity->user_id && (strcmp(default_own_id, identity->user_id) == 0))) 
   29.10 +    bool is_own_user = identity->me;
   29.11 +
   29.12 +    // Is this me, temporary or not? If so, BAIL.    
   29.13 +    if (!is_own_user) {
   29.14 +        if (default_own_id) {
   29.15 +            if (!EMPTYSTR(identity->user_id)) {
   29.16 +                if (strcmp(default_own_id, identity->user_id) == 0) {
   29.17 +                    is_own_user = true;
   29.18 +                }
   29.19 +                else {
   29.20 +                    char* alias = NULL;
   29.21 +                    if (get_userid_alias_default(session, identity->user_id, &alias) == PEP_STATUS_OK) {
   29.22 +                        if (alias && strcmp(default_own_id, alias) == 0)
   29.23 +                            is_own_user = true;
   29.24 +                        free(alias);    
   29.25 +                    }
   29.26 +                }
   29.27 +            }
   29.28 +            else {
   29.29 +                // Check if own address. For now, this is a special case;
   29.30 +                // we try to require apps to send in user_ids, but must prevent
   29.31 +                // writes to an own identity from within THIS function
   29.32 +                // NOTE: These semantics MAY CHANGE.
   29.33 +                bool _own_addr = false;
   29.34 +                is_own_address(session, identity->address, &_own_addr);
   29.35 +                
   29.36 +                // N.B. KB: I would prefer consistent semantics here - that is to say,
   29.37 +                // we also set is_own_user here and force PEP_ILLEGAL_VALUE                
   29.38 +                if (_own_addr) {
   29.39 +                    free(identity->user_id);
   29.40 +                    identity->user_id = strdup(default_own_id);
   29.41 +                    return _myself(session, identity, false, false, true);
   29.42 +                }    
   29.43 +            }
   29.44 +        }
   29.45 +        // Otherwise, we don't even HAVE an own user yet, so we're ok.
   29.46 +    }    
   29.47 +    if (is_own_user)
   29.48      {
   29.49          free(default_own_id);
   29.50          return PEP_ILLEGAL_VALUE;
   29.51 @@ -994,7 +1029,11 @@
   29.52      return status;
   29.53  }
   29.54  
   29.55 -PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags)
   29.56 +PEP_STATUS _myself(PEP_SESSION session, 
   29.57 +                   pEp_identity * identity, 
   29.58 +                   bool do_keygen, 
   29.59 +                   bool ignore_flags,
   29.60 +                   bool read_only)
   29.61  {
   29.62  
   29.63      PEP_STATUS status;
   29.64 @@ -1016,18 +1055,24 @@
   29.65      status = get_default_own_userid(session, &default_own_id);
   29.66  
   29.67      // Deal with non-default user_ids.
   29.68 +    // FIXME: if non-default and read-only, reject totally?
   29.69      if (default_own_id && strcmp(default_own_id, identity->user_id) != 0) {
   29.70 -        
   29.71 -        status = set_userid_alias(session, default_own_id, identity->user_id);
   29.72 -        // Do we want this to be fatal? For now, we'll do it...
   29.73 -        if (status != PEP_STATUS_OK)
   29.74 -            goto pEp_free;
   29.75 -            
   29.76 -        free(identity->user_id);
   29.77 -        identity->user_id = strdup(default_own_id);
   29.78 -        if (identity->user_id == NULL) {
   29.79 -            status = PEP_OUT_OF_MEMORY;
   29.80 -            goto pEp_free;
   29.81 +        if (read_only) {
   29.82 +            free(identity->user_id);
   29.83 +            identity->user_id = strdup(default_own_id);
   29.84 +        }
   29.85 +        else {
   29.86 +            status = set_userid_alias(session, default_own_id, identity->user_id);
   29.87 +            // Do we want this to be fatal? For now, we'll do it...
   29.88 +            if (status != PEP_STATUS_OK)
   29.89 +                goto pEp_free;
   29.90 +                
   29.91 +            free(identity->user_id);
   29.92 +            identity->user_id = strdup(default_own_id);
   29.93 +            if (identity->user_id == NULL) {
   29.94 +                status = PEP_OUT_OF_MEMORY;
   29.95 +                goto pEp_free;
   29.96 +            }
   29.97          }
   29.98      }
   29.99  
  29.100 @@ -1060,7 +1105,7 @@
  29.101      // Set usernames - priority is input username > stored name > address
  29.102      // If there's an input username, we always patch the username with that
  29.103      // input.
  29.104 -    if (EMPTYSTR(identity->username)) {
  29.105 +    if (EMPTYSTR(identity->username) || read_only) {
  29.106          bool stored_uname = (stored_identity && !EMPTYSTR(stored_identity->username));
  29.107          char* uname = (stored_uname ? stored_identity->username : identity->address);
  29.108          free(identity->username);
  29.109 @@ -1079,41 +1124,45 @@
  29.110      }
  29.111  
  29.112      // check stored identity
  29.113 -    if (stored_identity && !EMPTYSTR(stored_identity->fpr)) {
  29.114 -        // Fall back / retrieve
  29.115 -        status = validate_fpr(session, stored_identity, false, true);
  29.116 -        if (status == PEP_OUT_OF_MEMORY)
  29.117 -            goto pEp_free;
  29.118 -        if (status == PEP_STATUS_OK) {
  29.119 -            if (stored_identity->comm_type >= PEP_ct_strong_but_unconfirmed) {
  29.120 -                identity->fpr = strdup(stored_identity->fpr);
  29.121 -                assert(identity->fpr);
  29.122 -                if (!identity->fpr) {
  29.123 -                    status = PEP_OUT_OF_MEMORY;
  29.124 -                    goto pEp_free;
  29.125 -                }
  29.126 -                valid_key_found = true;            
  29.127 -            }
  29.128 -            else {
  29.129 -                bool revoked = false;
  29.130 -                status = key_revoked(session, stored_identity->fpr, &revoked);
  29.131 -                if (status)
  29.132 -                    goto pEp_free;
  29.133 -                if (revoked) {
  29.134 -                    revoked_fpr = strdup(stored_identity->fpr);
  29.135 -                    assert(revoked_fpr);
  29.136 -                    if (!revoked_fpr) {
  29.137 +    if (stored_identity) {
  29.138 +        if (!EMPTYSTR(stored_identity->fpr)) {
  29.139 +            // Fall back / retrieve
  29.140 +            status = validate_fpr(session, stored_identity, false, true);
  29.141 +            if (status == PEP_OUT_OF_MEMORY)
  29.142 +                goto pEp_free;
  29.143 +            if (status == PEP_STATUS_OK) {
  29.144 +                if (stored_identity->comm_type >= PEP_ct_strong_but_unconfirmed) {
  29.145 +                    identity->fpr = strdup(stored_identity->fpr);
  29.146 +                    assert(identity->fpr);
  29.147 +                    if (!identity->fpr) {
  29.148                          status = PEP_OUT_OF_MEMORY;
  29.149                          goto pEp_free;
  29.150                      }
  29.151 +                    valid_key_found = true;            
  29.152 +                }
  29.153 +                else {
  29.154 +                    bool revoked = false;
  29.155 +                    status = key_revoked(session, stored_identity->fpr, &revoked);
  29.156 +                    if (status)
  29.157 +                        goto pEp_free;
  29.158 +                    if (revoked) {
  29.159 +                        revoked_fpr = strdup(stored_identity->fpr);
  29.160 +                        assert(revoked_fpr);
  29.161 +                        if (!revoked_fpr) {
  29.162 +                            status = PEP_OUT_OF_MEMORY;
  29.163 +                            goto pEp_free;
  29.164 +                        }
  29.165 +                    }
  29.166                  }
  29.167              }
  29.168          }
  29.169 +        // reconcile language, flags
  29.170 +        transfer_ident_lang_and_flags(identity, stored_identity);
  29.171      }
  29.172      
  29.173      // Nothing left to do but generate a key
  29.174      if (!valid_key_found) {
  29.175 -        if (!do_keygen)
  29.176 +        if (!do_keygen || read_only)
  29.177              status = PEP_GET_KEY_FAILED;
  29.178          else {
  29.179  // /            DEBUG_LOG("Generating key pair", "debug", identity->address);
  29.180 @@ -1151,12 +1200,14 @@
  29.181      
  29.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
  29.183      // it's NOT ok
  29.184 -    PEP_STATUS set_id_status = set_identity(session, identity);
  29.185 -    if (set_id_status == PEP_STATUS_OK)
  29.186 -        set_id_status = set_as_pEp_user(session, identity);
  29.187 +    if (!read_only) {
  29.188 +        PEP_STATUS set_id_status = set_identity(session, identity);
  29.189 +        if (set_id_status == PEP_STATUS_OK)
  29.190 +            set_id_status = set_as_pEp_user(session, identity);
  29.191  
  29.192 -    status = (status == PEP_STATUS_OK ? set_id_status : status);
  29.193 -
  29.194 +        status = (status == PEP_STATUS_OK ? set_id_status : status);
  29.195 +    }
  29.196 +    
  29.197  pEp_free:    
  29.198      free(default_own_id);
  29.199      free(revoked_fpr);                     
  29.200 @@ -1166,7 +1217,7 @@
  29.201  
  29.202  DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
  29.203  {
  29.204 -    return _myself(session, identity, true, false);
  29.205 +    return _myself(session, identity, true, false, false);
  29.206  }
  29.207  
  29.208  DYNAMIC_API PEP_STATUS register_examine_function(
  29.209 @@ -1495,7 +1546,6 @@
  29.210          }
  29.211      }    
  29.212  
  29.213 -pEp_free:
  29.214      free(ident_default_fpr);
  29.215      free(cached_fpr);
  29.216      free_identity(tmp_id);
  29.217 @@ -1610,8 +1660,10 @@
  29.218      unsigned int flags = 0;
  29.219      
  29.220      identity_list *_bl = _own_identities;
  29.221 +
  29.222 +    sqlite3_bind_int(session->own_identities_retrieve, 1, excluded_flags);
  29.223 +
  29.224      do {
  29.225 -        sqlite3_bind_int(session->own_identities_retrieve, 1, excluded_flags);
  29.226          result = sqlite3_step(session->own_identities_retrieve);
  29.227          switch (result) {
  29.228              case SQLITE_ROW:
  29.229 @@ -1685,7 +1737,8 @@
  29.230  PEP_STATUS _own_keys_retrieve(
  29.231          PEP_SESSION session,
  29.232          stringlist_t **keylist,
  29.233 -        identity_flags_t excluded_flags
  29.234 +        identity_flags_t excluded_flags,
  29.235 +        bool private_only
  29.236        )
  29.237  {
  29.238      PEP_STATUS status = PEP_STATUS_OK;
  29.239 @@ -1700,26 +1753,20 @@
  29.240      sqlite3_reset(session->own_keys_retrieve);
  29.241      
  29.242      int result;
  29.243 -    char *fpr = NULL;
  29.244      
  29.245      stringlist_t *_bl = _keylist;
  29.246 -    do {
  29.247 -        sqlite3_bind_int(session->own_keys_retrieve, 1, excluded_flags);
  29.248 +    sqlite3_bind_int(session->own_keys_retrieve, 1, excluded_flags);
  29.249 +
  29.250 +    do {        
  29.251          result = sqlite3_step(session->own_keys_retrieve);
  29.252          switch (result) {
  29.253              case SQLITE_ROW:
  29.254 -                fpr = strdup((const char *) sqlite3_column_text(session->own_keys_retrieve, 0));
  29.255 -                if(fpr == NULL)
  29.256 +                _bl = stringlist_add(_bl, (const char *)
  29.257 +                        sqlite3_column_text(session->own_keys_retrieve, 0));
  29.258 +                if (_bl == NULL)
  29.259                      goto enomem;
  29.260 -
  29.261 -                _bl = stringlist_add(_bl, fpr);
  29.262 -                if (_bl == NULL) {
  29.263 -                    free(fpr);
  29.264 -                    goto enomem;
  29.265 -                }
  29.266                  if (_keylist == NULL)
  29.267                      _keylist = _bl;
  29.268 -                
  29.269                  break;
  29.270                  
  29.271              case SQLITE_DONE:
  29.272 @@ -1732,8 +1779,33 @@
  29.273      } while (result != SQLITE_DONE);
  29.274      
  29.275      sqlite3_reset(session->own_keys_retrieve);
  29.276 -    if (status == PEP_STATUS_OK)
  29.277 +    if (status == PEP_STATUS_OK) {
  29.278 +        dedup_stringlist(_keylist);
  29.279 +        if (private_only) {
  29.280 +            stringlist_t* _kl = _keylist;
  29.281 +            stringlist_t* _kl_prev = NULL;
  29.282 +            while (_kl) {
  29.283 +                bool has_private = false;
  29.284 +                contains_priv_key(session, _kl->value, &has_private);
  29.285 +                if (!has_private) {
  29.286 +                    stringlist_t* _kl_tmp = _kl;
  29.287 +                    if (_kl_prev)
  29.288 +                        _kl_prev->next = _kl->next;
  29.289 +                    else 
  29.290 +                        _keylist = _kl->next;
  29.291 +                        
  29.292 +                    _kl = _kl->next;
  29.293 +                    
  29.294 +                    _kl_tmp->next = NULL;
  29.295 +                    free_stringlist(_kl_tmp);
  29.296 +                    continue;
  29.297 +                }
  29.298 +                _kl_prev = _kl;
  29.299 +                _kl = _kl->next;
  29.300 +            }
  29.301 +        }
  29.302          *keylist = _keylist;
  29.303 +    }
  29.304      else
  29.305          free_stringlist(_keylist);
  29.306      
  29.307 @@ -1749,7 +1821,7 @@
  29.308  
  29.309  DYNAMIC_API PEP_STATUS own_keys_retrieve(PEP_SESSION session, stringlist_t **keylist)
  29.310  {
  29.311 -    return _own_keys_retrieve(session, keylist, 0);
  29.312 +    return _own_keys_retrieve(session, keylist, 0, true);
  29.313  }
  29.314  
  29.315  DYNAMIC_API PEP_STATUS set_own_key(
  29.316 @@ -1770,7 +1842,7 @@
  29.317              EMPTYSTR(me->user_id) || EMPTYSTR(me->username))
  29.318          return PEP_ILLEGAL_VALUE;
  29.319  
  29.320 -    status = _myself(session, me, false, true);
  29.321 +    status = _myself(session, me, false, true, false);
  29.322      // we do not need a valid key but dislike other errors
  29.323      if (status != PEP_STATUS_OK && status != PEP_GET_KEY_FAILED && status != PEP_KEY_UNSUITABLE)
  29.324          return status;
  29.325 @@ -1939,6 +2011,7 @@
  29.326          thing = _pgp_thing_next(thing);
  29.327          switch (thing) {
  29.328              case _pgp_fpr:
  29.329 +                // PEP_OWN_USERID is ok here because this is only run on first use!
  29.330                  identity = new_identity(NULL, NULL, PEP_OWN_USERID, NULL);
  29.331                  if (!identity) {
  29.332                      status = PEP_OUT_OF_MEMORY;
    30.1 --- a/src/keymanagement.h	Thu Mar 28 15:40:45 2019 +0100
    30.2 +++ b/src/keymanagement.h	Fri May 17 17:30:57 2019 +0200
    30.3 @@ -114,7 +114,11 @@
    30.4  
    30.5  DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity);
    30.6  
    30.7 -PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags);
    30.8 +PEP_STATUS _myself(PEP_SESSION session, 
    30.9 +                   pEp_identity * identity, 
   30.10 +                   bool do_keygen, 
   30.11 +                   bool ignore_flags,
   30.12 +                   bool read_only);
   30.13  
   30.14  // retrieve_next_identity() - callback being called by do_keymanagement()
   30.15  //
   30.16 @@ -326,17 +330,19 @@
   30.17  //  parameters:
   30.18  //      session (in)            session to use
   30.19  //      keylist (out)           list of fingerprints
   30.20 -//      excluded_flags (int)    flags to exclude from results
   30.21 -//
   30.22 +//      excluded_flags (in)     flags to exclude from results
   30.23 +//      private_only (in)       if true, return only fprs for
   30.24 +//                              which we have the secret part
   30.25  //  caveat:
   30.26  //      the ownership of the list goes to the caller
   30.27  DYNAMIC_API PEP_STATUS _own_keys_retrieve(
   30.28          PEP_SESSION session,
   30.29          stringlist_t **keylist,
   30.30 -        identity_flags_t excluded_flags
   30.31 +        identity_flags_t excluded_flags,
   30.32 +        bool private_only
   30.33        );
   30.34  
   30.35 -// own_keys_retrieve() - retrieve all flagged keypair fingerprints 
   30.36 +// own_keys_retrieve() - retrieve all flagged public/private keypair fingerprints 
   30.37  //
   30.38  //  parameters:
   30.39  //      session (in)            session to use
   30.40 @@ -344,6 +350,8 @@
   30.41  //
   30.42  //  caveat:
   30.43  //      the ownership of the list goes to the caller
   30.44 +//      this function does not return keys without a private key part
   30.45 +//
   30.46  DYNAMIC_API PEP_STATUS own_keys_retrieve(
   30.47          PEP_SESSION session,
   30.48          stringlist_t **keylist
   30.49 @@ -375,7 +383,7 @@
   30.50                                   stringlist_t** keys);
   30.51  
   30.52  
   30.53 -PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags);
   30.54 +//PEP_STATUS _myself(PEP_SESSION session, pEp_identity * identity, bool do_keygen, bool ignore_flags);
   30.55  
   30.56  PEP_STATUS add_mistrusted_key(PEP_SESSION session, const char* fpr);
   30.57  PEP_STATUS delete_mistrusted_key(PEP_SESSION session, const char* fpr);
    31.1 --- a/src/message.h	Thu Mar 28 15:40:45 2019 +0100
    31.2 +++ b/src/message.h	Fri May 17 17:30:57 2019 +0200
    31.3 @@ -30,7 +30,8 @@
    31.4  
    31.5  typedef enum _PEP_enc_format {
    31.6      PEP_enc_none = 0,                       // message is not encrypted
    31.7 -    PEP_enc_pieces,                         // inline PGP + PGP extensions
    31.8 +    PEP_enc_pieces = 1,                     // inline PGP + PGP extensions, was removed
    31.9 +    PEP_enc_inline = 1,                     // still there
   31.10      PEP_enc_S_MIME,                         // RFC5751
   31.11      PEP_enc_PGP_MIME,                       // RFC3156
   31.12      PEP_enc_PEP,                            // pEp encryption format
    32.1 --- a/src/message_api.c	Thu Mar 28 15:40:45 2019 +0100
    32.2 +++ b/src/message_api.c	Fri May 17 17:30:57 2019 +0200
    32.3 @@ -10,6 +10,7 @@
    32.4  #include "baseprotocol.h"
    32.5  #include "KeySync_fsm.h"
    32.6  #include "base64.h"
    32.7 +#include "resource_id.h"
    32.8  
    32.9  #include <assert.h>
   32.10  #include <string.h>
   32.11 @@ -267,14 +268,6 @@
   32.12          return uri + 3;
   32.13  }
   32.14  
   32.15 -// static bool is_file_uri(char* str) {
   32.16 -//     return(strncmp(str, "file://", 7) == 0);
   32.17 -// }
   32.18 -
   32.19 -static bool is_cid_uri(const char* str) {
   32.20 -    return(strncmp(str, "cid://", 6) == 0);
   32.21 -}
   32.22 -
   32.23  static bool string_equality(const char *s1, const char *s2)
   32.24  {
   32.25      if (s1 == NULL || s2 == NULL)
   32.26 @@ -978,37 +971,57 @@
   32.27      return NULL;    
   32.28  }
   32.29  
   32.30 -static PEP_STATUS update_identity_recip_list(PEP_SESSION session,
   32.31 -                                             identity_list* list) {
   32.32 -
   32.33 -    PEP_STATUS status = PEP_STATUS_OK;
   32.34 -
   32.35 -    if (!session)
   32.36 -        return PEP_UNKNOWN_ERROR;
   32.37 -    
   32.38 -    identity_list* id_list_ptr = NULL;
   32.39 -        
   32.40 -    for (id_list_ptr = list; id_list_ptr; id_list_ptr = id_list_ptr->next) {
   32.41 -        pEp_identity* curr_identity = id_list_ptr->ident;
   32.42 -        if (curr_identity) {
   32.43 -            if (!is_me(session, curr_identity)) {
   32.44 -                char* name_bak = curr_identity->username;
   32.45 -                curr_identity->username = NULL;
   32.46 -                status = update_identity(session, curr_identity);
   32.47 -                if (name_bak && 
   32.48 -                    (EMPTYSTR(curr_identity->username) || strcmp(name_bak, curr_identity->username) != 0)) {
   32.49 -                    free(curr_identity->username);
   32.50 -                    curr_identity->username = name_bak;
   32.51 -                }                        
   32.52 -            }
   32.53 -            else
   32.54 -                status = myself(session, curr_identity);
   32.55 -        if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
   32.56 -            return status;
   32.57 -        }
   32.58 +static PEP_STATUS encrypt_PGP_inline(
   32.59 +        PEP_SESSION session,
   32.60 +        const message *src,
   32.61 +        stringlist_t *keys,
   32.62 +        message *dst,
   32.63 +        PEP_encrypt_flags_t flags
   32.64 +    )
   32.65 +{
   32.66 +    char *ctext = NULL;
   32.67 +    size_t csize = 0;
   32.68 +
   32.69 +    PEP_STATUS status = encrypt_and_sign(session, keys, src->longmsg,
   32.70 +            strlen(src->longmsg), &ctext, &csize);
   32.71 +    if (status)
   32.72 +        return status;
   32.73 +
   32.74 +    dst->enc_format = PEP_enc_inline;
   32.75 +
   32.76 +    // shortmsg is being copied
   32.77 +    if (src->shortmsg) {
   32.78 +        dst->shortmsg = strdup(src->shortmsg);
   32.79 +        assert(dst->shortmsg);
   32.80 +        if (!dst->shortmsg)
   32.81 +            return PEP_OUT_OF_MEMORY;
   32.82      }
   32.83 -    
   32.84 -    return PEP_STATUS_OK;                                  
   32.85 +
   32.86 +    // id is staying the same
   32.87 +    if (src->id) {
   32.88 +        dst->id = strdup(src->id);
   32.89 +        assert(dst->id);
   32.90 +        if (!dst->id)
   32.91 +            return PEP_OUT_OF_MEMORY;
   32.92 +    }
   32.93 +
   32.94 +    char *_ctext = realloc(ctext, csize + 1);
   32.95 +    assert(_ctext);
   32.96 +    if (!_ctext)
   32.97 +        return PEP_OUT_OF_MEMORY;
   32.98 +    _ctext[csize] = 0;
   32.99 +
  32.100 +    dst->longmsg = _ctext;
  32.101 +
  32.102 +    // longmsg_formatted is unsupported
  32.103 +
  32.104 +    // attachments are going unencrypted
  32.105 +    bloblist_t *bl = bloblist_dup(src->attachments);
  32.106 +    if (!bl)
  32.107 +        return PEP_OUT_OF_MEMORY;
  32.108 +    dst->attachments = bl;
  32.109 +
  32.110 +    return PEP_STATUS_OK;
  32.111  }
  32.112  
  32.113  static PEP_STATUS encrypt_PGP_MIME(
  32.114 @@ -1100,6 +1113,19 @@
  32.115      return status;
  32.116  }
  32.117  
  32.118 +static bool _has_PGP_MIME_format(message* msg) {
  32.119 +    if (!msg || !msg->attachments || !msg->attachments->next)
  32.120 +        return false;
  32.121 +    if (msg->attachments->next->next)
  32.122 +        return false;
  32.123 +    if (!msg->attachments->mime_type ||
  32.124 +        strcmp(msg->attachments->mime_type, "application/pgp-encrypted") != 0)    
  32.125 +        return false;
  32.126 +    if (!msg->attachments->next->mime_type || 
  32.127 +        strcmp(msg->attachments->next->mime_type, "application/octet-stream") != 0)        
  32.128 +        return false;
  32.129 +    return true;    
  32.130 +}
  32.131  
  32.132  static PEP_rating _rating(PEP_comm_type ct)
  32.133  {
  32.134 @@ -1306,7 +1332,8 @@
  32.135      if (!is_me(session, ident))
  32.136          status = update_identity(session, ident);
  32.137      else
  32.138 -        status = myself(session, ident);
  32.139 +        // ???
  32.140 +        status = _myself(session, ident, false, false, true);
  32.141  
  32.142      if (status == PEP_STATUS_OK) {
  32.143          if (ident->comm_type == PEP_ct_compromised)
  32.144 @@ -1360,15 +1387,15 @@
  32.145      return comm_type;
  32.146  }
  32.147  
  32.148 -static void free_bl_entry(bloblist_t *bl)
  32.149 -{
  32.150 -    if (bl) {
  32.151 -        free(bl->value);
  32.152 -        free(bl->mime_type);
  32.153 -        free(bl->filename);
  32.154 -        free(bl);
  32.155 -    }
  32.156 -}
  32.157 +// static void free_bl_entry(bloblist_t *bl)
  32.158 +// {
  32.159 +//     if (bl) {
  32.160 +//         free(bl->value);
  32.161 +//         free(bl->mime_type);
  32.162 +//         free(bl->filename);
  32.163 +//         free(bl);
  32.164 +//     }
  32.165 +// }
  32.166  
  32.167  static bool is_key(const bloblist_t *bl)
  32.168  {
  32.169 @@ -1389,33 +1416,52 @@
  32.170             );
  32.171  }
  32.172  
  32.173 -static void remove_attached_keys(message *msg)
  32.174 -{
  32.175 -    if (msg) {
  32.176 -        bloblist_t *last = NULL;
  32.177 -        for (bloblist_t *bl = msg->attachments; bl && bl->value; ) {
  32.178 -            bloblist_t *next = bl->next;
  32.179 -
  32.180 -            if (is_key(bl)) {
  32.181 -                if (last) {
  32.182 -                    last->next = next;
  32.183 -                }
  32.184 -                else {
  32.185 -                    msg->attachments = next;
  32.186 -                }
  32.187 -                free_bl_entry(bl);
  32.188 -            }
  32.189 -            else {
  32.190 -                last = bl;
  32.191 -            }
  32.192 -            bl = next;
  32.193 -        }
  32.194 +// static void remove_attached_keys(message *msg)
  32.195 +// {
  32.196 +//     if (msg) {
  32.197 +//         bloblist_t *last = NULL;
  32.198 +//         for (bloblist_t *bl = msg->attachments; bl && bl->value; ) {
  32.199 +//             bloblist_t *next = bl->next;
  32.200 +// 
  32.201 +//             if (is_key(bl)) {
  32.202 +//                 if (last) {
  32.203 +//                     last->next = next;
  32.204 +//                 }
  32.205 +//                 else {
  32.206 +//                     msg->attachments = next;
  32.207 +//                 }
  32.208 +//                 free_bl_entry(bl);
  32.209 +//             }
  32.210 +//             else {
  32.211 +//                 last = bl;
  32.212 +//             }
  32.213 +//             bl = next;
  32.214 +//         }
  32.215 +//     }
  32.216 +// }
  32.217 +
  32.218 +static bool compare_first_n_bytes(const char* first, const char* second, size_t n) {
  32.219 +    int i;
  32.220 +    for (i = 0; i < n; i++) {
  32.221 +        char num1 = *first;
  32.222 +        char num2 = *second;
  32.223 +
  32.224 +        if (num1 != num2)
  32.225 +            return false;
  32.226 +                    
  32.227 +        if (num1 == '\0') {
  32.228 +            if (num2 == '\0')
  32.229 +                return true;
  32.230 +        }   
  32.231 +        first++;
  32.232 +        second++;                     
  32.233      }
  32.234 +    return true;
  32.235  }
  32.236  
  32.237  bool import_attached_keys(
  32.238          PEP_SESSION session,
  32.239 -        const message *msg,
  32.240 +        message *msg,
  32.241          identity_list **private_idents
  32.242      )
  32.243  {
  32.244 @@ -1428,9 +1474,20 @@
  32.245      bool remove = false;
  32.246  
  32.247      int i = 0;
  32.248 +    
  32.249 +    bloblist_t* prev = NULL;
  32.250 +    
  32.251 +    bool do_not_advance = false;
  32.252 +    const char* pubkey_header = "-----BEGIN PGP PUBLIC KEY BLOCK-----";
  32.253 +    const char* privkey_header = "-----BEGIN PGP PRIVATE KEY BLOCK-----";
  32.254 +    // Hate my magic numbers at your peril, but I don't want a strlen each time
  32.255 +    const size_t PUBKEY_HSIZE = 36;
  32.256 +    const size_t PRIVKEY_HSIZE = 37;
  32.257 +
  32.258      for (bloblist_t *bl = msg->attachments; i < MAX_KEYS_TO_IMPORT && bl && bl->value;
  32.259 -            bl = bl->next, i++)
  32.260 +         i++)
  32.261      {
  32.262 +        do_not_advance = false;
  32.263          if (bl && bl->value && bl->size && bl->size < MAX_KEY_SIZE
  32.264                  && is_key(bl))
  32.265          {
  32.266 @@ -1460,12 +1517,42 @@
  32.267                      // We shouldn't delete it or import it, because we can't
  32.268                      // do the latter.
  32.269                      free(bl_ptext);
  32.270 +                    prev = bl;
  32.271 +                    bl = bl->next;
  32.272                      continue;
  32.273                  }
  32.274              }
  32.275              identity_list *local_private_idents = NULL;
  32.276 -            import_key(session, blob_value, blob_size, &local_private_idents);
  32.277 -            remove = true;
  32.278 +            PEP_STATUS import_status = import_key(session, blob_value, blob_size, &local_private_idents);
  32.279 +            bloblist_t* to_delete = NULL;
  32.280 +            switch (import_status) {
  32.281 +                case PEP_NO_KEY_IMPORTED:
  32.282 +                    break;
  32.283 +                case PEP_KEY_IMPORT_STATUS_UNKNOWN:
  32.284 +                    // We'll delete armoured stuff, at least
  32.285 +                    if (blob_size <= PUBKEY_HSIZE)
  32.286 +                        break;
  32.287 +                    if ((!compare_first_n_bytes(pubkey_header, (const char*)blob_value, PUBKEY_HSIZE)) &&
  32.288 +                       (!compare_first_n_bytes(privkey_header, (const char*)blob_value, PRIVKEY_HSIZE)))
  32.289 +                        break;
  32.290 +                    // else fall through and delete    
  32.291 +                case PEP_KEY_IMPORTED:
  32.292 +                case PEP_STATUS_OK:
  32.293 +                    to_delete = bl;
  32.294 +                    if (prev)
  32.295 +                        prev->next = bl->next;
  32.296 +                    else
  32.297 +                        msg->attachments = bl->next;
  32.298 +                    bl = bl->next;
  32.299 +                    to_delete->next = NULL;
  32.300 +                    free_bloblist(to_delete);
  32.301 +                    do_not_advance = true;
  32.302 +                    remove = true;
  32.303 +                    break;
  32.304 +                default:  
  32.305 +                    // bad stuff, but ok.
  32.306 +                    break;
  32.307 +            }
  32.308              if (private_idents && *private_idents == NULL && local_private_idents != NULL)
  32.309                  *private_idents = local_private_idents;
  32.310              else
  32.311 @@ -1473,6 +1560,10 @@
  32.312              if (free_blobval)
  32.313                  free(blob_value);
  32.314          }
  32.315 +        if (!do_not_advance) {
  32.316 +            prev = bl;
  32.317 +            bl = bl->next;
  32.318 +        }
  32.319      }
  32.320      return remove;
  32.321  }
  32.322 @@ -1537,7 +1628,7 @@
  32.323      assert(msg);
  32.324  
  32.325      if (is_PGP_message_text(msg->longmsg)) {
  32.326 -        msg->enc_format = PEP_enc_pieces;
  32.327 +        msg->enc_format = PEP_enc_inline;
  32.328          return PEP_crypt_OpenPGP;
  32.329      }
  32.330      else if (msg->attachments && msg->attachments->next &&
  32.331 @@ -1569,8 +1660,9 @@
  32.332      char* longmsg = NULL;
  32.333      char* shortmsg = NULL;
  32.334      char* msg_wrap_info = NULL;
  32.335 -    separate_short_and_long(src->longmsg, &shortmsg, &msg_wrap_info,
  32.336 -                            &longmsg);
  32.337 +    if (src->longmsg)
  32.338 +        separate_short_and_long(src->longmsg, &shortmsg, &msg_wrap_info,
  32.339 +                                &longmsg);
  32.340      if (longmsg) {                    
  32.341          free(src->longmsg);
  32.342          free(shortmsg);
  32.343 @@ -1846,7 +1938,7 @@
  32.344      }
  32.345      else {
  32.346          // FIXME - we need to deal with transport types (via flag)
  32.347 -        if ((!force_v_1) && ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp)) {
  32.348 +        if ((enc_format != PEP_enc_inline) && (!force_v_1) && ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp)) {
  32.349              message_wrap_type wrap_type = ((flags & PEP_encrypt_flag_key_reset_only) ? PEP_message_key_reset : PEP_message_default);
  32.350              _src = wrap_message_as_attachment(NULL, src, wrap_type, false);
  32.351              if (!_src)
  32.352 @@ -1854,7 +1946,7 @@
  32.353          }
  32.354          else {
  32.355              // hide subject
  32.356 -            if (!session->unencrypted_subject) {
  32.357 +            if (enc_format != PEP_enc_inline && !session->unencrypted_subject) {
  32.358                  status = replace_subject(_src);
  32.359                  if (status == PEP_OUT_OF_MEMORY)
  32.360                      goto enomem;
  32.361 @@ -1875,9 +1967,9 @@
  32.362                  status = encrypt_PGP_MIME(session, _src, keys, msg, flags);
  32.363                  break;
  32.364  
  32.365 -            /* case PEP_enc_PEP:
  32.366 -                // TODO: implement
  32.367 -                NOT_IMPLEMENTED */
  32.368 +            case PEP_enc_inline:
  32.369 +                status = encrypt_PGP_inline(session, _src, keys, msg, flags);
  32.370 +                break;
  32.371  
  32.372              default:
  32.373                  assert(0);
  32.374 @@ -2210,6 +2302,10 @@
  32.375                  _cleanup_src(src, false);
  32.376              break;
  32.377  
  32.378 +        case PEP_enc_inline:
  32.379 +            status = encrypt_PGP_inline(session, _src, keys, msg, flags);
  32.380 +            break;
  32.381 +
  32.382          default:
  32.383              assert(0);
  32.384              status = PEP_ILLEGAL_VALUE;
  32.385 @@ -2550,7 +2646,7 @@
  32.386      
  32.387      switch (src->enc_format) {
  32.388          case PEP_enc_PGP_MIME:
  32.389 -        case PEP_enc_pieces:
  32.390 +        case PEP_enc_inline:
  32.391          case PEP_enc_PGP_MIME_Outlook1:
  32.392  //        case PEP_enc_none: // FIXME - this is wrong
  32.393  
  32.394 @@ -2642,7 +2738,7 @@
  32.395              *text_size = src->attachments->size;
  32.396              break;
  32.397  
  32.398 -        case PEP_enc_pieces:
  32.399 +        case PEP_enc_inline:
  32.400              *crypto_text = src->longmsg;
  32.401              *text_size = strlen(*crypto_text);
  32.402              break;
  32.403 @@ -2770,6 +2866,15 @@
  32.404                                          
  32.405              free_stringlist(_keylist);
  32.406  
  32.407 +            char* filename_uri = NULL;
  32.408 +
  32.409 +            bool has_uri_prefix = (pgp_filename ? (is_file_uri(pgp_filename) || is_cid_uri(pgp_filename)) :
  32.410 +                                                  (_s->filename ? (is_file_uri(_s->filename) || is_cid_uri(_s->filename)) :
  32.411 +                                                                  false
  32.412 +                                                  )
  32.413 +                                  );
  32.414 +            
  32.415 +
  32.416              if (ptext) {
  32.417                  if (is_encrypted_html_attachment(_s)) {
  32.418                      msg->longmsg_formatted = ptext;
  32.419 @@ -2778,9 +2883,14 @@
  32.420                  else {
  32.421                      static const char * const mime_type = "application/octet-stream";                    
  32.422                      if (pgp_filename) {
  32.423 +                        if (!has_uri_prefix)
  32.424 +                            filename_uri = build_uri("file", pgp_filename);
  32.425 +
  32.426                          _m = bloblist_add(_m, ptext, psize, mime_type,
  32.427 -                             pgp_filename);
  32.428 -                        free(pgp_filename);                        
  32.429 +                             (filename_uri ? filename_uri : pgp_filename));
  32.430 +
  32.431 +                        free(pgp_filename);
  32.432 +                        free(filename_uri);
  32.433                          if (_m == NULL)
  32.434                              return PEP_OUT_OF_MEMORY;
  32.435                      }
  32.436 @@ -2790,9 +2900,13 @@
  32.437                          if (filename == NULL)
  32.438                              return PEP_OUT_OF_MEMORY;
  32.439  
  32.440 +                        if (!has_uri_prefix)
  32.441 +                            filename_uri = build_uri("file", filename);
  32.442 +
  32.443                          _m = bloblist_add(_m, ptext, psize, mime_type,
  32.444 -                            filename);
  32.445 +                             (filename_uri ? filename_uri : filename));
  32.446                          free(filename);
  32.447 +                        free(filename_uri);
  32.448                          if (_m == NULL)
  32.449                              return PEP_OUT_OF_MEMORY;
  32.450                      }
  32.451 @@ -2808,7 +2922,12 @@
  32.452                  if (copy == NULL)
  32.453                      return PEP_OUT_OF_MEMORY;
  32.454                  memcpy(copy, _s->value, _s->size);
  32.455 -                _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
  32.456 +
  32.457 +                if (!has_uri_prefix && _s->filename)
  32.458 +                    filename_uri = build_uri("file", _s->filename);
  32.459 +
  32.460 +                _m = bloblist_add(_m, copy, _s->size, _s->mime_type, 
  32.461 +                        (filename_uri ? filename_uri : _s->filename));
  32.462                  if (_m == NULL)
  32.463                      return PEP_OUT_OF_MEMORY;
  32.464              }
  32.465 @@ -2819,7 +2938,13 @@
  32.466              if (copy == NULL)
  32.467                  return PEP_OUT_OF_MEMORY;
  32.468              memcpy(copy, _s->value, _s->size);
  32.469 -            _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
  32.470 +
  32.471 +            char* filename_uri = NULL;
  32.472 +
  32.473 +            _m = bloblist_add(_m, copy, _s->size, _s->mime_type, 
  32.474 +                    ((_s->filename && !(is_file_uri(_s->filename) || is_cid_uri(_s->filename))) ?
  32.475 +                         (filename_uri = build_uri("file", _s->filename)) : _s->filename));
  32.476 +            free(filename_uri);
  32.477              if (_m == NULL)
  32.478                  return PEP_OUT_OF_MEMORY;
  32.479          }
  32.480 @@ -2829,23 +2954,30 @@
  32.481  }
  32.482  
  32.483  static PEP_STATUS import_priv_keys_from_decrypted_msg(PEP_SESSION session,
  32.484 -                                                      message* src, 
  32.485                                                        message* msg,
  32.486                                                        bool* imported_keys,
  32.487                                                        bool* imported_private,
  32.488 -                                                      identity_list** private_il) {
  32.489 -                                                          
  32.490 +                                                      identity_list** private_il)
  32.491 +{
  32.492 +    assert(msg && imported_keys && imported_private);
  32.493 +    if (!(msg && imported_keys && imported_private))
  32.494 +        return PEP_ILLEGAL_VALUE;
  32.495 +
  32.496      PEP_STATUS status = PEP_STATUS_OK;
  32.497 -    
  32.498 +    *imported_keys = NULL;
  32.499 +    *imported_private = false;
  32.500 +    if (private_il)
  32.501 +        *private_il = NULL;
  32.502 +
  32.503      // check for private key in decrypted message attachment while importing
  32.504      identity_list *_private_il = NULL;
  32.505 -    *imported_keys = import_attached_keys(session, msg, &_private_il);
  32.506 -    
  32.507 -    if (_private_il && identity_list_length(_private_il) == 1 &&
  32.508 -        _private_il->ident->address)
  32.509 -        *imported_private = true;
  32.510 -
  32.511 -    if (private_il && imported_private) {
  32.512 +
  32.513 +    bool _imported_keys = import_attached_keys(session, msg, &_private_il);
  32.514 +    bool _imported_private = false;
  32.515 +    if (_private_il && _private_il->ident && _private_il->ident->address)
  32.516 +        _imported_private = true;
  32.517 +
  32.518 +    if (private_il && _imported_private) {
  32.519          // the private identity list should NOT be subject to myself() or
  32.520          // update_identity() at this point.
  32.521          // If the receiving app wants them to be in the trust DB, it
  32.522 @@ -2855,30 +2987,35 @@
  32.523          char* own_id = NULL;
  32.524          status = get_default_own_userid(session, &own_id);
  32.525          
  32.526 -        if (status != PEP_STATUS_OK) {
  32.527 -            free(own_id);
  32.528 -            own_id = NULL;
  32.529 -        }
  32.530 -        
  32.531 -        identity_list* il = _private_il;
  32.532 -        for ( ; il; il = il->next) {
  32.533 +        for (identity_list* il = _private_il; il; il = il->next) {
  32.534              if (own_id) {
  32.535                  free(il->ident->user_id);
  32.536                  il->ident->user_id = strdup(own_id);
  32.537 +                assert(il->ident->user_id);
  32.538 +                if (!il->ident->user_id) {
  32.539 +                    status = PEP_OUT_OF_MEMORY;
  32.540 +                    break;
  32.541 +                }
  32.542              }
  32.543              il->ident->me = true;
  32.544          }
  32.545 -        *private_il = _private_il;
  32.546 -        
  32.547          free(own_id);
  32.548 +        if (!status)
  32.549 +            *private_il = _private_il;
  32.550 +    }
  32.551 +    else {
  32.552 +        free_identity_list(_private_il);
  32.553      }
  32.554 -    else
  32.555 -        free_identity_list(_private_il);
  32.556   
  32.557 -    
  32.558 +    if (!status) {
  32.559 +        *imported_keys = _imported_keys;
  32.560 +        *imported_private = _imported_private;
  32.561 +    }
  32.562 +
  32.563      return status;
  32.564  }
  32.565  
  32.566 +// FIXME: myself ??????
  32.567  static PEP_STATUS update_sender_to_pEp_trust(
  32.568          PEP_SESSION session, 
  32.569          pEp_identity* sender, 
  32.570 @@ -2951,6 +3088,8 @@
  32.571      }
  32.572      
  32.573      resultid->lang[0] = srcid->lang[0];
  32.574 +    resultid->lang[1] = srcid->lang[1];
  32.575 +    resultid->lang[2] = 0;
  32.576      resultid->me = srcid->me;
  32.577      resultid->flags = srcid->flags;
  32.578  
  32.579 @@ -3102,7 +3241,7 @@
  32.580          return false;
  32.581      PEP_STATUS status = import_key(session, the_key->value, the_key->size, NULL);
  32.582      free_bloblist(the_key);
  32.583 -    if (status == PEP_STATUS_OK)
  32.584 +    if (status == PEP_STATUS_OK || status == PEP_KEY_IMPORTED)
  32.585          return true;
  32.586      return false;
  32.587  }
  32.588 @@ -3173,7 +3312,7 @@
  32.589  
  32.590  }
  32.591  
  32.592 -DYNAMIC_API PEP_STATUS _decrypt_message(
  32.593 +static PEP_STATUS _decrypt_message(
  32.594          PEP_SESSION session,
  32.595          message *src,
  32.596          message **dst,
  32.597 @@ -3183,7 +3322,6 @@
  32.598          identity_list **private_il
  32.599      )
  32.600  {
  32.601 -    
  32.602      assert(session);
  32.603      assert(src);
  32.604      assert(dst);
  32.605 @@ -3209,6 +3347,7 @@
  32.606      stringlist_t *_keylist = NULL;
  32.607      char* signer_fpr = NULL;
  32.608      bool is_pEp_msg = is_a_pEpmessage(src);
  32.609 +    bool myself_read_only = (src->dir == PEP_dir_incoming);
  32.610  
  32.611      // Grab input flags
  32.612      bool reencrypt = (((*flags & PEP_decrypt_flag_untrusted_server) > 0) && *keylist && !EMPTYSTR((*keylist)->value));
  32.613 @@ -3258,7 +3397,13 @@
  32.614  
  32.615      /*** Begin Import any attached public keys and update identities accordingly ***/
  32.616      // Private key in unencrypted mail are ignored -> NULL
  32.617 -    bool imported_keys = import_attached_keys(session, src, NULL);
  32.618 +    //
  32.619 +    // This import is from the outermost message.
  32.620 +    // We don't do this for PGP_mime.
  32.621 +    bool imported_keys = false;
  32.622 +    if (!_has_PGP_MIME_format(src))
  32.623 +        imported_keys = import_attached_keys(session, src, NULL);
  32.624 +            
  32.625      import_header_keys(session, src);
  32.626      
  32.627      // FIXME: is this really necessary here?
  32.628 @@ -3266,7 +3411,7 @@
  32.629          if (!is_me(session, src->from))
  32.630              status = update_identity(session, src->from);
  32.631          else
  32.632 -            status = myself(session, src->from);
  32.633 +            status = _myself(session, src->from, false, false, myself_read_only);
  32.634          
  32.635          // We absolutely should NOT be bailing here unless it's a serious error
  32.636          if (status == PEP_OUT_OF_MEMORY)
  32.637 @@ -3295,8 +3440,9 @@
  32.638  
  32.639          *rating = PEP_rating_unencrypted;
  32.640  
  32.641 -        if (imported_keys)
  32.642 -            remove_attached_keys(src);
  32.643 +        // We remove these from the outermost source message
  32.644 +        // if (imported_keys)
  32.645 +        //     remove_attached_keys(src);
  32.646                                      
  32.647          pull_up_attached_main_msg(src);
  32.648          
  32.649 @@ -3346,7 +3492,10 @@
  32.650                  // N.B. Apparently, we always import private keys into the keyring; however,
  32.651                  // we do NOT always allow those to be used for encryption. THAT is controlled
  32.652                  // by setting it as an own identity associated with the key in the DB.
  32.653 -                status = import_priv_keys_from_decrypted_msg(session, src, msg,
  32.654 +                //
  32.655 +                // We are importing from the decrypted outermost message now.
  32.656 +                //
  32.657 +                status = import_priv_keys_from_decrypted_msg(session, msg,
  32.658                                                               &imported_keys,
  32.659                                                               &imported_private_key_address,
  32.660                                                               private_il);
  32.661 @@ -3366,7 +3515,7 @@
  32.662                  }
  32.663                  break;
  32.664  
  32.665 -            case PEP_enc_pieces:
  32.666 +            case PEP_enc_inline:
  32.667                  status = PEP_STATUS_OK;
  32.668                  
  32.669                  _decrypt_in_pieces_status = _decrypt_in_pieces(session, src, &msg, ptext, psize);
  32.670 @@ -3469,9 +3618,11 @@
  32.671                                              // If we have a message 2.0 message, we are ONLY going to be ok with keys
  32.672                                              // we imported from THIS part of the message.
  32.673                                              imported_private_key_address = false;
  32.674 -                                            free(private_il);
  32.675 +                                            free(private_il); 
  32.676                                              private_il = NULL;
  32.677 -                                            status = import_priv_keys_from_decrypted_msg(session, src, inner_message,
  32.678 +                                            
  32.679 +                                            // import keys from decrypted INNER source
  32.680 +                                            status = import_priv_keys_from_decrypted_msg(session, inner_message,
  32.681                                                                                           &imported_keys,
  32.682                                                                                           &imported_private_key_address,
  32.683                                                                                           private_il);
  32.684 @@ -3494,7 +3645,7 @@
  32.685                                                  if (!is_me(session, src->from))
  32.686                                                      update_identity(session, (src->from));
  32.687                                                  else
  32.688 -                                                    myself(session, src->from);
  32.689 +                                                    _myself(session, src->from, false, false, myself_read_only);
  32.690                                              }
  32.691                                              break;        
  32.692                                          }
  32.693 @@ -3576,9 +3727,10 @@
  32.694          
  32.695          /* add pEp-related status flags to header */
  32.696          decorate_message(msg, *rating, _keylist, false, false);
  32.697 -        
  32.698 -        if (imported_keys)
  32.699 -            remove_attached_keys(msg);
  32.700 +
  32.701 +        // Maybe unnecessary
  32.702 +        // if (imported_keys)
  32.703 +        //     remove_attached_keys(msg);
  32.704                      
  32.705          if (calculated_src->id && calculated_src != msg) {
  32.706              msg->id = strdup(calculated_src->id);
  32.707 @@ -3737,22 +3889,17 @@
  32.708  
  32.709      message *msg = *dst ? *dst : src;
  32.710  
  32.711 -    if (session->inject_sync_event && msg && msg->from) {
  32.712 +    if (session->inject_sync_event && msg && msg->from &&
  32.713 +            !(*flags & PEP_decrypt_flag_dont_trigger_sync)) {
  32.714          size_t size;
  32.715          const char *data;
  32.716          char *sync_fpr = NULL;
  32.717 -        status = base_extract_message(session, msg, &size, &data, &sync_fpr);
  32.718 -        if (!status && size && data) {
  32.719 -            pEp_identity *_from = identity_dup(msg->from);
  32.720 -            if (!_from) {
  32.721 -                free_message(*dst);
  32.722 -                *dst = NULL;
  32.723 -                free_stringlist(*keylist);
  32.724 -                *keylist = NULL;
  32.725 -                return PEP_OUT_OF_MEMORY;
  32.726 -            }
  32.727 -            session->sync_state.common.from = _from;
  32.728 -            signal_Sync_message(session, *rating, data, size, sync_fpr);
  32.729 +        PEP_STATUS tmpstatus = base_extract_message(session, msg, &size, &data, &sync_fpr);
  32.730 +        if (!tmpstatus && size && data) {
  32.731 +            if (sync_fpr)
  32.732 +                signal_Sync_message(session, *rating, data, size, msg->from, sync_fpr);
  32.733 +            else if (*keylist)
  32.734 +                signal_Sync_message(session, *rating, data, size, msg->from, (*keylist)->value);
  32.735          }
  32.736          free(sync_fpr);
  32.737      }
  32.738 @@ -3957,8 +4104,10 @@
  32.739      if (!(session && ident && rating))
  32.740          return PEP_ILLEGAL_VALUE;
  32.741  
  32.742 +    *rating = PEP_rating_undefined;
  32.743 +
  32.744      if (ident->me)
  32.745 -        status = _myself(session, ident, false, true);
  32.746 +        status = _myself(session, ident, false, true, true);
  32.747      else
  32.748          status = update_identity(session, ident);
  32.749  
  32.750 @@ -4307,10 +4456,21 @@
  32.751      // Find own identity corresponding to given account address.
  32.752      // In that case we want default key attached to own identity
  32.753      pEp_identity *stored_identity = NULL;
  32.754 +    
  32.755 +    char* own_id = NULL;
  32.756 +    status = get_default_own_userid(session, &own_id);
  32.757 +
  32.758 +    if (!(status == PEP_STATUS_OK && own_id)) {
  32.759 +        free(own_id);
  32.760 +        return PEP_CANNOT_FIND_IDENTITY;
  32.761 +    }
  32.762 +    
  32.763      status = get_identity(session,
  32.764                            received_by->address,
  32.765 -                          PEP_OWN_USERID,
  32.766 +                          own_id,
  32.767                            &stored_identity);
  32.768 +    free(own_id);
  32.769 +    own_id = NULL;                      
  32.770  
  32.771      if (status != PEP_STATUS_OK) {
  32.772          free_identity(stored_identity);
  32.773 @@ -4326,227 +4486,6 @@
  32.774      return status;
  32.775  }
  32.776  
  32.777 -DYNAMIC_API PEP_STATUS MIME_decrypt_message(
  32.778 -    PEP_SESSION session,
  32.779 -    const char *mimetext,
  32.780 -    size_t size,
  32.781 -    char** mime_plaintext,
  32.782 -    stringlist_t **keylist,
  32.783 -    PEP_rating *rating,
  32.784 -    PEP_decrypt_flags_t *flags,
  32.785 -    char** modified_src
  32.786 -)
  32.787 -{
  32.788 -    assert(mimetext);
  32.789 -    assert(mime_plaintext);
  32.790 -    assert(keylist);
  32.791 -    assert(rating);
  32.792 -    assert(flags);
  32.793 -    assert(modified_src);
  32.794 -
  32.795 -    if (!(mimetext && mime_plaintext && keylist && rating && flags && modified_src))
  32.796 -        return PEP_ILLEGAL_VALUE;
  32.797 -        
  32.798 -    PEP_STATUS status = PEP_STATUS_OK;
  32.799 -    message* tmp_msg = NULL;
  32.800 -    message* dec_msg = NULL;
  32.801 -    *mime_plaintext = NULL;
  32.802 -
  32.803 -    status = mime_decode_message(mimetext, size, &tmp_msg);
  32.804 -    if (status != PEP_STATUS_OK)
  32.805 -        goto pEp_error;
  32.806 -
  32.807 -    // MIME decode message delivers only addresses. We need more.
  32.808 -    if (tmp_msg->from) {
  32.809 -        if (!is_me(session, tmp_msg->from))
  32.810 -            status = update_identity(session, (tmp_msg->from));
  32.811 -        else
  32.812 -            status = myself(session, tmp_msg->from);
  32.813 -
  32.814 -        if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
  32.815 -            goto pEp_error;
  32.816 -    }
  32.817 -
  32.818 -    status = update_identity_recip_list(session, tmp_msg->to);
  32.819 -    if (status != PEP_STATUS_OK)
  32.820 -        goto pEp_error;
  32.821 -
  32.822 -    status = update_identity_recip_list(session, tmp_msg->cc);
  32.823 -    if (status != PEP_STATUS_OK)
  32.824 -        goto pEp_error;
  32.825 -
  32.826 -    status = update_identity_recip_list(session, tmp_msg->bcc);
  32.827 -    if (status != PEP_STATUS_OK)
  32.828 -        goto pEp_error;
  32.829 -
  32.830 -    PEP_STATUS decrypt_status = decrypt_message(session,
  32.831 -                                                tmp_msg,
  32.832 -                                                &dec_msg,
  32.833 -                                                keylist,
  32.834 -                                                rating,
  32.835 -                                                flags);
  32.836 -
  32.837 -
  32.838 -    if (!dec_msg && (decrypt_status == PEP_UNENCRYPTED || decrypt_status == PEP_VERIFIED)) {
  32.839 -        dec_msg = message_dup(tmp_msg);
  32.840 -    }
  32.841 -    
  32.842 -    if (decrypt_status > PEP_CANNOT_DECRYPT_UNKNOWN || !dec_msg)
  32.843 -    {
  32.844 -        status = decrypt_status;
  32.845 -        goto pEp_error;
  32.846 -    }
  32.847 -
  32.848 -    if (*flags & PEP_decrypt_flag_src_modified) {
  32.849 -        _mime_encode_message_internal(tmp_msg, false, modified_src, true);
  32.850 -        if (!modified_src) {
  32.851 -            *flags &= (~PEP_decrypt_flag_src_modified);
  32.852 -            decrypt_status = PEP_CANNOT_REENCRYPT; // Because we couldn't return it, I guess.
  32.853 -        }
  32.854 -    }
  32.855 -
  32.856 -    // FIXME: test with att
  32.857 -    status = _mime_encode_message_internal(dec_msg, false, mime_plaintext, true);
  32.858 -
  32.859 -    if (status == PEP_STATUS_OK)
  32.860 -    {
  32.861 -        free(tmp_msg);
  32.862 -        free(dec_msg);
  32.863 -        return decrypt_status;
  32.864 -    }
  32.865 -    
  32.866 -pEp_error:
  32.867 -    free_message(tmp_msg);
  32.868 -    free_message(dec_msg);
  32.869 -
  32.870 -    return status;
  32.871 -}
  32.872 -
  32.873 -
  32.874 -DYNAMIC_API PEP_STATUS MIME_encrypt_message(
  32.875 -    PEP_SESSION session,
  32.876 -    const char *mimetext,
  32.877 -    size_t size,
  32.878 -    stringlist_t* extra,
  32.879 -    char** mime_ciphertext,
  32.880 -    PEP_enc_format enc_format,
  32.881 -    PEP_encrypt_flags_t flags
  32.882 -)
  32.883 -{
  32.884 -    PEP_STATUS status = PEP_STATUS_OK;
  32.885 -    message* tmp_msg = NULL;
  32.886 -    message* enc_msg = NULL;
  32.887 -
  32.888 -    status = mime_decode_message(mimetext, size, &tmp_msg);
  32.889 -    if (status != PEP_STATUS_OK)
  32.890 -        goto pEp_error;
  32.891 -
  32.892 -    // MIME decode message delivers only addresses. We need more.
  32.893 -    if (tmp_msg->from) {
  32.894 -        char* own_id = NULL;
  32.895 -        status = get_default_own_userid(session, &own_id);
  32.896 -        free(tmp_msg->from->user_id);
  32.897 -        
  32.898 -        if (status != PEP_STATUS_OK || !own_id) {
  32.899 -            tmp_msg->from->user_id = strdup(PEP_OWN_USERID);
  32.900 -        }
  32.901 -        else {
  32.902 -            tmp_msg->from->user_id = own_id; // ownership transfer
  32.903 -        }
  32.904 -            
  32.905 -        status = myself(session, tmp_msg->from);
  32.906 -        if (status != PEP_STATUS_OK)
  32.907 -            goto pEp_error;
  32.908 -    }
  32.909 -    
  32.910 -    // Own identities can be retrieved here where they would otherwise
  32.911 -    // fail because we lack all other information. This is ok and even
  32.912 -    // desired. FIXME: IS it?
  32.913 -    status = update_identity_recip_list(session, tmp_msg->to);
  32.914 -    if (status != PEP_STATUS_OK)
  32.915 -        goto pEp_error;
  32.916 -    
  32.917 -    status = update_identity_recip_list(session, tmp_msg->cc);
  32.918 -    if (status != PEP_STATUS_OK)
  32.919 -        goto pEp_error;
  32.920 -    
  32.921 -    status = update_identity_recip_list(session, tmp_msg->bcc);
  32.922 -    if (status != PEP_STATUS_OK)
  32.923 -        goto pEp_error;
  32.924 -    
  32.925 -    // This isn't incoming, though... so we need to reverse the direction
  32.926 -    tmp_msg->dir = PEP_dir_outgoing;
  32.927 -    status = encrypt_message(session,
  32.928 -                             tmp_msg,
  32.929 -                             extra,
  32.930 -                             &enc_msg,
  32.931 -                             enc_format,
  32.932 -                             flags);
  32.933 -                             
  32.934 -    if (status != PEP_STATUS_OK)
  32.935 -        goto pEp_error;
  32.936 -
  32.937 -
  32.938 -    if (!enc_msg) {
  32.939 -        status = PEP_UNKNOWN_ERROR;
  32.940 -        goto pEp_error;
  32.941 -    }
  32.942 -
  32.943 -    status = _mime_encode_message_internal(enc_msg, false, mime_ciphertext, false);
  32.944 -
  32.945 -pEp_error:
  32.946 -    free_message(tmp_msg);
  32.947 -    free_message(enc_msg);
  32.948 -
  32.949 -    return status;
  32.950 -
  32.951 -}
  32.952 -
  32.953 -DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
  32.954 -    PEP_SESSION session,
  32.955 -    pEp_identity* target_id,
  32.956 -    const char *mimetext,
  32.957 -    size_t size,
  32.958 -    stringlist_t* extra,
  32.959 -    char** mime_ciphertext,
  32.960 -    PEP_enc_format enc_format,
  32.961 -    PEP_encrypt_flags_t flags
  32.962 -)
  32.963 -{
  32.964 -    PEP_STATUS status = PEP_STATUS_OK;
  32.965 -    message* tmp_msg = NULL;
  32.966 -    message* enc_msg = NULL;
  32.967 -
  32.968 -    status = mime_decode_message(mimetext, size, &tmp_msg);
  32.969 -    if (status != PEP_STATUS_OK)
  32.970 -        goto pEp_error;
  32.971 -
  32.972 -    // This isn't incoming, though... so we need to reverse the direction
  32.973 -    tmp_msg->dir = PEP_dir_outgoing;
  32.974 -    status = encrypt_message_for_self(session,
  32.975 -                                      target_id,
  32.976 -                                      tmp_msg,
  32.977 -                                      extra,
  32.978 -                                      &enc_msg,
  32.979 -                                      enc_format,
  32.980 -                                      flags);
  32.981 -    if (status != PEP_STATUS_OK)
  32.982 -        goto pEp_error;
  32.983 - 
  32.984 -    if (!enc_msg) {
  32.985 -        status = PEP_UNKNOWN_ERROR;
  32.986 -        goto pEp_error;
  32.987 -    }
  32.988 -
  32.989 -    status = mime_encode_message(enc_msg, false, mime_ciphertext);
  32.990 -
  32.991 -pEp_error:
  32.992 -    free_message(tmp_msg);
  32.993 -    free_message(enc_msg);
  32.994 -
  32.995 -    return status;
  32.996 -}
  32.997 -
  32.998  static PEP_rating string_to_rating(const char * rating)
  32.999  {
 32.1000      if (rating == NULL)
 32.1001 @@ -4679,7 +4618,7 @@
 32.1002      if (!is_me(session, msg->from))
 32.1003          status = update_identity(session, msg->from);
 32.1004      else
 32.1005 -        status = myself(session, msg->from);
 32.1006 +        status = _myself(session, msg->from, false, false, true);
 32.1007  
 32.1008      switch (status) {
 32.1009          case PEP_KEY_NOT_FOUND:
 32.1010 @@ -4738,4 +4677,3 @@
 32.1011      free_identity(ident);
 32.1012      return status;
 32.1013  }
 32.1014 -
    33.1 --- a/src/message_api.h	Thu Mar 28 15:40:45 2019 +0100
    33.2 +++ b/src/message_api.h	Fri May 17 17:30:57 2019 +0200
    33.3 @@ -14,7 +14,7 @@
    33.4  
    33.5  bool import_attached_keys(
    33.6          PEP_SESSION session, 
    33.7 -        const message *msg,
    33.8 +        message *msg,
    33.9          identity_list **private_idents
   33.10      );
   33.11  
   33.12 @@ -159,78 +159,6 @@
   33.13          PEP_encrypt_flags_t flags
   33.14      );
   33.15  
   33.16 -
   33.17 -// MIME_encrypt_message() - encrypt a MIME message, with MIME output
   33.18 -//
   33.19 -//  parameters:
   33.20 -//      session (in)            session handle
   33.21 -//      mimetext (in)           MIME encoded text to encrypt
   33.22 -//      size (in)               size of input mime text
   33.23 -//      extra (in)              extra keys for encryption
   33.24 -//      mime_ciphertext (out)   encrypted, encoded message
   33.25 -//      enc_format (in)         encrypted format
   33.26 -//      flags (in)              flags to set special encryption features
   33.27 -//
   33.28 -//  return value:
   33.29 -//      PEP_STATUS_OK           if everything worked
   33.30 -//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
   33.31 -//      PEP_CANNOT_CREATE_TEMP_FILE
   33.32 -//                              if there are issues with temp files; in
   33.33 -//                              this case errno will contain the underlying
   33.34 -//                              error
   33.35 -//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
   33.36 -//
   33.37 -//  caveat:
   33.38 -//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
   33.39 -//      will remain in the ownership of the caller
   33.40 -DYNAMIC_API PEP_STATUS MIME_encrypt_message(
   33.41 -    PEP_SESSION session,
   33.42 -    const char *mimetext,
   33.43 -    size_t size,
   33.44 -    stringlist_t* extra,
   33.45 -    char** mime_ciphertext,
   33.46 -    PEP_enc_format enc_format,
   33.47 -    PEP_encrypt_flags_t flags
   33.48 -);
   33.49 -
   33.50 -
   33.51 -// MIME_encrypt_message_for_self() - encrypt MIME message for user's identity only,
   33.52 -//                              ignoring recipients and other identities from
   33.53 -//                              the message, with MIME output
   33.54 -//  parameters:
   33.55 -//      session (in)            session handle
   33.56 -//      target_id (in)          self identity this message should be encrypted for
   33.57 -//      mimetext (in)           MIME encoded text to encrypt
   33.58 -//      size (in)               size of input mime text
   33.59 -//      extra (in)              extra keys for encryption
   33.60 -//      mime_ciphertext (out)   encrypted, encoded message
   33.61 -//      enc_format (in)         encrypted format
   33.62 -//      flags (in)              flags to set special encryption features
   33.63 -//
   33.64 -//  return value:
   33.65 -//      PEP_STATUS_OK           if everything worked
   33.66 -//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
   33.67 -//      PEP_CANNOT_CREATE_TEMP_FILE
   33.68 -//                              if there are issues with temp files; in
   33.69 -//                              this case errno will contain the underlying
   33.70 -//                              error
   33.71 -//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
   33.72 -//
   33.73 -//  caveat:
   33.74 -//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
   33.75 -//      will remain in the ownership of the caller
   33.76 -DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
   33.77 -    PEP_SESSION session,
   33.78 -    pEp_identity* target_id,
   33.79 -    const char *mimetext,
   33.80 -    size_t size,
   33.81 -    stringlist_t* extra,
   33.82 -    char** mime_ciphertext,
   33.83 -    PEP_enc_format enc_format,
   33.84 -    PEP_encrypt_flags_t flags
   33.85 -);
   33.86 -
   33.87 -
   33.88  typedef enum _PEP_rating {
   33.89      PEP_rating_undefined = 0,
   33.90      PEP_rating_cannot_decrypt,
   33.91 @@ -270,7 +198,8 @@
   33.92      PEP_decrypt_flag_ignore = 0x4,
   33.93      PEP_decrypt_flag_src_modified = 0x8,
   33.94      // input flags    
   33.95 -    PEP_decrypt_flag_untrusted_server = 0x100
   33.96 +    PEP_decrypt_flag_untrusted_server = 0x100,
   33.97 +    PEP_decrypt_flag_dont_trigger_sync = 0x200,
   33.98  } PEP_decrypt_flags; 
   33.99  
  33.100  typedef unsigned int PEP_decrypt_flags_t;
  33.101 @@ -337,65 +266,6 @@
  33.102          PEP_decrypt_flags_t *flags
  33.103  );
  33.104  
  33.105 -
  33.106 -// MIME_decrypt_message() - decrypt a MIME message, with MIME output
  33.107 -//
  33.108 -//  parameters:
  33.109 -//      session (in)            session handle
  33.110 -//      mimetext (in)           MIME encoded text to decrypt
  33.111 -//      size (in)               size of mime text to decode (in order to decrypt)
  33.112 -//      mime_plaintext (out)    decrypted, encoded message
  33.113 -//      keylist (inout)         in: stringlist with additional keyids for reencryption if needed
  33.114 -//                                  (will be freed and replaced with output keylist)
  33.115 -//                              out: stringlist with keyids
  33.116 -//      rating (out)            rating for the message
  33.117 -//      flags (inout)           flags to signal special decryption features (see below)
  33.118 -//      modified_src (out)      modified source string, if decrypt had reason to change it
  33.119 -//
  33.120 -//  return value:
  33.121 -//      decrypt status          if everything worked with MIME encode/decode, 
  33.122 -//                              the status of the decryption is returned 
  33.123 -//                              (PEP_STATUS_OK or decryption error status)
  33.124 -//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
  33.125 -//      PEP_CANNOT_CREATE_TEMP_FILE
  33.126 -//                              if there are issues with temp files; in
  33.127 -//                              this case errno will contain the underlying
  33.128 -//                              error
  33.129 -//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
  33.130 -//
  33.131 -//  flag values:
  33.132 -//      in:
  33.133 -//          PEP_decrypt_flag_untrusted_server
  33.134 -//              used to signal that decrypt function should engage in behaviour
  33.135 -//              specified for when the server storing the source is untrusted.
  33.136 -//      out:
  33.137 -//          PEP_decrypt_flag_own_private_key
  33.138 -//              private key was imported for one of our addresses (NOT trusted
  33.139 -//              or set to be used - handshake/trust is required for that)
  33.140 -//          PEP_decrypt_flag_src_modified
  33.141 -//              indicates that the modified_src field should contain a modified
  33.142 -//              version of the source, at the moment always as a result of the
  33.143 -//              input flags. 
  33.144 -//          PEP_decrypt_flag_consume
  33.145 -//              used by sync 
  33.146 -//          PEP_decrypt_flag_ignore
  33.147 -//              used by sync 
  33.148 -// 
  33.149 -//  caveat:
  33.150 -//      the decrypted, encoded mime text will go to the ownership of the caller; mimetext
  33.151 -//      will remain in the ownership of the caller
  33.152 -DYNAMIC_API PEP_STATUS MIME_decrypt_message(
  33.153 -    PEP_SESSION session,
  33.154 -    const char *mimetext,
  33.155 -    size_t size,
  33.156 -    char** mime_plaintext,
  33.157 -    stringlist_t **keylist,
  33.158 -    PEP_rating *rating,
  33.159 -    PEP_decrypt_flags_t *flags,
  33.160 -    char** modified_src
  33.161 -);
  33.162 -
  33.163 -
  33.164  // own_message_private_key_details() - details on own key in own message
  33.165  //
  33.166  //  parameters:
    34.1 --- a/src/mime.c	Thu Mar 28 15:40:45 2019 +0100
    34.2 +++ b/src/mime.c	Fri May 17 17:30:57 2019 +0200
    34.3 @@ -1,7 +1,7 @@
    34.4  // This file is under GNU General Public License 3.0
    34.5  // see LICENSE.txt
    34.6  
    34.7 -#include "pEp_internal.h"
    34.8 +#define _EXPORT_PEP_ENGINE_DLL
    34.9  #include "mime.h"
   34.10  
   34.11  #include <string.h>
   34.12 @@ -9,10 +9,6 @@
   34.13  #include <assert.h>
   34.14  #include <errno.h>
   34.15  
   34.16 -#include "resource_id.h"
   34.17 -#include "etpan_mime.h"
   34.18 -#include "wrappers.h"
   34.19 -
   34.20  static bool is_whitespace(char c)
   34.21  {
   34.22      switch (c) {
   34.23 @@ -37,889 +33,6 @@
   34.24      return strncmp(text, "-----BEGIN PGP MESSAGE-----", 27) == 0;
   34.25  }
   34.26  
   34.27 -#define TMP_TEMPLATE "pEp.XXXXXXXXXXXXXXXXXXXX"
   34.28 -#ifdef _WIN32
   34.29 -#define PATH_SEP '\\'
   34.30 -#else
   34.31 -#define PATH_SEP '/'
   34.32 -#endif
   34.33 -
   34.34 -// This function was rewritten to use in-memory buffers instead of
   34.35 -// temporary files when the pgp/mime support was implemented for
   34.36 -// outlook, as the existing code did not work well on windows.
   34.37 -
   34.38 -static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
   34.39 -{
   34.40 -    PEP_STATUS status = PEP_STATUS_OK;
   34.41 -    int col;
   34.42 -    int r;
   34.43 -	size_t len;
   34.44 -	char* buf = NULL;
   34.45 -
   34.46 -	MMAPString* buffer;
   34.47 -
   34.48 -	buffer = mmap_string_new(NULL);
   34.49 -	if (buffer == NULL)
   34.50 -		goto enomem;
   34.51 -	
   34.52 -	col = 0;
   34.53 -	r = mailmime_write_mem(buffer, &col, mime);
   34.54 -	assert(r == MAILIMF_NO_ERROR);
   34.55 -	if (r == MAILIMF_ERROR_MEMORY)
   34.56 -		goto enomem;
   34.57 -	else if (r != MAILIMF_NO_ERROR)
   34.58 -		goto err_file;
   34.59 -
   34.60 -	// we overallocate by 1 byte, so we have a terminating 0.
   34.61 -	len = buffer->len;
   34.62 -	buf = calloc(len + 1, 1);
   34.63 -	if (buf == NULL)
   34.64 -		goto enomem;
   34.65 -
   34.66 -	memcpy(buf, buffer->str, len);
   34.67 -	mmap_string_free(buffer);
   34.68 -
   34.69 -    *mimetext = buf;
   34.70 -    return PEP_STATUS_OK;
   34.71 -
   34.72 -err_file:
   34.73 -    status = PEP_CANNOT_CREATE_TEMP_FILE;
   34.74 -    goto pEp_error;
   34.75 -
   34.76 -enomem:
   34.77 -    status = PEP_OUT_OF_MEMORY;
   34.78 -
   34.79 -pEp_error:
   34.80 -	if (buffer)
   34.81 -		mmap_string_free(buffer);
   34.82 -	if (buf)
   34.83 -		free(buf);
   34.84 -    return status;
   34.85 -}
   34.86 -
   34.87 -static PEP_STATUS mime_attachment(
   34.88 -        bloblist_t *blob,
   34.89 -        struct mailmime **result,
   34.90 -        bool transport_encode
   34.91 -    )
   34.92 -{
   34.93 -    PEP_STATUS status = PEP_STATUS_OK;
   34.94 -    struct mailmime * mime = NULL;
   34.95 -    char * mime_type;
   34.96 -    assert(blob);
   34.97 -    assert(result);
   34.98 -
   34.99 -    *result = NULL;
  34.100 -
  34.101 -// TODO: It seems the pEp COM server adapter sends an empty string here,
  34.102 -// which leads to a crash later. Thus, we workaround here by treating an
  34.103 -// empty string as NULL. We need to check whether the bug really is here,
  34.104 -// or the pEp COM server adapter needs to be changed.
  34.105 -    if (blob->mime_type == NULL || blob->mime_type[0] == '\0')
  34.106 -        mime_type = "application/octet-stream";
  34.107 -    else
  34.108 -        mime_type = blob->mime_type;
  34.109 -
  34.110 -    pEp_rid_list_t* resource = parse_uri(blob->filename);
  34.111 -
  34.112 -    bool already_ascii = !(must_chunk_be_encoded(blob->value, blob->size, true));
  34.113 -
  34.114 -    mime = get_file_part(resource, mime_type, blob->value, blob->size, 
  34.115 -                          (already_ascii ? false : transport_encode));
  34.116 -    free_rid_list(resource);
  34.117 -    
  34.118 -    assert(mime);
  34.119 -    if (mime == NULL)
  34.120 -        goto enomem;
  34.121 -
  34.122 -    *result = mime;
  34.123 -    return PEP_STATUS_OK;
  34.124 -
  34.125 -enomem:
  34.126 -    status = PEP_OUT_OF_MEMORY;
  34.127 -
  34.128 -    if (mime)
  34.129 -        mailmime_free(mime);
  34.130 -
  34.131 -    return status;
  34.132 -}
  34.133 -
  34.134 -static PEP_STATUS mime_html_text(
  34.135 -        const char *plaintext,
  34.136 -        const char *htmltext,
  34.137 -        bloblist_t *attachments,
  34.138 -        struct mailmime **result,
  34.139 -        bool transport_encode
  34.140 -    )
  34.141 -{
  34.142 -    PEP_STATUS status = PEP_STATUS_OK;
  34.143 -    struct mailmime * top_level_html_mime = NULL;
  34.144 -    struct mailmime * mime = NULL;
  34.145 -    struct mailmime * submime = NULL;
  34.146 -    int r;
  34.147 -
  34.148 -    assert(plaintext);
  34.149 -    assert(htmltext);
  34.150 -    assert(result);
  34.151 -
  34.152 -    *result = NULL;
  34.153 -
  34.154 -    mime = part_multiple_new("multipart/alternative");
  34.155 -    assert(mime);
  34.156 -    if (mime == NULL)
  34.157 -        goto enomem;
  34.158 -
  34.159 -    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
  34.160 -    
  34.161 -    int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  34.162 -    submime = get_text_part(NULL, "text/plain", plaintext, strlen(plaintext),
  34.163 -            encoding_type);
  34.164 -    free_rid_list(resource);
  34.165 -    resource = NULL;
  34.166 -    
  34.167 -    assert(submime);
  34.168 -    if (submime == NULL)
  34.169 -        goto enomem;
  34.170 -
  34.171 -    r = mailmime_smart_add_part(mime, submime);
  34.172 -    assert(r == MAILIMF_NO_ERROR);
  34.173 -    if (r == MAILIMF_ERROR_MEMORY) {
  34.174 -        goto enomem;
  34.175 -    }
  34.176 -    else {
  34.177 -        // mailmime_smart_add_part() takes ownership of submime
  34.178 -        submime = NULL;
  34.179 -    }
  34.180 -
  34.181 -    bool inlined_attachments = false;
  34.182 -    
  34.183 -    bloblist_t* traversal_ptr = attachments;
  34.184 -    
  34.185 -    while (traversal_ptr) {
  34.186 -        if (traversal_ptr->disposition == PEP_CONTENT_DISP_INLINE) {
  34.187 -            inlined_attachments = true;
  34.188 -            break;
  34.189 -        }
  34.190 -        traversal_ptr = traversal_ptr->next;
  34.191 -    }
  34.192 -
  34.193 -    if (inlined_attachments) {
  34.194 -        /* Noooooo... dirk, why do you do this to me? */
  34.195 -        submime = part_multiple_new("multipart/related");
  34.196 -        assert(submime);
  34.197 -        if (submime == NULL)
  34.198 -            goto enomem;
  34.199 -
  34.200 -        top_level_html_mime = submime;
  34.201 -        
  34.202 -        r = mailmime_smart_add_part(mime, top_level_html_mime);
  34.203 -        assert(r == MAILIMF_NO_ERROR);
  34.204 -        if (r == MAILIMF_ERROR_MEMORY) {
  34.205 -            goto enomem;
  34.206 -        }
  34.207 -        else {
  34.208 -            // mailmime_smart_add_part() takes ownership of submime
  34.209 -            submime = NULL;
  34.210 -        }
  34.211 -    }
  34.212 -    else {
  34.213 -        top_level_html_mime = mime;
  34.214 -    }
  34.215 -
  34.216 -//    resource = new_rid_node(PEP_RID_FILENAME, "msg.html");
  34.217 -    submime = get_text_part(NULL, "text/html", htmltext, strlen(htmltext),
  34.218 -            encoding_type);
  34.219 -    free_rid_list(resource);
  34.220 -    resource = NULL;
  34.221 -    
  34.222 -    assert(submime);
  34.223 -    if (submime == NULL)
  34.224 -        goto enomem;
  34.225 -
  34.226 -    r = mailmime_smart_add_part(top_level_html_mime, submime);
  34.227 -    assert(r == MAILIMF_NO_ERROR);
  34.228 -    if (r == MAILIMF_ERROR_MEMORY)
  34.229 -        goto enomem;
  34.230 -    else {
  34.231 -        // mailmime_smart_add_part() takes ownership of submime
  34.232 -        submime = NULL;
  34.233 -    }
  34.234 -
  34.235 -    bloblist_t *_a;
  34.236 -    for (_a = attachments; _a != NULL; _a = _a->next) {
  34.237 -        if (_a->disposition != PEP_CONTENT_DISP_INLINE)
  34.238 -            continue;
  34.239 -        status = mime_attachment(_a, &submime, transport_encode);
  34.240 -        if (status != PEP_STATUS_OK)
  34.241 -            return PEP_UNKNOWN_ERROR; // FIXME
  34.242 -
  34.243 -        r = mailmime_smart_add_part(top_level_html_mime, submime);
  34.244 -        assert(r == MAILIMF_NO_ERROR);
  34.245 -        if (r == MAILIMF_ERROR_MEMORY) {
  34.246 -            goto enomem;
  34.247 -        }
  34.248 -        else {
  34.249 -            // mailmime_smart_add_part() takes ownership of submime
  34.250 -            submime = NULL;
  34.251 -        }
  34.252 -    }
  34.253 -
  34.254 -    *result = mime;
  34.255 -    return PEP_STATUS_OK;
  34.256 -
  34.257 -enomem:
  34.258 -    status = PEP_OUT_OF_MEMORY;
  34.259 -
  34.260 -    if (mime)
  34.261 -        mailmime_free(mime);
  34.262 -
  34.263 -    if (submime)
  34.264 -        mailmime_free(submime);
  34.265 -
  34.266 -    return status;
  34.267 -}
  34.268 -
  34.269 -
  34.270 -// FIXME: maybe need to add transport_encode field here
  34.271 -static struct mailimf_mailbox * identity_to_mailbox(const pEp_identity *ident)
  34.272 -{
  34.273 -    char *_username = NULL;
  34.274 -    struct mailimf_mailbox *mb;
  34.275 -
  34.276 -    if (!ident->username)
  34.277 -        _username = strdup("");
  34.278 -    else
  34.279 -        _username = must_field_value_be_encoded(ident->username) ?
  34.280 -                    mailmime_encode_subject_header("utf-8", ident->username, 0) : 
  34.281 -                    strdup(ident->username);
  34.282 -                  
  34.283 -    assert(_username);
  34.284 -    if (_username == NULL)
  34.285 -        goto enomem;
  34.286 -
  34.287 -    mb = mailbox_from_string(_username, ident->address);
  34.288 -    if (mb == NULL)
  34.289 -        goto enomem;
  34.290 -
  34.291 -    free(_username);
  34.292 -    _username = NULL;
  34.293 -
  34.294 -    return mb;
  34.295 -
  34.296 -enomem:
  34.297 -    free(_username);
  34.298 -    return NULL;
  34.299 -}
  34.300 -
  34.301 -static struct mailimf_mailbox_list * identity_to_mbl(
  34.302 -        const pEp_identity *ident)
  34.303 -{
  34.304 -    struct mailimf_mailbox_list *mbl = NULL;
  34.305 -    struct mailimf_mailbox *mb = NULL;
  34.306 -    clist *list = NULL;
  34.307 -    int r;
  34.308 -
  34.309 -    assert(ident);
  34.310 -
  34.311 -    list = clist_new();
  34.312 -    if (list == NULL)
  34.313 -        goto enomem;
  34.314 -
  34.315 -    mb = identity_to_mailbox(ident);
  34.316 -    if (mb == NULL)
  34.317 -        goto enomem;
  34.318 -
  34.319 -    r = clist_append(list, mb);
  34.320 -    if (r)
  34.321 -        goto enomem;
  34.322 -
  34.323 -    mbl = mailimf_mailbox_list_new(list);
  34.324 -    if (mbl == NULL)
  34.325 -        goto enomem;
  34.326 -
  34.327 -    return mbl;
  34.328 -
  34.329 -enomem:
  34.330 -    if (mb)
  34.331 -        mailimf_mailbox_free(mb);
  34.332 -
  34.333 -    if (list)
  34.334 -        clist_free(list);
  34.335 -
  34.336 -    return NULL;
  34.337 -}
  34.338 -
  34.339 -static struct mailimf_address_list * identity_list_to_mal(identity_list *il)
  34.340 -{
  34.341 -    struct mailimf_address_list *mal = NULL;
  34.342 -    struct mailimf_mailbox *mb = NULL;
  34.343 -    struct mailimf_address * addr = NULL;
  34.344 -    clist *list = NULL;
  34.345 -    int r;
  34.346 -
  34.347 -    assert(il);
  34.348 -
  34.349 -    list = clist_new();
  34.350 -    if (list == NULL)
  34.351 -        goto enomem;
  34.352 -
  34.353 -    identity_list *_il;
  34.354 -    for (_il = il; _il && _il->ident; _il = _il->next) {
  34.355 -        mb = identity_to_mailbox(_il->ident);
  34.356 -        if (mb == NULL)
  34.357 -            goto enomem;
  34.358 -
  34.359 -        addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
  34.360 -        if (addr == NULL)
  34.361 -            goto enomem;
  34.362 -        mb = NULL;
  34.363 -
  34.364 -        r = clist_append(list, addr);
  34.365 -        if (r)
  34.366 -            goto enomem;
  34.367 -        addr = NULL;
  34.368 -    }
  34.369 -    mal = mailimf_address_list_new(list);
  34.370 -    if (mal == NULL)
  34.371 -        goto enomem;
  34.372 -
  34.373 -    return mal;
  34.374 -
  34.375 -enomem:
  34.376 -    if (mb)
  34.377 -        mailimf_mailbox_free(mb);
  34.378 -
  34.379 -    if (addr)
  34.380 -        mailimf_address_free(addr);
  34.381 -
  34.382 -    if (list)
  34.383 -        clist_free(list);
  34.384 -
  34.385 -    return NULL;
  34.386 -}
  34.387 -
  34.388 -static clist * stringlist_to_clist(stringlist_t *sl, bool transport_encode)
  34.389 -{
  34.390 -    clist * cl = clist_new();
  34.391 -    assert(cl);
  34.392 -    if (cl == NULL)
  34.393 -        return NULL;
  34.394 -
  34.395 -    if (!sl || ((!sl->value || sl->value[0] == '\0') && sl->next == NULL))
  34.396 -        return cl;
  34.397 -        
  34.398 -    stringlist_t *_sl;
  34.399 -    for (_sl = sl; _sl; _sl = _sl->next) {
  34.400 -        int r;
  34.401 -        char * value = ((transport_encode && must_field_value_be_encoded(_sl->value)) ?
  34.402 -                        mailmime_encode_subject_header("utf-8", _sl->value, 0) :
  34.403 -                        strdup(_sl->value));
  34.404 -        assert(value);
  34.405 -        if (value == NULL) {
  34.406 -            clist_free(cl);
  34.407 -            return NULL;
  34.408 -        }
  34.409 -        r = clist_append(cl, value);
  34.410 -        assert(r == 0);
  34.411 -        if (r) {
  34.412 -            free(value);
  34.413 -            clist_free(cl);
  34.414 -            return NULL;
  34.415 -        }
  34.416 -    }
  34.417 -
  34.418 -    return cl;
  34.419 -}
  34.420 -
  34.421 -static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
  34.422 -{
  34.423 -    PEP_STATUS status = PEP_STATUS_OK;
  34.424 -    struct mailimf_fields * fields = NULL;
  34.425 -    int r;
  34.426 -    clist * fields_list = NULL;
  34.427 -    unsigned char pEpstr[] = PEP_SUBJ_STRING; // unsigned due to UTF-8 byte fun
  34.428 -#ifdef WIN32
  34.429 -    char* altstr = "pEp";
  34.430 -#else
  34.431 -    char* altstr = (char*)pEpstr;
  34.432 -#endif        
  34.433 -    char *subject = msg->shortmsg ? msg->shortmsg : altstr;
  34.434 -
  34.435 -    assert(msg);
  34.436 -    assert(result);
  34.437 -
  34.438 -    *result = NULL;
  34.439 -
  34.440 -    fields_list = clist_new();
  34.441 -    assert(fields_list);
  34.442 -    if (fields_list == NULL)
  34.443 -        goto enomem;
  34.444 -
  34.445 -    if (msg->id) {
  34.446 -        char *_msgid = strdup(msg->id);
  34.447 -        assert(_msgid);
  34.448 -        if (_msgid == NULL)
  34.449 -            goto enomem;
  34.450 -
  34.451 -        r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
  34.452 -                (_new_func_t) mailimf_message_id_new, _msgid);
  34.453 -        if (r) {
  34.454 -            free(_msgid);
  34.455 -            goto enomem;
  34.456 -        }
  34.457 -    }
  34.458 -
  34.459 -    if (msg->sent) {
  34.460 -        struct mailimf_date_time * dt = timestamp_to_etpantime(msg->sent);
  34.461 -        if (dt == NULL)
  34.462 -            goto enomem;
  34.463 -
  34.464 -        r = _append_field(fields_list, MAILIMF_FIELD_ORIG_DATE,
  34.465 -                (_new_func_t) mailimf_orig_date_new, dt);
  34.466 -        if (r) {
  34.467 -            mailimf_date_time_free(dt);
  34.468 -            goto enomem;
  34.469 -        }
  34.470 -        dt = NULL;
  34.471 -    }
  34.472 -
  34.473 -     if (msg->from) {
  34.474 -        struct mailimf_mailbox_list *from = identity_to_mbl(msg->from);
  34.475 -        if (from == NULL)
  34.476 -            goto enomem;
  34.477 -
  34.478 -        r = _append_field(fields_list, MAILIMF_FIELD_FROM,
  34.479 -                (_new_func_t) mailimf_from_new, from);
  34.480 -        if (r) {
  34.481 -            mailimf_mailbox_list_free(from);
  34.482 -            goto enomem;
  34.483 -        }
  34.484 -    }
  34.485 -
  34.486 -    if (msg->to) {
  34.487 -        struct mailimf_address_list *to = identity_list_to_mal(msg->to);
  34.488 -        if (to == NULL)
  34.489 -            goto enomem;
  34.490 -
  34.491 -        r = _append_field(fields_list, MAILIMF_FIELD_TO,
  34.492 -                (_new_func_t) mailimf_to_new, to);
  34.493 -        if (r) {
  34.494 -            mailimf_address_list_free(to);
  34.495 -            goto enomem;
  34.496 -        }
  34.497 -    }
  34.498 -
  34.499 -    char* _subject = NULL;
  34.500 -    if (!must_field_value_be_encoded(subject)) {
  34.501 -        _subject = strdup(subject);
  34.502 -        assert(_subject);
  34.503 -    }
  34.504 -    else {
  34.505 -        _subject = mailmime_encode_subject_header("utf-8", subject, 1);
  34.506 -    }
  34.507 -    if (_subject == NULL)
  34.508 -        goto enomem;
  34.509 -
  34.510 -    r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
  34.511 -            (_new_func_t) mailimf_subject_new, _subject);
  34.512 -    if (r) {
  34.513 -        free(_subject);
  34.514 -        goto enomem;
  34.515 -    }
  34.516 -
  34.517 -    if (msg->cc) {
  34.518 -        struct mailimf_address_list *cc = identity_list_to_mal(msg->cc);
  34.519 -        if (cc == NULL)
  34.520 -            goto enomem;
  34.521 -
  34.522 -        r = _append_field(fields_list, MAILIMF_FIELD_CC,
  34.523 -                (_new_func_t) mailimf_cc_new, cc);
  34.524 -        if (r) {
  34.525 -            mailimf_address_list_free(cc);
  34.526 -            goto enomem;
  34.527 -        }
  34.528 -    }
  34.529 -    
  34.530 -    if (msg->bcc) {
  34.531 -        struct mailimf_address_list *bcc = identity_list_to_mal(msg->bcc);
  34.532 -        if (bcc == NULL)
  34.533 -            goto enomem;
  34.534 -
  34.535 -        r = _append_field(fields_list, MAILIMF_FIELD_BCC,
  34.536 -                (_new_func_t) mailimf_bcc_new, bcc);
  34.537 -        if (r) {
  34.538 -            mailimf_address_list_free(bcc);
  34.539 -            goto enomem;
  34.540 -        }
  34.541 -    }
  34.542 -    
  34.543 -    if (msg->reply_to) {
  34.544 -        struct mailimf_address_list *reply_to = identity_list_to_mal(msg->reply_to);
  34.545 -        if (reply_to == NULL)
  34.546 -            goto enomem;
  34.547 -
  34.548 -        r = _append_field(fields_list, MAILIMF_FIELD_REPLY_TO,
  34.549 -                (_new_func_t) mailimf_reply_to_new, reply_to);
  34.550 -        if (r) {
  34.551 -            mailimf_address_list_free(reply_to);
  34.552 -            goto enomem;
  34.553 -        }
  34.554 -    }
  34.555 -
  34.556 -    if (msg->in_reply_to) {
  34.557 -        clist *in_reply_to = stringlist_to_clist(msg->in_reply_to, true);
  34.558 -        if (in_reply_to == NULL)
  34.559 -            goto enomem;
  34.560 -
  34.561 -        r = _append_field(fields_list, MAILIMF_FIELD_IN_REPLY_TO,
  34.562 -                (_new_func_t) mailimf_in_reply_to_new, in_reply_to);
  34.563 -        if (r) {
  34.564 -            clist_free(in_reply_to);
  34.565 -            goto enomem;
  34.566 -        }
  34.567 -    }
  34.568 -
  34.569 -    if (msg->references) {
  34.570 -        clist *references = stringlist_to_clist(msg->references, true);
  34.571 -        if (references == NULL)
  34.572 -            goto enomem;
  34.573 -
  34.574 -        r = _append_field(fields_list, MAILIMF_FIELD_REFERENCES,
  34.575 -                (_new_func_t) mailimf_references_new, references);
  34.576 -        if (r) {
  34.577 -            clist_free(references);
  34.578 -            goto enomem;
  34.579 -        }
  34.580 -    }
  34.581 -
  34.582 -    if (msg->keywords) {
  34.583 -        clist *keywords = stringlist_to_clist(msg->keywords, true);
  34.584 -        if (keywords == NULL)
  34.585 -            goto enomem;
  34.586 -
  34.587 -        r = _append_field(fields_list, MAILIMF_FIELD_KEYWORDS,
  34.588 -                (_new_func_t) mailimf_keywords_new, keywords);
  34.589 -        if (r) {
  34.590 -            clist_free(keywords);
  34.591 -            goto enomem;
  34.592 -        }
  34.593 -    }
  34.594 -
  34.595 -    if (msg->comments) {
  34.596 -        char *comments = NULL;
  34.597 -        if (!must_field_value_be_encoded(msg->comments)) {
  34.598 -            comments = strdup(msg->comments);
  34.599 -            assert(comments);
  34.600 -        }
  34.601 -        else  {
  34.602 -            comments = mailmime_encode_subject_header("utf-8", msg->comments, 0);
  34.603 -        }
  34.604 -        if (comments == NULL)
  34.605 -            goto enomem;
  34.606 -
  34.607 -        r = _append_field(fields_list, MAILIMF_FIELD_COMMENTS,
  34.608 -                (_new_func_t) mailimf_comments_new, comments);
  34.609 -        if (r) {
  34.610 -            free(comments);
  34.611 -            goto enomem;
  34.612 -        }
  34.613 -    }
  34.614 -
  34.615 -    if (msg->opt_fields) {
  34.616 -        stringpair_list_t *_l;
  34.617 -        for (_l = msg->opt_fields; _l && _l->value; _l = _l->next) {
  34.618 -            char *key = _l->value->key;
  34.619 -            char *value = _l->value->value;
  34.620 -            if (key && value) {
  34.621 -                r = _append_optional_field(fields_list, key, value);
  34.622 -
  34.623 -                if (r)
  34.624 -                    goto enomem;
  34.625 -            }
  34.626 -        }
  34.627 -    }
  34.628 -
  34.629 -    fields = mailimf_fields_new(fields_list);
  34.630 -    assert(fields);
  34.631 -    if (fields == NULL)
  34.632 -        goto enomem;
  34.633 -
  34.634 -    *result = fields;
  34.635 -
  34.636 -    return PEP_STATUS_OK;
  34.637 -
  34.638 -enomem:
  34.639 -    status = PEP_OUT_OF_MEMORY;
  34.640 -
  34.641 -    if (fields_list)
  34.642 -        clist_free(fields_list);
  34.643 -
  34.644 -    if (fields)
  34.645 -        mailimf_fields_free(fields);
  34.646 -
  34.647 -    return status;
  34.648 -}
  34.649 -
  34.650 -static bool has_exceptional_extension(char* filename) {
  34.651 -    if (!filename)
  34.652 -        return false;
  34.653 -    int len = strlen(filename);
  34.654 -    if (len < 4)
  34.655 -        return false;
  34.656 -    char* ext_start = filename + (len - 4);
  34.657 -    if (strcmp(ext_start, ".pgp") == 0 || strcmp(ext_start, ".gpg") == 0 ||
  34.658 -        strcmp(ext_start, ".asc") == 0 || strcmp(ext_start, ".pEp") == 0)
  34.659 -        return true;
  34.660 -    return false;
  34.661 -}
  34.662 -
  34.663 -static pEp_rid_list_t* choose_resource_id(pEp_rid_list_t* rid_list) {
  34.664 -    pEp_rid_list_t* retval = rid_list;
  34.665 -    
  34.666 -    /* multiple elements - least common case */
  34.667 -    if (rid_list && rid_list->next) {
  34.668 -        pEp_rid_list_t* rid_list_curr = rid_list;
  34.669 -        retval = rid_list; 
  34.670 -        
  34.671 -        while (rid_list_curr) {
  34.672 -            pEp_resource_id_type rid_type = rid_list_curr->rid_type;
  34.673 -            if (rid_type == PEP_RID_CID)
  34.674 -                retval = rid_list_curr;
  34.675 -            else if (rid_type == PEP_RID_FILENAME && has_exceptional_extension(rid_list_curr->rid))
  34.676 -                return rid_list_curr;
  34.677 -            rid_list_curr = rid_list_curr->next;
  34.678 -        }
  34.679 -    } 
  34.680 -    return retval;
  34.681 -}
  34.682 -
  34.683 -// static void split_inlined_and_attached(bloblist_t** inlined, bloblist_t** attached) {
  34.684 -//     bloblist_t** curr_pp = attached;
  34.685 -//     bloblist_t* curr = *curr_pp;
  34.686 -//     
  34.687 -//     bloblist_t* inline_ret = NULL;
  34.688 -//     bloblist_t** inline_curr_pp = &inline_ret;
  34.689 -//     
  34.690 -//     bloblist_t* att_ret = NULL;
  34.691 -//     bloblist_t** att_curr_pp = &att_ret;
  34.692 -//     
  34.693 -//     while (curr) {
  34.694 -//         if (curr->disposition == PEP_CONTENT_DISP_INLINE) {
  34.695 -//             *inline_curr_pp = curr;
  34.696 -//             inline_curr_pp = &(curr->next);
  34.697 -//         }
  34.698 -//         else {
  34.699 -//             *att_curr_pp = curr;
  34.700 -//             att_curr_pp = &(curr->next);            
  34.701 -//         }
  34.702 -//         *curr_pp = curr->next;
  34.703 -//         curr->next = NULL;
  34.704 -//         curr = *curr_pp;
  34.705 -//     }
  34.706 -//     
  34.707 -//     *inlined = inline_ret;
  34.708 -//     *attached = att_ret;
  34.709 -// }
  34.710 -
  34.711 -
  34.712 -static PEP_STATUS mime_encode_message_plain(
  34.713 -        const message *msg,
  34.714 -        bool omit_fields,
  34.715 -        struct mailmime **result,
  34.716 -        bool transport_encode
  34.717 -    )
  34.718 -{
  34.719 -    struct mailmime * mime = NULL;
  34.720 -    struct mailmime * submime = NULL;
  34.721 -    int r;
  34.722 -    PEP_STATUS status;
  34.723 -    //char *subject;
  34.724 -    char *plaintext;
  34.725 -    char *htmltext;
  34.726 -
  34.727 -    assert(msg);
  34.728 -    assert(result);
  34.729 -    
  34.730 -    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp";  // not used, yet.
  34.731 -    plaintext = (msg->longmsg) ? msg->longmsg : "";
  34.732 -    htmltext = msg->longmsg_formatted;
  34.733 -
  34.734 -    if (htmltext && (htmltext[0] != '\0')) {
  34.735 -        /* first, we need to strip out the inlined attachments to ensure this
  34.736 -           gets set up correctly */
  34.737 -           
  34.738 -        status = mime_html_text(plaintext, htmltext, msg->attachments, &mime,
  34.739 -                                transport_encode);
  34.740 -                
  34.741 -        if (status != PEP_STATUS_OK)
  34.742 -            goto pEp_error;
  34.743 -    }
  34.744 -    else {
  34.745 -        pEp_rid_list_t* resource = NULL;
  34.746 -        if (is_PGP_message_text(plaintext)) {
  34.747 -            resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
  34.748 -            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_7BIT : 0);
  34.749 -            mime = get_text_part(resource, "application/octet-stream", plaintext,
  34.750 -                    strlen(plaintext), encoding_type);
  34.751 -        }
  34.752 -        else {
  34.753 -            resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
  34.754 -            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  34.755 -            mime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
  34.756 -                    encoding_type);
  34.757 -        }
  34.758 -        free_rid_list(resource);
  34.759 -        
  34.760 -        assert(mime);
  34.761 -        if (mime == NULL)
  34.762 -            goto enomem;
  34.763 -    }
  34.764 -
  34.765 -    bool normal_attachments = false;
  34.766 -    
  34.767 -    bloblist_t* traversal_ptr = msg->attachments;
  34.768 -    
  34.769 -    while (traversal_ptr) {
  34.770 -        if (traversal_ptr->disposition != PEP_CONTENT_DISP_INLINE) {
  34.771 -            normal_attachments = true;
  34.772 -            break;
  34.773 -        }
  34.774 -        traversal_ptr = traversal_ptr->next;
  34.775 -    }
  34.776 -
  34.777 -    if (normal_attachments) {
  34.778 -        submime = mime;
  34.779 -        mime = part_multiple_new("multipart/mixed");
  34.780 -        assert(mime);
  34.781 -        if (mime == NULL)
  34.782 -            goto enomem;
  34.783 -
  34.784 -        r = mailmime_smart_add_part(mime, submime);
  34.785 -        assert(r == MAILIMF_NO_ERROR);
  34.786 -        if (r == MAILIMF_ERROR_MEMORY) {
  34.787 -            goto enomem;
  34.788 -        }
  34.789 -        else {
  34.790 -            // mailmime_smart_add_part() takes ownership of submime
  34.791 -            submime = NULL;
  34.792 -        }
  34.793 -
  34.794 -        bloblist_t *_a;
  34.795 -        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
  34.796 -
  34.797 -            if (_a->disposition == PEP_CONTENT_DISP_INLINE)
  34.798 -                continue;
  34.799 -
  34.800 -            status = mime_attachment(_a, &submime, transport_encode);
  34.801 -            if (status != PEP_STATUS_OK)
  34.802 -                goto pEp_error;
  34.803 -
  34.804 -            r = mailmime_smart_add_part(mime, submime);
  34.805 -            assert(r == MAILIMF_NO_ERROR);
  34.806 -            if (r == MAILIMF_ERROR_MEMORY) {
  34.807 -                goto enomem;
  34.808 -            }
  34.809 -            else {
  34.810 -                // mailmime_smart_add_part() takes ownership of submime
  34.811 -                submime = NULL;
  34.812 -            }
  34.813 -        }
  34.814 -    }
  34.815 -
  34.816 -    *result = mime;
  34.817 -    return PEP_STATUS_OK;
  34.818 -
  34.819 -enomem:
  34.820 -    status = PEP_OUT_OF_MEMORY;
  34.821 -
  34.822 -pEp_error:
  34.823 -    if (mime)
  34.824 -        mailmime_free(mime);
  34.825 -
  34.826 -    if (submime)
  34.827 -        mailmime_free(submime);
  34.828 -
  34.829 -    return status;
  34.830 -}
  34.831 -
  34.832 -static PEP_STATUS mime_encode_message_PGP_MIME(
  34.833 -        const message * msg,
  34.834 -        bool omit_fields,
  34.835 -        struct mailmime **result
  34.836 -    )
  34.837 -{
  34.838 -    struct mailmime * mime = NULL;
  34.839 -    struct mailmime * submime = NULL;
  34.840 -	struct mailmime_parameter * param;
  34.841 -    int r;
  34.842 -    PEP_STATUS status;
  34.843 -    char *plaintext;
  34.844 -    size_t plaintext_size;
  34.845 -
  34.846 -    assert(msg->attachments && msg->attachments->next &&
  34.847 -            msg->attachments->next->value);
  34.848 -
  34.849 -    plaintext = msg->attachments->next->value;
  34.850 -    plaintext_size = msg->attachments->next->size;
  34.851 -
  34.852 -    mime = part_multiple_new("multipart/encrypted");
  34.853 -    assert(mime);
  34.854 -    if (mime == NULL)
  34.855 -        goto enomem;
  34.856 -
  34.857 -    param = mailmime_param_new_with_data("protocol", "application/pgp-encrypted");
  34.858 -    clist_append(mime->mm_content_type->ct_parameters, param);
  34.859 -
  34.860 -    submime = get_pgp_encrypted_part();
  34.861 -    assert(submime);
  34.862 -    if (submime == NULL)
  34.863 -        goto enomem;
  34.864 -
  34.865 -    r = mailmime_smart_add_part(mime, submime);
  34.866 -    assert(r == MAILIMF_NO_ERROR);
  34.867 -    if (r == MAILIMF_ERROR_MEMORY) {
  34.868 -        goto enomem;
  34.869 -    }
  34.870 -    else {
  34.871 -        // mailmime_smart_add_part() takes ownership of submime
  34.872 -        submime = NULL;
  34.873 -    }
  34.874 -
  34.875 -    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
  34.876 -    submime = get_text_part(resource, "application/octet-stream", plaintext,
  34.877 -            plaintext_size, MAILMIME_MECHANISM_7BIT);
  34.878 -            
  34.879 -    free_rid_list(resource);
  34.880 -    
  34.881 -    assert(submime);
  34.882 -    if (submime == NULL)
  34.883 -        goto enomem;
  34.884 -
  34.885 -    r = mailmime_smart_add_part(mime, submime);
  34.886 -    assert(r == MAILIMF_NO_ERROR);
  34.887 -    if (r == MAILIMF_ERROR_MEMORY) {
  34.888 -        goto enomem;
  34.889 -    }
  34.890 -    else {
  34.891 -        // mailmime_smart_add_part() takes ownership of submime
  34.892 -        submime = NULL;
  34.893 -    }
  34.894 -
  34.895 -    *result = mime;
  34.896 -    return PEP_STATUS_OK;
  34.897 -
  34.898 -enomem:
  34.899 -    status = PEP_OUT_OF_MEMORY;
  34.900 -
  34.901 -    if (mime)
  34.902 -        mailmime_free(mime);
  34.903 -
  34.904 -    if (submime)
  34.905 -        mailmime_free(submime);
  34.906 -
  34.907 -    return status;
  34.908 -}
  34.909 -
  34.910  DYNAMIC_API PEP_STATUS mime_encode_message(
  34.911          const message * msg,
  34.912          bool omit_fields,
  34.913 @@ -929,807 +42,3 @@
  34.914      return _mime_encode_message_internal(msg, omit_fields, mimetext, true);
  34.915  }
  34.916  
  34.917 -PEP_STATUS _mime_encode_message_internal(
  34.918 -        const message * msg,
  34.919 -        bool omit_fields,
  34.920 -        char **mimetext,
  34.921 -        bool transport_encode
  34.922 -    )
  34.923 -{
  34.924 -    PEP_STATUS status = PEP_STATUS_OK;
  34.925 -    struct mailmime * msg_mime = NULL;
  34.926 -    struct mailmime * mime = NULL;
  34.927 -    struct mailimf_fields * fields = NULL;
  34.928 -    char *buf = NULL;
  34.929 -    int r;
  34.930 -
  34.931 -    assert(msg);
  34.932 -    assert(mimetext);
  34.933 -
  34.934 -    if (!(msg && mimetext))
  34.935 -        return PEP_ILLEGAL_VALUE;
  34.936 -
  34.937 -    *mimetext = NULL;
  34.938 -
  34.939 -    switch (msg->enc_format) {
  34.940 -        case PEP_enc_none:
  34.941 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
  34.942 -            break;
  34.943 -
  34.944 -        case PEP_enc_pieces:
  34.945 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
  34.946 -            break;
  34.947 -
  34.948 -        case PEP_enc_S_MIME:
  34.949 -            NOT_IMPLEMENTED
  34.950 -                
  34.951 -        case PEP_enc_PGP_MIME:
  34.952 -            status = mime_encode_message_PGP_MIME(msg, omit_fields, &mime);
  34.953 -            break;
  34.954 -
  34.955 -        case PEP_enc_PEP:
  34.956 -            NOT_IMPLEMENTED
  34.957 -
  34.958 -        default:
  34.959 -            NOT_IMPLEMENTED
  34.960 -    }
  34.961 -
  34.962 -    if (status != PEP_STATUS_OK)
  34.963 -        goto pEp_error;
  34.964 -
  34.965 -    msg_mime = mailmime_new_message_data(NULL);
  34.966 -    assert(msg_mime);
  34.967 -    if (msg_mime == NULL)
  34.968 -        goto enomem;
  34.969 -
  34.970 -    r = mailmime_add_part(msg_mime, mime);
  34.971 -    if (r) {
  34.972 -        mailmime_free(mime);
  34.973 -        goto enomem;
  34.974 -    }
  34.975 -    mime = NULL;
  34.976 -
  34.977 -    if (!omit_fields) {
  34.978 -        status = build_fields(msg, &fields);
  34.979 -        if (status != PEP_STATUS_OK)
  34.980 -            goto pEp_error;
  34.981 -
  34.982 -        mailmime_set_imf_fields(msg_mime, fields);
  34.983 -    }
  34.984 -
  34.985 -    status = render_mime(msg_mime, &buf);
  34.986 -    if (status != PEP_STATUS_OK)
  34.987 -        goto pEp_error;
  34.988 -
  34.989 -    mailmime_free(msg_mime);
  34.990 -    *mimetext = buf;
  34.991 -
  34.992 -    return PEP_STATUS_OK;
  34.993 -
  34.994 -enomem:
  34.995 -    status = PEP_OUT_OF_MEMORY;
  34.996 -
  34.997 -pEp_error:
  34.998 -    if (msg_mime)
  34.999 -        mailmime_free(msg_mime);
 34.1000 -    else
 34.1001 -        if (mime)
 34.1002 -            mailmime_free(mime);
 34.1003 -
 34.1004 -    return status;
 34.1005 -}
 34.1006 -
 34.1007 -static pEp_identity *mailbox_to_identity(const struct mailimf_mailbox * mb)
 34.1008 -{
 34.1009 -    char *username = NULL;
 34.1010 -
 34.1011 -    assert(mb);
 34.1012 -    assert(mb->mb_addr_spec);
 34.1013 -
 34.1014 -    if (mb->mb_addr_spec == NULL)
 34.1015 -        return NULL;
 34.1016 -
 34.1017 -    if (mb->mb_display_name) {
 34.1018 -        size_t index = 0;
 34.1019 -        const int r = mailmime_encoded_phrase_parse("utf-8", mb->mb_display_name,
 34.1020 -                strlen(mb->mb_display_name), &index, "utf-8", &username);
 34.1021 -        if (r)
 34.1022 -            goto enomem;
 34.1023 -    }
 34.1024 -
 34.1025 -    pEp_identity *ident = new_identity(mb->mb_addr_spec, NULL, NULL, username);
 34.1026 -    if (ident == NULL)
 34.1027 -        goto enomem;
 34.1028 -    free(username);
 34.1029 -
 34.1030 -    return ident;
 34.1031 -
 34.1032 -enomem:
 34.1033 -    free(username);
 34.1034 -    return NULL;
 34.1035 -}
 34.1036 -
 34.1037 -static pEp_identity * mbl_to_identity(const struct mailimf_mailbox_list * mbl)
 34.1038 -{
 34.1039 -    struct mailimf_mailbox * mb = clist_content(clist_begin(mbl->mb_list));
 34.1040 -    return mailbox_to_identity(mb);
 34.1041 -}
 34.1042 -
 34.1043 -static identity_list * mal_to_identity_list(
 34.1044 -        const struct mailimf_address_list *mal
 34.1045 -    )
 34.1046 -{
 34.1047 -    assert(mal);
 34.1048 -    clist *list = mal->ad_list;
 34.1049 -
 34.1050 -    identity_list *il = new_identity_list(NULL);
 34.1051 -    if (il == NULL)
 34.1052 -        goto enomem;
 34.1053 -
 34.1054 -    identity_list *_il = il;
 34.1055 -    for (clistiter *cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
 34.1056 -        pEp_identity *ident;
 34.1057 -
 34.1058 -        struct mailimf_address *addr = clist_content(cur);
 34.1059 -        switch(addr->ad_type) {
 34.1060 -            case MAILIMF_ADDRESS_MAILBOX:
 34.1061 -                ident = mailbox_to_identity(addr->ad_data.ad_mailbox);
 34.1062 -                if (ident == NULL)
 34.1063 -                    goto enomem;
 34.1064 -                _il = identity_list_add(_il, ident);
 34.1065 -                if (_il == NULL)
 34.1066 -                    goto enomem;
 34.1067 -                break;
 34.1068 -
 34.1069 -            case MAILIMF_ADDRESS_GROUP:
 34.1070 -                {
 34.1071 -                    struct mailimf_mailbox_list * mbl =
 34.1072 -                            addr->ad_data.ad_group->grp_mb_list;
 34.1073 -                    for (clistiter *cur2 = clist_begin(mbl->mb_list); cur2 != NULL;
 34.1074 -                            cur2 = clist_next(cur2)) {
 34.1075 -                        ident = mailbox_to_identity(clist_content(cur));
 34.1076 -                        if (ident == NULL)
 34.1077 -                            goto enomem;
 34.1078 -                        _il = identity_list_add(_il, ident);
 34.1079 -                        if (_il == NULL)
 34.1080 -                            goto enomem;
 34.1081 -                    }
 34.1082 -                }
 34.1083 -                break;
 34.1084 -
 34.1085 -            default:
 34.1086 -                assert(0);
 34.1087 -                goto enomem;
 34.1088 -        }
 34.1089 -    }
 34.1090 -
 34.1091 -    return il;
 34.1092 -
 34.1093 -enomem:
 34.1094 -    free_identity_list(il);
 34.1095 -    return NULL;
 34.1096 -}
 34.1097 -
 34.1098 -static stringlist_t * clist_to_stringlist(const clist *list)
 34.1099 -{
 34.1100 -    char *text = NULL;;
 34.1101 -    stringlist_t * sl = new_stringlist(NULL);
 34.1102 -    if (sl == NULL)
 34.1103 -        return NULL;
 34.1104 -
 34.1105 -    stringlist_t *_sl = sl;
 34.1106 -    for (clistiter *cur = clist_begin(list); cur != NULL; cur = clist_next(cur)) {
 34.1107 -        char *phrase = clist_content(cur);
 34.1108 -        size_t index = 0;
 34.1109 -        
 34.1110 -        const int r = mailmime_encoded_phrase_parse("utf-8", phrase, strlen(phrase),
 34.1111 -                &index, "utf-8", &text);
 34.1112 -        if (r)
 34.1113 -            goto enomem;
 34.1114 -
 34.1115 -        _sl = stringlist_add(_sl, text);
 34.1116 -        if (_sl == NULL)
 34.1117 -            goto enomem;
 34.1118 -
 34.1119 -        free(text);
 34.1120 -        text = NULL;
 34.1121 -    }
 34.1122 -
 34.1123 -    return sl;
 34.1124 -
 34.1125 -enomem:
 34.1126 -    free_stringlist(sl);
 34.1127 -    free(text);
 34.1128 -
 34.1129 -    return NULL;
 34.1130 -}
 34.1131 -
 34.1132 -static PEP_STATUS read_fields(message *msg, clist *fieldlist)
 34.1133 -{
 34.1134 -    PEP_STATUS status = PEP_STATUS_OK;
 34.1135 -    struct mailimf_field * _field;
 34.1136 -    clistiter *cur;
 34.1137 -    size_t index;
 34.1138 -    int r;
 34.1139 -    
 34.1140 -    stringpair_list_t *opt = msg->opt_fields;
 34.1141 -
 34.1142 -    if (!fieldlist)
 34.1143 -        return PEP_STATUS_OK;
 34.1144 -        
 34.1145 -    for (cur = clist_begin(fieldlist); cur != NULL; cur = clist_next(cur)) {
 34.1146 -        _field = clist_content(cur);
 34.1147 -
 34.1148 -        switch (_field->fld_type) {
 34.1149 -            case MAILIMF_FIELD_MESSAGE_ID:
 34.1150 -                {
 34.1151 -                    char * text = _field->fld_data.fld_message_id->mid_value;
 34.1152 -
 34.1153 -                    free(msg->id);
 34.1154 -                    index = 0;
 34.1155 -                    r = mailmime_encoded_phrase_parse("utf-8", text,
 34.1156 -                            strlen(text), &index, "utf-8", &msg->id);
 34.1157 -                    if (r)
 34.1158 -                        goto enomem;
 34.1159 -                }
 34.1160 -                break;
 34.1161 -
 34.1162 -            case MAILIMF_FIELD_SUBJECT:
 34.1163 -                {
 34.1164 -                    char * text = _field->fld_data.fld_subject->sbj_value;
 34.1165 -
 34.1166 -                    free(msg->shortmsg);
 34.1167 -                    index = 0;
 34.1168 -                    r = mailmime_encoded_phrase_parse("utf-8", text,
 34.1169 -                            strlen(text), &index, "utf-8", &msg->shortmsg);
 34.1170 -                    if (r)
 34.1171 -                        goto enomem;
 34.1172 -                }
 34.1173 -                break;
 34.1174 -
 34.1175 -            case MAILIMF_FIELD_ORIG_DATE:
 34.1176 -                {
 34.1177 -                    struct mailimf_date_time *date =
 34.1178 -                        _field->fld_data.fld_orig_date->dt_date_time;
 34.1179 -
 34.1180 -                    free_timestamp(msg->sent);
 34.1181 -                    msg->sent = etpantime_to_timestamp(date);
 34.1182 -                    if (msg->sent == NULL)
 34.1183 -                        goto enomem;
 34.1184 -                }
 34.1185 -                break;
 34.1186 -
 34.1187 -            case MAILIMF_FIELD_FROM:
 34.1188 -                {
 34.1189 -                    struct mailimf_mailbox_list *mbl =
 34.1190 -                            _field->fld_data.fld_from->frm_mb_list;
 34.1191 -                    pEp_identity *ident;
 34.1192 -
 34.1193 -                    ident = mbl_to_identity(mbl);
 34.1194 -                    if (ident == NULL)
 34.1195 -                        goto pEp_error;
 34.1196 -
 34.1197 -                    free_identity(msg->from);
 34.1198 -                    msg->from = ident;
 34.1199 -                }
 34.1200 -                break;
 34.1201 -
 34.1202 -            case MAILIMF_FIELD_TO:
 34.1203 -                {
 34.1204 -                    struct mailimf_address_list *mal =
 34.1205 -                            _field->fld_data.fld_to->to_addr_list;
 34.1206 -                    identity_list *il = mal_to_identity_list(mal);
 34.1207 -                    if (il == NULL)
 34.1208 -                        goto enomem;
 34.1209 -
 34.1210 -                    free_identity_list(msg->to);
 34.1211 -                    msg->to = il;
 34.1212 -                }
 34.1213 -                break;
 34.1214 -
 34.1215 -            case MAILIMF_FIELD_CC:
 34.1216 -                {
 34.1217 -                    struct mailimf_address_list *mal =
 34.1218 -                            _field->fld_data.fld_cc->cc_addr_list;
 34.1219 -                    identity_list *il = mal_to_identity_list(mal);
 34.1220 -                    if (il == NULL)
 34.1221 -                        goto enomem;
 34.1222 -
 34.1223 -                    free_identity_list(msg->cc);
 34.1224 -                    msg->cc = il;
 34.1225 -                }
 34.1226 -                break;
 34.1227 -
 34.1228 -            case MAILIMF_FIELD_BCC:
 34.1229 -                {
 34.1230 -                    struct mailimf_address_list *mal =
 34.1231 -                            _field->fld_data.fld_bcc->bcc_addr_list;
 34.1232 -                    identity_list *il = mal_to_identity_list(mal);
 34.1233 -                    if (il == NULL)
 34.1234 -                        goto enomem;
 34.1235 -
 34.1236 -                    free_identity_list(msg->bcc);
 34.1237 -                    msg->bcc = il;
 34.1238 -                }
 34.1239 -                break;
 34.1240 -
 34.1241 -            case MAILIMF_FIELD_REPLY_TO:
 34.1242 -                {
 34.1243 -                    struct mailimf_address_list *mal =
 34.1244 -                            _field->fld_data.fld_reply_to->rt_addr_list;
 34.1245 -                    identity_list *il = mal_to_identity_list(mal);
 34.1246 -                    if (il == NULL)
 34.1247 -                        goto enomem;
 34.1248 -
 34.1249 -                    free_identity_list(msg->reply_to);
 34.1250 -                    msg->reply_to = il;
 34.1251 -                }
 34.1252 -                break;
 34.1253 -
 34.1254 -            case MAILIMF_FIELD_IN_REPLY_TO:
 34.1255 -                {
 34.1256 -                    clist *list = _field->fld_data.fld_in_reply_to->mid_list;
 34.1257 -                    stringlist_t *sl = clist_to_stringlist(list);
 34.1258 -                    if (sl == NULL)
 34.1259 -                        goto enomem;
 34.1260 -
 34.1261 -                    free_stringlist(msg->in_reply_to);
 34.1262 -                    msg->in_reply_to = sl;
 34.1263 -                }
 34.1264 -                break;
 34.1265 -
 34.1266 -            case MAILIMF_FIELD_REFERENCES:
 34.1267 -                {
 34.1268 -                    clist *list = _field->fld_data.fld_references->mid_list;
 34.1269 -                    stringlist_t *sl = clist_to_stringlist(list);
 34.1270 -                    if (sl == NULL)
 34.1271 -                        goto enomem;
 34.1272 -
 34.1273 -                    free_stringlist(msg->references);
 34.1274 -                    msg->references = sl;
 34.1275 -                }
 34.1276 -                break;
 34.1277 -
 34.1278 -            case MAILIMF_FIELD_KEYWORDS:
 34.1279 -                {
 34.1280 -                    clist *list = _field->fld_data.fld_keywords->kw_list;
 34.1281 -                    stringlist_t *sl = clist_to_stringlist(list);
 34.1282 -                    if (sl == NULL)
 34.1283 -                        goto enomem;
 34.1284 -
 34.1285 -                    free_stringlist(msg->keywords);
 34.1286 -                    msg->keywords = sl;
 34.1287 -                }
 34.1288 -                break;
 34.1289 -
 34.1290 -            case MAILIMF_FIELD_COMMENTS:
 34.1291 -                {
 34.1292 -                    char * text = _field->fld_data.fld_comments->cm_value;
 34.1293 -
 34.1294 -                    free(msg->comments);
 34.1295 -                    index = 0;
 34.1296 -                    r = mailmime_encoded_phrase_parse("utf-8", text,
 34.1297 -                            strlen(text), &index, "utf-8", &msg->comments);
 34.1298 -                    if (r)
 34.1299 -                        goto enomem;
 34.1300 -                }
 34.1301 -                break;
 34.1302 -
 34.1303 -            case MAILIMF_FIELD_OPTIONAL_FIELD:
 34.1304 -                {
 34.1305 -                    char * name =
 34.1306 -                            _field->fld_data.fld_optional_field->fld_name;
 34.1307 -                    char * value =
 34.1308 -                            _field->fld_data.fld_optional_field->fld_value;
 34.1309 -                    char *_value;
 34.1310 -
 34.1311 -                    index = 0;
 34.1312 -                    r = mailmime_encoded_phrase_parse("utf-8", value,
 34.1313 -                            strlen(value), &index, "utf-8", &_value);
 34.1314 -                    if (r)
 34.1315 -                        goto enomem;
 34.1316 -
 34.1317 -                    stringpair_t *pair = new_stringpair(name, _value);
 34.1318 -                    if (pair == NULL)
 34.1319 -                        goto enomem;
 34.1320 -
 34.1321 -                    opt = stringpair_list_add(opt, pair);
 34.1322 -                    free(_value);
 34.1323 -                    if (opt == NULL)
 34.1324 -                        goto enomem;
 34.1325 -
 34.1326 -                    if (msg->opt_fields == NULL)
 34.1327 -                        msg->opt_fields = opt;
 34.1328 -                }
 34.1329 -                break;
 34.1330 -        }
 34.1331 -    }
 34.1332 -    
 34.1333 -    return PEP_STATUS_OK;
 34.1334 -
 34.1335 -enomem:
 34.1336 -    status = PEP_OUT_OF_MEMORY;
 34.1337 -
 34.1338 -pEp_error:
 34.1339 -    return status;
 34.1340 -}
 34.1341 -
 34.1342 -static PEP_STATUS interpret_body(struct mailmime *part, char **longmsg, size_t *size)
 34.1343 -{
 34.1344 -    const char *text;
 34.1345 -    char *_longmsg;
 34.1346 -    size_t length;
 34.1347 -    size_t _size;
 34.1348 -    size_t index;
 34.1349 -    char *type = NULL;
 34.1350 -    char *charset = NULL;
 34.1351 -
 34.1352 -    assert(part);
 34.1353 -    assert(longmsg);
 34.1354 -
 34.1355 -    *longmsg = NULL;
 34.1356 -    if (size)
 34.1357 -        *size = 0;
 34.1358 -
 34.1359 -    if (part->mm_body == NULL)
 34.1360 -        return PEP_ILLEGAL_VALUE;
 34.1361 -
 34.1362 -    text = part->mm_body-> dt_data.dt_text.dt_data;
 34.1363 -    if (text == NULL)
 34.1364 -        return PEP_ILLEGAL_VALUE;
 34.1365 -
 34.1366 -    length = part->mm_body->dt_data.dt_text.dt_length;
 34.1367 -
 34.1368 -    if (part->mm_body->dt_encoded) {
 34.1369 -        int code = part->mm_body->dt_encoding;
 34.1370 -        index = 0;
 34.1371 -        int r = mailmime_part_parse(text, length, &index, code, &_longmsg, &_size);
 34.1372 -        switch (r) {
 34.1373 -            case MAILIMF_NO_ERROR:
 34.1374 -                break;
 34.1375 -            case MAILIMF_ERROR_MEMORY:
 34.1376 -                return PEP_OUT_OF_MEMORY;
 34.1377 -            default:
 34.1378 -                return PEP_ILLEGAL_VALUE;
 34.1379 -        }
 34.1380 -    }
 34.1381 -    else {
 34.1382 -        _size = length + 1;
 34.1383 -        _longmsg = strndup(text, length);
 34.1384 -        if (_longmsg == NULL)
 34.1385 -            return PEP_OUT_OF_MEMORY;
 34.1386 -    }
 34.1387 -
 34.1388 -    if (part->mm_content_type) {
 34.1389 -        if (_get_content_type(part->mm_content_type, &type, &charset) == 0) {
 34.1390 -            if (charset && strncasecmp(charset, "utf-8", 5) != 0) {
 34.1391 -                char * _text;
 34.1392 -                int r = charconv("utf-8", charset, _longmsg, _size, &_text);
 34.1393 -                switch (r) {
 34.1394 -                    case MAILIMF_NO_ERROR:
 34.1395 -                        break;
 34.1396 -                    case MAILIMF_ERROR_MEMORY:
 34.1397 -                        return PEP_OUT_OF_MEMORY;
 34.1398 -                    default:
 34.1399 -                        return PEP_ILLEGAL_VALUE;
 34.1400 -                }
 34.1401 -                free(_longmsg);
 34.1402 -                _longmsg = _text;
 34.1403 -            }
 34.1404 -        }
 34.1405 -    }
 34.1406 -    // FIXME: KG - we now have the text we want.
 34.1407 -    // Now we need to strip sigs and process them if they are there..
 34.1408 -    
 34.1409 -
 34.1410 -    *longmsg = _longmsg;
 34.1411 -    if (size)
 34.1412 -        *size = _size;
 34.1413 -
 34.1414 -    return PEP_STATUS_OK;
 34.1415 -}
 34.1416 -
 34.1417 -// THIS IS A BEST-EFFORT ONLY FUNCTION, AND WE ARE NOT DOING MORE THAN THE
 34.1418 -// SUBJECT FOR NOW.
 34.1419 -static PEP_STATUS interpret_protected_headers(
 34.1420 -        struct mailmime* mime, 
 34.1421 -        message* msg
 34.1422 -    )
 34.1423 -{
 34.1424 -    // N.B. this is *very much* enigmail output specific, and right now,
 34.1425 -    // we only care about subject replacement.
 34.1426 -    const char* header_string = "Content-Type: text/rfc822-headers; protected-headers=\"v1\"\nContent-Disposition: inline\n\n";
 34.1427 -    size_t content_length = mime->mm_length;
 34.1428 -    size_t header_strlen = strlen(header_string);
 34.1429 -    if (header_strlen < content_length) {
 34.1430 -        const char* headerblock = mime->mm_mime_start;
 34.1431 -        size_t subject_len = 0;
 34.1432 -        headerblock = strstr(headerblock, header_string);
 34.1433 -        if (headerblock) {
 34.1434 -            const char* subj_start = "Subject: ";
 34.1435 -            headerblock = strstr(headerblock, subj_start);
 34.1436 -            if (headerblock) {
 34.1437 -                size_t subj_len = strlen(subj_start);
 34.1438 -                headerblock += subj_len;
 34.1439 -                char* end_pt = strstr(headerblock, "\n");
 34.1440 -                if (end_pt) {
 34.1441 -                    if (end_pt != mime->mm_mime_start && *(end_pt - 1) == '\r')
 34.1442 -                        end_pt--;
 34.1443 -                    subject_len = end_pt - headerblock;
 34.1444 -                    char* new_subj = (char*)calloc(subject_len + 1, 1);
 34.1445 -                    if (new_subj) {
 34.1446 -                        strlcpy(new_subj, headerblock, subject_len + 1);
 34.1447 -                        free(msg->shortmsg);
 34.1448 -                        msg->shortmsg = new_subj;
 34.1449 -                    }    
 34.1450 -                } // if there's no endpoint, there's something wrong here so we ignore all
 34.1451 -                  // This is best effort.
 34.1452 -            }
 34.1453 -        }
 34.1454 -    }
 34.1455 -    return PEP_STATUS_OK;
 34.1456 -}
 34.1457 -
 34.1458 -static PEP_STATUS interpret_MIME(
 34.1459 -        struct mailmime *mime,
 34.1460 -        message *msg
 34.1461 -    )
 34.1462 -{
 34.1463 -    PEP_STATUS status = PEP_STATUS_OK;
 34.1464 -
 34.1465 -    assert(mime);
 34.1466 -    assert(msg);
 34.1467 -
 34.1468 -    struct mailmime_content *content = mime->mm_content_type;
 34.1469 -    if (content) {
 34.1470 -        if (_is_multipart(content, "alternative")) {
 34.1471 -            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 34.1472 -            if (partlist == NULL)
 34.1473 -                return PEP_ILLEGAL_VALUE;
 34.1474 -
 34.1475 -            clistiter *cur;
 34.1476 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 34.1477 -                struct mailmime *part = clist_content(cur);
 34.1478 -                if (part == NULL)
 34.1479 -                    return PEP_ILLEGAL_VALUE;
 34.1480 -
 34.1481 -                content = part->mm_content_type;
 34.1482 -                assert(content);
 34.1483 -                if (content == NULL)
 34.1484 -                    return PEP_ILLEGAL_VALUE;
 34.1485 -
 34.1486 -                if (_is_text_part(content, "plain") && msg->longmsg == NULL) {
 34.1487 -                    status = interpret_body(part, &msg->longmsg, NULL);
 34.1488 -                    if (status)
 34.1489 -                        return status;
 34.1490 -                }
 34.1491 -                else if (_is_text_part(content, "rfc822-headers")) {
 34.1492 -                    status = interpret_protected_headers(part, msg);
 34.1493 -                    if (status)
 34.1494 -                        return status;
 34.1495 -                }
 34.1496 -                else if (_is_text_part(content, "html") &&
 34.1497 -                        msg->longmsg_formatted == NULL) {
 34.1498 -                    status = interpret_body(part, &msg->longmsg_formatted,
 34.1499 -                            NULL);
 34.1500 -                    if (status)
 34.1501 -                        return status;
 34.1502 -                }
 34.1503 -                else /* add as attachment */ {
 34.1504 -                    status = interpret_MIME(part, msg);
 34.1505 -                    if (status)
 34.1506 -                        return status;
 34.1507 -                }
 34.1508 -            }
 34.1509 -        }
 34.1510 -        else if (_is_multipart(content, "encrypted")) {
 34.1511 -            if (msg->longmsg == NULL)
 34.1512 -                msg->longmsg = strdup("");
 34.1513 -            assert(msg->longmsg);
 34.1514 -            if (!msg->longmsg)
 34.1515 -                return PEP_OUT_OF_MEMORY;
 34.1516 -
 34.1517 -            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 34.1518 -            if (partlist == NULL)
 34.1519 -                return PEP_ILLEGAL_VALUE;
 34.1520 -
 34.1521 -            clistiter *cur;
 34.1522 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 34.1523 -                struct mailmime *part= clist_content(cur);
 34.1524 -                if (part == NULL)
 34.1525 -                    return PEP_ILLEGAL_VALUE;
 34.1526 -
 34.1527 -                status = interpret_MIME(part, msg);
 34.1528 -                if (status != PEP_STATUS_OK)
 34.1529 -                    return status;
 34.1530 -            }
 34.1531 -        }
 34.1532 -        else if (_is_multipart(content, NULL)) {
 34.1533 -            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
 34.1534 -            if (partlist == NULL)
 34.1535 -                return PEP_ILLEGAL_VALUE;
 34.1536 -
 34.1537 -            clistiter *cur;
 34.1538 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
 34.1539 -                struct mailmime *part= clist_content(cur);
 34.1540 -                if (part == NULL)
 34.1541 -                    return PEP_ILLEGAL_VALUE;
 34.1542 -                status = interpret_MIME(part, msg);
 34.1543 -                if (status != PEP_STATUS_OK)
 34.1544 -                    return status;
 34.1545 -            }
 34.1546 -        }
 34.1547 -        else {
 34.1548 -            if (_is_text_part(content, "html") &&
 34.1549 -                msg->longmsg_formatted == NULL) {
 34.1550 -                status = interpret_body(mime, &msg->longmsg_formatted,
 34.1551 -                                        NULL);
 34.1552 -                if (status)
 34.1553 -                    return status;
 34.1554 -            }
 34.1555 -            else if (_is_text_part(content, "rfc822-headers")) {
 34.1556 -                status = interpret_protected_headers(mime, msg);
 34.1557 -                if (status)
 34.1558 -                    return status;
 34.1559 -            }
 34.1560 -            else if (_is_text_part(content, NULL) && msg->longmsg == NULL) {
 34.1561 -                status = interpret_body(mime, &msg->longmsg, NULL);
 34.1562 -                if (status)
 34.1563 -                    return status;
 34.1564 -            }
 34.1565 -            else {
 34.1566 -                char *data = NULL;
 34.1567 -                size_t size = 0;
 34.1568 -                char * mime_type;
 34.1569 -                char * charset;
 34.1570 -                char * filename;
 34.1571 -                int r;
 34.1572 -
 34.1573 -                r = _get_content_type(content, &mime_type, &charset);
 34.1574 -                switch (r) {
 34.1575 -                    case 0:
 34.1576 -                        break;
 34.1577 -                    case EINVAL:
 34.1578 -                        return PEP_ILLEGAL_VALUE;
 34.1579 -                    case ENOMEM:
 34.1580 -                        return PEP_OUT_OF_MEMORY;
 34.1581 -                    default:
 34.1582 -                        return PEP_UNKNOWN_ERROR;
 34.1583 -                }
 34.1584 -
 34.1585 -                assert(mime_type);
 34.1586 -
 34.1587 -                status = interpret_body(mime, &data, &size);
 34.1588 -                if (status)
 34.1589 -                    return status;
 34.1590 -
 34.1591 -                pEp_rid_list_t* resource_id_list = _get_resource_id_list(mime);
 34.1592 -                pEp_rid_list_t* chosen_resource_id = choose_resource_id(resource_id_list);
 34.1593 -                
 34.1594 -                //filename = _get_filename_or_cid(mime);
 34.1595 -                char *_filename = NULL;
 34.1596 -                
 34.1597 -                if (chosen_resource_id) {
 34.1598 -                    filename = chosen_resource_id->rid;
 34.1599 -                    size_t index = 0;
 34.1600 -                    /* NOTA BENE */
 34.1601 -                    /* The prefix we just added shouldn't be a problem - this is about decoding %XX (RFC 2392) */
 34.1602 -                    /* If it becomes one, we have some MESSY fixing to do. :(                                  */
 34.1603 -                    r = mailmime_encoded_phrase_parse("utf-8", filename,
 34.1604 -                            strlen(filename), &index, "utf-8", &_filename);
 34.1605 -                    if (r) {
 34.1606 -                        goto enomem;
 34.1607 -                    }
 34.1608 -                    char* file_prefix = NULL;
 34.1609 -                    
 34.1610 -                    /* in case there are others later */
 34.1611 -                    switch (chosen_resource_id->rid_type) {
 34.1612 -                        case PEP_RID_CID:
 34.1613 -                            file_prefix = "cid";
 34.1614 -                            break;
 34.1615 -                        case PEP_RID_FILENAME:
 34.1616 -                            file_prefix = "file";
 34.1617 -                            break;
 34.1618 -                        default:
 34.1619 -                            break;
 34.1620 -                    }
 34.1621 -
 34.1622 -                    
 34.1623 -                    if (file_prefix) {
 34.1624 -                        filename = build_uri(file_prefix, _filename);
 34.1625 -                        free(_filename);
 34.1626 -                        _filename = filename;
 34.1627 -                    }
 34.1628 -                }
 34.1629 -
 34.1630 -                bloblist_t *_a = bloblist_add(msg->attachments, data, size,
 34.1631 -                        mime_type, _filename);
 34.1632 -                free(_filename);
 34.1633 -                free_rid_list(resource_id_list);
 34.1634 -                resource_id_list = NULL;
 34.1635 -                if (_a == NULL)
 34.1636 -                    return PEP_OUT_OF_MEMORY;
 34.1637 -                if (msg->attachments == NULL)
 34.1638 -                    msg->attachments = _a;
 34.1639 -            }
 34.1640 -        }
 34.1641 -    }
 34.1642 -
 34.1643 -    return PEP_STATUS_OK;
 34.1644 -
 34.1645 -enomem:
 34.1646 -    return PEP_OUT_OF_MEMORY;
 34.1647 -}
 34.1648 -
 34.1649 -DYNAMIC_API PEP_STATUS mime_decode_message(
 34.1650 -        const char *mimetext,
 34.1651 -        size_t size,
 34.1652 -        message **msg
 34.1653 -    )
 34.1654 -{
 34.1655 -    PEP_STATUS status = PEP_STATUS_OK;
 34.1656 -    struct mailmime * mime = NULL;
 34.1657 -    int r;
 34.1658 -    message *_msg = NULL;
 34.1659 -    size_t index;