PluginProbe ʕ •ᴥ•ʔ
Wordfence Security – Firewall, Malware Scan, and Login Security / 3.2.1
Wordfence Security – Firewall, Malware Scan, and Login Security v3.2.1
8.2.2 8.2.1 8.2.0 3.7.1 3.7.2 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.8.8 3.8.9 3.9.1 4.0.1 4.0.2 4.0.3 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.0.9 5.1.1 5.1.2 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.1 5.3.10 5.3.11 5.3.12 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.3.8 5.3.9 6.0.1 6.0.10 6.0.11 6.0.12 6.0.14 6.0.15 6.0.16 6.0.17 6.0.18 6.0.19 6.0.2 6.0.20 6.0.21 6.0.22 6.0.23 6.0.24 6.0.25 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.0.8 6.0.9 6.1.1 6.1.10 6.1.11 6.1.12 6.1.14 6.1.15 6.1.16 6.1.17 6.1.2 6.1.3 6.1.4 6.1.5 6.1.6 6.1.7 6.1.8 6.1.9 6.2.0 6.2.1 6.2.10 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.2.8 6.2.9 6.3.0 6.3.1 6.3.10 6.3.11 6.3.12 6.3.14 6.3.15 6.3.16 6.3.17 6.3.18 6.3.19 6.3.2 6.3.20 6.3.21 6.3.22 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.3.8 6.3.9 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1.0 7.1.1 7.1.10 7.1.11 7.1.12 7.1.14 7.1.15 7.1.16 7.1.17 7.1.18 7.1.19 7.1.2 7.1.20 7.1.3 7.1.4 7.1.5 7.1.6 7.1.7 7.1.8 7.1.9 7.10.0 7.10.1 7.10.2 7.10.3 7.10.4 7.10.5 7.10.6 7.10.7 7.11.0 7.11.1 7.11.2 7.11.3 7.11.4 7.11.5 7.11.6 7.11.7 7.2.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3.1 7.3.2 7.3.3 7.3.4 7.3.5 7.3.6 7.4.0 7.4.1 7.4.10 7.4.11 7.4.12 7.4.14 7.4.2 7.4.3 trunk 7.4.4 1.1 7.4.5 1.2 7.4.6 1.3 7.4.7 1.3.1 7.4.8 1.3.2 7.4.9 1.3.3 7.5.0 1.4.2 7.5.1 1.4.3 7.5.10 1.4.4 7.5.11 1.4.5 7.5.2 1.4.6 7.5.3 1.4.7 7.5.4 1.4.8 7.5.5 1.5.1 7.5.6 1.5.2 7.5.7 1.5.3 7.5.8 1.5.4 7.5.9 1.5.5 7.6.0 1.5.6 7.6.1 2.0.1 7.6.2 2.0.2 7.7.0 2.0.3 7.7.1 2.0.5 7.8.0 2.0.6 7.8.1 2.0.7 7.8.2 2.1.0 7.9.0 2.1.1 7.9.1 2.1.2 7.9.2 2.1.3 7.9.3 2.1.4 8.0.0 2.1.5 8.0.1 3.0.2 8.0.2 3.0.3 8.0.3 3.0.4 8.0.4 3.0.5 8.0.5 3.0.6 8.1.0 3.0.7 8.1.1 3.0.8 8.1.2 3.0.9 8.1.3 3.1.0 8.1.4 3.1.1 v1.4.1 3.1.2 3.1.4 3.1.6 3.2.1 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.1 3.4.4 3.4.5 3.5.1 3.5.2 3.6.1 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9
wordfence / js / admin.js
wordfence / js Last commit date
admin.js 13 years ago jquery.colorbox-min.js 14 years ago jquery.dataTables.min.js 14 years ago jquery.tmpl.min.js 14 years ago jquery.tools.min.js 14 years ago tourTip.js 13 years ago
admin.js
1125 lines
1 if(! window['wordfenceAdmin']){
2 window['wordfenceAdmin'] = {
3 loading16: '<div class="wfLoading16"></div>',
4 actUpdateInterval: 2000,
5 dbCheckTables: [],
6 dbCheckCount_ok: 0,
7 dbCheckCount_skipped: 0,
8 dbCheckCount_errors: 0,
9 issues: [],
10 ignoreData: false,
11 iconErrorMsgs: [],
12 scanIDLoaded: 0,
13 colorboxQueue: [],
14 colorboxOpen: false,
15 mode: '',
16 visibleIssuesPanel: 'new',
17 preFirstScanMsgsLoaded: false,
18 newestActivityTime: 0, //must be 0 to force loading of all initially
19 elementGeneratorIter: 1,
20 reloadConfigPage: false,
21 nonce: false,
22 tickerUpdatePending: false,
23 activityLogUpdatePending: false,
24 lastALogCtime: 0,
25 activityQueue: [],
26 totalActAdded: 0,
27 maxActivityLogItems: 1000,
28 scanReqAnimation: false,
29 debugOn: false,
30 blockedCountriesPending: [],
31 ownCountry: "",
32 schedStartHour: false,
33 currentPointer: false,
34 init: function(){
35 this.nonce = WordfenceAdminVars.firstNonce;
36 this.debugOn = WordfenceAdminVars.debugOn == '1' ? true : false;
37 this.tourClosed = WordfenceAdminVars.tourClosed == '1' ? true : false;
38 var startTicker = false;
39 if(jQuery('#wordfenceMode_scan').length > 0){
40 this.mode = 'scan';
41 jQuery('#wfALogViewLink').prop('href', WordfenceAdminVars.siteBaseURL + '?_wfsf=viewActivityLog&nonce=' + this.nonce);
42 jQuery('#consoleActivity').scrollTop(jQuery('#consoleActivity').prop('scrollHeight'));
43 jQuery('#consoleScan').scrollTop(jQuery('#consoleScan').prop('scrollHeight'));
44 this.noScanHTML = jQuery('#wfNoScanYetTmpl').tmpl().html();
45 this.loadIssues();
46 this.startActivityLogUpdates();
47 if(! this.tourClosed){
48 this.scanTourStart();
49 }
50 } else if(jQuery('#wordfenceMode_activity').length > 0){
51 this.mode = 'activity';
52 this.activityMode = 'hit';
53 startTicker = true;
54 if(! this.tourClosed){
55 var self = this;
56 this.tour('wfWelcomeContent3', 'wfHeading', 'top', 'left', "Learn about IP Blocking", function(){ self.tourRedir('WordfenceBlockedIPs'); });
57 }
58 } else if(jQuery('#wordfenceMode_options').length > 0){
59 this.mode = 'options';
60 jQuery('.wfConfigElem').change(function(){ jQuery('#securityLevel').val('CUSTOM'); });
61 this.updateTicker(true);
62 startTicker = true;
63 if(! this.tourClosed){
64 var self = this;
65 this.tour('wfContentBasicOptions', 'wfMarkerBasicOptions', 'top', 'left', "Learn about Live Traffic Options", function(){
66 self.tour('wfContentLiveTrafficOptions', 'wfMarkerLiveTrafficOptions', 'bottom', 'left', "Learn about Scanning Options", function(){
67 self.tour('wfContentScansToInclude', 'wfMarkerScansToInclude', 'bottom', 'left', "Learn about Firewall Rules", function(){
68 self.tour('wfContentFirewallRules', 'wfMarkerFirewallRules', 'bottom', 'left', "Learn about Login Security", function(){
69 self.tour('wfContentLoginSecurity', 'wfMarkerLoginSecurity', 'bottom', 'left', "Learn about Other Options", function(){
70 self.tour('wfContentOtherOptions', 'wfMarkerOtherOptions', 'bottom', 'left', false, false);
71 });
72 });
73 });
74 });
75 });
76 }
77 } else if(jQuery('#wordfenceMode_blockedIPs').length > 0){
78 this.mode = 'blocked';
79 this.staticTabChanged();
80 this.updateTicker(true);
81 startTicker = true;
82 if(! this.tourClosed){
83 var self = this;
84 this.tour('wfWelcomeContent4', 'wfHeading', 'top', 'left', "Learn how to Block Countries", function(){ self.tourRedir('WordfenceCountryBlocking'); });
85 }
86 } else if(jQuery('#wordfenceMode_countryBlocking').length > 0){
87 this.mode = 'countryBlocking';
88 startTicker = false;
89 this.drawBlockedCountries();
90 if(! this.tourClosed){
91 var self = this;
92 this.tour('wfWelcomeContentCntBlk', 'wfHeading', 'top', 'left', "Learn how to Schedule Scans", function(){ self.tourRedir('WordfenceScanSchedule'); });
93 }
94 } else if(jQuery('#wordfenceMode_scanScheduling').length > 0){
95 this.mode = 'scanScheduling';
96 startTicker = false;
97 this.sched_modeChange();
98 if(! this.tourClosed){
99 var self = this;
100 this.tour('wfWelcomeContentScanSched', 'wfHeading', 'top', 'left', "Learn how to Customize Wordfence", function(){ self.tourRedir('WordfenceSecOpt'); });
101 }
102 } else {
103 this.mode = false;
104 }
105 if(this.mode){ //We are in a Wordfence page
106 var self = this;
107 if(startTicker){
108 this.liveInt = setInterval(function(){ self.updateTicker(); }, 2000);
109 }
110 jQuery(document).bind('cbox_closed', function(){ self.colorboxIsOpen = false; self.colorboxServiceQueue(); });
111 }
112 },
113 scanTourStart: function(){
114 var self = this;
115 this.tour('wfWelcomeContent1', 'wfHeading', 'top', 'left', "Continue the Tour", function(){
116 self.tour('wfWelcomeContent2', 'wfHeading', 'top', 'left', "Learn how to use Wordfence", function(){
117 self.tour('wfWelcomeContent3', 'wfHeading', 'top', 'left', "Learn about Live Traffic", function(){ self.tourRedir('WordfenceActivity'); });
118 });
119 });
120 },
121 tourRedir: function(menuItem){
122 window.location.href = 'admin.php?page=' + menuItem;
123 },
124 tourFinish: function(){
125 this.ajax('wordfence_tourClosed', {}, function(res){});
126 },
127 tour: function(contentID, elemID, edge, align, buttonLabel, buttonCallback){
128 var self = this;
129 if(this.currentPointer){
130 this.currentPointer.pointer('destroy');
131 this.currentPointer = false;
132 }
133 var options = {
134 buttons: function(event, t){
135 var buttonElem = jQuery('<div id="wfTourButCont"><a id="pointer-close" style="margin-left:5px" class="button-secondary">End the Tour</a></div><div><a id="wfRateLink" href="http://wordpress.org/extend/plugins/wordfence/" target="_blank" style="font-size: 10px; font-family: Verdana;">Help spread the word by rating us 5&#9733; on WordPress.org</a></div>');
136 buttonElem.find('#pointer-close').bind('click.pointer', function (evtObj) {
137 if(evtObj.srcElement.id == 'wfRateLink'){
138 return true;
139 }
140 self.tourFinish();
141 t.element.pointer('close');
142 return false;
143 });
144 return buttonElem;
145 },
146 close: function(){},
147 content: jQuery('#' + contentID).tmpl().html(),
148 pointerWidth: 400,
149 position: {
150 edge: edge,
151 align: align,
152 }
153 };
154 this.currentPointer = jQuery('#' + elemID).pointer(options).pointer('open');
155 if(buttonLabel && buttonCallback){
156 jQuery('#pointer-close').after('<a id="pointer-primary" class="button-primary">' + buttonLabel + '</a>');
157 jQuery('#pointer-primary').click(buttonCallback);
158 }
159 },
160 startTourAgain: function(){
161 this.ajax('wordfence_startTourAgain', {}, function(res){});
162 this.tourClosed = false;
163 this.scanTourStart();
164 },
165 showLoading: function(){
166 this.removeLoading();
167 jQuery('<div id="wordfenceWorking">Wordfence is working...</div>').appendTo('body');
168 },
169 removeLoading: function(){
170 jQuery('#wordfenceWorking').remove();
171 },
172 startActivityLogUpdates: function(){
173 var self = this;
174 setInterval(function(){
175 self.updateActivityLog();
176 }, this.actUpdateInterval);
177 },
178 updateActivityLog: function(){
179 if(this.activityLogUpdatePending){
180 return;
181 }
182 this.activityLogUpdatePending = true;
183 var self = this;
184 this.ajax('wordfence_activityLogUpdate', {
185 lastctime: this.lastALogCtime
186 }, function(res){ self.doneUpdateActivityLog(res); }, function(){ self.activityLogUpdatePending = false; }, true);
187
188 },
189 doneUpdateActivityLog: function(res){
190 this.actNextUpdateAt = (new Date()).getTime() + this.actUpdateInterval;
191 if(res.ok){
192 if(res.items.length > 0){
193 this.activityQueue.push.apply(this.activityQueue, res.items);
194 this.lastALogCtime = res.items[res.items.length - 1].ctime;
195 this.processActQueue(res.currentScanID);
196 }
197 }
198 this.activityLogUpdatePending = false;
199 },
200 processActQueue: function(currentScanID){
201 if(this.activityQueue.length > 0){
202
203 this.addActItem(this.activityQueue.shift());
204 this.totalActAdded++;
205 if(this.totalActAdded > this.maxActivityLogItems){
206 jQuery('#consoleActivity div:first').remove();
207 this.totalActAdded--;
208 }
209
210 var timeTillNextUpdate = this.actNextUpdateAt - (new Date()).getTime();
211 var maxRate = 50 / 1000; //Rate per millisecond
212 var bulkTotal = 0;
213 while(this.activityQueue.length > 0 && this.activityQueue.length / timeTillNextUpdate > maxRate ){
214 var item = this.activityQueue.shift();
215 if(item){
216 bulkTotal++;
217 this.addActItem(item);
218 }
219 }
220 this.totalActAdded += bulkTotal;
221 if(this.totalActAdded > this.maxActivityLogItems){
222 jQuery('#consoleActivity div:lt(' + bulkTotal + ')').remove();
223 this.totalActAdded -= bulkTotal;
224 }
225 var minDelay = 100;
226 var delay = minDelay;
227 if(timeTillNextUpdate < 1){
228 delay = minDelay;
229 } else {
230 delay = Math.round(timeTillNextUpdate / this.activityQueue.length);
231 if(delay < minDelay){ delay = minDelay; }
232 }
233 var self = this;
234 setTimeout(function(){ self.processActQueue(); }, delay);
235 }
236 jQuery('#consoleActivity').scrollTop(jQuery('#consoleActivity').prop('scrollHeight'));
237 },
238 processActArray: function(arr){
239 for(var i = 0; i < arr.length; i++){
240 this.addActItem(arr[i]);
241 }
242 },
243 addActItem: function(item){
244 if(item.msg.indexOf('SUM_') == 0){
245 this.processSummaryLine(item);
246 jQuery('#consoleSummary').scrollTop(jQuery('#consoleSummary').prop('scrollHeight'));
247 jQuery('#wfStartingScan').addClass('wfSummaryOK').html('Done.');
248 } else if(this.debugOn || item.level < 4){
249
250 var html = '<div class="wfActivityLine';
251 if(this.debugOn){
252 html += ' wf' + item.type;
253 }
254 html += '">[' + item.date + ']&nbsp;' + item.msg + '</div>';
255 jQuery('#consoleActivity').append(html);
256 if(/Scan complete\./i.test(item.msg)){
257 this.loadIssues();
258 }
259 }
260 },
261 processSummaryLine: function(item){
262 if(item.msg.indexOf('SUM_START:') != -1){
263 var msg = item.msg.replace('SUM_START:', '');
264 jQuery('#consoleSummary').append('<div class="wfSummaryLine"><div class="wfSummaryDate">[' + item.date + ']</div><div class="wfSummaryMsg">' + msg + '</div><div class="wfSummaryResult"><div class="wfSummaryLoading"></div></div><div class="wfClear"></div>');
265 summaryUpdated = true;
266 } else if(item.msg.indexOf('SUM_ENDBAD') != -1){
267 var msg = item.msg.replace('SUM_ENDBAD:', '');
268 jQuery('div.wfSummaryMsg:contains("' + msg + '")').next().addClass('wfSummaryBad').html('Problems found.');
269 summaryUpdated = true;
270 } else if(item.msg.indexOf('SUM_ENDOK') != -1){
271 var msg = item.msg.replace('SUM_ENDOK:', '');
272 jQuery('div.wfSummaryMsg:contains("' + msg + '")').next().addClass('wfSummaryOK').html('Secure.');
273 summaryUpdated = true;
274 } else if(item.msg.indexOf('SUM_ENDERR') != -1){
275 var msg = item.msg.replace('SUM_ENDERR:', '');
276 jQuery('div.wfSummaryMsg:contains("' + msg + '")').next().addClass('wfSummaryErr').html('An error occurred.');
277 summaryUpdated = true;
278 } else if(item.msg.indexOf('SUM_DISABLED:') != -1){
279 var msg = item.msg.replace('SUM_DISABLED:', '');
280 jQuery('#consoleSummary').append('<div class="wfSummaryLine"><div class="wfSummaryDate">[' + item.date + ']</div><div class="wfSummaryMsg">' + msg + '</div><div class="wfSummaryResult">Disabled [<a href="admin.php?page=WordfenceSecOpt">Visit Options to Enable</a>]</div><div class="wfClear"></div>');
281 summaryUpdated = true;
282 } else if(item.msg.indexOf('SUM_PAIDONLY:') != -1){
283 var msg = item.msg.replace('SUM_PAIDONLY:', '');
284 jQuery('#consoleSummary').append('<div class="wfSummaryLine"><div class="wfSummaryDate">[' + item.date + ']</div><div class="wfSummaryMsg">' + msg + '</div><div class="wfSummaryResult"><a href="https://www.wordfence.com/choose-a-wordfence-membership-type/?s2-ssl=yes" target="_blank">Paid Members Only</a></div><div class="wfClear"></div>');
285 summaryUpdated = true;
286 } else if(item.msg.indexOf('SUM_FINAL:') != -1){
287 var msg = item.msg.replace('SUM_FINAL:', '');
288 jQuery('#consoleSummary').append('<div class="wfSummaryLine"><div class="wfSummaryDate">[' + item.date + ']</div><div class="wfSummaryMsg wfSummaryFinal">' + msg + '</div><div class="wfSummaryResult wfSummaryOK">Scan Complete.</div><div class="wfClear"></div>');
289 } else if(item.msg.indexOf('SUM_PREP:') != -1){
290 var msg = item.msg.replace('SUM_PREP:', '');
291 jQuery('#consoleSummary').empty().html('<div class="wfSummaryLine"><div class="wfSummaryDate">[' + item.date + ']</div><div class="wfSummaryMsg">' + msg + '</div><div class="wfSummaryResult" id="wfStartingScan"><div class="wfSummaryLoading"></div></div><div class="wfClear"></div>');
292 } else if(item.msg.indexOf('SUM_KILLED:') != -1){
293 var msg = item.msg.replace('SUM_KILLED:', '');
294 jQuery('#consoleSummary').empty().html('<div class="wfSummaryLine"><div class="wfSummaryDate">[' + item.date + ']</div><div class="wfSummaryMsg">' + msg + '</div><div class="wfSummaryResult wfSummaryOK">Scan Complete.</div><div class="wfClear"></div>');
295 }
296 },
297 processActQueueItem: function(){
298 var item = this.activityQueue.shift();
299 if(item){
300 jQuery('#consoleActivity').append('<div class="wfActivityLine wf' + item.type + '">[' + item.date + ']&nbsp;' + item.msg + '</div>');
301 this.totalActAdded++;
302 if(this.totalActAdded > this.maxActivityLogItems){
303 jQuery('#consoleActivity div:first').remove();
304 this.totalActAdded--;
305 }
306 if(item.msg == 'Scan complete.'){
307 this.loadIssues();
308 }
309 }
310 },
311 updateTicker: function(forceUpdate){
312 if( (! forceUpdate) && this.tickerUpdatePending){
313 return;
314 }
315 this.tickerUpdatePending = true;
316 var self = this;
317 var alsoGet = '';
318 var otherParams = '';
319 if(this.mode == 'activity' && /^(?:404|hit|human|ruser|gCrawler|crawler|loginLogout)$/.test(this.activityMode)){
320 alsoGet = 'logList_' + this.activityMode;
321 otherParams = this.newestActivityTime;
322 }
323 this.ajax('wordfence_ticker', {
324 alsoGet: alsoGet,
325 otherParams: otherParams
326 }, function(res){ self.handleTickerReturn(res); }, function(){ self.tickerUpdatePending = false; }, true);
327 },
328 handleTickerReturn: function(res){
329 this.tickerUpdatePending = false;
330 var statusMsgChanged = false;
331 var newMsg = "";
332 var oldMsg = jQuery('#wfLiveStatus').html();
333 if( res.msg ){
334 newMsg = res.msg;
335 } else {
336 newMsg = "Idle";
337 }
338 if(newMsg && oldMsg && newMsg != oldMsg){
339 statusMsgChanged = true;
340 }
341 if(newMsg && newMsg != oldMsg){
342 jQuery('#wfLiveStatus').hide().html(newMsg).fadeIn(200);
343 }
344
345 if(this.mode == 'activity'){
346 if(res.alsoGet != 'logList_' + this.activityMode){ return; } //user switched panels since ajax request started
347 if(/^(?:topScanners|topLeechers)$/.test(this.activityMode)){
348 if(statusMsgChanged){ this.updateTicker(true); } return;
349 }
350 if(res.events.length > 0){
351 this.newestActivityTime = res.events[0]['ctime'];
352 }
353 var haveEvents = false;
354 if(jQuery('#wfActivity_' + this.activityMode + ' .wfActEvent').length > 0){
355 haveEvents = true;
356 }
357 if(res.events.length > 0){
358 if(! haveEvents){
359 jQuery('#wfActivity_' + this.activityMode).empty();
360 }
361 for(i = res.events.length - 1; i >= 0; i--){
362 var elemID = '#wfActEvent_' + res.events[i].id;
363 if(jQuery(elemID).length < 1){
364 res.events[i]['activityMode'] = this.activityMode;
365 var newElem;
366 if(this.activityMode == 'loginLogout'){
367 newElem = jQuery('#wfLoginLogoutEventTmpl').tmpl(res.events[i]);
368 } else {
369 newElem = jQuery('#wfHitsEventTmpl').tmpl(res.events[i]);
370 }
371 jQuery(newElem).find('.wfTimeAgo').data('wfctime', res.events[i].ctime);
372 newElem.prependTo('#wfActivity_' + this.activityMode).fadeIn();
373 }
374 }
375 this.reverseLookupIPs();
376 } else {
377 if(! haveEvents){
378 jQuery('#wfActivity_' + this.activityMode).html('<div>No events to report yet.</div>');
379 }
380 }
381 var self = this;
382 jQuery('.wfTimeAgo').each(function(idx, elem){
383 jQuery(elem).html(self.makeTimeAgo(res.serverTime - jQuery(elem).data('wfctime')) + ' ago');
384 });
385 }
386 if(statusMsgChanged){ this.updateTicker(true); } return;
387 },
388 reverseLookupIPs: function(){
389 var ips = [];
390 jQuery('.wfReverseLookup').each(function(idx, elem){
391 var txt = jQuery(elem).text();
392 if(/^\d+\.\d+\.\d+\.\d+$/.test(txt) && (! jQuery(elem).data('wfReverseDone'))){
393 jQuery(elem).data('wfReverseDone', true);
394 ips.push(jQuery(elem).text());
395 }
396 });
397 if(ips.length < 1){ return; }
398 var uni = {};
399 var uniqueIPs = [];
400 for(var i = 0; i < ips.length; i++){
401 if(! uni[ips[i]]){
402 uni[ips[i]] = true;
403 uniqueIPs.push(ips[i]);
404 }
405 }
406 this.ajax('wordfence_reverseLookup', {
407 ips: uniqueIPs.join(',')
408 },
409 function(res){
410 if(res.ok){
411 jQuery('.wfReverseLookup').each(function(idx, elem){
412 var txt = jQuery(elem).text();
413 for(ip in res.ips){
414 if(txt == ip){
415 if(res.ips[ip]){
416 jQuery(elem).html('<strong>Hostname:</strong>&nbsp;' + res.ips[ip]);
417 } else {
418 jQuery(elem).html('');
419 }
420 }
421 }
422 });
423 }
424 }, false, false);
425 },
426 killScan: function(){
427 var self = this;
428 this.ajax('wordfence_killScan', {}, function(res){
429 if(res.ok){
430 self.colorbox('400px', "Kill requested", "A termination request has been sent to any running scans.");
431 } else {
432 self.colorbox('400px', "Kill failed", "We failed to send a termination request.");
433 }
434 });
435 },
436 startScan: function(){
437 var scanReqAnimation = setInterval(function(){
438 var str = jQuery('#wfStartScanButton1').prop('value');
439 ch = str.charAt(str.length - 1);
440 if(ch == '/'){ ch = '-'; }
441 else if(ch == '-'){ ch = '\\'; }
442 else if(ch == '\\'){ ch = '|'; }
443 else if(ch == '|'){ ch = '/'; }
444 else {ch = '/'; }
445 jQuery('#wfStartScanButton1,#wfStartScanButton2').prop('value', "Requesting a New Scan " + ch);
446 }, 100);
447 setTimeout(function(res){
448 clearInterval(scanReqAnimation);
449 jQuery('#wfStartScanButton1,#wfStartScanButton2').prop('value', "Start a Wordfence Scan");
450 }, 3000);
451 this.ajax('wordfence_scan', {}, function(res){ } );
452 },
453 loadIssues: function(callback){
454 if(this.mode != 'scan'){
455 return;
456 }
457 var self = this;
458 this.ajax('wordfence_loadIssues', { }, function(res){
459 self.displayIssues(res, callback);
460 });
461 },
462 sev2num: function(str){
463 if(/wfProbSev1/.test(str)){
464 return 1;
465 } else if(/wfProbSev2/.test(str)){
466 return 2;
467 } else {
468 return 0;
469 }
470 },
471 displayIssues: function(res, callback){
472 var self = this;
473 res.summary['lastScanCompleted'] = res['lastScanCompleted'];
474 jQuery('.wfIssuesContainer').hide();
475 for(issueStatus in res.issuesLists){
476 var containerID = 'wfIssues_dataTable_' + issueStatus;
477 var tableID = 'wfIssuesTable_' + issueStatus;
478 if(jQuery('#' + containerID).length < 1){
479 //Invalid issue status
480 continue;
481 }
482 if(res.issuesLists[issueStatus].length < 1){
483 if(issueStatus == 'new'){
484 if(res.lastScanCompleted == 'ok'){
485 jQuery('#' + containerID).html('<p style="font-size: 20px; color: #0A0;">Congratulations! You have no security issues on your site.</p>');
486 } else if(res['lastScanCompleted']){
487 //jQuery('#' + containerID).html('<p style="font-size: 12px; color: #A00;">The latest scan failed: ' + res.lastScanCompleted + '</p>');
488 } else {
489 jQuery('#' + containerID).html();
490 }
491
492 } else {
493 jQuery('#' + containerID).html('<p>There are currently <strong>no issues</strong> being ignored on this site.</p>');
494 }
495 continue;
496 }
497 jQuery('#' + containerID).html('<table cellpadding="0" cellspacing="0" border="0" class="display" id="' + tableID + '"></table>');
498
499 jQuery.fn.dataTableExt.oSort['severity-asc'] = function(y,x){ x = WFAD.sev2num(x); y = WFAD.sev2num(y); if(x < y){ return 1; } if(x > y){ return -1; } return 0; };
500 jQuery.fn.dataTableExt.oSort['severity-desc'] = function(y,x){ x = WFAD.sev2num(x); y = WFAD.sev2num(y); if(x > y){ return 1; } if(x < y){ return -1; } return 0; };
501
502 jQuery('#' + tableID).dataTable({
503 "bFilter": false,
504 "bInfo": false,
505 "bPaginate": false,
506 "bLengthChange": false,
507 "bAutoWidth": false,
508 "aaData": res.issuesLists[issueStatus],
509 "aoColumns": [
510 {
511 "sTitle": '<div class="th_wrapp">Severity</div>',
512 "sWidth": '128px',
513 "sClass": "center",
514 "sType": 'severity',
515 "fnRender": function(obj) {
516 var cls = "";
517 cls = 'wfProbSev' + obj.aData.severity;
518 return '<span class="' + cls + '"></span>';
519 }
520 },
521 {
522 "sTitle": '<div class="th_wrapp">Issue</div>',
523 "bSortable": false,
524 "sWidth": '400px',
525 "sType": 'html',
526 fnRender: function(obj){
527 var tmplName = 'issueTmpl_' + obj.aData.type;
528 return jQuery('#' + tmplName).tmpl(obj.aData).html();
529 }
530 }
531 ]
532 });
533 }
534 if(callback){
535 jQuery('#wfIssues_' + this.visibleIssuesPanel).fadeIn(500, function(){ callback(); });
536 } else {
537 jQuery('#wfIssues_' + this.visibleIssuesPanel).fadeIn(500);
538 }
539 return true;
540 },
541 ajax: function(action, data, cb, cbErr, noLoading){
542 if(typeof(data) == 'string'){
543 if(data.length > 0){
544 data += '&';
545 }
546 data += 'action=' + action + '&nonce=' + this.nonce;
547 } else if(typeof(data) == 'object'){
548 data['action'] = action;
549 data['nonce'] = this.nonce;
550 }
551 if(! cbErr){
552 cbErr = function(){};
553 }
554 var self = this;
555 if(! noLoading){
556 this.showLoading();
557 }
558 jQuery.ajax({
559 type: 'POST',
560 url: WordfenceAdminVars.ajaxURL,
561 dataType: "json",
562 data: data,
563 success: function(json){
564 self.removeLoading();
565 if(json && json.nonce){
566 self.nonce = json.nonce;
567 }
568 if(json && json.errorMsg){
569 self.colorbox('400px', 'An error occurred', json.errorMsg);
570 }
571 cb(json);
572 },
573 error: function(){ self.removeLoading(); cbErr(); }
574 });
575 },
576 colorbox: function(width, heading, body){
577 this.colorboxQueue.push([width, heading, body]);
578 this.colorboxServiceQueue();
579 },
580 colorboxServiceQueue: function(){
581 if(this.colorboxIsOpen){ return; }
582 if(this.colorboxQueue.length < 1){ return; }
583 var elem = this.colorboxQueue.shift();
584 this.colorboxOpen(elem[0], elem[1], elem[2]);
585 },
586 colorboxOpen: function(width, heading, body){
587 this.colorboxIsOpen = true;
588 jQuery.colorbox({ width: width, html: "<h3>" + heading + "</h3><p>" + body + "</p>"});
589 },
590 scanRunningMsg: function(){ this.colorbox('400px', "A scan is running", "A scan is currently in progress. Please wait until it finishes before starting another scan."); },
591 errorMsg: function(msg){ this.colorbox('400px', "An error occurred:", msg); },
592 deleteFile: function(issueID){
593 var self = this;
594 this.ajax('wordfence_deleteFile', {
595 issueID: issueID
596 }, function(res){ self.doneDeleteFile(res); });
597 },
598 doneDeleteFile: function(res){
599 var cb = false;
600 var self = this;
601 if(res.ok){
602 this.loadIssues(function(){ self.colorbox('400px', "Success deleting file", "The file " + res.file + " was successfully deleted."); });
603 } else if(res.cerrorMsg){
604 this.loadIssues(function(){ self.colorbox('400px', 'An error occurred', res.cerrorMsg); });
605 }
606 },
607 restoreFile: function(issueID){
608 var self = this;
609 this.ajax('wordfence_restoreFile', {
610 issueID: issueID
611 }, function(res){ self.doneRestoreFile(res); });
612 },
613 doneRestoreFile: function(res){
614 var self = this;
615 if(res.ok){
616 this.loadIssues(function(){ self.colorbox("400px", "File restored OK", "The file " + res.file + " was restored succesfully."); });
617 } else if(res.cerrorMsg){
618 this.loadIssues(function(){ self.colorbox('400px', 'An error occurred', res.cerrorMsg); });
619 }
620 },
621 deleteIssue: function(id){
622 var self = this;
623 this.ajax('wordfence_deleteIssue', { id: id }, function(res){
624 self.loadIssues();
625 });
626 },
627 updateIssueStatus: function(id, st){
628 var self = this;
629 this.ajax('wordfence_updateIssueStatus', { id: id, 'status': st }, function(res){
630 if(res.ok){
631 self.loadIssues();
632 }
633 });
634 },
635 updateAllIssues: function(op){ // deleteIgnored, deleteNew, ignoreAllNew
636 var head = "Please confirm";
637 if(op == 'deleteIgnored'){
638 body = "You have chosen to remove all ignored issues. Once these issues are removed they will be re-scanned by Wordfence and if they have not been fixed, they will appear in the 'new issues' list. Are you sure you want to do this?";
639 } else if(op == 'deleteNew'){
640 body = "You have chosen to mark all new issues as fixed. If you have not really fixed these issues, they will reappear in the new issues list on the next scan. If you have not fixed them and want them excluded from scans you should choose to 'ignore' them instead. Are you sure you want to mark all new issues as fixed?";
641 } else if(op == 'ignoreAllNew'){
642 body = "You have chosen to ignore all new issues. That means they will be excluded from future scans. You should only do this if you're sure all new issues are not a problem. Are you sure you want to ignore all new issues?";
643 } else {
644 return;
645 }
646 this.colorbox('450px', head, body + '<br /><br /><center><input type="button" name="but1" value="Cancel" onclick="jQuery.colorbox.close();" />&nbsp;&nbsp;&nbsp;<input type="button" name="but2" value="Yes I\'m sure" onclick="jQuery.colorbox.close(); WFAD.confirmUpdateAllIssues(\'' + op + '\');" /><br />');
647 },
648 confirmUpdateAllIssues: function(op){
649 var self = this;
650 this.ajax('wordfence_updateAllIssues', { op: op }, function(res){ self.loadIssues(); });
651 },
652 es: function(val){
653 if(val){
654 return val;
655 } else {
656 return "";
657 }
658 },
659 noQuotes: function(str){
660 return str.replace(/"/g,'&#34;').replace(/\'/g, '&#145;');
661 },
662 commify: function(num){
663 return ("" + num).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
664 },
665 switchToLiveTab: function(elem){
666 jQuery('.wfTab1').removeClass('selected');
667 jQuery(elem).addClass('selected');
668 jQuery('.wfDataPanel').hide();
669 var self = this;
670 jQuery('#wfActivity').fadeIn(function(){ self.completeLiveTabSwitch(); });
671 },
672 completeLiveTabSwitch: function(){
673 this.ajax('wordfence_loadActivityLog', {}, function(res){
674 var html = '<a href="#" class="wfALogMailLink" onclick="WFAD.emailActivityLog(); return false;"></a><a href="#" class="wfALogReloadLink" onclick="WFAD.reloadActivityData(); return false;"></a>';
675 if(res.events && res.events.length > 0){
676 jQuery('#wfActivity').empty();
677 for(var i = 0; i < res.events.length; i++){
678 var timeTaken = '0.0000';
679 if(res.events[i + 1]){
680 timeTaken = (res.events[i].ctime - res.events[i + 1].ctime).toFixed(4);
681 }
682 var red = "";
683 if(res.events[i].type == 'error'){
684 red = ' class="wfWarn" ';
685 }
686 html += '<div ' + red + 'class="wfALogEntry"><span ' + red + 'class="wfALogTime">[' + res.events[i].type + '&nbsp;:&nbsp;' + timeTaken + '&nbsp;:&nbsp;' + res.events[i].timeAgo + ' ago]</span>&nbsp;' + res.events[i].msg + "</div>";
687 }
688 jQuery('#wfActivity').html(html);
689 } else {
690 jQuery('#wfActivity').html("<p>&nbsp;&nbsp;No activity to report yet. Please complete your first scan.</p>");
691 }
692 });
693 },
694 emailActivityLog: function(){
695 this.colorbox('400px', 'Email Wordfence Activity Log', "Enter the email address you would like to send the Wordfence activity log to. Note that the activity log may contain thousands of lines of data. This log is usually only sent to a member of the Wordfence support team. It also contains your PHP configuration from the phpinfo() function for diagnostic data.<br /><br /><input type='text' value='support@wordfence.com' size='20' id='wfALogRecip' /><input type='button' value='Send' onclick=\"WFAD.completeEmailActivityLog();\" /><input type='button' value='Cancel' onclick='jQuery.colorbox.close();' /><br /><br />");
696 },
697 completeEmailActivityLog: function(){
698 jQuery.colorbox.close();
699 var email = jQuery('#wfALogRecip').val();
700 if(! /^[^@]+@[^@]+$/.test(email)){
701 alert("Please enter a valid email address.");
702 return;
703 }
704 var self = this;
705 this.ajax('wordfence_sendActivityLog', { email: jQuery('#wfALogRecip').val() }, function(res){
706 if(res.ok){
707 self.colorbox('400px', 'Activity Log Sent', "Your Wordfence activity log was sent to " + email + "<br /><br /><input type='button' value='Close' onclick='jQuery.colorbox.close();' /><br /><br />");
708 }
709 });
710 },
711 reloadActivityData: function(){
712 jQuery('#wfActivity').html('<div class="wfLoadingWhite32"></div>'); //&nbsp;<br />&nbsp;<br />&nbsp;<br />&nbsp;<br />&nbsp;<br />&nbsp;<br />&nbsp;<br />&nbsp;<br />&nbsp;<br />&nbsp;<br />
713 this.completeLiveTabSwitch();
714 },
715 switchToSummaryTab: function(elem){
716 jQuery('.wfTab1').removeClass('selected');
717 jQuery(elem).addClass('selected');
718 jQuery('.wfDataPanel').hide();
719 jQuery('#wfSummaryTables').fadeIn();
720 },
721 switchIssuesTab: function(elem, type){
722 jQuery('.wfTab2').removeClass('selected');
723 jQuery('.wfIssuesContainer').hide();
724 jQuery(elem).addClass('selected');
725 this.visibleIssuesPanel = type;
726 jQuery('#wfIssues_' + type).fadeIn();
727 },
728 switchTab: function(tabElement, tabClass, contentClass, selectedContentID, callback){
729 jQuery('.' + tabClass).removeClass('selected');
730 jQuery(tabElement).addClass('selected');
731 jQuery('.' + contentClass).hide().html('<div class="wfLoadingWhite32"></div>');
732 var func = function(){};
733 if(callback){
734 func = function(){ callback(); };
735 }
736 jQuery('#' + selectedContentID).fadeIn(func);
737 },
738 activityTabChanged: function(){
739 var mode = jQuery('.wfDataPanel:visible')[0].id.replace('wfActivity_','');
740 if(! mode){ return; }
741 this.activityMode = mode;
742 this.reloadActivities();
743 },
744 reloadActivities: function(){
745 jQuery('#wfActivity_' + this.activityMode).html('<div class="wfLoadingWhite32"></div>');
746 this.newestActivityTime = 0;
747 this.updateTicker(true);
748 },
749 staticTabChanged: function(){
750 var mode = jQuery('.wfDataPanel:visible')[0].id.replace('wfActivity_','');
751 if(! mode){ return; }
752 this.activityMode = mode;
753
754 var self = this;
755 this.ajax('wordfence_loadStaticPanel', {
756 mode: this.activityMode
757 }, function(res){
758 self.completeLoadStaticPanel(res);
759 });
760 },
761 completeLoadStaticPanel: function(res){
762 var contentElem = '#wfActivity_' + this.activityMode;
763 jQuery(contentElem).empty();
764 if(res.results && res.results.length > 0){
765 var tmpl;
766 if(this.activityMode == 'topScanners' || this.activityMode == 'topLeechers'){
767 tmpl = '#wfLeechersTmpl';
768 } else if(this.activityMode == 'blockedIPs'){
769 tmpl = '#wfBlockedIPsTmpl';
770 } else if(this.activityMode == 'lockedOutIPs'){
771 tmpl = '#wfLockedOutIPsTmpl';
772 } else if(this.activityMode == 'throttledIPs'){
773 tmpl = '#wfThrottledIPsTmpl';
774 } else { return; }
775 jQuery(tmpl).tmpl(res).prependTo(contentElem);
776 this.reverseLookupIPs();
777 } else {
778 if(this.activityMode == 'topScanners' || this.activityMode == 'topLeechers'){
779 jQuery(contentElem).html("No site hits have been logged yet. Check back soon.");
780 } else if(this.activityMode == 'blockedIPs'){
781 jQuery(contentElem).html("No IP addresses have been blocked yet. If you manually block an IP address or if Wordfence automatically blocks one, it will appear here.");
782 } else if(this.activityMode == 'lockedOutIPs'){
783 jQuery(contentElem).html("No IP addresses have been locked out from signing in or using the password recovery system.");
784 } else if(this.activityMode == 'throttledIPs'){
785 jQuery(contentElem).html("No IP addresses have been throttled yet. If an IP address accesses the site too quickly and breaks one of the Wordfence rules, it will appear here.");
786 } else { return; }
787 }
788 },
789 ucfirst: function(str){
790 str = "" + str;
791 return str.charAt(0).toUpperCase() + str.slice(1);
792 },
793 makeIPTrafLink: function(IP){
794 return WordfenceAdminVars.siteBaseURL + '?_wfsf=IPTraf&nonce=' + this.nonce + '&IP=' + encodeURIComponent(IP);
795 },
796 makeDiffLink: function(dat){
797 return WordfenceAdminVars.siteBaseURL + '?_wfsf=diff&nonce=' + this.nonce +
798 '&file=' + encodeURIComponent(this.es(dat['file'])) +
799 '&cType=' + encodeURIComponent(this.es(dat['cType'])) +
800 '&cKey=' + encodeURIComponent(this.es(dat['cKey'])) +
801 '&cName=' + encodeURIComponent(this.es(dat['cName'])) +
802 '&cVersion=' + encodeURIComponent(this.es(dat['cVersion']));
803 },
804 makeViewFileLink: function(file){
805 return WordfenceAdminVars.siteBaseURL + '?_wfsf=view&nonce=' + this.nonce + '&file=' + encodeURIComponent(file);
806 },
807 makeTimeAgo: function(t){
808 var months = Math.floor(t / (86400 * 30));
809 var days = Math.floor(t / 86400);
810 var hours = Math.floor(t / 3600);
811 var minutes = Math.floor(t / 60);
812 if(months > 0){
813 days -= months * 30;
814 return this.pluralize(months, 'month', days, 'day');
815 } else if(days > 0){
816 hours -= days * 24;
817 return this.pluralize(days, 'day', hours, 'hour');
818 } else if(hours > 0) {
819 minutes -= hours * 60;
820 return this.pluralize(hours, 'hour', minutes, 'min');
821 } else if(minutes > 0) {
822 //t -= minutes * 60;
823 return this.pluralize(minutes, 'minute');
824 } else {
825 return Math.round(t) + " seconds";
826 }
827 },
828 pluralize: function(m1, t1, m2, t2){
829 if(m1 != 1) {
830 t1 = t1 + 's';
831 }
832 if(m2 != 1) {
833 t2 = t2 + 's';
834 }
835 if(m1 && m2){
836 return m1 + ' ' + t1 + ' ' + m2 + ' ' + t2;
837 } else {
838 return m1 + ' ' + t1;
839 }
840 },
841 blockIP: function(IP, reason){
842 var self = this;
843 this.ajax('wordfence_blockIP', {
844 IP: IP,
845 reason: reason
846 }, function(res){
847 if(res.errorMsg){
848 return;
849 } else {
850 self.reloadActivities();
851 }
852 });
853 },
854 blockIPTwo: function(IP, reason){
855 var self = this;
856 this.ajax('wordfence_blockIP', {
857 IP: IP,
858 reason: reason
859 }, function(res){
860 if(res.errorMsg){
861 return;
862 } else {
863 self.staticTabChanged();
864 }
865 });
866 },
867 unlockOutIP: function(IP){
868 var self = this;
869 this.ajax('wordfence_unlockOutIP', {
870 IP: IP
871 }, function(res){ self.staticTabChanged(); });
872 },
873 unblockIP: function(IP){
874 var self = this;
875 this.ajax('wordfence_unblockIP', {
876 IP: IP
877 }, function(res){ self.staticTabChanged(); });
878 },
879 permBlockIP: function(IP){
880 var self = this;
881 this.ajax('wordfence_permBlockIP', {
882 IP: IP
883 }, function(res){ self.staticTabChanged(); });
884 },
885 makeElemID: function(){
886 return 'wfElemGen' + this.elementGeneratorIter++;
887 },
888 pulse: function(sel){
889 jQuery(sel).fadeIn(function(){
890 setTimeout(function(){ jQuery(sel).fadeOut(); }, 2000);
891 });
892 },
893 saveConfig: function(){
894 var qstr = jQuery('#wfConfigForm').serialize();
895 var self = this;
896 jQuery('.wfSavedMsg').hide();
897 jQuery('.wfAjax24').show();
898 this.ajax('wordfence_saveConfig', qstr, function(res){
899 jQuery('.wfAjax24').hide();
900 if(res.ok){
901 if(res['paidKeyMsg']){
902 self.colorbox('400px', "Congratulations! You have been upgraded to Premium Scanning.", "You have upgraded to a Premium API key. Once this page reloads, you can choose which premium scanning options you would like to enable and then click save. Click the button below to reload this page now.<br /><br /><center><input type='button' name='wfReload' value='Reload page and enable Premium options' onclick='window.location.reload();' /></center>");
903 return;
904 } else if(res['reload'] == 'reload' || WFAD.reloadConfigPage){
905 self.colorbox('400px', "Please reload this page", "You selected a config option that requires a page reload. Click the button below to reload this page to update the menu.<br /><br /><center><input type='button' name='wfReload' value='Reload page' onclick='window.location.reload();' /></center>");
906 return;
907 } else {
908 self.pulse('.wfSavedMsg');
909 }
910 } else if(res.errorMsg){
911 return;
912 } else {
913 self.colorbox('400px', 'An error occurred', 'We encountered an error trying to save your changes.');
914 }
915 });
916 },
917 changeSecurityLevel: function(){
918 var level = jQuery('#securityLevel').val();
919 for(var k in WFSLevels[level].checkboxes){
920 if(k != 'liveTraf_ignorePublishers'){
921 jQuery('#' + k).prop("checked", WFSLevels[level].checkboxes[k]);
922 }
923 }
924 for(var k in WFSLevels[level].otherParams){
925 if(! /^(?:apiKey|securityLevel|alertEmails|liveTraf_ignoreUsers|liveTraf_ignoreIPs|liveTraf_ignoreUA|liveTraf_hitsMaxSize|maxMem)$/.test(k)){
926 jQuery('#' + k).val(WFSLevels[level].otherParams[k]);
927 }
928 }
929 },
930 clearAllBlocked: function(op){
931 if(op == 'blocked'){
932 body = "Are you sure you want to clear all blocked IP addresses and allow visitors from those addresses to access the site again?";
933 } else if(op == 'locked'){
934 body = "Are you sure you want to clear all locked IP addresses and allow visitors from those addresses to sign in again?";
935 } else {
936 return;
937 }
938 this.colorbox('450px', "Please confirm", body +
939 '<br /><br /><center><input type="button" name="but1" value="Cancel" onclick="jQuery.colorbox.close();" />&nbsp;&nbsp;&nbsp;' +
940 '<input type="button" name="but2" value="Yes I\'m sure" onclick="jQuery.colorbox.close(); WFAD.confirmClearAllBlocked(\'' + op + '\');"><br />');
941 },
942 confirmClearAllBlocked: function(op){
943 var self = this;
944 this.ajax('wordfence_clearAllBlocked', { op: op }, function(res){
945 self.staticTabChanged();
946 });
947 },
948 setOwnCountry: function(code){
949 this.ownCountry = (code + "").toUpperCase();
950 },
951 addBlockedCountry: function(code, name){
952 code = (code + "").toUpperCase();
953 if(code == this.ownCountry){
954 this.colorbox('400px', "Please confirm blocking yourself", "You are about to block your own country. This could lead to you being locked out. Please make sure that your user profile on this machine has a current and valid email address and make sure you know what it is. That way if you are locked out, you can send yourself an unlock email. If you're sure you want to block your own country, click 'Confirm' below, otherwise click 'Cancel'.<br />" +
955 '<input type="button" name="but1" value="Confirm" onclick="jQuery.colorbox.close(); WFAD.addBlockedCountryConfirm(\'' + code + '\',\'' + name + '\');" />&nbsp;<input type="button" name="but1" value="Cancel" onclick="jQuery.colorbox.close();" />');
956 } else {
957 this.addBlockedCountryConfirm(code, name);
958 }
959 },
960 addBlockedCountryConfirm: function(code, name){
961 var exists = false;
962 for(var i = 0; i < this.blockedCountriesPending.length; i++){
963 if(this.blockedCountriesPending[i][0] == code){
964 return;
965 }
966 }
967 this.blockedCountriesPending.push([code, name]);
968 this.drawBlockedCountries();
969 },
970 loadBlockedCountries: function(str){
971 var codes = str.split(',');
972 var self = this;
973 jQuery("#wfBlockedCountry > option").each(function() {
974 for(var i = 0; i < codes.length; i++){
975 if(codes[i] == this.value){
976 self.addBlockedCountryConfirm(this.value, this.text);
977 }
978 }
979 });
980 this.drawBlockedCountries();
981 },
982 drawBlockedCountries: function(){
983 var html = "";
984 var self = this;
985 if(this.blockedCountriesPending.length < 1){
986 jQuery('#wfCountryList').html('<span style="color: #999;">There are no countries currently blocked.</span>');
987 return;
988 }
989 jQuery("#wfBlockedCountry > option").each(function() {
990 for(var i = 0; i < self.blockedCountriesPending.length; i++){
991 if(self.blockedCountriesPending[i][0] == this.value){
992 html += "Blocking: " + this.text + '&nbsp;&nbsp;<a href="#" onclick="WFAD.removeBlockedCountry(\'' + this.value + '\'); return false;">[remove]</a><br />';
993 }
994 }
995 });
996 jQuery('#wfCountryList').html(html);
997
998 },
999 removeBlockedCountry: function(code){
1000 var newArr = [];
1001 for(var i = 0; i < this.blockedCountriesPending.length; i++){
1002 if(this.blockedCountriesPending[i][0] != code){
1003 newArr.push(this.blockedCountriesPending[i]);
1004 }
1005 }
1006 this.blockedCountriesPending = newArr;
1007 this.drawBlockedCountries();
1008 },
1009 saveCountryBlocking: function(){
1010 var action = jQuery('#wfBlockAction').val();
1011 var redirURL = jQuery('#wfRedirURL').val();
1012 if(action == 'redir' && (! /^https?:\/\/[^\/]+/i.test(redirURL))){
1013 this.colorbox('400px', "Please enter a URL for redirection", "You have chosen to redirect blocked countries to a specific page. You need to enter a URL in the text box provided that starts with http:// or https://");
1014 return;
1015 }
1016 var loggedInBlocked = jQuery('#wfLoggedInBlocked').is(':checked') ? '1' : '0';
1017 var loginFormBlocked = jQuery('#wfLoginFormBlocked').is(':checked') ? '1' : '0';
1018 var codesArr = [];
1019 for(var i = 0; i < this.blockedCountriesPending.length; i++){
1020 codesArr.push(this.blockedCountriesPending[i][0]);
1021 }
1022 var codes = codesArr.join(',');
1023 jQuery('.wfAjax24').show();
1024 var self = this;
1025 this.ajax('wordfence_saveCountryBlocking', {
1026 blockAction: action,
1027 redirURL: redirURL,
1028 loggedInBlocked: loggedInBlocked,
1029 loginFormBlocked: loginFormBlocked,
1030 codes: codes
1031 }, function(res){
1032 jQuery('.wfAjax24').hide();
1033 self.pulse('.wfSavedMsg');
1034 });
1035 },
1036 paidUsersOnly: function(msg){
1037 var pos = jQuery('#paidWrap').position();
1038 var width = jQuery('#paidWrap').width();
1039 var height = jQuery('#paidWrap').height();
1040 jQuery('<div style="position: absolute; left: ' + pos.left + 'px; top: ' + pos.top + 'px; background-color: #FFF; width: ' + width + 'px; height: ' + height + 'px;"><div class="paidInnerMsg">' + msg + ' <a href="https://www.wordfence.com/choose-a-wordfence-membership-type/?s2-ssl=yes" target="_blank">Click here to upgrade and gain access to this feature.</div></div>').insertAfter('#paidWrap').fadeTo(10000, 0.7);
1041 },
1042 sched_modeChange: function(){
1043 var self = this;
1044 if(jQuery('#schedMode').val() == 'auto'){
1045 jQuery('.wfSchedCheckbox').attr('disabled', true);
1046 } else {
1047 jQuery('.wfSchedCheckbox').attr('disabled', false);
1048 }
1049 },
1050 sched_shortcut: function(mode){
1051 if(jQuery('#schedMode').val() == 'auto'){
1052 this.colorbox('400px', 'Change the scan mode', "You need to change the scan mode to manually scheduled scans if you want to select scan times.");
1053 return;
1054 }
1055 jQuery('.wfSchedCheckbox').prop('checked', false);
1056 if(this.schedStartHour === false){
1057 this.schedStartHour = Math.floor((Math.random()*24));
1058 } else {
1059 this.schedStartHour++;
1060 if(this.schedStartHour > 23){
1061 this.schedStartHour = 0;
1062 }
1063 }
1064 if(mode == 'onceDaily'){
1065 for(var i = 0; i <= 6; i++){
1066 jQuery('#wfSchedDay_' + i + '_' + this.schedStartHour).attr('checked', true);
1067 }
1068 } else if(mode == 'twiceDaily'){
1069 var secondHour = this.schedStartHour + 12;
1070 if(secondHour >= 24){ secondHour = secondHour - 24; }
1071 for(var i = 0; i <= 6; i++){
1072 jQuery('#wfSchedDay_' + i + '_' + this.schedStartHour).attr('checked', true);
1073 jQuery('#wfSchedDay_' + i + '_' + secondHour).attr('checked', true);
1074 }
1075 } else if(mode == 'oddDaysWE'){
1076 var startDay = Math.floor((Math.random()));
1077 jQuery('#wfSchedDay_1_' + this.schedStartHour).attr('checked', true);
1078 jQuery('#wfSchedDay_3_' + this.schedStartHour).attr('checked', true);
1079 jQuery('#wfSchedDay_5_' + this.schedStartHour).attr('checked', true);
1080 jQuery('#wfSchedDay_6_' + this.schedStartHour).attr('checked', true);
1081 jQuery('#wfSchedDay_0_' + this.schedStartHour).attr('checked', true);
1082 } else if(mode == 'weekends'){
1083 var startDay = Math.floor((Math.random()));
1084 jQuery('#wfSchedDay_6_' + this.schedStartHour).attr('checked', true);
1085 jQuery('#wfSchedDay_0_' + this.schedStartHour).attr('checked', true);
1086 } else if(mode == 'every6hours'){
1087 for(var i = 0; i <= 6; i++){
1088 for(var hour = this.schedStartHour; hour < this.schedStartHour + 24; hour = hour + 6){
1089 var displayHour = hour;
1090 if(displayHour >= 24){ displayHour = displayHour - 24; }
1091 jQuery('#wfSchedDay_' + i + '_' + displayHour).attr('checked', true);
1092 }
1093 }
1094 }
1095
1096 },
1097 sched_save: function(){
1098 var schedMode = jQuery('#schedMode').val();
1099 var schedule = [];
1100 for(var day = 0; day <= 6; day++){
1101 var hours = [];
1102 for(var hour = 0; hour <= 23; hour++){
1103 var elemID = '#wfSchedDay_' + day + '_' + hour;
1104 hours[hour] = jQuery(elemID).is(':checked') ? '1' : '0';
1105 }
1106 schedule[day] = hours.join(',');
1107 }
1108 scheduleTxt = schedule.join('|');
1109 var self = this;
1110 this.ajax('wordfence_saveScanSchedule', {
1111 schedMode: schedMode,
1112 schedTxt: scheduleTxt
1113 }, function(res){
1114 jQuery('#wfScanStartTime').html(res.nextStart);
1115 jQuery('.wfAjax24').hide();
1116 self.pulse('.wfSaveMsg');
1117 });
1118 }
1119 };
1120 window['WFAD'] = window['wordfenceAdmin'];
1121 }
1122 jQuery(function(){
1123 wordfenceAdmin.init();
1124 });
1125