/// Plexes the request depending on arguments. int oterm_get_data(oterm_data *data, onion_request *req, onion_response *res){ const char *username=onion_request_get_session(req,"username"); if (!username){ ONION_WARNING("Trying to enter authenticated area without username."); return OCS_FORBIDDEN; } oterm_session *o=(oterm_session*)onion_dict_get(data->sessions, onion_request_get_session(req,"username")); if (!o){ o=oterm_session_new(); onion_dict_lock_write(data->sessions); onion_dict_add(data->sessions,onion_request_get_session(req,"username"),o, 0); onion_dict_unlock(data->sessions); } const char *path=onion_request_get_path(req); ONION_DEBUG("Ask path %s (%p)", path, data); if (strcmp(path,"new")==0){ if (onion_request_get_post(req, "command")){ free(data->exec_command); data->exec_command=strdup(onion_request_get_post(req, "command")); } oterm_new(data, o, onion_request_get_session(req, "username"), onion_request_get_session(req, "nopam") ? 0 : 1 ); return onion_shortcut_response("ok", 200, req, res); } if (strcmp(path,"status")==0) return oterm_status(o,req, res); return OCS_NOT_PROCESSED; }
void t05_create_add_free_POST(){ INIT_LOCAL(); onion_request *req; int ok; req=onion_request_new(custom_io); FAIL_IF_EQUAL(req,NULL); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); const char *query="POST /myurl%20/is/very/deeply/nested?test=test&query2=query%202&more_query=%20more%20query+10 HTTP/1.0\n" "Host: 127.0.0.1\n\rContent-Length: 50\n" "Other-Header: My header is very long and with spaces...\r\n\r\nempty_post=&post_data=1&post_data2=2&empty_post_2=\n"; int i; // Straight write, with clean (keep alive like) for (i=0;i<10;i++){ FAIL_IF_NOT_EQUAL(req->flags,0); ok=REQ_WRITE(req,query); FAIL_IF_NOT_EQUAL(ok, OCS_CLOSE_CONNECTION); FAIL_IF_EQUAL(req->flags,OR_GET|OR_HTTP11); FAIL_IF_EQUAL(req->headers, NULL); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->headers,"Host"), "127.0.0.1"); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->headers,"Other-Header"), "My header is very long and with spaces..."); FAIL_IF_NOT_EQUAL_STR(req->fullpath,"/myurl /is/very/deeply/nested"); FAIL_IF_NOT_EQUAL_STR(req->path,"myurl /is/very/deeply/nested"); FAIL_IF_EQUAL(req->GET,NULL); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->GET,"test"), "test"); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->GET,"query2"), "query 2"); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->GET,"more_query"), " more query 10"); const onion_dict *post=onion_request_get_post_dict(req); FAIL_IF_EQUAL(post,NULL); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(post,"post_data"), "1"); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(post,"post_data2"), "2"); FAIL_IF_NOT_EQUAL_STR( onion_request_get_post(req, "empty_post"), ""); FAIL_IF_NOT_EQUAL_STR( onion_request_get_post(req, "empty_post_2"), ""); onion_request_clean(req); FAIL_IF_NOT_EQUAL(req->GET,NULL); } onion_request_free(req); END_LOCAL(); }
onion_connection_status upload_file(upload_file_data *data, onion_request *req, onion_response *res){ if (onion_request_get_flags(req)&OR_POST){ const char *name=onion_request_get_post(req,"file"); const char *filename=onion_request_get_file(req,"file"); if (name && filename){ char finalname[1024]; snprintf(finalname,sizeof(finalname),"%s/%s",data->abspath,name); ONION_DEBUG("Copying from %s to %s",filename,finalname); unlink(finalname); // Just try to unlink it, if fail, sure its because it does not exist. int src=open(filename,O_RDONLY); int dst=open(finalname, O_WRONLY|O_CREAT, 0666); if (!src || !dst){ ONION_ERROR("Could not open src or dst file (%d %d)",src,dst); return OCS_INTERNAL_ERROR; } ssize_t r,w; char buffer[1024*4]; while ( (r=read(src,buffer,sizeof(buffer))) > 0){ w=write(dst,buffer,r); if (w!=r){ ONION_ERROR("Error writing file"); break; } } close(src); close(dst); } } return 0; // I just ignore the request, but process over the FILE data }
/// Resize the window. int oterm_resize(process *p, onion_request* req, onion_response *res){ //const char *data=onion_request_get_query(req,"resize"); //int ok=kill(o->pid, SIGWINCH); struct winsize winSize; memset(&winSize, 0, sizeof(winSize)); const char *t=onion_request_get_post(req,"width"); winSize.ws_row = (unsigned short)atoi(t ? t : "80"); t=onion_request_get_post(req,"height"); winSize.ws_col = (unsigned short)atoi(t ? t : "25"); int ok=ioctl(p->fd, TIOCSWINSZ, (char *)&winSize) == 0; if (ok>=0) return onion_shortcut_response("OK",HTTP_OK, req, res); else return onion_shortcut_response("Error",HTTP_INTERNAL_ERROR, req, res); }
/// Sets internally the window title, for reference. int oterm_title(process *p, onion_request* req, onion_response *res){ const char *t=onion_request_get_post(req, "title"); if (!t) return onion_shortcut_response("Error, must set title", HTTP_INTERNAL_ERROR, req, res); if (p->title) free(p->title); p->title=strdup(t); ONION_DEBUG("Set term %d title %s", p->pid, p->title); return onion_shortcut_response("OK", HTTP_OK, req, res); }
/// Input data to the process int oterm_in(process *p, onion_request *req, onion_response *res){ oterm_check_running(p); const char *data; data=onion_request_get_post(req,"type"); ssize_t w; if (data){ //fprintf(stderr,"%s:%d write %ld bytes\n",__FILE__,__LINE__,strlen(data)); size_t r=strlen(data); w=write(p->fd, data, r); if (w!=r){ ONION_WARNING("Error writing data to process. Not all data written. (%d).",w); return onion_shortcut_response("Error", HTTP_INTERNAL_ERROR, req, res); } } return onion_shortcut_response("OK", HTTP_OK, req, res); }
onion_connection_status check_answer(void *privdata, onion_request *req, onion_response *res) { trivia_question const* const q = privdata; if (onion_request_get_flags(req)&OR_HEAD){ onion_response_write_headers(res); return OCS_PROCESSED; } const char *answer = onion_request_get_post(req,"answer"); const char *uri; if(strcmp_ignoring_case_and_whitespace(q->correct_answer, answer) == 0) { lamp->green = 65535; uri = q->correct_uri; } else { lamp->red = 65535; uri = q->again_uri; } return onion_shortcut_response_extra_headers("<h1>302 - Moved</h1>", HTTP_REDIRECT, req, res, "Location", uri, NULL ); }
/* return value marks, if reply string contains data which should * return to the web client: * -2: No data written into reply. Input generate error. Currently, it's not handled. * -1: No data written into reply. Input generate state which require reloading of web page. * 0: data written into reply * 1: No data written into reply, but input processed successful.*/ bool OnionServer::updateWebserver( Onion::Request *preq, int actionid, Onion::Response *pres ){ VPRINT("Actionid: %i \n", actionid); switch(actionid){ case 4: { /* Command Message */ const char* json_str = onion_request_get_post(preq->c_handler(), "cmd"); std::string reply; if( json_str != NULL){ Messages &q = m_b9CreatorSettings.m_queues; std::string cmd(json_str); q.add_command(cmd); reply = "ok"; }else{ reply = "missing post variable 'cmd'"; } pres->write(reply.c_str(), reply.size() ); return true; } break; case 3: { /* Quit */ std::string reply("quit"); pres->write(reply.c_str(), reply.size() ); printf("Quitting...\n"); m_b9CreatorSettings.lock(); m_b9CreatorSettings.m_die = true; m_b9CreatorSettings.unlock(); return true; } break; default: break; } return false; }
onion_connection_status post_check(expected_post *post, onion_request *req){ const char *filename=onion_request_get_post(req,"file"); const char *tmpfilename=onion_request_get_file(req,"file"); post->test_ok=1; ONION_DEBUG("Got filename %s, expected %s",filename,post->filename); if (strcmp(filename, post->filename)!=0){ ONION_ERROR("File names do not match: %s %s", filename, post->filename); post->test_ok=0; } ONION_DEBUG("Temporal file %s",tmpfilename); struct stat st; if (stat(tmpfilename, &st)!=0){ ONION_ERROR("Could not stat temp file"); post->test_ok=0; } if (st.st_size!=post->size){ ONION_ERROR("Size do not match, expected %d, got %d",post->size,st.st_size); post->test_ok=0; } char tmp[256]; snprintf(tmp,sizeof(tmp),"%s-",tmpfilename); ONION_DEBUG("Linking to %s", tmp); FAIL_IF_NOT_EQUAL(link(tmpfilename, tmp),0); if (post->tmplink) free(post->tmplink); post->tmplink=strdup(tmp); if (post->tmpfilename) free(post->tmpfilename); post->tmpfilename=strdup(tmpfilename); return OCS_INTERNAL_ERROR; }
int OnionServer::updateSetting(onion_request *req, onion_response *res){ int actionid = atoi( onion_request_get_queryd(req,"actionid","0") ); printf("Actionid: %i \n", actionid); switch(actionid){ case 8:{ //quit programm m_psettingKinectGrid->setMode(QUIT); } break; case 7:{ //load masks m_psettingKinectGrid->setMode(LOAD_MASKS); } break; case 6:{ //save masks m_psettingKinectGrid->setMode(SAVE_MASKS); } break; case 5:{ //select view //m_view = atoi( onion_request_get_queryd(req,"view","-1") ); m_view = atoi( onion_request_get_post(req,"view") ); printf("Set view to %i.\n",m_view); } break; case 4:{ //repoke printf("Repoke\n"); m_psettingKinectGrid->setMode(REPOKE_DETECTION); } break; case 3:{ // area detection int start = atoi( onion_request_get_queryd(req,"start","1") ); if( start == 1) m_psettingKinectGrid->setMode(AREA_DETECTION_START); else{ m_psettingKinectGrid->setMode(AREA_DETECTION_END); } } break; case 2:{ const char* filename = onion_request_get_post(req,"filename"); printf("Save new settingKinectGrid: %s\n",filename); if( check_filename(filename ) == 1){ m_psettingKinect->saveConfigFile(filename); m_psettingKinectGrid->setString("lastSetting",filename); m_psettingKinectGrid->saveConfigFile("settingKinectGrid.ini"); }else{ printf("Filename not allowed\n"); } /* force reload of website */ return 0; } break; case 1:{ const char* filename = onion_request_get_post(req,"filename"); printf("Load new settingKinectGrid: %s\n",filename); if( check_filename(filename ) == 1){ m_psettingKinect->loadConfigFile(filename); }else{ printf("Filename not allowed\n"); } return -1; } break; case 0: default:{ printf("update settingKinect values\n"); const char* json_str = onion_request_get_post(req,"settingKinect"); if( json_str != NULL){ //printf("Get new settingKinect: %s\n",json_str); m_psettingKinect->setConfig(json_str, NO); }else{ return -1; } } break; } return 0; }
/** * @short Gets a put data * @memberof onion_request_t * @ingroup request */ const char *onion_request_get_put(onion_request *req, const char *query){ return onion_request_get_post(req,query); }
void momf_canvasedit (struct mom_item_st *tkitm) { enum canvedit_closoff_en { mec_wexitm, mec_protowebstate, mec_thiswebstate, mec__last }; struct mom_item_st *wexitm = NULL; struct mom_item_st *thistatitm = NULL; struct mom_item_st *sessitm = NULL; struct mom_item_st *hsetitm = NULL; mom_item_lock (tkitm); const struct mom_boxnode_st *tknod = (struct mom_boxnode_st *) tkitm->itm_payload; MOM_DEBUGPRINTF (web, "momf_canvedit start tkitm=%s tknod=%s", mom_item_cstring (tkitm), mom_value_cstring ((const struct mom_hashedvalue_st *) tknod)); if (mom_itype (tknod) != MOMITY_NODE || mom_raw_size (tknod) < mec__last) { /// should not happen MOM_WARNPRINTF ("momf_canvedit bad tknod %s", mom_value_cstring ((const struct mom_hashedvalue_st *) tknod)); goto end; } { wexitm = mom_dyncast_item (tknod->nod_sons[mec_wexitm]); assert (wexitm && wexitm->va_itype == MOMITY_ITEM); mom_item_lock (wexitm); thistatitm = mom_dyncast_item (tknod->nod_sons[mec_thiswebstate]); assert (thistatitm && thistatitm->va_itype == MOMITY_ITEM); MOM_DEBUGPRINTF (web, "momf_canvedit tkitm=%s wexitm=%s paylkind %s thistatitm=%s", mom_item_cstring (tkitm), mom_item_cstring (wexitm), mom_itype_str (wexitm->itm_payload), mom_item_cstring (thistatitm)); mom_item_lock (thistatitm); } struct mom_webexch_st *wexch = (struct mom_webexch_st *) wexitm->itm_payload; assert (wexch && wexch->va_itype == MOMITY_WEBEXCH); sessitm = wexch->webx_sessitm; mom_item_lock (sessitm); MOM_DEBUGPRINTF (web, "momf_canvedit tkitm=%s wexch #%ld meth %s fupath %s sessitm %s", mom_item_cstring (tkitm), wexch->webx_count, mom_webmethod_name (wexch->webx_meth), onion_request_get_fullpath (wexch->webx_requ), mom_item_cstring (sessitm)); sessitm->itm_pcomp = mom_vectvaldata_resize (sessitm->itm_pcomp, mes__last); if (! (hsetitm = mom_dyncast_item (mom_vectvaldata_nth (sessitm->itm_pcomp, mes_itmhset)))) { hsetitm = mom_clone_item (MOM_PREDEFITM (hashset)); mom_vectvaldata_put_nth (sessitm->itm_pcomp, mes_itmhset, (struct mom_hashedvalue_st *) hsetitm); hsetitm->itm_payload = (struct mom_anyvalue_st *) mom_hashset_reserve (NULL, 20); MOM_DEBUGPRINTF (web, "momf_canvedit tkitm=%s wexch #%ld new hsetitm %s", mom_item_cstring (tkitm), wexch->webx_count, mom_item_cstring (hsetitm)); } else MOM_DEBUGPRINTF (web, "momf_canvedit tkitm=%s wexch #%ld got hsetitm %s", mom_item_cstring (tkitm), wexch->webx_count, mom_item_cstring (hsetitm)); mom_item_lock (hsetitm); if (wexch->webx_meth == MOMWEBM_POST) { const char *dofillcanvas = onion_request_get_post (wexch->webx_requ, "do_fillcanvas"); MOM_DEBUGPRINTF (web, "momf_canvedit tkitm=%s wexch #%ld do_fillcanvas %s", mom_item_cstring (tkitm), wexch->webx_count, dofillcanvas); if (dofillcanvas) dofillcanvas_canvedit_mom (wexch, tkitm, wexitm, thistatitm); } end: if (hsetitm) mom_item_unlock (hsetitm); if (thistatitm) mom_item_unlock (thistatitm); if (wexitm) mom_item_unlock (wexitm); if (sessitm) mom_item_unlock (sessitm); mom_item_unlock (tkitm); } /* end of momf_canvedit */
/* return value marks, if reply string contains data which should * return to the web client: * -3: No data written into reply. Input generate state which require reloading of web page. * -2: No data written into reply, but input processed successful. * -1: No data written into reply. Input has generate error. (Currently not used.) * 0: data written into reply * 1: data written, but error occours. * 2: two signals wrote data. The output is likely unuseable Old approach was: Signal return value is OR-Combination of signal handles. true: request handling succesful. false: no handler deals with the request. */ int OnionServer::updateWebserver( Onion::Request *preq, int actionid, Onion::Response *pres ){ VPRINT("Http action id: %i \n", actionid); switch(actionid){ case HTTP_ACTION_SEND_COMMAND: { /* Command Message, unused */ const char* json_str = onion_request_get_post(preq->c_handler(), "cmd"); std::string reply; if( json_str != NULL){ Messages &q = m_settingKinect.m_queues; std::string cmd(json_str); q.add_command(cmd); reply = "ok"; }else{ reply = "missing post variable 'cmd'"; } pres->write(reply.c_str(), reply.size() ); return 0; } break; case HTTP_ACTION_RESET_CONFIG:{ //reset config values to defaults. m_settingKinect.loadConfigFile(""); std::string reply("ok"); pres->write(reply.c_str(), reply.size() ); return 0; } break; case HTTP_ACTION_QUIT_PROGRAM:{ //quit programm std::string reply("quit"); pres->write(reply.c_str(), reply.size() ); VPRINT("Quitting...\n"); m_settingKinect.lock(); //m_settingKinect.m_die = true; m_settingKinect.setMode(QUIT); m_settingKinect.unlock(); return 0; } break; case HTTP_ACTION_LOAD_MASKS:{ //load masks m_settingKinect.setMode(LOAD_MASKS); std::string reply("ok"); pres->write(reply.c_str(), reply.size() ); return 0; } break; case HTTP_ACTION_SAVE_MASKS:{ //save masks m_settingKinect.setMode(SAVE_MASKS); std::string reply("ok"); pres->write(reply.c_str(), reply.size() ); return 0; } break; case HTTP_ACTION_SELECT_VIEW:{ //select view //m_view = atoi( onion_request_get_queryd(req,"view","0") ); m_view = (View) atoi( onion_request_get_post(preq->c_handler(),"view") ); VPRINT("Set view to %i.\n",(int)m_view); std::string reply("ok"); pres->write(reply.c_str(), reply.size() ); return 0; } break; case HTTP_ACTION_REPOKE:{ //repoke VPRINT("Repoke\n"); m_settingKinect.setMode(REPOKE_DETECTION); std::string reply("ok"); pres->write(reply.c_str(), reply.size() ); return 0; } break; case HTTP_ACTION_SET_AREA_DETECTION:{ // area detection int start = atoi( onion_request_get_post(preq->c_handler(),"start") ); if( start == 1) m_settingKinect.setMode(AREA_DETECTION_START); else{ m_settingKinect.setMode(AREA_DETECTION_END); } std::string reply("ok"); pres->write(reply.c_str(), reply.size() ); return 0; } break; case HTTP_ACTION_SAVE_CONFIG:{ const char* configFilename = onion_request_get_post(preq->c_handler(), "configFilename"); VPRINT("Save new settingKinectGrid: %s\n",configFilename); if( check_configFilename(configFilename) ){ m_settingKinect.saveConfigFile(configFilename); //m_settingKinect.setString("lastSetting",configFilename); //m_settingKinect.saveConfigFile("settingKinectGrid.ini"); }else{ VPRINT("Filename not allowed\n"); } std::string reply("ok"); pres->write(reply.c_str(), reply.size() ); return 0; } break; case HTTP_ACTION_LOAD_CONFIG:{ const char* configFilename = onion_request_get_post(preq->c_handler(), "configFilename"); VPRINT("Load new settingKinectGrid: %s\n",configFilename); if( check_configFilename(configFilename) ){ m_settingKinect.loadConfigFile(configFilename); }else{ printf("Filename not allowed\n"); } /* force reload of website */ std::string reply("reload"); pres->write(reply.c_str(), reply.size() ); return 0; } break; //case 0: // this case will be handled in webserverUpdateConfig default:{ } break; } return -3; }
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; }