/* * Copyright 2017 Chris Xiong * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef CGILIB_HPP #define CGILIB_HPP #include #include #include #include const char* base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; std::string base64_encode(std::string s) { std::string r=""; for(unsigned i=0;i>2; r+=base64_table[b]; b=(s[i]&0x03)<<4; if(i+1>4; r+=base64_table[b]; b=(s[i+1]&0x0F)<<2; if(i+2>6; r+=base64_table[b]; b=s[i+2]&0x3F; r+=base64_table[b]; }else r+=base64_table[b],r+='='; }else r+=base64_table[b],r+="=="; } return r; } void split(std::string s,char c,std::vector& v) { v.clear(); for(size_t anch=0;;) { std::string sec; if(s.find(c,anch)==std::string::npos) sec=s.substr(anch); else sec=s.substr(anch,s.find(c,anch)-anch); v.push_back(sec); if(s.find(c,anch)==std::string::npos)break; anch=s.find(c,anch)+1; } } std::string trim(std::string s) { int l=0;for(;isblank(s[l]);++l) s=s.substr(l); while(isblank(s.back()))s.pop_back(); return s; } class QueryStrParser { private: std::map q; void parse(std::string es) { for(size_t anch=0;;) { std::string sec; if(es.find('&',anch)==std::string::npos) sec=es.substr(anch); else sec=es.substr(anch,es.find('&',anch)-anch); if(sec.find('=')==std::string::npos) q[sec.substr(0)]=""; else q[sec.substr(0,sec.find('='))]=sec.substr(sec.find('=')+1); if(es.find('&',anch)==std::string::npos)break; anch=es.find('&',anch)+1; } } public: QueryStrParser() { char* e=getenv("QUERY_STRING"); if(!e)return; parse(std::string(e)); } QueryStrParser(std::string s) { parse(s); } bool exist(std::string s) { return q.find(s)!=q.end(); } std::string value(std::string s) { if(!exist(s))return ""; return q.find(s)->second; } }; class RequestCookies { private: std::map m; void parse(std::string cookie) { std::vector v; split(cookie,';',v); } public: RequestCookies() { char* e=getenv("HTTP_COOKIE"); if(!e)return; parse(std::string(e)); } }; class DOMAttrib { private: std::map m; public: DOMAttrib(std::string s="") { for(size_t anch=0;;) { std::string sec; if(s.find('"',anch)==std::string::npos) sec=s.substr(anch); else sec=s.substr(anch,s.find('"',s.find('"',anch)+1)-anch+1); if(sec.find('=')==std::string::npos) m[sec.substr(0)]=""; else m[sec.substr(0,sec.find('='))]=sec.substr(sec.find('=')+2), m[sec.substr(0,sec.find('='))].pop_back(); if(s.find(' ',anch+sec.length())==std::string::npos)break; anch=s.find(' ',anch+sec.length())+1; } } void setAttrib(std::string a,std::string v){m[a]=v;} void eraseAttrib(std::string a){if(existAttrib(a))m.erase(m.find(a));} bool existAttrib(std::string a){return m.find(a)!=m.end();} std::string getAttrib(std::string a){if(!existAttrib(a))return "";return m[a];} std::string to_string() { std::string r;bool cf=false; for(auto i=m.begin();i!=m.end();++i) { if(cf)r+=' ';else cf=true; r+=i->first+"=\""+i->second+"\""; } return r; } }; static const char* twoxx[]={ "OK", "Created", "Accepted", "Non-Authoritative Information", "No Content", "Reset Content", "Partial Content", "Multi-Status", "Already Reported" }; static const char* threexx[]={ "Multiple Choices", "Moved Permanently", "Found", "See Other", "Not Modified", "Use Proxy", "???", "Temporary Redirect" }; static const char* fourxx[]={ "Bad Request", "Unauthorized", "Payment Required", "Forbidden", "Not Found", "Method Not Allowed", "Not Acceptable", "Proxy Authentication Required", "Request Timeout", "Conflict", "Gone", "Length Required", "Precondition Failed", "Request Entity Too Large", "Request-URI Too Long", "Unsupported Media Type", "Requested Range Not Satisfiable", "Expectation Failed" }; static const char* fivexx[]={ "Internal Server Error", "Not Implemented", "Bad Gateway", "Service Unavailable", "Gateway Timeout", "HTTP Version Not Supported" }; class HTTPHeader { private: int status; std::vector hdr; public: HTTPHeader(){status=200;} void setStatusCode(int c){status=c;} int statusCode(){return status;} void appendHeader(std::string s){hdr.push_back(s);} void print() { if(status>=200&&status<=208) printf("Status: %d %s\r\n",status,twoxx[status-200]); if(status>=300&&status<=307) printf("Status: %d %s\r\n",status,threexx[status-300]); if(status>=400&&status<=417) printf("Status: %d %s\r\n",status,fourxx[status-400]); if(status>=500&&status<=505) printf("Status: %d %s\r\n",status,fivexx[status-500]); for(unsigned i=0;i