toolkit/crashreporter/test/browser/crashreport.sjs

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/crashreporter/test/browser/crashreport.sjs	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,180 @@
     1.4 +const Cc = Components.classes;
     1.5 +const Ci = Components.interfaces;
     1.6 +const CC = Components.Constructor;
     1.7 +
     1.8 +const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
     1.9 +                              "nsIBinaryInputStream",
    1.10 +                              "setInputStream");
    1.11 +
    1.12 +function parseHeaders(data, start)
    1.13 +{
    1.14 +  let headers = {};
    1.15 +
    1.16 +  while (true) {
    1.17 +    let done = false;
    1.18 +    let end = data.indexOf("\r\n", start);
    1.19 +    if (end == -1) {
    1.20 +      done = true;
    1.21 +      end = data.length;
    1.22 +    }
    1.23 +    let line = data.substring(start, end);
    1.24 +    start = end + 2;
    1.25 +    if (line == "")
    1.26 +      // empty line, we're done
    1.27 +      break;
    1.28 +
    1.29 +    //XXX: this doesn't handle multi-line headers. do we care?
    1.30 +    let [name, value] = line.split(':');
    1.31 +    //XXX: not normalized, should probably use nsHttpHeaders or something
    1.32 +    headers[name] = value.trimLeft();
    1.33 +  }
    1.34 +  return [headers, start];
    1.35 +}
    1.36 +
    1.37 +function parseMultipartForm(request)
    1.38 +{
    1.39 +  let boundary = null;
    1.40 +  // See if this is a multipart/form-data request, and if so, find the
    1.41 +  // boundary string
    1.42 +  if (request.hasHeader("Content-Type")) {
    1.43 +    var contenttype = request.getHeader("Content-Type");
    1.44 +    var bits = contenttype.split(";");
    1.45 +    if (bits[0] == "multipart/form-data") {
    1.46 +      for (var i = 1; i < bits.length; i++) {
    1.47 +        var b = bits[i].trimLeft();
    1.48 +        if (b.indexOf("boundary=") == 0) {
    1.49 +          // grab everything after boundary=
    1.50 +          boundary = "--" + b.substring(9);
    1.51 +          break;
    1.52 +        }
    1.53 +      }
    1.54 +    }
    1.55 +  }
    1.56 +  if (boundary == null)
    1.57 +    return null;
    1.58 +
    1.59 +  let body = new BinaryInputStream(request.bodyInputStream);
    1.60 +  let avail;
    1.61 +  let bytes = [];
    1.62 +  while ((avail = body.available()) > 0) {
    1.63 +    let readBytes = body.readByteArray(avail);
    1.64 +    for (let b of readBytes) {
    1.65 +      bytes.push(b);
    1.66 +    }
    1.67 +  }
    1.68 +  let data = "";
    1.69 +  for (let b of bytes) {
    1.70 +    data += String.fromCharCode(b);
    1.71 +  }
    1.72 +  let formData = {};
    1.73 +  let done = false;
    1.74 +  let start = 0;
    1.75 +  while (true) {
    1.76 +    // read first line
    1.77 +    let end = data.indexOf("\r\n", start);
    1.78 +    if (end == -1) {
    1.79 +      done = true;
    1.80 +      end = data.length;
    1.81 +    }
    1.82 +
    1.83 +    let line = data.substring(start, end);
    1.84 +    // look for closing boundary delimiter line
    1.85 +    if (line == boundary + "--") {
    1.86 +      break;
    1.87 +    }
    1.88 +
    1.89 +    if (line != boundary) {
    1.90 +      dump("expected boundary line but didn't find it!");
    1.91 +      break;
    1.92 +    }
    1.93 +
    1.94 +    // parse headers
    1.95 +    start = end + 2;
    1.96 +    let headers = null;
    1.97 +    [headers, start] = parseHeaders(data, start);
    1.98 +
    1.99 +    // find next boundary string
   1.100 +    end = data.indexOf("\r\n" + boundary, start);
   1.101 +    if (end == -1) {
   1.102 +      dump("couldn't find next boundary string\n");
   1.103 +      break;
   1.104 +    }
   1.105 +
   1.106 +    // read part data, stick in formData using Content-Disposition header
   1.107 +    let part = data.substring(start, end);
   1.108 +    start = end + 2;
   1.109 +
   1.110 +    if ("Content-Disposition" in headers) {
   1.111 +      let bits = headers["Content-Disposition"].split(';');
   1.112 +      if (bits[0] == 'form-data') {
   1.113 +        for (let i = 0; i < bits.length; i++) {
   1.114 +          let b = bits[i].trimLeft();
   1.115 +          if (b.indexOf('name=') == 0) {
   1.116 +            //TODO: handle non-ascii here?
   1.117 +            let name = b.substring(6, b.length - 1);
   1.118 +            //TODO: handle multiple-value properties?
   1.119 +            formData[name] = part;
   1.120 +          }
   1.121 +          //TODO: handle filename= ?
   1.122 +          //TODO: handle multipart/mixed for multi-file uploads?
   1.123 +        }
   1.124 +      }
   1.125 +    }
   1.126 +  }
   1.127 +  return formData;
   1.128 +}
   1.129 +
   1.130 +function handleRequest(request, response)
   1.131 +{
   1.132 +  if (request.method == "GET") {
   1.133 +    let id = null;
   1.134 +    for each(p in request.queryString.split('&')) {
   1.135 +      let [key, value] = p.split('=');
   1.136 +      if (key == 'id')
   1.137 +        id = value;
   1.138 +    }
   1.139 +    if (id == null) {
   1.140 +      response.setStatusLine(request.httpVersion, 400, "Bad Request");
   1.141 +      response.write("Missing id parameter");
   1.142 +    }
   1.143 +    else {
   1.144 +      let data = getState(id);
   1.145 +      if (data == "") {
   1.146 +        response.setStatusLine(request.httpVersion, 404, "Not Found");
   1.147 +        response.write("Not Found");
   1.148 +      }
   1.149 +      else {
   1.150 +        response.setHeader("Content-Type", "text/plain", false);
   1.151 +        response.write(data);
   1.152 +      }
   1.153 +    }
   1.154 +  }
   1.155 +  else if (request.method == "POST") {
   1.156 +    let formData = parseMultipartForm(request);
   1.157 +
   1.158 +    if (formData && 'upload_file_minidump' in formData) {
   1.159 +      response.setHeader("Content-Type", "text/plain", false);
   1.160 +
   1.161 +      let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
   1.162 +        .getService(Ci.nsIUUIDGenerator);
   1.163 +      let uuid = uuidGenerator.generateUUID().toString();
   1.164 +      // ditch the {}, add bp- prefix
   1.165 +      uuid = 'bp-' + uuid.substring(1,uuid.length-2);
   1.166 +
   1.167 +      let d = JSON.stringify(formData);
   1.168 +      //dump('saving crash report ' + uuid + ': ' + d + '\n');
   1.169 +      setState(uuid, d);
   1.170 +
   1.171 +      response.write("CrashID=" + uuid + "\n");
   1.172 +    }
   1.173 +    else {
   1.174 +      dump('*** crashreport.sjs: Malformed request?\n');
   1.175 +      response.setStatusLine(request.httpVersion, 400, "Bad Request");
   1.176 +      response.write("Missing minidump file");
   1.177 +    }
   1.178 +  }
   1.179 +  else {
   1.180 +    response.setStatusLine(request.httpVersion, 405, "Method not allowed");
   1.181 +    response.write("Can't handle HTTP method " + request.method);
   1.182 +  }
   1.183 +}

mercurial