Permalink
Browse files

reworked the DAV support a bit - don't use an appmod, instead yaws ha…

…s built-in support for DAV methods. Added support for missing DAV methods (COPY etc).

git-svn-id: https://erlyaws.svn.sourceforge.net/svnroot/erlyaws/trunk/yaws@927 9fbdc01b-0d2c-0410-bfb7-fb27d70d8b52
  • Loading branch information...
1 parent 6cf3ece commit 868ce8ad136102ec4d75a7bcb4232feaec8f638a @mbj4668 mbj4668 committed Nov 23, 2005
Showing with 548 additions and 291 deletions.
  1. +11 −7 include/yaws.hrl
  2. +1 −2 src/Makefile
  3. +0 −267 src/dav.erl
  4. +14 −5 src/yaws.erl
  5. +8 −0 src/yaws_config.erl
  6. +432 −4 src/yaws_dav.erl
  7. +82 −6 src/yaws_server.erl
View
@@ -101,22 +101,24 @@
-define(SC_DIR_LISTINGS, 16).
-define(SC_DEFLATE, 32).
-define(SC_DIR_ALL_ZIP, 64).
-
+-define(SC_DAV, 128).
-define(SC_DEF, ?SC_ACCESS_LOG bor ?SC_ADD_PORT).
-define(sc_has_access_log(SC),
- ((SC#sconf.flags band ?SC_ACCESS_LOG) /= 0)).
+ (((SC)#sconf.flags band ?SC_ACCESS_LOG) /= 0)).
-define(sc_has_add_port(SC),
- ((SC#sconf.flags band ?SC_ADD_PORT) /= 0)).
+ (((SC)#sconf.flags band ?SC_ADD_PORT) /= 0)).
-define(sc_has_tilde_expand(SC),
- ((SC#sconf.flags band ?SC_TILDE_EXPAND) /= 0)).
+ (((SC)#sconf.flags band ?SC_TILDE_EXPAND) /= 0)).
-define(sc_has_dir_listings(SC),
- ((SC#sconf.flags band ?SC_DIR_LISTINGS) /= 0)).
+ (((SC)#sconf.flags band ?SC_DIR_LISTINGS) /= 0)).
-define(sc_has_deflate(SC),
- ((SC#sconf.flags band ?SC_DEFLATE) /= 0)).
+ (((SC)#sconf.flags band ?SC_DEFLATE) /= 0)).
-define(sc_has_dir_all_zip(SC),
- ((SC#sconf.flags band ?SC_DIR_ALL_ZIP) /= 0)).
+ (((SC)#sconf.flags band ?SC_DIR_ALL_ZIP) /= 0)).
+-define(sc_has_dav(SC),
+ (((SC)#sconf.flags band ?SC_DAV) /= 0)).
-define(sc_set_access_log(SC, Bool),
@@ -133,6 +135,8 @@
SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_DEFLATE, Bool)}).
-define(sc_set_dir_all_zip(SC, Bool),
SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_DIR_ALL_ZIP, Bool)}).
+-define(sc_set_dav(SC, Bool),
+ SC#sconf{flags = yaws:flag(SC#sconf.flags, ?SC_DAV, Bool)}).
View
@@ -31,8 +31,7 @@ MODULES=yaws \
yaws_html \
yaws_log_file_h \
yaws_rss \
- dav
-
+ yaws_dav
EBIN_FILES=$(MODULES:%=../ebin/%.$(EMULATOR)) ../ebin/yaws.app
View
@@ -1,267 +0,0 @@
--module(dav).
-%%%-------------------------------------------------------------------
-%%% Created : 17 May 2005 by Torbjorn Tornkvist <tobbe@struts.tornkvist.org>
-%%% Desc. : WebDav-appmod file system interface.
-%%%
-%%% Test it, example: cadaver http://struts:8000/dav
-%%%
-%%%
-%%% NOTE: This is work in heavy progress!!
-%%%
-%%%-------------------------------------------------------------------
--export([out/1]).
-
--include("../include/yaws_api.hrl").
--include("../include/yaws_dav.hrl").
--include_lib("kernel/include/file.hrl").
-
-
--define(elog(X,Y), error_logger:info_msg("*elog ~p:~p: " X,
- [?MODULE, ?LINE | Y])).
-
-
--define(IS_PROPFIND(A), (A#arg.req)#http_request.method == "PROPFIND"). % FIXME why lists ?
--define(IS_MKCOL(A), (A#arg.req)#http_request.method == "MKCOL").
--define(IS_GET(A), (A#arg.req)#http_request.method == 'GET').
--define(IS_PUT(A), (A#arg.req)#http_request.method == 'PUT').
--define(IS_DELETE(A), (A#arg.req)#http_request.method == 'DELETE').
-
-
-out(A) when ?IS_PROPFIND(A) ->
- propfind(A);
-out(A) when ?IS_MKCOL(A) ->
- create_directory(A);
-out(A) when ?IS_GET(A) ->
- do_get(A);
-out(A) when ?IS_PUT(A) ->
- do_put(A);
-out(A) when ?IS_DELETE(A) ->
- do_delete(A);
-out(A) ->
- ?elog("Got Method=~p~n", [(A#arg.req)#http_request.method]),
- out403().
-
-
-do_delete(A) ->
- Path = A#arg.docroot ++ rm_dav(A#arg.server_path),
- ?elog("DELETE Path=~p~n", [Path]),
- case file:read_file_info(Path) of
- {ok, F} when F#file_info.type == directory ->
- case file:delete_dir(Path) of
- ok -> out200();
- _ -> out403() % FIXME , should do recursive delete !!
- end;
- _ ->
- case file:delete(Path) of
- ok -> out200();
- _ -> out403()
- end
- end.
-
-do_get(A) ->
- Path = A#arg.docroot ++ rm_dav(A#arg.server_path),
- {ok, B} = file:read_file(Path),
- out200(B).
-
-do_put(A) ->
- Path = A#arg.docroot ++ rm_dav(A#arg.server_path),
- ?elog("PUT Path=~p~n", [Path]),
- Data = A#arg.clidata,
- case file:write_file(Path, Data) of
- ok -> out200();
- _ -> out409()
- end.
-
-create_directory(A) ->
- Path = A#arg.docroot ++ rm_dav(A#arg.server_path),
- case file:make_dir(Path) of
- ok ->
- out201();
- {error, Reason} ->
- ?elog("failed to create dir: ~p , reason: ~p~n", [Path, Reason]),
- out403()
- end.
-
-
-propfind(A) ->
- ?elog("propfind: appmoddata=~p~n", [A#arg.appmoddata]),
- %% Depth:
- %% If '0', then no members should be returned.
- %% If '1', then members one level down should be included in the reply.
- %% If 'infinity', then all members, recursively, should be included.
- case depth(A) of
- 0 ->
- ?elog("propfind: Depth=0~n", []),
- Response = depth_zero(A),
- MultiStatus = [{multistatus, [{'xmlns',"DAV:"}], Response}],
- B = yaws_dav:xml_expand(MultiStatus),
- out207(B);
- 1 ->
- %% FIXME should get root dir from yaws.conf
- Entries = get_entries(A),
- ?elog("propfind: Depth=1 , length(Entries)=~p~n", [length(Entries)]),
- Url = "http://struts/dav/", % FIXME
- F = fun(Finfo) -> response_entry(Finfo, Url) end,
- Responses = lists:map(F, Entries),
- MultiStatus = [{multistatus, [{'xmlns',"DAV:"}], Responses}],
- B = yaws_dav:xml_expand(MultiStatus),
- out207(B)
- end.
-
-date_string({{Y,M,D}, {Hr,Min,Sec}}) ->
- lists:concat([D, " ", month(M), " ", Y, " ", Hr, ":", Min, ":", Sec]).
-
-rm_dav("/dav"++L) -> L;
-rm_dav([H|T]) -> [H|rm_dav(T)];
-rm_dav([] ) -> [].
-
-
-get_entries(A) ->
- Path = A#arg.docroot ++ A#arg.appmoddata,
- case file:read_file_info(Path) of
- {ok, Dir} when Dir#file_info.type == directory ->
- {ok, L} = file:list_dir(Path),
- [{Name,element(2,file:read_file_info(Path++"/"++Name))} || Name <- L];
- {ok, Else} ->
- [{get_name(Path),Else}]
- end.
-
-%%% FIXME should get a proper file_info entry here
-%%
-response_entry({Name, F}, Url) when F#file_info.type == directory -> % Dir
- {response, [],
- [{href, [], [Url ++ Name]},
- {propstat, [],
- [{prop, [],
- [{name, [], [Name]},
- {creationdate, [], [date_string(F#file_info.ctime)]},
- {getlastmodified, [], [date_string(F#file_info.mtime)]},
- {getcontentlength, [], [integer_to_list(F#file_info.size)]},
- {resourcetype, [],
- [{collection, [], []}]}
- %%{ishidden, [], [bool2lnum(F#file.is_hidden)]}]},
- ]},
- {status, [], % Status 1
- ["HTTP/1.1 200 OK"]}]}]};
-%%
-response_entry({Name, F}, Url) when F#file_info.type == regular -> % File
- {response, [],
- [{href, [], [Url ++ Name]},
- {propstat, [],
- [{prop, [],
- [{name, [], [Name]},
- {creationdate, [], [date_string(F#file_info.ctime)]},
- {getlastmodified, [], [date_string(F#file_info.mtime)]},
- {getcontentlength, [], [integer_to_list(F#file_info.size)]},
- {resourcetype, [], []}
- %%{ishidden, [], [bool2lnum(F#file.is_hidden)]}]},
- ]},
- {status, [], % Status 1
- ["HTTP/1.1 200 OK"]}]}]};
-%%
-response_entry(F, _Url) ->
- ?elog("ignoring file: ~p~n", [F]),
- [].
-
-
-get_name("/") -> "/";
-get_name("") -> "/";
-get_name(L) ->
- [Rname|_] = string:tokens(lists:reverse(L), "/"),
- lists:reverse(Rname).
-
-file_name("/") -> ".";
-file_name("") -> ".";
-file_name(L) ->
- [Rname|_] = string:tokens(lists:reverse(L), "/"),
- lists:reverse(Rname).
-
-
-
-depth_zero(A) ->
- Path = A#arg.docroot ++ A#arg.appmoddata,
- Url = "http://struts/dav" ++ A#arg.appmoddata, % FIXME
- Name = file_name(Path),
- {ok, F} = file:read_file_info(Path), % FIXME
- ?elog("server_path=~p~n", [A#arg.server_path]),
- [{response, [],
- [{href, [], [Url]},
- {propstat, [],
- [{prop, [],
- [{name, [], [Name]},
- {creationdate, [], [date_string(F#file_info.ctime)]},
- {getlastmodified, [], [date_string(F#file_info.mtime)]},
- {getcontentlength, [], [integer_to_list(F#file_info.size)]},
- {resourcetype, [],
- is_collection(F)}
- %%{ishidden, [], [bool2lnum(F#file.is_hidden)]}]},
- ]},
- {status, [],
- ["HTTP/1.1 200 OK"]}]}]}].
-
-is_collection(F) when F#file_info.type == directory ->
- [{collection, [], []}];
-is_collection(_) ->
- [].
-
-
-depth(A) ->
- %%
- %% Look for: {http_header, _Num, 'Depth', _, Depth}
- %%
- Hs = (A#arg.headers)#headers.other,
- case lists:keysearch("Depth", 3, Hs) of
- {value, {_,_,"Depth",_,Depth}} ->
- to_depth(Depth);
- _ ->
- 0
- end.
-
-to_depth("infinity") -> infinity;
-to_depth(L) ->
- case catch list_to_integer(L) of
- I when integer(I) -> I;
- _ -> 0
- end.
-
-
-
-out207(L) ->
- outXXX(207, L).
-
-outXXX(XXX, L) ->
- [{status, XXX},
- {header, {content_type, "text/xml; charset=\"utf-8\""}},
- {html, L}].
-
-out200(L) ->
- [{status, 200},
- {header, {content_type, "text/html"}},
- {html, L}].
-
-
-out200() ->
- [{status, 200}].
-
-out201() ->
- [{status, 201}].
-
-out403() ->
- [{status, 403}].
-
-out409() ->
- [{status, 409}].
-
-
-month(1) -> "Jan";
-month(2) -> "Feb";
-month(3) -> "Mar";
-month(4) -> "Apr";
-month(5) -> "May";
-month(6) -> "Jun";
-month(7) -> "Jul";
-month(8) -> "Aug";
-month(9) -> "Sep";
-month(10) -> "Oct";
-month(11) -> "Nov";
-month(12) -> "Dec".
View
@@ -1215,12 +1215,21 @@ dcc(Req, Headers) ->
%%
make_allow_header() ->
- "Allow: GET, POST, PUT, OPTIONS, HEAD, PROPFIND, MKCOL\r\n".
+ HasDav = ?sc_has_dav(get(sc)),
+ ["Allow: GET, POST, OPTIONS, HEAD",
+ if HasDav == true ->
+ ", PUT, PROPFIND, MKCOL, MOVE, COPY\r\n";
+ false ->
+ "\r\n"
+ end].
make_server_header() ->
- ["Server: Yaws/", yaws_vsn:version(), " Yet Another Web Server\r\n",
- "DAV: 1\r\n"].
-
-
+ HasDav = ?sc_has_dav(get(sc)),
+ ["Server: Yaws/", yaws_vsn:version(), " Yet Another Web Server\r\n" |
+ if HasDav == true ->
+ ["DAV: 1\r\n"];
+ true ->
+ []
+ end].
make_last_modified_header(FI) ->
N = element(2, now()),
View
@@ -509,6 +509,14 @@ fload(FD, server, GC, C, Cs, Lno, Chars) ->
false ->
{error, ?F("Expect true|false at line ~w", [Lno])}
end;
+ ["dav", '=', Bool] ->
+ case is_bool(Bool) of
+ {true, Val} ->
+ C2 = ?sc_set_dav(C, Val),
+ fload(FD, server, GC, C2, Cs, Lno+1, Next);
+ false ->
+ {error, ?F("Expect true|false at line ~w", [Lno])}
+ end;
["port", '=', Val] ->
case (catch list_to_integer(Val)) of
I when integer(I) ->
Oops, something went wrong.

0 comments on commit 868ce8a

Please sign in to comment.