| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /*
- * Copyright (C) 2008 by egnite GmbH. All rights reserved.
- * Copyright (C) 2001-2007 by egnite Software GmbH. 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 copyright holders nor the names of
- * 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.
- *
- * For additional information see http://www.ethernut.de/
- */
- /*!
- * \file pro/httpopt.c
- * \brief Optional HTTP routines.
- *
- * \verbatim
- *
- * $Log$
- * Revision 1.4 2009/02/13 14:52:05 haraldkipp
- * Include memdebug.h for heap management debugging support.
- *
- * Revision 1.3 2008/08/11 07:00:35 haraldkipp
- * BSD types replaced by stdint types (feature request #1282721).
- *
- * Revision 1.2 2008/05/13 21:46:06 thiagocorrea
- * Fix a few documentation typos.
- *
- * Revision 1.1 2008/04/01 10:11:35 haraldkipp
- * Added the new, enhanced httpd API library.
- * Bugs #1839026 and #1839029 fixed.
- *
- *
- * \endverbatim
- */
- #include <cfg/arch.h>
- #include <string.h>
- #include <io.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <memdebug.h>
- #include <sys/heap.h>
- #include <sys/version.h>
- #include "dencode.h"
- #include <pro/httpd.h>
- /*!
- * \addtogroup xgHTTPD
- */
- /*@{*/
- extern MIMETYPES mimeTypes[];
- extern char *http_root;
- /*!
- * \brief Set the mime type handler for a specified file extension.
- *
- * This is the function that handles / sends a specific file type to the
- * client. Specially used for server side includes (shtml files)
- *
- * \param extension Filename extension the handler should be registered for
- * \param handler pointer to a function of the type void (u_char filename)
- * \return 1 on error or 0 on success
- */
- uint8_t NutSetMimeHandler(char *extension, void (*handler)(FILE *stream, int fd, int file_len, char *http_root, REQUEST *req))
- {
- size_t i;
- if (extension == NULL)
- return 1;
- for (i = 0; mimeTypes[i].mtyp_ext; i++)
- if (strcasecmp(extension, mimeTypes[i].mtyp_ext) == 0) {
- mimeTypes[i].mtyp_handler = handler;
- return 0;
- }
- return 1;
- }
- /*!
- * \brief URLEncodes a string
- *
- * \param str String to encode
- *
- * \return A new allocated encoded string, or NULL if str is null, or
- * if there's not enough memory for the new string.
- *
- * \note Remember to free() to the returned string.
- */
- char *NutHttpURLEncode(char *str)
- {
- static char *hexdigits = "0123456789ABCDEF";
- register char *ptr1, *ptr2;
- char *encstring;
- int numEncs = 0;
- if (!str)
- return NULL;
- /* Calculate how many characters we need to encode */
- for (ptr1 = str; *ptr1; ptr1++) {
- if (!isalnum((unsigned char)*ptr1) || *ptr1 == '%' || *ptr1 == '&'|| *ptr1 == '+' ||
- *ptr1 == ',' || *ptr1 == ':' || *ptr1 == ';'|| *ptr1 == '='|| *ptr1 == '?'|| *ptr1 == '@')
- numEncs++;
- }
- /* Now we can calculate the encoded string length */
- encstring = (char *) malloc(strlen(str) + 2 * numEncs + 1);
- if (encstring) {
- /* Encode the string. ptr1 refers to the original string,
- * and ptr2 refers to the new string. */
- ptr2 = encstring;
- for (ptr1 = str; *ptr1; ptr1++) {
- if (isalnum((unsigned char)*ptr1) || *ptr1 == '%' || *ptr1 == '&'|| *ptr1 == '+' ||
- *ptr1 == ',' || *ptr1 == ':' || *ptr1 == ';'|| *ptr1 == '='|| *ptr1 == '?'|| *ptr1 == '@')
- *ptr2++ = *ptr1;
- else {
- *ptr2++ = '%';
- *ptr2++ = hexdigits[(*ptr1 >> 4)];
- *ptr2++ = hexdigits[*ptr1 & 0x0F];
- }
- }
- *ptr2++ = 0;
- }
- return encstring;
- }
- /*!
- * \brief Parses the QueryString
- *
- * Reads the query from input stream and parses it into
- * name/value table. To save RAM, this method allocated ram and
- * uses req_query to store the input data. Then it creates a table
- * of pointers into the req_query buffer.
- *
- * \param stream Input stream
- * \param req Request object to parse
- */
- void NutHttpProcessPostQuery(FILE *stream, REQUEST * req)
- {
- int got;
- register int i;
- register char *ptr;
- if (req->req_query != NULL)
- return;
- if (!stream)
- return;
- if (req->req_method == METHOD_POST) {
- req->req_query = malloc(req->req_length+1);
- if (req->req_query == NULL) {
- /* Out of memory */
- req->req_numqptrs = 0;
- return;
- }
- memset(req->req_query, 0, req->req_length+1);
- i = 0;
- while (i < req->req_length) {
- got = fread(&req->req_query[i], 1, req->req_length-i, stream);
- if (got <= 0) {
- free(req->req_query);
- req->req_numqptrs = 0;
- req->req_query = NULL;
- return;
- }
- i += got;
- }
- } else return;
- req->req_numqptrs = 1;
- for (ptr = req->req_query; *ptr; ptr++)
- if (*ptr == '&')
- req->req_numqptrs++;
- req->req_qptrs = (char **) malloc(sizeof(char *) * (req->req_numqptrs * 2));
- if (!req->req_qptrs) {
- /* Out of memory */
- free(req->req_query);
- req->req_numqptrs = 0;
- req->req_query = NULL;
- return;
- }
- req->req_qptrs[0] = req->req_query;
- req->req_qptrs[1] = 0;
- for (ptr = req->req_query, i = 2; *ptr; ptr++) {
- if (*ptr == '&') {
- req->req_qptrs[i] = ptr + 1;
- req->req_qptrs[i + 1] = NULL;
- *ptr = 0;
- i += 2;
- }
- }
- for (i = 0; i < req->req_numqptrs; i++) {
- for (ptr = req->req_qptrs[i * 2]; *ptr; ptr++) {
- if (*ptr == '=') {
- req->req_qptrs[i * 2 + 1] = ptr + 1;
- *ptr = 0;
- NutHttpURLDecode(req->req_qptrs[i * 2 + 1]);
- break;
- }
- }
- NutHttpURLDecode(req->req_qptrs[i * 2]);
- }
- }
- /*!
- * \brief Gets a request parameter value by name
- *
- * \param req Request object
- * \param name Name of parameter
- *
- * \return Pointer to the parameter value.
- */
- char *NutHttpGetParameter(REQUEST * req, char *name)
- {
- int i;
- for (i = 0; i < req->req_numqptrs; i++)
- if (strcmp(req->req_qptrs[i * 2], name) == 0)
- return req->req_qptrs[i * 2 + 1];
- return NULL;
- }
- /*!
- * \brief Gets the number of request parameters
- *
- * The following code fragment retrieves all name/value pairs of the
- * request.
- *
- * \code
- * #include <pro/httpd.h>
- *
- * char *name;
- * char *value;
- * int i;
- * int n = NutHttpGetParameterCount(req);
- *
- * for (i = 0; i < n; i++) {
- * name = NutHttpGetParameterName(req, i);
- * value = NutHttpGetParameterValue(req, i);
- * }
- * \endcode
- *
- * \param req Request object
- *
- * \return The number of request parameters
- */
- int NutHttpGetParameterCount(REQUEST * req)
- {
- return req->req_numqptrs;
- }
- /*!
- * \brief Gets the name of a request parameter
- *
- * \param req Request object
- * \param index Index of the requested parameter.
- *
- * \return Pointer to the parameter name at the given index,
- * or NULL if index is out of range.
- */
- char *NutHttpGetParameterName(REQUEST * req, int index)
- {
- if (index < 0 || index >= NutHttpGetParameterCount(req))
- return NULL;
- return req->req_qptrs[index * 2];
- }
- /*!
- * \brief Get the value of a request parameter
- *
- * \param req Request object
- * \param index Index to the requested parameter.
- *
- * \return Pointer to the parameter value at the given index,
- * or NULL if index is out of range.
- */
- char *NutHttpGetParameterValue(REQUEST * req, int index)
- {
- if (index < 0 || index >= NutHttpGetParameterCount(req))
- return NULL;
- return req->req_qptrs[index * 2 + 1];
- }
- /*@}*/
|