bump version and add go-ndef to vendor

This commit is contained in:
Andrea Franz 2019-11-19 18:05:56 +01:00
parent f35c31a20a
commit 4baa54e4e6
No known key found for this signature in database
GPG Key ID: 4F0D2F2D9DE7F29D
15 changed files with 1782 additions and 1 deletions

View File

@ -1 +1 @@
0.2.0
0.2.1

165
vendor/github.com/hsanjuan/go-ndef/LICENSE generated vendored Normal file
View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

96
vendor/github.com/hsanjuan/go-ndef/byte_utils.go generated vendored Normal file
View File

@ -0,0 +1,96 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
package ndef
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
)
// BytesToUint64 parses a byte slice to an uint64 (BigEndian). If the slice
// is longer than 8 bytes, it's truncated. If it's shorter, they are considered
// the less significant bits of the uint64.
func bytesToUint64(b []byte) uint64 {
// Make sure we are not parsing more than 8 bytes (uint64 size)
byte8 := make([]byte, 8)
if len(b) > 8 {
copy(byte8, b[len(b)-8:]) // use the last 8 bytes
} else {
copy(byte8[8-len(b):], b) // copy to last positions of byte8
}
return binary.BigEndian.Uint64(byte8)
}
// Uint64ToBytes converts a BigEndian uint64 into a byte slice of
// desiredLen. For lengths under 8 bytes, the 8 byte result is
// truncated (the most significant bytes are discarded
func uint64ToBytes(n uint64, desiredLen int) []byte {
buf := new(bytes.Buffer)
binary.Write(buf, binary.BigEndian, n)
if desiredLen >= 8 {
slice := make([]byte, desiredLen)
copy(slice[desiredLen-8:], buf.Bytes())
return slice
}
return buf.Bytes()[8-desiredLen:]
}
// func PrintBytes(bytes []byte, length int) {
// for i := 0; i < length; i++ {
// fmt.Printf("%02x ", bytes[i])
// }
// fmt.Println()
// }
// FmtBytes receives a byte slice and a n value and returns
// a string with first n hex-formatted values of the slice
func fmtBytes(bytes []byte, n int) (str string) {
if n > len(bytes) {
n = len(bytes)
}
for i := 0; i < n; i++ {
str += fmt.Sprintf("%02x ", bytes[i])
}
return str
}
// Reads from the bytes buffer and panics with an error
// if the buffer does not have the bytes to read that we want
// This is meant as a replacement for byteslice[3:3+x] where
// I don't have to constantly check the array length
// but instead I throw a custom panic
func getBytes(b *bytes.Buffer, n int) []byte {
slice := make([]byte, n)
nread, err := b.Read(slice)
if err != nil || nread != n {
panic(errors.New("unexpected end of data"))
}
return slice
}
// Same as above bug for a single byte
func getByte(b *bytes.Buffer) byte {
byte, err := b.ReadByte()
if err != nil {
panic(errors.New("unexpected end of data"))
}
return byte
}

235
vendor/github.com/hsanjuan/go-ndef/message.go generated vendored Normal file
View File

