OSDN Git Service

Merge branch 'branch_0.12.0' into branch_0.13.0
[modchxj/mod_chxj.git] / src / chxj_apache.c
1 /*
2  * Copyright (C) 2005-2009 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_apache.h"
18 #if defined(CHXJ_TEST)
19 #include "pcre.h"
20 #undef ap_regex_t
21 #undef ap_regmatch_t
22 #ifndef POSIX_MALLOC_THRESHOLD
23 #define POSIX_MALLOC_THRESHOLD (10)
24 #endif
25 #endif
26
27 const char *
28 chxj_apache_run_http_scheme(request_rec *r)
29 {
30 #if defined(CHXJ_TEST)
31   return test_run_http_scheme(r);
32 #else
33 #  if AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER == 2
34   return ap_run_http_scheme(r);
35 #  else
36   return ap_run_http_method(r);
37 #  endif
38 #endif
39 }
40
41 char *chxj_os_escape_path(apr_pool_t *p, const char *path, int partial) 
42 {
43 #if defined(CHXJ_TEST)
44   return test_os_escape_path(p, path, partial);
45 #else
46   return ap_os_escape_path(p, path, partial);
47 #endif
48 }
49
50
51 void
52 chxj_set_content_type(request_rec *r, const char *ct)
53 {
54 #if defined(CHXJ_TEST)
55   test_set_content_type(r, ct);
56 #else
57   ap_set_content_type(r, ct);
58 #endif
59 }
60
61
62 void *
63 chxj_get_module_config(const ap_conf_vector_t *cv, const module *m)
64 {
65 #if defined(CHXJ_TEST)
66   return test_get_module_config(cv,m);
67 #else
68   return ap_get_module_config(cv,m);
69 #endif
70 }
71
72
73 char *
74 chxj_ap_escape_html(apr_pool_t *p, const char *s) 
75 {
76 #if defined(CHXJ_TEST)
77   return test_ap_escape_html(p, s);
78 #else
79   return ap_escape_html(p, s);
80 #endif
81 }
82
83
84 int
85 chxj_ap_regcomp(ap_regex_t *preg, const char *pattern, int cflags)
86 {
87 #if defined(CHXJ_TEST)
88   const char *errorptr;
89   int erroffset;
90   int options = 0;
91   
92   if ((cflags & AP_REG_ICASE) != 0) options |= PCRE_CASELESS;
93   if ((cflags & AP_REG_NEWLINE) != 0) options |= PCRE_MULTILINE;
94   
95   preg->re_pcre = pcre_compile(pattern, options, &errorptr, &erroffset, NULL);
96   preg->re_erroffset = erroffset;
97   
98   if (preg->re_pcre == NULL) return AP_REG_INVARG;
99   
100   preg->re_nsub = pcre_info((const pcre *)preg->re_pcre, NULL, NULL);
101   return 0;
102 #else
103   return ap_regcomp(preg,pattern,cflags);
104 #endif
105 }
106
107 ap_regex_t *
108 chxj_ap_pregcomp(apr_pool_t *p, const char *pattern, int cflags)
109 {
110 #if defined(CHXJ_TEST)
111   ap_regex_t *preg = apr_palloc(p, sizeof(*preg));
112   if (chxj_ap_regcomp(preg, pattern, cflags)) {
113     return NULL;
114   }
115   return preg;
116 #else
117   return ap_pregcomp(p, pattern, cflags);
118 #endif
119 }
120 void 
121 chxj_ap_pregfree(apr_pool_t *p, ap_regex_t *reg)
122 {
123 #if defined(CHXJ_TEST)
124 #else
125   return ap_pregfree(p, reg);
126 #endif
127 }
128
129 int
130 chxj_ap_regexec(const ap_regex_t *preg, const char *string, apr_size_t nmatch, ap_regmatch_t *pmatch, int eflags)
131 {
132 #if defined(CHXJ_TEST)
133   /* copy from apache2.2.8 server/util_pcre.c */
134   int rc;
135   int options = 0;
136   int *ovector = NULL;
137   int small_ovector[POSIX_MALLOC_THRESHOLD * 3];
138   int allocated_ovector = 0;
139
140   if ((eflags & AP_REG_NOTBOL) != 0) options |= PCRE_NOTBOL;
141   if ((eflags & AP_REG_NOTEOL) != 0) options |= PCRE_NOTEOL;
142
143   ((ap_regex_t *)preg)->re_erroffset = (apr_size_t)(-1);  /* Only has meaning after compile */
144
145   if (nmatch > 0) {
146     if (nmatch <= POSIX_MALLOC_THRESHOLD) {
147       ovector = &(small_ovector[0]);
148     }
149     else {
150       ovector = (int *)malloc(sizeof(int) * nmatch * 3);
151       if (ovector == NULL) return AP_REG_ESPACE;
152       allocated_ovector = 1;
153     }
154   }
155
156   rc = pcre_exec((const pcre *)preg->re_pcre, NULL, string, (int)strlen(string), 0, options, ovector, nmatch * 3);
157   if (rc == 0) rc = nmatch;    /* All captured slots were filled in */
158   if (rc >= 0) {
159     apr_size_t i;
160     for (i = 0; i < (apr_size_t)rc; i++) {
161       pmatch[i].rm_so = ovector[i*2];
162       pmatch[i].rm_eo = ovector[i*2+1];
163     }
164     if (allocated_ovector) free(ovector);
165     for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1;
166     return 0;
167   } 
168   else {
169     if (allocated_ovector) free(ovector);
170     switch(rc) {
171     case PCRE_ERROR_NOMATCH: return AP_REG_NOMATCH;
172     case PCRE_ERROR_NULL: return AP_REG_INVARG;
173     case PCRE_ERROR_BADOPTION: return AP_REG_INVARG;
174     case PCRE_ERROR_BADMAGIC: return AP_REG_INVARG;
175     case PCRE_ERROR_UNKNOWN_NODE: return AP_REG_ASSERT;
176     case PCRE_ERROR_NOMEMORY: return AP_REG_ESPACE;
177 #ifdef PCRE_ERROR_MATCHLIMIT
178     case PCRE_ERROR_MATCHLIMIT: return AP_REG_ESPACE;
179 #endif
180 #ifdef PCRE_ERROR_BADUTF8
181     case PCRE_ERROR_BADUTF8: return AP_REG_INVARG;
182 #endif
183 #ifdef PCRE_ERROR_BADUTF8_OFFSET
184     case PCRE_ERROR_BADUTF8_OFFSET: return AP_REG_INVARG;
185 #endif
186     default: return AP_REG_ASSERT;
187     }
188   }
189 #else
190   return ap_regexec(preg, string, nmatch, pmatch, eflags);
191 #endif
192 }
193
194 char *
195 chxj_ap_pregsub(apr_pool_t *p, const char *input, const char *source, size_t nmatch, ap_regmatch_t pmatch[])
196 {
197 #if defined(CHXJ_TEST)
198   /* copy from apache2.2.8 server/util.c */
199   const char *src = input;
200   char *dest, *dst;
201   char c;
202   size_t no;
203   int len;
204
205   if (!source) return NULL;
206   if (!nmatch) return apr_pstrdup(p, src);
207
208   len = 0;
209   while ((c = *src++) != '\0') {
210     if (c == '&') no = 0;
211     else if (c == '$' && apr_isdigit(*src))
212       no = *src++ - '0';
213     else
214       no = 10;
215
216     if (no > 9) {                /* Ordinary character. */
217       if (c == '\\' && (*src == '$' || *src == '&'))
218         c = *src++;
219       len++;
220     }
221     else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
222       len += pmatch[no].rm_eo - pmatch[no].rm_so;
223     }
224   }
225   dest = dst = apr_pcalloc(p, len + 1);
226   /* Now actually fill in the string */
227   src = input;
228   while ((c = *src++) != '\0') {
229     if (c == '&')
230       no = 0;
231     else if (c == '$' && apr_isdigit(*src))
232       no = *src++ - '0';
233     else
234       no = 10;
235
236     if (no > 9) {                /* Ordinary character. */
237       if (c == '\\' && (*src == '$' || *src == '&'))
238          c = *src++;
239       *dst++ = c;
240     }
241     else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
242       len = pmatch[no].rm_eo - pmatch[no].rm_so;
243       memcpy(dst, source + pmatch[no].rm_so, len);
244       dst += len;
245     }
246   }
247   *dst = '\0';
248
249   return dest;
250 #else
251   return ap_pregsub(p, input, source, nmatch, pmatch);
252 #endif
253 }
254 /*
255  * vim:ts=2 et
256  */