Beispiel #1
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();
}
Beispiel #2
0
/// Writes the desired function to st->out
static void function_write(parser_status *st, function_data *d){
	if (d->code){
		if (use_orig_line_numbers)
			fprintf(st->out, "#line 1\n");
		if (d->is_static)
			fprintf(st->out, "static ");
		fprintf(st->out, 
"void %s(%s){\n", d->id, d->signature ? d->signature : "onion_dict *context, onion_response *res"
					);
		
		if (use_orig_line_numbers){
			fprintf(st->out, "#line 1\n");
		
			// Write code, but change \n\n to \n
			const char *data=onion_block_data(d->code);
			int ldata=onion_block_size(d->code);
			int i=0, li=0;
			char lc=0;
			for (i=0;i<ldata;i++){
				if (data[i]=='\n' && lc=='\n'){ // Two in a row
					fwrite(&data[li], 1, i-li-1, st->out);
					li=i;
				}
				lc=data[i];
			}
			fwrite(&data[li], 1, i-li, st->out);
			fprintf(st->out, "#line 1\n");
		}
		else{
			fwrite(onion_block_data(d->code), 1, onion_block_size(d->code), st->out);
		}

		fprintf(st->out,"}\n");
	}
}
Beispiel #3
0
onion_connection_status return_length(void *_, onion_request * req,
                                      onion_response * res) {
  ONION_DEBUG("Data size: %d", onion_block_size(onion_request_get_data(req)));
  onion_response_printf(res, "%ld\n",
                        onion_block_size(onion_request_get_data(req)));

  return OCS_PROCESSED;
}
Beispiel #4
0
/**
 * @short Handles a propfind
 * 
 * @param path the shared path.
 */
onion_connection_status onion_webdav_propfind(const char *filename, onion_webdav *wd, onion_request* req, onion_response* res){
	// Prepare the basepath, necesary for props.
	char *basepath=NULL;
	int pathlen=0;
	const char *current_path=onion_request_get_path(req);
	const char *fullpath=onion_request_get_fullpath(req);
	pathlen=(current_path-fullpath);
	basepath=alloca(pathlen+1);
	memcpy(basepath, fullpath, pathlen+1);
	ONION_DEBUG0("Pathbase initial <%s> %d", basepath, pathlen); 
	while(basepath[pathlen]=='/' && pathlen>0)
		pathlen--;
	basepath[pathlen+1]=0;
				 
	ONION_DEBUG0("PROPFIND; pathbase %s", basepath);
	int depth;
	{
		const char *depths=onion_request_get_header(req, "Depth");
		if (!depths){
			ONION_ERROR("Missing Depth header on webdav request");
			return OCS_INTERNAL_ERROR;
		}
		if (strcmp(depths,"infinity")==0){
			ONION_ERROR("Infinity depth not supported yet.");
			return OCS_INTERNAL_ERROR;
		}
		depth=atoi(depths);
	}

	int props=onion_webdav_parse_propfind(onion_request_get_data(req));
	ONION_DEBUG("Asking for props %08X, depth %d", props, depth);
	
	onion_block *block=onion_webdav_write_propfind(basepath, filename, onion_request_get_path(req), depth, props);
	
	if (!block) // No block, resource does not exist
		return onion_shortcut_response("Not found", HTTP_NOT_FOUND, req, res);
		
	ONION_DEBUG0("Printing block %s", onion_block_data(block));
	
	onion_response_set_header(res, "Content-Type", "text/xml; charset=\"utf-8\"");
	onion_response_set_length(res, onion_block_size(block));
	onion_response_set_code(res, HTTP_MULTI_STATUS);
	onion_response_write_headers(res);
	onion_response_flush(res);
	
	onion_response_write(res, onion_block_data(block), onion_block_size(block));
	
	onion_block_free(block);
	
	return OCS_PROCESSED;
}
Beispiel #5
0
/**
 * @short Helps to prepare each pair.
 */
