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 long int MAX_PAYLOAD_SIZE = 10 * (1 << 20); // 10MB 91 static const int SHORT_RECORD_SIZE = 256; 92 93 // TNF Type define 94 enum EmTnfType { 95 TNF_EMPTY = 0x00, 96 TNF_WELL_KNOWN = 0x01, 97 TNF_MIME_MEDIA = 0x02, 98 TNF_ABSOLUTE_URI = 0x03, 99 TNF_EXTERNAL_TYPE = 0x04, 100 TNF_UNKNOWN = 0x05, 101 TNF_UNCHANGED = 0x06, 102 TNF_RESERVED = 0x07 103 }; 104 105 // record Flag 106 enum EmRecordFlag { 107 FLAG_MB = 0x80, 108 FLAG_ME = 0x40, 109 FLAG_CF = 0x20, 110 FLAG_SR = 0x10, 111 FLAG_IL = 0x08, 112 FLAG_TNF = 0x07 113 }; 114 115 enum EmRtdType { 116 RTD_UNKNOWN = 0, 117 RTD_TEXT, 118 RTD_URI, 119 RTD_SMART_POSTER, 120 RTD_ALTERNATIVE_CARRIER, 121 RTD_HANDOVER_CARRIER, 122 RTD_HANDOVER_REQUEST, 123 RTD_HANDOVER_SELECT, 124 RTD_OHOS_APP, 125 RTD_RESERVED, 126 }; 127 public: 128 explicit NdefMessage(std::vector<std::shared_ptr<NdefRecord>> ndefRecords); 129 ~NdefMessage(); 130 131 /** 132 * @Description constructe a ndef message with raw bytes. 133 * @param data raw bytes to parse ndef message 134 * @return std::shared_ptr<NdefMessage> 135 */ 136 static std::shared_ptr<NdefMessage> GetNdefMessage(const std::string& data); 137 /** 138 * @Description constructe a ndef message with record list. 139 * @param ndefRecords record list to parse ndef message 140 * @return std::shared_ptr<NdefMessage> 141 */ 142 static std::shared_ptr<NdefMessage> GetNdefMessage(std::vector<std::shared_ptr<NdefRecord>> ndefRecords); 143 /** 144 * @Description convert the rtd bytes into byte array defined in Nfc forum. 145 * @param rtdtype rtd type of a record 146 * @return rtd byte array 147 */ 148 static std::string GetTagRtdType(EmRtdType rtdtype); 149 /** 150 * @Description Create a ndef record with uri data. 151 * @param uriString uri data for new a ndef record 152 * @return std::shared_ptr<NdefRecord> 153 */ 154 static std::shared_ptr<NdefRecord> MakeUriRecord(const std::string& uriString); 155 /** 156 * @Description Create a ndef record with text data. 157 * @param text text data for new a ndef record 158 * @param locale language code for the ndef record . if locale is null, use default locale 159 * @return std::shared_ptr<NdefRecord> 160 */ 161 static std::shared_ptr<NdefRecord> MakeTextRecord(const std::string& text, const std::string& locale); 162 /** 163 * @Description Create a ndef record with mime data. 164 * @param mimeType type of mime data for new a ndef record 165 * @param mimeData mime data for new a ndef record 166 * @return std::shared_ptr<NdefRecord> 167 */ 168 static std::shared_ptr<NdefRecord> MakeMimeRecord(const std::string& mimeType, const std::string& mimeData); 169 170 /** 171 * @Description Create a ndef record with external data. 172 * @param domainName domain name of issuing organization for the external data 173 * @param serviceName domain specific type of data for the external data 174 * @param externalData data payload of a ndef record 175 * @return std::shared_ptr<NdefRecord> 176 */ 177 static std::shared_ptr<NdefRecord> MakeExternalRecord(const std::string& domainName, 178 const std::string& serviceName, 179 const std::string& externalData); 180 /** 181 * @Description parse a ndef message into raw bytes. 182 * @param ndefMessage a ndef message to parse 183 * @return raw bytes of a ndef message 184 */ 185 static std::string MessageToString(std::weak_ptr<NdefMessage> ndefMessage); 186 /** 187 * @Description parse a ndef record into raw bytes. 188 * @param record a ndef record to parse 189 * @param buffer raw bytes of a ndef record 190 * @param bIsMB the flag of begin record 191 * @param bIsME the flag of end record 192 * @return void 193 */ 194 static void NdefRecordToString(std::weak_ptr<NdefRecord> record, std::string& buffer, bool bIsMB, bool bIsME); 195 /** 196 * @Description Get all records of a ndef message. 197 * @param void 198 * @return record list of a ndef message 199 */ 200 std::vector<std::shared_ptr<NdefRecord>> GetNdefRecords() const; 201 202 private: 203 static std::shared_ptr<NdefRecord> CreateNdefRecord(short tnf, const std::string& id, 204 const std::string& payload, const std::string& tagRtdType); 205 static bool CheckTnf(short tnf, const std::string& tagRtdType, 206 const std::string& id, const std::string& payload); 207 static std::vector<std::shared_ptr<NdefRecord>> ParseRecord(const std::string& data, bool isMbMeIgnored); 208 static void ParseRecordLayoutHead(RecordLayout& layout, unsigned char head); 209 static bool IsInvalidRecordLayoutHead(RecordLayout& layout, bool isChunkFound, 210 uint32_t parsedRecordSize, bool isMbMeIgnored); 211 static void ParseRecordLayoutLength(RecordLayout& layout, bool isChunkFound, 212 const std::string& data, uint32_t& parsedDataIndex); 213 static bool IsRecordLayoutLengthInvalid(RecordLayout& layout, bool isChunkFound); 214 static std::string ParseRecordType(RecordLayout& layout, const std::string& data, uint32_t& parsedDataIndex); 215 static std::string ParseRecordId(RecordLayout& layout, const std::string& data, uint32_t& parsedDataIndex); 216 static std::string ParseRecordPayload(RecordLayout& layout, const std::string& data, uint32_t& parsedDataIndex); 217 218 static void SaveRecordChunks(RecordLayout& layout, bool isChunkFound, std::vector<std::string>& chunks, 219 char& chunkTnf, const std::string& payload); 220 static std::string MergePayloadByChunks(RecordLayout& layout, bool isChunkFound, std::vector<std::string>& chunks, 221 char chunkTnf, const std::string& payload); 222 223 private: 224 std::vector<std::shared_ptr<NdefRecord>> ndefRecordList_ {}; 225 }; 226 227 // RTD types definitions, see NFC Record Type Definition (RTD) Specification. 228 const static std::array<std::string, NdefMessage::EmRtdType::RTD_RESERVED> HEX_RTD_TYPE = { 229 "", // RTD_UNKNOWN 230 "54", // 0x54, RTD_TEXT 231 "55", // 0x55, RTD_URI 232 }; 233 234 } // namespace KITS 235 } // namespace NFC 236 } // namespace OHOS 237 #endif // NDEF_MESSAGE_H 238