Nut/OS  4.10.3
API Reference
asp.c
Go to the documentation of this file.
00001 /****************************************************************************
00002 *  Copyright (c) 2004 by Michael Fischer. 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 author nor the names of its contributors may 
00014 *     be used to endorse or promote products derived from this software 
00015 *     without specific prior written permission.
00016 *
00017 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 
00021 *  THE COPYRIGHT OWNER 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 ****************************************************************************
00031 *  History:
00032 *
00033 *  31.03.04  mifi   First Version
00034 *  02.10.04  mifi   Add function to register a user callback
00035 *  04.08.05  or     Adopted to new new mime-handler framework
00036 ****************************************************************************/
00037 
00038 /*
00039  * $Log$
00040  * Revision 1.6  2009/02/13 14:52:05  haraldkipp
00041  * Include memdebug.h for heap management debugging support.
00042  *
00043  * Revision 1.5  2009/02/06 15:40:29  haraldkipp
00044  * Using newly available strdup() and calloc().
00045  * Replaced NutHeap routines by standard malloc/free.
00046  * Replaced pointer value 0 by NULL.
00047  *
00048  * Revision 1.4  2008/05/16 01:46:43  thiagocorrea
00049  * Minor spellcheck fix on the documentation.
00050  *
00051  * Revision 1.3  2006/03/16 15:25:38  haraldkipp
00052  * Changed human readable strings from u_char to char to stop GCC 4 from
00053  * nagging about signedness.
00054  *
00055  * Revision 1.2  2005/08/10 09:26:38  olereinhardt
00056  * Corrected documentation
00057  *
00058  * Revision 1.1  2005/08/05 11:21:02  olereinhardt
00059  * Added Michael Fischers ASP support. Initial checkin
00060  *
00061  */  
00062 
00067 
00068 
00069 #include <sys/heap.h>
00070 #include <sys/confnet.h>
00071 #include <sys/version.h>
00072 
00073 #include <stdlib.h>
00074 #include <string.h>
00075 #include <io.h>
00076 #include <fcntl.h>
00077 #include <memdebug.h>
00078 
00079 #include <pro/httpd.h>
00080 #include <pro/asp.h>
00081 #include <arpa/inet.h>
00082 
00083 extern CONFNET confnet;
00084 
00085 /*==========================================================*/
00086 /*  DEFINE: All Structures and Common Constants             */
00087 /*==========================================================*/
00088 /*
00089  * Use the half size of the normal buffer, because we need
00090  * 2 buffers. To save memory, we have divide the size too.
00091  */
00092 #define MAX_BUFFER_SIZE     256
00093 
00094 /*
00095  * Do NOT use more than 250 for the len.
00096  * Because we use a unsigned char for the ASPFuncLen
00097  */
00098 #define MAX_ASP_FUNC_SIZE   64
00099 
00100 enum {
00101     ASP_STATE_IDLE = 0,
00102     ASP_STATE_START,
00103     ASP_STATE_COPY_FUNC
00104 };
00105 
00106 /*==========================================================*/
00107 /*  DEFINE: Definition of all local Data                    */
00108 /*==========================================================*/
00109 static int (*asp_callback)(char *, FILE *) = NULL;
00110 
00111 /*==========================================================*/
00112 /*  DEFINE: Definition of all local Procedures              */
00113 /*==========================================================*/
00114 /************************************************************/
00115 /*  ProcessASPFunction                                      */
00116 /************************************************************/
00117 static void ProcessAspFunction(char *pASPFunction, FILE * stream)
00118 {
00119     if (strstr(pASPFunction, "nut_version") != NULL) {
00120         fprintf(stream, "%s", NutVersionString());
00121         return;
00122     }
00123 
00124     if (strstr(pASPFunction, "nut_mac_addr") != NULL) {
00125         fprintf(stream, "%02X:%02X:%02X:%02X:%02X:%02X",
00126                 confnet.cdn_mac[0], confnet.cdn_mac[1], confnet.cdn_mac[2],
00127                 confnet.cdn_mac[3], confnet.cdn_mac[4], confnet.cdn_mac[5]);
00128         return;
00129     }
00130 
00131     if (strstr(pASPFunction, "nut_ip_addr") != NULL) {
00132         fputs(inet_ntoa(confnet.cdn_ip_addr), stream);
00133         return;
00134     }
00135 
00136     if (strstr(pASPFunction, "nut_ip_mask") != NULL) {
00137         fputs(inet_ntoa(confnet.cdn_ip_mask), stream);
00138         return;
00139     }
00140 
00141     if (strstr(pASPFunction, "nut_gateway") != NULL) {
00142         fputs(inet_ntoa(confnet.cdn_gateway), stream);
00143         return;
00144     }
00145 
00146     /*
00147      * Check if the user has registered an ASPCallback
00148      */
00149     if (asp_callback != NULL) {
00150         asp_callback(pASPFunction, stream);
00151     }
00152 }
00153 
00154 /*==========================================================*/
00155 /*  DEFINE: All code exported                               */
00156 /*==========================================================*/
00157 /************************************************************/
00158 /*  NutHttpCheckAsp                                         */
00159 /************************************************************/
00160 void NutHttpProcessAsp(FILE * stream, int fd, int file_len, char* http_root, REQUEST *req)
00161 {
00162     int n;
00163     char *pReadBuffer = NULL;
00164     char *pWriteBuffer = NULL;
00165     char *pASPFunction = NULL;
00166     char Data;
00167     int Size;
00168     long lFileLen;
00169     unsigned char bASPState = ASP_STATE_IDLE;
00170     int ReadCount;
00171     int WriteCount;
00172     unsigned char bASPFuncLen;
00173 
00174     lFileLen = _filelength(fd);
00175 
00176     Size = MAX_BUFFER_SIZE;
00177     WriteCount = 0;
00178     bASPFuncLen = 0;
00179     pASPFunction = malloc(MAX_ASP_FUNC_SIZE);
00180     pReadBuffer = malloc(Size);
00181     /*
00182      * For our VERY SPECIAL case, the size of the WriteBuffer must have one char more
00183      * as the ReadBuffer. Because we must be able to save one more char from the round before.
00184      */
00185     pWriteBuffer = malloc(Size + 1);
00186 
00187     if ((pReadBuffer != NULL) && (pWriteBuffer != NULL) && (pASPFunction != NULL)) {
00188 
00189         while (lFileLen) {
00190             if (lFileLen < MAX_BUFFER_SIZE) {
00191                 Size = (int) lFileLen;
00192             }
00193 
00194             n = _read(fd, pReadBuffer, Size);
00195 
00196             for (ReadCount = 0; ReadCount < n; ReadCount++) {
00197 
00198                 Data = pReadBuffer[ReadCount];
00199 
00200                 switch (bASPState) {
00201                 
00202                 case ASP_STATE_IDLE:
00203                     if (Data == '<') {
00204                         bASPState = ASP_STATE_START;
00205                     }
00206                     pWriteBuffer[WriteCount] = Data;
00207                     WriteCount++;
00208                     break;
00209                     /* ASP_STATE_IDLE */
00210 
00211                 case ASP_STATE_START:
00212                     if (Data == '%') {
00213                         bASPState = ASP_STATE_COPY_FUNC;
00214                         if (WriteCount) {
00215                             WriteCount--;
00216                         }
00217 
00218                         /*
00219                          * Write the data up to the ASPFunction
00220                          */
00221                         if (WriteCount) {
00222                             fwrite(pWriteBuffer, 1, WriteCount, stream);
00223                             WriteCount = 0;
00224                         }
00225                     } else {
00226                         bASPState = ASP_STATE_IDLE;
00227                         pWriteBuffer[WriteCount] = Data;
00228                         WriteCount++;
00229                     }
00230                     break;
00231                     /* ASP_STATE_START_1 */
00232 
00233                 case ASP_STATE_COPY_FUNC:
00234                     if (Data == '>') {
00235                         bASPState = ASP_STATE_IDLE;
00236                         pASPFunction[bASPFuncLen] = 0;
00237 
00238                         ProcessAspFunction(pASPFunction, stream);
00239                         bASPFuncLen = 0;
00240                     } else {
00241                         /*
00242                          * Skip over the END of an ASPFunction
00243                          */
00244                         if (Data == '%') {
00245                             Data = 0;
00246                         }
00247 
00248                         pASPFunction[bASPFuncLen] = Data;
00249                         bASPFuncLen++;
00250                         if (bASPFuncLen >= MAX_ASP_FUNC_SIZE) {
00251                             /*
00252                              * This make no sense, but protect our stack
00253                              */
00254                             bASPFuncLen = 0;
00255                         }
00256                     }
00257                     break;
00258                     /* ASP_STATE_COPY_FUNC */
00259                 } /* end switch (bASPState) */
00260             } /* end for */
00261 
00262             /*
00263              * If data are available in the WriteBuffer, 
00264              * send it out...
00265              */
00266             if (WriteCount) {
00267                 /*
00268                  * Now we must test a VERY SPECIAL case !
00269                  * It could be possible that the last char in the buffer is a '<'.
00270                  * Now the State is ASP_STATE_START. If the next chunk starts with a
00271                  * '%' it is to late, because we have send out the '<'.
00272                  * Therefore we must test if the last char is a '<', in this case send all the
00273                  * rest and save the '<' for the next round.
00274                  */
00275 
00276                 if (pWriteBuffer[WriteCount - 1] == '<') {
00277                     WriteCount--;
00278                     fwrite(pWriteBuffer, 1, WriteCount, stream);
00279 
00280                     /*
00281                      * Now put the '<' in the buffer for the next round
00282                      */
00283                     pWriteBuffer[0] = '<';
00284                     WriteCount = 1;
00285                 } else {
00286                     fwrite(pWriteBuffer, 1, WriteCount, stream);
00287                     WriteCount = 0;
00288                 }
00289             }
00290 
00291             lFileLen -= (long) n;
00292         }
00293     }
00294 
00295     if (pReadBuffer != NULL) {
00296         free(pReadBuffer);
00297     }
00298     if (pWriteBuffer != NULL) {
00299         free(pWriteBuffer);
00300     }
00301     if (pASPFunction != NULL) {
00302         free(pASPFunction);
00303     }
00304 }
00305 
00306 /************************************************************/
00307 /*  NutRegisterAspCallback                                  */
00308 /*                                                          */
00309 /*  return 0 on success, -1 otherwise.                      */
00310 /************************************************************/
00311 int NutRegisterAspCallback(int (*func) (char *, FILE *))
00312 {
00313     register int result = 0;
00314 
00315     if (asp_callback == NULL) {
00316         asp_callback = func;
00317     } else {
00318         result = -1;
00319     }
00320 
00321     return (result);
00322 }
00323 
00332 void NutRegisterAsp(void)
00333 {
00334     NutSetMimeHandler(".asp", NutHttpProcessAsp);
00335 }
00336