1d25dac7peter/*
2d25dac7peter * log-escape.c :  Functions for escaping log items
3d25dac7peter *                 copied from Apache httpd
4d25dac7peter *
5d25dac7peter * ====================================================================
6d25dac7peter * Licensed to the Apache Software Foundation (ASF) under one or more
7d25dac7peter * contributor license agreements.  See the NOTICE file distributed with
8d25dac7peter * this work for additional information regarding copyright ownership.
9d25dac7peter * The ASF licenses this file to You under the Apache License, Version 2.0
10d25dac7peter * (the "License"); you may not use this file except in compliance with
11d25dac7peter * the License.  You may obtain a copy of the License at
12d25dac7peter *
13d25dac7peter *     http://www.apache.org/licenses/LICENSE-2.0
14d25dac7peter *
15d25dac7peter * Unless required by applicable law or agreed to in writing, software
16d25dac7peter * distributed under the License is distributed on an "AS IS" BASIS,
17d25dac7peter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18d25dac7peter * See the License for the specific language governing permissions and
19d25dac7peter * limitations under the License.
20d25dac7peter *
21d25dac7peter * ====================================================================
22d25dac7peter *    Licensed to the Apache Software Foundation (ASF) under one
23d25dac7peter *    or more contributor license agreements.  See the NOTICE file
24d25dac7peter *    distributed with this work for additional information
25d25dac7peter *    regarding copyright ownership.  The ASF licenses this file
26d25dac7peter *    to you under the Apache License, Version 2.0 (the
27d25dac7peter *    "License"); you may not use this file except in compliance
28d25dac7peter *    with the License.  You may obtain a copy of the License at
29d25dac7peter *
30d25dac7peter *      http://www.apache.org/licenses/LICENSE-2.0
31d25dac7peter *
32d25dac7peter *    Unless required by applicable law or agreed to in writing,
33d25dac7peter *    software distributed under the License is distributed on an
34d25dac7peter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
35d25dac7peter *    KIND, either express or implied.  See the License for the
36d25dac7peter *    specific language governing permissions and limitations
37d25dac7peter *    under the License.
38d25dac7peter * ====================================================================
39d25dac7peter */
40d25dac7peter
41d25dac7peter
42d25dac7peter#include <apr.h>
43d25dac7peter#define APR_WANT_STRFUNC
44d25dac7peter#include <apr_want.h>
45d25dac7peter#include "server.h"
46d25dac7peter#include "svn_ctype.h"
47d25dac7peter
48d25dac7peter/* copied from httpd-2.2.4/server/util.c */
49d25dac7peter/* c2x takes an unsigned, and expects the caller has guaranteed that
50d25dac7peter * 0 <= what < 256... which usually means that you have to cast to
51d25dac7peter * unsigned char first, because (unsigned)(char)(x) first goes through
52d25dac7peter * signed extension to an int before the unsigned cast.
53d25dac7peter *
54d25dac7peter * The reason for this assumption is to assist gcc code generation --
55d25dac7peter * the unsigned char -> unsigned extension is already done earlier in
56d25dac7peter * both uses of this code, so there's no need to waste time doing it
57d25dac7peter * again.
58d25dac7peter */
59d25dac7peterstatic const char c2x_table[] = "0123456789abcdef";
60d25dac7peter
61d25dac7peter/* copied from httpd-2.2.4/server/util.c */
62d25dac7peterstatic APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix,
63d25dac7peter                                     unsigned char *where)
64d25dac7peter{
65d25dac7peter#if APR_CHARSET_EBCDIC
66d25dac7peter    what = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)what);
67d25dac7peter#endif /*APR_CHARSET_EBCDIC*/
68d25dac7peter    *where++ = prefix;
69d25dac7peter    *where++ = c2x_table[what >> 4];
70d25dac7peter    *where++ = c2x_table[what & 0xf];
71d25dac7peter    return where;
72d25dac7peter}
73d25dac7peter
74d25dac7peter/* copied from httpd-2.2.4/server/util.c */
75d25dac7peterapr_size_t escape_errorlog_item(char *dest, const char *source,
76d25dac7peter                                apr_size_t buflen)
77d25dac7peter{
78d25dac7peter    unsigned char *d, *ep;
79d25dac7peter    const unsigned char *s;
80d25dac7peter
81d25dac7peter    if (!source || !buflen) { /* be safe */
82d25dac7peter        return 0;
83d25dac7peter    }
84d25dac7peter
85d25dac7peter    d = (unsigned char *)dest;
86d25dac7peter    s = (const unsigned char *)source;
87d25dac7peter    ep = d + buflen - 1;
88d25dac7peter
89d25dac7peter    for (; d < ep && *s; ++s) {
90d25dac7peter
91d25dac7peter        /* httpd-2.2.4/server/util.c has this:
92d25dac7peter             if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
93d25dac7peter           which does this same check with a fast lookup table.  Well,
94d25dac7peter           mostly the same; we don't escape quotes, as that does.
95d25dac7peter        */
96d25dac7peter        if (*s && (   !svn_ctype_isprint(*s)
97d25dac7peter                   || *s == '\\'
98d25dac7peter                   || svn_ctype_iscntrl(*s))) {
99d25dac7peter            *d++ = '\\';
100d25dac7peter            if (d >= ep) {
101d25dac7peter                --d;
102d25dac7peter                break;
103d25dac7peter            }
104d25dac7peter
105d25dac7peter            switch(*s) {
106d25dac7peter            case '\b':
107d25dac7peter                *d++ = 'b';
108d25dac7peter                break;
109d25dac7peter            case '\n':
110d25dac7peter                *d++ = 'n';
111d25dac7peter                break;
112d25dac7peter            case '\r':
113d25dac7peter                *d++ = 'r';
114d25dac7peter                break;
115d25dac7peter            case '\t':
116d25dac7peter                *d++ = 't';
117d25dac7peter                break;
118d25dac7peter            case '\v':
119d25dac7peter                *d++ = 'v';
120d25dac7peter                break;
121d25dac7peter            case '\\':
122d25dac7peter                *d++ = *s;
123d25dac7peter                break;
124d25dac7peter            case '"': /* no need for this in error log */
125d25dac7peter                d[-1] = *s;
126d25dac7peter                break;
127d25dac7peter            default:
128d25dac7peter                if (d >= ep - 2) {
129d25dac7peter                    ep = --d; /* break the for loop as well */
130d25dac7peter                    break;
131d25dac7peter                }
132d25dac7peter                c2x(*s, 'x', d);
133d25dac7peter                d += 3;
134d25dac7peter            }
135d25dac7peter        }
136d25dac7peter        else {
137d25dac7peter            *d++ = *s;
138d25dac7peter        }
139d25dac7peter    }
140d25dac7peter    *d = '\0';
141d25dac7peter
142d25dac7peter    return (d - (unsigned char *)dest);
143d25dac7peter}
144