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 * @file apr_escape.h
18 * @brief APR-UTIL Escaping
19 */
20#ifndef APR_ESCAPE_H
21#define APR_ESCAPE_H
22#include "apr.h"
23#include "apr_general.h"
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28/**
29 * @defgroup APR_Util_Escaping Escape functions
30 * @ingroup APR
31 * @{
32 */
33
34/* Simple escape/unescape functions.
35 *
36 * The design goal of these functions are:
37 *
38 * - Avoid unnecessary work.
39 *
40 * In most cases the strings passed in do not need to be escaped at all. In
41 * these cases the original string will be returned.
42 *
43 * - Lowest possible memory footprint.
44 *
45 * The amount of memory allocated for a given encoding is calculated based
46 * on the exact amount of memory needed, and not the theoretical worst case
47 * scenario.
48 *
49 */
50
51/**
52 * When passing a string to one of the escape functions, this value can be
53 * passed to indicate a string-valued key, and have the length computed
54 * automatically.
55 */
56#define APR_ESCAPE_STRING      (-1)
57
58/**
59 * Apply LDAP distinguished name escaping as per RFC4514.
60 */
61#define APR_ESCAPE_LDAP_DN     (0x01)
62
63/**
64 * Apply LDAP filter escaping as per RFC4515.
65 */
66#define APR_ESCAPE_LDAP_FILTER (0x02)
67
68/**
69 * Apply both RFC4514 and RFC4515 LDAP escaping.
70 */
71#define APR_ESCAPE_LDAP_ALL    (0x03)
72
73/**
74 * Perform shell escaping on the provided string.
75 *
76 * Shell escaping causes characters to be prefixed with a '\' character.
77 * @param escaped Optional buffer to write the encoded string, can be
78 * NULL
79 * @param str The original string
80 * @param slen The length of the original string, or APR_ESCAPE_STRING
81 * @param len If present, returns the length of the string
82 * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
83 * detected or the string was NULL
84 */
85APR_DECLARE(apr_status_t) apr_escape_shell(char *escaped, const char *str,
86        apr_ssize_t slen, apr_size_t *len);
87
88/**
89 * Perform shell escaping on the provided string, returning the result
90 * from the pool.
91 *
92 * Shell escaping causes characters to be prefixed with a '\' character.
93 *
94 * If no characters were escaped, the original string is returned.
95 * @param p Pool to allocate from
96 * @param str The original string
97 * @return the encoded string, allocated from the pool, or the original
98 * string if no escaping took place or the string was NULL.
99 */
100APR_DECLARE(const char *) apr_pescape_shell(apr_pool_t *p, const char *str)
101        __attribute__((nonnull(1)));
102
103/**
104 * Unescapes a URL, leaving reserved characters intact.
105 * @param escaped Optional buffer to write the encoded string, can be
106 * NULL
107 * @param url String to be unescaped
108 * @param slen The length of the original url, or APR_ESCAPE_STRING
109 * @param forbid Optional list of forbidden characters, in addition to
110 * 0x00
111 * @param reserved Optional list of reserved characters that will be
112 * left unescaped
113 * @param plus If non zero, '+' is converted to ' ' as per
114 * application/x-www-form-urlencoded encoding
115 * @param len If set, the length of the escaped string will be returned
116 * @return APR_SUCCESS on success, APR_NOTFOUND if no characters are
117 * decoded or the string is NULL, APR_EINVAL if a bad escape sequence is
118 * found, APR_BADCH if a character on the forbid list is found.
119 */
120APR_DECLARE(apr_status_t) apr_unescape_url(char *escaped, const char *url,
121        apr_ssize_t slen, const char *forbid, const char *reserved, int plus,
122        apr_size_t *len);
123
124/**
125 * Unescapes a URL, leaving reserved characters intact, returning the
126 * result from a pool.
127 * @param p Pool to allocate from
128 * @param url String to be unescaped in place
129 * @param forbid Optional list of forbidden characters, in addition to
130 * 0x00
131 * @param reserved Optional list of reserved characters that will be
132 * left unescaped
133 * @param plus If non zero, '+' is converted to ' ' as per
134 * application/x-www-form-urlencoded encoding
135 * @return A string allocated from the pool on success, the original string
136 * if no characters are decoded, or NULL if a bad escape sequence is found
137 * or if a character on the forbid list is found, or if the original string
138 * was NULL.
139 */
140APR_DECLARE(const char *) apr_punescape_url(apr_pool_t *p, const char *url,
141        const char *forbid, const char *reserved, int plus)
142        __attribute__((nonnull(1)));
143
144/**
145 * Escape a path segment, as defined in RFC1808.
146 * @param escaped Optional buffer to write the encoded string, can be
147 * NULL
148 * @param str The original string
149 * @param slen The length of the original string, or APR_ESCAPE_STRING
150 * @param len If present, returns the length of the string
151 * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
152 * detected or the string was NULL
153 */
154APR_DECLARE(apr_status_t) apr_escape_path_segment(char *escaped,
155        const char *str, apr_ssize_t slen, apr_size_t *len);
156
157/**
158 * Escape a path segment, as defined in RFC1808, returning the result from a
159 * pool.
160 * @param p Pool to allocate from
161 * @param str String to be escaped
162 * @return A string allocated from the pool on success, the original string
163 * if no characters are encoded or the string is NULL.
164 */
165APR_DECLARE(const char *) apr_pescape_path_segment(apr_pool_t *p,
166        const char *str) __attribute__((nonnull(1)));
167
168/**
169 * Converts an OS path to a URL, in an OS dependent way, as defined in RFC1808.
170 * In all cases if a ':' occurs before the first '/' in the URL, the URL should
171 * be prefixed with "./" (or the ':' escaped). In the case of Unix, this means
172 * leaving '/' alone, but otherwise doing what escape_path_segment() does. For
173 * efficiency reasons, we don't use escape_path_segment(), which is provided for
174 * reference. Again, RFC 1808 is where this stuff is defined.
175 *
176 * If partial is set, os_escape_path() assumes that the path will be appended to
177 * something with a '/' in it (and thus does not prefix "./").
178 * @param escaped Optional buffer to write the encoded string, can be
179 * NULL
180 * @param path The original string
181 * @param slen The length of the original string, or APR_ESCAPE_STRING
182 * @param partial If non zero, suppresses the prepending of "./"
183 * @param len If present, returns the length of the string
184 * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
185 * detected or if the string was NULL
186 */
187APR_DECLARE(apr_status_t) apr_escape_path(char *escaped, const char *path,
188        apr_ssize_t slen, int partial, apr_size_t *len);
189
190/**
191 * Converts an OS path to a URL, in an OS dependent way, as defined in RFC1808,
192 * returning the result from a pool.
193 *
194 * In all cases if a ':' occurs before the first '/' in the URL, the URL should
195 * be prefixed with "./" (or the ':' escaped). In the case of Unix, this means
196 * leaving '/' alone, but otherwise doing what escape_path_segment() does. For
197 * efficiency reasons, we don't use escape_path_segment(), which is provided for
198 * reference. Again, RFC 1808 is where this stuff is defined.
199 *
200 * If partial is set, os_escape_path() assumes that the path will be appended to
201 * something with a '/' in it (and thus does not prefix "./").
202 * @param p Pool to allocate from
203 * @param str The original string
204 * @param partial If non zero, suppresses the prepending of "./"
205 * @return A string allocated from the pool on success, the original string
206 * if no characters are encoded or if the string was NULL.
207 */
208APR_DECLARE(const char *) apr_pescape_path(apr_pool_t *p, const char *str,
209        int partial) __attribute__((nonnull(1)));
210
211/**
212 * Urlencode a string, as defined in
213 * http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1.
214 * @param escaped Optional buffer to write the encoded string, can be
215 * NULL
216 * @param str The original string
217 * @param slen The length of the original string, or APR_ESCAPE_STRING
218 * @param len If present, returns the length of the string
219 * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
220 * detected or if the stirng was NULL
221 */
222APR_DECLARE(apr_status_t) apr_escape_urlencoded(char *escaped, const char *str,
223        apr_ssize_t slen, apr_size_t *len);
224
225/**
226 * Urlencode a string, as defined in
227 * http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1, returning
228 * the result from a pool.
229 * @param p Pool to allocate from
230 * @param str String to be escaped
231 * @return A string allocated from the pool on success, the original string
232 * if no characters are encoded or if the string was NULL.
233 */
234APR_DECLARE(const char *) apr_pescape_urlencoded(apr_pool_t *p,
235        const char *str) __attribute__((nonnull(1)));
236
237/**
238 * Apply entity encoding to a string. Characters are replaced as follows:
239 * '<' becomes '\&lt;', '>' becomes '\&gt;', '&' becomes '\&amp;', the
240 * double quote becomes '\&quot;" and the single quote becomes '\&apos;'.
241 *
242 * If toasc is not zero, any non ascii character will be encoded as
243 * '%\#ddd;', where ddd is the decimal code of the character.
244 * @param escaped Optional buffer to write the encoded string, can be
245 * NULL
246 * @param str The original string
247 * @param slen The length of the original string, or APR_ESCAPE_STRING
248 * @param toasc If non zero, encode non ascii characters
249 * @param len If present, returns the length of the string
250 * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
251 * detected or the string was NULL
252 */
253APR_DECLARE(apr_status_t) apr_escape_entity(char *escaped, const char *str,
254        apr_ssize_t slen, int toasc, apr_size_t *len);
255
256/**
257 * Apply entity encoding to a string, returning the result from a pool.
258 * Characters are replaced as follows: '<' becomes '\&lt;', '>' becomes
259 * '\&gt;', '&' becomes '\&amp;', the double quote becomes '\&quot;" and the
260 * single quote becomes '\&apos;'.
261 * @param p Pool to allocate from
262 * @param str The original string
263 * @param toasc If non zero, encode non ascii characters
264 * @return A string allocated from the pool on success, the original string
265 * if no characters are encoded or the string is NULL.
266 */
267APR_DECLARE(const char *) apr_pescape_entity(apr_pool_t *p, const char *str,
268        int toasc) __attribute__((nonnull(1)));
269
270/**
271 * Decodes html entities or numeric character references in a string. If
272 * the string to be unescaped is syntactically incorrect, then the
273 * following fixups will be made:
274 * unknown entities will be left undecoded;
275 * references to unused numeric characters will be deleted.
276 * In particular, &#00; will not be decoded, but will be deleted.
277 * @param unescaped Optional buffer to write the encoded string, can be
278 * NULL
279 * @param str The original string
280 * @param slen The length of the original string, or APR_ESCAPE_STRING
281 * @param len If present, returns the length of the string
282 * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
283 * detected or the string was NULL
284 */
285APR_DECLARE(apr_status_t) apr_unescape_entity(char *unescaped, const char *str,
286        apr_ssize_t slen, apr_size_t *len);
287
288/**
289 * Decodes html entities or numeric character references in a string. If
290 * the string to be unescaped is syntactically incorrect, then the
291 * following fixups will be made:
292 * unknown entities will be left undecoded;
293 * references to unused numeric characters will be deleted.
294 * In particular, &#00; will not be decoded, but will be deleted.
295 * @param p Pool to allocate from
296 * @param str The original string
297 * @return A string allocated from the pool on success, the original string
298 * if no characters are encoded or the string is NULL.
299 */
300APR_DECLARE(const char *) apr_punescape_entity(apr_pool_t *p, const char *str)
301        __attribute__((nonnull(1)));
302
303/**
304 * Escape control characters in a string, as performed by the shell's
305 * 'echo' command. Characters are replaced as follows:
306 * \\a alert (bell), \\b backspace, \\f form feed, \\n new line, \\r carriage
307 * return, \\t horizontal tab, \\v vertical tab, \\ backslash.
308 *
309 * Any non ascii character will be encoded as '\\xHH', where HH is the hex
310 * code of the character.
311 *
312 * If quote is not zero, the double quote character will also be escaped.
313 * @param escaped Optional buffer to write the encoded string, can be
314 * NULL
315 * @param str The original string
316 * @param slen The length of the original string, or APR_ESCAPE_STRING
317 * @param quote If non zero, encode double quotes
318 * @param len If present, returns the length of the string
319 * @return APR_SUCCESS, or APR_NOTFOUND if no changes to the string were
320 * detected or the string was NULL
321 */
322APR_DECLARE(apr_status_t) apr_escape_echo(char *escaped, const char *str,
323        apr_ssize_t slen, int quote, apr_size_t *len);
324
325/**
326 * Escape control characters in a string, as performed by the shell's
327 * 'echo' command, and return the results from a pool. Characters are
328 * replaced as follows: \\a alert (bell), \\b backspace, \\f form feed,
329 * \\n new line, \\r carriage return, \\t horizontal tab, \\v vertical tab,
330 * \\ backslash.
331 *
332 * Any non ascii character will be encoded as '\\xHH', where HH is the hex
333 * code of the character.
334 *
335 * If quote is not zero, the double quote character will also be escaped.
336 * @param p Pool to allocate from
337 * @param str The original string
338 * @param quote If non zero, encode double quotes
339 * @return A string allocated from the pool on success, the original string
340 * if no characters are encoded or the string is NULL.
341 */
342APR_DECLARE(const char *) apr_pescape_echo(apr_pool_t *p, const char *str,
343        int quote);
344
345/**
346 * Convert binary data to a hex encoding.
347 * @param dest The destination buffer, can be NULL
348 * @param src The original buffer
349 * @param srclen The length of the original buffer
350 * @param colon If not zero, insert colon characters between hex digits.
351 * @param len If present, returns the length of the string
352 * @return APR_SUCCESS, or APR_NOTFOUND if the string was NULL
353 */
354APR_DECLARE(apr_status_t) apr_escape_hex(char *dest, const void *src,
355        apr_size_t srclen, int colon, apr_size_t *len);
356
357/**
358 * Convert binary data to a hex encoding, and return the results from a
359 * pool.
360 * @param p Pool to allocate from
361 * @param src The original buffer
362 * @param slen The length of the original buffer
363 * @param colon If not zero, insert colon characters between hex digits.
364 * @return A zero padded buffer allocated from the pool on success, or
365 * NULL if src was NULL.
366 */
367APR_DECLARE(const char *) apr_pescape_hex(apr_pool_t *p, const void *src,
368        apr_size_t slen, int colon) __attribute__((nonnull(1)));
369
370/**
371 * Convert hex encoded string to binary data.
372 * @param dest The destination buffer, can be NULL
373 * @param str The original buffer
374 * @param slen The length of the original buffer
375 * @param colon If not zero, ignore colon characters between hex digits.
376 * @param len If present, returns the length of the string
377 * @return APR_SUCCESS, or APR_NOTFOUND if the string was NULL, or APR_BADCH
378 * if a non hex character is present.
379 */
380APR_DECLARE(apr_status_t) apr_unescape_hex(void *dest, const char *str,
381        apr_ssize_t slen, int colon, apr_size_t *len);
382
383/**
384 * Convert hex encoding to binary data, and return the results from a pool.
385 * If the colon character appears between pairs of hex digits, it will be
386 * ignored.
387 * @param p Pool to allocate from
388 * @param str The original string
389 * @param colon If not zero, ignore colon characters between hex digits.
390 * @param len If present, returns the length of the final buffer
391 * @return A buffer allocated from the pool on success, or NULL if src was
392 * NULL, or a bad character was present.
393 */
394APR_DECLARE(const void *) apr_punescape_hex(apr_pool_t *p, const char *str,
395        int colon, apr_size_t *len);
396
397/**
398 * Apply LDAP escaping to binary data. Characters from RFC4514 and RFC4515
399 * are escaped with their hex equivalents.
400 * @param dest The destination buffer, can be NULL
401 * @param src The original buffer
402 * @param srclen The length of the original buffer
403 * @param flags APR_ESCAPE_LDAP_DN for RFC4514, APR_ESCAPE_LDAP_FILTER for
404 * RFC4515, APR_ESCAPE_LDAP_ALL for both
405 * @param len If present, returns the length of the string
406 * @return APR_SUCCESS, or APR_NOTFOUND if the string was NULL
407 */
408APR_DECLARE(apr_status_t) apr_escape_ldap(char *dest, const void *src,
409        apr_ssize_t srclen, int flags, apr_size_t *len);
410
411/**
412 * Apply LDAP escaping to binary data, and return the results from a
413 * pool. Characters from RFC4514 and RFC4515 are escaped with their hex
414 * equivalents.
415 * @param p Pool to allocate from
416 * @param src The original buffer
417 * @param slen The length of the original buffer
418 * @param flags APR_ESCAPE_LDAP_DN for RFC4514, APR_ESCAPE_LDAP_FILTER for
419 * RFC4515, APR_ESCAPE_LDAP_ALL for both
420 * @return A zero padded buffer allocated from the pool on success, or
421 * NULL if src was NULL.
422 */
423APR_DECLARE(const char *) apr_pescape_ldap(apr_pool_t *p, const void *src,
424        apr_ssize_t slen, int flags) __attribute__((nonnull(1)));
425
426/** @} */
427#ifdef __cplusplus
428}
429#endif
430
431#endif	/* !APR_ESCAPE_H */
432