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

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