1/*
2 * Copyright (c) 2021-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 "sms_mms_ability.h"
17
18#include "ability_context.h"
19#include "ability_loader.h"
20#include "abs_rdb_predicates.h"
21#include "abs_shared_result_set.h"
22#include "data_storage_errors.h"
23#include "data_storage_log_wrapper.h"
24#include "datashare_ext_ability.h"
25#include "datashare_predicates.h"
26#include "new"
27#include "permission_util.h"
28#include "rdb_errno.h"
29#include "rdb_utils.h"
30#include "sms_mms_data.h"
31#include "telephony_datashare_stub_impl.h"
32#include "uri.h"
33#include "utility"
34
35namespace OHOS {
36using AppExecFwk::Ability;
37using AppExecFwk::AbilityLoader;
38namespace Telephony {
39const int32_t CHANGED_ROWS = 0;
40static const std::map<std::string, MessageUriType> smsMmsUriMap_ = {
41    { "/sms_mms/sms_mms_info", MessageUriType::SMS_MMS },
42    { "/sms_mms/sms_mms_info/thirty", MessageUriType::THIRTY },
43    { "/sms_mms/sms_mms_info/max_group", MessageUriType::MAX_GROUP },
44    { "/sms_mms/sms_mms_info/unread_total", MessageUriType::UNREAD_TOTAL },
45    { "/sms_mms/mms_protocol", MessageUriType::MMS_PROTOCOL },
46    { "/sms_mms/sms_subsection", MessageUriType::SMS_SUBSECTION },
47    { "/sms_mms/mms_part", MessageUriType::MMS_PART },
48    { "/sms_mms/session", MessageUriType::SESSION },
49    { "/sms_mms/mms_pdu", MessageUriType::MMS_PDU },
50};
51
52SmsMmsAbility::SmsMmsAbility() : DataShareExtAbility() {}
53
54SmsMmsAbility::~SmsMmsAbility() {}
55
56SmsMmsAbility* SmsMmsAbility::Create()
57{
58    DATA_STORAGE_LOGD("SmsMmsAbility::Create begin.");
59    auto self =  new SmsMmsAbility();
60    self->DoInit();
61    return self;
62}
63
64void SmsMmsAbility::DoInit()
65{
66    if (initDatabaseDir && initRdbStore) {
67        DATA_STORAGE_LOGI("DoInit has done");
68        return;
69    }
70    auto abilityContext = AbilityRuntime::Context::GetApplicationContext();
71    if (abilityContext == nullptr) {
72        DATA_STORAGE_LOGE("DoInit GetAbilityContext is null");
73        return;
74    }
75    // switch database dir to el1 for init before unlock
76    abilityContext->SwitchArea(0);
77    std::string path = abilityContext->GetDatabaseDir();
78    if (!path.empty()) {
79        initDatabaseDir = true;
80        path.append("/");
81        helper_.UpdateDbPath(path);
82        if (helper_.Init() == NativeRdb::E_OK) {
83            initRdbStore = true;
84        } else {
85            DATA_STORAGE_LOGE("DoInit rdb init failed!");
86            initRdbStore = false;
87        }
88    } else {
89        DATA_STORAGE_LOGE("DoInit##databaseDir is empty!");
90        initDatabaseDir = false;
91    }
92}
93
94sptr<IRemoteObject> SmsMmsAbility::OnConnect(const AAFwk::Want &want)
95{
96    DATA_STORAGE_LOGI("SmsMmsAbility::OnConnect");
97    Extension::OnConnect(want);
98    sptr<DataShare::TelephonyDataShareStubImpl> remoteObject =
99        new (std::nothrow) DataShare::TelephonyDataShareStubImpl();
100    if (remoteObject == nullptr) {
101        DATA_STORAGE_LOGE("%{public}s No memory allocated for DataShareStubImpl", __func__);
102        return nullptr;
103    }
104    remoteObject->SetSmsMmsAbility(std::static_pointer_cast<SmsMmsAbility>(shared_from_this()));
105    DATA_STORAGE_LOGI("SmsMmsAbility %{public}s end.", __func__);
106    return remoteObject->AsObject();
107}
108
109void SmsMmsAbility::OnStart(const AppExecFwk::Want &want)
110{
111    DATA_STORAGE_LOGI("SmsMmsAbility::OnStart");
112    Extension::OnStart(want);
113    DoInit();
114}
115
116int SmsMmsAbility::Insert(const Uri &uri, const DataShare::DataShareValuesBucket &value)
117{
118    if (!PermissionUtil::CheckPermission(Permission::READ_MESSAGES)) {
119        DATA_STORAGE_LOGE("Permission denied!");
120        return DATA_STORAGE_ERR_PERMISSION_ERR;
121    }
122    if (!IsInitOk()) {
123        return DATA_STORAGE_ERROR;
124    }
125    std::lock_guard<std::mutex> guard(lock_);
126    Uri tempUri = uri;
127    MessageUriType messageUriType = ParseUriType(tempUri);
128    int64_t id = DATA_STORAGE_ERROR;
129    OHOS::NativeRdb::ValuesBucket values = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
130    switch (messageUriType) {
131        case MessageUriType::SMS_MMS: {
132            helper_.Insert(id, values, TABLE_SMS_MMS_INFO);
133            break;
134        }
135        case MessageUriType::MMS_PROTOCOL: {
136            helper_.Insert(id, values, TABLE_MMS_PROTOCOL);
137            break;
138        }
139        case MessageUriType::SMS_SUBSECTION: {
140            helper_.Insert(id, values, TABLE_SMS_SUBSECTION);
141            break;
142        }
143        case MessageUriType::MMS_PART: {
144            helper_.Insert(id, values, TABLE_MMS_PART);
145            break;
146        }
147        case MessageUriType::SESSION: {
148            helper_.Insert(id, values, TABLE_SESSION);
149            break;
150        }
151        case MessageUriType::MMS_PDU: {
152            helper_.Insert(id, values, TABLE_MMS_PDU);
153            break;
154        }
155        default:
156            DATA_STORAGE_LOGI("SmsMmsAbility::Insert##uri = %{public}s", uri.ToString().c_str());
157            break;
158    }
159    return id;
160}
161
162std::shared_ptr<DataShare::DataShareResultSet> SmsMmsAbility::Query(
163    const Uri &uri, const DataShare::DataSharePredicates &predicates, std::vector<std::string> &columns,
164    DataShare::DatashareBusinessError &businessError)
165{
166    if (!PermissionUtil::CheckPermission(Permission::READ_MESSAGES)) {
167        DATA_STORAGE_LOGE("Permission denied!");
168        return nullptr;
169    }
170    if (!IsInitOk()) {
171        return nullptr;
172    }
173    Uri tempUri = uri;
174    MessageUriType messageUriType = ParseUriType(tempUri);
175    if (messageUriType == MessageUriType::MAX_GROUP || messageUriType == MessageUriType::UNREAD_TOTAL) {
176        return GetResultSet(messageUriType, uri);
177    }
178    NativeRdb::AbsRdbPredicates *absRdbPredicates = GetPredicates(messageUriType, uri);
179    std::shared_ptr<DataShare::DataShareResultSet> sharedPtrResult = nullptr;
180    if (absRdbPredicates != nullptr) {
181        NativeRdb::RdbPredicates rdbPredicates = ConvertPredicates(absRdbPredicates->GetTableName(), predicates);
182        auto resultSet = helper_.Query(rdbPredicates, columns);
183        if (resultSet == nullptr) {
184            DATA_STORAGE_LOGE("SmsMmsAbility::Query  NativeRdb::ResultSet is null!");
185            delete absRdbPredicates;
186            absRdbPredicates = nullptr;
187            return nullptr;
188        }
189        auto queryResultSet = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet);
190        sharedPtrResult = std::make_shared<DataShare::DataShareResultSet>(queryResultSet);
191        delete absRdbPredicates;
192        absRdbPredicates = nullptr;
193    } else {
194        DATA_STORAGE_LOGE("SmsMmsAbility::Query  NativeRdb::AbsRdbPredicates is null!");
195    }
196    return sharedPtrResult;
197}
198
199int SmsMmsAbility::Update(
200    const Uri &uri, const DataShare::DataSharePredicates &predicates,
201    const DataShare::DataShareValuesBucket &value)
202{
203    if (!PermissionUtil::CheckPermission(Permission::READ_MESSAGES)) {
204        DATA_STORAGE_LOGE("Permission denied!");
205        return DATA_STORAGE_ERR_PERMISSION_ERR;
206    }
207    int result = DATA_STORAGE_ERROR;
208    if (!IsInitOk()) {
209        return result;
210    }
211    std::lock_guard<std::mutex> guard(lock_);
212    Uri tempUri = uri;
213    MessageUriType messageUriType = ParseUriType(tempUri);
214    NativeRdb::AbsRdbPredicates *absRdbPredicates = GetPredicates(messageUriType, uri);
215    if (absRdbPredicates != nullptr) {
216        int changedRows = CHANGED_ROWS;
217        NativeRdb::RdbPredicates rdbPredicates = ConvertPredicates(absRdbPredicates->GetTableName(), predicates);
218        OHOS::NativeRdb::ValuesBucket values = RdbDataShareAdapter::RdbUtils::ToValuesBucket(value);
219        result = helper_.Update(changedRows, values, rdbPredicates);
220        delete absRdbPredicates;
221        absRdbPredicates = nullptr;
222    } else {
223        DATA_STORAGE_LOGE("SmsMmsAbility::Update  NativeRdb::AbsRdbPredicates is null!");
224    }
225    return result;
226}
227
228NativeRdb::AbsRdbPredicates *SmsMmsAbility::GetPredicates(MessageUriType messageUriType, const Uri &uri)
229{
230    NativeRdb::AbsRdbPredicates *absRdbPredicates = nullptr;
231    switch (messageUriType) {
232        case MessageUriType::SMS_MMS: {
233            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_SMS_MMS_INFO);
234            return absRdbPredicates;
235        }
236        case MessageUriType::MMS_PROTOCOL: {
237            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_MMS_PROTOCOL);
238            return absRdbPredicates;
239        }
240        case MessageUriType::SMS_SUBSECTION: {
241            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_SMS_SUBSECTION);
242            return absRdbPredicates;
243        }
244        case MessageUriType::MMS_PART: {
245            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_MMS_PART);
246            return absRdbPredicates;
247        }
248        case MessageUriType::SESSION: {
249            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_SESSION);
250            return absRdbPredicates;
251        }
252        case MessageUriType::MMS_PDU: {
253            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_MMS_PDU);
254            return absRdbPredicates;
255        }
256        default:
257            DATA_STORAGE_LOGD("GetPredicates##uri = %{private}s", uri.ToString().c_str());
258            return absRdbPredicates;
259    }
260}
261
262std::shared_ptr<DataShare::DataShareResultSet> SmsMmsAbility::GetResultSet(
263    MessageUriType messageUriType, const Uri &uri)
264{
265    std::shared_ptr<DataShare::DataShareResultSet> sharedPtrResult = nullptr;
266    std::shared_ptr<NativeRdb::ResultSet> resultSet = nullptr;
267    switch (messageUriType) {
268        case MessageUriType::MAX_GROUP: {
269            resultSet = helper_.QueryMaxGroupId();
270            if (resultSet == nullptr) {
271                DATA_STORAGE_LOGE("ResultSet is null!");
272                return nullptr;
273            }
274            auto queryResultSet = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet);
275            sharedPtrResult = std::make_shared<DataShare::DataShareResultSet>(queryResultSet);
276            break;
277        }
278        case MessageUriType::UNREAD_TOTAL: {
279            resultSet = helper_.StatisticsUnRead();
280            if (resultSet == nullptr) {
281                DATA_STORAGE_LOGE("ResultSet is null!");
282                return nullptr;
283            }
284            auto queryResultSet = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet);
285            sharedPtrResult = std::make_shared<DataShare::DataShareResultSet>(queryResultSet);
286            break;
287        }
288        default:
289            DATA_STORAGE_LOGI("uri = %{public}s", uri.ToString().c_str());
290            break;
291    }
292    return sharedPtrResult;
293}
294
295int SmsMmsAbility::Delete(const Uri &uri, const DataShare::DataSharePredicates &predicates)
296{
297    if (!PermissionUtil::CheckPermission(Permission::READ_MESSAGES)) {
298        DATA_STORAGE_LOGE("Permission denied!");
299        return DATA_STORAGE_ERR_PERMISSION_ERR;
300    }
301    int result = DATA_STORAGE_ERROR;
302    if (!IsInitOk()) {
303        return result;
304    }
305    std::lock_guard<std::mutex> guard(lock_);
306    Uri tempUri = uri;
307    MessageUriType messageUriType = ParseUriType(tempUri);
308    NativeRdb::AbsRdbPredicates *absRdbPredicates = CreateAbsRdbPredicates(messageUriType, result, tempUri);
309    if (absRdbPredicates != nullptr) {
310        NativeRdb::RdbPredicates rdbPredicates = ConvertPredicates(absRdbPredicates->GetTableName(), predicates);
311        int deletedRows = CHANGED_ROWS;
312        result = helper_.Delete(deletedRows, rdbPredicates);
313        delete absRdbPredicates;
314        absRdbPredicates = nullptr;
315    } else if (result == DATA_STORAGE_ERROR) {
316        DATA_STORAGE_LOGE("SmsMmsAbility::Delete NativeRdb::AbsRdbPredicates is null!");
317    }
318    return result;
319}
320
321NativeRdb::AbsRdbPredicates *SmsMmsAbility::CreateAbsRdbPredicates(MessageUriType messageUriType, int &result, Uri uri)
322{
323    NativeRdb::AbsRdbPredicates *absRdbPredicates = nullptr;
324    switch (messageUriType) {
325        case MessageUriType::SMS_MMS: {
326            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_SMS_MMS_INFO);
327            return absRdbPredicates;
328        }
329        case MessageUriType::THIRTY: {
330            result = helper_.DeleteDataByThirty();
331            if (result != NativeRdb::E_OK) {
332                DATA_STORAGE_LOGE("SmsMmsAbility::Delete  DeleteDataByThirty fail!");
333                result = static_cast<int>(LoadProFileErrorType::DELETE_THIRTY_DATA_FAIL);
334            }
335            return absRdbPredicates;
336        }
337        case MessageUriType::MMS_PROTOCOL: {
338            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_MMS_PROTOCOL);
339            return absRdbPredicates;
340        }
341        case MessageUriType::SMS_SUBSECTION: {
342            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_SMS_SUBSECTION);
343            return absRdbPredicates;
344        }
345        case MessageUriType::MMS_PART: {
346            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_MMS_PART);
347            return absRdbPredicates;
348        }
349        case MessageUriType::SESSION: {
350            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_SESSION);
351            return absRdbPredicates;
352        }
353        case MessageUriType::MMS_PDU: {
354            absRdbPredicates = new NativeRdb::AbsRdbPredicates(TABLE_MMS_PDU);
355            return absRdbPredicates;
356        }
357        default:
358            DATA_STORAGE_LOGI("SmsMmsAbility::Delete##uri = %{public}s", uri.ToString().c_str());
359            return absRdbPredicates;
360    }
361}
362
363bool SmsMmsAbility::IsInitOk()
364{
365    if (!initDatabaseDir) {
366        DATA_STORAGE_LOGE("SmsMmsAbility::IsInitOk initDatabaseDir failed!");
367    } else if (!initRdbStore) {
368        DATA_STORAGE_LOGE("SmsMmsAbility::IsInitOk initRdbStore failed!");
369    }
370    return initDatabaseDir && initRdbStore;
371}
372
373std::string SmsMmsAbility::GetType(const Uri &uri)
374{
375    DATA_STORAGE_LOGI("SmsMmsAbility::GetType##uri = %{public}s", uri.ToString().c_str());
376    std::string retval(uri.ToString());
377    return retval;
378}
379
380int SmsMmsAbility::OpenFile(const Uri &uri, const std::string &mode)
381{
382    DATA_STORAGE_LOGI("SmsMmsAbility::OpenFile##uri = %{public}s", uri.ToString().c_str());
383    Uri tempUri = uri;
384    MessageUriType messageUriType = ParseUriType(tempUri);
385    return static_cast<int>(messageUriType);
386}
387
388int SmsMmsAbility::BatchInsert(const Uri &uri, const std::vector<DataShare::DataShareValuesBucket> &values)
389{
390    if (!PermissionUtil::CheckPermission(Permission::READ_MESSAGES)) {
391        DATA_STORAGE_LOGE("Permission denied!");
392        return DATA_STORAGE_ERR_PERMISSION_ERR;
393    }
394    int result = DATA_STORAGE_ERROR;
395    if (!IsInitOk()) {
396        return result;
397    }
398    std::lock_guard<std::mutex> guard(lock_);
399    Uri tempUri = uri;
400    MessageUriType messageUriType = ParseUriType(tempUri);
401    int64_t id = DATA_STORAGE_ERROR;
402    if (messageUriType == MessageUriType::SMS_MMS) {
403        result = helper_.BatchInsertSmsMmsInfo(id, values);
404    } else {
405        DATA_STORAGE_LOGI("SmsMmsAbility::BatchInsert##uri = %{public}s", uri.ToString().c_str());
406    }
407    return result;
408}
409
410MessageUriType SmsMmsAbility::ParseUriType(Uri &uri)
411{
412    DATA_STORAGE_LOGD("SmsMmsAbility::ParseUriType start");
413    MessageUriType messageUriType = MessageUriType::UNKNOW;
414    std::string uriPath = uri.ToString();
415    if (!uriPath.empty()) {
416        helper_.ReplaceAllStr(uriPath, ":///", "://");
417        Uri tempUri(uriPath);
418        std::string path = tempUri.GetPath();
419        if (!path.empty() && !smsMmsUriMap_.empty()) {
420            DATA_STORAGE_LOGD("SmsMmsAbility::ParseUriType##path = %{private}s", path.c_str());
421            auto it = smsMmsUriMap_.find(path);
422            if (it != smsMmsUriMap_.end()) {
423                messageUriType = it->second;
424                DATA_STORAGE_LOGD("SmsMmsAbility::ParseUriType##messageUriType = %{private}d", messageUriType);
425            }
426        }
427    }
428    return messageUriType;
429}
430
431OHOS::NativeRdb::RdbPredicates SmsMmsAbility::ConvertPredicates(
432    const std::string &tableName, const DataShare::DataSharePredicates &predicates)
433{
434    OHOS::NativeRdb::RdbPredicates res = RdbDataShareAdapter::RdbUtils::ToPredicates(predicates, tableName);
435    return res;
436}
437} // namespace Telephony
438} // namespace OHOS
439