/// Gets the output data int oterm_out(process *o, onion_request *req, onion_response *res){ pthread_mutex_lock(&o->mutex); if (onion_request_get_query(req, "initial")){ if (o->buffer[BUFFER_SIZE-1]!=0){ // If 0 then never wrote on it. So if not, write from pos to end too, first. onion_response_write(res, &o->buffer[o->buffer_pos], BUFFER_SIZE-o->buffer_pos); } onion_response_write(res, o->buffer, o->buffer_pos); onion_response_printf(res, "\033]oterm;%d;", o->buffer_pos); onion_response_printf(res, "\033]url;https://localhost:8080/uuid/%s/;", o->uuid); pthread_mutex_unlock(&o->mutex); return OCS_PROCESSED; } int16_t p=atoi(onion_request_get_queryd(req, "pos", "0")); //o->buffer_pos; ONION_DEBUG("Wait for data at %d", p); while(p==o->buffer_pos) // We need it to be diferent, if not does not make sense to wake up pthread_cond_wait(&o->dataReady, &o->mutex); ONION_DEBUG("Data ready at %d (waiting from %d)", o->buffer_pos, p); if (o->buffer_pos<p){ onion_response_write(res, &o->buffer[p], BUFFER_SIZE-p); p=0; } onion_response_write(res, &o->buffer[p], o->buffer_pos-p); onion_response_printf(res, "\033]oterm;%d;", o->buffer_pos); pthread_mutex_unlock(&o->mutex); return OCS_PROCESSED; }
/** * @short Writes all the header to the given response * @memberof onion_response_t * @ingroup response * * 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) { if (!res->request) { ONION_ERROR ("Bad formed response. Need a request at creation. Will not write headers."); return -1; } 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; }
onion_connection_status handle_bad_answer_question(void *data, onion_request *req, onion_response *res) { trivia_question const* const q = data; trivia_response_print_head(res); onion_response_printf(res, "%s<br>", trivia_bad_answer_message); onion_response_printf(res, q->ask); trivia_response_form_with_button(res, "Submit", q->uri, ".data"); trivia_response_print_tail(res); return OCS_PROCESSED; }
int hello(void *p, onion_request * req, onion_response * res) { //onion_response_set_length(res, 11); onion_response_write0(res, "Hello world"); if (onion_request_get_query(req, "1")) { onion_response_printf(res, "<p>Path: %s", onion_request_get_query(req, "1")); } onion_response_printf(res, "<p>Client description: %s", onion_request_get_client_description(req)); return OCS_PROCESSED; }
onion_connection_status handle_done(void *_, onion_request *req, onion_response *res) { done_count++; trivia_response_print_head(res); if(done_count == 1) { lamp->have_winner = 1; onion_response_printf(res, trivia_end.winner_message, done_count); } else { onion_response_printf(res, trivia_end.other_message, done_count); } trivia_response_print_tail(res); return OCS_PROCESSED; }
/* * Here's the routine that will replace the standard error_exit method: */ void onion_error_exit (j_common_ptr cinfo) { /* cinfo->err really points to a onion_error_mgr struct, so coerce pointer */ onion_error_ptr myerr = (onion_error_ptr) cinfo->err; /* Always display the message. */ /* We could postpone this until after returning, if we chose. */ //(*cinfo->err->output_message) (cinfo); /* Create the message */ char* msg = (char *) malloc( JMSG_LENGTH_MAX); ( *(cinfo->err->format_message) ) (cinfo, msg); onion_jpeg_data *d=(onion_jpeg_data*)cinfo->client_data; if (!d->sent){ onion_response_set_code(d->res, HTTP_INTERNAL_ERROR); onion_response_printf(d->res, "Libpng error: %s", msg); d->sent=1; } ONION_ERROR("%s", msg); free(msg); msg=NULL; /* Return control to the setjmp point */ longjmp(myerr->setjmp_buffer, 1); }
void t05_printf(){ INIT_LOCAL(); onion *server=onion_new(0); onion_add_listen_point(server,NULL,NULL,onion_buffer_listen_point_new()); onion_request *request; char buffer[4096]; memset(buffer,0,sizeof(buffer)); request=onion_request_new(server->listen_points[0]); onion_response *response=onion_response_new(request); onion_response_printf(response, "%s %d %p", "Hello world", 123, NULL); onion_response_flush(response); onion_response_free(response); buffer[sizeof(buffer)-1]=0; strncpy(buffer,onion_buffer_listen_point_get_buffer_data(request),sizeof(buffer)-1); onion_request_free(request); onion_free(server); FAIL_IF_NOT_STRSTR(buffer, "Hello world 123 (nil)"); END_LOCAL(); }
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; }
onion_connection_status handle_start(void *_, onion_request *req, onion_response *res) { trivia_response_print_head(res); onion_response_printf(res, trivia_start_message); trivia_response_print_button(res, "Start", trivia_questions->uri); trivia_response_print_tail(res); return OCS_PROCESSED; }
void trivia_response_print_button(onion_response* res, char *name, char *dest) { onion_response_printf(res, "<form class=\"button-primary\" method=\"POST\" action=\"%s\">" "<input type=\"submit\" value=\"%s\" autofocus>" "</form>", dest, name); }
void trivia_response_form_with_button(onion_response* res, char *name, char *dest, char *dest_postfix) { onion_response_printf(res, "<form class=\"button-primary\" method=\"POST\" action=\"%s%s\">" "<input type=\"text\" name=\"answer\" autofocus>" "<input type=\"submit\" value=\"%s\">" "</form>", dest, dest_postfix, name); }
// If not sent yet, writes the error. also always write it to the log. static void error(png_struct *p, const char *msg){ onion_png_data *d=(onion_png_data*)png_get_io_ptr(p); if (!d->sent){ onion_response_set_code(d->res, HTTP_INTERNAL_ERROR); onion_response_printf(d->res, "Libpng error: %s", msg); d->sent=1; } ONION_ERROR("%s", msg); }
bool print_reqn(int *n, reqres_t * reqres) { ONION_INFO("Writing %d to %p", *n, reqres->res); onion_response_printf(reqres->res, "%d\n", *n); int err = onion_response_flush(reqres->res); if (err < 0) { // Manually close connection free_reqres(reqres); ONION_INFO("Closed connection."); return false; } return true; }
static onion_connection_status ask_session(void *_, onion_request *req, onion_response *res){ onion_dict *session=onion_request_get_session_dict(req); if (set_data_on_session) onion_dict_add(session,"Test","New data to create the session",0); has_set_cookie=0; onion_response_write0(res, "If I write before getting session, then there is no Set-Cookie.\n"); onion_response_printf(res, "%d elements at the session.\n", onion_dict_count(session)); ONION_DEBUG("Session ID is %s, cookies %s",req->session_id, onion_request_get_header(req, "Cookie")); strcpy(lastsessionid, req->session_id); return OCS_PROCESSED; }
onion_connection_status method(void *ignore, onion_request *req, onion_response *res){ if (onion_response_write_headers(res)==OR_SKIP_CONTENT) // Head return OCS_PROCESSED; onion_response_write0(res, "<html><body>\n<h1>Petition resume</h1>\n"); int flags=onion_request_get_flags(req); if (flags&OR_GET) onion_response_write0(res,"<h2>GET"); else if (flags&OR_POST) onion_response_write0(res,"<h2>POST"); else onion_response_write0(res,"<h2>UNKNOWN"); onion_response_printf(res," %s</h2>\n<ul>",onion_request_get_path(req)); const onion_dict *get=onion_request_get_query_dict(req); const onion_dict *post=onion_request_get_post_dict(req); const onion_dict *headers=onion_request_get_header_dict(req); onion_response_printf(res,"<li>Header %d elements<ul>",onion_dict_count(headers)); if (headers) onion_dict_preorder(headers, print_dict_element, res); onion_response_printf(res,"</ul></li>\n"); onion_response_printf(res,"<li>GET %d elements<ul>",onion_dict_count(get)); if (get) onion_dict_preorder(get, print_dict_element, res); onion_response_printf(res,"</ul></li>\n"); onion_response_printf(res,"<li>POST %d elements<ul>",onion_dict_count(post)); if (post) onion_dict_preorder(post, print_dict_element, res); onion_response_printf(res,"</ul></li>\n"); onion_response_write0(res,"<p>\n"); onion_response_write0(res,"<form method=\"GET\">" "<input type=\"text\" name=\"test\">" "<input type=\"submit\" name=\"submit\" value=\"GET\">" "</form><p>\n"); onion_response_write0(res,"<form method=\"POST\" enctype=\"application/x-www-form-urlencoded\">" "<textarea name=\"text\"></textarea>" "<input type=\"text\" name=\"test\">" "<input type=\"submit\" name=\"submit\" value=\"POST urlencoded\">" "</form>" "<p>\n"); onion_response_write0(res,"<form method=\"POST\" enctype=\"multipart/form-data\">" "<input type=\"file\" name=\"file\">" "<textarea name=\"text\"></textarea>" "<input type=\"text\" name=\"test\">" "<input type=\"submit\" name=\"submit\" value=\"POST multipart\">" "</form>" "<p>\n"); onion_response_write0(res,"</body></html>"); return OCS_PROCESSED; }
/// Default directory handler: The style + dirname on a h1 void onion_handler_export_local_header_default(onion_response *res, const char *dirname){ onion_response_write0(res, "<style>body{ background: #fefefe; font-family: sans-serif; margin-left: 5%; margin-right: 5%; }\n" " table{ background: white; width: 100%; border: 1px solid #aaa; border-radius: 5px; -moz-border-radius: 5px; } \n" " th{ background: #eee; } tbody tr:hover td{ background: yellow; } tr.dir td{ background: #D4F0FF; }\n" " table a{ display: block; } th{ cursor: pointer} h1,h2{ color: black; text-align: center; } \n" " a{ color: red; text-decoration: none; }</style>\n"); onion_response_printf(res,"<h1>Listing of directory %s</h1>\n",dirname); if (dirname[0]!='\0' && dirname[1]!='\0') // It will be 0, when showpath is "/" onion_response_write0(res,"<h2><a href=\"..\">Go up..</a></h2>\n"); }
/** * @short Handler that just echoes all data, writing what was a header, what the method... */ onion_connection_status allinfo_handler(void *data, onion_request *req){ onion_response *res=onion_response_new(req); onion_response_write_headers(res); int f=onion_request_get_flags(req); onion_response_printf(res, "Method: %s\n",(f&OR_GET) ? "GET" : (f&OR_HEAD) ? "HEAD" : "POST"); onion_response_printf(res, "Path: %s\n",onion_request_get_path(req)); onion_response_printf(res, "Version: %s\n",onion_request_get_flags(req)&OR_HTTP11 ? "HTTP/1.1" : "HTTP/1.0"); allinfo_dict_print_t aid; aid.res=res; aid.part="Query"; onion_dict_preorder(onion_request_get_query_dict(req),allinfo_query, &aid); aid.part="Header"; onion_dict_preorder(onion_request_get_header_dict(req),allinfo_query, &aid); aid.part="POST"; onion_dict_preorder(onion_request_get_post_dict(req),allinfo_query, &aid); aid.part="FILE"; onion_dict_preorder(onion_request_get_file_dict(req),allinfo_query, &aid); return onion_response_free(res);; }
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); }
onion_connection_status handler(void *request_list_v, onion_request * req, onion_response * res) { // Some hello message onion_response_printf(res, "Starting poll\n"); onion_response_flush(res); // Add it to the request_list lists. request_list_t *request_list = request_list_v; reqres_t *reqres = onion_low_malloc(sizeof(reqres_t)); reqres->req = req; reqres->res = res; pthread_mutex_lock(&request_list->lock); request_list->reqres = onion_ptr_list_add(request_list->reqres, reqres); pthread_mutex_unlock(&request_list->lock); // Yield thread to the poller, ensures request and response are not freed. return OCS_YIELD; }
/** * @short Returns the directory listing */ int onion_handler_export_local_directory(onion_handler_export_local_data *data, const char *realp, const char *showpath, onion_request *req, onion_response *res){ DIR *dir=opendir(realp); if (!dir) // Continue on next. Quite probably a custom error. return 0; onion_response_set_header(res, "Content-Type", "text/html; charset=utf-8"); onion_response_write0(res,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" "<html>\n" " <head><meta content=\"text/html; charset=UTF-8\" http-equiv=\"content-type\"/>\n"); onion_response_printf(res,"<title>Directory listing of %s</title>\n",showpath); onion_response_write0(res,"</head>\n" " <body>\n" "<script>\n" "showListing = function(){\n" " var q = function(t){\n" " return t.replace('\"','%22')\n" " } \n" " var t=document.getElementById('filebody')\n" " while ( t.childNodes.length >= 1 )\n" " t.removeChild( t.firstChild ); \n" " for (var i=0;i<files.length;i++){\n" " var f=files[i]\n" " var h='<tr class=\"'+f[3]+'\"><td><a href=\"'+q(f[0])+'\">'+f[0]+'</a></td><td>'+f[1]+'</td><td>'+f[2]+'</td></tr>'\n" " t.innerHTML+=h\n" " }\n" "}\n" "\n" "update = function(n){\n" " var _cmp = function(a,b){\n" " if (a[n]<b[n])\n" " return -1\n" " if (a[n]>b[n])\n" " return 1\n" " return 0\n" " }\n" " files=files.sort(_cmp)\n" " showListing()\n" "}\n" "window.onload=function(){\n" " files=files.splice(0,files.length-1)\n" " update(0)\n" "}\n" "\n" "files=[\n"); struct dirent *fi; struct stat st; char temp[1024]; struct passwd *pwd; while ( (fi=readdir(dir)) != NULL ){ if (fi->d_name[0]=='.') continue; snprintf(temp,sizeof(temp),"%s/%s",realp,fi->d_name); stat(temp, &st); pwd=getpwuid(st.st_uid); if (S_ISDIR(st.st_mode)) onion_response_printf(res, " ['%s/',%d,'%s','dir'],\n",fi->d_name, st.st_size, pwd ? pwd->pw_name : "???"); else onion_response_printf(res, " ['%s',%d,'%s','file'],\n",fi->d_name, st.st_size, pwd ? pwd->pw_name : "???"); } onion_response_write0(res," [] ]\n</script>\n"); if (data->renderer_header) data->renderer_header(res, showpath); onion_response_write0(res,"<table id=\"filelist\">\n" "<thead><tr>\n" " <th onclick=\"update(0)\" id=\"filename\">Filename</th>\n" " <th onclick=\"update(1)\" id=\"size\">Size</th>" " <th onclick=\"update(2)\" id=\"owner\">Owner</th></tr>\n" "</thead>\n" "<tbody id=\"filebody\">\n</tbody>\n</table>\n</body>\n"); if (data->renderer_footer) data->renderer_footer(res, showpath); onion_response_write0(res,"</body></html>"); closedir(dir); return OCS_PROCESSED; }
static int api_mail_do_post(ONION_FUNC_PROTO_STR, int mode) { const char * userid = onion_request_get_query(req, "userid"); const char * appkey = onion_request_get_query(req, "appkey"); const char * sessid = onion_request_get_query(req, "sessid"); const char * token = onion_request_get_query(req, "token"); const char * to_userid = onion_request_get_query(req, "to_userid"); const char * title = onion_request_get_query(req, "title"); const char * backup = onion_request_get_query(req, "backup"); if(!userid || !appkey || !sessid || !title || !to_userid || !token) return api_error(p, req, res, API_RT_WRONGPARAM); struct userec *ue = getuser(userid); if(!ue) return api_error(p, req, res, API_RT_NOSUCHUSER); struct userec currentuser; memcpy(¤tuser, ue, sizeof(currentuser)); free(ue); int r = check_user_session(¤tuser, sessid, appkey); if(r != API_RT_SUCCESSFUL) { return api_error(p, req, res, r); } if(HAS_PERM(PERM_DENYMAIL)) { return api_error(p, req, res, API_RT_MAILNOPPERM); } int uent_index = get_user_utmp_index(sessid); struct user_info *ui = &(shm_utmp->uinfo[uent_index]); if(strcmp(ui->token, token) != 0) { return api_error(p, req, res, API_RT_WRONGTOKEN); } // 更新 token 和来源 IP getrandomstr_r(ui->token, TOKENLENGTH+1); const char * fromhost = onion_request_get_header(req, "X-Real-IP"); memset(ui->from, 0, 20); strncpy(ui->from, fromhost, 20); if(check_user_maxmail(currentuser)) { return api_error(p, req, res, API_RT_MAILFULL); } struct userec *to_user = getuser(to_userid); if(!to_user) { return api_error(p, req, res, API_RT_NOSUCHUSER); } if(inoverride(currentuser.userid, to_user->userid, "rejects")) { free(to_user); return api_error(p, req, res, API_RT_INUSERBLIST); } const char * data = onion_request_get_post(req, "content"); char filename[80]; sprintf(filename, "bbstmpfs/tmp/%s_%s.tmp", currentuser.userid, ui->token); char * data2 = strdup(data); while(strstr(data2, "[ESC]") != NULL) data2 = string_replace(data2, "[ESC]", "\033"); char * data_gbk = (char *)malloc(strlen(data2)*2); u2g(data2, strlen(data2), data_gbk, strlen(data2)*2); f_write(filename, data_gbk); free(data2); int mark=0; // 文件标记 //if(insertattachments(filename, data_gbk, currentuser->userid)>0) //mark |= FH_ATTACHED; free(data_gbk); char * title_tmp = (char *)malloc(strlen(title)*2); u2g(title, strlen(title), title_tmp, strlen(title)*2); char title_gbk[80], title_tmp2[80]; strncpy(title_gbk, title_tmp[0]==0 ? "No Subject" : title_tmp, 80); snprintf(title_tmp2, 80, "{%s} %s", to_user->userid, title); free(title_tmp); r = do_mail_post(to_user->userid, title, filename, currentuser.userid, currentuser.username, fromhost, 0, mark); if(backup && strcasecmp(backup, "true")==0) { do_mail_post_to_sent_box(currentuser.userid, title_tmp2, filename, currentuser.userid, currentuser.username, fromhost, 0, mark); } unlink(filename); free(to_user); if(r<0) { return api_error(p, req, res, API_RT_MAILINNERR); } api_set_json_header(res); onion_response_printf(res, "{ \"errcode\":0, \"token\":\"%s\" }", ui->token); return OCS_PROCESSED; }
void trivia_response_print_head(onion_response* res) { onion_response_printf(res, PAGE_HEAD, trivia_title); }
void trivia_response_print_tail(onion_response* res) { onion_response_printf(res, PAGE_TAIL); }