@ -0,0 +1,235 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
package ndef
import (
"bytes"
"errors"
"fmt"
"strings"
)
// Message represents an NDEF Message, which is a collection of one or
// more NDEF Records.
//
// Most common types of NDEF Messages (URI, Media) only have a single
// record. However, others, like Smart Posters, have multiple ones.
type Message struct {
Records []*Record
}
// NewMessage returns a new Message initialized with a single Record
// with the TNF, Type, ID and Payload values.
func NewMessage(tnf byte, rtype string, id string, payload RecordPayload) *Message {
return &Message{
Records: []*Record{NewRecord(tnf, rtype, id, payload)},
}
}
// NewMessageFromRecords returns a new Message containing several NDEF
// Records. The MB and ME flags for the records are adjusted to
// create a valid message.
func NewMessageFromRecords(records ...*Record) *Message {
n := len(records)
if n == 0 {
return &Message{}
}
last := n - 1
for _, r := range records {
r.SetMB(false)
r.SetME(false)
}
records[0].SetMB(true)
records[last].SetME(true)
return &Message{
Records: records,
}
}
// NewTextMessage returns a new Message with a single Record
// of WellKnownType T[ext].
func NewTextMessage(textVal, language string) *Message {
return &Message{
[]*Record{NewTextRecord(textVal, language)},
}
}
// NewURIMessage returns a new Message with a single Record
// of WellKnownType U[RI].
func NewURIMessage(uriVal string) *Message {
return &Message{
[]*Record{NewURIRecord(uriVal)},
}
}
// NewSmartPosterMessage returns a new Message with a single Record
// of WellKnownType Sp (Smart Poster).
func NewSmartPosterMessage(msgPayload *Message) *Message {
return &Message{
[]*Record{NewSmartPosterRecord(msgPayload)},
}
}
// NewMediaMessage returns a new Message with a single Record
// of Media (RFC-2046) type.
//
// mimeType is something like "text/json" or "image/jpeg".
func NewMediaMessage(mimeType string, payload []byte) *Message {
return &Message{
[]*Record{NewMediaRecord(mimeType, payload)},
}
}
// NewAbsoluteURIMessage returns a new Message with a single Record
// of AbsoluteURI type.
//
// AbsoluteURI means that the type of the payload for this record is
// defined by an URI resource. It is not supposed to be used to
// describe an URI. For that, use NewURIRecord().
func NewAbsoluteURIMessage(typeURI string, payload []byte) *Message {
return &Message{
[]*Record{NewAbsoluteURIRecord(typeURI, payload)},
}
}
// NewExternalMessage returns a new Message with a single Record
// of NFC Forum External type.
func NewExternalMessage(extType string, payload []byte) *Message {
return &Message{
[]*Record{NewExternalRecord(extType, payload)},
}
}
// Returns the string representation of each of the records in the message.
func (m *Message) String() string {
str := ""
last := len(m.Records) - 1
for i, r := range m.Records {
str += r.String()
if i != last {
str += "\n"
}
}
return str
}
// Inspect returns a string with information about the message and its records.
func (m *Message) Inspect() string {
str := fmt.Sprintf("NDEF Message with %d records.", len(m.Records))
if len(m.Records) > 0 {
str += "\n"
for i, r := range m.Records {
str += fmt.Sprintf("Record %d:\n", i)
rIns := r.Inspect()
rInsLines := strings.Split(rIns, "\n")
for _, l := range rInsLines {
str += " " + l + "\n"
}
}
}
return str
}
// Unmarshal parses a byte slice into a Message. This is done by
// parsing all Records in the slice, until there are no more to parse.
//
// Returns the number of bytes processed (message length), or an error
// if something looks wrong with the message or its records.
func (m *Message) Unmarshal(buf []byte) (rLen int, err error) {
m.Records = []*Record{}
rLen = 0
for rLen < len(buf) {
r := new(Record)
recordLen, err := r.Unmarshal(buf[rLen:])
rLen += recordLen
if err != nil {
return rLen, err
}
m.Records = append(m.Records, r)
if r.ME() { // last record in message
break
}
}
err = m.check()
return rLen, err
}
// Marshal provides the byte slice representation of a Message,
// which is the concatenation of the Marshaling of each of its records.
//
// Returns an error if something goes wrong.
func (m *Message) Marshal() ([]byte, error) {
err := m.check()
if err != nil {
return nil, err
}
var buffer bytes.Buffer
for _, r := range m.Records {
rBytes, err := r.Marshal()
if err != nil {
return nil, err
}
_, err = buffer.Write(rBytes)
if err != nil {
return nil, err
}
}
return buffer.Bytes(), nil
}
func (m *Message) check() error {
last := len(m.Records) - 1
if last < 0 {
return errors.New(eNORECORDS)
}
if !m.Records[0].MB() {
return errors.New(eNOMB)
}
if !m.Records[last].ME() {
return errors.New(eNOME)
}
for i, r := range m.Records {
if i > 0 && r.MB() {
return errors.New(eBADMB)
}
if i < last && r.ME() {
return errors.New(eBADME)
}
}
return nil
}
// Check errors
const (
eNORECORDS = "NDEF Message Check: No records"
eNOMB = "NDEF Message Check: first record has not the MessageBegin flag set"
eNOME = "NDEF Message Check: last record has not the MessageEnd flag set"
eBADMB = "NDEF Message Check: middle record has the MessageBegin flag set"
eBADME = "NDEF Message Check: middle record has the MessageEnd flag set"
)

36
vendor/github.com/hsanjuan/go-ndef/ndef.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
// Package ndef provides an implementation of the NFC Data Exchange
// Format (NDEF) specification:
// - NFCForum-TS-NDEF_1.0
// - NFCForum-TS-RTD_1.0
// It allows to parse byte slices into a structured Message type,
// as well as to turn an Message into a bytes again.
package ndef
// Possible values for the TNF Field as defined in the specification.
const (
Empty = byte(iota)
NFCForumWellKnownType
MediaType
AbsoluteURI
NFCForumExternalType
Unknown
Unchanged
Reserved
)

342
vendor/github.com/hsanjuan/go-ndef/record.go generated vendored Normal file
View File

