• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "pbap_pse_vcard_manager.h"
17 #include <algorithm>
18 #include <cstring>
19 #include <exception>
20 #include <functional>
21 #include <set>
22 #include <sstream>
23 #include "../obex/obex_utils.h"
24 #include "data_access.h"
25 #include "log.h"
26 #include "pbap_pse_def.h"
27 #include "stub/vcard_util.h"
28 
29 using namespace stub;
30 
31 namespace OHOS {
32 namespace bluetooth {
33 class PbapPseVcardDataAccess {
34 public:
35     struct SetPullvCardEntryParam {
36         std::u16string folderId = u"";
37         std::u16string entryId = u"";
38         uint32_t supportedFeatures = 0;
39     };
SetPullvCardListingSize(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,PbapPseVcardManager::PhoneBookResult & result,const PbapPseAppParams & pbapAppParams)40     static void SetPullvCardListingSize(const std::unique_ptr<DataAccess> &dataAccess, const std::u16string &folderId,
41         PbapPseVcardManager::PhoneBookResult &result, const PbapPseAppParams &pbapAppParams)
42     {
43         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
44         std::string select = "select count(distinct vcard_uid) from vcard_view t where folder_id = ? ";
45         select += GetVcardSelectorWhere(pbapAppParams);
46         if (pbapAppParams.GetSearchValueUtf8().size() > 0) {
47             select += GetVcardSearchPropertyWhere(pbapAppParams);
48         }
49         auto stmt = dataAccess->CreateStatement(select);
50         if (!stmt) {
51             result.rspCode_ = ObexRspCode::INTERNAL_SERVER_ERROR;
52             return;
53         }
54         int pIndex = 1;
55         stmt->SetParam16String(pIndex++, folderId);
56         if (pbapAppParams.GetSearchValueUtf8().size() > 0) {
57             const uint8_t *data = pbapAppParams.GetSearchValueUtf8().data();
58             std::string searchValue(data, data + pbapAppParams.GetSearchValueUtf8().size());
59             stmt->SetParamString(pIndex++, searchValue);
60         }
61         auto dataResult = stmt->Query();
62         int count = 0;
63         if (dataResult->Next()) {
64             count = dataResult->GetInt(0);
65         }
66         result.phoneBookSize_ = count;
67     }
68 
SetPullvCardListing(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,PbapPseVcardManager::PhoneBookResult & result,const PbapPseAppParams & pbapAppParams)69     static void SetPullvCardListing(const std::unique_ptr<DataAccess> &dataAccess, const std::u16string &folderId,
70         PbapPseVcardManager::PhoneBookResult &result, const PbapPseAppParams &pbapAppParams)
71     {
72         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
73         auto vcardListing = SelectPullvCardListing(dataAccess, folderId, pbapAppParams);
74         if (vcardListing.size() == 0) {
75             PBAP_PSE_LOG_DEBUG("SetPullvCardListing size is 0");
76             return;
77         }
78         std::stringstream ss;
79         ss << "<?xml version=\"1.0\"?>";
80         ss << "<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">";
81         ss << "<vCard-listing version=\"1.0\">";
82         for (auto &item : vcardListing) {
83             ss << "<card handle=\"";
84             ss << std::hex << item.first;
85             ss << ".vcf\" name=\"";
86             ss << NameEncodeForXml(item.second);
87             ss << "\"/>";
88         }
89         ss << "</vCard-listing>";
90         std::string xml = ss.str();
91         result.result_.insert(result.result_.end(), xml.begin(), xml.end());
92     }
93 
NameEncodeForXml(const std::string & name)94     static std::string NameEncodeForXml(const std::string &name)
95     {
96         std::stringstream ss;
97         for (char c : name) {
98             switch (c) {
99                 case '<':
100                     ss << "&lt;";
101                     break;
102                 case '>':
103                     ss << "&gt;";
104                     break;
105                 case '\"':
106                     ss << "&quot;";
107                     break;
108                 case '\'':
109                     ss << "&#039;";
110                     break;
111                 case '&':
112                     ss << "&amp;";
113                     break;
114 
115                 default:
116                     ss << c;
117                     break;
118             }
119         }
120         return ss.str();
121     }
122 
SetNewMissedCalls(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,PbapPseVcardManager::PhoneBookResult & result)123     static void SetNewMissedCalls(const std::unique_ptr<DataAccess> &dataAccess, const std::u16string &folderId,
124         PbapPseVcardManager::PhoneBookResult &result)
125     {
126         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
127         std::string select =
128             "select count(vcard_uid) from vcard where vcard_folder_id = ? and vcard_new_missed_call = 1";
129         auto stmt = dataAccess->CreateStatement(select);
130         if (!stmt) {
131             result.rspCode_ = ObexRspCode::INTERNAL_SERVER_ERROR;
132             return;
133         }
134         stmt->SetParam16String(1, folderId);
135         auto dataResult = stmt->Query();
136         int count = 0;
137         if (dataResult->Next()) {
138             count = dataResult->GetInt(0);
139         }
140         result.newMissedCallsSize_ = count;
141     }
142 
SetPhoneBookSize(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,PbapPseVcardManager::PhoneBookResult & result,const PbapPseAppParams & pbapAppParams)143     static void SetPhoneBookSize(const std::unique_ptr<DataAccess> &dataAccess, const std::u16string &folderId,
144         PbapPseVcardManager::PhoneBookResult &result, const PbapPseAppParams &pbapAppParams)
145     {
146         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
147         std::string select = "select count(distinct vcard_uid) from vcard_view t where folder_id = ? ";
148         select += GetVcardSelectorWhere(pbapAppParams);
149 
150         auto stmt = dataAccess->CreateStatement(select);
151         if (!stmt) {
152             result.rspCode_ = ObexRspCode::INTERNAL_SERVER_ERROR;
153             return;
154         }
155         stmt->SetParam16String(1, folderId);
156         auto dataResult = stmt->Query();
157         int count = 0;
158         if (dataResult->Next()) {
159             count = dataResult->GetInt(0);
160         }
161         result.phoneBookSize_ = count;
162     }
163 
SetPhoneBook(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,PbapPseVcardManager::PhoneBookResult & result,const PbapPseAppParams & pbapAppParams,const uint32_t & supportedFeatures)164     static void SetPhoneBook(const std::unique_ptr<DataAccess> &dataAccess, const std::u16string &folderId,
165         PbapPseVcardManager::PhoneBookResult &result, const PbapPseAppParams &pbapAppParams,
166         const uint32_t &supportedFeatures)
167     {
168         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
169         auto vcardUids = SelectPhoneBookVcardUids(dataAccess, folderId, pbapAppParams);
170 
171         // 5.1.4.2 Format :vCard2.1, vCard3.0
172         bool isOutVcard21 = true;  // The format vCard 2.1 shall be the default format if this header is not specified.
173         if (pbapAppParams.GetFormat()) {
174             // 0x00 = 2.1 0x01 = 3.0
175             isOutVcard21 = (*pbapAppParams.GetFormat() == 0x00);
176         }
177         // 5.1.4.11 ResetNewMissedCalls :not support in this impl
178 
179         // 5.1.4.1 PropertySelector :PropertyMask (64-bit value)
180         std::vector<std::string> includeProperties;
181         // Mandatory properties for vCard 2.1 are VERSION ,N and TEL.
182         // Mandatory properties for vCard 3.0 are VERSION, N, FN and TEL.
183         std::vector<std::string> mandatoryProperties;
184         mandatoryProperties.push_back("VERSION");
185         mandatoryProperties.push_back("N");
186         if (!isOutVcard21) {
187             mandatoryProperties.push_back("FN");
188         }
189         mandatoryProperties.push_back("TEL");
190         if (pbapAppParams.GetPropertySelector()) {
191             includeProperties = PbapPseVcardManager::GetIncludeProperties(*pbapAppParams.GetPropertySelector());
192             if (includeProperties.size() > 0) {
193                 includeProperties.insert(
194                     includeProperties.end(), mandatoryProperties.begin(), mandatoryProperties.end());
195             }
196         }
197         const VCardVersion outVer = isOutVcard21 ? VCardVersion::VER_2_1 : VCardVersion::VER_3_0;
198 
199         std::function<void(VCard &)> fun = [&mandatoryProperties, &result, &outVer](VCard &vcard) {
200             // 5.1.4.1 all Mandatory here means that the PSE shall always return the properties VERSION, N and TEL
201             // vCard 2.1 or VERSION, N, FN and TEL for a vCard 3.0.
202             AddMissProperties(vcard, mandatoryProperties);
203 
204             if (vcard.Properties().size() > 0) {
205                 std::vector<uint8_t> vcardBytes = VCardUtil::Build(vcard, outVer);
206                 result.result_.insert(result.result_.end(), vcardBytes.begin(), vcardBytes.end());
207             }
208         };
209         SelectPhoneBookVcardList(
210             dataAccess, vcardUids, GetPropertySelectorWhere(includeProperties), supportedFeatures, fun);
211     }
212 
SetPullvCardEntry(const std::unique_ptr<DataAccess> & dataAccess,const SetPullvCardEntryParam & param,const PbapPseAppParams & pbapAppParams,PbapPseVcardManager::PhoneBookResult & result)213     static void SetPullvCardEntry(
214             const std::unique_ptr<DataAccess> &dataAccess,
215             const SetPullvCardEntryParam& param,
216             const PbapPseAppParams &pbapAppParams, PbapPseVcardManager::PhoneBookResult &result)
217     {
218         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
219         auto vcardUids = SelectVcardEntryUid(dataAccess, param.folderId, param.entryId, pbapAppParams);
220         if (vcardUids.size() == 0) {
221             PBAP_PSE_LOG_DEBUG("SelectPhoneBookVcardUids size = 0");
222             result.rspCode_ = ObexRspCode::NOT_FOUND;
223             return;
224         }
225         // 5.1.4.2 Format :vCard2.1, vCard3.0
226         bool isOutVcard21 = true;  // The format vCard 2.1 shall be the default format if this header is not specified.
227         if (pbapAppParams.GetFormat()) {
228             // 0x00 = 2.1 0x01 = 3.0
229             isOutVcard21 = (*pbapAppParams.GetFormat() == 0x00);
230         }
231 
232         // 5.1.4.1 PropertySelector :PropertyMask (64-bit value)
233         std::vector<std::string> includeProperties;
234         // Mandatory properties for vCard 2.1 are VERSION ,N and TEL.
235         // Mandatory properties for vCard 3.0 are VERSION, N, FN and TEL.
236         std::vector<std::string> mandatoryProperties;
237         mandatoryProperties.push_back("VERSION");
238         mandatoryProperties.push_back("N");
239         if (!isOutVcard21) {
240             mandatoryProperties.push_back("FN");
241         }
242         mandatoryProperties.push_back("TEL");
243         if (pbapAppParams.GetPropertySelector()) {
244             includeProperties = PbapPseVcardManager::GetIncludeProperties(*pbapAppParams.GetPropertySelector());
245             if (includeProperties.size() > 0) {
246                 includeProperties.insert(
247                     includeProperties.end(), mandatoryProperties.begin(), mandatoryProperties.end());
248             }
249         }
250         const VCardVersion outVer = isOutVcard21 ? VCardVersion::VER_2_1 : VCardVersion::VER_3_0;
251         std::function<void(VCard &)> fun = [&mandatoryProperties, &result, &outVer](VCard &vcard) {
252             // 5.1.4.1 all Mandatory here means that the PSE shall always return the properties VERSION, N and TEL
253             // vCard 2.1 or VERSION, N, FN and TEL for a vCard 3.0.
254             AddMissProperties(vcard, mandatoryProperties);
255 
256             if (vcard.Properties().size() > 0) {
257                 std::vector<uint8_t> vcardBytes = VCardUtil::Build(vcard, outVer);
258                 result.result_.insert(result.result_.end(), vcardBytes.begin(), vcardBytes.end());
259             }
260         };
261         SelectPhoneBookVcardList(
262             dataAccess, vcardUids, GetPropertySelectorWhere(includeProperties), param.supportedFeatures, fun);
263     }
264 
SetDbId(const std::unique_ptr<DataAccess> & dataAccess,PbapPseVcardManager::PhoneBookResult & result)265     static void SetDbId(const std::unique_ptr<DataAccess> &dataAccess, PbapPseVcardManager::PhoneBookResult &result)
266     {
267         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
268         std::string select = "select db_id from vcard_db_id limit 1";
269 
270         auto stmt = dataAccess->CreateStatement(select);
271         if (!stmt) {
272             result.rspCode_ = ObexRspCode::INTERNAL_SERVER_ERROR;
273             return;
274         }
275 
276         auto dataResult = stmt->Query();
277         if (dataResult->Next()) {
278             std::string dbId = dataResult->GetString(0);
279             if (dbId.size() > 0) {
280                 std::vector<uint8_t> tmpPv(dbId.c_str(), dbId.c_str() + dbId.size());
281                 result.databaseIdentifier_ = tmpPv;
282                 FitListToSize(result.databaseIdentifier_, 0x10);
283             }
284         }
285     }
286 
SetFolderVersion(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,PbapPseVcardManager::PhoneBookResult & result)287     static void SetFolderVersion(const std::unique_ptr<DataAccess> &dataAccess, const std::u16string &folderId,
288         PbapPseVcardManager::PhoneBookResult &result)
289     {
290         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
291         std::string select =
292             "select folder_id, primary_folder_version, secondary_folder_version from vcard_folder where folder_id = ?";
293 
294         auto stmt = dataAccess->CreateStatement(select);
295         if (!stmt) {
296             result.rspCode_ = ObexRspCode::INTERNAL_SERVER_ERROR;
297             return;
298         }
299         stmt->SetParam16String(1, folderId);
300         auto dataResult = stmt->Query();
301         if (dataResult->Next()) {
302             std::string pv = dataResult->GetString(0x01);
303             if (pv.size() > 0) {
304                 std::vector<uint8_t> tmpPv(pv.c_str(), pv.c_str() + pv.size());
305                 result.primaryFolderVersion_ = tmpPv;
306                 FitListToSize(result.primaryFolderVersion_, 0x10);
307             }
308             std::string sv = dataResult->GetString(0x02);
309             if (sv.size() > 0) {
310                 std::vector<uint8_t> tmpSv(sv.c_str(), sv.c_str() + sv.size());
311                 result.secondaryFolderVersion_ = tmpSv;
312                 FitListToSize(result.secondaryFolderVersion_, 0x10);
313             }
314         }
315     }
316 
SetCommonResult(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,PbapPseVcardManager::PhoneBookResult & result,const uint32_t & supportedFeatures)317     static void SetCommonResult(const std::unique_ptr<DataAccess> &dataAccess, const std::u16string &folderId,
318         PbapPseVcardManager::PhoneBookResult &result, const uint32_t &supportedFeatures)
319     {
320         if (folderId == u"mch") {
321             // 5.1.4.6 NewMissedCalls
322             // This application parameter shall be used in the response when the phone book object is mch. It shall
323             // indicate the number of undismissed missed calls on the PSE at the point of the request. This value is the
324             // same for mch and cch objects.
325             result.newMissedCalls_ = true;
326             SetNewMissedCalls(dataAccess, folderId, result);
327             if (result.rspCode_ != ObexRspCode::SUCCESS) {
328                 return;
329             }
330         }
331         if (PbapPseVcardManager::IsSupportedDbVer(supportedFeatures)) {
332             SetFolderVersion(dataAccess, folderId, result);
333             if (result.rspCode_ != ObexRspCode::SUCCESS) {
334                 return;
335             }
336         }
337         if (PbapPseVcardManager::IsSupportedDbVer(supportedFeatures)) {
338             SetDbId(dataAccess, result);
339             if (result.rspCode_ != ObexRspCode::SUCCESS) {
340                 return;
341             }
342         }
343     }
344 
FitListToSize(std::vector<uint8_t> & list,size_t size)345     static void FitListToSize(std::vector<uint8_t> &list, size_t size)
346     {
347         if (list.size() == size) {
348             return;
349         }
350         if (list.size() > size) {
351             while (list.size() > size) {
352                 list.pop_back();
353             }
354         } else {
355             size_t fitSize = size - list.size();
356             list.insert(list.begin(), fitSize, 0x00);
357         }
358     }
359 
360 private:
GetSelectPullvCardListingSql(const PbapPseAppParams & pbapAppParams)361     static std::string GetSelectPullvCardListingSql(const PbapPseAppParams &pbapAppParams)
362     {
363         std::string select = "select distinct t.vcard_handle_id, t.property_value as name from vcard_view t ";
364         std::string where = " where t.folder_id = ? and t.property_id ='N' ";
365         where += GetVcardSelectorWhere(pbapAppParams);
366         if (pbapAppParams.GetSearchValueUtf8().size() > 0) {
367             where += GetVcardSearchPropertyWhere(pbapAppParams);
368         }
369         // If this application parameter is not specified, the default order is “Indexed”.
370         std::string orderBy = " order by t.vcard_handle_id asc ";
371         // 5.3.4.1 Order : Alphabetical, Indexed, Phonetical
372         if (pbapAppParams.GetOrder()) {
373             switch (*pbapAppParams.GetOrder()) {
374                 case 0x01:  // alphanumeric
375                     orderBy = " order by t.property_value asc, t.vcard_handle_id asc";
376                     break;
377                 case 0x02:  // phonetic
378                     orderBy = " order by (select property_value from vcard_view where vcard_uid = t.vcard_uid and "
379                               "property_id = "
380                               "'SOUND' limit 1) is null asc ";
381                     orderBy +=
382                         ", (select property_value from vcard_view where vcard_uid = t.vcard_uid and property_id = "
383                         "'SOUND' limit 1) asc ";
384                     orderBy += ", t.vcard_handle_id asc ";
385                     break;
386                 default:
387                     // default indexed
388                     break;
389             }
390         }
391         select += where;
392         select += orderBy;
393         select += " limit ? offset ?";
394         return select;
395     }
396 
SelectPullvCardListing(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,const PbapPseAppParams & pbapAppParams)397     static std::vector<std::pair<int, std::string>> SelectPullvCardListing(
398         const std::unique_ptr<DataAccess> &dataAccess, const std::u16string &folderId,
399         const PbapPseAppParams &pbapAppParams)
400     {
401         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
402         std::string select = GetSelectPullvCardListingSql(pbapAppParams);
403         // 5.1.4.3 MaxListCount  default max is 65535
404         uint16_t maxListCount = 0xFFFF;
405         if (pbapAppParams.GetMaxListCount()) {
406             maxListCount = *pbapAppParams.GetMaxListCount();
407         }
408         // 5.1.4.4 ListStartOffset
409         uint16_t listStartOffset = 0;  // The offset shall be 0 if this header is not specified
410         if (pbapAppParams.GetListStartOffset()) {
411             listStartOffset = *pbapAppParams.GetListStartOffset();
412         }
413         std::vector<std::pair<int, std::string>> vcardUids;
414         auto stmtVcardIds = dataAccess->CreateStatement(select);
415         if (!stmtVcardIds) {
416             return vcardUids;
417         }
418         int paramIndex = 1;
419         stmtVcardIds->SetParam16String(paramIndex++, folderId);
420         if (pbapAppParams.GetSearchValueUtf8().size() > 0) {
421             const uint8_t *data = pbapAppParams.GetSearchValueUtf8().data();
422             std::string searchValue(data, data + pbapAppParams.GetSearchValueUtf8().size());
423             stmtVcardIds->SetParamString(paramIndex++, searchValue);
424         }
425         stmtVcardIds->SetParamInt(paramIndex++, maxListCount);
426         stmtVcardIds->SetParamInt(paramIndex++, listStartOffset);
427         auto dataResult = stmtVcardIds->Query();
428         while (dataResult->Next()) {
429             int index = 0;
430             int vcardUid = dataResult->GetInt(index++);
431             std::string name = dataResult->GetString(index++);
432             vcardUids.push_back(std::make_pair(vcardUid, name));
433         }
434         return vcardUids;
435     }
436 
SelectPhoneBookVcardUids(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,const PbapPseAppParams & pbapAppParams)437     static std::vector<std::pair<int64_t, int>> SelectPhoneBookVcardUids(
438         const std::unique_ptr<DataAccess> &dataAccess, const std::u16string &folderId,
439         const PbapPseAppParams &pbapAppParams)
440     {
441         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
442         std::string select = "select distinct vcard_uid, vcard_version from vcard_view t where folder_id = ? ";
443         select += GetVcardSelectorWhere(pbapAppParams);
444         select += " order by vcard_handle_id asc";
445         select += " limit ? offset ?";
446 
447         // 5.1.4.3 MaxListCount  default max is 65535
448         uint16_t maxListCount = 0xFFFF;
449         if (pbapAppParams.GetMaxListCount()) {
450             maxListCount = *pbapAppParams.GetMaxListCount();
451         }
452         // 5.1.4.4 ListStartOffset
453         uint16_t listStartOffset = 0;  // The offset shall be 0 if this header is not specified
454         if (pbapAppParams.GetListStartOffset()) {
455             listStartOffset = *pbapAppParams.GetListStartOffset();
456         }
457         std::vector<std::pair<int64_t, int>> vcardUids;
458         auto stmtVcardIds = dataAccess->CreateStatement(select);
459         if (!stmtVcardIds) {
460             return vcardUids;
461         }
462         int pIndex = 1;
463         stmtVcardIds->SetParam16String(pIndex++, folderId);
464         stmtVcardIds->SetParamInt(pIndex++, maxListCount);
465         stmtVcardIds->SetParamInt(pIndex++, listStartOffset);
466         auto dataResult = stmtVcardIds->Query();
467         while (dataResult->Next()) {
468             int index = 0;
469             int64_t vcardUid = dataResult->GetInt64(index++);
470             int vcardVer = dataResult->GetInt(index++);
471             vcardUids.push_back(std::make_pair(vcardUid, vcardVer));
472         }
473         return vcardUids;
474     }
475 
GetSelectPhoneBookVcardListSql(const std::string & whereSql)476     static std::string GetSelectPhoneBookVcardListSql(const std::string &whereSql)
477     {
478         std::string sql = "select"
479                           "    vcard_handle_id"
480                           "  , vcard_version"
481                           "  , property_group"
482                           "  , property_id"
483                           "  , property_details"
484                           "  , property_value "
485                           "from"
486                           "  vcard_view t "
487                           "where"
488                           "  vcard_uid = ? " +
489                           whereSql +
490                           "order by"
491                           "  profile_property_order is null asc"
492                           "  , profile_property_order asc";
493         return sql;
494     }
495 
IsNeedInclude(const std::string & propertyId,const uint32_t & supportedFeatures)496     static bool IsNeedInclude(const std::string &propertyId, const uint32_t &supportedFeatures)
497     {
498         if (propertyId == "X-BT-UCI" && !PbapPseVcardManager::IsSupportedXBtUCI(supportedFeatures)) {
499             return false;
500         }
501         if (propertyId == "X-BT-UID" && !PbapPseVcardManager::IsSupportedXBtUID(supportedFeatures)) {
502             return false;
503         }
504         return true;
505     }
506 
SelectPhoneBookVcardList(const std::unique_ptr<DataAccess> & dataAccess,const std::vector<std::pair<int64_t,int>> & vcardUids,const std::string whereSql,const uint32_t & supportedFeatures,const std::function<void (VCard &)> & handleFun)507     static bool SelectPhoneBookVcardList(const std::unique_ptr<DataAccess> &dataAccess,
508         const std::vector<std::pair<int64_t, int>> &vcardUids, const std::string whereSql,
509         const uint32_t &supportedFeatures, const std::function<void(VCard &)> &handleFun)
510     {
511         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
512         std::string select = GetSelectPhoneBookVcardListSql(whereSql);
513         auto stmt = dataAccess->CreateStatement(select);
514         if (!stmt) {
515             PBAP_PSE_LOG_ERROR("Error in CreateStatement");
516             return false;
517         }
518         for (size_t i = 0; i < vcardUids.size(); i++) {
519             auto pair = vcardUids.at(i);
520             int64_t vcardUid = pair.first;
521             int vcardVer = pair.second;
522             stmt->ClearParams();
523             stmt->SetParamInt64(1, vcardUid);
524             bool isCurVcard21 = (vcardVer == 0);
525             auto dataResult = stmt->Query();
526             VCard vcard;
527             const VCardVersion curVer = isCurVcard21 ? VCardVersion::VER_2_1 : VCardVersion::VER_3_0;
528             while (dataResult->Next()) {
529                 int index = 0;
530                 int vcardHandleId = dataResult->GetInt(index++);
531                 int vcardVersion = dataResult->GetInt(index++);
532                 std::string propertyGroup = dataResult->GetString(index++);
533                 std::string propertyId = dataResult->GetString(index++);
534                 if (!IsNeedInclude(propertyId, supportedFeatures)) {
535                     continue;
536                 }
537                 std::string propertyDetails = dataResult->GetString(index++);
538                 std::string propertyValue = dataResult->GetString(index++);
539                 PBAP_PSE_LOG_DEBUG("[%{public}zu]: %jd\t%{public}d\t%{public}d\t%{public}s\t%{public}s\t%{public}s",
540                     i,
541                     vcardUid,
542                     vcardHandleId,
543                     vcardVersion,
544                     propertyId.c_str(),
545                     propertyDetails.c_str(),
546                     propertyValue.c_str());
547                 vcard.AddProperty(VCardProperty(curVer, propertyGroup, propertyId, propertyValue, propertyDetails));
548             }
549             handleFun(vcard);
550         }
551         return true;
552     }
553 
SelectVcardEntryUid(const std::unique_ptr<DataAccess> & dataAccess,const std::u16string & folderId,std::u16string entryId,const PbapPseAppParams & pbapAppParams)554     static std::vector<std::pair<int64_t, int>> SelectVcardEntryUid(const std::unique_ptr<DataAccess> &dataAccess,
555         const std::u16string &folderId, std::u16string entryId, const PbapPseAppParams &pbapAppParams)
556     {
557         PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
558         std::string select = "select distinct t.vcard_uid, t.vcard_version from vcard_view t where 1 = 1 ";
559         std::string where = "";
560         bool isXBtUid = entryId.find(PBAP_PSE_X_BT_UID_PREFIX) == 0;
561         if (isXBtUid) {
562             where += "and exists (";
563             where += "select 1 from vcard_view s where s.vcard_uid = t.vcard_uid and "
564                      "s.property_id = 'X-BT-UID' and s.property_value = ? ";
565             where += ")";
566         } else {
567             where += "and t.folder_id = ? and t.vcard_handle_id = ? ";
568         }
569         where += GetVcardSelectorWhere(pbapAppParams);
570         select += where;
571         select += " limit 1";
572 
573         std::vector<std::pair<int64_t, int>> vcardUids;
574         auto stmtVcardIds = dataAccess->CreateStatement(select);
575         if (!stmtVcardIds) {
576             return vcardUids;
577         }
578         int pIndex = 1;
579         if (isXBtUid) {
580             entryId = entryId.substr(PBAP_PSE_X_BT_UID_PREFIX.size());
581             stmtVcardIds->SetParam16String(pIndex++, entryId);
582         } else {
583             entryId = entryId.substr(0, entryId.size() - PBAP_PSE_VCARD_SUFFIX.size());
584             stmtVcardIds->SetParam16String(pIndex++, folderId);
585             int handleId = PbapPseVcardManager::VcardHandleId2Int(entryId);
586             stmtVcardIds->SetParamInt(pIndex++, handleId);
587         }
588 
589         auto dataResult = stmtVcardIds->Query();
590         while (dataResult->Next()) {
591             int index = 0;
592             int64_t vcardUid = dataResult->GetInt64(index++);
593             int vcardVer = dataResult->GetInt(index++);
594             vcardUids.push_back(std::make_pair(vcardUid, vcardVer));
595         }
596         return vcardUids;
597     }
598 
GetPropertySelectorWhere(const std::vector<std::string> & includeProperties)599     static std::string GetPropertySelectorWhere(const std::vector<std::string> &includeProperties)
600     {
601         std::string inSection = "";
602         if (includeProperties.size() > 0) {
603             inSection += " and property_id in (";
604             for (size_t i = 0; i < includeProperties.size(); i++) {
605                 if (i > 0) {
606                     inSection += ",";
607                 }
608                 inSection += "'" + includeProperties.at(i) + "'";
609             }
610             inSection += ") ";
611         }
612 
613         return inSection;
614     }
615 
GetVcardSearchPropertyWhere(const PbapPseAppParams & pbapAppParams)616     static std::string GetVcardSearchPropertyWhere(const PbapPseAppParams &pbapAppParams)
617     {
618         std::string andSection = "";
619         // 5.3.4.3 SearchValue :<text string>
620         if (pbapAppParams.GetSearchValueUtf8().size() > 0) {
621             andSection += "and exists (";
622             andSection += "select 1 from vcard_view s where s.vcard_uid = t.vcard_uid and "
623                           "s.property_id = '";
624 
625             // 5.3.4.2 SearchProperty :Name, Number, Sound
626             std::string searchPropertyId = "N";
627             if (pbapAppParams.GetSearchProperty()) {
628                 switch (*pbapAppParams.GetSearchProperty()) {
629                     case 0x01:  // Number
630                         searchPropertyId = "TEL";
631                         break;
632                     case 0x02:  // Sound
633                         searchPropertyId = "SOUND";
634                         break;
635                     default:
636                         searchPropertyId = "N";  // default Name
637                         break;
638                 }
639             }
640             andSection += searchPropertyId + "' and s.property_value like '%' || ? || '%'";
641             andSection += ")";
642         }
643         return andSection;
644     }
645 
GetVcardSelectorWhere(const PbapPseAppParams & pbapAppParams)646     static std::string GetVcardSelectorWhere(const PbapPseAppParams &pbapAppParams)
647     {
648         std::string andSection = "";
649         // 5.1.4.7 vCardSelector
650         if (!pbapAppParams.GetVcardSelector()) {
651             return andSection;
652         }
653         uint64_t vcardSelector = *pbapAppParams.GetVcardSelector();
654         // 5.1.4.8 vCardSelectorOperator
655         // All vCards shall be returned if contains all zeros.
656         if (vcardSelector == 0) {
657             return andSection;
658         }
659         auto selectorProperties = PbapPseVcardManager::GetIncludeProperties(vcardSelector);
660         if (selectorProperties.size() == 0) {
661             return andSection;
662         }
663         std::string relations = "or";
664         if (pbapAppParams.GetVcardSelectorOperator()) {
665             if (*pbapAppParams.GetVcardSelectorOperator() == 0x01) {
666                 relations = "and";
667             }
668         }
669         andSection += " and (";
670         for (size_t i = 0; i < selectorProperties.size(); i++) {
671             if (i > 0) {
672                 andSection += " " + relations + " ";
673             }
674             andSection += " exists (";
675             andSection += "select 1 from vcard_view s where s.vcard_uid = t.vcard_uid and "
676                           "s.property_id = '" +
677                           selectorProperties.at(i) + "' and s.property_value != ''";
678             andSection += ")";
679         }
680         andSection += ") ";
681         return andSection;
682     }
683 
AddMissProperties(VCard & vcard,const std::vector<std::string> & properties)684     static void AddMissProperties(VCard &vcard, const std::vector<std::string> &properties)
685     {
686         for (auto propertyId : properties) {
687             if (!vcard.HasProperty(propertyId)) {
688                 vcard.AddProperty(VCardProperty(vcard.GetVersion(), "", propertyId, "", ""));
689             }
690         }
691     }
692 };
693 
694 const std::map<char16_t, uint8_t> PbapPseVcardManager::VCARD_HANDLE_CHAR_MAP = {
695     {'0', 0},
696     {'1', 1},
697     {'2', 2},
698     {'3', 3},
699     {'4', 4},
700     {'5', 5},
701     {'6', 6},
702     {'7', 7},
703     {'8', 8},
704     {'9', 9},
705     {'A', 10},
706     {'B', 11},
707     {'C', 12},
708     {'D', 13},
709     {'E', 14},
710     {'F', 15},
711     {'a', 10},
712     {'b', 11},
713     {'c', 12},
714     {'d', 13},
715     {'e', 14},
716     {'f', 15}
717 };
718 
719 const std::map<std::u16string, std::u16string> PbapPseVcardManager::VIRTUAL_VCF_FOLDER_MAP = {
720     {u"/telecom/pb.vcf", u"pb"},
721     {u"/telecom/ich.vcf", u"ich"},
722     {u"/telecom/och.vcf", u"och"},
723     {u"/telecom/mch.vcf", u"mch"},
724     {u"/telecom/cch.vcf", u"cch"},
725     {u"/telecom/spd.vcf", u"spd"},
726     {u"/telecom/fav.vcf", u"fav"},
727     {u"/SIM1/telecom/pb.vcf", u"pb1"},
728     {u"/SIM1/telecom/ich.vcf", u"ich1"},
729     {u"/SIM1/telecom/och.vcf", u"och1"},
730     {u"/SIM1/telecom/mch.vcf", u"mch1"},
731     {u"/SIM1/telecom/cch.vcf", u"cch1"},
732 };
733 
734 const std::map<uint64_t, std::string> PbapPseVcardManager::PROPERTY_MASK_MAP = {
735     {uint64_t(1) << 0, "VERSION"},
736     {uint64_t(1) << 1, "FN"},
737     {uint64_t(1) << 2, "N"},
738     {uint64_t(1) << 3, "PHOTO"},
739     {uint64_t(1) << 4, "BDAY"},
740     {uint64_t(1) << 5, "ADR"},
741     {uint64_t(1) << 6, "LABEL"},
742     {uint64_t(1) << 7, "TEL"},
743     {uint64_t(1) << 8, "EMAIL"},
744     {uint64_t(1) << 9, "MAILER"},
745     {uint64_t(1) << 10, "TZ"},
746     {uint64_t(1) << 11, "GEO"},
747     {uint64_t(1) << 12, "TITLE"},
748     {uint64_t(1) << 13, "ROLE"},
749     {uint64_t(1) << 14, "LOGO"},
750     {uint64_t(1) << 15, "AGENT"},
751     {uint64_t(1) << 16, "ORG"},
752     {uint64_t(1) << 17, "NOTE"},
753     {uint64_t(1) << 18, "REV"},
754     {uint64_t(1) << 19, "SOUND"},
755     {uint64_t(1) << 20, "URL"},
756     {uint64_t(1) << 21, "UID"},
757     {uint64_t(1) << 22, "KEY"},
758     {uint64_t(1) << 23, "NICKNAME"},
759     {uint64_t(1) << 24, "CATEGORIES"},
760     {uint64_t(1) << 25, "PROID"},
761     {uint64_t(1) << 26, "CLASS"},
762     {uint64_t(1) << 27, "SORT-STRING"},
763     {uint64_t(1) << 28, "X-IRMC-CALL-DATETIME"},
764     {uint64_t(1) << 29, "X-BT-SPEEDDIALKEY"},
765     {uint64_t(1) << 30, "X-BT-UCI"},
766     {uint64_t(1) << 31, "X-BT-UID"}
767 };
768 
769 std::string PbapPseVcardManager::g_pbapDbFile = PBAP_PSE_DEFAULT_DB_FILE;
770 
SetDbFile(const std::string dbFile)771 void PbapPseVcardManager::SetDbFile(const std::string dbFile)
772 {
773     g_pbapDbFile = dbFile;
774 }
775 
PullPhoneBook(std::u16string nameWithFolder,const PbapPseAppParams & pbapAppParams,const uint32_t & supportedFeatures,PhoneBookResult & result)776 void PbapPseVcardManager::PullPhoneBook(std::u16string nameWithFolder, const PbapPseAppParams &pbapAppParams,
777     const uint32_t &supportedFeatures, PhoneBookResult &result)
778 {
779     PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
780     if (nameWithFolder.at(0) != '/') {
781         nameWithFolder = u"/" + nameWithFolder;
782     }
783     auto target = VIRTUAL_VCF_FOLDER_MAP.find(nameWithFolder);
784     // not find folder
785     if (target == VIRTUAL_VCF_FOLDER_MAP.end()) {
786         PBAP_PSE_LOG_ERROR("can't find vcard %{public}s", ObexUtils::UnicodeToUtf8(nameWithFolder).c_str());
787         result.rspCode_ = ObexRspCode::NOT_FOUND;
788         return;
789     }
790 
791     auto dataAccess = DataAccess::GetConnection(g_pbapDbFile);
792     if (!dataAccess) {
793         result.rspCode_ = ObexRspCode::NOT_FOUND;
794         return;
795     }
796 
797     const std::u16string &folderId = target->second;
798     if (pbapAppParams.GetMaxListCount()) {
799         uint16_t maxListCount = *pbapAppParams.GetMaxListCount();
800         // PBAP_v1.2.3-5.1.4.3 MaxListCount
801         result.phoneBookSizeOnly_ = maxListCount == 0;
802     }
803     if (result.phoneBookSizeOnly_) {
804         PBAP_PSE_LOG_DEBUG("GetPhoneBookSizeOnly");
805         PbapPseVcardDataAccess::SetPhoneBookSize(dataAccess, folderId, result, pbapAppParams);
806         if (result.rspCode_ != ObexRspCode::SUCCESS) {
807             return;
808         }
809     }
810     PbapPseVcardDataAccess::SetCommonResult(dataAccess, folderId, result, supportedFeatures);
811     if (result.rspCode_ != ObexRspCode::SUCCESS) {
812         return;
813     }
814     if (!result.phoneBookSizeOnly_) {
815         PBAP_PSE_LOG_DEBUG("GetPhoneBook");
816         PbapPseVcardDataAccess::SetPhoneBook(dataAccess, folderId, result, pbapAppParams, supportedFeatures);
817     }
818 }
819 
PullvCardListing(std::u16string currentPath,std::u16string folderName,const PbapPseAppParams & pbapAppParams,const uint32_t & supportedFeatures,PhoneBookResult & result)820 void PbapPseVcardManager::PullvCardListing(std::u16string currentPath, std::u16string folderName,
821     const PbapPseAppParams &pbapAppParams, const uint32_t &supportedFeatures, PhoneBookResult &result)
822 {
823     PBAP_PSE_LOG_INFO("%{public}s ", __PRETTY_FUNCTION__);
824     std::u16string nameWithFolder = currentPath;
825     if (folderName.size() > 0) {
826         nameWithFolder += u"/" + folderName;
827     }
828     nameWithFolder += PBAP_PSE_VCARD_SUFFIX;
829     auto target = VIRTUAL_VCF_FOLDER_MAP.find(nameWithFolder);
830     // not find folder
831     if (target == VIRTUAL_VCF_FOLDER_MAP.end()) {
832         PBAP_PSE_LOG_ERROR("can't find folder [%{public}s] in [%{public}s]",
833             ObexUtils::UnicodeToUtf8(folderName).c_str(),
834             ObexUtils::UnicodeToUtf8(currentPath).c_str());
835         result.rspCode_ = ObexRspCode::NOT_FOUND;
836         return;
837     }
838     auto dataAccess = DataAccess::GetConnection(g_pbapDbFile);
839     if (!dataAccess) {
840         result.rspCode_ = ObexRspCode::NOT_FOUND;
841         return;
842     }
843     const std::u16string &folderId = target->second;
844 
845     if (pbapAppParams.GetMaxListCount()) {
846         uint16_t maxListCount = *pbapAppParams.GetMaxListCount();
847         // PBAP_v1.2.3-5.1.4.3 MaxListCount
848         result.phoneBookSizeOnly_ = maxListCount == 0;
849     }
850     if (result.phoneBookSizeOnly_) {
851         PbapPseVcardDataAccess::SetPullvCardListingSize(dataAccess, folderId, result, pbapAppParams);
852         if (result.rspCode_ != ObexRspCode::SUCCESS) {
853             return;
854         }
855     }
856 
857     PbapPseVcardDataAccess::SetCommonResult(dataAccess, folderId, result, supportedFeatures);
858 
859     if (result.rspCode_ != ObexRspCode::SUCCESS) {
860         return;
861     }
862 
863     if (!result.phoneBookSizeOnly_) {
864         PbapPseVcardDataAccess::SetPullvCardListing(dataAccess, folderId, result, pbapAppParams);
865     }
866 }
867 
PullvCardEntry(std::u16string currentPath,std::u16string entryId,const PbapPseAppParams & pbapAppParams,const uint32_t & supportedFeatures,PhoneBookResult & result)868 void PbapPseVcardManager::PullvCardEntry(std::u16string currentPath, std::u16string entryId,
869     const PbapPseAppParams &pbapAppParams, const uint32_t &supportedFeatures, PhoneBookResult &result)
870 {
871     std::u16string folderId = u"";
872     if (entryId.find(PBAP_PSE_X_BT_UID_PREFIX) == std::string::npos) {
873         // not find folder
874         std::u16string nameWithFolder = currentPath + PBAP_PSE_VCARD_SUFFIX;
875         auto target = VIRTUAL_VCF_FOLDER_MAP.find(nameWithFolder);
876         if (target == VIRTUAL_VCF_FOLDER_MAP.end()) {
877             PBAP_PSE_LOG_ERROR("can't find folder [%{public}s] ", ObexUtils::UnicodeToUtf8(currentPath).c_str());
878             result.rspCode_ = ObexRspCode::NOT_FOUND;
879             return;
880         }
881         folderId = target->second;
882     }
883     auto dataAccess = DataAccess::GetConnection(g_pbapDbFile);
884     if (!dataAccess) {
885         result.rspCode_ = ObexRspCode::NOT_FOUND;
886         return;
887     }
888     if (IsSupportedDbVer(supportedFeatures)) {
889         PbapPseVcardDataAccess::SetDbId(dataAccess, result);
890         if (result.rspCode_ != ObexRspCode::SUCCESS) {
891             return;
892         }
893     }
894 
895     PbapPseVcardDataAccess::SetPullvCardEntryParam param = {
896         folderId, entryId, supportedFeatures
897     };
898     PbapPseVcardDataAccess::SetPullvCardEntry(dataAccess, param, pbapAppParams, result);
899 }
900 
CheckPhoneBookPath(std::u16string path)901 bool PbapPseVcardManager::CheckPhoneBookPath(std::u16string path)
902 {
903     if (path.size() == 0) {
904         return true;
905     }
906     if (path.at(0) != '/') {
907         path = u"/" + path;
908     }
909     if (path.back() != '/') {
910         path += u"/";
911     }
912     for (auto &item : VIRTUAL_VCF_FOLDER_MAP) {
913         std::u16string fullPath = item.first;
914         fullPath = fullPath.substr(0, fullPath.size() - PBAP_PSE_VCARD_SUFFIX.size()) + u"/";
915         if (fullPath.find(path) == 0) {
916             return true;
917         }
918     }
919     return false;
920 }
921 
CheckVcardHandleId(const std::u16string & handleId)922 bool PbapPseVcardManager::CheckVcardHandleId(const std::u16string &handleId)
923 {
924     if (handleId.size() == 0) {
925         return false;
926     }
927     for (char16_t c : handleId) {
928         if (VCARD_HANDLE_CHAR_MAP.find(c) == VCARD_HANDLE_CHAR_MAP.end()) {
929             return false;
930         }
931     }
932     return true;
933 }
934 
VcardHandleId2Int(const std::u16string & handleId)935 int PbapPseVcardManager::VcardHandleId2Int(const std::u16string &handleId)
936 {
937     size_t size = handleId.size();
938     if (size == 0) {
939         return -1;
940     }
941     int dec = 0;
942     for (size_t index = 0; index < size; index++) {
943         char16_t c = handleId.at(index);
944         if (VCARD_HANDLE_CHAR_MAP.find(c) == VCARD_HANDLE_CHAR_MAP.end()) {
945             return -1;
946         }
947         uint8_t num = VCARD_HANDLE_CHAR_MAP.find(c)->second;
948         if (num == 0) {
949             continue;
950         }
951         int m = 1;
952         for (size_t count = 0; count < size - index - 1; count++) {
953             m *= 0x10;
954         }
955         dec += (num * m);
956     }
957     return dec;
958 }
959 
GetIncludeProperties(uint64_t propertySelector)960 std::vector<std::string> PbapPseVcardManager::GetIncludeProperties(uint64_t propertySelector)
961 {
962     std::vector<std::string> list;
963     for (auto item : PROPERTY_MASK_MAP) {
964         if ((propertySelector & item.first) != 0) {
965             list.push_back(item.second);
966         }
967     }
968     return list;
969 }
970 
IsSupportedFolderVer(const uint32_t & supportedFeatures)971 bool PbapPseVcardManager::IsSupportedFolderVer(const uint32_t &supportedFeatures)
972 {
973     return (PBAP_FEATURES_FOLDER_VERSION_COUNTERS & supportedFeatures) != 0;
974 }
975 
IsSupportedDbVer(const uint32_t & supportedFeatures)976 bool PbapPseVcardManager::IsSupportedDbVer(const uint32_t &supportedFeatures)
977 {
978     return (PBAP_FEATURES_DATABASE_IDENTIFIER & supportedFeatures) != 0;
979 }
980 
IsSupportedXBtUCI(const uint32_t & supportedFeatures)981 bool PbapPseVcardManager::IsSupportedXBtUCI(const uint32_t &supportedFeatures)
982 {
983     return (PBAP_FEATURES_X_BT_UCI_VCARD_PROPERTY & supportedFeatures) != 0;
984 }
985 
IsSupportedXBtUID(const uint32_t & supportedFeatures)986 bool PbapPseVcardManager::IsSupportedXBtUID(const uint32_t &supportedFeatures)
987 {
988     return (PBAP_FEATURES_X_BT_UID_VCARD_PROPERTY & supportedFeatures) != 0;
989 }
990 }  // namespace bluetooth
991 }  // namespace OHOS
992