/* Copyright 2006 Joachim Zobel . * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * The advantage of SAX buckets is that you are not trapped in a callback * anymore. Event handling can be done from the filters brigade loop. * The functions below are intended to help with this. */ /* XXX * Taking Advantage of SAX buckets * Loop processing replaces callback processing * Needed: * inspect-Functions to check for tags and namespaces * A way to bridge the brigade gap * A stack of buckets kept for processing * A function to read tag content? * * Keep stops brigade passing * So we can go back in the bucket chain */ #include "apr.h" #include "apr_general.h" //#include "apr_tables.h" #include "compat.h" /***************************************************************************** * Functions and Macros *****************************************************************************/ #define BUCKET_IS_SAX(b) ((b)->type == &bucket_type_sax) /** * Returns the buckets type assuming it is a SAX bucket * @param b - The SAX bucket that will be checked * @return The buckets type */ #define sax_inspect_which(b) (((bucket_sax *)(b)->data)->which) /** * Returns the buckets event assuming it is a SAX bucket * @param b - The SAX bucket that will be checked * @return The buckets event */ #define sax_inspect_event(b) (((bucket_sax *)(b)->data)->event) /** * Checks if a bucket belongs to the namespace identified by uri and prefix. If both * are given both must match. Note that an end ns bucket only has a prefix. * @param b - The SAX bucket that will be checked * @param uri - The namespace (must be a unified name), NULL means wildcard * @param prefix - The namespace by prefix (must be a unified name), NULL means wildcard * @param check_attr - if this is set, the attribute namespaces will be checked. * This will only detect start buckets. * @return The buckets start/end id */ se_id_t sax_inspect_ns(apr_bucket *b, const xml_char_t *uri, const xml_char_t *prefix, int check_attr) ; /** * Checks if a bucket is a matching end. * @param b - The bucket that will be checked * @param start - The start buckets se_id * @return !=0, if the bucket matches */ //int sax_inspect_end(apr_bucket *b, se_id_t start) ; /** * Gets the se_id * @param b - The bucket that will be checked * @return The buckets se_id, 0 if there is none */ se_id_t sax_inspect_se_id(apr_bucket *b) ; /***************************************************************************** * The start bucket stack. *****************************************************************************/ /** * We can not search forward in the bucket stream * since we may reach the end of the current brigade. * We can however turn passing brigades off and do * the processing when the end tag is reached. The * start stack exists to keep track of the start * buckets of the tags we are processing this way. */ typedef apr_array_header_t start_stack_t ; /** * Init the start_stack_t * @param ss - The pool to use * @return The new stack */ #define sax_start_stack_init(pool) apr_array_make(pool, 6, sizeof(apr_bucket_t *)) /** * Do we need to skip ap_pass_brigade? * @param ss - The start bucket stack * @return true/false */ #define sax_start_stack_keep(ss) (ss->nelts) /** * Get the top element from the start stack without popping it * @param p - The process stack * @return A pointer to the top element */ #define sax_start_stack_top(ss) ((ss->nelts>0)?((apr_bucket_t **)ss->elts+ss->nelts-1):NULL) /** * There are cases where we do not need to keep the buckets. * We do however need to track matching ends. */ typedef apr_array_header_t se_stack_t ; /** * Init the se_stack_t * @param ss - The pool to use * @return The new stack */ #define sax_se_stack_init(pool) apr_array_make(pool, 6, sizeof(se_id_t)) /** * Do we need to skip ap_pass_brigade? * @param ss - The se bucket stack * @return true/false */ #define sax_se_stack_keep(ss) (ss->nelts) /** * Get the top element from the se stack without popping it * @param p - The process stack * @return A pointer to the top element */ #define sax_se_stack_top(ss) ((ss->nelts>0)?((se_id_t *)ss->elts+ss->nelts-1):NULL) /** * Get the content of a tag. * @param fbuf - The content is written to this * @param s - The start bucket * @param e - The end bucket * @param encoded - Shall the return be XML encoded * @param delete - delete those buckets, that have been extracted * @return The number of characters written to fbuf */ apr_off_t sax_extract_tag_content(frag_buffer_t *fbuf, apr_bucket *s, apr_bucket *e, int encoded, int delete) ; /** * Extract the next attribute for the given ns * @param attr - a (start elements) array off attributes * @param uri - the unified ns uri. NULL is wildcard * @param prefix - the unified ns prefix. NULL is wildcard * @return the pointer to the next matching attribute, NULL if none was found. * If the start element already matches, it is returned. */ attr_t *sax_extract_next_attr(attr_t *attr, const xml_char_t *uri, const xml_char_t *prefix) ; /** * Extract the attribute for the given name (incl. ns) and removes it. * @param name - The name of the desired attribute * @param uri - the unified ns uri. NULL is wildcard * @param prefix - the unified ns prefix. NULL is wildcard * @return The value for the given name. If none was found, NULL is returned. */ const xml_char_t *sax_pop_attr(apr_bucket *s, const xml_char_t *name, const xml_char_t *uri, const xml_char_t *prefix) ;