@ -0,0 +1,342 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
package ndef
import (
"bytes"
"errors"
"fmt"
"github.com/hsanjuan/go-ndef/types/absoluteuri"
"github.com/hsanjuan/go-ndef/types/ext"
"github.com/hsanjuan/go-ndef/types/media"
"github.com/hsanjuan/go-ndef/types/wkt/text"
"github.com/hsanjuan/go-ndef/types/wkt/uri"
)
// A Record is an NDEF Record. Multiple records can be
// part of a single NDEF Message.
type Record struct {
chunks []*recordChunk
}
// NewRecord returns a single-chunked record with the given options.
// Use a generic.Payload if you want to use a custom byte-slice for payload.
func NewRecord(tnf byte, typ string, id string, payload RecordPayload) *Record {
var payloadBytes []byte
if payload != nil {
payloadBytes = payload.Marshal()
}
chunk := newChunk(
tnf,
typ,
id,
payloadBytes,
)
return &Record{
chunks: []*recordChunk{chunk},
}
}
// TNF returns the Type Name Format (3 bits) associated to this Record.
func (r *Record) TNF() byte {
if r.Empty() {
return 0
}
return r.chunks[0].TNF
}
// Type returns the declared Type for this record.
func (r *Record) Type() string {
if r.Empty() {
return ""
}
return r.chunks[0].Type
}
// ID returns the declared record ID for this record.
func (r *Record) ID() string {
if r.Empty() {
return ""
}
return r.chunks[0].ID
}
// Payload returns the RecordPayload for this record. It will use
// one of the supported types, or otherwise a generic.Payload.
func (r *Record) Payload() (RecordPayload, error) {
if r.Empty() {
return nil, errors.New("empty record")
}
var buf bytes.Buffer
for _, chunk := range r.chunks {
_, err := buf.Write(chunk.Payload)
if err != nil {
return nil, err
}
}
return makeRecordPayload(r.TNF(), r.Type(), buf.Bytes()), nil
}
// Empty returns true if this record has no chunks.
func (r *Record) Empty() bool {
return len(r.chunks) == 0
}
// MB returns the value of the MessageBegin bit of the first chunk of this
// record, signaling that this is the first record in an NDEF Message.
// a NDEF Message.
func (r *Record) MB() bool {
if r.Empty() {
return false
}
return r.chunks[0].MB
}
// SetMB sets the MessageBegin bit of the first chunk of this Record.
func (r *Record) SetMB(b bool) {
if r.Empty() {
return
}
r.chunks[0].MB = b
}
// ME returns the value of the MessageEnd bit of the last chunk of this Record,
// signaling that this is the last record in an NDEF Message.
func (r *Record) ME() bool {
if r.Empty() {
return false
}
return r.chunks[len(r.chunks)-1].ME
}
// SetME sets the MessageEnd bit of the last chunk of this record.
func (r *Record) SetME(b bool) {
if r.Empty() {
return
}
r.chunks[len(r.chunks)-1].ME = b
}
// NewTextRecord returns a new Record with a
// Payload of Text [Well-Known] Type.
func NewTextRecord(textVal, language string) *Record {
pl := text.New(textVal, language)
return NewRecord(NFCForumWellKnownType, "T", "", pl)
}
// NewURIRecord returns a new Record with a
// Payload of URI [Well-Known] Type.
func NewURIRecord(uriVal string) *Record {
pl := uri.New(uriVal)
return NewRecord(NFCForumWellKnownType, "U", "", pl)
}
// NewSmartPosterRecord creates a new Record representing a Smart Poster.
// The Payload of a Smart Poster is an NDEF Message.
func NewSmartPosterRecord(msg *Message) *Record {
pl := NewSmartPosterPayload(msg)
return NewRecord(NFCForumWellKnownType, "Sp", "", pl)
}
// NewMediaRecord returns a new Record with a
// Media type (per RFC-2046) as payload.
//
// mimeType is something like "text/json" or "image/jpeg".
func NewMediaRecord(mimeType string, payload []byte) *Record {
pl := media.New(mimeType, payload)
return NewRecord(MediaType, mimeType, "", pl)
}
// NewAbsoluteURIRecord returns a new Record with a
// Payload of Absolute URI type.
//
// AbsoluteURI means that the type of the payload for this record is
// defined by an URI resource. It is not supposed to be used to
// describe an URI. For that, use NewURIRecord().
func NewAbsoluteURIRecord(typeURI string, payload []byte) *Record {
pl := absoluteuri.New(typeURI, payload)
return NewRecord(AbsoluteURI, typeURI, "", pl)
}
// NewExternalRecord returns a new Record with a
// Payload of NFC Forum external type.
func NewExternalRecord(extType string, payload []byte) *Record {
pl := ext.New(extType, payload)
return NewRecord(NFCForumExternalType, extType, "", pl)
}
// String a string representation of the payload of the record, prefixed
// by the URN of the resource.
//
// Note that not all NDEF Payloads are supported, and that custom types/payloads
// are considered not printable. In those cases, a generic RecordPayload is
// used and an explanatory message is returned instead.
// See submodules under "types/" for a list of supported types.
func (r *Record) String() string {
pl, err := r.Payload()
if err != nil {
return err.Error()
}
return pl.Type() + ":" + pl.String()
}
// Inspect provides a string with information about this record.
// For a String representation of the contents use String().
func (r *Record) Inspect() string {
if r.Empty() {
return "Empty record"
}
pl, err := r.Payload()
if err != nil {
return err.Error()
}
var str string
str += fmt.Sprintf("TNF: %d\n", r.TNF())
str += fmt.Sprintf("Type: %s\n", r.Type())
str += fmt.Sprintf("ID: %s\n", r.ID())
str += fmt.Sprintf("MB: %t\n", r.MB())
str += fmt.Sprintf("ME: %t\n", r.ME())
str += fmt.Sprintf("Payload Length: %d", pl.Len())
return str
}
// Unmarshal parses a byte slice into a Record struct (the slice can
// have extra bytes which are ignored). The Record is always reset before
// parsing.
//
// It does this by parsing every record chunk until a chunk with the CF flag
// cleared is read is read.
//
// Returns how many bytes were parsed from the slice (record length) or
// an error if something went wrong.
func (r *Record) Unmarshal(buf []byte) (rLen int, err error) {
rLen = 0
var chunks []*recordChunk
for rLen < len(buf) {
chunk := &recordChunk{}
chunkSize, err := chunk.Unmarshal(buf[rLen:])
rLen += chunkSize
if err != nil {
return rLen, err
}
chunks = append(chunks, chunk)
// the last chunk record of a chunked record
// has the CF flag cleared.
if !chunk.CF {
break
}
}
r.chunks = chunks
err = r.check()
return rLen, err
}
// Marshal returns the byte representation of a Record. It does this
// by producing a single record chunk.
//
// Note that if the original Record was unmarshaled from many chunks,
// the recovery is not possible anymore.
func (r *Record) Marshal() ([]byte, error) {
err := r.check()
if err != nil {
return nil, err
}
var buf bytes.Buffer
for _, chunk := range r.chunks {
chunkBytes, err := chunk.Marshal()
if err != nil {
return buf.Bytes(), err
}
_, err = buf.Write(chunkBytes)
if err != nil {
return buf.Bytes(), err
}
}
return buf.Bytes(), nil
}
func (r *Record) check() error {
chunksLen := len(r.chunks)
last := chunksLen - 1
if chunksLen == 0 {
return errors.New(eNOCHUNKS)
}
if chunksLen == 1 && r.chunks[0].CF {
return errors.New(eFIRSTCHUNKED)
}
if r.chunks[0].CF && r.chunks[last].CF {
return errors.New(eLASTCHUNKED)
}
if chunksLen > 1 {
chunksWithoutCF := 0
chunksWithIL := 0
chunksWithTypeLength := 0
chunksWithoutUnchangedType := 0
for i, r := range r.chunks {
// Check CF in all but the last
if !r.CF && i != last {
chunksWithoutCF++
}
// Check IL in all but first
if r.IL && i != 0 {
chunksWithIL++
}
// TypeLength should be zero except in the first
if r.TypeLength > 0 && i != 0 {
chunksWithTypeLength++
}
// All but first chunk should have TNF to 0x06
if r.TNF != Unchanged && i != 0 {
chunksWithoutUnchangedType++
}
}
if chunksWithoutCF > 0 {
return errors.New(eCFMISSING)
}
if chunksWithIL > 0 {
return errors.New(eBADIL)
}
if chunksWithTypeLength > 0 {
return errors.New(eBADTYPELENGTH)
}
if chunksWithoutUnchangedType > 0 {
return errors.New(eBADTNF)
}
}
return nil
}
// Set some short-hands for the errors that can happen on check().
const (
eNOCHUNKS = "NDEF Record Check: No chunks"
eFIRSTCHUNKED = "NDEF Record Check: A single record cannot have the Chunk flag set"
eLASTCHUNKED = "NDEF Record Check: Last record cannot have the Chunk flag set"
eCFMISSING = "NDEF Record Check: Chunk Flag missing from some records"
eBADIL = "NDEF Record Check: IL flag is set on a middle or final chunk"
eBADTYPELENGTH = "NDEF Record Check: A middle or last chunk has TypeLength != 0"
eBADTNF = "NDEF Record Check: A middle or last chunk TNF is not UNCHANGED"
)

