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: cgi.c,v $ 00035 * Revision 1.6.2.1 2009/03/09 17:47:41 haraldkipp 00036 * GCC specific implementation removed. This fixes the missing alloca for 00037 * older avr-libc versions. 00038 * 00039 * Revision 1.6 2008/07/26 14:09:29 haraldkipp 00040 * Fixed another problem with ICCAVR. 00041 * 00042 * Revision 1.5 2008/07/25 12:17:26 olereinhardt 00043 * Imagecraft compilers does not support alloca (to allocate memory from the 00044 * stack). So we use NutHeapAlloc / NutHeapClear instead for Imagecraft. 00045 * 00046 * Revision 1.4 2008/07/17 11:33:32 olereinhardt 00047 * - Check for unique cgi names 00048 * - Alloc local copy of cgi name. Allows dynamicaly generated cgi names 00049 * - Function to register a different cgi-bin path. Multiple path allowed. 00050 * See httpd demo for an example 00051 * 00052 * Revision 1.3 2008/07/09 14:23:49 haraldkipp 00053 * Info about NutRegisterCgi's first parameter updated. 00054 * 00055 * Revision 1.2 2006/10/08 16:48:22 haraldkipp 00056 * Documentation fixed 00057 * 00058 * Revision 1.1.1.1 2003/05/09 14:41:56 haraldkipp 00059 * Initial using 3.2.1 00060 * 00061 * Revision 1.7 2003/02/04 18:17:31 harald 00062 * Version 3 released 00063 * 00064 * Revision 1.6 2002/06/26 17:29:49 harald 00065 * First pre-release with 2.4 stack 00066 * 00067 */ 00068 00069 #include <sys/heap.h> 00070 #include <string.h> 00071 00072 #include <pro/httpd.h> 00073 00078 00079 CGIFUNCTION *volatile cgiFunctionList = 0; 00080 char *cgiBinPath = NULL; 00081 00089 void NutRegisterCgiBinPath(char *path) 00090 { 00091 if (cgiBinPath) { 00092 NutHeapFree(cgiBinPath); 00093 } 00094 00095 cgiBinPath = NutHeapAlloc(strlen(path) + 1); 00096 strcpy(cgiBinPath, path); 00097 } 00098 00109 int NutCgiCheckRequest(FILE * stream, REQUEST * req) 00110 { 00111 /* 00112 * My version sticks with basic C routines. I hope, that it is also 00113 * faster and uses less memory. But it hasn't been tested very well, 00114 * so let's keep Ole's variant for GCC. 00115 */ 00116 size_t len; 00117 CONST char *cp; 00118 CONST char *cgi_bin = cgiBinPath ? cgiBinPath : "cgi-bin/"; 00119 00120 while (*cgi_bin) { 00121 /* Skip leading path separators. */ 00122 while (*cgi_bin == ';') 00123 cgi_bin++; 00124 /* Determine the length of the next path component. */ 00125 for (len = 0, cp = cgi_bin; *cp && *cp != ';'; len++, cp++); 00126 if (len) { 00127 /* Check if the URL starts with this component. If yes, run the CGI. */ 00128 if (strncasecmp(req->req_url, cgi_bin, len) == 0) { 00129 NutCgiProcessRequest(stream, req, len); 00130 return 1; 00131 } 00132 /* Try the next path component. */ 00133 cgi_bin += len; 00134 } 00135 } 00136 return 0; 00137 } 00138 00148 int NutRegisterCgi(char *name, int (*func) (FILE *, REQUEST *)) 00149 { 00150 int unique_name = 1; 00151 CGIFUNCTION *cgi; 00152 00153 cgi = cgiFunctionList; 00154 while (cgi != NULL) { 00155 if (strcmp(name, cgi->cgi_name) == 0) { 00156 unique_name = 0; 00157 break; 00158 } 00159 cgi = cgi->cgi_next; 00160 } 00161 00162 if ((!unique_name) || ((cgi = NutHeapAlloc(sizeof(CGIFUNCTION))) == 0)) { 00163 return -1; 00164 } 00165 cgi->cgi_next = cgiFunctionList; 00166 cgi->cgi_name = NutHeapAlloc(strlen(name)+1); 00167 strcpy(cgi->cgi_name, name); 00168 cgi->cgi_func = func; 00169 cgiFunctionList = cgi; 00170 00171 return 0; 00172 } 00173 00184 void NutCgiProcessRequest(FILE * stream, REQUEST * req, int name_pos) 00185 { 00186 CGIFUNCTION *cgi; 00187 00188 if (req->req_method != METHOD_GET && req->req_method != METHOD_POST) { 00189 NutHttpSendError(stream, req, 501); 00190 return; 00191 } 00192 00193 for (cgi = cgiFunctionList; cgi; cgi = cgi->cgi_next) { 00194 if (strcasecmp(cgi->cgi_name, req->req_url + name_pos) == 0) 00195 break; 00196 } 00197 if (cgi == 0) 00198 NutHttpSendError(stream, req, 404); 00199 else if ((*cgi->cgi_func) (stream, req)) 00200 NutHttpSendError(stream, req, 500); 00201 return; 00202 } 00203