1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #ifndef _MOD_INCLUDE_H
18 #define _MOD_INCLUDE_H 1
20 #include "apr_pools.h"
21 #include "apr_optional.h"
23 #define STARTING_SEQUENCE "<!--#"
24 #define ENDING_SEQUENCE "-->"
26 #define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
27 #define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
28 #define SIZEFMT_BYTES 0
30 #define TMP_BUF_SIZE 1024
31 #if APR_CHARSET_EBCDIC
32 #define RAW_ASCII_CHAR(ch) apr_xlate_conv_byte(ap_hdrs_from_ascii, (unsigned char)ch)
33 #else /*APR_CHARSET_EBCDIC*/
34 #define RAW_ASCII_CHAR(ch) (ch)
35 #endif /*APR_CHARSET_EBCDIC*/
37 /****************************************************************************
38 * Used to keep context information during parsing of a request for SSI tags.
39 * This is especially useful if the tag stretches across multiple buckets or
40 * brigades. This keeps track of which buckets need to be replaced with the
41 * content generated by the SSI tag.
43 * state: PRE_HEAD - State prior to finding the first character of the
44 * STARTING_SEQUENCE. Next state is PARSE_HEAD.
45 * PARSE_HEAD - State entered once the first character of the
46 * STARTING_SEQUENCE is found and exited when the
47 * the full STARTING_SEQUENCE has been matched or
48 * a match failure occurs. Next state is PRE_HEAD
50 * PARSE_TAG - State entered once the STARTING sequence has been
51 * matched. It is exited when the first character in
52 * ENDING_SEQUENCE is found. Next state is PARSE_TAIL.
53 * PARSE_TAIL - State entered from PARSE_TAG state when the first
54 * character in ENDING_SEQUENCE is encountered. This
55 * state is exited when the ENDING_SEQUENCE has been
56 * completely matched, or when a match failure occurs.
57 * Next state is PARSE_TAG or PARSED.
58 * PARSED - State entered from PARSE_TAIL once the complete
59 * ENDING_SEQUENCE has been matched. The SSI tag is
60 * processed and the SSI buckets are replaced with the
61 * SSI content during this state.
62 * parse_pos: Current matched position within the STARTING_SEQUENCE or
63 * ENDING_SEQUENCE during the PARSE_HEAD and PARSE_TAIL states.
64 * This is especially useful when the sequence spans brigades.
65 * X_start_bucket: These point to the buckets containing the first character
66 * of the STARTING_SEQUENCE, the first non-whitespace
67 * character of the tag, and the first character in the
68 * ENDING_SEQUENCE (head_, tag_, and tail_ respectively).
69 * The buckets are kept intact until the PARSED state is
70 * reached, at which time the tag is consolidated and the
71 * buckets are released. The buckets that these point to
72 * have all been set aside in the ssi_tag_brigade (along
73 * with all of the intervening buckets).
74 * X_start_index: The index points within the specified bucket contents
75 * where the first character of the STARTING_SEQUENCE,
76 * the first non-whitespace character of the tag, and the
77 * first character in the ENDING_SEQUENCE can be found
78 * (head_, tag_, and tail_ respectively).
79 * combined_tag: Once the PARSED state is reached the tag is collected from
80 * the bucket(s) in the ssi_tag_brigade into this contiguous
81 * buffer. The buckets in the ssi_tag_brigade are released
82 * and the tag is processed.
83 * curr_tag_pos: Ptr to the combined_tag buffer indicating the current
85 * tag_length: The number of bytes in the actual tag (excluding the
86 * STARTING_SEQUENCE, leading and trailing whitespace,
87 * and ENDING_SEQUENCE). This length is computed as the
88 * buckets are parsed and set aside during the PARSE_TAG state.
89 * ssi_tag_brigade: The temporary brigade used by this filter to set aside
90 * the buckets containing parts of the ssi tag and headers.
93 /* I keep this stuff here, because of binary compat. It probably doesn't care,
96 #ifdef MOD_INCLUDE_REDESIGN
97 typedef enum {PRE_HEAD, BLOW_PARSE_HEAD, BLOW_PARSE_DIRECTIVE, PARSE_TAG,
98 BLOW_PARSE_TAIL, PARSED} states;
100 typedef enum {PRE_HEAD, PARSE_HEAD, PARSE_DIRECTIVE, PARSE_TAG, PARSE_TAIL,
104 /** forward referenced as it needs to be held on the context */
105 typedef struct bndm_t bndm_t;
107 typedef struct include_filter_ctx {
109 long flags; /* See the FLAG_XXXXX definitions. */
110 int if_nesting_level;
111 apr_size_t parse_pos;
117 apr_bucket *head_start_bucket;
118 apr_size_t head_start_index;
120 apr_bucket *tag_start_bucket;
121 apr_size_t tag_start_index;
123 apr_bucket *tail_start_bucket;
124 apr_size_t tail_start_index;
128 apr_size_t directive_length;
129 apr_size_t tag_length;
132 char *error_str_override;
134 char *time_str_override;
137 apr_bucket_brigade *ssi_tag_brigade;
138 bndm_t *start_seq_pat;
143 regmatch_t (*re_result)[10];
146 /* These flags are used to set flag bits. */
147 #define FLAG_PRINTING 0x00000001 /* Printing conditional lines. */
148 #define FLAG_COND_TRUE 0x00000002 /* Conditional eval'd to true. */
149 #define FLAG_SIZE_IN_BYTES 0x00000004 /* Sizes displayed in bytes. */
150 #define FLAG_NO_EXEC 0x00000008 /* No Exec in current context. */
152 /* These flags are used to clear flag bits. */
153 #define FLAG_SIZE_ABBREV 0xFFFFFFFB /* Reset SIZE_IN_BYTES bit. */
154 #define FLAG_CLEAR_PRINT_COND 0xFFFFFFFC /* Reset PRINTING and COND_TRUE*/
155 #define FLAG_CLEAR_PRINTING 0xFFFFFFFE /* Reset just PRINTING bit. */
157 #define CREATE_ERROR_BUCKET(cntx, t_buck, h_ptr, ins_head) \
159 /* XXX: it'd probably be nice to use a pool bucket here */ \
160 t_buck = apr_bucket_heap_create(cntx->error_str, \
161 strlen(cntx->error_str), \
162 NULL, h_ptr->list); \
163 APR_BUCKET_INSERT_BEFORE(h_ptr, t_buck); \
165 if (ins_head == NULL) { \
170 /* Make sure to check the return code rc. If it is anything other
171 * than APR_SUCCESS, then you should return this value up the
174 #define SPLIT_AND_PASS_PRETAG_BUCKETS(brgd, cntxt, next, rc) \
175 if ((APR_BRIGADE_EMPTY((cntxt)->ssi_tag_brigade)) && \
176 ((cntxt)->head_start_bucket != NULL)) { \
177 apr_bucket_brigade *tag_plus; \
179 tag_plus = apr_brigade_split((brgd), (cntxt)->head_start_bucket); \
180 if ((cntxt)->output_flush) { \
181 APR_BRIGADE_INSERT_TAIL((brgd), apr_bucket_flush_create((brgd)->bucket_alloc)); \
183 (rc) = ap_pass_brigade((next), (brgd)); \
184 (cntxt)->bytes_parsed = 0; \
189 typedef int (include_handler_fn_t)(include_ctx_t *ctx, apr_bucket_brigade **bb,
190 request_rec *r, ap_filter_t *f, apr_bucket *head_ptr,
191 apr_bucket **inserted_head);
193 APR_DECLARE_OPTIONAL_FN(void, ap_ssi_get_tag_and_value, (include_ctx_t *ctx,
197 APR_DECLARE_OPTIONAL_FN(char*, ap_ssi_parse_string, (request_rec *r,
203 APR_DECLARE_OPTIONAL_FN(void, ap_register_include_handler,
204 (char *tag, include_handler_fn_t *func));
206 #endif /* MOD_INCLUDE */