static void acl_xml_node_reset(ACL_XML_NODE *node) { ACL_VSTRING_RESET(node->ltag); ACL_VSTRING_RESET(node->rtag); ACL_VSTRING_RESET(node->text); ACL_VSTRING_TERMINATE(node->ltag); ACL_VSTRING_TERMINATE(node->rtag); ACL_VSTRING_TERMINATE(node->text); node->id = NULL; if (node->attr_list) acl_array_clean(node->attr_list, (void (*)(void*)) acl_xml_attr_free); node->parent = NULL; acl_ring_init(&node->children); node->depth = 0; acl_ring_init(&node->node); node->curr_attr = NULL; node->quote = 0; node->last_ch = 0; node->nlt = 0; node->meta[0] = 0; node->flag = 0; node->status = ACL_XML_S_NXT; }
static void incr_string(ACL_VSTRING *vp, int len, const char* s, int debug) { int i; printf("max: %ld, len: %ld, cnt: %ld\r\n", (long) vp->maxlen, vp->vbuf.len, vp->vbuf.cnt); for (i = 0; i < len; i++) ACL_VSTRING_ADDCH(vp, 'x'); if (s && *s) acl_vstring_sprintf_append(vp, "%s", s); else ACL_VSTRING_TERMINATE(vp); if (debug) printf("[%s]\r\n", acl_vstring_str(vp)); printf("strlen: %ld, ACL_VSTRING_LEN: %ld, max: %ld\r\n", (long) strlen(acl_vstring_str(vp)), (long) ACL_VSTRING_LEN(vp), (long) vp->maxlen); printf("Enter any key to continue ...\r\n\r\n"); getchar(); ACL_VSTRING_RESET(vp); ACL_VSTRING_TERMINATE(vp); }
static void __hdr_reset(HTTP_HDR_REQ *hh, int clear_cookies) { hh->port = 80; hh->method[0] = 0; hh->host[0] = 0; hh->flag = 0; if (hh->url_part) { ACL_VSTRING_RESET(hh->url_part); ACL_VSTRING_TERMINATE(hh->url_part); } if (hh->url_path) { ACL_VSTRING_RESET(hh->url_path); ACL_VSTRING_TERMINATE(hh->url_path); } if (hh->url_params) { ACL_VSTRING_RESET(hh->url_params); ACL_VSTRING_TERMINATE(hh->url_params); } if (hh->file_path) { ACL_VSTRING_RESET(hh->file_path); ACL_VSTRING_TERMINATE(hh->file_path); } if (hh->params_table) acl_htable_reset(hh->params_table, __request_args_free_fn); if (clear_cookies && hh->cookies_table) acl_htable_reset(hh->cookies_table, __cookies_args_free_fn); }
static const char *xml_parse_meta_text(ACL_XML *xml, const char *data) { int ch; if (LEN(xml->curr_node->text) == 0) { SKIP_SPACE(data); } while ((ch = *data) != 0) { if (xml->curr_node->quote) { if (ch == xml->curr_node->quote) { xml->curr_node->quote = 0; } ACL_VSTRING_ADDCH(xml->curr_node->text, ch); } else if (IS_QUOTE(ch)) { if (xml->curr_node->quote == 0) { xml->curr_node->quote = ch; } ACL_VSTRING_ADDCH(xml->curr_node->text, ch); } else if (ch == '<') { xml->curr_node->nlt++; ACL_VSTRING_ADDCH(xml->curr_node->text, ch); } else if (ch == '>') { if (xml->curr_node->nlt == 0) { char *last; size_t off; data++; xml->curr_node->status = ACL_XML_S_MEND; if ((xml->curr_node->flag & ACL_XML_F_META_QM) == 0) break; last = acl_vstring_end(xml->curr_node->text) - 1; if (last < STR(xml->curr_node->text) || *last != '?') break; off = ACL_VSTRING_LEN(xml->curr_node->text) - 1; if (off == 0) break; ACL_VSTRING_AT_OFFSET(xml->curr_node->text, off); ACL_VSTRING_TERMINATE(xml->curr_node->text); xml_meta_attr(xml->curr_node); break; } xml->curr_node->nlt--; ACL_VSTRING_ADDCH(xml->curr_node->text, ch); } else { ACL_VSTRING_ADDCH(xml->curr_node->text, ch); } data++; } ACL_VSTRING_TERMINATE(xml->curr_node->text); return (data); }
int acl_xml_decode(const char *in, ACL_VSTRING *out) { int n = 0, len; const char *ptr = in, *pre; const ACL_TOKEN *token; const XML_SPEC *spec; acl_pthread_once(&__token_once, xml_decode_init); if (__token_tree == NULL) acl_msg_fatal("__token_tree null"); while (*ptr != 0) { pre = ptr; token = acl_token_tree_match(__token_tree, &ptr, NULL, NULL); if (token == NULL) { pre = markup_unescape(pre, out); len = (int) (ptr - pre); if (len > 0) acl_vstring_memcat(out, pre, len); break; } spec = (const XML_SPEC*) token->ctx; acl_assert(spec != NULL); len = (int) (ptr - pre - spec->len); if (len > 0) acl_vstring_memcat(out, pre, len); acl_vstring_strcat(out, spec->str); n++; } ACL_VSTRING_TERMINATE(out); return (n); }
static const char *xml_parse_left_em(ACL_XML *xml, const char *data) { if (*data == '-') { if (xml->curr_node->meta[1] != '-') { xml->curr_node->meta[1] = '-'; } else if (xml->curr_node->meta[2] != '-') { xml->curr_node->meta[0] = 0; xml->curr_node->meta[1] = 0; xml->curr_node->meta[2] = 0; xml->curr_node->flag |= ACL_XML_F_META_CM; xml->curr_node->status = ACL_XML_S_MCMT; } data++; } else { if (xml->curr_node->meta[1] == '-') { ACL_VSTRING_ADDCH(xml->curr_node->ltag, '-'); xml->curr_node->meta[1] = 0; } xml->curr_node->flag |= ACL_XML_F_META_EM; xml->curr_node->status = ACL_XML_S_MTAG; } ACL_VSTRING_TERMINATE(xml->curr_node->ltag); return (data); }
ACL_VSTRING *acl_hex_decode(ACL_VSTRING *result, const char *in, int len) { const unsigned char *cp; int count; unsigned int hex; unsigned int bin; ACL_VSTRING_RESET(result); for (cp = UCHAR_PTR(in), count = len; count > 0; cp += 2, count -= 2) { if (count < 2) return (0); hex = cp[0]; if (hex >= '0' && hex <= '9') bin = (hex - '0') << 4; else if (hex >= 'A' && hex <= 'F') bin = (hex - 'A' + 10) << 4; else if (hex >= 'a' && hex <= 'f') bin = (hex - 'a' + 10) << 4; else return (0); hex = cp[1]; if (hex >= '0' && hex <= '9') bin |= (hex - '0') ; else if (hex >= 'A' && hex <= 'F') bin |= (hex - 'A' + 10) ; else if (hex >= 'a' && hex <= 'f') bin |= (hex - 'a' + 10) ; else return (0); ACL_VSTRING_ADDCH(result, bin); } ACL_VSTRING_TERMINATE(result); return (result); }
void acl_token_name(const ACL_TOKEN *token, ACL_VSTRING *buf) { int i, n; char *ptr, *pend, ch; const ACL_TOKEN *token_iter; ACL_VSTRING_RESET(buf); token_iter = token; while (token_iter && token_iter->parent != NULL) { ACL_VSTRING_ADDCH(buf, token_iter->ch); token_iter = token_iter->parent; } ACL_VSTRING_TERMINATE(buf); pend = acl_vstring_end(buf) - 1; ptr = STR(buf); i = 0; n = (int) (pend - ptr + 1) / 2; while (i < n) { ch = *ptr; *ptr = *pend; *pend = ch; i++; ptr++; pend--; } }
static const char *tok822_comment(TOK822 *tp, const char *str) { int level = 1; int ch; /* * XXX We cheat by storing comments in their external form. Otherwise it * would be a royal pain to preserve \ before (. That would require a * recursive parser; the easy to implement stack-based recursion would be * too expensive. */ ACL_VSTRING_ADDCH(tp->vstr, '('); while ((ch = *(const unsigned char *) str) != 0) { ACL_VSTRING_ADDCH(tp->vstr, ch); str++; if (ch == '(') { /* comments can nest! */ level++; } else if (ch == ')') { if (--level == 0) break; } else if (ch == '\\') { if ((ch = *(unsigned char *) str) == 0) break; ACL_VSTRING_ADDCH(tp->vstr, ch); str++; } } ACL_VSTRING_TERMINATE(tp->vstr); return (str); }
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 const char *xml_meta_attr_value(ACL_XML_ATTR *attr, const char *data) { int ch; SKIP_SPACE(data); if (*data == 0) return data; if (IS_QUOTE(*data)) attr->quote = *data++; while ((ch = *data) != 0) { if (attr->backslash) { if (ch == 'b') ADDCH(attr->value, '\b'); else if (ch == 'f') ADDCH(attr->value, '\f'); else if (ch == 'n') ADDCH(attr->value, '\n'); else if (ch == 'r') ADDCH(attr->value, '\r'); else if (ch == 't') ADDCH(attr->value, '\t'); else ADDCH(attr->value, ch); attr->backslash = 0; } else if (ch == '\\') { if (attr->part_word) { ADDCH(attr->value, ch); attr->part_word = 0; } else attr->backslash = 1; } else if (attr->quote) { if (ch == attr->quote) { data++; break; } ADDCH(attr->value, ch); } else if (IS_SPACE(ch)) { data++; break; } else { ADDCH(attr->value, ch); if ((attr->node->xml->flag & ACL_XML_FLAG_PART_WORD)) { if (attr->part_word) attr->part_word = 0; else if (ch < 0) attr->part_word = 1; } } data++; } ACL_VSTRING_TERMINATE(attr->value); return data; }
ACL_VSTRING *acl_hex_encode(ACL_VSTRING *result, const char *in, int len) { const unsigned char *cp; int ch; int count; ACL_VSTRING_RESET(result); for (cp = UCHAR_PTR(in), count = len; count > 0; count--, cp++) { ch = *cp; ACL_VSTRING_ADDCH(result, acl_hex_chars[(ch >> 4) & 0xf]); ACL_VSTRING_ADDCH(result, acl_hex_chars[ch & 0xf]); } ACL_VSTRING_TERMINATE(result); return (result); }
static const char *xml_parse_meta_tag(ACL_XML *xml, const char *data) { int ch; while ((ch = *data) != 0) { data++; if (IS_SPACE(ch)) { xml->curr_node->status = ACL_XML_S_MTXT; break; } ACL_VSTRING_ADDCH(xml->curr_node->ltag, ch); } ACL_VSTRING_TERMINATE(xml->curr_node->ltag); return (data); }
static const char *xml_parse_attr(ACL_XML *xml, const char *data) { int ch; ACL_XML_ATTR *attr = xml->curr_node->curr_attr; if (attr == NULL || LEN(attr->name) == 0) { SKIP_SPACE(data); /* 略过 ' ', '\t' */ if (*data == 0) return (NULL); SKIP_WHILE(*data == '=', data); if (*data == 0) return (NULL); } if (*data == '>') { xml->curr_node->status = ACL_XML_S_LGT; xml_parse_check_self_closed(xml); xml->curr_node->curr_attr = NULL; data++; return (data); } xml->curr_node->last_ch = *data; if (*data == '/') { data++; return (data); } if (attr == NULL) { attr = acl_xml_attr_alloc(xml->curr_node); xml->curr_node->curr_attr = attr; } while ((ch = *data) != 0) { xml->curr_node->last_ch = ch; if (ch == '=') { xml->curr_node->status = ACL_XML_S_AVAL; data++; break; } if (!IS_SPACE(ch)) ACL_VSTRING_ADDCH(attr->name, ch); data++; } ACL_VSTRING_TERMINATE(attr->name); return (data); }
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); } }
static const char *xml_meta_attr_name(ACL_XML_ATTR *attr, const char *data) { int ch; while ((ch = *data) != 0) { if (ch == '=') { data++; ACL_VSTRING_TERMINATE(attr->name); break; } if (!IS_SPACE(ch)) ACL_VSTRING_ADDCH(attr->name, ch); data++; } return data; }
int acl_xml_encode(const char *in, ACL_VSTRING *out) { int n = 0; while (*in) { if (__charmap[(unsigned char)(*in)] != NULL) { acl_vstring_strcat(out, __charmap[(unsigned char)(*in)]); n++; } else ACL_VSTRING_ADDCH(out, (*in)); in++; } ACL_VSTRING_TERMINATE(out); return (n); }
ACL_VSTRING *escape(ACL_VSTRING *result, const char *data, ssize_t len) { int ch; ACL_VSTRING_RESET(result); while (len-- > 0) { ch = *UCHAR(data++); if (ACL_ISASCII(ch)) { if (ACL_ISPRINT(ch)) { if (ch == '\\') ACL_VSTRING_ADDCH(result, ch); ACL_VSTRING_ADDCH(result, ch); continue; } else if (ch == '\a') { /* \a -> audible bell */ acl_vstring_strcat(result, "\\a"); continue; } else if (ch == '\b') { /* \b -> backspace */ acl_vstring_strcat(result, "\\b"); continue; } else if (ch == '\f') { /* \f -> formfeed */ acl_vstring_strcat(result, "\\f"); continue; } else if (ch == '\n') { /* \n -> newline */ acl_vstring_strcat(result, "\\n"); continue; } else if (ch == '\r') { /* \r -> carriagereturn */ acl_vstring_strcat(result, "\\r"); continue; } else if (ch == '\t') { /* \t -> horizontal tab */ acl_vstring_strcat(result, "\\t"); continue; } else if (ch == '\v') { /* \v -> vertical tab */ acl_vstring_strcat(result, "\\v"); continue; } } if (ACL_ISDIGIT(*UCHAR(data))) acl_vstring_sprintf_append(result, "\\%03d", ch); else acl_vstring_sprintf_append(result, "\\%d", ch); } ACL_VSTRING_TERMINATE(result); return (result); }
ACL_VSTRING *tok822_internalize(ACL_VSTRING *vp, TOK822 *tree, int flags) { TOK822 *tp; if (flags & TOK822_STR_WIPE) ACL_VSTRING_RESET(vp); for (tp = tree; tp; tp = tp->next) { switch (tp->type) { case ',': ACL_VSTRING_ADDCH(vp, tp->type); if (flags & TOK822_STR_LINE) { ACL_VSTRING_ADDCH(vp, '\n'); continue; } break; case TOK822_ADDR: tok822_internalize(vp, tp->head, TOK822_STR_NONE); break; case TOK822_COMMENT: case TOK822_ATOM: case TOK822_QSTRING: acl_vstring_strcat(vp, acl_vstring_str(tp->vstr)); break; case TOK822_DOMLIT: ACL_VSTRING_ADDCH(vp, '['); acl_vstring_strcat(vp, acl_vstring_str(tp->vstr)); ACL_VSTRING_ADDCH(vp, ']'); break; case TOK822_STARTGRP: ACL_VSTRING_ADDCH(vp, ':'); break; default: if (tp->type >= TOK822_MINTOK) acl_msg_panic("tok822_internalize: unknown operator %d", tp->type); ACL_VSTRING_ADDCH(vp, tp->type); } if (tok822_append_space(tp)) ACL_VSTRING_ADDCH(vp, ' '); } if (flags & TOK822_STR_TERM) ACL_VSTRING_TERMINATE(vp); return (vp); }
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 const char *xml_parse_text(ACL_XML *xml, const char *data) { int ch; if (LEN(xml->curr_node->text) == 0) { SKIP_SPACE(data); if (*data == 0) return (NULL); } while ((ch = *data) != 0) { if (ch == '<') { xml->curr_node->status = ACL_XML_S_RLT; data++; break; } ACL_VSTRING_ADDCH(xml->curr_node->text, ch); data++; } ACL_VSTRING_TERMINATE(xml->curr_node->text); if (xml->curr_node->status != ACL_XML_S_RLT) return (data); if ((xml->curr_node->flag & ACL_XML_F_SELF_CL)) { /* 如果该标签是自关闭类型,则应使父结点直接跳至右边 '/' 处理位置, * 同时使本结点跳至右边 '>' 处理位置 */ ACL_XML_NODE *parent = acl_xml_node_parent(xml->curr_node); if (parent != xml->root) parent->status = ACL_XML_S_RLT; xml->curr_node->status = ACL_XML_S_RGT; } if (LEN(xml->curr_node->text) == 0) return (data); return (data); }
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, '>'); }
int mac_expand(ACL_VSTRING *result, const char *pattern, int flags, const char *filter, MAC_EXP_LOOKUP_FN lookup, char *context) { MAC_EXP mc; int status; /* * Bundle up the request and do the substitutions. */ mc.result = result; mc.flags = flags; mc.filter = filter; mc.lookup = lookup; mc.context = context; mc.status = 0; mc.level = 0; ACL_VSTRING_RESET(result); status = mac_parse(pattern, mac_expand_callback, (char *) &mc); ACL_VSTRING_TERMINATE(result); return (status); }
int acl_xml_encode(const char *in, ACL_VSTRING *out) { const unsigned char *ptr = (const unsigned char*) in; int n = 0; size_t len = strlen(in); len += len / 2; ACL_VSTRING_SPACE(out, (int) len); while (*ptr) { if (__charmap[*ptr] != NULL) { acl_vstring_strcat(out, __charmap[*ptr]); n++; } else { ACL_VSTRING_ADDCH(out, *ptr); } ptr++; } ACL_VSTRING_TERMINATE(out); return n; }
static const char *xml_parse_right_lt(ACL_XML *xml, const char *data) { ACL_XML_NODE *node; SKIP_SPACE(data); if (*data == 0) return (NULL); if (*data == '/') { xml->curr_node->status = ACL_XML_S_RTAG; data++; return (data); } else if ((xml->curr_node->flag & ACL_XML_F_LEAF)) { ACL_VSTRING_ADDCH(xml->curr_node->text, '<'); ACL_VSTRING_ADDCH(xml->curr_node->text, *data); ACL_VSTRING_TERMINATE(xml->curr_node->text); xml->curr_node->status = ACL_XML_S_TXT; data++; return (data); } /* 说明遇到了当前结点的子结点 */ /* 重新设置当前结点状态,以便于其可以找到 "</" */ xml->curr_node->status = ACL_XML_S_TXT; /* 创建新的子结点,并将其加入至当前结点的子结点集合中 */ node = acl_xml_node_alloc(xml); acl_xml_node_add_child(xml->curr_node, node); node->depth = xml->curr_node->depth + 1; if (node->depth > xml->depth) xml->depth = node->depth; xml->curr_node = node; xml->curr_node->status = ACL_XML_S_LLT; return (data); }
HTTP_HDR_REQ *http_hdr_req_create(const char *url, const char *method, const char *version) { const char *myname = "http_hdr_req_create"; HTTP_HDR_REQ *hdr_req; ACL_VSTRING *req_line = acl_vstring_alloc(256); HTTP_HDR_ENTRY *entry; const char *ptr; static char *__user_agent = "Mozilla/5.0 (Windows; U; Windows NT 5.0" "; zh-CN; rv:1.9.0.3) Gecko/2008092417 ACL/3.0.6"; if (url == NULL || *url == 0) { acl_msg_error("%s(%d): url invalid", myname, __LINE__); return NULL; } if (method == NULL || *method == 0) { acl_msg_error("%s(%d): method invalid", myname, __LINE__); return NULL; } if (version == NULL || *version == 0) { acl_msg_error("%s(%d): version invalid", myname, __LINE__); return NULL; } acl_vstring_strcpy(req_line, method); acl_vstring_strcat(req_line, " "); if (strncasecmp(url, "http://", sizeof("http://") - 1) == 0) url += sizeof("http://") - 1; else if (strncasecmp(url, "https://", sizeof("https://") - 1) == 0) url += sizeof("https://") -1; ptr = strchr(url, '/'); if (ptr) acl_vstring_strcat(req_line, ptr); else { ACL_VSTRING_ADDCH(req_line, '/'); ACL_VSTRING_TERMINATE(req_line); } acl_vstring_strcat(req_line, " "); acl_vstring_strcat(req_line, version); entry = http_hdr_entry_new(acl_vstring_str(req_line)); acl_vstring_free(req_line); if (entry == NULL) { acl_msg_error("%s(%d): http_hdr_entry_new return null for (%s)", myname, __LINE__, acl_vstring_str(req_line)); return NULL; } hdr_req = http_hdr_req_new(); http_hdr_append_entry(&hdr_req->hdr, entry); hdr_req->flag |= (HTTP_HDR_REQ_FLAG_PARSE_PARAMS | HTTP_HDR_REQ_FLAG_PARSE_COOKIE); if (http_hdr_req_line_parse(hdr_req) < 0) { http_hdr_req_free(hdr_req); return NULL; } hdr_req->host[0] = 0; __get_host_from_url(hdr_req->host, sizeof(hdr_req->host), url); if (hdr_req->host[0] != 0) http_hdr_put_str(&hdr_req->hdr, "Host", hdr_req->host); http_hdr_put_str(&hdr_req->hdr, "Connection", "Close"); http_hdr_put_str(&hdr_req->hdr, "User-Agent", __user_agent); return hdr_req; }
static int vstring_extend(ACL_VBUF *bp, ssize_t incr) { const char *myname = "vstring_extend"; ssize_t used = (ssize_t) (bp->ptr - bp->data), new_len; ACL_VSTRING *vp = (ACL_VSTRING *) bp; if (vp->maxlen > 0 && (ssize_t) ACL_VSTRING_LEN(vp) >= vp->maxlen) { ACL_VSTRING_AT_OFFSET(vp, vp->maxlen - 1); ACL_VSTRING_TERMINATE(vp); acl_msg_warn("%s(%d), %s: overflow maxlen: %ld, %ld", __FILE__, __LINE__, myname, (long) vp->maxlen, (long) ACL_VSTRING_LEN(vp)); bp->flags |= ACL_VBUF_FLAG_EOF; return ACL_VBUF_EOF; } #ifdef ACL_WINDOWS if (bp->fd == ACL_FILE_INVALID && (bp->flags & ACL_VBUF_FLAG_FIXED)) #else if (bp->fd < 0 && (bp->flags & ACL_VBUF_FLAG_FIXED)) #endif { acl_msg_warn("%s(%d), %s: can't extend fixed buffer", __FILE__, __LINE__, myname); return ACL_VBUF_EOF; } /* * Note: vp->vbuf.len is the current buffer size (both on entry and on * exit of this routine). We round up the increment size to the buffer * size to avoid silly little buffer increments. With really large * strings we might want to abandon the length doubling strategy, and * go to fixed increments. */ #ifdef INCR_NO_DOUBLE /* below come from redis-server/sds.c/sdsMakeRoomFor, which can * avoid memory double growing too large --- 2015.2.2, zsx */ new_len = bp->len + incr; if (new_len < MAX_PREALLOC) new_len *= 2; else new_len += MAX_PREALLOC; #else new_len = bp->len + (bp->len > incr ? bp->len : incr); #endif if (vp->maxlen > 0 && new_len > vp->maxlen) new_len = vp->maxlen; if (vp->slice) bp->data = (unsigned char *) acl_slice_pool_realloc( __FILE__, __LINE__, vp->slice, bp->data, new_len); else if (vp->dbuf) { const unsigned char *data = bp->data; bp->data = (unsigned char *) acl_dbuf_pool_alloc( vp->dbuf, new_len); memcpy(bp->data, data, used); acl_dbuf_pool_free(vp->dbuf, data); } else if (bp->fd != ACL_FILE_INVALID) { #ifdef ACL_UNIX acl_off_t off = new_len - 1; if (acl_lseek(bp->fd, off, SEEK_SET) != (acl_off_t) off) acl_msg_fatal("lseek failed: %s, off: %lld", acl_last_serror(), off); if (acl_file_write(bp->fd, "\0", 1, 0, NULL, NULL) == ACL_VSTREAM_EOF) { acl_msg_fatal("write error: %s", acl_last_serror()); } #endif } else bp->data = (unsigned char *) acl_myrealloc(bp->data, new_len); bp->len = new_len; bp->ptr = bp->data + used; bp->cnt = bp->len - used; return 0; }
ACL_VSTRING *tok822_externalize(ACL_VSTRING *vp, TOK822 *tree, int flags) { ACL_VSTRING *tmp; TOK822 *tp; ssize_t start = 0; TOK822 *addr = 0; ssize_t addr_len = 0; /* * Guard against a Sendmail buffer overflow (CERT advisory CA-2003-07). * The problem was that Sendmail could store too much non-address text * (comments, phrases, etc.) into a static 256-byte buffer. * * When the buffer fills up, fixed Sendmail versions remove comments etc. * and reduce the information to just <$g>, which expands to <address>. * No change is made when an address expression (text separated by * commas) contains no address. This fix reportedly also protects * Sendmail systems that are still vulnerable to this problem. * * Postfix takes the same approach, grudgingly. To avoid unnecessary damage, * Postfix removes comments etc. only when the amount of non-address text * in an address expression (text separated by commas) exceeds 250 bytes. * * With Sendmail, the address part of an address expression is the * right-most <> instance in that expression. If an address expression * contains no <>, then Postfix guarantees that it contains at most one * non-comment string; that string is the address part of the address * expression, so there is no ambiguity. * * Finally, we note that stress testing shows that other code in Sendmail * 8.12.8 bluntly truncates ``text <address>'' to 256 bytes even when * this means chopping the <address> somewhere in the middle. This is a * loss of control that we're not entirely comfortable with. However, * unbalanced quotes and dangling backslash do not seem to influence the * way that Sendmail parses headers, so this is not an urgent problem. */ #define MAX_NONADDR_LENGTH 250 #define RESET_NONADDR_LENGTH { \ start = ACL_VSTRING_LEN(vp); \ addr = 0; \ addr_len = 0; \ } #define ENFORCE_NONADDR_LENGTH do { \ if (addr && (ssize_t) ACL_VSTRING_LEN(vp) - addr_len > start + MAX_NONADDR_LENGTH) \ strip_address(vp, start, addr->head); \ } while(0) if (flags & TOK822_STR_WIPE) ACL_VSTRING_RESET(vp); if (flags & TOK822_STR_TRNC) RESET_NONADDR_LENGTH; for (tp = tree; tp; tp = tp->next) { switch (tp->type) { case ',': if (flags & TOK822_STR_TRNC) ENFORCE_NONADDR_LENGTH; ACL_VSTRING_ADDCH(vp, tp->type); ACL_VSTRING_ADDCH(vp, (flags & TOK822_STR_LINE) ? '\n' : ' '); if (flags & TOK822_STR_TRNC) RESET_NONADDR_LENGTH; continue; /* * XXX In order to correctly externalize an address, it is not * sufficient to quote individual atoms. There are higher-level * rules that say when an address localpart needs to be quoted. * We wing it with the quote_822_local() routine, which ignores * the issue of atoms in the domain part that would need quoting. */ case TOK822_ADDR: addr = tp; tmp = acl_vstring_alloc(100); tok822_internalize(tmp, tp->head, TOK822_STR_TERM); addr_len = ACL_VSTRING_LEN(vp); quote_822_local_flags(vp, acl_vstring_str(tmp), QUOTE_FLAG_8BITCLEAN | QUOTE_FLAG_APPEND); addr_len = ACL_VSTRING_LEN(vp) - addr_len; acl_vstring_free(tmp); break; case TOK822_ATOM: case TOK822_COMMENT: acl_vstring_strcat(vp, acl_vstring_str(tp->vstr)); break; case TOK822_QSTRING: ACL_VSTRING_ADDCH(vp, '"'); tok822_copy_quoted(vp, acl_vstring_str(tp->vstr), "\"\\\r\n"); ACL_VSTRING_ADDCH(vp, '"'); break; case TOK822_DOMLIT: ACL_VSTRING_ADDCH(vp, '['); tok822_copy_quoted(vp, acl_vstring_str(tp->vstr), "\\\r\n"); ACL_VSTRING_ADDCH(vp, ']'); break; case TOK822_STARTGRP: ACL_VSTRING_ADDCH(vp, ':'); break; case '<': if (tp->next && tp->next->type == '>') { addr = tp; addr_len = 0; } ACL_VSTRING_ADDCH(vp, '<'); break; default: if (tp->type >= TOK822_MINTOK) acl_msg_panic("tok822_externalize: unknown operator %d", tp->type); ACL_VSTRING_ADDCH(vp, tp->type); } if (tok822_append_space(tp)) ACL_VSTRING_ADDCH(vp, ' '); } if (flags & TOK822_STR_TRNC) ENFORCE_NONADDR_LENGTH; if (flags & TOK822_STR_TERM) ACL_VSTRING_TERMINATE(vp); return (vp); }
static const char *json_tag(ACL_JSON *json, const char *data) { ACL_JSON_NODE *node = json->curr_node; int ch; while ((ch = *data) != 0) { /* 如果前面有引号,则需要找到结尾引号 */ if (node->quote) { if (node->backslash) { if (ch == 'b') ADDCH(node->ltag, '\b'); else if (ch == 'f') ADDCH(node->ltag, '\f'); else if (ch == 'n') ADDCH(node->ltag, '\n'); else if (ch == 'r') ADDCH(node->ltag, '\r'); else if (ch == 't') ADDCH(node->ltag, '\t'); else ADDCH(node->ltag, ch); node->backslash = 0; } /* 当为双字节汉字时,第一个字节为的高位为 1, * 第二个字节为 92,正好与转义字符相同 */ else if (ch == '\\') { /* 处理半个汉字的情形 */ if (node->part_word) { ADDCH(node->ltag, ch); node->part_word = 0; } else node->backslash = 1; } else if (ch == node->quote) { ACL_JSON_NODE *parent; parent = acl_json_node_parent(node); acl_assert(parent); /* 数组对象的子结点允许为单独的字符串或对象 */ if (parent->left_ch == '[') json->status = ACL_JSON_S_NEXT; /* 标签值分析结束,下一步需要找到冒号 */ else json->status = ACL_JSON_S_COLON; node->quote = 0; node->part_word = 0; data++; break; } /* 是否兼容后半个汉字为转义符 '\' 的情况 */ else if ((json->flag & ACL_JSON_FLAG_PART_WORD)) { ADDCH(node->ltag, ch); /* 处理半个汉字的情形 */ if (node->part_word) node->part_word = 0; else if (ch < 0) node->part_word = 1; } else { ADDCH(node->ltag, ch); } } /* 分析标签名前没有引号的情况 */ else if (node->backslash) { ADDCH(node->ltag, ch); node->backslash = 0; } /* 当为双字节汉字时,第一个字节为的高位为 1, * 第二个字节为 92,正好与转义字符相同 */ else if (ch == '\\') { /* 处理半个汉字的情形 */ if (node->part_word) { ADDCH(node->ltag, ch); node->part_word = 0; } else node->backslash = 1; } else if (IS_SPACE(ch) || ch == ':') { /* 标签名分析结束,下一步需要找到冒号 */ json->status = ACL_JSON_S_COLON; node->part_word = 0; break; } /* 是否兼容后半个汉字为转义符 '\' 的情况 */ else if ((json->flag & ACL_JSON_FLAG_PART_WORD)) { ADDCH(node->ltag, ch); /* 处理半个汉字的情形 */ if (node->part_word) node->part_word = 0; else if (ch < 0) node->part_word = 1; } else { ADDCH(node->ltag, ch); } data++; } /* 如果标签名非空,则需要保证以 0 结尾 */ if (LEN(node->ltag) > 0) ACL_VSTRING_TERMINATE(node->ltag); return data; }
static const char *json_string(ACL_JSON *json, const char *data) { ACL_JSON_NODE *node = json->curr_node; int ch; /* 当文本长度为 0 时,可以认为还未遇到有效的字符 */ if (LEN(node->text) == 0) { /* 先过滤开头没用的空格 */ SKIP_SPACE(data); if (*data == 0) return NULL; } /* 说明本结点是叶结点 */ while ((ch = *data) != 0) { /* 如果开始有引号,则需要以该引号作为结尾符 */ if (node->quote) { if (node->backslash) { if (ch == 'b') ADDCH(node->text, '\b'); else if (ch == 'f') ADDCH(node->text, '\f'); else if (ch == 'n') ADDCH(node->text, '\n'); else if (ch == 'r') ADDCH(node->text, '\r'); else if (ch == 't') ADDCH(node->text, '\t'); else ADDCH(node->text, ch); node->backslash = 0; } /* 当为双字节汉字时,第一个字节为的高位为 1, * 第二个字节有可能为 92,正好与转义字符相同 */ else if (ch == '\\') { /* 处理半个汉字的情况,如果前一个字节是前 * 半个汉字,则当前的转义符当作后半个汉字 */ if (node->part_word) { ADDCH(node->text, ch); node->part_word = 0; } else node->backslash = 1; } else if (ch == node->quote) { node->quote = 0; /* 切换至查询该结点的兄弟结点的过程 */ json->status = ACL_JSON_S_STREND; node->part_word = 0; data++; break; } /* 是否兼容后半个汉字为转义符 '\' 的情况 */ else if ((json->flag & ACL_JSON_FLAG_PART_WORD)) { ADDCH(node->text, ch); /* 若前一个字节为前半个汉字,则当前字节 * 为后半个汉字,正好为一个完整的汉字 */ if (node->part_word) node->part_word = 0; /* 前一个字节非前半个汉字且当前字节高位 * 为 1,则表明当前字节为前半个汉字 */ else if (ch < 0) node->part_word = 1; } else { ADDCH(node->text, ch); } } else if (node->backslash) { ADDCH(node->text, ch); node->backslash = 0; } else if (ch == '\\') { if (node->part_word) { ADDCH(node->text, ch); node->part_word = 0; } else node->backslash = 1; } else if (IS_SPACE(ch) || ch == ',' || ch == ';' || ch == '}' || ch == ']') { /* 切换至查询该结点的兄弟结点的过程 */ json->status = ACL_JSON_S_STREND; break; } /* 是否兼容后半个汉字为转义符 '\' 的情况 */ else if ((json->flag & ACL_JSON_FLAG_PART_WORD)) { ADDCH(node->text, ch); /* 处理半个汉字的情形 */ if (node->part_word) node->part_word = 0; else if (ch < 0) node->part_word = 1; } else { ADDCH(node->text, ch); } data++; } if (LEN(node->text) > 0) ACL_VSTRING_TERMINATE(node->text); return data; }