Example #1
0
static int do_print( void *_c, const char *buf, int len ) {
	mcontext *c = (mcontext*)_c;
	ap_soft_timeout("Client Timeout",c->r);
	send_headers(c);
	ap_rwrite(buf,len,c->r);
	ap_kill_timeout(c->r);
	return c->r->connection->aborted == 0;
}
Example #2
0
static void request_print( const char *data, int size, void *_c ) {
	mcontext *c = (mcontext *)_c;
	if( c == NULL ) c = CONTEXT();
	if( size == -1 ) size = (int)strlen(data);
	ap_soft_timeout("Client Timeout",c->r);
	send_headers(c);
	ap_rwrite(data,size,c->r);
	ap_kill_timeout(c->r);
}
Example #3
0
static int handle_request(request_rec *r)
{
	tmcdreq_t tmcdreq, *reqp = &tmcdreq;
	tmcdresp_t *response = NULL;
	char *command;
	struct in_addr local_addr;
	struct in_addr remote_addr;
	struct sockaddr_in redir_client;
	int tmcd_status;
	int status = OK;
	char *status_line = NULL;
	char *args = NULL;
	char *function_args = NULL;
	char *p;
	char **argv = NULL;
	int argc, i;

	reqp->istcp = 1;
	reqp->isssl = 1; /* FIXME */

	if (strcmp(r->handler, "tmcd")) {
		status = DECLINED;
		goto err;
	}

#if 0
	r->allowed |= (AP_METHOD_BIT << M_GET);
	if (r->method_number != M_GET) {
		status = DECLINED;
		goto err;
	}
#endif

	memset(reqp, 0, sizeof(*reqp));

	local_addr = r->connection->local_addr.sin_addr;
	remote_addr = r->connection->remote_addr.sin_addr;

	reqp->version = 1; /* FIXME need sane default */
	tmcd_init(reqp, &local_addr, NULL);

	command = r->path_info;
	while (*command && *command == '/') {
		command++;
	}
	if (command[0] == '\0') {
		status = HTTP_BAD_REQUEST;
		goto err;
	}

	if (r->args) {
		args = malloc(strlen(r->args) + 1);
		if (args == NULL) {
			status = HTTP_INTERNAL_SERVER_ERROR;
			goto err;
		}

		strcpy(args, r->args);
		argv = make_argv(args, &argc, '&');
		if (argv == NULL) {
			status = HTTP_INTERNAL_SERVER_ERROR;
			goto err;
		}

		for (i = 0; i < argc; i++) {
			/* Unescape the arguments */
			p = args;
			while (*p) {
				if (*p == '+')
					*p = ' ';
				p++;
			}

			status = ap_unescape_url(args);
			if (status != OK) {
				goto err;
			}

			if (strncasecmp(argv[i], "version=", 8) == 0) {
				long version;
				char *end;
				version = strtol(argv[i] + 8, &end, 10);
				if (*end != '\0' || *(argv[i] + 8) == '\0') {
					status = HTTP_BAD_REQUEST;
					status_line = "Invalid Version";
					goto err;
				}

				reqp->version = version;
			} else if (strncasecmp(argv[i], "redirect=", 9) == 0) {
				if (inet_pton(AF_INET, argv[i] + 9,
				              &redir_client.sin_addr) <= 0) {
					status = HTTP_BAD_REQUEST;
					status_line = "Invalid IP Address";
					goto err;
				}
				/* FIXME info message */

				if (remote_addr.s_addr != local_addr.s_addr) {
					status = HTTP_FORBIDDEN;
					status_line = "Redirection Not Allowed";
					goto err;
				}

				remote_addr =
				    redir_client.sin_addr;

			} else if (strncasecmp(argv[i], "vnodeid=", 8) == 0) {
				if (strlen(argv[i] + 8) >=
				           sizeof(reqp->vnodeid)) {
					status = HTTP_BAD_REQUEST;
					status_line =
					    "Virtual Node ID Too Long";
					goto err;
				}
				reqp->isvnode = 1;
				strcpy(reqp->vnodeid, argv[i] + 8);
			} else if (strncasecmp(argv[i], "args=", 5) == 0) {
				function_args = argv[i] + 5;
			}
		}

	}

	/* FIXME handle wanodekey */
	if ((tmcd_status = iptonodeid(reqp, remote_addr, NULL))) {
		if (reqp->isvnode) {
			status_line = "Invalid Virtual Node";
		}
		else {
			status_line = "Invalid Node";
		}
		status = HTTP_NOT_FOUND;
		goto err;
	}

	if (reqp->tmcd_redirect[0]) {
		/* FIXME what if https should be used? */
		/* FIXME do I need to specify the args should be passed too? */
		char *uri = ap_psprintf(r->pool, "http://%s%s?%s", reqp->tmcd_redirect,
		                        r->uri, r->args);
		ap_table_setn(r->headers_out, "Location", uri);
		status = HTTP_MOVED_TEMPORARILY;
		goto done;
	}

	tmcd_status = tmcd_handle_request(reqp, &response, command,
	                                  function_args);

	if (tmcd_status == TMCD_STATUS_OK) {
		r->content_type = response->type;
		ap_set_content_length(r, response->length);
		/* FIXME doctype */
		ap_soft_timeout("tmcd response call trace", r);
		ap_send_http_header(r);
		ap_rprintf(r, "%s", response->data);
		ap_kill_timeout(r);
		status = OK;
		goto done;
	} else {
		switch(tmcd_status) {
			case TMCD_STATUS_UNKNOWN_COMMAND:
				status = HTTP_NOT_FOUND;
				status_line = "Unknown Command";
				break;
			case TMCD_STATUS_REQUIRES_ENCRYPTION:
				status = HTTP_FORBIDDEN;
				status_line = "SSL Required";
				break;
			case TMCD_STATUS_NODE_NOT_ALLOCATED:
				status = HTTP_FORBIDDEN;
				status_line = "Node Not Allocated";
				break;
			case TMCD_STATUS_COMMAND_FAILED:
				status = HTTP_INTERNAL_SERVER_ERROR;
				if (response && response->data) {
					status_line = response->data;
				}
				break;
			case TMCD_STATUS_MALLOC_FAILED:
				status = HTTP_INTERNAL_SERVER_ERROR;
				break;
		}

		goto err;
	}
err:
done:
	if (argv)
		free(argv);

	if (args)
		free(args);

	if (response)
		tmcd_free_response(response);

	if (status_line) {
		r->status_line = ap_psprintf(r->pool, "%3.3u %s", status,
		                             status_line);
	}
	return status;
}
/*
 *	ic_transfer_response()
 *	----------------------
 *	Read the response from the Interchange server
 *	and relay it to the client
 */
static int ic_transfer_response(request_rec *r,BUFF *ic_buff)
{
	const char *location;
	int rc,ic_sock;
	char sbuf[MAX_STRING_LEN],argsbuffer[MAX_STRING_LEN];

	/*
	 *	get the socket we are using to talk to the
	 *	Interchange server, and wait for Interchange to
	 *	send us some data
	 */
	ic_sock = ap_bfileno(ic_buff,B_RD);
	rc = ic_select(ic_sock,0,IC_DEFAULT_TIMEOUT,0);
	if (rc < 0){
		ap_log_reason("Failed to select the response header",r->uri,r);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	/*
	 *	check the HTTP header to make sure that it looks valid
	 */
	if ((rc = ap_scan_script_header_err_buff(r,ic_buff,sbuf)) != OK) {
		if (rc == HTTP_INTERNAL_SERVER_ERROR) {
			ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,"Malformed header return by Interchange: %s",sbuf);
		}
		return rc;
	}

	/*
	 *	check the header for an HTTP redirect request
	 */
	location = ap_table_get(r->headers_out,"Location");
	if (r->status == 200 && location){
		fd_set sock_set;

		/*
		 *	check if we need to do an external redirect
		 */
		if (*location != '/')
			return REDIRECT;

		/*
		 *	we are here because we need to do an internal redirect
		 *
		 *	soak up any data from the Interchange socket
		 */
		rc = ic_select(ic_sock,0,IC_DEFAULT_TIMEOUT,0);
		if (rc < 0){
			ap_log_reason("Failed to select the response text",r->uri,r);
			return HTTP_INTERNAL_SERVER_ERROR;
		}

		/*
		 *	soak up any body-text sent by the Interchange server
		 */
		ap_soft_timeout("mod_interchange: Interchange read",r);
		while (ap_bgets(argsbuffer,MAX_STRING_LEN,ic_buff) > 0)
			;
		ap_kill_timeout(r);

		/*
		 *	always use the GET method for internal redirects
		 *	also, unset the Content-Length so that nothing
		 *	else tries to re-read the text we just soaked up
		 */
		r->method = ap_pstrdup(r->pool,"GET");
		r->method_number = M_GET;
		ap_table_unset(r->headers_in,"Content-Length");
		ap_internal_redirect(location,r);
		return OK;
	}

	/*
	 *	we were not redirected, so send the HTTP headers
	 *	to the client
	 */
	ap_hard_timeout("mod_interchange: Client write",r);
	ap_send_http_header(r);
	if (ap_rflush(r) < 0){
		ap_log_reason("error sending headers to client",r->uri,r);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	/*
	 *	if Interchange is sending body text (HTML), then
	 *	relay this to the client
	 */
	if (!r->header_only){
		ap_reset_timeout(r);
		if ((rc = ap_bnonblock(ic_buff,B_RD)) != 0){
			ap_log_reason("error turning non blocking I/O on Interchange socket",r->uri,r);
			return HTTP_INTERNAL_SERVER_ERROR;
		}
		ap_bsetflag(ic_buff,B_SAFEREAD,1);
		if (ap_send_fb(ic_buff,r) <= 0){
			ap_log_reason("error sending response body to client",r->uri,r);
			return HTTP_INTERNAL_SERVER_ERROR;
		}
	}
	ap_kill_timeout(r);
	return OK;
}
Example #5
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);
}
Example #6
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;
}
Example #7
0
static PyObject * req_readline(requestobject *self, PyObject *args)
{

    int rc, chunk_len, bytes_read;
    char *buffer;
    PyObject *result;
    int copied = 0;
    int len = -1;

    if (! PyArg_ParseTuple(args, "|i", &len)) 
	return NULL;

    if (len == 0) {
	return PyString_FromString("");
    }

    /* is this the first read? */
    if (! self->request_rec->read_length) {

	/* then do some initial setting up */
	rc = ap_setup_client_block(self->request_rec, REQUEST_CHUNKED_ERROR);

	if(rc != OK) {
	    PyObject *val = PyInt_FromLong(rc);
	    if (val == NULL)
		return NULL;
	    PyErr_SetObject(Mp_ServerReturn, val);
	    Py_DECREF(val);
	    return NULL;
	}

	if (! ap_should_client_block(self->request_rec)) {
	    /* client has nothing to send */
	    return PyString_FromString("");
	}
    }

    if (len < 0)
	len = self->request_rec->remaining + 
	    (self->rbuff_len - self->rbuff_pos);

    /* create the result buffer */
    result = PyString_FromStringAndSize(NULL, len);

    /* possibly no more memory */
    if (result == NULL) 
	return NULL;

    buffer = PyString_AS_STRING((PyStringObject *) result);

    /* is there anything left in the rbuff from previous reads? */
    if (self->rbuff_pos < self->rbuff_len) {
	
	/* if yes, process that first */
	while (self->rbuff_pos < self->rbuff_len) {

	    buffer[copied++] = self->rbuff[self->rbuff_pos];
	    if ((self->rbuff[self->rbuff_pos++] == '\n') || 
		(copied == len)) {

		/* our work is done */

		/* resize if necessary */
		if (copied < len) 
		    if(_PyString_Resize(&result, copied))
			return NULL;

		return result;
	    }
	}
    }

    /* if got this far, the buffer should be empty, we need to read more */
	
    /* create a read buffer */
    self->rbuff_len = len > HUGE_STRING_LEN ? len : HUGE_STRING_LEN;
    self->rbuff_pos = self->rbuff_len;
    self->rbuff = ap_palloc(self->request_rec->pool, self->rbuff_len);
    if (! self->rbuff)
	return PyErr_NoMemory();

    /* set timeout */
    ap_soft_timeout("mod_python_read", self->request_rec);

    /* read it in */
    Py_BEGIN_ALLOW_THREADS
	chunk_len = ap_get_client_block(self->request_rec, self->rbuff, 
					self->rbuff_len);
    Py_END_ALLOW_THREADS;
    bytes_read = chunk_len;

    /* if this is a "short read", try reading more */
    while ((chunk_len != 0 ) && (bytes_read + copied < len)) {
	Py_BEGIN_ALLOW_THREADS
	    chunk_len = ap_get_client_block(self->request_rec, 
					    self->rbuff + bytes_read, 
					    self->rbuff_len - bytes_read);
	Py_END_ALLOW_THREADS
	    ap_reset_timeout(self->request_rec);
	if (chunk_len == -1) {
	    ap_kill_timeout(self->request_rec);
	    PyErr_SetObject(PyExc_IOError, 
			    PyString_FromString("Client read error (Timeout?)"));
	    return NULL;
	}
	else
	    bytes_read += chunk_len;
    }
    self->rbuff_len = bytes_read;
    self->rbuff_pos = 0;
    ap_kill_timeout(self->request_rec);

    /* now copy the remaining bytes */
    while (self->rbuff_pos < self->rbuff_len) {

	buffer[copied++] = self->rbuff[self->rbuff_pos];
	if ((self->rbuff[self->rbuff_pos++] == '\n') || 
	    (copied == len)) 
	    /* our work is done */
	    break;
    }

    /* resize if necessary */
    if (copied < len) 
	if(_PyString_Resize(&result, copied))
	    return NULL;

    return result;
}
Example #8
0
static PyObject * req_read(requestobject *self, PyObject *args)
{

    int rc, bytes_read, chunk_len;
    char *buffer;
    PyObject *result;
    int copied = 0;
    int len = -1;

    if (! PyArg_ParseTuple(args, "|i", &len)) 
	return NULL;

    if (len == 0) {
	return PyString_FromString("");
    }

    /* is this the first read? */
    if (! self->request_rec->read_length) {

	/* then do some initial setting up */

	rc = ap_setup_client_block(self->request_rec, REQUEST_CHUNKED_ERROR);
	if(rc != OK) {
	    PyObject *val = PyInt_FromLong(rc);
	    if (val == NULL)
		return NULL;
	    PyErr_SetObject(Mp_ServerReturn, val);
	    Py_DECREF(val);
	    return NULL;
	}

	if (! ap_should_client_block(self->request_rec)) {
	    /* client has nothing to send */
	    return PyString_FromString("");
	}
    }

    if (len < 0)
	len = self->request_rec->remaining +
	    (self->rbuff_len - self->rbuff_pos);

    result = PyString_FromStringAndSize(NULL, len);

    /* possibly no more memory */
    if (result == NULL) 
	return NULL;

    buffer = PyString_AS_STRING((PyStringObject *) result);

    /* if anything left in the readline buffer */
    while ((self->rbuff_pos < self->rbuff_len) && (copied < len))
	buffer[copied++] = self->rbuff[self->rbuff_pos++];
    
    if (copied == len)
	return result; 	/* we're done! */

    /* set timeout */
    ap_soft_timeout("mod_python_read", self->request_rec);

    /* read it in */
    Py_BEGIN_ALLOW_THREADS
    chunk_len = ap_get_client_block(self->request_rec, buffer, len);
    Py_END_ALLOW_THREADS
    bytes_read = chunk_len;

    /* if this is a "short read", try reading more */
    while ((bytes_read < len) && (chunk_len != 0)) {
	Py_BEGIN_ALLOW_THREADS
	chunk_len = ap_get_client_block(self->request_rec, 
					buffer+bytes_read, len-bytes_read);
	Py_END_ALLOW_THREADS
	ap_reset_timeout(self->request_rec);
	if (chunk_len == -1) {
	    ap_kill_timeout(self->request_rec);
	    PyErr_SetObject(PyExc_IOError, 
			    PyString_FromString("Client read error (Timeout?)"));
	    return NULL;
	}
	else
	    bytes_read += chunk_len;
    }

    ap_kill_timeout(self->request_rec);

    /* resize if necessary */
    if (bytes_read < len) 
	if(_PyString_Resize(&result, bytes_read))
	    return NULL;

    return result;
}
Example #9
0
/* 
 * Sample content handler.  All this does is display the call list that has
 * been built up so far.
 *
 * The return value instructs the caller concerning what happened and what to
 * do next:
 *  OK ("we did our thing")
 *  DECLINED ("this isn't something with which we want to get involved")
 *  HTTP_mumble ("an error status should be reported")
 */
