/**************************************************************************** * Copyright (c) 2004 by Michael Fischer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * **************************************************************************** * History: * * 31.03.04 mifi First Version * 02.10.04 mifi Add function to register a user callback * 04.08.05 or Adopted to new new mime-handler framework ****************************************************************************/ /* * $Log$ * Revision 1.6 2009/02/13 14:52:05 haraldkipp * Include memdebug.h for heap management debugging support. * * Revision 1.5 2009/02/06 15:40:29 haraldkipp * Using newly available strdup() and calloc(). * Replaced NutHeap routines by standard malloc/free. * Replaced pointer value 0 by NULL. * * Revision 1.4 2008/05/16 01:46:43 thiagocorrea * Minor spellcheck fix on the documentation. * * Revision 1.3 2006/03/16 15:25:38 haraldkipp * Changed human readable strings from u_char to char to stop GCC 4 from * nagging about signedness. * * Revision 1.2 2005/08/10 09:26:38 olereinhardt * Corrected documentation * * Revision 1.1 2005/08/05 11:21:02 olereinhardt * Added Michael Fischers ASP support. Initial checkin * */ /*! * \addtogroup xgHTTPD */ /*@{*/ #include #include #include #include #include #include #include #include #include #include #include extern CONFNET confnet; /*==========================================================*/ /* DEFINE: All Structures and Common Constants */ /*==========================================================*/ /* * Use the half size of the normal buffer, because we need * 2 buffers. To save memory, we have divide the size too. */ #define MAX_BUFFER_SIZE 256 /* * Do NOT use more than 250 for the len. * Because we use a unsigned char for the ASPFuncLen */ #define MAX_ASP_FUNC_SIZE 64 enum { ASP_STATE_IDLE = 0, ASP_STATE_START, ASP_STATE_COPY_FUNC }; /*==========================================================*/ /* DEFINE: Definition of all local Data */ /*==========================================================*/ static int (*asp_callback)(char *, FILE *) = NULL; /*==========================================================*/ /* DEFINE: Definition of all local Procedures */ /*==========================================================*/ /************************************************************/ /* ProcessASPFunction */ /************************************************************/ static void ProcessAspFunction(char *pASPFunction, FILE * stream) { if (strstr(pASPFunction, "nut_version") != NULL) { fprintf(stream, "%s", NutVersionString()); return; } if (strstr(pASPFunction, "nut_mac_addr") != NULL) { fprintf(stream, "%02X:%02X:%02X:%02X:%02X:%02X", confnet.cdn_mac[0], confnet.cdn_mac[1], confnet.cdn_mac[2], confnet.cdn_mac[3], confnet.cdn_mac[4], confnet.cdn_mac[5]); return; } if (strstr(pASPFunction, "nut_ip_addr") != NULL) { fputs(inet_ntoa(confnet.cdn_ip_addr), stream); return; } if (strstr(pASPFunction, "nut_ip_mask") != NULL) { fputs(inet_ntoa(confnet.cdn_ip_mask), stream); return; } if (strstr(pASPFunction, "nut_gateway") != NULL) { fputs(inet_ntoa(confnet.cdn_gateway), stream); return; } /* * Check if the user has registered an ASPCallback */ if (asp_callback != NULL) { asp_callback(pASPFunction, stream); } } /*==========================================================*/ /* DEFINE: All code exported */ /*==========================================================*/ /************************************************************/ /* NutHttpCheckAsp */ /************************************************************/ void NutHttpProcessAsp(FILE * stream, int fd, int file_len, char* http_root, REQUEST *req) { int n; char *pReadBuffer = NULL; char *pWriteBuffer = NULL; char *pASPFunction = NULL; char Data; int Size; long lFileLen; unsigned char bASPState = ASP_STATE_IDLE; int ReadCount; int WriteCount; unsigned char bASPFuncLen; lFileLen = _filelength(fd); Size = MAX_BUFFER_SIZE; WriteCount = 0; bASPFuncLen = 0; pASPFunction = malloc(MAX_ASP_FUNC_SIZE); pReadBuffer = malloc(Size); /* * For our VERY SPECIAL case, the size of the WriteBuffer must have one char more * as the ReadBuffer. Because we must be able to save one more char from the round before. */ pWriteBuffer = malloc(Size + 1); if ((pReadBuffer != NULL) && (pWriteBuffer != NULL) && (pASPFunction != NULL)) { while (lFileLen) { if (lFileLen < MAX_BUFFER_SIZE) { Size = (int) lFileLen; } n = _read(fd, pReadBuffer, Size); for (ReadCount = 0; ReadCount < n; ReadCount++) { Data = pReadBuffer[ReadCount]; switch (bASPState) { case ASP_STATE_IDLE: if (Data == '<') { bASPState = ASP_STATE_START; } pWriteBuffer[WriteCount] = Data; WriteCount++; break; /* ASP_STATE_IDLE */ case ASP_STATE_START: if (Data == '%') { bASPState = ASP_STATE_COPY_FUNC; if (WriteCount) { WriteCount--; } /* * Write the data up to the ASPFunction */ if (WriteCount) { fwrite(pWriteBuffer, 1, WriteCount, stream); WriteCount = 0; } } else { bASPState = ASP_STATE_IDLE; pWriteBuffer[WriteCount] = Data; WriteCount++; } break; /* ASP_STATE_START_1 */ case ASP_STATE_COPY_FUNC: if (Data == '>') { bASPState = ASP_STATE_IDLE; pASPFunction[bASPFuncLen] = 0; ProcessAspFunction(pASPFunction, stream); bASPFuncLen = 0; } else { /* * Skip over the END of an ASPFunction */ if (Data == '%') { Data = 0; } pASPFunction[bASPFuncLen] = Data; bASPFuncLen++; if (bASPFuncLen >= MAX_ASP_FUNC_SIZE) { /* * This make no sense, but protect our stack */ bASPFuncLen = 0; } } break; /* ASP_STATE_COPY_FUNC */ } /* end switch (bASPState) */ } /* end for */ /* * If data are available in the WriteBuffer, * send it out... */ if (WriteCount) { /* * Now we must test a VERY SPECIAL case ! * It could be possible that the last char in the buffer is a '<'. * Now the State is ASP_STATE_START. If the next chunk starts with a * '%' it is to late, because we have send out the '<'. * Therefore we must test if the last char is a '<', in this case send all the * rest and save the '<' for the next round. */ if (pWriteBuffer[WriteCount - 1] == '<') { WriteCount--; fwrite(pWriteBuffer, 1, WriteCount, stream); /* * Now put the '<' in the buffer for the next round */ pWriteBuffer[0] = '<'; WriteCount = 1; } else { fwrite(pWriteBuffer, 1, WriteCount, stream); WriteCount = 0; } } lFileLen -= (long) n; } } if (pReadBuffer != NULL) { free(pReadBuffer); } if (pWriteBuffer != NULL) { free(pWriteBuffer); } if (pASPFunction != NULL) { free(pASPFunction); } } /************************************************************/ /* NutRegisterAspCallback */ /* */ /* return 0 on success, -1 otherwise. */ /************************************************************/ int NutRegisterAspCallback(int (*func) (char *, FILE *)) { register int result = 0; if (asp_callback == NULL) { asp_callback = func; } else { result = -1; } return (result); } /*! * \brief Register ASP handler for asp files. * * asp files may use the following syntax: * * <%my_function%> */ void NutRegisterAsp(void) { NutSetMimeHandler(".asp", NutHttpProcessAsp); } /*@}*/