📄 cgi.cpp
字号:
#include "cgi.h"CGI::CGI() { stdin=fopen("aa","r"); request_method=INTERACTIVE; is_multipart=false; char *method; method=getenv("REQUEST_METHOD"); if(!method) request_method=INTERACTIVE; else if(!strcmp(method,"POST")) request_method=POST; else if(!strcmp(method,"GET")) request_method=GET; else if(!strcmp(method,"HEAD")) request_method=HEAD; if(request_method==POST) { if(isMultyPart()) { is_multipart=true; buildMultyPart(); return; } } switch(request_method) { case POST: getPostQuery(); break; case GET: getGetQuery(); break; case HEAD: getHeadQuery(); break; case INTERACTIVE: cout << "Switching to interactive mode...\n"; getInteractiveQuery(); break; default: query_string=""; } if(request_method==INTERACTIVE) getInteractiveCookie(); else getStdCookie(); decodeQuery(); decodeCookie(); parseQuery(); parseCookie();}CGI::~CGI() {}string CGI::getQVal(const string &key,int id=0) { map<string,vector<control *> >::const_iterator ci=extended_query_map.find(key); if(ci==extended_query_map.end()) { return ""; } else { if((ci->second)[id]->is_in_file) { return ""; } else { return (extended_query_map[key])[id]->value; } }}FILE *CGI::getUpload(const string &key,int id=0) { map<string,vector<control *> >::const_iterator ci=extended_query_map.find(key); if(ci==extended_query_map.end()) return 0; else { if((ci->second)[id]->is_in_file) { return (extended_query_map[key])[id]->content; } else { return 0; } }}string CGI::getUploadedFileName(const string &key,int id=0) { map<string,vector<control *> >::const_iterator ci=extended_query_map.find(key); if(ci==extended_query_map.end()) return ""; else { if((ci->second)[id]->is_in_file) { return (extended_query_map[key])[id]->attributes["filename"]; } else { return ""; } }}control *CGI::getControl(const string &key,int id=0) { map<string,vector<control *> >::const_iterator ci=extended_query_map.find(key); if(ci==extended_query_map.end()) return 0; else return (extended_query_map[key])[id];} string &CGI::getCVal(const string &key) { return cookie_map[key];}string &CGI::getQuery() { return query_string_decoded;}string &CGI::getCookie() { return cookie_string_decoded;}bool CGI::isQKey(const string &key) { for(int i=0;i<query_keys.size();i++) { if(key==query_keys[i]) return true; return false; }}bool CGI::isCKey(const string &key) { map<string,string>::const_iterator ci=cookie_map.find(key); if(ci!=cookie_map.end()) { return true; } else { return false; }} void CGI::getPostQuery() { int content_length; int i; content_length=atoi(getenv("CONTENT_LENGTH")); for(i=0;i<content_length;i++) { query_string+=getchar(); }}void CGI::getGetQuery() { query_string=getenv("QUERY_STRING"); cerr << "query_string="<<query_string<<endl;}void CGI::getHeadQuery() { query_string="";}void CGI::getInteractiveQuery() { char tmp; while(1) { tmp=(char)fgetc(stdin); if(feof(stdin)) break; query_string+=tmp; }}void CGI::getInteractiveCookie() { if(getenv("HTTP_COOKIE")) cookie_string=getenv("HTTP_COOKIE"); else cookie_string="";}void CGI::getStdCookie() { if(getenv("HTTP_COOKIE")) cookie_string=getenv("HTTP_COOKIE"); else cookie_string="";}vector<string> &CGI::getQKeys() { return query_keys;}vector<string> &CGI::getCKeys() { return cookie_keys;}void CGI::decodeQuery() { const char *src=query_string.c_str(); char *dst=(char *)calloc(strlen(src),sizeof(char)); int state=0; char tmp; int j=0; for(unsigned i=0;i<strlen(src);i++) { switch(state) { case 0: if(src[i]=='+') dst[j++]=' '; else if(src[i]=='%') state=1; else dst[j++]=src[i]; break; case 1: if(strchr("0123456789ABCDEFabcdef",src[i])) { state=2; tmp=(toupper(src[i])>='A' && toupper(src[i])<='F') ? (toupper(src[i])-'A'+10) : (src[i]-'0'); tmp*=16; } else { dst[j++]='%'; dst[j++]=src[i]; state=0; } break; case 2: if(strchr("0123456789ABCDEFabcdef",src[i])) { tmp+=(toupper(src[i])>='A' && toupper(src[i])<='F') ? (toupper(src[i])-'A'+10) : (src[i]-'0'); dst[j++]=tmp; } else { dst[j++]='%'; dst[j++]=src[i-1]; dst[j++]=src[i]; } state=0; break; } dst[j]=0; } query_string_decoded=dst;}void CGI::decodeCookie() { const char *src=cookie_string.c_str(); char *dst=(char *)calloc(strlen(src),sizeof(char)); int state=0; char tmp; int j=0; for(unsigned i=0;i<strlen(src);i++) { switch(state) { case 0: if(src[i]=='+') dst[j++]=' '; else if(src[i]=='%') state=1; else dst[j++]=src[i]; break; case 1: if(strchr("0123456789ABCDEFabcdef",src[i])) { state=2; tmp=(toupper(src[i])>='A' && toupper(src[i])<='F') ? (toupper(src[i])-'A'+10) : (src[i]-'0'); tmp*=16; } else { dst[j++]='%'; dst[j++]=src[i]; state=0; } break; case 2: if(strchr("0123456789ABCDEFabcdef",src[i])) { tmp+=(toupper(src[i])>='A' && toupper(src[i])<='F') ? (toupper(src[i])-'A'+10) : (src[i]-'0'); } else { dst[j++]='%'; dst[j++]=src[i-1]; dst[j++]=src[i]; } state=0; break; } dst[j]=0; } cookie_string_decoded=dst;} void CGI::parseQuery() { const char *query=query_string_decoded.c_str(); string key,val; int state=0; unsigned i; control *ctrl; for(i=0;i<strlen(query);i++) { // state machine switch(state) { case 0: // key cannot start from digit key=""; val=""; if(isalpha(query[i]) || query[i]=='_') { key+=query[i]; state=1; } break; case 1: if(isalnum(query[i]) || query[i]=='_') { key+=query[i]; state=1; } else if(query[i]=='=') { ctrl=new control; extended_query_map[key].push_back(ctrl); query_keys.push_back(key); ctrl->is_in_file=false; state=2; } else if(query[i]=='&') { state=0; } break; case 2: // value if(query[i]!='&') { val+=query[i]; } else { ctrl->value=val; state=0; } break; } } if(state==2) { ctrl->value=val; }}void CGI::parseCookie() { const char *cookie=cookie_string_decoded.c_str(); string key,val; int state=0; unsigned i; for(i=0;i<strlen(cookie);i++) { // state machine switch(state) { case 0: // key cannot start from digit key=""; val=""; if(isalpha(cookie[i]) || cookie[i]=='_') { key+=cookie[i]; state=1; } break; case 1: if(isalnum(cookie[i]) || cookie[i]=='_') { key+=cookie[i]; state=1; } else if(cookie[i]=='=') { state=2; } else if(cookie[i]==';') { // skip '; ' state=3; } break; case 2: // value if(cookie[i]!=';') { val+=cookie[i]; } else { state=3; } break; case 3: if(cookie[i]==' ') { cookie_map[key]=val; cookie_keys.push_back(key); cerr << "Testing \n"; } state=0; break; } } if(state==3 || state==1 || state==2) { cookie_map[key]=val; cookie_keys.push_back(key); }}void CGI::setCookie(const string &key,const string &val,const string &expires, const string &path,const string &domain,bool secure) { cout << "Set-Cookie: " << key << "=" << val << ";"; if(expires!="") { cout << " expires="<<expires<<";"; } if(path!="") { cout << " path="<<path<<";"; } if(domain!="") { cout << " domain="<<domain<<";"; } if(secure) { cout << " secure"; } cout << endl;}bool CGI::isMultyPart() { cerr << "Checking if multypart.."; if(!getenv("CONTENT_TYPE")) return false; string c_type=getenv("CONTENT_TYPE"); if(c_type.find("multipart/form-data")==0) { cerr << " yes\n"; return true; } cerr << " no\n"; return false;}/* Here will be state machine : in state 0 we are accumulating */void CGI::buildMultyPart() { string c_type=getenv("CONTENT_TYPE"); string::size_type st=c_type.find("boundary="); string boundary=c_type.substr(st+string("boundary=").size()); string buf; char *tmp; int c_len = atoi(getenv("CONTENT_LENGTH")); int state=0; int buf_pos=0; char c; control *cntrl; cerr << "In buildMultyPartEx(): c_type="<<c_type<<" boundary="<<boundary<<endl; tmp=(char *)calloc(boundary.size(),sizeof(char)); while(1) { c=getchar(); if(feof(stdin)) break; switch(state) { case 0: // wolking through description lines waiting content if(c=='\n') { if(buf==boundary) { state=1; buf=""; cntrl=new control; } else ; // some error ocured .. } else { buf+=c; } break; case 1: if(c=='\n') { setAttr(buf,cntrl); buf=""; state=2; } else { buf+=c; } break; case 2: if(c=='\n') { // head finished... extended_query_map[cntrl->attributes["name"]].push_back(cntrl); query_keys.push_back(cntrl->attributes["name"]); if(cntrl->attributes["filename"]!="") { cntrl->content=tmpfile(); cntrl->is_in_file=true; } else { cntrl->is_in_file=false; } buf_pos=0; state=3; } else { ungetc(c,stdin); state=1; } break; case 3: if(buf_pos<boundary.size()-1) { tmp[buf_pos++]=c; } else { tmp[buf_pos++]=c; // cerr << tmp << endl; if(boundary==string(tmp)) { state=4; } else { state=5; } } break; case 4: if(c!='-') { // Here's some important notice: boundary placed in the body is always finished with \n so we should just get through here .. buf=""; cntrl=new control; buf_pos=0; // ungetc(c,stdin); state=1; } // Next symbol should be - and should be last so in next iteration we'll finish .. break; case 5: if(cntrl->is_in_file) { if(fputc(tmp[0],cntrl->content)==EOF) cerr << "Cannot fputc char ... \n"; } else { cntrl->value+=tmp[0]; // cerr << cntrl->value << endl; } NEXT_CHAR(tmp,boundary.size(),c); // cerr << tmp << endl; // cerr << boundary << endl; if(boundary==string(tmp)) { state=4; } break; } } free(tmp); } void CGI::setAttr(string &buf,control *c) { if(buf.substr(0,string("Content-Disposition").size())=="Content-Disposition") { string::size_type s=0; c->attributes["name"]=""; c->attributes["filename"]=""; s=buf.find("name="); s+=string("name=").size(); s++;// skip quotes while(buf[s]!='"') c->attributes["name"]+=buf[s++]; s++; if(s>=buf.size()) return; if(buf[s]!=';') return; s=buf.find("filename="); s+=string("filename=").size(); s++; // skip quotes while(buf[s]!='"') c->attributes["filename"]+=buf[s++]; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -