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_decoder_v21.h"
17
18 #include <algorithm>
19 #include <cctype>
20 #include <codecvt>
21 #include <locale>
22 #include <sstream>
23 #include <vector>
24
25 #include "telephony_common_utils.h"
26 #include "telephony_errors.h"
27 #include "telephony_log_wrapper.h"
28 #include "vcard_constant.h"
29 #include "vcard_file_utils.h"
30 #include "vcard_utils.h"
31
32 namespace OHOS {
33 namespace Telephony {
34 std::mutex rawDataMutex_;
35 namespace {
36 constexpr int32_t STATUS_GROUP_OR_TYPE_NAME = 1;
37 constexpr int32_t STATUS_PARAMS = 2;
38 constexpr int32_t STATUS_PARAMS_IN_DQUOTE = 3;
39 } // namespace
40
AddVCardDecodeListener(std::shared_ptr<VCardDecodeListener> listener)41 void VCardDecoderV21::AddVCardDecodeListener(std::shared_ptr<VCardDecodeListener> listener)
42 {
43 if (listener == nullptr) {
44 TELEPHONY_LOGE("listener is nullptr");
45 return;
46 }
47 std::lock_guard<std::mutex> lock(rawDataMutex_);
48 listeners_.push_back(listener);
49 }
50
NotifyStarted()51 void VCardDecoderV21::NotifyStarted()
52 {
53 for (auto it : listeners_) {
54 if (it == nullptr) {
55 continue;
56 }
57 it->OnStarted();
58 }
59 }
60
NotifyEnded()61 void VCardDecoderV21::NotifyEnded()
62 {
63 for (auto it : listeners_) {
64 if (it == nullptr) {
65 continue;
66 }
67 it->OnEnded();
68 }
69 }
70
NotifyOneContactStarted()71 void VCardDecoderV21::NotifyOneContactStarted()
72 {
73 for (auto it : listeners_) {
74 if (it == nullptr) {
75 continue;
76 }
77 it->OnOneContactStarted();
78 }
79 }
80
NotifyOneContactEnded()81 void VCardDecoderV21::NotifyOneContactEnded()
82 {
83 for (auto it : listeners_) {
84 if (it == nullptr) {
85 continue;
86 }
87 it->OnOneContactEnded();
88 }
89 }
90
NotifyRawDataCreated(std::shared_ptr<VCardRawData> rawData)91 void VCardDecoderV21::NotifyRawDataCreated(std::shared_ptr<VCardRawData> rawData)
92 {
93 for (auto it : listeners_) {
94 if (it == nullptr) {
95 continue;
96 }
97 it->OnRawDataCreated(rawData);
98 }
99 }
100
Decode(int32_t & errorCode)101 void VCardDecoderV21::Decode(int32_t &errorCode)
102 {
103 NotifyStarted();
104 while (!IsEnd() && DecodeOne(errorCode)) {
105 if (errorCode != TELEPHONY_SUCCESS) {
106 TELEPHONY_LOGE("Failed to decode");
107 }
108 }
109 NotifyEnded();
110 }
111
DecodeOne(int32_t & errorCode)112 bool VCardDecoderV21::DecodeOne(int32_t &errorCode)
113 {
114 errorCode = TELEPHONY_SUCCESS;
115 currentCharset_ = DEFAULT_CHARSET;
116 currentEncoding_ = DEFAULT_ENCODING;
117 NotifyOneContactStarted();
118 if (!ReadBegin()) {
119 TELEPHONY_LOGE("Failed to decode");
120 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
121 return false;
122 }
123 ParseItems(errorCode);
124 if (errorCode != TELEPHONY_SUCCESS) {
125 TELEPHONY_LOGE("Failed to parse item");
126 return false;
127 }
128 NotifyOneContactEnded();
129 fileUtils_.SkipEmptyLines();
130 return true;
131 }
132
ReadBegin()133 bool VCardDecoderV21::ReadBegin()
134 {
135 std::string line = GetNonEmptyLine();
136 if (line == "") {
137 TELEPHONY_LOGE("empty file");
138 return false;
139 }
140 std::vector<std::string> strArr = VCardUtils::Split(line, ":");
141 int32_t expectSize = 2;
142 if (static_cast<int32_t>(strArr.size()) == expectSize &&
143 VCardUtils::EqualsIgnoreCase(VCardUtils::Trim(strArr[0]), VCARD_TYPE_BEGIN) &&
144 VCardUtils::EqualsIgnoreCase(VCardUtils::Trim(strArr[1]), DATA_VCARD)) {
145 return true;
146 }
147 return false;
148 }
149
ParseItems(int32_t & errorCode)150 void VCardDecoderV21::ParseItems(int32_t &errorCode)
151 {
152 while (ParseItem(errorCode)) {
153 if (errorCode != TELEPHONY_SUCCESS) {
154 TELEPHONY_LOGE("Failed to parse item");
155 return;
156 }
157 }
158 }
159
ParseItem(int32_t & errorCode)160 bool VCardDecoderV21::ParseItem(int32_t &errorCode)
161 {
162 currentEncoding_ = DEFAULT_ENCODING;
163 std::string line = GetNonEmptyLine();
164 if (line == "") {
165 TELEPHONY_LOGI("File is finish");
166 return false;
167 }
168 std::lock_guard<std::mutex> lock(rawDataMutex_);
169 auto rawData = std::make_shared<VCardRawData>();
170 if (rawData == nullptr) {
171 TELEPHONY_LOGE("rawData is nullptr!");
172 return false;
173 }
174 BuildRawData(line, rawData, errorCode);
175 if (errorCode != TELEPHONY_SUCCESS) {
176 TELEPHONY_LOGE("Build raw data failed");
177 return false;
178 }
179 std::string name = VCardUtils::ToUpper(rawData->GetName());
180 std::string rawDataValue = rawData->GetRawValue();
181 if (name == VCARD_TYPE_END && VCardUtils::EqualsIgnoreCase(rawDataValue, DATA_VCARD)) {
182 TELEPHONY_LOGI("Vcard parse end");
183 return false;
184 }
185 if (name == VCARD_TYPE_AGENT) {
186 DealAgent(rawData, errorCode);
187 return true;
188 }
189 RecordUnknowParamType(name);
190 DealRawDataValue(name, rawData, errorCode);
191 return !fileUtils_.IsEnd();
192 }
193
DealRawDataValue(const std::string & name,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)194 void VCardDecoderV21::DealRawDataValue(
195 const std::string &name, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
196 {
197 if (rawData == nullptr) {
198 TELEPHONY_LOGE("rawData is nullptr!");
199 return;
200 }
201 std::string nameUp = VCardUtils::ToUpper(rawData->GetName());
202 std::string rawValue = rawData->GetRawValue();
203 std::string sourceCharset = DEFAULT_INTERMEDIATE_CHARSET;
204 auto charsets = rawData->GetParameters(VCARD_PARAM_CHARSET);
205 std::string targetCharset = ((static_cast<int32_t>(charsets.size()) != 0) ? charsets[0] : "");
206 if (targetCharset.empty()) {
207 targetCharset = DEFAULT_IMPORT_CHARSET;
208 }
209 if (nameUp == VCARD_TYPE_ADR || nameUp == VCARD_TYPE_ORG || nameUp == VCARD_TYPE_N) {
210 DealAdrOrgN(rawValue, rawData, sourceCharset, targetCharset, errorCode);
211 return;
212 }
213 if (currentEncoding_ == VCARD_PARAM_ENCODING_QP ||
214 ((nameUp == VCARD_TYPE_FN) && rawData->GetParameters(VCARD_PARAM_ENCODING).empty())) {
215 DealEncodingQPOrNoEncodingFN(rawValue, rawData, sourceCharset, targetCharset, errorCode);
216 return;
217 }
218 if (currentEncoding_ == VCARD_PARAM_ENCODING_BASE64 || currentEncoding_ == VCARD_PARAM_ENCODING_B) {
219 DealBase64OrB(rawValue, rawData, errorCode);
220 return;
221 }
222 if (!(currentEncoding_ == VCARD_PARAM_ENCODING_7BIT || currentEncoding_ == VCARD_PARAM_ENCODING_8BIT ||
223 VCardUtils::StartWith(currentEncoding_, "X-"))) {
224 TELEPHONY_LOGI("encoding is no support %{public}s ", currentEncoding_.c_str());
225 }
226 if (GetVersion() == VERSION_21) {
227 DealV21Value(rawValue);
228 }
229 std::string temp = VCardUtils::ConvertCharset(rawValue, "", targetCharset, errorCode);
230 if (errorCode != TELEPHONY_SUCCESS) {
231 TELEPHONY_LOGE("GetQuotedPrintableValue failed");
232 return;
233 }
234 std::vector<std::string> valueList;
235 std::string value = UnescapeText(temp);
236 valueList.push_back(value);
237 rawData->SetValues(valueList);
238 NotifyRawDataCreated(rawData);
239 }
240
DealV21Value(std::string & rawValue)241 void VCardDecoderV21::DealV21Value(std::string &rawValue)
242 {
243 std::string str;
244 while (true) {
245 std::string line = PeekLine();
246 if (line.empty() || line[0] != ' ' || VCardUtils::ToUpper(line).find("END:VCARD") != std::string::npos) {
247 break;
248 }
249 GetLine();
250 if (str.empty()) {
251 str = rawValue;
252 }
253 str += line.substr(1);
254 }
255 rawValue = str;
256 }
257
GetVersion()258 std::string VCardDecoderV21::GetVersion()
259 {
260 return VERSION_21;
261 }
262
DealBase64OrB(const std::string & rawValue,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)263 void VCardDecoderV21::DealBase64OrB(
264 const std::string &rawValue, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
265 {
266 if (rawData == nullptr) {
267 TELEPHONY_LOGE("rawData is nullptr!");
268 return;
269 }
270 std::string base64 = GetBase64(rawValue, errorCode);
271 rawData->SetByte(VCardUtils::DecodeBase64(base64));
272 NotifyRawDataCreated(rawData);
273 }
274
DealEncodingQPOrNoEncodingFN(const std::string & rawValue,std::shared_ptr<VCardRawData> rawData,const std::string & fromCharSet,const std::string & toCharSet,int32_t & errorCode)275 void VCardDecoderV21::DealEncodingQPOrNoEncodingFN(const std::string &rawValue, std::shared_ptr<VCardRawData> rawData,
276 const std::string &fromCharSet, const std::string &toCharSet, int32_t &errorCode)
277 {
278 if (rawData == nullptr) {
279 TELEPHONY_LOGE("rawData is nullptr!");
280 return;
281 }
282 std::string quotedPrintableValue = GetQuotedPrintableValue(rawValue, errorCode);
283 if (errorCode != TELEPHONY_SUCCESS) {
284 TELEPHONY_LOGE("GetQuotedPrintableValue failed");
285 return;
286 }
287 std::string encodedValue = ParseQuotedPrintableValue(quotedPrintableValue, fromCharSet, toCharSet, errorCode);
288 if (errorCode != TELEPHONY_SUCCESS) {
289 TELEPHONY_LOGE("GetQuotedPrintableValue failed");
290 return;
291 }
292 rawData->SetRawValue(quotedPrintableValue);
293 rawData->AppendValues({ encodedValue });
294 NotifyRawDataCreated(rawData);
295 }
296
RecordUnknowParamType(const std::string & name)297 void VCardDecoderV21::RecordUnknowParamType(const std::string &name)
298 {
299 if (!(ContainValue(VCardUtils::ToUpper(name), GetSupportType()) || VCardUtils::StartWith(name, "X-"))) {
300 unknowParamType_.insert(name);
301 }
302 }
303
GetLine()304 std::string VCardDecoderV21::GetLine()
305 {
306 std::string line = "";
307 fileUtils_.ReadLine(line);
308 return line;
309 }
310
PeekLine()311 std::string VCardDecoderV21::PeekLine()
312 {
313 std::string line = "";
314 fileUtils_.PeekLine(line);
315 return line;
316 }
317
GetNonEmptyLine()318 std::string VCardDecoderV21::GetNonEmptyLine()
319 {
320 std::string line = "";
321 while (fileUtils_.ReadLine(line)) {
322 line = VCardUtils::Trim(line);
323 if (!line.empty()) {
324 break;
325 }
326 }
327 return line;
328 }
329
BuildRawData(const std::string & line,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)330 void VCardDecoderV21::BuildRawData(const std::string &line, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
331 {
332 int32_t length = static_cast<int32_t>(line.length());
333 if (length >= 0 && line[0] == '#') {
334 TELEPHONY_LOGE("line is invalid");
335 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
336 return;
337 }
338 int32_t status = STATUS_GROUP_OR_TYPE_NAME;
339 int32_t namePos = 0;
340 errorCode = TELEPHONY_SUCCESS;
341 for (int32_t i = 0; i < length && errorCode == TELEPHONY_SUCCESS; i++) {
342 if (status == STATUS_GROUP_OR_TYPE_NAME) {
343 DealGroupOrTypeNameStatus(line, rawData, errorCode, status, namePos, i);
344 continue;
345 }
346 if (status == STATUS_PARAMS) {
347 DealParamsStatus(line, rawData, errorCode, status, namePos, i);
348 continue;
349 }
350 if (status == STATUS_PARAMS_IN_DQUOTE) {
351 status = STATUS_PARAMS;
352 continue;
353 }
354 }
355 }
356
DealGroupOrTypeNameStatus(const std::string & line,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode,int32_t & status,int32_t & namePos,int32_t & index)357 void VCardDecoderV21::DealGroupOrTypeNameStatus(const std::string &line, std::shared_ptr<VCardRawData> rawData,
358 int32_t &errorCode, int32_t &status, int32_t &namePos, int32_t &index)
359 {
360 if (rawData == nullptr) {
361 TELEPHONY_LOGE("rawData is nullptr!");
362 return;
363 }
364 if (line[index] == ':') {
365 rawData->SetName(line.substr(namePos, index - namePos));
366 rawData->SetRawValue(index < static_cast<int32_t>(line.length()) - 1 ? line.substr(index + 1) : "");
367 index = static_cast<int32_t>(line.length());
368 return;
369 }
370
371 if (line[index] == '.') {
372 std::string groupName = line.substr(namePos, index - namePos);
373 if (groupName.length() == 0) {
374 TELEPHONY_LOGI("Empty group");
375 } else {
376 rawData->AppendGroup(groupName);
377 }
378 namePos = index + 1;
379 return;
380 }
381 if (line[index] == ';') {
382 rawData->SetName(line.substr(namePos, index - namePos));
383 namePos = index + 1;
384 status = STATUS_PARAMS;
385 return;
386 }
387 }
388
DealParamsStatus(const std::string & line,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode,int32_t & status,int32_t & namePos,int32_t & index)389 void VCardDecoderV21::DealParamsStatus(const std::string &line, std::shared_ptr<VCardRawData> rawData,
390 int32_t &errorCode, int32_t &status, int32_t &namePos, int32_t &index)
391 {
392 if (rawData == nullptr) {
393 TELEPHONY_LOGE("rawData is nullptr!");
394 return;
395 }
396 if (line[index] == '"') {
397 status = STATUS_PARAMS_IN_DQUOTE;
398 return;
399 }
400 if (line[index] == ';') {
401 DealParams(line.substr(namePos, index - namePos), rawData, errorCode);
402 namePos = index + 1;
403 return;
404 }
405
406 if (line[index] == ':') {
407 DealParams(line.substr(namePos, index - namePos), rawData, errorCode);
408 namePos = index + 1;
409 rawData->SetRawValue(index < static_cast<int32_t>(line.length()) - 1 ? line.substr(index + 1) : "");
410 index = static_cast<int32_t>(line.length());
411 return;
412 }
413 }
414
DealParams(const std::string & params,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)415 void VCardDecoderV21::DealParams(const std::string ¶ms, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
416 {
417 auto strs = VCardUtils::Split(params, "=");
418 if (static_cast<int32_t>(strs.size()) == SIZE_TWO) {
419 std::string name = VCardUtils::ToUpper(VCardUtils::Trim(strs[0]));
420 std::string value = VCardUtils::Trim(strs[1]);
421 if (name == VCARD_PARAM_TYPE) {
422 DealTypeParam(value, rawData, errorCode);
423 return;
424 }
425 if (name == VCARD_PARAM_VALUE) {
426 DealValueParam(value, rawData, errorCode);
427 return;
428 }
429 if (name == VCARD_PARAM_ENCODING) {
430 DealEncodingParam(VCardUtils::ToUpper(value), rawData, errorCode);
431 return;
432 }
433 if (name == VCARD_PARAM_CHARSET) {
434 DealCharsetParam(value, rawData, errorCode);
435 return;
436 }
437 if (name == VCARD_PARAM_LANGUAGE) {
438 DealLanguageParam(value, rawData, errorCode);
439 return;
440 }
441 if (VCardUtils::StartWith(name, "X-")) {
442 DealAnyParam(name, value, rawData, errorCode);
443 return;
444 }
445 TELEPHONY_LOGE("Param type is not support");
446 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
447 return;
448 }
449 DealNoNameParam((strs.size() == SIZE_ZERO) ? "" : strs[0], rawData, errorCode);
450 }
451
DealNoNameParam(const std::string & paramValue,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)452 void VCardDecoderV21::DealNoNameParam(
453 const std::string ¶mValue, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
454 {
455 DealTypeParam(paramValue, rawData, errorCode);
456 }
457
DealTypeParam(const std::string & type,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)458 void VCardDecoderV21::DealTypeParam(const std::string &type, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
459 {
460 if (rawData == nullptr) {
461 TELEPHONY_LOGE("rawData is nullptr!");
462 return;
463 }
464 if (!(ContainValue(VCardUtils::ToUpper(type), GetSupportParamType()) || VCardUtils::StartWith(type, "X-"))) {
465 unknowParamType_.insert(type);
466 }
467 rawData->AppendParameter(VCARD_PARAM_TYPE, type);
468 }
469
DealValueParam(const std::string & value,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)470 void VCardDecoderV21::DealValueParam(
471 const std::string &value, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
472 {
473 if (rawData == nullptr) {
474 TELEPHONY_LOGE("rawData is nullptr!");
475 return;
476 }
477 if (!(ContainValue(VCardUtils::ToUpper(value), GetSupportParamValue()) || VCardUtils::StartWith(value, "X-"))) {
478 unknowParamValue_.insert(value);
479 }
480 rawData->AppendParameter(VCARD_PARAM_VALUE, value);
481 }
482
DealEncodingParam(const std::string & encoding,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)483 void VCardDecoderV21::DealEncodingParam(
484 const std::string &encoding, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
485 {
486 if (rawData == nullptr) {
487 TELEPHONY_LOGE("rawData is nullptr!");
488 return;
489 }
490 if (ContainValue(encoding, GetSupportParamEncoding()) || VCardUtils::StartWith(encoding, "X-")) {
491 rawData->AppendParameter(VCARD_PARAM_ENCODING, encoding);
492 currentEncoding_ = encoding;
493 return;
494 }
495 TELEPHONY_LOGE("Encoding is not support");
496 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
497 }
498
DealCharsetParam(const std::string & charset,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)499 void VCardDecoderV21::DealCharsetParam(
500 const std::string &charset, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
501 {
502 if (rawData == nullptr) {
503 TELEPHONY_LOGE("rawData is nullptr!");
504 return;
505 }
506 currentCharset_ = charset;
507 rawData->AppendParameter(VCARD_PARAM_CHARSET, charset);
508 }
509
DealLanguageParam(const std::string & language,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)510 void VCardDecoderV21::DealLanguageParam(
511 const std::string &language, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
512 {
513 if (rawData == nullptr) {
514 TELEPHONY_LOGE("rawData is nullptr!");
515 return;
516 }
517 auto strs = VCardUtils::Split(language, "-");
518 if (static_cast<int32_t>(strs.size()) != SIZE_TWO) {
519 TELEPHONY_LOGE("Language error");
520 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
521 return;
522 }
523 if (!IsAllAscLetter(strs[0]) || !IsAllAscLetter(strs[1])) {
524 TELEPHONY_LOGE("Language error");
525 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
526 return;
527 }
528 rawData->AppendParameter(VCARD_PARAM_LANGUAGE, language);
529 }
530
DealAnyParam(const std::string & param,const std::string & paramValue,std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)531 void VCardDecoderV21::DealAnyParam(
532 const std::string ¶m, const std::string ¶mValue, std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
533 {
534 if (rawData == nullptr) {
535 TELEPHONY_LOGE("rawData is nullptr!");
536 return;
537 }
538 rawData->AppendParameter(param, paramValue);
539 }
540
GetSupportParamType()541 std::vector<std::string> VCardDecoderV21::GetSupportParamType()
542 {
543 return { "DOM", "INTL", "POSTAL", "PARCEL", "HOME", "WORK", "PREF", "VOICE", "FAX", "MSG", "CELL", "PAGER", "BBS",
544 "MODEM", "CAR", "ISDN", "VIDEO", "AOL", "APPLELINK", "ATTMAIL", "CIS", "EWORLD", "INTERNET", "IBMMAIL",
545 "MCIMAIL", "POWERSHARE", "PRODIGY", "TLX", "X400", "GIF", "CGM", "WMF", "BMP", "MET", "PMB", "DIB", "PICT",
546 "TIFF", "PDF", "PS", "JPEG", "QTIME", "MPEG", "MPEG2", "AVI", "WAVE", "AIFF", "PCM", "X509", "PGP" };
547 }
548
GetSupportParamValue()549 std::vector<std::string> VCardDecoderV21::GetSupportParamValue()
550 {
551 return { "INLINE", "URL", "CONTENT-ID", "CID" };
552 }
553
GetSupportType()554 std::vector<std::string> VCardDecoderV21::GetSupportType()
555 {
556 return { VCARD_TYPE_BEGIN, VCARD_TYPE_END, VCARD_TYPE_LOGO, VCARD_TYPE_PHOTO, "LABEL", VCARD_TYPE_FN,
557 VCARD_TYPE_TITLE, "SOUND", VCARD_TYPE_VERSION, VCARD_TYPE_TEL, VCARD_TYPE_EMAIL, "TZ", "GEO", VCARD_TYPE_NOTE,
558 VCARD_TYPE_URL, VCARD_TYPE_BDAY, "ROLE", "REV", "UID", "KEY", "MAILER" };
559 }
560
GetSupportParamEncoding()561 std::vector<std::string> VCardDecoderV21::GetSupportParamEncoding()
562 {
563 return { VCARD_PARAM_ENCODING_7BIT, VCARD_PARAM_ENCODING_8BIT, VCARD_PARAM_ENCODING_QP, VCARD_PARAM_ENCODING_BASE64,
564 VCARD_PARAM_ENCODING_B };
565 }
566
IsAllAscLetter(const std::string & value)567 bool VCardDecoderV21::IsAllAscLetter(const std::string &value)
568 {
569 for (auto ch : value) {
570 if (!IsAscChar(ch)) {
571 return false;
572 }
573 }
574 return true;
575 }
576
ContainValue(const std::string & value,const std::vector<std::string> values)577 bool VCardDecoderV21::ContainValue(const std::string &value, const std::vector<std::string> values)
578 {
579 auto it = std::find(values.begin(), values.end(), value);
580 return it != values.end();
581 }
582
DealAdrOrgN(const std::string & rawValue,std::shared_ptr<VCardRawData> rawData,const std::string & fromCharSet,const std::string & toCharSet,int32_t & errorCode)583 void VCardDecoderV21::DealAdrOrgN(const std::string &rawValue, std::shared_ptr<VCardRawData> rawData,
584 const std::string &fromCharSet, const std::string &toCharSet, int32_t &errorCode)
585 {
586 if (rawData == nullptr) {
587 TELEPHONY_LOGE("rawData is nullptr!");
588 return;
589 }
590 if (currentEncoding_ == VCARD_PARAM_ENCODING_QP) {
591 std::string quotedPrintableValue = GetQuotedPrintableValue(rawValue, errorCode);
592 if (errorCode != TELEPHONY_SUCCESS) {
593 TELEPHONY_LOGE("GetQuotedPrintableValue failed");
594 return;
595 }
596 std::vector<std::string> encodedValues;
597 ParseQuotedPrintableValues(quotedPrintableValue, encodedValues, fromCharSet, toCharSet, errorCode);
598 if (errorCode != TELEPHONY_SUCCESS) {
599 TELEPHONY_LOGE("ParseQuotedPrintableValues failed");
600 return;
601 }
602 rawData->SetRawValue(quotedPrintableValue);
603 rawData->AppendValues(encodedValues);
604 NotifyRawDataCreated(rawData);
605 return;
606 }
607 std::string value = VCardUtils::ConvertCharset(GetPoMultiLine(rawValue), "", toCharSet, errorCode);
608 if (errorCode != TELEPHONY_SUCCESS) {
609 TELEPHONY_LOGE("ConvertCharset failed");
610 return;
611 }
612 rawData->AppendValues(BuildListFromValue(value));
613 NotifyRawDataCreated(rawData);
614 }
615
ParseQuotedPrintableValues(const std::string & rawValue,std::vector<std::string> & encodedValues,const std::string & fromCharSet,const std::string & toCharSet,int32_t & errorCode)616 void VCardDecoderV21::ParseQuotedPrintableValues(const std::string &rawValue, std::vector<std::string> &encodedValues,
617 const std::string &fromCharSet, const std::string &toCharSet, int32_t &errorCode)
618 {
619 auto quotedPrintableList = BuildListFromValue(rawValue);
620 for (auto temp : quotedPrintableList) {
621 auto value = ParseQuotedPrintableValue(temp, fromCharSet, toCharSet, errorCode);
622 if (errorCode != TELEPHONY_SUCCESS) {
623 TELEPHONY_LOGE("GetQuotedPrintableValue failed");
624 return;
625 }
626 encodedValues.push_back(value);
627 }
628 }
629
GetQuotedPrintableValue(const std::string & str,int32_t & errorCode)630 std::string VCardDecoderV21::GetQuotedPrintableValue(const std::string &str, int32_t &errorCode)
631 {
632 std::string target;
633 std::string firstStr = str;
634 if (!VCardUtils::EndWith(VCardUtils::Trim(firstStr), "=")) {
635 target += VCardUtils::Trim(firstStr);
636 return target;
637 }
638 target += VCardUtils::Trim(firstStr) + "\r\n";
639 while (true) {
640 std::string line = GetLine();
641 if (line.empty()) {
642 TELEPHONY_LOGE("QuotedPritableValue error");
643 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
644 return "";
645 }
646 if (!VCardUtils::EndWith(VCardUtils::Trim(line), "=")) {
647 target += VCardUtils::Trim(line);
648 return target;
649 }
650 target += VCardUtils::Trim(line) + "\r\n";
651 }
652 }
653
ParseQuotedPrintableValue(const std::string & from,const std::string & fromCharSet,const std::string & toCharSet,int32_t & errorCode)654 std::string VCardDecoderV21::ParseQuotedPrintableValue(
655 const std::string &from, const std::string &fromCharSet, const std::string &toCharSet, int32_t &errorCode)
656 {
657 std::vector<std::string> lines = VCardUtils::Split(from, "\r\n");
658 std::string printableValue;
659 for (auto &it : lines) {
660 if (VCardUtils::EndWith(it, "=")) {
661 printableValue += it.substr(0, static_cast<int32_t>(it.length()) - 1);
662 continue;
663 }
664 printableValue += it;
665 }
666 std::string encodeValue = DecodeQuotedPrintable(printableValue);
667 return VCardUtils::ConvertCharset(encodeValue, "", toCharSet, errorCode);
668 }
669
DecodeQuotedPrintable(const std::string & encodedString)670 std::string VCardDecoderV21::DecodeQuotedPrintable(const std::string &encodedString)
671 {
672 std::istringstream iss(encodedString);
673 std::ostringstream oss;
674 char ch;
675 while (iss.get(ch)) {
676 if (ch == '=') {
677 char hex[VALUE_INDEX_THREE] = { 0 };
678 iss.get(hex, VALUE_INDEX_THREE);
679 std::string hexStr(hex);
680 if (IsValidHexValue(hexStr)) {
681 int decodedChar = std::stoi(hexStr, nullptr, DECODE_CHAR_MAX_SIZE);
682 oss << static_cast<char>(decodedChar);
683 } else {
684 TELEPHONY_LOGE("decoding QP failed");
685 }
686 } else {
687 oss << ch;
688 }
689 }
690 return oss.str();
691 }
692
BuildListFromValue(const std::string & value)693 std::vector<std::string> VCardDecoderV21::BuildListFromValue(const std::string &value)
694 {
695 std::vector<std::string> list;
696 std::string temp;
697 int32_t length = static_cast<int32_t>(value.length());
698 for (int i = 0; i < length; i++) {
699 auto ch = value[i];
700 if (ch == '\\' && i < length - 1) {
701 char nextCh = value[i + 1];
702 std::string unescapedStr = UnescapeChar(nextCh);
703 if (!unescapedStr.empty()) {
704 temp += unescapedStr;
705 i++;
706 continue;
707 }
708 temp += ch;
709 continue;
710 }
711 if (ch == ';') {
712 list.push_back(temp);
713 temp = "";
714 continue;
715 }
716 temp += ch;
717 }
718 list.push_back(temp);
719 return list;
720 }
721
DealAgent(std::shared_ptr<VCardRawData> rawData,int32_t & errorCode)722 void VCardDecoderV21::DealAgent(std::shared_ptr<VCardRawData> rawData, int32_t &errorCode)
723 {
724 if (rawData == nullptr) {
725 TELEPHONY_LOGE("rawData is nullptr!");
726 return;
727 }
728 if (VCardUtils::ToUpper(rawData->GetRawValue()).find("BEGIN : VCARD") != std::string::npos) {
729 TELEPHONY_LOGE("Agent data error");
730 errorCode = TELEPHONY_ERR_VCARD_FILE_INVALID;
731 return;
732 }
733 NotifyRawDataCreated(rawData);
734 }
735
GetBase64(const std::string & value,int32_t & errorCode)736 std::string VCardDecoderV21::GetBase64(const std::string &value, int32_t &errorCode)
737 {
738 std::string str;
739 str += value;
740 while (true) {
741 std::string line = PeekLine();
742 if (line[0] != ' ') {
743 break;
744 }
745 std::string nameUp = getUpperName(line);
746 if (ContainValue(nameUp, GetSupportType())) {
747 TELEPHONY_LOGI("GetBase64 contain vcard type");
748 break;
749 }
750 GetLine();
751 str += VCardUtils::Trim(line);
752 }
753 return str;
754 }
755
UnescapeText(const std::string & from)756 std::string VCardDecoderV21::UnescapeText(const std::string &from)
757 {
758 return from;
759 }
760
UnescapeChar(char ch)761 std::string VCardDecoderV21::UnescapeChar(char ch)
762 {
763 if (ch == '\\' || ch == ';' || ch == ':' || ch == ',') {
764 return std::string(1, ch);
765 }
766 return "";
767 }
768
GetPoMultiLine(const std::string & from)769 std::string VCardDecoderV21::GetPoMultiLine(const std::string &from)
770 {
771 std::string str;
772 str += from;
773 while (true) {
774 std::string line = PeekLine();
775 if ((line.empty())) {
776 break;
777 }
778 std::string name = getUpperName(line);
779 if (!name.empty()) {
780 break;
781 }
782 GetLine();
783 str += " " + line;
784 }
785 return str;
786 }
787
getUpperName(const std::string & line)788 std::string VCardDecoderV21::getUpperName(const std::string &line)
789 {
790 auto colonIndex = line.find(":");
791 auto semiColonIndex = line.find(";");
792 if (colonIndex != std::string::npos || semiColonIndex != std::string::npos) {
793 int32_t minIndex = static_cast<int32_t>(colonIndex);
794 if (colonIndex == std::string::npos) {
795 minIndex = static_cast<int32_t>(semiColonIndex);
796 } else if (semiColonIndex != std::string::npos) {
797 minIndex = std::min(colonIndex, semiColonIndex);
798 }
799 return VCardUtils::ToUpper(line.substr(0, minIndex));
800 }
801 return "";
802 }
803
IsAscChar(char ch)804 bool VCardDecoderV21::IsAscChar(char ch)
805 {
806 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
807 return true;
808 }
809 return false;
810 }
811
~VCardDecoderV21()812 VCardDecoderV21::~VCardDecoderV21()
813 {
814 fileUtils_.Close();
815 }
816
817 } // namespace Telephony
818 } // namespace OHOS
819