diff options
Diffstat (limited to 'src/web/mod_http_fileserver.erl')
-rw-r--r-- | src/web/mod_http_fileserver.erl | 141 |
1 files changed, 84 insertions, 57 deletions
diff --git a/src/web/mod_http_fileserver.erl b/src/web/mod_http_fileserver.erl index 71a62720..8fe0c0fc 100644 --- a/src/web/mod_http_fileserver.erl +++ b/src/web/mod_http_fileserver.erl @@ -25,6 +25,7 @@ %%%---------------------------------------------------------------------- -module(mod_http_fileserver). + -author('mmirra@process-one.net'). -behaviour(gen_mod). @@ -47,58 +48,66 @@ -export([reopen_log/1]). -include("ejabberd.hrl"). + -include("jlib.hrl"). + -include_lib("kernel/include/file.hrl"). %%-include("ejabberd_http.hrl"). %% TODO: When ejabberd-modules SVN gets the new ejabberd_http.hrl, delete this code: --record(request, {method, - path, - q = [], - us, - auth, - lang = "", - data = "", - ip, - host, % string() - port, % integer() - tp, % transfer protocol = http | https - headers - }). +-record(request, + {method, path, q = [], us, auth, lang = <<"">>, + data = <<"">>, ip, host, port, tp, headers}). -ifdef(SSL40). + -define(STRING2LOWER, string). + -else. + -ifdef(SSL39). + -define(STRING2LOWER, string). + -else. + -define(STRING2LOWER, httpd_util). + -endif. + -endif. --record(state, {host, docroot, accesslog, accesslogfd, directory_indices, - custom_headers, default_content_type, content_types = []}). +-record(state, + {host, docroot, accesslog, accesslogfd, + directory_indices, custom_headers, default_content_type, + content_types = []}). -define(PROCNAME, ejabberd_mod_http_fileserver). %% Response is {DataSize, Code, [{HeaderKey, HeaderValue}], Data} --define(HTTP_ERR_FILE_NOT_FOUND, {-1, 404, [], "Not found"}). --define(HTTP_ERR_FORBIDDEN, {-1, 403, [], "Forbidden"}). - --define(DEFAULT_CONTENT_TYPE, "application/octet-stream"). --define(DEFAULT_CONTENT_TYPES, [{".css", "text/css"}, - {".gif", "image/gif"}, - {".html", "text/html"}, - {".jar", "application/java-archive"}, - {".jpeg", "image/jpeg"}, - {".jpg", "image/jpeg"}, - {".js", "text/javascript"}, - {".png", "image/png"}, - {".svg", "image/svg+xml"}, - {".txt", "text/plain"}, - {".xml", "application/xml"}, - {".xpi", "application/x-xpinstall"}, - {".xul", "application/vnd.mozilla.xul+xml"}]). +-define(HTTP_ERR_FILE_NOT_FOUND, + {-1, 404, [], <<"Not found">>}). + +-define(HTTP_ERR_FORBIDDEN, + {-1, 403, [], <<"Forbidden">>}). + +-define(DEFAULT_CONTENT_TYPE, + <<"application/octet-stream">>). + +-define(DEFAULT_CONTENT_TYPES, + [{<<".css">>, <<"text/css">>}, + {<<".gif">>, <<"image/gif">>}, + {<<".html">>, <<"text/html">>}, + {<<".jar">>, <<"application/java-archive">>}, + {<<".jpeg">>, <<"image/jpeg">>}, + {<<".jpg">>, <<"image/jpeg">>}, + {<<".js">>, <<"text/javascript">>}, + {<<".png">>, <<"image/png">>}, + {<<".svg">>, <<"image/svg+xml">>}, + {<<".txt">>, <<"text/plain">>}, + {<<".xml">>, <<"application/xml">>}, + {<<".xpi">>, <<"application/x-xpinstall">>}, + {<<".xul">>, <<"application/vnd.mozilla.xul+xml">>}]). -compile(export_all). @@ -162,22 +171,34 @@ init([Host, Opts]) -> end. initialize(Host, Opts) -> - DocRoot = gen_mod:get_opt(docroot, Opts, undefined), + DocRoot = gen_mod:get_opt(docroot, Opts, fun(A) -> A end, undefined), check_docroot_defined(DocRoot, Host), DRInfo = check_docroot_exists(DocRoot), check_docroot_is_dir(DRInfo, DocRoot), check_docroot_is_readable(DRInfo, DocRoot), - AccessLog = gen_mod:get_opt(accesslog, Opts, undefined), + AccessLog = gen_mod:get_opt(accesslog, Opts, + fun iolist_to_binary/1, + undefined), AccessLogFD = try_open_log(AccessLog, Host), - DirectoryIndices = gen_mod:get_opt(directory_indices, Opts, []), - CustomHeaders = gen_mod:get_opt(custom_headers, Opts, []), + DirectoryIndices = gen_mod:get_opt(directory_indices, Opts, + fun(L) when is_list(L) -> L end, + []), + CustomHeaders = gen_mod:get_opt(custom_headers, Opts, + fun(L) when is_list(L) -> L end, + []), DefaultContentType = gen_mod:get_opt(default_content_type, Opts, + fun iolist_to_binary/1, ?DEFAULT_CONTENT_TYPE), - ContentTypes = build_list_content_types(gen_mod:get_opt(content_types, Opts, []), ?DEFAULT_CONTENT_TYPES), + ContentTypes = build_list_content_types( + gen_mod:get_opt(content_types, Opts, + fun(L) when is_list(L) -> L end, + []), + ?DEFAULT_CONTENT_TYPES), ?INFO_MSG("initialize: ~n ~p", [ContentTypes]),%+++ {DocRoot, AccessLog, AccessLogFD, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes}. + %% @spec (AdminCTs::[CT], Default::[CT]) -> [CT] %% where CT = {Extension::string(), Value} %% Value = string() | undefined @@ -187,32 +208,36 @@ initialize(Host, Opts) -> build_list_content_types(AdminCTsUnsorted, DefaultCTsUnsorted) -> AdminCTs = lists:ukeysort(1, AdminCTsUnsorted), DefaultCTs = lists:ukeysort(1, DefaultCTsUnsorted), - CTsUnfiltered = lists:ukeymerge(1, AdminCTs, DefaultCTs), - [{Extension, Value} || {Extension, Value} <- CTsUnfiltered, Value /= undefined]. + CTsUnfiltered = lists:ukeymerge(1, AdminCTs, + DefaultCTs), + [{Extension, Value} + || {Extension, Value} <- CTsUnfiltered, + Value /= undefined]. check_docroot_defined(DocRoot, Host) -> case DocRoot of - undefined -> throw({undefined_docroot_option, Host}); - _ -> ok + undefined -> throw({undefined_docroot_option, Host}); + _ -> ok end. check_docroot_exists(DocRoot) -> case file:read_file_info(DocRoot) of - {error, Reason} -> throw({error_access_docroot, DocRoot, Reason}); - {ok, FI} -> FI + {error, Reason} -> + throw({error_access_docroot, DocRoot, Reason}); + {ok, FI} -> FI end. check_docroot_is_dir(DRInfo, DocRoot) -> case DRInfo#file_info.type of - directory -> ok; - _ -> throw({docroot_not_directory, DocRoot}) + directory -> ok; + _ -> throw({docroot_not_directory, DocRoot}) end. check_docroot_is_readable(DRInfo, DocRoot) -> case DRInfo#file_info.access of - read -> ok; - read_write -> ok; - _ -> throw({docroot_not_readable, DocRoot}) + read -> ok; + read_write -> ok; + _ -> throw({docroot_not_readable, DocRoot}) end. try_open_log(undefined, _Host) -> @@ -341,12 +366,14 @@ serve_index(FileName, [Index | T], CH, DefaultContentType, ContentTypes) -> %% and serve it up. serve_file(FileInfo, FileName, CustomHeaders, DefaultContentType, ContentTypes) -> ?DEBUG("Delivering: ~s", [FileName]), + ContentType = content_type(FileName, DefaultContentType, + ContentTypes), {ok, FileContents} = file:read_file(FileName), - ContentType = content_type(FileName, DefaultContentType, ContentTypes), - {FileInfo#file_info.size, - 200, [{"Server", "ejabberd"}, - {"Last-Modified", last_modified(FileInfo)}, - {"Content-Type", ContentType} | CustomHeaders], + {FileInfo#file_info.size, 200, + [{<<"Server">>, <<"ejabberd">>}, + {<<"Last-Modified">>, last_modified(FileInfo)}, + {<<"Content-Type">>, ContentType} + | CustomHeaders], FileContents}. %%---------------------------------------------------------------------- @@ -406,8 +433,8 @@ add_to_log(File, FileSize, Code, Request) -> find_header(Header, Headers, Default) -> case lists:keysearch(Header, 1, Headers) of - {value, {_, Value}} -> Value; - false -> Default + {value, {_, Value}} -> Value; + false -> Default end. %%---------------------------------------------------------------------- @@ -426,8 +453,8 @@ join([H | T], Separator) -> content_type(Filename, DefaultContentType, ContentTypes) -> Extension = ?STRING2LOWER:to_lower(filename:extension(Filename)), case lists:keysearch(Extension, 1, ContentTypes) of - {value, {_, ContentType}} -> ContentType; - false -> DefaultContentType + {value, {_, ContentType}} -> ContentType; + false -> DefaultContentType end. last_modified(FileInfo) -> |