diff options
author | lukasza <lukasza@chromium.org> | 2016-01-08 11:35:04 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-08 19:36:02 +0000 |
commit | c644f37125ab27311d697af61e56c64d0e29027e (patch) | |
tree | f9f73168acee7cfe259bcaaf5425deeab99071f8 /net | |
parent | 5efcee9378877176a9ccf173e3bcfa4a902b55d9 (diff) | |
download | chromium_src-c644f37125ab27311d697af61e56c64d0e29027e.zip chromium_src-c644f37125ab27311d697af61e56c64d0e29027e.tar.gz chromium_src-c644f37125ab27311d697af61e56c64d0e29027e.tar.bz2 |
Introducing a net::GenerateMimeMultipartBoundary helper.
... and using the helper in places that had introduced separate
functions for generating a random Mime boundary (sometimes with
bugs - i.e. using '*' characters is disallowed by RFC 1341).
TBR=bartfab@chromium.org, stevet@chromium.org
BUG=575733
Review URL: https://codereview.chromium.org/1547593002
Cr-Commit-Position: refs/heads/master@{#368404}
Diffstat (limited to 'net')
-rw-r--r-- | net/base/mime_util.cc | 49 | ||||
-rw-r--r-- | net/base/mime_util.h | 4 | ||||
-rw-r--r-- | net/base/mime_util_unittest.cc | 28 |
3 files changed, 81 insertions, 0 deletions
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc index d1e202b..3e8d615 100644 --- a/net/base/mime_util.cc +++ b/net/base/mime_util.cc @@ -7,9 +7,11 @@ #include <map> #include <string> +#include "base/base64.h" #include "base/containers/hash_tables.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/rand_util.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -511,6 +513,17 @@ void HashSetToVector(base::hash_set<T>* source, std::vector<T>* target) { (*target)[old_target_size + i] = *iter; } +// Characters to be used for mime multipart boundary. +// The RFC 2046 spec says the alphanumeric characters plus the +// following characters are legal for boundaries: '()+_,-./:=? +// However the following characters, though legal, cause some sites +// to fail: (),./:=+ +const char kMimeBoundaryCharacters[] = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +// Size of mime multipart boundary. +const size_t kMimeBoundarySize = 69; + } // namespace void GetExtensionsForMimeType( @@ -557,6 +570,42 @@ void GetExtensionsForMimeType( HashSetToVector(&unique_extensions, extensions); } +NET_EXPORT std::string GenerateMimeMultipartBoundary() { + // Based on RFC 1341, section "7.2.1 Multipart: The common syntax": + // Because encapsulation boundaries must not appear in the body parts being + // encapsulated, a user agent must exercise care to choose a unique + // boundary. The boundary in the example above could have been the result of + // an algorithm designed to produce boundaries with a very low probability + // of already existing in the data to be encapsulated without having to + // prescan the data. + // [...] + // the boundary parameter [...] consists of 1 to 70 characters from a set of + // characters known to be very robust through email gateways, and NOT ending + // with white space. + // [...] + // boundary := 0*69<bchars> bcharsnospace + // bchars := bcharsnospace / " " + // bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / "+" / + // "_" / "," / "-" / "." / "/" / ":" / "=" / "?" + + std::string result; + result.reserve(kMimeBoundarySize); + result.append("----MultipartBoundary--"); + while (result.size() < (kMimeBoundarySize - 4)) { + // Subtract 2 from the array size to 1) exclude '\0', and 2) turn the size + // into the last index. + const int last_char_index = sizeof(kMimeBoundaryCharacters) - 2; + char c = kMimeBoundaryCharacters[base::RandInt(0, last_char_index)]; + result.push_back(c); + } + result.append("----"); + + // Not a strict requirement - documentation only. + DCHECK_EQ(kMimeBoundarySize, result.size()); + + return result; +} + void AddMultipartValueForUpload(const std::string& value_name, const std::string& value, const std::string& mime_boundary, diff --git a/net/base/mime_util.h b/net/base/mime_util.h index d58ddb0..48b9a64 100644 --- a/net/base/mime_util.h +++ b/net/base/mime_util.h @@ -100,6 +100,10 @@ enum CertificateMimeType { CERTIFICATE_MIME_TYPE_PKCS12_ARCHIVE, }; +// Generates a random MIME multipart boundary. +// The returned string is guaranteed to be at most 70 characters long. +NET_EXPORT std::string GenerateMimeMultipartBoundary(); + // Prepares one value as part of a multi-part upload request. NET_EXPORT void AddMultipartValueForUpload(const std::string& value_name, const std::string& value, diff --git a/net/base/mime_util_unittest.cc b/net/base/mime_util_unittest.cc index 8bc61bc..0787d8c 100644 --- a/net/base/mime_util_unittest.cc +++ b/net/base/mime_util_unittest.cc @@ -273,6 +273,34 @@ TEST(MimeUtilTest, TestGetExtensionsForMimeType) { } } +TEST(MimeUtilTest, TestGenerateMimeMultipartBoundary) { + std::string boundary1 = GenerateMimeMultipartBoundary(); + std::string boundary2 = GenerateMimeMultipartBoundary(); + + // RFC 1341 says: the boundary parameter [...] consists of 1 to 70 characters. + EXPECT_GE(70u, boundary1.size()); + EXPECT_GE(70u, boundary2.size()); + + // RFC 1341 asks to: exercise care to choose a unique boundary. + EXPECT_NE(boundary1, boundary2); + ASSERT_LE(16u, boundary1.size()); + ASSERT_LE(16u, boundary2.size()); + + // Expect that we don't pick '\0' character from the array/string + // where we take the characters from. + EXPECT_EQ(std::string::npos, boundary1.find('\0')); + EXPECT_EQ(std::string::npos, boundary2.find('\0')); + + // Asserts below are not RFC 1341 requirements, but are here + // to improve readability of generated MIME documents and to + // try to preserve some aspects of the old boundary generation code. + EXPECT_EQ("--", boundary1.substr(0, 2)); + EXPECT_EQ("--", boundary2.substr(0, 2)); + EXPECT_NE(std::string::npos, boundary1.find("MultipartBoundary")); + EXPECT_NE(std::string::npos, boundary2.find("MultipartBoundary")); + EXPECT_EQ("--", boundary1.substr(boundary1.size() - 2, 2)); + EXPECT_EQ("--", boundary2.substr(boundary2.size() - 2, 2)); +} TEST(MimeUtilTest, TestAddMultipartValueForUpload) { const char ref_output[] = |