tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

send-file-formdata-helper.js (3466B)


      1 "use strict";
      2 
      3 const kTestChars = "ABC~‾¥≈¤・・•∙·☼★星🌟星★☼·∙•・・¤≈¥‾~XYZ";
      4 
      5 // formDataPostFileUploadTest - verifies multipart upload structure and
      6 // numeric character reference replacement for filenames, field names,
      7 // and field values using FormData and fetch().
      8 //
      9 // Uses /fetch/api/resources/echo-content.py to echo the upload
     10 // POST (unlike in send-file-form-helper.js, here we expect all
     11 // multipart/form-data request bodies to be UTF-8, so we don't need to
     12 // escape controls and non-ASCII bytes).
     13 //
     14 // Fields in the parameter object:
     15 //
     16 // - fileNameSource: purely explanatory and gives a clue about which
     17 //   character encoding is the source for the non-7-bit-ASCII parts of
     18 //   the fileBaseName, or Unicode if no smaller-than-Unicode source
     19 //   contains all the characters. Used in the test name.
     20 // - fileBaseName: the not-necessarily-just-7-bit-ASCII file basename
     21 //   used for the constructed test file. Used in the test name.
     22 const formDataPostFileUploadTest = ({
     23  fileNameSource,
     24  fileBaseName,
     25 }) => {
     26  promise_test(async (testCase) => {
     27    const formData = new FormData();
     28    let file = new Blob([kTestChars], { type: "text/plain" });
     29    try {
     30      // Switch to File in browsers that allow this
     31      file = new File([file], fileBaseName, { type: file.type });
     32    } catch (ignoredException) {
     33    }
     34 
     35    // Used to verify that the browser agrees with the test about
     36    // field value replacement and encoding independently of file system
     37    // idiosyncracies.
     38    formData.append("filename", fileBaseName);
     39 
     40    // Same, but with name and value reversed to ensure field names
     41    // get the same treatment.
     42    formData.append(fileBaseName, "filename");
     43 
     44    formData.append("file", file, fileBaseName);
     45 
     46    const formDataText = await (await fetch(
     47      `/fetch/api/resources/echo-content.py`,
     48      {
     49        method: "POST",
     50        body: formData,
     51      },
     52    )).text();
     53    const formDataLines = formDataText.split("\r\n");
     54    if (formDataLines.length && !formDataLines[formDataLines.length - 1]) {
     55      --formDataLines.length;
     56    }
     57    assert_greater_than(
     58      formDataLines.length,
     59      2,
     60      `${fileBaseName}: multipart form data must have at least 3 lines: ${
     61        JSON.stringify(formDataText)
     62      }`,
     63    );
     64    const boundary = formDataLines[0];
     65    assert_equals(
     66      formDataLines[formDataLines.length - 1],
     67      boundary + "--",
     68      `${fileBaseName}: multipart form data must end with ${boundary}--: ${
     69        JSON.stringify(formDataText)
     70      }`,
     71    );
     72 
     73    const asValue = fileBaseName.replace(/\r\n?|\n/g, "\r\n");
     74    const asName = asValue.replace(/[\r\n"]/g, encodeURIComponent);
     75    const asFilename = fileBaseName.replace(/[\r\n"]/g, encodeURIComponent);
     76    const expectedText = [
     77      boundary,
     78      'Content-Disposition: form-data; name="filename"',
     79      "",
     80      asValue,
     81      boundary,
     82      `Content-Disposition: form-data; name="${asName}"`,
     83      "",
     84      "filename",
     85      boundary,
     86      `Content-Disposition: form-data; name="file"; ` +
     87      `filename="${asFilename}"`,
     88      "Content-Type: text/plain",
     89      "",
     90      kTestChars,
     91      boundary + "--",
     92    ].join("\r\n");
     93 
     94    assert_true(
     95      formDataText.startsWith(expectedText),
     96      `Unexpected multipart-shaped form data received:\n${formDataText}\nExpected:\n${expectedText}`,
     97    );
     98  }, `Upload ${fileBaseName} (${fileNameSource}) in fetch with FormData`);
     99 };