Apache HTTPD
apr_escape.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/* escape/unescape functions.
18 *
19 * These functions perform various escaping operations, and are provided in
20 * pairs, a function to query the length of and escape existing buffers, as
21 * well as companion functions to perform the same process to memory
22 * allocated from a pool.
23 *
24 * The API is designed to have the smallest possible RAM footprint, and so
25 * will only allocate the exact amount of RAM needed for each conversion.
26 */
27
28#include "apr_escape.h"
29#include "apr_escape_test_char.h"
30#include "apr_encode_private.h"
31#include "apr_lib.h"
32#include "apr_strings.h"
33
34/* we assume the folks using this ensure 0 <= c < 256... which means
35 * you need a cast to (unsigned char) first, you can't just plug a
36 * char in here and get it to work, because if char is signed then it
37 * will first be sign extended.
38 */
39#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
40
43{
44 unsigned char *d;
45 const unsigned char *s;
46 apr_size_t size = 1;
47 int found = 0;
48
49 d = (unsigned char *) escaped;
50 s = (const unsigned char *) str;
51
52 if (s) {
53 if (d) {
54 for (; *s && slen; ++s, slen--) {
55#if defined(OS2) || defined(WIN32)
56 /*
57 * Newlines to Win32/OS2 CreateProcess() are ill advised.
58 * Convert them to spaces since they are effectively white
59 * space to most applications
60 */
61 if (*s == '\r' || *s == '\n') {
62 if (d) {
63 *d++ = ' ';
64 found = 1;
65 }
66 continue;
67 }
68#endif
70 *d++ = '\\';
71 size++;
72 found = 1;
73 }
74 *d++ = *s;
75 size++;
76 }
77 *d = '\0';
78 }
79 else {
80 for (; *s && slen; ++s, slen--) {
82 size++;
83 found = 1;
84 }
85 size++;
86 }
87 }
88 }
89
90 if (len) {
91 *len = size;
92 }
93 if (!found) {
94 return APR_NOTFOUND;
95 }
96
97 return APR_SUCCESS;
98}
99
100APR_DECLARE(const char *) apr_pescape_shell(apr_pool_t *p, const char *str)
101{
103
105 case APR_SUCCESS: {
106 char *cmd = apr_palloc(p, len);
108 return cmd;
109 }
110 case APR_NOTFOUND: {
111 break;
112 }
113 }
114
115 return str;
116}
117
118static char x2c(const char *what)
119{
120 register char digit;
121
122#if !APR_CHARSET_EBCDIC
123 digit =
124 ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
125 digit *= 16;
126 digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0'));
127#else /*APR_CHARSET_EBCDIC*/
128 char xstr[5];
129 xstr[0]='0';
130 xstr[1]='x';
131 xstr[2]=what[0];
132 xstr[3]=what[1];
133 xstr[4]='\0';
134 digit = TO_NATIVE(strtol(xstr, NULL, 16));
135#endif /*APR_CHARSET_EBCDIC*/
136 return (digit);
137}
138
140 apr_ssize_t slen, const char *forbid, const char *reserved, int plus,
142{
143 apr_size_t size = 1;
144 int found = 0;
145 const char *s = (const char *) url;
146 char *d = (char *) escaped;
147 register int badesc, badpath;
148
149 if (!url) {
150 return APR_NOTFOUND;
151 }
152
153 badesc = 0;
154 badpath = 0;
155 if (s) {
156 if (d) {
157 for (; *s && slen; ++s, d++, slen--) {
158 if (plus && *s == '+') {
159 *d = ' ';
160 found = 1;
161 }
162 else if (*s != '%') {
163 *d = *s;
164 }
165 else {
166 if (!apr_isxdigit(*(s + 1)) || !apr_isxdigit(*(s + 2))) {
167 badesc = 1;
168 *d = '%';
169 }
170 else {
171 char decoded;
172 decoded = x2c(s + 1);
173 if ((decoded == '\0')
174 || (forbid && strchr(forbid, decoded))) {
176 *d = decoded;
177 s += 2;
178 slen -= 2;
179 }
180 else if (reserved && strchr(reserved, decoded)) {
181 *d++ = *s++;
182 *d++ = *s++;
183 *d = *s;
184 size += 2;
185 }
186 else {
187 *d = decoded;
188 s += 2;
189 slen -= 2;
190 found = 1;
191 }
192 }
193 }
194 size++;
195 }
196 *d = '\0';
197 }
198 else {
199 for (; *s && slen; ++s, slen--) {
200 if (plus && *s == '+') {
201 found = 1;
202 }
203 else if (*s != '%') {
204 /* character unchanged */
205 }
206 else {
207 if (!apr_isxdigit(*(s + 1)) || !apr_isxdigit(*(s + 2))) {
208 badesc = 1;
209 }
210 else {
211 char decoded;
212 decoded = x2c(s + 1);
213 if ((decoded == '\0')
214 || (forbid && strchr(forbid, decoded))) {
215 badpath = 1;
216 s += 2;
217 slen -= 2;
218 }
219 else if (reserved && strchr(reserved, decoded)) {
220 s += 2;
221 slen -= 2;
222 size += 2;
223 }
224 else {
225 s += 2;
226 slen -= 2;
227 found = 1;
228 }
229 }
230 }
231 size++;
232 }
233 }
234 }
235
236 if (len) {
237 *len = size;
238 }
239 if (badesc) {
240 return APR_EINVAL;
241 }
242 else if (badpath) {
243 return APR_BADCH;
244 }
245 else if (!found) {
246 return APR_NOTFOUND;
247 }
248
249 return APR_SUCCESS;
250}
251
252APR_DECLARE(const char *) apr_punescape_url(apr_pool_t *p, const char *url,
253 const char *forbid, const char *reserved, int plus)
254{
256
258 plus, &len)) {
259 case APR_SUCCESS: {
260 char *buf = apr_palloc(p, len);
262 NULL);
263 return buf;
264 }
265 case APR_EINVAL:
266 case APR_BADCH: {
267 return NULL;
268 }
269 case APR_NOTFOUND: {
270 break;
271 }
272 }
273
274 return url;
275}
276
277/* c2x takes an unsigned, and expects the caller has guaranteed that
278 * 0 <= what < 256... which usually means that you have to cast to
279 * unsigned char first, because (unsigned)(char)(x) first goes through
280 * signed extension to an int before the unsigned cast.
281 *
282 * The reason for this assumption is to assist gcc code generation --
283 * the unsigned char -> unsigned extension is already done earlier in
284 * both uses of this code, so there's no need to waste time doing it
285 * again.
286 */
287static const char c2x_table[] = "0123456789abcdef";
288
289static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix,
290 unsigned char *where)
291{
292#if APR_CHARSET_EBCDIC
293 what = convert_e2a[(unsigned char)what];
294#endif /*APR_CHARSET_EBCDIC*/
295 *where++ = prefix;
296 *where++ = c2x_table[what >> 4];
297 *where++ = c2x_table[what & 0xf];
298 return where;
299}
300
302 const char *str, apr_ssize_t slen, apr_size_t *len)
303{
304 apr_size_t size = 1;
305 int found = 0;
306 const unsigned char *s = (const unsigned char *) str;
307 unsigned char *d = (unsigned char *) escaped;
308 unsigned c;
309
310 if (s) {
311 if (d) {
312 while ((c = *s) && slen) {
314 d = c2x(c, '%', d);
315 size += 2;
316 found = 1;
317 }
318 else {
319 *d++ = c;
320 }
321 ++s;
322 size++;
323 slen--;
324 }
325 *d = '\0';
326 }
327 else {
328 while ((c = *s) && slen) {
330 size += 2;
331 found = 1;
332 }
333 ++s;
334 size++;
335 slen--;
336 }
337 }
338 }
339
340 if (len) {
341 *len = size;
342 }
343 if (!found) {
344 return APR_NOTFOUND;
345 }
346
347 return APR_SUCCESS;
348}
349
351 const char *str)
352{
354
356 case APR_SUCCESS: {
357 char *cmd = apr_palloc(p, len);
359 return cmd;
360 }
361 case APR_NOTFOUND: {
362 break;
363 }
364 }
365
366 return str;
367}
368
371{
372 apr_size_t size = 1;
373 int found = 0;
374 const unsigned char *s = (const unsigned char *) path;
375 unsigned char *d = (unsigned char *) escaped;
376 unsigned c;
377
378 if (!path) {
379 return APR_NOTFOUND;
380 }
381
382 if (!partial) {
383 const char *colon = strchr(path, ':');
384 const char *slash = strchr(path, '/');
385
386 if (colon && (!slash || colon < slash)) {
387 if (d) {
388 *d++ = '.';
389 *d++ = '/';
390 }
391 size += 2;
392 found = 1;
393 }
394 }
395 if (d) {
396 while ((c = *s) && slen) {
398 d = c2x(c, '%', d);
399 size += 2;
400 found = 1;
401 }
402 else {
403 *d++ = c;
404 }
405 ++s;
406 size++;
407 slen--;
408 }
409 *d = '\0';
410 }
411 else {
412 while ((c = *s) && slen) {
414 size += 2;
415 found = 1;
416 }
417 ++s;
418 size++;
419 slen--;
420 }
421 }
422
423 if (len) {
424 *len = size;
425 }
426 if (!found) {
427 return APR_NOTFOUND;
428 }
429
430 return APR_SUCCESS;
431}
432
433APR_DECLARE(const char *) apr_pescape_path(apr_pool_t *p, const char *str,
434 int partial)
435{
437
439 case APR_SUCCESS: {
440 char *path = apr_palloc(p, len);
442 return path;
443 }
444 case APR_NOTFOUND: {
445 break;
446 }
447 }
448
449 return str;
450}
451
454{
455 apr_size_t size = 1;
456 int found = 0;
457 const unsigned char *s = (const unsigned char *) str;
458 unsigned char *d = (unsigned char *) escaped;
459 unsigned c;
460
461 if (s) {
462 if (d) {
463 while ((c = *s) && slen) {
465 d = c2x(c, '%', d);
466 size += 2;
467 found = 1;
468 }
469 else if (c == ' ') {
470 *d++ = '+';
471 found = 1;
472 }
473 else {
474 *d++ = c;
475 }
476 ++s;
477 size++;
478 slen--;
479 }
480 *d = '\0';
481 }
482 else {
483 while ((c = *s) && slen) {
485 size += 2;
486 found = 1;
487 }
488 else if (c == ' ') {
489 found = 1;
490 }
491 ++s;
492 size++;
493 slen--;
494 }
495 }
496 }
497
498 if (len) {
499 *len = size;
500 }
501 if (!found) {
502 return APR_NOTFOUND;
503 }
504
505 return APR_SUCCESS;
506}
507
508APR_DECLARE(const char *) apr_pescape_urlencoded(apr_pool_t *p, const char *str)
509{
511
513 case APR_SUCCESS: {
514 char *encoded = apr_palloc(p, len);
516 return encoded;
517 }
518 case APR_NOTFOUND: {
519 break;
520 }
521 }
522
523 return str;
524}
525
528{
529 apr_size_t size = 1;
530 int found = 0;
531 const unsigned char *s = (const unsigned char *) str;
532 unsigned char *d = (unsigned char *) escaped;
533 unsigned c;
534
535 if (s) {
536 if (d) {
537 while ((c = *s) && slen) {
538 if (TEST_CHAR(c, T_ESCAPE_XML)) {
539 switch (c) {
540 case '>': {
541 memcpy(d, "&gt;", 4);
542 size += 4;
543 d += 4;
544 break;
545 }
546 case '<': {
547 memcpy(d, "&lt;", 4);
548 size += 4;
549 d += 4;
550 break;
551 }
552 case '&': {
553 memcpy(d, "&amp;", 5);
554 size += 5;
555 d += 5;
556 break;
557 }
558 case '\"': {
559 memcpy(d, "&quot;", 6);
560 size += 6;
561 d += 6;
562 break;
563 }
564 case '\'': {
565 memcpy(d, "&apos;", 6);
566 size += 6;
567 d += 6;
568 break;
569 }
570 }
571 found = 1;
572 }
573 else if (toasc && !apr_isascii(c)) {
574 int offset = apr_snprintf((char *) d, 7, "&#%3.3d;", c);
575 size += offset;
576 d += offset;
577 found = 1;
578 }
579 else {
580 *d++ = c;
581 size++;
582 }
583 ++s;
584 slen--;
585 }
586 *d = '\0';
587 }
588 else {
589 while ((c = *s) && slen) {
590 if (TEST_CHAR(c, T_ESCAPE_XML)) {
591 switch (c) {
592 case '>': {
593 size += 4;
594 break;
595 }
596 case '<': {
597 size += 4;
598 break;
599 }
600 case '&': {
601 size += 5;
602 break;
603 }
604 case '\"': {
605 size += 6;
606 break;
607 }
608 case '\'': {
609 size += 6;
610 break;
611 }
612 }
613 found = 1;
614 }
615 else if (toasc && !apr_isascii(c)) {
616 size += apr_snprintf(NULL, 0, "&#%3.3d;", c);
617 found = 1;
618 }
619 else {
620 size++;
621 }
622 ++s;
623 slen--;
624 }
625 }
626 }
627
628 if (len) {
629 *len = size;
630 }
631 if (!found) {
632 return APR_NOTFOUND;
633 }
634
635 return APR_SUCCESS;
636}
637
638APR_DECLARE(const char *) apr_pescape_entity(apr_pool_t *p, const char *str,
639 int toasc)
640{
642
644 case APR_SUCCESS: {
645 char *cmd = apr_palloc(p, len);
647 return cmd;
648 }
649 case APR_NOTFOUND: {
650 break;
651 }
652 }
653
654 return str;
655}
656
657/* maximum length of any ISO-LATIN-1 HTML entity name. */
658#define MAXENTLEN (6)
659
662{
663 int found = 0;
664 apr_size_t size = 1;
665 int val, i, j;
666 char *d = unescaped;
667 const char *s = str;
668 const char *ents;
669 static const char * const entlist[MAXENTLEN + 1] =
670 {
671 NULL, /* 0 */
672 NULL, /* 1 */
673 "lt\074gt\076", /* 2 */
674 "amp\046ETH\320eth\360", /* 3 */
675 "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml"
676 "\353iuml\357ouml\366uuml\374yuml\377", /* 4 */
677 "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc"
678 "\333THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352"
679 "icirc\356ocirc\364ucirc\373thorn\376", /* 5 */
680 "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311"
681 "Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde"
682 "\325Oslash\330Ugrave\331Uacute\332Yacute\335agrave\340"
683 "aacute\341atilde\343ccedil\347egrave\350eacute\351igrave"
684 "\354iacute\355ntilde\361ograve\362oacute\363otilde\365"
685 "oslash\370ugrave\371uacute\372yacute\375" /* 6 */
686 };
687
688 if (s) {
689 if (d) {
690 for (; *s != '\0' && slen; s++, d++, size++, slen--) {
691 if (*s != '&') {
692 *d = *s;
693 continue;
694 }
695 /* find end of entity */
696 for (i = 1; s[i] != ';' && s[i] != '\0' && (slen - i) != 0;
697 i++) {
698 continue;
699 }
700
701 if (s[i] == '\0' || (slen - i) == 0) { /* treat as normal data */
702 *d = *s;
703 continue;
704 }
705
706 /* is it numeric ? */
707 if (s[1] == '#') {
708 for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
709 val = val * 10 + s[j] - '0';
710 }
711 s += i;
712 if (j < i || val <= 8 || (val >= 11 && val <= 31)
713 || (val >= 127 && val <= 160) || val >= 256) {
714 d--; /* no data to output */
715 size--;
716 }
717 else {
718 *d = TO_ASCII(val);
719 found = 1;
720 }
721 }
722 else {
723 j = i - 1;
724 if (j > MAXENTLEN || entlist[j] == NULL) {
725 /* wrong length */
726 *d = '&';
727 continue; /* skip it */
728 }
729 for (ents = entlist[j]; *ents != '\0'; ents += i) {
730 if (strncmp(s + 1, ents, j) == 0) {
731 break;
732 }
733 }
734
735 if (*ents == '\0') {
736 *d = '&'; /* unknown */
737 }
738 else {
739 *d = TO_ASCII(ents[j]);
740 s += i;
741 slen -= i;
742 found = 1;
743 }
744 }
745 }
746 *d = '\0';
747 }
748 else {
749 for (; *s != '\0' && slen; s++, size++, slen--) {
750 if (*s != '&') {
751 continue;
752 }
753 /* find end of entity */
754 for (i = 1; s[i] != ';' && s[i] != '\0' && (slen - i) != 0;
755 i++) {
756 continue;
757 }
758
759 if (s[i] == '\0' || (slen - i) == 0) { /* treat as normal data */
760 continue;
761 }
762
763 /* is it numeric ? */
764 if (s[1] == '#') {
765 for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
766 val = val * 10 + s[j] - '0';
767 }
768 s += i;
769 if (j < i || val <= 8 || (val >= 11 && val <= 31)
770 || (val >= 127 && val <= 160) || val >= 256) {
771 /* no data to output */
772 size--;
773 }
774 else {
775 found = 1;
776 }
777 }
778 else {
779 j = i - 1;
780 if (j > MAXENTLEN || entlist[j] == NULL) {
781 /* wrong length */
782 continue; /* skip it */
783 }
784 for (ents = entlist[j]; *ents != '\0'; ents += i) {
785 if (strncmp(s + 1, ents, j) == 0) {
786 break;
787 }
788 }
789
790 if (*ents == '\0') {
791 /* unknown */
792 }
793 else {
794 s += i;
795 slen -= i;
796 found = 1;
797 }
798 }
799 }
800 }
801 }
802
803 if (len) {
804 *len = size;
805 }
806 if (!found) {
807 return APR_NOTFOUND;
808 }
809
810 return APR_SUCCESS;
811}
812
813APR_DECLARE(const char *) apr_punescape_entity(apr_pool_t *p, const char *str)
814{
816
818 case APR_SUCCESS: {
819 char *cmd = apr_palloc(p, len);
821 return cmd;
822 }
823 case APR_NOTFOUND: {
824 break;
825 }
826 }
827
828 return str;
829}
830
833{
834 apr_size_t size = 1;
835 int found = 0;
836 const unsigned char *s = (const unsigned char *) str;
837 unsigned char *d = (unsigned char *) escaped;
838 unsigned c;
839
840 if (s) {
841 if (d) {
842 while ((c = *s) && slen) {
843 if (TEST_CHAR(c, T_ESCAPE_ECHO)) {
844 *d++ = '\\';
845 size++;
846 switch (c) {
847 case '\a':
848 *d++ = 'a';
849 size++;
850 found = 1;
851 break;
852 case '\b':
853 *d++ = 'b';
854 size++;
855 found = 1;
856 break;
857 case '\f':
858 *d++ = 'f';
859 size++;
860 found = 1;
861 break;
862 case '\n':
863 *d++ = 'n';
864 size++;
865 found = 1;
866 break;
867 case '\r':
868 *d++ = 'r';
869 size++;
870 found = 1;
871 break;
872 case '\t':
873 *d++ = 't';
874 size++;
875 found = 1;
876 break;
877 case '\v':
878 *d++ = 'v';
879 size++;
880 found = 1;
881 break;
882 case '\\':
883 *d++ = '\\';
884 size++;
885 found = 1;
886 break;
887 case '"':
888 if (quote) {
889 *d++ = c;
890 size++;
891 found = 1;
892 }
893 else {
894 d[-1] = c;
895 }
896 break;
897 default:
898 c2x(c, 'x', d);
899 d += 3;
900 size += 3;
901 found = 1;
902 break;
903 }
904 }
905 else {
906 *d++ = c;
907 size++;
908 }
909 ++s;
910 slen--;
911 }
912 *d = '\0';
913 }
914 else {
915 while ((c = *s) && slen) {
916 if (TEST_CHAR(c, T_ESCAPE_ECHO)) {
917 size++;
918 switch (c) {
919 case '\a':
920 case '\b':
921 case '\f':
922 case '\n':
923 case '\r':
924 case '\t':
925 case '\v':
926 case '\\':
927 size++;
928 found = 1;
929 break;
930 case '"':
931 if (quote) {
932 size++;
933 found = 1;
934 }
935 break;
936 default:
937 size += 3;
938 found = 1;
939 break;
940 }
941 }
942 else {
943 size++;
944 }
945 ++s;
946 slen--;
947 }
948 }
949 }
950
951 if (len) {
952 *len = size;
953 }
954 if (!found) {
955 return APR_NOTFOUND;
956 }
957
958 return APR_SUCCESS;
959}
960
961APR_DECLARE(const char *) apr_pescape_echo(apr_pool_t *p, const char *str,
962 int quote)
963{
965
967 case APR_SUCCESS: {
968 char *cmd = apr_palloc(p, len);
970 return cmd;
971 }
972 case APR_NOTFOUND: {
973 break;
974 }
975 }
976
977 return str;
978}
979
982{
983 const unsigned char *in = src;
985
986 if (!src) {
987 return APR_NOTFOUND;
988 }
989
990 if (dest) {
991 for (size = 0; size < srclen; size++) {
992 if (colon && size) {
993 *dest++ = ':';
994 }
995 *dest++ = c2x_table[in[size] >> 4];
996 *dest++ = c2x_table[in[size] & 0xf];
997 }
998 *dest = '\0';
999 }
1000
1001 if (len) {
1002 if (colon && srclen) {
1003 *len = srclen * 3;
1004 }
1005 else {
1006 *len = srclen * 2 + 1;
1007 }
1008 }
1009
1010 return APR_SUCCESS;
1011}
1012
1013APR_DECLARE(const char *) apr_pescape_hex(apr_pool_t *p, const void *src,
1014 apr_size_t srclen, int colon)
1015{
1017
1018 switch (apr_escape_hex(NULL, src, srclen, colon, &len)) {
1019 case APR_SUCCESS: {
1020 char *cmd = apr_palloc(p, len);
1022 return cmd;
1023 }
1024 case APR_NOTFOUND: {
1025 break;
1026 }
1027 }
1028
1029 return src;
1030}
1031
1034{
1035 apr_size_t size = 0;
1036 int flip = 0;
1037 const unsigned char *s = (const unsigned char *) str;
1038 unsigned char *d = (unsigned char *) dest;
1039 unsigned c;
1040 unsigned char u = 0;
1041
1042 if (s) {
1043 if (d) {
1044 while ((c = *s) && slen) {
1045
1046 if (!flip) {
1047 u = 0;
1048 }
1049
1050 if (colon && c == ':' && !flip) {
1051 ++s;
1052 slen--;
1053 continue;
1054 }
1055 else if (apr_isdigit(c)) {
1056 u |= c - '0';
1057 }
1058 else if (apr_isupper(c) && c <= 'F') {
1059 u |= c - ('A' - 10);
1060 }
1061 else if (apr_islower(c) && c <= 'f') {
1062 u |= c - ('a' - 10);
1063 }
1064 else {
1065 return APR_BADCH;
1066 }
1067
1068 if (flip) {
1069 *d++ = u;
1070 size++;
1071 }
1072 else {
1073 u <<= 4;
1074 *d = u;
1075 }
1076 flip = !flip;
1077
1078 ++s;
1079 slen--;
1080 }
1081 }
1082 else {
1083 while ((c = *s) && slen) {
1084
1085 if (colon && c == ':' && !flip) {
1086 ++s;
1087 slen--;
1088 continue;
1089 }
1090 else if (apr_isdigit(c)) {
1091 /* valid */
1092 }
1093 else if (apr_isupper(c) && c <= 'F') {
1094 /* valid */
1095 }
1096 else if (apr_islower(c) && c <= 'f') {
1097 /* valid */
1098 }
1099 else {
1100 return APR_BADCH;
1101 }
1102
1103 if (flip) {
1104 size++;
1105 }
1106 flip = !flip;
1107
1108 ++s;
1109 slen--;
1110 }
1111 }
1112 }
1113
1114 if (len) {
1115 *len = size;
1116 }
1117 if (!s) {
1118 return APR_NOTFOUND;
1119 }
1120
1121 return APR_SUCCESS;
1122}
1123
1124APR_DECLARE(const void *) apr_punescape_hex(apr_pool_t *p, const char *str,
1125 int colon, apr_size_t *len)
1126{
1128
1130 case APR_SUCCESS: {
1131 void *cmd = apr_palloc(p, size);
1133 return cmd;
1134 }
1135 case APR_BADCH:
1136 case APR_NOTFOUND: {
1137 break;
1138 }
1139 }
1140
1141 return NULL;
1142}
1143
1146{
1147 apr_size_t size = 1;
1148 int found = 0;
1149 const unsigned char *s = (const unsigned char *) str;
1150 unsigned char *d = (unsigned char *) escaped;
1151 unsigned c;
1152
1153 if (s) {
1154 if (d) {
1155 while (((c = *s) && slen) || (slen > 0)) {
1158 d = c2x(c, '\\', d);
1159 size += 2;
1160 found = 1;
1161 }
1162 else {
1163 *d++ = c;
1164 }
1165 ++s;
1166 size++;
1167 slen--;
1168 }
1169 *d = '\0';
1170 }
1171 else {
1172 while (((c = *s) && slen) || (slen > 0)) {
1175 size += 2;
1176 found = 1;
1177 }
1178 ++s;
1179 size++;
1180 slen--;
1181 }
1182 }
1183 }
1184
1185 if (len) {
1186 *len = size;
1187 }
1188 if (!found) {
1189 return APR_NOTFOUND;
1190 }
1191
1192 return APR_SUCCESS;
1193}
1194
1195APR_DECLARE(const char *) apr_pescape_ldap(apr_pool_t *p, const void *src,
1197{
1199
1200 switch (apr_escape_ldap(NULL, src, srclen, flags, &len)) {
1201 case APR_SUCCESS: {
1202 char *encoded = apr_palloc(p, len);
1203 apr_escape_ldap(encoded, src, srclen, flags, NULL);
1204 return encoded;
1205 }
1206 case APR_NOTFOUND: {
1207 break;
1208 }
1209 }
1210
1211 return src;
1212}
1213
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Encoding Private.
static char x2c(const char *what)
Definition apr_escape.c:118
static const char c2x_table[]
Definition apr_escape.c:287
#define TEST_CHAR(c, f)
Definition apr_escape.c:39
static APR_INLINE unsigned char * c2x(unsigned what, unsigned char prefix, unsigned char *where)
Definition apr_escape.c:289
#define MAXENTLEN
Definition apr_escape.c:658
APR-UTIL Escaping.
APR general purpose library routines.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
return found
Definition core.c:2840
request_rec int int apr_table_t const char * path
const unsigned char * buf
Definition util_md5.h:50
#define APR_BADCH
Definition apr_errno.h:457
#define APR_NOTFOUND
Definition apr_errno.h:463
#define APR_EINVAL
Definition apr_errno.h:711
#define TO_ASCII(ch)
#define TO_NATIVE(ch)
const char * src
Definition apr_encode.h:167
const char apr_ssize_t int flags
Definition apr_encode.h:168
const char apr_ssize_t slen
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 char apr_ssize_t const char const char int plus
Definition apr_escape.h:121
const void apr_size_t srclen
Definition apr_escape.h:355
#define APR_ESCAPE_STRING
Definition apr_escape.h:56
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
#define APR_ESCAPE_LDAP_FILTER
Definition apr_escape.h:66
const char apr_ssize_t int toasc
Definition apr_escape.h:254
#define APR_ESCAPE_LDAP_DN
Definition apr_escape.h:61
const void apr_status_t(*) apr_status_t(* APR_DECLARE)(void) apr_pool_pre_cleanup_register(apr_pool_t *p
Definition apr_pools.h:646
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
#define apr_isupper(c)
Definition apr_lib.h:227
#define apr_isdigit(c)
Definition apr_lib.h:209
#define apr_isxdigit(c)
Definition apr_lib.h:229
#define apr_isascii(c)
Definition apr_lib.h:218
#define apr_islower(c)
Definition apr_lib.h:213
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_seek_where_t where
apr_seek_where_t apr_off_t * offset
apr_vformatter_buff_t * c
Definition apr_lib.h:175
const char * s
Definition apr_strings.h:95
apr_int32_t in
apr_cmdtype_e cmd
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
#define T_OS_ESCAPE_PATH
#define T_ESCAPE_URLENCODED
#define T_ESCAPE_PATH_SEGMENT
#define T_ESCAPE_SHELL_CMD
#define T_ESCAPE_LDAP_FILTER
#define T_ESCAPE_XML
#define T_ESCAPE_LDAP_DN
#define T_ESCAPE_ECHO
#define str
#define xstr(s)