269
vendor/github.com/hsanjuan/go-ndef/record_chunk.go generated vendored Normal file
View File

@ -0,0 +1,269 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
package ndef
import (
"bytes"
"errors"
"fmt"
"runtime"
)
// RecordChunk represents how a Record is actually stored
// We need this for parsing and checking the validity of a Record
// before assembling them.
type recordChunk struct {
// First byte
MB bool // Message begin
ME bool // Message end
CF bool // Chunk Flag
SR bool // Short record
IL bool // ID length field present
TNF byte // Type name format (3 bits)
TypeLength byte // Type Length
IDLength byte // Length of the ID field
PayloadLength uint64 // Length of the Payload.
Type string // Type of the payload. Must follow TNF
ID string // An URI (per RFC 3986)
Payload []byte // Payload
}
// Reset clears up all the fields of the Record and sets them to their
// default values.
func (r *recordChunk) Reset() {
r.MB = false
r.ME = false
r.CF = false
r.SR = false
r.IL = false
r.TNF = 0
r.TypeLength = 0
r.IDLength = 0
r.PayloadLength = 0
r.Type = ""
r.ID = ""
r.Payload = []byte{}
}
// New returns a single RecordChunk with the given options. This chunk can be
// used directly to make a single-chunk NDEF Record on a single-record NDEF
// message: the MB and ME fields are set to true.
func newChunk(tnf byte, typ string, id string, payload []byte) *recordChunk {
chunk := &recordChunk{}
chunk.Reset()
chunk.MB = true // Message-begin
chunk.ME = true // Message-end
chunk.CF = false // not chunked
chunk.IL = len(id) > 0 // only if ID field present
chunk.TNF = tnf
chunk.TypeLength = byte(len([]byte(typ)))
chunk.Type = typ
chunk.IDLength = byte(len([]byte(id)))
chunk.ID = id
payloadLen := uint64(len(payload))
if payloadLen > 4294967295 { //2^32-1. 4GB message max.
payloadLen = 4294967295
}
chunk.SR = payloadLen < 256 // Short record vs. Long
chunk.PayloadLength = payloadLen
// FIXME: If payload is greater than 2^32 - 1
// we'll truncate without warning.
chunk.Payload = payload[:payloadLen]
return chunk
}
// Provide a string with information about this record chunk.
// Records' payload do not make sense without having compiled a whole Record
// so they are not dealed with here.
func (r *recordChunk) String() string {
var str string
str += fmt.Sprintf("MB: %t | ME: %t | CF: %t | SR: %t | IL: %t | TNF: %d\n",
r.MB, r.ME, r.CF, r.SR, r.IL, r.TNF)
str += fmt.Sprintf("TypeLength: %d", r.TypeLength)
str += fmt.Sprintf(" | Type: %s\n", r.Type)
str += fmt.Sprintf("Record Payload Length: %d",
r.PayloadLength)
if r.IL {
str += fmt.Sprintf(" | IDLength: %d", r.IDLength)
str += fmt.Sprintf(" | ID: %s", r.ID)
}
str += fmt.Sprintf("\n")
return str
}
// Unmarshal parses a byte slice into a single Record chunk struct (the slice
// can have extra bytes which are ignored). The Record is always reset before
// parsing.
//
// Returns how many bytes were parsed from the slice (record length) or
// an error if something went wrong.
func (r *recordChunk) Unmarshal(buf []byte) (rLen int, err error) {
// Handle errors that are produced by getByte() and getBytes()
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
err = r.(error)
err = errors.New("Record.Unmarshal: " + err.Error())
}
}()
r.Reset()
bytesBuf := bytes.NewBuffer(buf)
firstByte := getByte(bytesBuf)
r.MB = (firstByte >> 7 & 0x1) == 1
r.ME = (firstByte >> 6 & 0x1) == 1
r.CF = (firstByte >> 5 & 0x1) == 1
r.SR = (firstByte >> 4 & 0x1) == 1
r.IL = (firstByte >> 3 & 0x1) == 1
r.TNF = firstByte & 0x7
r.TypeLength = getByte(bytesBuf)
if r.SR { //This is a short record
r.PayloadLength = uint64(getByte(bytesBuf))
} else { // Regular record
r.PayloadLength = bytesToUint64(getBytes(bytesBuf, 4))
}
if r.IL {
r.IDLength = getByte(bytesBuf)
}
r.Type = string(getBytes(bytesBuf, int(r.TypeLength)))
if r.IL {
r.ID = string(getBytes(bytesBuf, int(r.IDLength)))
}
r.Payload = getBytes(bytesBuf, int(r.PayloadLength))
rLen = len(buf) - bytesBuf.Len()
err = r.Check()
if err != nil {
return rLen, err
}
return rLen, nil
}
// Marshal returns the byte representation of a Record, or an error
// if something went wrong
func (r *recordChunk) Marshal() ([]byte, error) {
err := r.Check()
if err != nil {
return nil, err
}
var buffer bytes.Buffer
firstByte := byte(0)
if r.MB {
firstByte |= 0x1 << 7
}
if r.ME {
firstByte |= 0x1 << 6
}
if r.CF {
firstByte |= 0x1 << 5
}
if r.SR {
firstByte |= 0x1 << 4
}
if r.IL {
firstByte |= 0x1 << 3
}
firstByte |= (r.TNF & 0x7) //Last 3 bits are from TNF
buffer.WriteByte(firstByte)
// TypeLength byte
buffer.WriteByte(r.TypeLength)
// Payload Length byte (for SR) or 4 bytes for the regular case
if r.SR {
buffer.WriteByte(byte(r.PayloadLength))
} else {
buffer.Write(uint64ToBytes(r.PayloadLength, 4))
}
// ID Length byte if we are meant to have it
if r.IL {
buffer.WriteByte(r.IDLength)
}
// Write the type bytes if we have something
if r.TypeLength > 0 {
buffer.Write([]byte(r.Type))
}
// Write the ID bytes if we have something
if r.IL && r.IDLength > 0 {
buffer.Write([]byte(r.ID))
}
buffer.Write(r.Payload)
return buffer.Bytes(), nil
}
// Check verifies that fields in this chunk are not in violation of the spec.
func (r *recordChunk) Check() error {
// If the TNF value is 0x00, the TYPE_LENGTH, ID_LENGTH,
// and PAYLOAD_LENGTH fields MUST be zero and the TYPE, ID,
// and PAYLOAD fields MUST be omitted from the record.
if r.TNF == Empty && (r.TypeLength > 0 ||
r.IDLength > 0 || r.PayloadLength > 0) {
return errors.New("Record.check: " +
"Empty record TNF but not empty fields")
}
// If the TNF value is 0x05 or 0x06 (Unknown/Unchanged),
// the TYPE_LENGTH field MUST be 0 and the TYPE
// field MUST be omitted from the NDEF record.
if (r.TNF == Unknown || r.TNF == Unchanged) && r.TypeLength > 0 {
return errors.New("Record.check: " +
"This TNF does not support a Type field")
}
// The TNF value MUST NOT be 0x07.
if r.TNF == Reserved {
return errors.New("Record.check: " +
"The TNF cannot be Reserved, that value is reserved.")
}
// NFC Record Type Definition 3.4:
// The binary encoding of Well Known Types
// (including Global and Local Names) and External
// Type names MUST be done according to the
// ASCII chart in Appendix A.
if r.TNF == NFCForumWellKnownType ||
r.TNF == NFCForumExternalType {
typeString := string(r.Type)
for _, rune := range typeString {
if rune < 32 || rune > 126 {
return errors.New("Record.check(): " +
"Record type names SHALL " +
"be formed of characters from of the " +
"US ASCII [ASCII] character set")
}
}
}
if r.IL && r.IDLength > 0 {
for _, rune := range r.ID {
if rune < 32 || rune > 126 {
return errors.New("Record.check(): " +
"ID must use ASCII characters")
}
}
}
return nil
}

