]> mj.ucw.cz Git - libucw.git/blob - ucw/utils/ucw-urltool.c
Macros: CLAMP now accepts arbitrary types, not only ints
[libucw.git] / ucw / utils / ucw-urltool.c
1 /*
2  *      Sherlock Utilities -- URL Handling Tool
3  *
4  *      (c) 2004 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <ucw/lib.h>
8 #include <ucw/getopt.h>
9 #include <ucw/url.h>
10 #include <ucw/fastbuf.h>
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 static byte *base_url;
17 static struct url base;
18 static uint opt_split = 0, opt_normalize = 0, opt_forgive = 0;
19 static struct fastbuf *fout;
20 static uint err_count;
21
22 static void
23 process_url(byte *url)
24 {
25   byte buf1[MAX_URL_SIZE], buf2[MAX_URL_SIZE], buf3[MAX_URL_SIZE], buf4[MAX_URL_SIZE];
26   int e;
27   struct url ur;
28
29   if ((e = url_deescape(url, buf1)) || (e = url_split(buf1, &ur, buf2)))
30     goto error;
31   if ((base_url || opt_normalize) && (e = url_normalize(&ur, &base)))
32     goto error;
33   if (opt_normalize && (e = url_canonicalize(&ur)))
34     goto error;
35   if (opt_split)
36     {
37       if (ur.protocol)
38         bprintf(fout, "protocol=%s\n", ur.protocol);
39       if (ur.user)
40         bprintf(fout, "user=%s\n", ur.user);
41       if (ur.pass)
42         bprintf(fout, "pass=%s\n", ur.pass);
43       if (ur.host)
44         bprintf(fout, "host=%s\n", ur.host);
45       if (ur.port != ~0U)
46         bprintf(fout, "port=%d\n", ur.port);
47       if (ur.rest)
48         bprintf(fout, "rest=%s\n", ur.rest);
49       bputc(fout, '\n');
50     }
51   else
52     {
53       if ((e = url_pack(&ur, buf3)) || (e = url_enescape(buf3, buf4)))
54         goto error;
55       bprintf(fout, "%s\n", buf4);
56     }
57   return;
58
59  error:
60   msg(L_ERROR, "%s: %s", url, url_error(e));
61   err_count++;
62 }
63
64 static char *shortopts = CF_SHORT_OPTS "b:fns";
65 static struct option longopts[] =
66 {
67   CF_LONG_OPTS
68   { "base",             1, 0, 'b' },
69   { "forgive",          0, 0, 'f' },
70   { "normalize",        0, 0, 'n' },
71   { "split",            0, 0, 's' },
72   { NULL,               0, 0, 0 }
73 };
74
75 static char *help = "\
76 Usage: ucw-urltool [<options>] <operations> [<URL's>]\n\
77 \n\
78 Options:\n"
79 CF_USAGE "\
80 -b, --base <URL>\tInput URL's are relative to this base\n\
81 -f, --forgive\t\tReturn exit status 0 even if there were errors\n\
82 \n\
83 Operations:\n\
84 -s, --split\t\tSplit a given URL to components\n\
85 -n, --normalize\t\tNormalize given URL\n\
86 ";
87
88 static void NONRET
89 usage(byte *msg)
90 {
91   if (msg)
92     {
93       fputs(msg, stderr);
94       fputc('\n', stderr);
95     }
96   fputs(help, stderr);
97   exit(1);
98 }
99
100 int
101 main(int argc, char **argv)
102 {
103   int opt, err;
104   byte *base_url = NULL;
105   byte basebuf1[MAX_URL_SIZE], basebuf2[MAX_URL_SIZE];
106
107   log_init(argv[0]);
108   while ((opt = cf_getopt(argc, argv, shortopts, longopts, NULL)) >= 0)
109     switch (opt)
110       {
111       case 'b':
112         base_url = optarg;
113         err = url_canon_split(base_url, basebuf1, basebuf2, &base);
114         if (err)
115           die("Invalid base URL: %s", url_error(err));
116         break;
117       case 's':
118         opt_split = 1;
119         break;
120       case 'n':
121         opt_normalize = 1;
122         break;
123       case 'f':
124         opt_forgive = 1;
125         break;
126       default:
127         usage("Invalid option");
128       }
129
130   fout = bfdopen_shared(1, 4096);
131   if (optind >= argc)
132     {
133       struct fastbuf *fin = bfdopen_shared(0, 4096);
134       byte url[MAX_URL_SIZE];
135       while (bgets(fin, url, sizeof(url)))
136         process_url(url);
137       bclose(fin);
138     }
139   else
140     while (optind < argc)
141       process_url(argv[optind++]);
142   bclose(fout);
143
144   return (err_count && !opt_forgive);
145 }