00001 /** 00002 * @copyright 00003 * ==================================================================== 00004 * Copyright (c) 2000-2004 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 00023 00024 #ifndef SVN_XML_H 00025 #define SVN_XML_H 00026 00027 #include <apr.h> 00028 #include <apr_pools.h> 00029 #include <apr_hash.h> 00030 00031 #include "svn_error.h" 00032 #include "svn_string.h" 00033 00034 #ifdef __cplusplus 00035 extern "C" { 00036 #endif /* __cplusplus */ 00037 00038 /** The namespace all Subversion XML uses. */ 00039 #define SVN_XML_NAMESPACE "svn:" 00040 00041 /** Used as style argument to @c svn_xml_make_open_tag() and friends. */ 00042 enum svn_xml_open_tag_style { 00043 /** <tag ...> */ 00044 svn_xml_normal = 1, 00045 00046 /** <tag ...>, no cosmetic newline */ 00047 svn_xml_protect_pcdata, 00048 00049 /** <tag .../> */ 00050 svn_xml_self_closing 00051 }; 00052 00053 00054 00055 /** Determine if a string of character @a data of length @a len is a 00056 * safe bet for use with the svn_xml_escape_* functions found in this 00057 * header. 00058 * 00059 * Return @c TRUE if it is, @c FALSE otherwise. 00060 * 00061 * Essentially, this function exists to determine whether or not 00062 * simply running a string of bytes through the Subversion XML escape 00063 * routines will produce legitimate XML. It should only be necessary 00064 * for data which might contain bytes that cannot be safely encoded 00065 * into XML (upper ASCII and control characters, for example). 00066 */ 00067 svn_boolean_t svn_xml_is_xml_safe (const char *data, 00068 apr_size_t len); 00069 00070 00071 /** Create or append in @a *outstr an xml-escaped version of @a string, 00072 * suitable for output as character data. 00073 * 00074 * If @a *outstr is @c NULL, store a new stringbuf, else append to the 00075 * existing stringbuf there. 00076 */ 00077 void svn_xml_escape_cdata_stringbuf (svn_stringbuf_t **outstr, 00078 const svn_stringbuf_t *string, 00079 apr_pool_t *pool); 00080 00081 /** Same as @c svn_xml_escape_cdata_stringbuf, but @a string is an 00082 * @c svn_string_t. 00083 */ 00084 void svn_xml_escape_cdata_string (svn_stringbuf_t **outstr, 00085 const svn_string_t *string, 00086 apr_pool_t *pool); 00087 00088 /** Same as @c svn_xml_escape_cdata_stringbuf, but @a string is a 00089 * null-terminated C string. 00090 */ 00091 void svn_xml_escape_cdata_cstring (svn_stringbuf_t **outstr, 00092 const char *string, 00093 apr_pool_t *pool); 00094 00095 00096 /** Create or append in @a *outstr an xml-escaped version of @a string, 00097 * suitable for output as an attribute value. 00098 * 00099 * If @a *outstr is @c NULL, store a new stringbuf, else append to the 00100 * existing stringbuf there. 00101 */ 00102 void svn_xml_escape_attr_stringbuf (svn_stringbuf_t **outstr, 00103 const svn_stringbuf_t *string, 00104 apr_pool_t *pool); 00105 00106 /** Same as @c svn_xml_escape_attr_stringbuf, but @a string is an 00107 * @c svn_string_t. 00108 */ 00109 void svn_xml_escape_attr_string (svn_stringbuf_t **outstr, 00110 const svn_string_t *string, 00111 apr_pool_t *pool); 00112 00113 /** Same as @c svn_xml_escape_attr_stringbuf, but @a string is a 00114 * null-terminated C string. 00115 */ 00116 void svn_xml_escape_attr_cstring (svn_stringbuf_t **outstr, 00117 const char *string, 00118 apr_pool_t *pool); 00119 00120 00121 /*---------------------------------------------------------------*/ 00122 00123 /* Generalized Subversion XML Parsing */ 00124 00125 /** A generalized Subversion XML parser object */ 00126 typedef struct svn_xml_parser_t svn_xml_parser_t; 00127 00128 typedef void (*svn_xml_start_elem)(void *baton, 00129 const char *name, 00130 const char **atts); 00131 00132 typedef void (*svn_xml_end_elem)(void *baton, const char *name); 00133 00134 /* data is not NULL-terminated. */ 00135 typedef void (*svn_xml_char_data)(void *baton, 00136 const char *data, 00137 apr_size_t len); 00138 00139 00140 /** Create a general Subversion XML parser */ 00141 svn_xml_parser_t *svn_xml_make_parser (void *baton, 00142 svn_xml_start_elem start_handler, 00143 svn_xml_end_elem end_handler, 00144 svn_xml_char_data data_handler, 00145 apr_pool_t *pool); 00146 00147 00148 /** Free a general Subversion XML parser */ 00149 void svn_xml_free_parser (svn_xml_parser_t *svn_parser); 00150 00151 00152 /** Push @a len bytes of xml data in @a buf at @a svn_parser. 00153 * 00154 * If this is the final push, @a is_final must be set. 00155 * 00156 * An error will be returned if there was a syntax problem in the XML, 00157 * or if any of the callbacks set an error using 00158 * @c svn_xml_signal_bailout(). 00159 * 00160 * If an error is returned, the @c svn_xml_parser_t will have been freed 00161 * automatically, so the caller should not call @c svn_xml_free_parser(). 00162 */ 00163 svn_error_t *svn_xml_parse (svn_xml_parser_t *parser, 00164 const char *buf, 00165 apr_size_t len, 00166 svn_boolean_t is_final); 00167 00168 00169 00170 /** The way to officially bail out of xml parsing. 00171 * 00172 * Store @a error in @a svn_parser and set all expat callbacks to @c NULL. 00173 */ 00174 void svn_xml_signal_bailout (svn_error_t *error, 00175 svn_xml_parser_t *svn_parser); 00176 00177 00178 00179 00180 00181 /*** Helpers for dealing with the data Expat gives us. ***/ 00182 00183 /** Return the value associated with @a name in expat attribute array @a atts, 00184 * else return @c NULL. 00185 * 00186 * (There could never be a @c NULL attribute value in the XML, 00187 * although the empty string is possible.) 00188 * 00189 * @a atts is an array of c-strings: even-numbered indexes are names, 00190 * odd-numbers hold values. If all is right, it should end on an 00191 * even-numbered index pointing to @c NULL. 00192 */ 00193 const char *svn_xml_get_attr_value (const char *name, const char **atts); 00194 00195 00196 00197 /* Converting between Expat attribute lists and APR hash tables. */ 00198 00199 00200 /** Create an attribute hash from @c va_list @a ap. 00201 * 00202 * The contents of @a ap are alternating <tt>char *</tt> keys and 00203 * <tt>char *</tt> vals, terminated by a final @c NULL falling on an 00204 * odd index (zero-based). 00205 */ 00206 apr_hash_t *svn_xml_ap_to_hash (va_list ap, apr_pool_t *pool); 00207 00208 /** Create a hash that corresponds to Expat xml attribute list @a atts. 00209 * 00210 * The hash's keys and values are <tt>char *</tt>'s. 00211 * 00212 * @a atts may be null, in which case you just get an empty hash back 00213 * (this makes life more convenient for some callers). 00214 */ 00215 apr_hash_t *svn_xml_make_att_hash (const char **atts, apr_pool_t *pool); 00216 00217 00218 /** Like @c svn_xml_make_att_hash(), but takes a hash and preserves any 00219 * key/value pairs already in it. 00220 */ 00221 void svn_xml_hash_atts_preserving (const char **atts, 00222 apr_hash_t *ht, 00223 apr_pool_t *pool); 00224 00225 /** Like @c svn_xml_make_att_hash(), but takes a hash and overwrites 00226 * key/value pairs already in it that also appear in @a atts. 00227 */ 00228 void svn_xml_hash_atts_overlaying (const char **atts, 00229 apr_hash_t *ht, 00230 apr_pool_t *pool); 00231 00232 00233 00234 /* Printing XML */ 00235 00236 /** Create an XML header and return it in @a *str. 00237 * 00238 * Fully-formed XML documents should start out with a header, 00239 * something like 00240 * <?xml version="1.0" encoding="utf-8"?> 00241 * 00242 * This function returns such a header. @a *str must either be @c NULL, in 00243 * which case a new string is created, or it must point to an existing 00244 * string to be appended to. 00245 */ 00246 void svn_xml_make_header (svn_stringbuf_t **str, apr_pool_t *pool); 00247 00248 00249 /** Store a new xml tag @a tagname in @a *str. 00250 * 00251 * If @a str is @c NULL, allocate @a *str in @a pool; else append the new 00252 * tag to @a *str, allocating in @a str's pool 00253 * 00254 * Take the tag's attributes from varargs, a null-terminated list of 00255 * alternating <tt>char *</tt> key and <tt>char *</tt> val. Do xml-escaping 00256 * on each val. 00257 * 00258 * @a style is one of the enumerated styles in @c svn_xml_open_tag_style. 00259 */ 00260 void svn_xml_make_open_tag (svn_stringbuf_t **str, 00261 apr_pool_t *pool, 00262 enum svn_xml_open_tag_style style, 00263 const char *tagname, 00264 ...); 00265 00266 00267 /** Like @c svn_xml_make_open_tag, but takes a @c va_list instead of being 00268 * variadic. 00269 */ 00270 void svn_xml_make_open_tag_v (svn_stringbuf_t **str, 00271 apr_pool_t *pool, 00272 enum svn_xml_open_tag_style style, 00273 const char *tagname, 00274 va_list ap); 00275 00276 00277 /** Like @c svn_xml_make_tag, but takes a hash table of attributes 00278 * (<tt>char *</tt> keys mapping to <tt>char *</tt> values). 00279 * 00280 * You might ask, why not just provide @c svn_xml_make_tag_atts()? 00281 * 00282 * The reason is that a hash table is the most natural interface to an 00283 * attribute list; the fact that Expat uses <tt>char **</tt> atts instead is 00284 * certainly a defensible implementation decision, but since we'd have 00285 * to have special code to support such lists throughout Subversion 00286 * anyway, we might as well write that code for the natural interface 00287 * (hashes) and then convert in the few cases where conversion is 00288 * needed. Someday it might even be nice to change expat-lite to work 00289 * with apr hashes. 00290 * 00291 * See conversion functions @c svn_xml_make_att_hash() and 00292 * @c svn_xml_make_att_hash_overlaying(). Callers should use those to 00293 * convert Expat attr lists into hashes when necessary. 00294 */ 00295 void svn_xml_make_open_tag_hash (svn_stringbuf_t **str, 00296 apr_pool_t *pool, 00297 enum svn_xml_open_tag_style style, 00298 const char *tagname, 00299 apr_hash_t *attributes); 00300 00301 00302 /** Makes a close tag. */ 00303 void svn_xml_make_close_tag (svn_stringbuf_t **str, 00304 apr_pool_t *pool, 00305 const char *tagname); 00306 00307 00308 00309 #ifdef __cplusplus 00310 } 00311 #endif /* __cplusplus */ 00312 00313 #endif /* SVN_XML_H */