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