PageSourceSearch

https://securitytxt.org/js/genform.js?v=1788777000

js securitytxt.org collected 2026-10-02 02:14:17 UTC 6,825 bytes, 198 lines download raw bytes

1textareaElement = document.getElementById("text-to-copy");
2
3genform.addEventListener("submit", function(event){
4    event.preventDefault();
5
6    // First, validate the form
7    var didValidationFail = false;
8    var contactInputElements = document.getElementById('contact').getElementsByTagName('input');
9
10    for (var i = 0; i < contactInputElements.length; i++) {
11        var inputEl = contactInputElements[i];
12        checkContactValidity(inputEl);
13
14        if (!isContactValid(inputEl)) {
15            inputEl.focus();
16            didValidationFail = true;
17        }
18    }
19
20    if (didValidationFail) {
21        document.getElementById('validation-errors-box').classList.remove('is-hidden');
22        return;
23    } else {
24        document.getElementById('validation-errors-box').classList.add('is-hidden');
25    }
26
27    generate('security.txt', [
28        "contact", "expires", "encryption", "acknowledgments", "preferredLanguages", "canonical", "policy", "hiring", "csaf"
29    ]);
30
31    scrollToStepTwo()
32});
33
34// Convert a date string and time string into a string compliant with the RFC
35function formatDate(dateString, timeString) {
36    // The replace operation is for Safari compatibility: it can only parse YYYY/MM/DD dates and most
37    // other browsers support both YYYY-MM-DD and YYYY/MM/DD.
38    var date = new Date(dateString.replace(/-/g, '/') + ' ' + timeString);
39
40    return date.toISOString();
41}
42
43function generate(filename, field_array){
44    var text = "";
45
46    // Converts camel case like 'abcDefGhi' into
47    // the format 'Abc-Def-Ghi'
48    function camelToHyphen(camelCaseWord) {
49        // introduce the special case for CSAF (short term solution)
50        if (camelCaseWord === "csaf") {return "CSAF"}
51        
52        var components = camelCaseWord.split(/(?=[A-Z])/) // abcDef => [abc, Def]
53
54        return components.map(function (component) {
55          return component[0].toUpperCase() + component.slice(1) // ABC => Abc
56        }).join('-')
57    }
58
59    field_array.forEach(function(e){
60        console.log(e)
61
62        if (e == "expires") {
63            var dateInput = document.getElementById(e).querySelector("[type='date']");
64            var timeInput = document.getElementById(e).querySelector("[type='time']");
65
66            text += camelToHyphen(e) + ": " + formatDate(dateInput.value, timeInput.value) + "\n";
67        } else {
68            var inputs = document.getElementById(e).querySelector(".list-of-inputs")
69            inputs.querySelectorAll("input").forEach(function(child) {
70                if(child.value.length > 0){
71                    text += camelToHyphen(e) + ": " + child.value + "\n";
72                }
73            });
74        }
75    });
76
77    textareaElement.value = text;
78
79    if (document.queryCommandSupported("copy")) {
80        document.getElementById("copy-button").removeAttribute("disabled")
81    }
82}
83
84function addAlternative(button) {
85    var list = button.parentElement.parentElement.parentElement.querySelector(".list-of-inputs")
86
87    var newInput = document.createElement("INPUT")
88    newInput.setAttribute("placeholder", "Another possible alternative")
89    newInput.setAttribute("class", "input")
90
91    var newInputControl = document.createElement("DIV")
92    newInputControl.setAttribute("class", "control is-expanded")
93    newInputControl.appendChild(newInput)
94
95    if (button.parentElement.parentElement.parentElement.id === 'contact') {
96        newInput.addEventListener('change', function () { autoprefixEmail(newInput); });
97
98        var errorMessage = document.createElement('P');
99        newInputControl.appendChild(errorMessage);
100        errorMessage.textContent = 'Each contact field must begin with https:// for web URIs; tel: for telephone numbers; or mailto: for e-mails.';
101
102        var ERROR_MESSAGE_CLASSES = ['is-danger', 'is-hidden', 'help']
103
104        for (var i = 0; i < ERROR_MESSAGE_CLASSES.length; i++) {
105            errorMessage.classList.add(ERROR_MESSAGE_CLASSES[i])
106        }
107    }
108
109    var removeButton = document.createElement("BUTTON")
110    removeButton.setAttribute("type", "button")
111    removeButton.setAttribute("class", "button is-danger")
112    removeButton.textContent = "Remove"
113    
114    var removeButtonControl = document.createElement("DIV")
115    removeButtonControl.setAttribute("class", "control")
116    removeButtonControl.appendChild(removeButton)
117
118    var overallField = document.createElement("LI")
119    overallField.setAttribute("class", "field is-grouped")
120    overallField.appendChild(newInputControl)
121    overallField.appendChild(removeButtonControl)
122
123    removeButton.addEventListener("click", function() {
124        // not using Element.remove() to maintain support
125        // with Internet Explorer
126        overallField.parentNode.removeChild(overallField)
127    })
128
129    list.appendChild(overallField)
130    newInput.focus()
131}
132
133function copyTextarea(){
134    textareaElement.select();
135    document.execCommand("copy");
136
137    window.getSelection().empty();
138    showNotification();
139}
140
141function scrollToStepTwo() {
142  var stepTwo = document.getElementById("step-two")
143
144  if (stepTwo.scrollIntoView) {
145      stepTwo.scrollIntoView({behavior: "smooth", block: "start"})
146  } else {
147      location.hash = "step-two"
148  }
149}
150
151notification = document.getElementById("txt-notification");
152
153function removeNotification(){
154    function hide(){
155        notification.classList.remove("visible");
156        notification.removeEventListener("transitionend ", hide);
157    };
158
159    notification.classList.remove("opaque");
160    notification.addEventListener("transitionend", hide)
161}
162
163function showNotification(){
164    notification.classList.add("visible");
165    setTimeout(function(){
166        // doesn't work when called on the same tick
167        notification.classList.add("opaque");
168    });
169}
170
171function isContactValid(el) {
172    var VALIDATION_REGEX = /^(mailto:|https:\/\/|tel:)/i;
173
174    return VALIDATION_REGEX.test(el.value);
175}
176
177function checkContactValidity(el) {
178    if (isContactValid(el)) {
179        el.parentElement.getElementsByTagName("p")[0].classList.add('is-hidden');
180        el.classList.remove('is-danger');
181    } else {
182        el.parentElement.getElementsByTagName("p")[0].classList.remove('is-hidden')
183        el.classList.add('is-danger');
184    }
185}
186
187function autoprefixEmail(inputEl) {
188    // Add mailto: prefix, e.g. [email protected] -> mailto:[email protected]
189
190    // NOTE: If this regular expression is changed in future, it should always fail if
191    // the user enters some other schema (e.g. https://) so they always have the option of overriding it.
192    // Currently this is achieved by not allowing a colon to appear in the input.
193    if (/^[a-z0-9_+.-]+@[a-z0-9_+.-]+$/i.test(inputEl.value)) {
194        inputEl.value = 'mailto:' + inputEl.value;
195    }
196
197    checkContactValidity(inputEl); // potentially remove validation error if issue resolved
198}

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.