Coverage Report

Created: 2025-07-11 06:40

/src/httpd/srclib/apr/encoding/apr_escape.c
Line
Count
Source (jump to first uncovered line)
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
0
#define TEST_CHAR(c, f)        (test_char_table[(apr_uint16_t)(c)] & (f))
40
41
APR_DECLARE(apr_status_t) apr_escape_shell(char *escaped, const char *str,
42
        apr_ssize_t slen, apr_size_t *len)
43
0
{
44
0
    unsigned char *d;
45
0
    const unsigned char *s;
46
0
    apr_size_t size = 1;
47
0
    int found = 0;
48
49
0
    d = (unsigned char *) escaped;
50
0
    s = (const unsigned char *) str;
51
52
0
    if (s) {
53
0
        if (d) {
54
0
            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
69
0
                if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
70
0
                    *d++ = '\\';
71
0
                    size++;
72
0
                    found = 1;
73
0
                }
74
0
                *d++ = *s;
75
0
                size++;
76
0
            }
77
0
            *d = '\0';
78
0
        }
79
0
        else {
80
0
            for (; *s && slen; ++s, slen--) {
81
0
                if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
82
0
                    size++;
83
0
                    found = 1;
84
0
                }
85
0
                size++;
86
0
            }
87
0
        }
88
0
    }
89
90
0
    if (len) {
91
0
        *len = size;
92
0
    }
93
0
    if (!found) {
94
0
        return APR_NOTFOUND;
95
0
    }
96
97
0
    return APR_SUCCESS;
98
0
}
99
100
APR_DECLARE(const char *) apr_pescape_shell(apr_pool_t *p, const char *str)
101
0
{
102
0
    apr_size_t len;
103
104
0
    switch (apr_escape_shell(NULL, str, APR_ESCAPE_STRING, &len)) {
105
0
    case APR_SUCCESS: {
106
0
        char *cmd = apr_palloc(p, len);
107
0
        apr_escape_shell(cmd, str, APR_ESCAPE_STRING, NULL);
108
0
        return cmd;
109
0
    }
110
0
    case APR_NOTFOUND: {
111
0
        break;
112
0
    }
113
0
    }
114
115
0
    return str;
116
0
}
117
118
static char x2c(const char *what)
119
0
{
120
0
    register char digit;
121
122
0
#if !APR_CHARSET_EBCDIC
123
0
    digit =
124
0
            ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
125
0
    digit *= 16;
126
0
    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
0
    return (digit);
137
0
}
138
139
APR_DECLARE(apr_status_t) apr_unescape_url(char *escaped, const char *url,
140
        apr_ssize_t slen, const char *forbid, const char *reserved, int plus,
141
        apr_size_t *len)
142
0
{
143
0
    apr_size_t size = 1;
144
0
    int found = 0;
145
0
    const char *s = (const char *) url;
146
0
    char *d = (char *) escaped;
147
0
    register int badesc, badpath;
148
149
0
    if (!url) {
150
0
        return APR_NOTFOUND;
151
0
    }
152
153
0
    badesc = 0;
154
0
    badpath = 0;
155
0
    if (s) {
156
0
        if (d) {
157
0
            for (; *s && slen; ++s, d++, slen--) {
158
0
                if (plus && *s == '+') {
159
0
                    *d = ' ';
160
0
                    found = 1;
161
0
                }
162
0
                else if (*s != '%') {
163
0
                    *d = *s;
164
0
                }
165
0
                else {
166
0
                    if (!apr_isxdigit(*(s + 1)) || !apr_isxdigit(*(s + 2))) {
167
0
                        badesc = 1;
168
0
                        *d = '%';
169
0
                    }
170
0
                    else {
171
0
                        char decoded;
172
0
                        decoded = x2c(s + 1);
173
0
                        if ((decoded == '\0')
174
0
                                || (forbid && strchr(forbid, decoded))) {
175
0
                            badpath = 1;
176
0
                            *d = decoded;
177
0
                            s += 2;
178
0
                            slen -= 2;
179
0
                        }
180
0
                        else if (reserved && strchr(reserved, decoded)) {
181
0
                            *d++ = *s++;
182
0
                            *d++ = *s++;
183
0
                            *d = *s;
184
0
                            size += 2;
185
0
                        }
186
0
                        else {
187
0
                            *d = decoded;
188
0
                            s += 2;
189
0
                            slen -= 2;
190
0
                            found = 1;
191
0
                        }
192
0
                    }
193
0
                }
194
0
                size++;
195
0
            }
196
0
            *d = '\0';
197
0
        }
198
0
        else {
199
0
            for (; *s && slen; ++s, slen--) {
200
0
                if (plus && *s == '+') {
201
0
                    found = 1;
202
0
                }
203
0
                else if (*s != '%') {
204
                    /* character unchanged */
205
0
                }
206
0
                else {
207
0
                    if (!apr_isxdigit(*(s + 1)) || !apr_isxdigit(*(s + 2))) {
208
0
                        badesc = 1;
209
0
                    }
210
0
                    else {
211
0
                        char decoded;
212
0
                        decoded = x2c(s + 1);
213
0
                        if ((decoded == '\0')
214
0
                                || (forbid && strchr(forbid, decoded))) {
215
0
                            badpath = 1;
216
0
                            s += 2;
217
0
                            slen -= 2;
218
0
                        }
219
0
                        else if (reserved && strchr(reserved, decoded)) {
220
0
                            s += 2;
221
0
                            slen -= 2;
222
0
                            size += 2;
223
0
                        }
224
0
                        else {
225
0
                            s += 2;
226
0
                            slen -= 2;
227
0
                            found = 1;
228
0
                        }
229
0
                    }
230
0
                }
231
0
                size++;
232
0
            }
233
0
        }
234
0
    }
235
236
0
    if (len) {
237
0
        *len = size;
238
0
    }
239
0
    if (badesc) {
240
0
        return APR_EINVAL;
241
0
    }
242
0
    else if (badpath) {
243
0
        return APR_BADCH;
244
0
    }
245
0
    else if (!found) {
246
0
        return APR_NOTFOUND;
247
0
    }
248
249
0
    return APR_SUCCESS;
250
0
}
251
252
APR_DECLARE(const char *) apr_punescape_url(apr_pool_t *p, const char *url,
253
        const char *forbid, const char *reserved, int plus)
