1*1a96fba6SXin Li // Copyright 2014 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li
5*1a96fba6SXin Li #include <brillo/mime_utils.h>
6*1a96fba6SXin Li
7*1a96fba6SXin Li #include <algorithm>
8*1a96fba6SXin Li #include <base/strings/string_util.h>
9*1a96fba6SXin Li #include <brillo/strings/string_utils.h>
10*1a96fba6SXin Li
11*1a96fba6SXin Li namespace brillo {
12*1a96fba6SXin Li
13*1a96fba6SXin Li // ***************************************************************************
14*1a96fba6SXin Li // ******************************* MIME types ********************************
15*1a96fba6SXin Li // ***************************************************************************
16*1a96fba6SXin Li const char mime::types::kApplication[] = "application";
17*1a96fba6SXin Li const char mime::types::kAudio[] = "audio";
18*1a96fba6SXin Li const char mime::types::kImage[] = "image";
19*1a96fba6SXin Li const char mime::types::kMessage[] = "message";
20*1a96fba6SXin Li const char mime::types::kMultipart[] = "multipart";
21*1a96fba6SXin Li const char mime::types::kText[] = "text";
22*1a96fba6SXin Li const char mime::types::kVideo[] = "video";
23*1a96fba6SXin Li
24*1a96fba6SXin Li const char mime::parameters::kCharset[] = "charset";
25*1a96fba6SXin Li
26*1a96fba6SXin Li const char mime::image::kJpeg[] = "image/jpeg";
27*1a96fba6SXin Li const char mime::image::kPng[] = "image/png";
28*1a96fba6SXin Li const char mime::image::kBmp[] = "image/bmp";
29*1a96fba6SXin Li const char mime::image::kTiff[] = "image/tiff";
30*1a96fba6SXin Li const char mime::image::kGif[] = "image/gif";
31*1a96fba6SXin Li
32*1a96fba6SXin Li const char mime::text::kPlain[] = "text/plain";
33*1a96fba6SXin Li const char mime::text::kHtml[] = "text/html";
34*1a96fba6SXin Li const char mime::text::kXml[] = "text/xml";
35*1a96fba6SXin Li
36*1a96fba6SXin Li const char mime::application::kOctet_stream[] = "application/octet-stream";
37*1a96fba6SXin Li const char mime::application::kJson[] = "application/json";
38*1a96fba6SXin Li const char mime::application::kWwwFormUrlEncoded[] =
39*1a96fba6SXin Li "application/x-www-form-urlencoded";
40*1a96fba6SXin Li const char mime::application::kProtobuf[] = "application/x-protobuf";
41*1a96fba6SXin Li
42*1a96fba6SXin Li const char mime::multipart::kFormData[] = "multipart/form-data";
43*1a96fba6SXin Li const char mime::multipart::kMixed[] = "multipart/mixed";
44*1a96fba6SXin Li
45*1a96fba6SXin Li // ***************************************************************************
46*1a96fba6SXin Li // **************************** Utility Functions ****************************
47*1a96fba6SXin Li // ***************************************************************************
EncodeParam(const std::string & param)48*1a96fba6SXin Li static std::string EncodeParam(const std::string& param) {
49*1a96fba6SXin Li // If the string contains one of "tspecials" characters as
50*1a96fba6SXin Li // specified in RFC 1521, enclose it in quotes.
51*1a96fba6SXin Li if (param.find_first_of("()<>@,;:\\\"/[]?=") != std::string::npos) {
52*1a96fba6SXin Li return '"' + param + '"';
53*1a96fba6SXin Li }
54*1a96fba6SXin Li return param;
55*1a96fba6SXin Li }
56*1a96fba6SXin Li
DecodeParam(const std::string & param)57*1a96fba6SXin Li static std::string DecodeParam(const std::string& param) {
58*1a96fba6SXin Li if (param.size() > 1 && param.front() == '"' && param.back() == '"') {
59*1a96fba6SXin Li return param.substr(1, param.size() - 2);
60*1a96fba6SXin Li }
61*1a96fba6SXin Li return param;
62*1a96fba6SXin Li }
63*1a96fba6SXin Li
64*1a96fba6SXin Li // ***************************************************************************
65*1a96fba6SXin Li // ******************** Main MIME manipulation functions *********************
66*1a96fba6SXin Li // ***************************************************************************
67*1a96fba6SXin Li
Split(const std::string & mime_string,std::string * type,std::string * subtype,mime::Parameters * parameters)68*1a96fba6SXin Li bool mime::Split(const std::string& mime_string,
69*1a96fba6SXin Li std::string* type,
70*1a96fba6SXin Li std::string* subtype,
71*1a96fba6SXin Li mime::Parameters* parameters) {
72*1a96fba6SXin Li std::vector<std::string> parts =
73*1a96fba6SXin Li brillo::string_utils::Split(mime_string, ";");
74*1a96fba6SXin Li if (parts.empty())
75*1a96fba6SXin Li return false;
76*1a96fba6SXin Li
77*1a96fba6SXin Li if (!mime::Split(parts.front(), type, subtype))
78*1a96fba6SXin Li return false;
79*1a96fba6SXin Li
80*1a96fba6SXin Li if (parameters) {
81*1a96fba6SXin Li parameters->clear();
82*1a96fba6SXin Li parameters->reserve(parts.size() - 1);
83*1a96fba6SXin Li for (size_t i = 1; i < parts.size(); i++) {
84*1a96fba6SXin Li auto pair = brillo::string_utils::SplitAtFirst(parts[i], "=");
85*1a96fba6SXin Li pair.second = DecodeParam(pair.second);
86*1a96fba6SXin Li parameters->push_back(pair);
87*1a96fba6SXin Li }
88*1a96fba6SXin Li }
89*1a96fba6SXin Li return true;
90*1a96fba6SXin Li }
91*1a96fba6SXin Li
Split(const std::string & mime_string,std::string * type,std::string * subtype)92*1a96fba6SXin Li bool mime::Split(const std::string& mime_string,
93*1a96fba6SXin Li std::string* type,
94*1a96fba6SXin Li std::string* subtype) {
95*1a96fba6SXin Li std::string mime = mime::RemoveParameters(mime_string);
96*1a96fba6SXin Li auto types = brillo::string_utils::SplitAtFirst(mime, "/");
97*1a96fba6SXin Li
98*1a96fba6SXin Li if (type)
99*1a96fba6SXin Li *type = types.first;
100*1a96fba6SXin Li
101*1a96fba6SXin Li if (subtype)
102*1a96fba6SXin Li *subtype = types.second;
103*1a96fba6SXin Li
104*1a96fba6SXin Li return !types.first.empty() && !types.second.empty();
105*1a96fba6SXin Li }
106*1a96fba6SXin Li
Combine(const std::string & type,const std::string & subtype,const mime::Parameters & parameters)107*1a96fba6SXin Li std::string mime::Combine(const std::string& type,
108*1a96fba6SXin Li const std::string& subtype,
109*1a96fba6SXin Li const mime::Parameters& parameters) {
110*1a96fba6SXin Li std::vector<std::string> parts;
111*1a96fba6SXin Li parts.push_back(brillo::string_utils::Join("/", type, subtype));
112*1a96fba6SXin Li for (const auto& pair : parameters) {
113*1a96fba6SXin Li parts.push_back(
114*1a96fba6SXin Li brillo::string_utils::Join("=", pair.first, EncodeParam(pair.second)));
115*1a96fba6SXin Li }
116*1a96fba6SXin Li return brillo::string_utils::Join("; ", parts);
117*1a96fba6SXin Li }
118*1a96fba6SXin Li
GetType(const std::string & mime_string)119*1a96fba6SXin Li std::string mime::GetType(const std::string& mime_string) {
120*1a96fba6SXin Li std::string mime = mime::RemoveParameters(mime_string);
121*1a96fba6SXin Li return brillo::string_utils::SplitAtFirst(mime, "/").first;
122*1a96fba6SXin Li }
123*1a96fba6SXin Li
GetSubtype(const std::string & mime_string)124*1a96fba6SXin Li std::string mime::GetSubtype(const std::string& mime_string) {
125*1a96fba6SXin Li std::string mime = mime::RemoveParameters(mime_string);
126*1a96fba6SXin Li return brillo::string_utils::SplitAtFirst(mime, "/").second;
127*1a96fba6SXin Li }
128*1a96fba6SXin Li
GetParameters(const std::string & mime_string)129*1a96fba6SXin Li mime::Parameters mime::GetParameters(const std::string& mime_string) {
130*1a96fba6SXin Li std::string type;
131*1a96fba6SXin Li std::string subtype;
132*1a96fba6SXin Li mime::Parameters parameters;
133*1a96fba6SXin Li
134*1a96fba6SXin Li if (mime::Split(mime_string, &type, &subtype, ¶meters))
135*1a96fba6SXin Li return parameters;
136*1a96fba6SXin Li
137*1a96fba6SXin Li return mime::Parameters();
138*1a96fba6SXin Li }
139*1a96fba6SXin Li
RemoveParameters(const std::string & mime_string)140*1a96fba6SXin Li std::string mime::RemoveParameters(const std::string& mime_string) {
141*1a96fba6SXin Li return brillo::string_utils::SplitAtFirst(mime_string, ";").first;
142*1a96fba6SXin Li }
143*1a96fba6SXin Li
AppendParameter(const std::string & mime_string,const std::string & paramName,const std::string & paramValue)144*1a96fba6SXin Li std::string mime::AppendParameter(const std::string& mime_string,
145*1a96fba6SXin Li const std::string& paramName,
146*1a96fba6SXin Li const std::string& paramValue) {
147*1a96fba6SXin Li std::string mime(mime_string);
148*1a96fba6SXin Li mime += "; ";
149*1a96fba6SXin Li mime += brillo::string_utils::Join("=", paramName, EncodeParam(paramValue));
150*1a96fba6SXin Li return mime;
151*1a96fba6SXin Li }
152*1a96fba6SXin Li
GetParameterValue(const std::string & mime_string,const std::string & paramName)153*1a96fba6SXin Li std::string mime::GetParameterValue(const std::string& mime_string,
154*1a96fba6SXin Li const std::string& paramName) {
155*1a96fba6SXin Li mime::Parameters params = mime::GetParameters(mime_string);
156*1a96fba6SXin Li for (const auto& pair : params) {
157*1a96fba6SXin Li if (base::EqualsCaseInsensitiveASCII(pair.first.c_str(), paramName.c_str()))
158*1a96fba6SXin Li return pair.second;
159*1a96fba6SXin Li }
160*1a96fba6SXin Li return std::string();
161*1a96fba6SXin Li }
162*1a96fba6SXin Li
163*1a96fba6SXin Li } // namespace brillo
164