From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- toolkit/crashreporter/test/browser/crashreport.sjs | 176 +++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 toolkit/crashreporter/test/browser/crashreport.sjs (limited to 'toolkit/crashreporter/test/browser/crashreport.sjs') diff --git a/toolkit/crashreporter/test/browser/crashreport.sjs b/toolkit/crashreporter/test/browser/crashreport.sjs new file mode 100644 index 0000000000..908455c9e6 --- /dev/null +++ b/toolkit/crashreporter/test/browser/crashreport.sjs @@ -0,0 +1,176 @@ +const CC = Components.Constructor; + +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function parseHeaders(data, start) { + let headers = {}; + + while (true) { + let end = data.indexOf("\r\n", start); + if (end == -1) { + end = data.length; + } + let line = data.substring(start, end); + start = end + 2; + if (line == "") { + // empty line, we're done + break; + } + + //XXX: this doesn't handle multi-line headers. do we care? + let [name, value] = line.split(":"); + //XXX: not normalized, should probably use nsHttpHeaders or something + headers[name] = value.trimLeft(); + } + return [headers, start]; +} + +function parseMultipartForm(request) { + let boundary = null; + // See if this is a multipart/form-data request, and if so, find the + // boundary string + if (request.hasHeader("Content-Type")) { + var contenttype = request.getHeader("Content-Type"); + var bits = contenttype.split(";"); + if (bits[0] == "multipart/form-data") { + for (var i = 1; i < bits.length; i++) { + var b = bits[i].trimLeft(); + if (b.indexOf("boundary=") == 0) { + // grab everything after boundary= + boundary = "--" + b.substring(9); + break; + } + } + } + } + if (boundary == null) { + return null; + } + + let body = new BinaryInputStream(request.bodyInputStream); + let avail; + let bytes = []; + while ((avail = body.available()) > 0) { + let readBytes = body.readByteArray(avail); + for (let b of readBytes) { + bytes.push(b); + } + } + let data = ""; + for (let b of bytes) { + data += String.fromCharCode(b); + } + let formData = {}; + let start = 0; + while (true) { + // read first line + let end = data.indexOf("\r\n", start); + if (end == -1) { + end = data.length; + } + + let line = data.substring(start, end); + // look for closing boundary delimiter line + if (line == boundary + "--") { + break; + } + + if (line != boundary) { + dump("expected boundary line but didn't find it!"); + break; + } + + // parse headers + start = end + 2; + let headers = null; + [headers, start] = parseHeaders(data, start); + + // find next boundary string + end = data.indexOf("\r\n" + boundary, start); + if (end == -1) { + dump("couldn't find next boundary string\n"); + break; + } + + // read part data, stick in formData using Content-Disposition header + let part = data.substring(start, end); + start = end + 2; + + if ("Content-Disposition" in headers) { + let bits = headers["Content-Disposition"].split(";"); + if (bits[0] == "form-data") { + for (let i = 0; i < bits.length; i++) { + let b = bits[i].trimLeft(); + if (b.indexOf("name=") == 0) { + //TODO: handle non-ascii here? + let name = b.substring(6, b.length - 1); + //TODO: handle multiple-value properties? + if ( + "Content-Type" in headers && + headers["Content-Type"] == "application/json" + ) { + formData = Object.assign(formData, JSON.parse(part)); + } else { + formData[name] = part; + } + } + //TODO: handle filename= ? + //TODO: handle multipart/mixed for multi-file uploads? + } + } + } + } + return formData; +} + +function handleRequest(request, response) { + if (request.method == "GET") { + let id = null; + for (let p of request.queryString.split("&")) { + let [key, value] = p.split("="); + if (key == "id") { + id = value; + } + } + if (id == null) { + response.setStatusLine(request.httpVersion, 400, "Bad Request"); + response.write("Missing id parameter"); + } else { + let data = getState(id); + if (data == "") { + response.setStatusLine(request.httpVersion, 404, "Not Found"); + response.write("Not Found"); + } else { + response.setHeader("Content-Type", "text/plain", false); + response.write(data); + } + } + } else if (request.method == "POST") { + let formData = parseMultipartForm(request); + + if (formData && "upload_file_minidump" in formData) { + response.setHeader("Content-Type", "text/plain", false); + + let uuid = Services.uuid.generateUUID().toString(); + // ditch the {}, add bp- prefix + uuid = "bp-" + uuid.substring(1, uuid.length - 1); + + let d = JSON.stringify(formData); + //dump('saving crash report ' + uuid + ': ' + d + '\n'); + setState(uuid, d); + + response.write("CrashID=" + uuid + "\n"); + } else { + dump("*** crashreport.sjs: Malformed request?\n"); + response.setStatusLine(request.httpVersion, 400, "Bad Request"); + response.write("Missing minidump file"); + } + } else { + response.setStatusLine(request.httpVersion, 405, "Method not allowed"); + response.write("Can't handle HTTP method " + request.method); + } +} -- cgit v1.2.3