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

📄 sflhttp.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  ----------------------------------------------------------------<Prolog>-
    Name:       sflhttp.c
    Title:      HTTP and CGI Support functions
    Package:    Standard Function Library (SFL)

    Written:    1996/05/31  iMatix SFL project team <sfl@imatix.com>
    Revised:    2000/01/19

    Copyright:  Copyright (c) 1996-2000 iMatix Corporation
    License:    This is free software; you can redistribute it and/or modify
                it under the terms of the SFL License Agreement as provided
                in the file LICENSE.TXT.  This software is distributed in
                the hope that it will be useful, but without any warranty.
 ------------------------------------------------------------------</Prolog>-*/

#include "prelude.h"                    /*  Universal header file            */
#include "sflstr.h"                     /*  String functions                 */
#include "sflsymb.h"                    /*  Symbol functions                 */
#include "sflconv.h"                    /*  Convertion functions             */
#include "sfllist.h"                    /*  Linked-list functions            */
#include "sflmem.h"                     /*  Memory functions                 */
#include "sflfind.h"                    /*  Find text functions              */
#include "sflfile.h"                    /*  Files functions                  */
#include "sfldate.h"                    /*  Date/time functions              */
#include "sflprint.h"                   /*  snprintf functions               */
#include "sflhttp.h"                    /*  Prototypes for functions         */

/*  Constants -------------------------------------------------------------- */

/*  This is the maximum size of a stream of HTTP query data coming from a
 *  file.  Used by cgi_parse_file_vars ().
 */

#define CGI_QUERY_FILE_MAX      65535U
#define MULTI_BUFFER_SIZE       16384
#define REST_BUFFER_SIZE        20000


/*- Local functions ---------------------------------------------------------*/

static size_t http_escape_char        (char code, char *result, size_t outmax,
                                       Bool hex_spaces);
static int    decode_hex              (const char **input, size_t outmax);
static void   save_multipart_header   (SYMTAB *table, SYMTAB *header,
                                       char *data, char *tmp_name,
                                       const char *local_format);
static void   multipart_decode_header (char *header, SYMTAB *table);
static DESCR *http_multipart2url      (const SYMTAB *symtab);


/*  ---------------------------------------------------------------------[<]-
    Function: http_escape

    Synopsis: Performs HTTP escaping on a string.  This works as follows:
    all characters except alphanumerics and spaces are converted into the
    3-byte sequence "%xx" where xx is the character's hexadecimal value;
    spaces are replaced by '+'.  Line breaks are stored as "%0D%0A", where
    a 'line break' is any one of: "\n", "\r", "\n\r", or "\r\n".  If the
    result buffer is NULL, calculates the required size, allocates a block
    of memory, and returns that.  Otherwise, returns result, which must be
    large enough for the escaping operation (see http_escape_size()).
    When you all http_escape() with a null target block, you must free the
    returned block using mem_free().  Returns NULL if it could not allocate
    a target block as required.  If outmax is non-zero then no more than
    outmax characters (including the NULL terminator) are stored.
    ---------------------------------------------------------------------[>]-*/

char *
http_escape (
    const char *string,
    char *result,
    size_t outmax)
{
    char
        *target;                        /*  Where we store the result        */
    size_t
        length;                         /*  of escaped character             */

    ASSERT (string);
    if (outmax == 0)                    /*  If no fixed length, get total len*/
        outmax = http_escape_size (string);

    if (result == NULL)
        if ((result = mem_alloc (outmax)) == NULL)
            return (NULL);              /*  Could not allocate a block       */

    if (outmax > 1)
        outmax -= 1;                    /*  Leave space for NULL terminator  */
    else
    if (outmax == 1)                    /*  Only room for terminator         */
      {
        *result = '\0';
        return (result);
      }
    target = result;
    while (*string)
      {
        length = http_escape_char (*string, target, outmax, FALSE);
        if (length == 0)
            break;
        
        target += length;
        outmax -= length;
        if (*string == '\n' || *string == '\r')
          {
            if ((string [1] == '\n' || string [1] == '\r')
            &&  (string [1] != *string))
                string++;
          }
        string++;
      }
    *target = '\0';                     /*  Terminate target string          */
    return (result);
}


/*---------------------------------------------------------------------------
 *  http_escape_char -- local
 *
 *  Performs HTTP escaping on a character.
 *---------------------------------------------------------------------------*/

static size_t
http_escape_char (
    char   code,
    char  *result,
    size_t outmax,
    Bool   hex_spaces)
{
    static char
        hex_char [] = "0123456789ABCDEF";

    if (isalnum (code))                 /*  Don't escape letters or digits   */
      {
        if (outmax < 1)
            return (0);
        *result = code;
        return 1;
      }
    else
    if (code == ' ' && !hex_spaces)     /*  Spaces are replaced by '+'       */
      {
        if (outmax < 1)
            return (0);
        *result = '+';
        return 1;
      }
    if (code == '\n' || code == '\r')
      {
        if (outmax < 6)
            return 0;
        *result++ = '%';                /*  New line becomes %0A%0D          */
        *result++ = '0';
        *result++ = 'A';
        *result++ = '%';
        *result++ = '0';
        *result++ = 'D';
        return (6);
      }
    else
      {
        if (outmax < 3)
            return 0;
        *result++ = '%';                /*  Some other escaped character     */
        *result++ = hex_char [(byte) code >> 4];
        *result++ = hex_char [(byte) code & 15];
        return (3);
      }
}


