couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dav...@apache.org
Subject [08/49] Remove src/couch
Date Wed, 05 Feb 2014 14:50:30 GMT
http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed98610c/src/couch/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_misc_handlers.erl b/src/couch/src/couch_httpd_misc_handlers.erl
deleted file mode 100644
index 3b2bbeb..0000000
--- a/src/couch/src/couch_httpd_misc_handlers.erl
+++ /dev/null
@@ -1,306 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(couch_httpd_misc_handlers).
-
--export([handle_welcome_req/2,handle_favicon_req/2,handle_utils_dir_req/2,
-    handle_all_dbs_req/1,handle_restart_req/1,
-    handle_uuids_req/1,handle_config_req/1,handle_log_req/1,
-    handle_task_status_req/1, handle_file_req/2]).
-
--export([increment_update_seq_req/2]).
-
-
--include_lib("couch/include/couch_db.hrl").
-
--import(couch_httpd,
-    [send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,
-    start_json_response/2,send_chunk/2,last_chunk/1,end_json_response/1,
-    start_chunked_response/3, send_error/4]).
-
-% httpd global handlers
-
-handle_welcome_req(#httpd{method='GET'}=Req, WelcomeMessage) ->
-    send_json(Req, {[
-        {couchdb, WelcomeMessage},
-        {uuid, couch_server:get_uuid()},
-        {version, list_to_binary(couch_server:get_version())}
-        ] ++ case config:get("vendor") of
-        [] ->
-            [];
-        Properties ->
-            [{vendor, {[{?l2b(K), ?l2b(V)} || {K, V} <- Properties]}}]
-        end
-    });
-handle_welcome_req(Req, _) ->
-    send_method_not_allowed(Req, "GET,HEAD").
-
-handle_favicon_req(#httpd{method='GET'}=Req, DocumentRoot) ->
-    {{Year,Month,Day},Time} = erlang:universaltime(),
-    OneYearFromNow = {{Year+1,Month,Day},Time},
-    CachingHeaders = [
-        %favicon should expire a year from now
-        {"Cache-Control", "public, max-age=31536000"},
-        {"Expires", couch_util:rfc1123_date(OneYearFromNow)}
-    ],
-    couch_httpd:serve_file(Req, "favicon.ico", DocumentRoot, CachingHeaders);
-
-handle_favicon_req(Req, _) ->
-    send_method_not_allowed(Req, "GET,HEAD").
-
-handle_file_req(#httpd{method='GET'}=Req, Document) ->
-    couch_httpd:serve_file(Req, filename:basename(Document), filename:dirname(Document));
-
-handle_file_req(Req, _) ->
-    send_method_not_allowed(Req, "GET,HEAD").
-
-handle_utils_dir_req(#httpd{method='GET'}=Req, DocumentRoot) ->
-    "/" ++ UrlPath = couch_httpd:path(Req),
-    case couch_httpd:partition(UrlPath) of
-    {_ActionKey, "/", RelativePath} ->
-        % GET /_utils/path or GET /_utils/
-        CachingHeaders =
-                [{"Cache-Control", "private, must-revalidate"}],
-        couch_httpd:serve_file(Req, RelativePath, DocumentRoot, CachingHeaders);
-    {_ActionKey, "", _RelativePath} ->
-        % GET /_utils
-        RedirectPath = couch_httpd:path(Req) ++ "/",
-        couch_httpd:send_redirect(Req, RedirectPath)
-    end;
-handle_utils_dir_req(Req, _) ->
-    send_method_not_allowed(Req, "GET,HEAD").
-
-handle_all_dbs_req(#httpd{method='GET'}=Req) ->
-    {ok, DbNames} = couch_server:all_databases(),
-    send_json(Req, DbNames);
-handle_all_dbs_req(Req) ->
-    send_method_not_allowed(Req, "GET,HEAD").
-
-
-handle_task_status_req(#httpd{method='GET'}=Req) ->
-    ok = couch_httpd:verify_is_server_admin(Req),
-    % convert the list of prop lists to a list of json objects
-    send_json(Req, [{Props} || Props <- couch_task_status:all()]);
-handle_task_status_req(Req) ->
-    send_method_not_allowed(Req, "GET,HEAD").
-
-
-handle_restart_req(#httpd{method='GET', path_parts=[_, <<"token">>]}=Req) ->
-    ok = couch_httpd:verify_is_server_admin(Req),
-    Token = case application:get_env(couch, instance_token) of
-        {ok, Tok} ->
-            Tok;
-        _ ->
-            Tok = erlang:phash2(make_ref()),
-            application:set_env(couch, instance_token, Tok),
-            Tok
-    end,
-    send_json(Req, 200, {[{token, Token}]});
-handle_restart_req(#httpd{method='POST'}=Req) ->
-    couch_httpd:validate_ctype(Req, "application/json"),
-    ok = couch_httpd:verify_is_server_admin(Req),
-    Result = send_json(Req, 202, {[{ok, true}]}),
-    couch:restart(),
-    Result;
-handle_restart_req(Req) ->
-    send_method_not_allowed(Req, "POST").
-
-
-handle_uuids_req(#httpd{method='GET'}=Req) ->
-    Count = list_to_integer(couch_httpd:qs_value(Req, "count", "1")),
-    UUIDs = [couch_uuids:new() || _ <- lists:seq(1, Count)],
-    Etag = couch_httpd:make_etag(UUIDs),
-    couch_httpd:etag_respond(Req, Etag, fun() ->
-        CacheBustingHeaders = [
-            {"Date", couch_util:rfc1123_date()},
-            {"Cache-Control", "no-cache"},
-            % Past date, ON PURPOSE!
-            {"Expires", "Fri, 01 Jan 1990 00:00:00 GMT"},
-            {"Pragma", "no-cache"},
-            {"ETag", Etag}
-        ],
-        send_json(Req, 200, CacheBustingHeaders, {[{<<"uuids">>, UUIDs}]})
-    end);
-handle_uuids_req(Req) ->
-    send_method_not_allowed(Req, "GET").
-
-
-% Config request handler
-
-
-% GET /_config/
-% GET /_config
-handle_config_req(#httpd{method='GET', path_parts=[_]}=Req) ->
-    ok = couch_httpd:verify_is_server_admin(Req),
-    Grouped = lists:foldl(fun({{Section, Key}, Value}, Acc) ->
-        case dict:is_key(Section, Acc) of
-        true ->
-            dict:append(Section, {list_to_binary(Key), list_to_binary(Value)}, Acc);
-        false ->
-            dict:store(Section, [{list_to_binary(Key), list_to_binary(Value)}], Acc)
-        end
-    end, dict:new(), config:all()),
-    KVs = dict:fold(fun(Section, Values, Acc) ->
-        [{list_to_binary(Section), {Values}} | Acc]
-    end, [], Grouped),
-    send_json(Req, 200, {KVs});
-% GET /_config/Section
-handle_config_req(#httpd{method='GET', path_parts=[_,Section]}=Req) ->
-    ok = couch_httpd:verify_is_server_admin(Req),
-    KVs = [{list_to_binary(Key), list_to_binary(Value)}
-            || {Key, Value} <- config:get(Section)],
-    send_json(Req, 200, {KVs});
-% GET /_config/Section/Key
-handle_config_req(#httpd{method='GET', path_parts=[_, Section, Key]}=Req) ->
-    ok = couch_httpd:verify_is_server_admin(Req),
-    case config:get(Section, Key, null) of
-    null ->
-        throw({not_found, unknown_config_value});
-    Value ->
-        send_json(Req, 200, list_to_binary(Value))
-    end;
-% POST /_config/_reload - Flushes unpersisted config values from RAM
-handle_config_req(#httpd{method='POST', path_parts=[_, <<"_reload">>]}=Req) ->
-    ok = couch_httpd:verify_is_server_admin(Req),
-    ok = config:reload(),
-    send_json(Req, 200, {[{ok, true}]});
-% PUT or DELETE /_config/Section/Key
-handle_config_req(#httpd{method=Method, path_parts=[_, Section, Key]}=Req)
-      when (Method == 'PUT') or (Method == 'DELETE') ->
-    ok = couch_httpd:verify_is_server_admin(Req),
-    Persist = couch_httpd:header_value(Req, "X-Couch-Persist") /= "false",
-    case config:get(<<"httpd">>, <<"config_whitelist">>, null) of
-        null ->
-            % No whitelist; allow all changes.
-            handle_approved_config_req(Req, Persist);
-        WhitelistValue ->
-            % Provide a failsafe to protect against inadvertently locking
-            % onesself out of the config by supplying a syntactically-incorrect
-            % Erlang term. To intentionally lock down the whitelist, supply a
-            % well-formed list which does not include the whitelist config
-            % variable itself.
-            FallbackWhitelist = [{<<"httpd">>, <<"config_whitelist">>}],
-
-            Whitelist = case couch_util:parse_term(WhitelistValue) of
-                {ok, Value} when is_list(Value) ->
-                    Value;
-                {ok, _NonListValue} ->
-                    FallbackWhitelist;
-                {error, _} ->
-                    [{WhitelistSection, WhitelistKey}] = FallbackWhitelist,
-                    ?LOG_ERROR("Only whitelisting ~s/~s due to error parsing: ~p",
-                               [WhitelistSection, WhitelistKey, WhitelistValue]),
-                    FallbackWhitelist
-            end,
-
-            IsRequestedKeyVal = fun(Element) ->
-                case Element of
-                    {A, B} ->
-                        % For readability, tuples may be used instead of binaries
-                        % in the whitelist.
-                        case {couch_util:to_binary(A), couch_util:to_binary(B)} of
-                            {Section, Key} ->
-                                true;
-                            {Section, <<"*">>} ->
-                                true;
-                            _Else ->
-                                false
-                        end;
-                    _Else ->
-                        false
-                end
-            end,
-
-            case lists:any(IsRequestedKeyVal, Whitelist) of
-                true ->
-                    % Allow modifying this whitelisted variable.
-                    handle_approved_config_req(Req, Persist);
-                _NotWhitelisted ->
-                    % Disallow modifying this non-whitelisted variable.
-                    send_error(Req, 400, <<"modification_not_allowed">>,
-                               ?l2b("This config variable is read-only"))
-            end
-    end;
-handle_config_req(Req) ->
-    send_method_not_allowed(Req, "GET,PUT,POST,DELETE").
-
-% PUT /_config/Section/Key
-% "value"
-handle_approved_config_req(#httpd{method='PUT', path_parts=[_, Section, Key]}=Req, Persist) ->
-    Value = case Section of
-    <<"admins">> ->
-        couch_passwords:hash_admin_password(couch_httpd:json_body(Req));
-    _ ->
-        couch_httpd:json_body(Req)
-    end,
-    OldValue = config:get(Section, Key, ""),
-    case config:set(Section, Key, ?b2l(Value), Persist) of
-    ok ->
-        send_json(Req, 200, list_to_binary(OldValue));
-    Error ->
-        throw(Error)
-    end;
-% DELETE /_config/Section/Key
-handle_approved_config_req(#httpd{method='DELETE',path_parts=[_,Section,Key]}=Req, Persist) ->
-    case config:get(Section, Key, null) of
-    null ->
-        throw({not_found, unknown_config_value});
-    OldValue ->
-        config:delete(Section, Key, Persist),
-        send_json(Req, 200, list_to_binary(OldValue))
-    end.
-
-
-% httpd db handlers
-
-increment_update_seq_req(#httpd{method='POST'}=Req, Db) ->
-    couch_httpd:validate_ctype(Req, "application/json"),
-    {ok, NewSeq} = couch_db:increment_update_seq(Db),
-    send_json(Req, {[{ok, true},
-        {update_seq, NewSeq}
-    ]});
-increment_update_seq_req(Req, _Db) ->
-    send_method_not_allowed(Req, "POST").
-
-% httpd log handlers
-
-handle_log_req(#httpd{method='GET'}=Req) ->
-    ok = couch_httpd:verify_is_server_admin(Req),
-    Bytes = list_to_integer(couch_httpd:qs_value(Req, "bytes", "1000")),
-    Offset = list_to_integer(couch_httpd:qs_value(Req, "offset", "0")),
-    Chunk = couch_log:read(Bytes, Offset),
-    {ok, Resp} = start_chunked_response(Req, 200, [
-        % send a plaintext response
-        {"Content-Type", "text/plain; charset=utf-8"},
-        {"Content-Length", integer_to_list(length(Chunk))}
-    ]),
-    send_chunk(Resp, Chunk),
-    last_chunk(Resp);
-handle_log_req(#httpd{method='POST'}=Req) ->
-    {PostBody} = couch_httpd:json_body_obj(Req),
-    Level = couch_util:get_value(<<"level">>, PostBody),
-    Message = ?b2l(couch_util:get_value(<<"message">>, PostBody)),
-    case Level of
-    <<"debug">> ->
-        ?LOG_DEBUG(Message, []),
-        send_json(Req, 200, {[{ok, true}]});
-    <<"info">> ->
-        ?LOG_INFO(Message, []),
-        send_json(Req, 200, {[{ok, true}]});
-    <<"error">> ->
-        ?LOG_ERROR(Message, []),
-        send_json(Req, 200, {[{ok, true}]});
-    _ ->
-        send_json(Req, 400, {[{error, ?l2b(io_lib:format("Unrecognized log level '~s'", [Level]))}]})
-    end;
-handle_log_req(Req) ->
-    send_method_not_allowed(Req, "GET,POST").

http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed98610c/src/couch/src/couch_httpd_oauth.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_oauth.erl b/src/couch/src/couch_httpd_oauth.erl
deleted file mode 100644
index 8fd4c30..0000000
--- a/src/couch/src/couch_httpd_oauth.erl
+++ /dev/null
@@ -1,387 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License.  You may obtain a copy of
-% the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(couch_httpd_oauth).
-
--include_lib("couch/include/couch_db.hrl").
--include("couch_js_functions.hrl").
-
--export([oauth_authentication_handler/1, handle_oauth_req/1]).
-
--define(OAUTH_DDOC_ID, <<"_design/oauth">>).
--define(OAUTH_VIEW_NAME, <<"oauth_credentials">>).
-
--record(callback_params, {
-    consumer,
-    token,
-    token_secret,
-    url,
-    signature,
-    params,
-    username
-}).
-
-% OAuth auth handler using per-node user db
-oauth_authentication_handler(Req) ->
-    serve_oauth(Req, fun oauth_auth_callback/2, true).
-
-
-oauth_auth_callback(Req, #callback_params{token_secret = undefined}) ->
-    couch_httpd:send_error(
-         Req, 400, <<"invalid_token">>, <<"Invalid OAuth token.">>);
-
-oauth_auth_callback(#httpd{mochi_req = MochiReq} = Req, CbParams) ->
-    Method = atom_to_list(MochiReq:get(method)),
-    #callback_params{
-        consumer = Consumer,
-        token_secret = TokenSecret,
-        url = Url,
-        signature = Sig,
-        params = Params,
-        username = User
-    } = CbParams,
-    case oauth:verify(Sig, Method, Url, Params, Consumer, TokenSecret) of
-    true ->
-        set_user_ctx(Req, User);
-    false ->
-        ?LOG_DEBUG("OAuth handler: signature verification failed for user `~p`~n"
-            "Received signature is `~p`~n"
-            "HTTP method is `~p`~n"
-            "URL is `~p`~n"
-            "Parameters are `~p`~n"
-            "Consumer is `~p`, token secret is `~p`~n"
-            "Expected signature was `~p`~n",
-            [User, Sig, Method, Url, Params, Consumer, TokenSecret,
-                oauth:sign(Method, Url, Params, Consumer, "", TokenSecret)]),
-        Req
-    end.
-
-
-% Look up the consumer key and get the roles to give the consumer
-set_user_ctx(_Req, undefined) ->
-    throw({bad_request, unknown_oauth_token});
-set_user_ctx(Req, Name) ->
-    case couch_auth_cache:get_user_creds(Name) of
-        nil ->
-            ?LOG_DEBUG("OAuth handler: user `~p` credentials not found", [Name]),
-            Req;
-        User ->
-            Roles = couch_util:get_value(<<"roles">>, User, []),
-            Req#httpd{user_ctx=#user_ctx{name=Name, roles=Roles}}
-    end.
-
-% OAuth request_token
-handle_oauth_req(#httpd{path_parts=[_OAuth, <<"request_token">>], method=Method}=Req1) ->
-    serve_oauth(Req1, fun(Req, CbParams) ->
-        #callback_params{
-            consumer = Consumer,
-            token_secret = TokenSecret,
-            url = Url,
-            signature = Sig,
-            params = Params
-        } = CbParams,
-        case oauth:verify(
-            Sig, atom_to_list(Method), Url, Params, Consumer, TokenSecret) of
-        true ->
-            ok(Req, <<"oauth_token=requestkey&oauth_token_secret=requestsecret">>);
-        false ->
-            invalid_signature(Req)
-        end
-    end, false);
-handle_oauth_req(#httpd{path_parts=[_OAuth, <<"authorize">>]}=Req) ->
-    {ok, serve_oauth_authorize(Req)};
-handle_oauth_req(#httpd{path_parts=[_OAuth, <<"access_token">>], method='GET'}=Req1) ->
-    serve_oauth(Req1, fun(Req, CbParams) ->
-        #callback_params{
-            consumer = Consumer,
-            token = Token,
-            url = Url,
-            signature = Sig,
-            params = Params
-        } = CbParams,
-        case Token of
-        "requestkey" ->
-            case oauth:verify(
-                Sig, "GET", Url, Params, Consumer, "requestsecret") of
-            true ->
-                ok(Req,
-                    <<"oauth_token=accesskey&oauth_token_secret=accesssecret">>);
-            false ->
-                invalid_signature(Req)
-            end;
-        _ ->
-            couch_httpd:send_error(
-                Req, 400, <<"invalid_token">>, <<"Invalid OAuth token.">>)
-        end
-    end, false);
-handle_oauth_req(#httpd{path_parts=[_OAuth, <<"access_token">>]}=Req) ->
-    couch_httpd:send_method_not_allowed(Req, "GET").
-
-invalid_signature(Req) ->
-    couch_httpd:send_error(Req, 400, <<"invalid_signature">>, <<"Invalid signature value.">>).
-
-% This needs to be protected i.e. force user to login using HTTP Basic Auth or form-based login.
-serve_oauth_authorize(#httpd{method=Method}=Req1) ->
-    case Method of
-        'GET' ->
-            % Confirm with the User that they want to authenticate the Consumer
-            serve_oauth(Req1, fun(Req, CbParams) ->
-                #callback_params{
-                    consumer = Consumer,
-                    token_secret = TokenSecret,
-                    url = Url,
-                    signature = Sig,
-                    params = Params
-                } = CbParams,
-                case oauth:verify(
-                    Sig, "GET", Url, Params, Consumer, TokenSecret) of
-                true ->
-                    ok(Req, <<"oauth_token=requestkey&",
-                        "oauth_token_secret=requestsecret">>);
-                false ->
-                    invalid_signature(Req)
-                end
-            end, false);
-        'POST' ->
-            % If the User has confirmed, we direct the User back to the Consumer with a verification code
-            serve_oauth(Req1, fun(Req, CbParams) ->
-                #callback_params{
-                    consumer = Consumer,
-                    token_secret = TokenSecret,
-                    url = Url,
-                    signature = Sig,
-                    params = Params
-                } = CbParams,
-                case oauth:verify(
-                    Sig, "POST", Url, Params, Consumer, TokenSecret) of
-                true ->
-                    %redirect(oauth_callback, oauth_token, oauth_verifier),
-                    ok(Req, <<"oauth_token=requestkey&",
-                        "oauth_token_secret=requestsecret">>);
-                false ->
-                    invalid_signature(Req)
-                end
-            end, false);
-        _ ->
-            couch_httpd:send_method_not_allowed(Req1, "GET,POST")
-    end.
-
-serve_oauth(#httpd{mochi_req=MochiReq}=Req, Fun, FailSilently) ->
-    % 1. In the HTTP Authorization header as defined in OAuth HTTP Authorization Scheme.
-    % 2. As the HTTP POST request body with a content-type of application/x-www-form-urlencoded.
-    % 3. Added to the URLs in the query part (as defined by [RFC3986] section 3).
-    AuthHeader = case MochiReq:get_header_value("authorization") of
-        undefined ->
-            "";
-        Else ->
-            [Head | Tail] = re:split(Else, "\\s", [{parts, 2}, {return, list}]),
-            case [string:to_lower(Head) | Tail] of
-                ["oauth", Rest] -> Rest;
-                _ -> ""
-            end
-    end,
-    HeaderParams = oauth:header_params_decode(AuthHeader),
-    %Realm = couch_util:get_value("realm", HeaderParams),
-
-    % get requested path
-    RequestedPath = case MochiReq:get_header_value("x-couchdb-requested-path") of
-        undefined ->
-            case MochiReq:get_header_value("x-couchdb-vhost-path") of
-                undefined ->
-                    MochiReq:get(raw_path);
-                VHostPath ->
-                    VHostPath
-            end;
-        RequestedPath0 ->
-           RequestedPath0
-    end,
-    {_, QueryString, _} = mochiweb_util:urlsplit_path(RequestedPath),
-
-    Params = proplists:delete("realm", HeaderParams) ++ mochiweb_util:parse_qs(QueryString),
-
-    ?LOG_DEBUG("OAuth Params: ~p", [Params]),
-    case couch_util:get_value("oauth_version", Params, "1.0") of
-        "1.0" ->
-            case couch_util:get_value("oauth_consumer_key", Params, undefined) of
-                undefined ->
-                    case FailSilently of
-                        true -> Req;
-                        false -> couch_httpd:send_error(Req, 400, <<"invalid_consumer">>, <<"Invalid consumer.">>)
-                    end;
-                ConsumerKey ->
-                    Url = couch_httpd:absolute_uri(Req, RequestedPath),
-                    case get_callback_params(ConsumerKey, Params, Url) of
-                        {ok, CallbackParams} ->
-                            Fun(Req, CallbackParams);
-                        invalid_consumer_token_pair ->
-                            couch_httpd:send_error(
-                                Req, 400,
-                                <<"invalid_consumer_token_pair">>,
-                                <<"Invalid consumer and token pair.">>);
-                        {error, {Error, Reason}} ->
-                            couch_httpd:send_error(Req, 400, Error, Reason)
-                    end
-            end;
-        _ ->
-            couch_httpd:send_error(Req, 400, <<"invalid_oauth_version">>, <<"Invalid OAuth version.">>)
-    end.
-
-
-get_callback_params(ConsumerKey, Params, Url) ->
-    Token = couch_util:get_value("oauth_token", Params),
-    SigMethod = sig_method(Params),
-    CbParams0 = #callback_params{
-        token = Token,
-        signature = couch_util:get_value("oauth_signature", Params),
-        params = proplists:delete("oauth_signature", Params),
-        url = Url
-    },
-    case oauth_credentials_info(Token, ConsumerKey) of
-    nil ->
-        invalid_consumer_token_pair;
-    {error, _} = Err ->
-        Err;
-    {OauthCreds} ->
-        User = couch_util:get_value(<<"username">>, OauthCreds, []),
-        ConsumerSecret = ?b2l(couch_util:get_value(
-            <<"consumer_secret">>, OauthCreds, <<>>)),
-        TokenSecret = ?b2l(couch_util:get_value(
-            <<"token_secret">>, OauthCreds, <<>>)),
-        case (User =:= []) orelse (ConsumerSecret =:= []) orelse
-            (TokenSecret =:= []) of
-        true ->
-            invalid_consumer_token_pair;
-        false ->
-            CbParams = CbParams0#callback_params{
-                consumer = {ConsumerKey, ConsumerSecret, SigMethod},
-                token_secret = TokenSecret,
-                username = User
-            },
-            ?LOG_DEBUG("Got OAuth credentials, for ConsumerKey `~p` and "
-                "Token `~p`, from the views, User: `~p`, "
-                "ConsumerSecret: `~p`, TokenSecret: `~p`",
-                [ConsumerKey, Token, User, ConsumerSecret, TokenSecret]),
-            {ok, CbParams}
-        end
-    end.
-
-
-sig_method(Params) ->
-    sig_method_1(couch_util:get_value("oauth_signature_method", Params)).
-sig_method_1("PLAINTEXT") ->
-    plaintext;
-% sig_method_1("RSA-SHA1") ->
-%    rsa_sha1;
-sig_method_1("HMAC-SHA1") ->
-    hmac_sha1;
-sig_method_1(_) ->
-    undefined.
-
-
-ok(#httpd{mochi_req=MochiReq}, Body) ->
-    {ok, MochiReq:respond({200, [], Body})}.
-
-
-oauth_credentials_info(Token, ConsumerKey) ->
-    case use_auth_db() of
-    {ok, Db} ->
-        Result = case query_oauth_view(Db, [?l2b(ConsumerKey), ?l2b(Token)]) of
-        [] ->
-            nil;
-        [Creds] ->
-            Creds;
-        [_ | _] ->
-            Reason = iolist_to_binary(
-                io_lib:format("Found multiple OAuth credentials for the pair "
-                    " (consumer_key: `~p`, token: `~p`)", [ConsumerKey, Token])),
-            {error, {<<"oauth_token_consumer_key_pair">>, Reason}}
-        end,
-        couch_db:close(Db),
-        Result;
-    nil ->
-        {
-            case config:get("oauth_consumer_secrets", ConsumerKey) of
-            undefined -> [];
-            ConsumerSecret -> [{<<"consumer_secret">>, ?l2b(ConsumerSecret)}]
-            end
-            ++
-            case config:get("oauth_token_secrets", Token) of
-            undefined -> [];
-            TokenSecret -> [{<<"token_secret">>, ?l2b(TokenSecret)}]
-            end
-            ++
-            case config:get("oauth_token_users", Token) of
-            undefined -> [];
-            User -> [{<<"username">>, ?l2b(User)}]
-            end
-        }
-    end.
-
-
-use_auth_db() ->
-    case config:get("couch_httpd_oauth", "use_users_db", "false") of
-    "false" ->
-        nil;
-    "true" ->
-        AuthDb = open_auth_db(),
-        {ok, _AuthDb2} = ensure_oauth_views_exist(AuthDb)
-    end.
-
-
-open_auth_db() ->
-    DbName = ?l2b(config:get("couch_httpd_auth", "authentication_db")),
-    DbOptions = [{user_ctx, #user_ctx{roles = [<<"_admin">>]}}],
-    {ok, AuthDb} = couch_db:open_int(DbName, DbOptions),
-    AuthDb.
-
-
-ensure_oauth_views_exist(AuthDb) ->
-    case couch_db:open_doc(AuthDb, ?OAUTH_DDOC_ID, []) of
-    {ok, _DDoc} ->
-        {ok, AuthDb};
-    _ ->
-        {ok, DDoc} = get_oauth_ddoc(),
-        {ok, _Rev} = couch_db:update_doc(AuthDb, DDoc, []),
-        {ok, _AuthDb2} = couch_db:reopen(AuthDb)
-    end.
-
-
-get_oauth_ddoc() ->
-    Json = {[
-        {<<"_id">>, ?OAUTH_DDOC_ID},
-        {<<"language">>, <<"javascript">>},
-        {<<"views">>,
-            {[
-                {?OAUTH_VIEW_NAME,
-                    {[
-                        {<<"map">>, ?OAUTH_MAP_FUN}
-                    ]}
-                }
-            ]}
-        }
-    ]},
-    {ok, couch_doc:from_json_obj(Json)}.
-
-
-query_oauth_view(Db, Key) ->
-    ViewOptions = [
-        {start_key, Key},
-        {end_key, Key}
-    ],
-    Callback = fun({row, Row}, Acc) ->
-            {ok, [couch_util:get_value(value, Row) | Acc]};
-        (_, Acc) ->
-            {ok, Acc}
-    end,
-    {ok, Result} = couch_mrview:query_view(
-        Db, ?OAUTH_DDOC_ID, ?OAUTH_VIEW_NAME, ViewOptions, Callback, []),
-    Result.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed98610c/src/couch/src/couch_httpd_proxy.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_proxy.erl b/src/couch/src/couch_httpd_proxy.erl
deleted file mode 100644
index 7e9aed7..0000000
--- a/src/couch/src/couch_httpd_proxy.erl
+++ /dev/null
@@ -1,426 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
--module(couch_httpd_proxy).
-
--export([handle_proxy_req/2]).
-
--include_lib("couch/include/couch_db.hrl").
--include_lib("ibrowse/include/ibrowse.hrl").
-
--define(TIMEOUT, infinity).
--define(PKT_SIZE, 4096).
-
-
-handle_proxy_req(Req, ProxyDest) ->
-    Method = get_method(Req),
-    Url = get_url(Req, ProxyDest),
-    Version = get_version(Req),
-    Headers = get_headers(Req),
-    Body = get_body(Req),
-    Options = [
-        {http_vsn, Version},
-        {headers_as_is, true},
-        {response_format, binary},
-        {stream_to, {self(), once}}
-    ],
-    case ibrowse:send_req(Url, Headers, Method, Body, Options, ?TIMEOUT) of
-        {ibrowse_req_id, ReqId} ->
-            stream_response(Req, ProxyDest, ReqId);
-        {error, Reason} ->
-            throw({error, Reason})
-    end.
-    
-
-get_method(#httpd{mochi_req=MochiReq}) ->
-    case MochiReq:get(method) of
-        Method when is_atom(Method) ->
-            list_to_atom(string:to_lower(atom_to_list(Method)));
-        Method when is_list(Method) ->
-            list_to_atom(string:to_lower(Method));
-        Method when is_binary(Method) ->
-            list_to_atom(string:to_lower(?b2l(Method)))
-    end.
-
-
-get_url(Req, ProxyDest) when is_binary(ProxyDest) ->
-    get_url(Req, ?b2l(ProxyDest));
-get_url(#httpd{mochi_req=MochiReq}=Req, ProxyDest) ->
-    BaseUrl = case mochiweb_util:partition(ProxyDest, "/") of
-        {[], "/", _} -> couch_httpd:absolute_uri(Req, ProxyDest);
-        _ -> ProxyDest
-    end,
-    ProxyPrefix = "/" ++ ?b2l(hd(Req#httpd.path_parts)),
-    RequestedPath = MochiReq:get(raw_path),
-    case mochiweb_util:partition(RequestedPath, ProxyPrefix) of
-        {[], ProxyPrefix, []} ->
-            BaseUrl;
-        {[], ProxyPrefix, [$/ | DestPath]} ->
-            remove_trailing_slash(BaseUrl) ++ "/" ++ DestPath;
-        {[], ProxyPrefix, DestPath} ->
-            remove_trailing_slash(BaseUrl) ++ "/" ++ DestPath;
-        _Else ->
-            throw({invalid_url_path, {ProxyPrefix, RequestedPath}})
-    end.
-
-get_version(#httpd{mochi_req=MochiReq}) ->
-    MochiReq:get(version).
-
-
-get_headers(#httpd{mochi_req=MochiReq}) ->
-    to_ibrowse_headers(mochiweb_headers:to_list(MochiReq:get(headers)), []).
-
-to_ibrowse_headers([], Acc) ->
-    lists:reverse(Acc);
-to_ibrowse_headers([{K, V} | Rest], Acc) when is_atom(K) ->
-    to_ibrowse_headers([{atom_to_list(K), V} | Rest], Acc);
-to_ibrowse_headers([{K, V} | Rest], Acc) when is_list(K) ->
-    case string:to_lower(K) of
-        "content-length" ->
-            to_ibrowse_headers(Rest, [{content_length, V} | Acc]);
-        % This appears to make ibrowse too smart.
-        %"transfer-encoding" ->
-        %    to_ibrowse_headers(Rest, [{transfer_encoding, V} | Acc]);
-        _ ->
-            to_ibrowse_headers(Rest, [{K, V} | Acc])
-    end.
-
-get_body(#httpd{method='GET'}) ->
-    fun() -> eof end;
-get_body(#httpd{method='HEAD'}) ->
-    fun() -> eof end;
-get_body(#httpd{method='DELETE'}) ->
-    fun() -> eof end;
-get_body(#httpd{mochi_req=MochiReq}) ->
-    case MochiReq:get(body_length) of
-        undefined ->
-            <<>>;
-        {unknown_transfer_encoding, Unknown} ->
-            exit({unknown_transfer_encoding, Unknown});
-        chunked ->
-            {fun stream_chunked_body/1, {init, MochiReq, 0}};
-        0 ->
-            <<>>;
-        Length when is_integer(Length) andalso Length > 0 ->
-            {fun stream_length_body/1, {init, MochiReq, Length}};
-        Length ->
-            exit({invalid_body_length, Length})
-    end.
-
-
-remove_trailing_slash(Url) ->
-    rem_slash(lists:reverse(Url)).
-
-rem_slash([]) ->
-    [];
-rem_slash([$\s | RevUrl]) ->
-    rem_slash(RevUrl);
-rem_slash([$\t | RevUrl]) ->
-    rem_slash(RevUrl);
-rem_slash([$\r | RevUrl]) ->
-    rem_slash(RevUrl);
-rem_slash([$\n | RevUrl]) ->
-    rem_slash(RevUrl);
-rem_slash([$/ | RevUrl]) ->
-    rem_slash(RevUrl);
-rem_slash(RevUrl) ->
-    lists:reverse(RevUrl).
-
-
-stream_chunked_body({init, MReq, 0}) ->
-    % First chunk, do expect-continue dance.
-    init_body_stream(MReq),
-    stream_chunked_body({stream, MReq, 0, [], ?PKT_SIZE});
-stream_chunked_body({stream, MReq, 0, Buf, BRem}) ->
-    % Finished a chunk, get next length. If next length
-    % is 0, its time to try and read trailers.
-    {CRem, Data} = read_chunk_length(MReq),
-    case CRem of
-        0 ->
-            BodyData = lists:reverse(Buf, Data),
-            {ok, BodyData, {trailers, MReq, [], ?PKT_SIZE}}; 
-        _ ->
-            stream_chunked_body(
-                {stream, MReq, CRem, [Data | Buf], BRem-size(Data)}
-            )
-    end;
-stream_chunked_body({stream, MReq, CRem, Buf, BRem}) when BRem =< 0 ->
-    % Time to empty our buffers to the upstream socket.
-    BodyData = lists:reverse(Buf),
-    {ok, BodyData, {stream, MReq, CRem, [], ?PKT_SIZE}};
-stream_chunked_body({stream, MReq, CRem, Buf, BRem}) ->
-    % Buffer some more data from the client.
-    Length = lists:min([CRem, BRem]),
-    Socket = MReq:get(socket),
-    NewState = case mochiweb_socket:recv(Socket, Length, ?TIMEOUT) of
-        {ok, Data} when size(Data) == CRem ->
-            case mochiweb_socket:recv(Socket, 2, ?TIMEOUT) of
-                {ok, <<"\r\n">>} ->
-                    {stream, MReq, 0, [<<"\r\n">>, Data | Buf], BRem-Length-2};
-                _ ->
-                    exit(normal)
-            end;
-        {ok, Data} ->
-            {stream, MReq, CRem-Length, [Data | Buf], BRem-Length};
-        _ ->
-            exit(normal)
-    end,
-    stream_chunked_body(NewState);
-stream_chunked_body({trailers, MReq, Buf, BRem}) when BRem =< 0 ->
-    % Empty our buffers and send data upstream.
-    BodyData = lists:reverse(Buf),
-    {ok, BodyData, {trailers, MReq, [], ?PKT_SIZE}};
-stream_chunked_body({trailers, MReq, Buf, BRem}) ->
-    % Read another trailer into the buffer or stop on an
-    % empty line.
-    Socket = MReq:get(socket),
-    mochiweb_socket:setopts(Socket, [{packet, line}]),
-    case mochiweb_socket:recv(Socket, 0, ?TIMEOUT) of
-        {ok, <<"\r\n">>} ->
-            mochiweb_socket:setopts(Socket, [{packet, raw}]),
-            BodyData = lists:reverse(Buf, <<"\r\n">>),
-            {ok, BodyData, eof};
-        {ok, Footer} ->
-            mochiweb_socket:setopts(Socket, [{packet, raw}]),
-            NewState = {trailers, MReq, [Footer | Buf], BRem-size(Footer)},
-            stream_chunked_body(NewState);
-        _ ->
-            exit(normal)
-    end;
-stream_chunked_body(eof) ->
-    % Tell ibrowse we're done sending data.
-    eof.
-
-
-stream_length_body({init, MochiReq, Length}) ->
-    % Do the expect-continue dance
-    init_body_stream(MochiReq),
-    stream_length_body({stream, MochiReq, Length});
-stream_length_body({stream, _MochiReq, 0}) ->
-    % Finished streaming.
-    eof;
-stream_length_body({stream, MochiReq, Length}) ->
-    BufLen = lists:min([Length, ?PKT_SIZE]),
-    case MochiReq:recv(BufLen) of
-        <<>> -> eof;
-        Bin -> {ok, Bin, {stream, MochiReq, Length-BufLen}}
-    end.
-
-
-init_body_stream(MochiReq) ->
-    Expect = case MochiReq:get_header_value("expect") of
-        undefined ->
-            undefined;
-        Value when is_list(Value) ->
-            string:to_lower(Value)
-    end,
-    case Expect of
-        "100-continue" ->
-            MochiReq:start_raw_response({100, gb_trees:empty()});
-        _Else ->
-            ok
-    end.
-
-
-read_chunk_length(MochiReq) ->
-    Socket = MochiReq:get(socket),
-    mochiweb_socket:setopts(Socket, [{packet, line}]),
-    case mochiweb_socket:recv(Socket, 0, ?TIMEOUT) of
-        {ok, Header} ->
-            mochiweb_socket:setopts(Socket, [{packet, raw}]),
-            Splitter = fun(C) ->
-                C =/= $\r andalso C =/= $\n andalso C =/= $\s
-            end,
-            {Hex, _Rest} = lists:splitwith(Splitter, ?b2l(Header)),
-            {mochihex:to_int(Hex), Header};
-        _ ->
-            exit(normal)
-    end.
-
-
-stream_response(Req, ProxyDest, ReqId) ->
-    receive
-        {ibrowse_async_headers, ReqId, "100", _} ->
-            % ibrowse doesn't handle 100 Continue responses which
-            % means we have to discard them so the proxy client
-            % doesn't get confused.
-            ibrowse:stream_next(ReqId),
-            stream_response(Req, ProxyDest, ReqId);
-        {ibrowse_async_headers, ReqId, Status, Headers} ->
-            {Source, Dest} = get_urls(Req, ProxyDest),
-            FixedHeaders = fix_headers(Source, Dest, Headers, []),
-            case body_length(FixedHeaders) of
-                chunked ->
-                    {ok, Resp} = couch_httpd:start_chunked_response(
-                        Req, list_to_integer(Status), FixedHeaders
-                    ),
-                    ibrowse:stream_next(ReqId),
-                    stream_chunked_response(Req, ReqId, Resp),
-                    {ok, Resp};
-                Length when is_integer(Length) ->
-                    {ok, Resp} = couch_httpd:start_response_length(
-                        Req, list_to_integer(Status), FixedHeaders, Length
-                    ),
-                    ibrowse:stream_next(ReqId),
-                    stream_length_response(Req, ReqId, Resp),
-                    {ok, Resp};
-                _ ->
-                    {ok, Resp} = couch_httpd:start_response(
-                        Req, list_to_integer(Status), FixedHeaders
-                    ),
-                    ibrowse:stream_next(ReqId),
-                    stream_length_response(Req, ReqId, Resp),
-                    % XXX: MochiWeb apparently doesn't look at the
-                    % response to see if it must force close the
-                    % connection. So we help it out here.
-                    erlang:put(mochiweb_request_force_close, true),
-                    {ok, Resp}
-            end
-    end.
-
-
-stream_chunked_response(Req, ReqId, Resp) ->
-    receive
-        {ibrowse_async_response, ReqId, {error, Reason}} ->
-            throw({error, Reason});
-        {ibrowse_async_response, ReqId, Chunk} ->
-            couch_httpd:send_chunk(Resp, Chunk),
-            ibrowse:stream_next(ReqId),
-            stream_chunked_response(Req, ReqId, Resp);
-        {ibrowse_async_response_end, ReqId} ->
-            couch_httpd:last_chunk(Resp)
-    end.
-
-
-stream_length_response(Req, ReqId, Resp) ->
-    receive
-        {ibrowse_async_response, ReqId, {error, Reason}} ->
-            throw({error, Reason});
-        {ibrowse_async_response, ReqId, Chunk} ->
-            couch_httpd:send(Resp, Chunk),
-            ibrowse:stream_next(ReqId),
-            stream_length_response(Req, ReqId, Resp);
-        {ibrowse_async_response_end, ReqId} ->
-            ok
-    end.
-
-
-get_urls(Req, ProxyDest) ->
-    SourceUrl = couch_httpd:absolute_uri(Req, "/" ++ hd(Req#httpd.path_parts)),
-    Source = parse_url(?b2l(iolist_to_binary(SourceUrl))),
-    case (catch parse_url(ProxyDest)) of
-        Dest when is_record(Dest, url) ->
-            {Source, Dest};
-        _ ->
-            DestUrl = couch_httpd:absolute_uri(Req, ProxyDest),
-            {Source, parse_url(DestUrl)}
-    end.
-
-
-fix_headers(_, _, [], Acc) ->
-    lists:reverse(Acc);
-fix_headers(Source, Dest, [{K, V} | Rest], Acc) ->
-    Fixed = case string:to_lower(K) of
-        "location" -> rewrite_location(Source, Dest, V);
-        "content-location" -> rewrite_location(Source, Dest, V);
-        "uri" -> rewrite_location(Source, Dest, V);
-        "destination" -> rewrite_location(Source, Dest, V);
-        "set-cookie" -> rewrite_cookie(Source, Dest, V);
-        _ -> V
-    end,
-    fix_headers(Source, Dest, Rest, [{K, Fixed} | Acc]).
-
-
-rewrite_location(Source, #url{host=Host, port=Port, protocol=Proto}, Url) ->
-    case (catch parse_url(Url)) of
-        #url{host=Host, port=Port, protocol=Proto} = Location ->
-            DestLoc = #url{
-                protocol=Source#url.protocol,
-                host=Source#url.host,
-                port=Source#url.port,
-                path=join_url_path(Source#url.path, Location#url.path)
-            },
-            url_to_url(DestLoc);
-        #url{} ->
-            Url;
-        _ ->
-            url_to_url(Source#url{path=join_url_path(Source#url.path, Url)})
-    end.
-
-
-rewrite_cookie(_Source, _Dest, Cookie) ->
-    Cookie.
-
-
-parse_url(Url) when is_binary(Url) ->
-    ibrowse_lib:parse_url(?b2l(Url));
-parse_url(Url) when is_list(Url) ->
-    ibrowse_lib:parse_url(?b2l(iolist_to_binary(Url))).
-
-
-join_url_path(Src, Dst) ->
-    Src2 = case lists:reverse(Src) of
-        "/" ++ RestSrc -> lists:reverse(RestSrc);
-        _ -> Src
-    end,
-    Dst2 = case Dst of
-        "/" ++ RestDst -> RestDst;
-        _ -> Dst
-    end,
-    Src2 ++ "/" ++ Dst2.
-
-
-url_to_url(#url{host=Host, port=Port, path=Path, protocol=Proto} = Url) ->
-    LPort = case {Proto, Port} of
-        {http, 80} -> "";
-        {https, 443} -> "";
-        _ -> ":" ++ integer_to_list(Port)
-    end,
-    LPath = case Path of
-        "/" ++ _RestPath -> Path;
-        _ -> "/" ++ Path
-    end,
-    HostPart = case Url#url.host_type of
-        ipv6_address ->
-            "[" ++ Host ++ "]";
-        _ ->
-            Host
-    end,
-    atom_to_list(Proto) ++ "://" ++ HostPart ++ LPort ++ LPath.
-
-
-body_length(Headers) ->
-    case is_chunked(Headers) of
-        true -> chunked;
-        _ -> content_length(Headers)
-    end.
-
-
-is_chunked([]) ->
-    false;
-is_chunked([{K, V} | Rest]) ->
-    case string:to_lower(K) of
-        "transfer-encoding" ->
-            string:to_lower(V) == "chunked";
-        _ ->
-            is_chunked(Rest)
-    end.
-
-content_length([]) ->
-    undefined;
-content_length([{K, V} | Rest]) ->
-    case string:to_lower(K) of
-        "content-length" ->
-            list_to_integer(V);
-        _ ->
-            content_length(Rest)
-    end.
-

http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed98610c/src/couch/src/couch_httpd_rewrite.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_rewrite.erl b/src/couch/src/couch_httpd_rewrite.erl
deleted file mode 100644
index abd6af5..0000000
--- a/src/couch/src/couch_httpd_rewrite.erl
+++ /dev/null
@@ -1,483 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-%
-% bind_path is based on bind method from Webmachine
-
-
-%% @doc Module for URL rewriting by pattern matching.
-
--module(couch_httpd_rewrite).
--export([handle_rewrite_req/3]).
--include_lib("couch/include/couch_db.hrl").
-
--define(SEPARATOR, $\/).
--define(MATCH_ALL, {bind, <<"*">>}).
-
-
-%% doc The http rewrite handler. All rewriting is done from
-%% /dbname/_design/ddocname/_rewrite by default.
-%%
-%% each rules should be in rewrites member of the design doc.
-%% Ex of a complete rule :
-%%
-%%  {
-%%      ....
-%%      "rewrites": [
-%%      {
-%%          "from": "",
-%%          "to": "index.html",
-%%          "method": "GET",
-%%          "query": {}
-%%      }
-%%      ]
-%%  }
-%%
-%%  from: is the path rule used to bind current uri to the rule. It
-%% use pattern matching for that.
-%%
-%%  to: rule to rewrite an url. It can contain variables depending on binding
-%% variables discovered during pattern matching and query args (url args and from
-%% the query member.)
-%%
-%%  method: method to bind the request method to the rule. by default "*"
-%%  query: query args you want to define they can contain dynamic variable
-%% by binding the key to the bindings
-%%
-%%
-%% to and from are path with  patterns. pattern can be string starting with ":" or
-%% "*". ex:
-%% /somepath/:var/*
-%%
-%% This path is converted in erlang list by splitting "/". Each var are
-%% converted in atom. "*" is converted to '*' atom. The pattern matching is done
-%% by splitting "/" in request url in a list of token. A string pattern will
-%% match equal token. The star atom ('*' in single quotes) will match any number
-%% of tokens, but may only be present as the last pathtern in a pathspec. If all
-%% tokens are matched and all pathterms are used, then the pathspec matches. It works
-%% like webmachine. Each identified token will be reused in to rule and in query
-%%
-%% The pattern matching is done by first matching the request method to a rule. by
-%% default all methods match a rule. (method is equal to "*" by default). Then
-%% It will try to match the path to one rule. If no rule match, then a 404 error
-%% is displayed.
-%%
-%% Once a rule is found we rewrite the request url using the "to" and
-%% "query" members. The identified token are matched to the rule and
-%% will replace var. if '*' is found in the rule it will contain the remaining
-%% part if it exists.
-%%
-%% Examples:
-%%
-%% Dispatch rule            URL             TO                  Tokens
-%%
-%% {"from": "/a/b",         /a/b?k=v        /some/b?k=v         var =:= b
-%% "to": "/some/"}                                              k = v
-%%
-%% {"from": "/a/b",         /a/b            /some/b?var=b       var =:= b
-%% "to": "/some/:var"}
-%%
-%% {"from": "/a",           /a              /some
-%% "to": "/some/*"}
-%%
-%% {"from": "/a/*",         /a/b/c          /some/b/c
-%% "to": "/some/*"}
-%%
-%% {"from": "/a",           /a              /some
-%% "to": "/some/*"}
-%%
-%% {"from": "/a/:foo/*",    /a/b/c          /some/b/c?foo=b     foo =:= b
-%% "to": "/some/:foo/*"}
-%%
-%% {"from": "/a/:foo",     /a/b             /some/?k=b&foo=b    foo =:= b
-%% "to": "/some",
-%%  "query": {
-%%      "k": ":foo"
-%%  }}
-%%
-%% {"from": "/a",           /a?foo=b        /some/b             foo =:= b
-%% "to": "/some/:foo",
-%%  }}
-
-
-
-handle_rewrite_req(#httpd{
-        path_parts=[DbName, <<"_design">>, DesignName, _Rewrite|PathParts],
-        method=Method,
-        mochi_req=MochiReq}=Req, _Db, DDoc) ->
-
-    % we are in a design handler
-    DesignId = <<"_design/", DesignName/binary>>,
-    Prefix = <<"/", (?l2b(couch_util:url_encode(DbName)))/binary, "/", DesignId/binary>>,
-    QueryList = lists:map(fun decode_query_value/1, couch_httpd:qs(Req)),
-
-    MaxRewritesList = config:get("httpd", "rewrite_limit", "100"),
-    MaxRewrites = list_to_integer(MaxRewritesList),
-    case get(couch_rewrite_count) of
-        undefined ->
-            put(couch_rewrite_count, 1);
-        NumRewrites when NumRewrites < MaxRewrites ->
-            put(couch_rewrite_count, NumRewrites + 1);
-        _ ->
-            throw({bad_request, <<"Exceeded rewrite recursion limit">>})
-    end,
-
-    #doc{body={Props}} = DDoc,
-
-    % get rules from ddoc
-    case couch_util:get_value(<<"rewrites">>, Props) of
-        undefined ->
-            couch_httpd:send_error(Req, 404, <<"rewrite_error">>,
-                <<"Invalid path.">>);
-        Bin when is_binary(Bin) ->
-            couch_httpd:send_error(Req, 400, <<"rewrite_error">>,
-                <<"Rewrite rules are a String. They must be a JSON Array.">>);
-        Rules ->
-            % create dispatch list from rules
-            DispatchList =  [make_rule(Rule) || {Rule} <- Rules],
-            Method1 = couch_util:to_binary(Method),
-
-            %% get raw path by matching url to a rule.
-            RawPath = case try_bind_path(DispatchList, Method1, 
-                    PathParts, QueryList) of
-                no_dispatch_path ->
-                    throw(not_found);
-                {NewPathParts, Bindings} ->
-                    Parts = [quote_plus(X) || X <- NewPathParts],
-
-                    % build new path, reencode query args, eventually convert
-                    % them to json
-                    Bindings1 = maybe_encode_bindings(Bindings),
-                    Path = binary_to_list(
-                        iolist_to_binary([
-                                string:join(Parts, [?SEPARATOR]),
-                                [["?", mochiweb_util:urlencode(Bindings1)] 
-                                    || Bindings1 =/= [] ]
-                            ])),
-                    
-                    % if path is relative detect it and rewrite path
-                    case mochiweb_util:safe_relative_path(Path) of
-                        undefined ->
-                            ?b2l(Prefix) ++ "/" ++ Path;
-                        P1 ->
-                            ?b2l(Prefix) ++ "/" ++ P1
-                    end
-
-                end,
-
-            % normalize final path (fix levels "." and "..")
-            RawPath1 = ?b2l(iolist_to_binary(normalize_path(RawPath))),
-
-            % In order to do OAuth correctly, we have to save the
-            % requested path. We use default so chained rewriting
-            % wont replace the original header.
-            Headers = mochiweb_headers:default("x-couchdb-requested-path",
-                                             MochiReq:get(raw_path),
-                                             MochiReq:get(headers)),
-
-            ?LOG_DEBUG("rewrite to ~p ~n", [RawPath1]),
-
-            % build a new mochiweb request
-            MochiReq1 = mochiweb_request:new(MochiReq:get(socket),
-                                             MochiReq:get(method),
-                                             RawPath1,
-                                             MochiReq:get(version),
-                                             Headers),
-
-            % cleanup, It force mochiweb to reparse raw uri.
-            MochiReq1:cleanup(),
-
-            #httpd{
-                db_url_handlers = DbUrlHandlers,
-                design_url_handlers = DesignUrlHandlers,
-                default_fun = DefaultFun,
-                url_handlers = UrlHandlers,
-                user_ctx = UserCtx
-            } = Req,
-            erlang:put(pre_rewrite_user_ctx, UserCtx),
-            couch_httpd:handle_request_int(MochiReq1, DefaultFun,
-                    UrlHandlers, DbUrlHandlers, DesignUrlHandlers)
-        end.
-
-quote_plus({bind, X}) ->
-    mochiweb_util:quote_plus(X);
-quote_plus(X) ->
-    mochiweb_util:quote_plus(X).
-
-%% @doc Try to find a rule matching current url. If none is found
-%% 404 error not_found is raised
-try_bind_path([], _Method, _PathParts, _QueryList) ->
-    no_dispatch_path;
-try_bind_path([Dispatch|Rest], Method, PathParts, QueryList) ->
-    [{PathParts1, Method1}, RedirectPath, QueryArgs, Formats] = Dispatch,
-    case bind_method(Method1, Method) of
-        true ->
-            case bind_path(PathParts1, PathParts, []) of
-                {ok, Remaining, Bindings} ->
-                    Bindings1 = Bindings ++ QueryList,
-                    % we parse query args from the rule and fill
-                    % it eventually with bindings vars
-                    QueryArgs1 = make_query_list(QueryArgs, Bindings1,
-                        Formats, []),
-                    % remove params in QueryLists1 that are already in
-                    % QueryArgs1
-                    Bindings2 = lists:foldl(fun({K, V}, Acc) ->
-                        K1 = to_binding(K),
-                        KV = case couch_util:get_value(K1, QueryArgs1) of
-                            undefined -> [{K1, V}];
-                            _V1 -> []
-                        end,
-                        Acc ++ KV
-                    end, [], Bindings1),
-
-                    FinalBindings = Bindings2 ++ QueryArgs1,
-                    NewPathParts = make_new_path(RedirectPath, FinalBindings,
-                                    Remaining, []),
-                    {NewPathParts, FinalBindings};
-                fail ->
-                    try_bind_path(Rest, Method, PathParts, QueryList)
-            end;
-        false ->
-            try_bind_path(Rest, Method, PathParts, QueryList)
-    end.
-
-%% rewriting dynamically the quey list given as query member in
-%% rewrites. Each value is replaced by one binding or an argument
-%% passed in url.
-make_query_list([], _Bindings, _Formats, Acc) ->
-    Acc;
-make_query_list([{Key, {Value}}|Rest], Bindings, Formats, Acc) ->
-    Value1 = {Value},
-    make_query_list(Rest, Bindings, Formats, [{to_binding(Key), Value1}|Acc]);
-make_query_list([{Key, Value}|Rest], Bindings, Formats, Acc) when is_binary(Value) ->
-    Value1 = replace_var(Value, Bindings, Formats),
-    make_query_list(Rest, Bindings, Formats, [{to_binding(Key), Value1}|Acc]);
-make_query_list([{Key, Value}|Rest], Bindings, Formats, Acc) when is_list(Value) ->
-    Value1 = replace_var(Value, Bindings, Formats),
-    make_query_list(Rest, Bindings, Formats, [{to_binding(Key), Value1}|Acc]);
-make_query_list([{Key, Value}|Rest], Bindings, Formats, Acc) ->
-    make_query_list(Rest, Bindings, Formats, [{to_binding(Key), Value}|Acc]).
-
-replace_var(<<"*">>=Value, Bindings, Formats) ->
-    get_var(Value, Bindings, Value, Formats);
-replace_var(<<":", Var/binary>> = Value, Bindings, Formats) ->
-    get_var(Var, Bindings, Value, Formats);
-replace_var(Value, _Bindings, _Formats) when is_binary(Value) ->
-    Value;
-replace_var(Value, Bindings, Formats) when is_list(Value) ->
-    lists:reverse(lists:foldl(fun
-                (<<":", Var/binary>>=Value1, Acc) ->
-                    [get_var(Var, Bindings, Value1, Formats)|Acc];
-                (Value1, Acc) ->
-                    [Value1|Acc]
-            end, [], Value));
-replace_var(Value, _Bindings, _Formats) ->
-    Value.
-                    
-maybe_json(Key, Value) ->
-    case lists:member(Key, [<<"key">>, <<"startkey">>, <<"start_key">>,
-                <<"endkey">>, <<"end_key">>, <<"keys">>]) of
-        true ->
-            ?JSON_ENCODE(Value);
-        false ->
-            Value
-    end.
-
-get_var(VarName, Props, Default, Formats) ->
-    VarName1 = to_binding(VarName),
-    Val = couch_util:get_value(VarName1, Props, Default),
-    maybe_format(VarName, Val, Formats).
-
-maybe_format(VarName, Value, Formats) ->
-    case couch_util:get_value(VarName, Formats) of
-        undefined ->
-             Value;
-        Format ->
-            format(Format, Value)
-    end.
-
-format(<<"int">>, Value) when is_integer(Value) ->
-    Value;
-format(<<"int">>, Value) when is_binary(Value) ->
-    format(<<"int">>, ?b2l(Value));
-format(<<"int">>, Value) when is_list(Value) ->
-    case (catch list_to_integer(Value)) of
-        IntVal when is_integer(IntVal) ->
-            IntVal;
-        _ ->
-            Value
-    end;
-format(<<"bool">>, Value) when is_binary(Value) ->
-    format(<<"bool">>, ?b2l(Value));
-format(<<"bool">>, Value) when is_list(Value) ->
-    case string:to_lower(Value) of
-        "true" -> true;
-        "false" -> false;
-        _ -> Value
-    end;
-format(_Format, Value) ->
-   Value. 
-
-%% doc: build new patch from bindings. bindings are query args
-%% (+ dynamic query rewritten if needed) and bindings found in
-%% bind_path step.
-make_new_path([], _Bindings, _Remaining, Acc) ->
-    lists:reverse(Acc);
-make_new_path([?MATCH_ALL], _Bindings, Remaining, Acc) ->
-    Acc1 = lists:reverse(Acc) ++ Remaining,
-    Acc1;
-make_new_path([?MATCH_ALL|_Rest], _Bindings, Remaining, Acc) ->
-    Acc1 = lists:reverse(Acc) ++ Remaining,
-    Acc1;
-make_new_path([{bind, P}|Rest], Bindings, Remaining, Acc) ->
-    P2 = case couch_util:get_value({bind, P}, Bindings) of
-        undefined -> << "undefined">>;
-        P1 -> 
-            iolist_to_binary(P1)
-    end,
-    make_new_path(Rest, Bindings, Remaining, [P2|Acc]);
-make_new_path([P|Rest], Bindings, Remaining, Acc) ->
-    make_new_path(Rest, Bindings, Remaining, [P|Acc]).
-
-
-%% @doc If method of the query fith the rule method. If the
-%% method rule is '*', which is the default, all
-%% request method will bind. It allows us to make rules
-%% depending on HTTP method.
-bind_method(?MATCH_ALL, _Method ) ->
-    true;
-bind_method({bind, Method}, Method) ->
-    true;
-bind_method(_, _) ->
-    false.
-
-
-%% @doc bind path. Using the rule from we try to bind variables given
-%% to the current url by pattern matching
-bind_path([], [], Bindings) ->
-    {ok, [], Bindings};
-bind_path([?MATCH_ALL], [Match|_RestMatch]=Rest, Bindings) ->
-    {ok, Rest, [{?MATCH_ALL, Match}|Bindings]};
-bind_path(_, [], _) ->
-    fail;
-bind_path([{bind, Token}|RestToken],[Match|RestMatch],Bindings) ->
-    bind_path(RestToken, RestMatch, [{{bind, Token}, Match}|Bindings]);
-bind_path([Token|RestToken], [Token|RestMatch], Bindings) ->
-    bind_path(RestToken, RestMatch, Bindings);
-bind_path(_, _, _) ->
-    fail.
-
-
-%% normalize path.
-normalize_path(Path)  ->
-    "/" ++ string:join(normalize_path1(string:tokens(Path,
-                "/"), []), [?SEPARATOR]).
-
-
-normalize_path1([], Acc) ->
-    lists:reverse(Acc);
-normalize_path1([".."|Rest], Acc) ->
-    Acc1 = case Acc of
-        [] -> [".."|Acc];
-        [T|_] when T =:= ".." -> [".."|Acc];
-        [_|R] -> R
-    end,
-    normalize_path1(Rest, Acc1);
-normalize_path1(["."|Rest], Acc) ->
-    normalize_path1(Rest, Acc);
-normalize_path1([Path|Rest], Acc) ->
-    normalize_path1(Rest, [Path|Acc]).
-
-
-%% @doc transform json rule in erlang for pattern matching
-make_rule(Rule) ->
-    Method = case couch_util:get_value(<<"method">>, Rule) of
-        undefined -> ?MATCH_ALL;
-        M -> to_binding(M)
-    end,
-    QueryArgs = case couch_util:get_value(<<"query">>, Rule) of
-        undefined -> [];
-        {Args} -> Args
-        end,
-    FromParts  = case couch_util:get_value(<<"from">>, Rule) of
-        undefined -> [?MATCH_ALL];
-        From ->
-            parse_path(From)
-        end,
-    ToParts  = case couch_util:get_value(<<"to">>, Rule) of
-        undefined ->
-            throw({error, invalid_rewrite_target});
-        To ->
-            parse_path(To)
-        end,
-    Formats = case couch_util:get_value(<<"formats">>, Rule) of
-        undefined -> [];
-        {Fmts} -> Fmts
-    end,
-    [{FromParts, Method}, ToParts, QueryArgs, Formats].
-
-parse_path(Path) ->
-    {ok, SlashRE} = re:compile(<<"\\/">>),
-    path_to_list(re:split(Path, SlashRE), [], 0).
-
-%% @doc convert a path rule (from or to) to an erlang list
-%% * and path variable starting by ":" are converted
-%% in erlang atom.
-path_to_list([], Acc, _DotDotCount) ->
-    lists:reverse(Acc);
-path_to_list([<<>>|R], Acc, DotDotCount) ->
-    path_to_list(R, Acc, DotDotCount);
-path_to_list([<<"*">>|R], Acc, DotDotCount) ->
-    path_to_list(R, [?MATCH_ALL|Acc], DotDotCount);
-path_to_list([<<"..">>|R], Acc, DotDotCount) when DotDotCount == 2 ->
-    case config:get("httpd", "secure_rewrites", "true") of
-    "false" ->
-        path_to_list(R, [<<"..">>|Acc], DotDotCount+1);
-    _Else ->
-        ?LOG_INFO("insecure_rewrite_rule ~p blocked", [lists:reverse(Acc) ++ [<<"..">>] ++ R]),
-        throw({insecure_rewrite_rule, "too many ../.. segments"})
-    end;
-path_to_list([<<"..">>|R], Acc, DotDotCount) ->
-    path_to_list(R, [<<"..">>|Acc], DotDotCount+1);
-path_to_list([P|R], Acc, DotDotCount) ->
-    P1 = case P of
-        <<":", Var/binary>> ->
-            to_binding(Var);
-        _ -> P
-    end,
-    path_to_list(R, [P1|Acc], DotDotCount).
-
-maybe_encode_bindings([]) ->
-    [];
-maybe_encode_bindings(Props) -> 
-    lists:foldl(fun 
-            ({{bind, <<"*">>}, _V}, Acc) ->
-                Acc;
-            ({{bind, K}, V}, Acc) ->
-                V1 = iolist_to_binary(maybe_json(K, V)),
-                [{K, V1}|Acc]
-        end, [], Props).
-                
-decode_query_value({K,V}) ->
-    case lists:member(K, ["key", "startkey", "start_key",
-                "endkey", "end_key", "keys"]) of
-        true ->
-            {to_binding(K), ?JSON_DECODE(V)};
-        false ->
-            {to_binding(K), ?l2b(V)}
-    end.
-
-to_binding({bind, V}) ->
-    {bind, V};
-to_binding(V) when is_list(V) ->
-    to_binding(?l2b(V));
-to_binding(V) ->
-    {bind, V}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed98610c/src/couch/src/couch_httpd_stats_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_stats_handlers.erl b/src/couch/src/couch_httpd_stats_handlers.erl
deleted file mode 100644
index b858830..0000000
--- a/src/couch/src/couch_httpd_stats_handlers.erl
+++ /dev/null
@@ -1,56 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(couch_httpd_stats_handlers).
--include_lib("couch/include/couch_db.hrl").
-
--export([handle_stats_req/1]).
--import(couch_httpd, [
-    send_json/2, send_json/3, send_json/4, send_method_not_allowed/2,
-    start_json_response/2, send_chunk/2, end_json_response/1,
-    start_chunked_response/3, send_error/4
-]).
-
-handle_stats_req(#httpd{method='GET', path_parts=[_]}=Req) ->
-    flush(Req),
-    send_json(Req, couch_stats_aggregator:all(range(Req)));
-
-handle_stats_req(#httpd{method='GET', path_parts=[_, _Mod]}) ->
-    throw({bad_request, <<"Stat names must have exactly to parts.">>});
-
-handle_stats_req(#httpd{method='GET', path_parts=[_, Mod, Key]}=Req) ->
-    flush(Req),
-    Stats = couch_stats_aggregator:get_json({list_to_atom(binary_to_list(Mod)),
-        list_to_atom(binary_to_list(Key))}, range(Req)),
-    send_json(Req, {[{Mod, {[{Key, Stats}]}}]});
-
-handle_stats_req(#httpd{method='GET', path_parts=[_, _Mod, _Key | _Extra]}) ->
-    throw({bad_request, <<"Stat names must have exactly two parts.">>});
-
-handle_stats_req(Req) ->
-    send_method_not_allowed(Req, "GET").
-
-range(Req) ->
-    case couch_util:get_value("range", couch_httpd:qs(Req)) of
-        undefined ->
-            0;
-        Value ->
-            list_to_integer(Value)
-    end.
-
-flush(Req) ->
-    case couch_util:get_value("flush", couch_httpd:qs(Req)) of
-        "true" ->
-            couch_stats_aggregator:collect_sample();
-        _Else ->
-            ok
-    end.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed98610c/src/couch/src/couch_httpd_vhost.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_httpd_vhost.erl b/src/couch/src/couch_httpd_vhost.erl
deleted file mode 100644
index 29fddfe..0000000
--- a/src/couch/src/couch_httpd_vhost.erl
+++ /dev/null
@@ -1,397 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(couch_httpd_vhost).
--behaviour(gen_server).
--behaviour(config_listener).
-
--export([start_link/0, reload/0, get_state/0, dispatch_host/1]).
--export([urlsplit_netloc/2, redirect_to_vhost/2]).
--export([host/1, split_host_port/1]).
-
--export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-
-% config_listener api
--export([handle_config_change/5]).
-
--include_lib("couch/include/couch_db.hrl").
-
--define(SEPARATOR, $\/).
--define(MATCH_ALL, {bind, '*'}).
-
--record(vhosts_state, {
-        vhosts,
-        vhost_globals,
-        vhosts_fun}).
-
-%% doc the vhost manager.
-%% This gen_server keep state of vhosts added to the ini and try to
-%% match the Host header (or forwarded) against rules built against
-%% vhost list.
-%%
-%% Declaration of vhosts take place in the configuration file :
-%%
-%% [vhosts]
-%% example.com = /example
-%% *.example.com = /example
-%%
-%% The first line will rewrite the rquest to display the content of the
-%% example database. This rule works only if the Host header is
-%% 'example.com' and won't work for CNAMEs. Second rule on the other hand
-%% match all CNAMES to example db. So www.example.com or db.example.com
-%% will work.
-%%
-%% The wildcard ('*') should always be the last in the cnames:
-%%
-%%      "*.db.example.com = /"  will match all cname on top of db
-%% examples to the root of the machine.
-%%
-%%
-%% Rewriting Hosts to path
-%% -----------------------
-%%
-%% Like in the _rewrite handler you could match some variable and use
-%them to create the target path. Some examples:
-%%
-%%    [vhosts]
-%%    *.example.com = /*
-%%    :dbname.example.com = /:dbname
-%%    :ddocname.:dbname.example.com = /:dbname/_design/:ddocname/_rewrite
-%%
-%% First rule pass wildcard as dbname, second do the same but use a
-%% variable name and the third one allows you to use any app with
-%% @ddocname in any db with @dbname .
-%%
-%% You could also change the default function to handle request by
-%% changing the setting `redirect_vhost_handler` in `httpd` section of
-%% the Ini:
-%%
-%%    [httpd]
-%%    redirect_vhost_handler = {Module, Fun}
-%%
-%% The function take 2 args : the mochiweb request object and the target
-%%% path.
-
-start_link() ->
-    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
-
-%% @doc reload vhosts rules
-reload() ->
-    gen_server:call(?MODULE, reload).
-
-get_state() ->
-    gen_server:call(?MODULE, get_state).
-
-%% @doc Try to find a rule matching current Host heade. some rule is
-%% found it rewrite the Mochiweb Request else it return current Request.
-dispatch_host(MochiReq) ->
-    #vhosts_state{
-        vhost_globals = VHostGlobals,
-        vhosts = VHosts,
-        vhosts_fun=Fun} = get_state(),
-
-    {"/" ++ VPath, Query, Fragment} = mochiweb_util:urlsplit_path(MochiReq:get(raw_path)),
-    VPathParts =  string:tokens(VPath, "/"),
-
-    VHost = host(MochiReq),
-    {VHostParts, VhostPort} = split_host_port(VHost),
-    FinalMochiReq = case try_bind_vhost(VHosts, lists:reverse(VHostParts),
-            VhostPort, VPathParts) of
-        no_vhost_matched -> MochiReq;
-        {VhostTarget, NewPath} ->
-            case vhost_global(VHostGlobals, MochiReq) of
-                true ->
-                    MochiReq;
-                _Else ->
-                    NewPath1 = mochiweb_util:urlunsplit_path({NewPath, Query,
-                                          Fragment}),
-                    MochiReq1 = mochiweb_request:new(MochiReq:get(socket),
-                                      MochiReq:get(method),
-                                      NewPath1,
-                                      MochiReq:get(version),
-                                      MochiReq:get(headers)),
-                    Fun(MochiReq1, VhostTarget)
-            end
-    end,
-    FinalMochiReq.
-
-append_path("/"=_Target, "/"=_Path) ->
-    "/";
-append_path(Target, Path) ->
-    Target ++ Path.
-
-% default redirect vhost handler
-redirect_to_vhost(MochiReq, VhostTarget) ->
-    Path = MochiReq:get(raw_path),
-    Target = append_path(VhostTarget, Path),
-
-    ?LOG_DEBUG("Vhost Target: '~p'~n", [Target]),
-
-    Headers = mochiweb_headers:enter("x-couchdb-vhost-path", Path,
-        MochiReq:get(headers)),
-
-    % build a new mochiweb request
-    MochiReq1 = mochiweb_request:new(MochiReq:get(socket),
-                                      MochiReq:get(method),
-                                      Target,
-                                      MochiReq:get(version),
-                                      Headers),
-    % cleanup, It force mochiweb to reparse raw uri.
-    MochiReq1:cleanup(),
-    MochiReq1.
-
-%% if so, then it will not be rewritten, but will run as a normal couchdb request.
-%* normally you'd use this for _uuids _utils and a few of the others you want to
-%% keep available on vhosts. You can also use it to make databases 'global'.
-vhost_global( VhostGlobals, MochiReq) ->
-    RawUri = MochiReq:get(raw_path),
-    {"/" ++ Path, _, _} = mochiweb_util:urlsplit_path(RawUri),
-
-    Front = case couch_httpd:partition(Path) of
-    {"", "", ""} ->
-        "/"; % Special case the root url handler
-    {FirstPart, _, _} ->
-        FirstPart
-    end,
-    [true] == [true||V <- VhostGlobals, V == Front].
-
-%% bind host
-%% first it try to bind the port then the hostname.
-try_bind_vhost([], _HostParts, _Port, _PathParts) ->
-    no_vhost_matched;
-try_bind_vhost([VhostSpec|Rest], HostParts, Port, PathParts) ->
-    {{VHostParts, VPort, VPath}, Path} = VhostSpec,
-    case bind_port(VPort, Port) of
-        ok ->
-            case bind_vhost(lists:reverse(VHostParts), HostParts, []) of
-                {ok, Bindings, Remainings} ->
-                    case bind_path(VPath, PathParts) of
-                        {ok, PathParts1} ->
-                            Path1 = make_target(Path, Bindings, Remainings, []),
-                            {make_path(Path1), make_path(PathParts1)};
-                        fail ->
-                            try_bind_vhost(Rest, HostParts, Port,
-                                PathParts)
-                    end;
-                fail -> try_bind_vhost(Rest, HostParts, Port, PathParts)
-            end;
-        fail ->  try_bind_vhost(Rest, HostParts, Port, PathParts)
-    end.
-
-%% doc: build new patch from bindings. bindings are query args
-%% (+ dynamic query rewritten if needed) and bindings found in
-%% bind_path step.
-%% TODO: merge code with rewrite. But we need to make sure we are
-%% in string here.
-make_target([], _Bindings, _Remaining, Acc) ->
-    lists:reverse(Acc);
-make_target([?MATCH_ALL], _Bindings, Remaining, Acc) ->
-    Acc1 = lists:reverse(Acc) ++ Remaining,
-    Acc1;
-make_target([?MATCH_ALL|_Rest], _Bindings, Remaining, Acc) ->
-    Acc1 = lists:reverse(Acc) ++ Remaining,
-    Acc1;
-make_target([{bind, P}|Rest], Bindings, Remaining, Acc) ->
-    P2 = case couch_util:get_value({bind, P}, Bindings) of
-        undefined ->  "undefined";
-        P1 -> P1
-    end,
-    make_target(Rest, Bindings, Remaining, [P2|Acc]);
-make_target([P|Rest], Bindings, Remaining, Acc) ->
-    make_target(Rest, Bindings, Remaining, [P|Acc]).
-
-%% bind port
-bind_port(Port, Port) -> ok;
-bind_port('*', _) -> ok;
-bind_port(_,_) -> fail.
-
-%% bind bhost
-bind_vhost([],[], Bindings) -> {ok, Bindings, []};
-bind_vhost([?MATCH_ALL], [], _Bindings) -> fail;
-bind_vhost([?MATCH_ALL], Rest, Bindings) -> {ok, Bindings, Rest};
-bind_vhost([], _HostParts, _Bindings) -> fail;
-bind_vhost([{bind, Token}|Rest], [Match|RestHost], Bindings) ->
-    bind_vhost(Rest, RestHost, [{{bind, Token}, Match}|Bindings]);
-bind_vhost([Cname|Rest], [Cname|RestHost], Bindings) ->
-    bind_vhost(Rest, RestHost, Bindings);
-bind_vhost(_, _, _) -> fail.
-
-%% bind path
-bind_path([], PathParts) ->
-    {ok, PathParts};
-bind_path(_VPathParts, []) ->
-    fail;
-bind_path([Path|VRest],[Path|Rest]) ->
-   bind_path(VRest, Rest);
-bind_path(_, _) ->
-    fail.
-
-% utilities
-
-
-%% create vhost list from ini
-
-host(MochiReq) ->
-    XHost = config:get("httpd", "x_forwarded_host",
-                             "X-Forwarded-Host"),
-    case MochiReq:get_header_value(XHost) of
-        undefined ->
-            case MochiReq:get_header_value("Host") of
-                undefined -> [];
-                Value1 -> Value1
-            end;
-        Value -> Value
-    end.
-
-make_vhosts() ->
-    Vhosts = lists:foldl(fun
-                ({_, ""}, Acc) ->
-                    Acc;
-                ({Vhost, Path}, Acc) ->
-                    [{parse_vhost(Vhost), split_path(Path)}|Acc]
-            end, [], config:get("vhosts")),
-
-    lists:reverse(lists:usort(Vhosts)).
-
-
-parse_vhost(Vhost) ->
-    case urlsplit_netloc(Vhost, []) of
-        {[], Path} ->
-            {make_spec("*", []), '*', Path};
-        {HostPort, []} ->
-            {H, P} = split_host_port(HostPort),
-            H1 = make_spec(H, []),
-            {H1, P, []};
-        {HostPort, Path} ->
-            {H, P} = split_host_port(HostPort),
-            H1 = make_spec(H, []),
-            {H1, P, string:tokens(Path, "/")}
-    end.
-
-
-split_host_port(HostAsString) ->
-    case string:rchr(HostAsString, $:) of
-        0 ->
-            {split_host(HostAsString), '*'};
-        N ->
-            HostPart = string:substr(HostAsString, 1, N-1),
-            case (catch erlang:list_to_integer(string:substr(HostAsString,
-                            N+1, length(HostAsString)))) of
-                {'EXIT', _} ->
-                    {split_host(HostAsString), '*'};
-                Port ->
-                    {split_host(HostPart), Port}
-            end
-    end.
-
-split_host(HostAsString) ->
-    string:tokens(HostAsString, "\.").
-
-split_path(Path) ->
-    make_spec(string:tokens(Path, "/"), []).
-
-
-make_spec([], Acc) ->
-    lists:reverse(Acc);
-make_spec([""|R], Acc) ->
-    make_spec(R, Acc);
-make_spec(["*"|R], Acc) ->
-    make_spec(R, [?MATCH_ALL|Acc]);
-make_spec([P|R], Acc) ->
-    P1 = parse_var(P),
-    make_spec(R, [P1|Acc]).
-
-
-parse_var(P) ->
-    case P of
-        ":" ++ Var ->
-            {bind, Var};
-        _ -> P
-    end.
-
-
-% mochiweb doesn't export it.
-urlsplit_netloc("", Acc) ->
-    {lists:reverse(Acc), ""};
-urlsplit_netloc(Rest=[C | _], Acc) when C =:= $/; C =:= $?; C =:= $# ->
-    {lists:reverse(Acc), Rest};
-urlsplit_netloc([C | Rest], Acc) ->
-    urlsplit_netloc(Rest, [C | Acc]).
-
-make_path(Parts) ->
-     "/" ++ string:join(Parts,[?SEPARATOR]).
-
-init(_) ->
-    ok = config:listen_for_changes(?MODULE, nil),
-
-    %% load configuration
-    {VHostGlobals, VHosts, Fun} = load_conf(),
-    State = #vhosts_state{
-        vhost_globals=VHostGlobals,
-        vhosts=VHosts,
-        vhosts_fun=Fun},
-    {ok, State}.
-
-handle_call(reload, _From, _State) ->
-    {VHostGlobals, VHosts, Fun} = load_conf(),
-    {reply, ok, #vhosts_state{
-            vhost_globals=VHostGlobals,
-            vhosts=VHosts,
-            vhosts_fun=Fun}};
-handle_call(get_state, _From, State) ->
-    {reply, State, State};
-handle_call(_Msg, _From, State) ->
-    {noreply, State}.
-
-handle_cast(_Msg, State) ->
-    {noreply, State}.
-
-handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
-    erlang:send_after(5000, self(), restart_config_listener),
-    {noreply, State};
-handle_info(restart_config_listener, State) ->
-    ok = config:listen_for_changes(?MODULE, nil),
-    {noreply, State};
-handle_info(_Info, State) ->
-    {noreply, State}.
-
-terminate(_Reason, _State) ->
-    ok.
-
-code_change(_OldVsn, State, _Extra) ->
-    {ok, State}.
-
-
-handle_config_change("httpd", "vhost_global_handlers", _, _, _) ->
-    {ok, ?MODULE:reload()};
-handle_config_change("httpd", "redirect_vhost_handler", _, _, _) ->
-    {ok, ?MODULE:reload()};
-handle_config_change("vhosts", _, _, _, _) ->
-    {ok, ?MODULE:reload()};
-handle_config_change(_, _, _, _, _) ->
-    {ok, nil}.
-
-
-load_conf() ->
-    %% get vhost globals
-    VHostGlobals = re:split(config:get("httpd",
-            "vhost_global_handlers",""), "\\s*,\\s*",[{return, list}]),
-
-    %% build vhosts matching rules
-    VHosts = make_vhosts(),
-
-    %% build vhosts handler fun
-    DefaultVHostFun = "{couch_httpd_vhost, redirect_to_vhost}",
-    Fun = couch_httpd:make_arity_2_fun(config:get("httpd",
-            "redirect_vhost_handler", DefaultVHostFun)),
-
-    {VHostGlobals, VHosts, Fun}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed98610c/src/couch/src/couch_js_functions.hrl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_js_functions.hrl b/src/couch/src/couch_js_functions.hrl
deleted file mode 100644
index 2ecd851..0000000
--- a/src/couch/src/couch_js_functions.hrl
+++ /dev/null
@@ -1,155 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License.  You may obtain a copy of
-% the License at
-%
-%   http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--define(AUTH_DB_DOC_VALIDATE_FUNCTION, <<"
-    function(newDoc, oldDoc, userCtx, secObj) {
-        if (newDoc._deleted === true) {
-            // allow deletes by admins and matching users
-            // without checking the other fields
-            if ((userCtx.roles.indexOf('_admin') !== -1) ||
-                (userCtx.name == oldDoc.name)) {
-                return;
-            } else {
-                throw({forbidden: 'Only admins may delete other user docs.'});
-            }
-        }
-
-        if ((oldDoc && oldDoc.type !== 'user') || newDoc.type !== 'user') {
-            throw({forbidden : 'doc.type must be user'});
-        } // we only allow user docs for now
-
-        if (!newDoc.name) {
-            throw({forbidden: 'doc.name is required'});
-        }
-
-        if (!newDoc.roles) {
-            throw({forbidden: 'doc.roles must exist'});
-        }
-
-        if (!isArray(newDoc.roles)) {
-            throw({forbidden: 'doc.roles must be an array'});
-        }
-
-        if (newDoc._id !== ('org.couchdb.user:' + newDoc.name)) {
-            throw({
-                forbidden: 'Doc ID must be of the form org.couchdb.user:name'
-            });
-        }
-
-        if (oldDoc) { // validate all updates
-            if (oldDoc.name !== newDoc.name) {
-                throw({forbidden: 'Usernames can not be changed.'});
-            }
-        }
-
-        if (newDoc.password_sha && !newDoc.salt) {
-            throw({
-                forbidden: 'Users with password_sha must have a salt.' +
-                    'See /_utils/script/couch.js for example code.'
-            });
-        }
-
-        var is_server_or_database_admin = function(userCtx, secObj) {
-            // see if the user is a server admin
-            if(userCtx.roles.indexOf('_admin') !== -1) {
-                return true; // a server admin
-            }
-
-            // see if the user a database admin specified by name
-            if(secObj && secObj.admins && secObj.admins.names) {
-                if(secObj.admins.names.indexOf(userCtx.name) !== -1) {
-                    return true; // database admin
-                }
-            }
-
-            // see if the user a database admin specified by role
-            if(secObj && secObj.admins && secObj.admins.roles) {
-                var db_roles = secObj.admins.roles;
-                for(var idx = 0; idx < userCtx.roles.length; idx++) {
-                    var user_role = userCtx.roles[idx];
-                    if(db_roles.indexOf(user_role) !== -1) {
-                        return true; // role matches!
-                    }
-                }
-            }
-
-            return false; // default to no admin
-        }
-
-        if (!is_server_or_database_admin(userCtx, secObj)) {
-            if (oldDoc) { // validate non-admin updates
-                if (userCtx.name !== newDoc.name) {
-                    throw({
-                        forbidden: 'You may only update your own user document.'
-                    });
-                }
-                // validate role updates
-                var oldRoles = oldDoc.roles.sort();
-                var newRoles = newDoc.roles.sort();
-
-                if (oldRoles.length !== newRoles.length) {
-                    throw({forbidden: 'Only _admin may edit roles'});
-                }
-
-                for (var i = 0; i < oldRoles.length; i++) {
-                    if (oldRoles[i] !== newRoles[i]) {
-                        throw({forbidden: 'Only _admin may edit roles'});
-                    }
-                }
-            } else if (newDoc.roles.length > 0) {
-                throw({forbidden: 'Only _admin may set roles'});
-            }
-        }
-
-        // no system roles in users db
-        for (var i = 0; i < newDoc.roles.length; i++) {
-            if (newDoc.roles[i][0] === '_') {
-                throw({
-                    forbidden:
-                    'No system roles (starting with underscore) in users db.'
-                });
-            }
-        }
-
-        // no system names as names
-        if (newDoc.name[0] === '_') {
-            throw({forbidden: 'Username may not start with underscore.'});
-        }
-
-        var badUserNameChars = [':'];
-
-        for (var i = 0; i < badUserNameChars.length; i++) {
-            if (newDoc.name.indexOf(badUserNameChars[i]) >= 0) {
-                throw({forbidden: 'Character `' + badUserNameChars[i] +
-                        '` is not allowed in usernames.'});
-            }
-        }
-    }
-">>).
-
-
--define(OAUTH_MAP_FUN, <<"
-    function(doc) {
-        if (doc.type === 'user' && doc.oauth && doc.oauth.consumer_keys) {
-            for (var consumer_key in doc.oauth.consumer_keys) {
-                for (var token in doc.oauth.tokens) {
-                    var obj = {
-                        'consumer_secret': doc.oauth.consumer_keys[consumer_key],
-                        'token_secret': doc.oauth.tokens[token],
-                        'username': doc.name
-                    };
-                    emit([consumer_key, token], obj);
-                }
-            }
-        }
-    }
-">>).


Mime
View raw message