Subversion 1.6.16
|
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 */