Exemplo n.º 1
0
// The fixup filter's job is to determine if the content body needs to be rewritten,
// and if it does need to be rewritten, it triggers the work
static int porter_fixup(request_rec *r)
{
  apr_status_t rv;
  apr_table_setn(r->headers_in, HTTP_X_UPLOADS, NULL);

  porter_server_conf *config = (porter_server_conf *)ap_get_module_config(r->server->module_config, &porter_module);

  if(!config->enabled)
  {
    PORTER_LOG("Sadly you don't want your uploads to scale !! Good bye");
    return DECLINED;
  }

  int http_status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
  if (http_status != OK) {
    return http_status;
  }

  if (porter_should_rewrite_body(r, config))
  {
    PORTER_HANDLE_ERROR(porter_process_upload(r));
  }

  return DECLINED;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
/**
 * 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;
}
Exemplo n.º 5
0
/**
 * 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;
}
Exemplo n.º 6
0
/* 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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
/**
 * 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;
}
Exemplo n.º 10
0
CAMLprim value
netcgi2_apache_request_setup_client_block (value rv, value rp)
{
    CAMLparam2 (rv, rp);
    request_rec *r = Request_rec_val (rv);
    int i = ap_setup_client_block (r, Int_val (rp));
    CAMLreturn (Val_int(i)); /* possible error dealt with on the Caml side */
}
/*
 * This handles scgi:(dest) URLs
 */
