75c5426fd3fbdfef79e190054ce87b91e37cee72
[Packages/TYPO3.CMS.git] / typo3 / sysext / rsaauth / Resources / Public / JavaScript / RsaEncryption.js
1 (function() {
2 'use strict';
3
4 /**
5 * Prevent calling the function multiple times
6 */
7 var documentReadyFunctionCalled = false;
8
9 var rsaEncryption = function(form) {
10
11 /**
12 * Submitted form element
13 */
14 this.form = form;
15
16 /**
17 * Store found fields in an array
18 */
19 this.fields = [];
20
21 /**
22 * XMLHttpRequest
23 */
24 this.xhr = null;
25
26 /**
27 * Remember if we fetched the RSA key already
28 */
29 this.fetchedRsaKey = false;
30
31 /**
32 * Fetches a new public key by Ajax and encrypts the password for transmission
33 */
34 this.handleFormSubmitRequest = function(event) {
35 var rsaEncryption = this.rsaEncryption || event.srcElement.rsaEncryption;
36 if (!rsaEncryption) {
37 return;
38 }
39 if (rsaEncryption.fields.length && !rsaEncryption.fetchedRsaKey) {
40 rsaEncryption.fetchedRsaKey = true;
41 rsaEncryption.ajaxCall(
42 TYPO3RsaEncryptionPublicKeyUrl, // defined in PHP
43 rsaEncryption,
44 function(response) {
45 rsaEncryption.handlePublicKeyResponse(response, rsaEncryption);
46 }
47 );
48
49 if (event.preventDefault) {
50 event.preventDefault();
51 } else if (window.event) {
52 window.event.returnValue = false;
53 }
54 }
55 };
56
57 this.ajaxCall = function(url, rsaEncryption, callback) {
58 // Abort previous request, only last request/generated key pair can be used
59 if (rsaEncryption.xhr) {
60 rsaEncryption.xhr.abort();
61 }
62
63 if (typeof XMLHttpRequest !== 'undefined') {
64 rsaEncryption.xhr = new XMLHttpRequest();
65 } else {
66 var versions = [
67 'MSXML2.XmlHttp.5.0',
68 'MSXML2.XmlHttp.4.0',
69 'MSXML2.XmlHttp.3.0',
70 'MSXML2.XmlHttp.2.0',
71 'Microsoft.XmlHttp'
72 ];
73 for (var i = 0, count = versions.length; i < count; i++) {
74 try {
75 rsaEncryption.xhr = new ActiveXObject(versions[i]);
76 break;
77 } catch (e) {
78 }
79 }
80 }
81
82 rsaEncryption.xhr.onreadystatechange = function() {
83 // Only process requests that are ready and have a status (not aborted)
84 if (rsaEncryption.xhr.readyState === 4 && rsaEncryption.xhr.status > 0) {
85 callback(rsaEncryption.xhr);
86 }
87 };
88
89 rsaEncryption.xhr.open('GET', url, true);
90 rsaEncryption.xhr.send('');
91 };
92
93 this.handlePublicKeyResponse = function(response, rsaEncryption) {
94 var publicKey = response.responseText.split(':');
95 if (!publicKey[0] || !publicKey[1]) {
96 alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.');
97 return false;
98 }
99
100 var rsa = new RSAKey();
101 rsa.setPublic(publicKey[0], publicKey[1]);
102 for (var i = rsaEncryption.fields.length; i--;) {
103 var field = rsaEncryption.fields[i];
104 var encryptedValue = rsa.encrypt(field.value);
105 // Replace value with encrypted value
106 field.value = 'rsa:' + hex2b64(encryptedValue);
107 }
108
109 // Submit the form again but now with encrypted values
110 var form = document.createElement('form');
111 if (form.submit.call) {
112 form.submit.call(rsaEncryption.form);
113 } else {
114 var fields = rsaEncryption.form.getElementsByTagName('*');
115 for (var j = fields.length; j--;) {
116 var submitField = fields[j];
117 if (submitField.nodeName.toLowerCase() === 'input' && submitField.type === "submit") {
118 submitField.click();
119 }
120 }
121 }
122 };
123 };
124
125 /**
126 * Bind submit handler to all forms with input:data-rsa-encryption fields
127 */
128 function ready() {
129 if (documentReadyFunctionCalled) {
130 return;
131 }
132
133 documentReadyFunctionCalled = true;
134 rng_seed_time();
135 var forms = document.getElementsByTagName('form');
136 for (var i = forms.length; i--;) {
137 var form = forms[i];
138 var fields = form.getElementsByTagName('*');
139 for (var j = fields.length; j--;) {
140 var field = fields[j];
141 if (field.nodeName.toLowerCase() === 'input') {
142 var dataAttribute = field.getAttribute('data-rsa-encryption');
143 if (dataAttribute || dataAttribute === '' && field.outerHTML.match(/ data-rsa-encryption=""/)) {
144 if (!form.rsaEncryption) {
145 form.rsaEncryption = new rsaEncryption(form);
146 if (form.addEventListener) {
147 form.addEventListener('submit', form.rsaEncryption.handleFormSubmitRequest, false);
148 } else if (form.attachEvent) {
149 form.attachEvent('onsubmit', form.rsaEncryption.handleFormSubmitRequest);
150 }
151 }
152 form.rsaEncryption.fields.push(field);
153 }
154 }
155 }
156 }
157 }
158
159 // If the document is ready, callback function can be called
160 if (document.readyState === 'complete') {
161 setTimeout(ready, 1);
162 } else {
163 // Install event handlers for older browsers
164 if (document.addEventListener) {
165 // First register DOMContentLoaded event
166 document.addEventListener('DOMContentLoaded', ready, false);
167 // Register backup on windows object
168 window.addEventListener('load', ready, false);
169 } else {
170 // Fallback for Internet Explorer
171 document.attachEvent('onreadystatechange', function() {
172 if (document.readyState === 'complete') {
173 ready();
174 }
175 });
176 window.attachEvent('onload', ready);
177 }
178 }
179
180 })();