def cmd(message, **kwargs): """The *text* command creates an NFC Forum Text Record with the given input text. The text language defaults to 'en' and can be set with --language followed by the IANA language code. \b Examples: ndeftool text '' | hexdump -Cv ndeftool text 'Created with the nfcpy ndeftool.' print ndeftool text 'first record' text 'second record' print ndeftool text -l en 'English' text -l de 'Deutsch' print """ dmsg(__name__ + ' ' + str(kwargs)) if message is None: message = [] content = kwargs['text'] language = kwargs['language'] encoding = kwargs['encoding'] record = ndef.TextRecord(content, language, encoding) message.append(record) return message
def load_file(f, decode_errors): fn = getattr(f, 'name', '<stdin>') try: records = list(ndef.message_decoder(f.read(), decode_errors)) info("loaded %d record(s) from %s" % (len(records), fn)) return records except ndef.DecodeError as error: dmsg(str(error)) errmsg = "%s does not contain a valid NDEF message." % fn raise click.ClickException(errmsg)
def cmd(message, **kwargs): """The *smartposter* command creates an NFC Forum Smart Poster Record for the resource identifier. A smart poster record combines the uniform resource identifier with additional data such as titles and icons for representation and processing instructions for the reader application. A smart poster should have title text entries for the desired languages, added with repetitive '-t' options. An English title text may also be added with '-T'. The recommended action set with '-a' tells the reader application to either run the default action for the URI, save it for later or open for editing. A smart poster may also provide a collection of icons for graphical representation. An icon file is added with the '-i' option which may be used more than once. The icon type is determined from the file content and must be an 'image' or 'video' mime type. \b Examples: ndeftool smartposter http://nfcpy.org print ndeftool smartposter -T 'nfcpy project' http://nfcpy.org print ndeftool smartposter -t en 'nfcpy project' http://nfcpy.org print ndeftool smartposter -T 'EMERGENCY CALL 911' -a exec tel:911 ndeftool smartposter -i nfcpy-logo-32x32.ico http://nfcpy.org """ dmsg(__name__ + ' ' + str(kwargs)) if message is None: message = [] record = ndef.SmartposterRecord(kwargs['resource']) for lang, text in kwargs['titles']: record.set_title(text, lang) if kwargs['title']: record.set_title(kwargs['title'], 'en') if kwargs['action']: record.action = kwargs['action'] for icon_file in kwargs['icons']: icon_data = icon_file.read() icon_type = magic.from_buffer(icon_data, mime=True) if icon_type.startswith('image/') or icon_type.startswith('video/'): record.add_icon(icon_type, icon_data) else: errmsg = "file %s is not a proper icon file" % icon_file.name raise click.ClickException(errmsg) message.append(record) return message
def cmd(ctx, message, **kwargs): """The *load* command reads records or payloads from disk files or standard input. The files to read are searched with the pattern specified by PATH which in the simplest form is an existing file name. Other forms may include '*', '?' and character ranges expressed by '[]'. A single '-' may be used to read from standard input. Note that patterns containg wildcards may need to be escaped to avoid shell expansion. The default mode of operation is to load files containing NDEF records. In '--pack' mode the files are loaded into the payload of NDEF records with record type (NDEF Record TNF and TYPE) set to the mimetype discovered from the payload and record name (NDEF Record ID) set to the filename. \b Examples: ndeftool load message.ndef print ndeftool load '*.ndef' print cat message.ndef | ndeftool load - print ndeftool load --pack /etc/hostname print ndeftool load --pack '/etc/cron.daily/*' print """ dmsg(__name__ + ' ' + str(kwargs)) if message is None: message = [] if kwargs['path'] == '-': filenames = kwargs['path'] else: filenames = sorted(glob.iglob(kwargs['path'])) if len(filenames) == 0: info("No files selected by path '%s'." % kwargs['path']) for filename in filenames: try: f = click.open_file(filename, 'rb') except (OSError, IOError) as error: warn(str(error)) else: if kwargs['pack']: message.append(pack_file(f)) else: message.extend(load_file(f, ctx.meta['decode-errors'])) return message
def cmd(message, **kwargs): """The *uri* command creates an NFC Forum URI Record wit the given resource identifier. Note that this is actually an Internationalized Resource Identifier (IRI). \b Examples: ndeftool uri 'http://nfcpy.org' print """ dmsg(__name__ + ' ' + str(kwargs)) if message is None: message = [] record = ndef.UriRecord(kwargs['resource']) message.append(record) return message
def cmd(ctx, message, **kwargs): """The *payload* command either changes the current last record's data (NDEF Record PAYLOAD) or, if the current message does not have any records, creates a record with the given record data. The changed record is verified to successfully encode and decode unless disabled with -x. The data string may contain hexadecimal bytes using '\\xNN' notation where each N is a nibble from [0-F]. \b Examples: ndeftool payload 'Hello World' typename 'text/plain' print ndeftool payload '\\x02enHello World' typename 'urn:nfc:wkt:T' print -l """ dmsg(__name__ + ' ' + str(kwargs)) dmsg(repr(kwargs['data'])) if not message: message = [ndef.Record('unknown')] record_type = message[-1].type record_name = message[-1].name record_data = eval(repr(kwargs['data'].encode()).replace('\\\\', '\\')) record = ndef.Record(record_type, record_name, record_data) if not kwargs['no_check']: octets = b''.join(ndef.message_encoder([record])) errors = ctx.meta['decode-errors'] try: record = next(ndef.message_decoder(octets, errors)) except ndef.DecodeError as error: raise click.ClickException(str(error)) message[-1] = record return message
def cmd(message, **kwargs): """The *identifier* command either changes the current last record's name (NDEF Record ID) or, if the current message does not have any records, creates a record with unknown record type and the given record name. \b Examples: ndeftool identifier 'record identifier' print ndeftool text 'first' id 'r1' text 'second' id 'r2' print """ dmsg(__name__ + ' ' + str(kwargs)) if not message: message = [ndef.Record('unknown')] try: message[-1].name = kwargs['name'].encode('latin', 'replace') except ValueError as error: raise click.ClickException(str(error)) return message
def cmd(ctx, message, **kwargs): """The *typename* command either changes the current last record's type (NDEF Record TNF and TYPE) or, if the current message does not have any records, creates a record with the given record type. The changed record is verified to successfully encode and decode unless disabled with -x. \b Examples: ndeftool typename 'text/plain' print ndeftool typename 'text/plain' payload 'Hello World' print """ dmsg(__name__ + ' ' + str(kwargs)) if not message: message = [ndef.Record()] record_type = kwargs['type'].encode('latin', 'replace') record_name = message[-1].name record_data = message[-1].data try: record = ndef.Record(record_type, record_name, record_data) except ValueError as error: raise click.ClickException(str(error)) if not kwargs['no_check']: octets = b''.join(ndef.message_encoder([record])) errors = ctx.meta['decode-errors'] try: record = next(ndef.message_decoder(octets, errors)) except ndef.DecodeError as error: raise click.ClickException(str(error)) message[-1] = record return message
def cmd(ctx, message, **kwargs): """The *print* command outputs a formatted representation of all current NDEF Records. By default this is the one line str() representation for each record. The '--long' format produces multiple indented lines per record in an attempt to provide a more readable output. Printing consumes all records so that no more data is send to stdout or given to the next command. This can be changed with the '--keep' flag. When given as the first command *print* attempts to decode an NDEF message from standard input and then process the generated list of records. \b Examples: ndeftool text 'made with ndeftool' print ndeftool text 'say one' print text 'say two' print ndeftool text one print --keep text two print ndeftool text 'print from stdin' | ndeftool print ndeftool text 'before' | ndeftool print text 'after' print """ dmsg(__name__ + ' ' + str(kwargs)) if message is None: info("Reading data from standard input") octets = click.get_binary_stream('stdin').read() errors = ctx.meta['decode-errors'] try: message = list(ndef.message_decoder(octets, errors)) except ndef.DecodeError as error: raise click.ClickException(str(error)) for index, record in enumerate(message): if not kwargs['long']: echo(str(record)) continue if isinstance(record, ndef.TextRecord): echo("NFC Forum Text Record [record #{}]".format(index + 1)) echo(LONG_FORMAT.format("content", record.text)) echo(LONG_FORMAT.format("language", record.language)) echo(LONG_FORMAT.format("encoding", record.encoding)) elif isinstance(record, ndef.UriRecord): echo("NFC Forum URI Record [record #{}]".format(index + 1)) echo(LONG_FORMAT.format("resource", record.iri)) elif isinstance(record, ndef.SmartposterRecord): echo("NFC Forum Smart Poster Record [record #{}]".format(index + 1)) echo(LONG_FORMAT.format("resource", record.resource.iri)) if record.action: echo(LONG_FORMAT.format("action", record.action)) for lang, text in record.titles.items(): echo(LONG_FORMAT.format("title_" + lang, text)) for icon_type, icon_data in record.icons.items(): echo(LONG_FORMAT.format(icon_type, "%d byte" % len(icon_data))) else: echo("Record [record #{}]".format(index + 1)) echo(LONG_FORMAT.format("type", record.type)) echo(LONG_FORMAT.format("name", record.name)) echo(LONG_FORMAT.format("data", bytes(record.data))) return message if kwargs['keep'] else []
def cmd(ctx, message, **kwargs): """The *save* command writes the current records to disk. The records to write can be restricted to the subset selected with '--skip', '--count', '--head' and '--tail' applied in that order. The default mode is to save all selected records as one NDEF message into a single file given by PATH. In '--burst' mode each record is written as one NDEF message into a separate file under the directory given by PATH. The file names are three digit numbers created from the record index. In '--unpack' mode the payload of each record is written to a separate file under directory PATH with the file name set to the record name (NDEF Record ID). Records without name are not written unless '--unpack' and '--burst' are both set. The *save* command does not replace existing files or directories unless this is requested with '--force'. The *save* command consumes records from the internal message pipe. This can be prevented with '--keep', all records are then forwarded to the next command or written to standard output. When *save* is the first command it creates the pipe by reading from standard input. \b Examples: ndeftool text 'Hello World' save text.ndef ndeftool text 'Hello World' | ndeftool save text.ndef ndeftool text 'One' save one.ndef text 'Two' save two.ndef """ dmsg(__name__ + ' ' + str(kwargs)) path = kwargs['path'] if os.path.exists(path) and not kwargs['force']: errmsg = "path '%s' exists. Use '--force' to replace." raise click.ClickException(errmsg % path) if message is None: info("Reading data from standard input") octets = click.get_binary_stream('stdin').read() errors = ctx.meta['decode-errors'] try: message = list(ndef.message_decoder(octets, errors)) except ndef.DecodeError as error: raise click.ClickException(str(error)) first = min(kwargs['skip'], len(message)) count = min(kwargs['count'] or len(message), len(message)) head = min(kwargs['head'] or count, count) tail = min(kwargs['tail'] or count, count) dmsg("first=%d count=%d head=%d tail=%d" % (first, count, head, tail)) count = min(head, tail, len(message) - first) first = first + head - min(head, tail) dmsg("first=%d count=%d head=%d tail=%d" % (first, count, head, tail)) if kwargs['burst'] or kwargs['unpack']: path = os.path.normpath(path) try: if os.path.isdir(path): shutil.rmtree(path) os.mkdir(path) except (OSError, IOError) as error: raise click.ClickException(str(error)) for index, record in enumerate(message[first:first + count]): name = None if kwargs['unpack'] and record.name: name = record.name if kwargs['burst'] and not name: name = '%03d.ndef' % index if name: with click.open_file('%s/%s' % (path, name), 'wb') as f: info("Saving 1 record to {}.".format(f.name)) if kwargs['unpack']: f.write(record.data) else: f.write(b''.join(ndef.message_encoder([record]))) else: warn("Skipping 1 record without name") else: with click.open_file(path, 'wb') as f: filename = f.name if f.name != '-' else '<stdout>' info("Saving {num} record{s} to {path}.".format( num=count, path=filename, s=('', 's')[count > 1])) f.write(b''.join(ndef.message_encoder(message[first:first + count]))) if not kwargs['keep']: del message[first:first + count] return message