1 /*
2 
3   silcmime.h
4 
5   Author: Pekka Riikonen <priikone@silcnet.org>
6 
7   Copyright (C) 2005 - 2006 Pekka Riikonen
8 
9   The contents of this file are subject to one of the Licenses specified
10   in the COPYING file;  You may not use this file except in compliance
11   with the License.
12 
13   The software distributed under the License is distributed on an "AS IS"
14   basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
15   KIND, either expressed or implied.  See the COPYING file for more
16   information.
17 
18 */
19 
20 /****h* silcutil/SILC MIME Interface
21  *
22  * DESCRIPTION
23  *
24  * Simple implementation of MIME.  Supports creation and parsing of simple
25  * MIME messages, multipart MIME messages, including nested multiparts, and
26  * MIME fragmentation and defragmentation.
27  *
28  * SILC Mime API is not thread-safe.  If the same MIME context must be
29  * used in multithreaded environment concurrency control must be employed.
30  *
31  ***/
32 
33 #ifndef SILCMIME_H
34 #define SILCMIME_H
35 
36 /****s* silcutil/SILCMIMEAPI/SilcMime
37  *
38  * NAME
39  *
40  *    typedef struct SilcMimeStruct *SilcMime;
41  *
42  * DESCRIPTION
43  *
44  *    This context is the actual MIME message and is allocated
45  *    by silc_mime_alloc and given as argument to all silc_mime_*
46  *    functions.  It is freed by the silc_mime_free function.
47  *
48  ***/
49 typedef struct SilcMimeStruct *SilcMime;
50 
51 /****s* silcutil/SILCMIMEAPI/SilcMimeAssembler
52  *
53  * NAME
54  *
55  *    typedef struct SilcMimeAssemblerStruct *SilcMimeAssembler;
56  *
57  * DESCRIPTION
58  *
59  *    This context is a SILC MIME Assembler that is used to assemble partial
60  *    MIME messages (fgraments) into complete MIME messages.  It is allocated
61  *    by silc_mime_assembler_alloc and freed by silc_mime_assembler_free.
62  *
63  ***/
64 typedef struct SilcMimeAssemblerStruct *SilcMimeAssembler;
65 
66 /****f* silcutil/SILCMIMEAPI/silc_mime_alloc
67  *
68  * SYNOPSIS
69  *
70  *    SilcMime silc_mime_alloc(void)
71  *
72  * DESCRIPTION
73  *
74  *    Allocates SILC Mime message context.
75  *
76  ***/
77 SilcMime silc_mime_alloc(void);
78 
79 /****f* silcutil/SILCMIMEAPI/silc_mime_free
80  *
81  * SYNOPSIS
82  *
83  *    void silc_mime_alloc(SilcMime mime)
84  *
85  * DESCRIPTION
86  *
87  *    Frees `mime' context.
88  *
89  ***/
90 void silc_mime_free(SilcMime mime);
91 
92 /****f* silcutil/SILCMIMEAPI/silc_mime_assembler_alloc
93  *
94  * SYNOPSIS
95  *
96  *    SilcMimeAssembler silc_mime_assembler_alloc(void);
97  *
98  * DESCRIPTION
99  *
100  *    Allocates MIME fragment assembler.
101  *
102  ***/
103 SilcMimeAssembler silc_mime_assembler_alloc(void);
104 
105 /****f* silcutil/SILCMIMEAPI/silc_mime_assembler_free
106  *
107  * SYNOPSIS
108  *
109  *    void silc_mime_assembler_free(SilcMimeAssembler assembler)
110  *
111  * DESCRIPTION
112  *
113  *    Frees `assembler' context.
114  *
115  ***/
116 void silc_mime_assembler_free(SilcMimeAssembler assembler);
117 
118 /****f* silcutil/SILCMIMEAPI/silc_mime_decode
119  *
120  * SYNOPSIS
121  *
122  *    SilcMime silc_mime_decode(SilcMime mime, const unsigned char *data,
123  *                              SilcUInt32 data_len);
124  *
125  * DESCRIPTION
126  *
127  *    Decodes a MIME message and returns the parsed message into newly
128  *    allocated SilcMime context and returns it.  If `mime' is non-NULL
129  *    then the MIME message will be encoded into the pre-allocated `mime'
130  *    context and same context is returned.  If it is NULL then newly
131  *    allocated SilcMime context is returned.  On error NULL is returned.
132  *
133  * EXAMPLE
134  *
135  *    // Parse MIME message and get its content type
136  *    mime = silc_mime_decode(NULL, data, data_len);
137  *    type = silc_mime_get_field(mime, "Content-Type");
138  *    ...
139  *
140  *    // Assemble received MIME fragment
141  *    mime = silc_mime_decode(NULL, data, data_len);
142  *    if (silc_mime_is_partial(mime) == TRUE)
143  *      silc_mime_assmeble(assembler, mime);
144  *
145  ***/
146 SilcMime silc_mime_decode(SilcMime mime, const unsigned char *data,
147 			  SilcUInt32 data_len);
148 
149 /****f* silcutil/SILCMIMEAPI/silc_mime_encode
150  *
151  * SYNOPSIS
152  *
153  *    unsigned char *silc_mime_encode(SilcMime mime, SilcUInt32 *encoded_len);
154  *
155  * DESCRIPTION
156  *
157  *    Encodes the `mime' context into a raw MIME message (may be human
158  *    readable).  The caller must free the returned buffer.  If the `mime'
159  *    is multipart MIME message all parts will be automatically encoded
160  *    as well.
161  *
162  *    If you want to create fragmented MIME message use the function
163  *    silc_mime_encode_partial.
164  *
165  ***/
166 unsigned char *silc_mime_encode(SilcMime mime, SilcUInt32 *encoded_len);
167 
168 /****f* silcutil/SILCMIMEAPI/silc_mime_assemble
169  *
170  * SYNOPSIS
171  *
172  *    SilcMime silc_mime_assemble(SilcMimeAssembler assembler,
173  *                                SilcMime partial);
174  *
175  * DESCRIPTION
176  *
177  *    Processes and attempts to assemble the received MIME fragment `partial'.
178  *    To check if a received MIME message is a fragment use the
179  *    silc_mime_is_partial function.  Returns NULL if all fragments has not
180  *    yet been received, or the newly allocated completed MIME message if
181  *    all fragments were received.  The caller must free the returned
182  *    SilcMime context.  The caller must not free the `partial'.
183  *
184  * EXAMPLE
185  *
186  *    // Assemble received MIME fragment
187  *    mime = silc_mime_decode(data, data_len);
188  *    if (silc_mime_is_partial(mime) == TRUE) {
189  *      complete = silc_mime_assmeble(assembler, mime);
190  *      if (complete == NULL)
191  *        return;
192  *      ...
193  *    }
194  *
195  ***/
196 SilcMime silc_mime_assemble(SilcMimeAssembler assembler, SilcMime partial);
197 
198 /****f* silcutil/SILCMIMEAPI/silc_mime_encode_partial
199  *
200  * SYNOPSIS
201  *
202  *    SilcDList silc_mime_encode_partial(SilcMime mime, int max_size);
203  *
204  * DESCRIPTION
205  *
206  *    Same as silc_mime_encode except fragments the MIME message `mime'
207  *    if it is larger than `max_size' in bytes.  Returns the MIME fragments
208  *    in SilcDList where each entry is SilcBuffer context.  The caller must
209  *    free the returned list and all SilcBuffer entries in it by calling
210  *    silc_mime_partial_free function.
211  *
212  *    To assemble the fragments into a complete MIME message the
213  *    silc_mime_assemble can be used.
214  *
215  ***/
216 SilcDList silc_mime_encode_partial(SilcMime mime, int max_size);
217 
218 /****f* silcutil/SILCMIMEAPI/silc_mime_partial_free
219  *
220  * SYNOPSIS
221  *
222  *    void silc_mime_partial_free(SilcDList partials);
223  *
224  * DESCRIPTION
225  *
226  *    This function must be called to free the list returned by the
227  *    silc_mime_encode_partial function.
228  *
229  ***/
230 void silc_mime_partial_free(SilcDList partials);
231 
232 /****f* silcutil/SILCMIMEAPI/silc_mime_add_field
233  *
234  * SYNOPSIS
235  *
236  *    void silc_mime_add_field(SilcMime mime,
237  *                             const char *field, const char *value);
238  *
239  * DESCRIPTION
240  *
241  *    Adds a field indicated by `field' to MIME message `mime'.  The field
242  *    value is `value'.
243  *
244  * EXAMPLE
245  *
246  *    silc_mime_add_field(mime, "MIME-Version", "1.0");
247  *    silc_mime_add_field(mime, "Content-Type", "image/jpeg");
248  *    silc_mime_add_field(mime, "Content-Transfer-Encoding", "binary");
249  *
250  ***/
251 void silc_mime_add_field(SilcMime mime, const char *field, const char *value);
252 
253 /****f* silcutil/SILCMIMEAPI/silc_mime_get_field
254  *
255  * SYNOPSIS
256  *
257  *    const char *silc_mime_get_field(SilcMime mime, const char *field);
258  *
259  * DESCRIPTION
260  *
261  *    Returns the `field' value or NULL if such field does not exist in the
262  *    MIME message `mime'.
263  *
264  ***/
265 const char *silc_mime_get_field(SilcMime mime, const char *field);
266 
267 /****f* silcutil/SILCMIMEAPI/silc_mime_add_data
268  *
269  * SYNOPSIS
270  *
271  *    void silc_mime_add_data(SilcMime mime, const unsigned char *data,
272  *                            SilcUInt32 data_len);
273  *
274  * DESCRIPTION
275  *
276  *    Adds the actual MIME data to the `mime' message.
277  *
278  ***/
279 void silc_mime_add_data(SilcMime mime, const unsigned char *data,
280 			SilcUInt32 data_len);
281 
282 /****f* silcutil/SILCMIMEAPI/silc_mime_get_data
283  *
284  * SYNOPSIS
285  *
286  *    const unsigned char *
287  *    silc_mime_get_data(SilcMime mime, SilcUInt32 *data_len);
288  *
289  * DESCRIPTION
290  *
291  *    Returns the MIME data from the `mime' message.
292  *
293  ***/
294 const unsigned char *silc_mime_get_data(SilcMime mime, SilcUInt32 *data_len);
295 
296 /****f* silcutil/SILCMIMEAPI/silc_mime_steal_data
297  *
298  * SYNOPSIS
299  *
300  *    unsigned char *
301  *    silc_mime_steal_data(SilcMime mime, SilcUInt32 *data_len);
302  *
303  * DESCRIPTION
304  *
305  *    Returns the MIME data from the `mime' message.  The data will be
306  *    removed from the `mime' and the caller is responsible of freeing the
307  *    returned pointer.
308  *
309  ***/
310 unsigned char *silc_mime_steal_data(SilcMime mime, SilcUInt32 *data_len);
311 
312 /****f* silcutil/SILCMIMEAPI/silc_mime_is_partial
313  *
314  * SYNOPSIS
315  *
316  *    SilcBool silc_mime_is_partial(SilcMime mime);
317  *
318  * DESCRIPTION
319  *
320  *    Returns TRUE if the MIME message `mime' is a partial MIME fragment.
321  *
322  ***/
323 SilcBool silc_mime_is_partial(SilcMime mime);
324 
325 /****f* silcutil/SILCMIMEAPI/silc_mime_set_multipart
326  *
327  * SYNOPSIS
328  *
329  *    void silc_mime_set_multipart(SilcMime mime, const char *type,
330  *                                 const char *boundary);
331  *
332  * DESCRIPTION
333  *
334  *    Sets the `mime' to be a multipart MIME message.  The `type' specifies
335  *    the multipart type, usually "mixed", but can be something else too.
336  *    The `boundary' specifies the multipart boundary.
337  *
338  ***/
339 void silc_mime_set_multipart(SilcMime mime, const char *type,
340 			     const char *boundary);
341 
342 /****f* silcutil/SILCMIMEAPI/silc_mime_add_multipart
343  *
344  * SYNOPSIS
345  *
346  *    SilcBool silc_mime_add_multipart(SilcMime mime, SilcMime part);
347  *
348  * DESCRIPTION
349  *
350  *    Adds a multipart `part` to MIME message `mime'.  The `part' will be
351  *    freed automatically when silc_mime_free is called for `mime'.  Returns
352  *    TRUE if `part' was added to `mime' and FALSE if `mime' is not marked
353  *    as multipart MIME message.
354  *
355  * NOTES
356  *
357  *    The silc_mime_set_multipart must be called for `mime' before parts
358  *    can be added to it.  Otherwise FALSE will be returned.
359  *
360  * EXAMPLE
361  *
362  *    part = silc_mime_alloc();
363  *    silc_mime_add_field(part, "Content-Type", "image/jpeg");
364  *    silc_mime_add_data(part, data, data_len);
365  *
366  *    silc_mime_set_multipart(mime, "mixed", "boundary1");
367  *    silc_mime_add_multipart(mime, part);
368  *
369  ***/
370 SilcBool silc_mime_add_multipart(SilcMime mime, SilcMime part);
371 
372 /****f* silcutil/SILCMIMEAPI/silc_mime_is_multipart
373  *
374  * SYNOPSIS
375  *
376  *    SilcBool silc_mime_is_multipart(SilcMime mime);
377  *
378  * DESCRIPTION
379  *
380  *    Returns TRUE if the MIME message `mime' is a multipart MIME message.
381  *    Its parts can be get by calling silc_mime_get_multiparts.
382  *
383  ***/
384 SilcBool silc_mime_is_multipart(SilcMime mime);
385 
386 /****f* silcutil/SILCMIMEAPI/silc_mime_get_multiparts
387  *
388  * SYNOPSIS
389  *
390  *    SilcDList silc_mime_get_multiparts(SilcMime mime, const char **type);
391  *
392  * DESCRIPTION
393  *
394  *    Returns list of the parts from the MIME message `mime'.  Each entry
395  *    in the list is SilcMime context.  The caller must not free the returned
396  *    list or the SilcMime contexts in the list.  Returns NULL if no parts
397  *    exists in the MIME message.  Returns the multipart type (like "mixed")
398  *    into `type' pointer.
399  *
400  ***/
401 SilcDList silc_mime_get_multiparts(SilcMime mime, const char **type);
402 
403 #include "silcmime_i.h"
404 
405 #endif /* SILCMIME_H */
406