chromium/net/base/mime_util.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/mime_util.h"

#include <algorithm>
#include <iterator>
#include <map>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_set>

#include "base/base64.h"
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/lazy_instance.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "net/base/platform_mime_util.h"
#include "net/http/http_util.h"

string;

namespace net {

// Singleton utility class for mime types.
class MimeUtil : public PlatformMimeUtil {};  // class MimeUtil

// This variable is Leaky because we need to access it from WorkerPool threads.
static base::LazyInstance<MimeUtil>::Leaky g_mime_util =;

struct MimeInfo {};

// How to use the MIME maps
// ------------------------
// READ THIS BEFORE MODIFYING THE MIME MAPPINGS BELOW.
//
// There are two hardcoded mappings from MIME types: kPrimaryMappings and
// kSecondaryMappings.
//
// kPrimaryMappings:
//
//   Use this for mappings that are critical to the web platform.  Mappings you
//   add to this list take priority over the underlying platform when converting
//   from file extension -> MIME type.  Thus file extensions listed here will
//   work consistently across platforms.
//
// kSecondaryMappings:
//
//   Use this for mappings that must exist, but can be overridden by user
//   preferences.
//
// The following applies to both lists:
//
// * The same extension can appear multiple times in the same list under
//   different MIME types.  Extensions that appear earlier take precedence over
//   those that appear later.
//
// * A MIME type must not appear more than once in a single list.  It is valid
//   for the same MIME type to appear in kPrimaryMappings and
//   kSecondaryMappings.
//
// The MIME maps are used for three types of lookups:
//
// 1) MIME type -> file extension.  Implemented as
//    GetPreferredExtensionForMimeType().
//
//    Sources are consulted in the following order:
//
//    a) As a special case application/octet-stream is mapped to nothing.  Web
//       sites are supposed to use this MIME type to indicate that the content
//       is opaque and shouldn't be parsed as any specific type of content.  It
//       doesn't make sense to map this to anything.
//
//    b) The underlying platform.  If the operating system has a mapping from
//       the MIME type to a file extension, then that takes priority.  The
//       platform is assumed to represent the user's preference.
//
//    c) kPrimaryMappings.  Order doesn't matter since there should only be at
//       most one entry per MIME type.
//
//    d) kSecondaryMappings.  Again, order doesn't matter.
//
// 2) File extension -> MIME type.  Implemented in GetMimeTypeFromExtension().
//
//    Sources are considered in the following order:
//
//    a) kPrimaryMappings.  Order matters here since file extensions can appear
//       multiple times on these lists.  The first mapping in order of
//       appearance in the list wins.
//
//    b) Underlying platform.
//
//    c) kSecondaryMappings.  Again, the order matters.
//
// 3) File extension -> Well known MIME type.  Implemented as
//    GetWellKnownMimeTypeFromExtension().
//
//    This is similar to 2), with the exception that b) is skipped.  I.e.  Only
//    considers the hardcoded mappings in kPrimaryMappings and
//    kSecondaryMappings.

// See comments above for details on how this list is used.
static const MimeInfo kPrimaryMappings[] =;

// See comments above for details on how this list is used.
static const MimeInfo kSecondaryMappings[] =;

// Finds mime type of |ext| from |mappings|.
template <size_t num_mappings>
static std::optional<std::string_view> FindMimeType(
    const MimeInfo (&mappings)[num_mappings],
    const std::string& ext) {}

static base::FilePath::StringType StringToFilePathStringType(
    std::string_view string_piece) {}

// Helper used in MimeUtil::GetPreferredExtensionForMimeType() to search
// preferred extension in MimeInfo arrays.
template <size_t num_mappings>
static bool FindPreferredExtension(const MimeInfo (&mappings)[num_mappings],
                                   const std::string& mime_type,
                                   base::FilePath::StringType* result) {}

bool MimeUtil::GetMimeTypeFromExtension(const base::FilePath::StringType& ext,
                                        string* result) const {}

bool MimeUtil::GetWellKnownMimeTypeFromExtension(
    const base::FilePath::StringType& ext,
    string* result) const {}

bool MimeUtil::GetPreferredExtensionForMimeType(
    const std::string& mime_type,
    base::FilePath::StringType* extension) const {}

bool MimeUtil::GetMimeTypeFromFile(const base::FilePath& file_path,
                                   string* result) const {}

bool MimeUtil::GetMimeTypeFromExtensionHelper(
    const base::FilePath::StringType& ext,
    bool include_platform_types,
    string* result) const {}

MimeUtil::MimeUtil() = default;

// Tests for MIME parameter equality. Each parameter in the |mime_type_pattern|
// must be matched by a parameter in the |mime_type|. If there are no
// parameters in the pattern, the match is a success.
//
// According rfc2045 keys of parameters are case-insensitive, while values may
// or may not be case-sensitive, but they are usually case-sensitive. So, this
// function matches values in *case-sensitive* manner, however note that this
// may produce some false negatives.
bool MatchesMimeTypeParameters(std::string_view mime_type_pattern,
                               std::string_view mime_type) {}

// This comparison handles absolute maching and also basic
// wildcards.  The plugin mime types could be:
//      application/x-foo
//      application/*
//      application/*+xml
//      *
// Also tests mime parameters -- all parameters in the pattern must be present
// in the tested type for a match to succeed.
bool MimeUtil::MatchesMimeType(std::string_view mime_type_pattern,
                               std::string_view mime_type) const {}

bool ParseMimeType(const std::string& type_str,
                   std::string* mime_type,
                   base::StringPairs* params) {}

bool MimeUtil::ParseMimeTypeWithoutParameter(std::string_view type_string,
                                             std::string* top_level_type,
                                             std::string* subtype) const {}

// See https://www.iana.org/assignments/media-types/media-types.xhtml
static const char* const kLegalTopLevelTypes[] =;

bool MimeUtil::IsValidTopLevelMimeType(const std::string& type_string) const {}

//----------------------------------------------------------------------------
// Wrappers for the singleton
//----------------------------------------------------------------------------

bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext,
                              std::string* mime_type) {}

bool GetMimeTypeFromFile(const base::FilePath& file_path,
                         std::string* mime_type) {}

bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext,
                                       std::string* mime_type) {}

bool GetPreferredExtensionForMimeType(const std::string& mime_type,
                                      base::FilePath::StringType* extension) {}

bool MatchesMimeType(std::string_view mime_type_pattern,
                     std::string_view mime_type) {}

bool ParseMimeTypeWithoutParameter(std::string_view type_string,
                                   std::string* top_level_type,
                                   std::string* subtype) {}

bool IsValidTopLevelMimeType(const std::string& type_string) {}

namespace {

// From http://www.w3schools.com/media/media_mimeref.asp and
// http://plugindoc.mozdev.org/winmime.php
static const char* const kStandardImageTypes[] =;
static const char* const kStandardAudioTypes[] =;
// https://tools.ietf.org/html/rfc8081
static const char* const kStandardFontTypes[] =;
static const char* const kStandardVideoTypes[] =;

struct StandardType {};
static const StandardType kStandardTypes[] =;

// GetExtensionsFromHardCodedMappings() adds file extensions (without a leading
// dot) to the set |extensions|, for all MIME types matching |mime_type|.
//
// The meaning of |mime_type| depends on the value of |prefix_match|:
//
//  * If |prefix_match = false| then |mime_type| is an exact (case-insensitive)
//    string such as "text/plain".
//
//  * If |prefix_match = true| then |mime_type| is treated as the prefix for a
//    (case-insensitive) string. For instance "Text/" would match "text/plain".
void GetExtensionsFromHardCodedMappings(
    base::span<const MimeInfo> mappings,
    const std::string& mime_type,
    bool prefix_match,
    std::unordered_set<base::FilePath::StringType>* extensions) {}

void GetExtensionsHelper(
    base::span<const char* const> standard_types,
    const std::string& leading_mime_type,
    std::unordered_set<base::FilePath::StringType>* extensions) {}

// Note that the elements in the source set will be appended to the target
// vector.
template <class T>
void UnorderedSetToVector(std::unordered_set<T>* source,
                          std::vector<T>* target) {}

// Characters to be used for mime multipart boundary.
//
// TODO(rsleevi): crbug.com/575779: Follow the spec or fix the spec.
// 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: (),./:=+
constexpr std::string_view kMimeBoundaryCharacters(
    "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");

// Size of mime multipart boundary.
const size_t kMimeBoundarySize =;

}  // namespace

void GetExtensionsForMimeType(
    const std::string& unsafe_mime_type,
    std::vector<base::FilePath::StringType>* extensions) {}

NET_EXPORT std::string GenerateMimeMultipartBoundary() {}

void AddMultipartValueForUpload(const std::string& value_name,
                                const std::string& value,
                                const std::string& mime_boundary,
                                const std::string& content_type,
                                std::string* post_data) {}

void AddMultipartValueForUploadWithFileName(const std::string& value_name,
                                            const std::string& file_name,
                                            const std::string& value,
                                            const std::string& mime_boundary,
                                            const std::string& content_type,
                                            std::string* post_data) {}

void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary,
                                         std::string* post_data) {}

// TODO(toyoshim): We may prefer to implement a strict RFC2616 media-type
// (https://tools.ietf.org/html/rfc2616#section-3.7) parser.
std::optional<std::string> ExtractMimeTypeFromMediaType(
    const std::string& type_string,
    bool accept_comma_separated) {}

}  // namespace net