for Low Memory Platforms.

Dependents:   TinyHTTPServer_WIZ820io

Fork of HTTPD by Suga koubou

Committer:
ban4jp
Date:
Tue Feb 04 03:07:05 2014 +0000
Revision:
2:905fe8dfebd6
Parent:
0:d18dff347122
Changed server name.; Disabled keep-alive.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:d18dff347122 1 /* Copyright (C) 2013 Hiroshi Suga, MIT License
okini3939 0:d18dff347122 2 *
okini3939 0:d18dff347122 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
okini3939 0:d18dff347122 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
okini3939 0:d18dff347122 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
okini3939 0:d18dff347122 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
okini3939 0:d18dff347122 7 * furnished to do so, subject to the following conditions:
okini3939 0:d18dff347122 8 *
okini3939 0:d18dff347122 9 * The above copyright notice and this permission notice shall be included in all copies or
okini3939 0:d18dff347122 10 * substantial portions of the Software.
okini3939 0:d18dff347122 11 *
okini3939 0:d18dff347122 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
okini3939 0:d18dff347122 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
okini3939 0:d18dff347122 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
okini3939 0:d18dff347122 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
okini3939 0:d18dff347122 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
okini3939 0:d18dff347122 17 */
okini3939 0:d18dff347122 18
okini3939 0:d18dff347122 19 #include "HTTPD.h"
okini3939 0:d18dff347122 20 #include <ctype.h>
okini3939 0:d18dff347122 21 #include <stdlib.h>
okini3939 0:d18dff347122 22 #include <string.h>
okini3939 0:d18dff347122 23
okini3939 0:d18dff347122 24 #define MIMETABLE_NUM 9
okini3939 0:d18dff347122 25 static const struct {
okini3939 0:d18dff347122 26 char ext[5];
okini3939 0:d18dff347122 27 char type[24];
okini3939 0:d18dff347122 28 } mimetable[MIMETABLE_NUM] = {
okini3939 0:d18dff347122 29 {"txt", "text/plain"}, // default
okini3939 0:d18dff347122 30 {"html", "text/html"},
okini3939 0:d18dff347122 31 {"htm", "text/html"},
okini3939 0:d18dff347122 32 {"css", "text/css"},
okini3939 0:d18dff347122 33 {"js", "application/javascript"},
okini3939 0:d18dff347122 34 {"jpg", "image/jpeg"},
okini3939 0:d18dff347122 35 {"png", "image/png"},
okini3939 0:d18dff347122 36 {"gif", "image/gif"},
okini3939 0:d18dff347122 37 {"ico", "image/x-icon"},
okini3939 0:d18dff347122 38 };
okini3939 0:d18dff347122 39
okini3939 0:d18dff347122 40 char *HTTPD::getUri (int id) {
okini3939 0:d18dff347122 41 return _state[id].uri;
okini3939 0:d18dff347122 42 }
okini3939 0:d18dff347122 43
okini3939 0:d18dff347122 44 char *HTTPD::getFilename (int id) {
okini3939 0:d18dff347122 45 return _state[id].filename;
okini3939 0:d18dff347122 46 }
okini3939 0:d18dff347122 47
okini3939 0:d18dff347122 48 char *HTTPD::getQueryString (int id) {
okini3939 0:d18dff347122 49 return _state[id].querystring;
okini3939 0:d18dff347122 50 }
okini3939 0:d18dff347122 51
okini3939 0:d18dff347122 52 int HTTPD::receive (int id, char *buf, int len) {
okini3939 0:d18dff347122 53 int i;
okini3939 0:d18dff347122 54
okini3939 0:d18dff347122 55 for (i = 0; i < len; i ++) {
okini3939 0:d18dff347122 56 if (_state[id].buf->dequeue(&buf[i]) == false) break;
okini3939 0:d18dff347122 57 }
okini3939 0:d18dff347122 58 return i;
okini3939 0:d18dff347122 59 }
okini3939 0:d18dff347122 60
okini3939 0:d18dff347122 61 int HTTPD::send (int id, const char *body, int len, const char *header) {
okini3939 0:d18dff347122 62 char buf[HTTPD_CMD_SIZE];
okini3939 0:d18dff347122 63
okini3939 0:d18dff347122 64 strcpy(buf, "HTTP/1.1 200 OK\r\n");
okini3939 0:d18dff347122 65 _state[id].client->send_all(buf, strlen(buf));
ban4jp 2:905fe8dfebd6 66 strcpy(buf, server_name);
okini3939 0:d18dff347122 67 _state[id].client->send_all(buf, strlen(buf));
okini3939 0:d18dff347122 68 if (_state[id].keepalive) {
okini3939 0:d18dff347122 69 strcpy(buf, "Connection: Keep-Alive\r\n");
okini3939 0:d18dff347122 70 } else {
okini3939 0:d18dff347122 71 strcpy(buf, "Connection: close\r\n");
okini3939 0:d18dff347122 72 }
okini3939 0:d18dff347122 73 _state[id].client->send_all(buf, strlen(buf));
okini3939 0:d18dff347122 74 if (header) {
okini3939 0:d18dff347122 75 _state[id].client->send_all((char*)header, strlen(header));
okini3939 0:d18dff347122 76 }
okini3939 0:d18dff347122 77 sprintf(buf, "Content-Length: %d\r\n\r\n", len);
okini3939 0:d18dff347122 78 _state[id].client->send_all(buf, strlen(buf));
okini3939 0:d18dff347122 79
okini3939 0:d18dff347122 80 return _state[id].client->send_all((char*)body, len);
okini3939 0:d18dff347122 81 }
okini3939 0:d18dff347122 82
okini3939 0:d18dff347122 83 int HTTPD::getHandler (const char *uri) {
okini3939 0:d18dff347122 84 int i;
okini3939 0:d18dff347122 85
okini3939 0:d18dff347122 86 for (i = 0; i < _handler_count; i ++) {
okini3939 0:d18dff347122 87 if (strncmp(uri, _handler[i].uri, strlen(_handler[i].uri)) == NULL) {
okini3939 0:d18dff347122 88 // found
okini3939 0:d18dff347122 89 return i;
okini3939 0:d18dff347122 90 }
okini3939 0:d18dff347122 91 }
okini3939 0:d18dff347122 92 return -1;
okini3939 0:d18dff347122 93 }
okini3939 0:d18dff347122 94
okini3939 0:d18dff347122 95 int HTTPD::attach (const char *uri, const char *dir) {
okini3939 0:d18dff347122 96 if (_handler_count < HTTPD_MAX_HANDLES) {
okini3939 0:d18dff347122 97 _handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1);
okini3939 0:d18dff347122 98 strcpy(_handler[_handler_count].uri, uri);
okini3939 0:d18dff347122 99 _handler[_handler_count].dir = (char*)malloc(strlen(dir) + 1);
okini3939 0:d18dff347122 100 strcpy(_handler[_handler_count].dir, dir);
okini3939 0:d18dff347122 101 _handler[_handler_count].funcCgi = NULL;
okini3939 0:d18dff347122 102 _handler_count ++;
okini3939 0:d18dff347122 103 return 0;
okini3939 0:d18dff347122 104 } else {
okini3939 0:d18dff347122 105 return -1;
okini3939 0:d18dff347122 106 }
okini3939 0:d18dff347122 107 }
okini3939 0:d18dff347122 108
okini3939 0:d18dff347122 109 int HTTPD::attach (const char *uri, void (*funcCgi)(int)) {
okini3939 0:d18dff347122 110 if (_handler_count < HTTPD_MAX_HANDLES) {
okini3939 0:d18dff347122 111 _handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1);
okini3939 0:d18dff347122 112 strcpy(_handler[_handler_count].uri, uri);
okini3939 0:d18dff347122 113 _handler[_handler_count].dir = NULL;
okini3939 0:d18dff347122 114 _handler[_handler_count].funcCgi = funcCgi;
okini3939 0:d18dff347122 115 _handler_count ++;
okini3939 0:d18dff347122 116 return 0;
okini3939 0:d18dff347122 117 } else {
okini3939 0:d18dff347122 118 return -1;
okini3939 0:d18dff347122 119 }
okini3939 0:d18dff347122 120 }
okini3939 0:d18dff347122 121
okini3939 0:d18dff347122 122
okini3939 0:d18dff347122 123 char *HTTPD::mimetype (char *file) {
okini3939 0:d18dff347122 124 int i, j;
okini3939 0:d18dff347122 125
okini3939 0:d18dff347122 126 for (i = 0; i < MIMETABLE_NUM; i ++) {
okini3939 0:d18dff347122 127 j = strlen(mimetable[i].ext);
okini3939 0:d18dff347122 128 if (file[strlen(file) - j - 1] == '.' &&
okini3939 0:d18dff347122 129 strnicmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) {
okini3939 0:d18dff347122 130 return (char*)mimetable[i].type;
okini3939 0:d18dff347122 131 }
okini3939 0:d18dff347122 132 }
okini3939 0:d18dff347122 133 return (char*)mimetable[0].type;
okini3939 0:d18dff347122 134 }
okini3939 0:d18dff347122 135
okini3939 0:d18dff347122 136 int HTTPD::strnicmp (const char *p1, const char *p2, int n) {
okini3939 0:d18dff347122 137 int i, r = -1;
okini3939 0:d18dff347122 138 char c1, c2;
okini3939 0:d18dff347122 139
okini3939 0:d18dff347122 140 for (i = 0; i < n; i ++) {
okini3939 0:d18dff347122 141 c1 = (p1[i] >= 'a' && p1[i] <= 'z') ? p1[i] - ('a' - 'A'): p1[i];
okini3939 0:d18dff347122 142 c2 = (p2[i] >= 'a' && p2[i] <= 'z') ? p2[i] - ('a' - 'A'): p2[i];
okini3939 0:d18dff347122 143 r = c1 - c2;
okini3939 0:d18dff347122 144 if (r) break;
okini3939 0:d18dff347122 145 }
okini3939 0:d18dff347122 146 return r;
okini3939 0:d18dff347122 147 }
okini3939 0:d18dff347122 148
okini3939 0:d18dff347122 149
okini3939 0:d18dff347122 150 /* base64encode code from
okini3939 0:d18dff347122 151 * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
okini3939 0:d18dff347122 152 */
okini3939 0:d18dff347122 153 int HTTPD::base64encode (const char *input, int length, char *output, int len) {
okini3939 0:d18dff347122 154 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
okini3939 0:d18dff347122 155 unsigned int c, c1, c2, c3;
okini3939 0:d18dff347122 156
okini3939 0:d18dff347122 157 if (len < ((((length-1)/3)+1)<<2)) return -1;
okini3939 0:d18dff347122 158 for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
okini3939 0:d18dff347122 159 c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
okini3939 0:d18dff347122 160 c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
okini3939 0:d18dff347122 161 c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
okini3939 0:d18dff347122 162
okini3939 0:d18dff347122 163 c = ((c1 & 0xFC) >> 2);
okini3939 0:d18dff347122 164 output[j+0] = base64[c];
okini3939 0:d18dff347122 165 c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
okini3939 0:d18dff347122 166 output[j+1] = base64[c];
okini3939 0:d18dff347122 167 c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
okini3939 0:d18dff347122 168 output[j+2] = (length>i+1)?base64[c]:'=';
okini3939 0:d18dff347122 169 c = (c3 & 0x3F);
okini3939 0:d18dff347122 170 output[j+3] = (length>i+2)?base64[c]:'=';
okini3939 0:d18dff347122 171 }
okini3939 0:d18dff347122 172 output[(((length-1)/3)+1)<<2] = '\0';
okini3939 0:d18dff347122 173 return 0;
okini3939 0:d18dff347122 174 }
okini3939 0:d18dff347122 175
okini3939 0:d18dff347122 176
okini3939 0:d18dff347122 177 /* urlencode code from
okini3939 0:d18dff347122 178 * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
okini3939 0:d18dff347122 179 */
okini3939 0:d18dff347122 180 int HTTPD::urlencode (const char *str, char *buf, int len) {
okini3939 0:d18dff347122 181 // char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
okini3939 0:d18dff347122 182 const char *pstr = str;
okini3939 0:d18dff347122 183 char *pbuf = buf;
okini3939 0:d18dff347122 184
okini3939 0:d18dff347122 185 if (len < (strlen(str) * 3 + 1)) return -1;
okini3939 0:d18dff347122 186 while (*pstr) {
okini3939 0:d18dff347122 187 if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
okini3939 0:d18dff347122 188 *pbuf++ = *pstr;
okini3939 0:d18dff347122 189 else if (*pstr == ' ')
okini3939 0:d18dff347122 190 *pbuf++ = '+';
okini3939 0:d18dff347122 191 else
okini3939 0:d18dff347122 192 *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
okini3939 0:d18dff347122 193 pstr++;
okini3939 0:d18dff347122 194 }
okini3939 0:d18dff347122 195 *pbuf = '\0';
okini3939 0:d18dff347122 196 return 0;
okini3939 0:d18dff347122 197 }
okini3939 0:d18dff347122 198
okini3939 0:d18dff347122 199 /* urldecode code from
okini3939 0:d18dff347122 200 * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
okini3939 0:d18dff347122 201 */
okini3939 0:d18dff347122 202 int HTTPD::urldecode (const char *str, char *buf, int len) {
okini3939 0:d18dff347122 203 // char *pstr = str, *buf = (char*)malloc(strlen(str) + 1), *pbuf = buf;
okini3939 0:d18dff347122 204 const char *pstr = str;
okini3939 0:d18dff347122 205 char *pbuf = buf;
okini3939 0:d18dff347122 206
okini3939 0:d18dff347122 207 if (len < (strlen(str) / 3 - 1)) return -1;
okini3939 0:d18dff347122 208 while (*pstr) {
okini3939 0:d18dff347122 209 if (*pstr == '%') {
okini3939 0:d18dff347122 210 if (pstr[1] && pstr[2]) {
okini3939 0:d18dff347122 211 *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
okini3939 0:d18dff347122 212 pstr += 2;
okini3939 0:d18dff347122 213 }
okini3939 0:d18dff347122 214 } else if (*pstr == '+') {
okini3939 0:d18dff347122 215 *pbuf++ = ' ';
okini3939 0:d18dff347122 216 } else {
okini3939 0:d18dff347122 217 *pbuf++ = *pstr;
okini3939 0:d18dff347122 218 }
okini3939 0:d18dff347122 219 pstr++;
okini3939 0:d18dff347122 220 }
okini3939 0:d18dff347122 221 *pbuf = '\0';
okini3939 0:d18dff347122 222 return 0;
okini3939 0:d18dff347122 223 }
okini3939 0:d18dff347122 224
okini3939 0:d18dff347122 225 int HTTPD::from_hex (int ch) {
okini3939 0:d18dff347122 226 return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
okini3939 0:d18dff347122 227 }
okini3939 0:d18dff347122 228
okini3939 0:d18dff347122 229 int HTTPD::to_hex (int code) {
okini3939 0:d18dff347122 230 static char hex[] = "0123456789abcdef";
okini3939 0:d18dff347122 231 return hex[code & 15];
okini3939 0:d18dff347122 232 }