ruby-lsapi 4.2 → 4.3
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.
- 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;
|