2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
16 | George Schlossnagle <george@omniti.com> |
17 | Rasmus Lerdorf <rasmus@php.net> |
18 | Arun C. Murthy <arunc@yahoo-inc.com> |
19 | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
20 +----------------------------------------------------------------------+
22 This software was contributed to PHP by Community Connect Inc. in 2002
23 and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
24 Future revisions and derivatives of this source code must acknowledge
25 Community Connect Inc. as the original contributor of this module by
26 leaving this note intact in the source code.
28 All other licensing and usage conditions are those of the PHP Group.
32 /* $Id: apc.c,v 3.18.2.1 2008/03/25 18:04:53 gopalv Exp $ */
35 #include <regex.h> /* for POSIX regular expressions */
38 #define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
40 /* {{{ memory allocation wrappers */
42 void* apc_emalloc(size_t n)
46 apc_eprint("apc_emalloc: malloc failed to allocate %u bytes:", n);
51 void* apc_erealloc(void* p, size_t n)
55 apc_eprint("apc_erealloc: realloc failed to allocate %u bytes:", n);
60 void apc_efree(void* p)
63 apc_eprint("apc_efree: attempt to free null pointer");
68 char* apc_estrdup(const char* s)
77 dup = (char*) malloc(len+1);
79 apc_eprint("apc_estrdup: malloc failed to allocate %u bytes:", len+1);
86 void* apc_xstrdup(const char* s, apc_malloc_t f)
88 return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f) : NULL;
91 void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f)
95 if (p != NULL && (q = f(n)) != NULL) {
104 /* {{{ console display functions */
106 static void my_log(int level, const char* fmt, va_list args)
108 static const char* level_strings[] = {
114 static const int num_levels = NELEMS(level_strings);
117 char* buf; /* for ctime */
123 else if (level >= num_levels)
124 level = num_levels-1;
127 buf = ctime(&now); /* TODO: replace with reentrant impl */
130 fprintf(stderr, "[%s] [%s] ", buf, level_strings[level]);
131 vfprintf(stderr, fmt, args);
133 if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
134 fprintf(stderr, " %s", strerror(errno));
136 fprintf(stderr, "\n");
138 if (level == APC_ERROR) {
143 void apc_log(int level, const char* fmt, ...)
147 my_log(level, fmt, args);
151 void apc_eprint(const char* fmt, ...)
155 my_log(APC_ERROR, fmt, args);
159 void apc_wprint(const char* fmt, ...)
163 my_log(APC_WARNING, fmt, args);
167 void apc_nprint(const char* fmt, ...)
171 my_log(APC_NOTICE, fmt, args);
175 void apc_dprint(const char* fmt, ...)
180 my_log(APC_DBG, fmt, args);
187 /* {{{ string and text manipulation */
189 char* apc_append(const char* s, const char* t)
198 p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char));
200 memcpy(p + slen, t, tlen + 1);
205 char* apc_substr(const char* s, int start, int length)
208 int src_len = strlen(s);
210 /* bring start into range */
214 else if (start >= src_len) {
218 /* bring length into range */
219 if (length < 0 || src_len - start < length) {
220 length = src_len - start;
223 /* create the substring */
224 substr = apc_xmemcpy(s + start, length + 1, apc_emalloc);
225 substr[length] = '\0';
229 char** apc_tokenize(const char* s, char delim)
231 char** tokens; /* array of tokens, NULL terminated */
232 int size; /* size of tokens array */
233 int n; /* index of next token in tokens array */
234 int cur; /* current position in input string */
235 int end; /* final legal position in input string */
236 int next; /* position of next delimiter in input */
247 tokens = (char**) apc_emalloc(size * sizeof(char*));
251 /* search for the next delimiter */
252 char* p = strchr(s + cur, delim);
253 next = p ? p-s : end+1;
255 /* resize token array if necessary */
258 tokens = (char**) apc_erealloc(tokens, size * sizeof(char*));
261 /* save the current token */
262 tokens[n] = apc_substr(s, cur, next-cur);
273 /* similar to php_stream_stat_path */
275 #define APC_URL_STAT(wrapper, filename, pstatbuf) \
276 ((wrapper)->wops->url_stat((wrapper), (filename), 0, (pstatbuf), NULL TSRMLS_CC))
278 #define APC_URL_STAT(wrapper, filename, pstatbuf) \
279 ((wrapper)->wops->url_stat((wrapper), (filename), (pstatbuf) TSRMLS_CC))
282 int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo)
286 int exec_fname_length;
289 php_stream_wrapper *wrapper = NULL;
290 char *path_for_open = NULL;
294 assert(filename && fileinfo);
297 wrapper = php_stream_locate_url_wrapper(filename, &path_for_open, 0 TSRMLS_CC);
299 if(!wrapper || !wrapper->wops || !wrapper->wops->url_stat) {
304 if(wrapper != &php_plain_files_wrapper) {
305 if(APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) {
306 strncpy(fileinfo->fullpath, path_for_open, MAXPATHLEN);
309 return -1; /* cannot stat */
313 if (IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) &&
314 APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) {
315 strncpy(fileinfo->fullpath, path_for_open, MAXPATHLEN);
319 paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR);
323 /* for each directory in paths, look for filename inside */
324 for (i = 0; paths[i]; i++) {
325 snprintf(fileinfo->fullpath, sizeof(fileinfo->fullpath), "%s%c%s", paths[i], DEFAULT_SLASH, path_for_open);
326 if (APC_URL_STAT(wrapper, fileinfo->fullpath, &fileinfo->st_buf) == 0) {
332 /* check in path of the calling scripts' current working directory */
333 /* modified from main/streams/plain_wrapper.c */
334 if(!found && zend_is_executing(TSRMLS_C)) {
335 exec_fname = zend_get_executed_filename(TSRMLS_C);
336 exec_fname_length = strlen(exec_fname);
337 while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
338 if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
339 /* not: [no active file] or no path */
340 memcpy(fileinfo->fullpath, exec_fname, exec_fname_length);
341 fileinfo->fullpath[exec_fname_length] = DEFAULT_SLASH;
342 strlcpy(fileinfo->fullpath +exec_fname_length +1, path_for_open,sizeof(fileinfo->fullpath)-exec_fname_length-1);
343 /* apc_wprint("filename: %s, exec_fname: %s, fileinfo->fullpath: %s", path_for_open, exec_fname, fileinfo->fullpath); */
344 if (APC_URL_STAT(wrapper, fileinfo->fullpath, &fileinfo->st_buf) == 0) {
350 /* free the value returned by apc_tokenize */
351 for (i = 0; paths[i]; i++) {
356 return found ? 0 : -1;
361 /* {{{ regular expression wrapper functions */
368 void* apc_regex_compile_array(char* patterns[])
377 /* count the number of patterns in patterns */
378 for (npat = 0; patterns[npat] != NULL; npat++) {}
383 /* allocate the array of compiled expressions */
384 regs = (apc_regex**) apc_emalloc(sizeof(apc_regex*) * (npat + 1));
385 for (i = 0; i <= npat; i++) {
386 regs[i] = (apc_regex *) apc_emalloc(sizeof(apc_regex));
388 regs[i]->type = APC_NEGATIVE_MATCH;
391 /* compile the expressions */
392 for (i = 0; i < npat; i++) {
393 char *pattern = patterns[i];
394 if(pattern[0]=='+') { regs[i]->type = APC_POSITIVE_MATCH; pattern = patterns[i]+sizeof(char); }
395 else if(pattern[0]=='-') { regs[i]->type = APC_NEGATIVE_MATCH; pattern = patterns[i]+sizeof(char); }
397 regs[i]->reg = (regex_t*) apc_emalloc(sizeof(regex_t));
399 if (regcomp(regs[i]->reg, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
400 apc_wprint("apc_regex_compile_array: invalid expression '%s'",
403 apc_regex_destroy_array(regs);
412 void apc_regex_destroy_array(void* p)
415 apc_regex** regs = (apc_regex**) p;
418 for (i = 0; regs[i]->reg != NULL; i++) {
419 regfree(regs[i]->reg);
420 apc_efree(regs[i]->reg);
427 int apc_regex_match_array(void* p, const char* input)
435 regs = (apc_regex**) p;
436 for (i = 0; regs[i]->reg != NULL; i++)
437 if (regexec(regs[i]->reg, input, 0, NULL, 0) == 0)
438 return (int)(regs[i]->type);
445 /* {{{ crc32 implementation */
447 /* this table was generated by crc32gen() */
448 static unsigned int crc32tab[] = {
449 /* 0 */ 0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd,
450 /* 4 */ 0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1,
451 /* 8 */ 0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4,
452 /* 12 */ 0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8,
453 /* 16 */ 0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef,
454 /* 20 */ 0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3,
455 /* 24 */ 0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6,
456 /* 28 */ 0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da,
457 /* 32 */ 0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9,
458 /* 36 */ 0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995,
459 /* 40 */ 0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0,
460 /* 44 */ 0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c,
461 /* 48 */ 0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b,
462 /* 52 */ 0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7,
463 /* 56 */ 0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492,
464 /* 60 */ 0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be,
465 /* 64 */ 0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815,
466 /* 68 */ 0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939,
467 /* 72 */ 0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c,
468 /* 76 */ 0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20,
469 /* 80 */ 0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027,
470 /* 84 */ 0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b,
471 /* 88 */ 0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e,
472 /* 92 */ 0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512,
473 /* 96 */ 0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871,
474 /* 100 */ 0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d,
475 /* 104 */ 0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68,
476 /* 108 */ 0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44,
477 /* 112 */ 0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043,
478 /* 116 */ 0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f,
479 /* 120 */ 0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a,
480 /* 124 */ 0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576,
481 /* 128 */ 0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d,
482 /* 132 */ 0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861,
483 /* 136 */ 0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54,
484 /* 140 */ 0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78,
485 /* 144 */ 0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f,
486 /* 148 */ 0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053,
487 /* 152 */ 0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566,
488 /* 156 */ 0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a,
489 /* 160 */ 0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929,
490 /* 164 */ 0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805,
491 /* 168 */ 0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30,
492 /* 172 */ 0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c,
493 /* 176 */ 0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b,
494 /* 180 */ 0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037,
495 /* 184 */ 0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502,
496 /* 188 */ 0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e,
497 /* 192 */ 0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985,
498 /* 196 */ 0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9,
499 /* 200 */ 0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c,
500 /* 204 */ 0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0,
501 /* 208 */ 0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7,
502 /* 212 */ 0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b,
503 /* 216 */ 0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae,
504 /* 220 */ 0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482,
505 /* 224 */ 0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1,
506 /* 228 */ 0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd,
507 /* 232 */ 0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8,
508 /* 236 */ 0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4,
509 /* 240 */ 0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3,
510 /* 244 */ 0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff,
511 /* 248 */ 0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca,
512 /* 252 */ 0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6,
515 unsigned int apc_crc32(const char* buf, int len)
521 /* preconditioning */
524 for (i = 0; i < len; i++) {
525 k = (crc ^ buf[i]) & 0x000000FF;
526 crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
529 /* postconditioning */
533 /* crc32gen: generate the nth (0..255) crc32 table value */
535 static unsigned long crc32gen(int n)
541 for (i = 8; i >= 0; i--) {
543 crc = (crc >> 1) ^ 0xEDB88320;
560 * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
561 * vim<600: expandtab sw=4 ts=4 sts=4