Apache HTTPD
md_json.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <assert.h>
18#include <apr_lib.h>
19#include <apr_strings.h>
20#include <apr_buckets.h>
21#include <apr_date.h>
22
23#include "md_json.h"
24#include "md_log.h"
25#include "md_http.h"
26#include "md_time.h"
27#include "md_util.h"
28
29/* jansson thinks everyone compiles with the platform's cc in its fullest capabilities
30 * when undefining their INLINEs, we get static, unused functions, arg
31 */
32#if defined(__GNUC__)
33#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
34#pragma GCC diagnostic push
35#endif
36#pragma GCC diagnostic ignored "-Wunused-function"
37#pragma GCC diagnostic ignored "-Wunreachable-code"
38#elif defined(__clang__)
39#pragma clang diagnostic push
40#pragma clang diagnostic ignored "-Wunused-function"
41#endif
42
43#include <jansson_config.h>
44#undef JSON_INLINE
45#define JSON_INLINE
46#include <jansson.h>
47
48#if defined(__GNUC__)
49#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
50#pragma GCC diagnostic pop
51#endif
52#elif defined(__clang__)
53#pragma clang diagnostic pop
54#endif
55
60
61/**************************************************************************************************/
62/* lifecycle */
63
65{
66 md_json_t *json = data;
67 if (json) {
68 md_json_destroy(json);
69 }
70 return APR_SUCCESS;
71}
72
74{
75 md_json_t *json;
76
77 if (!j) {
79 if (abfn) {
81 }
82 assert(j != NULL); /* failsafe in case abort is unset */
83 }
84 json = apr_pcalloc(pool, sizeof(*json));
85 json->p = pool;
86 json->j = j;
88
89 return json;
90}
91
96
98{
99 return json_create(pool, json_string(s));
100}
101
103{
104 if (json && json->j) {
105 assert(json->j->refcount > 0);
106 json_decref(json->j);
107 json->j = NULL;
108 }
109}
110
112{
113 return json_create(pool, json_copy(json->j));
114}
115
117{
118 return json_create(pool, json_deep_copy(json->j));
119}
120
121/**************************************************************************************************/
122/* selectors */
123
124
125static json_t *jselect(const md_json_t *json, va_list ap)
126{
127 json_t *j;
128 const char *key;
129
130 j = json->j;
131 key = va_arg(ap, char *);
132 while (key && j) {
133 j = json_object_get(j, key);
134 key = va_arg(ap, char *);
135 }
136 return j;
137}
138
139static json_t *jselect_parent(const char **child_key, int create, md_json_t *json, va_list ap)
140{
141 const char *key, *next;
142 json_t *j, *jn;
143
144 *child_key = NULL;
145 j = json->j;
146 key = va_arg(ap, char *);
147 while (key && j) {
148 next = va_arg(ap, char *);
149 if (next) {
150 jn = json_object_get(j, key);
151 if (!jn && create) {
152 jn = json_object();
154 }
155 j = jn;
156 }
157 else {
158 *child_key = key;
159 }
160 key = next;
161 }
162 return j;
163}
164
166{
167 const char *key;
168 json_t *j, *aj;
169
170 j = jselect_parent(&key, 1, json, ap);
171
172 if (!j || !json_is_object(j)) {
173 return APR_EINVAL;
174 }
175
176 aj = json_object_get(j, key);
177 if (!aj) {
178 aj = json_array();
180 }
181
182 if (!json_is_array(aj)) {
183 return APR_EINVAL;
184 }
185
187 return APR_SUCCESS;
188}
189
191{
192 const char *key;
193 json_t *j, *aj;
194
195 j = jselect_parent(&key, 1, json, ap);
196
197 if (!j || !json_is_object(j)) {
199 return APR_EINVAL;
200 }
201
202 aj = json_object_get(j, key);
203 if (!aj) {
204 aj = json_array();
206 }
207
208 if (!json_is_array(aj)) {
210 return APR_EINVAL;
211 }
212
213 if (json_array_size(aj) <= index) {
215 }
216 else {
217 json_array_insert(aj, index, val);
218 }
219 return APR_SUCCESS;
220}
221
223{
224 const char *key;
225 json_t *j;
226
227 j = jselect_parent(&key, 1, json, ap);
228
229 if (!j) {
230 return APR_EINVAL;
231 }
232
233 if (key) {
234 if (!json_is_object(j)) {
235 return APR_EINVAL;
236 }
238 }
239 else {
240 /* replace */
241 if (json->j) {
242 json_decref(json->j);
243 }
245 json->j = val;
246 }
247 return APR_SUCCESS;
248}
249
251{
252 const char *key;
253 json_t *j;
254
255 j = jselect_parent(&key, 1, json, ap);
256
257 if (!j) {
259 return APR_EINVAL;
260 }
261
262 if (key) {
263 if (!json_is_object(j)) {
265 return APR_EINVAL;
266 }
268 }
269 else {
270 /* replace */
271 if (json->j) {
272 json_decref(json->j);
273 }
274 json->j = val;
275 }
276 return APR_SUCCESS;
277}
278
279int md_json_has_key(const md_json_t *json, ...)
280{
281 json_t *j;
282 va_list ap;
283
284 va_start(ap, json);
285 j = jselect(json, ap);
286 va_end(ap);
287
288 return j != NULL;
289}
290
291/**************************************************************************************************/
292/* type things */
293
295{
296 json_t *j;
297 va_list ap;
298
299 va_start(ap, json);
300 j = jselect(json, ap);
301 va_end(ap);
302 switch (jtype) {
303 case MD_JSON_TYPE_OBJECT: return (j && json_is_object(j));
304 case MD_JSON_TYPE_ARRAY: return (j && json_is_array(j));
305 case MD_JSON_TYPE_STRING: return (j && json_is_string(j));
306 case MD_JSON_TYPE_REAL: return (j && json_is_real(j));
307 case MD_JSON_TYPE_INT: return (j && json_is_integer(j));
308 case MD_JSON_TYPE_BOOL: return (j && (json_is_true(j) || json_is_false(j)));
309 case MD_JSON_TYPE_NULL: return (j == NULL);
310 }
311 return 0;
312}
313
314static const char *md_json_type_name(const md_json_t *json)
315{
316 json_t *j = json->j;
317 if (json_is_object(j)) return "object";
318 if (json_is_array(j)) return "array";
319 if (json_is_string(j)) return "string";
320 if (json_is_real(j)) return "real";
321 if (json_is_integer(j)) return "integer";
322 if (json_is_true(j)) return "true";
323 if (json_is_false(j)) return "false";
324 return "unknown";
325}
326
327/**************************************************************************************************/
328/* booleans */
329
330int md_json_getb(const md_json_t *json, ...)
331{
332 json_t *j;
333 va_list ap;
334
335 va_start(ap, json);
336 j = jselect(json, ap);
337 va_end(ap);
338
339 return j? json_is_true(j) : 0;
340}
341
343{
344 va_list ap;
345 apr_status_t rv;
346
347 va_start(ap, json);
348 rv = jselect_set_new(json_boolean(value), json, ap);
349 va_end(ap);
350 return rv;
351}
352
353/**************************************************************************************************/
354/* numbers */
355
356double md_json_getn(const md_json_t *json, ...)
357{
358 json_t *j;
359 va_list ap;
360
361 va_start(ap, json);
362 j = jselect(json, ap);
363 va_end(ap);
364 return (j && json_is_number(j))? json_number_value(j) : 0.0;
365}
366
368{
369 va_list ap;
370 apr_status_t rv;
371
372 va_start(ap, json);
373 rv = jselect_set_new(json_real(value), json, ap);
374 va_end(ap);
375 return rv;
376}
377
378/**************************************************************************************************/
379/* longs */
380
381long md_json_getl(const md_json_t *json, ...)
382{
383 json_t *j;
384 va_list ap;
385
386 va_start(ap, json);
387 j = jselect(json, ap);
388 va_end(ap);
389 return (long)((j && json_is_number(j))? json_integer_value(j) : 0L);
390}
391
393{
394 va_list ap;
395 apr_status_t rv;
396
397 va_start(ap, json);
398 rv = jselect_set_new(json_integer(value), json, ap);
399 va_end(ap);
400 return rv;
401}
402
403/**************************************************************************************************/
404/* strings */
405
406const char *md_json_gets(const md_json_t *json, ...)
407{
408 json_t *j;
409 va_list ap;
410
411 va_start(ap, json);
412 j = jselect(json, ap);
413 va_end(ap);
414
415 return (j && json_is_string(j))? json_string_value(j) : NULL;
416}
417
418const char *md_json_dups(apr_pool_t *p, const md_json_t *json, ...)
419{
420 json_t *j;
421 va_list ap;
422
423 va_start(ap, json);
424 j = jselect(json, ap);
425 va_end(ap);
426
427 return (j && json_is_string(j))? apr_pstrdup(p, json_string_value(j)) : NULL;
428}
429
430apr_status_t md_json_sets(const char *value, md_json_t *json, ...)
431{
432 va_list ap;
433 apr_status_t rv;
434
435 va_start(ap, json);
436 rv = jselect_set_new(json_string(value), json, ap);
437 va_end(ap);
438 return rv;
439}
440
441/**************************************************************************************************/
442/* time */
443
445{
446 json_t *j;
447 va_list ap;
448
449 va_start(ap, json);
450 j = jselect(json, ap);
451 va_end(ap);
452
453 if (!j || !json_is_string(j)) return 0;
455}
456
458{
459 char ts[APR_RFC822_DATE_LEN];
460 va_list ap;
461 apr_status_t rv;
462
464 va_start(ap, json);
465 rv = jselect_set_new(json_string(ts), json, ap);
466 va_end(ap);
467 return rv;
468}
469
470/**************************************************************************************************/
471/* json itself */
472
474{
475 json_t *j;
476 va_list ap;
477
478 va_start(ap, json);
479 j = jselect(json, ap);
480 va_end(ap);
481
482 if (j) {
483 if (j == json->j) {
484 return json;
485 }
486 json_incref(j);
487 return json_create(json->p, j);
488 }
489 return NULL;
490}
491
493{
494 json_t *j;
495 va_list ap;
496
497 va_start(ap, json);
498 j = jselect(json, ap);
499 va_end(ap);
500
501 if (j) {
502 json_incref(j);
503 return json_create(p, j);
504 }
505 return NULL;
506}
507
508const md_json_t *md_json_getcj(const md_json_t *json, ...)
509{
510 json_t *j;
511 va_list ap;
512
513 va_start(ap, json);
514 j = jselect(json, ap);
515 va_end(ap);
516
517 if (j) {
518 if (j == json->j) {
519 return json;
520 }
521 json_incref(j);
522 return json_create(json->p, j);
523 }
524 return NULL;
525}
526
528{
529 va_list ap;
530 apr_status_t rv;
531 const char *key;
532 json_t *j;
533
534 if (value) {
535 va_start(ap, json);
536 rv = jselect_set(value->j, json, ap);
537 va_end(ap);
538 }
539 else {
540 va_start(ap, json);
541 j = jselect_parent(&key, 1, json, ap);
542 va_end(ap);
543
544 if (key && j && !json_is_object(j)) {
546 rv = APR_SUCCESS;
547 }
548 else {
549 rv = APR_EINVAL;
550 }
551 }
552 return rv;
553}
554
556{
557 va_list ap;
558 apr_status_t rv;
559
560 va_start(ap, json);
561 rv = jselect_add(value->j, json, ap);
562 va_end(ap);
563 return rv;
564}
565
567{
568 va_list ap;
569 apr_status_t rv;
570
571 va_start(ap, json);
572 rv = jselect_insert(value->j, index, json, ap);
573 va_end(ap);
574 return rv;
575}
576
578{
579 json_t *j;
580 va_list ap;
581 apr_size_t n = 0;
582
583 va_start(ap, json);
584 j = jselect(json, ap);
585 va_end(ap);
586
587 if (j && json_is_array(j)) {
588 n = json_array_size(j);
589 while (n > max_elements) {
590 json_array_remove(j, n-1);
591 n = json_array_size(j);
592 }
593 }
594 return n;
595}
596
597/**************************************************************************************************/
598/* arrays / objects */
599
601{
602 json_t *j;
603 va_list ap;
604
605 va_start(ap, json);
606 j = jselect(json, ap);
607 va_end(ap);
608
609 if (j && json_is_object(j)) {
611 }
612 else if (j && json_is_array(j)) {
614 }
615 return APR_SUCCESS;
616}
617
619{
620 const char *key;
621 json_t *j;
622 va_list ap;
623
624 va_start(ap, json);
625 j = jselect_parent(&key, 0, json, ap);
626 va_end(ap);
627
628 if (key && j && json_is_object(j)) {
630 }
631 return APR_SUCCESS;
632}
633
634/**************************************************************************************************/
635/* object strings */
636
638{
639 json_t *j;
640 va_list ap;
641
642 va_start(ap, json);
643 j = jselect(json, ap);
644 va_end(ap);
645
646 if (j && json_is_object(j)) {
647 const char *key;
648 json_t *val;
649
651 if (json_is_string(val)) {
653 }
654 }
655 return APR_SUCCESS;
656 }
657 return APR_ENOENT;
658}
659
660static int object_set(void *data, const char *key, const char *val)
661{
662 json_t *j = data, *nj = json_string(val);
665 return 1;
666}
667
669{
670 json_t *nj, *j;
671 va_list ap;
672
673 va_start(ap, json);
674 j = jselect(json, ap);
675 va_end(ap);
676
677 if (!j || !json_is_object(j)) {
678 const char *key;
679
680 va_start(ap, json);
681 j = jselect_parent(&key, 1, json, ap);
682 va_end(ap);
683
684 if (!key || !j || !json_is_object(j)) {
685 return APR_EINVAL;
686 }
687 nj = json_object();
689 j = nj;
690 }
691
693 return APR_SUCCESS;
694}
695
696/**************************************************************************************************/
697/* conversions */
698
700{
701 (void)p;
702 (void)baton;
703 return md_json_setj(value, json, NULL);
704}
705
707{
708 (void)p;
709 (void)baton;
710 *pvalue = json;
711 return APR_SUCCESS;
712}
713
715{
716 (void)baton;
717 return md_json_setj(md_json_clone(p, value), json, NULL);
718}
719
721{
722 (void)baton;
723 *pvalue = md_json_clone(p, json);
724 return APR_SUCCESS;
725}
726
727/**************************************************************************************************/
728/* array generic */
729
731 const md_json_t *json, ...)
732{
733 json_t *j;
734 va_list ap;
736 size_t index;
737 json_t *val;
739 void *element;
740
741 va_start(ap, json);
742 j = jselect(json, ap);
743 va_end(ap);
744
745 if (!j || !json_is_array(j)) {
746 return APR_ENOENT;
747 }
748
749 wrap.p = a->pool;
750 json_array_foreach(j, index, val) {
751 wrap.j = val;
752 if (APR_SUCCESS == (rv = cb(&element, &wrap, wrap.p, baton))) {
753 if (element) {
754 APR_ARRAY_PUSH(a, void*) = element;
755 }
756 }
757 else if (APR_ENOENT == rv) {
758 rv = APR_SUCCESS;
759 }
760 else {
761 break;
762 }
763 }
764 return rv;
765}
766
768 md_json_t *json, ...)
769{
770 json_t *j, *nj;
773 va_list ap;
774 int i;
775
776 va_start(ap, json);
777 j = jselect(json, ap);
778 va_end(ap);
779
780 if (!j || !json_is_array(j)) {
781 const char *key;
782
783 va_start(ap, json);
784 j = jselect_parent(&key, 1, json, ap);
785 va_end(ap);
786
787 if (!key || !j || !json_is_object(j)) {
788 return APR_EINVAL;
789 }
790 nj = json_array();
792 j = nj;
793 }
794
796 wrap.p = json->p;
797 for (i = 0; i < a->nelts; ++i) {
798 if (!cb) {
799 return APR_EINVAL;
800 }
801 wrap.j = json_string("");
802 if (APR_SUCCESS == (rv = cb(APR_ARRAY_IDX(a, i, void*), &wrap, json->p, baton))) {
804 }
805 }
806 return rv;
807}
808
810{
811 json_t *j;
812 va_list ap;
813 size_t index;
814 json_t *val;
816
817 va_start(ap, json);
818 j = jselect(json, ap);
819 va_end(ap);
820
821 if (!j || !json_is_array(j)) {
822 return 0;
823 }
824
825 wrap.p = json->p;
826 json_array_foreach(j, index, val) {
827 wrap.j = val;
828 if (!cb(baton, index, &wrap)) {
829 return 0;
830 }
831 }
832 return 1;
833}
834
836{
837 json_t *j;
838 va_list ap;
839 const char *key;
840 json_t *val;
842
843 va_start(ap, json);
844 j = jselect(json, ap);
845 va_end(ap);
846
847 if (!j || !json_is_object(j)) {
848 return 0;
849 }
850
851 wrap.p = json->p;
853 wrap.j = val;
854 if (!cb(baton, key, &wrap)) {
855 return 0;
856 }
857 }
858 return 1;
859}
860
861/**************************************************************************************************/
862/* array strings */
863
865{
866 json_t *j;
867 va_list ap;
868
869 va_start(ap, json);
870 j = jselect(json, ap);
871 va_end(ap);
872
873 if (j && json_is_array(j)) {
874 size_t index;
875 json_t *val;
876
877 json_array_foreach(j, index, val) {
878 if (json_is_string(val)) {
879 APR_ARRAY_PUSH(a, const char *) = json_string_value(val);
880 }
881 }
882 return APR_SUCCESS;
883 }
884 return APR_ENOENT;
885}
886
888{
889 json_t *j;
890 va_list ap;
891
892 va_start(ap, json);
893 j = jselect(json, ap);
894 va_end(ap);
895
896 if (j && json_is_array(j)) {
897 size_t index;
898 json_t *val;
899
901 json_array_foreach(j, index, val) {
902 if (json_is_string(val)) {
904 }
905 }
906 return APR_SUCCESS;
907 }
908 return APR_ENOENT;
909}
910
912{
913 json_t *nj, *j;
914 va_list ap;
915 int i;
916
917 va_start(ap, json);
918 j = jselect(json, ap);
919 va_end(ap);
920
921 if (!j || !json_is_array(j)) {
922 const char *key;
923
924 va_start(ap, json);
925 j = jselect_parent(&key, 1, json, ap);
926 va_end(ap);
927
928 if (!key || !j || !json_is_object(j)) {
929 return APR_EINVAL;
930 }
931 nj = json_array();
933 j = nj;
934 }
935
937 for (i = 0; i < a->nelts; ++i) {
939 }
940 return APR_SUCCESS;
941}
942
943/**************************************************************************************************/
944/* formatting, parsing */
945
946typedef struct {
949 const char *fname;
952
953/* Convert from md_json_fmt_t to the Jansson json_dumpX flags. */
955{
956 /* NOTE: JSON_PRESERVE_ORDER is off by default before Jansson 2.8. It
957 * doesn't have any semantic effect on the protocol, but it does let the
958 * md_json_writeX unit tests run deterministically. */
959 return JSON_PRESERVE_ORDER |
961}
962
963static int dump_cb(const char *buffer, size_t len, void *baton)
964{
966 apr_status_t rv;
967
968 rv = apr_brigade_write(bb, NULL, NULL, buffer, len);
969 return (rv == APR_SUCCESS)? 0 : -1;
970}
971
977
978static int chunk_cb(const char *buffer, size_t len, void *baton)
979{
981 char *chunk;
982
983 if (len > 0) {
984 chunk = apr_palloc(chunks->pool, len+1);
986 chunk[len] = '\0';
987 APR_ARRAY_PUSH(chunks, const char*) = chunk;
988 }
989 return 0;
990}
991
993{
995 int rv;
996
997 chunks = apr_array_make(p, 10, sizeof(char *));
999 if (APR_SUCCESS != rv) {
1001 "md_json_writep failed to dump JSON");
1002 return NULL;
1003 }
1004
1005 switch (chunks->nelts) {
1006 case 0:
1007 return "";
1008 case 1:
1009 return APR_ARRAY_IDX(chunks, 0, const char*);
1010 default:
1011 return apr_array_pstrcat(p, chunks, 0);
1012 }
1013}
1014
1016{
1017 apr_status_t rv;
1018 const char *s;
1019
1020 if ((s = md_json_writep(json, p, fmt))) {
1021 rv = apr_file_write_full(f, s, strlen(s), NULL);
1022 if (APR_SUCCESS != rv) {
1023 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, json->p, "md_json_writef: error writing file");
1024 }
1025 }
1026 else {
1027 rv = APR_EINVAL;
1029 "md_json_writef: error dumping json (%s)", md_json_dump_state(json, p));
1030 }
1031 return rv;
1032}
1033
1035 const char *fpath, apr_fileperms_t perms)
1036{
1037 apr_status_t rv;
1038 apr_file_t *f;
1039
1040 rv = md_util_fcreatex(&f, fpath, perms, p);
1041 if (APR_SUCCESS == rv) {
1042 rv = md_json_writef(json, p, fmt, f);
1044 }
1045 return rv;
1046}
1047
1049{
1051 apr_status_t rv = md_json_writef(ctx->json, p, ctx->fmt, f);
1052 if (APR_SUCCESS != rv) {
1053 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "freplace json in %s", ctx->fname);
1054 }
1055 return rv;
1056}
1057
1059 const char *fpath, apr_fileperms_t perms)
1060{
1062 ctx.json = json;
1063 ctx.fmt = fmt;
1064 ctx.fname = fpath;
1066}
1067
1069{
1071 json_t *j;
1072
1073 j = json_loadb(data, data_len, 0, &error);
1074 if (!j) {
1075 return APR_EINVAL;
1076 }
1077 *pjson = json_create(pool, j);
1078 return APR_SUCCESS;
1079}
1080
1081static size_t load_cb(void *data, size_t max_len, void *baton)
1082{
1083 apr_bucket_brigade *body = baton;
1084 size_t blen, read_len = 0;
1085 const char *bdata;
1086 char *dest = data;
1087 apr_bucket *b;
1088 apr_status_t rv;
1089
1090 while (body && !APR_BRIGADE_EMPTY(body) && max_len > 0) {
1091 b = APR_BRIGADE_FIRST(body);
1093 if (APR_BUCKET_IS_EOS(b)) {
1094 body = NULL;
1095 }
1096 }
1097 else {
1098 rv = apr_bucket_read(b, &bdata, &blen, APR_BLOCK_READ);
1099 if (rv == APR_SUCCESS) {
1100 if (blen > max_len) {
1102 blen = max_len;
1103 }
1104 memcpy(dest, bdata, blen);
1105 read_len += blen;
1106 max_len -= blen;
1107 dest += blen;
1108 }
1109 else {
1110 body = NULL;
1111 if (!APR_STATUS_IS_EOF(rv)) {
1112 /* everything beside EOF is an error */
1113 read_len = (size_t)-1;
1114 }
1115 }
1116 }
1119 }
1120
1121 return read_len;
1122}
1123
1125{
1127 json_t *j;
1128
1129 j = json_load_callback(load_cb, bb, 0, &error);
1130 if (j) {
1131 *pjson = json_create(pool, j);
1132 } else {
1134 "failed to load JSON file: %s (line %d:%d)",
1135 error.text, error.line, error.column);
1136 }
1137 return (j && *pjson) ? APR_SUCCESS : APR_EINVAL;
1138}
1139
1140static size_t load_file_cb(void *data, size_t max_len, void *baton)
1141{
1142 apr_file_t *f = baton;
1144 apr_status_t rv;
1145
1146 rv = apr_file_read(f, data, &len);
1147 if (APR_SUCCESS == rv) {
1148 return len;
1149 }
1150 else if (APR_EOF == rv) {
1151 return 0;
1152 }
1153 return (size_t)-1;
1154}
1155
1157{
1158 apr_file_t *f;
1159 json_t *j;
1160 apr_status_t rv;
1162
1163 rv = apr_file_open(&f, fpath, APR_FOPEN_READ, 0, p);
1164 if (rv != APR_SUCCESS) {
1165 return rv;
1166 }
1167
1169 if (j) {
1170 *pjson = json_create(p, j);
1171 }
1172 else {
1174 "failed to load JSON file %s: %s (line %d:%d)",
1175 fpath, error.text, error.line, error.column);
1176 }
1177
1179 return (j && *pjson) ? APR_SUCCESS : APR_EINVAL;
1180}
1181
1182/**************************************************************************************************/
1183/* http get */
1184
1186{
1188 const char *ctype, *p;
1189
1190 *pjson = NULL;
1191 if (!res->body) goto cleanup;
1192 ctype = md_util_parse_ct(res->req->pool, apr_table_get(res->headers, "content-type"));
1193 if (!ctype) goto cleanup;
1194 p = ctype + strlen(ctype) +1;
1195 if (!strcmp(p - sizeof("/json"), "/json")
1196 || !strcmp(p - sizeof("+json"), "+json")) {
1197 rv = md_json_readb(pjson, pool, res->body);
1198 }
1199cleanup:
1200 return rv;
1201}
1202
1208
1210{
1211 resp_data *resp = data;
1212 return md_json_read_http(&resp->json, resp->pool, res);
1213}
1214
1216 struct md_http_t *http, const char *url)
1217{
1218 apr_status_t rv;
1220
1221 memset(&resp, 0, sizeof(resp));
1222 resp.pool = pool;
1223
1225
1226 if (rv == APR_SUCCESS) {
1227 *pjson = resp.json;
1228 return resp.rv;
1229 }
1230 *pjson = NULL;
1231 return rv;
1232}
1233
1234
1236{
1237 json_t *j;
1238 va_list ap;
1240
1241 va_start(ap, src);
1242 j = jselect(src, ap);
1243 va_end(ap);
1244
1245 if (j) {
1246 va_start(ap, src);
1247 rv = jselect_set(j, dest, ap);
1248 va_end(ap);
1249 }
1250 return rv;
1251}
1252
1253const char *md_json_dump_state(const md_json_t *json, apr_pool_t *p)
1254{
1255 if (!json) return "NULL";
1256 return apr_psprintf(p, "%s, refc=%ld", md_json_type_name(json), (long)json->j->refcount);
1257}
1258
1260{
1261 char ts[APR_RFC822_DATE_LEN];
1262 json_t *jn, *j;
1263 va_list ap;
1264 const char *key;
1265 apr_status_t rv;
1266
1267 if (tp && tp->start && tp->end) {
1268 jn = json_object();
1269 apr_rfc822_date(ts, tp->start);
1270 json_object_set_new(jn, "from", json_string(ts));
1271 apr_rfc822_date(ts, tp->end);
1272 json_object_set_new(jn, "until", json_string(ts));
1273
1274 va_start(ap, json);
1275 rv = jselect_set_new(jn, json, ap);
1276 va_end(ap);
1277 return rv;
1278 }
1279 else {
1280 va_start(ap, json);
1281 j = jselect_parent(&key, 0, json, ap);
1282 va_end(ap);
1283
1284 if (key && j && json_is_object(j)) {
1285 json_object_del(j, key);
1286 }
1287 return APR_SUCCESS;
1288 }
1289}
1290
1292{
1293 json_t *j, *jts;
1294 va_list ap;
1295
1296 va_start(ap, json);
1297 j = jselect(json, ap);
1298 va_end(ap);
1299
1300 memset(tp, 0, sizeof(*tp));
1301 if (!j) goto not_found;
1302 jts = json_object_get(j, "from");
1303 if (!jts || !json_is_string(jts)) goto not_found;
1305 jts = json_object_get(j, "until");
1306 if (!jts || !json_is_string(jts)) goto not_found;
1308 return APR_SUCCESS;
1309not_found:
1310 return APR_ENOENT;
1311}
int n
Definition ap_regex.h:278
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Buckets/Bucket Brigades.
APR-UTIL date routines.
APR general purpose library routines.
APR Strings library.
ap_vhost_iterate_conn_cb void * baton
Definition http_vhost.h:87
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_EOF
Definition apr_errno.h:461
#define APR_ENOMEM
Definition apr_errno.h:683
#define APR_ENOENT
Definition apr_errno.h:662
#define APR_EINVAL
Definition apr_errno.h:711
#define APR_STATUS_IS_EOF(s)
Definition apr_errno.h:567
apr_file_t * f
#define APR_BUCKET_REMOVE(e)
#define APR_BUCKET_IS_METADATA(e)
#define apr_bucket_split(e, point)
#define APR_BRIGADE_EMPTY(b)
#define apr_bucket_delete(e)
#define APR_BUCKET_IS_EOS(e)
apr_brigade_flush void * ctx
apr_bucket apr_bucket_brigade * a
#define APR_BRIGADE_FIRST(b)
#define apr_bucket_read(e, str, len, block)
@ APR_BLOCK_READ
Definition apr_buckets.h:58
apr_pool_t const char apr_dbd_t const char ** error
Definition apr_dbd.h:143
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
apr_datum_t apr_datum_t * pvalue
Definition apr_dbm.h:128
const char * src
Definition apr_encode.h:167
const char * url
Definition apr_escape.h:120
const char const apr_size_t data_len
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const char int apr_pool_t * pool
Definition apr_cstr.h:84
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_int32_t apr_fileperms_t
const char * key
const char apr_fileperms_t perms
void * data
void const char apr_status_t(* cleanup)(void *))
char * buffer
#define APR_FOPEN_READ
Definition apr_file_io.h:54
apr_vformatter_buff_t const char * fmt
Definition apr_lib.h:175
apr_vformatter_buff_t const char va_list ap
Definition apr_lib.h:176
apr_pool_t * b
Definition apr_pools.h:529
int(* apr_abortfunc_t)(int retcode)
Definition apr_pools.h:148
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char * s
Definition apr_strings.h:95
#define APR_ARRAY_PUSH(ary, type)
Definition apr_tables.h:150
#define APR_ARRAY_IDX(ary, i, type)
Definition apr_tables.h:141
#define APR_RFC822_DATE_LEN
Definition apr_time.h:186
apr_int64_t apr_time_t
Definition apr_time.h:45
apr_pool_t * p
Definition md_event.c:32
apr_status_t md_http_GET_perform(struct md_http_t *http, const char *url, struct apr_table_t *headers, md_http_response_cb *cb, void *baton)
Definition md_http.c:349
md_json_t * md_json_create(apr_pool_t *pool)
Definition md_json.c:92
apr_status_t md_json_set_timeperiod(const md_timeperiod_t *tp, md_json_t *json,...)
Definition md_json.c:1259
apr_status_t md_json_getsa(apr_array_header_t *a, const md_json_t *json,...)
Definition md_json.c:864
md_json_t * md_json_dupj(apr_pool_t *p, const md_json_t *json,...)
Definition md_json.c:492
int md_json_getb(const md_json_t *json,...)
Definition md_json.c:330
static json_t * jselect(const md_json_t *json, va_list ap)
Definition md_json.c:125
static size_t fmt_to_flags(md_json_fmt_t fmt)
Definition md_json.c:954
static apr_status_t jselect_insert(json_t *val, size_t index, md_json_t *json, va_list ap)
Definition md_json.c:190
apr_status_t md_json_clr(md_json_t *json,...)
Definition md_json.c:600
static size_t load_cb(void *data, size_t max_len, void *baton)
Definition md_json.c:1081
static apr_status_t json_pool_cleanup(void *data)
Definition md_json.c:64
md_json_t * md_json_create_s(apr_pool_t *pool, const char *s)
Definition md_json.c:97
double md_json_getn(const md_json_t *json,...)
Definition md_json.c:356
apr_status_t md_json_sets(const char *value, md_json_t *json,...)
Definition md_json.c:430
const char * md_json_gets(const md_json_t *json,...)
Definition md_json.c:406
long md_json_getl(const md_json_t *json,...)
Definition md_json.c:381
apr_status_t md_json_setn(double value, md_json_t *json,...)
Definition md_json.c:367
static apr_status_t jselect_set(json_t *val, md_json_t *json, va_list ap)
Definition md_json.c:222
apr_status_t md_json_pass_from(void **pvalue, md_json_t *json, apr_pool_t *p, void *baton)
Definition md_json.c:706
md_json_t * md_json_copy(apr_pool_t *pool, const md_json_t *json)
Definition md_json.c:111
apr_status_t md_json_geta(apr_array_header_t *a, md_json_from_cb *cb, void *baton, const md_json_t *json,...)
Definition md_json.c:730
static int chunk_cb(const char *buffer, size_t len, void *baton)
Definition md_json.c:978
md_json_t * md_json_getj(md_json_t *json,...)
Definition md_json.c:473
const md_json_t * md_json_getcj(const md_json_t *json,...)
Definition md_json.c:508
apr_status_t md_json_freplace(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt, const char *fpath, apr_fileperms_t perms)
Definition md_json.c:1058
static apr_status_t json_resp_cb(const md_http_response_t *res, void *data)
Definition md_json.c:1209
md_json_t * md_json_clone(apr_pool_t *pool, const md_json_t *json)
Definition md_json.c:116
int md_json_iterkey(md_json_iterkey_cb *cb, void *baton, md_json_t *json,...)
Definition md_json.c:835
apr_status_t md_json_seta(apr_array_header_t *a, md_json_to_cb *cb, void *baton, md_json_t *json,...)
Definition md_json.c:767
static int object_set(void *data, const char *key, const char *val)
Definition md_json.c:660
apr_status_t md_json_gets_dict(apr_table_t *dict, const md_json_t *json,...)
Definition md_json.c:637
static json_t * jselect_parent(const char **child_key, int create, md_json_t *json, va_list ap)
Definition md_json.c:139
apr_status_t md_json_dupsa(apr_array_header_t *a, apr_pool_t *p, md_json_t *json,...)
Definition md_json.c:887
apr_status_t md_json_addj(const md_json_t *value, md_json_t *json,...)
Definition md_json.c:555
apr_size_t md_json_limita(size_t max_elements, md_json_t *json,...)
Definition md_json.c:577
apr_status_t md_json_readf(md_json_t **pjson, apr_pool_t *p, const char *fpath)
Definition md_json.c:1156
apr_status_t md_json_set_time(apr_time_t value, md_json_t *json,...)
Definition md_json.c:457
apr_status_t md_json_readb(md_json_t **pjson, apr_pool_t *pool, apr_bucket_brigade *bb)
Definition md_json.c:1124
apr_status_t md_json_insertj(md_json_t *value, size_t index, md_json_t *json,...)
Definition md_json.c:566
apr_status_t md_json_fcreatex(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt, const char *fpath, apr_fileperms_t perms)
Definition md_json.c:1034
apr_status_t md_json_pass_to(void *value, md_json_t *json, apr_pool_t *p, void *baton)
Definition md_json.c:699
apr_status_t md_json_writef(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt, apr_file_t *f)
Definition md_json.c:1015
apr_status_t md_json_copy_to(md_json_t *dest, const md_json_t *src,...)
Definition md_json.c:1235
int md_json_is(const md_json_type_t jtype, md_json_t *json,...)
Definition md_json.c:294
static size_t load_file_cb(void *data, size_t max_len, void *baton)
Definition md_json.c:1140
static apr_status_t jselect_add(json_t *val, md_json_t *json, va_list ap)
Definition md_json.c:165
apr_status_t md_json_del(md_json_t *json,...)
Definition md_json.c:618
apr_status_t md_json_http_get(md_json_t **pjson, apr_pool_t *pool, struct md_http_t *http, const char *url)
Definition md_json.c:1215
apr_status_t md_json_setj(const md_json_t *value, md_json_t *json,...)
Definition md_json.c:527
apr_status_t md_json_clone_from(void **pvalue, const md_json_t *json, apr_pool_t *p, void *baton)
Definition md_json.c:720
apr_status_t md_json_get_timeperiod(md_timeperiod_t *tp, md_json_t *json,...)
Definition md_json.c:1291
apr_status_t md_json_read_http(md_json_t **pjson, apr_pool_t *pool, const md_http_response_t *res)
Definition md_json.c:1185
static apr_status_t write_json(void *baton, apr_file_t *f, apr_pool_t *p)
Definition md_json.c:1048
apr_status_t md_json_sets_dict(apr_table_t *dict, md_json_t *json,...)
Definition md_json.c:668
int md_json_has_key(const md_json_t *json,...)
Definition md_json.c:279
int md_json_itera(md_json_itera_cb *cb, void *baton, md_json_t *json,...)
Definition md_json.c:809
static const char * md_json_type_name(const md_json_t *json)
Definition md_json.c:314
apr_time_t md_json_get_time(const md_json_t *json,...)
Definition md_json.c:444
void md_json_destroy(md_json_t *json)
Definition md_json.c:102
apr_status_t md_json_writeb(const md_json_t *json, md_json_fmt_t fmt, apr_bucket_brigade *bb)
Definition md_json.c:972
static apr_status_t jselect_set_new(json_t *val, md_json_t *json, va_list ap)
Definition md_json.c:250
apr_status_t md_json_setb(int value, md_json_t *json,...)
Definition md_json.c:342
static md_json_t * json_create(apr_pool_t *pool, json_t *j)
Definition md_json.c:73
static int dump_cb(const char *buffer, size_t len, void *baton)
Definition md_json.c:963
apr_status_t md_json_readd(md_json_t **pjson, apr_pool_t *pool, const char *data, size_t data_len)
Definition md_json.c:1068
const char * md_json_dups(apr_pool_t *p, const md_json_t *json,...)
Definition md_json.c:418
apr_status_t md_json_clone_to(void *value, md_json_t *json, apr_pool_t *p, void *baton)
Definition md_json.c:714
apr_status_t md_json_setl(long value, md_json_t *json,...)
Definition md_json.c:392
const char * md_json_dump_state(const md_json_t *json, apr_pool_t *p)
Definition md_json.c:1253
apr_status_t md_json_setsa(apr_array_header_t *a, md_json_t *json,...)
Definition md_json.c:911
const char * md_json_writep(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt)
Definition md_json.c:992
apr_status_t md_json_to_cb(void *value, md_json_t *json, apr_pool_t *p, void *baton)
Definition md_json.h:95
md_json_fmt_t
Definition md_json.h:42
@ MD_JSON_FMT_COMPACT
Definition md_json.h:43
md_json_type_t
Definition md_json.h:31
@ MD_JSON_TYPE_INT
Definition md_json.h:36
@ MD_JSON_TYPE_ARRAY
Definition md_json.h:33
@ MD_JSON_TYPE_BOOL
Definition md_json.h:37
@ MD_JSON_TYPE_STRING
Definition md_json.h:34
@ MD_JSON_TYPE_OBJECT
Definition md_json.h:32
@ MD_JSON_TYPE_NULL
Definition md_json.h:38
@ MD_JSON_TYPE_REAL
Definition md_json.h:35
int md_json_iterkey_cb(void *baton, const char *key, md_json_t *json)
Definition md_json.h:117
apr_status_t md_json_from_cb(void **pvalue, md_json_t *json, apr_pool_t *p, void *baton)
Definition md_json.h:96
int md_json_itera_cb(void *baton, size_t index, md_json_t *json)
Definition md_json.h:113
void md_log_perror(const char *file, int line, md_log_level_t level, apr_status_t rv, apr_pool_t *p, const char *fmt,...)
Definition md_log.c:68
#define MD_LOG_MARK
Definition md_log.h:39
@ MD_LOG_ERR
Definition md_log.h:24
const char * md_util_parse_ct(apr_pool_t *pool, const char *cth)
Definition md_util.c:1547
apr_status_t md_util_freplace(const char *fpath, apr_fileperms_t perms, apr_pool_t *p, md_util_file_cb *write_cb, void *baton)
Definition md_util.c:433
apr_status_t md_util_fcreatex(apr_file_t **pf, const char *fn, apr_fileperms_t perms, apr_pool_t *p)
Definition md_util.c:362
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
md_json_fmt_t fmt
Definition md_json.c:948
const md_json_t * json
Definition md_json.c:947
const char * fname
Definition md_json.c:949
apr_file_t * f
Definition md_json.c:950
apr_pool_t * p
Definition md_json.c:57
json_t * j
Definition md_json.c:58
apr_time_t end
Definition md_time.h:29
apr_time_t start
Definition md_time.h:28
apr_pool_t * pool
Definition md_json.c:1205
md_json_t * json
Definition md_json.c:1206
apr_status_t rv
Definition md_json.c:1204
apr_status_t apr_rfc822_date(char *date_str, apr_time_t t)
Definition timestr.c:42