static int example_handler(request_rec *r)
{

    excfg *dcfg;

    dcfg = our_dconfig(r);
    trace_add(r->server, r, dcfg, "example_handler()");
    /*
     * We're about to start sending content, so we need to force the HTTP
     * headers to be sent at this point.  Otherwise, no headers will be sent
     * at all.  We can set any we like first, of course.  **NOTE** Here's
     * where you set the "Content-type" header, and you do so by putting it in
     * r->content_type, *not* r->headers_out("Content-type").  If you don't
     * set it, it will be filled in with the server's default type (typically
     * "text/plain").  You *must* also ensure that r->content_type is lower
     * case.
     *
     * We also need to start a timer so the server can know if the connexion
     * is broken.
     */
    r->content_type = "text/html";

    ap_soft_timeout("send example call trace", r);
    ap_send_http_header(r);
#ifdef CHARSET_EBCDIC
    /* Server-generated response, converted */
    ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1);
#endif

    /*
     * If we're only supposed to send header information (HEAD request), we're
     * already there.
     */
    if (r->header_only) {
        ap_kill_timeout(r);
        return OK;
    }

    /*
     * Now send our actual output.  Since we tagged this as being
     * "text/html", we need to embed any HTML.
     */
    ap_rputs(DOCTYPE_HTML_3_2, r);
    ap_rputs("<HTML>\n", r);
    ap_rputs(" <HEAD>\n", r);
    ap_rputs("  <TITLE>mod_example Module Content-Handler Output\n", r);
    ap_rputs("  </TITLE>\n", r);
    ap_rputs(" </HEAD>\n", r);
    ap_rputs(" <BODY>\n", r);
    ap_rputs("  <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r);
    ap_rputs("  </H1>\n", r);
    ap_rputs("  <P>\n", r);
    ap_rprintf(r, "  Apache HTTP Server version: \"%s\"\n",
	    ap_get_server_version());
    ap_rputs("  <BR>\n", r);
    ap_rprintf(r, "  Server built: \"%s\"\n", ap_get_server_built());
    ap_rputs("  </P>\n", r);;
    ap_rputs("  <P>\n", r);
    ap_rputs("  The format for the callback trace is:\n", r);
    ap_rputs("  </P>\n", r);
    ap_rputs("  <DL>\n", r);
    ap_rputs("   <DT><EM>n</EM>.<SAMP>&lt;routine-name&gt;", r);
    ap_rputs("(&lt;routine-data&gt;)</SAMP>\n", r);
    ap_rputs("   </DT>\n", r);
    ap_rputs("   <DD><SAMP>[&lt;applies-to&gt;]</SAMP>\n", r);
    ap_rputs("   </DD>\n", r);
    ap_rputs("  </DL>\n", r);
    ap_rputs("  <P>\n", r);
    ap_rputs("  The <SAMP>&lt;routine-data&gt;</SAMP> is supplied by\n", r);
    ap_rputs("  the routine when it requests the trace,\n", r);
    ap_rputs("  and the <SAMP>&lt;applies-to&gt;</SAMP> is extracted\n", r);
    ap_rputs("  from the configuration record at the time of the trace.\n", r);
    ap_rputs("  <STRONG>SVR()</STRONG> indicates a server environment\n", r);
    ap_rputs("  (blank means the main or default server, otherwise it's\n", r);
    ap_rputs("  the name of the VirtualHost); <STRONG>DIR()</STRONG>\n", r);
    ap_rputs("  indicates a location in the URL or filesystem\n", r);
    ap_rputs("  namespace.\n", r);
    ap_rputs("  </P>\n", r);
    ap_rprintf(r, "  <H2>Static callbacks so far:</H2>\n  <OL>\n%s  </OL>\n",
            trace);
    ap_rputs("  <H2>Request-specific callbacks so far:</H2>\n", r);
    ap_rprintf(r, "  <OL>\n%s  </OL>\n", ap_table_get(r->notes, TRACE_NOTE));
    ap_rputs("  <H2>Environment for <EM>this</EM> call:</H2>\n", r);
    ap_rputs("  <UL>\n", r);
    ap_rprintf(r, "   <LI>Applies-to: <SAMP>%s</SAMP>\n   </LI>\n", dcfg->loc);
    ap_rprintf(r, "   <LI>\"Example\" directive declared here: %s\n   </LI>\n",
            (dcfg->local ? "YES" : "NO"));
    ap_rprintf(r, "   <LI>\"Example\" inherited: %s\n   </LI>\n",
            (dcfg->congenital ? "YES" : "NO"));
    ap_rputs("  </UL>\n", r);
    ap_rputs(" </BODY>\n", r);
    ap_rputs("</HTML>\n", r);
    /*
     * We're all done, so cancel the timeout we set.  Since this is probably
     * the end of the request we *could* assume this would be done during
     * post-processing - but it's possible that another handler might be
     * called and inherit our outstanding timer.  Not good; to each its own.
     */
    ap_kill_timeout(r);
    /*
     * We did what we wanted to do, so tell the rest of the server we
     * succeeded.
     */
    return OK;
}