couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cml...@apache.org
Subject svn commit: r642953 [3/3] - in /incubator/couchdb/vendor/mochiweb: ./ current/ current/deps/ current/doc/ current/ebin/ current/include/ current/priv/ current/priv/skel/ current/priv/skel/deps/ current/priv/skel/doc/ current/priv/skel/ebin/ current/pri...
Date Mon, 31 Mar 2008 10:30:34 GMT
Added: incubator/couchdb/vendor/mochiweb/current/src/mochiweb_response.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb_response.erl?rev=642953&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb_response.erl (added)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb_response.erl Mon Mar 31 03:30:27
2008
@@ -0,0 +1,52 @@
+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2007 Mochi Media, Inc.
+
+%% @doc Response abstraction.
+
+-module(mochiweb_response, [Request, Code, Headers]).
+-author('bob@mochimedia.com').
+
+-define(QUIP, "Any of you quaids got a smint?").
+
+-export([get_header_value/1, get/1, dump/0]).
+-export([send/1, write_chunk/1]).
+
+%% @spec get_header_value(string() | atom() | binary()) -> string() | undefined
+%% @doc Get the value of the given response header.
+get_header_value(K) ->
+    mochiweb_headers:get_value(K, Headers).
+
+%% @spec get(request | code | headers) -> term()
+%% @doc Return the internal representation of the given field.
+get(request) ->
+    Request;
+get(code) ->
+    Code;
+get(headers) ->
+    Headers.
+
+%% @spec dump() -> {mochiweb_request, [{atom(), term()}]}
+%% @doc Dump the internal representation to a "human readable" set of terms
+%%      for debugging/inspection purposes.
+dump() ->
+    [{request, Request:dump()},
+     {code, Code},
+     {headers, mochiweb_headers:to_list(Headers)}].
+
+%% @spec send(iodata()) -> ok
+%% @doc Send data over the socket if the method is not HEAD.
+send(Data) ->
+    case Request:get(method) of
+	'HEAD' ->
+	    ok;
+	_ ->
+	    Request:send(Data)
+    end.
+
+%% @spec write_chunk(iodata()) -> ok
+%% @doc Write a chunk of a HTTP chunked response. If Data is zero length,
+%%      then the chunked response will be finished.
+write_chunk(Data) ->
+    Length = iolist_size(Data),    
+    send(io_lib:format("~.16b\r\n", [Length])),
+    send([Data, <<"\r\n">>]).