254
0
{
255
0
    apr_size_t len;
256
257
0
    switch (apr_unescape_url(NULL, url, APR_ESCAPE_STRING, forbid, reserved,
258
0
            plus, &len)) {
259
0
    case APR_SUCCESS: {
260
0
        char *buf = apr_palloc(p, len);
261
0
        apr_unescape_url(buf, url, APR_ESCAPE_STRING, forbid, reserved, plus,
262
0
                NULL);
263
0
        return buf;
264
0
    }
265
0
    case APR_EINVAL:
266
0
    case APR_BADCH: {
267
0
        return NULL;
268
0
    }
269
0
    case APR_NOTFOUND: {
270
0
        break;
271
0
    }
272
0
    }
273
274
0
    return url;
275
0
}
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
 */
287
static const char c2x_table[] = "0123456789abcdef";
288
289
static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix,
290
        unsigned char *where)
291
0
{
292
#if APR_CHARSET_EBCDIC
293
    what = convert_e2a[(unsigned char)what];
294
#endif /*APR_CHARSET_EBCDIC*/
295
0
    *where++ = prefix;
296
0
    *where++ = c2x_table[what >> 4];
297
0
    *where++ = c2x_table[what & 0xf];
298
0
    return where;
299
0
}
300
301
APR_DECLARE(apr_status_t) apr_escape_path_segment(char *escaped,
302
        const char *str, apr_ssize_t slen, apr_size_t *len)
303
0
{
304
0
    apr_size_t size = 1;
305
0
    int found = 0;
306
0
    const unsigned char *s = (const unsigned char *) str;
307
0
    unsigned char *d = (unsigned char *) escaped;
308
0
    unsigned c;
309
310
0
    if (s) {
311
0
        if (d) {
312
0
            while ((c = *s) && slen) {
313
0
                if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) {
314
0
                    d = c2x(c, '%', d);
315
0
                    size += 2;
316
0
                    found = 1;
317
0
                }
318
0
                else {
319
0
                    *d++ = c;
320
0
                }
321
0
                ++s;
322
0
                size++;
323
0
                slen--;
324
0
            }
325
0
            *d = '\0';
326
0
        }
327
0
        else {
328
0
            while ((c = *s) && slen) {
329
0
                if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) {
330
0
                    size += 2;
331
0
                    found = 1;
332
0
                }
333
0
                ++s;
334
0
                size++;
335
0
                slen--;
336
0
            }
337
0
        }
338
0
    }
339
340
0
    if (len) {
341
0
        *len = size;
342
0
    }
343
0
    if (!found) {
344
0
        return APR_NOTFOUND;
345
0
    }
346
347
0
    return APR_SUCCESS;
348
0
}
349
350
APR_DECLARE(const char *) apr_pescape_path_segment(apr_pool_t *p,
351
        const char *str)
352
0
{
353
0
    apr_size_t len;
354
355
0
    switch (apr_escape_path_segment(NULL, str, APR_ESCAPE_STRING, &len)) {
356
0
    case APR_SUCCESS: {
357
0
        char *cmd = apr_palloc(p, len);
358
0
        apr_escape_path_segment(cmd, str, APR_ESCAPE_STRING, NULL);
359
0
        return cmd;
360
0
    }
361
0
    case APR_NOTFOUND: {
362
0
        break;
363
0
    }
364
0
    }
365
366
0
    return str;
367
0
}
368
369
APR_DECLARE(apr_status_t) apr_escape_path(char *escaped, const char *path,
370
        apr_ssize_t slen, int partial, apr_size_t *len)
371
0
{
372
0
    apr_size_t size = 1;
373
0
    int found = 0;
374
0
    const unsigned char *s = (const unsigned char *) path;
375
0
    unsigned char *d = (unsigned char *) escaped;
376
0
    unsigned c;
377
378
0
    if (!path) {
379
0
        return APR_NOTFOUND;
380
0
    }
381
382
0
    if (!partial) {
383
0
        const char *colon = strchr(path, ':');
384
0
        const char *slash = strchr(path, '/');
385
386
0
        if (colon && (!slash || colon < slash)) {
387
0
            if (d) {
388
0
                *d++ = '.';
389
0
                *d++ = '/';
390
0
            }
391
0
            size += 2;
392
0
            found = 1;
393
0
        }
394
0
    }
395
0
    if (d) {
396
0
        while ((c = *s) && slen) {
397
0
            if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
398
0
                d = c2x(c, '%', d);
399
0
                size += 2;
400
0
                found = 1;
401
0
            }
402
0
            else {
403
0
                *d++ = c;
404
0
            }
405
0
            ++s;
406
0
            size++;
407
0
            slen--;
408
0
        }
409
0
        *d = '\0';
410
0
    }
411
0
    else {
412
0
        while ((c = *s) && slen) {
413
0
            if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
414
0
                size += 2;
415
0
                found = 1;
416
0
            }
417
0
            ++s;
418
0
            size++;
419
0
            slen--;
420
0
        }
421
0
    }
422
423
0
    if (len) {
424
0
        *len = size;
425
0
    }
426
0
    if (!found) {
427
0
        return APR_NOTFOUND;
428
0
    }
429
430
0
    return APR_SUCCESS;
431
0
}
432
433
APR_DECLARE(const char *) apr_pescape_path(apr_pool_t *p, const char *str,
434
        int partial)
435
0
{
436
0
    apr_size_t len;
437
438
0
    switch (apr_escape_path(NULL, str, APR_ESCAPE_STRING, partial, &len)) {
439
0
    case APR_SUCCESS: {
440
0
        char *path = apr_palloc(p, len);
441
0
        apr_escape_path(path, str, APR_ESCAPE_STRING, partial, NULL);
442
0
        return path;
443
0
    }
444
0
    case APR_NOTFOUND: {
445
0
        break;
446
0
    }
447
0
    }
448
449
0
    return str;
450
0
}
451
452
APR_DECLARE(apr_status_t) apr_escape_urlencoded(char *escaped, const char *str,
453
        apr_ssize_t slen, apr_size_t *len)
