• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 #include "tool_setup.h"
25 
26 #define ENABLE_CURLX_PRINTF
27 
28 /* use our own printf() functions */
29 #include "curlx.h"
30 #include "tool_cfgable.h"
31 #include "tool_writeout_json.h"
32 #include "tool_writeout.h"
33 
jsonWriteString(FILE * stream,const char * in,bool lowercase)34 void jsonWriteString(FILE *stream, const char *in, bool lowercase)
35 {
36   const char *i = in;
37   const char *in_end = in + strlen(in);
38 
39   fputc('\"', stream);
40   for(; i < in_end; i++) {
41     switch(*i) {
42     case '\\':
43       fputs("\\\\", stream);
44       break;
45     case '\"':
46       fputs("\\\"", stream);
47       break;
48     case '\b':
49       fputs("\\b", stream);
50       break;
51     case '\f':
52       fputs("\\f", stream);
53       break;
54     case '\n':
55       fputs("\\n", stream);
56       break;
57     case '\r':
58       fputs("\\r", stream);
59       break;
60     case '\t':
61       fputs("\\t", stream);
62       break;
63     default:
64       if (*i < 32) {
65         fprintf(stream, "u%04x", *i);
66       }
67       else {
68         char out = *i;
69         if(lowercase && (out >= 'A' && out <= 'Z'))
70           /* do not use tolower() since that's locale specific */
71           out |= ('a' - 'A');
72         fputc(out, stream);
73       }
74       break;
75     }
76   }
77   fputc('\"', stream);
78 }
79 
ourWriteOutJSON(FILE * stream,const struct writeoutvar mappings[],struct per_transfer * per,CURLcode per_result)80 void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
81                      struct per_transfer *per, CURLcode per_result)
82 {
83   int i;
84 
85   fputs("{", stream);
86 
87   for(i = 0; mappings[i].name != NULL; i++) {
88     if(mappings[i].writefunc &&
89        mappings[i].writefunc(stream, &mappings[i], per, per_result, true))
90       fputs(",", stream);
91   }
92 
93   /* The variables are sorted in alphabetical order but as a special case
94      curl_version (which is not actually a --write-out variable) is last. */
95   fprintf(stream, "\"curl_version\":");
96   jsonWriteString(stream, curl_version(), FALSE);
97   fprintf(stream, "}");
98 }
99 
100 #ifdef _MSC_VER
101 /* warning C4706: assignment within conditional expression */
102 #pragma warning(disable:4706)
103 #endif
104 
headerJSON(FILE * stream,struct per_transfer * per)105 void headerJSON(FILE *stream, struct per_transfer *per)
106 {
107   struct curl_header *header;
108   struct curl_header *prev = NULL;
109 
110   fputc('{', stream);
111   while((header = curl_easy_nextheader(per->curl, CURLH_HEADER, -1,
112                                        prev))) {
113     if(header->amount > 1) {
114       if(!header->index) {
115         /* act on the 0-index entry and pull the others in, then output in a
116            JSON list */
117         size_t a = header->amount;
118         size_t i = 0;
119         char *name = header->name;
120         if(prev)
121           fputs(",\n", stream);
122         jsonWriteString(stream, header->name, TRUE);
123         fputc(':', stream);
124         prev = header;
125         fputc('[', stream);
126         do {
127           jsonWriteString(stream, header->value, FALSE);
128           if(++i >= a)
129             break;
130           fputc(',', stream);
131           if(curl_easy_header(per->curl, name, i, CURLH_HEADER,
132                               -1, &header))
133             break;
134         } while(1);
135         fputc(']', stream);
136       }
137     }
138     else {
139       if(prev)
140         fputs(",\n", stream);
141       jsonWriteString(stream, header->name, TRUE);
142       fputc(':', stream);
143       fputc('[', stream);
144       jsonWriteString(stream, header->value, FALSE);
145       fputc(']', stream);
146       prev = header;
147     }
148   }
149   fputs("\n}", stream);
150 }
151