'
);
},
promptToRepairFileDone: function(issueID, dontPromptAgain) {
if (dontPromptAgain) {
if (window.localStorage) {
window.localStorage.setItem('wf-repair-file-sudo', (new Date().getTime() + 86400000));
}
}
this.repairFile(issueID);
},
repairFile: function(issueID) {
var self = this;
self.colorboxClose();
this.restoreFile(issueID, function(res) {
if (res.ok) {
var issueElement = $('.wf-issue[data-issue-id=' + parseInt(issueID, 10) + ']');
issueElement.remove();
self.updateIssueCounts(res.issueCounts);
self.repositionSiteCleaningCallout();
self.updateBulkButtons();
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("Success restoring file"), sprintf(__("The file %s was successfully restored."), res.file));
}
else if (res.errorMsg) {
self.colorboxError(res.errorMsg, res.tokenInvalid);
}
});
},
deleteDatabaseOption: function(issueID) {
var self = this;
this.ajax('wordfence_deleteDatabaseOption', {
issueID: issueID
}, function(res) {
self.doneDeleteDatabaseOption(res);
});
},
doneDeleteDatabaseOption: function(res) {
var cb = false;
var self = this;
if (res.ok) {
this.loadIssues(function() {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("Success removing option"), sprintf(__("The option %s was successfully removed."), res.option_name));
});
} else if (res.cerrorMsg) {
this.loadIssues(function() {
WFAD.colorboxError(res.cerrorMsg, res.tokenInvalid);
});
}
},
useRecommendedHowGetIPs: function(issueID) {
var self = this;
this.ajax('wordfence_misconfiguredHowGetIPsChoice', {
issueID: issueID,
choice: 'yes'
}, function(res) {
if (res.ok) {
jQuery('#wordfenceMisconfiguredHowGetIPsNotice').fadeOut();
self.loadIssues(function() {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("Success updating option"), __("The 'How does Wordfence get IPs' option was successfully updated to the recommended value."));
});
} else if (res.cerrorMsg) {
self.loadIssues(function() {
WFAD.colorboxError(res.cerrorMsg, res.tokenInvalid);
});
}
});
},
fixFPD: function(issueID) {
var self = this;
var title = __("Full Path Disclosure");
issueID = parseInt(issueID);
this.ajax('wordfence_checkHtaccess', {}, function(res) {
if (res.ok) {
self.colorboxModalHTML((self.isSmallScreen ? '300px' : '400px'), title, __('We are about to change your .htaccess file. Please make a backup of this file before proceeding.')
+ ' '
+ '' + __('Click here to download a backup copy of your .htaccess file now') + '
');
} else if (res.nginx) {
self.colorboxModalHTML((self.isSmallScreen ? '300px' : '400px'), title, __('You are using an Nginx web server and using a FastCGI processor like PHP5-FPM. You will need to manually modify your php.ini to disable display_error'));
} else if (res.err) {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("We encountered a problem"), sprintf(__("We can't modify your .htaccess file for you because: %s"), res.err));
}
});
},
fixFPD_WriteHtAccess: function(issueID) {
var self = this;
self.colorboxClose();
this.ajax('wordfence_fixFPD', {
issueID: issueID
}, function(res) {
if (res.ok) {
self.loadIssues(function() {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("File restored OK"), __("The Full Path disclosure issue has been fixed"));
});
} else {
self.loadIssues(function() {
WFAD.colorboxError(res.cerrorMsg, res.tokenInvalid);
});
}
});
},
hideFile: function(issueID, callback) {
WFAD.ajax('wordfence_checkHtaccess', {}, function(checkRes) {
if (checkRes.ok) {
WFAD.colorboxModalHTML((WFAD.isSmallScreen ? '300px' : '400px'), __('.htaccess change'), __('We are about to change your .htaccess file. Please make a backup of this file before proceeding.')
+ ' '
+ '' + __('Click here to download a backup copy of your .htaccess file now') + ''
+ '
'
);
$('#dlButton').on('click', function(e) {
$('#wfFPDNextBut').prop('disabled', false);
});
$('#wfFPDNextBut').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
WFAD.ajax('wordfence_hideFileHtaccess', {
issueID: issueID
}, function(res) {
WFAD.colorboxClose();
typeof callback === 'function' && callback(res);
});
});
}
else if (checkRes.nginx) {
WFAD.colorboxModal((WFAD.isSmallScreen ? '300px' : '400px'), __('Unable to automatically hide file'), __('You are using an Nginx web server and using a FastCGI processor like PHP5-FPM. You will need to manually delete or hide those files.'));
}
else if (checkRes.err) {
WFAD.colorboxModal((WFAD.isSmallScreen ? '300px' : '400px'), __("We encountered a problem"), sprintf(__("We can't modify your .htaccess file for you because: %s"), res.err));
}
});
},
restoreFile: function(issueID, callback) {
this.ajax('wordfence_restoreFile', {
issueID: issueID
}, function(res) {
if (res.needsCredentials) {
document.location.href = res.redirect;
}
else {
typeof callback === 'function' && callback(res);
}
});
},
disableDirectoryListing: function(issueID) {
var self = this;
var title = "Disable Directory Listing";
issueID = parseInt(issueID);
this.ajax('wordfence_checkHtaccess', {}, function(res) {
if (res.ok) {
self.colorboxModalHTML((self.isSmallScreen ? '300px' : '400px'), title, __('We are about to change your .htaccess file. Please make a backup of this file before proceeding.')
+ ' '
+ '' + __('Click here to download a backup copy of your .htaccess file now') + '' +
'
' +
'');
} else if (res.nginx) {
self.colorboxModalHTML((self.isSmallScreen ? '300px' : '400px'), __("You are using Nginx as your web server. You'll need to disable autoindexing in your nginx.conf. See the Nginx docs for more info on how to do this."));
} else if (res.err) {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("We encountered a problem"), sprintf(__("We can't modify your .htaccess file for you because: %s"), res.err));
}
});
},
confirmDisableDirectoryListing: function(issueID) {
var self = this;
this.colorboxClose();
this.ajax('wordfence_disableDirectoryListing', {
issueID: issueID
}, function(res) {
if (res.ok) {
self.loadIssues(function() {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("Directory Listing Disabled"), __("Directory listing has been disabled on your server."));
});
} else {
//self.loadIssues(function() {
// self.colorbox('400px', 'An error occurred', res.errorMsg);
//});
}
});
},
deleteIssue: function(id) {
var self = this;
this.ajax('wordfence_deleteIssue', {id: id}, function(res) {
self.loadIssues();
});
},
updateIssueStatus: function(id, st, callback) {
this.ajax('wordfence_updateIssueStatus', {id: id, 'status': st}, function(res) {
typeof callback === 'function' && callback(res);
});
},
es: function(val) {
if (val) {
return val;
} else {
return "";
}
},
noQuotes: function(str) {
return str.replace(/"/g, '"').replace(/\'/g, '');
},
commify: function(num) {
return ("" + num).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
},
switchToLiveTab: function(elem) {
jQuery('.wfTab1').removeClass('selected');
jQuery(elem).addClass('selected');
jQuery('.wfDataPanel').hide();
var self = this;
jQuery('#wfActivity').fadeIn(function() {
self.completeLiveTabSwitch();
});
},
completeLiveTabSwitch: function() {
this.ajax('wordfence_loadActivityLog', {}, function(res) {
var html = '';
if (res.events && res.events.length > 0) {
jQuery('#wfActivity').empty();
for (var i = 0; i < res.events.length; i++) {
var timeTaken = '0.0000';
if (res.events[i + 1]) {
timeTaken = (res.events[i].ctime - res.events[i + 1].ctime).toFixed(4);
}
var red = "";
if (res.events[i].type == 'error') {
red = ' class="wfWarn" ';
}
html += '
" + __('No activity to report yet. Please complete your first scan.') + "
");
}
});
},
emailActivityLog: function() {
this.colorboxModalHTML((this.isSmallScreen ? '300px' : '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.") + "
");
},
completeEmailActivityLog: function() {
WFAD.colorboxClose();
var email = jQuery('#wfALogRecip').val();
if (!/^[^@]+@[^@]+$/.test(email)) {
alert(__("Please enter a valid email address."));
return;
}
var self = this;
this.ajax('wordfence_sendActivityLog', {email: jQuery('#wfALogRecip').val()}, function(res) {
if (res.ok) {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __('Activity Log Sent'), sprintf(__("Your Wordfence activity log was sent to %s"), email));
}
});
},
reloadActivityData: function() {
jQuery('#wfActivity').html(''); //
this.completeLiveTabSwitch();
},
switchToSummaryTab: function(elem) {
jQuery('.wfTab1').removeClass('selected');
jQuery(elem).addClass('selected');
jQuery('.wfDataPanel').hide();
jQuery('#wfSummaryTables').fadeIn();
},
switchIssuesTab: function(elem, type) {
jQuery('.wfTab2').removeClass('selected');
jQuery('.wfIssuesContainer').hide();
jQuery(elem).addClass('selected');
this.visibleIssuesPanel = type;
jQuery('#wfIssues_' + type).fadeIn();
},
switchTab: function(tabElement, tabClass, contentClass, selectedContentID, callback) {
jQuery('.' + tabClass).removeClass('selected');
jQuery(tabElement).addClass('selected');
jQuery('.' + contentClass).hide().html('');
var func = function() {
};
if (callback) {
func = function() {
callback();
};
}
jQuery('#' + selectedContentID).fadeIn(func);
},
reloadLiveTraffic: function() {
this.newestActivityTime = 0;
this.updateLiveTraffic(true);
},
ucfirst: function(str) {
str = "" + str;
return str.charAt(0).toUpperCase() + str.slice(1);
},
makeIPTrafLink: function(IP) {
return WordfenceAdminVars.siteBaseURL + '?_wfsf=IPTraf&nonce=' + this.nonce + '&IP=' + encodeURIComponent(IP);
},
getRealFileParameters: function(data) {
if ('realFile' in data) {
return '&realFile=' + encodeURIComponent(this.es(data['realFile'])) + '&realFileToken=' + encodeURIComponent(this.es(data['realFileToken']));
}
else {
return '';
}
},
makeDiffLink: function(dat) {
return WordfenceAdminVars.siteBaseURL + '?_wfsf=diff&nonce=' + this.nonce +
'&file=' + encodeURIComponent(this.es(dat['file'])) +
this.getRealFileParameters(dat) +
'&cType=' + encodeURIComponent(this.es(dat['cType'])) +
'&cKey=' + encodeURIComponent(this.es(dat['cKey'])) +
'&cName=' + encodeURIComponent(this.es(dat['cName'])) +
'&cVersion=' + encodeURIComponent(this.es(dat['cVersion']));
},
makeViewFileLink: function(data) {
return WordfenceAdminVars.siteBaseURL + '?_wfsf=view&nonce=' + this.nonce + '&file=' + encodeURIComponent(data.file) + this.getRealFileParameters(data);
},
makeDownloadFileLink: function(data) {
return WordfenceAdminVars.siteBaseURL + '?_wfsf=download&nonce=' + this.nonce + '&file=' + encodeURIComponent(data.file) + this.getRealFileParameters(data);
},
makeViewOptionLink: function(option, siteID) {
return WordfenceAdminVars.siteBaseURL + '?_wfsf=viewOption&nonce=' + this.nonce + '&option=' + encodeURIComponent(option) + '&site_id=' + encodeURIComponent(siteID);
},
parseHashes: function() {
var hashes = window.location.hash.replace('%23', '#');
var splitHashes = hashes.split('#');
var result = [];
for (var i = 0; i < splitHashes.length; i++) {
if (splitHashes[i].length > 0) {
result.push(splitHashes[i]);
}
}
return result;
},
makeTimeAgo: function(t) {
var months = Math.floor(t / (86400 * 30));
var days = Math.floor(t / 86400);
var hours = Math.floor(t / 3600);
var minutes = Math.floor(t / 60);
if (months > 0) {
days -= months * 30;
return this.pluralize(months, 'month', days, 'day');
} else if (days > 0) {
hours -= days * 24;
return this.pluralize(days, 'day', hours, 'hour');
} else if (hours > 0) {
minutes -= hours * 60;
return this.pluralize(hours, 'hour', minutes, 'min');
} else if (minutes > 0) {
//t -= minutes * 60;
return this.pluralize(minutes, 'minute');
} else {
return Math.round(t) + " seconds";
}
},
pluralize: function(m1, t1, m2, t2) {
if (m1 != 1) {
t1 = t1 + 's';
}
if (m2 != 1) {
t2 = t2 + 's';
}
if (m1 && m2) {
return m1 + ' ' + t1 + ' ' + m2 + ' ' + t2;
} else {
return m1 + ' ' + t1;
}
},
isValidIP: function(ip) {
if (!ip) {
return false;
}
ip = ip.replace(/ /g, '');
if (ip.match(/^(?:\d{1,3}(?:\.|$)){4}/)) { //IPv4
var octets = ip.split('.');
if (octets.length != 4) {
return false;
}
for (var i = 0; i < octets.length; i++) {
if (parseInt(octets[i]) > 255) {
return false;
}
}
return !!this.inet_pton(ip);
}
else if (ip.match(/^((?:[\da-f]{1,4}(?::|)){0,8})(::)?((?:[\da-f]{1,4}(?::|)){0,8})$/i)) { //IPv6
if (ip == '::') {
return true;
}
var colonCount = ip.split(':').length - 1;
var doubleColonPos = ip.indexOf('::');
if (doubleColonPos > -1) {
var expansionLength = ((doubleColonPos == 0 || doubleColonPos == ip.length - 2) ? 9 : 8) - colonCount;
if (expansionLength == 0) { //Double-colon in a full IPv6 address
return false;
}
var expansion = '';
for (i = 0; i < expansionLength; i++) {
expansion += ':0000';
}
ip = ip.replace('::', expansion + ':');
ip = ip.replace(/(?:^\:|\:$)/, '', ip);
}
var ipGroups = ip.split(':');
var ipBin = '';
for (i = 0; i < ipGroups.length; i++) {
var group = ipGroups[i];
if (group.length > 4 || group.length == 0) {
return false;
}
group = ("0000" + group).slice(-4);
var b1 = parseInt(group.slice(0, 2), 16);
var b2 = parseInt(group.slice(-2), 16);
if (isNaN(b1) || isNaN(b2)) {
return false;
}
ipBin += String.fromCharCode(b1) + String.fromCharCode(b2);
}
return ipBin.length == 16 ? true : false;
}
return false;
},
parseIPRange: function(range) {
if (!range) {
return false;
}
range = range.replace(/ /g, '');
range = range.replace(/[\u2013-\u2015]/g, '-'); //Non-hyphen dashes to hyphen
if (range && /^[^\-]+\-[^\-]+$/.test(range)) {
var count = 1;
var countOverflow = false;
var ips = range.split('-');
var ip1 = this.inet_pton(ips[0]);
var ip2 = this.inet_pton(ips[1]);
if (ip1 === false || !this.isValidIP(ips[0]) || ip2 === false || !this.isValidIP(ips[1])) {
return false;
}
//Both to 16-byte binary strings
var binStart = ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" + ip1).slice(-16);
var binEnd = ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" + ip2).slice(-16);
for (var i = 0; i < binStart.length; i++) {
var n0 = binStart.charCodeAt(i);
var n1 = binEnd.charCodeAt(i);
if (i < 11 && n1 - n0 > 0) { //Based on Number.MAX_SAFE_INTEGER, which equals 2 ^ 53 - 1. Any of the first 9 bytes and part of the 10th that add to the range will put us over that
countOverflow = true;
break;
}
else if (i < 11 && n1 - n0 < 0) {
return false;
}
count += (n1 - n0) << (8 * (15 - i));
if (count < 1) {
return false;
}
}
return {start: ip1, end: ip2, count: count, countOverflow: countOverflow};
}
else if (range && /^[^\/]+\/\d+$/.test(range)) {
var count = 1;
var countOverflow = false;
var components = range.split('/');
var ip = this.inet_pton(components[0]);
var bits = parseInt(components[1]);
if (ip === false || !this.isValidIP(components[0])) {
return false;
}
var binIP = ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" + ip).slice(-16);
if (binIP.slice(12) === "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff") {
if (bits < 1 || bits > 32) {
return false;
}
}
else {
if (bits < 1 || bits > 128) {
return false;
}
}
if (bits >= 53) {
countOverflow = true;
count = Math.pow(2, 53) - 1; /* Number.MAX_SAFE_INTEGER is unavailable in IE */
}
else {
count = Math.pow(2, bits);
}
return {ip: ip, bits: bits, count: count, countOverflow: countOverflow};
}
return false;
},
calcRangeTotal: function() {
var range = jQuery('#ipRange').val();
if (!range) {
return;
}
range = range.replace(/ /g, '');
range = range.replace(/[\u2013-\u2015]/g, '-'); //Non-hyphen dashes to hyphen
if (range && /^[^\-]+\-[^\-]+$/.test(range)) {
var count = 1;
var countOverflow = false;
var badRange = false;
var badIP = false;
var ips = range.split('-');
var ip1 = this.inet_pton(ips[0]);
var ip2 = this.inet_pton(ips[1]);
if (ip1 === false || ip2 === false) {
badIP = true;
}
else {
//Both to 16-byte binary strings
var binStart = ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" + ip1).slice(-16);
var binEnd = ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" + ip2).slice(-16);
for (var i = 0; i < binStart.length; i++) {
var n0 = binStart.charCodeAt(i);
var n1 = binEnd.charCodeAt(i);
if (i < 11 && n1 - n0 > 0) { //Based on Number.MAX_SAFE_INTEGER, which equals 2 ^ 53 - 1. Any of the first 9 bytes and part of the 10th that add to the range will put us over that
countOverflow = true;
break;
}
else if (i < 11 && n1 - n0 < 0) {
badRange = true;
break;
}
count += (n1 - n0) << (8 * (15 - i));
if (count < 1) {
badRange = true;
break;
}
}
}
if (badIP) {
jQuery('#wfShowRangeTotal').html("Invalid IP entered.");
return;
}
else if (badRange) {
jQuery('#wfShowRangeTotal').html("Invalid. Starting IP is greater than ending IP.");
return;
}
else if (countOverflow) {
jQuery('#wfShowRangeTotal').html("Valid: >281474976710656 addresses in range.");
return;
}
jQuery('#wfShowRangeTotal').html("Valid: " + count + " addresses in range.");
}
else {
jQuery('#wfShowRangeTotal').empty();
}
},
completeWhois: function(res, ret) {
ret = ret === undefined ? false : !!ret;
var self = this;
var rawhtml = "";
var ipRangeTmpl = jQuery("
" +
"" + __('Block This Network') + "" +
"{{html totalStr}}{{if totalStr.indexOf(ipRange) == -1}} (${ipRange}){{/if}}" +
'{{if (totalIPs)}} [' + __('${totalIPs} addresses in this network') + ']{{/if}}' +
"
" + sprintf(__("Use one of these %s codes to log in if you are unable to access your phone. Codes are 16 characters long, plus optional spaces. Each one may be used only once."), res.recoveryCodes.length) + "
";
var recoveryCodeFileContents = __('Cellphone Sign-In Recovery Codes') + " - " + res.homeurl + " (" + res.username + ")\r\n";
recoveryCodeFileContents = recoveryCodeFileContents + "\r\n" + __("Each line of 16 letters and numbers is a single recovery code, with optional spaces for readability. When typing your password, enter \"wf\" followed by the entire code like \"mypassword wf1234 5678 90AB CDEF\". If your site shows a separate prompt for entering a code after entering only your username and password, enter only the code like \"1234 5678 90AB CDEF\". Your recovery codes are:") + "\r\n\r\n";
var splitter = /.{4}/g;
for (var i = 0; i < res.recoveryCodes.length; i++) {
var code = res.recoveryCodes[i];
var chunks = code.match(splitter);
message = message + "
" + __("This will be shown only once. Keep these codes somewhere safe.") + "
";
self.colorboxModalHTML((self.isSmallScreen ? '300px' : '400px'), __("Recovery Codes"), message, {onComplete: function() {
jQuery('#wfTwoFactorDownload').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
saveAs(new Blob([recoveryCodeFileContents], {type: "text/plain;charset=" + document.characterSet}), self.htmlEscape(res.homeurl) + "_" + self.htmlEscape(res.username) + "_recoverycodes.txt");
});
}});
}
}
var updatedTwoFac = jQuery('#wfTwoFacUserTmpl').tmpl({users: [res]});
jQuery('#twoFactorUser-none').remove();
jQuery('#wfTwoFacUsers > table > tbody:last-child').append(updatedTwoFac.find('tbody > tr'));
}
});
},
twoFacActivate: function(userID, code) {
var self = this;
this.ajax('wordfence_twoFacActivate', {
userID: userID,
code: code
}, function(res) {
if (res.ok) {
var updatedTwoFac = jQuery('#wfTwoFacUserTmpl').tmpl({users: [res]});
updatedTwoFac.find('tbody > tr').each(function(index, element) {
jQuery('#' + jQuery(element).attr('id')).replaceWith(element);
});
self.twoFacStatus(__('Cellphone Sign-in activated for user.'));
}
});
},
delTwoFac: function(userID) {
this.ajax('wordfence_twoFacDel', {
userID: userID
}, function(res) {
if (res.ok) {
jQuery('#twoFactorUser-' + res.userID).fadeOut(function() {
jQuery(this).remove();
if (jQuery('#wfTwoFacUsers > table > tbody:last-child').children().length == 0) {
jQuery('#wfTwoFacUsers').html(jQuery('#wfTwoFacUserTmpl').tmpl({users: []}));
}
});
}
});
},
loadTwoFactor: function() {
this.ajax('wordfence_loadTwoFactor', {}, function(res) {
jQuery('#wfTwoFacUsers').html(jQuery('#wfTwoFacUserTmpl').tmpl(res));
});
},
getQueryParam: function(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.search);
if (results == null) {
return "";
} else {
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
},
inet_aton: function(dot) {
var d = dot.split('.');
return ((((((+d[0]) * 256) + (+d[1])) * 256) + (+d[2])) * 256) + (+d[3]);
},
inet_ntoa: function(num) {
var d = num % 256;
for (var i = 3; i > 0; i--) {
num = Math.floor(num / 256);
d = num % 256 + '.' + d;
}
return d;
},
inet_pton: function(a) {
// discuss at: http://phpjs.org/functions/inet_pton/
// original by: Theriault
// example 1: inet_pton('::');
// returns 1: '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'
// example 2: inet_pton('127.0.0.1');
// returns 2: '\x7F\x00\x00\x01'
var r, m, x, i, j, f = String.fromCharCode;
m = a.match(/^(?:\d{1,3}(?:\.|$)){4}/); // IPv4
if (m) {
m = m[0].split('.');
m = f(m[0]) + f(m[1]) + f(m[2]) + f(m[3]);
// Return if 4 bytes, otherwise false.
return m.length === 4 ? m : false;
}
r = /^((?:[\da-f]{1,4}(?::|)){0,8})(::)?((?:[\da-f]{1,4}(?::|)){0,8})$/i;
m = a.match(r); // IPv6
if (m) {
if (a == '::') {
return "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
}
var colonCount = a.split(':').length - 1;
var doubleColonPos = a.indexOf('::');
if (doubleColonPos > -1) {
var expansionLength = ((doubleColonPos == 0 || doubleColonPos == a.length - 2) ? 9 : 8) - colonCount;
var expansion = '';
for (i = 0; i < expansionLength; i++) {
expansion += ':0000';
}
a = a.replace('::', expansion + ':');
a = a.replace(/(?:^\:|\:$)/, '', a);
}
var ipGroups = a.split(':');
var ipBin = '';
for (i = 0; i < ipGroups.length; i++) {
var group = ipGroups[i];
if (group.length > 4) {
return false;
}
group = ("0000" + group).slice(-4);
var b1 = parseInt(group.slice(0, 2), 16);
var b2 = parseInt(group.slice(-2), 16);
if (isNaN(b1) || isNaN(b2)) {
return false;
}
ipBin += f(b1) + f(b2);
}
return ipBin.length == 16 ? ipBin : false;
}
return false; // Invalid IP.
},
inet_ntop: function(a) {
// discuss at: http://phpjs.org/functions/inet_ntop/
// original by: Theriault
// example 1: inet_ntop('\x7F\x00\x00\x01');
// returns 1: '127.0.0.1'
// example 2: inet_ntop('\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1');
// returns 2: '::1'
var i = 0,
m = '',
c = [];
a += '';
if (a.length === 4) { // IPv4
return [
a.charCodeAt(0), a.charCodeAt(1), a.charCodeAt(2), a.charCodeAt(3)].join('.');
} else if (a.length === 16) { // IPv6
for (i = 0; i < 16; i++) {
c.push(((a.charCodeAt(i++) << 8) + a.charCodeAt(i))
.toString(16));
}
return c.join(':')
.replace(/((^|:)0(?=:|$))+:?/g, function(t) {
m = (t.length > m.length) ? t : m;
return t;
})
.replace(m || ' ', '::');
} else { // Invalid length
return false;
}
},
deleteAdminUser: function(issueID) {
var self = this;
this.ajax('wordfence_deleteAdminUser', {
issueID: issueID
}, function(res) {
if (res.ok) {
self.loadIssues(function() {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("Successfully deleted admin"), sprintf(__("The admin user %s was successfully deleted."), res.user_login));
});
} else if (res.errorMsg) {
self.loadIssues(function() {
WFAD.colorboxError(res.errorMsg, res.tokenInvalid);
});
}
});
},
revokeAdminUser: function(issueID) {
var self = this;
this.ajax('wordfence_revokeAdminUser', {
issueID: issueID
}, function(res) {
if (res.ok) {
self.loadIssues(function() {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("Successfully revoked admin"), sprintf(__("All capabilties of admin user %s were successfully revoked."), res.user_login));
});
} else if (res.errorMsg) {
self.loadIssues(function() {
WFAD.colorboxError(res.errorMsg, res.tokenInvalid);
});
}
});
},
acknowledgeAdminUser: function (issueID) {
var self = this;
this.ajax('wordfence_acknowledgeAdminUser', {
issueID: issueID
}, function(res) {
if (res.ok) {
self.loadIssues(function() {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __("Successfully acknowledged admin"), sprintf(__("The admin user %s will no longer show up in future scans."), res.user_login));
});
} else if (res.errorMsg) {
self.loadIssues(function() {
WFAD.colorboxError(res.errorMsg, res.tokenInvalid);
});
}
});
},
windowHasFocus: function() {
if (typeof document.hasFocus === 'function') {
return document.hasFocus();
}
// Older versions of Opera
return this._windowHasFocus;
},
htmlEscape: function(html) {
return String(html)
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(//g, '>');
},
permanentlyBlockAllIPs: function(type) {
var self = this;
this.ajax('wordfence_permanentlyBlockAllIPs', {
type: type
}, function(res) {
$('#wfTabs').find('.wfTab1').eq(0).trigger('click');
});
},
showTimestamp: function(timestamp, serverTime, format) {
serverTime = serverTime === undefined ? new Date().getTime() / 1000 : serverTime;
format = format === undefined ? '${dateTime} (${timeAgo} ago)' : format;
var date = new Date(timestamp * 1000);
return jQuery.tmpl(format, {
dateTime: date.toLocaleDateString() + ' ' + date.toLocaleTimeString(),
timeAgo: this.makeTimeAgo(serverTime - timestamp)
});
},
updateTimeAgo: function() {
var self = this;
jQuery('.wfTimeAgo-timestamp').each(function(idx, elem) {
var el = jQuery(elem);
var testEl = el;
if (typeof jQuery === "function" && testEl instanceof jQuery) {
testEl = testEl[0];
}
var rect = testEl.getBoundingClientRect();
if (!(rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth))) {
return;
}
var timestamp = el.data('wfctime');
if (!timestamp) {
timestamp = el.attr('data-timestamp');
}
var serverTime = self.serverMicrotime;
var format = el.data('wfformat');
if (!format) {
format = el.attr('data-format');
}
el.html(self.showTimestamp(timestamp, serverTime, format));
});
},
wafData: {
whitelistedURLParams: []
},
restoreWAFData: {
whitelistedURLParams: []
},
wafWhitelistedBulkChangeEnabled: function(enabled) {
$('.wf-whitelist-table-bulk-checkbox.wf-option-checkbox.wf-checked').each(function() {
$(this).closest('tr').find('.wf-whitelist-item-enabled.wf-option-checkbox').each(function() {
if (($(this).hasClass('wf-checked') && !enabled) || (!$(this).hasClass('wf-checked') && enabled)) {
var tr = $(this).closest('tr');
if (tr.is(':visible')) {
WFAD.wafWhitelistedChangeEnabled(tr.data('key'), enabled);
}
}
});
})
},
wafWhitelistedChangeEnabled: function(key, enabled) {
$('#waf-whitelisted-urls-wrapper .whitelist-table > tbody > tr[data-key="' + key + '"]').each(function() {
var adding = !!$(this).data('adding');
if (adding) {
WFAD.pendingChanges['whitelistedURLParams']['add'][key]['data']['disabled'] = !enabled ? 1 : 0;
}
else {
if (!(WFAD.pendingChanges['whitelistedURLParams'] instanceof Object)) {
WFAD.pendingChanges['whitelistedURLParams'] = {};
}
if (!(WFAD.pendingChanges['whitelistedURLParams']['enabled'] instanceof Object)) {
WFAD.pendingChanges['whitelistedURLParams']['enabled'] = {};
}
WFAD.pendingChanges['whitelistedURLParams']['enabled'][key] = !!enabled ? 1 : 0;
}
$(this).find('.wf-whitelist-item-enabled.wf-option-checkbox').toggleClass('wf-checked', !!enabled);
});
},
wafWhitelistedBulkDelete: function() {
$('.wf-whitelist-table-bulk-checkbox.wf-option-checkbox.wf-checked').each(function() {
$(this).closest('tr').find('.wf-whitelist-item-enabled.wf-option-checkbox').each(function() {
var tr = $(this).closest('tr');
if (tr.is(':visible')) {
WFAD.wafWhitelistedDelete(tr.data('key'));
}
});
});
},
wafWhitelistedDelete: function(key) {
$('#waf-whitelisted-urls-wrapper .whitelist-table > tbody > tr[data-key="' + key + '"]').each(function() {
var adding = !!$(this).data('adding');
if (adding) {
delete WFAD.pendingChanges['whitelistedURLParams']['add'][key];
}
else {
if (!(WFAD.pendingChanges['whitelistedURLParams'] instanceof Object)) {
WFAD.pendingChanges['whitelistedURLParams'] = {};
}
if (!(WFAD.pendingChanges['whitelistedURLParams']['delete'] instanceof Object)) {
WFAD.pendingChanges['whitelistedURLParams']['delete'] = {};
}
WFAD.pendingChanges['whitelistedURLParams']['delete'][key] = 1;
}
for (var i = 0; i < WFAD.wafData.whitelistedURLParams.length; i++) {
var testKey = WFAD.wafData.whitelistedURLParams[i].path + '|' + WFAD.wafData.whitelistedURLParams[i].paramKey;
if (testKey == key) {
WFAD.wafData.whitelistedURLParams.splice(i, 1);
break;
}
}
});
},
wafConfigPageRender: function() {
WFAD.wafData.ruleCount = 0;
if (WFAD.wafData.rules) {
WFAD.wafData.ruleCount = Object.keys(WFAD.wafData.rules).length;
}
var whitelistedIPsEl = $('#waf-whitelisted-urls-tmpl').tmpl(WFAD.wafData);
$('#waf-whitelisted-urls-wrapper').html(whitelistedIPsEl);
var rulesEl = $('#waf-rules-tmpl').tmpl(WFAD.wafData);
$('#waf-rules-wrapper').html(rulesEl);
$('#waf-show-all-rules-button').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
$('#waf-rules-wrapper').addClass('wf-show-all');
});
if (WFAD.wafData['rulesLastUpdated']) {
var date = new Date(WFAD.wafData['rulesLastUpdated'] * 1000);
WFAD.renderWAFRulesLastUpdated(date);
}
$(window).trigger('wordfenceWAFConfigPageRender');
},
renderWAFRulesLastUpdated: function(date) {
var dateString = date.toString();
if (date.toLocaleString) {
dateString = date.toLocaleString();
}
$('#waf-rules-last-updated').text(sprintf(__('Last Updated: %s'), dateString))
.css({
'opacity': 0
})
.animate({
'opacity': 1
}, 500);
},
renderWAFRulesNextUpdate: function(date) {
var dateString = date.toString();
if (date.toLocaleString) {
dateString = date.toLocaleString();
}
$('#waf-rules-next-update').text(sprintf(__('Next Update Check: %s'), dateString))
.css({
'opacity': 0
})
.animate({
'opacity': 1
}, 500);
},
wafUpdateRules: function(onSuccess) {
var self = this;
this.ajax('wordfence_updateWAFRules', {}, function(res) {
self.wafData = res;
self.restoreWAFData.rules = res.rules;
self.restoreWAFData.rulesLastUpdated = res.rulesLastUpdated;
self.wafConfigPageRender();
if (self.wafData['updated']) {
if (!self.wafData['isPaid']) {
self.colorboxModalHTML((self.isSmallScreen ? '300px' : '400px'), __('Rules Updated'), __('Your rules have been updated successfully. You are currently using the free version of Wordfence. Upgrade to Wordfence premium to have your rules updated automatically as new threats emerge. Click here to purchase a premium license. Note: Your rules will still update every 30 days as a free user.'));
} else {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __('Rules Updated'), __('Your rules have been updated successfully.'));
}
}
else {
if (self.wafData['failure'] == 'ratelimit') {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __('Rule Update Failed'), __('No rules were updated. Your website has reached the maximum number of rule update requests. Please try again later.'));
}
else if (self.wafData['failure'] == 'unreachable') {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __('Rule Update Failed'), __('No rules were updated. Please verify your website can reach the Wordfence servers.'));
}
else {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __('Rule Update Failed'), __('No rules were updated. Please verify you have permissions to write to the /wp-content/wflogs directory.'));
}
}
if (typeof onSuccess === 'function') {
return onSuccess.apply(this, arguments);
}
});
},
dateFormat: function(date) {
if (date instanceof Date) {
if (date.toLocaleString) {
return date.toLocaleString();
}
return date.toString();
}
return date;
},
confirmWAFConfigureAutoPrepend: function() {
var self = this;
this.ajax('wordfence_wafConfigureAutoPrepend', {}, function(res) {
self.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __('.htaccess Updated'), __("Your .htaccess has been updated successfully. Please verify your site is functioning normally."));
});
},
updatePendingChanges: function() {
$(window).off('beforeunload', WFAD._unsavedOptionsHandler);
if (Object.keys(WFAD.pendingChanges).length) {
$('#wf-cancel-changes').removeClass('wf-disabled');
$('#wf-save-changes').removeClass('wf-disabled');
$(window).on('beforeunload', WFAD._unsavedOptionsHandler);
}
else {
$('#wf-cancel-changes').addClass('wf-disabled');
$('#wf-save-changes').addClass('wf-disabled');
}
},
_unsavedOptionsHandler: function(e) {
var message = __("You have unsaved changes to your options. If you leave this page, those changes will be lost."); //Only shows on older browsers, newer browsers don't allow message customization
e = e || window.event;
if (e) {
e.returnValue = message; //IE and Firefox
}
return message; //Others
},
setOption: function(key, value, successCallback, failureCallback, failureAfterModal) {
var changes = {};
changes[key] = value;
this.ajax('wordfence_saveOptions', {changes: JSON.stringify(changes), page: WFAD.getParameterByName('page')}, function(res) {
if (res.success) {
typeof successCallback == 'function' && successCallback(res);
}
else {
failureAfterModal = typeof failureAfterModal !== 'undefined' && failureAfterModal;
var modalSettings = {};
if (failureAfterModal)
modalSettings.onClosed = failureCallback;
WFAD.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __('Error Saving Option'), res.error, modalSettings);
if (!failureAfterModal)
typeof failureCallback == 'function' && failureCallback(res);
}
});
},
saveOptions: function(successCallback, failureCallback) {
if (!Object.keys(WFAD.pendingChanges).length) {
return;
}
var self = this;
this.ajax('wordfence_saveOptions', {changes: JSON.stringify(WFAD.pendingChanges), page: WFAD.getParameterByName('page')}, function(res) {
if (res.success) {
typeof successCallback == 'function' && successCallback(res);
}
else {
WFAD.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __('Error Saving Options'), res.error);
typeof failureCallback == 'function' && failureCallback
}
});
},
enableAllOptionsPage: function() {
this.ajax('wordfence_enableAllOptionsPage', {}, function(res) {
if (res.redirect) {
window.location.href = res.redirect;
}
else {
WFAD.colorboxModal((self.isSmallScreen ? '300px' : '400px'), __('Error Enabling All Options Page'), res.error);
}
});
},
getParameterByName: function(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
},
base64_decode: function(s) {
var e = {}, i, b = 0, c, x, l = 0, a, r = '', w = String.fromCharCode, L = s.length;
var A = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for (i = 0; i < 64; i++) {
e[A.charAt(i)] = i;
}
for (x = 0; x < L; x++) {
c = e[s.charAt(x)];
b = (b << 6) + c;
l += 6;
while (l >= 8) {
((a = (b >>> (l -= 8)) & 0xff) || (x < (L - 2))) && (r += w(a));
}
}
return r;
},
base64_encode: function (input) {
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
}
else if (isNaN(chr3)) {
enc4 = 64;
}
output = output + chars.charAt(enc1) + chars.charAt(enc2) + chars.charAt(enc3) + chars.charAt(enc4);
}
return output;
}
};
window['WFAD'] = window['wordfenceAdmin'];
setInterval(function() {
WFAD.updateTimeAgo();
}, 1000);
}
__ = window.wfi18n.__;
sprintf = window.wfi18n.sprintf;
jQuery(function() {
wordfenceAdmin.init();
jQuery(window).on('focus', function() {
if (jQuery('body').hasClass('wordfenceLiveActivityPaused')) {
jQuery('body').removeClass('wordfenceLiveActivityPaused');
}
});
});
$(function() {
$('#wf-mobile-controls').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
$.wfMobileMenu({
menuItems: [
{title: __('Save Changes'), primary: true, disabled: $('#wf-save-changes').hasClass('wf-disabled'), action: function() { $('#wf-save-changes').trigger('click'); }},
{title: __('Cancel Changes'), primary: false, disabled: $('#wf-cancel-changes').hasClass('wf-disabled'), action: function() { $('#wf-cancel-changes').trigger('click'); }},
{title: __('Restore Defaults'), primary: false, disabled: $('#wf-restore-defaults').hasClass('wf-disabled'), action: function() { $('#wf-restore-defaults').trigger('click'); }}
]
});
});
$('#wf-restore-defaults').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
var restoreDefaultsSection = $(this).data('restoreDefaultsSection');
var prompt = $('#wfTmpl_restoreDefaultsPrompt').tmpl();
var promptHTML = $("").append(prompt).html();
WFAD.colorboxHTML((WFAD.isSmallScreen ? '300px' : '400px'), promptHTML, {overlayClose: false, closeButton: false, className: 'wf-modal', onComplete: function() {
$('#wf-restore-defaults-prompt-cancel').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
WFAD.colorboxClose();
});
$('#wf-restore-defaults-prompt-confirm').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
WFAD.ajax('wordfence_restoreDefaults', {section: restoreDefaultsSection}, function(res) {
if (res.success) {
window.location.reload(true);
}
else {
WFAD.colorboxClose();
WFAD.colorboxModal((WFAD.isSmallScreen ? '300px' : '400px'), __('Error Restoring Defaults'), res.error);
}
});
});
}});
});
$('#wf-save-changes').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
WFAD.saveOptions(function(res) {
WFAD.pendingChanges = {};
WFAD.updatePendingChanges();
if (res.redirect) {
window.location.href = res.redirect;
}
else {
window.location.reload(true);
}
});
});
$('#wf-cancel-changes').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
WFAD.pendingChanges = {};
WFAD.updatePendingChanges();
//On/Off options
$('.wf-option.wf-option-toggled').each(function() {
var enabledValue = $(this).data('enabledValue');
var disabledValue = $(this).data('disabledValue');
var originalValue = $(this).data('originalValue');
if (enabledValue == originalValue) {
$(this).find('.wf-option-checkbox').addClass('wf-checked').attr('aria-checked', 'true');
}
else {
$(this).find('.wf-option-checkbox').removeClass('wf-checked').attr('aria-checked', 'false');
}
$(this).trigger('change', [true]);
});
$('.wf-option-toggled-boolean-switch').each(function() {
var enabledValue = $(this).data('enabledValue');
var disabledValue = $(this).data('disabledValue');
var originalValue = $(this).data('originalValue');
if (enabledValue == originalValue) {
$(this).find('.wf-boolean-switch').addClass('wf-active').attr('aria-checked', 'true');
}
else {
$(this).find('.wf-boolean-switch').removeClass('wf-active').attr('aria-checked', 'false');
}
$(this).trigger('change', [true]);
});
$('.wf-option.wf-option-toggled-segmented').each(function() {
var originalValue = $(this).data('originalValue');
$(this).find('[type=radio]').each(function() {
if (this.value == originalValue) {
this.checked = true;
return false;
}
});
$(this).trigger('change', [true]);
});
//On/Off multiple options
$('.wf-option.wf-option-toggled-multiple').each(function() {
$(this).find('.wf-option-checkboxes > ul').each(function() {
var enabledValue = $(this).data('enabledValue');
var disabledValue = $(this).data('disabledValue');
var originalValue = $(this).data('originalValue');
if (enabledValue == originalValue) {
$(this).find('.wf-option-checkbox').addClass('wf-checked').attr('aria-checked', 'true');
}
else {
$(this).find('.wf-option-checkbox').removeClass('wf-checked').attr('aria-checked', 'false');
}
});
$(this).trigger('change', [true]);
});
//On/Off options with menu
$('.wf-option.wf-option-toggled-select').each(function() {
var selectElement = $(this).find('.wf-option-select select');
var enabledToggleValue = $(this).data('enabledToggleValue');
var disabledToggleValue = $(this).data('disabledToggleValue');
var originalToggleValue = $(this).data('originalToggleValue');
if (enabledToggleValue == originalToggleValue) {
$(this).find('.wf-option-checkbox').addClass('wf-checked').attr('aria-checked', 'true');
selectElement.attr('disabled', false);
}
else {
$(this).find('.wf-option-checkbox').removeClass('wf-checked').attr('aria-checked', 'false');
selectElement.attr('disabled', true);
}
var originalSelectValue = $(this).data('originalSelectValue');
$(this).find('.wf-option-select select').val(originalSelectValue).trigger('change');
$(this).trigger('change', [true]);
});
//Menu options
$('.wf-option.wf-option-select').each(function() {
var originalSelectValue = $(this).data('originalSelectValue');
$(this).find('.wf-option-select select').val(originalSelectValue).trigger('change');
$(this).trigger('change', [true]);
});
//Text options
$('.wf-option.wf-option-text').each(function() {
var originalTextValue = $(this).data('originalTextValue');
if (typeof originalTextValue !== 'undefined') {
$(this).find('.wf-option-text input').val(originalTextValue);
}
$(this).trigger('change', [true]);
});
//Text area options
$('.wf-option.wf-option-textarea').each(function() {
var originalTextValue = $(this).data('originalTextValue');
$(this).find('.wf-option-textarea textarea').val(originalTextValue);
$(this).trigger('change', [true]);
});
//Token options
$('.wf-option.wf-option-token').each(function() {
var originalTokenValue = $(this).data('originalTokenValue');
$(this).find('select').val(originalTokenValue).trigger('change');
$(this).trigger('change', [true]);
});
//Switch options
$('.wf-option.wf-option-switch').each(function() {
var originalValue = $(this).data('originalValue');
$(this).find('.wf-switch > li').each(function() {
$(this).toggleClass('wf-active', originalValue == $(this).data('optionValue')).attr('aria-checked', originalValue == $(this).data('optionValue') ? 'true' : 'false');
});
$(this).trigger('change', [true]);
});
//Other options
$(window).trigger('wfOptionsReset');
});
var select2s = $('.wf-select2');
if (select2s.length && $.fn.wfselect2) {
select2s.wfselect2({
minimumResultsForSearch: 5
});
}
if ($.fn.tooltip) {
$('.wf-status-circular').each(function() {
var circle = $(this);
var tmplID = 'tooltip-' + this.id + '-tmpl';
var circleTmpl = $('#' + tmplID);
if (circleTmpl.length) {
circle.tooltip({
tooltipClass: "wf-circle-tooltip",
position: {
my: "left-40 bottom",
at: "center top",
using: function(obj, info) {
var el = $(this);
el.removeClass('wf-tooltip-vertical-top wf-tooltip-vertical-bottom ' +
'wf-tooltip-horizontal-left wf-tooltip-horizontal-right')
.addClass('wf-tooltip-vertical-' + info.vertical)
.addClass('wf-tooltip-horizontal-' + info.horizontal);
$(this).css({
left: obj.left + 'px',
top: obj.top + 'px'
});
}
},
items: this,
close: function (event, ui) {
ui.tooltip.hover(
function () {
$(this).stop(true).fadeTo(400, 1);
},
function () {
$(this).fadeOut("400", function () {
$(this).remove();
})
});
},
content: function() {
var circleClone = $(this).clone();
circleClone.find('svg, .wf-status-circular-text').css('opacity', 1.0);
var circleHTML = $(circleClone).html();
return circleTmpl.tmpl({
statusCircle: circleHTML
});
}
})
// .tooltip('open');
}
});
}
});
})(jQuery);
//wfCircularProgress
jQuery.fn.wfCircularProgress = function(options) {
var __ = window.wfi18n.__;
var sprintf = window.wfi18n.sprintf;
jQuery(this).each(function() {
var creationOptions;
try {
creationOptions = JSON.parse(jQuery(this).data('wfCircularProgressOptions'));
}
catch (e) { /* Ignore */ }
if (typeof creationOptions !== 'object') {
creationOptions = {};
}
var opts = jQuery.extend({}, jQuery.fn.wfCircularProgress.defaults, creationOptions, options);
var center = Math.floor(opts.diameter / 2);
var insetRadius = center - opts.strokeWidth * 2;
var circumference = 2 * insetRadius * Math.PI;
var finalOffset = -(circumference * (1 - opts.endPercent));
var initialOffset = -(circumference);
var terminatorRadius = Math.floor(opts.strokeWidth * 1.5);
var terminatorDiameter = 2 * terminatorRadius;
var finalTerminatorX = center - insetRadius * Math.cos(Math.PI * 2 * (opts.endPercent - 0.25));
var finalTerminatorY = center + insetRadius * Math.sin(Math.PI * 2 * (opts.endPercent - 0.25));
var initialTerminatorX = center - insetRadius * Math.cos(Math.PI * 2 * (opts.startPercent - 0.25));
var initialTerminatorY = center + insetRadius * Math.sin(Math.PI * 2 * (opts.startPercent - 0.25));
var terminatorSVG = "m 0,-" + terminatorRadius + " a " + terminatorRadius + "," + terminatorRadius + " 0 1 1 0," + terminatorDiameter + " a " + terminatorRadius + "," + terminatorRadius + " 0 1 1 0,-" + terminatorDiameter;
jQuery(this).data('wfCircularProgressOptions', JSON.stringify(opts));
jQuery(this).css('width', opts.diameter + 'px');
jQuery(this).css('height', opts.diameter + 'px');
var svg = jQuery(this).find('svg');
if (svg.length == 0) { svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); jQuery(this).append(svg); }
var inactivePath = jQuery(this).find('.wf-status-circular-inactive-path');
if (inactivePath.length == 0) { inactivePath = document.createElementNS("http://www.w3.org/2000/svg", "path"); jQuery(inactivePath).addClass('wf-status-circular-inactive-path'); jQuery(svg).append(inactivePath); }
var activePath = jQuery(this).find('.wf-status-circular-active-path');
if (activePath.length == 0) { activePath = document.createElementNS("http://www.w3.org/2000/svg", "path"); jQuery(activePath).addClass('wf-status-circular-active-path'); jQuery(svg).append(activePath); }
var terminator = jQuery(this).find('.wf-status-circular-terminator');
if (terminator.length == 0) { terminator = document.createElementNS("http://www.w3.org/2000/svg", "path"); jQuery(terminator).addClass('wf-status-circular-terminator'); jQuery(svg).append(terminator); }
var text = jQuery(this).find('.wf-status-circular-text');
if (text.length == 0) { text = jQuery(''); jQuery(this).append(text); }
var pendingOverlay = jQuery(this).find('.wf-status-overlay-text');
if (pendingOverlay.length == 0) { pendingOverlay = jQuery(''); jQuery(this).append(pendingOverlay); }
jQuery(svg).attr('viewBox', '0 0 ' + opts.diameter + ' ' + opts.diameter);
jQuery(svg).css('display', 'block');
jQuery(svg).css('width', opts.diameter + 'px');
jQuery(svg).css('height', opts.diameter + 'px');
jQuery(inactivePath).attr('d', 'M ' + center + ',' + center + ' m 0,-' + insetRadius + ' a ' + insetRadius + ',' +insetRadius + ' 0 1 1 0,' + (2 * insetRadius) + ' a ' + insetRadius + ',' + insetRadius + ' 0 1 1 0,-' + (2 * insetRadius));
jQuery(inactivePath).attr('stroke', opts.inactiveColor);
jQuery(inactivePath).attr('stroke-width', opts.strokeWidth);
jQuery(inactivePath).attr('fill-opacity', 0);
jQuery(activePath).attr('d', 'M ' + center + ',' + center + ' m 0,-' + insetRadius + ' a ' + insetRadius + ',' + insetRadius + ' 0 1 1 0,' + (2 * insetRadius) + ' a ' + insetRadius + ',' + insetRadius + ' 0 1 1 0,-' + (2 * insetRadius));
jQuery(activePath).attr('stroke', opts.color);
jQuery(activePath).attr('stroke-width', opts.strokeWidth);
jQuery(activePath).attr('stroke-dasharray', circumference + ',' + circumference);
jQuery(activePath).attr('stroke-dashoffset', initialOffset);
jQuery(activePath).attr('fill-opacity', 0);
jQuery(terminator).attr('d', 'M ' + initialTerminatorX + ',' + initialTerminatorY + ' ' + terminatorSVG);
jQuery(terminator).attr('stroke', opts.color);
jQuery(terminator).attr('stroke-width', opts.strokeWidth);
jQuery(terminator).attr('fill', '#ffffff');
jQuery(pendingOverlay).html(opts.pendingMessage);
jQuery(pendingOverlay).animate({
opacity: opts.pendingOverlay ? 1.0 : 0.0,
}, {
duration: 500,
step: function(value) {
var opacity = 1.0 - (value * 0.8);
jQuery(svg).css('opacity', opacity);
jQuery(text).css('opacity', opacity);
},
complete: function() {
jQuery(svg).css('opacity', opts.pendingOverlay ? 0.2 : 1.0);
jQuery(text).css('opacity', opts.pendingOverlay ? 0.2 : 1.0);
}
});
jQuery(activePath).animate({
"stroke-dashoffset": finalOffset + 'px'
}, {
duration: 500,
step: function(value) {
var percentage = 1 + value / circumference;
var x = center - insetRadius * Math.cos(Math.PI * 2 * (percentage - 0.25));
var y = center + insetRadius * Math.sin(Math.PI * 2 * (percentage - 0.25));
jQuery(terminator).attr('d', 'M ' + x + ',' + y + ' ' + terminatorSVG);
text.html(Math.round(percentage * 100) + '%');
},
complete: function() {
text.html(Math.round(opts.endPercent * 100) + '%');
}
});
});
};
(function() {
var __ = window.wfi18n.__;
var sprintf = window.wfi18n.sprintf;
jQuery.fn.wfCircularProgress.defaults = {
startPercent: 0,
endPercent: 1,
color: '#16bc9b',
inactiveColor: '#ececec',
strokeWidth: 3,
diameter: 100,
pendingOverlay: false,
pendingMessage: __('Note: Status will update when changes are saved'),
};
})();
//wfDrawer
(function ($, document, window) {
var __ = window.wfi18n.__;
var sprintf = window.wfi18n.sprintf;
var defaults = {
width: '600px',
clickOverlayDismiss: false,
content: false,
onComplete: false,
};
var publicMethod = $.fn['wfDrawer'] = $['wfDrawer'] = function (options) {
var opts = $.extend({}, defaults, options);
var overlay = $('').css('opacity', 0);
if (opts.clickOverlayDismiss) {
overlay.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
$.wfDrawer.close();
});
}
$('body').append(overlay);
var drawer = $('').css('width', opts.width).css('right', '-' + opts.width);
if (opts.content) {
drawer.append(opts.content);
}
$('body').append(drawer);
overlay.animate({
"opacity": 1
});
drawer.animate({
"right": '0px'
},
{
complete: function() {
typeof opts.onComplete === 'function' && opts.onComplete();
}
});
};
publicMethod.close = function() {
var overlay = $('.wf-drawer-overlay');
overlay.animate({
"opacity": 0
},
{
complete: function() {
overlay.remove();
}
});
var drawer = $('.wf-drawer');
drawer.animate({
"right": '-' + drawer.css('width')
},
{
complete: function() {
drawer.remove();
}
});
};
}(jQuery, document, window));
//wfMobileMenu
(function ($, document, window) {
var __ = window.wfi18n.__;
var sprintf = window.wfi18n.sprintf;
var defaults = {
width: '280px',
clickOverlayDismiss: true,
menuItems: [],
onDismiss: false,
};
var publicMethod = $.fn['wfMobileMenu'] = $['wfMobileMenu'] = function (options) {
var opts = $.extend({}, defaults, options);
var overlay = $('').css('opacity', 0);
if (opts.clickOverlayDismiss) {
overlay.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
typeof opts.onDismiss === 'function' && opts.onDismiss(false);
$.wfMobileMenu.close();
});
}
$('body').append(overlay);
var menu = $('
').css('width', opts.width).css('bottom', '-9999px');
var itemsWrapper = menu.find('.wf-mobile-menu-items');
for (var i = 0; i < opts.menuItems.length; i++) {
var button = $('