1 /* 2 * Copyright (C) 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 #ifndef NDEF_MESSAGE_H 16 #define NDEF_MESSAGE_H 17 18 #include <array> 19 #include <string> 20 #include <vector> 21 22 namespace OHOS { 23 namespace NFC { 24 namespace KITS { 25 // record data, see NFC Data Exchange Format (NDEF) Technical Specification. 26 struct NdefRecord { 27 short tnf_; 28 std::string id_; // hex string, 0x00~0xFF 29 std::string payload_; // hex string, 0x00~0xFF 30 std::string tagRtdType_; // hex string, 0x00~0xFF 31 }; 32 33 // layout, see NFC Data Exchange Format (NDEF) Technical Specification. 34 struct RecordLayout { 35 bool mb; // message begin 36 bool me; // message end 37 bool cf; // chunk flag 38 bool sr; // short record 39 bool il; // id length 40 short tnf; // type name format 41 uint16_t typeLength; 42 uint32_t payloadLength; 43 uint16_t idLength; 44 }; 45 46 // URI charactor code defined by NFC Forum 47 static const size_t MAX_URI_CODE_NUM = 0x24; 48 static std::array<std::string, MAX_URI_CODE_NUM> g_uriPrefix = { 49 "", // NFC Forum define value: 0x00 50 "http://www.", // NFC Forum define value: 0x01 51 "https://www.", // NFC Forum define value: 0x02 52 "http://", // NFC Forum define value: 0x03 53 "https://", // NFC Forum define value: 0x04 54 "tel:", // NFC Forum define value: 0x05 55 "mailto:", // NFC Forum define value: 0x06 56 "ftp://anonymous:anonymous@", // NFC Forum define value: 0x07 57 "ftp://ftp.", // NFC Forum define value: 0x08 58 "ftps://", // NFC Forum define value: 0x09 59 "sftp://", // NFC Forum define value: 0x0A 60 "smb://", // NFC Forum define value: 0x0B 61 "nfs://", // NFC Forum define value: 0x0C 62 "ftp://", // NFC Forum define value: 0x0D 63 "dav://", // NFC Forum define value: 0x0E 64 "news:", // NFC Forum define value: 0x0F 65 "telnet://", // NFC Forum define value: 0x10 66 "imap:", // NFC Forum define value: 0x11 67 "rtsp://", // NFC Forum define value: 0x12 68 "urn:", // NFC Forum define value: 0x13 69 "pop:", // NFC Forum define value: 0x14 70 "sip:", // NFC Forum define value: 0x15 71 "sips:", // NFC Forum define value: 0x16 72 "tftp:", // NFC Forum define value: 0x17 73 "btspp://", // NFC Forum define value: 0x18 74 "btl2cap://", // NFC Forum define value: 0x19 75 "btgoep://", // NFC Forum define value: 0x1A 76 "tcpobex://", // NFC Forum define value: 0x1B 77 "irdaobex://", // NFC Forum define value: 0x1C 78 "file://", // NFC Forum define value: 0x1D 79 "urn:epc:id:", // NFC Forum define value: 0x1E 80 "urn:epc:tag:", // NFC Forum define value: 0x1F 81 "urn:epc:pat:", // NFC Forum define value: 0x20 82 "urn:epc:raw:", // NFC Forum define value: 0x21 83 "urn:epc:", // NFC Forum define value: 0x22 84 "urn:nfc:", // NFC Forum define value: 0x23 85 }; 86 87 class NdefMessage final { 88 public: 89 const int MAX_RTD_TYPE_LEN = 2; 90 static const int MIN_RECORD_LEN = 3; 91 static const long int MAX_PAYLOAD_SIZE = 10 * (1 << 20); // 10MB 92 static const int SHORT_RECORD_SIZE = 256; 93 static const unsigned int ONE_BYTE_SHIFT = 8; 94 95 // TNF Type define 96 enum EmTnfType { 97 TNF_EMPTY = 0x00, 98 TNF_WELL_KNOWN = 0x01, 99 TNF_MIME_MEDIA = 0x02, 100 TNF_ABSOLUTE_URI = 0x03, 101 TNF_EXTERNAL_TYPE = 0x04, 102 TNF_UNKNOWN = 0x05, 103 TNF_UNCHANGED = 0x06, 104 TNF_RESERVED = 0x07 105 }; 106 107 // record Flag 108 enum EmRecordFlag { 109 FLAG_MB = 0x80, 110 FLAG_ME = 0x40, 111 FLAG_CF = 0x20, 112 FLAG_SR = 0x10, 113 FLAG_IL = 0x08, 114 FLAG_TNF = 0x07 115 }; 116 117 enum EmRtdType { 118 RTD_UNKNOWN = 0, 119 RTD_TEXT, 120 RTD_URI, 121 RTD_SMART_POSTER, 122 RTD_ALTERNATIVE_CARRIER, 123 RTD_HANDOVER_CARRIER, 124 RTD_HANDOVER_REQUEST, 125 RTD_HANDOVER_SELECT, 126 RTD_OHOS_APP, 127 RTD_RESERVED, 128 }; 129 public: 130 explicit NdefMessage(std::vector<std::shared_ptr<NdefRecord>> ndefRecords); 131 ~NdefMessage(); 132 133 /** 134 * @Description constructe a ndef message with raw bytes. 135 * @param data raw bytes to parse ndef message 136 * @return std::shared_ptr<NdefMessage> 137 */ 138 static std::shared_ptr<NdefMessage> GetNdefMessage(const std::string& data); 139 /** 140 * @Description constructe a ndef message with record list. 141 * @param ndefRecords record list to parse ndef message 142 * @return std::shared_ptr<NdefMessage> 143 */ 144 static std::shared_ptr<NdefMessage> GetNdefMessage(std::vector<std::shared_ptr<NdefRecord>> ndefRecords); 145 /** 146 * @Description convert the rtd bytes into byte array defined in Nfc forum. 147 * @param rtdtype rtd type of a record 148 * @return rtd byte array 149 */ 150 static std::string GetTagRtdType(EmRtdType rtdtype); 151 /** 152 * @Description Create a ndef record with uri data. 153 * @param uriString uri data for new a ndef record 154 * @return std::shared_ptr<NdefRecord> 155 */ 156 static std::shared_ptr<NdefRecord> MakeUriRecord(const std::string& uriString); 157 /** 158 * @Description Create a ndef record with text data. 159 * @param text text data for new a ndef record 160 * @param locale language code for the ndef record . if locale is null, use default locale 161 * @return std::shared_ptr<NdefRecord> 162 */ 163 static std::shared_ptr<NdefRecord> MakeTextRecord(const std::string& text, const std::string& locale); 164 /** 165 * @Description Create a ndef record with mime data. 166 * @param mimeType type of mime data for new a ndef record 167 * @param mimeData mime data for new a ndef record 168 * @return std::shared_ptr<NdefRecord> 169 */ 170 static std::shared_ptr<NdefRecord> MakeMimeRecord(const std::string& mimeType, const std::string& mimeData); 171 172 /** 173 * @Description Create a ndef record with external data. 174 * @param domainName domain name of issuing organization for the external data 175 * @param serviceName domain specific type of data for the external data 176 * @param externalData data payload of a ndef record 177 * @return std::shared_ptr<NdefRecord> 178 */ 179 static std::shared_ptr<NdefRecord> MakeExternalRecord(const std::string& domainName, 180 const std::string& serviceName, 181 const std::string& externalData); 182 /** 183 * @Description parse a ndef message into raw bytes. 184 * @param ndefMessage a ndef message to parse 185 * @return raw bytes of a ndef message 186 */ 187 static std::string MessageToString(std::weak_ptr<NdefMessage> ndefMessage); 188 /** 189 * @Description parse a ndef record into raw bytes. 190 * @param record a ndef record to parse 191 * @param buffer raw bytes of a ndef record 192 * @param bIsMB the flag of begin record 193 * @param bIsME the flag of end record 194 * @return void 195 */ 196 static void NdefRecordToString(std::weak_ptr<NdefRecord> record, std::string& buffer, bool bIsMB, bool bIsME); 197 /** 198 * @Description Get all records of a ndef message. 199 * @param void 200 * @return record list of a ndef message 201 */ 202 std::vector<std::shared_ptr<NdefRecord>> GetNdefRecords() const; 203 204 private: 205 static std::shared_ptr<NdefRecord> CreateNdefRecord(short tnf, const std::string& id, 206 const std::string& payload, const std::string& tagRtdType); 207 static bool CheckTnf(short tnf, const std::string& tagRtdType, 208 const std::string& id, const std::string& payload); 209 static std::vector<std::shared_ptr<NdefRecord>> ParseRecord(const std::string& data, bool isMbMeIgnored); 210 static void ParseRecordLayoutHead(RecordLayout& layout, unsigned char head); 211 static bool IsInvalidRecordLayoutHead(RecordLayout& layout, bool isChunkFound, 212 uint32_t parsedRecordSize, bool isMbMeIgnored); 213 static void ParseRecordLayoutLength(RecordLayout& layout, bool isChunkFound, 214 const std::string& data, uint32_t& parsedDataIndex); 215 static bool IsRecordLayoutLengthInvalid(RecordLayout& layout, bool isChunkFound); 216 static std::string ParseRecordType(RecordLayout& layout, const std::string& data, uint32_t& parsedDataIndex); 217 static std::string ParseRecordId(RecordLayout& layout, const std::string& data, uint32_t& parsedDataIndex); 218 static std::string ParseRecordPayload(RecordLayout& layout, const std::string& data, uint32_t& parsedDataIndex); 219 220 static void SaveRecordChunks(RecordLayout& layout, bool isChunkFound, std::vector<std::string>& chunks, 221 char& chunkTnf, const std::string& payload); 222 static std::string MergePayloadByChunks(RecordLayout& layout, bool isChunkFound, std::vector<std::string>& chunks, 223 char chunkTnf, const std::string& payload); 224 225 private: 226 std::vector<std::shared_ptr<NdefRecord>> ndefRecordList_ {}; 227 }; 228 229 // RTD types definitions, see NFC Record Type Definition (RTD) Specification. 230 const static std::array<std::string, NdefMessage::EmRtdType::RTD_RESERVED> HEX_RTD_TYPE = { 231 "", // RTD_UNKNOWN 232 "54", // 0x54, RTD_TEXT 233 "55", // 0x55, RTD_URI 234 }; 235 236 } // namespace KITS 237 } // namespace NFC 238 } // namespace OHOS 239 #endif // NDEF_MESSAGE_H 240