71
vendor/github.com/hsanjuan/go-ndef/record_payload.go generated vendored Normal file
View File

@ -0,0 +1,71 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
package ndef
import (
"github.com/hsanjuan/go-ndef/types/absoluteuri"
"github.com/hsanjuan/go-ndef/types/ext"
"github.com/hsanjuan/go-ndef/types/generic"
"github.com/hsanjuan/go-ndef/types/media"
"github.com/hsanjuan/go-ndef/types/wkt/text"
"github.com/hsanjuan/go-ndef/types/wkt/uri"
)
// The RecordPayload interface should be implemented by supported
// NDEF Record types. It ensures that we have a way to interpret payloads
// into printable information and to produce NDEF Record payloads for a given
// type.
type RecordPayload interface {
// Returns a string representation of the Payload
String() string
// Provides serialization for the Payload
Marshal() []byte
// Provides de-serialization for the Payload
Unmarshal(buf []byte)
// Returns a string indetifying the type of this payload
Type() string
// Returns the length of the Payload (serialized)
Len() int
}
func makeRecordPayload(tnf byte, rtype string, payload []byte) RecordPayload {
var r RecordPayload
switch tnf {
case NFCForumWellKnownType:
switch rtype {
case "U":
r = new(uri.Payload)
case "T":
r = new(text.Payload)
case "Sp":
r = new(SmartPosterPayload)
default:
r = new(generic.Payload)
}
case MediaType:
r = media.New(rtype, nil)
case NFCForumExternalType:
r = ext.New(rtype, nil)
case AbsoluteURI:
r = absoluteuri.New(rtype, nil)
default:
r = new(generic.Payload)
}
r.Unmarshal(payload)
return r
}

