1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 **/
19 
20 #include "common.h"
21 #include "zbxjson.h"
22 #include "json_parser.h"
23 
24 /******************************************************************************
25  *                                                                            *
26  * Function: zbx_json_strerror                                                *
27  *                                                                            *
28  * Purpose: return string describing json error                               *
29  *                                                                            *
30  * Return value: pointer to the null terminated string                        *
31  *                                                                            *
32  * Author: Eugene Grigorjev                                                   *
33  *                                                                            *
34  ******************************************************************************/
35 #define ZBX_JSON_MAX_STRERROR	255
36 
37 static char	zbx_json_strerror_message[ZBX_JSON_MAX_STRERROR];
38 
zbx_json_strerror(void)39 const char	*zbx_json_strerror(void)
40 {
41 	return zbx_json_strerror_message;
42 }
43 
44 #ifdef HAVE___VA_ARGS__
45 #	define zbx_set_json_strerror(fmt, ...) __zbx_zbx_set_json_strerror(ZBX_CONST_STRING(fmt), ##__VA_ARGS__)
46 #else
47 #	define zbx_set_json_strerror __zbx_zbx_set_json_strerror
48 #endif
__zbx_zbx_set_json_strerror(const char * fmt,...)49 static void	__zbx_zbx_set_json_strerror(const char *fmt, ...)
50 {
51 	va_list	args;
52 
53 	va_start(args, fmt);
54 
55 	zbx_vsnprintf(zbx_json_strerror_message, sizeof(zbx_json_strerror_message), fmt, args);
56 
57 	va_end(args);
58 }
59 
60 /******************************************************************************
61  *                                                                            *
62  * Function: __zbx_json_realloc                                               *
63  *                                                                            *
64  * Author: Alexander Vladishev                                                *
65  *                                                                            *
66  ******************************************************************************/
__zbx_json_realloc(struct zbx_json * j,size_t need)67 static void	__zbx_json_realloc(struct zbx_json *j, size_t need)
68 {
69 	int	realloc = 0;
70 
71 	if (NULL == j->buffer)
72 	{
73 		if (need > sizeof(j->buf_stat))
74 		{
75 			j->buffer_allocated = need;
76 			j->buffer = zbx_malloc(j->buffer, j->buffer_allocated);
77 		}
78 		else
79 		{
80 			j->buffer_allocated = sizeof(j->buf_stat);
81 			j->buffer = j->buf_stat;
82 		}
83 		return;
84 	}
85 
86 	while (need > j->buffer_allocated)
87 	{
88 		if (0 == j->buffer_allocated)
89 			j->buffer_allocated = 1024;
90 		else
91 			j->buffer_allocated *= 2;
92 		realloc = 1;
93 	}
94 
95 	if (1 == realloc)
96 	{
97 		if (j->buffer == j->buf_stat)
98 		{
99 			j->buffer = NULL;
100 			j->buffer = zbx_malloc(j->buffer, j->buffer_allocated);
101 			memcpy(j->buffer, j->buf_stat, sizeof(j->buf_stat));
102 		}
103 		else
104 			j->buffer = zbx_realloc(j->buffer, j->buffer_allocated);
105 	}
106 }
107 
zbx_json_init(struct zbx_json * j,size_t allocate)108 void	zbx_json_init(struct zbx_json *j, size_t allocate)
109 {
110 	assert(j);
111 
112 	j->buffer = NULL;
113 	j->buffer_allocated = 0;
114 	j->buffer_offset = 0;
115 	j->buffer_size = 0;
116 	j->status = ZBX_JSON_EMPTY;
117 	j->level = 0;
118 	__zbx_json_realloc(j, allocate);
119 	*j->buffer = '\0';
120 
121 	zbx_json_addobject(j, NULL);
122 }
123 
zbx_json_clean(struct zbx_json * j)124 void	zbx_json_clean(struct zbx_json *j)
125 {
126 	assert(j);
127 
128 	j->buffer_offset = 0;
129 	j->buffer_size = 0;
130 	j->status = ZBX_JSON_EMPTY;
131 	j->level = 0;
132 	*j->buffer = '\0';
133 
134 	zbx_json_addobject(j, NULL);
135 }
136 
zbx_json_free(struct zbx_json * j)137 void	zbx_json_free(struct zbx_json *j)
138 {
139 	assert(j);
140 
141 	if (j->buffer != j->buf_stat)
142 		zbx_free(j->buffer);
143 }
144 
__zbx_json_stringsize(const char * string,zbx_json_type_t type)145 static size_t	__zbx_json_stringsize(const char *string, zbx_json_type_t type)
146 {
147 	size_t		len = 0;
148 	const char	*sptr;
149 	char		buffer[] = {"null"};
150 
151 	for (sptr = (NULL != string ? string : buffer); '\0' != *sptr; sptr++)
152 	{
153 		switch (*sptr)
154 		{
155 			case '"':  /* quotation mark */
156 			case '\\': /* reverse solidus */
157 			/* We do not escape '/' (solidus). https://www.rfc-editor.org/errata_search.php?rfc=4627 */
158 			/* says: "/" and "\/" are both allowed and both produce the same result. */
159 			case '\b': /* backspace */
160 			case '\f': /* formfeed */
161 			case '\n': /* newline */
162 			case '\r': /* carriage return */
163 			case '\t': /* horizontal tab */
164 				len += 2;
165 				break;
166 			default:
167 				/* RFC 8259 requires escaping control characters U+0000 - U+001F */
168 				if (0x1f >= (unsigned char)*sptr)
169 					len += 6;
170 				else
171 					len++;
172 		}
173 	}
174 
175 	if (NULL != string && ZBX_JSON_TYPE_STRING == type)
176 		len += 2; /* "" */
177 
178 	return len;
179 }
180 
__zbx_json_insstring(char * p,const char * string,zbx_json_type_t type)181 static char	*__zbx_json_insstring(char *p, const char *string, zbx_json_type_t type)
182 {
183 	const char	*sptr;
184 	char		buffer[] = {"null"};
185 
186 	if (NULL != string && ZBX_JSON_TYPE_STRING == type)
187 		*p++ = '"';
188 
189 	for (sptr = (NULL != string ? string : buffer); '\0' != *sptr; sptr++)
190 	{
191 		switch (*sptr)
192 		{
193 			case '"':		/* quotation mark */
194 				*p++ = '\\';
195 				*p++ = '"';
196 				break;
197 			case '\\':		/* reverse solidus */
198 				*p++ = '\\';
199 				*p++ = '\\';
200 				break;
201 			/* We do not escape '/' (solidus). https://www.rfc-editor.org/errata_search.php?rfc=4627 */
202 			/* says: "/" and "\/" are both allowed and both produce the same result. */
203 			case '\b':		/* backspace */
204 				*p++ = '\\';
205 				*p++ = 'b';
206 				break;
207 			case '\f':		/* formfeed */
208 				*p++ = '\\';
209 				*p++ = 'f';
210 				break;
211 			case '\n':		/* newline */
212 				*p++ = '\\';
213 				*p++ = 'n';
214 				break;
215 			case '\r':		/* carriage return */
216 				*p++ = '\\';
217 				*p++ = 'r';
218 				break;
219 			case '\t':		/* horizontal tab */
220 				*p++ = '\\';
221 				*p++ = 't';
222 				break;
223 			default:
224 				/* RFC 8259 requires escaping control characters U+0000 - U+001F */
225 				if (0x1f >= (unsigned char)*sptr)
226 				{
227 					*p++ = '\\';
228 					*p++ = 'u';
229 					*p++ = '0';
230 					*p++ = '0';
231 					*p++ = zbx_num2hex((((unsigned char)*sptr) >> 4) & 0xf);
232 					*p++ = zbx_num2hex(((unsigned char)*sptr) & 0xf);
233 				}
234 				else
235 					*p++ = *sptr;
236 		}
237 	}
238 
239 	if (NULL != string && ZBX_JSON_TYPE_STRING == type)
240 		*p++ = '"';
241 
242 	return p;
243 }
244 
__zbx_json_addobject(struct zbx_json * j,const char * name,int object)245 static void	__zbx_json_addobject(struct zbx_json *j, const char *name, int object)
246 {
247 	size_t	len = 2; /* brackets */
248 	char	*p, *psrc, *pdst;
249 
250 	assert(j);
251 
252 	if (ZBX_JSON_COMMA == j->status)
253 		len++; /* , */
254 
255 	if (NULL != name)
256 	{
257 		len += __zbx_json_stringsize(name, ZBX_JSON_TYPE_STRING);
258 		len += 1; /* : */
259 	}
260 
261 	__zbx_json_realloc(j, j->buffer_size + len + 1/*'\0'*/);
262 
263 	psrc = j->buffer + j->buffer_offset;
264 	pdst = j->buffer + j->buffer_offset + len;
265 
266 	memmove(pdst, psrc, j->buffer_size - j->buffer_offset + 1/*'\0'*/);
267 
268 	p = psrc;
269 
270 	if (ZBX_JSON_COMMA == j->status)
271 		*p++ = ',';
272 
273 	if (NULL != name)
274 	{
275 		p = __zbx_json_insstring(p, name, ZBX_JSON_TYPE_STRING);
276 		*p++ = ':';
277 	}
278 
279 	*p++ = object ? '{' : '[';
280 	*p = object ? '}' : ']';
281 
282 	j->buffer_offset = p - j->buffer;
283 	j->buffer_size += len;
284 	j->level++;
285 	j->status = ZBX_JSON_EMPTY;
286 }
287 
zbx_json_addobject(struct zbx_json * j,const char * name)288 void	zbx_json_addobject(struct zbx_json *j, const char *name)
289 {
290 	__zbx_json_addobject(j, name, 1);
291 }
292 
zbx_json_addarray(struct zbx_json * j,const char * name)293 void	zbx_json_addarray(struct zbx_json *j, const char *name)
294 {
295 	__zbx_json_addobject(j, name, 0);
296 }
297 
zbx_json_addstring(struct zbx_json * j,const char * name,const char * string,zbx_json_type_t type)298 void	zbx_json_addstring(struct zbx_json *j, const char *name, const char *string, zbx_json_type_t type)
299 {
300 	size_t	len = 0;
301 	char	*p, *psrc, *pdst;
302 
303 	assert(j);
304 
305 	if (ZBX_JSON_COMMA == j->status)
306 		len++; /* , */
307 
308 	if (NULL != name)
309 	{
310 		len += __zbx_json_stringsize(name, ZBX_JSON_TYPE_STRING);
311 		len += 1; /* : */
312 	}
313 	len += __zbx_json_stringsize(string, type);
314 
315 	__zbx_json_realloc(j, j->buffer_size + len + 1/*'\0'*/);
316 
317 	psrc = j->buffer + j->buffer_offset;
318 	pdst = j->buffer + j->buffer_offset + len;
319 
320 	memmove(pdst, psrc, j->buffer_size - j->buffer_offset + 1/*'\0'*/);
321 
322 	p = psrc;
323 
324 	if (ZBX_JSON_COMMA == j->status)
325 		*p++ = ',';
326 
327 	if (NULL != name)
328 	{
329 		p = __zbx_json_insstring(p, name, ZBX_JSON_TYPE_STRING);
330 		*p++ = ':';
331 	}
332 	p = __zbx_json_insstring(p, string, type);
333 
334 	j->buffer_offset = p - j->buffer;
335 	j->buffer_size += len;
336 	j->status = ZBX_JSON_COMMA;
337 }
338 
zbx_json_adduint64(struct zbx_json * j,const char * name,zbx_uint64_t value)339 void	zbx_json_adduint64(struct zbx_json *j, const char *name, zbx_uint64_t value)
340 {
341 	char	buffer[MAX_ID_LEN];
342 
343 	zbx_snprintf(buffer, sizeof(buffer), ZBX_FS_UI64, value);
344 	zbx_json_addstring(j, name, buffer, ZBX_JSON_TYPE_INT);
345 }
346 
zbx_json_close(struct zbx_json * j)347 int	zbx_json_close(struct zbx_json *j)
348 {
349 	if (1 == j->level)
350 	{
351 		zbx_set_json_strerror("cannot close top level object");
352 		return FAIL;
353 	}
354 
355 	j->level--;
356 	j->buffer_offset++;
357 	j->status = ZBX_JSON_COMMA;
358 
359 	return SUCCEED;
360 }
361 
362 /******************************************************************************
363  *                                                                            *
364  * Function: __zbx_json_type                                                  *
365  *                                                                            *
366  * Purpose: return type of pointed value                                      *
367  *                                                                            *
368  * Return value: type of pointed value                                        *
369  *                                                                            *
370  * Author: Alexander Vladishev                                                *
371  *                                                                            *
372  ******************************************************************************/
__zbx_json_type(const char * p)373 static zbx_json_type_t	__zbx_json_type(const char *p)
374 {
375 	if ('"' == *p)
376 		return ZBX_JSON_TYPE_STRING;
377 	if (('0' <= *p && *p <= '9') || '-' == *p)
378 		return ZBX_JSON_TYPE_INT;
379 	if ('[' == *p)
380 		return ZBX_JSON_TYPE_ARRAY;
381 	if ('{' == *p)
382 		return ZBX_JSON_TYPE_OBJECT;
383 	if ('n' == p[0] && 'u' == p[1] && 'l' == p[2] && 'l' == p[3])
384 		return ZBX_JSON_TYPE_NULL;
385 
386 	zbx_set_json_strerror("Invalid type of JSON value \"%.64s\"", p);
387 
388 	return ZBX_JSON_TYPE_UNKNOWN;
389 }
390 
391 /******************************************************************************
392  *                                                                            *
393  * Function: __zbx_json_rbracket                                              *
394  *                                                                            *
395  * Purpose: return position of right bracket                                  *
396  *                                                                            *
397  * Return value: position of right bracket                                    *
398  *               NULL - an error occurred                                     *
399  *                                                                            *
400  * Author: Alexander Vladishev                                                *
401  *                                                                            *
402  ******************************************************************************/
__zbx_json_rbracket(const char * p)403 static const char	*__zbx_json_rbracket(const char *p)
404 {
405 	int	level = 0;
406 	int	state = 0; /* 0 - outside string; 1 - inside string */
407 	char	lbracket, rbracket;
408 
409 	assert(p);
410 
411 	lbracket = *p;
412 
413 	if ('{' != lbracket && '[' != lbracket)
414 		return NULL;
415 
416 	rbracket = ('{' == lbracket ? '}' : ']');
417 
418 	while ('\0' != *p)
419 	{
420 		switch (*p)
421 		{
422 			case '"':
423 				state = (0 == state ? 1 : 0);
424 				break;
425 			case '\\':
426 				if (1 == state)
427 					if ('\0' == *++p)
428 						return NULL;
429 				break;
430 			case '[':
431 			case '{':
432 				if (0 == state)
433 					level++;
434 				break;
435 			case ']':
436 			case '}':
437 				if (0 == state)
438 				{
439 					level--;
440 					if (0 == level)
441 						return (rbracket == *p ? p : NULL);
442 				}
443 				break;
444 		}
445 		p++;
446 	}
447 
448 	return NULL;
449 }
450 
451 /******************************************************************************
452  *                                                                            *
453  * Function: zbx_json_open                                                    *
454  *                                                                            *
455  * Purpose: open json buffer and check for brackets                           *
456  *                                                                            *
457  * Return value: SUCCESS - processed successfully                             *
458  *               FAIL - an error occurred                                     *
459  *                                                                            *
460  ******************************************************************************/
zbx_json_open(const char * buffer,struct zbx_json_parse * jp)461 int	zbx_json_open(const char *buffer, struct zbx_json_parse *jp)
462 {
463 	char	*error = NULL;
464 	int	len;
465 
466 	SKIP_WHITESPACE(buffer);
467 
468 	/* return immediate failure without logging when opening empty string */
469 	if ('\0' == *buffer)
470 		return FAIL;
471 
472 	jp->start = buffer;
473 	jp->end = NULL;
474 
475 	if (0 == (len = zbx_json_validate(jp->start, &error)))
476 	{
477 		if (NULL != error)
478 		{
479 			zbx_set_json_strerror("cannot parse as a valid JSON object: %s", error);
480 			zbx_free(error);
481 		}
482 		else
483 			zbx_set_json_strerror("cannot parse as a valid JSON object \"%.64s\"", buffer);
484 
485 		return FAIL;
486 	}
487 	jp->end = jp->start + len - 1;
488 
489 	return SUCCEED;
490 }
491 
492 /******************************************************************************
493  *                                                                            *
494  * Function: zbx_json_next                                                    *
495  *                                                                            *
496  * Purpose: locate next pair or element                                       *
497  *                                                                            *
498  * Return value: NULL - no more values                                        *
499  *               NOT NULL - pointer to pair or element                        *
500  *      {"name",...    or  "array":["name", ... ,1,null]                      *
501  * p =   ^                                         ^                          *
502  *                                                                            *
503  * Author: Alexander Vladishev                                                *
504  *                                                                            *
505  ******************************************************************************/
zbx_json_next(const struct zbx_json_parse * jp,const char * p)506 const char	*zbx_json_next(const struct zbx_json_parse *jp, const char *p)
507 {
508 	int	level = 0;
509 	int	state = 0;	/* 0 - outside string; 1 - inside string */
510 
511 	if (1 == jp->end - jp->start)	/* empty object or array */
512 		return NULL;
513 
514 	if (NULL == p)
515 	{
516 		p = jp->start + 1;
517 		SKIP_WHITESPACE(p);
518 		return p;
519 	}
520 
521 	while (p <= jp->end)
522 	{
523 		switch (*p)
524 		{
525 			case '"':
526 				state = (0 == state) ? 1 : 0;
527 				break;
528 			case '\\':
529 				if (1 == state)
530 					p++;
531 				break;
532 			case '[':
533 			case '{':
534 				if (0 == state)
535 					level++;
536 				break;
537 			case ']':
538 			case '}':
539 				if (0 == state)
540 				{
541 					if (0 == level)
542 						return NULL;
543 					level--;
544 				}
545 				break;
546 			case ',':
547 				if (0 == state && 0 == level)
548 				{
549 					p++;
550 					SKIP_WHITESPACE(p);
551 					return p;
552 				}
553 				break;
554 		}
555 		p++;
556 	}
557 
558 	return NULL;
559 }
560 
zbx_json_decodenull(const char * p)561 static const char	*zbx_json_decodenull(const char *p)
562 {
563 	if ('n' == p[0] && 'u' == p[1] && 'l' == p[2] && 'l' == p[3])
564 		return p + 4;
565 
566 	return NULL;
567 }
568 
569 /******************************************************************************
570  *                                                                            *
571  * Function: zbx_json_decode_character                                        *
572  *                                                                            *
573  * Purpose: decodes escape character                                          *
574  *                                                                            *
575  * Parameters: p - [IN/OUT] a pointer to the next character in string         *
576  *                                                                            *
577  * Return value: 0 - invalid escape character                                 *
578  *               !0 - the escaped character                                   *
579  *                                                                            *
580  ******************************************************************************/
zbx_json_decode_character(const char ** p)581 static char	zbx_json_decode_character(const char **p)
582 {
583 	char	out;
584 
585 	switch (*(++*p))
586 	{
587 		case '"':
588 			out = '"';
589 			break;
590 		case '\\':
591 			out = '\\';
592 			break;
593 		case '/':
594 			out = '/';
595 			break;
596 		case 'b':
597 			out = '\b';
598 			break;
599 		case 'f':
600 			out = '\f';
601 			break;
602 		case 'n':
603 			out = '\n';
604 			break;
605 		case 'r':
606 			out = '\r';
607 			break;
608 		case 't':
609 			out = '\t';
610 			break;
611 		case 'u':
612 			*p += 3; /* "u00" */
613 			out = zbx_hex2num(**p) << 4;
614 			out += zbx_hex2num(*(++*p));
615 			break;
616 		default:
617 			THIS_SHOULD_NEVER_HAPPEN;
618 			return '\0';
619 	}
620 
621 	++*p;
622 
623 	return out;
624 }
625 
626 /******************************************************************************
627  *                                                                            *
628  * Function: zbx_json_copy_string                                             *
629  *                                                                            *
630  * Purpose: copies json name/string value by omitting leading/trailing " and  *
631  *          converting escape sequences                                       *
632  *                                                                            *
633  * Parameters: p     - [IN] a pointer to the next character in string         *
634  *             out   - [OUT] the output buffer                                *
635  *             size  - [IN] the output buffer size                            *
636  *                                                                            *
637  * Return value: A pointer to the next character in input string or NULL if   *
638  *               string copying failed.                                       *
639  *                                                                            *
640  ******************************************************************************/
zbx_json_copy_string(const char * p,char * out,size_t size)641 static const char	*zbx_json_copy_string(const char *p, char *out, size_t size)
642 {
643 	char	*start = out;
644 
645 	p++;
646 
647 	while ('\0' != *p)
648 	{
649 		switch (*p)
650 		{
651 			case '\\':
652 				if ('\0' != (*out = zbx_json_decode_character(&p)))
653 					out++;
654 				break;
655 			case '"':
656 				*out = '\0';
657 				return ++p;
658 			default:
659 				*out++ = *p++;
660 		}
661 
662 		if ((size_t)(out - start) == size)
663 			break;
664 	}
665 
666 	return NULL;
667 }
668 
669 /******************************************************************************
670  *                                                                            *
671  * Function: zbx_json_copy_value                                              *
672  *                                                                            *
673  * Purpose: copies json value                                                 *
674  *                                                                            *
675  * Parameters: p     - [IN] a pointer to the next character in string         *
676  *             len   - [IN] the value length                                  *
677  *             out   - [OUT] the output buffer                                *
678  *             size  - [IN] the output buffer size                            *
679  *                                                                            *
680  * Return value: A pointer to the next character in input string or NULL if   *
681  *               string copying failed.                                       *
682  *                                                                            *
683  * Comments: String values are converted (leading/trailing " dropped and      *
684  *           escape sequences translated) while other values are simply       *
685  *           copied.                                                          *
686  *                                                                            *
687  ******************************************************************************/
zbx_json_copy_value(const char * p,size_t len,char * out,size_t size)688 static const char	*zbx_json_copy_value(const char *p, size_t len, char *out, size_t size)
689 {
690 	if (ZBX_JSON_TYPE_STRING == __zbx_json_type(p))
691 	{
692 		if (NULL == zbx_json_copy_string(p, out, size))
693 			return NULL;
694 	}
695 	else
696 		zbx_strlcpy(out, p, MIN(size, len + 1));
697 
698 	return p + len;
699 }
700 
zbx_json_decodevalue(const char * p,char * string,size_t size,int * is_null)701 static const char	*zbx_json_decodevalue(const char *p, char *string, size_t size, int *is_null)
702 {
703 	size_t	len;
704 
705 	switch (__zbx_json_type(p))
706 	{
707 		case ZBX_JSON_TYPE_STRING:
708 		case ZBX_JSON_TYPE_INT:
709 			if (NULL != is_null)
710 				*is_null = 0;
711 
712 			if (0 == (len = json_parse_value(p, NULL)))
713 				return NULL;
714 
715 			return zbx_json_copy_value(p, len, string, size);
716 		case ZBX_JSON_TYPE_NULL:
717 			if (NULL != is_null)
718 				*is_null = 1;
719 			*string = '\0';
720 			return zbx_json_decodenull(p);
721 		default:
722 			return NULL;
723 	}
724 }
725 
zbx_json_decodevalue_dyn(const char * p,char ** string,size_t * string_alloc,int * is_null)726 static const char	*zbx_json_decodevalue_dyn(const char *p, char **string, size_t *string_alloc, int *is_null)
727 {
728 	size_t	len;
729 
730 	switch (__zbx_json_type(p))
731 	{
732 		case ZBX_JSON_TYPE_STRING:
733 		case ZBX_JSON_TYPE_INT:
734 			if (NULL != is_null)
735 				*is_null = 0;
736 
737 			if (0 == (len = json_parse_value(p, NULL)))
738 				return NULL;
739 
740 			if (*string_alloc <= len)
741 			{
742 				*string_alloc = len + 1;
743 				*string = zbx_realloc(*string, *string_alloc);
744 			}
745 
746 			return zbx_json_copy_value(p, len, *string, *string_alloc);
747 		case ZBX_JSON_TYPE_NULL:
748 			if (NULL != is_null)
749 				*is_null = 1;
750 
751 			if (*string_alloc < 1)
752 			{
753 				*string_alloc = 1;
754 				*string = zbx_realloc(*string, *string_alloc);
755 			}
756 
757 			**string = '\0';
758 
759 			return zbx_json_decodenull(p);
760 		default:
761 			return NULL;
762 	}
763 }
764 
zbx_json_pair_next(const struct zbx_json_parse * jp,const char * p,char * name,size_t len)765 const char	*zbx_json_pair_next(const struct zbx_json_parse *jp, const char *p, char *name, size_t len)
766 {
767 	if (NULL == (p = zbx_json_next(jp, p)))
768 		return NULL;
769 
770 	if (ZBX_JSON_TYPE_STRING != __zbx_json_type(p))
771 		return NULL;
772 
773 	if (NULL == (p = zbx_json_copy_string(p, name, len)))
774 		return NULL;
775 
776 	SKIP_WHITESPACE(p);
777 
778 	if (':' != *p++)
779 		return NULL;
780 
781 	SKIP_WHITESPACE(p);
782 
783 	return p;
784 }
785 
786 /******************************************************************************
787  *                                                                            *
788  * Function: zbx_json_pair_by_name                                            *
789  *                                                                            *
790  * Purpose: find pair by name and return pointer to value                     *
791  *                                                                            *
792  * Return value: pointer to value                                             *
793  *        {"name":["a","b",...]}                                              *
794  *                ^ - returned pointer                                        *
795  *                                                                            *
796  * Author: Alexander Vladishev                                                *
797  *                                                                            *
798  ******************************************************************************/
zbx_json_pair_by_name(const struct zbx_json_parse * jp,const char * name)799 const char	*zbx_json_pair_by_name(const struct zbx_json_parse *jp, const char *name)
800 {
801 	char		buffer[MAX_STRING_LEN];
802 	const char	*p = NULL;
803 
804 	while (NULL != (p = zbx_json_pair_next(jp, p, buffer, sizeof(buffer))))
805 		if (0 == strcmp(name, buffer))
806 			return p;
807 
808 	zbx_set_json_strerror("Can't find pair with name \"%s\"", name);
809 
810 	return NULL;
811 }
812 
813 /******************************************************************************
814  *                                                                            *
815  * Function: zbx_json_next_value                                              *
816  *                                                                            *
817  * Author: Alexander Vladishev                                                *
818  *                                                                            *
819  ******************************************************************************/
zbx_json_next_value(const struct zbx_json_parse * jp,const char * p,char * string,size_t len,int * is_null)820 const char	*zbx_json_next_value(const struct zbx_json_parse *jp, const char *p, char *string, size_t len, int *is_null)
821 {
822 	if (NULL == (p = zbx_json_next(jp, p)))
823 		return NULL;
824 
825 	return zbx_json_decodevalue(p, string, len, is_null);
826 }
827 
828 /******************************************************************************
829  *                                                                            *
830  * Function: zbx_json_next_value_dyn                                          *
831  *                                                                            *
832  ******************************************************************************/
zbx_json_next_value_dyn(const struct zbx_json_parse * jp,const char * p,char ** string,size_t * string_alloc,int * is_null)833 const char	*zbx_json_next_value_dyn(const struct zbx_json_parse *jp, const char *p, char **string,
834 		size_t *string_alloc, int *is_null)
835 {
836 	if (NULL == (p = zbx_json_next(jp, p)))
837 		return NULL;
838 
839 	return zbx_json_decodevalue_dyn(p, string, string_alloc, is_null);
840 }
841 
842 /******************************************************************************
843  *                                                                            *
844  * Function: zbx_json_value_by_name                                           *
845  *                                                                            *
846  * Purpose: return value by pair name                                         *
847  *                                                                            *
848  * Return value: SUCCEED - if value successfully parsed, FAIL - otherwise     *
849  *                                                                            *
850  * Author: Alexander Vladishev                                                *
851  *                                                                            *
852  ******************************************************************************/
zbx_json_value_by_name(const struct zbx_json_parse * jp,const char * name,char * string,size_t len)853 int	zbx_json_value_by_name(const struct zbx_json_parse *jp, const char *name, char *string, size_t len)
854 {
855 	const char	*p;
856 
857 	if (NULL == (p = zbx_json_pair_by_name(jp, name)))
858 		return FAIL;
859 
860 	if (NULL == zbx_json_decodevalue(p, string, len, NULL))
861 		return FAIL;
862 
863 	return SUCCEED;
864 }
865 
866 /******************************************************************************
867  *                                                                            *
868  * Function: zbx_json_value_by_name_dyn                                       *
869  *                                                                            *
870  * Purpose: return value by pair name                                         *
871  *                                                                            *
872  * Return value: SUCCEED - if value successfully parsed, FAIL - otherwise     *
873  *                                                                            *
874  * Author: Alexander Vladishev                                                *
875  *                                                                            *
876  ******************************************************************************/
zbx_json_value_by_name_dyn(const struct zbx_json_parse * jp,const char * name,char ** string,size_t * string_alloc)877 int	zbx_json_value_by_name_dyn(const struct zbx_json_parse *jp, const char *name, char **string, size_t *string_alloc)
878 {
879 	const char	*p;
880 
881 	if (NULL == (p = zbx_json_pair_by_name(jp, name)))
882 		return FAIL;
883 
884 	if (NULL == zbx_json_decodevalue_dyn(p, string, string_alloc, NULL))
885 		return FAIL;
886 
887 	return SUCCEED;
888 }
889 
890 /******************************************************************************
891  *                                                                            *
892  * Function: zbx_json_brackets_open                                           *
893  *                                                                            *
894  * Return value: SUCCESS - processed successfully                             *
895  *               FAIL - an error occurred                                     *
896  *                                                                            *
897  * Author: Alexander Vladishev                                                *
898  *                                                                            *
899  ******************************************************************************/
zbx_json_brackets_open(const char * p,struct zbx_json_parse * jp)900 int	zbx_json_brackets_open(const char *p, struct zbx_json_parse *jp)
901 {
902 	if (NULL == (jp->end = __zbx_json_rbracket(p)))
903 	{
904 		zbx_set_json_strerror("Can't open JSON object or array \"%.64s\"", p);
905 		return FAIL;
906 	}
907 
908 	SKIP_WHITESPACE(p);
909 
910 	jp->start = p;
911 
912 	return SUCCEED;
913 }
914 
915 /******************************************************************************
916  *                                                                            *
917  * Function: zbx_json_brackets_by_name                                        *
918  *                                                                            *
919  * Return value: SUCCESS - processed successfully                             *
920  *               FAIL - an error occurred                                     *
921  *                                                                            *
922  * Author: Alexander Vladishev                                                *
923  *                                                                            *
924  ******************************************************************************/
zbx_json_brackets_by_name(const struct zbx_json_parse * jp,const char * name,struct zbx_json_parse * out)925 int	zbx_json_brackets_by_name(const struct zbx_json_parse *jp, const char *name, struct zbx_json_parse *out)
926 {
927 	const char	*p;
928 
929 	if (NULL == (p = zbx_json_pair_by_name(jp, name)))
930 		return FAIL;
931 
932 	if (FAIL == zbx_json_brackets_open(p, out))
933 		return FAIL;
934 
935 	return SUCCEED;
936 }
937 
938 /******************************************************************************
939  *                                                                            *
940  * Function: zbx_json_object_is_empty                                         *
941  *                                                                            *
942  * Return value: SUCCESS - if object is empty                                 *
943  *               FAIL - if object contains data                               *
944  *                                                                            *
945  * Author: Alexander Vladishev                                                *
946  *                                                                            *
947  ******************************************************************************/
zbx_json_object_is_empty(const struct zbx_json_parse * jp)948 int	zbx_json_object_is_empty(const struct zbx_json_parse *jp)
949 {
950 	return jp->end - jp->start > 1 ? FAIL : SUCCEED;
951 }
952 
953 /******************************************************************************
954  *                                                                            *
955  * Function: zbx_json_count                                                   *
956  *                                                                            *
957  * Return value: number of elements in zbx_json_parse object                  *
958  *                                                                            *
959  * Author: Alexander Vladishev                                                *
960  *                                                                            *
961  ******************************************************************************/
zbx_json_count(const struct zbx_json_parse * jp)962 int	zbx_json_count(const struct zbx_json_parse *jp)
963 {
964 	int		num = 0;
965 	const char	*p = NULL;
966 
967 	while (NULL != (p = zbx_json_next(jp, p)))
968 		num++;
969 
970 	return num;
971 }
972