diff --git a/src/Identity.cc b/src/Identity.cc index fb1250f..708f765 100644 --- a/src/Identity.cc +++ b/src/Identity.cc @@ -1,5 +1,6 @@ #include "Identity.hh" #include +#include namespace pEp { namespace PythonAdapter { @@ -48,13 +49,6 @@ namespace pEp { return ident; } - Identity::operator pEp_identity *() - { - if (!_ident) - throw bad_cast(); - return _ident; - } - void Identity::lang(string value) { if (value == "") @@ -69,6 +63,78 @@ namespace pEp { { return _ident->lang; } + + object identity_attr(pEp_identity *&ident) + { + pEp_identity *_dup; + + if (!ident) + _dup = new_identity(NULL, NULL, NULL, NULL); + else + _dup = identity_dup(ident); + if (!_dup) + throw bad_alloc(); + + Identity *_ident = new Identity(_dup); + return object(_ident); + } + + void identity_attr(pEp_identity *&ident, object value) + { + extract< string > extract_string(value); + if (extract_string.check()) { + string str = extract_string(); + pEp_identity *_ident = new_identity(str.c_str(), NULL, NULL, + NULL); + if (!_ident) + throw bad_alloc(); + free_identity(ident); + ident = _ident; + return; + } + + Identity& _ident = extract< Identity& >(value); + free_identity(ident); + ident = _ident.detach(); + } + + list identitylist_attr(identity_list *&il) + { + 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, list value) + { + identity_list *_il = new_identity_list(NULL); + if (!_il) + throw bad_alloc(); + + identity_list *_i = _il; + for (int i=0; i extract_identity(value[i]); + if (!extract_identity.check()) { + free_identity_list(_il); + } + pEp_identity *_ident = extract_identity().detach(); + _i = identity_list_add(_i, _ident); + if (!_i) { + free_identity_list(_il); + throw bad_alloc(); + } + } + + free_identity_list(il); + il = _il; + } } } diff --git a/src/Identity.hh b/src/Identity.hh index 4ad786d..5e08fc9 100644 --- a/src/Identity.hh +++ b/src/Identity.hh @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include "str_attr.hh" @@ -18,7 +19,6 @@ namespace pEp { Identity(const Identity& second); Identity(pEp_identity *ident); ~Identity(); - operator pEp_identity *(); void attach(pEp_identity *ident); pEp_identity *detach(); @@ -46,6 +46,12 @@ namespace pEp { identity_flags_t flags() { return _ident->flags; } void flags(identity_flags_t flags) { _ident->flags = flags; } }; + + object identity_attr(pEp_identity *&ident); + void identity_attr(pEp_identity *&ident, object value); + + list identitylist_attr(identity_list *&il); + void identitylist_attr(identity_list *&il, list value); } } diff --git a/src/message.cc b/src/message.cc index e6b27c6..7623702 100644 --- a/src/message.cc +++ b/src/message.cc @@ -8,13 +8,14 @@ namespace pEp { namespace PythonAdapter { using namespace std; - Message::Blob::Blob(bloblist_t *bl) : _bl(bl), part_of_chain(false) + Message::Blob::Blob(bloblist_t *bl, bool chained) : + _bl(bl), part_of_chain(chained) { if (!_bl) throw bad_alloc(); } - Message::Blob::Blob(object data) : + Message::Blob::Blob(object data, string mime_type, string filename) : _bl(new_bloblist(NULL, 0, NULL, NULL)), part_of_chain(false) { if (!_bl) @@ -37,6 +38,9 @@ namespace pEp { _bl->value = mem; PyBuffer_Release(&src); + + this->mime_type(mime_type); + this->filename(filename); } Message::Blob::Blob(const Message::Blob& second) : @@ -127,6 +131,55 @@ namespace pEp { throw bad_cast(); return _msg; } + + tuple Message::attachments() + { + list l; + + for (bloblist_t *bl = _msg->attachments; bl && bl->value; bl = + bl->next) { + l.append(Blob(bl, true)); + } + + return tuple(l); + } + + void Message::attachments(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(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(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; + } } } diff --git a/src/message.hh b/src/message.hh index 5ed0107..62183bd 100644 --- a/src/message.hh +++ b/src/message.hh @@ -3,9 +3,7 @@ #include #include #include -#include -#include -#include +#include "Identity.hh" #include "str_attr.hh" namespace pEp { @@ -19,15 +17,17 @@ namespace pEp { message *_msg; public: - // Blob is owning a bloblist_t struct + // 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)); - Blob(object data); + 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(); @@ -41,6 +41,8 @@ namespace pEp { static PyBufferProcs bp; + friend class Message; + protected: static int getbuffer(PyObject *self, Py_buffer *view, int flags); }; @@ -68,18 +70,33 @@ namespace pEp { string longmsg_formatted() { return str_attr(_msg->longmsg_formatted); } void longmsg_formatted(string value) { str_attr(_msg->longmsg_formatted, value); } - bloblist_t *attachments; - char *rawmsg_ref; - size_t rawmsg_size; - timestamp *sent; - timestamp *recv; - pEp_identity *from; - identity_list *to; - pEp_identity *recv_by; - - identity_list *cc; - identity_list *bcc; - identity_list *reply_to; + tuple attachments(); + void attachments(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); } + + object from() { return identity_attr(_msg->from); } + void from(object value) { identity_attr(_msg->from, value); } + + list to() { return identitylist_attr(_msg->to); } + void to(list value) { identitylist_attr(_msg->to, value); } + + object recv_by() { return identity_attr(_msg->recv_by); } + void recv_by(object value) { identity_attr(_msg->recv_by, value); } + + list cc() { return identitylist_attr(_msg->cc); } + void cc(list value) { identitylist_attr(_msg->cc, value); } + + list bcc() { return identitylist_attr(_msg->bcc); } + void bcc(list value) { identitylist_attr(_msg->bcc, value); } + + list reply_to() { return identitylist_attr(_msg->reply_to); } + void reply_to(list value) { identitylist_attr(_msg->reply_to, value); } + stringlist_t *in_reply_to; struct _message *refering_msg_ref; diff --git a/src/pEpmodule.cc b/src/pEpmodule.cc index 4d28030..0fd9ab2 100644 --- a/src/pEpmodule.cc +++ b/src/pEpmodule.cc @@ -9,7 +9,7 @@ namespace pEp { namespace PythonAdapter { using namespace std; - string about() + static string about() { string version = string(version_string) + "\np≡p version " + PEP_VERSION + "\n"; @@ -29,21 +29,21 @@ BOOST_PYTHON_MODULE(pEp) generator gen; std::locale::global(gen("")); - def("about", about, "delivers the p≡p about string"); + scope().attr("about") = about(); - class_("Identity", "p≡p identity") + auto identity_class = class_("Identity", "p≡p identity") .add_property("address", (string(Identity::*)()) &Identity::address, (void(Identity::*)(string)) &Identity::address, "email address or URI") .add_property("fpr", (string(Identity::*)()) &Identity::fpr, (void(Identity::*)(string)) &Identity::fpr, - "key ID (fingerprint)") + "key ID (full fingerprint, hex encoded)") .add_property("user_id", (string(Identity::*)()) &Identity::user_id, (void(Identity::*)(string)) &Identity::user_id, - "ID of person associated") + "ID of person associated or 'pEp_own_userId' if own identity") .add_property("username", (string(Identity::*)()) &Identity::username, (void(Identity::*)(string)) &Identity::username, - "name of person associated") + "name in full of person associated") .add_property("comm_type", (int(Identity::*)()) (PEP_comm_type(Identity::*)()) &Identity::comm_type, (void(Identity::*)(int)) @@ -56,10 +56,14 @@ BOOST_PYTHON_MODULE(pEp) (void(Identity::*)(bool)) &Identity::me, "true if own identity, false otherwise") .add_property("flags", (identity_flags_t(Identity::*)()) &Identity::flags, - (void(Identity::*)(identity_flags_t)) &Identity::flags); + (void(Identity::*)(identity_flags_t)) &Identity::flags, + "flags (p≡p internal)"); + + identity_class.attr("PEP_OWN_USERID") = "pEp_own_userId"; - auto blob = class_("Blob", "Binary large object", - init< object >(args("data"), "init buffer with binary data") ) + auto blob_class = class_("Blob", "Binary large object", + init< object, char const*, char const* >(args("data", "mime_type", "filename"), + "init buffer with binary data") ) .add_property("mime_type", (string(Message::Blob::*)()) &Message::Blob::mime_type, (void(Message::Blob::*)(string)) &Message::Blob::mime_type, "MIME type of object in Blob") @@ -68,6 +72,52 @@ BOOST_PYTHON_MODULE(pEp) "filename of object in Blob") .add_property("size", &Message::Blob::size, "size of Blob in bytes"); - ((PyTypeObject *)(void *)blob.ptr())->tp_as_buffer = &Message::Blob::bp; + ((PyTypeObject *)(void *)blob_class.ptr())->tp_as_buffer = &Message::Blob::bp; + + auto message_class = class_("Message", "p≡p message") + .add_property("dir", (int(Message::*)()) + (PEP_msg_direction(Message::*)()) &Message::dir, + (void(Message::*)(int)) + (void(Message::*)(PEP_msg_direction)) &Message::dir, + "0: incoming, 1: outgoing message") + .add_property("id", (string(Message::*)()) &Message::id, + (void(Message::*)(string)) &Message::id, + "message ID") + .add_property("shortmsg", (string(Message::*)()) &Message::shortmsg, + (void(Message::*)(string)) &Message::shortmsg, + "subject or short message") + .add_property("longmsg", (string(Message::*)()) &Message::longmsg, + (void(Message::*)(string)) &Message::longmsg, + "body or long version of message") + .add_property("longmsg_formatted", (string(Message::*)()) &Message::longmsg_formatted, + (void(Message::*)(string)) &Message::longmsg_formatted, + "HTML body or fromatted long version of message") + .add_property("attachments", (tuple(Message::*)()) &Message::attachments, + (void(Message::*)(list)) &Message::attachments, + "tuple of Blobs with attachments; setting moves Blobs to attachment tuple") + .add_property("sent", (time_t(Message::*)()) &Message::sent, + (void(Message::*)(time_t)) &Message::sent, + "time when message was sent in UTC seconds since epoch") + .add_property("recv", (time_t(Message::*)()) &Message::recv, + (void(Message::*)(time_t)) &Message::recv, + "time when message was received in UTC seconds since epoch") + .add_property("from_", (object(Message::*)()) &Message::from, + (void(Message::*)(object)) &Message::from, + "identity where message is from") + .add_property("to", (list(Message::*)()) &Message::to, + (void(Message::*)(list)) &Message::to, + "list of identities message is going to") + .add_property("recv_by", (object(Message::*)()) &Message::recv_by, + (void(Message::*)(object)) &Message::recv_by, + "identity where message was received by") + .add_property("cc", (list(Message::*)()) &Message::cc, + (void(Message::*)(list)) &Message::cc, + "list of identities message is going cc") + .add_property("bcc", (list(Message::*)()) &Message::bcc, + (void(Message::*)(list)) &Message::bcc, + "list of identities message is going bcc") + .add_property("reply_to", (list(Message::*)()) &Message::reply_to, + (void(Message::*)(list)) &Message::reply_to, + "list of identities where message will be replied to"); } diff --git a/src/pEpmodule.hh b/src/pEpmodule.hh index af5b07a..35a83bd 100644 --- a/src/pEpmodule.hh +++ b/src/pEpmodule.hh @@ -7,7 +7,6 @@ namespace pEp { using namespace std; const char *version_string = "p≡p Python adapter version 0.1"; - string about(); } } diff --git a/src/str_attr.cc b/src/str_attr.cc index 1b28b9f..f4cfc68 100644 --- a/src/str_attr.cc +++ b/src/str_attr.cc @@ -1,12 +1,20 @@ +#include +#include #include "str_attr.hh" #include -#include namespace pEp { namespace utility { using namespace std; using namespace boost::locale; + 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); @@ -16,11 +24,18 @@ namespace pEp { throw bad_alloc(); } - string str_attr(char *&str) + time_t timestamp_attr(timestamp *&ts) { - if (!str) - return string(""); - return string(str); + if (!ts) + return 0; + + return timegm(ts); + } + + void timestamp_attr(timestamp *&ts, time_t value) + { + free_timestamp(ts); + ts = new_timestamp(value); } } } diff --git a/src/str_attr.hh b/src/str_attr.hh index c68e83c..a2fdd0c 100644 --- a/src/str_attr.hh +++ b/src/str_attr.hh @@ -1,13 +1,19 @@ #pragma once #include +#include +#include namespace pEp { namespace utility { using namespace std; + using namespace boost::python; - void str_attr(char *&str, string value); 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); } }