svn_xml.h revision 299742
1/**
2 * @copyright
3 * ====================================================================
4 *    Licensed to the Apache Software Foundation (ASF) under one
5 *    or more contributor license agreements.  See the NOTICE file
6 *    distributed with this work for additional information
7 *    regarding copyright ownership.  The ASF licenses this file
8 *    to you under the Apache License, Version 2.0 (the
9 *    "License"); you may not use this file except in compliance
10 *    with the License.  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *    Unless required by applicable law or agreed to in writing,
15 *    software distributed under the License is distributed on an
16 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 *    KIND, either express or implied.  See the License for the
18 *    specific language governing permissions and limitations
19 *    under the License.
20 * ====================================================================
21 * @endcopyright
22 *
23 * @file svn_xml.h
24 * @brief XML code shared by various Subversion libraries.
25 */
26
27#ifndef SVN_XML_H
28#define SVN_XML_H
29
30#include <apr.h>
31#include <apr_pools.h>
32#include <apr_hash.h>
33
34#include "svn_types.h"
35#include "svn_string.h"
36
37#ifdef __cplusplus
38extern "C" {
39#endif /* __cplusplus */
40
41/** The namespace all Subversion XML uses. */
42#define SVN_XML_NAMESPACE "svn:"
43
44/** Used as style argument to svn_xml_make_open_tag() and friends. */
45enum svn_xml_open_tag_style {
46  /** <tag ...> */
47  svn_xml_normal = 1,
48
49  /** <tag ...>, no cosmetic newline */
50  svn_xml_protect_pcdata,
51
52  /** <tag .../>  */
53  svn_xml_self_closing
54};
55
56
57
58/** Determine if a string of character @a data of length @a len is a
59 * safe bet for use with the svn_xml_escape_* functions found in this
60 * header.
61 *
62 * Return @c TRUE if it is, @c FALSE otherwise.
63 *
64 * Essentially, this function exists to determine whether or not
65 * simply running a string of bytes through the Subversion XML escape
66 * routines will produce legitimate XML.  It should only be necessary
67 * for data which might contain bytes that cannot be safely encoded
68 * into XML (certain control characters, for example).
69 */
70svn_boolean_t
71svn_xml_is_xml_safe(const char *data,
72                    apr_size_t len);
73
74/** Create or append in @a *outstr an xml-escaped version of @a string,
75 * suitable for output as character data.
76 *
77 * If @a *outstr is @c NULL, set @a *outstr to a new stringbuf allocated
78 * in @a pool, else append to the existing stringbuf there.
79 */
80void
81svn_xml_escape_cdata_stringbuf(svn_stringbuf_t **outstr,
82                               const svn_stringbuf_t *string,
83                               apr_pool_t *pool);
84
85/** Same as svn_xml_escape_cdata_stringbuf(), but @a string is an
86 * @c svn_string_t.
87 */
88void
89svn_xml_escape_cdata_string(svn_stringbuf_t **outstr,
90                            const svn_string_t *string,
91                            apr_pool_t *pool);
92
93/** Same as svn_xml_escape_cdata_stringbuf(), but @a string is a
94 * NULL-terminated C string.
95 */
96void
97svn_xml_escape_cdata_cstring(svn_stringbuf_t **outstr,
98                             const char *string,
99                             apr_pool_t *pool);
100
101
102/** Create or append in @a *outstr an xml-escaped version of @a string,
103 * suitable for output as an attribute value.
104 *
105 * If @a *outstr is @c NULL, set @a *outstr to a new stringbuf allocated
106 * in @a pool, else append to the existing stringbuf there.
107 */
108void
109svn_xml_escape_attr_stringbuf(svn_stringbuf_t **outstr,
110                              const svn_stringbuf_t *string,
111                              apr_pool_t *pool);
112
113/** Same as svn_xml_escape_attr_stringbuf(), but @a string is an
114 * @c svn_string_t.
115 */
116void
117svn_xml_escape_attr_string(svn_stringbuf_t **outstr,
118                           const svn_string_t *string,
119                           apr_pool_t *pool);
120
121/** Same as svn_xml_escape_attr_stringbuf(), but @a string is a
122 * NULL-terminated C string.
123 */
124void
125svn_xml_escape_attr_cstring(svn_stringbuf_t **outstr,
126                            const char *string,
127                            apr_pool_t *pool);
128
129/**
130 * Return UTF-8 string @a string if it contains no characters that are
131 * unrepresentable in XML.  Else, return a copy of @a string,
132 * allocated in @a pool, with each unrepresentable character replaced
133 * by "?\uuu", where "uuu" is the three-digit unsigned decimal value
134 * of that character.
135 *
136 * Neither the input nor the output need be valid XML; however, the
137 * output can always be safely XML-escaped.
138 *
139 * @note The current implementation treats all Unicode characters as
140 * representable, except for most ASCII control characters (the
141 * exceptions being CR, LF, and TAB, which are valid in XML).  There
142 * may be other UTF-8 characters that are invalid in XML; see
143 * http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=90591
144 * and its thread for details.
145 *
146 * @since New in 1.2.
147 */
148const char *
149svn_xml_fuzzy_escape(const char *string,
150                     apr_pool_t *pool);
151
152
153/*---------------------------------------------------------------*/
154
155/* Generalized Subversion XML Parsing */
156
157/** A generalized Subversion XML parser object */
158typedef struct svn_xml_parser_t svn_xml_parser_t;
159
160typedef void (*svn_xml_start_elem)(void *baton,
161                                   const char *name,
162                                   const char **atts);
163
164typedef void (*svn_xml_end_elem)(void *baton, const char *name);
165
166/* data is not NULL-terminated. */
167typedef void (*svn_xml_char_data)(void *baton,
168                                  const char *data,
169                                  apr_size_t len);
170
171
172/** Create a general Subversion XML parser */
173svn_xml_parser_t *
174svn_xml_make_parser(void *baton,
175                    svn_xml_start_elem start_handler,
176                    svn_xml_end_elem end_handler,
177                    svn_xml_char_data data_handler,
178                    apr_pool_t *pool);
179
180
181/** Free a general Subversion XML parser */
182void
183svn_xml_free_parser(svn_xml_parser_t *svn_parser);
184
185
186/** Push @a len bytes of xml data in @a buf at @a svn_parser.
187 *
188 * If this is the final push, @a is_final must be set.
189 *
190 * An error will be returned if there was a syntax problem in the XML,
191 * or if any of the callbacks set an error using
192 * svn_xml_signal_bailout().
193 *
194 * If an error is returned, the @c svn_xml_parser_t will have been freed
195 * automatically, so the caller should not call svn_xml_free_parser().
196 */
197svn_error_t *
198svn_xml_parse(svn_xml_parser_t *svn_parser,
199              const char *buf,
200              apr_size_t len,
201              svn_boolean_t is_final);
202
203
204
205/** The way to officially bail out of xml parsing.
206 *
207 * Store @a error in @a svn_parser and set all expat callbacks to @c NULL.
208 */
209void
210svn_xml_signal_bailout(svn_error_t *error,
211                       svn_xml_parser_t *svn_parser);
212
213
214
215
216
217/*** Helpers for dealing with the data Expat gives us. ***/
218
219/** Return the value associated with @a name in expat attribute array @a atts,
220 * else return @c NULL.
221 *
222 * (There could never be a @c NULL attribute value in the XML,
223 * although the empty string is possible.)
224 *
225 * @a atts is an array of c-strings: even-numbered indexes are names,
226 * odd-numbers hold values.  If all is right, it should end on an
227 * even-numbered index pointing to @c NULL.
228 */
229const char *
230svn_xml_get_attr_value(const char *name,
231                       const char *const *atts);
232
233
234
235/* Converting between Expat attribute lists and APR hash tables. */
236
237
238/** Create an attribute hash from @c va_list @a ap.
239 *
240 * The contents of @a ap are alternating <tt>char *</tt> keys and
241 * <tt>char *</tt> vals, terminated by a final @c NULL falling on an
242 * even index (zero-based).
243 */
244apr_hash_t *
245svn_xml_ap_to_hash(va_list ap,
246                   apr_pool_t *pool);
247
248/** Create a hash that corresponds to Expat xml attribute list @a atts.
249 *
250 * The hash's keys and values are <tt>char *</tt>'s.
251 *
252 * @a atts may be NULL, in which case you just get an empty hash back
253 * (this makes life more convenient for some callers).
254 */
255apr_hash_t *
256svn_xml_make_att_hash(const char **atts,
257                      apr_pool_t *pool);
258
259
260/** Like svn_xml_make_att_hash(), but takes a hash and preserves any
261 * key/value pairs already in it.
262 */
263void
264svn_xml_hash_atts_preserving(const char **atts,
265                             apr_hash_t *ht,
266                             apr_pool_t *pool);
267
268/** Like svn_xml_make_att_hash(), but takes a hash and overwrites
269 * key/value pairs already in it that also appear in @a atts.
270 */
271void
272svn_xml_hash_atts_overlaying(const char **atts,
273                             apr_hash_t *ht,
274                             apr_pool_t *pool);
275
276
277
278/* Printing XML */
279
280/** Create an XML header and return it in @a *str.
281 *
282 * Fully-formed XML documents should start out with a header,
283 * something like <pre>
284 *         \<?xml version="1.0" encoding="UTF-8"?\>
285 * </pre>
286 *
287 * This function returns such a header.  @a *str must either be @c NULL, in
288 * which case a new string is created, or it must point to an existing
289 * string to be appended to. @a encoding must either be NULL, in which case
290 * encoding information is omitted from the header, or must be the name of
291 * the encoding of the XML document, such as "UTF-8".
292 *
293 * @since New in 1.7.
294 */
295void
296svn_xml_make_header2(svn_stringbuf_t **str,
297                     const char *encoding,
298                     apr_pool_t *pool);
299
300/** Like svn_xml_make_header2(), but does not emit encoding information.
301 *
302 * @deprecated Provided for backward compatibility with the 1.6 API.
303 */
304SVN_DEPRECATED
305void
306svn_xml_make_header(svn_stringbuf_t **str,
307                    apr_pool_t *pool);
308
309
310/** Store a new xml tag @a tagname in @a *str.
311 *
312 * If @a *str is @c NULL, set @a *str to a new stringbuf allocated
313 * in @a pool, else append to the existing stringbuf there.
314 *
315 * Take the tag's attributes from varargs, a SVN_VA_NULL-terminated list of
316 * alternating <tt>char *</tt> key and <tt>char *</tt> val.  Do xml-escaping
317 * on each val.
318 *
319 * @a style is one of the enumerated styles in @c svn_xml_open_tag_style.
320 */
321void
322svn_xml_make_open_tag(svn_stringbuf_t **str,
323                      apr_pool_t *pool,
324                      enum svn_xml_open_tag_style style,
325                      const char *tagname,
326                      ...) SVN_NEEDS_SENTINEL_NULL;
327
328
329/** Like svn_xml_make_open_tag(), but takes a @c va_list instead of being
330 * variadic.
331 */
332void
333svn_xml_make_open_tag_v(svn_stringbuf_t **str,
334                        apr_pool_t *pool,
335                        enum svn_xml_open_tag_style style,
336                        const char *tagname,
337                        va_list ap);
338
339
340/** Like svn_xml_make_open_tag(), but takes a hash table of attributes
341 * (<tt>char *</tt> keys mapping to <tt>char *</tt> values).
342 *
343 * You might ask, why not just provide svn_xml_make_tag_atts()?
344 *
345 * The reason is that a hash table is the most natural interface to an
346 * attribute list; the fact that Expat uses <tt>char **</tt> atts instead is
347 * certainly a defensible implementation decision, but since we'd have
348 * to have special code to support such lists throughout Subversion
349 * anyway, we might as well write that code for the natural interface
350 * (hashes) and then convert in the few cases where conversion is
351 * needed.  Someday it might even be nice to change expat-lite to work
352 * with apr hashes.
353 *
354 * See conversion functions svn_xml_make_att_hash() and
355 * svn_xml_make_att_hash_overlaying().  Callers should use those to
356 * convert Expat attr lists into hashes when necessary.
357 */
358void
359svn_xml_make_open_tag_hash(svn_stringbuf_t **str,
360                           apr_pool_t *pool,
361                           enum svn_xml_open_tag_style style,
362                           const char *tagname,
363                           apr_hash_t *attributes);
364
365
366/** Store an xml close tag @a tagname in @a str.
367 *
368 * If @a *str is @c NULL, set @a *str to a new stringbuf allocated
369 * in @a pool, else append to the existing stringbuf there.
370 */
371void
372svn_xml_make_close_tag(svn_stringbuf_t **str,
373                       apr_pool_t *pool,
374                       const char *tagname);
375
376
377#ifdef __cplusplus
378}
379#endif /* __cplusplus */
380
381#endif /* SVN_XML_H */
382