Exemple #1
0
void POST_a_lot(void) {
  sleep(1);

  onion_block *tosend = onion_block_new();
  onion_block_add_str(tosend,
                      "POST /configuration HTTP/1.1\nHost: example.com\nContent-Type: x-application/garbage\nContent-Length: 1000000\n\n");

  {
    int i;
    onion_block *bl = onion_block_new();
    for (i = 0; i < 1000; i++) {
      onion_block_add_char(bl, rand() & 255);
    }
    for (i = 0; i < 1000; i++) {
      onion_block_add_block(tosend, bl);
    }
    onion_block_free(bl);
  }

  onion_block *bl = connect_and_send("127.0.0.1", "8080", tosend, 1024 * 64);
  onion_block_free(tosend);

  ONION_DEBUG("%p", strstr(onion_block_data(bl), "\n1000000\n"));
  FAIL_IF_NOT(strstr(onion_block_data(bl), "\n1000000\n") != NULL);

  onion_block_free(bl);
}
Exemple #2
0
void t04_server_overflow(){
	INIT_LOCAL();
	onion *server=onion_new(0);
  onion_listen_point *lp=onion_buffer_listen_point_new();
  onion_add_listen_point(server,NULL,NULL,lp);
	onion_set_root_handler(server, onion_handler_static("Succedded", 200));
	
	onion_block *long_req=onion_block_new();
	
	onion_block_add_str(long_req,"GET / HTTP/1.1\n");
	int i;
	for(i=0;i<1000;i++){
		onion_block_add_str(long_req,"Header-1: This is header1 Header-2: This is header 2 ");
	}
	onion_request *req=onion_request_new(lp);
	onion_request_write(req, onion_block_data(long_req),onion_block_size(long_req)-1); // send it all, but the final 0.
	const char *buffer=onion_buffer_listen_point_get_buffer_data(req);
	FAIL_IF_NOT_EQUAL_STR(buffer,"");
	onion_request_write(req, "\n\n",2); // finish this request. no \n\n before to check possible bugs.

	buffer=onion_buffer_listen_point_get_buffer_data(req);
	FAIL_IF_EQUAL_STR(buffer,"");
	FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n");
	FAIL_IF_NOT_STRSTR(buffer, "\r\nContent-Length: 9\r\n");
	FAIL_IF_NOT_STRSTR(buffer, "libonion");
	FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nSuccedded");

	onion_block_free(long_req);
	onion_request_free(req);
	onion_free(server);

	END_LOCAL();
}
Exemple #3
0
void t02_several_add_methods(){
	INIT_TEST();
	
	onion_block *block=onion_block_new();
	
	FAIL_IF_EQUAL(block, NULL);
	
	int i;
	for (i=0;i<1024;i++){
		onion_block_add_char(block, (char)i);
	}
	onion_block_clear(block);
	
	onion_block_add_str(block, "first ");
	for (i=0;i<1024;i++)
		onion_block_add_str(block, "test ");
	
	FAIL_IF_NOT_STRSTR(onion_block_data(block), "test");
	
	for (i=0;i<1024;i++)
		onion_block_add_data(block, "world", 4);
	
	FAIL_IF_STRSTR(onion_block_data(block), "world");
	FAIL_IF_NOT_STRSTR(onion_block_data(block), "worl");	
	
	int s=onion_block_size(block);
	
	onion_block_add_block(block, block);
	FAIL_IF_NOT_EQUAL(onion_block_size(block), s+s);
	
	onion_block_free(block);
	
	END_TEST();
}
Exemple #4
0
void POST_json(void) {
  sleep(1);

  onion_block *tosend = onion_block_new();
  onion_block_add_str(tosend,
                      "POST /configuration HTTP/1.1\nHost: example.com\nContent-Type: application/json\nContent-Length: 30\n\n"
                      "{\n   \"a\": \"10\",\n   \"b\": \"20\"\n}");
  onion_block *bl = connect_and_send("127.0.0.1", "8080", tosend, 1024 * 1024);

  FAIL_IF_NOT(strstr(onion_block_data(bl), "Done"));
  onion_block_free(bl);
  onion_block_free(tosend);
}
Exemple #5
0
/**
 * @short Prepares the response for propfinds
 * 
 * @param realpath Shared folder
 * @param urlpath URL of the requested propfind
 * @param depth Depth of query, 0 or 1.
 * @param props Properties of the query
 * 
 * @returns An onion_block with the XML data.
 */
