Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 554 lines (492 sloc) 17.877 kb
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been add...
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 has b...
mbj4668 authored
4 %%% Modified: 21 Nov 2005 by <mbj@tail-f.com>
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been add...
Tobbe Tornquist authored
5 %%% Desc. : WebDav specifics.
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws has b...
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 add...
Tobbe Tornquist authored
8 %%%-------------------------------------------------------------------
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws has b...
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 has b...
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 has b...
mbj4668 authored
17 -include_lib("kernel/include/file.hrl").
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been add...
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 add...
Tobbe Tornquist authored
22
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws has b...
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 has b...
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 statem...
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 statem...
authored
39 SSL = yaws:is_ssl(SC),
868ce8a @mbj4668 reworked the DAV support a bit - don't use an appmod, instead yaws has b...
mbj4668 authored
40 FName = davpath(ARG),
ba34c61 @capflam Fix SSL socket wrapping
capflam 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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 users...
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 users...
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 users...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
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 has b...
mbj4668 authored
333 end.
16299b3 Adding the beginning of WebDav support. The PROPFIND method has been add...
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 add...
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 add...
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 add...
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 add...
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 has b...
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 add...
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 has b...
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 add...
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 add...
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 add...
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 has b...
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 has b...
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 has b...
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 has b...
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 @capflam Parse extensions and trailing headers of chunked transfer encoded reques...
capflam 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 has b...
mbj4668 authored
517 yaws:setopts(CliSock, [binary, {packet, raw}], SSL),
518 if
0be3c7e @klacke untabified all of yaws
authored
519 N == 0 ->
a66f8a3 @capflam Parse extensions and trailing headers of chunked transfer encoded reques...
capflam 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 statem...
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 has b...
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 has b...
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 has b...
mbj4668 authored
552 end.
553
Something went wrong with that request. Please try again.