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
*.seed
*.log
@@ -11,9 +31,4 @@ pids
logs
results
npm-debug.log
node_modules
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
[![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);

View File

@@ -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',
'<!(node -e "require(\'nan\')")'
],
'link_settings': {
'libraries': [ '-lpcsclite' ],
'library_dirs': [ '/usr/lib' ]
}
}],
['OS=="mac"', {
'libraries': ['-framework', 'PCSC'],
"include_dirs" : [ "<!(node -e \"require('nan')\")" ]
}],
['OS=="win"', {
'libraries': ['-lWinSCard'],
"include_dirs" : [ "<!(node -e \"require('nan')\")" ]
}]
]
}
]
"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",
"<!(node -e \"require('nan')\")"
],
"link_settings": {
"libraries": [
"-lpcsclite"
],
"library_dirs": [
"/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) {
console.log('Error(', this.name, '):', err.message);
});
pcsc.on('reader', function (reader) {
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();
}
});
}
});
}
}
});
console.log('New reader detected', reader.name);
reader.on('end', function() {
console.log('Reader', this.name, 'removed');
});
reader.on('error', function (err) {
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) {
console.log('PCSC error', err.message);
pcsc.on('error', function (err) {
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');
/****************************************************************************** var bt = require('buffertools'); */
const EventEmitter = require('events');
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
*/
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];
}
}

View File

@@ -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 <santiago.gimeno@gmail.com>",
"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 <santiago.gimeno@gmail.com>",
"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
}

View File

@@ -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() {