454
0
{
455
0
    apr_size_t size = 1;
456
0
    int found = 0;
457
0
    const unsigned char *s = (const unsigned char *) str;
458
0
    unsigned char *d = (unsigned char *) escaped;
459
0
    unsigned c;
460
461
0
    if (s) {
462
0
        if (d) {
463
0
            while ((c = *s) && slen) {
464
0
                if (TEST_CHAR(c, T_ESCAPE_URLENCODED)) {
465
0
                    d = c2x(c, '%', d);
466
0
                    size += 2;
467
0
                    found = 1;
468
0
                }
469
0
                else if (c == ' ') {
470
0
                    *d++ = '+';
471
0
                    found = 1;
472
0
                }
473
0
                else {
474
0
                    *d++ = c;
475
0
                }
476
0
                ++s;
477
0
                size++;
478
0
                slen--;
479
0
            }
480
0
            *d = '\0';
481
0
        }
482
0
        else {
483
0
            while ((c = *s) && slen) {
484
0
                if (TEST_CHAR(c, T_ESCAPE_URLENCODED)) {
485
0
                    size += 2;
486
0
                    found = 1;
487
0
                }
488
0
                else if (c == ' ') {
489
0
                    found = 1;
490
0
                }
491
0
                ++s;
492
0
                size++;
493
0
                slen--;
494
0
            }
495
0
        }
496
0
    }
497
498
0
    if (len) {
499
0
        *len = size;
500
0
    }
501
0
    if (!found) {
502
0
        return APR_NOTFOUND;
503
0
    }
504
505
0
    return APR_SUCCESS;
506
0
}
507
508
APR_DECLARE(const char *) apr_pescape_urlencoded(apr_pool_t *p, const char *str)
509
0
{
510
0
    apr_size_t len;
511
512
0
    switch (apr_escape_urlencoded(NULL, str, APR_ESCAPE_STRING, &len)) {
513
0
    case APR_SUCCESS: {
514
0
        char *encoded = apr_palloc(p, len);
515
0
        apr_escape_urlencoded(encoded, str, APR_ESCAPE_STRING, NULL);
516
0
        return encoded;
517
0
    }
518
0
    case APR_NOTFOUND: {
519
0
        break;
520
0
    }
521
0
    }
522
523
0
    return str;
524
0
}
525
526
APR_DECLARE(apr_status_t) apr_escape_entity(char *escaped, const char *str,
527
        apr_ssize_t slen, int toasc, apr_size_t *len)
528
0
{
529
0
    apr_size_t size = 1;
530
0
    int found = 0;
531
0
    const unsigned char *s = (const unsigned char *) str;
532
0
    unsigned char *d = (unsigned char *) escaped;
533
0
    unsigned c;
534
535
0
    if (s) {
536
0
        if (d) {
537
0
            while ((c = *s) && slen) {
538
0
                if (TEST_CHAR(c, T_ESCAPE_XML)) {
539
0
                    switch (c) {
540
0
                    case '>': {
541
0
                        memcpy(d, "&gt;", 4);
542
0
                        size += 4;
543
0
                        d += 4;
544
0
                        break;
545
0
                    }
546
0
                    case '<': {
547
0
                        memcpy(d, "&lt;", 4);
548
0
                        size += 4;
549
0
                        d += 4;
550
0
                        break;
551
0
                    }
552
0
                    case '&': {
553
0
                        memcpy(d, "&amp;", 5);
554
0
                        size += 5;
555
0
                        d += 5;
556
0
                        break;
557
0
                    }
558
0
                    case '\"': {
559
0
                        memcpy(d, "&quot;", 6);
560
0
                        size += 6;
561
0
                        d += 6;
562
0
                        break;
563
0
                    }
564
0
                    case '\'': {
565
0
                        memcpy(d, "&apos;", 6);
566
0
                        size += 6;
567
0
                        d += 6;
568
0
                        break;
569
0
                    }
570
0
                    }
571
0
                    found = 1;
572
0
                }
573
0
                else if (toasc && !apr_isascii(c)) {
574
0
                    int offset = apr_snprintf((char *) d, 7, "&#%3.3d;", c);
575
0
                    size += offset;
576
0
                    d += offset;
577
0
                    found = 1;
578
0
                }
579
0
                else {
580
0
                    *d++ = c;
581
0
                    size++;
582
0
                }
583
0
                ++s;
584
0
                slen--;
585
0
            }
586
0
            *d = '\0';
587
0
        }
588
0
        else {
589
0
            while ((c = *s) && slen) {
590
0
                if (TEST_CHAR(c, T_ESCAPE_XML)) {
591
0
                    switch (c) {
592
0
                    case '>': {
593
0
                        size += 4;
594
0
                        break;
595
0
                    }
596
0
                    case '<': {
597
0
                        size += 4;
598
0
                        break;
599
0
                    }
600
0
                    case '&': {
601
0
                        size += 5;
602
0
                        break;
603
0
                    }
604
0
                    case '\"': {
605
0
                        size += 6;
606
0
                        break;
607
0
                    }
608
0
                    case '\'': {
609
0
                        size += 6;
610
0
                        break;
611
0
                    }
612
0
                    }
613
0
                    found = 1;
614
0
                }
615
0
                else if (toasc && !apr_isascii(c)) {
616
0
                    size += apr_snprintf(NULL, 0, "&#%3.3d;", c);
617
0
                    found = 1;
618
0
                }
619
0
                else {
620
0
                    size++;
621
0
                }
622
0
                ++s;
623
0
                slen--;
624
0
            }
625
0
        }
626
0
    }
627
628
0
    if (len) {
629
0
        *len = size;
630
0
    }
631
0
    if (!found) {
632
0
        return APR_NOTFOUND;
633
0
    }
634
635
0
    return APR_SUCCESS;
636
0
}
637
638
APR_DECLARE(const char *) apr_pescape_entity(apr_pool_t *p, const char *str,
639
        int toasc)
