📄 http_extra.c
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@CFILE http_extra.c * * Extra HTTP headers * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */#include "config.h"#include <stddef.h>#include <stdlib.h>#include <string.h>#include <limits.h>#include <assert.h>#include "sofia-sip/http_parser.h"/* ========================================================================== *//**@HTTP_HEADER http_proxy_connection Proxy-Connection extension header. */#define http_proxy_connection_d msg_list_d#define http_proxy_connection_e msg_list_emsg_hclass_t http_proxy_connection_class[] =HTTP_HEADER_CLASS_LIST(proxy_connection, "Proxy-Connection", list);/* ====================================================================== *//**@HTTP_HEADER http_cookie Cookie extension header. * * The Cookie header is used to transmit state information from server * back to the http client. Its syntax is defined in RFC 2109 section 4.3.4 * as follows: * * @code * cookie = "Cookie:" cookie-version * 1*((";" | ",") cookie-value) * cookie-value = NAME "=" VALUE [";" path] [";" domain] * cookie-version = "$Version" "=" value * NAME = attr * VALUE = value * path = "$Path" "=" value * domain = "$Domain" "=" value * @endcode * *//**@ingroup http_cookie * * @typedef typedef struct http_cookie_s http_cookie_t; * * The structure http_cookie_t contains representation of @b Cookie * header. Please note that a single http_cookie_t can contain many * cookies. * * The http_cookie_t is defined as follows: * @code * typedef struct http_cookie_s * { * } http_cookie_t; * @endcode *//**Update Cookie parameters. * * The function http_cookie_update() updates a @b Cookie parameter * shortcuts. * * @param sc pointer to a @c http_cookie_t object */static inlinevoid http_cookie_update(http_cookie_t *c){ int i; c->c_name = NULL; c->c_version = NULL, c->c_domain = NULL, c->c_path = NULL; if (!c->c_params) return; if (!(MSG_PARAM_MATCH(c->c_version, c->c_params[0], "$Version"))) return; if (!c->c_params[1] || c->c_params[1][0] == '$') return; c->c_name = c->c_params[1]; for (i = 2; ; i++) { msg_param_t p = c->c_params[i]; if (!p || *p++ != '$') break; switch (p[0]) { case 'd': case 'D': MSG_PARAM_MATCH(c->c_domain, p, "Domain"); break; case 'p': case 'P': MSG_PARAM_MATCH(c->c_path, p, "Path"); break; } }}/* Scan a cookie parameter */static int cookie_scanner(char *s){ char *p = s; unsigned tlen; skip_token(&s); if (s == p) /* invalid parameter name */ return -1; tlen = s - p; if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } if (*s == '=') { char *v; s++; skip_lws(&s); v = s; /* get value */ if (*s == '"') { int qlen = span_quoted(s); if (!qlen) return -1; s += qlen; } else { s += strcspn(s, ",;" LWS); if (s == v) return -1; } if (p + tlen + 1 != v) { memmove(p + tlen + 1, v, s - v); p[tlen] = '='; p[tlen + 1 + (s - v)] = '\0'; } } if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); } return s - p;}/** Decode (parse) a Cookie header */int http_cookie_d(su_home_t *home, msg_header_t *h, char *s, int slen){ http_cookie_t *c = (http_cookie_t *)h; assert(h); assert(sizeof(*h)); for (;*s;) { /* Ignore empty entries (comma-whitespace) */ if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; } if (msg_any_list_d(home, &s, (msg_param_t **)&c->c_params, cookie_scanner, ';') == -1) return -1; if (*s != '\0' && *s != ',') return -1; if (!c->c_params) return -1; } http_cookie_update(c); return 0;}/** Encode (print) a Cookie header */int http_cookie_e(char b[], int bsiz, msg_header_t const *h, int flags){ char *b0 = b, *end = b + bsiz; http_cookie_t const *c = (http_cookie_t *)h; int i; if (c->c_params) { for (i = 0; c->c_params[i]; i++) { if (i > 0) MSG_CHAR_E(b, end, ';'); MSG_STRING_E(b, end, c->c_params[i]); } } MSG_TERM_E(b, end); return b - b0;}/** Calculate extra storage used by Cookie header field */int http_cookie_dup_xtra(msg_header_t const *h, int offset){ int rv = offset; http_cookie_t const *c = (http_cookie_t *)h; MSG_PARAMS_SIZE(rv, c->c_params); return rv;}/** Duplicate a Cookie header field */char *http_cookie_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, int xtra){ http_cookie_t *c = (http_cookie_t *)dst; http_cookie_t const *o = (http_cookie_t const *)src; char *end = b + xtra; b = msg_params_dup(&c->c_params, o->c_params, b, xtra); http_cookie_update(c); assert(b <= end); return b;}msg_hclass_t http_cookie_class[] =HTTP_HEADER_CLASS(cookie, "Cookie", c_params, append, cookie);/* ====================================================================== *//**@HTTP_HEADER http_set_cookie Set-Cookie extension header. * * The Set-Cookie header is used to transmit state information from server * back to the http client. Its syntax is defined in RFC 2109 section 4.2.2 * as follows: * * @code * set-cookie = "Set-Cookie:" cookies * cookies = 1#cookie * cookie = NAME "=" VALUE *(";" cookie-av) * NAME = attr * VALUE = value * cookie-av = "Comment" "=" value * | "Domain" "=" value * | "Max-Age" "=" value * | "Path" "=" value * | "Secure" * | "Version" "=" 1*DIGIT * * @endcode * *//**@ingroup http_set_cookie * * @typedef typedef struct http_set_cookie_s http_set_cookie_t; * * The structure http_set_cookie_t contains representation of @b Set-Cookie * header. * * The http_set_cookie_t is defined as follows: * @code * typedef struct http_set_cookie_s * { * } http_set_cookie_t; * @endcode *//**Update Set-Cookie parameters. * * The function http_set_cookie_update() updates a @b Set-Cookie parameter * shortcuts. * * @param sc pointer to a @c http_set_cookie_t object */static inlinevoid http_set_cookie_update(http_set_cookie_t *sc){ int i; sc->sc_name = NULL; sc->sc_version = NULL, sc->sc_domain = NULL, sc->sc_path = NULL; sc->sc_comment = NULL, sc->sc_max_age = NULL, sc->sc_secure = 0; if (!sc->sc_params) return; sc->sc_name = sc->sc_params[0]; for (i = 1; sc->sc_params[i]; i++) { msg_param_t p = sc->sc_params[i]; switch (p[0]) { case 'c': case 'C': MSG_PARAM_MATCH(sc->sc_comment, p, "Comment"); break; case 'd': case 'D': MSG_PARAM_MATCH(sc->sc_domain, p, "Domain"); break; case 'm': case 'M': MSG_PARAM_MATCH(sc->sc_max_age, p, "Max-Age"); break; case 'p': case 'P': MSG_PARAM_MATCH(sc->sc_path, p, "Path"); break; case 's': case 'S': MSG_PARAM_MATCH_P(sc->sc_secure, p, "Secure"); break; case 'v': case 'V': MSG_PARAM_MATCH(sc->sc_version, p, "Version"); break; } }}#include <sofia-sip/msg_date.h>/* Scan a cookie parameter */static int set_cookie_scanner(char *s){ char *rest;#define LOOKING_AT(s, what) \ (strncasecmp((s), what, strlen(what)) == 0 && (rest = s + strlen(what))) /* Special cases from Netscape spec */ if (LOOKING_AT(s, "expires=")) { msg_time_t value; msg_date_d((char const **)&rest, &value); } else if (LOOKING_AT(s, "path=/")) { for (;;) { rest += span_unreserved(rest); if (*rest != '/') break; rest++; } } else { return msg_attribute_value_scanner(s); }#undef LOOKING_AT if (IS_LWS(*rest)) { *rest++ = '\0'; skip_lws(&rest); } return rest - s;}/** Decode (parse) Set-Cookie header */int http_set_cookie_d(su_home_t *home, msg_header_t *h, char *s, int slen){ msg_header_t **hh = &h->sh_succ, *h0 = h; http_set_cookie_t *sc = (http_set_cookie_t *)h; msg_param_t *params; assert(h); assert(sizeof(*h)); for (;*s;) { /* Ignore empty entries (comma-whitespace) */ if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; } if (!h) { /* Allocate next header structure */ if (!(h = msg_header_alloc(home, h0->sh_class, 0))) return -1; *hh = h; h->sh_prev = hh; hh = &h->sh_succ; sc = sc->sc_next = (http_set_cookie_t *)h; } /* "Set-Cookie:" 1#(NAME "=" VALUE *(";" cookie-av))) */ params = su_zalloc(home, MSG_PARAMS_NUM(1) * sizeof(msg_param_t)); if (!params) return -1; params[0] = s, sc->sc_params = params; s += strcspn(s, ",;" LWS); if (*s) { *s++ = '\0'; skip_lws(&s); if (*s && msg_any_list_d(home, &s, (msg_param_t **)&sc->sc_params, set_cookie_scanner, ';') == -1) return -1; } if (*s != '\0' && *s != ',') return -1; if (sc->sc_params) http_set_cookie_update(sc); h = NULL; } return 0;}/** Encode (print) Set-Cookie header */int http_set_cookie_e(char b[], int bsiz, msg_header_t const *h, int flags){ char *b0 = b, *end = b + bsiz; http_set_cookie_t const *sc = (http_set_cookie_t *)h; int i; if (sc->sc_params) { for (i = 0; sc->sc_params[i]; i++) { if (i > 0) MSG_CHAR_E(b, end, ';'); MSG_STRING_E(b, end, sc->sc_params[i]); } } MSG_TERM_E(b, end); return b - b0;}/** Calculate extra storage used by Set-Cookie header field */int http_set_cookie_dup_xtra(msg_header_t const *h, int offset){ int rv = offset; http_set_cookie_t const *sc = (http_set_cookie_t *)h; MSG_PARAMS_SIZE(rv, sc->sc_params); return rv;}/** Duplicate a Set-Cookie header field */char *http_set_cookie_dup_one(msg_header_t *dst, msg_header_t const *src, char *b, int xtra){ http_set_cookie_t *sc = (http_set_cookie_t *)dst; http_set_cookie_t const *o = (http_set_cookie_t const *)src; char *end = b + xtra; b = msg_params_dup(&sc->sc_params, o->sc_params, b, xtra); http_set_cookie_update(sc); assert(b <= end); return b;}msg_hclass_t http_set_cookie_class[] =HTTP_HEADER_CLASS(set_cookie, "Set-Cookie", sc_params, append, set_cookie);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -