1bc2ed2b3Sopenharmony_ci/* 2bc2ed2b3Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3bc2ed2b3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4bc2ed2b3Sopenharmony_ci * you may not use this file except in compliance with the License. 5bc2ed2b3Sopenharmony_ci * You may obtain a copy of the License at 6bc2ed2b3Sopenharmony_ci * 7bc2ed2b3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8bc2ed2b3Sopenharmony_ci * 9bc2ed2b3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10bc2ed2b3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11bc2ed2b3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12bc2ed2b3Sopenharmony_ci * See the License for the specific language governing permissions and 13bc2ed2b3Sopenharmony_ci * limitations under the License. 14bc2ed2b3Sopenharmony_ci */ 15bc2ed2b3Sopenharmony_ci#include "ndef_message.h" 16bc2ed2b3Sopenharmony_ci#include "loghelper.h" 17bc2ed2b3Sopenharmony_ci#include "nfc_sdk_common.h" 18bc2ed2b3Sopenharmony_ci 19bc2ed2b3Sopenharmony_cinamespace OHOS { 20bc2ed2b3Sopenharmony_cinamespace NFC { 21bc2ed2b3Sopenharmony_cinamespace KITS { 22bc2ed2b3Sopenharmony_ciusing KITS::NfcSdkCommon; 23bc2ed2b3Sopenharmony_ciNdefMessage::NdefMessage(std::vector<std::shared_ptr<NdefRecord>> ndefRecords) 24bc2ed2b3Sopenharmony_ci : ndefRecordList_(std::move(ndefRecords)) 25bc2ed2b3Sopenharmony_ci{ 26bc2ed2b3Sopenharmony_ci} 27bc2ed2b3Sopenharmony_ci 28bc2ed2b3Sopenharmony_ciNdefMessage::~NdefMessage() 29bc2ed2b3Sopenharmony_ci{ 30bc2ed2b3Sopenharmony_ci ndefRecordList_.clear(); 31bc2ed2b3Sopenharmony_ci} 32bc2ed2b3Sopenharmony_ci 33bc2ed2b3Sopenharmony_cistd::shared_ptr<NdefMessage> NdefMessage::GetNdefMessage(const std::string& data) 34bc2ed2b3Sopenharmony_ci{ 35bc2ed2b3Sopenharmony_ci std::vector<std::shared_ptr<NdefRecord>> ndefRecords = ParseRecord(data, false); 36bc2ed2b3Sopenharmony_ci if (ndefRecords.empty()) { 37bc2ed2b3Sopenharmony_ci ErrorLog("GetNdefMessage, ndefRecords invalid."); 38bc2ed2b3Sopenharmony_ci return std::shared_ptr<NdefMessage>(); 39bc2ed2b3Sopenharmony_ci } 40bc2ed2b3Sopenharmony_ci return GetNdefMessage(ndefRecords); 41bc2ed2b3Sopenharmony_ci} 42bc2ed2b3Sopenharmony_ci 43bc2ed2b3Sopenharmony_cistd::shared_ptr<NdefMessage> NdefMessage::GetNdefMessage(std::vector<std::shared_ptr<NdefRecord>> ndefRecords) 44bc2ed2b3Sopenharmony_ci{ 45bc2ed2b3Sopenharmony_ci return std::make_shared<NdefMessage>(std::move(ndefRecords)); 46bc2ed2b3Sopenharmony_ci} 47bc2ed2b3Sopenharmony_ci 48bc2ed2b3Sopenharmony_cistd::string NdefMessage::GetTagRtdType(EmRtdType rtdtype) 49bc2ed2b3Sopenharmony_ci{ 50bc2ed2b3Sopenharmony_ci std::string rtd; 51bc2ed2b3Sopenharmony_ci switch (rtdtype) { 52bc2ed2b3Sopenharmony_ci case EmRtdType::RTD_TEXT: 53bc2ed2b3Sopenharmony_ci rtd = "T"; // 0x54 54bc2ed2b3Sopenharmony_ci break; 55bc2ed2b3Sopenharmony_ci case EmRtdType::RTD_URI: 56bc2ed2b3Sopenharmony_ci rtd = "U"; // 0x55 57bc2ed2b3Sopenharmony_ci break; 58bc2ed2b3Sopenharmony_ci case EmRtdType::RTD_SMART_POSTER: 59bc2ed2b3Sopenharmony_ci rtd = "Sp"; // 0x53, 0x70 60bc2ed2b3Sopenharmony_ci break; 61bc2ed2b3Sopenharmony_ci case EmRtdType::RTD_ALTERNATIVE_CARRIER: 62bc2ed2b3Sopenharmony_ci rtd = "ac"; // 0x61, 0x63 63bc2ed2b3Sopenharmony_ci break; 64bc2ed2b3Sopenharmony_ci case EmRtdType::RTD_HANDOVER_CARRIER: 65bc2ed2b3Sopenharmony_ci rtd = "Hc"; // 0x48, 0x63 66bc2ed2b3Sopenharmony_ci break; 67bc2ed2b3Sopenharmony_ci case EmRtdType::RTD_HANDOVER_REQUEST: 68bc2ed2b3Sopenharmony_ci rtd = "Hr"; // 0x48, 0x72 69bc2ed2b3Sopenharmony_ci break; 70bc2ed2b3Sopenharmony_ci case EmRtdType::RTD_HANDOVER_SELECT: 71bc2ed2b3Sopenharmony_ci rtd = "Hs"; // 0x48, 0x73 72bc2ed2b3Sopenharmony_ci break; 73bc2ed2b3Sopenharmony_ci case EmRtdType::RTD_OHOS_APP: 74bc2ed2b3Sopenharmony_ci rtd = "ohos.com:pkg"; // "ohos.com:pkg" 75bc2ed2b3Sopenharmony_ci break; 76bc2ed2b3Sopenharmony_ci default: 77bc2ed2b3Sopenharmony_ci rtd.clear(); 78bc2ed2b3Sopenharmony_ci break; 79bc2ed2b3Sopenharmony_ci } 80bc2ed2b3Sopenharmony_ci return rtd; 81bc2ed2b3Sopenharmony_ci} 82bc2ed2b3Sopenharmony_ci 83bc2ed2b3Sopenharmony_cistd::vector<std::shared_ptr<NdefRecord>> NdefMessage::GetNdefRecords() const 84bc2ed2b3Sopenharmony_ci{ 85bc2ed2b3Sopenharmony_ci return ndefRecordList_; 86bc2ed2b3Sopenharmony_ci} 87bc2ed2b3Sopenharmony_ci 88bc2ed2b3Sopenharmony_cistd::shared_ptr<NdefRecord> NdefMessage::MakeUriRecord(const std::string& uriString) 89bc2ed2b3Sopenharmony_ci{ 90bc2ed2b3Sopenharmony_ci if (uriString.empty()) { 91bc2ed2b3Sopenharmony_ci ErrorLog("MakeUriRecord, uriString invalid."); 92bc2ed2b3Sopenharmony_ci return std::shared_ptr<NdefRecord>(); 93bc2ed2b3Sopenharmony_ci } 94bc2ed2b3Sopenharmony_ci 95bc2ed2b3Sopenharmony_ci std::string payload = "00"; 96bc2ed2b3Sopenharmony_ci std::string uri = uriString; 97bc2ed2b3Sopenharmony_ci for (size_t i = 1; i < g_uriPrefix.size() - 1; i++) { 98bc2ed2b3Sopenharmony_ci if (!uriString.compare(0, g_uriPrefix[i].size(), g_uriPrefix[i])) { 99bc2ed2b3Sopenharmony_ci payload = NfcSdkCommon::UnsignedCharToHexString(i & 0xFF); 100bc2ed2b3Sopenharmony_ci uri = uriString.substr(g_uriPrefix[i].size()); 101bc2ed2b3Sopenharmony_ci break; 102bc2ed2b3Sopenharmony_ci } 103bc2ed2b3Sopenharmony_ci } 104bc2ed2b3Sopenharmony_ci 105bc2ed2b3Sopenharmony_ci payload += NfcSdkCommon::StringToHexString(uri); 106bc2ed2b3Sopenharmony_ci 107bc2ed2b3Sopenharmony_ci std::string id = ""; 108bc2ed2b3Sopenharmony_ci std::string tagRtdType = NfcSdkCommon::StringToHexString(GetTagRtdType(EmRtdType::RTD_URI)); 109bc2ed2b3Sopenharmony_ci return CreateNdefRecord(TNF_WELL_KNOWN, id, payload, tagRtdType); 110bc2ed2b3Sopenharmony_ci} 111bc2ed2b3Sopenharmony_ci 112bc2ed2b3Sopenharmony_cistd::shared_ptr<NdefRecord> NdefMessage::MakeTextRecord(const std::string& text, const std::string& locale) 113bc2ed2b3Sopenharmony_ci{ 114bc2ed2b3Sopenharmony_ci std::string tagRtdType = NfcSdkCommon::StringToHexString(GetTagRtdType(EmRtdType::RTD_TEXT)); 115bc2ed2b3Sopenharmony_ci std::string id = ""; 116bc2ed2b3Sopenharmony_ci int localeLen = locale.size() & 0xFF; 117bc2ed2b3Sopenharmony_ci std::string payload = NfcSdkCommon::UnsignedCharToHexString(localeLen); 118bc2ed2b3Sopenharmony_ci payload += NfcSdkCommon::StringToHexString(locale); 119bc2ed2b3Sopenharmony_ci payload += NfcSdkCommon::StringToHexString(text); 120bc2ed2b3Sopenharmony_ci return CreateNdefRecord(TNF_WELL_KNOWN, id, payload, tagRtdType); 121bc2ed2b3Sopenharmony_ci} 122bc2ed2b3Sopenharmony_ci 123bc2ed2b3Sopenharmony_cistd::shared_ptr<NdefRecord> NdefMessage::MakeMimeRecord(const std::string& mimeType, const std::string& mimeData) 124bc2ed2b3Sopenharmony_ci{ 125bc2ed2b3Sopenharmony_ci if (mimeType.empty() || mimeData.empty()) { 126bc2ed2b3Sopenharmony_ci ErrorLog("MakeMimeRecord, mimeType or mimeData invalid."); 127bc2ed2b3Sopenharmony_ci return std::shared_ptr<NdefRecord>(); 128bc2ed2b3Sopenharmony_ci } 129bc2ed2b3Sopenharmony_ci std::string id = ""; 130bc2ed2b3Sopenharmony_ci size_t t = mimeType.find_first_of('/'); 131bc2ed2b3Sopenharmony_ci if (t == 0 || t == (mimeType.size() - 1)) { 132bc2ed2b3Sopenharmony_ci ErrorLog("MakeMimeRecord, mimeType should have major and minor type if '/' exists."); 133bc2ed2b3Sopenharmony_ci return std::shared_ptr<NdefRecord>(); 134bc2ed2b3Sopenharmony_ci } 135bc2ed2b3Sopenharmony_ci return CreateNdefRecord(TNF_MIME_MEDIA, id, mimeData, NfcSdkCommon::StringToHexString(mimeType)); 136bc2ed2b3Sopenharmony_ci} 137bc2ed2b3Sopenharmony_ci 138bc2ed2b3Sopenharmony_cistd::shared_ptr<NdefRecord> NdefMessage::MakeExternalRecord(const std::string& domainName, 139bc2ed2b3Sopenharmony_ci const std::string& serviceName, 140bc2ed2b3Sopenharmony_ci const std::string& externalData) 141bc2ed2b3Sopenharmony_ci{ 142bc2ed2b3Sopenharmony_ci if (domainName.empty() || serviceName.empty() || externalData.empty()) { 143bc2ed2b3Sopenharmony_ci ErrorLog("MakeExternalRecord, domainName or serviceName invalid."); 144bc2ed2b3Sopenharmony_ci return std::shared_ptr<NdefRecord>(); 145bc2ed2b3Sopenharmony_ci } 146bc2ed2b3Sopenharmony_ci 147bc2ed2b3Sopenharmony_ci std::string domain = domainName; 148bc2ed2b3Sopenharmony_ci std::string service = serviceName; 149bc2ed2b3Sopenharmony_ci domain.erase(0, domain.find_first_not_of("\r\t\n ")); 150bc2ed2b3Sopenharmony_ci domain.erase(domain.find_last_not_of("\r\t\n ") + 1); 151bc2ed2b3Sopenharmony_ci transform(domain.begin(), domain.end(), domain.begin(), ::tolower); 152bc2ed2b3Sopenharmony_ci service.erase(0, service.find_first_not_of("\r\t\n ")); 153bc2ed2b3Sopenharmony_ci service.erase(service.find_last_not_of("\r\t\n ") + 1); 154bc2ed2b3Sopenharmony_ci transform(service.begin(), service.end(), service.begin(), ::tolower); 155bc2ed2b3Sopenharmony_ci 156bc2ed2b3Sopenharmony_ci if (domain.empty() || service.empty()) { 157bc2ed2b3Sopenharmony_ci return std::shared_ptr<NdefRecord>(); 158bc2ed2b3Sopenharmony_ci } 159bc2ed2b3Sopenharmony_ci 160bc2ed2b3Sopenharmony_ci std::string tagRtdType = NfcSdkCommon::StringToHexString(domain + ":" + service); 161bc2ed2b3Sopenharmony_ci std::string id = ""; 162bc2ed2b3Sopenharmony_ci 163bc2ed2b3Sopenharmony_ci return CreateNdefRecord(TNF_EXTERNAL_TYPE, id, externalData, tagRtdType); 164bc2ed2b3Sopenharmony_ci} 165bc2ed2b3Sopenharmony_ci 166bc2ed2b3Sopenharmony_cistd::string NdefMessage::MessageToString(std::weak_ptr<NdefMessage> ndefMessage) 167bc2ed2b3Sopenharmony_ci{ 168bc2ed2b3Sopenharmony_ci std::string buffer; 169bc2ed2b3Sopenharmony_ci if (ndefMessage.expired()) { 170bc2ed2b3Sopenharmony_ci ErrorLog("MessageToString, ndefMessage invalid."); 171bc2ed2b3Sopenharmony_ci return buffer; 172bc2ed2b3Sopenharmony_ci } 173bc2ed2b3Sopenharmony_ci for (size_t i = 0; i < ndefMessage.lock()->ndefRecordList_.size(); i++) { 174bc2ed2b3Sopenharmony_ci bool bIsMB = (i == 0); // first record 175bc2ed2b3Sopenharmony_ci bool bIsME = (i == ndefMessage.lock()->ndefRecordList_.size() - 1); // last record 176bc2ed2b3Sopenharmony_ci NdefRecordToString(ndefMessage.lock()->ndefRecordList_.at(i), buffer, bIsMB, bIsME); 177bc2ed2b3Sopenharmony_ci } 178bc2ed2b3Sopenharmony_ci return buffer; 179bc2ed2b3Sopenharmony_ci} 180bc2ed2b3Sopenharmony_ci 181bc2ed2b3Sopenharmony_civoid NdefMessage::NdefRecordToString(std::weak_ptr<NdefRecord> record, std::string& buffer, bool bIsMB, bool bIsME) 182bc2ed2b3Sopenharmony_ci{ 183bc2ed2b3Sopenharmony_ci if (record.expired()) { 184bc2ed2b3Sopenharmony_ci ErrorLog("NdefRecordToString, record invalid."); 185bc2ed2b3Sopenharmony_ci return; 186bc2ed2b3Sopenharmony_ci } 187bc2ed2b3Sopenharmony_ci std::string payload = record.lock()->payload_; 188bc2ed2b3Sopenharmony_ci uint32_t tnf = record.lock()->tnf_; 189bc2ed2b3Sopenharmony_ci std::string id = record.lock()->id_; 190bc2ed2b3Sopenharmony_ci std::string rtdType = record.lock()->tagRtdType_; 191bc2ed2b3Sopenharmony_ci bool sr = NfcSdkCommon::GetHexStrBytesLen(payload) < SHORT_RECORD_SIZE; 192bc2ed2b3Sopenharmony_ci bool il = (tnf == TNF_EMPTY) ? true : (NfcSdkCommon::GetHexStrBytesLen(id) > 0); 193bc2ed2b3Sopenharmony_ci unsigned char flag = (unsigned char)((bIsMB ? FLAG_MB : 0) | (bIsME ? FLAG_ME : 0) 194bc2ed2b3Sopenharmony_ci | (sr ? FLAG_SR : 0) | (il ? FLAG_IL : 0)) | (char)tnf; 195bc2ed2b3Sopenharmony_ci buffer.append(NfcSdkCommon::UnsignedCharToHexString(flag)); 196bc2ed2b3Sopenharmony_ci buffer.append(NfcSdkCommon::IntToHexString(NfcSdkCommon::GetHexStrBytesLen(rtdType))); 197bc2ed2b3Sopenharmony_ci if (sr) { 198bc2ed2b3Sopenharmony_ci buffer.append(NfcSdkCommon::IntToHexString(NfcSdkCommon::GetHexStrBytesLen(payload))); 199bc2ed2b3Sopenharmony_ci } else { 200bc2ed2b3Sopenharmony_ci buffer.append(NfcSdkCommon::IntToHexString(NfcSdkCommon::GetHexStrBytesLen(payload))); 201bc2ed2b3Sopenharmony_ci } 202bc2ed2b3Sopenharmony_ci if (il) { 203bc2ed2b3Sopenharmony_ci buffer.append(NfcSdkCommon::IntToHexString(NfcSdkCommon::GetHexStrBytesLen(id))); 204bc2ed2b3Sopenharmony_ci } 205bc2ed2b3Sopenharmony_ci 206bc2ed2b3Sopenharmony_ci buffer.append(rtdType); 207bc2ed2b3Sopenharmony_ci buffer.append(id); 208bc2ed2b3Sopenharmony_ci buffer.append(payload); 209bc2ed2b3Sopenharmony_ci} 210bc2ed2b3Sopenharmony_ci 211bc2ed2b3Sopenharmony_civoid NdefMessage::ParseRecordLayoutHead(RecordLayout& layout, unsigned char head) 212bc2ed2b3Sopenharmony_ci{ 213bc2ed2b3Sopenharmony_ci layout.mb = (head & FLAG_MB) != 0; 214bc2ed2b3Sopenharmony_ci layout.me = (head & FLAG_ME) != 0; 215bc2ed2b3Sopenharmony_ci layout.cf = (head & FLAG_CF) != 0; 216bc2ed2b3Sopenharmony_ci layout.sr = (head & FLAG_SR) != 0; 217bc2ed2b3Sopenharmony_ci layout.il = (head & FLAG_IL) != 0; 218bc2ed2b3Sopenharmony_ci layout.tnf = static_cast<short>(head & FLAG_TNF); 219bc2ed2b3Sopenharmony_ci} 220bc2ed2b3Sopenharmony_ci 221bc2ed2b3Sopenharmony_cibool NdefMessage::IsInvalidRecordLayoutHead(RecordLayout& layout, bool isChunkFound, 222bc2ed2b3Sopenharmony_ci uint32_t parsedRecordSize, bool isMbMeIgnored) 223bc2ed2b3Sopenharmony_ci{ 224bc2ed2b3Sopenharmony_ci if (!layout.mb && parsedRecordSize == 0 && !isChunkFound && !isMbMeIgnored) { 225bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, 1st error for mb and size."); 226bc2ed2b3Sopenharmony_ci return true; 227bc2ed2b3Sopenharmony_ci } else if (layout.mb && (parsedRecordSize != 0 || isChunkFound) && !isMbMeIgnored) { 228bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, 2nd error for mb and size"); 229bc2ed2b3Sopenharmony_ci return true; 230bc2ed2b3Sopenharmony_ci } else if (isChunkFound && layout.il) { 231bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, 3rd error for il"); 232bc2ed2b3Sopenharmony_ci return true; 233bc2ed2b3Sopenharmony_ci } else if (layout.cf && layout.me) { 234bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, 4th error for cf and me"); 235bc2ed2b3Sopenharmony_ci return true; 236bc2ed2b3Sopenharmony_ci } else if (isChunkFound && layout.tnf != TNF_UNCHANGED) { 237bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, 5th error for tnf"); 238bc2ed2b3Sopenharmony_ci return true; 239bc2ed2b3Sopenharmony_ci } else if (!isChunkFound && layout.tnf == TNF_UNCHANGED) { 240bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, 6th error for tnf"); 241bc2ed2b3Sopenharmony_ci return true; 242bc2ed2b3Sopenharmony_ci } 243bc2ed2b3Sopenharmony_ci return false; 244bc2ed2b3Sopenharmony_ci} 245bc2ed2b3Sopenharmony_ci 246bc2ed2b3Sopenharmony_civoid NdefMessage::ParseRecordLayoutLength(RecordLayout& layout, bool isChunkFound, 247bc2ed2b3Sopenharmony_ci const std::string& data, uint32_t& parsedDataIndex) 248bc2ed2b3Sopenharmony_ci{ 249bc2ed2b3Sopenharmony_ci layout.typeLength = NfcSdkCommon::GetByteFromHexStr(data, parsedDataIndex++) & 0xFF; 250bc2ed2b3Sopenharmony_ci if (layout.sr) { 251bc2ed2b3Sopenharmony_ci layout.payloadLength = NfcSdkCommon::GetByteFromHexStr(data, parsedDataIndex++) & 0xFF; 252bc2ed2b3Sopenharmony_ci } else { 253bc2ed2b3Sopenharmony_ci if (NfcSdkCommon::GetHexStrBytesLen(data) < parsedDataIndex + int(sizeof(int))) { 254bc2ed2b3Sopenharmony_ci layout.payloadLength = 0; 255bc2ed2b3Sopenharmony_ci } else { 256bc2ed2b3Sopenharmony_ci std::string lenString = data.substr(parsedDataIndex * HEX_BYTE_LEN, sizeof(int) * HEX_BYTE_LEN); 257bc2ed2b3Sopenharmony_ci layout.payloadLength = 0; 258bc2ed2b3Sopenharmony_ci for (unsigned int i = 0; i < sizeof(int); i++) { 259bc2ed2b3Sopenharmony_ci layout.payloadLength += 260bc2ed2b3Sopenharmony_ci (NfcSdkCommon::GetByteFromHexStr(lenString, i) << ((sizeof(int) - i - 1) * ONE_BYTE_SHIFT)); 261bc2ed2b3Sopenharmony_ci } 262bc2ed2b3Sopenharmony_ci parsedDataIndex += sizeof(int); 263bc2ed2b3Sopenharmony_ci } 264bc2ed2b3Sopenharmony_ci } 265bc2ed2b3Sopenharmony_ci layout.idLength = layout.il ? (NfcSdkCommon::GetByteFromHexStr(data, parsedDataIndex++) & 0xFF) : 0; 266bc2ed2b3Sopenharmony_ci} 267bc2ed2b3Sopenharmony_ci 268bc2ed2b3Sopenharmony_cibool NdefMessage::IsRecordLayoutLengthInvalid(RecordLayout& layout, bool isChunkFound) 269bc2ed2b3Sopenharmony_ci{ 270bc2ed2b3Sopenharmony_ci // for the middle chunks record, need the type length is zero. 271bc2ed2b3Sopenharmony_ci if (isChunkFound && layout.typeLength != 0) { 272bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, 1st error for typeLength"); 273bc2ed2b3Sopenharmony_ci return true; 274bc2ed2b3Sopenharmony_ci } 275bc2ed2b3Sopenharmony_ci 276bc2ed2b3Sopenharmony_ci // for the first chunk, expected has type. 277bc2ed2b3Sopenharmony_ci if (layout.cf && !isChunkFound) { 278bc2ed2b3Sopenharmony_ci if (layout.typeLength == 0 && layout.tnf != TNF_UNKNOWN) { 279bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, 2nd error for typeLength and tnf"); 280bc2ed2b3Sopenharmony_ci return true; 281bc2ed2b3Sopenharmony_ci } 282bc2ed2b3Sopenharmony_ci } 283bc2ed2b3Sopenharmony_ci 284bc2ed2b3Sopenharmony_ci if (layout.payloadLength > MAX_PAYLOAD_SIZE) { 285bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, 3rd error for payloadLength"); 286bc2ed2b3Sopenharmony_ci return true; 287bc2ed2b3Sopenharmony_ci } 288bc2ed2b3Sopenharmony_ci return false; 289bc2ed2b3Sopenharmony_ci} 290bc2ed2b3Sopenharmony_ci 291bc2ed2b3Sopenharmony_cistd::string NdefMessage::ParseRecordType(RecordLayout& layout, const std::string& data, uint32_t& parsedDataIndex) 292bc2ed2b3Sopenharmony_ci{ 293bc2ed2b3Sopenharmony_ci if (layout.typeLength <= 0) { 294bc2ed2b3Sopenharmony_ci ErrorLog("IsInvalidRecordLayoutHead, typeLength less than 0."); 295bc2ed2b3Sopenharmony_ci return ""; 296bc2ed2b3Sopenharmony_ci } 297bc2ed2b3Sopenharmony_ci if (NfcSdkCommon::GetHexStrBytesLen(data) < parsedDataIndex + layout.typeLength) { 298bc2ed2b3Sopenharmony_ci ErrorLog("data len.%{public}d index.%{public}d rtdtype len.%{public}d error", 299bc2ed2b3Sopenharmony_ci NfcSdkCommon::GetHexStrBytesLen(data), parsedDataIndex, layout.typeLength); 300bc2ed2b3Sopenharmony_ci return ""; 301bc2ed2b3Sopenharmony_ci } 302bc2ed2b3Sopenharmony_ci std::string type = data.substr(parsedDataIndex * HEX_BYTE_LEN, layout.typeLength * HEX_BYTE_LEN); 303bc2ed2b3Sopenharmony_ci parsedDataIndex += layout.typeLength; 304bc2ed2b3Sopenharmony_ci return type; 305bc2ed2b3Sopenharmony_ci} 306bc2ed2b3Sopenharmony_ci 307bc2ed2b3Sopenharmony_cistd::string NdefMessage::ParseRecordId(RecordLayout& layout, const std::string& data, uint32_t& parsedDataIndex) 308bc2ed2b3Sopenharmony_ci{ 309bc2ed2b3Sopenharmony_ci if (layout.idLength <= 0) { 310bc2ed2b3Sopenharmony_ci ErrorLog("ParseRecordId, idLength <= 0"); 311bc2ed2b3Sopenharmony_ci return ""; 312bc2ed2b3Sopenharmony_ci } 313bc2ed2b3Sopenharmony_ci if (NfcSdkCommon::GetHexStrBytesLen(data) < parsedDataIndex + layout.idLength) { 314bc2ed2b3Sopenharmony_ci ErrorLog("data len.%{public}d index.%{public}d id len.%{public}d error", 315bc2ed2b3Sopenharmony_ci NfcSdkCommon::GetHexStrBytesLen(data), parsedDataIndex, layout.idLength); 316bc2ed2b3Sopenharmony_ci return ""; 317bc2ed2b3Sopenharmony_ci } 318bc2ed2b3Sopenharmony_ci std::string id = data.substr(parsedDataIndex * HEX_BYTE_LEN, layout.idLength * HEX_BYTE_LEN); 319bc2ed2b3Sopenharmony_ci parsedDataIndex += layout.idLength; 320bc2ed2b3Sopenharmony_ci return id; 321bc2ed2b3Sopenharmony_ci} 322bc2ed2b3Sopenharmony_ci 323bc2ed2b3Sopenharmony_cistd::string NdefMessage::ParseRecordPayload(RecordLayout& layout, const std::string& data, uint32_t& parsedDataIndex) 324bc2ed2b3Sopenharmony_ci{ 325bc2ed2b3Sopenharmony_ci if (layout.payloadLength <= 0) { 326bc2ed2b3Sopenharmony_ci ErrorLog("ParseRecordPayload, payloadLength <= 0"); 327bc2ed2b3Sopenharmony_ci return ""; 328bc2ed2b3Sopenharmony_ci } 329bc2ed2b3Sopenharmony_ci if (NfcSdkCommon::GetHexStrBytesLen(data) < (parsedDataIndex + layout.payloadLength)) { 330bc2ed2b3Sopenharmony_ci ErrorLog("data len.%{public}d index.%{public}d payload len.%{public}d error", 331bc2ed2b3Sopenharmony_ci NfcSdkCommon::GetHexStrBytesLen(data), parsedDataIndex, layout.payloadLength); 332bc2ed2b3Sopenharmony_ci return ""; 333bc2ed2b3Sopenharmony_ci } 334bc2ed2b3Sopenharmony_ci std::string payload = data.substr(parsedDataIndex * HEX_BYTE_LEN, layout.payloadLength * HEX_BYTE_LEN); 335bc2ed2b3Sopenharmony_ci parsedDataIndex += layout.payloadLength; 336bc2ed2b3Sopenharmony_ci return payload; 337bc2ed2b3Sopenharmony_ci} 338bc2ed2b3Sopenharmony_ci 339bc2ed2b3Sopenharmony_civoid NdefMessage::SaveRecordChunks(RecordLayout& layout, bool isChunkFound, 340bc2ed2b3Sopenharmony_ci std::vector<std::string>& chunks, char& chunkTnf, const std::string& payload) 341bc2ed2b3Sopenharmony_ci{ 342bc2ed2b3Sopenharmony_ci // handle for the first chunk. 343bc2ed2b3Sopenharmony_ci if (layout.cf && !isChunkFound) { 344bc2ed2b3Sopenharmony_ci chunks.clear(); 345bc2ed2b3Sopenharmony_ci chunkTnf = layout.tnf; 346bc2ed2b3Sopenharmony_ci } 347bc2ed2b3Sopenharmony_ci 348bc2ed2b3Sopenharmony_ci // save the payload for all(first/middle/last) chunk. 349bc2ed2b3Sopenharmony_ci if (layout.cf || isChunkFound) { 350bc2ed2b3Sopenharmony_ci chunks.push_back(payload); 351bc2ed2b3Sopenharmony_ci } 352bc2ed2b3Sopenharmony_ci} 353bc2ed2b3Sopenharmony_ci 354bc2ed2b3Sopenharmony_cistd::string NdefMessage::MergePayloadByChunks(RecordLayout& layout, bool isChunkFound, 355bc2ed2b3Sopenharmony_ci std::vector<std::string>& chunks, char chunkTnf, const std::string& payload) 356bc2ed2b3Sopenharmony_ci{ 357bc2ed2b3Sopenharmony_ci // it's the last chunk, merge the payload for NdefRecord. 358bc2ed2b3Sopenharmony_ci if (!layout.cf && isChunkFound) { 359bc2ed2b3Sopenharmony_ci std::string mergedPayload; 360bc2ed2b3Sopenharmony_ci for (std::string n : chunks) { 361bc2ed2b3Sopenharmony_ci mergedPayload += n; 362bc2ed2b3Sopenharmony_ci } 363bc2ed2b3Sopenharmony_ci layout.tnf = chunkTnf; 364bc2ed2b3Sopenharmony_ci return mergedPayload; 365bc2ed2b3Sopenharmony_ci } 366bc2ed2b3Sopenharmony_ci return payload; 367bc2ed2b3Sopenharmony_ci} 368bc2ed2b3Sopenharmony_ci 369bc2ed2b3Sopenharmony_cistd::shared_ptr<NdefRecord> NdefMessage::CreateNdefRecord(short tnf, const std::string& id, 370bc2ed2b3Sopenharmony_ci const std::string& payload, const std::string& tagRtdType) 371bc2ed2b3Sopenharmony_ci{ 372bc2ed2b3Sopenharmony_ci bool isValidTnf = CheckTnf(tnf, tagRtdType, id, payload); 373bc2ed2b3Sopenharmony_ci if (!isValidTnf) { 374bc2ed2b3Sopenharmony_ci ErrorLog("CreateNdefRecord, isValidTnf failed."); 375bc2ed2b3Sopenharmony_ci return std::shared_ptr<NdefRecord>(); 376bc2ed2b3Sopenharmony_ci } 377bc2ed2b3Sopenharmony_ci std::shared_ptr<NdefRecord> ndefRecord = std::make_shared<NdefRecord>(); 378bc2ed2b3Sopenharmony_ci ndefRecord->tnf_ = tnf; 379bc2ed2b3Sopenharmony_ci ndefRecord->id_ = id; 380bc2ed2b3Sopenharmony_ci ndefRecord->payload_ = payload; 381bc2ed2b3Sopenharmony_ci ndefRecord->tagRtdType_ = tagRtdType; 382bc2ed2b3Sopenharmony_ci return ndefRecord; 383bc2ed2b3Sopenharmony_ci} 384bc2ed2b3Sopenharmony_ci 385bc2ed2b3Sopenharmony_cibool NdefMessage::CheckTnf(short tnf, const std::string& tagRtdType, const std::string& id, const std::string& payload) 386bc2ed2b3Sopenharmony_ci{ 387bc2ed2b3Sopenharmony_ci switch (tnf) { 388bc2ed2b3Sopenharmony_ci case TNF_EMPTY: 389bc2ed2b3Sopenharmony_ci if (!tagRtdType.empty() || !id.empty() || !payload.empty()) { 390bc2ed2b3Sopenharmony_ci ErrorLog("CheckTnf, TNF_EMPTY error."); 391bc2ed2b3Sopenharmony_ci return false; 392bc2ed2b3Sopenharmony_ci } 393bc2ed2b3Sopenharmony_ci break; 394bc2ed2b3Sopenharmony_ci case TNF_WELL_KNOWN: 395bc2ed2b3Sopenharmony_ci case TNF_MIME_MEDIA: 396bc2ed2b3Sopenharmony_ci case TNF_ABSOLUTE_URI: 397bc2ed2b3Sopenharmony_ci case TNF_EXTERNAL_TYPE: 398bc2ed2b3Sopenharmony_ci return true; 399bc2ed2b3Sopenharmony_ci case TNF_UNKNOWN: 400bc2ed2b3Sopenharmony_ci case TNF_RESERVED: 401bc2ed2b3Sopenharmony_ci if (tagRtdType.empty()) { 402bc2ed2b3Sopenharmony_ci return false; 403bc2ed2b3Sopenharmony_ci } 404bc2ed2b3Sopenharmony_ci return true; 405bc2ed2b3Sopenharmony_ci case TNF_UNCHANGED: 406bc2ed2b3Sopenharmony_ci return false; 407bc2ed2b3Sopenharmony_ci default: 408bc2ed2b3Sopenharmony_ci break; 409bc2ed2b3Sopenharmony_ci } 410bc2ed2b3Sopenharmony_ci return false; 411bc2ed2b3Sopenharmony_ci} 412bc2ed2b3Sopenharmony_ci 413bc2ed2b3Sopenharmony_cistd::vector<std::shared_ptr<NdefRecord>> NdefMessage::ParseRecord(const std::string& data, bool isMbMeIgnored) 414bc2ed2b3Sopenharmony_ci{ 415bc2ed2b3Sopenharmony_ci std::vector<std::shared_ptr<NdefRecord>> recordList; 416bc2ed2b3Sopenharmony_ci if (data.empty()) { 417bc2ed2b3Sopenharmony_ci ErrorLog("ParseRecord, raw data empty."); 418bc2ed2b3Sopenharmony_ci return recordList; 419bc2ed2b3Sopenharmony_ci } 420bc2ed2b3Sopenharmony_ci 421bc2ed2b3Sopenharmony_ci std::string tagRtdType; 422bc2ed2b3Sopenharmony_ci std::string id; 423bc2ed2b3Sopenharmony_ci std::vector<std::string> chunks; 424bc2ed2b3Sopenharmony_ci bool isChunkFound = false; 425bc2ed2b3Sopenharmony_ci char chunkTnf = 0; 426bc2ed2b3Sopenharmony_ci bool isMessageEnd = false; 427bc2ed2b3Sopenharmony_ci uint32_t parsedDataIndex = 0; 428bc2ed2b3Sopenharmony_ci while (!isMessageEnd) { 429bc2ed2b3Sopenharmony_ci RecordLayout layout; 430bc2ed2b3Sopenharmony_ci ParseRecordLayoutHead(layout, NfcSdkCommon::GetByteFromHexStr(data, parsedDataIndex++)); 431bc2ed2b3Sopenharmony_ci isMessageEnd = layout.me; 432bc2ed2b3Sopenharmony_ci 433bc2ed2b3Sopenharmony_ci if (data.size() / HEX_BYTE_LEN < parsedDataIndex) { 434bc2ed2b3Sopenharmony_ci return recordList; 435bc2ed2b3Sopenharmony_ci } 436bc2ed2b3Sopenharmony_ci if ((data.size() / HEX_BYTE_LEN - parsedDataIndex) < MIN_RECORD_LEN && !isMessageEnd) { 437bc2ed2b3Sopenharmony_ci return recordList; 438bc2ed2b3Sopenharmony_ci } 439bc2ed2b3Sopenharmony_ci if (IsInvalidRecordLayoutHead(layout, isChunkFound, recordList.size(), isMbMeIgnored)) { 440bc2ed2b3Sopenharmony_ci return recordList; 441bc2ed2b3Sopenharmony_ci } 442bc2ed2b3Sopenharmony_ci 443bc2ed2b3Sopenharmony_ci ParseRecordLayoutLength(layout, isChunkFound, data, parsedDataIndex); 444bc2ed2b3Sopenharmony_ci 445bc2ed2b3Sopenharmony_ci if (IsRecordLayoutLengthInvalid(layout, isChunkFound)) { 446bc2ed2b3Sopenharmony_ci return recordList; 447bc2ed2b3Sopenharmony_ci } 448bc2ed2b3Sopenharmony_ci 449bc2ed2b3Sopenharmony_ci if (!isChunkFound) { 450bc2ed2b3Sopenharmony_ci // don't parse the type and id for the middle chunks record, allowed them tobe empty. 451bc2ed2b3Sopenharmony_ci tagRtdType = ParseRecordType(layout, data, parsedDataIndex); 452bc2ed2b3Sopenharmony_ci id = ParseRecordId(layout, data, parsedDataIndex); 453bc2ed2b3Sopenharmony_ci } 454bc2ed2b3Sopenharmony_ci 455bc2ed2b3Sopenharmony_ci // parse the payload. 456bc2ed2b3Sopenharmony_ci std::string payload = ParseRecordPayload(layout, data, parsedDataIndex); 457bc2ed2b3Sopenharmony_ci SaveRecordChunks(layout, isChunkFound, chunks, chunkTnf, payload); 458bc2ed2b3Sopenharmony_ci payload = MergePayloadByChunks(layout, isChunkFound, chunks, chunkTnf, payload); 459bc2ed2b3Sopenharmony_ci if (NfcSdkCommon::GetHexStrBytesLen(payload) > MAX_PAYLOAD_SIZE) { 460bc2ed2b3Sopenharmony_ci ErrorLog("ParseRecord, payload > MAX_PAYLOAD_SIZE"); 461bc2ed2b3Sopenharmony_ci return recordList; 462bc2ed2b3Sopenharmony_ci } 463bc2ed2b3Sopenharmony_ci 464bc2ed2b3Sopenharmony_ci // if not the last chunk, continue to parse again. 465bc2ed2b3Sopenharmony_ci isChunkFound = layout.cf; 466bc2ed2b3Sopenharmony_ci if (isChunkFound) { 467bc2ed2b3Sopenharmony_ci continue; 468bc2ed2b3Sopenharmony_ci } 469bc2ed2b3Sopenharmony_ci 470bc2ed2b3Sopenharmony_ci // all chunks parsed end, add a new NdefRecord. 471bc2ed2b3Sopenharmony_ci std::shared_ptr<NdefRecord> record = CreateNdefRecord(layout.tnf, id, payload, tagRtdType); 472bc2ed2b3Sopenharmony_ci recordList.push_back(record); 473bc2ed2b3Sopenharmony_ci 474bc2ed2b3Sopenharmony_ci // isMbMeIgnored is true, means that single record need tobe parsed. 475bc2ed2b3Sopenharmony_ci if (isMbMeIgnored) { 476bc2ed2b3Sopenharmony_ci break; 477bc2ed2b3Sopenharmony_ci } 478bc2ed2b3Sopenharmony_ci } 479bc2ed2b3Sopenharmony_ci return recordList; 480bc2ed2b3Sopenharmony_ci} 481bc2ed2b3Sopenharmony_ci} // namespace KITS 482bc2ed2b3Sopenharmony_ci} // namespace NFC 483bc2ed2b3Sopenharmony_ci} // namespace OHOS 484