📄 cookies.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * Module: cookies.c * * Description: Implements a minimal cookie handler for session persistence. * * References: RFC 2109 * * Author: Paul Keogh, ANAM Wireless Internet Solutions * * Date: May 2000 */#include <string.h>#include <ctype.h>#include "gwlib/gwlib.h"#include "wsp.h"#include "cookies.h"/* Statics */static Octstr *get_header_value(Octstr*);static Cookie *parse_cookie(Octstr*);static void add_cookie_to_cache(const WSPMachine*, Cookie*);static void expire_cookies(List*);static void cookie_destroy(void*);static int have_cookie(List*, Cookie*);static int parse_http_date(const char*);static Cookie emptyCookie;Cookie *cookie_create(void){ Cookie *p; p = gw_malloc(sizeof(Cookie)); /* Never returns NULL */ *p = emptyCookie; p -> max_age = -1; time (&p -> birth); return p;}void cookies_destroy(List *cookies) { gwlib_assert_init(); if (cookies == NULL) return; list_destroy(cookies, cookie_destroy);}int get_cookies(List *headers, const WSPMachine *sm){ Octstr *header = NULL; Octstr *value = NULL; Cookie *cookie = NULL; long pos = 0; /* * This can happen if the user aborts while the HTTP request is pending from the server. * In that case, the session machine is destroyed and is not available to this function * for cookie caching. */ if (sm == NULL) { info (0, "No session machine for cookie retrieval"); return 0; } for (pos = 0; pos < list_len(headers); pos++) { header = list_get(headers, pos); /* debug ("wap.wsp.http", 0, "get_cookies: Examining header (%s)", octstr_get_cstr (header)); */ if (strncasecmp ("set-cookie", octstr_get_cstr (header),10) == 0) { debug ("wap.wsp.http", 0, "Caching cookie (%s)", octstr_get_cstr (header)); if ((value = get_header_value (header)) == NULL) { error (0, "get_cookies: No value in (%s)", octstr_get_cstr(header)); continue; } /* Parse the received cookie */ if ((cookie = parse_cookie(value)) != NULL) { /* Check to see if this cookie is already present */ if (have_cookie(sm->cookies, cookie) == 1) { debug("wap.wsp.http", 0, "parse_cookie: Cookie present"); cookie_destroy(cookie); continue; } else { add_cookie_to_cache(sm, cookie); debug("wap.wsp.http", 0, "get_cookies: Added (%s)", octstr_get_cstr(cookie -> name)); } } } } debug("wap.wsp.http", 0, "get_cookies: End"); return 0;}int set_cookies(List *headers, WSPMachine *sm){ Cookie *value = NULL; Octstr *cookie = NULL; long pos = 0; if (headers == NULL || sm == NULL) { error (0, "set_cookies: Null argument(s) - no headers, WSPMachine or both"); return -1; } if (sm->cookies == NULL) sm->cookies = list_create(); /* Expire cookies that have timed out */ expire_cookies(sm->cookies); /* Walk through the cookie cache, adding the cookie to the request headers */ if (list_len(sm->cookies) > 0) { debug("wap.wsp.http", 0, "set_cookies: Cookies in cache"); for (pos = 0; pos < list_len(sm->cookies); pos++) { value = list_get(sm->cookies, pos); cookie = octstr_create("Cookie: "); if (value->version) octstr_append(cookie, value->version); octstr_append(cookie, value->name); octstr_append_char(cookie, '='); octstr_append(cookie, value->value); if (value->path) { octstr_append_char(cookie, ';'); octstr_append(cookie, value->path); } if (value->domain) { octstr_append_char(cookie, ';'); octstr_append(cookie, value->domain); } list_append(headers, cookie); debug("wap.wsp.http", 0, "set_cookies: Added (%s)", octstr_get_cstr (cookie)); } } else debug("wap.wsp.http", 0, "set_cookies: No cookies in cache"); return 0;}/* * Private interface functions *//* * Function: get_header_value * * Description: Gets the header value as an Octstr. */static Octstr *get_header_value(Octstr *header) { Octstr *h = NULL; long colon = -1; if (header == NULL) { error(0, "get_header_value: NULL argument"); return NULL; } octstr_strip_blanks(header); colon = octstr_search_char(header, ':', 0); if (colon == -1) { error(0, "get_header_value: Malformed header (%s)", octstr_get_cstr (header)); return NULL; } else { h = octstr_copy(header, colon + 1, octstr_len(header)); octstr_strip_blanks(h); } debug("wap.wsp.http", 0, "get_header_value: Value (%s)", octstr_get_cstr (h)); return h;}/* * Function: parse_cookie * * Description: Parses the received cookie and rewrites it for sending. */static Cookie *parse_cookie(Octstr *cookiestr){ char *v = NULL; char *p = NULL; int delta = 0; Cookie *c = NULL; Octstr **f = NULL; if (cookiestr == NULL) { error(0, "parse_cookie: NULL argument"); return NULL; } v = gw_strdup(octstr_get_cstr (cookiestr)); p = strtok(v, ";"); c = cookie_create(); /* Never returns NULL */ while (p != NULL) { while (isspace((int)*p)) p++; /* Skip leading whitespace */ if (strncasecmp("version", p, 7) == 0) f = &c -> version; else if (strncasecmp("path", p, 4) == 0) f = &c -> path; else if (strncasecmp("domain", p, 6) == 0) f = &c -> domain; /* XXX DAVI: Shouldn't we check if domain is similar * to real domain, and to set domain to * real domain if not set by header ??? */ else if (strncasecmp("max-age", p, 7) == 0) { c -> max_age = atol(strrchr (p, '=') + 1); p = strtok(NULL, ";"); continue; } else if (strncasecmp("expires", p, 7) == 0) { delta = parse_http_date(p); if (delta != -1) c->max_age = delta; p = strtok(NULL, ";"); continue; } else if (strncasecmp("comment", p, 7) == 0 ) { /* Ignore comments */ p = strtok(NULL, ";"); continue; } else if (strncasecmp("secure", p, 6) == 0 ) { /* XXX DAVI: this should processed */ p = strtok(NULL, ";"); continue; } else { /* Name value pair - this should be first */ char *equals = NULL; if ((equals = strrchr(p, '=')) != NULL) { *equals = '\0'; c->name = octstr_create(p); c->value = octstr_create(equals + 1); } else { error(0, "parse_cookie: Bad name=value cookie component (%s)", p); cookie_destroy(c); return NULL; } p = strtok(NULL, ";"); continue; } if (*f != NULL) { /* Undefined behaviour - 4.2.2 */ error(0, "parse_cookie: Duplicate cookie field (%s), discarding", p);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -