
38 changed files with 2232 additions and 2148 deletions
@ -0,0 +1,22 @@ |
|||||
|
include Makefile.conf |
||||
|
|
||||
|
.PHONY: all build clean devenv envtest |
||||
|
|
||||
|
all: build_ext |
||||
|
|
||||
|
build_ext: |
||||
|
python3 setup.py build_ext $(BUILD_EXT_OPTS) |
||||
|
|
||||
|
clean: |
||||
|
rm -r $(BUILD_DIR) |
||||
|
|
||||
|
devenv: |
||||
|
LD_LIBRARY_PATH=$(PREFIX)/lib \
|
||||
|
DYLD_LIBRARY_PATH=$(PREFIX)/lib \
|
||||
|
PYTHONPATH=$PYTHONPATH:`pwd`/build/lib.linux-x86_64-3.7:\
|
||||
|
PYTHONPATH=$PYTHONPATH:`pwd`/build/lib.macosx-10.9-x86_64-3.8:\
|
||||
|
`pwd`/src \
|
||||
|
bash -l |
||||
|
|
||||
|
envtest: |
||||
|
python3 -c 'import pEp' |
@ -0,0 +1,15 @@ |
|||||
|
HERE:=$(dir $(lastword $(MAKEFILE_LIST))) |
||||
|
|
||||
|
# Defaults
|
||||
|
DEBUG=0 |
||||
|
PREFIX?=$(HOME) |
||||
|
BUILD_DIR = ./build |
||||
|
|
||||
|
######### Overrides #########
|
||||
|
-include $(HERE)local.conf |
||||
|
|
||||
|
ifeq ($(DEBUG),1) |
||||
|
BUILD_EXT_OPTS+=--debug |
||||
|
endif |
||||
|
|
||||
|
BUILD_EXT_OPTS += --prefix=$(PREFIX) |
@ -0,0 +1,11 @@ |
|||||
|
# This is an Example build config file (local.conf) |
||||
|
# you might not need this file, but if the defaults dont work for you |
||||
|
# You can override them here. |
||||
|
# Tweak the values to your needs and rename it to local.conf |
||||
|
|
||||
|
######### C++ Compiler ######### |
||||
|
# DEBUG=1 |
||||
|
# DEBUG=0 |
||||
|
|
||||
|
############# DIRS ############# |
||||
|
# PREFIX=$(HOME)/local |
@ -1,97 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#include "user_interface.hh" |
|
||||
#include <assert.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
Adapter::Adapter(bool unregister_this) |
|
||||
: flag_unregister(unregister_this) |
|
||||
{ |
|
||||
session(init); |
|
||||
} |
|
||||
|
|
||||
Adapter::~Adapter() |
|
||||
{ |
|
||||
session(release); |
|
||||
} |
|
||||
|
|
||||
PEP_SESSION Adapter::session(session_action action) |
|
||||
{ |
|
||||
lock_guard<mutex> lock(mtx()); |
|
||||
|
|
||||
thread_local static PEP_SESSION _session = nullptr; |
|
||||
thread_local int booked = 0; |
|
||||
PEP_STATUS status = PEP_STATUS_OK; |
|
||||
|
|
||||
switch (action) { |
|
||||
case release: |
|
||||
if (booked) |
|
||||
--booked; |
|
||||
if (!booked && _session) { |
|
||||
::release(_session); |
|
||||
_session = nullptr; |
|
||||
} |
|
||||
break; |
|
||||
|
|
||||
case none: |
|
||||
if (_session) |
|
||||
break; |
|
||||
|
|
||||
case init: |
|
||||
++booked; |
|
||||
if (!_session) |
|
||||
status = ::init(&_session, _messageToSend, _inject_sync_event); |
|
||||
break; |
|
||||
|
|
||||
default: |
|
||||
status = PEP_ILLEGAL_VALUE; |
|
||||
} |
|
||||
|
|
||||
if (status) |
|
||||
_throw_status(status); |
|
||||
|
|
||||
return _session; |
|
||||
} |
|
||||
|
|
||||
::utility::locked_queue< SYNC_EVENT > * Adapter::q = nullptr; |
|
||||
bool Adapter::flag_sync_enabled = false; |
|
||||
|
|
||||
void Adapter::shutdown_sync() |
|
||||
{ |
|
||||
if (queue_active()) |
|
||||
queue().push_front(nullptr); |
|
||||
flag_sync_enabled = false; |
|
||||
} |
|
||||
|
|
||||
PyObject *Adapter::ui_object(PyObject *value) |
|
||||
{ |
|
||||
lock_guard<mutex> lock(mtx()); |
|
||||
static PyObject *obj = nullptr; |
|
||||
if (value) |
|
||||
obj = value; |
|
||||
return obj; |
|
||||
} |
|
||||
|
|
||||
int Adapter::_inject_sync_event(SYNC_EVENT ev, void *management) |
|
||||
{ |
|
||||
if (!flag_sync_enabled) |
|
||||
return 1; |
|
||||
|
|
||||
if (is_sync_thread(adapter.session())) { |
|
||||
PEP_STATUS status = do_sync_protocol_step(adapter.session(), adapter.ui_object(), ev); |
|
||||
return status == PEP_STATUS_OK ? 0 : 1; |
|
||||
} |
|
||||
|
|
||||
try { |
|
||||
queue().push_back(ev); |
|
||||
} |
|
||||
catch (exception&) { |
|
||||
return 1; |
|
||||
} |
|
||||
return 0; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -1,59 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include "pEpmodule.hh" |
|
||||
#include "locked_queue.hh" |
|
||||
#include "user_interface.hh" |
|
||||
#include <pEp/sync_api.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
using Message = pEp::PythonAdapter::Message; |
|
||||
|
|
||||
class Adapter { |
|
||||
bool flag_unregister; |
|
||||
|
|
||||
public: |
|
||||
Adapter(bool unregister_this = false); |
|
||||
virtual ~Adapter(); |
|
||||
|
|
||||
enum session_action { |
|
||||
none = 0, |
|
||||
init, |
|
||||
release |
|
||||
}; |
|
||||
|
|
||||
PEP_SESSION session(session_action action = none); |
|
||||
static ::utility::locked_queue< SYNC_EVENT >& queue() |
|
||||
{ |
|
||||
if (!q) |
|
||||
q = new ::utility::locked_queue< SYNC_EVENT >(); |
|
||||
return *q; |
|
||||
} |
|
||||
void script_is_implementing_sync() { flag_sync_enabled = true; } |
|
||||
void shutdown_sync(); |
|
||||
bool is_sync_active() { return flag_sync_enabled; } |
|
||||
|
|
||||
protected: |
|
||||
static PyObject *ui_object(PyObject *value = nullptr); |
|
||||
static int _inject_sync_event(SYNC_EVENT ev, void *management); |
|
||||
|
|
||||
static ::utility::locked_queue< SYNC_EVENT > *q; |
|
||||
static bool flag_sync_enabled; |
|
||||
|
|
||||
bool queue_active() { return !!q; } |
|
||||
|
|
||||
private: |
|
||||
static mutex& mtx() |
|
||||
{ |
|
||||
static mutex m; |
|
||||
return m; |
|
||||
} |
|
||||
|
|
||||
friend class UserInterface_callback; |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -1,161 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#include "basic_api.hh" |
|
||||
#include <sstream> |
|
||||
#include <pEp/keymanagement.h> |
|
||||
#include <pEp/message_api.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
void update_identity(Identity& ident) |
|
||||
{ |
|
||||
if (ident.address() == "") |
|
||||
throw invalid_argument("address needed"); |
|
||||
if (ident.user_id() == PEP_OWN_USERID) |
|
||||
throw runtime_error("update_identity: '" PEP_OWN_USERID |
|
||||
"' may only be used for own identities"); |
|
||||
|
|
||||
PEP_STATUS status = update_identity(adapter.session(), ident); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
void myself(Identity& ident) |
|
||||
{ |
|
||||
if (ident.address() == "") |
|
||||
throw invalid_argument("address needed"); |
|
||||
if (ident.username() == "") |
|
||||
throw invalid_argument("username needed"); |
|
||||
|
|
||||
if (ident.user_id() == "") |
|
||||
ident.user_id(ident.address()); |
|
||||
|
|
||||
PEP_STATUS status = myself(adapter.session(), ident); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
string _trustwords(Identity me, Identity partner, string lang, bool full) |
|
||||
{ |
|
||||
if (me.fpr() == "" || partner.fpr() == "") |
|
||||
throw invalid_argument("fingerprint needed in Identities"); |
|
||||
|
|
||||
if (lang == "" && me.lang() == partner.lang()) |
|
||||
lang = me.lang(); |
|
||||
|
|
||||
char *words = NULL; |
|
||||
size_t size = 0; |
|
||||
PEP_STATUS status = get_trustwords(adapter.session(), me, partner, |
|
||||
lang.c_str(),&words, &size, full); |
|
||||
_throw_status(status); |
|
||||
return words; |
|
||||
} |
|
||||
|
|
||||
void trust_personal_key(Identity ident) |
|
||||
{ |
|
||||
if (ident.fpr() == "") |
|
||||
throw invalid_argument("fingerprint needed in Identities"); |
|
||||
if (ident.user_id() == "") |
|
||||
throw invalid_argument("user_id must be provided"); |
|
||||
|
|
||||
PEP_STATUS status = trust_personal_key(adapter.session(), ident); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
void set_identity_flags(Identity ident, identity_flags_t flags) |
|
||||
{ |
|
||||
if (ident.address() == "") |
|
||||
throw invalid_argument("address needed"); |
|
||||
if (ident.user_id() == "") |
|
||||
throw invalid_argument("user_id needed"); |
|
||||
|
|
||||
PEP_STATUS status = set_identity_flags(adapter.session(), ident, flags); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
void unset_identity_flags(Identity ident, identity_flags_t flags) |
|
||||
{ |
|
||||
if (ident.address() == "") |
|
||||
throw invalid_argument("address needed"); |
|
||||
if (ident.user_id() == "") |
|
||||
throw invalid_argument("user_id needed"); |
|
||||
|
|
||||
PEP_STATUS status = unset_identity_flags(adapter.session(), ident, flags); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
void key_reset_trust(Identity ident) |
|
||||
{ |
|
||||
if (ident.fpr() == "") |
|
||||
throw invalid_argument("fpr needed"); |
|
||||
if (ident.address() == "") |
|
||||
throw invalid_argument("address needed"); |
|
||||
if (ident.user_id() == "") |
|
||||
throw invalid_argument("user_id needed"); |
|
||||
|
|
||||
PEP_STATUS status = key_reset_trust(adapter.session(), ident); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
boost::python::list import_key(string key_data) |
|
||||
{ |
|
||||
::identity_list *private_keys = NULL; |
|
||||
PEP_STATUS status = ::import_key(adapter.session(), key_data.c_str(), key_data.size(), &private_keys); |
|
||||
if (status && status != PEP_KEY_IMPORTED) |
|
||||
_throw_status(status); |
|
||||
|
|
||||
auto result = boost::python::list(); |
|
||||
for (::identity_list *il = private_keys; il && il->ident; il=il->next) { |
|
||||
::pEp_identity *ident = ::identity_dup(il->ident); |
|
||||
if (!ident) { |
|
||||
free_identity_list(private_keys); |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
result.append(Identity(ident)); |
|
||||
} |
|
||||
|
|
||||
free_identity_list(private_keys); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
string export_key(Identity ident) |
|
||||
{ |
|
||||
PEP_STATUS status = PEP_STATUS_OK; |
|
||||
char* key_data = NULL; |
|
||||
size_t size; |
|
||||
status = ::export_key(adapter.session(), ident.fpr().c_str(), &key_data, &size); |
|
||||
|
|
||||
_throw_status(status); |
|
||||
return key_data; |
|
||||
} |
|
||||
|
|
||||
string export_secret_key(Identity ident) |
|
||||
{ |
|
||||
PEP_STATUS status = PEP_STATUS_OK; |
|
||||
char* key_data = NULL; |
|
||||
size_t size; |
|
||||
status = ::export_secret_key(adapter.session(), ident.fpr().c_str(), &key_data, &size); |
|
||||
|
|
||||
_throw_status(status); |
|
||||
return key_data; |
|
||||
} |
|
||||
|
|
||||
void set_own_key(Identity& ident, string fpr) |
|
||||
{ |
|
||||
if (ident.address() == "") |
|
||||
throw invalid_argument("address needed"); |
|
||||
if (ident.username() == "") |
|
||||
throw invalid_argument("username needed"); |
|
||||
if (ident.user_id() == "") |
|
||||
throw invalid_argument("user_id needed"); |
|
||||
if (fpr == "") |
|
||||
throw invalid_argument("fpr needed"); |
|
||||
|
|
||||
|
|
||||
const char* fpr_c = fpr.c_str(); |
|
||||
PEP_STATUS status = set_own_key(adapter.session(), ident, fpr_c); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,25 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include "pEpmodule.hh" |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
void update_identity(Identity& ident); |
|
||||
void myself(Identity& ident); |
|
||||
string _trustwords(Identity me, Identity partner, string lang, bool full); |
|
||||
void trust_personal_key(Identity ident); |
|
||||
|
|
||||
void set_identity_flags(Identity ident, identity_flags_t flags); |
|
||||
void unset_identity_flags(Identity ident, identity_flags_t flags); |
|
||||
|
|
||||
void key_reset_trust(Identity ident); |
|
||||
|
|
||||
boost::python::list import_key(string key_data); |
|
||||
string export_key(Identity ident); |
|
||||
string export_secret_key(Identity ident); |
|
||||
void set_own_key(Identity& ident, string fpr); |
|
||||
} |
|
||||
} |
|
@ -1,278 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#include "identity.hh" |
|
||||
#include "pEpmodule.hh" |
|
||||
#include "basic_api.hh" |
|
||||
#include "message_api.hh" |
|
||||
#include <typeinfo> |
|
||||
#include <sstream> |
|
||||
#include <pEp/identity_list.h> |
|
||||
#include <pEp/keymanagement.h> |
|
||||
#include <pEp/key_reset.h> |
|
||||
#include <pEp/message_api.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
|
|
||||
Identity::Identity(string address, string username, string user_id, |
|
||||
string fpr, int comm_type, string lang, identity_flags_t flags) |
|
||||
: _ident(new_identity(address.c_str(), fpr.c_str(), user_id.c_str(), |
|
||||
username.c_str()), &::free_identity) |
|
||||
{ |
|
||||
if (!_ident) |
|
||||
throw bad_alloc(); |
|
||||
_ident->comm_type = (PEP_comm_type) comm_type; |
|
||||
_ident->flags = (identity_flags_t) flags; |
|
||||
this->lang(lang); |
|
||||
} |
|
||||
|
|
||||
Identity::Identity(const Identity& second) |
|
||||
: _ident(second._ident) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
Identity::Identity(pEp_identity *ident) |
|
||||
: _ident(ident, &::free_identity) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
Identity::~Identity() |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
Identity::operator pEp_identity *() |
|
||||
{ |
|
||||
return _ident.get(); |
|
||||
} |
|
||||
|
|
||||
Identity::operator const pEp_identity *() const |
|
||||
{ |
|
||||
return _ident.get(); |
|
||||
} |
|
||||
|
|
||||
string Identity::_repr() |
|
||||
{ |
|
||||
stringstream build; |
|
||||
build << "Identity("; |
|
||||
string address; |
|
||||
if (_ident->address) |
|
||||
address = string(_ident->address); |
|
||||
build << repr(address) << ", "; |
|
||||
string username; |
|
||||
if (_ident->username) |
|
||||
username = string(_ident->username); |
|
||||
build << repr(username) << ", "; |
|
||||
string user_id; |
|
||||
if (_ident->user_id) |
|
||||
user_id = string(_ident->user_id); |
|
||||
build << repr(user_id) << ", "; |
|
||||
string fpr; |
|
||||
if (_ident->fpr) |
|
||||
fpr = string(_ident->fpr); |
|
||||
build << repr(fpr) << ", "; |
|
||||
build << (int) _ident->comm_type << ", "; |
|
||||
string lang = _ident->lang; |
|
||||
build << repr(lang) << ")"; |
|
||||
return build.str(); |
|
||||
} |
|
||||
|
|
||||
string Identity::_str() |
|
||||
{ |
|
||||
if (!(_ident->address && _ident->address[0])) |
|
||||
return ""; |
|
||||
if (!(_ident->username && _ident->username[0])) |
|
||||
return _ident->address; |
|
||||
return string(_ident->username) + " <" + _ident->address + ">"; |
|
||||
} |
|
||||
|
|
||||
void Identity::username(string value) |
|
||||
{ |
|
||||
if (value.length() && value.length() < 5) |
|
||||
throw length_error("username must be at least 5 characters"); |
|
||||
|
|
||||
str_attr(_ident->username, value); |
|
||||
} |
|
||||
|
|
||||
void Identity::lang(string value) |
|
||||
{ |
|
||||
if (value == "") |
|
||||
memset(_ident->lang, 0, 3); |
|
||||
else if (value.length() != 2) |
|
||||
throw length_error("length of lang must be 2"); |
|
||||
else |
|
||||
memcpy(_ident->lang, value.c_str(), 3); |
|
||||
} |
|
||||
|
|
||||
string Identity::lang() |
|
||||
{ |
|
||||
return _ident->lang; |
|
||||
} |
|
||||
|
|
||||
int Identity::rating() |
|
||||
{ |
|
||||
if (!(_ident->address)) |
|
||||
throw invalid_argument("address must be given"); |
|
||||
|
|
||||
PEP_rating rating = PEP_rating_undefined; |
|
||||
PEP_STATUS status = ::identity_rating(adapter.session(), _ident.get(), &rating); |
|
||||
_throw_status(status); |
|
||||
|
|
||||
return (int) rating; |
|
||||
} |
|
||||
|
|
||||
PEP_color Identity::color() |
|
||||
{ |
|
||||
return _color(rating()); |
|
||||
} |
|
||||
|
|
||||
Identity Identity::copy() |
|
||||
{ |
|
||||
pEp_identity *dup = ::identity_dup(*this); |
|
||||
if (!dup) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
return Identity(dup); |
|
||||
} |
|
||||
|
|
||||
Identity Identity::deepcopy(dict&) |
|
||||
{ |
|
||||
return copy(); |
|
||||
} |
|
||||
|
|
||||
void Identity::update() |
|
||||
{ |
|
||||
update_identity(*this); |
|
||||
} |
|
||||
|
|
||||
void Identity::key_reset(string fpr) |
|
||||
{ |
|
||||
PEP_STATUS status = ::key_reset_identity(adapter.session(), *this, |
|
||||
fpr != "" ? fpr.c_str() : nullptr); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
void Identity::key_mistrusted() |
|
||||
{ |
|
||||
PEP_STATUS status = ::key_mistrusted(adapter.session(), *this); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
bool Identity::is_pEp_user() |
|
||||
{ |
|
||||
bool result; |
|
||||
PEP_STATUS status = ::is_pEp_user(adapter.session(), *this, &result); |
|
||||
_throw_status(status); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
void Identity::enable_for_sync() |
|
||||
{ |
|
||||
PEP_STATUS status = ::enable_identity_for_sync(adapter.session(), *this); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
void Identity::disable_for_sync() |
|
||||
{ |
|
||||
PEP_STATUS status = ::disable_identity_for_sync(adapter.session(), *this); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
Myself::Myself(string address, string username, string user_id, string lang) |
|
||||
: Identity(address, username, user_id, "", 0, lang) |
|
||||
|
|
||||
{ |
|
||||
if (!(address.length() && username.length())) |
|
||||
throw invalid_argument("address and username must be set"); |
|
||||
if (lang.length() && lang.length() != 2) |
|
||||
throw length_error("lang must be an ISO 639-1 language code or empty"); |
|
||||
|
|
||||
// FIXME: should set .me
|
|
||||
// _ident->me = true;
|
|
||||
if (user_id.length()) |
|
||||
throw runtime_error("user_id feature not yet implemented for Myself"); |
|
||||
} |
|
||||
|
|
||||
void Myself::update() |
|
||||
{ |
|
||||
pEp::PythonAdapter::myself(*this); |
|
||||
} |
|
||||
|
|
||||
Identity identity_attr(pEp_identity *&ident) |
|
||||
{ |
|
||||
if (!ident) |
|
||||
throw out_of_range("no identity assigned"); |
|
||||
|
|
||||
pEp_identity *_dup = identity_dup(ident); |
|
||||
if (!_dup) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
Identity _ident(_dup); |
|
||||
return _ident; |
|
||||
} |
|
||||
|
|
||||
void identity_attr(pEp_identity *&ident, object value) |
|
||||
{ |
|
||||
Identity& _ident = extract< Identity& >(value); |
|
||||
pEp_identity *_dup = ::identity_dup(_ident); |
|
||||
if (!_dup) |
|
||||
throw bad_alloc(); |
|
||||
PEP_STATUS status = update_identity(adapter.session(), _dup); |
|
||||
_throw_status(status); |
|
||||
free_identity(ident); |
|
||||
ident = _dup; |
|
||||
} |
|
||||
|
|
||||
boost::python::list identitylist_attr(identity_list *&il) |
|
||||
{ |
|
||||
boost::python::list result; |
|
||||
|
|
||||
for (identity_list *_il = il; _il && _il->ident; _il = _il->next) { |
|
||||
pEp_identity *ident = ::identity_dup(_il->ident); |
|
||||
if (!ident) |
|
||||
throw bad_alloc(); |
|
||||
result.append(object(Identity(ident))); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
void identitylist_attr(identity_list *&il, boost::python::list value) |
|
||||
{ |
|
||||
identity_list *_il = new_identity_list(NULL); |
|
||||
if (!_il) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
identity_list *_i = _il; |
|
||||
for (int i=0; i<len(value); i++) { |
|
||||
extract< Identity& > extract_identity(value[i]); |
|
||||
if (!extract_identity.check()) { |
|
||||
free_identity_list(_il); |
|
||||
} |
|
||||
pEp_identity *_ident = extract_identity(); |
|
||||
pEp_identity *_dup = ::identity_dup(_ident); |
|
||||
if (!_dup) { |
|
||||
free_identity_list(_il); |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
PEP_STATUS status = update_identity(adapter.session(), _dup); |
|
||||
if (status != PEP_STATUS_OK) { |
|
||||
free_identity_list(_il); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
_i = identity_list_add(_i, _dup); |
|
||||
if (!_i) { |
|
||||
free_identity_list(_il); |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
free_identity_list(il); |
|
||||
il = _il; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -1,90 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <boost/python.hpp> |
|
||||
#include <pEp/pEpEngine.h> |
|
||||
#include <pEp/message_api.h> |
|
||||
#include <string> |
|
||||
#include <memory> |
|
||||
#include <cstddef> |
|
||||
#include "str_attr.hh" |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
using namespace utility; |
|
||||
using namespace std; |
|
||||
|
|
||||
// Identity is owning a pEp_identity
|
|
||||
|
|
||||
class Identity { |
|
||||
protected: |
|
||||
shared_ptr< pEp_identity > _ident; |
|
||||
|
|
||||
public: |
|
||||
Identity(string address = "", string username = "", |
|
||||
string user_id = "", string fpr = "", int comm_type = 0, |
|
||||
string lang = "", identity_flags_t flags = 0); |
|
||||
|
|
||||
Identity(const Identity& second); |
|
||||
Identity(pEp_identity *ident); |
|
||||
virtual ~Identity(); |
|
||||
operator pEp_identity *(); |
|
||||
operator const pEp_identity *() const; |
|
||||
|
|
||||
string _repr(); |
|
||||
string _str(); |
|
||||
|
|
||||
string address() { return str_attr(_ident->address); } |
|
||||
void address(string value) { str_attr(_ident->address, value); } |
|
||||
|
|
||||
string fpr() { return str_attr(_ident->fpr); } |
|
||||
void fpr(string value) { str_attr(_ident->fpr, value); } |
|
||||
|
|
||||
string user_id() { return str_attr(_ident->user_id); } |
|
||||
void user_id(string value) { str_attr(_ident->user_id, value); } |
|
||||
|
|
||||
string username() { return str_attr(_ident->username); } |
|
||||
void username(string value); |
|
||||
|
|
||||
PEP_comm_type comm_type() { return _ident->comm_type; } |
|
||||
void comm_type(PEP_comm_type value) { _ident->comm_type = value; }; |
|
||||
|
|
||||
std::string lang(); |
|
||||
void lang(std::string value); |
|
||||
|
|
||||
identity_flags_t flags() { return _ident->flags; } |
|
||||
void flags(identity_flags_t flags) { _ident->flags = flags; } |
|
||||
|
|
||||
int rating(); |
|
||||
PEP_color color(); |
|
||||
|
|
||||
Identity copy(); |
|
||||
Identity deepcopy(dict& memo); |
|
||||
|
|
||||
virtual void update(); |
|
||||
|
|
||||
void key_reset(string fpr=""); |
|
||||
void key_mistrusted(); |
|
||||
|
|
||||
bool is_pEp_user(); |
|
||||
|
|
||||
void enable_for_sync(); |
|
||||
void disable_for_sync(); |
|
||||
}; |
|
||||
|
|
||||
class Myself : public Identity { |
|
||||
public: |
|
||||
Myself(string address, string username, string user_id="", string lang=""); |
|
||||
virtual void update(); |
|
||||
}; |
|
||||
|
|
||||
Identity identity_attr(pEp_identity *&ident); |
|
||||
void identity_attr(pEp_identity *&ident, object value); |
|
||||
|
|
||||
boost::python::list identitylist_attr(identity_list *&il); |
|
||||
void identitylist_attr(identity_list *&il, boost::python::list value); |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -1,61 +0,0 @@ |
|||||
#pragma once |
|
||||
|
|
||||
#include <list> |
|
||||
#include <mutex> |
|
||||
|
|
||||
namespace utility |
|
||||
{ |
|
||||
using namespace std; |
|
||||
|
|
||||
template<class T> class locked_queue |
|
||||
{ |
|
||||
mutex _mtx; |
|
||||
list<T> _q; |
|
||||
|
|
||||
public: |
|
||||
T& back() |
|
||||
{ |
|
||||
lock_guard<mutex> lg(_mtx); |
|
||||
return _q.back(); |
|
||||
} |
|
||||
T& front() |
|
||||
{ |
|
||||
lock_guard<mutex> lg(_mtx); |
|
||||
return _q.front(); |
|
||||
} |
|
||||
T pop_back() |
|
||||
{ |
|
||||
lock_guard<mutex> lg(_mtx); |
|
||||
T r = _q.back(); |
|
||||
_q.pop_back(); |
|
||||
return r; |
|
||||
} |
|
||||
T pop_front() |
|
||||
{ |
|
||||
lock_guard<mutex> lg(_mtx); |
|
||||
T r = _q.front(); |
|
||||
_q.pop_front(); |
|
||||
return r; |
|
||||
} |
|
||||
void push_back(const T& data) |
|
||||
{ |
|
||||
lock_guard<mutex> lg(_mtx); |
|
||||
_q.push_back(data); |
|
||||
} |
|
||||
void push_front(const T& data) |
|
||||
{ |
|
||||
lock_guard<mutex> lg(_mtx); |
|
||||
_q.push_front(data); |
|
||||
} |
|
||||
size_t size() |
|
||||
{ |
|
||||
lock_guard<mutex> lg(_mtx); |
|
||||
return _q.size(); |
|
||||
} |
|
||||
bool empty() |
|
||||
{ |
|
||||
lock_guard<mutex> lg(_mtx); |
|
||||
return _q.empty(); |
|
||||
} |
|
||||
}; |
|
||||
}; |
|
@ -1,406 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#include <Python.h> |
|
||||
#include "message.hh" |
|
||||
#include "message_api.hh" |
|
||||
#include <stdlib.h> |
|
||||
#include <string.h> |
|
||||
#include <stdexcept> |
|
||||
#include <sstream> |
|
||||
#include <vector> |
|
||||
#include <pEp/mime.h> |
|
||||
#include <pEp/keymanagement.h> |
|
||||
#include <pEp/message_api.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
using namespace std; |
|
||||
|
|
||||
Message::Blob::Blob(bloblist_t *bl, bool chained) : |
|
||||
_bl(bl), part_of_chain(chained) |
|
||||
{ |
|
||||
if (!_bl) |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
|
|
||||
Message::Blob::Blob(object data, string mime_type, string filename) : |
|
||||
_bl(new_bloblist(NULL, 0, NULL, NULL)), part_of_chain(false) |
|
||||
{ |
|
||||
if (!_bl) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
Py_buffer src; |
|
||||
int result = PyObject_GetBuffer(data.ptr(), &src, PyBUF_CONTIG_RO); |
|
||||
if (result) |
|
||||
throw invalid_argument("need a contiguous buffer to read"); |
|
||||
|
|
||||
char *mem = (char *)malloc(src.len); |
|
||||
if (!mem) { |
|
||||
PyBuffer_Release(&src); |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
|
|
||||
memcpy(mem, src.buf, src.len); |
|
||||
free(_bl->value); |
|
||||
_bl->size = src.len; |
|
||||
_bl->value = mem; |
|
||||
|
|
||||
PyBuffer_Release(&src); |
|
||||
|
|
||||
this->mime_type(mime_type); |
|
||||
this->filename(filename); |
|
||||
} |
|
||||
|
|
||||
Message::Blob::Blob(const Message::Blob& second) : |
|
||||
_bl(second._bl), part_of_chain(true) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
Message::Blob::~Blob() |
|
||||
{ |
|
||||
if (!part_of_chain) { |
|
||||
free(_bl->value); |
|
||||
free(_bl); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
string Message::Blob::_repr() |
|
||||
{ |
|
||||
stringstream build; |
|
||||
build << "Blob("; |
|
||||
if (!_bl) { |
|
||||
build << "b'', '', ''"; |
|
||||
} |
|
||||
else { |
|
||||
build << "bytes(" << _bl->size << "), "; |
|
||||
string mime_type; |
|
||||
if (_bl->mime_type) |
|
||||
mime_type = string(_bl->mime_type); |
|
||||
string filename; |
|
||||
if (_bl->filename) |
|
||||
filename = string(_bl->filename); |
|
||||
build << repr(mime_type) << ", "; |
|
||||
build << repr(filename); |
|
||||
} |
|
||||
build << ")"; |
|
||||
return build.str(); |
|
||||
} |
|
||||
|
|
||||
int Message::Blob::getbuffer(PyObject *self, Py_buffer *view, int flags) { |
|
||||
bloblist_t *bl = NULL; |
|
||||
|
|
||||
try { |
|
||||
Message::Blob& blob = extract< Message::Blob& >(self); |
|
||||
bl = blob._bl; |
|
||||
} |
|
||||
catch (exception& e) { |
|
||||
PyErr_SetString(PyExc_RuntimeError, "extract not possible"); |
|
||||
view->obj = NULL; |
|
||||
return -1; |
|
||||
} |
|
||||
|
|
||||
if (!(bl && bl->value)) { |
|
||||
PyErr_SetString(PyExc_RuntimeError, "no data available"); |
|
||||
view->obj = NULL; |
|
||||
return -1; |
|
||||
} |
|
||||
|
|
||||
return PyBuffer_FillInfo(view, self, bl->value, bl->size, 0, flags); |
|
||||
} |
|
||||
|
|
||||
string Message::Blob::decode(string encoding) |
|
||||
{ |
|
||||
if (encoding == "") { |
|
||||
string _mime_type = _bl->mime_type ? _bl->mime_type : ""; |
|
||||
encoding = "ascii"; |
|
||||
|
|
||||
if (_mime_type == "application/pEp.sync") |
|
||||
encoding = "pep.sync"; |
|
||||
|
|
||||
if (_mime_type == "application/pEp.keyreset") |
|
||||
encoding = "pep.distribution"; |
|
||||
|
|
||||
} |
|
||||
object codecs = import("codecs"); |
|
||||
object _decode = codecs.attr("decode"); |
|
||||
return call< string >(_decode.ptr(), this, encoding); |
|
||||
} |
|
||||
|
|
||||
PyBufferProcs Message::Blob::bp = { getbuffer, NULL }; |
|
||||
|
|
||||
Message::Message(int dir, Identity *from) |
|
||||
: _msg(new_message((PEP_msg_direction) dir), &free_message) |
|
||||
{ |
|
||||
if (!_msg) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
if (from) { |
|
||||
_msg->from = ::identity_dup(*from); |
|
||||
if (!_msg->from) |
|
||||
throw bad_alloc(); |
|
||||
_msg->dir = (PEP_msg_direction) dir; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
Message::Message(string mimetext) |
|
||||
: _msg(NULL, &free_message) |
|
||||
{ |
|
||||
message *_cpy; |
|
||||
PEP_STATUS status = mime_decode_message(mimetext.c_str(), |
|
||||
mimetext.size(), &_cpy, NULL); |
|
||||
switch (status) { |
|
||||
case PEP_STATUS_OK: |
|
||||
if (_cpy) |
|
||||
_cpy->dir = PEP_dir_outgoing; |
|
||||
else |
|
||||
_cpy = new_message(PEP_dir_outgoing); |
|
||||
|
|
||||
if (!_cpy) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
_msg = shared_ptr< message >(_cpy); |
|
||||
break; |
|
||||
|
|
||||
case PEP_BUFFER_TOO_SMALL: |
|
||||
throw runtime_error("mime_decode_message: buffer too small"); |
|
||||
|
|
||||
case PEP_CANNOT_CREATE_TEMP_FILE: |
|
||||
throw runtime_error("mime_decode_message: cannot create temp file"); |
|
||||
|
|
||||
case PEP_OUT_OF_MEMORY: |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
default: |
|
||||
stringstream build; |
|
||||
build << "mime_decode_message: unknown error (" << (int) status << ")"; |
|
||||
throw runtime_error(build.str()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
Message::Message(const Message& second) |
|
||||
: _msg(second._msg) |
|
||||
{ |
|
||||
if (!_msg.get()) |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
|
|
||||
Message::Message(message *msg) |
|
||||
: _msg(::message_dup(msg), &free_message) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
Message::~Message() |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
Message::operator message *() |
|
||||
{ |
|
||||
return _msg.get(); |
|
||||
} |
|
||||
|
|
||||
Message::operator const message *() const |
|
||||
{ |
|
||||
return _msg.get(); |
|
||||
} |
|
||||
|
|
||||
string Message::_str() |
|
||||
{ |
|
||||
if (!(_msg->from && _msg->from->address && _msg->from->address[0])) |
|
||||
throw out_of_range(".from_.address missing"); |
|
||||
|
|
||||
char *mimetext; |
|
||||
string result; |
|
||||
|
|
||||
PEP_STATUS status = mime_encode_message(*this, false, &mimetext, false); |
|
||||
switch (status) { |
|
||||
case PEP_STATUS_OK: |
|
||||
result = mimetext; |
|
||||
free(mimetext); |
|
||||
break; |
|
||||
|
|
||||
case PEP_BUFFER_TOO_SMALL: |
|
||||
throw runtime_error("mime_encode_message: buffer too small"); |
|
||||
|
|
||||
case PEP_CANNOT_CREATE_TEMP_FILE: |
|
||||
throw runtime_error("mime_encode_message: cannot create temp file"); |
|
||||
|
|
||||
case PEP_OUT_OF_MEMORY: |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
default: |
|
||||
stringstream build; |
|
||||
build << "mime_encode_message: unknown error (" << (int) status << ")"; |
|
||||
throw runtime_error(build.str()); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
string Message::_repr() |
|
||||
{ |
|
||||
stringstream build; |
|
||||
build << "Message(" << repr(_str()) << ")"; |
|
||||
return build.str(); |
|
||||
} |
|
||||
|
|
||||
boost::python::tuple Message::attachments() |
|
||||
{ |
|
||||
boost::python::list l; |
|
||||
|
|
||||
for (bloblist_t *bl = _msg->attachments; bl && bl->value; bl = |
|
||||
bl->next) { |
|
||||
l.append(Blob(bl, true)); |
|
||||
} |
|
||||
|
|
||||
return boost::python::tuple(l); |
|
||||
} |
|
||||
|
|
||||
void Message::attachments(boost::python::list value) |
|
||||
{ |
|
||||
bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL); |
|
||||
if (!bl) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
bloblist_t *_l = bl; |
|
||||
for (int i=0; i<len(value); i++) { |
|
||||
Message::Blob& blob = extract< Message::Blob& >(value[i]); |
|
||||
_l = bloblist_add(_l, blob._bl->value, blob._bl->size, |
|
||||
blob._bl->mime_type, blob._bl->filename); |
|
||||
if (!_l) { |
|
||||
for (_l = bl; _l && _l->value; ) { |
|
||||
free(_l->mime_type); |
|
||||
free(_l->filename); |
|
||||
bloblist_t *_ll = _l; |
|
||||
_l = _l->next; |
|
||||
free(_ll); |
|
||||
} |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
for (int i=0; i<len(value); i++) { |
|
||||
Message::Blob& blob = extract< Message::Blob& >(value[i]); |
|
||||
blob._bl->value = NULL; |
|
||||
blob._bl->size = 0; |
|
||||
free(blob._bl->mime_type); |
|
||||
blob._bl->mime_type = NULL; |
|
||||
free(blob._bl->filename); |
|
||||
blob._bl->filename = NULL; |
|
||||
} |
|
||||
|
|
||||
free_bloblist(_msg->attachments); |
|
||||
_msg->attachments = bl; |
|
||||
} |
|
||||
|
|
||||
Message Message::encrypt() |
|
||||
{ |
|
||||
boost::python::list extra; |
|
||||
return encrypt_message(*this, extra, PEP_enc_PGP_MIME, 0); |
|
||||
} |
|
||||
|
|
||||
Message Message::_encrypt(boost::python::list extra, int enc_format, int flags) |
|
||||
{ |
|
||||
if (!enc_format) |
|
||||
enc_format = PEP_enc_PGP_MIME; |
|
||||
return encrypt_message(*this, extra, enc_format, flags); |
|
||||
} |
|
||||
|
|
||||
boost::python::tuple Message::decrypt(int flags) { |
|
||||
return pEp::PythonAdapter::decrypt_message(*this, flags); |
|
||||
} |
|
||||
|
|
||||
PEP_rating Message::outgoing_rating() |
|
||||
{ |
|
||||
if (_msg->dir != PEP_dir_outgoing) |
|
||||
throw invalid_argument("Message.dir must be outgoing"); |
|
||||
|
|
||||
if (from().address() == "") |
|
||||
throw invalid_argument("from.address needed"); |
|
||||
if (from().username() == "") |
|
||||
throw invalid_argument("from.username needed"); |
|
||||
|
|
||||
if (len(to()) + len(cc()) == 0) |
|
||||
throw invalid_argument("either to or cc needed"); |
|
||||
|
|
||||
PEP_STATUS status = myself(adapter.session(), _msg->from); |
|
||||
_throw_status(status); |
|
||||
|
|
||||
PEP_rating rating = PEP_rating_undefined; |
|
||||
status = outgoing_message_rating(adapter.session(), *this, &rating); |
|
||||
_throw_status(status); |
|
||||
|
|
||||
return rating; |
|
||||
} |
|
||||
|
|
||||
PEP_color Message::outgoing_color() |
|
||||
{ |
|
||||
return _color(outgoing_rating()); |
|
||||
} |
|
||||
|
|
||||
Message Message::copy() |
|
||||
{ |
|
||||
message *dup = message_dup(*this); |
|
||||
if (!dup) |
|
||||
throw bad_alloc(); |
|
||||
return Message(dup); |
|
||||
} |
|
||||
|
|
||||
Message Message::deepcopy(dict&) |
|
||||
{ |
|
||||
return copy(); |
|
||||
} |
|
||||
|
|
||||
Message outgoing_message(Identity me) |
|
||||
{ |
|
||||
if (me.address().empty() || me.user_id().empty()) |
|
||||
throw runtime_error("at least address and user_id of own user needed"); |
|
||||
|
|
||||
::myself(adapter.session(), me); |
|
||||
auto m = Message(PEP_dir_outgoing, &me); |
|
||||
return m; |
|
||||
} |
|
||||
|
|
||||
static object update(Identity ident) |
|
||||
{ |
|
||||
if (ident.address().empty()) |
|
||||
throw runtime_error("at least address needed"); |
|
||||
update_identity(adapter.session(), ident); |
|
||||
return object(ident); |
|
||||
} |
|
||||
|
|
||||
static boost::python::list update(boost::python::list il) |
|
||||
{ |
|
||||
for (int i=0; i<len(il); i++) { |
|
||||
update(extract< Identity >(il[i])); |
|
||||
} |
|
||||
|
|
||||
return il; |
|
||||
} |
|
||||
|
|
||||
Message incoming_message(string mime_text) |
|
||||
{ |
|
||||
auto m = Message(mime_text); |
|
||||
m.dir(PEP_dir_incoming); |
|
||||
|
|
||||
try { |
|
||||
m.from(update(m.from())); |
|
||||
} |
|
||||
catch (out_of_range&) { } |
|
||||
|
|
||||
try { |
|
||||
m.recv_by(update(m.recv_by())); |
|
||||
} |
|
||||
catch (out_of_range&) { } |
|
||||
|
|
||||
m.to(update(m.to())); |
|
||||
m.cc(update(m.cc())); |
|
||||
m.reply_to(update(m.reply_to())); |
|
||||
|
|
||||
return m; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,145 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <boost/python.hpp> |
|
||||
#include <boost/lexical_cast.hpp> |
|
||||
#include <pEp/message.h> |
|
||||
#include <pEp/message_api.h> |
|
||||
#include <string> |
|
||||
#include "str_attr.hh" |
|
||||
#include "identity.hh" |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
using namespace std; |
|
||||
using namespace boost::python; |
|
||||
using boost::lexical_cast; |
|
||||
|
|
||||
// Message is owning a message struct
|
|
||||
|
|
||||
class Message { |
|
||||
shared_ptr< ::message > _msg; |
|
||||
|
|
||||
public: |
|
||||
// Blob is owning a bloblist_t struct - or not and just managing
|
|
||||
// one depending on part_of_chain
|
|
||||
|
|
||||
class Blob { |
|
||||
bloblist_t *_bl; |
|
||||
bool part_of_chain; |
|
||||
|
|
||||
public: |
|
||||
Blob(bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL), |
|
||||
bool chained = false); |
|
||||
Blob(object data, string mime_type = "", string filename = ""); |
|
||||
Blob(const Blob& second); |
|
||||
~Blob(); |
|
||||
|
|
||||
string _repr(); |
|
||||
|
|
||||
string mime_type() { return _bl ? str_attr(_bl->mime_type) : ""; } |
|
||||
void mime_type(string value) { str_attr(_bl->mime_type, value); } |
|
||||
|
|
||||
string filename() { return str_attr(_bl->filename); } |
|
||||
void filename(string value) { str_attr(_bl->filename, value); } |
|
||||
|
|
||||
size_t size() { return _bl->size; } |
|
||||
string decode(string encoding); |
|
||||
string decode() { return decode(""); } |
|
||||
|
|
||||
static PyBufferProcs bp; |
|
||||
|
|
||||
friend class Message; |
|
||||
|
|
||||
protected: |
|
||||
static int getbuffer(PyObject *self, Py_buffer *view, int flags); |
|
||||
}; |
|
||||
|
|
||||
Message(int dir = PEP_dir_outgoing, Identity *from = NULL); |
|
||||
Message(string mimetext); |
|
||||
Message(const Message& second); |
|
||||
Message(message *msg); |
|
||||
~Message(); |
|
||||
operator message *(); |
|
||||
operator const message *() const; |
|
||||
|
|
||||
string _str(); |
|
||||
string _repr(); |
|
||||
|
|
||||
PEP_msg_direction dir() { return _msg->dir; } |
|
||||
void dir(PEP_msg_direction value) { _msg->dir = value; } |
|
||||
|
|
||||
string id() { return str_attr(_msg->id); } |
|
||||
void id(string value) { str_attr(_msg->id, value); } |
|
||||
|
|
||||
string shortmsg() { return str_attr(_msg->shortmsg); } |
|
||||
void shortmsg(string value) { str_attr(_msg->shortmsg, value); } |
|
||||
|
|
||||
string longmsg() { return str_attr(_msg->longmsg); } |
|
||||
void longmsg(string value) { str_attr(_msg->longmsg, value); } |
|
||||
|
|
||||
string longmsg_formatted() { return str_attr(_msg->longmsg_formatted); } |
|
||||
void longmsg_formatted(string value) { str_attr(_msg->longmsg_formatted, value); } |
|
||||
|
|
||||
boost::python::tuple attachments(); |
|
||||
void attachments(boost::python::list value); |
|
||||
|
|
||||
time_t sent() { return timestamp_attr(_msg->sent); } |
|
||||
void sent(time_t value) { timestamp_attr(_msg->sent, value); } |
|
||||
|
|
||||
time_t recv() { return timestamp_attr(_msg->recv); } |
|
||||
void recv(time_t value) { timestamp_attr(_msg->recv, value); } |
|
||||
|
|
||||
Identity from() { return identity_attr(_msg->from); } |
|
||||
void from(object value) { identity_attr(_msg->from, value); } |
|
||||
|
|
||||
boost::python::list to() { return identitylist_attr(_msg->to); } |
|
||||
void to(boost::python::list value) { identitylist_attr(_msg->to, value); } |
|
||||
|
|
||||
Identity recv_by() { return identity_attr(_msg->recv_by); } |
|
||||
void recv_by(object value) { identity_attr(_msg->recv_by, value); } |
|
||||
|
|
||||
boost::python::list cc() { return identitylist_attr(_msg->cc); } |
|
||||
void cc(boost::python::list value) { identitylist_attr(_msg->cc, value); } |
|
||||
|
|
||||
boost::python::list bcc() { return identitylist_attr(_msg->bcc); } |
|
||||
void bcc(boost::python::list value) { identitylist_attr(_msg->bcc, value); } |
|
||||
|
|
||||
boost::python::list reply_to() { return identitylist_attr(_msg->reply_to); } |
|
||||
void reply_to(boost::python::list value) { identitylist_attr(_msg->reply_to, value); } |
|
||||
|
|
||||
boost::python::list in_reply_to() { return strlist_attr(_msg->in_reply_to); } |
|
||||
void in_reply_to(boost::python::list value) { strlist_attr(_msg->in_reply_to, value); } |
|
||||
|
|
||||
boost::python::list references() { return strlist_attr(_msg->references); } |
|
||||
void references(boost::python::list value) { strlist_attr(_msg->references, value); } |
|
||||
|
|
||||
boost::python::list keywords() { return strlist_attr(_msg->keywords); } |
|
||||
void keywords(boost::python::list value) { strlist_attr(_msg->keywords, value); } |
|
||||
|
|
||||
string comments() { return str_attr(_msg->comments); } |
|
||||
void comments(string value) { str_attr(_msg->comments, value); } |
|
||||
|
|
||||
dict opt_fields() { return strdict_attr(_msg->opt_fields); } |
|
||||
void opt_fields(dict value) { return strdict_attr(_msg->opt_fields, value); } |
|
||||
|
|
||||
PEP_enc_format enc_format() { return _msg->enc_format; } |
|
||||
void enc_format(PEP_enc_format value) { _msg->enc_format = value; } |
|
||||
|
|
||||
Message encrypt(); |
|
||||
Message _encrypt(boost::python::list extra, int enc_format=4, int flags=0); |
|
||||
|
|
||||
boost::python::tuple decrypt(int flags=0); |
|
||||
PEP_rating outgoing_rating(); |
|
||||
PEP_color outgoing_color(); |
|
||||
Message deepcopy(dict& memo); |
|
||||
Message copy(); |
|
||||
}; |
|
||||
|
|
||||
Message outgoing_message(Identity me); |
|
||||
Message incoming_message(string mime_text); |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -1,167 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#include "message_api.hh" |
|
||||
#include "basic_api.hh" |
|
||||
#include <pEp/pEpEngine.h> |
|
||||
#include <pEp/message_api.h> |
|
||||
#include <pEp/sync_api.h> |
|
||||
#include <pEp/sync_codec.h> |
|
||||
#include <pEp/distribution_codec.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
Message encrypt_message(Message src, boost::python::list extra, int enc_format, |
|
||||
int flags) |
|
||||
{ |
|
||||
Identity _from = src.from(); |
|
||||
if (_from.address() == "") |
|
||||
throw invalid_argument("encrypt_message: src.from_.address empty"); |
|
||||
if (_from.username() == "") |
|
||||
throw invalid_argument("encrypt_message: src.from_.username empty"); |
|
||||
|
|
||||
if (_from.user_id() == "") |
|
||||
src.from().user_id(_from.address()); |
|
||||
|
|
||||
stringlist_t *_extra = to_stringlist(extra); |
|
||||
PEP_enc_format _enc_format = (PEP_enc_format) enc_format; |
|
||||
PEP_encrypt_flags_t _flags = (PEP_encrypt_flags_t) flags; |
|
||||
message *_dst = NULL; |
|
||||
|
|
||||
message *_src = src; |
|
||||
PEP_STATUS status = encrypt_message(adapter.session(), _src, _extra, &_dst, |
|
||||
_enc_format, _flags); |
|
||||
free_stringlist(_extra); |
|
||||
_throw_status(status); |
|
||||
|
|
||||
if (!_dst || _dst == _src) |
|
||||
return Message(_src); |
|
||||
|
|
||||
return Message(_dst); |
|
||||
} |
|
||||
|
|
||||
boost::python::tuple decrypt_message(Message src, int flags) |
|
||||
{ |
|
||||
message *_dst = NULL; |
|
||||
stringlist_t *_keylist = NULL; |
|
||||
PEP_rating _rating = PEP_rating_undefined; |
|
||||
PEP_decrypt_flags_t _flags = (PEP_decrypt_flags_t) flags; |
|
||||
message *_src = src; |
|
||||
|
|
||||
PEP_STATUS status = ::decrypt_message(adapter.session(), _src, &_dst, &_keylist, |
|
||||
&_rating, &_flags); |
|
||||
_throw_status(status); |
|
||||
|
|
||||
boost::python::list keylist; |
|
||||
if (_keylist) { |
|
||||
keylist = from_stringlist(_keylist); |
|
||||
free_stringlist(_keylist); |
|
||||
} |
|
||||
|
|
||||
Message dst = _dst ? Message(_dst) : Message(src); |
|
||||
return boost::python::make_tuple(dst, keylist, _rating, _flags); |
|
||||
} |
|
||||
|
|
||||
PEP_color _color(int rating) |
|
||||
{ |
|
||||
return ::color_from_rating((PEP_rating) rating); |
|
||||
} |
|
||||
|
|
||||
boost::python::tuple sync_decode(object buffer) |
|
||||
{ |
|
||||
Py_buffer src; |
|
||||
int result = PyObject_GetBuffer(buffer.ptr(), &src, PyBUF_CONTIG_RO); |
|
||||
if (result) |
|
||||
throw invalid_argument("need a contiguous buffer to read"); |
|
||||
|
|
||||
char *dst = NULL; |
|
||||
PEP_STATUS status = PER_to_XER_Sync_msg((char *) src.buf, src.len, &dst); |
|
||||
PyBuffer_Release(&src); |
|
||||
_throw_status(status); |
|
||||
|
|
||||
string _dst(dst); |
|
||||
free(dst); |
|
||||
return boost::python::make_tuple(_dst, 0); |
|
||||
} |
|
||||
|
|
||||
static boost::python::tuple sync_encode(string text) |
|
||||
{ |
|
||||
char *data = NULL; |
|
||||
size_t size = 0; |
|
||||
PEP_STATUS status = XER_to_PER_Sync_msg(text.c_str(), &data, &size); |
|
||||
_throw_status(status); |
|
||||
|
|
||||
PyObject *ba = PyBytes_FromStringAndSize(data, size); |
|
||||
free(data); |
|
||||
if (!ba) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
return boost::python::make_tuple(object(handle<>(ba)), 0); |
|
||||
} |
|
||||
|
|
||||
boost::python::tuple Distribution_decode(object buffer) |
|
||||
{ |
|
||||
Py_buffer src; |
|
||||
int result = PyObject_GetBuffer(buffer.ptr(), &src, PyBUF_CONTIG_RO); |
|
||||
if (result) |
|
||||
throw invalid_argument("need a contiguous buffer to read"); |
|
||||
|
|
||||
char *dst = NULL; |
|
||||
PEP_STATUS status = PER_to_XER_Distribution_msg((char *) src.buf, src.len, &dst); |
|
||||
PyBuffer_Release(&src); |
|
||||
_throw_status(status); |
|
||||
|
|
||||
string _dst(dst); |
|
||||
free(dst); |
|
||||
return boost::python::make_tuple(_dst, 0); |
|
||||
} |
|
||||
|
|
||||
static boost::python::tuple Distribution_encode(string text) |
|
||||
{ |
|
||||
char *data = NULL; |
|
||||
size_t size = 0; |
|
||||
PEP_STATUS status = XER_to_PER_Distribution_msg(text.c_str(), &data, &size); |
|
||||
_throw_status(status); |
|
||||
|
|
||||
PyObject *ba = PyBytes_FromStringAndSize(data, size); |
|
||||
free(data); |
|
||||
if (!ba) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
return boost::python::make_tuple(object(handle<>(ba)), 0); |
|
||||
} |
|
||||
|
|
||||
object sync_search(string name) |
|
||||
{ |
|
||||
if (name != "pep.sync") { |
|
||||
return object(); |
|
||||
} |
|
||||
else { |
|
||||
object codecs = import("codecs"); |
|
||||
object CodecInfo = codecs.attr("CodecInfo"); |
|
||||
|
|
||||
object _sync_decode = make_function(sync_decode); |
|
||||
object _sync_encode = make_function(sync_encode); |
|
||||
|
|
||||
return call< object >(CodecInfo.ptr(), _sync_encode, _sync_decode); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
object distribution_search(string name) |
|
||||
{ |
|
||||
if (name != "pep.distribution") { |
|
||||
return object(); |
|
||||
} |
|
||||
else { |
|
||||
object codecs = import("codecs"); |
|
||||
object CodecInfo = codecs.attr("CodecInfo"); |
|
||||
|
|
||||
object _distribution_decode = make_function(Distribution_decode); |
|
||||
object _distribution_encode = make_function(Distribution_encode); |
|
||||
|
|
||||
return call< object >(CodecInfo.ptr(), _distribution_encode, _distribution_decode); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
@ -1,17 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include "pEpmodule.hh" |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
Message encrypt_message(Message src, boost::python::list extra = boost::python::list(), |
|
||||
int enc_format = 4, int flags = 0); |
|
||||
boost::python::tuple decrypt_message(Message src, int flags=0); |
|
||||
PEP_color _color(int rating); |
|
||||
object sync_search(string name); |
|
||||
object distribution_search(string name); |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,52 @@ |
|||||
|
# pEp package |
||||
|
# This file is being exectued upon 'import pEp' |
||||
|
# |
||||
|
# __all__ could be used to limit the symbols exported when using from <pkg> import * |
||||
|
|
||||
|
|
||||
|
# Import all symbols EXCEPT the ones beginning with underscore into the current namespace |
||||
|
from native_pEp import * |
||||
|
# TODO: inter-pkg ref to make sure which native_pEp in sys.path gets loaded |
||||
|
# like: pEp.native_pEp |
||||
|
# import the module |
||||
|
import native_pEp |
||||
|
|
||||
|
# Executed on module import |
||||
|
def init(): |
||||
|
print(init, "called") |
||||
|
native_pEp._init_after_main_module() |
||||
|
|
||||
|
|
||||
|
def message_to_send(msg): |
||||
|
""" |
||||
|
message_to_send(msg) |
||||
|
override pEp.message_to_send(msg) with your own implementation |
||||
|
this callback is being called when a p≡p management message needs to be sent |
||||
|
GIL CAVEAT |
||||
|
""" |
||||
|
print("message_to_send() - default callback\n") |
||||
|
print("overwrite this method") |
||||
|
|
||||
|
|
||||
|
def notify_handshake(me, partner, signal): |
||||
|
""" |
||||
|
notifyHandshake(self, me, partner) |
||||
|
me own identity |
||||
|
partner identity of communication partner |
||||
|
signal the handshake signal |
||||
|
overwrite this method with an implementation of a handshake dialog |
||||
|
GIL CAVEAT |
||||
|
""" |
||||
|
print("message_to_send() - default callback\n") |
||||
|
print("overwrite this method") |
||||
|
|
||||
|
|
||||
|
# Executed when run as script |
||||
|
def main(): |
||||
|
print("I am being run as a script") |
||||
|
|
||||
|
# MAIN |
||||
|
if __name__ == "__main__": |
||||
|
main() |
||||
|
else: |
||||
|
init() |
@ -0,0 +1,172 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
// System
|
||||
|
#include <sstream> |
||||
|
|
||||
|
// Engine
|
||||
|
#include <pEp/keymanagement.h> |
||||
|
#include <pEp/message_api.h> |
||||
|
#include <pEp/Adapter.hh> |
||||
|
|
||||
|
// local
|
||||
|
#include "basic_api.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
using namespace std; |
||||
|
|
||||
|
void update_identity(Identity& ident) |
||||
|
{ |
||||
|
if (ident.address() == "") |
||||
|
throw invalid_argument("address needed"); |
||||
|
if (ident.user_id() == PEP_OWN_USERID) |
||||
|
throw runtime_error("update_identity: '" PEP_OWN_USERID |
||||
|
"' may only be used for own identities"); |
||||
|
|
||||
|
PEP_STATUS status = update_identity(Adapter::session(), ident); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
void myself(Identity& ident) |
||||
|
{ |
||||
|
if (ident.address() == "") |
||||
|
throw invalid_argument("address needed"); |
||||
|
if (ident.username() == "") |
||||
|
throw invalid_argument("username needed"); |
||||
|
|
||||
|
if (ident.user_id() == "") |
||||
|
ident.user_id(ident.address()); |
||||
|
|
||||
|
PEP_STATUS status = myself(Adapter::session(), ident); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
string _trustwords(Identity me, Identity partner, string lang, bool full) |
||||
|
{ |
||||
|
if (me.fpr() == "" || partner.fpr() == "") |
||||
|
throw invalid_argument("fingerprint needed in Identities"); |
||||
|
|
||||
|
if (lang == "" && me.lang() == partner.lang()) |
||||
|
lang = me.lang(); |
||||
|
|
||||
|
char *words = NULL; |
||||
|
size_t size = 0; |
||||
|
PEP_STATUS status = get_trustwords(Adapter::session(), me, partner, |
||||
|
lang.c_str(),&words, &size, full); |
||||
|
_throw_status(status); |
||||
|
return words; |
||||
|
} |
||||
|
|
||||
|
void trust_personal_key(Identity ident) |
||||
|
{ |
||||
|
if (ident.fpr() == "") |
||||
|
throw invalid_argument("fingerprint needed in Identities"); |
||||
|
if (ident.user_id() == "") |
||||
|
throw invalid_argument("user_id must be provided"); |
||||
|
|
||||
|
PEP_STATUS status = trust_personal_key(Adapter::session(), ident); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
void set_identity_flags(Identity ident, identity_flags_t flags) |
||||
|
{ |
||||
|
if (ident.address() == "") |
||||
|
throw invalid_argument("address needed"); |
||||
|
if (ident.user_id() == "") |
||||
|
throw invalid_argument("user_id needed"); |
||||
|
|
||||
|
PEP_STATUS status = set_identity_flags(Adapter::session(), ident, flags); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
void unset_identity_flags(Identity ident, identity_flags_t flags) |
||||
|
{ |
||||
|
if (ident.address() == "") |
||||
|
throw invalid_argument("address needed"); |
||||
|
if (ident.user_id() == "") |
||||
|
throw invalid_argument("user_id needed"); |
||||
|
|
||||
|
PEP_STATUS status = unset_identity_flags(Adapter::session(), ident, flags); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
void key_reset_trust(Identity ident) |
||||
|
{ |
||||
|
if (ident.fpr() == "") |
||||
|
throw invalid_argument("fpr needed"); |
||||
|
if (ident.address() == "") |
||||
|
throw invalid_argument("address needed"); |
||||
|
if (ident.user_id() == "") |
||||
|
throw invalid_argument("user_id needed"); |
||||
|
|
||||
|
PEP_STATUS status = key_reset_trust(Adapter::session(), ident); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
boost::python::list import_key(string key_data) |
||||
|
{ |
||||
|
::identity_list *private_keys = NULL; |
||||
|
PEP_STATUS status = ::import_key(Adapter::session(), key_data.c_str(), key_data.size(), &private_keys); |
||||
|
if (status && status != PEP_KEY_IMPORTED) |
||||
|
_throw_status(status); |
||||
|
|
||||
|
auto result = boost::python::list(); |
||||
|
for (::identity_list *il = private_keys; il && il->ident; il=il->next) { |
||||
|
::pEp_identity *ident = ::identity_dup(il->ident); |
||||
|
if (!ident) { |
||||
|
free_identity_list(private_keys); |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
result.append(Identity(ident)); |
||||
|
} |
||||
|
|
||||
|
free_identity_list(private_keys); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
string export_key(Identity ident) |
||||
|
{ |
||||
|
PEP_STATUS status = PEP_STATUS_OK; |
||||
|
char* key_data = NULL; |
||||
|
size_t size; |
||||
|
status = ::export_key(Adapter::session(), ident.fpr().c_str(), &key_data, &size); |
||||
|
|
||||
|
_throw_status(status); |
||||
|
return key_data; |
||||
|
} |
||||
|
|
||||
|
string export_secret_key(Identity ident) |
||||
|
{ |
||||
|
PEP_STATUS status = PEP_STATUS_OK; |
||||
|
char* key_data = NULL; |
||||
|
size_t size; |
||||
|
status = ::export_secret_key(Adapter::session(), ident.fpr().c_str(), &key_data, &size); |
||||
|
|
||||
|
_throw_status(status); |
||||
|
return key_data; |
||||
|
} |
||||
|
|
||||
|
void set_own_key(Identity& ident, string fpr) |
||||
|
{ |
||||
|
if (ident.address() == "") |
||||
|
throw invalid_argument("address needed"); |
||||
|
if (ident.username() == "") |
||||
|
throw invalid_argument("username needed"); |
||||
|
if (ident.user_id() == "") |
||||
|
throw invalid_argument("user_id needed"); |
||||
|
if (fpr == "") |
||||
|
throw invalid_argument("fpr needed"); |
||||
|
|
||||
|
|
||||
|
const char* fpr_c = fpr.c_str(); |
||||
|
PEP_STATUS status = set_own_key(Adapter::session(), ident, fpr_c); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
} // namespace PythonAdapter
|
||||
|
} // namespace pEp {
|
||||
|
|
||||
|
|
@ -0,0 +1,30 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef BASIC_API_HH |
||||
|
#define BASIC_API_HH |
||||
|
|
||||
|
#include "pEpmodule.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
|
||||
|
void update_identity(Identity& ident); |
||||
|
void myself(Identity& ident); |
||||
|
string _trustwords(Identity me, Identity partner, string lang, bool full); |
||||
|
void trust_personal_key(Identity ident); |
||||
|
|
||||
|
void set_identity_flags(Identity ident, identity_flags_t flags); |
||||
|
void unset_identity_flags(Identity ident, identity_flags_t flags); |
||||
|
|
||||
|
void key_reset_trust(Identity ident); |
||||
|
|
||||
|
boost::python::list import_key(string key_data); |
||||
|
string export_key(Identity ident); |
||||
|
string export_secret_key(Identity ident); |
||||
|
void set_own_key(Identity& ident, string fpr); |
||||
|
|
||||
|
} /* namespace PythonAdapter */ |
||||
|
} /* namespace pEp */ |
||||
|
|
||||
|
#endif /* BASIC_API_HH */ |
@ -0,0 +1,285 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
// System
|
||||
|
#include <typeinfo> |
||||
|
#include <sstream> |
||||
|
|
||||
|
// Engine
|
||||
|
#include <pEp/identity_list.h> |
||||
|
#include <pEp/keymanagement.h> |
||||
|
#include <pEp/key_reset.h> |
||||
|
|
||||
|
// local
|
||||
|
#include "identity.hh" |
||||
|
#include "pEpmodule.hh" |
||||
|
#include "basic_api.hh" |
||||
|
#include "message_api.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
using namespace std; |
||||
|
using namespace boost::python; |
||||
|
|
||||
|
Identity::Identity(string address, string username, string user_id, |
||||
|
string fpr, int comm_type, string lang, identity_flags_t flags) |
||||
|
: _ident(new_identity(address.c_str(), fpr.c_str(), user_id.c_str(), |
||||
|
username.c_str()), &::free_identity) |
||||
|
{ |
||||
|
if (!_ident) |
||||
|
throw bad_alloc(); |
||||
|
_ident->comm_type = (PEP_comm_type) comm_type; |
||||
|
_ident->flags = (identity_flags_t) flags; |
||||
|
this->lang(lang); |
||||
|
} |
||||
|
|
||||
|
Identity::Identity(const Identity& second) |
||||
|
: _ident(second._ident) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Identity::Identity(pEp_identity *ident) |
||||
|
: _ident(ident, &::free_identity) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Identity::~Identity() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Identity::operator pEp_identity *() |
||||
|
{ |
||||
|
return _ident.get(); |
||||
|
} |
||||
|
|
||||
|
Identity::operator const pEp_identity *() const |
||||
|
{ |
||||
|
return _ident.get(); |
||||
|
} |
||||
|
|
||||
|
string Identity::_repr() |
||||
|
{ |
||||
|
stringstream build; |
||||
|
build << "Identity("; |
||||
|
string address; |
||||
|
if (_ident->address) |
||||
|
address = string(_ident->address); |
||||
|
build << repr(address) << ", "; |
||||
|
string username; |
||||
|
if (_ident->username) |
||||
|
username = string(_ident->username); |
||||
|
build << repr(username) << ", "; |
||||
|
string user_id; |
||||
|
if (_ident->user_id) |
||||
|
user_id = string(_ident->user_id); |
||||
|
build << repr(user_id) << ", "; |
||||
|
string fpr; |
||||
|
if (_ident->fpr) |
||||
|
fpr = string(_ident->fpr); |
||||
|
build << repr(fpr) << ", "; |
||||
|
build << (int) _ident->comm_type << ", "; |
||||
|
string lang = _ident->lang; |
||||
|
build << repr(lang) << ")"; |
||||
|
return build.str(); |
||||
|
} |
||||
|
|
||||
|
string Identity::_str() |
||||
|
{ |
||||
|
if (!(_ident->address && _ident->address[0])) |
||||
|
return ""; |
||||
|
if (!(_ident->username && _ident->username[0])) |
||||
|
return _ident->address; |
||||
|
return string(_ident->username) + " <" + _ident->address + ">"; |
||||
|
} |
||||
|
|
||||
|
void Identity::username(string value) |
||||
|
{ |
||||
|
if (value.length() && value.length() < 5) |
||||
|
throw length_error("username must be at least 5 characters"); |
||||
|
|
||||
|
str_attr(_ident->username, value); |
||||
|
} |
||||
|
|
||||
|
void Identity::lang(string value) |
||||
|
{ |
||||
|
if (value == "") |
||||
|
memset(_ident->lang, 0, 3); |
||||
|
else if (value.length() != 2) |
||||
|
throw length_error("length of lang must be 2"); |
||||
|
else |
||||
|
memcpy(_ident->lang, value.c_str(), 3); |
||||
|
} |
||||
|
|
||||
|
string Identity::lang() |
||||
|
{ |
||||
|
return _ident->lang; |
||||
|
} |
||||
|
|
||||
|
int Identity::rating() |
||||
|
{ |
||||
|
if (!(_ident->address)) |
||||
|
throw invalid_argument("address must be given"); |
||||
|
|
||||
|
PEP_rating rating = PEP_rating_undefined; |
||||
|
PEP_STATUS status = ::identity_rating(Adapter::session(), _ident.get(), &rating); |
||||
|
_throw_status(status); |
||||
|
|
||||
|
return (int) rating; |
||||
|
} |
||||
|
|
||||
|
PEP_color Identity::color() |
||||
|
{ |
||||
|
return _color(rating()); |
||||
|
} |
||||
|
|
||||
|
Identity Identity::copy() |
||||
|
{ |
||||
|
pEp_identity *dup = ::identity_dup(*this); |
||||
|
if (!dup) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
return Identity(dup); |
||||
|
} |
||||
|
|
||||
|
Identity Identity::deepcopy(dict&) |
||||
|
{ |
||||
|
return copy(); |
||||
|
} |
||||
|
|
||||
|
void Identity::update() |
||||
|
{ |
||||
|
update_identity(*this); |
||||
|
} |
||||
|
|
||||
|
void Identity::key_reset(string fpr) |
||||
|
{ |
||||
|
PEP_STATUS status = ::key_reset_identity(Adapter::session(), *this, |
||||
|
fpr != "" ? fpr.c_str() : nullptr); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
void Identity::key_mistrusted() |
||||
|
{ |
||||
|
PEP_STATUS status = ::key_mistrusted(Adapter::session(), *this); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
bool Identity::is_pEp_user() |
||||
|
{ |
||||
|
bool result; |
||||
|
PEP_STATUS status = ::is_pEp_user(Adapter::session(), *this, &result); |
||||
|
_throw_status(status); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
void Identity::enable_for_sync() |
||||
|
{ |
||||
|
PEP_STATUS status = ::enable_identity_for_sync(Adapter::session(), *this); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
void Identity::disable_for_sync() |
||||
|
{ |
||||
|
PEP_STATUS status = ::disable_identity_for_sync(Adapter::session(), *this); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
Myself::Myself(string address, string username, string user_id, string lang) |
||||
|
: Identity(address, username, user_id, "", 0, lang) |
||||
|
|
||||
|
{ |
||||
|
if (!(address.length() && username.length())) |
||||
|
throw invalid_argument("address and username must be set"); |
||||
|
if (lang.length() && lang.length() != 2) |
||||
|
throw length_error("lang must be an ISO 639-1 language code or empty"); |
||||
|
|
||||
|
// FIXME: should set .me
|
||||
|
// _ident->me = true;
|
||||
|
if (user_id.length()) |
||||
|
throw runtime_error("user_id feature not yet implemented for Myself"); |
||||
|
} |
||||
|
|
||||
|
void Myself::update() |
||||
|
{ |
||||
|
pEp::PythonAdapter::myself(*this); |
||||
|
} |
||||
|
|
||||
|
Identity identity_attr(pEp_identity *&ident) |
||||
|
{ |
||||
|
if (!ident) |
||||
|
throw out_of_range("no identity assigned"); |
||||
|
|
||||
|
pEp_identity *_dup = identity_dup(ident); |
||||
|
if (!_dup) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
Identity _ident(_dup); |
||||
|
return _ident; |
||||
|
} |
||||
|
|
||||
|
void identity_attr(pEp_identity *&ident, object value) |
||||
|
{ |
||||
|
Identity& _ident = extract< Identity& >(value); |
||||
|
pEp_identity *_dup = ::identity_dup(_ident); |
||||
|
if (!_dup) |
||||
|
throw bad_alloc(); |
||||
|
PEP_STATUS status = update_identity(Adapter::session(), _dup); |
||||
|
_throw_status(status); |
||||
|
free_identity(ident); |
||||
|
ident = _dup; |
||||
|
} |
||||
|
|
||||
|
boost::python::list identitylist_attr(identity_list *&il) |
||||
|
{ |
||||
|
boost::python::list result; |
||||
|
|
||||
|
for (identity_list *_il = il; _il && _il->ident; _il = _il->next) { |
||||
|
pEp_identity *ident = ::identity_dup(_il->ident); |
||||
|
if (!ident) |
||||
|
throw bad_alloc(); |
||||
|
result.append(object(Identity(ident))); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
void identitylist_attr(identity_list *&il, boost::python::list value) |
||||
|
{ |
||||
|
identity_list *_il = new_identity_list(NULL); |
||||
|
if (!_il) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
identity_list *_i = _il; |
||||
|
for (int i=0; i<len(value); i++) { |
||||
|
extract< Identity& > extract_identity(value[i]); |
||||
|
if (!extract_identity.check()) { |
||||
|
free_identity_list(_il); |
||||
|
} |
||||
|
pEp_identity *_ident = extract_identity(); |
||||
|
pEp_identity *_dup = ::identity_dup(_ident); |
||||
|
if (!_dup) { |
||||
|
free_identity_list(_il); |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
PEP_STATUS status = update_identity(Adapter::session(), _dup); |
||||
|
if (status != PEP_STATUS_OK) { |
||||
|
free_identity_list(_il); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
_i = identity_list_add(_i, _dup); |
||||
|
if (!_i) { |
||||
|
free_identity_list(_il); |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
free_identity_list(il); |
||||
|
il = _il; |
||||
|
} |
||||
|
|
||||
|
} // namespace PythonAdapter
|
||||
|
} // namespace pEp {
|
||||
|
|
@ -0,0 +1,102 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef IDENTITY_HH |
||||
|
#define IDENTITY_HH |
||||
|
|
||||
|
// System
|
||||
|
#include <boost/python.hpp> |
||||
|
#include <string> |
||||
|
#include <memory> |
||||
|
#include <cstddef> |
||||
|
|
||||
|
// Engine
|
||||
|
#include <pEp/pEpEngine.h> |
||||
|
#include <pEp/message_api.h> |
||||
|
|
||||
|
//libpEpAdapter
|
||||
|
#include "pEp/Adapter.hh" |
||||
|
|
||||
|
// local
|
||||
|
#include "str_attr.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
|
||||
|
using std::string; |
||||
|
using std::shared_ptr; |
||||
|
|
||||
|
// Identity is owning a pEp_identity
|
||||
|
|
||||
|
class Identity { |
||||
|
protected: |
||||
|
shared_ptr< pEp_identity > _ident; |
||||
|
|
||||
|
public: |
||||
|
Identity(string address = "", string username = "", |
||||
|
string user_id = "", string fpr = "", int comm_type = 0, |
||||
|
string lang = "", identity_flags_t flags = 0); |
||||
|
|
||||
|
Identity(const Identity& second); |
||||
|
Identity(pEp_identity *ident); |
||||
|
virtual ~Identity(); |
||||
|
operator pEp_identity *(); |
||||
|
operator const pEp_identity *() const; |
||||
|
|
||||
|
string _repr(); |
||||
|
string _str(); |
||||
|
|
||||
|
string address() { return str_attr(_ident->address); } |
||||
|
void address(string value) { str_attr(_ident->address, value); } |
||||
|
|
||||
|
string fpr() { return str_attr(_ident->fpr); } |
||||
|
void fpr(string value) { str_attr(_ident->fpr, value); } |
||||
|
|
||||
|
string user_id() { return str_attr(_ident->user_id); } |
||||
|
void user_id(string value) { str_attr(_ident->user_id, value); } |
||||
|
|
||||
|
string username() { return str_attr(_ident->username); } |
||||
|
void username(string value); |
||||
|
|
||||
|
PEP_comm_type comm_type() { return _ident->comm_type; } |
||||
|
void comm_type(PEP_comm_type value) { _ident->comm_type = value; }; |
||||
|
|
||||
|
std::string lang(); |
||||
|
void lang(std::string value); |
||||
|
|
||||
|
identity_flags_t flags() { return _ident->flags; } |
||||
|
void flags(identity_flags_t flags) { _ident->flags = flags; } |
||||
|
|
||||
|
int rating(); |
||||
|
PEP_color color(); |
||||
|
|
||||
|
Identity copy(); |
||||
|
Identity deepcopy(dict& memo); |
||||
|
|
||||
|
virtual void update(); |
||||
|
|
||||
|
void key_reset(string fpr=""); |
||||
|
void key_mistrusted(); |
||||
|
|
||||
|
bool is_pEp_user(); |
||||
|
|
||||
|
void enable_for_sync(); |
||||
|
void disable_for_sync(); |
||||
|
}; |
||||
|
|
||||
|
class Myself : public Identity { |
||||
|
public: |
||||
|
Myself(string address, string username, string user_id="", string lang=""); |
||||
|
virtual void update(); |
||||
|
}; |
||||
|
|
||||
|
Identity identity_attr(pEp_identity *&ident); |
||||
|
void identity_attr(pEp_identity *&ident, object value); |
||||
|
|
||||
|
boost::python::list identitylist_attr(identity_list *&il); |
||||
|
void identitylist_attr(identity_list *&il, boost::python::list value); |
||||
|
|
||||
|
} /* namespace PythonAdapter */ |
||||
|
} /* namespace pEp */ |
||||
|
|
||||
|
#endif /* IDENTITY_HH */ |
@ -0,0 +1,413 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
// System
|
||||
|
#include <cstdlib> |
||||
|
#include <cstring> |
||||
|
#include <stdexcept> |
||||
|
#include <sstream> |
||||
|
#include <vector> |
||||
|
#include <Python.h> |
||||
|
|
||||
|
// Engine
|
||||
|
#include <pEp/mime.h> |
||||
|
#include <pEp/keymanagement.h> |
||||
|
#include <pEp/message_api.h> |
||||
|
|
||||
|
// local
|
||||
|
#include "message.hh" |
||||
|
#include "message_api.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
using namespace std; |
||||
|
using namespace boost::python; |
||||
|
|
||||
|
Message::Blob::Blob(bloblist_t *bl, bool chained) : |
||||
|
_bl(bl), part_of_chain(chained) |
||||
|
{ |
||||
|
if (!_bl) |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
|
||||
|
Message::Blob::Blob(object data, string mime_type, string filename) : |
||||
|
_bl(new_bloblist(NULL, 0, NULL, NULL)), part_of_chain(false) |
||||
|
{ |
||||
|
if (!_bl) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
Py_buffer src; |
||||
|
int result = PyObject_GetBuffer(data.ptr(), &src, PyBUF_CONTIG_RO); |
||||
|
if (result) |
||||
|
throw invalid_argument("need a contiguous buffer to read"); |
||||
|
|
||||
|
char *mem = (char *)malloc(src.len); |
||||
|
if (!mem) { |
||||
|
PyBuffer_Release(&src); |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
|
||||
|
memcpy(mem, src.buf, src.len); |
||||
|
free(_bl->value); |
||||
|
_bl->size = src.len; |
||||
|
_bl->value = mem; |
||||
|
|
||||
|
PyBuffer_Release(&src); |
||||
|
|
||||
|
this->mime_type(mime_type); |
||||
|
this->filename(filename); |
||||
|
} |
||||
|
|
||||
|
Message::Blob::Blob(const Message::Blob& second) : |
||||
|
_bl(second._bl), part_of_chain(true) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Message::Blob::~Blob() |
||||
|
{ |
||||
|
if (!part_of_chain) { |
||||
|
free(_bl->value); |
||||
|
free(_bl); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
string Message::Blob::_repr() |
||||
|
{ |
||||
|
stringstream build; |
||||
|
build << "Blob("; |
||||
|
if (!_bl) { |
||||
|
build << "b'', '', ''"; |
||||
|
} |
||||
|
else { |
||||
|
build << "bytes(" << _bl->size << "), "; |
||||
|
string mime_type; |
||||
|
if (_bl->mime_type) |
||||
|
mime_type = string(_bl->mime_type); |
||||
|
string filename; |
||||
|
if (_bl->filename) |
||||
|
filename = string(_bl->filename); |
||||
|
build << repr(mime_type) << ", "; |
||||
|
build << repr(filename); |
||||
|
} |
||||
|
build << ")"; |
||||
|
return build.str(); |
||||
|
} |
||||
|
|
||||
|
int Message::Blob::getbuffer(PyObject *self, Py_buffer *view, int flags) { |
||||
|
bloblist_t *bl = NULL; |
||||
|
|
||||
|
try { |
||||
|
Message::Blob& blob = extract< Message::Blob& >(self); |
||||
|
bl = blob._bl; |
||||
|
} |
||||
|
catch (exception& e) { |
||||
|
PyErr_SetString(PyExc_RuntimeError, "extract not possible"); |
||||
|
view->obj = NULL; |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
if (!(bl && bl->value)) { |
||||
|
PyErr_SetString(PyExc_RuntimeError, "no data available"); |
||||
|
view->obj = NULL; |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
return PyBuffer_FillInfo(view, self, bl->value, bl->size, 0, flags); |
||||
|
} |
||||
|
|
||||
|
string Message::Blob::decode(string encoding) |
||||
|
{ |
||||
|
if (encoding == "") { |
||||
|
string _mime_type = _bl->mime_type ? _bl->mime_type : ""; |
||||
|
encoding = "ascii"; |
||||
|
|
||||
|
if (_mime_type == "application/pEp.sync") |
||||
|
encoding = "pep.sync"; |
||||
|
|
||||
|
if (_mime_type == "application/pEp.keyreset") |
||||
|
encoding = "pep.distribution"; |
||||
|
|
||||
|
} |
||||
|
object codecs = import("codecs"); |
||||
|
object _decode = codecs.attr("decode"); |
||||
|
return call< string >(_decode.ptr(), this, encoding); |
||||
|
} |
||||
|
|
||||
|
PyBufferProcs Message::Blob::bp = { getbuffer, NULL }; |
||||
|
|
||||
|
Message::Message(int dir, Identity *from) |
||||
|
: _msg(new_message((PEP_msg_direction) dir), &free_message) |
||||
|
{ |
||||
|
if (!_msg) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
if (from) { |
||||
|
_msg->from = ::identity_dup(*from); |
||||
|
if (!_msg->from) |
||||
|
throw bad_alloc(); |
||||
|
_msg->dir = (PEP_msg_direction) dir; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Message::Message(string mimetext) |
||||
|
: _msg(NULL, &free_message) |
||||
|
{ |
||||
|
message *_cpy; |
||||
|
PEP_STATUS status = mime_decode_message(mimetext.c_str(), |
||||
|
mimetext.size(), &_cpy, NULL); |
||||
|
switch (status) { |
||||
|
case PEP_STATUS_OK: |
||||
|
if (_cpy) |
||||
|
_cpy->dir = PEP_dir_outgoing; |
||||
|
else |
||||
|
_cpy = new_message(PEP_dir_outgoing); |
||||
|
|
||||
|
if (!_cpy) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
_msg = shared_ptr< message >(_cpy); |
||||
|
break; |
||||
|
|
||||
|
case PEP_BUFFER_TOO_SMALL: |
||||
|
throw runtime_error("mime_decode_message: buffer too small"); |
||||
|
|
||||
|
case PEP_CANNOT_CREATE_TEMP_FILE: |
||||
|
throw runtime_error("mime_decode_message: cannot create temp file"); |
||||
|
|
||||
|
case PEP_OUT_OF_MEMORY: |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
default: |
||||
|
stringstream build; |
||||
|
build << "mime_decode_message: unknown error (" << (int) status << ")"; |
||||
|
throw runtime_error(build.str()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Message::Message(const Message& second) |
||||
|
: _msg(second._msg) |
||||
|
{ |
||||
|
if (!_msg.get()) |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
|
||||
|
Message::Message(message *msg) |
||||
|
: _msg(::message_dup(msg), &free_message) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Message::~Message() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Message::operator message *() |
||||
|
{ |
||||
|
return _msg.get(); |
||||
|
} |
||||
|
|
||||
|
Message::operator const message *() const |
||||
|
{ |
||||
|
return _msg.get(); |
||||
|
} |
||||
|
|
||||
|
string Message::_str() |
||||
|
{ |
||||
|
if (!(_msg->from && _msg->from->address && _msg->from->address[0])) |
||||
|
throw out_of_range(".from_.address missing"); |
||||
|
|
||||
|
char *mimetext; |
||||
|
string result; |
||||
|
|
||||
|
PEP_STATUS status = mime_encode_message(*this, false, &mimetext, false); |
||||
|
switch (status) { |
||||
|
case PEP_STATUS_OK: |
||||
|
result = mimetext; |
||||
|
free(mimetext); |
||||
|
break; |
||||
|
|
||||
|
case PEP_BUFFER_TOO_SMALL: |
||||
|
throw runtime_error("mime_encode_message: buffer too small"); |
||||
|
|
||||
|
case PEP_CANNOT_CREATE_TEMP_FILE: |
||||
|
throw runtime_error("mime_encode_message: cannot create temp file"); |
||||
|
|
||||
|
case PEP_OUT_OF_MEMORY: |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
default: |
||||
|
stringstream build; |
||||
|
build << "mime_encode_message: unknown error (" << (int) status << ")"; |
||||
|
throw runtime_error(build.str()); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
string Message::_repr() |
||||
|
{ |
||||
|
stringstream build; |
||||
|
build << "Message(" << repr(_str()) << ")"; |
||||
|
return build.str(); |
||||
|
} |
||||
|
|
||||
|
boost::python::tuple Message::attachments() |
||||
|
{ |
||||
|
boost::python::list l; |
||||
|
|
||||
|
for (bloblist_t *bl = _msg->attachments; bl && bl->value; bl = |
||||
|
bl->next) { |
||||
|
l.append(Blob(bl, true)); |
||||
|
} |
||||
|
|
||||
|
return boost::python::tuple(l); |
||||
|
} |
||||
|
|
||||
|
void Message::attachments(boost::python::list value) |
||||
|
{ |
||||
|
bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL); |
||||
|
if (!bl) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
bloblist_t *_l = bl; |
||||
|
for (int i=0; i<len(value); i++) { |
||||
|
Message::Blob& blob = extract< Message::Blob& >(value[i]); |
||||
|
_l = bloblist_add(_l, blob._bl->value, blob._bl->size, |
||||
|
blob._bl->mime_type, blob._bl->filename); |
||||
|
if (!_l) { |
||||
|
for (_l = bl; _l && _l->value; ) { |
||||
|
free(_l->mime_type); |
||||
|
free(_l->filename); |
||||
|
bloblist_t *_ll = _l; |
||||
|
_l = _l->next; |
||||
|
free(_ll); |
||||
|
} |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (int i=0; i<len(value); i++) { |
||||
|
Message::Blob& blob = extract< Message::Blob& >(value[i]); |
||||
|
blob._bl->value = NULL; |
||||
|
blob._bl->size = 0; |
||||
|
free(blob._bl->mime_type); |
||||
|
blob._bl->mime_type = NULL; |
||||
|
free(blob._bl->filename); |
||||
|
blob._bl->filename = NULL; |
||||
|
} |
||||
|
|
||||
|
free_bloblist(_msg->attachments); |
||||
|
_msg->attachments = bl; |
||||
|
} |
||||
|
|
||||
|
Message Message::encrypt() |
||||
|
{ |
||||
|
boost::python::list extra; |
||||
|
return encrypt_message(*this, extra, PEP_enc_PGP_MIME, 0); |
||||
|
} |
||||
|
|
||||
|
Message Message::_encrypt(boost::python::list extra, int enc_format, int flags) |
||||
|
{ |
||||
|
if (!enc_format) |
||||
|
enc_format = PEP_enc_PGP_MIME; |
||||
|
return encrypt_message(*this, extra, enc_format, flags); |
||||
|
} |
||||
|
|
||||
|
boost::python::tuple Message::decrypt(int flags) { |
||||
|
return pEp::PythonAdapter::decrypt_message(*this, flags); |
||||
|
} |
||||
|
|
||||
|
PEP_rating Message::outgoing_rating() |
||||
|
{ |
||||
|
if (_msg->dir != PEP_dir_outgoing) |
||||
|
throw invalid_argument("Message.dir must be outgoing"); |
||||
|
|
||||
|
if (from().address() == "") |
||||
|
throw invalid_argument("from.address needed"); |
||||
|
if (from().username() == "") |
||||
|
throw invalid_argument("from.username needed"); |
||||
|
|
||||
|
if (len(to()) + len(cc()) == 0) |
||||
|
throw invalid_argument("either to or cc needed"); |
||||
|
|
||||
|
PEP_STATUS status = myself(Adapter::session(), _msg->from); |
||||
|
_throw_status(status); |
||||
|
|
||||
|
PEP_rating rating = PEP_rating_undefined; |
||||
|
status = outgoing_message_rating(Adapter::session(), *this, &rating); |
||||
|
_throw_status(status); |
||||
|
|
||||
|
return rating; |
||||
|
} |
||||
|
|
||||
|
PEP_color Message::outgoing_color() |
||||
|
{ |
||||
|
return _color(outgoing_rating()); |
||||
|
} |
||||
|
|
||||
|
Message Message::copy() |
||||
|
{ |
||||
|
message *dup = message_dup(*this); |
||||
|
if (!dup) |
||||
|
throw bad_alloc(); |
||||
|
return Message(dup); |
||||
|
} |
||||
|
|
||||
|
Message Message::deepcopy(dict&) |
||||
|
{ |
||||
|
return copy(); |
||||
|
} |
||||
|
|
||||
|
Message outgoing_message(Identity me) |
||||
|
{ |
||||
|
if (me.address().empty() || me.user_id().empty()) |
||||
|
throw runtime_error("at least address and user_id of own user needed"); |
||||
|
|
||||
|
::myself(Adapter::session(), me); |
||||
|
auto m = Message(PEP_dir_outgoing, &me); |
||||
|
return m; |
||||
|
} |
||||
|
|
||||
|
static object update(Identity ident) |
||||
|
{ |
||||
|
if (ident.address().empty()) |
||||
|
throw runtime_error("at least address needed"); |
||||
|
update_identity(Adapter::session(), ident); |
||||
|
return object(ident); |
||||
|
} |
||||
|
|
||||
|
static boost::python::list update(boost::python::list il) |
||||
|
{ |
||||
|
for (int i=0; i<len(il); i++) { |
||||
|
update(extract< Identity >(il[i])); |
||||
|
} |
||||
|
|
||||
|
return il; |
||||
|
} |
||||
|
|
||||
|
Message incoming_message(string mime_text) |
||||
|
{ |
||||
|
auto m = Message(mime_text); |
||||
|
m.dir(PEP_dir_incoming); |
||||
|
|
||||
|
try { |
||||
|
m.from(update(m.from())); |
||||
|
} |
||||
|
catch (out_of_range&) { } |
||||
|
|
||||
|
try { |
||||
|
m.recv_by(update(m.recv_by())); |
||||
|
} |
||||
|
catch (out_of_range&) { } |
||||
|
|
||||
|
m.to(update(m.to())); |
||||
|
m.cc(update(m.cc())); |
||||
|
m.reply_to(update(m.reply_to())); |
||||
|
|
||||
|
return m; |
||||
|
} |
||||
|
|
||||
|
} // namespace PythonAdapter
|
||||
|
} // namespace pEp {
|
@ -0,0 +1,154 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef MESSAGE_HH |
||||
|
#define MESSAGE_HH |
||||
|
|
||||
|
// System
|
||||
|
#include <string> |
||||
|
#include <boost/python.hpp> |
||||
|
#include <boost/lexical_cast.hpp> |
||||
|
|
||||
|
// Engine
|
||||
|
#include <pEp/message.h> |
||||
|
#include <pEp/message_api.h> |
||||
|
|
||||
|
// local
|
||||
|
#include "str_attr.hh" |
||||
|
#include "identity.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
using std::string; |
||||
|
using std::runtime_error; |
||||
|
using std::invalid_argument; |
||||
|
using boost::lexical_cast; |
||||
|
|
||||
|
// Message is owning a message struct
|
||||
|
|
||||
|
class Message { |
||||
|
shared_ptr< ::message > _msg; |
||||
|
|
||||
|
public: |
||||
|
// Blob is owning a bloblist_t struct - or not and just managing
|
||||
|
// one depending on part_of_chain
|
||||
|
|
||||
|
class Blob { |
||||
|
bloblist_t *_bl; |
||||
|
bool part_of_chain; |
||||
|
|
||||
|
public: |
||||
|
Blob(bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL), |
||||
|
bool chained = false); |
||||
|
Blob(object data, string mime_type = "", string filename = ""); |
||||
|
Blob(const Blob& second); |
||||
|
~Blob(); |
||||
|
|
||||
|
string _repr(); |
||||
|
|
||||
|
string mime_type() { return _bl ? str_attr(_bl->mime_type) : ""; } |
||||
|
void mime_type(string value) { str_attr(_bl->mime_type, value); } |
||||
|
|
||||
|
string filename() { return str_attr(_bl->filename); } |
||||
|
void filename(string value) { str_attr(_bl->filename, value); } |
||||
|
|
||||
|
size_t size() { return _bl->size; } |
||||
|
string decode(string encoding); |
||||
|
string decode() { return decode(""); } |
||||
|
|
||||
|
static PyBufferProcs bp; |
||||
|
|
||||
|
friend class Message; |
||||
|
|
||||
|
protected: |
||||
|
static int getbuffer(PyObject *self, Py_buffer *view, int flags); |
||||
|
}; |
||||
|
|
||||
|
Message(int dir = PEP_dir_outgoing, Identity *from = NULL); |
||||
|
Message(string mimetext); |
||||
|
Message(const Message& second); |
||||
|
Message(message *msg); |
||||
|
~Message(); |
||||
|
operator message *(); |
||||
|
operator const message *() const; |
||||
|
|
||||
|
string _str(); |
||||
|
string _repr(); |
||||
|
|
||||
|
PEP_msg_direction dir() { return _msg->dir; } |
||||
|
void dir(PEP_msg_direction value) { _msg->dir = value; } |
||||
|
|
||||
|
string id() { return str_attr(_msg->id); } |
||||
|
void id(string value) { str_attr(_msg->id, value); } |
||||
|
|
||||
|
string shortmsg() { return str_attr(_msg->shortmsg); } |
||||
|
void shortmsg(string value) { str_attr(_msg->shortmsg, value); } |
||||
|
|
||||
|
string longmsg() { return str_attr(_msg->longmsg); } |
||||
|
void longmsg(string value) { str_attr(_msg->longmsg, value); } |
||||
|
|
||||
|
string longmsg_formatted() { return str_attr(_msg->longmsg_formatted); } |
||||
|
void longmsg_formatted(string value) { str_attr(_msg->longmsg_formatted, value); } |
||||
|
|
||||
|
boost::python::tuple attachments(); |
||||
|
void attachments(boost::python::list value); |
||||
|
|
||||
|
time_t sent() { return timestamp_attr(_msg->sent); } |
||||
|
void sent(time_t value) { timestamp_attr(_msg->sent, value); } |
||||
|
|
||||
|
time_t recv() { return timestamp_attr(_msg->recv); } |
||||
|
void recv(time_t value) { timestamp_attr(_msg->recv, value); } |
||||
|
|
||||
|
Identity from() { return identity_attr(_msg->from); } |
||||
|
void from(object value) { identity_attr(_msg->from, value); } |
||||
|
|
||||
|
boost::python::list to() { return identitylist_attr(_msg->to); } |
||||
|
void to(boost::python::list value) { identitylist_attr(_msg->to, value); } |
||||
|
|
||||
|
Identity recv_by() { return identity_attr(_msg->recv_by); } |
||||
|
void recv_by(object value) { identity_attr(_msg->recv_by, value); } |
||||
|
|
||||
|
boost::python::list cc() { return identitylist_attr(_msg->cc); } |
||||
|
void cc(boost::python::list value) { identitylist_attr(_msg->cc, value); } |
||||
|
|
||||
|
boost::python::list bcc() { return identitylist_attr(_msg->bcc); } |
||||
|
void bcc(boost::python::list value) { identitylist_attr(_msg->bcc, value); } |
||||
|
|
||||
|
boost::python::list reply_to() { return identitylist_attr(_msg->reply_to); } |
||||
|
void reply_to(boost::python::list value) { identitylist_attr(_msg->reply_to, value); } |
||||
|
|
||||
|
boost::python::list in_reply_to() { return strlist_attr(_msg->in_reply_to); } |
||||
|
void in_reply_to(boost::python::list value) { strlist_attr(_msg->in_reply_to, value); } |
||||
|
|
||||
|
boost::python::list references() { return strlist_attr(_msg->references); } |
||||
|
void references(boost::python::list value) { strlist_attr(_msg->references, value); } |
||||
|
|
||||
|
boost::python::list keywords() { return strlist_attr(_msg->keywords); } |
||||
|
void keywords(boost::python::list value) { strlist_attr(_msg->keywords, value); } |
||||
|
|
||||
|
string comments() { return str_attr(_msg->comments); } |
||||
|
void comments(string value) { str_attr(_msg->comments, value); } |
||||
|
|
||||
|
dict opt_fields() { return strdict_attr(_msg->opt_fields); } |
||||
|
void opt_fields(dict value) { return strdict_attr(_msg->opt_fields, value); } |
||||
|
|
||||
|
PEP_enc_format enc_format() { return _msg->enc_format; } |
||||
|
void enc_format(PEP_enc_format value) { _msg->enc_format = value; } |
||||
|
|
||||
|
Message encrypt(); |
||||
|
Message _encrypt(boost::python::list extra, int enc_format=4, int flags=0); |
||||
|
|
||||
|
boost::python::tuple decrypt(int flags=0); |
||||
|
PEP_rating outgoing_rating(); |
||||
|
PEP_color outgoing_color(); |
||||
|
Message deepcopy(dict& memo); |
||||
|
Message copy(); |
||||
|
}; |
||||
|
|
||||
|
Message outgoing_message(Identity me); |
||||
|
Message incoming_message(string mime_text); |
||||
|
|
||||
|
} /* namespace PythonAdapter */ |
||||
|
} /* namespace pEp */ |
||||
|
|
||||
|
#endif /* MESSAGE_HH */ |
@ -0,0 +1,172 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
// Engine
|
||||
|
#include <pEp/pEpEngine.h> |
||||
|
#include <pEp/message_api.h> |
||||
|
#include <pEp/sync_api.h> |
||||
|
#include <pEp/sync_codec.h> |
||||
|
#include <pEp/distribution_codec.h> |
||||
|
|
||||
|
// local
|
||||
|
#include "message_api.hh" |
||||
|
#include "basic_api.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
using namespace std; |
||||
|
using namespace boost::python; |
||||
|
|
||||
|
Message encrypt_message(Message src, boost::python::list extra, int enc_format, int flags) |
||||
|
{ |
||||
|
Identity _from = src.from(); |
||||
|
if (_from.address() == "") |
||||
|
throw invalid_argument("encrypt_message: src.from_.address empty"); |
||||
|
if (_from.username() == "") |
||||
|
throw invalid_argument("encrypt_message: src.from_.username empty"); |
||||
|
|
||||
|
if (_from.user_id() == "") |
||||
|
src.from().user_id(_from.address()); |
||||
|
|
||||
|
stringlist_t *_extra = to_stringlist(extra); |
||||
|
PEP_enc_format _enc_format = (PEP_enc_format) enc_format; |
||||
|
PEP_encrypt_flags_t _flags = (PEP_encrypt_flags_t) flags; |
||||
|
message *_dst = NULL; |
||||
|
|
||||
|
message *_src = src; |
||||
|
PEP_STATUS status = encrypt_message(Adapter::session(), _src, _extra, &_dst, |
||||
|
_enc_format, _flags); |
||||
|
free_stringlist(_extra); |
||||
|
_throw_status(status); |
||||
|
|
||||
|
if (!_dst || _dst == _src) |
||||
|
return Message(_src); |
||||
|
|
||||
|
return Message(_dst); |
||||
|
} |
||||
|
|
||||
|
boost::python::tuple decrypt_message(Message src, int flags) |
||||
|
{ |
||||
|
message *_dst = NULL; |
||||
|
stringlist_t *_keylist = NULL; |
||||
|
PEP_rating _rating = PEP_rating_undefined; |
||||
|
PEP_decrypt_flags_t _flags = (PEP_decrypt_flags_t) flags; |
||||
|
message *_src = src; |
||||
|
|
||||
|
PEP_STATUS status = ::decrypt_message(Adapter::session(), _src, &_dst, &_keylist, |
||||
|
&_rating, &_flags); |
||||
|
_throw_status(status); |
||||
|
|
||||
|
boost::python::list keylist; |
||||
|
if (_keylist) { |
||||
|
keylist = from_stringlist(_keylist); |
||||
|
free_stringlist(_keylist); |
||||
|
} |
||||
|
|
||||
|
Message dst = _dst ? Message(_dst) : Message(src); |
||||
|
return boost::python::make_tuple(dst, keylist, _rating, _flags); |
||||
|
} |
||||
|
|
||||
|
PEP_color _color(int rating) |
||||
|
{ |
||||
|
return ::color_from_rating((PEP_rating) rating); |
||||
|
} |
||||
|
|
||||
|
boost::python::tuple sync_decode(object buffer) |
||||
|
{ |
||||
|
Py_buffer src; |
||||
|
int result = PyObject_GetBuffer(buffer.ptr(), &src, PyBUF_CONTIG_RO); |
||||
|
if (result) |
||||
|
throw invalid_argument("need a contiguous buffer to read"); |
||||
|
|
||||
|
char *dst = NULL; |
||||
|
PEP_STATUS status = PER_to_XER_Sync_msg((char *) src.buf, src.len, &dst); |
||||
|
PyBuffer_Release(&src); |
||||
|
_throw_status(status); |
||||
|
|
||||
|
string _dst(dst); |
||||
|
free(dst); |
||||
|
return boost::python::make_tuple(_dst, 0); |
||||
|
} |
||||
|
|
||||
|
static boost::python::tuple sync_encode(string text) |
||||
|
{ |
||||
|
char *data = NULL; |
||||
|
size_t size = 0; |
||||
|
PEP_STATUS status = XER_to_PER_Sync_msg(text.c_str(), &data, &size); |
||||
|
_throw_status(status); |
||||
|
|
||||
|
PyObject *ba = PyBytes_FromStringAndSize(data, size); |
||||
|
free(data); |
||||
|
if (!ba) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
return boost::python::make_tuple(object(handle<>(ba)), 0); |
||||
|
} |
||||
|
|
||||
|
boost::python::tuple Distribution_decode(object buffer) |
||||
|
{ |
||||
|
Py_buffer src; |
||||
|
int result = PyObject_GetBuffer(buffer.ptr(), &src, PyBUF_CONTIG_RO); |
||||
|
if (result) |
||||
|
throw invalid_argument("need a contiguous buffer to read"); |
||||
|
|
||||
|
char *dst = NULL; |
||||
|
PEP_STATUS status = PER_to_XER_Distribution_msg((char *) src.buf, src.len, &dst); |
||||
|
PyBuffer_Release(&src); |
||||
|
_throw_status(status); |
||||
|
|
||||
|
string _dst(dst); |
||||
|
free(dst); |
||||
|
return boost::python::make_tuple(_dst, 0); |
||||
|
} |
||||
|
|
||||
|
static boost::python::tuple Distribution_encode(string text) |
||||
|
{ |
||||
|
char *data = NULL; |
||||
|
size_t size = 0; |
||||
|
PEP_STATUS status = XER_to_PER_Distribution_msg(text.c_str(), &data, &size); |
||||
|
_throw_status(status); |
||||
|
|
||||
|
PyObject *ba = PyBytes_FromStringAndSize(data, size); |
||||
|
free(data); |
||||
|
if (!ba) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
return boost::python::make_tuple(object(handle<>(ba)), 0); |
||||
|
} |
||||
|
|
||||
|
object sync_search(string name) |
||||
|
{ |
||||
|
if (name != "pep.sync") { |
||||
|
return object(); |
||||
|
} |
||||
|
else { |
||||
|
object codecs = import("codecs"); |
||||
|
object CodecInfo = codecs.attr("CodecInfo"); |
||||
|
|
||||
|
object _sync_decode = make_function(sync_decode); |
||||
|
object _sync_encode = make_function(sync_encode); |
||||
|
|
||||
|
return call< object >(CodecInfo.ptr(), _sync_encode, _sync_decode); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
object distribution_search(string name) |
||||
|
{ |
||||
|
if (name != "pep.distribution") { |
||||
|
return object(); |
||||
|
} |
||||
|
else { |
||||
|
object codecs = import("codecs"); |
||||
|
object CodecInfo = codecs.attr("CodecInfo"); |
||||
|
|
||||
|
object _distribution_decode = make_function(Distribution_decode); |
||||
|
object _distribution_encode = make_function(Distribution_encode); |
||||
|
|
||||
|
return call< object >(CodecInfo.ptr(), _distribution_encode, _distribution_decode); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} // namespace PythonAdapter
|
||||
|
} // namespace pEp {
|
@ -0,0 +1,27 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef MESSAGE_API_HH |
||||
|
#define MESSAGE_API_HH |
||||
|
|
||||
|
#include "pEpmodule.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
|
||||
|
Message encrypt_message( |
||||
|
Message src, |
||||
|
boost::python::list extra = boost::python::list(), |
||||
|
int enc_format = 4, |
||||
|
int flags = 0 |
||||
|
); |
||||
|
|
||||
|
boost::python::tuple decrypt_message(Message src, int flags=0); |
||||
|
PEP_color _color(int rating); |
||||
|
object sync_search(string name); |
||||
|
object distribution_search(string name); |
||||
|
|
||||
|
} /* namespace PythonAdapter */ |
||||
|
} /* namespace pEp */ |
||||
|
|
||||
|
#endif /* MESSAGE_API_HH */ |
@ -0,0 +1,28 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef PEPMODULE_HH |
||||
|
#define PEPMODULE_HH |
||||
|
|
||||
|
// Engine
|
||||
|
#include <pEp/pEpEngine.h> |
||||
|
|
||||
|
// local
|
||||
|
#include "message.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
|
||||
|
extern string device_name; |
||||
|
void config_passive_mode(bool enable); |
||||
|
void config_unencrypted_subject(bool enable); |
||||
|
void key_reset_user(string user_id, string fpr); |
||||
|
void key_reset_all_own_keys(); |
||||
|
void _throw_status(PEP_STATUS status); |
||||
|
PEP_STATUS _messageToSend(::message *msg); |
||||
|
PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal); |
||||
|
|
||||
|
} /* namespace PythonAdapter */ |
||||
|
} /* namespace pEp */ |
||||
|
|
||||
|
#endif /* PEPMODULE_HH */ |
@ -0,0 +1,184 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
// System
|
||||
|
#include <cstdlib> |
||||
|
#include <boost/python.hpp> |
||||
|
#include <boost/locale.hpp> |
||||
|
|
||||
|
// local
|
||||
|
#include "str_attr.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
using namespace std; |
||||
|
using namespace boost::python; |
||||
|
using namespace boost::locale; |
||||
|
|
||||
|
object repr(object s) |
||||
|
{ |
||||
|
return s.attr("__repr__")(); |
||||
|
} |
||||
|
|
||||
|
string repr(string s) |
||||
|
{ |
||||
|
str _s = s.c_str(); |
||||
|
object _r = _s.attr("__repr__")(); |
||||
|
string r = extract< string >(_r); |
||||
|
return r; |
||||
|
} |
||||
|
|
||||
|
string str_attr(char *&str) |
||||
|
{ |
||||
|
if (!str) |
||||
|
return string(""); |
||||
|
return string(str); |
||||
|
} |
||||
|
|
||||
|
void str_attr(char *&str, string value) |
||||
|
{ |
||||
|
string normalized = normalize(value, norm_nfc); |
||||
|
free(str); |
||||
|
str = strdup(normalized.c_str()); |
||||
|
if (!str) |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
|
||||
|
time_t timestamp_attr(timestamp *&ts) |
||||
|
{ |
||||
|
if (!ts) |
||||
|
return 0; |
||||
|
|
||||
|
return timegm(ts); |
||||
|
} |
||||
|
|
||||
|
void timestamp_attr(timestamp *&ts, time_t value) |
||||
|
{ |
||||
|
free_timestamp(ts); |
||||
|
ts = new_timestamp(value); |
||||
|
} |
||||
|
|
||||
|
boost::python::list strlist_attr(stringlist_t *&sl) |
||||
|
{ |
||||
|
boost::python::list result; |
||||
|
|
||||
|
for (stringlist_t *_sl = sl; _sl && _sl->value; _sl = _sl->next) { |
||||
|
string s(_sl->value); |
||||
|
result.append(object(s)); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
void strlist_attr(stringlist_t *&sl, boost::python::list value) |
||||
|
{ |
||||
|
stringlist_t *_sl = new_stringlist(NULL); |
||||
|
if (!_sl) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
stringlist_t *_s = _sl; |
||||
|
for (int i=0; i<len(value); i++) { |
||||
|
extract< string > extract_string(value[i]); |
||||
|
if (!extract_string.check()) { |
||||
|
free_stringlist(_sl); |
||||
|
} |
||||
|
string s = extract_string(); |
||||
|
s = normalize(s, norm_nfc); |
||||
|
_s = stringlist_add(_s, s.c_str()); |
||||
|
if (!_s) { |
||||
|
free_stringlist(_sl); |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
free_stringlist(sl); |
||||
|
sl = _sl; |
||||
|
} |
||||
|
|
||||
|
dict strdict_attr(stringpair_list_t *&spl) |
||||
|
{ |
||||
|
dict result; |
||||
|
|
||||
|
for (stringpair_list_t *_spl = spl; _spl && _spl->value; _spl = |
||||
|
_spl->next) { |
||||
|
stringpair_t *p = _spl->value; |
||||
|
if (p->key && p->value) { |
||||
|
string key(p->key); |
||||
|
string value(p->value); |
||||
|
|
||||
|
result[key] = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
void strdict_attr(stringpair_list_t *&spl, dict value) |
||||
|
{ |
||||
|
stringpair_list_t *_spl = new_stringpair_list(NULL); |
||||
|
if (!_spl) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
stringpair_list_t *_s = _spl; |
||||
|
for (int i=0; i<len(value); i++) { |
||||
|
extract< string > extract_key(value.keys()[i]); |
||||
|
extract< string > extract_value(value.values()[i]); |
||||
|
|
||||
|
if (!(extract_key.check() && extract_value.check())) |
||||
|
free_stringpair_list(_spl); |
||||
|
|
||||
|
string key = extract_key(); |
||||
|
key = normalize(key, norm_nfc); |
||||
|
string _value = extract_value(); |
||||
|
_value = normalize(_value, norm_nfc); |
||||
|
stringpair_t *pair = new_stringpair(key.c_str(), _value.c_str()); |
||||
|
if (!pair) { |
||||
|
free_stringpair_list(_spl); |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
_s = stringpair_list_add(_s, pair); |
||||
|
if (!_s) { |
||||
|
free_stringpair_list(_spl); |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
free_stringpair_list(spl); |
||||
|
spl = _spl; |
||||
|
} |
||||
|
|
||||
|
stringlist_t *to_stringlist(boost::python::list l) |
||||
|
{ |
||||
|
stringlist_t *result = new_stringlist(NULL); |
||||
|
if (!result) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
stringlist_t *_s = result; |
||||
|
for (int i=0; i<len(l); i++) { |
||||
|
extract< string > extract_string(l[i]); |
||||
|
if (!extract_string.check()) |
||||
|
free_stringlist(result); |
||||
|
string s = extract_string(); |
||||
|
_s = stringlist_add(_s, s.c_str()); |
||||
|
if (!_s) { |
||||
|
free_stringlist(result); |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
boost::python::list from_stringlist(const stringlist_t *sl) |
||||
|
{ |
||||
|
boost::python::list result; |
||||
|
for (const stringlist_t *_sl = sl; _sl && _sl->value; _sl = _sl->next) { |
||||
|
string s = _sl->value; |
||||
|
result.append(s); |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
} // namespace PythonAdapter
|
||||
|
} // namespace pEp {
|
||||
|
|
@ -0,0 +1,43 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef STR_ATTR_HH |
||||
|
#define STR_ATTR_HH |
||||
|
|
||||
|
// System
|
||||
|
#include <string> |
||||
|
|
||||
|
// Engine
|
||||
|
#include <pEp/pEpEngine.h> |
||||
|
#include <pEp/timestamp.h> |
||||
|
#include <pEp/stringlist.h> |
||||
|
#include <pEp/stringpair.h> |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
using std::string; |
||||
|
using boost::python::object; |
||||
|
using boost::python::dict; |
||||
|
|
||||
|
object repr(object s); |
||||
|
string repr(string s); |
||||
|
|
||||
|
string str_attr(char *&str); |
||||
|
void str_attr(char *&str, string value); |
||||
|
|
||||
|
time_t timestamp_attr(timestamp *&ts); |
||||
|
void timestamp_attr(timestamp *&ts, time_t value); |
||||
|
|
||||
|
boost::python::list strlist_attr(stringlist_t *&sl); |
||||
|
void strlist_attr(stringlist_t *&sl, boost::python::list value); |
||||
|
|
||||
|
dict strdict_attr(stringpair_list_t *&spl); |
||||
|
void strdict_attr(stringpair_list_t *&spl, dict value); |
||||
|
|
||||
|
stringlist_t *to_stringlist(boost::python::list l); |
||||
|
boost::python::list from_stringlist(const stringlist_t *sl); |
||||
|
|
||||
|
} /* namespace PythonAdapter */ |
||||
|
} /* namespace pEp */ |
||||
|
|
||||
|
#endif /* STR_ATTR_HH */ |
@ -0,0 +1,130 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
// System
|
||||
|
#include <cassert> |
||||
|
|
||||
|
// local
|
||||
|
#include "user_interface.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
using namespace std; |
||||
|
using namespace boost::python; |
||||
|
|
||||
|
UserInterface *UserInterface::_ui = nullptr; |
||||
|
|
||||
|
UserInterface::UserInterface() |
||||
|
{ |
||||
|
if (_ui) |
||||
|
throw runtime_error("only one UserInterface thread allowed"); |
||||
|
_ui = this; |
||||
|
} |
||||
|
|
||||
|
UserInterface::~UserInterface() |
||||
|
{ |
||||
|
_ui = nullptr; |
||||
|
} |
||||
|
|
||||
|
UserInterface_callback::UserInterface_callback(PyObject *self) : |
||||
|
UserInterface(), _self(self) |
||||
|
{ |
||||
|
// adapter.ui_object(self);
|
||||
|
// PEP_STATUS status = ::register_sync_callbacks(Adapter::session(),
|
||||
|
// (void *) this, _notifyHandshake, retrieve_next_sync_event);
|
||||
|
// assert(status == PEP_STATUS_OK);
|
||||
|
// if (status)
|
||||
|
// _throw_status(status);
|
||||
|
} |
||||
|
|
||||
|
UserInterface_callback::~UserInterface_callback() |
||||
|
{ |
||||
|
// ::unregister_sync_callbacks(Adapter::session());
|
||||
|
} |
||||
|
|
||||
|
PEP_STATUS UserInterface::_notifyHandshake( |
||||
|
pEp_identity *me, pEp_identity *partner, |
||||
|
sync_handshake_signal signal |
||||
|
) |
||||
|
{ |
||||
|
if (!(me && partner)) |
||||
|
return PEP_ILLEGAL_VALUE; |
||||
|
|
||||
|
auto that = dynamic_cast< UserInterface_callback * >(_ui); |
||||
|
that->notifyHandshake(Identity(me), Identity(partner), signal); |
||||
|
|
||||
|
return PEP_STATUS_OK; |
||||
|
} |
||||
|
|
||||
|
void UserInterface::deliverHandshakeResult(int result, object identities) |
||||
|
{ |
||||
|
identity_list *shared_identities = nullptr; |
||||
|
if (identities != boost::python::api::object() && boost::python::len(identities)) { |
||||
|
shared_identities = new_identity_list(nullptr); |
||||
|
if (!shared_identities) |
||||
|
throw bad_alloc(); |
||||
|
|
||||
|
try { |
||||
|
identity_list *si = shared_identities; |
||||
|
for (int i=0; i < boost::python::len(identities); ++i) { |
||||
|
Identity ident = extract< Identity >(identities[i]); |
||||
|
si = identity_list_add(si, ident); |
||||
|
if (!si) |
||||
|
throw bad_alloc(); |
||||
|
} |
||||
|
} |
||||
|
catch (exception& ex) { |
||||
|
free_identity_list(shared_identities); |
||||
|
throw ex; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
PEP_STATUS status = ::deliverHandshakeResult(Adapter::session(), |
||||
|
(sync_handshake_result) result, shared_identities); |
||||
|
free_identity_list(shared_identities); |
||||
|
_throw_status(status); |
||||
|
} |
||||
|
|
||||
|
//PEP_rating UserInterface::get_key_rating_for_user(string user_id, string fpr)
|
||||
|
//{
|
||||
|
// PEP_rating result;
|
||||
|
// PEP_STATUS status =
|
||||
|
// ::get_key_rating_for_user(Adapter::session(),
|
||||
|
// user_id.c_str(), fpr.c_str(), &result);
|
||||
|
// _throw_status(status);
|
||||
|
// return result;
|
||||
|
//}
|
||||
|
|
||||
|
//SYNC_EVENT UserInterface::retrieve_next_sync_event(void *management, unsigned threshold)
|
||||
|
//{
|
||||
|
// time_t started = time(nullptr);
|
||||
|
// bool timeout = false;
|
||||
|
//
|
||||
|
// while (adapter.queue().empty()) {
|
||||
|
// int i = 0;
|
||||
|
// ++i;
|
||||
|
// if (i > 10) {
|
||||
|
// if (time(nullptr) > started + threshold) {
|
||||
|
// timeout = true;
|
||||
|
// break;
|
||||
|
// }
|
||||
|
// i = 0;
|
||||
|
// }
|
||||
|
// nanosleep((const struct timespec[]){{0, 100000000L}}, NULL);
|
||||
|
// }
|
||||
|
//
|
||||
|
// if (timeout)
|
||||
|
// return new_sync_timeout_event();
|
||||
|
//
|
||||
|
// return adapter.queue().pop_front();
|
||||
|
//}
|
||||
|
|
||||
|
void UserInterface_callback::notifyHandshake( |
||||
|
Identity me, Identity partner, sync_handshake_signal signal) |
||||
|
{ |
||||
|
call_method< void >(_self, "notifyHandshake", me, partner, signal); |
||||
|
} |
||||
|
|
||||
|
} // namespace PythonAdapter
|
||||
|
} // namespace pEp {
|
||||
|
|
@ -0,0 +1,60 @@ |
|||||
|
// This file is under GNU Affero General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef USER_INTERFACE_HH |
||||
|
#define USER_INTERFACE_HH |
||||
|
|
||||
|
// System
|
||||
|
#include <csetjmp> |
||||
|
|
||||
|
// Engine
|
||||
|
#include <pEp/sync_api.h> |
||||
|
#include <pEp/message_api.h> |
||||
|
|
||||
|
// local
|
||||
|
#include "pEpmodule.hh" |
||||
|
|
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PythonAdapter { |
||||
|
|
||||
|
class UserInterface { |
||||
|
static UserInterface *_ui; |
||||
|
public: |
||||
|
UserInterface(); |
||||
|
virtual ~UserInterface(); |
||||
|
|
||||
|
virtual void notifyHandshake( |
||||
|
Identity me, |
||||
|
Identity partner, |
||||
|
sync_handshake_signal signal) |
||||
|
{ |
||||
|
throw runtime_error("override this method"); |
||||
|
} |
||||
|
|
||||
|
virtual void deliverHandshakeResult(int result, object identities); |
||||
|
|
||||
|
// PEP_rating get_key_rating_for_user(string user_id, string fpr);
|
||||
|
|
||||
|
protected: |
||||
|
static PEP_STATUS _notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal); |
||||
|
}; |
||||
|
|
||||
|
class UserInterface_callback : public UserInterface { |
||||
|
PyObject *_self; |
||||
|
public: |
||||
|
UserInterface_callback(PyObject *self); |
||||
|
~UserInterface_callback(); |
||||
|
|
||||
|
void notifyHandshake( |
||||
|
Identity me, |
||||
|
Identity partner, |
||||
|
sync_handshake_signal signal |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
} /* namespace PythonAdapter */ |
||||
|
} /* namespace pEp */ |
||||
|
|
||||
|
#endif /* USER_INTERFACE_HH */ |
||||
|
|
@ -1,23 +0,0 @@ |
|||||
#pragma once |
|
||||
|
|
||||
#include <boost/python.hpp> |
|
||||
#include "identity.hh" |
|
||||
#include "message.hh" |
|
||||
#include "adapter.hh" |
|
||||
#include <pEp/pEpEngine.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
extern string device_name; |
|
||||
void config_passive_mode(bool enable); |
|
||||
void config_unencrypted_subject(bool enable); |
|
||||
void key_reset_user(string user_id, string fpr); |
|
||||
void key_reset_all_own_keys(); |
|
||||
void _throw_status(PEP_STATUS status); |
|
||||
void messageToSend(Message msg); |
|
||||
PEP_STATUS _messageToSend(::message *msg); |
|
||||
void do_sync_protocol(); |
|
||||
extern Adapter adapter; |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -1,179 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#include <boost/python.hpp> |
|
||||
#include <boost/locale.hpp> |
|
||||
#include "str_attr.hh" |
|
||||
#include <stdlib.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace utility { |
|
||||
using namespace std; |
|
||||
using namespace boost::locale; |
|
||||
|
|
||||
object repr(object s) |
|
||||
{ |
|
||||
return s.attr("__repr__")(); |
|
||||
} |
|
||||
|
|
||||
string repr(string s) |
|
||||
{ |
|
||||
str _s = s.c_str(); |
|
||||
object _r = _s.attr("__repr__")(); |
|
||||
string r = extract< string >(_r); |
|
||||
return r; |
|
||||
} |
|
||||
|
|
||||
string str_attr(char *&str) |
|
||||
{ |
|
||||
if (!str) |
|
||||
return string(""); |
|
||||
return string(str); |
|
||||
} |
|
||||
|
|
||||
void str_attr(char *&str, string value) |
|
||||
{ |
|
||||
string normalized = normalize(value, norm_nfc); |
|
||||
free(str); |
|
||||
str = strdup(normalized.c_str()); |
|
||||
if (!str) |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
|
|
||||
time_t timestamp_attr(timestamp *&ts) |
|
||||
{ |
|
||||
if (!ts) |
|
||||
return 0; |
|
||||
|
|
||||
return timegm(ts); |
|
||||
} |
|
||||
|
|
||||
void timestamp_attr(timestamp *&ts, time_t value) |
|
||||
{ |
|
||||
free_timestamp(ts); |
|
||||
ts = new_timestamp(value); |
|
||||
} |
|
||||
|
|
||||
boost::python::list strlist_attr(stringlist_t *&sl) |
|
||||
{ |
|
||||
boost::python::list result; |
|
||||
|
|
||||
for (stringlist_t *_sl = sl; _sl && _sl->value; _sl = _sl->next) { |
|
||||
string s(_sl->value); |
|
||||
result.append(object(s)); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
void strlist_attr(stringlist_t *&sl, boost::python::list value) |
|
||||
{ |
|
||||
stringlist_t *_sl = new_stringlist(NULL); |
|
||||
if (!_sl) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
stringlist_t *_s = _sl; |
|
||||
for (int i=0; i<len(value); i++) { |
|
||||
extract< string > extract_string(value[i]); |
|
||||
if (!extract_string.check()) { |
|
||||
free_stringlist(_sl); |
|
||||
} |
|
||||
string s = extract_string(); |
|
||||
s = normalize(s, norm_nfc); |
|
||||
_s = stringlist_add(_s, s.c_str()); |
|
||||
if (!_s) { |
|
||||
free_stringlist(_sl); |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
free_stringlist(sl); |
|
||||
sl = _sl; |
|
||||
} |
|
||||
|
|
||||
dict strdict_attr(stringpair_list_t *&spl) |
|
||||
{ |
|
||||
dict result; |
|
||||
|
|
||||
for (stringpair_list_t *_spl = spl; _spl && _spl->value; _spl = |
|
||||
_spl->next) { |
|
||||
stringpair_t *p = _spl->value; |
|
||||
if (p->key && p->value) { |
|
||||
string key(p->key); |
|
||||
string value(p->value); |
|
||||
|
|
||||
result[key] = value; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
void strdict_attr(stringpair_list_t *&spl, dict value) |
|
||||
{ |
|
||||
stringpair_list_t *_spl = new_stringpair_list(NULL); |
|
||||
if (!_spl) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
stringpair_list_t *_s = _spl; |
|
||||
for (int i=0; i<len(value); i++) { |
|
||||
extract< string > extract_key(value.keys()[i]); |
|
||||
extract< string > extract_value(value.values()[i]); |
|
||||
|
|
||||
if (!(extract_key.check() && extract_value.check())) |
|
||||
free_stringpair_list(_spl); |
|
||||
|
|
||||
string key = extract_key(); |
|
||||
key = normalize(key, norm_nfc); |
|
||||
string _value = extract_value(); |
|
||||
_value = normalize(_value, norm_nfc); |
|
||||
stringpair_t *pair = new_stringpair(key.c_str(), _value.c_str()); |
|
||||
if (!pair) { |
|
||||
free_stringpair_list(_spl); |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
_s = stringpair_list_add(_s, pair); |
|
||||
if (!_s) { |
|
||||
free_stringpair_list(_spl); |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
free_stringpair_list(spl); |
|
||||
spl = _spl; |
|
||||
} |
|
||||
|
|
||||
stringlist_t *to_stringlist(boost::python::list l) |
|
||||
{ |
|
||||
stringlist_t *result = new_stringlist(NULL); |
|
||||
if (!result) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
stringlist_t *_s = result; |
|
||||
for (int i=0; i<len(l); i++) { |
|
||||
extract< string > extract_string(l[i]); |
|
||||
if (!extract_string.check()) |
|
||||
free_stringlist(result); |
|
||||
string s = extract_string(); |
|
||||
_s = stringlist_add(_s, s.c_str()); |
|
||||
if (!_s) { |
|
||||
free_stringlist(result); |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
boost::python::list from_stringlist(const stringlist_t *sl) |
|
||||
{ |
|
||||
boost::python::list result; |
|
||||
for (const stringlist_t *_sl = sl; _sl && _sl->value; _sl = _sl->next) { |
|
||||
string s = _sl->value; |
|
||||
result.append(s); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -1,36 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <string> |
|
||||
#include <pEp/pEpEngine.h> |
|
||||
#include <pEp/timestamp.h> |
|
||||
#include <pEp/stringlist.h> |
|
||||
#include <pEp/stringpair.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace utility { |
|
||||
using namespace std; |
|
||||
using namespace boost::python; |
|
||||
|
|
||||
object repr(object s); |
|
||||
string repr(string s); |
|
||||
|
|
||||
string str_attr(char *&str); |
|
||||
void str_attr(char *&str, string value); |
|
||||
|
|
||||
time_t timestamp_attr(timestamp *&ts); |
|
||||
void timestamp_attr(timestamp *&ts, time_t value); |
|
||||
|
|
||||
boost::python::list strlist_attr(stringlist_t *&sl); |
|
||||
void strlist_attr(stringlist_t *&sl, boost::python::list value); |
|
||||
|
|
||||
dict strdict_attr(stringpair_list_t *&spl); |
|
||||
void strdict_attr(stringpair_list_t *&spl, dict value); |
|
||||
|
|
||||
stringlist_t *to_stringlist(boost::python::list l); |
|
||||
boost::python::list from_stringlist(const stringlist_t *sl); |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -1,125 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#include "user_interface.hh" |
|
||||
#include <assert.h> |
|
||||
#include <time.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
UserInterface *UserInterface::_ui = nullptr; |
|
||||
|
|
||||
UserInterface::UserInterface() |
|
||||
{ |
|
||||
if (_ui) |
|
||||
throw runtime_error("only one UserInterface thread allowed"); |
|
||||
_ui = this; |
|
||||
} |
|
||||
|
|
||||
UserInterface::~UserInterface() |
|
||||
{ |
|
||||
_ui = nullptr; |
|
||||
} |
|
||||
|
|
||||
UserInterface_callback::UserInterface_callback(PyObject *self) : |
|
||||
UserInterface(), _self(self) |
|
||||
{ |
|
||||
adapter.ui_object(self); |
|
||||
PEP_STATUS status = ::register_sync_callbacks(adapter.session(), |
|
||||
(void *) this, _notifyHandshake, retrieve_next_sync_event); |
|
||||
assert(status == PEP_STATUS_OK); |
|
||||
if (status) |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
UserInterface_callback::~UserInterface_callback() |
|
||||
{ |
|
||||
::unregister_sync_callbacks(adapter.session()); |
|
||||
} |
|
||||
|
|
||||
PEP_STATUS UserInterface::_notifyHandshake( |
|
||||
pEp_identity *me, pEp_identity *partner, |
|
||||
sync_handshake_signal signal |
|
||||
) |
|
||||
{ |
|
||||
if (!(me && partner)) |
|
||||
return PEP_ILLEGAL_VALUE; |
|
||||
|
|
||||
auto that = dynamic_cast< UserInterface_callback * >(_ui); |
|
||||
that->notifyHandshake(Identity(me), Identity(partner), signal); |
|
||||
|
|
||||
return PEP_STATUS_OK; |
|
||||
} |
|
||||
|
|
||||
void UserInterface::deliverHandshakeResult(int result, object identities) |
|
||||
{ |
|
||||
identity_list *shared_identities = nullptr; |
|
||||
if (identities != boost::python::api::object() && |
|
||||
boost::python::len(identities)) { |
|
||||
shared_identities = new_identity_list(nullptr); |
|
||||
if (!shared_identities) |
|
||||
throw bad_alloc(); |
|
||||
|
|
||||
try { |
|
||||
identity_list *si = shared_identities; |
|
||||
for (int i=0; i < boost::python::len(identities); ++i) { |
|
||||
Identity ident = extract< Identity >(identities[i]); |
|
||||
si = identity_list_add(si, ident); |
|
||||
if (!si) |
|
||||
throw bad_alloc(); |
|
||||
} |
|
||||
} |
|
||||
catch (exception& ex) { |
|
||||
free_identity_list(shared_identities); |
|
||||
throw ex; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
PEP_STATUS status = ::deliverHandshakeResult(adapter.session(), |
|
||||
(sync_handshake_result) result, shared_identities); |
|
||||
free_identity_list(shared_identities); |
|
||||
_throw_status(status); |
|
||||
} |
|
||||
|
|
||||
PEP_rating UserInterface::get_key_rating_for_user(string user_id, string fpr) |
|
||||
{ |
|
||||
PEP_rating result; |
|
||||
PEP_STATUS status = |
|
||||
::get_key_rating_for_user(adapter.session(), |
|
||||
user_id.c_str(), fpr.c_str(), &result); |
|
||||
_throw_status(status); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
SYNC_EVENT UserInterface::retrieve_next_sync_event(void *management, unsigned threshold) |
|
||||
{ |
|
||||
time_t started = time(nullptr); |
|
||||
bool timeout = false; |
|
||||
|
|
||||
while (adapter.queue().empty()) { |
|
||||
int i = 0; |
|
||||
++i; |
|
||||
if (i > 10) { |
|
||||
if (time(nullptr) > started + threshold) { |
|
||||
timeout = true; |
|
||||
break; |
|
||||
} |
|
||||
i = 0; |
|
||||
} |
|
||||
nanosleep((const struct timespec[]){{0, 100000000L}}, NULL); |
|
||||
} |
|
||||
|
|
||||
if (timeout) |
|
||||
return new_sync_timeout_event(); |
|
||||
|
|
||||
return adapter.queue().pop_front(); |
|
||||
} |
|
||||
|
|
||||
void UserInterface_callback::notifyHandshake( |
|
||||
Identity me, Identity partner, sync_handshake_signal signal) |
|
||||
{ |
|
||||
call_method< void >(_self, "notifyHandshake", me, partner, signal); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -1,50 +0,0 @@ |
|||||
// This file is under GNU Affero General Public License 3.0
|
|
||||
// see LICENSE.txt
|
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include "pEpmodule.hh" |
|
||||
#include <setjmp.h> |
|
||||
#include <pEp/sync_api.h> |
|
||||
#include <pEp/message_api.h> |
|
||||
|
|
||||
namespace pEp { |
|
||||
namespace PythonAdapter { |
|
||||
class UserInterface { |
|
||||
static UserInterface *_ui; |
|
||||
public: |
|
||||
UserInterface(); |
|
||||
virtual ~UserInterface(); |
|
||||
|
|
||||
virtual void notifyHandshake( |
|
||||
pEp::PythonAdapter::Identity me, |
|
||||
pEp::PythonAdapter::Identity partner, |
|
||||
sync_handshake_signal signal) |
|
||||
{ |
|
||||
throw runtime_error("override this method"); |
|
||||
} |
|
||||
|
|
||||
virtual void deliverHandshakeResult(int result, object identities); |
|
||||
|
|
||||
PEP_rating get_key_rating_for_user(string user_id, string fpr); |
|
||||
|
|
||||
protected: |
|
||||
static PEP_STATUS _notifyHandshake(pEp_identity *me, |
|
||||
pEp_identity *partner, sync_handshake_signal signal); |
|
||||
static SYNC_EVENT retrieve_next_sync_event(void *management, unsigned threshold); |
|
||||
}; |
|
||||
|
|
||||
class UserInterface_callback : public UserInterface { |
|
||||
PyObject *_self; |
|
||||
public: |
|
||||
UserInterface_callback(PyObject *self); |
|
||||
~UserInterface_callback(); |
|
||||
|
|
||||
void notifyHandshake( |
|
||||
pEp::PythonAdapter::Identity me, |
|
||||
pEp::PythonAdapter::Identity partner, |
|
||||
sync_handshake_signal signal); |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
|
|
@ -0,0 +1,47 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
import pEp |
||||
|
import time |
||||
|
|
||||
|
def message_to_send(msg): |
||||
|
print("User defined message_to_send() called") |
||||
|
m, keys, rating, flags = msg.decrypt() |
||||
|
try: |
||||
|
print(m.attachments[0].decode()) |
||||
|
except UnicodeDecodeError as e: |
||||
|
print("decode failed") |
||||
|
|
||||
|
def notify_handshake(me, partner, signal): |
||||
|
print("User defined notify_handshake() called") |
||||
|
print(me) |
||||
|
print(partner) |
||||
|
print(signal) |
||||
|
|
||||
|
def start_stop_sync(duration): |
||||
|
pEp.start_sync() |
||||
|
time.sleep(duration) |
||||
|
pEp.shutdown_sync() |
||||
|
|
||||
|
|
||||
|
alice = pEp.Identity("test@alice.com", "alice", "23") |
||||
|
pEp.myself(alice) |
||||
|
print(alice.fpr) |
||||
|
|
||||
|
dir(pEp) |
||||
|
|
||||
|
# test default callback |
||||
|
start_stop_sync(1) |
||||
|
|
||||
|
# test user defined callback |
||||
|
pEp.message_to_send = message_to_send |
||||
|
# pEp.notify_handshake = notify_handshake |
||||
|
|
||||
|
start_stop_sync(1) |
||||
|
|
||||
|
# pEp.start_sync() |
||||
|
# while(True): |
||||
|
# print("is_sync_active: {}".format(pEp.is_sync_active())) |
||||
|
# time.sleep(3) |
||||
|
# pEp.key_reset_all_own_keys() |
||||
|
# time.sleep(3) |
Loading…
Reference in new issue