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 +}