Representing MIME multipart bodies and their manipulation. More...
Data Structures | |
struct | msg_multipart_s |
Structure for a part in MIME multipart message. More... | |
Defines | |
#define | MSG_MULTIPART_INIT() |
Header class for Recursive multipart header. | |
Enumerations | |
enum | { msg_multipart_hash } |
Functions | |
msg_multipart_t * | msg_multipart_init (msg_multipart_t x[1]) |
Initialize an msg_multipart_t structure. | |
int | msg_is_multipart (msg_header_t const *header) |
Test if header object is an instance of msg_multipart_t. | |
msg_multipart_t * | msg_multipart_dup (su_home_t *home, msg_multipart_t const *header) |
Duplicate (deep copy) msg_multipart_t. | |
msg_multipart_t * | msg_multipart_copy (su_home_t *home, msg_multipart_t const *header) |
Copy an msg_multipart_t header structure. | |
msg_multipart_t * | msg_multipart_make (su_home_t *home, char const *s) |
Make a header structure msg_multipart_t. | |
msg_multipart_t * | msg_multipart_format (su_home_t *home, char const *fmt,...))) |
Make a Recursive multipart header from formatting result. | |
Variables | |
msg_parse_f | msg_multipart_d |
Parse a Recursive multipart header. | |
msg_print_f | msg_multipart_e |
Print a Recursive multipart header. |
Representing MIME multipart bodies and their manipulation.
The msg_multipart_t is an object for storing MIME multipart message bodies. It includes message components used for framing and identifying message parts. Its syntax is defined in RFC 2046 as follows:
multipart-body := [preamble CRLF] dash-boundary transport-padding CRLF body-part *encapsulation close-delimiter transport-padding [CRLF epilogue] preamble := discard-text discard-text := *(*text CRLF) ; May be ignored or discarded. dash-boundary := "--" boundary ; boundary taken from the value of boundary parameter ; of the Content-Type field. boundary := 0*69<bchars> bcharsnospace bchars := bcharsnospace / " " bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / "+" / "_" / "," / "-" / "." / "/" / ":" / "=" / "?" transport-padding := *LWSP-char ; Composers MUST NOT generate non-zero length ; transport padding, but receivers MUST be able to ; handle padding added by message transports. body-part := <"message" as defined in @RFC822, with all header fields optional, not starting with the specified dash-boundary, and with the delimiter not occurring anywhere in the body part. Note that the semantics of a part differ from the semantics of a message, as described in the text.> encapsulation := delimiter transport-padding CRLF body-part close-delimiter := delimiter "--" delimiter := CRLF dash-boundary epilogue := discard-text
When a message body contains a multipart entity (in other words, it has a MIME media type of "multipart"), the application can split the multipart entity into body parts
The parsing is relatively simple, the application just gives a memory home object, a Content-Type header object and message body object as an argument to msg_multipart_parse() function:
if (sip->sip_content_type && su_casenmatch(sip->sip_content_type, "multipart/", 10)) { msg_multipart_t *mp; if (sip->sip_multipart) mp = sip->sip_multipart; else mp = msg_multipart_parse(msg_home(msg), sip->sip_content_type, (sip_payload_t *)sip->sip_payload); if (mp) ... processing multipart ... else ... error handling ... }
The resulting list of msg_multipart_t structures contain the parts of the multipart entity, each part represented by a separate msg_multipart_t structure. Please note that in order to make error recovery possible, the parsing is not recursive - if multipart contains another multipart, the application is responsible for scanning for it and parsing it.
Constructing a multipart body is a bit more hairy. The application needs a message object (msg_t), which is used to buffer the encoding of multipart components.
As an example, let us create a "multipart/mixed" multipart entity with a HTML and GIF contents, and convert it into a sip_payload_t structure:
msg_t *msg = msg_create(sip_default_mclass, 0); su_home_t *home = msg_home(msg); sip_t *sip = sip_object(msg); sip_content_type_t *c; msg_multipart_t *mp = NULL; msg_header_t *h = NULL; char *b; size_t len, offset; mp = msg_multipart_create(home, "text/html;level=3", html, strlen(html)); mp->mp_next = msg_multipart_create(home, "image/gif", gif, giflen); c = sip_content_type_make(home, "multipart/mixed"); // Add delimiters to multipart, and boundary parameter to content-type if (msg_multipart_complete(home, c, mp) < 0) return -1; // Error // Combine multipart components into the chain h = NULL; if (msg_multipart_serialize(&h, mp) < 0) return -1; // Error // Encode all multipart components len = msg_multipart_prepare(msg, mp, 0); if (len < 0) return -1; // Error pl = sip_payload_create(home, NULL, len); // Copy each element from multipart to pl_data b = pl->pl_data; for (offset = 0, h = mp; offset < len; h = h->sh_succ) { memcpy(b + offset, h->sh_data, h->sh_len); offset += h->sh_len; }
#define MSG_MULTIPART_INIT | ( | ) |
Header class for Recursive multipart header.
The header class msg_multipart_class defines how a Recursive multipart header header is parsed and printed. It also contains methods used by message parser and other functions to manipulate the msg_multipart_t header structure.Initializer for an msg_multipart_t structure.
A static msg_multipart_t structure must be initialized with the MSG_MULTIPART_INIT() macro. For instance,
msg_multipart_t msg_multipart = MSG_MULTIPART_INIT;
int msg_is_multipart | ( | msg_header_t const * | header | ) | [inline] |
Test if header object is an instance of msg_multipart_t.
The function msg_is_multipart() returns true (nonzero) if the header class is an instance of Recursive multipart header object and false (zero) otherwise.
header | pointer to the header structure to be tested |
msg_multipart_t * msg_multipart_copy | ( | su_home_t * | home, | |
msg_multipart_t const * | header | |||
) | [inline] |
Copy an msg_multipart_t header structure.
The function msg_multipart_copy() copies a header structure header. If the header structure header contains a reference (header->h_next
) to a list of headers, all the headers in that list are copied, too. The function uses given memory home to allocate all the memory areas used to copy the header structure header.
home | memory home used to allocate new structure | |
header | pointer to the header structure to be duplicated |
When copying, only the header structure and parameter lists attached to it are duplicated. The new header structure retains all the references to the strings within the old header, including the encoding of the old header, if present.
multipart = msg_multipart_copy(home, msg->msg_multipart);
msg_multipart_t * msg_multipart_dup | ( | su_home_t * | home, | |
msg_multipart_t const * | header | |||
) | [inline] |
Duplicate (deep copy) msg_multipart_t.
The function msg_multipart_dup() duplicates a header structure header. If the header structure header contains a reference (header->x_next
) to a list of headers, all the headers in the list are duplicated, too.
home | memory home used to allocate new structure | |
header | header structure to be duplicated |
When duplicating, all parameter lists and non-constant strings attached to the header are copied, too. The function uses given memory home to allocate all the memory areas used to copy the header.
multipart = msg_multipart_dup(home, msg->msg_multipart);
msg_multipart_t * msg_multipart_format | ( | su_home_t * | home, | |
char const * | fmt, | |||
... | ||||
) | [inline] |
Make a Recursive multipart header from formatting result.
The function msg_multipart_format() makes a new Recursive multipart header object using snprintf-formatted result as its value. The function first prints the arguments according to the format fmt specified. Then it allocates a new header structure, and uses the formatting result as the header value.
home | memory home used to allocate new header structure. | |
fmt | string used as a printf()-style format | |
... | argument list for format |
msg_multipart_t* msg_multipart_init | ( | msg_multipart_t | x[1] | ) | [inline] |
Initialize an msg_multipart_t structure.
An msg_multipart_t structure can be initialized with the msg_multipart_init() function/macro. For instance,
msg_multipart_t msg_multipart; msg_multipart_init(&msg_multipart);
x | pointer to msg_multipart_t structure |
msg_multipart_t* msg_multipart_make | ( | su_home_t * | home, | |
char const * | s | |||
) | [inline] |
Make a header structure msg_multipart_t.
The function msg_multipart_make() makes a new msg_multipart_t header structure. It allocates a new header structure, and decodes the string s as the value of the structure.
home | memory home used to allocate new header structure. | |
s | string to be decoded as value of the new header structure |