⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpd.c

📁 HTTPD server. AVR platform
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (C) 2001-2003 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 EGNITE SOFTWARE GMBH 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 EGNITE
 * SOFTWARE GMBH 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/
 */

/*
 * $Log: httpd.c,v $
 * Revision 1.3  2003/07/20 16:03:27  haraldkipp
 * Saved some RAM by moving string literals to program memory.
 *
 * Revision 1.2  2003/07/17 12:28:21  haraldkipp
 * Memory hole bugfix
 *
 * Revision 1.1.1.1  2003/05/09 14:41:58  haraldkipp
 * Initial using 3.2.1
 *
 * Revision 1.14  2003/02/04 18:17:32  harald
 * Version 3 released
 *
 * Revision 1.13  2003/01/14 17:04:20  harald
 * Using FAT file system and added types
 *
 * Revision 1.12  2002/10/31 16:32:45  harald
 * Mods by troth for Linux
 *
 * Revision 1.11  2002/09/15 17:08:44  harald
 * Allow different character sets
 *
 * Revision 1.10  2002/06/26 17:29:49  harald
 * First pre-release with 2.4 stack
 *
 */

#include <string.h>
#include <io.h>
#include <fcntl.h>

#include <sys/heap.h>
#include <sys/version.h>

#include "dencode.h"

#include <pro/httpd.h>

/*!
 * \addtogroup xgHTTPD
 */
/*@{*/

static struct {
    char *ext;
    char *type;
} mimeTypes[] = {
    {
    ".txt", "text/plain"}, {
    ".html", "text/html"}, {
    ".htm", "text/html"}, {
    ".gif", "image/gif"}, {
    ".jpg", "image/jpeg"}, {
    ".pdf", "application/pdf"}, {
    ".js", "application/x-javascript"}
};

static char *http_root;

/*!
 * \brief Send top lines of a standard HTML header.
 *
 * Sends HTTP and Server version lines.
 *
 * \param stream Stream of the socket connection, previously opened for 
 *               binary read and write.
 * \param req    The associated client request.
 * \param status Response status, error code or 200, if no error occured.
 * \param title  Error text, or OK, if no error occured.
 */
void NutHttpSendHeaderTop(FILE * stream, REQUEST * req, int status, char *title)
{
    static prog_char fmt_P[] = "HTTP/%d.%d %d %s\r\nServer: Ethernut %s\r\n";

    fprintf_P(stream, fmt_P, req->req_version / 10, req->req_version % 10, 
              status, title, NutVersionString());
}

/*!
 * \brief Send bottom lines of a standard HTML header.
 *
 * Sends Content-Type, Content-Lenght and Connection lines.
 *
 * \param stream    Stream of the socket connection, previously opened 
 *                  for  binary read and write.
 * \param mime_type Points to a string that specifies the content type. 
 *                  Examples are "text/html", "image/png", 
 *                  "image/gif", "video/mpeg" or "text/css".
 *                  A null pointer is ignored.
 * \param bytes     Content length of the data following this
 *                  header. Ignored, if negative.
 */
void NutHttpSendHeaderBot(FILE * stream, char *mime_type, long bytes)
{
    static prog_char typ_fmt_P[] = "Content-Type: %s\r\n";
    static prog_char len_fmt_P[] = "Content-Length: %ld\r\n";
    static prog_char ccl_str_P[] = "Connection: close\r\n\r\n";

    if (mime_type)
        fprintf_P(stream, typ_fmt_P, mime_type);
    if (bytes >= 0)
        fprintf_P(stream, len_fmt_P, bytes);
    fputs_P(ccl_str_P, stream);
}

/*!
 * \brief Send a HTTP error response.
 *
 * A canned error file is used.
 *
 * \param stream Stream of the socket connection, previously opened for 
 *               binary read and write.
 * \param req    Contains the HTTP request.
 * \param status Error code to be returned.
 */
void NutHttpSendError(FILE * stream, REQUEST * req, int status)
{
    static prog_char err_fmt_P[] = "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD><BODY>%d %s</BODY></HTML>";
    static prog_char auth_fmt_P[] = "WWW-Authenticate: Basic realm=\"%s\"";
    char *title;

    switch (status) {
    case 400:
        title = "Bad Request";
        break;
    case 401:
        title = "Unauthorized";
        break;
    case 404:
        title = "Not Found";
        break;
    case 500:
        title = "Internal Error";
        break;
    case 501:
        title = "Not Implemented";
        break;
    default:
        title = "Error";
        break;
    }

    NutHttpSendHeaderTop(stream, req, status, title);
    if (status == 401) {
        char *cp = 0;
        char *realm = req->req_url;

        if ((cp = strrchr(realm, '/')) != 0)
            *cp = 0;
        else
            realm = ".";
        fprintf_P(stream, auth_fmt_P, realm);
        if (cp)
            *cp = '/';
    }
    NutHttpSendHeaderBot(stream, "text/html", -1);
    fprintf_P(stream, err_fmt_P, status, title, status, title);
}

/*!
 * \brief Return the mime type description of a specified file name.
 *
 * The mime type returned is based on the file extension.
 *
 * \todo Function to register additional mime types. Currently only
 *       .txt, .html, .gif and .jpg are supported.
 *
 * \param name Name of the file.
 *
 * \return A pointer to a static string, containing the
 *         associated mime type description. If the extension
 *         is not registered, "text/plain; charset=iso-8859-1"
 *         is returned. If the filename is empty, then
 *         "text/hatml; charset=iso-8859-1" is returned.
 */
char *NutGetMimeType(char *name)
{
    size_t i;
    int fl;

    if (name == 0 || (fl = strlen(name)) == 0)
        return mimeTypes[1].type;
    for (i = 0; i < sizeof(mimeTypes) / sizeof(*mimeTypes); i++)
        if (strcasecmp
            (&(name[fl - strlen(mimeTypes[i].ext)]),
             mimeTypes[i].ext) == 0)
            return mimeTypes[i].type;
    return mimeTypes[0].type;
}

static void NutHttpProcessFileRequest(FILE * stream, REQUEST * req)
{
    int fd;
    int n;
    char *data;
    int size;
    long file_len;
    char *filename = NULL;

    /*
     * Validate authorization.
     */
    if (NutHttpAuthValidate(req)) {
        NutHttpSendError(stream, req, 401);
        return;
    }

    /*
     * Process CGI.
     */
    if (strncasecmp(req->req_url, "cgi-bin/", 8) == 0) {
        NutCgiProcessRequest(stream, req);
        return;
    }

    /*
     * Process file.
     */
    if (http_root) {
        filename =
            NutHeapAlloc(strlen(http_root) + strlen(req->req_url) + 1);
        strcpy(filename, http_root);
    } else {
        filename = NutHeapAlloc(strlen(req->req_url) + 6);
        strcpy(filename, "UROM:");
    }
    strcat(filename, req->req_url);

    fd = _open(filename, _O_BINARY | _O_RDONLY);
    NutHeapFree(filename);
    if (fd == -1) {
        u_char *index;
        u_short urll;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -