Changed save.js, fdc.js, and diskdump.js to use a shared download function
This commit is contained in:
parent
3dd7512f4f
commit
255700f88a
7 changed files with 1332 additions and 1337 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -87,7 +87,7 @@ var fNormalize = true;
|
||||||
* BufferPF(init, start, end)
|
* BufferPF(init, start, end)
|
||||||
*
|
*
|
||||||
* BufferPF is our browser polyfill (hence the PF) for Node's Buffer class. It's basically a wrapper object
|
* 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
|
* This is NOT a general-purpose polyfill. It supports only those Buffer constructor calls and methods that the
|
||||||
* DiskDump module actually requires.
|
* DiskDump module actually requires.
|
||||||
|
|
@ -311,10 +311,10 @@ BufferPF.prototype.slice = function(start, end)
|
||||||
/**
|
/**
|
||||||
* DiskDump()
|
* 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.
|
* 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.
|
* to prevent random enumeration of other server resources.
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
|
|
@ -336,7 +336,10 @@ function DiskDump(sDiskPath, asExclude, sFormat, fComments, mbHD, sServerRoot, s
|
||||||
* with a slash, and process.cwd() otherwise.
|
* with a slash, and process.cwd() otherwise.
|
||||||
*/
|
*/
|
||||||
this.sServerRoot = sServerRoot;
|
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.asExclude = asExclude || DiskDump.asExclusions;
|
||||||
this.mbHD = mbHD? parseInt(mbHD, 10) : 0;
|
this.mbHD = mbHD? parseInt(mbHD, 10) : 0;
|
||||||
this.sFormat = (sFormat || DumpAPI.FORMAT.JSON);
|
this.sFormat = (sFormat || DumpAPI.FORMAT.JSON);
|
||||||
|
|
@ -402,7 +405,7 @@ DiskDump.setLogFile = function(file) {
|
||||||
* Class constants
|
* Class constants
|
||||||
*/
|
*/
|
||||||
DiskDump.sAPIURL = "http://www.pcjs.org" + DumpAPI.ENDPOINT;
|
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.sNotice = DiskDump.sAPIURL + " " + DiskDump.sCopyright;
|
||||||
DiskDump.sUsage = "Usage: " + DiskDump.sAPIURL + "?" + DumpAPI.QUERY.PATH + "={url}&" + DumpAPI.QUERY.FORMAT + "=json|data|hex|bytes|img";
|
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) {
|
disk.loadFile(function(err) {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
var sResponse = disk.convertToJSON();
|
var sData, sType, fBase64;
|
||||||
if (sResponse) web.downloadJSON(sResponse);
|
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) {
|
web.getResource(sPath, "bytes", true, function doneReadFileBrowser(sURL, sResource, nErrorCode) {
|
||||||
var buf = sResource;
|
var buf = sResource;
|
||||||
if (!nErrorCode) {
|
if (!nErrorCode) {
|
||||||
if (str.endsWith(sURL, ".img")) {
|
if (!str.endsWith(sURL, ".json")) {
|
||||||
buf = new BufferPF(sResource);
|
buf = new BufferPF(sResource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3050,6 +3067,25 @@ DiskDump.prototype.convertToIMG = function()
|
||||||
return this.bufDisk;
|
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) {
|
if (NODE) {
|
||||||
module.exports = DiskDump;
|
module.exports = DiskDump;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ function FileDump(sFormat, fComments, fDecimal, offDump, nWidthDump, sServerRoot
|
||||||
* Class constants
|
* Class constants
|
||||||
*/
|
*/
|
||||||
FileDump.sAPIURL = "http://www.pcjs.org" + DumpAPI.ENDPOINT;
|
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.sNotice = FileDump.sAPIURL + " " + FileDump.sCopyright;
|
||||||
FileDump.sUsage = "Usage: " + FileDump.sAPIURL + "?" + DumpAPI.QUERY.FILE + "=({path}|{URL})&" + DumpAPI.QUERY.FORMAT + "=(json|data|hex|bytes|rom)";
|
FileDump.sUsage = "Usage: " + FileDump.sAPIURL + "?" + DumpAPI.QUERY.FILE + "=({path}|{URL})&" + DumpAPI.QUERY.FORMAT + "=(json|data|hex|bytes|rom)";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -477,19 +477,8 @@ FDC.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
||||||
if (drive) {
|
if (drive) {
|
||||||
if (drive.disk) {
|
if (drive.disk) {
|
||||||
if (DEBUG) fdc.println("saving disk " + drive.disk.sDiskPath + "...");
|
if (DEBUG) fdc.println("saving disk " + drive.disk.sDiskPath + "...");
|
||||||
var sURI = "data:application/octet-stream;base64," + drive.disk.encodeAsBase64();
|
var sAlert = web.downloadFile(drive.disk.encodeAsBase64(), "octet-stream", true, drive.disk.sDiskFile.replace(".json", ".img"));
|
||||||
var link = document.createElement('a');
|
web.alertUser(sAlert);
|
||||||
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 + '".');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
fdc.notice("No disk loaded in drive");
|
fdc.notice("No disk loaded in drive");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -198,45 +198,18 @@ function downloadPC(sURL, sCSS, nErrorCode, aMachineInfo)
|
||||||
if (sXMLFile && sXSLFile) {
|
if (sXMLFile && sXSLFile) {
|
||||||
var sResources = JSON.stringify(resNew);
|
var sResources = JSON.stringify(resNew);
|
||||||
|
|
||||||
|
sScript += ".js";
|
||||||
sPCJS = matchScript[1] + "var resources=" + sResources + ";" + matchScript[2] + matchScript[3];
|
sPCJS = matchScript[1] + "var resources=" + sResources + ";" + matchScript[2] + matchScript[3];
|
||||||
Component.log("saving machine: '" + idMachine + "' (" + sPCJS.length + " bytes)");
|
Component.log("saving machine: '" + idMachine + "' (" + sPCJS.length + " bytes)");
|
||||||
|
|
||||||
var sURI, sAlert;
|
sPCJS = sPCJS.replace(/\u00A9/g, "©");
|
||||||
var link = document.createElement('a');
|
|
||||||
var fDownload = (!DEBUG && typeof link.download == 'string');
|
|
||||||
|
|
||||||
if (MAXDEBUG) {
|
var sAlert = web.downloadFile(sPCJS, "javascript", false, sScript);
|
||||||
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, "©");
|
|
||||||
sURI = "data:application/javascript,";
|
|
||||||
if (!web.isUserAgent("Firefox")) {
|
|
||||||
fDownload = false;
|
|
||||||
sURI += encodeURI(sPCJS);
|
|
||||||
} else {
|
|
||||||
sURI += encodeURIComponent(sPCJS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fDownload) {
|
sAlert += ', copy it to your web server as "' + sScript + '", and then add the following to your web page:\n\n';
|
||||||
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 += '<div id="' + idMachine + '"></div>\n';
|
sAlert += '<div id="' + idMachine + '"></div>\n';
|
||||||
sAlert += '...\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 += '<script type="text/javascript">embedPC("' + idMachine + '","' + sXMLFile + '","' + sXSLFile + '");</script>\n\n';
|
||||||
sAlert += 'The machine should appear where the <div> is located.';
|
sAlert += 'The machine should appear where the <div> is located.';
|
||||||
web.alertUser(sAlert);
|
web.alertUser(sAlert);
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,7 @@ web.getResource = function(sURL, dataPost, fAsync, done)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof dataPost == "object") {
|
if (dataPost && typeof dataPost == "object") {
|
||||||
var sDataPost = "";
|
var sDataPost = "";
|
||||||
for (var p in dataPost) {
|
for (var p in dataPost) {
|
||||||
if (!dataPost.hasOwnProperty(p)) continue;
|
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]
|
* @param {string} [sFileName]
|
||||||
*/
|
*/
|
||||||
web.downloadJSON = function(sJSON, sFileName)
|
web.downloadFile = function(sData, sType, fBase64, sFileName)
|
||||||
{
|
{
|
||||||
var link, sAlert;
|
var link = null, sAlert;
|
||||||
var fDownload = !!sFileName;
|
var sURI = "data:application/" + sType + (fBase64? ";base64" : "") + ",";
|
||||||
var sURI = "data:application/json,";
|
|
||||||
|
|
||||||
if (!web.isUserAgent("Firefox")) {
|
if (!web.isUserAgent("Firefox")) {
|
||||||
fDownload = false;
|
sURI += (fBase64? sData : encodeURI(sData));
|
||||||
sURI += encodeURI(sJSON);
|
|
||||||
} else {
|
} else {
|
||||||
sURI += encodeURIComponent(sJSON);
|
sURI += (fBase64? sData : encodeURIComponent(sData));
|
||||||
if (fDownload) {
|
if (sFileName) {
|
||||||
link = document.createElement('a');
|
link = document.createElement('a');
|
||||||
if (typeof link.download != 'string') fDownload = false;
|
if (typeof link.download != 'string') link = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (link) {
|
||||||
if (fDownload) {
|
|
||||||
link.href = sURI;
|
link.href = sURI;
|
||||||
link.download = sFileName;
|
link.download = sFileName;
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link); // Firefox requires the link to be in the body
|
||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
sAlert = 'Check your Downloads folder for "' + sFileName + '".';
|
sAlert = 'Check your Downloads folder for "' + sFileName + '"';
|
||||||
} else {
|
} else {
|
||||||
window.open(sURI);
|
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';
|
||||||
}
|
}
|
||||||
|
return sAlert;
|
||||||
web.alertUser(sAlert);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* onCountRepeat(n, fnRepeat, fnComplete, msDelay)
|
* onCountRepeat(n, fnRepeat, fnComplete, msDelay)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue