void t07_replace(){ INIT_LOCAL(); onion_dict *dict=onion_dict_new(); onion_dict_add(dict,"a","1", OD_DUP_ALL|OD_REPLACE); onion_dict_add(dict,"a","1", OD_REPLACE); onion_dict_add(dict,"a","1", OD_DUP_ALL|OD_REPLACE); onion_dict_add(dict,"a","1", OD_REPLACE); onion_dict_add(dict,"a","1", OD_DUP_ALL|OD_REPLACE); int n=0; onion_dict_preorder(dict, t07_sum, &n); FAIL_IF_NOT_EQUAL_INT(n,1); onion_dict_add(dict,"a","1", 0); n=0; onion_dict_preorder(dict, t07_sum, &n); FAIL_IF_NOT_EQUAL_INT(n,2); onion_dict_free(dict); END_LOCAL(); }
/** * @short Just asks the user for the answer. */ onion_connection_status ask_handler(void *none, onion_request *req, onion_response *res){ char temp[1024]; strcpy(temp, onion_request_get_path(req)); onion_dict_preorder(onion_request_get_query_dict(req),format_query,temp); char *resp=ask_question(temp); if (!resp) return OCS_INTERNAL_ERROR; onion_response_write0(res, resp); free(resp); return OCS_PROCESSED; }
void t11_hard_dup(){ INIT_LOCAL(); onion_dict *orig=onion_dict_new(); char tmp[9]; int i; for (i=0;i<256;i++){ sprintf(tmp,"%08X",rand()); onion_dict_add(orig, tmp, tmp, OD_DUP_ALL); } onion_dict_add(orig, "0", "no frees", 0); onion_dict *dest=onion_dict_hard_dup(orig); /// Check they have exactly the same keys. onion_dict_preorder(orig, cmpdict, dest); onion_dict_preorder(dest, cmpdict, orig); onion_dict_free(orig); onion_dict_free(dest); END_LOCAL(); }
/** * @short Writes all the header to the given response * @memberof onion_response_t * * It writes the headers and depending on the method, return OR_SKIP_CONTENT. this is set when in head mode. Handlers * should react to this return by not trying to write more, but if they try this object will just skip those writtings. * * Explicit calling to this function is not necessary, as as soon as the user calls any write function this will * be performed. * * As soon as the headers are written, any modification on them will be just ignored. * * @returns 0 if should procced to normal data write, or OR_SKIP_CONTENT if should not write content. */ int onion_response_write_headers(onion_response *res){ res->flags|=OR_HEADER_SENT; // I Set at the begining so I can do normal writing. res->request->flags|=OR_HEADER_SENT; char chunked=0; if (res->request->flags&OR_HTTP11){ onion_response_printf(res, "HTTP/1.1 %d %s\r\n",res->code, onion_response_code_description(res->code)); //ONION_DEBUG("Response header: HTTP/1.1 %d %s\n",res->code, onion_response_code_description(res->code)); if (!(res->flags&OR_LENGTH_SET) && onion_request_keep_alive(res->request)){ onion_response_write(res, CONNECTION_CHUNK_ENCODING, sizeof(CONNECTION_CHUNK_ENCODING)-1); chunked=1; } } else{ onion_response_printf(res, "HTTP/1.0 %d %s\r\n",res->code, onion_response_code_description(res->code)); //ONION_DEBUG("Response header: HTTP/1.0 %d %s\n",res->code, onion_response_code_description(res->code)); if (res->flags&OR_LENGTH_SET) // On HTTP/1.0, i need to state it. On 1.1 it is default. onion_response_write(res, CONNECTION_KEEP_ALIVE, sizeof(CONNECTION_KEEP_ALIVE)-1); } if (!(res->flags&OR_LENGTH_SET) && !chunked && !(res->flags&OR_CONNECTION_UPGRADE)) onion_response_write(res, CONNECTION_CLOSE, sizeof(CONNECTION_CLOSE)-1); if (res->flags&OR_CONNECTION_UPGRADE) onion_response_write(res, CONNECTION_UPGRADE, sizeof(CONNECTION_UPGRADE)-1); onion_dict_preorder(res->headers, write_header, res); if (res->request->session_id && (onion_dict_count(res->request->session)>0)) // I have session with something, tell user onion_response_printf(res, "Set-Cookie: sessionid=%s; httponly; Path=/\n", res->request->session_id); onion_response_write(res,"\r\n",2); ONION_DEBUG0("Headers written"); res->sent_bytes=-res->buffer_pos; // the header size is not counted here. It will add again so start negative. if ((res->request->flags&OR_METHODS)==OR_HEAD){ onion_response_flush(res); res->flags|=OR_SKIP_CONTENT; return OR_SKIP_CONTENT; } if (chunked){ onion_response_flush(res); res->flags|=OR_CHUNKED; } return 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); }
onion_connection_status sessions(void *ignore, onion_request *req){ onion_response *res=onion_response_new(req); onion_dict *session=onion_request_get_session_dict(req); if (onion_request_get_query(req, "reset")){ onion_request_session_free(req); onion_response_write0(res, "ok"); return onion_response_free(res); } const char *n=onion_dict_get(session, "count"); int count; if (n){ count=atoi(n)+1; } else count=0; char tmp[16]; snprintf(tmp,sizeof(tmp),"%d",count); onion_dict_add(session, "count", tmp, OD_DUP_ALL|OD_REPLACE); if (onion_response_write_headers(res)==OR_SKIP_CONTENT) // Head return onion_response_free(res); onion_response_write0(res, "<html><body>\n<h1>Session data</h1>\n"); if (session){ onion_response_printf(res,"<ul>\n"); onion_dict_preorder(session, print_dict_element, res); onion_response_printf(res,"</ul>\n"); } else{ onion_response_printf(res,"No session data"); } onion_response_write0(res,"</body></html>"); return onion_response_free(res); }
void t05_preorder(){ INIT_LOCAL(); onion_dict *dict; dict=onion_dict_new(); onion_dict_add(dict,"A","B",0); onion_dict_add(dict,"C","D",0); onion_dict_add(dict,"E","F",0); onion_dict_add(dict,"G","H",0); onion_dict_add(dict,"I","J",0); onion_dict_add(dict,"K","L",0); onion_dict_add(dict,"M","N",0); onion_dict_add(dict,"O","P",0); onion_dict_add(dict,"Q","R",0); onion_dict_add(dict,"S","T",0); char buffer[4096]; memset(buffer,0,sizeof(buffer)); onion_dict_preorder(dict, append_as_headers, buffer); FAIL_IF_NOT_EQUAL_STR(buffer,"A: B\nC: D\nE: F\nG: H\nI: J\nK: L\nM: N\nO: P\nQ: R\nS: T\n"); onion_dict_free(dict); END_LOCAL(); }
/** * @short Creates a full duplicate of the dict * @memberof onion_dict_t * * Its actually the same, but with refcount increased, so future frees will free the dict * only on latest one. * * Any change on one dict is made also on the other one, as well as rwlock... This is usefull on a multhreaded * environment so that multiple threads cna have the same dict and free it when not in use anymore. */ onion_dict *onion_dict_hard_dup(onion_dict *dict){ onion_dict *d=onion_dict_new(); onion_dict_preorder(dict, onion_dict_hard_dup_helper, d); return d; }
/** * @short memberof onion_dict_t * * Meres the contents of other dictionary intro me. * * @param me The current dictionary where keys: vlaues will be added * @param other Dictionary with keys to add to me */ void onion_dict_merge(onion_dict *me, const onion_dict *other){ onion_dict_preorder(other, onion_dict_add_merge, me); }
/** * @short Cleans a request object to reuse it. * @memberof onion_request_t * @ingroup request */ 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->PUT){ onion_dict_free(req->PUT); req->PUT=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; } }