mongrel_esi 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +53 -0
- data/LICENSE +471 -0
- data/README +186 -0
- data/Rakefile +141 -0
- data/bin/mongrel_esi +271 -0
- data/ext/esi/common.rl +41 -0
- data/ext/esi/esi_parser.c +387 -0
- data/ext/esi/extconf.rb +6 -0
- data/ext/esi/machine.rb +499 -0
- data/ext/esi/parser.c +1675 -0
- data/ext/esi/parser.h +113 -0
- data/ext/esi/parser.rb +49 -0
- data/ext/esi/parser.rl +398 -0
- data/ext/esi/ruby_esi.rl +135 -0
- data/ext/esi/run-test.rb +3 -0
- data/ext/esi/test/common.rl +41 -0
- data/ext/esi/test/parser.c +1676 -0
- data/ext/esi/test/parser.h +113 -0
- data/ext/esi/test/parser.rl +398 -0
- data/ext/esi/test/test.c +373 -0
- data/ext/esi/test1.rb +56 -0
- data/ext/esi/test2.rb +45 -0
- data/lib/esi/cache.rb +207 -0
- data/lib/esi/config.rb +154 -0
- data/lib/esi/dispatcher.rb +27 -0
- data/lib/esi/handler.rb +236 -0
- data/lib/esi/invalidator.rb +40 -0
- data/lib/esi/logger.rb +46 -0
- data/lib/esi/router.rb +84 -0
- data/lib/esi/tag/attempt.rb +6 -0
- data/lib/esi/tag/base.rb +85 -0
- data/lib/esi/tag/except.rb +24 -0
- data/lib/esi/tag/include.rb +190 -0
- data/lib/esi/tag/invalidate.rb +54 -0
- data/lib/esi/tag/try.rb +40 -0
- data/lib/multi_dirhandler.rb +70 -0
- data/setup.rb +1585 -0
- data/test/integration/basic_test.rb +39 -0
- data/test/integration/cache_test.rb +37 -0
- data/test/integration/docs/content/500.html +16 -0
- data/test/integration/docs/content/500_with_failover.html +16 -0
- data/test/integration/docs/content/500_with_failover_to_alt.html +8 -0
- data/test/integration/docs/content/ajax_test_page.html +15 -0
- data/test/integration/docs/content/cookie_variable.html +3 -0
- data/test/integration/docs/content/foo.html +15 -0
- data/test/integration/docs/content/include_in_include.html +15 -0
- data/test/integration/docs/content/malformed_transforms.html +16 -0
- data/test/integration/docs/content/malformed_transforms.html-correct +11 -0
- data/test/integration/docs/content/static-failover.html +20 -0
- data/test/integration/docs/content/test2.html +1 -0
- data/test/integration/docs/content/test3.html +17 -0
- data/test/integration/docs/esi_invalidate.html +6 -0
- data/test/integration/docs/esi_mixed_content.html +15 -0
- data/test/integration/docs/esi_test_content.html +27 -0
- data/test/integration/docs/index.html +688 -0
- data/test/integration/docs/test1.html +1 -0
- data/test/integration/docs/test3.html +9 -0
- data/test/integration/docs/test_failover.html +1 -0
- data/test/integration/handler_test.rb +270 -0
- data/test/integration/help.rb +234 -0
- data/test/net/get_test.rb +197 -0
- data/test/net/net_helper.rb +16 -0
- data/test/net/server_test.rb +249 -0
- data/test/unit/base_tag_test.rb +44 -0
- data/test/unit/esi-sample.html +56 -0
- data/test/unit/help.rb +77 -0
- data/test/unit/include_request_test.rb +69 -0
- data/test/unit/include_tag_test.rb +14 -0
- data/test/unit/parser_test.rb +478 -0
- data/test/unit/router_test.rb +34 -0
- data/test/unit/sample.html +21 -0
- data/tools/rakehelp.rb +119 -0
- metadata +182 -0
data/ext/esi/parser.h
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) 2007 Todd A. Fisher
|
3
|
+
* You can redistribute it and/or modify it under the same terms as Mozilla Public License 1.1.
|
4
|
+
*/
|
5
|
+
#ifndef ESI_PARSER_H
|
6
|
+
#define ESI_PARSER_H
|
7
|
+
#include <sys/types.h>
|
8
|
+
|
9
|
+
|
10
|
+
char *esi_strndup( const char *str, size_t len );
|
11
|
+
|
12
|
+
/*
|
13
|
+
* ESI Attribute is a single attribute with name and value
|
14
|
+
*
|
15
|
+
* e.g. for an esi include tag:
|
16
|
+
*
|
17
|
+
* <esi:include src='/foo/bar/' timeout='10'/>
|
18
|
+
*
|
19
|
+
* 2 attributes would be allocated
|
20
|
+
*
|
21
|
+
* attrs[0]->name => 'src'
|
22
|
+
* attrs[0]->value => '/foo/bar/'
|
23
|
+
*
|
24
|
+
* attrs[1]->name => 'timeout'
|
25
|
+
* attrs[1]->value => '10'
|
26
|
+
*
|
27
|
+
* */
|
28
|
+
typedef struct _ESIAttr {
|
29
|
+
char *name;
|
30
|
+
char *value;
|
31
|
+
struct _ESIAttr *next;
|
32
|
+
}ESIAttribute;
|
33
|
+
|
34
|
+
ESIAttribute *esi_attribute_new( const char *name, size_t name_length, const char *value, size_t value_length );
|
35
|
+
ESIAttribute *esi_attribute_copy( ESIAttribute *attribute );
|
36
|
+
void esi_attribute_free( ESIAttribute *attribute );
|
37
|
+
|
38
|
+
typedef void (*start_tag_cb)(const void *data,
|
39
|
+
const char *name_start,
|
40
|
+
size_t name_length,
|
41
|
+
ESIAttribute *attributes,
|
42
|
+
void *user_data);
|
43
|
+
|
44
|
+
typedef void (*end_tag_cb)(const void *data,
|
45
|
+
const char *name_start,
|
46
|
+
size_t name_length,
|
47
|
+
void *user_data);
|
48
|
+
|
49
|
+
typedef void (*output_cb)(const void *data,
|
50
|
+
size_t length,
|
51
|
+
void *user_data);
|
52
|
+
|
53
|
+
typedef struct _ESIParser {
|
54
|
+
int cs;
|
55
|
+
int prev_state;
|
56
|
+
|
57
|
+
void *user_data;
|
58
|
+
|
59
|
+
const char *mark;
|
60
|
+
size_t overflow_data_size; /* current size of the overflow data buffer */
|
61
|
+
char *overflow_data; /* overflow buffer if execute finishes and we are not in a final state store the parse data */
|
62
|
+
|
63
|
+
size_t echobuffer_allocated; /* amount of memory allocated for the echobuffer */
|
64
|
+
size_t echobuffer_index; /* current write position of the last echo'ed character */
|
65
|
+
char *echobuffer; /* echo buffer if the parse state is not 0 we store the characters here */
|
66
|
+
|
67
|
+
const char *tag_text; /* start pointer in data */
|
68
|
+
size_t tag_text_length; /* length from tag_text within data */
|
69
|
+
|
70
|
+
const char *attr_key; /* start pointer in data */
|
71
|
+
size_t attr_key_length;
|
72
|
+
|
73
|
+
const char *attr_value; /* start pointer in data */
|
74
|
+
size_t attr_value_length;
|
75
|
+
|
76
|
+
ESIAttribute *attributes, *last;
|
77
|
+
|
78
|
+
start_tag_cb start_tag_handler;
|
79
|
+
end_tag_cb end_tag_handler;
|
80
|
+
output_cb output_handler;
|
81
|
+
|
82
|
+
} ESIParser;
|
83
|
+
|
84
|
+
/* create a new Edge Side Include Parser */
|
85
|
+
ESIParser *esi_parser_new();
|
86
|
+
void esi_parser_free( ESIParser *parser );
|
87
|
+
|
88
|
+
/* initialize the parser */
|
89
|
+
int esi_parser_init( ESIParser *parser );
|
90
|
+
|
91
|
+
/*
|
92
|
+
* send a chunk of data to the parser, the internal parser state is returned
|
93
|
+
*/
|
94
|
+
int esi_parser_execute( ESIParser *parser, const char *data, size_t length );
|
95
|
+
/*
|
96
|
+
* let the parser no that it has reached the end and it should flush any remaining data to the desired output device
|
97
|
+
*/
|
98
|
+
int esi_parser_finish( ESIParser *parser );
|
99
|
+
|
100
|
+
/*
|
101
|
+
* setup a callback to execute when a new esi: start tag is encountered
|
102
|
+
* this is will fire for all block tags e.g. <esi:try>, <esi:attempt> and also
|
103
|
+
* inline tags <esi:inline src='cache-key'/> <esi:include src='dest'/>
|
104
|
+
*/
|
105
|
+
void esi_parser_start_tag_handler( ESIParser *parser, start_tag_cb callback );
|
106
|
+
|
107
|
+
void esi_parser_end_tag_handler( ESIParser *parser, end_tag_cb callback );
|
108
|
+
|
109
|
+
/* setup a callback to recieve data ready for output */
|
110
|
+
void esi_parser_output_handler( ESIParser *parser, output_cb output_handler );
|
111
|
+
|
112
|
+
|
113
|
+
#endif
|
data/ext/esi/parser.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'esi/machine'
|
2
|
+
|
3
|
+
module ESI
|
4
|
+
class Parser < ESI::ParserMachine
|
5
|
+
# Provides a stream like interface to a single parameter block
|
6
|
+
class StreamCallBack
|
7
|
+
def initialize(callback)
|
8
|
+
@callback = callback
|
9
|
+
end
|
10
|
+
def << (output)
|
11
|
+
@callback.call( output )
|
12
|
+
end
|
13
|
+
end
|
14
|
+
attr_accessor :esi_tag, :output, :depth
|
15
|
+
|
16
|
+
def initialize( options = {} )
|
17
|
+
super()
|
18
|
+
@data = nil
|
19
|
+
@prev_buffer = ""
|
20
|
+
@start_tag = nil # call back for when we encounter a start tag
|
21
|
+
@end_tag = nil # call back for when we encounter an end tag
|
22
|
+
@esi_tag = nil # the current active esi tag
|
23
|
+
@output = nil
|
24
|
+
@depth = options[:depth] || 0 # used to track the depth of requests include tags should be initialized with this depth
|
25
|
+
end
|
26
|
+
|
27
|
+
def start_tag_handler(&block)
|
28
|
+
@start_tag = block
|
29
|
+
end
|
30
|
+
|
31
|
+
def end_tag_handler(&block)
|
32
|
+
@end_tag = block
|
33
|
+
end
|
34
|
+
|
35
|
+
def output_handler(&block)
|
36
|
+
@output = StreamCallBack.new(block)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def stream_buffer(string)
|
41
|
+
if @esi_tag
|
42
|
+
@esi_tag.buffer( @output, string )# unless string.strip.empty?
|
43
|
+
else
|
44
|
+
@output << string
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
data/ext/esi/parser.rl
ADDED
@@ -0,0 +1,398 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include <ctype.h>
|
5
|
+
#include "parser.h"
|
6
|
+
|
7
|
+
/* define default callbacks */
|
8
|
+
static void
|
9
|
+
esi_parser_default_start_cb( const void *data,
|
10
|
+
const char *name_start,
|
11
|
+
size_t name_length,
|
12
|
+
ESIAttribute *attributes,
|
13
|
+
void *user_data )
|
14
|
+
{
|
15
|
+
}
|
16
|
+
static void
|
17
|
+
esi_parser_default_end_cb( const void *data,
|
18
|
+
const char *name_start,
|
19
|
+
size_t name_length,
|
20
|
+
void *user_data )
|
21
|
+
{
|
22
|
+
}
|
23
|
+
static void
|
24
|
+
esi_parser_default_output_cp(const void *data,
|
25
|
+
size_t length,
|
26
|
+
void *user_data)
|
27
|
+
{
|
28
|
+
}
|
29
|
+
#ifdef DEBUG
|
30
|
+
static void debug_string( const char *msg, const char *str, size_t len )
|
31
|
+
{
|
32
|
+
char *pstr = esi_strndup( str, len );
|
33
|
+
printf( "%s :'%s'\n", msg, pstr );
|
34
|
+
free( pstr );
|
35
|
+
}
|
36
|
+
#endif
|
37
|
+
|
38
|
+
static void esi_parser_echo_char( ESIParser *parser, char ch )
|
39
|
+
{
|
40
|
+
parser->output_handler( (void*)&ch, 1, parser->user_data );
|
41
|
+
}
|
42
|
+
|
43
|
+
static void esi_parser_echo_buffer( ESIParser *parser )
|
44
|
+
{
|
45
|
+
// debug_string( "echobuffer", parser->echobuffer, parser->echobuffer_index+1 );
|
46
|
+
parser->output_handler( parser->echobuffer, parser->echobuffer_index+1, parser->user_data );
|
47
|
+
}
|
48
|
+
|
49
|
+
static void esi_parser_echobuffer_clear( ESIParser *parser )
|
50
|
+
{
|
51
|
+
parser->echobuffer_index = -1;
|
52
|
+
}
|
53
|
+
|
54
|
+
static void esi_parser_concat_to_echobuffer( ESIParser *parser, char ch )
|
55
|
+
{
|
56
|
+
parser->echobuffer_index++;
|
57
|
+
|
58
|
+
if( parser->echobuffer_allocated <= parser->echobuffer_index ){
|
59
|
+
// double the echobuffer size
|
60
|
+
parser->echobuffer_allocated *= 2;
|
61
|
+
parser->echobuffer = (char*)realloc( parser->echobuffer, parser->echobuffer_allocated );
|
62
|
+
}
|
63
|
+
parser->echobuffer[parser->echobuffer_index] = ch;
|
64
|
+
// debug_string( "echo buffer", parser->echobuffer, parser->echobuffer_index+1 );
|
65
|
+
}
|
66
|
+
|
67
|
+
static void ltrim_pointer( const char **ptr, const char *bounds, size_t *len )
|
68
|
+
{
|
69
|
+
// remove any spaces or = at the before the value
|
70
|
+
while( isspace( **ptr ) ||
|
71
|
+
**ptr == '=' ||
|
72
|
+
**ptr == '"' ||
|
73
|
+
**ptr == '<' ||
|
74
|
+
**ptr == '\'' &&
|
75
|
+
*len > 0 &&
|
76
|
+
(*ptr != bounds) ){
|
77
|
+
(*ptr)++;
|
78
|
+
(*len)--;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
%%{
|
83
|
+
machine esi;
|
84
|
+
|
85
|
+
action begin {
|
86
|
+
parser->mark = p;
|
87
|
+
//debug_string( "begin", p, 1 );
|
88
|
+
}
|
89
|
+
action finish {
|
90
|
+
// printf( "finish\n" );
|
91
|
+
}
|
92
|
+
|
93
|
+
# record the position of the start tag
|
94
|
+
action see_start_tag {
|
95
|
+
parser->tag_text = parser->mark+1;
|
96
|
+
parser->tag_text_length = p - (parser->mark+1);
|
97
|
+
// debug_string( "have esi start", parser->tag_text, parser->tag_text_length );
|
98
|
+
parser->mark = p;
|
99
|
+
//debug_string( "see_start_tag", p, 1 );
|
100
|
+
}
|
101
|
+
|
102
|
+
action see_end_tag {
|
103
|
+
//debug_string( "see_end_tag: before parsed esi tag", parser->tag_text, parser->tag_text_length );
|
104
|
+
ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
105
|
+
//debug_string( "see_end_tag: after parsed esi tag", parser->tag_text, parser->tag_text_length );
|
106
|
+
parser->start_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->attributes, parser->user_data );
|
107
|
+
//debug_string( "see_end_tag: after start parsed esi tag", parser->tag_text, parser->tag_text_length );
|
108
|
+
parser->end_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->user_data );
|
109
|
+
//debug_string( "see_end_tag: after end parsed esi tag", parser->tag_text, parser->tag_text_length );
|
110
|
+
parser->tag_text = NULL;
|
111
|
+
parser->tag_text_length = 0;
|
112
|
+
parser->mark = p;
|
113
|
+
//debug_string( "see_end_tag", p, 1 );
|
114
|
+
}
|
115
|
+
|
116
|
+
action see_block_start_with_attributes {
|
117
|
+
// debug_string( "parsed esi tag", parser->tag_text, parser->tag_text_length );
|
118
|
+
ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
119
|
+
parser->start_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->attributes, parser->user_data );
|
120
|
+
parser->tag_text = NULL;
|
121
|
+
parser->tag_text_length = 0;
|
122
|
+
}
|
123
|
+
|
124
|
+
action see_attribute_key {
|
125
|
+
parser->attr_key = parser->mark;
|
126
|
+
parser->attr_key_length = p - parser->mark;
|
127
|
+
parser->mark = p;
|
128
|
+
ltrim_pointer( &(parser->attr_key), p, &(parser->attr_key_length) );
|
129
|
+
// debug_string( "\tattribute key", parser->attr_key, parser->attr_key_length );
|
130
|
+
//debug_string( "see_attribute_key", p, 1 );
|
131
|
+
}
|
132
|
+
|
133
|
+
action see_attribute_value {
|
134
|
+
ESIAttribute *attr;
|
135
|
+
parser->attr_value = parser->mark;
|
136
|
+
parser->attr_value_length = p - parser->mark;
|
137
|
+
parser->mark = p;
|
138
|
+
|
139
|
+
ltrim_pointer( &(parser->attr_value), p, &(parser->attr_value_length) );
|
140
|
+
|
141
|
+
// allocate a new attribute
|
142
|
+
attr = esi_attribute_new( parser->attr_key, parser->attr_key_length,
|
143
|
+
parser->attr_value, parser->attr_value_length );
|
144
|
+
if( parser->attributes ){
|
145
|
+
parser->last->next = attr;
|
146
|
+
parser->last = attr;
|
147
|
+
}
|
148
|
+
else{
|
149
|
+
parser->last = parser->attributes = attr;
|
150
|
+
}
|
151
|
+
// debug_string( "\tattribute value", parser->attr_value, parser->attr_value_length );
|
152
|
+
//debug_string( "see_attribute_value", p, 1 );
|
153
|
+
}
|
154
|
+
|
155
|
+
action block_start_tag {
|
156
|
+
parser->tag_text = parser->mark;
|
157
|
+
parser->tag_text_length = p - parser->mark;
|
158
|
+
parser->mark = p;
|
159
|
+
ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
160
|
+
parser->start_tag_handler( data, parser->tag_text, parser->tag_text_length, NULL, parser->user_data );
|
161
|
+
//debug_string( "block_start_tag", p, 1 );
|
162
|
+
}
|
163
|
+
|
164
|
+
action block_end_tag {
|
165
|
+
parser->tag_text = parser->mark+2;
|
166
|
+
parser->tag_text_length = p - (parser->mark+2);
|
167
|
+
//printf( "mark: [%s], p: [%s], length: %d\n", parser->mark, p, parser->tag_text_length );
|
168
|
+
parser->mark = p;
|
169
|
+
//debug_string( "block_end_tag: before parsed esi tag", parser->tag_text, parser->tag_text_length );
|
170
|
+
ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
171
|
+
//debug_string( "block_end_tag: after parsed esi tag", parser->tag_text, parser->tag_text_length );
|
172
|
+
parser->end_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->user_data );
|
173
|
+
}
|
174
|
+
|
175
|
+
action echo {
|
176
|
+
switch( cs ){
|
177
|
+
case 0:
|
178
|
+
if( parser->prev_state != 12 && parser->prev_state != 7 ){
|
179
|
+
if( parser->echobuffer && (parser->prev_state != (esi_en_main +1)) && parser->prev_state != 60 ){
|
180
|
+
// stream echobuffer
|
181
|
+
esi_parser_echo_buffer( parser );
|
182
|
+
}
|
183
|
+
// printf( "[%d: %c]", cs, *p );
|
184
|
+
// stream the current character
|
185
|
+
esi_parser_echo_char( parser, *p );
|
186
|
+
}
|
187
|
+
// clear the echobuffer
|
188
|
+
esi_parser_echobuffer_clear( parser );
|
189
|
+
break;
|
190
|
+
default:
|
191
|
+
// append characters to echobuffer
|
192
|
+
esi_parser_concat_to_echobuffer( parser, *p );
|
193
|
+
}
|
194
|
+
parser->prev_state = cs;
|
195
|
+
}
|
196
|
+
|
197
|
+
include esi_common_parser "common.rl";
|
198
|
+
}%%
|
199
|
+
|
200
|
+
%%write data;
|
201
|
+
|
202
|
+
char *esi_strndup( const char *str, size_t len )
|
203
|
+
{
|
204
|
+
char *s = (char*)malloc(sizeof(char)*(len+1));
|
205
|
+
memcpy( s, str, len );
|
206
|
+
s[len] = '\0';
|
207
|
+
return s;
|
208
|
+
}
|
209
|
+
|
210
|
+
ESIAttribute *esi_attribute_new( const char *name, size_t name_length, const char *value, size_t value_length )
|
211
|
+
{
|
212
|
+
ESIAttribute *attr = (ESIAttribute*)malloc(sizeof(ESIAttribute));
|
213
|
+
attr->name = esi_strndup(name, name_length);
|
214
|
+
attr->value = esi_strndup(value, value_length);
|
215
|
+
attr->next = NULL;
|
216
|
+
return attr;
|
217
|
+
}
|
218
|
+
|
219
|
+
ESIAttribute *esi_attribute_copy( ESIAttribute *attribute )
|
220
|
+
{
|
221
|
+
ESIAttribute *head, *nattr;
|
222
|
+
if( !attribute ){ return NULL; }
|
223
|
+
|
224
|
+
// copy the first attribute
|
225
|
+
nattr = esi_attribute_new( attribute->name, strlen( attribute->name ),
|
226
|
+
attribute->value, strlen( attribute->value ) );
|
227
|
+
// save a pointer for return
|
228
|
+
head = nattr;
|
229
|
+
// copy next attributes
|
230
|
+
attribute = attribute->next;
|
231
|
+
while( attribute ) {
|
232
|
+
// set the next attribute
|
233
|
+
nattr->next = esi_attribute_new( attribute->name, strlen( attribute->name ),
|
234
|
+
attribute->value, strlen( attribute->value ) );
|
235
|
+
// next attribute
|
236
|
+
nattr = nattr->next;
|
237
|
+
attribute = attribute->next;
|
238
|
+
}
|
239
|
+
return head;
|
240
|
+
}
|
241
|
+
|
242
|
+
void esi_attribute_free( ESIAttribute *attribute )
|
243
|
+
{
|
244
|
+
ESIAttribute *ptr;
|
245
|
+
while( attribute ){
|
246
|
+
free( attribute->name );
|
247
|
+
free( attribute->value );
|
248
|
+
ptr = attribute->next;
|
249
|
+
free( attribute );
|
250
|
+
attribute = ptr;
|
251
|
+
}
|
252
|
+
}
|
253
|
+
|
254
|
+
ESIParser *esi_parser_new()
|
255
|
+
{
|
256
|
+
ESIParser *parser = (ESIParser*)malloc(sizeof(ESIParser));
|
257
|
+
parser->cs = esi_start;
|
258
|
+
parser->mark = NULL;
|
259
|
+
parser->overflow_data_size = 0;
|
260
|
+
parser->overflow_data = NULL;
|
261
|
+
|
262
|
+
/* allocate 1024 bytes for the echobuffer */
|
263
|
+
parser->echobuffer_allocated = 1024;
|
264
|
+
parser->echobuffer_index = -1;
|
265
|
+
parser->echobuffer = (char*)malloc(sizeof(char)*parser->echobuffer_allocated);
|
266
|
+
|
267
|
+
parser->attributes = NULL;
|
268
|
+
parser->last = NULL;
|
269
|
+
|
270
|
+
parser->start_tag_handler = esi_parser_default_start_cb;
|
271
|
+
parser->end_tag_handler = esi_parser_default_end_cb;
|
272
|
+
parser->output_handler = esi_parser_default_output_cp;
|
273
|
+
|
274
|
+
return parser;
|
275
|
+
}
|
276
|
+
void esi_parser_free( ESIParser *parser )
|
277
|
+
{
|
278
|
+
if( parser->overflow_data ){ free( parser->overflow_data ); }
|
279
|
+
|
280
|
+
free( parser->echobuffer );
|
281
|
+
esi_attribute_free( parser->attributes );
|
282
|
+
|
283
|
+
free( parser );
|
284
|
+
}
|
285
|
+
|
286
|
+
void esi_parser_output_handler( ESIParser *parser, output_cb output_handler )
|
287
|
+
{
|
288
|
+
parser->output_handler = output_handler;
|
289
|
+
}
|
290
|
+
|
291
|
+
int esi_parser_init( ESIParser *parser )
|
292
|
+
{
|
293
|
+
int cs;
|
294
|
+
%% write init;
|
295
|
+
parser->prev_state = parser->cs = cs;
|
296
|
+
return 0;
|
297
|
+
}
|
298
|
+
|
299
|
+
static int compute_offset( const char *mark, const char *data )
|
300
|
+
{
|
301
|
+
if( mark ){
|
302
|
+
return mark - data;
|
303
|
+
}
|
304
|
+
return -1;
|
305
|
+
}
|
306
|
+
|
307
|
+
int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
|
308
|
+
{
|
309
|
+
int cs = parser->cs;
|
310
|
+
const char *p = data;
|
311
|
+
const char *pe = data + length;
|
312
|
+
|
313
|
+
if( length == 0 ){ return cs; }
|
314
|
+
|
315
|
+
if( parser->overflow_data && parser->overflow_data_size > 0 ){
|
316
|
+
|
317
|
+
// recompute mark, tag_text, attr_key, and attr_value since they all exist within overflow_data
|
318
|
+
int mark_offset = compute_offset( parser->mark, parser->overflow_data );
|
319
|
+
int tag_text_offset = compute_offset( parser->tag_text, parser->overflow_data );
|
320
|
+
int attr_key_offset = compute_offset( parser->attr_key, parser->overflow_data );
|
321
|
+
int attr_value_offset = compute_offset( parser->attr_value, parser->overflow_data );
|
322
|
+
|
323
|
+
// debug_string("grow overflow buffer", parser->overflow_data, parser->overflow_data_size );
|
324
|
+
|
325
|
+
parser->overflow_data = (char*)realloc( parser->overflow_data, sizeof(char)*(parser->overflow_data_size+length) );
|
326
|
+
memcpy( parser->overflow_data+parser->overflow_data_size, data, length );
|
327
|
+
|
328
|
+
p = parser->overflow_data + parser->overflow_data_size;
|
329
|
+
|
330
|
+
// in our new memory space mark will now be
|
331
|
+
parser->mark = ( mark_offset >= 0 ) ? parser->overflow_data + mark_offset : NULL;
|
332
|
+
parser->tag_text = ( tag_text_offset >= 0 ) ? parser->overflow_data + tag_text_offset : NULL;
|
333
|
+
parser->attr_key = ( attr_key_offset >= 0 ) ? parser->overflow_data + attr_key_offset : NULL;
|
334
|
+
parser->attr_value = ( attr_value_offset >= 0 ) ? parser->overflow_data + attr_value_offset : NULL;
|
335
|
+
|
336
|
+
data = parser->overflow_data;
|
337
|
+
parser->overflow_data_size = length = length + parser->overflow_data_size;
|
338
|
+
pe = data + length;
|
339
|
+
|
340
|
+
// debug_string( "overflow", parser->overflow_data, parser->overflow_data_size );
|
341
|
+
}
|
342
|
+
|
343
|
+
if( !parser->mark ){
|
344
|
+
parser->mark = p;
|
345
|
+
}
|
346
|
+
|
347
|
+
// printf( "cs: %d, ", cs );
|
348
|
+
// debug_string( "data", data, length );
|
349
|
+
|
350
|
+
%% write exec;
|
351
|
+
|
352
|
+
parser->cs = cs;
|
353
|
+
|
354
|
+
if( cs != esi_start && cs != 0 ){
|
355
|
+
|
356
|
+
if( !parser->overflow_data ){
|
357
|
+
// recompute mark, tag_text, attr_key, and attr_value since they all exist within overflow_data
|
358
|
+
int mark_offset = compute_offset( parser->mark, data );
|
359
|
+
int tag_text_offset = compute_offset( parser->tag_text, data );
|
360
|
+
int attr_key_offset = compute_offset( parser->attr_key, data );
|
361
|
+
int attr_value_offset = compute_offset( parser->attr_value, data );
|
362
|
+
//debug_string( "mark before move", parser->mark, 1 );
|
363
|
+
|
364
|
+
parser->overflow_data = (char*)malloc( sizeof( char ) * length );
|
365
|
+
memcpy( parser->overflow_data, data, length );
|
366
|
+
parser->overflow_data_size = length;
|
367
|
+
|
368
|
+
// in our new memory space mark will now be
|
369
|
+
parser->mark = ( mark_offset >= 0 ) ? parser->overflow_data + mark_offset : NULL;
|
370
|
+
parser->tag_text = ( tag_text_offset >= 0 ) ? parser->overflow_data + tag_text_offset : NULL;
|
371
|
+
parser->attr_key = ( attr_key_offset >= 0 ) ? parser->overflow_data + attr_key_offset : NULL;
|
372
|
+
parser->attr_value = ( attr_value_offset >= 0 ) ? parser->overflow_data + attr_value_offset : NULL;
|
373
|
+
//if( parser->mark ){ debug_string( "mark after move", parser->mark, 1 ); } else { printf( "mark is now empty\n" ); }
|
374
|
+
}
|
375
|
+
|
376
|
+
}else if( parser->overflow_data ){
|
377
|
+
free( parser->overflow_data );
|
378
|
+
parser->overflow_data = NULL;
|
379
|
+
parser->overflow_data_size = 0;
|
380
|
+
}
|
381
|
+
|
382
|
+
return cs;
|
383
|
+
}
|
384
|
+
int esi_parser_finish( ESIParser *parser )
|
385
|
+
{
|
386
|
+
%% write eof;
|
387
|
+
return 0;
|
388
|
+
}
|
389
|
+
|
390
|
+
void esi_parser_start_tag_handler( ESIParser *parser, start_tag_cb callback )
|
391
|
+
{
|
392
|
+
parser->start_tag_handler = callback;
|
393
|
+
}
|
394
|
+
|
395
|
+
void esi_parser_end_tag_handler( ESIParser *parser, end_tag_cb callback )
|
396
|
+
{
|
397
|
+
parser->end_tag_handler = callback;
|
398
|
+
}
|