1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include <thread.h>
6 #include <plumb.h>
7 #include <9p.h>
8
9 #include "dat.h"
10 #include "fns.h"
11
12 static int plumbsendfd;
13 static int plumbwebfd;
14 static Channel *plumbchan;
15
16 static void plumbwebproc(void*);
17 static void plumbwebthread(void*);
18 static void plumbsendproc(void*);
19
20 void
plumbinit(void)21 plumbinit(void)
22 {
23 plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
24 plumbwebfd = plumbopen("web", OREAD|OCEXEC);
25 }
26
27 void
plumbstart(void)28 plumbstart(void)
29 {
30 plumbchan = chancreate(sizeof(Plumbmsg*), 0);
31 proccreate(plumbwebproc, nil, STACK);
32 threadcreate(plumbwebthread, nil, STACK);
33 }
34
35 static void
plumbwebthread(void *)36 plumbwebthread(void*)
37 {
38 char *base;
39 Plumbmsg *m;
40
41 for(;;){
42 m = recvp(plumbchan);
43 if(m == nil)
44 threadexits(nil);
45 base = plumblookup(m->attr, "baseurl");
46 if(base == nil)
47 base = m->wdir;
48 plumburl(m->data, base);
49 plumbfree(m);
50 }
51 }
52
53 static void
plumbwebproc(void *)54 plumbwebproc(void*)
55 {
56 Plumbmsg *m;
57
58 for(;;){
59 m = plumbrecv(plumbwebfd);
60 sendp(plumbchan, m);
61 if(m == nil)
62 threadexits(nil);
63 }
64 }
65
66 static void
addattr(Plumbmsg * m,char * name,char * value)67 addattr(Plumbmsg *m, char *name, char *value)
68 {
69 Plumbattr *a;
70
71 a = malloc(sizeof(Plumbattr));
72 a->name = name;
73 a->value = value;
74 a->next = m->attr;
75 m->attr = a;
76 }
77
78 static void
freeattrs(Plumbmsg * m)79 freeattrs(Plumbmsg *m)
80 {
81 Plumbattr *a, *next;
82
83 a = m->attr;
84 while(a != nil) {
85 next = a->next;
86 free(a);
87 a = next;
88 }
89 }
90
91 static struct
92 {
93 char *ctype;
94 char *ext;
95 }
96 ctypes[] =
97 {
98 { "application/msword", "doc" },
99 { "application/pdf", "pdf" },
100 { "application/postscript", "ps" },
101 { "application/rtf", "rtf" },
102 { "image/gif", "gif" },
103 { "image/jpeg", "jpg" },
104 { "image/png", "png" },
105 { "image/ppm", "ppm" },
106 { "image/tiff", "tiff" },
107 { "text/html", "html" },
108 { "text/plain", "txt" },
109 { "text/xml", "xml" },
110 };
111
112 void
replumb(Client * c)113 replumb(Client *c)
114 {
115 int i;
116 Plumbmsg *m;
117 char name[128], *ctype, *ext, *p;
118
119 if(!c->plumbed)
120 return;
121 m = emalloc(sizeof(Plumbmsg));
122 m->src = "webfs";
123 m->dst = nil;
124 m->wdir = "/";
125 m->type = "text";
126 m->attr = nil;
127 addattr(m, "url", c->url->url);
128 ctype = c->contenttype;
129 ext = nil;
130 if(ctype != nil) {
131 addattr(m, "content-type", ctype);
132 for(i = 0; i < nelem(ctypes); i++) {
133 if(strcmp(ctype, ctypes[i].ctype) == 0) {
134 ext = ctypes[i].ext;
135 break;
136 }
137 }
138 }
139 if(ext == nil) {
140 p = strrchr(c->url->url, '/');
141 if(p != nil)
142 p = strrchr(p+1, '.');
143 if(p != nil && strlen(p) <= 5)
144 ext = p+1;
145 else
146 ext = "txt"; /* punt */
147 }
148 c->ext = ext;
149 if(0)fprint(2, "content type %s -> extension .%s\n", ctype, ext);
150 m->ndata = snprint(name, sizeof name, "/mnt/web/%d/body.%s", c->num, ext);
151 m->data = estrdup(name);
152 proccreate(plumbsendproc, m, STACK); /* separate proc to avoid a deadlock */
153 }
154
155 static void
plumbsendproc(void * x)156 plumbsendproc(void *x)
157 {
158 Plumbmsg *m;
159
160 m = x;
161 plumbsend(plumbsendfd, m);
162 freeattrs(m);
163 free(m->data);
164 free(m);
165 }
166