2 * Copyright (C) 2005-2009 Atsushi Konno All rights reserved.
3 * Copyright (C) 2005 QSDN,Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 #include "chxj_cookie.h"
21 #include "chxj_url_encode.h"
22 #include "chxj_apply_convrule.h"
23 #include "chxj_str_util.h"
25 #include "ap_release.h"
31 #include "apr_base64.h"
36 #if defined(USE_MYSQL_COOKIE)
37 # include "chxj_mysql.h"
39 #if defined(USE_MEMCACHE_COOKIE)
40 # include "chxj_memcache.h"
44 #define DUMP_HEADERS(X) do { \
46 apr_array_header_t *__headers = (apr_array_header_t*)apr_table_elts((X)); \
47 apr_table_entry_t *__hentryp = (apr_table_entry_t*)__headers->elts; \
48 for (__ii=0; __ii<__headers->nelts; __ii++) { \
49 DBG(r, "key:[%s] val:[%s]", __hentryp[__ii].key, __hentryp[__ii].val); \
55 static char* s_get_hostname_from_url(request_rec* r, char* value);
56 static char* s_cut_until_end_hostname(request_rec*, char* value);
57 static int valid_domain(request_rec *r, const char *value);
58 static int valid_path(request_rec *r, const char *value);
59 static int valid_expires(request_rec *r, const char *value);
60 static int valid_secure(request_rec *r, const char *value);
61 static int check_valid_cookie_attribute(request_rec *r, const char *pair);
62 static int check_valid_cookie_attribute_expires_only(request_rec *r, const char *value);
64 apr_proc_mutex_t *global_cookie_mutex;
67 alloc_cookie_id(request_rec *r)
71 unsigned char *md5_value;
76 uuid_string = apr_palloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1);
77 memset(uuid_string, 0, APR_UUID_FORMATTED_LENGTH + 1);
78 apr_uuid_format(uuid_string, &uuid);;
80 md5_value = (unsigned char*)apr_palloc(r->pool, APR_MD5_DIGESTSIZE + 1);
81 memset(md5_value, 0, APR_MD5_DIGESTSIZE + 1);
83 retval = apr_md5(md5_value,
84 (const char*)uuid_string,
85 APR_UUID_FORMATTED_LENGTH);
86 if (retval != APR_SUCCESS) {
87 ERR(r, "md5 failed.");
91 cookie_id = apr_palloc(r->pool, apr_base64_encode_len(APR_MD5_DIGESTSIZE)+1);
92 memset(cookie_id, 0, APR_MD5_DIGESTSIZE+1);
93 apr_base64_encode(cookie_id, (char*)md5_value, APR_MD5_DIGESTSIZE);
95 DBG(r, "cookie_id=[%s]", cookie_id);
97 cookie_id = chxj_url_encode(r->pool,cookie_id);
99 DBG(r, "cookie_id=[%s]", cookie_id);
108 chxj_save_cookie(request_rec *r)
111 apr_array_header_t *headers;
112 apr_table_entry_t *hentryp;
113 apr_array_header_t *err_headers;
114 apr_table_entry_t *err_hentryp;
117 mod_chxj_config *dconf;
118 chxjconvrule_entry *entryp;
119 apr_table_t *new_cookie_table;
122 cookie_t *old_cookie;
124 apr_uri_t parsed_uri;
129 DBG(r, "start chxj_save_cookie()");
131 apr_pool_create(&pool, r->pool);
133 cookie = (cookie_t*)apr_palloc(pool, sizeof(cookie_t));
134 cookie->cookie_id = NULL;
139 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
140 entryp = chxj_apply_convrule(r, dconf->convrules);
142 DBG(r, "end chxj_save_cookie() no pattern");
145 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
146 DBG(r, "end chxj_save_cookie() CookieOff");
152 headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
153 hentryp = (apr_table_entry_t*)headers->elts;
154 err_headers = (apr_array_header_t*)apr_table_elts(r->err_headers_out);
155 err_hentryp = (apr_table_entry_t*)err_headers->elts;
158 new_cookie_table = apr_table_make(pool, 0);
160 for (ii=0; ii<headers->nelts; ii++) {
161 if (strcasecmp(hentryp[ii].key, "Set-Cookie") == 0) {
162 DBG(r, "REQ[%X] cookie=[%s:%s]", (unsigned int)(apr_size_t)r, hentryp[ii].key, hentryp[ii].val);
168 char *pair = apr_psprintf(pool, "%s:%s", hentryp[ii].key, hentryp[ii].val);
169 if (check_valid_cookie_attribute_expires_only(r, pair)) {
170 buff = apr_pstrdup(pool, hentryp[ii].val);
171 val = strchr(buff, '=');
175 apr_table_set(new_cookie_table, apr_pstrdup(pool, key), apr_pstrdup(pool, val));
176 if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++;
182 for (ii=0; ii<err_headers->nelts; ii++) {
183 if (strcasecmp(err_hentryp[ii].key, "Set-Cookie") == 0) {
184 DBG(r, "REQ[%X] cookie=[%s:%s]", (unsigned int)(apr_size_t)r, err_hentryp[ii].key, err_hentryp[ii].val);
190 char *pair = apr_psprintf(pool, "%s:%s", err_hentryp[ii].key, err_hentryp[ii].val);
191 if (check_valid_cookie_attribute_expires_only(r, pair)) {
192 buff = apr_pstrdup(pool, err_hentryp[ii].val);
193 val = strchr(buff, '=');
197 apr_table_set(new_cookie_table, apr_pstrdup(pool, key), apr_pstrdup(pool, val));
198 if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++;
204 apr_table_unset(r->headers_out, "Set-Cookie");
205 apr_table_unset(r->err_headers_out, "Set-Cookie");
208 apr_uri_parse(pool,r->uri, &parsed_uri);
209 refer_string = apr_psprintf(pool,
211 chxj_run_http_scheme(r),
213 apr_uri_unparse(pool,
215 APR_URI_UNP_OMITSITEPART));
216 if (r->args && strlen(r->args)) {
217 refer_string = apr_pstrcat(pool, refer_string, "?", r->args, NULL);
219 apr_table_setn(new_cookie_table, REFERER_COOKIE_KEY, refer_string);
220 DBG(r, "ADD REFER[%s]", refer_string);
226 * check input parameters
228 old_cookie_id = (char*)apr_table_get(r->headers_in, "CHXJ_COOKIE_ID");
230 old_cookie = chxj_load_cookie(r, old_cookie_id);
231 if (old_cookie && old_cookie->cookie_headers) {
232 hentryp = (apr_table_entry_t*)old_cookie->cookie_headers->elts;
233 for (ii=0; ii<old_cookie->cookie_headers->nelts; ii++) {
234 if (hentryp && apr_table_get(new_cookie_table, hentryp[ii].key) == NULL) {
235 apr_table_add(new_cookie_table, apr_pstrdup(pool, hentryp[ii].key), apr_pstrdup(pool, hentryp[ii].val));
239 chxj_delete_cookie(r, old_cookie_id);
240 chxj_delete_cookie_expire(r, old_cookie_id);
248 DBG(r, "REQ[%X] end chxj_save_cookie() (no cookie)", (unsigned int)(apr_size_t)r);
255 cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(new_cookie_table);
256 hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;
257 apr_size_t store_string_len = 0;
258 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
259 if (ii) store_string_len++;
260 store_string_len += (strlen(hentryp[ii].key) + strlen(hentryp[ii].val) + 1);
262 store_string = apr_palloc(pool, store_string_len + 1);
263 memset(store_string, 0, store_string_len + 1);
266 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
267 if (ii) store_string[npos++] = '\n';
268 memcpy(&store_string[npos], hentryp[ii].key, strlen(hentryp[ii].key));
269 npos += strlen(hentryp[ii].key);
270 store_string[npos++] = '=';
271 memcpy(&store_string[npos], hentryp[ii].val, strlen(hentryp[ii].val));
272 npos += strlen(hentryp[ii].val);
275 if (old_cookie_id && IS_COOKIE_LAZY(dconf)) {
276 DBG(r, "REQ[%X] LAZY COOKIE save",(unsigned int)(apr_size_t)r);
277 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
279 else if (old_cookie_id && apr_table_get(r->headers_in, "X-Chxj-Cookie-No-Update")) {
280 DBG(r, "REQ[%X] NO UPDATE MODE",(unsigned int)(apr_size_t)r);
281 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
284 if (old_cookie_id && apr_table_get(r->headers_in, "X-Chxj-Forward")) {
285 DBG(r, "REQ[%X] NO LAZY COOKIE(X-Chxj-Forward) save",(unsigned int)(apr_size_t)r);
286 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
289 DBG(r, "REQ[%X] NO LAZY COOKIE save",(unsigned int)(apr_size_t)r);
290 cookie->cookie_id = alloc_cookie_id(r);
294 DBG(r, "REQ[%X] TYPE:[%d]", (unsigned int)(apr_size_t)r, dconf->cookie_store_type);
298 #if defined(USE_MYSQL_COOKIE)
299 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
300 if (! chxj_save_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) {
301 ERR(r, "%s:%d faild: chxj_save_cookie_mysql() cookie_id:[%s]", APLOG_MARK,cookie->cookie_id);
308 #if defined(USE_MEMCACHE_COOKIE)
309 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
310 if (! chxj_save_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) {
311 ERR(r, "%s:%d failed: chxj_save_cookie_memcache() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id);
318 if (IS_COOKIE_STORE_DBM(dconf->cookie_store_type) || ! done_proc) {
319 if (! chxj_save_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) {
320 ERR(r, "%s:%d failed: chxj_save_cookie_dbm() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id);
326 apr_table_unset(r->headers_out, "Set-Cookie");
327 apr_table_unset(r->err_headers_out, "Set-Cookie");
330 chxj_save_cookie_expire(r, cookie);
334 DBG(r, "end chxj_save_cookie()");
344 chxj_update_cookie(request_rec *r, cookie_t *old_cookie)
347 apr_array_header_t *headers;
348 apr_table_entry_t *hentryp;
350 mod_chxj_config *dconf;
351 chxjconvrule_entry *entryp;
355 DBG(r, "start chxj_update_cookie()");
356 if (!old_cookie || ! old_cookie->cookie_headers || ! old_cookie->cookie_id) {
357 DBG(r, "end chxj_update_cookie() (old_cookie is null)");
361 cookie = (cookie_t *)apr_palloc(r->pool, sizeof(cookie_t));
362 cookie->cookie_id = NULL;
364 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
365 entryp = chxj_apply_convrule(r, dconf->convrules);
367 DBG(r, "end chxj_update_cookie() no pattern");
370 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
371 DBG(r, "end chxj_update_cookie() CookieOff");
375 headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
376 hentryp = (apr_table_entry_t*)headers->elts;
378 chxj_delete_cookie(r, old_cookie->cookie_id);
379 chxj_delete_cookie_expire(r, old_cookie->cookie_id);
381 if (IS_COOKIE_LAZY(dconf)) {
383 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie->cookie_id);
386 DBG(r, "NO LAZY MODE");
387 cookie->cookie_id = alloc_cookie_id(r);
390 cookie->cookie_headers = old_cookie->cookie_headers;
391 store_string = apr_palloc(r->pool, 1);
393 hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;
395 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
396 if (ii) store_string = apr_pstrcat(r->pool,
401 DBG(r, "OLD COOKIE VALUE=[%s][%s]", hentryp[ii].key, hentryp[ii].val);
402 store_string = apr_pstrcat(r->pool,
412 #if defined(USE_MYSQL_COOKIE)
413 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
414 if (!chxj_update_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) {
415 ERR(r, "failed: chxj_update_cookie_mysql() cookie_id:[%s]", cookie->cookie_id);
422 #if defined(USE_MEMCACHE_COOKIE)
423 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
424 if (! chxj_update_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) {
425 ERR(r, "failed: chxj_update_cookie_memcache() cookie_id:[%s]", cookie->cookie_id);
431 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
432 if (! chxj_update_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) {
433 ERR(r, "failed: chxj_update_cookie_dbm() cookie_id:[%s]", cookie->cookie_id);
439 chxj_save_cookie_expire(r, cookie);
441 apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id);
445 DBG(r, "end chxj_update_cookie()");
452 * @return loaded data.
455 chxj_load_cookie(request_rec *r, char *cookie_id)
457 mod_chxj_config *dconf;
458 chxjconvrule_entry *entryp;
460 apr_table_t *load_cookie_table;
461 char *load_string = NULL;
468 DBG(r, "start chxj_load_cookie() cookie_id=[%s]", cookie_id);
469 chxj_cookie_expire_gc(r);
471 cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t));
472 cookie->cookie_headers = NULL;
473 cookie->cookie_id = chxj_url_decode(r->pool, apr_pstrdup(r->pool, cookie_id));
474 cookie->cookie_id = chxj_url_encode(r->pool, cookie->cookie_id);
477 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
478 entryp = chxj_apply_convrule(r, dconf->convrules);
480 DBG(r, "end chxj_load_cookie() no pattern");
483 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
484 DBG(r, "end chxj_load_cookie() CookieOff");
487 load_cookie_table = apr_table_make(r->pool, 0);
491 #if defined(USE_MYSQL_COOKIE)
492 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
493 if (! (load_string = chxj_load_cookie_mysql(r, dconf, cookie->cookie_id))) {
494 ERR(r, "%s:%d failed: chxj_load_cookie_mysql() cookie_id:[%s]", APLOG_MARK, cookie_id);
500 #if defined(USE_MEMCACHE_COOKIE)
501 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
502 if (! (load_string = chxj_load_cookie_memcache(r, dconf, cookie->cookie_id))) {
503 ERR(r, "%s:%d failed: chxj_load_cookie_memcache() cookie_id:[%s]", APLOG_MARK,cookie_id);
509 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
510 if (! (load_string = chxj_load_cookie_dbm(r, dconf, cookie->cookie_id))) {
511 ERR(r, "%s:%d failed: chxj_load_cookie_dbm() cookie_id:[%s]", APLOG_MARK,cookie_id);
518 DBG(r, "load_string=[%s]", load_string);
519 header_cookie = apr_palloc(r->pool, 1);
520 header_cookie[0] = 0;
524 pair = apr_strtok(load_string, "\n", &pstat);
528 DBG(r, "Cookie:[%s]", pair);
530 tmp_pair = apr_pstrdup(r->pool, pair);
531 val = strchr(tmp_pair, '=');
535 apr_table_add(load_cookie_table, key, val);
536 DBG(r, "ADD key:[%s] val:[%s]", key, val);
538 tmp_pair = apr_pstrdup(r->pool, pair);
539 tmp_sem = strchr(tmp_pair, ';');
543 if (check_valid_cookie_attribute(r, pair)) {
544 if (strlen(header_cookie))
545 header_cookie = apr_pstrcat(r->pool, header_cookie, ";", NULL);
547 header_cookie = apr_pstrcat(r->pool, header_cookie, tmp_pair, NULL);
550 if (strlen(header_cookie)) {
551 DBG(r, "ADD COOKIE to REQUEST HEADER:[%s]", header_cookie);
552 apr_table_add(r->headers_in, "Cookie", header_cookie);
555 cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(load_cookie_table);
557 if (apr_table_get(r->headers_in, "referer") == NULL) {
558 apr_table_setn(r->headers_in,
560 apr_table_get(load_cookie_table, REFERER_COOKIE_KEY));
564 * save cookie_id to request header.
566 apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id);
569 DBG(r, "end chxj_load_cookie()");
575 DBG(r, "end chxj_load_cookie()");
580 check_valid_cookie_attribute(request_rec *r, const char *value)
591 DBG(r, "start check_valid_cookie_attribute() value:[%s]", value);
593 domain_pair = path_pair = expire_pair = secure_pair = NULL;
594 p = apr_pstrdup(r->pool, value);
596 /* pass first pair */
597 first_pair = apr_strtok(p, ";", &pstat);
600 pair = apr_strtok(NULL, ";", &pstat);
602 pair = qs_trim_string(r->pool, pair);
603 if (STRNCASEEQ('d','D',"domain", pair, sizeof("domain")-1)) {
604 domain_pair = apr_pstrdup(r->pool, pair);
606 else if (STRNCASEEQ('p','P',"path", pair, sizeof("path")-1)) {
607 path_pair = apr_pstrdup(r->pool, pair);
609 else if (STRNCASEEQ('e','E',"expires", pair, sizeof("expires")-1)) {
610 expire_pair = apr_pstrdup(r->pool, pair);
612 else if (STRNCASEEQ('s','S',"secure", pair, sizeof("secure")-1)) {
613 secure_pair = apr_pstrdup(r->pool, pair);
618 if (!valid_domain(r, domain_pair)) {
619 DBG(r, "invalid domain. domain_pair:[%s]", domain_pair);
624 if (!valid_path(r, path_pair)) {
625 DBG(r, "invalid path. path_pair:[%s]", path_pair);
630 if (!valid_expires(r, expire_pair)) {
631 DBG(r, "invalid expire. expire_pair:[%s]", expire_pair);
636 if (!valid_secure(r, secure_pair)) {
637 DBG(r, "invalid secure. secure_pair:[%s]", secure_pair);
641 DBG(r, "end check_valid_cookie_attribute() value:[%s]", value);
647 check_valid_cookie_attribute_expires_only(request_rec *r, const char *value)
652 char *expire_pair = NULL;
655 DBG(r, "REQ[%X] start check_valid_cookie_attribute_expires_only() value:[%s]", (unsigned int)(apr_size_t)r, value);
658 p = apr_pstrdup(r->pool, value);
660 /* pass first pair */
661 first_pair = apr_strtok(p, ";", &pstat);
664 pair = apr_strtok(NULL, ";", &pstat);
666 pair = qs_trim_string(r->pool, pair);
667 if (STRNCASEEQ('e','E',"expires", pair, sizeof("expires")-1)) {
668 expire_pair = apr_pstrdup(r->pool, pair);
673 if (!valid_expires(r, expire_pair)) {
674 DBG(r, "REQ[%X] invalid expire. expire_pair:[%s]", (unsigned int)(apr_size_t)r, expire_pair);
678 DBG(r, "REQ[%X] end check_valid_cookie_attribute_expires_only() value:[%s]", (unsigned int)(apr_size_t)r, value);
684 valid_domain(request_rec *r, const char *value)
690 char *p = apr_pstrdup(r->pool, value);
691 const char *host = apr_table_get(r->headers_in, HTTP_HOST);
693 DBG(r, "start valid_domain() value:[%s]", value);
694 DBG(r, "host:[%s]", host);
698 name = apr_strtok(p,"=", &pstat);
699 name = qs_trim_string(r->pool, name);
700 val = apr_strtok(NULL, "=", &pstat);
701 val = qs_trim_string(r->pool, val);
704 if (chxj_strcasenrcmp(r->pool, host, val, strlen(val))) {
705 DBG(r, "not match domain. host domain:[%s] vs value:[%s]", host, val);
709 DBG(r, "end valid_domain() value:[%s]", value);
715 valid_path(request_rec *r, const char *value)
717 char *p = apr_pstrdup(r->pool, value);
724 DBG(r, "start valid_path() unparsed_uri:[%s] value:[%s]", r->unparsed_uri, value);
725 if (chxj_starts_with(r->unparsed_uri, "http://")) {
726 uri = strchr(&r->unparsed_uri[sizeof("http://")], '/');
728 uri = apr_pstrdup(r->pool, uri);
731 else if (chxj_starts_with(r->unparsed_uri, "https://")) {
732 uri = strchr(&r->unparsed_uri[sizeof("https://")], '/');
734 uri = apr_pstrdup(r->pool, uri);
737 else if (chxj_starts_with(r->unparsed_uri, "/")) {
738 uri = apr_pstrdup(r->pool, r->unparsed_uri);
741 uri = apr_pstrdup(r->pool, "/");
744 if ((tmp = strchr(uri, '?'))) {
747 DBG(r, "uri=[%s]", uri);
748 name = apr_strtok(p, "=", &pstat);
749 val = apr_strtok(NULL, "=", &pstat);
750 name = qs_trim_string(r->pool, name);
751 val = qs_trim_string(r->pool, val);
752 DBG(r, "name=[%s] val=[%s]", name, val);
754 DBG(r, "val:[%s] vs uri:[%s]", val, uri);
755 if (! chxj_starts_with(uri, val)) {
756 DBG(r, "end valid_path() unparsed_uri:[%s] value:[%s] (false)", r->unparsed_uri, value);
759 DBG(r, "end valid_path() unparsed_uri:[%s] value:[%s] (true)", r->unparsed_uri, value);
765 valid_expires(request_rec *r, const char *value)
769 char *p = apr_pstrdup(r->pool, value);
774 DBG(r, "start valid_expire() value:[%s]", value);
775 name = apr_strtok(p, "=", &pstat);
776 val = apr_strtok(NULL, "=", &pstat);
777 DBG(r, "name=[%s] val=[%s]", name, val);
778 now = apr_time_now();
779 expires = chxj_parse_cookie_expires(val);
781 DBG(r, "end valid_expire() value:[%s] (expired)", value);
785 DBG(r, "end valid_expire() value:[%s] (non expired)", value);
791 valid_secure(request_rec *r, const char *value)
794 DBG(r, "start valid_secure() value:[%s]", value);
795 scheme = chxj_apache_run_http_scheme(r);
796 if (strcasecmp("https", scheme)) {
797 DBG(r, "end valid_secure() value:[%s] (non secure)", value);
800 DBG(r, "end valid_secure() value:[%s] (secure)", value);
806 chxj_add_cookie_parameter(request_rec *r, char *value, cookie_t *cookie)
812 DBG(r, "start chxj_add_cookie_parameter() cookie_id=[%s]", (cookie) ? cookie->cookie_id : NULL);
814 dst = apr_pstrdup(r->pool, value);
819 if (!cookie->cookie_id)
822 if (chxj_cookie_check_host(r, value) != 0) {
823 DBG(r, "end chxj_add_cookie_parameter()(check host)");
827 qs = strchr(dst, '#');
829 name = apr_pstrdup(r->pool, qs);
833 qs = strchr(dst, '?');
835 dst = apr_psprintf(r->pool, "%s&%s=%s%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id, name);
838 dst = apr_psprintf(r->pool, "%s?%s=%s%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id, name);
841 DBG(r, "end chxj_add_cookie_parameter() dst=[%s]", dst);
846 DBG(r, "end chxj_add_cookie_parameter() (on_error)");
852 chxj_add_cookie_no_update_parameter(request_rec *r, char *value)
858 DBG(r, "REQ[%X] start chxj_add_cookie_no_update_parameter()", (unsigned int)(apr_size_t)r);
860 if (! value || ! *value) {
861 DBG(r, "REQ[%X] end chxj_add_cookie_parameter()(void value)", (unsigned int)(apr_size_t)r);
862 return apr_pstrdup(r->pool, "");
865 dst = apr_pstrdup(r->pool, value);
867 if (chxj_cookie_check_host(r, value) != 0) {
868 DBG(r, "REQ[%X] end chxj_add_cookie_parameter()(check host)", (unsigned int)(apr_size_t)r);
872 qs = strchr(dst, '#');
874 name = apr_pstrdup(r->pool, qs);
877 dst = apr_psprintf(r->pool, "%s%c%s=true%s", dst, (strchr(dst,'?')) ? '&' : '?',CHXJ_COOKIE_NOUPDATE_PARAM, name);
878 DBG(r, "REQ[%X] end chxj_add_cookie_no_update_parameter() dst=[%s]", (unsigned int)(apr_size_t)r, dst);
882 DBG(r, "REQ[%X] end chxj_add_cookie_no_update_parameter() (on_error)", (unsigned int)(apr_size_t)r);
888 chxj_cookie_check_host(request_rec *r, char *value)
891 mod_chxj_config *dconf;
893 DBG(r, "REQ[%X] start chxj_cookie_check_host()", (unsigned int)(apr_size_t)r);
894 DBG(r, "REQ[%X] hostname=[%s] vs Location:[%s]", (unsigned int)(apr_size_t)r, r->hostname, value);
896 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
898 hostnm = s_get_hostname_from_url(r, value);
900 if (dconf->allowed_cookie_domain) {
901 DBG(r, "REQ[%X] allowed_domain[%s] vs Location:[%s]", (unsigned int)(apr_size_t)r, dconf->allowed_cookie_domain, value);
902 if (chxj_strcasenrcmp(r->pool, hostnm, dconf->allowed_cookie_domain, strlen(dconf->allowed_cookie_domain))) {
903 DBG(r, "REQ[%X] end chxj_cookie_check_host() (false/allowed_domain)", (unsigned int)(apr_size_t)r);
907 DBG(r, "REQ[%X] end chxj_cookie_check_host() (true/allowed_domain)", (unsigned int)(apr_size_t)r);
912 if (strcasecmp(hostnm, r->hostname) == 0) {
913 DBG(r, "REQ[%X] end chxj_cookie_check_host() (true)", (unsigned int)(apr_size_t)r);
917 DBG(r, "REQ[%X] end chxj_cookie_check_host() (false)", (unsigned int)(apr_size_t)r);
922 DBG(r, "REQ[%X] end chxj_cookie_check_host() (true)", (unsigned int)(apr_size_t)r);
928 s_get_hostname_from_url(request_rec *r, char *value)
933 if (strncasecmp(value, "http://", 7) == 0 )
934 return s_cut_until_end_hostname(r, &value[7]);
936 if (strncasecmp(value, "https://", 8) == 0)
937 return s_cut_until_end_hostname(r, &value[8]);
944 s_cut_until_end_hostname(request_rec *r, char *value)
949 hostnm = sp = apr_pstrdup(r->pool, value);
951 if (*sp == '/'|| *sp == '?' || *sp == ':') {
962 chxj_delete_cookie(request_rec *r, const char *cookie_id)
965 mod_chxj_config *dconf;
967 DBG(r, "start chxj_delete_cookie()");
968 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
970 #if defined(USE_MYSQL_COOKIE)
971 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
972 if (! chxj_delete_cookie_mysql(r, dconf, cookie_id)) {
973 ERR(r, "failed: chxj_delete_cookie_mysql() cookie_id:[%s]", cookie_id);
974 DBG(r, "end chxj_delete_cookie()");
980 #if defined(USE_MEMCACHE_COOKIE)
981 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
982 if (! chxj_delete_cookie_memcache(r, dconf, cookie_id)) {
983 ERR(r, "failed: chxj_delete_cookie_memcache() cookie_id:[%s]", cookie_id);
984 DBG(r, "end chxj_delete_cookie()");
990 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
991 if (! chxj_delete_cookie_dbm(r, dconf, cookie_id)) {
992 ERR(r, "failed: chxj_delete_cookie_dbm() cookie_id:[%s]", cookie_id);
993 DBG(r, "end chxj_delete_cookie()");
998 DBG(r, "end chxj_delete_cookie()");
1006 chxj_save_cookie_expire(request_rec *r, cookie_t *cookie)
1009 mod_chxj_config *dconf;
1011 DBG(r, "start chxj_save_cookie_expire()");
1013 DBG(r, "cookie is NULL");
1016 if (!cookie->cookie_id) {
1017 DBG(r, "cookie->cookie_id is NULL");
1021 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1023 DBG(r, "dconf is NULL");
1027 #if defined(USE_MYSQL_COOKIE)
1028 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1029 if (! chxj_save_cookie_expire_mysql(r, dconf, cookie->cookie_id)) {
1030 ERR(r, "failed: chxj_save_cookie_expire_mysql() cookie_id:[%s]", cookie->cookie_id);
1031 DBG(r, "end chxj_save_cookie_expire()");
1037 #if defined(USE_MEMCACHE_COOKIE)
1038 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1039 if (! chxj_save_cookie_expire_memcache(r, dconf, cookie->cookie_id)) {
1040 ERR(r, "failed: chxj_save_cookie_expire_memcache() cookie_id:[%s]", cookie->cookie_id);
1041 DBG(r, "end chxj_save_cookie_expire()");
1047 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
1048 if (! chxj_save_cookie_expire_dbm(r, dconf, cookie->cookie_id)) {
1049 ERR(r, "failed: chxj_save_cookie_expire_dbm() cookie_id:[%s]", cookie->cookie_id);
1050 DBG(r, "end chxj_save_cookie_expire()");
1055 DBG(r, "end chxj_save_cookie_expire()");
1060 chxj_delete_cookie_expire(request_rec *r, char *cookie_id)
1063 mod_chxj_config *dconf;
1065 DBG(r, "start chxj_delete_cookie_expire()");
1067 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1069 #if defined(USE_MYSQL_COOKIE)
1070 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1071 if (! chxj_delete_cookie_expire_mysql(r, dconf, cookie_id)) {
1072 ERR(r, "failed: chxj_delete_cookie_expire_mysql() cookie_id:[%s]", cookie_id);
1078 #if defined(USE_MEMCACHE_COOKIE)
1079 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1080 if (!chxj_delete_cookie_expire_memcache(r, dconf, cookie_id)) {
1081 ERR(r, "failed: chxj_delete_cookie_expire_memcache() cookie_id:[%s]", cookie_id);
1087 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
1088 if (!chxj_delete_cookie_expire_dbm(r, dconf, cookie_id)) {
1089 ERR(r, "failed: chxj_delete_cookie_expire_dbm() cookie_id:[%s]", cookie_id);
1094 DBG(r, "end chxj_delete_cookie_expire()");
1099 chxj_cookie_expire_gc(request_rec *r)
1101 mod_chxj_config *dconf;
1104 DBG(r, "start chxj_cookie_expire_gc()");
1106 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1107 #if defined(USE_MYSQL_COOKIE)
1108 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1109 if (! chxj_cookie_expire_gc_mysql(r, dconf)) {
1110 ERR(r, "%s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_mysql()", APLOG_MARK);
1116 #if defined(USE_MEMCACHE_COOKIE)
1117 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1118 if (! chxj_cookie_expire_gc_memcache(r, dconf)) {
1119 ERR(r, "%s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_memcache()", APLOG_MARK);
1126 if (! chxj_cookie_expire_gc_dbm(r, dconf)) {
1127 ERR(r, "%s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_dbm()", APLOG_MARK);
1131 DBG(r, "end chxj_cookie_expire_gc()");
1135 chxj_parse_cookie_expires(const char *s)
1137 if (!s) return (apr_time_t)0;
1138 return apr_date_parse_rfc(s);
1143 __chxj_cookie_lock(request_rec *r, const char *filename, int line)
1145 mod_chxj_config *dconf;
1148 cookie_lock_t *ret = NULL;
1150 DBG(r, "start chxj_cookie_lock() call from %s:%d", filename, line);
1151 if ((rv = apr_proc_mutex_lock(global_cookie_mutex)) != APR_SUCCESS) {
1153 ERR(r, "%s:%d apr_proc_mutex_lock failure.(%d:%s)", APLOG_MARK, rv, apr_strerror(rv, errstr, 255));
1156 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1157 #if defined(USE_MYSQL_COOKIE)
1158 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1159 if (! chxj_cookie_lock_mysql(r, dconf)) {
1160 ERR(r, "%s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_mysql()", APLOG_MARK);
1164 ret = apr_palloc(r->pool, sizeof(*ret));
1165 memset(ret, 0, sizeof(*ret));
1168 #if defined(USE_MEMCACHE_COOKIE)
1169 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1170 if (! chxj_cookie_lock_memcache(r, dconf)) {
1171 ERR(r, "%s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_memcache()", APLOG_MARK);
1175 ret = apr_palloc(r->pool, sizeof(*ret));
1176 memset(ret, 0, sizeof(*ret));
1180 if (!(ret = chxj_cookie_lock_dbm(r, dconf))) {
1181 ERR(r, "%s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_dbm()", APLOG_MARK);
1182 DBG(r, "end chxj_cookie_lock() call from %s:%d", filename, line);
1186 DBG(r, "REQ:[%X] end chxj_cookie_lock() call from %s:%d", (unsigned int)(apr_size_t)r, filename, line);
1192 __chxj_cookie_unlock(request_rec *r, cookie_lock_t *lock, const char *filename, int line)
1194 mod_chxj_config *dconf;
1199 DBG(r, "start chxj_cookie_unlock() call from %s:%d", filename, line);
1201 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1202 #if defined(USE_MYSQL_COOKIE)
1203 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1204 if (! chxj_cookie_unlock_mysql(r, dconf)) {
1205 ERR(r, "failed: chxj_cookie_unlock_mysql()");
1207 goto end_chxj_cookie_unlock;
1212 #if defined(USE_MEMCACHE_COOKIE)
1213 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1214 if (! chxj_cookie_unlock_memcache(r, dconf)) {
1215 ERR(r, "failed: chxj_cookie_unlock_memcache()");
1217 goto end_chxj_cookie_unlock;
1223 if (! chxj_cookie_unlock_dbm(r, lock, dconf)) {
1224 ERR(r, "failed: chxj_cookie_unlock_dbm()");
1226 goto end_chxj_cookie_unlock;
1229 end_chxj_cookie_unlock:
1230 if ((rv = apr_proc_mutex_unlock(global_cookie_mutex)) != APR_SUCCESS) {
1232 ERR(r, "%s:%d apr_proc_mutex_unlock failure.(%d:%s)", APLOG_MARK, rv, apr_strerror(rv, errstr, 255));
1233 DBG(r, "end chxj_cookie_unlock() call from %s:%d", filename, line);
1236 DBG(r, "end chxj_cookie_unlock() call from %s:%d", filename, line);