forked from osmocom/wireshark
Pass an HTTP message type to all HTTP subdissectors.
This gets complicated, because those subdissectors might be called by other dissectors as well. We need a better way of passing that sort of out-of-bound information. Pull some routines used for processing Content-Type parameters into common code; we can't guarantee that the media parameters passed in would be writable (passing it as *the* data hid that; passing a structure with that *and* the HTTP message type revealed it), so don't convert it to lower-case in place. Use that information, if available, to determine whether an IPP message is a requet or a response. Change-Id: I4bccc9f05cd0b14ad445be7ab37b3d884d841325 Reviewed-on: https://code.wireshark.org/review/17216 Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
parent
efdcb25360
commit
5825f59ddc
|
@ -127,6 +127,7 @@ set(LIBWIRESHARK_FILES
|
|||
in_cksum.c
|
||||
ipproto.c
|
||||
ipv4.c
|
||||
media_params.c
|
||||
next_tvb.c
|
||||
oids.c
|
||||
osi-utils.c
|
||||
|
|
|
@ -89,6 +89,7 @@ LIBWIRESHARK_SRC = \
|
|||
in_cksum.c \
|
||||
ipproto.c \
|
||||
ipv4.c \
|
||||
media_params.c \
|
||||
next_tvb.c \
|
||||
oids.c \
|
||||
osi-utils.c \
|
||||
|
@ -237,6 +238,7 @@ LIBWIRESHARK_INCLUDES = \
|
|||
ipv6.h \
|
||||
lapd_sapi.h \
|
||||
llcsaps.h \
|
||||
media_params.h \
|
||||
next_tvb.h \
|
||||
nlpid.h \
|
||||
oids.h \
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <epan/packet.h>
|
||||
#include <wsutil/str_util.h>
|
||||
|
||||
#include "packet-http.h"
|
||||
|
||||
void proto_register_http_urlencoded(void);
|
||||
void proto_reg_handoff_http_urlencoded(void);
|
||||
|
||||
|
@ -123,18 +125,27 @@ dissect_form_urlencoded(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi
|
|||
proto_item *ti;
|
||||
gint offset = 0, next_offset;
|
||||
const char *data_name;
|
||||
http_message_info_t *message_info;
|
||||
|
||||
data_name = pinfo->match_string;
|
||||
if (! (data_name && data_name[0])) {
|
||||
/*
|
||||
* No information from "match_string"
|
||||
*/
|
||||
data_name = (char *)data;
|
||||
if (! (data_name && data_name[0])) {
|
||||
message_info = (http_message_info_t *)data;
|
||||
if (message_info == NULL) {
|
||||
/*
|
||||
* No information from dissector data
|
||||
*/
|
||||
data_name = NULL;
|
||||
} else {
|
||||
data_name = message_info->media_str;
|
||||
if (! (data_name && data_name[0])) {
|
||||
/*
|
||||
* No information from dissector data
|
||||
*/
|
||||
data_name = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,14 +49,6 @@
|
|||
#include "packet-tcp.h"
|
||||
#include "packet-ssl.h"
|
||||
|
||||
typedef enum _http_type {
|
||||
HTTP_REQUEST,
|
||||
HTTP_RESPONSE,
|
||||
HTTP_NOTIFICATION,
|
||||
HTTP_OTHERS
|
||||
} http_type_t;
|
||||
|
||||
|
||||
void proto_register_http(void);
|
||||
void proto_reg_handoff_http(void);
|
||||
void proto_register_message_http(void);
|
||||
|
@ -764,6 +756,7 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
int reported_length;
|
||||
guint16 word;
|
||||
gboolean leading_crlf = FALSE;
|
||||
http_message_info_t message_info;
|
||||
|
||||
reported_length = tvb_reported_length_remaining(tvb, offset);
|
||||
if (reported_length < 1) {
|
||||
|
@ -1428,13 +1421,13 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
if (headers.content_encoding != NULL &&
|
||||
g_ascii_strcasecmp(headers.content_encoding, "identity") != 0) {
|
||||
/*
|
||||
* We currently can't handle, for example, "compress";
|
||||
* We currently don't handle, for example, "compress";
|
||||
* just handle them as data for now.
|
||||
*
|
||||
* After July 7, 2004 the LZW patent expires, so support
|
||||
* might be added then. However, I don't think that
|
||||
* anybody ever really implemented "compress", due to
|
||||
* the aforementioned patent.
|
||||
* After July 7, 2004 the LZW patent expired, so
|
||||
* support could be added. However, I don't think
|
||||
* that anybody ever really implemented "compress",
|
||||
* due to the aforementioned patent.
|
||||
*/
|
||||
tvbuff_t *uncomp_tvb = NULL;
|
||||
proto_item *e_ti = NULL;
|
||||
|
@ -1559,11 +1552,13 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
pinfo->match_uint);
|
||||
}
|
||||
|
||||
message_info.type = http_type;
|
||||
message_info.media_str = media_str;
|
||||
if (handle != NULL) {
|
||||
/*
|
||||
* We have a subdissector - call it.
|
||||
*/
|
||||
dissected = call_dissector_only(handle, next_tvb, pinfo, tree, media_str);
|
||||
dissected = call_dissector_only(handle, next_tvb, pinfo, tree, &message_info);
|
||||
if (!dissected)
|
||||
expert_add_info(pinfo, http_tree, &ei_http_subdissector_failed);
|
||||
}
|
||||
|
@ -1591,7 +1586,7 @@ dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
* Calling the default media handle if there is a content-type that
|
||||
* wasn't handled above.
|
||||
*/
|
||||
call_dissector_with_data(media_handle, next_tvb, pinfo, tree, media_str);
|
||||
call_dissector_with_data(media_handle, next_tvb, pinfo, tree, &message_info);
|
||||
} else {
|
||||
/* Call the default data dissector */
|
||||
call_data_dissector(next_tvb, pinfo, http_tree);
|
||||
|
|
|
@ -85,4 +85,17 @@ typedef struct _http_conv_t {
|
|||
http_req_res_t *req_res_tail;
|
||||
} http_conv_t;
|
||||
|
||||
typedef enum _http_type {
|
||||
HTTP_REQUEST,
|
||||
HTTP_RESPONSE,
|
||||
HTTP_NOTIFICATION,
|
||||
HTTP_OTHERS
|
||||
} http_type_t;
|
||||
|
||||
/** Passed to dissectors called by the HTTP dissector. */
|
||||
typedef struct _http_message_info_t {
|
||||
http_type_t type; /* Message type; may be HTTP_OTHERS if not called by HTTP */
|
||||
const char *media_str; /* Content-Type parameters */
|
||||
} http_message_info_t;
|
||||
|
||||
#endif /* __PACKET_HTTP_H__ */
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <wsutil/str_util.h>
|
||||
|
||||
#include "packet-ber.h"
|
||||
#include "packet-http.h"
|
||||
#include "packet-imf.h"
|
||||
#include "packet-ess.h"
|
||||
#include "packet-p1.h"
|
||||
|
@ -813,6 +814,8 @@ dissect_imf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
|||
/* now dissect the MIME based upon the content type */
|
||||
|
||||
if(content_type_str && media_type_dissector_table) {
|
||||
http_message_info_t message_info;
|
||||
|
||||
col_set_fence(pinfo->cinfo, COL_INFO);
|
||||
|
||||
if(content_encoding_str && !g_ascii_strncasecmp(content_encoding_str, "base64", 6)) {
|
||||
|
@ -823,7 +826,9 @@ dissect_imf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
|||
next_tvb = tvb_new_subset_remaining(tvb, end_offset);
|
||||
}
|
||||
|
||||
dissector_try_string(media_type_dissector_table, content_type_str, next_tvb, pinfo, tree, (void*)parameters);
|
||||
message_info.type = HTTP_OTHERS;
|
||||
message_info.media_str = parameters;
|
||||
dissector_try_string(media_type_dissector_table, content_type_str, next_tvb, pinfo, tree, (void*)&message_info);
|
||||
} else {
|
||||
|
||||
/* just show the lines or highlight the rest of the buffer as message text */
|
||||
|
|
|
@ -189,16 +189,34 @@ static int add_value_head(const gchar *tag_desc, proto_tree *tree,
|
|||
tvbuff_t *tvb, int offset, int name_length, int value_length, char **name_val);
|
||||
|
||||
static int
|
||||
dissect_ipp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
||||
dissect_ipp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
|
||||
{
|
||||
proto_tree *ipp_tree;
|
||||
proto_item *ti;
|
||||
int offset = 0;
|
||||
gboolean is_request = (pinfo->destport == pinfo->match_uint);
|
||||
/* XXX - should this be based on the HTTP header? */
|
||||
http_message_info_t *message_info = (http_message_info_t *)data;
|
||||
gboolean is_request;
|
||||
guint16 status_code;
|
||||
const gchar *status_type;
|
||||
|
||||
if (message_info != NULL) {
|
||||
switch (message_info->type) {
|
||||
|
||||
case HTTP_REQUEST:
|
||||
is_request = TRUE;
|
||||
break;
|
||||
|
||||
case HTTP_RESPONSE:
|
||||
is_request = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
is_request = (pinfo->destport == pinfo->match_uint);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
is_request = (pinfo->destport == pinfo->match_uint);
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPP");
|
||||
if (is_request)
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "IPP request");
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
*
|
||||
* National variants
|
||||
* French ISUP Specification: SPIROU 1998 - 002-005 edition 1 ( Info found here http://www.icg-corp.com/docs/ISUP.pdf ).
|
||||
* See also http://www.fftelecoms.org/sites/default/files/contenus_lies/fft_interco_ip_-_sip-i_interface_specification_v1_0.pdf
|
||||
* Israeli ISUP Specification: excertp (for BCM message) found in https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4231 .
|
||||
* Russian national ISUP-R 2000: RD 45.217-2001 book 4
|
||||
* Japan ISUP http://www.ttc.or.jp/jp/document_list/sum/sum_JT-Q763v21.1.pdf
|
||||
|
@ -54,12 +55,14 @@
|
|||
#include <epan/sctpppids.h>
|
||||
#include <epan/reassemble.h>
|
||||
#include <epan/to_str.h>
|
||||
#include <epan/media_params.h>
|
||||
#include <wsutil/str_util.h>
|
||||
#include "packet-q931.h"
|
||||
#include "packet-isup.h"
|
||||
#include "packet-e164.h"
|
||||
#include "packet-charging_ase.h"
|
||||
#include "packet-mtp3.h"
|
||||
#include "packet-http.h"
|
||||
|
||||
void proto_register_isup(void);
|
||||
void proto_reg_handoff_isup(void);
|
||||
|
@ -10419,31 +10422,47 @@ dissect_application_isup(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo
|
|||
proto_tree *isup_tree = NULL;
|
||||
tvbuff_t *message_tvb;
|
||||
guint8 message_type;
|
||||
gchar *content_type_parameter_str;
|
||||
const char *version, *base;
|
||||
int len_version, len_base;
|
||||
guint8 itu_isup_variant = ISUP_ITU_STANDARD_VARIANT; /* Default */
|
||||
|
||||
if (data) {
|
||||
content_type_parameter_str = ascii_strdown_inplace((gchar *)data);
|
||||
if (strstr(content_type_parameter_str, "ansi")) {
|
||||
isup_standard = ANSI_STANDARD;
|
||||
col_append_str(pinfo->cinfo, COL_PROTOCOL, "/ISUP(ANSI)");
|
||||
message_type = tvb_get_guint8(tvb, 0);
|
||||
/* application/ISUP has no CIC */
|
||||
col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ",
|
||||
"ISUP:%s",
|
||||
val_to_str_ext_const(message_type, &ansi_isup_message_type_value_acro_ext, "reserved"));
|
||||
if (tree) {
|
||||
ti = proto_tree_add_item(tree, proto_isup, tvb, 0, -1, ENC_NA);
|
||||
isup_tree = proto_item_add_subtree(ti, ett_isup);
|
||||
}
|
||||
http_message_info_t *message_info = (http_message_info_t *)data;
|
||||
if (message_info->media_str) {
|
||||
version = find_parameter(message_info->media_str, "version=", &len_version);
|
||||
base = find_parameter(message_info->media_str, "base=", &len_base);
|
||||
if ((version && len_version >= 4 && g_ascii_strncasecmp(version, "ansi", 4) == 0) ||
|
||||
(base && len_base >= 4 && g_ascii_strncasecmp(base, "ansi", 4) == 0)) {
|
||||
/*
|
||||
* "version" or "base" parameter begins with "ansi", so it's ANSI.
|
||||
*/
|
||||
isup_standard = ANSI_STANDARD;
|
||||
col_append_str(pinfo->cinfo, COL_PROTOCOL, "/ISUP(ANSI)");
|
||||
message_type = tvb_get_guint8(tvb, 0);
|
||||
/* application/ISUP has no CIC */
|
||||
col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ",
|
||||
"ISUP:%s",
|
||||
val_to_str_ext_const(message_type, &ansi_isup_message_type_value_acro_ext, "reserved"));
|
||||
if (tree) {
|
||||
ti = proto_tree_add_item(tree, proto_isup, tvb, 0, -1, ENC_NA);
|
||||
isup_tree = proto_item_add_subtree(ti, ett_isup);
|
||||
}
|
||||
|
||||
message_tvb = tvb_new_subset_remaining(tvb, 0);
|
||||
dissect_ansi_isup_message(message_tvb, pinfo, isup_tree, ISUP_ITU_STANDARD_VARIANT, 0);
|
||||
return tvb_reported_length(tvb);
|
||||
} else if (strstr(content_type_parameter_str, "spirou")) {
|
||||
isup_standard = ITU_STANDARD;
|
||||
itu_isup_variant = ISUP_FRENCH_VARIANT;
|
||||
message_tvb = tvb_new_subset_remaining(tvb, 0);
|
||||
dissect_ansi_isup_message(message_tvb, pinfo, isup_tree, ISUP_ITU_STANDARD_VARIANT, 0);
|
||||
return tvb_reported_length(tvb);
|
||||
} else if ((version && g_ascii_strncasecmp(version, "spirou", len_version) == 0) ||
|
||||
(base && g_ascii_strncasecmp(base, "spirou", len_base) == 0)) {
|
||||
/*
|
||||
* "version" or "base" version is "spirou", so it's SPIROU.
|
||||
*/
|
||||
isup_standard = ITU_STANDARD;
|
||||
itu_isup_variant = ISUP_FRENCH_VARIANT;
|
||||
} else {
|
||||
isup_standard = ITU_STANDARD;
|
||||
}
|
||||
} else {
|
||||
/* default to ITU */
|
||||
isup_standard = ITU_STANDARD;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include <wiretap/wtap.h>
|
||||
|
||||
#include "packet-http.h"
|
||||
|
||||
void proto_register_json(void);
|
||||
void proto_reg_handoff_json(void);
|
||||
static char *json_string_unescape(tvbparse_elem_t *tok);
|
||||
|
@ -116,6 +118,7 @@ dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
|
|||
json_parser_data_t parser_data;
|
||||
tvbparse_t *tt;
|
||||
|
||||
http_message_info_t *message_info;
|
||||
const char *data_name;
|
||||
int offset;
|
||||
|
||||
|
@ -138,12 +141,20 @@ dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
|
|||
/*
|
||||
* No information from "match_string"
|
||||
*/
|
||||
data_name = (char *)data;
|
||||
if (! (data_name && data_name[0])) {
|
||||
message_info = (http_message_info_t *)data;
|
||||
if (message_info == NULL) {
|
||||
/*
|
||||
* No information from dissector data
|
||||
*/
|
||||
data_name = NULL;
|
||||
} else {
|
||||
data_name = message_info->media_str;
|
||||
if (! (data_name && data_name[0])) {
|
||||
/*
|
||||
* No information from dissector data
|
||||
*/
|
||||
data_name = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <wsutil/str_util.h>
|
||||
|
||||
#include "packet-jxta.h"
|
||||
#include "packet-http.h"
|
||||
|
||||
void proto_register_jxta(void);
|
||||
void proto_reg_handoff_jxta(void);
|
||||
|
@ -2052,11 +2053,11 @@ static int dissect_media( const gchar* fullmediatype, tvbuff_t * tvb, packet_inf
|
|||
gchar *mediatype = wmem_strdup(wmem_packet_scope(), fullmediatype);
|
||||
gchar *parms_at = strchr(mediatype, ';');
|
||||
const char *save_match_string = pinfo->match_string;
|
||||
char *media_str = NULL;
|
||||
http_message_info_t message_info = { HTTP_OTHERS, NULL };
|
||||
|
||||
/* Based upon what is done in packet-media.c we set up type and params */
|
||||
if (NULL != parms_at) {
|
||||
media_str = wmem_strdup( wmem_packet_scope(), parms_at + 1 );
|
||||
message_info.media_str = wmem_strdup( wmem_packet_scope(), parms_at + 1 );
|
||||
*parms_at = '\0';
|
||||
}
|
||||
|
||||
|
@ -2086,7 +2087,7 @@ static int dissect_media( const gchar* fullmediatype, tvbuff_t * tvb, packet_inf
|
|||
}
|
||||
}
|
||||
} else {
|
||||
dissected = dissector_try_string(media_type_dissector_table, mediatype, tvb, pinfo, tree, media_str) ? tvb_captured_length(tvb) : 0;
|
||||
dissected = dissector_try_string(media_type_dissector_table, mediatype, tvb, pinfo, tree, &message_info) ? tvb_captured_length(tvb) : 0;
|
||||
|
||||
if( dissected != (int) tvb_captured_length(tvb) ) {
|
||||
/* g_message( "%s : %d expected, %d dissected", mediatype, tvb_captured_length(tvb), dissected ); */
|
||||
|
@ -2094,7 +2095,7 @@ static int dissect_media( const gchar* fullmediatype, tvbuff_t * tvb, packet_inf
|
|||
}
|
||||
|
||||
if (0 == dissected) {
|
||||
dissected = call_dissector_with_data(media_handle, tvb, pinfo, tree, media_str);
|
||||
dissected = call_dissector_with_data(media_handle, tvb, pinfo, tree, &message_info);
|
||||
}
|
||||
|
||||
pinfo->match_string = save_match_string;
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
#include <wsutil/str_util.h>
|
||||
|
||||
#include "packet-http.h"
|
||||
|
||||
void proto_register_media(void);
|
||||
|
||||
/* proto_media cannot be static because it's referenced in the
|
||||
|
@ -48,6 +50,7 @@ dissect_media(tvbuff_t *tvb, packet_info *pinfo , proto_tree *tree, void* data)
|
|||
int bytes;
|
||||
proto_item *ti;
|
||||
proto_tree *media_tree = 0;
|
||||
http_message_info_t *message_info = (http_message_info_t *)data;
|
||||
heur_dtbl_entry_t *hdtbl_entry;
|
||||
|
||||
if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &hdtbl_entry, data)) {
|
||||
|
@ -63,11 +66,12 @@ dissect_media(tvbuff_t *tvb, packet_info *pinfo , proto_tree *tree, void* data)
|
|||
ti = proto_tree_add_item(tree, proto_media, tvb, 0, -1, ENC_NA);
|
||||
media_tree = proto_item_add_subtree(ti, ett_media);
|
||||
|
||||
if (data) {
|
||||
if (message_info != NULL && message_info->media_str != NULL) {
|
||||
/* The media type has parameters */
|
||||
|
||||
proto_tree_add_bytes_format_value(media_tree, hf_media_type, tvb, 0, bytes,
|
||||
NULL, "%s; %s (%d byte%s)",
|
||||
pinfo->match_string, (char *)data,
|
||||
pinfo->match_string, message_info->media_str,
|
||||
bytes, plurality(bytes, "", "s"));
|
||||
} else {
|
||||
/* The media type has no parameters */
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <wsutil/str_util.h>
|
||||
|
||||
#include "packet-msrp.h"
|
||||
#include "packet-http.h"
|
||||
|
||||
void proto_register_msrp(void);
|
||||
void proto_reg_handoff_msrp(void);
|
||||
|
@ -471,7 +472,7 @@ dissect_msrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
|
|||
int found_match = 0;
|
||||
gint content_type_len, content_type_parameter_str_len;
|
||||
gchar *media_type_str_lower_case = NULL;
|
||||
char *content_type_parameter_str = NULL;
|
||||
http_message_info_t message_info = { HTTP_OTHERS, NULL };
|
||||
tvbuff_t *next_tvb;
|
||||
gint parameter_offset;
|
||||
gint semi_colon_offset;
|
||||
|
@ -655,7 +656,7 @@ dissect_msrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
|
|||
parameter_offset++;
|
||||
content_type_len = semi_colon_offset - value_offset;
|
||||
content_type_parameter_str_len = line_end_offset - parameter_offset;
|
||||
content_type_parameter_str = tvb_get_string_enc(wmem_packet_scope(), tvb,
|
||||
message_info.media_str = tvb_get_string_enc(wmem_packet_scope(), tvb,
|
||||
parameter_offset, content_type_parameter_str_len, ENC_UTF_8|ENC_NA);
|
||||
}
|
||||
media_type_str_lower_case = ascii_strdown_inplace(
|
||||
|
@ -689,7 +690,7 @@ dissect_msrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
|
|||
found_match = dissector_try_string(media_type_dissector_table,
|
||||
media_type_str_lower_case,
|
||||
next_tvb, pinfo,
|
||||
msrp_data_tree, content_type_parameter_str);
|
||||
msrp_data_tree, &message_info);
|
||||
/* If no match dump as text */
|
||||
}
|
||||
if ( found_match == 0 )
|
||||
|
|
|
@ -59,12 +59,14 @@
|
|||
|
||||
#include <epan/packet.h>
|
||||
#include <epan/expert.h>
|
||||
#include <epan/media_params.h>
|
||||
#include <epan/prefs.h>
|
||||
#include <wsutil/str_util.h>
|
||||
#include "packet-imf.h"
|
||||
|
||||
#include "packet-dcerpc.h"
|
||||
#include "packet-gssapi.h"
|
||||
#include "packet-http.h"
|
||||
|
||||
void proto_register_multipart(void);
|
||||
void proto_reg_handoff_multipart(void);
|
||||
|
@ -179,13 +181,12 @@ static gint
|
|||
process_preamble(proto_tree *tree, tvbuff_t *tvb, multipart_info_t *m_info,
|
||||
gboolean *last_boundary);
|
||||
static gint
|
||||
process_body_part(proto_tree *tree, tvbuff_t *tvb, multipart_info_t *m_info,
|
||||
process_body_part(proto_tree *tree, tvbuff_t *tvb,
|
||||
http_message_info_t *input_message_info, multipart_info_t *m_info,
|
||||
packet_info *pinfo, gint start, gint idx,
|
||||
gboolean *last_boundary);
|
||||
static gint
|
||||
is_known_multipart_header(const char *header_str, guint len);
|
||||
static gint
|
||||
index_of_char(const char *str, const char c);
|
||||
|
||||
|
||||
/* Return a tvb that contains the binary representation of a base64
|
||||
|
@ -310,96 +311,6 @@ unfold_and_compact_mime_header(const char *lines, gint *first_colon_offset)
|
|||
return (ret);
|
||||
}
|
||||
|
||||
/* Return the index of a given char in the given string,
|
||||
* or -1 if not found.
|
||||
*/
|
||||
static gint
|
||||
index_of_char(const char *str, const char c)
|
||||
{
|
||||
gint len = 0;
|
||||
const char *p = str;
|
||||
|
||||
while (*p && *p != c) {
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
|
||||
if (*p)
|
||||
return len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *find_parameter(char *parameters, const char *key, int *retlen)
|
||||
{
|
||||
char *start, *p;
|
||||
int keylen = 0;
|
||||
int len = 0;
|
||||
|
||||
if(!parameters || !*parameters || !key || strlen(key) == 0)
|
||||
/* we won't be able to find anything */
|
||||
return NULL;
|
||||
|
||||
keylen = (int) strlen(key);
|
||||
p = parameters;
|
||||
|
||||
while (*p) {
|
||||
|
||||
while ((*p) && g_ascii_isspace(*p))
|
||||
p++; /* Skip white space */
|
||||
|
||||
if (g_ascii_strncasecmp(p, key, keylen) == 0)
|
||||
break;
|
||||
/* Skip to next parameter */
|
||||
p = strchr(p, ';');
|
||||
if (p == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
p++; /* Skip semicolon */
|
||||
|
||||
}
|
||||
if (*p == 0x0)
|
||||
return NULL; /* key wasn't found */
|
||||
|
||||
start = p + keylen;
|
||||
if (start[0] == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the parameter value
|
||||
*/
|
||||
if (start[0] == '"') {
|
||||
/*
|
||||
* Parameter value is a quoted-string
|
||||
*/
|
||||
start++; /* Skip the quote */
|
||||
len = index_of_char(start, '"');
|
||||
if (len < 0) {
|
||||
/*
|
||||
* No closing quote
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Look for end of boundary
|
||||
*/
|
||||
p = start;
|
||||
while (*p) {
|
||||
if (*p == ';' || g_ascii_isspace(*p))
|
||||
break;
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
if(retlen)
|
||||
(*retlen) = len;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/* Retrieve the media information from pinfo->private_data,
|
||||
* and compute the boundary string and its length.
|
||||
* Return a pointer to a filled-in multipart_info_t, or NULL on failure.
|
||||
|
@ -409,7 +320,7 @@ static char *find_parameter(char *parameters, const char *key, int *retlen)
|
|||
* leading hyphens. (quote from rfc2046)
|
||||
*/
|
||||
static multipart_info_t *
|
||||
get_multipart_info(packet_info *pinfo, const char *str)
|
||||
get_multipart_info(packet_info *pinfo, http_message_info_t *message_info)
|
||||
{
|
||||
const char *start_boundary, *start_protocol = NULL;
|
||||
int len_boundary = 0, len_protocol = 0;
|
||||
|
@ -418,16 +329,22 @@ get_multipart_info(packet_info *pinfo, const char *str)
|
|||
char *parameters;
|
||||
gint dummy;
|
||||
|
||||
if ((type == NULL) || (str == NULL)) {
|
||||
/*
|
||||
* We need both a content type AND parameters
|
||||
* for multipart dissection.
|
||||
*/
|
||||
/*
|
||||
* We need both a content type AND parameters
|
||||
* for multipart dissection.
|
||||
*/
|
||||
if (type == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (message_info == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (message_info->media_str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Clean up the parameters */
|
||||
parameters = unfold_and_compact_mime_header(str, &dummy);
|
||||
parameters = unfold_and_compact_mime_header(message_info->media_str, &dummy);
|
||||
|
||||
start_boundary = find_parameter(parameters, "boundary=", &len_boundary);
|
||||
|
||||
|
@ -626,14 +543,15 @@ dissect_kerberos_encrypted_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree
|
|||
* Return the offset to the start of the next body-part.
|
||||
*/
|
||||
static gint
|
||||
process_body_part(proto_tree *tree, tvbuff_t *tvb, multipart_info_t *m_info,
|
||||
process_body_part(proto_tree *tree, tvbuff_t *tvb,
|
||||
http_message_info_t *input_message_info, multipart_info_t *m_info,
|
||||
packet_info *pinfo, gint start, gint idx,
|
||||
gboolean *last_boundary)
|
||||
{
|
||||
proto_tree *subtree;
|
||||
proto_item *ti;
|
||||
gint offset = start, next_offset = 0;
|
||||
char *parameters = NULL;
|
||||
http_message_info_t message_info = { input_message_info->type, NULL };
|
||||
gint body_start, boundary_start, boundary_line_len;
|
||||
|
||||
gchar *content_type_str = NULL;
|
||||
|
@ -753,9 +671,9 @@ process_body_part(proto_tree *tree, tvbuff_t *tvb, multipart_info_t *m_info,
|
|||
|
||||
if (semicolon_offset > 0) {
|
||||
value_str[semicolon_offset] = '\0';
|
||||
parameters = wmem_strdup(wmem_packet_scope(), value_str + semicolon_offset + 1);
|
||||
message_info.media_str = wmem_strdup(wmem_packet_scope(), value_str + semicolon_offset + 1);
|
||||
} else {
|
||||
parameters = NULL;
|
||||
message_info.media_str = NULL;
|
||||
}
|
||||
|
||||
content_type_str = wmem_ascii_strdown(wmem_packet_scope(), value_str, -1);
|
||||
|
@ -764,7 +682,7 @@ process_body_part(proto_tree *tree, tvbuff_t *tvb, multipart_info_t *m_info,
|
|||
proto_item_append_text(ti, " (%s)", content_type_str);
|
||||
|
||||
/* find the "name" parameter in case we don't find a content disposition "filename" */
|
||||
if((mimetypename = find_parameter(parameters, "name=", &len)) != NULL) {
|
||||
if((mimetypename = find_parameter(message_info.media_str, "name=", &len)) != NULL) {
|
||||
mimetypename = g_strndup(mimetypename, len);
|
||||
}
|
||||
|
||||
|
@ -835,7 +753,7 @@ process_body_part(proto_tree *tree, tvbuff_t *tvb, multipart_info_t *m_info,
|
|||
tmp_tvb = encrypt.gssapi_decrypted_tvb;
|
||||
is_raw_data = FALSE;
|
||||
content_type_str = m_info->orig_content_type;
|
||||
parameters = m_info->orig_parameters;
|
||||
message_info.media_str = m_info->orig_parameters;
|
||||
} else if(encrypt.gssapi_encrypted_tvb) {
|
||||
tmp_tvb = encrypt.gssapi_encrypted_tvb;
|
||||
proto_tree_add_expert(tree, pinfo, &ei_multipart_decryption_not_possible, tmp_tvb, 0, -1);
|
||||
|
@ -867,21 +785,21 @@ process_body_part(proto_tree *tree, tvbuff_t *tvb, multipart_info_t *m_info,
|
|||
* First try the dedicated multipart dissector table
|
||||
*/
|
||||
dissected = dissector_try_string(multipart_media_subdissector_table,
|
||||
content_type_str, tmp_tvb, pinfo, subtree, parameters);
|
||||
content_type_str, tmp_tvb, pinfo, subtree, &message_info);
|
||||
if (! dissected) {
|
||||
/*
|
||||
* Fall back to the default media dissector table
|
||||
*/
|
||||
dissected = dissector_try_string(media_type_dissector_table,
|
||||
content_type_str, tmp_tvb, pinfo, subtree, parameters);
|
||||
content_type_str, tmp_tvb, pinfo, subtree, &message_info);
|
||||
}
|
||||
if (! dissected) {
|
||||
const char *save_match_string = pinfo->match_string;
|
||||
pinfo->match_string = content_type_str;
|
||||
call_dissector_with_data(media_handle, tmp_tvb, pinfo, subtree, parameters);
|
||||
call_dissector_with_data(media_handle, tmp_tvb, pinfo, subtree, &message_info);
|
||||
pinfo->match_string = save_match_string;
|
||||
}
|
||||
parameters = NULL; /* Shares same memory as content_type_str */
|
||||
message_info.media_str = NULL; /* Shares same memory as content_type_str */
|
||||
} else {
|
||||
call_data_dissector(tmp_tvb, pinfo, subtree);
|
||||
}
|
||||
|
@ -908,7 +826,8 @@ static int dissect_multipart(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
|
|||
proto_tree *subtree;
|
||||
proto_item *ti;
|
||||
proto_item *type_ti;
|
||||
multipart_info_t *m_info = get_multipart_info(pinfo, (const char*)data);
|
||||
http_message_info_t *message_info = (http_message_info_t *)data;
|
||||
multipart_info_t *m_info = get_multipart_info(pinfo, message_info);
|
||||
gint header_start = 0;
|
||||
gint body_index = 0;
|
||||
gboolean last_boundary = FALSE;
|
||||
|
@ -952,7 +871,7 @@ static int dissect_multipart(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
|
|||
* Process the encapsulated bodies
|
||||
*/
|
||||
while (last_boundary == FALSE) {
|
||||
header_start = process_body_part(subtree, tvb, m_info,
|
||||
header_start = process_body_part(subtree, tvb, message_info, m_info,
|
||||
pinfo, header_start, body_index++, &last_boundary);
|
||||
if (header_start == -1) {
|
||||
return tvb_reported_length(tvb);
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "packet-e164.h"
|
||||
#include "packet-sip.h"
|
||||
|
||||
#include "packet-http.h"
|
||||
|
||||
#include "packet-sdp.h" /* SDP needs a transport layer to determine request/response */
|
||||
|
||||
/* un-comment the following as well as this line in conversation.c, to enable debug printing */
|
||||
|
@ -2863,7 +2865,7 @@ dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info
|
|||
char cseq_method[MAX_CSEQ_METHOD_SIZE] = "";
|
||||
char call_id[MAX_CALL_ID_SIZE] = "";
|
||||
gchar *media_type_str_lower_case = NULL;
|
||||
char *content_type_parameter_str = NULL;
|
||||
http_message_info_t message_info = { HTTP_OTHERS, NULL };
|
||||
char *content_encoding_parameter_str = NULL;
|
||||
guint resend_for_packet = 0;
|
||||
guint request_for_response = 0;
|
||||
|
@ -3614,7 +3616,7 @@ dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info
|
|||
content_type_end = tvb_skip_wsp_return(tvb, semi_colon_offset-1);
|
||||
content_type_len = content_type_end - value_offset;
|
||||
content_type_parameter_str_len = value_offset + value_len - parameter_offset;
|
||||
content_type_parameter_str = tvb_get_string_enc(wmem_packet_scope(), tvb, parameter_offset,
|
||||
message_info.media_str = tvb_get_string_enc(wmem_packet_scope(), tvb, parameter_offset,
|
||||
content_type_parameter_str_len, ENC_UTF_8|ENC_NA);
|
||||
}
|
||||
media_type_str_lower_case = ascii_strdown_inplace(
|
||||
|
@ -4168,7 +4170,7 @@ dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info
|
|||
found_match = dissector_try_string(media_type_dissector_table,
|
||||
media_type_str_lower_case,
|
||||
next_tvb, pinfo,
|
||||
message_body_tree, content_type_parameter_str);
|
||||
message_body_tree, &message_info);
|
||||
DENDENT();
|
||||
DPRINT(("done calling dissector_try_string() with found_match=%u", found_match));
|
||||
|
||||
|
@ -4180,7 +4182,7 @@ dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info
|
|||
found_match = dissector_try_string(media_type_dissector_table,
|
||||
"multipart/",
|
||||
next_tvb, pinfo,
|
||||
message_body_tree, content_type_parameter_str);
|
||||
message_body_tree, &message_info);
|
||||
DENDENT();
|
||||
DPRINT(("done calling dissector_try_string() with found_match=%u", found_match));
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <epan/tap.h>
|
||||
#include "packet-tcp.h"
|
||||
#include "packet-ssl.h"
|
||||
#include "packet-http.h"
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
#define ZLIB_CONST
|
||||
|
@ -177,6 +178,7 @@ typedef struct _spdy_data_frame_t {
|
|||
} spdy_data_frame_t;
|
||||
|
||||
typedef struct _spdy_stream_info_t {
|
||||
http_type_t message_type;
|
||||
gchar *content_type;
|
||||
gchar *content_type_parameters;
|
||||
gchar *content_encoding;
|
||||
|
@ -514,6 +516,7 @@ static spdy_conv_t * get_or_create_spdy_conversation_data(packet_info *pinfo) {
|
|||
*/
|
||||
static void spdy_save_stream_info(spdy_conv_t *conv_data,
|
||||
guint32 stream_id,
|
||||
http_type_t message_type,
|
||||
gchar *content_type,
|
||||
gchar *content_type_params,
|
||||
gchar *content_encoding) {
|
||||
|
@ -524,6 +527,7 @@ static void spdy_save_stream_info(spdy_conv_t *conv_data,
|
|||
}
|
||||
|
||||
si = (spdy_stream_info_t *)wmem_alloc(wmem_file_scope(), sizeof(spdy_stream_info_t));
|
||||
si->message_type = message_type;
|
||||
si->content_type = content_type;
|
||||
si->content_type_parameters = content_type_params;
|
||||
si->content_encoding = content_encoding;
|
||||
|
@ -725,6 +729,7 @@ static int dissect_spdy_data_payload(tvbuff_t *tvb,
|
|||
dissector_handle_t handle;
|
||||
guint num_data_frames;
|
||||
gboolean dissected;
|
||||
http_message_info_t message_info;
|
||||
|
||||
/* Add frame description. */
|
||||
proto_item_append_text(spdy_proto, ", Stream: %d, Length: %d",
|
||||
|
@ -911,11 +916,13 @@ static int dissect_spdy_data_payload(tvbuff_t *tvb,
|
|||
handle = dissector_get_string_handle(media_type_subdissector_table,
|
||||
si->content_type);
|
||||
}
|
||||
message_info.type = si->message_type;
|
||||
message_info.media_str = media_str;
|
||||
if (handle != NULL) {
|
||||
/*
|
||||
* We have a subdissector - call it.
|
||||
*/
|
||||
dissected = call_dissector_with_data(handle, data_tvb, pinfo, spdy_tree, media_str);
|
||||
dissected = call_dissector_with_data(handle, data_tvb, pinfo, spdy_tree, &message_info);
|
||||
} else {
|
||||
dissected = FALSE;
|
||||
}
|
||||
|
@ -925,7 +932,7 @@ static int dissect_spdy_data_payload(tvbuff_t *tvb,
|
|||
* Calling the default media handle if there is a content-type that
|
||||
* wasn't handled above.
|
||||
*/
|
||||
call_dissector_with_data(media_handle, next_tvb, pinfo, spdy_tree, media_str);
|
||||
call_dissector_with_data(media_handle, next_tvb, pinfo, spdy_tree, &message_info);
|
||||
} else {
|
||||
/* Call the default data dissector */
|
||||
call_data_dissector(next_tvb, pinfo, spdy_tree);
|
||||
|
@ -1328,8 +1335,9 @@ static int dissect_spdy_header_payload(
|
|||
*/
|
||||
if (content_type != NULL && !pinfo->fd->flags.visited) {
|
||||
gchar *content_type_params = spdy_parse_content_type(content_type);
|
||||
spdy_save_stream_info(conv_data, stream_id, content_type,
|
||||
content_type_params, content_encoding);
|
||||
spdy_save_stream_info(conv_data, stream_id,
|
||||
(hdr_status == NULL) ? HTTP_REQUEST : HTTP_RESPONSE,
|
||||
content_type, content_type_params, content_encoding);
|
||||
}
|
||||
|
||||
return frame->length;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include <epan/packet.h>
|
||||
|
||||
#include "packet-http.h"
|
||||
|
||||
/*
|
||||
* Media dissector for line-based text media like text/plain, message/http.
|
||||
|
@ -59,6 +60,7 @@ dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* da
|
|||
proto_item *ti;
|
||||
gint offset = 0, next_offset;
|
||||
gint len;
|
||||
http_message_info_t *message_info;
|
||||
const char *data_name;
|
||||
int length = tvb_captured_length(tvb);
|
||||
|
||||
|
@ -78,12 +80,20 @@ dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* da
|
|||
/*
|
||||
* No information from "match_string"
|
||||
*/
|
||||
data_name = (char *)data;
|
||||
if (! (data_name && data_name[0])) {
|
||||
message_info = (http_message_info_t *)data;
|
||||
if (message_info == NULL) {
|
||||
/*
|
||||
* No information from dissector data
|
||||
*/
|
||||
data_name = NULL;
|
||||
} else {
|
||||
data_name = message_info->media_str;
|
||||
if (! (data_name && data_name[0])) {
|
||||
/*
|
||||
* No information from dissector data
|
||||
*/
|
||||
data_name = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/* media_params.c
|
||||
* Routines for parsing media type parameters
|
||||
* Copyright 2004, Anders Broman.
|
||||
* Copyright 2004, Olivier Biot.
|
||||
*
|
||||
* Refer to the AUTHORS file or the AUTHORS section in the man page
|
||||
* for contacting the author(s) of this file.
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <epan/media_params.h>
|
||||
|
||||
/* Return the index of a given char in the given string,
|
||||
* or -1 if not found.
|
||||
*/
|
||||
gint
|
||||
index_of_char(const char *str, const char c)
|
||||
{
|
||||
gint len = 0;
|
||||
const char *p = str;
|
||||
|
||||
while (*p && *p != c) {
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
|
||||
if (*p)
|
||||
return len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *
|
||||
find_parameter(const char *parameters, const char *key, int *retlen)
|
||||
{
|
||||
const char *start, *p;
|
||||
int keylen = 0;
|
||||
int len = 0;
|
||||
|
||||
if(!parameters || !*parameters || !key || strlen(key) == 0)
|
||||
/* we won't be able to find anything */
|
||||
return NULL;
|
||||
|
||||
keylen = (int) strlen(key);
|
||||
p = parameters;
|
||||
|
||||
while (*p) {
|
||||
|
||||
while ((*p) && g_ascii_isspace(*p))
|
||||
p++; /* Skip white space */
|
||||
|
||||
if (g_ascii_strncasecmp(p, key, keylen) == 0)
|
||||
break;
|
||||
/* Skip to next parameter */
|
||||
p = strchr(p, ';');
|
||||
if (p == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
p++; /* Skip semicolon */
|
||||
|
||||
}
|
||||
if (*p == 0x0)
|
||||
return NULL; /* key wasn't found */
|
||||
|
||||
start = p + keylen;
|
||||
if (start[0] == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the parameter value
|
||||
*/
|
||||
if (start[0] == '"') {
|
||||
/*
|
||||
* Parameter value is a quoted-string
|
||||
*/
|
||||
start++; /* Skip the quote */
|
||||
len = index_of_char(start, '"');
|
||||
if (len < 0) {
|
||||
/*
|
||||
* No closing quote
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Look for end of boundary
|
||||
*/
|
||||
p = start;
|
||||
while (*p) {
|
||||
if (*p == ';' || g_ascii_isspace(*p))
|
||||
break;
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
if(retlen)
|
||||
(*retlen) = len;
|
||||
|
||||
/*
|
||||
* This is one of those ugly routines like strchr() where you can
|
||||
* pass in a constant or non-constant string, and the result
|
||||
* points into that string and inherits the constness of the
|
||||
* input argument, but C doesn't support that, so the input
|
||||
* parameter is const char * and the result is char *.
|
||||
*/
|
||||
return (char *)start;
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/* media_params.h
|
||||
* Routines for parsing media type parameters
|
||||
* Copyright 2004, Anders Broman.
|
||||
* Copyright 2004, Olivier Biot.
|
||||
*
|
||||
* Refer to the AUTHORS file or the AUTHORS section in the man page
|
||||
* for contacting the author(s) of this file.
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __MEDIA_PARAMS_H__
|
||||
#define __MEDIA_PARAMS_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "ws_symbol_export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Return the index of a given char in the given string,
|
||||
* or -1 if not found.
|
||||
*/
|
||||
WS_DLL_PUBLIC gint
|
||||
index_of_char(const char *str, const char c);
|
||||
|
||||
WS_DLL_PUBLIC char *
|
||||
find_parameter(const char *parameters, const char *key, int *retlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* media_params.h */
|
Loading…
Reference in New Issue