xref: /plan9/sys/src/cmd/abaco/urls.c (revision 7ab27030036b6c877a6f81728daeda263d1ca3cf)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <thread.h>
6 #include <cursor.h>
7 #include <mouse.h>
8 #include <keyboard.h>
9 #include <frame.h>
10 #include <plumb.h>
11 #include <html.h>
12 #include "dat.h"
13 #include "fns.h"
14 
15 Url *
urlalloc(Runestr * src,Runestr * post,int m)16 urlalloc(Runestr *src, Runestr *post, int m)
17 {
18 	Url *u;
19 
20 	u = emalloc(sizeof(Url));
21 	copyrunestr(&u->src, src);
22 	if(m==HPost)
23 		copyrunestr(&u->post, post);
24 	u->method = m;
25 	incref(u);
26 	return u;
27 }
28 
29 void
urlfree(Url * u)30 urlfree(Url *u)
31 {
32 	if(u && decref(u)==0){
33 		closerunestr(&u->src);
34 		closerunestr(&u->act);
35 		closerunestr(&u->post);
36 		closerunestr(&u->ctype);
37 		free(u);
38 	}
39 }
40 
41 Url *
urldup(Url * a)42 urldup(Url *a)
43 {
44 	Url *b;
45 
46 	b = emalloc(sizeof(Url));
47 	b->method = a->method;
48 	copyrunestr(&b->src, &a->src);
49 	copyrunestr(&b->act, &a->act);
50 	copyrunestr(&b->post, &a->post);
51 	copyrunestr(&b->ctype, &a->ctype);
52 	return b;
53 }
54 
55 static
56 Runestr
getattr(int conn,char * s)57 getattr(int conn, char *s)
58 {
59 	char buf[BUFSIZE];
60 	int fd, n;
61 
62 	snprint(buf, sizeof(buf), "%s/%d/%s", webmountpt, conn, s);
63 	fd = open(buf, OREAD);
64 	if(fd < 0)
65 		error("can't open attr file");
66 
67 	n = read(fd, buf, sizeof(buf)-1);
68 	if(n < 0)
69 		error("can't read");
70 
71 	close(fd);
72 	buf[n] = '\0';
73 	return (Runestr){runesmprint("%s", buf), n};
74 }
75 
76 int
urlopen(Url * u)77 urlopen(Url *u)
78 {
79 	char buf[BUFSIZE];
80 	int cfd, fd, conn, n;
81 
82 	snprint(buf, sizeof(buf), "%s/clone", webmountpt);
83 	cfd = open(buf, ORDWR);
84 	if(cfd < 0)
85 		error("can't open clone file");
86 
87 	n = read(cfd, buf, sizeof(buf)-1);
88 	if(n <= 0)
89 		error("reading clone");
90 
91 	buf[n] = '\0';
92 	conn = atoi(buf);
93 
94 	snprint(buf, sizeof(buf), "url %S", u->src.r);
95 	if(write(cfd, buf, strlen(buf)) < 0){
96 //		fprint(2, "write: %s: %r\n", buf);
97     Err:
98 		close(cfd);
99 		return -1;
100 	}
101 	if(u->method==HPost && u->post.r != nil){
102 		snprint(buf, sizeof(buf), "%s/%d/postbody", webmountpt, conn);
103 		fd = open(buf, OWRITE);
104 		if(fd < 0){
105 //			fprint(2, "urlopen: bad query: %s: %r\n", buf);
106 			goto Err;
107 		}
108 		snprint(buf, sizeof(buf), "%S", u->post.r);
109 		if(write(fd, buf, strlen(buf)) < 0)
110 			fprint(2, "urlopen: bad query: %s: %r\n", buf);
111 
112 		close(fd);
113 	}
114 	snprint(buf, sizeof(buf), "%s/%d/body", webmountpt, conn);
115 	fd = open(buf, OREAD);
116 	if(fd < 0){
117 //		fprint(2, "open: %S: %r\n", u->src.r);
118 		goto Err;
119 	}
120 	u->ctype = getattr(conn, "contenttype");
121 	u->act = getattr(conn, "parsed/url");
122 	if(u->act.nr == 0)
123 		copyrunestr(&u->act, &u->src);
124 	close(cfd);
125 	return fd;
126 }
127 
128 void
urlcanon(Rune * name)129 urlcanon(Rune *name){
130 	Rune *s, *t;
131 	Rune **comp, **p, **q;
132 	int rooted;
133 
134 	name = runestrchr(name, L'/')+2;
135 	rooted=name[0]==L'/';
136 	/*
137 	 * Break the name into a list of components
138 	 */
139 	comp=emalloc(runestrlen(name)*sizeof(char *));
140 	p=comp;
141 	*p++=name;
142 	for(s=name;;s++){
143 		if(*s==L'/'){
144 			*p++=s+1;
145 			*s='\0';
146 		}
147 		else if(*s=='\0')
148 			break;
149 	}
150 	*p=0;
151 	/*
152 	 * go through the component list, deleting components that are empty (except
153 	 * the last component) or ., and any .. and its non-.. predecessor.
154 	 */
155 	p=q=comp;
156 	while(*p){
157 		if(runestrcmp(*p, L"")==0 && p[1]!=0
158 		|| runestrcmp(*p, L".")==0)
159 			p++;
160 		else if(runestrcmp(*p, L"..")==0 && q!=comp && runestrcmp(q[-1], L"..")!=0){
161 			--q;
162 			p++;
163 		}
164 		else
165 			*q++=*p++;
166 	}
167 	*q=0;
168 	/*
169 	 * rebuild the path name
170 	 */
171 	s=name;
172 	if(rooted) *s++='/';
173 	for(p=comp;*p;p++){
174 		t=*p;
175 		while(*t) *s++=*t++;
176 		if(p[1]!=0) *s++='/';
177 	}
178 	*s='\0';
179 	free(comp);
180 }
181 
182 /* this is a HACK */
183 Rune *
urlcombine(Rune * b,Rune * u)184 urlcombine(Rune *b, Rune *u)
185 {
186 	Rune *p, *q, *sep, *s;
187 	Rune endrune[] = { L'?', L'#' };
188 	int i, restore;
189 
190 	if(u == nil)
191 		error("urlcombine: u == nil");
192 
193 	if(validurl(u))
194 		return erunestrdup(u);
195 
196 	if(b==nil || !validurl(b))
197 		error("urlcombine: b==nil || !validurl(b)");
198 
199 	if(runestrncmp(u, L"//", 2) == 0){
200 		q =  runestrchr(b, L':');
201 		return runesmprint("%.*S:%S", (int)(q-b), b, u);
202 	}
203 	p = runestrstr(b, L"://")+3;
204 	sep = L"";
205 	q = nil;
206 	if(*u ==L'/')
207 		q = runestrchr(p, L'/');
208 	else if(*u==L'#' || *u==L'?'){
209 		for(i=0; i<nelem(endrune); i++)
210 			if(q = runestrchr(p, endrune[i]))
211 				break;
212 	}else{
213 		sep = L"/";
214 		restore = 0;
215 		s = runestrchr(p, L'?');
216 		if(s != nil){
217 			*s = '\0';
218 			restore = 1;
219 		}
220 		q = runestrrchr(p, L'/');
221 		if(restore)
222 			*s = L'?';
223 	}
224 	if(q == nil)
225 		p = runesmprint("%S%S%S", b, sep, u);
226 	else
227 		p = runesmprint("%.*S%S%S", (int)(q-b), b, sep, u);
228 	urlcanon(p);
229 	return p;
230 }
231