DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (d38398e5144e)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 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);
  }
}