anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

httpd.h (5019B)

      1 /*
      2  *
      3  * (C) 2012-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  */
      8 
      9 #ifndef ANOPE_HTTPD_H
     10 #define ANOPE_HTTPD_H
     11 
     12 enum HTTPError
     13 {
     14 	HTTP_ERROR_OK = 200,
     15 	HTTP_FOUND = 302,
     16 	HTTP_BAD_REQUEST = 400,
     17 	HTTP_PAGE_NOT_FOUND = 404,
     18 	HTTP_NOT_SUPPORTED = 505
     19 };
     20 
     21 /* A message to someone */
     22 struct HTTPReply
     23 {
     24 	HTTPError error;
     25 	Anope::string content_type;
     26 	std::map<Anope::string, Anope::string, ci::less> headers;
     27 	typedef std::list<std::pair<Anope::string, Anope::string> > cookie;
     28 	std::vector<cookie> cookies;
     29 
     30 	HTTPReply() : error(HTTP_ERROR_OK), length(0) { }
     31 
     32 	HTTPReply(const HTTPReply& other) : error(other.error), length(other.length)
     33 	{
     34 		content_type = other.content_type;
     35 		headers = other.headers;
     36 		cookies = other.cookies;
     37 
     38 		for (unsigned i = 0; i < other.out.size(); ++i)
     39 			out.push_back(new Data(other.out[i]->buf, other.out[i]->len));
     40 	}
     41 
     42 	~HTTPReply()
     43 	{
     44 		for (unsigned i = 0; i < out.size(); ++i)
     45 			delete out[i];
     46 		out.clear();
     47 	}
     48 
     49 	struct Data
     50 	{
     51 		char *buf;
     52 		size_t len;
     53 
     54 		Data(const char *b, size_t l)
     55 		{
     56 			this->buf = new char[l];
     57 			memcpy(this->buf, b, l);
     58 			this->len = l;
     59 		}
     60 
     61 		~Data()
     62 		{
     63 			delete [] buf;
     64 		}
     65 	};
     66 
     67 	std::deque<Data *> out;
     68 	size_t length;
     69 
     70 	void Write(const Anope::string &message)
     71 	{
     72 		this->out.push_back(new Data(message.c_str(), message.length()));
     73 		this->length += message.length();
     74 	}
     75 
     76 	void Write(const char *b, size_t l)
     77 	{
     78 		this->out.push_back(new Data(b, l));
     79 		this->length += l;
     80 	}
     81 };
     82 
     83 /* A message from someone */
     84 struct HTTPMessage
     85 {
     86 	std::map<Anope::string, Anope::string> headers;
     87 	std::map<Anope::string, Anope::string> cookies;
     88 	std::map<Anope::string, Anope::string> get_data;
     89 	std::map<Anope::string, Anope::string> post_data;
     90 	Anope::string content;
     91 };
     92 
     93 class HTTPClient;
     94 class HTTPProvider;
     95 
     96 class HTTPPage : public Base
     97 {
     98 	Anope::string url;
     99 	Anope::string content_type;
    100 
    101  public:
    102 	HTTPPage(const Anope::string &u, const Anope::string &ct = "text/html") : url(u), content_type(ct) { }
    103 
    104 	const Anope::string &GetURL() const { return this->url; }
    105 
    106 	const Anope::string &GetContentType() const { return this->content_type; }
    107 
    108 	/** Called when this page is requested
    109 	 * @param The server this page is on
    110 	 * @param The page name
    111 	 * @param The client requesting the page
    112 	 * @param The HTTP header sent from the client to request the page
    113 	 * @param The HTTP header that will be sent back to the client
    114 	 */
    115 	virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0;
    116 };
    117 
    118 class HTTPClient : public ClientSocket, public BinarySocket, public Base
    119 {
    120  protected:
    121 	void WriteClient(const Anope::string &message)
    122 	{
    123 		BinarySocket::Write(message + "\r\n");
    124 	}
    125 
    126  public:
    127 	HTTPClient(ListenSocket *l, int f, const sockaddrs &a) : ClientSocket(l, a), BinarySocket() { }
    128 
    129 	virtual const Anope::string GetIP()
    130 	{
    131 		return this->clientaddr.addr();
    132 	}
    133 
    134 	virtual void SendError(HTTPError err, const Anope::string &msg) = 0;
    135 	virtual void SendReply(HTTPReply *) = 0;
    136 };
    137 
    138 class HTTPProvider : public ListenSocket, public Service
    139 {
    140 	Anope::string ip;
    141 	unsigned short port;
    142 	bool ssl;
    143  public:
    144 	std::vector<Anope::string> ext_ips;
    145 	std::vector<Anope::string> ext_headers;
    146 
    147 	HTTPProvider(Module *c, const Anope::string &n, const Anope::string &i, const unsigned short p, bool s) : ListenSocket(i, p, i.find(':') != Anope::string::npos), Service(c, "HTTPProvider", n), ip(i), port(p), ssl(s) { }
    148 
    149 	const Anope::string &GetIP() const
    150 	{
    151 		return this->ip;
    152 	}
    153 
    154 	unsigned short GetPort() const
    155 	{
    156 		return this->port;
    157 	}
    158 
    159 	bool IsSSL() const
    160 	{
    161 		return this->ssl;
    162 	}
    163 
    164 	virtual bool RegisterPage(HTTPPage *page) = 0;
    165 	virtual void UnregisterPage(HTTPPage *page) = 0;
    166 	virtual HTTPPage* FindPage(const Anope::string &name) = 0;
    167 };
    168 
    169 namespace HTTPUtils
    170 {
    171 	inline Anope::string URLDecode(const Anope::string &url)
    172 	{
    173 		Anope::string decoded;
    174 
    175 		for (unsigned i = 0; i < url.length(); ++i)
    176 		{
    177 			const char& c = url[i];
    178 
    179 			if (c == '%' && i + 2 < url.length())
    180 			{
    181 				Anope::string dest;
    182 				Anope::Unhex(url.substr(i + 1, 2), dest);
    183 				decoded += dest;
    184 				i += 2;
    185 			}
    186 			else if (c == '+')
    187 				decoded += ' ';
    188 			else
    189 				decoded += c;
    190 		}
    191 
    192 		return decoded;
    193 	}
    194 
    195 	inline Anope::string URLEncode(const Anope::string &url)
    196 	{
    197 		Anope::string encoded;
    198 
    199 		for (unsigned i = 0; i < url.length(); ++i)
    200 		{
    201 			const char& c = url[i];
    202 
    203 			if (isalnum(c) || c == '.' || c == '-' || c == '*' || c == '_')
    204 				encoded += c;
    205 			else if (c == ' ')
    206 				encoded += '+';
    207 			else
    208 				encoded += "%" + Anope::Hex(c);
    209 		}
    210 
    211 		return encoded;
    212 	}
    213 
    214 	inline Anope::string Escape(const Anope::string &src)
    215 	{
    216 		Anope::string dst;
    217 
    218 		for (unsigned i = 0; i < src.length(); ++i)
    219 		{
    220 			switch (src[i])
    221 			{
    222 				case '<':
    223 					dst += "&lt;";
    224 					break;
    225 				case '>':
    226 					dst += "&gt;";
    227 					break;
    228 				case '"':
    229 					dst += "&quot;";
    230 					break;
    231 				case '&':
    232 					dst += "&amp;";
    233 					break;
    234 				default:
    235 					dst += src[i];
    236 			}
    237 		}
    238 
    239 		return dst;
    240 	}
    241 }
    242 
    243 #endif // ANOPE_HTTPD_H