1 /*
2  * Copyright (c) 2022 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 <cstdio>
17 #include <thread>
18 
19 #include "upload/file_adapter.h"
20 #include "upload/upload_task.h"
21 
22 using namespace OHOS::AppExecFwk;
23 namespace OHOS::Request::Upload {
ObtainFile()24 ObtainFile::ObtainFile()
25 {
26     fileAdapter_ = std::make_shared<FileAdapter>();
27 }
~ObtainFile()28 ObtainFile::~ObtainFile()
29 {
30 }
31 
GetFile(FILE **file, const std::string &fileUri, unsigned int &fileSize, std::shared_ptr<OHOS::AbilityRuntime::Context> &context)32 uint32_t ObtainFile::GetFile(FILE **file, const std::string &fileUri, unsigned int &fileSize,
33     std::shared_ptr<OHOS::AbilityRuntime::Context> &context)
34 {
35     uint32_t ret = UPLOAD_OK;
36     std::string dataAbilityHead("dataability");
37     std::string internalHead("internal");
38 
39     // file type check
40     if (fileUri.compare(0, dataAbilityHead.size(), dataAbilityHead) == 0) {
41         UPLOAD_HILOGD(UPLOAD_MODULE_FRAMEWORK, "GetDataAbilityFile");
42         ret = GetDataAbilityFile(file, fileUri, fileSize, context);
43     } else if (fileUri.compare(0, internalHead.size(), internalHead) == 0) {
44         UPLOAD_HILOGD(UPLOAD_MODULE_FRAMEWORK, "GetInternalFile");
45         ret = GetInternalFile(file, fileUri, fileSize, context);
46     } else {
47         UPLOAD_HILOGE(UPLOAD_MODULE_FRAMEWORK, "wrong path");
48         ret = UPLOAD_ERRORCODE_UNSUPPORT_URI;
49         *file = nullptr;
50         fileSize = 0;
51     }
52 
53     UPLOAD_HILOGD(UPLOAD_MODULE_FRAMEWORK, "get file ret : %{public}u, size : %{public}u", ret, fileSize);
54     return ret;
55 }
56 
GetDataAbilityFile(FILE **file, const std::string &fileUri, uint32_t &fileSize, std::shared_ptr<OHOS::AbilityRuntime::Context> &context)57 uint32_t ObtainFile::GetDataAbilityFile(FILE **file, const std::string &fileUri, uint32_t &fileSize,
58     std::shared_ptr<OHOS::AbilityRuntime::Context> &context)
59 {
60     uint32_t ret = UPLOAD_OK;
61     FILE *filePtr = nullptr;
62     int32_t fileLength = 0;
63 
64     do {
65         int32_t fd = fileAdapter_->DataAbilityOpenFile(fileUri, context);
66         if (fd < 0) {
67             UPLOAD_HILOGE(UPLOAD_MODULE_FRAMEWORK, "ObtainFile::GetDataAbilityFile, open file error.");
68             ret = UPLOAD_ERRORCODE_GET_FILE_ERROR;
69             break;
70         }
71 
72         filePtr = fdopen(fd, "r");
73         if (filePtr == nullptr) {
74             UPLOAD_HILOGE(UPLOAD_MODULE_FRAMEWORK, "ObtainFile::GetDataAbilityFile, fdopen error.");
75             ret = UPLOAD_ERRORCODE_GET_FILE_ERROR;
76             break;
77         }
78 
79         (void)fseek(filePtr, 0, SEEK_END);
80         fileLength = ftell(filePtr);
81         if (fileLength == -1) {
82             UPLOAD_HILOGE(UPLOAD_MODULE_FRAMEWORK, "ObtainFile::GetDataAbilityFile, ftell error.");
83             ret = UPLOAD_ERRORCODE_GET_FILE_ERROR;
84             break;
85         }
86         (void)fseek(filePtr, 0, SEEK_SET);
87     } while (0);
88 
89     *file = filePtr;
90     fileSize = static_cast<uint32_t>(fileLength);
91     return ret;
92 }
93 
IsValidPath(const std::string &filePath)94 bool ObtainFile::IsValidPath(const std::string &filePath)
95 {
96     char resolvedPath[PATH_MAX + 1] = { 0 };
97     if (filePath.length() > PATH_MAX || realpath(filePath.c_str(), resolvedPath) == nullptr
98         || strncmp(resolvedPath, filePath.c_str(), filePath.length()) != 0) {
99         UPLOAD_HILOGE(UPLOAD_MODULE_FRAMEWORK, "filePath error");
100         return false;
101     }
102     return true;
103 }
104 
SplitPath(const std::string &fileUri, std::string &fileName)105 bool ObtainFile::SplitPath(const std::string &fileUri, std::string &fileName)
106 {
107     std::string pattern = "internal://cache/";
108     size_t pos = fileUri.find(pattern);
109     if (pos != 0) {
110         UPLOAD_HILOGE(UPLOAD_MODULE_FRAMEWORK, "internal path is invalid");
111         return false;
112     }
113     fileName = fileUri.substr(pattern.size(), fileUri.size());
114     return true;
115 }
116 
GetInternalFile(FILE **file, const std::string &fileUri, uint32_t &fileSize, std::shared_ptr<OHOS::AbilityRuntime::Context> &context)117 uint32_t ObtainFile::GetInternalFile(FILE **file, const std::string &fileUri, uint32_t &fileSize,
118     std::shared_ptr<OHOS::AbilityRuntime::Context> &context)
119 {
120     std::string fileName;
121     if (!SplitPath(fileUri, fileName)) {
122         return UPLOAD_ERRORCODE_UNSUPPORT_URI;
123     }
124     std::string filePath = fileAdapter_->InternalGetFilePath(context);
125     if (filePath.empty()) {
126         UPLOAD_HILOGE(UPLOAD_MODULE_FRAMEWORK, "ObtainFile::GetInternalFile, internal to cache error");
127         return UPLOAD_ERRORCODE_GET_FILE_ERROR;
128     }
129     filePath += "/" + fileName;
130     if (!IsValidPath(filePath)) {
131         return UPLOAD_ERRORCODE_GET_FILE_ERROR;
132     }
133     FILE *filePtr = fopen(filePath.c_str(), "r");
134     if (filePtr == nullptr) {
135         UPLOAD_HILOGE(UPLOAD_MODULE_FRAMEWORK, "open file error, error info : %{public}d.", errno);
136         return UPLOAD_ERRORCODE_GET_FILE_ERROR;
137     }
138     (void)fseek(filePtr, 0, SEEK_END);
139     int32_t fileLength = ftell(filePtr);
140     (void)fseek(filePtr, 0, SEEK_SET);
141 
142     *file = filePtr;
143     fileSize = fileLength;
144     return UPLOAD_OK;
145 }
146 } // namespace OHOS::Request::Upload