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 &params, 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 &paramValue, 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 &param, const std::string &paramValue, 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