onion_block *onion_webdav_write_propfind(const char *basepath, const char *realpath, const char *urlpath, int depth, 
																				 int props){
	onion_block *data=onion_block_new();
	xmlTextWriterPtr writer;
	xmlBufferPtr buf;
	buf = xmlBufferCreate();
	if (buf == NULL) {
		ONION_ERROR("testXmlwriterMemory: Error creating the xml buffer");
		return data;
	}
	writer = xmlNewTextWriterMemory(buf, 0);
	if (writer == NULL) {
		ONION_ERROR("testXmlwriterMemory: Error creating the xml writer");
		return data;
	}
	int error;
	xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL);
	xmlTextWriterStartElement(writer, BAD_CAST "D:multistatus");
		xmlTextWriterWriteAttribute(writer, BAD_CAST "xmlns:D" ,BAD_CAST "DAV:");
			error=onion_webdav_write_props(writer, basepath, realpath, urlpath, NULL, props);
			if (depth>0){
				ONION_DEBUG("Get also all files");
				DIR *dir=opendir(realpath);
				if (!dir){
					ONION_ERROR("Error opening dir %s to check files on it", realpath);
				}
				else{
					struct dirent *de;
					while ( (de=readdir(dir)) ){
						if (de->d_name[0]!='.')
							onion_webdav_write_props(writer, basepath, realpath, urlpath, de->d_name, props);
					}
					closedir(dir);
				}
			}
		xmlTextWriterEndElement(writer);
	xmlTextWriterEndElement(writer);
	
	
	xmlTextWriterEndDocument(writer);
	xmlFreeTextWriter(writer);
	
	onion_block_add_str(data, (const char*)buf->content);
	xmlBufferFree(buf);

	if (error){
		onion_block_free(data);
		return NULL;
	}
	return data;
}
/**
 * @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;
}
Exemple #7
0
void t01_create_and_free(){
	INIT_TEST();
	
	onion_block *block=onion_block_new();
	
	FAIL_IF_EQUAL(block, NULL);
	
	int i;
	for (i=0;i<16*1024;i++){
		onion_block_add_char(block, (char)i);
	}
	
	onion_block_free(block);
	
	END_TEST();
}
Exemple #8
0
/**
 * @short Creates a new function on top of the stack.
 * 
 * It can receive a fmt argument that sets the id. If none, its assigned automatically.
 */
function_data *function_new(parser_status *st, const char *fmt, ...){
	function_data *d=malloc(sizeof(function_data));
	d->flags=0;
	d->code=onion_block_new();
	if (st){
		st->current_code=d->code;
		list_add(st->function_stack, d);
		list_add(st->functions, d);
		//ONION_DEBUG("push function stack, length is %d", list_count(st->function_stack));
	}
	d->signature=NULL;
	
	char tmp[512]; // Here at begining was 128, but somehow it was corrupting stack. Stack cheap here, so no risks.
	if (!fmt){
		d->is_static=1;
		snprintf(tmp, sizeof(tmp), "otemplate_f_%04X",st->function_count++);
	}
	else{
		d->is_static=0;
		va_list va;
		va_start(va, fmt);
		vsnprintf(tmp,sizeof(tmp),fmt,va);
		va_end(va);
		
		char *p=tmp;
		while (*p){
			if (*p=='.')
				*p='_';
      if (*p=='-')
        *p='_';
			p++;
		}
		if (isdigit(tmp[0])){
      memmove(tmp+1,tmp,strlen(tmp)+1);
      tmp[0]='_';
    }
	}
	
	ONION_DEBUG("New function %s", tmp);
	
	
	d->id=strdup(tmp);
	return d;
}
Exemple #9
0
/**
 * @short Converts a dict to a json string
 * @memberof onion_dict_t
 *
 * Given a dictionary and a buffer (with size), it writes a json dictionary to it.
 *
 * @returns an onion_block with the json data, or NULL on error
 */
