Ejemplo n.º 1
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;
	}
}
Ejemplo n.º 2
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();
}
Ejemplo n.º 3
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");
	}
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
onion_connection_status process_request(void *_, onion_request * req,
                                        onion_response * res) {
  onion_response_write0(res, "Done");

  const onion_block *data = onion_request_get_data(req);
  FAIL_IF_NOT(data);
  FAIL_IF_NOT_EQUAL_STR(onion_block_data(data),
                        "{\n   \"a\": \"10\",\n   \"b\": \"20\"\n}");

  ONION_DEBUG(onion_block_data(data));

  return OCS_PROCESSED;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
void t18_json_escape_codes(){
	INIT_LOCAL();

	onion_dict *d=onion_dict_from_json("{ \"hello\": \"Hello\\nworld\", \"second\":\"second\" }");
	FAIL_IF_NOT_STRSTR(onion_dict_get(d, "hello"), "Hello\nworld");
	FAIL_IF_NOT_STRSTR(onion_dict_get(d, "second"), "second");
	onion_dict_free(d);

	d=onion_dict_from_json("{ \"hello\": \"\\uD83D\\uDE02\" }");
	FAIL_IF_NOT_STRSTR(onion_dict_get(d, "hello"), "😂");
	onion_dict_free(d);

	d=onion_dict_from_json("{ \"hello\": \"\\uD83D\\uDE03\" }"); // Another code point
	FAIL_IF_STRSTR(onion_dict_get(d, "hello"), "😂");
	onion_dict_free(d);

	d=onion_dict_from_json("{ \"hello\": \"\\u007b\" }"); // simple unicode
	FAIL_IF_NOT_STRSTR(onion_dict_get(d, "hello"), "{");
	onion_dict_free(d);

	d=onion_dict_from_json("{ \"hello\": \"\\\"Quote\" }"); // Escape quote
	FAIL_IF_NOT_STRSTR(onion_dict_get(d, "hello"), "\"Quote");
	onion_dict_free(d);

	d=onion_dict_from_json("{ \"hello\": \"\"Quote\" }"); // Must fail
	FAIL_IF_NOT_EQUAL(d, NULL);

	d=onion_dict_new();
	onion_dict_add(d, "hello", "Hello\nWorld\\", 0);
	onion_dict_add(d, "second", "123", 0);
	onion_block *b=onion_dict_to_json(d);
	FAIL_IF_NOT_EQUAL_STR(onion_block_data(b),"{\"hello\":\"Hello\\nWorld\\\\\", \"second\":\"123\"}");
	onion_block_free(b);
	onion_dict_free(d);

	d=onion_dict_new();
	onion_dict_add(d, "hello", "😂\t\n😂", 0);
	b=onion_dict_to_json(d);
	FAIL_IF_NOT_EQUAL_STR(onion_block_data(b),"{\"hello\":\"😂\\t\\n😂\"}");
	onion_block_free(b);
	onion_dict_free(d);

	d=onion_dict_new();
	onion_dict_add(d, "hello", "\02\03\x7f", 0);
	b=onion_dict_to_json(d);
	FAIL_IF_NOT_EQUAL_STR(onion_block_data(b),"{\"hello\":\"\\u0002\\u0003\\u007F\"}");
	onion_block_free(b);
	onion_dict_free(d);

	END_LOCAL();
}
Ejemplo n.º 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();
}
Ejemplo n.º 9
0
/**
 * @short Reads from the data to fulfill content-length data.
 * 
 * All data is writen a temporal file, which will be removed later.
 */
static onion_connection_status parse_PUT(onion_request *req, onion_buffer *data){
	onion_token *token=req->parser_data;
	int length=data->size-data->pos;
	int exit=0;
	
	if (length>=token->extra_size-token->pos){
		exit=1;
		length=token->extra_size-token->pos;
	}

	//ONION_DEBUG0("Writing %d. %d / %d bytes", length, token->pos+length, token->extra_size);

	int *fd=(int*)token->extra;
	ssize_t w=write(*fd, &data->data[data->pos], length);
	if (w<0){
		ONION_ERROR("Could not write all data to temporal file.");
		return OCS_INTERNAL_ERROR;
	}
	data->pos+=length;
	token->pos+=length;

#if __DEBUG__
	const char *filename=onion_block_data(req->data);
	ONION_DEBUG0("Done with PUT. Created %s (%d bytes)", filename, token->pos);
#endif
	
	if (exit){
		close (*fd);
		free(fd);
		token->extra=NULL;
		return onion_request_process(req);
	}
	
	return OCS_NEED_MORE_DATA;
}
Ejemplo n.º 10
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);
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
/**
 * @short Parses a block variable and writes the code necesary.
 * 
 * It can go deep inside a dict or list, and apply filters.
 */
