· 6 years ago · Jan 24, 2020, 09:02 PM
1var module;
2
3// Start new object if we haven't got one yet
4if ("undefined" === typeof assess) {
5 var assess = [];
6}
7
8// Show secret level
9assess.showSecretLevel = function() {
10 var bonusChapter = top.get("holder").dataset.bonus;
11 top.get("completedButton").innerHTML =
12 "Correct! Well done. Go to challenge " +
13 bonusChapter +
14 " BONUS CHALLENGE! →";
15 top.get("completedButton").href = "challenge-" + bonusChapter + "";
16};
17
18// Attempt to score a flag
19assess.attemptFlag = function(challenge, flag, csrf) {
20 var xhr = top.assess.xhrObj();
21 // Clear any existing timer to slide away the slider
22 if ("undefined" !== typeof top.assess.popMessageTimeout) {
23 clearTimeout(top.assess.popMessageTimeout);
24 }
25 // Do not allow additional attempts whilst flag attempt in progress
26 if (
27 "undefined" === typeof top.assess.cpa_flagAttemptInProgress ||
28 false === top.assess.cpa_flagAttemptInProgress
29 ) {
30 assess.attemptFlagXHR(xhr, challenge, flag, csrf);
31 }
32};
33
34// Attempt flag over XHR now
35assess.attemptFlagXHR = function(xhr, challenge, flag, csrf) {
36 top.assess.cpa_flagAttemptInProgress = true;
37 xhr.onreadystatechange = function() {
38 if (4 === xhr.readyState) {
39 top.assess.handleFlagAttemptResponse(xhr, challenge);
40 }
41 };
42
43 xhr.open("POST", "api", true);
44 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
45 xhr.send(
46 "action=flag_attempt&challenge=" +
47 challenge +
48 "&flag=" +
49 encodeURIComponent(flag) +
50 "&csrf=" +
51 csrf +
52 "&timetaken="
53 );
54};
55
56// Handle flag attempt response
57assess.handleFlagAttemptResponse = function(xhr, challenge) {
58 var responseText = xhr.responseText;
59 var responseJSON = JSON.parse(responseText);
60 switch (xhr.status) {
61 case 200:
62 top.assess.handleFlagAttemptResponse200(xhr);
63 if ("correct" === responseJSON.attempt.result) {
64 top.assess.handleFlagAttemptResponse200Correct(xhr, challenge);
65 }
66 break;
67 case 403:
68 top.assess.handleFlagAttemptResponse403();
69 break;
70 }
71 top.assess.handleFlagAttemptResponseMsg();
72 top.assess.cpa_flagAttemptInProgress = false;
73};
74
75// Handle flag attempt response message
76assess.handleFlagAttemptResponseMsg = function() {
77 // Show message
78 top.get("pop-message").style.transition = "top 0.3s ease-in-out";
79 setTimeout(top.assess.popMessageShowHide, 0, "show");
80 // After 2 secs slide it away
81 top.assess.popMessageTimeout = setTimeout(
82 top.assess.popMessageShowHide,
83 2000,
84 "hide"
85 );
86};
87
88// Handle flag attempt response for status 200
89assess.handleFlagAttemptResponse200 = function(xhr) {
90 var responseText = xhr.responseText;
91 var responseJSON = JSON.parse(responseText);
92 // Display success/fail message
93 top.get("pop-message").className =
94 "correct" === responseJSON.attempt.result
95 ? "pop pop-success pop-show"
96 : "pop pop-error pop-show";
97 top.get("pop-message").innerHTML = responseJSON.attempt.message;
98};
99
100// Handle flag attempt response for status 200 & correct
101assess.handleFlagAttemptResponse200Correct = function(xhr, challenge) {
102 var responseText = xhr.responseText;
103 var responseJSON = JSON.parse(responseText);
104 if (
105 1 === responseJSON.completed_core &&
106 challenge !== parseInt(top.get("holder").dataset.bonus, 10)
107 ) {
108 top.assess.showSecretLevel();
109 }
110 setTimeout(top.assess.showFlagCompletedElems, 2300);
111 top.assess.rctStopPingTimer();
112};
113
114// Handle flag attempt response for status 403
115assess.handleFlagAttemptResponse403 = function() {
116 // Display fail message
117 top.get("pop-message").className = "pop pop-error pop-show";
118 top.get("pop-message").innerHTML = "Nope, that's the wrong code.";
119};
120
121// Show/hide the pop message
122assess.popMessageShowHide = function(vis) {
123 top.get("pop-message").style.top = "show" === vis ? "-46px" : 0;
124};
125
126// Show flag completed DOM elems on page
127assess.showFlagCompletedElems = function() {
128 top.get("completedStamp").style.display = "block";
129 top.get("flagForm").style.display = "none";
130 top.get("completedButton").style.display = "block";
131};
132
133// Challenge timer
134assess.runChallengeTimer = function() {
135 top.assess.challengeTimer.elem = top.get("holder");
136 top.assess.challengeTimer.challengeID = parseInt(
137 top.assess.challengeTimer.elem.dataset.challengeid,
138 10
139 );
140 top.assess.challengeTimer.csrf =
141 top.assess.challengeTimer.elem.dataset.token;
142 top.assess.challengeTimer.timeoutAfter = parseInt(
143 top.assess.challengeTimer.elem.dataset.timeoutafter,
144 10
145 );
146 top.assess.challengeTimer.incrementTime = parseInt(
147 top.assess.challengeTimer.elem.dataset.incrementtime,
148 10
149 );
150
151 // Start the idle timer and activity check
152 top.assess.challengeTimer.idleTimer = setTimeout(
153 top.assess.rctIdleTimeout,
154 top.assess.challengeTimer.timeoutAfter
155 );
156 if (document.hasFocus()) {
157 top.assess.rctCheckActivity();
158 }
159 top.assess.rctCheckChallengeTime();
160};
161
162assess.rctIdleTimeout = function() {
163 top.assess.challengeTimer.isIdle = true;
164};
165
166assess.rctResetIdleTimer = function() {
167 clearTimeout(top.assess.challengeTimer.idleTimer);
168 top.assess.challengeTimer.idleTimer = setTimeout(
169 top.assess.rctIdleTimeout,
170 top.assess.challengeTimer.timeoutAfter
171 );
172 top.assess.challengeTimer.isIdle = false;
173};
174
175assess.rctCheckActivity = function() {
176 document.onmousemove = top.assess.rctResetIdleTimer; // Mouse movement
177 document.onscroll = top.assess.rctResetIdleTimer; // Scroll
178 document.onclick = top.assess.rctResetIdleTimer; // Click
179 document.onkeypress = top.assess.rctResetIdleTimer; // Key press
180 document.onmousedown = top.assess.rctResetIdleTimer; // Touch screens
181 document.ontouchstart = top.assess.rctResetIdleTimer; // Touch screens
182};
183
184assess.rctUpdateChallengeTimeSpent = function() {
185 var xhr = top.assess.xhrObj();
186
187 if (false === top.assess.challengeTimer.isIdle) {
188 xhr.onreadystatechange = function() {
189 // On successful response...
190 if (4 === xhr.readyState) {
191 top.assess.rctClearTimer(xhr);
192 }
193 };
194
195 xhr.open("POST", "api", true);
196 xhr.setRequestHeader(
197 "Content-type",
198 "application/x-www-form-urlencoded"
199 );
200 //var timetaken = localStorage.getItem('timer_' + challenge);
201 xhr.send(
202 "action=updateTime&challenge=" +
203 top.assess.challengeTimer.challengeID +
204 "&time=" +
205 top.assess.challengeTimer.incrementTime / 1000 +
206 "&csrf=" +
207 top.assess.challengeTimer.csrf
208 );
209 return true;
210 }
211};
212
213assess.rctClearTimer = function(xhr) {
214 if (200 === xhr.status) {
215 var responseText = xhr.responseText;
216 var responseJSON = JSON.parse(responseText);
217 if (true === responseJSON.complete) {
218 clearInterval(top.assess.challengeTimer.timerInterval);
219 return true;
220 }
221 }
222 return false;
223};
224
225assess.rctCheckChallengeTime = function() {
226 top.assess.challengeTimer.timerInterval = setInterval(
227 top.assess.rctUpdateChallengeTimeSpent,
228 top.assess.challengeTimer.incrementTime
229 );
230};
231
232assess.rctStopPingTimer = function() {
233 clearTimeout(top.assess.challengeTimer.idleTimer);
234 clearInterval(top.assess.challengeTimer.timerInterval);
235};
236
237assess.formSubmit = function(formElem) {
238 var submitJSON = JSON.parse(formElem.dataset.submit.replace(/'/g, '"'));
239 // Attempt flag
240 if ("attemptFlag" === submitJSON.type) {
241 top.assess.attemptFlag(
242 ("0" + top.get("holder").dataset.challengeid).slice(-2),
243 top.get("codeAttempt").value,
244 top.get("holder").dataset.token
245 );
246 return false;
247 }
248};
249
250assess.setNowhereLink = function(elem) {
251 elem.classList.add("going-nowhere");
252 setTimeout(top.assess.setNowhereLinkReset, 1000, elem);
253 return false;
254};
255
256assess.setNowhereLinkReset = function(elem) {
257 elem.classList.remove("going-nowhere");
258 return false;
259};
260
261assess.initAssess = function() {
262 top.assess.challengeTimer = {
263 timerInterval: false,
264 isIdle: false,
265 elem: top.get("holder")
266 };
267 // Start timers if challenge not finished yet
268 if (
269 "undefined" !== typeof top.assess.startTimer &&
270 true === top.assess.startTimer
271 ) {
272 top.assess.runChallengeTimer();
273 }
274 return true;
275};
276
277if ("undefined" !== typeof top.assess) {
278 top.assess.addEvent(window, "load", top.assess.initAssess);
279}
280
281if ("object" === typeof module) {
282 module.exports = {
283 assess: assess
284 };
285}