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);
109 chxj_save_cookie(request_rec *r)
112 apr_array_header_t *headers;
113 apr_table_entry_t *hentryp;
114 apr_array_header_t *err_headers;
115 apr_table_entry_t *err_hentryp;
118 mod_chxj_config *dconf;
119 mod_chxj_req_config *req_conf;
120 chxjconvrule_entry *entryp;
121 apr_table_t *new_cookie_table;
124 cookie_t *old_cookie;
126 apr_uri_t parsed_uri;
131 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
133 apr_pool_create(&pool, r->pool);
135 cookie = (cookie_t*)apr_palloc(pool, sizeof(cookie_t));
136 cookie->cookie_id = NULL;
141 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
142 req_conf = chxj_get_req_config(r);
143 /*-------------------------------------------------------------------------*/
144 /* already setup entryp if request_conf->user_agent is not null */
145 /*-------------------------------------------------------------------------*/
146 if (req_conf->user_agent) {
147 entryp = req_conf->entryp;
150 entryp = chxj_apply_convrule(r, dconf->convrules);
153 DBG(r,"REQ[%X] end %s() no pattern",TO_ADDR(r),__func__);
156 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT) && ! (entryp->action & CONVRULE_COOKIE_ONLY_BIT)) {
157 DBG(r,"REQ[%X] end %s() CookieOff",TO_ADDR(r),__func__);
163 headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
164 hentryp = (apr_table_entry_t*)headers->elts;
165 err_headers = (apr_array_header_t*)apr_table_elts(r->err_headers_out);
166 err_hentryp = (apr_table_entry_t*)err_headers->elts;
169 new_cookie_table = apr_table_make(pool, 0);
171 for (ii=0; ii<headers->nelts; ii++) {
172 if (strcasecmp(hentryp[ii].key, "Set-Cookie") == 0) {
173 DBG(r, "REQ[%X] cookie=[%s:%s]", TO_ADDR(r), hentryp[ii].key, hentryp[ii].val);
179 char *pair = apr_psprintf(pool, "%s:%s", hentryp[ii].key, hentryp[ii].val);
180 if (check_valid_cookie_attribute_expires_only(r, pair)) {
181 buff = apr_pstrdup(pool, hentryp[ii].val);
182 val = strchr(buff, '=');
186 apr_table_set(new_cookie_table, apr_pstrdup(pool, key), apr_pstrdup(pool, val));
187 if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++;
193 for (ii=0; ii<err_headers->nelts; ii++) {
194 if (strcasecmp(err_hentryp[ii].key, "Set-Cookie") == 0) {
195 DBG(r, "REQ[%X] cookie=[%s:%s]", TO_ADDR(r), err_hentryp[ii].key, err_hentryp[ii].val);
201 char *pair = apr_psprintf(pool, "%s:%s", err_hentryp[ii].key, err_hentryp[ii].val);
202 if (check_valid_cookie_attribute_expires_only(r, pair)) {
203 buff = apr_pstrdup(pool, err_hentryp[ii].val);
204 val = strchr(buff, '=');
208 apr_table_set(new_cookie_table, apr_pstrdup(pool, key), apr_pstrdup(pool, val));
209 if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++;
216 apr_table_unset(r->headers_out, "Set-Cookie");
217 apr_table_unset(r->err_headers_out, "Set-Cookie");
221 apr_uri_parse(pool,r->uri, &parsed_uri);
222 refer_string = apr_psprintf(pool,
224 chxj_run_http_scheme(r),
226 apr_uri_unparse(pool,
228 APR_URI_UNP_OMITSITEPART));
229 if (r->args && strlen(r->args)) {
230 refer_string = apr_pstrcat(pool, refer_string, "?", r->args, NULL);
232 apr_table_setn(new_cookie_table, REFERER_COOKIE_KEY, refer_string);
233 DBG(r, "REQ[%X] ADD REFER[%s]", TO_ADDR(r),refer_string);
239 * check input parameters
241 old_cookie_id = (char*)apr_table_get(r->headers_in, "CHXJ_COOKIE_ID");
243 old_cookie = chxj_load_cookie(r, old_cookie_id);
244 if (old_cookie && old_cookie->cookie_headers) {
245 hentryp = (apr_table_entry_t*)old_cookie->cookie_headers->elts;
246 for (ii=0; ii<old_cookie->cookie_headers->nelts; ii++) {
247 if (hentryp && apr_table_get(new_cookie_table, hentryp[ii].key) == NULL) {
248 apr_table_add(new_cookie_table, apr_pstrdup(pool, hentryp[ii].key), apr_pstrdup(pool, hentryp[ii].val));
252 chxj_delete_cookie(r, old_cookie_id);
253 chxj_delete_cookie_expire(r, old_cookie_id);
261 DBG(r,"REQ[%X] end %s() (no cookie)",TO_ADDR(r),__func__);
268 cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(new_cookie_table);
269 hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;
270 apr_size_t store_string_len = 0;
271 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
272 if (ii) store_string_len++;
273 store_string_len += (strlen(hentryp[ii].key) + strlen(hentryp[ii].val) + 1);
275 store_string = apr_palloc(pool, store_string_len + 1);
276 memset(store_string, 0, store_string_len + 1);
279 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
280 if (ii) store_string[npos++] = '\n';
281 memcpy(&store_string[npos], hentryp[ii].key, strlen(hentryp[ii].key));
282 npos += strlen(hentryp[ii].key);
283 store_string[npos++] = '=';
284 memcpy(&store_string[npos], hentryp[ii].val, strlen(hentryp[ii].val));
285 npos += strlen(hentryp[ii].val);
288 if (old_cookie_id && IS_COOKIE_LAZY(dconf)) {
289 DBG(r, "REQ[%X] LAZY COOKIE save",TO_ADDR(r));
290 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
292 else if (old_cookie_id && apr_table_get(r->headers_in, "X-Chxj-Cookie-No-Update")) {
293 DBG(r, "REQ[%X] NO UPDATE MODE",TO_ADDR(r));
294 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
297 if (old_cookie_id && apr_table_get(r->headers_in, "X-Chxj-Forward")) {
298 DBG(r, "REQ[%X] NO LAZY COOKIE(X-Chxj-Forward) save",TO_ADDR(r));
299 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
302 DBG(r, "REQ[%X] NO LAZY COOKIE save",TO_ADDR(r));
303 cookie->cookie_id = alloc_cookie_id(r);
307 DBG(r,"REQ[%X] TYPE:[%d]", TO_ADDR(r), dconf->cookie_store_type);
308 DBG(r,"REQ[%X] STORE STRING:=======================================================", TO_ADDR(r));
309 DBG(r,"REQ[%X] [%s]", TO_ADDR(r), store_string);
310 DBG(r,"REQ[%X] =======================================================:STORE STRING", TO_ADDR(r));
314 #if defined(USE_MYSQL_COOKIE)
315 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
316 if (! chxj_save_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) {
317 ERR(r, "%s:%d faild: chxj_save_cookie_mysql() cookie_id:[%s]", APLOG_MARK,cookie->cookie_id);
324 #if defined(USE_MEMCACHE_COOKIE)
325 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
326 if (! chxj_save_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) {
327 ERR(r, "%s:%d failed: chxj_save_cookie_memcache() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id);
334 if (IS_COOKIE_STORE_DBM(dconf->cookie_store_type) || ! done_proc) {
335 if (! chxj_save_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) {
336 ERR(r, "%s:%d failed: chxj_save_cookie_dbm() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id);
343 apr_table_unset(r->headers_out, "Set-Cookie");
344 apr_table_unset(r->err_headers_out, "Set-Cookie");
348 chxj_save_cookie_expire(r, cookie);
352 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
362 chxj_update_cookie(request_rec *r, cookie_t *old_cookie)
365 apr_array_header_t *headers;
366 apr_table_entry_t *hentryp;
368 mod_chxj_config *dconf;
369 mod_chxj_req_config *req_conf;
370 chxjconvrule_entry *entryp;
374 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
375 if (!old_cookie || ! old_cookie->cookie_headers || ! old_cookie->cookie_id) {
376 DBG(r,"REQ[%X] old_cookie is null",TO_ADDR(r));
377 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
381 cookie = (cookie_t *)apr_palloc(r->pool, sizeof(cookie_t));
382 cookie->cookie_id = NULL;
384 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
385 req_conf = chxj_get_req_config(r);
386 /*-------------------------------------------------------------------------*/
387 /* already setup entryp if request_conf->user_agent is not null */
388 /*-------------------------------------------------------------------------*/
389 if (req_conf->user_agent) {
390 entryp = req_conf->entryp;
393 entryp = chxj_apply_convrule(r, dconf->convrules);
396 DBG(r,"REQ[%X] no pattern",TO_ADDR(r));
397 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
400 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
401 DBG(r,"REQ[%X] CookieOff",TO_ADDR(r));
402 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
406 headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
407 hentryp = (apr_table_entry_t*)headers->elts;
409 chxj_delete_cookie(r, old_cookie->cookie_id);
410 chxj_delete_cookie_expire(r, old_cookie->cookie_id);
412 if (IS_COOKIE_LAZY(dconf)) {
413 DBG(r,"REQ[%X] LAZY MODE",TO_ADDR(r));
414 cookie->cookie_id = apr_pstrdup(r->pool, old_cookie->cookie_id);
417 DBG(r,"REQ[%X] NO LAZY MODE",TO_ADDR(r));
418 cookie->cookie_id = alloc_cookie_id(r);
421 cookie->cookie_headers = old_cookie->cookie_headers;
422 store_string = apr_palloc(r->pool, 1);
424 hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;
426 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
427 if (ii) store_string = apr_pstrcat(r->pool,
432 DBG(r,"REQ[%X] OLD COOKIE VALUE=[%s][%s]",TO_ADDR(r), hentryp[ii].key, hentryp[ii].val);
433 store_string = apr_pstrcat(r->pool,
443 #if defined(USE_MYSQL_COOKIE)
444 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
445 if (!chxj_update_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) {
446 ERR(r,"REQ[%X] failed: chxj_update_cookie_mysql() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
453 #if defined(USE_MEMCACHE_COOKIE)
454 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
455 if (! chxj_update_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) {
456 ERR(r, "REQ[%X] failed: chxj_update_cookie_memcache() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
462 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
463 if (! chxj_update_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) {
464 ERR(r, "REQ[%X] failed: chxj_update_cookie_dbm() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
470 chxj_save_cookie_expire(r, cookie);
472 apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id);
476 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
483 * @return loaded data.
486 chxj_load_cookie(request_rec *r, char *cookie_id)
488 mod_chxj_config *dconf;
489 mod_chxj_req_config *req_conf;
490 chxjconvrule_entry *entryp;
492 apr_table_t *load_cookie_table;
493 char *load_string = NULL;
500 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
501 DBG(r,"REQ[%X] cookie_id=[%s]", TO_ADDR(r), cookie_id);
502 chxj_cookie_expire_gc(r);
504 cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t));
505 cookie->cookie_headers = NULL;
506 cookie->cookie_id = chxj_url_decode(r->pool, apr_pstrdup(r->pool, cookie_id));
507 cookie->cookie_id = chxj_url_encode(r->pool, cookie->cookie_id);
510 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
511 req_conf = chxj_get_req_config(r);
512 /*-------------------------------------------------------------------------*/
513 /* already setup entryp if request_conf->user_agent is not null */
514 /*-------------------------------------------------------------------------*/
515 if (req_conf->user_agent) {
516 entryp = req_conf->entryp;
519 entryp = chxj_apply_convrule(r, dconf->convrules);
522 DBG(r,"REQ[%X] pattern", TO_ADDR(r));
523 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
526 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT) && ! (entryp->action & CONVRULE_COOKIE_ONLY_BIT)) {
527 DBG(r,"REQ[%X] CookieOff", TO_ADDR(r));
528 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
531 load_cookie_table = apr_table_make(r->pool, 0);
535 #if defined(USE_MYSQL_COOKIE)
536 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
537 if (! (load_string = chxj_load_cookie_mysql(r, dconf, cookie->cookie_id))) {
538 ERR(r, "REQ[%X] %s:%d failed: chxj_load_cookie_mysql() cookie_id:[%s]", TO_ADDR(r),APLOG_MARK, cookie_id);
544 #if defined(USE_MEMCACHE_COOKIE)
545 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
546 if (! (load_string = chxj_load_cookie_memcache(r, dconf, cookie->cookie_id))) {
547 ERR(r, "REQ[%X] %s:%d failed: chxj_load_cookie_memcache() cookie_id:[%s]", TO_ADDR(r),APLOG_MARK,cookie_id);
553 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
554 if (! (load_string = chxj_load_cookie_dbm(r, dconf, cookie->cookie_id))) {
555 ERR(r, "REQ[%X] %s:%d failed: chxj_load_cookie_dbm() cookie_id:[%s]", TO_ADDR(r),APLOG_MARK,cookie_id);
562 DBG(r, "REQ[%X] load_string=[%s]", TO_ADDR(r), load_string);
563 header_cookie = apr_palloc(r->pool, 1);
564 header_cookie[0] = 0;
568 pair = apr_strtok(load_string, "\n", &pstat);
572 DBG(r,"REQ[%X] Cookie:[%s]", TO_ADDR(r), pair);
574 tmp_pair = apr_pstrdup(r->pool, pair);
575 val = strchr(tmp_pair, '=');
579 apr_table_add(load_cookie_table, key, val);
580 DBG(r,"REQ[%X] ADD key:[%s] val:[%s]", TO_ADDR(r), key, val);
582 tmp_pair = apr_pstrdup(r->pool, pair);
583 tmp_sem = strchr(tmp_pair, ';');
587 if (check_valid_cookie_attribute(r, pair)) {
588 if (strlen(header_cookie))
589 header_cookie = apr_pstrcat(r->pool, header_cookie, ";", NULL);
591 header_cookie = apr_pstrcat(r->pool, header_cookie, tmp_pair, NULL);
594 if (strlen(header_cookie)) {
595 DBG(r,"REQ[%X] ADD COOKIE to REQUEST HEADER:[%s]", TO_ADDR(r), header_cookie);
596 apr_table_add(r->headers_in, "Cookie", header_cookie);
599 cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(load_cookie_table);
601 if (apr_table_get(r->headers_in, "referer") == NULL) {
602 apr_table_setn(r->headers_in,
604 apr_table_get(load_cookie_table, REFERER_COOKIE_KEY));
608 * save cookie_id to request header.
610 apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id);
613 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
619 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
624 check_valid_cookie_attribute(request_rec *r, const char *value)
635 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
636 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r),value);
638 domain_pair = path_pair = expire_pair = secure_pair = NULL;
639 p = apr_pstrdup(r->pool, value);
641 /* pass first pair */
642 first_pair = apr_strtok(p, ";", &pstat);
645 pair = apr_strtok(NULL, ";", &pstat);
647 pair = qs_trim_string(r->pool, pair);
648 if (STRNCASEEQ('d','D',"domain", pair, sizeof("domain")-1)) {
649 domain_pair = apr_pstrdup(r->pool, pair);
651 else if (STRNCASEEQ('p','P',"path", pair, sizeof("path")-1)) {
652 path_pair = apr_pstrdup(r->pool, pair);
654 else if (STRNCASEEQ('e','E',"expires", pair, sizeof("expires")-1)) {
655 expire_pair = apr_pstrdup(r->pool, pair);
657 else if (STRNCASEEQ('s','S',"secure", pair, sizeof("secure")-1)) {
658 secure_pair = apr_pstrdup(r->pool, pair);
663 if (!valid_domain(r, domain_pair)) {
664 DBG(r,"REQ[%X] invalid domain. domain_pair:[%s]", TO_ADDR(r),domain_pair);
665 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
670 if (!valid_path(r, path_pair)) {
671 DBG(r,"REQ[%X] invalid path. path_pair:[%s]", TO_ADDR(r),path_pair);
672 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
677 if (!valid_expires(r, expire_pair)) {
678 DBG(r,"REQ[%X] invalid expire. expire_pair:[%s]", TO_ADDR(r),expire_pair);
679 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
684 if (!valid_secure(r, secure_pair)) {
685 DBG(r,"REQ[%X] invalid secure. secure_pair:[%s]", TO_ADDR(r),secure_pair);
686 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
690 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r),value);
691 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
697 check_valid_cookie_attribute_expires_only(request_rec *r, const char *value)
702 char *expire_pair = NULL;
705 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
706 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
709 p = apr_pstrdup(r->pool, value);
711 /* pass first pair */
712 first_pair = apr_strtok(p, ";", &pstat);
715 pair = apr_strtok(NULL, ";", &pstat);
717 pair = qs_trim_string(r->pool, pair);
718 if (STRNCASEEQ('e','E',"expires", pair, sizeof("expires")-1)) {
719 expire_pair = apr_pstrdup(r->pool, pair);
724 if (!valid_expires(r, expire_pair)) {
725 DBG(r,"REQ[%X] invalid expire. expire_pair:[%s]", TO_ADDR(r), expire_pair);
726 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
730 DBG(r,"REQ[%X] value:[%s]",TO_ADDR(r), value);
731 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
737 valid_domain(request_rec *r, const char *value)
743 char *p = apr_pstrdup(r->pool, value);
744 char *host = (char *)apr_table_get(r->headers_in, HTTP_HOST);
746 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
747 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
749 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
750 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
753 DBG(r, "REQ[%X] host:[%s]", TO_ADDR(r), host);
754 host = s_cut_until_end_hostname(r, apr_pstrdup(r->pool, host));
755 DBG(r, "REQ[%X] host:[%s](after s_cut_until_end_hostname())", TO_ADDR(r), host);
757 name = apr_strtok(p,"=", &pstat);
758 name = qs_trim_string(r->pool, name);
759 val = apr_strtok(NULL, "=", &pstat);
760 val = qs_trim_string(r->pool, val);
763 if (chxj_strcasenrcmp(r->pool, host, val, strlen(val))) {
764 DBG(r,"REQ[%X] not match domain. host domain:[%s] vs value:[%s]", TO_ADDR(r), host, val);
765 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
766 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
770 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r), value);
771 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
777 valid_path(request_rec *r, const char *value)
779 char *p = apr_pstrdup(r->pool, value);
786 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
787 DBG(r,"REQ[%X] unparsed_uri:[%s] value:[%s]", TO_ADDR(r),r->unparsed_uri, value);
788 if (chxj_starts_with(r->unparsed_uri, "http://")) {
789 uri = strchr(&r->unparsed_uri[sizeof("http://")], '/');
791 uri = apr_pstrdup(r->pool, uri);
794 else if (chxj_starts_with(r->unparsed_uri, "https://")) {
795 uri = strchr(&r->unparsed_uri[sizeof("https://")], '/');
797 uri = apr_pstrdup(r->pool, uri);
800 else if (chxj_starts_with(r->unparsed_uri, "/")) {
801 uri = apr_pstrdup(r->pool, r->unparsed_uri);
804 uri = apr_pstrdup(r->pool, "/");
807 if ((tmp = strchr(uri, '?'))) {
810 DBG(r,"REQ[%X] uri=[%s]", TO_ADDR(r),uri);
811 name = apr_strtok(p, "=", &pstat);
812 val = apr_strtok(NULL, "=", &pstat);
813 name = qs_trim_string(r->pool, name);
814 val = qs_trim_string(r->pool, val);
815 DBG(r,"REQ[%X] name=[%s] val=[%s]", TO_ADDR(r),name, val);
817 DBG(r, "REQ[%X] val:[%s] vs uri:[%s]", TO_ADDR(r),val, uri);
818 if (! chxj_starts_with(uri, val)) {
819 DBG(r,"REQ[%X] unparsed_uri:[%s] value:[%s] (false)",TO_ADDR(r), r->unparsed_uri, value);
820 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
823 DBG(r,"REQ[%X] unparsed_uri:[%s] value:[%s] (true)", TO_ADDR(r),r->unparsed_uri, value);
824 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
830 valid_expires(request_rec *r, const char *value)
834 char *p = apr_pstrdup(r->pool, value);
839 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
840 DBG(r,"REQ[%X] value:[%s]",TO_ADDR(r),value);
841 name = apr_strtok(p, "=", &pstat);
842 val = apr_strtok(NULL, "=", &pstat);
843 DBG(r,"REQ[%X] name=[%s] val=[%s]", TO_ADDR(r),name, val);
844 now = apr_time_now();
845 expires = chxj_parse_cookie_expires(val);
847 DBG(r,"REQ[%X] value:[%s] (expired)", TO_ADDR(r),value);
848 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
852 DBG(r,"REQ[%X] value:[%s] (non expired)", TO_ADDR(r),value);
853 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
859 valid_secure(request_rec *r, const char *value)
862 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
863 DBG(r,"REQ[%X] value:[%s]", TO_ADDR(r),value);
864 scheme = chxj_apache_run_http_scheme(r);
865 if (strcasecmp("https", scheme)) {
866 DBG(r,"REQ[%X] value:[%s] (non secure)", TO_ADDR(r),value);
867 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
870 DBG(r,"REQ[%X] value:[%s] (secure)", TO_ADDR(r),value);
871 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
877 chxj_add_cookie_parameter(request_rec *r, char *value, cookie_t *cookie)
883 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
884 DBG(r,"REQ[%X] cookie_id=[%s]", TO_ADDR(r), (cookie) ? cookie->cookie_id : NULL);
886 dst = apr_pstrdup(r->pool, value);
891 if (!cookie->cookie_id)
894 if (chxj_cookie_check_host(r, value) != 0) {
895 DBG(r,"REQ[%X] (check host)", TO_ADDR(r));
896 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
900 qs = strchr(dst, '#');
902 name = apr_pstrdup(r->pool, qs);
906 qs = strchr(dst, '?');
909 qs = chxj_delete_chxj_cc_param(r, ++qs);
910 DBG(r, "REQ[%X] qs:[%s]",TO_ADDR(r), qs);
912 if (qs && strlen(qs)) {
913 dst = apr_psprintf(r->pool, "%s?%s", dst, qs);
917 dst = apr_psprintf(r->pool, "%s&%s=%s%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id, name);
920 dst = apr_psprintf(r->pool, "%s?%s=%s%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id, name);
923 DBG(r,"REQ[%X] dst=[%s]", TO_ADDR(r), dst);
924 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
929 DBG(r,"REQ[%X] (on_error)", TO_ADDR(r));
930 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
936 chxj_add_cookie_no_update_parameter(request_rec *r, char *value, int xmlflag)
942 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
944 if (! value || ! *value) {
945 DBG(r,"REQ[%X] (void value)", TO_ADDR(r));
946 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
947 return apr_pstrdup(r->pool, "");
950 dst = apr_pstrdup(r->pool, value);
952 if (chxj_cookie_check_host(r, value) != 0) {
953 DBG(r,"REQ[%X] (check host)", TO_ADDR(r));
954 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
958 qs = strchr(dst, '#');
960 name = apr_pstrdup(r->pool, qs);
967 dst = apr_psprintf(r->pool, "%s%s%s=true%s", dst, (strchr(dst,'?')) ? amp : "?",CHXJ_COOKIE_NOUPDATE_PARAM, name);
968 DBG(r,"REQ[%X] dst=[%s]", TO_ADDR(r), dst);
969 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
973 DBG(r,"REQ[%X] (on_error)", TO_ADDR(r));
974 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
980 chxj_cookie_check_host(request_rec *r, char *value)
983 mod_chxj_config *dconf;
985 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
986 DBG(r,"REQ[%X] hostname=[%s] vs Location:[%s]", TO_ADDR(r), r->hostname, value);
988 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
990 hostnm = s_get_hostname_from_url(r, value);
992 if (dconf->allowed_cookie_domain) {
993 DBG(r, "REQ[%X] allowed_domain[%s] vs Location:[%s]", TO_ADDR(r), dconf->allowed_cookie_domain, value);
994 if (chxj_strcasenrcmp(r->pool, hostnm, dconf->allowed_cookie_domain, strlen(dconf->allowed_cookie_domain))) {
995 DBG(r,"REQ[%X] (false/allowed_domain)", TO_ADDR(r));
996 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1000 DBG(r,"REQ[%X] (true/allowed_domain)", TO_ADDR(r));
1001 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1006 if (strcasecmp(hostnm, r->hostname) == 0) {
1007 DBG(r,"REQ[%X] (true)", TO_ADDR(r));
1008 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1012 DBG(r,"REQ[%X] (false)", TO_ADDR(r));
1013 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1018 DBG(r,"REQ[%X] (true)", TO_ADDR(r));
1019 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1025 s_get_hostname_from_url(request_rec *r, char *value)
1030 if (strncasecmp(value, "http://", 7) == 0 )
1031 return s_cut_until_end_hostname(r, &value[7]);
1033 if (strncasecmp(value, "https://", 8) == 0)
1034 return s_cut_until_end_hostname(r, &value[8]);
1041 s_cut_until_end_hostname(request_rec *r, char *value)
1046 hostnm = sp = apr_pstrdup(r->pool, value);
1048 if (*sp == '/'|| *sp == '?' || *sp == ':') {
1059 chxj_delete_cookie(request_rec *r, const char *cookie_id)
1062 mod_chxj_config *dconf;
1064 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1065 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1067 #if defined(USE_MYSQL_COOKIE)
1068 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1069 if (! chxj_delete_cookie_mysql(r, dconf, cookie_id)) {
1070 ERR(r,"REQ[%X] failed: chxj_delete_cookie_mysql() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1071 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1077 #if defined(USE_MEMCACHE_COOKIE)
1078 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1079 if (! chxj_delete_cookie_memcache(r, dconf, cookie_id)) {
1080 ERR(r,"REQ[%X] failed: chxj_delete_cookie_memcache() cookie_id:[%s]", TO_ADDR(r), cookie_id);
1081 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1087 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
1088 if (! chxj_delete_cookie_dbm(r, dconf, cookie_id)) {
1089 ERR(r,"REQ[%X] failed: chxj_delete_cookie_dbm() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1090 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1095 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1103 chxj_save_cookie_expire(request_rec *r, cookie_t *cookie)
1106 mod_chxj_config *dconf;
1108 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1110 DBG(r,"REQ[%X] cookie is NULL",TO_ADDR(r));
1111 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1114 if (!cookie->cookie_id) {
1115 DBG(r,"REQ[%X] cookie->cookie_id is NULL",TO_ADDR(r));
1116 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1120 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1122 DBG(r,"REQ[%X] dconf is NULL",TO_ADDR(r));
1123 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1127 #if defined(USE_MYSQL_COOKIE)
1128 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1129 if (! chxj_save_cookie_expire_mysql(r, dconf, cookie->cookie_id)) {
1130 ERR(r,"REQ[%X] failed: chxj_save_cookie_expire_mysql() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
1131 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1137 #if defined(USE_MEMCACHE_COOKIE)
1138 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1139 if (! chxj_save_cookie_expire_memcache(r, dconf, cookie->cookie_id)) {
1140 ERR(r,"REQ[%X] failed: chxj_save_cookie_expire_memcache() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
1141 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1147 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
1148 if (! chxj_save_cookie_expire_dbm(r, dconf, cookie->cookie_id)) {
1149 ERR(r,"REQ[%X] failed: chxj_save_cookie_expire_dbm() cookie_id:[%s]", TO_ADDR(r),cookie->cookie_id);
1150 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1155 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1160 chxj_delete_cookie_expire(request_rec *r, char *cookie_id)
1163 mod_chxj_config *dconf;
1165 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1167 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1169 #if defined(USE_MYSQL_COOKIE)
1170 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1171 if (! chxj_delete_cookie_expire_mysql(r, dconf, cookie_id)) {
1172 ERR(r,"REQ[%X] failed: chxj_delete_cookie_expire_mysql() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1173 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1179 #if defined(USE_MEMCACHE_COOKIE)
1180 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1181 if (!chxj_delete_cookie_expire_memcache(r, dconf, cookie_id)) {
1182 ERR(r,"REQ[%X] failed: chxj_delete_cookie_expire_memcache() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1183 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1189 if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
1190 if (!chxj_delete_cookie_expire_dbm(r, dconf, cookie_id)) {
1191 ERR(r,"REQ[%X] failed: chxj_delete_cookie_expire_dbm() cookie_id:[%s]", TO_ADDR(r),cookie_id);
1192 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1197 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1202 chxj_cookie_expire_gc(request_rec *r)
1204 mod_chxj_config *dconf;
1207 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1209 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1210 #if defined(USE_MYSQL_COOKIE)
1211 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1212 if (! chxj_cookie_expire_gc_mysql(r, dconf)) {
1213 ERR(r,"REQ[%X] %s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_mysql()", TO_ADDR(r),APLOG_MARK);
1214 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1220 #if defined(USE_MEMCACHE_COOKIE)
1221 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1222 if (! chxj_cookie_expire_gc_memcache(r, dconf)) {
1223 ERR(r,"REQ[%X] %s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_memcache()", TO_ADDR(r),APLOG_MARK);
1224 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1231 if (! chxj_cookie_expire_gc_dbm(r, dconf)) {
1232 ERR(r,"REQ[%X] %s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_dbm()", TO_ADDR(r),APLOG_MARK);
1233 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1237 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1241 chxj_parse_cookie_expires(const char *s)
1243 if (!s) return (apr_time_t)0;
1244 return apr_date_parse_rfc(s);
1249 __chxj_cookie_lock(request_rec *r, const char *filename, int line)
1251 mod_chxj_config *dconf;
1254 cookie_lock_t *ret = NULL;
1256 DBG(r,"REQ[%X] start %s() call from %s:%d",TO_ADDR(r),__func__, filename,line);
1257 if ((rv = apr_proc_mutex_lock(global_cookie_mutex)) != APR_SUCCESS) {
1259 ERR(r,"REQ[%X] %s:%d apr_proc_mutex_lock failure.(%d:%s)", TO_ADDR(r),APLOG_MARK, rv, apr_strerror(rv, errstr, 255));
1260 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1263 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1264 #if defined(USE_MYSQL_COOKIE)
1265 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1266 if (! chxj_cookie_lock_mysql(r, dconf)) {
1267 ERR(r,"REQ[%X] %s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_mysql()", TO_ADDR(r),APLOG_MARK);
1268 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1272 ret = apr_palloc(r->pool, sizeof(*ret));
1273 memset(ret, 0, sizeof(*ret));
1276 #if defined(USE_MEMCACHE_COOKIE)
1277 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1278 if (! chxj_cookie_lock_memcache(r, dconf)) {
1279 ERR(r,"REQ[%X] %s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_memcache()", TO_ADDR(r),APLOG_MARK);
1280 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
1284 ret = apr_palloc(r->pool, sizeof(*ret));
1285 memset(ret, 0, sizeof(*ret));
1289 if (!(ret = chxj_cookie_lock_dbm(r, dconf))) {
1290 ERR(r,"REQ[%X] %s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_dbm()", TO_ADDR(r),APLOG_MARK);
1291 DBG(r,"REQ[%X] end %s() call from %s:%d",TO_ADDR(r),__func__,filename,line);
1295 DBG(r,"REQ[%X] end %s() call from %s:%d",TO_ADDR(r),__func__,filename,line);
1301 __chxj_cookie_unlock(request_rec *r, cookie_lock_t *lock, const char *filename, int line)
1303 mod_chxj_config *dconf;
1308 DBG(r,"REQ[%X] start %s() call from %s:%d", TO_ADDR(r),__func__,filename, line);
1310 dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
1311 #if defined(USE_MYSQL_COOKIE)
1312 if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
1313 if (! chxj_cookie_unlock_mysql(r, dconf)) {
1314 ERR(r,"REQ[%X] failed: chxj_cookie_unlock_mysql()",TO_ADDR(r));
1316 goto end_chxj_cookie_unlock;
1321 #if defined(USE_MEMCACHE_COOKIE)
1322 if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
1323 if (! chxj_cookie_unlock_memcache(r, dconf)) {
1324 ERR(r,"REQ[%X] failed: chxj_cookie_unlock_memcache()",TO_ADDR(r));
1326 goto end_chxj_cookie_unlock;
1332 if (! chxj_cookie_unlock_dbm(r, lock, dconf)) {
1333 ERR(r,"REQ[%X] failed: chxj_cookie_unlock_dbm()",TO_ADDR(r));
1335 goto end_chxj_cookie_unlock;
1338 end_chxj_cookie_unlock:
1339 if ((rv = apr_proc_mutex_unlock(global_cookie_mutex)) != APR_SUCCESS) {
1341 ERR(r,"REQ[%X] %s:%d apr_proc_mutex_unlock failure.(%d:%s)", TO_ADDR(r),APLOG_MARK, rv, apr_strerror(rv, errstr, 255));
1342 DBG(r,"REQ[%X] end %s() call from %s:%d", TO_ADDR(r),__func__,filename, line);
1345 DBG(r,"REQ[%X] end %s() call from %s:%d", TO_ADDR(r),__func__,filename, line);
1351 #include "chxj_encoding.h"
1353 s_convert_a_tag(request_rec *r, const char *s, apr_size_t *len, cookie_t *cookie)
1356 ap_regex_t *regexp = NULL;
1361 apr_pool_create(&pool, r->pool);
1362 regexp = ap_pregcomp(pool, "(<a[^>]*>)", AP_REG_EXTENDED|AP_REG_ICASE);
1364 qs_init_malloc(&doc);
1365 qs_init_root_node(&doc);
1368 ap_regmatch_t match[10];
1369 if (ap_regexec((const ap_regex_t *)regexp, &s[nowpos], (apr_size_t)regexp->re_nsub + 1, match, 0) == 0) {
1370 apr_size_t plen = match[1].rm_so;
1372 char *tmpstr = apr_palloc(pool, plen + 1);
1373 memset(tmpstr, 0, plen + 1);
1374 memcpy(tmpstr, &s[nowpos], plen);
1375 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1380 char *matchstr = ap_pregsub(pool, "$1", &s[nowpos], regexp->re_nsub + 1, match);
1382 Node *node = qs_parse_tag(&doc, matchstr, strlen(matchstr) - 1);
1385 DBG(r,"REQ[%X] matchstr:[%s]", TO_ADDR(r),matchstr);
1386 dst = apr_pstrcat(pool, (dst) ? dst : "", "<a ", NULL);
1387 for (attr = qs_get_attr(&doc,node);
1389 attr = qs_get_next_attr(&doc,attr)) {
1390 char *name = qs_get_attr_name(&doc,attr);
1391 char *value = qs_get_attr_value(&doc,attr);
1392 DBG(r,"REQ[%X] name:[%s] value=[%s]",TO_ADDR(r), name, value);
1393 if (STRCASEEQ('h', 'H', "href", name)
1394 && ! chxj_starts_with(value, "mailto:")
1395 && ! chxj_starts_with(value, "tel:")) {
1396 char *flgp = strchr(value, '#');
1399 int flgl = strlen(flgp);
1400 flgsv = apr_palloc(pool, flgl+1);
1401 memset(flgsv, 0, flgl + 1);
1402 memcpy(flgsv, flgp, flgl);
1405 if (strchr(value, '?') != 0) {
1406 value = apr_pstrcat(pool, value, "&_chxj_cc=", cookie->cookie_id, NULL);
1409 value = apr_pstrcat(pool, value, "?_chxj_cc=", cookie->cookie_id, NULL);
1412 value = apr_pstrcat(pool, value, flgsv, NULL);
1414 dst = apr_pstrcat(pool, (dst) ? dst : "", "href='", value, "' ", NULL);
1417 dst = apr_pstrcat(pool, (dst) ? dst : "", name, "='", value, "' ", NULL);
1420 dst = apr_pstrcat(pool, (dst) ? dst : "", ">", NULL);
1421 plen += strlen(matchstr);
1430 if ((apr_size_t)nowpos < *len) {
1431 apr_size_t plen = *len - nowpos;
1432 char *tmpstr = apr_palloc(pool, plen + 1);
1433 memset(tmpstr, 0, plen+1);
1434 memcpy(tmpstr, &s[nowpos], plen);
1435 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1442 s_convert_img_tag(request_rec *r, const char *s, apr_size_t *len, cookie_t *cookie)
1445 ap_regex_t *regexp = NULL;
1450 apr_pool_create(&pool, r->pool);
1451 regexp = ap_pregcomp(pool, "(<img[^>]*>)", AP_REG_EXTENDED|AP_REG_ICASE);
1453 qs_init_malloc(&doc);
1454 qs_init_root_node(&doc);
1457 ap_regmatch_t match[10];
1458 if (ap_regexec((const ap_regex_t *)regexp, &s[nowpos], (apr_size_t)regexp->re_nsub + 1, match, 0) == 0) {
1459 apr_size_t plen = match[1].rm_so;
1461 char *tmpstr = apr_palloc(pool, plen + 1);
1462 memset(tmpstr, 0, plen + 1);
1463 memcpy(tmpstr, &s[nowpos], plen);
1464 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1469 char *matchstr = ap_pregsub(pool, "$1", &s[nowpos], regexp->re_nsub + 1, match);
1471 Node *node = qs_parse_tag(&doc, matchstr, strlen(matchstr) - 1);
1474 DBG(r,"REQ[%X] matchstr:[%s]", TO_ADDR(r),matchstr);
1475 dst = apr_pstrcat(pool, (dst) ? dst : "", "<img ", NULL);
1476 for (attr = qs_get_attr(&doc,node);
1478 attr = qs_get_next_attr(&doc,attr)) {
1479 char *name = qs_get_attr_name(&doc,attr);
1480 char *value = qs_get_attr_value(&doc,attr);
1481 DBG(r,"REQ[%X] name:[%s] value=[%s]", TO_ADDR(r),name, value);
1482 if (STRCASEEQ('s', 'S', "src", name)) {
1483 if (strchr(value, '?') != 0) {
1484 value = apr_pstrcat(pool, value, "&_chxj_cc=", cookie->cookie_id, "&_chxj_nc=true", NULL);
1487 value = apr_pstrcat(pool, value, "?_chxj_cc=", cookie->cookie_id, "&_chxj_nc=true", NULL);
1489 dst = apr_pstrcat(pool, (dst) ? dst : "", "src='", value, "' ", NULL);
1492 dst = apr_pstrcat(pool, (dst) ? dst : "", name, "='", value, "' ", NULL);
1495 dst = apr_pstrcat(pool, (dst) ? dst : "", "/>", NULL);
1496 plen += strlen(matchstr);
1505 if ((apr_size_t)nowpos < *len) {
1506 apr_size_t plen = *len - nowpos;
1507 char *tmpstr = apr_palloc(pool, plen + 1);
1508 memset(tmpstr, 0, plen+1);
1509 memcpy(tmpstr, &s[nowpos], plen);
1510 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1517 s_convert_form_tag(request_rec *r, const char *s, apr_size_t *len, cookie_t *cookie)
1520 ap_regex_t *regexp = NULL;
1526 apr_pool_create(&pool, r->pool);
1527 regexp = ap_pregcomp(pool, "(</form>)", AP_REG_EXTENDED|AP_REG_ICASE);
1529 qs_init_malloc(&doc);
1530 qs_init_root_node(&doc);
1531 cookie_id = chxj_url_decode(pool, cookie->cookie_id);
1534 ap_regmatch_t match[10];
1535 if (ap_regexec((const ap_regex_t *)regexp, &s[nowpos], (apr_size_t)regexp->re_nsub + 1, match, 0) == 0) {
1536 apr_size_t plen = match[1].rm_so;
1538 char *tmpstr = apr_palloc(pool, plen + 1);
1539 memset(tmpstr, 0, plen + 1);
1540 memcpy(tmpstr, &s[nowpos], plen);
1541 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1546 char *matchstr = ap_pregsub(pool, "$1", &s[nowpos], regexp->re_nsub + 1, match);
1548 DBG(r,"REQ[%X] matchstr:[%s]",TO_ADDR(r),matchstr);
1549 dst = apr_pstrcat(pool, (dst) ? dst : "", "<input type='hidden' name='_chxj_cc' value='", cookie_id, "' />", matchstr, NULL);
1550 plen += strlen(matchstr);
1559 if ((apr_size_t)nowpos < *len) {
1560 apr_size_t plen = *len - nowpos;
1561 char *tmpstr = apr_palloc(pool, plen + 1);
1562 memset(tmpstr, 0, plen + 1);
1563 memcpy(tmpstr, &s[nowpos], plen);
1564 dst = apr_pstrcat(pool, (dst) ? dst : "", tmpstr, NULL);
1572 chxj_cookie_only_mode(request_rec *r, const char *src, apr_size_t *len, cookie_t* cookie)
1578 DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
1579 s = chxj_encoding(r, src, len);
1581 dst = s_convert_a_tag(r, s, len, cookie);
1582 dst = s_convert_img_tag(r, dst, len, cookie);
1583 dst = s_convert_form_tag(r, dst, len, cookie);
1585 result = chxj_rencoding(r, dst, len, NULL);
1586 DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);