Compare commits

...

22 Commits

Author SHA1 Message Date
Krista Bennett 9c8de423f3 ENGINE-847: integrated new expectation that properly encrypted and signed messages where we have no information tying that key to the from identity will now be seen as unreliable into DefaultFromEmailTest - down to two failures in that file, anyway
2 years ago
Krista Bennett 80467be4a8 ENGINE-847: incremental repair of er... yeah. I think the ratings calculus needs a little more thought. Will do what I can before I go, but I am not sure this is really going to end up being the elegant solution intended, so pls look carefully at it, fdik.
2 years ago
Krista Bennett 827c211600 ENGINE-847: Some fixes and got further tests working
2 years ago
Krista Bennett 8be484f8c5 Fixed non-updated identities issue in new rating code
2 years ago
Krista Bennett f1c902154b Merge branch 'master' into ENGINE-847
2 years ago
Volker Birk 77e5ecb9ba add encode_PEPMessage_message() and decode_PEPMessage_message() to MapAsn1Test.check_map_asn1_message
2 years ago
Volker Birk 63cad5dc47 Bumped header patch number for NEXT release
2 years ago
Volker Birk fc0151e7ec Merge branch 'ENGINE-898' of ssh://gitea.pep.foundation:23065/pEp.foundation/pEpEngine into ENGINE-898
2 years ago
Volker Birk 314b7a9fd8 add PEPMessage codec functions and complete ENGINE-898
2 years ago
Volker Birk e964ec6f2a add PEPMessage codec functions
2 years ago
Volker Birk 0999587a01 adding MapAsn1Test.check_map_asn1_message
2 years ago
Volker Birk 00c658e735 support disabling max_blob_size
2 years ago
Volker Birk 1d421c9389 add PEPMessage_to_message()
2 years ago
Volker Birk b1a1be1ee1 adding PEPMessage_from_message()
2 years ago
Volker Birk 9f761a04ba adding safeguard; if the structure is healthy this should never happen
2 years ago
Volker Birk 7c6b80d774 implement BlobList_to_bloblist()
2 years ago
Volker Birk a0efd037bb implement BlobList_from_bloblist()
2 years ago
Volker Birk 052e23d2c6 conversion of base types
2 years ago
Volker Birk 7de726962a changes in PEPMessage
2 years ago
Volker Birk c256b63051 avoid double build
2 years ago
Volker Birk 3c46ea46f0 nameclash
2 years ago
Volker Birk d5dfd19a3f add message.asn1 with ASN.1 based p≡p message format
2 years ago

@ -19,7 +19,7 @@ STORAGE_FILES = $(addsuffix .asn1, $(STORAGE))
.PHONY: all clean install uninstall
all: Sync.c Distribution.c Storage.c
all: Sync.c Distribution.c Storage.c PEPMessage.c
$(MAKE) libasn1.a
libasn1.a: $(ALL_OBJECTS)
@ -43,6 +43,11 @@ Storage.c: $(STORAGE_FILES) pEp.asn1
rm -f converter-sample.c
touch Storage.c
PEPMessage.c: message.asn1 pEp.asn1
$(ASN1C) -gen-PER $(ASN1C_OPTIONS) $+
rm -f converter-sample.c
touch PEPMessage.c
clean:
rm -f *.a *.o *.c *.h *.sample \
$(SYNC_FILES) $(DISTRIBUTION_FILES) $(STORAGE_FILES)

