isbinaryfile
Advanced tools
Comparing version 1.0.1 to 2.0.0
126
index.js
var fs = require('fs'); | ||
var path = require("path"); | ||
var max_bytes = 512; | ||
module.exports = function(bytes, size) { | ||
var max_bytes = 512; | ||
// Read the file with no encoding for raw buffer access. | ||
if (size === undefined) { | ||
var file = bytes; | ||
if (!fs.existsSync(file)) | ||
return false; | ||
var descriptor = fs.openSync(file, 'r'); | ||
try { | ||
bytes = new Buffer(max_bytes); | ||
size = fs.readSync(descriptor, bytes, 0, bytes.length, 0); | ||
} finally { | ||
fs.closeSync(descriptor); | ||
} | ||
// Read the file with no encoding for raw buffer access. | ||
if (size === undefined) { | ||
var file = bytes, existsSync = fs.existsSync || path.existsSync; | ||
if (!existsSync(file)) | ||
return false; | ||
var descriptor = fs.openSync(file, 'r'); | ||
try { | ||
bytes = new Buffer(max_bytes); | ||
size = fs.readSync(descriptor, bytes, 0, bytes.length, 0); | ||
} finally { | ||
fs.closeSync(descriptor); | ||
} | ||
} | ||
else if (typeof size === "function") { | ||
var file = bytes, callback = size; | ||
var exists = fs.exists || path.exists; | ||
exists(file, function (exists) { | ||
if (!exists) return callback(null, false); | ||
if (size == 0) | ||
return false; | ||
fs.open(file, 'r', function(err, descriptor){ | ||
if (err) return callback(err); | ||
var bytes = new Buffer(max_bytes); | ||
// Read the file with no encoding for raw buffer access. | ||
fs.read(descriptor, bytes, 0, bytes.length, 0, function(err, size, bytes){ | ||
fs.close(descriptor, function(err2){ | ||
if (err || err2) | ||
return callback(err || err2); | ||
return callback(null, isBinaryCheck(bytes, size)); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} | ||
var suspicious_bytes = 0; | ||
var total_bytes = Math.min(size, max_bytes); | ||
return isBinaryCheck(bytes, size); | ||
} | ||
if (size >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) { | ||
// UTF-8 BOM. This isn't binary. | ||
return false; | ||
} | ||
function isBinaryCheck(bytes, size) { | ||
if (size === 0) | ||
return false; | ||
for (var i = 0; i < total_bytes; i++) { | ||
if (bytes[i] == 0) { // NULL byte--it's binary! | ||
return true; | ||
} | ||
else if ((bytes[i] < 7 || bytes[i] > 14) && (bytes[i] < 32 || bytes[i] > 127)) { | ||
// UTF-8 detection | ||
if (bytes[i] > 191 && bytes[i] < 224 && i + 1 < total_bytes) { | ||
i++; | ||
if (bytes[i] < 192) { | ||
continue; | ||
} | ||
} | ||
else if (bytes[i] > 223 && bytes[i] < 239 && i + 2 < total_bytes) { | ||
i++; | ||
if (bytes[i] < 192 && bytes[i + 1] < 192) { | ||
i++; | ||
continue; | ||
} | ||
} | ||
suspicious_bytes++; | ||
// Read at least 32 bytes before making a decision | ||
if (i > 32 && (suspicious_bytes * 100) / total_bytes > 10) { | ||
return true; | ||
} | ||
} | ||
} | ||
var suspicious_bytes = 0; | ||
var total_bytes = Math.min(size, max_bytes); | ||
if ((suspicious_bytes * 100) / total_bytes > 10) { | ||
return true; | ||
if (size >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) { | ||
// UTF-8 BOM. This isn't binary. | ||
return false; | ||
} | ||
for (var i = 0; i < total_bytes; i++) { | ||
if (bytes[i] === 0) { // NULL byte--it's binary! | ||
return true; | ||
} | ||
else if ((bytes[i] < 7 || bytes[i] > 14) && (bytes[i] < 32 || bytes[i] > 127)) { | ||
// UTF-8 detection | ||
if (bytes[i] > 191 && bytes[i] < 224 && i + 1 < total_bytes) { | ||
i++; | ||
if (bytes[i] < 192) { | ||
continue; | ||
} | ||
} | ||
else if (bytes[i] > 223 && bytes[i] < 239 && i + 2 < total_bytes) { | ||
i++; | ||
if (bytes[i] < 192 && bytes[i + 1] < 192) { | ||
i++; | ||
continue; | ||
} | ||
} | ||
suspicious_bytes++; | ||
// Read at least 32 bytes before making a decision | ||
if (i > 32 && (suspicious_bytes * 100) / total_bytes > 10) { | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
if ((suspicious_bytes * 100) / total_bytes > 10) { | ||
return true; | ||
} | ||
return false; | ||
} |
{ | ||
"name": "isbinaryfile", | ||
"version" : "1.0.1", | ||
"version" : "2.0.0", | ||
"description": "Detects if a file is binary in Node.js. Similar to Perl's -B.", | ||
@@ -5,0 +5,0 @@ "main" : "./lib/panino.js", |
isBinaryFile | ||
============ | ||
Detects if a file is binary in Node.js. Similar to [Perl's `-B` switch](http://stackoverflow.com/questions/899206/how-does-perl-know-a-file-is-binary), in that: | ||
Detects if a file is binary in Node.js. Similar to [Perl's `-B` | ||
switch](http://stackoverflow.com/questions/899206/how-does-perl-know-a-file-is-binary), | ||
in that: | ||
* it reads the first few thousand bytes of a file | ||
* checks for a `null` byte; if it's found, it's binary | ||
* flags non-ASCII characters. After a certain number of "weird" characters, the file is flagged as binary | ||
* flags non-ASCII characters. After a certain number of "weird" characters, the | ||
file is flagged as binary | ||
All the logic is also pretty much ported from [ag](https://github.com/ggreer/the_silver_searcher). | ||
All the logic is also pretty much ported from | ||
[ag](https://github.com/ggreer/the_silver_searcher). | ||
@@ -22,26 +30,29 @@ Note: if the file doesn't exist or it is empty, this function returns `false`. | ||
If you pass in one argument, this module assumes it's just the file path, and performs the appropriate file read and stat functionality internally: | ||
If you pass in one argument, this module assumes it's just the file path, and | ||
performs the appropriate file read and stat functionality internally, as sync | ||
options: | ||
```javascript | ||
var isBinaryFileSync = require("isbinaryfile").isBinaryFileSync; | ||
``` javascript | ||
var isBinaryFileSync = require("isbinaryfile"); | ||
if (isBinaryFileSync(process.argv[2])) | ||
console.log("It is!") | ||
console.log("It is!") | ||
else | ||
console.log("No.") | ||
console.log("No.") | ||
``` | ||
Ta da. | ||
Ta da. | ||
However, if you've already read and `stat()`-ed a file (for some other reason), | ||
you can pass in both the file's raw data and the stat's `size` info to save | ||
time: | ||
However, if you've already read and `stat()`-ed a file (for some other reason), you can pass in both the file's raw data and the stat's `size` info to save time: | ||
```javascript | ||
fs.readFile(process.argv[2], function(err, data) { | ||
fs.lstat(process.argv[2], function(err, stat) { | ||
if (isBinaryFileSync(data, stat.size)) | ||
console.log("It is!") | ||
else | ||
console.log("No.") | ||
}); | ||
fs.lstat(process.argv[2], function(err, stat) { | ||
if (isBinaryFileSync(data, stat.size)) | ||
console.log("It is!") | ||
else | ||
console.log("No.") | ||
}); | ||
}); | ||
@@ -52,8 +63,19 @@ ``` | ||
Previous to version 1.0.0, this program always ran in sync mode. Now, there's an | ||
async option. The async option is a method called `isBinaryFile`. Its callback | ||
has two arguments: `err` and `isBinary`. | ||
Previous to version 2.0.0, this program always ran in sync mode. Now, there's | ||
an async option. Simply pass a function as your second parameter, and isBinaryFile | ||
will figure the rest out: | ||
The sync option is called `isBinaryFileSync`. | ||
``` javascript | ||
var isBinaryFileSync = require("isbinaryfile"); | ||
isBinaryFileSync(process.argv[2], function(err, result) { | ||
if (err) return console.error(err); | ||
if (result) | ||
console.log("It is!") | ||
else | ||
console.log("No.") | ||
} | ||
``` | ||
## Testing | ||
@@ -71,3 +93,3 @@ | ||
Copyright (c) 2013 Garen J. Torikian | ||
Copyright (c) 2013 Garen J. Torikian | ||
@@ -94,2 +116,1 @@ Permission is hereby granted, free of charge, to any person | ||
OTHER DEALINGS IN THE SOFTWARE. | ||
@@ -8,49 +8,62 @@ "mocha"; | ||
describe('isBinaryFile', function() { | ||
it('should fail on a binary program', function() { | ||
assert(isBinaryFile("tests/fixtures/01_grep")); | ||
it('should fail on a binary program', function() { | ||
assert(isBinaryFile("tests/fixtures/01_grep")); | ||
var bytes = fs.readFileSync("tests/fixtures/01_grep"); | ||
var stat = fs.lstatSync("tests/fixtures/01_grep"); | ||
assert(isBinaryFile(bytes, stat.size)); | ||
}); | ||
var bytes = fs.readFileSync("tests/fixtures/01_grep"); | ||
var stat = fs.lstatSync("tests/fixtures/01_grep"); | ||
assert(isBinaryFile(bytes, stat.size)); | ||
}); | ||
it('should not fail on an extensionless script', function() { | ||
assert(!isBinaryFile("tests/fixtures/02_perl_script")); | ||
it('should not fail on an extensionless script', function() { | ||
assert(!isBinaryFile("tests/fixtures/02_perl_script")); | ||
var bytes = fs.readFileSync("tests/fixtures/02_perl_script"); | ||
var stat = fs.lstatSync("tests/fixtures/02_perl_script"); | ||
assert(!isBinaryFile(bytes, stat.size)); | ||
}); | ||
var bytes = fs.readFileSync("tests/fixtures/02_perl_script"); | ||
var stat = fs.lstatSync("tests/fixtures/02_perl_script"); | ||
assert(!isBinaryFile(bytes, stat.size)); | ||
}); | ||
it('should not fail on a russian text', function() { | ||
assert(!isBinaryFile("tests/fixtures/03_Руководство_по_эксплуатации.rst")); | ||
var bytes = fs.readFileSync("tests/fixtures/03_Руководство_по_эксплуатации.rst"); | ||
var stat = fs.lstatSync("tests/fixtures/03_Руководство_по_эксплуатации.rst"); | ||
assert(!isBinaryFile(bytes, stat.size)); | ||
}); | ||
it('should not fail on a russian text', function() { | ||
assert(!isBinaryFile("tests/fixtures/03_Руководство_по_эксплуатации.rst")); | ||
it('should not fail on a PDF', function() { | ||
assert(isBinaryFile("tests/fixtures/04_HelloWorld.pdf")); | ||
var bytes = fs.readFileSync("tests/fixtures/03_Руководство_по_эксплуатации.rst"); | ||
var stat = fs.lstatSync("tests/fixtures/03_Руководство_по_эксплуатации.rst"); | ||
assert(!isBinaryFile(bytes, stat.size)); | ||
}); | ||
var bytes = fs.readFileSync("tests/fixtures/04_HelloWorld.pdf"); | ||
var stat = fs.lstatSync("tests/fixtures/04_HelloWorld.pdf"); | ||
assert(isBinaryFile(bytes, stat.size)); | ||
}); | ||
it('should not fail on a PDF', function() { | ||
assert(isBinaryFile("tests/fixtures/04_HelloWorld.pdf")); | ||
it('should not fail on a zero-byte file', function() { | ||
assert(!isBinaryFile("tests/fixtures/05_null_file.gif")); | ||
var bytes = fs.readFileSync("tests/fixtures/05_null_file.gif"); | ||
var stat = fs.lstatSync("tests/fixtures/05_null_file.gif"); | ||
assert(!isBinaryFile(bytes, stat.size)); | ||
}); | ||
var bytes = fs.readFileSync("tests/fixtures/04_HelloWorld.pdf"); | ||
var stat = fs.lstatSync("tests/fixtures/04_HelloWorld.pdf"); | ||
assert(isBinaryFile(bytes, stat.size)); | ||
}); | ||
it('should not fail on a gif', function() { | ||
assert(isBinaryFile("tests/fixtures/06_trunks.gif")); | ||
var bytes = fs.readFileSync("tests/fixtures/06_trunks.gif"); | ||
var stat = fs.lstatSync("tests/fixtures/06_trunks.gif"); | ||
assert(isBinaryFile(bytes, stat.size)); | ||
it('should not fail on a zero-byte file', function() { | ||
assert(!isBinaryFile("tests/fixtures/05_null_file.gif")); | ||
var bytes = fs.readFileSync("tests/fixtures/05_null_file.gif"); | ||
var stat = fs.lstatSync("tests/fixtures/05_null_file.gif"); | ||
assert(!isBinaryFile(bytes, stat.size)); | ||
}); | ||
it('should not fail on a gif', function() { | ||
assert(isBinaryFile("tests/fixtures/06_trunks.gif")); | ||
var bytes = fs.readFileSync("tests/fixtures/06_trunks.gif"); | ||
var stat = fs.lstatSync("tests/fixtures/06_trunks.gif"); | ||
assert(isBinaryFile(bytes, stat.size)); | ||
}); | ||
it('should not fail with async', function(done) { | ||
assert.doesNotThrow(function() { | ||
isBinaryFile("tests/fixtures/06_trunks.gif", function(err, result) { | ||
assert(!err); | ||
assert(result); | ||
done(); | ||
}, function(err) { | ||
if (err) throw err; | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83604
13
132
113