1 /*
2  * Copyright (c) 2023 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 "file_uri.h"
17 
18 #include <unistd.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 
22 #include "uri.h"
23 
24 #include "common_func.h"
25 #include "log.h"
26 #include "sandbox_helper.h"
27 #include "parameter.h"
28 
29 using namespace std;
30 namespace OHOS {
31 namespace AppFileService {
32 namespace ModuleFileUri {
33 const std::string PATH_SHARE = "/data/storage/el2/share";
34 const std::string MODE_RW = "/rw/";
35 const std::string MODE_R = "/r/";
36 const std::string FILE_SCHEME_PREFIX = "file://";
37 const std::string FILE_MANAGER_AUTHORITY = "docs";
38 const std::string MEDIA_AUTHORITY = "media";
39 const std::string NETWORK_PARA = "?networkid=";
40 const std::string BACKFLASH = "/";
41 const std::string FULL_MOUNT_ENABLE_PARAMETER = "const.filemanager.full_mount.enable";
CheckFileManagerFullMountEnable()42 static bool CheckFileManagerFullMountEnable()
43 {
44     char value[] = "false";
45     int retSystem = GetParameter(FULL_MOUNT_ENABLE_PARAMETER.c_str(), "false", value, sizeof(value));
46     if (retSystem > 0 && !strcmp(value, "true")) {
47         LOGD("The full mount enable parameter is true");
48         return true;
49     }
50     LOGD("The full mount enable parameter is false");
51     return false;
52 }
53 
GetName()54 string FileUri::GetName()
55 {
56     string sandboxPath = SandboxHelper::Decode(uri_.GetPath());
57     size_t posLast = sandboxPath.find_last_of("/");
58     if (posLast == string::npos) {
59         return "";
60     }
61 
62     if (posLast == sandboxPath.size()) {
63         return "";
64     }
65 
66     return sandboxPath.substr(posLast + 1);
67 }
68 
GetPath()69 string FileUri::GetPath()
70 {
71     string sandboxPath = SandboxHelper::Decode(uri_.GetPath());
72     string bundleName = uri_.GetAuthority();
73     if (bundleName == MEDIA_AUTHORITY && sandboxPath.find(".") != string::npos) {
74         size_t pos = sandboxPath.rfind("/");
75         if (pos == string::npos) {
76             return "";
77         }
78         return sandboxPath.substr(0, pos);
79     }
80 
81     return sandboxPath;
82 }
83 
GetRealPath()84 string FileUri::GetRealPath()
85 {
86     string sandboxPath = SandboxHelper::Decode(uri_.GetPath());
87     string realPath = sandboxPath;
88     string bundleName = uri_.GetAuthority();
89     if (bundleName == FILE_MANAGER_AUTHORITY &&
90         uri_.ToString().find(NETWORK_PARA) == string::npos &&
91         (access(realPath.c_str(), F_OK) == 0 || CheckFileManagerFullMountEnable())) {
92         return realPath;
93     }
94 
95     if (((bundleName != "") && (bundleName != CommonFunc::GetSelfBundleName())) ||
96         uri_.ToString().find(NETWORK_PARA) != string::npos) {
97         realPath = PATH_SHARE + MODE_RW + bundleName + sandboxPath;
98         if (access(realPath.c_str(), F_OK) != 0) {
99             realPath = PATH_SHARE + MODE_R + bundleName + sandboxPath;
100         }
101     }
102     return realPath;
103 }
104 
GetRealPathBySA(const std::string & targetBundleName)105 string FileUri::GetRealPathBySA(const std::string &targetBundleName)
106 {
107     string sandboxPath = SandboxHelper::Decode(uri_.GetPath());
108     string realPath = sandboxPath;
109     string bundleName = uri_.GetAuthority();
110     if (bundleName == FILE_MANAGER_AUTHORITY &&
111         uri_.ToString().find(NETWORK_PARA) == string::npos &&
112         (access(realPath.c_str(), F_OK) == 0 || CheckFileManagerFullMountEnable())) {
113         return realPath;
114     }
115     realPath = PATH_SHARE + MODE_R + bundleName + sandboxPath;
116     return realPath;
117 }
118 
ToString()119 string FileUri::ToString()
120 {
121     return uri_.ToString();
122 }
123 
GetFullDirectoryUri()124 string FileUri::GetFullDirectoryUri()
125 {
126     string uri = uri_.ToString();
127     struct stat fileInfo;
128     if (stat(GetRealPath().c_str(), &fileInfo) != 0) {
129         LOGE("fileInfo is error,%{public}s", strerror(errno));
130         return "";
131     }
132     if (S_ISREG(fileInfo.st_mode)) {
133         LOGD("uri's st_mode is reg");
134         size_t pos = uri.rfind("/");
135         return uri.substr(0, pos);
136     }
137     if (S_ISDIR(fileInfo.st_mode)) {
138         LOGD("uri's st_mode is dir");
139         return uri;
140     }
141     LOGD("uri's st_mode is not reg and dir");
142     return "";
143 }
144 
IsRemoteUri()145 bool FileUri::IsRemoteUri()
146 {
147     size_t pos = uri_.ToString().find(NETWORK_PARA);
148     if (pos != string::npos && pos > 0 && pos < uri_.ToString().size() - NETWORK_PARA.size()) {
149         if (uri_.ToString().substr(pos + NETWORK_PARA.size()).find(BACKFLASH) == string::npos) {
150             return true;
151         }
152     }
153     return false;
154 }
155 
CheckUriFormat(const std::string & uri)156 bool FileUri::CheckUriFormat(const std::string &uri)
157 {
158     if (uri.find(FILE_SCHEME_PREFIX) != 0) {
159         LOGE("URI is missing file://");
160         return false;
161     }
162     return true;
163 }
164 
FileUri(const string & uriOrPath)165 FileUri::FileUri(const string &uriOrPath): uri_(
166     (uriOrPath.find(FILE_SCHEME_PREFIX) == 0) ? uriOrPath : CommonFunc::GetUriFromPath(uriOrPath)
167 )
168 {}
169 }
170 }  // namespace AppFileService
171 }  // namespace OHOS