640
0
{
641
0
    apr_size_t len;
642
643
0
    switch (apr_escape_entity(NULL, str, APR_ESCAPE_STRING, toasc, &len)) {
644
0
    case APR_SUCCESS: {
645
0
        char *cmd = apr_palloc(p, len);
646
0
        apr_escape_entity(cmd, str, APR_ESCAPE_STRING, toasc, NULL);
647
0
        return cmd;
648
0
    }
649
0
    case APR_NOTFOUND: {
650
0
        break;
651
0
    }
652
0
    }
653
654
0
    return str;
655
0
}
656
657
/* maximum length of any ISO-LATIN-1 HTML entity name. */
658
0
#define MAXENTLEN (6)
659
660
APR_DECLARE(apr_status_t) apr_unescape_entity(char *unescaped, const char *str,
661
        apr_ssize_t slen, apr_size_t *len)
662
0
{
663
0
    int found = 0;
664
0
    apr_size_t size = 1;
665
0
    int val, i, j;
666
0
    char *d = unescaped;
667
0
    const char *s = str;
668
0
    const char *ents;
669
0
    static const char * const entlist[MAXENTLEN + 1] =
670
0
    {
671
0
            NULL, /* 0 */
672
0
            NULL, /* 1 */
673
0
            "lt\074gt\076", /* 2 */
674
0
            "amp\046ETH\320eth\360", /* 3 */
675
0
            "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml"
676
0
            "\353iuml\357ouml\366uuml\374yuml\377", /* 4 */
677
0
            "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc"
678
0
            "\333THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352"
679
0
            "icirc\356ocirc\364ucirc\373thorn\376", /* 5 */
680
0
            "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311"
681
0
            "Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde"
682
0
            "\325Oslash\330Ugrave\331Uacute\332Yacute\335agrave\340"
683
0
            "aacute\341atilde\343ccedil\347egrave\350eacute\351igrave"
684
0
            "\354iacute\355ntilde\361ograve\362oacute\363otilde\365"
685
0
            "oslash\370ugrave\371uacute\372yacute\375" /* 6 */
686
0
    };
687
688
0
    if (s) {
689
0
        if (d) {
690
0
            for (; *s != '\0' && slen; s++, d++, size++, slen--) {
691
0
                if (*s != '&') {
692
0
                    *d = *s;
693
0
                    continue;
694
0
                }
695
                /* find end of entity */
696
0
                for (i = 1; s[i] != ';' && s[i] != '\0' && (slen - i) != 0;
697
0
                        i++) {
698
0
                    continue;
699
0
                }
700
701
0
                if (s[i] == '\0' || (slen - i) == 0) { /* treat as normal data */
702
0
                    *d = *s;
703
0
                    continue;
704
0
                }
705
706
                /* is it numeric ? */
707
0
                if (s[1] == '#') {
708
0
                    for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
709
0
                        val = val * 10 + s[j] - '0';
710
0
                    }
711
0
                    s += i;
712
0
                    if (j < i || val <= 8 || (val >= 11 && val <= 31)
713
0
                            || (val >= 127 && val <= 160) || val >= 256) {
714
0
                        d--; /* no data to output */
715
0
                        size--;
716
0
                    }
717
0
                    else {
718
0
                        *d = TO_ASCII(val);
719
0
                        found = 1;
720
0
                    }
721
0
                }
722
0
                else {
723
0
                    j = i - 1;
724
0
                    if (j > MAXENTLEN || entlist[j] == NULL) {
725
                        /* wrong length */
726
0
                        *d = '&';
727
0
                        continue; /* skip it */
728
0
                    }
729
0
                    for (ents = entlist[j]; *ents != '\0'; ents += i) {
730
0
                        if (strncmp(s + 1, ents, j) == 0) {
731
0
                            break;
732
0
                        }
733
0
                    }
734
735
0
                    if (*ents == '\0') {
736
0
                        *d = '&'; /* unknown */
737
0
                    }
738
0
                    else {
739
0
                        *d = TO_ASCII(ents[j]);
740
0
                        s += i;
741
0
                        slen -= i;
742
0
                        found = 1;
743
0
                    }
744
0
                }
745
0
            }
746
0
            *d = '\0';
747
0
        }
748
0
        else {
749
0
            for (; *s != '\0' && slen; s++, size++, slen--) {
750
0
                if (*s != '&') {
751
0
                    continue;
752
0
                }
753
                /* find end of entity */
754
0
                for (i = 1; s[i] != ';' && s[i] != '\0' && (slen - i) != 0;
755
0
                        i++) {
756
0
                    continue;
757
0
                }
758
759
0
                if (s[i] == '\0' || (slen - i) == 0) { /* treat as normal data */
760
0
                    continue;
761
0
                }
762
763
                /* is it numeric ? */
764
0
                if (s[1] == '#') {
765
0
                    for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
766
0
                        val = val * 10 + s[j] - '0';
767
0
                    }
768
0
                    s += i;
769
0
                    if (j < i || val <= 8 || (val >= 11 && val <= 31)
770
0
                            || (val >= 127 && val <= 160) || val >= 256) {
771
                        /* no data to output */
772
0
                        size--;
773
0
                    }
774
0
                    else {
775
0
                        found = 1;
776
0
                    }
777
0
                }
778
0
                else {
779
0
                    j = i - 1;
780
0
                    if (j > MAXENTLEN || entlist[j] == NULL) {
781
                        /* wrong length */
782
0
                        continue; /* skip it */
783
0
                    }
784
0
                    for (ents = entlist[j]; *ents != '\0'; ents += i) {
785
0
                        if (strncmp(s + 1, ents, j) == 0) {
786
0
                            break;
787
0
                        }
788
0
                    }
789
790
0
                    if (*ents == '\0') {
791
                        /* unknown */
792
0
                    }
793
0
                    else {
794
0
                        s += i;
795
0
                        slen -= i;
796
0
                        found = 1;
797
0
                    }
798
0
                }
799
0
            }
800
0
        }
