1 /*
2 * Copyright (C) 2023 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 "vcard_manager.h"
17
18 #include "telephony_errors.h"
19 #include "telephony_log_wrapper.h"
20 #include "vcard_constant.h"
21 #include "vcard_encoder.h"
22 #include "vcard_file_utils.h"
23 #include "vcard_rdb_helper.h"
24 #include "vcard_utils.h"
25
26 namespace OHOS {
27 namespace Telephony {
VCardManager()28 VCardManager::VCardManager()
29 {
30 listener_ = std::make_shared<VCardManager::DecodeListener>();
31 }
32
GetContacts()33 std::vector<std::shared_ptr<VCardContact>> &VCardManager::DecodeListener::GetContacts()
34 {
35 return contacts_;
36 }
37
OnStarted()38 void VCardManager::DecodeListener::OnStarted()
39 {
40 contacts_.clear();
41 }
42
OnEnded()43 void VCardManager::DecodeListener::OnEnded()
44 {
45 TELEPHONY_LOGI("OnEnded contact size %{public}d", static_cast<int32_t>(contacts_.size()));
46 VCardDecoder::Close();
47 }
48
OnOneContactStarted()49 void VCardManager::DecodeListener::OnOneContactStarted()
50 {
51 TELEPHONY_LOGI("OnOneContactStarted index %{public}d", static_cast<int32_t>(contacts_.size()));
52 currentContact_ = std::make_shared<VCardContact>();
53 }
54
OnOneContactEnded()55 void VCardManager::DecodeListener::OnOneContactEnded()
56 {
57 TELEPHONY_LOGI("OnOneContactEnded index %{public}d", static_cast<int32_t>(contacts_.size()));
58 contacts_.push_back(currentContact_);
59 currentContact_ = nullptr;
60 }
61
OnRawDataCreated(std::shared_ptr<VCardRawData> rawData)62 void VCardManager::DecodeListener::OnRawDataCreated(std::shared_ptr<VCardRawData> rawData)
63 {
64 if (rawData == nullptr || currentContact_ == nullptr) {
65 return;
66 }
67 int32_t errorCode = TELEPHONY_SUCCESS;
68 currentContact_->AddRawData(rawData, errorCode);
69 }
70
ImportLock( const std::string &path, std::shared_ptr<DataShare::DataShareHelper> dataShareHelper, int32_t accountId)71 int32_t VCardManager::ImportLock(
72 const std::string &path, std::shared_ptr<DataShare::DataShareHelper> dataShareHelper, int32_t accountId)
73 {
74 std::lock_guard<std::mutex> lock(mutex_);
75 if (dataShareHelper == nullptr) {
76 TELEPHONY_LOGE("DataShareHelper is nullptr");
77 return TELEPHONY_ERR_LOCAL_PTR_NULL;
78 }
79 SetDataHelper(dataShareHelper);
80 int32_t errorCode = Import(path, accountId);
81 Release();
82 TELEPHONY_LOGI("ImportLock errorCode : %{public}d finish", errorCode);
83 return errorCode;
84 }
85
Import(const std::string &path, int32_t accountId)86 int32_t VCardManager::Import(const std::string &path, int32_t accountId)
87 {
88 int32_t errorCode = TELEPHONY_SUCCESS;
89 Decode(path, errorCode);
90 if (errorCode != TELEPHONY_SUCCESS) {
91 TELEPHONY_LOGE("Failed to decode");
92 return errorCode;
93 }
94 BatchInsertContactDbAbility(accountId, errorCode);
95 if (errorCode != TELEPHONY_SUCCESS) {
96 TELEPHONY_LOGE("Failed to insert ability");
97 return errorCode;
98 }
99 TELEPHONY_LOGI("Import size %{public}d success", static_cast<int32_t>(listener_->GetContacts().size()));
100 return errorCode;
101 }
102
Decode(const std::string &path, int32_t &errorCode)103 void VCardManager::Decode(const std::string &path, int32_t &errorCode)
104 {
105 std::shared_ptr<VCardDecoder> decoder = VCardDecoder::Create(path, errorCode);
106 if (decoder == nullptr || errorCode != TELEPHONY_SUCCESS) {
107 TELEPHONY_LOGE("Failed to get decoder");
108 return;
109 }
110 decoder->AddVCardDecodeListener(listener_);
111 decoder->Decode(errorCode);
112 if (errorCode != TELEPHONY_SUCCESS) {
113 TELEPHONY_LOGE("Failed to decode");
114 }
115 }
116
InsertContactDbAbility(int32_t accountId, int32_t &errorCode)117 void VCardManager::InsertContactDbAbility(int32_t accountId, int32_t &errorCode)
118 {
119 if (listener_ == nullptr) {
120 errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
121 return;
122 }
123 if (listener_->GetContacts().size() == 0) {
124 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
125 return;
126 }
127 for (std::shared_ptr<VCardContact> contact : listener_->GetContacts()) {
128 auto rawId = InsertRawContact(accountId);
129 if (rawId <= 0) {
130 TELEPHONY_LOGE("Failed to insert raw contact");
131 errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
132 continue;
133 }
134 if (InsertContactData(rawId, contact) == TELEPHONY_ERROR) {
135 TELEPHONY_LOGE("Insert contactData failed");
136 errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
137 }
138 }
139 }
140
BatchInsertContactDbAbility(int32_t accountId, int32_t &errorCode)141 void VCardManager::BatchInsertContactDbAbility(int32_t accountId, int32_t &errorCode)
142 {
143 if (listener_ == nullptr) {
144 errorCode = TELEPHONY_ERR_LOCAL_PTR_NULL;
145 return;
146 }
147 if (listener_->GetContacts().size() < BATCH_INSERT_MAX_SIZE) {
148 TELEPHONY_LOGI("contactData < BATCH_INSERT_MAX_SIZE");
149 InsertContactDbAbility(accountId, errorCode);
150 return;
151 }
152 if (listener_->GetContacts().size() == 0) {
153 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
154 return;
155 }
156 std::vector<std::vector<std::shared_ptr<VCardContact>>> splitList =
157 SplitContactsVector(listener_->GetContacts(), BATCH_INSERT_MAX_SIZE);
158 TELEPHONY_LOGI(
159 "contactData > BATCH_INSERT_MAX_SIZE, split List size %{public}d", static_cast<int32_t>(splitList.size()));
160 for (std::vector<std::shared_ptr<VCardContact>> list : splitList) {
161 TELEPHONY_LOGI("List size %{public}d", static_cast<int32_t>(list.size()));
162 std::vector<int32_t> rawIds;
163 BatchInsertRawContact(accountId, list.size(), rawIds, errorCode);
164 if (errorCode == TELEPHONY_ERROR) {
165 TELEPHONY_LOGE("Failed to batch insert raw contact");
166 continue;
167 }
168 BatchInsertContactData(rawIds, list, errorCode);
169 if (errorCode == TELEPHONY_ERROR) {
170 TELEPHONY_LOGE("Failed to batch insert contactData");
171 continue;
172 }
173 }
174 }
175
BatchInsertRawContact( int32_t accountId, uint32_t size, std::vector<int32_t> &rawIds, int32_t &errorCode)176 void VCardManager::BatchInsertRawContact(
177 int32_t accountId, uint32_t size, std::vector<int32_t> &rawIds, int32_t &errorCode)
178 {
179 int32_t rawContactMaxId = VCardRdbHelper::GetInstance().QueryRawContactMaxId();
180 std::vector<DataShare::DataShareValuesBucket> rawContactValues;
181 for (uint32_t i = 0; i < size; i++) {
182 OHOS::DataShare::DataShareValuesBucket valuesBucket;
183 valuesBucket.Put(RawContact::ACCOUNT_ID, GetAccountId());
184 if (IsContactsIdExit(accountId)) {
185 valuesBucket.Put(RawContact::CONTACT_ID, accountId);
186 }
187 rawContactValues.push_back(valuesBucket);
188 rawIds.push_back(rawContactMaxId + i + 1);
189 }
190 VCardRdbHelper::GetInstance().BatchInsertRawContact(rawContactValues);
191 }
192
BatchInsertContactData( std::vector<int32_t> &rawIds, const std::vector<std::shared_ptr<VCardContact>> &contactList, int32_t &errorCode)193 void VCardManager::BatchInsertContactData(
194 std::vector<int32_t> &rawIds, const std::vector<std::shared_ptr<VCardContact>> &contactList, int32_t &errorCode)
195 {
196 std::vector<DataShare::DataShareValuesBucket> contactDataValues;
197 for (size_t i = 0; i < rawIds.size(); i++) {
198 int32_t rawId = rawIds[i];
199 TELEPHONY_LOGI("rawId %{public}d", rawId);
200 std::shared_ptr<VCardContact> contact = contactList[i];
201 if (contact == nullptr) {
202 errorCode = TELEPHONY_ERROR;
203 TELEPHONY_LOGE("contact is nullptr");
204 continue;
205 }
206 contact->BuildContactData(rawId, contactDataValues);
207 if (contactDataValues.empty()) {
208 TELEPHONY_LOGE("no contactData insert");
209 errorCode = TELEPHONY_ERROR;
210 }
211 }
212 int ret = VCardRdbHelper::GetInstance().BatchInsertContactData(contactDataValues);
213 if (ret == TELEPHONY_ERROR) {
214 TELEPHONY_LOGE("batch insert contactDatat failed");
215 errorCode = TELEPHONY_ERROR;
216 }
217 }
218
SplitContactsVector( std::vector<std::shared_ptr<VCardContact>> list, size_t step)219 std::vector<std::vector<std::shared_ptr<VCardContact>>> VCardManager::SplitContactsVector(
220 std::vector<std::shared_ptr<VCardContact>> list, size_t step)
221 {
222 std::vector<std::vector<std::shared_ptr<VCardContact>>> result;
223 if (step >= list.size()) {
224 result.push_back(list);
225 } else {
226 std::vector<std::shared_ptr<VCardContact>>::iterator curPtr = list.begin();
227 std::vector<std::shared_ptr<VCardContact>>::iterator endPtr = list.end();
228 std::vector<std::shared_ptr<VCardContact>>::iterator end;
229 while (curPtr < endPtr) {
230 end = static_cast<size_t>(endPtr - curPtr) > step ? (step + curPtr) : endPtr;
231 step = static_cast<size_t>(endPtr - curPtr) > step ? step : static_cast<size_t>(endPtr - curPtr);
232 result.push_back(std::vector<std::shared_ptr<VCardContact>>(curPtr, end));
233 curPtr += step;
234 }
235 }
236 return result;
237 }
238
InsertRawContact(int32_t accountId)239 int32_t VCardManager::InsertRawContact(int32_t accountId)
240 {
241 OHOS::DataShare::DataShareValuesBucket ValuesBucket;
242 ValuesBucket.Put(RawContact::ACCOUNT_ID, GetAccountId());
243 if (IsContactsIdExit(accountId)) {
244 ValuesBucket.Put(RawContact::CONTACT_ID, accountId);
245 }
246 return VCardRdbHelper::GetInstance().InsertRawContact(ValuesBucket);
247 }
248
IsContactsIdExit(int32_t accountId)249 bool VCardManager::IsContactsIdExit(int32_t accountId)
250 {
251 std::vector<std::string> columns;
252 OHOS::DataShare::DataSharePredicates predicates;
253 predicates.EqualTo(Contact::ID, std::to_string(accountId));
254 auto resultSet = VCardRdbHelper::GetInstance().QueryContact(columns, predicates);
255 if (resultSet == nullptr) {
256 return false;
257 }
258 bool result = (resultSet->GoToFirstRow() == DataShare::E_OK);
259 resultSet->Close();
260 return result;
261 }
262
GetAccountId()263 int32_t VCardManager::GetAccountId()
264 {
265 std::vector<std::string> columns;
266 OHOS::DataShare::DataSharePredicates predicates;
267 predicates.EqualTo(Account::ACCOUNT_TYPE, "com.ohos.contacts");
268 auto resultSet = VCardRdbHelper::GetInstance().QueryAccount(columns, predicates);
269 if (resultSet == nullptr) {
270 return -1;
271 }
272 resultSet->GoToFirstRow();
273 int32_t index = 0;
274 int32_t id = 0;
275 resultSet->GetColumnIndex(Account::ID, index);
276 resultSet->GetInt(index, id);
277 resultSet->Close();
278 return id;
279 }
280
IsAccountIdExit(int32_t accountId)281 bool VCardManager::IsAccountIdExit(int32_t accountId)
282 {
283 std::vector<std::string> columns;
284 OHOS::DataShare::DataSharePredicates predicates;
285 predicates.EqualTo(Account::ID, std::to_string(accountId));
286 auto resultSet = VCardRdbHelper::GetInstance().QueryAccount(columns, predicates);
287 if (resultSet == nullptr) {
288 return false;
289 }
290 bool result = (resultSet->GoToFirstRow() == DataShare::E_OK);
291 resultSet->Close();
292 return result;
293 }
294
InsertContactData(int32_t rawId, std::shared_ptr<VCardContact> contact)295 int32_t VCardManager::InsertContactData(int32_t rawId, std::shared_ptr<VCardContact> contact)
296 {
297 if (contact == nullptr) {
298 return TELEPHONY_ERROR;
299 }
300 std::vector<DataShare::DataShareValuesBucket> contactDataValues;
301 contact->BuildContactData(rawId, contactDataValues);
302 if (contactDataValues.empty()) {
303 TELEPHONY_LOGI("no data insert");
304 return TELEPHONY_ERROR;
305 }
306 int ret = VCardRdbHelper::GetInstance().InsertContactData(contactDataValues);
307 if (ret == TELEPHONY_ERROR) {
308 TELEPHONY_LOGE("insert failed");
309 return TELEPHONY_ERROR;
310 }
311 return TELEPHONY_SUCCESS;
312 }
313
ParameterTypeAndCharsetCheck(int32_t cardType, std::string charset, int32_t &errorCode)314 bool VCardManager::ParameterTypeAndCharsetCheck(int32_t cardType, std::string charset, int32_t &errorCode)
315 {
316 if (cardType < VERSION_21_NUM || cardType > VERSION_40_NUM) {
317 errorCode = TELEPHONY_ERR_ARGUMENT_INVALID;
318 return false;
319 }
320 if (!charset.empty() && !VCardUtils::EqualsIgnoreCase(DEFAULT_CHARSET, charset)) {
321 errorCode = TELEPHONY_ERR_ARGUMENT_INVALID;
322 return false;
323 }
324 errorCode = TELEPHONY_SUCCESS;
325 return true;
326 }
327
ExportLock(std::string &path, std::shared_ptr<DataShare::DataShareHelper> dataShareHelper, const DataShare::DataSharePredicates &predicates, int32_t cardType, const std::string &charset)328 int32_t VCardManager::ExportLock(std::string &path, std::shared_ptr<DataShare::DataShareHelper> dataShareHelper,
329 const DataShare::DataSharePredicates &predicates, int32_t cardType, const std::string &charset)
330 {
331 std::lock_guard<std::mutex> lock(mutex_);
332 if (dataShareHelper == nullptr) {
333 TELEPHONY_LOGE("DataShareHelper is nullptr");
334 return TELEPHONY_ERR_LOCAL_PTR_NULL;
335 }
336 SetDataHelper(dataShareHelper);
337 int32_t errorCode = Export(path, predicates, cardType, charset);
338 Release();
339 TELEPHONY_LOGI("ExportLock errorCode : %{public}d finish", errorCode);
340 return errorCode;
341 }
342
Export( std::string &path, const DataShare::DataSharePredicates &predicates, int32_t cardType, const std::string &charset)343 int32_t VCardManager::Export(
344 std::string &path, const DataShare::DataSharePredicates &predicates, int32_t cardType, const std::string &charset)
345 {
346 int32_t errorCode = TELEPHONY_SUCCESS;
347 if (!ParameterTypeAndCharsetCheck(cardType, charset, errorCode)) {
348 return errorCode;
349 }
350 std::vector<std::string> columns;
351 auto resultSet = VCardRdbHelper::GetInstance().QueryContact(columns, predicates);
352 if (resultSet == nullptr) {
353 TELEPHONY_LOGE("QueryContact failed");
354 return TELEPHONY_ERR_LOCAL_PTR_NULL;
355 }
356 int32_t resultSetNum = resultSet->GoToFirstRow();
357 std::string result = "";
358 VCardEncoder encoder { cardType, charset };
359 while (resultSetNum == 0 && errorCode == TELEPHONY_SUCCESS) {
360 result += encoder.ContructVCard(resultSet, errorCode);
361 resultSetNum = resultSet->GoToNextRow();
362 }
363 if (errorCode != TELEPHONY_SUCCESS) {
364 TELEPHONY_LOGE("Export data failed");
365 resultSet->Close();
366 return errorCode;
367 }
368 if (path.empty()) {
369 std::string fileName = VCardUtils::CreateFileName();
370 path = VCARD_EXPORT_FILE_PATH + fileName;
371 } else {
372 path = path + VCardUtils::CreateFileName();
373 }
374 if (!result.empty()) {
375 VCardUtils::SaveFile(result, path);
376 resultSet->Close();
377 } else {
378 resultSet->Close();
379 return TELEPHONY_ERROR;
380 }
381 return TELEPHONY_SUCCESS;
382 }
383
ExportToStr( std::string &str, const DataShare::DataSharePredicates &predicates, int32_t cardType, const std::string &charset)384 int32_t VCardManager::ExportToStr(
385 std::string &str, const DataShare::DataSharePredicates &predicates, int32_t cardType, const std::string &charset)
386 {
387 std::vector<std::string> columns;
388 auto resultSet = VCardRdbHelper::GetInstance().QueryContact(columns, predicates);
389 if (resultSet == nullptr) {
390 TELEPHONY_LOGE("QueryContact failed");
391 return TELEPHONY_ERR_LOCAL_PTR_NULL;
392 }
393 int32_t resultSetNum = resultSet->GoToFirstRow();
394 VCardEncoder encoder { cardType, charset };
395 int32_t errorCode = TELEPHONY_SUCCESS;
396 str = "";
397 while (resultSetNum == 0 && errorCode == TELEPHONY_SUCCESS) {
398 str += encoder.ContructVCard(resultSet, errorCode);
399 resultSetNum = resultSet->GoToNextRow();
400 }
401 if (errorCode != TELEPHONY_SUCCESS) {
402 TELEPHONY_LOGE("Export data failed");
403 resultSet->Close();
404 return errorCode;
405 }
406 resultSet->Close();
407 return TELEPHONY_SUCCESS;
408 }
409
SetDataHelper(std::shared_ptr<DataShare::DataShareHelper> dataShareHelper)410 void VCardManager::SetDataHelper(std::shared_ptr<DataShare::DataShareHelper> dataShareHelper)
411 {
412 VCardRdbHelper::GetInstance().SetDataHelper(dataShareHelper);
413 }
414
GetInstance()415 VCardManager &VCardManager::GetInstance()
416 {
417 static VCardManager instance;
418 return instance;
419 }
420
Release()421 void VCardManager::Release()
422 {
423 VCardRdbHelper::GetInstance().Release();
424 if (listener_ != nullptr) {
425 listener_->GetContacts().clear();
426 }
427 }
428 } // namespace Telephony
429 } // namespace OHOS
430