00001 /* 00002 * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00018 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00020 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00021 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00023 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00026 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00027 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * For additional information see http://www.ethernut.de/ 00031 */ 00032 00033 /* 00034 * $Log$ 00035 * Revision 1.9 2009/02/13 14:52:05 haraldkipp 00036 * Include memdebug.h for heap management debugging support. 00037 * 00038 * Revision 1.8 2009/02/06 15:40:29 haraldkipp 00039 * Using newly available strdup() and calloc(). 00040 * Replaced NutHeap routines by standard malloc/free. 00041 * Replaced pointer value 0 by NULL. 00042 * 00043 * Revision 1.7 2008/08/22 09:23:56 haraldkipp 00044 * GCC specific implementation removed. 00045 * 00046 * Revision 1.6 2008/07/26 14:09:29 haraldkipp 00047 * Fixed another problem with ICCAVR. 00048 * 00049 * Revision 1.5 2008/07/25 12:17:26 olereinhardt 00050 * Imagecraft compilers does not support alloca (to allocate memory from the 00051 * stack). So we use NutHeapAlloc / NutHeapClear instead for Imagecraft. 00052 * 00053 * Revision 1.4 2008/07/17 11:33:32 olereinhardt 00054 * - Check for unique cgi names 00055 * - Alloc local copy of cgi name. Allows dynamicaly generated cgi names 00056 * - Function to register a different cgi-bin path. Multiple path allowed. 00057 * See httpd demo for an example 00058 * 00059 * Revision 1.3 2008/07/09 14:23:49 haraldkipp 00060 * Info about NutRegisterCgi's first parameter updated. 00061 * 00062 * Revision 1.2 2006/10/08 16:48:22 haraldkipp 00063 * Documentation fixed 00064 * 00065 * Revision 1.1.1.1 2003/05/09 14:41:56 haraldkipp 00066 * Initial using 3.2.1 00067 * 00068 * Revision 1.7 2003/02/04 18:17:31 harald 00069 * Version 3 released 00070 * 00071 * Revision 1.6 2002/06/26 17:29:49 harald 00072 * First pre-release with 2.4 stack 00073 * 00074 */ 00075 00076 #include <sys/heap.h> 00077 #include <stdlib.h> 00078 #include <string.h> 00079 #include <memdebug.h> 00080 00081 #include <pro/httpd.h> 00082 00087 00088 CGIFUNCTION *volatile cgiFunctionList = 0; 00089 char *cgiBinPath = NULL; 00090 00098 void NutRegisterCgiBinPath(char *path) 00099 { 00100 if (cgiBinPath) { 00101 free(cgiBinPath); 00102 } 00103 cgiBinPath = strdup(path); 00104 } 00105 00116 int NutCgiCheckRequest(FILE * stream, REQUEST * req) 00117 { 00118 /* 00119 * My version sticks with basic C routines. I hope, that it is also 00120 * faster and uses less memory. But it hasn't been tested very well, 00121 * so let's keep Ole's variant for GCC. 00122 */ 00123 size_t len; 00124 CONST char *cp; 00125 CONST char *cgi_bin = cgiBinPath ? cgiBinPath : "cgi-bin/"; 00126 00127 while (*cgi_bin) { 00128 /* Skip leading path separators. */ 00129 while (*cgi_bin == ';') 00130 cgi_bin++; 00131 /* Determine the length of the next path component. */ 00132 for (len = 0, cp = cgi_bin; *cp && *cp != ';'; len++, cp++); 00133 if (len) { 00134 /* Check if the URL starts with this component. If yes, run the CGI. */ 00135 if (strncasecmp(req->req_url, cgi_bin, len) == 0) { 00136 NutCgiProcessRequest(stream, req, len); 00137 return 1; 00138 } 00139 /* Try the next path component. */ 00140 cgi_bin += len; 00141 } 00142 } 00143 return 0; 00144 } 00145 00155 int NutRegisterCgi(char *name, int (*func) (FILE *, REQUEST *)) 00156 { 00157 int unique_name = 1; 00158 CGIFUNCTION *cgi; 00159 00160 cgi = cgiFunctionList; 00161 while (cgi != NULL) { 00162 if (strcmp(name, cgi->cgi_name) == 0) { 00163 unique_name = 0; 00164 break; 00165 } 00166 cgi = cgi->cgi_next; 00167 } 00168 00169 if ((!unique_name) || ((cgi = malloc(sizeof(CGIFUNCTION))) == 0)) { 00170 return -1; 00171 } 00172 cgi->cgi_next = cgiFunctionList; 00173 cgi->cgi_name = strdup(name); 00174 cgi->cgi_func = func; 00175 cgiFunctionList = cgi; 00176 00177 return 0; 00178 } 00179 00190 void NutCgiProcessRequest(FILE * stream, REQUEST * req, int name_pos) 00191 { 00192 CGIFUNCTION *cgi; 00193 00194 if (req->req_method != METHOD_GET && req->req_method != METHOD_POST) { 00195 NutHttpSendError(stream, req, 501); 00196 return; 00197 } 00198 00199 for (cgi = cgiFunctionList; cgi; cgi = cgi->cgi_next) { 00200 if (strcasecmp(cgi->cgi_name, req->req_url + name_pos) == 0) 00201 break; 00202 } 00203 if (cgi == 0) 00204 NutHttpSendError(stream, req, 404); 00205 else if ((*cgi->cgi_func) (stream, req)) 00206 NutHttpSendError(stream, req, 500); 00207 return; 00208 } 00209