801
0
    }
802
803
0
    if (len) {
804
0
        *len = size;
805
0
    }
806
0
    if (!found) {
807
0
        return APR_NOTFOUND;
808
0
    }
809
810
0
    return APR_SUCCESS;
811
0
}
812
813
APR_DECLARE(const char *) apr_punescape_entity(apr_pool_t *p, const char *str)
814
0
{
815
0
    apr_size_t len;
816
817
0
    switch (apr_unescape_entity(NULL, str, APR_ESCAPE_STRING, &len)) {
818
0
    case APR_SUCCESS: {
819
0
        char *cmd = apr_palloc(p, len);
820
0
        apr_unescape_entity(cmd, str, APR_ESCAPE_STRING, NULL);
821
0
        return cmd;
822
0
    }
823
0
    case APR_NOTFOUND: {
824
0
        break;
825
0
    }
826
0
    }
827
828
0
    return str;
829
0
}
830
831
APR_DECLARE(apr_status_t) apr_escape_echo(char *escaped, const char *str,
832
        apr_ssize_t slen, int quote, apr_size_t *len)
833
0
{
834
0
    apr_size_t size = 1;
835
0
    int found = 0;
836
0
    const unsigned char *s = (const unsigned char *) str;
837
0
    unsigned char *d = (unsigned char *) escaped;
838
0
    unsigned c;
839
840
0
    if (s) {
841
0
        if (d) {
842
0
            while ((c = *s) && slen) {
843
0
                if (TEST_CHAR(c, T_ESCAPE_ECHO)) {
844
0
                    *d++ = '\\';
845
0
                    size++;
846
0
                    switch (c) {
847
0
                    case '\a':
848
0
                        *d++ = 'a';
849
0
                        size++;
850
0
                        found = 1;
851
0
                        break;
852
0
                    case '\b':
853
0
                        *d++ = 'b';
854
0
                        size++;
855
0
                        found = 1;
856
0
                        break;
857
0
                    case '\f':
858
0
                        *d++ = 'f';
859
0
                        size++;
860
0
                        found = 1;
861
0
                        break;
862
0
                    case '\n':
863
0
                        *d++ = 'n';
864
0
                        size++;
865
0
                        found = 1;
866
0
                        break;
867
0
                    case '\r':
868
0
                        *d++ = 'r';
869
0
                        size++;
870
0
                        found = 1;
871
0
                        break;
872
0
                    case '\t':
873
0
                        *d++ = 't';
874
0
                        size++;
875
0
                        found = 1;
876
0
                        break;
877
0
                    case '\v':
878
0
                        *d++ = 'v';
879
0
                        size++;
880
0
                        found = 1;
881
0
                        break;
882
0
                    case '\\':
883
0
                        *d++ = '\\';
884
0
                        size++;
885
0
                        found = 1;
886
0
                        break;
887
0
                    case '"':
888
0
                        if (quote) {
889
0
                            *d++ = c;
890
0
                            size++;
891
0
                            found = 1;
892
0
                        }
893
0
                        else {
894
0
                            d[-1] = c;
895
0
                        }
896
0
                        break;
897
0
                    default:
898
0
                        c2x(c, 'x', d);
899
0
                        d += 3;
900
0
                        size += 3;
901
0
                        found = 1;
902
0
                        break;
903
0
                    }
904
0
                }
905
0
                else {
906
0
                    *d++ = c;
907
0
                    size++;
908
0
                }
909
0
                ++s;
910
0
                slen--;
911
0
            }
912
0
            *d = '\0';
913
0
        }
914
0
        else {
915
0
            while ((c = *s) && slen) {
916
0
                if (TEST_CHAR(c, T_ESCAPE_ECHO)) {
917
0
                    size++;
918
0
                    switch (c) {
919
0
                    case '\a':
920
0
                    case '\b':
921
0
                    case '\f':
922
0
                    case '\n':
923
0
                    case '\r':
924
0
                    case '\t':
925
0
                    case '\v':
926
0
                    case '\\':
927
0
                        size++;
928
0
                        found = 1;
929
0
                        break;
930
0
                    case '"':
931
0
                        if (quote) {
932
0
                            size++;
933
0
                            found = 1;
934
0
                        }
935
0
                        break;
936
0
                    default:
937
0
                        size += 3;
938
0
                        found = 1;
939
0
                        break;
940
0
                    }
941
0
                }
942
0
                else {
943
0
                    size++;
944
0
                }
945
0
                ++s;
946
0
                slen--;
947
0
            }
948
0
        }
949
0
    }
950
951
0
    if (len) {
952
0
        *len = size;
953
0
    }
954
0
    if (!found) {
955
0
        return APR_NOTFOUND;
956
0
    }
957
958
0
    return APR_SUCCESS;
959
0
}
960
961
APR_DECLARE(const char *) apr_pescape_echo(apr_pool_t *p, const char *str,
962
        int quote)
963
0
{
964
0
    apr_size_t len;
965
966
0
    switch (apr_escape_echo(NULL, str, APR_ESCAPE_STRING, quote, &len)) {
967
0
    case APR_SUCCESS: {
968
0
        char *cmd = apr_palloc(p, len);
969
0
        apr_escape_echo(cmd, str, APR_ESCAPE_STRING, quote, NULL);
970
0
        return cmd;
971
0
    }
972
0
    case APR_NOTFOUND: {
973
0
        break;
974
0
    }
975
0
    }
976
977
0
    return str;
978
0
}
979
980
APR_DECLARE(apr_status_t) apr_escape_hex(char *dest, const void *src,
981
        apr_size_t srclen, int colon, apr_size_t *len)
