Nut/OS  4.10.3
API Reference
cgi.c
Go to the documentation of this file.
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