Ejemplo n.º 1
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.º 2
0
/**
 * @short Deletes a request and all its data
 * @memberof onion_request_t
 */
void onion_request_free(onion_request *req){
  ONION_DEBUG0("Free request %p", req);
	onion_dict_free(req->headers);
	
	if (req->parser_data){
		onion_request_parser_data_free(req->parser_data);
		req->parser_data=NULL;
	}
	
	if (req->fullpath)
		free(req->fullpath);
	if (req->GET)
		onion_dict_free(req->GET);
	if (req->POST)
		onion_dict_free(req->POST);
	if (req->FILES){
		onion_dict_preorder(req->FILES, unlink_files, NULL);
		onion_dict_free(req->FILES);
	}
	if (req->parser_data)
		free(req->parser_data);
	if (req->client_info)
		free(req->client_info);
	if (req->session_id)
		free(req->session_id);
	if (req->session)
		onion_dict_free(req->session); // Not really remove, just dereference
	if (req->data)
		onion_block_free(req->data);

	free(req);
}
Ejemplo n.º 3
0
/**
 * @short Cleans a request object to reuse it.
 * @memberof onion_request_t
 */
void onion_request_clean(onion_request* req){
  ONION_DEBUG0("Clean request %p", req);
  onion_dict_free(req->headers);
  req->headers=onion_dict_new();
  if (req->parser_data){
    onion_request_parser_data_free(req->parser_data);
    req->parser_data=NULL;
  }
  req->parser=NULL;
  req->flags&=0x0F00; // I keep server flags.
  if (req->fullpath){
    free(req->fullpath);
    req->path=req->fullpath=NULL;
  }
  if (req->GET){
    onion_dict_free(req->GET);
    req->GET=NULL;
  }
  if (req->POST){
    onion_dict_free(req->POST);
    req->POST=NULL;
  }
  if (req->FILES){
    onion_dict_preorder(req->FILES, unlink_files, NULL);
    onion_dict_free(req->FILES);
    req->FILES=NULL;
  }
  if (req->data){
    onion_block_free(req->data);
    req->data=NULL;
  }
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
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.º 6
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.º 7
0
/// Include an external html. This is only the call, the programmer must compile such html too.
void tag_include(parser_status* st, list* l){
	function_data *d=function_new(st, "%s", tag_value_arg(l, 1));
	function_pop(st);
	onion_block_free(d->code); // This means no impl
	d->code=NULL; 
	
	function_add_code(st, "  %s(context, res);\n", d->id);
}
Ejemplo n.º 8
0
/**
 * @short Cleans a request object to reuse it.
 * @memberof onion_request_t
 */
void onion_request_clean(onion_request* req) {
    ONION_DEBUG0("Clean request %p", req);
    onion_dict_free(req->headers);
    req->headers=onion_dict_new();
    onion_dict_set_flags(req->headers, OD_ICASE);
    req->flags&=OR_NO_KEEP_ALIVE; // I keep keep alive.
    if (req->parser_data) {
        onion_request_parser_data_free(req->parser_data);
        req->parser_data=NULL;
    }
    if (req->fullpath) {
        onion_low_free(req->fullpath);
        req->path=req->fullpath=NULL;
    }
    if (req->GET) {
        onion_dict_free(req->GET);
        req->GET=NULL;
    }
    if (req->POST) {
        onion_dict_free(req->POST);
        req->POST=NULL;
    }
    if (req->FILES) {
        onion_dict_preorder(req->FILES, unlink_files, NULL);
        onion_dict_free(req->FILES);
        req->FILES=NULL;
    }
    if (req->session_id) {
        if (onion_dict_count(req->session)==0) {
            onion_request_session_free(req);
        }
        else {
            onion_sessions_save(req->connection.listen_point->server->sessions, req->session_id, req->session);
            onion_dict_free(req->session); // Not really remove, just dereference
            req->session=NULL;
            onion_low_free(req->session_id);
            req->session_id=NULL;
        }
    }
    if (req->data) {
        onion_block_free(req->data);
        req->data=NULL;
    }
    if (req->connection.cli_info) {
        onion_low_free(req->connection.cli_info);
        req->connection.cli_info=NULL;
    }
    if (req->cookies) {
        onion_dict_free(req->cookies);
        req->cookies=NULL;
    }
    if (req->free_list) {
        onion_ptr_list_foreach(req->free_list, onion_low_free);
        onion_ptr_list_free(req->free_list);
        req->free_list=NULL;
    }
}
Ejemplo n.º 9
0
void tag_extends(parser_status *st, list *l){
	function_data *d=function_new(st, "%s", tag_value_arg(l, 1));
	function_pop(st);
	onion_block_free(d->code);
	d->code=NULL;
	
	function_add_code(st, "  %s(context, res);", d->id);
	d=(function_data*)st->function_stack->tail->data;
	d->flags|=F_NO_MORE_WRITE;
}
Ejemplo n.º 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;
}
Ejemplo n.º 11
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.º 12
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;
}
Ejemplo n.º 13
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();
}
Ejemplo n.º 14
0
/**
 * @short Deletes a request and all its data
 * @memberof onion_request_t
 */
void onion_request_free(onion_request *req) {
    ONION_DEBUG0("Free request %p", req);
    onion_dict_free(req->headers);

    if (req->connection.listen_point!=NULL && req->connection.listen_point->close)
        req->connection.listen_point->close(req);
    if (req->fullpath)
        onion_low_free(req->fullpath);
    if (req->GET)
        onion_dict_free(req->GET);
    if (req->POST)
        onion_dict_free(req->POST);
    if (req->FILES) {
        onion_dict_preorder(req->FILES, unlink_files, NULL);
        onion_dict_free(req->FILES);
    }
    if (req->session) {
        if (onion_dict_count(req->session)==0)
            onion_request_session_free(req);
        else {
            onion_sessions_save(req->connection.listen_point->server->sessions, req->session_id, req->session);
            onion_dict_free(req->session); // Not really remove, just dereference
            onion_low_free(req->session_id);
        }
    }
    if (req->data)
        onion_block_free(req->data);
    if (req->connection.cli_info)
        onion_low_free(req->connection.cli_info);

    if (req->websocket)
        onion_websocket_free(req->websocket);

    if (req->parser_data) {
        onion_low_free(req->parser_data);
    }
    if (req->cookies)
        onion_dict_free(req->cookies);
    if (req->free_list) {
        onion_ptr_list_foreach(req->free_list, onion_low_free);
        onion_ptr_list_free(req->free_list);
    }
    onion_low_free(req);
}
Ejemplo n.º 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;
}
Ejemplo n.º 16
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.º 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);
}
Ejemplo n.º 18
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.º 19
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.º 20
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.º 21
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.º 22
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;
}
Ejemplo n.º 23
0
/**
 * @short Removes the data used by the function.
 */
void function_free(function_data * d) {
  if (d->code)
    onion_block_free(d->code);
  free(d->id);
  free(d);
}
Ejemplo n.º 24
0
Archivo: dict.c Proyecto: rtmagic/onion
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;
}
Ejemplo n.º 25
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;
		}