summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/test/browser/crashreport.sjs
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/test/browser/crashreport.sjs')
-rw-r--r--toolkit/crashreporter/test/browser/crashreport.sjs180
1 files changed, 180 insertions, 0 deletions
diff --git a/toolkit/crashreporter/test/browser/crashreport.sjs b/toolkit/crashreporter/test/browser/crashreport.sjs
new file mode 100644
index 000000000..f3bd858eb
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/crashreport.sjs
@@ -0,0 +1,180 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const CC = Components.Constructor;
+
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function parseHeaders(data, start)
+{
+ let headers = {};
+
+ while (true) {
+ let done = false;
+ let end = data.indexOf("\r\n", start);
+ if (end == -1) {
+ done = true;
+ 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 done = false;
+ let start = 0;
+ while (true) {
+ // read first line
+ let end = data.indexOf("\r\n", start);
+ if (end == -1) {
+ done = true;
+ 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?
+ 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 uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
+ .getService(Ci.nsIUUIDGenerator);
+ let uuid = uuidGenerator.generateUUID().toString();
+ // ditch the {}, add bp- prefix
+ uuid = 'bp-' + uuid.substring(1,uuid.length-2);
+
+ 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);
+ }
+}