64
vendor/github.com/hsanjuan/go-ndef/sp.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
package ndef
// Unfortunately splitting this to its own package causes a hard to break cycle.
// SmartPosterPayload represents the Payload of a Smart Poster, which is
// an NDEF Message with one or multiple records.
type SmartPosterPayload struct {
Message *Message
}
// NewSmartPosterPayload returns a new Smart Poster payload.
func NewSmartPosterPayload(msg *Message) *SmartPosterPayload {
return &SmartPosterPayload{
Message: msg,
}
}
// String returns the contents of the message contained in the Smart Poster.
func (sp *SmartPosterPayload) String() string {
str := "\n"
str += sp.Message.String()
return str
}
// Type returns the URN for the Smart Poster type
func (sp *SmartPosterPayload) Type() string {
return "urn:nfc:wkt:Sp"
}
// Marshal returns the bytes representing the payload of a Smart Poster.
// The payload is the contained NDEF Message.
func (sp *SmartPosterPayload) Marshal() []byte {
bs, _ := sp.Message.Marshal()
return bs
}
// Unmarshal parses the SmartPosterPayload from a Smart Poster.
func (sp *SmartPosterPayload) Unmarshal(buf []byte) {
msg := &Message{}
msg.Unmarshal(buf)
sp.Message = msg
}
// Len returns the length of this payload in bytes.
func (sp *SmartPosterPayload) Len() int {
return len(sp.Marshal())
}

View File

