blob: dc574978faad3f922e6c20428213aada7522515b [file] [log] [blame]
Chris Sosa45d9f102014-03-24 11:18:54 -07001// 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 "buffet/mime_utils.h"
6
7#include <algorithm>
8#include <base/strings/string_util.h>
9
10#include "buffet/string_utils.h"
11
Alex Vakulenkoaf23b322014-05-08 16:25:45 -070012namespace buffet {
Chris Sosa45d9f102014-03-24 11:18:54 -070013
Alex Vakulenkoaf23b322014-05-08 16:25:45 -070014// ***************************************************************************
15// ******************************* MIME types ********************************
16// ***************************************************************************
Chris Sosa45d9f102014-03-24 11:18:54 -070017const char mime::types::kApplication[] = "application";
18const char mime::types::kAudio[] = "audio";
19const char mime::types::kImage[] = "image";
20const char mime::types::kMessage[] = "message";
21const char mime::types::kMultipart[] = "multipart";
22const char mime::types::kText[] = "text";
23const char mime::types::kVideo[] = "video";
24
25const char mime::parameters::kCharset[] = "charset";
26
27const char mime::image::kJpeg[] = "image/jpeg";
28const char mime::image::kPng[] = "image/png";
29const char mime::image::kBmp[] = "image/bmp";
30const char mime::image::kTiff[] = "image/tiff";
31const char mime::image::kGif[] = "image/gif";
32
33const char mime::text::kPlain[] = "text/plain";
34const char mime::text::kHtml[] = "text/html";
35const char mime::text::kXml[] = "text/xml";
36
37const char mime::application::kOctet_stream[] = "application/octet-stream";
38const char mime::application::kJson[] = "application/json";
39const char mime::application::kWwwFormUrlEncoded[] =
40 "application/x-www-form-urlencoded";
41
Alex Vakulenkoaf23b322014-05-08 16:25:45 -070042// ***************************************************************************
43// **************************** Utility Functions ****************************
44// ***************************************************************************
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070045static std::string EncodeParam(const std::string& param) {
Chris Sosa45d9f102014-03-24 11:18:54 -070046 // If the string contains one of "tspecials" characters as
47 // specified in RFC 1521, enclose it in quotes.
48 if (param.find_first_of("()<>@,;:\\\"/[]?=") != std::string::npos) {
49 return '"' + param + '"';
50 }
51 return param;
52}
53
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070054static std::string DecodeParam(const std::string& param) {
Chris Sosa45d9f102014-03-24 11:18:54 -070055 if (param.size() > 1 && param.front() == '"' && param.back() == '"') {
56 return param.substr(1, param.size() - 2);
57 }
58 return param;
59}
60
Alex Vakulenkoaf23b322014-05-08 16:25:45 -070061// ***************************************************************************
62// ******************** Main MIME manipulation functions *********************
63// ***************************************************************************
Chris Sosa45d9f102014-03-24 11:18:54 -070064
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070065bool mime::Split(const std::string& mime_string,
Chris Sosa45d9f102014-03-24 11:18:54 -070066 std::string* type, std::string* subtype,
67 mime::Parameters* parameters) {
68 std::vector<std::string> parts = string_utils::Split(mime_string, ';');
69 if (parts.empty())
70 return false;
71
72 if (!mime::Split(parts.front(), type, subtype))
73 return false;
74
Alex Vakulenkoaf23b322014-05-08 16:25:45 -070075 if (parameters) {
Chris Sosa45d9f102014-03-24 11:18:54 -070076 parameters->clear();
77 parameters->reserve(parts.size() - 1);
78 for (size_t i = 1; i < parts.size(); i++) {
79 auto pair = string_utils::SplitAtFirst(parts[i], '=');
80 pair.second = DecodeParam(pair.second);
81 parameters->push_back(pair);
82 }
83 }
84 return true;
85}
86
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070087bool mime::Split(const std::string& mime_string,
Chris Sosa45d9f102014-03-24 11:18:54 -070088 std::string* type, std::string* subtype) {
89 std::string mime = mime::RemoveParameters(mime_string);
90 auto types = string_utils::SplitAtFirst(mime, '/');
91
Alex Vakulenkoaf23b322014-05-08 16:25:45 -070092 if (type)
Chris Sosa45d9f102014-03-24 11:18:54 -070093 *type = types.first;
94
Alex Vakulenkoaf23b322014-05-08 16:25:45 -070095 if (subtype)
Chris Sosa45d9f102014-03-24 11:18:54 -070096 *subtype = types.second;
97
98 return !types.first.empty() && !types.second.empty();
99}
100
Alex Vakulenkob8ba5952014-04-17 11:35:56 -0700101std::string mime::Combine(const std::string& type, const std::string& subtype,
102 const mime::Parameters& parameters) {
Chris Sosa45d9f102014-03-24 11:18:54 -0700103 std::vector<std::string> parts;
104 parts.push_back(string_utils::Join('/', type, subtype));
Alex Vakulenkoa0424dd2014-06-13 16:10:17 -0700105 for (const auto& pair : parameters) {
Chris Sosa45d9f102014-03-24 11:18:54 -0700106 parts.push_back(string_utils::Join('=', pair.first,
107 EncodeParam(pair.second)));
108 }
109 return string_utils::Join("; ", parts);
110}
111
Alex Vakulenkob8ba5952014-04-17 11:35:56 -0700112std::string mime::GetType(const std::string& mime_string) {
Chris Sosa45d9f102014-03-24 11:18:54 -0700113 std::string mime = mime::RemoveParameters(mime_string);
114 return string_utils::SplitAtFirst(mime, '/').first;
115}
116
Alex Vakulenkob8ba5952014-04-17 11:35:56 -0700117std::string mime::GetSubtype(const std::string& mime_string) {
Chris Sosa45d9f102014-03-24 11:18:54 -0700118 std::string mime = mime::RemoveParameters(mime_string);
119 return string_utils::SplitAtFirst(mime, '/').second;
120}
121
Alex Vakulenkob8ba5952014-04-17 11:35:56 -0700122mime::Parameters mime::GetParameters(const std::string& mime_string) {
Chris Sosa45d9f102014-03-24 11:18:54 -0700123 std::string type;
124 std::string subtype;
125 mime::Parameters parameters;
126
127 if (mime::Split(mime_string, &type, &subtype, &parameters))
128 return std::move(parameters);
129
130 return mime::Parameters();
131}
132
Alex Vakulenkob8ba5952014-04-17 11:35:56 -0700133std::string mime::RemoveParameters(const std::string& mime_string) {
Chris Sosa45d9f102014-03-24 11:18:54 -0700134 return string_utils::SplitAtFirst(mime_string, ';').first;
135}
136
Alex Vakulenkob8ba5952014-04-17 11:35:56 -0700137std::string mime::AppendParameter(const std::string& mime_string,
138 const std::string& paramName,
139 const std::string& paramValue) {
Chris Sosa45d9f102014-03-24 11:18:54 -0700140 std::string mime(mime_string);
141 mime += "; ";
142 mime += string_utils::Join('=', paramName, EncodeParam(paramValue));
143 return mime;
144}
145
Alex Vakulenkob8ba5952014-04-17 11:35:56 -0700146std::string mime::GetParameterValue(const std::string& mime_string,
147 const std::string& paramName) {
Chris Sosa45d9f102014-03-24 11:18:54 -0700148 mime::Parameters params = mime::GetParameters(mime_string);
Alex Vakulenkoa0424dd2014-06-13 16:10:17 -0700149 for (const auto& pair : params) {
Chris Sosa45d9f102014-03-24 11:18:54 -0700150 if (base::strcasecmp(pair.first.c_str(), paramName.c_str()) == 0)
151 return pair.second;
152 }
153 return std::string();
154}
Alex Vakulenkoaf23b322014-05-08 16:25:45 -0700155
156} // namespace buffet