1 /*
2 * Copyright 1999-2019 Alibaba Cloud All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <algorithm>
18 #include <alibabacloud/core/Utils.h>
19 #include <sstream>
20 #include <stdlib.h>
21
22 #ifdef _WIN32
23 #include <Windows.h>
24 #elif defined(USE_CRYPTO_MBEDTLS)
25 #include "mbedtls/md.h"
26 #include "mbedtls/compat-1.3.h"
27 #include "mbedtls/sha1.h"
28 #include "mbedtls/base64.h"
29 #include "mbedtls/md5.h"
30 #else
31 #include <openssl/hmac.h>
32 #include <openssl/md5.h>
33 #include <uuid/uuid.h>
34 #endif
35 #include <curl/curl.h>
36 #include <json/json.h>
37 #include <time.h>
38
GenerateUuid()39 std::string AlibabaCloud::GenerateUuid() {
40 #ifdef _WIN32
41 char *data;
42 UUID uuidhandle;
43 UuidCreate(&uuidhandle);
44 UuidToString(&uuidhandle, reinterpret_cast<RPC_CSTR *>(&data));
45 std::string uuid(data);
46 RpcStringFree(reinterpret_cast<RPC_CSTR *>(&data));
47 return uuid;
48 #else
49 #if 0
50 uuid_t uu;
51 uuid_generate(uu);
52 char buf[36];
53 uuid_unparse(uu, buf);
54 return buf;
55 #else
56 char buf[36];
57 unsigned int seed = (unsigned int)aos_now();
58
59 srand(seed);
60 sprintf(buf,"680c83c1-fa94-4b90-a364-%d",rand());
61 std::string uuid(buf);
62 return uuid;
63 #endif
64 #endif
65 }
66
UrlEncode(const std::string & src)67 std::string AlibabaCloud::UrlEncode(const std::string &src) {
68 CURL *curl = curl_easy_init();
69 char *output = curl_easy_escape(curl, src.c_str(), src.size());
70 std::string result(output);
71 curl_free(output);
72 curl_easy_cleanup(curl);
73 return result;
74 }
75
UrlDecode(const std::string & src)76 std::string AlibabaCloud::UrlDecode(const std::string &src) {
77 CURL *curl = curl_easy_init();
78 int outlength = 0;
79 char *output = curl_easy_unescape(curl, src.c_str(), src.size(), &outlength);
80 std::string result(output, outlength);
81 curl_free(output);
82 curl_easy_cleanup(curl);
83 return result;
84 }
85
ComputeContentMD5(const char * data,size_t size)86 std::string AlibabaCloud::ComputeContentMD5(const char *data, size_t size) {
87 #ifdef _WIN32
88 HCRYPTPROV hProv = 0;
89 HCRYPTHASH hHash = 0;
90 BYTE pbHash[16];
91 DWORD dwDataLen = 16;
92
93 CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
94 CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
95 CryptHashData(hHash, (BYTE *)(data), size, 0);
96 CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwDataLen, 0);
97
98 CryptDestroyHash(hHash);
99 CryptReleaseContext(hProv, 0);
100
101 DWORD dlen = 0;
102 CryptBinaryToString(pbHash, dwDataLen,
103 CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &dlen);
104 char *dest = new char[dlen];
105 CryptBinaryToString(pbHash, dwDataLen,
106 CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, dest, &dlen);
107 std::string ret = std::string(dest, dlen);
108 delete dest;
109 return ret;
110
111 #elif defined(USE_CRYPTO_MBEDTLS)
112 unsigned char md_data[16];
113 unsigned int mdLen = 16;
114 mbedtls_md5_context ctx;
115 unsigned int olen = 0;
116
117 mbedtls_md5_ret((const unsigned char*)data, size, md_data);
118
119 char encodedData[100];
120
121 mbedtls_base64_encode((unsigned char*)encodedData, sizeof(encodedData), &olen, md_data, mdLen);
122
123 return encodedData;
124 #else
125 unsigned char md[MD5_DIGEST_LENGTH];
126 MD5(reinterpret_cast<const unsigned char *>(data), size,
127 (unsigned char *)&md);
128
129 char encodedData[100];
130 EVP_EncodeBlock(reinterpret_cast<unsigned char *>(encodedData), md,
131 MD5_DIGEST_LENGTH);
132 return encodedData;
133 #endif
134 }
135
StringReplace(std::string & src,const std::string & s1,const std::string & s2)136 void AlibabaCloud::StringReplace(std::string &src, const std::string &s1,
137 const std::string &s2) {
138 std::string::size_type pos = 0;
139 while ((pos = src.find(s1, pos)) != std::string::npos) {
140 src.replace(pos, s1.length(), s2);
141 pos += s2.length();
142 }
143 }
144
HttpMethodToString(HttpRequest::Method method)145 std::string AlibabaCloud::HttpMethodToString(HttpRequest::Method method) {
146 switch (method) {
147 case HttpRequest::Method::Head:
148 return "HEAD";
149 break;
150 case HttpRequest::Method::Post:
151 return "POST";
152 break;
153 case HttpRequest::Method::Put:
154 return "PUT";
155 break;
156 case HttpRequest::Method::Delete:
157 return "DELETE";
158 break;
159 case HttpRequest::Method::Connect:
160 return "CONNECT";
161 break;
162 case HttpRequest::Method::Options:
163 return "OPTIONS";
164 break;
165 case HttpRequest::Method::Patch:
166 return "PATCH";
167 break;
168 case HttpRequest::Method::Trace:
169 return "TRACE";
170 break;
171 case HttpRequest::Method::Get:
172 default:
173 return "GET";
174 break;
175 }
176 }
177
canonicalizedQuery(const std::map<std::string,std::string> & params)178 std::string AlibabaCloud::canonicalizedQuery(
179 const std::map<std::string, std::string> ¶ms) {
180 if (params.empty())
181 return std::string();
182
183 std::stringstream ss;
184 for (const auto &p : params) {
185 std::string key = UrlEncode(p.first);
186 StringReplace(key, "+", "%20");
187 StringReplace(key, "*", "%2A");
188 StringReplace(key, "%7E", "~");
189 std::string value = UrlEncode(p.second);
190 StringReplace(value, "+", "%20");
191 StringReplace(value, "*", "%2A");
192 StringReplace(value, "%7E", "~");
193 ss << "&" << key << "=" << value;
194 }
195 return ss.str().substr(1);
196 }
197
canonicalizedHeaders(const HttpMessage::HeaderCollection & headers)198 std::string AlibabaCloud::canonicalizedHeaders(
199 const HttpMessage::HeaderCollection &headers) {
200 std::map<std::string, std::string> materials;
201 for (const auto &p : headers) {
202 std::string key = p.first;
203 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
204 if (key.find("x-acs-") != 0)
205 continue;
206
207 std::string value = p.second;
208 StringReplace(value, "\t", " ");
209 StringReplace(value, "\n", " ");
210 StringReplace(value, "\r", " ");
211 StringReplace(value, "\f", " ");
212 materials[key] = value;
213 }
214
215 if (materials.empty())
216 return std::string();
217 std::stringstream ss;
218 for (const auto &p : materials)
219 ss << p.first << ":" << p.second << "\n";
220
221 return ss.str();
222 }
223
GetEnv(const std::string env)224 std::string AlibabaCloud::GetEnv(const std::string env) {
225 #ifdef _WIN32
226 char *buf = nullptr;
227 size_t sz = 0;
228 if (_dupenv_s(&buf, &sz, env.c_str()) == 0 && buf != nullptr) {
229 std::string var(buf);
230 free(buf);
231 return var;
232 } else {
233 if (buf) {
234 free(buf);
235 }
236 return std::string();
237 }
238 #else
239 char *var = getenv(env.c_str());
240 if (var) {
241 return std::string(var);
242 }
243 return std::string();
244 #endif
245 }
246
247 std::string
MapToJson(const std::map<std::string,std::string> & maps)248 AlibabaCloud::MapToJson(const std::map<std::string, std::string> &maps) {
249 Json::Value jsonObject;
250 Json::FastWriter writer;
251 for (std::map<std::string, std::string>::const_iterator iter = maps.begin();
252 iter != maps.end(); ++iter) {
253 jsonObject[iter->first] = iter->second;
254 }
255 std::string unformat_str = writer.write(jsonObject);
256 return unformat_str.substr(0, unformat_str.length() - 1);
257 }
258
259 std::map<std::string, std::string>
JsonToMap(const std::string & json)260 AlibabaCloud::JsonToMap(const std::string &json) {
261 Json::Reader reader;
262 Json::Value value;
263 std::map<std::string, std::string> maps;
264
265 if (json.length() > 0) {
266 if (reader.parse(json, value)) {
267 Json::Value::Members members = value.getMemberNames();
268 for (Json::Value::Members::iterator it = members.begin();
269 it != members.end(); ++it) {
270 Json::ValueType vt = value[*it].type();
271 switch (vt) {
272 case Json::stringValue: {
273 maps.insert(
274 std::pair<std::string, std::string>(*it, value[*it].asString()));
275 break;
276 }
277 case Json::intValue: {
278 int inttmp = value[*it].asInt();
279 maps.insert(
280 std::pair<std::string, std::string>(*it, std::to_string(inttmp)));
281 break;
282 }
283 case Json::arrayValue: {
284 std::string strid;
285 for (unsigned int i = 0; i < value[*it].size(); i++) {
286 strid += value[*it][i].asString();
287 strid += ",";
288 }
289 if (!strid.empty()) {
290 strid = strid.substr(0, strid.size() - 1);
291 }
292 maps.insert(std::pair<std::string, std::string>(*it, strid));
293 break;
294 }
295 default: {
296 break;
297 }
298 }
299 }
300 }
301 }
302
303 return maps;
304 }