static int scgi_handler(request_rec *r, proxy_worker *worker,
                        proxy_server_conf *conf, char *url,
                        const char *proxyname, apr_port_t proxyport)
{
    int status;
    proxy_conn_rec *backend = NULL;
    apr_pool_t *p = r->pool;
    apr_uri_t *uri = apr_palloc(r->pool, sizeof(*uri));
    char dummy;

    if (strncasecmp(url, SCHEME "://", sizeof(SCHEME) + 2)) {
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "proxy: " PROXY_FUNCTION ": declining URL %s", url);
        return DECLINED;
    }
    url += sizeof(SCHEME); /* keep the slashes */
    
    /* Create space for state information */
    status = ap_proxy_acquire_connection(PROXY_FUNCTION, &backend, worker,
                                         r->server);
    if (status != OK) {
        goto cleanup;
    }
    backend->is_ssl = 0;

    /* Step One: Determine Who To Connect To */
    status = ap_proxy_determine_connection(p, r, conf, worker, backend,
                                           uri, &url, proxyname, proxyport,
                                           &dummy, 1);
    if (status != OK) {
        goto cleanup;
    }

    /* Step Two: Make the Connection */
    if (ap_proxy_connect_backend(PROXY_FUNCTION, backend, worker, r->server)) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                     "proxy: " PROXY_FUNCTION ": failed to make connection "
                     "to backend: %s:%u", backend->hostname, backend->port);
        status = HTTP_SERVICE_UNAVAILABLE;
        goto cleanup;
    }

    /* Step Three: Process the Request */
    if (   ((status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK)
        || ((status = send_headers(r, backend)) != OK)
        || ((status = send_request_body(r, backend)) != OK)
        || ((status = pass_response(r, backend)) != OK)) {
        goto cleanup;
    }

cleanup:
    if (backend) {
        backend->close = 1; /* always close the socket */
        ap_proxy_release_connection(PROXY_FUNCTION, backend, r->server);
    }
    return status;
}
Exemplo n.º 12
0
int TestHandler::handler(ApacheRequestRec *pRequest)
{
    mHits++;
    pRequest->content_type("application/x-httpd-cgi");
    pRequest->dump();
    pRequest->rprintf("BOO");
    ap_setup_client_block(pRequest->get_request_rec(), REQUEST_CHUNKED_ERROR);
    return OK;
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
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();
}
Exemplo n.º 15
0
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>");
		}
	}
}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
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);
  }
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
static int
ipp_handler(request_rec *r)
{
	papi_attribute_t **request = NULL, **response = NULL;
	IPPListenerConfig *config;
	papi_status_t status;
	int ret;

	/* Really, IPP is all POST requests */
	if (r->method_number != M_POST)
		return (DECLINED);

#ifndef APACHE2
	/*
	 * An IPP request must have a MIME type of "application/ipp"
	 * (RFC-2910, Section 4, page 19).  If it doesn't match this
	 * MIME type, we should decline the request and let someone else
	 * try and handle it.
	 */
	if (r->headers_in != NULL) {
		char *mime_type = (char *)ap_table_get(r->headers_in,
							"Content-Type");

		if ((mime_type == NULL) ||
		    (strcasecmp(mime_type, "application/ipp") != 0))
			return (DECLINED);
	}
#endif
	/* CHUNKED_DECHUNK might not work right for IPP? */
	if ((ret = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK)
		return (ret);

	if (!ap_should_client_block(r))
		return (HTTP_INTERNAL_SERVER_ERROR);

#ifndef APACHE2
	ap_soft_timeout("ipp_module: read/reply request ", r);
#endif
	/* read the IPP request off the network */
	status = ipp_read_message(read_data, r, &request, IPP_TYPE_REQUEST);

	if (status != PAPI_OK)
		_log_rerror(APLOG_MARK, APLOG_ERR, r,
			"read failed: %s\n", papiStatusString(status));
#ifdef DEBUG
	papiAttributeListPrint(stderr, request, "request (%d)  ", getpid());
#endif

	(void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
		"originating-host", (char *)
#ifdef APACHE2
		ap_get_remote_host
			(r->connection, r->per_dir_config, REMOTE_NAME, NULL));
#else
		ap_get_remote_host
			(r->connection, r->per_dir_config, REMOTE_NAME));
#endif

	(void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
				"uri-port", ap_get_server_port(r));
	if (r->headers_in != NULL) {
		char *host = (char *)ap_table_get(r->headers_in, "Host");

		if ((host == NULL) || (host[0] == '\0'))
			host = (char *)ap_get_server_name(r);

		(void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
				"uri-host", host);
	}
	(void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL,
				"uri-path", r->uri);

	config = ap_get_module_config(r->per_dir_config, &ipp_module);
	if (config != NULL) {
		(void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
				"conformance", config->conformance);
		(void) papiAttributeListAddCollection(&request, PAPI_ATTR_EXCL,
				"operations", config->operations);
		if (config->default_user != NULL)
			(void) papiAttributeListAddString(&request,
						PAPI_ATTR_EXCL, "default-user",
						config->default_user);
		if (config->default_svc != NULL)
			(void) papiAttributeListAddString(&request,
					PAPI_ATTR_EXCL, "default-service",
					config->default_svc);
	}

	/*
	 * For Trusted Solaris, pass the fd number of the socket connection
	 * to the backend so the it can be forwarded to the backend print
	 * service to retrieve the sensativity label off of a multi-level
	 * port.
	 */
	(void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL,
			"peer-socket", ap_bfileno(r->connection->client, B_RD));

	/* process the request */
	status = ipp_process_request(request, &response, read_data, r);
	if (status != PAPI_OK) {
		errno = 0;
		_log_rerror(APLOG_MARK, APLOG_ERR, r,
			"request failed: %s\n", papiStatusString(status));
		discard_data(r);
	}
#ifdef DEBUG
	fprintf(stderr, "processing result: %s\n", papiStatusString(status));
	papiAttributeListPrint(stderr, response, "response (%d)  ", getpid());
#endif

	/*
	 * If the client is using chunking and we have not yet received the
	 * final "0" sized chunk, we need to discard any data that may
	 * remain in the post request.
	 */
	if ((r->read_chunked != 0) &&
	    (ap_table_get(r->headers_in, "Content-Length") == NULL))
		discard_data(r);

	/* write an IPP response back to the network */
	r->content_type = "application/ipp";

#ifndef	APACHE2
	ap_send_http_header(r);
#endif

	status = ipp_write_message(write_data, r, response);
	if (status != PAPI_OK)
		_log_rerror(APLOG_MARK, APLOG_ERR, r,
			"write failed: %s\n", papiStatusString(status));
#ifdef DEBUG
	fprintf(stderr, "write result: %s\n", papiStatusString(status));
	fflush(stderr);
#endif

	papiAttributeListFree(request);
	papiAttributeListFree(response);

#ifndef APACHE2
	ap_kill_timeout(r);
	if (ap_rflush(r) < 0)
		_log_rerror(APLOG_MARK, APLOG_ERR, r,
			"flush failed, response may not have been sent");
#endif

	return (OK);
}
Exemplo n.º 21
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;
    }

}
Exemplo n.º 22
0
/**
 * Look at the request to see if Resin should handle it.
 */