onion_block *onion_dict_to_json(onion_dict *dict){
	onion_block *block=onion_block_new();

	onion_block_add_char(block, '{');
	if (dict && dict->root)
		onion_dict_node_preorder(dict->root, (void*)onion_dict_json_preorder, block);


	int s=onion_block_size(block);
	if (s==0){ // Error.
		onion_block_free(block);
		return NULL;
	}
	if (s!=1) // To remove a final ", "
		onion_block_rewind(block, 2);

	onion_block_add_char(block, '}');


	return block;
}
Exemple #10
0
/**
 * @short Prepares the CONTENT LENGTH
 */
static onion_connection_status prepare_CONTENT_LENGTH(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_post_size){
		ONION_ERROR("Trying to set more data at server than allowed %d", req->connection.listen_point->server->max_post_size);
		return OCS_INTERNAL_ERROR;
	}

	req->data=onion_block_new();
	
	token->extra=NULL;
	token->extra_size=cl;
	token->pos=0;

	req->parser=parse_CONTENT_LENGTH;
	return OCS_NEED_MORE_DATA;
}
Exemple #11
0
onion_dict *onion_dict_from_json_(const char **_data){
	const char *data=*_data;
	ONION_DEBUG("Parse %s", *_data);
	while (is_json_space(*data))
		++data;
	if (*data!='{')
		return NULL;
	++data;

	while (is_json_space(*data))
		++data;
	;
	onion_dict *ret=onion_dict_new();
	onion_block *key=onion_block_new();
	onion_block *value=onion_block_new();
	while (*data!='}'){
		// Get Key
		ssize_t read_bytes=onion_json_unquote_add(key, data);
		if (read_bytes<0)
			goto error;
		data+=read_bytes;

		while (is_json_space(*data))
			++data;

		/// Get :
		if (*data!=':'){ // Includes \0
			ONION_DEBUG("Expected : got %c", *data);
			goto error;
		}
		++data;
		while (is_json_space(*data))
			++data;

		/// Get Value
		if (*data=='{'){ // Includes \0
			*_data=data;

			onion_dict *sub=onion_dict_from_json_(_data);
			if (!sub){
				goto error;
			}
			onion_dict_add(ret, onion_block_data(key), sub, OD_DUP_KEY|OD_DICT|OD_FREE_VALUE);
			data=*_data;
		}
		else if (is_json_digit(*data)){
			while(is_json_digit(*data)){
				onion_block_add_char(value, *data);
				++data;
			}
			onion_dict_add(ret, onion_block_data(key), onion_block_data(value), OD_DUP_ALL);
		}
		else if (*data=='"'){ // parse string
			ssize_t read_bytes=onion_json_unquote_add(value, data);
			if (read_bytes<0)
				goto error;
			data+=read_bytes;
			onion_dict_add(ret, onion_block_data(key), onion_block_data(value), OD_DUP_ALL);
			onion_block_clear(value);
		}
		else { // Includes \0
			ONION_DEBUG("Expected \" got %c", *data);
			goto error;
		}
		onion_block_clear(key);

		while (is_json_space(*data))
			++data;
		if (*data=='}'){
			++data;
			*_data=data;
			onion_block_free(key);
			onion_block_free(value);
			return ret;
		}
		if (*data!=','){
			ONION_DEBUG("Expected , got %c", *data);
			goto error;
		}
		++data;
		while (is_json_space(*data))
			++data;
	}
	++data;
	*_data=data;
	onion_block_free(key);
	onion_block_free(value);
	return ret;
error:
	onion_block_free(key);
	onion_block_free(value);
	onion_dict_free(ret);
	return NULL;
}
Exemple #12
0
onion_block *connect_and_send(const char *ip, const char *port,
                              const onion_block * msg, size_t maxsize) {
  int fd;
  {
    struct addrinfo hints;
    struct addrinfo *server;

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_UNSPEC;
    hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;

    if (getaddrinfo(ip, port, &hints, &server) < 0) {
      ONION_ERROR("Error getting server info");
      return NULL;
    }
    fd = socket(server->ai_family, server->ai_socktype | SOCK_CLOEXEC,
                server->ai_protocol);

    if (connect(fd, server->ai_addr, server->ai_addrlen) == -1) {
      close(fd);
      fd = -1;
      ONION_ERROR("Error connecting to server %s:%s", ip, port);
      return NULL;
    }

    freeaddrinfo(server);
  }

  size_t left = onion_block_size(msg);
  const char *data = onion_block_data(msg);
  while (left > 0) {
    ONION_DEBUG(".");
    int towrite = (left > maxsize) ? maxsize : left;
    int ret = write(fd, data, towrite);
    FAIL_IF(ret <= 0);
    if (ret <= 0) {
      ONION_ERROR("Error sending data.");
      return NULL;
    }
    left -= ret;
    data += ret;
  }
  onion_block *bl = onion_block_new();
  char tmp[256];
  int r = 0;
  int total = 0;
  do {
    r = read(fd, tmp, sizeof(tmp));
    ONION_DEBUG("+ %d", r);
    if (r > 0) {
      total += r;
      onion_block_add_data(bl, tmp, r);
    }
  } while (r > 0);
  ONION_DEBUG("Total %d", total);

  FAIL_IF(total == 0);

  close(fd);

  return bl;
}
Exemple #13
0
/**
 * @short Compiles the infilename to outfilename.
 */
