Changed save.js, fdc.js, and diskdump.js to use a shared download function

This commit is contained in:
Jeff Parsons 2016-02-23 00:06:38 -08:00
commit 255700f88a
7 changed files with 1332 additions and 1337 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -87,7 +87,7 @@ var fNormalize = true;
* BufferPF(init, start, end)
*
* BufferPF is our browser polyfill (hence the PF) for Node's Buffer class. It's basically a wrapper object
* containing a real Buffer in Node and a simulated buffer in a browser.
* containing a real Buffer in Node and a simulated buffer in the browser.
*
* This is NOT a general-purpose polyfill. It supports only those Buffer constructor calls and methods that the
* DiskDump module actually requires.
@ -311,10 +311,10 @@ BufferPF.prototype.slice = function(start, end)
/**
* DiskDump()
*
* TODO: Honor the caller's mbHD size. At the moment, any hard disk build request translates to 10Mb,
* TODO: Honor the caller's mbHD size. At the moment, any hard disk request translates to 10Mb,
* since we rely on a "canned" BPB in aDefaultBPBs.
*
* TODO: If sServerRoot is set, make sure the final sDiskPath refers to something in either /apps/ or /disks/,
* TODO: If sServerRoot is set, make sure sDiskPath refers to something in either /apps/ or /disks/,
* to prevent random enumeration of other server resources.
*
* @constructor
@ -336,7 +336,10 @@ function DiskDump(sDiskPath, asExclude, sFormat, fComments, mbHD, sServerRoot, s
* with a slash, and process.cwd() otherwise.
*/
this.sServerRoot = sServerRoot;
this.sDiskPath = (net.isRemote(sDiskPath)? sDiskPath : path.join(this.sServerRoot, sDiskPath));
this.sDiskPath = sDiskPath;
if (this.sServerRoot && !net.isRemote(sDiskPath)) {
this.sDiskPath = path.join(this.sServerRoot, sDiskPath);
}
this.asExclude = asExclude || DiskDump.asExclusions;
this.mbHD = mbHD? parseInt(mbHD, 10) : 0;
this.sFormat = (sFormat || DumpAPI.FORMAT.JSON);
@ -402,7 +405,7 @@ DiskDump.setLogFile = function(file) {
* Class constants
*/
DiskDump.sAPIURL = "http://www.pcjs.org" + DumpAPI.ENDPOINT;
DiskDump.sCopyright = "© 2012-2015 by Jeff Parsons (@jeffpar)";
DiskDump.sCopyright = "© 2012-2016 by Jeff Parsons (@jeffpar)";
DiskDump.sNotice = DiskDump.sAPIURL + " " + DiskDump.sCopyright;
DiskDump.sUsage = "Usage: " + DiskDump.sAPIURL + "?" + DumpAPI.QUERY.PATH + "={url}&" + DumpAPI.QUERY.FORMAT + "=json|data|hex|bytes|img";
@ -669,8 +672,22 @@ DiskDump.API = function(aParms)
disk.loadFile(function(err) {
if (!err) {
var sResponse = disk.convertToJSON();
if (sResponse) web.downloadJSON(sResponse);
var sData, sType, fBase64;
if (sFormat == DumpAPI.FORMAT.IMG) {
sType = "octet-stream";
var buf = disk.convertToIMG();
if (buf) {
sData = disk.encodeAsBase64(buf);
fBase64 = true;
}
} else {
sType = "json";
sData = disk.convertToJSON();
}
if (sData) {
var sAlert = web.downloadFile(sData, sType, fBase64);
web.alertUser(sAlert);
}
}
});
};
@ -1041,7 +1058,7 @@ DiskDump.readFile = function(sPath, sEncoding, done)
web.getResource(sPath, "bytes", true, function doneReadFileBrowser(sURL, sResource, nErrorCode) {
var buf = sResource;
if (!nErrorCode) {
if (str.endsWith(sURL, ".img")) {
if (!str.endsWith(sURL, ".json")) {
buf = new BufferPF(sResource);
}
}
@ -3050,6 +3067,25 @@ DiskDump.prototype.convertToIMG = function()
return this.bufDisk;
};
/**
* encodeAsBase64(buf)
*
* Converts the buffer contents to base64. TODO: Consider implementing BufferPF.toString('ascii').
*
* @this {DiskDump}
* @param {Buffer} buf
* @return {string}
*/
DiskDump.prototype.encodeAsBase64 = function(buf)
{
var s = "";
for (var off = 0; off < buf.length; off++) {
s += String.fromCharCode(buf.readUInt8(off));
}
return btoa(s);
};
if (NODE) {
module.exports = DiskDump;
} else {

View file

@ -82,7 +82,7 @@ function FileDump(sFormat, fComments, fDecimal, offDump, nWidthDump, sServerRoot
* Class constants
*/
FileDump.sAPIURL = "http://www.pcjs.org" + DumpAPI.ENDPOINT;
FileDump.sCopyright = "© 2012-2015 by Jeff Parsons (@jeffpar)";
FileDump.sCopyright = "© 2012-2016 by Jeff Parsons (@jeffpar)";
FileDump.sNotice = FileDump.sAPIURL + " " + FileDump.sCopyright;
FileDump.sUsage = "Usage: " + FileDump.sAPIURL + "?" + DumpAPI.QUERY.FILE + "=({path}|{URL})&" + DumpAPI.QUERY.FORMAT + "=(json|data|hex|bytes|rom)";

View file

@ -477,19 +477,8 @@ FDC.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
if (drive) {
if (drive.disk) {
if (DEBUG) fdc.println("saving disk " + drive.disk.sDiskPath + "...");
var sURI = "data:application/octet-stream;base64," + drive.disk.encodeAsBase64();
var link = document.createElement('a');
var sFileName = drive.disk.sDiskFile.replace(".json", ".img");
if (typeof link.download == 'string') {
link.href = sURI;
link.download = sFileName;
document.body.appendChild(link); // Firefox requires the link to be in the body
link.click();
document.body.removeChild(link);
} else {
window.open(sURI);
web.alertUser('The disk is being downloaded, but you will need to manually rename it to "' + sFileName + '".');
}
var sAlert = web.downloadFile(drive.disk.encodeAsBase64(), "octet-stream", true, drive.disk.sDiskFile.replace(".json", ".img"));
web.alertUser(sAlert);
} else {
fdc.notice("No disk loaded in drive");
}

View file

@ -198,45 +198,18 @@ function downloadPC(sURL, sCSS, nErrorCode, aMachineInfo)
if (sXMLFile && sXSLFile) {
var sResources = JSON.stringify(resNew);
sScript += ".js";
sPCJS = matchScript[1] + "var resources=" + sResources + ";" + matchScript[2] + matchScript[3];
Component.log("saving machine: '" + idMachine + "' (" + sPCJS.length + " bytes)");
var sURI, sAlert;
var link = document.createElement('a');
var fDownload = (!DEBUG && typeof link.download == 'string');
sPCJS = sPCJS.replace(/\u00A9/g, "&#xA9;");
if (MAXDEBUG) {
sPCJS = sPCJS.replace(/[\u00A0-\u2666]/g, function(c) {
return '&#' + c.charCodeAt(0) + ';';
});
sURI = "data:application/javascript;base64," + btoa(encodeURI(sPCJS));
} else {
sPCJS = sPCJS.replace(/\u00A9/g, "&#xA9;");
sURI = "data:application/javascript,";
if (!web.isUserAgent("Firefox")) {
fDownload = false;
sURI += encodeURI(sPCJS);
} else {
sURI += encodeURIComponent(sPCJS);
}
}
var sAlert = web.downloadFile(sPCJS, "javascript", false, sScript);
if (fDownload) {
link.href = sURI;
link.download = sScript + ".js";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
sAlert = 'Check your Downloads folder for "' + link.download + '", ';
} else {
window.open(sURI);
sAlert = 'Check your browser for a new window/tab containing the PCjs script, ';
}
sAlert += 'copy it to your web server as "' + sScript + '.js", and then add the following to your web page:\n\n';
sAlert += ', copy it to your web server as "' + sScript + '", and then add the following to your web page:\n\n';
sAlert += '<div id="' + idMachine + '"></div>\n';
sAlert += '...\n';
sAlert += '<script type="text/javascript" src="' + sScript + '.js"></script>\n';
sAlert += '<script type="text/javascript" src="' + sScript + '"></script>\n';
sAlert += '<script type="text/javascript">embedPC("' + idMachine + '","' + sXMLFile + '","' + sXSLFile + '");</script>\n\n';
sAlert += 'The machine should appear where the <div> is located.';
web.alertUser(sAlert);

View file

@ -239,7 +239,7 @@ web.getResource = function(sURL, dataPost, fAsync, done)
};
}
if (typeof dataPost == "object") {
if (dataPost && typeof dataPost == "object") {
var sDataPost = "";
for (var p in dataPost) {
if (!dataPost.hasOwnProperty(p)) continue;
@ -601,44 +601,41 @@ web.getURLParameters = function(sParms)
};
/**
* downloadJSON()
* downloadFile(sData, sType, fBase64, sFileName)
*
* @param {string} sJSON
* @param {string} sData
* @param {string} sType
* @param {boolean} [fBase64]
* @param {string} [sFileName]
*/
web.downloadJSON = function(sJSON, sFileName)
web.downloadFile = function(sData, sType, fBase64, sFileName)
{
var link, sAlert;
var fDownload = !!sFileName;
var sURI = "data:application/json,";
var link = null, sAlert;
var sURI = "data:application/" + sType + (fBase64? ";base64" : "") + ",";
if (!web.isUserAgent("Firefox")) {
fDownload = false;
sURI += encodeURI(sJSON);
sURI += (fBase64? sData : encodeURI(sData));
} else {
sURI += encodeURIComponent(sJSON);
if (fDownload) {
sURI += (fBase64? sData : encodeURIComponent(sData));
if (sFileName) {
link = document.createElement('a');
if (typeof link.download != 'string') fDownload = false;
if (typeof link.download != 'string') link = null;
}
}
if (fDownload) {
if (link) {
link.href = sURI;
link.download = sFileName;
document.body.appendChild(link);
document.body.appendChild(link); // Firefox requires the link to be in the body
link.click();
document.body.removeChild(link);
sAlert = 'Check your Downloads folder for "' + sFileName + '".';
sAlert = 'Check your Downloads folder for "' + sFileName + '"';
} else {
window.open(sURI);
sAlert = 'Check your browser for a new window/tab containing the requested data.';
sAlert = 'Check your browser for a new window/tab containing the requested data';
}
web.alertUser(sAlert);
return sAlert;
};
/**
* onCountRepeat(n, fnRepeat, fnComplete, msDelay)
*