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