wsp_headers.c
来自「mms client」· C语言 代码 · 共 2,167 行 · 第 1/5 页
C
2,167 行
/* * wsp_headers.c - Implement WSP PDU headers * * References: * WSP specification version 1.1 * RFC 2068, Hypertext Transfer Protocol HTTP/1.1 * RFC 2616, Hypertext Transfer Protocol HTTP/1.1 * * For push headers, WSP specification, June 2000 conformance release * * This file has two parts. The first part decodes the request's headers * from WSP to HTTP. The second part encodes the response's headers from * HTTP to WSP. * * Note that push header encoding and decoding are divided two parts: * first decoding and encoding numeric values and then packing these values * into WSP format and unpacking them from WSP format. This module contains * only packing and unpacking parts. * * Richard Braakman */#include <string.h>#include <limits.h>#include <ctype.h>#include "gwlib/gwlib.h"#include "wsp.h"#include "wsp_headers.h"#include "wsp_strings.h"/* The value defined as Quote in 8.4.2.1 */#define WSP_QUOTE 127/* Largest value that will fit in a Short-integer encoding */#define MAX_SHORT_INTEGER 127/* Marker values used in the encoding */#define BASIC_AUTHENTICATION 128#define ABSOLUTE_TIME 128#define RELATIVE_TIME 129#define BYTE_RANGE 128#define SUFFIX_BYTE_RANGE 129/* Use this value for Expires headers if we can't parse the expiration * date. It's about one day after the start of the epoch. We don't * use the exact start of the epoch because some clients have trouble * with that. */#define LONG_AGO_VALUE 100000/* * get field value and return its type as predefined data types * There are three kinds of field encodings: * WSP_FIELD_VALUE_NUL_STRING: 0-terminated string * WSP_FIELD_VALUE_ENCODED: short integer, range 0-127 * WSP_FIELD_VALUE_DATA: octet string defined by length * The function will return one of those values, and modify the parse context * to make it easy to get the field data. * WSP_FIELD_VALUE_NUL_STRING: Leave parsing position at start of string * WSP_FIELD_VALUE_ENCODED: Put value in *well_known_value, leave * parsing position after field value. * WSP_FIELD_VALUE_DATA: Leave parsing position at start of data, and set * a parse limit at the end of data. */int field_value(ParseContext *context, int *well_known_value){ int val; unsigned long len; val = parse_get_char(context); if (val >= 0 && val < 31) { *well_known_value = -1; parse_limit(context, val); return WSP_FIELD_VALUE_DATA; } else if (val == 31) { *well_known_value = -1; len = parse_get_uintvar(context); parse_limit(context, len); return WSP_FIELD_VALUE_DATA; } else if (val > 127) { *well_known_value = val - 128; return WSP_FIELD_VALUE_ENCODED; } else if (val == WSP_QUOTE) { /* 127 */ *well_known_value = -1; /* We already consumed the Quote */ return WSP_FIELD_VALUE_NUL_STRING; } else { *well_known_value = -1; /* Un-parse the character we just read */ parse_skip(context, -1); return WSP_FIELD_VALUE_NUL_STRING; }}/* Skip over a field_value as defined above. */void skip_field_value(ParseContext *context){ int val; int ret; ret = field_value(context, &val); if (ret == WSP_FIELD_VALUE_DATA) { parse_skip_to_limit(context); parse_pop_limit(context); }}/* Multi-octet-integer is defined in 8.4.2.1 */long unpack_multi_octet_integer(ParseContext *context, long len){ long val = 0; if (len > (long) sizeof(val) || len < 0) return -1; while (len > 0) { val = val * 256 + parse_get_char(context); len--; } if (parse_error(context)) return -1; return val;}/* This function is similar to field_value, but it is used at various * places in the grammar where we expect either an Integer-value * or some kind of NUL-terminated text. * * Return values are just like field_value except that WSP_FIELD_VALUE_DATA * will not be returned. * * As a special case, we parse a 0-length Long-integer as an * WSP_FIELD_VALUE_NONE, so that we can distinguish between No-value * and an Integer-value of 0. (A real integer 0 would be encoded as * a Short-integer; the definition of Long-integer seems to allow * 0-length integers, but the definition of Multi-octet-integer does * not, so this is an unclear area of the specification.) */int secondary_field_value(ParseContext *context, long *result){ int val; long length; val = parse_get_char(context); if (val == 0) { *result = 0; return WSP_FIELD_VALUE_NONE; } else if (val > 0 && val < 31) { *result = unpack_multi_octet_integer(context, val); return WSP_FIELD_VALUE_ENCODED; } else if (val == 31) { length = parse_get_uintvar(context); *result = unpack_multi_octet_integer(context, length); return WSP_FIELD_VALUE_ENCODED; } else if (val > 127) { *result = val - 128; return WSP_FIELD_VALUE_ENCODED; } else if (val == WSP_QUOTE) { /* 127 */ *result = -1; return WSP_FIELD_VALUE_NUL_STRING; } else { *result = -1; /* Un-parse the character we just read */ parse_skip(context, -1); return WSP_FIELD_VALUE_NUL_STRING; }}/* Integer-value is defined in 8.4.2.3 */Octstr *unpack_integer_value(ParseContext *context){ Octstr *decoded; unsigned long value; int val; val = parse_get_char(context); if (val < 31) { value = unpack_multi_octet_integer(context, val); } else if (val > 127) { value = val - 128; } else { warning(0, "WSP headers: bad integer-value."); return NULL; } decoded = octstr_create(""); octstr_append_decimal(decoded, value); return decoded;}/* Q-value is defined in 8.4.2.3 */Octstr *convert_q_value(int q){ Octstr *result = NULL; /* When quality factor 0 and quality factors with one or two * decimal digits are encoded, they shall be multiplied by 100 * and incremented by one, so that they encode as a one-octet * value in range 1-100. */ if (q >= 1 && q <= 100) { q = q - 1; result = octstr_create("0."); octstr_append_char(result, (q / 10) + '0'); if (q % 10 > 0) octstr_append_char(result, (q % 10) + '0'); return result; } /* Three decimal quality factors shall be multiplied with 1000 * and incremented by 100. */ if (q > 100 && q <= 1000) { q = q - 100; result = octstr_create("0."); octstr_append_char(result, (q / 100) + '0'); if (q % 100 > 0) octstr_append_char(result, (q / 10 % 10) + '0'); if (q % 10 > 0) octstr_append_char(result, (q % 10) + '0'); return result; } return NULL;}/* Q-value is defined in 8.4.2.3 */Octstr *unpack_q_value(ParseContext *context){ int c, c2; c = parse_get_char(context); if (c < 0) return NULL; if (c & 0x80) { c2 = parse_get_char(context); if (c2 < 0 || (c2 & 0x80)) return NULL; c = ((c & 0x7f) << 8) + c2; } return convert_q_value(c);}/* Version-value is defined in 8.4.2.3 */Octstr *unpack_version_value(long value){ Octstr *result; int major, minor; major = ((value >> 4) & 0x7); minor = (value & 0xf); result = octstr_create(""); octstr_append_char(result, major + '0'); if (minor != 15) { octstr_append_char(result, '.'); octstr_append_decimal(result, minor); } return result;}/* Called with the parse limit set to the end of the parameter data, * and decoded containing the unpacked header line so far. * Parameter is defined in 8.4.2.4. */int unpack_parameter(ParseContext *context, Octstr *decoded){ Octstr *parm = NULL; Octstr *value = NULL; int ret; long type; long val; ret = secondary_field_value(context, &type); if (parse_error(context) || ret == WSP_FIELD_VALUE_NONE) { warning(0, "bad parameter"); goto error; } if (ret == WSP_FIELD_VALUE_ENCODED) { /* Typed-parameter */ parm = wsp_parameter_to_string(type); if (!parm) warning(0, "Unknown parameter %02lx.", type); } else if (ret == WSP_FIELD_VALUE_NUL_STRING) { /* Untyped-parameter */ parm = parse_get_nul_string(context); if (!parm) warning(0, "Format error in parameter."); type = -1; /* We treat Untyped-value as a special type. Its format * Integer-value | Text-value is pretty similar to most * typed formats. */ } else { panic(0, "Unknown secondary field value type %d.", ret); } if (type == 0x00) /* q */ value = unpack_q_value(context); else { ret = secondary_field_value(context, &val); if (parse_error(context)) { warning(0, "bad parameter value"); goto error; } if (ret == WSP_FIELD_VALUE_ENCODED) { switch (type) { case -1: /* untyped: Integer-value */ case 3: /* type: Integer-value */ case 8: /* padding: Short-integer */ value = octstr_create(""); octstr_append_decimal(value, val); break; case 0: /* q, already handled above */ gw_assert(0); break; case 1: /* charset: Well-known-charset */ value = wsp_charset_to_string(val); if (!value) warning(0, "Unknown charset %04lx.", val); break; case 2: /* level: Version-value */ value = unpack_version_value(val); break; case 5: /* name: Text-string */ case 6: /* filename: Text-string */ warning(0, "Text-string parameter with integer encoding"); break; case 7: /* differences: Field-name */ value = wsp_header_to_string(val); if (!value) warning(0, "Unknown differences header %02lx.", val); break; default: warning(0, "Unknown parameter encoding %02lx.", type); break; } } else if (ret == WSP_FIELD_VALUE_NONE) { value = octstr_create(""); } else { gw_assert(ret == WSP_FIELD_VALUE_NUL_STRING); /* Text-value = No-value | Token-text | Quoted-string */ value = parse_get_nul_string(context); if (!value) warning(0, "Format error in parameter value."); else { if (octstr_get_char(value, 0) == '"') { /* Quoted-string */ octstr_append_char(value, '"'); } } } } if (!parm || !value) { warning(0, "Skipping parameters"); goto error; } octstr_append(decoded, octstr_imm("; ")); octstr_append(decoded, parm); if (octstr_len(value) > 0) { octstr_append_char(decoded, '='); octstr_append(decoded, value); } octstr_destroy(parm); octstr_destroy(value); return 0;error: parse_skip_to_limit(context); octstr_destroy(parm); octstr_destroy(value); parse_set_error(context); return -1;}void unpack_all_parameters(ParseContext *context, Octstr *decoded){ int ret = 0; while (ret >= 0 && !parse_error(context) && parse_octets_left(context) > 0) { ret = unpack_parameter(context, decoded); }}/* Unpack parameters in the format used by credentials and challenge, * which differs from the format used by all other HTTP headers. */void unpack_broken_parameters(ParseContext *context, Octstr *decoded){ int ret = 0; int first = 1; long pos; while (ret >= 0 && !parse_error(context) && parse_octets_left(context) > 0) { pos = octstr_len(decoded); ret = unpack_parameter(context, decoded); if (ret >= 0) { if (first) { /* Zap ';' */ octstr_delete(decoded, pos, 1); first = 0; } else { /* Replace ';' with ',' */ octstr_set_char(decoded, pos, first ? ' ' : ','); } } }}void unpack_optional_q_value(ParseContext *context, Octstr *decoded){ if (parse_octets_left(context) > 0) { Octstr *qval = unpack_q_value(context); if (qval) { octstr_append(decoded, octstr_imm("; q=")); octstr_append(decoded, qval); octstr_destroy(qval); } else warning(0, "Bad q-value"); }}/* Date-value is defined in 8.4.2.3. */Octstr *unpack_date_value(ParseContext *context)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?