Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cfb.njs 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/usr/bin/env node
  2. /* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */
  3. /* eslint-env node */
  4. /* vim: set ts=2 ft=javascript: */
  5. var n = "cfb";
  6. var X = require('../');
  7. var fs = require('fs');
  8. var program = require('commander');
  9. var PRINTJ = require("printj");
  10. var sprintf = PRINTJ.sprintf;
  11. program
  12. .version(X.version)
  13. .usage('[options] <file> [subfiles...]')
  14. .option('-l, --list-files', 'list files')
  15. .option('-r, --repair', 'attempt to repair and garbage-collect archive')
  16. .option('-c, --create', 'create file')
  17. .option('-a, --append', 'add files to CFB (overwrite existing data)')
  18. .option('-d, --delete', 'delete files from CFB')
  19. .option('-O, --to-stdout', 'extract raw contents to stdout')
  20. .option('-z, --dump', 'dump internal representation but do not extract')
  21. .option('-q, --quiet', 'process but do not report')
  22. .option('--here', 'skip the CFB root name when extracting')
  23. .option('--osx', 'use OSX-style unzip listing')
  24. .option('--zlib', 'use native zlib')
  25. .option('--local', 'print times in local timezone')
  26. .option('--dev', 'development mode')
  27. .option('--read', 'read but do not print out contents');
  28. program.parse(process.argv);
  29. if(program.zlib) X.utils.use_zlib(require('zlib'));
  30. var exit = process.exit;
  31. var die = function(errno/*:number*/, msg/*:string*/) { console.error(n + ": " + msg); exit(errno); };
  32. var logit = function(cmd/*:string*/, f/*:string*/) { console.error(sprintf("%-6s %s", cmd, f)); };
  33. if(program.args.length === 0) die(1, "must specify a filename");
  34. if(program.create) {
  35. logit("create", program.args[0]);
  36. var newcfb = X.utils.cfb_new();
  37. X.writeFile(newcfb, program.args[0]);
  38. }
  39. if(!fs.existsSync(program.args[0])) die(1, "must specify a filename");
  40. var opts = ({type:'file'}/*:any*/);
  41. if(program.dev) opts.WTF = true;
  42. var cfb = X.read(program.args[0], opts);
  43. if(program.quiet) exit(0);
  44. if(program.dump) {
  45. console.log("Full Paths:");
  46. console.log(cfb.FullPaths.map(function(x/*:string*/) { return " " + x; }).join("\n"));
  47. console.log("File Index:");
  48. console.log(cfb.FileIndex);
  49. exit(0);
  50. }
  51. if(program.repair) { X.writeFile(cfb, program.args[0]); exit(0); }
  52. var rlen = cfb.FullPaths[0].length;
  53. function fix_string(x/*:string*/)/*:string*/ { return x.replace(/[\u0000-\u001f]/g, function($$) { return sprintf("\\u%04X", $$.charCodeAt(0)); }); }
  54. var format_date = function(date/*:Date*/, osx/*:?any*/)/*:string*/ {
  55. var datefmt = osx ? "%02u-%02u-%04u %02u:%02u": "%02u-%02u-%02u %02u:%02u";
  56. var MM = program.local ? date.getMonth() + 1 : date.getUTCMonth() + 1;
  57. var DD = program.local ? date.getDate() : date.getUTCDate();
  58. var YY = (program.local ? date.getFullYear() : date.getUTCFullYear())%(osx ? 10000 : 100);
  59. var hh = program.local ? date.getHours() : date.getUTCHours();
  60. var mm = program.local ? date.getMinutes() : date.getUTCMinutes();
  61. return sprintf(datefmt, MM, DD, YY, hh, mm);
  62. };
  63. if(program.listFiles) {
  64. var basetime = new Date(Date.UTC(1980,0,1));
  65. var cnt = 0, rootsize = 0, filesize = 0;
  66. var fmtstr = "%9lu %s %s";
  67. if(program.osx) {
  68. console.log("Archive: " + program.args[0]);
  69. console.log(" Length Date Time Name");
  70. console.log("--------- ---------- ----- ----");
  71. fmtstr = "%9lu %s %s";
  72. } else {
  73. console.log(" Length Date Time Name");
  74. console.log(" -------- ---- ---- ----");
  75. }
  76. cfb.FileIndex.forEach(function(file/*:CFBEntry*/, i/*:number*/) {
  77. switch(file.type) {
  78. case 5:
  79. basetime = file.ct || file.mt || basetime;
  80. rootsize = file.size;
  81. break;
  82. case 2:
  83. var fixname = fix_string(cfb.FullPaths[i]);
  84. if(program.osx && fixname.match(/\\u0001Sh33tJ5/)) return;
  85. if(program.here) fixname = fixname.slice(rlen);
  86. console.log(sprintf(fmtstr, file.size, format_date(file.mt || basetime, program.osx), fixname));
  87. filesize += file.size;
  88. ++cnt;
  89. }
  90. });
  91. var outfmt = "%9lu %lu file%s";
  92. if(program.osx) {
  93. console.log("--------- -------");
  94. outfmt = "%9lu %lu file%s";
  95. } else {
  96. console.log(" -------- -------");
  97. }
  98. console.log(sprintf(outfmt, rootsize || filesize, cnt, (cnt !== 1 ? "s" : "")));
  99. exit(0);
  100. }
  101. function mkdirp(path/*:string*/) { path.split("/").reduce(function(acc/*:string*/, p/*:string*/) {
  102. acc += p + "/";
  103. if(!fs.existsSync(acc)) { logit("mkdir", acc); fs.mkdirSync(acc); }
  104. return acc;
  105. }, ""); }
  106. function write(path/*:string*/, data/*:CFBEntry*/) {
  107. logit("write", fix_string(path));
  108. fs.writeFileSync(path, /*::new Buffer((*/data.content/*:: :any))*/ || new Buffer(0));
  109. }
  110. if(program.create || program.append) {
  111. program.args.slice(1).forEach(function(x/*:string*/) {
  112. logit("append", x);
  113. X.utils.cfb_add(cfb, "/" + x, fs.readFileSync(x));
  114. });
  115. X.writeFile(cfb, program.args[0]);
  116. exit(0);
  117. }
  118. if(program.delete) {
  119. program.args.slice(1).forEach(function(x/*:string*/) {
  120. logit("delete", x);
  121. X.utils.cfb_del(cfb, "/" + x);
  122. });
  123. X.writeFile(cfb, program.args[0]);
  124. exit(0);
  125. }
  126. if(program.args.length > 1) {
  127. program.args.slice(1).forEach(function(x/*:string*/) {
  128. var data/*:?CFBEntry*/ = X.find(cfb, x.replace(/\\u000\d/g,"!"));
  129. if(!data) { console.error(x + ": file not found"); return; }
  130. if(data.type !== 2) { console.error(x + ": not a file"); return; }
  131. var idx = cfb.FileIndex.indexOf(data), path = cfb.FullPaths[idx];
  132. if(program.toStdout) return process.stdout.write(/*::new Buffer((*/data.content/*:: :any))*/);
  133. mkdirp(path.slice(0, path.lastIndexOf("/")));
  134. write(path, data);
  135. });
  136. exit(0);
  137. }
  138. if(program.toStdout) exit(0);
  139. for(var i=program.here ? 1 : 0; i!==cfb.FullPaths.length; ++i) {
  140. if(!cfb.FileIndex[i].name) continue;
  141. var fp = cfb.FullPaths[i];
  142. if(program.here) fp = fp.slice(rlen);
  143. if(fp.slice(-1) === "/") mkdirp(fp);
  144. else {
  145. if(fp.indexOf("/") > -1) mkdirp(fp.slice(0, fp.lastIndexOf("/")));
  146. write(fp, cfb.FileIndex[i]);
  147. }
  148. }