@ -0,0 +1,65 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
// Package absoluteuri provides an implementation for NDEF Payloads
// of Absolute URI type.
package absoluteuri
// Payload is a wrapper to store a Payload
type Payload struct {
URIType string
Payload []byte
}
// New returns a pointer to a Payload type holding the given payload with the
// given type.
func New(uriType string, payload []byte) *Payload {
return &Payload{
URIType: uriType,
Payload: payload,
}
}
// String returns a string explaining that we are not sure how to print
// this type.
func (absu *Payload) String() string {
if absu.Len() > 0 {
return "<The message contains a binary payload>"
}
return ""
}
// Type returns the URI defining the type for this payload
func (absu *Payload) Type() string {
return absu.URIType
}
// Marshal returns the bytes representing the payload
func (absu *Payload) Marshal() []byte {
return absu.Payload
}
// Unmarshal parses a generic payload
func (absu *Payload) Unmarshal(buf []byte) {
absu.Payload = buf
}
// Len is the length of the byte slice resulting of Marshaling
// this Payload.
func (absu *Payload) Len() int {
return len(absu.Marshal())
}

65
vendor/github.com/hsanjuan/go-ndef/types/ext/ext.go generated vendored Normal file
View File

@ -0,0 +1,65 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
// Package ext provides an implementation for NDEF Payloads of NFC Forum
// External Type.
package ext
// Payload is a wrapper to store a Payload
type Payload struct {
ExtType string
Payload []byte
}
// New returns a pointer to a Payload type holding the given payload with the
// given type.
func New(extType string, payload []byte) *Payload {
return &Payload{
ExtType: extType,
Payload: payload,
}
}
// String returns a string explaining that we are not sure how to print
// this type.
func (extT *Payload) String() string {
if extT.Len() > 0 {
return "<The message contains a binary payload>"
}
return ""
}
// Type returns a readable type name for this payload.
func (extT *Payload) Type() string {
return "urn:nfc:ext:" + extT.ExtType
}
// Marshal returns the bytes representing the payload
func (extT *Payload) Marshal() []byte {
return extT.Payload
}
// Unmarshal parses a generic payload
func (extT *Payload) Unmarshal(buf []byte) {
extT.Payload = buf
}
// Len is the length of the byte slice resulting of Marshaling
// this Payload.
func (extT *Payload) Len() int {
return len(extT.Marshal())
}

View File

@ -0,0 +1,62 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
// Package generic provides a generic implementation for NDEF Payloads which are
// either custom or not supported yet.
package generic
// Payload is a wrapper to store a Payload.
type Payload struct {
Payload []byte
}
// New returns a pointer to a Payload type holding the given payload.
func New(payload []byte) *Payload {
return &Payload{
Payload: payload,
}
}
// String returns a string explaining that we are not sure how to print
// this type.
func (g *Payload) String() string {
if g.Len() > 0 {
return "<The message contains a binary payload>"
}
return ""
}
// Type returns the name of the payload type. In this case, it's generic.
func (g *Payload) Type() string {
return "go-ndef-generic"
}
// Marshal returns the bytes representing the payload of a Record of
// generic type.
func (g *Payload) Marshal() []byte {
return g.Payload
}
// Unmarshal parses a generic payload.
func (g *Payload) Unmarshal(buf []byte) {
g.Payload = buf
}
// Len is the length of the byte slice resulting of Marshaling.
func (g *Payload) Len() int {
return len(g.Marshal())
}

View File

@ -0,0 +1,65 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
// Package media provides an implementation for NDEF Payloads for media
// types.
package media
// Payload is a wrapper to store a Payload
type Payload struct {
MimeType string
Payload []byte
}
// New returns a pointer to a Payload type holding the given payload with the
// given type.
func New(mimeType string, payload []byte) *Payload {
return &Payload{
MimeType: mimeType,
Payload: payload,
}
}
// String returns a string explaining that we are not sure how to print
// this type.
func (media *Payload) String() string {
if media.Len() > 0 {
return "<The message contains a payload>"
}
return ""
}
// Type returns the mime type of this payload.
func (media *Payload) Type() string {
return media.MimeType
}
// Marshal returns the bytes representing the payload
func (media *Payload) Marshal() []byte {
return media.Payload
}
// Unmarshal parses a generic payload
func (media *Payload) Unmarshal(buf []byte) {
media.Payload = buf
}
// Len is the length of the byte slice resulting of Marshaling
// this Payload.
func (media *Payload) Len() int {
return len(media.Marshal())
}

View File

