asar.js 5.41 KB
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.readAsar = readAsar;
exports.readAsarJson = readAsarJson;
exports.AsarFilesystem = exports.Node = void 0;

function _chromiumPickleJs() {
  const data = require("chromium-pickle-js");

  _chromiumPickleJs = function () {
    return data;
  };

  return data;
}

function _fsExtra() {
  const data = require("fs-extra");

  _fsExtra = function () {
    return data;
  };

  return data;
}

var path = _interopRequireWildcard(require("path"));

function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

/** @internal */
class Node {}
/** @internal */


exports.Node = Node;

class AsarFilesystem {
  constructor(src, header = new Node(), headerSize = -1) {
    this.src = src;
    this.header = header;
    this.headerSize = headerSize;
    this.offset = 0;

    if (this.header.files == null) {
      this.header.files = {};
    }
  }

  searchNodeFromDirectory(p, isCreate) {
    let node = this.header;

    for (const dir of p.split(path.sep)) {
      if (dir !== ".") {
        let child = node.files[dir];

        if (child == null) {
          if (!isCreate) {
            return null;
          }

          child = new Node();
          child.files = {};
          node.files[dir] = child;
        }

        node = child;
      }
    }

    return node;
  }

  getOrCreateNode(p) {
    if (p == null || p.length === 0) {
      return this.header;
    }

    const name = path.basename(p);
    const dirNode = this.searchNodeFromDirectory(path.dirname(p), true);

    if (dirNode.files == null) {
      dirNode.files = {};
    }

    let result = dirNode.files[name];

    if (result == null) {
      result = new Node();
      dirNode.files[name] = result;
    }

    return result;
  }

  addFileNode(file, dirNode, size, unpacked, stat) {
    if (size > 4294967295) {
      throw new Error(`${file}: file size cannot be larger than 4.2GB`);
    }

    const node = new Node();
    node.size = size;

    if (unpacked) {
      node.unpacked = true;
    } else {
      // electron expects string
      node.offset = this.offset.toString();

      if (process.platform !== "win32" && stat.mode & 0o100) {
        node.executable = true;
      }

      this.offset += node.size;
    }

    let children = dirNode.files;

    if (children == null) {
      children = {};
      dirNode.files = children;
    }

    children[path.basename(file)] = node;
    return node;
  }

  getNode(p) {
    const node = this.searchNodeFromDirectory(path.dirname(p), false);
    return node.files[path.basename(p)];
  }

  getFile(p, followLinks = true) {
    const info = this.getNode(p); // if followLinks is false we don't resolve symlinks

    return followLinks && info.link != null ? this.getFile(info.link) : info;
  }

  async readJson(file) {
    return JSON.parse((await this.readFile(file)).toString());
  }

  readFile(file) {
    return readFileFromAsar(this, file, this.getFile(file));
  }

}

exports.AsarFilesystem = AsarFilesystem;

async function readAsar(archive) {
  const fd = await (0, _fsExtra().open)(archive, "r");
  let size;
  let headerBuf;

  try {
    const sizeBuf = Buffer.allocUnsafe(8);

    if ((await (0, _fsExtra().read)(fd, sizeBuf, 0, 8, null)).bytesRead !== 8) {
      throw new Error("Unable to read header size");
    }

    const sizePickle = (0, _chromiumPickleJs().createFromBuffer)(sizeBuf);
    size = sizePickle.createIterator().readUInt32();
    headerBuf = Buffer.allocUnsafe(size);

    if ((await (0, _fsExtra().read)(fd, headerBuf, 0, size, null)).bytesRead !== size) {
      throw new Error("Unable to read header");
    }
  } finally {
    await (0, _fsExtra().close)(fd);
  }

  const headerPickle = (0, _chromiumPickleJs().createFromBuffer)(headerBuf);
  const header = headerPickle.createIterator().readString();
  return new AsarFilesystem(archive, JSON.parse(header), size);
}

async function readAsarJson(archive, file) {
  const fs = await readAsar(archive);
  return await fs.readJson(file);
}

async function readFileFromAsar(filesystem, filename, info) {
  const size = info.size;
  const buffer = Buffer.allocUnsafe(size);

  if (size <= 0) {
    return buffer;
  }

  if (info.unpacked) {
    return await (0, _fsExtra().readFile)(path.join(`${filesystem.src}.unpacked`, filename));
  }

  const fd = await (0, _fsExtra().open)(filesystem.src, "r");

  try {
    const offset = 8 + filesystem.headerSize + parseInt(info.offset, 10);
    await (0, _fsExtra().read)(fd, buffer, 0, size, offset);
  } finally {
    await (0, _fsExtra().close)(fd);
  }

  return buffer;
} 
// __ts-babel@6.0.4
//# sourceMappingURL=asar.js.map