int work(const char *infilename, const char *outfilename, onion_assets_file *assets){
	tag_init();
	parser_status status;
	memset(&status, 0, sizeof(status));
	status.mode=TEXT;
	status.functions=list_new((void*)function_free);
	status.function_stack=list_new(NULL);
	status.status=0;
	status.line=1;
	status.rawblock=onion_block_new();
	status.infilename=infilename;
	char tmp2[256];
	strncpy(tmp2, infilename, sizeof(tmp2)-1);
	const char *tname=basename(tmp2);
  ONION_DEBUG("Create init function on top, tname %s",tname);
	status.blocks_init=function_new(&status, "%s_blocks_init", tname);
	status.blocks_init->signature="onion_dict *context";
	
	if (strcmp(infilename, "-")==0)
		status.in=stdin;
	else
		status.in=fopen(infilename,"rt");
	
	if (!status.in){
		ONION_ERROR("Could not open in file %s", infilename);
		goto work_end;
	}

	ONION_DEBUG("Create main function on top, tname %s",tname);
	function_new(&status, tname);
	
	function_add_code(&status, 
"  int has_context=(context!=NULL);\n"
"  if (!has_context)\n"
"    context=onion_dict_new();\n"
"  \n"
"  %s(context);\n",  status.blocks_init->id);
	
	parse_template(&status);
	
	((function_data*)status.function_stack->tail->data)->flags=0;
	
	function_add_code(&status,
"  if (!has_context)\n"
"    onion_dict_free(context);\n"
	);
	
	if (status.status){
		ONION_ERROR("Parsing error");
		goto work_end;
	}

	if (strcmp(outfilename, "-")==0)
		status.out=stdout;
	else
		status.out=fopen(outfilename,"wt");
	if (!status.out){
		ONION_ERROR("Could not open out file %s", infilename);
		goto work_end;
	}
	
	fprintf(status.out,
"/** Autogenerated by otemplate v. 0.2.0 */\n"
"\n"
"#include <libintl.h>\n"
"#include <string.h>\n\n"
"#include <onion/onion.h>\n"
"#include <onion/dict.h>\n"
"\n"
"typedef struct dict_res_t{\n"
"	onion_dict *dict;\n"
"	onion_response *res;\n"
"}dict_res;\n"
"\n"
"\n");

	functions_write_declarations_assets(&status, assets);
	
	functions_write_declarations(&status);

	functions_write_main_code(&status);

	if (use_orig_line_numbers)
		fprintf(status.out, "#line 1 \"%s\"\n", infilename);

	functions_write_code(&status);

work_end:
	if (status.in)
		fclose(status.in);
	if (status.out)
		fclose(status.out);
	list_free(status.functions);
	list_free(status.function_stack);
	//list_free(status.blocks);
	onion_block_free(status.rawblock);
	
	tag_free();
	return status.status;
}
Exemple #14
0
/**
 * @short Solves a variable into code.
 * 
 * It uses the type to check it its a literal string, a dcit string or a dict.
 */
