summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/www/script/test/invalid_docids.js10
-rw-r--r--src/couchdb/couch_doc.erl24
-rw-r--r--src/couchdb/couch_httpd_db.erl2
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}]);