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

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/