static void onion_dict_json_preorder(onion_block *block, const char *key, const void *value, int flags){
	if (!onion_block_size(block)) // Error somewhere.
		return;
	char *s;
	s=onion_c_quote_new(key);
	if (s==NULL){
		onion_block_clear(block);
		return;
	}
	onion_block_add_str(block, s);
	free(s);
	onion_block_add_char(block, ':');
	if (flags&OD_DICT){
		onion_block *tmp;
		tmp=onion_dict_to_json((onion_dict*)value);
		if (!tmp){
			onion_block_clear(block);
			return;
		}
		onion_block_add_block(block, tmp);
		onion_block_free(tmp);
	}
	else{
		s=onion_c_quote_new(value);
		if (s==NULL){
			onion_block_clear(block);
			return;
		}
		onion_block_add_str(block, s);
		free(s);
	}
	onion_block_add_data(block, ", ",2);
}
Beispiel #6
0
/**
 * @short One block read from in, prepare the output.
 * 
 * Depending on the mode of the block it calls the appropiate handler: variable, tag or just write text.
 */
void write_block(parser_status *st, onion_block *b){
	int mode=st->last_wmode;
	//ONION_DEBUG("Write mode %d, code %s", mode, b->data);
	switch(mode){
		case TEXT:
		{
			int oldl;
			if ( (oldl=onion_block_size(b)) ){
				char *safe=onion_c_quote_new(onion_block_data(b));
				function_add_code(st, "  onion_response_write(res, %s, %d);\n", safe, oldl);
				free(safe);
			}
		}
			break;
		case VARIABLE:
			variable_write(st, b);
			break;
		case TAG:
			tag_write(st, b);
			break;
		default:
			ONION_ERROR("Unknown final mode %d", mode);
	}
	onion_block_clear(st->rawblock);
}
Beispiel #7
0
/**
 * @short Allows to change some properties of the file
 */
onion_connection_status onion_webdav_proppatch(const char *filename, onion_webdav *wd, onion_request *req, onion_response *res){
	xmlDocPtr doc;
	const onion_block *block=onion_request_get_data(req);
// 	ONION_DEBUG("%s",onion_block_data(block));
	if (!block)
		return OCS_INTERNAL_ERROR;
	doc = xmlParseMemory((char*)onion_block_data(block), onion_block_size(block));
	
	xmlNode *root = NULL;
	root = xmlDocGetRootElement(doc);
	int ok=0;
	
	while (root){
		ONION_DEBUG("%s", root->name);
		if (strcmp((const char*)root->name,"propertyupdate")==0){
			xmlNode *propertyupdate = root->children;
			while (propertyupdate){
				ONION_DEBUG("%s", propertyupdate->name);
				if (strcmp((const char*)propertyupdate->name,"set")==0){
					xmlNode *set = propertyupdate->children;
					while (set){
						ONION_DEBUG("%s", set->name);
						if (strcmp((const char*)set->name,"prop")==0){
							ONION_DEBUG("in prop");
							xmlNode *prop = set->children;
							while (prop){
								ONION_DEBUG("prop %s", prop->name);
								if (strcmp((const char*)prop->name,"executable")==0){
									ONION_DEBUG("Setting executable %s", prop->children->content);
									struct stat st;
									stat(filename, &st);
									if (toupper(prop->children->content[0])=='T'){
										chmod(filename, st.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
									}
									else{
										chmod(filename, st.st_mode & ~( S_IXUSR | S_IXGRP | S_IXOTH) );
									}
									ok=1;
								}
								prop=prop->next;
							}
						}
						set=set->next;
					}
				}
				propertyupdate=propertyupdate->next;
			}
		}
		root=root->next;
	}
	
	xmlFreeDoc(doc); 
	if (ok){
		onion_response_write_headers(res);
		return OCS_PROCESSED;
	}
	else{
		return OCS_INTERNAL_ERROR;
	}
}
Beispiel #8
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();
}
Beispiel #9
0
/**
 * @short Returns the set of props for this query
 * 
 * The block contains the propfind xml, and it returns the mask of props to show.
 * 
 */
