32 |
32 |
33 #include "webdav.h" |
33 #include "webdav.h" |
34 #include "../ucx/string.h" |
34 #include "../ucx/string.h" |
35 #include "../util/pool.h" |
35 #include "../util/pool.h" |
36 #include "../util/pblock.h" |
36 #include "../util/pblock.h" |
|
37 #include "../util/date.h" |
37 |
38 |
38 #include "davparser.h" |
39 #include "davparser.h" |
39 |
40 |
40 int webdav_service(pblock *pb, Session *sn, Request *rq) { |
41 int webdav_service(pblock *pb, Session *sn, Request *rq) { |
41 return webdav_propfind(pb, sn, rq); |
42 char *method = pblock_findkeyval(pb_key_method, rq->reqpb); |
|
43 if(method == NULL) { |
|
44 return REQ_ABORTED; |
|
45 } |
|
46 |
|
47 if(!strcmp(method, "PROPFIND")) { |
|
48 return webdav_propfind(pb, sn, rq); |
|
49 } else if(!strcmp(method, "PUT")) { |
|
50 return webdav_put(pb, sn, rq); |
|
51 } |
|
52 |
|
53 return REQ_NOACTION; |
|
54 } |
|
55 |
|
56 int webdav_put(pblock *pb, Session *sn, Request *rq) { |
|
57 int length = 0; |
|
58 |
|
59 char *ctlen = pblock_findkeyval(pb_key_content_length, rq->headers); |
|
60 if(ctlen) { |
|
61 length = atoi(ctlen); |
|
62 } else { |
|
63 /* invalid request */ |
|
64 printf("invalid request\n"); |
|
65 return REQ_ABORTED; |
|
66 } |
|
67 |
|
68 printf("PUT length: %d\n", length); |
|
69 |
|
70 int status = 204; |
|
71 if(length >= 0) { |
|
72 char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars); |
|
73 |
|
74 FILE *out = fopen(ppath, "w"); |
|
75 if(out == NULL) { |
|
76 fprintf(stderr, "fopen(%s, \"w\") failed\n", ppath); |
|
77 return REQ_ABORTED; |
|
78 } |
|
79 setvbuf(out, NULL, _IONBF, 0); |
|
80 |
|
81 size_t l = (length > 4096) ? (4096) : (length); |
|
82 char *buffer = malloc(l); |
|
83 |
|
84 int r; |
|
85 int r2 = 0; |
|
86 while(r2 < length) { |
|
87 r = netbuf_getbytes(sn->inbuf, buffer, l); |
|
88 if(r == NETBUF_EOF) { |
|
89 break; |
|
90 } |
|
91 fwrite(buffer, 1, r, out); |
|
92 |
|
93 r2 += r; |
|
94 } |
|
95 |
|
96 fclose(out); |
|
97 } |
|
98 |
|
99 protocol_status(sn, rq, status, NULL); |
|
100 pblock_removekey(pb_key_content_type, rq->srvhdrs); |
|
101 pblock_nninsert("content-length", 0, rq->srvhdrs); |
|
102 http_start_response(sn, rq); |
|
103 |
|
104 return REQ_PROCEED; |
42 } |
105 } |
43 |
106 |
44 int webdav_propfind(pblock *pb, Session *sn, Request *rq) { |
107 int webdav_propfind(pblock *pb, Session *sn, Request *rq) { |
45 /* TODO: clean up if errors occurs */ |
108 /* TODO: clean up if errors occurs */ |
46 |
109 |
89 /* write xml response header */ |
152 /* write xml response header */ |
90 sbuf_puts(davrq->out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); |
153 sbuf_puts(davrq->out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); |
91 sbuf_puts(davrq->out, "<D:multistatus xmlns:D=\"DAV:\">\n"); |
154 sbuf_puts(davrq->out, "<D:multistatus xmlns:D=\"DAV:\">\n"); |
92 |
155 |
93 /* begin multistatus response */ |
156 /* begin multistatus response */ |
94 int is_dir = 0; |
|
95 char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); |
157 char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); |
96 char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars); |
158 char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars); |
97 |
159 |
98 struct stat st; |
160 struct stat st; |
99 if(stat(ppath, &st) != 0) { |
161 if(stat(ppath, &st) != 0) { |
120 } |
182 } |
121 |
183 |
122 sstr_t filename = sstr(f->d_name); |
184 sstr_t filename = sstr(f->d_name); |
123 sstr_t _path = sstr(ppath); |
185 sstr_t _path = sstr(ppath); |
124 sstr_t _uri = sstr(uri); |
186 sstr_t _uri = sstr(uri); |
|
187 sstr_t ps; |
|
188 sstr_t us; |
|
189 ps.length = 0; |
|
190 ps.ptr = NULL; |
|
191 us.length = 0; |
|
192 us.ptr = NULL; |
|
193 if(_path.ptr[_path.length - 1] != '/') { |
|
194 ps = sstrn("/", 1); |
|
195 } |
|
196 if(_uri.ptr[_uri.length - 1] != '/') { |
|
197 us = sstrn("/", 1); |
|
198 } |
125 |
199 |
126 sstr_t newuri; |
200 sstr_t newuri; |
127 newuri.length = filename.length + _uri.length; |
201 newuri.length = filename.length + _uri.length + us.length; |
128 newuri.ptr = alloca(newuri.length + 1); |
202 newuri.ptr = alloca(newuri.length + 1); |
129 newuri = sstrncat(2, newuri, _uri, filename); |
203 if(us.length == 1) { |
|
204 newuri = sstrncat(3, newuri, _uri, us, filename); |
|
205 } else { |
|
206 newuri = sstrncat(2, newuri, _uri, filename); |
|
207 } |
130 |
208 |
131 sstr_t newpath; |
209 sstr_t newpath; |
132 newpath.length = _path.length + filename.length; |
210 newpath.length = _path.length + filename.length + ps.length; |
133 newpath.ptr = alloca(newpath.length + 1); |
211 newpath.ptr = alloca(newpath.length + 1); |
134 newpath = sstrncat(2, newpath, _path, filename); |
212 if(ps.length == 1) { |
|
213 newpath = sstrncat(3, newpath, _path, ps, filename); |
|
214 } else { |
|
215 newpath = sstrncat(2, newpath, _path, filename); |
|
216 } |
135 |
217 |
136 /* child response */ |
218 /* child response */ |
137 dav_resource_response(davrq, newpath, newuri); |
219 dav_resource_response(davrq, newpath, newuri); |
138 } |
220 } |
139 } |
221 } |
265 } |
347 } |
266 } else if(!strcmp(s, "getcontentlength") && !S_ISDIR(st.st_mode)) { |
348 } else if(!strcmp(s, "getcontentlength") && !S_ISDIR(st.st_mode)) { |
267 char buf[32]; |
349 char buf[32]; |
268 size_t n = snprintf(buf, 32, "%d", st.st_size); |
350 size_t n = snprintf(buf, 32, "%d", st.st_size); |
269 dav_propfind_add_str_prop(rq, prop, buf, n); |
351 dav_propfind_add_str_prop(rq, prop, buf, n); |
|
352 } else if(!strcmp(s, "getlastmodified")) { |
|
353 sstr_t s = date_format_http(st.st_mtim.tv_sec, rq->sn->pool); |
|
354 dav_propfind_add_str_prop(rq, prop, s.ptr, s.length); |
|
355 } else if(!strcmp(s, "creationdate")) { |
|
356 sstr_t s = date_format_iso8601(st.st_ctim.tv_sec, rq->sn->pool); |
|
357 dav_propfind_add_str_prop(rq, prop, s.ptr, s.length); |
270 } else { |
358 } else { |
271 dav_propfind_add_prop_error(rq, prop, 404); |
359 dav_propfind_add_prop_error(rq, prop, 404); |
272 } |
360 } |
273 } |
361 } |
274 } |
362 } |