1 /*
2  * Copyright (C) 2021-2024 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_persist_helper.h"
17 
18 #include "ability_manager_interface.h"
19 #include "if_system_ability_manager.h"
20 #include "iservice_registry.h"
21 #include "parameter.h"
22 #include "phonenumbers/phonenumber.pb.h"
23 #include "resource_manager.h"
24 #include "string_utils.h"
25 #include "system_ability.h"
26 #include "system_ability_definition.h"
27 #include "telephony_errors.h"
28 #include "telephony_log_wrapper.h"
29 
30 namespace OHOS {
31 namespace Telephony {
32 constexpr static uint8_t SMS_TYPE_CDMA = 2;
33 const std::string SMS_URI = "datashare:///com.ohos.smsmmsability";
34 const std::string SMS_SUBSECTION = "datashare:///com.ohos.smsmmsability/sms_mms/sms_subsection";
35 const std::string SMS_MMS_INFO = "datashare:///com.ohos.smsmmsability/sms_mms/sms_mms_info";
36 const std::string SMS_SESSION = "datashare:///com.ohos.smsmmsability/sms_mms/session";
37 const std::string CONTACT_URI = "datashare:///com.ohos.contactsdataability";
38 const std::string CONTACT_BLOCK = "datashare:///com.ohos.contactsdataability/contacts/contact_blocklist";
39 const std::string CONTACT_DATA = "datashare:///com.ohos.contactsdataability/contacts/contact_data";
40 const std::string RAW_CONTACT = "datashare:///com.ohos.contactsdataability/contacts/raw_contact";
41 const std::string ISO_COUNTRY_CODE = "CN";
42 const std::string PHONE_NUMBER = "phone_number";
43 const std::string DETAIL_INFO = "detail_info";
44 const std::string TYPE_ID = "type_id";
45 std::string ID = "id";
46 const std::string RAW_CONTACT_ID = "raw_contact_id";
47 const std::string CONTACTED_COUNT = "contacted_count";
48 const std::string LASTEST_CONTACTED_TIME = "lastest_contacted_time";
49 constexpr static uint8_t TYPE_ID_VALUE = 5;
50 const std::string PREFIX = "+86";
51 const std::string NUMBER_START_STR = "192";
52 
SmsPersistHelper()53 SmsPersistHelper::SmsPersistHelper() {}
54 
~SmsPersistHelper()55 SmsPersistHelper::~SmsPersistHelper() {}
56 
CreateDataShareHelper(const std::string & uri)57 std::shared_ptr<DataShare::DataShareHelper> SmsPersistHelper::CreateDataShareHelper(const std::string &uri)
58 {
59     auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
60     if (saManager == nullptr) {
61         TELEPHONY_LOGE(" Get system ability mgr failed.");
62         return nullptr;
63     }
64     auto remoteObj = saManager->GetSystemAbility(TELEPHONY_SMS_MMS_SYS_ABILITY_ID);
65     if (remoteObj == nullptr) {
66         TELEPHONY_LOGE("GetSystemAbility Service Failed.");
67         return nullptr;
68     }
69     return DataShare::DataShareHelper::Creator(remoteObj, uri);
70 }
71 
Insert(DataShare::DataShareValuesBucket & values,uint16_t & dataBaseId)72 bool SmsPersistHelper::Insert(DataShare::DataShareValuesBucket &values, uint16_t &dataBaseId)
73 {
74     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(SMS_URI);
75     if (helper == nullptr) {
76         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
77         return false;
78     }
79     Uri uri(SMS_SUBSECTION);
80     int ret = helper->Insert(uri, values);
81     helper->Release();
82     dataBaseId = ret;
83     return ret >= 0 ? true : false;
84 }
85 
Insert(std::string tableUri,DataShare::DataShareValuesBucket & values)86 bool SmsPersistHelper::Insert(std::string tableUri, DataShare::DataShareValuesBucket &values)
87 {
88     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(SMS_URI);
89     if (helper == nullptr) {
90         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
91         return false;
92     }
93     Uri uri(tableUri);
94     int ret = helper->Insert(uri, values);
95     helper->Release();
96     return ret >= 0 ? true : false;
97 }
98 
QuerySession(DataShare::DataSharePredicates & predicates,uint16_t & sessionId,uint16_t & messageCount)99 bool SmsPersistHelper::QuerySession(
100     DataShare::DataSharePredicates &predicates, uint16_t &sessionId, uint16_t &messageCount)
101 {
102     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(SMS_URI);
103     if (helper == nullptr) {
104         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
105         return false;
106     }
107     Uri uri(SMS_SESSION);
108     std::vector<std::string> columns;
109     auto resultSet = helper->Query(uri, predicates, columns);
110     if (resultSet == nullptr) {
111         TELEPHONY_LOGE("Query Result Set nullptr Failed.");
112         helper->Release();
113         return false;
114     }
115     resultSet->GoToFirstRow();
116     int32_t columnInt;
117     int columnIndex;
118     resultSet->GetColumnIndex("id", columnIndex);
119     if (resultSet->GetInt(columnIndex, columnInt) == 0) {
120         sessionId = columnInt;
121     }
122     resultSet->GetColumnIndex("message_count", columnIndex);
123     if (resultSet->GetInt(columnIndex, columnInt) == 0) {
124         messageCount = columnInt;
125         resultSet->Close();
126         helper->Release();
127         return true;
128     }
129     resultSet->Close();
130     helper->Release();
131     return false;
132 }
133 
Update(DataShare::DataSharePredicates & predicates,DataShare::DataShareValuesBucket & values)134 bool SmsPersistHelper::Update(DataShare::DataSharePredicates &predicates, DataShare::DataShareValuesBucket &values)
135 {
136     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(SMS_URI);
137     if (helper == nullptr) {
138         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
139         return false;
140     }
141     Uri uri(SMS_SESSION);
142     int ret = helper->Update(uri, predicates, values);
143     helper->Release();
144     return ret >= 0 ? true : false;
145 }
146 
Query(DataShare::DataSharePredicates & predicates,std::vector<SmsReceiveIndexer> & indexers)147 bool SmsPersistHelper::Query(DataShare::DataSharePredicates &predicates, std::vector<SmsReceiveIndexer> &indexers)
148 {
149     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(SMS_URI);
150     if (helper == nullptr) {
151         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
152         return false;
153     }
154     Uri uri(SMS_SUBSECTION);
155     std::vector<std::string> columns;
156     auto resultSet = helper->Query(uri, predicates, columns);
157     if (resultSet == nullptr) {
158         TELEPHONY_LOGE("Query Result Set nullptr Failed.");
159         helper->Release();
160         return false;
161     }
162 
163     int resultSetNum = resultSet->GoToFirstRow();
164     TELEPHONY_LOGE("resultSetNum is %{public}d before cycle", resultSetNum);
165     while (resultSetNum == 0) {
166         SmsReceiveIndexer indexer;
167         ResultSetConvertToIndexer(indexer, resultSet);
168         indexers.push_back(indexer);
169         resultSetNum = resultSet->GoToNextRow();
170         TELEPHONY_LOGE("resultSetNum is %{public}d in cycle", resultSetNum);
171     }
172     resultSet->Close();
173     helper->Release();
174     return true;
175 }
176 
QueryMaxGroupId(DataShare::DataSharePredicates & predicates,uint16_t & maxGroupId)177 bool SmsPersistHelper::QueryMaxGroupId(DataShare::DataSharePredicates &predicates, uint16_t &maxGroupId)
178 {
179     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(SMS_URI);
180     if (helper == nullptr) {
181         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
182         return false;
183     }
184     Uri uri(SMS_MMS_INFO);
185     std::vector<std::string> columns;
186     auto resultSet = helper->Query(uri, predicates, columns);
187     if (resultSet == nullptr) {
188         TELEPHONY_LOGE("Query Result Set nullptr Failed.");
189         helper->Release();
190         return false;
191     }
192 
193     int32_t columnInt;
194     int columnIndex;
195     resultSet->GoToLastRow();
196     resultSet->GetColumnIndex(SmsMmsInfo::GROUP_ID, columnIndex);
197     if (resultSet->GetInt(columnIndex, columnInt) == 0) {
198         maxGroupId = columnInt;
199     }
200     resultSet->Close();
201     helper->Release();
202     return true;
203 }
204 
Delete(DataShare::DataSharePredicates & predicates)205 bool SmsPersistHelper::Delete(DataShare::DataSharePredicates &predicates)
206 {
207     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(SMS_URI);
208     if (helper == nullptr) {
209         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
210         return false;
211     }
212     Uri uri(SMS_SUBSECTION);
213     int ret = helper->Delete(uri, predicates);
214     helper->Release();
215     return ret >= 0 ? true : false;
216 }
217 
QueryBlockPhoneNumber(const std::string & phoneNum)218 bool SmsPersistHelper::QueryBlockPhoneNumber(const std::string &phoneNum)
219 {
220     bool result = false;
221     if (phoneNum.empty()) {
222         return result;
223     }
224     return result;
225 }
226 
FormatSmsNumber(const std::string & num,std::string countryCode,const i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat formatInfo,std::string & formatNum)227 int32_t SmsPersistHelper::FormatSmsNumber(const std::string &num, std::string countryCode,
228     const i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat formatInfo, std::string &formatNum)
229 {
230     if (num.empty()) {
231         TELEPHONY_LOGE("num is nullptr!");
232         return TELEPHONY_ERR_ARGUMENT_INVALID;
233     }
234     i18n::phonenumbers::PhoneNumberUtil *phoneUtils = i18n::phonenumbers::PhoneNumberUtil::GetInstance();
235     if (phoneUtils == nullptr) {
236         TELEPHONY_LOGE("phoneUtils is nullptr");
237         return TELEPHONY_ERR_LOCAL_PTR_NULL;
238     }
239     transform(countryCode.begin(), countryCode.end(), countryCode.begin(), ::toupper);
240     i18n::phonenumbers::PhoneNumber parseResult;
241     phoneUtils->Parse(num, countryCode, &parseResult);
242     if (phoneUtils->IsValidNumber(parseResult)) {
243         phoneUtils->Format(parseResult, formatInfo, &formatNum);
244     } else {
245         std::string numTemp = "";
246         numTemp.assign(num);
247         CbnFormat(numTemp, formatInfo, formatNum);
248     }
249     if (formatNum.empty() || formatNum == "0") {
250         return TELEPHONY_ERROR;
251     }
252     TrimSpace(formatNum);
253     return TELEPHONY_SUCCESS;
254 }
255 
CbnFormat(std::string & numTemp,const i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat formatInfo,std::string & formatNum)256 void SmsPersistHelper::CbnFormat(std::string &numTemp,
257     const i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat formatInfo, std::string &formatNum)
258 {
259     TELEPHONY_LOGD("into CbnFormat");
260     uint8_t minLength = 3;
261     if (numTemp.size() < minLength) {
262         TELEPHONY_LOGD("Phonenumber is too short");
263         return;
264     }
265     if (numTemp.substr(0, NUMBER_START_STR.size()) == NUMBER_START_STR ||
266         numTemp.substr(PREFIX.size(), NUMBER_START_STR.size()) == NUMBER_START_STR) {
267         if (formatInfo == i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::NATIONAL) {
268             if (numTemp.substr(0, PREFIX.size()) == PREFIX) {
269                 numTemp.erase(0, PREFIX.size());
270                 formatNum.assign(numTemp);
271                 return;
272             }
273             formatNum.assign(numTemp);
274             return;
275         }
276         if (formatInfo == i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL) {
277             if (numTemp.substr(0, PREFIX.size()) == PREFIX) {
278                 formatNum.assign(numTemp);
279                 return;
280             }
281             formatNum.assign(PREFIX + numTemp);
282         }
283     }
284 }
285 
TrimSpace(std::string & num)286 void SmsPersistHelper::TrimSpace(std::string &num)
287 {
288     std::string word;
289     std::stringstream streamNum(num);
290     std::string store;
291     while (streamNum >> word) {
292         store += word;
293     }
294     num = store;
295 }
296 
UpdateContact(const std::string & address)297 bool SmsPersistHelper::UpdateContact(const std::string &address)
298 {
299     bool result = false;
300     if (address.empty()) {
301         TELEPHONY_LOGE("address empty");
302         return result;
303     }
304     int32_t rawCountId = 0;
305     int32_t contactedCount = 0;
306     bool ret = QueryContactedCount(address, rawCountId, contactedCount);
307     if (!ret) {
308         TELEPHONY_LOGE("get contacted count fail");
309         return result;
310     }
311     TELEPHONY_LOGI("rawCountId:%{public}d, contactedCount:%{public}d", rawCountId, contactedCount);
312     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(CONTACT_URI);
313     if (helper == nullptr) {
314         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
315         return false;
316     }
317     std::time_t timep;
318     int64_t currentTime = time(&timep);
319     Uri uri(RAW_CONTACT);
320     DataShare::DataSharePredicates predicates;
321     predicates.EqualTo(ID, rawCountId);
322     DataShare::DataShareValuesBucket bucket;
323     bucket.Put(CONTACTED_COUNT, contactedCount + 1);
324     bucket.Put(LASTEST_CONTACTED_TIME, std::to_string(currentTime));
325     auto updateValue = helper->Update(uri, predicates, bucket);
326     TELEPHONY_LOGI("updateValue:%{public}d", updateValue);
327     helper->Release();
328     return updateValue >= 0 ? true : false;
329 }
330 
QueryContactedCount(const std::string & address,int32_t & rawCountId,int32_t & contactedCount)331 bool SmsPersistHelper::QueryContactedCount(const std::string &address, int32_t &rawCountId, int32_t &contactedCount)
332 {
333     bool ret = QueryRawContactId(address, rawCountId);
334     if (!ret) {
335         TELEPHONY_LOGE("no sms address in contact");
336         return ret;
337     }
338     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(CONTACT_URI);
339     if (helper == nullptr) {
340         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
341         return false;
342     }
343     Uri uri(RAW_CONTACT);
344     std::vector<std::string> columns;
345     DataShare::DataSharePredicates predicates;
346     predicates.EqualTo(ID, rawCountId);
347     auto resultSet = helper->Query(uri, predicates, columns);
348     bool result = false;
349     if (resultSet == nullptr) {
350         TELEPHONY_LOGE("result set nullptr.");
351         helper->Release();
352         return result;
353     }
354     int32_t count = 0;
355     if (resultSet->GetRowCount(count) == 0 && count != 0) {
356         resultSet->GoToFirstRow();
357         int columnIndex;
358         resultSet->GetColumnIndex(CONTACTED_COUNT, columnIndex);
359         if (resultSet->GetInt(columnIndex, contactedCount) == 0) {
360             result = true;
361         }
362     }
363     resultSet->Close();
364     helper->Release();
365     return result;
366 }
367 
QueryRawContactId(const std::string & address,int32_t & rawCountId)368 bool SmsPersistHelper::QueryRawContactId(const std::string &address, int32_t &rawCountId)
369 {
370     std::shared_ptr<DataShare::DataShareHelper> helper = CreateDataShareHelper(CONTACT_URI);
371     if (helper == nullptr) {
372         TELEPHONY_LOGE("Create Data Ability Helper nullptr Failed.");
373         return false;
374     }
375     Uri uri(CONTACT_DATA);
376     std::vector<std::string> columns;
377     DataShare::DataSharePredicates predicates;
378     std::string nationalNum;
379     std::string internationalNum;
380     int32_t ret = FormatSmsNumber(
381         address, ISO_COUNTRY_CODE, i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::NATIONAL, nationalNum);
382     if (ret != TELEPHONY_SUCCESS) {
383         TELEPHONY_LOGE("Phone Number format Failed.");
384         nationalNum = address;
385     }
386     ret = FormatSmsNumber(address, ISO_COUNTRY_CODE,
387         i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL, internationalNum);
388     if (ret != TELEPHONY_SUCCESS) {
389         TELEPHONY_LOGE("Phone Number format Failed.");
390         internationalNum = address;
391     }
392     predicates.EqualTo(DETAIL_INFO, nationalNum)->Or()->EqualTo(DETAIL_INFO, internationalNum);
393     predicates.EqualTo(TYPE_ID, TYPE_ID_VALUE);
394     auto resultSet = helper->Query(uri, predicates, columns);
395     bool result = false;
396     if (resultSet == nullptr) {
397         TELEPHONY_LOGE("result set nullptr.");
398         helper->Release();
399         return result;
400     }
401     int32_t count = 0;
402     if (resultSet->GetRowCount(count) == 0 && count != 0) {
403         resultSet->GoToFirstRow();
404         int columnIndex;
405         resultSet->GetColumnIndex(RAW_CONTACT_ID, columnIndex);
406         if (resultSet->GetInt(columnIndex, rawCountId) == 0) {
407             result = true;
408         }
409     }
410     resultSet->Close();
411     helper->Release();
412     return result;
413 }
414 
QueryParamBoolean(const std::string key,bool defValue)415 bool SmsPersistHelper::QueryParamBoolean(const std::string key, bool defValue)
416 {
417     const int PARAM_SIZE = 64;
418     char paramOutBuff[PARAM_SIZE] = { 0 };
419     std::string defStrValue = defValue ? "1" : "0";
420     std::string paramValue(defStrValue);
421 
422     int retLen = GetParameter(key.c_str(), defStrValue.c_str(), paramOutBuff, PARAM_SIZE);
423     if (retLen > 0) {
424         paramOutBuff[retLen] = '\0';
425         paramValue.assign(paramOutBuff, retLen);
426     }
427 
428     TELEPHONY_LOGI("QueryParamBoolean: %{public}zu : %{public}s", paramValue.size(), paramValue.c_str());
429     if ((paramValue == std::string("1")) || (paramValue == std::string("y")) || (paramValue == std::string("yes")) ||
430         (paramValue == std::string("on")) || (paramValue == std::string("true"))) {
431         return true;
432     } else if ((paramValue == std::string("0")) || (paramValue == std::string("n")) ||
433                (paramValue == std::string("no")) || (paramValue == std::string("off")) ||
434                (paramValue == std::string("false"))) {
435         return false;
436     }
437     return defValue;
438 }
439 
ConvertIntToIndexer(SmsReceiveIndexer & info,const std::shared_ptr<DataShare::DataShareResultSet> & resultSet)440 void SmsPersistHelper::ConvertIntToIndexer(
441     SmsReceiveIndexer &info, const std::shared_ptr<DataShare::DataShareResultSet> &resultSet)
442 {
443     int32_t columnInt;
444     int columnIndex;
445     resultSet->GetColumnIndex(SmsSubsection::FORMAT, columnIndex);
446     if (resultSet->GetInt(columnIndex, columnInt) == 0) {
447         info.SetIsCdma(columnInt == SMS_TYPE_CDMA);
448     }
449 
450     resultSet->GetColumnIndex(SmsSubsection::SMS_SUBSECTION_ID, columnIndex);
451     if (resultSet->GetInt(columnIndex, columnInt) == 0) {
452         info.SetMsgRefId(columnInt);
453     }
454 
455     resultSet->GetColumnIndex(SmsSubsection::SIZE, columnIndex);
456     if (resultSet->GetInt(columnIndex, columnInt) == 0) {
457         info.SetMsgCount(columnInt);
458     }
459 
460     resultSet->GetColumnIndex(SmsSubsection::SUBSECTION_INDEX, columnIndex);
461     if (resultSet->GetInt(columnIndex, columnInt) == 0) {
462         info.SetMsgSeqId(columnInt);
463     }
464 
465     resultSet->GetColumnIndex(SmsSubsection::DEST_PORT, columnIndex);
466     if (resultSet->GetInt(columnIndex, columnInt) == 0) {
467         info.SetDestPort(columnInt);
468     }
469 
470     resultSet->GetColumnIndex(SmsSubsection::ID, columnIndex);
471     if (resultSet->GetInt(columnIndex, columnInt) == 0) {
472         info.SetDataBaseId(columnInt);
473     }
474 }
475 
ConvertStringToIndexer(SmsReceiveIndexer & info,const std::shared_ptr<DataShare::DataShareResultSet> & resultSet)476 void SmsPersistHelper::ConvertStringToIndexer(
477     SmsReceiveIndexer &info, const std::shared_ptr<DataShare::DataShareResultSet> &resultSet)
478 {
479     int columnIndex;
480     std::string columnValue;
481     resultSet->GetColumnIndex(SmsSubsection::RECEIVER_NUMBER, columnIndex);
482     if (resultSet->GetString(columnIndex, columnValue) == 0) {
483         info.SetVisibleAddress(columnValue);
484     }
485     resultSet->GetColumnIndex(SmsSubsection::SENDER_NUMBER, columnIndex);
486     if (resultSet->GetString(columnIndex, columnValue) == 0) {
487         info.SetOriginatingAddress(columnValue);
488     }
489 
490     resultSet->GetColumnIndex(SmsSubsection::START_TIME, columnIndex);
491     if (resultSet->GetString(columnIndex, columnValue) == 0) {
492         info.SetTimestamp(std::stol(columnValue));
493     }
494     resultSet->GetColumnIndex(SmsSubsection::END_TIME, columnIndex);
495     if (resultSet->GetString(columnIndex, columnValue) == 0) {
496         info.SetTimestamp(std::stol(columnValue));
497     }
498 
499     resultSet->GetColumnIndex(SmsSubsection::REW_PUD, columnIndex);
500     if (resultSet->GetString(columnIndex, columnValue) == 0) {
501         info.SetPdu(StringUtils::HexToByteVector(columnValue));
502     }
503 }
504 
ResultSetConvertToIndexer(SmsReceiveIndexer & info,const std::shared_ptr<DataShare::DataShareResultSet> & resultSet)505 void SmsPersistHelper::ResultSetConvertToIndexer(
506     SmsReceiveIndexer &info, const std::shared_ptr<DataShare::DataShareResultSet> &resultSet)
507 {
508     ConvertIntToIndexer(info, resultSet);
509     ConvertStringToIndexer(info, resultSet);
510 }
511 } // namespace Telephony
512 } // namespace OHOS
513