| /* ==================================================================== |
| * Copyright (c) 1995-1999 The Apache Group. 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. All advertising materials mentioning features or use of this |
| * software must display the following acknowledgment: |
| * "This product includes software developed by the Apache Group |
| * for use in the Apache HTTP server project (http://www.apache.org/)." |
| * |
| * 4. The names "Apache Server" and "Apache Group" must not be used to |
| * endorse or promote products derived from this software without |
| * prior written permission. For written permission, please contact |
| * apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache" |
| * nor may "Apache" appear in their names without prior written |
| * permission of the Apache Group. |
| * |
| * 6. Redistributions of any form whatsoever must retain the following |
| * acknowledgment: |
| * "This product includes software developed by the Apache Group |
| * for use in the Apache HTTP server project (http://www.apache.org/)." |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 APACHE 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 Apache Group and was originally based |
| * on public domain software written at the National Center for |
| * Supercomputing Applications, University of Illinois, Urbana-Champaign. |
| * For more information on the Apache Group and the Apache HTTP server |
| * project, please see <http://www.apache.org/>. |
| * |
| */ |
| |
| #include "apache_cookie.h" |
| |
| static char *cookie_path(request_rec *r) |
| { |
| int path_info_start = ap_find_path_info(r->uri, r->path_info); |
| int uri_len = strlen(r->uri); |
| char *retval, *tmp = r->uri; |
| tmp += (uri_len - path_info_start); |
| retval = ap_make_dirstr_parent(r->pool, tmp); |
| return retval; |
| } |
| |
| char *ApacheCookie_expires(ApacheCookie *c, char *time_str) |
| { |
| char *expires; |
| |
| expires = ApacheUtil_expires(c->r->pool, time_str, EXPIRES_COOKIE); |
| if (expires) { |
| c->expires = expires; |
| } |
| |
| return c->expires; |
| } |
| |
| #define cookie_get_set(thing,val) \ |
| retval = thing; \ |
| if(val) thing = ap_pstrdup(c->r->pool, val) |
| |
| char *ApacheCookie_attr(ApacheCookie *c, char *key, char *val) |
| { |
| char *retval = NULL; |
| int ix = key[0] == '-' ? 1 : 0; |
| |
| switch (key[ix]) { |
| case 'n': |
| cookie_get_set(c->name, val); |
| break; |
| case 'v': |
| ApacheCookieAdd(c, val); |
| break; |
| case 'e': |
| retval = ApacheCookie_expires(c, val); |
| break; |
| case 'd': |
| cookie_get_set(c->domain, val); |
| break; |
| case 'p': |
| cookie_get_set(c->path, val); |
| break; |
| case 's': |
| if(val) { |
| c->secure = |
| !strcaseEQ(val, "off") && |
| !strcaseEQ(val, "0"); |
| } |
| retval = c->secure ? "on" : ""; |
| break; |
| default: |
| ap_log_rerror(APC_ERROR, |
| "[libapreq] unknown cookie pair: `%s' => `%s'", key, val); |
| }; |
| |
| return retval; |
| } |
| |
| ApacheCookie *ApacheCookie_new(request_rec *r, ...) |
| { |
| va_list args; |
| ApacheCookie *c = |
| ap_pcalloc(r->pool, sizeof(ApacheCookie)); |
| |
| c->r = r; |
| c->values = ap_make_array(r->pool, 1, sizeof(char *)); |
| c->secure = 0; |
| c->name = c->expires = c->domain = NULL; |
| c->path = cookie_path(r); |
| |
| va_start(args, r); |
| for(;;) { |
| char *key, *val; |
| key = va_arg(args, char *); |
| if (key == NULL) { |
| break; |
| } |
| val = va_arg(args, char *); |
| (void)ApacheCookie_attr(c, key, val); |
| } |
| va_end(args); |
| |
| return c; |
| } |
| |
| ApacheCookieJar *ApacheCookie_parse(request_rec *r, const char *data) |
| { |
| const char *pair; |
| ApacheCookieJar *retval = |
| ap_make_array(r->pool, 1, sizeof(ApacheCookie *)); |
| |
| if (!data) { |
| if (!(data = ap_table_get(r->headers_in, "Cookie"))) { |
| return retval; |
| } |
| } |
| |
| while (*data && (pair = ap_getword(r->pool, &data, ';'))) { |
| const char *key, *val; |
| ApacheCookie *c; |
| |
| while (ap_isspace(*data)) { |
| ++data; |
| } |
| key = ap_getword(r->pool, &pair, '='); |
| c = ApacheCookie_new(r, "-name", key, NULL); |
| if (c->values) { |
| c->values->nelts = 0; |
| } |
| else { |
| c->values = ap_make_array(r->pool, 4, sizeof(char *)); |
| } |
| while (*pair && (val = ap_getword(r->pool, &pair, '&'))) { |
| ap_unescape_url((char *)val); |
| ApacheCookieAdd(c, val); |
| } |
| ApacheCookieJarAdd(retval, c); |
| } |
| |
| return retval; |
| } |
| |
| #define cookie_push_arr(arr, val) \ |
| *(char **)ap_push_array(arr) = (char *)val |
| |
| #define cookie_push_named(arr, name, val) \ |
| if(val) { \ |
| cookie_push_arr(arr, ap_pstrcat(p, name, "=", val, NULL)); \ |
| } |
| |
| #define escape_url(val) \ |
| ap_os_escape_path(p, val?val:"", 1) |
| |
| char *ApacheCookie_as_string(ApacheCookie *c) |
| { |
| array_header *values; |
| pool *p = c->r->pool; |
| char *cookie, *retval; |
| int i; |
| |
| if (!c->name) { |
| return ""; |
| } |
| |
| values = ap_make_array(p, 6, sizeof(char *)); |
| cookie_push_named(values, "domain", c->domain); |
| cookie_push_named(values, "path", c->path); |
| cookie_push_named(values, "expires", c->expires); |
| if (c->secure) { |
| cookie_push_arr(values, "secure"); |
| } |
| |
| cookie = ap_pstrcat(p, escape_url(c->name), "=", NULL); |
| for (i=0; i<c->values->nelts; i++) { |
| cookie = ap_pstrcat(p, cookie, |
| escape_url(((char**)c->values->elts)[i]), |
| (i < (c->values->nelts-1) ? "&" : NULL), |
| NULL); |
| } |
| |
| retval = cookie; |
| for (i=0; i<values->nelts; i++) { |
| retval = ap_pstrcat(p, retval, "; ", |
| ((char**)values->elts)[i], NULL); |
| } |
| |
| return retval; |
| } |
| |
| void ApacheCookie_bake(ApacheCookie *c) |
| { |
| ap_table_add(c->r->err_headers_out, "Set-Cookie", |
| ApacheCookie_as_string(c)); |
| } |