ConvertFb2.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. const ConvertBase = require('./ConvertBase');
  2. const iconv = require('iconv-lite');
  3. const textUtils = require('./textUtils');
  4. class ConvertFb2 extends ConvertBase {
  5. check(data, opts) {
  6. const {dataType} = opts;
  7. return (
  8. ( (dataType && dataType.ext == 'xml') || this.isDataXml(data) ) &&
  9. data.toString().indexOf('<FictionBook') >= 0
  10. );
  11. }
  12. async run(data, opts) {
  13. let newData = data.slice(0, 1024);
  14. //Корректируем кодировку для проверки, 16-битные кодировки должны стать utf-8
  15. const encoding = textUtils.getEncoding(newData);
  16. if (encoding.indexOf('UTF-16') == 0) {
  17. newData = Buffer.from(iconv.decode(newData, encoding));
  18. }
  19. //Проверяем
  20. if (!this.check(newData, opts))
  21. return false;
  22. //Корректируем кодировку всего объема
  23. newData = data;
  24. if (encoding.indexOf('UTF-16') == 0) {
  25. newData = Buffer.from(iconv.decode(newData, encoding));
  26. }
  27. //Корректируем пробелы, всякие файлы попадаются :(
  28. if (newData[0] == 32) {
  29. newData = Buffer.from(newData.toString().trim());
  30. }
  31. //Окончательно корректируем кодировку
  32. return this.checkEncoding(newData);
  33. }
  34. checkEncoding(data) {
  35. let result = data;
  36. let q = '"';
  37. let left = data.indexOf('<?xml version="1.0"');
  38. if (left < 0) {
  39. left = data.indexOf('<?xml version=\'1.0\'');
  40. q = '\'';
  41. }
  42. if (left >= 0) {
  43. const right = data.indexOf('?>', left);
  44. if (right >= 0) {
  45. const head = data.slice(left, right + 2).toString();
  46. const m = head.match(/encoding=['"](.*?)['"]/);
  47. if (m) {
  48. let encoding = m[1].toLowerCase();
  49. if (encoding != 'utf-8') {
  50. //encoding может не соответсвовать реальной кодировке файла, поэтому:
  51. let calcEncoding = textUtils.getEncoding(data);
  52. if (calcEncoding.indexOf('ISO-8859') >= 0) {
  53. calcEncoding = encoding;
  54. }
  55. result = iconv.decode(data, calcEncoding);
  56. result = Buffer.from(result.toString().replace(m[0], `encoding=${q}utf-8${q}`));
  57. }
  58. }
  59. }
  60. }
  61. return result;
  62. }
  63. }
  64. module.exports = ConvertFb2;