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