static int onion_webdav_parse_propfind(const onion_block *block){
	// For parsing the data
	xmlDocPtr doc;
	doc = xmlParseMemory((char*)onion_block_data(block), onion_block_size(block));
	
	if (doc == NULL) {
		ONION_ERROR("Error: unable to parse OPTIONS");
		return OCS_INTERNAL_ERROR;
	}
	
	int props=0;
	xmlNode *root = NULL;
	root = xmlDocGetRootElement(doc);
	while (root){
		if (strcmp((const char*)root->name,"propfind")==0){
			xmlNode *propfind = root->children;
			while (propfind){
				if (strcmp((const char*)propfind->name,"prop")==0){
					xmlNode *prop = propfind->children;
					while (prop){
						if (strcmp((const char*)prop->name, "text")==0) // ignore
							;
						else if (strcmp((const char*)prop->name, "resourcetype")==0)
							props|=WD_RESOURCE_TYPE;
						else if (strcmp((const char*)prop->name, "getcontentlength")==0)
							props|=WD_CONTENT_LENGTH;
						else if (strcmp((const char*)prop->name, "getlastmodified")==0)
							props|=WD_LAST_MODIFIED;
						else if (strcmp((const char*)prop->name, "creationdate")==0)
							props|=WD_CREATION_DATE;
						else if (strcmp((const char*)prop->name, "getetag")==0)
							props|=WD_ETAG;
						else if (strcmp((const char*)prop->name, "getcontenttype")==0)
							props|=WD_CONTENT_TYPE;
						else if (strcmp((const char*)prop->name, "displayname")==0)
							props|=WD_DISPLAY_NAME;
						else if (strcmp((const char*)prop->name, "executable")==0)
							props|=WD_EXECUTABLE;
						else{
							char tmp[256];
							snprintf(tmp,sizeof(tmp),"g0:%s", prop->name);
							ONION_DEBUG("Unknown requested property with tag %s", prop->name);
						}
						
						prop=prop->next;
					}
					
				}
				propfind=propfind->next;
			}
		}
		root=root->next;
	}
	xmlFreeDoc(doc); 
	
	return props;
}
Beispiel #10
0
/**
 * @short Shortcut to answer some json data
 * 
 * It converts to json the passed dict and returns it. The dict is freed before returning.
 */
onion_connection_status onion_shortcut_response_json(onion_dict *d, onion_request *req, onion_response *res){
	onion_response_set_header(res, "Content-Type", "application/json");
	
	onion_block *bl=onion_dict_to_json(d);
	onion_dict_free(d);
	char tmp[16];
	snprintf(tmp,sizeof(tmp),"%ld",(long)onion_block_size(bl));
	int ret=onion_shortcut_response_extra_headers(onion_block_data(bl), HTTP_OK, req, res, "Content-Length", tmp, NULL);
	onion_block_free(bl);
	return ret;
}
Beispiel #11
0
/// Writes the desired function to st->out
static void function_write(parser_status * st, function_data * d) {
  ONION_DEBUG("Write function %s", d->id);
  if (d->code) {
    if (use_orig_line_numbers)
      fprintf(st->out, "#line 1\n");
    if (d->is_static)
      fprintf(st->out, "static ");
    fprintf(st->out,
            "void %s(%s){\n", d->id,
            d->signature ? d->signature :
            "onion_dict *context, onion_response *res");

    const char *data = onion_block_data(d->code);
    int ldata = onion_block_size(d->code);
    if (use_orig_line_numbers) {
      fprintf(st->out, "#line 1\n");

      // Write code, but change \n\n to \n
      int i = 0, li = 0, diff;
      char lc = 0;
      ssize_t r;
      for (i = 0; i < ldata; i++) {
        if (data[i] == '\n' && lc == '\n') {    // Two in a row
          diff = i - li - 1;
          r = fwrite(&data[li], 1, diff, st->out);
          if (r != diff) {
            ONION_ERROR("Could not write all data");
            abort();
          }
          li = i;
        }
        lc = data[i];
      }
      diff = i - li;
      r = fwrite(&data[li], 1, diff, st->out);
      if (r != diff) {
        ONION_ERROR("Could not write all data");
        abort();
      }
      fprintf(st->out, "#line 1\n");
    } else {
      ssize_t r = fwrite(data, 1, ldata, st->out);
      if (r != ldata) {
        ONION_ERROR("Could not write all data");
        abort();
      }
    }

    fprintf(st->out, "}\n");
  }
}
Beispiel #12
0
/**
 * @short One block read from in, prepare the output.
 * 
 * Depending on the mode of the block it calls the appropiate handler: variable, tag or just write text.
 */
