Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Zip.js
- Copyright (c) 2013 Gildas Lormeau. All rights reserved.
- Please read copyright notice, list of conditions and the disclaimer https://raw.githubusercontent.com/gildas-lormeau/zip.js/master/WebContent/zip.js
- */
- if (!window.vkopt) window.vkopt={};
- (function(obj) {
- "use strict";
- var ERR_WRITE = "Error while writing zip file.";
- var ERR_READ_DATA = "Error while reading file data.";
- var ERR_DUPLICATED_NAME = "File already exists.";
- var CHUNK_SIZE = 512 * 1024;
- var appendABViewSupported;
- try {
- appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
- } catch (e) {
- }
- function Crc32() {
- this.crc = -1;
- }
- Crc32.prototype.append = function append(data) {
- var crc = this.crc | 0, table = this.table;
- for (var offset = 0, len = data.length | 0; offset < len; offset++)
- crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];
- this.crc = crc;
- };
- Crc32.prototype.get = function get() {
- return ~this.crc;
- };
- Crc32.prototype.table = (function() {
- var i, j, t, table = []; // Uint32Array is actually slower than []
- for (i = 0; i < 256; i++) {
- t = i;
- for (j = 0; j < 8; j++)
- if (t & 1)
- t = (t >>> 1) ^ 0xEDB88320;
- else
- t = t >>> 1;
- table[i] = t;
- }
- return table;
- })();
- // "no-op" codec
- function NOOP() {}
- NOOP.prototype.append = function append(bytes, onprogress) {
- return bytes;
- };
- NOOP.prototype.flush = function flush() {};
- function getDataHelper(byteLength, bytes) {
- var dataBuffer, dataArray;
- dataBuffer = new ArrayBuffer(byteLength);
- dataArray = new Uint8Array(dataBuffer);
- if (bytes)
- dataArray.set(bytes, 0);
- return {
- buffer : dataBuffer,
- array : dataArray,
- view : new DataView(dataBuffer)
- };
- }
- function blobSlice(blob, index, length) {
- if (index < 0 || length < 0 || index + length > blob.size)
- throw new RangeError('offset:' + index + ', length:' + length + ', size:' + blob.size);
- if (blob.slice)
- return blob.slice(index, index + length);
- else if (blob.webkitSlice)
- return blob.webkitSlice(index, index + length);
- else if (blob.mozSlice)
- return blob.mozSlice(index, index + length);
- else if (blob.msSlice)
- return blob.msSlice(index, index + length);
- }
- // Readers
- function Reader() {
- }
- function BlobReader(blob) {
- var that = this;
- function init(callback) {
- that.size = blob.size;
- callback();
- }
- function readUint8Array(index, length, callback, onerror) {
- var reader = new FileReader();
- reader.onload = function(e) {
- callback(new Uint8Array(e.target.result));
- };
- reader.onerror = onerror;
- try {
- reader.readAsArrayBuffer(blobSlice(blob, index, length));
- } catch (e) {
- onerror(e);
- }
- }
- that.size = 0;
- that.init = init;
- that.readUint8Array = readUint8Array;
- }
- BlobReader.prototype = new Reader();
- BlobReader.prototype.constructor = BlobReader;
- // Writers
- function Writer() {
- }
- Writer.prototype.getData = function(callback) {
- callback(this.data);
- };
- function BlobWriter(contentType) {
- var blob, that = this;
- function init(callback) {
- blob = new Blob([], {
- type : contentType
- });
- callback();
- }
- function writeUint8Array(array, callback) {
- blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
- type : contentType
- });
- callback();
- }
- function getData(callback) {
- callback(blob);
- }
- that.init = init;
- that.writeUint8Array = writeUint8Array;
- that.getData = getData;
- }
- BlobWriter.prototype = new Writer();
- BlobWriter.prototype.constructor = BlobWriter;
- function FileWriter(fileEntry, contentType) {
- var writer, that = this;
- function init(callback, onerror) {
- fileEntry.createWriter(function(fileWriter) {
- writer = fileWriter;
- callback();
- }, onerror);
- }
- function writeUint8Array(array, callback, onerror) {
- var blob = new Blob([ appendABViewSupported ? array : array.buffer ], {
- type : contentType
- });
- writer.onwrite = function() {
- writer.onwrite = null;
- callback();
- };
- writer.onerror = onerror;
- writer.write(blob);
- }
- function getData(callback) {
- fileEntry.file(callback);
- }
- that.init = init;
- that.writeUint8Array = writeUint8Array;
- that.getData = getData;
- }
- FileWriter.prototype = new Writer();
- FileWriter.prototype.constructor = FileWriter;
- function MutableFileWriter(fileHandle, contentType) {
- var lockedFile, that = this;
- function init(callback) {
- //lockedFile = fileHandle.open('readwrite');
- callback();
- }
- function writeUint8Array(array, callback) {
- var blob = new Blob([ appendABViewSupported ? array : array.buffer ], {
- type : contentType
- });
- var lockedFile = fileHandle.open('readwrite');
- var writing = lockedFile.append(blob)
- writing.onsuccess = function(){
- callback();
- }
- writing.onerror = function(){
- console.log('Something goes wrong in the writing process: ' + this.error);
- }
- }
- function getData(callback) {
- fileHandle.getFile().onsuccess = function () {
- callback(this.result);
- }
- }
- that.init = init;
- that.writeUint8Array = writeUint8Array;
- that.getData = getData;
- }
- MutableFileWriter.prototype = new Writer();
- MutableFileWriter.prototype.constructor = MutableFileWriter;
- function launchProcess(process, reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror) {
- var chunkIndex = 0, index, outputSize = 0,
- crcInput = crcType === 'input',
- crcOutput = crcType === 'output',
- crc = new Crc32();
- function step() {
- var outputData;
- index = chunkIndex * CHUNK_SIZE;
- if (index < size)
- reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(inputData) {
- var outputData;
- try {
- outputData = process.append(inputData, function(loaded) {
- if (onprogress)
- onprogress(index + loaded, size);
- });
- } catch (e) {
- onreaderror(e);
- return;
- }
- if (outputData) {
- outputSize += outputData.length;
- writer.writeUint8Array(outputData, function() {
- chunkIndex++;
- setTimeout(step, 1);
- }, onwriteerror);
- if (crcOutput)
- crc.append(outputData);
- } else {
- chunkIndex++;
- setTimeout(step, 1);
- }
- if (crcInput)
- crc.append(inputData);
- if (onprogress)
- onprogress(index, size);
- }, onreaderror);
- else {
- try {
- outputData = process.flush();
- } catch (e) {
- onreaderror(e);
- return;
- }
- if (outputData) {
- if (crcOutput)
- crc.append(outputData);
- outputSize += outputData.length;
- writer.writeUint8Array(outputData, function() {
- onend(outputSize, crc.get());
- }, onwriteerror);
- } else
- onend(outputSize, crc.get());
- }
- }
- step();
- }
- function copy(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
- var crcType = 'input';
- launchProcess(new NOOP(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);
- }
- // ZipWriter
- function encodeUTF8(string) {
- return unescape(encodeURIComponent(string));
- }
- function getBytes(str) {
- var i, array = [];
- for (i = 0; i < str.length; i++)
- array.push(str.charCodeAt(i));
- return array;
- }
- function createZipWriter(writer, callback, onerror) {
- var files = {}, filenames = [], datalength = 0;
- var deflateSN = 0;
- function onwriteerror(err) {
- onerror(err || ERR_WRITE);
- }
- function onreaderror(err) {
- onerror(err || ERR_READ_DATA);
- }
- var zipWriter = {
- add : function(name, reader, onend, onprogress, options) {
- var header, filename, date;
- var worker = this._worker;
- function writeHeader(callback) {
- var data;
- date = options.lastModDate || new Date();
- header = getDataHelper(26);
- files[name] = {
- headerArray : header.array,
- directory : options.directory,
- filename : filename,
- offset : datalength,
- comment : getBytes(encodeUTF8(options.comment || ""))
- };
- header.view.setUint32(0, 0x14000808);
- if (options.version)
- header.view.setUint8(0, options.version);
- header.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);
- header.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);
- header.view.setUint16(22, filename.length, true);
- data = getDataHelper(30 + filename.length);
- data.view.setUint32(0, 0x504b0304);
- data.array.set(header.array, 4);
- data.array.set(filename, 30);
- datalength += data.array.length;
- writer.writeUint8Array(data.array, callback, onwriteerror);
- }
- function writeFooter(compressedLength, crc32) {
- var footer = getDataHelper(16);
- datalength += compressedLength || 0;
- footer.view.setUint32(0, 0x504b0708);
- if (typeof crc32 != "undefined") {
- header.view.setUint32(10, crc32, true);
- footer.view.setUint32(4, crc32, true);
- }
- if (reader) {
- footer.view.setUint32(8, compressedLength, true);
- header.view.setUint32(14, compressedLength, true);
- footer.view.setUint32(12, reader.size, true);
- header.view.setUint32(18, reader.size, true);
- }
- writer.writeUint8Array(footer.array, function() {
- datalength += 16;
- onend();
- }, onwriteerror);
- }
- function writeFile() {
- options = options || {};
- name = name.trim();
- if (options.directory && name.charAt(name.length - 1) != "/")
- name += "/";
- if (files.hasOwnProperty(name)) {
- onerror(ERR_DUPLICATED_NAME);
- return;
- }
- filename = getBytes(encodeUTF8(name));
- filenames.push(name);
- writeHeader(function() {
- if (reader)
- copy(worker, deflateSN++, reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);
- else
- writeFooter();
- }, onwriteerror);
- }
- if (reader)
- reader.init(writeFile, onreaderror);
- else
- writeFile();
- },
- close : function(callback) {
- if (this._worker) {
- this._worker.terminate();
- this._worker = null;
- }
- var data, length = 0, index = 0, indexFilename, file;
- for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
- file = files[filenames[indexFilename]];
- length += 46 + file.filename.length + file.comment.length;
- }
- data = getDataHelper(length + 22);
- for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
- file = files[filenames[indexFilename]];
- data.view.setUint32(index, 0x504b0102);
- data.view.setUint16(index + 4, 0x1400);
- data.array.set(file.headerArray, index + 6);
- data.view.setUint16(index + 32, file.comment.length, true);
- if (file.directory)
- data.view.setUint8(index + 38, 0x10);
- data.view.setUint32(index + 42, file.offset, true);
- data.array.set(file.filename, index + 46);
- data.array.set(file.comment, index + 46 + file.filename.length);
- index += 46 + file.filename.length + file.comment.length;
- }
- data.view.setUint32(index, 0x504b0506);
- data.view.setUint16(index + 8, filenames.length, true);
- data.view.setUint16(index + 10, filenames.length, true);
- data.view.setUint32(index + 12, length, true);
- data.view.setUint32(index + 16, datalength, true);
- writer.writeUint8Array(data.array, function() {
- writer.getData(callback);
- }, onwriteerror);
- },
- _worker: null
- };
- callback(zipWriter);
- }
- function resolveURLs(urls) {
- var a = document.createElement('a');
- return urls.map(function(url) {
- a.href = url;
- return a.href;
- });
- }
- function onerror_default(error) {
- console.error(error);
- }
- obj.zipjs = {
- Writer : Writer,
- BlobWriter : BlobWriter,
- FileWriter : FileWriter,
- MutableFileWriter: MutableFileWriter,
- BlobReader : BlobReader,
- createWriter : function(writer, callback, onerror) {
- onerror = onerror || onerror_default;
- writer.init(function() {
- createZipWriter(writer, callback, onerror);
- }, onerror);
- }
- };
- })(vkopt);
- (function(obj) {
- var requestFileSystem = obj.webkitRequestFileSystem || obj.mozRequestFileSystem || obj.requestFileSystem;
- var url_create = (window.URL || window.webkitURL || window.mozURL || window).createObjectURL;
- var url_revoke = (window.URL || window.webkitURL || window.mozURL || window).revokeObjectURL;
- function onerror(message) {
- alert(message);
- }
- var model = function(file_name){
- var
- zipFileEntry, zipWriter, writer,
- creationMethod = 'Blob',
- download_url = null;
- if (typeof requestFileSystem != "undefined")
- creationMethod = 'File';
- else
- if (typeof IDBMutableFile != "undefined")
- creationMethod = 'MutableFile';
- function createTempFile(file_name, callback) {
- var tmpFilename = file_name || "tmp.zip";
- requestFileSystem(TEMPORARY, 4 * 1024 * 1024 * 1024, function(filesystem) {
- function create() {
- filesystem.root.getFile(tmpFilename, {
- create : true
- }, function(zipFile) {
- callback(zipFile);
- });
- }
- filesystem.root.getFile(tmpFilename, null, function(entry) {
- entry.remove(create, create);
- }, create);
- });
- }
- function createMutableFile(file_name, contentType, cb){
- var idb = indexedDB.open("vkoptFileStorageDB",{version: 1, storage:'persistent'});
- idb.onsuccess = function(){
- var db = this.result;
- var buildHandle = db.createMutableFile(file_name, contentType);
- buildHandle.onsuccess = function(){
- cb && cb(this.result); // fileHandle
- };
- };
- }
- //function onprogress(current, total) {}
- var add_locked = false;
- var addFile = function (name, data, ondone, onprogress){
- if (add_locked){
- var args = Array.prototype.slice.call(arguments);
- setTimeout(function(){addFile.apply(this, args)}, Math.round(Math.random()*100)+10);
- return;
- }
- add_locked = true;
- var add = function(){
- zipWriter.add(name, new vkopt.zipjs.BlobReader(data), function() {
- add_locked = false;
- ondone();
- }, onprogress);
- }
- function createZipWriter() {
- vkopt.zipjs.createWriter(writer, function(writer) {
- zipWriter = writer;
- add();
- }, onerror);
- }
- if (zipWriter)
- add();
- else switch(creationMethod){
- case 'Blob': {
- writer = new vkopt.zipjs.BlobWriter();
- createZipWriter();
- break;
- };
- case 'File': {
- createTempFile(file_name, function(fileEntry) {
- zipFileEntry = fileEntry;
- writer = new vkopt.zipjs.FileWriter(zipFileEntry);
- createZipWriter();
- });
- break;
- };
- case 'MutableFile': {
- createMutableFile(file_name, "application/zip", function(fileHandle) {
- writer = new vkopt.zipjs.MutableFileWriter(fileHandle, "application/zip");
- createZipWriter();
- })
- break;
- }
- }
- };
- var addFiles = function (files, onadd, onprogress, onend) {
- var addIndex = 0;
- function nextFile() {
- var file = files[addIndex];
- onadd(file);
- addFile(file.name, file, function(){
- addIndex++;
- if (addIndex < files.length)
- nextFile();
- else
- onend();
- }, onprogress)
- }
- nextFile();
- };
- var getBlobURL = function(callback) {
- zipWriter.close(function(blob) {
- var blobURL = creationMethod == "File" ? zipFileEntry.toURL() : url_create(blob);
- callback(blobURL);
- zipWriter = null;
- });
- };
- var getBlob = function(callback) {
- zipWriter.close(callback);
- };
- return {
- addFile: addFile,
- addFiles : addFiles,
- getBlobURL : getBlobURL,
- getBlob : getBlob,
- download: function(){
- var dl = function(){
- if (creationMethod == 'MutableFile'){
- var fr = document.createElement('iframe');
- fr.frameBorder = 0;
- fr.width = 1;
- fr.height = 1;
- document.body.appendChild(fr);
- var doc = fr.contentDocument;
- var form = doc.createElement('form');
- form.action = download_url;
- doc.body.appendChild(form);
- form.submit();
- setTimeout(function(){
- fr.parentNode.removeChild(fr);
- }, 100);
- } else {
- var dlnk = document.createElement('a');
- dlnk.href = download_url;
- dlnk.download = file_name;
- (window.utilsNode || document.body).appendChild(dlnk)
- dlnk.click();
- vkopt.log('Download zip file: ', file_name);
- setTimeout(function(){
- re(dlnk);
- //url_revoke(dlnk);
- },200);
- }
- }
- if (typeof navigator.msSaveBlob == "function") {
- getBlob(function(blob) {
- navigator.msSaveBlob(blob, file_name);
- });
- } else {
- if (!download_url){
- getBlobURL(function(blobURL){
- download_url = blobURL;
- vkopt.log(file_name + ' download url: ' + download_url);
- dl();
- })
- } else dl();
- }
- }
- };
- };
- obj.zip = model;
- })(vkopt);
- var download_photo_list = function(list, name, on_progress){
- var modes = [
- 'direct download',
- 'direct download',
- 'download with domain replace',
- 'download with domain replace',
- 'download through ext bg'
- ];
- var max_threads = 5;
- var max_zip_size = 400 * 1024 * 1024; // 400Mb
- var cur = 0;
- var dl_cnt = 0;
- var zip_cnt = 0;
- var size_sum = 0;
- var url, file_name;
- //var phz = vkopt.zip(name || 'photos.zip');
- var xhrs = [];
- for (var i = 0; i < max_threads; i++){
- var xhr = new XMLHttpRequest();
- xhr.responseType = 'blob';
- xhrs.push(xhr);
- }
- var make_next_zip = function(cb){
- var zipname = (name || 'photos.zip').replace(/(\.zip)?$/i, '_p' + zip_cnt + '.zip');
- size_sum = 0;
- phz = vkopt.zip(zipname);
- phz.addFile('0_info.txt', new Blob(['Archive #'+zip_cnt+'\r\nOriginal file name: ' + zipname + '\r\nDownloaded from vk.com by vkopt extension ( http://vkopt.net/ )'],{type:'plain/text'}), function(){
- cb && cb();
- });
- zip_cnt++;
- }
- var dl = function(idx, mode, callback){
- var error_fired = false;
- var xhr = xhrs.pop();
- if (!xhr) {
- vkopt.log('Get existing XHR object error. Create new');
- xhr = new XMLHttpRequest();
- xhr.responseType = 'blob';
- }
- mode = mode || 0;
- url = list[idx];
- file_name = url.split('?')[0].split('/').pop();
- var onload = function(){
- if (xhr.status == 200){
- xhrs.push(xhr);
- callback(null, xhr.response, idx)
- } else
- onerror();
- };
- var onerror = function(){
- if (error_fired) return;
- error_fired = true;
- vkopt.log('Failed ' + modes[mode] + ': ' + file_name);
- xhrs.push(xhr);
- dl(idx, mode+1, callback)
- };
- xhr.onload = onload;
- xhr.onerror = onerror;
- //xhr.onprogress = function(e){console.log(e.loaded, e.total)}
- switch(mode){
- case 0:
- case 1: //retry
- {
- xhr.open('GET', url, true);
- xhr.send();
- break;
- };
- case 2:
- case 3: // retry
- {
- if (/pp\.userapi\.com/.test(url)){ // пробудем подставить в ссылку домен раздачи, на котором есть CORS хидеры.
- xhrs.push(xhr);
- dl(idx, mode+1, callback);
- } else if (/[^\/\/]+\.userapi\.com/.test(url)){
- url = url.replace(/:\/\/[^\/\/]+\.userapi\.com/,'://pp.userapi.com')
- xhr.open('GET', url, true);
- xhr.send();
- } else
- onerror();
- break;
- };
- case 4: {
- vk_aj.ajax({url: url, method: 'GET', responseType: 'arraybuffer'}, function (response) {
- if (response && response.status == 200){
- xhrs.push(xhr);
- callback(null, new Blob([new Uint8Array(response.raw)],{type:'image/jpeg'}), idx);
- } else
- onerror();
- });
- break;
- };
- default: {
- xhrs.push(xhr);
- callback('Failed while downloading "'+file_name+'"', null, idx);
- }
- }
- }
- if (list.length < 1){
- alert('Photos not found');
- return;
- }
- var thread_count = 0;
- var run_threads = function(){
- make_next_zip(function(){
- for (var i = 0; i < max_threads; i++)
- (cur < list.length) && step();
- });
- }
- var step = function(){
- thread_count++;
- dl(cur++, 0,function(err, result, num){
- size_sum += result.size || result.length || 0;
- phz.addFile(num + '_' + file_name, result, function(){
- dl_cnt++;
- thread_count--;
- on_progress(dl_cnt, list.length);
- if (size_sum >= max_zip_size) {
- check_ready();
- } else if (cur < list.length){
- step();
- } else {
- check_ready();
- }
- });
- });
- }
- var check_ready = function(){
- if (thread_count == 0){
- phz.download();
- if (cur < list.length){
- run_threads();
- }
- } else
- vkopt.log('Wait download ending...');
- }
- run_threads();
- }
- function run(){
- var ainfo = location.href.match(/album(-?\d+)_(\d+)/);
- var p = geByClass1('photos_album_intro_info');
- var wrp = se('<div id="vk_ph_progress" style="padding:10px 40px"></div>');
- if (p)
- p.appendChild(wrp);
- else
- return;
- vkApis.photos_hd(ainfo[1], ainfo[2], function(r){
- vkopt.log('Links collected. Downloading...');
- download_photo_list(r, ainfo[0]+'.zip', function(progr, total){
- wrp.innerHTML = vkProgressBar(progr, total, 700, 'Downloading and Archiving %');
- });
- }, function(progr, total){
- wrp.innerHTML = vkProgressBar(progr, total, 700, 'Collecting links %');
- });
- }
- //*
- if (navigator.storage && navigator.storage.persist)
- navigator.storage.persist().then(function(granted){
- run();
- });
- //*/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement