зеркало из https://github.com/mozilla/gecko-dev.git
210 строки
5.6 KiB
JavaScript
210 строки
5.6 KiB
JavaScript
// Test the plaintext-or-binary sniffer
|
|
|
|
"use strict";
|
|
|
|
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
|
|
|
|
// List of Content-Type headers to test. For each header we have an array.
|
|
// The first element in the array is the Content-Type header string. The
|
|
// second element in the array is a boolean indicating whether we allow
|
|
// sniffing for that type.
|
|
var contentTypeHeaderList = [
|
|
["text/plain", true],
|
|
["text/plain; charset=ISO-8859-1", true],
|
|
["text/plain; charset=iso-8859-1", true],
|
|
["text/plain; charset=UTF-8", true],
|
|
["text/plain; charset=unknown", false],
|
|
["text/plain; param", false],
|
|
["text/plain; charset=ISO-8859-1; param", false],
|
|
["text/plain; charset=iso-8859-1; param", false],
|
|
["text/plain; charset=UTF-8; param", false],
|
|
["text/plain; charset=utf-8", false],
|
|
["text/plain; charset=utf8", false],
|
|
["text/plain; charset=UTF8", false],
|
|
["text/plain; charset=iSo-8859-1", false],
|
|
];
|
|
|
|
// List of response bodies to test. For each response we have an array. The
|
|
// first element in the array is the body string. The second element in the
|
|
// array is a boolean indicating whether that string should sniff as binary.
|
|
var bodyList = [["Plaintext", false]];
|
|
|
|
// List of possible BOMs
|
|
var BOMList = [
|
|
"\xFE\xFF", // UTF-16BE
|
|
"\xFF\xFE", // UTF-16LE
|
|
"\xEF\xBB\xBF", // UTF-8
|
|
"\x00\x00\xFE\xFF", // UCS-4BE
|
|
"\x00\x00\xFF\xFE", // UCS-4LE
|
|
];
|
|
|
|
// Build up bodyList. The things we treat as binary are ASCII codes 0-8,
|
|
// 14-26, 28-31. That is, the control char range, except for tab, newline,
|
|
// vertical tab, form feed, carriage return, and ESC (this last being used by
|
|
// Shift_JIS, apparently).
|
|
function isBinaryChar(ch) {
|
|
return (
|
|
(0 <= ch && ch <= 8) || (14 <= ch && ch <= 26) || (28 <= ch && ch <= 31)
|
|
);
|
|
}
|
|
|
|
// Test chars on their own
|
|
var i;
|
|
for (i = 0; i <= 127; ++i) {
|
|
bodyList.push([String.fromCharCode(i), isBinaryChar(i)]);
|
|
}
|
|
|
|
// Test that having a BOM prevents plaintext sniffing
|
|
var j;
|
|
for (i = 0; i <= 127; ++i) {
|
|
for (j = 0; j < BOMList.length; ++j) {
|
|
bodyList.push([BOMList[j] + String.fromCharCode(i, i), false]);
|
|
}
|
|
}
|
|
|
|
// Test that having a BOM requires at least 4 chars to kick in
|
|
for (i = 0; i <= 127; ++i) {
|
|
for (j = 0; j < BOMList.length; ++j) {
|
|
bodyList.push([
|
|
BOMList[j] + String.fromCharCode(i),
|
|
BOMList[j].length == 2 && isBinaryChar(i),
|
|
]);
|
|
}
|
|
}
|
|
|
|
function makeChan(headerIdx, bodyIdx) {
|
|
var chan = NetUtil.newChannel({
|
|
uri:
|
|
"http://localhost:" +
|
|
httpserv.identity.primaryPort +
|
|
"/" +
|
|
headerIdx +
|
|
"/" +
|
|
bodyIdx,
|
|
loadUsingSystemPrincipal: true,
|
|
}).QueryInterface(Ci.nsIHttpChannel);
|
|
|
|
chan.loadFlags |= Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
|
|
|
|
return chan;
|
|
}
|
|
|
|
function makeListener(headerIdx, bodyIdx) {
|
|
var listener = {
|
|
onStartRequest: function test_onStartR(request) {
|
|
try {
|
|
var chan = request.QueryInterface(Ci.nsIChannel);
|
|
|
|
Assert.equal(chan.status, Cr.NS_OK);
|
|
|
|
var type = chan.contentType;
|
|
|
|
var expectedType =
|
|
contentTypeHeaderList[headerIdx][1] && bodyList[bodyIdx][1]
|
|
? "application/x-vnd.mozilla.guess-from-ext"
|
|
: "text/plain";
|
|
if (expectedType != type) {
|
|
do_throw(
|
|
"Unexpected sniffed type '" +
|
|
type +
|
|
"'. " +
|
|
"Should be '" +
|
|
expectedType +
|
|
"'. " +
|
|
"Header is ['" +
|
|
contentTypeHeaderList[headerIdx][0] +
|
|
"', " +
|
|
contentTypeHeaderList[headerIdx][1] +
|
|
"]. " +
|
|
"Body is ['" +
|
|
bodyList[bodyIdx][0].toSource() +
|
|
"', " +
|
|
bodyList[bodyIdx][1] +
|
|
"]."
|
|
);
|
|
}
|
|
Assert.equal(expectedType, type);
|
|
} catch (e) {
|
|
do_throw("Unexpected exception: " + e);
|
|
}
|
|
|
|
throw Components.Exception("", Cr.NS_ERROR_ABORT);
|
|
},
|
|
|
|
onDataAvailable: function test_ODA() {
|
|
do_throw("Should not get any data!");
|
|
},
|
|
|
|
onStopRequest: function test_onStopR(request, status) {
|
|
// Advance to next test
|
|
++headerIdx;
|
|
if (headerIdx == contentTypeHeaderList.length) {
|
|
headerIdx = 0;
|
|
++bodyIdx;
|
|
}
|
|
|
|
if (bodyIdx == bodyList.length) {
|
|
do_test_pending();
|
|
httpserv.stop(do_test_finished);
|
|
} else {
|
|
doTest(headerIdx, bodyIdx);
|
|
}
|
|
|
|
do_test_finished();
|
|
},
|
|
};
|
|
|
|
return listener;
|
|
}
|
|
|
|
function doTest(headerIdx, bodyIdx) {
|
|
var chan = makeChan(headerIdx, bodyIdx);
|
|
|
|
var listener = makeListener(headerIdx, bodyIdx);
|
|
|
|
chan.asyncOpen(listener);
|
|
|
|
do_test_pending();
|
|
}
|
|
|
|
function createResponse(headerIdx, bodyIdx, metadata, response) {
|
|
response.setHeader(
|
|
"Content-Type",
|
|
contentTypeHeaderList[headerIdx][0],
|
|
false
|
|
);
|
|
response.bodyOutputStream.write(
|
|
bodyList[bodyIdx][0],
|
|
bodyList[bodyIdx][0].length
|
|
);
|
|
}
|
|
|
|
function makeHandler(headerIdx, bodyIdx) {
|
|
var f = function handlerClosure(metadata, response) {
|
|
return createResponse(headerIdx, bodyIdx, metadata, response);
|
|
};
|
|
return f;
|
|
}
|
|
|
|
var httpserv;
|
|
function run_test() {
|
|
// disable on Windows for now, because it seems to leak sockets and die.
|
|
// Silly operating system!
|
|
// This is a really nasty way to detect Windows. I wish we could do better.
|
|
if (mozinfo.os == "win") {
|
|
//failing eslint no-empty test
|
|
}
|
|
|
|
httpserv = new HttpServer();
|
|
|
|
for (i = 0; i < contentTypeHeaderList.length; ++i) {
|
|
for (j = 0; j < bodyList.length; ++j) {
|
|
httpserv.registerPathHandler("/" + i + "/" + j, makeHandler(i, j));
|
|
}
|
|
}
|
|
|
|
httpserv.start(-1);
|
|
|
|
doTest(0, 0);
|
|
}
|