mongrel_esi 0.4.1 → 0.5.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/Rakefile +15 -8
- data/bin/mongrel_esi +0 -0
- data/ext/esi/common.rl +32 -27
- data/ext/esi/esi_parser.c +11 -4
- data/ext/esi/parser.c +4536 -901
- data/ext/esi/parser.h +7 -0
- data/ext/esi/parser.rl +171 -53
- data/ext/esi/run-test.rb +0 -0
- data/ext/esi/test/common.rl +32 -27
- data/ext/esi/test/parser.c +322 -1342
- data/ext/esi/test/parser.h +7 -0
- data/ext/esi/test/parser.rl +171 -53
- data/ext/esi/test/test.c +13 -4
- data/ext/esi/test1.rb +35 -3
- data/lib/esi/cache.rb +2 -1
- data/lib/esi/config.rb +37 -0
- data/lib/esi/dispatcher.rb +3 -5
- data/lib/esi/invalidator.rb +3 -0
- data/lib/esi/logger.rb +0 -7
- data/lib/esi/parser.rb +70 -0
- data/lib/esi/processor.rb +88 -0
- data/lib/esi/proxy.rb +104 -0
- data/lib/esi/response.rb +106 -0
- data/lib/esi/router.rb +3 -0
- data/lib/esi/tag/attempt.rb +3 -0
- data/lib/esi/tag/base.rb +3 -1
- data/lib/esi/tag/except.rb +2 -0
- data/lib/esi/tag/include.rb +131 -132
- data/lib/esi/tag/invalidate.rb +2 -0
- data/lib/esi/tag/try.rb +3 -0
- data/test/integration/basic_test.rb +0 -1
- data/test/integration/docs/esi_max_age_varies.html +10 -0
- data/test/integration/handler_test.rb +31 -5
- data/test/integration/help.rb +13 -1
- data/test/load_test.rb +133 -0
- data/test/unit/include_request_test.rb +1 -1
- data/test/unit/parser_test.rb +41 -5
- data/test/unit/response_test.rb +184 -0
- metadata +50 -224
- data/doc/rdoc/classes/ESI/Cache.html +0 -178
- data/doc/rdoc/classes/ESI/Cache.src/M000060.html +0 -17
- data/doc/rdoc/classes/ESI/Cache.src/M000061.html +0 -20
- data/doc/rdoc/classes/ESI/Config/CacheConfig.html +0 -212
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000055.html +0 -19
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000056.html +0 -19
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000057.html +0 -18
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000058.html +0 -18
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000059.html +0 -18
- data/doc/rdoc/classes/ESI/Config/ConfigRouter.html +0 -187
- data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000052.html +0 -19
- data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000053.html +0 -21
- data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000054.html +0 -21
- data/doc/rdoc/classes/ESI/Config.html +0 -291
- data/doc/rdoc/classes/ESI/Config.src/M000043.html +0 -18
- data/doc/rdoc/classes/ESI/Config.src/M000044.html +0 -18
- data/doc/rdoc/classes/ESI/Config.src/M000045.html +0 -35
- data/doc/rdoc/classes/ESI/Config.src/M000046.html +0 -38
- data/doc/rdoc/classes/ESI/Config.src/M000047.html +0 -23
- data/doc/rdoc/classes/ESI/Config.src/M000048.html +0 -18
- data/doc/rdoc/classes/ESI/Config.src/M000049.html +0 -20
- data/doc/rdoc/classes/ESI/Config.src/M000050.html +0 -18
- data/doc/rdoc/classes/ESI/Config.src/M000051.html +0 -24
- data/doc/rdoc/classes/ESI/Dispatcher.html +0 -172
- data/doc/rdoc/classes/ESI/Dispatcher.src/M000062.html +0 -23
- data/doc/rdoc/classes/ESI/Dispatcher.src/M000063.html +0 -20
- data/doc/rdoc/classes/ESI/Fragment.html +0 -218
- data/doc/rdoc/classes/ESI/Fragment.src/M000076.html +0 -21
- data/doc/rdoc/classes/ESI/Fragment.src/M000077.html +0 -18
- data/doc/rdoc/classes/ESI/Fragment.src/M000078.html +0 -18
- data/doc/rdoc/classes/ESI/Handler.html +0 -236
- data/doc/rdoc/classes/ESI/Handler.src/M000079.html +0 -19
- data/doc/rdoc/classes/ESI/Handler.src/M000080.html +0 -161
- data/doc/rdoc/classes/ESI/Handler.src/M000081.html +0 -24
- data/doc/rdoc/classes/ESI/Handler.src/M000082.html +0 -18
- data/doc/rdoc/classes/ESI/Handler.src/M000083.html +0 -26
- data/doc/rdoc/classes/ESI/Handler.src/M000084.html +0 -30
- data/doc/rdoc/classes/ESI/Invalidator.html +0 -131
- data/doc/rdoc/classes/ESI/Invalidator.src/M000004.html +0 -41
- data/doc/rdoc/classes/ESI/Log.html +0 -251
- data/doc/rdoc/classes/ESI/Log.src/M000005.html +0 -18
- data/doc/rdoc/classes/ESI/Log.src/M000006.html +0 -18
- data/doc/rdoc/classes/ESI/Log.src/M000007.html +0 -18
- data/doc/rdoc/classes/ESI/Log.src/M000008.html +0 -18
- data/doc/rdoc/classes/ESI/Log.src/M000009.html +0 -18
- data/doc/rdoc/classes/ESI/Log.src/M000010.html +0 -18
- data/doc/rdoc/classes/ESI/Log.src/M000011.html +0 -18
- data/doc/rdoc/classes/ESI/Log.src/M000012.html +0 -18
- data/doc/rdoc/classes/ESI/Log.src/M000013.html +0 -18
- data/doc/rdoc/classes/ESI/MemcachedCache.html +0 -314
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000034.html +0 -24
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000035.html +0 -22
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000036.html +0 -19
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000037.html +0 -23
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000038.html +0 -18
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000039.html +0 -19
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000040.html +0 -18
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000041.html +0 -18
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000042.html +0 -17
- data/doc/rdoc/classes/ESI/Router.html +0 -229
- data/doc/rdoc/classes/ESI/Router.src/M000073.html +0 -36
- data/doc/rdoc/classes/ESI/Router.src/M000074.html +0 -25
- data/doc/rdoc/classes/ESI/Router.src/M000075.html +0 -24
- data/doc/rdoc/classes/ESI/RubyCache.html +0 -278
- data/doc/rdoc/classes/ESI/RubyCache.src/M000064.html +0 -20
- data/doc/rdoc/classes/ESI/RubyCache.src/M000065.html +0 -22
- data/doc/rdoc/classes/ESI/RubyCache.src/M000066.html +0 -21
- data/doc/rdoc/classes/ESI/RubyCache.src/M000067.html +0 -22
- data/doc/rdoc/classes/ESI/RubyCache.src/M000068.html +0 -18
- data/doc/rdoc/classes/ESI/RubyCache.src/M000069.html +0 -22
- data/doc/rdoc/classes/ESI/RubyCache.src/M000070.html +0 -18
- data/doc/rdoc/classes/ESI/RubyCache.src/M000071.html +0 -18
- data/doc/rdoc/classes/ESI/RubyCache.src/M000072.html +0 -18
- data/doc/rdoc/classes/ESI/Tag/Attempt.html +0 -113
- data/doc/rdoc/classes/ESI/Tag/Base.html +0 -267
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000028.html +0 -26
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000029.html +0 -23
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000030.html +0 -22
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000031.html +0 -18
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000032.html +0 -22
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000033.html +0 -23
- data/doc/rdoc/classes/ESI/Tag/Except.html +0 -184
- data/doc/rdoc/classes/ESI/Tag/Except.src/M000020.html +0 -21
- data/doc/rdoc/classes/ESI/Tag/Except.src/M000021.html +0 -20
- data/doc/rdoc/classes/ESI/Tag/Except.src/M000022.html +0 -18
- data/doc/rdoc/classes/ESI/Tag/Include.html +0 -189
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000017.html +0 -20
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000018.html +0 -18
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000019.html +0 -125
- data/doc/rdoc/classes/ESI/Tag/IncludeRequest/Error.html +0 -155
- data/doc/rdoc/classes/ESI/Tag/IncludeRequest/Error.src/M000016.html +0 -19
- data/doc/rdoc/classes/ESI/Tag/IncludeRequest.html +0 -199
- data/doc/rdoc/classes/ESI/Tag/IncludeRequest.src/M000014.html +0 -18
- data/doc/rdoc/classes/ESI/Tag/IncludeRequest.src/M000015.html +0 -42
- data/doc/rdoc/classes/ESI/Tag/Invalidate.html +0 -171
- data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000025.html +0 -19
- data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000026.html +0 -51
- data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000027.html +0 -19
- data/doc/rdoc/classes/ESI/Tag/Try.html +0 -161
- data/doc/rdoc/classes/ESI/Tag/Try.src/M000023.html +0 -40
- data/doc/rdoc/classes/ESI/Tag/Try.src/M000024.html +0 -18
- data/doc/rdoc/classes/ESI/Tag.html +0 -137
- data/doc/rdoc/classes/ESI.html +0 -169
- data/doc/rdoc/classes/MultiDirHandler.html +0 -198
- data/doc/rdoc/classes/MultiDirHandler.src/M000001.html +0 -20
- data/doc/rdoc/classes/MultiDirHandler.src/M000002.html +0 -28
- data/doc/rdoc/classes/MultiDirHandler.src/M000003.html +0 -22
- data/doc/rdoc/classes/Net/An/HTTP.html +0 -137
- data/doc/rdoc/classes/Net/An/HTTP.src/M000087.html +0 -17
- data/doc/rdoc/classes/Net/An/IORequest.html +0 -139
- data/doc/rdoc/classes/Net/An/IORequest.src/M000088.html +0 -17
- data/doc/rdoc/classes/Net/An/IOResponse.html +0 -139
- data/doc/rdoc/classes/Net/An/IOResponse.src/M000085.html +0 -17
- data/doc/rdoc/classes/Net/An/IOSocket.html +0 -137
- data/doc/rdoc/classes/Net/An/IOSocket.src/M000086.html +0 -17
- data/doc/rdoc/classes/Net/An.html +0 -114
- data/doc/rdoc/classes/Net.html +0 -119
- data/doc/rdoc/created.rid +0 -1
- data/doc/rdoc/files/COPYING.html +0 -168
- data/doc/rdoc/files/LICENSE.html +0 -605
- data/doc/rdoc/files/README.html +0 -361
- data/doc/rdoc/files/lib/esi/cache_rb.html +0 -113
- data/doc/rdoc/files/lib/esi/config_rb.html +0 -108
- data/doc/rdoc/files/lib/esi/dispatcher_rb.html +0 -109
- data/doc/rdoc/files/lib/esi/handler_rb.html +0 -121
- data/doc/rdoc/files/lib/esi/invalidator_rb.html +0 -117
- data/doc/rdoc/files/lib/esi/logger_rb.html +0 -108
- data/doc/rdoc/files/lib/esi/router_rb.html +0 -101
- data/doc/rdoc/files/lib/esi/tag/attempt_rb.html +0 -101
- data/doc/rdoc/files/lib/esi/tag/base_rb.html +0 -108
- data/doc/rdoc/files/lib/esi/tag/except_rb.html +0 -101
- data/doc/rdoc/files/lib/esi/tag/include_rb.html +0 -109
- data/doc/rdoc/files/lib/esi/tag/invalidate_rb.html +0 -109
- data/doc/rdoc/files/lib/esi/tag/try_rb.html +0 -108
- data/doc/rdoc/files/lib/multi_dirhandler_rb.html +0 -109
- data/doc/rdoc/files/lib/net/ahttp_rb.html +0 -109
- data/doc/rdoc/fr_class_index.html +0 -55
- data/doc/rdoc/fr_file_index.html +0 -44
- data/doc/rdoc/fr_method_index.html +0 -114
- data/doc/rdoc/index.html +0 -24
- data/doc/rdoc/rdoc-style.css +0 -208
- data/ext/esi/parser.rb +0 -49
- data/ext/esi/ruby_esi.rl +0 -135
- data/lib/esi/handler.rb +0 -221
- data/lib/net/ahttp.rb +0 -36
data/ext/esi/parser.h
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
#define ESI_PARSER_H
|
|
7
7
|
#include <sys/types.h>
|
|
8
8
|
|
|
9
|
+
/* how much output to hold in memory before sending out */
|
|
10
|
+
#define ESI_OUTPUT_BUFFER_SIZE 1024
|
|
9
11
|
|
|
10
12
|
char *esi_strndup( const char *str, size_t len );
|
|
11
13
|
|
|
@@ -75,6 +77,11 @@ typedef struct _ESIParser {
|
|
|
75
77
|
|
|
76
78
|
ESIAttribute *attributes, *last;
|
|
77
79
|
|
|
80
|
+
/* this memory will be pass to the output_cb when either it's full
|
|
81
|
+
* or eof is encountered */
|
|
82
|
+
char output_buffer[ESI_OUTPUT_BUFFER_SIZE+1];
|
|
83
|
+
size_t output_buffer_size;
|
|
84
|
+
|
|
78
85
|
start_tag_cb start_tag_handler;
|
|
79
86
|
end_tag_cb end_tag_handler;
|
|
80
87
|
output_cb output_handler;
|
data/ext/esi/parser.rl
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2008 Todd A. Fisher
|
|
3
|
+
* see LICENSE
|
|
4
|
+
*/
|
|
1
5
|
#include <stdio.h>
|
|
2
6
|
#include <stdlib.h>
|
|
3
7
|
#include <string.h>
|
|
4
8
|
#include <ctype.h>
|
|
5
9
|
#include "parser.h"
|
|
6
10
|
|
|
11
|
+
#ifdef DEBUG
|
|
12
|
+
static void debug_string( const char *msg, const char *str, size_t len )
|
|
13
|
+
{
|
|
14
|
+
char *pstr = esi_strndup( str, len );
|
|
15
|
+
printf( "%s :'%s'\n", msg, pstr );
|
|
16
|
+
free( pstr );
|
|
17
|
+
}
|
|
18
|
+
#endif
|
|
19
|
+
|
|
7
20
|
/* define default callbacks */
|
|
8
21
|
static void
|
|
9
22
|
esi_parser_default_start_cb( const void *data,
|
|
@@ -26,58 +39,102 @@ esi_parser_default_output_cp(const void *data,
|
|
|
26
39
|
void *user_data)
|
|
27
40
|
{
|
|
28
41
|
}
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
* flush output buffer
|
|
45
|
+
*/
|
|
46
|
+
static void esi_parser_flush_output( ESIParser *parser )
|
|
31
47
|
{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
48
|
+
if( parser->output_buffer_size > 0 ) {
|
|
49
|
+
//debug_string( "esi_parser_flush_output:", parser->output_buffer, parser->output_buffer_size );
|
|
50
|
+
parser->output_handler( (void*)parser->output_buffer, parser->output_buffer_size, parser->user_data );
|
|
51
|
+
parser->output_buffer_size = 0;
|
|
52
|
+
}
|
|
35
53
|
}
|
|
36
|
-
|
|
37
|
-
|
|
54
|
+
/* send the character to the output handler marking it
|
|
55
|
+
* as ready for consumption, e.g. not an esi tag
|
|
56
|
+
*/
|
|
38
57
|
static void esi_parser_echo_char( ESIParser *parser, char ch )
|
|
39
58
|
{
|
|
40
|
-
parser->
|
|
59
|
+
parser->output_buffer[parser->output_buffer_size++] = ch;
|
|
60
|
+
if( parser->output_buffer_size == ESI_OUTPUT_BUFFER_SIZE ) {
|
|
61
|
+
// flush the buffer to the consumer
|
|
62
|
+
esi_parser_flush_output( parser );
|
|
63
|
+
}
|
|
41
64
|
}
|
|
42
|
-
|
|
65
|
+
/* send any buffered characters to the output handler.
|
|
66
|
+
* This happens when we enter a case such as <em> where the
|
|
67
|
+
* first two characters < and e match the <esi: expression
|
|
68
|
+
*/
|
|
43
69
|
static void esi_parser_echo_buffer( ESIParser *parser )
|
|
44
70
|
{
|
|
45
|
-
|
|
46
|
-
|
|
71
|
+
size_t i = 0, len = parser->echobuffer_index + 1;;
|
|
72
|
+
//debug_string( "echobuffer", parser->echobuffer, parser->echobuffer_index+1 );
|
|
73
|
+
//parser->output_handler( parser->echobuffer, parser->echobuffer_index+1, parser->user_data );
|
|
74
|
+
for( ; i < len; ++i ) {
|
|
75
|
+
esi_parser_echo_char( parser, parser->echobuffer[i] );
|
|
76
|
+
}
|
|
47
77
|
}
|
|
48
|
-
|
|
78
|
+
/*
|
|
79
|
+
* clear the buffer, no buffered characters should be emitted .
|
|
80
|
+
* e.g. we matched an esi tag completely and all buffered characters can be tossed out
|
|
81
|
+
*/
|
|
49
82
|
static void esi_parser_echobuffer_clear( ESIParser *parser )
|
|
50
83
|
{
|
|
51
84
|
parser->echobuffer_index = -1;
|
|
52
85
|
}
|
|
53
86
|
|
|
87
|
+
/*
|
|
88
|
+
* add a character to the echobuffer.
|
|
89
|
+
* this happens when we can't determine if the character is allowed to be sent to the client device
|
|
90
|
+
* e.g. matching <e it's not yet determined if these characters are safe to send or not
|
|
91
|
+
*/
|
|
54
92
|
static void esi_parser_concat_to_echobuffer( ESIParser *parser, char ch )
|
|
55
93
|
{
|
|
56
94
|
parser->echobuffer_index++;
|
|
57
95
|
|
|
58
96
|
if( parser->echobuffer_allocated <= parser->echobuffer_index ){
|
|
59
|
-
|
|
97
|
+
/* double the echobuffer size
|
|
98
|
+
* we're getting some crazy input if this case ever happens
|
|
99
|
+
*/
|
|
60
100
|
parser->echobuffer_allocated *= 2;
|
|
61
101
|
parser->echobuffer = (char*)realloc( parser->echobuffer, parser->echobuffer_allocated );
|
|
62
102
|
}
|
|
63
103
|
parser->echobuffer[parser->echobuffer_index] = ch;
|
|
64
104
|
// debug_string( "echo buffer", parser->echobuffer, parser->echobuffer_index+1 );
|
|
65
105
|
}
|
|
66
|
-
|
|
106
|
+
/*
|
|
107
|
+
* the mark boundary is not always going to be exactly on the attribute or tag name boundary
|
|
108
|
+
* this trims characters from the left to right, advancing *ptr and reducing *len
|
|
109
|
+
*/
|
|
67
110
|
static void ltrim_pointer( const char **ptr, const char *bounds, size_t *len )
|
|
68
111
|
{
|
|
69
112
|
// remove any spaces or = at the before the value
|
|
70
|
-
while( isspace( **ptr ) ||
|
|
113
|
+
while( (isspace( **ptr ) ||
|
|
71
114
|
**ptr == '=' ||
|
|
72
115
|
**ptr == '"' ||
|
|
73
116
|
**ptr == '<' ||
|
|
74
|
-
**ptr == '\'' &&
|
|
75
|
-
*len > 0 &&
|
|
76
|
-
(*ptr != bounds) ){
|
|
117
|
+
**ptr == '\'' ) && (*len > 0) && (*ptr != bounds) ){
|
|
77
118
|
(*ptr)++;
|
|
78
119
|
(*len)--;
|
|
79
120
|
}
|
|
80
121
|
}
|
|
122
|
+
/*
|
|
123
|
+
* similar to ltrim_pointer, this walks from bounds to *ptr, reducing *len
|
|
124
|
+
*/
|
|
125
|
+
static void rtrim_pointer( const char **ptr, const char *bounds, size_t *len )
|
|
126
|
+
{
|
|
127
|
+
bounds = (*ptr+(*len-1));
|
|
128
|
+
// remove any spaces or = at the before the value
|
|
129
|
+
while( (isspace( *bounds ) ||
|
|
130
|
+
*bounds == '=' ||
|
|
131
|
+
*bounds == '"' ||
|
|
132
|
+
*bounds == '>' ||
|
|
133
|
+
*bounds == '\'') && (*len > 0) && (*ptr != bounds) ){
|
|
134
|
+
bounds--;
|
|
135
|
+
(*len)--;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
81
138
|
|
|
82
139
|
%%{
|
|
83
140
|
machine esi;
|
|
@@ -94,53 +151,84 @@ static void ltrim_pointer( const char **ptr, const char *bounds, size_t *len )
|
|
|
94
151
|
action see_start_tag {
|
|
95
152
|
parser->tag_text = parser->mark+1;
|
|
96
153
|
parser->tag_text_length = p - (parser->mark+1);
|
|
97
|
-
// debug_string( "have esi start", parser->tag_text, parser->tag_text_length );
|
|
98
154
|
parser->mark = p;
|
|
99
|
-
//debug_string( "see_start_tag", p, 1 );
|
|
100
155
|
}
|
|
101
156
|
|
|
157
|
+
# detected an inline tag end, sends the start tag and end tag callback
|
|
102
158
|
action see_end_tag {
|
|
103
|
-
|
|
159
|
+
/* trim the tag text */
|
|
104
160
|
ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
|
105
|
-
|
|
161
|
+
rtrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
|
162
|
+
|
|
163
|
+
/* send the start tag and end tag message */
|
|
164
|
+
esi_parser_flush_output( parser );
|
|
106
165
|
parser->start_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->attributes, parser->user_data );
|
|
107
|
-
|
|
166
|
+
esi_parser_flush_output( parser );
|
|
108
167
|
parser->end_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->user_data );
|
|
109
|
-
|
|
168
|
+
esi_parser_flush_output( parser );
|
|
169
|
+
|
|
170
|
+
/* mark the position */
|
|
110
171
|
parser->tag_text = NULL;
|
|
111
172
|
parser->tag_text_length = 0;
|
|
112
173
|
parser->mark = p;
|
|
113
|
-
|
|
174
|
+
|
|
175
|
+
/* clear out the echo buffer */
|
|
176
|
+
esi_parser_echobuffer_clear( parser );
|
|
114
177
|
}
|
|
115
|
-
|
|
178
|
+
|
|
179
|
+
# block tag start, with attributes
|
|
116
180
|
action see_block_start_with_attributes {
|
|
117
|
-
|
|
181
|
+
/* trim tag text */
|
|
118
182
|
ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
|
183
|
+
rtrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
|
184
|
+
|
|
185
|
+
/* send the start and end tag message */
|
|
186
|
+
esi_parser_flush_output( parser );
|
|
119
187
|
parser->start_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->attributes, parser->user_data );
|
|
188
|
+
esi_parser_flush_output( parser );
|
|
189
|
+
|
|
120
190
|
parser->tag_text = NULL;
|
|
121
191
|
parser->tag_text_length = 0;
|
|
192
|
+
parser->mark = p;
|
|
193
|
+
|
|
194
|
+
/* clear out the echo buffer */
|
|
195
|
+
esi_parser_echobuffer_clear( parser );
|
|
122
196
|
}
|
|
123
|
-
|
|
197
|
+
|
|
198
|
+
# see an attribute key, /foo\s*=/
|
|
124
199
|
action see_attribute_key {
|
|
200
|
+
/* save the attribute key start */
|
|
125
201
|
parser->attr_key = parser->mark;
|
|
202
|
+
/* compute the length of the key */
|
|
126
203
|
parser->attr_key_length = p - parser->mark;
|
|
204
|
+
/* save the position following the key */
|
|
127
205
|
parser->mark = p;
|
|
206
|
+
|
|
207
|
+
/* trim the attribute key */
|
|
128
208
|
ltrim_pointer( &(parser->attr_key), p, &(parser->attr_key_length) );
|
|
129
|
-
|
|
130
|
-
//debug_string( "see_attribute_key", p, 1 );
|
|
209
|
+
rtrim_pointer( &(parser->attr_key), p, &(parser->attr_key_length) );
|
|
131
210
|
}
|
|
132
211
|
|
|
212
|
+
# see an attribute value, aprox ~= /['"].*['"]/
|
|
133
213
|
action see_attribute_value {
|
|
134
214
|
ESIAttribute *attr;
|
|
215
|
+
|
|
216
|
+
/* save the attribute value start */
|
|
135
217
|
parser->attr_value = parser->mark;
|
|
218
|
+
/* compute the length of the value */
|
|
136
219
|
parser->attr_value_length = p - parser->mark;
|
|
220
|
+
/* svae the position following the value */
|
|
137
221
|
parser->mark = p;
|
|
138
|
-
|
|
222
|
+
|
|
223
|
+
/* trim the attribute value */
|
|
139
224
|
ltrim_pointer( &(parser->attr_value), p, &(parser->attr_value_length) );
|
|
225
|
+
rtrim_pointer( &(parser->attr_value), p, &(parser->attr_value_length) );
|
|
140
226
|
|
|
141
|
-
|
|
227
|
+
/* using the attr_key and attr_value, allocate a new attribute object */
|
|
142
228
|
attr = esi_attribute_new( parser->attr_key, parser->attr_key_length,
|
|
143
229
|
parser->attr_value, parser->attr_value_length );
|
|
230
|
+
|
|
231
|
+
/* add the new attribute to the list of attributes */
|
|
144
232
|
if( parser->attributes ){
|
|
145
233
|
parser->last->next = attr;
|
|
146
234
|
parser->last = attr;
|
|
@@ -148,49 +236,67 @@ static void ltrim_pointer( const char **ptr, const char *bounds, size_t *len )
|
|
|
148
236
|
else{
|
|
149
237
|
parser->last = parser->attributes = attr;
|
|
150
238
|
}
|
|
151
|
-
// debug_string( "\tattribute value", parser->attr_value, parser->attr_value_length );
|
|
152
|
-
//debug_string( "see_attribute_value", p, 1 );
|
|
153
239
|
}
|
|
154
240
|
|
|
241
|
+
# simple block start tag detected, e.g. <esi:try> no attributes
|
|
155
242
|
action block_start_tag {
|
|
243
|
+
|
|
156
244
|
parser->tag_text = parser->mark;
|
|
157
245
|
parser->tag_text_length = p - parser->mark;
|
|
246
|
+
|
|
158
247
|
parser->mark = p;
|
|
248
|
+
|
|
159
249
|
ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
|
250
|
+
rtrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
|
251
|
+
|
|
252
|
+
esi_parser_flush_output( parser );
|
|
160
253
|
parser->start_tag_handler( data, parser->tag_text, parser->tag_text_length, NULL, parser->user_data );
|
|
161
|
-
|
|
254
|
+
esi_parser_flush_output( parser );
|
|
255
|
+
|
|
256
|
+
esi_parser_echobuffer_clear( parser );
|
|
162
257
|
}
|
|
163
258
|
|
|
259
|
+
# block end tag detected, e.g. </esi:try>
|
|
164
260
|
action block_end_tag {
|
|
261
|
+
/* offset by 2 to account for the </ characters */
|
|
165
262
|
parser->tag_text = parser->mark+2;
|
|
166
263
|
parser->tag_text_length = p - (parser->mark+2);
|
|
167
|
-
|
|
264
|
+
|
|
168
265
|
parser->mark = p;
|
|
169
|
-
|
|
266
|
+
|
|
170
267
|
ltrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
|
171
|
-
|
|
268
|
+
rtrim_pointer( &(parser->tag_text), p, &(parser->tag_text_length) );
|
|
269
|
+
|
|
270
|
+
esi_parser_flush_output( parser );
|
|
172
271
|
parser->end_tag_handler( data, parser->tag_text, parser->tag_text_length, parser->user_data );
|
|
272
|
+
esi_parser_flush_output( parser );
|
|
273
|
+
|
|
274
|
+
esi_parser_echobuffer_clear( parser );
|
|
173
275
|
}
|
|
174
276
|
|
|
277
|
+
# process each character in the input stream for output
|
|
175
278
|
action echo {
|
|
279
|
+
//printf( "[%c:%d],", *p, cs );
|
|
176
280
|
switch( cs ){
|
|
177
|
-
case 0:
|
|
178
|
-
if( parser->prev_state != 12 && parser->prev_state != 7 ){
|
|
179
|
-
if( parser->echobuffer &&
|
|
180
|
-
|
|
281
|
+
case 0: /* non matching state */
|
|
282
|
+
if( parser->prev_state != 12 && parser->prev_state != 7 ){ /* states following a possible end state for a tag */
|
|
283
|
+
if( parser->echobuffer && parser->echobuffer_index != -1 ){
|
|
284
|
+
/* send the echo buffer */
|
|
181
285
|
esi_parser_echo_buffer( parser );
|
|
182
286
|
}
|
|
183
|
-
|
|
184
|
-
// stream the current character
|
|
287
|
+
/* send the current character */
|
|
185
288
|
esi_parser_echo_char( parser, *p );
|
|
186
289
|
}
|
|
187
|
-
|
|
290
|
+
/* clear the echo buffer */
|
|
188
291
|
esi_parser_echobuffer_clear( parser );
|
|
189
292
|
break;
|
|
190
293
|
default:
|
|
191
|
-
|
|
294
|
+
/* append to the echo buffer */
|
|
192
295
|
esi_parser_concat_to_echobuffer( parser, *p );
|
|
193
296
|
}
|
|
297
|
+
/* save the previous state, necessary for end case detection such as /> and </esi:try> the trailing > character
|
|
298
|
+
is state 12 and 7
|
|
299
|
+
*/
|
|
194
300
|
parser->prev_state = cs;
|
|
195
301
|
}
|
|
196
302
|
|
|
@@ -199,6 +305,7 @@ static void ltrim_pointer( const char **ptr, const char *bounds, size_t *len )
|
|
|
199
305
|
|
|
200
306
|
%%write data;
|
|
201
307
|
|
|
308
|
+
/* dup the string up to len */
|
|
202
309
|
char *esi_strndup( const char *str, size_t len )
|
|
203
310
|
{
|
|
204
311
|
char *s = (char*)malloc(sizeof(char)*(len+1));
|
|
@@ -260,7 +367,7 @@ ESIParser *esi_parser_new()
|
|
|
260
367
|
parser->overflow_data = NULL;
|
|
261
368
|
|
|
262
369
|
/* allocate 1024 bytes for the echobuffer */
|
|
263
|
-
parser->echobuffer_allocated =
|
|
370
|
+
parser->echobuffer_allocated = ESI_OUTPUT_BUFFER_SIZE; /* NOTE: change this value, to reduce memory consumtion or allocations */
|
|
264
371
|
parser->echobuffer_index = -1;
|
|
265
372
|
parser->echobuffer = (char*)malloc(sizeof(char)*parser->echobuffer_allocated);
|
|
266
373
|
|
|
@@ -271,6 +378,9 @@ ESIParser *esi_parser_new()
|
|
|
271
378
|
parser->end_tag_handler = esi_parser_default_end_cb;
|
|
272
379
|
parser->output_handler = esi_parser_default_output_cp;
|
|
273
380
|
|
|
381
|
+
parser->output_buffer_size = 0;
|
|
382
|
+
memset( parser->output_buffer, 0, ESI_OUTPUT_BUFFER_SIZE );
|
|
383
|
+
|
|
274
384
|
return parser;
|
|
275
385
|
}
|
|
276
386
|
void esi_parser_free( ESIParser *parser )
|
|
@@ -304,14 +414,22 @@ static int compute_offset( const char *mark, const char *data )
|
|
|
304
414
|
return -1;
|
|
305
415
|
}
|
|
306
416
|
|
|
417
|
+
/* accept an arbitrary length string buffer
|
|
418
|
+
* when this methods exits it determines if an end state was reached
|
|
419
|
+
* if no end state was reached it saves the full input into an internal buffer
|
|
420
|
+
* when invoked next, it reuses that internable buffer copying all pointers into the
|
|
421
|
+
* newly allocated buffer. if it exits in a terminal state, e.g. 0 then it will dump these buffers
|
|
422
|
+
*/
|
|
307
423
|
int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
|
|
308
424
|
{
|
|
309
425
|
int cs = parser->cs;
|
|
310
426
|
const char *p = data;
|
|
427
|
+
const char *eof = NULL; // ragel 6.x compat
|
|
311
428
|
const char *pe = data + length;
|
|
312
429
|
|
|
313
430
|
if( length == 0 ){ return cs; }
|
|
314
431
|
|
|
432
|
+
/* there's an existing overflow buffer data append the new data to the existing data */
|
|
315
433
|
if( parser->overflow_data && parser->overflow_data_size > 0 ){
|
|
316
434
|
|
|
317
435
|
// recompute mark, tag_text, attr_key, and attr_value since they all exist within overflow_data
|
|
@@ -320,13 +438,11 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
|
|
|
320
438
|
int attr_key_offset = compute_offset( parser->attr_key, parser->overflow_data );
|
|
321
439
|
int attr_value_offset = compute_offset( parser->attr_value, parser->overflow_data );
|
|
322
440
|
|
|
323
|
-
// debug_string("grow overflow buffer", parser->overflow_data, parser->overflow_data_size );
|
|
324
|
-
|
|
325
441
|
parser->overflow_data = (char*)realloc( parser->overflow_data, sizeof(char)*(parser->overflow_data_size+length) );
|
|
326
442
|
memcpy( parser->overflow_data+parser->overflow_data_size, data, length );
|
|
327
443
|
|
|
328
444
|
p = parser->overflow_data + parser->overflow_data_size;
|
|
329
|
-
|
|
445
|
+
|
|
330
446
|
// in our new memory space mark will now be
|
|
331
447
|
parser->mark = ( mark_offset >= 0 ) ? parser->overflow_data + mark_offset : NULL;
|
|
332
448
|
parser->tag_text = ( tag_text_offset >= 0 ) ? parser->overflow_data + tag_text_offset : NULL;
|
|
@@ -335,9 +451,9 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
|
|
|
335
451
|
|
|
336
452
|
data = parser->overflow_data;
|
|
337
453
|
parser->overflow_data_size = length = length + parser->overflow_data_size;
|
|
454
|
+
// printf( "grow overflow data: %ld\n", parser->overflow_data_size );
|
|
338
455
|
pe = data + length;
|
|
339
456
|
|
|
340
|
-
// debug_string( "overflow", parser->overflow_data, parser->overflow_data_size );
|
|
341
457
|
}
|
|
342
458
|
|
|
343
459
|
if( !parser->mark ){
|
|
@@ -345,7 +461,6 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
|
|
|
345
461
|
}
|
|
346
462
|
|
|
347
463
|
// printf( "cs: %d, ", cs );
|
|
348
|
-
// debug_string( "data", data, length );
|
|
349
464
|
|
|
350
465
|
%% write exec;
|
|
351
466
|
|
|
@@ -353,6 +468,7 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
|
|
|
353
468
|
|
|
354
469
|
if( cs != esi_start && cs != 0 ){
|
|
355
470
|
|
|
471
|
+
/* reached the end and we're not at a termination point save the buffer as overflow */
|
|
356
472
|
if( !parser->overflow_data ){
|
|
357
473
|
// recompute mark, tag_text, attr_key, and attr_value since they all exist within overflow_data
|
|
358
474
|
int mark_offset = compute_offset( parser->mark, data );
|
|
@@ -364,6 +480,7 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
|
|
|
364
480
|
parser->overflow_data = (char*)malloc( sizeof( char ) * length );
|
|
365
481
|
memcpy( parser->overflow_data, data, length );
|
|
366
482
|
parser->overflow_data_size = length;
|
|
483
|
+
// printf( "allocate overflow data: %ld\n", parser->overflow_data_size );
|
|
367
484
|
|
|
368
485
|
// in our new memory space mark will now be
|
|
369
486
|
parser->mark = ( mark_offset >= 0 ) ? parser->overflow_data + mark_offset : NULL;
|
|
@@ -374,6 +491,7 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
|
|
|
374
491
|
}
|
|
375
492
|
|
|
376
493
|
}else if( parser->overflow_data ){
|
|
494
|
+
/* dump the overflow buffer execution ended at a final state */
|
|
377
495
|
free( parser->overflow_data );
|
|
378
496
|
parser->overflow_data = NULL;
|
|
379
497
|
parser->overflow_data_size = 0;
|
|
@@ -383,7 +501,7 @@ int esi_parser_execute( ESIParser *parser, const char *data, size_t length )
|
|
|
383
501
|
}
|
|
384
502
|
int esi_parser_finish( ESIParser *parser )
|
|
385
503
|
{
|
|
386
|
-
|
|
504
|
+
esi_parser_flush_output( parser );
|
|
387
505
|
return 0;
|
|
388
506
|
}
|
|
389
507
|
|