123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615 |
- <<<<<<< HEAD
- /* Based on node-formidable by Felix Geisendörfer
- * Igor Afonov - afonov@gmail.com - 2012
- * MIT License - http://www.opensource.org/licenses/mit-license.php
- */
- #include "multipart_parser.h"
- #include <stdio.h>
- #include <stdarg.h>
- #include <string.h>
- static void multipart_log(const char * format, ...)
- {
- #ifdef DEBUG_MULTIPART
- va_list args;
- va_start(args, format);
- fprintf(stderr, "[HTTP_MULTIPART_PARSER] %s:%d: ", __FILE__, __LINE__);
- vfprintf(stderr, format, args);
- fprintf(stderr, "\n");
- #endif
- }
- #define NOTIFY_CB(FOR) \
- do { \
- if (p->settings->on_##FOR) { \
- if (p->settings->on_##FOR(p) != 0) { \
- return i; \
- } \
- } \
- } while (0)
- #define EMIT_DATA_CB(FOR, ptr, len) \
- do { \
- if (p->settings->on_##FOR) { \
- if (p->settings->on_##FOR(p, ptr, len) != 0) { \
- return i; \
- } \
- } \
- } while (0)
- #define LF 10
- #define CR 13
- struct multipart_parser {
- void * data;
- size_t index;
- size_t boundary_length;
- unsigned char state;
- const multipart_parser_settings* settings;
- char* lookbehind;
- char multipart_boundary[1];
- };
- enum state {
- s_uninitialized = 1,
- s_start,
- s_start_boundary,
- s_header_field_start,
- s_header_field,
- s_headers_almost_done,
- s_header_value_start,
- s_header_value,
- s_header_value_almost_done,
- s_part_data_start,
- s_part_data,
- s_part_data_almost_boundary,
- s_part_data_boundary,
- s_part_data_almost_end,
- s_part_data_end,
- s_part_data_final_hyphen,
- s_end
- };
- multipart_parser* multipart_parser_init
- (const char *boundary, const multipart_parser_settings* settings) {
- multipart_parser* p = malloc(sizeof(multipart_parser) +
- strlen(boundary) +
- strlen(boundary) + 9);
- strcpy(p->multipart_boundary, boundary);
- p->boundary_length = strlen(boundary);
-
- p->lookbehind = (p->multipart_boundary + p->boundary_length + 1);
- p->index = 0;
- p->state = s_start;
- p->settings = settings;
- return p;
- }
- void multipart_parser_free(multipart_parser* p) {
- free(p);
- }
- void multipart_parser_set_data(multipart_parser *p, void *data) {
- p->data = data;
- }
- void *multipart_parser_get_data(multipart_parser *p) {
- return p->data;
- }
- size_t multipart_parser_execute(multipart_parser* p, const char *buf, size_t len) {
- size_t i = 0;
- size_t mark = 0;
- char c, cl;
- int is_last = 0;
- while(i < len) {
- c = buf[i];
- is_last = (i == (len - 1));
- switch (p->state) {
- case s_start:
- multipart_log("s_start");
- p->index = 0;
- p->state = s_start_boundary;
- /* fallthrough */
- case s_start_boundary:
- multipart_log("s_start_boundary");
- if (p->index == p->boundary_length) {
- if (c != CR) {
- return i;
- }
- p->index++;
- break;
- } else if (p->index == (p->boundary_length + 1)) {
- if (c != LF) {
- return i;
- }
- p->index = 0;
- NOTIFY_CB(part_data_begin);
- p->state = s_header_field_start;
- break;
- }
- if (c != p->multipart_boundary[p->index]) {
- return i;
- }
- p->index++;
- break;
- case s_header_field_start:
- multipart_log("s_header_field_start");
- mark = i;
- p->state = s_header_field;
- /* fallthrough */
- case s_header_field:
- multipart_log("s_header_field");
- if (c == CR) {
- p->state = s_headers_almost_done;
- break;
- }
- if (c == ':') {
- EMIT_DATA_CB(header_field, buf + mark, i - mark);
- p->state = s_header_value_start;
- break;
- }
- cl = tolower(c);
- if ((c != '-') && (cl < 'a' || cl > 'z')) {
- multipart_log("invalid character in header name");
- return i;
- }
- if (is_last)
- EMIT_DATA_CB(header_field, buf + mark, (i - mark) + 1);
- break;
- case s_headers_almost_done:
- multipart_log("s_headers_almost_done");
- if (c != LF) {
- return i;
- }
- p->state = s_part_data_start;
- break;
- case s_header_value_start:
- multipart_log("s_header_value_start");
- if (c == ' ') {
- break;
- }
- mark = i;
- p->state = s_header_value;
- /* fallthrough */
- case s_header_value:
- multipart_log("s_header_value");
- if (c == CR) {
- EMIT_DATA_CB(header_value, buf + mark, i - mark);
- p->state = s_header_value_almost_done;
- break;
- }
- if (is_last)
- EMIT_DATA_CB(header_value, buf + mark, (i - mark) + 1);
- break;
- case s_header_value_almost_done:
- multipart_log("s_header_value_almost_done");
- if (c != LF) {
- return i;
- }
- p->state = s_header_field_start;
- break;
- case s_part_data_start:
- multipart_log("s_part_data_start");
- NOTIFY_CB(headers_complete);
- mark = i;
- p->state = s_part_data;
- /* fallthrough */
- case s_part_data:
- multipart_log("s_part_data");
- if (c == CR) {
- EMIT_DATA_CB(part_data, buf + mark, i - mark);
- mark = i;
- p->state = s_part_data_almost_boundary;
- p->lookbehind[0] = CR;
- break;
- }
- if (is_last)
- EMIT_DATA_CB(part_data, buf + mark, (i - mark) + 1);
- break;
- case s_part_data_almost_boundary:
- multipart_log("s_part_data_almost_boundary");
- if (c == LF) {
- p->state = s_part_data_boundary;
- p->lookbehind[1] = LF;
- p->index = 0;
- break;
- }
- EMIT_DATA_CB(part_data, p->lookbehind, 1);
- p->state = s_part_data;
- mark = i --;
- break;
- case s_part_data_boundary:
- multipart_log("s_part_data_boundary");
- if (p->multipart_boundary[p->index] != c) {
- EMIT_DATA_CB(part_data, p->lookbehind, 2 + p->index);
- p->state = s_part_data;
- mark = i --;
- break;
- }
- p->lookbehind[2 + p->index] = c;
- if ((++ p->index) == p->boundary_length) {
- NOTIFY_CB(part_data_end);
- p->state = s_part_data_almost_end;
- }
- break;
- case s_part_data_almost_end:
- multipart_log("s_part_data_almost_end");
- if (c == '-') {
- p->state = s_part_data_final_hyphen;
- break;
- }
- if (c == CR) {
- p->state = s_part_data_end;
- break;
- }
- return i;
-
- case s_part_data_final_hyphen:
- multipart_log("s_part_data_final_hyphen");
- if (c == '-') {
- NOTIFY_CB(body_end);
- p->state = s_end;
- break;
- }
- return i;
- case s_part_data_end:
- multipart_log("s_part_data_end");
- if (c == LF) {
- p->state = s_header_field_start;
- NOTIFY_CB(part_data_begin);
- break;
- }
- return i;
- case s_end:
- multipart_log("s_end: %02X", (int) c);
- break;
- default:
- multipart_log("Multipart parser unrecoverable error");
- return 0;
- }
- ++ i;
- }
- return len;
- }
- =======
- /* Based on node-formidable by Felix Geisendörfer
- * Igor Afonov - afonov@gmail.com - 2012
- * MIT License - http://www.opensource.org/licenses/mit-license.php
- */
- #include "multipart_parser.h"
- #include <stdio.h>
- #include <stdarg.h>
- #include <string.h>
- static void multipart_log(const char * format, ...)
- {
- #ifdef DEBUG_MULTIPART
- va_list args;
- va_start(args, format);
- fprintf(stderr, "[HTTP_MULTIPART_PARSER] %s:%d: ", __FILE__, __LINE__);
- vfprintf(stderr, format, args);
- fprintf(stderr, "\n");
- #endif
- }
- #define NOTIFY_CB(FOR) \
- do { \
- if (p->settings->on_##FOR) { \
- if (p->settings->on_##FOR(p) != 0) { \
- return i; \
- } \
- } \
- } while (0)
- #define EMIT_DATA_CB(FOR, ptr, len) \
- do { \
- if (p->settings->on_##FOR) { \
- if (p->settings->on_##FOR(p, ptr, len) != 0) { \
- return i; \
- } \
- } \
- } while (0)
- #define LF 10
- #define CR 13
- struct multipart_parser {
- void * data;
- size_t index;
- size_t boundary_length;
- unsigned char state;
- const multipart_parser_settings* settings;
- char* lookbehind;
- char multipart_boundary[1];
- };
- enum state {
- s_uninitialized = 1,
- s_start,
- s_start_boundary,
- s_header_field_start,
- s_header_field,
- s_headers_almost_done,
- s_header_value_start,
- s_header_value,
- s_header_value_almost_done,
- s_part_data_start,
- s_part_data,
- s_part_data_almost_boundary,
- s_part_data_boundary,
- s_part_data_almost_end,
- s_part_data_end,
- s_part_data_final_hyphen,
- s_end
- };
- multipart_parser* multipart_parser_init
- (const char *boundary, const multipart_parser_settings* settings) {
- multipart_parser* p = malloc(sizeof(multipart_parser) +
- strlen(boundary) +
- strlen(boundary) + 9);
- strcpy(p->multipart_boundary, boundary);
- p->boundary_length = strlen(boundary);
-
- p->lookbehind = (p->multipart_boundary + p->boundary_length + 1);
- p->index = 0;
- p->state = s_start;
- p->settings = settings;
- return p;
- }
- void multipart_parser_free(multipart_parser* p) {
- free(p);
- }
- void multipart_parser_set_data(multipart_parser *p, void *data) {
- p->data = data;
- }
- void *multipart_parser_get_data(multipart_parser *p) {
- return p->data;
- }
- size_t multipart_parser_execute(multipart_parser* p, const char *buf, size_t len) {
- size_t i = 0;
- size_t mark = 0;
- char c, cl;
- int is_last = 0;
- while(i < len) {
- c = buf[i];
- is_last = (i == (len - 1));
- switch (p->state) {
- case s_start:
- multipart_log("s_start");
- p->index = 0;
- p->state = s_start_boundary;
- /* fallthrough */
- case s_start_boundary:
- multipart_log("s_start_boundary");
- if (p->index == p->boundary_length) {
- if (c != CR) {
- return i;
- }
- p->index++;
- break;
- } else if (p->index == (p->boundary_length + 1)) {
- if (c != LF) {
- return i;
- }
- p->index = 0;
- NOTIFY_CB(part_data_begin);
- p->state = s_header_field_start;
- break;
- }
- if (c != p->multipart_boundary[p->index]) {
- return i;
- }
- p->index++;
- break;
- case s_header_field_start:
- multipart_log("s_header_field_start");
- mark = i;
- p->state = s_header_field;
- /* fallthrough */
- case s_header_field:
- multipart_log("s_header_field");
- if (c == CR) {
- p->state = s_headers_almost_done;
- break;
- }
- if (c == ':') {
- EMIT_DATA_CB(header_field, buf + mark, i - mark);
- p->state = s_header_value_start;
- break;
- }
- cl = tolower(c);
- if ((c != '-') && (cl < 'a' || cl > 'z')) {
- multipart_log("invalid character in header name");
- return i;
- }
- if (is_last)
- EMIT_DATA_CB(header_field, buf + mark, (i - mark) + 1);
- break;
- case s_headers_almost_done:
- multipart_log("s_headers_almost_done");
- if (c != LF) {
- return i;
- }
- p->state = s_part_data_start;
- break;
- case s_header_value_start:
- multipart_log("s_header_value_start");
- if (c == ' ') {
- break;
- }
- mark = i;
- p->state = s_header_value;
- /* fallthrough */
- case s_header_value:
- multipart_log("s_header_value");
- if (c == CR) {
- EMIT_DATA_CB(header_value, buf + mark, i - mark);
- p->state = s_header_value_almost_done;
- break;
- }
- if (is_last)
- EMIT_DATA_CB(header_value, buf + mark, (i - mark) + 1);
- break;
- case s_header_value_almost_done:
- multipart_log("s_header_value_almost_done");
- if (c != LF) {
- return i;
- }
- p->state = s_header_field_start;
- break;
- case s_part_data_start:
- multipart_log("s_part_data_start");
- NOTIFY_CB(headers_complete);
- mark = i;
- p->state = s_part_data;
- /* fallthrough */
- case s_part_data:
- multipart_log("s_part_data");
- if (c == CR) {
- EMIT_DATA_CB(part_data, buf + mark, i - mark);
- mark = i;
- p->state = s_part_data_almost_boundary;
- p->lookbehind[0] = CR;
- break;
- }
- if (is_last)
- EMIT_DATA_CB(part_data, buf + mark, (i - mark) + 1);
- break;
- case s_part_data_almost_boundary:
- multipart_log("s_part_data_almost_boundary");
- if (c == LF) {
- p->state = s_part_data_boundary;
- p->lookbehind[1] = LF;
- p->index = 0;
- break;
- }
- EMIT_DATA_CB(part_data, p->lookbehind, 1);
- p->state = s_part_data;
- mark = i --;
- break;
- case s_part_data_boundary:
- multipart_log("s_part_data_boundary");
- if (p->multipart_boundary[p->index] != c) {
- EMIT_DATA_CB(part_data, p->lookbehind, 2 + p->index);
- p->state = s_part_data;
- mark = i --;
- break;
- }
- p->lookbehind[2 + p->index] = c;
- if ((++ p->index) == p->boundary_length) {
- NOTIFY_CB(part_data_end);
- p->state = s_part_data_almost_end;
- }
- break;
- case s_part_data_almost_end:
- multipart_log("s_part_data_almost_end");
- if (c == '-') {
- p->state = s_part_data_final_hyphen;
- break;
- }
- if (c == CR) {
- p->state = s_part_data_end;
- break;
- }
- return i;
-
- case s_part_data_final_hyphen:
- multipart_log("s_part_data_final_hyphen");
- if (c == '-') {
- NOTIFY_CB(body_end);
- p->state = s_end;
- break;
- }
- return i;
- case s_part_data_end:
- multipart_log("s_part_data_end");
- if (c == LF) {
- p->state = s_header_field_start;
- NOTIFY_CB(part_data_begin);
- break;
- }
- return i;
- case s_end:
- multipart_log("s_end: %02X", (int) c);
- break;
- default:
- multipart_log("Multipart parser unrecoverable error");
- return 0;
- }
- ++ i;
- }
- return len;
- }
- >>>>>>> 08a3f61f844fd56297a491016c3f540974b6f434
|