%%% BEGIN openflax/handler/autocomplete.erl %%% %%% %%% openflax - Open Source web server for Erlang/OTP %%% Copyright (c)2003 Cat's Eye Technologies. All rights reserved. %%% %%% Redistribution and use in source and binary forms, with or without %%% modification, are permitted provided that the following conditions %%% are met: %%% %%% Redistributions of source code must retain the above copyright %%% notice, this list of conditions and the following disclaimer. %%% %%% Redistributions in binary form must reproduce the above copyright %%% notice, this list of conditions and the following disclaimer in %%% the documentation and/or other materials provided with the %%% distribution. %%% %%% Neither the name of Cat's Eye Technologies nor the names of its %%% contributors may be used to endorse or promote products derived %%% from this software without specific prior written permission. %%% %%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND %%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, %%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF %%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE %%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE %%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, %%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, %%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, %%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON %%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, %%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY %%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE %%% POSSIBILITY OF SUCH DAMAGE. %% @doc Filename auto-completion handler for OpenFlax. %% %%

This handler should be invoked from cfg_openflax_dispatch %% when the URI matches a pattern of "* " or similar. %% The trailing space (shown as a plus sign in the URL) indicates the %% filename is not complete. This handler will complete that filename, %% if possible, and redirect the user agent to that resource.

%% %%

This handler requires openflax.handler.file.

%% %% @end -module(openflax.handler.autocomplete). -vsn('$Id: autocomplete.erl 31 2004-04-23 07:00:11Z catseye $'). -author('cpressey@catseye.mine.nu'). -copyright('Copyright (c)2003 Cat`s Eye Technologies. All rights reserved.'). -behaviour(openflax.handler). -export([start/1, stop/1, serve/1]). % behaviour -import(lists). -import(string). -import(filename). -import(file). %% @spec start(conf()) -> conf() %% @doc Initializes the filename auto-completion handler. start(Conf) -> openflax.conf:new(). %% @spec stop(conf()) -> conf() %% @doc Shuts down the auto-completion handler. stop(Conf) -> Conf. %% @spec serve(conf()) -> ok | {error, Reason} %% @doc Redirects the user agent from a partial filename %% to a full filename matching the partial filename, if any. serve(Conf) -> FileName = openflax.handler.file:document(Conf), % Perform filename completion case complete(openflax.string:truncate(FileName), Conf) of [NewFileName | _] -> % Found a prefix, so redirect them to it redirect_completed(NewFileName, Conf); [] -> % No match at all - still not found {not_found, Conf} end. %% @spec redirect_completed(filename(), conf()) -> ok %% @doc Redirects the user agent to the completed filename. %% Called only when filename completion is successful. redirect_completed(NewFileName, Conf) -> StartChar = length(openflax.conf:get_string(cfg_document_root, Conf)) + 1, NewFileName0 = "/" ++ string:substr(NewFileName, StartChar), {{moved_permanently, NewFileName0}, Conf}. %% @spec complete(string(), conf()) -> [filename()] %% @doc Given a partial name of a file with a full path, returns a list of %% files in that directory that the prefix matches. The list may be empty %% (if no files match,) it may have one entry (if there was a unique match,) %% or it may have many entries (if the prefix was ambiguous.) complete(PartialFileName, Conf) -> DirName = filename:dirname(PartialFileName), BaseName = filename:basename(PartialFileName), {ok, Dir} = file:list_dir(DirName), Dir0 = lists:filter(fun(X) -> openflax.handler.file:is_accessible(filename:join([DirName, X]), Conf) end, Dir), Dir1 = lists:reverse(lists:sort(Dir0)), complete(DirName, Dir1, BaseName, length(BaseName), []). complete(DirName, [], PartialFileName, Length, Acc) -> Acc; complete(DirName, [FileName | Tail], PartialFileName, Length, Acc) -> Test = string:left(FileName, Length), case string:left(FileName, Length) of PartialFileName -> FullFileName = filename:join([DirName, FileName]), complete(DirName, Tail, PartialFileName, Length, [FullFileName | Acc]); _ -> complete(DirName, Tail, PartialFileName, Length, Acc) end. %%% END of openflax/handler/autocomplete.erl %%%