diff --git a/asn.1/message.asn1 b/asn.1/message.asn1 index 71708d19a..230108ed5 100644 --- a/asn.1/message.asn1 +++ b/asn.1/message.asn1 @@ -27,22 +27,28 @@ MessageDirection ::= ENUMERATED { 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 + 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. -*/ +-- 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 diff --git a/src/map_asn1.c b/src/map_asn1.c index f1840304a..60dd1aed4 100644 --- a/src/map_asn1.c +++ b/src/map_asn1.c @@ -401,3 +401,103 @@ enomem: return NULL; } +BlobList_t *BlobList_from_bloblist( + bloblist_t *list, + BlobList_t *result, + bool copy, + size_t max_blob_size + ) +{ + bool allocated = !result; + + assert(list); + if (!list) + 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 = NULL; + 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 = NULL; + 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; +} + diff --git a/src/map_asn1.h b/src/map_asn1.h index 5c526cb77..4828183c6 100644 --- a/src/map_asn1.h +++ b/src/map_asn1.h @@ -15,6 +15,7 @@ #include "../asn.1/StringPair.h" #include "../asn.1/StringPairList.h" #include "../asn.1/PStringList.h" +#include "../asn.1/BlobList.h" #ifdef __cplusplus extern "C" { @@ -203,12 +204,58 @@ PStringList_t *PStringList_from_stringlist( * */ -stringlist_t *StringPairList_to_stringlist( - StringPairList_t *list, +stringlist_t *PStringList_to_stringlist( + PStringList_t *list, stringlist_t *result ); +/** + * + * + * @brief Convert bloblist_t into ASN.1 BlobList_t + * + * @param list[in] bloblist to convert + * @param result[inout] BlobList_t to update or NULL to alloc a new one + * @param copy copy data if true, move data otherwise + * @param max_blob_size reject if sum(blob.size) > max_blob_size + * + * @retval pointer to updated or allocated result + * + * @warning if a new struct is allocated, the ownership goes to the caller + * + */ + +BlobList_t *BlobList_from_bloblist( + bloblist_t *list, + BlobList_t *result, + bool copy, + size_t max_blob_size + ); + +/** + * + * + * @brief Convert ASN.1 BlobList_t to bloblist_t + * + * @param list[in] ASN.1 BlobList_t to convert + * @param result[inout] bloblist_t to update or NULL to alloc a new one + * @param copy copy data if true, move data otherwise + * @param max_blob_size reject if sum(blob.size) > max_blob_size + * + * @retval pointer to updated or allocated result + * + * @warning if a new struct is allocated, the ownership goes to the caller + * + */ + +bloblist_t *BlobList_to_bloblist( + BlobList_t *list, + bloblist_t *result, + bool copy, + size_t max_blob_size + ); + #ifdef __cplusplus } #endif