| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- /**
- * PrivateBin
- *
- * a zero-knowledge paste bin
- *
- * @see {@link https://github.com/PrivateBin/PrivateBin}
- * @copyright 2012 Sébastien SAUVAGE ({@link http://sebsauvage.net})
- * @license {@link https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License}
- * @version 1.3
- * @name Legacy
- * @namespace
- *
- * IMPORTANT NOTICE FOR DEVELOPERS:
- * The logic in this file is intended to run in legacy browsers. Avoid any use of:
- * - ES6 or newer in general
- * - const/let, use the traditional var declarations instead
- * - async/await or Promises, use traditional callbacks
- * - shorthand function notation "() => output", use the full "function() {return output;}" style
- * - IE doesn't support:
- * - URL(), use the traditional window.location object
- * - endsWith(), use indexof()
- * - yes, this logic needs to support IE 5 or 6, to at least display the error message
- */
- // main application start, called when DOM is fully loaded
- jQuery(document).ready(function() {
- 'use strict';
- // run main controller
- $.Legacy.Check.init();
- });
- jQuery.Legacy = (function($) {
- 'use strict';
- /**
- * compatibility check
- *
- * @name Check
- * @class
- */
- var Check = (function () {
- var me = {};
- /**
- * Status of the initial check, true means it passed
- *
- * @private
- * @prop {bool}
- */
- var status = false;
- /**
- * Initialization check did run
- *
- * @private
- * @prop {bool}
- */
- var init = false;
- /**
- * blacklist of UserAgents (parts) known to belong to a bot
- *
- * @private
- * @enum {Array}
- * @readonly
- */
- var badBotUA = [
- 'Bot',
- 'bot'
- ];
- /**
- * whitelist of top level domains to consider a secure context,
- * regardless of protocol
- *
- * @private
- * @enum {Array}
- * @readonly
- */
- var tld = [
- '.onion',
- '.i2p'
- ];
- /**
- * whitelist of hostnames to consider a secure context,
- * regardless of protocol
- *
- * @private
- * @enum {Array}
- * @readonly
- */
- // whitelists of TLDs & local hostnames
- var hostname = [
- 'localhost',
- '127.0.0.1',
- '[::1]'
- ];
- /**
- * check if the context is secure
- *
- * @private
- * @name Check.isSecureContext
- * @function
- * @return {bool}
- */
- function isSecureContext()
- {
- // use .isSecureContext if available
- if (window.isSecureContext === true || window.isSecureContext === false) {
- return window.isSecureContext;
- }
- // HTTP is obviously insecure
- if (window.location.protocol !== 'http:') {
- return true;
- }
- // filter out actually secure connections over HTTP
- for (var i = 0; i < tld.length; i++) {
- if (
- window.location.hostname.indexOf(
- tld[i],
- window.location.hostname.length - tld[i].length
- ) !== -1
- ) {
- return true;
- }
- }
- // whitelist localhost for development
- for (var j = 0; j < hostname.length; j++) {
- if (window.location.hostname === hostname[j]) {
- return true;
- }
- }
- // totally INSECURE http protocol!
- return false;
- }
- /**
- * checks whether this is a bot we dislike
- *
- * @private
- * @name Check.isBadBot
- * @function
- * @return {bool}
- */
- function isBadBot() {
- // check whether a bot user agent part can be found in the current
- // user agent
- for (var i = 0; i < badBotUA.length; i++) {
- if (navigator.userAgent.indexOf(badBotUA[i]) !== -1) {
- return true;
- }
- }
- return false;
- }
- /**
- * checks whether this is an unsupported browser, via feature detection
- *
- * @private
- * @name Check.isOldBrowser
- * @function
- * @return {bool}
- */
- function isOldBrowser() {
- // webcrypto support
- if (!(
- 'crypto' in window &&
- 'getRandomValues' in window.crypto &&
- 'subtle' in window.crypto &&
- 'encrypt' in window.crypto.subtle &&
- 'decrypt' in window.crypto.subtle &&
- 'Uint8Array' in window &&
- 'Uint32Array' in window
- )) {
- return true;
- }
- // not checking for async/await, ES6 or Promise support, as most
- // browsers introduced these earlier then webassembly and webcrypto:
- // https://github.com/PrivateBin/PrivateBin/pull/431#issuecomment-493129359
- return false;
- }
- /**
- * shows an error message
- *
- * @private
- * @name Check.showError
- * @param {string} message
- * @function
- */
- function showError(message)
- {
- var $error = $('#errormessage'),
- $glyphIcon = $error.find(':first'),
- $element;
- if ($glyphIcon.length) {
- // if there is an icon, we need to provide an inner element
- // to translate the message into, instead of the parent
- $element = $('<span>');
- $error.html(' ').prepend($glyphIcon).append($element);
- } else {
- $element = $error;
- }
- if (message.indexOf('<a') === -1) {
- $element.text(message);
- } else {
- $element.html(message);
- }
- $error.removeClass('hidden');
- }
- /**
- * returns if the check has concluded
- *
- * @name Check.getInit
- * @function
- * @return {bool}
- */
- me.getInit = function()
- {
- return init;
- };
-
- /**
- * returns the current status of the check
- *
- * @name Check.getStatus
- * @function
- * @return {bool}
- */
- me.getStatus = function()
- {
- return status;
- };
-
- /**
- * init on application start, returns an all-clear signal
- *
- * @name Check.init
- * @function
- */
- me.init = function()
- {
- // prevent bots from viewing a paste and potentially deleting data
- // when burn-after-reading is set
- if (isBadBot()) {
- showError('I love you too, bot…');
- init = true;
- return;
- }
- if (isOldBrowser()) {
- // some browsers (Chrome based ones) would have webcrypto support if using HTTPS
- if (!isSecureContext()) {
- showError(
- 'Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href="%s">switching to HTTPS</a>.'.replace(
- '%s',
- 'https' + window.location.href.slice(4)
- )
- );
- }
- $('#oldnotice').removeClass('hidden');
- init = true;
- return;
- }
- if (!isSecureContext()) {
- $('#httpnotice').removeClass('hidden');
- }
- init = true;
- // only if everything passed, we set the status to true
- status = true;
- };
- return me;
- })();
- return {
- Check: Check
- };
- })(jQuery);
|