summaryrefslogtreecommitdiff
path: root/src/couchdb/couch_httpd_db.erl
diff options
context:
space:
mode:
authorJan Lehnardt <jan@apache.org>2009-03-06 00:12:15 +0000
committerJan Lehnardt <jan@apache.org>2009-03-06 00:12:15 +0000
commita05797474397a1598ac2e3436bd8c1e4e2b8678a (patch)
tree8f7fb3b82ce1f8a95f2db7387e22259a558729a0 /src/couchdb/couch_httpd_db.erl
parent620db891b57c8a429a7f11f23eed302e5479f250 (diff)
Verify attachment names. They must be utf-8 (closes COUCHDB-280) and must not start with an underscore.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@750695 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/couchdb/couch_httpd_db.erl')
-rw-r--r--src/couchdb/couch_httpd_db.erl54
1 files changed, 51 insertions, 3 deletions
diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl
index 524b52b4..0ba8a873 100644
--- a/src/couchdb/couch_httpd_db.erl
+++ b/src/couchdb/couch_httpd_db.erl
@@ -116,6 +116,7 @@ db_req(#httpd{method='POST',path_parts=[_,<<"_bulk_docs">>]}=Req, Db) ->
Docs = lists:map(
fun({ObjProps} = JsonObj) ->
Doc = couch_doc:from_json_obj(JsonObj),
+ validate_attachment_names(Doc),
Id = case Doc#doc.id of
<<>> -> couch_util:new_uuid();
Id0 -> Id0
@@ -436,7 +437,7 @@ db_doc_req(#httpd{method='POST'}=Req, Db, DocId) ->
end,
NewAttachments = [
- {list_to_binary(Name), {list_to_binary(ContentType), Content}} ||
+ {validate_attachment_name(Name), {list_to_binary(ContentType), Content}} ||
{Name, {ContentType, _}, Content} <-
proplists:get_all_values("_attachments", Form)
],
@@ -460,6 +461,7 @@ db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) ->
[Rev0|_] -> Rev0;
[] -> undefined
end,
+ validate_attachment_names(Doc),
case couch_httpd:header_value(Req, "X-Couch-Full-Commit", "false") of
"true" ->
Options = [full_commit];
@@ -591,8 +593,11 @@ db_attachment_req(#httpd{method='GET'}=Req, Db, DocId, FileNameParts) ->
db_attachment_req(#httpd{method=Method}=Req, Db, DocId, FileNameParts)
when (Method == 'PUT') or (Method == 'DELETE') ->
- FileName = list_to_binary(mochiweb_util:join(lists:map(fun binary_to_list/1,
- FileNameParts),"/")),
+ FileName = validate_attachment_name(
+ mochiweb_util:join(
+ lists:map(fun binary_to_list/1,
+ FileNameParts),"/")),
+
NewAttachment = case Method of
'DELETE' ->
[];
@@ -708,3 +713,46 @@ parse_copy_destination_header(Req) ->
{list_to_binary(DocId), [list_to_binary(Rev)]}
end.
+validate_attachment_names(Doc) ->
+ lists:foreach(fun({Name, _}) ->
+ validate_attachment_name(Name)
+ end, Doc#doc.attachments).
+
+validate_attachment_name(Name) when is_list(Name) ->
+ validate_attachment_name(list_to_binary(Name));
+validate_attachment_name(Name) ->
+ case is_valid_utf8(Name) of
+ true ->
+ case Name of
+ <<"_",_/binary>>=Name -> throw({bad_request, <<"Attachment name can't start with '_'">>});
+ _ -> Name
+ end;
+ false -> throw({bad_request, <<"Attachment name is not UTF-8 encoded">>})
+ end.
+
+%% borrowed from mochijson2:json_bin_is_safe()
+is_valid_utf8(<<>>) ->
+ true;
+is_valid_utf8(<<C, Rest/binary>>) ->
+ case C of
+ $\" ->
+ false;
+ $\\ ->
+ false;
+ $\b ->
+ false;
+ $\f ->
+ false;
+ $\n ->
+ false;
+ $\r ->
+ false;
+ $\t ->
+ false;
+ C when C >= 0, C < $\s; C >= 16#7f, C =< 16#10FFFF ->
+ false;
+ C when C < 16#7f ->
+ is_valid_utf8(Rest);
+ _ ->
+ false
+ end.