void write_block(parser_status *st, onion_block *b){
	int mode=st->last_wmode;
	//ONION_DEBUG("Write mode %d, code %s", mode, b->data);
	switch(mode){
		case TEXT:
		{
			int oldl;
			if ( (oldl=onion_block_size(b)) ){
				if (oldl>0){ // Not Just \0
					int use_orig_line_numbers_bak=use_orig_line_numbers;
					use_orig_line_numbers=0;
					char *safe=onion_c_quote_new(onion_block_data(b));
					function_add_code(st, "  onion_response_write(res, ");
					int pos=0;
					int size=strlen(safe);
					char *s=safe;
					//ONION_DEBUG("------- pos %d, size %d",pos,size);
					while (pos<size){
						//ONION_DEBUG("pos %d, size %d",pos,size);
						char *e=strstr(s, "\n");
						if (!e)
							break;
						*e='\0';
						if (pos==0)
							function_add_code(st, "%s\n", s);
						else
							function_add_code(st, "      %s\n", s);
						pos+=(e-s)+1;
						s=e+1;
					}
					if (pos==0)
						function_add_code(st, "%s, %d);\n", s, oldl);
					else
						function_add_code(st, "      %s, %d);\n", s, oldl);
					use_orig_line_numbers=use_orig_line_numbers_bak;
					free(safe);
				}
			}
		}
			break;
		case VARIABLE:
			variable_write(st, b);
			break;
		case TAG:
			tag_write(st, b);
			break;
		default:
			ONION_ERROR("Unknown final mode %d", mode);
	}
	onion_block_clear(st->rawblock);
}
Beispiel #13
0
/**
 * @short Handles a propfind
 * 
 * @param path the shared path.
 */
onion_connection_status onion_webdav_propfind(const char *filename, onion_webdav *wd, onion_request* req, onion_response* res){
	ONION_DEBUG0("PROPFIND");
	int depth;
	{
		const char *depths=onion_request_get_header(req, "Depth");
		if (!depths){
			ONION_ERROR("Missing Depth header on webdav request");
			return OCS_INTERNAL_ERROR;
		}
		if (strcmp(depths,"infinity")==0){
			ONION_ERROR("Infinity depth not supported yet.");
			return OCS_INTERNAL_ERROR;
		}
		depth=atoi(depths);
	}

	int props=onion_webdav_parse_propfind(onion_request_get_data(req));
	ONION_DEBUG("Asking for props %08X, depth %d", props, depth);
	
	onion_block *block=onion_webdav_write_propfind(filename, onion_request_get_path(req), depth, props);
	
	if (!block) // No block, resource does not exist
		return onion_shortcut_response("Not found", HTTP_NOT_FOUND, req, res);
		
	ONION_DEBUG0("Printing block %s", onion_block_data(block));
	
	onion_response_set_header(res, "Content-Type", "text/xml; charset=\"utf-8\"");
	onion_response_set_length(res, onion_block_size(block));
	onion_response_set_code(res, HTTP_MULTI_STATUS);
	
	onion_response_write(res, onion_block_data(block), onion_block_size(block));
	
	onion_block_free(block);
	
	return OCS_PROCESSED;
}
Beispiel #14
0
onion_connection_status post_json_check(json_response *post, onion_request *req, onion_response *res){
	post->processed=1;
	
	FAIL_IF_NOT_EQUAL_INT(onion_request_get_flags(req)&OR_METHODS, OR_POST);
	FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req, "Content-Type"),"application/json");
	const onion_block *data=onion_request_get_data(req);
	FAIL_IF_EQUAL(data, NULL);
	if (!data)
		return OCS_INTERNAL_ERROR;
	
	FAIL_IF_NOT_EQUAL_INT(onion_block_size(data), sizeof(JSON_EXAMPLE));
	FAIL_IF_NOT_EQUAL_INT(memcmp(onion_block_data(data), JSON_EXAMPLE, sizeof(JSON_EXAMPLE)), 0);
	
	post->processed=2;
	
	return OCS_PROCESSED;
}
Beispiel #15
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;
}
Beispiel #16
0
/**
 * @short Adds some code to the top function
 */
