Subversion 1.6.16

svn_xml.h

Go to the documentation of this file.
00001 /**
00002  * @copyright
00003  * ====================================================================
00004  * Copyright (c) 2000-2006, 2008 CollabNet.  All rights reserved.
00005  *
00006  * This software is licensed as described in the file COPYING, which
00007  * you should have received as part of this distribution.  The terms
00008  * are also available at http://subversion.tigris.org/license-1.html.
00009  * If newer versions of this license are posted there, you may use a
00010  * newer version instead, at your option.
00011  *
00012  * This software consists of voluntary contributions made by many
00013  * individuals.  For exact contribution history, see the revision
00014  * history and logs, available at http://subversion.tigris.org/.
00015  * ====================================================================
00016  * @endcopyright
00017  *
00018  * @file svn_xml.h
00019  * @brief XML code shared by various Subversion libraries.
00020  */
00021 
00022 #ifndef SVN_XML_H
00023 #define SVN_XML_H
00024 
00025 #include <apr.h>
00026 #include <apr_pools.h>
00027 #include <apr_hash.h>
00028 
00029 #include "svn_types.h"
00030 #include "svn_string.h"
00031 
00032 #ifdef __cplusplus
00033 extern "C" {
00034 #endif /* __cplusplus */
00035 
00036 /** The namespace all Subversion XML uses. */
00037 #define SVN_XML_NAMESPACE "svn:"
00038 
00039 /** Used as style argument to svn_xml_make_open_tag() and friends. */
00040 enum svn_xml_open_tag_style {
00041   /** <tag ...> */
00042   svn_xml_normal = 1,
00043 
00044   /** <tag ...>, no cosmetic newline */
00045   svn_xml_protect_pcdata,
00046 
00047   /** <tag .../>  */
00048   svn_xml_self_closing
00049 };
00050 
00051 
00052 
00053 /** Determine if a string of character @a data of length @a len is a
00054  * safe bet for use with the svn_xml_escape_* functions found in this
00055  * header.
00056  *
00057  * Return @c TRUE if it is, @c FALSE otherwise.
00058  *
00059  * Essentially, this function exists to determine whether or not
00060  * simply running a string of bytes through the Subversion XML escape
00061  * routines will produce legitimate XML.  It should only be necessary
00062  * for data which might contain bytes that cannot be safely encoded
00063  * into XML (certain control characters, for example).
00064  */
00065 svn_boolean_t
00066 svn_xml_is_xml_safe(const char *data,
00067                     apr_size_t len);
00068 
00069 /** Create or append in @a *outstr an xml-escaped version of @a string,
00070  * suitable for output as character data.
00071  *
00072  * If @a *outstr is @c NULL, set @a *outstr to a new stringbuf allocated
00073  * in @a pool, else append to the existing stringbuf there.
00074  */
00075 void
00076 svn_xml_escape_cdata_stringbuf(svn_stringbuf_t **outstr,
00077                                const svn_stringbuf_t *string,
00078                                apr_pool_t *pool);
00079 
00080 /** Same as svn_xml_escape_cdata_stringbuf(), but @a string is an
00081  * @c svn_string_t.
00082  */
00083 void
00084 svn_xml_escape_cdata_string(svn_stringbuf_t **outstr,
00085                             const svn_string_t *string,
00086                             apr_pool_t *pool);
00087 
00088 /** Same as svn_xml_escape_cdata_stringbuf(), but @a string is a
00089  * NULL-terminated C string.
00090  */
00091 void
00092 svn_xml_escape_cdata_cstring(svn_stringbuf_t **outstr,
00093                              const char *string,
00094                              apr_pool_t *pool);
00095 
00096 
00097 /** Create or append in @a *outstr an xml-escaped version of @a string,
00098  * suitable for output as an attribute value.
00099  *
00100  * If @a *outstr is @c NULL, set @a *outstr to a new stringbuf allocated
00101  * in @a pool, else append to the existing stringbuf there.
00102  */
00103 void
00104 svn_xml_escape_attr_stringbuf(svn_stringbuf_t **outstr,
00105                               const svn_stringbuf_t *string,
00106                               apr_pool_t *pool);
00107 
00108 /** Same as svn_xml_escape_attr_stringbuf(), but @a string is an
00109  * @c svn_string_t.
00110  */
00111 void
00112 svn_xml_escape_attr_string(svn_stringbuf_t **outstr,
00113                            const svn_string_t *string,
00114                            apr_pool_t *pool);
00115 
00116 /** Same as svn_xml_escape_attr_stringbuf(), but @a string is a
00117  * NULL-terminated C string.
00118  */
00119 void
00120 svn_xml_escape_attr_cstring(svn_stringbuf_t **outstr,
00121                             const char *string,
00122                             apr_pool_t *pool);
00123 
00124 /**
00125  * Return UTF-8 string @a string if it contains no characters that are
00126  * unrepresentable in XML.  Else, return a copy of @a string,
00127  * allocated in @a pool, with each unrepresentable character replaced
00128  * by "?\uuu", where "uuu" is the three-digit unsigned decimal value
00129  * of that character.
00130  *
00131  * Neither the input nor the output need be valid XML; however, the
00132  * output can always be safely XML-escaped.
00133  *
00134  * @note The current implementation treats all Unicode characters as
00135  * representable, except for most ASCII control characters (the
00136  * exceptions being CR, LF, and TAB, which are valid in XML).  There
00137  * may be other UTF-8 characters that are invalid in XML; see
00138  * http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=90591
00139  * and its thread for details.
00140  *
00141  * @since New in 1.2.
00142  */
00143 const char *
00144 svn_xml_fuzzy_escape(const char *string,
00145                      apr_pool_t *pool);
00146 
00147 
00148 /*---------------------------------------------------------------*/
00149 
00150 /* Generalized Subversion XML Parsing */
00151 
00152 /** A generalized Subversion XML parser object */
00153 typedef struct svn_xml_parser_t svn_xml_parser_t;
00154 
00155 typedef void (*svn_xml_start_elem)(void *baton,
00156                                    const char *name,
00157                                    const char **atts);
00158 
00159 typedef void (*svn_xml_end_elem)(void *baton, const char *name);
00160 
00161 /* data is not NULL-terminated. */
00162 typedef void (*svn_xml_char_data)(void *baton,
00163                                   const char *data,
00164                                   apr_size_t len);
00165 
00166 
00167 /** Create a general Subversion XML parser */
00168 svn_xml_parser_t *
00169 svn_xml_make_parser(void *baton,
00170                     svn_xml_start_elem start_handler,
00171                     svn_xml_end_elem end_handler,
00172                     svn_xml_char_data data_handler,
00173                     apr_pool_t *pool);
00174 
00175 
00176 /** Free a general Subversion XML parser */
00177 void
00178 svn_xml_free_parser(svn_xml_parser_t *svn_parser);
00179 
00180 
00181 /** Push @a len bytes of xml data in @a buf at @a svn_parser.
00182  *
00183  * If this is the final push, @a is_final must be set.
00184  *
00185  * An error will be returned if there was a syntax problem in the XML,
00186  * or if any of the callbacks set an error using
00187  * svn_xml_signal_bailout().
00188  *
00189  * If an error is returned, the @c svn_xml_parser_t will have been freed
00190  * automatically, so the caller should not call svn_xml_free_parser().
00191  */
00192 svn_error_t *
00193 svn_xml_parse(svn_xml_parser_t *svn_parser,
00194               const char *buf,
00195               apr_size_t len,
00196               svn_boolean_t is_final);
00197 
00198 
00199 
00200 /** The way to officially bail out of xml parsing.
00201  *
00202  * Store @a error in @a svn_parser and set all expat callbacks to @c NULL.
00203  */
00204 void
00205 svn_xml_signal_bailout(svn_error_t *error,
00206                        svn_xml_parser_t *svn_parser);
00207 
00208 
00209 
00210 
00211 
00212 /*** Helpers for dealing with the data Expat gives us. ***/
00213 
00214 /** Return the value associated with @a name in expat attribute array @a atts,
00215  * else return @c NULL.
00216  *
00217  * (There could never be a @c NULL attribute value in the XML,
00218  * although the empty string is possible.)
00219  *
00220  * @a atts is an array of c-strings: even-numbered indexes are names,
00221  * odd-numbers hold values.  If all is right, it should end on an
00222  * even-numbered index pointing to @c NULL.
00223  */
00224 const char *
00225 svn_xml_get_attr_value(const char *name,
00226                        const char **atts);
00227 
00228 
00229 
00230 /* Converting between Expat attribute lists and APR hash tables. */
00231 
00232 
00233 /** Create an attribute hash from @c va_list @a ap.
00234  *
00235  * The contents of @a ap are alternating <tt>char *</tt> keys and
00236  * <tt>char *</tt> vals, terminated by a final @c NULL falling on an
00237  * even index (zero-based).
00238  */
00239 apr_hash_t *
00240 svn_xml_ap_to_hash(va_list ap,
00241                    apr_pool_t *pool);
00242 
00243 /** Create a hash that corresponds to Expat xml attribute list @a atts.
00244  *
00245  * The hash's keys and values are <tt>char *</tt>'s.
00246  *
00247  * @a atts may be NULL, in which case you just get an empty hash back
00248  * (this makes life more convenient for some callers).
00249  */
00250 apr_hash_t *
00251 svn_xml_make_att_hash(const char **atts,
00252                       apr_pool_t *pool);
00253 
00254 
00255 /** Like svn_xml_make_att_hash(), but takes a hash and preserves any
00256  * key/value pairs already in it.
00257  */
00258 void
00259 svn_xml_hash_atts_preserving(const char **atts,
00260                              apr_hash_t *ht,
00261                              apr_pool_t *pool);
00262 
00263 /** Like svn_xml_make_att_hash(), but takes a hash and overwrites
00264  * key/value pairs already in it that also appear in @a atts.
00265  */
00266 void
00267 svn_xml_hash_atts_overlaying(const char **atts,
00268                              apr_hash_t *ht,
00269                              apr_pool_t *pool);
00270 
00271 
00272 
00273 /* Printing XML */
00274 
00275 /** Create an XML header and return it in @a *str.
00276  *
00277  * Fully-formed XML documents should start out with a header,
00278  * something like
00279  *         <?xml version="1.0" encoding="utf-8"?>
00280  *
00281  * This function returns such a header.  @a *str must either be @c NULL, in
00282  * which case a new string is created, or it must point to an existing
00283  * string to be appended to.
00284  */
00285 void
00286 svn_xml_make_header(svn_stringbuf_t **str,
00287                     apr_pool_t *pool);
00288 
00289 
00290 /** Store a new xml tag @a tagname in @a *str.
00291  *
00292  * If @a *str is @c NULL, set @a *str to a new stringbuf allocated
00293  * in @a pool, else append to the existing stringbuf there.
00294  *
00295  * Take the tag's attributes from varargs, a NULL-terminated list of
00296  * alternating <tt>char *</tt> key and <tt>char *</tt> val.  Do xml-escaping
00297  * on each val.
00298  *
00299  * @a style is one of the enumerated styles in @c svn_xml_open_tag_style.
00300  */
00301 void
00302 svn_xml_make_open_tag(svn_stringbuf_t **str,
00303                       apr_pool_t *pool,
00304                       enum svn_xml_open_tag_style style,
00305                       const char *tagname,
00306                       ...);
00307 
00308 
00309 /** Like svn_xml_make_open_tag(), but takes a @c va_list instead of being
00310  * variadic.
00311  */
00312 void
00313 svn_xml_make_open_tag_v(svn_stringbuf_t **str,
00314                         apr_pool_t *pool,
00315                         enum svn_xml_open_tag_style style,
00316                         const char *tagname,
00317                         va_list ap);
00318 
00319 
00320 /** Like svn_xml_make_open_tag(), but takes a hash table of attributes
00321  * (<tt>char *</tt> keys mapping to <tt>char *</tt> values).
00322  *
00323  * You might ask, why not just provide svn_xml_make_tag_atts()?
00324  *
00325  * The reason is that a hash table is the most natural interface to an
00326  * attribute list; the fact that Expat uses <tt>char **</tt> atts instead is
00327  * certainly a defensible implementation decision, but since we'd have
00328  * to have special code to support such lists throughout Subversion
00329  * anyway, we might as well write that code for the natural interface
00330  * (hashes) and then convert in the few cases where conversion is
00331  * needed.  Someday it might even be nice to change expat-lite to work
00332  * with apr hashes.
00333  *
00334  * See conversion functions svn_xml_make_att_hash() and
00335  * svn_xml_make_att_hash_overlaying().  Callers should use those to
00336  * convert Expat attr lists into hashes when necessary.
00337  */
00338 void
00339 svn_xml_make_open_tag_hash(svn_stringbuf_t **str,
00340                            apr_pool_t *pool,
00341                            enum svn_xml_open_tag_style style,
00342                            const char *tagname,
00343                            apr_hash_t *attributes);
00344 
00345 
00346 /** Store an xml close tag @a tagname in @a str.
00347  *
00348  * If @a *str is @c NULL, set @a *str to a new stringbuf allocated
00349  * in @a pool, else append to the existing stringbuf there.
00350  */
00351 void
00352 svn_xml_make_close_tag(svn_stringbuf_t **str,
00353                        apr_pool_t *pool,
00354                        const char *tagname);
00355 
00356 
00357 #ifdef __cplusplus
00358 }
00359 #endif /* __cplusplus */
00360 
00361 #endif /* SVN_XML_H */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines