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