- BREAKING CHANGE from v0.9.35 and eariler: Move accounts into subfolder of SessionStore - viewergen and viewer updates from @GraspYonOx - new homepage theme inspired by @GraspYonOx - connect setup also mostly by @GraspYonOx - numerous bug fixes - nntp-server-zefie is now on npmjs - implement proper nodejs debugging - will start to phase out using console.log for actual debugging - existing "debug" (verbose) messages will stay as is - future code debugging will use debug() to debug WIP, therefore not showing to most users if it is accidently left in
195 lines
8.9 KiB
JavaScript
195 lines
8.9 KiB
JavaScript
class WTVFlashrom {
|
|
|
|
fs = require('fs');
|
|
https = require('follow-redirects').https;
|
|
use_zefie_server = true;
|
|
bf0app_update = false;
|
|
service_vaults = new Array();
|
|
no_debug = false;
|
|
service_name = "";
|
|
minisrv_config = [];
|
|
wtvshared = null;
|
|
|
|
|
|
constructor(minisrv_config, service_vaults, service_name, use_zefie_server = true, bf0app_update = false, no_debug = false) {
|
|
var { WTVShared } = require("./WTVShared.js");
|
|
this.service_vaults = service_vaults;
|
|
this.service_name = service_name;
|
|
this.use_zefie_server = use_zefie_server;
|
|
this.bf0app_update = bf0app_update;
|
|
this.no_debug = no_debug;
|
|
this.minisrv_config = minisrv_config;
|
|
this.wtvshared = new WTVShared(minisrv_config);
|
|
}
|
|
|
|
async doLocalFlashROM(flashrom_file_path, request_path, callback, info_only = false) {
|
|
// use local flashrom files;
|
|
var self = this;
|
|
try {
|
|
this.fs.readFile(flashrom_file_path, null, function (err, data) {
|
|
if (err) {
|
|
errpage = wtvshared.doErrorPage(400)
|
|
var headers = errpage[0];
|
|
data = err.toString();
|
|
callback(data, headers);
|
|
} else {
|
|
if (info_only) {
|
|
callback(self.getFlashromInfo(data, request_path));
|
|
} else {
|
|
self.sendToClient(data, request_path, callback);
|
|
}
|
|
}
|
|
});
|
|
} catch (e) {
|
|
var errpage = this.wtvshared.doErrorPage(404, "The service could not find the requested ROM.")
|
|
var headers = errpage[0];
|
|
var data = errpage[1];
|
|
callback(data, headers);
|
|
}
|
|
}
|
|
|
|
formatPartNum(partnum) {
|
|
if (partnum < 10) return "00" + partnum; // 1s
|
|
else if (partnum >= 10 && partnum < 100) return "0" + partnum; // 10s
|
|
else return partnum; // 100s
|
|
}
|
|
|
|
|
|
getFlashromInfo(data, path) {
|
|
var flashrom_info = new Array();
|
|
var flashrom_magic = "96031889";
|
|
var part_header = new Buffer.alloc(32);
|
|
data.copy(part_header, 0, 0, 32);
|
|
flashrom_info.header_length = data.readUInt16BE(26);
|
|
|
|
flashrom_info.is_bootrom = (/\.brom$/).test(path);
|
|
|
|
// re-read entire header
|
|
var part_header = new Buffer.alloc(flashrom_info.header_length);
|
|
data.copy(part_header, 0, 0, flashrom_info.header_length);
|
|
|
|
flashrom_info.magic = part_header.toString('hex', 0, 4);
|
|
flashrom_info.valid_flashrom = false;
|
|
if (flashrom_info.magic == flashrom_magic) flashrom_info.valid_flashrom = true;
|
|
if (!flashrom_info.valid_flashrom) console.error(" * Warning! FlashROM File Magic (" + flashrom_info.magic + ") did not match expected magic (" + flashrom_magic + ")...");
|
|
|
|
//if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # FlashROM File Magic (" + flashrom_info.magic + "), expected magic (" + flashrom_magic + "), OK = " + flashrom_info.valid_flashrom + "...");
|
|
flashrom_info.byte_progress = data.readUInt32BE(68);
|
|
flashrom_info.compression_type = parseInt(part_header[16], 16);
|
|
//if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # Flashrom Part Compression Type:", flashrom_info.compression_type);
|
|
flashrom_info.part_data_size = data.readUInt32BE(4);
|
|
//if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # Flashrom Part Data Size:", flashrom_info.part_data_size);
|
|
flashrom_info.part_total_size = flashrom_info.part_data_size + flashrom_info.header_length;
|
|
flashrom_info.total_parts_size = data.readUInt32BE(32);
|
|
flashrom_info.percent_complete = ((((flashrom_info.byte_progress + flashrom_info.part_total_size) / flashrom_info.total_parts_size)) * 100).toFixed(1);
|
|
|
|
if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Part Size :", flashrom_info.part_total_size);
|
|
if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Bytes Sent :", flashrom_info.byte_progress);
|
|
if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Bytes Sent+:", flashrom_info.byte_progress + flashrom_info.part_total_size, "(" + flashrom_info.percent_complete + "% complete)");
|
|
if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Total Size :", flashrom_info.total_parts_size);
|
|
|
|
// read current part number bit from part header
|
|
flashrom_info.part_number = data.readUInt16BE(28);
|
|
|
|
if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Curr Part Number :", flashrom_info.part_number);
|
|
flashrom_info.is_last_part = ((flashrom_info.byte_progress + flashrom_info.part_total_size) == flashrom_info.total_parts_size) ? true : false;
|
|
|
|
if (flashrom_info.is_last_part) {
|
|
if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Curr Part is Last:", flashrom_info.is_last_part);
|
|
} else {
|
|
flashrom_info.next_part_number = flashrom_info.part_number + 1;
|
|
if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Next Part Number :", flashrom_info.next_part_number);
|
|
}
|
|
|
|
if (this.minisrv_config.config.debug_flags.debug && this.minisrv_config.config.debug_flags.quiet) console.log(" # Sending", (flashrom_info.is_last_part) ? "Last Flashrom" : "Flashrom", "Part", flashrom_info.part_number, "- Bytes Sent:", flashrom_info.byte_progress + flashrom_info.part_total_size, "of", flashrom_info.total_parts_size, "(" + flashrom_info.percent_complete + " % complete)");
|
|
// read current part display message from part header
|
|
flashrom_info.message = new Buffer.from(part_header.toString('hex').substring(36 * 2, 68 * 2), 'hex').toString('ascii').replace(/[^0-9a-z\ \.\-]/gi, "");
|
|
flashrom_info.rompath = `wtv-flashrom:/${path}`;
|
|
|
|
if (flashrom_info.is_last_part && this.bf0app_update) {
|
|
flashrom_info.next_rompath = null;
|
|
} else if (flashrom_info.is_last_part && !this.bf0app_update) {
|
|
flashrom_info.next_rompath = "wtv-flashrom:/lc2-download-complete?";
|
|
} else {
|
|
flashrom_info.next_part_number = this.formatPartNum(flashrom_info.part_number + 1);
|
|
flashrom_info.next_rompath = flashrom_info.rompath.replace("part" + this.formatPartNum(flashrom_info.part_number), "part" + flashrom_info.next_part_number);
|
|
}
|
|
return flashrom_info;
|
|
}
|
|
|
|
async sendToClient(data, request_path, callback) {
|
|
var headers = "200 OK\n";
|
|
var flashrom_info = this.getFlashromInfo(data, request_path)
|
|
if (flashrom_info.is_bootrom) headers += "Content-Type: binary/x-wtv-bootrom"; // maybe?
|
|
else headers += "Content-Type: binary/x-wtv-flashblock";
|
|
if (flashrom_info.next_rompath != null && this.bf0app_update) headers += "\nwtv-visit: " + flashrom_info.next_rompath;
|
|
headers += "\nminisrv-no-mail-count: true";
|
|
callback(data, headers);
|
|
}
|
|
|
|
async getFlashromMeta(request_path, callback) {
|
|
// read 512 bytes of rom, and send result of getFlashromInfo
|
|
// to callback (in data)
|
|
this.getFlashRom(request_path, callback, 512);
|
|
}
|
|
|
|
async getFlashRom(request_path, callback, length = 0) {
|
|
var headers, flashrom_file_path = null;
|
|
var self = this;
|
|
Object.keys(self.service_vaults).forEach(function (g) {
|
|
if (flashrom_file_path != null) return;
|
|
flashrom_file_path = self.service_vaults[g] + "/" + self.service_name + "/" + request_path;
|
|
if (!self.fs.existsSync(flashrom_file_path)) flashrom_file_path = null;
|
|
});
|
|
if (this.use_zefie_server && !flashrom_file_path) {
|
|
// get flashrom files from archive.midnightchannel.net
|
|
var options = {
|
|
host: "archive.midnightchannel.net",
|
|
path: "/zefie/files/wtv-flashrom/" + request_path,
|
|
timeout: 5000,
|
|
method: 'GET'
|
|
}
|
|
if (length > 0) {
|
|
options.headers = {
|
|
'Range': 'bytes=0-' + length
|
|
}
|
|
}
|
|
|
|
const req = this.https.request(options, function (res) {
|
|
var data_hex = '';
|
|
res.setEncoding('hex');
|
|
|
|
res.on('data', d => {
|
|
data_hex += d;
|
|
})
|
|
|
|
res.on('end', function () {
|
|
if (self.minisrv_config.config.debug_flags.debug) console.log(` * zefie's FlashROM Server HTTP Status: ${res.statusCode} ${res.statusMessage}`)
|
|
if (res.statusCode == 200) {
|
|
var data = Buffer.from(data_hex, 'hex');
|
|
} else if (res.statusCode == 206) {
|
|
var data = self.getFlashromInfo(Buffer.from(data_hex, 'hex'), request_path);
|
|
} else if (res.statusCode == 404) {
|
|
var errpage = self.wtvshared.doErrorPage(404, "The service could not find the requested ROM on zefie's server.")
|
|
headers = errpage[0];
|
|
var data = errpage[1];
|
|
} else {
|
|
var errpage = self.wtvshared.doErrorPage(400)
|
|
headers = errpage[0];
|
|
var data = errpage[1];
|
|
}
|
|
if (!headers && res.statusCode != 206) {
|
|
self.sendToClient(data, request_path, callback);
|
|
} else {
|
|
callback(data, headers);
|
|
}
|
|
});
|
|
});
|
|
req.end();
|
|
} else {
|
|
this.doLocalFlashROM(flashrom_file_path, request_path, callback, ((length != 0) ? true : false));
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = WTVFlashrom; |