• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "cj_request_common.h"
17 
18 #include <cstdlib>
19 #include <fstream>
20 #include <sstream>
21 
22 #include "cj_request_ffi.h"
23 #include "ffrt.h"
24 #include "log.h"
25 #include "openssl/sha.h"
26 #include "parameter.h"
27 #include "request_common.h"
28 #include "securec.h"
29 
30 namespace OHOS::CJSystemapi::Request {
31 using OHOS::Request::Action;
32 using OHOS::Request::ExceptionErrorCode;
33 using OHOS::Request::Faults;
34 using OHOS::Request::FileSpec;
35 using OHOS::Request::FormItem;
36 using OHOS::Request::Reason;
37 
38 static constexpr const char *REASON_OK_INFO = "Task successful";
39 static constexpr const char *TASK_SURVIVAL_ONE_MONTH_INFO = "The task has not been completed for a month yet";
40 static constexpr const char *WAITTING_NETWORK_ONE_DAY_INFO = "The task waiting for network recovery has not been "
41                                                              "completed for a day yet";
42 static constexpr const char *STOPPED_NEW_FRONT_TASK_INFO = "Stopped by a new front task";
43 static constexpr const char *RUNNING_TASK_MEET_LIMITS_INFO = "Too many task in running state";
44 static constexpr const char *USER_OPERATION_INFO = "User operation";
45 static constexpr const char *APP_BACKGROUND_OR_TERMINATE_INFO = "The app is background or terminate";
46 static constexpr const char *NETWORK_OFFLINE_INFO = "NetWork is offline";
47 static constexpr const char *UNSUPPORTED_NETWORK_TYPE_INFO = "NetWork type not meet the task config";
48 static constexpr const char *BUILD_CLIENT_FAILED_INFO = "Build client error";
49 static constexpr const char *BUILD_REQUEST_FAILED_INFO = "Build request error";
50 static constexpr const char *GET_FILESIZE_FAILED_INFO = "Failed because cannot get the file size from the server and "
51                                                         "the precise is setted true by user";
52 static constexpr const char *CONTINUOUS_TASK_TIMEOUT_INFO = "Continuous processing task time out";
53 static constexpr const char *CONNECT_ERROR_INFO = "Connect error";
54 static constexpr const char *REQUEST_ERROR_INFO = "Request error";
55 static constexpr const char *UPLOAD_FILE_ERROR_INFO = "There are some files upload failed";
56 static constexpr const char *REDIRECT_ERROR_INFO = "Redirect error";
57 static constexpr const char *PROTOCOL_ERROR_INFO = "Http protocol error";
58 static constexpr const char *IO_ERROR_INFO = "Io Error";
59 static constexpr const char *UNSUPPORT_RANGE_REQUEST_INFO = "Range request not supported";
60 static constexpr const char *OTHERS_ERROR_INFO = "Some other error occured";
61 static constexpr const char *ACCOUNT_STOPPED_INFO = "Account stopped";
62 static constexpr const char *NETWORK_CHANGED_INFO = "Network changed";
63 static constexpr const char *DNS_INFO = "DNS error";
64 static constexpr const char *TCP_INFO = "TCP error";
65 static constexpr const char *SSL_INFO = "TSL/SSL error";
66 static constexpr const char *INSUFFICIENT_SPACE_INFO = "Insufficient space error";
67 
ReadBytesFromFile(const std::string & filePath,std::vector<uint8_t> & fileData)68 void ReadBytesFromFile(const std::string &filePath, std::vector<uint8_t> &fileData)
69 {
70     // Ensure filePath validity.
71     std::ifstream inputFile(filePath.c_str(), std::ios::binary);
72     if (inputFile.is_open()) {
73         inputFile.seekg(0, std::ios::end);
74         fileData.resize(inputFile.tellg());
75         inputFile.seekg(0);
76         inputFile.read(reinterpret_cast<char *>(fileData.data()), fileData.size());
77         inputFile.close();
78     } else {
79         REQUEST_HILOGW("Read bytes from file, invalid file path!");
80     }
81     return;
82 }
83 
MallocCString(const std::string & origin)84 char *MallocCString(const std::string &origin)
85 {
86     if (origin.empty()) {
87         return nullptr;
88     }
89     auto len = origin.length() + 1;
90     char *res = static_cast<char *>(malloc(sizeof(char) * len));
91     if (res == nullptr) {
92         return nullptr;
93     }
94     return std::char_traits<char>::copy(res, origin.c_str(), len);
95 }
96 
IsPathValid(const std::string & filePath)97 bool IsPathValid(const std::string &filePath)
98 {
99     auto path = filePath.substr(0, filePath.rfind('/'));
100     char resolvedPath[PATH_MAX + 1] = {0};
101     if (path.length() > PATH_MAX || realpath(path.c_str(), resolvedPath) == nullptr ||
102         strncmp(resolvedPath, path.c_str(), path.length()) != 0) {
103         REQUEST_HILOGE("invalid file path!");
104         return false;
105     }
106     return true;
107 }
108 
SHA256(const char * str,size_t len)109 std::string SHA256(const char *str, size_t len)
110 {
111     unsigned char hash[SHA256_DIGEST_LENGTH];
112     SHA256_CTX sha256;
113     SHA256_Init(&sha256);
114     SHA256_Update(&sha256, str, len);
115     SHA256_Final(hash, &sha256);
116     std::stringstream ss;
117     for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
118         // 2 means setting hte width of the output.
119         ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
120     }
121     return ss.str();
122 }
123 
ConvertError(int32_t errorCode)124 ExceptionError ConvertError(int32_t errorCode)
125 {
126     ExceptionError err;
127     auto generateError = [&err](ExceptionErrorCode errorCode, const std::string &info) {
128         err.code = errorCode;
129         err.errInfo = info;
130         REQUEST_HILOGE("errorCode: %{public}d, errInfo: %{public}s", err.code, err.errInfo.c_str());
131     };
132 
133     switch (errorCode) {
134         case ExceptionErrorCode::E_UNLOADING_SA:
135             generateError(ExceptionErrorCode::E_SERVICE_ERROR, "Service ability is quitting.");
136             break;
137         case ExceptionErrorCode::E_IPC_SIZE_TOO_LARGE:
138             generateError(ExceptionErrorCode::E_SERVICE_ERROR, "Ipc error.");
139             break;
140         case ExceptionErrorCode::E_MIMETYPE_NOT_FOUND:
141             generateError(ExceptionErrorCode::E_OTHER, "Mimetype not found.");
142             break;
143         case ExceptionErrorCode::E_TASK_INDEX_TOO_LARGE:
144             generateError(ExceptionErrorCode::E_TASK_NOT_FOUND, "Task index out of range.");
145             break;
146         default:
147             generateError(static_cast<ExceptionErrorCode>(errorCode), "");
148             break;
149     }
150 
151     return err;
152 }
153 
Convert2CProgress(const Progress & in)154 CProgress Convert2CProgress(const Progress &in)
155 {
156     CProgress out = {0};
157     out.state = static_cast<uint32_t>(in.state);
158     out.index = in.index;
159     out.processed = in.processed;
160 
161     if (in.sizes.size() > 0) {
162         out.sizeArr = static_cast<int64_t *>(malloc(sizeof(int64_t) * in.sizes.size()));
163         if (out.sizeArr == nullptr) {
164             return out;
165         }
166         for (std::vector<long>::size_type i = 0; i < in.sizes.size(); ++i) {
167             out.sizeArr[i] = in.sizes[i];
168         }
169         out.sizeArrLen = static_cast<int64_t>(in.sizes.size());
170     }
171 
172     if (in.extras.size() <= 0) {
173         return out;
174     }
175 
176     out.extras.headers = static_cast<CHashStrPair *>(malloc(sizeof(CHashStrPair) * in.extras.size()));
177     if (out.extras.headers == nullptr) {
178         return out;
179     }
180 
181     int index = 0;
182     for (auto iter = in.extras.begin(); iter != in.extras.end(); ++iter) {
183         CHashStrPair *elem = &out.extras.headers[index++];
184         elem->key = MallocCString(iter->first);
185         elem->value = MallocCString(iter->second);
186     }
187     out.extras.size = static_cast<int64_t>(in.extras.size());
188     return out;
189 }
190 
Convert2CArrString(const std::vector<std::string> & v)191 CArrString Convert2CArrString(const std::vector<std::string> &v)
192 {
193     CArrString out = {};
194     if (v.empty()) {
195         return out;
196     }
197 
198     out.head = static_cast<char **>(malloc(sizeof(char *) * v.size()));
199     if (out.head == nullptr) {
200         return out;
201     }
202 
203     int64_t index = 0;
204     for (auto iter : v) {
205         out.head[index] = MallocCString(iter);
206         index++;
207     }
208     out.size = index;
209     return out;
210 }
211 
Convert2CResponse(const std::shared_ptr<Response> & in)212 CResponse Convert2CResponse(const std::shared_ptr<Response> &in)
213 {
214     CResponse out = {0};
215     out.version = MallocCString(in->version);
216     out.statusCode = in->statusCode;
217     out.reason = MallocCString(in->reason);
218 
219     if (in->headers.size() <= 0) {
220         return out;
221     }
222     CHttpHeaderHashPair *hashHead =
223         static_cast<CHttpHeaderHashPair *>(malloc(sizeof(CHttpHeaderHashPair) * in->headers.size()));
224     if (hashHead == nullptr) {
225         return out;
226     }
227 
228     int64_t index = 0;
229     for (auto iter : in->headers) {
230         hashHead[index].key = MallocCString(iter.first);
231         hashHead[index].value = Convert2CArrString(iter.second);
232         index++;
233     }
234     out.headers.hashHead = hashHead;
235     out.headers.size = index;
236     return out;
237 }
238 
RemoveFile(const std::string & filePath)239 void RemoveFile(const std::string &filePath)
240 {
241     auto removeFile = [filePath]() -> void {
242         std::remove(filePath.c_str());
243         return;
244     };
245     ffrt::submit(removeFile, {}, {}, ffrt::task_attr().name("Os_Request_Rm").qos(ffrt::qos_default));
246 }
247 
GetSaveas(const std::vector<FileSpec> & files,Action action)248 std::string GetSaveas(const std::vector<FileSpec> &files, Action action)
249 {
250     if (action == Action::UPLOAD) {
251         return "";
252     }
253     if (files.empty()) {
254         return "";
255     }
256     return files[0].uri;
257 }
258 
Convert2Broken(Reason code)259 uint32_t Convert2Broken(Reason code)
260 {
261     static std::map<Reason, Faults> InnerCodeToBroken = {
262         {Reason::REASON_OK, Faults::OTHERS},
263         {Reason::TASK_SURVIVAL_ONE_MONTH, Faults::OTHERS},
264         {Reason::WAITTING_NETWORK_ONE_DAY, Faults::OTHERS},
265         {Reason::STOPPED_NEW_FRONT_TASK, Faults::OTHERS},
266         {Reason::RUNNING_TASK_MEET_LIMITS, Faults::OTHERS},
267         {Reason::USER_OPERATION, Faults::OTHERS},
268         {Reason::APP_BACKGROUND_OR_TERMINATE, Faults::OTHERS},
269         {Reason::NETWORK_OFFLINE, Faults::DISCONNECTED},
270         {Reason::UNSUPPORTED_NETWORK_TYPE, Faults::OTHERS},
271         {Reason::BUILD_CLIENT_FAILED, Faults::PARAM},
272         {Reason::BUILD_REQUEST_FAILED, Faults::PARAM},
273         {Reason::GET_FILESIZE_FAILED, Faults::FSIO},
274         {Reason::CONTINUOUS_TASK_TIMEOUT, Faults::OTHERS},
275         {Reason::CONNECT_ERROR, Faults::TCP},
276         {Reason::REQUEST_ERROR, Faults::PROTOCOL},
277         {Reason::UPLOAD_FILE_ERROR, Faults::OTHERS},
278         {Reason::REDIRECT_ERROR, Faults::REDIRECT},
279         {Reason::PROTOCOL_ERROR, Faults::PROTOCOL},
280         {Reason::IO_ERROR, Faults::FSIO},
281         {Reason::UNSUPPORT_RANGE_REQUEST, Faults::PROTOCOL},
282         {Reason::OTHERS_ERROR, Faults::OTHERS},
283         {Reason::ACCOUNT_STOPPED, Faults::OTHERS},
284         {Reason::NETWORK_CHANGED, Faults::OTHERS},
285         {Reason::DNS, Faults::DNS},
286         {Reason::TCP, Faults::TCP},
287         {Reason::SSL, Faults::SSL},
288         {Reason::INSUFFICIENT_SPACE, Faults::OTHERS},
289         {Reason::NETWORK_APP, Faults::DISCONNECTED},
290         {Reason::NETWORK_ACCOUNT, Faults::DISCONNECTED},
291         {Reason::APP_ACCOUNT, Faults::OTHERS},
292         {Reason::NETWORK_APP_ACCOUNT, Faults::DISCONNECTED},
293     };
294     constexpr const int32_t detailVersion = 12;
295     auto iter = InnerCodeToBroken.find(code);
296     if (iter != InnerCodeToBroken.end()) {
297         int32_t sdkVersion = GetSdkApiVersion();
298         REQUEST_HILOGD("GetSdkApiVersion %{public}d", sdkVersion);
299         if (sdkVersion < detailVersion &&
300             (iter->second == Faults::PARAM || iter->second == Faults::DNS || iter->second == Faults::TCP ||
301              iter->second == Faults::SSL || iter->second == Faults::REDIRECT)) {
302             return static_cast<uint32_t>(Faults::OTHERS);
303         }
304         return static_cast<uint32_t>(iter->second);
305     }
306     return 0;
307 }
308 
Convert2ReasonMsg(Reason code)309 std::string Convert2ReasonMsg(Reason code)
310 {
311     static std::map<Reason, std::string> ReasonMsg = {
312         {Reason::REASON_OK, REASON_OK_INFO},
313         {Reason::TASK_SURVIVAL_ONE_MONTH, TASK_SURVIVAL_ONE_MONTH_INFO},
314         {Reason::WAITTING_NETWORK_ONE_DAY, WAITTING_NETWORK_ONE_DAY_INFO},
315         {Reason::STOPPED_NEW_FRONT_TASK, STOPPED_NEW_FRONT_TASK_INFO},
316         {Reason::RUNNING_TASK_MEET_LIMITS, RUNNING_TASK_MEET_LIMITS_INFO},
317         {Reason::USER_OPERATION, USER_OPERATION_INFO},
318         {Reason::APP_BACKGROUND_OR_TERMINATE, APP_BACKGROUND_OR_TERMINATE_INFO},
319         {Reason::NETWORK_OFFLINE, NETWORK_OFFLINE_INFO},
320         {Reason::UNSUPPORTED_NETWORK_TYPE, UNSUPPORTED_NETWORK_TYPE_INFO},
321         {Reason::BUILD_CLIENT_FAILED, BUILD_CLIENT_FAILED_INFO},
322         {Reason::BUILD_REQUEST_FAILED, BUILD_REQUEST_FAILED_INFO},
323         {Reason::GET_FILESIZE_FAILED, GET_FILESIZE_FAILED_INFO},
324         {Reason::CONTINUOUS_TASK_TIMEOUT, CONTINUOUS_TASK_TIMEOUT_INFO},
325         {Reason::CONNECT_ERROR, CONNECT_ERROR_INFO},
326         {Reason::REQUEST_ERROR, REQUEST_ERROR_INFO},
327         {Reason::UPLOAD_FILE_ERROR, UPLOAD_FILE_ERROR_INFO},
328         {Reason::REDIRECT_ERROR, REDIRECT_ERROR_INFO},
329         {Reason::PROTOCOL_ERROR, PROTOCOL_ERROR_INFO},
330         {Reason::IO_ERROR, IO_ERROR_INFO},
331         {Reason::UNSUPPORT_RANGE_REQUEST, UNSUPPORT_RANGE_REQUEST_INFO},
332         {Reason::OTHERS_ERROR, OTHERS_ERROR_INFO},
333         {Reason::ACCOUNT_STOPPED, ACCOUNT_STOPPED_INFO},
334         {Reason::NETWORK_CHANGED, NETWORK_CHANGED_INFO},
335         {Reason::DNS, DNS_INFO},
336         {Reason::TCP, TCP_INFO},
337         {Reason::SSL, SSL_INFO},
338         {Reason::INSUFFICIENT_SPACE, INSUFFICIENT_SPACE_INFO},
339     };
340     auto iter = ReasonMsg.find(code);
341     if (iter != ReasonMsg.end()) {
342         return iter->second;
343     }
344     return "unknown";
345 }
346 
Convert2CHashStrArr(const std::map<std::string,std::string> & extras)347 CHashStrArr Convert2CHashStrArr(const std::map<std::string, std::string> &extras)
348 {
349     CHashStrArr out = {NULL};
350     size_t size = extras.size();
351     if (size == 0 || size > std::numeric_limits<size_t>::max() / sizeof(CHashStrPair)) {
352         return out;
353     }
354 
355     out.headers = static_cast<CHashStrPair *>(malloc(sizeof(CHashStrPair) * size));
356     if (out.headers == nullptr) {
357         return out;
358     }
359 
360     size_t i = 0;
361     for (const auto &it : extras) {
362         out.headers[i].key = MallocCString(it.first);
363         out.headers[i].value = MallocCString(it.second);
364         ++i;
365     }
366     out.size = static_cast<int64_t>(i);
367     return out;
368 }
369 
Convert2CFormItemArr(const std::vector<FileSpec> & files,const std::vector<FormItem> & forms)370 CFormItemArr Convert2CFormItemArr(const std::vector<FileSpec> &files, const std::vector<FormItem> &forms)
371 {
372     CFormItemArr out = {NULL};
373     size_t filesLen = files.size();
374     size_t formsLen = forms.size();
375     size_t len = filesLen + formsLen;
376     if (len == 0) {
377         return out;
378     }
379 
380     out.head = static_cast<CFormItem *>(malloc(sizeof(CFormItem) * len));
381     if (out.head == NULL) {
382         return out;
383     }
384     memset_s(out.head, sizeof(CFormItem) * len, 0, sizeof(CFormItem) * len);
385     size_t i = 0;
386     for (; i < formsLen; ++i) {
387         out.head[i].name = MallocCString(forms[i].name);
388         out.head[i].value.str = MallocCString(forms[i].value);
389         out.head[i].value.type = CFORM_ITEM_VALUE_TYPE_STRING;
390     }
391 
392     for (size_t j = 0; j < filesLen; ++j) {
393         out.head[i].name = MallocCString(files[j].name);
394         out.head[i].value.file.path = MallocCString(files[j].uri);
395         out.head[i].value.file.mimeType = MallocCString(files[j].type);
396         out.head[i].value.file.filename = MallocCString(files[j].filename);
397         out.head[i].value.type = CFORM_ITEM_VALUE_TYPE_FILE;
398         ++i;
399     }
400 
401     out.size = static_cast<int64_t>(i);
402     return out;
403 }
404 
405 } // namespace OHOS::CJSystemapi::Request
406