2 * Copyright (C) 2005-2011 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,"REQ[%X] cookie_id=[%s]", TO_ADDR(r),cookie_id);
97 cookie_id = chxj_url_encode(r->pool,cookie_id);
99 DBG(r, "REQ[%X] cookie_id=[%s]", TO_ADDR(r),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 mod_chxj_req_config *req_conf;
119 chxjconvrule_entry *entryp;
120 apr_table_t *new_cookie_table;
123 cookie_t *old_cookie;
125 apr_uri_t parsed_uri;
130 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
132 apr_pool_create(&pool, r->pool);
134 cookie = (cookie_t*)apr_palloc(pool, sizeof(cookie_t));
135 cookie->cookie_id = NULL;
140 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
141 req_conf = chxj_get_module_config(r->request_config, &chxj_module);
142 /*-------------------------------------------------------------------------*/
143 /* already setup entryp if request_conf->user_agent is not null */
144 /*-------------------------------------------------------------------------*/
145 if (req_conf->user_agent) {
146 entryp = req_conf->entryp;
149 entryp = chxj_apply_convrule(r, dconf->convrules);
152 DBG(r,"REQ[%X] end %s() no pattern",TO_ADDR(r),__func__);
155 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT) && ! (entryp->action & CONVRULE_COOKIE_ONLY_BIT)) {
156 DBG(r,"REQ[%X] end %s() CookieOff",TO_ADDR(r),__func__);
162 headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
163 hentryp = (apr_table_entry_t*)headers->elts;
164 err_headers = (apr_array_header_t*)apr_table_elts(r->err_headers_out);
165 err_hentryp = (apr_table_entry_t*)err_headers->elts;
168 new_cookie_table = apr_table_make(pool, 0);
170 for (ii=0; ii<headers->nelts; ii++) {
171 if (strcasecmp(hentryp[ii].key, "Set-Cookie") == 0) {
172 DBG(r, "REQ[%X] cookie=[%s:%s]", TO_ADDR(r), hentryp[ii].key, hentryp[ii].val);
178 char *pair = apr_psprintf(pool, "%s:%s", hentryp[ii].key, hentryp[ii].val);
179 if (check_valid_cookie_attribute_expires_only(r, pair)) {
180 buff = apr_pstrdup(pool, hentryp[ii].val);
181 val = strchr(buff, '=');
185 apr_table_set(new_cookie_table, apr_pstrdup(pool, key), apr_pstrdup(pool, val));
186 if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++;
192 for (ii=0; ii<err_headers->nelts; ii++) {
193 if (strcasecmp(err_hentryp[ii].key, "Set-Cookie") == 0) {
194 DBG(r, "REQ[%X] cookie=[%s:%s]", TO_ADDR(r), err_hentryp[ii].key, err_hentryp[ii].val);
200 char *pair = apr_psprintf(pool, "%s:%s", err_hentryp[ii].key, err_hentryp[ii].val);
201 if (check_valid_cookie_attribute_expires_only(r, pair)) {
202 buff = apr_pstrdup(pool, err_hentryp[ii].val);
203 val = strchr(buff, '=');
207 apr_table_set(new_cookie_table, apr_pstrdup(pool, key), apr_pstrdup(pool, val));
208 if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++;
214 apr_table_unset(r->headers_out, "Set-Cookie");
215 apr_table_unset(r->err_headers_out, "Set-Cookie");
218 apr_uri_parse(pool,r->uri, &parsed_uri);
219 refer_string = apr_psprintf(pool,
221 chxj_run_http_scheme(r),
223 apr_uri_unparse(pool,
225 APR_URI_UNP_OMITSITEPART));
226 if (r->args && strlen(r->args)) {
227 refer_string = apr_pstrcat(pool, refer_string, "?", r->args, NULL);
229 apr_table_setn(new_cookie_table, REFERER_COOKIE_KEY, refer_string);
230 DBG(r, "REQ[%X] ADD REFER[%s]", TO_ADDR(r),refer_string);
236 * check input parameters
238 old_cookie_id = (char*)apr_table_get(r->headers_in, "CHXJ_COOKIE_ID");
240 old_cookie = chxj_load_cookie(r, old_cookie_id);
241 if (old_cookie && old_cookie->cookie_headers) {
242 hentryp = (apr_table_entry_t*)old_cookie->cookie_headers->elts;
243 for (ii=0; ii<old_cookie->cookie_headers->nelts; ii++) {
244 if (hentryp && apr_table_get(new_cookie_table, hentryp[ii].key) == NULL) {
245 apr_table_add(new_cookie_table, apr_pstrdup(pool, hentryp[ii].key), apr_pstrdup(pool, hentryp[ii].val));
249 chxj_delete_cookie(r, old_cookie_id);
250 chxj_delete_cookie_expire(r, old_cookie_id);
258 DBG(r,"REQ[%X] end %s() (no cookie)",TO_ADDR(r),__func__);
265 cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(new_cookie_table);
266 hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;
267 apr_size_t store_string_len = 0;
268 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
269 if (ii) store_string_len++;
270 store_string_len += (strlen(hentryp[ii].key) + strlen(hentryp[ii].val) + 1);
272 store_string = apr_palloc(pool, store_string_len + 1);
273 memset(store_string, 0, store_string_len + 1);
276 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
277 if (ii) store_string[npos++] = '\n';
278 memcpy(&store_string[npos], hentryp[ii].key, strlen(hentryp[ii].key));
279 npos += strlen(hentryp[ii].key);
280 store_string[npos++] = '=';
281 memcpy(&store_string[npos], hentryp[ii].val, strlen(hentryp[ii].val));
282 npos += strlen(hentryp[ii].val);
285 if (old_cookie_id && IS_COOKIE_LAZY(dconf)) {
286 DBG(r, "REQ[%X] LAZY COOKIE save",TO_ADDR(r));
287 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
289 else if (old_cookie_id && apr_table_get(r->headers_in, "X-Chxj-Cookie-No-Update")) {
290 DBG(r, "REQ[%X] NO UPDATE MODE",TO_ADDR(r));
291 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
294 if (old_cookie_id && apr_table_get(r->headers_in, "X-Chxj-Forward")) {
295 DBG(r, "REQ[%X] NO LAZY COOKIE(X-Chxj-Forward) save",TO_ADDR(r));
296 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
299 DBG(r, "REQ[%X] NO LAZY COOKIE save",TO_ADDR(r));
300 cookie->cookie_id = alloc_cookie_id(r);
304 DBG(r,"REQ[%X] TYPE:[%d]", TO_ADDR(r), dconf->cookie_store_type);
305 DBG(r,"REQ[%X] STORE STRING:=======================================================", TO_ADDR(r));
306 DBG(r,"REQ[%X] [%s]", TO_ADDR(r), store_string);
307 DBG(r,"REQ[%X] =======================================================:STORE STRING", TO_ADDR(r));
311 #if defined(USE_MYSQL_COOKIE)
312 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
313 if (! chxj_save_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) {
314 ERR(r, "%s:%d faild: chxj_save_cookie_mysql() cookie_id:[%s]", APLOG_MARK,cookie->cookie_id);
321 #if defined(USE_MEMCACHE_COOKIE)
322 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
323 if (! chxj_save_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) {
324 ERR(r, "%s:%d failed: chxj_save_cookie_memcache() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id);
331 if (IS_COOKIE_STORE_DBM(dconf->cookie_store_type) || ! done_proc) {
332 if (! chxj_save_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) {
333 ERR(r, "%s:%d failed: chxj_save_cookie_dbm() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id);
339 apr_table_unset(r->headers_out, "Set-Cookie");
340 apr_table_unset(r->err_headers_out, "Set-Cookie");
343 chxj_save_cookie_expire(r, cookie);
347 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
357 chxj_update_cookie(request_rec *r, cookie_t *old_cookie)
360 apr_array_header_t *headers;
361 apr_table_entry_t *hentryp;
363 mod_chxj_config *dconf;
364 mod_chxj_req_config *req_conf;
365 chxjconvrule_entry *entryp;
369 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
370 if (!old_cookie || ! old_cookie->cookie_headers || ! old_cookie->cookie_id) {
371 DBG(r,"REQ[%X] old_cookie is null",TO_ADDR(r));
372 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
376 cookie = (cookie_t *)apr_palloc(r->pool, sizeof(cookie_t));
377 cookie->cookie_id = NULL;
379 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
380 req_conf = chxj_get_module_config(r->request_config, &chxj_module);
381 /*-------------------------------------------------------------------------*/
382 /* already setup entryp if request_conf->user_agent is not null */
383 /*-------------------------------------------------------------------------*/
384 if (req_conf->user_agent) {
385 entryp = req_conf->entryp;
388 entryp = chxj_apply_convrule(r, dconf->convrules);
391 DBG(r,"REQ[%X] no pattern",TO_ADDR(r));
392 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
395 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
396 DBG(r,"REQ[%X] CookieOff",TO_ADDR(r));
397 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
401 headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
402 hentryp = (apr_table_entry_t*)headers->elts;
404 chxj_delete_cookie(r, old_cookie->cookie_id);
405 chxj_delete_cookie_expire(r, old_cookie->cookie_id);
407 if (IS_COOKIE_LAZY(dconf)) {
408 DBG(r,"REQ[%X] LAZY MODE",TO_ADDR(r));
409 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie->cookie_id);
412 DBG(r,"REQ[%X] NO LAZY MODE",TO_ADDR(r));
413 cookie->cookie_id = alloc_cookie_id(r);
416 cookie->cookie_headers = old_cookie->cookie_headers;
417 store_string = apr_palloc(r->pool, 1);
419 hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;
421 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
422 if (ii) store_string = apr_pstrcat(r->pool,
427 DBG(r,"REQ[%X] OLD COOKIE VALUE=[%s][%s]",TO_ADDR(r), hentryp[ii].key, hentryp[ii].val);
428 store_string = apr_pstrcat(r->pool,
438 #if defined(USE_MYSQL_COOKIE)
439 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
440 if (!chxj_update_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) {
441 ERR(r,"REQ[%X] failed: chxj_update_cookie_mysql() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
448 #if defined(USE_MEMCACHE_COOKIE)
449 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
450 if (! chxj_update_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) {
451 ERR(r, "REQ[%X] failed: chxj_update_cookie_memcache() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
457 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
458 if (! chxj_update_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) {
459 ERR(r, "REQ[%X] failed: chxj_update_cookie_dbm() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
465 chxj_save_cookie_expire(r, cookie);
467 apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id);
471 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
478 * @return loaded data.
481 chxj_load_cookie(request_rec *r, char *cookie_id)
483 mod_chxj_config *dconf;
484 mod_chxj_req_config *req_conf;
485 chxjconvrule_entry *entryp;
487 apr_table_t *load_cookie_table;
488 char *load_string = NULL;
495 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
496 DBG(r,"REQ[%X] cookie_id=[%s]", TO_ADDR(r), cookie_id);
497 chxj_cookie_expire_gc(r);
499 cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t));
500 cookie->cookie_headers = NULL;
501 cookie->cookie_id = chxj_url_decode(r->pool, apr_pstrdup(r->pool, cookie_id));
502 cookie->cookie_id = chxj_url_encode(r->pool, cookie->cookie_id);
505 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
506 req_conf = chxj_get_module_config(r->request_config, &chxj_module);
507 /*-------------------------------------------------------------------------*/
508 /* already setup entryp if request_conf->user_agent is not null */
509 /*-------------------------------------------------------------------------*/
510 if (req_conf->user_agent) {
511 entryp = req_conf->entryp;
514 entryp = chxj_apply_convrule(r, dconf->convrules);
517 DBG(r,"REQ[%X] pattern", TO_ADDR(r));
518 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
521 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT) && ! (entryp->action & CONVRULE_COOKIE_ONLY_BIT)) {
522 DBG(r,"REQ[%X] CookieOff", TO_ADDR(r));
523 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
526 load_cookie_table = apr_table_make(r->pool, 0);
530 #if defined(USE_MYSQL_COOKIE)
531 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
532 if (! (load_string = chxj_load_cookie_mysql(r, dconf, cookie->cookie_id))) {
533 ERR(r, "REQ[%X] %s:%d failed: chxj_load_cookie_mysql() cookie_id:[%s]", TO_ADDR(r),APLOG_MARK, cookie_id);
539 #if defined(USE_MEMCACHE_COOKIE)
540 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
541 if (! (load_string = chxj_load_cookie_memcache(r, dconf, cookie->cookie_id))) {
542 ERR(r, "REQ[%X] %s:%d failed: chxj_load_cookie_memcache() cookie_id:[%s]", TO_ADDR(r),APLOG_MARK,cookie_id);
548 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
549 if (! (load_string = chxj_load_cookie_dbm(r, dconf, cookie->cookie_id))) {
550 ERR(r, "REQ[%X] %s:%d failed: chxj_load_cookie_dbm() cookie_id:[%s]", TO_ADDR(r),APLOG_MARK,cookie_id);
557 DBG(r, "REQ[%X] load_string=[%s]", TO_ADDR(r), load_string);
558 header_cookie = apr_palloc(r->pool, 1);
559 header_cookie[0] = 0;
563 pair = apr_strtok(load_string, "\n", &pstat);
567 DBG(r,"REQ[%X] Cookie:[%s]", TO_ADDR(r), pair);
569 tmp_pair = apr_pstrdup(r->pool, pair);
570 val = strchr(tmp_pair, '=');
574 apr_table_add(load_cookie_table, key, val);
575 DBG(r,"REQ[%X] ADD key:[%s] val:[%s]", TO_ADDR(r), key, val);
577 tmp_pair = apr_pstrdup(r->pool, pair);
578 tmp_sem = strchr(tmp_pair, ';');
582 if (check_valid_cookie_attribute(r, pair)) {
583 if (strlen(header_cookie))
584 header_cookie = apr_pstrcat(r->pool, header_cookie, ";", NULL);
586 header_cookie = apr_pstrcat(r->pool, header_cookie, tmp_pair, NULL);
589 if (strlen(header_cookie)) {
590 DBG(r,"REQ[%X] ADD COOKIE to REQUEST HEADER:[%s]", TO_ADDR(r), header_cookie);
591 apr_table_add(r->headers_in, "Cookie", header_cookie);
594 cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(load_cookie_table);
596 if (apr_table_get(r->headers_in, "referer") == NULL) {
597 apr_table_setn(r->headers_in,
599 apr_table_get(load_cookie_table, REFERER_COOKIE_KEY));
603 * save cookie_id to request header.
605 apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id);
608 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
614 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
619 check_valid_cookie_attribute(request_rec *r, const char *value)
630 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
631 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r),value);
633 domain_pair = path_pair = expire_pair = secure_pair = NULL;
634 p = apr_pstrdup(r->pool, value);
636 /* pass first pair */
637 first_pair = apr_strtok(p, ";", &pstat);
640 pair = apr_strtok(NULL, ";", &pstat);
642 pair = qs_trim_string(r->pool, pair);
643 if (STRNCASEEQ('d','D',"domain", pair, sizeof("domain")-1)) {
644 domain_pair = apr_pstrdup(r->pool, pair);
646 else if (STRNCASEEQ('p','P',"path", pair, sizeof("path")-1)) {
647 path_pair = apr_pstrdup(r->pool, pair);
649 else if (STRNCASEEQ('e','E',"expires", pair, sizeof("expires")-1)) {
650 expire_pair = apr_pstrdup(r->pool, pair);
652 else if (STRNCASEEQ('s','S',"secure", pair, sizeof("secure")-1)) {
653 secure_pair = apr_pstrdup(r->pool, pair);
658 if (!valid_domain(r, domain_pair)) {
659 DBG(r,"REQ[%X] invalid domain. domain_pair:[%s]", TO_ADDR(r),domain_pair);
660 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
665 if (!valid_path(r, path_pair)) {
666 DBG(r,"REQ[%X] invalid path. path_pair:[%s]", TO_ADDR(r),path_pair);
667 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
672 if (!valid_expires(r, expire_pair)) {
673 DBG(r,"REQ[%X] invalid expire. expire_pair:[%s]", TO_ADDR(r),expire_pair);
674 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
679 if (!valid_secure(r, secure_pair)) {
680 DBG(r,"REQ[%X] invalid secure. secure_pair:[%s]", TO_ADDR(r),secure_pair);
681 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
685 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r),value);
686 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
692 check_valid_cookie_attribute_expires_only(request_rec *r, const char *value)
697 char *expire_pair = NULL;
700 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
701 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
704 p = apr_pstrdup(r->pool, value);
706 /* pass first pair */
707 first_pair = apr_strtok(p, ";", &pstat);
710 pair = apr_strtok(NULL, ";", &pstat);
712 pair = qs_trim_string(r->pool, pair);
713 if (STRNCASEEQ('e','E',"expires", pair, sizeof("expires")-1)) {
714 expire_pair = apr_pstrdup(r->pool, pair);
719 if (!valid_expires(r, expire_pair)) {
720 DBG(r,"REQ[%X] invalid expire. expire_pair:[%s]", TO_ADDR(r), expire_pair);
721 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
725 DBG(r,"REQ[%X] value:[%s]",TO_ADDR(r), value);
726 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
732 valid_domain(request_rec *r, const char *value)
738 char *p = apr_pstrdup(r->pool, value);
739 char *host = (char *)apr_table_get(r->headers_in, HTTP_HOST);
741 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
742 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
744 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
745 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
748 DBG(r, "REQ[%X] host:[%s]", TO_ADDR(r), host);
749 host = s_cut_until_end_hostname(r, apr_pstrdup(r->pool, host));
750 DBG(r, "REQ[%X] host:[%s](after s_cut_until_end_hostname())", TO_ADDR(r), host);
752 name = apr_strtok(p,"=", &pstat);
753 name = qs_trim_string(r->pool, name);
754 val = apr_strtok(NULL, "=", &pstat);
755 val = qs_trim_string(r->pool, val);
758 if (chxj_strcasenrcmp(r->pool, host, val, strlen(val))) {
759 DBG(r,"REQ[%X] not match domain. host domain:[%s] vs value:[%s]", TO_ADDR(r), host, val);
760 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
761 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
765 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
766 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
772 valid_path(request_rec *r, const char *value)
774 char *p = apr_pstrdup(r->pool, value);
781 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
782 DBG(r,"REQ[%X] unparsed_uri:[%s] value:[%s]", TO_ADDR(r),r->unparsed_uri, value);
783 if (chxj_starts_with(r->unparsed_uri, "http://")) {
784 uri = strchr(&r->unparsed_uri[sizeof("http://")], '/');
786 uri = apr_pstrdup(r->pool, uri);
789 else if (chxj_starts_with(r->unparsed_uri, "https://")) {
790 uri = strchr(&r->unparsed_uri[sizeof("https://")], '/');
792 uri = apr_pstrdup(r->pool, uri);
795 else if (chxj_starts_with(r->unparsed_uri, "/")) {
796 uri = apr_pstrdup(r->pool, r->unparsed_uri);
799 uri = apr_pstrdup(r->pool, "/");
802 if ((tmp = strchr(uri, '?'))) {
805 DBG(r,"REQ[%X] uri=[%s]", TO_ADDR(r),uri);
806 name = apr_strtok(p, "=", &pstat);
807 val = apr_strtok(NULL, "=", &pstat);
808 name = qs_trim_string(r->pool, name);
809 val = qs_trim_string(r->pool, val);
810 DBG(r,"REQ[%X] name=[%s] val=[%s]", TO_ADDR(r),name, val);
812 DBG(r, "REQ[%X] val:[%s] vs uri:[%s]", TO_ADDR(r),val, uri);
813 if (! chxj_starts_with(uri, val)) {
814 DBG(r,"REQ[%X] unparsed_uri:[%s] value:[%s] (false)",TO_ADDR(r), r->unparsed_uri, value);
815 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
818 DBG(r,"REQ[%X] unparsed_uri:[%s] value:[%s] (true)", TO_ADDR(r),r->unparsed_uri, value);
819 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
825 valid_expires(request_rec *r, const char *value)
829 char *p = apr_pstrdup(r->pool, value);
834 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
835 DBG(r,"REQ[%X] value:[%s]",TO_ADDR(r),value);
836 name = apr_strtok(p, "=", &pstat);
837 val = apr_strtok(NULL, "=", &pstat);
838 DBG(r,"REQ[%X] name=[%s] val=[%s]", TO_ADDR(r),name, val);
839 now = apr_time_now();
840 expires = chxj_parse_cookie_expires(val);
842 DBG(r,"REQ[%X] value:[%s] (expired)", TO_ADDR(r),value);
843 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
847 DBG(r,"REQ[%X] value:[%s] (non expired)", TO_ADDR(r),value);
848 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
854 valid_secure(request_rec *r, const char *value)
857 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
858 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r),value);
859 scheme = chxj_apache_run_http_scheme(r);
860 if (strcasecmp("https", scheme)) {
861 DBG(r,"REQ[%X] value:[%s] (non secure)", TO_ADDR(r),value);
862 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
865 DBG(r,"REQ[%X] value:[%s] (secure)", TO_ADDR(r),value);
866 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
872 chxj_add_cookie_parameter(request_rec *r, char *value, cookie_t *cookie)
878 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
879 DBG(r,"REQ[%X] cookie_id=[%s]", TO_ADDR(r), (cookie) ? cookie->cookie_id : NULL);
881 dst = apr_pstrdup(r->pool, value);
886 if (!cookie->cookie_id)
889 if (chxj_cookie_check_host(r, value) != 0) {
890 DBG(r,"REQ[%X] (check host)", TO_ADDR(r));
891 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
895 qs = strchr(dst, '#');
897 name = apr_pstrdup(r->pool, qs);
901 qs = strchr(dst, '?');
904 qs = chxj_delete_chxj_cc_param(r, ++qs);
905 DBG(r, "REQ[%X] qs:[%s]",TO_ADDR(r), qs);
907 if (qs && strlen(qs)) {
908 dst = apr_psprintf(r->pool, "%s?%s", dst, qs);
912 dst = apr_psprintf(r->pool, "%s&%s=%s%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id, name);
915 dst = apr_psprintf(r->pool, "%s?%s=%s%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id, name);
918 DBG(r,"REQ[%X] dst=[%s]", TO_ADDR(r), dst);
919 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
924 DBG(r,"REQ[%X] (on_error)", TO_ADDR(r));
925 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
931 chxj_add_cookie_no_update_parameter(request_rec *r, char *value)
937 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
939 if (! value || ! *value) {
940 DBG(r,"REQ[%X] (void value)", TO_ADDR(r));
941 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
942 return apr_pstrdup(r->pool, "");
945 dst = apr_pstrdup(r->pool, value);
947 if (chxj_cookie_check_host(r, value) != 0) {
948 DBG(r,"REQ[%X] (check host)", TO_ADDR(r));
949 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
953 qs = strchr(dst, '#');
955 name = apr_pstrdup(r->pool, qs);
958 dst = apr_psprintf(r->pool, "%s%c%s=true%s", dst, (strchr(dst,'?')) ? '&' : '?',CHXJ_COOKIE_NOUPDATE_PARAM, name);
959 DBG(r,"REQ[%X] dst=[%s]", TO_ADDR(r), dst);
960 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
964 DBG(r,"REQ[%X] (on_error)", TO_ADDR(r));
965 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
971 chxj_cookie_check_host(request_rec *r, char *value)
974 mod_chxj_config *dconf;
976 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
977 DBG(r,"REQ[%X] hostname=[%s] vs Location:[%s]", TO_ADDR(r), r->hostname, value);
979 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
981 hostnm = s_get_hostname_from_url(r, value);
983 if (dconf->allowed_cookie_domain) {
984 DBG(r, "REQ[%X] allowed_domain[%s] vs Location:[%s]", TO_ADDR(r), dconf->allowed_cookie_domain, value);
985 if (chxj_strcasenrcmp(r->pool, hostnm, dconf->allowed_cookie_domain, strlen(dconf->allowed_cookie_domain))) {
986 DBG(r,"REQ[%X] (false/allowed_domain)", TO_ADDR(r));
987 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
991 DBG(r,"REQ[%X] (true/allowed_domain)", TO_ADDR(r));
992 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
997 if (strcasecmp(hostnm, r->hostname) == 0) {
998 DBG(r,"REQ[%X] (true)", TO_ADDR(r));
999 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1003 DBG(r,"REQ[%X] (false)", TO_ADDR(r));
1004 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1009 DBG(r,"REQ[%X] (true)", TO_ADDR(r));
1010 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1016 s_get_hostname_from_url(request_rec *r, char *value)
1021 if (strncasecmp(value, "http://", 7) == 0 )
1022 return s_cut_until_end_hostname(r, &value[7]);
1024 if (strncasecmp(value, "https://", 8) == 0)
1025 return s_cut_until_end_hostname(r, &value[8]);
1032 s_cut_until_end_hostname(request_rec *r, char *value)
1037 hostnm = sp = apr_pstrdup(r->pool, value);
1039 if (*sp == '/'|| *sp == '?' || *sp == ':') {
1050 chxj_delete_cookie(request_rec *r, const char *cookie_id)
1053 mod_chxj_config *dconf;
1055 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1056 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1058 #if defined(USE_MYSQL_COOKIE)
1059 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1060 if (! chxj_delete_cookie_mysql(r, dconf, cookie_id)) {
1061 ERR(r,"REQ[%X] failed: chxj_delete_cookie_mysql() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1062 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1068 #if defined(USE_MEMCACHE_COOKIE)
1069 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1070 if (! chxj_delete_cookie_memcache(r, dconf, cookie_id)) {
1071 ERR(r,"REQ[%X] failed: chxj_delete_cookie_memcache() cookie_id:[%s]", TO_ADDR(r), cookie_id);
1072 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1078 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
1079 if (! chxj_delete_cookie_dbm(r, dconf, cookie_id)) {
1080 ERR(r,"REQ[%X] failed: chxj_delete_cookie_dbm() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1081 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1086 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1094 chxj_save_cookie_expire(request_rec *r, cookie_t *cookie)
1097 mod_chxj_config *dconf;
1099 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1101 DBG(r,"REQ[%X] cookie is NULL",TO_ADDR(r));
1102 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1105 if (!cookie->cookie_id) {
1106 DBG(r,"REQ[%X] cookie->cookie_id is NULL",TO_ADDR(r));
1107 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1111 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1113 DBG(r,"REQ[%X] dconf is NULL",TO_ADDR(r));
1114 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1118 #if defined(USE_MYSQL_COOKIE)
1119 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1120 if (! chxj_save_cookie_expire_mysql(r, dconf, cookie->cookie_id)) {
1121 ERR(r,"REQ[%X] failed: chxj_save_cookie_expire_mysql() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
1122 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1128 #if defined(USE_MEMCACHE_COOKIE)
1129 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1130 if (! chxj_save_cookie_expire_memcache(r, dconf, cookie->cookie_id)) {
1131 ERR(r,"REQ[%X] failed: chxj_save_cookie_expire_memcache() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
1132 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1138 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
1139 if (! chxj_save_cookie_expire_dbm(r, dconf, cookie->cookie_id)) {
1140 ERR(r,"REQ[%X] failed: chxj_save_cookie_expire_dbm() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
1141 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1146 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1151 chxj_delete_cookie_expire(request_rec *r, char *cookie_id)
1154 mod_chxj_config *dconf;
1156 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1158 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1160 #if defined(USE_MYSQL_COOKIE)
1161 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1162 if (! chxj_delete_cookie_expire_mysql(r, dconf, cookie_id)) {
1163 ERR(r,"REQ[%X] failed: chxj_delete_cookie_expire_mysql() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1164 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1170 #if defined(USE_MEMCACHE_COOKIE)
1171 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1172 if (!chxj_delete_cookie_expire_memcache(r, dconf, cookie_id)) {
1173 ERR(r,"REQ[%X] failed: chxj_delete_cookie_expire_memcache() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1174 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1180 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
1181 if (!chxj_delete_cookie_expire_dbm(r, dconf, cookie_id)) {
1182 ERR(r,"REQ[%X] failed: chxj_delete_cookie_expire_dbm() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1183 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1188 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1193 chxj_cookie_expire_gc(request_rec *r)
1195 mod_chxj_config *dconf;
1198 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1200 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1201 #if defined(USE_MYSQL_COOKIE)
1202 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1203 if (! chxj_cookie_expire_gc_mysql(r, dconf)) {
1204 ERR(r,"REQ[%X] %s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_mysql()", TO_ADDR(r),APLOG_MARK);
1205 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1211 #if defined(USE_MEMCACHE_COOKIE)
1212 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1213 if (! chxj_cookie_expire_gc_memcache(r, dconf)) {
1214 ERR(r,"REQ[%X] %s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_memcache()", TO_ADDR(r),APLOG_MARK);
1215 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1222 if (! chxj_cookie_expire_gc_dbm(r, dconf)) {
1223 ERR(r,"REQ[%X] %s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_dbm()", TO_ADDR(r),APLOG_MARK);
1224 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1228 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1232 chxj_parse_cookie_expires(const char *s)
1234 if (!s) return (apr_time_t)0;
1235 return apr_date_parse_rfc(s);
1240 __chxj_cookie_lock(request_rec *r, const char *filename, int line)
1242 mod_chxj_config *dconf;
1245 cookie_lock_t *ret = NULL;
1247 DBG(r,"REQ[%X] start %s() call from %s:%d",TO_ADDR(r),__func__, filename,line);
1248 if ((rv = apr_proc_mutex_lock(global_cookie_mutex)) != APR_SUCCESS) {
1250 ERR(r,"REQ[%X] %s:%d apr_proc_mutex_lock failure.(%d:%s)", TO_ADDR(r),APLOG_MARK, rv, apr_strerror(rv, errstr, 255));
1251 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1254 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1255 #if defined(USE_MYSQL_COOKIE)
1256 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1257 if (! chxj_cookie_lock_mysql(r, dconf)) {
1258 ERR(r,"REQ[%X] %s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_mysql()", TO_ADDR(r),APLOG_MARK);
1259 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1263 ret = apr_palloc(r->pool, sizeof(*ret));
1264 memset(ret, 0, sizeof(*ret));
1267 #if defined(USE_MEMCACHE_COOKIE)
1268 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1269 if (! chxj_cookie_lock_memcache(r, dconf)) {
1270 ERR(r,"REQ[%X] %s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_memcache()", TO_ADDR(r),APLOG_MARK);
1271 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1275 ret = apr_palloc(r->pool, sizeof(*ret));
1276 memset(ret, 0, sizeof(*ret));
1280 if (!(ret = chxj_cookie_lock_dbm(r, dconf))) {
1281 ERR(r,"REQ[%X] %s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_dbm()", TO_ADDR(r),APLOG_MARK);
1282 DBG(r,"REQ[%X] end %s() call from %s:%d",TO_ADDR(r),__func__,filename,line);
1286 DBG(r,"REQ[%X] end %s() call from %s:%d",TO_ADDR(r),__func__,filename,line);
1292 __chxj_cookie_unlock(request_rec *r, cookie_lock_t *lock, const char *filename, int line)
1294 mod_chxj_config *dconf;
1299 DBG(r,"REQ[%X] start %s() call from %s:%d", TO_ADDR(r),__func__,filename, line);
1301 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1302 #if defined(USE_MYSQL_COOKIE)
1303 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1304 if (! chxj_cookie_unlock_mysql(r, dconf)) {
1305 ERR(r,"REQ[%X] failed: chxj_cookie_unlock_mysql()",TO_ADDR(r));
1307 goto end_chxj_cookie_unlock;
1312 #if defined(USE_MEMCACHE_COOKIE)
1313 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1314 if (! chxj_cookie_unlock_memcache(r, dconf)) {
1315 ERR(r,"REQ[%X] failed: chxj_cookie_unlock_memcache()",TO_ADDR(r));
1317 goto end_chxj_cookie_unlock;
1323 if (! chxj_cookie_unlock_dbm(r, lock, dconf)) {
1324 ERR(r,"REQ[%X] failed: chxj_cookie_unlock_dbm()",TO_ADDR(r));
1326 goto end_chxj_cookie_unlock;
1329 end_chxj_cookie_unlock:
1330 if ((rv = apr_proc_mutex_unlock(global_cookie_mutex)) != APR_SUCCESS) {
1332 ERR(r,"REQ[%X] %s:%d apr_proc_mutex_unlock failure.(%d:%s)", TO_ADDR(r),APLOG_MARK, rv, apr_strerror(rv, errstr, 255));
1333 DBG(r,"REQ[%X] end %s() call from %s:%d", TO_ADDR(r),__func__,filename, line);
1336 DBG(r,"REQ[%X] end %s() call from %s:%d", TO_ADDR(r),__func__,filename, line);
1342 #include "chxj_encoding.h"
1344 s_convert_a_tag(request_rec *r, const char *s, apr_size_t *len, cookie_t *cookie)
1347 ap_regex_t *regexp = NULL;
1352 apr_pool_create(&pool, r->pool);
1353 regexp = ap_pregcomp(pool, "(<a[^>]*>)", AP_REG_EXTENDED|AP_REG_ICASE);
1355 qs_init_malloc(&doc);
1356 qs_init_root_node(&doc);
1359 ap_regmatch_t match[10];
1360 if (ap_regexec((const ap_regex_t *)regexp, &s[nowpos], (apr_size_t)regexp->re_nsub + 1, match, 0) == 0) {
1361 apr_size_t plen = match[1].rm_so;
1363 char *tmpstr = apr_palloc(pool, plen + 1);
1364 memset(tmpstr, 0, plen + 1);
1365 memcpy(tmpstr, &s[nowpos], plen);
1366 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1371 char *matchstr = ap_pregsub(pool, "$1", &s[nowpos], regexp->re_nsub + 1, match);
1373 Node *node = qs_parse_tag(&doc, matchstr, strlen(matchstr) - 1);
1376 DBG(r,"REQ[%X] matchstr:[%s]", TO_ADDR(r),matchstr);
1377 dst = apr_pstrcat(pool, (dst) ? dst : "", "<a ", NULL);
1378 for (attr = qs_get_attr(&doc,node);
1380 attr = qs_get_next_attr(&doc,attr)) {
1381 char *name = qs_get_attr_name(&doc,attr);
1382 char *value = qs_get_attr_value(&doc,attr);
1383 DBG(r,"REQ[%X] name:[%s] value=[%s]",TO_ADDR(r), name, value);
1384 if (STRCASEEQ('h', 'H', "href", name)
1385 && ! chxj_starts_with(value, "mailto:")
1386 && ! chxj_starts_with(value, "tel:")) {
1387 char *flgp = strchr(value, '#');
1390 int flgl = strlen(flgp);
1391 flgsv = apr_palloc(pool, flgl+1);
1392 memset(flgsv, 0, flgl + 1);
1393 memcpy(flgsv, flgp, flgl);
1396 if (strchr(value, '?') != 0) {
1397 value = apr_pstrcat(pool, value, "&_chxj_cc=", cookie->cookie_id, NULL);
1400 value = apr_pstrcat(pool, value, "?_chxj_cc=", cookie->cookie_id, NULL);
1403 value = apr_pstrcat(pool, value, flgsv, NULL);
1405 dst = apr_pstrcat(pool, (dst) ? dst : "", "href='", value, "' ", NULL);
1408 dst = apr_pstrcat(pool, (dst) ? dst : "", name, "='", value, "' ", NULL);
1411 dst = apr_pstrcat(pool, (dst) ? dst : "", ">", NULL);
1412 plen += strlen(matchstr);
1421 if ((apr_size_t)nowpos < *len) {
1422 apr_size_t plen = *len - nowpos;
1423 char *tmpstr = apr_palloc(pool, plen + 1);
1424 memset(tmpstr, 0, plen+1);
1425 memcpy(tmpstr, &s[nowpos], plen);
1426 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1433 s_convert_img_tag(request_rec *r, const char *s, apr_size_t *len, cookie_t *cookie)
1436 ap_regex_t *regexp = NULL;
1441 apr_pool_create(&pool, r->pool);
1442 regexp = ap_pregcomp(pool, "(<img[^>]*>)", AP_REG_EXTENDED|AP_REG_ICASE);
1444 qs_init_malloc(&doc);
1445 qs_init_root_node(&doc);
1448 ap_regmatch_t match[10];
1449 if (ap_regexec((const ap_regex_t *)regexp, &s[nowpos], (apr_size_t)regexp->re_nsub + 1, match, 0) == 0) {
1450 apr_size_t plen = match[1].rm_so;
1452 char *tmpstr = apr_palloc(pool, plen + 1);
1453 memset(tmpstr, 0, plen + 1);
1454 memcpy(tmpstr, &s[nowpos], plen);
1455 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1460 char *matchstr = ap_pregsub(pool, "$1", &s[nowpos], regexp->re_nsub + 1, match);
1462 Node *node = qs_parse_tag(&doc, matchstr, strlen(matchstr) - 1);
1465 DBG(r,"REQ[%X] matchstr:[%s]", TO_ADDR(r),matchstr);
1466 dst = apr_pstrcat(pool, (dst) ? dst : "", "<img ", NULL);
1467 for (attr = qs_get_attr(&doc,node);
1469 attr = qs_get_next_attr(&doc,attr)) {
1470 char *name = qs_get_attr_name(&doc,attr);
1471 char *value = qs_get_attr_value(&doc,attr);
1472 DBG(r,"REQ[%X] name:[%s] value=[%s]", TO_ADDR(r),name, value);
1473 if (STRCASEEQ('s', 'S', "src", name)) {
1474 if (strchr(value, '?') != 0) {
1475 value = apr_pstrcat(pool, value, "&_chxj_cc=", cookie->cookie_id, "&_chxj_nc=true", NULL);
1478 value = apr_pstrcat(pool, value, "?_chxj_cc=", cookie->cookie_id, "&_chxj_nc=true", NULL);
1480 dst = apr_pstrcat(pool, (dst) ? dst : "", "src='", value, "' ", NULL);
1483 dst = apr_pstrcat(pool, (dst) ? dst : "", name, "='", value, "' ", NULL);
1486 dst = apr_pstrcat(pool, (dst) ? dst : "", "/>", NULL);
1487 plen += strlen(matchstr);
1496 if ((apr_size_t)nowpos < *len) {
1497 apr_size_t plen = *len - nowpos;
1498 char *tmpstr = apr_palloc(pool, plen + 1);
1499 memset(tmpstr, 0, plen+1);
1500 memcpy(tmpstr, &s[nowpos], plen);
1501 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1508 s_convert_form_tag(request_rec *r, const char *s, apr_size_t *len, cookie_t *cookie)
1511 ap_regex_t *regexp = NULL;
1517 apr_pool_create(&pool, r->pool);
1518 regexp = ap_pregcomp(pool, "(</form>)", AP_REG_EXTENDED|AP_REG_ICASE);
1520 qs_init_malloc(&doc);
1521 qs_init_root_node(&doc);
1522 cookie_id = chxj_url_decode(pool, cookie->cookie_id);
1525 ap_regmatch_t match[10];
1526 if (ap_regexec((const ap_regex_t *)regexp, &s[nowpos], (apr_size_t)regexp->re_nsub + 1, match, 0) == 0) {
1527 apr_size_t plen = match[1].rm_so;
1529 char *tmpstr = apr_palloc(pool, plen + 1);
1530 memset(tmpstr, 0, plen + 1);
1531 memcpy(tmpstr, &s[nowpos], plen);
1532 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1537 char *matchstr = ap_pregsub(pool, "$1", &s[nowpos], regexp->re_nsub + 1, match);
1539 DBG(r,"REQ[%X] matchstr:[%s]",TO_ADDR(r),matchstr);
1540 dst = apr_pstrcat(pool, (dst) ? dst : "", "<input type='hidden' name='_chxj_cc' value='", cookie_id, "' />", matchstr, NULL);
1541 plen += strlen(matchstr);
1550 if ((apr_size_t)nowpos < *len) {
1551 apr_size_t plen = *len - nowpos;
1552 char *tmpstr = apr_palloc(pool, plen + 1);
1553 memset(tmpstr, 0, plen + 1);
1554 memcpy(tmpstr, &s[nowpos], plen);
1555 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1563 chxj_cookie_only_mode(request_rec *r, const char *src, apr_size_t *len, cookie_t* cookie)
1569 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1570 s = chxj_encoding(r, src, len);
1572 dst = s_convert_a_tag(r, s, len, cookie);
1573 dst = s_convert_img_tag(r, dst, len, cookie);
1574 dst = s_convert_form_tag(r, dst, len, cookie);
1576 result = chxj_rencoding(r, dst, len, NULL);
1577 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);