Apache HTTPD
util.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. 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 * util.c: string utility things
19 *
20 * 3/21/93 Rob McCool
21 * 1995-96 Many changes by the Apache Software Foundation
22 *
23 */
24
25/* Debugging aid:
26 * #define DEBUG to trace all cfg_open*()/cfg_closefile() calls
27 * #define DEBUG_CFG_LINES to trace every line read from the config files
28 */
29
30#include "apr.h"
31#include "apr_strings.h"
32#include "apr_lib.h"
33
34#define APR_WANT_STDIO
35#define APR_WANT_STRFUNC
36#include "apr_want.h"
37
38#if APR_HAVE_UNISTD_H
39#include <unistd.h>
40#endif
41#if APR_HAVE_PROCESS_H
42#include <process.h> /* for getpid() on Win32 */
43#endif
44#if APR_HAVE_NETDB_H
45#include <netdb.h> /* for gethostbyname() */
46#endif
47
48#include "ap_config.h"
49#include "apr_base64.h"
50#include "apr_fnmatch.h"
51#include "httpd.h"
52#include "http_main.h"
53#include "http_log.h"
54#include "http_protocol.h"
55#include "http_config.h"
56#include "http_core.h"
57#include "util_ebcdic.h"
58#include "util_varbuf.h"
59
60#ifdef HAVE_PWD_H
61#include <pwd.h>
62#endif
63#ifdef HAVE_GRP_H
64#include <grp.h>
65#endif
66#ifdef HAVE_SYS_LOADAVG_H
67#include <sys/loadavg.h>
68#endif
69
70#include "ap_mpm.h"
71
72/* A bunch of functions in util.c scan strings looking for certain characters.
73 * To make that more efficient we encode a lookup table. The test_char_table
74 * is generated automatically by gen_test_char.c.
75 */
76#include "test_char.h"
77
78/* we know core's module_index is 0 */
79#undef APLOG_MODULE_INDEX
80#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
81
82/* maximum nesting level for config directories */
83#ifndef AP_MAX_FNMATCH_DIR_DEPTH
84#define AP_MAX_FNMATCH_DIR_DEPTH (128)
85#endif
86
87/*
88 * Examine a field value (such as a media-/content-type) string and return
89 * it sans any parameters; e.g., strip off any ';charset=foo' and the like.
90 */
91AP_DECLARE(char *) ap_field_noparam(apr_pool_t *p, const char *intype)
92{
93 const char *semi;
94
95 if (intype == NULL) return NULL;
96
97 semi = ap_strchr_c(intype, ';');
98 if (semi == NULL) {
99 return apr_pstrdup(p, intype);
100 }
101 else {
102 while ((semi > intype) && apr_isspace(semi[-1])) {
103 semi--;
104 }
105 return apr_pstrmemdup(p, intype, semi - intype);
106 }
107}
108
110 int gmt)
111{
113 char ts[MAX_STRING_LEN];
114 char tf[MAX_STRING_LEN];
116
117 if (gmt) {
118 const char *f;
119 char *strp;
120
121 apr_time_exp_gmt(&xt, t);
122 /* Convert %Z to "GMT" and %z to "+0000";
123 * on hosts that do not have a time zone string in struct tm,
124 * strftime must assume its argument is local time.
125 */
126 for(strp = tf, f = fmt; strp < tf + sizeof(tf) - 6 && (*strp = *f)
127 ; f++, strp++) {
128 if (*f != '%') continue;
129 switch (f[1]) {
130 case '%':
131 *++strp = *++f;
132 break;
133 case 'Z':
134 *strp++ = 'G';
135 *strp++ = 'M';
136 *strp = 'T';
137 f++;
138 break;
139 case 'z': /* common extension */
140 *strp++ = '+';
141 *strp++ = '0';
142 *strp++ = '0';
143 *strp++ = '0';
144 *strp = '0';
145 f++;
146 break;
147 }
148 }
149 *strp = '\0';
150 fmt = tf;
151 }
152 else {
153 apr_time_exp_lt(&xt, t);
154 }
155
156 /* check return code? */
158 ts[MAX_STRING_LEN - 1] = '\0';
159 return apr_pstrdup(p, ts);
160}
161
162/* Roy owes Rob beer. */
163/* Rob owes Roy dinner. */
164
165/* These legacy comments would make a lot more sense if Roy hadn't
166 * replaced the old later_than() routine with util_date.c.
167 *
168 * Well, okay, they still wouldn't make any sense.
169 */
170
171/* Match = 0, NoMatch = 1, Abort = -1
172 * Based loosely on sections of wildmat.c by Rich Salz
173 * Hmmm... shouldn't this really go component by component?
174 */
175AP_DECLARE(int) ap_strcmp_match(const char *str, const char *expected)
176{
177 apr_size_t x, y;
178
179 for (x = 0, y = 0; expected[y]; ++y, ++x) {
180 if (expected[y] == '*') {
181 while (expected[++y] == '*');
182 if (!expected[y])
183 return 0;
184 while (str[x]) {
185 int ret;
186 if ((ret = ap_strcmp_match(&str[x++], &expected[y])) != 1)
187 return ret;
188 }
189 return -1;
190 }
191 else if (!str[x])
192 return -1;
193 else if ((expected[y] != '?') && (str[x] != expected[y]))
194 return 1;
195 }
196 return (str[x] != '\0');
197}
198
199AP_DECLARE(int) ap_strcasecmp_match(const char *str, const char *expected)
200{
201 apr_size_t x, y;
202
203 for (x = 0, y = 0; expected[y]; ++y, ++x) {
204 if (!str[x] && expected[y] != '*')
205 return -1;
206 if (expected[y] == '*') {
207 while (expected[++y] == '*');
208 if (!expected[y])
209 return 0;
210 while (str[x]) {
211 int ret;
212 if ((ret = ap_strcasecmp_match(&str[x++], &expected[y])) != 1)
213 return ret;
214 }
215 return -1;
216 }
217 else if (expected[y] != '?'
218 && apr_tolower(str[x]) != apr_tolower(expected[y]))
219 return 1;
220 }
221 return (str[x] != '\0');
222}
223
224/* We actually compare the canonical root to this root, (but we don't
225 * waste time checking the case), since every use of this function in
226 * httpd-2.1 tests if the path is 'proper', meaning we've already passed
227 * it through apr_filepath_merge, or we haven't.
228 */
230{
231 const char *newpath;
232 const char *ourdir = dir;
234 || strncmp(newpath, ourdir, strlen(newpath)) != 0) {
235 return 0;
236 }
237 return 1;
238}
239
241{
242 for (; *str; str++)
243 if ((*str == '*') || (*str == '?'))
244 return 1;
245 return 0;
246}
247
248/*
249 * Here's a pool-based interface to the POSIX-esque ap_regcomp().
250 * Note that we return ap_regex_t instead of being passed one.
251 * The reason is that if you use an already-used ap_regex_t structure,
252 * the memory that you've already allocated gets forgotten, and
253 * regfree() doesn't clear it. So we don't allow it.
254 */
255
257{
259 return APR_SUCCESS;
260}
261
263 int cflags)
264{
265 ap_regex_t *preg = apr_palloc(p, sizeof *preg);
267 if (err) {
268 if (err == AP_REG_ESPACE)
270 return NULL;
271 }
272
275
276 return preg;
277}
278
280{
281 ap_regfree(reg);
282 apr_pool_cleanup_kill(p, (void *) reg, regex_cleanup);
283}
284
285/*
286 * Similar to standard strstr() but we ignore case in this version.
287 * Based on the strstr() implementation further below.
288 */
289AP_DECLARE(char *) ap_strcasestr(const char *s1, const char *s2)
290{
291 char *p1, *p2;
292 if (*s2 == '\0') {
293 /* an empty s2 */
294 return((char *)s1);
295 }
296 while(1) {
297 for ( ; (*s1 != '\0') && (apr_tolower(*s1) != apr_tolower(*s2)); s1++);
298 if (*s1 == '\0') {
299 return(NULL);
300 }
301 /* found first character of s2, see if the rest matches */
302 p1 = (char *)s1;
303 p2 = (char *)s2;
304 for (++p1, ++p2; apr_tolower(*p1) == apr_tolower(*p2); ++p1, ++p2) {
305 if (*p1 == '\0') {
306 /* both strings ended together */
307 return((char *)s1);
308 }
309 }
310 if (*p2 == '\0') {
311 /* second string ended, a match */
312 break;
313 }
314 /* didn't find a match here, try starting at next character in s1 */
315 s1++;
316 }
317 return((char *)s1);
318}
319
320/*
321 * Returns an offsetted pointer in bigstring immediately after
322 * prefix. Returns bigstring if bigstring doesn't start with
323 * prefix or if prefix is longer than bigstring while still matching.
324 * NOTE: pointer returned is relative to bigstring, so we
325 * can use standard pointer comparisons in the calling function
326 * (eg: test if ap_stripprefix(a,b) == a)
327 */
328AP_DECLARE(const char *) ap_stripprefix(const char *bigstring,
329 const char *prefix)
330{
331 const char *p1;
332
333 if (*prefix == '\0')
334 return bigstring;
335
336 p1 = bigstring;
337 while (*p1 && *prefix) {
338 if (*p1++ != *prefix++)
339 return bigstring;
340 }
341 if (*prefix == '\0')
342 return p1;
343
344 /* hit the end of bigstring! */
345 return bigstring;
346}
347
348/* This function substitutes for $0-$9, filling in regular expression
349 * submatches. Pass it the same nmatch and pmatch arguments that you
350 * passed ap_regexec(). pmatch should not be greater than the maximum number
351 * of subexpressions - i.e. one more than the re_nsub member of ap_regex_t.
352 *
353 * nmatch must be <=AP_MAX_REG_MATCH (10).
354 *
355 * input should be the string with the $-expressions, source should be the
356 * string that was matched against.
357 *
358 * It returns the substituted string, or NULL if a vbuf is used.
359 * On errors, returns the orig string.
360 *
361 * Parts of this code are based on Henry Spencer's regsub(), from his
362 * AT&T V8 regexp package.
363 */
364
366 struct ap_varbuf *vb, const char *input,
367 const char *source, apr_size_t nmatch,
369{
370 const char *src = input;
371 char *dst;
372 char c;
374 apr_size_t len = 0;
375
376 AP_DEBUG_ASSERT((result && p && !vb) || (vb && !p && !result));
378 return APR_EINVAL;
379 if (!nmatch) {
380 len = strlen(src);
381 if (maxlen > 0 && len >= maxlen)
382 return APR_ENOMEM;
383 if (!vb) {
385 return APR_SUCCESS;
386 }
387 else {
389 return APR_SUCCESS;
390 }
391 }
392
393 /* First pass, find the size */
394 while ((c = *src++) != '\0') {
395 if (c == '$' && apr_isdigit(*src))
396 no = *src++ - '0';
397 else
399
400 if (no >= AP_MAX_REG_MATCH) { /* Ordinary character. */
401 if (c == '\\' && *src)
402 src++;
403 len++;
404 }
405 else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
406 if (APR_SIZE_MAX - len <= pmatch[no].rm_eo - pmatch[no].rm_so)
407 return APR_ENOMEM;
409 }
410
411 }
412
413 if (len >= maxlen && maxlen > 0)
414 return APR_ENOMEM;
415
416 if (!vb) {
417 *result = dst = apr_palloc(p, len + 1);
418 }
419 else {
420 if (vb->strlen == AP_VARBUF_UNKNOWN)
421 vb->strlen = strlen(vb->buf);
422 ap_varbuf_grow(vb, vb->strlen + len);
423 dst = vb->buf + vb->strlen;
424 vb->strlen += len;
425 }
426
427 /* Now actually fill in the string */
428
429 src = input;
430
431 while ((c = *src++) != '\0') {
432 if (c == '$' && apr_isdigit(*src))
433 no = *src++ - '0';
434 else
436
437 if (no >= AP_MAX_REG_MATCH) { /* Ordinary character. */
438 if (c == '\\' && *src)
439 c = *src++;
440 *dst++ = c;
441 }
442 else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
444 memcpy(dst, source + pmatch[no].rm_so, len);
445 dst += len;
446 }
447
448 }
449 *dst = '\0';
450
451 return APR_SUCCESS;
452}
453
454#ifndef AP_PREGSUB_MAXLEN
455#define AP_PREGSUB_MAXLEN (HUGE_STRING_LEN * 8)
456#endif
457AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input,
458 const char *source, apr_size_t nmatch,
460{
461 char *result;
464 if (rc != APR_SUCCESS)
465 result = NULL;
466 return result;
467}
468
470 const char *input, const char *source,
472 apr_size_t maxlen)
473{
475 pmatch, maxlen);
476 if (rc != APR_SUCCESS)
477 *result = NULL;
478 return rc;
479}
480
481/* Forward declare */
482static char x2c(const char *what);
483
484#define IS_SLASH_OR_NUL(s) (s == '\0' || AP_IS_SLASH(s))
485
486/*
487 * Inspired by mod_jk's jk_servlet_normalize().
488 */
489AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags)
490{
491 int ret = 1;
492 apr_size_t l = 1, w = 1, n;
494 int merge_slashes = (flags & AP_NORMALIZE_MERGE_SLASHES) != 0;
495
496 if (!AP_IS_SLASH(path[0])) {
497 /* Besides "OPTIONS *", a request-target should start with '/'
498 * per RFC 7230 section 5.3, so anything else is invalid.
499 */
500 if (path[0] == '*' && path[1] == '\0') {
501 return 1;
502 }
503 /* However, AP_NORMALIZE_ALLOW_RELATIVE can be used to bypass
504 * this restriction (e.g. for subrequest file lookups).
505 */
506 if (!(flags & AP_NORMALIZE_ALLOW_RELATIVE) || path[0] == '\0') {
507 return 0;
508 }
509
510 l = w = 0;
511 }
512
513 while (path[l] != '\0') {
514 /* RFC-3986 section 2.3:
515 * For consistency, percent-encoded octets in the ranges of
516 * ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D),
517 * period (%2E), underscore (%5F), or tilde (%7E) should [...]
518 * be decoded to their corresponding unreserved characters by
519 * URI normalizers.
520 */
521 if (decode_unreserved && path[l] == '%') {
522 if (apr_isxdigit(path[l + 1]) && apr_isxdigit(path[l + 2])) {
523 const char c = x2c(&path[l + 1]);
525 /* Replace last char and fall through as the current
526 * read position */
527 l += 2;
528 path[l] = c;
529 }
530 }
531 else {
532 /* Invalid encoding */
533 ret = 0;
534 }
535 }
536
537 if (w == 0 || AP_IS_SLASH(path[w - 1])) {
538 /* Collapse ///// sequences to / */
539 if (merge_slashes && AP_IS_SLASH(path[l])) {
540 do {
541 l++;
542 } while (AP_IS_SLASH(path[l]));
543 continue;
544 }
545
546 if (path[l] == '.') {
547 /* Remove /./ segments */
548 if (IS_SLASH_OR_NUL(path[l + 1])) {
549 l++;
550 if (path[l]) {
551 l++;
552 }
553 continue;
554 }
555
556 /* Remove /xx/../ segments (or /xx/.%2e/ when
557 * AP_NORMALIZE_DECODE_UNRESERVED is set since we
558 * decoded only the first dot above).
559 */
560 n = l + 1;
561 if ((path[n] == '.' || (decode_unreserved
562 && path[n] == '%'
563 && path[++n] == '2'
564 && (path[++n] == 'e'
565 || path[n] == 'E')))
566 && IS_SLASH_OR_NUL(path[n + 1])) {
567 /* Wind w back to remove the previous segment */
568 if (w > 1) {
569 do {
570 w--;
571 } while (w && !AP_IS_SLASH(path[w - 1]));
572 }
573 else {
574 /* Already at root, ignore and return a failure
575 * if asked to.
576 */
578 ret = 0;
579 }
580 }
581
582 /* Move l forward to the next segment */
583 l = n + 1;
584 if (path[l]) {
585 l++;
586 }
587 continue;
588 }
589 }
590 }
591
592 path[w++] = path[l++];
593 }
594 path[w] = '\0';
595
596 return ret;
597}
598
599/*
600 * Parse .. so we don't compromise security
601 */
609
611{
612
613 char *d, *s;
614
615 if (!*name) {
616 return;
617 }
618
619 s = d = name;
620
621#ifdef HAVE_UNC_PATHS
622 /* Check for UNC names. Leave leading two slashes. */
623 if (is_fs_path && s[0] == '/' && s[1] == '/')
624 *d++ = *s++;
625#endif
626
627 while (*s) {
628 if ((*d++ = *s) == '/') {
629 do {
630 ++s;
631 } while (*s == '/');
632 }
633 else {
634 ++s;
635 }
636 }
637 *d = '\0';
638}
639
641{
643}
644
645/*
646 * copy at most n leading directories of s into d
647 * d should be at least as large as s plus 1 extra byte
648 * assumes n > 0
649 * the return value is the ever useful pointer to the trailing \0 of d
650 *
651 * MODIFIED FOR HAVE_DRIVE_LETTERS and NETWARE environments,
652 * so that if n == 0, "/" is returned in d with n == 1
653 * and s == "e:/test.html", "e:/" is returned in d
654 * *** See also ap_directory_walk in server/request.c
655 *
656 * examples:
657 * /a/b, 0 ==> / (true for all platforms)
658 * /a/b, 1 ==> /
659 * /a/b, 2 ==> /a/
660 * /a/b, 3 ==> /a/b/
661 * /a/b, 4 ==> /a/b/
662 *
663 * c:/a/b 0 ==> /
664 * c:/a/b 1 ==> c:/
665 * c:/a/b 2 ==> c:/a/
666 * c:/a/b 3 ==> c:/a/b
667 * c:/a/b 4 ==> c:/a/b
668 */
669AP_DECLARE(char *) ap_make_dirstr_prefix(char *d, const char *s, int n)
670{
671 if (n < 1) {
672 *d = '/';
673 *++d = '\0';
674 return (d);
675 }
676
677 for (;;) {
678 if (*s == '\0' || (*s == '/' && (--n) == 0)) {
679 *d = '/';
680 break;
681 }
682 *d++ = *s++;
683 }
684 *++d = 0;
685 return (d);
686}
687
688
689/*
690 * return the parent directory name including trailing / of the file s
691 */
693{
694 const char *last_slash = ap_strrchr_c(s, '/');
695 char *d;
696 int l;
697
698 if (last_slash == NULL) {
699 return apr_pstrdup(p, "");
700 }
701 l = (last_slash - s) + 1;
702 d = apr_pstrmemdup(p, s, l);
703
704 return (d);
705}
706
707
709{
710 int x, n;
711
712 for (x = 0, n = 0; path[x]; x++)
713 if (path[x] == '/')
714 n++;
715 return n;
716}
717
718AP_DECLARE(char *) ap_getword_nc(apr_pool_t *atrans, char **line, char stop)
719{
720 return ap_getword(atrans, (const char **) line, stop);
721}
722
723AP_DECLARE(char *) ap_getword(apr_pool_t *atrans, const char **line, char stop)
724{
725 const char *pos = *line;
726 int len;
727 char *res;
728
729 while ((*pos != stop) && *pos) {
730 ++pos;
731 }
732
733 len = pos - *line;
734 res = apr_pstrmemdup(atrans, *line, len);
735
736 if (stop) {
737 while (*pos == stop) {
738 ++pos;
739 }
740 }
741 *line = pos;
742
743 return res;
744}
745
747{
748 return ap_getword_white(atrans, (const char **) line);
749}
750
751AP_DECLARE(char *) ap_getword_white(apr_pool_t *atrans, const char **line)
752{
753 const char *pos = *line;
754 int len;
755 char *res;
756
757 while (!apr_isspace(*pos) && *pos) {
758 ++pos;
759 }
760
761 len = pos - *line;
762 res = apr_pstrmemdup(atrans, *line, len);
763
764 while (apr_isspace(*pos)) {
765 ++pos;
766 }
767
768 *line = pos;
769
770 return res;
771}
772
774 char stop)
775{
776 return ap_getword_nulls(atrans, (const char **) line, stop);
777}
778
779AP_DECLARE(char *) ap_getword_nulls(apr_pool_t *atrans, const char **line,
780 char stop)
781{
782 const char *pos = ap_strchr_c(*line, stop);
783 char *res;
784
785 if (!pos) {
786 apr_size_t len = strlen(*line);
787 res = apr_pstrmemdup(atrans, *line, len);
788 *line += len;
789 return res;
790 }
791
792 res = apr_pstrmemdup(atrans, *line, pos - *line);
793
794 ++pos;
795
796 *line = pos;
797
798 return res;
799}
800
801/* Get a word, (new) config-file style --- quoted strings and backslashes
802 * all honored
803 */
804
805static char *substring_conf(apr_pool_t *p, const char *start, int len,
806 char quote)
807{
808 char *result = apr_palloc(p, len + 1);
809 char *resp = result;
810 int i;
811
812 for (i = 0; i < len; ++i) {
813 if (start[i] == '\\' && (start[i + 1] == '\\'
814 || (quote && start[i + 1] == quote)))
815 *resp++ = start[++i];
816 else
817 *resp++ = start[i];
818 }
819
820 *resp++ = '\0';
821#if RESOLVE_ENV_PER_TOKEN
822 return (char *)ap_resolve_env(p,result);
823#else
824 return result;
825#endif
826}
827
829{
830 return ap_getword_conf(p, (const char **) line);
831}
832
833AP_DECLARE(char *) ap_getword_conf(apr_pool_t *p, const char **line)
834{
835 const char *str = *line, *strend;
836 char *res;
837 char quote;
838
839 while (apr_isspace(*str))
840 ++str;
841
842 if (!*str) {
843 *line = str;
844 return "";
845 }
846
847 if ((quote = *str) == '"' || quote == '\'') {
848 strend = str + 1;
849 while (*strend && *strend != quote) {
850 if (*strend == '\\' && strend[1] &&
851 (strend[1] == quote || strend[1] == '\\')) {
852 strend += 2;
853 }
854 else {
855 ++strend;
856 }
857 }
858 res = substring_conf(p, str + 1, strend - str - 1, quote);
859
860 if (*strend == quote)
861 ++strend;
862 }
863 else {
864 strend = str;
865 while (*strend && !apr_isspace(*strend))
866 ++strend;
867
868 res = substring_conf(p, str, strend - str, 0);
869 }
870
871 while (apr_isspace(*strend))
872 ++strend;
873 *line = strend;
874 return res;
875}
876
878{
879 return ap_getword_conf2(p, (const char **) line);
880}
881
882AP_DECLARE(char *) ap_getword_conf2(apr_pool_t *p, const char **line)
883{
884 const char *str = *line, *strend;
885 char *res;
886 char quote;
887 int count = 1;
888
889 while (apr_isspace(*str))
890 ++str;
891
892 if (!*str) {
893 *line = str;
894 return "";
895 }
896
897 if ((quote = *str) == '"' || quote == '\'')
898 return ap_getword_conf(p, line);
899
900 if (quote == '{') {
901 strend = str + 1;
902 while (*strend) {
903 if (*strend == '}' && !--count)
904 break;
905 if (*strend == '{')
906 ++count;
907 if (*strend == '\\' && strend[1] && strend[1] == '\\') {
908 ++strend;
909 }
910 ++strend;
911 }
912 res = substring_conf(p, str + 1, strend - str - 1, 0);
913
914 if (*strend == '}')
915 ++strend;
916 }
917 else {
918 strend = str;
919 while (*strend && !apr_isspace(*strend))
920 ++strend;
921
922 res = substring_conf(p, str, strend - str, 0);
923 }
924
925 while (apr_isspace(*strend))
926 ++strend;
927 *line = strend;
928 return res;
929}
930
932{
933#ifdef DEBUG
935 "Done with config file %s", cfp->name);
936#endif
937 return (cfp->close == NULL) ? 0 : cfp->close(cfp->param);
938}
939
940/* we can't use apr_file_* directly because of linking issues on Windows */
942{
943 return apr_file_close(param);
944}
945
946static apr_status_t cfg_getch(char *ch, void *param)
947{
948 return apr_file_getc(ch, param);
949}
950
952{
953 return apr_file_gets(buf, bufsiz, param);
954}
955
956/* Open a ap_configfile_t as FILE, return open ap_configfile_t struct pointer */
958 apr_pool_t *p, const char *name)
959{
962 apr_finfo_t finfo;
964#ifdef DEBUG
965 char buf[120];
966#endif
967
968 if (name == NULL) {
970 "Internal error: pcfg_openfile() called with NULL filename");
971 return APR_EBADF;
972 }
973
976#ifdef DEBUG
978 "Opening config file %s (%s)",
979 name, (status != APR_SUCCESS) ?
980 apr_strerror(status, buf, sizeof(buf)) : "successful");
981#endif
982 if (status != APR_SUCCESS)
983 return status;
984
986 if (status != APR_SUCCESS)
987 return status;
988
989 if (finfo.filetype != APR_REG &&
992#else
993 strcmp(name, "/dev/null") != 0) {
994#endif /* WIN32 || OS2 */
996 "Access to file %s denied by server: not a regular file",
997 name);
999 return APR_EBADF;
1000 }
1001
1002#ifdef WIN32
1003 /* Some twisted character [no pun intended] at MS decided that a
1004 * zero width joiner as the lead wide character would be ideal for
1005 * describing Unicode text files. This was further convoluted to
1006 * another MSism that the same character mapped into utf-8, EF BB BF
1007 * would signify utf-8 text files.
1008 *
1009 * Since MS configuration files are all protecting utf-8 encoded
1010 * Unicode path, file and resource names, we already have the correct
1011 * WinNT encoding. But at least eat the stupid three bytes up front.
1012 */
1013 {
1014 unsigned char buf[4];
1015 apr_size_t len = 3;
1017 if ((status != APR_SUCCESS) || (len < 3)
1018 || memcmp(buf, "\xEF\xBB\xBF", 3) != 0) {
1019 apr_off_t zero = 0;
1021 }
1022 }
1023#endif
1024
1025 new_cfg = apr_palloc(p, sizeof(*new_cfg));
1026 new_cfg->param = file;
1027 new_cfg->name = apr_pstrdup(p, name);
1028 new_cfg->getch = cfg_getch;
1029 new_cfg->getstr = cfg_getstr;
1030 new_cfg->close = cfg_close;
1031 new_cfg->line_number = 0;
1032 *ret_cfg = new_cfg;
1033 return APR_SUCCESS;
1034}
1035
1036
1037/* Allocate a ap_configfile_t handle with user defined functions and params */
1039 apr_pool_t *p, const char *descr, void *param,
1040 apr_status_t (*getc_func) (char *ch, void *param),
1041 apr_status_t (*gets_func) (void *buf, apr_size_t bufsize, void *param),
1042 apr_status_t (*close_func) (void *param))
1043{
1045 new_cfg->param = param;
1046 new_cfg->name = descr;
1047 new_cfg->getch = getc_func;
1048 new_cfg->getstr = gets_func;
1049 new_cfg->close = close_func;
1050 new_cfg->line_number = 0;
1051 return new_cfg;
1052}
1053
1054/* Read one character from a configfile_t */
1056{
1057 apr_status_t rc = cfp->getch(ch, cfp->param);
1058 if (rc == APR_SUCCESS && *ch == LF)
1059 ++cfp->line_number;
1060 return rc;
1061}
1062
1065{
1066 if (rc == APR_SUCCESS)
1067 return NULL;
1068
1069 if (rc == APR_ENOSPC)
1070 return apr_psprintf(p, "Error reading %s at line %d: Line too long",
1071 cfp->name, cfp->line_number);
1072
1073 return apr_psprintf(p, "Error reading %s at line %d: %pm",
1074 cfp->name, cfp->line_number, &rc);
1075}
1076
1077/* Read one line from open ap_configfile_t, strip LF, increase line number */
1078/* If custom handler does not define a getstr() function, read char by char */
1081{
1083 /* If a "get string" function is defined, use it */
1084 if (cfp->getstr != NULL) {
1085 char *cp;
1086 char *cbuf = buf + offset;
1088
1089 while (1) {
1090 ++cfp->line_number;
1091 rc = cfp->getstr(cbuf, cbufsize, cfp->param);
1092 if (rc == APR_EOF) {
1093 if (cbuf != buf + offset) {
1094 *cbuf = '\0';
1095 break;
1096 }
1097 else {
1098 return APR_EOF;
1099 }
1100 }
1101 if (rc != APR_SUCCESS) {
1102 return rc;
1103 }
1104
1105 /*
1106 * check for line continuation,
1107 * i.e. match [^\\]\\[\r]\n only
1108 */
1109 cp = cbuf;
1110 cp += strlen(cp);
1111 if (cp > buf && cp[-1] == LF) {
1112 cp--;
1113 if (cp > buf && cp[-1] == CR)
1114 cp--;
1115 if (cp > buf && cp[-1] == '\\') {
1116 cp--;
1117 /*
1118 * line continuation requested -
1119 * then remove backslash and continue
1120 */
1121 cbufsize -= (cp-cbuf);
1122 cbuf = cp;
1123 continue;
1124 }
1125 }
1126 else if (cp - buf >= bufsize - 1) {
1127 return APR_ENOSPC;
1128 }
1129 break;
1130 }
1131 } else {
1132 /* No "get string" function defined; read character by character */
1134
1135 if (bufsize < 2) {
1136 /* too small, assume caller is crazy */
1137 return APR_EINVAL;
1138 }
1139 buf[offset] = '\0';
1140
1141 while (1) {
1142 char c;
1143 rc = cfp->getch(&c, cfp->param);
1144 if (rc == APR_EOF) {
1145 if (i > offset)
1146 break;
1147 else
1148 return APR_EOF;
1149 }
1150 if (rc != APR_SUCCESS)
1151 return rc;
1152 if (c == LF) {
1153 ++cfp->line_number;
1154 /* check for line continuation */
1155 if (i > 0 && buf[i-1] == '\\') {
1156 i--;
1157 continue;
1158 }
1159 else {
1160 break;
1161 }
1162 }
1163 buf[i] = c;
1164 ++i;
1165 if (i >= bufsize - 1) {
1166 return APR_ENOSPC;
1167 }
1168 }
1169 buf[i] = '\0';
1170 }
1171 return APR_SUCCESS;
1172}
1173
1174static int cfg_trim_line(char *buf)
1175{
1176 char *start, *end;
1177 /*
1178 * Leading and trailing white space is eliminated completely
1179 */
1180 start = buf;
1181 while (apr_isspace(*start))
1182 ++start;
1183 /* blast trailing whitespace */
1184 end = &start[strlen(start)];
1185 while (--end >= start && apr_isspace(*end))
1186 *end = '\0';
1187 /* Zap leading whitespace by shifting */
1188 if (start != buf)
1189 memmove(buf, start, end - start + 2);
1190#ifdef DEBUG_CFG_LINES
1191 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, APLOGNO(00555) "Read config: '%s'", buf);
1192#endif
1193 return end - start + 1;
1194}
1195
1196/* Read one line from open ap_configfile_t, strip LF, increase line number */
1197/* If custom handler does not define a getstr() function, read char by char */
1199 ap_configfile_t *cfp)
1200{
1202 if (rc == APR_SUCCESS)
1204 return rc;
1205}
1206
1208 ap_configfile_t *cfp,
1210{
1213 vb->strlen = 0;
1214 *vb->buf = '\0';
1215
1216 if (vb->strlen == AP_VARBUF_UNKNOWN)
1217 vb->strlen = strlen(vb->buf);
1218 if (vb->avail - vb->strlen < 3) {
1219 new_len = vb->avail * 2;
1220 if (new_len > max_len)
1221 new_len = max_len;
1222 else if (new_len < 3)
1223 new_len = 3;
1225 }
1226
1227 for (;;) {
1228 rc = ap_cfg_getline_core(vb->buf, vb->avail, vb->strlen, cfp);
1229 if (rc == APR_ENOSPC || rc == APR_SUCCESS)
1230 vb->strlen += strlen(vb->buf + vb->strlen);
1231 if (rc != APR_ENOSPC)
1232 break;
1233 if (vb->avail >= max_len)
1234 return APR_ENOSPC;
1235 new_len = vb->avail * 2;
1236 if (new_len > max_len)
1237 new_len = max_len;
1239 --cfp->line_number;
1240 }
1241 if (vb->strlen > max_len)
1242 return APR_ENOSPC;
1243 if (rc == APR_SUCCESS)
1244 vb->strlen = cfg_trim_line(vb->buf);
1245 return rc;
1246}
1247
1248/* Size an HTTP header field list item, as separated by a comma.
1249 * The return value is a pointer to the beginning of the non-empty list item
1250 * within the original string (or NULL if there is none) and the address
1251 * of field is shifted to the next non-comma, non-whitespace character.
1252 * len is the length of the item excluding any beginning whitespace.
1253 */
1254AP_DECLARE(const char *) ap_size_list_item(const char **field, int *len)
1255{
1256 const unsigned char *ptr = (const unsigned char *)*field;
1257 const unsigned char *token;
1258 int in_qpair, in_qstr, in_com;
1259
1260 /* Find first non-comma, non-whitespace byte */
1261
1262 while (*ptr == ',' || apr_isspace(*ptr))
1263 ++ptr;
1264
1265 token = ptr;
1266
1267 /* Find the end of this item, skipping over dead bits */
1268
1269 for (in_qpair = in_qstr = in_com = 0;
1270 *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
1271 ++ptr) {
1272
1273 if (in_qpair) {
1274 in_qpair = 0;
1275 }
1276 else {
1277 switch (*ptr) {
1278 case '\\': in_qpair = 1; /* quoted-pair */
1279 break;
1280 case '"' : if (!in_com) /* quoted string delim */
1281 in_qstr = !in_qstr;
1282 break;
1283 case '(' : if (!in_qstr) /* comment (may nest) */
1284 ++in_com;
1285 break;
1286 case ')' : if (in_com) /* end comment */
1287 --in_com;
1288 break;
1289 default : break;
1290 }
1291 }
1292 }
1293
1294 if ((*len = (ptr - token)) == 0) {
1295 *field = (const char *)ptr;
1296 return NULL;
1297 }
1298
1299 /* Advance field pointer to the next non-comma, non-white byte */
1300
1301 while (*ptr == ',' || apr_isspace(*ptr))
1302 ++ptr;
1303
1304 *field = (const char *)ptr;
1305 return (const char *)token;
1306}
1307
1308/* Retrieve an HTTP header field list item, as separated by a comma,
1309 * while stripping insignificant whitespace and lowercasing anything not in
1310 * a quoted string or comment. The return value is a new string containing
1311 * the converted list item (or NULL if none) and the address pointed to by
1312 * field is shifted to the next non-comma, non-whitespace.
1313 */
1315{
1316 const char *tok_start;
1317 const unsigned char *ptr;
1318 unsigned char *pos;
1319 char *token;
1320 int addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0, tok_len = 0;
1321
1322 /* Find the beginning and maximum length of the list item so that
1323 * we can allocate a buffer for the new string and reset the field.
1324 */
1326 return NULL;
1327 }
1328 token = apr_palloc(p, tok_len + 1);
1329
1330 /* Scan the token again, but this time copy only the good bytes.
1331 * We skip extra whitespace and any whitespace around a '=', '/',
1332 * or ';' and lowercase normal characters not within a comment,
1333 * quoted-string or quoted-pair.
1334 */
1335 for (ptr = (const unsigned char *)tok_start, pos = (unsigned char *)token;
1336 *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
1337 ++ptr) {
1338
1339 if (in_qpair) {
1340 in_qpair = 0;
1341 *pos++ = *ptr;
1342 }
1343 else {
1344 switch (*ptr) {
1345 case '\\': in_qpair = 1;
1346 if (addspace == 1)
1347 *pos++ = ' ';
1348 *pos++ = *ptr;
1349 addspace = 0;
1350 break;
1351 case '"' : if (!in_com)
1352 in_qstr = !in_qstr;
1353 if (addspace == 1)
1354 *pos++ = ' ';
1355 *pos++ = *ptr;
1356 addspace = 0;
1357 break;
1358 case '(' : if (!in_qstr)
1359 ++in_com;
1360 if (addspace == 1)
1361 *pos++ = ' ';
1362 *pos++ = *ptr;
1363 addspace = 0;
1364 break;
1365 case ')' : if (in_com)
1366 --in_com;
1367 *pos++ = *ptr;
1368 addspace = 0;
1369 break;
1370 case ' ' :
1371 case '\t': if (addspace)
1372 break;
1373 if (in_com || in_qstr)
1374 *pos++ = *ptr;
1375 else
1376 addspace = 1;
1377 break;
1378 case '=' :
1379 case '/' :
1380 case ';' : if (!(in_com || in_qstr))
1381 addspace = -1;
1382 *pos++ = *ptr;
1383 break;
1384 default : if (addspace == 1)
1385 *pos++ = ' ';
1386 *pos++ = (in_com || in_qstr) ? *ptr
1387 : apr_tolower(*ptr);
1388 addspace = 0;
1389 break;
1390 }
1391 }
1392 }
1393 *pos = '\0';
1394
1395 return token;
1396}
1397
1403
1404/* Find an item in canonical form (lowercase, no extra spaces) within
1405 * an HTTP field value list. Returns 1 if found, 0 if not found.
1406 * This would be much more efficient if we stored header fields as
1407 * an array of list items as they are received instead of a plain string.
1408 */
1409static int find_list_item(apr_pool_t *p, const char *line,
1410 const char *tok, ap_etag_e type)
1411{
1412 const unsigned char *pos;
1413 const unsigned char *ptr = (const unsigned char *)line;
1414 int good = 0, addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0;
1415
1416 if (!line || !tok) {
1417 return 0;
1418 }
1419 if (type == AP_ETAG_STRONG && *tok != '\"') {
1420 return 0;
1421 }
1422 if (type == AP_ETAG_WEAK) {
1423 if (*tok == 'W' && (*(tok+1)) == '/' && (*(tok+2)) == '\"') {
1424 tok += 2;
1425 }
1426 else if (*tok != '\"') {
1427 return 0;
1428 }
1429 }
1430
1431 do { /* loop for each item in line's list */
1432
1433 /* Find first non-comma, non-whitespace byte */
1434 while (*ptr == ',' || apr_isspace(*ptr)) {
1435 ++ptr;
1436 }
1437
1438 /* Account for strong or weak Etags, depending on our search */
1439 if (type == AP_ETAG_STRONG && *ptr != '\"') {
1440 break;
1441 }
1442 if (type == AP_ETAG_WEAK) {
1443 if (*ptr == 'W' && (*(ptr+1)) == '/' && (*(ptr+2)) == '\"') {
1444 ptr += 2;
1445 }
1446 else if (*ptr != '\"') {
1447 break;
1448 }
1449 }
1450
1451 if (*ptr)
1452 good = 1; /* until proven otherwise for this item */
1453 else
1454 break; /* no items left and nothing good found */
1455
1456 /* We skip extra whitespace and any whitespace around a '=', '/',
1457 * or ';' and lowercase normal characters not within a comment,
1458 * quoted-string or quoted-pair.
1459 */
1460 for (pos = (const unsigned char *)tok;
1461 *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
1462 ++ptr) {
1463
1464 if (in_qpair) {
1465 in_qpair = 0;
1466 if (good)
1467 good = (*pos++ == *ptr);
1468 }
1469 else {
1470 switch (*ptr) {
1471 case '\\': in_qpair = 1;
1472 if (addspace == 1)
1473 good = good && (*pos++ == ' ');
1474 good = good && (*pos++ == *ptr);
1475 addspace = 0;
1476 break;
1477 case '"' : if (!in_com)
1478 in_qstr = !in_qstr;
1479 if (addspace == 1)
1480 good = good && (*pos++ == ' ');
1481 good = good && (*pos++ == *ptr);
1482 addspace = 0;
1483 break;
1484 case '(' : if (!in_qstr)
1485 ++in_com;
1486 if (addspace == 1)
1487 good = good && (*pos++ == ' ');
1488 good = good && (*pos++ == *ptr);
1489 addspace = 0;
1490 break;
1491 case ')' : if (in_com)
1492 --in_com;
1493 good = good && (*pos++ == *ptr);
1494 addspace = 0;
1495 break;
1496 case ' ' :
1497 case '\t': if (addspace || !good)
1498 break;
1499 if (in_com || in_qstr)
1500 good = (*pos++ == *ptr);
1501 else
1502 addspace = 1;
1503 break;
1504 case '=' :
1505 case '/' :
1506 case ';' : if (!(in_com || in_qstr))
1507 addspace = -1;
1508 good = good && (*pos++ == *ptr);
1509 break;
1510 default : if (!good)
1511 break;
1512 if (addspace == 1)
1513 good = (*pos++ == ' ');
1514 if (in_com || in_qstr)
1515 good = good && (*pos++ == *ptr);
1516 else
1517 good = good
1518 && (apr_tolower(*pos++) == apr_tolower(*ptr));
1519 addspace = 0;
1520 break;
1521 }
1522 }
1523 }
1524 if (good && *pos)
1525 good = 0; /* not good if only a prefix was matched */
1526
1527 } while (*ptr && !good);
1528
1529 return good;
1530}
1531
1532/* Find an item in canonical form (lowercase, no extra spaces) within
1533 * an HTTP field value list. Returns 1 if found, 0 if not found.
1534 * This would be much more efficient if we stored header fields as
1535 * an array of list items as they are received instead of a plain string.
1536 */
1538 const char *tok)
1539{
1540 return find_list_item(p, line, tok, AP_ETAG_NONE);
1541}
1542
1543/* Find a strong Etag in canonical form (lowercase, no extra spaces) within
1544 * an HTTP field value list. Returns 1 if found, 0 if not found.
1545 */
1547 const char *tok)
1548{
1549 return find_list_item(p, line, tok, AP_ETAG_STRONG);
1550}
1551
1552/* Find a weak ETag in canonical form (lowercase, no extra spaces) within
1553 * an HTTP field value list. Returns 1 if found, 0 if not found.
1554 */
1556 const char *tok)
1557{
1558 return find_list_item(p, line, tok, AP_ETAG_WEAK);
1559}
1560
1561/* Grab a list of tokens of the format 1#token (from RFC7230) */
1563 const char *str_in,
1565 int skip_invalid)
1566{
1567 int in_leading_space = 1;
1568 int in_trailing_space = 0;
1569 int string_end = 0;
1570 const char *tok_begin;
1571 const char *cur;
1572
1573 if (!str_in) {
1574 return NULL;
1575 }
1576
1577 tok_begin = cur = str_in;
1578
1579 while (!string_end) {
1580 const unsigned char c = (unsigned char)*cur;
1581
1582 if (!TEST_CHAR(c, T_HTTP_TOKEN_STOP)) {
1583 /* Non-separator character; we are finished with leading
1584 * whitespace. We must never have encountered any trailing
1585 * whitespace before the delimiter (comma) */
1586 in_leading_space = 0;
1587 if (in_trailing_space) {
1588 return "Encountered illegal whitespace in token";
1589 }
1590 }
1591 else if (c == ' ' || c == '\t') {
1592 /* "Linear whitespace" only includes ASCII CRLF, space, and tab;
1593 * we can't get a CRLF since headers are split on them already,
1594 * so only look for a space or a tab */
1595 if (in_leading_space) {
1596 /* We're still in leading whitespace */
1597 ++tok_begin;
1598 }
1599 else {
1600 /* We must be in trailing whitespace */
1602 }
1603 }
1604 else if (c == ',' || c == '\0') {
1605 if (!in_leading_space) {
1606 /* If we're out of the leading space, we know we've read some
1607 * characters of a token */
1608 if (*tokens == NULL) {
1609 *tokens = apr_array_make(p, 4, sizeof(char *));
1610 }
1611 APR_ARRAY_PUSH(*tokens, char *) =
1612 apr_pstrmemdup((*tokens)->pool, tok_begin,
1614 }
1615 /* We're allowed to have null elements, just don't add them to the
1616 * array */
1617
1618 tok_begin = cur + 1;
1619 in_leading_space = 1;
1621 string_end = (c == '\0');
1622 }
1623 else {
1624 /* Encountered illegal separator char */
1625 if (skip_invalid) {
1626 /* Skip to the next separator */
1627 const char *temp;
1628 temp = ap_strchr_c(cur, ',');
1629 if(!temp) {
1630 temp = ap_strchr_c(cur, '\0');
1631 }
1632
1633 /* Act like we haven't seen a token so we reset */
1634 cur = temp - 1;
1635 in_leading_space = 1;
1637 }
1638 else {
1639 return apr_psprintf(p, "Encountered illegal separator "
1640 "'\\x%.2x'", (unsigned int)c);
1641 }
1642 }
1643
1644 ++cur;
1645 }
1646
1647 return NULL;
1648}
1649
1650/* Scan a string for HTTP VCHAR/obs-text characters including HT and SP
1651 * (as used in header values, for example, in RFC 7230 section 3.2)
1652 * returning the pointer to the first non-HT ASCII ctrl character.
1653 */
1654AP_DECLARE(const char *) ap_scan_http_field_content(const char *ptr)
1655{
1656 for ( ; !TEST_CHAR(*ptr, T_HTTP_CTRLS); ++ptr) ;
1657
1658 return ptr;
1659}
1660
1661/* Scan a string for HTTP token characters, returning the pointer to
1662 * the first non-token character.
1663 */
1664AP_DECLARE(const char *) ap_scan_http_token(const char *ptr)
1665{
1666 for ( ; !TEST_CHAR(*ptr, T_HTTP_TOKEN_STOP); ++ptr) ;
1667
1668 return ptr;
1669}
1670
1671/* Scan a string for visible ASCII (0x21-0x7E) or obstext (0x80+)
1672 * and return a pointer to the first ctrl/space character encountered.
1673 */
1674AP_DECLARE(const char *) ap_scan_vchar_obstext(const char *ptr)
1675{
1676 for ( ; TEST_CHAR(*ptr, T_VCHAR_OBSTEXT); ++ptr) ;
1677
1678 return ptr;
1679}
1680
1681/* Retrieve a token, spacing over it and returning a pointer to
1682 * the first non-white byte afterwards. Note that these tokens
1683 * are delimited by semis and commas; and can also be delimited
1684 * by whitespace at the caller's option.
1685 */
1686
1688 int accept_white)
1689{
1690 const char *ptr = *accept_line;
1691 const char *tok_start;
1692 char *token;
1693
1694 /* Find first non-white byte */
1695
1696 while (apr_isspace(*ptr))
1697 ++ptr;
1698
1699 tok_start = ptr;
1700
1701 /* find token end, skipping over quoted strings.
1702 * (comments are already gone).
1703 */
1704
1705 while (*ptr && (accept_white || !apr_isspace(*ptr))
1706 && *ptr != ';' && *ptr != ',') {
1707 if (*ptr++ == '"')
1708 while (*ptr)
1709 if (*ptr++ == '"')
1710 break;
1711 }
1712
1713 token = apr_pstrmemdup(p, tok_start, ptr - tok_start);
1714
1715 /* Advance accept_line pointer to the next non-white byte */
1716
1717 while (apr_isspace(*ptr))
1718 ++ptr;
1719
1720 *accept_line = ptr;
1721 return token;
1722}
1723
1724
1725/* find http tokens, see the definition of token from RFC2068 */
1726AP_DECLARE(int) ap_find_token(apr_pool_t *p, const char *line, const char *tok)
1727{
1728 const unsigned char *start_token;
1729 const unsigned char *s;
1730
1731 if (!line)
1732 return 0;
1733
1734 s = (const unsigned char *)line;
1735 for (;;) {
1736 /* find start of token, skip all stop characters */
1737 while (*s && TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
1738 ++s;
1739 }
1740 if (!*s) {
1741 return 0;
1742 }
1743 start_token = s;
1744 /* find end of the token */
1745 while (*s && !TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
1746 ++s;
1747 }
1748 if (!ap_cstr_casecmpn((const char *)start_token, (const char *)tok,
1749 s - start_token)) {
1750 return 1;
1751 }
1752 if (!*s) {
1753 return 0;
1754 }
1755 }
1756}
1757
1758static const char *find_last_token(apr_pool_t *p, const char *line,
1759 const char *tok)
1760{
1761 int llen, tlen, lidx;
1762
1763 if (!line)
1764 return NULL;
1765
1766 llen = strlen(line);
1767 tlen = strlen(tok);
1768 lidx = llen - tlen;
1769
1770 if (lidx < 0 ||
1771 (lidx > 0 && !(apr_isspace(line[lidx - 1]) || line[lidx - 1] == ',')))
1772 return NULL;
1773
1774 if (ap_cstr_casecmpn(&line[lidx], tok, tlen) == 0) {
1775 return &line[lidx];
1776 }
1777 return NULL;
1778}
1779
1781 const char *tok)
1782{
1783 return find_last_token(p, line, tok) != NULL;
1784}
1785
1786AP_DECLARE(int) ap_is_chunked(apr_pool_t *p, const char *line)
1787{
1788 const char *s;
1789
1790 if (!line)
1791 return 0;
1792 if (!ap_cstr_casecmp(line, "chunked")) {
1793 return 1;
1794 }
1795
1796 s = find_last_token(p, line, "chunked");
1797
1798 if (!s) return 0;
1799
1800 /* eat spaces right-to-left to see what precedes "chunked" */
1801 while (--s > line) {
1802 if (*s != ' ') break;
1803 }
1804
1805 /* found delim, or leading ws (input wasn't parsed by httpd as a header) */
1806 if (*s == ',' || *s == ' ') {
1807 return 1;
1808 }
1809 return 0;
1810}
1811
1813{
1814 char *cmd;
1815 unsigned char *d;
1816 const unsigned char *s;
1817
1818 cmd = apr_palloc(p, 2 * strlen(str) + 1); /* Be safe */
1819 d = (unsigned char *)cmd;
1820 s = (const unsigned char *)str;
1821 for (; *s; ++s) {
1822
1823#if defined(OS2) || defined(WIN32)
1824 /*
1825 * Newlines to Win32/OS2 CreateProcess() are ill advised.
1826 * Convert them to spaces since they are effectively white
1827 * space to most applications
1828 */
1829 if (*s == '\r' || *s == '\n') {
1830 *d++ = ' ';
1831 continue;
1832 }
1833#endif
1834
1836 *d++ = '\\';
1837 }
1838 *d++ = *s;
1839 }
1840 *d = '\0';
1841
1842 return cmd;
1843}
1844
1845static char x2c(const char *what)
1846{
1847 char digit;
1848
1849#if !APR_CHARSET_EBCDIC
1850 digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10
1851 : (what[0] - '0'));
1852 digit *= 16;
1853 digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10
1854 : (what[1] - '0'));
1855#else /*APR_CHARSET_EBCDIC*/
1856 char xstr[5];
1857 xstr[0]='0';
1858 xstr[1]='x';
1859 xstr[2]=what[0];
1860 xstr[3]=what[1];
1861 xstr[4]='\0';
1863 0xFF & strtol(xstr, NULL, 16));
1864#endif /*APR_CHARSET_EBCDIC*/
1865 return (digit);
1866}
1867
1868/*
1869 * Unescapes a URL, leaving reserved characters intact.
1870 * Returns 0 on success, non-zero on error
1871 * Failure is due to
1872 * bad % escape returns HTTP_BAD_REQUEST
1873 *
1874 * decoding %00 or a forbidden character returns HTTP_NOT_FOUND
1875 */
1876
1877static int unescape_url(char *url, const char *forbid, const char *reserved,
1878 unsigned int flags)
1879{
1880 const int keep_slashes = (flags & AP_UNESCAPE_URL_KEEP_SLASHES) != 0,
1883 int badesc, badpath;
1884 char *x, *y;
1885
1886 badesc = 0;
1887 badpath = 0;
1888 /* Initial scan for first '%'. Don't bother writing values before
1889 * seeing a '%' */
1890 y = strchr(url, '%');
1891 if (y == NULL) {
1892 return OK;
1893 }
1894 for (x = y; *y; ++x, ++y) {
1895 if (*y != '%') {
1896 *x = *y;
1897 }
1898 else {
1899 if (!apr_isxdigit(*(y + 1)) || !apr_isxdigit(*(y + 2))) {
1900 badesc = 1;
1901 *x = '%';
1902 }
1903 else {
1904 char decoded;
1905 decoded = x2c(y + 1);
1906 if ((decoded == '\0')
1908 || (forbid && ap_strchr_c(forbid, decoded))) {
1909 badpath = 1;
1910 *x = decoded;
1911 y += 2;
1912 }
1913 else if ((keep_unreserved && TEST_CHAR(decoded,
1917 *x++ = *y++;
1918 *x++ = *y++;
1919 *x = *y;
1920 }
1921 else {
1922 *x = decoded;
1923 y += 2;
1924 }
1925 }
1926 }
1927 }
1928 *x = '\0';
1929 if (badesc) {
1930 return HTTP_BAD_REQUEST;
1931 }
1932 else if (badpath) {
1933 return HTTP_NOT_FOUND;
1934 }
1935 else {
1936 return OK;
1937 }
1938}
1940{
1941 /* Traditional */
1942 return unescape_url(url, AP_SLASHES, NULL, 0);
1943}
1945{
1946 /* AllowEncodedSlashes (corrected) */
1947 if (decode_slashes) {
1948 /* no chars reserved */
1949 return unescape_url(url, NULL, NULL, 0);
1950 } else {
1951 /* reserve (do not decode) encoded slashes */
1952 return unescape_url(url, NULL, AP_SLASHES, 0);
1953 }
1954}
1955AP_DECLARE(int) ap_unescape_url_ex(char *url, unsigned int flags)
1956{
1957 return unescape_url(url, NULL, NULL, flags);
1958}
1959
1960#ifdef NEW_APIS
1961/* IFDEF these out until they've been thought through.
1962 * Just a germ of an API extension for now
1963 */
1965{
1966 /* leave RFC1738 reserved characters intact, * so proxied URLs
1967 * don't get mangled. Where does that leave encoded '&' ?
1968 */
1969 return unescape_url(url, NULL, "/;?", 0);
1970}
1971AP_DECLARE(int) ap_unescape_url_reserved(char *url, const char *reserved)
1972{
1973 return unescape_url(url, NULL, reserved);
1974}
1975#endif
1976
1978{
1979 char *slider;
1980
1981 /* replace plus with a space */
1982 if (query) {
1983 for (slider = query; *slider; slider++) {
1984 if (*slider == '+') {
1985 *slider = ' ';
1986 }
1987 }
1988 }
1989
1990 /* unescape everything else */
1991 return unescape_url(query, NULL, NULL, 0);
1992}
1993
1995 apr_port_t port, const request_rec *r)
1996{
1997 if (ap_is_default_port(port, r)) {
1998 return apr_pstrdup(p, hostname);
1999 }
2000 else {
2001 return apr_psprintf(p, "%s:%u", hostname, port);
2002 }
2003}
2004
2006{
2007 return unescape_url(url, NULL, NULL, 0);
2008}
2009
2010/* c2x takes an unsigned, and expects the caller has guaranteed that
2011 * 0 <= what < 256... which usually means that you have to cast to
2012 * unsigned char first, because (unsigned)(char)(x) first goes through
2013 * signed extension to an int before the unsigned cast.
2014 *
2015 * The reason for this assumption is to assist gcc code generation --
2016 * the unsigned char -> unsigned extension is already done earlier in
2017 * both uses of this code, so there's no need to waste time doing it
2018 * again.
2019 */
2020static const char c2x_table[] = "0123456789abcdef";
2021
2022static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix,
2023 unsigned char *where)
2024{
2025#if APR_CHARSET_EBCDIC
2026 what = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)what);
2027#endif /*APR_CHARSET_EBCDIC*/
2028 *where++ = prefix;
2029 *where++ = c2x_table[what >> 4];
2030 *where++ = c2x_table[what & 0xf];
2031 return where;
2032}
2033
2034/*
2035 * escape_path_segment() escapes a path segment, as defined in RFC 1808. This
2036 * routine is (should be) OS independent.
2037 *
2038 * os_escape_path() converts an OS path to a URL, in an OS dependent way. In all
2039 * cases if a ':' occurs before the first '/' in the URL, the URL should be
2040 * prefixed with "./" (or the ':' escaped). In the case of Unix, this means
2041 * leaving '/' alone, but otherwise doing what escape_path_segment() does. For
2042 * efficiency reasons, we don't use escape_path_segment(), which is provided for
2043 * reference. Again, RFC 1808 is where this stuff is defined.
2044 *
2045 * If partial is set, os_escape_path() assumes that the path will be appended to
2046 * something with a '/' in it (and thus does not prefix "./").
2047 */
2048
2049AP_DECLARE(char *) ap_escape_path_segment_buffer(char *copy, const char *segment)
2050{
2051 const unsigned char *s = (const unsigned char *)segment;
2052 unsigned char *d = (unsigned char *)copy;
2053 unsigned c;
2054
2055 while ((c = *s)) {
2057 d = c2x(c, '%', d);
2058 }
2059 else {
2060 *d++ = c;
2061 }
2062 ++s;
2063 }
2064 *d = '\0';
2065 return copy;
2066}
2067
2069{
2070 return ap_escape_path_segment_buffer(apr_palloc(p, 3 * strlen(segment) + 1), segment);
2071}
2072
2074{
2075 char *copy = apr_palloc(p, 3 * strlen(path) + 3);
2076 const unsigned char *s = (const unsigned char *)path;
2077 unsigned char *d = (unsigned char *)copy;
2078 unsigned c;
2079
2080 if (!partial) {
2081 const char *colon = ap_strchr_c(path, ':');
2082 const char *slash = ap_strchr_c(path, '/');
2083
2084 if (colon && (!slash || colon < slash)) {
2085 *d++ = '.';
2086 *d++ = '/';
2087 }
2088 }
2089 while ((c = *s)) {
2091 d = c2x(c, '%', d);
2092 }
2093 else {
2094 *d++ = c;
2095 }
2096 ++s;
2097 }
2098 *d = '\0';
2099 return copy;
2100}
2101
2102AP_DECLARE(char *) ap_escape_urlencoded_buffer(char *copy, const char *buffer)
2103{
2104 const unsigned char *s = (const unsigned char *)buffer;
2105 unsigned char *d = (unsigned char *)copy;
2106 unsigned c;
2107
2108 while ((c = *s)) {
2110 d = c2x(c, '%', d);
2111 }
2112 else if (c == ' ') {
2113 *d++ = '+';
2114 }
2115 else {
2116 *d++ = c;
2117 }
2118 ++s;
2119 }
2120 *d = '\0';
2121 return copy;
2122}
2123
2125{
2126 return ap_escape_urlencoded_buffer(apr_palloc(p, 3 * strlen(buffer) + 1), buffer);
2127}
2128
2129/* ap_escape_uri is now a macro for os_escape_path */
2130
2131AP_DECLARE(char *) ap_escape_html2(apr_pool_t *p, const char *s, int toasc)
2132{
2133 apr_size_t i, j;
2134 char *x;
2135
2136 /* first, count the number of extra characters */
2137 for (i = 0, j = 0; s[i] != '\0'; i++) {
2138 if (i + j > APR_SIZE_MAX - 6) {
2139 abort();
2140 }
2141 if (s[i] == '<' || s[i] == '>')
2142 j += 3;
2143 else if (s[i] == '&')
2144 j += 4;
2145 else if (s[i] == '"')
2146 j += 5;
2147 else if (toasc && !apr_isascii(s[i]))
2148 j += 5;
2149 }
2150
2151 if (j == 0)
2152 return apr_pstrmemdup(p, s, i);
2153
2154 x = apr_palloc(p, i + j + 1);
2155 for (i = 0, j = 0; s[i] != '\0'; i++, j++)
2156 if (s[i] == '<') {
2157 memcpy(&x[j], "&lt;", 4);
2158 j += 3;
2159 }
2160 else if (s[i] == '>') {
2161 memcpy(&x[j], "&gt;", 4);
2162 j += 3;
2163 }
2164 else if (s[i] == '&') {
2165 memcpy(&x[j], "&amp;", 5);
2166 j += 4;
2167 }
2168 else if (s[i] == '"') {
2169 memcpy(&x[j], "&quot;", 6);
2170 j += 5;
2171 }
2172 else if (toasc && !apr_isascii(s[i])) {
2173 char *esc = apr_psprintf(p, "&#%3.3d;", (unsigned char)s[i]);
2174 memcpy(&x[j], esc, 6);
2175 j += 5;
2176 }
2177 else
2178 x[j] = s[i];
2179
2180 x[j] = '\0';
2181 return x;
2182}
2184{
2185 char *ret;
2186 unsigned char *d;
2187 const unsigned char *s;
2188 apr_size_t length, escapes = 0;
2189
2190 if (!str) {
2191 return NULL;
2192 }
2193
2194 /* Compute how many characters need to be escaped */
2195 s = (const unsigned char *)str;
2196 for (; *s; ++s) {
2197 if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
2198 escapes++;
2199 }
2200 }
2201
2202 /* Compute the length of the input string, including NULL */
2203 length = s - (const unsigned char *)str + 1;
2204
2205 /* Fast path: nothing to escape */
2206 if (escapes == 0) {
2207 return apr_pmemdup(p, str, length);
2208 }
2209
2210 /* Each escaped character needs up to 3 extra bytes (0 --> \x00) */
2211 ret = apr_palloc(p, length + 3 * escapes);
2212 d = (unsigned char *)ret;
2213 s = (const unsigned char *)str;
2214 for (; *s; ++s) {
2215 if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
2216 *d++ = '\\';
2217 switch(*s) {
2218 case '\b':
2219 *d++ = 'b';
2220 break;
2221 case '\n':
2222 *d++ = 'n';
2223 break;
2224 case '\r':
2225 *d++ = 'r';
2226 break;
2227 case '\t':
2228 *d++ = 't';
2229 break;
2230 case '\v':
2231 *d++ = 'v';
2232 break;
2233 case '\\':
2234 case '"':
2235 *d++ = *s;
2236 break;
2237 default:
2238 c2x(*s, 'x', d);
2239 d += 3;
2240 }
2241 }
2242 else {
2243 *d++ = *s;
2244 }
2245 }
2246 *d = '\0';
2247
2248 return ret;
2249}
2250
2253{
2254 unsigned char *d, *ep;
2255 const unsigned char *s;
2256
2257 if (!source || !buflen) { /* be safe */
2258 return 0;
2259 }
2260
2261 d = (unsigned char *)dest;
2262 s = (const unsigned char *)source;
2263 ep = d + buflen - 1;
2264
2265 for (; d < ep && *s; ++s) {
2266
2267 if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
2268 *d++ = '\\';
2269 if (d >= ep) {
2270 --d;
2271 break;
2272 }
2273
2274 switch(*s) {
2275 case '\b':
2276 *d++ = 'b';
2277 break;
2278 case '\n':
2279 *d++ = 'n';
2280 break;
2281 case '\r':
2282 *d++ = 'r';
2283 break;
2284 case '\t':
2285 *d++ = 't';
2286 break;
2287 case '\v':
2288 *d++ = 'v';
2289 break;
2290 case '\\':
2291 *d++ = *s;
2292 break;
2293 case '"': /* no need for this in error log */
2294 d[-1] = *s;
2295 break;
2296 default:
2297 if (d >= ep - 2) {
2298 ep = --d; /* break the for loop as well */
2299 break;
2300 }
2301 c2x(*s, 'x', d);
2302 d += 3;
2303 }
2304 }
2305 else {
2306 *d++ = *s;
2307 }
2308 }
2309 *d = '\0';
2310
2311 return (d - (unsigned char *)dest);
2312}
2313
2314AP_DECLARE(void) ap_bin2hex(const void *src, apr_size_t srclen, char *dest)
2315{
2316 const unsigned char *in = src;
2317 apr_size_t i;
2318
2319 for (i = 0; i < srclen; i++) {
2320 *dest++ = c2x_table[in[i] >> 4];
2321 *dest++ = c2x_table[in[i] & 0xf];
2322 }
2323 *dest = '\0';
2324}
2325
2327{
2328 apr_finfo_t finfo;
2329
2330 if (apr_stat(&finfo, path, APR_FINFO_TYPE, p) != APR_SUCCESS)
2331 return 0; /* in error condition, just return no */
2332
2333 return (finfo.filetype == APR_DIR);
2334}
2335
2337{
2338 apr_finfo_t finfo;
2339
2341 return 0; /* in error condition, just return no */
2342
2343 return (finfo.filetype == APR_DIR);
2344}
2345
2347 const char *src2)
2348{
2350 char *path;
2351
2352 len1 = strlen(src1);
2353 len2 = strlen(src2);
2354 /* allocate +3 for '/' delimiter, trailing NULL and overallocate
2355 * one extra byte to allow the caller to add a trailing '/'
2356 */
2357 path = (char *)apr_palloc(a, len1 + len2 + 3);
2358 if (len1 == 0) {
2359 *path = '/';
2360 memcpy(path + 1, src2, len2 + 1);
2361 }
2362 else {
2363 char *next;
2364 memcpy(path, src1, len1);
2365 next = path + len1;
2366 if (next[-1] != '/') {
2367 *next++ = '/';
2368 }
2369 memcpy(next, src2, len2 + 1);
2370 }
2371 return path;
2372}
2373
2374/*
2375 * Check for an absoluteURI syntax (see section 3.2 in RFC2068).
2376 */
2377AP_DECLARE(int) ap_is_url(const char *u)
2378{
2379 int x;
2380
2381 for (x = 0; u[x] != ':'; x++) {
2382 if ((!u[x]) ||
2383 ((!apr_isalnum(u[x])) &&
2384 (u[x] != '+') && (u[x] != '-') && (u[x] != '.'))) {
2385 return 0;
2386 }
2387 }
2388
2389 return (x ? 1 : 0); /* If the first character is ':', it's broken, too */
2390}
2391
2392AP_DECLARE(int) ap_ind(const char *s, char c)
2393{
2394 const char *p = ap_strchr_c(s, c);
2395
2396 if (p == NULL)
2397 return -1;
2398 return p - s;
2399}
2400
2401AP_DECLARE(int) ap_rind(const char *s, char c)
2402{
2403 const char *p = ap_strrchr_c(s, c);
2404
2405 if (p == NULL)
2406 return -1;
2407 return p - s;
2408}
2409
2411{
2412 while (*str) {
2413 *str = apr_tolower(*str);
2414 ++str;
2415 }
2416}
2417
2419{
2420 while (*str) {
2421 *str = apr_toupper(*str);
2422 ++str;
2423 }
2424}
2425
2426/*
2427 * We must return a FQDN
2428 */
2430{
2431#ifndef MAXHOSTNAMELEN
2432#define MAXHOSTNAMELEN 256
2433#endif
2434 char str[MAXHOSTNAMELEN + 1];
2435 char *server_hostname = NULL;
2437 char *hostname;
2438
2439 if (apr_gethostname(str, sizeof(str) - 1, a) != APR_SUCCESS) {
2441 "%s: apr_gethostname() failed to determine ServerName",
2443 } else {
2444 str[sizeof(str) - 1] = '\0';
2446 if ( (apr_getnameinfo(&hostname, sockaddr, 0) == APR_SUCCESS) &&
2447 (ap_strchr_c(hostname, '.')) ) {
2448 server_hostname = apr_pstrdup(a, hostname);
2449 return server_hostname;
2450 } else if (ap_strchr_c(str, '.')) {
2451 server_hostname = apr_pstrdup(a, str);
2452 } else {
2454 server_hostname = apr_pstrdup(a, hostname);
2455 }
2456 } else {
2458 "%s: apr_sockaddr_info_get() failed for %s",
2460 }
2461 }
2462
2463 if (!server_hostname)
2464 server_hostname = apr_pstrdup(a, "127.0.0.1");
2465
2467 "%s: Could not reliably determine the server's fully qualified "
2468 "domain name, using %s. Set the 'ServerName' directive globally "
2469 "to suppress this message",
2470 ap_server_argv0, server_hostname);
2471
2472 return server_hostname;
2473}
2474
2475/* simple 'pool' alloc()ing glue to apr_base64.c
2476 */
2478{
2479 char *decoded;
2480
2483
2484 return decoded;
2485}
2486
2488{
2489 char *encoded;
2490 int l = strlen(string);
2491
2492 encoded = (char *) apr_palloc(p, apr_base64_encode_len(l));
2493 apr_base64_encode(encoded, string, l);
2494
2495 return encoded;
2496}
2497
2498/* we want to downcase the type/subtype for comparison purposes
2499 * but nothing else because ;parameter=foo values are case sensitive.
2500 * XXX: in truth we want to downcase parameter names... but really,
2501 * apache has never handled parameters and such correctly. You
2502 * also need to compress spaces and such to be able to compare
2503 * properly. -djg
2504 */
2506{
2507 char *semi;
2508
2509 semi = strchr(str, ';');
2510 if (semi) {
2511 *semi = '\0';
2512 }
2513
2515
2516 if (semi) {
2517 *semi = ';';
2518 }
2519}
2520
2521/*
2522 * Given a string, replace any bare " with \" .
2523 */
2525{
2526 apr_size_t size, extra = 0;
2527 const char *inchr = instring;
2528 char *outchr, *outstring;
2529
2530 /*
2531 * Look through the input string, jogging the length of the output
2532 * string up by an extra byte each time we find an unescaped ".
2533 */
2534 while (*inchr != '\0') {
2535 if (*inchr == '"') {
2536 extra++;
2537 }
2538 /*
2539 * If we find a slosh, and it's not the last byte in the string,
2540 * it's escaping something - advance past both bytes.
2541 */
2542 else if ((*inchr == '\\') && (inchr[1] != '\0')) {
2543 inchr++;
2544 }
2545 inchr++;
2546 }
2547
2548 if (!extra) {
2549 return apr_pstrdup(p, instring);
2550 }
2551
2552 /* How large will the string become, once we escaped all the quotes?
2553 * The tricky cases are
2554 * - an `instring` that is already longer than `ptrdiff_t`
2555 * can hold (which is an undefined case in C, as C defines ptrdiff_t as
2556 * a signed difference between pointers into the same array and one index
2557 * beyond).
2558 * - an `instring` that, including the `extra` chars we want to add, becomes
2559 * even larger than apr_size_t can handle.
2560 * Since this function was not designed to ever return NULL for failure, we
2561 * can only trigger a hard assertion failure. It seems more a programming
2562 * mistake (or failure to verify the input causing this) that leads to this
2563 * situation.
2564 */
2565 ap_assert(inchr - instring > 0);
2566 size = ((apr_size_t)(inchr - instring)) + 1;
2567 ap_assert(size + extra > size);
2568
2570 inchr = instring;
2571 outchr = outstring;
2572 /*
2573 * Now copy the input string to the output string, inserting a slosh
2574 * in front of every " that doesn't already have one.
2575 */
2576 while (*inchr != '\0') {
2577 if (*inchr == '"') {
2578 *outchr++ = '\\';
2579 }
2580 else if ((*inchr == '\\') && (inchr[1] != '\0')) {
2581 *outchr++ = *inchr++;
2582 }
2583 *outchr++ = *inchr++;
2584 }
2585 *outchr = '\0';
2586 return outstring;
2587}
2588
2589/*
2590 * Given a string, append the PID deliminated by delim.
2591 * Usually used to create a pid-appended filepath name
2592 * (eg: /a/b/foo -> /a/b/foo.6726). A function, and not
2593 * a macro, to avoid unistd.h dependency
2594 */
2595AP_DECLARE(char *) ap_append_pid(apr_pool_t *p, const char *string,
2596 const char *delim)
2597{
2598 return apr_psprintf(p, "%s%s%" APR_PID_T_FMT, string,
2599 delim, getpid());
2600
2601}
2602
2621#define CHECK_OVERFLOW(a, b) if (a > b) return APR_EGENERAL
2623 const char *timeout_parameter,
2625 const char *default_time_unit)
2626{
2627 char *endp;
2628 const char *time_str;
2631
2632 tout = apr_strtoi64(timeout_parameter, &endp, 10);
2633 if (errno) {
2634 return errno;
2635 }
2636 if (!endp || !*endp) {
2637 time_str = default_time_unit;
2638 }
2639 else {
2640 time_str = endp;
2641 }
2642
2643 if (tout < 0) {
2644 return APR_EGENERAL;
2645 }
2646
2647 switch (*time_str) {
2648 /* Time is in seconds */
2649 case 's':
2652 break;
2653 /* Time is in hours */
2654 case 'h':
2656 check = apr_time_from_sec(tout * 3600);
2657 break;
2658 case 'm':
2659 switch (*(++time_str)) {
2660 /* Time is in milliseconds */
2661 case 's':
2664 break;
2665 /* Time is in minutes */
2666 case 'i':
2669 break;
2670 default:
2671 return APR_EGENERAL;
2672 }
2673 break;
2674 default:
2675 return APR_EGENERAL;
2676 }
2677
2679 return APR_SUCCESS;
2680}
2681#undef CHECK_OVERFLOW
2682
2684{
2685 char *end;
2686
2687 return (apr_isdigit(*str)
2688 && apr_strtoff(len, str, &end, 10) == APR_SUCCESS
2689 && *end == '\0');
2690}
2691
2699{
2700 apr_off_t cl;
2701 const char *cls;
2702
2703 return (!r->header_only
2704 && (r->kept_body
2705 || apr_table_get(r->headers_in, "Transfer-Encoding")
2706 || ((cls = apr_table_get(r->headers_in, "Content-Length"))
2707 && ap_parse_strict_length(&cl, cls) && cl > 0)));
2708}
2709
2711{
2712 void **ptr = (void **)data_;
2713 *ptr = NULL;
2714 return APR_SUCCESS;
2715}
2716
2718
2719 for ( ; *src; src++, dest++)
2720 {
2721 if (!apr_isprint(*src))
2722 *dest = 'x';
2723 else if (!apr_isalnum(*src))
2724 *dest = '_';
2725 else
2726 *dest = (char)*src;
2727 }
2728 *dest = '\0';
2729 return APR_SUCCESS;
2730
2731}
2732
2734 const char **dest)
2735{
2736 char *new = apr_palloc(p, strlen(src)+1);
2737 if (!new)
2738 return APR_ENOMEM;
2739 *dest = new;
2740 return ap_str2_alnum(src, new);
2741}
2742
2776/* form parsing stuff */
2786
2788 apr_array_header_t **ptr,
2790{
2792 int seen_eos = 0;
2793 char buffer[HUGE_STRING_LEN + 1];
2794 const char *ct;
2795 apr_size_t offset = 0;
2800 char escaped_char[2] = { 0 };
2801
2802 *ptr = pairs;
2803
2804 /* sanity check - we only support forms for now */
2805 ct = apr_table_get(r->headers_in, "Content-Type");
2806 if (!ct || ap_cstr_casecmpn("application/x-www-form-urlencoded", ct, 33)) {
2807 return ap_discard_request_body(r);
2808 }
2809
2810 if (usize > APR_SIZE_MAX >> 1)
2811 size = APR_SIZE_MAX >> 1;
2812 else
2813 size = usize;
2814
2815 if (!f) {
2816 f = r->input_filters;
2817 }
2818
2820 do {
2821 apr_bucket *bucket = NULL, *last = NULL;
2822
2823 int rv = ap_get_brigade(f, bb, AP_MODE_READBYTES,
2825 if (rv != APR_SUCCESS) {
2828 }
2829
2830 for (bucket = APR_BRIGADE_FIRST(bb);
2831 bucket != APR_BRIGADE_SENTINEL(bb);
2832 last = bucket, bucket = APR_BUCKET_NEXT(bucket)) {
2833 const char *data;
2835
2836 if (last) {
2838 }
2839 if (APR_BUCKET_IS_EOS(bucket)) {
2840 seen_eos = 1;
2841 break;
2842 }
2843 if (bucket->length == 0) {
2844 continue;
2845 }
2846
2847 rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
2848 if (rv != APR_SUCCESS) {
2850 return HTTP_BAD_REQUEST;
2851 }
2852
2853 slide = len;
2854 while (state != FORM_ABORT && slide-- > 0 && size >= 0 && num != 0) {
2855 char c = *data++;
2856 if ('+' == c) {
2857 c = ' ';
2858 }
2859 else if ('&' == c) {
2860 state = FORM_AMP;
2861 }
2862 if ('%' == c) {
2864 continue;
2865 }
2866 if (FORM_PERCENTA == percent) {
2867 escaped_char[0] = c;
2869 continue;
2870 }
2871 if (FORM_PERCENTB == percent) {
2872 escaped_char[1] = c;
2873 c = x2c(escaped_char);
2875 }
2876 switch (state) {
2877 case FORM_AMP:
2878 if (pair) {
2879 const char *tmp = apr_pmemdup(r->pool, buffer, offset);
2882 }
2883 state = FORM_NAME;
2884 pair = NULL;
2885 offset = 0;
2886 num--;
2887 break;
2888 case FORM_NAME:
2889 if (offset < HUGE_STRING_LEN) {
2890 if ('=' == c) {
2892 pair->name = apr_pstrmemdup(r->pool, buffer, offset);
2894 state = FORM_VALUE;
2895 offset = 0;
2896 }
2897 else {
2898 buffer[offset++] = c;
2899 size--;
2900 }
2901 }
2902 else {
2903 state = FORM_ABORT;
2904 }
2905 break;
2906 case FORM_VALUE:
2907 if (offset >= HUGE_STRING_LEN) {
2908 const char *tmp = apr_pmemdup(r->pool, buffer, offset);
2911 offset = 0;
2912 }
2913 buffer[offset++] = c;
2914 size--;
2915 break;
2916 default:
2917 break;
2918 }
2919 }
2920
2921 }
2922
2924 } while (!seen_eos);
2925
2926 if (FORM_ABORT == state || size < 0 || num == 0) {
2928 }
2929 else if (FORM_VALUE == state && pair && offset > 0) {
2930 const char *tmp = apr_pmemdup(r->pool, buffer, offset);
2933 }
2934
2935 return OK;
2936
2937}
2938
2939#define VARBUF_SMALL_SIZE 2048
2940#define VARBUF_MAX_SIZE (APR_SIZE_MAX - 1 - \
2941 APR_ALIGN_DEFAULT(sizeof(struct ap_varbuf_info)))
2942
2947
2949{
2950 struct ap_varbuf_info *info = info_;
2951 info->node->next = NULL;
2952 apr_allocator_free(info->allocator, info->node);
2953 return APR_SUCCESS;
2954}
2955
2956static const char nul = '\0';
2957static char * const varbuf_empty = (char *)&nul;
2958
2961{
2962 vb->buf = varbuf_empty;
2963 vb->avail = 0;
2965 vb->pool = p;
2966 vb->info = NULL;
2967
2969}
2970
2972{
2975 struct ap_varbuf_info *new_info;
2976 char *new;
2977
2978 AP_DEBUG_ASSERT(vb->strlen == AP_VARBUF_UNKNOWN || vb->avail >= vb->strlen);
2979
2980 if (new_len <= vb->avail)
2981 return;
2982
2983 if (new_len < 2 * vb->avail && vb->avail < VARBUF_MAX_SIZE/2) {
2984 /* at least double the size, to avoid repeated reallocations */
2985 new_len = 2 * vb->avail;
2986 }
2987 else if (new_len > VARBUF_MAX_SIZE) {
2991 return;
2992 }
2993
2994 new_len++; /* add space for trailing \0 */
2995 if (new_len <= VARBUF_SMALL_SIZE) {
2997 new = apr_palloc(vb->pool, new_len);
2998 if (vb->avail && vb->strlen != 0) {
2999 AP_DEBUG_ASSERT(vb->buf != NULL);
3001 if (new == vb->buf + vb->avail + 1) {
3002 /* We are lucky: the new memory lies directly after our old
3003 * buffer, we can now use both.
3004 */
3005 vb->avail += new_len;
3006 return;
3007 }
3008 else {
3009 /* copy up to vb->strlen + 1 bytes */
3010 memcpy(new, vb->buf, vb->strlen == AP_VARBUF_UNKNOWN ?
3011 vb->avail + 1 : vb->strlen + 1);
3012 }
3013 }
3014 else {
3015 *new = '\0';
3016 }
3017 vb->avail = new_len - 1;
3018 vb->buf = new;
3019 return;
3020 }
3021
3022 /* The required block is rather larger. Use allocator directly so that
3023 * the memory can be freed independently from the pool. */
3025 /* Happens if APR was compiled with APR_POOL_DEBUG */
3026 if (allocator == NULL) {
3029 }
3030 if (new_len <= VARBUF_MAX_SIZE)
3032 new_len + APR_ALIGN_DEFAULT(sizeof(*new_info)));
3033 if (!new_node) {
3037 return;
3038 }
3039 new_info = (struct ap_varbuf_info *)new_node->first_avail;
3040 new_node->first_avail += APR_ALIGN_DEFAULT(sizeof(*new_info));
3041 new_info->node = new_node;
3042 new_info->allocator = allocator;
3043 new = new_node->first_avail;
3044 AP_DEBUG_ASSERT(new_node->endp - new_node->first_avail >= new_len);
3045 new_len = new_node->endp - new_node->first_avail;
3046
3047 if (vb->avail && vb->strlen != 0)
3048 memcpy(new, vb->buf, vb->strlen == AP_VARBUF_UNKNOWN ?
3049 vb->avail + 1 : vb->strlen + 1);
3050 else
3051 *new = '\0';
3052 if (vb->info)
3056 vb->info = new_info;
3057 vb->buf = new;
3058 vb->avail = new_len - 1;
3059}
3060
3061AP_DECLARE(void) ap_varbuf_strmemcat(struct ap_varbuf *vb, const char *str,
3062 int len)
3063{
3064 if (len == 0)
3065 return;
3066 if (!vb->avail) {
3067 ap_varbuf_grow(vb, len);
3068 memcpy(vb->buf, str, len);
3069 vb->buf[len] = '\0';
3070 vb->strlen = len;
3071 return;
3072 }
3073 if (vb->strlen == AP_VARBUF_UNKNOWN)
3074 vb->strlen = strlen(vb->buf);
3075 ap_varbuf_grow(vb, vb->strlen + len);
3076 memcpy(vb->buf + vb->strlen, str, len);
3077 vb->strlen += len;
3078 vb->buf[vb->strlen] = '\0';
3079}
3080
3082{
3083 if (vb->info) {
3085 vb->info = NULL;
3086 }
3087 vb->buf = NULL;
3088}
3089
3091 const char *prepend, apr_size_t prepend_len,
3092 const char *append, apr_size_t append_len,
3094{
3095 apr_size_t i = 0;
3096 struct iovec vec[3];
3097
3098 if (prepend) {
3099 vec[i].iov_base = (void *)prepend;
3100 vec[i].iov_len = prepend_len;
3101 i++;
3102 }
3103 if (buf->avail && buf->strlen) {
3104 if (buf->strlen == AP_VARBUF_UNKNOWN)
3105 buf->strlen = strlen(buf->buf);
3106 vec[i].iov_base = (void *)buf->buf;
3107 vec[i].iov_len = buf->strlen;
3108 i++;
3109 }
3110 if (append) {
3111 vec[i].iov_base = (void *)append;
3112 vec[i].iov_len = append_len;
3113 i++;
3114 }
3115 if (i)
3116 return apr_pstrcatv(p, vec, i, new_len);
3117
3118 if (new_len)
3119 *new_len = 0;
3120 return "";
3121}
3122
3124 const char *input,
3125 const char *source,
3128 apr_size_t maxlen)
3129{
3130 return regsub_core(NULL, NULL, vb, input, source, nmatch, pmatch, maxlen);
3131}
3132
3133static const char * const oom_message = "[crit] Memory allocation failed, "
3134 "aborting process." APR_EOL_STR;
3135
3137{
3138 int written, count = strlen(oom_message);
3139 const char *buf = oom_message;
3140 do {
3141 written = write(STDERR_FILENO, buf, count);
3142 if (written == count)
3143 break;
3144 if (written > 0) {
3145 buf += written;
3146 count -= written;
3147 }
3148 } while (written >= 0 || errno == EINTR);
3149 abort();
3150}
3151
3153{
3154 void *p = malloc(size);
3155 if (p == NULL && size != 0)
3157 return p;
3158}
3159
3160AP_DECLARE(void *) ap_calloc(size_t nelem, size_t size)
3161{
3162 void *p = calloc(nelem, size);
3163 if (p == NULL && nelem != 0 && size != 0)
3165 return p;
3166}
3167
3168AP_DECLARE(void *) ap_realloc(void *ptr, size_t size)
3169{
3170 void *p = realloc(ptr, size);
3171 if (p == NULL && size != 0)
3173 return p;
3174}
3175
3176#if APR_HAS_THREADS
3177
3178#if APR_VERSION_AT_LEAST(1,8,0) && !defined(AP_NO_THREAD_LOCAL)
3179
3180#define ap_thread_current_create apr_thread_current_create
3181
3182#else /* APR_VERSION_AT_LEAST(1,8,0) && !defined(AP_NO_THREAD_LOCAL) */
3183
3184#if AP_HAS_THREAD_LOCAL
3185
3186struct thread_ctx {
3188 void *data;
3189};
3190
3192
3193static void *APR_THREAD_FUNC thread_start(apr_thread_t *thread, void *data)
3194{
3195 struct thread_ctx *ctx = data;
3196
3197 current_thread = thread;
3198 return ctx->func(thread, ctx->data);
3199}
3200
3204 void *data, apr_pool_t *pool)
3205{
3206 struct thread_ctx *ctx = apr_palloc(pool, sizeof(*ctx));
3207
3208 ctx->func = func;
3209 ctx->data = data;
3210 return apr_thread_create(thread, attr, thread_start, ctx, pool);
3211}
3212
3213#endif /* AP_HAS_THREAD_LOCAL */
3214
3218{
3219 apr_status_t rv;
3223 apr_pool_t *p;
3224
3225 *current = ap_thread_current();
3226 if (*current) {
3227 return APR_EEXIST;
3228 }
3229
3231 if (rv != APR_SUCCESS) {
3232 if (abort_fn)
3233 abort_fn(rv);
3234 return rv;
3235 }
3237 if (rv != APR_SUCCESS) {
3239 return rv;
3240 }
3242
3244 rv = apr_os_thread_put(current, &osthd, p);
3245 if (rv != APR_SUCCESS) {
3247 return rv;
3248 }
3249
3250#if AP_HAS_THREAD_LOCAL
3251 current_thread = *current;
3252#endif
3253 return APR_SUCCESS;
3254}
3255
3257{
3258#if AP_HAS_THREAD_LOCAL
3260#endif
3261}
3262
3264{
3265#if AP_HAS_THREAD_LOCAL
3266 return current_thread;
3267#else
3268 return NULL;
3269#endif
3270}
3271
3272#endif /* APR_VERSION_AT_LEAST(1,8,0) && !defined(AP_NO_THREAD_LOCAL) */
3273
3275{
3276 apr_thread_t *thd = arg;
3278 return APR_SUCCESS;
3279}
3280
3283{
3284 apr_status_t rv;
3286
3287 /* Create an apr_thread_t for the main child thread to set up its Thread
3288 * Local Storage. Since it's detached and won't apr_thread_exit(), destroy
3289 * its pool before exiting via a cleanup of the given pool.
3290 */
3291 if ((rv = apr_threadattr_create(&attr, pool))
3292 || (rv = apr_threadattr_detach_set(attr, 1))
3293 || (rv = ap_thread_current_create(thread, attr, pool))) {
3294 *thread = NULL;
3295 return rv;
3296 }
3297
3300 return APR_SUCCESS;
3301}
3302
3303#endif /* APR_HAS_THREADS */
3304
3306{
3307 int i, j, server_limit, thread_limit;
3308 int ready = 0;
3309 int busy = 0;
3310 int total;
3312
3313 /* preload errored fields, we overwrite */
3314 ld->idle = -1;
3315 ld->busy = -1;
3316 ld->bytes_served = 0;
3317 ld->access_count = 0;
3318
3322
3323 for (i = 0; i < server_limit; i++) {
3326
3327 for (j = 0; j < thread_limit; j++) {
3328 int res;
3329 worker_score *ws = NULL;
3331 res = ws->status;
3332
3333 if (!ps->quiescing && ps->pid) {
3334 if (res == SERVER_READY && ps->generation == mpm_generation) {
3335 ready++;
3336 }
3337 else if (res != SERVER_DEAD &&
3339 ps->generation == mpm_generation) {
3340 busy++;
3341 }
3342 }
3343
3344 if (ap_extended_status && !ps->quiescing && ps->pid) {
3345 if (ws->access_count != 0
3346 || (res != SERVER_READY && res != SERVER_DEAD)) {
3347 ld->access_count += ws->access_count;
3348 ld->bytes_served += ws->bytes_served;
3349 }
3350 }
3351 }
3352 }
3353 total = busy + ready;
3354 if (total) {
3355 ld->idle = ready * 100 / total;
3356 ld->busy = busy * 100 / total;
3357 }
3358}
3359
3361{
3362 /* preload errored fields, we overwrite */
3363 ld->loadavg = -1.0;
3364 ld->loadavg5 = -1.0;
3365 ld->loadavg15 = -1.0;
3366
3367#if HAVE_GETLOADAVG
3368 {
3369 double la[3];
3370 int num;
3371
3372 num = getloadavg(la, 3);
3373 if (num > 0) {
3374 ld->loadavg = (float)la[0];
3375 }
3376 if (num > 1) {
3377 ld->loadavg5 = (float)la[1];
3378 }
3379 if (num > 2) {
3380 ld->loadavg15 = (float)la[2];
3381 }
3382 }
3383#endif
3384}
3385
3387 const char *cmd,
3388 const char * const * argv)
3389{
3390 char buf[MAX_STRING_LEN];
3391 apr_procattr_t *procattr;
3393 apr_file_t *fp;
3394 apr_size_t nbytes = 1;
3395 char c;
3396 int k;
3397
3398 if (apr_procattr_create(&procattr, p) != APR_SUCCESS)
3399 return NULL;
3402 return NULL;
3403 if (apr_procattr_dir_set(procattr,
3405 return NULL;
3407 return NULL;
3408 proc = apr_pcalloc(p, sizeof(apr_proc_t));
3409 if (apr_proc_create(proc, cmd, argv, NULL, procattr, p) != APR_SUCCESS)
3410 return NULL;
3411 fp = proc->out;
3412
3413 if (fp == NULL)
3414 return NULL;
3415 /* XXX: we are reading 1 byte at a time here */
3416 for (k = 0; apr_file_read(fp, &c, &nbytes) == APR_SUCCESS
3417 && nbytes == 1 && (k < MAX_STRING_LEN-1) ; ) {
3418 if (c == '\n' || c == '\r')
3419 break;
3420 buf[k++] = c;
3421 }
3422 buf[k] = '\0';
3423 apr_file_close(fp);
3424
3425 return apr_pstrndup(p, buf, k);
3426}
3427
3429 const char *s,
3430 int start)
3431{
3432 if (start >= 0) {
3433 int i;
3434
3435 for (i = start; i < array->nelts; i++) {
3436 const char *p = APR_ARRAY_IDX(array, i, const char *);
3437 if (!strcmp(p, s)) {
3438 return i;
3439 }
3440 }
3441 }
3442
3443 return -1;
3444}
3445
3447 const char *s)
3448{
3449 return (ap_array_str_index(array, s, 0) >= 0);
3450}
3451
3452#if !APR_CHARSET_EBCDIC
3453/*
3454 * Our own known-fast translation table for casecmp by character.
3455 * Only ASCII alpha characters 41-5A are folded to 61-7A, other
3456 * octets (such as extended latin alphabetics) are never case-folded.
3457 * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
3458 */
3459static const short ucharmap[] = {
3460 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
3461 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
3462 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
3463 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
3464 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
3465 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
3466 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
3467 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
3468 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
3469 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
3470 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
3471 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
3472 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
3473 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
3474 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
3475 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
3476 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
3477 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
3478 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
3479 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
3480 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
3481 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
3482 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
3483 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
3484 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
3485 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
3486 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
3487 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
3488 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
3489 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
3490 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
3491 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
3492};
3493#else /* APR_CHARSET_EBCDIC */
3494/*
3495 * Derived from apr-iconv/ccs/cp037.c for EBCDIC case comparison,
3496 * provides unique identity of every char value (strict ISO-646
3497 * conformance, arbitrary election of an ISO-8859-1 ordering, and
3498 * very arbitrary control code assignments into C1 to achieve
3499 * identity and a reversible mapping of code points),
3500 * then folding the equivalences of ASCII 41-5A into 61-7A,
3501 * presenting comparison results in a somewhat ISO/IEC 10646
3502 * (ASCII-like) order, depending on the EBCDIC code page in use.
3503 *
3504 * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
3505 */
3506static const short ucharmap[] = {
3507 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
3508 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
3509 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
3510 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
3511 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
3512 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
3513 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
3514 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
3515 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,
3516 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
3517 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,
3518 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
3519 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,
3520 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
3521 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,
3522 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
3523 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
3524 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,
3525 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
3526 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
3527 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
3528 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,
3529 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,
3530 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,
3531 0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
3532 0x68, 0x69, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,
3533 0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
3534 0x71, 0x72, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,
3535 0x5C, 0xF7, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
3536 0x79, 0x7A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
3537 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
3538 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F
3539};
3540#endif
3541
3542AP_DECLARE(int) ap_cstr_casecmp(const char *s1, const char *s2)
3543{
3544 const unsigned char *str1 = (const unsigned char *)s1;
3545 const unsigned char *str2 = (const unsigned char *)s2;
3546 for (;;)
3547 {
3548 const int c1 = (int)(*str1);
3549 const int c2 = (int)(*str2);
3550 const int cmp = ucharmap[c1] - ucharmap[c2];
3551 /* Not necessary to test for !c2, this is caught by cmp */
3552 if (cmp || !c1)
3553 return cmp;
3554 str1++;
3555 str2++;
3556 }
3557}
3558
3559AP_DECLARE(int) ap_cstr_casecmpn(const char *s1, const char *s2, apr_size_t n)
3560{
3561 const unsigned char *str1 = (const unsigned char *)s1;
3562 const unsigned char *str2 = (const unsigned char *)s2;
3563 while (n--)
3564 {
3565 const int c1 = (int)(*str1);
3566 const int c2 = (int)(*str2);
3567 const int cmp = ucharmap[c1] - ucharmap[c2];
3568 /* Not necessary to test for !c2, this is caught by cmp */
3569 if (cmp || !c1)
3570 return cmp;
3571 str1++;
3572 str2++;
3573 }
3574 return 0;
3575}
3576
3577typedef struct {
3578 const char *fname;
3579} fnames;
3580
3581static int fname_alphasort(const void *fn1, const void *fn2)
3582{
3583 const fnames *f1 = fn1;
3584 const fnames *f2 = fn2;
3585
3586 return strcmp(f1->fname, f2->fname);
3587}
3588
3590 const char *(*cb)(ap_dir_match_t *w, const char *fname), void *ctx)
3591{
3592 ap_dir_match_t *w = apr_palloc(cmd->temp_pool, sizeof(*w));
3593
3594 w->prefix = apr_pstrcat(cmd->pool, cmd->cmd->name, ": ", NULL);
3595 w->p = cmd->pool;
3596 w->ptemp = cmd->temp_pool;
3597 w->flags = flags;
3598 w->cb = cb;
3599 w->ctx = ctx;
3600 w->depth = 0;
3601
3602 return w;
3603}
3604
3606{
3607 const char *error;
3608 apr_status_t rv;
3609
3611 apr_dir_t *dirp;
3613 int current;
3615 fnames *fnew;
3616 char *path = apr_pstrdup(w->ptemp, fname);
3617
3618 if (++w->depth > AP_MAX_FNMATCH_DIR_DEPTH) {
3619 return apr_psprintf(w->p, "%sDirectory '%s' exceeds the maximum include "
3620 "directory nesting level of %u. You have "
3621 "probably a recursion somewhere.", w->prefix ? w->prefix : "", path,
3623 }
3624
3625 /*
3626 * first course of business is to grok all the directory
3627 * entries here and store 'em away. Recall we need full pathnames
3628 * for this.
3629 */
3630 rv = apr_dir_open(&dirp, path, w->ptemp);
3631 if (rv != APR_SUCCESS) {
3632 return apr_psprintf(w->p, "%sCould not open directory %s: %pm",
3633 w->prefix ? w->prefix : "", path, &rv);
3634 }
3635
3636 candidates = apr_array_make(w->ptemp, 1, sizeof(fnames));
3638 /* strip out '.' and '..' */
3639 if (strcmp(dirent.name, ".")
3640 && strcmp(dirent.name, "..")) {
3642 fnew->fname = ap_make_full_path(w->ptemp, path, dirent.name);
3643 }
3644 }
3645
3647 if (candidates->nelts != 0) {
3648 qsort((void *) candidates->elts, candidates->nelts,
3649 sizeof(fnames), fname_alphasort);
3650
3651 /*
3652 * Now recurse these... we handle errors and subdirectories
3653 * via the recursion, which is nice
3654 */
3655 for (current = 0; current < candidates->nelts; ++current) {
3656 fnew = &((fnames *) candidates->elts)[current];
3657 error = ap_dir_nofnmatch(w, fnew->fname);
3658 if (error) {
3659 return error;
3660 }
3661 }
3662 }
3663
3664 w->depth--;
3665
3666 return NULL;
3667 }
3668 else if (w->flags & AP_DIR_FLAG_OPTIONAL) {
3669 /* If the optional flag is set (like for IncludeOptional) we can
3670 * tolerate that no file or directory is present and bail out.
3671 */
3672 apr_finfo_t finfo;
3673 if (apr_stat(&finfo, fname, APR_FINFO_TYPE, w->ptemp) != APR_SUCCESS
3674 || finfo.filetype == APR_NOFILE)
3675 return NULL;
3676 }
3677
3678 return w->cb(w, fname);
3679}
3680
3681AP_DECLARE(const char *)ap_dir_fnmatch(ap_dir_match_t *w, const char *path,
3682 const char *fname)
3683{
3684 const char *rest;
3685 apr_status_t rv;
3686 apr_dir_t *dirp;
3689 fnames *fnew;
3690 int current;
3691
3692 /* find the first part of the filename */
3693 rest = ap_strchr_c(fname, '/');
3694 if (rest) {
3696 rest++;
3697 }
3698
3699 /* optimisation - if the filename isn't a wildcard, process it directly */
3700 if (!apr_fnmatch_test(fname)) {
3702 if (!rest) {
3703 return ap_dir_nofnmatch(w, path);
3704 }
3705 else {
3706 return ap_dir_fnmatch(w, path, rest);
3707 }
3708 }
3709
3710 /*
3711 * first course of business is to grok all the directory
3712 * entries here and store 'em away. Recall we need full pathnames
3713 * for this.
3714 */
3715 rv = apr_dir_open(&dirp, path, w->ptemp);
3716 if (rv != APR_SUCCESS) {
3717 /* If the directory doesn't exist and the optional flag is set
3718 * there is no need to return an error.
3719 */
3720 if (rv == APR_ENOENT && (w->flags & AP_DIR_FLAG_OPTIONAL)) {
3721 return NULL;
3722 }
3723 return apr_psprintf(w->p, "%sCould not open directory %s: %pm",
3724 w->prefix ? w->prefix : "", path, &rv);
3725 }
3726
3727 candidates = apr_array_make(w->ptemp, 1, sizeof(fnames));
3729 /* strip out '.' and '..' */
3730 if (strcmp(dirent.name, ".")
3731 && strcmp(dirent.name, "..")
3732 && (apr_fnmatch(fname, dirent.name,
3734 const char *full_path = ap_make_full_path(w->ptemp, path, dirent.name);
3735 /* If matching internal to path, and we happen to match something
3736 * other than a directory, skip it
3737 */
3738 if (rest && (dirent.filetype != APR_DIR)) {
3739 continue;
3740 }
3742 fnew->fname = full_path;
3743 }
3744 }
3745
3747 if (candidates->nelts != 0) {
3748 const char *error;
3749
3750 qsort((void *) candidates->elts, candidates->nelts,
3751 sizeof(fnames), fname_alphasort);
3752
3753 /*
3754 * Now recurse these... we handle errors and subdirectories
3755 * via the recursion, which is nice
3756 */
3757 for (current = 0; current < candidates->nelts; ++current) {
3758 fnew = &((fnames *) candidates->elts)[current];
3759 if (!rest) {
3760 error = ap_dir_nofnmatch(w, fnew->fname);
3761 }
3762 else {
3763 error = ap_dir_fnmatch(w, fnew->fname, rest);
3764 }
3765 if (error) {
3766 return error;
3767 }
3768 }
3769 }
3770 else {
3771
3772 if (!(w->flags & AP_DIR_FLAG_OPTIONAL)) {
3773 return apr_psprintf(w->p, "%sNo matches for the wildcard '%s' in '%s', failing",
3774 w->prefix ? w->prefix : "", fname, path);
3775 }
3776 }
3777
3778 return NULL;
3779}
Symbol export macros and hook functions.
#define AP_DECLARE_NONSTD(type)
Definition ap_config.h:77
#define AP_DECLARE(type)
Definition ap_config.h:67
Apache Multi-Processing Module library.
int n
Definition ap_regex.h:278
const char * pattern
Definition ap_regex.h:243
const char apr_size_t ap_regmatch_t * pmatch
Definition ap_regex.h:172
const char int cflags
Definition ap_regex.h:159
const ap_regex_t * preg
Definition ap_regex.h:197
const char apr_size_t len
Definition ap_regex.h:187
const char apr_size_t nmatch
Definition ap_regex.h:172
@ AP_REG_ESPACE
Definition ap_regex.h:102
#define NETWARE
APR-UTIL Base64 Encoding.
#define TEST_CHAR(c, f)
Definition apr_escape.c:39
APR FNMatch Functions.
APR general purpose library routines.
#define f2(x, y, z)
Definition apr_sha1.c:64
#define f1(x, y, z)
Definition apr_sha1.c:63
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
APR Standard Headers Support.
apr_status_t ap_pool_cleanup_set_null(void *data_)
Definition util.c:2710
const char * ap_pcfg_strerror(apr_pool_t *p, ap_configfile_t *cfp, apr_status_t rc)
Definition util.c:1063
int ap_cfg_closefile(ap_configfile_t *cfp)
Definition util.c:931
apr_status_t ap_pcfg_openfile(ap_configfile_t **ret_cfg, apr_pool_t *p, const char *name)
Definition util.c:957
apr_status_t ap_cfg_getc(char *ch, ap_configfile_t *cfp)
Definition util.c:1055
const char * hostname
request_rec int int apr_table_t const char * path
const char server_rec server_rec ** ps
request_rec * r
apr_status_t ap_cfg_getline(char *buf, apr_size_t bufsize, ap_configfile_t *cfp)
Definition util.c:1198
#define HUGE_STRING_LEN
Definition httpd.h:303
#define MAX_STRING_LEN
Definition httpd.h:300
#define AP_MAX_REG_MATCH
Definition httpd.h:309
#define OK
Definition httpd.h:456
#define ap_is_default_port(port, r)
Definition httpd.h:287
apr_status_t ap_get_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes)
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_NOTICE
Definition http_log.h:69
#define APLOG_STARTUP
Definition http_log.h:105
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define ap_log_perror
Definition http_log.h:412
#define APLOG_WARNING
Definition http_log.h:68
#define APLOG_ALERT
Definition http_log.h:65
#define APLOG_DEBUG
Definition http_log.h:71
const char * ap_server_argv0
Definition config.c:60
const unsigned char * buf
Definition util_md5.h:50
int ap_map_http_request_error(apr_status_t rv, int status)
int ap_discard_request_body(request_rec *r)
apr_status_t ap_varbuf_cfg_getline(struct ap_varbuf *vb, ap_configfile_t *cfp, apr_size_t max_len)
Definition util.c:1207
void ap_varbuf_free(struct ap_varbuf *vb)
Definition util.c:3081
void ap_varbuf_grow(struct ap_varbuf *vb, apr_size_t new_len)
Definition util.c:2971
void ap_varbuf_strmemcat(struct ap_varbuf *vb, const char *str, int len)
Definition util.c:3061
#define AP_VARBUF_UNKNOWN
Definition util_varbuf.h:43
apr_status_t ap_varbuf_regsub(struct ap_varbuf *vb, const char *input, const char *source, apr_size_t nmatch, ap_regmatch_t pmatch[], apr_size_t maxlen)
Definition util.c:3123
char * ap_varbuf_pdup(apr_pool_t *p, struct ap_varbuf *buf, const char *prepend, apr_size_t prepend_len, const char *append, apr_size_t append_len, apr_size_t *new_len)
Definition util.c:3090
void ap_varbuf_init(apr_pool_t *p, struct ap_varbuf *vb, apr_size_t init_size)
Definition util.c:2959
const char apr_port_t port
Definition http_vhost.h:125
void const char * arg
Definition http_vhost.h:63
#define LF
Definition httpd.h:720
#define CR
Definition httpd.h:722
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOSPC
Definition apr_errno.h:676
#define APR_EBADF
Definition apr_errno.h:704
#define APR_EOF
Definition apr_errno.h:461
#define APR_ENOMEM
Definition apr_errno.h:683
#define APR_ENOENT
Definition apr_errno.h:662
#define APR_EINVAL
Definition apr_errno.h:711
#define APR_EEXIST
Definition apr_errno.h:648
unsigned int count
Definition apr_md5.h:152
apr_file_t * f
#define APR_BRIGADE_INSERT_TAIL(b, e)
apr_file_t apr_off_t start
#define APR_BUCKET_NEXT(e)
#define APR_BRIGADE_SENTINEL(b)
#define apr_bucket_delete(e)
#define APR_BUCKET_IS_EOS(e)
apr_brigade_flush void * ctx
apr_bucket apr_bucket_brigade * a
#define APR_BRIGADE_FIRST(b)
#define apr_bucket_read(e, str, len, block)
int apr_off_t * length
@ APR_BLOCK_READ
Definition apr_buckets.h:58
apr_pool_t apr_dbd_t const char * query
Definition apr_dbd.h:396
apr_pool_t const char apr_dbd_t const char ** error
Definition apr_dbd.h:143
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
const char * src
Definition apr_encode.h:167
const char apr_ssize_t int flags
Definition apr_encode.h:168
const char * url
Definition apr_escape.h:120
const void apr_size_t int colon
Definition apr_escape.h:355
const char apr_ssize_t int partial
Definition apr_escape.h:188
const char apr_ssize_t const char * forbid
Definition apr_escape.h:121
const void apr_size_t srclen
Definition apr_escape.h:355
const char apr_ssize_t const char const char * reserved
Definition apr_escape.h:121
const char apr_ssize_t int quote
Definition apr_escape.h:323
const char apr_ssize_t int toasc
Definition apr_escape.h:254
apr_redis_t * rc
Definition apr_redis.h:173
#define HTTP_BAD_REQUEST
Definition httpd.h:508
#define HTTP_REQUEST_ENTITY_TOO_LARGE
Definition httpd.h:521
#define HTTP_NOT_FOUND
Definition httpd.h:512
char * ap_append_pid(apr_pool_t *p, const char *string, const char *delim)
Definition util.c:2595
#define AP_NORMALIZE_DECODE_UNRESERVED
Definition httpd.h:1789
#define AP_NORMALIZE_ALLOW_RELATIVE
Definition httpd.h:1787
int ap_array_str_index(const apr_array_header_t *array, const char *s, int start)
Definition util.c:3428
char * ap_getword_white(apr_pool_t *p, const char **line)
Definition util.c:751
int ap_strcmp_match(const char *str, const char *expected)
Definition util.c:175
int ap_strcasecmp_match(const char *str, const char *expected)
Definition util.c:199
char * ap_get_exec_line(apr_pool_t *p, const char *cmd, const char *const *argv)
Definition util.c:3386
#define AP_DIR_FLAG_RECURSIVE
Definition httpd.h:2586
char * ap_getword_white_nc(apr_pool_t *atrans, char **line)
Definition util.c:746
#define AP_IS_SLASH(s)
Definition httpd.h:2698
int ap_is_chunked(apr_pool_t *p, const char *line)
Definition util.c:1786
int ap_is_directory(apr_pool_t *p, const char *path)
Definition util.c:2326
char * ap_getword_nulls_nc(apr_pool_t *atrans, char **line, char stop)
Definition util.c:773
char * ap_escape_urlencoded_buffer(char *copy, const char *buffer)
Definition util.c:2102
char * ap_get_local_host(apr_pool_t *a)
Definition util.c:2429
int ap_is_url(const char *u)
Definition util.c:2377
char * ap_make_full_path(apr_pool_t *a, const char *src1, const char *src2)
Definition util.c:2346
int ap_count_dirs(const char *path)
Definition util.c:708
const char * ap_scan_http_token(const char *ptr)
Definition util.c:1664
char * ap_getword_conf2(apr_pool_t *p, const char **line)
Definition util.c:882
int ap_cstr_casecmp(const char *s1, const char *s2)
Definition util.c:3542
const char * ap_parse_token_list_strict(apr_pool_t *p, const char *str_in, apr_array_header_t **tokens, int skip_invalid)
Definition util.c:1562
char * ap_pbase64encode(apr_pool_t *p, char *string)
Definition util.c:2487
#define AP_UNESCAPE_URL_KEEP_SLASHES
Definition httpd.h:1754
char * ap_make_dirstr_prefix(char *d, const char *s, int n)
Definition util.c:669
void ap_get_loadavg(ap_loadavg_t *ld)
Definition util.c:3360
int ap_unescape_url_ex(char *url, unsigned int flags)
Definition util.c:1955
char * ap_getword(apr_pool_t *atrans, const char **line, char stop)
Definition util.c:723
#define AP_SLASHES
Definition httpd.h:2699
char * ap_escape_logitem(apr_pool_t *p, const char *str)
Definition util.c:2183
char * ap_escape_path_segment(apr_pool_t *p, const char *segment)
Definition util.c:2068
int ap_normalize_path(char *path, unsigned int flags)
Definition util.c:489
#define ap_strrchr_c(s, c)
Definition httpd.h:2357
char * ap_strcasestr(const char *s1, const char *s2)
Definition util.c:289
int ap_find_etag_weak(apr_pool_t *p, const char *line, const char *tok)
Definition util.c:1555
char * ap_getword_conf_nc(apr_pool_t *p, char **line)
Definition util.c:828
char * ap_escape_path_segment_buffer(char *copy, const char *segment)
Definition util.c:2049
void ap_bin2hex(const void *src, apr_size_t srclen, char *dest)
Definition util.c:2314
int ap_unescape_urlencoded(char *query)
Definition util.c:1977
#define AP_UNESCAPE_URL_KEEP_UNRESERVED
Definition httpd.h:1752
char * ap_escape_shell_cmd(apr_pool_t *p, const char *str)
Definition util.c:1812
#define ap_strchr_c(s, c)
Definition httpd.h:2353
char * ap_get_token(apr_pool_t *p, const char **accept_line, int accept_white)
Definition util.c:1687
#define AP_NORMALIZE_MERGE_SLASHES
Definition httpd.h:1790
const char * ap_resolve_env(apr_pool_t *p, const char *word)
Definition core.c:1376
char * ap_get_list_item(apr_pool_t *p, const char **field)
Definition util.c:1314
void ap_no2slash(char *name)
Definition util.c:640
int ap_find_etag_strong(apr_pool_t *p, const char *line, const char *tok)
Definition util.c:1546
int ap_unescape_all(char *url)
Definition util.c:2005
apr_status_t ap_str2_alnum(const char *src, char *dest)
Definition util.c:2717
void ap_str_toupper(char *str)
Definition util.c:2418
char * ap_make_dirstr_parent(apr_pool_t *p, const char *s)
Definition util.c:692
int ap_rind(const char *s, char c)
Definition util.c:2401
char * ap_pregsub(apr_pool_t *p, const char *input, const char *source, apr_size_t nmatch, ap_regmatch_t pmatch[])
Definition util.c:457
#define AP_DEBUG_ASSERT(exp)
Definition httpd.h:2283
void ap_abort_on_oom(void)
Definition util.c:3136
int ap_is_rdirectory(apr_pool_t *p, const char *path)
Definition util.c:2336
char * ap_getword_conf2_nc(apr_pool_t *p, char **line)
Definition util.c:877
int ap_request_has_body(request_rec *r)
Definition util.c:2698
char * ap_pbase64decode(apr_pool_t *p, const char *bufcoded)
Definition util.c:2477
const char * ap_scan_vchar_obstext(const char *ptr)
Definition util.c:1674
void ap_content_type_tolower(char *str)
Definition util.c:2505
int ap_find_token(apr_pool_t *p, const char *line, const char *tok)
Definition util.c:1726
void ap_getparents(char *name)
Definition util.c:602
int ap_parse_form_data(request_rec *r, ap_filter_t *f, apr_array_header_t **ptr, apr_size_t num, apr_size_t usize)
Definition util.c:2787
char * ap_getword_nulls(apr_pool_t *atrans, const char **line, char stop)
Definition util.c:779
apr_status_t ap_pregsub_ex(apr_pool_t *p, char **result, const char *input, const char *source, apr_size_t nmatch, ap_regmatch_t pmatch[], apr_size_t maxlen)
Definition util.c:469
int ap_cstr_casecmpn(const char *s1, const char *s2, apr_size_t n)
Definition util.c:3559
void * ap_calloc(size_t nelem, size_t size)
Definition util.c:3160
char * ap_escape_html2(apr_pool_t *p, const char *s, int toasc)
Definition util.c:2131
int ap_is_matchexp(const char *str)
Definition util.c:240
const char * ap_scan_http_field_content(const char *ptr)
Definition util.c:1654
char * ap_ht_time(apr_pool_t *p, apr_time_t t, const char *fmt, int gmt)
Definition util.c:109
#define AP_UNESCAPE_URL_FORBID_SLASHES
Definition httpd.h:1753
void ap_no2slash_ex(char *name, int is_fs_path)
Definition util.c:610
void ap_str_tolower(char *str)
Definition util.c:2410
int ap_parse_strict_length(apr_off_t *len, const char *str)
Definition util.c:2683
char * ap_escape_urlencoded(apr_pool_t *p, const char *buffer)
Definition util.c:2124
apr_size_t ap_escape_errorlog_item(char *dest, const char *source, apr_size_t buflen)
Definition util.c:2251
int ap_array_str_contains(const apr_array_header_t *array, const char *s)
Definition util.c:3446
#define ap_assert(exp)
Definition httpd.h:2271
int ap_unescape_url(char *url)
Definition util.c:1939
char * ap_construct_server(apr_pool_t *p, const char *hostname, apr_port_t port, const request_rec *r)
Definition util.c:1994
int ap_ind(const char *s, char c)
Definition util.c:2392
apr_status_t ap_pstr2_alnum(apr_pool_t *p, const char *src, const char **dest)
Definition util.c:2733
ap_regex_t * ap_pregcomp(apr_pool_t *p, const char *pattern, int cflags)
Definition util.c:262
char * ap_field_noparam(apr_pool_t *p, const char *intype)
Definition util.c:91
const char * ap_size_list_item(const char **field, int *len)
Definition util.c:1254
#define AP_NORMALIZE_NOT_ABOVE_ROOT
Definition httpd.h:1788
void * ap_realloc(void *ptr, size_t size)
Definition util.c:3168
int ap_unescape_url_keep2f(char *url, int decode_slashes)
Definition util.c:1944
void ap_pregfree(apr_pool_t *p, ap_regex_t *reg)
Definition util.c:279
const char * ap_stripprefix(const char *bigstring, const char *prefix)
Definition util.c:328
char * ap_os_escape_path(apr_pool_t *p, const char *path, int partial)
Definition util.c:2073
#define AP_DIR_FLAG_OPTIONAL
Definition httpd.h:2580
void ap_get_sload(ap_sload_t *ld)
Definition util.c:3305
int ap_find_list_item(apr_pool_t *p, const char *line, const char *tok)
Definition util.c:1537
apr_status_t ap_timeout_parameter_parse(const char *timeout_parameter, apr_interval_time_t *timeout, const char *default_time_unit)
Definition util.c:2622
char * ap_getword_nc(apr_pool_t *atrans, char **line, char stop)
Definition util.c:718
void * ap_malloc(size_t size)
Definition util.c:3152
char * ap_escape_quotes(apr_pool_t *p, const char *instring)
Definition util.c:2524
int ap_find_last_token(apr_pool_t *p, const char *line, const char *tok)
Definition util.c:1780
char * ap_getword_conf(apr_pool_t *p, const char **line)
Definition util.c:833
int ap_os_is_path_absolute(apr_pool_t *p, const char *dir)
Definition util.c:229
apr_size_t size
apr_uint32_t apr_uint32_t cmp
Definition apr_atomic.h:106
const char int apr_pool_t * pool
Definition apr_cstr.h:84
const char * str2
Definition apr_cstr.h:161
const char * input
Definition apr_cstr.h:93
#define apr_isprint(c)
Definition apr_lib.h:221
#define apr_isspace(c)
Definition apr_lib.h:225
#define apr_isalnum(c)
Definition apr_lib.h:203
#define apr_toupper(c)
Definition apr_lib.h:233
#define apr_isdigit(c)
Definition apr_lib.h:209
#define apr_isxdigit(c)
Definition apr_lib.h:229
#define apr_tolower(c)
Definition apr_lib.h:231
#define apr_isascii(c)
Definition apr_lib.h:218
#define APR_SUCCESS
Definition apr_errno.h:225
char apr_size_t bufsize
Definition apr_errno.h:53
int apr_status_t
Definition apr_errno.h:44
@ APR_REG
@ APR_DIR
@ APR_NOFILE
void apr_size_t * nbytes
apr_seek_where_t where
const struct iovec * vec
apr_seek_where_t apr_off_t * offset
void * data
const char apr_file_t * file
int type
char * buffer
#define APR_READ
Definition apr_file_io.h:93
#define APR_BUFFERED
#define APR_OS_DEFAULT
#define APR_SET
const char * fname
#define APR_FINFO_LINK
#define APR_FINFO_DIRENT
#define APR_FINFO_TYPE
#define APR_FNM_PERIOD
Definition apr_fnmatch.h:62
apr_array_header_t ** result
#define APR_ALIGN_DEFAULT(size)
#define memmove(a, b, c)
apr_vformatter_buff_t const char * fmt
Definition apr_lib.h:175
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_sockaddr_t apr_sockaddr_t apr_sockaddr_t * source
apr_sockaddr_t * sockaddr
apr_interval_time_t t
apr_size_t buflen
apr_uint16_t apr_port_t
#define APR_UNSPEC
apr_interval_time_t apr_int32_t * num
Definition apr_poll.h:273
apr_interval_time_t apr_pollcb_cb_t func
Definition apr_poll.h:422
apr_pool_t * b
Definition apr_pools.h:529
int(* apr_abortfunc_t)(int retcode)
Definition apr_pools.h:148
apr_abortfunc_t apr_allocator_t * allocator
Definition apr_pools.h:208
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
apr_pool_t apr_abortfunc_t abort_fn
Definition apr_pools.h:198
apr_dir_t * dir
const char char ** end
const char char ** last
const char * s
Definition apr_strings.h:95
#define APR_ARRAY_PUSH(ary, type)
Definition apr_tables.h:150
#define APR_ARRAY_IDX(ary, i, type)
Definition apr_tables.h:141
apr_proc_t * proc
void *(APR_THREAD_FUNC * apr_thread_start_t)(apr_thread_t *, void *)
apr_int32_t apr_int32_t apr_int32_t err
const char const char *const const char *const apr_procattr_t * attr
apr_int32_t in
#define APR_FULL_BLOCK
apr_cmdtype_e cmd
int int status
@ APR_PROGRAM
#define apr_time_as_msec(time)
Definition apr_time.h:72
#define apr_time_from_msec(msec)
Definition apr_time.h:75
apr_int64_t apr_interval_time_t
Definition apr_time.h:55
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_sec(time)
Definition apr_time.h:63
#define apr_time_from_sec(sec)
Definition apr_time.h:78
apr_status_t ap_mpm_query(int query_code, int *result)
Definition mpm_common.c:421
#define AP_MPMQ_HARD_LIMIT_THREADS
Definition ap_mpm.h:158
#define AP_MPMQ_GENERATION
Definition ap_mpm.h:178
#define AP_MPMQ_HARD_LIMIT_DAEMONS
Definition ap_mpm.h:156
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP protocol handling.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
struct param_s param
const char * argv[3]
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
static int server_limit
Definition mod_status.c:89
static int thread_limit
Definition mod_status.c:89
apr_os_thread_t apr_os_thread_current()
Definition thread.c:142
apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on)
Definition thread.c:41
apr_status_t apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool)
Definition thread.c:24
apr_status_t apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr, apr_thread_start_t func, void *data, apr_pool_t *pool)
Definition thread.c:73
#define SERVER_STARTING
Definition scoreboard.h:57
int ap_generation_t
Definition scoreboard.h:78
scoreboard * ap_scoreboard_image
Definition scoreboard.c:44
int ap_extended_status
Definition scoreboard.c:61
#define SERVER_DEAD
Definition scoreboard.h:56
#define SERVER_IDLE_KILL
Definition scoreboard.h:66
#define SERVER_READY
Definition scoreboard.h:58
process_score * ap_get_scoreboard_process(int x)
Definition scoreboard.c:702
#define T_HTTP_TOKEN_STOP
#define T_VCHAR_OBSTEXT
#define T_ESCAPE_LOGITEM
#define T_OS_ESCAPE_PATH
#define T_HTTP_CTRLS
#define T_ESCAPE_URLENCODED
#define T_URI_UNRESERVED
#define T_ESCAPE_PATH_SEGMENT
#define T_ESCAPE_SHELL_CMD
static apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize, apr_size_t offset, ap_configfile_t *cfp)
Definition util.c:1079
static apr_status_t cfg_close(void *param)
Definition util.c:941
static apr_status_t varbuf_cleanup(void *info_)
Definition util.c:2948
#define VARBUF_MAX_SIZE
Definition util.c:2940
#define VARBUF_SMALL_SIZE
Definition util.c:2939
static char x2c(const char *what)
Definition util.c:1845
static apr_status_t cfg_getstr(void *buf, apr_size_t bufsiz, void *param)
Definition util.c:951
static const char nul
Definition util.c:2956
static apr_status_t regex_cleanup(void *preg)
Definition util.c:256
static apr_status_t regsub_core(apr_pool_t *p, char **result, struct ap_varbuf *vb, const char *input, const char *source, apr_size_t nmatch, ap_regmatch_t pmatch[], apr_size_t maxlen)
Definition util.c:365
static const char c2x_table[]
Definition util.c:2020
static int find_list_item(apr_pool_t *p, const char *line, const char *tok, ap_etag_e type)
Definition util.c:1409
static char * substring_conf(apr_pool_t *p, const char *start, int len, char quote)
Definition util.c:805
static apr_status_t cfg_getch(char *ch, void *param)
Definition util.c:946
static char *const varbuf_empty
Definition util.c:2957
#define AP_PREGSUB_MAXLEN
Definition util.c:455
static APR_INLINE unsigned char * c2x(unsigned what, unsigned char prefix, unsigned char *where)
Definition util.c:2022
static int unescape_url(char *url, const char *forbid, const char *reserved, unsigned int flags)
Definition util.c:1877
ap_configfile_t * ap_pcfg_open_custom(apr_pool_t *p, const char *descr, void *param, apr_status_t(*getc_func)(char *ch, void *param), apr_status_t(*gets_func)(void *buf, apr_size_t bufsize, void *param), apr_status_t(*close_func)(void *param))
Definition util.c:1038
ap_dir_match_t * ap_dir_cfgmatch(cmd_parms *cmd, int flags, const char *(*cb)(ap_dir_match_t *w, const char *fname), void *ctx)
Definition util.c:3589
const char * ap_dir_fnmatch(ap_dir_match_t *w, const char *path, const char *fname)
Definition util.c:3681
#define IS_SLASH_OR_NUL(s)
Definition util.c:484
#define AP_MAX_FNMATCH_DIR_DEPTH
Definition util.c:84
static const short ucharmap[]
Definition util.c:3459
#define CHECK_OVERFLOW(a, b)
Definition util.c:2621
ap_etag_e
Definition util.c:1398
@ AP_ETAG_WEAK
Definition util.c:1400
@ AP_ETAG_NONE
Definition util.c:1399
@ AP_ETAG_STRONG
Definition util.c:1401
const char * ap_dir_nofnmatch(ap_dir_match_t *w, const char *fname)
Definition util.c:3605
static const char *const oom_message
Definition util.c:3133
static int cfg_trim_line(char *buf)
Definition util.c:1174
ap_form_type_t
Definition util.c:2777
@ FORM_PERCENTB
Definition util.c:2783
@ FORM_ABORT
Definition util.c:2784
@ FORM_VALUE
Definition util.c:2781
@ FORM_AMP
Definition util.c:2779
@ FORM_PERCENTA
Definition util.c:2782
@ FORM_NORMAL
Definition util.c:2778
@ FORM_NAME
Definition util.c:2780
static int fname_alphasort(const void *fn1, const void *fn2)
Definition util.c:3581
#define MAXHOSTNAMELEN
static const char * find_last_token(apr_pool_t *p, const char *line, const char *tok)
Definition util.c:1758
char * name
apr_status_t(* getch)(char *ch, void *param)
unsigned line_number
const char * name
apr_status_t(* close)(void *param)
apr_status_t(* getstr)(void *buf, apr_size_t bufsiz, void *param)
const char *(* cb)(ap_dir_match_t *w, const char *fname)
Definition httpd.h:2604
void * ctx
Definition httpd.h:2606
const char * prefix
Definition httpd.h:2602
apr_pool_t * p
Definition httpd.h:2598
apr_pool_t * ptemp
Definition httpd.h:2600
unsigned int depth
Definition httpd.h:2610
The representation of a filter chain.
A structure to hold various server loadavg.
Definition httpd.h:1427
A structure to hold server load params.
Definition httpd.h:1411
apr_allocator_t * allocator
Definition util.c:2945
struct apr_memnode_t * node
Definition util.c:2944
apr_pool_t * pool
Definition util_varbuf.h:63
apr_size_t avail
Definition util_varbuf.h:54
apr_size_t strlen
Definition util_varbuf.h:59
char * buf
Definition util_varbuf.h:50
struct ap_varbuf_info * info
Definition util_varbuf.h:66
apr_size_t length
apr_filetype_e filetype
apr_memnode_t * next
apr_file_t * out
apr_thread_start_t func
struct apr_bucket_alloc_t * bucket_alloc
Definition httpd.h:1201
const char * fname
Definition util.c:3578
A structure that represents the current request.
Definition httpd.h:845
int header_only
Definition httpd.h:875
apr_pool_t * pool
Definition httpd.h:847
conn_rec * connection
Definition httpd.h:849
apr_bucket_brigade * kept_body
Definition httpd.h:953
struct ap_filter_t * input_filters
Definition httpd.h:1072
apr_table_t * headers_in
Definition httpd.h:976
worker_score ** servers
Definition scoreboard.h:163
apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, apr_dir_t *thedir)
Definition dir.c:142
apr_status_t apr_dir_close(apr_dir_t *thedir)
Definition dir.c:109
apr_status_t apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool)
Definition dir.c:75
apr_status_t apr_gethostname(char *buf, apr_int32_t len, apr_pool_t *cont)
Definition sockopt.c:389
apr_status_t apr_strftime(char *s, apr_size_t *retsize, apr_size_t max, const char *format, apr_time_exp_t *xt)
Definition timestr.c:132
Utilities for EBCDIC conversion.
#define str
@ AP_MODE_READBYTES
Definition util_filter.h:43
Apache resizable variable length buffer library.
IN ULONG IN INT timeout
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray
INT info
#define xstr(s)