OSDN Git Service

* Added test code of the <plaintext> tag for au HDML converter.
[modchxj/mod_chxj.git] / src / chxj_cookie.c
1 /*
2  * Copyright (C) 2005-2008 Atsushi Konno All rights reserved.
3  * Copyright (C) 2005 QSDN,Inc. All rights reserved.
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 #include <time.h>
18
19 #include "mod_chxj.h"
20 #include "chxj_cookie.h"
21 #include "chxj_url_encode.h"
22 #include "chxj_apply_convrule.h"
23 #include "chxj_str_util.h"
24
25 #include "ap_release.h"
26
27 #include "apu.h"
28 #include "apr_dbm.h"
29 #include "apr_uuid.h"
30 #include "apr_md5.h"
31 #include "apr_base64.h"
32 #include "apr_uri.h"
33 #include "apr_time.h"
34 #include "apr_date.h"
35
36 #if defined(USE_MYSQL_COOKIE)
37 #  include "chxj_mysql.h"
38 #endif
39 #if defined(USE_MEMCACHE_COOKIE)
40 #  include "chxj_memcache.h"
41 #endif
42 #include "chxj_dbm.h"
43
44
45 static char* s_get_hostname_from_url(request_rec* r, char* value);
46 static char* s_cut_until_end_hostname(request_rec*, char* value);
47 static int valid_domain(request_rec *r, const char *value);
48 static int valid_path(request_rec *r, const char *value);
49 static int valid_expires(request_rec *r, const char *value);
50 static int valid_secure(request_rec *r, const char *value);
51 static int check_valid_cookie_attribute(request_rec *r, const char *pair);
52
53
54 static char *
55 alloc_cookie_id(request_rec *r)
56 {
57   char                *cookie_id;
58   char                *uuid_string;
59   unsigned char       *md5_value;
60   apr_uuid_t          uuid;
61   apr_status_t        retval;
62
63   apr_uuid_get(&uuid);
64   uuid_string = apr_palloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1);
65   memset(uuid_string, 0, APR_UUID_FORMATTED_LENGTH + 1);
66   apr_uuid_format(uuid_string, &uuid);;
67
68   md5_value = (unsigned char*)apr_palloc(r->pool, APR_MD5_DIGESTSIZE + 1);
69   memset(md5_value, 0, APR_MD5_DIGESTSIZE + 1);
70
71   retval = apr_md5(md5_value, 
72                    (const char*)uuid_string, 
73                    APR_UUID_FORMATTED_LENGTH);
74   if (retval != APR_SUCCESS) {
75     ERR(r, "md5 failed.");
76     return NULL;
77   }
78
79   cookie_id = apr_palloc(r->pool, apr_base64_encode_len(APR_MD5_DIGESTSIZE)+1);
80   memset(cookie_id, 0, APR_MD5_DIGESTSIZE+1);
81   apr_base64_encode(cookie_id, (char*)md5_value, APR_MD5_DIGESTSIZE);
82
83   DBG(r, "cookie_id=[%s]", cookie_id);
84
85   cookie_id = chxj_url_encode(r,cookie_id);
86
87   DBG(r, "cookie_id=[%s]", cookie_id);
88   return cookie_id;
89 }
90
91
92 /*
93  *
94  */
95 cookie_t*
96 chxj_save_cookie(request_rec* r)
97 {
98   int                 ii;
99   apr_array_header_t* headers;
100   apr_table_entry_t*  hentryp;
101   char                *old_cookie_id;
102   char                *store_string;
103   mod_chxj_config     *dconf;
104   chxjconvrule_entry  *entryp;
105   apr_table_t*        new_cookie_table;
106   int                 has_cookie = 0;
107   cookie_t*           cookie;
108   cookie_t*           old_cookie;
109   char*               refer_string;
110   apr_uri_t           parsed_uri;
111   int                 has_refer;
112
113
114   DBG(r, "start chxj_save_cookie()");
115
116   cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t));
117   cookie->cookie_id = NULL;
118
119   has_cookie = 0;
120   has_refer = 0;
121
122   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
123   entryp = chxj_apply_convrule(r, dconf->convrules);
124   if (! entryp) {
125     DBG(r, "end chxj_save_cookie() no pattern");
126     return NULL;
127   }
128   if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
129     DBG(r, "end chxj_save_cookie() CookieOff");
130     return NULL;
131   }
132
133
134
135   headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
136   hentryp = (apr_table_entry_t*)headers->elts;
137
138
139   new_cookie_table = apr_table_make(r->pool, 0);
140
141   for (ii=0; ii<headers->nelts; ii++) {
142     if (strcasecmp(hentryp[ii].key, "Set-Cookie") == 0) {
143       DBG(r, "=====================================");
144       DBG(r, "cookie=[%s:%s]", hentryp[ii].key, hentryp[ii].val);
145
146       char* key;
147       char* val;
148       char* buff;
149
150
151       buff = apr_pstrdup(r->pool, hentryp[ii].val);
152       val = strchr(buff, '=');
153       if (val) {
154         key = buff;
155         *val++ = 0;
156         apr_table_add(new_cookie_table, key, val);
157         if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++;
158         
159       }
160
161       has_cookie = 1;
162       DBG(r, "=====================================");
163     }
164   }
165   apr_table_unset(r->headers_out, "Set-Cookie");
166
167   if (! has_refer) {
168     apr_uri_parse(r->pool,r->uri, &parsed_uri);
169     refer_string = apr_psprintf(r->pool, 
170                                 "%s://%s%s", 
171                                 chxj_run_http_scheme(r),
172                                 r->hostname,
173                                 apr_uri_unparse(r->pool,
174                                                 &parsed_uri,
175                                                 APR_URI_UNP_OMITSITEPART));
176     if (r->args && strlen(r->args)) {
177       refer_string = apr_pstrcat(r->pool, refer_string, "?", r->args, NULL);
178     }
179     apr_table_setn(new_cookie_table, REFERER_COOKIE_KEY, refer_string);
180     DBG(r, "ADD REFER[%s]", refer_string);
181     has_cookie++;
182   }
183
184
185   /*
186    * check input parameters
187    */
188   old_cookie_id = (char*)apr_table_get(r->headers_in, "CHXJ_COOKIE_ID");
189   if (old_cookie_id) {
190     old_cookie = chxj_load_cookie(r, old_cookie_id); 
191     if (old_cookie && old_cookie->cookie_headers) {
192       hentryp = (apr_table_entry_t*)old_cookie->cookie_headers->elts;
193       for (ii=0; ii<old_cookie->cookie_headers->nelts; ii++) {
194         if (hentryp && apr_table_get(new_cookie_table, hentryp[ii].key) == NULL) {
195           apr_table_add(new_cookie_table, hentryp[ii].key, hentryp[ii].val);
196           has_cookie = 1;
197         }
198       }
199       chxj_delete_cookie(r,        old_cookie_id);
200       chxj_delete_cookie_expire(r, old_cookie_id);
201     }
202   }
203
204   if (! has_cookie) {
205     DBG(r, "no cookie");
206     DBG(r, "end chxj_save_cookie()");
207     return NULL;
208   }
209
210   /*
211    * create val
212    */
213   cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(new_cookie_table);
214   store_string = apr_palloc(r->pool, 1);
215   store_string[0] = 0;
216   hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;
217
218   for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
219     if (ii) store_string = apr_pstrcat(r->pool,
220                                store_string, 
221                                "\n",
222                                NULL);
223
224     store_string = apr_pstrcat(r->pool, 
225                                store_string, 
226                                hentryp[ii].key, 
227                                "=",
228                                hentryp[ii].val, 
229                                NULL);
230   }
231
232   if (old_cookie_id && IS_COOKIE_LAZY(dconf)) {
233     DBG(r, "LAZY COOKIE save");
234     cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id);
235   }
236   else {
237     DBG(r, "NO LAZY COOKIE save");
238     cookie->cookie_id = alloc_cookie_id(r);
239   }
240
241 DBG(r, "TYPE:[%d]", dconf->cookie_store_type);
242   {
243     int done_proc = 0;
244 #if defined(USE_MYSQL_COOKIE)
245     if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
246       if (! chxj_save_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) {
247         ERR(r, "faild: chxj_save_cookie_mysql() cookie_id:[%s]", cookie->cookie_id);
248         goto on_error;
249       }
250       done_proc = 1;
251     }
252 #endif
253 #if defined(USE_MEMCACHE_COOKIE)
254     if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
255       if (! chxj_save_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) {
256         ERR(r, "failed: chxj_save_cookie_memcache() cookie_id:[%s]", cookie->cookie_id);
257         goto on_error;
258       }
259       done_proc = 1;
260     }
261 #endif
262     if (IS_COOKIE_STORE_DBM(dconf->cookie_store_type) || ! done_proc) {
263       if (! chxj_save_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) {
264         ERR(r, "failed: chxj_save_cookie_dbm() cookie_id:[%s]", cookie->cookie_id);
265         goto on_error;
266       }
267     }
268   }
269
270
271   chxj_save_cookie_expire(r, cookie);
272
273
274
275 on_error:
276   DBG(r, "end chxj_save_cookie()");
277   return cookie;
278 }
279
280 /*
281  *
282  */
283 cookie_t*
284 chxj_update_cookie(request_rec* r, cookie_t* old_cookie)
285 {
286   int                 ii;
287   apr_array_header_t* headers;
288   apr_table_entry_t*  hentryp;
289   char*               store_string;
290   mod_chxj_config*    dconf;
291   chxjconvrule_entry* entryp;
292   cookie_t*           cookie;
293
294
295   DBG(r, "start chxj_update_cookie()");
296   if (!old_cookie || ! old_cookie->cookie_headers || ! old_cookie->cookie_id) {
297     DBG(r, "end chxj_update_cookie() (old_cookie is null)");
298     return  NULL;
299   }
300
301   cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t));
302   cookie->cookie_id = NULL;
303
304
305   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
306   entryp = chxj_apply_convrule(r, dconf->convrules);
307   if (! entryp) {
308     DBG(r, "end chxj_update_cookie() no pattern");
309     return NULL;
310   }
311   if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
312     DBG(r, "end chxj_update_cookie() CookieOff");
313     return NULL;
314   }
315
316
317   headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
318   hentryp = (apr_table_entry_t*)headers->elts;
319
320
321   chxj_delete_cookie(r,        old_cookie->cookie_id);
322   chxj_delete_cookie_expire(r, old_cookie->cookie_id);
323
324   if (IS_COOKIE_LAZY(dconf)) {
325     DBG(r, "LAZY MODE");
326     cookie->cookie_id = apr_pstrdup(r->pool, old_cookie->cookie_id);
327   }
328   else {
329     DBG(r, "NO LAZY MODE");
330     cookie->cookie_id = alloc_cookie_id(r);
331   }
332
333   cookie->cookie_headers = old_cookie->cookie_headers;
334   store_string = apr_palloc(r->pool, 1);
335   store_string[0] = 0;
336   hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;
337
338   for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
339     if (ii) store_string = apr_pstrcat(r->pool,
340                                store_string, 
341                                "\n",
342                                NULL);
343
344     DBG(r, "OLD COOKIE VALUE=[%s][%s]", hentryp[ii].key, hentryp[ii].val);
345     store_string = apr_pstrcat(r->pool, 
346                                store_string, 
347                                hentryp[ii].key, 
348                                "=",
349                                hentryp[ii].val, 
350                                NULL);
351   }
352
353   {
354     int done_proc = 0;
355 #if defined(USE_MYSQL_COOKIE)
356     if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
357       if (!chxj_update_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) {
358         ERR(r, "failed: chxj_update_cookie_mysql() cookie_id:[%s]", cookie->cookie_id);
359         goto on_error;
360       }
361       done_proc = 1;
362     }
363 #endif
364
365 #if defined(USE_MEMCACHE_COOKIE)
366     if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
367       if (! chxj_update_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) {
368         ERR(r, "failed: chxj_update_cookie_memcache() cookie_id:[%s]", cookie->cookie_id);
369         goto on_error;
370       }
371       done_proc = 1;
372     }
373 #endif
374     if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
375       if (! chxj_update_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) {
376         ERR(r, "failed: chxj_update_cookie_dbm() cookie_id:[%s]", cookie->cookie_id);
377         goto on_error;
378       }
379     }
380   }
381
382   chxj_save_cookie_expire(r, cookie);
383
384   apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id);
385
386
387 on_error:
388   DBG(r, "end   chxj_update_cookie()");
389   return cookie;
390 }
391
392
393 /*
394  *
395  * @return loaded data.
396  */
397 cookie_t*
398 chxj_load_cookie(request_rec* r, char* cookie_id)
399 {
400   mod_chxj_config         *dconf;
401   chxjconvrule_entry      *entryp;
402   cookie_t                *cookie;
403   apr_table_t             *load_cookie_table;
404   char                    *load_string = NULL;
405   char                    *pstat;
406   char                    *key;
407   char                    *val;
408   char                    *pair;
409   char                    *header_cookie;
410
411   DBG(r, "========================================================");
412   DBG(r, "========================================================");
413   DBG(r, "========================================================");
414   DBG(r, "========================================================");
415   DBG(r, "start chxj_load_cookie() cookie_id=[%s]", cookie_id);
416   chxj_cookie_expire_gc(r);
417
418   cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t));
419   cookie->cookie_headers = NULL;
420   cookie->cookie_id = apr_pstrdup(r->pool, cookie_id);
421
422   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
423   entryp = chxj_apply_convrule(r, dconf->convrules);
424   if (! entryp) {
425     DBG(r, "end chxj_load_cookie() no pattern");
426     goto on_error0;
427   }
428   if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
429     DBG(r, "end chxj_load_cookie() CookieOff");
430     goto on_error0;
431   }
432   load_cookie_table = apr_table_make(r->pool, 0);
433
434   {
435     int done_proc = 0;
436 #if defined(USE_MYSQL_COOKIE)
437     if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
438       if (! (load_string = chxj_load_cookie_mysql(r, dconf, cookie->cookie_id))) {
439         ERR(r, "failed: chxj_load_cookie_mysql() cookie_id:[%s]", cookie_id);
440         goto on_error0;
441       }
442       done_proc = 1;
443     }
444 #endif
445 #if defined(USE_MEMCACHE_COOKIE)
446     if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
447       if (! (load_string = chxj_load_cookie_memcache(r, dconf, cookie->cookie_id))) {
448         ERR(r, "failed: chxj_load_cookie_memcache() cookie_id:[%s]", cookie_id);
449         goto on_error0;
450       }
451       done_proc = 1;
452     }
453 #endif
454     if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
455       if (! (load_string = chxj_load_cookie_dbm(r, dconf, cookie->cookie_id))) {
456         ERR(r, "failed: chxj_load_cookie_dbm() cookie_id:[%s]", cookie_id);
457         goto on_error0;
458       }
459     }
460   }
461
462   if (load_string) {
463     DBG(r, "load_string=[%s]", load_string);
464     header_cookie = apr_palloc(r->pool, 1);
465     header_cookie[0] = 0;
466     for (;;) {
467       char* tmp_sem;
468       pair = apr_strtok(load_string, "\n", &pstat);  
469       load_string = NULL;
470       if (!pair) break;
471
472       DBG(r, "Cookie:[%s]", pair);
473       char* tmp_pair;
474
475       tmp_pair = apr_pstrdup(r->pool, pair);
476       val = strchr(tmp_pair, '=');
477       if (val) {
478         key = tmp_pair;
479         *val++ = 0;
480         apr_table_add(load_cookie_table, key, val);
481         DBG(r, "ADD key:[%s] val:[%s]", key, val);
482       }
483       tmp_pair = apr_pstrdup(r->pool, pair);
484       tmp_sem = strchr(tmp_pair, ';'); 
485       if (tmp_sem)
486         *tmp_sem = '\0';
487
488       if (check_valid_cookie_attribute(r, pair)) {
489         if (strlen(header_cookie)) 
490           header_cookie = apr_pstrcat(r->pool, header_cookie, ";", NULL);
491   
492         header_cookie = apr_pstrcat(r->pool, header_cookie, tmp_pair, NULL);
493       }
494     }
495     if (strlen(header_cookie)) {
496       DBG(r, "ADD COOKIE to REQUEST HEADER:[%s]", header_cookie);
497       apr_table_add(r->headers_in, "Cookie", header_cookie);
498     }
499   
500     cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(load_cookie_table);
501
502     if (apr_table_get(r->headers_in, "referer") == NULL) {
503       apr_table_setn(r->headers_in, 
504                      "referer",
505                      apr_table_get(load_cookie_table, REFERER_COOKIE_KEY));
506     }
507   
508     /*
509      * save cookie_id to request header.
510      */
511     apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id);
512   }
513
514   DBG(r, "end   chxj_load_cookie()");
515   DBG(r, "========================================================");
516   DBG(r, "========================================================");
517   DBG(r, "========================================================");
518   DBG(r, "========================================================");
519
520   return cookie;
521
522
523 on_error0:
524
525   DBG(r, "end   chxj_load_cookie()");
526   DBG(r, "========================================================");
527   DBG(r, "========================================================");
528   DBG(r, "========================================================");
529   DBG(r, "========================================================");
530   return NULL;
531 }
532
533 static int
534 check_valid_cookie_attribute(request_rec *r, const char *value)
535 {
536   char *pstat;
537   char *pair;
538   char *first_pair;
539   char *domain_pair;
540   char *path_pair;
541   char *expire_pair;
542   char *secure_pair;
543   char *p;
544
545   DBG(r, "start check_valid_cookie_attribute() value:[%s]", value);
546
547   domain_pair = path_pair = expire_pair = secure_pair = NULL;
548   p = apr_pstrdup(r->pool, value);
549
550   /* pass first pair */
551   first_pair = apr_strtok(p, ";", &pstat);  
552
553   for (;;) {
554     pair = apr_strtok(NULL, ";", &pstat);
555     if (! pair) break;
556     pair = qs_trim_string(r->pool, pair);
557     if (STRNCASEEQ('d','D',"domain", pair, sizeof("domain")-1)) {
558       domain_pair = apr_pstrdup(r->pool, pair);
559     }
560     else if (STRNCASEEQ('p','P',"path", pair, sizeof("path")-1)) {
561       path_pair = apr_pstrdup(r->pool, pair);
562     }
563     else if (STRNCASEEQ('e','E',"expires", pair, sizeof("expires")-1)) {
564       expire_pair = apr_pstrdup(r->pool, pair);
565     }
566     else if (STRNCASEEQ('s','S',"secure", pair, sizeof("secure")-1)) {
567       secure_pair = apr_pstrdup(r->pool, pair);
568     }
569   }
570
571   if (domain_pair) {
572     if (!valid_domain(r, domain_pair)) {
573       DBG(r, "invalid domain. domain_pair:[%s]", domain_pair);
574       return CHXJ_FALSE;
575     }
576   }
577   if (path_pair) {
578     if (!valid_path(r, path_pair)) {
579       DBG(r, "invalid path. path_pair:[%s]", path_pair);
580       return CHXJ_FALSE;
581     }
582   }
583   if (expire_pair) {
584     if (!valid_expires(r, expire_pair)) {
585       DBG(r, "invalid expire. expire_pair:[%s]", expire_pair);
586       return CHXJ_FALSE;
587     }
588   }
589   if (secure_pair) {
590     if (!valid_secure(r, secure_pair)) {
591       DBG(r, "invalid secure. secure_pair:[%s]", secure_pair);
592       return CHXJ_FALSE;
593     }
594   }
595   DBG(r, "end check_valid_cookie_attribute() value:[%s]", value);
596   return CHXJ_TRUE;
597 }
598
599 static int
600 valid_domain(request_rec *r, const char *value)
601 {
602   int len;
603   char *name;
604   char *val;
605   char *pstat;
606   char *p = apr_pstrdup(r->pool, value);
607   const char *host = apr_table_get(r->headers_in, HTTP_HOST);
608
609   DBG(r, "start valid_domain() value:[%s]", value);
610   DBG(r, "host:[%s]", host);
611   if (!host)
612     return CHXJ_TRUE;
613
614   name = apr_strtok(p,"=", &pstat);
615   name = qs_trim_string(r->pool, name);
616   val = apr_strtok(NULL, "=", &pstat);
617   val = qs_trim_string(r->pool, val);
618   len = strlen(host);
619   if (len) {
620     if (chxj_strcasenrcmp(r->pool, host, val, strlen(val))) {
621       DBG(r, "not match domain. host domain:[%s] vs value:[%s]", host, val);
622       return CHXJ_FALSE;
623     }
624   }
625   DBG(r, "end valid_domain() value:[%s]", value);
626   return CHXJ_TRUE;
627 }
628
629 static int
630 valid_path(request_rec *r, const char *value)
631 {
632   char *p = apr_pstrdup(r->pool, value);
633   char *uri;
634   char *tmp;
635   char *name;
636   char *val;
637   char *pstat;
638
639   DBG(r, "start valid_path() unparsed_uri:[%s] value:[%s]", r->unparsed_uri, value);
640   if (chxj_starts_with(r->unparsed_uri, "http://")) {
641     uri = strchr(&r->unparsed_uri[sizeof("http://")], '/');
642     if (uri != NULL) {
643       uri = apr_pstrdup(r->pool, uri);
644     }
645   }
646   else if (chxj_starts_with(r->unparsed_uri, "https://")) {
647     uri = strchr(&r->unparsed_uri[sizeof("https://")], '/');
648     if (uri != NULL) {
649       uri = apr_pstrdup(r->pool, uri);
650     }
651   }
652   else if (chxj_starts_with(r->unparsed_uri, "/")) {
653     uri = apr_pstrdup(r->pool, r->unparsed_uri);
654   }
655   else {
656     uri = apr_pstrdup(r->pool, "/");
657   }
658   
659   if ((tmp = strchr(uri, '?'))) {
660     *tmp = '\0';
661   }
662   DBG(r, "uri=[%s]", uri);
663   name = apr_strtok(p, "=", &pstat);
664   val = apr_strtok(NULL, "=", &pstat);
665   name = qs_trim_string(r->pool, name);
666   val = qs_trim_string(r->pool, val);
667   DBG(r, "name=[%s] val=[%s]", name, val);
668   
669   DBG(r, "val:[%s] vs uri:[%s]", val, uri);
670   if (! chxj_starts_with(uri, val)) {
671     DBG(r, "end valid_path() unparsed_uri:[%s] value:[%s] (false)", r->unparsed_uri, value);
672     return CHXJ_FALSE;
673   }
674   DBG(r, "end valid_path() unparsed_uri:[%s] value:[%s] (true)", r->unparsed_uri, value);
675   return CHXJ_TRUE;
676 }
677
678 static int
679 valid_expires(request_rec *r, const char *value)
680 {
681   char *name;
682   char *val;
683   char *p = apr_pstrdup(r->pool, value);
684   char *pstat;
685   apr_time_t expires;
686   apr_time_t now;
687   DBG(r, "start valid_expire() value:[%s]", value);
688
689   name = apr_strtok(p, "=", &pstat);
690   val  = apr_strtok(NULL, "=", &pstat);
691   DBG(r, "name=[%s] val=[%s]", name, val);
692   now = apr_time_now();
693   expires = chxj_parse_cookie_expires(val);
694   DBG(r, "now=[%lld] expires=[%lld]", now, expires);
695   if (expires < now) {
696     DBG(r, "end valid_expire() value:[%s] (expired)", value);
697     return CHXJ_FALSE;
698   }
699   
700   DBG(r, "end valid_expire() value:[%s] (non expired)", value);
701   return CHXJ_TRUE;
702 }
703
704 static int
705 valid_secure(request_rec *r, const char *value)
706 {
707   const char *scheme;
708   DBG(r, "start valid_secure() value:[%s]", value);
709   scheme = chxj_apache_run_http_scheme(r);
710   if (strcasecmp("https", scheme)) {
711     DBG(r, "end valid_secure() value:[%s] (non secure)", value);
712     return CHXJ_FALSE;
713   }
714   DBG(r, "end valid_secure() value:[%s] (secure)", value);
715   return CHXJ_TRUE;
716 }
717
718
719 char*
720 chxj_add_cookie_parameter(request_rec* r, char* value, cookie_t* cookie)
721 {
722   char* qs;
723   char* dst;
724
725   DBG(r, "start chxj_add_cookie_parameter() cookie_id=[%s]", (cookie) ? cookie->cookie_id : NULL);
726
727   dst = apr_pstrdup(r->pool, value);
728
729   if (!cookie)
730     goto on_error;
731
732   if (!cookie->cookie_id)
733     goto on_error;
734
735   if (chxj_cookie_check_host(r, value) != 0) {
736     DBG(r, "end chxj_add_cookie_parameter()(check host)");
737     goto on_error;
738   }
739
740   qs = strchr(dst, '?');
741   if (qs) {
742     dst = apr_psprintf(r->pool, "%s&%s=%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id);
743   }
744   else {
745     dst = apr_psprintf(r->pool, "%s?%s=%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id);
746   }
747
748   DBG(r, "end   chxj_add_cookie_parameter() dst=[%s]", dst);
749
750   return dst;
751
752 on_error:
753   DBG(r, "end   chxj_add_cookie_parameter() (on_error)");
754   return dst;
755 }
756
757
758 int
759 chxj_cookie_check_host(request_rec* r, char* value) 
760 {
761   char* hostnm;
762
763   DBG(r, "hostname=[%s]", r->hostname);
764
765   hostnm = s_get_hostname_from_url(r, value);
766   if (hostnm) {
767     if (strcasecmp(hostnm, r->hostname) == 0)
768       return 0;
769     else
770       return 1;
771   }
772   return 0;
773 }
774
775
776 static char*
777 s_get_hostname_from_url(request_rec* r, char* value)
778 {
779   if (!value) 
780     return NULL; 
781
782   if (strncasecmp(value, "http://",  7) == 0 )
783     return s_cut_until_end_hostname(r, &value[7]);
784
785   if (strncasecmp(value, "https://", 8) == 0)
786     return s_cut_until_end_hostname(r, &value[8]);
787
788   return NULL;
789 }
790
791
792 static char* 
793 s_cut_until_end_hostname(request_rec* r, char* value)
794 {
795   char* sp;
796   char* hostnm;
797
798   hostnm = sp = apr_pstrdup(r->pool, value);
799   for (;*sp; sp++) {
800     if (*sp == '/'|| *sp == '?') {
801       *sp = '\0';
802       break;
803     }
804   }
805   return hostnm;
806 }
807
808
809
810 void
811 chxj_delete_cookie(request_rec *r, const char *cookie_id)
812 {
813   int done_proc = 0;
814   mod_chxj_config *dconf;
815
816   DBG(r, "start chxj_delete_cookie()");
817   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
818
819 #if defined(USE_MYSQL_COOKIE)
820   if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
821     if (! chxj_delete_cookie_mysql(r, dconf, cookie_id)) {
822       ERR(r, "failed: chxj_delete_cookie_mysql() cookie_id:[%s]", cookie_id);
823       DBG(r, "end   chxj_delete_cookie()");
824       return;
825     }
826     done_proc = 1;
827   }
828 #endif
829
830 #if defined(USE_MEMCACHE_COOKIE)
831   if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
832     if (! chxj_delete_cookie_memcache(r, dconf, cookie_id)) {
833       ERR(r, "failed: chxj_delete_cookie_memcache() cookie_id:[%s]", cookie_id);
834       DBG(r, "end   chxj_delete_cookie()");
835       return;
836     }
837     done_proc = 1;
838   }
839 #endif
840   if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
841     if (! chxj_delete_cookie_dbm(r, dconf, cookie_id)) {
842       ERR(r, "failed: chxj_delete_cookie_dbm() cookie_id:[%s]", cookie_id);
843       DBG(r, "end   chxj_delete_cookie()");
844       return;
845     }
846   }
847
848   DBG(r, "end   chxj_delete_cookie()");
849 }
850
851
852 /*
853  *
854  */
855 void
856 chxj_save_cookie_expire(request_rec* r, cookie_t* cookie)
857 {
858   int done_proc = 0;
859   mod_chxj_config         *dconf;
860
861   DBG(r, "start chxj_save_cookie_expire()");
862   if (!cookie) {
863     DBG(r, "cookie is NULL");
864     return;
865   }
866   if (!cookie->cookie_id) {
867     DBG(r, "cookie->cookie_id is NULL");
868     return;
869   }
870
871   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
872   if (!dconf) {
873     DBG(r, "dconf is NULL");
874     return;
875   }
876
877 #if defined(USE_MYSQL_COOKIE)
878   if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
879     if (! chxj_save_cookie_expire_mysql(r, dconf, cookie->cookie_id)) {
880       ERR(r, "failed: chxj_save_cookie_expire_mysql() cookie_id:[%s]", cookie->cookie_id);
881       DBG(r, "end   chxj_save_cookie_expire()");
882       return;
883     }
884     done_proc = 1;
885   }
886 #endif
887 #if defined(USE_MEMCACHE_COOKIE)
888   if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
889     if (! chxj_save_cookie_expire_memcache(r, dconf, cookie->cookie_id)) {
890       ERR(r, "failed: chxj_save_cookie_expire_memcache() cookie_id:[%s]", cookie->cookie_id);
891       DBG(r, "end   chxj_save_cookie_expire()");
892       return;
893     }
894     done_proc = 1;
895   }
896 #endif
897   if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
898     if (! chxj_save_cookie_expire_dbm(r, dconf, cookie->cookie_id)) {
899       ERR(r, "failed: chxj_save_cookie_expire_dbm() cookie_id:[%s]", cookie->cookie_id);
900       DBG(r, "end   chxj_save_cookie_expire()");
901       return;
902     }
903   }
904
905   DBG(r, "end   chxj_save_cookie_expire()");
906 }
907
908
909
910
911
912 void
913 chxj_delete_cookie_expire(request_rec* r, char* cookie_id)
914 {
915   int done_proc = 0;
916   mod_chxj_config*  dconf;
917
918   DBG(r, "start chxj_delete_cookie_expire()");
919
920   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
921
922 #if defined(USE_MYSQL_COOKIE)
923   if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
924     if (! chxj_delete_cookie_expire_mysql(r, dconf, cookie_id)) {
925       ERR(r, "failed: chxj_delete_cookie_expire_mysql() cookie_id:[%s]", cookie_id);
926       return;
927     }
928     done_proc = 1;
929   }
930 #endif
931 #if defined(USE_MEMCACHE_COOKIE)
932   if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
933     if (!chxj_delete_cookie_expire_memcache(r, dconf, cookie_id)) {
934       ERR(r, "failed: chxj_delete_cookie_expire_memcache() cookie_id:[%s]", cookie_id);
935       return;
936     } 
937     done_proc = 1;
938   }
939 #endif
940   if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) {
941     if (!chxj_delete_cookie_expire_dbm(r, dconf, cookie_id)) {
942       ERR(r, "failed: chxj_delete_cookie_expire_dbm() cookie_id:[%s]", cookie_id);
943       return;
944     } 
945   }
946
947   DBG(r, "end   chxj_delete_cookie_expire()");
948
949   return;
950 }
951
952
953 void
954 chxj_cookie_expire_gc(request_rec* r)
955 {
956   mod_chxj_config   *dconf;
957   int done_proc = 0;
958
959   DBG(r, "start chxj_cookie_expire_gc()");
960
961   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
962 #if defined(USE_MYSQL_COOKIE)
963   if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) {
964     if (! chxj_cookie_expire_gc_mysql(r, dconf)) {
965       ERR(r, "failed: chxj_cookie_expire_gc_mysql()");
966       return;
967     }
968     done_proc = 1;
969   } 
970 #endif
971 #if defined(USE_MEMCACHE_COOKIE)
972   if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) {
973     if (! chxj_cookie_expire_gc_memcache(r, dconf)) {
974       ERR(r, "failed: chxj_cookie_expire_gc_memcache()");
975       return;
976     }
977     done_proc = 1;
978   } 
979 #endif
980   if (!done_proc) {
981     if (! chxj_cookie_expire_gc_dbm(r, dconf)) {
982       ERR(r, "failed: chxj_cookie_expire_gc_dbm()");
983       return;
984     }
985   }
986   DBG(r, "end   chxj_cookie_expire_gc()");
987 }
988
989 apr_time_t
990 chxj_parse_cookie_expires(const char *s)
991 {
992   if (!s) return (apr_time_t)0;
993   return apr_date_parse_rfc(s);
994 }
995 /*
996  * vim:ts=2 et
997  */