static const char *xml_parse_left_tag(ACL_XML *xml, const char *data) { int ch; if (LEN(xml->curr_node->ltag) == 0) { SKIP_SPACE(data); } while ((ch = *data) != 0) { data++; if (ch == '>') { xml->curr_node->status = ACL_XML_S_LGT; xml_parse_check_self_closed(xml); if ((xml->curr_node->flag & ACL_XML_F_SELF_CL) && xml->curr_node->last_ch == '/') { acl_vstring_truncate(xml->curr_node->ltag, LEN(xml->curr_node->ltag) - 1); } break; } else if (IS_SPACE(ch)) { xml->curr_node->status = ACL_XML_S_ATTR; xml->curr_node->last_ch = ch; break; } else { ACL_VSTRING_ADDCH(xml->curr_node->ltag, ch); xml->curr_node->last_ch = ch; } } ACL_VSTRING_TERMINATE(xml->curr_node->ltag); return (data); }
static void mime_header_line(MIME_NODE *node) { const HEADER_OPTS *header_info; size_t len = LEN(node->buffer); char *ptr = strrchr(STR(node->buffer), '\n'); if (ptr) { *ptr-- = 0; len--; if (ptr > STR(node->buffer)) { if (*ptr == '\r') { *ptr = 0; len--; } } if (len == 0) return; acl_vstring_truncate(node->buffer, len); } header_info = header_opts_find(STR(node->buffer), node->state->key_buffer); if (header_info) { if (header_info->type == HDR_CONTENT_TYPE) mime_content_type(node, header_info); else if (header_info->type == HDR_CONTENT_TRANSFER_ENCODING) mime_content_encoding(node, header_info); else if (node == node->state->root) { /* 说明邮件头 */ if ((header_info->flags & HDR_OPT_RECIP) && (header_info->flags & HDR_OPT_EXTRACT)) { /* 分析收件人地址: To, Cc, Bcc */ mail_rcpt(node, header_info); } else if ((header_info->flags & HDR_OPT_SENDER)) { /* 分析发件人地址: From, Sender, * Replyto, Returnpath */ mail_from(node, header_info); } else if ((header_info->flags & HDR_OPT_SUBJECT)) { mail_subject(node, header_info); } } else if (header_info->type == HDR_CONTENT_DISPOSITION) { mime_content_disposition(node, header_info); } } if (node->header_list) { HEADER_NV *header = header_split(STR(node->buffer)); if (header) node->header_list->push_back(node->header_list, header); } ACL_VSTRING_RESET(node->buffer); /* 清空缓冲区 */ node->last_ch = 0; node->last_lf = 0; }
void mime_state_downgrade(MIME_STATE *state, int rec_type, const char *text, ssize_t len) { static char hexchars[] = "0123456789ABCDEF"; const unsigned char *cp; MIME_NODE *node = state->curr_node; int ch; #define CU_CHAR_PTR(x) ((const unsigned char *) (x)) #define QP_ENCODE(buffer, ch) { \ buffer += '='; \ buffer += (char) hexchars[(ch >> 4) & 0xff]; \ buffer += (char) hexchars[ch & 0xf]; \ } /* * Insert a soft line break when the output reaches a critical length * before we reach a hard line break. */ for (cp = CU_CHAR_PTR(text); cp < CU_CHAR_PTR(text + len); cp++) { /* Critical length before hard line break. */ if (LEN(node->buffer) > 72) { node->buffer += '='; } /* Append the next character. */ ch = *cp; if ((ch < 32 && ch != '\t') || ch == '=' || ch > 126) { QP_ENCODE(node->buffer, ch); } else { ADDCH(node->buffer, ch); } } /* * Flush output after a hard line break (i.e. the end of a REC_TYPE_NORM * record). Fix trailing whitespace as per the RFC: in the worst case, * the output length will grow from 73 characters to 75 characters. */ if (rec_type == REC_TYPE_NORM) { if (LEN(node->buffer) > 0 && ((ch = END(node->buffer)[-1]) == ' ' || ch == '\t')) { acl_vstring_truncate(node->buffer, LEN(node->buffer) - 1); QP_ENCODE(node->buffer, ch); } ACL_VSTRING_TERMINATE(node->buffer); } }
const char *str_name_mask_opt(ACL_VSTRING *buf, const char *context, const NAME_MASK *table, int mask, int flags) { const char *myname = "name_mask"; const NAME_MASK *np; int len; static ACL_VSTRING *my_buf = 0; int delim = (flags & NAME_MASK_COMMA ? ',' : (flags & NAME_MASK_PIPE ? '|' : ' ')); if (buf == 0) { if (my_buf == 0) my_buf = acl_vstring_alloc(1); buf = my_buf; } ACL_VSTRING_RESET(buf); for (np = table; mask != 0; np++) { if (np->name == 0) { if (flags & NAME_MASK_FATAL) { acl_msg_fatal("%s: unknown %s bit in mask: 0x%x", myname, context, mask); } else if (flags & NAME_MASK_RETURN) { acl_msg_warn("%s: unknown %s bit in mask: 0x%x", myname, context, mask); return (0); } else if (flags & NAME_MASK_NUMBER) { acl_vstring_sprintf_append(buf, "0x%x%c", mask, delim); } break; } if (mask & np->mask) { mask &= ~np->mask; acl_vstring_sprintf_append(buf, "%s%c", np->name, delim); } } if ((len = (int) ACL_VSTRING_LEN(buf)) > 0) acl_vstring_truncate(buf, len - 1); ACL_VSTRING_TERMINATE(buf); return (STR(buf)); }
static void strip_address(ACL_VSTRING *vp, ssize_t start, TOK822 *addr) { ACL_VSTRING *tmp; /* * Emit plain <address>. Discard any comments or phrases. */ ACL_VSTRING_TERMINATE(vp); acl_msg_warn("stripping too many comments from address: %.100s...", acl_vstring_str(vp) + start); //acl_printable(vstring_str(vp) + start, '?')); //zsx acl_vstring_truncate(vp, start); ACL_VSTRING_ADDCH(vp, '<'); if (addr) { tmp = acl_vstring_alloc(100); tok822_internalize(tmp, addr, TOK822_STR_TERM); quote_822_local_flags(vp, acl_vstring_str(tmp), QUOTE_FLAG_8BITCLEAN | QUOTE_FLAG_APPEND); acl_vstring_free(tmp); } ACL_VSTRING_ADDCH(vp, '>'); }
ssize_t header_token(HEADER_TOKEN *token, ssize_t token_len, ACL_VSTRING *token_buffer, const char **ptr, const char *user_specials, int user_terminator) { ssize_t comment_level; const unsigned char *cp; ssize_t len; int ch; ssize_t tok_count; ssize_t n; /* * Initialize. */ ACL_VSTRING_RESET(token_buffer); cp = CU_CHAR_PTR(*ptr); tok_count = 0; if (user_specials == 0) user_specials = LEX_822_SPECIALS; /* * Main parsing loop. * * XXX What was the reason to continue parsing when user_terminator is * specified? Perhaps this was needed at some intermediate stage of * development? */ while ((ch = *cp) != 0 && (user_terminator != 0 || tok_count < token_len)) { cp++; /* * Skip RFC 822 linear white space. */ if (IS_SPACE_TAB_CR_LF(ch)) continue; /* * Terminator. */ if (ch == user_terminator) break; /* * Skip RFC 822 comment. */ if (ch == '(') { comment_level = 1; while ((ch = *cp) != 0) { cp++; if (ch == '(') { /* comments can nest! */ comment_level++; } else if (ch == ')') { if (--comment_level == 0) break; } else if (ch == '\\') { if ((ch = *cp) == 0) break; cp++; } } continue; } /* * Copy quoted text according to RFC 822. */ if (ch == '"') { if (tok_count < token_len) { token[tok_count].u.offset = LEN(token_buffer); token[tok_count].type = HEADER_TOK_QSTRING; } while ((ch = *cp) != 0) { cp++; if (ch == '"') break; if (ch == '\n') { /* unfold */ if (tok_count < token_len) { len = LEN(token_buffer); while (len > 0 && IS_SPACE_TAB_CR_LF(STR(token_buffer)[len - 1])) len--; if (len < (ssize_t) LEN(token_buffer)) acl_vstring_truncate(token_buffer, len); } continue; } if (ch == '\\') { if (tok_count < token_len) ACL_VSTRING_ADDCH(token_buffer, ch); if (*cp == 0) break; ch = *cp; cp++; } if (tok_count < token_len) ACL_VSTRING_ADDCH(token_buffer, ch); } if (tok_count < token_len) { ACL_VSTRING_ADDCH(token_buffer, 0); tok_count++; } continue; } /* * Control, or special. */ if (strchr(user_specials, ch) || ACL_ISCNTRL(ch)) { if (tok_count < token_len) { token[tok_count].u.offset = LEN(token_buffer); token[tok_count].type = ch; ACL_VSTRING_ADDCH(token_buffer, ch); ACL_VSTRING_ADDCH(token_buffer, 0); tok_count++; } continue; } /* * Token. */ else { if (tok_count < token_len) { token[tok_count].u.offset = LEN(token_buffer); token[tok_count].type = HEADER_TOK_TOKEN; ACL_VSTRING_ADDCH(token_buffer, ch); } while ((ch = *cp) != 0 && !IS_SPACE_TAB_CR_LF(ch) && !ACL_ISCNTRL(ch) && !strchr(user_specials, ch)) { cp++; if (tok_count < token_len) ACL_VSTRING_ADDCH(token_buffer, ch); } if (tok_count < token_len) { ACL_VSTRING_ADDCH(token_buffer, 0); tok_count++; } continue; } } /* * Ignore a zero-length item after the last terminator. */ if (tok_count == 0 && ch == 0) return (-1); /* * Finalize. Fill in the string pointer array, now that the token buffer * is no longer dynamically reallocated as it grows. */ *ptr = (const char *) cp; for (n = 0; n < tok_count; n++) token[n].u.value = STR(token_buffer) + token[n].u.offset; //if (acl_msg_verbose) // acl_msg_info("header_token: %s %s %s", // tok_count > 0 ? token[0].u.value : "", // tok_count > 1 ? token[1].u.value : "", // tok_count > 2 ? token[2].u.value : ""); return (tok_count); }