netwerk/test/unit/test_duplicate_headers.js

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

michael@0 1 /*
michael@0 2 * Tests bugs 597706, 655389: prevent duplicate headers with differing values
michael@0 3 * for some headers like Content-Length, Location, etc.
michael@0 4 */
michael@0 5
michael@0 6 ////////////////////////////////////////////////////////////////////////////////
michael@0 7 // Test infrastructure
michael@0 8
michael@0 9 Cu.import("resource://testing-common/httpd.js");
michael@0 10
michael@0 11 XPCOMUtils.defineLazyGetter(this, "URL", function() {
michael@0 12 return "http://localhost:" + httpserver.identity.primaryPort;
michael@0 13 });
michael@0 14
michael@0 15 var httpserver = new HttpServer();
michael@0 16 var index = 0;
michael@0 17 var test_flags = new Array();
michael@0 18 var testPathBase = "/dupe_hdrs";
michael@0 19
michael@0 20 function run_test()
michael@0 21 {
michael@0 22 httpserver.start(-1);
michael@0 23
michael@0 24 do_test_pending();
michael@0 25 run_test_number(1);
michael@0 26 }
michael@0 27
michael@0 28 function run_test_number(num)
michael@0 29 {
michael@0 30 testPath = testPathBase + num;
michael@0 31 httpserver.registerPathHandler(testPath, eval("handler" + num));
michael@0 32
michael@0 33 var channel = setupChannel(testPath);
michael@0 34 flags = test_flags[num]; // OK if flags undefined for test
michael@0 35 channel.asyncOpen(new ChannelListener(eval("completeTest" + num),
michael@0 36 channel, flags), null);
michael@0 37 }
michael@0 38
michael@0 39 function setupChannel(url)
michael@0 40 {
michael@0 41 var ios = Components.classes["@mozilla.org/network/io-service;1"].
michael@0 42 getService(Ci.nsIIOService);
michael@0 43 var chan = ios.newChannel(URL + url, "", null);
michael@0 44 var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel);
michael@0 45 return httpChan;
michael@0 46 }
michael@0 47
michael@0 48 function endTests()
michael@0 49 {
michael@0 50 httpserver.stop(do_test_finished);
michael@0 51 }
michael@0 52
michael@0 53 ////////////////////////////////////////////////////////////////////////////////
michael@0 54 // Test 1: FAIL because of conflicting Content-Length headers
michael@0 55 test_flags[1] = CL_EXPECT_FAILURE;
michael@0 56
michael@0 57 function handler1(metadata, response)
michael@0 58 {
michael@0 59 var body = "012345678901234567890123456789";
michael@0 60 // Comrades! We must seize power from the petty-bourgeois running dogs of
michael@0 61 // httpd.js in order to reply with multiple instances of the same header!
michael@0 62 response.seizePower();
michael@0 63 response.write("HTTP/1.0 200 OK\r\n");
michael@0 64 response.write("Content-Type: text/plain\r\n");
michael@0 65 response.write("Content-Length: 30\r\n");
michael@0 66 response.write("Content-Length: 20\r\n");
michael@0 67 response.write("\r\n");
michael@0 68 response.write(body);
michael@0 69 response.finish();
michael@0 70 }
michael@0 71
michael@0 72
michael@0 73 function completeTest1(request, data, ctx)
michael@0 74 {
michael@0 75 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 76
michael@0 77 run_test_number(2);
michael@0 78 }
michael@0 79
michael@0 80 ////////////////////////////////////////////////////////////////////////////////
michael@0 81 // Test 2: OK to have duplicate same Content-Length headers
michael@0 82
michael@0 83 function handler2(metadata, response)
michael@0 84 {
michael@0 85 var body = "012345678901234567890123456789";
michael@0 86 response.seizePower();
michael@0 87 response.write("HTTP/1.0 200 OK\r\n");
michael@0 88 response.write("Content-Type: text/plain\r\n");
michael@0 89 response.write("Content-Length: 30\r\n");
michael@0 90 response.write("Content-Length: 30\r\n");
michael@0 91 response.write("\r\n");
michael@0 92 response.write(body);
michael@0 93 response.finish();
michael@0 94 }
michael@0 95
michael@0 96 function completeTest2(request, data, ctx)
michael@0 97 {
michael@0 98 do_check_eq(request.status, 0);
michael@0 99 run_test_number(3);
michael@0 100 }
michael@0 101
michael@0 102 ////////////////////////////////////////////////////////////////////////////////
michael@0 103 // Test 3: FAIL: 2nd Content-length is blank
michael@0 104 test_flags[3] = CL_EXPECT_FAILURE;
michael@0 105
michael@0 106 function handler3(metadata, response)
michael@0 107 {
michael@0 108 var body = "012345678901234567890123456789";
michael@0 109 response.seizePower();
michael@0 110 response.write("HTTP/1.0 200 OK\r\n");
michael@0 111 response.write("Content-Type: text/plain\r\n");
michael@0 112 response.write("Content-Length: 30\r\n");
michael@0 113 response.write("Content-Length:\r\n");
michael@0 114 response.write("\r\n");
michael@0 115 response.write(body);
michael@0 116 response.finish();
michael@0 117 }
michael@0 118
michael@0 119 function completeTest3(request, data, ctx)
michael@0 120 {
michael@0 121 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 122
michael@0 123 run_test_number(4);
michael@0 124 }
michael@0 125
michael@0 126 ////////////////////////////////////////////////////////////////////////////////
michael@0 127 // Test 4: ensure that blank C-len header doesn't allow attacker to reset Clen,
michael@0 128 // then insert CRLF attack
michael@0 129 test_flags[4] = CL_EXPECT_FAILURE;
michael@0 130
michael@0 131 function handler4(metadata, response)
michael@0 132 {
michael@0 133 var body = "012345678901234567890123456789";
michael@0 134
michael@0 135 response.seizePower();
michael@0 136 response.write("HTTP/1.0 200 OK\r\n");
michael@0 137 response.write("Content-Type: text/plain\r\n");
michael@0 138 response.write("Content-Length: 30\r\n");
michael@0 139
michael@0 140 // Bad Mr Hacker! Bad!
michael@0 141 var evilBody = "We are the Evil bytes, Evil bytes, Evil bytes!";
michael@0 142 response.write("Content-Length:\r\n");
michael@0 143 response.write("Content-Length: %s\r\n\r\n%s" % (evilBody.length, evilBody));
michael@0 144 response.write("\r\n");
michael@0 145 response.write(body);
michael@0 146 response.finish();
michael@0 147 }
michael@0 148
michael@0 149 function completeTest4(request, data, ctx)
michael@0 150 {
michael@0 151 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 152
michael@0 153 run_test_number(5);
michael@0 154 }
michael@0 155
michael@0 156
michael@0 157 ////////////////////////////////////////////////////////////////////////////////
michael@0 158 // Test 5: ensure that we take 1st instance of duplicate, nonmerged headers that
michael@0 159 // are permitted : (ex: Referrer)
michael@0 160
michael@0 161 function handler5(metadata, response)
michael@0 162 {
michael@0 163 var body = "012345678901234567890123456789";
michael@0 164 response.seizePower();
michael@0 165 response.write("HTTP/1.0 200 OK\r\n");
michael@0 166 response.write("Content-Type: text/plain\r\n");
michael@0 167 response.write("Content-Length: 30\r\n");
michael@0 168 response.write("Referer: naive.org\r\n");
michael@0 169 response.write("Referer: evil.net\r\n");
michael@0 170 response.write("\r\n");
michael@0 171 response.write(body);
michael@0 172 response.finish();
michael@0 173 }
michael@0 174
michael@0 175 function completeTest5(request, data, ctx)
michael@0 176 {
michael@0 177 try {
michael@0 178 referer = request.getResponseHeader("Referer");
michael@0 179 do_check_eq(referer, "naive.org");
michael@0 180 } catch (ex) {
michael@0 181 do_throw("Referer header should be present");
michael@0 182 }
michael@0 183
michael@0 184 run_test_number(6);
michael@0 185 }
michael@0 186
michael@0 187 ////////////////////////////////////////////////////////////////////////////////
michael@0 188 // Test 5: FAIL if multiple, different Location: headers present
michael@0 189 // - needed to prevent CRLF injection attacks
michael@0 190 test_flags[6] = CL_EXPECT_FAILURE;
michael@0 191
michael@0 192 function handler6(metadata, response)
michael@0 193 {
michael@0 194 var body = "012345678901234567890123456789";
michael@0 195 response.seizePower();
michael@0 196 response.write("HTTP/1.0 301 Moved\r\n");
michael@0 197 response.write("Content-Type: text/plain\r\n");
michael@0 198 response.write("Content-Length: 30\r\n");
michael@0 199 response.write("Location: " + URL + "/content\r\n");
michael@0 200 response.write("Location: http://www.microsoft.com/\r\n");
michael@0 201 response.write("Connection: close\r\n");
michael@0 202 response.write("\r\n");
michael@0 203 response.write(body);
michael@0 204 response.finish();
michael@0 205 }
michael@0 206
michael@0 207 function completeTest6(request, data, ctx)
michael@0 208 {
michael@0 209 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 210
michael@0 211 // run_test_number(7); // Test 7 leaking under e10s: unrelated bug?
michael@0 212 run_test_number(8);
michael@0 213 }
michael@0 214
michael@0 215 ////////////////////////////////////////////////////////////////////////////////
michael@0 216 // Test 7: OK to have multiple Location: headers with same value
michael@0 217
michael@0 218 function handler7(metadata, response)
michael@0 219 {
michael@0 220 var body = "012345678901234567890123456789";
michael@0 221 response.seizePower();
michael@0 222 response.write("HTTP/1.0 301 Moved\r\n");
michael@0 223 response.write("Content-Type: text/plain\r\n");
michael@0 224 response.write("Content-Length: 30\r\n");
michael@0 225 // redirect to previous test handler that completes OK: test 5
michael@0 226 response.write("Location: " + URL + testPathBase + "5\r\n");
michael@0 227 response.write("Location: " + URL + testPathBase + "5\r\n");
michael@0 228 response.write("Connection: close\r\n");
michael@0 229 response.write("\r\n");
michael@0 230 response.write(body);
michael@0 231 response.finish();
michael@0 232 }
michael@0 233
michael@0 234 function completeTest7(request, data, ctx)
michael@0 235 {
michael@0 236 // for some reason need this here
michael@0 237 request.QueryInterface(Components.interfaces.nsIHttpChannel);
michael@0 238
michael@0 239 try {
michael@0 240 referer = request.getResponseHeader("Referer");
michael@0 241 do_check_eq(referer, "naive.org");
michael@0 242 } catch (ex) {
michael@0 243 do_throw("Referer header should be present");
michael@0 244 }
michael@0 245
michael@0 246 run_test_number(8);
michael@0 247 }
michael@0 248
michael@0 249 ////////////////////////////////////////////////////////////////////////////////
michael@0 250 // FAIL if 2nd Location: headers blank
michael@0 251 test_flags[8] = CL_EXPECT_FAILURE;
michael@0 252
michael@0 253 function handler8(metadata, response)
michael@0 254 {
michael@0 255 var body = "012345678901234567890123456789";
michael@0 256 response.seizePower();
michael@0 257 response.write("HTTP/1.0 301 Moved\r\n");
michael@0 258 response.write("Content-Type: text/plain\r\n");
michael@0 259 response.write("Content-Length: 30\r\n");
michael@0 260 // redirect to previous test handler that completes OK: test 4
michael@0 261 response.write("Location: " + URL + testPathBase + "4\r\n");
michael@0 262 response.write("Location:\r\n");
michael@0 263 response.write("Connection: close\r\n");
michael@0 264 response.write("\r\n");
michael@0 265 response.write(body);
michael@0 266 response.finish();
michael@0 267 }
michael@0 268
michael@0 269 function completeTest8(request, data, ctx)
michael@0 270 {
michael@0 271 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 272
michael@0 273 run_test_number(9);
michael@0 274 }
michael@0 275
michael@0 276 ////////////////////////////////////////////////////////////////////////////////
michael@0 277 // Test 9: ensure that blank Location header doesn't allow attacker to reset,
michael@0 278 // then insert an evil one
michael@0 279 test_flags[9] = CL_EXPECT_FAILURE;
michael@0 280
michael@0 281 function handler9(metadata, response)
michael@0 282 {
michael@0 283 var body = "012345678901234567890123456789";
michael@0 284 response.seizePower();
michael@0 285 response.write("HTTP/1.0 301 Moved\r\n");
michael@0 286 response.write("Content-Type: text/plain\r\n");
michael@0 287 response.write("Content-Length: 30\r\n");
michael@0 288 // redirect to previous test handler that completes OK: test 2
michael@0 289 response.write("Location: " + URL + testPathBase + "2\r\n");
michael@0 290 response.write("Location:\r\n");
michael@0 291 // redirect to previous test handler that completes OK: test 4
michael@0 292 response.write("Location: " + URL + testPathBase + "4\r\n");
michael@0 293 response.write("Connection: close\r\n");
michael@0 294 response.write("\r\n");
michael@0 295 response.write(body);
michael@0 296 response.finish();
michael@0 297 }
michael@0 298
michael@0 299 function completeTest9(request, data, ctx)
michael@0 300 {
michael@0 301 // All redirection should fail:
michael@0 302 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 303
michael@0 304 run_test_number(10);
michael@0 305 }
michael@0 306
michael@0 307 ////////////////////////////////////////////////////////////////////////////////
michael@0 308 // Test 10: FAIL: if conflicting values for Content-Dispo
michael@0 309 test_flags[10] = CL_EXPECT_FAILURE;
michael@0 310
michael@0 311 function handler10(metadata, response)
michael@0 312 {
michael@0 313 var body = "012345678901234567890123456789";
michael@0 314 response.seizePower();
michael@0 315 response.write("HTTP/1.0 200 OK\r\n");
michael@0 316 response.write("Content-Type: text/plain\r\n");
michael@0 317 response.write("Content-Length: 30\r\n");
michael@0 318 response.write("Content-Disposition: attachment; filename=foo\r\n");
michael@0 319 response.write("Content-Disposition: attachment; filename=bar\r\n");
michael@0 320 response.write("Content-Disposition: attachment; filename=baz\r\n");
michael@0 321 response.write("\r\n");
michael@0 322 response.write(body);
michael@0 323 response.finish();
michael@0 324 }
michael@0 325
michael@0 326
michael@0 327 function completeTest10(request, data, ctx)
michael@0 328 {
michael@0 329 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 330
michael@0 331 run_test_number(11);
michael@0 332 }
michael@0 333
michael@0 334 ////////////////////////////////////////////////////////////////////////////////
michael@0 335 // Test 11: OK to have duplicate same Content-Disposition headers
michael@0 336
michael@0 337 function handler11(metadata, response)
michael@0 338 {
michael@0 339 var body = "012345678901234567890123456789";
michael@0 340 response.seizePower();
michael@0 341 response.write("HTTP/1.0 200 OK\r\n");
michael@0 342 response.write("Content-Type: text/plain\r\n");
michael@0 343 response.write("Content-Length: 30\r\n");
michael@0 344 response.write("Content-Disposition: attachment; filename=foo\r\n");
michael@0 345 response.write("Content-Disposition: attachment; filename=foo\r\n");
michael@0 346 response.write("\r\n");
michael@0 347 response.write(body);
michael@0 348 response.finish();
michael@0 349 }
michael@0 350
michael@0 351 function completeTest11(request, data, ctx)
michael@0 352 {
michael@0 353 do_check_eq(request.status, 0);
michael@0 354
michael@0 355 try {
michael@0 356 var chan = request.QueryInterface(Ci.nsIChannel);
michael@0 357 do_check_eq(chan.contentDisposition, chan.DISPOSITION_ATTACHMENT);
michael@0 358 do_check_eq(chan.contentDispositionFilename, "foo");
michael@0 359 do_check_eq(chan.contentDispositionHeader, "attachment; filename=foo");
michael@0 360 } catch (ex) {
michael@0 361 do_throw("error parsing Content-Disposition: " + ex);
michael@0 362 }
michael@0 363
michael@0 364 run_test_number(12);
michael@0 365 }
michael@0 366
michael@0 367 ////////////////////////////////////////////////////////////////////////////////
michael@0 368 // Bug 716801 OK for Location: header to be blank
michael@0 369
michael@0 370 function handler12(metadata, response)
michael@0 371 {
michael@0 372 var body = "012345678901234567890123456789";
michael@0 373 response.seizePower();
michael@0 374 response.write("HTTP/1.0 200 OK\r\n");
michael@0 375 response.write("Content-Type: text/plain\r\n");
michael@0 376 response.write("Content-Length: 30\r\n");
michael@0 377 response.write("Location:\r\n");
michael@0 378 response.write("Connection: close\r\n");
michael@0 379 response.write("\r\n");
michael@0 380 response.write(body);
michael@0 381 response.finish();
michael@0 382 }
michael@0 383
michael@0 384 function completeTest12(request, data, ctx)
michael@0 385 {
michael@0 386 do_check_eq(request.status, Components.results.NS_OK);
michael@0 387 do_check_eq(30, data.length);
michael@0 388
michael@0 389 run_test_number(13);
michael@0 390 }
michael@0 391
michael@0 392 ////////////////////////////////////////////////////////////////////////////////
michael@0 393 // Negative content length is ok
michael@0 394 test_flags[13] = CL_ALLOW_UNKNOWN_CL;
michael@0 395
michael@0 396 function handler13(metadata, response)
michael@0 397 {
michael@0 398 var body = "012345678901234567890123456789";
michael@0 399 response.seizePower();
michael@0 400 response.write("HTTP/1.0 200 OK\r\n");
michael@0 401 response.write("Content-Type: text/plain\r\n");
michael@0 402 response.write("Content-Length: -1\r\n");
michael@0 403 response.write("Connection: close\r\n");
michael@0 404 response.write("\r\n");
michael@0 405 response.write(body);
michael@0 406 response.finish();
michael@0 407 }
michael@0 408
michael@0 409 function completeTest13(request, data, ctx)
michael@0 410 {
michael@0 411 do_check_eq(request.status, Components.results.NS_OK);
michael@0 412 do_check_eq(30, data.length);
michael@0 413
michael@0 414 run_test_number(14);
michael@0 415 }
michael@0 416
michael@0 417 ////////////////////////////////////////////////////////////////////////////////
michael@0 418 // leading negative content length is not ok if paired with positive one
michael@0 419
michael@0 420 test_flags[14] = CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL;
michael@0 421
michael@0 422 function handler14(metadata, response)
michael@0 423 {
michael@0 424 var body = "012345678901234567890123456789";
michael@0 425 response.seizePower();
michael@0 426 response.write("HTTP/1.0 200 OK\r\n");
michael@0 427 response.write("Content-Type: text/plain\r\n");
michael@0 428 response.write("Content-Length: -1\r\n");
michael@0 429 response.write("Content-Length: 30\r\n");
michael@0 430 response.write("Connection: close\r\n");
michael@0 431 response.write("\r\n");
michael@0 432 response.write(body);
michael@0 433 response.finish();
michael@0 434 }
michael@0 435
michael@0 436 function completeTest14(request, data, ctx)
michael@0 437 {
michael@0 438 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 439
michael@0 440 run_test_number(15);
michael@0 441 }
michael@0 442
michael@0 443 ////////////////////////////////////////////////////////////////////////////////
michael@0 444 // trailing negative content length is not ok if paired with positive one
michael@0 445
michael@0 446 test_flags[15] = CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL;
michael@0 447
michael@0 448 function handler15(metadata, response)
michael@0 449 {
michael@0 450 var body = "012345678901234567890123456789";
michael@0 451 response.seizePower();
michael@0 452 response.write("HTTP/1.0 200 OK\r\n");
michael@0 453 response.write("Content-Type: text/plain\r\n");
michael@0 454 response.write("Content-Length: 30\r\n");
michael@0 455 response.write("Content-Length: -1\r\n");
michael@0 456 response.write("Connection: close\r\n");
michael@0 457 response.write("\r\n");
michael@0 458 response.write(body);
michael@0 459 response.finish();
michael@0 460 }
michael@0 461
michael@0 462 function completeTest15(request, data, ctx)
michael@0 463 {
michael@0 464 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 465
michael@0 466 run_test_number(16);
michael@0 467 }
michael@0 468
michael@0 469 ////////////////////////////////////////////////////////////////////////////////
michael@0 470 // empty content length is ok
michael@0 471 test_flags[16] = CL_ALLOW_UNKNOWN_CL;
michael@0 472 reran16 = false;
michael@0 473
michael@0 474 function handler16(metadata, response)
michael@0 475 {
michael@0 476 var body = "012345678901234567890123456789";
michael@0 477 response.seizePower();
michael@0 478 response.write("HTTP/1.0 200 OK\r\n");
michael@0 479 response.write("Content-Type: text/plain\r\n");
michael@0 480 response.write("Content-Length: \r\n");
michael@0 481 response.write("Cache-Control: max-age=600\r\n");
michael@0 482 response.write("Connection: close\r\n");
michael@0 483 response.write("\r\n");
michael@0 484 response.write(body);
michael@0 485 response.finish();
michael@0 486 }
michael@0 487
michael@0 488 function completeTest16(request, data, ctx)
michael@0 489 {
michael@0 490 do_check_eq(request.status, Components.results.NS_OK);
michael@0 491 do_check_eq(30, data.length);
michael@0 492
michael@0 493 if (!reran16) {
michael@0 494 reran16 = true;
michael@0 495 run_test_number(16);
michael@0 496 }
michael@0 497 else {
michael@0 498 run_test_number(17);
michael@0 499 }
michael@0 500 }
michael@0 501
michael@0 502 ////////////////////////////////////////////////////////////////////////////////
michael@0 503 // empty content length paired with non empty is not ok
michael@0 504 test_flags[17] = CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL;
michael@0 505
michael@0 506 function handler17(metadata, response)
michael@0 507 {
michael@0 508 var body = "012345678901234567890123456789";
michael@0 509 response.seizePower();
michael@0 510 response.write("HTTP/1.0 200 OK\r\n");
michael@0 511 response.write("Content-Type: text/plain\r\n");
michael@0 512 response.write("Content-Length: \r\n");
michael@0 513 response.write("Content-Length: 30\r\n");
michael@0 514 response.write("Connection: close\r\n");
michael@0 515 response.write("\r\n");
michael@0 516 response.write(body);
michael@0 517 response.finish();
michael@0 518 }
michael@0 519
michael@0 520 function completeTest17(request, data, ctx)
michael@0 521 {
michael@0 522 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 523
michael@0 524 run_test_number(18);
michael@0 525 }
michael@0 526
michael@0 527 ////////////////////////////////////////////////////////////////////////////////
michael@0 528 // alpha content-length is just like -1
michael@0 529 test_flags[18] = CL_ALLOW_UNKNOWN_CL;
michael@0 530
michael@0 531 function handler18(metadata, response)
michael@0 532 {
michael@0 533 var body = "012345678901234567890123456789";
michael@0 534 response.seizePower();
michael@0 535 response.write("HTTP/1.0 200 OK\r\n");
michael@0 536 response.write("Content-Type: text/plain\r\n");
michael@0 537 response.write("Content-Length: seventeen\r\n");
michael@0 538 response.write("Connection: close\r\n");
michael@0 539 response.write("\r\n");
michael@0 540 response.write(body);
michael@0 541 response.finish();
michael@0 542 }
michael@0 543
michael@0 544 function completeTest18(request, data, ctx)
michael@0 545 {
michael@0 546 do_check_eq(request.status, Components.results.NS_OK);
michael@0 547 do_check_eq(30, data.length);
michael@0 548
michael@0 549 run_test_number(19);
michael@0 550 }
michael@0 551
michael@0 552 ////////////////////////////////////////////////////////////////////////////////
michael@0 553 // semi-colons are ok too in the content-length
michael@0 554 test_flags[19] = CL_ALLOW_UNKNOWN_CL;
michael@0 555
michael@0 556 function handler19(metadata, response)
michael@0 557 {
michael@0 558 var body = "012345678901234567890123456789";
michael@0 559 response.seizePower();
michael@0 560 response.write("HTTP/1.0 200 OK\r\n");
michael@0 561 response.write("Content-Type: text/plain\r\n");
michael@0 562 response.write("Content-Length: 30;\r\n");
michael@0 563 response.write("Connection: close\r\n");
michael@0 564 response.write("\r\n");
michael@0 565 response.write(body);
michael@0 566 response.finish();
michael@0 567 }
michael@0 568
michael@0 569 function completeTest19(request, data, ctx)
michael@0 570 {
michael@0 571 do_check_eq(request.status, Components.results.NS_OK);
michael@0 572 do_check_eq(30, data.length);
michael@0 573
michael@0 574 run_test_number(20);
michael@0 575 }
michael@0 576
michael@0 577 ////////////////////////////////////////////////////////////////////////////////
michael@0 578 // FAIL if 1st Location: header is blank, followed by non-blank
michael@0 579 test_flags[20] = CL_EXPECT_FAILURE;
michael@0 580
michael@0 581 function handler20(metadata, response)
michael@0 582 {
michael@0 583 var body = "012345678901234567890123456789";
michael@0 584 response.seizePower();
michael@0 585 response.write("HTTP/1.0 301 Moved\r\n");
michael@0 586 response.write("Content-Type: text/plain\r\n");
michael@0 587 response.write("Content-Length: 30\r\n");
michael@0 588 // redirect to previous test handler that completes OK: test 4
michael@0 589 response.write("Location:\r\n");
michael@0 590 response.write("Location: " + URL + testPathBase + "4\r\n");
michael@0 591 response.write("Connection: close\r\n");
michael@0 592 response.write("\r\n");
michael@0 593 response.write(body);
michael@0 594 response.finish();
michael@0 595 }
michael@0 596
michael@0 597 function completeTest20(request, data, ctx)
michael@0 598 {
michael@0 599 do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT);
michael@0 600
michael@0 601 endTests();
michael@0 602 }
michael@0 603

mercurial