1 /**
2 * Copyright 2006 Christian Liesch
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /**
18 * @file
19 *
20 * @Author christian liesch <liesch@gmx.ch>
21 *
22 * Implementation of the HTTP Test Tool htt_regex.
23 */
24
25 /************************************************************************
26 * Includes
27 ***********************************************************************/
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include <apr.h>
33 #include <apr_strings.h>
34
35 #include "defines.h"
36 #include "regex.h"
37
38
39 /************************************************************************
40 * Definitions
41 ***********************************************************************/
42
43 struct htt_regex_s {
44 const char *pattern;
45 int match;
46 void *re_pcre;
47 apr_size_t re_nsub;
48 apr_size_t re_erroffset;
49 };
50
51 #ifndef POSIX_MALLOC_THRESHOLD
52 #define POSIX_MALLOC_THRESHOLD (10)
53 #endif
54
55
56 /************************************************************************
57 * Forward declaration
58 ***********************************************************************/
59
60 static apr_status_t htt_regex_cleanup(void *preg);
61
62
63 /************************************************************************
64 * Implementation
65 ***********************************************************************/
66
67 /**
68 * Compile a pattern to a regular expression
69 *
70 * @param p IN pool
71 * @param pattern IN pattern to compile
72 * @param error IN error string
73 * @param erroff IN offset into pattern wherer compilation fails
74 *
75 * @return regular express on success else NULL
76 */
htt_regexcomp(apr_pool_t * p,const char * pattern,const char ** error,int * erroff)77 htt_regex_t *htt_regexcomp(apr_pool_t * p, const char *pattern,
78 const char **error, int *erroff) {
79 htt_regex_t *preg = apr_palloc(p, sizeof *preg);
80
81 preg->match = 0;
82 preg->pattern = apr_pstrdup(p, pattern);
83
84 preg->re_pcre = pcre_compile(pattern, 0, error, erroff, NULL);
85 preg->re_erroffset = *erroff;
86
87 if (preg->re_pcre == NULL) {
88 return NULL;
89 }
90
91 pcre_fullinfo((const pcre *)preg->re_pcre, NULL, PCRE_INFO_CAPTURECOUNT, &(preg->re_nsub));
92
93 apr_pool_cleanup_register(p, (void *) preg, htt_regex_cleanup,
94 apr_pool_cleanup_null);
95
96 return preg;
97 }
98
99 /**
100 * Execute a string on a compiled regular expression
101 *
102 * @param preg IN regular expression
103 * @param data IN data to parse
104 * @param len IN data length
105 * @param nmatch IN number of matches
106 * @param pmatch IN offest of matched substrings
107 * @param eflags IN extended flags see pcre.h
108 *
109 * @return 0 on success
110 */
htt_regexec(htt_regex_t * preg,const char * data,apr_size_t len,apr_size_t nmatch,regmatch_t pmatch[],int eflags)111 int htt_regexec(htt_regex_t * preg, const char *data, apr_size_t len,
112 apr_size_t nmatch, regmatch_t pmatch[], int eflags) {
113 int rc;
114 int options = 0;
115 int *ovector = NULL;
116 int small_ovector[POSIX_MALLOC_THRESHOLD * 3];
117 int allocated_ovector = 0;
118
119 ((htt_regex_t *) preg)->re_erroffset = (apr_size_t) (-1); /* Only has meaning after compile */
120
121 if (nmatch > 0) {
122 if (nmatch <= POSIX_MALLOC_THRESHOLD) {
123 ovector = &(small_ovector[0]);
124 }
125 else {
126 ovector = (int *) malloc(sizeof(int) * nmatch * 3);
127 allocated_ovector = 1;
128 }
129 }
130
131 rc = pcre_exec((const pcre *) preg->re_pcre, NULL, data,
132 len, 0, options, ovector, nmatch * 3);
133
134 if (rc == 0) {
135 rc = nmatch; /* All captured slots were filled in */
136 }
137
138 if (rc >= 0) {
139 apr_size_t i;
140 for (i = 0; i < (apr_size_t) rc; i++) {
141 pmatch[i].rm_so = ovector[i * 2];
142 pmatch[i].rm_eo = ovector[i * 2 + 1];
143 }
144 if (allocated_ovector) {
145 free(ovector);
146 }
147 for (; i < nmatch; i++)
148 pmatch[i].rm_so = pmatch[i].rm_eo = -1;
149 ++preg->match;
150 return 0;
151 }
152 else {
153 if (allocated_ovector) {
154 free(ovector);
155 }
156 return rc;
157 }
158 }
159
160 /**
161 * returns number of matches on this regular expression
162 *
163 * @param preg IN regular expression
164 *
165 * @return number of matches
166 */
htt_regexhits(htt_regex_t * preg)167 int htt_regexhits(htt_regex_t * preg) {
168 return preg->match;
169 }
170
171 /**
172 * return pattern of compiled htt_regex
173 * @param preg IN regular expression
174 * @return pattern
175 */
htt_regexpattern(htt_regex_t * reg)176 const char *htt_regexpattern(htt_regex_t *reg) {
177 return reg->pattern;
178 }
179
180 /**
181 * Clean up function for pool cleanup
182 *
183 * @preg IN compiled regular expression
184 *
185 * @return APR_SUCCESS
186 */
htt_regex_cleanup(void * preg)187 static apr_status_t htt_regex_cleanup(void *preg) {
188 pcre_free(((htt_regex_t *) preg)->re_pcre);
189 return APR_SUCCESS;
190 }
191
192