void function_add_code(parser_status *st, const char *fmt, ...){
	function_data *p=(function_data*)st->function_stack->tail->data;
	if (p->flags&F_NO_MORE_WRITE)
		return;
	
	char tmp[4096];
	
	va_list ap;
	va_start(ap, fmt);
	vsnprintf(tmp, sizeof(tmp), fmt, ap);
	va_end(ap);

	if (use_orig_line_numbers){
		char line[32];
		int p=onion_block_size(st->current_code);
		if (p && onion_block_data(st->current_code)[p-1]!='\n')
			onion_block_add_char(st->current_code, '\n');
		snprintf(line,sizeof(line),"#line %d\n", st->line);
		// I have to do it for every \n too. This is going to be slow.
		const char *orig=tmp;
		int lorig=strlen(orig);
		int i=0, li=0;
		for (i=0;i<lorig;i++){
			if (orig[i]=='\n'){
				onion_block_add_str(st->current_code, line);
				onion_block_add_data(st->current_code, &orig[li], i-li+1);
				li=i;
			}
		}
		if (i-1!=li){
			onion_block_add_str(st->current_code, line);
			onion_block_add_str(st->current_code, &orig[li]);
		}
	}
	else{
		//ONION_DEBUG("Add to level %d text %s",list_count(st->function_stack), tmp);
		onion_block_add_str(st->current_code, tmp);
	}
}
Beispiel #17
0
/**
 * @short Helps to prepare each pair.
 */
static void onion_dict_json_preorder(onion_block *block, const char *key, const void *value, int flags){
	if (!onion_block_size(block)) // Error somewhere.
		return;
	onion_block_add_char(block,'\"');
	onion_json_quote_add(block, key);
	onion_block_add_data(block,"\":",2);
	if (flags&OD_DICT){
		onion_block *tmp;
		tmp=onion_dict_to_json((onion_dict*)value);
		if (!tmp){
			onion_block_clear(block);
			return;
		}
		onion_block_add_block(block, tmp);
		onion_block_free(tmp);
	}
	else{
		onion_block_add_char(block,'\"');
		onion_json_quote_add(block, value);
		onion_block_add_char(block,'\"');
	}
	onion_block_add_data(block, ", ",2);
}
Beispiel #18
0
/**
 * @short Reads from the data to fulfill content-length data.
 */
