Apache HTTPD
mod_data.c
Go to the documentation of this file.
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17/*
18 * mod_data.c --- Turn the response into an rfc2397 data URL, suitable for
19 * displaying as inline content on a page.
20 */
21
22#include "apr.h"
23#include "apr_strings.h"
24#include "apr_buckets.h"
25#include "apr_base64.h"
26#include "apr_lib.h"
27
28#include "ap_config.h"
29#include "util_filter.h"
30#include "httpd.h"
31#include "http_config.h"
32#include "http_log.h"
33#include "http_request.h"
34#include "http_protocol.h"
35
36#define DATA_FILTER "DATA"
37
38module AP_MODULE_DECLARE_DATA data_module;
39
40typedef struct data_ctx
41{
42 unsigned char overflow[3];
43 int count;
46
66{
67 apr_bucket *e, *ee;
68 request_rec *r = f->r;
69 data_ctx *ctx = f->ctx;
71
72 /* first time in? create a context */
73 if (!ctx) {
74 char *type;
75 char *charset = NULL;
76 char *end;
77 const char *content_length;
78
79 /* base64-ing won't work on subrequests, it would be nice if
80 * it did. Within subrequests, we have no EOS to check for,
81 * so we don't know when to flush the tail to the network.
82 */
83 if (!ap_is_initial_req(f->r)) {
85 return ap_pass_brigade(f->next, bb);
86 }
87
88 ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
89 ctx->bb = apr_brigade_create(r->pool, f->c->bucket_alloc);
90
92 if (type) {
93 charset = strchr(type, ' ');
94 if (charset) {
95 *charset++ = 0;
96 end = strchr(charset, ' ');
97 if (end) {
98 *end++ = 0;
99 }
100 }
101 }
102
103 apr_brigade_printf(ctx->bb, NULL, NULL, "data:%s%s;base64,",
104 type ? type : "", charset ? charset : "");
105
106 content_length = apr_table_get(r->headers_out, "Content-Length");
107 if (content_length) {
109 apr_brigade_length(ctx->bb, 1, &len);
110 if (ap_parse_strict_length(&clen, content_length)
111 && clen < APR_INT32_MAX) {
113 apr_base64_encode_len((int)clen) - 1);
114 }
115 else {
116 apr_table_unset(r->headers_out, "Content-Length");
117 }
118 }
119
120 ap_set_content_type_ex(r, "text/plain", 1);
121
122 }
123
124 /* Do nothing if asked to filter nothing. */
125 if (APR_BRIGADE_EMPTY(bb)) {
126 return ap_pass_brigade(f->next, bb);
127 }
128
129 while (APR_SUCCESS == rv && !APR_BRIGADE_EMPTY(bb)) {
130 const char *data;
132 apr_size_t tail;
134 /* buffer big enough for 8000 encoded bytes (6000 raw bytes) and terminator */
136 char encoded[((sizeof(ctx->overflow)) / 3) * 4 + 1];
137
138 e = APR_BRIGADE_FIRST(bb);
139
140 /* EOS means we are done. */
141 if (APR_BUCKET_IS_EOS(e)) {
142
143 /* write away the tail */
144 if (ctx->count) {
145 len = apr_base64_encode_binary(encoded, ctx->overflow,
146 ctx->count);
147 apr_brigade_write(ctx->bb, NULL, NULL, encoded, len - 1);
148 ctx->count = 0;
149 }
150
151 /* pass the EOS across */
154
155 /* pass what we have down the chain */
157 rv = ap_pass_brigade(f->next, ctx->bb);
158
159 /* pass any stray buckets after the EOS down the stack */
160 if ((APR_SUCCESS == rv) && (!APR_BRIGADE_EMPTY(bb))) {
161 rv = ap_pass_brigade(f->next, bb);
162 }
163 continue;
164 }
165
166 /* flush what we can, we can't flush the tail until EOS */
167 if (APR_BUCKET_IS_FLUSH(e)) {
168
169 /* pass the flush bucket across */
172
173 /* pass what we have down the chain */
174 rv = ap_pass_brigade(f->next, ctx->bb);
175 continue;
176 }
177
178 /* metadata buckets are preserved as is */
180 /*
181 * Remove meta data bucket from old brigade and insert into the
182 * new.
183 */
186 continue;
187 }
188
189 /* make sure we don't read more than 6000 bytes at a time */
191
192 /* size will never be more than 6000 bytes */
193 if (APR_SUCCESS == (rv = apr_bucket_read(e, &data, &size,
194 APR_BLOCK_READ))) {
195
196 /* fill up and write out our overflow buffer if partially used */
197 while (size && ctx->count && ctx->count < sizeof(ctx->overflow)) {
198 ctx->overflow[ctx->count++] = *data++;
199 size--;
200 }
201 if (ctx->count == sizeof(ctx->overflow)) {
202 len = apr_base64_encode_binary(encoded, ctx->overflow,
203 sizeof(ctx->overflow));
204 apr_brigade_write(ctx->bb, NULL, NULL, encoded, len - 1);
205 ctx->count = 0;
206 }
207
208 /* write the main base64 chunk */
209 tail = size % sizeof(ctx->overflow);
210 size -= tail;
211 if (size) {
213 (const unsigned char *) data, size);
215 }
216
217 /* save away any tail in the overflow buffer */
218 if (tail) {
219 memcpy(ctx->overflow, data + size, tail);
220 ctx->count += tail;
221 }
222
224
225 /* pass what we have down the chain */
226 rv = ap_pass_brigade(f->next, ctx->bb);
227 if (rv) {
228 /* should break out of the loop, since our write to the client
229 * failed in some way. */
230 continue;
231 }
232
233 }
234
235 }
236
237 return rv;
238
239}
240
241static const command_rec data_cmds[] = { { NULL } };
242
249 NULL, /* create per-directory config structure */
250 NULL, /* merge per-directory config structures */
251 NULL, /* create per-server config structure */
252 NULL, /* merge per-server config structures */
253 data_cmds, /* command apr_table_t */
254 register_hooks /* register hooks */
255};
Symbol export macros and hook functions.
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Base64 Encoding.
APR-UTIL Buckets/Bucket Brigades.
APR general purpose library routines.
APR Strings library.
#define AP_DECLARE_MODULE(foo)
request_rec * r
apr_status_t ap_pass_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket)
ap_filter_rec_t * ap_register_output_filter(const char *name, ap_out_filter_func filter_func, ap_init_filter_func filter_init, ap_filter_type ftype)
void ap_remove_output_filter(ap_filter_t *f)
@ AP_FTYPE_RESOURCE
void ap_set_content_length(request_rec *r, apr_off_t length)
Definition protocol.c:160
void ap_set_content_type_ex(request_rec *r, const char *ct, int trusted)
int ap_is_initial_req(request_rec *r)
Definition request.c:2567
apr_file_t * f
#define APR_BUCKET_IS_FLUSH(e)
#define APR_BUCKET_REMOVE(e)
#define APR_BUCKET_IS_METADATA(e)
#define APR_BRIGADE_INSERT_TAIL(b, e)
apr_bucket * e
#define APR_BUCKET_BUFF_SIZE
Definition apr_buckets.h:54
#define APR_BRIGADE_EMPTY(b)
#define apr_bucket_delete(e)
#define APR_BUCKET_IS_EOS(e)
apr_brigade_flush void * ctx
#define APR_BRIGADE_FIRST(b)
#define apr_bucket_read(e, str, len, block)
@ APR_BLOCK_READ
Definition apr_buckets.h:58
#define STANDARD20_MODULE_STUFF
int ap_parse_strict_length(apr_off_t *len, const char *str)
Definition util.c:2683
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void * data
int type
char * buffer
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char char ** end
Apache Configuration.
Apache Logging library.
HTTP protocol handling.
Apache Request library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
static apr_status_t data_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
Definition mod_data.c:65
static const command_rec data_cmds[]
Definition mod_data.c:241
static void register_hooks(apr_pool_t *p)
Definition mod_data.c:243
#define DATA_FILTER
Definition mod_data.c:36
return NULL
Definition mod_so.c:359
The representation of a filter chain.
apr_bucket_brigade * bb
Definition mod_data.c:44
unsigned char overflow[3]
Definition mod_data.c:42
int count
Definition mod_data.c:43
A structure that represents the current request.
Definition httpd.h:845
const char * content_type
Definition httpd.h:992
apr_pool_t * pool
Definition httpd.h:847
apr_table_t * headers_out
Definition httpd.h:978
Apache filter library.