diff options
18 files changed, 108 insertions, 151 deletions
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.cc index f719de7..1f373f5 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.cc +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.cc @@ -124,9 +124,6 @@ void DeviceCommandScreenshotJob::OnFailure(UploadJob::ErrorCode error_code) { case UploadJob::SERVER_ERROR: result_code = FAILURE_SERVER; break; - case UploadJob::CONTENT_ENCODING_ERROR: - result_code = FAILURE_CLIENT; - break; } base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, diff --git a/chrome/browser/chromeos/policy/upload_job.h b/chrome/browser/chromeos/policy/upload_job.h index 9702d12..1df7573 100644 --- a/chrome/browser/chromeos/policy/upload_job.h +++ b/chrome/browser/chromeos/policy/upload_job.h @@ -30,7 +30,6 @@ class UploadJob { // If the upload fails, the Delegate's OnFailure() method is invoked with // one of these error codes. enum ErrorCode { - CONTENT_ENCODING_ERROR = 0, // Failed to encode content. NETWORK_ERROR = 1, // Network failure. AUTHENTICATION_ERROR = 2, // Authentication failure. SERVER_ERROR = 3 // Server returned error or malformed reply. diff --git a/chrome/browser/chromeos/policy/upload_job_impl.cc b/chrome/browser/chromeos/policy/upload_job_impl.cc index f1a4783..97a379e 100644 --- a/chrome/browser/chromeos/policy/upload_job_impl.cc +++ b/chrome/browser/chromeos/policy/upload_job_impl.cc @@ -4,15 +4,16 @@ #include "chrome/browser/chromeos/policy/upload_job_impl.h" +#include <stddef.h> #include <set> #include <utility> #include "base/logging.h" #include "base/macros.h" -#include "base/rand_util.h" #include "base/strings/stringprintf.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/google_service_auth_error.h" +#include "net/base/mime_util.h" #include "net/http/http_status_code.h" #include "net/url_request/url_request_status.h" @@ -20,41 +21,18 @@ namespace policy { namespace { -// Defines the characters that might appear in strings generated by -// GenerateRandomString(). -const char kAlphaNum[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - // Format for bearer tokens in HTTP requests to access OAuth 2.0 protected // resources. const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; -// Prefix added to a randomly generated string when choosing the MIME boundary. -const char kMultipartBoundaryPrefix[] = "----**--"; - -// Postfix added to a randomly generated string when choosing the MIME boundary. -const char kMultipartBoundaryPostfix[] = "--**----"; - // Value the "Content-Type" field will be set to in the POST request. const char kUploadContentType[] = "multipart/form-data"; -// Number of retries when randomly generating a MIME boundary. -const int kMimeBoundaryRetries = 3; - -// Length of the random string for the MIME boundary. -const int kMimeBoundarySize = 32; - // Number of upload retries. const int kMaxRetries = 1; -// Generates a random alphanumeric string of length |length|. -std::string GenerateRandomString(size_t length) { - std::string random; - random.reserve(length); - for (size_t i = 0; i < length; i++) - random.push_back(kAlphaNum[base::RandGenerator(sizeof(kAlphaNum) - 1)]); - return random; -} +// Max size of MIME boundary according to RFC 1341, section 7.2.1. +const size_t kMaxMimeBoundarySize = 70; } // namespace @@ -95,10 +73,6 @@ class DataSegment { // Returns the size in bytes of the blob in |data_|. size_t GetDataSize() const; - // Helper method that performs a substring match of |chunk| in |data_|. - // Returns |true| if |chunk| matches a substring, |false| otherwise. - bool CheckIfDataContains(const std::string& chunk); - private: const std::string name_; const std::string filename_; @@ -137,28 +111,14 @@ scoped_ptr<std::string> DataSegment::GetData() { return std::move(data_); } -bool DataSegment::CheckIfDataContains(const std::string& chunk) { - DCHECK(data_); - return data_->find(chunk) != std::string::npos; -} - size_t DataSegment::GetDataSize() const { DCHECK(data_); return data_->size(); } -std::string UploadJobImpl::RandomMimeBoundaryGenerator::GenerateBoundary( - size_t length) const { - std::string boundary; - boundary.reserve(length); - DCHECK_GT(length, sizeof(kMultipartBoundaryPrefix) + - sizeof(kMultipartBoundaryPostfix)); - const size_t random_part_length = length - sizeof(kMultipartBoundaryPrefix) - - sizeof(kMultipartBoundaryPostfix); - boundary.append(kMultipartBoundaryPrefix); - boundary.append(GenerateRandomString(random_part_length)); - boundary.append(kMultipartBoundaryPostfix); - return boundary; +std::string UploadJobImpl::RandomMimeBoundaryGenerator::GenerateBoundary() + const { + return net::GenerateMimeMultipartBoundary(); } UploadJobImpl::UploadJobImpl( @@ -236,30 +196,8 @@ bool UploadJobImpl::SetUpMultipart() { return false; } - // Generates random MIME boundaries and tests if they appear in any of the - // data segments. Tries up to |kMimeBoundaryRetries| times to find a MIME - // boundary that does not appear within any data segment. - bool found = false; - int retry = 0; - do { - found = true; - mime_boundary_.reset(new std::string( - boundary_generator_->GenerateBoundary(kMimeBoundarySize))); - for (const auto& data_segment : data_segments_) { - if (data_segment->CheckIfDataContains(*mime_boundary_)) { - found = false; - break; - } - } - ++retry; - } while (!found && retry <= kMimeBoundaryRetries); - - // Notify the delegate that content encoding failed. - if (!found) { - delegate_->OnFailure(CONTENT_ENCODING_ERROR); - mime_boundary_.reset(); - return false; - } + mime_boundary_.reset( + new std::string(boundary_generator_->GenerateBoundary())); // Estimate an upper bound for the total message size to make memory // allocation more efficient. It is not an error if this turns out to be too @@ -268,7 +206,7 @@ bool UploadJobImpl::SetUpMultipart() { for (const auto& data_segment : data_segments_) { for (const auto& entry : data_segment->GetHeaderEntries()) size += entry.first.size() + entry.second.size(); - size += kMimeBoundarySize + data_segment->GetName().size() + + size += kMaxMimeBoundarySize + data_segment->GetName().size() + data_segment->GetFilename().size() + data_segment->GetDataSize(); // Add some extra space for all the constants and control characters. size += 128; diff --git a/chrome/browser/chromeos/policy/upload_job_impl.h b/chrome/browser/chromeos/policy/upload_job_impl.h index 958eef3..7c7106f 100644 --- a/chrome/browser/chromeos/policy/upload_job_impl.h +++ b/chrome/browser/chromeos/policy/upload_job_impl.h @@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_CHROMEOS_POLICY_UPLOAD_JOB_IMPL_H_ #define CHROME_BROWSER_CHROMEOS_POLICY_UPLOAD_JOB_IMPL_H_ -#include <stddef.h> - #include <map> #include <string> @@ -36,7 +34,7 @@ class UploadJobImpl : public UploadJob, public: virtual ~MimeBoundaryGenerator(); - virtual std::string GenerateBoundary(size_t length) const = 0; + virtual std::string GenerateBoundary() const = 0; private: DISALLOW_ASSIGN(MimeBoundaryGenerator); @@ -48,8 +46,7 @@ class UploadJobImpl : public UploadJob, public: ~RandomMimeBoundaryGenerator() override; - std::string GenerateBoundary( - size_t length) const override; // MimeBoundaryGenerator + std::string GenerateBoundary() const override; // MimeBoundaryGenerator }; UploadJobImpl(const GURL& upload_url, diff --git a/chrome/browser/chromeos/policy/upload_job_unittest.cc b/chrome/browser/chromeos/policy/upload_job_unittest.cc index 85f88cb..bc5f5a9 100644 --- a/chrome/browser/chromeos/policy/upload_job_unittest.cc +++ b/chrome/browser/chromeos/policy/upload_job_unittest.cc @@ -51,8 +51,9 @@ class RepeatingMimeBoundaryGenerator ~RepeatingMimeBoundaryGenerator() override {} // MimeBoundaryGenerator: - std::string GenerateBoundary(size_t length) const override { - return std::string(length, character_); + std::string GenerateBoundary() const override { + const int kMimeBoundarySize = 32; + return std::string(kMimeBoundarySize, character_); } private: diff --git a/chrome/common/cloud_print/cloud_print_helpers.cc b/chrome/common/cloud_print/cloud_print_helpers.cc index 406c54b..6fcd8bd 100644 --- a/chrome/common/cloud_print/cloud_print_helpers.cc +++ b/chrome/common/cloud_print/cloud_print_helpers.cc @@ -12,7 +12,6 @@ #include "base/logging.h" #include "base/md5.h" #include "base/memory/scoped_ptr.h" -#include "base/rand_util.h" #include "base/strings/stringprintf.h" #include "base/sys_info.h" #include "base/values.h" @@ -207,13 +206,6 @@ std::string GetMultipartMimeType(const std::string& mime_boundary) { return std::string("multipart/form-data; boundary=") + mime_boundary; } -// Create a MIME boundary marker (27 '-' characters followed by 16 hex digits). -void CreateMimeBoundaryForUpload(std::string* out) { - int r1 = base::RandInt(0, std::numeric_limits<int32_t>::max()); - int r2 = base::RandInt(0, std::numeric_limits<int32_t>::max()); - base::SStringPrintf(out, "---------------------------%08X%08X", r1, r2); -} - std::string GetHashOfPrinterTags(const PrinterTags& printer_tags) { return HashPrinterTags(PreparePrinterTags(printer_tags)); } diff --git a/chrome/common/cloud_print/cloud_print_helpers.h b/chrome/common/cloud_print/cloud_print_helpers.h index 273e6d4..009fab6 100644 --- a/chrome/common/cloud_print/cloud_print_helpers.h +++ b/chrome/common/cloud_print/cloud_print_helpers.h @@ -70,9 +70,6 @@ scoped_ptr<base::DictionaryValue> ParseResponseJSON( // Returns the MIME type of multipart with |mime_boundary|. std::string GetMultipartMimeType(const std::string& mime_boundary); -// Create a MIME boundary marker (27 '-' characters followed by 16 hex digits). -void CreateMimeBoundaryForUpload(std::string *out); - // Returns an MD5 hash for |printer_tags| and the default required tags. std::string GetHashOfPrinterTags(const PrinterTags& printer_tags); diff --git a/chrome/service/cloud_print/cloud_print_connector.cc b/chrome/service/cloud_print/cloud_print_connector.cc index 731d9c9..1bec7b08 100644 --- a/chrome/service/cloud_print/cloud_print_connector.cc +++ b/chrome/service/cloud_print/cloud_print_connector.cc @@ -362,8 +362,7 @@ void CloudPrintConnector::ReportUserMessage(const std::string& message_id, const std::string& failure_msg) { // This is a fire and forget type of function. // Result of this request will be ignored. - std::string mime_boundary; - CreateMimeBoundaryForUpload(&mime_boundary); + std::string mime_boundary = net::GenerateMimeMultipartBoundary(); GURL url = GetUrlForUserMessage(settings_.server_url(), message_id); std::string post_data; net::AddMultipartValueForUpload(kMessageTextValue, failure_msg, mime_boundary, @@ -609,8 +608,7 @@ void CloudPrintConnector::OnReceivePrinterCaps( const printing::PrinterBasicInfo& info = pending_tasks_.front().printer_info; DCHECK(IsSamePrinter(info.printer_name, printer_name)); - std::string mime_boundary; - CreateMimeBoundaryForUpload(&mime_boundary); + std::string mime_boundary = net::GenerateMimeMultipartBoundary(); std::string post_data; net::AddMultipartValueForUpload(kProxyIdValue, diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index 2f255f9..a720d5e 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc @@ -684,8 +684,7 @@ void PrinterJobHandler::OnReceivePrinterCaps( printer_watcher_->GetCurrentPrinterInfo(&printer_info); std::string post_data; - std::string mime_boundary; - CreateMimeBoundaryForUpload(&mime_boundary); + std::string mime_boundary = net::GenerateMimeMultipartBoundary(); if (succeeded) { std::string caps_hash = diff --git a/cloud_print/gcp20/prototype/cloud_print_requester.cc b/cloud_print/gcp20/prototype/cloud_print_requester.cc index b32456c..ccae344 100644 --- a/cloud_print/gcp20/prototype/cloud_print_requester.cc +++ b/cloud_print/gcp20/prototype/cloud_print_requester.cc @@ -12,7 +12,6 @@ #include "base/json/json_writer.h" #include "base/md5.h" #include "base/message_loop/message_loop.h" -#include "base/rand_util.h" #include "base/strings/stringprintf.h" #include "cloud_print/gcp20/prototype/cloud_print_url_request_context_getter.h" #include "google_apis/google_api_keys.h" @@ -125,11 +124,7 @@ void CloudPrintRequester::StartRegistration(const std::string& proxy_id, const std::string& user, const LocalSettings& settings, const std::string& cdd) { - std::string mime_boundary; - int r1 = base::RandInt(0, std::numeric_limits<int32_t>::max()); - int r2 = base::RandInt(0, std::numeric_limits<int32_t>::max()); - base::SStringPrintf(&mime_boundary, - "---------------------------%08X%08X", r1, r2); + std::string mime_boundary = net::GenerateMimeMultipartBoundary(); std::string data; std::string data_mimetype; diff --git a/components/search_engines/template_url.cc b/components/search_engines/template_url.cc index a75779b..dcf45f8 100644 --- a/components/search_engines/template_url.cc +++ b/components/search_engines/template_url.cc @@ -14,7 +14,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/metrics/field_trial.h" -#include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" @@ -277,12 +276,9 @@ bool TemplateURLRef::EncodeFormData(const PostParams& post_params, return false; const char kUploadDataMIMEType[] = "multipart/form-data; boundary="; - const char kMultipartBoundary[] = "----+*+----%016" PRIx64 "----+*+----"; // Each name/value pair is stored in a body part which is preceded by a - // boundary delimiter line. Uses random number generator here to create - // a unique boundary delimiter for form data encoding. - std::string boundary = base::StringPrintf(kMultipartBoundary, - base::RandUint64()); + // boundary delimiter line. + std::string boundary = net::GenerateMimeMultipartBoundary(); // Sets the content MIME type. post_content->first = kUploadDataMIMEType; post_content->first += boundary; diff --git a/content/browser/download/mhtml_generation_manager.cc b/content/browser/download/mhtml_generation_manager.cc index 792e019..ef92023 100644 --- a/content/browser/download/mhtml_generation_manager.cc +++ b/content/browser/download/mhtml_generation_manager.cc @@ -12,10 +12,8 @@ #include "base/files/file.h" #include "base/guid.h" #include "base/macros.h" -#include "base/rand_util.h" #include "base/scoped_observer.h" #include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "content/browser/bad_message.h" #include "content/browser/frame_host/frame_tree_node.h" @@ -26,6 +24,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host_observer.h" #include "content/public/browser/web_contents.h" +#include "net/base/mime_util.h" namespace content { @@ -73,7 +72,6 @@ class MHTMLGenerationManager::Job : public RenderProcessHostObserver { void RenderProcessHostDestroyed(RenderProcessHost* host) override; private: - static std::string GenerateMHTMLBoundaryMarker(); static int64_t CloseFileOnFileThread(base::File file); void AddFrame(RenderFrameHost* render_frame_host); @@ -124,7 +122,7 @@ MHTMLGenerationManager::Job::Job(int job_id, GenerateMHTMLCallback callback) : job_id_(job_id), frame_tree_node_id_of_busy_frame_(FrameTreeNode::kFrameTreeNodeInvalidId), - mhtml_boundary_marker_(GenerateMHTMLBoundaryMarker()), + mhtml_boundary_marker_(net::GenerateMimeMultipartBoundary()), salt_(base::GenerateGUID()), callback_(callback), observed_renderer_process_host_(this) { @@ -280,25 +278,6 @@ int64_t MHTMLGenerationManager::Job::CloseFileOnFileThread(base::File file) { return file_size; } -// static -std::string MHTMLGenerationManager::Job::GenerateMHTMLBoundaryMarker() { - // TODO(lukasza): Introduce and use a shared helper function in - // net/base/mime_util.h instead of having the ad-hoc code below. - - // Trying to generate random boundaries similar to IE/UnMHT - // (ex: ----=_NextPart_000_001B_01CC157B.96F808A0). - uint8_t random_values[10]; - base::RandBytes(random_values, sizeof(random_values)); - - std::string result("----=_NextPart_000_"); - result += base::HexEncode(random_values + 0, 2); - result += '_'; - result += base::HexEncode(random_values + 2, 4); - result += '.'; - result += base::HexEncode(random_values + 6, 4); - return result; -} - MHTMLGenerationManager* MHTMLGenerationManager::GetInstance() { return base::Singleton<MHTMLGenerationManager>::get(); } diff --git a/google_apis/drive/base_requests.cc b/google_apis/drive/base_requests.cc index 3e5b0d1..8a4e38b 100644 --- a/google_apis/drive/base_requests.cc +++ b/google_apis/drive/base_requests.cc @@ -12,7 +12,6 @@ #include "base/json/json_writer.h" #include "base/location.h" #include "base/macros.h" -#include "base/rand_util.h" #include "base/sequenced_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -27,6 +26,7 @@ #include "net/base/elements_upload_data_stream.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" +#include "net/base/mime_util.h" #include "net/base/net_errors.h" #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" @@ -76,13 +76,6 @@ const char kMultipartItemHeaderFormat[] = "--%s\nContent-Type: %s\n\n"; // Footer for whole multipart message. const char kMultipartFooterFormat[] = "--%s--"; -// Characters to be used for multipart/related boundary. -const char kBoundaryCharacters[] = - "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -// Size of multipart/related's boundary. -const char kBoundarySize = 70; - // Parses JSON passed in |json| on |blocking_task_runner|. Runs |callback| on // the calling thread when finished with either success or failure. // The callback must not be null. @@ -227,13 +220,7 @@ void GenerateMultipartBody(MultipartType multipart_type, // Generate random boundary. if (predetermined_boundary.empty()) { while (true) { - boundary.resize(kBoundarySize); - for (int i = 0; i < kBoundarySize; ++i) { - // Subtract 2 from the array size to exclude '\0', and to turn the size - // into the last index. - const int last_char_index = arraysize(kBoundaryCharacters) - 2; - boundary[i] = kBoundaryCharacters[base::RandInt(0, last_char_index)]; - } + boundary = net::GenerateMimeMultipartBoundary(); bool conflict_with_content = false; for (auto& part : parts) { if (part.data.find(boundary, 0) != std::string::npos) { diff --git a/google_apis/drive/drive_api_requests_unittest.cc b/google_apis/drive/drive_api_requests_unittest.cc index 0912d61..3200339 100644 --- a/google_apis/drive/drive_api_requests_unittest.cc +++ b/google_apis/drive/drive_api_requests_unittest.cc @@ -2141,7 +2141,7 @@ TEST_F(DriveApiRequestsTest, BatchUploadRequestProgress) { new TestBatchableDelegate(GURL("http://example.com/test"), "application/binary", std::string(0, 'c'), base::Bind(&EmptyClosure))}; - const size_t kExpectedUploadDataPosition[] = {208, 517, 776}; + const size_t kExpectedUploadDataPosition[] = {207, 515, 773}; const size_t kExpectedUploadDataSize = 851; request->AddRequest(requests[0]); request->AddRequest(requests[1]); 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[] = diff --git a/third_party/WebKit/Source/platform/network/FormDataEncoder.cpp b/third_party/WebKit/Source/platform/network/FormDataEncoder.cpp index e66bf81..0b73501 100644 --- a/third_party/WebKit/Source/platform/network/FormDataEncoder.cpp +++ b/third_party/WebKit/Source/platform/network/FormDataEncoder.cpp @@ -99,6 +99,7 @@ WTF::TextEncoding FormDataEncoder::encodingFromAcceptCharset(const String& accep return charset; } +// TODO(lukasza): Reuse net::GenerateMimeMultipartBoundary instead. Vector<char> FormDataEncoder::generateUniqueBoundaryString() { Vector<char> boundary; |