blob: a4f29cad80bbea21cb84ceb0146a14cb7742fcb6 [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
12using namespace chromeos;
13
14//***************************************************************************
15//******************************* MIME types ********************************
16//***************************************************************************
17const 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
42//***************************************************************************
43//**************************** Utility Functions ****************************
44//***************************************************************************
45static std::string EncodeParam(std::string const& param) {
46 // 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
54static std::string DecodeParam(std::string const& param) {
55 if (param.size() > 1 && param.front() == '"' && param.back() == '"') {
56 return param.substr(1, param.size() - 2);
57 }
58 return param;
59}
60
61//***************************************************************************
62//******************** Main MIME manipulation functions *********************
63//***************************************************************************
64
65bool mime::Split(std::string const& mime_string,
66 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
75 if(parameters) {
76 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
87bool mime::Split(std::string const& mime_string,
88 std::string* type, std::string* subtype) {
89 std::string mime = mime::RemoveParameters(mime_string);
90 auto types = string_utils::SplitAtFirst(mime, '/');
91
92 if(type)
93 *type = types.first;
94
95 if(subtype)
96 *subtype = types.second;
97
98 return !types.first.empty() && !types.second.empty();
99}
100
101std::string mime::Combine(std::string const& type, std::string const& subtype,
102 mime::Parameters const& parameters) {
103 std::vector<std::string> parts;
104 parts.push_back(string_utils::Join('/', type, subtype));
105 for (std::pair<std::string, std::string> const& pair : parameters) {
106 parts.push_back(string_utils::Join('=', pair.first,
107 EncodeParam(pair.second)));
108 }
109 return string_utils::Join("; ", parts);
110}
111
112std::string mime::GetType(std::string const& mime_string) {
113 std::string mime = mime::RemoveParameters(mime_string);
114 return string_utils::SplitAtFirst(mime, '/').first;
115}
116
117std::string mime::GetSubtype(std::string const& mime_string) {
118 std::string mime = mime::RemoveParameters(mime_string);
119 return string_utils::SplitAtFirst(mime, '/').second;
120}
121
122mime::Parameters mime::GetParameters(std::string const& mime_string) {
123 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
133std::string mime::RemoveParameters(std::string const& mime_string) {
134 return string_utils::SplitAtFirst(mime_string, ';').first;
135}
136
137std::string mime::AppendParameter(std::string const& mime_string,
138 std::string const& paramName,
139 std::string const& paramValue) {
140 std::string mime(mime_string);
141 mime += "; ";
142 mime += string_utils::Join('=', paramName, EncodeParam(paramValue));
143 return mime;
144}
145
146std::string mime::GetParameterValue(std::string const& mime_string,
147 std::string const& paramName) {
148 mime::Parameters params = mime::GetParameters(mime_string);
149 for(auto const& pair : params) {
150 if (base::strcasecmp(pair.first.c_str(), paramName.c_str()) == 0)
151 return pair.second;
152 }
153 return std::string();
154}