From a05797474397a1598ac2e3436bd8c1e4e2b8678a Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Fri, 6 Mar 2009 00:12:15 +0000 Subject: 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 --- src/couchdb/couch_httpd_db.erl | 54 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) (limited to 'src/couchdb') 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(<>) -> + 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. -- cgit v1.2.3