index.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. var fs = require('fs');
  2. var path = require('path');
  3. var alloc = require('buffer-alloc');
  4. var MAX_BYTES = 512;
  5. module.exports = function(bytes, size, cb) {
  6. // Only two args
  7. if (cb === undefined) {
  8. var file = bytes;
  9. cb = size;
  10. fs.stat(file, function(err, stat) {
  11. if (err || !stat.isFile()) return cb(err, false);
  12. fs.open(file, 'r', function(r_err, descriptor){
  13. if (r_err) return cb(r_err);
  14. bytes = alloc(MAX_BYTES);
  15. // Read the file with no encoding for raw buffer access.
  16. fs.read(descriptor, bytes, 0, bytes.length, 0, function(err, size, bytes){
  17. fs.close(descriptor, function(c_err){
  18. if (c_err) return cb(c_err, false);
  19. return cb(null, isBinaryCheck(bytes, size));
  20. });
  21. });
  22. });
  23. });
  24. }
  25. else
  26. return cb(null, isBinaryCheck(bytes, size));
  27. };
  28. function isBinaryCheck(bytes, size) {
  29. if (size === 0)
  30. return false;
  31. var suspicious_bytes = 0;
  32. var total_bytes = Math.min(size, MAX_BYTES);
  33. // UTF-8 BOM
  34. if (size >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
  35. return false;
  36. }
  37. // UTF-32 BOM
  38. if (size >= 4 && bytes[0] === 0x00 && bytes[1] === 0x00 && bytes[2] == 0xFE && bytes[3] == 0xFF) {
  39. return false;
  40. }
  41. // UTF-32 LE BOM
  42. if (size >= 4 && bytes[0] == 0xFF && bytes[1] == 0xFE && bytes[2] === 0x00 && bytes[3] === 0x00) {
  43. return false;
  44. }
  45. // GB BOM
  46. if (size >= 4 && bytes[0] == 0x84 && bytes[1] == 0x31 && bytes[2] == 0x95 && bytes[3] == 0x33) {
  47. return false;
  48. }
  49. if (total_bytes >= 5 && bytes.slice(0, 5) == "%PDF-") {
  50. /* PDF. This is binary. */
  51. return true;
  52. }
  53. // UTF-16 BE BOM
  54. if (size >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF) {
  55. return false;
  56. }
  57. // UTF-16 LE BOM
  58. if (size >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE) {
  59. return false;
  60. }
  61. for (var i = 0; i < total_bytes; i++) {
  62. if (bytes[i] === 0) { // NULL byte--it's binary!
  63. return true;
  64. }
  65. else if ((bytes[i] < 7 || bytes[i] > 14) && (bytes[i] < 32 || bytes[i] > 127)) {
  66. // UTF-8 detection
  67. if (bytes[i] > 193 && bytes[i] < 224 && i + 1 < total_bytes) {
  68. i++;
  69. if (bytes[i] > 127 && bytes[i] < 192) {
  70. continue;
  71. }
  72. }
  73. else if (bytes[i] > 223 && bytes[i] < 240 && i + 2 < total_bytes) {
  74. i++;
  75. if (bytes[i] > 127 && bytes[i] < 192 && bytes[i + 1] > 127 && bytes[i + 1] < 192) {
  76. i++;
  77. continue;
  78. }
  79. }
  80. suspicious_bytes++;
  81. // Read at least 32 bytes before making a decision
  82. if (i > 32 && (suspicious_bytes * 100) / total_bytes > 10) {
  83. return true;
  84. }
  85. }
  86. }
  87. if ((suspicious_bytes * 100) / total_bytes > 10) {
  88. return true;
  89. }
  90. return false;
  91. }
  92. module.exports.sync = function(bytes, size) {
  93. // Only one arg
  94. if (size === undefined) {
  95. var file = bytes;
  96. try {
  97. if(!fs.statSync(file).isFile()) return false;
  98. } catch (err) {
  99. // otherwise continue on
  100. }
  101. var descriptor = fs.openSync(file, 'r');
  102. try {
  103. // Read the file with no encoding for raw buffer access.
  104. bytes = alloc(MAX_BYTES);
  105. size = fs.readSync(descriptor, bytes, 0, bytes.length, 0);
  106. } finally {
  107. fs.closeSync(descriptor);
  108. }
  109. return isBinaryCheck(bytes, size);
  110. }
  111. else
  112. return isBinaryCheck(bytes, size);
  113. }