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_initialize.h"
17 
18 #include <regex>
19 #include <sys/stat.h>
20 #include <algorithm>
21 #include <cstring>
22 #include <filesystem>
23 #include <fcntl.h>
24 #include <fstream>
25 #include "securec.h"
26 #include "constant.h"
27 #include "js_common.h"
28 #include "cj_request_log.h"
29 #include "request_manager.h"
30 #include "cj_request_common.h"
31 #include "net_conn_client.h"
32 #include "cj_request_task.h"
33 
34 namespace OHOS::CJSystemapi::Request {
35 
36 using OHOS::Request::Action;
37 using OHOS::Request::Version;
38 using OHOS::Request::FileSpec;
39 using OHOS::Request::FormItem;
40 using OHOS::Request::ExceptionErrorCode;
41 using OHOS::AbilityRuntime::Context;
42 
43 static constexpr uint32_t TOKEN_MAX_BYTES = 2048;
44 static constexpr uint32_t TOKEN_MIN_BYTES = 8;
45 static constexpr uint32_t URL_MAXIMUM = 2048;
46 static constexpr uint32_t TITLE_MAXIMUM = 256;
47 static constexpr uint32_t DESCRIPTION_MAXIMUM = 1024;
48 
49 static constexpr uint32_t FILE_PERMISSION = 0644;
50 
51 static const std::string AREA1 = "el1";
52 static const std::string AREA2 = "el2";
53 
ParseBundleName(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,std::string & bundleName)54 ExceptionError CJInitialize::ParseBundleName(const std::shared_ptr<OHOS::AbilityRuntime::Context> &context,
55     std::string &bundleName)
56 {
57     if (context->GetApplicationInfo() == nullptr) {
58         return {
59             .code = ExceptionErrorCode::E_OTHER,
60             .errInfo = "ApplicationInfo is null"
61         };
62     }
63 
64     bundleName = context->GetBundleName();
65 
66     return {
67         .code = ExceptionErrorCode::E_OK
68     };
69 }
70 
ParseUrl(std::string & url)71 bool CJInitialize::ParseUrl(std::string &url)
72 {
73     if (url.size() > URL_MAXIMUM) {
74         REQUEST_HILOGE("The URL exceeds the maximum length of 2048");
75         return false;
76     }
77     if (!std::regex_match(url, std::regex("^http(s)?:\\/\\/.+"))) {
78         REQUEST_HILOGE("ParseUrl error");
79         return false;
80     }
81 
82     return true;
83 }
84 
ParseCertsPath(std::string & url,std::vector<std::string> & certsPath)85 bool CJInitialize::ParseCertsPath(std::string &url, std::vector<std::string> &certsPath)
86 {
87     if (url.size() > URL_MAXIMUM) {
88         REQUEST_HILOGE("The URL exceeds the maximum length of 2048");
89         return false;
90     }
91     if (!regex_match(url, std::regex("^http(s)?:\\/\\/.+"))) {
92         REQUEST_HILOGE("ParseUrl error");
93         return false;
94     }
95 
96     typedef std::string::const_iterator iter_t;
97     iter_t urlEnd = url.end();
98     iter_t protocolStart = url.cbegin();
99     iter_t protocolEnd = std::find(protocolStart, urlEnd, ':');
100     std::string protocol = std::string(protocolStart, protocolEnd);
101     if (protocol != "https") {
102         REQUEST_HILOGD("Using Http");
103         return true;
104     }
105     if (protocolEnd != urlEnd) {
106         std::string afterProtocol = &*(protocolEnd);
107         // 3 is the num of ://
108         if ((afterProtocol.length() > 3) && (afterProtocol.substr(0, 3) == "://")) {
109             // 3 means go beyound :// in protocolEnd
110             protocolEnd += 3;
111         } else {
112             protocolEnd = url.cbegin();
113         }
114     } else {
115         protocolEnd = url.cbegin();
116     }
117     iter_t hostStart = protocolEnd;
118     iter_t pathStart = std::find(hostStart, urlEnd, '/');
119     iter_t queryStart = std::find(url.cbegin(), urlEnd, '?');
120     iter_t hostEnd = std::find(protocolEnd, (pathStart != urlEnd) ? pathStart : queryStart, ':');
121     std::string hostname = std::string(hostStart, hostEnd);
122     REQUEST_HILOGD("Hostname is %{public}s", hostname.c_str());
123     NetManagerStandard::NetConnClient::GetInstance().GetTrustAnchorsForHostName(hostname, certsPath);
124 
125     return true;
126 }
127 
Convert2FileSpec(const CFileSpec * cFile,const char * name,FileSpec & file)128 bool CJInitialize::Convert2FileSpec(const CFileSpec *cFile, const char *name, FileSpec &file)
129 {
130     file.name = name;
131 
132     if (cFile->path == nullptr) {
133         return false;
134     }
135     file.uri = cFile->path;
136     if (file.uri.empty()) {
137         return false;
138     }
139     if (cFile->filename != nullptr) {
140         file.filename = cFile->filename;
141     }
142 
143     if (cFile->mimeType != nullptr) {
144         file.type = cFile->mimeType;
145     }
146 
147     return true;
148 }
149 
Convert2FileSpecs(const CFileSpecArr * cFiles,const char * name,std::vector<FileSpec> & files)150 bool CJInitialize::Convert2FileSpecs(const CFileSpecArr *cFiles, const char *name, std::vector<FileSpec> &files)
151 {
152     for (int i = 0; i < cFiles->size; ++i) {
153         FileSpec file;
154         if (!Convert2FileSpec(&cFiles->head[i], name, file)) {
155             return false;
156         }
157         files.push_back(file);
158     }
159     return true;
160 }
161 
ParseFormItems(const CFormItemArr * cForms,std::vector<FormItem> & forms,std::vector<FileSpec> & files)162 bool CJInitialize::ParseFormItems(const CFormItemArr *cForms, std::vector<FormItem> &forms,
163     std::vector<FileSpec> &files)
164 {
165     for (int i = 0; i < cForms->size; ++i) {
166         CFormItem *cForm = &cForms->head[i];
167         if (cForm->value.str != nullptr) {
168             FormItem form;
169             form.name = cForm->name;
170             form.value = cForm->value.str;
171             forms.push_back(form);
172         } else if (cForm->value.file.path != nullptr) {
173             FileSpec file;
174             if (!Convert2FileSpec(&cForm->value.file, cForm->name, file)) {
175                 REQUEST_HILOGE("Convert2FileSpec failed");
176                 return false;
177             }
178             files.push_back(file);
179         } else if (cForm->value.files.size > 0) {
180             if (!Convert2FileSpecs(&cForm->value.files, cForm->name, files)) {
181                 return false;
182             }
183         } else {
184             REQUEST_HILOGE("value type is error");
185             return false;
186         }
187     }
188 
189     return true;
190 }
191 
ParseData(const CConfig * config,Config & out)192 bool CJInitialize::ParseData(const CConfig *config, Config &out)
193 {
194     REQUEST_HILOGD("formItems.size is %{public}" PRIi64 ", data.str is %{public}p", config->data.formItems.size,
195         config->data.str);
196     if (config->data.str == nullptr && config->data.formItems.size <= 0) {
197         return true;
198     }
199 
200     if (out.action == Action::UPLOAD && config->data.formItems.size > 0) {
201         return ParseFormItems(&config->data.formItems, out.forms, out.files);
202     } else if (out.action == Action::DOWNLOAD && config->data.str != nullptr) {
203         out.data = config->data.str;
204     } else {
205         REQUEST_HILOGE("data type is error");
206         return false;
207     }
208 
209     return true;
210 }
211 
ParseIndex(Config & config)212 bool CJInitialize::ParseIndex(Config &config)
213 {
214     if (config.action == Action::DOWNLOAD) {
215         config.index = 0;
216         return true;
217     }
218     if (config.files.size() <= config.index) {
219         REQUEST_HILOGE("files.size is %{public}zu, index is %{public}d", config.files.size(), config.index);
220         return false;
221     }
222     return true;
223 }
224 
ParseBegins(int64_t & begins)225 int64_t CJInitialize::ParseBegins(int64_t &begins)
226 {
227     return begins >= 0 ? begins : 0;
228 }
229 
ParseTitle(Config & config)230 bool CJInitialize::ParseTitle(Config &config)
231 {
232     if (config.title.size() > TITLE_MAXIMUM) {
233         return false;
234     }
235 
236     if (config.title.empty()) {
237         config.title = config.action == Action::UPLOAD ? "upload" : "download";
238     }
239 
240     return true;
241 }
242 
ParseToken(Config & config)243 bool CJInitialize::ParseToken(Config &config)
244 {
245     if (config.token.empty()) {
246         config.token = "null";
247         return true;
248     }
249     size_t len = config.token.length();
250     if (len < TOKEN_MIN_BYTES || len > TOKEN_MAX_BYTES) {
251         return false;
252     }
253 
254     config.token = SHA256(config.token.c_str(), len);
255     return true;
256 }
257 
ParseDescription(std::string & description)258 bool CJInitialize::ParseDescription(std::string &description)
259 {
260     return description.size() <= DESCRIPTION_MAXIMUM;
261 }
262 
ParseSaveas(Config & config)263 bool CJInitialize::ParseSaveas(Config &config)
264 {
265     if (config.action != Action::DOWNLOAD) {
266         config.saveas = "";
267         return true;
268     }
269 
270     std::string temp = config.saveas;
271     if (temp.empty() || temp == "./") {
272         return InterceptData("/", config.url, config.saveas);
273     }
274     temp = std::string(temp, 0, temp.find_last_not_of(' ') + 1);
275     if (temp.size() == 0 || temp[temp.size() - 1] == '/') {
276         return false;
277     }
278     config.saveas = temp;
279     return true;
280 }
281 
ParseMethod(Config & config)282 void CJInitialize::ParseMethod(Config &config)
283 {
284     std::string method = config.method;
285     config.method = config.action == Action::UPLOAD ? "PUT" : "GET";
286     if (!method.empty()) {
287         transform(method.begin(), method.end(), method.begin(), ::toupper);
288         if (config.action == Action::UPLOAD && (method == "POST" || method == "PUT")) {
289             config.method = method;
290         }
291         if (config.action == Action::DOWNLOAD && (method == "POST" || method == "GET")) {
292             config.method = method;
293         }
294     }
295 }
296 
ParseNetwork(Network & network)297 void CJInitialize::ParseNetwork(Network &network)
298 {
299     if (network != Network::ANY && network != Network::WIFI && network != Network::CELLULAR) {
300         network = Network::ANY;
301     }
302 }
303 
ParseBackGround(Mode mode,bool & background)304 void CJInitialize::ParseBackGround(Mode mode, bool &background)
305 {
306     background = mode == Mode::BACKGROUND;
307 }
308 
StringSplit(const std::string & str,const char delim,std::vector<std::string> & elems)309 void CJInitialize::StringSplit(const std::string &str, const char delim, std::vector<std::string> &elems)
310 {
311     std::stringstream stream(str);
312     std::string item;
313     while (std::getline(stream, item, delim)) {
314         if (!item.empty()) {
315             elems.push_back(item);
316         }
317     }
318     return;
319 }
320 
GetBaseDir(std::string & baseDir)321 bool CJInitialize::GetBaseDir(std::string &baseDir)
322 {
323     auto context = OHOS::AbilityRuntime::Context::GetApplicationContext();
324     if (context == nullptr) {
325         REQUEST_HILOGE("AppContext is null.");
326         return false;
327     }
328 
329     baseDir = context->GetBaseDir();
330     if (baseDir.empty()) {
331         REQUEST_HILOGE("Base dir not found.");
332         return false;
333     }
334     return true;
335 }
336 
CheckPathBaseDir(const std::string & filepath,std::string & baseDir)337 bool CJInitialize::CheckPathBaseDir(const std::string &filepath, std::string &baseDir)
338 {
339     if (!CJInitialize::GetBaseDir(baseDir)) {
340         return false;
341     }
342     if (filepath.find(baseDir) == 0) {
343         return true;
344     }
345     // check baseDir replaced with el2
346     if (baseDir.find(AREA1) != std::string::npos) {
347         baseDir = baseDir.replace(baseDir.find(AREA1), AREA1.length(), AREA2);
348         if (filepath.find(baseDir) == 0) {
349             return true;
350         }
351         REQUEST_HILOGE("File dir not include base dir: %{public}s", baseDir.c_str());
352         return false;
353     }
354     // check baseDir replaced with el1
355     if (baseDir.find(AREA2) != std::string::npos) {
356         baseDir = baseDir.replace(baseDir.find(AREA2), AREA2.length(), AREA1);
357         if (filepath.find(baseDir) == 0) {
358             return true;
359         }
360         REQUEST_HILOGE("File dir not include base dir: %{public}s", baseDir.c_str());
361         return false;
362     }
363     return false;
364 }
365 
CreateDirs(const std::vector<std::string> & pathDirs)366 bool CJInitialize::CreateDirs(const std::vector<std::string> &pathDirs)
367 {
368     std::string path;
369     for (auto elem : pathDirs) {
370         path += "/" + elem;
371         std::error_code err;
372         if (std::filesystem::exists(path, err)) {
373             continue;
374         }
375         err.clear();
376         // create_directory noexcept.
377         if (!std::filesystem::create_directory(path, err)) {
378             REQUEST_HILOGE("Create Dir Err: %{public}d, %{public}s", err.value(), err.message().c_str());
379             return false;
380         }
381     }
382     return true;
383 }
384 
CheckDownloadFilePath(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,Config & config,std::string & errInfo)385 bool CJInitialize::CheckDownloadFilePath(const std::shared_ptr<OHOS::AbilityRuntime::Context> &context, Config &config,
386     std::string &errInfo)
387 {
388     std::string path = config.saveas;
389     if (!StandardizePath(context, config, path)) {
390         REQUEST_HILOGE("StandardizePath Err: %{public}s", path.c_str());
391         errInfo = "this is fail saveas path";
392         return false;
393     };
394     std::string normalPath;
395     std::vector<std::string> pathVec;
396     if (!WholeToNormal(path, normalPath, pathVec) || pathVec.empty()) {
397         REQUEST_HILOGE("WholeToNormal Err: %{public}s", path.c_str());
398         errInfo = "this is fail saveas path";
399         return false;
400     };
401     std::string baseDir;
402     if (!CheckPathBaseDir(normalPath, baseDir)) {
403         REQUEST_HILOGE("CheckPathBaseDir Err: %{public}s", normalPath.c_str());
404         errInfo = "this is fail saveas path";
405         return false;
406     };
407     // pop filename.
408     pathVec.pop_back();
409     if (!CreateDirs(pathVec)) {
410         REQUEST_HILOGE("CreateDirs Err: %{public}s", normalPath.c_str());
411         errInfo = "this is fail saveas path";
412         return false;
413     }
414     config.saveas = normalPath;
415     return true;
416 }
417 
FileToWhole(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,const Config & config,std::string & path)418 bool CJInitialize::FileToWhole(
419     const std::shared_ptr<OHOS::AbilityRuntime::Context> &context, const Config &config, std::string &path)
420 {
421     std::string bundleName = path.substr(0, path.find("/"));
422     if (bundleName != config.bundleName) {
423         REQUEST_HILOGE("path bundleName error.");
424         return false;
425     }
426     path.erase(0, bundleName.size());
427     return true;
428 }
429 
CacheToWhole(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,std::string & path)430 bool CJInitialize::CacheToWhole(const std::shared_ptr<OHOS::AbilityRuntime::Context> &context, std::string &path)
431 {
432     std::string cache = context->GetCacheDir();
433     if (cache.empty()) {
434         REQUEST_HILOGE("GetCacheDir error.");
435         return false;
436     }
437     path = cache + "/" + path;
438     return true;
439 }
440 
StandardizePath(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,const Config & config,std::string & path)441 bool CJInitialize::StandardizePath(const std::shared_ptr<OHOS::AbilityRuntime::Context> &context, const Config &config,
442     std::string &path)
443 {
444     std::string WHOLE_PREFIX = "/";
445     std::string FILE_PREFIX = "file://";
446     std::string INTERNAL_PREFIX = "internal://cache/";
447     std::string CURRENT_PREFIX = "./";
448 
449     if (path.find(WHOLE_PREFIX) == 0) {
450         return true;
451     }
452     if (path.find(FILE_PREFIX) == 0) {
453         path.erase(0, FILE_PREFIX.size());
454         return FileToWhole(context, config, path);
455     }
456     if (path.find(INTERNAL_PREFIX) == 0) {
457         path.erase(0, INTERNAL_PREFIX.size());
458         return CacheToWhole(context, path);
459     }
460     if (path.find(CURRENT_PREFIX) == 0) {
461         path.erase(0, CURRENT_PREFIX.size());
462         return CacheToWhole(context, path);
463     }
464     return CacheToWhole(context, path);
465 }
466 
PathVecToNormal(const std::vector<std::string> & in,std::vector<std::string> & out)467 bool CJInitialize::PathVecToNormal(const std::vector<std::string> &in, std::vector<std::string> &out)
468 {
469     for (auto elem : in) {
470         if (elem == "..") {
471             if (out.size() > 0) {
472                 out.pop_back();
473             } else {
474                 return false;
475             }
476         } else {
477             out.push_back(elem);
478         }
479     }
480     return true;
481 }
482 
WholeToNormal(const std::string & wholePath,std::string & normalPath,std::vector<std::string> & out)483 bool CJInitialize::WholeToNormal(const std::string &wholePath, std::string &normalPath, std::vector<std::string> &out)
484 {
485     std::vector<std::string> elems;
486     StringSplit(wholePath, '/', elems);
487     if (!PathVecToNormal(elems, out)) {
488         return false;
489     }
490     for (auto elem : out) {
491         normalPath += "/" + elem;
492     }
493     return true;
494 }
495 
UploadBodyFileProc(std::string & fileName,Config & config)496 ExceptionError CJInitialize::UploadBodyFileProc(std::string &fileName, Config &config)
497 {
498     int32_t bodyFd = open(fileName.c_str(), O_TRUNC | O_RDWR);
499     if (bodyFd < 0) {
500         bodyFd = open(fileName.c_str(), O_CREAT | O_RDWR, FILE_PERMISSION);
501         if (bodyFd < 0) {
502             return {
503                 .code = ExceptionErrorCode::E_FILE_IO,
504                 .errInfo = "Failed to open file errno " + std::to_string(errno)
505             };
506         }
507     }
508 
509     if (bodyFd >= 0) {
510         chmod(fileName.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWOTH);
511         close(bodyFd);
512     }
513     config.bodyFileNames.push_back(fileName);
514 
515     return {
516         .code = ExceptionErrorCode::E_OK
517     };
518 }
519 
CheckUploadBodyFiles(Config & config,const std::string & filePath)520 ExceptionError CJInitialize::CheckUploadBodyFiles(Config &config, const std::string &filePath)
521 {
522     size_t len = config.files.size();
523     for (size_t i = 0; i < len; i++) {
524         if (filePath.empty()) {
525             REQUEST_HILOGE("internal to cache error");
526             return {
527                 .code = ExceptionErrorCode::E_PARAMETER_CHECK,
528                 .errInfo = "IsPathValid error empty path"
529             };
530         }
531         auto now = std::chrono::high_resolution_clock::now();
532         auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
533         std::string fileName = filePath + "/tmp_body_" + std::to_string(i) + "_" + std::to_string(timestamp);
534         REQUEST_HILOGD("Create upload body file, %{public}s", fileName.c_str());
535         if (!IsPathValid(fileName)) {
536             REQUEST_HILOGE("IsPathValid error %{public}s", fileName.c_str());
537             return {
538                 .code = ExceptionErrorCode::E_PARAMETER_CHECK,
539                 .errInfo = "IsPathValid error fail path"
540             };
541         }
542         ExceptionError ret = UploadBodyFileProc(fileName, config);
543         if (ret.code != ExceptionErrorCode::E_OK) {
544             return ret;
545         }
546     }
547     return {
548         .code = ExceptionErrorCode::E_OK
549     };
550 }
551 
InterceptData(const std::string & str,const std::string & in,std::string & out)552 bool CJInitialize::InterceptData(const std::string &str, const std::string &in, std::string &out)
553 {
554     std::string tmpStr = std::string(in, 0, in.find_last_not_of(' ') + 1);
555     std::size_t position = tmpStr.find_last_of(str);
556     // when the str at last index, will error.
557     if (position == std::string::npos || position + 1 >= tmpStr.size()) {
558         return false;
559     }
560     out = std::string(tmpStr, position + 1);
561     return true;
562 }
563 
GetFD(const std::string & path,const Config & config,int32_t & fd)564 ExceptionError CJInitialize::GetFD(const std::string &path, const Config &config, int32_t &fd)
565 {
566     ExceptionError error = { .code = ExceptionErrorCode::E_OK };
567     fd = config.action == Action::UPLOAD ? open(path.c_str(), O_RDONLY) : open(path.c_str(), O_TRUNC | O_RDWR);
568     if (fd >= 0) {
569         REQUEST_HILOGD("File already exists");
570         if (config.action == Action::UPLOAD) {
571             chmod(path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
572             close(fd);
573             return error;
574         } else {
575             chmod(path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWOTH);
576         }
577 
578         if (config.overwrite) {
579             close(fd);
580             return error;
581         }
582         if (!config.firstInit) {
583             REQUEST_HILOGD("CJTask config is not firstInit");
584             close(fd);
585             return error;
586         }
587         close(fd);
588         ExceptionErrorCode code = ExceptionErrorCode::E_FILE_IO;
589         return {
590             .code = code,
591             .errInfo = "Download File already exists"
592         };
593     } else {
594         if (config.action == Action::UPLOAD) {
595             ExceptionErrorCode code = ExceptionErrorCode::E_FILE_IO;
596             return {
597                 .code = code,
598                 .errInfo = "Failed to open file errno " + std::to_string(errno)
599             };
600         }
601         fd = open(path.c_str(), O_CREAT | O_RDWR, FILE_PERMISSION);
602         if (fd < 0) {
603             return {
604                 .code = ExceptionErrorCode::E_FILE_IO,
605                 .errInfo = "Failed to open file errno " +std::to_string(errno)
606             };
607         }
608         chmod(path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWOTH);
609         close(fd);
610     }
611     return error;
612 }
613 
GetInternalPath(const std::string & fileUri,const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,Config & config,std::string & filePath)614 bool CJInitialize::GetInternalPath(const std::string &fileUri,
615     const std::shared_ptr<OHOS::AbilityRuntime::Context> &context, Config &config, std::string &filePath)
616 {
617     if (config.action == Action::DOWNLOAD && fileUri.find('/') == 0) {
618         filePath = fileUri;
619         return true;
620     }
621     std::string fileName;
622     std::string pattern = "./";
623     size_t pos = fileUri.find(pattern);
624     if (pos != 0) {
625         fileName = fileUri;
626     } else {
627         fileName = fileUri.substr(pattern.size(), fileUri.size());
628     }
629     if (fileName.empty()) {
630         return false;
631     }
632     filePath = context->GetCacheDir();
633     if (filePath.empty()) {
634         REQUEST_HILOGE("internal to cache error");
635         return false;
636     }
637 
638     filePath += "/" + fileName;
639     if (!IsPathValid(filePath)) {
640         REQUEST_HILOGE("IsPathValid error %{public}s", filePath.c_str());
641         return false;
642     }
643     return true;
644 }
645 
CheckFileSpec(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,Config & config)646 ExceptionError CJInitialize::CheckFileSpec(const std::shared_ptr<OHOS::AbilityRuntime::Context> &context,
647     Config &config)
648 {
649     ExceptionError err = { .code = ExceptionErrorCode::E_OK };
650     for (auto &file : config.files) {
651         std::string path;
652         if (!GetInternalPath(file.uri, context, config, path)) {
653             return {
654                 .code = ExceptionErrorCode::E_PARAMETER_CHECK,
655                 .errInfo = "this is fail path"
656             };
657         }
658         file.uri = path;
659         if (file.filename.empty()) {
660             InterceptData("/", file.uri, file.filename);
661         }
662         if (file.type.empty()) {
663             InterceptData(".", file.filename, file.type);
664         }
665         if (file.name.empty()) {
666             file.name = "file";
667         }
668 
669         if (!CJTask::SetPathPermission(file.uri)) {
670             return {
671                 .code = ExceptionErrorCode::E_FILE_IO,
672                 .errInfo = "set path permission fail"
673             };
674         }
675 
676         err = GetFD(path, config, file.fd);
677         if (err.code != ExceptionErrorCode::E_OK) {
678             return err;
679         }
680     }
681     return err;
682 }
683 
CheckFilePath(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,Config & config)684 ExceptionError CJInitialize::CheckFilePath(const std::shared_ptr<OHOS::AbilityRuntime::Context> &context,
685     Config &config)
686 {
687     ExceptionError err = { .code = ExceptionErrorCode::E_OK };
688     if (config.action == Action::DOWNLOAD) {
689         if (!CheckDownloadFilePath(context, config, err.errInfo)) {
690             err.code = ExceptionErrorCode::E_PARAMETER_CHECK;
691             return err;
692         }
693 
694         FileSpec file = { .uri = config.saveas };
695         config.files.push_back(file);
696     }
697 
698     err = CheckFileSpec(context, config);
699     if (err.code != ExceptionErrorCode::E_OK) {
700         return err;
701     }
702 
703     if (!CJTask::SetDirsPermission(config.certsPath)) {
704         return {
705             .code = ExceptionErrorCode::E_FILE_IO,
706             .errInfo = "set files of directors permission fail"
707         };
708     }
709 
710     if (config.action == Action::UPLOAD) {
711         std::string filePath = context->GetCacheDir();
712         err = CheckUploadBodyFiles(config, filePath);
713     }
714 
715     return err;
716 }
717 
ParseConfig(OHOS::AbilityRuntime::Context * stageContext,const CConfig * ffiConfig,Config & config)718 ExceptionError CJInitialize::ParseConfig(OHOS::AbilityRuntime::Context *stageContext, const CConfig *ffiConfig,
719     Config &config)
720 {
721     config.action = (OHOS::Request::Action)ffiConfig->action;
722     config.withErrCode = true;
723     config.version = Version::API10; // CJ only support API10
724 
725     if (stageContext == nullptr) {
726         return {
727             .code = ExceptionErrorCode::E_PARAMETER_CHECK,
728             .errInfo = "Get context fail"
729         };
730     }
731 
732     std::shared_ptr<OHOS::AbilityRuntime::Context> context = stageContext->shared_from_this();
733     ExceptionError ret = ParseBundleName(context, config.bundleName);
734     if (ret.code != 0) {
735         return ret;
736     }
737     ret.code = ExceptionErrorCode::E_PARAMETER_CHECK;
738     if (!ParseUrl(config.url)) {
739         ret.errInfo = "parse url error";
740         return ret;
741     }
742 
743     if (!ParseCertsPath(config.url, config.certsPath)) {
744         ret.errInfo = "parse certs path error";
745         return ret;
746     }
747 
748     if (!ParseData(ffiConfig, config)) {
749         ret.errInfo = "parse data error";
750         return ret;
751     }
752 
753     if (!ParseIndex(config)) {
754         ret.errInfo = "Index exceeds file list";
755         return ret;
756     }
757 
758     if (!ParseTitle(config) ||
759         !ParseToken(config) ||
760         !ParseDescription(config.description)) {
761         ret.errInfo = "Exceeding maximum length";
762         return ret;
763     }
764 
765     if (!ParseSaveas(config)) {
766         ret.errInfo = "parse saveas error";
767         return ret;
768     }
769 
770     ParseMethod(config);
771     ParseNetwork(config.network);
772     ParseBackGround(config.mode, config.background);
773     config.begins = ParseBegins(config.begins);
774 
775     return CheckFilePath(context, config);
776 }
777 
FindDir(const std::string & pathDir)778 bool CJInitialize::FindDir(const std::string &pathDir)
779 {
780     std::error_code err;
781     return std::filesystem::exists(pathDir, err);
782 }
783 
784 
785 } // namespace OHOS::CJSystemapi::Request
786