Files
medicalalert-web-reloaded/wp/wp-content/plugins/ip-geo-block/admin/js/authenticate.js
Tony Volpe be83910651 Merged in feature/280-dev-dev01 (pull request #21)
auto-patch  280-dev-dev01-2024-01-19T16_41_58

* auto-patch  280-dev-dev01-2024-01-19T16_41_58
2024-01-19 16:44:43 +00:00

520 lines
16 KiB
JavaScript

/*jslint white: true */
/*!
* Project: WP-ZEP - Zero-day exploit Prevention for wp-admin
* Copyright (c) 2013-2019 tokkonopapa (tokkonopapa@yahoo.com)
* This software is released under the MIT License.
*/
(function ($, window, document) {
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Description
var auth = IP_GEO_BLOCK_AUTH, wpzep = {
init: false,
regexp: new RegExp(auth.key + '(?:=|%3D)\\w+')
},
// regular expression to find target for is_admin()
regexp = new RegExp(
'^(?:' + (auth.home || '') + auth.admin
+ '|' + (auth.home || '') + auth.plugins
+ '|' + (auth.home || '') + auth.themes
+ '|' + (auth.admin ) // when site url is different from home url
+ ')(?:.*\\.php|.*\\/)?$'
),
// `theme-install.php` eats the query and set it to `request[browse]` as a parameter
theme_featured = function (data) {
var i = data.length, q = 'request%5Bbrowse%5D=' + auth.key;
while (i-- > 0) {
if (data[i].indexOf(q) !== -1) {
data[i] = 'request%5Bbrowse%5D=featured'; // correct the parameter
break;
}
}
return data;
},
// `upload.php` eats the query and set it to `query[ip-geo-block-auth-nonce]` as a parameter
media_library = function (data) {
var i = data.length, q = 'query%5B' + auth.key + '%5D=';
while (i-- > 0) {
if (data[i].indexOf(q) !== -1) {
delete data[i];
break;
}
}
return data;
},
// list of excluded links
ajax_links = {
'upload.php': media_library,
'theme-install.php': theme_featured,
'network/theme-install.php': theme_featured
};
// Check path that should be excluded
function check_ajax(path) {
path = path.replace(auth.home + auth.admin, '');
return ajax_links.hasOwnProperty(path) ? ajax_links[path] : null;
}
// Escape string for use in HTML.
function escapeHTML(html) {
var elem = document.createElement('div');
elem.appendChild(document.createTextNode(html));
html = elem.innerHTML.replace(/["']/g, function (match) {
return {
'"': '"',
"'": ''' //"
}[match];
});
elem = '';
return html;
}
// Parse a URL and return its components
function parse_uri(uri) {
// avoid malformed URI error when uri includes '%'
uri = /*decodeURIComponent*/(uri ? uri.toString() : '');
var m = uri.match(
// https://tools.ietf.org/html/rfc3986#appendix-B
/^(?:([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/
);
// scheme :// authority path ? query # fragment
return {
scheme: m[1] || '',
relative: m[2] || '',
authority: m[3] || '',
path: m[4] || '',
query: m[5] || '',
fragment: m[6] || ''
};
}
// Compose a URL from components
function compose_uri(uri) {
return (uri.scheme ? uri.scheme + ':' : '') +
(uri.relative + uri.path) +
(uri.query ? '?' + uri.query : '') +
(uri.fragment ? '#' + uri.fragment : '');
}
/**
* Convert relative url to absolute url using browser feature
*
* @param string target url
* @param string base of absolute url (default window.locatoin.href)
* @return component of url
*/
var absolute_uri = (function () {
var doc = null;
try {
new URL('/', 'http://example.com/'); // test if URL object is abailable
} catch (e) {
try {
doc = (new DOMParser()).parseFromString('<html><head></head><body></body></html>', 'text/html'); // IE11
} catch (f) {
doc = document.implementation.createHTMLDocument(''); // IE10
}
}
return function (url, base) {
var d = document, baseElm, aElm, result;
url = typeof url !== 'undefined' ? url : window.location.href;
if (null === doc) {
if (typeof base === 'undefined') {
base = window.location.href; // based on current url
}
try {
result = new URL(url, base); // base must be valid
} catch (e) {
result = new URL(url, window.location.href);
}
} else {
// use anchor element to resolve url
if (typeof base !== 'undefined') {
// assign base element to anchor to be independent of the current document
d = doc;
while (d.head.firstChild) {
d.head.removeChild(d.head.firstChild);
}
baseElm = d.createElement('base');
baseElm.setAttribute('href', base);
d.head.appendChild(baseElm);
}
aElm = d.createElement('a');
aElm.setAttribute('href', url);
aElm.setAttribute('href', aElm.href);
//d.appendChild(aElm);
result = {
protocol: aElm.protocol,
host: aElm.host,
hostname: aElm.hostname,
port: aElm.port,
pathname: aElm.pathname,
search: aElm.search,
hash: aElm.hash,
href: aElm.href,
username: '',
password: '',
origin : aElm.origin || null
};
if ('http:' === result.protocol && '80' === result.port) {
// remove port number `80` in case of `http` and defalut port
result.port = '';
result.host = result.host.replace(/:80$/, '');
} else if ('https:' === result.protocol && '443' === result.port) {
// remove port number `443` in case of `https` and defalut port
result.port = '';
result.host = result.host.replace(/:443$/, '');
}
if ('http:' === result.protocol || 'https:' === result.protocol) {
if (result.pathname && result.pathname.charAt(0) !== '/') {
// in case no `/` at the top
result.pathname = '/' + result.pathname;
}
if (!result.origin) {
result.origin = result.protocol + '//' + result.hostname + (result.port ? ':' + result.port : '');
}
}
}
if (result.username || result.password) {
// throw an error if basic basic authentication is targeted
throw new URIError(result.username + ':' + result.password);
}
return result;
};
}());
/*
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
function encodeURIComponentRFC3986(str) {
return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
return '%' + c.charCodeAt(0).toString(16);
});
}
*/
// Append the nonce as query strings to the uri
function add_query_nonce(uri, nonce) {
if (typeof uri !== 'object') { // `string` or `undefined`
uri = parse_uri(uri || window.location.href);
}
var data = uri.query ? uri.query.split('&') : [],
i = data.length,
q = auth.key + '=';
// remove an old nonce
while (i-- > 0) {
if (data[i].indexOf(q) === 0) { // or `wpzep.regexp.test(data[i])`
data.splice(i, 1);
break;
}
}
data.push(auth.key + '=' + encodeURIComponent(nonce)); //RFC3986
uri.query = data.join('&');
return compose_uri(uri);
}
// Check uri component if it is not empty or only fragment (`#...`)
function check_uri(uri) {
return (!uri.scheme || /^https?$/.test(uri.scheme)) && (uri.path || uri.query);
}
// Check uri where the nonce is needed
// Note: in case of url in the admin area of different site, it returns 0
function is_admin(url) {
// parse uri and get real path
try {
url = url || window.location.pathname || ''; // in case of empty `action` on the form tag
} catch (e) {
url = '';
}
var uri = parse_uri(url.toLowerCase());
// possibly scheme is `javascript` and path is `void(0);`
if (check_uri(uri)) {
// get absolute path with flattening `./`, `../`, `//`
uri = absolute_uri(url);
// external domain (`http://example` or `www.example`)
// https://tools.ietf.org/html/rfc6454#section-4
if (uri.origin !== window.location.origin) {
return -1; // external
}
// check if uri includes the target path of zep
url = regexp.exec(uri.pathname);
if (url) {
if ((0 <= url[0].indexOf(auth.admin + 'admin-')) ||
(0 <= url[0].indexOf(auth.admin )) ||
(0 <= url[0].indexOf(auth.plugins )) ||
(0 <= url[0].indexOf(auth.themes ))) {
return 1; // internal for admin
}
}
}
return 0; // internal not admin
}
// Check if current page is admin area and the target of wp-zep
function is_backend() {
return (is_admin(window.location.pathname) === 1 || wpzep.regexp(window.location.search));
}
// Check if url belongs to multisite
function is_multisite(url) {
var i, j, n = auth.sites.length;
for (i = 0; i < n; ++i) {
j = url.indexOf(auth.sites[i] + '/');
if (0 <= j && j <= 6) { // from `//` to `https://`
return true;
}
}
return false;
}
// check if the uri does not need a nonce
function is_neutral(uri) {
// return !uri.query; // without queries
// return !uri.query || !$('body').hasClass('wp-core-ui'); // without queries or outside dashboard
return /\/$/.test(uri.path); // `/wp-admin/`
}
// check if the link has nofollow
function has_nofollow($elem) {
return -1 !== ($elem.attr('rel') || '').indexOf('nofollow');
}
/*
$.ajaxSetup({
beforeSend: function (xhr, settings) {
// settings: {
// url: '/wp-admin/admin-ajax.php'
// method: 'POST' or 'GET'
// contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
// data: 'action=...'
// }
}
});
// plupload
$(window).on('BeforeUpload', function (uploader, file) {
console.log(uploader);
});
*/
// Embed a nonce before an Ajax request is sent
// $(document).ajaxSend(function (event, jqxhr, settings) {
$.ajaxPrefilter(function (settings /*, original, jqxhr*/) {
// POST to async-upload.php causes an error in https://wordpress.org/plugins/mammoth-docx-converter/
if (is_admin(settings.url) === 1 && !settings.url.match(/async-upload\.php$/)) {
// multipart/form-data (XMLHttpRequest Level 2)
// IE10+, Firefox 4+, Safari 5+, Android 3+
if (typeof window.FormData !== 'undefined' && settings.data instanceof FormData) {
settings.data.append(auth.key, auth.nonce);
}
// application/x-www-form-urlencoded
else {
// Behavior of jQuery Ajax
// method url url+data data
// GET query query data
// POST query query data
var data, callback, uri = parse_uri(settings.url);
if (typeof settings.data === 'undefined' || uri.query) {
settings.url = add_query_nonce(uri, auth.nonce);
} else {
data = settings.data ? settings.data.split('&') : [];
callback = check_ajax(window.location.pathname);
if (callback) {
data = callback(data);
}
data.push(auth.key + '=' + encodeURIComponent(auth.nonce)); //RFC3986
settings.data = data.join('&');
}
}
}
});
/*
* jQuery.bind-first library v0.2.3 (jquery >= 1.7)
* Copyright (c) 2013 Vladimir Zhuravlev
*
* Released under MIT License
* @license https://github.com/private-face/jquery.bind-first
*
* Date: Thu Feb 6 10:13:59 ICT 2014
*/
function moveHandlerToTop($el, eventName, isDelegated) {
var data = $._data($el[0]).events,
events = data[eventName],
handler = isDelegated ? events.splice(events.delegateCount - 1, 1)[0] : events.pop();
events.splice(isDelegated ? 0 : (events.delegateCount || 0), 0, handler);
}
function moveEventHandlers($elems, eventsString, isDelegate) {
var events = eventsString.split(/\s+/);
$elems.each(function(i) {
for (i = 0; i < events.length; ++i) {
var pureEventName = $.trim(events[i]).match(/[^\.]+/i)[0];
moveHandlerToTop($(this), pureEventName, isDelegate);
}
});
}
if (typeof $.fn.onFirst === 'undefined') {
$.fn.onFirst = function(types, selector) {
var type, $el = $(this), isDelegated = (typeof selector === 'string');
$.fn.on.apply($el, arguments);
// events map
if (typeof types === 'object') {
for (type in types) {
if (types.hasOwnProperty(type)) {
moveEventHandlers($el, type, isDelegated);
}
}
} else if (typeof types === 'string') {
moveEventHandlers($el, types, isDelegated);
}
return $el;
};
}
/*--------------------------------
* Attach event to the document
*--------------------------------*/
function attach_event() {
// https://www.sitepoint.com/jquery-body-on-document-on/
var elem = $(document); // `html` or `body` doesn't work with some browsers
elem.onFirst('click contextmenu', 'a', function (event) {
var admin = 0, // default: do nothing if href is empty
$this = $(this),
href = $this.attr('href') || '', // returns 'string' or 'undefined'
uri = parse_uri(href);
// check href has right scheme and path
if (check_uri(uri)) {
admin = is_admin(href);
}
// console.log('href:' + href, uri, 'admin:' + admin, 'is_backend:' + is_backend(), 'is_multisite:' + is_multisite(href));
// if context menu then continue and should be checked in check_nonce()
if ('click' !== event.type) {
return;
}
// if admin area (except a link with nofollow in the comment thread) then add a nonce
else if (admin === 1) {
$this.attr('href', is_neutral(uri) ? href :
add_query_nonce( href, has_nofollow($this) ? 'nofollow' : auth.nonce )
);
}
// if external then redirect with no referrer not to leak out the nonce
else if (admin === -1 && is_backend()) {
// open within the same window
if ('_self' === $this.attr('target') || is_multisite(href)) {
$this.attr('href', is_neutral(uri) ? href :
add_query_nonce( href, has_nofollow($this) ? 'nofollow' : auth.nonce )
);
}
// open a new window
else if (!this.hasAttribute('onClick')) {
// avoid `url=...;url=javascript:...`
href = href.split(';', 2).shift();
href = escapeHTML(decodeURIComponent(this.href)); // & => &amp;
admin = window.open();
admin.document.write(
'<!DOCTYPE html><html><head>' +
'<meta name="referrer" content="never" />' +
'<meta name="referrer" content="no-referrer" />' +
'<meta http-equiv="refresh" content="0; url=' + href + '" />' +
($('body').hasClass('webview') ? '<script>window.location.replace("' + href + '")</script>' : '') +
'</head></html>'
);
admin.document.close();
// stop event propagation and location transition
event.stopImmediatePropagation();
return false; // same as event.stopPropagation() and event.preventDefault()
}
}
});
elem.onFirst('submit', 'form', function (/*event*/) {
var $this = $(this), action = $this.attr('action'); // possibly 'undefined'
// if admin area then add the nonce
if (is_admin(action) === 1) {
if ('post' === ($this.attr('method') || '').toLowerCase()) {
$this.attr('action', add_query_nonce(action, auth.nonce));
} else {
// https://www.w3.org/TR/1999/REC-html401-19991224/types.html#type-name
$this.append('<input type="hidden" name="' + auth.key + '" value="' + auth.nonce + '">');
}
}
});
}
/*--------------------------------
* Something after document ready
*--------------------------------*/
function attach_ready(/*stat*/) {
if (!wpzep.init) {
wpzep.init = true;
$('img').each(function (/*index*/) {
var src = $(this).attr('src');
// if admin area
if (is_admin(src) === 1) {
$(this).attr('src', add_query_nonce(src, auth.nonce));
}
});
// Restore post revisions (wp-admin/revisions.php @since 2.6.0)
if ('undefined' !== typeof window._wpRevisionsSettings) {
var i, data = window._wpRevisionsSettings.revisionData, n = data.length;
for (i = 0; i < n; ++i) {
if (!wpzep.regexp.test(data[i].restoreUrl)) {
window._wpRevisionsSettings.revisionData[i].restoreUrl = add_query_nonce(data[i].restoreUrl, auth.nonce);
}
}
}
// Hide the title of sub-menu.
$('#toplevel_page_ip-geo-block li.wp-first-item').each(function (/*i, obj*/) {
var $this = $(this);
$this.css('display', 'IP Geo Block' === $this.children('a').text() ? 'none' : 'block');
});
}
}
$(window).on('error', function (/*event*/) { // event.originalEvent.message
attach_ready(); // fallback on error
});
$(function () {
attach_ready();
});
// Attach event to add nonce
attach_event();
}(jQuery, window, document));