static int cwx_dispatch(request_rec *r){
    CWX_CONFIG *config = cwx_get_server_config(r->server); 
    unsigned int now = (unsigned int) (r->request_time / 1000000);
    int len;
    char const* szTmp;
    CWX_SERVICE* svr = NULL;
    int ret = OK;
    CWX_CONNECT  conn;
    int code = DECLINED;

    //no config
    if (config == NULL || ! r->uri || !r->handler || ((r->method_number != M_GET)&&(r->method_number != M_POST)) ) return code;

    //no mine
    if ( 0 != memcmp(r->handler, "cwinux_", strlen("cwinux_"))) return code;
	//init the config
    if (!config->m_init) cwx_init_run_conf(config);
    //get svr name
    szTmp = strchr(r->handler + strlen("cwinux_"), '_');
    if (NULL == szTmp) return code;
    len = szTmp - (r->handler + strlen("cwinux_"));
    conn.m_svr_name = (char*)apr_pcalloc(r->pool, len + 1);
    memcpy(conn.m_svr_name, r->handler + strlen("cwinux_"), len);
    conn.m_svr_name[len] = 0x00;
    //get msg type
    szTmp++;
    len = strlen(szTmp);
    conn.m_msg_type = (char*)apr_pcalloc(r->pool, len + 1);
    memcpy(conn.m_msg_type, szTmp, len);
    conn.m_msg_type[len] = 0x00;
    //get svr object
    svr = (CWX_SERVICE*)apr_hash_get(config->m_svr_hash, conn.m_svr_name, APR_HASH_KEY_STRING);
    if (!svr) return code; //no service
    if (!svr->m_host_num) return HTTP_SERVICE_UNAVAILABLE; //no host

    conn.m_config = config;
    conn.m_service = svr;
    conn.m_pool = r->pool;
    conn.m_request = r;
    conn.m_host = NULL;
    conn.m_socket = NULL;
    conn.m_args_head = NULL;
    conn.m_args_tail = NULL;
    conn.m_def_host_index = 0;
    conn.m_cur_host_index = 0;
    ///install user's config
    cwx_fetch_conn_user_config(&conn);

    ///set the chunk type
    ret = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
    if (OK != ret) {
        CWX_ERR(("%s:%d:cwx_request(): Failure to invoke ap_setup_client_block().\n",__FILE__, __LINE__));
        return ret;
    }
    if (r->method_number == M_GET){
        conn.m_args = r->args;
    }else if (r->method_number == M_POST){
        conn.m_args = cwx_read_post(r);
        if (!conn.m_args) return DECLINED;
    }else{
        return DECLINED;
    }

    ///parse url's args
    cwx_parse_args(&conn);
    ///create the default connection
    cwx_get_def_conn(&conn);
    ///set default content type
    r->content_type = "text/html"; 
    while(1){
        //get ui host to query
        if (!conn.m_socket) cwx_get_back_host_conn(&conn);
        //no available host
        if (!conn.m_socket) return HTTP_SERVICE_UNAVAILABLE;
        //query
        code =  cwx_request(&conn);
        //free idle connect
        cwx_free_socket(&conn);
        //success, break;
        if (HTTP_PRECONDITION_FAILED != code) break;
        //using other.
        if ((time(NULL) - now > svr->m_user_config.m_query_timeout/2000)) break;
    }
    return code;
}
Exemplo n.º 23
0
static int
lisp_handler (request_rec * r)
{
  lisp_cfg_t * cfg
    = (ap_get_module_config ((r->per_dir_config), (&lisp_module)));
  int content_length = (-1);
  int keep_socket_p = 0;
  apr_socket_t * socket;
  const char * request_content_length = 0;

  cfg = local_lisp_cfg(cfg);

  if ((strcmp ((r->handler), "lisp-handler")) != 0)
    return (DECLINED);

  /* Open a connection to the Lisp process.  */
  ML_LOG_DEBUG (r, "open lisp connection");
  CVT_ERROR ((open_lisp_socket (cfg)), "opening connection to Lisp");
  (SERVER_SOCKET_SAFE_P (cfg)) = 0;
  socket = (SERVER_SOCKET (cfg));

  /* Remove any timeout that might be left over from earlier.  */
  ML_LOG_DEBUG (r, "clear socket timeout");
  CVT_ERROR ((apr_socket_timeout_set (socket, (-1))), "clearing read timeout");
  
  /* Convert environment variables to headers and send them.  */
  ML_LOG_DEBUG (r, "write env-var headers");
  ap_add_cgi_vars (r);
  ap_add_common_vars (r);
  if ((r->subprocess_env) != 0)
    CVT_ERROR
      ((copy_headers
	 	((r->subprocess_env), map_env_var_to_lisp_header, socket)),
              "writing to Lisp");

  /* Send this before client headers so ASSOC can be used to grab it
     without worrying about some joker sending a server-id header of
     his own.  (Robert Macomber) */
  ML_LOG_DEBUG (r, "write headers");
  CVT_ERROR ((write_lisp_header (socket, "server-id", (cfg->server_id))),
	     	     "writing to Lisp");

  CVT_ERROR ((write_lisp_header (socket, "server-baseversion", AP_SERVER_BASEVERSION)),
	     	     "writing to Lisp");
  CVT_ERROR ((write_lisp_header (socket, "modlisp-version", VERSION_STRING)),
	     	     "writing to Lisp");
  CVT_ERROR ((write_lisp_header (socket, "modlisp-major-version", "2")),
	     	     "writing to Lisp");
  /* Send all the remaining headers.  */
  if ((r->headers_in) != 0)
    CVT_ERROR
      ((copy_headers ((r->headers_in), map_header_to_lisp_header, socket)),
              "writing to Lisp");

  request_content_length = apr_table_get(r->headers_in, "Content-Length");

  /* Send the end-of-headers marker.  */
  ML_LOG_DEBUG (r, "write end-of-headers");
  CVT_ERROR ((write_lisp_line (socket, "end")), "writing to Lisp");

  /* Send the request entity.  */
  RELAY_HTTP_ERROR (ap_setup_client_block (r, REQUEST_CHUNKED_DECHUNK));
  if (ap_should_client_block (r))
    {
      char buffer [4096];
      ML_LOG_DEBUG (r, "write entity");
      while (1)
	{
	  long n_read = (ap_get_client_block (r, buffer, (sizeof (buffer))));
	  if (n_read < 0)
	    {
	      ML_LOG_PERROR (r, "error reading from client");
	      close_lisp_socket (cfg);
	      return (HTTP_INTERNAL_SERVER_ERROR);
	    }

	  /* for chunked case, when nread == 0, we will write 
	   * a terminating 0.*/
	  
	  {
	    apr_status_t status = APR_SUCCESS; 
	    
	    /* if there's no Content-Type header, the data must be chunked */
	    if (request_content_length == NULL)
	      status = write_lisp_data_chunk (socket, buffer, n_read);
	    else if (n_read != 0)
	      status = write_lisp_data (socket, buffer, n_read);
	    
	    if (APR_SUCCESS != status)
	      {
		while ((ap_get_client_block (r, buffer, sizeof(buffer)))
		       > 0)
		  ;
		ML_LOG_ERROR (status, r, "writing to Lisp");
		close_lisp_socket (cfg);
		return (HTTP_INTERNAL_SERVER_ERROR);
	      }
	  }
	  if( n_read == 0)
	    break;
	}
    }

  /* Set up read timeout so we don't hang forever if Lisp is wedged.  */
  ML_LOG_DEBUG (r, "set socket timeout");
  CVT_ERROR ((apr_socket_timeout_set (socket, READ_TIMEOUT)),
	     	     "setting read timeout");

  /* Read the headers and process them.  */
  ML_LOG_DEBUG (r, "read headers");
  while (1)
    {
      char header_name [4096];
      char header_value [MAX_STRING_LEN];
      CVT_ERROR
	((read_lisp_line (socket, header_name, (sizeof (header_name)))),
	 	 "reading from Lisp");

      if ((strcasecmp (header_name, "end")) == 0)
	break;

      CVT_ERROR
	((read_lisp_line (socket, header_value, (sizeof (header_value)))),
	 	 "reading from Lisp");

      if ((strcasecmp (header_name, "content-type")) == 0)
	{
	  char * tmp = (apr_pstrdup ((r->pool), header_value));
	  ap_content_type_tolower (tmp);
	  (r->content_type) = tmp;
	}
      else if ((strcasecmp (header_name, "status")) == 0)
	{
	  (r->status) = (atoi (header_value));
	  (r->status_line) = (apr_pstrdup ((r->pool), header_value));
	}
      else if ((strcasecmp (header_name, "location")) == 0)
	apr_table_set ((r->headers_out), header_name, header_value);
      else if ((strcasecmp (header_name, "content-length")) == 0)
	{
	  apr_table_set ((r->headers_out), header_name, header_value);
	  content_length = (atoi (header_value));
	}
      else if ((strcasecmp (header_name, "lisp-content-length")) == 0)
	{
	  content_length = (atoi (header_value));
	}
      else if ((strcasecmp (header_name, "last-modified")) == 0)
	{
	  apr_time_t mtime = (apr_date_parse_http (header_value));
	  r->mtime = mtime;
	  ap_set_last_modified (r);
	}
      else if ((strcasecmp (header_name, "keep-socket")) == 0)
	keep_socket_p = (atoi (header_value));
      else if ((strcasecmp (header_name, "log-emerg")) == 0)
	ap_log_error (APLOG_MARK, APLOG_EMERG, APR_SUCCESS, (r->server),
				  		      "%s", header_value);
      else if ((strcasecmp (header_name, "log-alert")) == 0)
	ap_log_error (APLOG_MARK, APLOG_ALERT, APR_SUCCESS, (r->server),
				  		      "%s", header_value);
      else if ((strcasecmp (header_name, "log-crit")) == 0)
	ap_log_error (APLOG_MARK, APLOG_CRIT, APR_SUCCESS, (r->server),
				  		      "%s", header_value);
      else if ((strcasecmp (header_name, "log-error")) == 0)
	ap_log_error (APLOG_MARK, APLOG_ERR, APR_SUCCESS, (r->server),
				  		      "%s", header_value);
      else if ((strcasecmp (header_name, "log-warning")) == 0)
	ap_log_error (APLOG_MARK, APLOG_WARNING, APR_SUCCESS, (r->server),
				  		      "%s", header_value);
      else if ((strcasecmp (header_name, "log-notice")) == 0)
	ap_log_error (APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, (r->server),
				  		      "%s", header_value);
      else if ((strcasecmp (header_name, "log-info")) == 0)
	ap_log_error (APLOG_MARK, APLOG_INFO, APR_SUCCESS, (r->server),
				  		      "%s", header_value);
      else if ((strcasecmp (header_name, "log-debug")) == 0)
	ap_log_error (APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, (r->server),
				  		      "%s", header_value);
      else if ((strcasecmp (header_name, "log")) == 0)
	ap_log_error (APLOG_MARK, APLOG_ERR, APR_SUCCESS, (r->server),
				  		      "%s", header_value);
      else if ((strcasecmp (header_name, "note")) == 0)
	{
	  char * p = (strchr (header_value, ' '));
	  if (p != 0)
	    {
	      (*p++) = '\0';
	      apr_table_setn ((r->notes),
			      			      (apr_pstrdup ((r->pool), header_value)),
						      			      (apr_pstrdup ((r->pool), p)));
	    }
	}
      else if ((strcasecmp (header_name, "set-cookie")) == 0)
	{
	  apr_table_add ((r->headers_out), header_name, header_value);
	}
      else
	apr_table_set ((r->headers_out), header_name, header_value);
    }

  /* Copy the reply entity from Lisp to the client...  */
  //  if (content_length > 0)
  {
    unsigned int n_read = 0;
    input_buffer_t * buffer;

    ML_LOG_DEBUG (r, "read entity");
    CVT_ERROR ((get_input_buffer (socket, (&buffer))), "reading from Lisp");
    while ((buffer->start) <= (buffer->end))
      {
	apr_status_t fill_status;
        unsigned int n_bytes = ((buffer->end) - (buffer->start));
        n_read += n_bytes;
        if ((content_length >= 0) && (n_read > content_length))
          {
            n_bytes -= (n_read - content_length);
            n_read -= (n_read - content_length);
          }
        /* ...unless it's a HEAD request. */
        if (!r->header_only && !write_client_data (r, (buffer->start), n_bytes))
          {
            close_lisp_socket (cfg);
            return (HTTP_INTERNAL_SERVER_ERROR);
          }
        (buffer->start) += n_bytes;
        if (n_read == content_length)
          break;

        fill_status = fill_input_buffer (socket);
        if ((fill_status == APR_EOF) && (content_length < 0))
          break;
        else
          CVT_ERROR (fill_status, "reading from Lisp");
      }
  }
  if ((content_length < 0) || (!keep_socket_p))
    CVT_ERROR ((close_lisp_socket (cfg)), "closing connection to Lisp");
  else
    (SERVER_SOCKET_SAFE_P (cfg)) = 1;
  ML_LOG_DEBUG (r, "request finished");
  return (OK);
}
Exemplo n.º 24
0
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;
}
Exemplo n.º 25
0
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;
}
Exemplo n.º 26
0
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;
}
Exemplo n.º 27
0
/*
 *	ic_handler()
 *	------------
 *	module content handler
 */
