📄 wsp_headers.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * 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. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 KANNEL GROUP OR ITS 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * 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. * * Some functions are declared non-static to provide them for external use, * ie. the MMS encapsulation encoding and decoding routines implemented in * other files. * * Richard Braakman * Stipe Tolj <tolj@wapme-systems.de> */#include <string.h>#include <limits.h>#include <ctype.h>#include "gwlib/gwlib.h"#include "wsp.h"#include "wsp_headers.h"#include "wsp_strings.h"/* * 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 wsp_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 wsp_skip_field_value(ParseContext *context){ int val; int ret; ret = wsp_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 */static 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 wsp_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 *wsp_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 */static 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 */static 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. Encoding-Version uses coding * defined in this chapter, see 8.4.2.70. */Octstr *wsp_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;}static Octstr *unpack_encoding_version(ParseContext *context){ int ch; ch = parse_get_char(context); if (ch < 128) { warning(0, "WSP: bad Encoding-Version value"); return NULL; } return wsp_unpack_version_value(((long) ch) - 128);}/* 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. */static int unpack_parameter(ParseContext *context, Octstr *decoded){ Octstr *parm = NULL; Octstr *value = NULL; int ret; long type; long val; ret = wsp_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 = wsp_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 = wsp_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, '"'); } else { /* DAVI! */ octstr_insert(value, octstr_imm("\""), 0); octstr_append_char(value, '"'); } } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -