PageSourceSearch

https://www.oss.nl/web/js/form/csrfprotection.js?2026-06-01T10:27:01Z

js oss.nl collected 2026-10-02 08:01:44 UTC 7,159 bytes, 212 lines download raw bytes

1/**
2 * Provide CSRF protection support.
3 */
4 var csrfProtection = csrfProtection || (function () { // Prevents loading this definition more than once
5  /**
6   * Returns an anti-CSRF token, which is a SHA-256 hash of the value of the X-CSRF-Token cookie and a nonce,
7   * postfixed with the used nonce.
8   *
9   * @return An anti-CSRF token.
10   */
11  function getCsrfToken() {
12    const cookies = document.cookie.match("X-CSRF-Token=([^;]*)");
13    var token = (cookies != null ? cookies[1] : '');
14    if (token !== '') {
15      const nonce = Date.now().toString(36).substring(2) + Math.random().toString(36).substring(2, 12).padEnd(10, '0');
16      token = _sha256(token + nonce) + nonce;
17    }
18    return token;
19  }
20
21  /**
22   * Fills all 'csrftoken' inputs with the value of the X-CSRF-Token cookie when their value is empty.
23   *
24   * @param selector a custom document selector to select the inputs to fill.
25   */
26  function setCsrfTokenInputs(selector = "input[name='csrftoken']") {
27    document.querySelectorAll(selector).forEach((input) => {
28      _setCsrfToken(input);
29    });
30  }
31
32  /**
33   * Helper function for addCsrfTokenInputs.
34   * Adds a csrf token input to a single form object.
35   * @param {*} form Form element
36   */
37  function _addCsrfTokenInput(form) {
38    if (form instanceof HTMLElement) {
39      const csrfTokenInput = form.querySelector("input[name='csrftoken']");
40      if (csrfTokenInput) {
41        _setCsrfToken(csrfTokenInput);
42      } else {
43        const input = document.createElement("input");
44        input.type = "hidden";
45        input.name = "csrftoken";
46        input.value = getCsrfToken();
47        form.appendChild(input);
48      }
49    }
50  }
51
52  /**
53   * Adds a 'csrftoken' input to forms with a POST action and fills them with the value of the X-CSRF-Token
54   * cookie. When a form already has a 'csrftoken' input, no new one is created and it is only filled.
55   *
56   * When `selector` is empty, a 'csrftoken' input is added to all forms with a POST action.
57   *
58   * @param selector a custom selector to select the relevant form.
59   */
60  function addCsrfTokenInputs(selectorOrForm = "form[method='post']") {
61    if (typeof selectorOrForm === "string") {
62      document.querySelectorAll(selectorOrForm).forEach((form) => {
63        _addCsrfTokenInput(form);
64      });
65    } else if (selectorOrForm instanceof HTMLElement) {
66      _addCsrfTokenInput(selectorOrForm);
67    }
68  }
69
70  /**
71   * Adds a 'csrftoken' input to a form and fills it with the token argument, or with the value of the
72   * X-CSRF-Token cookie when the token argument is absent.
73   * When the  form already has a 'csrftoken' input, no new one is created and it is only filled.
74   *
75   * @param form The form to which to add the 'csrftoken' input.
76   * @param token The token value (optional).
77   */
78  function addCsrfToken(form, token) {
79    var csrfTokenInput = form.csrftoken;
80    if (csrfTokenInput) {
81      _setCsrfToken(csrfTokenInput, token);
82    } else {
83      var input = document.createElement("input");
84      input.type = "hidden";
85      input.name = "csrftoken";
86      input.value = token ? token : getCsrfToken();
87      form.appendChild(input);
88    }
89  }
90
91  /**
92   * Fills an input with the CSRF token when it does not have a value. The CSRF token is taken from
93   * the token argument when it is not empty, or otherwise from the X-CSRF-Token cookie.
94   *
95   * @param input The input.
96   * @param token The token value (optional).
97   */
98  function _setCsrfToken(input, token) {
99    if (input.value === "") {
100      input.value = token ? token : getCsrfToken();
101    }
102  }
103
104  /**
105   * Calculates the SHA-256 hash of an ASCII string.
106   * This implementation has been provided instead of using the browser native crypto.subtle.digest
107   * function, because the latter is only available in secure contexts and its presence can therefore
108   * not be guaranteed.
109   */
110  function _sha256(text) {
111    function rightRotate(value, amount) {
112      return (value>>>amount) | (value<<(32 - amount));
113    }
114
115    var maxWord = Math.pow(2, 32);
116    var result = ''
117    var words = [];
118    var textBitLength = text['length']*8;
119    var hash = [];
120    var k = [];
121    var primeCounter = 0;
122    var i, j;
123
124    var isComposite = {};
125    for (var candidate = 2; primeCounter < 64;
125 candidate++) {
126      if (!isComposite[candidate]) {
127        for (i = 0; i < 313; i += candidate) {
128          isComposite[i] = candidate;
129        }
130        hash[primeCounter] = (Math.pow(candidate, 0.5)*maxWord) | 0;
131        k[primeCounter++] = (Math.pow(candidate, 1/3)*maxWord) | 0;
132      }
133    }
134
135    text += '\x80'
136    while (text['length']%64 - 56){
137      text += '\x00'
138    }
139
140    for (i = 0; i < text['length']; i++) {
141      j = text.charCodeAt(i);
142      if (j>>8) {
143		return; // ASCII check: only accept characters in range 0-255
144	  }
145      words[i>>2] |= j << ((3 - i)%4)*8;
146    }
147    words[words['length']] = ((textBitLength/maxWord)|0);
148    words[words['length']] = (textBitLength)
149
150    for (j = 0; j < words['length'];) {
151      var w = words.slice(j, j += 16);
152      var oldHash = hash;
153      hash = hash.slice(0, 8);
154
155      for (i = 0; i < 64; i++) {
156        var w15 = w[i - 15], w2 = w[i - 2];
157        var a = hash[0], e = hash[4];
158        var temp1 = hash[7]
159          + (rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25))
160          + ((e&hash[5])^((~e)&hash[6])) // ch
161          + k[i]
162          + (w[i] = (i < 16) ? w[i] : (
163              w[i - 16]
164              + (rightRotate(w15, 7) ^ rightRotate(w15, 18) ^ (w15>>>3))
165              + w[i - 7]
166              + (rightRotate(w2, 17) ^ rightRotate(w2, 19) ^ (w2>>>10))
167            ) | 0
168          );
169        var temp2 = (rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22))
170          + ((a&hash[1])^(a&hash[2])^(hash[1]&hash[2])); // maj
171
172        hash = [(temp1 + temp2)|0].concat(hash);
173        hash[4] = (hash[4] + temp1)|0;
174      }
175
176      for (i = 0; i < 8; i++) {
177        hash[i] = (hash[i] + oldHash[i])|0;
178      }
179    }
180
181    for (i = 0; i < 8; i++) {
182      for (j = 3; j + 1; j--) {
183        var b = (hash[i]>>(j*8))&255;
184        result += ((b < 16) ? 0 : '') + b.toString(16);
185      }
186    }
187    return result;
188  }
189
190  // If the addOnLoad attribute has been added to the script tag for this file
191  // then call the addCsrfTokenInputs function automatically when the page has loaded.
192  // This is done either by registering the addCsrfTokenInputs function with the addOnLoadListener
193  // function when it is present (it is defined in the global_edit-javascript_util template) and we
194  // are not in an iframe, or by registering it with the DOMContentLoaded event handler.
195  if (document.currentScript.getAttribute("addonload") === "true") {
196    if (typeof addOnLoadListener === "function" && window.location === window.parent.location) {
197      addOnLoadListener(addCsrfTokenInputs);
198    } else {
199      document.addEventListener("DOMContentLoaded", function() {
200        addCsrfTokenInputs();
201      });
202    }
203  }
204
205  // Public methods
206  return {
207    getCsrfToken: getCsrfToken,
208    setCsrfTokenInputs: setCsrfTokenInputs,
209    addCsrfTokenInputs: addCsrfTokenInputs,
210    addCsrfToken: addCsrfToken
211  }
212})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.