982
0
{
983
0
    const unsigned char *in = src;
984
0
    apr_size_t size;
985
986
0
    if (!src) {
987
0
        return APR_NOTFOUND;
988
0
    }
989
990
0
    if (dest) {
991
0
        for (size = 0; size < srclen; size++) {
992
0
            if (colon && size) {
993
0
                *dest++ = ':';
994
0
            }
995
0
            *dest++ = c2x_table[in[size] >> 4];
996
0
            *dest++ = c2x_table[in[size] & 0xf];
997
0
        }
998
0
        *dest = '\0';
999
0
    }
1000
1001
0
    if (len) {
1002
0
        if (colon && srclen) {
1003
0
            *len = srclen * 3;
1004
0
        }
1005
0
        else {
1006
0
            *len = srclen * 2 + 1;
1007
0
        }
1008
0
    }
1009
1010
0
    return APR_SUCCESS;
1011
0
}
1012
1013
APR_DECLARE(const char *) apr_pescape_hex(apr_pool_t *p, const void *src,
1014
        apr_size_t srclen, int colon)
1015
0
{
1016
0
    apr_size_t len;
1017
1018
0
    switch (apr_escape_hex(NULL, src, srclen, colon, &len)) {
1019
0
    case APR_SUCCESS: {
1020
0
        char *cmd = apr_palloc(p, len);
1021
0
        apr_escape_hex(cmd, src, srclen, colon, NULL);
1022
0
        return cmd;
1023
0
    }
1024
0
    case APR_NOTFOUND: {
1025
0
        break;
1026
0
    }
1027
0
    }
1028
1029
0
    return src;
1030
0
}
1031
1032
APR_DECLARE(apr_status_t) apr_unescape_hex(void *dest, const char *str,
1033
        apr_ssize_t slen, int colon, apr_size_t *len)
1034
0
{
1035
0
    apr_size_t size = 0;
1036
0
    int flip = 0;
1037
0
    const unsigned char *s = (const unsigned char *) str;
1038
0
    unsigned char *d = (unsigned char *) dest;
1039
0
    unsigned c;
1040
0
    unsigned char u = 0;
1041
1042
0
    if (s) {
1043
0
        if (d) {
1044
0
            while ((c = *s) && slen) {
1045
1046
0
                if (!flip) {
1047
0
                    u = 0;
1048
0
                }
1049
1050
0
                if (colon && c == ':' && !flip) {
1051
0
                    ++s;
1052
0
                    slen--;
1053
0
                    continue;
1054
0
                }
1055
0
                else if (apr_isdigit(c)) {
1056
0
                    u |= c - '0';
1057
0
                }
1058
0
                else if (apr_isupper(c) && c <= 'F') {
1059
0
                    u |= c - ('A' - 10);
1060
0
                }
1061
0
                else if (apr_islower(c) && c <= 'f') {
1062
0
                    u |= c - ('a' - 10);
1063
0
                }
1064
0
                else {
1065
0
                    return APR_BADCH;
1066
0
                }
1067
1068
0
                if (flip) {
1069
0
                    *d++ = u;
1070
0
                    size++;
1071
0
                }
1072
0
                else {
1073
0
                    u <<= 4;
1074
0
                    *d = u;
1075
0
                }
1076
0
                flip = !flip;
1077
1078
0
                ++s;
1079
0
                slen--;
1080
0
            }
1081
0
        }
1082
0
        else {
1083
0
            while ((c = *s) && slen) {
1084
1085
0
                if (colon && c == ':' && !flip) {
1086
0
                    ++s;
1087
0
                    slen--;
1088
0
                    continue;
1089
0
                }
1090
0
                else if (apr_isdigit(c)) {
1091
                    /* valid */
1092
0
                }
1093
0
                else if (apr_isupper(c) && c <= 'F') {
1094
                    /* valid */
1095
0
                }
1096
0
                else if (apr_islower(c) && c <= 'f') {
1097
                    /* valid */
1098
0
                }
1099
0
                else {
1100
0
                    return APR_BADCH;
1101
0
                }
1102
1103
0
                if (flip) {
1104
0
                    size++;
1105
0
                }
1106
0
                flip = !flip;
1107
1108
0
                ++s;
1109
0
                slen--;
1110
0
            }
1111
0
        }
1112
0
    }
1113
1114
0
    if (len) {
1115
0
        *len = size;
1116
0
    }
1117
0
    if (!s) {
1118
0
        return APR_NOTFOUND;
1119
0
    }
1120
1121
0
    return APR_SUCCESS;
1122
0
}
1123
1124
APR_DECLARE(const void *) apr_punescape_hex(apr_pool_t *p, const char *str,
1125
        int colon, apr_size_t *len)
1126
0
{
1127
0
    apr_size_t size;
1128
1129
0
    switch (apr_unescape_hex(NULL, str, APR_ESCAPE_STRING, colon, &size)) {
1130
0
    case APR_SUCCESS: {
1131
0
        void *cmd = apr_palloc(p, size);
1132
0
        apr_unescape_hex(cmd, str, APR_ESCAPE_STRING, colon, len);
1133
0
        return cmd;
1134
0
    }
1135
0
    case APR_BADCH:
1136
0
    case APR_NOTFOUND: {
1137
0
        break;
1138
0
    }
1139
0
    }
1140
1141
0
    return NULL;
1142
0
}
1143
1144
APR_DECLARE(apr_status_t) apr_escape_ldap(char *escaped, const void *str,
1145
        apr_ssize_t slen, int flags, apr_size_t *len)
