int papi_read_body (request_rec *r, char **buffer) { char buf[MAX_SIZE+1]; size_t bytes, count = 0; *buffer = apr_pstrdup (r->pool, ""); if (ap_setup_client_block (r, REQUEST_CHUNKED_DECHUNK) != OK) { APACHE_LOG (APLOG_ERR, "Bad request body!"); return HTTP_BAD_REQUEST; } if (ap_should_client_block (r)) { for (bytes = ap_get_client_block (r, buf, MAX_SIZE); bytes > 0; bytes = ap_get_client_block (r, buf, MAX_SIZE)) { (*buffer)[bytes-1] = '\0'; *buffer = apr_pstrcat (r->pool, *buffer, buf, NULL); count += bytes; } } else { APACHE_LOG (APLOG_WARNING, "No request body."); } (*buffer)[count-1] = '\0'; return OK; }
/* * Send request body (if any) */ static int send_request_body(request_rec *r, proxy_conn_rec *conn) { if (ap_should_client_block(r)) { char *buf = apr_palloc(r->pool, AP_IOBUFSIZE); int status; apr_size_t readlen; readlen = ap_get_client_block(r, buf, AP_IOBUFSIZE); while (readlen > 0) { status = sendall(conn, buf, readlen, r); if (status != OK) { return HTTP_SERVICE_UNAVAILABLE; } readlen = ap_get_client_block(r, buf, AP_IOBUFSIZE); } if (readlen == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: " PROXY_FUNCTION ": receiving request body " "failed"); return HTTP_INTERNAL_SERVER_ERROR; } } return OK; }
static char* cwx_read_post(request_rec *r){ char *data=0; const char *type; char buf[4096]; int rc = OK; if(r->method_number != M_POST) return 0; type = (char*)apr_table_get(r->headers_in, "Content-Type"); if(strcasecmp(type, "application/x-www-form-urlencoded") != 0) return 0; if (ap_should_client_block(r)) { int rsize, len_read, rpos=0; long length = r->remaining; data = (char*)apr_pcalloc(r->pool, length + 1); while ((len_read = ap_get_client_block(r, buf, sizeof(buf))) > 0) { if (rpos + len_read > length) { rsize = length - rpos; }else { rsize = len_read; } memcpy(data + rpos, buf, rsize); rpos += rsize; } data[rpos] = 0x00; } return data; }
/** * Use this function to read the body from request_rec * Pointer to data will be set to body * Returns -1 if failed */ static int read_body(request_rec *r, char **body) { *body = NULL; int ret = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR); if(OK == ret && ap_should_client_block(r)) { char* buffer = apr_pcalloc(r->pool, BLOCKSIZE); int len; char *data = apr_pcalloc(r->pool, 1); int d_size = 0; data[0] = '\0'; // Read body while((len=ap_get_client_block(r, buffer, BLOCKSIZE)) > 0) { char *tmp; // there is no apr_realloc tmp = apr_pcalloc(r->pool, d_size + len + 1); memcpy(tmp, data, d_size + 1); data = tmp; memcpy(&(data[d_size]), buffer, len); d_size += len; data[d_size] = '\0'; } if (len == -1) { return -1; } *body = data; ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "requrest_rec body[%s]", data); return 0; } return -1; }
static char* mapserver_read_post_data (request_rec *r) { int status; int size; long blen, rsize, rpos = 0; char *buffer = NULL; char buf [512]; if ((status = ap_setup_client_block (r, REQUEST_CHUNKED_ERROR)) != OK) return NULL; if (!ap_should_client_block (r)) return NULL; buffer = (char*) apr_palloc (r->pool, r->remaining + 1); size = r->remaining; buffer [size] = '\0'; if (!buffer) return NULL; while ((blen = ap_get_client_block (r, buf, sizeof (buf))) > 0) { if (rpos + blen > size) { rsize = blen - rpos; } else { rsize = blen; } memcpy ((char*) buffer + rpos, buf, rsize); rpos += rsize; } return buffer; }
static void discard_data(request_rec *r) { #ifdef APACHE2 (void) ap_discard_request_body(r); #else /* * This is taken from ap_discard_request_body(). The reason we can't * just use it in Apache 1.3 is that it does various timeout things we * don't want it to do. Apache 2.0 doesn't do that, so we can safely * use the normal function. */ if (r->read_chunked || r->remaining > 0) { char dumpbuf[HUGE_STRING_LEN]; int i; do { i = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN); #ifdef DEBUG dump_buffer(stderr, "discarded", dumpbuf, i); #endif } while (i > 0); } #endif }
const char * ws::apache2request::body() { if(_body != 0) { return _body; } if(ap_setup_client_block(__rr, REQUEST_CHUNKED_ERROR)) { return _body; } if(!ap_should_client_block(__rr)) { return _body; } apr_off_t length = __rr->remaining; apr_off_t len_read, rsize, rpos = 0; char argsbuffer[HUGE_STRING_LEN]; _body = (char*) apr_pcalloc(__rr->pool, (apr_size_t) (length + 1)); while((len_read = ap_get_client_block(__rr, argsbuffer, sizeof(argsbuffer))) > 0) { if((rpos + len_read) > length) { rsize = length - rpos; } else { rsize = len_read; } memcpy(_body + rpos, argsbuffer, (size_t) rsize); rpos += rsize; } return _body; }
static int util_read(request_rec *r, char **rbuf, apr_off_t *size) { int rc = OK; *size = 0; if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { return (rc); } if (ap_should_client_block(r)) { char argsbuffer[WEBGFARM_BUFFER_SIZE]; apr_off_t rsize, len_read, rpos = 0; apr_off_t length = r->remaining; *rbuf = (char *) apr_pcalloc(r->pool, (apr_size_t) (length + 1)); *size = length; while ((len_read = ap_get_client_block(r, argsbuffer, sizeof (argsbuffer))) > 0) { if ((rpos + len_read) > length) { rsize = length - rpos; } else { rsize = len_read; } memcpy((char *) *rbuf + rpos, argsbuffer, (size_t) rsize); rpos += rsize; } } return (rc); }
/** * Read s bytes into buffer b from request r * @param void * b a pre-allocated buffer * @param size_t s the amount of bytes to read * @param request_rec r The * @return int the amount of bytes read or -1 in case of an error **/ int mod_parrot_read(void * b, size_t s, request_rec * r) { apr_off_t count = r->read_length; if (ap_get_client_block(r, b, s) > 0) { return r->read_length - count; } return -1; }
/** * gets content if this is notification. */ static int content_read(request_rec *r, char **rbuf) { int rc; int rsize, len_read, rpos = 0; if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) { return -1; } if (ap_should_client_block(r)) { char argsbuffer[HUGE_STRING_LEN]; long length = r->remaining; *rbuf = ap_pcalloc(r->pool, length+1); ap_hard_timeout("content_read", r); while ((len_read = ap_get_client_block(r, argsbuffer, sizeof(argsbuffer))) > 0) { ap_reset_timeout(r); if ((rpos + len_read) > length) { rsize = length -rpos; } else { rsize = len_read; } memcpy((char*) *rbuf + rpos, argsbuffer, rsize); rpos = rpos + rsize; } ap_kill_timeout(r); } am_web_log_debug("in content_read: rpos=%d", rpos); return rpos; }
/** * handles a client request */ static int write_request(stream_t *s, request_rec *r, config_t *config, cluster_t *cluster, int *keepalive, int session_index, int backup_index, char *ip, char *session_id) { int len; int code; int write_length; time_t new_time; time_t start_time = r->request_time; hmux_start_channel(s, 1); write_env(s, r, session_id); write_headers(s, r); write_added_headers(s, r); /* read post data */ if (ap_should_client_block(r)) { char buf[BUF_LENGTH]; int ack_size = s->cluster_srun->srun->send_buffer_size; int send_length = 0; while ((len = ap_get_client_block(r, buf, BUF_LENGTH)) > 0) { /* ap_reset_timeout(r); */ cse_write_packet(s, HMUX_DATA, buf, len); send_length += len; if (ack_size <= send_length) { send_length = 0; cse_write_byte(s, HMUX_YIELD); code = send_data(s, r, HMUX_ACK, keepalive); if (code < 0 || code == HMUX_QUIT || code == HMUX_EXIT) break; } } } cse_write_byte(s, HMUX_QUIT); code = send_data(s, r, HMUX_QUIT, keepalive); if (code >= 0 || s->sent_data) return code; write_length = s->write_length; if (cse_open_connection(s, cluster, session_index, backup_index, r->request_time, r->pool)) { s->write_length = write_length; LOG(("retry connection %d\n", s->socket)); return send_data(s, r, HMUX_QUIT, keepalive); } else { return HTTP_SERVICE_UNAVAILABLE; } }
static void fill_buffer( mcontext *c, value buf, int *len ) { int pos = *len; while( pos < BUFSIZE ) { int k = ap_get_client_block(c->r,val_string(buf)+pos,BUFSIZE-pos); if( k == 0 ) break; pos += k; } *len = pos; }
static int do_stream_data( void *_c, char *buf, int size ) { mcontext *c = (mcontext*)_c; // startup if( size == 0 ) { if( !ap_should_client_block(c->r) ) return -1; c->need_discard = true; return 0; } return ap_get_client_block(c->r,buf,size); }
CAMLprim value netcgi2_apache_request_get_client_block_buffered(value rv, value bufv, value ofsv, value lenv) { CAMLparam4(rv, bufv, ofsv, lenv); request_rec *r = Request_rec_val(rv); int ofs = Int_val(ofsv); int len = Int_val(lenv); int i; i = ap_get_client_block (r, String_val(bufv) + ofs, len); /* Error dealt with on the Caml side. */ CAMLreturn(Val_int(i)); }
static POSTDATA_T* SmartHome_handler_get_post_data(request_rec *r) { int ret = 0; int pos = 0; ret = ap_setup_client_block(r,REQUEST_CHUNKED_ERROR); printf("request_rec->ap_setup_client_block() = %d\r\n",ret); printf("request_rec->ap_get_client_block()\r\n"); pos = 0; while((ret = ap_get_client_block(r,sys.post_data.data+pos,sizeof(ap_get_client_block)))>0){ pos+=ret; } sys.post_data.len = pos; return &sys.post_data; }
static mrb_value ap_mrb_get_request_body(mrb_state *mrb, mrb_value str) { char *val; int len; request_rec *r = ap_mrb_get_request(); if (r->method_number == M_POST) { ap_setup_client_block(r, REQUEST_CHUNKED_ERROR); len = r->remaining; val = apr_pcalloc(r->pool, len); ap_should_client_block(r); ap_get_client_block(r, val, len); return mrb_str_new(mrb, val, len); } return mrb_nil_value(); }
/** * handles a client request */ static int write_request(stream_t *s, request_rec *r, config_t *config, int session_index, int backup_index) { int len; int code = -1; write_env(s, r); write_headers(s, r); write_added_headers(s, r); /* read post data */ if (ap_should_client_block(r)) { char buf[BUF_LENGTH]; int ack_size = s->cluster_srun->srun->send_buffer_size; int send_length = 0; while ((len = ap_get_client_block(r, buf, BUF_LENGTH)) > 0) { LOG(("%s:%d:write-request(): w-D %d\n", __FILE__, __LINE__, len)); if (ack_size <= send_length + len && send_length > 0) { LOG(("%s:%d:write-request(): w-Y send_length=%d ack_size=%d\n", __FILE__, __LINE__, send_length, ack_size)); send_length = 0; cse_write_byte(s, HMUX_YIELD); code = send_data(s, r); if (code != HMUX_ACK) break; } cse_write_packet(s, HMUX_DATA, buf, len); send_length += len; } } LOG(("%s:%d:write-request(): w-Q\n", __FILE__, __LINE__)); cse_write_byte(s, HMUX_QUIT); code = send_data(s, r); LOG(("%s:%d:write_request(): return code %c\n", __FILE__, __LINE__, code)); return code; }
static void readPostData(request_rec* r) { int rc; if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) { ap_rprintf(r, "readPostData\trc\t[%d]<br>", rc); } else { if (ap_should_client_block(r)) { char data[HUGE_STRING_LEN]; int rsize, len_read, rpos=0; long length = r->remaining; while ((len_read = ap_get_client_block(r, data, sizeof(data))) > 0) { ap_rprintf(r, "Read Data : <br>[%s]<br>", data); } } else { ap_rprintf(r, "readPostData\t[NULL]<br>"); } } }
void ssl_io_suck(request_rec *r, SSL *ssl) { int rc; int len; char *buf; int buflen; char c; int sucked; if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) == OK) { if (ap_should_client_block(r)) { /* read client request block through Apache API */ buflen = HUGE_STRING_LEN; buf = ap_palloc(r->pool, buflen); ap_hard_timeout("SSL I/O request body pre-sucking", r); sucked = 0; ssl_io_suck_start(r); while ((len = ap_get_client_block(r, buf, buflen)) > 0) { ssl_io_suck_record(r, buf, len); sucked += len; ap_reset_timeout(r); } ssl_io_suck_end(r); ap_kill_timeout(r); /* suck trailing data (usually CR LF) which is still in the Apache BUFF layer */ ap_hard_timeout("SSL I/O request trailing data pre-sucking", r); while (ap_bpeekc(r->connection->client) != EOF) { c = ap_bgetc(r->connection->client); ssl_io_suck_record(r, &c, 1); sucked++; } ap_kill_timeout(r); ssl_log(r->server, SSL_LOG_TRACE, "I/O: sucked %d bytes of input data from SSL/TLS I/O layer " "for delayed injection into Apache I/O layer", sucked); } } return; }
/* ** Binding to ap_get_client_block. ** Uses the request_rec defined as an upvalue. ** Receives a number of bytes to read. ** Returns a string or nil if EOS. */ static int req_get_client_block (lua_State *L) { request_rec *r = CHECK_REQUEST_OBJECT(1); char buffer[ML_POST_BUFFER_SIZE + 1]; int bytesleft = luaL_optint (L, 2, ML_POST_BUFFER_SIZE); int status, n; int count = 0; if (bytesleft < 0) { luaL_error (L, "block size must be positive"); return 0; } while (bytesleft) { n = (bytesleft > ML_POST_BUFFER_SIZE) ? ML_POST_BUFFER_SIZE : bytesleft; status = ap_get_client_block (r, buffer, n); if (status == 0) /* end-of-body */ { if (r->remaining > 0) continue; /* still has something to read */ else break; /* end-of-stream */ } else if (status == -1) /* error or premature chunk end */ { lua_pushnil (L); lua_pushstring (L, "error getting client block"); return 2; } else { bytesleft -= status; lua_pushlstring (L, buffer, status); count++; } } /* is this necessary? */ if (count) lua_concat (L, count); else lua_pushnil (L); return 1; }
static int read_chars (lua_State *L, request_rec* r, size_t n) { size_t len; char tmpbuf[HUGE_STRING_LEN]; len = HUGE_STRING_LEN; /* try to read that much each time */ if (len > n) len = n; if ( (len = ap_get_client_block(r, tmpbuf, len)) > 0) { lua_pushlstring(L, tmpbuf, len); return 1; } else ap_discard_request_body(r); return 0; }
int request_parser::read_body(char*& rbuf, std::size_t& rbufLen) const { /*~~~~~~~~*/ int rc = OK; /*~~~~~~~~*/ if((rc = ap_setup_client_block(m_r, REQUEST_CHUNKED_ERROR))) { return(rc); } if(ap_should_client_block(m_r)) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ char argsbuffer[HUGE_STRING_LEN]; apr_off_t rsize, len_read, rpos = 0; apr_off_t length = m_r->remaining; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ rbuf = static_cast<char*>(apr_pcalloc(m_r->pool, (apr_size_t) (length + 1))); rbufLen = length; // We will not read body greater than limit if (static_cast<grader::request_parser::size_type>(length) > grader::request_parser::MAX_BODY_LENGTH) return (HTTP_REQUEST_ENTITY_TOO_LARGE); while((len_read = ap_get_client_block(m_r, argsbuffer, sizeof(argsbuffer))) > 0) { if((rpos + len_read) > length) { rsize = length - rpos; } else { rsize = len_read; } memcpy(rbuf + rpos, argsbuffer, (size_t) rsize); rpos += rsize; } } return(rc); }
static int util_read(ApacheRequest *req, const char **rbuf) { request_rec *r = req->r; int rc = OK; if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { return rc; } if (ap_should_client_block(r)) { char buff[HUGE_STRING_LEN]; int rsize, len_read, rpos=0; long length = r->remaining; if (length > req->post_max && req->post_max > 0) { ap_log_rerror(REQ_ERROR, "[libapreq] entity too large (%d, max=%d)", (int)length, req->post_max); return HTTP_REQUEST_ENTITY_TOO_LARGE; } *rbuf = ap_pcalloc(r->pool, length + 1); ap_hard_timeout("[libapreq] util_read", r); while ((len_read = ap_get_client_block(r, buff, sizeof(buff))) > 0) { if ((rpos + len_read) > length) { rsize = length - rpos; } else { rsize = len_read; } memcpy((char*)*rbuf + rpos, buff, rsize); rpos += rsize; } ap_kill_timeout(r); } return rc; }
static int wrap_read (void *data, char *buf, size_t len) { WRAPPER_DATA *wrap = (WRAPPER_DATA *)data; int ret; int x = 0; #if ECS_DEBUG>1 fprintf (stderr, "wrap_read (%s, %d)\n", buf, len); #endif do { ret = ap_get_client_block(wrap->r, buf + x, len - x); if (ret <= 0) break; x += ret; } while (x < len); #if ECS_DEBUG>1 fprintf (stderr, "done ap_get_client_block\n"); #endif if (ret < 0) return ret; return x; }
CAMLprim value netcgi2_apache_request_get_client_block (value rv) { CAMLparam1 (rv); CAMLlocal1 (str); request_rec *r = Request_rec_val (rv); const int huge_string_len = 8192; /* Same as Apache's HUGE_STRING_LEN. */ char buffer [huge_string_len]; int i; str = Val_unit; i = ap_get_client_block (r, buffer, huge_string_len); if (i == -1) { /* FIXME: It seems there is now way to get more info about the error. */ caml_failwith("ap_get_client_block"); } str = alloc_string (i); memcpy (String_val (str), buffer, i); CAMLreturn (str); }
/** gsoap function that requests the next piece of data from us */ static size_t frecv(struct soap *psoap, char *pBuf, apr_size_t len) { request_rec *r = NULL; apr_size_t nRet = 0; gsoapRequestConfiguration *pRqConf = getRequestConfiguration(psoap); if (NULL != pRqConf) { r = pRqConf->r; if (!pRqConf->headers_received) { apr_table_do(send_header_to_gsoap, psoap, r->headers_in, NULL); pRqConf->headers_received = TRUE; } /* * Steven Elliott <*****@*****.**>: * It's not obvious from Apache documentation documentation how * exactly ap_get_client_block() should be called in both the chunked * and non-chunked cases. In the chunked case r->remaining is zero, * so that can't be an upper bound to the number of bytes read. * However, this site: * http://docstore.mik.ua/orelly/apache_mod/139.htm * cautions that "If you are handling non-chunked data, do not try to * read more than the number of bytes declared in Content-length * because this may cause the attempted read to block indefinitely." * Consequently my best guess, with regard to what is safe, is in the * non-chunked case continue doing as mod_gsoap has done in the past * and limit the upper bound to r->remaining. In the chunked case * read "len", which almost certainly exceeds what was posted. * Hopefully if ap_get_client_block() blocks it returns no later than * when the current post is complete regardless of chunking or * keep-alive. */ nRet = ap_get_client_block(r, pBuf, r->read_chunked ? len : (len > r->remaining ? r->remaining : len)); } return nRet; }
static ssize_t read_data(void *fd, void *buf, size_t siz) { ssize_t len_read; request_rec *ap_r = (request_rec *)fd; len_read = ap_get_client_block(ap_r, buf, siz); #ifndef APACHE2 ap_reset_timeout(ap_r); #endif #ifdef DEBUG fprintf(stderr, "read_data(0x%8.8x, 0x%8.8x, %d): %d", fd, buf, siz, len_read); if (len_read < 0) fprintf(stderr, ": %s", strerror(errno)); putc('\n', stderr); dump_buffer(stderr, "read_data:", buf, len_read); #endif return (len_read); }
BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize) { request_rec *r = ((isapi_cid *)ConnID)->r; DWORD read = 0; int res; if (r->remaining < (long) *lpdwSize) *lpdwSize = r->remaining; while (read < *lpdwSize && ((res = ap_get_client_block(r, (char*)lpvBuffer + read, *lpdwSize - read)) > 0)) { if (res < 0) { *lpdwSize = 0; if (!GetLastError()) SetLastError(ERROR); /* XXX: Find the right error code */ return FALSE; } read += res; } *lpdwSize = read; return TRUE; }
int ApacheRequest_parse_multipart(ApacheRequest *req) { request_rec *r = req->r; int rc = OK; const char *ct = ap_table_get(r->headers_in, "Content-Type"); long length; char *boundary; multipart_buffer *mbuff; ApacheUpload *upload = NULL; if (!ct) { ap_log_rerror(REQ_ERROR, "[libapreq] no Content-type header!"); return HTTP_INTERNAL_SERVER_ERROR; } if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { return rc; } if (!ap_should_client_block(r)) { return rc; } if ((length = r->remaining) > req->post_max && req->post_max > 0) { ap_log_rerror(REQ_ERROR, "[libapreq] entity too large (%d, max=%d)", (int)length, req->post_max); return HTTP_REQUEST_ENTITY_TOO_LARGE; } (void)ap_getword(r->pool, &ct, '='); boundary = ap_getword_conf(r->pool, &ct); if (!(mbuff = multipart_buffer_new(boundary, length, r))) { return DECLINED; } while (!multipart_buffer_eof(mbuff)) { table *header = multipart_buffer_headers(mbuff); const char *cd, *param=NULL, *filename=NULL; char buff[FILLUNIT]; int blen, wlen; if (!header) { #ifdef DEBUG ap_log_rerror(REQ_ERROR, "[libapreq] silently drop remaining '%ld' bytes", r->remaining); #endif ap_hard_timeout("[libapreq] parse_multipart", r); while ( ap_get_client_block(r, buff, sizeof(buff)) > 0 ) /* wait for more input to ignore */ ; ap_kill_timeout(r); return OK; } if ((cd = ap_table_get(header, "Content-Disposition"))) { const char *pair; while (*cd && (pair = ap_getword(r->pool, &cd, ';'))) { const char *key; while (ap_isspace(*cd)) { ++cd; } if (ap_ind(pair, '=')) { key = ap_getword(r->pool, &pair, '='); if(strEQ(key, "name")) { param = ap_getword_conf(r->pool, &pair); } else if(strEQ(key, "filename")) { filename = ap_getword_conf(r->pool, &pair); } } } if (!filename) { char *value = multipart_buffer_read_body(mbuff); ap_table_add(req->parms, param, value); continue; } if (!param) continue; /* shouldn't happen, but just in case. */ if (req->disable_uploads) { ap_log_rerror(REQ_ERROR, "[libapreq] file upload forbidden"); return HTTP_FORBIDDEN; } ap_table_add(req->parms, param, filename); if (upload) { upload->next = ApacheUpload_new(req); upload = upload->next; } else { upload = ApacheUpload_new(req); req->upload = upload; } if (! req->upload_hook && ! ApacheRequest_tmpfile(req, upload) ) { return HTTP_INTERNAL_SERVER_ERROR; } upload->info = header; upload->filename = ap_pstrdup(req->r->pool, filename); upload->name = ap_pstrdup(req->r->pool, param); /* mozilla empty-file (missing CRLF) hack */ fill_buffer(mbuff); if( strEQN(mbuff->buf_begin, mbuff->boundary, strlen(mbuff->boundary)) ) { r->remaining -= 2; continue; } while ((blen = multipart_buffer_read(mbuff, buff, sizeof(buff)))) { if (req->upload_hook != NULL) { wlen = req->upload_hook(req->hook_data, buff, blen, upload); } else { wlen = fwrite(buff, 1, blen, upload->fp); } if (wlen != blen) { return HTTP_INTERNAL_SERVER_ERROR; } upload->size += wlen; } if (upload->size > 0 && (upload->fp != NULL)) { fseek(upload->fp, 0, 0); } } } return OK; }
/* XXX: Is there is still an O(n^2) attack possible here? Please detail. */ BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType) { isapi_cid *cid = (isapi_cid *)hConn; request_rec *r = cid->r; request_rec *subreq; switch (dwHSERequest) { case 1: /* HSE_REQ_SEND_URL_REDIRECT_RESP */ /* Set the status to be returned when the HttpExtensionProc() * is done. * WARNING: Microsoft now advertises HSE_REQ_SEND_URL_REDIRECT_RESP * and HSE_REQ_SEND_URL as equivalant per the Jan 2000 SDK. * They most definately are not, even in their own samples. */ ap_table_set(r->headers_out, "Location", lpvBuffer); cid->status = cid->r->status = cid->ecb->dwHttpStatusCode = HTTP_MOVED_TEMPORARILY; return TRUE; case 2: /* HSE_REQ_SEND_URL */ /* Soak up remaining input (there should be none) */ if (r->remaining > 0) { char argsbuffer[HUGE_STRING_LEN]; while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0); } /* Reset the method to GET */ r->method = ap_pstrdup(r->pool, "GET"); r->method_number = M_GET; /* Don't let anyone think there's still data */ ap_table_unset(r->headers_in, "Content-Length"); /* AV fault per PR3598 - redirected path is lost! */ (char*)lpvBuffer = ap_pstrdup(r->pool, (char*)lpvBuffer); ap_internal_redirect((char*)lpvBuffer, r); return TRUE; case 3: /* HSE_REQ_SEND_RESPONSE_HEADER */ { /* Parse them out, or die trying */ DWORD statlen = 0, headlen = 0; if (lpvBuffer) statlen = strlen((char*) lpvBuffer); if (lpdwDataType) headlen = strlen((char*) lpdwDataType); return SendResponseHeaderEx(cid, (char*) lpvBuffer, (char*) lpdwDataType, statlen, headlen); } case 4: /* HSE_REQ_DONE_WITH_SESSION */ /* Do nothing... since we don't support async I/O, they'll * return from HttpExtensionProc soon */ return TRUE; case 1001: /* HSE_REQ_MAP_URL_TO_PATH */ { /* Map a URL to a filename */ char *file = (char *)lpvBuffer; DWORD len; subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, file, *lpdwSize), r); len = ap_cpystrn(file, subreq->filename, *lpdwSize) - file; /* IIS puts a trailing slash on directories, Apache doesn't */ if (S_ISDIR (subreq->finfo.st_mode)) { if (len < *lpdwSize - 1) { file[len++] = '\\'; file[len] = '\0'; } } *lpdwSize = len; return TRUE; } case 1002: /* HSE_REQ_GET_SSPI_INFO */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction HSE_REQ_GET_SSPI_INFO " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1003: /* HSE_APPEND_LOG_PARAMETER */ /* Log lpvBuffer, of lpdwSize bytes, in the URI Query (cs-uri-query) field * This code will do for now... */ ap_table_set(r->notes, "isapi-parameter", (char*) lpvBuffer); if (AppendLogToQuery) { if (r->args) r->args = ap_pstrcat(r->pool, r->args, (char*) lpvBuffer, NULL); else r->args = ap_pstrdup(r->pool, (char*) lpvBuffer); } if (AppendLogToErrors) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r, "ISAPI %s: %s", cid->r->filename, (char*) lpvBuffer); return TRUE; /* We don't support all this async I/O, Microsoft-specific stuff */ case 1005: /* HSE_REQ_IO_COMPLETION */ case 1006: /* HSE_REQ_TRANSMIT_FILE */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI asynchronous I/O not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1007: /* HSE_REQ_REFRESH_ISAPI_ACL */ /* Since we don't override the user ID and access, we can't reset. */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_REFRESH_ISAPI_ACL " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1008: /* HSE_REQ_IS_KEEP_CONN */ *((LPBOOL) lpvBuffer) = (r->connection->keepalive == 1); return TRUE; case 1010: /* HSE_REQ_ASYNC_READ_CLIENT */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI asynchronous I/O not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1011: /* HSE_REQ_GET_IMPERSONATION_TOKEN Added in ISAPI 4.0 */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_GET_IMPERSONATION_TOKEN " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; #ifdef HSE_REQ_MAP_URL_TO_PATH_EX case 1012: /* HSE_REQ_MAP_URL_TO_PATH_EX */ { /* Map a URL to a filename */ LPHSE_URL_MAPEX_INFO info = (LPHSE_URL_MAPEX_INFO) lpdwDataType; char* test_uri = ap_pstrndup(r->pool, (char *)lpvBuffer, *lpdwSize); subreq = ap_sub_req_lookup_uri(test_uri, r); info->cchMatchingURL = strlen(test_uri); info->cchMatchingPath = ap_cpystrn(info->lpszPath, subreq->filename, MAX_PATH) - info->lpszPath; /* Mapping started with assuming both strings matched. * Now roll on the path_info as a mismatch and handle * terminating slashes for directory matches. */ if (subreq->path_info && *subreq->path_info) { ap_cpystrn(info->lpszPath + info->cchMatchingPath, subreq->path_info, MAX_PATH - info->cchMatchingPath); info->cchMatchingURL -= strlen(subreq->path_info); if (S_ISDIR(subreq->finfo.st_mode) && info->cchMatchingPath < MAX_PATH - 1) { /* roll forward over path_info's first slash */ ++info->cchMatchingPath; ++info->cchMatchingURL; } } else if (S_ISDIR(subreq->finfo.st_mode) && info->cchMatchingPath < MAX_PATH - 1) { /* Add a trailing slash for directory */ info->lpszPath[info->cchMatchingPath++] = '/'; info->lpszPath[info->cchMatchingPath] = '\0'; } /* If the matched isn't a file, roll match back to the prior slash */ if (!subreq->finfo.st_mode) { while (info->cchMatchingPath && info->cchMatchingURL) { if (info->lpszPath[info->cchMatchingPath - 1] == '/') break; --info->cchMatchingPath; --info->cchMatchingURL; } } /* Paths returned with back slashes */ for (test_uri = info->lpszPath; *test_uri; ++test_uri) if (*test_uri == '/') *test_uri = '\\'; /* is a combination of: * HSE_URL_FLAGS_READ 0x001 Allow read * HSE_URL_FLAGS_WRITE 0x002 Allow write * HSE_URL_FLAGS_EXECUTE 0x004 Allow execute * HSE_URL_FLAGS_SSL 0x008 Require SSL * HSE_URL_FLAGS_DONT_CACHE 0x010 Don't cache (VRoot only) * HSE_URL_FLAGS_NEGO_CERT 0x020 Allow client SSL cert * HSE_URL_FLAGS_REQUIRE_CERT 0x040 Require client SSL cert * HSE_URL_FLAGS_MAP_CERT 0x080 Map client SSL cert to account * HSE_URL_FLAGS_SSL128 0x100 Require 128-bit SSL cert * HSE_URL_FLAGS_SCRIPT 0x200 Allow script execution * * XxX: As everywhere, EXEC flags could use some work... * and this could go further with more flags, as desired. */ info->dwFlags = (subreq->finfo.st_mode & _S_IREAD ? 0x001 : 0) | (subreq->finfo.st_mode & _S_IWRITE ? 0x002 : 0) | (subreq->finfo.st_mode & _S_IEXEC ? 0x204 : 0); return TRUE; } #endif case 1014: /* HSE_REQ_ABORTIVE_CLOSE */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction HSE_REQ_ABORTIVE_CLOSE" " is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1015: /* HSE_REQ_GET_CERT_INFO_EX Added in ISAPI 4.0 */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_GET_CERT_INFO_EX " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; #ifdef HSE_REQ_SEND_RESPONSE_HEADER_EX case 1016: /* HSE_REQ_SEND_RESPONSE_HEADER_EX Added in ISAPI 4.0 */ { LPHSE_SEND_HEADER_EX_INFO shi = (LPHSE_SEND_HEADER_EX_INFO) lpvBuffer; /* XXX: ignore shi->fKeepConn? We shouldn't need the advise */ /* r->connection->keepalive = shi->fKeepConn; */ return SendResponseHeaderEx(cid, shi->pszStatus, shi->pszHeader, shi->cchStatus, shi->cchHeader); } #endif case 1017: /* HSE_REQ_CLOSE_CONNECTION Added after ISAPI 4.0 */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_CLOSE_CONNECTION " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; case 1018: /* HSE_REQ_IS_CONNECTED Added after ISAPI 4.0 */ /* Returns True if client is connected c.f. MSKB Q188346 * XXX: That statement is very ambigious... assuming the * identical return mechanism as HSE_REQ_IS_KEEP_CONN. */ *((LPBOOL) lpvBuffer) = (r->connection->aborted == 0); return TRUE; case 1020: /* HSE_REQ_EXTENSION_TRIGGER Added after ISAPI 4.0 */ /* Undocumented - defined by the Microsoft Jan '00 Platform SDK */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction " "HSE_REQ_EXTENSION_TRIGGER " "is not supported: %s", r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; default: if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI ServerSupportFunction (%d) not supported: " "%s", dwHSERequest, r->filename); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } }