• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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_data_ability.h"
17 
18 #include <algorithm>
19 #include <regex>
20 #include <unordered_set>
21 
22 #include "accesstoken_kit.h"
23 #include "bytrace.h"
24 #include "bundle_mgr_interface.h"
25 #include "file_ex.h"
26 #include "ipc_singleton.h"
27 #include "ipc_skeleton.h"
28 #include "sa_mgr_client.h"
29 #include "string_ex.h"
30 #include "sys_mgr_client.h"
31 #include "system_ability_definition.h"
32 #include "medialibrary_sync_table.h"
33 
34 using namespace std;
35 using namespace OHOS::AppExecFwk;
36 using namespace OHOS::NativeRdb;
37 using namespace OHOS::DistributedKv;
38 
39 namespace OHOS {
40 namespace Media {
41 namespace {
42 const std::unordered_set<int32_t> UID_FREE_CHECK {
43     1006        // file_manager:x:1006:
44 };
45 const std::unordered_set<std::string> BUNDLE_FREE_CHECK {
46     "com.ohos.medialibrary.MediaScannerAbilityA"
47 };
48 const std::unordered_set<std::string> SYSTEM_BUNDLE_FREE_CHECK {
49     "com.ohos.screenshot"
50 };
51 std::mutex bundleMgrMutex;
52 }
53 const std::string MediaLibraryDataAbility::PERMISSION_NAME_READ_MEDIA = "ohos.permission.READ_MEDIA";
54 const std::string MediaLibraryDataAbility::PERMISSION_NAME_WRITE_MEDIA = "ohos.permission.WRITE_MEDIA";
55 REGISTER_AA(MediaLibraryDataAbility);
56 
57 const std::vector<std::string> fileKeyWhiteListUSet = {
58     MEDIA_DATA_DB_ID,
59     MEDIA_DATA_DB_URI,
60     MEDIA_DATA_DB_FILE_PATH,
61     MEDIA_DATA_DB_SIZE,
62     MEDIA_DATA_DB_PARENT_ID,
63     MEDIA_DATA_DB_DATE_MODIFIED,
64     MEDIA_DATA_DB_DATE_ADDED,
65     MEDIA_DATA_DB_MIME_TYPE,
66     MEDIA_DATA_DB_TITLE,
67     MEDIA_DATA_DB_DESCRIPTION,
68     MEDIA_DATA_DB_NAME,
69     MEDIA_DATA_DB_ORIENTATION,
70     MEDIA_DATA_DB_LATITUDE,
71     MEDIA_DATA_DB_LONGITUDE,
72     MEDIA_DATA_DB_DATE_TAKEN,
73     MEDIA_DATA_DB_THUMBNAIL,
74     MEDIA_DATA_DB_LCD,
75     MEDIA_DATA_DB_BUCKET_ID,
76     MEDIA_DATA_DB_BUCKET_NAME,
77     MEDIA_DATA_DB_DURATION,
78     MEDIA_DATA_DB_ARTIST,
79     MEDIA_DATA_DB_AUDIO_ALBUM,
80     MEDIA_DATA_DB_MEDIA_TYPE,
81     MEDIA_DATA_DB_HEIGHT,
82     MEDIA_DATA_DB_WIDTH,
83     MEDIA_DATA_DB_OWNER_PACKAGE,
84     MEDIA_DATA_DB_IS_FAV,
85     MEDIA_DATA_DB_IS_TRASH,
86     MEDIA_DATA_DB_DATE_TRASHED,
87     MEDIA_DATA_DB_IS_PENDING,
88     MEDIA_DATA_DB_TIME_PENDING,
89     MEDIA_DATA_DB_RELATIVE_PATH,
90     MEDIA_DATA_DB_VOLUME_NAME,
91     MEDIA_DATA_DB_SELF_ID,
92     MEDIA_DATA_DB_ALBUM,
93     MEDIA_DATA_DB_ALBUM_ID,
94     MEDIA_DATA_DB_ALBUM_NAME,
95     MEDIA_DATA_DB_COUNT,
96     MEDIA_DATA_DB_RINGTONE_URI,
97     MEDIA_DATA_DB_ALARM_URI,
98     MEDIA_DATA_DB_NOTIFICATION_URI,
99     MEDIA_DATA_DB_RINGTONE_TYPE
100 };
101 
OnStart(const AAFwk::Want & want)102 void MediaLibraryDataAbility::OnStart(const AAFwk::Want &want)
103 {
104     MEDIA_INFO_LOG("MediaLibraryDataAbility::OnStart");
105     Ability::OnStart(want);
106     InitMediaLibraryRdbStore();
107     MEDIA_INFO_LOG("bundleName = %{public}s", bundleName_.c_str());
108     auto abilityContext = std::make_unique<MediaLibraryDataAbility>(*this);
109     if (abilityContext != nullptr) {
110         MediaLibraryDevice::GetInstance()->SetAbilityContext(move(abilityContext));
111     }
112     SubscribeRdbStoreObserver();
113     InitDeviceData();
114 
115     if (rdbStore_ != nullptr) {
116         MEDIA_DEBUG_LOG("Distribute StartTrace:SyncPullAllTableTrace");
117         StartTrace(BYTRACE_TAG_OHOS, "SyncPullAllTableTrace");
118         MediaLibrarySyncTable syncTable;
119         syncTable.SyncPullAllTable(rdbStore_, bundleName_);
120         FinishTrace(BYTRACE_TAG_OHOS);
121         MEDIA_DEBUG_LOG("Distribute FinishTrace:SyncPullAllTableTrace");
122     }
123     InitialiseKvStore();
124 }
125 
OnStop()126 void MediaLibraryDataAbility::OnStop()
127 {
128     MEDIA_INFO_LOG("MediaLibraryDataAbility::OnStop");
129     Ability::OnStop();
130     rdbStore_ = nullptr;
131     isRdbStoreInitialized = false;
132 
133     if (scannerClient_ != nullptr) {
134         scannerClient_->Release();
135         scannerClient_ = nullptr;
136     }
137 
138     if (kvStorePtr_ != nullptr) {
139         dataManager_.CloseKvStore(KVSTORE_APPID, kvStorePtr_);
140         kvStorePtr_ = nullptr;
141     }
142     if (deviceStateCallback_ != nullptr && deviceInitCallback_ != nullptr) {
143         auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
144         deviceManager.UnInitDeviceManager(bundleName_);
145         deviceInitCallback_ = nullptr;
146         deviceManager.UnRegisterDevStateCallback(bundleName_);
147         deviceStateCallback_ = nullptr;
148         MediaLibraryDevice::GetInstance()->ClearAllDevices();
149     }
150     UnSubscribeRdbStoreObserver();
151 }
152 
MediaLibraryDataAbility(void)153 MediaLibraryDataAbility::MediaLibraryDataAbility(void)
154 {
155     isRdbStoreInitialized = false;
156     rdbStore_ = nullptr;
157     kvStorePtr_ = nullptr;
158     bundleName_ = DEVICE_BUNDLENAME;
159 }
160 
~MediaLibraryDataAbility(void)161 MediaLibraryDataAbility::~MediaLibraryDataAbility(void)
162 {
163     if (kvStorePtr_ != nullptr) {
164         dataManager_.CloseKvStore(KVSTORE_APPID, kvStorePtr_);
165         kvStorePtr_ = nullptr;
166     }
167 }
168 
OnCreate(RdbStore & store)169 int32_t MediaLibraryDataCallBack::OnCreate(RdbStore &store)
170 {
171     int32_t error_code = NativeRdb::E_ERROR;
172     error_code = store.ExecuteSql(CREATE_MEDIA_TABLE);
173     if (error_code == NativeRdb::E_OK) {
174         error_code = store.ExecuteSql(CREATE_SMARTALBUM_TABLE);
175     }
176     if (error_code == NativeRdb::E_OK) {
177         error_code = store.ExecuteSql(CREATE_SMARTALBUMMAP_TABLE);
178     }
179     if (error_code == NativeRdb::E_OK) {
180         error_code = store.ExecuteSql(CREATE_DEVICE_TABLE);
181     }
182     if (error_code == NativeRdb::E_OK) {
183         error_code = store.ExecuteSql(CREATE_CATEGORY_SMARTALBUMMAP_TABLE);
184     }
185     if (error_code == NativeRdb::E_OK) {
186         error_code = store.ExecuteSql(CREATE_IMAGE_VIEW);
187     }
188     if (error_code == NativeRdb::E_OK) {
189         error_code = store.ExecuteSql(CREATE_VIDEO_VIEW);
190     }
191     if (error_code == NativeRdb::E_OK) {
192         error_code = store.ExecuteSql(CREATE_AUDIO_VIEW);
193     }
194     if (error_code == NativeRdb::E_OK) {
195         error_code= store.ExecuteSql(CREATE_ABLUM_VIEW);
196     }
197     if (error_code == NativeRdb::E_OK) {
198         error_code= store.ExecuteSql(CREATE_SMARTABLUMASSETS_VIEW);
199     }
200     if (error_code == NativeRdb::E_OK) {
201         error_code= store.ExecuteSql(CREATE_ASSETMAP_VIEW);
202     }
203     if (error_code == NativeRdb::E_OK) {
204         isDistributedTables = true;
205     }
206     return error_code;
207 }
208 
OnUpgrade(RdbStore & store,int32_t oldVersion,int32_t newVersion)209 int32_t MediaLibraryDataCallBack::OnUpgrade(RdbStore &store, int32_t oldVersion, int32_t newVersion)
210 {
211 #ifdef RDB_UPGRADE_MOCK
212     const std::string ALTER_MOCK_COLUMN = "ALTER TABLE " + MEDIALIBRARY_TABLE +
213                                           " ADD COLUMN upgrade_test_column INT DEFAULT 0";
214     MEDIA_INFO_LOG("OnUpgrade |Rdb Verison %{public}d => %{public}d", oldVersion, newVersion);
215     int32_t error_code = NativeRdb::E_ERROR;
216     error_code = store.ExecuteSql(ALTER_MOCK_COLUMN);
217     if (error_code != NativeRdb::E_OK) {
218         MEDIA_INFO_LOG("Upgrade rdb error %{public}d", error_code);
219     }
220 #endif
221     return E_OK;
222 }
223 
GetDistributedTables()224 bool MediaLibraryDataCallBack::GetDistributedTables()
225 {
226     return isDistributedTables;
227 }
228 
InitMediaLibraryRdbStore()229 int32_t MediaLibraryDataAbility::InitMediaLibraryRdbStore()
230 {
231     MEDIA_INFO_LOG("InitMediaLibraryRdbStore IN |Rdb Verison %{public}d", MEDIA_RDB_VERSION);
232     if (isRdbStoreInitialized) {
233         return DATA_ABILITY_SUCCESS;
234     }
235 
236     int32_t errCode(DATA_ABILITY_FAIL);
237     auto context = GetAbilityContext();
238     if (context == nullptr) {
239         MEDIA_ERR_LOG("InitMediaRdbStore context is nullptr");
240         return errCode;
241     }
242 
243     string databaseDir = context->GetDatabaseDir();
244     string relativePath = MEDIA_DATA_ABILITY_DB_NAME;
245 
246     RdbStoreConfig config(databaseDir + "/" + relativePath);
247     config.SetBundleName(context->GetBundleName());
248     config.SetName(MEDIA_DATA_ABILITY_DB_NAME);
249     config.SetRelativePath(relativePath);
250     config.SetEncryptLevel(ENCRYPTION_LEVEL);
251     config.SetAppModuleName(context->GetHapModuleInfo()->moduleName);
252 
253     MediaLibraryDataCallBack rdbDataCallBack;
254 
255     rdbStore_ = RdbHelper::GetRdbStore(config, MEDIA_RDB_VERSION, rdbDataCallBack, errCode);
256     if (rdbStore_ == nullptr) {
257         MEDIA_ERR_LOG("InitMediaRdbStore GetRdbStore is failed ");
258         return errCode;
259     }
260 
261     if (rdbDataCallBack.GetDistributedTables()) {
262         auto ret = rdbStore_->SetDistributedTables(
263             {MEDIALIBRARY_TABLE, SMARTALBUM_TABLE, SMARTALBUM_MAP_TABLE, CATEGORY_SMARTALBUM_MAP_TABLE});
264         MEDIA_INFO_LOG("InitMediaLibraryRdbStore ret = %{public}d", ret);
265     }
266 
267     isRdbStoreInitialized = true;
268     mediaThumbnail_ = std::make_shared<MediaLibraryThumbnail>();
269     MEDIA_INFO_LOG("InitMediaLibraryRdbStore SUCCESS");
270     return DATA_ABILITY_SUCCESS;
271 }
272 
ExtractKeyWord(std::string & str)273 static void ExtractKeyWord(std::string &str)
274 {
275     if (str.empty()) {
276         return;
277     }
278     // add seprate space symbol,like file_id=?
279     std::regex spacePattern("\\=|\\<>|\\>|\\>=|\\<|\\<=|\\!=",
280         std::regex_constants::ECMAScript | std::regex_constants::icase);
281     str = regex_replace(str, spacePattern, " ");
282     // remove front space of key word
283     auto pos = str.find_first_not_of(" ");
284     if (pos != std::string::npos) {
285         str.erase(0, pos);
286     }
287     // remove back space of key word
288     pos = str.find_first_of(" ");
289     if (pos != std::string::npos) {
290         str = str.substr(0, pos);
291     }
292 }
293 
CheckWhiteList(const std::string & express)294 static bool CheckWhiteList(const std::string &express)
295 {
296     auto it = std::find_if(fileKeyWhiteListUSet.begin(), fileKeyWhiteListUSet.end(), [express](const std::string &str) {
297         return express.find(str) != string::npos;
298     });
299     if (it != fileKeyWhiteListUSet.end()) {
300         return true;
301     }
302     MEDIA_ERR_LOG("Failed to check express: %{private}s", express.c_str());
303 
304     return false;
305 }
306 
CheckExpressValidation(std::vector<std::string> & sepratedStr)307 static bool CheckExpressValidation(std::vector<std::string> &sepratedStr)
308 {
309     for (auto &str : sepratedStr) {
310         ExtractKeyWord(str);
311         if (str.empty() || (str.size() == 1 && str == " ")) {
312             continue;
313         }
314         if (!CheckWhiteList(str)) {
315             return false;
316         }
317     }
318 
319     return true;
320 }
321 
removeSpecialCondition(std::string & hacker,const std::string & pattern)322 static void removeSpecialCondition(std::string &hacker, const std::string &pattern)
323 {
324     auto pos = hacker.find(pattern);
325     while (pos != std::string::npos) {
326         hacker.replace(pos, pos + pattern.size(), " ");
327         pos = hacker.find(pattern);
328     }
329 }
330 
removeSpecialCondition(std::string & hacker)331 static void removeSpecialCondition(std::string &hacker)
332 {
333     const std::string S1 = "not between ? and ?";
334     const std::string S2 = "between ? and ?";
335     removeSpecialCondition(hacker, S1);
336     removeSpecialCondition(hacker, S2);
337 }
338 
SeprateSelection(std::string & strCondition,std::vector<std::string> & sepratedStr)339 static void SeprateSelection(std::string &strCondition, std::vector<std::string> &sepratedStr)
340 {
341     // 0. transform to lower
342     std::transform(strCondition.begin(), strCondition.end(), strCondition.begin(), ::tolower);
343     // 1.remove brackets
344     std::regex bracketsPattern("\\(|\\)", std::regex_constants::ECMAScript | std::regex_constants::icase);
345     strCondition = regex_replace(strCondition, bracketsPattern, "");
346 
347     // 2.remove redundant space
348     std::regex spacePattern("\\s+", std::regex_constants::ECMAScript | std::regex_constants::icase);
349     strCondition = regex_replace(strCondition, spacePattern, " ");
350 
351     // 3. remove special condition
352     removeSpecialCondition(strCondition);
353 
354     // 4. seprate core: according bound symbol,for example: and or ..
355     std::regex conditionPattern("\\s*and\\s+|\\s*or\\s+",
356         std::regex_constants::ECMAScript | std::regex_constants::icase);
357     std::sregex_token_iterator iter(strCondition.begin(), strCondition.end(), conditionPattern, -1);
358     decltype(iter) end;
359     while (iter != end) {
360         sepratedStr.push_back(iter->str());
361         ++iter;
362     }
363 }
364 
CheckKeyWord(const std::string & strCondition)365 static bool CheckKeyWord(const std::string &strCondition)
366 {
367     std::regex pattern("\\s*exec\\s*|\\s*insert\\s*|\\s*delete\\s*|\\s*update\\s*|" \
368                             "\\s*join\\s*|\\s*union\\s*|\\s*master\\s*|\\s*truncate\\s*",
369                     std::regex_constants::ECMAScript | std::regex_constants::icase);
370 
371     if (regex_search(strCondition, pattern)) {
372         MEDIA_ERR_LOG("Faild to check key word");
373         return false;
374     }
375 
376     return true;
377 }
378 
CheckIllegalCharacter(const std::string & strCondition)379 static bool CheckIllegalCharacter(const std::string &strCondition)
380 {
381     /* if strCondition contains ';', it will be sepreate to two clause */
382     if (strCondition.find(';') == std::string::npos) {
383         return true;
384     }
385     MEDIA_ERR_LOG("Faild to check illegal character");
386     /* other check to do */
387     return false;
388 }
389 
CheckWhereClause(const std::string & whereClause)390 static bool CheckWhereClause(const std::string &whereClause)
391 {
392     if (whereClause.empty() || (whereClause.size() == 1 && whereClause == " ")) {
393         return true;
394     }
395 
396     /* check whether query condition has illegal character */
397     if (!CheckIllegalCharacter(whereClause)) {
398         return false;
399     }
400 
401     /* check whether query condition has key word */
402     if (!CheckKeyWord(whereClause)) {
403         return false;
404     }
405 
406     std::vector<std::string> sepratedStr;
407     auto args = whereClause;
408     SeprateSelection(args, sepratedStr);
409     /* check every query condition */
410     return CheckExpressValidation(sepratedStr);
411 }
412 
GetType(const Uri & uri)413 std::string MediaLibraryDataAbility::GetType(const Uri &uri)
414 {
415     string getTypeUri = uri.ToString();
416     // If get uri contains media operation keyword, follow media operation procedure
417     if (getTypeUri.find(MEDIA_OPERN_KEYWORD) != string::npos) {
418         MediaLibraryKvStoreOperations kvStoreOprn;
419 
420         if (getTypeUri.find(MEDIA_KVSTOREOPRN) != string::npos) {
421             return kvStoreOprn.HandleKvStoreGetOperations(getTypeUri, kvStorePtr_);
422         }
423     }
424     return "";
425 }
426 
PreCheckInsert(const string & uri,const ValuesBucket & value)427 int32_t MediaLibraryDataAbility::PreCheckInsert(const string &uri, const ValuesBucket &value)
428 {
429     if ((!isRdbStoreInitialized) || (value.IsEmpty()) || (rdbStore_ == nullptr)) {
430         MEDIA_ERR_LOG("MediaLibraryDataAbility Insert: Input parameter is invalid");
431         return DATA_ABILITY_FAIL;
432     }
433 
434     string tmpUri = MEDIALIBRARY_DATA_URI + "/" + MEDIA_FILEOPRN + "/" + MEDIA_FILEOPRN_CLOSEASSET;
435     if (uri == tmpUri) {
436         if (!CheckClientPermission(PERMISSION_NAME_READ_MEDIA)) {
437             return DATA_ABILITY_PERMISSION_DENIED;
438         }
439     } else if (!CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
440         return DATA_ABILITY_PERMISSION_DENIED;
441     }
442     return DATA_ABILITY_SUCCESS;
443 }
444 
Insert(const Uri & uri,const ValuesBucket & value)445 int32_t MediaLibraryDataAbility::Insert(const Uri &uri, const ValuesBucket &value)
446 {
447     string insertUri = uri.ToString();
448     auto result = PreCheckInsert(insertUri, value);
449     if (result) {
450         return result;
451     }
452 
453     MediaLibrarySyncTable syncTable;
454     std::vector<std::string> devices = std::vector<std::string>();
455     // If insert uri contains media opearation, follow media operation procedure
456     if (insertUri.find(MEDIA_OPERN_KEYWORD) != string::npos) {
457         MediaLibraryFileOperations fileOprn;
458         MediaLibraryAlbumOperations albumOprn;
459         MediaLibrarySmartAlbumOperations smartalbumOprn;
460         MediaLibrarySmartAlbumMapOperations smartalbumMapOprn;
461         MediaLibraryKvStoreOperations kvStoreOprn;
462 
463         result = DATA_ABILITY_FAIL;
464         string operationType = MediaLibraryDataAbilityUtils::GetOperationType(insertUri);
465         MEDIA_INFO_LOG("operationType = %{public}s", operationType.c_str());
466         if ((operationType == MEDIA_FILEOPRN_CREATEASSET ||
467             operationType == MEDIA_ALBUMOPRN_CREATEALBUM) && !CheckFileNameValid(value)) {
468             return DATA_ABILITY_FILE_NAME_INVALID;
469         }
470         if (insertUri.find(MEDIA_FILEOPRN) != string::npos) {
471             result = fileOprn.HandleFileOperation(operationType, value, rdbStore_, mediaThumbnail_);
472             // After successfull close asset operation, do a scan file
473             if ((result >= 0) && (operationType == MEDIA_FILEOPRN_CLOSEASSET)) {
474                 ScanFile(value, rdbStore_);
475             }
476             syncTable.SyncPushTable(rdbStore_, bundleName_, MEDIALIBRARY_TABLE, devices);
477         } else if (insertUri.find(MEDIA_ALBUMOPRN) != string::npos) {
478             result = albumOprn.HandleAlbumOperations(operationType, value, rdbStore_);
479             syncTable.SyncPushTable(rdbStore_, bundleName_, SMARTALBUM_TABLE, devices);
480         } else if (insertUri.find(MEDIA_SMARTALBUMOPRN) != string::npos) {
481             result = smartalbumOprn.HandleSmartAlbumOperations(operationType, value, rdbStore_);
482             syncTable.SyncPushTable(rdbStore_, bundleName_, SMARTALBUM_MAP_TABLE, devices);
483         } else if (insertUri.find(MEDIA_SMARTALBUMMAPOPRN) != string::npos) {
484             result = smartalbumMapOprn.HandleSmartAlbumMapOperations(operationType, value, rdbStore_);
485             syncTable.SyncPushTable(rdbStore_, bundleName_, CATEGORY_SMARTALBUM_MAP_TABLE, devices);
486         } else if (insertUri.find(MEDIA_KVSTOREOPRN) != string::npos) {
487             result = kvStoreOprn.HandleKvStoreInsertOperations(operationType, value, kvStorePtr_);
488         }
489         return result;
490     }
491 
492     // Normal URI scenario
493     int64_t outRowId = DATA_ABILITY_FAIL;
494     (void)rdbStore_->Insert(outRowId, MEDIALIBRARY_TABLE, value);
495 
496     syncTable.SyncPushTable(rdbStore_, bundleName_, MEDIALIBRARY_TABLE, devices);
497     return outRowId;
498 }
499 
Delete(const Uri & uri,const DataAbilityPredicates & predicates)500 int32_t MediaLibraryDataAbility::Delete(const Uri &uri, const DataAbilityPredicates &predicates)
501 {
502     if (!isRdbStoreInitialized || (rdbStore_ == nullptr)) {
503         MEDIA_ERR_LOG("MediaLibraryDataAbility Delete:Rdb Store is not initialized");
504         return DATA_ABILITY_FAIL;
505     }
506 
507     if (!CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
508         return DATA_ABILITY_PERMISSION_DENIED;
509     }
510     string uriString = uri.ToString();
511     string strDeleteCondition = predicates.GetWhereClause();
512     if (strDeleteCondition.empty()) {
513         string::size_type pos = uriString.find_last_of('/');
514         CHECK_AND_RETURN_RET_LOG((pos != string::npos) && (pos == MEDIALIBRARY_DATA_URI.length()), DATA_ABILITY_FAIL,
515             "Invalid index position");
516 
517         string strRow = uriString.substr(pos + 1);
518         CHECK_AND_RETURN_RET_LOG(MediaLibraryDataAbilityUtils::IsNumber(strRow), DATA_ABILITY_FAIL, "Index not digit");
519 
520         strDeleteCondition = MEDIA_DATA_DB_ID + " = " + strRow;
521         uriString = uriString.substr(0, pos);
522     }
523 
524     // After removing the index values, check whether URI is correct
525     CHECK_AND_RETURN_RET_LOG(uriString == MEDIALIBRARY_DATA_URI, DATA_ABILITY_FAIL, "Not Data ability Uri");
526 
527     vector<string> whereArgs = predicates.GetWhereArgs();
528     int32_t deletedRows = DATA_ABILITY_FAIL;
529     (void)rdbStore_->Delete(deletedRows, MEDIALIBRARY_TABLE, strDeleteCondition, whereArgs);
530 
531     return deletedRows;
532 }
QueryBySmartTableType(TableType tabletype,string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore)533 shared_ptr<AbsSharedResultSet> QueryBySmartTableType(TableType tabletype,
534     string strQueryCondition,
535     DataAbilityPredicates predicates,
536     vector<string> columns,
537     std::shared_ptr<NativeRdb::RdbStore> rdbStore)
538 {
539     shared_ptr<AbsSharedResultSet> queryResultSet;
540     if (tabletype == TYPE_SMARTALBUM) {
541         AbsRdbPredicates mediaLibSAAbsPred(SMARTALBUM_TABLE);
542         if (predicates.IsDistinct()) {
543             mediaLibSAAbsPred.Distinct();
544         }
545 
546         mediaLibSAAbsPred.SetWhereClause(strQueryCondition);
547         mediaLibSAAbsPred.SetWhereArgs(predicates.GetWhereArgs());
548         mediaLibSAAbsPred.Limit(predicates.GetLimit());
549         mediaLibSAAbsPred.SetOrder(predicates.GetOrder());
550 
551         queryResultSet = rdbStore->Query(mediaLibSAAbsPred, columns);
552         CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
553     } else if (tabletype == TYPE_SMARTALBUM_MAP) {
554         AbsRdbPredicates mediaLibSAMAbsPred(SMARTALBUM_MAP_TABLE);
555         if (predicates.IsDistinct()) {
556             mediaLibSAMAbsPred.Distinct();
557         }
558 
559         mediaLibSAMAbsPred.SetWhereClause(strQueryCondition);
560         mediaLibSAMAbsPred.SetWhereArgs(predicates.GetWhereArgs());
561         mediaLibSAMAbsPred.Limit(predicates.GetLimit());
562         mediaLibSAMAbsPred.SetOrder(predicates.GetOrder());
563 
564         queryResultSet = rdbStore->Query(mediaLibSAMAbsPred, columns);
565         CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
566     }
567     return queryResultSet;
568 }
569 
QueryFile(string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore,string networkId)570 shared_ptr<AbsSharedResultSet> QueryFile(string strQueryCondition,
571     DataAbilityPredicates predicates,
572     vector<string> columns,
573     std::shared_ptr<NativeRdb::RdbStore> rdbStore,
574     string networkId)
575 {
576     shared_ptr<AbsSharedResultSet> queryResultSet;
577     string tableName = MEDIALIBRARY_TABLE;
578     if (!networkId.empty()) {
579         MEDIA_DEBUG_LOG("ObtainDistributedTableName start");
580         StartTrace(BYTRACE_TAG_OHOS, "QueryFile rdbStore->ObtainDistributedTableName");
581         tableName = rdbStore->ObtainDistributedTableName(networkId, MEDIALIBRARY_TABLE);
582         MEDIA_DEBUG_LOG("tableName in %{public}s", tableName.c_str());
583         FinishTrace(BYTRACE_TAG_OHOS);
584     }
585     AbsRdbPredicates mediaLibAbsPredFile(tableName);
586 
587     if (!networkId.empty()) {
588         MEDIA_INFO_LOG("Not empty networkId %{public}s", networkId.c_str());
589         std::vector<string> devices = std::vector<string>();
590         devices.push_back(networkId);
591         mediaLibAbsPredFile.InDevices(devices);
592     }
593     if (predicates.IsDistinct()) {
594         mediaLibAbsPredFile.Distinct();
595     }
596     mediaLibAbsPredFile.SetWhereClause(strQueryCondition);
597     mediaLibAbsPredFile.SetWhereArgs(predicates.GetWhereArgs());
598     mediaLibAbsPredFile.Limit(predicates.GetLimit());
599     mediaLibAbsPredFile.SetOrder(predicates.GetOrder());
600 
601     StartTrace(BYTRACE_TAG_OHOS, "QueryFile RdbStore->Query");
602     queryResultSet = rdbStore->Query(mediaLibAbsPredFile, columns);
603     FinishTrace(BYTRACE_TAG_OHOS);
604 
605     return queryResultSet;
606 }
607 
ObtionCondition(string & strQueryCondition,const vector<string> & whereArgs)608 string ObtionCondition(string &strQueryCondition, const vector<string> &whereArgs)
609 {
610     for (string args : whereArgs) {
611         size_t pos = strQueryCondition.find('?');
612         MEDIA_INFO_LOG("obtionCondition pos = %{public}d", (int)pos);
613         if (pos != string::npos) {
614             MEDIA_INFO_LOG("ObtionCondition before = %{public}s", strQueryCondition.c_str());
615             strQueryCondition.replace(pos, 1, "'" + args + "'");
616             MEDIA_INFO_LOG("ObtionCondition end = %{public}s", strQueryCondition.c_str());
617         }
618     }
619     return strQueryCondition;
620 }
621 
QueryAlbum(string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore,string networkId)622 shared_ptr<AbsSharedResultSet> QueryAlbum(string strQueryCondition,
623     DataAbilityPredicates predicates,
624     vector<string> columns,
625     std::shared_ptr<NativeRdb::RdbStore> rdbStore,
626     string networkId)
627 {
628     shared_ptr<AbsSharedResultSet> queryResultSet;
629     if (!networkId.empty()) {
630         string tableName = rdbStore->ObtainDistributedTableName(networkId, MEDIALIBRARY_TABLE);
631         MEDIA_INFO_LOG("tableName is %{public}s", tableName.c_str());
632         AbsRdbPredicates mediaLibAbsPredAlbum(tableName);
633         if (!strQueryCondition.empty()) {
634             strQueryCondition = ObtionCondition(strQueryCondition, predicates.GetWhereArgs());
635         }
636         string distributedAlbumSql = MediaLibraryDataAbilityUtils::GetDistributedAlbumSql(strQueryCondition, tableName);
637         queryResultSet = rdbStore->QuerySql(distributedAlbumSql);
638     } else {
639             AbsRdbPredicates mediaLibAbsPredAlbum(ABLUM_VIEW_NAME);
640         if (strQueryCondition.empty()) {
641             queryResultSet = rdbStore->QuerySql("SELECT * FROM " + ABLUM_VIEW_NAME);
642         } else {
643             if (predicates.IsDistinct()) {
644                 mediaLibAbsPredAlbum.Distinct();
645             }
646             mediaLibAbsPredAlbum.SetWhereClause(strQueryCondition);
647             mediaLibAbsPredAlbum.SetWhereArgs(predicates.GetWhereArgs());
648             mediaLibAbsPredAlbum.Limit(predicates.GetLimit());
649             mediaLibAbsPredAlbum.SetOrder(predicates.GetOrder());
650             queryResultSet = rdbStore->Query(mediaLibAbsPredAlbum, columns);
651         }
652     }
653     return queryResultSet;
654 }
655 
QueryDeviceInfo(string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore)656 shared_ptr<AbsSharedResultSet> QueryDeviceInfo(string strQueryCondition,
657     DataAbilityPredicates predicates, vector<string> columns, std::shared_ptr<NativeRdb::RdbStore> rdbStore)
658 {
659     shared_ptr<AbsSharedResultSet> queryResultSet;
660     AbsRdbPredicates deviceAbsRdbPredicates(DEVICE_TABLE);
661     if (predicates.IsDistinct()) {
662         deviceAbsRdbPredicates.Distinct();
663     }
664 
665     deviceAbsRdbPredicates.SetWhereClause(strQueryCondition);
666     deviceAbsRdbPredicates.SetWhereArgs(predicates.GetWhereArgs());
667     deviceAbsRdbPredicates.Limit(predicates.GetLimit());
668     deviceAbsRdbPredicates.SetOrder(predicates.GetOrder());
669 
670     queryResultSet = rdbStore->Query(deviceAbsRdbPredicates, columns);
671     CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query All Device failed");
672     return queryResultSet;
673 }
674 
QueryByViewType(TableType tabletype,string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore)675 shared_ptr<AbsSharedResultSet> QueryByViewType(TableType tabletype,
676     string strQueryCondition,
677     DataAbilityPredicates predicates,
678     vector<string> columns,
679     std::shared_ptr<NativeRdb::RdbStore> rdbStore)
680 {
681     shared_ptr<AbsSharedResultSet> queryResultSet;
682     if (tabletype == TYPE_ASSETSMAP_TABLE) {
683         AbsRdbPredicates mediaLibAbsPredAlbum(ASSETMAP_VIEW_NAME);
684         if (strQueryCondition.empty()) {
685             queryResultSet = rdbStore->QuerySql("SELECT * FROM " + ASSETMAP_VIEW_NAME);
686         } else {
687             if (predicates.IsDistinct()) {
688                 mediaLibAbsPredAlbum.Distinct();
689             }
690             mediaLibAbsPredAlbum.SetWhereClause(strQueryCondition);
691             mediaLibAbsPredAlbum.SetWhereArgs(predicates.GetWhereArgs());
692             mediaLibAbsPredAlbum.Limit(predicates.GetLimit());
693             mediaLibAbsPredAlbum.SetOrder(predicates.GetOrder());
694             queryResultSet = rdbStore->Query(mediaLibAbsPredAlbum, columns);
695         }
696     } else if (tabletype == TYPE_SMARTALBUMASSETS_TABLE) {
697         AbsRdbPredicates mediaLibAbsPredAlbum(SMARTABLUMASSETS_VIEW_NAME);
698         if (strQueryCondition.empty()) {
699             queryResultSet = rdbStore->QuerySql("SELECT * FROM " + SMARTABLUMASSETS_VIEW_NAME);
700         } else {
701             if (predicates.IsDistinct()) {
702                 mediaLibAbsPredAlbum.Distinct();
703             }
704             mediaLibAbsPredAlbum.SetWhereClause(strQueryCondition);
705             mediaLibAbsPredAlbum.SetWhereArgs(predicates.GetWhereArgs());
706             mediaLibAbsPredAlbum.Limit(predicates.GetLimit());
707             mediaLibAbsPredAlbum.SetOrder(predicates.GetOrder());
708             queryResultSet = rdbStore->Query(mediaLibAbsPredAlbum, columns);
709         }
710     }
711     return queryResultSet;
712 }
SplitKeyValue(const string & keyValue,string & key,string & value)713 void SplitKeyValue(const string& keyValue, string &key, string &value)
714 {
715     string::size_type pos = keyValue.find('=');
716     if (string::npos != pos) {
717         key = keyValue.substr(0, pos);
718         value = keyValue.substr(pos + 1);
719     }
720 }
SplitKeys(const string & query,vector<string> & keys)721 void SplitKeys(const string& query, vector<string>& keys)
722 {
723     string::size_type pos1 = 0;
724     string::size_type pos2 = query.find('&');
725     while (string::npos != pos2) {
726         keys.push_back(query.substr(pos1, pos2-pos1));
727         pos1 = pos2 + 1;
728         pos2 = query.find('&', pos1);
729     }
730     if (pos1 != query.length()) {
731         keys.push_back(query.substr(pos1));
732     }
733 }
ParseThumbnailInfo(string & uriString,vector<int> & space)734 bool ParseThumbnailInfo(string &uriString, vector<int> &space)
735 {
736     string::size_type pos = uriString.find_last_of('?');
737     string queryKeys;
738     if (string::npos == pos) {
739         return false;
740     }
741     vector<string> keyWords = {
742         MEDIA_OPERN_KEYWORD,
743         MEDIA_DATA_DB_WIDTH,
744         MEDIA_DATA_DB_HEIGHT
745     };
746     queryKeys = uriString.substr(pos + 1);
747     uriString = uriString.substr(0, pos);
748     vector<string> vectorKeys;
749     SplitKeys(queryKeys, vectorKeys);
750     if (vectorKeys.size() != keyWords.size()) {
751         MEDIA_ERR_LOG("Parse error keys count %{public}d", (int)vectorKeys.size());
752         return false;
753     }
754     string action;
755     int width = 0;
756     int height = 0;
757     for (uint32_t i = 0; i < vectorKeys.size(); i++) {
758         string subKey, subVal;
759         SplitKeyValue(vectorKeys[i], subKey, subVal);
760         if (subKey.empty()) {
761             MEDIA_ERR_LOG("Parse key error [ %{public}s ]", vectorKeys[i].c_str());
762             return false;
763         }
764         if (subKey == MEDIA_OPERN_KEYWORD) {
765             action = subVal;
766         } else if (subKey == MEDIA_DATA_DB_WIDTH) {
767             if (MediaLibraryDataAbilityUtils::IsNumber(subVal)) {
768                 width = stoi(subVal);
769             }
770         } else if (subKey == MEDIA_DATA_DB_HEIGHT) {
771             if (MediaLibraryDataAbilityUtils::IsNumber(subVal)) {
772                 height = stoi(subVal);
773             }
774         }
775     }
776     MEDIA_INFO_LOG("ParseThumbnailInfo| action [%{public}s] width %{public}d height %{public}d",
777         action.c_str(), width, height);
778     if (action != MEDIA_DATA_DB_THUMBNAIL || width <= 0 || height <= 0) {
779         MEDIA_ERR_LOG("ParseThumbnailInfo | Error args");
780         return false;
781     }
782     space.push_back(width);
783     space.push_back(height);
784     return true;
785 }
GenThumbnail(shared_ptr<RdbStore> rdb,shared_ptr<MediaLibraryThumbnail> thumbnail,string & rowId,vector<int> space,string & networkId)786 shared_ptr<AbsSharedResultSet> GenThumbnail(shared_ptr<RdbStore> rdb,
787     shared_ptr<MediaLibraryThumbnail> thumbnail,
788     string &rowId, vector<int> space, string &networkId)
789 {
790     shared_ptr<AbsSharedResultSet> queryResultSet;
791     int width = space[0];
792     int height = space[1];
793     string filesTableName = MEDIALIBRARY_TABLE;
794 
795     if (!networkId.empty()) {
796         StartTrace(BYTRACE_TAG_OHOS, "rdb->ObtainDistributedTableName");
797         filesTableName = rdb->ObtainDistributedTableName(networkId, MEDIALIBRARY_TABLE);
798         FinishTrace(BYTRACE_TAG_OHOS);
799     }
800 
801     MEDIA_INFO_LOG("Get filesTableName [ %{public}s ]", filesTableName.c_str());
802     ThumbRdbOpt opts = {
803         .store = rdb,
804         .table = filesTableName,
805         .row = rowId
806     };
807     Size size = {
808         .width = width,
809         .height = height
810     };
811 
812     MEDIA_INFO_LOG("Get thumbnail [ %{public}s ]", opts.row.c_str());
813     StartTrace(BYTRACE_TAG_OHOS, "thumbnail->GetThumbnailKey");
814     queryResultSet = thumbnail->GetThumbnailKey(opts, size);
815     FinishTrace(BYTRACE_TAG_OHOS);
816 
817     return queryResultSet;
818 }
DealWithUriString(string & uriString,TableType & tabletype,string & strQueryCondition,string::size_type & pos,string & strRow)819 static void DealWithUriString(string &uriString, TableType &tabletype,
820     string &strQueryCondition, string::size_type &pos, string &strRow)
821 {
822     string type = uriString.substr(pos + 1);
823     MEDIA_INFO_LOG("MediaLibraryDataAbility uriString type = %{public}s", type.c_str());
824     if (type == MEDIA_ALBUMOPRN_QUERYALBUM) {
825         tabletype = TYPE_ALBUM_TABLE;
826         uriString = MEDIALIBRARY_DATA_URI;
827     } else if (uriString == MEDIALIBRARY_DATA_URI + "/"
828                + MEDIA_ALBUMOPRN_QUERYALBUM + "/" + SMARTABLUMASSETS_VIEW_NAME) {
829         tabletype = TYPE_SMARTALBUMASSETS_TABLE;
830         uriString = MEDIALIBRARY_SMARTALBUM_URI;
831     } else if (uriString == MEDIALIBRARY_DATA_URI + "/"
832                + MEDIA_ALBUMOPRN_QUERYALBUM + "/" + ASSETMAP_VIEW_NAME) {
833         tabletype = TYPE_ASSETSMAP_TABLE;
834         uriString = MEDIALIBRARY_SMARTALBUM_URI;
835     } else if (uriString == MEDIALIBRARY_DATA_URI + "/" + MEDIA_DEVICE_QUERYALLDEVICE) {
836         tabletype = TYPE_ALL_DEVICE;
837         uriString = MEDIALIBRARY_DATA_URI;
838     } else if (uriString == MEDIALIBRARY_DATA_URI + "/" + MEDIA_DEVICE_QUERYACTIVEDEVICE) {
839         tabletype = TYPE_ACTIVE_DEVICE;
840         uriString = MEDIALIBRARY_DATA_URI;
841     } else if (strQueryCondition.empty() && pos != string::npos) {
842         strRow = type;
843         uriString = uriString.substr(0, pos);
844         string::size_type posTable = uriString.find_last_of('/');
845         string tableName = uriString.substr(posTable + 1);
846         MEDIA_INFO_LOG("MediaLibraryDataAbility tableName = %{public}s", tableName.c_str());
847         MEDIA_INFO_LOG("MediaLibraryDataAbility strRow = %{public}s", strRow.c_str());
848         if (SMARTALBUM_TABLE.compare(tableName) == 0) {
849             tabletype = TYPE_SMARTALBUM;
850             strQueryCondition = SMARTALBUM_DB_ID + " = " + strRow;
851         } else if (SMARTALBUM_MAP_TABLE.compare(tableName) == 0) {
852             tabletype = TYPE_SMARTALBUM_MAP;
853             strQueryCondition = SMARTALBUMMAP_DB_ALBUM_ID + " = " + strRow;
854         } else {
855             tabletype = TYPE_DATA;
856             strQueryCondition = MEDIA_DATA_DB_ID + " = " + strRow;
857         }
858     }
859 }
Query(const Uri & uri,const vector<string> & columns,const DataAbilityPredicates & predicates)860 shared_ptr<AbsSharedResultSet> MediaLibraryDataAbility::Query(const Uri &uri,
861                                                               const vector<string> &columns,
862                                                               const DataAbilityPredicates &predicates)
863 {
864     StartTrace(BYTRACE_TAG_OHOS, "MediaLibraryDataAbility::Query");
865 
866     if ((!isRdbStoreInitialized) || (rdbStore_ == nullptr)) {
867         MEDIA_ERR_LOG("Rdb Store is not initialized");
868         return nullptr;
869     }
870 
871     StartTrace(BYTRACE_TAG_OHOS, "CheckClientPermission");
872     if (!CheckClientPermission(PERMISSION_NAME_READ_MEDIA)) {
873         return nullptr;
874     }
875     FinishTrace(BYTRACE_TAG_OHOS);
876 
877     shared_ptr<AbsSharedResultSet> queryResultSet;
878     TableType tabletype = TYPE_DATA;
879     string strRow, uriString = uri.ToString(), strQueryCondition = predicates.GetWhereClause();
880 
881     if (!CheckWhereClause(strQueryCondition)) {
882         MEDIA_ERR_LOG("illegal query whereClause input %{public}s", strQueryCondition.c_str());
883         return nullptr;
884     }
885 
886     vector<int> space;
887     bool thumbnailQuery = ParseThumbnailInfo(uriString, space);
888     string networkId = MediaLibraryDataAbilityUtils::GetNetworkIdFromUri(uriString);
889     string::size_type pos = uriString.find_last_of('/');
890     string type = uriString.substr(pos + 1);
891     MEDIA_DEBUG_LOG("uriString = %{public}s, type = %{public}s, thumbnailQuery %{public}d, Rdb Verison %{public}d",
892         uriString.c_str(), type.c_str(), thumbnailQuery, MEDIA_RDB_VERSION);
893     DealWithUriString(uriString, tabletype, strQueryCondition, pos, strRow);
894 
895     if (!networkId.empty() && (tabletype != TYPE_ASSETSMAP_TABLE) && (tabletype != TYPE_SMARTALBUMASSETS_TABLE)) {
896         StartTrace(BYTRACE_TAG_OHOS, "QuerySync");
897         auto ret = QuerySync();
898         FinishTrace(BYTRACE_TAG_OHOS);
899         MEDIA_INFO_LOG("MediaLibraryDataAbility QuerySync result = %{public}d", ret);
900     }
901 
902     if (thumbnailQuery) {
903         StartTrace(BYTRACE_TAG_OHOS, "GenThumbnail");
904         queryResultSet = GenThumbnail(rdbStore_, mediaThumbnail_, strRow, space, networkId);
905         FinishTrace(BYTRACE_TAG_OHOS);
906     } else if (tabletype == TYPE_SMARTALBUM || tabletype == TYPE_SMARTALBUM_MAP) {
907         queryResultSet = QueryBySmartTableType(tabletype, strQueryCondition, predicates, columns, rdbStore_);
908         CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
909     } else if (tabletype == TYPE_ASSETSMAP_TABLE || tabletype == TYPE_SMARTALBUMASSETS_TABLE) {
910         queryResultSet = QueryByViewType(tabletype, strQueryCondition, predicates, columns, rdbStore_);
911     } else if (tabletype == TYPE_ALL_DEVICE || tabletype == TYPE_ACTIVE_DEVICE) {
912         queryResultSet = QueryDeviceInfo(strQueryCondition, predicates, columns, rdbStore_);
913     } else if (tabletype == TYPE_ALBUM_TABLE) {
914         queryResultSet = QueryAlbum(strQueryCondition, predicates, columns, rdbStore_, networkId);
915         CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
916     } else {
917         StartTrace(BYTRACE_TAG_OHOS, "QueryFile");
918         queryResultSet = QueryFile(strQueryCondition, predicates, columns, rdbStore_, networkId);
919         CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
920         FinishTrace(BYTRACE_TAG_OHOS);
921     }
922 
923     FinishTrace(BYTRACE_TAG_OHOS);
924 
925     return queryResultSet;
926 }
927 
Update(const Uri & uri,const ValuesBucket & value,const DataAbilityPredicates & predicates)928 int32_t MediaLibraryDataAbility::Update(const Uri &uri, const ValuesBucket &value,
929     const DataAbilityPredicates &predicates)
930 {
931     MEDIA_INFO_LOG("Update");
932     if ((!isRdbStoreInitialized) || (rdbStore_ == nullptr) || (value.IsEmpty())) {
933         MEDIA_ERR_LOG("MediaLibraryDataAbility Update:Input parameter is invalid ");
934         return DATA_ABILITY_FAIL;
935     }
936     if (!CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
937         return DATA_ABILITY_PERMISSION_DENIED;
938     }
939     MediaLibraryFileOperations fileOprn;
940     int32_t changedRows = DATA_ABILITY_FAIL;
941     string uriString = uri.ToString();
942     vector<string> devices = vector<string>();
943     MEDIA_INFO_LOG("Update uriString = %{public}s", uriString.c_str());
944     string strUpdateCondition = predicates.GetWhereClause();
945     if (strUpdateCondition.empty()) {
946         string::size_type pos = uriString.find_last_of('/');
947         CHECK_AND_RETURN_RET_LOG((pos != string::npos) && (pos == MEDIALIBRARY_DATA_URI.length()), DATA_ABILITY_FAIL,
948             "Invalid index position");
949 
950         string strRow = uriString.substr(pos + 1);
951         CHECK_AND_RETURN_RET_LOG(MediaLibraryDataAbilityUtils::IsNumber(strRow), DATA_ABILITY_FAIL, "Index not digit");
952 
953         uriString = uriString.substr(0, pos);
954         strUpdateCondition = MEDIA_DATA_DB_ID + " = " + strRow;
955     }
956     // After removing the index values, check whether URI is correct
957 
958     vector<string> whereArgs = predicates.GetWhereArgs();
959     if (uriString.find(MEDIA_SMARTALBUMOPRN) != string::npos) {
960         (void)rdbStore_->Update(changedRows, SMARTALBUM_TABLE, value, strUpdateCondition, whereArgs);
961     } else if (uriString.find(MEDIA_SMARTALBUMMAPOPRN) != string::npos) {
962         (void)rdbStore_->Update(changedRows, SMARTALBUM_MAP_TABLE, value, strUpdateCondition, whereArgs);
963     } else {
964         if (uriString == MEDIALIBRARY_DATA_URI + "/" + Media::MEDIA_FILEOPRN
965                 + "/" + Media::MEDIA_FILEOPRN_MODIFYASSET) {
966         int result = fileOprn.HandleFileOperation(MEDIA_FILEOPRN_MODIFYASSET, value, rdbStore_, mediaThumbnail_);
967         if (result < 0) {
968             return result;
969             }
970         }
971     (void)rdbStore_->Update(changedRows, MEDIALIBRARY_TABLE, value, strUpdateCondition, whereArgs);
972     }
973     if (changedRows >= 0) {
974         MediaLibrarySyncTable syncTable;
975         syncTable.SyncPushTable(rdbStore_, bundleName_, MEDIALIBRARY_TABLE, devices);
976     }
977     return changedRows;
978 }
979 
BatchInsert(const Uri & uri,const vector<ValuesBucket> & values)980 int32_t MediaLibraryDataAbility::BatchInsert(const Uri &uri, const vector<ValuesBucket> &values)
981 {
982     string uriString = uri.ToString();
983     if ((!isRdbStoreInitialized) || (rdbStore_ == nullptr) || (uriString != MEDIALIBRARY_DATA_URI)) {
984         MEDIA_ERR_LOG("MediaLibraryDataAbility BatchInsert: Input parameter is invalid");
985         return DATA_ABILITY_FAIL;
986     }
987     int32_t rowCount = 0;
988     for (auto it = values.begin(); it != values.end(); it++) {
989         if (Insert(uri, *it) >= 0) {
990             rowCount++;
991         }
992     }
993 
994     return rowCount;
995 }
996 
ScanFile(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore1)997 void MediaLibraryDataAbility::ScanFile(const ValuesBucket &values, const shared_ptr<RdbStore> &rdbStore1)
998 {
999     if (scannerClient_ == nullptr) {
1000         scannerClient_ = MediaScannerHelperFactory::CreateScannerHelper();
1001     }
1002 
1003     if (scannerClient_ != nullptr) {
1004         string actualUri;
1005         ValueObject valueObject;
1006 
1007         if (values.GetObject(MEDIA_DATA_DB_URI, valueObject)) {
1008             valueObject.GetString(actualUri);
1009         }
1010 
1011         string id = MediaLibraryDataAbilityUtils::GetIdFromUri(actualUri);
1012         string srcPath = MediaLibraryDataAbilityUtils::GetPathFromDb(id, rdbStore1);
1013         if (!srcPath.empty()) {
1014             std::shared_ptr<ScanFileCallback> scanFileCb = make_shared<ScanFileCallback>();
1015             CHECK_AND_RETURN_LOG(scanFileCb != nullptr, "Failed to create scan file callback object");
1016             auto ret = scannerClient_->ScanFile(srcPath, scanFileCb);
1017             CHECK_AND_RETURN_LOG(ret == 0, "Failed to initiate scan request");
1018         }
1019     }
1020 }
1021 /**
1022  * @brief
1023  * @param uri
1024  * @param  mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access
1025  * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file,
1026  * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data,
1027  *  or "rwt" for read and write access that truncates any existing file.
1028  * /
1029  * @return int32_t
1030  */
OpenFile(const Uri & uri,const std::string & mode)1031 int32_t MediaLibraryDataAbility::OpenFile(const Uri &uri, const std::string &mode)
1032 {
1033     string uriString = uri.ToString();
1034     shared_ptr<FileAsset> fileAsset = MediaLibraryDataAbilityUtils::GetFileAssetFromDb(uriString, rdbStore_);
1035     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, DATA_ABILITY_FAIL, "Failed to obtain path from Database");
1036     bool isWriteMode = MediaLibraryDataAbilityUtils::checkOpenMode(mode);
1037     if (isWriteMode) {
1038         if (MediaLibraryDataAbilityUtils::checkFilePending(fileAsset)) {
1039             MEDIA_ERR_LOG("MediaLibraryDataAbility OpenFile: File is pending");
1040             return DATA_ABILITY_HAS_OPENED_FAIL;
1041         }
1042     }
1043     if (mode == MEDIA_FILEMODE_READONLY) {
1044         if (!CheckClientPermission(PERMISSION_NAME_READ_MEDIA)) {
1045             return DATA_ABILITY_PERMISSION_DENIED;
1046         }
1047     } else if (mode == MEDIA_FILEMODE_WRITEONLY || mode == MEDIA_FILEMODE_WRITETRUNCATE ||
1048         mode == MEDIA_FILEMODE_WRITEAPPEND) {
1049         if (!CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
1050             return DATA_ABILITY_PERMISSION_DENIED;
1051         }
1052     } else if (mode == MEDIA_FILEMODE_READWRITETRUNCATE || mode == MEDIA_FILEMODE_READWRITE) {
1053         if (!CheckClientPermission(PERMISSION_NAME_READ_MEDIA) ||
1054             !CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
1055             return DATA_ABILITY_PERMISSION_DENIED;
1056         }
1057     }
1058     string path = MediaFileUtils::UpdatePath(fileAsset->GetPath(), fileAsset->GetUri());
1059     int32_t fd = fileAsset->OpenAsset(path, mode);
1060     if (fd < 0) {
1061         MEDIA_ERR_LOG("open file fd %{public}d, errno %{public}d", fd, errno);
1062         return DATA_ABILITY_HAS_FD_ERROR;
1063     }
1064     if (isWriteMode && fd > 0) {
1065         int32_t errorCode = MediaLibraryDataAbilityUtils::setFilePending(uriString, true, rdbStore_);
1066         if (errorCode == DATA_ABILITY_FAIL) {
1067             fileAsset->CloseAsset(fd);
1068             MEDIA_ERR_LOG("MediaLibraryDataAbility OpenFile: Set file to pending DB error");
1069             return DATA_ABILITY_HAS_DB_ERROR;
1070         }
1071     }
1072     MEDIA_INFO_LOG("MediaLibraryDataAbility OpenFile: Success");
1073     return fd;
1074 }
1075 
InitDeviceData()1076 void MediaLibraryDataAbility::InitDeviceData()
1077 {
1078     if (rdbStore_ == nullptr) {
1079         MEDIA_ERR_LOG("MediaLibraryDataAbility InitDeviceData rdbStore is null");
1080         return;
1081     }
1082     std::string extra = "";
1083     auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
1084     deviceInitCallback_ = std::make_shared<MediaLibraryInitCallback>();
1085     if (deviceInitCallback_ == nullptr) {
1086         MEDIA_ERR_LOG("MediaLibraryDataAbility MediaLibraryInitCallback failed!");
1087         return;
1088     }
1089     deviceManager.InitDeviceManager(bundleName_, deviceInitCallback_);
1090 
1091     MEDIA_DEBUG_LOG("Distribute StartTrace:InitDeviceRdbStoreTrace");
1092     StartTrace(BYTRACE_TAG_OHOS, "InitDeviceRdbStoreTrace", -1);
1093     if (!MediaLibraryDevice::GetInstance()->InitDeviceRdbStore(rdbStore_, bundleName_)) {
1094         MEDIA_ERR_LOG("MediaLibraryDataAbility InitDeviceData failed!");
1095         return;
1096     }
1097     FinishTrace(BYTRACE_TAG_OHOS);
1098     MEDIA_DEBUG_LOG("Distribute FinishTrace:InitDeviceRdbStoreTrace");
1099 
1100     deviceStateCallback_ = std::make_shared<MediaLibraryDeviceStateCallback>(rdbStore_, bundleName_);
1101     if (deviceStateCallback_ == nullptr) {
1102         MEDIA_ERR_LOG("MediaLibraryDataAbility MediaLibraryDeviceStateCallback failed!");
1103         return;
1104     }
1105 
1106     if (deviceManager.RegisterDevStateCallback(bundleName_, extra, deviceStateCallback_) != 0) {
1107         deviceStateCallback_ = nullptr;
1108         MEDIA_ERR_LOG("MediaLibraryDataAbility RegisterDevStateCallback failed!");
1109         return;
1110     }
1111     MEDIA_INFO_LOG("MediaLibraryDataAbility InitDeviceData OUT");
1112 }
1113 
SubscribeRdbStoreObserver()1114 bool MediaLibraryDataAbility::SubscribeRdbStoreObserver()
1115 {
1116     if (rdbStore_ == nullptr) {
1117         MEDIA_ERR_LOG("MediaLibraryDataAbility SubscribeRdbStoreObserver rdbStore is null");
1118         return false;
1119     }
1120     rdbStoreObs_ = std::make_shared<MediaLibraryRdbStoreObserver>(bundleName_);
1121     if (rdbStoreObs_ == nullptr) {
1122         return false;
1123     }
1124 
1125     DistributedRdb::SubscribeOption option;
1126     option.mode = DistributedRdb::SubscribeMode::REMOTE;
1127     bool ret = rdbStore_->Subscribe(option, rdbStoreObs_.get());
1128     MEDIA_INFO_LOG("MediaLibraryDataAbility Subscribe ret = %d", ret);
1129 
1130     return ret;
1131 }
1132 
UnSubscribeRdbStoreObserver()1133 bool MediaLibraryDataAbility::UnSubscribeRdbStoreObserver()
1134 {
1135     if (rdbStore_ == nullptr) {
1136         MEDIA_ERR_LOG("MediaLibraryDataAbility UnSubscribeRdbStoreObserver rdbStore is null");
1137         return false;
1138     }
1139 
1140     DistributedRdb::SubscribeOption option;
1141     option.mode = DistributedRdb::SubscribeMode::REMOTE;
1142     bool ret = rdbStore_->UnSubscribe(option, rdbStoreObs_.get());
1143     MEDIA_INFO_LOG("MediaLibraryDataAbility UnSubscribe ret = %d", ret);
1144     if (ret) {
1145         rdbStoreObs_ = nullptr;
1146     }
1147 
1148     return ret;
1149 }
1150 
QuerySync(const std::string & deviceId,const std::string & tableName)1151 bool MediaLibraryDataAbility::QuerySync(const std::string &deviceId, const std::string &tableName)
1152 {
1153     if (deviceId.empty() || tableName.empty()) {
1154         return false;
1155     }
1156 
1157     OHOS::DistributedHardware::DmDeviceInfo deviceInfo;
1158     auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
1159     auto ret = deviceManager.GetLocalDeviceInfo(bundleName_, deviceInfo);
1160     if (ret != ERR_OK) {
1161         MEDIA_ERR_LOG("MediaLibraryDataAbility QuerySync Failed to get local device info.");
1162         return false;
1163     }
1164 
1165     if (deviceId == std::string(deviceInfo.deviceId)) {
1166         return true;
1167     }
1168 
1169     int32_t syncStatus = DEVICE_SYNCSTATUSING;
1170     auto result = MediaLibraryDevice::GetInstance()->GetDevicieSyncStatus(deviceId, syncStatus, bundleName_);
1171     if (result && syncStatus == DEVICE_SYNCSTATUS_COMPLETE) {
1172         return true;
1173     }
1174 
1175     std::vector<std::string> devices = { deviceId };
1176     MediaLibrarySyncTable syncTable;
1177     return syncTable.SyncPullTable(rdbStore_, bundleName_, tableName, devices);
1178 }
1179 
QuerySync()1180 bool MediaLibraryDataAbility::QuerySync()
1181 {
1182     std::string strQueryCondition = DEVICE_DB_SYNC_STATUS + "=" + std::to_string(DEVICE_SYNCSTATUSING) +
1183         " AND " + DEVICE_DB_DATE_MODIFIED + "=0";
1184 
1185     std::vector<std::string> columns;
1186     std::vector<std::string> devices;
1187     shared_ptr<AbsSharedResultSet> queryResultSet;
1188     AbsRdbPredicates deviceAbsRdbPredicates(DEVICE_TABLE);
1189     deviceAbsRdbPredicates.SetWhereClause(strQueryCondition);
1190 
1191     queryResultSet = rdbStore_->Query(deviceAbsRdbPredicates, columns);
1192     if (queryResultSet == nullptr) {
1193         return false;
1194     }
1195 
1196     if (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
1197         int32_t columnIndexId;
1198         std::string deviceId;
1199         queryResultSet->GetColumnIndex(DEVICE_DB_DEVICEID, columnIndexId);
1200         queryResultSet->GetString(columnIndexId, deviceId);
1201 
1202         if (!deviceId.empty()) {
1203             devices.push_back(deviceId);
1204         }
1205     }
1206 
1207     if (devices.empty()) {
1208         return true;
1209     }
1210 
1211     MediaLibrarySyncTable syncTable;
1212     return syncTable.SyncPullAllTableByDeviceId(rdbStore_, bundleName_, devices);
1213 }
1214 
CheckFileNameValid(const ValuesBucket & value)1215 bool MediaLibraryDataAbility::CheckFileNameValid(const ValuesBucket &value)
1216 {
1217     ValueObject valueObject;
1218     string displayName("");
1219     if (!value.GetObject(MEDIA_DATA_DB_NAME, valueObject)) {
1220         return false;
1221     }
1222     valueObject.GetString(displayName);
1223 
1224     if (displayName.empty()) {
1225         return false;
1226     }
1227 
1228     if (displayName.at(0) == '.') {
1229         std::string bundleName = GetClientBundleName();
1230         if (IsSameTextStr(displayName, ".nofile") && IsSameTextStr(bundleName, "fms_service")) {
1231             return true;
1232         }
1233         return false;
1234     }
1235     return true;
1236 }
1237 
GetSysBundleManager()1238 sptr<AppExecFwk::IBundleMgr> MediaLibraryDataAbility::GetSysBundleManager()
1239 {
1240     if (bundleMgr_ == nullptr) {
1241         std::lock_guard<std::mutex> lock(bundleMgrMutex);
1242         if (bundleMgr_ == nullptr) {
1243             auto saMgr = OHOS::DelayedSingleton<SaMgrClient>::GetInstance();
1244             if (saMgr == nullptr) {
1245                 MEDIA_ERR_LOG("failed to get SaMgrClient::GetInstance");
1246                 return nullptr;
1247             }
1248             auto bundleObj = saMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
1249             if (bundleObj == nullptr) {
1250                 MEDIA_ERR_LOG("failed to get GetSystemAbility");
1251                 return nullptr;
1252             }
1253             auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
1254             if (bundleMgr == nullptr) {
1255                 MEDIA_ERR_LOG("failed to iface_cast");
1256                 return nullptr;
1257             }
1258             bundleMgr_ = bundleMgr;
1259         }
1260     }
1261     return bundleMgr_;
1262 }
1263 
GetClientBundle(int uid)1264 std::string MediaLibraryDataAbility::GetClientBundle(int uid)
1265 {
1266     auto bms = GetSysBundleManager();
1267     std::string bundleName = "";
1268     if (bms == nullptr) {
1269         MEDIA_INFO_LOG("GetClientBundleName bms failed");
1270         return bundleName;
1271     }
1272     auto result = bms->GetBundleNameForUid(uid, bundleName);
1273     MEDIA_INFO_LOG("uid %{public}d bundleName is %{public}s ", uid, bundleName.c_str());
1274     if (!result) {
1275         MEDIA_ERR_LOG("GetBundleNameForUid fail");
1276         return "";
1277     }
1278     return bundleName;
1279 }
1280 
GetClientBundleName()1281 std::string MediaLibraryDataAbility::GetClientBundleName()
1282 {
1283     int uid = IPCSkeleton::GetCallingUid();
1284     return GetClientBundle(uid);
1285 }
1286 
CheckClientPermission(const std::string & permissionStr)1287 bool MediaLibraryDataAbility::CheckClientPermission(const std::string& permissionStr)
1288 {
1289     int uid = IPCSkeleton::GetCallingUid();
1290     if (UID_FREE_CHECK.find(uid) != UID_FREE_CHECK.end()) {
1291         MEDIA_INFO_LOG("CheckClientPermission: Pass the uid white list");
1292         return true;
1293     }
1294 
1295     std::string bundleName = GetClientBundle(uid);
1296     MEDIA_INFO_LOG("CheckClientPermission: bundle name: %{public}s", bundleName.c_str());
1297     if (BUNDLE_FREE_CHECK.find(bundleName) != BUNDLE_FREE_CHECK.end()) {
1298         MEDIA_INFO_LOG("CheckClientPermission: Pass the bundle name white list");
1299         return true;
1300     }
1301 
1302     auto bundleMgr = GetSysBundleManager();
1303     if ((bundleMgr != nullptr) && bundleMgr->CheckIsSystemAppByUid(uid) &&
1304         (SYSTEM_BUNDLE_FREE_CHECK.find(bundleName) != SYSTEM_BUNDLE_FREE_CHECK.end())) {
1305         MEDIA_INFO_LOG("CheckClientPermission: Pass the system bundle name white list");
1306         return true;
1307     }
1308 
1309     Security::AccessToken::AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
1310     int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller,
1311         permissionStr);
1312     if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
1313         MEDIA_ERR_LOG("MediaLibraryDataAbility Query: Have no media permission");
1314         return false;
1315     }
1316     return true;
1317 }
1318 
InitialiseKvStore()1319 void MediaLibraryDataAbility::InitialiseKvStore()
1320 {
1321     MEDIA_INFO_LOG("MediaLibraryDataAbility::InitialiseKvStore");
1322     if (kvStorePtr_ != nullptr) {
1323         return;
1324     }
1325 
1326     Options options = {
1327         .createIfMissing = true,
1328         .encrypt = false,
1329         .autoSync = false,
1330         .kvStoreType = KvStoreType::SINGLE_VERSION
1331     };
1332 
1333     Status status = dataManager_.GetSingleKvStore(options, KVSTORE_APPID, KVSTORE_STOREID, kvStorePtr_);
1334     if (status != Status::SUCCESS || kvStorePtr_ == nullptr) {
1335         MEDIA_INFO_LOG("MediaLibraryDataAbility::InitialiseKvStore failed %{public}d", status);
1336     }
1337 }
1338 
OnScanFinished(const int32_t status,const std::string & uri,const std::string & path)1339 void ScanFileCallback::OnScanFinished(const int32_t status, const std::string &uri, const std::string &path) {}
1340 
OnDeviceOnline(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)1341 void MediaLibraryDeviceStateCallback::OnDeviceOnline(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
1342 {
1343     MediaLibraryDevice::GetInstance()->OnDeviceOnline(deviceInfo, bundleName_);
1344 
1345     MediaLibrarySyncTable syncTable;
1346     std::string deviceId = deviceInfo.deviceId;
1347     std::vector<std::string> devices = { deviceId };
1348     syncTable.SyncPullAllTableByDeviceId(rdbStore_, bundleName_, devices);
1349 }
1350 
OnDeviceOffline(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)1351 void MediaLibraryDeviceStateCallback::OnDeviceOffline(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
1352 {
1353     MediaLibraryDevice::GetInstance()->OnDeviceOffline(deviceInfo, bundleName_);
1354 }
1355 
OnDeviceChanged(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)1356 void MediaLibraryDeviceStateCallback::OnDeviceChanged(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
1357 {
1358     MediaLibraryDevice::GetInstance()->OnDeviceChanged(deviceInfo);
1359 }
1360 
OnDeviceReady(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)1361 void MediaLibraryDeviceStateCallback::OnDeviceReady(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
1362 {
1363     MediaLibraryDevice::GetInstance()->OnDeviceReady(deviceInfo);
1364 }
1365 
OnRemoteDied()1366 void MediaLibraryInitCallback::OnRemoteDied()
1367 {
1368     MEDIA_INFO_LOG("MediaLibraryInitCallback OnRemoteDied call");
1369 }
1370 
MediaLibraryRdbStoreObserver(std::string & bundleName)1371 MediaLibraryRdbStoreObserver::MediaLibraryRdbStoreObserver(std::string &bundleName)
1372 {
1373     bundleName_ = bundleName;
1374     isNotifyDeviceChange_ = false;
1375 
1376     if (timer_ == nullptr) {
1377         timer_ = std::make_unique<OHOS::Utils::Timer>(bundleName_);
1378         timerId_ = timer_->Register(std::bind(&MediaLibraryRdbStoreObserver::NotifyDeviceChange, this),
1379                                     NOTIFY_TIME_INTERVAL);
1380         timer_->Setup();
1381     }
1382 }
1383 
~MediaLibraryRdbStoreObserver()1384 MediaLibraryRdbStoreObserver::~MediaLibraryRdbStoreObserver()
1385 {
1386     if (timer_ != nullptr) {
1387         timer_->Shutdown();
1388         timer_->Unregister(timerId_);
1389         timer_ = nullptr;
1390     }
1391 }
1392 
OnChange(const std::vector<std::string> & devices)1393 void MediaLibraryRdbStoreObserver::OnChange(const std::vector<std::string>& devices)
1394 {
1395     MEDIA_INFO_LOG("MediaLibraryRdbStoreObserver OnChange call");
1396     if (devices.empty() || bundleName_.empty()) {
1397         return;
1398     }
1399     MediaLibraryDevice::GetInstance()->NotifyRemoteFileChange();
1400     for (auto &deviceId : devices) {
1401         MediaLibraryDevice::GetInstance()->UpdateDevicieSyncStatus(deviceId, DEVICE_SYNCSTATUS_COMPLETE, bundleName_);
1402         isNotifyDeviceChange_ = true;
1403     }
1404 }
1405 
NotifyDeviceChange()1406 void MediaLibraryRdbStoreObserver::NotifyDeviceChange()
1407 {
1408     if (isNotifyDeviceChange_) {
1409         MediaLibraryDevice::GetInstance()->NotifyDeviceChange();
1410         isNotifyDeviceChange_ = false;
1411     }
1412 }
1413 }  // namespace Media
1414 }  // namespace OHOS
1415