OSDN Git Service

* changed feature.
[modchxj/mod_chxj.git] / src / chxj_tag_util.c
1 /*
2  * Copyright (C) 2005-2011 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 "chxj_tag_util.h"
18 #include "chxj_url_encode.h"
19 #include "chxj_str_util.h"
20 #include "chxj_jreserved_tag.h"
21 #include "mod_chxj.h"
22
23
24 /**
25  * The value of the VALUE attribute that the object tag node maintains is
26  * acquired.
27  *
28  * @param doc  [i] The pointer to the Doc structure to be scanned is
29  *                 specified.
30  * @param node [i] The tag node to be scanned is specified.
31  * @param pool [i] To use POOL.
32  * @return The value of the VALUE attribute that the object tag node maintains
33  *         is returned. NULL is returned when not found.
34  */
35 char *
36 qs_get_value_attr(Doc *doc, Node *node, apr_pool_t *pool)
37 {
38   Attr *attr;
39
40   /*--------------------------------------------------------------------------*/
41   /* The object tag node is scanned.                                          */
42   /*--------------------------------------------------------------------------*/
43   for (attr = qs_get_attr(doc,node);
44        attr;
45        attr = qs_get_next_attr(doc,attr)) {
46     char *name  = qs_get_attr_name(doc,attr);
47     char *value = qs_get_attr_value(doc,attr);
48     if (STRCASEEQ('v','V',"value",name)) {
49       /*----------------------------------------------------------------------*/
50       /* The VALUE attribute was found.                                       */
51       /*----------------------------------------------------------------------*/
52       return apr_pstrdup(pool, value);
53     }
54   }
55   /*--------------------------------------------------------------------------*/
56   /* not found                                                                */
57   /*--------------------------------------------------------------------------*/
58   return NULL;
59 }
60
61
62 /**
63  * The value of the checked tag is acquired.
64  *
65  * @param doc  [i] The pointer to the Doc structure to be scanned is
66  *                 specified.
67  * @param tag  [i] The tag node to be scanned is specified.
68  * @param pool [i] To use POOL(unused).
69  * @return The value of the checked tag is returned. NULL is returned when
70  *         not found.
71  */
72 char *
73 qs_get_checked_attr(Doc *doc, Node *tag, apr_pool_t *UNUSED(pool))
74 {
75   Attr *attr;
76   /*--------------------------------------------------------------------------*/
77   /* The object tag node is scanned.                                          */
78   /*--------------------------------------------------------------------------*/
79   for (attr = qs_get_attr(doc,tag);
80        attr != NULL;
81        attr = qs_get_next_attr(doc,attr)) {
82     char *name  = qs_get_attr_name(doc,attr);
83     if (STRCASEEQ('c','C',"checked",name)) {
84       /*----------------------------------------------------------------------*/
85       /* The VALUE attribute was found.                                       */
86       /*----------------------------------------------------------------------*/
87       return name;
88     }
89   }
90   /*------------------------------------------------------------------------*/
91   /* not found                                                              */
92   /*------------------------------------------------------------------------*/
93   return NULL;
94 }
95
96
97 /**
98  * The value of the type attribute is acquired.
99  *
100  * @param doc  [i] The pointer to the Doc structure to be scanned is
101  *                 specified.
102  * @param tag  [i] The tag node to be scanned is specified.
103  * @param r    [i] To use POOL, the pointer to request_rec is specified.
104  * @return The value of the type attribute is returned. NULL is returned when
105  *         not found.
106  */
107 char *
108 qs_get_type_attr(Doc *doc, Node *tag, apr_pool_t *pool)
109 {
110   Attr *attr;
111   /*--------------------------------------------------------------------------*/
112   /* The object tag node is scanned.                                          */
113   /*--------------------------------------------------------------------------*/
114   for (attr = qs_get_attr(doc,tag);
115        attr != NULL;
116        attr = qs_get_next_attr(doc,attr)) {
117     char *name  = qs_get_attr_name(doc,attr);
118     char *value = qs_get_attr_value(doc,attr);
119     if (STRCASEEQ('t','T',"type",name)) {
120       /*----------------------------------------------------------------------*/
121       /* The VALUE attribute was found.                                       */
122       /*----------------------------------------------------------------------*/
123       return apr_pstrdup(pool, value);
124     }
125   }
126   /*--------------------------------------------------------------------------*/
127   /* not found                                                                */
128   /*--------------------------------------------------------------------------*/
129   return NULL;
130 }
131
132
133 /**
134  * The character string area in 0 bytes is allocated.
135  *
136  * @param pool    [i]   To use POOL.
137  * @return The allocated 0 byte character string is returned.
138  */
139 char *
140 qs_alloc_zero_byte_string(apr_pool_t *pool)
141 {
142   char *tgt;
143
144   if (! pool) {
145     return NULL;
146   }
147   tgt = apr_palloc(pool, 1);
148   tgt[0] = '\0';
149
150   return tgt;
151 }
152
153
154 /**
155  * A consecutive head and the last WHITESPACE are removed.
156  *
157  * @param p    [i]   To use POOL
158  * @param s    [i]   The character string that should be removed is specified.
159  * @return The character string that has been removed is returned.
160  */
161 char *
162 qs_trim_string(apr_pool_t *p, char *s)
163 {
164   char *ss;
165   int len;
166   int ii;
167
168   if (! s) return apr_pstrdup(p, "");
169
170   ss = apr_pstrdup(p, s);
171   len = strlen(s);
172   ii = 0;
173   for (ii = 0;is_white_space(*ss) && ii < len; ss++, ii++);
174
175   ii = strlen(ss);
176   for(;is_white_space(ss[ii-1]) && ii > 0; ii--);
177
178   ss[ii] = '\0';
179
180   return ss;
181 }
182
183
184 /**
185  * The value of child TEXT of tag that maintains the SELECTED attribute is 
186  * returned. 
187  *
188  * @param Doc  [i] The pointer to the Doc structure to be scanned is 
189  *                 specified. 
190  * @param node [i] The tag node to be scanned is specified.
191  * @param pool [i] To use POOL.
192  * @reutrn  The value of child TEXT of tag that maintains the SELECTED 
193  *          attribute is returned. NULL is returned when not found. 
194  */
195 char *
196 qs_get_selected_value_text(Doc *doc, Node *node, apr_pool_t *pool)
197 {
198   Node *child;
199   Node *selchild;
200   char *result   = NULL;
201
202   for (child = qs_get_child_node(doc,node);
203        child != NULL; 
204        child = qs_get_next_node(doc,child)) {
205     char *name = qs_get_node_name(doc,child);
206     /*------------------------------------------------------------------------*/
207     /* <OPTION> tag                                                           */
208     /*------------------------------------------------------------------------*/
209     if (STRCASEEQ('o','O',"option",name)) {
210       Attr *attr;
211       for (attr =  qs_get_attr(doc,child); 
212            attr != NULL; 
213            attr = qs_get_next_attr(doc,attr)) {
214         char *name2  = qs_get_attr_name(doc,attr);
215         if (STRCASEEQ('s','S',"selected",name2)) {
216           /*------------------------------------------------------------------*/
217           /* SELECTED Value Found                                             */
218           /*------------------------------------------------------------------*/
219           selchild = qs_get_child_node(doc, child);
220           if (! selchild) {
221             /* void value */
222             return apr_pstrdup(pool, "");
223           }
224           return qs_get_node_value(doc, selchild);
225         }
226       }
227     }
228
229     if ((result = qs_get_selected_value_text(doc, child, pool)) != NULL) {
230       return result;
231     }
232   }
233
234   /*--------------------------------------------------------------------------*/
235   /* not found                                                                */
236   /*--------------------------------------------------------------------------*/
237   return NULL;
238 }
239
240
241 /**
242  * The value of tag that maintains the SELECTED attribute is acquired. 
243  *
244  * @param doc    [i]  The pointer to the Doc structure to be scanned is 
245  *                    specified. 
246  * @param node   [i]  The SELECT tag node is specified.
247  * @param pool   [i] To use POOL.
248  * @return The value of tag that maintains the SELECTED attribute is 
249  *         returned. NULL is returned when not found. 
250  */
251 char *
252 qs_get_selected_value(Doc *doc, Node *node, apr_pool_t *pool)
253 {
254   Node *child;
255   char *result    = NULL;
256
257   for (child = qs_get_child_node(doc,node); 
258        child != NULL; 
259        child = qs_get_next_node(doc,child)) {
260     char *name = qs_get_node_name(doc,child);
261     /*------------------------------------------------------------------------*/
262     /* <OPTION> tag                                                           */
263     /*------------------------------------------------------------------------*/
264     if (STRCASEEQ('o','O',"option",name)) {
265       Attr *attr;
266       for (attr = qs_get_attr(doc,child); 
267            attr; 
268            attr = qs_get_next_attr(doc,attr)) {
269         char *name2  = qs_get_attr_name(doc,attr);
270         if (STRCASEEQ('s','S',"selected",name2)) {
271           /*------------------------------------------------------------------*/
272           /* SELECTED Value Found                                             */
273           /*------------------------------------------------------------------*/
274           return qs_get_value_attr(doc, child, doc->buf.pool);
275         }
276       }
277     }
278
279     if ((result = qs_get_selected_value(doc, child, pool)) != NULL) {
280       return result;
281     }
282   }
283
284   /*--------------------------------------------------------------------------*/
285   /* not found                                                                */
286   /*--------------------------------------------------------------------------*/
287   return NULL;
288 }
289
290
291 /**
292  * The value of the NAME attribute is acquired.
293  *
294  * @param doc  [i] The pointer to the Doc structure at the output
295  *                 destination is specified.
296  * @param tag  [i] The tag node to want to acquire the SIZE attribute
297  *                 is specified.
298  * @param pool [i] To use POOL.
299  * @return The value of the NAME attribute is returned. NULL is
300  *         returned when not is.
301  */
302 char *
303 qs_get_name_attr(Doc *doc, Node *tag, apr_pool_t *pool)
304 {
305   Attr *attr;
306   for (attr = qs_get_attr(doc,tag); 
307        attr; 
308        attr = qs_get_next_attr(doc,attr)) {
309     char *name  = qs_get_attr_name(doc,attr);
310     char *value = qs_get_attr_value(doc,attr);
311     if (STRCASEEQ('n','N',"name",name)) {
312       return apr_pstrdup(pool, (value ? value : ""));
313     }
314   }
315   return NULL;
316 }
317
318
319 /**
320  * The value of the SIZE attribute is acquired.
321  *
322  * @param doc  [i] The pointer to the Doc structure at the output
323  *                 destination is specified.
324  * @param tag  [i] The tag node to want to acquire the SIZE attribute
325  *                 is specified.
326  * @param pool [i] To use POOL.
327  * @return The value of the SIZE attribute is returned. NULL is
328  *         returned when not is.
329  */
330 char *
331 qs_get_size_attr(Doc *doc, Node *tag, apr_pool_t *pool)
332 {
333   Attr *attr;
334   for (attr = qs_get_attr(doc,tag); 
335        attr; 
336        attr = qs_get_next_attr(doc,attr)) {
337     char *name  = qs_get_attr_name(doc,attr);
338     char *value = qs_get_attr_value(doc,attr);
339     if (STRCASEEQ('s','S',"size",name)) {
340       return apr_pstrdup(pool, (value ? value : ""));
341     }
342   }
343   return NULL;
344 }
345
346
347 /**
348  * The value of the ACCESSKEY attribute is acquired.
349  *
350  * @param doc  [i] The pointer to the Doc structure at the output
351  *                 destination is specified.
352  * @param tag  [i] The tag node to want to acquire the ACCESSKEY attribute
353  *                 is specified.
354  * @param pool [i] To use POOL.
355  * @return The value of the ACCESSKEY attribute is returned. NULL is
356  *         returned when not is.
357  */
358 char *
359 qs_get_accesskey_attr(Doc *doc, Node *tag, apr_pool_t *pool)
360 {
361   Attr *attr;
362   for (attr = qs_get_attr(doc,tag); 
363        attr; 
364        attr = qs_get_next_attr(doc,attr)) {
365     char *name  = qs_get_attr_name(doc,attr);
366     char *value = qs_get_attr_value(doc,attr);
367     if (STRCASEEQ('a','A',"accesskey",name)) {
368       return apr_pstrdup(pool, value);
369     }
370   }
371   return NULL;
372 }
373
374
375 /**
376  * The value of the ISTYLE attribute is acquired.
377  *
378  * @param doc  [i] The pointer to the Doc structure at the output
379  *                 destination is specified.
380  * @param tag  [i] The tag node to want to acquire the ISTYLE attribute
381  *                 is specified.
382  * @param pool [i] To use POOL.
383  * @return The value of the ISTYLE attribute is returned. NULL is
384  *         returned when not is.
385  */
386 char *
387 qs_get_istyle_attr(Doc *doc, Node *tag, apr_pool_t *pool)
388 {
389   Attr *attr;
390   for (attr = qs_get_attr(doc,tag); 
391        attr != NULL; 
392        attr = qs_get_next_attr(doc,attr)) {
393     char *name  = qs_get_attr_name(doc,attr);
394     char *value = qs_get_attr_value(doc,attr);
395     if (STRCASEEQ('i','I',"istyle",name)) {
396       return apr_pstrdup(pool, value);
397     }
398   }
399   return NULL;
400 }
401
402
403 /**
404  * The value of the MAXLENGTH attribute is acquired from the tag node of the
405  * object.
406  *
407  * @param doc  [i] The pointer to the Doc structure at the output
408  *                 destination is specified.
409  * @param tag  [i] The tag node to want to acquire the MAXLENGTH attribute
410  *                 is specified.
411  * @param pool [i] To use POOL.
412  * @return The value of the MAXLENGTH attribute is returned. NULL is
413  *         returned when not is.
414  */
415 char *
416 qs_get_maxlength_attr(Doc *doc, Node *tag, apr_pool_t *pool)
417 {
418   Attr *attr;
419   for (attr = qs_get_attr(doc,tag);
420        attr; 
421        attr = qs_get_next_attr(doc,attr)) {
422     char *name  = qs_get_attr_name(doc,attr);
423     char *value = qs_get_attr_value(doc,attr);
424     if (STRCASEEQ('m','M',"maxlength",name)) {
425       return apr_pstrdup(pool, value);
426     }
427   }
428   return NULL;
429 }
430
431
432 /**
433  * It is scanned whether the CHECKBOX tag of the object is CHECKED. 
434  *
435  * @param doc  [i] The pointer to the Doc structure at the output
436  *                 destination is specified.
437  * @param tag  [i] The tag node to want to acquire the CHECKBOX attribute
438  *                 is specified.
439  * @param pool [i] To use POOL.
440  * @return 1 is returned when it is CHECKED and, additionally, 0 is returned. 
441  */
442 int
443 qs_is_checked_checkbox_attr(Doc *doc, Node *tag, apr_pool_t *UNUSED(pool))
444 {
445   Attr *attr;
446   for (attr = qs_get_attr(doc,tag);
447        attr; 
448        attr = qs_get_next_attr(doc,attr)) {
449     char *name  = qs_get_attr_name(doc,attr);
450     if (STRCASEEQ('c','C',"checked",name)) {
451       return 1;
452     }
453   }
454   return 0;
455 }
456
457
458 int
459 chxj_chxjif_is_mine(device_table *spec, Doc *doc, Node *tag)
460 {
461   request_rec *r = doc->r;
462   Attr        *attr;
463
464   for (attr = qs_get_attr(doc,tag);
465        attr; 
466        attr = qs_get_next_attr(doc,attr)) {
467     char *name  = qs_get_attr_name(doc,attr);
468     char *value = qs_get_attr_value(doc,attr);
469     if ((*name == 'l' || *name == 'L') && strcasecmp(name, "lang") == 0) {
470
471       DBG(r,"REQ[%X] lang found [%s] spec [%d]", TO_ADDR(r),value, spec->html_spec_type);
472       if (STRCASEEQ('a','A',"all",value)) {
473         return 1;
474       }
475       else if (STRCASEEQ('x','X',"xhtml",value)) {
476         if (spec->html_spec_type == CHXJ_SPEC_XHtml_Mobile_1_0) {
477           /* Yes , it is mine */
478           return 1;
479         }
480       }
481       else if (STRCASEEQ('h','H',"hdml",value)) {
482         if (spec->html_spec_type == CHXJ_SPEC_Hdml) {
483           /* Yes , it is mine */
484           return 1;
485         }
486       }
487       else if (STRCASEEQ('j','J',"jhtml",value)) {
488         if (spec->html_spec_type == CHXJ_SPEC_Jhtml) {
489           /* Yes , it is mine */
490           return 1;
491         }
492       }
493       else if (STRCASEEQ('j','J',"jxhtml",value)) {
494         if (spec->html_spec_type == CHXJ_SPEC_Jxhtml) {
495           /* Yes , it is mine */
496           return 1;
497         }
498       }
499       else if (STRCASEEQ('c','C',"chtml",value)) {
500         switch (spec->html_spec_type) {
501         case CHXJ_SPEC_Chtml_1_0:
502         case CHXJ_SPEC_Chtml_2_0:
503         case CHXJ_SPEC_Chtml_3_0:
504         case CHXJ_SPEC_Chtml_4_0:
505         case CHXJ_SPEC_Chtml_5_0:
506         case CHXJ_SPEC_Chtml_6_0:
507         case CHXJ_SPEC_Chtml_7_0:
508           return 1;
509         default:
510           break;
511         }
512       }
513       else if (STRCASEEQ('i','I',"ixhtml",value)) {
514         switch (spec->html_spec_type) {
515         case CHXJ_SPEC_Chtml_6_0:
516         case CHXJ_SPEC_Chtml_7_0:
517           return 1;
518         default:
519           break;
520         }
521       }
522     }
523   }
524
525   /* No, it is not mine. */
526   return 0;
527 }
528
529
530 /**
531  * The value of the DESTLANG attribute is acquired from the tag node of the
532  * object.
533  *
534  * @param doc  [i] The pointer to the Doc structure at the output
535  *                 destination is specified.
536  * @param tag  [i] The tag node to want to acquire the DESTLANG attribute
537  *                 is specified.
538  * @param pool [i] To use POOL.
539  * @return The value of the DESTLANG attribute is returned. NULL is
540  *         returned when not is.
541  */
542 char *
543 qs_get_destlang_attr(Doc *doc, Node *tag, apr_pool_t *pool)
544 {
545   Attr  *attr;
546   for (attr = qs_get_attr(doc,tag);
547        attr; 
548        attr = qs_get_next_attr(doc,attr)) {
549     char *name  = qs_get_attr_name(doc,attr);
550     char *value = qs_get_attr_value(doc,attr);
551     if (STRCASEEQ('d','D',"destlang",name)) {
552       return apr_pstrdup(pool, value);
553     }
554   }
555
556   return NULL;
557 }
558
559
560 /**
561  * The value of the PARSE attribute is acquired.
562  *
563  * @param doc  [i] The pointer to the Doc structure to be scanned is
564  *                 specified.
565  * @param tag  [i] The tag node to be scanned is specified.
566  * @param pool [i] To use POOL.
567  * @return The value of the PARSE attribute is returned. NULL is returned when
568  *         not found.
569  */
570 char *
571 qs_get_parse_attr(Doc *doc, Node *tag, apr_pool_t *pool)
572 {
573   Attr *attr;
574   /*--------------------------------------------------------------------------*/
575   /* The object tag node is scanned.                                          */
576   /*--------------------------------------------------------------------------*/
577   for (attr = qs_get_attr(doc,tag);
578        attr;
579        attr = qs_get_next_attr(doc,attr)) {
580     char *name  = qs_get_attr_name(doc,attr);
581     char *value = qs_get_attr_value(doc,attr);
582     if (STRCASEEQ('p','P',"parse",name)) {
583       /*----------------------------------------------------------------------*/
584       /* The VALUE attribute was found.                                       */
585       /*----------------------------------------------------------------------*/
586       return apr_pstrdup(pool, value);
587     }
588   }
589
590   /*--------------------------------------------------------------------------*/
591   /* not found                                                                */
592   /*--------------------------------------------------------------------------*/
593   return NULL;
594 }
595
596
597 char *
598 chxj_form_action_to_hidden_tag(
599   request_rec         *r,
600   apr_pool_t          *pool,
601   const char          *str,
602   int                 xmlFlag,
603   int                 post,
604   char                **new_query_string,
605   int                 docomo,
606   int                 softbank,
607   chxjconvrule_entry  *entryp)
608 {
609   char *s = apr_pstrdup(pool, str);
610   *new_query_string = NULL;
611   int no_qsconv_flag = (((unsigned int)entryp->action & CONVRULE_QSCONV_OFF_BIT) != 0);
612   if (!s) return NULL;
613   if (chxj_starts_with(s, "http://") || chxj_starts_with(s, "https://")) {
614     apr_uri_t url;
615     apr_uri_parse(pool, s, &url);
616     if (url.hostname && strcasecmp(url.hostname, r->hostname) != 0) {
617       return NULL;
618     }
619   }
620   s = strchr(s, '?');
621   if (!s) return NULL;
622   s++;
623   char *result = NULL;
624
625   char *pstat;
626   char *pstat2;
627   for (;;) {
628     char *pair = apr_strtok(s, "&", &pstat);
629     if (! pair) break;
630     if (strncasecmp(pair, "amp;", 4) == 0) {
631       pair += 4;
632     }
633     s = NULL;
634     char *key = apr_strtok(pair, "=",  &pstat2);
635     char *val = "";
636     if (key) {
637       val = apr_strtok(NULL, "=", &pstat2);
638       if (!val) val = "";
639     }
640     char *tmp = NULL;
641     
642     if (no_qsconv_flag) {
643       if (*new_query_string) {
644         *new_query_string = apr_psprintf(pool, "%s&%s=%s", *new_query_string, chxj_jreserved_to_safe_tag(r, key, entryp), val);
645       }
646       else {
647         *new_query_string = apr_psprintf(pool, "%s=%s", chxj_jreserved_to_safe_tag(r, key, entryp), val);
648       }
649     }
650     else {
651       if (post && strcasecmp(key, "guid") == 0 && docomo) {
652         *new_query_string = apr_psprintf(pool, "%s=%s", key, val);
653       }
654       else {
655         if (! post || strcasecmp(key, "_chxj_cc") == 0 || strcasecmp(key, "_chxj_nc") == 0) {
656           if (softbank) {
657             tmp = apr_psprintf(pool, 
658                                "<input type=\"hidden\" name=\"%s\" value=\"%s\"%s>", 
659                                chxj_jreserved_to_safe_tag(r, 
660                                                           chxj_url_decode(pool, key), 
661                                                           entryp), 
662                                chxj_url_decode(pool, val), 
663                                (xmlFlag == 1) ? " /" : "");
664           }
665           else {
666             tmp = apr_psprintf(pool, 
667                                "<input type=\"hidden\" name=\"%s\" value=\"%s\"%s>", 
668                                chxj_url_decode(pool, key), 
669                                chxj_url_decode(pool, val), 
670                                (xmlFlag == 1) ? " /" : "");
671           }
672         }
673         else {
674           if (entryp->action & CONVRULE_JRCONV_OFF_BIT) {
675             if (chxj_is_jreserved_tag(key)) {
676               tmp = apr_psprintf(pool, 
677                                  "<input type=\"hidden\" name=\"%s\" value=\"%s\"%s>", 
678                                  chxj_url_decode(pool, key), 
679                                  chxj_url_decode(pool, val), 
680                                  (xmlFlag == 1) ? " /" : "");
681             }
682             else {
683               tmp = apr_psprintf(pool, 
684                                  "<input type=\"hidden\" name=\"_chxj_qs_%s\" value=\"%s\"%s>", 
685                                  chxj_url_decode(pool, key), 
686                                  chxj_url_decode(pool, val), 
687                                  (xmlFlag == 1) ? " /" : "");
688             }
689           }
690           else {
691             tmp = apr_psprintf(pool, 
692                                "<input type=\"hidden\" name=\"_chxj_qs_%s\" value=\"%s\"%s>", 
693                                chxj_url_decode(pool, key), 
694                                chxj_url_decode(pool, val), 
695                                (xmlFlag == 1) ? " /" : "");
696           }
697         }
698         if (result) {
699           result = apr_pstrcat(pool, result, tmp, NULL);
700         }
701         else {
702           result = tmp;
703         }
704       }
705     }
706   }
707   return result;
708 }
709
710
711 char *
712 chxj_delete_chxj_cc_param(
713   request_rec         *r,
714   const char          *str)
715 {
716   apr_pool_t  *pool;
717   char        *s;
718   int         xmlFlag = 0;
719
720   DBG(r,"REQ[%X] start %s()",TO_ADDR(r),__func__);
721   DBG(r,"REQ[%X] str:[%s]", TO_ADDR(r),str);
722
723   apr_pool_create(&pool, r->pool);
724   s = apr_pstrdup(pool, str);
725   if (!s) {
726     ERR(r,"REQ[%X] Memory Allocation Error", TO_ADDR(r));
727     DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
728     return NULL;
729   }
730   char *result = NULL;
731
732   char *pstat;
733   char *pstat2;
734   for (;;) {
735     char *pair = apr_strtok(s, "&", &pstat);
736     if (! pair) break;
737     if (strncasecmp(pair, "amp;", 4) == 0) {
738       pair += 4;
739       xmlFlag = 1;
740     }
741     s = NULL;
742     char *key = apr_strtok(pair, "=",  &pstat2);
743     char *val = "";
744     if (key) {
745       val = apr_strtok(NULL, "=", &pstat2);
746       if (!val) val = "";
747     }
748     if (strcasecmp(key, "_chxj_cc")) {
749       if (result) {
750         result = apr_pstrcat(pool, result, ((xmlFlag) ? "&amp;" : "&"), key, "=", val, NULL);
751       }
752       else {
753         result = apr_pstrcat(pool, key, "=", val, NULL);
754       }
755     }
756   }
757   DBG(r, "REQ[%X] result:[%s]", TO_ADDR(r), result);
758   DBG(r,"REQ[%X] end %s()",TO_ADDR(r),__func__);
759   return result;
760 }
761 /*
762  * vim:ts=2 et
763  */