static onion_connection_status parse_CONTENT_LENGTH(onion_request *req, onion_buffer *data){
	onion_token *token=req->parser_data;
	size_t skip=data->pos; // First packet will be headers + some data, later ony data
	int length=data->size-skip;
	bool exit=false;
	size_t current_size=onion_block_size(req->data);

	ONION_DEBUG0("Adding data to request->data (non form POST) %d + %d / %d [%d/%d] %p",
		current_size, length, token->extra_size, skip, data->size, data->data+current_size);

	if (length + current_size >= token->extra_size){
		ONION_DEBUG0("Done");
		exit=true;
		length=token->extra_size - current_size;
	}

	onion_block_add_data(req->data, &data->data[skip], length);
	data->pos+=length; // done

	if (exit)
		return OCS_REQUEST_READY;

	return OCS_NEED_MORE_DATA;
}
Beispiel #19
0
void t10_tojson(){
	INIT_LOCAL();
	
	onion_dict *d=onion_dict_new();
	const char *tmp;
	int s;
	onion_block *b;
	b=onion_dict_to_json(d);
	tmp=onion_block_data(b);
	ONION_DEBUG("Json returned is '%s'", tmp);
	FAIL_IF_NOT_EQUAL_STR(tmp,"{}");
	onion_block_free(b);
	
	onion_dict_add(d, "test", "json", 0);
	
	b=onion_dict_to_json(d);
	tmp=onion_block_data(b);
	s=onion_block_size(b);
	ONION_DEBUG("Json returned is '%s'", tmp);
	FAIL_IF(s<=0);
	FAIL_IF_EQUAL(strstr(tmp,"{"), NULL);
	FAIL_IF_EQUAL(strstr(tmp,"}"), NULL);

	FAIL_IF_EQUAL(strstr(tmp,"\"test\""), NULL);
	FAIL_IF_EQUAL(strstr(tmp,"\"json\""), NULL);
	FAIL_IF_NOT_EQUAL(strstr(tmp,","), NULL);
	onion_block_free(b);
	
	onion_dict_add(d, "other", "data", 0);

	b=onion_dict_to_json(d);
	tmp=onion_block_data(b);
	s=onion_block_size(b);
	ONION_DEBUG("Json returned is '%s'", tmp);
	FAIL_IF(s<=0);
	FAIL_IF_EQUAL(strstr(tmp,"{"), NULL);
	FAIL_IF_EQUAL(strstr(tmp,"}"), NULL);

	FAIL_IF_EQUAL(strstr(tmp,"\"test\""), NULL);
	FAIL_IF_EQUAL(strstr(tmp,"\"json\""), NULL);
	FAIL_IF_EQUAL(strstr(tmp,","), NULL);
	FAIL_IF_EQUAL(strstr(tmp,"\"other\""), NULL);
	FAIL_IF_EQUAL(strstr(tmp,"\"data\""), NULL);
	onion_block_free(b);
	
	onion_dict_add(d, "with\"", "data\n", 0);

	b=onion_dict_to_json(d);
	tmp=onion_block_data(b);
	s=onion_block_size(b);
	ONION_DEBUG("Json returned is '%s'", tmp);
	FAIL_IF(s<=0);

	FAIL_IF_EQUAL(strstr(tmp,"\\n"), NULL);
	FAIL_IF_EQUAL(strstr(tmp,"\\\""), NULL);
	onion_block_free(b);
	
	onion_dict_free(d);
	
	END_LOCAL();
}
Beispiel #20
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;
}
Beispiel #21
0
Datei: tags.c Projekt: Paxa/onion
/**
 * Current block is a tag, slice it and call the proper handler.
 */
void tag_write(parser_status *st, onion_block *b){
	//ONION_DEBUG("Write tag %s",b->data);
	
	list *command=list_new((void*)tag_token_free);
	
	char mode=0; // 0 skip spaces, 1 in single var, 2 in quotes
	
	// Split into elements for the list
	int i, li=0;
	const char *data=onion_block_data(b);
	int size=onion_block_size(b);
	for (i=0;i<size;i++){
		char c=data[i];
		switch(mode){
			case 0:
				if (!isspace(c)){
					if (c=='"'){
						mode=2;
						li=i+1;
					}
					else{
						mode=1;
						li=i;
					}
				}
				break;
			case 1:
				if (isspace(c)){
					mode=0;
					list_add(command, tag_token_new(&data[li], i-li, T_VAR));
				}
				break;
			case 2:
				if (c=='"'){
					mode=0;
					list_add(command, tag_token_new(&data[li], i-li, T_STRING));
				}
				break;
		}
	}
	if (mode==1)
		list_add(command, tag_token_new(&data[li], i-li, T_VAR));
	
	if (!command->head){
		ONION_ERROR("%s:%d Incomplete command", st->infilename, st->line);
		st->status=1;
		return;
	}
	
	// Call the function.
	tag_token *commandtoken=command->head->data;
	const char *commandname=commandtoken->data;

	void (*f)(parser_status *st, list *args);
	f=(void*)onion_dict_get(tags, commandname);
	if (f)
		f(st, command);
	else{
		ONION_ERROR("%s:%d Unknown command '%s'. ", st->infilename, st->line, commandname);
		st->status=1;
	}
	
	list_free(command);
}