diff --git a/www/js/app.js b/www/js/app.js index 4953c653..dcfc322b 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -3173,7 +3173,7 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies', 'q', 'module' selectedArchive.getDirEntryByTitle(title).then(function (dirEntry) { selectedArchive.readBinaryFile(dirEntry, function (fileDirEntry, content) { var url = fileDirEntry.url; - var mimetype = selectedArchive.getMimetype(dirEntry.mimetype); + var mimetype = dirEntry.getMimetype(); if (!dataRequested) { uiUtil.feedNodeWithBlob(image, 'src', content, mimetype, params.allowHTMLExtraction); } diff --git a/www/js/lib/abstractFilesystemAccess.js b/www/js/lib/abstractFilesystemAccess.js index b4514c5f..afafce17 100644 --- a/www/js/lib/abstractFilesystemAccess.js +++ b/www/js/lib/abstractFilesystemAccess.js @@ -58,7 +58,7 @@ define(['q', 'jquery'], function(q, jQuery) { }; // We try to match both a standalone ZIM file (.zim) or - // the first file of a splitted ZIM files collection (.zimaa) + // the first file of a split ZIM files collection (.zimaa) var regexpZIMFileName = /\.zim(aa)?$/i; /** diff --git a/www/js/lib/zimArchive.js b/www/js/lib/zimArchive.js index c334c83c..4921958c 100644 --- a/www/js/lib/zimArchive.js +++ b/www/js/lib/zimArchive.js @@ -115,16 +115,6 @@ define(['zimfile', 'zimDirEntry', 'util', 'utf8'], return this._file !== null; }; - /** - * Looks up the dirEntry's mimetype number in the ZIM file's MIME type list, and returns the corresponding MIME type - * - * @param {Integer} mimetype The mimetype number stored in dirEntry.mimetype, used as a lookup value - * @return {String} The MIME type corresponding to mimetype in the ZIM file's MIME type list - */ - ZIMArchive.prototype.getMimetype = function(mimetype) { - return this._file.mimeTypes.get(mimetype); - }; - /** * Looks for the DirEntry of the main page * @param {callbackDirEntry} callback diff --git a/www/js/lib/zimDirEntry.js b/www/js/lib/zimDirEntry.js index 974deb7e..d621a724 100644 --- a/www/js/lib/zimDirEntry.js +++ b/www/js/lib/zimDirEntry.js @@ -31,7 +31,7 @@ define([], function() { * @property {File} _zimfile The ZIM file * @property {Boolean} redirect * @property {Integer} offset - * @property {Integer} mimetype MIME type number as defined in the MIME type list + * @property {Integer} mimetypeInteger MIME type number as defined in the MIME type list * @property {String} namespace defines to which namespace this directory entry belongs * @property {Integer} redirectTarget * @property {Integer} cluster cluster number in which the data of this directory entry is stored @@ -49,7 +49,7 @@ define([], function() { this._zimfile = zimfile; this.redirect = dirEntryData.redirect; this.offset = dirEntryData.offset; - this.mimetype = dirEntryData.mimetype; + this.mimetypeInteger = dirEntryData.mimetypeInteger; this.namespace = dirEntryData.namespace; this.redirectTarget = dirEntryData.redirectTarget; this.cluster = dirEntryData.cluster; @@ -66,7 +66,7 @@ define([], function() { */ DirEntry.prototype.toStringId = function() { //@todo also store isRedirect and redirectTarget - return this.offset + '|' + this.mimetype + '|' + this.namespace + '|' + this.cluster + '|' + + return this.offset + '|' + this.mimetypeInteger + '|' + this.namespace + '|' + this.cluster + '|' + this.blob + '|' + this.url + '|' + this.title + '|' + this.redirect + '|' + this.redirectTarget; }; @@ -96,7 +96,7 @@ define([], function() { var data = {}; var idParts = stringId.split("|"); data.offset = parseInt(idParts[0], 10); - data.mimetype = parseInt(idParts[1], 10); + data.mimetypeInteger = parseInt(idParts[1], 10); data.namespace = idParts[2]; data.cluster = parseInt(idParts[3], 10); data.blob = parseInt(idParts[4], 10); @@ -117,6 +117,15 @@ define([], function() { return this.title ? this.title : this.url; }; + /** + * Looks up the dirEntry's mimetype number in the ZIM file's MIME type list, and returns the corresponding MIME type + * + * @return {String} The MIME type corresponding to mimetypeInteger in the ZIM file's MIME type list + */ + DirEntry.prototype.getMimetype = function() { + return this._zimfile.mimeTypes.get(this.mimetypeInteger); + }; + /** * Functions and classes exposed by this module */ diff --git a/www/js/lib/zimfile.js b/www/js/lib/zimfile.js index 450861fa..17137bac 100644 --- a/www/js/lib/zimfile.js +++ b/www/js/lib/zimfile.js @@ -110,42 +110,6 @@ define(['xzdec_wrapper', 'util', 'utf8', 'q', 'zimDirEntry'], function(xz, util, } }; - /** - * Reads the whole MIME type list and returns it as a populated Map - * The mimeTypeMap is extracted once after the user has picked the ZIM file - * and is stored as ZIMFile.mimetypes. - * - * @returns {Promise} A promise for the MIME Type list as a Map - */ - ZIMFile.prototype._mimeTypeMap = function() { - var typeMap = new Map; - return this._readSlice(this.mimeListPos, 256).then(function(data) { - // DEV: We have read 256 bytes: increase this if you encounter longer MIME type lists - // also change "while (pos < 255)" below - if (data.subarray) { - var i = 1; - var pos = -1; - var mimeString; - while (pos < 255) { - pos++; - mimeString = utf8.parse(data.subarray(pos), true); - // If the parsed data is an empty string, we have reached the end of the MIME type list, so break - if (!mimeString) break; - // Store the parsed string in the Map - typeMap.set(i, mimeString); - i++; - while (data[pos]) { - pos++; - } - } - } - return typeMap; - }).fail(function(err) { - console.errror('Unable to read MIME type list: ' + err); - return new Map; - }); - }; - /** * * @param {Integer} offset @@ -159,10 +123,10 @@ define(['xzdec_wrapper', 'util', 'utf8', 'q', 'zimDirEntry'], function(xz, util, var dirEntry = { offset: offset, - mimetype: readInt(data, 0, 2), + mimetypeInteger: readInt(data, 0, 2), namespace: String.fromCharCode(data[3]) }; - dirEntry.redirect = (dirEntry.mimetype === 0xffff); + dirEntry.redirect = (dirEntry.mimetypeInteger === 0xffff); if (dirEntry.redirect) dirEntry.redirectTarget = readInt(data, 8, 4); else @@ -244,6 +208,45 @@ define(['xzdec_wrapper', 'util', 'utf8', 'q', 'zimDirEntry'], function(xz, util, }); }; + /** + * Reads the whole MIME type list and returns it as a populated Map + * The mimeTypeMap is extracted once after the user has picked the ZIM file + * and is stored as ZIMFile.mimeTypes + * + * @param {File} file The ZIM file (or first file in array of files) from which the MIME type list +* is to be extracted + * @param {Integer} mimeListPos The offset in at which the MIME type list is found + * @param {Integer} urlPtrPos The offset of the byte after the end of the MIME type list in + * @returns {Promise} A promise for the MIME Type list as a Map + */ + function readMimetypeMap(file, mimeListPos, urlPtrPos) { + var typeMap = new Map; + var size = urlPtrPos - mimeListPos; + return util.readFileSlice(file, mimeListPos, size).then(function(data) { + if (data.subarray) { + var i = 1; + var pos = -1; + var mimeString; + while (pos < size) { + pos++; + mimeString = utf8.parse(data.subarray(pos), true); + // If the parsed data is an empty string, we have reached the end of the MIME type list, so break + if (!mimeString) break; + // Store the parsed string in the Map + typeMap.set(i, mimeString); + i++; + while (data[pos]) { + pos++; + } + } + } + return typeMap; + }).fail(function(err) { + console.error('Unable to read MIME type list', err); + return new Map; + }); + } + return { /** * @@ -263,21 +266,22 @@ define(['xzdec_wrapper', 'util', 'utf8', 'q', 'zimDirEntry'], function(xz, util, } return 0; }); - return util.readFileSlice(fileArray[0], 0, 80).then(function(header) - { + return util.readFileSlice(fileArray[0], 0, 80).then(function(header) { + var mimeListPos = readInt(header, 56, 8); + var urlPtrPos = readInt(header, 32, 8); + return readMimetypeMap(fileArray[0], mimeListPos, urlPtrPos).then(function(data) { var zf = new ZIMFile(fileArray); zf.articleCount = readInt(header, 24, 4); zf.clusterCount = readInt(header, 28, 4); - zf.urlPtrPos = readInt(header, 32, 8); + zf.urlPtrPos = urlPtrPos; zf.titlePtrPos = readInt(header, 40, 8); zf.clusterPtrPos = readInt(header, 48, 8); - zf.mimeListPos = readInt(header, 56, 8); + zf.mimeListPos = mimeListPos; zf.mainPage = readInt(header, 64, 4); zf.layoutPage = readInt(header, 68, 4); - zf._mimeTypeMap().then(function(data) { zf.mimeTypes = data; + return zf; }); - return zf; }); } };