📄 wap_push_pap_mime.c
字号:
* Control entity headers must contain Content-Type: application/xml headers. * Rfc 2045, Appendix A does not specify the order of entity headers and states * that all rfc 822 headers having a string "Content" in their field-name must * be accepted. Rfc 822 grammar is capitulated in appendix D. * Message starts after the first null line, so only something after it can be * an extension header (or any header). */static int check_control_headers(Octstr **body_part){ if (check_control_content_type_header(body_part, octstr_imm("\r\n\r\n")) == 0) return 0; if (drop_optional_header(body_part, "Content-Transfer-Encoding:", octstr_imm("\r\n\r\n")) == 0) return 0; if (drop_optional_header(body_part, "Content-ID:", octstr_imm("\r\n\r\n")) == 0) return 0; if (drop_optional_header(body_part, "Content-Description:", octstr_imm("\r\n\r\n")) == 0) return 0; if (drop_extension_headers(body_part, octstr_imm("\r\n\r\n")) == 0) return 0; return 1;}static int check_control_content_type_header(Octstr **body_part, Octstr *boundary){ long content_pos; long message_start_pos; message_start_pos = octstr_search(*body_part, boundary, 0); if ((content_pos = octstr_case_nsearch(*body_part, octstr_imm("Content-Type:"), 0, message_start_pos)) < 0 || octstr_case_search(*body_part, octstr_imm("application/xml"), 0) < 0) { return 0; } if (drop_header_true(body_part, content_pos) < 0) return 0; return 1;}/* * This function actually removes a header (deletes corresponding part from * the octet string body_part), in addition of all stuff prepending it. So * deleting start from the octet 0. Content_pos tells where the header starts. */static int drop_header_true(Octstr **body_part, long content_pos) { long next_header_pos; next_header_pos = -1; if ((next_header_pos = parse_field_value(*body_part, content_pos)) == 0) return 0; if ((next_header_pos = parse_terminator(*body_part, next_header_pos)) == 0) return 0; octstr_delete(*body_part, 0, next_header_pos); return 1;}static int drop_optional_header(Octstr **body_part, char *name, Octstr *boundary){ long content_pos; long message_start_pos; content_pos = -1; message_start_pos = octstr_search(*body_part, boundary, 0); if ((content_pos = octstr_case_nsearch(*body_part, octstr_imm(name), 0, message_start_pos)) < 0) return 1; if (drop_header_true(body_part, content_pos) < 0) return 0; return 1;}/* * Extension headers are defined in rfc 822, Appendix D, as fields. We must * parse all rfc 822 headers containing a string "Content". These headers * are optional, too. For general definition of message parts see chapter 4.1. * Specifically: "everything after first null line is message body". */static int drop_extension_headers(Octstr **body_part, Octstr *boundary){ long content_pos, next_header_pos; long next_content_part_pos; next_content_part_pos = octstr_case_search(*body_part, boundary, 0); do { if ((content_pos = octstr_case_nsearch(*body_part, octstr_imm("Content"), 0, next_content_part_pos)) < 0) return 1; if ((next_header_pos = parse_field_name(*body_part, content_pos)) < 0) return 0; if ((next_header_pos = parse_field_value(*body_part, next_header_pos)) < 0) return 0; if ((next_header_pos = parse_terminator(*body_part, next_header_pos)) == 0) return 0; } while (islwspchar(octstr_get_char(*body_part, next_header_pos))); octstr_delete(*body_part, content_pos, next_header_pos - content_pos); return 1;}static long parse_field_value(Octstr *pap_content, long pos){ int c; while (!is_cr(c = octstr_get_char(pap_content, pos)) && pos < octstr_len(pap_content)) { ++pos; } if (is_lf(c)) { if (is_lf(octstr_get_char(pap_content, pos))) { ++pos; } else { return -1; } } if (pos == octstr_len(pap_content)) { return -1; } return pos;}static long parse_field_name(Octstr *content, long pos){ while (octstr_get_char(content, pos) != ':' && pos < octstr_len(content)) ++pos; if (pos == octstr_len(content)) return -1; return pos;}/* * Transfer entity headers of a body part (it is, from the content entity) * to a header list. Push Message, chapter 6.2.1.10 states that Content-Type * header is mandatory. * Message proper starts after first empty line. We search only to it, and * remove the line here. * Return 0 when error, 1 otherwise. In addition, return the modified body * part and content headers. */static int pass_data_headers(Octstr **body_part, List **data_headers){ *data_headers = http_create_empty_headers(); if (check_data_content_type_header(body_part, data_headers, octstr_imm("\r\n\r\n")) == 0) { warning(0, "MIME: pass_data_headers: Content-Type header missing"); return 0; } if (pass_optional_header(body_part, "Content-Transfer-Encoding", data_headers, octstr_imm("\r\n\r\n")) < 0) goto operror; if (pass_optional_header(body_part, "Content-ID", data_headers, octstr_imm("\r\n\r\n")) < 0) goto operror; if (pass_optional_header(body_part, "Content-Description", data_headers, octstr_imm("\r\n\r\n")) < 0) goto operror; if (pass_extension_headers(body_part, data_headers, octstr_imm("\r\n\r\n")) == 0) goto operror; octstr_delete(*body_part, 0, octstr_len(octstr_imm("\r\n"))); return 1;operror: warning(0, "MIME: pass_data_headers: an unparsable optional header"); return 0;}/* * Checks if body_part contains a Content-Type header. Tranfers this header to * a list content_headers. (Only part before 'boundary'). * Return 1, when Content-Type headers was found, 0 otherwise */static int check_data_content_type_header(Octstr **body_part, List **content_headers, Octstr *boundary){ long header_pos, next_header_pos; Octstr *content_header; long message_start_pos; header_pos = next_header_pos = -1; content_header = octstr_create("Content-Type"); message_start_pos = octstr_search(*body_part, boundary, 0); if ((header_pos = octstr_case_nsearch(*body_part, content_header, 0, message_start_pos)) < 0) { goto error; } if ((next_header_pos = pass_field_value(body_part, &content_header, header_pos + octstr_len(content_header))) < 0) { goto error; } if ((next_header_pos = parse_terminator(*body_part, next_header_pos)) < 0) { goto error; } octstr_delete(*body_part, header_pos, next_header_pos - header_pos); list_append(*content_headers, octstr_duplicate(content_header)); octstr_destroy(content_header); return 1;error: octstr_destroy(content_header); return 0;}/* * We try to find an optional header, so a failure to find one is not an * error. Return -1 when error, 0 when header name not found, 1 otherwise. * Search only until 'boundary'. */static int pass_optional_header(Octstr **body_part, char *name, List **content_headers, Octstr *boundary){ long content_pos, next_header_pos; Octstr *osname, *osvalue; long message_start_pos; content_pos = next_header_pos = -1; osname = octstr_create(name); osvalue = octstr_create(""); message_start_pos = octstr_search(*body_part, boundary, 0); if ((content_pos = octstr_case_nsearch(*body_part, osname, 0, message_start_pos)) < 0) goto noheader; if ((next_header_pos = pass_field_value(body_part, &osvalue, content_pos + octstr_len(osname))) < 0) goto error; if ((next_header_pos = parse_terminator(*body_part, next_header_pos)) == 0) goto error; drop_separator(&osvalue, &next_header_pos); http_header_add(*content_headers, name, octstr_get_cstr(osvalue)); octstr_delete(*body_part, content_pos, next_header_pos - content_pos); octstr_destroy(osname); octstr_destroy(osvalue); return 1;error: octstr_destroy(osvalue); octstr_destroy(osname); return -1;noheader: octstr_destroy(osvalue); octstr_destroy(osname); return 0;}/* * Remove ':' plus spaces from the header value */static void drop_separator(Octstr **header_value, long *pos){ long count; octstr_delete(*header_value, 0, 1); /* remove :*/ count = octstr_drop_leading_blanks(header_value); pos = pos - 1 - count;} /* * Return number of spaces dropped. */static long octstr_drop_leading_blanks(Octstr **header_value){ long count; count = 0; while (octstr_get_char(*header_value, 0) == ' ') { octstr_delete(*header_value, 0, 1); ++count; } return count;}/* * Extension headers are optional, see Push Message, chapter 6.2. Field struc- * ture is defined in rfc 822, chapter 3.2. Extension headers are defined in * rfc 2045, chapter 9, grammar in appendix A. (Only to the next null line). * Return 0 when error, 1 otherwise. */static int pass_extension_headers(Octstr **body_part, List **content_headers, Octstr *boundary){ long next_field_part_pos, count; Octstr *header_name, *header_value; long next_content_part_pos; header_name = octstr_create(""); header_value = octstr_create(""); count = 0; next_field_part_pos = 0; next_content_part_pos = octstr_search(*body_part, boundary, 0); do { if ((octstr_case_nsearch(*body_part, octstr_imm("Content"), 0, next_content_part_pos)) < 0) goto end; if ((next_field_part_pos = pass_field_name(body_part, &header_name, next_field_part_pos)) < 0) goto error; if ((next_field_part_pos = pass_field_value(body_part, &header_value, next_field_part_pos)) < 0) goto error; if ((next_field_part_pos = parse_terminator(*body_part, next_field_part_pos)) == 0) goto error; drop_separator(&header_value, &next_field_part_pos); http_header_add(*content_headers, octstr_get_cstr(header_name), octstr_get_cstr(header_value)); } while (islwspchar(octstr_get_char(*body_part, next_field_part_pos))); octstr_delete(*body_part, 0, next_field_part_pos);/* * An intentional fall-through. We must eventually use a function for memory * cleaning. */end: octstr_destroy(header_name); octstr_destroy(header_value); return 1;error: octstr_destroy(header_name); octstr_destroy(header_value); return 0;}static long pass_field_value(Octstr **body_part, Octstr **header, long pos){ int c; long start; Octstr *field = NULL; start = pos; while (!is_cr(c = octstr_get_char(*body_part, pos)) && pos < octstr_len(*body_part)) { ++pos; } if (pos == octstr_len(*body_part)) { return -1; } field = octstr_copy(*body_part, start, pos - start); octstr_append(*header, field); octstr_destroy(field); return pos;}static long pass_field_name(Octstr **body_part, Octstr **field_part, long pos){ int c; long start; Octstr *name = NULL; start = pos; while (((c = octstr_get_char(*body_part, pos)) != ':') && pos < octstr_len(*body_part)) { ++pos; } if (pos == octstr_len(*body_part)) { return -1; } name = octstr_copy(*body_part, start, pos - start); octstr_append(*field_part, name); octstr_destroy(name); return pos;}/* This is actually CRLF epilogue. */static int parse_epilogue(Octstr **mime_content){ long pos; if (octstr_len(*mime_content) == 0) return 0; if ((pos = parse_terminator(*mime_content, 0)) < 0) return -1; octstr_delete(*mime_content, 0, octstr_len(*mime_content)); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -