blob: 2e6f3238009b0b6554b920ef9c17f06531b92a84 [file]
// 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.
#ifndef NET_HTTP_HTTP_CONTENT_DISPOSITION_H_
#define NET_HTTP_HTTP_CONTENT_DISPOSITION_H_
#include <string>
#include <string_view>
#include "net/base/net_export.h"
namespace net {
class HttpResponseHeaders;
class NET_EXPORT HttpContentDisposition {
public:
enum Type {
INLINE,
ATTACHMENT,
};
// Properties of the Content-Disposition header. These flags are used to
// report download metrics in UMA. This enum isn't directly used in UMA but
// mapped to another one for binary compatiblity; ie. changes are OK.
enum ParseResultFlags {
INVALID = 0,
// A valid disposition-type is present.
HAS_DISPOSITION_TYPE = 1 << 0,
// The disposition-type is not 'inline' or 'attachment'.
HAS_UNKNOWN_DISPOSITION_TYPE = 1 << 1,
// Has a valid non-empty 'filename' attribute.
HAS_FILENAME = 1 << 2,
// Has a valid non-empty 'filename*' attribute.
HAS_EXT_FILENAME = 1 << 3,
// The following fields are properties of the 'filename' attribute:
// Quoted-string contains non-ASCII characters.
HAS_NON_ASCII_STRINGS = 1 << 4,
// Quoted-string contains percent-encoding.
HAS_PERCENT_ENCODED_STRINGS = 1 << 5,
// Quoted-string contains RFC 2047 encoded words.
HAS_RFC2047_ENCODED_STRINGS = 1 << 6,
// Has a filename that starts with a single quote.
HAS_SINGLE_QUOTED_FILENAME = 1 << 7,
};
// NOTE: Until features::kOnlyParseFirstContentDisposition is removed, new
// consumers should use EnumerateHeader() to get the first Content-Disposition
// header and then pass it to the constructor that takes a std::string_view.
// Once that's removed, however, this constructor should be used. This comment
// should be removed when that happens.
// TODO(crbug.com/519218483): Remove this comment in late Q3/Q4 2026, when
// the feature is removed.
//
// Preferred constructor. Uses the first Content-Disposition header in the
// response (retrieved using `HttpResponseHeaders::EnumerateHeader`). Only
// looks at the first Content-Disposition header. The HTTP code guarantees
// that if there are multiple Content-Disposition fields, they're all
// identical, but that might not be the case if they come from other sources
// (e.g., data URLs, extensions).
//
// Note that no Content-Disposition header or an empty header results in an
// inline type with no filename.
HttpContentDisposition(const HttpResponseHeaders& headers,
const std::string& referrer_charset);
// Overload for the case when an HttpResponseHeaders is not available. While
// both overloads behave the same, please use the first constructor if
// possible, to avoid having to pull out the right header from
// HttpResponseHeaders, and for somewhat improved performance. Can be called
// either on the first header only, or all headers merged together and
// separated by commas (and will return the same result). Should not be called
// directly on Content-Disposition headers after the first one, even if the
// first one is invalid.
HttpContentDisposition(std::string_view header,
const std::string& referrer_charset);
HttpContentDisposition(const HttpContentDisposition&) = delete;
HttpContentDisposition& operator=(const HttpContentDisposition&) = delete;
~HttpContentDisposition();
bool is_attachment() const { return type() == ATTACHMENT; }
Type type() const { return type_; }
const std::string& filename() const { return filename_; }
// A combination of ParseResultFlags values.
int parse_result_flags() const { return parse_result_flags_; }
private:
void Parse(std::string_view header, const std::string& referrer_charset);
// Parses the content disposition type, if present, and sets `type_`. Returns
// `header` with the content disposition type removed.
std::string_view ConsumeDispositionType(std::string_view header);
Type type_ = INLINE;
std::string filename_;
int parse_result_flags_ = INVALID;
};
} // namespace net
#endif // NET_HTTP_HTTP_CONTENT_DISPOSITION_H_