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 "medialibrary_command.h"
17 
18 #include "media_file_uri.h"
19 #include "media_file_utils.h"
20 #include "media_log.h"
21 #include "medialibrary_data_manager_utils.h"
22 #include "medialibrary_db_const.h"
23 #include "medialibrary_unistore_manager.h"
24 #include "medialibrary_errno.h"
25 #include "userfilemgr_uri.h"
26 
27 using namespace std;
28 using namespace OHOS::NativeRdb;
29 using namespace OHOS::DataShare;
30 
31 namespace OHOS {
32 namespace Media {
33 
MediaLibraryCommand(const Uri & uri)34 MediaLibraryCommand::MediaLibraryCommand(const Uri &uri) : uri_(uri)
35 {
36     ParseOprnObjectFromUri();
37     ParseOprnTypeFromUri();
38     ParseQuerySetMapFromUri();
39     SetApiFromQuerySetMap();
40     ParseOprnObjectFromFileUri();
41     ParseTableName();
42 }
43 
MediaLibraryCommand(const Uri & uri,const ValuesBucket & value)44 MediaLibraryCommand::MediaLibraryCommand(const Uri &uri, const ValuesBucket &value) : uri_(uri), insertValue_(value)
45 {
46     ParseOprnObjectFromUri();
47     ParseOprnTypeFromUri();
48     ParseQuerySetMapFromUri();
49     SetApiFromQuerySetMap();
50     ParseOprnObjectFromFileUri();
51     ParseTableName();
52 }
53 
MediaLibraryCommand(const Uri & uri,const OperationType & oprnType)54 MediaLibraryCommand::MediaLibraryCommand(const Uri &uri, const OperationType &oprnType) : uri_(uri), oprnType_(oprnType)
55 {
56     ParseOprnObjectFromUri();
57     ParseQuerySetMapFromUri();
58     SetApiFromQuerySetMap();
59     ParseOprnObjectFromFileUri();
60     ParseTableName();
61 }
62 
MediaLibraryCommand(const OperationObject & oprnObject,const OperationType & oprnType,MediaLibraryApi api)63 MediaLibraryCommand::MediaLibraryCommand(const OperationObject &oprnObject, const OperationType &oprnType,
64     MediaLibraryApi api) : oprnObject_(oprnObject), oprnType_(oprnType), api_(api)
65 {
66     ParseTableName();
67 }
68 
MediaLibraryCommand(const OperationObject & oprnObject,const OperationType & oprnType,const ValuesBucket & value,MediaLibraryApi api)69 MediaLibraryCommand::MediaLibraryCommand(const OperationObject &oprnObject, const OperationType &oprnType,
70     const ValuesBucket &value, MediaLibraryApi api) :insertValue_(value), oprnObject_(oprnObject),
71     oprnType_(oprnType), api_(api)
72 {
73     ParseTableName();
74 }
75 
MediaLibraryCommand(const OperationObject & oprnObject,const OperationType & oprnType,const string & networkId,MediaLibraryApi api)76 MediaLibraryCommand::MediaLibraryCommand(const OperationObject &oprnObject, const OperationType &oprnType,
77     const string &networkId, MediaLibraryApi api) : oprnObject_(oprnObject), oprnType_(oprnType),
78     oprnDevice_(networkId), api_(api)
79 {
80     ParseTableName();
81 }
82 
~MediaLibraryCommand()83 MediaLibraryCommand::~MediaLibraryCommand() {}
84 
85 // set functions
SetOprnObject(OperationObject object)86 void MediaLibraryCommand::SetOprnObject(OperationObject object)
87 {
88     oprnObject_ = object;
89 }
90 
SetOprnAssetId(const std::string & oprnId)91 void MediaLibraryCommand::SetOprnAssetId(const std::string &oprnId)
92 {
93     oprnFileId_ = oprnId;
94 }
95 
SetValueBucket(const NativeRdb::ValuesBucket & value)96 void MediaLibraryCommand::SetValueBucket(const NativeRdb::ValuesBucket &value)
97 {
98     insertValue_ = value;
99 }
100 
SetTableName(const std::string & tableName)101 void MediaLibraryCommand::SetTableName(const std::string &tableName)
102 {
103     tableName_ = tableName;
104 }
105 
SetBundleName(const std::string & bundleName)106 void MediaLibraryCommand::SetBundleName(const std::string &bundleName)
107 {
108     bundleName_ = bundleName;
109 }
110 
SetDeviceName(const std::string & deviceName)111 void MediaLibraryCommand::SetDeviceName(const std::string &deviceName)
112 {
113     deviceName_ = deviceName;
114 }
115 
SetResult(const std::string & result)116 void MediaLibraryCommand::SetResult(const std::string &result)
117 {
118     result_ = result;
119 }
120 
IsDataSharePredNull() const121 bool MediaLibraryCommand::IsDataSharePredNull() const
122 {
123     return datasharePred_ == nullptr;
124 }
125 
126 // get functions
GetOprnObject() const127 OperationObject MediaLibraryCommand::GetOprnObject() const
128 {
129     return oprnObject_;
130 }
131 
GetOprnType() const132 OperationType MediaLibraryCommand::GetOprnType() const
133 {
134     return oprnType_;
135 }
136 
GetValueBucket()137 ValuesBucket &MediaLibraryCommand::GetValueBucket()
138 {
139     return insertValue_;
140 }
141 
GetAbsRdbPredicates()142 AbsRdbPredicates *MediaLibraryCommand::GetAbsRdbPredicates()
143 {
144     if (absRdbPredicates_ == nullptr) {
145         InitAbsRdbPredicates();
146     }
147     return absRdbPredicates_.get();
148 }
149 
GetTableName()150 const string &MediaLibraryCommand::GetTableName()
151 {
152     if (tableName_.empty()) {
153         ParseTableName();
154     }
155 
156     return tableName_;
157 }
158 
GetOprnFileId()159 const string &MediaLibraryCommand::GetOprnFileId()
160 {
161     if (oprnFileId_.empty()) {
162         ParseFileId();
163     }
164 
165     return oprnFileId_;
166 }
167 
GetOprnDevice()168 const string &MediaLibraryCommand::GetOprnDevice()
169 {
170     if (oprnDevice_.empty()) {
171         oprnDevice_ = MediaFileUtils::GetNetworkIdFromUri(uri_.ToString());
172     }
173     return oprnDevice_;
174 }
175 
GetUri() const176 const Uri &MediaLibraryCommand::GetUri() const
177 {
178     return uri_;
179 }
180 
GetBundleName()181 const string &MediaLibraryCommand::GetBundleName()
182 {
183     return bundleName_;
184 }
185 
GetDeviceName()186 const string &MediaLibraryCommand::GetDeviceName()
187 {
188     return deviceName_;
189 }
190 
GetResult()191 const string &MediaLibraryCommand::GetResult()
192 {
193     return result_;
194 }
195 
GetUriStringWithoutSegment() const196 string MediaLibraryCommand::GetUriStringWithoutSegment() const
197 {
198     string uriString = uri_.ToString();
199     size_t questionMaskPoint = uriString.rfind('?');
200     size_t hashKeyPoint = uriString.rfind('#');
201     if (questionMaskPoint != string::npos) {
202         return uriString.substr(0, questionMaskPoint);
203     }
204     if (hashKeyPoint != string::npos) {
205         return uriString.substr(0, hashKeyPoint);
206     }
207     return uriString;
208 }
209 
GetApi()210 MediaLibraryApi MediaLibraryCommand::GetApi()
211 {
212     return api_;
213 }
214 
GetQuerySetParam(const std::string & key)215 string MediaLibraryCommand::GetQuerySetParam(const std::string &key)
216 {
217     if (key.empty() || querySetMap_.find(key) == querySetMap_.end()) {
218         return "";
219     }
220     return querySetMap_[key];
221 }
222 
ParseOprnObjectFromUri()223 void MediaLibraryCommand::ParseOprnObjectFromUri()
224 {
225     const string opObject = MediaFileUri::GetPathFirstDentry(uri_);
226     if (OPRN_OBJ_MAP.find(opObject) != OPRN_OBJ_MAP.end()) {
227         oprnObject_ = OPRN_OBJ_MAP.at(opObject);
228     }
229     MEDIA_DEBUG_LOG("Command operation object is %{public}d", oprnObject_);
230 }
231 
ParseOprnTypeFromUri()232 void MediaLibraryCommand::ParseOprnTypeFromUri()
233 {
234     const string opType = MediaFileUri::GetPathSecondDentry(uri_);
235     if (OPRN_TYPE_MAP.find(opType) != OPRN_TYPE_MAP.end()) {
236         oprnType_ = OPRN_TYPE_MAP.at(opType);
237     } else {
238         oprnType_ = OperationType::QUERY;
239     }
240     MEDIA_DEBUG_LOG("Command operation type is %{public}d", oprnType_);
241 }
242 
GetDistTable(const string & table,const string & networkId)243 static string GetDistTable(const string &table, const string &networkId)
244 {
245     string ret = MEDIALIBRARY_TABLE;
246     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
247     if (rdbStore == nullptr) {
248         return ret;
249     }
250 
251     int errCode = E_ERR;
252     if (table == PhotoColumn::PHOTOS_TABLE || table == AudioColumn::AUDIOS_TABLE) {
253         ret = rdbStore->ObtainDistributedTableName(networkId, table, errCode);
254     } else {
255         ret = rdbStore->ObtainDistributedTableName(networkId, MEDIALIBRARY_TABLE, errCode);
256     }
257     return ret;
258 }
259 
ParseTableName()260 void MediaLibraryCommand::ParseTableName()
261 {
262     if (TABLE_NAME_MAP.find(oprnObject_) != TABLE_NAME_MAP.end()) {
263         auto cmdObj = TABLE_NAME_MAP.at(oprnObject_);
264         if (cmdObj.find(oprnType_) != cmdObj.end()) {
265             tableName_ = cmdObj.at(oprnType_);
266         } else if (cmdObj.find(OperationType::UNKNOWN_TYPE) != cmdObj.end()) {
267             tableName_ = cmdObj.at(OperationType::UNKNOWN_TYPE);
268         } else {
269             tableName_ = MEDIALIBRARY_TABLE;
270         }
271     } else {
272         tableName_ = MEDIALIBRARY_TABLE;
273     }
274     // distributed tablename, smartalbum and smartalbumMap can not distributed
275     if ((oprnObject_ == OperationObject::SMART_ALBUM) || (oprnObject_ == OperationObject::SMART_ALBUM_MAP)) {
276         MEDIA_DEBUG_LOG("smart table name is %{public}s", tableName_.c_str());
277         return;
278     }
279     // distributed tablename
280     auto networkId = GetOprnDevice();
281     if (networkId.empty()) {
282         return;
283     }
284     tableName_ = GetDistTable(tableName_, networkId);
285     MEDIA_INFO_LOG("Table name is %{public}s", tableName_.c_str());
286 }
287 
InitAbsRdbPredicates()288 void MediaLibraryCommand::InitAbsRdbPredicates()
289 {
290     if (tableName_.empty()) {
291         ParseTableName();
292     }
293     absRdbPredicates_ = make_unique<AbsRdbPredicates>(tableName_);
294 }
295 
ParseFileId()296 void MediaLibraryCommand::ParseFileId()
297 {
298     int32_t fileIdInValue = -1;
299     ValueObject valueObject;
300     if (insertValue_.GetObject(MEDIA_DATA_DB_ID, valueObject)) {
301         valueObject.GetInt(fileIdInValue);
302     }
303     if (fileIdInValue != -1) {
304         oprnFileId_ = to_string(fileIdInValue);
305         return;
306     }
307     string uriInValue;
308     if (insertValue_.GetObject(MEDIA_DATA_DB_URI, valueObject)) {
309         valueObject.GetString(uriInValue);
310     }
311     if (uriInValue.empty()) {
312         uriInValue = GetUriStringWithoutSegment();
313     }
314 
315     string idFromUri = MediaFileUtils::GetIdFromUri(uriInValue);
316     if (!MediaLibraryDataManagerUtils::IsNumber(idFromUri)) {
317         return;
318     }
319     oprnFileId_ = idFromUri;
320 }
321 
ParseQuerySetMapFromUri()322 void MediaLibraryCommand::ParseQuerySetMapFromUri()
323 {
324     // uri format: datashare:///media/photo_operation/create_asset?op1=xxx&op2=yyy&api_version=10#abc
325     // QuerySetMap: {"op1": "xxx", "op2": "yyy", "api_version": "10"}
326     string uriStr = uri_.ToString();
327     size_t cutPoint = uriStr.find('#');
328     if (cutPoint != string::npos) {
329         uriStr = uriStr.substr(0, cutPoint);
330     }
331     MediaFileUri mediaUri(uriStr);
332     querySetMap_ = mediaUri.GetQueryKeys();
333 }
334 
SetApiFromQuerySetMap()335 void MediaLibraryCommand::SetApiFromQuerySetMap()
336 {
337     if (querySetMap_.find(URI_PARAM_API_VERSION) == querySetMap_.end()) {
338         api_ = MediaLibraryApi::API_OLD;
339     } else {
340         string apiString = querySetMap_[URI_PARAM_API_VERSION];
341         if (!MediaLibraryDataManagerUtils::IsNumber(apiString)) {
342             api_ = MediaLibraryApi::API_OLD;
343             return;
344         }
345         int32_t apiNum = stoi(apiString);
346         if (apiNum <= static_cast<int32_t>(MediaLibraryApi::API_START) ||
347             apiNum >= static_cast<int32_t>(MediaLibraryApi::API_END)) {
348             MEDIA_ERR_LOG("this api num is wrong: %{public}d", apiNum);
349             api_ = MediaLibraryApi::API_OLD;
350         } else {
351             api_ = static_cast<MediaLibraryApi>(apiNum);
352         }
353     }
354 }
355 
ParseOprnObjectFromFileUri()356 void MediaLibraryCommand::ParseOprnObjectFromFileUri()
357 {
358     if (oprnObject_ != OperationObject::UNKNOWN_OBJECT) {
359         return;
360     }
361 
362     string uri = uri_.ToString();
363     // parse cache file uri
364     if (MediaFileUtils::StartsWith(uri, PhotoColumn::PHOTO_CACHE_URI_PREFIX)) {
365         oprnObject_ = OperationObject::PAH_PHOTO;
366         return;
367     }
368 
369     for (const auto &item : OPRN_MAP) {
370         if (MediaFileUtils::StartsWith(uri, item.first)) {
371             oprnObject_ = item.second;
372             break;
373         }
374     }
375 }
376 
SetDataSharePred(const DataSharePredicates & pred)377 void MediaLibraryCommand::SetDataSharePred(const DataSharePredicates &pred)
378 {
379     datasharePred_ = make_unique<const DataSharePredicates>(pred);
380 }
381 
382 // Caller is responsible for calling SetDataSharePred() firstly, before calling GetDataSharePred()
GetDataSharePred() const383 const DataSharePredicates &MediaLibraryCommand::GetDataSharePred() const
384 {
385     return *datasharePred_;
386 }
387 } // namespace Media
388 } // namespace OHOS
389