Allow Content-Type application/sru+xml YAZ-840
[yaz-moved-to-github.git] / util / yaz-url.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5
6 #if HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9
10 #include <string.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <yaz/url.h>
14 #include <yaz/options.h>
15 #include <yaz/log.h>
16 #include <yaz/backtrace.h>
17
18 static void usage(void)
19 {
20     printf("yaz-icu [options] url ..\n");
21     printf(" -H name:value       Sets HTTP header (repeat if necessary)\n");
22     printf(" -m method           Sets HTTP method\n");
23     printf(" -O fname            Writes HTTP content to file\n");
24     printf(" -p fname            POSTs file at following url\n");
25     printf(" -R num              Set maximum number of HTTP redirects\n");
26     printf(" -u user/password    Sets Basic HTTP auth\n");
27     printf(" -v                  Verbose\n");
28     printf(" -x proxy            Sets HTTP proxy\n");
29     exit(1);
30 }
31
32 static char *get_file(const char *fname, size_t *len)
33 {
34     char *buf = 0;
35     FILE *inf = fopen(fname, "rb");
36     if (!inf)
37     {
38         yaz_log(YLOG_FATAL|YLOG_ERRNO, "Could not open %s", fname);
39         exit(1);
40     }
41     if (fseek(inf, 0L, SEEK_END))
42     {
43         yaz_log(YLOG_FATAL|YLOG_ERRNO, "fseek of %s failed", fname);
44         exit(1);
45     }
46     *len = ftell(inf);
47     if (*len)  /* zero length not considered an error */
48     {
49         size_t r;
50         buf = xmalloc(*len);
51         fseek(inf, 0L, SEEK_SET);
52         r = fread(buf, 1, *len, inf);
53         if (r != *len)
54         {
55             yaz_log(YLOG_FATAL|YLOG_ERRNO, "short fread of %s", fname);
56             exit(1);
57         }
58     }
59     fclose(inf);
60     return buf;
61 }
62
63 int main(int argc, char **argv)
64 {
65     int ret;
66     char *arg;
67     yaz_url_t p = yaz_url_create();
68     char *post_buf = 0;
69     size_t post_len = 0;
70     const char *method = "GET";
71     Z_HTTP_Response *http_response;
72     Z_HTTP_Header *http_headers = 0;
73     ODR odr = odr_createmem(ODR_ENCODE);
74     int exit_code = 0;
75     int no_urls = 0;
76     const char *outfname = 0;
77
78     yaz_enable_panic_backtrace(*argv);
79     while ((ret = options("h{help}H:m:O:p:R{max-redirs}:u:vx:", argv, argc, &arg))
80            != YAZ_OPTIONS_EOF)
81     {
82         switch (ret)
83         {
84         case 'h':
85             usage();
86             break;
87         case 'H':
88             if (!strchr(arg, ':'))
89             {
90                 yaz_log(YLOG_FATAL, "bad header option (missing :) %s\n", arg);
91                 exit_code = 1;
92             }
93             else
94             {
95                 char *cp = strchr(arg, ':');
96                 char *name = odr_malloc(odr, 1 + cp - arg);
97                 char *value = cp + 1;
98                 memcpy(name, arg, cp - arg);
99                 name[cp - arg] = '\0';
100                 while (*value == ' ') /* skip space after = */
101                     value++;
102                 z_HTTP_header_add(odr, &http_headers, name, value);
103             }
104             break;
105         case 'm':
106             method = arg;
107             break;
108         case 'O':
109             outfname = arg;
110             break;
111         case 'p':
112             xfree(post_buf);
113             post_buf = get_file(arg, &post_len);
114             method = "POST";
115             break;
116         case 'R':
117             yaz_url_set_max_redirects(p, atoi(arg));
118             break;
119         case 'u':
120             if (strchr(arg, '/'))
121             {
122                 char *cp = strchr(arg, '/');
123                 char *user = odr_malloc(odr, 1 + cp - arg);
124                 char *password = cp + 1;
125                 memcpy(user, arg, cp - arg);
126                 user[cp - arg] = '\0';
127                 z_HTTP_header_add_basic_auth(odr, &http_headers, user,
128                                              password);
129             }
130             else
131                 z_HTTP_header_add_basic_auth(odr, &http_headers, arg, 0);
132             break;
133         case 'v':
134             yaz_url_set_verbose(p, 1);
135             break;
136         case 'x':
137             yaz_url_set_proxy(p, arg);
138             break;
139         case 0:
140             http_response = yaz_url_exec(p, arg, method, http_headers,
141                                          post_buf, post_len);
142             if (!http_response)
143                 exit_code = 1;
144             else
145             {
146                 FILE *outf = stdout;
147                 if (outfname)
148                 {
149                     outf = fopen(outfname, "w");
150                     if (!outf)
151                     {
152                         yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", outfname);
153                         exit(1);
154                     }
155                 }
156                 fwrite(http_response->content_buf, 1,
157                        http_response->content_len, outf);
158                 if (outfname)
159                     fclose(outf);
160             }
161             no_urls++;
162             break;
163         default:
164             usage();
165         }
166     }
167     xfree(post_buf);
168     yaz_url_destroy(p);
169     odr_destroy(odr);
170     if (no_urls == 0)
171         usage();
172     exit(exit_code);
173 }
174
175 /*
176  * Local variables:
177  * c-basic-offset: 4
178  * c-file-style: "Stroustrup"
179  * indent-tabs-mode: nil
180  * End:
181  * vim: shiftwidth=4 tabstop=8 expandtab
182  */
183