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