1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
#ifndef _MOD_INCLUDE_H
#define _MOD_INCLUDE_H 1
#include "apr_pools.h"
#include "apr_optional.h"
#define STARTING_SEQUENCE "<!--#"
#define ENDING_SEQUENCE "-->"
#define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
#define SIZEFMT_BYTES 0
#define SIZEFMT_KMG 1
#define TMP_BUF_SIZE 1024
#if APR_CHARSET_EBCDIC
#define RAW_ASCII_CHAR(ch) apr_xlate_conv_byte(ap_hdrs_from_ascii, (unsigned char)ch)
#else /*APR_CHARSET_EBCDIC*/
#define RAW_ASCII_CHAR(ch) (ch)
#endif /*APR_CHARSET_EBCDIC*/
/****************************************************************************
* Used to keep context information during parsing of a request for SSI tags.
* This is especially useful if the tag stretches across multiple buckets or
* brigades. This keeps track of which buckets need to be replaced with the
* content generated by the SSI tag.
*
* state: PRE_HEAD - State prior to finding the first character of the
* STARTING_SEQUENCE. Next state is PARSE_HEAD.
* PARSE_HEAD - State entered once the first character of the
* STARTING_SEQUENCE is found and exited when the
* the full STARTING_SEQUENCE has been matched or
* a match failure occurs. Next state is PRE_HEAD
* or PARSE_TAG.
* PARSE_TAG - State entered once the STARTING sequence has been
* matched. It is exited when the first character in
* ENDING_SEQUENCE is found. Next state is PARSE_TAIL.
* PARSE_TAIL - State entered from PARSE_TAG state when the first
* character in ENDING_SEQUENCE is encountered. This
* state is exited when the ENDING_SEQUENCE has been
* completely matched, or when a match failure occurs.
* Next state is PARSE_TAG or PARSED.
* PARSED - State entered from PARSE_TAIL once the complete
* ENDING_SEQUENCE has been matched. The SSI tag is
* processed and the SSI buckets are replaced with the
* SSI content during this state.
* parse_pos: Current matched position within the STARTING_SEQUENCE or
* ENDING_SEQUENCE during the PARSE_HEAD and PARSE_TAIL states.
* This is especially useful when the sequence spans brigades.
* X_start_bucket: These point to the buckets containing the first character
* of the STARTING_SEQUENCE, the first non-whitespace
* character of the tag, and the first character in the
* ENDING_SEQUENCE (head_, tag_, and tail_ respectively).
* The buckets are kept intact until the PARSED state is
* reached, at which time the tag is consolidated and the
* buckets are released. The buckets that these point to
* have all been set aside in the ssi_tag_brigade (along
* with all of the intervening buckets).
* X_start_index: The index points within the specified bucket contents
* where the first character of the STARTING_SEQUENCE,
* the first non-whitespace character of the tag, and the
* first character in the ENDING_SEQUENCE can be found
* (head_, tag_, and tail_ respectively).
* combined_tag: Once the PARSED state is reached the tag is collected from
* the bucket(s) in the ssi_tag_brigade into this contiguous
* buffer. The buckets in the ssi_tag_brigade are released
* and the tag is processed.
* curr_tag_pos: Ptr to the combined_tag buffer indicating the current
* parse position.
* tag_length: The number of bytes in the actual tag (excluding the
* STARTING_SEQUENCE, leading and trailing whitespace,
* and ENDING_SEQUENCE). This length is computed as the
* buckets are parsed and set aside during the PARSE_TAG state.
* ssi_tag_brigade: The temporary brigade used by this filter to set aside
* the buckets containing parts of the ssi tag and headers.
*/
/* I keep this stuff here, because of binary compat. It probably doesn't care,
* but who knows ...?
*/
#ifdef MOD_INCLUDE_REDESIGN
typedef enum {PRE_HEAD, BLOW_PARSE_HEAD, BLOW_PARSE_DIRECTIVE, PARSE_TAG,
BLOW_PARSE_TAIL, PARSED} states;
#else
typedef enum {PRE_HEAD, PARSE_HEAD, PARSE_DIRECTIVE, PARSE_TAG, PARSE_TAIL,
PARSED} states;
#endif
/** forward referenced as it needs to be held on the context */
typedef struct bndm_t bndm_t;
typedef struct include_filter_ctx {
states state;
long flags; /* See the FLAG_XXXXX definitions. */
int if_nesting_level;
apr_size_t parse_pos;
int bytes_parsed;
apr_status_t status;
int output_now;
int output_flush;
apr_bucket *head_start_bucket;
apr_size_t head_start_index;
apr_bucket *tag_start_bucket;
apr_size_t tag_start_index;
apr_bucket *tail_start_bucket;
apr_size_t tail_start_index;
char *combined_tag;
char *curr_tag_pos;
apr_size_t directive_length;
apr_size_t tag_length;
char *error_str;
char *error_str_override;
char *time_str;
char *time_str_override;
apr_pool_t *pool;
apr_bucket_brigade *ssi_tag_brigade;
bndm_t *start_seq_pat;
char *start_seq;
int start_seq_len;
char *end_seq;
char *re_string;
regmatch_t (*re_result)[10];
} include_ctx_t;
/* These flags are used to set flag bits. */
#define FLAG_PRINTING 0x00000001 /* Printing conditional lines. */
#define FLAG_COND_TRUE 0x00000002 /* Conditional eval'd to true. */
#define FLAG_SIZE_IN_BYTES 0x00000004 /* Sizes displayed in bytes. */
#define FLAG_NO_EXEC 0x00000008 /* No Exec in current context. */
/* These flags are used to clear flag bits. */
#define FLAG_SIZE_ABBREV 0xFFFFFFFB /* Reset SIZE_IN_BYTES bit. */
#define FLAG_CLEAR_PRINT_COND 0xFFFFFFFC /* Reset PRINTING and COND_TRUE*/
#define FLAG_CLEAR_PRINTING 0xFFFFFFFE /* Reset just PRINTING bit. */
#define CREATE_ERROR_BUCKET(cntx, t_buck, h_ptr, ins_head) \
{ \
/* XXX: it'd probably be nice to use a pool bucket here */ \
t_buck = apr_bucket_heap_create(cntx->error_str, \
strlen(cntx->error_str), \
NULL, h_ptr->list); \
APR_BUCKET_INSERT_BEFORE(h_ptr, t_buck); \
\
if (ins_head == NULL) { \
ins_head = t_buck; \
} \
}
/* Make sure to check the return code rc. If it is anything other
* than APR_SUCCESS, then you should return this value up the
* call chain.
*/
#define SPLIT_AND_PASS_PRETAG_BUCKETS(brgd, cntxt, next, rc) \
if ((APR_BRIGADE_EMPTY((cntxt)->ssi_tag_brigade)) && \
((cntxt)->head_start_bucket != NULL)) { \
apr_bucket_brigade *tag_plus; \
\
tag_plus = apr_brigade_split((brgd), (cntxt)->head_start_bucket); \
if ((cntxt)->output_flush) { \
APR_BRIGADE_INSERT_TAIL((brgd), apr_bucket_flush_create((brgd)->bucket_alloc)); \
} \
(rc) = ap_pass_brigade((next), (brgd)); \
(cntxt)->bytes_parsed = 0; \
(brgd) = tag_plus; \
}
typedef int (include_handler_fn_t)(include_ctx_t *ctx, apr_bucket_brigade **bb,
request_rec *r, ap_filter_t *f, apr_bucket *head_ptr,
apr_bucket **inserted_head);
APR_DECLARE_OPTIONAL_FN(void, ap_ssi_get_tag_and_value, (include_ctx_t *ctx,
char **tag,
char **tag_val,
int dodecode));
APR_DECLARE_OPTIONAL_FN(char*, ap_ssi_parse_string, (request_rec *r,
include_ctx_t *ctx,
const char *in,
char *out,
apr_size_t length,
int leave_name));
APR_DECLARE_OPTIONAL_FN(void, ap_register_include_handler,
(char *tag, include_handler_fn_t *func));
#endif /* MOD_INCLUDE */
|