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