Permalink
Browse files

Adding the beginning of WebDav support. The PROPFIND method has been …

…added. The intention is to let appmods take care of the WebDav specfics.

git-svn-id: https://erlyaws.svn.sourceforge.net/svnroot/erlyaws/trunk/yaws@877 9fbdc01b-0d2c-0410-bfb7-fb27d70d8b52
  • Loading branch information...
1 parent 45836ca commit 16299b328a56edbc66f43588336efe8d2807cf05 Tobbe Tornquist committed May 16, 2005
Showing with 145 additions and 2 deletions.
  1. +11 −0 include/yaws_dav.hrl
  2. +3 −0 src/Makefile
  3. +3 −2 src/yaws.erl
  4. +75 −0 src/yaws_dav.erl
  5. +53 −0 src/yaws_server.erl
View
@@ -0,0 +1,11 @@
+-ifndef(_YAWS_DAV).
+-define(_YAWS_DAV, true).
+
+-record(propfind, {
+ prop = [],
+ uri = ""
+ }).
+
+
+
+-endif.
View
@@ -44,6 +44,9 @@ ERLC_FLAGS+=-W $(DEBUG_FLAGS) -pa ../../yaws
all: yaws_vsn.erl $(EBIN_FILES)
+dav:
+ $(MAKE) MODULES="$(MODULES) yaws_dav"
+
$(EBIN_FILES) : ../include/yaws.hrl ../include/yaws_api.hrl
yaws_vsn.erl: yaws_vsn.template ../vsn.mk
View
@@ -1217,9 +1217,10 @@ dcc(Req, Headers) ->
%%
make_allow_header() ->
- "Allow: GET, POST, PUT, OPTIONS, HEAD\r\n".
+ "Allow: GET, POST, PUT, OPTIONS, HEAD, PROPFIND\r\n".
make_server_header() ->
- ["Server: Yaws/", yaws_vsn:version(), " Yet Another Web Server\r\n"].
+ ["Server: Yaws/", yaws_vsn:version(), " Yet Another Web Server\r\n",
+ "DAV: 1\r\n"].
View
@@ -0,0 +1,75 @@
+-module(yaws_dav).
+%%%-------------------------------------------------------------------
+%%% Created : 15 May 2005 by Tobbet <tobbe@tornkvist.org>
+%%% Desc. : WebDav specifics.
+%%%-------------------------------------------------------------------
+-export([parse_xml/1, xml_expand/1]).
+
+-include_lib("yaws/include/yaws_dav.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+
+-define(elog(X,Y), error_logger:info_msg("*elog ~p:~p: " X,
+ [?MODULE, ?LINE | Y])).
+
+
+xml_expand(L) ->
+ Prolog = ["<?xml version=\"1.0\" encoding=\"utf-8\" ?>"],
+ xmerl:export_simple(L,xmerl_xml,[{prolog,Prolog}]).
+
+
+parse_xml([]) -> [];
+parse_xml(L) when list(L) ->
+ case catch xmerl_scan:string(L, [{namespace_conformant, true}]) of
+ {X,_} when record(X, xmlElement) ->
+ parse_dav(X);
+ _Z ->
+ {error, "xml scanner failed"}
+ end.
+
+-define(CONTENT(X), X#xmlElement.content).
+
+-define(IS_PROPFIND(X), #xmlElement{expanded_name = {'DAV:',propfind}} = X).
+-define(IS_PROP(X), #xmlElement{expanded_name = {'DAV:',prop}} = X).
+-define(IS_NAME(X), #xmlElement{expanded_name = {'DAV:',name}} = X).
+-define(IS_PARENTNAME(X), #xmlElement{expanded_name = {'DAV:',parentname}} = X).
+-define(IS_HREF(X), #xmlElement{expanded_name = {'DAV:',href}} = X).
+-define(IS_ISHIDDEN(X), #xmlElement{expanded_name = {'DAV:',ishidden}} = X).
+-define(IS_ISCOLLECTION(X), #xmlElement{expanded_name = {'DAV:',iscollection}} = X).
+
+
+parse_dav(?IS_PROPFIND(X)) ->
+ parse_propfind(?CONTENT(X), #propfind{});
+parse_dav(X) ->
+ %%?elog("parse_dav: GOT ~p~n", [X]),
+ {error, "parse_dav"}. % FIXME , webdav (tobbe)
+
+
+parse_propfind([?IS_PROP(H)|T], R) ->
+ Prop = parse_prop(?CONTENT(H)),
+ parse_propfind(T, R#propfind{prop = Prop});
+parse_propfind([H|T], R) ->
+ %%?elog("parse_propfind: ~p~n",[H]),
+ parse_propfind(T, R);
+parse_propfind([], R) ->
+ R.
+
+parse_prop(L) ->
+ parse_prop(L, []).
+
+parse_prop([?IS_NAME(_H)|T], L) ->
+ parse_prop(T, [name | L]);
+parse_prop([?IS_PARENTNAME(_H)|T], L) ->
+ parse_prop(T, [parentname | L]);
+parse_prop([?IS_HREF(_H)|T], L) ->
+ parse_prop(T, [href | L]);
+parse_prop([?IS_ISHIDDEN(_H)|T], L) ->
+ parse_prop(T, [ishidden | L]);
+parse_prop([?IS_ISCOLLECTION(_H)|T], L) ->
+ parse_prop(T, [iscollection | L]);
+parse_prop([H|T], L) ->
+ %%?elog("parse_propfind: ~p~n",[H]), % FIXME , webdav
+ parse_prop(T, L);
+parse_prop([], L) ->
+ lists:reverse(L). % preserve order!
+
+
View
@@ -47,6 +47,10 @@
}).
+-define(elog(X,Y), error_logger:info_msg("*elog ~p:~p: " X,
+ [?MODULE, ?LINE | Y])).
+
+
start_link(A) ->
gen_server:start_link({local, yaws_server}, yaws_server, A, []).
@@ -1166,6 +1170,52 @@ not_implemented(CliSock, Req, Head) ->
deliver_options(CliSock, Req).
+%%%
+%%% WebDav specifics: PROPFIND, ...
+%%%
+'PROPFIND'(CliSock, Req, Head) ->
+ %%?elog("PROPFIND Req=~p H=~p~n",
+ %% [?format_record(Req, http_request),
+ %% ?format_record(Head, headers)]),
+ ok = inet_setopts(CliSock, [{packet, raw}, binary]),
+ SC=get(sc),
+ PPS = SC#sconf.partial_post_size,
+ Bin = case Head#headers.content_length of
+ undefined ->
+ case Head#headers.connection of
+ "close" ->
+ get_client_data(CliSock, all, is_ssl(SC#sconf.ssl));
+ _ ->
+ ?Debug("No content length header ",[]),
+ exit(normal)
+ end;
+ Len when integer(PPS) ->
+ Int_len = list_to_integer(Len),
+ if
+ Int_len == 0 ->
+ <<>>;
+ PPS < Int_len ->
+ {partial, get_client_data(CliSock, PPS,
+ is_ssl(SC#sconf.ssl))};
+ true ->
+ get_client_data(CliSock, Int_len,
+ is_ssl(SC#sconf.ssl))
+ end;
+ Len when PPS == nolimit ->
+ Int_len = list_to_integer(Len),
+ if
+ Int_len == 0 ->
+ <<>>;
+ true ->
+ get_client_data(CliSock, Int_len,
+ is_ssl(SC#sconf.ssl))
+ end
+ end,
+ ARG = make_arg(CliSock, Head, Req, Bin),
+ handle_request(CliSock, ARG, size(un_partial(Bin))).
+
+
+
make_arg(CliSock, Head, Req, Bin) ->
SC = get(sc),
ARG = #arg{clisock = CliSock,
@@ -1177,6 +1227,9 @@ make_arg(CliSock, Head, Req, Bin) ->
clidata = Bin},
apply(SC#sconf.arg_rewrite_mod, arg_rewrite, [ARG]).
+
+handle_extension_method("PROPFIND", CliSock, Req, Head) ->
+ 'PROPFIND'(CliSock, Req, Head);
handle_extension_method(_Method, CliSock, Req, Head) ->
not_implemented(CliSock, Req, Head).

0 comments on commit 16299b3

Please sign in to comment.