static int ic_handler(request_rec *r)
{
	ic_conf_rec *conf_rec;
	BUFF *ic_buff;
	int i,rc;

	if (r->method_number == M_OPTIONS){
		r->allowed |= (1 << M_GET);
		r->allowed |= (1 << M_PUT);
		r->allowed |= (1 << M_POST);
		return DECLINED;
	}

	if ((rc = ap_setup_client_block(r,REQUEST_CHUNKED_ERROR)) != OK)
		return rc;

	/*
	 *	get our configuration
	 */
	conf_rec = (ic_conf_rec *)ap_get_module_config(r->per_dir_config,&interchange_module);
	if (!conf_rec){
		ap_log_reason("interchange-handler not configured properly",r->uri,r);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	/*
	 *	check if the requested URI matches strings in the
	 *	"ordinary file" list.  This module will not handle
	 *	the request if a match is found, and will leave it
	 *	up to Apache to work out what to do with the request
	 */
	for (i = 0; i < conf_rec->ordinarylist_no; i++){
		if (strncmp(r->uri,conf_rec->ordinarylist[i],strlen(conf_rec->ordinarylist[i])) == 0){
			return DECLINED;
		}
	}

	/*
	 *	check if the requested URI matches an entry in the drop list.
	 *	If so then return a 404 (not found) status.  Note that a
	 *	substring match is used
	 */
	for (i = 0; i < conf_rec->droplist_no; i++){
		if (strstr(r->uri,conf_rec->droplist[i])){
			ap_log_reason("interchange-handler match found in the drop list",r->uri,r);
			ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,"Requested URI (%s) matches drop list entry (%s)",r->uri,conf_rec->droplist[i]);
			return HTTP_NOT_FOUND;
		}
	}

	/*
	 *	connect to the Interchange server
	 */
	ic_buff = ic_connect(r,conf_rec);
	if (!ic_buff)
		return HTTP_INTERNAL_SERVER_ERROR;

	/*
	 *	send the client's request to Interchange
	 */
	rc = ic_send_request(r,conf_rec,ic_buff);

	/*
	 *	receive the response from the Interchange server
	 *	and relay that response to the client
	 */
	if (rc == OK)
		rc = ic_transfer_response(r,ic_buff);

	/*
	 *	close the Interchange socket and return
	 */
	ap_bclose(ic_buff);
	return rc;
}
Exemplo n.º 28
0
/* ====================================================================
 * 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;
}
Exemplo n.º 29
0
/* This provides a simple UI for accessing the key database 
 * used to grant access to users owning a yubikey or not.
 *
 * This is primarily a web version of htaccess.
 */