@ -0,0 +1,98 @@
-- This file is under BSD License 2.0
--
-- Sync protocol for p≡p
-- Copyright (c) 2021 p≡p foundation
--
-- Written by Hartmut Goebel
PEP-MESSAGE {
iso(1) org(3) dod(6) internet(1) private(4)
enterprise(1) pEp(47878) message(1)
}
DEFINITIONS
AUTOMATIC TAGS EXTENSIBILITY IMPLIED ::=
BEGIN
EXPORTS PEPMessage;
IMPORTS
PString, PStringList, Identity, IdentityList, StringPairList, Hash
FROM PEP { iso(1) org(3) dod(6) internet(1) private(4)
enterprise(1) pEp(47878) basic(0) };
MessageDirection ::= ENUMERATED {
incoming (0),
outgoing (1)
}
ContentDisposition ::= ENUMERATED {
attachment (0),
inline (1),
other (2)
}
Blob ::= SEQUENCE {
value OCTET STRING (SIZE(0..102400000)), -- up to 100 MB
mime-type PString OPTIONAL,
filename PString OPTIONAL,
disposition ContentDisposition
}
BlobList ::= SEQUENCE OF Blob
-- For the purposes of this profile, GeneralizedTime values MUST be
-- expressed in Coordinated Universal Time (UTC) and MUST include seconds
-- (i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds
-- is zero. GeneralizedTime values MUST NOT include fractional seconds.
-- To make this more explicit, the type-name "Timestamp" is used in this
-- profile.
Timestamp ::= GeneralizedTime
PEPMessage ::= SEQUENCE {
direction MessageDirection OPTIONAL, -- used only in "inner" messages
id PString OPTIONAL, -- UTF-8 string of message ID
sent Timestamp OPTIONAL, -- when the message is sent
recv Timestamp OPTIONAL, -- when the message is received
from Identity, -- whom the message is from
-- At least one of to, cc must not be an empty list
-- FIXME: Can this be constrained?
to IdentityList OPTIONAL, -- whom the message is to
cc IdentityList OPTIONAL, -- whom a CC is being sent
bcc IdentityList OPTIONAL, -- whom a BCC is being sent
recv-by Identity OPTIONAL, -- via which identity the message
-- is received
reply-to IdentityList OPTIONAL, -- where a reply should go to
in-reply-to PStringList OPTIONAL, -- list of UTF-8 strings with
-- MessageIDs of refering messages
-- internal: refering_msg_ref
references PStringList OPTIONAL, -- list of UTF-8 strings with
-- references
-- internal: refered_by _message-ref-list
keywords PStringList OPTIONAL, -- list of UTF-8 strings with keywords
comments PString OPTIONAL, -- UTF-8 string with comments
opt-fields StringPairList OPTIONAL, -- optional fields
sender-fpr Hash OPTIONAL, -- fingerprint of sending signer
-- At least one of shortmsg, longmsg, longmsg-formatted must be present
-- FIXME: Can this be constrained?
shortmsg PString OPTIONAL, -- UTF-8 string of short message
-- longmsg must only be used if implementation can handle dynamic allocation
longmsg UTF8String OPTIONAL, -- UTF-8 string of long message
-- (plain)
-- longmsg-formatted must only be used if implementation can handle
-- dynamic allocation
longmsg-formatted UTF8String OPTIONAL, -- UTF-8 string of long message
-- (formatted)
attachments BlobList OPTIONAL -- blobs with attachments
-- internal: rawmsg
}
END

@ -12,12 +12,13 @@ DEFINITIONS AUTOMATIC TAGS EXTENSIBILITY IMPLIED ::=
BEGIN
EXPORTS Identity, IdentityList, TID, Hash, Version, Rating;
EXPORTS Identity, IdentityList, TID, Hash, Version, Rating, PString, PStringList, StringPair, StringPairList;
ISO639-1 ::= PrintableString(FROM ("a".."z")) (SIZE(2))
Hex ::= PrintableString(FROM ("A".."F") | FROM ("0".."9"))
Hex ::= PrintableString(FROM ("A".."F" | "0".."9"))
Hash ::= Hex(SIZE(16..128)) -- 32bit Key ID to SHA512 in hex
PString ::= UTF8String (SIZE(1..1024))
PString ::= UTF8String (SIZE(0..1024))
PStringList ::= SEQUENCE OF PString
TID ::= OCTET STRING (SIZE(16)) -- UUID version 4 variant 1
Identity ::= SEQUENCE {
@ -62,5 +63,12 @@ Rating ::= ENUMERATED {
under-attack (-3)
}
StringPair ::= SEQUENCE {
key PString,
value PString
}
StringPairList ::= SEQUENCE OF StringPair
END

@ -131,8 +131,8 @@ IdentityList_t *IdentityList_from_identity_list(
{
bool allocated = !result;
assert(list);
if (!list)
assert(list && list->ident);
if (!(list && list->ident))
return NULL;
if (allocated) {
@ -190,3 +190,902 @@ enomem:
return NULL;
}
StringPair_t *StringPair_from_Struct(
const stringpair_t *value,
StringPair_t *result
)
{
bool allocated = !result;
assert(value);
if (!value)
return NULL;
if (allocated)
result = (StringPair_t *) calloc(1, sizeof(StringPair_t));
assert(result);
if (!result)
return NULL;
if (value->key) {
int r = OCTET_STRING_fromBuf(&result->key, value->key, -1);
if (r)
goto enomem;
}
if (value->value) {
int r = OCTET_STRING_fromBuf(&result->value, value->value, -1);
if (r)
goto enomem;
}
return result;
enomem:
if (allocated)
ASN_STRUCT_FREE(asn_DEF_StringPair, result);
return NULL;
}
stringpair_t *StringPair_to_Struct(StringPair_t *value)
{
assert(value);
if (!value)
return NULL;
stringpair_t *result = (stringpair_t *) calloc(1, sizeof(stringpair_t));
assert(result);
if (!result)
goto enomem;
result->key = strndup((char *) value->key.buf,
value->key.size);
assert(result->key);
if (!result->key)
goto enomem;
result->value = strndup((char *) value->value.buf,
value->value.size);
assert(result->value);
if (!result->value)
goto enomem;
return result;
enomem:
free_stringpair(result);
return NULL;
}
StringPairList_t *StringPairList_from_stringpair_list(
const stringpair_list_t *list,
StringPairList_t *result
)
{
bool allocated = !result;
assert(list && list->value);
if (!(list && list->value))
return NULL;
if (allocated) {
result = (StringPairList_t *) calloc(1, sizeof(StringPairList_t));
assert(result);
if (!result)
return NULL;
}
else {
asn_sequence_empty(result);
}
for (const stringpair_list_t *l = list; l && l->value; l=l->next) {
StringPair_t *value = StringPair_from_Struct(l->value, NULL);
if (ASN_SEQUENCE_ADD(&result->list, value)) {
ASN_STRUCT_FREE(asn_DEF_StringPair, value);
goto enomem;
}
}
return result;
enomem:
if (allocated)
ASN_STRUCT_FREE(asn_DEF_StringPairList, result);
return NULL;
}
stringpair_list_t *StringPairList_to_stringpair_list(
StringPairList_t *list,
stringpair_list_t *result
)
{
bool allocated = !result;
assert(list);
if (!list)
return NULL;
if (allocated)
result = new_stringpair_list(NULL);
if (!result)
return NULL;
stringpair_list_t *r = result;
for (int i=0; i<list->list.count; i++) {
stringpair_t *value = StringPair_to_Struct(list->list.array[i]);
r = stringpair_list_add(r, value);
if (!r)
goto enomem;
}
return result;
enomem:
if (allocated)
free_stringpair_list(result);
return NULL;
}
PStringList_t *PStringList_from_stringlist(
const stringlist_t *list,
PStringList_t *result
)
{
bool allocated = !result;
assert(list && list->value);
if (!(list && list->value))
return NULL;
if (allocated) {
result = (PStringList_t *) calloc(1, sizeof(PStringList_t));
assert(result);
if (!result)
return NULL;
}
else {
asn_sequence_empty(result);
}
for (const stringlist_t *l = list; l && l->value; l=l->next) {
PString_t *element = (PString_t *) calloc(1, sizeof(PString_t));
assert(element);
if (!element)
goto enomem;
int r = OCTET_STRING_fromBuf(element, l->value, -1);
if (r)
goto enomem;
if (ASN_SEQUENCE_ADD(&result->list, element)) {
ASN_STRUCT_FREE(asn_DEF_PString, element);
goto enomem;
}
}
return result;
enomem:
if (allocated)
ASN_STRUCT_FREE(asn_DEF_PStringList, result);
return NULL;
}
stringlist_t *PStringList_to_stringlist(PStringList_t *list)
{
assert(list);
if (!list)
return NULL;
stringlist_t *result = (stringlist_t *) calloc(1, sizeof(stringlist_t));
assert(result);
if (!result)
goto enomem;
stringlist_t *r = result;
for (int i=0; i<list->list.count; i++) {
char *s = strndup((char *) list->list.array[i]->buf,
list->list.array[i]->size);
assert(s);
if (!s)
goto enomem;
r->value = s;
if (i < list->list.count-1) {
r->next = (stringlist_t *) calloc(1, sizeof(stringlist_t));
assert(r->next);
if (!r->next)
goto enomem;
r = r->next;
}
}
return result;
enomem:
free_stringlist(result);
return NULL;
}
BlobList_t *BlobList_from_bloblist(
bloblist_t *list,
BlobList_t *result,
bool copy,
size_t max_blob_size
)
{
bool allocated = !result;
if (!max_blob_size)
max_blob_size = SIZE_MAX;
assert(list && list->value);
if (!(list && list->value))
return NULL;
if (allocated) {
result = (BlobList_t *) calloc(1, sizeof(BlobList_t));
assert(result);
if (!result)
return NULL;
}
else {
asn_sequence_empty(result);
}
size_t rest_blob_size = max_blob_size;
for (bloblist_t *l = list; l && l->value; l=l->next) {
Blob_t *element = (Blob_t *) calloc(1, sizeof(Blob_t));
assert(element);
if (!element)
goto enomem;
int r = 0;
if (l->size > rest_blob_size)
goto enomem;
rest_blob_size -= l->size;
if (copy) {
r = OCTET_STRING_fromBuf(&element->value, l->value, l->size);
if (r)
goto enomem;
}
else /* move */ {
#if defined(__CHAR_BIT__) && __CHAR_BIT__ == 8
element->value.buf = (uint8_t *) l->value;
#else
// FIXME: this is problematic on platforms with bytes != octets
// we want this warning
element->value.buf = l->value;
#endif
l->value = NULL;
element->value.size = l->size;
l->size = 0;
}
if (!EMPTYSTR(l->mime_type)) {
PString_t *_mime_type = (PString_t *) calloc(1, sizeof(PString_t));
assert(_mime_type);
if (!_mime_type)
goto enomem;
r = OCTET_STRING_fromBuf(_mime_type, l->mime_type, -1);
if (r)
goto enomem;
element->mime_type = _mime_type;
}
if (!EMPTYSTR(l->filename)) {
PString_t *_filename = (PString_t *) calloc(1, sizeof(PString_t));
assert(_filename);
if (!_filename)
goto enomem;
r = OCTET_STRING_fromBuf(_filename, l->filename, -1);
if (r)
goto enomem;
element->filename = _filename;
}
switch (l->disposition) {
case PEP_CONTENT_DISP_ATTACHMENT:
element->disposition = ContentDisposition_attachment;
break;
case PEP_CONTENT_DISP_INLINE:
element->disposition = ContentDisposition_inline;
break;
case PEP_CONTENT_DISP_OTHER:
element->disposition = ContentDisposition_other;
break;
default:
assert(0); // should not happen; use default
element->disposition = ContentDisposition_attachment;
}
if (ASN_SEQUENCE_ADD(&result->list, element)) {
ASN_STRUCT_FREE(asn_DEF_Blob, element);
goto enomem;
}
}
return result;
enomem:
if (allocated)
ASN_STRUCT_FREE(asn_DEF_BlobList, result);
return NULL;
}
bloblist_t *BlobList_to_bloblist(
BlobList_t *list,
bloblist_t *result,
bool copy,
size_t max_blob_size
)
{
bool allocated = !result;
if (!max_blob_size)
max_blob_size = SIZE_MAX;
assert(list);
if (!list)
return NULL;
if (allocated)
result = new_bloblist(NULL, 0, NULL, NULL);
if (!result)
return NULL;
size_t rest_blob_size = max_blob_size;
bloblist_t *r = result;
for (int i=0; i<list->list.count; i++) {
// this should not happen
assert(list->list.array[i]);
if (!list->list.array[i])
goto enomem;
if (list->list.array[i]->value.size > rest_blob_size)
goto enomem;
rest_blob_size -= list->list.array[i]->value.size;
char *_mime_type = NULL;
if (list->list.array[i]->mime_type) {
_mime_type = strndup((char *) list->list.array[i]->mime_type->buf,
list->list.array[i]->mime_type->size);
assert(_mime_type);
if (!_mime_type)
goto enomem;
}
char *_filename = NULL;
if (list->list.array[i]->filename) {
_filename = strndup((char *) list->list.array[i]->filename->buf,
list->list.array[i]->filename->size);
assert(_filename);
if (!_filename)
goto enomem;
}
#if defined(__CHAR_BIT__) && __CHAR_BIT__ == 8
char *_data = (char *) list->list.array[i]->value.buf;
#else
// FIXME: this is problematic on platforms with bytes != octets
// we want this warning
char *_data = list->list.array[i]->value.buf;
#endif
if (copy) {
_data = strndup(_data, list->list.array[i]->value.size);
assert(_data);
if (!_data)
goto enomem;
}
// bloblist_add() has move semantics
r = bloblist_add(r, _data, list->list.array[i]->value.size, _mime_type,
_filename);
if (!copy) {
list->list.array[i]->value.buf = NULL;
list->list.array[i]->value.size = 0;
}
if (!r)
goto enomem;
switch (list->list.array[i]->disposition) {
case ContentDisposition_attachment:
r->disposition = PEP_CONTENT_DISP_ATTACHMENT;
break;
case ContentDisposition_inline:
r->disposition = PEP_CONTENT_DISP_INLINE;
break;
case ContentDisposition_other:
r->disposition = PEP_CONTENT_DISP_OTHER;
break;
default:
assert(0); // should not happen; use default
r->disposition = PEP_CONTENT_DISP_ATTACHMENT;
}
}
return result;
enomem:
if (allocated)
free_bloblist(result);
return NULL;
}
PEPMessage_t *PEPMessage_from_message(
message *msg,
PEPMessage_t *result,
bool copy,
size_t max_blob_size
)
{
bool allocated = !result;
if (!max_blob_size)
max_blob_size = SIZE_MAX;
assert(msg);
if (!msg)
return NULL;
if (allocated) {
result = (PEPMessage_t *) calloc(1, sizeof(PEPMessage_t));
assert(result);
if (!result)
return NULL;
}
else {
asn_sequence_empty(result);
}
// direction will be skipped on the line
if (!EMPTYSTR(msg->id)) {
PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
assert(str);
if (!str)
goto enomem;
int r = OCTET_STRING_fromBuf(str, msg->id, -1);
if (r)
goto enomem;
result->id = str;
}
if (msg->sent) {
Timestamp_t *ts = asn_time2GT(NULL, msg->sent, 1);
if (!ts)
goto enomem;
result->sent = ts;
}
if (msg->recv) {
Timestamp_t *ts = asn_time2GT(NULL, msg->recv, 1);
if (!ts)
goto enomem;
result->recv = ts;
}
if (!msg->from) // from is not optional
goto enomem;
Identity_from_Struct(msg->from, &result->from);
if (msg->to && msg->to->ident) {
IdentityList_t *l = IdentityList_from_identity_list(msg->to, NULL);
if (!l)
goto enomem;
result->to = l;
}
if (msg->cc && msg->cc->ident) {
IdentityList_t *l = IdentityList_from_identity_list(msg->cc, NULL);
if (!l)
goto enomem;
result->cc = l;
}
if (msg->bcc && msg->bcc->ident) {
IdentityList_t *l = IdentityList_from_identity_list(msg->bcc, NULL);
if (!l)
goto enomem;
result->bcc = l;
}
if (msg->recv_by) {
Identity_t *i = Identity_from_Struct(msg->recv_by, NULL);
if (!i)
goto enomem;
result->recv_by = i;
}
if (msg->reply_to && msg->reply_to->ident) {
IdentityList_t *l = IdentityList_from_identity_list(msg->reply_to, NULL);
if (!l)
goto enomem;
result->reply_to = l;
}
if (msg->in_reply_to && msg->in_reply_to->value) {
PStringList_t *l = PStringList_from_stringlist(msg->in_reply_to, NULL);
if (!l)
goto enomem;
result->in_reply_to = l;
}
if (msg->references && msg->references->value) {
PStringList_t *l = PStringList_from_stringlist(msg->references, NULL);
if (!l)
goto enomem;
result->references = l;
}
if (msg->keywords && msg->keywords->value) {
PStringList_t *l = PStringList_from_stringlist(msg->keywords, NULL);
if (!l)
goto enomem;
result->keywords = l;
}
if (!EMPTYSTR(msg->comments)) {
PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
assert(str);
if (!str)
goto enomem;
int r = OCTET_STRING_fromBuf(str, msg->comments, -1);
if (r)
goto enomem;
result->comments = str;
}
if (msg->opt_fields && msg->opt_fields->value) {
StringPairList_t *l = StringPairList_from_stringpair_list(msg->opt_fields, NULL);
if (!l)
goto enomem;
result->opt_fields = l;
}
if (!EMPTYSTR(msg->_sender_fpr)) {
Hash_t *str = (Hash_t *) calloc(1, sizeof(Hash_t));
assert(str);
if (!str)
goto enomem;
int r = OCTET_STRING_fromBuf(str, msg->_sender_fpr, -1);
if (r)
goto enomem;
result->sender_fpr = str;
}
if (!EMPTYSTR(msg->shortmsg)) {
PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
assert(str);
if (!str)
goto enomem;
int r = OCTET_STRING_fromBuf(str, msg->shortmsg, -1);
if (r)
goto enomem;
result->shortmsg = str;
}
size_t rest_blob_size = max_blob_size;
if (!EMPTYSTR(msg->longmsg)) {
PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
assert(str);
if (!str)
goto enomem;
if (copy) {
int r = OCTET_STRING_fromBuf(str, msg->longmsg, -1);
if (r)
goto enomem;
if (str->size > rest_blob_size)
goto enomem;
}
else /* move */ {
str->size = strlen(msg->longmsg);
if (str->size > rest_blob_size)
goto enomem;
str->buf = (uint8_t *) msg->longmsg;
msg->longmsg = NULL;
}
rest_blob_size -= str->size;
result->longmsg = str;
}
if (!EMPTYSTR(msg->longmsg_formatted)) {
PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
assert(str);
if (!str)
goto enomem;
if (copy) {
int r = OCTET_STRING_fromBuf(str, msg->longmsg_formatted, -1);
if (r)
goto enomem;
if (str->size > rest_blob_size)
goto enomem;
}
else /* move */ {
str->size = strlen(msg->longmsg_formatted);
if (str->size > rest_blob_size)
goto enomem;
str->buf = (uint8_t *) msg->longmsg_formatted;
msg->longmsg_formatted = NULL;
}
rest_blob_size -= str->size;
result->longmsg_formatted = str;
}
if (msg->attachments && msg->attachments->value) {
BlobList_t *bl = BlobList_from_bloblist(msg->attachments, NULL, copy,
rest_blob_size);
if (!bl)
goto enomem;
result->attachments = bl;
}
return result;
enomem:
if (allocated)
ASN_STRUCT_FREE(asn_DEF_PEPMessage, result);
return NULL;
}
message *PEPMessage_to_message(
PEPMessage_t *msg,
message *result,
bool copy,
size_t max_blob_size
)
{
bool allocated = !result;
if (!max_blob_size)
max_blob_size = SIZE_MAX;
assert(msg);
if (!msg)
return NULL;
if (allocated) {
result = new_message(PEP_dir_incoming);
if (!result)
goto enomem;
}
if (msg->direction) {
switch (*msg->direction) {
case MessageDirection_incoming:
result->dir = PEP_dir_incoming;
break;
case MessageDirection_outgoing:
result->dir = PEP_dir_outgoing;
break;
default:
assert(0);
}
}
if (msg->id) {
result->id = strndup((char *) msg->id->buf, msg->id->size);
assert(result->id);
if (!result->id)
goto enomem;
}
if (msg->sent) {
timestamp *_sent = new_timestamp(0);
if (!_sent)
goto enomem;
if (asn_GT2time(msg->sent, _sent, 1) == -1)
goto enomem;
result->sent = _sent;
}
if (msg->recv) {
timestamp *_recv = new_timestamp(0);
if (!_recv)
goto enomem;
if (asn_GT2time(msg->recv, _recv, 1) == -1)
goto enomem;
result->recv = _recv;
}
// from is mandatory
result->from = Identity_to_Struct(&msg->from, NULL);
if (!result->from)
goto enomem;
if (msg->to) {
identity_list *il = IdentityList_to_identity_list(msg->to, NULL);
if (!il)
goto enomem;
result->to = il;
}
if (msg->cc) {
identity_list *il = IdentityList_to_identity_list(msg->cc, NULL);
if (!il)
goto enomem;
result->cc = il;
}
if (msg->bcc) {
identity_list *il = IdentityList_to_identity_list(msg->bcc, NULL);
if (!il)
goto enomem;
result->bcc = il;
}
if (msg->recv_by) {
pEp_identity *i = Identity_to_Struct(msg->recv_by, NULL);
if (!i)
goto enomem;
result->recv_by = i;
}
if (msg->reply_to) {
identity_list *il = IdentityList_to_identity_list(msg->reply_to, NULL);
if (!il)
goto enomem;
result->reply_to = il;
}
if (msg->in_reply_to) {
stringlist_t *l = PStringList_to_stringlist(msg->in_reply_to);
if (!l)
goto enomem;
result->in_reply_to = l;
}
if (msg->references) {
stringlist_t *l = PStringList_to_stringlist(msg->references);
if (!l)
goto enomem;
result->references = l;
}
if (msg->keywords) {
stringlist_t *l = PStringList_to_stringlist(msg->keywords);
if (!l)
goto enomem;
result->keywords = l;
}
if (msg->comments) {
char *s = strndup((char *) msg->comments->buf, msg->comments->size);
assert(s);
if (!s)
goto enomem;
result->comments = s;
}
if (msg->opt_fields) {
stringpair_list_t *l =
StringPairList_to_stringpair_list(msg->opt_fields, NULL);
if (!l)
goto enomem;
result->opt_fields = l;
}
if (msg->sender_fpr) {
char *_sender_fpr = strndup((char *) msg->sender_fpr->buf,
msg->sender_fpr->size);
if (!_sender_fpr)
goto enomem;
result->_sender_fpr = _sender_fpr;
}
if (msg->shortmsg) {
char *s = strndup((char *) msg->shortmsg->buf, msg->shortmsg->size);
assert(s);
if (!s)
goto enomem;
result->shortmsg = s;
}
size_t rest_blob_size = max_blob_size;
if (msg->longmsg) {
if (msg->longmsg->size > rest_blob_size)
goto enomem;
char *s = NULL;
if (copy) {
s = strndup((char *) msg->longmsg->buf, msg->longmsg->size);
if (!s)
goto enomem;
rest_blob_size -= msg->longmsg->size;
}
else /* move */ {
s = (char *) msg->longmsg->buf;
msg->longmsg->buf = NULL;
rest_blob_size -= msg->longmsg->size;
msg->longmsg->size = 0;
}
result->longmsg = s;
}
if (msg->longmsg_formatted) {
if (msg->longmsg_formatted->size > rest_blob_size)
goto enomem;
char *s = NULL;
if (copy) {
s = strndup((char *) msg->longmsg_formatted->buf,
msg->longmsg_formatted->size);
if (!s)
goto enomem;
rest_blob_size -= msg->longmsg_formatted->size;
}
else /* move */ {
s = (char *) msg->longmsg_formatted->buf;
msg->longmsg_formatted->buf = NULL;
rest_blob_size -= msg->longmsg_formatted->size;
msg->longmsg_formatted->size = 0;
}
result->longmsg_formatted = s;
}
if (msg->attachments) {
bloblist_t *a = BlobList_to_bloblist(msg->attachments, NULL, copy,
rest_blob_size);
if (!a)
goto enomem;
result->attachments = a;
}
return result;
enomem:
if (allocated)
free_message(result);
return NULL;
}

@ -7,10 +7,8 @@
#ifndef MAP_ASN1_H
#define MAP_ASN1_H
#include "pEpEngine.h"
#include "identity_list.h"
#include "../asn.1/Identity.h"
#include "../asn.1/IdentityList.h"
#include "message.h"
#include "../asn.1/PEPMessage.h"
#ifdef __cplusplus
extern "C" {
@ -89,6 +87,217 @@ IdentityList_t *IdentityList_from_identity_list(
identity_list *IdentityList_to_identity_list(IdentityList_t *list, identity_list *result);
/**
* <!-- StringPair_from_Struct() -->
*
* @brief Convert stringpair_t into ASN.1 StringPair_t
*
* @param value[in] stringpair_t to convert
* @param result[in,out] StringPair_t to update or NULL to alloc a new one
*
* @retval pointer to updated or allocated result
*
* @warning if a new struct is allocated, the ownership goes to the caller
*
*/
StringPair_t *StringPair_from_Struct(
const stringpair_t *value,
StringPair_t *result
);
/**
* <!-- StringPair_to_Struct() -->
*
* @brief Convert ASN.1 StringPair_t into stringpair_t
*
* @param value[in] StringPair_t to convert
*
* @retval pointer to updated or allocated result
*
* @warning a new struct is allocated, the ownership goes to the caller
*
*/
stringpair_t *StringPair_to_Struct(StringPair_t *value);
/**
* <!-- StringPairList_from_stringpair_list() -->
*
* @brief Convert stringpair_list_t into ASN.1 StringPairList_t
*
* @param list[