xref: /aosp_15_r20/external/libbrillo/brillo/mime_utils.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
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, &parameters))
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