ba0ecf03dd
We now properly try to read archives in all three formats. If none are valid, the dataFileService.readDataArrayAsPossibleArchive fails (as it should), and then the Dockerfile service will try to read the file directly as a Dockerfile. Fixes #1889 Fixes #1891
176 lines
4.6 KiB
JavaScript
176 lines
4.6 KiB
JavaScript
/**
|
|
* Service which provides helper methods for downloading a data file from a URL, and extracting
|
|
* its contents as .tar, .tar.gz, or .zip file. Note that this service depends on external
|
|
* library code in the lib/ directory:
|
|
* - jszip.min.js
|
|
* - Blob.js
|
|
* - zlib.js
|
|
*/
|
|
angular.module('quay').factory('DataFileService', [function() {
|
|
var dataFileService = {};
|
|
|
|
dataFileService.getName_ = function(filePath) {
|
|
var parts = filePath.split('/');
|
|
return parts[parts.length - 1];
|
|
};
|
|
|
|
dataFileService.tryAsZip_ = function(buf, success, failure) {
|
|
var zip = null;
|
|
var zipFiles = null;
|
|
try {
|
|
var zip = new JSZip(buf);
|
|
zipFiles = zip.files;
|
|
} catch (e) {
|
|
failure();
|
|
return;
|
|
}
|
|
|
|
var files = [];
|
|
for (var filePath in zipFiles) {
|
|
if (zipFiles.hasOwnProperty(filePath)) {
|
|
files.push({
|
|
'name': dataFileService.getName_(filePath),
|
|
'path': filePath,
|
|
'canRead': true,
|
|
'toBlob': (function(fp) {
|
|
return function() {
|
|
return new Blob([zip.file(fp).asArrayBuffer()]);
|
|
};
|
|
}(filePath))
|
|
});
|
|
}
|
|
}
|
|
|
|
success(files);
|
|
};
|
|
|
|
dataFileService.tryAsTarGz_ = function(buf, success, failure) {
|
|
var gunzip = new Zlib.Gunzip(new Uint8Array(buf));
|
|
var plain = null;
|
|
|
|
try {
|
|
plain = gunzip.decompress();
|
|
} catch (e) {
|
|
failure();
|
|
return;
|
|
}
|
|
|
|
if (plain.byteLength == 0) {
|
|
plain = buf;
|
|
}
|
|
|
|
dataFileService.tryAsTar_(plain, success, failure);
|
|
};
|
|
|
|
dataFileService.tryAsTar_ = function(buf, success, failure) {
|
|
var collapsePath = function(originalPath) {
|
|
// Tar files can contain entries of the form './', so we need to collapse
|
|
// those paths down.
|
|
var parts = originalPath.split('/');
|
|
for (var i = parts.length - 1; i >= 0; i--) {
|
|
var part = parts[i];
|
|
if (part == '.') {
|
|
parts.splice(i, 1);
|
|
}
|
|
}
|
|
return parts.join('/');
|
|
};
|
|
|
|
var handler = new Untar(new Uint8Array(buf));
|
|
handler.process(function(status, read, files, err) {
|
|
switch (status) {
|
|
case 'error':
|
|
failure(err);
|
|
break;
|
|
|
|
case 'done':
|
|
var processed = [];
|
|
for (var i = 0; i < files.length; ++i) {
|
|
var currentFile = files[i];
|
|
var path = collapsePath(currentFile.meta.filename);
|
|
|
|
if (path == '' || path == 'pax_global_header') { continue; }
|
|
|
|
processed.push({
|
|
'name': dataFileService.getName_(path),
|
|
'path': path,
|
|
'canRead': true,
|
|
'toBlob': (function(currentFile) {
|
|
return function() {
|
|
return new Blob([currentFile.buffer], {type: 'application/octet-binary'});
|
|
};
|
|
}(currentFile))
|
|
});
|
|
}
|
|
success(processed);
|
|
break;
|
|
}
|
|
});
|
|
};
|
|
|
|
dataFileService.blobToString = function(blob, callback) {
|
|
var reader = new FileReader();
|
|
reader.onload = function(event){
|
|
callback(reader.result);
|
|
};
|
|
reader.readAsText(blob);
|
|
};
|
|
|
|
dataFileService.arrayToString = function(buf, callback) {
|
|
var bb = new Blob([buf], {type: 'application/octet-binary'});
|
|
var f = new FileReader();
|
|
f.onload = function(e) {
|
|
callback(e.target.result);
|
|
};
|
|
f.onerror = function(e) {
|
|
callback(null);
|
|
};
|
|
f.onabort = function(e) {
|
|
callback(null);
|
|
};
|
|
f.readAsText(bb);
|
|
};
|
|
|
|
dataFileService.readDataArrayAsPossibleArchive = function(buf, success, failure) {
|
|
dataFileService.tryAsZip_(buf, success, function() {
|
|
dataFileService.tryAsTarGz_(buf, success, function() {
|
|
dataFileService.tryAsTar_(buf, success, failure);
|
|
});
|
|
});
|
|
};
|
|
|
|
dataFileService.downloadDataFileAsArrayBuffer = function($scope, url, progress, error, loaded) {
|
|
var request = new XMLHttpRequest();
|
|
request.open('GET', url, true);
|
|
request.responseType = 'arraybuffer';
|
|
|
|
request.onprogress = function(e) {
|
|
$scope.$apply(function() {
|
|
var percentLoaded;
|
|
if (e.lengthComputable) {
|
|
progress(e.loaded / e.total);
|
|
}
|
|
});
|
|
};
|
|
|
|
request.onerror = function() {
|
|
$scope.$apply(function() {
|
|
error();
|
|
});
|
|
};
|
|
|
|
request.onload = function() {
|
|
if (this.status == 200) {
|
|
$scope.$apply(function() {
|
|
var uint8array = new Uint8Array(request.response);
|
|
loaded(uint8array);
|
|
});
|
|
return;
|
|
}
|
|
};
|
|
|
|
request.send();
|
|
};
|
|
|
|
return dataFileService;
|
|
}]);
|