merge 'default' into JSON-156

JSON-156
Roker 3 years ago
commit fd54377ae2

@ -165,19 +165,19 @@ the `Debug` or `Release` directory of the solution.
## Running the pEp JSON Adapter
You can use `make run` to start the server.
1. Run ./pep-json-server. This creates a file that is readable only by the
current user (~/.pEp/json-token-${USER}) and contains the address and
1. Run `./pEp-mini-json-adapter`. This creates a file that is readable only by the
current user (`~/.pEp/json-token`) and contains the address and
port the JSON adapter is listening on, normally 127.0.0.1:4223 and a
"security-token" that must be given in each function call to authenticate
you as the valid user.
```
./pep-json-server
./pEp-mini-json-adapter
```
2. Visit that address (normally http://127.0.0.1:4223/) in your
2. Visit that address (normally `http://127.0.0.1:4223/`) in your
JavaScript-enabled web browser to see the "JavaScript test client".
3. Call any function ("version()" or "get_gpg_path()" should work just
3. Call any function (`version()` or `get_gpg_path()` should work just
fine) with the correct security token.
## Using the p≡p JSON Adapter
@ -285,6 +285,90 @@ Currently there are no range checks for numerical parameter types (e.g. a
JSON decimal number can hold a bigger value than the `int` parameter type of
a certain C function).
### JSON RPC Requests
The JSON Server Adapter offers its services via HTTP on the address and port
specified on command line. It offers a simple test HTML page on the root
URL.
The JSON RPC functions are POST requests to the path /ja/0.1/callFunction
and the JSON RPC data comes, as usual for POST requests, in the request body and
must be in UTF-8 without any BOM. The `Content-Type` of the request is not relevant.
Here is the body of an example request:
```
{
"id": 1001,
"jsonrpc": "2.0",
"security_token": "YSxxkNga0YUlkmdpUL6_qJuioicGK1wOC5sjGVG",
"method": "import_key",
"params": [
"4oW5PKhgY8XdvIYQiu+KaKnZYyP5UseHD1Sfjb8HpO75m/QT/FxFI………",
4444,
[
"OP"
]
]
}
```
another example:
```
{
"id": 1002,
"jsonrpc": "2.0",
"security_token": "YSxxkNga0YUlkmdpUL6_qJuioicGK1wOC5sjGVG",
"method": "myself",
"params": [
{
"user_id": "alice",
"username": "Alice in pEp land",
"address": "alice@pEp.lol",
"fpr": "4ABE3AAF59AC32CFE4F86500A9411D176FF00E97"
}
]
}
```
Output parameters must be given, but their value is not relevant. The
JavaScript example test client fills the output values with a dummy array,
containing one string element "OP", just to ease debugging.
The result contains the return value and the values of the output parameters,
in reverse order:
Request:
```
{
"id": 1003,
"jsonrpc": "2.0",
"security_token": "YSxxkNga0YUlkmdpUL6_qJuioicGK1wOC5sjGVG",
"method": "get_languagelist",
"params": [
[
"OP"
]
]
}
```
Result:
```
{
"outParams": [
"\"en\",\"English\",\"I want to display the trustwords in English language\"……"
],
"return": {
"status": 0,
"hex": "0 \"PEP_STATUS_OK\""
}
}
```
### API Reference
An complete overview with all functions that are callable from the client

@ -111,7 +111,6 @@
<ClInclude Include="..\..\server\json_spirit\json_spirit_writer_template.h" />
<ClInclude Include="..\..\server\logger.hh" />
<ClInclude Include="..\..\server\logger_config.hh" />
<ClInclude Include="..\..\server\mini-adapter-impl.hh" />
<ClInclude Include="..\..\server\nfc.hh" />
<ClInclude Include="..\..\server\nfc_sets.hh" />
<ClInclude Include="..\..\server\pEp-types.hh" />
@ -128,7 +127,7 @@
<ClCompile Include="..\..\server\base64.cc" />
<ClCompile Include="..\..\server\context.cc" />
<ClCompile Include="..\..\server\c_string.cc" />
<ClCompile Include="..\..\server\daemonize.cc" />
<ClCompile Include="..\..\server\daemonize_windows.cc" />
<ClCompile Include="..\..\server\ev_server.cc" />
<ClCompile Include="..\..\server\function_map.cc" />
<ClCompile Include="..\..\server\inout.cc" />

@ -105,9 +105,6 @@
<ClInclude Include="..\..\server\json_spirit\json_spirit_writer_template.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\server\mini-adapter-impl.hh">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\server\session_registry.hh">
<Filter>Header Files</Filter>
</ClInclude>
@ -155,9 +152,6 @@
<ClCompile Include="..\..\server\ev_server.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\server\daemonize.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\server\context.cc">
<Filter>Source Files</Filter>
</ClCompile>
@ -182,6 +176,9 @@
<ClCompile Include="..\..\server\session_registry.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\server\daemonize_windows.cc">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

@ -1,154 +1,196 @@
# Copyright 2017 pEp Security SA
#
# This file is part of pEp JSON Server Adapter.
#
# pEp JSON Server Adapter is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License, version 3, as
# published by the Free Software Foundation.
#
# pEp JSON Server Adapter is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with pEp JSON Server Adapter. If not, see <http://www.gnu.org/licenses/>.
include Makefile.conf
ifneq ($(wildcard local.conf),)
$(info ================================================)
$(info Overrides in \`local.conf\` are used.)
$(info ================================================)
endif
ifdef BUILD_CONFIG
$(info ================================================)
$(info Overrides in \`$(BUILD_CONFIG)\` are used.)
$(info ================================================)
endif
# These source files shall _not_ be part of the libjson-adapter.a:
NO_SOURCE=$(wildcard mini-adapter-*.cc) servertest.cc $(wildcard unittest_*.cc)
ALL_SOURCE=$(filter-out $(NO_SOURCE),$(wildcard json_spirit/*.cpp))
ALL_SOURCE+= prefix-config.cc
ALL_SOURCE+= $(filter-out $(NO_SOURCE),$(wildcard *.cc))
DEPENDS0=$(subst .cpp,.d,$(ALL_SOURCE))
DEPENDS=$(subst .cc,.d,$(DEPENDS0))
ALL_OBJECTS0=$(subst .cpp,.o,$(ALL_SOURCE))
ALL_OBJECTS=$(subst .cc,.o,$(ALL_OBJECTS0))
# this ifeq is not optional, because otherwise local.conf would always be built
ifeq ($(BUILD_FOR),Linux)
LIBPATH=LD_LIBRARY_PATH
else
LIBPATH=DYLD_LIBRARY_PATH
ifeq ($(wildcard local.conf),local.conf)
-include local.conf
endif
ifeq ($(BUILD_FOR),Linux)
LD_EAGER_VAR=LD_BIND_NOW=placeholder
else
LD_EAGER_VAR=DYLD_BIND_AT_LAUNCH=placeholder
endif
# Create a list of the extra library paths for the loader.
# Note that += can not be used here, as it changes the amount of whitespace
EXTRA_LIB_PATHS=$(PREFIX)/lib:
ifdef BOOST_LIB
EXTRA_LIB_PATHS:=$(EXTRA_LIB_PATHS)$(patsubst -L%,%,$(BOOST_LIB)):
endif
ifdef ENGINE_LIB
EXTRA_LIB_PATHS:=$(EXTRA_LIB_PATHS)$(patsubst -L%,%,$(ENGINE_LIB)):
endif
ifdef ETPAN_LIB
EXTRA_LIB_PATHS:=$(EXTRA_LIB_PATHS)$(patsubst -L%,%,$(ETPAN_LIB)):
endif
ifdef GPGME_LIB
EXTRA_LIB_PATHS:=$(EXTRA_LIB_PATHS)$(patsubst -L%,%,$(GPGME_LIB)):
endif
ifdef UUID_LIB
EXTRA_LIB_PATHS:=$(EXTRA_LIB_PATHS)$(patsubst -L%,%,$(UUID_LIB)):
endif
# Remove trailing ':'
EXTRA_LIB_PATHS:=$(EXTRA_LIB_PATHS::=)
# default config
CMD_PFX=$(LIBPATH)=$(EXTRA_LIB_PATHS)
# these are source builds
ifdef DEBUG
CMD_PFX+= $(LD_EAGER_VAR)
endif
PEP_WEBSERVER?=../../webserver
PEP_ADAPTER_LIBRARY=../../libpEpAdapter
PEP_ENGINE?=../../pEpEngine
LIBETPAN_FDIK?=../../libetpan
SEQOUIA_PGP?=../../sequoia
NETTLE?=../../nettle
BOOST_INCLUDE_PATH?=../../boost_1_72_0
BOOST_LIBRARY_PATH?=../../boost_1_72_0/stage/lib
.PHONY: all lib
all: $(TARGET) $(TARGET_TEST) $(TARGET_GTEST)
# path to installed libraries
lib: libjson-adapter.a
PREFIX=$(HOME)
$(TARGET): mini-adapter-main.o mini-adapter-impl.o libjson-adapter.a
$(CXX) $(CPPFLAGS) $^ $(LDFLAGS) $(LDLIBS) -o $@
PEP_INCLUDE?=$(PREFIX)/include
$(TARGET)-static: mini-adapter-main.o mini-adapter-impl.o libjson-adapter.a
$(CXX) $(CPPFLAGS) $^ $(LDFLAGS) $(LDLIBS) -static -o $@
LIBRARY_PATH?=/opt/local/lib
$(TARGET_TEST): servertest.o libjson-adapter.a
$(CXX) $(CPPFLAGS) $^ $(LDFLAGS) $(LDLIBS) -o $@
GMP_LIBRARY_PATH?=$(LIBRARY_PATH)
SQLITE3_LIBRARY_PATH?=$(LIBRARY_PATH)
LIBZ_LIBRARY_PATH?=$(LIBRARY_PATH)
ICONV_LIBRARY_PATH?=$(LIBRARY_PATH)
LIBEVENT_LIBRARY_PATH=$(LIBRARY_PATH)
$(TARGET_GTEST): unittest_json.o unittest_nfc.o unittest_decompose.o unittest_rpc.o \
unittest_logger.o unittest_pEp.o \
gtest-all.o gtest_main.o libjson-adapter.a
$(CXX) $(CPPFLAGS) $^ $(LDFLAGS) $(LDLIBS) -o $@
AR?=ar
CC?=cc
CXX?=c++
CFLAGS+=-std=c14
CXXFLAGS+=-I$(BOOST_INCLUDE_PATH) -I$(PEP_INCLUDE) -std=c++14
LDFLAGS+=-std=c++14
libjson-adapter.a: $(ALL_OBJECTS)
$(AR) rcs $@ $^
ifdef NDEBUG
CFLAGS+=-O3 -DNDEBUG -fvisibility=hidden -fno-stack-check
CXXFLAGS+=-O3 -DNDEBUG -fvisibility=hidden -fno-stack-check
else
CFLAGS+=-O0 -g -DDEBUG_ENABLED -fvisibility=hidden -fno-stack-check
CXXFLAGS+=-O0 -g -DDEBUG_ENABLED -fvisibility=hidden -fno-stack-check
endif
gtest-all.o: $(GTEST_DIR)/src/gtest-all.cc
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -o $@ -c $<
TARGET=pEp-mini-json-adapter
LIB_TARGET=libjson-adapter.a
gtest_main.o: $(GTEST_DIR)/src/gtest_main.cc
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -o $@ -c $<
ALL_SOURCE=$(filter-out unittest_%.cc,$(wildcard *.cc))
LIB_SOURCE=$(filter-out miniadapter-%.cc,$(ALL_SOURCE))
MA_SOURCE=$(wildcard miniadapter-*.cc)
DEPENDS=$(subst .cc,.d,$(ALL_SOURCE))
ALL_OBJECTS=$(subst .d,.o,$(DEPENDS))
LIB_OBJECTS=$(subst .cc,.o,$(LIB_SOURCE))
MA_OBJECTS=$(subst .cc,.o,$(MA_SOURCE))
SPIRIT_SOURCE=$(wildcard json_spirit/*.cpp)
SPIRIT_OBJECTS=$(subst .cpp,.o,$(SPIRIT_SOURCE))
%.o: %.cc %.hh
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
TEST_SOURCE=$(wildcard test_*.cc)
TEST_OBJECTS=$(subst .cc,.o,$(TEST_SOURCE))
TESTS=$(subst .cc,,$(TEST_SOURCE))
%.d: %.cpp
@set -e; rm -f $@; \
$(CXX) -MM $(CPPFLAGS) $(CXXFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
all: $(TARGET)
%.d: %.cc
@set -e; rm -f $@; \
$(CXX) -MM $(CPPFLAGS) $(CXXFLAGS) $< > $@.$$$$; \
$(CC) -MM $(CPPFLAGS) $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# If only the goal 'clean' is given, do not generate and include the '%.d' files.
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPENDS)
-include $(DEPENDS)
endif
.PHONY: install
install: all
mkdir -v -p "$(PREFIX)/bin" "$(PREFIX)/lib"
mkdir -v -p "$(HTML_DIRECTORY)"
cp -v ../html/* "$(HTML_DIRECTORY)"
cp -v libjson-adapter.a "$(PREFIX)/lib"
cp -v "$(TARGET)" "$(TARGET_TEST)" "$(TARGET_GTEST)" "$(PREFIX)/bin"
$(LIB_TARGET): $(LIB_OBJECTS)
$(AR) -cr $@ $^
$(TARGET): $(LIB_TARGET) $(MA_OBJECTS) $(SPIRIT_OBJECTS)
$(CXX) $(LDFLAGS) -liconv \
-lobjc -framework Foundation -framework Security \
$(PEP_WEBSERVER)/libpEpwebserver.a \
$(BOOST_LIBRARY_PATH)/libboost_filesystem$(BOOST_MT).a \
$(BOOST_LIBRARY_PATH)/libboost_program_options$(BOOST_MT).a \
$(BOOST_LIBRARY_PATH)/libboost_system$(BOOST_MT).a \
$(BOOST_LIBRARY_PATH)/libboost_thread$(BOOST_MT).a \
$(BOOST_LIBRARY_PATH)/libboost_regex$(BOOST_MT).a \
$(ICONV_LIBRARY_PATH)/libiconv.a \
$(LIBZ_LIBRARY_PATH)/libz.a \
$(SQLITE3_LIBRARY_PATH)/libsqlite3.a \
$(GMP_LIBRARY_PATH)/libgmp.a \
$(NETTLE)/libnettle.a $(NETTLE)/libhogweed.a \
$(SEQOUIA_PGP)/target/release/libsequoia_ffi.a \
$(SEQOUIA_PGP)/target/release/libsequoia_openpgp_ffi.a \
$(LIBETPAN_FDIK)/src/.libs/libetpan.a \
$(PEP_ENGINE)/src/libpEpEngine.a $(PEP_ENGINE)/asn.1/libasn1.a \
$(PEP_ADAPTER_LIBRARY)/libpEpAdapter.a \
$(MA_OBJECTS) $(SPIRIT_OBJECTS) $(LIB_TARGET) -o "$@"
%.o: %.cc
$(CXX) $(CXXFLAGS) -c -o $@ $^
test_%: test_%.o $(TARGET)
$(CXX) $(LDFLAGS) $(TARGET) -o $@ $<
test: $(TESTS)
for i in $(TESTS) ; do ./$$i ; done
.PHONY: clean uninstall install
install: $(TARGET)
mkdir -p $(PREFIX)/include/pEp
cp -v *.hh $(PREFIX)/include/pEp
cp -v lib*.a $(PREFIX)/lib/
uninstall:
for i in *.hh; do rm -f $(PREFIX)/include/pEp/\$i ; done
.PHONY: clean
clean:
rm -vf "$(TARGET)" "$(TARGET_TEST)" "$(TARGET_GTEST)"
rm -vf *.o json_spirit/*.o
rm -vf *.a json_spirit/*.a
rm -vf *.d json_spirit/*.d
.PHONY: run
run:
@echo "The adapter must be installed for $< to work"
$(CMD_PFX) "$(PREFIX)/bin/$(TARGET)"
.PHONY: test
test:
@echo "The adapter must be installed for $< to work"
$(CMD_PFX) "$(PREFIX)/bin/$(TARGET_TEST)"
$(CMD_PFX) "$(PREFIX)/bin/$(TARGET_GTEST)"
rm -vf *.o *.d *.d.* $(TARGET) $(TESTS)
local.conf:
@echo "# the following are directories with the source build" >> local.conf
@echo "# ---------------------------------------------------" >> local.conf
@echo >> local.conf
@echo "# path to pEp webserver" >> local.conf
@echo >> local.conf
@echo "PEP_WEBSERVER=$(PEP_WEBSERVER)" >> local.conf
@echo >> local.conf
@echo "# path to pEp adapter library" >> local.conf
@echo >> local.conf
@echo "PEP_ADAPTER_LIBRARY=$(PEP_ADAPTER_LIBRARY)" >> local.conf
@echo >> local.conf
@echo "# path to pEp engine" >> local.conf
@echo >> local.conf
@echo "PEP_ENGINE=$(PEP_ENGINE)" >> local.conf
@echo >> local.conf
@echo "# path to fdik fork of libetpan" >> local.conf
@echo >> local.conf
@echo "LIBETPAN_FDIK=$(LIBETPAN_FDIK)" >> local.conf
@echo >> local.conf
@echo "# path to Sequoia PGP" >> local.conf
@echo >> local.conf
@echo "SEQOUIA_PGP=$(SEQOUIA_PGP)" >> local.conf
@echo >> local.conf
@echo "# path to nettle and hogweed crypto libraries" >> local.conf
@echo >> local.conf
@echo "NETTLE=$(NETTLE)" >> local.conf
@echo >> local.conf
@echo "# path where to find boost" >> local.conf
@echo >> local.conf
@echo "BOOST_INCLUDE_PATH=$(BOOST_INCLUDE_PATH)" >> local.conf
@echo "BOOST_LIBRARY_PATH=$(BOOST_LIBRARY_PATH)" >> local.conf
@echo >> local.conf
@echo >> local.conf
@echo "# these are installation directories" >> local.conf
@echo "# ----------------------------------" >> local.conf
@echo >> local.conf
@echo "# pEp installation header file directory" >> local.conf
@echo >> local.conf
@echo "PEP_INCLUDE=$(PEP_INCLUDE)" >> local.conf
@echo >> local.conf
@echo "# path where to find GMP" >> local.conf
@echo >> local.conf
@echo "GMP_LIBRARY_PATH=$(GMP_LIBRARY_PATH)" >> local.conf
@echo >> local.conf
@echo "# path where to find SQLite3" >> local.conf
@echo >> local.conf
@echo "SQLITE3_LIBRARY_PATH=$(SQLITE3_LIBRARY_PATH)" >> local.conf
@echo >> local.conf
@echo "# path where to find libz" >> local.conf
@echo >> local.conf
@echo "LIBZ_LIBRARY_PATH=$(LIBZ_LIBRARY_PATH)" >> local.conf
@echo >> local.conf
@echo "# path where to find GNU iconv" >> local.conf
@echo >> local.conf
@echo "ICONV_LIBRARY_PATH=$(ICONV_LIBRARY_PATH)" >> local.conf
@echo >> local.conf
@echo "# path where to find libevent" >> local.conf
@echo >> local.conf
@echo "LIBEVENT_LIBRARY_PATH=$(LIBEVENT_LIBRARY_PATH)" >> local.conf
help:
@echo "usage:"
@echo " make local.conf # optional"
@echo " generate a local.conf with default paths"
@echo
@echo " make libjson-adapter.a"
@echo " build adapter library"
@echo
@echo " make pEp-mini-json-adapter # default"
@echo " compile and link mini adapter"
@echo

@ -1,153 +0,0 @@
# Copyright 2017 pEp Security SA
#
# This file is part of pEp JSON Server Adapter.
#
# pEp JSON Server Adapter is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License, version 3, as
# published by the Free Software Foundation.
#
# pEp JSON Server Adapter is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with pEp JSON Server Adapter. If not, see <http://www.gnu.org/licenses/>.
HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
######### General #########
BUILD_ON:=$(shell uname)
# This variable specifies the platform that the engine should be cross-compiled for.
BUILD_FOR=$(BUILD_ON)
# Cross-compiling is currently not supported.
# Maybe you can hack something with `local.conf`.
ifneq ($(BUILD_ON),$(BUILD_FOR))
$(error "I don't know how to build for $(BUILD_FOR) on $(BUILD_ON).")
endif
# Installation path prefix for libraries and binaries, except for HTML files
PREFIX=/usr
# Installation path for HTML files
HTML_DIRECTORY=$(PREFIX)/share/pEp/json-adapter/html
# Filename of the pEp JSON Server Adapter binary
TARGET=pEp-mini-json-adapter
# Filename of the pEp JSON Server Adapter testing binary
TARGET_TEST=servertest
# Filename of the unittest binary
TARGET_GTEST=unittests
# If empty, create a release build.
# Otherwise, create a debug build.
# This variable is ineffective in your local.conf file.
DEBUG=placeholder
# If empty, suppress compiler warnings.
# Otherwise, print warnings.
# This variable is ineffective in your local.conf file.
WARN=placeholder
######### C++ #########
TARGET_ARCH=
ifeq ($(BUILD_FOR),Linux)
CXX=g++ -std=c++14 -pthread -fPIC
else ifeq ($(BUILD_FOR),Darwin)
# clang issues a warning when "-pthread" is used for linking. So, include it in CXXFLAGS, and not in CXX
# "c++" != "clang"
CXX=c++ -std=c++14 -fPIC
endif
HTML_DIR ?= "html"
CPPFLAGS=-isystem $(GTEST_DIR)/include -DHTML_DIR=$(HTML_DIR)
ifeq ($(BUILD_FOR),Linux)
CXXFLAGS=-fstack-protector-all # -fdiagnostics-color=always
ifdef WARN
CXXFLAGS+= -Wall
else
CXXFLAGS+= -w
endif
ifdef DEBUG
CXXFLAGS+= -O0 -g -ggdb -DDEBUG_ENABLED
else
CXXFLAGS+= -O3 -DNDEBUG
endif
CXXFLAGS+=-fvisibility=hidden
else ifeq ($(BUILD_FOR),Darwin)
CXXFLAGS=-pthread -fstack-protector-all # -fcolor-diagnostics
ifdef WARN
CXXFLAGS+= -Wall
else
CXXFLAGS+= -w
endif
ifdef DEBUG
CXXFLAGS+= -O0 -g -DDEBUG_ENABLED
else
CXXFLAGS+= -O3 -DNDEBUG
endif
CXXFLAGS+=-fvisibility=hidden
endif
CXXFLAGS+= -Ijson_spirit $(BOOST_INC) $(ENGINE_INC) $(ETPAN_INC) $(GPGME_INC) $(UUID_INC)
LDFLAGS+= $(BOOST_LIB) $(ENGINE_LIB) $(ETPAN_LIB) $(GPGME_LIB) $(UUID_LIB)
ifeq ($(BUILD_FOR),Linux)
LDLIBS+= -lpEpEngine -lpEpAdapter -lboost_system -lboost_filesystem -lboost_program_options -lboost_thread -Wl,-rpath-link="$(patsubst -L%,%,$(ETPAN_LIB))"
GTEST_DIR=/usr/src/googletest/googletest/
else ifeq ($(BUILD_FOR),Darwin)
LDLIBS+= -lpEpEngine -lpEpAdapter -lboost_system-mt -lboost_filesystem-mt -lboost_program_options-mt -lboost_thread-mt
endif
LDLIBS+=$(WEBSERVER_LIB) -lboost_regex-mt
######### Google Test #########
#GTEST_DIR=
######### boost #########
BOOST_INC=
BOOST_LIB=
######### Engine #########
ENGINE_INC=-I$(HOME)/code/engine/build/include
ENGINE_LIB=-L$(HOME)/code/engine/build/lib
######### Etpan #########
ETPAN_INC=-I$(HOME)/code/libetpan/build/include
ETPAN_LIB=-L$(HOME)/code/libetpan/build/lib
######### pEp::Webserver #########
WEBSERVER_LIB=$(HOME)/local/lib/libpEpwebserver.a
######### GPGME #########
GPGME_INC=
GPGME_LIB=
######### OSSP uuid #########
UUID_INC=
UUID_LIB=
######### Footer #########
-include $(HERE)/local.conf
ifdef BUILD_CONFIG
-include $(BUILD_CONFIG)
endif

@ -1,10 +1,18 @@
#include "base64.hh"
#include "logger.hh"
#include <stdint.h>
#include <stdexcept>
namespace
{
Logger& Log()
{
static Logger L("b64");
return L;
}
#define __ (-1) // invalid char -> exception!
#define SP (-2) // space char -> ignore
#define EQ (-3) // '=' char -> special handling of EOF
@ -80,6 +88,7 @@ try{
if(u3!=255) { ret += char( (u2 << 6) | (u3 ) ); }
}
DEBUG_OUT( Log(), "decode %zu input bytes into %zd output bytes.", input.size(), ret.size());
return ret;
}
catch(const IllegalCharacter& ic)
@ -115,9 +124,10 @@ std::string base64_encode(const std::string& input)
ret += b64c[ (u>>12) & 63 ];
ret += b64c[ (u>> 6) & 63 ];
ret += '=';
DEBUG_OUT( Log(), "encode %zu input bytes into %zd output bytes.", input.size(), ret.size());
return ret;
}
case 1 :
{
const uint32_t u = U8(s[0])*65536;
@ -125,9 +135,16 @@ std::string base64_encode(const std::string& input)
ret += b64c[ (u>>12) & 63 ];
ret += '=';
ret += '=';
DEBUG_OUT( Log(), "encode %zu input bytes into %zd output bytes.", input.size(), ret.size());
return ret;
}
case 0: return ret;
case 0:
{
DEBUG_OUT( Log(), "encode %zu input bytes into %zd output bytes.", input.size(), ret.size());
return ret;
}
default : throw std::logic_error("Internal error in base64_encode()!");
}
}

@ -16,3 +16,6 @@ Out<c_string, ParamFlag::DontOwn>::~Out()
template<>
In<size_t, ParamFlag::NoInput>::~In()
{}
template<>
js::Value Type2String<binary_string>::get() { return "BinaryString"; }

@ -10,11 +10,17 @@
#include <string>
#include "inout.hh"
#include "base64.hh"
// just an empty tag type
// just empty tag types:
// UTF-8 NFC strings:
struct c_string
{ };
// "binary" strings. Always base64-encoded at JSON-RPC side
struct binary_string
{ };
template<ParamFlag PF>
struct In<c_string, PF>
@ -48,6 +54,40 @@ struct In<c_string, PF>
const std::string value;
};
template<ParamFlag PF>
struct In<binary_string, PF>
{
typedef In<binary_string, PF> Self;
typedef const char* c_type;
enum { is_output = false, need_input = !(PF & ParamFlag::NoInput) };
~In() = default;
In(const Self& other) = delete;
In(Self&& victim) = delete;
Self& operator=(const Self&) = delete;
In(const js::Value& v, Context* ctx, unsigned param_nr)
: is_null ( v.is_null() )
, value( bool(PF & ParamFlag::NullOkay) && is_null ? "" : base64_decode(from_json<std::string>(v)) )
{
ctx->store(param_nr, value.length());
}
js::Value to_json() const
{
return is_null ? js::Value{} : ::to_json<std::string>(base64_encode(value));
}
c_type get_value() const { return is_null ? nullptr : value.data(); }
const bool is_null;
const std::string value;
};
template<ParamFlag PF>
struct Out<c_string, PF>

@ -1,13 +1,33 @@
#include "context.hh"
#include "logger.hh"
namespace
{
Logger& Log()
{
static Logger L("ctx");
return L;
}
}
void Context::store(int position, size_t value)
{
DEBUG_OUT( Log(), "Store value %zu for position %d.", value, position);
obj_store.emplace( position, value );
}
size_t Context::retrieve(int position)
{
return obj_store.at(position);
try{
const size_t value = obj_store.at(position);
DEBUG_OUT( Log(), "Retrieve value %zu for position %d.", value, position);
return value;
}catch(const std::out_of_range& e)
{
Log() << Logger::Error << "There is no value stored at position " << position << "!";
throw;
}
}

@ -0,0 +1,15 @@
#include "daemonize.hh"
// Unix/Linux implementation
#include <cstdlib>
void daemonize (const bool, const uintptr_t )
{
daemon(1,0);
}
void daemonize_commit (const int retval)
{
// nothing to do anymore. It was totally BS.
}

@ -169,189 +169,4 @@ void daemonize_commit (int retval)
throw std::runtime_error("Can not close pipe's write end in background process!");
}
#else
// Unix/Linux implementation
#include <cstdlib>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#include <thread>
#include <iostream>
#include <stdexcept>
#include <system_error>
volatile sig_atomic_t sig_term_recv = 0;
int retval_pipefd[2]; /* read fd, write fd */
pid_t fpid = 1; /* frontend process PID */
void handle_sig_term (int signal)
{
sig_term_recv = 1;
}
void daemonize (const bool daemonize, const uintptr_t status_handle)
{
int retval = EXIT_FAILURE;
pid_t pid, sid, daemon_pid;
struct sigaction sig_action = {};
sig_action.sa_handler = handle_sig_term;
bool this_process_should_term = 0;
int child_status = 0;
FILE * ipipe;
int c;
pid = getpid();
if ( daemonize == true && fpid == 1 ) fpid = pid;
/* only the frontend process shall continue */
if ( fpid == 1 || fpid != pid ) return;
if (pipe (retval_pipefd))
throw std::runtime_error ("Cannot create return-value pipe!");
/* now fork the intermediate process */
pid = fork ();
if (pid < 0)
throw std::runtime_error ("Cannot fork child process!");
if (pid > 0)
{
/*
* This is the foreground process which needs to stick around until the
* background process has comminicated success or failure or has crashed.
* As soon as a feedback is obtained from the background process, inform
* the intermediate process to exit (kill TERM) and eventually "copy up"
* the exit value of the background process.
*/
/* close the write end of the return value pipe */
close (retval_pipefd[1]);
/* read pipe until closed or crashed on writing side */
ipipe = fdopen (retval_pipefd[0], "r");
while ((c = getw (ipipe)) != EOF)
{
retval = c;
this_process_should_term = 1;
}
fclose (ipipe);
if (c == EOF)
this_process_should_term = 1;
do
{
kill (pid, SIGTERM);
if (!this_process_should_term && (waitpid (pid, &child_status, WUNTRACED) > 0))
{
if (WIFEXITED(child_status) || WIFSIGNALED(child_status))
{
retval = WEXITSTATUS(child_status);
this_process_should_term = 1;
}
}
} while (!this_process_should_term);
exit (retval); /* exit the foreground process */
}
/*
* At this point we are the intermediate child process,
* which now needs to fork the daemon process.
*/
/* close the read end of the pipe, belonging to the foreground process */
close (retval_pipefd[0]);
/* create a new SID for the child process */
sid = setsid();
if (sid < 0)
throw std::runtime_error ("Cannot call setsid()");
daemon_pid = fork();
if (daemon_pid < 0)
throw std::runtime_error ("Cannot fork again!");
if (daemon_pid > 0)
{
/*
* This now sticks around until it gets the TERM signal from the
* foreground process. At that point, it will see if the daemon
* process is still running, and if not, proxy it's retval (which
* will be again proxied by the frontend process).
*/
close (retval_pipefd[1]);
do {
if (!this_process_should_term && (waitpid (daemon_pid, &child_status, WUNTRACED) > 0))
{
if ((WIFEXITED(child_status) || WIFSIGNALED(child_status)))
{
retval = WEXITSTATUS(child_status);
this_process_should_term = 1;
}
}
}
while (!(sig_term_recv || this_process_should_term));
_exit (retval);
}
/* At this point we are a daemon process */
sig_action.sa_handler = SIG_DFL;
sigaction (SIGTERM, &sig_action, NULL);
umask (0007);
/* daemons normally chdir("/"), we don't do this until our code has evolved */
/* chdir("/"); */
/* We delay closing the terminal to daemonize_commit(). */
const int fd = open ("/dev/null", O_RDONLY, 0);
if (fd == -1)
throw std::runtime_error ("Cannot open /dev/null!");
dup2 (fd, STDIN_FILENO);
}
void daemonize_commit (const int retval)
{
static int commited = 0;
FILE * retvalfd;
pid_t pid;
pid = getpid();
/* nothing to do if not the daemon process */
if ( fpid == 1 || fpid == pid )
return;
if (commited) return;
commited = 1;
const int fd = open ("/dev/null", O_WRONLY, 0);
if (fd == -1)
throw std::runtime_error ("Cannot open /dev/null!");
retvalfd = fdopen (retval_pipefd[1], "a");
putw (retval, retvalfd);
fclose (retvalfd);
close (retval_pipefd[1]);
dup2 (fd, STDOUT_FILENO);
dup2 (fd, STDERR_FILENO);
}
#endif // ! _WIN32
#endif // _WIN32

@ -22,6 +22,7 @@
#include <pEp/Adapter.hh>
#include <pEp/status_to_string.hh>
#include <pEp/slurp.hh>
#include <pEp/message_cache.hh>
#include <boost/filesystem.hpp>
#include "json_spirit/json_spirit_reader.h"
@ -69,28 +70,36 @@ const FunctionMap functions = {
// from message_api.h
FP( "Message API", new Separator ),
FP( "encrypt_message", new FuncPC<PEP_STATUS, In_Pep_Session, InOut<message*>, In<stringlist_t*>, Out<message*>, In<PEP_enc_format>, In<PEP_encrypt_flags_t>>( &encrypt_message ) ),
FP( "cache_encrypt_message", new FuncPC<PEP_STATUS, In_Pep_Session, InOut<message*>, In<stringlist_t*>, Out<message*>, In<PEP_enc_format>, In<PEP_encrypt_flags_t>>( &pEp::MessageCache::cache_encrypt_message ) ),
FP( "encrypt_message_and_add_priv_key", new FuncPC<PEP_STATUS, In_Pep_Session,
In<message*>, Out<message*>, In<c_string>, In<PEP_enc_format>, In<PEP_encrypt_flags_t>>( &encrypt_message_and_add_priv_key) ),
FP( "encrypt_message_for_self", new FuncPC<PEP_STATUS, In_Pep_Session,
In<pEp_identity*>, In<message*>, In<stringlist_t*>, Out<message*>, In<PEP_enc_format>, In<PEP_encrypt_flags_t>>( &encrypt_message_for_self ) ),
FP( "cache_encrypt_message_for_self", new FuncPC<PEP_STATUS, In_Pep_Session,
In<pEp_identity*>, In<message*>, In<stringlist_t*>, Out<message*>, In<PEP_enc_format>, In<PEP_encrypt_flags_t>>( &pEp::MessageCache::cache_encrypt_message_for_self) ),
FP( "decrypt_message", new FuncPC<PEP_STATUS, In_Pep_Session, InOut<message*>, Out<message*>, InOutP<stringlist_t*>, Out<PEP_rating>, InOutP<PEP_decrypt_flags_t>>( &decrypt_message ) ),
FP( "get_key_rating_for_user", new Func<PEP_STATUS, In_Pep_Session, In<c_string>, In<c_string>, Out<PEP_rating>>( &get_key_rating_for_user) ),
FP( "cache_decrypt_message", new FuncPC<PEP_STATUS, In_Pep_Session, InOut<message*>, Out<message*>, InOutP<stringlist_t*>, Out<PEP_rating>, InOutP<PEP_decrypt_flags_t>>( &pEp::MessageCache::cache_decrypt_message) ),
FP( "get_key_rating_for_user", new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, In<c_string>, Out<PEP_rating>>( &get_key_rating_for_user) ),
// from mime.h
FP( "MIME handling API", new Separator),
FP( "mime_encode_message", new Func<PEP_STATUS, In<const message*>, In<bool>, Out<char*>, In<bool, ParamFlag::NoInput>>( &mime_encode_message )),
FP( "cache_mime_encode_message", new Func<PEP_STATUS, In<int>, In<const message*>, In<bool>, Out<char*>, In<bool, ParamFlag::NoInput>>( &pEp::MessageCache::cache_mime_encode_message)),
FP( "cache_release", new Func<PEP_STATUS, In<c_string>>( &pEp::MessageCache::cache_release )),
FP( "mime_decode_message", new Func<PEP_STATUS, In<c_string>, InLength<>, Out<message*>, In<bool*, ParamFlag::NoInput>>( &mime_decode_message )),
FP( "cache_mime_decode_message", new Func<PEP_STATUS, In<c_string>, InLength<>, Out<message*>, In<bool*, ParamFlag::NoInput>>( &pEp::MessageCache::cache_mime_decode_message )),
// from pEpEngine.h
FP( "pEp Engine Core API", new Separator),
// FP( "log_event", new Func<PEP_STATUS, In_Pep_Session, In<c_string>, In<c_string>, In<c_string>, In<c_string>>( &log_event) ),
FP( "get_trustwords", new Func<PEP_STATUS, In_Pep_Session, In<const pEp_identity*>, In<const pEp_identity*>, In<Language>, Out<char*>, Out<size_t>, In<bool>>( &get_trustwords) ),
FP( "re_evaluate_message_rating", new Func<PEP_STATUS, In_Pep_Session, In<message *>, In<stringlist_t *>, In<PEP_rating>, Out<PEP_rating>>( &re_evaluate_message_rating ) ),
FP( "get_languagelist", new Func<PEP_STATUS, In_Pep_Session, Out<char*>>( &get_languagelist) ),
FP( "get_trustwords", new FuncPC<PEP_STATUS, In_Pep_Session, In<const pEp_identity*>, In<const pEp_identity*>, In<Language>, Out<char*>, Out<size_t>, In<bool>>( &get_trustwords) ),
FP( "re_evaluate_message_rating", new FuncPC<PEP_STATUS, In_Pep_Session, In<message *>, In<stringlist_t *>, In<PEP_rating>, Out<PEP_rating>>( &re_evaluate_message_rating ) ),
FP( "get_languagelist", new FuncPC<PEP_STATUS, In_Pep_Session, Out<char*>>( &get_languagelist) ),
// FP( "get_phrase" , new Func<PEP_STATUS, In_Pep_Session, In<Language>, In<int>, Out<char*>> ( &get_phrase) ),
// FP( "get_engine_version", new Func<const char*> ( &get_engine_version) ),
FP( "is_pEp_user" , new Func<PEP_STATUS, In_Pep_Session, In<pEp_identity*>, Out<bool>>( &is_pEp_user) ),
FP( "is_pEp_user" , new FuncPC<PEP_STATUS, In_Pep_Session, In<pEp_identity*>, Out<bool>>( &is_pEp_user) ),
FP( "config_passive_mode", new FuncCache<void, In_Pep_Session, In<bool>>( "conf_p_m", &config_passive_mode) ),
FP( "config_unencrypted_subject", new FuncCache<void, In_Pep_Session, In<bool>>( "conf_u_s", &config_unencrypted_subject) ),
@ -102,49 +111,49 @@ const FunctionMap functions = {
FP( "config_passphrase_for_new_keys", new FuncCachePassphrase4NewKeys<void, In_Pep_Session, In<bool>, In<c_string>>( "config_passphrase4nk" ) ),
FP( "Identity Management API", new Separator),
FP( "get_identity" , new Func<PEP_STATUS, In_Pep_Session, In<c_string>, In<c_string>, Out<pEp_identity*>>( &get_identity) ),
FP( "set_identity" , new Func<PEP_STATUS, In_Pep_Session, In<const pEp_identity*>> ( &set_identity) ),
FP( "mark_as_comprimized", new Func<PEP_STATUS, In_Pep_Session, In<c_string>> ( &mark_as_compromized) ),
FP( "identity_rating" , new Func<PEP_STATUS, In_Pep_Session, In<pEp_identity*>, Out<PEP_rating>>( &identity_rating) ),
FP( "outgoing_message_rating", new Func<PEP_STATUS, In_Pep_Session, In<message*>, Out<PEP_rating>>( &outgoing_message_rating) ),
FP( "outgoing_message_rating_preview", new Func<PEP_STATUS, In_Pep_Session, In<message*>, Out<PEP_rating>>( &outgoing_message_rating_preview) ),
FP( "set_identity_flags" , new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>, In<identity_flags_t>>( &set_identity_flags) ),
FP( "unset_identity_flags" , new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>, In<identity_flags_t>>( &unset_identity_flags) ),
FP( "get_identity" , new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, In<c_string>, Out<pEp_identity*>>( &get_identity) ),
FP( "set_identity" , new FuncPC<PEP_STATUS, In_Pep_Session, In<const pEp_identity*>> ( &set_identity) ),
FP( "mark_as_comprimized", new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>> ( &mark_as_compromized) ),
FP( "identity_rating" , new FuncPC<PEP_STATUS, In_Pep_Session, In<pEp_identity*>, Out<PEP_rating>>( &identity_rating) ),
FP( "outgoing_message_rating", new FuncPC<PEP_STATUS, In_Pep_Session, In<message*>, Out<PEP_rating>>( &outgoing_message_rating) ),
FP( "outgoing_message_rating_preview", new FuncPC<PEP_STATUS, In_Pep_Session, In<message*>, Out<PEP_rating>>( &outgoing_message_rating_preview) ),
FP( "set_identity_flags" , new FuncPC<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>, In<identity_flags_t>>( &set_identity_flags) ),
FP( "unset_identity_flags" , new FuncPC<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>, In<identity_flags_t>>( &unset_identity_flags) ),
FP( "Low level Key Management API", new Separator),
FP( "generate_keypair", new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> ( &generate_keypair) ),
FP( "delete_keypair", new Func<PEP_STATUS, In_Pep_Session, In<c_string>> ( &delete_keypair) ),
FP( "import_key" , new Func<PEP_STATUS, In_Pep_Session, In<c_string>, In<std::size_t>, Out<identity_list*>> ( &import_key) ),
FP( "export_key" , new Func<PEP_STATUS, In_Pep_Session, In<c_string>, Out<char*>, Out<std::size_t>> ( &export_key) ),
FP( "find_keys" , new Func<PEP_STATUS, In_Pep_Session, In<c_string>, Out<stringlist_t*>> ( &find_keys) ),
FP( "get_trust" , new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> ( &get_trust) ),
FP( "own_key_is_listed", new Func<PEP_STATUS, In_Pep_Session, In<c_string>, Out<bool>> ( &own_key_is_listed) ),
FP( "own_identities_retrieve", new Func<PEP_STATUS, In_Pep_Session, Out<identity_list*>>( &own_identities_retrieve ) ),
FP( "set_own_key", new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>, In<c_string>>( &set_own_key ) ),
FP( "key_reset_identity", new Func<PEP_STATUS, In_Pep_Session, In<pEp_identity*>, In<c_string>>( &key_reset_identity) ),
FP( "generate_keypair", new FuncPC<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> ( &generate_keypair) ),
FP( "delete_keypair", new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>> ( &delete_keypair) ),
FP( "import_key" , new FuncPC<PEP_STATUS, In_Pep_Session, In<binary_string>, InLength<>, Out<identity_list*>> ( &import_key) ),
FP( "export_key" , new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, Out<char*>, Out<std::size_t>> ( &export_key) ),
FP( "find_keys" , new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, Out<stringlist_t*>> ( &find_keys) ),
FP( "get_trust" , new FuncPC<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> ( &get_trust) ),
FP( "own_key_is_listed", new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, Out<bool>> ( &own_key_is_listed) ),
FP( "own_identities_retrieve", new FuncPC<PEP_STATUS, In_Pep_Session, Out<identity_list*>>( &own_identities_retrieve ) ),
FP( "set_own_key", new FuncPC<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>, In<c_string>>( &set_own_key ) ),
FP( "key_reset_identity", new FuncPC<PEP_STATUS, In_Pep_Session, In<pEp_identity*>, In<c_string>>( &key_reset_identity) ),
FP( "key_reset_user", new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string> , In<c_string, ParamFlag::NullOkay>>( &key_reset_user) ),
FP( "key_reset_all_own_keys", new Func<PEP_STATUS, In_Pep_Session>( &key_reset_all_own_keys) ),
FP( "key_reset_all_own_keys", new FuncPC<PEP_STATUS, In_Pep_Session>( &key_reset_all_own_keys) ),
FP( "myself" , new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> ( &myself) ),
FP( "update_identity", new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> ( &update_identity) ),
FP( "myself" , new FuncPC<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> ( &myself) ),
FP( "update_identity", new FuncPC<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> ( &update_identity) ),
FP( "trust_personal_key", new Func<PEP_STATUS, In_Pep_Session, In<pEp_identity*>>( &trust_personal_key) ),
FP( "trust_own_key", new Func<PEP_STATUS, In_Pep_Session, In<pEp_identity*>>( &trust_own_key) ),
FP( "key_mistrusted", new Func<PEP_STATUS, In_Pep_Session, In<pEp_identity*>>( &key_mistrusted) ),
FP( "key_reset_trust", new Func<PEP_STATUS, In_Pep_Session, In<pEp_identity*>>( &key_reset_trust) ),
FP( "trust_personal_key", new FuncPC<PEP_STATUS, In_Pep_Session, In<pEp_identity*>>( &trust_personal_key) ),
FP( "trust_own_key", new FuncPC<PEP_STATUS, In_Pep_Session, In<pEp_identity*>>( &trust_own_key) ),
FP( "key_mistrusted", new FuncPC<PEP_STATUS, In_Pep_Session, In<pEp_identity*>>( &key_mistrusted) ),
FP( "key_reset_trust", new FuncPC<PEP_STATUS, In_Pep_Session, In<pEp_identity*>>( &key_reset_trust) ),
FP( "least_trust" , new Func<PEP_STATUS, In_Pep_Session, In<c_string>, Out<PEP_comm_type>> ( &least_trust) ),
FP( "get_key_rating", new Func<PEP_STATUS, In_Pep_Session, In<c_string>, Out<PEP_comm_type>> ( &get_key_rating) ),
FP( "renew_key" , new Func<PEP_STATUS, In_Pep_Session, In<c_string>, In<const timestamp*>> ( &renew_key) ),
FP( "revoke" , new Func<PEP_STATUS, In_Pep_Session, In<c_string>, In<c_string>> ( &revoke_key) ),
FP( "key_expired" , new Func<PEP_STATUS, In_Pep_Session, In<c_string>, In<time_t>, Out<bool>> ( &key_expired) ),
FP( "least_trust" , new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, Out<PEP_comm_type>> ( &least_trust) ),
FP( "get_key_rating", new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, Out<PEP_comm_type>> ( &get_key_rating) ),
FP( "renew_key" , new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, In<const timestamp*>> ( &renew_key) ),
FP( "revoke" , new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, In<c_string>> ( &revoke_key) ),
FP( "key_expired" , new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, In<time_t>, Out<bool>> ( &key_expired) ),
FP( "from blacklist.h & OpenPGP_compat.h", new Separator),
FP( "blacklist_add" , new Func<PEP_STATUS, In_Pep_Session, In<c_string>> ( &blacklist_add) ),
FP( "blacklist_delete", new Func<PEP_STATUS, In_Pep_Session, In<c_string>> ( &blacklist_delete) ),
FP( "blacklist_is_listed", new Func<PEP_STATUS, In_Pep_Session, In<c_string>, Out<bool>> ( &blacklist_is_listed) ),
FP( "blacklist_retrieve" , new Func<PEP_STATUS, In_Pep_Session, Out<stringlist_t*>> ( &blacklist_retrieve) ),
FP( "OpenPGP_list_keyinfo", new Func<PEP_STATUS, In_Pep_Session, In<c_string>, Out<stringpair_list_t*>> ( &OpenPGP_list_keyinfo) ),
FP( "blacklist_add" , new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>> ( &blacklist_add) ),
FP( "blacklist_delete", new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>> ( &blacklist_delete) ),
FP( "blacklist_is_listed", new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, Out<bool>> ( &blacklist_is_listed) ),
FP( "blacklist_retrieve" , new FuncPC<PEP_STATUS, In_Pep_Session, Out<stringlist_t*>> ( &blacklist_retrieve) ),
FP( "OpenPGP_list_keyinfo", new FuncPC<PEP_STATUS, In_Pep_Session, In<c_string>, Out<stringpair_list_t*>> ( &OpenPGP_list_keyinfo) ),
FP( "Event Listener & Results", new Separator ),
FP( "deliverHandshakeResult" , new Func<PEP_STATUS, In_Pep_Session, In<sync_handshake_result>, In<const identity_list*> > (&deliverHandshakeResult) ),
@ -156,8 +165,8 @@ const FunctionMap functions = {
FP( "close_session" , new Func<void, In<JsonAdapter*,ParamFlag::NoInput>, In<std::string>> (&JsonAdapter::close_session) ),
FP( "Sync", new Separator ),
FP( "leave_device_group" , new Func<PEP_STATUS, In_Pep_Session> (&leave_device_group) ),
FP( "enable_identity_for_sync" , new Func<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> (&enable_identity_for_sync)),
FP( "leave_device_group" , new FuncPC<PEP_STATUS, In_Pep_Session> (&leave_device_group) ),
FP( "enable_identity_for_sync" , new FuncPC<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> (&enable_identity_for_sync)),
FP( "disable_identity_for_sync", new FuncPC<PEP_STATUS, In_Pep_Session, InOut<pEp_identity*>> (&disable_identity_for_sync)),
#ifndef JSON_ADAPTER_LIBRARY

@ -116,16 +116,33 @@ public:
{
// extract the U'th element of the parameter list
const Element element(parameters[U], ctx, U);
const js::Value ret = NextHelper::call(fn, ctx, out_parameters, parameters, a2..., element );
if(Element::is_output)
{
js::Value out = element.to_json();
// std::cerr << "|$ Out #" << U << " : " << js::write(out) << "\n";
out_parameters.push_back( std::move(out) );
}else{
// std::cerr << "|$ Param #" << U << " is not for output.\n";
// std::cerr << "|$ Out #" << U << " : " << js::write(out) << "\n";
out_parameters.push_back(std::move(out));
}
else {
// std::cerr << "|$ Param #" << U << " is not for output.\n";
}
#ifdef _MSC_BUILD
if (ret.type() == js::array_type && !ret.get_array().empty()) {
try {
const js::Array ret_ = ret.get_array()[0].get_array();
#ifndef NDEBUG
std::string _ret_ = js::write(ret_);
#endif
return ret_;
}
catch (std::runtime_error&) {
return ret;
}
}
else
#endif
return ret;
}
};
@ -187,7 +204,7 @@ public:
out_params.reserve( Helper::nr_of_output_params );
js::Value ret = Helper::call(fn, context, out_params, *p_params);
std::string _ret = js::value_type_to_string(ret.type());
js::Object rs;
rs.emplace_back("outParams", std::move(out_params));
rs.emplace_back("return", std::move(ret));

@ -169,10 +169,7 @@ js::Value to_json<timestamp *>(timestamp * const& t)
return js::Value{};
}
// neither timegm() nor mktime() respect t->tm_gmtoff for their conversions. What a mess!
// But t->tm_gmtoff is non-standard, though, and doesn't exist on MS Windows. In ENGINE-735
// we switched to `timestamp` to cater for Windows and now convert to UTC in Windows' `timegm`.
const int64_t u = timegm(t);
const int64_t u = timegm_with_gmtoff(t);
return js::Value{u};
}

@ -187,8 +187,9 @@ ServerVersion JsonAdapter::version()
PEP_STATUS JsonAdapter::messageToSend(message* msg)
{
JsonAdapter& ja = getInstance();
js::Value v{to_json(msg)};
getInstance().i->makeAndDeliverRequest("messageToSend", js::Array{ std::move(v) } );
ja.i->makeAndDeliverRequest("messageToSend", js::Array{ std::move(v) } );
return PEP_STATUS_OK;
}
@ -314,7 +315,8 @@ void JsonAdapter::close_session(const std::string& session_id)
std::string JsonAdapter::create_session()
{
return create_random_token(12);
std::string rt = create_random_token(12);
return rt;
}

@ -1,6 +1,7 @@
#ifndef JSON_ADAPTER_HH
#define JSON_ADAPTER_HH
#include <thread>
#include <pEp/message.h>
#include <pEp/sync_api.h>
#include "registry.hh"
@ -36,8 +37,8 @@ public:
JsonAdapter& ignore_session_errors(bool _ig);
// if called with "false" the JSON Adpapter would no longer deliver HTML and JavaScript files, only handle JSON-RPC requests
JsonAdapter& deliver_html(bool _deliver_html);
JsonAdapter& deliver_html(bool _deliver_html);
// look for a free port to listen on and set the given configuration
void prepare_run(const std::string& address, unsigned start_port, unsigned end_port, ::messageToSend_t messageToSend);
@ -69,6 +70,8 @@ public:
unsigned request_count() const;
virtual std::thread::id get_sync_thread_id() const = 0;
// returns 'true' if 's' is the security token created by the function above.
virtual bool verify_security_token(const std::string& s) const override;

@ -8,7 +8,7 @@
namespace
{
std::atomic<unsigned long long> request_nr{0};
std::atomic<std::uint64_t> request_nr{0};
}

@ -6,6 +6,8 @@
#include <pEp/call_with_lock.hh>
#include <pEp/status_to_string.hh> // from libpEpAdapter.
#include <pEp/locked_queue.hh>
#include <pEp/Adapter.hh>
#include <pEp/callback_dispatcher.hh>
namespace pEp {
namespace mini {
@ -17,90 +19,30 @@ namespace mini {
PEP_SESSION keyserver_lookup_session = nullptr; // FIXME: what if another adapter started it already?
ThreadPtr keyserver_lookup_thread;
utility::locked_queue< Sync_event*, &free_Sync_event> sync_queue;
PEP_SESSION sync_session = nullptr;
ThreadPtr sync_thread;
int injectSyncMsg(Sync_event* msg, void* /* management */)
{
sync_queue.push_back(msg);
return 0;
}
int injectIdentity(pEp_identity* idy)
{
keyserver_lookup_queue.push_back(idy);
return 0;
}
Sync_event* retrieveNextSyncMsg(void* /*management*/, unsigned timeout)
{
Sync_event* msg = nullptr;
if(timeout)
{
const bool success = sync_queue.try_pop_front(msg, std::chrono::seconds(timeout));
if(!success)
{
// this is timeout occurrence
return new_sync_timeout_event();
}
}else{
msg = sync_queue.pop_front();
}
return msg;
}
pEp_identity* retrieveNextIdentity(void* /*userdata*/)
{
return keyserver_lookup_queue.pop_front();
}
void* syncThreadRoutine(void* arg)
{
PEP_STATUS status = pEp::call_with_lock(&init, &sync_session, &JsonAdapter::messageToSend, &injectSyncMsg);
if (status != PEP_STATUS_OK)
throw std::runtime_error("Cannot init sync_session! status: " + ::pEp::status_to_string(status));
status = register_sync_callbacks(sync_session,
(void*) -1,
&JsonAdapter::notifyHandshake,
&retrieveNextSyncMsg);
if (status != PEP_STATUS_OK)
throw std::runtime_error("Cannot register sync callbacks! status: " + ::pEp::status_to_string(status));
status = do_sync_protocol(sync_session, arg); // does the whole work
sync_queue.clear(); // remove remaining messages
<