void variable_solve(parser_status *st, const char *data, const char *tmpname, vartype_e type){
	if (type==LITERAL){
		char *s=onion_c_quote_new(data);
		function_add_code(st,
"    %s=%s;\n", tmpname, s);
		free(s);
		return;
	}
	if (! (type==STRING || type==DICT) ){
		ONION_ERROR("Invalid type for variable solve");
		exit(1);
	}
	
	
	list *parts=list_new(onion_block_free);
	onion_block *lastblock;
	list_add(parts, lastblock=onion_block_new());
	
	
	int i=0;
	int l=strlen(data);
	const char *d=data;
	for (i=0;i<l;i++){
		if (d[i]=='.')
			list_add(parts, lastblock=onion_block_new());
		else if (d[i]==' ')
			continue;
		else
			onion_block_add_char(lastblock, d[i]);
	}

	if (list_count(parts)==1){
		char *s=onion_c_quote_new(onion_block_data(lastblock));
		if (type==STRING)
			function_add_code(st, 
	"    %s=onion_dict_get(context, %s);\n", tmpname, s);
		else if (type==DICT)
			function_add_code(st, 
	"    %s=onion_dict_get_dict(context, %s);\n", tmpname, s);
		free(s);
	}
	else{
		if (type==STRING)
			function_add_code(st,"    %s=onion_dict_rget(context", tmpname);
		else if (type==DICT)
			function_add_code(st,"    %s=onion_dict_rget_dict(context", tmpname);
		else{
			ONION_ERROR("Invalid type for variable solve");
			exit(1);
		}
		list_item *it=parts->head;
		while (it){
			lastblock=it->data;
			char *s=onion_c_quote_new(onion_block_data(lastblock));
			function_add_code(st,", %s", s);
			free(s);
			it=it->next;
		}
		function_add_code(st,", NULL);\n");
	}
	list_free(parts);
}
Exemple #15
0
onion_dict *onion_dict_from_json_(const char **_data){
	const char *data=*_data;
	ONION_DEBUG("Parse %s", *_data);
	while (isspace(SAFETY_CAST(*data)))
		++data;
	if (*data!='{')
		return NULL;
	++data;
	
	while (isspace(SAFETY_CAST(*data)))
		++data;
	;
	onion_dict *ret=onion_dict_new();
	onion_block *key=onion_block_new();
	onion_block *value=onion_block_new();
	while (*data!='}'){
		// Get Key
		if (*data!='"'){ // Includes \0
			ONION_DEBUG("Expected \" got %c", *data);
			goto error;
		}
		++data;
		while (*data!='"'){
			if (!*data){ // \0
				ONION_DEBUG("Expected \" got eof");
				goto error;
			}
			onion_block_add_char(key, *data);
			++data;
		}
		++data;
		while (isspace(SAFETY_CAST(*data)))
			++data;

		/// Get :
		if (*data!=':'){ // Includes \0
			ONION_DEBUG("Expected : got %c", *data);
			goto error;
		}
		++data;
		while (isspace(SAFETY_CAST(*data)))
			++data;

		/// Get Value
		if (*data=='{'){ // Includes \0
			*_data=data;

			onion_dict *sub=onion_dict_from_json_(_data);
			if (!sub){
				goto error;
			}
			onion_dict_add(ret, onion_block_data(key), sub, OD_DUP_KEY|OD_DICT|OD_FREE_VALUE);
			data=*_data;
		}
		else if (isdigit(SAFETY_CAST(*data))){
			while(isdigit(SAFETY_CAST(*data))){
				onion_block_add_char(value, *data);
				++data;
			}
			onion_dict_add(ret, onion_block_data(key), onion_block_data(value), OD_DUP_ALL);
		}
		else if (*data=='"'){
			++data;
			while (*data!='"'){
				if (!*data){ // \0
					ONION_DEBUG("Expected \" got eof");
					goto error;
				}
				onion_block_add_char(value, *data);
				++data;
			}
			++data;

			onion_dict_add(ret, onion_block_data(key), onion_block_data(value), OD_DUP_ALL);
			onion_block_clear(value);
		}
		else { // Includes \0
			ONION_DEBUG("Expected \" got %c", *data);
			goto error;
		}
		onion_block_clear(key);
		
		while (isspace(SAFETY_CAST(*data)))
			++data;
		if (*data=='}'){
			++data;
			*_data=data;
			onion_block_free(key);
			onion_block_free(value);
			return ret;
		}
		if (*data!=','){
			ONION_DEBUG("Expected , got %c", *data);
			goto error;
		}
		++data;
		while (isspace(SAFETY_CAST(*data)))
			++data;
	}
	++data;
	*_data=data;
	onion_block_free(key);
	onion_block_free(value);
	return ret;
error:
	onion_block_free(key);
	onion_block_free(value);
	onion_dict_free(ret);
	return NULL;
}