This source file includes following definitions.
- zend_accel_blacklist_init
- blacklist_report_regexp_error
- zend_accel_blacklist_update_regexp
- zend_accel_blacklist_shutdown
- zend_accel_blacklist_allocate
- zend_accel_blacklist_loadone
- zend_accel_blacklist_load
- zend_accel_blacklist_is_blacklisted
- zend_accel_blacklist_apply
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include "main/php.h"
23 #include "main/fopen_wrappers.h"
24 #include "ZendAccelerator.h"
25 #include "zend_accelerator_blacklist.h"
26
27 #ifdef ZEND_WIN32
28 # define REGEX_MODE (REG_EXTENDED|REG_NOSUB|REG_ICASE)
29 #else
30 # define REGEX_MODE (REG_EXTENDED|REG_NOSUB)
31 #endif
32
33 #ifdef HAVE_GLOB
34 #ifdef PHP_WIN32
35 #include "win32/glob.h"
36 #else
37 #include <glob.h>
38 #endif
39 #endif
40
41 #include "ext/pcre/php_pcre.h"
42
43 #define ZEND_BLACKLIST_BLOCK_SIZE 32
44
45 struct _zend_regexp_list {
46 pcre *re;
47 zend_regexp_list *next;
48 };
49
50 zend_blacklist accel_blacklist;
51
52 void zend_accel_blacklist_init(zend_blacklist *blacklist)
53 {
54 blacklist->pos = 0;
55 blacklist->size = ZEND_BLACKLIST_BLOCK_SIZE;
56
57 if (blacklist->entries != NULL) {
58 zend_accel_blacklist_shutdown(blacklist);
59 }
60
61 blacklist->entries = (zend_blacklist_entry *) calloc(sizeof(zend_blacklist_entry), blacklist->size);
62 if (!blacklist->entries) {
63 zend_accel_error(ACCEL_LOG_FATAL, "Blacklist initialization: no memory\n");
64 return;
65 }
66 blacklist->regexp_list = NULL;
67 }
68
69 static void blacklist_report_regexp_error(const char *pcre_error, int pcre_error_offset)
70 {
71 zend_accel_error(ACCEL_LOG_ERROR, "Blacklist compilation failed (offset: %d), %s\n", pcre_error_offset, pcre_error);
72 }
73
74 static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
75 {
76 const char *pcre_error;
77 int i, pcre_error_offset;
78 zend_regexp_list **regexp_list_it, *it;
79 char regexp[12*1024], *p, *end, *c, *backtrack = NULL;
80
81 if (blacklist->pos == 0) {
82
83 return;
84 }
85
86 regexp_list_it = &(blacklist->regexp_list);
87
88 regexp[0] = '^';
89 regexp[1] = '(';
90 p = regexp + 2;
91 end = regexp + sizeof(regexp) - sizeof("[^\\\\]*)\0");
92
93 for (i = 0; i < blacklist->pos; ) {
94 c = blacklist->entries[i].path;
95 if (p + blacklist->entries[i].path_length < end) {
96 while (*c && p < end) {
97 switch (*c) {
98 case '?':
99 c++;
100 #ifdef ZEND_WIN32
101 p[0] = '[';
102 p[1] = '^';
103 p[2] = '\\';
104 p[3] = '\\';
105 p[4] = ']';
106 p += 5;
107 #else
108 p[0] = '[';
109 p[1] = '^';
110 p[2] = '/';
111 p[3] = ']';
112 p += 4;
113 #endif
114 break;
115 case '*':
116 c++;
117 if (*c == '*') {
118 c++;
119 p[0] = '.';
120 p[1] = '*';
121 p += 2;
122 } else {
123 #ifdef ZEND_WIN32
124 p[0] = '[';
125 p[1] = '^';
126 p[2] = '\\';
127 p[3] = '\\';
128 p[4] = ']';
129 p[5] = '*';
130 p += 6;
131 #else
132 p[0] = '[';
133 p[1] = '^';
134 p[2] = '/';
135 p[3] = ']';
136 p[4] = '*';
137 p += 5;
138 #endif
139 }
140 break;
141 case '^':
142 case '.':
143 case '[':
144 case ']':
145 case '$':
146 case '(':
147 case ')':
148 case '|':
149 case '+':
150 case '{':
151 case '}':
152 case '\\':
153 *p++ = '\\';
154
155 default:
156 *p++ = *c++;
157 }
158 }
159 }
160
161 if (*c || i == blacklist->pos - 1) {
162 if (*c) {
163 if (!backtrack) {
164 zend_accel_error(ACCEL_LOG_ERROR, "Too long blacklist entry\n");
165 }
166 p = backtrack;
167 } else {
168 i++;
169 }
170 *p++ = ')';
171 *p++ = '\0';
172
173 it = (zend_regexp_list*)malloc(sizeof(zend_regexp_list));
174 if (!it) {
175 zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
176 return;
177 }
178 it->next = NULL;
179
180 if ((it->re = pcre_compile(regexp, PCRE_NO_AUTO_CAPTURE, &pcre_error, &pcre_error_offset, 0)) == NULL) {
181 blacklist_report_regexp_error(pcre_error, pcre_error_offset);
182 }
183
184 p = regexp + 2;
185 *regexp_list_it = it;
186 regexp_list_it = &it->next;
187 } else {
188 backtrack = p;
189 *p++ = '|';
190 i++;
191 }
192 }
193 }
194
195 void zend_accel_blacklist_shutdown(zend_blacklist *blacklist)
196 {
197 zend_blacklist_entry *p = blacklist->entries, *end = blacklist->entries + blacklist->pos;
198
199 while (p<end) {
200 free(p->path);
201 p++;
202 }
203 free(blacklist->entries);
204 blacklist->entries = NULL;
205 if (blacklist->regexp_list) {
206 zend_regexp_list *temp, *it = blacklist->regexp_list;
207 while (it) {
208 pcre_free(it->re);
209 temp = it;
210 it = it->next;
211 free(temp);
212 }
213 }
214 }
215
216 static inline void zend_accel_blacklist_allocate(zend_blacklist *blacklist)
217 {
218 if (blacklist->pos == blacklist->size) {
219 blacklist->size += ZEND_BLACKLIST_BLOCK_SIZE;
220 blacklist->entries = (zend_blacklist_entry *) realloc(blacklist->entries, sizeof(zend_blacklist_entry)*blacklist->size);
221 }
222 }
223
224 #ifdef HAVE_GLOB
225 static void zend_accel_blacklist_loadone(zend_blacklist *blacklist, char *filename)
226 #else
227 void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
228 #endif
229 {
230 char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1], *blacklist_path = NULL;
231 FILE *fp;
232 int path_length, blacklist_path_length;
233
234 if ((fp = fopen(filename, "r")) == NULL) {
235 zend_accel_error(ACCEL_LOG_WARNING, "Cannot load blacklist file: %s\n", filename);
236 return;
237 }
238
239 zend_accel_error(ACCEL_LOG_DEBUG,"Loading blacklist file: '%s'", filename);
240
241 if (VCWD_REALPATH(filename, buf)) {
242 blacklist_path_length = zend_dirname(buf, strlen(buf));
243 blacklist_path = zend_strndup(buf, blacklist_path_length);
244 }
245
246 memset(buf, 0, sizeof(buf));
247 memset(real_path, 0, sizeof(real_path));
248
249 while (fgets(buf, MAXPATHLEN, fp) != NULL) {
250 char *path_dup, *pbuf;
251 path_length = strlen(buf);
252 if (path_length > 0 && buf[path_length - 1] == '\n') {
253 buf[--path_length] = 0;
254 if (path_length > 0 && buf[path_length - 1] == '\r') {
255 buf[--path_length] = 0;
256 }
257 }
258
259
260 pbuf = &buf[0];
261 while (*pbuf == '\r') {
262 *pbuf++ = 0;
263 path_length--;
264 }
265
266
267 if (pbuf[0] == '\"' && pbuf[path_length - 1]== '\"') {
268 *pbuf++ = 0;
269 path_length -= 2;
270 }
271
272 if (path_length == 0) {
273 continue;
274 }
275
276
277 if (pbuf[0]==';') {
278 continue;
279 }
280
281 path_dup = zend_strndup(pbuf, path_length);
282 if (blacklist_path) {
283 expand_filepath_ex(path_dup, real_path, blacklist_path, blacklist_path_length);
284 } else {
285 expand_filepath(path_dup, real_path);
286 }
287 path_length = strlen(real_path);
288
289 free(path_dup);
290
291 zend_accel_blacklist_allocate(blacklist);
292 blacklist->entries[blacklist->pos].path_length = path_length;
293 blacklist->entries[blacklist->pos].path = (char *)malloc(path_length + 1);
294 if (!blacklist->entries[blacklist->pos].path) {
295 zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
296 fclose(fp);
297 return;
298 }
299 blacklist->entries[blacklist->pos].id = blacklist->pos;
300 memcpy(blacklist->entries[blacklist->pos].path, real_path, path_length + 1);
301 blacklist->pos++;
302 }
303 fclose(fp);
304 if (blacklist_path) {
305 free(blacklist_path);
306 }
307 zend_accel_blacklist_update_regexp(blacklist);
308 }
309
310 #ifdef HAVE_GLOB
311 void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
312 {
313 glob_t globbuf;
314 int ret;
315 unsigned int i;
316
317 memset(&globbuf, 0, sizeof(glob_t));
318
319 ret = glob(filename, 0, NULL, &globbuf);
320 #ifdef GLOB_NOMATCH
321 if (ret == GLOB_NOMATCH || !globbuf.gl_pathc) {
322 #else
323 if (!globbuf.gl_pathc) {
324 #endif
325 zend_accel_error(ACCEL_LOG_WARNING, "No blacklist file found matching: %s\n", filename);
326 } else {
327 for(i=0 ; i<globbuf.gl_pathc; i++) {
328 zend_accel_blacklist_loadone(blacklist, globbuf.gl_pathv[i]);
329 }
330 globfree(&globbuf);
331 }
332 }
333 #endif
334
335 zend_bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *verify_path)
336 {
337 int ret = 0;
338 zend_regexp_list *regexp_list_it = blacklist->regexp_list;
339
340 if (regexp_list_it == NULL) {
341 return 0;
342 }
343 while (regexp_list_it != NULL) {
344 if (pcre_exec(regexp_list_it->re, NULL, verify_path, strlen(verify_path), 0, 0, NULL, 0) >= 0) {
345 ret = 1;
346 break;
347 }
348 regexp_list_it = regexp_list_it->next;
349 }
350 return ret;
351 }
352
353 void zend_accel_blacklist_apply(zend_blacklist *blacklist, blacklist_apply_func_arg_t func, void *argument)
354 {
355 int i;
356
357 for (i = 0; i < blacklist->pos; i++) {
358 func(&blacklist->entries[i], argument);
359 }
360 }