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