summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--epan/CMakeLists.txt14
-rw-r--r--epan/Makefile.am6
-rw-r--r--epan/Makefile.nmake24
-rw-r--r--epan/dissectors/packet-json.c32
-rw-r--r--epan/jsmn/Makefile.am63
-rw-r--r--epan/jsmn/Makefile.common38
-rw-r--r--epan/jsmn/Makefile.nmake44
-rw-r--r--epan/jsmn/jsmn.c345
-rw-r--r--wiretap/CMakeLists.txt1
-rw-r--r--wiretap/Makefile.common1
-rw-r--r--wiretap/file_access.c8
-rw-r--r--wiretap/json.c138
-rw-r--r--wiretap/json.h55
-rw-r--r--wiretap/wtap.c3
-rw-r--r--wiretap/wtap.h2
-rw-r--r--wsutil/CMakeLists.txt1
-rw-r--r--wsutil/Makefile.common2
-rw-r--r--wsutil/jsmn.c387
-rw-r--r--wsutil/jsmn.h (renamed from epan/jsmn/jsmn.h)56
20 files changed, 662 insertions, 559 deletions
diff --git a/configure.ac b/configure.ac
index 4b7db7e165..dd0b50234b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index bdc988ca53..371f623eea 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -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
diff --git a/epan/Makefile.am b/epan/Makefile.am
index cbbfac3ef4..ac19b3f7a1 100644
--- a/epan/Makefile.am
+++ b/epan/Makefile.am
@@ -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
diff --git a/epan/Makefile.nmake b/epan/Makefile.nmake
index 47d5bcca4b..f0ad957250 100644
--- a/epan/Makefile.nmake
+++ b/epan/Makefile.nmake
@@ -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
diff --git a/epan/dissectors/packet-json.c b/epan/dissectors/packet-json.c
index 745ef7076f..4451b7de03 100644
--- a/epan/dissectors/packet-json.c
+++ b/epan/dissectors/packet-json.c
@@ -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 */
diff --git a/epan/jsmn/Makefile.am b/epan/jsmn/Makefile.am
deleted file mode 100644
index 60e824e8aa..0000000000
--- a/epan/jsmn/Makefile.am
+++ /dev/null
@@ -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:
-#
diff --git a/epan/jsmn/Makefile.common b/epan/jsmn/Makefile.common
deleted file mode 100644
index 1e9548f3b8..0000000000
--- a/epan/jsmn/Makefile.common
+++ /dev/null
@@ -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:
-#
diff --git a/epan/jsmn/Makefile.nmake b/epan/jsmn/Makefile.nmake
deleted file mode 100644
index f657ea5f6d..0000000000
--- a/epan/jsmn/Makefile.nmake
+++ /dev/null
@@ -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:
-#
diff --git a/epan/jsmn/jsmn.c b/epan/jsmn/jsmn.c
deleted file mode 100644
index 30014239ea..0000000000
--- a/epan/jsmn/jsmn.c
+++ /dev/null
@@ -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:
- */
diff --git a/wiretap/CMakeLists.txt b/wiretap/CMakeLists.txt
index 1e7ead3ad8..52b3738320 100644
--- a/wiretap/CMakeLists.txt
+++ b/wiretap/CMakeLists.txt
@@ -46,6 +46,7 @@ set(CLEAN_FILES
ipfix.c
iptrace.c
iseries.c
+ json.c
k12.c
lanalyzer.c
libpcap.c
diff --git a/wiretap/Makefile.common b/wiretap/Makefile.common
index f1f30b0352..9bd64db3d4 100644
--- a/wiretap/Makefile.common
+++ b/wiretap/Makefile.common
@@ -52,6 +52,7 @@ NONGENERATED_C_FILES = \
iptrace.c \
iseries.c \
mime_file.c \
+ json.c \
k12.c \
lanalyzer.c \
logcat_text.c \
diff --git a/wiretap/file_access.c b/wiretap/file_access.c
index 9006e4862c..898f17e078 100644
--- a/wiretap/file_access.c
+++ b/wiretap/file_access.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,
diff --git a/wiretap/json.c b/wiretap/json.c
new file mode 100644
index 0000000000..9e81f2e56d
--- /dev/null
+++ b/wiretap/json.c
@@ -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:
+ */
diff --git a/wiretap/json.h b/wiretap/json.h
new file mode 100644
index 0000000000..8c233cb771
--- /dev/null
+++ b/wiretap/json.h
@@ -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:
+ */
diff --git a/wiretap/wtap.c b/wiretap/wtap.c
index 6b0cf92610..4de71ee723 100644
--- a/wiretap/wtap.c
+++ b/wiretap/wtap.c
@@ -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
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index 1570466579..f5aaebfa61 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -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()
diff --git a/wsutil/CMakeLists.txt b/wsutil/CMakeLists.txt
index c7e8138efc..fe2d662eac 100644
--- a/wsutil/CMakeLists.txt
+++ b/wsutil/CMakeLists.txt
@@ -53,6 +53,7 @@ set(WSUTIL_FILES
eax.c
filesystem.c
g711.c
+ jsmn.c
md4.c
md5.c
mpeg-audio.c
diff --git a/wsutil/Makefile.common b/wsutil/Makefile.common
index aa050da5de..5385c8a7a9 100644
--- a/wsutil/Makefile.common
+++ b/wsutil/Makefile.common
@@ -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 \
diff --git a/wsutil/jsmn.c b/wsutil/jsmn.c
new file mode 100644
index 0000000000..834e4b1ee9
--- /dev/null
+++ b/wsutil/jsmn.c
@@ -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:
+ */
diff --git a/epan/jsmn/jsmn.h b/wsutil/jsmn.h
index 458e7d447b..e4817dac5b 100644
--- a/epan/jsmn/jsmn.h
+++ b/wsutil/jsmn.h
@@ -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:
*/