@ -0,0 +1,119 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
// BUG(hector): The implementation ignores the guidelines about displaying the
// text and removing the control characters.
// BUG(hector): UTF-16 with different byte order, with/without BOM is not tested.
// Package text provides support for NDEF Payloads of Text type.
// It follows the NFC Forum Text Record Type Definition specification
// (NFCForum-TS-RTD_Text_1.0).
//
// The Payload type implements the RecordPayload interface from ndef,
// so it can be used as ndef.Record.Payload.
package text
import (
"bytes"
"strings"
"unicode/utf16"
)
// Payload represents a NDEF Record Payload of type "T", which
// holds a text field and IANA-formatted language information.
type Payload struct {
Language string
Text string
}
// New returns a pointer to a Payload.
//
// The language parameter must be compliant to RFC 3066 (i.e. "en_US"),
// but no check is performed.
func New(text, language string) *Payload {
return &Payload{
Language: language,
Text: text,
}
}
// String returns the actual text. Language information is ommited.
func (t *Payload) String() string {
return t.Text
}
// Type returns the URN for Text types.
func (t *Payload) Type() string {
return "urn:nfc:wkt:T"
}
// Marshal returns the bytes representing the payload of a text Record.
func (t *Payload) Marshal() []byte {
var buf bytes.Buffer
ianaLen := byte(len(t.Language))
buf.WriteByte(ianaLen)
buf.Write([]byte(t.Language))
buf.Write([]byte(t.Text))
return buf.Bytes()
}
// Unmarshal parses the Payload from a text Record.
func (t *Payload) Unmarshal(buf []byte) {
t.Language = ""
t.Text = ""
i := byte(0)
if len(buf) < 1 {
return
}
firstByte := buf[i]
i++
isUtf16 := firstByte>>7 == 1
// firstByte>>6 must be set to 0
ianaLen := 0x3F & firstByte // last 5 bytes
if len(buf) < int(i+ianaLen) {
return
}
t.Language = string(buf[i : i+ianaLen])
i += ianaLen
if len(buf) < int(i) {
return
}
if isUtf16 {
//Convert buf to []uint16
bytesBuf := bytes.NewBuffer(buf[i:])
var finished bool
var uint16buf []uint16
for !finished {
b1, err := bytesBuf.ReadByte()
b2, err := bytesBuf.ReadByte()
uint16buf = append(uint16buf,
uint16(b1<<8)|uint16(b2))
finished = err != nil
}
runes := utf16.Decode(uint16buf)
// It appears we get an extra trailing char at the end
t.Text = strings.TrimSuffix(string(runes), "\x00")
} else {
t.Text = string(buf[i:])
}
}
// Len is the length of the byte slice resulting of Marshaling..
func (t *Payload) Len() int {
return len(t.Marshal())
}

127
vendor/github.com/hsanjuan/go-ndef/types/wkt/uri/uri.go generated vendored Normal file
View File

@ -0,0 +1,127 @@
/***
Copyright (c) 2018, Hector Sanjuan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
// Package uri provides support for NDEF Payloads of URI type.
// It follows the NFC Forum URI Record Type Definition specification
// (NFCForum-TS-RTD_URI_1.0).
//
// The Payload type implements the RecordPayload interface from ndef,
// so it can be used as ndef.Record.Payload.
package uri
import (
"regexp"
"strings"
)
// URIProtocols provides a mapping between the first byte if a NDEF Payload of
// type "U" (URI) and the string value for the protocol.
var URIProtocols = map[byte]string{
0: "",
1: "http://www.",
2: "https://www.",
3: "http://",
4: "https://",
5: "tel:",
6: "mailto:",
7: "ftp://anonymous:anonymous@",
8: "ftp://ftp.",
9: "ftps://",
10: "sftp://",
11: "smb://",
12: "nfs://",
13: "ftp://",
14: "dev://",
15: "news:",
16: "telnet://",
17: "imap:",
18: "rtsp://",
19: "urn:",
20: "pop:",
21: "sip:",
22: "sips:",
23: "tftp:",
24: "btspp://",
25: "btl2cap://",
26: "btgoep://",
27: "tcpobex://",
28: "irdaobex://",
29: "file://",
30: "urn:epc:id:",
31: "urn:epc:tag:",
32: "urn:epc:pat:",
33: "urn:epc:raw:",
34: "urn:epc:",
35: "urn:nfc:",
}
// Payload represents a NDEF Record Payload of Type "U".
type Payload struct {
IdentCode byte
URIField string
}
// New returns a pointer to an Payload object.
// The Identifier code is automatically
// set based on the provided string.
func New(uriStr string) *Payload {
u := new(Payload)
u.URIField = uriStr
for i := byte(1); i < 36; i++ {
m, _ := regexp.MatchString("^"+URIProtocols[i], uriStr)
if m {
u.IdentCode = i
u.URIField = strings.Replace(uriStr,
URIProtocols[i], "", 1)
break
}
}
return u
}
// String returns the URI string.
func (u *Payload) String() string {
return URIProtocols[u.IdentCode] + u.URIField
}
// Type returns the Uniform Resource Name for URIs.
func (u *Payload) Type() string {
return "urn:nfc:wkt:U"
}
// Marshal returns the bytes representing the payload of a Record of URI type.
func (u *Payload) Marshal() []byte {
p := []byte{u.IdentCode}
return append(p, []byte(u.URIField)...)
}
// Unmarshal parses the payload of a URI type record.
func (u *Payload) Unmarshal(buf []byte) {
u.IdentCode = 0
u.URIField = ""
if len(buf) > 0 {
u.IdentCode = buf[0]
}
if len(buf) > 1 {
u.URIField = string(buf[1:])
}
}
// Len is the length of the byte slice resulting of Marshaling.
func (u *Payload) Len() int {
return len(u.Marshal())
}