Added JSON native file support.
libjsmn has also been moved from epan/ to wsutil/ to make it visible from wiretap. Change-Id: I59abb3419acb1baa83194b38152d3651ed5c123c Bug: 10878 Reviewed-on: https://code.wireshark.org/review/6716 Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
This commit is contained in:
parent
1478db03d5
commit
bd911096bd
@ -3107,7 +3107,6 @@ AC_OUTPUT(
|
||||
epan/dissectors/dcerpc/Makefile
|
||||
epan/dissectors/pidl/Makefile
|
||||
epan/ftypes/Makefile
|
||||
epan/jsmn/Makefile
|
||||
epan/nghttp2/Makefile
|
||||
epan/wmem/Makefile
|
||||
epan/wslua/Makefile
|
||||
|
@ -1517,11 +1517,6 @@ set(WMEM_FILES
|
||||
)
|
||||
source_group(wmem FILES ${WMEM_FILES})
|
||||
|
||||
set(JSMN_FILES
|
||||
jsmn/jsmn.c
|
||||
)
|
||||
source_group(jsmn FILES ${JSMN_FILES})
|
||||
|
||||
set(NGHTTP2_FILES
|
||||
nghttp2/nghttp2_buf.c
|
||||
nghttp2/nghttp2_hd.c
|
||||
@ -1690,7 +1685,6 @@ set(CLEAN_FILES
|
||||
${DISSECTOR_SUPPORT_SRC}
|
||||
${LIBWIRESHARK_ASM_FILES}
|
||||
${WMEM_FILES}
|
||||
${JSMN_FILES}
|
||||
${NGHTTP2_FILES}
|
||||
${WSLUA_FILES}
|
||||
)
|
||||
@ -1713,7 +1707,6 @@ add_library(epan ${LINK_MODE_LIB}
|
||||
${DFILTER_FILES}
|
||||
${FTYPE_FILES}
|
||||
${WMEM_FILES}
|
||||
${JSMN_FILES}
|
||||
${NGHTTP2_FILES}
|
||||
${WSLUA_FILES}
|
||||
${DISSECTOR_FILES}
|
||||
@ -1743,7 +1736,6 @@ file(GLOB DFILTER_HEADERS dfilter/*.h ../tools/lemon/cppmagic.h)
|
||||
file(GLOB D_HEADERS dissectors/*.h)
|
||||
file(GLOB FTYPES_HEADERS ftypes/*.h)
|
||||
file(GLOB WMEM_HEADERS wmem/*.h)
|
||||
file(GLOB JSMN_HEADERS jsmn/*.h)
|
||||
file(GLOB NGHTTP2_HEADERS nghttp2/*.h)
|
||||
file(MAKE_DIRECTORY ${ABICHECK_TMPDIR}
|
||||
${ABICHECK_TMPDIR}/epan
|
||||
@ -1753,7 +1745,6 @@ file(MAKE_DIRECTORY ${ABICHECK_TMPDIR}
|
||||
${ABICHECK_TMPDIR}/dissectors
|
||||
${ABICHECK_TMPDIR}/ftypes
|
||||
${ABICHECK_TMPDIR}/wmem
|
||||
${ABICHECK_TMPDIR}/jsmn
|
||||
${ABICHECK_TMPDIR}/nghttp2)
|
||||
|
||||
file(COPY ../color.h ../register.h DESTINATION ${ABICHECK_TMPDIR})
|
||||
@ -1764,7 +1755,6 @@ file(COPY ${DFILTER_HEADERS} DESTINATION ${ABICHECK_TMPDIR}/dfilter)
|
||||
file(COPY ${D_HEADERS} DESTINATION ${ABICHECK_TMPDIR}/dissectors)
|
||||
file(COPY ${FTYPES_HEADERS} DESTINATION ${ABICHECK_TMPDIR}/ftypes)
|
||||
file(COPY ${WMEM_HEADERS} DESTINATION ${ABICHECK_TMPDIR}/wmem)
|
||||
file(COPY ${JSMN_HEADERS} DESTINATION ${ABICHECK_TMPDIR}/jsmn)
|
||||
file(COPY ${NGHTTP2_HEADERS} DESTINATION ${ABICHECK_TMPDIR}/nghttp2)
|
||||
|
||||
add_custom_command(OUTPUT libwireshark.abi.tar.gz
|
||||
@ -1781,10 +1771,10 @@ add_custom_command(OUTPUT libwireshark.abi.tar.gz
|
||||
${ABICHECK_TMPDIR}/epan/* ${ABICHECK_TMPDIR}/compress/*
|
||||
${ABICHECK_TMPDIR}/dfilter/* ${ABICHECK_TMPDIR}/dissectors/*
|
||||
${ABICHECK_TMPDIR}/ftypes/* ${ABICHECK_TMPDIR}/wmem/*
|
||||
${ABICHECK_TMPDIR}/jsmn/* ${ABICHECK_TMPDIR}/nghttp2/*
|
||||
${ABICHECK_TMPDIR}/nghttp2/*
|
||||
DEPENDS ${HEADERS}
|
||||
${CRYPT_HEADERS} ${COMPRESS_HEADERS} ${DFILTER_HEADERS} ${D_HEADERS}
|
||||
${FTYPES_HEADERS} ${WMEM_HEADERS} ${JSMN_HEADERS} ${NGHTTP2_HEADERS} epan)
|
||||
${FTYPES_HEADERS} ${WMEM_HEADERS} ${NGHTTP2_HEADERS} epan)
|
||||
|
||||
# By default the name for a library with target name epan will be libepan,
|
||||
# but Ethereal is now named Wireshark
|
||||
|
@ -33,7 +33,7 @@ wslua_dir =
|
||||
wslua_dist_dir = wslua
|
||||
endif # HAVE_LIBLUA
|
||||
|
||||
SUBDIRS = compress crypt ftypes dfilter dissectors jsmn nghttp2 wmem $(wslua_dir)
|
||||
SUBDIRS = compress crypt ftypes dfilter dissectors nghttp2 wmem $(wslua_dir)
|
||||
|
||||
DIST_SUBDIRS = $(SUBDIRS) $(wslua_dist_dir)
|
||||
|
||||
@ -127,7 +127,7 @@ libwireshark_la_LIBADD = \
|
||||
libwireshark_asmopt.la crypt/libairpdcap.la \
|
||||
ftypes/libftypes.la dfilter/libdfilter.la dissectors/libdissectors.la \
|
||||
dissectors/libdirtydissectors.la dissectors/libfiledissectors.la \
|
||||
jsmn/libjsmn.la nghttp2/libnghttp2.la wmem/libwmem.la $(wslua_lib) \
|
||||
nghttp2/libnghttp2.la wmem/libwmem.la $(wslua_lib) \
|
||||
@SOCKET_LIBS@ @NSL_LIBS@ \
|
||||
@C_ARES_LIBS@ @ADNS_LIBS@ @LIBGCRYPT_LIBS@ @LIBGNUTLS_LIBS@ \
|
||||
@KRB5_LIBS@ @SSL_LIBS@ @LIBSMI_LDFLAGS@ @GEOIP_LIBS@ \
|
||||
@ -138,7 +138,7 @@ libwireshark_la_DEPENDENCIES = \
|
||||
libwireshark_generated.la compress/liblzxpress.la\
|
||||
libwireshark_asmopt.la crypt/libairpdcap.la \
|
||||
ftypes/libftypes.la dfilter/libdfilter.la dissectors/libdissectors.la \
|
||||
dissectors/libdirtydissectors.la jsmn/libjsmn.la nghttp2/libnghttp2.la \
|
||||
dissectors/libdirtydissectors.la nghttp2/libnghttp2.la \
|
||||
wmem/libwmem.la $(wslua_lib) \
|
||||
${top_builddir}/wsutil/libwsutil.la \
|
||||
${top_builddir}/wiretap/libwiretap.la
|
||||
|
@ -71,7 +71,6 @@ libwireshark_LIBS = \
|
||||
dfilter\dfilter.lib \
|
||||
wmem\wmem.lib \
|
||||
$(WSLUA_LIB) \
|
||||
jsmn\jsmn.lib \
|
||||
nghttp2\nghttp2.lib \
|
||||
dissectors\dissectors.lib
|
||||
|
||||
@ -92,17 +91,17 @@ DOXYGEN_DEP=doxygen
|
||||
!ENDIF
|
||||
|
||||
!IFDEF ENABLE_LIBWIRESHARK
|
||||
all: compress crypt ftypes dfilter wmem $(WSLUA_DIR) jsmn nghttp2 dissectors libwireshark.dll
|
||||
all: compress crypt ftypes dfilter wmem $(WSLUA_DIR) nghttp2 dissectors libwireshark.dll
|
||||
!ELSE
|
||||
all: compress crypt ftypes dfilter wmem $(WSLUA_DIR) jsmn nghttp2 dissectors libwireshark.lib
|
||||
all: compress crypt ftypes dfilter wmem $(WSLUA_DIR) nghttp2 dissectors libwireshark.lib
|
||||
!ENDIF
|
||||
|
||||
# For use when making libwireshark.dll
|
||||
libwireshark.lib: libwireshark.dll
|
||||
libwireshark.exp: libwireshark.dll
|
||||
|
||||
libwireshark.dll: ..\config.h $(LIBWIRESHARK_OBJECTS) compress crypt ftypes dfilter wmem $(WSLUA_DIR) jsmn nghttp2 dissectors $(DOXYGEN_DEP) $(EXTRA_OBJECTS) \
|
||||
crypt\airpdcap.lib ftypes\ftypes.lib dfilter\dfilter.lib wmem\wmem.lib dissectors\dissectors.lib $(WSLUA_LIB) jsmn\jsmn.lib nghttp2\nghttp2.lib ..\image\libwireshark.res
|
||||
libwireshark.dll: ..\config.h $(LIBWIRESHARK_OBJECTS) compress crypt ftypes dfilter wmem $(WSLUA_DIR) nghttp2 dissectors $(DOXYGEN_DEP) $(EXTRA_OBJECTS) \
|
||||
crypt\airpdcap.lib ftypes\ftypes.lib dfilter\dfilter.lib wmem\wmem.lib dissectors\dissectors.lib $(WSLUA_LIB) nghttp2\nghttp2.lib ..\image\libwireshark.res
|
||||
@echo Linking libwireshark.dll
|
||||
$(link) $(dlllflags) $(conlibsdll) shell32.lib psapi.lib \
|
||||
$(LOCAL_LDFLAGS) $(DLL_LDFLAGS) \
|
||||
@ -112,8 +111,8 @@ libwireshark.dll: ..\config.h $(LIBWIRESHARK_OBJECTS) compress crypt ftypes dfil
|
||||
dissectors\register.obj \
|
||||
$(EXTRA_OBJECTS)
|
||||
|
||||
libwireshark.lib : ..\config.h $(LIBWIRESHARK_OBJECTS) compress crypt ftypes dfilter wmem $(WSLUA_DIR) jsmn nghttp2 dissectors $(DOXYGEN_DEP) $(EXTRA_OBJECTS) \
|
||||
crypt\airpdcap.lib ftypes\ftypes.lib dfilter\dfilter.lib wmem\wmem.lib $(WSLUA_LIB) jsmn\jsmn.lib nghttp2\nghttp2.lib dissectors\dissectors.lib
|
||||
libwireshark.lib : ..\config.h $(LIBWIRESHARK_OBJECTS) compress crypt ftypes dfilter wmem $(WSLUA_DIR) nghttp2 dissectors $(DOXYGEN_DEP) $(EXTRA_OBJECTS) \
|
||||
crypt\airpdcap.lib ftypes\ftypes.lib dfilter\dfilter.lib wmem\wmem.lib $(WSLUA_LIB) nghttp2\nghttp2.lib dissectors\dissectors.lib
|
||||
link /lib /out:libwireshark.lib $(LIBWIRESHARK_OBJECTS) \
|
||||
$(EXTRA_OBJECTS)
|
||||
|
||||
@ -144,8 +143,6 @@ clean: clean-local
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake clean
|
||||
cd ../wslua
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake clean
|
||||
cd ../jsmn
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake clean
|
||||
cd ../nghttp2
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake clean
|
||||
cd ..
|
||||
@ -182,8 +179,6 @@ distclean: distclean-local
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake distclean
|
||||
cd ../wslua
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake distclean
|
||||
cd ../jsmn
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake distclean
|
||||
cd ../nghttp2
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake distclean
|
||||
cd ..
|
||||
@ -205,8 +200,6 @@ maintainer-clean: maintainer-clean-local
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake maintainer-clean
|
||||
cd ../wslua
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake maintainer-clean
|
||||
cd ../jsmn
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake maintainer-clean
|
||||
cd ../nghttp2
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake maintainer-clean
|
||||
cd ..
|
||||
@ -246,11 +239,6 @@ wslua:: ..\config.h
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake
|
||||
cd ..
|
||||
|
||||
jsmn:: ..\config.h
|
||||
cd jsmn
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake
|
||||
cd ..
|
||||
|
||||
nghttp2:: ..\config.h
|
||||
cd nghttp2
|
||||
$(MAKE) /$(MAKEFLAGS) -f Makefile.nmake
|
||||
|
@ -31,11 +31,13 @@
|
||||
|
||||
#include <epan/packet.h>
|
||||
#include <epan/tvbparse.h>
|
||||
#include <epan/jsmn/jsmn.h>
|
||||
#include <wsutil/jsmn.h>
|
||||
|
||||
#include <wsutil/str_util.h>
|
||||
#include <wsutil/unicode-utils.h>
|
||||
|
||||
#include <wiretap/wtap.h>
|
||||
|
||||
void proto_register_json(void);
|
||||
void proto_reg_handoff_json(void);
|
||||
|
||||
@ -119,6 +121,20 @@ dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
|
||||
const char *data_name;
|
||||
int offset;
|
||||
|
||||
/* JSON dissector can be called in a JSON native file or when transported
|
||||
* by another protocol. We set the column values only if they've not been
|
||||
* already set by someone else.
|
||||
*/
|
||||
wmem_list_frame_t *proto = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
|
||||
if (proto) {
|
||||
const char *name = proto_get_protocol_filter_name(GPOINTER_TO_INT(wmem_list_frame_data(proto)));
|
||||
|
||||
if (!strcmp(name, "frame")) {
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "JSON");
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "JavaScript Object Notation");
|
||||
}
|
||||
}
|
||||
|
||||
data_name = pinfo->match_string;
|
||||
if (! (data_name && data_name[0])) {
|
||||
/*
|
||||
@ -572,19 +588,12 @@ static void init_json_parser(void) {
|
||||
static gboolean
|
||||
dissect_json_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
||||
{
|
||||
/* We expect no more than 1024 tokens */
|
||||
const guint max_tokens = 1024;
|
||||
guint len = tvb_captured_length(tvb);
|
||||
guint8* buf = tvb_get_string_enc(wmem_packet_scope(), tvb, 0, len, ENC_ASCII);
|
||||
const guint8* buf = tvb_get_string_enc(wmem_packet_scope(), tvb, 0, len, ENC_ASCII);
|
||||
|
||||
jsmn_parser p;
|
||||
|
||||
jsmntok_t* t = (jsmntok_t*)wmem_alloc_array(wmem_packet_scope(), jsmntok_t, max_tokens);
|
||||
|
||||
jsmn_init(&p);
|
||||
if (jsmn_parse(&p, buf, len, t, max_tokens) < 0) {
|
||||
if (jsmn_is_json(buf, len) == FALSE)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (dissect_json(tvb, pinfo, tree, data) != 0);
|
||||
}
|
||||
|
||||
@ -628,6 +637,7 @@ proto_reg_handoff_json(void)
|
||||
{
|
||||
heur_dissector_add("hpfeeds", dissect_json_heur, proto_json);
|
||||
heur_dissector_add("db-lsp", dissect_json_heur, proto_json);
|
||||
dissector_add_uint("wtap_encap", WTAP_ENCAP_JSON, json_handle);
|
||||
|
||||
dissector_add_string("media_type", "application/json", json_handle); /* RFC 4627 */
|
||||
dissector_add_string("media_type", "application/json-rpc", json_handle); /* JSON-RPC over HTTP */
|
||||
|
@ -1,63 +0,0 @@
|
||||
# Makefile.am
|
||||
# Automake file for libjsmn library
|
||||
#
|
||||
# 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.
|
||||
|
||||
if HAVE_WARNINGS_AS_ERRORS
|
||||
AM_CFLAGS = -Werror
|
||||
endif
|
||||
|
||||
include Makefile.common
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir) \
|
||||
$(LIBJSMN_CFLAGS)
|
||||
|
||||
noinst_LTLIBRARIES = libjsmn.la
|
||||
|
||||
CLEANFILES = \
|
||||
libjsmn.a \
|
||||
libjsmn.la \
|
||||
*~
|
||||
|
||||
DISTCLEANFILES =
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in
|
||||
|
||||
libjsmn_la_SOURCES = \
|
||||
$(LIBJSMN_SRC) \
|
||||
$(LIBJSMN_INCLUDES)
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.common \
|
||||
Makefile.nmake
|
||||
|
||||
#
|
||||
# Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
#
|
||||
# Local variables:
|
||||
# c-basic-offset: 8
|
||||
# tab-width: 8
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
#
|
||||
# vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
||||
# :indentSize=8:tabSize=8:noTabs=false:
|
||||
#
|
@ -1,38 +0,0 @@
|
||||
# Makefile.common
|
||||
# Contains the stuff from Makefile.am and Makefile.nmake that is
|
||||
# a) common to both files and
|
||||
# b) portable between both files
|
||||
#
|
||||
# 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.
|
||||
|
||||
LIBJSMN_SRC = jsmn.c
|
||||
LIBJSMN_INCLUDES = jsmn.h
|
||||
|
||||
#
|
||||
# Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
#
|
||||
# Local variables:
|
||||
# c-basic-offset: 8
|
||||
# tab-width: 8
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
#
|
||||
# vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
||||
# :indentSize=8:tabSize=8:noTabs=false:
|
||||
#
|
@ -1,44 +0,0 @@
|
||||
## Makefile for building jsmn.lib with Microsoft C and nmake
|
||||
## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
|
||||
#
|
||||
|
||||
include ..\..\config.nmake
|
||||
|
||||
include Makefile.common
|
||||
|
||||
############### no need to modify below this line #########
|
||||
|
||||
CFLAGS=$(WARNINGS_ARE_ERRORS) $(STANDARD_CFLAGS) \
|
||||
/I. /Ijsmn /I../.. $(GLIB_CFLAGS) -DWS_BUILD_DLL
|
||||
|
||||
.c.obj::
|
||||
$(CC) $(CFLAGS) -Fd.\ -c $<
|
||||
|
||||
OBJECTS = $(LIBJSMN_SRC:.c=.obj)
|
||||
|
||||
jsmn.lib: $(OBJECTS)
|
||||
link /lib /out:jsmn.lib $(OBJECTS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) jsmn.lib *.nativecodeanalysis.xml *.pdb *.sbr
|
||||
|
||||
distclean: clean
|
||||
|
||||
maintainer-clean: distclean
|
||||
|
||||
checkapi:
|
||||
$(PERL) ../../tools/checkAPIs.pl -g termoutput -build \
|
||||
$(LIBJSMN_INCLUDES)
|
||||
|
||||
#
|
||||
# Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
#
|
||||
# Local variables:
|
||||
# c-basic-offset: 8
|
||||
# tab-width: 8
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
#
|
||||
# vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
||||
# :indentSize=8:tabSize=8:noTabs=false:
|
||||
#
|
345
epan/jsmn/jsmn.c
345
epan/jsmn/jsmn.c
@ -1,345 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Serge A. Zaitsev
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jsmn.h"
|
||||
|
||||
/**
|
||||
* Allocates a fresh unused token from the token pull.
|
||||
*/
|
||||
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
|
||||
jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *tok;
|
||||
if (parser->toknext >= num_tokens) {
|
||||
return NULL;
|
||||
}
|
||||
tok = &tokens[parser->toknext++];
|
||||
tok->start = tok->end = -1;
|
||||
tok->size = 0;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
tok->parent = -1;
|
||||
#endif
|
||||
return tok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills token type and boundaries.
|
||||
*/
|
||||
static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
|
||||
int start, int end) {
|
||||
token->type = type;
|
||||
token->start = start;
|
||||
token->end = end;
|
||||
token->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills next available token with JSON primitive.
|
||||
*/
|
||||
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
|
||||
size_t len, jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
int start;
|
||||
|
||||
start = parser->pos;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
switch (js[parser->pos]) {
|
||||
#ifndef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by "," or "}" or "]" */
|
||||
case ':':
|
||||
#endif
|
||||
case '\t' : case '\r' : case '\n' : case ' ' :
|
||||
case ',' : case ']' : case '}' :
|
||||
goto found;
|
||||
}
|
||||
if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by a comma/object/array */
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
#endif
|
||||
|
||||
found:
|
||||
if (tokens == NULL) {
|
||||
parser->pos--;
|
||||
return 0;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
parser->pos--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filsl next token with JSON string.
|
||||
*/
|
||||
static int jsmn_parse_string(jsmn_parser *parser, const char *js,
|
||||
size_t len, jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
|
||||
int start = parser->pos;
|
||||
|
||||
parser->pos++;
|
||||
|
||||
/* Skip starting quote */
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c = js[parser->pos];
|
||||
|
||||
/* Quote: end of string */
|
||||
if (c == '\"') {
|
||||
if (tokens == NULL) {
|
||||
return 0;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Backslash: Quoted symbol expected */
|
||||
if (c == '\\' && parser->pos + 1 < len) {
|
||||
int i;
|
||||
parser->pos++;
|
||||
switch (js[parser->pos]) {
|
||||
/* Allowed escaped symbols */
|
||||
case '\"': case '/' : case '\\' : case 'b' :
|
||||
case 'f' : case 'r' : case 'n' : case 't' :
|
||||
break;
|
||||
/* Allows escaped symbol \uXXXX */
|
||||
case 'u':
|
||||
parser->pos++;
|
||||
for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
|
||||
/* If it isn't a hex character we have an error */
|
||||
if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
|
||||
(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
|
||||
(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
parser->pos++;
|
||||
}
|
||||
parser->pos--;
|
||||
break;
|
||||
/* Unexpected symbol */
|
||||
default:
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON string and fill tokens.
|
||||
*/
|
||||
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
jsmntok_t *tokens, unsigned int num_tokens) {
|
||||
int r;
|
||||
int i;
|
||||
jsmntok_t *token;
|
||||
int count = 0;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c;
|
||||
jsmntype_t type;
|
||||
|
||||
c = js[parser->pos];
|
||||
switch (c) {
|
||||
case '{': case '[':
|
||||
count++;
|
||||
if (tokens == NULL) {
|
||||
break;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL)
|
||||
return JSMN_ERROR_NOMEM;
|
||||
if (parser->toksuper != -1) {
|
||||
tokens[parser->toksuper].size++;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
}
|
||||
token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
token->start = parser->pos;
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case '}': case ']':
|
||||
if (tokens == NULL)
|
||||
break;
|
||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
if (parser->toknext < 1) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token = &tokens[parser->toknext - 1];
|
||||
for (;;) {
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token->end = parser->pos + 1;
|
||||
parser->toksuper = token->parent;
|
||||
break;
|
||||
}
|
||||
if (token->parent == -1) {
|
||||
break;
|
||||
}
|
||||
token = &tokens[token->parent];
|
||||
}
|
||||
#else
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
parser->toksuper = -1;
|
||||
token->end = parser->pos + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Error if unmatched closing bracket */
|
||||
if (i == -1) return JSMN_ERROR_INVAL;
|
||||
for (; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
parser->toksuper = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case '\"':
|
||||
r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
|
||||
if (r < 0) return r;
|
||||
count++;
|
||||
if (parser->toksuper != -1 && tokens != NULL)
|
||||
tokens[parser->toksuper].size++;
|
||||
break;
|
||||
case '\t' : case '\r' : case '\n' : case ' ':
|
||||
break;
|
||||
case ':':
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case ',':
|
||||
if (tokens != NULL && parser->toksuper != -1 &&
|
||||
tokens[parser->toksuper].type != JSMN_ARRAY &&
|
||||
tokens[parser->toksuper].type != JSMN_OBJECT) {
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
parser->toksuper = tokens[parser->toksuper].parent;
|
||||
#else
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
|
||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
||||
parser->toksuper = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitives are: numbers and booleans */
|
||||
case '-': case '0': case '1' : case '2': case '3' : case '4':
|
||||
case '5': case '6': case '7' : case '8': case '9':
|
||||
case 't': case 'f': case 'n' :
|
||||
/* And they must not be keys of the object */
|
||||
if (tokens != NULL && parser->toksuper != -1) {
|
||||
jsmntok_t *t = &tokens[parser->toksuper];
|
||||
if (t->type == JSMN_OBJECT ||
|
||||
(t->type == JSMN_STRING && t->size != 0)) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* In non-strict mode every unquoted value is a primitive */
|
||||
default:
|
||||
#endif
|
||||
r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
|
||||
if (r < 0) return r;
|
||||
count++;
|
||||
if (parser->toksuper != -1 && tokens != NULL)
|
||||
tokens[parser->toksuper].size++;
|
||||
break;
|
||||
|
||||
#ifdef JSMN_STRICT
|
||||
/* Unexpected char in strict mode */
|
||||
default:
|
||||
return JSMN_ERROR_INVAL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
/* Unmatched opened object or array */
|
||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new parser based over a given buffer with an array of tokens
|
||||
* available.
|
||||
*/
|
||||
void jsmn_init(jsmn_parser *parser) {
|
||||
parser->pos = 0;
|
||||
parser->toknext = 0;
|
||||
parser->toksuper = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
@ -46,6 +46,7 @@ set(CLEAN_FILES
|
||||
ipfix.c
|
||||
iptrace.c
|
||||
iseries.c
|
||||
json.c
|
||||
k12.c
|
||||
lanalyzer.c
|
||||
libpcap.c
|
||||
|
@ -52,6 +52,7 @@ NONGENERATED_C_FILES = \
|
||||
iptrace.c \
|
||||
iseries.c \
|
||||
mime_file.c \
|
||||
json.c \
|
||||
k12.c \
|
||||
lanalyzer.c \
|
||||
logcat_text.c \
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include "hcidump.h"
|
||||
#include "logcat.h"
|
||||
#include "logcat_text.h"
|
||||
#include "json.h"
|
||||
#include "network_instruments.h"
|
||||
#include "k12.h"
|
||||
#include "ber.h"
|
||||
@ -156,6 +157,7 @@ static const struct file_extension_info file_type_extensions_base[] = {
|
||||
{ "MPEG2 transport stream", "mp2t;ts;mpg" },
|
||||
{ "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr" },
|
||||
{ "CAM Inspector file", "camins" },
|
||||
{ "JavaScript Object Notation file", "json" }
|
||||
};
|
||||
|
||||
#define N_FILE_TYPE_EXTENSIONS (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
|
||||
@ -395,6 +397,7 @@ static struct open_info open_info_base[] = {
|
||||
/* Extremely weak heuristics - put them at the end. */
|
||||
{ "Ixia IxVeriWave .vwr Raw Capture", OPEN_INFO_HEURISTIC, vwr_open, "vwr", NULL, NULL },
|
||||
{ "CAM Inspector file", OPEN_INFO_HEURISTIC, camins_open, "camins", NULL, NULL },
|
||||
{ "JavaScript Object Notation", OPEN_INFO_HEURISTIC, json_open, "json", NULL, NULL }
|
||||
};
|
||||
|
||||
/* this is only used to build the dynamic array on load, do NOT use this
|
||||
@ -1488,6 +1491,11 @@ static const struct file_type_subtype_info dump_open_table_base[] = {
|
||||
FALSE, FALSE, 0,
|
||||
logcat_dump_can_write_encap, logcat_binary_dump_open, NULL },
|
||||
|
||||
/* WTAP_FILE_TYPE_SUBTYPE_JSON */
|
||||
{ "JavaScript Object Notation", "json", "json", "NULL",
|
||||
FALSE, FALSE, 0,
|
||||
NULL, NULL, NULL },
|
||||
|
||||
/* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_BRIEF */
|
||||
{ "Android Logcat Brief text format", "logcat-brief", NULL, NULL,
|
||||
FALSE, FALSE, 0,
|
||||
|
138
wiretap/json.c
Normal file
138
wiretap/json.c
Normal file
@ -0,0 +1,138 @@
|
||||
/* json.c
|
||||
*
|
||||
* Copyright 2015, Dario Lombardo <lomato@gmail.com>
|
||||
*
|
||||
* 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 "wtap-int.h"
|
||||
#include "file_wrappers.h"
|
||||
|
||||
#include <json.h>
|
||||
#include <wsutil/jsmn.h>
|
||||
|
||||
static gboolean json_read_file(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
|
||||
Buffer *buf, int *err, gchar **err_info)
|
||||
{
|
||||
gint64 file_size;
|
||||
int packet_size;
|
||||
|
||||
if ((file_size = wtap_file_size(wth, err)) == -1)
|
||||
return FALSE;
|
||||
|
||||
if (file_size > MAX_FILE_SIZE) {
|
||||
/*
|
||||
* Don't blow up trying to allocate space for an
|
||||
* immensely-large file.
|
||||
*/
|
||||
*err = WTAP_ERR_BAD_FILE;
|
||||
*err_info = g_strdup_printf("mime_file: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
|
||||
file_size, MAX_FILE_SIZE);
|
||||
return FALSE;
|
||||
}
|
||||
packet_size = (int)file_size;
|
||||
|
||||
phdr->rec_type = REC_TYPE_PACKET;
|
||||
phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
|
||||
|
||||
phdr->caplen = packet_size;
|
||||
phdr->len = packet_size;
|
||||
|
||||
phdr->ts.secs = 0;
|
||||
phdr->ts.nsecs = 0;
|
||||
|
||||
return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
|
||||
}
|
||||
|
||||
static gboolean json_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf,
|
||||
int *err, gchar **err_info)
|
||||
{
|
||||
/* there is only one packet */
|
||||
if (seek_off > 0) {
|
||||
*err = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
|
||||
return FALSE;
|
||||
|
||||
return json_read_file(wth, wth->random_fh, phdr, buf, err, err_info);
|
||||
}
|
||||
|
||||
static gboolean json_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
|
||||
{
|
||||
gint64 offset;
|
||||
|
||||
*err = 0;
|
||||
|
||||
offset = file_tell(wth->fh);
|
||||
|
||||
/* there is only ever one packet */
|
||||
if (offset != 0)
|
||||
return FALSE;
|
||||
|
||||
*data_offset = offset;
|
||||
|
||||
return json_read_file(wth, wth->fh, &wth->phdr, wth->frame_buffer, err, err_info);
|
||||
}
|
||||
|
||||
wtap_open_return_val json_open(wtap *wth, int *err, gchar **err_info _U_)
|
||||
{
|
||||
guint8* filebuf;
|
||||
guint read;
|
||||
|
||||
filebuf = (guint8*)g_malloc0(MAX_FILE_SIZE);
|
||||
if (!filebuf)
|
||||
return WTAP_OPEN_ERROR;
|
||||
|
||||
read = file_read(filebuf, MAX_FILE_SIZE, wth->fh);
|
||||
|
||||
if (jsmn_is_json(filebuf, read) == FALSE) {
|
||||
g_free(filebuf);
|
||||
return WTAP_OPEN_NOT_MINE;
|
||||
}
|
||||
|
||||
if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
|
||||
g_free(filebuf);
|
||||
return WTAP_OPEN_ERROR;
|
||||
}
|
||||
|
||||
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_JSON;
|
||||
wth->file_encap = WTAP_ENCAP_JSON;
|
||||
wth->file_tsprec = WTAP_TSPREC_SEC;
|
||||
wth->subtype_read = json_read;
|
||||
wth->subtype_seek_read = json_seek_read;
|
||||
wth->snapshot_length = 0;
|
||||
|
||||
g_free(filebuf);
|
||||
return WTAP_OPEN_MINE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
55
wiretap/json.h
Normal file
55
wiretap/json.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* json.h
|
||||
*
|
||||
* Copyright 2015, Dario Lombardo <lomato@gmail.com>
|
||||
*
|
||||
* 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 __JSON_H__
|
||||
#define __JSON_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "wtap.h"
|
||||
|
||||
/*
|
||||
* Impose a not-too-large limit on the maximum file size, to avoid eating
|
||||
* up 99% of the (address space, swap partition, disk space for swap/page
|
||||
* files); if we were to return smaller chunks and let the dissector do
|
||||
* reassembly, it would *still* have to allocate a buffer the size of
|
||||
* the file, so it's not as if we'd neve try to allocate a buffer the
|
||||
* size of the file.
|
||||
*
|
||||
* For now, go for 50MB.
|
||||
*/
|
||||
#define MAX_FILE_SIZE (50*1024*1024)
|
||||
|
||||
wtap_open_return_val json_open(wtap *wth, int *err, gchar **err_info);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
@ -740,6 +740,9 @@ static struct encap_type_info encap_table_base[] = {
|
||||
|
||||
/* WTAP_ENCAP_LOOP */
|
||||
{ "OpenBSD loopback", "loop" },
|
||||
|
||||
/* WTAP_ENCAP_JSON */
|
||||
{ "JavaScript Object Notation", "json" }
|
||||
};
|
||||
|
||||
WS_DLL_LOCAL
|
||||
|
@ -266,6 +266,7 @@ extern "C" {
|
||||
#define WTAP_ENCAP_EPON 173
|
||||
#define WTAP_ENCAP_IPMI_TRACE 174
|
||||
#define WTAP_ENCAP_LOOP 175
|
||||
#define WTAP_ENCAP_JSON 176
|
||||
/* After adding new item here, please also add new item to encap_table_base array */
|
||||
|
||||
#define WTAP_NUM_ENCAP_TYPES wtap_get_num_encap_types()
|
||||
@ -352,6 +353,7 @@ extern "C" {
|
||||
#define WTAP_FILE_TYPE_SUBTYPE_LOGCAT_LONG 74
|
||||
#define WTAP_FILE_TYPE_SUBTYPE_COLASOFT_CAPSA 75
|
||||
#define WTAP_FILE_TYPE_SUBTYPE_COLASOFT_PACKET_BUILDER 76
|
||||
#define WTAP_FILE_TYPE_SUBTYPE_JSON 77
|
||||
|
||||
#define WTAP_NUM_FILE_TYPES_SUBTYPES wtap_get_num_file_types_subtypes()
|
||||
|
||||
|
@ -53,6 +53,7 @@ set(WSUTIL_FILES
|
||||
eax.c
|
||||
filesystem.c
|
||||
g711.c
|
||||
jsmn.c
|
||||
md4.c
|
||||
md5.c
|
||||
mpeg-audio.c
|
||||
|
@ -50,6 +50,7 @@ LIBWSUTIL_SRC = \
|
||||
eax.c \
|
||||
filesystem.c \
|
||||
g711.c \
|
||||
jsmn.c \
|
||||
md4.c \
|
||||
md5.c \
|
||||
mpeg-audio.c \
|
||||
@ -98,6 +99,7 @@ libwsutil_nonrepl_INCLUDES = \
|
||||
eax.h \
|
||||
filesystem.h \
|
||||
g711.h \
|
||||
jsmn.h \
|
||||
md4.h \
|
||||
md5.h \
|
||||
mpeg-audio.h \
|
||||
|
387
wsutil/jsmn.c
Normal file
387
wsutil/jsmn.c
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Serge A. Zaitsev
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jsmn.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
/**
|
||||
* Allocates a fresh unused token from the token pull.
|
||||
*/
|
||||
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
|
||||
jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *tok;
|
||||
if (parser->toknext >= num_tokens) {
|
||||
return NULL;
|
||||
}
|
||||
tok = &tokens[parser->toknext++];
|
||||
tok->start = tok->end = -1;
|
||||
tok->size = 0;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
tok->parent = -1;
|
||||
#endif
|
||||
return tok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills token type and boundaries.
|
||||
*/
|
||||
static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
|
||||
int start, int end) {
|
||||
token->type = type;
|
||||
token->start = start;
|
||||
token->end = end;
|
||||
token->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills next available token with JSON primitive.
|
||||
*/
|
||||
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
|
||||
size_t len, jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
int start;
|
||||
|
||||
start = parser->pos;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
switch (js[parser->pos]) {
|
||||
#ifndef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by "," or "}" or "]" */
|
||||
case ':':
|
||||
#endif
|
||||
case '\t' : case '\r' : case '\n' : case ' ' :
|
||||
case ',' : case ']' : case '}' :
|
||||
goto found;
|
||||
}
|
||||
if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by a comma/object/array */
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
#endif
|
||||
|
||||
found:
|
||||
if (tokens == NULL) {
|
||||
parser->pos--;
|
||||
return 0;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
parser->pos--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filsl next token with JSON string.
|
||||
*/
|
||||
static int jsmn_parse_string(jsmn_parser *parser, const char *js,
|
||||
size_t len, jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
|
||||
int start = parser->pos;
|
||||
|
||||
parser->pos++;
|
||||
|
||||
/* Skip starting quote */
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c = js[parser->pos];
|
||||
|
||||
/* Quote: end of string */
|
||||
if (c == '\"') {
|
||||
if (tokens == NULL) {
|
||||
return 0;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Backslash: Quoted symbol expected */
|
||||
if (c == '\\' && parser->pos + 1 < len) {
|
||||
int i;
|
||||
parser->pos++;
|
||||
switch (js[parser->pos]) {
|
||||
/* Allowed escaped symbols */
|
||||
case '\"': case '/' : case '\\' : case 'b' :
|
||||
case 'f' : case 'r' : case 'n' : case 't' :
|
||||
break;
|
||||
/* Allows escaped symbol \uXXXX */
|
||||
case 'u':
|
||||
parser->pos++;
|
||||
for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
|
||||
/* If it isn't a hex character we have an error */
|
||||
if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
|
||||
(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
|
||||
(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
parser->pos++;
|
||||
}
|
||||
parser->pos--;
|
||||
break;
|
||||
/* Unexpected symbol */
|
||||
default:
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON string and fill tokens.
|
||||
*/
|
||||
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
jsmntok_t *tokens, unsigned int num_tokens) {
|
||||
int r;
|
||||
int i;
|
||||
jsmntok_t *token;
|
||||
int count = 0;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c;
|
||||
jsmntype_t type;
|
||||
|
||||
c = js[parser->pos];
|
||||
switch (c) {
|
||||
case '{': case '[':
|
||||
count++;
|
||||
if (tokens == NULL) {
|
||||
break;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL)
|
||||
return JSMN_ERROR_NOMEM;
|
||||
if (parser->toksuper != -1) {
|
||||
tokens[parser->toksuper].size++;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
}
|
||||
token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
token->start = parser->pos;
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case '}': case ']':
|
||||
if (tokens == NULL)
|
||||
break;
|
||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
if (parser->toknext < 1) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token = &tokens[parser->toknext - 1];
|
||||
for (;;) {
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token->end = parser->pos + 1;
|
||||
parser->toksuper = token->parent;
|
||||
break;
|
||||
}
|
||||
if (token->parent == -1) {
|
||||
break;
|
||||
}
|
||||
token = &tokens[token->parent];
|
||||
}
|
||||
#else
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
parser->toksuper = -1;
|
||||
token->end = parser->pos + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Error if unmatched closing bracket */
|
||||
if (i == -1) return JSMN_ERROR_INVAL;
|
||||
for (; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
parser->toksuper = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case '\"':
|
||||
r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
|
||||
if (r < 0) return r;
|
||||
count++;
|
||||
if (parser->toksuper != -1 && tokens != NULL)
|
||||
tokens[parser->toksuper].size++;
|
||||
break;
|
||||
case '\t' : case '\r' : case '\n' : case ' ':
|
||||
break;
|
||||
case ':':
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case ',':
|
||||
if (tokens != NULL && parser->toksuper != -1 &&
|
||||
tokens[parser->toksuper].type != JSMN_ARRAY &&
|
||||
tokens[parser->toksuper].type != JSMN_OBJECT) {
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
parser->toksuper = tokens[parser->toksuper].parent;
|
||||
#else
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
|
||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
||||
parser->toksuper = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitives are: numbers and booleans */
|
||||
case '-': case '0': case '1' : case '2': case '3' : case '4':
|
||||
case '5': case '6': case '7' : case '8': case '9':
|
||||
case 't': case 'f': case 'n' :
|
||||
/* And they must not be keys of the object */
|
||||
if (tokens != NULL && parser->toksuper != -1) {
|
||||
jsmntok_t *t = &tokens[parser->toksuper];
|
||||
if (t->type == JSMN_OBJECT ||
|
||||
(t->type == JSMN_STRING && t->size != 0)) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* In non-strict mode every unquoted value is a primitive */
|
||||
default:
|
||||
#endif
|
||||
r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
|
||||
if (r < 0) return r;
|
||||
count++;
|
||||
if (parser->toksuper != -1 && tokens != NULL)
|
||||
tokens[parser->toksuper].size++;
|
||||
break;
|
||||
|
||||
#ifdef JSMN_STRICT
|
||||
/* Unexpected char in strict mode */
|
||||
default:
|
||||
return JSMN_ERROR_INVAL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
/* Unmatched opened object or array */
|
||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new parser based over a given buffer with an array of tokens
|
||||
* available.
|
||||
*/
|
||||
void jsmn_init(jsmn_parser *parser) {
|
||||
parser->pos = 0;
|
||||
parser->toknext = 0;
|
||||
parser->toksuper = -1;
|
||||
}
|
||||
|
||||
gboolean jsmn_is_json(const guint8* buf, const size_t len)
|
||||
{
|
||||
/* We expect no more than 1024 tokens */
|
||||
guint max_tokens = 1024;
|
||||
jsmntok_t* t;
|
||||
jsmn_parser p;
|
||||
gboolean ret = TRUE;
|
||||
int rcode;
|
||||
|
||||
t = g_new0(jsmntok_t, max_tokens);
|
||||
|
||||
if (!t)
|
||||
return FALSE;
|
||||
|
||||
jsmn_init(&p);
|
||||
rcode = jsmn_parse(&p, buf, len, t, max_tokens);
|
||||
if (rcode < 0) {
|
||||
switch (rcode) {
|
||||
case JSMN_ERROR_NOMEM:
|
||||
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "jsmn: not enough tokens were provided");
|
||||
break;
|
||||
case JSMN_ERROR_INVAL:
|
||||
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "jsmn: invalid character inside JSON string");
|
||||
break;
|
||||
case JSMN_ERROR_PART:
|
||||
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "jsmn: the string is not a full JSON packet, "
|
||||
"more bytes expected");
|
||||
break;
|
||||
default:
|
||||
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "jsmn: unexpected error");
|
||||
break;
|
||||
}
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
g_free(t);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=4 noexpandtab:
|
||||
* :indentSize=4:tabSize=4:noTabs=false:
|
||||
*/
|
@ -25,6 +25,9 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <ws_symbol_export.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -37,19 +40,19 @@ extern "C" {
|
||||
* o Other primitive: number, boolean (true/false) or null
|
||||
*/
|
||||
typedef enum {
|
||||
JSMN_PRIMITIVE = 0,
|
||||
JSMN_OBJECT = 1,
|
||||
JSMN_ARRAY = 2,
|
||||
JSMN_STRING = 3
|
||||
JSMN_PRIMITIVE = 0,
|
||||
JSMN_OBJECT = 1,
|
||||
JSMN_ARRAY = 2,
|
||||
JSMN_STRING = 3
|
||||
} jsmntype_t;
|
||||
|
||||
typedef enum {
|
||||
/* Not enough tokens were provided */
|
||||
JSMN_ERROR_NOMEM = -1,
|
||||
/* Invalid character inside JSON string */
|
||||
JSMN_ERROR_INVAL = -2,
|
||||
/* The string is not a full JSON packet, more bytes expected */
|
||||
JSMN_ERROR_PART = -3
|
||||
/* Not enough tokens were provided */
|
||||
JSMN_ERROR_NOMEM = -1,
|
||||
/* Invalid character inside JSON string */
|
||||
JSMN_ERROR_INVAL = -2,
|
||||
/* The string is not a full JSON packet, more bytes expected */
|
||||
JSMN_ERROR_PART = -3
|
||||
} jsmnerr_t;
|
||||
|
||||
/**
|
||||
@ -60,12 +63,12 @@ typedef enum {
|
||||
* size the size of the token
|
||||
*/
|
||||
typedef struct {
|
||||
jsmntype_t type;
|
||||
int start;
|
||||
int end;
|
||||
int size;
|
||||
jsmntype_t type;
|
||||
int start;
|
||||
int end;
|
||||
int size;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
int parent;
|
||||
int parent;
|
||||
#endif
|
||||
} jsmntok_t;
|
||||
|
||||
@ -74,22 +77,27 @@ typedef struct {
|
||||
* the string being parsed now and current position in that string
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int pos; /* offset in the JSON string */
|
||||
unsigned int toknext; /* next token to allocate */
|
||||
int toksuper; /* superior token node, e.g parent object or array */
|
||||
unsigned int pos; /* offset in the JSON string */
|
||||
unsigned int toknext; /* next token to allocate */
|
||||
int toksuper; /* superior token node, e.g parent object or array */
|
||||
} jsmn_parser;
|
||||
|
||||
/**
|
||||
* Create JSON parser over an array of tokens
|
||||
*/
|
||||
void jsmn_init(jsmn_parser *parser);
|
||||
WS_DLL_PUBLIC void jsmn_init(jsmn_parser *parser);
|
||||
|
||||
/**
|
||||
* Run JSON parser. It parses a JSON data string into and array of tokens, each describing
|
||||
* a single JSON object.
|
||||
*/
|
||||
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
jsmntok_t *tokens, unsigned int num_tokens);
|
||||
jsmntok_t *tokens, unsigned int num_tokens);
|
||||
|
||||
/**
|
||||
* Check if a buffer is json an returns true if it is.
|
||||
*/
|
||||
WS_DLL_PUBLIC gboolean jsmn_is_json(const guint8* buf, const size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@ -102,10 +110,10 @@ int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=9:noTabs=true:
|
||||
* vi: set shiftwidth=4 tabstop=4 noexpandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=false:
|
||||
*/
|
Loading…
x
Reference in New Issue
Block a user