/** * @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); }
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(); }
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(); }
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); }
/** * @short Adds some code to a given function. */ void function_add_code_f(struct function_data_t *f, const char *fmt, ...) { char tmp[4096]; va_list ap; va_start(ap, fmt); vsnprintf(tmp, sizeof(tmp), fmt, ap); va_end(ap); //ONION_DEBUG("Add to level %d text %s",list_count(st->function_stack), tmp); onion_block_add_str(f->code, tmp); }
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); }
/** * @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); } }
/** * @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; }