/* *---------------------------------------------------------------------- * * ReadParams -- * * Reads FastCGI name-value pairs from stream until EOF. Converts * each pair to name=value format and adds it to Params structure. * *---------------------------------------------------------------------- */ static int ReadParams(Params * paramsPtr, FCGX_Stream * stream) { int nameLen, valueLen; unsigned char lenBuff[3]; char *nameValue; while ((nameLen = FCGX_GetChar(stream)) != EOF) { /* * Read name length (one or four bytes) and value length * (one or four bytes) from stream. */ if ((nameLen & 0x80) != 0) { if (FCGX_GetStr((char *)&lenBuff[0], 3, stream) != 3) { SetError(stream, FCGX_PARAMS_ERROR); return -1; } nameLen = ((nameLen & 0x7f) << 24) + (lenBuff[0] << 16) + (lenBuff[1] << 8) + lenBuff[2]; } if ((valueLen = FCGX_GetChar(stream)) == EOF) { SetError(stream, FCGX_PARAMS_ERROR); return -1; } if ((valueLen & 0x80) != 0) { if (FCGX_GetStr((char *)&lenBuff[0], 3, stream) != 3) { SetError(stream, FCGX_PARAMS_ERROR); return -1; } valueLen = ((valueLen & 0x7f) << 24) + (lenBuff[0] << 16) + (lenBuff[1] << 8) + lenBuff[2]; } /* * nameLen and valueLen are now valid; read the name and value * from stream and construct a standard environment entry. */ nameValue = (char *)Malloc(nameLen + valueLen + 2); if (FCGX_GetStr(nameValue, nameLen, stream) != nameLen) { SetError(stream, FCGX_PARAMS_ERROR); free(nameValue); return -1; } *(nameValue + nameLen) = '='; if (FCGX_GetStr(nameValue + nameLen + 1, valueLen, stream) != valueLen) { SetError(stream, FCGX_PARAMS_ERROR); free(nameValue); return -1; } *(nameValue + nameLen + valueLen + 1) = '\0'; PutParam(paramsPtr, nameValue); } return 0; }
/* * get_range_query * Parses the GET|POST request and extracts the 'range query' * string. * Args: * - FCGX_Request * (of the thread) * - char * (location where the 'range query' is written) * Returns: * - O (expand) * - 1 (list) */ static int get_range_query(FCGX_Request *rq, char *query) { char *method = FCGX_GetParam("REQUEST_METHOD", rq->envp); char *script_name = FCGX_GetParam("SCRIPT_NAME", rq->envp); int list = -1; /* list or expand? */ char *decoded_url; /* accept only GET && POST */ if(strcmp(method, "GET") != 0 && strcmp(method, "POST") != 0) { invalid_request(rq, "401", "Only GET || POST Request_Method Allowed"); } else if (strcmp(method, "GET") == 0) { decoded_url = curl_unescape(FCGX_GetParam("QUERY_STRING", rq->envp), 0); strcpy(query, decoded_url); curl_free(decoded_url); } else if (strcmp(method, "POST") == 0) { /* TODO: i might have to loop this in while and do a strcat + realloc if i need to increase string length at runtime */ FCGX_GetStr(query, QUERY_STR_SIZE, rq->in); } /* we have two cases here * - /range/list?(.*) * - /range/expand?(.*) * SCRIPT_NAME == /range/list || /range/expand * QUERY_STRING == (.*) (in our case query has it) * strtok() for SCRIPT_NAME and decide which kind it is, * for QUERY_STRING is passed as is. */ if (strlen(query) == 0) { invalid_request(rq, "402", "No Query String Found"); return 0; } /* list ? */ list = strcmp(script_name, "/range/list") == 0 ? 1 : -1; /* if not list, but is expand */ if (list != 1 && strcmp(script_name, "/range/expand") == 0) list = 0; /* neither list nor expand */ if (list == -1) { invalid_request(rq, "403", "Expects /range/list?... or /range/expand?..."); return 0; } /* FCGX_FPrintF(rq->out, "Content-type: text/plain\r\n" "foo: bar\r\n" "\r\n"); FCGX_FPrintF(rq->out, "List (%d) Query: (%s) Script: (%s)\n", list, query, script_name); */ return list; }
static ssize_t fcgi_stream_read(void *handle, char *buf, size_t size) { FCGX_Stream *s; ssize_t bytes_read; s = handle; bytes_read = FCGX_GetStr(buf, size, s); return bytes_read; }
size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp) { int n; if(fp->stdio_stream) return fread(ptr, size, nmemb, fp->stdio_stream); else if(fp->fcgx_stream) { n = FCGX_GetStr((char *) ptr, size * nmemb, fp->fcgx_stream); return (n/size); } return EOF; }
int get_body_chunk(char *buf, int buflen) { int r = FCGX_GetStr(buf, buflen, fcgi_in); if(r>=0) { if(authed == AUTH_BODYCHECK) authed = AUTH_BODYCHECKING; if(authed == AUTH_BODYCHECKING && !sxi_sha1_update(body_ctx, buf, r)) { WARN("digest update failed"); authed = AUTH_NOTAUTH; return -1; } } else authed = AUTH_NOTAUTH; return r; }
static VALUE fcgi_stream_read(int argc, VALUE *argv, VALUE self) { VALUE num,str; FCGX_Stream *stream; char *buff; int n; if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } Data_Get_Struct(self, FCGX_Stream, stream); if (argc==0) { buff = ALLOC_N(char, 16384); n = FCGX_GetStr(buff, 16384, stream); CHECK_STREAM_ERROR(stream); if (n == 0) { free(buff); return Qnil; } str = rb_str_new(buff, n); OBJ_TAINT(str); while(!FCGX_HasSeenEOF(stream)) { n = FCGX_GetStr(buff, 16384, stream); CHECK_STREAM_ERROR(stream); if (n > 0) { rb_str_cat(str, buff, n); } else { free(buff); return Qnil; } } free(buff); return str; }
/* Returns the number of bytes read, or -1 on error. */ static int readContentData(HTTPRequest *req, void *buffer, int dataSize, int mustFill) { WOLog (WO_INFO, "data size: %d", dataSize ); //int n = fread(buffer, 1, dataSize, stdin); int n = FCGX_GetStr(buffer, dataSize, in); if (n != dataSize) { //int err = ferror(stdin); int err = FCGX_GetError(in); if (err) WOLog(WO_ERR,"Error getting content data: %s (%d)", strerror(errno), err); } /* *((char*)buffer+dataSize) = '\0'; WOLog ( WO_INFO, "buffer: %s", (char *)buffer );*/ return n == dataSize ? n : -1; }
/* *---------------------------------------------------------------------- * * FCGI_fread, FCGI_fwrite -- * * Wrappers for functions defined in H&S Section 15.13 * *---------------------------------------------------------------------- */ size_t FCGI_fread(void *ptr, size_t size, size_t nmemb, FCGI_FILE *fp) { int n; if(fp->stdio_stream) return fread(ptr, size, nmemb, fp->stdio_stream); else if(fp->fcgx_stream) { if((size * nmemb) == 0) { return 0; } ASSERT(size * nmemb < (size_t)INT_MAX); n = FCGX_GetStr((char *) ptr, (int)(size * nmemb), fp->fcgx_stream); ASSERT(n >= 0); return ((size_t)n/size); } return (size_t)EOF; }
/* *---------------------------------------------------------------------- * * ProcessBeginRecord -- * * Reads an FCGI_BEGIN_REQUEST record. * * Results: * BEGIN_RECORD for normal return. FCGX_PROTOCOL_ERROR for * protocol error. SKIP for attempt to multiplex * connection. -1 for error from write (errno in stream). * * Side effects: * In case of BEGIN_RECORD return, stores requestId, role, * keepConnection values, and sets isBeginProcessed = TRUE. * *---------------------------------------------------------------------- */ static int ProcessBeginRecord(int requestId, FCGX_Stream * stream) { FCGX_Stream_Data *data = (FCGX_Stream_Data *) stream->data; FCGI_BeginRequestBody body; if (requestId == 0 || data->contentLen != sizeof(body)) { return FCGX_PROTOCOL_ERROR; } if (data->reqDataPtr->isBeginProcessed) { /* * The Web server is multiplexing the connection. This library * doesn't know how to handle multiplexing, so respond with * FCGI_END_REQUEST{protocolStatus = FCGI_CANT_MPX_CONN} */ FCGI_EndRequestRecord endRequestRecord; endRequestRecord.header = MakeHeader(FCGI_END_REQUEST, requestId, sizeof(endRequestRecord.body), 0); endRequestRecord.body = MakeEndRequestBody(0, FCGI_CANT_MPX_CONN); if (write_it_all(data->reqDataPtr->ipcFd, (char *)&endRequestRecord, sizeof(endRequestRecord)) < 0) { SetError(stream, OS_Errno); return -1; } return SKIP; } /* * Accept this new request. Read the record body. */ data->reqDataPtr->requestId = requestId; if (FCGX_GetStr((char *)&body, sizeof(body), stream) != sizeof(body)) { return FCGX_PROTOCOL_ERROR; } data->reqDataPtr->keepConnection = (body.flags & FCGI_KEEP_CONN); data->reqDataPtr->role = (body.roleB1 << 8) + body.roleB0; data->reqDataPtr->isBeginProcessed = TRUE; return BEGIN_RECORD; }
int bridge_request_getinput(bridge_request_t *self, char **data) { char *contentLength; char *buffer; int len = 0; if ((contentLength = FCGX_GetParam("CONTENT_LENGTH", self->request.envp)) != 0) len = strtol(contentLength, NULL, 10); if (len <= 0) return EINVAL; if ((buffer = malloc((size_t)len+1)) == 0) { FCGX_PutS("out of memory!", self->request.err); return ENOMEM; } if (FCGX_GetStr(buffer, len, self->request.in) != len) { FCGX_PutS("Got less data than expected.", self->request.err); return EINVAL; } buffer[len] = '\0'; *data = buffer; return 0; }
std::size_t fastcgi::read(char *buffer, std::size_t size) { assert(accepted()); return static_cast<std::size_t>(FCGX_GetStr(buffer, size, req_.get()->in)); }
int lsp::read_request_data(lua_State *L) { FCGX_Request* r = (FCGX_Request*)luaL_lsp_get_io_ctx(L); const char* p=FCGX_GetParam("CONTENT_LENGTH", r->envp); int content_length = p? atoi(p) : -1; if(content_length < 0) return 411;//HTTP_LENGTH_REQUIRED; // TODO: for max post? if(content_length > 4096) return 400;//HTTP_BAD_REQUEST; int retval = 0; luaL_Buffer buf; luaL_buffinit(L,&buf); //if(ap_should_client_block(apr)) { char *tmp = new char[1024]; int len = 0; while(len<content_length) { int n = content_length - len; //n = ap_get_client_block(apr,tmp,n>sizeof(tmp)?sizeof(tmp):n); n = FCGX_GetStr(tmp, n > 1024 ? 1024 : n, r->in); if(n <= 0) break; len += n; luaL_addlstring(&buf,tmp,n); } if(len!=content_length) retval = -1;//HTTP_REQUEST_TIME_OUT; delete[] tmp; } const char* content_type = FCGX_GetParam("CONTENT_TYPE", r->envp); int n = lua_gettop(L); if(content_type && !strcmp(content_type,"application/x-www-form-urlencoded")) { lua_getglobal(L,"args_decode"); luaL_pushresult(&buf); if(lua_isfunction(L,-2) && !lua_pcall(L,1,1,0)) lua_setglobal(L,"args_post"); } else { lua_getfield(L,LUA_GLOBALSINDEX,"env"); luaL_pushresult(&buf); if(lua_istable(L,-2)) lua_setfield(L,-2,"content"); } lua_pop(L,lua_gettop(L)-n); return retval; }
static PyObject * fcgi_Stream_read(fcgi_Stream *self, PyObject *args) { FCGX_Stream *s; long bytesrequested = -1; size_t bytesread, buffersize, chunksize; PyObject *v; fcgi_Stream_Check(); s = *(self->s); if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested)) return NULL; if (bytesrequested == 0) return PyString_FromString(""); if (bytesrequested < 0) buffersize = new_buffersize((size_t)0); else buffersize = bytesrequested; if (buffersize > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "requested number of bytes is more than a Python string can hold"); return NULL; } v = PyString_FromStringAndSize((char *)NULL, buffersize); if (v == NULL) return NULL; bytesread = 0; for (;;) { Py_BEGIN_ALLOW_THREADS chunksize = FCGX_GetStr(BUF(v) + bytesread, buffersize - bytesread, s); Py_END_ALLOW_THREADS if (chunksize == 0) { if (FCGX_HasSeenEOF(s)) break; PyErr_SetString(PyExc_IOError, "Read failed"); Py_DECREF(v); return NULL; } bytesread += chunksize; if (bytesread < buffersize) { break; } if (bytesrequested < 0) { buffersize = new_buffersize(buffersize); if (_PyString_Resize(&v, buffersize) < 0) return NULL; } else { /* Got what was requested. */ break; } } if (bytesread != buffersize) _PyString_Resize(&v, bytesread); return v; }
int stone_request_init(ngx_pool_t *pool, stone_request_t *req, struct FCGX_Request *fcgx ){ char *contentData, *temp; uint contentLen; //getenv( "CONTENT_TYPE" ); req->env->ContentType = FCGX_GetParam("CONTENT_TYPE",fcgx->envp); //getenv( "CONTENT_LENGTH" ); char *lpszContentLenght = FCGX_GetParam("CONTENT_LENGTH",fcgx->envp); req->env->ContentLength = strtol( (lpszContentLenght != 0 ? lpszContentLenght : "0"), 0, 10 ); contentLen = req->env->ContentLength; // Get boundary data if available if( req->env->ContentType != 0 ) { char *lpszTemp = index( req->env->ContentType, ';' ); if( lpszTemp != 0 ) { *lpszTemp = 0; if( strncasecmp( lpszTemp + 2, "boundary=", 9 ) == 0 ) { req->env->Boundary = ngx_palloc( pool, STONE_BOUNDARY_LEN_MAX ); ngx_strlcpy( req->env->Boundary, lpszTemp + 11, STONE_BOUNDARY_LEN_MAX ); req->env->BoundaryLen = strlen( req->env->Boundary ); } } } // Store query data //main_store_data( pool, req->get, getenv( "QUERY_STRING" ) ); main_store_data( pool, req->get, FCGX_GetParam("QUERY_STRING",fcgx->envp) ); // Get more data if available (from standart input) if( req->env->ContentType != 0 && req->env->ContentLength > 0 ) { // Check lenght if( req->env->ContentLength > STONE_UPLOAD_LEN_MAX ) { //log_printf( threadInfo, LOG_WARNING, "Main::Loop: Content lenght is too big (%u > %u)", req->env->ContentLength, NNCMS_UPLOAD_LEN_MAX ); } else { // Retreive data contentData = ngx_palloc( pool, req->env->ContentLength + 1 ); if( contentData == NULL ) { //log_printf( threadInfo, LOG_ALERT, "Main::Loop: Unable to allocate %u bytes for content (max: %u)", req->env->ContentLength, NNCMS_UPLOAD_LEN_MAX ); } else { //int nResult = FCGI_gets( contentData, req->env->ContentLength, threadInfo->fcgi_request->in ); int nResult = FCGX_GetStr( contentData, req->env->ContentLength, fcgx->in ); contentData[nResult] = 0; /* temp = contentData; do{ *temp++ = getchar(); }while( --contentLen != 0); //contentData[nResult] = 0; if( strlen( contentData ) < req->env->ContentLength ){ //log_printf( threadInfo, LOG_WARNING, "Main::Loop: Received %u, required %u. Not enough bytes received on standard input", nResult, req->env->ContentLength ); } */ if ( nResult < req->env->ContentLength ){ } if( strcmp( req->env->ContentType, "application/x-www-form-urlencoded" ) == 0 ) main_store_data( pool, req->post, contentData ); // RFC1867: Form-based File Upload in HTML if( strcmp( req->env->ContentType, "multipart/form-data" ) == 0 ) main_store_data_rfc1867( pool, req, contentData ); } } } // And even more data (from cookies) //main_store_data( pool, req->cookie, getenv( "HTTP_COOKIE" ) ); main_store_data( pool, req->cookie, FCGX_GetParam("HTTP_COOKIE",fcgx->envp) ); return 0; }
int FastcgiRequest::read(char *buf, int size) { return FCGX_GetStr(buf, size, fcgiRequest_.in); }
size_t fcgi_stream::read(char *d,size_t len) { return FCGX_GetStr(d,len,request.in); };
static int nlua_webio(FCGX_Request *request, char *arg, int id) { char *method = FCGX_GetParam("REQUEST_METHOD", request->envp); /* If it's a POST, then write to Lua's stdin */ if (!strcmp(method, "POST")) { char bfr[8192]; int bytes_read, bytes_written; int timeout = DEFAULT_WEBIO_TIMEOUT; if (*arg) { timeout = strtoul(arg, NULL, 0); if (timeout < 0 || timeout > MAX_WEBIO_TIMEOUT) timeout = DEFAULT_WEBIO_TIMEOUT; } FCGX_FPrintF(request->out, "Content-Type: text/html\r\n\r\n"); while ( (bytes_read = FCGX_GetStr(bfr, sizeof(bfr), request->in)) > 0) { char *left = bfr; /* if (enc && (!strcmp(enc, "hex") || !strcmp(enc, "hexecho"))) { char *s = bfr; int input=0, output=0; while (input < bytes_read) { s[output] = (tohex(s[input++])<<4)&0xf0; if (s[input]) s[output] |= tohex(s[input++])&0x0f; output++; } s[output] = '\0'; bytes_read /= 2; } if (!strcmp(enc, "hexecho") || !strcmp(enc, "echo")) FCGX_PutStr(bfr, bytes_read, request->out); */ while (bytes_read > 0) { bytes_written = write(nlua_states[id].in_fd, left, bytes_read); if (bytes_written < 0) { perror("Unable to write file"); return make_error(request, "Unable to write file", errno); } left += bytes_written; bytes_read -= bytes_written; } } } /* If it's not a POST, then read from stdout / stderr */ else if (!strcmp(method, "GET")) { fd_set s; struct timeval t = {DEFAULT_WEBIO_TIMEOUT, 20000}; int i; int read_fd, handle_id; int max; FD_ZERO(&s); FD_SET(nlua_states[id].out_fd, &s); max = nlua_states[id].out_fd; FD_SET(nlua_states[id].err_fd, &s); if (max < nlua_states[id].err_fd) max = nlua_states[id].err_fd; FD_SET(nlua_states[id].out_ctrl, &s); if (max < nlua_states[id].out_ctrl) max = nlua_states[id].out_ctrl; i = select(max+1, &s, NULL, NULL, &t); if (i > 0) { char bfr[16384]; if (FD_ISSET(nlua_states[id].out_fd, &s)) { read_fd = nlua_states[id].out_fd; handle_id = 1; } else if (FD_ISSET(nlua_states[id].err_fd, &s)) { read_fd = nlua_states[id].err_fd; handle_id = 2; } else { read_fd = nlua_states[id].out_ctrl; handle_id = 3; } i = read(read_fd, bfr, sizeof(bfr)); if (i == -1 && (errno == EINTR || errno == EAGAIN)) { /* Interrupted, but try again */ FCGX_FPrintF(request->out, "Content-Type: text/html\r\n" "X-Handle: %d\r\n" "\r\n", handle_id); return 0; } else if (i == -1) { /* Unrecoverable error */ kill(nlua_states[id].pid, SIGKILL); kill(nlua_states[id].pid, SIGTERM); close(nlua_states[id].out_fd); close(nlua_states[id].err_fd); close(nlua_states[id].out_ctrl); nlua_states[id].out_fd = -1; nlua_states[id].err_fd = -1; nlua_states[id].out_ctrl = -1; nlua_pool_status[id] = 0; return make_error(request, "Unable to read from handle", errno); } /* The handle control fd requires special care */ else if (handle_id == 3) return handle_ctrl(request, bfr, i); else if (i == 0) { /* Connection closed */ close(nlua_states[id].out_fd); close(nlua_states[id].err_fd); close(nlua_states[id].out_ctrl); nlua_states[id].out_fd = -1; nlua_states[id].err_fd = -1; nlua_states[id].out_ctrl = -1; nlua_pool_status[id] = 0; FCGX_FPrintF(request->out, "Content-Type: text/plain\r\n" "Status: 204\r\n" "X-Handle: %d\r\n" "\r\n", handle_id); } else { FCGX_FPrintF(request->out, "Content-Type: text/plain\r\n" "X-Handle: %d\r\n" "\r\n", handle_id); FCGX_PutStr(bfr, i, request->out); } } else if (!i || (i == -1 && (errno == EINTR || errno == EAGAIN))) { /* No data to read */ FCGX_FPrintF(request->out, "Content-Type: text/html\r\n\r\n"); } else { /* Error occurred */ kill(nlua_states[id].pid, SIGKILL); kill(nlua_states[id].pid, SIGTERM); close(nlua_states[id].out_fd); close(nlua_states[id].err_fd); close(nlua_states[id].out_ctrl); nlua_states[id].out_fd = -1; nlua_states[id].err_fd = -1; nlua_states[id].out_ctrl = -1; nlua_pool_status[id] = 0; return make_error(request, "Unable to read from stdout", errno); } } else { return make_error(request, "Unrecognized http method", 0); } return 0; }
static int io_fcgi_read(void *context, void *buffer, int size) { FCGX_Request *request = (FCGX_Request *)context; return FCGX_GetStr((char *)buffer, size, request->in); }
if (n > 0) { rb_str_cat(str, buff, n); } else { free(buff); return Qnil; } } free(buff); return str; } num = argv[0]; n = NUM2INT(num); buff = ALLOC_N(char, n); n = FCGX_GetStr(buff, n, stream); CHECK_STREAM_ERROR(stream); if (n > 0) { str = rb_str_new(buff, n); OBJ_TAINT(str); free(buff); return str; } else { free(buff); return Qnil; } } static VALUE fcgi_stream_eof(VALUE self) {
Q_LONG FastCgiDevice::readBlock( char *data, Q_ULONG maxlen ) { return FCGX_GetStr( data, maxlen, m_stream ); }
int HttpRequestX::ParseUrlQuery(){ if(m_initialized){ return m_param_count; } m_initialized = true; char * content_type = GetContentType(); if(content_type != NULL && strncmp(content_type, "multipart", 10) == 0) { return 0; // todo: support multipart/form-data } char * param_buffer = NULL; if(GetMethod() == HTTP_METHOD_POST) { unsigned long content_len; char * content_len_str = GetEnv("CONTENT_LENGTH"); sscanf(content_len_str,"%ld",&content_len); content_len += 1; if(content_len > MAX_CONTENT_LENGTH) { // TODO 检查content_len是否超出最大 return -2; } param_buffer = (char*) malloc (sizeof(char)*content_len); bzero(param_buffer, sizeof(char)*content_len); int read_num = FCGX_GetStr(param_buffer, content_len, request_.in); if (read_num < 0) { return -1; } } else if(GetMethod() == HTTP_METHOD_GET) { char * query_string = GetEnv("QUERY_STRING"); param_buffer = strdup(query_string); } else { //TODO: 不支持的方法 return -1; } char *query = param_buffer; int len = strlen(param_buffer); int num = 0; // 参数个数 char * q = query; if(q == NULL) { free(param_buffer); return 0; } while(strsep(&q, "&") != NULL){ num ++; } if(num == 0) { free(param_buffer); return 0; } int size = (num)*sizeof(param_pair_t); if(m_params == NULL){ m_params = (param_pair_t*)malloc(size); } else if(m_param_array_size<num){ // 与上次请求的参数个数相比较,如果需要更多内存,则重新分配 m_params = (param_pair_t*)realloc(m_params, size); m_param_array_size = num; } if(m_params == NULL) { free(param_buffer); return -1; } memset(m_params, 0, size); param_pair_t * my_param = m_params; char * name; char * value; for (q = query; q < (query + len);){ name = q; value = q; q += strlen(q)+1; // 跳到下一个参数 name = strsep(&value, "="); // 分解当前参数 my_param->name = url_decode2(strdup(name)); my_param->value = url_decode2(strdup(value==NULL ? "" : value) ); my_param++; } free(param_buffer); return num; }