mirror of
https://github.com/janeczku/calibre-web
synced 2024-12-24 17:10:31 +00:00
91 lines
2.4 KiB
JavaScript
91 lines
2.4 KiB
JavaScript
// Copyright (c) 2017 Matthew Brennan Jones <matthew.brennan.jones@gmail.com>
|
|
// This software is licensed under a MIT License
|
|
// https://github.com/workhorsy/uncompress.js
|
|
|
|
"use strict";
|
|
|
|
// Based on the information from:
|
|
// https://en.wikipedia.org/wiki/Tar_(computing)
|
|
|
|
|
|
(function() {
|
|
|
|
const TAR_TYPE_FILE = 0;
|
|
const TAR_TYPE_DIR = 5;
|
|
|
|
const TAR_HEADER_SIZE = 512;
|
|
const TAR_TYPE_OFFSET = 156;
|
|
const TAR_TYPE_SIZE = 1;
|
|
const TAR_SIZE_OFFSET = 124;
|
|
const TAR_SIZE_SIZE = 12;
|
|
const TAR_NAME_OFFSET = 0;
|
|
const TAR_NAME_SIZE = 100;
|
|
|
|
function _tarRead(view, offset, size) {
|
|
return view.slice(offset, offset + size);
|
|
}
|
|
|
|
function tarGetEntries(filename, array_buffer) {
|
|
let view = new Uint8Array(array_buffer);
|
|
let offset = 0;
|
|
let entries = [];
|
|
|
|
while (offset + TAR_HEADER_SIZE < view.byteLength) {
|
|
// Get entry name
|
|
let entry_name = saneMap(_tarRead(view, offset + TAR_NAME_OFFSET, TAR_NAME_SIZE), String.fromCharCode);
|
|
entry_name = entry_name.join('').replace(/\0/g, '');
|
|
|
|
// No entry name, so probably the last block
|
|
if (entry_name.length === 0) {
|
|
break;
|
|
}
|
|
|
|
// Get entry size
|
|
let entry_size = parseInt(saneJoin(saneMap(_tarRead(view, offset + TAR_SIZE_OFFSET, TAR_SIZE_SIZE), String.fromCharCode), ''), 8);
|
|
let entry_type = saneMap(_tarRead(view, offset + TAR_TYPE_OFFSET, TAR_TYPE_SIZE), String.fromCharCode) | 0;
|
|
|
|
// Save this as en entry if it is a file or directory
|
|
if (entry_type === TAR_TYPE_FILE || entry_type === TAR_TYPE_DIR) {
|
|
let entry = {
|
|
name: entry_name,
|
|
size: entry_size,
|
|
is_file: entry_type == TAR_TYPE_FILE,
|
|
offset: offset
|
|
};
|
|
entries.push(entry);
|
|
}
|
|
|
|
// Round the offset up to be divisible by TAR_HEADER_SIZE
|
|
offset += (entry_size + TAR_HEADER_SIZE);
|
|
if (offset % TAR_HEADER_SIZE > 0) {
|
|
let even = (offset / TAR_HEADER_SIZE) | 0; // number of times it goes evenly into TAR_HEADER_SIZE
|
|
offset = (even + 1) * TAR_HEADER_SIZE;
|
|
}
|
|
}
|
|
|
|
return entries;
|
|
}
|
|
|
|
function tarGetEntryData(entry, array_buffer) {
|
|
let view = new Uint8Array(array_buffer);
|
|
let offset = entry.offset;
|
|
let size = entry.size;
|
|
|
|
// Get entry data
|
|
let entry_data = _tarRead(view, offset + TAR_HEADER_SIZE, size);
|
|
return entry_data;
|
|
}
|
|
|
|
// Figure out if we are running in a Window or Web Worker
|
|
let scope = null;
|
|
if (typeof window === 'object') {
|
|
scope = window;
|
|
} else if (typeof importScripts === 'function') {
|
|
scope = self;
|
|
}
|
|
|
|
// Set exports
|
|
scope.tarGetEntries = tarGetEntries;
|
|
scope.tarGetEntryData = tarGetEntryData;
|
|
})();
|