00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032 #ifdef HAVE_STDIO_H
00033 #include <stdio.h>
00034 #endif
00035
00036 #ifdef HAVE_STDLIB_H
00037 #include <stdlib.h>
00038 #endif
00039
00040 #ifdef HAVE_STRING_H
00041 #include <string.h>
00042 #endif
00043
00044 #ifdef HAVE_ERRNO_H
00045 #include <errno.h>
00046 #endif
00047
00048 #ifdef HAVE_NETINET_IN_H
00049 #include <netinet/in.h>
00050 #endif
00051
00052
00053
00054
00055
00056 #include "nanohttp-logging.h"
00057 #include "nanohttp-error.h"
00058 #include "nanohttp-common.h"
00059 #include "nanohttp-socket.h"
00060 #include "nanohttp-stream.h"
00061 #include "nanohttp-mime.h"
00062
00063
00064
00065
00066
00067 typedef void (*MIME_part_begin) (void *);
00068 typedef void (*MIME_part_end) (void *);
00069 typedef void (*MIME_parse_begin) (void *);
00070 typedef void (*MIME_parse_end) (void *);
00071 typedef void (*MIME_ERROR_bytes) (void *, const unsigned char *, int);
00072
00073 typedef enum _MIME_parser_status
00074 {
00075 MIME_PARSER_INCOMPLETE_MESSAGE,
00076 MIME_PARSER_READ_ERROR,
00077 MIME_PARSER_OK
00078 } MIME_parser_status;
00079
00080 typedef enum _MIME_read_status
00081 {
00082 MIME_READ_OK,
00083 MIME_READ_EOF,
00084 MIME_READ_ERROR
00085 } MIME_read_status;
00086
00087 #define MIME_READER_MAX_BUFFER_SIZE 1054
00088 #define MIME_PARSER_BUFFER_SIZE 1054
00089
00090
00091 typedef MIME_read_status(*MIME_read_function) (void *, unsigned char *,
00092 int *);
00093
00094
00099 typedef struct _MIME_reader
00100 {
00101 int size;
00102 int marker;
00103 int current;
00104 MIME_read_function read_function;
00105 char buffer[MIME_READER_MAX_BUFFER_SIZE];
00106 void *userdata;
00107 } MIME_reader;
00108
00109
00110 MIME_read_status MIME_filereader_function(void *userdata,
00111 unsigned char *dest, int *size);
00112
00113 typedef struct _MIME_callbacks
00114 {
00115 MIME_part_begin part_begin_cb;
00116 MIME_part_end part_end_cb;
00117 MIME_parse_begin parse_begin_cb;
00118 MIME_parse_end parse_end_cb;
00119 MIME_ERROR_bytes received_bytes_cb;
00120 } MIME_callbacks;
00121
00122
00123 MIME_parser_status MIME_parse(MIME_read_function reader_function,
00124 void *reader_userdata,
00125 const char *user_boundary,
00126 const MIME_callbacks * callbacks,
00127 void *callbacks_userdata);
00128
00129
00133 void
00134 MIME_reader_init(MIME_reader * reader,
00135 MIME_read_function reader_function, void *userdata)
00136 {
00137 reader->size = 0;
00138 reader->marker = -1;
00139 reader->current = 0;
00140 reader->userdata = userdata;
00141 reader->read_function = reader_function;
00142
00143 }
00144
00148 MIME_read_status
00149 MIME_reader_read(MIME_reader * reader, unsigned char *buffer, int size)
00150 {
00151 MIME_read_status status;
00152 int len;
00153 unsigned char tempBuffer[MIME_READER_MAX_BUFFER_SIZE];
00154 int rest_size;
00155
00156
00157 if (reader->size == reader->current)
00158 {
00159
00160
00161
00162 if (reader->marker > -1)
00163 {
00164 if (reader->marker != 0)
00165 {
00166 memcpy(tempBuffer, reader->buffer + reader->marker,
00167 reader->size - reader->marker);
00168 memcpy(reader->buffer, tempBuffer, reader->size - reader->marker);
00169 reader->current = reader->size - reader->marker;
00170 }
00171 else if (reader->current == MIME_READER_MAX_BUFFER_SIZE - 1)
00172 {
00173 fprintf(stderr, "Marker error");
00174 return MIME_READ_ERROR;
00175 }
00176 reader->marker = 0;
00177 }
00178 else
00179 reader->current = 0;
00180
00181 len = MIME_READER_MAX_BUFFER_SIZE - reader->current - 1;
00182 status = reader->read_function(reader->userdata,
00183 reader->buffer + reader->current,
00184 &len);
00185
00186 if (status == MIME_READ_OK)
00187 {
00188 reader->size = len + reader->current;
00189 }
00190 else
00191 return status;
00192 }
00193
00194 if (size <= reader->size - reader->current)
00195 {
00196 memcpy(buffer, reader->buffer + reader->current, size);
00197 reader->current += size;
00198 return MIME_READ_OK;
00199 }
00200 else
00201 {
00202
00203 rest_size = reader->size - reader->current;
00204 memcpy(buffer, reader->buffer + reader->current, rest_size);
00205
00206 reader->current = reader->size;
00207 return MIME_reader_read(reader, buffer + rest_size, size - rest_size);
00208 }
00209 }
00210
00211
00212 void
00213 MIME_reader_set_marker(MIME_reader * reader)
00214 {
00215 reader->marker = reader->current;
00216 }
00217
00218 void
00219 MIME_reader_unset_marker(MIME_reader * reader)
00220 {
00221 reader->marker = -1;
00222 }
00223
00224 void
00225 MIME_reader_jump_marker(MIME_reader * reader)
00226 {
00227 reader->current = reader->marker;
00228 }
00229
00230
00231
00232 typedef struct _MIME_buffer
00233 {
00234 unsigned char data[MIME_PARSER_BUFFER_SIZE];
00235 int size;
00236 } MIME_buffer;
00237
00238
00239 void
00240 MIME_buffer_init(MIME_buffer * buffer)
00241 {
00242 buffer->size = 0;
00243 }
00244
00245 void
00246 MIME_buffer_add(MIME_buffer * buffer, unsigned char ch)
00247 {
00248 buffer->data[buffer->size++] = ch;
00249 }
00250
00251 void
00252 MIME_buffer_add_bytes(MIME_buffer * buffer, unsigned char *bytes, int size)
00253 {
00254 memcpy(buffer->data, bytes, size);
00255 buffer->size += size;
00256 }
00257
00258 int
00259 MIME_buffer_is_full(MIME_buffer * buffer)
00260 {
00261 return buffer->size + 150 >= MIME_PARSER_BUFFER_SIZE;
00262 }
00263
00264 int
00265 MIME_buffer_is_empty(MIME_buffer * buffer)
00266 {
00267 return buffer->size == 0;
00268 }
00269
00270 void
00271 MIME_buffer_clear(MIME_buffer * buffer)
00272 {
00273 buffer->size = 0;
00274 }
00275
00276
00277 MIME_parser_status
00278 MIME_parse(MIME_read_function reader_function,
00279 void *reader_userdata,
00280 const char *user_boundary,
00281 const MIME_callbacks * callbacks, void *callbacks_userdata)
00282 {
00283 char boundary[150];
00284 unsigned char ch[153];
00285 int boundary_length, n, ignore = 0;
00286 MIME_reader reader;
00287 MIME_buffer buffer;
00288 MIME_read_status status;
00289
00290
00291 MIME_reader_init(&reader, reader_function, reader_userdata);
00292
00293
00294 MIME_buffer_init(&buffer);
00295
00296
00297 sprintf(boundary, "\n--%s", user_boundary);
00298 boundary_length = strlen(boundary);
00299
00300
00301 callbacks->parse_begin_cb(callbacks_userdata);
00302
00303 while (1)
00304 {
00305 set_marker:
00306
00307
00308 MIME_reader_set_marker(&reader);
00309
00310 read_byte:
00311
00312
00313 status = MIME_reader_read(&reader, ch, 1);
00314 if (status == MIME_READ_EOF)
00315 return MIME_PARSER_INCOMPLETE_MESSAGE;
00316 else if (status == MIME_READ_ERROR)
00317 return MIME_PARSER_READ_ERROR;
00318
00319 if (ch[0] == '\r' && !ignore)
00320 {
00321 n = 0;
00322 while (n < boundary_length)
00323 {
00324
00325 status = MIME_reader_read(&reader, ch, 1);
00326 if (status == MIME_READ_EOF)
00327 return MIME_PARSER_INCOMPLETE_MESSAGE;
00328 else if (status == MIME_READ_ERROR)
00329 return MIME_PARSER_READ_ERROR;
00330
00331
00332 if (ch[0] == boundary[n])
00333 {
00334 n = n + 1;
00335 continue;
00336 }
00337 else
00338 {
00339 MIME_reader_jump_marker(&reader);
00340 ignore = 1;
00341 goto read_byte;
00342 }
00343
00344 }
00345
00346
00347 status = MIME_reader_read(&reader, ch, 1);
00348
00349
00350 if (status == MIME_READ_EOF)
00351 return MIME_PARSER_INCOMPLETE_MESSAGE;
00352 else if (status == MIME_READ_ERROR)
00353 return MIME_PARSER_READ_ERROR;
00354
00355
00356 if (ch[0] == '\r')
00357 {
00358
00359 status = MIME_reader_read(&reader, ch, 1);
00360
00361
00362 if (status == MIME_READ_EOF)
00363 return MIME_PARSER_INCOMPLETE_MESSAGE;
00364 else if (status == MIME_READ_ERROR)
00365 return MIME_PARSER_READ_ERROR;
00366
00367
00368 if (ch[0] == '\n')
00369 {
00370 if (!MIME_buffer_is_empty(&buffer))
00371 {
00372
00373 callbacks->received_bytes_cb(callbacks_userdata, buffer.data,
00374 buffer.size);
00375
00376
00377 MIME_buffer_clear(&buffer);
00378
00379
00380 callbacks->part_end_cb(callbacks_userdata);
00381 }
00382
00383
00384 callbacks->part_begin_cb(callbacks_userdata);
00385 goto set_marker;
00386
00387 }
00388 else
00389 {
00390
00391 MIME_reader_jump_marker(&reader);
00392 MIME_reader_read(&reader, ch, boundary_length + 2);
00393
00394 MIME_buffer_add_bytes(&buffer, ch, boundary_length + 2);
00395
00396 if (MIME_buffer_is_full(&buffer))
00397 {
00398
00399 callbacks->received_bytes_cb(callbacks_userdata, buffer.data,
00400 buffer.size);
00401
00402
00403
00404 MIME_buffer_clear(&buffer);
00405 }
00406 }
00407
00408 }
00409 else
00410 {
00411 if (ch[0] == '-')
00412 {
00413
00414 status = MIME_reader_read(&reader, ch, 1);
00415
00416 if (status == MIME_READ_EOF)
00417 return MIME_PARSER_INCOMPLETE_MESSAGE;
00418 else if (status == MIME_READ_ERROR)
00419 return MIME_PARSER_READ_ERROR;
00420
00421 if (ch[0] == '-')
00422 {
00423 if (!MIME_buffer_is_empty(&buffer))
00424 {
00425
00426 callbacks->received_bytes_cb(callbacks_userdata, buffer.data,
00427 buffer.size);
00428
00429
00430 MIME_buffer_clear(&buffer);
00431
00432
00433 callbacks->part_end_cb(callbacks_userdata);
00434 }
00435
00436
00437 callbacks->parse_end_cb(callbacks_userdata);
00438
00439
00440
00441
00442
00443 return MIME_PARSER_OK;
00444
00445 }
00446 else
00447 {
00448 MIME_reader_jump_marker(&reader);
00449 ignore = 1;
00450 goto read_byte;
00451 }
00452
00453 }
00454 else
00455 {
00456 MIME_reader_jump_marker(&reader);
00457 ignore = 1;
00458 goto read_byte;
00459 }
00460
00461 }
00462
00463 }
00464 else
00465 {
00466 ignore = 0;
00467 MIME_buffer_add(&buffer, ch[0]);
00468
00469
00470 if (MIME_buffer_is_full(&buffer))
00471 {
00472
00473 callbacks->received_bytes_cb(callbacks_userdata, buffer.data,
00474 buffer.size);
00475
00476
00477 MIME_buffer_clear(&buffer);
00478 }
00479 }
00480 }
00481 }
00482
00483 MIME_read_status
00484 MIME_filereader_function(void *userdata, unsigned char *dest, int *size)
00485 {
00486 FILE *f = (FILE *) userdata;
00487
00488 if (feof(f))
00489 return MIME_READ_EOF;
00490
00491 *size = fread(dest, 1, *size, f);
00492 return MIME_READ_OK;
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 typedef struct _mime_callback_data
00504 {
00505 int part_id;
00506 struct attachments_t *message;
00507 struct part_t *current_part;
00508 int buffer_capacity;
00509 char header[4064];
00510 char root_id[256];
00511 int header_index;
00512 int header_search;
00513 FILE *current_fd;
00514 char root_dir[512];
00515 } mime_callback_data_t;
00516
00517
00518 MIME_read_status
00519 mime_streamreader_function(void *userdata, unsigned char *dest, int *size)
00520 {
00521 int len = 0;
00522 struct http_input_stream_t *in = (struct http_input_stream_t *) userdata;
00523
00524 if (!http_input_stream_is_ready(in))
00525 return MIME_READ_EOF;
00526
00527 len = http_input_stream_read(in, dest, *size);
00528
00529
00530 if (len == -1)
00531 {
00532 log_error4("[%d] %s():%s ", herror_code(in->err), herror_func(in->err),
00533 herror_message(in->err));
00534 }
00535
00536 *size = len;
00537 if (*size != -1)
00538 {
00539 return MIME_READ_OK;
00540 }
00541 return MIME_READ_ERROR;
00542 }
00543
00544
00545
00546
00547
00548 static void
00549 _mime_parse_begin(void *data)
00550 {
00551
00552
00553
00554 log_verbose2("Begin parse (%p)", data);
00555
00556 return;
00557 }
00558
00559
00560 static void
00561 _mime_parse_end(void *data)
00562 {
00563
00564
00565
00566 log_verbose2("End parse (%p)", data);
00567
00568 return;
00569 }
00570
00571
00572 static void
00573 _mime_part_begin(void *data)
00574 {
00575 char buffer[1054];
00576 struct part_t *part;
00577 mime_callback_data_t *cbdata;
00578
00579 cbdata = (mime_callback_data_t *) data;
00580 log_verbose2("Begin Part (%p)", data);
00581 if (!(part = (struct part_t *) malloc(sizeof(struct part_t))))
00582 {
00583 log_error2("malloc failed (%s)", strerror(errno));
00584 return;
00585 }
00586 part->next = NULL;
00587
00588
00589 if (cbdata->current_part)
00590 cbdata->current_part->next = part;
00591
00592 cbdata->current_part = part;
00593
00594 if (!cbdata->message->parts)
00595 cbdata->message->parts = part;
00596
00597 cbdata->header[0] = '\0';
00598 cbdata->header_index = 0;
00599 cbdata->header_search = 0;
00600
00601 #ifdef WIN32
00602 sprintf(buffer, "%s\\mime_%p_%d.part", cbdata->root_dir,
00603 cbdata, cbdata->part_id++);
00604 #else
00605 sprintf(buffer, "%s/mime_%p_%d.part", cbdata->root_dir,
00606 cbdata, cbdata->part_id++);
00607 #endif
00608
00609
00610 part->deleteOnExit = 1;
00611 cbdata->current_fd = fopen(buffer, "wb");
00612 if (cbdata->current_fd)
00613 strcpy(cbdata->current_part->filename, buffer);
00614 else
00615 log_error2("Can not open file for write '%s'", buffer);
00616 }
00617
00618
00619 static void
00620 _mime_part_end(void *data)
00621 {
00622 mime_callback_data_t *cbdata = (mime_callback_data_t *) data;
00623 log_verbose2("End Part (%p)", data);
00624 if (cbdata->current_fd)
00625 {
00626 fclose(cbdata->current_fd);
00627 cbdata->current_fd = NULL;
00628 }
00629
00630 return;
00631 }
00632
00633
00634 static hpair_t *
00635 _mime_process_header(char *buffer)
00636 {
00637 int i = 0, c = 0, proc_key, begin = 0;
00638 hpair_t *first = NULL, *last = NULL;
00639 char key[1054], value[1054];
00640
00641 key[0] = '\0';
00642 value[0] = '\0';
00643 proc_key = 1;
00644
00645 while (buffer[i] != '\0')
00646 {
00647 if (buffer[i] == '\r' && buffer[i + 1] == '\n')
00648 {
00649 value[c] = '\0';
00650 if (last)
00651 {
00652 last->next = hpairnode_new(key, value, NULL);
00653 last = last->next;
00654 }
00655 else
00656 {
00657 first = last = hpairnode_new(key, value, NULL);
00658 }
00659 proc_key = 1;
00660 c = 0;
00661 i++;
00662 }
00663 else if (buffer[i] == ':')
00664 {
00665 key[c] = '\0';
00666 c = 0;
00667 begin = 0;
00668 proc_key = 0;
00669 }
00670 else
00671 {
00672 if (proc_key)
00673 key[c++] = buffer[i];
00674 else
00675 {
00676 if (buffer[i] != ' ')
00677 begin = 1;
00678 if (begin)
00679 value[c++] = buffer[i];
00680 }
00681 }
00682 i++;
00683 }
00684 return first;
00685 }
00686
00687
00688 static void
00689 _mime_received_bytes(void *data, const unsigned char *bytes, int size)
00690 {
00691 int i = 0;
00692 char *id, *type, *location;
00693 mime_callback_data_t *cbdata = (mime_callback_data_t *) data;
00694
00695 if (!cbdata)
00696 {
00697 log_error1
00698 ("MIME transport error Called <received bytes> without initializing\n");
00699 return;
00700 }
00701 if (!cbdata->current_part)
00702 {
00703 log_error1
00704 ("MIME transport error Called <received bytes> without initializing\n");
00705 return;
00706 }
00707
00708
00709
00710 if (cbdata->header_search < 4)
00711 {
00712
00713 for (i = 0; i < size; i++)
00714 {
00715 if (cbdata->header_search == 0)
00716 {
00717 if (bytes[i] == '\r')
00718 cbdata->header_search++;
00719 else
00720 {
00721 cbdata->header[cbdata->header_index++] = bytes[i];
00722 cbdata->header_search = 0;
00723 }
00724 }
00725
00726 else if (cbdata->header_search == 1)
00727 {
00728 if (bytes[i] == '\n')
00729 cbdata->header_search++;
00730 else
00731 {
00732 cbdata->header[cbdata->header_index++] = '\r';
00733 cbdata->header[cbdata->header_index++] = bytes[i];
00734 cbdata->header_search = 0;
00735 }
00736 }
00737
00738 else if (cbdata->header_search == 2)
00739 {
00740 if (bytes[i] == '\r')
00741 cbdata->header_search++;
00742 else
00743 {
00744 cbdata->header[cbdata->header_index++] = '\r';
00745 cbdata->header[cbdata->header_index++] = '\n';
00746 cbdata->header[cbdata->header_index++] = bytes[i];
00747 cbdata->header_search = 0;
00748 }
00749 }
00750
00751 else if (cbdata->header_search == 3)
00752 {
00753 if (bytes[i] == '\n')
00754 {
00755 cbdata->header[cbdata->header_index++] = '\r';
00756 cbdata->header[cbdata->header_index++] = '\n';
00757 cbdata->header[cbdata->header_index++] = '\0';
00758 cbdata->header_search = 4;
00759 cbdata->current_part->header = _mime_process_header(cbdata->header);
00760 hpairnode_dump_deep(cbdata->current_part->header);
00761
00762 id = hpairnode_get(cbdata->current_part->header, HEADER_CONTENT_ID);
00763 if (id != NULL)
00764 {
00765 strcpy(cbdata->current_part->id, id);
00766 if (!strcmp(id, cbdata->root_id))
00767 cbdata->message->root_part = cbdata->current_part;
00768 }
00769 location =
00770 hpairnode_get(cbdata->current_part->header,
00771 HEADER_CONTENT_LOCATION);
00772 if (location != NULL)
00773 {
00774 strcpy(cbdata->current_part->location, location);
00775 }
00776 type =
00777 hpairnode_get(cbdata->current_part->header, HEADER_CONTENT_TYPE);
00778 if (type != NULL)
00779 {
00780 strcpy(cbdata->current_part->content_type, type);
00781 }
00782 i++;
00783 break;
00784 }
00785 else
00786 {
00787 cbdata->header[cbdata->header_index++] = '\r';
00788 cbdata->header[cbdata->header_index++] = '\n';
00789 cbdata->header[cbdata->header_index++] = '\r';
00790 cbdata->header[cbdata->header_index++] = bytes[i];
00791 cbdata->header_search = 0;
00792 }
00793 }
00794
00795
00796 }
00797 }
00798
00799 if (i >= size - 1)
00800 return;
00801
00802
00803
00804 if (cbdata->current_fd)
00805 fwrite(&(bytes[i]), 1, size - i, cbdata->current_fd);
00806
00807 return;
00808 }
00809
00810
00811
00812
00813
00814
00815 struct attachments_t *
00816 mime_message_parse(struct http_input_stream_t * in, const char *root_id,
00817 const char *boundary, const char *dest_dir)
00818 {
00819 MIME_parser_status status;
00820 MIME_callbacks callbacks;
00821 struct attachments_t *message;
00822
00823 mime_callback_data_t *cbdata;
00824
00825 if (!(cbdata = (mime_callback_data_t *) malloc(sizeof(mime_callback_data_t))))
00826 {
00827 log_error2("malloc failed (%s)", strerror(errno));
00828 return NULL;
00829 }
00830
00831 cbdata->part_id = 100;
00832 cbdata->buffer_capacity = 0;
00833 cbdata->current_fd = NULL;
00834 cbdata->current_part = NULL;
00835 cbdata->header_index = 0;
00836 cbdata->header_search = 0;
00837 strcpy(cbdata->root_id, root_id);
00838 strcpy(cbdata->root_dir, dest_dir);
00839
00840 if (!(message = (struct attachments_t *) malloc(sizeof(struct attachments_t))))
00841 {
00842 log_error2("malloc failed (%s)", strerror(errno));
00843 free(cbdata);
00844 return NULL;
00845 }
00846 cbdata->message = message;
00847 cbdata->message->parts = NULL;
00848 cbdata->message->root_part = NULL;
00849
00850 callbacks.parse_begin_cb = _mime_parse_begin;
00851 callbacks.parse_end_cb = _mime_parse_end;
00852 callbacks.part_begin_cb = _mime_part_begin;
00853 callbacks.part_end_cb = _mime_part_end;
00854 callbacks.received_bytes_cb = _mime_received_bytes;
00855
00856 status = MIME_parse(mime_streamreader_function,
00857 in, boundary, &callbacks, cbdata);
00858
00859 if (status == MIME_PARSER_OK)
00860 {
00861 free(cbdata);
00862 return message;
00863 }
00864 else
00865 {
00866 log_error2("MIME parser error '%s'!",
00867 status ==
00868 MIME_PARSER_READ_ERROR ? "read error" : "Incomplete message");
00869 return NULL;
00870 }
00871 }
00872
00873 struct attachments_t *
00874 mime_message_parse_from_file(FILE * in, const char *root_id,
00875 const char *boundary, const char *dest_dir)
00876 {
00877 MIME_parser_status status;
00878 MIME_callbacks callbacks;
00879 struct attachments_t *message;
00880
00881 mime_callback_data_t *cbdata;
00882
00883 if (!(cbdata = (mime_callback_data_t *) malloc(sizeof(mime_callback_data_t))))
00884 {
00885 log_error2("malloc failed (%s)", strerror(errno));
00886 return NULL;
00887 }
00888
00889 cbdata->part_id = 100;
00890 cbdata->buffer_capacity = 0;
00891 cbdata->current_fd = NULL;
00892 cbdata->current_part = NULL;
00893 cbdata->header_index = 0;
00894 cbdata->header_search = 0;
00895 strcpy(cbdata->root_id, root_id);
00896 strcpy(cbdata->root_dir, dest_dir);
00897
00898 if (!(message = (struct attachments_t *) malloc(sizeof(struct attachments_t))))
00899 {
00900 log_error2("malloc failed (%s)", strerror(errno));
00901 free(cbdata);
00902 return NULL;
00903 }
00904
00905 cbdata->message = message;
00906 cbdata->message->parts = NULL;
00907 cbdata->message->root_part = NULL;
00908
00909 callbacks.parse_begin_cb = _mime_parse_begin;
00910 callbacks.parse_end_cb = _mime_parse_end;
00911 callbacks.part_begin_cb = _mime_part_begin;
00912 callbacks.part_end_cb = _mime_part_end;
00913 callbacks.received_bytes_cb = _mime_received_bytes;
00914
00915 status = MIME_parse(MIME_filereader_function,
00916 in, boundary, &callbacks, cbdata);
00917
00918 if (status == MIME_PARSER_OK)
00919 {
00920 free(cbdata);
00921 return message;
00922 }
00923 else
00924 {
00925
00926
00927 log_error2("MIME parser error '%s'!",
00928 status ==
00929 MIME_PARSER_READ_ERROR ? "general error" :
00930 "Incomplete message");
00931 return NULL;
00932 }
00933 }
00934
00935 herror_t
00936 mime_get_attachments(content_type_t * ctype, struct http_input_stream_t * in,
00937 struct attachments_t ** dest)
00938 {
00939
00940 struct attachments_t *mimeMessage;
00941 struct part_t *part, *tmp_part = NULL;
00942 char *boundary, *root_id;
00943
00944
00945 if (!(ctype && !strcmp(ctype->type, "multipart/related")))
00946 return herror_new("mime_get_attachments", MIME_ERROR_NOT_MIME_MESSAGE,
00947 "Not a MIME message '%s'", ctype->type);
00948
00949 boundary = hpairnode_get(ctype->params, "boundary");
00950 root_id = hpairnode_get(ctype->params, "start");
00951 if (boundary == NULL)
00952 {
00953
00954 log_error1("'boundary' not set for multipart/related");
00955 return herror_new("mime_get_attachments", MIME_ERROR_NO_BOUNDARY_PARAM,
00956 "'boundary' not set for multipart/related");
00957 }
00958
00959 if (root_id == NULL)
00960 {
00961
00962 log_error1("'start' not set for multipart/related");
00963 return herror_new("mime_get_attachments", MIME_ERROR_NO_START_PARAM,
00964 "'start' not set for multipart/related");
00965 }
00966
00967 mimeMessage = mime_message_parse(in, root_id, boundary, ".");
00968 if (mimeMessage == NULL)
00969 {
00970
00971 log_error1("MIME Parse Error");
00972 return herror_new("mime_get_attachments", MIME_ERROR_PARSE_ERROR,
00973 "MIME Parse Error");
00974 }
00975
00976
00977 if (!mimeMessage->root_part)
00978 {
00979 attachments_free(mimeMessage);
00980 return herror_new("mime_get_attachments", MIME_ERROR_NO_ROOT_PART,
00981 "No root part found!");
00982 }
00983
00984
00985 part = mimeMessage->parts;
00986 while (part)
00987 {
00988 if (part == mimeMessage->root_part)
00989 {
00990 if (tmp_part)
00991 tmp_part->next = part->next;
00992 else
00993 mimeMessage->parts = part->next;
00994
00995 break;
00996 }
00997 tmp_part = part;
00998 part = part->next;
00999 }
01000 *dest = mimeMessage;
01001 return H_OK;
01002 }