diff --git a/http_server.c b/http_server.c index 288dc716..1c90d768 100644 --- a/http_server.c +++ b/http_server.c @@ -637,6 +637,17 @@ static int _parse_content_type(struct http_request *r, struct mime_content_type continue; } r->cursor = start; + if (_skip_literal(r, "format=")) { + size_t n = _parse_token_or_quoted_string(r, ct->format, sizeof ct->format); + if (n == 0) + return 0; + if (n >= sizeof ct->format) { + WARNF("HTTP Content-Type format truncated: %s", alloca_str_toprint(ct->format)); + return 0; + } + continue; + } + r->cursor = start; struct substring param; if (_skip_token(r, ¶m) && _skip_literal(r, "=") && _parse_token_or_quoted_string(r, NULL, 0)) { if (r->debug_flag && *r->debug_flag) @@ -1337,11 +1348,10 @@ static int http_request_parse_body_form_data(struct http_request *r) char labelstr[labellen + 1]; strncpy(labelstr, label.start, labellen)[labellen] = '\0'; str_tolower_inplace(labelstr); - const char *value = r->cursor; if (strcmp(labelstr, "content-length") == 0) { if (r->part_header.content_length != CONTENT_LENGTH_UNKNOWN) { if (r->debug_flag && *r->debug_flag) - DEBUGF("Skipping duplicate HTTP multipart header Content-Length: %s", alloca_toprint(50, sol, r->end - sol)); + DEBUGF("Skipping duplicate HTTP multipart header %s", alloca_toprint(50, sol, r->end - sol)); return 400; } http_size_t length; @@ -1357,7 +1367,7 @@ static int http_request_parse_body_form_data(struct http_request *r) else if (strcmp(labelstr, "content-type") == 0) { if (r->part_header.content_type.type[0]) { if (r->debug_flag && *r->debug_flag) - DEBUGF("Skipping duplicate HTTP multipart header Content-Type: %s", alloca_toprint(50, sol, r->end - sol)); + DEBUGF("Skipping duplicate HTTP multipart header %s", alloca_toprint(50, sol, r->end - sol)); return 400; } if (_parse_content_type(r, &r->part_header.content_type) && _skip_optional_space(r) && _skip_crlf(r)) { @@ -1371,7 +1381,7 @@ static int http_request_parse_body_form_data(struct http_request *r) else if (strcmp(labelstr, "content-disposition") == 0) { if (r->part_header.content_disposition.type[0]) { if (r->debug_flag && *r->debug_flag) - DEBUGF("Skipping duplicate HTTP multipart header Content-Disposition: %s", alloca_toprint(50, sol, r->end - sol)); + DEBUGF("Skipping duplicate HTTP multipart header %s", alloca_toprint(50, sol, r->end - sol)); return 400; } if (_parse_content_disposition(r, &r->part_header.content_disposition) && _skip_optional_space(r) && _skip_crlf(r)) { @@ -1385,7 +1395,7 @@ static int http_request_parse_body_form_data(struct http_request *r) else if (_skip_to_crlf(r)) { _commit(r); if (r->debug_flag && *r->debug_flag) - DEBUGF("Skip HTTP multipart header: %s: %s", alloca_str_toprint(labelstr), alloca_toprint(-1, value, value - r->cursor)); + DEBUGF("Skip HTTP multipart header: %s", alloca_toprint(50, sol, r->parsed - sol)); return 0; } } diff --git a/http_server.h b/http_server.h index 7de5bb9c..b57aff1b 100644 --- a/http_server.h +++ b/http_server.h @@ -68,6 +68,7 @@ struct mime_content_type { char subtype[64]; char multipart_boundary[71]; char charset[31]; + char format[31]; }; struct http_client_authorization { diff --git a/java/org/servalproject/servaldna/rhizome/RhizomeCommon.java b/java/org/servalproject/servaldna/rhizome/RhizomeCommon.java index 5f9892db..7106fe53 100644 --- a/java/org/servalproject/servaldna/rhizome/RhizomeCommon.java +++ b/java/org/servalproject/servaldna/rhizome/RhizomeCommon.java @@ -373,12 +373,15 @@ public class RhizomeCommon if (author != null) { wr.print("\r\n--" + boundary + "\r\n"); wr.print("Content-Disposition: form-data; name=\"bundle-author\"\r\n"); + wr.print("Content-Type: serval-mesh/sid\r\n"); + wr.print("Content-Transfer-Encoding: hex\r\n"); wr.print("\r\n"); wr.print(author.toHex()); } wr.print("\r\n--" + boundary + "\r\n"); wr.print("Content-Disposition: form-data; name=\"manifest\"\r\n"); - wr.print("Content-Type: rhizome-manifest/text\r\n"); + wr.print("Content-Type: rhizome/manifest; format=\"text+binarysig\"\r\n"); + wr.print("Content-Transfer-Encoding: binary\r\n"); wr.print("\r\n"); wr.flush(); manifest.toTextFormat(ost); @@ -391,6 +394,7 @@ public class RhizomeCommon } wr.print("\r\n"); wr.print("Content-Type: application/octet-stream\r\n"); + wr.print("Content-Transfer-Encoding: binary\r\n"); wr.print("\r\n"); wr.flush(); byte[] buffer = new byte[4096]; diff --git a/rhizome_restful.c b/rhizome_restful.c index 67f7e123..8da5929e 100644 --- a/rhizome_restful.c +++ b/rhizome_restful.c @@ -418,10 +418,12 @@ static int insert_mime_part_header(struct http_request *hr, const struct mime_pa if (r->u.insert.received_manifest) return http_response_form_part(r, "Duplicate", PART_MANIFEST, NULL, 0); form_buf_malloc_init(&r->u.insert.manifest, MAX_MANIFEST_BYTES); - if ( strcmp(h->content_type.type, "rhizome-manifest") != 0 - || strcmp(h->content_type.subtype, "text") != 0 + if ( strcmp(h->content_type.type, "rhizome") != 0 + || strcmp(h->content_type.subtype, "manifest") != 0 ) return http_response_form_part(r, "Unsupported Content-Type in", PART_MANIFEST, NULL, 0); + if (strcmp(h->content_type.format, "text+binarysig") != 0) + return http_response_form_part(r, "Unsupported rhizome/manifest format in", PART_MANIFEST, NULL, 0); r->u.insert.current_part = PART_MANIFEST; } else if (strcmp(h->content_disposition.name, PART_PAYLOAD) == 0) { diff --git a/strbuf_helpers.c b/strbuf_helpers.c index 05c271e8..140957de 100644 --- a/strbuf_helpers.c +++ b/strbuf_helpers.c @@ -813,6 +813,10 @@ strbuf strbuf_append_mime_content_type(strbuf sb, const struct mime_content_type strbuf_puts(sb, "; boundary="); strbuf_append_quoted_string(sb, ct->multipart_boundary); } + if (ct->format) { + strbuf_puts(sb, "; format="); + strbuf_append_quoted_string(sb, ct->format); + } return sb; } diff --git a/tests/rhizomerestful b/tests/rhizomerestful index acb93c12..8fe06aa2 100755 --- a/tests/rhizomerestful +++ b/tests/rhizomerestful @@ -515,7 +515,7 @@ test_RhizomeInsert() { --dump-header http.header$n \ --basic --user harry:potter \ "${authorargs[@]}" \ - --form "manifest=@manifest$n;type=rhizome-manifest/text" \ + --form "manifest=@manifest$n;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file$n${payload_filename[$n]:+;filename=\"${payload_filename[$n]}\"}" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header$n file$n.manifest @@ -579,7 +579,7 @@ test_RhizomeInsert() { --output nfile$n.manifest \ --dump-header http.headers$n \ --basic --user harry:potter \ - --form "manifest=@nmanifest$n;type=rhizome-manifest/text" \ + --form "manifest=@nmanifest$n;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@nfile$n;filename=\"nfile$n\"" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.headers$n nfile$n.manifest @@ -616,7 +616,7 @@ test_RhizomeInsertAnon() { --dump-header http.header \ --basic --user harry:potter \ --form "bundle-secret=$SECRET" \ - --form "manifest=@file2.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file2.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file2" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header ifile2.manifest @@ -642,7 +642,7 @@ test_RhizomeInsertEmpty() { --output empty.manifest \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=;type=rhizome-manifest/text" \ + --form "manifest=;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@empty;filename=\"lucky\"" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header empty.manifest @@ -671,7 +671,7 @@ test_RhizomeInsertLarge() { --output file1.manifest \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=;type=rhizome-manifest/text" \ + --form "manifest=;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file1" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header -v file1.manifest @@ -722,7 +722,7 @@ test_RhizomeInsertIncorrectManifestType() { --output http.body \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=;type=rhizome-manifest/something" \ + --form "manifest=;type=rhizome-manifest/text" \ --form "payload=@file1" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header http.body @@ -734,6 +734,29 @@ test_RhizomeInsertIncorrectManifestType() { assert_rhizome_list } +doc_RhizomeInsertIncorrectManifestFormat="HTTP RESTful insert Rhizome bundle, incorrect 'manifest' content format" +setup_RhizomeInsertIncorrectManifestFormat() { + setup + echo 'File one' >file1 +} +test_RhizomeInsertIncorrectManifestFormat() { + execute curl \ + --silent --show-error --write-out '%{http_code}' \ + --output http.body \ + --dump-header http.header \ + --basic --user harry:potter \ + --form "manifest=;type=rhizome/manifest;format=\"text\"" \ + --form "payload=@file1" \ + "http://$addr_localhost:$PORTA/restful/rhizome/insert" + tfw_cat http.header http.body + assertExitStatus == 0 + assertStdoutIs 403 + assertJq http.body 'contains({"http_status_code": 403})' + assertJqGrep --ignore-case http.body '.http_status_message' 'unsupported.*format.*manifest.*form.*part' + executeOk_servald rhizome list + assert_rhizome_list +} + doc_RhizomeInsertDuplicateManifest="HTTP RESTful insert Rhizome bundle, duplicate 'manifest' form part" setup_RhizomeInsertDuplicateManifest() { setup @@ -747,8 +770,8 @@ test_RhizomeInsertDuplicateManifest() { --output http.body \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=@file1.manifest;type=rhizome-manifest/text" \ - --form "manifest=@file2.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file1.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ + --form "manifest=@file2.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file1" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header http.body @@ -772,7 +795,7 @@ test_RhizomeInsertJournal() { --output http.body \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=@file1.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file1.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file1" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header http.body @@ -796,7 +819,7 @@ test_RhizomeInsertMissingPayload() { --output http.body \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=@file1.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file1.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header http.body assertExitStatus == 0 @@ -820,7 +843,7 @@ test_RhizomeInsertDuplicatePayload() { --output http.body \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=@file1.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file1.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file1" \ --form "payload=@file2" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" @@ -846,7 +869,7 @@ test_RhizomeInsertPartOrder() { --dump-header http.header \ --basic --user harry:potter \ --form "payload=@file1" \ - --form "manifest=@file1.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file1.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header http.body assertExitStatus == 0 @@ -869,7 +892,7 @@ test_RhizomeInsertPartUnsupported() { --output http.body \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=@file1.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file1.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file1" \ --form "happyhappy=joyjoy" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" @@ -897,7 +920,7 @@ test_RhizomeInsertIncorrectFilesize() { --output http.body \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=@file1.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file1.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file1" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header http.body @@ -911,7 +934,7 @@ test_RhizomeInsertIncorrectFilesize() { --output http.body \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=@file2.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file2.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file2" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header http.body @@ -936,7 +959,7 @@ test_RhizomeInsertIncorrectFilehash() { --output http.body \ --dump-header http.header \ --basic --user harry:potter \ - --form "manifest=@file1.manifest;type=rhizome-manifest/text" \ + --form "manifest=@file1.manifest;type=rhizome/manifest;format=\"text+binarysig\"" \ --form "payload=@file1" \ "http://$addr_localhost:$PORTA/restful/rhizome/insert" tfw_cat http.header http.body