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 #ifndef JS_CONCURRENT_MODULE_COMMON_HELPER_PATH_HELPER_H
17 #define JS_CONCURRENT_MODULE_COMMON_HELPER_PATH_HELPER_H
18 
19 #include <vector>
20 #include <string>
21 
22 #include "native_engine/native_engine.h"
23 #include "tools/log.h"
24 
25 namespace Commonlibrary::Concurrent::Common::Helper {
26 class PathHelper {
27 public:
28     static constexpr char PREFIX_BUNDLE[] = "@bundle:";
29     static constexpr char DOUBLE_POINT_TAG[] = "..";
30     static constexpr char NAME_SPACE_TAG = '@';
31     static constexpr char POINT_TAG[] = ".";
32     static constexpr char SLASH_TAG = '/';
33     static constexpr char EXT_NAME_ETS[] = ".ets";
34     static constexpr char EXT_NAME_TS[] = ".ts";
35     static constexpr char EXT_NAME_JS[] = ".js";
36     static constexpr char PAG_TAG[] = "pkg_modules";
37     static constexpr char NORMALIZED_OHMURL_TAG = '&';
38     static constexpr char PHYCICAL_FILE_PATH[] = "src/main";
39     static constexpr size_t NORMALIZED_OHMURL_ARGS_NUM = 5;
40 
CheckWorkerPath(napi_env env,std::string script,std::string fileName,bool isRelativePath)41     static bool CheckWorkerPath(napi_env env, std::string script, std::string fileName, bool isRelativePath)
42     {
43         std::string ohmurl = "";
44         std::string moduleName = "";
45         std::string bundleName = "";
46         if (script.find(PAG_TAG) == 0 || script.find(NAME_SPACE_TAG) != std::string::npos) {
47             HILOG_INFO("worker:: the HAR path cannot be verified");
48             return true;
49         }
50 
51         bool isNormalizedOhmUrlPack = reinterpret_cast<NativeEngine*>(env)->GetIsNormalizedOhmUrlPack();
52         if (isNormalizedOhmUrlPack) {
53             return CheckNormalizedWorkerPath(env, script, fileName, isRelativePath);
54         }
55         size_t prev = script.find_first_of(SLASH_TAG);
56         while (prev == 0 && script != "") {
57             script = script.substr(1);
58             prev = script.find_first_of(SLASH_TAG);
59         }
60         if (isRelativePath) {
61             if (prev != std::string::npos) {
62                 bundleName = script.substr(0, prev);
63             }
64             std::string temp = script.substr(prev + 1);
65             prev = temp.find_first_of(SLASH_TAG);
66             if (prev != std::string::npos) {
67                 moduleName = temp.substr(0, prev);
68             }
69             ohmurl = PREFIX_BUNDLE + script;
70         } else {
71             if (prev != std::string::npos) {
72                 moduleName = script.substr(0, prev);
73             }
74             bundleName = reinterpret_cast<NativeEngine*>(env)->GetBundleName();
75             prev = script.find_last_of(POINT_TAG);
76             if (prev != std::string::npos) {
77                 script = script.substr(0, prev);
78             }
79             ohmurl = PREFIX_BUNDLE + bundleName + SLASH_TAG + script;
80         }
81         return reinterpret_cast<NativeEngine*>(env)->IsExecuteModuleInAbcFile(bundleName, moduleName, ohmurl);
82     }
83 
CheckNormalizedWorkerPath(napi_env env,std::string script,std::string fileName,bool isRelativePath)84     static bool CheckNormalizedWorkerPath(napi_env env, std::string script, std::string fileName, bool isRelativePath)
85     {
86         std::string ohmurl = "";
87         std::string moduleName = "";
88         std::string bundleName = "";
89         if (isRelativePath) {
90             size_t prev = fileName.find_first_of(SLASH_TAG);
91             if (prev != std::string::npos) {
92                 moduleName = fileName.substr(0, prev);
93             }
94             ohmurl = script;
95         } else {
96             size_t prev = script.find_last_of(POINT_TAG);
97             if (prev != std::string::npos) {
98                 script = script.substr(0, prev);
99             }
100             prev = script.find_first_of(SLASH_TAG);
101             std::string path;
102             if (prev != std::string::npos) {
103                 moduleName = script.substr(0, prev);
104                 path = script.substr(prev);
105             }
106             bundleName = reinterpret_cast<NativeEngine*>(env)->GetBundleName();
107             std::string pkgName = reinterpret_cast<NativeEngine*>(env)->GetPkgName(moduleName);
108             ohmurl = NORMALIZED_OHMURL_TAG + pkgName + SLASH_TAG + PHYCICAL_FILE_PATH + path + NORMALIZED_OHMURL_TAG;
109         }
110         return reinterpret_cast<NativeEngine*>(env)->IsExecuteModuleInAbcFile(bundleName, moduleName, ohmurl);
111     }
112 
ConcatFileNameForWorker(napi_env env,std::string & script,std::string & fileName,bool & isRelativePath)113     static void ConcatFileNameForWorker(napi_env env, std::string &script, std::string &fileName, bool &isRelativePath)
114     {
115         std::string moduleName;
116         if (script.find_first_of(POINT_TAG) == 0) {
117             isRelativePath = true;
118         }
119         reinterpret_cast<NativeEngine*>(env)->GetCurrentModuleInfo(moduleName, fileName, isRelativePath);
120         if (isRelativePath) {
121             // if input is relative path, need to concat new recordName.
122             std::string recordName = moduleName;
123             size_t pos = moduleName.rfind(SLASH_TAG);
124             if (pos != std::string::npos) {
125                 moduleName = moduleName.substr(0, pos + 1); // from spcific file to dir
126             }
127             script = moduleName + script;
128             script = NormalizePath(script); // remove ../ and .ets
129 
130             if (recordName.at(0) == NORMALIZED_OHMURL_TAG) {
131                 script.append(1, NORMALIZED_OHMURL_TAG);
132                 std::vector<std::string> normalizedRes = SplitNormalizedRecordName(recordName);
133                 script += normalizedRes[NORMALIZED_OHMURL_ARGS_NUM - 1];
134             }
135         } else {
136             script = moduleName + script;
137         }
138     }
139 
NormalizePath(const std::string & entryPoint)140     static std::string NormalizePath(const std::string &entryPoint)
141     {
142         std::string res;
143         size_t prev = 0;
144         size_t curr = entryPoint.find(SLASH_TAG);
145         std::vector<std::string> elems;
146         // eliminate parent directory path
147         while (curr != std::string::npos) {
148             if (curr > prev) {
149                 std::string elem = entryPoint.substr(prev, curr - prev);
150                 if (elem == DOUBLE_POINT_TAG && entryPoint.at(curr) == SLASH_TAG
151                     && !elems.empty()) { // looking for xxx/../
152                     elems.pop_back();
153                 } else if (elem != POINT_TAG && elem != DOUBLE_POINT_TAG) { // remove ./
154                     elems.push_back(elem);
155                 }
156             }
157             prev = curr + 1;
158             curr = entryPoint.find(SLASH_TAG, prev);
159         }
160         if (prev != entryPoint.size()) {
161             elems.push_back(entryPoint.substr(prev));
162         }
163         for (auto e : elems) {
164             if (res.size() == 0 && entryPoint.at(0) != SLASH_TAG) {
165                 res.append(e);
166                 continue;
167             }
168             res.append(1, SLASH_TAG).append(e);
169         }
170         // remore suffix
171         size_t pos = res.rfind(POINT_TAG);
172         if (pos != std::string::npos) {
173             std::string suffix = res.substr(pos);
174             if (suffix == EXT_NAME_ETS || suffix == EXT_NAME_TS || suffix == EXT_NAME_JS) {
175                 res.erase(pos, suffix.length());
176             }
177         }
178         return res;
179     }
180 
181     /*
182     *  Split the recordName of the new ohmurl rule
183     *  recordName: &moduleName&bundleName&importPath&version
184     */
SplitNormalizedRecordName(const std::string & recordName)185     static std::vector<std::string> SplitNormalizedRecordName(const std::string &recordName)
186     {
187         std::vector<std::string> res(NORMALIZED_OHMURL_ARGS_NUM);
188         int index = NORMALIZED_OHMURL_ARGS_NUM - 1;
189         std::string temp;
190         int endIndex = static_cast<int>(recordName.size()) - 1;
191         for (int i = endIndex; i >= 0; i--) {
192             char element = recordName[i];
193             if (element == NORMALIZED_OHMURL_TAG) {
194                 res[index] = temp;
195                 index--;
196                 temp = "";
197                 continue;
198             }
199             temp = element + temp;
200         }
201         if (temp.size()) {
202             res[index] = temp;
203         }
204         return res;
205     }
206 };
207 } // namespace Commonlibrary::Concurrent::Common::Helper
208 #endif // JS_CONCURRENT_MODULE_COMMON_HELPER_OBJECT_HELPER_H
209