]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mothra/url.c
cwfs: fix listen filedescriptor leaks
[plan9front.git] / sys / src / cmd / mothra / url.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <event.h>
5 #include <panel.h>
6 #include "mothra.h"
7
8 static int
9 hexdigit(int c)
10 {
11         if(c >= '0' && c <= '9')
12                 return c-'0';
13         if(c >= 'a' && c <= 'f')
14                 return c-'a'+10;
15         if(c >= 'A' && c <= 'F')
16                 return c-'A'+10;
17         return -1;
18 }
19
20 static int
21 dechex(uchar *out, int lim, char *in, int n)
22 {
23         uchar *start, *end;
24         int c;
25
26         start = out;
27         end = start + lim;
28         while(n-- > 0 && out < end){
29                 c = *in++;
30                 if(c == 0)
31                         break;
32                 if(c & 0x80)
33                         return -1;
34                 if(c == '%'){
35                         n -= 2;
36                         if(n < 0 || (c = hexdigit(*in++)) == -1)
37                                 return -1;
38                         if((c = (c << 4) | hexdigit(*in++)) == -1)
39                                 return -1;
40                 }
41                 *out++ = c;
42         }
43         return out - start;
44 }
45
46 static int
47 dataget(Url *url)
48 {
49         int (*decfun)(uchar *, int, char *, int) = dechex;
50         char *s, *p;
51         int fd, n, m;
52
53         s = url->reltext;
54         if(cistrncmp(s, "data:", 5) != 0)
55                 return -1;
56         s += 5;
57         if((p = strchr(s, ',')) != nil){
58                 *p = 0;
59                 if(strstr(s, "base64") != nil)
60                         decfun = dec64;
61                 *p = ',';
62                 s = p+1;
63         } else
64                 s = strchr(s, 0);
65         n = strlen(s);
66         m = n+64;
67         p = malloc(m);
68         strcpy(p, "/tmp/duXXXXXXXXXXX");
69         if((fd = create(mktemp(p), ORDWR|ORCLOSE, 0600)) < 0){
70                 free(p);
71                 return -1;
72         }
73         if((m = (*decfun)((uchar*)p, m, s, n)) < 0 || write(fd, p, m) != m){
74                 free(p);
75                 close(fd);
76                 return -1;
77         }
78         free(p);
79         seek(fd, 0, 0);
80         return fd;
81 }
82
83 static int
84 fileget(Url *url)
85 {
86         char *rel, *base, *x;
87
88         rel = base = nil;
89         if(cistrncmp(url->basename, "file:", 5) == 0)
90                 base = url->basename+5;
91         if(cistrncmp(url->reltext, "file:", 5) == 0)
92                 rel = url->reltext+5;
93         if(rel == nil && base == nil)
94                 return -1;
95         if(rel == nil)
96                 rel = url->reltext;
97         if(base && base[0] == '/' && rel[0] != '/'){
98                 if(x = strrchr(base, '/'))
99                         *x = 0;
100                 snprint(url->fullname, sizeof(url->fullname), "%s/%s", base, rel);
101                 if(x)   *x = '/';
102         }else
103                 snprint(url->fullname, sizeof(url->fullname), "%s", rel);
104         url->tag[0] = 0;
105         if(x = strrchr(url->fullname, '#')){
106                 *x++ = 0;
107                 nstrcpy(url->tag, x, sizeof(url->tag));
108         }
109         base = cleanname(url->fullname);
110         x = base + strlen(base)+1;
111         if((x - base) > sizeof(url->fullname)-5)
112                 return -1;
113         memmove(url->fullname+5, base, x - base);
114         memmove(url->fullname, "file:", 5);
115         return open(url->fullname+5, OREAD);
116 }
117
118 char *mtpt="/mnt/web";
119
120 static int
121 webclone(Url *url, char *buf, int nbuf)
122 {
123         int n, conn, fd;
124
125         snprint(buf, nbuf, "%s/clone", mtpt);
126         if((fd = open(buf, ORDWR)) < 0)
127                 return -1;
128         if((n = read(fd, buf, nbuf-1)) <= 0){
129                 close(fd);
130                 return -1;
131         }
132         buf[n] = 0;
133         conn = atoi(buf);
134         if(url && url->reltext[0]){
135                 if(url->basename[0]){
136                         n = snprint(buf, nbuf, "baseurl %s", url->basename);
137                         write(fd, buf, n);
138                 }
139                 n = snprint(buf, nbuf, "url %s", url->reltext);
140                 if(write(fd, buf, n) < 0){
141                         close(fd);
142                         return -1;
143                 }
144         }
145         snprint(buf, nbuf, "%s/%d", mtpt, conn);
146         return fd;
147 }
148
149 static int
150 readstr(char *path, char *buf, int nbuf){
151         int n, fd;
152
153         n = 0;
154         if((fd = open(path, OREAD)) >= 0){
155                 if((n = read(fd, buf, nbuf-1)) < 0)
156                         n = 0;
157                 close(fd);
158         }
159         buf[n] = 0;
160         return n;
161 }
162
163 int
164 urlpost(Url *url, char *ctype)
165 {
166         char buf[1024];
167         int n, fd;
168
169         if((fd = webclone(url, buf, sizeof(buf))) < 0)
170                 return -1;
171         if(ctype && *ctype)
172                 fprint(fd, "contenttype %s", ctype);
173         n = strlen(buf);
174         snprint(buf+n, sizeof(buf)-n, "/postbody");
175         n = open(buf, OWRITE);
176         close(fd);
177         return n;
178 }
179
180 int
181 urlget(Url *url, int body)
182 {
183         char buf[1024];
184         int n, fd;
185
186         if(body < 0){
187                 if((fd = dataget(url)) >= 0)
188                         return fd;
189                 if((fd = fileget(url)) >= 0)
190                         return fd;
191                 if((fd = webclone(url, buf, sizeof(buf))) < 0)
192                         return -1;
193         }else{
194                 char *x;
195
196                 if(fd2path(body, buf, sizeof(buf))){
197                         close(body);
198                         return -1;
199                 }
200                 if(x = strrchr(buf, '/'))
201                         *x = 0;
202                 fd = open(buf, OREAD);
203                 close(body);
204         }
205         n = strlen(buf);
206         snprint(buf+n, sizeof(buf)-n, "/body");
207         body = open(buf, OREAD);
208         close(fd);
209         fd = body;
210         if(fd < 0)
211                 return -1;
212
213         snprint(buf+n, sizeof(buf)-n, "/parsed/url");
214         readstr(buf, url->fullname, sizeof(url->fullname));
215
216         snprint(buf+n, sizeof(buf)-n, "/parsed/fragment");
217         readstr(buf, url->tag, sizeof(url->tag));
218
219         snprint(buf+n, sizeof(buf)-n, "/contentencoding");
220         readstr(buf, buf, sizeof(buf));
221
222         if(!cistrcmp(buf, "compress"))
223                 fd = pipeline(fd, "exec uncompress");
224         else if(!cistrcmp(buf, "gzip"))
225                 fd = pipeline(fd, "exec gunzip");
226         else if(!cistrcmp(buf, "bzip2"))
227                 fd = pipeline(fd, "exec bunzip2");
228
229         return fd;
230 }
231
232 int
233 urlresolve(Url *url)
234 {
235         char buf[1024];
236         int n, fd;
237
238         if((fd = webclone(url, buf, sizeof(buf))) < 0)
239                 return -1;
240         n = strlen(buf);
241         snprint(buf+n, sizeof(buf)-n, "/parsed/url");
242         readstr(buf, url->fullname, sizeof(url->fullname));
243         snprint(buf+n, sizeof(buf)-n, "/parsed/fragment");
244         readstr(buf, url->tag, sizeof(url->tag));
245         close(fd);
246         return 0;
247 }