void variable_write(parser_status *st, onion_block *b){
	
	function_add_code(st,
"  {\n"
"    const char *tmp;\n");
	variable_solve(st, onion_block_data(b), "tmp", STRING);
	function_add_code(st,
"    if (tmp)\n"
"      onion_response_write_html_safe(res, tmp);\n"
"  }\n");
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
0
void t12_dict_in_dict(){
	INIT_LOCAL();
	
	onion_dict *A=onion_dict_new();
	onion_dict *B=onion_dict_new();
	onion_dict *C=onion_dict_new();
	onion_dict *D=onion_dict_new();
	
	int i;
	for (i=0;i<16;i++){
		char tmp[9];
		sprintf(tmp,"%08X",rand());
		onion_dict_add(A, tmp, tmp, OD_DUP_ALL);
		sprintf(tmp,"%08X",rand());
		onion_dict_add(B, tmp, tmp, OD_DUP_ALL);
		sprintf(tmp,"%08X",rand());
		onion_dict_add(C, tmp, tmp, OD_DUP_ALL);
		sprintf(tmp,"%08X",rand());
		onion_dict_add(D, tmp, tmp, OD_DUP_ALL);
	}

	onion_dict_add(A, "B", B, OD_DICT|OD_FREE_VALUE);
	onion_dict_add(A, "C", C, OD_DICT|OD_FREE_VALUE);
	onion_dict_add(A, "D", D, OD_DICT|OD_FREE_VALUE);

	FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get(A, "B"), NULL);
	FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get(A, "C"), NULL);
	FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get(A, "D"), NULL);

	FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get_dict(A, "B"), B);
	FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get_dict(A, "C"), C);
	FAIL_IF_NOT_EQUAL((onion_dict*)onion_dict_get_dict(A, "D"), D);
	
	{
		onion_block *tmpA=onion_dict_to_json(A);
		onion_block *tmpB=onion_dict_to_json(B);
		onion_block *tmpC=onion_dict_to_json(C);
		onion_block *tmpD=onion_dict_to_json(D);
		/*
		ONION_DEBUG("Json is: %s",tmpA);
		ONION_DEBUG("Json is: %s",tmpB);
		ONION_DEBUG("Json is: %s",tmpC);
		ONION_DEBUG("Json is: %s",tmpD);
		*/
		FAIL_IF_EQUAL( strstr(onion_block_data(tmpA), onion_block_data(tmpB)), NULL);
		FAIL_IF_EQUAL( strstr(onion_block_data(tmpA), onion_block_data(tmpC)), NULL);
		FAIL_IF_EQUAL( strstr(onion_block_data(tmpA), onion_block_data(tmpD)), NULL);
		onion_block_free(tmpA);
		onion_block_free(tmpB);
		onion_block_free(tmpC);
		onion_block_free(tmpD);
	}
	B=onion_dict_hard_dup(A);
	
	onion_dict_free(A);
	onion_dict_free(B);
	
	END_LOCAL();
}
Ejemplo n.º 16
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");
  }
}
Ejemplo n.º 17
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);
}
Ejemplo n.º 18
0
void onion_sessions_redis_save(onion_sessions *sessions, const char *session_id, onion_dict* data)
{
    onion_block *bl = onion_dict_to_json(data);

    ONION_DEBUG0("Save session %s: %s", session_id, onion_block_data(bl));

    onion_session_redis *p = sessions->data;
#ifdef HAVE_PTHREADS
    pthread_mutex_lock(&p->mutex);
#endif

    if(p == NULL)
    {
        redisReply* reply = redisCommand(p->context, "HDEL SESSIONS %b", session_id, strlen(session_id));

        if(reply->type != REDIS_REPLY_INTEGER)
        {
            ONION_ERROR("Error removing session");
        }
        freeReplyObject(reply);
    } else
    {
        const char* json = onion_block_data(bl);
        redisReply* reply = redisCommand(p->context, "HSET SESSIONS %b %b", session_id, strlen(session_id), json, strlen(json));

        if(reply->type != REDIS_REPLY_INTEGER)
        {
            ONION_ERROR("Error saving session");
        }
        freeReplyObject(reply);
        onion_block_free(bl);
    }

#ifdef HAVE_PTHREADS
    pthread_mutex_unlock(&p->mutex);
#endif
    return;
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
0
void onion_sessions_sqlite3_save(onion_sessions *sessions, const char *session_id, onion_dict *data){
	onion_block *bl=onion_dict_to_json(data);

	ONION_DEBUG0("Save session %s: %s", session_id, onion_block_data(bl));
	const char *json=onion_block_data(bl);

	int rc;
	onion_session_sqlite3 *p=sessions->data;
#ifdef HAVE_PTHREADS
	pthread_mutex_lock(&p->mutex);
#endif
	sqlite3_reset(p->save);
	rc=sqlite3_bind_text(p->save, 1, session_id, -1, SQLITE_STATIC);
	if( rc!=SQLITE_OK ){
		ONION_ERROR("Error binding session_id");
		goto error;
	}
	rc=sqlite3_bind_text(p->save, 2, json, -1, SQLITE_STATIC);
	if( rc!=SQLITE_OK ){
		ONION_ERROR("Error binding json data");
		goto error;
	}
	rc=sqlite3_step(p->save);
	if( rc!=SQLITE_DONE ){
		ONION_ERROR("Error saving session (%d)", rc);
		goto error;
	}

	ONION_DEBUG0("Session saved");
error:
	onion_block_free(bl);
#ifdef HAVE_PTHREADS
	pthread_mutex_unlock(&p->mutex);
#endif
	return;
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
0
/**
 * @short Simple put on webdav is just move a file from tmp to the final destination (or copy if could not move).
 * 
 */
onion_connection_status onion_webdav_put(const char *filename, onion_webdav *wd, onion_request *req, onion_response *res){
	ONION_DEBUG("Webdav puts %s", filename);
	
	const char *tmpfile=onion_block_data(onion_request_get_data(req));
	
	int ok=onion_shortcut_rename(tmpfile, filename);
	
	if (ok==0){
		ONION_DEBUG("Created %s succesfully", filename);
		return onion_shortcut_response("201 Created", 201, req, res);
	}
	else{
		ONION_ERROR("Could not rename %s to %s (%s)", tmpfile, filename, strerror(errno));
		return onion_shortcut_response("Could not create resource", HTTP_FORBIDDEN, req, res);
	}
}
Ejemplo n.º 23
0
void check_tests(onion_block *data, struct tests_call_otemplate *test){
	memset(test, 0, sizeof(*test));
	const char *tmp=onion_block_data(data);
	test->ok_title=test->ok_list=test->ok_hello=test->ok_title_title=0;
  if (strstr(tmp, "TITLE"))
    test->ok_title=1;
  if (strstr(tmp,"LIST"))
    test->ok_list=1;
  if (strstr(tmp,"{hello}"))
    test->ok_hello=1;
  if (strstr(tmp,"TITLE TITLE"))
    test->ok_title_title=1;
  if (strstr(tmp,"&lt;&quot;Hello&gt;"))
    test->ok_encoding=1;
	if (strstr(tmp,"internal loop"))
		test->ok_internal_loop=1;
}
Ejemplo n.º 24
0
/**
 * @short Main webdav handler, just redirects to the proper handler depending on headers and method
 */
onion_connection_status onion_webdav_handler(onion_webdav *wd, onion_request *req, onion_response *res){
	onion_response_set_header(res, "Dav", "1,2");
	onion_response_set_header(res, "MS-Author-Via", "DAV");
	
#ifdef __DEBUG__
	const onion_block *data=onion_request_get_data(req);
	if (data){
		ONION_DEBUG0("Have data!\n %s", onion_block_data(data));
	}
#endif

	
	char filename[512];
	snprintf(filename, sizeof(filename), "%s/%s", wd->path, onion_request_get_path(req));
	
	ONION_DEBUG("Check %s and %s", wd->path, filename);
	if (wd->check_permissions(wd->path, filename, req)!=0){
		return onion_shortcut_response("Forbidden", HTTP_FORBIDDEN, req, res);
	}

	
	switch (onion_request_get_flags(req)&OR_METHODS){
		case OR_GET:
		case OR_HEAD:
			return onion_webdav_get(filename, wd, req, res);
		case OR_OPTIONS:
			return onion_webdav_options(filename, wd, req, res);
		case OR_PROPFIND:
			return onion_webdav_propfind(filename, wd, req, res);
		case OR_PUT:
			return onion_webdav_put(filename, wd, req, res);
		case OR_DELETE:
			return onion_webdav_delete(filename, wd, req, res);
		case OR_MOVE:
			return onion_webdav_move(filename, wd, req, res);
		case OR_MKCOL:
			return onion_webdav_mkcol(filename, wd, req, res);
		case OR_PROPPATCH:
			return onion_webdav_proppatch(filename, wd, req, res);
	}
	
	onion_response_set_code(res, HTTP_NOT_IMPLEMENTED);
	onion_response_write0(res, "<h1>Work in progress...</h1>\n");
	
	return OCS_PROCESSED;
}
Ejemplo n.º 25
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;
}
Ejemplo n.º 26
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);
	}
}
Ejemplo n.º 27
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();
}
Ejemplo n.º 28
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;
}
Ejemplo n.º 29
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;
}
Ejemplo n.º 30
0
		/**
		 * @short Converts the dictionary to a JSON string.
		 */
		std::string toJSON() const{
			onion_block *bl=onion_dict_to_json(ptr);
			std::string str=onion_block_data(bl);
			onion_block_free(bl);
			return str;
		}