1146
0
{
1147
0
    apr_size_t size = 1;
1148
0
    int found = 0;
1149
0
    const unsigned char *s = (const unsigned char *) str;
1150
0
    unsigned char *d = (unsigned char *) escaped;
1151
0
    unsigned c;
1152
1153
0
    if (s) {
1154
0
        if (d) {
1155
0
            while (((c = *s) && slen) || (slen > 0)) {
1156
0
                if (((flags & APR_ESCAPE_LDAP_DN) && TEST_CHAR(c, T_ESCAPE_LDAP_DN))
1157
0
                     || ((flags & APR_ESCAPE_LDAP_FILTER) && TEST_CHAR(c, T_ESCAPE_LDAP_FILTER))) {
1158
0
                    d = c2x(c, '\\', d);
1159
0
                    size += 2;
1160
0
                    found = 1;
1161
0
                }
1162
0
                else {
1163
0
                    *d++ = c;
1164
0
                }
1165
0
                ++s;
1166
0
                size++;
1167
0
                slen--;
1168
0
            }
1169
0
            *d = '\0';
1170
0
        }
1171
0
        else {
1172
0
            while (((c = *s) && slen) || (slen > 0)) {
1173
0
                if (((flags & APR_ESCAPE_LDAP_DN) && TEST_CHAR(c, T_ESCAPE_LDAP_DN))
1174
0
                     || ((flags & APR_ESCAPE_LDAP_FILTER) && TEST_CHAR(c, T_ESCAPE_LDAP_FILTER))) {
1175
0
                    size += 2;
1176
0
                    found = 1;
1177
0
                }
1178
0
                ++s;
1179
0
                size++;
1180
0
                slen--;
1181
0
            }
1182
0
        }
1183
0
    }
1184
1185
0
    if (len) {
1186
0
        *len = size;
1187
0
    }
1188
0
    if (!found) {
1189
0
        return APR_NOTFOUND;
1190
0
    }
1191
1192
0
    return APR_SUCCESS;
1193
0
}
1194
1195
APR_DECLARE(const char *) apr_pescape_ldap(apr_pool_t *p, const void *src,
1196
        apr_ssize_t srclen, int flags)
1197
0
{
1198
0
    apr_size_t len;
1199
1200
0
    switch (apr_escape_ldap(NULL, src, srclen, flags, &len)) {
1201
0
    case APR_SUCCESS: {
1202
0
        char *encoded = apr_palloc(p, len);
1203
0
        apr_escape_ldap(encoded, src, srclen, flags, NULL);
1204
0
        return encoded;
1205
0
    }
1206
0
    case APR_NOTFOUND: {
1207
0
        break;
1208
0
    }
1209
0
    }
1210
1211
0
    return src;
1212
0
}
1213
1214
APR_DECLARE(apr_status_t) apr_escape_json(char *escaped, const char *str,
1215
        apr_ssize_t slen, int quote, apr_size_t *len)
