diff options
| -rw-r--r-- | share/www/script/test/basics.js | 22 | ||||
| -rw-r--r-- | src/couchdb/couch_httpd_db.erl | 2 | ||||
| -rw-r--r-- | src/couchdb/couch_rep.erl | 30 | ||||
| -rw-r--r-- | src/couchdb/couch_util.erl | 25 | 
4 files changed, 42 insertions, 37 deletions
| diff --git a/share/www/script/test/basics.js b/share/www/script/test/basics.js index 5e26360f..3979d860 100644 --- a/share/www/script/test/basics.js +++ b/share/www/script/test/basics.js @@ -29,15 +29,19 @@ couchTests.basics = function(debug) {    if (debug) debugger;    // creating a new DB should return Location header -  xhr = CouchDB.request("DELETE", "/test_suite_db"); -  xhr = CouchDB.request("PUT", "/test_suite_db"); -  TEquals("/test_suite_db", -    xhr.getResponseHeader("Location").substr(-14), -    "should return Location header to newly created document"); - -  TEquals("http://", -    xhr.getResponseHeader("Location").substr(0, 7), -    "should return absolute Location header to newly created document"); +  // and it should work for dbs with slashes (COUCHDB-411) +  var dbnames = ["test_suite_db", "test_suite_db%2Fwith_slashes"]; +  dbnames.forEach(function(dbname) { +    xhr = CouchDB.request("DELETE", "/" + dbname); +    xhr = CouchDB.request("PUT", "/" + dbname); +    TEquals(dbname, +      xhr.getResponseHeader("Location").substr(-dbname.length), +      "should return Location header to newly created document"); + +    TEquals("http://", +      xhr.getResponseHeader("Location").substr(0, 7), +      "should return absolute Location header to newly created document"); +  });    // Get the database info, check the db_name    T(db.info().db_name == "test_suite_db"); diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index 63ae5563..119182af 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -237,7 +237,7 @@ create_db_req(#httpd{user_ctx=UserCtx}=Req, DbName) ->      case couch_server:create(DbName, [{user_ctx, UserCtx}]) of      {ok, Db} ->          couch_db:close(Db), -        DocUrl = absolute_uri(Req, "/" ++ DbName), +        DocUrl = absolute_uri(Req, "/" ++ couch_util:url_encode(DbName)),          send_json(Req, 201, [{"Location", DocUrl}], {[{ok, true}]});      Error ->          throw(Error) diff --git a/src/couchdb/couch_rep.erl b/src/couchdb/couch_rep.erl index 3cb90347..71aa0693 100644 --- a/src/couchdb/couch_rep.erl +++ b/src/couchdb/couch_rep.erl @@ -392,7 +392,7 @@ att_stub_converter(DbS, Id, Rev,          #att{name=Name,data=stub,type=Type,len=Length}=Att) ->      #http_db{uri=DbUrl, headers=Headers} = DbS,      {Pos, [RevId|_]} = Rev, -    Url = lists:flatten([DbUrl, url_encode(Id), "/", url_encode(?b2l(Name)), +    Url = lists:flatten([DbUrl, couch_util:url_encode(Id), "/", couch_util:url_encode(?b2l(Name)),          "?rev=", ?b2l(couch_doc:rev_to_str({Pos,RevId}))]),      ?LOG_DEBUG("Attachment URL ~s", [Url]),      {ok, RcvFun} = make_att_stub_receiver(Url, Headers, Name, @@ -732,7 +732,7 @@ get_missing_revs(Db, DocId) ->  open_doc(#http_db{uri=DbUrl, headers=Headers}, DocId, Options) ->      [] = Options, -    case do_http_request(DbUrl ++ url_encode(DocId), get, Headers) of +    case do_http_request(DbUrl ++ couch_util:url_encode(DocId), get, Headers) of      {[{<<"error">>, ErrId}, {<<"reason">>, Reason}]} ->          {couch_util:to_existing_atom(ErrId), Reason};      Doc  -> @@ -744,7 +744,7 @@ open_doc(Db, DocId, Options) ->  open_doc_revs(#http_db{uri=DbUrl, headers=Headers} = DbS, DocId, Revs0,          [latest]) ->      Revs = couch_doc:rev_to_strs(Revs0), -    BaseUrl = DbUrl ++ url_encode(DocId) ++ "?revs=true&latest=true", +    BaseUrl = DbUrl ++ couch_util:url_encode(DocId) ++ "?revs=true&latest=true",      %% MochiWeb expects URLs < 8KB long, so maybe split into multiple requests      MaxN = trunc((8192 - length(BaseUrl))/14), @@ -827,7 +827,7 @@ binary_memory(Pid) ->  update_doc(#http_db{uri=DbUrl, headers=Headers}, #doc{id=DocId}=Doc, Options) ->      [] = Options, -    Url = DbUrl ++ url_encode(DocId), +    Url = DbUrl ++ couch_util:url_encode(DocId),      {ResponseMembers} = do_http_request(Url, put, Headers,              couch_doc:to_json_obj(Doc, [attachments])),      Rev = proplists:get_value(<<"rev">>, ResponseMembers), @@ -865,25 +865,3 @@ up_to_date(Source, Seq) ->      couch_db:close(NewDb),      T. -url_encode(Bin) when is_binary(Bin) -> -    url_encode(binary_to_list(Bin)); -url_encode([H|T]) -> -    if -    H >= $a, $z >= H -> -        [H|url_encode(T)]; -    H >= $A, $Z >= H -> -        [H|url_encode(T)]; -    H >= $0, $9 >= H -> -        [H|url_encode(T)]; -    H == $_; H == $.; H == $-; H == $: -> -        [H|url_encode(T)]; -    true -> -        case lists:flatten(io_lib:format("~.16.0B", [H])) of -        [X, Y] -> -            [$%, X, Y | url_encode(T)]; -        [X] -> -            [$%, $0, X | url_encode(T)] -        end -    end; -url_encode([]) -> -    []. diff --git a/src/couchdb/couch_util.erl b/src/couchdb/couch_util.erl index db9f937c..71c6aea9 100644 --- a/src/couchdb/couch_util.erl +++ b/src/couchdb/couch_util.erl @@ -18,7 +18,7 @@  -export([abs_pathname/1,abs_pathname/2, trim/1, ascii_lower/1]).  -export([encodeBase64/1, decodeBase64/1, to_hex/1,parse_term/1,dict_find/3]).  -export([file_read_size/1, get_nested_json_value/2, json_user_ctx/1]). --export([to_binary/1, to_list/1]). +-export([to_binary/1, to_list/1, url_encode/1]).  -include("couch_db.hrl").  -include_lib("kernel/include/file.hrl"). @@ -328,3 +328,26 @@ to_list(V) when is_atom(V) ->      atom_to_list(V);  to_list(V) ->      lists:flatten(io_lib:format("~p", [V])). + +url_encode(Bin) when is_binary(Bin) -> +    url_encode(binary_to_list(Bin)); +url_encode([H|T]) -> +    if +    H >= $a, $z >= H -> +        [H|url_encode(T)]; +    H >= $A, $Z >= H -> +        [H|url_encode(T)]; +    H >= $0, $9 >= H -> +        [H|url_encode(T)]; +    H == $_; H == $.; H == $-; H == $: -> +        [H|url_encode(T)]; +    true -> +        case lists:flatten(io_lib:format("~.16.0B", [H])) of +        [X, Y] -> +            [$%, X, Y | url_encode(T)]; +        [X] -> +            [$%, $0, X | url_encode(T)] +        end +    end; +url_encode([]) -> +    [].
\ No newline at end of file | 
