more handlers

Dependents:   bandwidth-meter-net mbedRail24v

Fork of Tiny-HTTPD by ban4jp -

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPD_util.cpp Source File

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 }