more handlers
Dependents: bandwidth-meter-net mbedRail24v
Fork of Tiny-HTTPD by
HTTPD_util.cpp
00001 /* Copyright (C) 2013 Hiroshi Suga, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00005 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00006 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00007 * furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "HTTPD.h" 00020 #include <ctype.h> 00021 #include <stdlib.h> 00022 #include <string.h> 00023 00024 #define MIMETABLE_NUM 9 00025 static const struct { 00026 char ext[5]; 00027 char type[24]; 00028 } mimetable[MIMETABLE_NUM] = { 00029 {"txt", "text/plain"}, // default 00030 {"html", "text/html"}, 00031 {"htm", "text/html"}, 00032 {"css", "text/css"}, 00033 {"js", "application/javascript"}, 00034 {"jpg", "image/jpeg"}, 00035 {"png", "image/png"}, 00036 {"gif", "image/gif"}, 00037 {"ico", "image/x-icon"}, 00038 }; 00039 00040 char *HTTPD::getUri (int id) { 00041 return _state[id].uri; 00042 } 00043 00044 char *HTTPD::getFilename (int id) { 00045 return _state[id].filename; 00046 } 00047 00048 char *HTTPD::getQueryString (int id) { 00049 return _state[id].querystring; 00050 } 00051 00052 int HTTPD::receive (int id, char *buf, int len) { 00053 int i; 00054 00055 for (i = 0; i < len; i ++) { 00056 if (_state[id].buf->dequeue(&buf[i]) == false) break; 00057 } 00058 return i; 00059 } 00060 00061 int HTTPD::send (int id, const char *body, int len, const char *header) { 00062 char buf[HTTPD_CMD_SIZE]; 00063 00064 strcpy(buf, "HTTP/1.1 200 OK\r\n"); 00065 _state[id].client->send_all(buf, strlen(buf)); 00066 strcpy(buf, server_name); 00067 _state[id].client->send_all(buf, strlen(buf)); 00068 if (_state[id].keepalive) { 00069 strcpy(buf, "Connection: Keep-Alive\r\n"); 00070 } else { 00071 strcpy(buf, "Connection: close\r\n"); 00072 } 00073 _state[id].client->send_all(buf, strlen(buf)); 00074 if (header) { 00075 _state[id].client->send_all((char*)header, strlen(header)); 00076 } 00077 sprintf(buf, "Content-Length: %d\r\n\r\n", len); 00078 _state[id].client->send_all(buf, strlen(buf)); 00079 00080 return _state[id].client->send_all((char*)body, len); 00081 } 00082 00083 int HTTPD::getHandler (const char *uri) { 00084 int i; 00085 00086 for (i = 0; i < _handler_count; i ++) { 00087 if (strncmp(uri, _handler[i].uri, strlen(_handler[i].uri)) == 0) { 00088 // found 00089 return i; 00090 } 00091 } 00092 return -1; 00093 } 00094 00095 int HTTPD::attach (const char *uri, const char *dir) { 00096 if (_handler_count < HTTPD_MAX_HANDLES) { 00097 _handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1); 00098 strcpy(_handler[_handler_count].uri, uri); 00099 _handler[_handler_count].dir = (char*)malloc(strlen(dir) + 1); 00100 strcpy(_handler[_handler_count].dir, dir); 00101 _handler[_handler_count].funcCgi = NULL; 00102 _handler_count ++; 00103 return 0; 00104 } else { 00105 return -1; 00106 } 00107 } 00108 00109 int HTTPD::attach (const char *uri, void (*funcCgi)(int)) { 00110 if (_handler_count < HTTPD_MAX_HANDLES) { 00111 _handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1); 00112 strcpy(_handler[_handler_count].uri, uri); 00113 _handler[_handler_count].dir = NULL; 00114 _handler[_handler_count].funcCgi = funcCgi; 00115 _handler_count ++; 00116 return 0; 00117 } else { 00118 return -1; 00119 } 00120 } 00121 00122 00123 char *HTTPD::mimetype (char *file) { 00124 int i, j; 00125 00126 for (i = 0; i < MIMETABLE_NUM; i ++) { 00127 j = strlen(mimetable[i].ext); 00128 if (file[strlen(file) - j - 1] == '.' && 00129 strnicmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) { 00130 return (char*)mimetable[i].type; 00131 } 00132 } 00133 return (char*)mimetable[0].type; 00134 } 00135 00136 int HTTPD::strnicmp (const char *p1, const char *p2, int n) { 00137 int i, r = -1; 00138 char c1, c2; 00139 00140 for (i = 0; i < n; i ++) { 00141 c1 = (p1[i] >= 'a' && p1[i] <= 'z') ? p1[i] - ('a' - 'A'): p1[i]; 00142 c2 = (p2[i] >= 'a' && p2[i] <= 'z') ? p2[i] - ('a' - 'A'): p2[i]; 00143 r = c1 - c2; 00144 if (r) break; 00145 } 00146 return r; 00147 } 00148 00149 00150 /* base64encode code from 00151 * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) 00152 */ 00153 int HTTPD::base64encode (const char *input, int length, char *output, int len) { 00154 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00155 unsigned int c, c1, c2, c3; 00156 00157 if (len < ((((length-1)/3)+1)<<2)) return -1; 00158 for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) { 00159 c1 = ((((unsigned char)*((unsigned char *)&input[i])))); 00160 c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0; 00161 c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0; 00162 00163 c = ((c1 & 0xFC) >> 2); 00164 output[j+0] = base64[c]; 00165 c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4); 00166 output[j+1] = base64[c]; 00167 c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6); 00168 output[j+2] = (length>i+1)?base64[c]:'='; 00169 c = (c3 & 0x3F); 00170 output[j+3] = (length>i+2)?base64[c]:'='; 00171 } 00172 output[(((length-1)/3)+1)<<2] = '\0'; 00173 return 0; 00174 } 00175 00176 00177 /* urlencode code from 00178 * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) 00179 */ 00180 int HTTPD::urlencode (const char *str, char *buf, int len) { 00181 // char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf; 00182 const char *pstr = str; 00183 char *pbuf = buf; 00184 00185 if (len < (strlen(str) * 3 + 1)) return -1; 00186 while (*pstr) { 00187 if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 00188 *pbuf++ = *pstr; 00189 else if (*pstr == ' ') 00190 *pbuf++ = '+'; 00191 else 00192 *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15); 00193 pstr++; 00194 } 00195 *pbuf = '\0'; 00196 return 0; 00197 } 00198 00199 /* urldecode code from 00200 * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) 00201 */ 00202 int HTTPD::urldecode (const char *str, char *buf, int len) { 00203 // char *pstr = str, *buf = (char*)malloc(strlen(str) + 1), *pbuf = buf; 00204 const char *pstr = str; 00205 char *pbuf = buf; 00206 00207 if (len < (strlen(str) / 3 - 1)) return -1; 00208 while (*pstr) { 00209 if (*pstr == '%') { 00210 if (pstr[1] && pstr[2]) { 00211 *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]); 00212 pstr += 2; 00213 } 00214 } else if (*pstr == '+') { 00215 *pbuf++ = ' '; 00216 } else { 00217 *pbuf++ = *pstr; 00218 } 00219 pstr++; 00220 } 00221 *pbuf = '\0'; 00222 return 0; 00223 } 00224 00225 int HTTPD::from_hex (int ch) { 00226 return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; 00227 } 00228 00229 int HTTPD::to_hex (int code) { 00230 static char hex[] = "0123456789abcdef"; 00231 return hex[code & 15]; 00232 }
Generated on Sun Jul 24 2022 08:41:21 by 1.7.2