diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..6b0ca6b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# editorconfig.org +root = true + +[*] +indent_style = tab +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[package.json] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index 57f1e52..571050d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,23 @@ +# node, npm +node_modules/ + +# Windows +Thumbs.db +Desktop.ini + +# Mac +.DS_Store +.supported + +# NetBeans +/nbproject/private/ + +# WebStorm +**/.idea/workspace.xml +**/.idea/tasks.xml + +dist/ + lib-cov *.seed *.log @@ -11,9 +31,4 @@ pids logs results -npm-debug.log -node_modules build/ - -.npmrc -*sublime* diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..f3e502d --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0997ad1 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + $USER_HOME$/.subversion + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..c6c77ab --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/node-pcsclite.iml b/.idea/node-pcsclite.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/node-pcsclite.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml new file mode 100644 index 0000000..9338ba6 --- /dev/null +++ b/.idea/watcherTasks.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.npmignore b/.npmignore index 75a5f79..e69de29 100644 --- a/.npmignore +++ b/.npmignore @@ -1,2 +0,0 @@ -*.sublime* -.npmrc diff --git a/README.md b/README.md index 4e0e886..4795f4b 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,38 @@ # node-pcsclite -[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/santigimeno/node-pcsclite?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Bindings over pcsclite to access Smart Cards. Starting with version **0.4.0** it works in **Linux**, **OS X** and **Windows**. ## Installation -You'll need a node version installed in the system. You have several options: +In order to install the package you need to **have installed in the system the +pcsclite libraries**. -* Download and install it from the [node website](http://nodejs.org/) -* Install it from your own distro. For the Debian users: - - `apt-get install nodejs nodejs-legacy` - -* Use [nodesource repository](https://github.com/nodesource/distributions) for different distros. -* Use tools like [nave](https://github.com/isaacs/nave) or [nvm](https://github.com/creationix/nvm) - -In order to install the package you need to have installed in the system the -pcsclite libraries. For example, in Debian/Ubuntu: - - apt-get install libpcsclite1 libpcsclite-dev - -Once they are installed just run: - - npm install pcsclite +In **macOS** and **Windows** you **don't have to install** anything. +> For example, in Debian/Ubuntu: +```bash +apt-get install libpcsclite1 libpcsclite-dev +``` To run any code you will also need to have installed the pcsc daemon: +```bash +apt-get install pcscd +``` + +Once you have all needed libraries, you can install using npm: + +```bash +npm install @pokusew/pcsclite --save +``` + - apt-get install pcscd ## Example -``` -var pcsc = require('pcsclite'); +```javascript +const pcsclite = require('pcsclite'); + +const pcsc = pcsclite(); -var pcsc = pcsc(); pcsc.on('reader', function(reader) { console.log('New reader detected', reader.name); diff --git a/binding.gyp b/binding.gyp index eb58aa6..76ba476 100644 --- a/binding.gyp +++ b/binding.gyp @@ -1,37 +1,63 @@ { - 'targets': [ - { - 'target_name': 'pcsclite', - 'sources': [ 'src/addon.cpp', 'src/pcsclite.cpp', 'src/cardreader.cpp' ], - 'cflags': [ - '-Wall', - '-Wextra', - '-Wno-unused-parameter', - '-fPIC', - '-fno-strict-aliasing', - '-fno-exceptions', - '-pedantic' - ], - 'conditions': [ - ['OS=="linux"', { - 'include_dirs': [ - '/usr/include/PCSC', - ' 0) { - readers.push(readers_str.slice(ini, ini + pos).toString()); - ini += pos + 1; - } - return readers; -}; -*/ +inherits(PCSCLite, EventEmitter); +inherits(CardReader, EventEmitter); -var parse_readers_string_by_hapet = function(readers_str) { +function parseReadersString(buffer) { - // without buffertool module ;) + const string = buffer.toString().slice(0, -1); + + // it looks like + // ACS ACR122U PICC Interface\u0000ACS ACR122U PICC Interface 01\u0000\u0000 + // [reader_name]\u0000[reader_name]\u0000\u0000 + // ^separator ^separator^end_separator + + // returns readers in array + // like [ 'ACS ACR122U PICC Interface', 'ACS ACR122U PICC Interface 01' ] + + return string.split('\u0000').slice(0, -1); - return [readers_str]; } /* * It returns an array with the elements contained in a that aren't contained in b */ function diff(a, b) { - return a.filter(function(i) { - return b.indexOf(i) === -1; - }); + + return a.filter(i => b.indexOf(i) === -1); + +} + +module.exports = function () { + + const readers = {}; + + const p = new PCSCLite(); + + process.nextTick(function () { + + p.start(function (err, data) { + + if (err) { + return p.emit('error', err); + } + + const names = parseReadersString(data); + + const currentNames = Object.keys(readers); + const newNames = diff(names, currentNames); + const removedNames = diff(currentNames, names); + + newNames.forEach(function (name) { + + const r = new CardReader(name); + + r.on('_end', function () { + r.removeAllListeners('status'); + r.emit('end'); + delete readers[name]; + }); + + readers[name] = r; + + r.get_status(function (err, state, atr) { + + if (err) { + return r.emit('error', err); + } + + const status = {state: state}; + + if (atr) { + status.atr = atr; + } + + r.emit('status', status); + + r.state = state; + + }); + + p.emit('reader', r); + + }); + + removedNames.forEach(function (name) { + readers[name].close(); + }); + + }); + + }); + + return p; }; -module.exports = function() { +CardReader.prototype.connect = function (options, cb) { - var readers = {}; - var p = new PCSCLite(); - process.nextTick(function() { - p.start(function(err, data) { - if (err) { - return p.emit('error', err); - } + if (typeof options === 'function') { + cb = options; + options = undefined; + } - /************************************************************* var names = parse_readers_string(data); */ - var names = parse_readers_string_by_hapet(data); + options = options || {}; + options.share_mode = options.share_mode || this.SCARD_SHARE_EXCLUSIVE; + options.protocol = options.protocol || this.SCARD_PROTOCOL_T0 | this.SCARD_PROTOCOL_T1; - var current_names = Object.keys(readers); - var new_names = diff(names, current_names); - var removed_names = diff(current_names, names); + if (!this.connected) { + this._connect(options.share_mode, options.protocol, cb); + } else { + cb(); + } - new_names.forEach(function(name) { - var r = new CardReader(name); - r.on('_end', function() { - r.removeAllListeners('status'); - r.emit('end'); - delete readers[name]; - }); - - readers[name] = r; - r.get_status(function(err, state, atr) { - if (err) { - return r.emit('error', err); - } - - var status = { state : state }; - if (atr) { - status.atr = atr; - } - - r.emit('status', status); - r.state = state; - }); - - p.emit('reader', r); - }); - - removed_names.forEach(function(name) { - readers[name].close(); - }); - }); - }); - - return p; }; -CardReader.prototype.connect = function(options, cb) { - if (typeof options === 'function') { - cb = options; - options = undefined; - } +CardReader.prototype.disconnect = function (disposition, cb) { - options = options || {}; - options.share_mode = options.share_mode || this.SCARD_SHARE_EXCLUSIVE; - options.protocol = options.protocol || this.SCARD_PROTOCOL_T0 | this.SCARD_PROTOCOL_T1; + if (typeof disposition === 'function') { + cb = disposition; + disposition = undefined; + } + + if (typeof disposition !== 'number') { + disposition = this.SCARD_UNPOWER_CARD; + } + + if (this.connected) { + this._disconnect(disposition, cb); + } else { + cb(); + } - if (!this.connected) { - this._connect(options.share_mode, options.protocol, cb); - } else { - cb(); - } }; -CardReader.prototype.disconnect = function(disposition, cb) { - if (typeof disposition === 'function') { - cb = disposition; - disposition = undefined; - } +CardReader.prototype.transmit = function (data, res_len, protocol, cb) { - if (typeof disposition !== 'number') { - disposition = this.SCARD_UNPOWER_CARD; - } + if (!this.connected) { + return cb(new Error('Card Reader not connected')); + } + + this._transmit(data, res_len, protocol, cb); - if (this.connected) { - this._disconnect(disposition, cb); - } else { - cb(); - } }; -CardReader.prototype.transmit = function(data, res_len, protocol, cb) { - if (!this.connected) { - return cb(new Error("Card Reader not connected")); - } +CardReader.prototype.control = function (data, control_code, res_len, cb) { - this._transmit(data, res_len, protocol, cb); -}; + if (!this.connected) { + return cb(new Error('Card Reader not connected')); + } -CardReader.prototype.control = function(data, control_code, res_len, cb) { - if (!this.connected) { - return cb(new Error("Card Reader not connected")); - } + const output = new Buffer(res_len); - var output = new Buffer(res_len); - this._control(data, control_code, output, function(err, len) { - if (err) { - return cb(err); - } + this._control(data, control_code, output, function (err, len) { + if (err) { + return cb(err); + } + + cb(err, output.slice(0, len)); + }); - cb(err, output.slice(0, len)); - }); }; // extend prototype function inherits(target, source) { - for (var k in source.prototype) { - target.prototype[k] = source.prototype[k]; - } + + for (const k in source.prototype) { + target.prototype[k] = source.prototype[k]; + } + } diff --git a/package.json b/package.json index 53d83b4..440341c 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,39 @@ { - "name": "pcsclite", - "version": "0.4.91", - "description": "Bindings over PC/SC to access Smart Cards", - "main": "index.js", - "directories": { - "test": "test" - }, - "dependencies": { - "bindings": "^1.2.0", - "nan": "^2.3.5" - }, - "devDependencies": { - "mocha": "~1.11.0", - "sinon": "~1.3.4", - "should": "~1.2.2" - }, - "scripts": { - "test": "mocha", - "install": "node-gyp rebuild" - }, - "repository": "https://github.com/santigimeno/node-pcsclite.git", - "keywords": [ - "pcsc", - "pcsclite", - "smartcards" - ], - "author": "Santiago Gimeno ", - "license": { - "type": "ISC", - "url": "https://github.com/santigimeno/node-pcsclite/blob/master/LICENSE" - }, - "gypfile": true + "name": "@pokusew/pcsclite", + "version": "0.4.11", + "description": "Bindings over PC/SC to access Smart Cards", + "keywords": [ + "pcsc", + "pcsclite", + "nfc", + "smartcards" + ], + "homepage": "https://github.com/pokusew/node-pcsclite#readme", + "bugs": { + "url": "https://github.com/pokusew/node-pcsclite/issues" + }, + "license": "ISC", + "author": "Santiago Gimeno ", + "main": "lib/pcsclite.js", + "directories": { + "test": "test" + }, + "repository": { + "type": "git", + "url": "https://github.com/pokusew/node-pcsclite.git" + }, + "scripts": { + "install": "node-gyp rebuild", + "test": "mocha" + }, + "dependencies": { + "bindings": "^1.2.1", + "nan": "^2.4.0" + }, + "devDependencies": { + "mocha": "^3.0.2", + "should": "^11.0.0", + "sinon": "^1.17.5" + }, + "gypfile": true } diff --git a/test/test.js b/test/test.js index 046e129..4e76c3f 100644 --- a/test/test.js +++ b/test/test.js @@ -1,6 +1,6 @@ -var should = require('should'); -var sinon = require('sinon'); -var pcsc = require('../lib/pcsclite'); +const should = require('should'); +const sinon = require('sinon'); +const pcsc = require('../lib/pcsclite'); describe('Testing PCSCLite private', function() {