1216
0
{
1217
0
    apr_size_t size = 1;
1218
0
    int found = quote;
1219
0
    int error = 0;
1220
0
    const unsigned char *s = (const unsigned char *) str;
1221
0
    unsigned char *d = (unsigned char *) escaped;
1222
0
    unsigned c;
1223
0
    const char invalid[3] = { 0xEF, 0xBF, 0xBD };
1224
1225
0
    if (s) {
1226
0
        if (d) {
1227
0
            if (quote) {
1228
0
                *d++ = '"';
1229
0
                size += 1;
1230
0
            }
1231
0
            while ((c = *s) && slen) {
1232
0
                if (TEST_CHAR(c, T_ESCAPE_JSON)) {
1233
0
                    switch (c) {
1234
0
                    case '\b':
1235
0
                        *d++ = '\\';
1236
0
                        *d++ = 'b';
1237
0
                        size += 2;
1238
0
                        found = 1;
1239
0
                        break;
1240
0
                    case '\f':
1241
0
                        *d++ = '\\';
1242
0
                        *d++ = 'f';
1243
0
                        size += 2;
1244
0
                        found = 1;
1245
0
                        break;
1246
0
                    case '\n':
1247
0
                        *d++ = '\\';
1248
0
                        *d++ = 'n';
1249
0
                        size += 2;
1250
0
                        found = 1;
1251
0
                        break;
1252
0
                    case '\r':
1253
0
                        *d++ = '\\';
1254
0
                        *d++ = 'r';
1255
0
                        size += 2;
1256
0
                        found = 1;
1257
0
                        break;
1258
0
                    case '\t':
1259
0
                        *d++ = '\\';
1260
0
                        *d++ = 't';
1261
0
                        size += 2;
1262
0
                        found = 1;
1263
0
                        break;
1264
0
                    case '\\':
1265
0
                        *d++ = '\\';
1266
0
                        *d++ = '\\';
1267
0
                        size += 2;
1268
0
                        found = 1;
1269
0
                        break;
1270
0
                    case '"':
1271
0
                        *d++ = '\\';
1272
0
                        *d++ = '"';
1273
0
                        size += 2; 
1274
0
                        found = 1;
1275
0
                        break;
1276
0
                    default:
1277
0
                        if (c < 0x20) {
1278
0
                            apr_snprintf((char *)d, 7, "\\u%04x", c);
1279
0
                            size += 6;
1280
0
                            d += 6; 
1281
0
                            found = 1;
1282
0
                        }
1283
0
                        else if (((c >> 7) == 0x00)) {
1284
                            /* 1 byte */
1285
0
                            memcpy(d, s, 1);
1286
0
                            d += 1;
1287
0
                            size += 1;
1288
0
                        }
1289
0
                        else if ((slen < 0 || slen > 1) && ((c >> 5) == 0x06) && s[1]) {
1290
                            /* 2 bytes */
1291
0
                            if ((slen > 0 && slen < 2) || (s[1] >> 6) != 0x02) {
1292
0
                                memcpy(d, invalid, sizeof(invalid));
1293
0
                                d += sizeof(invalid);
1294
0
                                size += sizeof(invalid);
1295
0
                                found = error = 1;
1296
0
                            }
1297
0
                            else {
1298
0
                                memcpy(d, s, 2);
1299
0
                                d += 2;
1300
0
                                size += 2;
1301
0
                                s += 1;
1302
0
                                slen -= 1;
1303
0
                            }
1304
0
                        }
1305
0
                        else if (((c >> 4) == 0x0E)) {
1306
                            /* 3 bytes */
1307
0
                            if ((slen > 0 && slen < 3) || (s[1] >> 6) != 0x02 || (s[2] >> 6) != 0x02) {
1308
0
                                memcpy(d, invalid, sizeof(invalid));
1309
0
                                size += sizeof(invalid);
1310
0
                                d += sizeof(invalid);
1311
0
                                found = error = 1;
1312
0
                            }
1313
0
                            else {
1314
0
                                memcpy(d, s, 3);
1315
0
                                d += 3;
1316
0
                                size += 3;
1317
0
                                s += 2;
1318
0
                                slen -= 2;
1319
0
                            }
1320
0
                        }
1321
0
                        else if ((c >> 3) == 0x1E) {
1322
                            /* 4 bytes */
1323
0
                            if ((slen > 0 && slen < 4) || (s[1] >> 6) != 0x02 || (s[2] >> 6) != 0x02 || (s[3] >> 6) != 0x02) {
1324
0
                                memcpy(d, invalid, sizeof(invalid));
1325
0
                                d += sizeof(invalid);
1326
0
                                size += sizeof(invalid);
1327
0
                                found = error = 1;
1328
0
                            }
1329
0
                            else {
1330
0
                                memcpy(d, s, 4);
1331
0
                                d += 4;
1332
0
                                size += 4;
1333
0
                                s += 3;
1334
0
                                slen -= 3;
1335
0
                            }
1336
0
                        }
1337
0
                        else {
1338
0
                            memcpy(d, invalid, sizeof(invalid));
1339
0
                            d += sizeof(invalid);
1340
0
                            size += sizeof(invalid);
1341
0
                            found = error = 1;
1342
0
                        }
1343
0
                        break;
1344
0
                    }
1345
0
                }
1346
0
                else {
1347
0
                    *d++ = c;
1348
0
                    size++;
1349
0
                }
1350
0
                ++s;
1351
0
                slen--;
1352
0
            }
1353
0
            if (quote) {
1354
0
                *d++ = '"';
1355
0
                size += 1;
1356
0
            }
1357
0
            *d = '\0';
1358
0
        }
1359
0
        else {
1360
0
            if (quote) {
1361
0
                size += 1;
1362
0
            }
1363
0
            while ((c = *s) && slen) {
1364
0
                if (TEST_CHAR(c, T_ESCAPE_JSON)) {
1365
0
                    switch (c) {
1366
0
                    case '\b':
1367
0
                    case '\f':
1368
0
                    case '\n':
1369
0
                    case '\r':
1370
0
                    case '\t':
1371
0
                    case '\\':
1372
0
                    case '"':
1373
0
                        size += 2;
1374
0
                        found = 1;
1375
0
                        break;
1376
0
                    default:
1377
0
                        if (c < 0x20) {
1378
0
                            size += 6; /* \uXXXX */
1379
0
                            found = 1;
1380
0
                        }
1381
0
                        else if (((c >> 7) == 0x00)) {
1382
                            /* 1 byte */
1383
0
                            size += 1;
1384
0
                        }
1385
0
                        else if ((slen < 0 || slen > 1) && ((c >> 5) == 0x06) && s[1]) {
1386
                            /* 2 bytes */
1387
0
                            if ((slen > 0 && slen < 2) || (s[1] >> 6) != 0x02) {
1388
0
                                size += sizeof(invalid);
1389
0
                                found = error = 1;
1390
0
                            }
1391
0
                            else {
1392
0
                                size += 2;
1393
0
                                s += 1;
1394
0
                                slen -= 1;
1395
0
                            }
1396
0
                        }
1397
0
                        else if (((c >> 4) == 0x0E)) {
1398
                            /* 3 bytes */
1399
0
                            if ((slen > 0 && slen < 3) || (s[1] >> 6) != 0x02 || (s[2] >> 6) != 0x02) {
1400
0
                                size += sizeof(invalid);
1401
0
                                found = error = 1;
1402
0
                            }
1403
0
                            else {
1404
0
                                size += 3;
1405
0
                                s += 2;
1406
0
                                slen -= 2;
1407
0
                            }
1408
0
                        }
1409
0
                        else if ((c >> 3) == 0x1E) {
1410
                            /* 4 bytes */
1411
0
                            if ((slen > 0 && slen < 4) || (s[1] >> 6) != 0x02 || (s[2] >> 6) != 0x02 || (s[3] >> 6) != 0x02) {
1412
0
                                size += sizeof(invalid);
1413
0
                                found = error = 1;
1414
0
                            }
1415
0
                            else {
1416
0
                                size += 4;
1417
0
                                s += 3;
1418
0
                                slen -= 3;
1419
0
                            }
1420
0
                        }
1421
0
                        else {
1422
0
                            size += sizeof(invalid);
1423
0
                            found = error = 1;
1424
0
                        }
1425
0
                    }
1426
0
                }
1427
0
                else {
1428
0
                    size++;
1429
0
                }
1430
0
                ++s;
1431
0
                slen--;
1432
0
            }
1433
0
            if (quote) {
1434
0
                size += 1;
1435
0
            }
1436
0
        }
1437
0
    }
1438
1439
0
    else if (quote) {
1440
0
        if (d) {
1441
0
            memcpy(d, "null", 5);
1442
0
        }
1443
0
        else {
1444
0
            size += 4;
1445
0
        }
1446
0
    }
1447
1448
0
    if (len) {
1449
0
        *len = size;
1450
0
    }
1451
0
    if (error) {
1452
0
        return APR_EINVAL;
1453
0
    }
1454
0
    if (!found) {
1455
0
        return APR_NOTFOUND;
1456
0
    }
1457
1458
0
    return APR_SUCCESS;
1459
0
}
1460
1461
APR_DECLARE(const char *) apr_pescape_json(apr_pool_t *p, const char *src,
1462
        apr_ssize_t srclen, int quote)
1463
0
{
1464
0
    apr_size_t len;
1465
1466
0
    switch (apr_escape_json(NULL, src, srclen, quote, &len)) {
1467
0
    case APR_NOTFOUND: {
1468
0
        break;
1469
0
    }
1470
0
    default: {
1471
0
        char *encoded = apr_palloc(p, len);
1472
0
        apr_escape_json(encoded, src, srclen, quote, NULL);
1473
0
        return encoded;
1474
0
    }
1475
0
    }
1476
1477
0
    return src;
1478
0
}
1479