ruby-lsapi 4.2 → 4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/lsapi/lsapidef.h +2 -1
- data/ext/lsapi/lsapilib.c +210 -145
- data/ext/lsapi/lsapilib.h +12 -12
- data/ext/lsapi/lsruby.c +438 -212
- data/lsapi.gemspec +16 -0
- metadata +8 -7
data/ext/lsapi/lsapilib.h
CHANGED
@@ -38,9 +38,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
38
38
|
extern "C" {
|
39
39
|
#endif
|
40
40
|
|
41
|
-
#include
|
42
|
-
#include <lsapidef.h>
|
41
|
+
#include "lsapidef.h"
|
43
42
|
|
43
|
+
#include <stddef.h>
|
44
44
|
#include <sys/time.h>
|
45
45
|
#include <sys/types.h>
|
46
46
|
|
@@ -276,28 +276,28 @@ static inline int LSAPI_ForeachSpecialEnv( LSAPI_CB_EnvHandler fn, void * arg )
|
|
276
276
|
static inline char * LSAPI_GetEnv( const char * name )
|
277
277
|
{ return LSAPI_GetEnv_r( &g_req, name ); }
|
278
278
|
|
279
|
-
static inline char * LSAPI_GetQueryString()
|
279
|
+
static inline char * LSAPI_GetQueryString(void)
|
280
280
|
{ return LSAPI_GetQueryString_r( &g_req ); }
|
281
281
|
|
282
|
-
static inline char * LSAPI_GetScriptFileName()
|
282
|
+
static inline char * LSAPI_GetScriptFileName(void)
|
283
283
|
{ return LSAPI_GetScriptFileName_r( &g_req ); }
|
284
284
|
|
285
|
-
static inline char * LSAPI_GetScriptName()
|
285
|
+
static inline char * LSAPI_GetScriptName(void)
|
286
286
|
{ return LSAPI_GetScriptName_r( &g_req ); }
|
287
287
|
|
288
|
-
static inline char * LSAPI_GetRequestMethod()
|
288
|
+
static inline char * LSAPI_GetRequestMethod(void)
|
289
289
|
{ return LSAPI_GetRequestMethod_r( &g_req ); }
|
290
290
|
|
291
|
-
static inline off_t LSAPI_GetReqBodyLen()
|
291
|
+
static inline off_t LSAPI_GetReqBodyLen(void)
|
292
292
|
{ return LSAPI_GetReqBodyLen_r( &g_req ); }
|
293
293
|
|
294
|
-
static inline off_t LSAPI_GetReqBodyRemain()
|
294
|
+
static inline off_t LSAPI_GetReqBodyRemain(void)
|
295
295
|
{ return LSAPI_GetReqBodyRemain_r( &g_req ); }
|
296
296
|
|
297
297
|
static inline ssize_t LSAPI_ReadReqBody( char * pBuf, size_t len )
|
298
298
|
{ return LSAPI_ReadReqBody_r( &g_req, pBuf, len ); }
|
299
299
|
|
300
|
-
static inline int LSAPI_ReqBodyGetChar()
|
300
|
+
static inline int LSAPI_ReqBodyGetChar(void)
|
301
301
|
{ return LSAPI_ReqBodyGetChar_r( &g_req ); }
|
302
302
|
|
303
303
|
static inline int LSAPI_ReqBodyGetLine( char * pBuf, int len, int *getLF )
|
@@ -319,7 +319,7 @@ static inline ssize_t LSAPI_sendfile( int fdIn, off_t* off, size_t size )
|
|
319
319
|
static inline ssize_t LSAPI_Write_Stderr( const char * pBuf, ssize_t len )
|
320
320
|
{ return LSAPI_Write_Stderr_r( &g_req, pBuf, len ); }
|
321
321
|
|
322
|
-
static inline int LSAPI_Flush()
|
322
|
+
static inline int LSAPI_Flush(void)
|
323
323
|
{ return LSAPI_Flush_r( &g_req ); }
|
324
324
|
|
325
325
|
static inline int LSAPI_AppendRespHeader( char * pBuf, int len )
|
@@ -359,9 +359,9 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp );
|
|
359
359
|
|
360
360
|
void LSAPI_Set_Slow_Req_Msecs( int msecs );
|
361
361
|
|
362
|
-
int LSAPI_Get_Slow_Req_Msecs(
|
362
|
+
int LSAPI_Get_Slow_Req_Msecs(void);
|
363
363
|
|
364
|
-
int LSAPI_is_suEXEC_Daemon();
|
364
|
+
int LSAPI_is_suEXEC_Daemon(void);
|
365
365
|
|
366
366
|
#if defined (c_plusplus) || defined (__cplusplus)
|
367
367
|
}
|
data/ext/lsapi/lsruby.c
CHANGED
@@ -15,6 +15,8 @@
|
|
15
15
|
#include <sys/socket.h>
|
16
16
|
#include <sys/wait.h>
|
17
17
|
#include <unistd.h>
|
18
|
+
#include <sys/mman.h>
|
19
|
+
#include <fcntl.h>
|
18
20
|
|
19
21
|
/* RUBY_EXTERN VALUE ruby_errinfo; */
|
20
22
|
RUBY_EXTERN VALUE rb_stdin;
|
@@ -36,6 +38,7 @@ static VALUE env_copy;
|
|
36
38
|
|
37
39
|
static VALUE lsapi_env;
|
38
40
|
|
41
|
+
static int MAX_BODYBUF_LENGTH = (10 * 1024 * 1024);
|
39
42
|
|
40
43
|
/* static VALUE lsapi_objrefs; */
|
41
44
|
|
@@ -44,10 +47,8 @@ typedef struct lsapi_data
|
|
44
47
|
LSAPI_Request * req;
|
45
48
|
VALUE env;
|
46
49
|
ssize_t (* fn_write)( LSAPI_Request *, const char * , size_t );
|
47
|
-
|
48
50
|
}lsapi_data;
|
49
51
|
|
50
|
-
|
51
52
|
static VALUE cLSAPI;
|
52
53
|
|
53
54
|
static VALUE s_req = Qnil;
|
@@ -57,17 +58,28 @@ static VALUE s_req_stderr = Qnil;
|
|
57
58
|
static lsapi_data * s_stderr_data;
|
58
59
|
static pid_t s_pid = 0;
|
59
60
|
|
60
|
-
|
61
|
-
static void lsapi_ruby_setenv(const char *name, const char *value)
|
61
|
+
typedef struct lsapi_body
|
62
62
|
{
|
63
|
-
|
63
|
+
char *bodyBuf; //we put small one into memory, otherwise, into a memory mapping file, and we still use the bodyBuf to access this mapping
|
64
|
+
int bodyLen; //expected length got form content-length
|
65
|
+
int bodyCurrentLen; //current length by read() readBodyToReqBuf
|
66
|
+
int curPos;
|
67
|
+
}lsapi_body;
|
64
68
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
static lsapi_body s_body;
|
70
|
+
static char sTempFile[1024] = {0};
|
71
|
+
|
72
|
+
/*
|
73
|
+
* static void lsapi_ruby_setenv(const char *name, const char *value)
|
74
|
+
* {
|
75
|
+
* if (!name) return;
|
76
|
+
*
|
77
|
+
* if (value && *value)
|
78
|
+
* ruby_setenv(name, value);
|
79
|
+
* else
|
80
|
+
* ruby_unsetenv(name);
|
81
|
+
} * *
|
82
|
+
*/
|
71
83
|
|
72
84
|
|
73
85
|
static void lsapi_mark( lsapi_data * data )
|
@@ -75,87 +87,87 @@ static void lsapi_mark( lsapi_data * data )
|
|
75
87
|
rb_gc_mark( data->env );
|
76
88
|
}
|
77
89
|
/*
|
78
|
-
static void lsapi_free_data( lsapi_data * data )
|
79
|
-
{
|
80
|
-
free( data );
|
81
|
-
}
|
82
|
-
*/
|
90
|
+
* static void lsapi_free_data( lsapi_data * data )
|
91
|
+
* {
|
92
|
+
* free( data );
|
93
|
+
} * *
|
94
|
+
*/
|
83
95
|
static int add_env_rails( const char * pKey, int keyLen, const char * pValue, int valLen,
|
84
|
-
|
96
|
+
void * arg )
|
85
97
|
{
|
86
98
|
char * p;
|
87
99
|
int len;
|
88
100
|
/* Fixup some environment variables for rails */
|
89
101
|
switch( *pKey )
|
90
102
|
{
|
91
|
-
|
92
|
-
|
93
|
-
{
|
94
|
-
if ( !*pValue )
|
95
|
-
return 1;
|
96
|
-
}
|
97
|
-
break;
|
98
|
-
case 'R':
|
99
|
-
if (( *(pKey+8) == 'U' )&&( strcmp( pKey, "REQUEST_URI" ) == 0 ))
|
100
|
-
{
|
101
|
-
p = strchr( pValue, '?' );
|
102
|
-
if ( p )
|
103
|
+
case 'Q':
|
104
|
+
if ( strcmp( pKey, "QUERY_STRING" ) == 0 )
|
103
105
|
{
|
104
|
-
|
105
|
-
|
106
|
-
valLen = p - pValue;
|
107
|
-
*p++ = 0;
|
108
|
-
*/
|
106
|
+
if ( !*pValue )
|
107
|
+
return 1;
|
109
108
|
}
|
110
|
-
|
109
|
+
break;
|
110
|
+
case 'R':
|
111
|
+
if (( *(pKey+8) == 'U' )&&( strcmp( pKey, "REQUEST_URI" ) == 0 ))
|
111
112
|
{
|
112
|
-
p = (
|
113
|
-
|
113
|
+
p = strchr( pValue, '?' );
|
114
|
+
if ( p )
|
115
|
+
{
|
116
|
+
len = valLen - ( p - pValue ) - 1;
|
117
|
+
/*
|
118
|
+
* valLen = p - pValue;
|
119
|
+
*p++ = 0;
|
120
|
+
*/
|
121
|
+
}
|
122
|
+
else
|
123
|
+
{
|
124
|
+
p = (char *)pValue + valLen;
|
125
|
+
len = 0;
|
126
|
+
}
|
127
|
+
rb_hash_aset( lsapi_env,rb_tainted_str_new("PATH_INFO", 9),
|
128
|
+
rb_tainted_str_new(pValue, p - pValue));
|
129
|
+
rb_hash_aset( lsapi_env,rb_tainted_str_new("REQUEST_PATH", 12),
|
130
|
+
rb_tainted_str_new(pValue, p - pValue));
|
131
|
+
if ( *p == '?' )
|
132
|
+
++p;
|
133
|
+
rb_hash_aset( lsapi_env,rb_tainted_str_new("QUERY_STRING", 12),
|
134
|
+
rb_tainted_str_new(p, len));
|
114
135
|
}
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
pValue = "/";
|
129
|
-
valLen = 1;
|
130
|
-
}
|
131
|
-
break;
|
132
|
-
case 'P':
|
133
|
-
if ( strcmp( pKey, "PATH_INFO" ) == 0 )
|
134
|
-
return 1;
|
135
|
-
default:
|
136
|
-
break;
|
136
|
+
break;
|
137
|
+
case 'S':
|
138
|
+
if ( strcmp( pKey, "SCRIPT_NAME" ) == 0 )
|
139
|
+
{
|
140
|
+
pValue = "/";
|
141
|
+
valLen = 1;
|
142
|
+
}
|
143
|
+
break;
|
144
|
+
case 'P':
|
145
|
+
if ( strcmp( pKey, "PATH_INFO" ) == 0 )
|
146
|
+
return 1;
|
147
|
+
default:
|
148
|
+
break;
|
137
149
|
}
|
138
150
|
|
139
151
|
/* lsapi_ruby_setenv(pKey, pValue ); */
|
140
152
|
|
141
153
|
rb_hash_aset( lsapi_env,rb_tainted_str_new(pKey, keyLen),
|
142
|
-
|
154
|
+
rb_tainted_str_new(pValue, valLen));
|
143
155
|
return 1;
|
144
156
|
}
|
145
157
|
|
146
158
|
static int add_env_no_fix( const char * pKey, int keyLen, const char * pValue, int valLen,
|
147
|
-
|
159
|
+
void * arg )
|
148
160
|
{
|
149
161
|
rb_hash_aset( lsapi_env,rb_tainted_str_new(pKey, keyLen),
|
150
|
-
|
162
|
+
rb_tainted_str_new(pValue, valLen));
|
151
163
|
return 1;
|
152
164
|
}
|
153
165
|
|
154
166
|
typedef int (*fn_add_env)( const char * pKey, int keyLen, const char * pValue, int valLen,
|
155
|
-
|
156
|
-
|
167
|
+
void * arg );
|
168
|
+
|
157
169
|
fn_add_env s_fn_add_env = add_env_no_fix;
|
158
|
-
|
170
|
+
|
159
171
|
static void clear_env()
|
160
172
|
{
|
161
173
|
/* rb_funcall( lsapi_env, rb_intern( "clear" ), 0 ); */
|
@@ -165,15 +177,11 @@ static void clear_env()
|
|
165
177
|
static void setup_cgi_env( lsapi_data * data )
|
166
178
|
{
|
167
179
|
clear_env();
|
168
|
-
|
180
|
+
|
169
181
|
LSAPI_ForeachHeader_r( data->req, s_fn_add_env, data );
|
170
182
|
LSAPI_ForeachEnv_r( data->req, s_fn_add_env, data );
|
171
|
-
|
172
183
|
}
|
173
184
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
185
|
static VALUE lsapi_s_accept( VALUE self )
|
178
186
|
{
|
179
187
|
int pid;
|
@@ -181,33 +189,39 @@ static VALUE lsapi_s_accept( VALUE self )
|
|
181
189
|
return Qnil;
|
182
190
|
else
|
183
191
|
{
|
184
|
-
|
192
|
+
if (s_body.bodyBuf != NULL)
|
193
|
+
free (s_body.bodyBuf);
|
194
|
+
|
195
|
+
s_body.bodyBuf = NULL;
|
196
|
+
s_body.bodyLen = -1;
|
197
|
+
s_body.bodyCurrentLen = 0;
|
198
|
+
s_body.curPos = 0;
|
199
|
+
|
185
200
|
pid = getpid();
|
186
201
|
if ( pid != s_pid )
|
187
202
|
{
|
188
203
|
s_pid = pid;
|
189
204
|
rb_funcall( Qnil, rb_intern( "srand" ), 0 );
|
190
205
|
}
|
191
|
-
|
206
|
+
|
192
207
|
setup_cgi_env( s_req_data );
|
193
208
|
return s_req;
|
194
209
|
}
|
195
|
-
|
196
210
|
}
|
197
211
|
|
198
212
|
/*
|
199
|
-
static int chdir_file( const char * pFile )
|
200
|
-
{
|
201
|
-
char * p = strrchr( pFile, '/' );
|
202
|
-
int ret;
|
203
|
-
if ( !p )
|
204
|
-
return -1;
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
}
|
210
|
-
*/
|
213
|
+
* static int chdir_file( const char * pFile )
|
214
|
+
* {
|
215
|
+
* char * p = strrchr( pFile, '/' );
|
216
|
+
* int ret;
|
217
|
+
* if ( !p )
|
218
|
+
* return -1;
|
219
|
+
*p = 0;
|
220
|
+
ret = chdir( pFile );
|
221
|
+
*p = '/';
|
222
|
+
return ret;
|
223
|
+
}
|
224
|
+
*/
|
211
225
|
|
212
226
|
static VALUE lsapi_eval_string_wrap(VALUE self, VALUE str)
|
213
227
|
{
|
@@ -224,18 +238,19 @@ static VALUE lsapi_eval_string_wrap(VALUE self, VALUE str)
|
|
224
238
|
|
225
239
|
static VALUE lsapi_process( VALUE self )
|
226
240
|
{
|
227
|
-
lsapi_data *data;
|
241
|
+
/* lsapi_data *data;
|
228
242
|
const char * pScriptPath;
|
229
243
|
Data_Get_Struct(self,lsapi_data, data);
|
230
244
|
pScriptPath = LSAPI_GetScriptFileName_r( data->req );
|
231
|
-
/*
|
232
|
-
if ( chdir_file( pScriptPath ) == -1 )
|
233
|
-
{
|
234
|
-
lsapi_send_error( 404 );
|
235
|
-
}
|
236
|
-
rb_load_file( pScriptPath );
|
237
245
|
*/
|
238
|
-
|
246
|
+
/*
|
247
|
+
* if ( chdir_file( pScriptPath ) == -1 )
|
248
|
+
* {
|
249
|
+
* lsapi_send_error( 404 );
|
250
|
+
* }
|
251
|
+
* rb_load_file( pScriptPath );
|
252
|
+
*/
|
253
|
+
return Qnil;
|
239
254
|
}
|
240
255
|
|
241
256
|
|
@@ -256,9 +271,9 @@ static VALUE lsapi_write( VALUE self, VALUE str )
|
|
256
271
|
lsapi_data *data;
|
257
272
|
int len;
|
258
273
|
Data_Get_Struct(self,lsapi_data, data);
|
259
|
-
/* len = LSAPI_Write_r( data->req, RSTRING_PTR(str), RSTRING_LEN(str) ); */
|
274
|
+
/* len = LSAPI_Write_r( data->req, RSTRING_PTR(str), RSTRING_LEN(str) ); */
|
260
275
|
if (TYPE(str) != T_STRING)
|
261
|
-
|
276
|
+
str = rb_obj_as_string(str);
|
262
277
|
len = (*data->fn_write)( data->req, RSTRING_PTR(str), RSTRING_LEN(str) );
|
263
278
|
return INT2NUM( len );
|
264
279
|
}
|
@@ -267,13 +282,13 @@ static VALUE lsapi_print( int argc, VALUE *argv, VALUE out )
|
|
267
282
|
{
|
268
283
|
int i;
|
269
284
|
VALUE line;
|
270
|
-
|
285
|
+
|
271
286
|
/* if no argument given, print `$_' */
|
272
287
|
if (argc == 0)
|
273
288
|
{
|
274
|
-
|
275
|
-
|
276
|
-
|
289
|
+
argc = 1;
|
290
|
+
line = rb_lastline_get();
|
291
|
+
argv = &line;
|
277
292
|
}
|
278
293
|
for (i = 0; i<argc; i++)
|
279
294
|
{
|
@@ -283,19 +298,19 @@ static VALUE lsapi_print( int argc, VALUE *argv, VALUE out )
|
|
283
298
|
}
|
284
299
|
switch (TYPE(argv[i]))
|
285
300
|
{
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
301
|
+
case T_NIL:
|
302
|
+
lsapi_write(out, rb_str_new2("nil"));
|
303
|
+
break;
|
304
|
+
default:
|
305
|
+
lsapi_write(out, argv[i]);
|
306
|
+
break;
|
292
307
|
}
|
293
308
|
}
|
294
309
|
if (!NIL_P(rb_output_rs))
|
295
310
|
{
|
296
311
|
lsapi_write(out, rb_output_rs);
|
297
312
|
}
|
298
|
-
|
313
|
+
|
299
314
|
return Qnil;
|
300
315
|
}
|
301
316
|
|
@@ -312,8 +327,8 @@ static VALUE lsapi_puts_ary(VALUE ary, VALUE out, int recur )
|
|
312
327
|
{
|
313
328
|
VALUE tmp;
|
314
329
|
long i;
|
315
|
-
|
316
|
-
if (recur)
|
330
|
+
|
331
|
+
if (recur)
|
317
332
|
{
|
318
333
|
tmp = rb_str_new2("[...]");
|
319
334
|
rb_io_puts(1, &tmp, out);
|
@@ -325,22 +340,22 @@ static VALUE lsapi_puts_ary(VALUE ary, VALUE out, int recur )
|
|
325
340
|
rb_io_puts(1, &tmp, out);
|
326
341
|
}
|
327
342
|
return Qnil;
|
328
|
-
|
343
|
+
|
329
344
|
}
|
330
345
|
#else
|
331
346
|
static VALUE lsapi_puts_ary(VALUE ary, VALUE out)
|
332
347
|
{
|
333
348
|
VALUE tmp;
|
334
349
|
int i;
|
335
|
-
|
350
|
+
|
336
351
|
for (i=0; i<RARRAY_LEN(ary); i++)
|
337
352
|
{
|
338
353
|
tmp = RARRAY_PTR(ary)[i];
|
339
|
-
|
354
|
+
if (rb_inspecting_p(tmp))
|
340
355
|
{
|
341
|
-
|
342
|
-
|
343
|
-
|
356
|
+
tmp = rb_str_new2("[...]");
|
357
|
+
}
|
358
|
+
lsapi_puts(1, &tmp, out);
|
344
359
|
}
|
345
360
|
return Qnil;
|
346
361
|
}
|
@@ -350,7 +365,7 @@ static VALUE lsapi_puts(int argc, VALUE *argv, VALUE out)
|
|
350
365
|
{
|
351
366
|
int i;
|
352
367
|
VALUE line;
|
353
|
-
|
368
|
+
|
354
369
|
/* if no argument given, print newline. */
|
355
370
|
if (argc == 0)
|
356
371
|
{
|
@@ -361,19 +376,19 @@ static VALUE lsapi_puts(int argc, VALUE *argv, VALUE out)
|
|
361
376
|
{
|
362
377
|
switch (TYPE(argv[i]))
|
363
378
|
{
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
379
|
+
case T_NIL:
|
380
|
+
line = rb_str_new2("nil");
|
381
|
+
break;
|
382
|
+
case T_ARRAY:
|
368
383
|
#if defined( RUBY_19 ) || defined( RUBY_2 )
|
369
|
-
|
384
|
+
rb_exec_recursive(lsapi_puts_ary, argv[i], out);
|
370
385
|
#else
|
371
|
-
|
386
|
+
rb_protect_inspect(lsapi_puts_ary, argv[i], out);
|
372
387
|
#endif
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
388
|
+
continue;
|
389
|
+
default:
|
390
|
+
line = argv[i];
|
391
|
+
break;
|
377
392
|
}
|
378
393
|
line = rb_obj_as_string(line);
|
379
394
|
lsapi_write(out, line);
|
@@ -382,7 +397,7 @@ static VALUE lsapi_puts(int argc, VALUE *argv, VALUE out)
|
|
382
397
|
lsapi_write(out, rb_default_rs);
|
383
398
|
}
|
384
399
|
}
|
385
|
-
|
400
|
+
|
386
401
|
return Qnil;
|
387
402
|
}
|
388
403
|
|
@@ -395,10 +410,10 @@ static VALUE lsapi_addstr(VALUE out, VALUE str)
|
|
395
410
|
|
396
411
|
static VALUE lsapi_flush( VALUE self )
|
397
412
|
{
|
398
|
-
/*
|
399
|
-
lsapi_data *data;
|
400
|
-
Data_Get_Struct(self,lsapi_data, data);
|
401
|
-
*/
|
413
|
+
/*
|
414
|
+
* lsapi_data *data;
|
415
|
+
* Data_Get_Struct(self,lsapi_data, data);
|
416
|
+
*/
|
402
417
|
LSAPI_Flush_r( &g_req );
|
403
418
|
return Qnil;
|
404
419
|
}
|
@@ -406,10 +421,10 @@ static VALUE lsapi_flush( VALUE self )
|
|
406
421
|
static VALUE lsapi_getc( VALUE self )
|
407
422
|
{
|
408
423
|
int ch;
|
409
|
-
/*
|
410
|
-
lsapi_data *data;
|
411
|
-
Data_Get_Struct(self,lsapi_data, data);
|
412
|
-
*/
|
424
|
+
/*
|
425
|
+
* lsapi_data *data;
|
426
|
+
* Data_Get_Struct(self,lsapi_data, data);
|
427
|
+
*/
|
413
428
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self))
|
414
429
|
{
|
415
430
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
@@ -420,88 +435,246 @@ static VALUE lsapi_getc( VALUE self )
|
|
420
435
|
return INT2NUM( ch );
|
421
436
|
}
|
422
437
|
|
438
|
+
static inline int isBodyWriteToFile()
|
439
|
+
{
|
440
|
+
return ((s_body.bodyLen >= MAX_BODYBUF_LENGTH)? (1): (0));
|
441
|
+
}
|
442
|
+
|
443
|
+
//create a temp file and open it, if failed, fd = -1
|
444
|
+
static inline int createTempFile()
|
445
|
+
{
|
446
|
+
int fd = -1;
|
447
|
+
char *sfn = strdup(sTempFile);
|
448
|
+
|
449
|
+
if ((fd = mkstemp(sfn)) == -1)
|
450
|
+
{
|
451
|
+
fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
|
452
|
+
}
|
453
|
+
else
|
454
|
+
unlink(sfn);
|
455
|
+
|
456
|
+
free(sfn);
|
457
|
+
return fd;
|
458
|
+
}
|
459
|
+
|
460
|
+
//return 1 if error occured!
|
461
|
+
//if already created, always OK (0)
|
462
|
+
static int createBodyBuf()
|
463
|
+
{
|
464
|
+
int fd = -1;
|
465
|
+
if (s_body.bodyLen == -1)
|
466
|
+
{
|
467
|
+
s_body.bodyLen = LSAPI_GetReqBodyLen_r(&g_req);
|
468
|
+
//Error if get a zeor length, should not happen
|
469
|
+
if (s_body.bodyLen < 0)
|
470
|
+
{
|
471
|
+
//Wrong bode length will be treated as 0
|
472
|
+
s_body.bodyLen = 0;
|
473
|
+
}
|
474
|
+
|
475
|
+
if (s_body.bodyLen > 0)
|
476
|
+
{
|
477
|
+
if (isBodyWriteToFile())
|
478
|
+
{
|
479
|
+
//create file mapping
|
480
|
+
fd = createTempFile();
|
481
|
+
if (fd == -1)
|
482
|
+
{
|
483
|
+
return 1;
|
484
|
+
}
|
485
|
+
ftruncate(fd, s_body.bodyLen);
|
486
|
+
s_body.bodyBuf = mmap(NULL, s_body.bodyLen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
487
|
+
if (s_body.bodyBuf == MAP_FAILED)
|
488
|
+
{
|
489
|
+
perror("File mapping failed. \n");
|
490
|
+
close(fd);
|
491
|
+
return 1;
|
492
|
+
}
|
493
|
+
|
494
|
+
close(fd); //close since needn't it anymore
|
495
|
+
}
|
496
|
+
else
|
497
|
+
{
|
498
|
+
s_body.bodyBuf = (char *)calloc(s_body.bodyLen, sizeof(char));
|
499
|
+
if (s_body.bodyBuf == NULL)
|
500
|
+
{
|
501
|
+
perror("Memory calloc error");
|
502
|
+
return 1;
|
503
|
+
}
|
504
|
+
}
|
505
|
+
}
|
506
|
+
}
|
507
|
+
|
508
|
+
return 0;
|
509
|
+
}
|
510
|
+
|
511
|
+
static inline int isAllBodyRead()
|
512
|
+
{
|
513
|
+
return (s_body.bodyCurrentLen < s_body.bodyLen)? 0 : 1;
|
514
|
+
}
|
515
|
+
|
516
|
+
static inline int isEofBodyBuf()
|
517
|
+
{
|
518
|
+
return (s_body.curPos < s_body.bodyLen) ? 0 : 1;
|
519
|
+
}
|
520
|
+
//try to read length as times pagesize (such as 8KB * N)
|
521
|
+
static int readBodyBuf(const int needRead)
|
522
|
+
{
|
523
|
+
const int blockSize = 8192;
|
524
|
+
char *buff = s_body.bodyBuf + s_body.bodyCurrentLen;
|
525
|
+
int nRead;
|
526
|
+
int readMore = (needRead + blockSize -1) / blockSize * blockSize;
|
527
|
+
int remain = LSAPI_GetReqBodyRemain_r( &g_req );
|
528
|
+
//Only when not enough left, needReadChange will be changed!!!
|
529
|
+
if (remain < readMore)
|
530
|
+
readMore = remain;
|
531
|
+
|
532
|
+
if ( readMore <= 0 )
|
533
|
+
return 0;
|
534
|
+
|
535
|
+
nRead = LSAPI_ReadReqBody_r(&g_req, buff, readMore);
|
536
|
+
if ( nRead > 0 )
|
537
|
+
s_body.bodyCurrentLen += nRead;
|
538
|
+
|
539
|
+
return nRead;
|
540
|
+
}
|
541
|
+
|
423
542
|
static VALUE lsapi_gets( VALUE self )
|
424
543
|
{
|
425
544
|
VALUE str;
|
426
|
-
int
|
427
|
-
|
428
|
-
|
545
|
+
const int blkSize = 4096;
|
546
|
+
int n;
|
547
|
+
char *p = NULL;
|
548
|
+
|
429
549
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self))
|
430
550
|
{
|
431
551
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
432
552
|
}
|
433
|
-
|
553
|
+
|
554
|
+
if (createBodyBuf() == 1)
|
555
|
+
{
|
434
556
|
return Qnil;
|
435
|
-
|
557
|
+
}
|
558
|
+
|
559
|
+
//comment:
|
560
|
+
while((p = memmem(s_body.bodyBuf + s_body.curPos, s_body.bodyCurrentLen - s_body.curPos, "\n", 1)) == NULL)
|
561
|
+
{
|
562
|
+
if (isAllBodyRead() == 1)
|
563
|
+
break;
|
564
|
+
//read one page and check, then reply
|
565
|
+
readBodyBuf(blkSize);
|
566
|
+
}
|
567
|
+
|
568
|
+
p = memmem(s_body.bodyBuf + s_body.curPos, s_body.bodyCurrentLen - s_body.curPos, "\n", 1);
|
569
|
+
if (p != NULL)
|
570
|
+
n = p - s_body.bodyBuf - s_body.curPos + 1;
|
571
|
+
else
|
572
|
+
n = s_body.bodyCurrentLen - s_body.curPos;
|
573
|
+
|
574
|
+
str = rb_str_buf_new( n );
|
436
575
|
OBJ_TAINT(str);
|
437
|
-
|
576
|
+
|
577
|
+
if (n > 0)
|
438
578
|
{
|
439
|
-
|
440
|
-
|
441
|
-
rb_str_buf_cat( str, buff, len );
|
442
|
-
|
579
|
+
rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n );
|
580
|
+
s_body.curPos += n;
|
443
581
|
}
|
444
|
-
|
445
|
-
return Qnil;
|
582
|
+
|
446
583
|
return str;
|
447
584
|
}
|
448
585
|
|
449
|
-
|
450
586
|
static VALUE lsapi_read(int argc, VALUE *argv, VALUE self)
|
451
587
|
{
|
452
588
|
VALUE str;
|
453
589
|
int n;
|
454
|
-
int
|
455
|
-
|
456
|
-
|
590
|
+
int needRead;
|
591
|
+
int nRead;
|
592
|
+
|
457
593
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self))
|
458
594
|
{
|
459
595
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
460
596
|
}
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
if ( remain <= 0 )
|
597
|
+
|
598
|
+
if (createBodyBuf() == 1)
|
599
|
+
{
|
465
600
|
return Qnil;
|
466
|
-
|
601
|
+
}
|
602
|
+
|
603
|
+
//we need to consider these 4 cases:
|
604
|
+
//1, need all data since argc == 0, we may have all data 2, or not
|
605
|
+
//3, need a length of data (argv >= 1), we may have enough data already read, 4, or not
|
606
|
+
if (argc == 0)
|
607
|
+
n = s_body.bodyLen - s_body.curPos;
|
608
|
+
else
|
467
609
|
{
|
468
|
-
n = NUM2INT(argv[0]);
|
469
|
-
if (
|
470
|
-
|
610
|
+
n = NUM2INT(argv[0]); //request that length from currentpos
|
611
|
+
if (n < 0)
|
612
|
+
return Qnil;
|
613
|
+
if (n > s_body.bodyLen - s_body.curPos)
|
614
|
+
n = s_body.bodyLen - s_body.curPos;
|
471
615
|
}
|
472
|
-
|
616
|
+
needRead = s_body.curPos + n - s_body.bodyCurrentLen;
|
617
|
+
if (needRead < 0)
|
618
|
+
needRead = 0;
|
619
|
+
|
620
|
+
str = rb_str_buf_new( n );
|
473
621
|
OBJ_TAINT(str);
|
474
|
-
|
622
|
+
if (n == 0)
|
623
|
+
return str;
|
624
|
+
|
625
|
+
//copy already have part first
|
626
|
+
if (n - needRead != 0)
|
475
627
|
{
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
628
|
+
rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n - needRead);
|
629
|
+
s_body.curPos += (n - needRead);
|
630
|
+
}
|
631
|
+
|
632
|
+
if (needRead > 0)
|
633
|
+
{
|
634
|
+
//try to read needRead, but may be less (changed) when read the end of the data
|
635
|
+
nRead = readBodyBuf(needRead);
|
636
|
+
if (nRead > 0)
|
484
637
|
{
|
485
|
-
|
486
|
-
|
638
|
+
n = ((nRead < needRead) ? nRead : needRead);
|
639
|
+
rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n );
|
640
|
+
s_body.curPos += n;
|
487
641
|
}
|
488
642
|
}
|
489
|
-
|
490
|
-
return Qnil;
|
643
|
+
|
491
644
|
return str;
|
492
645
|
}
|
493
646
|
|
494
|
-
static VALUE
|
647
|
+
static VALUE lsapi_rewind(VALUE self)
|
648
|
+
{
|
649
|
+
s_body.curPos = 0;
|
650
|
+
return self;
|
651
|
+
}
|
652
|
+
|
653
|
+
static VALUE lsapi_each(int argc, VALUE *argv, VALUE self)
|
495
654
|
{
|
496
|
-
|
497
|
-
|
655
|
+
VALUE str;
|
656
|
+
lsapi_rewind(self);
|
657
|
+
|
658
|
+
while(isEofBodyBuf() != 1)
|
659
|
+
{
|
660
|
+
str = lsapi_gets(self);
|
661
|
+
rb_yield(str);
|
662
|
+
}
|
663
|
+
return self;
|
498
664
|
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
665
|
+
}
|
666
|
+
|
667
|
+
static VALUE lsapi_eof(VALUE self)
|
668
|
+
{
|
669
|
+
/*
|
670
|
+
* lsapi_data *data;
|
671
|
+
*
|
672
|
+
* if (rb_safe_level() >= 4 && !OBJ_TAINTED(self))
|
673
|
+
* {
|
674
|
+
* rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
675
|
+
}
|
676
|
+
Data_Get_Struct(self, lsapi_data, data);
|
677
|
+
*/
|
505
678
|
return (LSAPI_GetReqBodyRemain_r( &g_req ) <= 0) ? Qtrue : Qfalse;
|
506
679
|
}
|
507
680
|
|
@@ -527,7 +700,22 @@ static VALUE lsapi_setsync(VALUE self,VALUE sync)
|
|
527
700
|
|
528
701
|
static VALUE lsapi_close(VALUE self)
|
529
702
|
{
|
530
|
-
LSAPI_Flush_r( &g_req );
|
703
|
+
LSAPI_Flush_r( &g_req );
|
704
|
+
if (isBodyWriteToFile())
|
705
|
+
{
|
706
|
+
//msync(s_body.bodyBuf, s_body.bodyLen, MS_SYNC);
|
707
|
+
//sleep(5);
|
708
|
+
munmap(s_body.bodyBuf, s_body.bodyLen);
|
709
|
+
}
|
710
|
+
else
|
711
|
+
free(s_body.bodyBuf);
|
712
|
+
|
713
|
+
s_body.bodyBuf = NULL;
|
714
|
+
s_body.bodyLen = -1;
|
715
|
+
s_body.bodyCurrentLen = 0;
|
716
|
+
s_body.curPos = 0;
|
717
|
+
//Should the temp be deleted here?!
|
718
|
+
|
531
719
|
return Qnil;
|
532
720
|
}
|
533
721
|
|
@@ -540,32 +728,72 @@ static VALUE lsapi_reopen( int argc, VALUE *argv, VALUE self)
|
|
540
728
|
/* constant silence hack */
|
541
729
|
orig_verbose = (VALUE)ruby_verbose;
|
542
730
|
ruby_verbose = Qnil;
|
543
|
-
|
731
|
+
|
544
732
|
rb_define_global_const("STDERR", orig_stderr);
|
545
|
-
|
733
|
+
|
546
734
|
ruby_verbose = (VALUE)orig_verbose;
|
547
|
-
|
735
|
+
|
548
736
|
return rb_funcall2( orig_stderr, rb_intern( "reopen" ), argc, argv );
|
549
|
-
|
737
|
+
|
550
738
|
}
|
551
739
|
return self;
|
552
740
|
}
|
553
741
|
|
742
|
+
static void readMaxBodyBufLength()
|
743
|
+
{
|
744
|
+
int n;
|
745
|
+
const char *p = getenv( "LSAPI_MAX_BODYBUF_LENGTH" );
|
746
|
+
if ( p )
|
747
|
+
{
|
748
|
+
n = atoi( p );
|
749
|
+
if (n > 0)
|
750
|
+
{
|
751
|
+
if (strstr(p, "M") || strstr(p, "m"))
|
752
|
+
MAX_BODYBUF_LENGTH = n * 1024 * 1024;
|
753
|
+
else if (strstr(p, "K") || strstr(p, "k"))
|
754
|
+
MAX_BODYBUF_LENGTH = n * 1024;
|
755
|
+
else
|
756
|
+
MAX_BODYBUF_LENGTH = n;
|
757
|
+
}
|
758
|
+
}
|
759
|
+
}
|
554
760
|
|
761
|
+
static void readTempFileTemplate()
|
762
|
+
{
|
763
|
+
const char *p = getenv( "LSAPI_TEMPFILE" );
|
764
|
+
if (p == NULL || strlen(p) > 1024 - 7)
|
765
|
+
p = "/tmp/lsapi.XXXXXX";
|
766
|
+
|
767
|
+
strcpy(sTempFile, p);
|
768
|
+
if (strlen(p) <= 6 || strcmp(p + (strlen(p) - 6), "XXXXXX") != 0)
|
769
|
+
strcat(sTempFile, ".XXXXXX");
|
770
|
+
}
|
555
771
|
|
772
|
+
static void initBodyBuf()
|
773
|
+
{
|
774
|
+
s_body.bodyBuf = NULL;
|
775
|
+
s_body.bodyLen = -1;
|
776
|
+
s_body.bodyCurrentLen = 0;
|
777
|
+
s_body.curPos = 0;
|
778
|
+
}
|
556
779
|
void Init_lsapi()
|
557
780
|
{
|
558
|
-
VALUE remove_env;
|
559
781
|
VALUE orig_verbose;
|
560
782
|
char * p;
|
561
|
-
|
562
783
|
LSAPI_Init();
|
563
|
-
|
564
|
-
|
784
|
+
initBodyBuf();
|
785
|
+
|
786
|
+
readMaxBodyBufLength();
|
787
|
+
readTempFileTemplate();
|
788
|
+
|
789
|
+
#ifdef rb_thread_select
|
790
|
+
LSAPI_Init_Env_Parameters( rb_thread_select );
|
791
|
+
#else
|
565
792
|
LSAPI_Init_Env_Parameters( select );
|
566
|
-
|
793
|
+
#endif
|
794
|
+
|
567
795
|
s_pid = getpid();
|
568
|
-
|
796
|
+
|
569
797
|
p = getenv( "RAILS_ROOT" );
|
570
798
|
if ( p )
|
571
799
|
{
|
@@ -574,8 +802,8 @@ void Init_lsapi()
|
|
574
802
|
}
|
575
803
|
if ( p || getenv( "RAILS_ENV" ) )
|
576
804
|
s_fn_add_env = add_env_rails;
|
577
|
-
|
578
|
-
|
805
|
+
|
806
|
+
|
579
807
|
orig_stdin = rb_stdin;
|
580
808
|
orig_stdout = rb_stdout;
|
581
809
|
orig_stderr = rb_stderr;
|
@@ -587,20 +815,15 @@ void Init_lsapi()
|
|
587
815
|
|
588
816
|
/* tell the garbage collector it is a global variable, do not recycle it. */
|
589
817
|
rb_global_variable(&env_copy);
|
590
|
-
|
591
|
-
rb_hash_aset( env_copy,rb_tainted_str_new("GATEWAY_INTERFACE", 17),
|
592
|
-
rb_tainted_str_new("CGI/1.2", 7));
|
593
818
|
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
*/
|
598
|
-
|
819
|
+
rb_hash_aset( env_copy,rb_tainted_str_new("GATEWAY_Irewindable_input.rbNTERFACE", 17),
|
820
|
+
rb_tainted_str_new("CGI/1.2", 7));
|
821
|
+
|
599
822
|
rb_define_global_function("eval_string_wrap", lsapi_eval_string_wrap, 1);
|
600
|
-
|
823
|
+
|
601
824
|
cLSAPI = rb_define_class("LSAPI", rb_cObject);
|
602
825
|
rb_define_singleton_method(cLSAPI, "accept", lsapi_s_accept, 0);
|
603
|
-
|
826
|
+
|
604
827
|
rb_define_method(cLSAPI, "process", lsapi_process, 0 );
|
605
828
|
/* rb_define_method(cLSAPI, "initialize", lsapi_initialize, 0); */
|
606
829
|
rb_define_method(cLSAPI, "putc", lsapi_putc, 1);
|
@@ -613,11 +836,14 @@ void Init_lsapi()
|
|
613
836
|
rb_define_method(cLSAPI, "getc", lsapi_getc, 0);
|
614
837
|
/* rb_define_method(cLSAPI, "ungetc", lsapi_ungetc, 1); */
|
615
838
|
rb_define_method(cLSAPI, "gets", lsapi_gets, 0);
|
616
|
-
|
839
|
+
|
617
840
|
//TEST: adding readline function to make irb happy?
|
618
841
|
/*rb_define_method(cLSAPI, "readline", lsapi_gets, 0); */
|
619
|
-
|
842
|
+
|
620
843
|
rb_define_method(cLSAPI, "read", lsapi_read, -1);
|
844
|
+
rb_define_method(cLSAPI, "rewind", lsapi_rewind, 0);
|
845
|
+
rb_define_method(cLSAPI, "each", lsapi_each, 0);
|
846
|
+
|
621
847
|
rb_define_method(cLSAPI, "eof", lsapi_eof, 0);
|
622
848
|
rb_define_method(cLSAPI, "eof?", lsapi_eof, 0);
|
623
849
|
rb_define_method(cLSAPI, "close", lsapi_close, 0);
|
@@ -629,34 +855,34 @@ void Init_lsapi()
|
|
629
855
|
rb_define_method(cLSAPI, "sync=", lsapi_setsync, 1);
|
630
856
|
rb_define_method(cLSAPI, "reopen", lsapi_reopen, -1 );
|
631
857
|
|
632
|
-
|
858
|
+
|
633
859
|
s_req = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_req_data );
|
634
860
|
s_req_data->req = &g_req;
|
635
861
|
s_req_data->fn_write = LSAPI_Write_r;
|
636
862
|
rb_stdin = rb_stdout = s_req;
|
637
|
-
|
863
|
+
|
638
864
|
#if RUBY_VERSION_CODE < 180
|
639
865
|
rb_defout = s_req;
|
640
866
|
#endif
|
641
867
|
rb_global_variable(&s_req );
|
642
|
-
|
868
|
+
|
643
869
|
s_req_stderr = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_stderr_data );
|
644
870
|
s_stderr_data->req = &g_req;
|
645
871
|
s_stderr_data->fn_write = LSAPI_Write_Stderr_r;
|
646
872
|
rb_stderr = s_req_stderr;
|
647
873
|
rb_global_variable(&s_req_stderr );
|
648
|
-
|
874
|
+
|
649
875
|
/* constant silence hack */
|
650
876
|
orig_verbose = (VALUE)ruby_verbose;
|
651
877
|
ruby_verbose = Qnil;
|
652
|
-
|
878
|
+
|
653
879
|
lsapi_env = rb_hash_new();
|
654
880
|
clear_env();
|
655
881
|
/* redefine ENV using a hash table, should be faster than char **environment */
|
656
882
|
rb_define_global_const("ENV", lsapi_env);
|
657
883
|
|
658
884
|
rb_define_global_const("STDERR", rb_stderr);
|
659
|
-
|
885
|
+
|
660
886
|
ruby_verbose = (VALUE)orig_verbose;
|
661
887
|
|
662
888
|
return;
|