Added: incubator/couchdb/vendor/mochiweb/current/src/mochiweb_skel.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb_skel.erl?rev=642953&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb_skel.erl (added)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb_skel.erl Mon Mar 31 03:30:27 2008
@@ -0,0 +1,71 @@
+-module(mochiweb_skel).
+-export([skelcopy/2]).
+
+-include_lib("kernel/include/file.hrl").
+
+%% External API
+
+skelcopy(DestDir, Name) ->
+    ok = ensuredir(DestDir),
+    LDst = case length(filename:dirname(DestDir)) of 
+               1 -> %% handle case when dirname returns "/"
+                   0;
+               N ->
+                   N + 1
+           end,
+    skelcopy(src(), DestDir, Name, LDst),
+    ok = file:make_symlink(
+        filename:join(filename:dirname(code:which(?MODULE)), ".."),
+        filename:join([DestDir, Name, "deps", "mochiweb-src"])).
+    
+
+%% Internal API
+
+src() ->
+    Dir = filename:dirname(code:which(?MODULE)),
+    filename:join(Dir, "../priv/skel").
+
+skel() ->
+    "skel".
+
+skelcopy(Src, DestDir, Name, LDst) ->
+    {ok, Dest, _} = regexp:gsub(filename:basename(Src), skel(), Name),
+    case file:read_file_info(Src) of
+        {ok, #file_info{type=directory, mode=Mode}} ->
+            Dir = DestDir ++ "/" ++ Dest,
+            EDst = lists:nthtail(LDst, Dir),
+            ok = ensuredir(Dir),
+            ok = file:write_file_info(Dir, #file_info{mode=Mode}),
+            {ok, Files} = file:list_dir(Src),
+            io:format("~s/~n", [EDst]),
+            lists:foreach(fun ("." ++ _) -> ok;
+                              (F) ->
+                                  skelcopy(filename:join(Src, F), 
+                                           Dir,
+                                           Name,
+                                           LDst)
+                          end,
+                          Files),
+            ok;
+        {ok, #file_info{type=regular, mode=Mode}} ->
+            OutFile = filename:join(DestDir, Dest),
+            {ok, B} = file:read_file(Src),
+            {ok, S, _} = regexp:gsub(binary_to_list(B), skel(), Name),
+            ok = file:write_file(OutFile, list_to_binary(S)),
+            ok = file:write_file_info(OutFile, #file_info{mode=Mode}),
+            io:format("    ~s~n", [filename:basename(Src)]),
+            ok;
+        {ok, _} ->
+            io:format("ignored source file: ~p~n", [Src]),
+            ok
+    end.
+
+ensuredir(Dir) ->
+    case file:make_dir(Dir) of
+        ok ->
+            ok;
+        {error, eexist} ->
+            ok;
+        E ->
+            E
+    end.

Added: incubator/couchdb/vendor/mochiweb/current/src/mochiweb_socket_server.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb_socket_server.erl?rev=642953&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb_socket_server.erl (added)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb_socket_server.erl Mon Mar 31 03:30:27
2008
@@ -0,0 +1,234 @@
+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2007 Mochi Media, Inc.
+
+%% @doc MochiWeb socket server.
+
+-module(mochiweb_socket_server).
+-author('bob@mochimedia.com').
+-behaviour(gen_server).
+
+-export([start/1, stop/1]).
+-export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3,
+	 handle_info/2]).
+-export([get/2]).
+
+-export([acceptor_loop/1]).
+
+-record(mochiweb_socket_server,
+	{port,
+	 loop,
+	 name=undefined,
+	 max=2048,
+	 ip=any,
+	 listen=null,
+	 acceptor=null,
+         backlog=30}).
+
+start(State=#mochiweb_socket_server{}) ->
+    start_server(State);
+start(Options) ->
+    start(parse_options(Options)).
+
+get(Name, Property) ->
+    gen_server:call(Name, {get, Property}).
+
+stop(Name) when is_atom(Name) ->
+    gen_server:cast(Name, stop);
+stop(Pid) when is_pid(Pid) ->
+    gen_server:cast(Pid, stop);
+stop({local, Name}) ->
+    stop(Name);
+stop({global, Name}) ->
+    stop(Name);
+stop(Options) ->
+    State = parse_options(Options),
+    stop(State#mochiweb_socket_server.name).
+
+%% Internal API
+
+parse_options(Options) ->
+    parse_options(Options, #mochiweb_socket_server{}).
+
+parse_options([], State) ->
+    State;
+parse_options([{name, L} | Rest], State) when is_list(L) ->
+    Name = {local, list_to_atom(L)},
+    parse_options(Rest, State#mochiweb_socket_server{name=Name});
+parse_options([{name, A} | Rest], State) when is_atom(A) ->
+    Name = {local, A},
+    parse_options(Rest, State#mochiweb_socket_server{name=Name});
+parse_options([{name, Name} | Rest], State) ->
+    parse_options(Rest, State#mochiweb_socket_server{name=Name});
+parse_options([{port, L} | Rest], State) when is_list(L) ->
+    Port = list_to_integer(L),
+    parse_options(Rest, State#mochiweb_socket_server{port=Port});
+parse_options([{port, Port} | Rest], State) ->
+    parse_options(Rest, State#mochiweb_socket_server{port=Port});
+parse_options([{ip, Ip} | Rest], State) ->
+    ParsedIp = case Ip of
+		   any ->
+		       any;
+		   Ip when is_tuple(Ip) ->
+		       Ip;
+		   Ip when is_list(Ip) ->
+		       {ok, IpTuple} = inet_parse:address(Ip),
+		       IpTuple
+	       end,
+    parse_options(Rest, State#mochiweb_socket_server{ip=ParsedIp});
+parse_options([{loop, Loop} | Rest], State) ->
+    parse_options(Rest, State#mochiweb_socket_server{loop=Loop});
+parse_options([{backlog, Backlog} | Rest], State) ->
+    parse_options(Rest, State#mochiweb_socket_server{backlog=Backlog});
+parse_options([{max, Max} | Rest], State) ->
+    MaxInt = case Max of
+		 Max when is_list(Max) ->
+		     list_to_integer(Max);
+		 Max when is_integer(Max) ->
+		     Max
+	     end,
+    parse_options(Rest, State#mochiweb_socket_server{max=MaxInt}).
+
+start_server(State=#mochiweb_socket_server{name=Name}) ->
+    case Name of
+	undefined ->
+	    gen_server:start_link(?MODULE, State, []);
+	_ ->
+	    gen_server:start_link(Name, ?MODULE, State, [])
+    end.
+
+init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog}) ->
+    process_flag(trap_exit, true),
+    BaseOpts = [binary, 
+		{reuseaddr, true},
+		{packet, 0},
+		{backlog, Backlog},
+		{recbuf, 8192},
+		{active, false}],
+    Opts = case Ip of
+	       any ->
+		   BaseOpts;
+	       Ip ->
+		   [{ip, Ip} | BaseOpts]
+	   end,
+    case gen_tcp_listen(Port, Opts, State) of
+        {stop, eacces} ->
+            case Port < 1024 of 
+                true ->
+                    case fdsrv:start() of
+                        {ok, _} ->
+                            case fdsrv:bind_socket(tcp, Port) of
+                                {ok, Fd} ->
+                                    gen_tcp_listen(Port, [{fd, Fd} | Opts], State);
+                                _ ->
+                                    {stop, fdsrv_bind_failed}
+                            end;
+                        _ ->
+                            {stop, fdsrv_start_failed}
+                    end;
+                false ->
+                    {stop, eacces}
+            end;
+        Other ->
+            Other
+    end.
+
+gen_tcp_listen(Port, Opts, State) ->
+    case gen_tcp:listen(Port, Opts) of
+        {ok, Listen} ->
+      	    {ok, ListenPort} = inet:port(Listen),
+       	    {ok, new_acceptor(State#mochiweb_socket_server{listen=Listen, 
+                                                           port=ListenPort})};
+      	{error, Reason} ->
+       	    {stop, Reason}
+    end.
+
+new_acceptor(State=#mochiweb_socket_server{max=0}) ->
+    io:format("Not accepting new connections~n"),
+    State#mochiweb_socket_server{acceptor=null};
+new_acceptor(State=#mochiweb_socket_server{listen=Listen,loop=Loop}) ->
+    Pid = proc_lib:spawn_link(?MODULE, acceptor_loop,
+			      [{self(), Listen, Loop}]),
+    State#mochiweb_socket_server{acceptor=Pid}.
+
+call_loop({M, F}, Socket) ->
+    M:F(Socket);
+call_loop(Loop, Socket) ->
+    Loop(Socket).
+
+acceptor_loop({Server, Listen, Loop}) ->
+    case catch gen_tcp:accept(Listen) of
+	{ok, Socket} ->
+	    gen_server:cast(Server, {accepted, self()}),
+	    call_loop(Loop, Socket);
+	{error, closed} ->
+	    exit({error, closed});
+	Other ->
+	    error_logger:error_report(
+	      [{application, mochiweb},
+	       "Accept failed error",
+	       lists:flatten(io_lib:format("~p", [Other]))]),
+	    exit({error, accept_failed})
+    end.
+	    
+
+do_get(port, #mochiweb_socket_server{port=Port}) ->
+    Port.
+    
+handle_call({get, Property}, _From, State) ->
+    Res = do_get(Property, State),
+    {reply, Res, State};
+handle_call(_Message, _From, State) ->
+    Res = error,
+    {reply, Res, State}.
+
+handle_cast({accepted, Pid},
+	    State=#mochiweb_socket_server{acceptor=Pid, max=Max}) ->
+    % io:format("accepted ~p~n", [Pid]),
+    State1 = State#mochiweb_socket_server{max=Max - 1},
+    {noreply, new_acceptor(State1)};
+handle_cast(stop, State) ->
+    {stop, normal, State}.
+
+terminate(_Reason, #mochiweb_socket_server{listen=Listen, port=Port}) ->
+    gen_tcp:close(Listen),
+    case Port < 1024 of 
+        true ->
+            catch fdsrv:stop(),
+            ok;
+        false ->
+            ok
+    end.
+
+code_change(_OldVsn, State, _Extra) ->
+    State.
+
+handle_info({'EXIT', Pid, normal},
+	    State=#mochiweb_socket_server{acceptor=Pid}) ->
+    % io:format("normal acceptor down~n"),
+    {noreply, new_acceptor(State)};
+handle_info({'EXIT', Pid, Reason},
+	    State=#mochiweb_socket_server{acceptor=Pid}) ->
+    error_logger:error_report({?MODULE, ?LINE,
+			       {acceptor_error, Reason}}),
+    timer:sleep(100),
+    {noreply, new_acceptor(State)};
+handle_info({'EXIT', _LoopPid, Reason},
+	    State=#mochiweb_socket_server{acceptor=Pid, max=Max}) ->
+    case Reason of 
+	normal ->
+	    ok;
+	_ ->
+	    error_logger:error_report({?MODULE, ?LINE,
+				       {child_error, Reason}})
+    end,
+    State1 = State#mochiweb_socket_server{max=Max + 1},
+    State2 = case Pid of
+		 null ->
+		     new_acceptor(State1);
+		 _ ->
+		     State1
+	     end,
+    {noreply, State2};
+handle_info(Info, State) ->
+    error_logger:info_report([{'INFO', Info}, {'State', State}]),
+    {noreply, State}.

Added: incubator/couchdb/vendor/mochiweb/current/src/mochiweb_sup.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb_sup.erl?rev=642953&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb_sup.erl (added)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb_sup.erl Mon Mar 31 03:30:27 2008
@@ -0,0 +1,34 @@
+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2007 Mochi Media, Inc.
+
+%% @doc Supervisor for the mochiweb application.
+
+-module(mochiweb_sup).
+-author('bob@mochimedia.com').
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start_link/0, upgrade/0]).
+
+%% supervisor callbacks
+-export([init/1]).
+
+%% @spec start_link() -> ServerRet
+%% @doc API for starting the supervisor.
+start_link() ->
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% @spec upgrade() -> ok
+%% @doc Add processes if necessary.
+upgrade() ->
+    {ok, {_, Specs}} = init([]),
+    [supervisor:start_child(?MODULE, Spec) || Spec <- Specs],
+    ok.
+
+%% @spec init([]) -> SupervisorTree
+%% @doc supervisor callback, ensures yaws is in embedded mode and then
+%%      returns the supervisor tree.
+init([]) ->
+    Processes = [],
+    {ok, {{one_for_one, 10, 10}, Processes}}.

Added: incubator/couchdb/vendor/mochiweb/current/src/mochiweb_util.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/mochiweb_util.erl?rev=642953&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/mochiweb_util.erl (added)
+++ incubator/couchdb/vendor/mochiweb/current/src/mochiweb_util.erl Mon Mar 31 03:30:27 2008
@@ -0,0 +1,486 @@
+%% @author Bob Ippolito <bob@mochimedia.com>
+%% @copyright 2007 Mochi Media, Inc.
+
+%% @doc Utilities for parsing and quoting.
+
+-module(mochiweb_util).
+-author('bob@mochimedia.com').
+-export([join/2, quote_plus/1, urlencode/1, parse_qs/1, unquote/1]).
+-export([path_split/1]).
+-export([urlsplit/1, urlsplit_path/1, urlunsplit/1, urlunsplit_path/1]).
+-export([guess_mime/1, parse_header/1]).
+-export([shell_quote/1, cmd/1, cmd_string/1, cmd_port/2]).
+-export([record_to_proplist/2, record_to_proplist/3]).
+-export([test/0]).
+
+-define(PERCENT, 37).  % $\%
+-define(FULLSTOP, 46). % $\.
+-define(IS_HEX(C), ((C >= $0 andalso C =< $9) orelse
+		    (C >= $a andalso C =< $f) orelse
+		    (C >= $A andalso C =< $F))).
+-define(QS_SAFE(C), ((C >= $a andalso C =< $z) orelse
+		     (C >= $A andalso C =< $Z) orelse
+		     (C >= $0 andalso C =< $9) orelse
+		     (C =:= ?FULLSTOP orelse C =:= $- orelse C =:= $~ orelse
+		      C =:= $_))).
+
+hexdigit(C) when C < 10 -> $0 + C;
+hexdigit(C) when C < 16 -> $A + (C - 10).
+
+unhexdigit(C) when C >= $0, C =< $9 -> C - $0;
+unhexdigit(C) when C >= $a, C =< $f -> C - $a + 10;
+unhexdigit(C) when C >= $A, C =< $F -> C - $A + 10.
+
+%% @spec shell_quote(string()) -> string()
+%% @doc Quote a string according to UNIX shell quoting rules, returns a string
+%%      surrounded by double quotes.
+shell_quote(L) ->
+    shell_quote(L, [$\"]).
+
+%% @spec cmd_port([string()], Options) -> port()
+%% @doc open_port({spawn, mochiweb_util:cmd_string(Argv)}, Options).
+cmd_port(Argv, Options) ->
+    open_port({spawn, cmd_string(Argv)}, Options).
+
+%% @spec cmd([string()]) -> string()
+%% @doc os:cmd(cmd_string(Argv)).
+cmd(Argv) ->
+    os:cmd(cmd_string(Argv)).
+
+%% @spec cmd_string([string()]) -> string()
+%% @doc Create a shell quoted command string from a list of arguments.
+cmd_string(Argv) ->
+    join([shell_quote(X) || X <- Argv], " ").
+
+%% @spec join([string()], Separator) -> string()
+%% @doc Join a list of strings together with the given separator
+%%      string or char.
+join([], _Separator) ->
+    [];
+join([S], _Separator) ->
+    lists:flatten(S);
+join(Strings, Separator) ->
+    lists:flatten(revjoin(lists:reverse(Strings), Separator, [])).
+
+revjoin([], _Separator, Acc) ->
+    Acc;
+revjoin([S | Rest], Separator, []) ->
+    revjoin(Rest, Separator, [S]);
+revjoin([S | Rest], Separator, Acc) ->
+    revjoin(Rest, Separator, [S, Separator | Acc]).
+
+%% @spec quote_plus(atom() | integer() | string()) -> string()
+%% @doc URL safe encoding of the given term.
+quote_plus(Atom) when is_atom(Atom) ->
+    quote_plus(atom_to_list(Atom));
+quote_plus(Int) when is_integer(Int) ->
+    quote_plus(integer_to_list(Int));
+quote_plus(String) ->
+    quote_plus(String, []).
+
+quote_plus([], Acc) ->
+    lists:reverse(Acc);
+quote_plus([C | Rest], Acc) when ?QS_SAFE(C) ->
+    quote_plus(Rest, [C | Acc]);
+quote_plus([$\s | Rest], Acc) ->
+    quote_plus(Rest, [$+ | Acc]);
+quote_plus([C | Rest], Acc) ->
+    <<Hi:4, Lo:4>> = <<C>>,
+    quote_plus(Rest, [hexdigit(Lo), hexdigit(Hi), ?PERCENT | Acc]).
+
+%% @spec urlencode([{Key, Value}]) -> string()
+%% @doc URL encode the property list.
+urlencode(Props) ->
+    RevPairs = lists:foldl(fun ({K, V}, Acc) ->
+				   [[quote_plus(K), $=, quote_plus(V)] | Acc]
+			   end, [], Props),
+    lists:flatten(revjoin(RevPairs, $&, [])).
+
+%% @spec parse_qs(string() | binary()) -> [{Key, Value}]
+%% @doc Parse a query string or application/x-www-form-urlencoded.
+parse_qs(Binary) when is_binary(Binary) ->
+    parse_qs(binary_to_list(Binary));
+parse_qs(String) ->
+    parse_qs(String, []).
+
+parse_qs([], Acc) ->
+    lists:reverse(Acc);
+parse_qs(String, Acc) ->
+    {Key, Rest} = parse_qs_key(String),
+    {Value, Rest1} = parse_qs_value(Rest),
+    parse_qs(Rest1, [{Key, Value} | Acc]).
+
+parse_qs_key(String) ->
+    parse_qs_key(String, []).
+
+parse_qs_key([], Acc) ->
+    {qs_revdecode(Acc), ""};
+parse_qs_key([$= | Rest], Acc) ->
+    {qs_revdecode(Acc), Rest};
+parse_qs_key(Rest=[$; | _], Acc) ->
+    {qs_revdecode(Acc), Rest};
+parse_qs_key(Rest=[$& | _], Acc) ->
+    {qs_revdecode(Acc), Rest};
+parse_qs_key([C | Rest], Acc) ->
+    parse_qs_key(Rest, [C | Acc]).
+
+parse_qs_value(String) ->
+    parse_qs_value(String, []).
+
+parse_qs_value([], Acc) ->
+    {qs_revdecode(Acc), ""};
+parse_qs_value([$; | Rest], Acc) ->
+    {qs_revdecode(Acc), Rest};
+parse_qs_value([$& | Rest], Acc) ->
+    {qs_revdecode(Acc), Rest};
+parse_qs_value([C | Rest], Acc) ->
+    parse_qs_value(Rest, [C | Acc]).
+
+%% @spec unquote(string() | binary()) -> string()
+%% @doc Unquote a URL encoded string.
+unquote(Binary) when is_binary(Binary) ->
+    unquote(binary_to_list(Binary));
+unquote(String) ->
+    qs_revdecode(lists:reverse(String)).
+
+qs_revdecode(S) ->
+    qs_revdecode(S, []).
+
+qs_revdecode([], Acc) ->
+    Acc;
+qs_revdecode([$+ | Rest], Acc) ->
+    qs_revdecode(Rest, [$\s | Acc]);
+qs_revdecode([Lo, Hi, ?PERCENT | Rest], Acc) when ?IS_HEX(Lo), ?IS_HEX(Hi) ->
+    qs_revdecode(Rest, [(unhexdigit(Lo) bor (unhexdigit(Hi) bsl 4)) | Acc]);
+qs_revdecode([C | Rest], Acc) ->
+    qs_revdecode(Rest, [C | Acc]).
+
+%% @spec urlsplit(Url) -> {Scheme, Netloc, Path, Query, Fragment}
+%% @doc Return a 5-tuple, does not expand % escapes. Only supports HTTP style
+%%      URLs.
+urlsplit(Url) ->
+    {Scheme, Url1} = urlsplit_scheme(Url),
+    {Netloc, Url2} = urlsplit_netloc(Url1),
+    {Path, Query, Fragment} = urlsplit_path(Url2),
+    {Scheme, Netloc, Path, Query, Fragment}.
+
+urlsplit_scheme(Url) ->
+    urlsplit_scheme(Url, []).
+
+urlsplit_scheme([], Acc) ->
+    {"", lists:reverse(Acc)};
+urlsplit_scheme(":" ++ Rest, Acc) ->
+    {string:to_lower(lists:reverse(Acc)), Rest};
+urlsplit_scheme([C | Rest], Acc) ->
+    urlsplit_scheme(Rest, [C | Acc]).
+
+urlsplit_netloc("//" ++ Rest) ->
+    urlsplit_netloc(Rest, []);
+urlsplit_netloc(Path) ->
+    {"", Path}.
+
+urlsplit_netloc(Rest=[C | _], Acc) when C =:= $/; C =:= $?; C =:= $# ->
+    {lists:reverse(Acc), Rest};
+urlsplit_netloc([C | Rest], Acc) ->
+    urlsplit_netloc(Rest, [C | Acc]).
+
+
+%% @spec path_split(string()) -> {Part, Rest}
+%% @doc Split a path starting from the left, as in URL traversal.
+%%      path_split("foo/bar") = {"foo", "bar"},
+%%      path_split("/foo/bar") = {"", "foo/bar"}.
+path_split(S) ->
+    path_split(S, []).
+
+path_split("", Acc) ->
+    {lists:reverse(Acc), ""};
+path_split("/" ++ Rest, Acc) ->
+    {lists:reverse(Acc), Rest};
+path_split([C | Rest], Acc) ->
+    path_split(Rest, [C | Acc]).
+
+
+%% @spec urlunsplit({Scheme, Netloc, Path, Query, Fragment}) -> string()
+%% @doc Assemble a URL from the 5-tuple. Path must be absolute.
+urlunsplit({Scheme, Netloc, Path, Query, Fragment}) ->
+    lists:flatten([case Scheme of "" -> "";  _ -> [Scheme, "://"] end,
+		   Netloc,
+		   urlunsplit_path({Path, Query, Fragment})]).
+
+%% @spec urlunsplit_path({Path, Query, Fragment}) -> string()
+%% @doc Assemble a URL path from the 3-tuple.
+urlunsplit_path({Path, Query, Fragment}) ->
+    lists:flatten([Path,
+		   case Query of "" -> ""; _ -> [$? | Query] end,
+		   case Fragment of "" -> ""; _ -> [$# | Fragment] end]).
+
+%% @spec urlsplit_path(Url) -> {Path, Query, Fragment}
+%% @doc Return a 3-tuple, does not expand % escapes. Only supports HTTP style
+%%      paths.
+urlsplit_path(Path) ->
+    urlsplit_path(Path, []).
+
+urlsplit_path("", Acc) ->
+    {lists:reverse(Acc), "", ""};
+urlsplit_path("?" ++ Rest, Acc) ->
+    {Query, Fragment} = urlsplit_query(Rest),
+    {lists:reverse(Acc), Query, Fragment};
+urlsplit_path("#" ++ Rest, Acc) ->
+    {lists:reverse(Acc), "", Rest};
+urlsplit_path([C | Rest], Acc) ->
+    urlsplit_path(Rest, [C | Acc]).
+
+urlsplit_query(Query) ->
+    urlsplit_query(Query, []).
+
+urlsplit_query("", Acc) ->
+    {lists:reverse(Acc), ""};
+urlsplit_query("#" ++ Rest, Acc) ->
+    {lists:reverse(Acc), Rest};
+urlsplit_query([C | Rest], Acc) ->
+    urlsplit_query(Rest, [C | Acc]).
+
+%% @spec guess_mime(string()) -> string()
+%% @doc  Guess the mime type of a file by the extension of its filename.
+guess_mime(File) ->
+    case filename:extension(File) of
+	".html" ->
+	    "text/html";
+	".xhtml" ->
+	    "application/xhtml+xml";
+	".xml" ->
+	    "application/xml";
+	".css" ->
+	    "text/css";
+	".js" ->
+	    "application/x-javascript";
+	".jpg" ->
+	    "image/jpeg";
+	".gif" ->
+	    "image/gif";
+	".png" ->
+	    "image/png";
+	".swf" ->
+	    "application/x-shockwave-flash";
+	".zip" ->
+	    "application/zip";
+	".bz2" ->
+	    "application/x-bzip2";
+	".gz" ->
+	    "application/x-gzip";
+	".tar" ->
+	    "application/x-tar";
+	".tgz" ->
+	    "application/x-gzip";
+	".txt" ->
+	    "text/plain";
+        ".doc" ->
+            "application/msword";
+        ".pdf" ->
+            "application/pdf";
+        ".xls" ->
+            "application/vnd.ms-excel";
+        ".rtf" ->
+            "application/rtf";
+        ".mov" ->
+            "video/quicktime";
+        ".mp3" ->
+            "audio/mpeg";
+        ".z" ->
+            "application/x-compress";
+        ".wav" ->
+            "audio/x-wav";
+        ".ico" ->
+            "image/x-icon";
+        ".bmp" ->
+            "image/bmp";
+        ".m4a" ->
+            "audio/mpeg";
+        ".m3u" ->
+            "audio/x-mpegurl";
+        ".exe" ->
+            "application/octet-stream";
+        ".csv" ->
+            "text/csv";
+        _ ->
+            "text/plain"
+    end.
+
+%% @spec parse_header(string()) -> {Type, [{K, V}]}
+%% @doc  Parse a Content-Type like header, return the main Content-Type
+%%       and a property list of options.
+parse_header(String) ->
+    %% TODO: This is exactly as broken as Python's cgi module.
+    %%       Should parse properly like mochiweb_cookies.
+    [Type | Parts] = [string:strip(S) || S <- string:tokens(String, ";")],
+    F = fun (S, Acc) ->
+		case lists:splitwith(fun (C) -> C =/= $= end, S) of
+		    {"", _} ->
+			%% Skip anything with no name
+			Acc;
+		    {_, ""} ->
+			%% Skip anything with no value
+			Acc;
+		    {Name, [$\= | Value]} ->
+			[{string:to_lower(string:strip(Name)),
+			  unquote_header(string:strip(Value))} | Acc]
+		end
+	end,
+    {string:to_lower(Type),
+     lists:foldr(F, [], Parts)}.
+
+unquote_header("\"" ++ Rest) ->
+    unquote_header(Rest, []);
+unquote_header(S) ->
+    S.
+
+unquote_header("", Acc) ->
+    lists:reverse(Acc);
+unquote_header("\"", Acc) ->
+    lists:reverse(Acc);
+unquote_header([$\\, C | Rest], Acc) ->
+    unquote_header(Rest, [C | Acc]);
+unquote_header([C | Rest], Acc) ->
+    unquote_header(Rest, [C | Acc]).
+
+%% @spec record_to_proplist(Record, Fields) -> proplist()
+%% @doc calls record_to_proplist/3 with a default TypeKey of '__record'
+record_to_proplist(Record, Fields) ->
+    record_to_proplist(Record, Fields, '__record').
+
+%% @spec record_to_proplist(Record, Fields, TypeKey) -> proplist()
+%% @doc Return a proplist of the given Record with each field in the 
+%%      Fields list set as a key with the corresponding value in the Record.
+%%      TypeKey is the key that is used to store the record type
+%%      Fields should be obtained by calling record_info(fields, record_type)
+%%      where record_type is the record type of Record
+record_to_proplist(Record, Fields, TypeKey)
+  when is_tuple(Record),
+       is_list(Fields),
+       size(Record) - 1 =:= length(Fields) ->
+    lists:zip([TypeKey | Fields], tuple_to_list(Record)).
+
+
+shell_quote([], Acc) ->
+    lists:reverse([$\" | Acc]);
+shell_quote([C | Rest], Acc) when C =:= $\" orelse C =:= $\` orelse
+                                  C =:= $\\ orelse C =:= $\$ ->
+    shell_quote(Rest, [C, $\\ | Acc]);
+shell_quote([C | Rest], Acc) ->
+    shell_quote(Rest, [C | Acc]).
+
+test() ->
+    test_join(),
+    test_quote_plus(),
+    test_unquote(),
+    test_urlencode(),
+    test_parse_qs(),
+    test_urlsplit_path(),
+    test_urlunsplit_path(),
+    test_urlsplit(),
+    test_urlunsplit(),
+    test_path_split(),
+    test_guess_mime(),
+    test_parse_header(),
+    test_shell_quote(),
+    test_cmd(),
+    test_cmd_string(),
+    ok.
+
+test_shell_quote() ->
+    "\"foo \\$bar\\\"\\`' baz\"" = shell_quote("foo $bar\"`' baz"),
+    ok.
+
+test_cmd() ->
+    "$bling$ `word`!\n" = cmd(["echo", "$bling$ `word`!"]),
+    ok.
+
+test_cmd_string() ->
+    "\"echo\" \"\\$bling\\$ \\`word\\`!\"" = cmd_string(["echo", "$bling$ `word`!"]),
+    ok.
+
+test_parse_header() ->
+    {"multipart/form-data", [{"boundary", "AaB03x"}]} =
+	parse_header("multipart/form-data; boundary=AaB03x"),
+    ok.
+
+test_guess_mime() ->
+    "text/plain" = guess_mime(""),
+    "text/plain" = guess_mime(".text"),
+    "application/zip" = guess_mime(".zip"),
+    "application/zip" = guess_mime("x.zip"),
+    "text/html" = guess_mime("x.html"),
+    "application/xhtml+xml" = guess_mime("x.xhtml"),
+    ok.
+
+test_path_split() ->
+    {"", "foo/bar"} = path_split("/foo/bar"),
+    {"foo", "bar"} = path_split("foo/bar"),
+    {"bar", ""} = path_split("bar"),
+    ok.
+
+test_urlsplit() ->
+    {"", "", "/foo", "", "bar?baz"} = urlsplit("/foo#bar?baz"),
+    {"http", "host:port", "/foo", "", "bar?baz"} =
+	urlsplit("http://host:port/foo#bar?baz"),
+    ok.
+
+test_urlsplit_path() ->
+    {"/foo/bar", "", ""} = urlsplit_path("/foo/bar"),
+    {"/foo", "baz", ""} = urlsplit_path("/foo?baz"),
+    {"/foo", "", "bar?baz"} = urlsplit_path("/foo#bar?baz"),
+    {"/foo", "", "bar?baz#wibble"} = urlsplit_path("/foo#bar?baz#wibble"),
+    {"/foo", "bar", "baz"} = urlsplit_path("/foo?bar#baz"),
+    {"/foo", "bar?baz", "baz"} = urlsplit_path("/foo?bar?baz#baz"),
+    ok.
+
+test_urlunsplit() ->
+    "/foo#bar?baz" = urlunsplit({"", "", "/foo", "", "bar?baz"}),
+    "http://host:port/foo#bar?baz" =
+	urlunsplit({"http", "host:port", "/foo", "", "bar?baz"}),
+    ok.
+
+test_urlunsplit_path() ->
+    "/foo/bar" = urlunsplit_path({"/foo/bar", "", ""}),
+    "/foo?baz" = urlunsplit_path({"/foo", "baz", ""}),
+    "/foo#bar?baz" = urlunsplit_path({"/foo", "", "bar?baz"}),
+    "/foo#bar?baz#wibble" = urlunsplit_path({"/foo", "", "bar?baz#wibble"}),
+    "/foo?bar#baz" = urlunsplit_path({"/foo", "bar", "baz"}),
+    "/foo?bar?baz#baz" = urlunsplit_path({"/foo", "bar?baz", "baz"}),
+    ok.
+
+test_join() ->
+    "foo,bar,baz" = join(["foo", "bar", "baz"], $,),
+    "foo,bar,baz" = join(["foo", "bar", "baz"], ","),
+    "foo bar" = join([["foo", " bar"]], ","),
+    "foo bar,baz" = join([["foo", " bar"], "baz"], ","),
+    "foo" = join(["foo"], ","),
+    "foobarbaz" = join(["foo", "bar", "baz"], ""),
+    ok.
+
+test_quote_plus() ->
+    "foo" = quote_plus(foo),
+    "1" = quote_plus(1),
+    "foo" = quote_plus("foo"),
+    "foo+bar" = quote_plus("foo bar"),
+    "foo%0A" = quote_plus("foo\n"),
+    "foo%0A" = quote_plus("foo\n"),
+    "foo%3B%26%3D" = quote_plus("foo;&="),
+    ok.
+
+test_unquote() ->
+    "foo bar" = unquote("foo+bar"),
+    "foo bar" = unquote("foo%20bar"),
+    "foo\r\n" = unquote("foo%0D%0A"),
+    ok.
+
+test_urlencode() ->
+    "foo=bar&baz=wibble+%0D%0A&z=1" = urlencode([{foo, "bar"},
+						 {"baz", "wibble \r\n"},
+						 {z, 1}]),
+    ok.
+
+test_parse_qs() ->
+    [{"foo", "bar"}, {"baz", "wibble \r\n"}, {"z", "1"}] =
+	parse_qs("foo=bar&baz=wibble+%0D%0A&z=1"),
+    ok.

Added: incubator/couchdb/vendor/mochiweb/current/src/reloader.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/src/reloader.erl?rev=642953&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/src/reloader.erl (added)
+++ incubator/couchdb/vendor/mochiweb/current/src/reloader.erl Mon Mar 31 03:30:27 2008
@@ -0,0 +1,107 @@
+%% @copyright 2007 Mochi Media, Inc.
+%% @author Matthew Dempsky <matthew@mochimedia.com>
+%%
+%% @doc Erlang module for automatically reloading modified modules
+%% during development.
+
+-module(reloader).
+-author("Matthew Dempsky <matthew@mochimedia.com>").
+
+-include_lib("kernel/include/file.hrl").
+
+-behaviour(gen_server).
+-export([start/0, start_link/0]).
+-export([stop/0]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+
+-record(state, {last, tref}).
+
+%% External API
+
+%% @spec start() -> ServerRet
+%% @doc Start the reloader.
+start() ->
+    gen_server:start({local, ?MODULE}, ?MODULE, [], []).
+
+%% @spec start_link() -> ServerRet
+%% @doc Start the reloader.
+start_link() ->
+    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+%% @spec stop() -> ok
+%% @doc Stop the reloader.
+stop() ->
+    gen_server:call(?MODULE, stop).
+
+%% gen_server callbacks
+
+%% @spec init([]) -> {ok, State}
+%% @doc gen_server init, opens the server in an initial state.
+init([]) ->
+    {ok, TRef} = timer:send_interval(timer:seconds(1), doit),
+    {ok, #state{last = stamp(), tref = TRef}}.
+
+%% @spec handle_call(Args, From, State) -> tuple()
+%% @doc gen_server callback.
+handle_call(stop, _From, State) ->
+    {stop, shutdown, stopped, State};
+handle_call(_Req, _From, State) ->
+    {reply, {error, badrequest}, State}.
+
+%% @spec handle_cast(Cast, State) -> tuple()
+%% @doc gen_server callback.
+handle_cast(_Req, State) ->
+    {noreply, State}.
+
+%% @spec handle_info(Info, State) -> tuple()
+%% @doc gen_server callback.
+handle_info(doit, State) ->
+    Now = stamp(),
+    doit(State#state.last, Now),
+    {noreply, State#state{last = Now}};
+handle_info(_Info, State) ->
+    {noreply, State}.
+
+%% @spec terminate(Reason, State) -> ok
+%% @doc gen_server termination callback.
+terminate(_Reason, State) ->
+    {ok, cancel} = timer:cancel(State#state.tref),
+    ok.
+
+
+%% @spec code_change(_OldVsn, State, _Extra) -> State
+%% @doc gen_server code_change callback (trivial).
+code_change(_Vsn, State, _Extra) ->
+    {ok, State}.
+
+%% Internal API
+
+doit(From, To) ->
+    [case file:read_file_info(Filename) of
+         {ok, FileInfo} when FileInfo#file_info.mtime >= From,
+                             FileInfo#file_info.mtime < To ->
+             io:format("Reloading ~p ...", [Module]),
+             code:purge(Module),
+             case code:load_file(Module) of
+                 {module, Module} ->
+                     io:format(" ok.~n"),
+                     reload;
+                 {error, Reason} ->
+                     io:format(" ~p.~n", [Reason]),
+                     error
+             end;
+         {ok, _} ->
+             unmodified;
+         {error, enoent} ->
+             %% The Erlang compiler deletes existing .beam files if
+             %% recompiling fails.  Maybe it's worth spitting out a
+             %% warning here, but I'd want to limit it to just once.
+             gone;
+         {error, Reason} ->
+             io:format("Error reading ~s's file info: ~p~n",
+                       [Filename, Reason]),
+             error
+     end || {Module, Filename} <- code:all_loaded(), is_list(Filename)].
+
+stamp() ->
+    erlang:localtime().

Added: incubator/couchdb/vendor/mochiweb/current/support/include.mk
URL: http://svn.apache.org/viewvc/incubator/couchdb/vendor/mochiweb/current/support/include.mk?rev=642953&view=auto
==============================================================================
--- incubator/couchdb/vendor/mochiweb/current/support/include.mk (added)
+++ incubator/couchdb/vendor/mochiweb/current/support/include.mk Mon Mar 31 03:30:27 2008
@@ -0,0 +1,46 @@
+## -*- makefile -*-
+
+######################################################################
+## Erlang
+
+ERL := erl
+ERLC := $(ERL)c
+
+INCLUDE_DIRS := ../include $(wildcard ../deps/*/include)
+EBIN_DIRS := $(wildcard ../deps/*/ebin)
+ERLC_FLAGS := -W $(INCLUDE_DIRS:../%=-I ../%) $(EBIN_DIRS:%=-pa %)
+
+ifndef no_debug_info
+  ERLC_FLAGS += +debug_info
+endif
+
+ifdef debug
+  ERLC_FLAGS += -Ddebug
+endif
+
+EBIN_DIR := ../ebin
+DOC_DIR  := ../doc
+EMULATOR := beam
+
+ERL_SOURCES := $(wildcard *.erl)
+ERL_HEADERS := $(wildcard *.hrl) $(wildcard ../include/*.hrl)
+ERL_OBJECTS := $(ERL_SOURCES:%.erl=$(EBIN_DIR)/%.$(EMULATOR))
+ERL_DOCUMENTS := $(ERL_SOURCES:%.erl=$(DOC_DIR)/%.html)
+ERL_OBJECTS_LOCAL := $(ERL_SOURCES:%.erl=./%.$(EMULATOR))
+APP_FILES := $(wildcard *.app)
+EBIN_FILES = $(ERL_OBJECTS) $(ERL_DOCUMENTS) $(APP_FILES:%.app=../ebin/%.app)
+EBIN_FILES_NO_DOCS = $(ERL_OBJECTS) $(APP_FILES:%.app=../ebin/%.app)
+MODULES = $(ERL_SOURCES:%.erl=%)
+
+../ebin/%.app: %.app
+	cp $< $@
+
+$(EBIN_DIR)/%.$(EMULATOR): %.erl
+	$(ERLC) $(ERLC_FLAGS) -o $(EBIN_DIR) $<
+
+./%.$(EMULATOR): %.erl
+	$(ERLC) $(ERLC_FLAGS) -o . $<
+
+$(DOC_DIR)/%.html: %.erl
+	$(ERL) -noshell -run edoc file $< -run init stop
+	mv *.html $(DOC_DIR)



Mime
View raw message