fixed parse readers string function

added .editorconfig
formatted code
updated dependencies
improved package.json
fixed version number
This commit is contained in:
Martin Endler
2016-08-10 20:39:11 +02:00
parent f65937eb9c
commit c3c3cf33ef
17 changed files with 414 additions and 266 deletions

21
.editorconfig Executable file
View File

@@ -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

25
.gitignore vendored
View File

@@ -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 lib-cov
*.seed *.seed
*.log *.log
@@ -11,9 +31,4 @@ pids
logs logs
results results
npm-debug.log
node_modules
build/ build/
.npmrc
*sublime*

6
.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

7
.idea/jsLibraryMappings.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="ECMAScript 6" />
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

19
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="SvnConfiguration">
<configuration>$USER_HOME$/.subversion</configuration>
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/node-pcsclite.iml" filepath="$PROJECT_DIR$/.idea/node-pcsclite.iml" />
</modules>
</component>
</project>

12
.idea/node-pcsclite.iml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

4
.idea/watcherTasks.xml generated Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions" suppressed-tasks="Babel" />
</project>

View File

@@ -1,2 +0,0 @@
*.sublime*
.npmrc

View File

@@ -1,39 +1,38 @@
# node-pcsclite # 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**. Bindings over pcsclite to access Smart Cards. Starting with version **0.4.0** it works in **Linux**, **OS X** and **Windows**.
## Installation ## 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/) In **macOS** and **Windows** you **don't have to install** anything.
* 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
> 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: 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 ## Example
``` ```javascript
var pcsc = require('pcsclite'); const pcsclite = require('pcsclite');
const pcsc = pcsclite();
var pcsc = pcsc();
pcsc.on('reader', function(reader) { pcsc.on('reader', function(reader) {
console.log('New reader detected', reader.name); console.log('New reader detected', reader.name);

View File

@@ -1,37 +1,63 @@
{ {
'targets': [ "targets": [
{ {
'target_name': 'pcsclite', "target_name": "pcsclite",
'sources': [ 'src/addon.cpp', 'src/pcsclite.cpp', 'src/cardreader.cpp' ], "sources": [
'cflags': [ "src/addon.cpp",
'-Wall', "src/pcsclite.cpp",
'-Wextra', "src/cardreader.cpp"
'-Wno-unused-parameter', ],
'-fPIC', "cflags": [
'-fno-strict-aliasing', "-Wall",
'-fno-exceptions', "-Wextra",
'-pedantic' "-Wno-unused-parameter",
], "-fPIC",
'conditions': [ "-fno-strict-aliasing",
['OS=="linux"', { "-fno-exceptions",
'include_dirs': [ "-pedantic"
'/usr/include/PCSC', ],
'<!(node -e "require(\'nan\')")' "conditions": [
], [
'link_settings': { "OS=='linux'",
'libraries': [ '-lpcsclite' ], {
'library_dirs': [ '/usr/lib' ] "include_dirs": [
} "/usr/include/PCSC",
}], "<!(node -e \"require('nan')\")"
['OS=="mac"', { ],
'libraries': ['-framework', 'PCSC'], "link_settings": {
"include_dirs" : [ "<!(node -e \"require('nan')\")" ] "libraries": [
}], "-lpcsclite"
['OS=="win"', { ],
'libraries': ['-lWinSCard'], "library_dirs": [
"include_dirs" : [ "<!(node -e \"require('nan')\")" ] "/usr/lib"
}] ]
] }
} }
] ],
[
"OS=='mac'",
{
"libraries": [
"-framework",
"PCSC"
],
"include_dirs": [
"<!(node -e \"require('nan')\")"
]
}
],
[
"OS=='win'",
{
"libraries": [
"-lWinSCard"
],
"include_dirs": [
"<!(node -e \"require('nan')\")"
]
}
]
]
}
]
} }

View File

@@ -1,57 +1,61 @@
#!/usr/bin/env node "use strict";
var pcsc = require('../index'); const pcsclite = require('../lib/pcsclite');
var pcsc = pcsc();
pcsc.on('reader', function(reader) {
console.log('New reader detected', reader.name); const pcsc = pcsclite();
reader.on('error', function(err) { pcsc.on('reader', function (reader) {
console.log('Error(', this.name, '):', err.message);
});
reader.on('status', function(status) { console.log('New reader detected', reader.name);
console.log('Status(', this.name, '):', status);
/* check what has changed */
var changes = this.state ^ status.state;
if (changes) {
if ((changes & this.SCARD_STATE_EMPTY) && (status.state & this.SCARD_STATE_EMPTY)) {
console.log("card removed");/* card removed */
reader.disconnect(reader.SCARD_LEAVE_CARD, function(err) {
if (err) {
console.log(err);
} else {
console.log('Disconnected');
}
});
} else if ((changes & this.SCARD_STATE_PRESENT) && (status.state & this.SCARD_STATE_PRESENT)) {
console.log("card inserted");/* card inserted */
reader.connect({ share_mode : this.SCARD_SHARE_SHARED }, function(err, protocol) {
if (err) {
console.log(err);
} else {
console.log('Protocol(', reader.name, '):', protocol);
reader.transmit(new Buffer([0x00, 0xB0, 0x00, 0x00, 0x20]), 40, protocol, function(err, data) {
if (err) {
console.log(err);
} else {
console.log('Data received', data);
reader.close();
pcsc.close();
}
});
}
});
}
}
});
reader.on('end', function() { reader.on('error', function (err) {
console.log('Reader', this.name, 'removed'); console.log('Error(', this.name, '):', err.message);
}); });
reader.on('status', function (status) {
console.log('Status(', this.name, '):', status);
/* check what has changed */
var changes = this.state ^ status.state;
if (changes) {
if ((changes & this.SCARD_STATE_EMPTY) && (status.state & this.SCARD_STATE_EMPTY)) {
console.log("card removed");
/* card removed */
reader.disconnect(reader.SCARD_LEAVE_CARD, function (err) {
if (err) {
console.log(err);
} else {
console.log('Disconnected');
}
});
} else if ((changes & this.SCARD_STATE_PRESENT) && (status.state & this.SCARD_STATE_PRESENT)) {
console.log("card inserted");
/* card inserted */
reader.connect({share_mode: this.SCARD_SHARE_SHARED}, function (err, protocol) {
if (err) {
console.log(err);
} else {
console.log('Protocol(', reader.name, '):', protocol);
reader.transmit(new Buffer([0x00, 0xB0, 0x00, 0x00, 0x20]), 40, protocol, function (err, data) {
if (err) {
console.log(err);
} else {
console.log('Data received', data);
reader.close();
pcsc.close();
}
});
}
});
}
}
});
reader.on('end', function () {
console.log('Reader', this.name, 'removed');
});
}); });
pcsc.on('error', function(err) { pcsc.on('error', function (err) {
console.log('PCSC error', err.message); console.log('PCSC error', err.message);
}); });

View File

@@ -1 +0,0 @@
module.exports = require('./lib/pcsclite');

View File

@@ -1,155 +1,174 @@
"use strict";
var events = require('events'); const EventEmitter = require('events');
/****************************************************************************** var bt = require('buffertools'); */ const pcsclite = require('bindings')('pcsclite');
const {PCSCLite, CardReader} = pcsclite;
/* Make sure we choose the correct build directory */
var bindings = require('bindings')('pcsclite');
var PCSCLite = bindings.PCSCLite;
var CardReader = bindings.CardReader;
inherits(PCSCLite, events.EventEmitter);
inherits(CardReader, events.EventEmitter);
/**
var parse_readers_string = function(readers_str) {
var pos;
var readers = [];
var ini = 0;
while ((pos = bt.indexOf(readers_str.slice(ini), '\0')) > 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 * It returns an array with the elements contained in a that aren't contained in b
*/ */
function diff(a, 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 = {}; if (typeof options === 'function') {
var p = new PCSCLite(); cb = options;
process.nextTick(function() { options = undefined;
p.start(function(err, data) { }
if (err) {
return p.emit('error', err);
}
/************************************************************* var names = parse_readers_string(data); */ options = options || {};
var names = parse_readers_string_by_hapet(data); 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); if (!this.connected) {
var new_names = diff(names, current_names); this._connect(options.share_mode, options.protocol, cb);
var removed_names = diff(current_names, names); } 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) { CardReader.prototype.disconnect = function (disposition, cb) {
if (typeof options === 'function') {
cb = options;
options = undefined;
}
options = options || {}; if (typeof disposition === 'function') {
options.share_mode = options.share_mode || this.SCARD_SHARE_EXCLUSIVE; cb = disposition;
options.protocol = options.protocol || this.SCARD_PROTOCOL_T0 | this.SCARD_PROTOCOL_T1; 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) { CardReader.prototype.transmit = function (data, res_len, protocol, cb) {
if (typeof disposition === 'function') {
cb = disposition;
disposition = undefined;
}
if (typeof disposition !== 'number') { if (!this.connected) {
disposition = this.SCARD_UNPOWER_CARD; 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) { CardReader.prototype.control = function (data, control_code, res_len, cb) {
if (!this.connected) {
return cb(new Error("Card Reader not connected"));
}
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) { const output = new Buffer(res_len);
if (!this.connected) {
return cb(new Error("Card Reader not connected"));
}
var output = new Buffer(res_len); this._control(data, control_code, output, function (err, len) {
this._control(data, control_code, output, function(err, len) { if (err) {
if (err) { return cb(err);
return cb(err); }
}
cb(err, output.slice(0, len));
});
cb(err, output.slice(0, len));
});
}; };
// extend prototype // extend prototype
function inherits(target, source) { 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];
}
} }

View File

@@ -1,34 +1,39 @@
{ {
"name": "pcsclite", "name": "@pokusew/pcsclite",
"version": "0.4.91", "version": "0.4.11",
"description": "Bindings over PC/SC to access Smart Cards", "description": "Bindings over PC/SC to access Smart Cards",
"main": "index.js", "keywords": [
"directories": { "pcsc",
"test": "test" "pcsclite",
}, "nfc",
"dependencies": { "smartcards"
"bindings": "^1.2.0", ],
"nan": "^2.3.5" "homepage": "https://github.com/pokusew/node-pcsclite#readme",
}, "bugs": {
"devDependencies": { "url": "https://github.com/pokusew/node-pcsclite/issues"
"mocha": "~1.11.0", },
"sinon": "~1.3.4", "license": "ISC",
"should": "~1.2.2" "author": "Santiago Gimeno <santiago.gimeno@gmail.com>",
}, "main": "lib/pcsclite.js",
"scripts": { "directories": {
"test": "mocha", "test": "test"
"install": "node-gyp rebuild" },
}, "repository": {
"repository": "https://github.com/santigimeno/node-pcsclite.git", "type": "git",
"keywords": [ "url": "https://github.com/pokusew/node-pcsclite.git"
"pcsc", },
"pcsclite", "scripts": {
"smartcards" "install": "node-gyp rebuild",
], "test": "mocha"
"author": "Santiago Gimeno <santiago.gimeno@gmail.com>", },
"license": { "dependencies": {
"type": "ISC", "bindings": "^1.2.1",
"url": "https://github.com/santigimeno/node-pcsclite/blob/master/LICENSE" "nan": "^2.4.0"
}, },
"gypfile": true "devDependencies": {
"mocha": "^3.0.2",
"should": "^11.0.0",
"sinon": "^1.17.5"
},
"gypfile": true
} }

View File

@@ -1,6 +1,6 @@
var should = require('should'); const should = require('should');
var sinon = require('sinon'); const sinon = require('sinon');
var pcsc = require('../lib/pcsclite'); const pcsc = require('../lib/pcsclite');
describe('Testing PCSCLite private', function() { describe('Testing PCSCLite private', function() {