/*  ---------------------------------------------------------------------[<]-
    Function: http_escape_size

    Synopsis: Returns the size of a string after HTTP escaping.  See the
    http_escape() function for details of the escaping algorithm.  Includes
    the null terminator in the returned size.
    ---------------------------------------------------------------------[>]-*/

size_t
http_escape_size (
    const char *string)
{
    size_t
        result_size = 1;                /*  Allow for null terminator        */

    ASSERT (string);
    while (*string)
      {
        if (isalnum (*string))          /*  Don't escape letters or digits   */
            result_size++;
        else
        if (*string == '\n' || *string == '\r')
          {
            if ((string [1] == '\n' || string [1] == '\r')
            &&  (string [1] != *string))
                string++;
            result_size += 6;           /*  Line ending becomes %0D%0A       */
          }
        else
            result_size += 3;           /*  Some other escaped character     */

        string++;
      }
    return (result_size);
}


/*  -------------------------------------------------------------------------
    Function: decode_hex

    Synopsis: Decodes a hexadecimal string.  Stops after outmax characters
    or when an invalid hex character is reached.  Sets the input pointer
    to the first unprocessed character.  Returns the result.
    -------------------------------------------------------------------------*/

int
decode_hex (
    const char   **input,
    size_t         outmax)
{
    static char
        hex_to_bin [128] = {
           -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,    /*            */
           -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,    /*            */
           -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,    /*            */
            0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,    /*   0..9     */
           -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,    /*   A..F     */
           -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,    /*            */
           -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,    /*   a..f     */
           -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 };  /*            */
    int
        nextch;
    size_t
        index,
        result;

    ASSERT (input);
    ASSERT (*input);

    index  = 0;
    result = 0;
    while (outmax == 0 || index < outmax)
      {
        nextch = (*input) [index] & 127;
        if (nextch && hex_to_bin [nextch] != -1)
          {
            result = result * 16 + hex_to_bin [nextch];
            index++;
          }
        else
            break;
      }
    (*input) += index;
    return (result);
}


/*  ---------------------------------------------------------------------[<]-
    Function: http_escape_hex

    Synopsis: Works as http_escape(), but converts spaces to %20 instead of
    '+'.  This encoding is standard for filenames and URL requests.
    ---------------------------------------------------------------------[>]-*/

char *
http_escape_hex (
    const char *string,
    char  *result,
    size_t outmax)
{
    char
        *target;                        /*  Where we store the result        */
    size_t
        length;                         /*  of escaped character             */

    ASSERT (string);
    if (outmax == 0)                    /*  If no fixed length, get total len*/
        outmax = http_escape_size (string);

    if (result == NULL)
        if ((result = mem_alloc (outmax)) == NULL)
            return (NULL);              /*  Could not allocate a block       */

    if (outmax > 1)
        outmax -= 1;                    /*  Leave space for NULL terminator  */
    else
    if (outmax == 1)                    /*  Only room for terminator         */
      {
        *result = '\0';
        return (result);
      }
    target = result;
    while (*string)
      {
        length = http_escape_char (*string, target, outmax, TRUE);
        if (length == 0)
            break;
        
        target += length;
        outmax -= length;
        if (*string == '\n' || *string == '\r')
          {
            if ((string [1] == '\n' || string [1] == '\r')
            &&  (string [1] != *string))
                string++;
          }
        string++;
      }
    *target = '\0';                     /*  Terminate target string          */
    return (result);
}


/*  ---------------------------------------------------------------------[<]-
    Function: http_unescape

    Synopsis: Removes HTTP escaping from a string.  See http_escape() for
    details of the escaping algorithm.  If the result string is NULL,
    modifies the source string in place, else fills-in the result string.
    Returns the resulting string.  End-of-line sequences (%0A%0D) are
    stored as a single new-line character, i.e. carriage-returns (%0D) are
    not stored.
    ---------------------------------------------------------------------[>]-*/

char *
http_unescape (
    char *string,
    char *result)
{
    char
        *target;                        /*  Where we store the result        */

    ASSERT (string);
    if (!result)                        /*  If result string is null,        */
        result = string;                /*    modify in place                */
    target = result;

    while (*string)
      {
        if (*string == '%'              /*  Unescape %xx sequence            */
        &&   string [1] && string [2])
          {
            string++;
            *target = decode_hex ((const char **) &string, 2);
            if (*target != '\r')
                target++;               /*  We do not store CRs              */
          }
        else
          {
            if (*string == '+')         /*  Spaces are escaped as '+'        */
                *target++ = ' ';
            else
                *target++ = *string;    /*  Otherwise just copy              */

            string++;
          }
      }
    *target = '\0';                     /*  Terminate target string          */
    return (result);

⌨️ 快捷键说明

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