diff options
-rw-r--r-- | share/www/script/test/invalid_docids.js | 10 | ||||
-rw-r--r-- | src/couchdb/couch_doc.erl | 24 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_db.erl | 2 |
3 files changed, 26 insertions, 10 deletions
diff --git a/share/www/script/test/invalid_docids.js b/share/www/script/test/invalid_docids.js index 814d1a21..4fc4bbf5 100644 --- a/share/www/script/test/invalid_docids.js +++ b/share/www/script/test/invalid_docids.js @@ -29,6 +29,16 @@ couchTests.invalid_docids = function(debug) { T(e.error == "bad_request"); } + // Via PUT with _id not in body. + var res = res = db.request("PUT", "/test_suite_db/_other", {"body": "{}"}); + T(res.status == 400); + T(JSON.parse(res.responseText).error == "bad_request"); + + // Accidental POST to form handling code. + res = db.request("POST", "/test_suite_db/_tmp_view", {"body": "{}"}); + T(res.status == 400); + T(JSON.parse(res.responseText).error == "bad_request"); + // Test invalid _prefix try { db.save({"_id": "_invalid"}); diff --git a/src/couchdb/couch_doc.erl b/src/couchdb/couch_doc.erl index 03cc8906..132c86d0 100644 --- a/src/couchdb/couch_doc.erl +++ b/src/couchdb/couch_doc.erl @@ -15,6 +15,7 @@ -export([to_doc_info/1,to_doc_info_path/1,parse_rev/1,parse_revs/1,rev_to_str/1,rev_to_strs/1]). -export([bin_foldl/3,bin_size/1,bin_to_binary/1,get_validate_doc_fun/1]). -export([from_json_obj/1,to_json_obj/2,has_stubs/1, merge_stubs/2]). +-export([validate_docid/1]). -include("couch_db.hrl"). @@ -143,23 +144,26 @@ parse_revs([Rev | Rest]) -> [parse_rev(Rev) | parse_revs(Rest)]. -transfer_fields([], #doc{body=Fields}=Doc) -> - % convert fields back to json object - Doc#doc{body={lists:reverse(Fields)}}; - -transfer_fields([{<<"_id">>, Id} | Rest], Doc) when is_binary(Id) -> +validate_docid(Id) when is_binary(Id) -> case Id of <<"_design/", _/binary>> -> ok; <<"_local/", _/binary>> -> ok; <<"_", _/binary>> -> throw({bad_request, <<"Only reserved document ids may start with underscore.">>}); _Else -> ok - end, - transfer_fields(Rest, Doc#doc{id=Id}); - -transfer_fields([{<<"_id">>, Id} | _Rest], _Doc) -> + end; +validate_docid(Id) -> ?LOG_DEBUG("Document id is not a string: ~p", [Id]), - throw({bad_request, <<"Document id must be a string">>}); + throw({bad_request, <<"Document id must be a string">>}). + +transfer_fields([], #doc{body=Fields}=Doc) -> + % convert fields back to json object + Doc#doc{body={lists:reverse(Fields)}}; + +transfer_fields([{<<"_id">>, Id} | Rest], Doc) -> + io:format("Transfering docid! ~p~n", [Id]), + validate_docid(Id), + transfer_fields(Rest, Doc#doc{id=Id}); transfer_fields([{<<"_rev">>, Rev} | Rest], #doc{revs={0, []}}=Doc) -> {Pos, RevId} = parse_rev(Rev), diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index d8a2a971..4fa5a9b6 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -497,6 +497,7 @@ db_doc_req(#httpd{method='GET'}=Req, Db, DocId) -> end; db_doc_req(#httpd{method='POST'}=Req, Db, DocId) -> + couch_doc:validate_docid(DocId), case couch_httpd:header_value(Req, "content-type") of "multipart/form-data" ++ _Rest -> ok; @@ -525,6 +526,7 @@ db_doc_req(#httpd{method='POST'}=Req, Db, DocId) -> ]}); db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) -> + couch_doc:validate_docid(DocId), Location = absolute_uri(Req, "/" ++ ?b2l(Db#db.name) ++ "/" ++ ?b2l(DocId)), update_doc(Req, Db, DocId, couch_httpd:json_body(Req), [{"Location", Location}]); |