From 503ec5bc103f3ff48cda349b1dfa8527c840182d Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Mon, 2 Feb 2009 23:36:53 +0000 Subject: [PATCH] Massive changes to support basic NDEF and URI record types --- pytikitag/nfc/__init__.py | 0 pytikitag/nfc/ndef.py | 61 +++++++++++++++++++++++++++++++++++++++ pytikitag/nfc/type2.py | 49 +++++++++++++++++++++++++++++++ pytikitag/tikitag.py | 9 ++++-- test.py | 23 ++++++--------- 5 files changed, 126 insertions(+), 16 deletions(-) create mode 100644 pytikitag/nfc/__init__.py create mode 100644 pytikitag/nfc/ndef.py create mode 100644 pytikitag/nfc/type2.py diff --git a/pytikitag/nfc/__init__.py b/pytikitag/nfc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pytikitag/nfc/ndef.py b/pytikitag/nfc/ndef.py new file mode 100644 index 0000000..870095a --- /dev/null +++ b/pytikitag/nfc/ndef.py @@ -0,0 +1,61 @@ +from smartcard.util import toASCIIString + +class NDEFReader(): + + _records = [] + items = [] + + _uri_lookup = { 0x00: "", 0x01: "http://www.", 0x02: "https://www.", + 0x03: "http://", 0x04: "https://", 0x05: "tel:", + 0x06: "mailto:", 0x07: "ftp://anonymous:anonymous@", + 0x08: "ftp://ftp.", 0x09: "ftps://", 0x0A: "sftp://", + 0x0B: "smb://", 0x0C: "nfs://", 0x0D: "ftp://", + 0x0E: "dav://", 0x0F: "news:", 0x10: "telent://", + 0x11: "imap:", 0x12: "rtsp://", 0x13: "urn:", + 0x14: "pop:", 0x15: "sip:", 0x16: "sips:", + 0x17: "tftp:", 0x18: "btspp://", 0x19: "btl2cap://", + 0x1A: "btgoep://", 0x1B: "tcpobex://", 0x1C: "irdaobex://", + 0x1D: "file://", 0x1E: "urn:epc:id:", 0x1F: "urn:epc:tag:", + 0x20: "urn:epc:pat:", 0x21: "urn:epc:raw:", 0x22: "urn:epc:", + 0x23: "urn:nfc:" } + + def _parse_item(self, item): + + item_type = item[1] + item_value = item[2] + + if item_type == 0x55: + # URL Type + if not item_value[0] > 0x23: + url = self._uri_lookup[item_value[0]] + toASCIIString(item_value[1:]) + else: + url = toASCIIString(item_value) + + self.items.append(["url", url]) + + + def __init__(self, ndef): + + if not ndef: + raise ValueError + + i = 0 + + while i <= len(ndef)-1: + + if ndef[i] == 0xD1: + ndef_mb = ndef[i+1] + ndef_len = ndef[i+2] + ndef_type = ndef[i+3] + ndef_value = ndef[i+4:i+4+ndef_len] + + self._records.append([ndef_mb, ndef_type, ndef_value]) + + i = i + 4 + ndef_len + else: + i = i + 1 + + for item in self._records: + self._parse_item(item) + + diff --git a/pytikitag/nfc/type2.py b/pytikitag/nfc/type2.py new file mode 100644 index 0000000..077010c --- /dev/null +++ b/pytikitag/nfc/type2.py @@ -0,0 +1,49 @@ +import ndef + +class NFCType2(): + + tags = [] + ndefs = [] + + def __init__(self, data): + + if not data: + raise ValueError + + # Minimum requirement is 6 x 4 byte pages to meet Type2 style tags + if len(data) > 6 * 4: + + # Set inital start point for a Type2, based on 3 pages of reserved + # data + i = 13 + + while i <= len(data)-1: + if data[i] == 0x00: + # Null, skip + i = i + 1 + + elif data[i] == 0x03: + # NDEF start tag + if data[i+1] == 0xFF: + # Multibyte length + tlv_len = data[i+2:i+3] + i = i + 4 + else: + tlv_len = data[i+1] + i = i + 2 + + tlv_data = data[i:i+tlv_len] + + i = i + tlv_len + + self.tags.append([0x03, tlv_data]) + + elif data[i] == 0xFE: + break + + else: + i = i + 1 + + for tag in self.tags: + if tag[0] == 0x03: + self.ndefs.append(ndef.NDEFReader(tag[1])) diff --git a/pytikitag/tikitag.py b/pytikitag/tikitag.py index b247755..d312ed0 100644 --- a/pytikitag/tikitag.py +++ b/pytikitag/tikitag.py @@ -1,4 +1,5 @@ import mifareul +from nfc import type2, ndef from smartcard.util import toHexString, toASCIIString class TikiTag(mifareul.MiFareUltralight): @@ -10,5 +11,9 @@ class TikiTag(mifareul.MiFareUltralight): return toHexString(d).replace(" ", "")[:16] def get_tag_url(self): - if toASCIIString(self.read_block(0x6)) == "tag.": - return "http://ttag.be/m/%s" % self.get_uid() + + self._tag = type2.NFCType2(self.read_tag()) + return self._tag.ndefs[0].items[0][1] + + + diff --git a/test.py b/test.py index bfda406..0ca39fa 100755 --- a/test.py +++ b/test.py @@ -1,6 +1,7 @@ #!/usr/bin/python import logging, sys from pytikitag import reader, tikitag +from pytikitag.nfc import type2 from smartcard.util import toHexString, toASCIIString log = logging.getLogger('pytikitag.mifareul') @@ -8,21 +9,15 @@ h = logging.StreamHandler(sys.stdout) log.addHandler(h) r = reader.TikiReader() - -print r.firmware_version() - m = tikitag.TikiTag(r) -print m.get_uid() +print "Tikitag ID: " + m.get_uid() +print "Manf: " + m.get_manf_ascii() + ", Serial: " + m.get_serial() +print "" +print "Reading Tikitag Data..." print m.get_tag_url() -#d = m.read_block(0x6) -#print "%s bytes" % len(d) -#print toASCIIString(d) - -#print m.write_block(0xf, [0xde, 0xad, 0xbe, 0xee]) - -#print toHexString(m.read_block(0xf)) - -print m.get_manf_ascii() -print m.get_serial() +#tag = type2.NFCType2(d) +#print tag.ndefs[0].items +#print toHexString(value) +#print toASCIIString(value)