curl tool: add filename_effective token for --write-out
[platform/upstream/curl.git] / src / tool_writeout.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2011, 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 http://curl.haxx.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  ***************************************************************************/
22 #include "setup.h"
23
24 #include <curl/curl.h>
25
26 #define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
27 #include <curl/mprintf.h>
28
29 #include "tool_cfgable.h"
30 #include "tool_writeout.h"
31
32 #include "memdebug.h" /* keep this as LAST include */
33
34 typedef enum {
35   VAR_NONE,       /* must be the first */
36   VAR_TOTAL_TIME,
37   VAR_NAMELOOKUP_TIME,
38   VAR_CONNECT_TIME,
39   VAR_APPCONNECT_TIME,
40   VAR_PRETRANSFER_TIME,
41   VAR_STARTTRANSFER_TIME,
42   VAR_SIZE_DOWNLOAD,
43   VAR_SIZE_UPLOAD,
44   VAR_SPEED_DOWNLOAD,
45   VAR_SPEED_UPLOAD,
46   VAR_HTTP_CODE,
47   VAR_HTTP_CODE_PROXY,
48   VAR_HEADER_SIZE,
49   VAR_REQUEST_SIZE,
50   VAR_EFFECTIVE_URL,
51   VAR_CONTENT_TYPE,
52   VAR_NUM_CONNECTS,
53   VAR_REDIRECT_TIME,
54   VAR_REDIRECT_COUNT,
55   VAR_FTP_ENTRY_PATH,
56   VAR_REDIRECT_URL,
57   VAR_SSL_VERIFY_RESULT,
58   VAR_EFFECTIVE_FILENAME,
59   VAR_NUM_OF_VARS /* must be the last */
60 } replaceid;
61
62 struct variable {
63   const char *name;
64   replaceid id;
65 };
66
67
68 static const struct variable replacements[]={
69   {"url_effective", VAR_EFFECTIVE_URL},
70   {"http_code", VAR_HTTP_CODE},
71   {"response_code", VAR_HTTP_CODE},
72   {"http_connect", VAR_HTTP_CODE_PROXY},
73   {"time_total", VAR_TOTAL_TIME},
74   {"time_namelookup", VAR_NAMELOOKUP_TIME},
75   {"time_connect", VAR_CONNECT_TIME},
76   {"time_appconnect", VAR_APPCONNECT_TIME},
77   {"time_pretransfer", VAR_PRETRANSFER_TIME},
78   {"time_starttransfer", VAR_STARTTRANSFER_TIME},
79   {"size_header", VAR_HEADER_SIZE},
80   {"size_request", VAR_REQUEST_SIZE},
81   {"size_download", VAR_SIZE_DOWNLOAD},
82   {"size_upload", VAR_SIZE_UPLOAD},
83   {"speed_download", VAR_SPEED_DOWNLOAD},
84   {"speed_upload", VAR_SPEED_UPLOAD},
85   {"content_type", VAR_CONTENT_TYPE},
86   {"num_connects", VAR_NUM_CONNECTS},
87   {"time_redirect", VAR_REDIRECT_TIME},
88   {"num_redirects", VAR_REDIRECT_COUNT},
89   {"ftp_entry_path", VAR_FTP_ENTRY_PATH},
90   {"redirect_url", VAR_REDIRECT_URL},
91   {"ssl_verify_result", VAR_SSL_VERIFY_RESULT},
92   {"filename_effective", VAR_EFFECTIVE_FILENAME},
93   {NULL, VAR_NONE}
94 };
95
96 void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo)
97 {
98   FILE *stream = stdout;
99   const char *ptr = writeinfo;
100   char *stringp;
101   long longinfo;
102   double doubleinfo;
103
104   while(ptr && *ptr) {
105     if('%' == *ptr) {
106       if('%' == ptr[1]) {
107         /* an escaped %-letter */
108         fputc('%', stream);
109         ptr += 2;
110       }
111       else {
112         /* this is meant as a variable to output */
113         char *end;
114         char keepit;
115         int i;
116         if(('{' == ptr[1]) && ((end = strchr(ptr, '}')) != NULL)) {
117           bool match = FALSE;
118           ptr += 2; /* pass the % and the { */
119           keepit = *end;
120           *end = 0; /* zero terminate */
121           for(i = 0; replacements[i].name; i++) {
122             if(curl_strequal(ptr, replacements[i].name)) {
123               match = TRUE;
124               switch(replacements[i].id) {
125               case VAR_EFFECTIVE_URL:
126                 if((CURLE_OK ==
127                     curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &stringp))
128                    && stringp)
129                   fputs(stringp, stream);
130                 break;
131               case VAR_HTTP_CODE:
132                 if(CURLE_OK ==
133                    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &longinfo))
134                   fprintf(stream, "%03ld", longinfo);
135                 break;
136               case VAR_HTTP_CODE_PROXY:
137                 if(CURLE_OK ==
138                    curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE,
139                                      &longinfo))
140                   fprintf(stream, "%03ld", longinfo);
141                 break;
142               case VAR_HEADER_SIZE:
143                 if(CURLE_OK ==
144                    curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &longinfo))
145                   fprintf(stream, "%ld", longinfo);
146                 break;
147               case VAR_REQUEST_SIZE:
148                 if(CURLE_OK ==
149                    curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &longinfo))
150                   fprintf(stream, "%ld", longinfo);
151                 break;
152               case VAR_NUM_CONNECTS:
153                 if(CURLE_OK ==
154                    curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &longinfo))
155                   fprintf(stream, "%ld", longinfo);
156                 break;
157               case VAR_REDIRECT_COUNT:
158                 if(CURLE_OK ==
159                    curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &longinfo))
160                   fprintf(stream, "%ld", longinfo);
161                 break;
162               case VAR_REDIRECT_TIME:
163                 if(CURLE_OK ==
164                    curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME,
165                                      &doubleinfo))
166                   fprintf(stream, "%.3f", doubleinfo);
167                 break;
168               case VAR_TOTAL_TIME:
169                 if(CURLE_OK ==
170                    curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &doubleinfo))
171                   fprintf(stream, "%.3f", doubleinfo);
172                 break;
173               case VAR_NAMELOOKUP_TIME:
174                 if(CURLE_OK ==
175                    curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME,
176                                      &doubleinfo))
177                   fprintf(stream, "%.3f", doubleinfo);
178                 break;
179               case VAR_CONNECT_TIME:
180                 if(CURLE_OK ==
181                    curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &doubleinfo))
182                   fprintf(stream, "%.3f", doubleinfo);
183                 break;
184               case VAR_APPCONNECT_TIME:
185                 if(CURLE_OK ==
186                    curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME,
187                                      &doubleinfo))
188                   fprintf(stream, "%.3f", doubleinfo);
189                 break;
190               case VAR_PRETRANSFER_TIME:
191                 if(CURLE_OK ==
192                    curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME,
193                                      &doubleinfo))
194                   fprintf(stream, "%.3f", doubleinfo);
195                 break;
196               case VAR_STARTTRANSFER_TIME:
197                 if(CURLE_OK ==
198                    curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME,
199                                      &doubleinfo))
200                   fprintf(stream, "%.3f", doubleinfo);
201                 break;
202               case VAR_SIZE_UPLOAD:
203                 if(CURLE_OK ==
204                    curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &doubleinfo))
205                   fprintf(stream, "%.0f", doubleinfo);
206                 break;
207               case VAR_SIZE_DOWNLOAD:
208                 if(CURLE_OK ==
209                    curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD,
210                                      &doubleinfo))
211                   fprintf(stream, "%.0f", doubleinfo);
212                 break;
213               case VAR_SPEED_DOWNLOAD:
214                 if(CURLE_OK ==
215                    curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD,
216                                      &doubleinfo))
217                   fprintf(stream, "%.3f", doubleinfo);
218                 break;
219               case VAR_SPEED_UPLOAD:
220                 if(CURLE_OK ==
221                    curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &doubleinfo))
222                   fprintf(stream, "%.3f", doubleinfo);
223                 break;
224               case VAR_CONTENT_TYPE:
225                 if((CURLE_OK ==
226                     curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &stringp))
227                    && stringp)
228                   fputs(stringp, stream);
229                 break;
230               case VAR_FTP_ENTRY_PATH:
231                 if((CURLE_OK ==
232                     curl_easy_getinfo(curl, CURLINFO_FTP_ENTRY_PATH, &stringp))
233                    && stringp)
234                   fputs(stringp, stream);
235                 break;
236               case VAR_REDIRECT_URL:
237                 if((CURLE_OK ==
238                     curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &stringp))
239                    && stringp)
240                   fputs(stringp, stream);
241                 break;
242               case VAR_SSL_VERIFY_RESULT:
243                 if(CURLE_OK ==
244                    curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT,
245                                      &longinfo))
246                   fprintf(stream, "%ld", longinfo);
247                 break;
248               case VAR_EFFECTIVE_FILENAME:
249                 if(outs->filename)
250                   fprintf(stream, "%s", outs->filename);
251                 break;
252               default:
253                 break;
254               }
255               break;
256             }
257           }
258           if(!match) {
259             fprintf(stderr, "curl: unknown --write-out variable: '%s'\n", ptr);
260           }
261           ptr = end + 1; /* pass the end */
262           *end = keepit;
263         }
264         else {
265           /* illegal syntax, then just output the characters that are used */
266           fputc('%', stream);
267           fputc(ptr[1], stream);
268           ptr += 2;
269         }
270       }
271     }
272     else if('\\' == *ptr) {
273       switch(ptr[1]) {
274       case 'r':
275         fputc('\r', stream);
276         break;
277       case 'n':
278         fputc('\n', stream);
279         break;
280       case 't':
281         fputc('\t', stream);
282         break;
283       default:
284         /* unknown, just output this */
285         fputc(*ptr, stream);
286         fputc(ptr[1], stream);
287         break;
288       }
289       ptr += 2;
290     }
291     else {
292       fputc(*ptr, stream);
293       ptr++;
294     }
295   }
296
297 }