📄 sflhttp.c
字号:
/* ----------------------------------------------------------------<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 + -