Esempio n. 1
0
/**
 * @short Writes some data to the response. Using sprintf format strings. va_list args version
 *
 * @param args va_list of arguments
 * @memberof onion_response_t
 */
ssize_t onion_response_vprintf(onion_response *res, const char *fmt, va_list args)
{
	char temp[512];
	int l;
	l=vsnprintf(temp, sizeof(temp), fmt, args);
	if (l<0) {
		ONION_ERROR("Invalid vprintf fmt");
		return -1;
	}
	else if (l<sizeof(temp)) {
		return onion_response_write(res, temp, l);
	}
	else {
		ssize_t s;
		char*buf = onion_low_scalar_malloc(l+1);
		if (!buf){
		  // this cannot happen, since onion_low_scalar_malloc
		  // handles that error...
			ONION_ERROR("Could not reserve %d bytes", l+1);
			return -1;
		}
		vsnprintf(buf, l, fmt, args);
		s = onion_response_write (res, buf, l);
		onion_low_free (buf);
		return s;
	}
}
Esempio n. 2
0
/**
 * @short Generates a unique id.
 * @memberof onion_sessions_t
 * @ingroup sessions
 *
 * This unique id is also dificult to guess, so that blind guessing will not work.
 *
 * Just now random 32 bytes string with alphanum chars. Not really safe as using simple C rand.
 *
 * The memory is malloc'ed and will be freed somewhere.
 */
char *onion_sessions_generate_id(){
	char allowed_chars[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

	char *ret=onion_low_scalar_malloc(33);
	onion_random_generate(ret,32);
	int i;
	for (i=0;i<32;i++){
		ret[i]=allowed_chars[ ret[i]%(sizeof(allowed_chars)-1) ];
	}
	ret[i]='\0';
	return ret;
}
Esempio n. 3
0
/**
 * @short Prepares the PUT
 *
 * It saves the data to a temporal file, which name is stored at data.
 */
static onion_connection_status prepare_PUT(onion_request *req){
	onion_token *token=req->parser_data;
	const char *content_size=onion_dict_get(req->headers, "Content-Length");
	if (!content_size){
		ONION_ERROR("I need the Content-Length header to get data");
		return OCS_INTERNAL_ERROR;
	}
	size_t cl=atol(content_size);

	if (cl>req->connection.listen_point->server->max_file_size){
		ONION_ERROR("Trying to PUT a file bigger than allowed size");
		return OCS_INTERNAL_ERROR;
	}

	req->data=onion_block_new();

	char filename[]="/tmp/onion-XXXXXX";
	int fd=mkstemp(filename);
	if (fd<0)
		ONION_ERROR("Could not create temporary file at %s.", filename);

	onion_block_add_str(req->data, filename);
	ONION_DEBUG0("Creating PUT file %s (%d bytes long)", filename, token->extra_size);

	if (!req->FILES){
		req->FILES=onion_dict_new();
	}
	{
	const char *filename=onion_block_data(req->data);
	onion_dict_add(req->FILES,"filename", filename, 0);
	}


	if (cl==0){
		ONION_DEBUG0("Created 0 length file");
		close(fd);
		return OCS_REQUEST_READY;
	}

	int *pfd=onion_low_scalar_malloc(sizeof(fd));
	*pfd=fd;

	assert(token->extra==NULL);
	token->extra=(char*)pfd;
	token->extra_size=cl;
	token->pos=0;

	req->parser=parse_PUT;
	return OCS_NEED_MORE_DATA;
}
Esempio n. 4
0
/**
 * @short Prepares the POST
 */
static onion_connection_status prepare_POST(onion_request *req){
	// ok post
	onion_token *token=req->parser_data;
	const char *content_type=onion_dict_get(req->headers, "Content-Type");
	const char *content_size=onion_dict_get(req->headers, "Content-Length");

	if (!content_size){
		ONION_ERROR("I need the content size header to support POST data");
		return OCS_INTERNAL_ERROR;
	}
	size_t cl=atol(content_size);
	if (cl==0)
		return OCS_REQUEST_READY;

	//ONION_DEBUG("Content type %s",content_type);
	if (!content_type || (strstr(content_type, "application/x-www-form-urlencoded"))){
		if (cl>req->connection.listen_point->server->max_post_size){
			ONION_ERROR("Asked to send much POST data. Limit %d. Failing.",req->connection.listen_point->server->max_post_size);
			return OCS_INTERNAL_ERROR;
		}
		assert(token->extra==NULL);
		token->extra=onion_low_scalar_malloc(cl+1); // Cl + \0
		token->extra_size=cl;
		req->free_list=onion_ptr_list_add(req->free_list, token->extra); // Free when the request is freed.

		req->parser=parse_POST_urlencode;
		return OCS_NEED_MORE_DATA;
	}

	// multipart.

	const char *mp_token=strstr(content_type, "boundary=");
	if (!mp_token){
		ONION_ERROR("No boundary set at content-type");
		return OCS_INTERNAL_ERROR;
	}
	mp_token+=9;
	if (cl>req->connection.listen_point->server->max_post_size) // I hope the missing part is files, else error later.
		cl=req->connection.listen_point->server->max_post_size;

	int mp_token_size=strlen(mp_token);
	token->extra_size=cl; // Max size of the multipart->data
	onion_multipart_buffer *multipart=onion_low_malloc(token->extra_size+sizeof(onion_multipart_buffer)+mp_token_size+2);
	assert(token->extra==NULL);
	token->extra=(char*)multipart;

	multipart->boundary=(char*)multipart+sizeof(onion_multipart_buffer)+1;
	multipart->size=mp_token_size+4;
	multipart->pos=2; // First boundary already have [\r]\n readen
	multipart->post_total_size=cl;
	multipart->file_total_size=0;
	multipart->boundary[0]='\r';
	multipart->boundary[1]='\n';
	multipart->boundary[2]='-';
	multipart->boundary[3]='-';
	strcpy(&multipart->boundary[4],mp_token);
	multipart->data=(char*)multipart+sizeof(onion_multipart_buffer)+multipart->size+1;

	//ONION_DEBUG("Multipart POST boundary '%s'",multipart->boundary);

	req->parser=parse_POST_multipart_start;

	return OCS_NEED_MORE_DATA;
}