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:
Dario Lombardo 2015-01-19 19:54:41 +01:00 committed by Pascal Quantin
parent 1478db03d5
commit bd911096bd
20 changed files with 662 additions and 559 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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:
#

View File

@ -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:
#

View File

@ -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:
#

View File

@ -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:
*/

View File

@ -46,6 +46,7 @@ set(CLEAN_FILES
ipfix.c
iptrace.c
iseries.c
json.c
k12.c
lanalyzer.c
libpcap.c

View File

@ -52,6 +52,7 @@ NONGENERATED_C_FILES = \
iptrace.c \
iseries.c \
mime_file.c \
json.c \
k12.c \
lanalyzer.c \
logcat_text.c \

View File

@ -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
View 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
View 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:
*/

View File

@ -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

View File

@ -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()

View File

@ -53,6 +53,7 @@ set(WSUTIL_FILES
eax.c
filesystem.c
g711.c
jsmn.c
md4.c
md5.c
mpeg-audio.c

View File

@ -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
View 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:
*/

View File

@ -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:
*/