static void mime_content_type(MIME_NODE *node, const HEADER_OPTS *header_info) { const char *cp; ssize_t tok_count; MIME_STATE *state = node->state; #define PARSE_CONTENT_TYPE_HEADER(state, ptr) \ header_token(state->token, MIME_MAX_TOKEN, \ state->token_buffer, ptr, RFC2045_TSPECIALS, ';') cp = STR(node->buffer) + strlen(header_info->name) + 1; if ((tok_count = PARSE_CONTENT_TYPE_HEADER(state, &cp)) <= 0) { /* * other/whatever. */ node->ctype = MIME_CTYPE_OTHER; return; } /* tok_count > 0 */ /* * message/whatever body parts start with another block of message * headers that we may want to look at. The partial and external-body * subtypes cannot be subjected to 8-bit -> 7-bit conversion, so we * must properly recognize them. */ if (TOKEN_MATCH(state->token[0], "message")) { node->ctype = MIME_CTYPE_MESSAGE; node->stype = MIME_STYPE_OTHER; if (tok_count >= 3 && state->token[1].type == '/') { if (TOKEN_MATCH(state->token[2], "rfc822")) node->stype = MIME_STYPE_RFC822; else if (TOKEN_MATCH(state->token[2], "partial")) node->stype = MIME_STYPE_PARTIAL; else if (TOKEN_MATCH(state->token[2], "external-body")) node->stype = MIME_STYPE_EXTERN_BODY; } } /* * multipart/digest has default content type message/rfc822, * multipart/whatever has default content type text/plain. */ else if (TOKEN_MATCH(state->token[0], "multipart")) { node->ctype = MIME_CTYPE_MULTIPART; if (tok_count >= 3 && state->token[1].type == '/') { if (TOKEN_MATCH(state->token[2], "digest")) { node->ctype = MIME_CTYPE_MESSAGE; node->stype = MIME_STYPE_RFC822; } else if (TOKEN_MATCH(state->token[2], "alternative")) { node->stype = MIME_STYPE_ALTERNATIVE; } else if (TOKEN_MATCH(state->token[2], "related")) { node->stype = MIME_STYPE_RELATED; } else if (TOKEN_MATCH(state->token[2], "mixed")) { node->stype = MIME_STYPE_MIXED; } else { node->stype = MIME_STYPE_OTHER; } } else { node->ctype = MIME_CTYPE_TEXT; node->stype = MIME_STYPE_PLAIN; } /* * Yes, this is supposed to capture multiple boundary strings, * which are illegal and which could be used to hide content in * an implementation dependent manner. The code below allows us * to find embedded message headers as long as the sender uses * only one of these same-level boundary strings. * * Yes, this is supposed to ignore the boundary value type. */ while ((tok_count = PARSE_CONTENT_TYPE_HEADER(state, &cp)) >= 0) { if (tok_count < 3 || state->token[1].type != '=') continue; if (TOKEN_MATCH(state->token[0], "boundary")) { if (node->boundary == NULL) node->boundary = acl_vstring_alloc(256); /* 需要添加 "--" 做为分隔符的前导符 */ SCP(node->boundary, "--"); SCAT(node->boundary, state->token[2].u.value); break; } } } /* * text/whatever. Right now we don't really care if it is plain or * not, but we may want to recognize subtypes later, and then this * code can serve as an example. */ else if (TOKEN_MATCH(state->token[0], "text")) { node->ctype = MIME_CTYPE_TEXT; if (tok_count >= 3 && state->token[1].type == '/') { if (TOKEN_MATCH(state->token[2], "plain")) node->stype = MIME_STYPE_PLAIN; else if (TOKEN_MATCH(state->token[2], "html")) node->stype = MIME_STYPE_HTML; else node->stype = MIME_STYPE_OTHER; } else node->stype = MIME_STYPE_OTHER; while ((tok_count = PARSE_CONTENT_TYPE_HEADER(state, &cp)) >= 0) { if (tok_count < 3 || state->token[1].type != '=') continue; if (TOKEN_MATCH(state->token[0], "charset") && node->charset == NULL) { node->charset = acl_mystrdup(state->token[2].u.value); break; } } /* 如果没有字符集, 则缺省采用 gb2312 */ if (node->charset == NULL) node->charset = acl_mystrdup("gb2312"); } else if (TOKEN_MATCH(state->token[0], "image")) { node->ctype = MIME_CTYPE_IMAGE; if (tok_count >= 3 && state->token[1].type == '/') { if (TOKEN_MATCH(state->token[2], "jpeg")) node->stype = MIME_STYPE_JPEG; else if (TOKEN_MATCH(state->token[2], "gif")) node->stype = MIME_STYPE_GIF; else if (TOKEN_MATCH(state->token[2], "bmp")) node->stype = MIME_STYPE_BMP; else if (TOKEN_MATCH(state->token[2], "png")) node->stype = MIME_STYPE_PNG; else node->stype = MIME_STYPE_OTHER; } else node->stype = MIME_STYPE_OTHER; while ((tok_count = PARSE_CONTENT_TYPE_HEADER(state, &cp)) >= 0) { if (tok_count < 3 || state->token[1].type != '=') continue; if (TOKEN_MATCH(state->token[0], "name") && node->header_name == NULL) { node->header_name = acl_mystrdup(state->token[2].u.value); break; } } } else if (TOKEN_MATCH(state->token[0], "application")) { node->ctype = MIME_CTYPE_APPLICATION; if (tok_count >= 3 && state->token[1].type == '/') { if (TOKEN_MATCH(state->token[2], "octet-stream")) node->stype = MIME_STYPE_OCTET_STREAM; else node->stype = MIME_STYPE_OTHER; } while ((tok_count = PARSE_CONTENT_TYPE_HEADER(state, &cp)) >= 0) { if (tok_count < 3 || state->token[1].type != '=') continue; if (TOKEN_MATCH(state->token[0], "name") && node->header_name == NULL) { node->header_name = acl_mystrdup(state->token[2].u.value); break; } } } }
string& string::operator +=(const char* s) { SCAT(vbf_, s); return *this; }