static int authn_yubikey_handler(request_rec *r)
{
    ap_configfile_t *f;
    char l[MAX_STRING_LEN];
    apr_status_t status;
    char *file_password = NULL;
    char *yubiKeyId = NULL;
    char *realName = NULL;
    apr_file_t *dbFormFile = NULL;
    yubiauth_dir_cfg *cfg = ap_get_module_config(r->per_dir_config, &authn_yubikey_module);

    if (strcmp(r->handler, "authn_yubikey")) {
        return DECLINED;
    }
    r->content_type = "text/html";

    /* Post back */
    if (r->method_number == M_POST) {
      const char *postbackContent = NULL;
      char *tmp = NULL;
      char buffer[1024];
      //Read the POST data sent from the client
      ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);

      if ( ap_should_client_block(r) == 1 ) {
              while ( ap_get_client_block(r, buffer, 1024) > 0 ) {
		postbackContent = apr_pstrcat(r->pool, buffer, tmp, NULL);
		//tmp = apr_pstrdup(r->pool, postbackContent);
	          }
      }
      else {
	        ap_rputs("No POST data available",r);
      }
      //We have the data now, now process it and save it into the db
      

      ap_set_content_type(r, "text/plain;");
      ap_rprintf(r, "Postback content: %s", postbackContent);

      return OK;
    }

    /* Serve content if it's a GET request */
    if (!r->header_only) {
      ap_rputs("<html><head><title>YubiAuth user management</title></head><body>", r);
      ap_rputs("<h1>Welcome to the YubiAuth user Mgmt.</h1><br>", r);
      ap_rputs("The following users could be found inside the database:<br>", r);
      //Open userDb file for looped output
      status = ap_pcfg_openfile(&f, r->pool, cfg->userAuthDbFilename);
      if (status != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
                      LOG_PREFIX "Could not open YubiAuthUserDb file: %s", 
		      cfg->userAuthDbFilename);
        return HTTP_INTERNAL_SERVER_ERROR;
      }
      ap_rputs("<table><thead><tr><th>TokenId</th><th>Real Name</th></tr></thead><tbody>\n", r);
      while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
        const char *rpw, *w;

        /* Skip # or blank lines. */
        if ((l[0] == '#') || (!l[0])) {
	  continue;
        }

        rpw = l;
        w = ap_getword(r->pool, &rpw, ':');
	//yubiKeyId = apr_pstrndup(r->pool, password, (apr_size_t) 12);
        //realName = ap_getword(r->pool, &rpw, ':');
	ap_rputs("<tr>", r);
	ap_rprintf(r, "<td>%s</td>", w);
	ap_rprintf(r, "<td>%s</td>\n", rpw);
	ap_rputs("</tr>", r);
      }
      ap_cfg_closefile(f);
      ap_rputs("</tbody></table>", r);
      ap_rputs("<h1>Want to add a user?</h1>.", r);
      ap_rputs("<form name=\"addUser\" method=\"POST\" action=\"/authme\">", r);
      ap_rputs("<input type=\"text\" name=\"tokenId\">", r);
      ap_rputs("<input type=\"text\" name=\"realUser\">", r);
      ap_rputs("<input type=\"submit\" value=\"Add User\">", r);
      ap_rputs("</form>", r);
      ap_rputs("</body></html>", r);
    }

    //If we receive a POST to this location, we probably want to update the userdb
    //be sure to check if there is a user set and that this user is allowed to change information
    // inside the userdb, we cn authenticate the user with the OTP token here too.
    //We should make the administrative user configurable, by specifying the token which is allowed
    // access ...
    return OK;
}
Exemplo n.º 30
0
static int neko_handler_rec( request_rec *r ) {
	mcontext ctx;
	neko_vm *vm;
	const char *ctype;
	value exc = NULL;

/*
	Seems to crash on Windows. And on Linux, we rarely have libGC 7.x installed anyway

#	if defined(APACHE_2_X) || defined(NEKO_WINDOWS)
	// we are using threads, so let's make sure that the current thread is registered
	neko_thread_register(true);
#	endif
*/

	config.hits++;

	ctx.r = r;
	ctx.main = cache_find(r);
	ctx.post_data = val_null;
	ctx.headers_sent = false;
	ctx.content_type = alloc_string("text/html");
    r->content_type = val_string(ctx.content_type);

	if( ap_setup_client_block(r,REQUEST_CHUNKED_ERROR) != 0 ) {
		send_headers(&ctx);
		apache_error(APLOG_WARNING,r,"ap_setup_client_block failed");
		return OK;
	}

	ctype = ap_table_get(r->headers_in,"Content-Type");
	if( (!ctype || strstr(ctype,"multipart/form-data") == NULL) && ap_should_client_block(r) ) {
#		define MAXLEN 1024
		char buf[MAXLEN];
		int len;
		int tlen = 0;
		buffer b = alloc_buffer(NULL);
		while( (len = ap_get_client_block(r,buf,MAXLEN)) > 0 ) {
			if( tlen < config.max_post_size )
				buffer_append_sub(b,buf,len);
			tlen += len;
		}
		if( tlen >= config.max_post_size ) {
			send_headers(&ctx);
			apache_error(APLOG_WARNING,r,"Maximum POST data exceeded. Try using multipart encoding");
			return OK;
		}
		ctx.post_data = buffer_to_string(b);
	}

	vm = neko_vm_alloc(NULL);
	if( config.use_stats ) neko_vm_set_stats(vm,neko_stats_measure,config.use_prim_stats?neko_stats_measure:NULL);

	neko_vm_set_custom(vm,k_mod_neko,&ctx);
	if( config.use_jit && !neko_vm_jit(vm,1) ) {
		send_headers(&ctx);
		apache_error(APLOG_WARNING,r,"JIT required by env. var but not enabled in NekoVM");
		return OK;
	}

	neko_vm_redirect(vm,request_print,&ctx);
	neko_vm_select(vm);

	if( ctx.main != NULL ) {
		value old = ctx.main;
		if( config.use_stats ) neko_stats_measure(vm,r->filename,1);
		val_callEx(val_null,old,NULL,0,&exc);
		if( config.use_stats ) neko_stats_measure(vm,r->filename,0);
		if( old != ctx.main ) cache_module(r->filename,FTIME(r),ctx.main);
	} else {
		char *base_uri = request_base_uri(r);
		value mload = neko_default_loader(&base_uri,1);
		value args[] = { alloc_string(r->filename), mload };
		char *p = strrchr(val_string(args[0]),'.');
		if( p != NULL )
			*p = 0;
		val_callEx(mload,val_field(mload,val_id("loadmodule")),args,2,&exc);
		if( ctx.main != NULL && config.use_cache )
			cache_module(r->filename,FTIME(r),ctx.main);
	}

	if( exc != NULL ) {
		buffer b = alloc_buffer(NULL);
		value v;
		int i;
		const char *p, *start;
		value st = neko_exc_stack(vm);
		val_buffer(b,exc);
		config.exceptions++;
		ap_soft_timeout("Client Timeout",r);
		send_headers(&ctx);
		v = buffer_to_string(b);
		p = val_string(v);
		start = p;
		ap_rprintf(r,"Uncaught exception - ");
		while( *p ) {
			if( *p == '<' || *p == '>' ) {
				ap_rwrite(start,(int)(p - start),r);
				ap_rwrite((*p == '<')?"&lt;":"&gt;",4, r);
				start = p + 1;
			}
			p++;
		}
		ap_rwrite(start,(int)(p - start),r);
		ap_rprintf(r,"<br/><br/>");
		for(i=0;i<val_array_size(st);i++) {
			value s = val_array_ptr(st)[i];
			if( val_is_null(s) )
				ap_rprintf(r,"Called from a C function<br/>");
			else if( val_is_string(s) ) {
				ap_rprintf(r,"Called from %s (no debug available)<br/>",val_string(s));
			} else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) )
				ap_rprintf(r,"Called from %s line %d<br/>",val_string(val_array_ptr(s)[0]),val_int(val_array_ptr(s)[1]));
			else {
				b = alloc_buffer(NULL);
				val_buffer(b,s);
				ap_rprintf(r,"Called from %s<br/>",val_string(buffer_to_string(b)));
			}
		}
		ap_kill_timeout(r);
		return OK;
	}

	send_headers(&ctx);
    return OK;
}