summaryrefslogblamecommitdiff
path: root/blog/sbs_2/cgi-src/cgiutils.hpp
blob: 3eca4dcd47c978ec73ad9563725f827dba37351f (plain) (tree)




















































































































































































































































                                                                                               
/*
 * 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 <cstdlib>
#include <map>
#include <string>
#include <vector>
const char* base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
std::string base64_encode(std::string s)
{
	std::string r="";
	for(unsigned i=0;i<s.length();i+=3)
	{
		int b=(s[i]&0xFC)>>2;
		r+=base64_table[b];
		b=(s[i]&0x03)<<4;
		if(i+1<s.length())
		{
			b|=(s[i+1]&0xF0)>>4;
			r+=base64_table[b];
			b=(s[i+1]&0x0F)<<2;
			if(i+2<s.length())
			{
				b|=(s[i+2]&0xC0)>>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<std::string>& 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<std::string,std::string> 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<std::string,std::string> m;
		void parse(std::string cookie)
		{
			std::vector<std::string> v;
			split(cookie,';',v);
		}
	public:
		RequestCookies()
		{
			char* e=getenv("HTTP_COOKIE");
			if(!e)return;
			parse(std::string(e));
		}
};
class DOMAttrib
{
	private:
		std::map<std::string,std::string> 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<std::string> 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<hdr.size();++i)
		printf("%s\r\n",hdr[i].c_str());
		printf("\r\n");
	}
};
#endif