/* * 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; }
CAMLprim value netcgi2_apache_request_should_client_block (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); CAMLreturn (Val_bool (ap_should_client_block (r))); }
/* * Binding to ap_should_client_block. * Uses the request_rec defined as an upvalue. * Returns the status code. */ static int req_should_client_block (lua_State *L) { request_rec *r = CHECK_REQUEST_OBJECT(1); lua_pushnumber (L, ap_should_client_block (r)); return 1; }
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; }
/** * 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; }
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; }
/* The sample content handler */ static int svc_simulator_256b_handler( request_rec * req) { int rv = 0; /*ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, req, "[svc_simulator_256b] damcame1");*/ if(strcmp(req->handler, "svc_simulator_256b_module")) { return DECLINED; } /* Set up the read policy from the client. */ if((rv = ap_setup_client_block(req, REQUEST_CHUNKED_DECHUNK)) != OK) { return rv; } ap_should_client_block(req); rv = svc_simulator_256b_process_request(req); if(DECLINED == rv) { return HTTP_INTERNAL_SERVER_ERROR; } return rv; }
/** * 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; }
/* {{{ sapi_apache_read_post */ static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC) { int total_read_bytes=0, read_bytes; request_rec *r = (request_rec *) SG(server_context); void (*handler)(int); /* * This handles the situation where the browser sends a Expect: 100-continue header * and needs to receive confirmation from the server on whether or not it can send * the rest of the request. RFC 2616 * */ if (!SG(read_post_bytes) && !ap_should_client_block(r)) { return total_read_bytes; } handler = signal(SIGPIPE, SIG_IGN); while (total_read_bytes<count_bytes) { hard_timeout("Read POST information", r); /* start timeout timer */ read_bytes = get_client_block(r, buffer+total_read_bytes, count_bytes-total_read_bytes); reset_timeout(r); if (read_bytes<=0) { break; } total_read_bytes += read_bytes; } signal(SIGPIPE, handler); return total_read_bytes; }
/** * Setup reading of a client block (i.e., POST or PUT data) * @param request_rec * req The request from which to read * @return int the amount of bytes remainig to be read **/ int mod_parrot_open_input(request_rec *req) { if(ap_setup_client_block(req, REQUEST_CHUNKED_ERROR)) return 0; if(!ap_should_client_block(req)) return 0; return req->remaining; }
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); }
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; }
/** * 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 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); }
// Determines whether or not porter should apply. Return true if the content // type is multipart/form-data and the content length is greater than // PorterMinSize. int porter_should_rewrite_body(request_rec *r, porter_server_conf *config) { if (ap_should_client_block(r)) { const char *content_type = apr_table_get(r->headers_in, "Content-Type"); const char *content_length = apr_table_get(r->headers_in, "Content-Length"); if (content_type && strcasecmp(content_type, "multipart/form-data") > 0 && atol(content_length) > config->minimum_multipart_size) { return 1; } } return 0; }
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; }
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; }
/* ==================================================================== * Handles one attempt to transact with the app server. * Returns one of the following codes: * 0 = success * 1 = failure, but ok to try again * 2 = failure, and do not try again * ==================================================================== */ static int transact_with_app_server(request_rec *r, wkcfg* cfg, WFILE* whole_dict, WFILE* int_dict, long length) { int sock = 0; BUFF* buffsocket; long bs; int ret; ap_hard_timeout("wk_send", r); sock = wksock_open(r, cfg->addr, cfg->port, cfg); if (sock <= 0) return 1; /* Errors after this point mean that the * whole request fails -- no retry is possible. * That's because once we've sent the request, it's possible * that the appserver has already started to work on the request, * and we don't want to accidentally submit the same request twice. */ log_debug("creating buffsocket", r); buffsocket = ap_bcreate(r->pool, B_SOCKET+B_RDWR); log_debug("push socket into fd", r); ap_bpushfd(buffsocket, sock, sock); /* Now we send the request to the AppServer */ log_debug("writing request to buff", r); bs = ap_bwrite(buffsocket, int_dict->str, int_dict->ptr - int_dict->str); bs = ap_bwrite(buffsocket, whole_dict->str, length); /* Now we pump through any client input. */ if ((ret = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != 0) return 2; if (ap_should_client_block(r)) { char * buff = ap_pcalloc(r->pool, MAX_STRING_LEN); int n; int sent = 0; int retry = 0; while ((n = ap_get_client_block(r, buff, MAX_STRING_LEN)) > 0) { retry = 0; sent = 0; while (retry < 10) { sent = sent + ap_bwrite(buffsocket, buff+sent, n-sent); if (sent < n) { retry++; sleep(1); log_error("Have to retry sending input to appserver", r->server); } else break; if (retry == 10) { /* AppServer stopped reading */ /* absorb any remaining input */ while (ap_get_client_block(r, buff, MAX_STRING_LEN) > 0) ; /* Dump it */ break; } } } } ap_bflush(buffsocket); /* Done sending */ log_debug("Sent Request to client", r); /* Let the AppServer know we're done */ shutdown(sock, 1); ap_kill_timeout(r); /* Now we get the response from the AppServer */ ap_hard_timeout("wk_read", r); log_debug("scanning for headers", r); /* pull out headers */ if ((ret = ap_scan_script_header_err_buff(r, buffsocket, NULL))) { if (ret >= 500 || ret < 0) { log_error("cannot scan servlet headers ", r->server); return 2; } r->status_line = NULL; } ap_send_http_header(r); /* now we just send the reply straight to the client */ log_debug("Sending response", r); length = ap_send_fb(buffsocket, r); //sprintf(msgbuf, "Sent %i bytes to the client", length); //log_debug(msgbuf, r); /* Kill timeouts, close buffer and socket and return */ ap_kill_timeout(r); log_debug("closing buffsocket", r); ap_bclose(buffsocket); log_debug("Done", r); return 0; }
int isapi_handler (request_rec *r) { LPEXTENSION_CONTROL_BLOCK ecb = ap_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK)); HSE_VERSION_INFO *pVer = ap_pcalloc(r->pool, sizeof(HSE_VERSION_INFO)); HINSTANCE isapi_handle; BOOL (*isapi_version)(HSE_VERSION_INFO *); /* entry point 1 */ DWORD (*isapi_entry)(LPEXTENSION_CONTROL_BLOCK); /* entry point 2 */ BOOL (*isapi_term)(DWORD); /* optional entry point 3 */ isapi_cid *cid = ap_pcalloc(r->pool, sizeof(isapi_cid)); table *e = r->subprocess_env; DWORD read; char *p; int retval; int res; /* Use similar restrictions as CGIs */ if (!(ap_allow_options(r) & OPT_EXECCGI)) return FORBIDDEN; if (r->finfo.st_mode == 0) return NOT_FOUND; if (S_ISDIR(r->finfo.st_mode)) return FORBIDDEN; if (!(isapi_handle = ap_os_dso_load(r->filename))) { ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, "ISAPI Could not load DLL: %s", r->filename); return SERVER_ERROR; } if (!(isapi_version = (void *)(ap_os_dso_sym(isapi_handle, "GetExtensionVersion")))) { ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, "DLL could not load GetExtensionVersion(): %s", r->filename); ap_os_dso_unload(isapi_handle); return SERVER_ERROR; } if (!(isapi_entry = (void *)(ap_os_dso_sym(isapi_handle, "HttpExtensionProc")))) { ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, "DLL could not load HttpExtensionProc(): %s", r->filename); ap_os_dso_unload(isapi_handle); return SERVER_ERROR; } isapi_term = (void *)(ap_os_dso_sym(isapi_handle, "TerminateExtension")); /* Run GetExtensionVersion() */ if (!(*isapi_version)(pVer)) { ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, "ISAPI GetExtensionVersion() failed: %s", r->filename); ap_os_dso_unload(isapi_handle); return SERVER_ERROR; } /* Set up variables. There are a couple of special cases for ISAPI. * XXX: These were taken verbatim from GetServerVariable, and should * be reviewed carefully. */ ap_add_common_vars(r); ap_add_cgi_vars(r); ap_table_setn(r->subprocess_env, "UNMAPPED_REMOTE_USER", "REMOTE_USER"); ap_table_setn(r->subprocess_env, "SERVER_PORT_SECURE", "0"); ap_table_setn(r->subprocess_env, "URL", r->uri); /* Set up connection ID */ ecb->ConnID = (HCONN)cid; cid->ecb = ecb; cid->r = r; cid->status = 0; ecb->cbSize = sizeof(struct _EXTENSION_CONTROL_BLOCK); ecb->dwVersion = MAKELONG(0, 2); ecb->dwHttpStatusCode = 0; strcpy(ecb->lpszLogData, ""); ecb->lpszMethod = ap_pstrdup(r->pool, r->method); ecb->lpszQueryString = ap_pstrdup(r->pool, ap_table_get(e, "QUERY_STRING")); ecb->lpszPathInfo = ap_pstrdup(r->pool, ap_table_get(e, "PATH_INFO")); ecb->lpszPathTranslated = ap_pstrdup(r->pool, ap_table_get(e, "PATH_TRANSLATED")); ecb->lpszContentType = ap_pstrdup(r->pool, ap_table_get(e, "CONTENT_TYPE")); /* Set up client input */ if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { if (isapi_term) (*isapi_term)( 2 /* HSE_TERM_MUST_UNLOAD */); ap_os_dso_unload(isapi_handle); return retval; } if (ap_should_client_block(r)) { /* Time to start reading the appropriate amount of data, * and allow the administrator to tweak the number * TODO: add the httpd.conf option for ReadAheadBuffer. */ if (r->remaining) { ecb->cbTotalBytes = r->remaining; if (ecb->cbTotalBytes > ReadAheadBuffer) ecb->cbAvailable = ReadAheadBuffer; else ecb->cbAvailable = ecb->cbTotalBytes; } else { ecb->cbTotalBytes = 0xffffffff; ecb->cbAvailable = ReadAheadBuffer; } ecb->lpbData = ap_pcalloc(r->pool, ecb->cbAvailable + 1); p = ecb->lpbData; read = 0; while (read < ecb->cbAvailable && ((res = ap_get_client_block(r, ecb->lpbData + read, ecb->cbAvailable - read)) > 0)) { read += res; } if (res < 0) { if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); ap_os_dso_unload(isapi_handle); return SERVER_ERROR; } /* Although its not to spec, IIS seems to null-terminate * its lpdData string. So we will too. * * XXX: This must be an issue... backing out the null * from the count of bytes. */ if (res == 0) ecb->cbAvailable = ecb->cbTotalBytes = read; else ecb->cbAvailable = read; ecb->lpbData[read] = '\0'; } else { ecb->cbTotalBytes = 0; ecb->cbAvailable = 0; ecb->lpbData = NULL; } /* Set up the callbacks */ ecb->GetServerVariable = &GetServerVariable; ecb->WriteClient = &WriteClient; ecb->ReadClient = &ReadClient; ecb->ServerSupportFunction = &ServerSupportFunction; /* All right... try and load the sucker */ retval = (*isapi_entry)(ecb); /* Set the status (for logging) */ if (ecb->dwHttpStatusCode) r->status = ecb->dwHttpStatusCode; /* Check for a log message - and log it */ if (ecb->lpszLogData && strcmp(ecb->lpszLogData, "")) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "ISAPI: %s: %s", ecb->lpszLogData, r->filename); /* Soak up any remaining input */ if (r->remaining > 0) { char argsbuffer[HUGE_STRING_LEN]; while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0); } /* All done with the DLL... get rid of it */ if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); ap_os_dso_unload(isapi_handle); switch(retval) { case 0: /* Strange, but MS isapi accepts this as success */ case HSE_STATUS_SUCCESS: case HSE_STATUS_SUCCESS_AND_KEEP_CONN: /* Ignore the keepalive stuff; Apache handles it just fine without * the ISA's "advice". */ if (cid->status) /* We have a special status to return */ return cid->status; return OK; case HSE_STATUS_PENDING: /* We don't support this */ if (LogNotSupported) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "ISAPI asynchronous I/O not supported: %s", r->filename); case HSE_STATUS_ERROR: default: return SERVER_ERROR; } }
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; }
/** parse_multipart_data : onpart:function:2 -> ondata:function:3 -> void <doc> Incrementally parse the multipart data. call [onpart(name,filename)] for each part found and [ondata(buf,pos,len)] when some data is available </doc> **/ static value parse_multipart_data( value onpart, value ondata ) { value buf; int len = 0; mcontext *c = CONTEXT(); const char *ctype = ap_table_get(c->r->headers_in,"Content-Type"); value boundstr; val_check_function(onpart,2); val_check_function(ondata,3); buf = alloc_empty_string(BUFSIZE); if( !ctype || strstr(ctype,"multipart/form-data") == NULL ) return val_null; // extract boundary value { const char *boundary, *bend; if( (boundary = strstr(ctype,"boundary=")) == NULL ) neko_error(); boundary += 9; PARSE_HEADER(boundary,bend); len = (int)(bend - boundary); boundstr = alloc_empty_string(len+2); if( val_strlen(boundstr) > BUFSIZE / 2 ) neko_error(); val_string(boundstr)[0] = '-'; val_string(boundstr)[1] = '-'; memcpy(val_string(boundstr)+2,boundary,len); } len = 0; if( !ap_should_client_block(c->r) ) neko_error(); while( true ) { char *name, *end_name, *filename, *end_file_name, *data; int pos; // refill buffer // we assume here that the the whole multipart header can fit in the buffer fill_buffer(c,buf,&len); // is boundary at the beginning of buffer ? if( len < val_strlen(boundstr) || memcmp(val_string(buf),val_string(boundstr),val_strlen(boundstr)) != 0 ) return discard_body(c); name = memfind(val_string(buf),len,"Content-Disposition:"); if( name == NULL ) break; name = memfind(name,len - (int)(name - val_string(buf)),"name="); if( name == NULL ) return discard_body(c); name += 5; PARSE_HEADER(name,end_name); data = memfind(end_name,len - (int)(end_name - val_string(buf)),"\r\n\r\n"); if( data == NULL ) return discard_body(c); filename = memfind(name,(int)(data - name),"filename="); if( filename != NULL ) { filename += 9; PARSE_HEADER(filename,end_file_name); } data += 4; pos = (int)(data - val_string(buf)); // send part name val_call2(onpart,copy_string(name,(int)(end_name - name)),filename?copy_string(filename,(int)(end_file_name - filename)):val_null); // read data while( true ) { const char *boundary; // recall buffer memmove(val_string(buf),val_string(buf)+pos,len - pos); len -= pos; pos = 0; fill_buffer(c,buf,&len); // lookup bounds boundary = memfind(val_string(buf),len,val_string(boundstr)); if( boundary == NULL ) { if( len == 0 ) return discard_body(c); // send as much buffer as possible to client if( len < BUFSIZE ) pos = len; else pos = len - val_strlen(boundstr) + 1; val_call3(ondata,buf,alloc_int(0),alloc_int(pos)); } else { // send remaining data pos = (int)(boundary - val_string(buf)); val_call3(ondata,buf,alloc_int(0),alloc_int(pos-2)); // recall memmove(val_string(buf),val_string(buf)+pos,len - pos); len -= pos; break; } } } return val_null; }
static int suphp_source_handler(request_rec *r) { suphp_conf *conf; int rv; pool *p; int fd; BUFF *script_in, *script_out, *script_err; char buffer[HUGE_STRING_LEN]; if (strcmp(r->method, "GET")) { return DECLINED; } conf = ap_get_module_config(r->server->module_config, &suphp_module); if (conf->php_path == NULL) { return DECLINED; } p = r->main ? r->main->pool : r->pool; fd = open(r->filename, O_NOCTTY, O_RDONLY); if (fd != -1) { close(fd); } else if (errno == EACCES) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "access to %s denied", r->filename); return HTTP_FORBIDDEN; } else if (errno == ENOENT || errno == ENOTDIR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "File does not exist: %s", r->filename); return HTTP_NOT_FOUND; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "could open file: %s", r->filename); return HTTP_NOT_FOUND; } /* Fork child process */ if (!ap_bspawn_child(p, suphp_source_child, (void *) r, kill_after_timeout, &script_in, &script_out, &script_err)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "couldn't spawn child process for: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } /* Read request body */ if (ap_should_client_block(r)) { char buffer[HUGE_STRING_LEN]; int len_read; ap_hard_timeout("reading request body", r); while (ap_get_client_block(r, buffer, HUGE_STRING_LEN) > 0) { ap_reset_timeout(r); // Ignore input } ap_bflush(script_in); ap_kill_timeout(r); } ap_bclose(script_in); /* Transfer output from PHP to client */ if (script_out) { /* Output headers and body */ r->content_type = "text/html"; ap_send_http_header(r); if (!r->header_only) { ap_send_fb(script_out, r); } ap_bclose(script_out); /* Errors have already been logged by child */ ap_bclose(script_err); } return OK; }
static int suphp_handler(request_rec *r) { suphp_conf *sconf; suphp_conf *dconf; #ifdef SUPHP_USE_USERGROUP char *ud_user = NULL; char *ud_group = NULL; int ud_success = 0; #endif struct stat finfo; int rv; char *auth_user = NULL; char *auth_pass = NULL; pool *p; BUFF *script_in, *script_out, *script_err; const char *handler; sconf = ap_get_module_config(r->server->module_config, &suphp_module); dconf = ap_get_module_config(r->per_dir_config, &suphp_module); p = r->main ? r->main->pool : r->pool; /* only handle request if mod_suphp is active for this handler */ /* check only first byte of value (second has to be \0) */ if (r->handler != NULL) { handler = r->handler; } else { handler = r->content_type; } if ((ap_table_get(dconf->handlers, handler) == NULL)) { if ((ap_table_get(sconf->handlers, handler) == NULL) || (*(ap_table_get(sconf->handlers, handler)) == '0')) { return DECLINED; } } else if (*(ap_table_get(dconf->handlers, handler)) == '0') { return DECLINED; } /* check if suPHP is enabled for this request */ if (((sconf->engine != SUPHP_ENGINE_ON) && (dconf->engine != SUPHP_ENGINE_ON)) || ((sconf->engine == SUPHP_ENGINE_ON) && (dconf->engine == SUPHP_ENGINE_OFF))) return DECLINED; /* check if file is existing and accessible */ rv = stat(ap_pstrdup(p, r->filename), &finfo); if (rv == 0) { ; /* do nothing */ } else if (errno == EACCES) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "access to %s denied", r->filename); return HTTP_FORBIDDEN; } else if (errno == ENOENT || errno == ENOTDIR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "File does not exist: %s", r->filename); return HTTP_NOT_FOUND; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "could not get fileinfo: %s", r->filename); return HTTP_NOT_FOUND; } #ifdef SUPHP_USE_USERGROUP if ((sconf->target_user == NULL || sconf->target_group == NULL) && (dconf->target_user == NULL || dconf->target_group == NULL)) { /* Identify mod_userdir request As Apache 1.3 does not yet provide a clean way to see whether a request was handled by mod_userdir, we assume this is true for any request beginning with ~ */ int ud_success = 0; /* set to 1 on success */ if (!strncmp("/~", r->uri, 2)) { char *username = ap_pstrdup(r->pool, r->uri + 2); char *pos = strchr(username, '/'); if (pos) { *pos = 0; if (strlen(username)) { struct passwd *pw; struct group *gr; gid_t gid; char *grpname; if ((pw = getpwnam(username)) != NULL) { gid = pw->pw_gid; if ((gr = getgrgid(gid)) != NULL) { grpname = gr->gr_name; } else { if ((grpname = ap_palloc(r->pool, 16)) == NULL) { return HTTP_INTERNAL_SERVER_ERROR; } ap_snprintf(grpname, 16, "#%ld", (long) gid); } ud_user = username; ud_group = grpname; ud_success = 1; } } } } if (!ud_success) { /* This is not a userdir request and user/group are not set, so log the error and return */ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "No user or group set - set suPHP_UserGroup"); return HTTP_INTERNAL_SERVER_ERROR; } } #endif /* SUPHP_USE_USERGROUP */ /* prepare environment for new process */ ap_add_common_vars(r); ap_add_cgi_vars(r); ap_table_unset(r->subprocess_env, "SUPHP_PHP_CONFIG"); ap_table_unset(r->subprocess_env, "SUPHP_AUTH_USER"); ap_table_unset(r->subprocess_env, "SUPHP_AUTH_PW"); #ifdef SUPHP_USE_USERGROUP ap_table_unset(r->subprocess_env, "SUPHP_USER"); ap_table_unset(r->subprocess_env, "SUPHP_GROUP"); ap_table_unset(r->subprocess_env, "SUPHP_USERDIR_USER"); ap_table_unset(r->subprocess_env, "SUPHP_USERDIR_GROUP"); #endif /* SUPHP_USE_USERGROUP */ if (dconf->php_config) { ap_table_set(r->subprocess_env, "SUPHP_PHP_CONFIG", dconf->php_config); } ap_table_set(r->subprocess_env, "SUPHP_HANDLER", handler); if (r->headers_in) { const char *auth; auth = ap_table_get(r->headers_in, "Authorization"); if (auth && auth[0] != 0 && strncmp(auth, "Basic ", 6) == 0) { char *user; char *pass; user = ap_pbase64decode(p, auth + 6); if (user) { pass = strchr(user, ':'); if (pass) { *pass++ = '\0'; auth_user = ap_pstrdup(p, user); auth_pass = ap_pstrdup(p, pass); } } } } if (auth_user && auth_pass) { ap_table_setn(r->subprocess_env, "SUPHP_AUTH_USER", auth_user); ap_table_setn(r->subprocess_env, "SUPHP_AUTH_PW", auth_pass); } #ifdef SUPHP_USE_USERGROUP if (dconf->target_user) { ap_table_set(r->subprocess_env, "SUPHP_USER", dconf->target_user); } else if (sconf->target_user) { ap_table_set(r->subprocess_env, "SUPHP_USER", sconf->target_user); } else { ap_table_set(r->subprocess_env, "SUPHP_USER", ud_user); } if (dconf->target_group) { ap_table_set(r->subprocess_env, "SUPHP_GROUP", dconf->target_group); } else if (sconf->target_group) { ap_table_set(r->subprocess_env, "SUPHP_GROUP", sconf->target_group); } else { ap_table_set(r->subprocess_env, "SUPHP_GROUP", ud_group); } if (ud_success) { ap_table_set(r->subprocess_env, "SUPHP_USERDIR_USER", ud_user); ap_table_set(r->subprocess_env, "SUPHP_USERDIR_GROUP", ud_group); } #endif /* SUPHP_USE_USERGROUP */ /* Fork child process */ if (!ap_bspawn_child(p, suphp_child, (void *) r, kill_after_timeout, &script_in, &script_out, &script_err)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "couldn't spawn child process for: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } /* Transfer request body to script */ if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) { /* Call failed, return status */ return rv; } if (ap_should_client_block(r)) { char buffer[HUGE_STRING_LEN]; int len_read; ap_hard_timeout("reading request body", r); while ((len_read = ap_get_client_block(r, buffer, HUGE_STRING_LEN)) > 0) { ap_reset_timeout(r); if (ap_bwrite(script_in, buffer, len_read) < len_read) { /* silly script stopped reading, soak up remaining message */ while (ap_get_client_block(r, buffer, HUGE_STRING_LEN) > 0) { /* dump it */ } break; } } ap_bflush(script_in); ap_kill_timeout(r); } ap_bclose(script_in); /* Transfer output from script to client */ if (script_out) { const char *location; char hbuffer[MAX_STRING_LEN]; char buffer[HUGE_STRING_LEN]; rv = ap_scan_script_header_err_buff(r, script_out, hbuffer); if (rv == HTTP_NOT_MODIFIED) { return rv; } else if (rv) { return HTTP_INTERNAL_SERVER_ERROR; } location = ap_table_get(r->headers_out, "Location"); if (location && r->status == 200) { /* Soak up all the script output */ ap_hard_timeout("reading from script", r); while (ap_bgets(buffer, HUGE_STRING_LEN, script_out) > 0) { continue; } ap_kill_timeout(r); ap_bclose(script_out); ap_bclose(script_err); if (location[0] == '/') { /* Redirect has always GET method */ r->method = ap_pstrdup(p, "GET"); r->method_number = M_GET; /* Remove Content-Length - redirect should not read * * request body */ ap_table_unset(r->headers_in, "Content-Length"); /* Do the redirect */ ap_internal_redirect_handler(location, r); return OK; } else { /* Script did not set status 302 - so it does not want * * to send its own body. Simply set redirect status */ return REDIRECT; } } /* Output headers and body */ ap_send_http_header(r); if (!r->header_only) { ap_send_fb(script_out, r); } ap_bclose(script_out); /* Errors have already been logged by child */ ap_bclose(script_err); } return OK; }
static int tora_handler( request_rec *r ) { mcontext ctx, *c = &ctx; if( strcmp(r->handler,"tora-handler") != 0) return DECLINED; // init context c->need_discard = false; c->is_multipart = false; c->headers_sent = false; c->is_form_post = false; c->r = r; c->post_data = NULL; c->xff = NULL; c->client_ip = NULL; c->p = NULL; c->r->content_type = "text/html"; config.hits++; // read post data { const char *ctype = ap_table_get(r->headers_in,"Content-Type"); ap_setup_client_block(r,REQUEST_CHUNKED_ERROR); if( ctype && strstr(ctype,"multipart/form-data") ) c->is_multipart = true; else if( ap_should_client_block(r) ) { int tlen = 0; c->post_data = (char*)malloc(config.max_post_size); while( true ) { int len = ap_get_client_block(r,c->post_data + tlen,config.max_post_size - tlen); if( len <= 0 ) break; tlen += len; } if( tlen >= config.max_post_size ) { discard_body(c); free(c->post_data); log_error(c,"Maximum POST data exceeded. Try using multipart encoding"); return OK; } c->post_data[tlen] = 0; c->post_data_size = tlen; c->is_form_post = ctype == NULL || (strstr(ctype,"urlencoded") != NULL); } } // init protocol { protocol_infos infos; request_rec *first = r; while( first->prev != NULL ) first = first->prev; infos.custom = c; infos.script = r->filename; infos.uri = first->uri; infos.hostname = r->hostname ? r->hostname : ""; if( config.proxy_mode ) { const char *xff = ap_table_get(r->headers_in,"X-Forwarded-For"); if( xff == NULL ) infos.client_ip = r->connection->remote_ip; else { char tmp; char *xend = (char*)xff + strlen(xff) - 1; while( xend > xff && *xend != ' ' && *xend != ',' ) xend--; c->client_ip = strdup(xend); infos.client_ip = c->client_ip; if( xend > xff && *xend == ' ' && xend[-1] == ',' ) xend--; tmp = *xend; *xend = 0; c->xff = strdup(xff); *xend = tmp; } } else infos.client_ip = inet_ntoa(REMOTE_ADDR(r->connection)); infos.http_method = r->method; infos.get_data = r->args; infos.post_data = c->post_data; infos.post_data_size = c->post_data_size; infos.content_type = ap_table_get(r->headers_in,"Content-Type"); infos.do_get_headers = do_get_headers; infos.do_get_params = do_get_params; infos.do_set_header = do_set_header; infos.do_set_return_code = do_set_return_code; infos.do_print = do_print; infos.do_flush = do_flush; infos.do_log = do_log; infos.do_stream_data = c->is_multipart ? do_stream_data : NULL; c->p = protocol_init(&infos); } // run protocol { int port = config.port_min + (config.hits % (1 + config.port_max - config.port_min)); if( !protocol_connect(c->p,config.host,port) || !protocol_send_request(c->p) || !protocol_read_answer(c->p) ) log_error(c,protocol_get_error(c->p)); } // cleanup protocol_free(c->p); free(c->xff); free(c->client_ip); free(c->post_data); send_headers(c); // in case... if( c->need_discard ) discard_body(c); return OK; }
static osrfStringArray* apacheParseParms(request_rec* r) { if( r == NULL ) return NULL; //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "got a valid request_rec"); char* arg = NULL; apr_pool_t *p = r->pool; /* memory pool */ growing_buffer* buffer = buffer_init(1025); /* gather the post args and append them to the url query string */ if( !strcmp(r->method,"POST") ) { ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK); //osrfLogDebug(OSRF_LOG_MARK, "gateway reading post data.."); //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "idlchunk reading post data.."); if(ap_should_client_block(r)) { /* Start with url query string, if any */ if(r->args && r->args[0]) buffer_add(buffer, r->args); char body[1025]; //osrfLogDebug(OSRF_LOG_MARK, "gateway client has post data, reading..."); /* Append POST data */ long bread; while( (bread = ap_get_client_block(r, body, sizeof(body) - 1)) ) { if(bread < 0) { //osrfLogInfo(OSRF_LOG_MARK, // "ap_get_client_block(): returned error, exiting POST reader"); break; } body[bread] = '\0'; buffer_add( buffer, body ); //osrfLogDebug(OSRF_LOG_MARK, // "gateway read %ld bytes: %d bytes of data so far", bread, buffer->n_used); if(buffer->n_used > APACHE_TOOLS_MAX_POST_SIZE) { //osrfLogError(OSRF_LOG_MARK, "gateway received POST larger " // "than %d bytes. dropping request", APACHE_TOOLS_MAX_POST_SIZE); buffer_free(buffer); return NULL; } } //osrfLogDebug(OSRF_LOG_MARK, "gateway done reading post data"); } } else { /* GET */ if(r->args && r->args[0]) buffer_add(buffer, r->args); //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "idlchunk read GET data.."); } if(buffer->n_used > 0) arg = apr_pstrdup(p, buffer->buf); else arg = NULL; buffer_free(buffer); if( !arg || !arg[0] ) { /* we received no request */ return NULL; } //osrfLogDebug(OSRF_LOG_MARK, "parsing URL params from post/get request data: %s", arg); //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "parsing URL params from post/get request data: %s", arg); osrfStringArray* sarray = osrfNewStringArray(12); /* method parameters */ int sanity = 0; char* key = NULL; /* query item name */ char* val = NULL; /* query item value */ /* Parse the post/get request data into a series of name/value pairs. */ /* Load each name into an even-numbered slot of an osrfStringArray, and */ /* the corresponding value into the following odd-numbered slot. */ while( arg && (val = ap_getword(p, (const char**) &arg, '&'))) { key = ap_getword(r->pool, (const char**) &val, '='); if(!key || !key[0]) break; ap_unescape_url(key); ap_unescape_url(val); //osrfLogDebug(OSRF_LOG_MARK, "parsed URL params %s=%s", key, val); osrfStringArrayAdd(sarray, key); osrfStringArrayAdd(sarray, val); if( sanity++ > 1000 ) { //osrfLogError(OSRF_LOG_MARK, // "Parsing URL params failed sanity check: 1000 iterations"); osrfStringArrayFree(sarray); return NULL; } } //osrfLogDebug(OSRF_LOG_MARK, // "Apache tools parsed %d params key/values", sarray->size / 2 ); return sarray; }