Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 554 lines (492 sloc) 17.877 kb
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
1 -module(yaws_dav).
2 %%%-------------------------------------------------------------------
3 %%% Created : 15 May 2005 by Tobbet <tobbe@tornkvist.org>
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
4 %%% Modified: 21 Nov 2005 by <mbj@tail-f.com>
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
5 %%% Desc. : WebDav specifics.
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
6 %%% To use, add a line dav = true in the <server>.
7 %%% TODO: fix more fine-grained permissions
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
8 %%%-------------------------------------------------------------------
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
9 -export([propfind/1, delete/1, put/2, mkcol/1, move/1, copy/1]).
5ef2b8a *** empty log message ***
Tobbe Tornquist authored
10 -export([parse_xml/1, xml_expand/1, xml_expand/2]).
11
ed4466e Fixed include file references.
Tobbe Tornquist authored
12 -include("../include/yaws_dav.hrl").
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
13 -include("../include/yaws_api.hrl").
14 -include("../include/yaws.hrl").
15 -include("yaws_debug.hrl").
ed4466e Fixed include file references.
Tobbe Tornquist authored
16 -include_lib("xmerl/include/xmerl.hrl").
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
17 -include_lib("kernel/include/file.hrl").
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
18
19
20 -define(elog(X,Y), error_logger:info_msg("*elog ~p:~p: " X,
0be3c7e @klacke untabified all of yaws
authored
21 [?MODULE, ?LINE | Y])).
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
22
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
23 delete(A) ->
24 Path = davpath(A),
25 ?elog("DELETE Path=~p~n", [Path]),
26 case rmrf(Path) of
0be3c7e @klacke untabified all of yaws
authored
27 ok -> out200();
28 _ -> out403()
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
29 end.
30
31 put(SC, ARG) ->
32 H = ARG#arg.headers,
33 PPS = SC#sconf.partial_post_size,
455578a @vinoski major trailing whitespace cleanup
vinoski authored
34 CT =
9a74e5a @klacke Major general code cleanup, finally got rid of all the export_all sta…
authored
35 case yaws:to_lower(H#headers.content_type) of
0be3c7e @klacke untabified all of yaws
authored
36 "multipart/form-data"++_ -> multipart;
37 _ -> urlencoded
38 end,
9a74e5a @klacke Major general code cleanup, finally got rid of all the export_all sta…
authored
39 SSL = yaws:is_ssl(SC),
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
40 FName = davpath(ARG),
ba34c61 Fix SSL socket wrapping
Christopher Faulet authored
41 CliSock = case yaws_api:get_sslsocket(ARG#arg.clisock) of
42 {ok, SslSock} -> SslSock;
43 undefined -> ARG#arg.clisock
44 end,
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
45 TmpName = FName ++ ".tmp",
46 %% FIXME: first check if we can write to original file??
47 case file:open(TmpName, [raw,write]) of
0be3c7e @klacke untabified all of yaws
authored
48 {ok, Fd} ->
49 try
50 case H#headers.content_length of
51 undefined ->
52 Chunked = H#headers.transfer_encoding == "chunked",
53 case H#headers.connection of
54 "close" when Chunked == false->
55 store_client_data(Fd, CliSock, all, SSL);
56 _ when Chunked == true ->
57 store_chunked_client_data(Fd, CliSock, SSL)
58 end;
f44be6a @klacke all calls to old deprecated guard tests removed
authored
59 Len when is_integer(PPS) ->
0be3c7e @klacke untabified all of yaws
authored
60 Int_len = list_to_integer(Len),
455578a @vinoski major trailing whitespace cleanup
vinoski authored
61 if
0be3c7e @klacke untabified all of yaws
authored
62 Int_len == 0 ->
63 ok;
64 PPS < Int_len, CT == multipart ->
65 %% FIXME: handle this
e3f358e @vinoski treat src warnings as errors
vinoski authored
66 %% {partial,
67 store_client_data(Fd,CliSock, PPS, SSL); % };
0be3c7e @klacke untabified all of yaws
authored
68 true ->
69 store_client_data(Fd, CliSock, Int_len, SSL)
70 end;
71 Len when PPS == nolimit ->
72 Int_len = list_to_integer(Len),
73 if
74 Int_len == 0 ->
75 ok;
76 true ->
77 store_client_data(Fd, CliSock, Int_len, SSL)
78 end
79 end,
80 file:close(Fd),
81 case file:rename(TmpName, FName) of
82 ok ->
83 out200();
84 Error ->
85 throw(Error)
86 end
87 catch
88 _:_Err ->
89 ?Debug("PUT error ~p\n", [_Err, TmpName]),
90 file:close(Fd),
91 file:delete(TmpName),
92 out409()
93 end;
94 _Error ->
95 ?Debug("PUT error ~p ~p\n", [_Error, TmpName]),
96 out409()
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
97 end.
0be3c7e @klacke untabified all of yaws
authored
98
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
99 mkcol(A) ->
100 Path = davpath(A),
101 case file:make_dir(Path) of
0be3c7e @klacke untabified all of yaws
authored
102 ok ->
103 out201();
104 {error, Reason} ->
105 ?elog("failed to create dir: ~p , reason: ~p~n", [Path, Reason]),
106 out403()
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
107 end.
108
109 copy(A) ->
110 copy_move(A, fun do_copy/2).
111
112 move(A) ->
113 copy_move(A, fun do_move/2).
114
115 copy_move(A, OpF) ->
116 case lists:keysearch("Destination", 3, (A#arg.headers)#headers.other) of
0be3c7e @klacke untabified all of yaws
authored
117 {value, {http_header, _, _, _, Url}} ->
118 %% FIXME: check for weird paths
119 {Url1, _} = yaws_api:url_decode_q_split(Url),
120 Path = Url1 -- davroot(A),
121 From = davpath(A),
122 To = A#arg.docroot ++ "/" ++ Path,
123 ?elog("move from ~p to ~p (~p)\n", [From, To, Url]),
124 DoOverwrite = get_overwrite(A),
125 IsSame = is_same(From, To),
126 ToExsist = exists(To),
127 if IsSame == true ->
128 [{status, 403}];
129 DoOverwrite == false,
130 ToExsist == true ->
131 [{status, 412}];
132 true ->
133 if DoOverwrite == true ->
134 rmrf(To);
135 true ->
136 ok
137 end,
138 OpF(From, To)
139 end;
140 _ ->
141 [{status, 501}]
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
142 end.
143
144 do_move(From, To) ->
145 case file:rename(From, To) of
0be3c7e @klacke untabified all of yaws
authored
146 ok ->
147 out201();
148 _ ->
149 case file:copy(From, To) of
d07115c @klacke Several cleanups due to dialyzer, also moved the control file into us…
authored
150 {ok,_} ->
0be3c7e @klacke untabified all of yaws
authored
151 ok = file:delete(From),
152 out201();
d07115c @klacke Several cleanups due to dialyzer, also moved the control file into us…
authored
153 {error, Reason} ->
0be3c7e @klacke untabified all of yaws
authored
154 ?elog("move from ~p to ~p failed: ~p\n",
d07115c @klacke Several cleanups due to dialyzer, also moved the control file into us…
authored
155 [From, To, Reason]),
0be3c7e @klacke untabified all of yaws
authored
156 out409()
157 end
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
158 end.
159
160 do_copy(From, To) ->
161 case file:copy(From, To) of
0be3c7e @klacke untabified all of yaws
authored
162 {ok, _} ->
163 out201();
164 Error ->
165 ?elog("move from ~p to ~p failed: ~p\n",
166 [From, To, Error]),
167 out409()
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
168 end.
169
170 propfind(A) ->
171 %% Depth:
172 %% If '0', then no members should be returned.
173 %% If '1', then members one level down should be included in the reply.
174 %% If 'infinity', then all members, recursively, should be included.
175 case depth(A) of
0be3c7e @klacke untabified all of yaws
authored
176 0 ->
177 ?elog("propfind: Depth=0~n", []),
178 Response = depth_zero(A),
179 MultiStatus = [{multistatus, [{'xmlns',"DAV:"}], Response}],
180 B = yaws_dav:xml_expand(MultiStatus),
181 out207(B);
182 1 ->
183 Entries = get_entries(A),
184 ?elog("propfind: Depth=1 , length(Entries)=~p~n",
185 [length(Entries)]),
186 Url = davurl(A),
187 F = fun(Finfo) -> response_entry(Finfo, Url) end,
188 Responses = lists:map(F, Entries),
189 MultiStatus = [{multistatus, [{'xmlns',"DAV:"}], Responses}],
190 B = yaws_dav:xml_expand(MultiStatus),
191 out207(B)
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
192 end.
193
194
195 date_string({{Y,M,D}, {Hr,Min,Sec}}) ->
196 lists:concat([D, " ", month(M), " ", Y, " ", Hr, ":", Min, ":", Sec]).
197
198 get_entries(A) ->
199 Path = davpath(A),
200 case file:read_file_info(Path) of
0be3c7e @klacke untabified all of yaws
authored
201 {ok, Dir} when Dir#file_info.type == directory ->
202 {ok, L} = file:list_dir(Path),
203 [{Name, element(2, file:read_file_info(Path ++ "/" ++ Name))} ||
204 Name <- L];
205 {ok, Else} ->
206 [{get_name(Path),Else}]
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
207 end.
208
209 %%% FIXME should get a proper file_info entry here
210 %%
211 response_entry({Name, F}, Url) when F#file_info.type == directory -> % Dir
212 {response, [],
213 [{href, [], [Url ++ Name]},
455578a @vinoski major trailing whitespace cleanup
vinoski authored
214 {propstat, [],
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
215 [{prop, [],
0be3c7e @klacke untabified all of yaws
authored
216 [{name, [], [Name]},
455578a @vinoski major trailing whitespace cleanup
vinoski authored
217 {creationdate, [], [date_string(F#file_info.ctime)]},
0be3c7e @klacke untabified all of yaws
authored
218 {getlastmodified, [], [date_string(F#file_info.mtime)]},
219 {getcontentlength, [], [integer_to_list(F#file_info.size)]},
455578a @vinoski major trailing whitespace cleanup
vinoski authored
220 {resourcetype, [],
0be3c7e @klacke untabified all of yaws
authored
221 [{collection, [], []}]}
222 %%{ishidden, [], [bool2lnum(F#file.is_hidden)]}]},
223 ]},
224 {status, [], % Status 1
225 ["HTTP/1.1 200 OK"]}]}]};
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
226 %%
227 response_entry({Name, F}, Url) when F#file_info.type == regular -> % File
228 {response, [],
229 [{href, [], [Url ++ Name]},
455578a @vinoski major trailing whitespace cleanup
vinoski authored
230 {propstat, [],
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
231 [{prop, [],
0be3c7e @klacke untabified all of yaws
authored
232 [{name, [], [Name]},
455578a @vinoski major trailing whitespace cleanup
vinoski authored
233 {creationdate, [], [date_string(F#file_info.ctime)]},
0be3c7e @klacke untabified all of yaws
authored
234 {getlastmodified, [], [date_string(F#file_info.mtime)]},
235 {getcontentlength, [], [integer_to_list(F#file_info.size)]},
236 {resourcetype, [], []}
237 %%{ishidden, [], [bool2lnum(F#file.is_hidden)]}]},
238 ]},
239 {status, [], % Status 1
240 ["HTTP/1.1 200 OK"]}]}]};
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
241 %%
242 response_entry(F, _Url) ->
243 ?elog("ignoring file: ~p~n", [F]),
244 [].
245
246
247 get_name("/") -> "/";
248 get_name("") -> "/";
249 get_name(L) ->
250 [Rname|_] = string:tokens(lists:reverse(L), "/"),
251 lists:reverse(Rname).
252
253 file_name("/") -> ".";
254 file_name("") -> ".";
255 file_name(L) ->
256 [Rname|_] = string:tokens(lists:reverse(L), "/"),
257 lists:reverse(Rname).
258
259 get_overwrite(A) ->
260 case lists:keysearch("Overwrite", 3, (A#arg.headers)#headers.other) of
0be3c7e @klacke untabified all of yaws
authored
261 {value, {http_header, _, _, _, "T"}} -> true;
262 _ -> false
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
263 end.
264
265 exists(Path) ->
266 case file:read_file_info(Path) of
0be3c7e @klacke untabified all of yaws
authored
267 {ok, _} -> true;
268 _ -> false
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
269 end.
0be3c7e @klacke untabified all of yaws
authored
270
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
271 %% FIXME: how to do this in a portable way? on unix we could check inode...
272 is_same(A, B) ->
273 A == B.
274
275
276 depth_zero(A) ->
277 Path = davpath(A),
278 Url = davurl(A),
279 Name = file_name(Path),
280 {ok, F} = file:read_file_info(Path), % FIXME
281 ?elog("server_path=~p~n", [A#arg.server_path]),
282 [{response, [],
283 [{href, [], [Url]},
455578a @vinoski major trailing whitespace cleanup
vinoski authored
284 {propstat, [],
0be3c7e @klacke untabified all of yaws
authored
285 [{prop, [],
286 [{name, [], [Name]},
455578a @vinoski major trailing whitespace cleanup
vinoski authored
287 {creationdate, [], [date_string(F#file_info.ctime)]},
0be3c7e @klacke untabified all of yaws
authored
288 {getlastmodified, [], [date_string(F#file_info.mtime)]},
289 {getcontentlength, [], [integer_to_list(F#file_info.size)]},
455578a @vinoski major trailing whitespace cleanup
vinoski authored
290 {resourcetype, [],
0be3c7e @klacke untabified all of yaws
authored
291 is_collection(F)}
292 %%{ishidden, [], [bool2lnum(F#file.is_hidden)]}]},
293 ]},
455578a @vinoski major trailing whitespace cleanup
vinoski authored
294 {status, [],
0be3c7e @klacke untabified all of yaws
authored
295 ["HTTP/1.1 200 OK"]}]}]}].
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
296
297 is_collection(F) when F#file_info.type == directory ->
0be3c7e @klacke untabified all of yaws
authored
298 [{collection, [], []}];
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
299 is_collection(_) ->
300 [].
301
302 davpath(A) ->
303 A#arg.docroot ++ A#arg.server_path.
304
305 davurl(A) ->
306 davroot(A) ++ A#arg.server_path ++ "/".
307
308 davroot(A) ->
309 Method = case A#arg.clisock of
5b34d48 @vinoski wrap SSL sockets in tuple
vinoski authored
310 {ssl ,_} -> "https";
0be3c7e @klacke untabified all of yaws
authored
311 _ -> "http"
312 end,
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
313 Host = (A#arg.headers)#headers.host,
314 Method ++ "://" ++ Host.
315
316 depth(A) ->
317 %%
318 %% Look for: {http_header, _Num, 'Depth', _, Depth}
319 %%
320 Hs = (A#arg.headers)#headers.other,
321 case lists:keysearch("Depth", 3, Hs) of
0be3c7e @klacke untabified all of yaws
authored
322 {value, {_,_,"Depth",_,Depth}} ->
323 to_depth(Depth);
324 _ ->
325 0
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
326 end.
327
328 to_depth("infinity") -> infinity;
329 to_depth(L) ->
330 case catch list_to_integer(L) of
f44be6a @klacke all calls to old deprecated guard tests removed
authored
331 I when is_integer(I) -> I;
0be3c7e @klacke untabified all of yaws
authored
332 _ -> 0
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
333 end.
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
334
335 xml_expand(L) ->
5ef2b8a *** empty log message ***
Tobbe Tornquist authored
336 xml_expand(L, "utf-8").
337
338 xml_expand(L, Cset) ->
339 Prolog = ["<?xml version=\"1.0\" encoding=\""++Cset++"\" ?>"],
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
340 xmerl:export_simple(L,xmerl_xml,[{prolog,Prolog}]).
341
342
343 parse_xml([]) -> [];
f44be6a @klacke all calls to old deprecated guard tests removed
authored
344 parse_xml(L) when is_list(L) ->
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
345 case catch xmerl_scan:string(L, [{namespace_conformant, true}]) of
f44be6a @klacke all calls to old deprecated guard tests removed
authored
346 {X,_} when is_record(X, xmlElement) ->
0be3c7e @klacke untabified all of yaws
authored
347 parse_dav(X);
348 _Z ->
349 ?elog("to_xml: error ~p~n", [_Z]),
350 {error, "xml scanner failed"}
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
351 end.
352
353 -define(CONTENT(X), X#xmlElement.content).
354
355 -define(IS_PROPFIND(X), #xmlElement{expanded_name = {'DAV:',propfind}} = X).
356 -define(IS_PROP(X), #xmlElement{expanded_name = {'DAV:',prop}} = X).
357 -define(IS_NAME(X), #xmlElement{expanded_name = {'DAV:',name}} = X).
358 -define(IS_PARENTNAME(X), #xmlElement{expanded_name = {'DAV:',parentname}} = X).
359 -define(IS_HREF(X), #xmlElement{expanded_name = {'DAV:',href}} = X).
360 -define(IS_ISHIDDEN(X), #xmlElement{expanded_name = {'DAV:',ishidden}} = X).
361 -define(IS_ISCOLLECTION(X), #xmlElement{expanded_name = {'DAV:',iscollection}} = X).
7f03335 *** empty log message ***
Tobbe Tornquist authored
362 -define(IS_ISREADONLY(X), #xmlElement{expanded_name = {'DAV:',isreadonly}} = X).
363 -define(IS_GETCONTENTTYPE(X), #xmlElement{expanded_name = {'DAV:',getcontenttype}} = X).
364 -define(IS_CONTENTCLASS(X), #xmlElement{expanded_name = {'DAV:',contentclass}} = X).
365 -define(IS_GETCONTENTLANGUAGE(X), #xmlElement{expanded_name = {'DAV:',getcontentlanguage}} = X).
366 -define(IS_CREATIONDATE(X), #xmlElement{expanded_name = {'DAV:',creationdate}} = X).
367 -define(IS_LASTACCESSED(X), #xmlElement{expanded_name = {'DAV:',lastaccessed}} = X).
368 -define(IS_GETLASTMODIFIED(X), #xmlElement{expanded_name = {'DAV:',getlastmodified}} = X).
369 -define(IS_GETCONTENTLENGTH(X), #xmlElement{expanded_name = {'DAV:',getcontentlength}} = X).
370 -define(IS_RESOURCETYPE(X), #xmlElement{expanded_name = {'DAV:',resourcetype}} = X).
371 -define(IS_ISSTRUCTUREDDOCUMENT(X), #xmlElement{expanded_name = {'DAV:',isstructureddocument}} = X).
372 -define(IS_DEFAULTDOCUMENT(X), #xmlElement{expanded_name = {'DAV:',defaultdocument}} = X).
373 -define(IS_DISPLAYNAME(X), #xmlElement{expanded_name = {'DAV:',displayname}} = X).
374 -define(IS_ISROOT(X), #xmlElement{expanded_name = {'DAV:',isroot}} = X).
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
375
376
377 parse_dav(?IS_PROPFIND(X)) ->
378 parse_propfind(?CONTENT(X), #propfind{});
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
379 parse_dav(_X) ->
380 %%?elog("parse_dav: GOT ~p~n", [_X]),
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
381 {error, "parse_dav"}. % FIXME , webdav (tobbe)
382
383
384 parse_propfind([?IS_PROP(H)|T], R) ->
385 Prop = parse_prop(?CONTENT(H)),
386 parse_propfind(T, R#propfind{prop = Prop});
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
387 parse_propfind([_H|T], R) ->
388 %%?elog("parse_propfind: ~p~n",[_H]),
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
389 parse_propfind(T, R);
390 parse_propfind([], R) ->
391 R.
392
393 parse_prop(L) ->
394 parse_prop(L, []).
395
396 parse_prop([?IS_NAME(_H)|T], L) ->
397 parse_prop(T, [name | L]);
398 parse_prop([?IS_PARENTNAME(_H)|T], L) ->
399 parse_prop(T, [parentname | L]);
400 parse_prop([?IS_HREF(_H)|T], L) ->
401 parse_prop(T, [href | L]);
402 parse_prop([?IS_ISHIDDEN(_H)|T], L) ->
403 parse_prop(T, [ishidden | L]);
404 parse_prop([?IS_ISCOLLECTION(_H)|T], L) ->
405 parse_prop(T, [iscollection | L]);
7f03335 *** empty log message ***
Tobbe Tornquist authored
406 parse_prop([?IS_ISREADONLY(_H)|T], L) ->
407 parse_prop(T, [isreadonly | L]);
408 parse_prop([?IS_GETCONTENTTYPE(_H)|T], L) ->
409 parse_prop(T, [getcontenttype | L]);
410 parse_prop([?IS_CONTENTCLASS(_H)|T], L) ->
411 parse_prop(T, [contentclass | L]);
412 parse_prop([?IS_GETCONTENTLANGUAGE(_H)|T], L) ->
413 parse_prop(T, [getcontentlanguage | L]);
414 parse_prop([?IS_CREATIONDATE(_H)|T], L) ->
415 parse_prop(T, [creationdate | L]);
416 parse_prop([?IS_LASTACCESSED(_H)|T], L) ->
417 parse_prop(T, [lastaccessed | L]);
418 parse_prop([?IS_GETLASTMODIFIED(_H)|T], L) ->
419 parse_prop(T, [getlastmodified | L]);
420 parse_prop([?IS_GETCONTENTLENGTH(_H)|T], L) ->
421 parse_prop(T, [getcontentlength | L]);
422 parse_prop([?IS_RESOURCETYPE(_H)|T], L) ->
423 parse_prop(T, [resourcetype | L]);
424 parse_prop([?IS_ISSTRUCTUREDDOCUMENT(_H)|T], L) ->
425 parse_prop(T, [isstructureddocument | L]);
426 parse_prop([?IS_DEFAULTDOCUMENT(_H)|T], L) ->
427 parse_prop(T, [defaultdocument | L]);
428 parse_prop([?IS_DISPLAYNAME(_H)|T], L) ->
429 parse_prop(T, [displayname | L]);
430 parse_prop([?IS_ISROOT(_H)|T], L) ->
431 parse_prop(T, [isroot | L]);
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
432 parse_prop([H|T], L) ->
7f03335 *** empty log message ***
Tobbe Tornquist authored
433 ?elog("parse_propfind: NYI ~p~n",[H]), % FIXME , webdav
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been …
Tobbe Tornquist authored
434 parse_prop(T, L);
435 parse_prop([], L) ->
436 lists:reverse(L). % preserve order!
437
438
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
439 month(1) -> "Jan";
440 month(2) -> "Feb";
441 month(3) -> "Mar";
442 month(4) -> "Apr";
443 month(5) -> "May";
444 month(6) -> "Jun";
445 month(7) -> "Jul";
446 month(8) -> "Aug";
447 month(9) -> "Sep";
448 month(10) -> "Oct";
449 month(11) -> "Nov";
450 month(12) -> "Dec".
451
452 out207(L) ->
453 outXXX(207, L).
454
455 outXXX(XXX, L) ->
456 [{status, XXX},
457 {header, {content_type, "text/xml; charset=\"utf-8\""}},
458 {html, L}].
0be3c7e @klacke untabified all of yaws
authored
459
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
460 out200() ->
461 [{status, 200}].
462
463 out201() ->
464 [{status, 201}].
465
466 out403() ->
467 [{status, 403}].
468
469 out409() ->
470 [{status, 409}].
471
472
473 rmrf(Path) ->
474 case file:read_file_info(Path) of
0be3c7e @klacke untabified all of yaws
authored
475 {ok, F} when F#file_info.type == directory ->
476 case file:list_dir(Path) of
477 {ok, Fs} ->
478 case rmrf(Path, Fs) of
479 ok ->
480 file:del_dir(Path);
481 _Err ->
482 ok
483 end;
484 Err ->
485 Err
486 end;
487 {ok, _} ->
488 file:delete(Path);
489 Err ->
490 Err
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
491 end.
492
493 rmrf(_Dir, []) ->
494 ok;
495 rmrf(Dir, [H|T]) ->
496 F = filename:join(Dir, H),
497 case rmrf(F) of
0be3c7e @klacke untabified all of yaws
authored
498 ok ->
499 rmrf(Dir, T);
500 Err ->
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
501 Err
502 end.
503
504
505 store_client_data(Fd, CliSock, all, SSlBool) ->
506 store_client_data_all(Fd, CliSock, SSlBool);
507
508 store_client_data(Fd, CliSock, Len, SSlBool) ->
509 store_client_data_len(Fd, CliSock, Len, SSlBool).
510
511
512 %% not nice to support this for ssl sockets
513 store_chunked_client_data(Fd, CliSock, SSL) ->
514 yaws:setopts(CliSock, [binary, {packet, line}], SSL),
a66f8a3 Parse extensions and trailing headers of chunked transfer encoded req…
Christopher Faulet authored
515 %% Ignore chunk extentions
516 {N, _Exts} = yaws:get_chunk_header(CliSock, SSL),
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
517 yaws:setopts(CliSock, [binary, {packet, raw}], SSL),
518 if
0be3c7e @klacke untabified all of yaws
authored
519 N == 0 ->
a66f8a3 Parse extensions and trailing headers of chunked transfer encoded req…
Christopher Faulet authored
520 %% Ignore chunk trailer
521 yaws:get_chunk_trailer(CliSock, SSL),
522 ok;
0be3c7e @klacke untabified all of yaws
authored
523 true ->
ca1c8b1 @karlsson Fixed a number of compiler warnings and html validation errors
karlsson authored
524 B = yaws:get_chunk(CliSock, N, 0,SSL),
9a74e5a @klacke Major general code cleanup, finally got rid of all the export_all sta…
authored
525 yaws:eat_crnl(CliSock,SSL),
0be3c7e @klacke untabified all of yaws
authored
526 ok = file:write(Fd, B),
527 store_chunked_client_data(Fd, CliSock, SSL)
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
528 end.
529
530 store_client_data_len(_Fd, _CliSock, 0, _SSlBool) ->
531 ok;
532 store_client_data_len(Fd, CliSock, Len, SSlBool) ->
533 case yaws:cli_recv(CliSock, Len, SSlBool) of
0be3c7e @klacke untabified all of yaws
authored
534 {ok, B} ->
535 ok = file:write(Fd, B),
536 store_client_data_len(Fd, CliSock, Len-size(B), SSlBool);
537 _Other ->
538 ?Debug("store_client_data_len: ~p~n", [_Other]),
539 exit(normal)
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
540 end.
541
542 store_client_data_all(Fd, CliSock, SSlBool) ->
543 case yaws:cli_recv(CliSock, 4000, SSlBool) of
0be3c7e @klacke untabified all of yaws
authored
544 {ok, B} ->
545 ok = file:write(Fd, B),
546 store_client_data_all(Fd, CliSock, SSlBool);
547 eof ->
548 ok;
549 _Other ->
550 ?Debug("store_client_data_all: ~p~n", [_Other]),
551 exit(normal)
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws ha…
mbj4668 authored
552 end.
553
Something went wrong with that request. Please try again.