'use strict'; /* * SimBrief APIv1 Javascript Functions * For use with VA Dispatch systems * By Derek Mayer - contact@simbrief.com * * Any individual wishing to make use of this class must first contact me * to obtain a unique API key; without which it will be impossible to connect * to the API. * * Any attempt to circumvent the API authorization, steal another * developer's API key, hack, compromise, or gain unauthorized access to * the SimBrief website or it's web systems, or bypass or allow others to bypass * the SimBrief.com login screen will result in immediate revocation of the * associated API key, and in serious situations, legal action at my discretion. */ /* * Settings and initial variables */ let sbform = "sbapiform"; let sbworkerurl = "https://www.simbrief.com/ofp/ofp.loader.api.php"; let sbworkerid = 'SBworker'; let sbcallerid = 'SBcaller'; let sbworkerstyle = 'width=600,height=315'; let sbworker; let SBloop; let ofp_id; let flight_id; let aircraft_id; let outputpage_save; let outputpage_calc; let fe_result; let timestamp; let api_code; function simbriefsubmit(_flight_id, _aircraft_id, outputpage) { flight_id = _flight_id; aircraft_id = _aircraft_id; if (sbworker) { sbworker.close(); } if (SBloop) { window.clearInterval(SBloop); } api_code = null; ofp_id = null; fe_result = null; timestamp = null; outputpage_save = null; outputpage_calc = null; console.log('Flight ID', _flight_id); console.log('Aircraft ID', _aircraft_id); console.log('Output Page', outputpage); do_simbriefsubmit(outputpage); } async function do_simbriefsubmit(outputpage) { //CATCH UNDEFINED OUTPUT PAGE, SET IT TO THE CURRENT PAGE if (!outputpage) { outputpage = location.href; } if (!timestamp) { timestamp = Math.round(+new Date() / 1000); } outputpage_save = outputpage; outputpage_calc = outputpage.replace("http://", ""); if (!api_code) { const api_req = document.getElementsByName('orig')[0].value + document.getElementsByName('dest')[0].value + document.getElementsByName('type')[0].value + timestamp + outputpage_calc; let apiCodeResp; try { apiCodeResp = await phpvms.request({ method: 'POST', url: '/simbrief/apicode', data: { api_req, flight_id, aircraft_id, } }); } catch (e) { console.log('request error', e); return; } api_code = apiCodeResp.data.api_code; console.log('API code response: ', api_code); } //IF API_CODE IS SET, FINALIZE FORM var apiform = document.getElementById(sbform); apiform.setAttribute("method", "get"); apiform.setAttribute("action", sbworkerurl); apiform.setAttribute("target", sbworkerid); var input = document.createElement("input"); input.setAttribute("type", "hidden"); input.setAttribute("name", "apicode"); input.setAttribute("value", api_code); apiform.appendChild(input); var input = document.createElement("input"); input.setAttribute("type", "hidden"); input.setAttribute("name", "outputpage"); input.setAttribute("value", outputpage_calc); apiform.appendChild(input); var input = document.createElement("input"); input.setAttribute("type", "hidden"); input.setAttribute("name", "timestamp"); input.setAttribute("value", timestamp); apiform.appendChild(input); //LAUNCH FORM window.name = sbcallerid; LaunchSBworker(); apiform.submit(); //DETERMINE OFP_ID ofp_id = timestamp + '_' + md5(document.getElementsByName('orig')[0].value + document.getElementsByName('dest')[0].value + document.getElementsByName('type')[0].value); //LOOP TO DETECT WHEN THE WORKER PROCESS IS CLOSED SBloop = window.setInterval(checkSBworker, 500); } /* * Other related functions */ function LaunchSBworker() { sbworker = window.open('about:blank', sbworkerid, sbworkerstyle) //TEST FOR POPUP BLOCKERS if (sbworker == null || typeof (sbworker) == 'undefined') { alert('Please disable your pop-up blocker to generate a flight plan!'); } else { if (window.focus) { sbworker.focus(); } } } function checkSBworker() { if (sbworker && sbworker.closed) { window.clearInterval(SBloop); Redirect_caller(); } } async function Redirect_caller() { /* * First check that the file actually exists. * It might not if the window was closed before completion. * * An external PHP file is used so as to avoid any "Same * Origin" errors. */ let apiCodeResp; try { apiCodeResp = await phpvms.request({ method: 'GET', url: '/simbrief/check_ofp', params: { aircraft_id, flight_id, ofp_id, } }); } catch (e) { console.log('request error', e); setTimeout(function () { Redirect_caller(); }, 500); return; } api_code = apiCodeResp.data.id; console.log('API code response: ', api_code); /* * If the file exists, redirect to the specified Output Page. */ outputpage_save += '/' + ofp_id; let apiform = document.createElement("form"); apiform.setAttribute("method", "get"); apiform.setAttribute("action", outputpage_save); /* * Analyse link to see if there are any prior GET params. * If so, append them to the form */ let urlinfo = urlObject({'url': outputpage_save}); for (let key in urlinfo['parameters']) { let input = document.createElement("input"); input.setAttribute("type", "hidden"); input.setAttribute("name", key); input.setAttribute("value", urlinfo['parameters'][key]); apiform.appendChild(input); } let input = document.createElement("input"); input.setAttribute("type", "hidden"); input.setAttribute("name", "ofp_id"); input.setAttribute("value", ofp_id); apiform.appendChild(input); document.body.appendChild(apiform); apiform.submit(); } function sb_res_load(url) { var fileref = document.createElement('script'); fileref.type = "text/javascript"; fileref.src = url + "&p=" + Math.floor(Math.random() * 10000000); document.getElementsByTagName("head")[0].appendChild(fileref); } /* * URLOBJECT function * Courtesy Ayman Farhat */ function urlObject(options) { "use strict"; /*global window, document*/ var url_search_arr, option_key, i, urlObj, get_param, key, val, url_query, url_get_params = {}, a = document.createElement('a'), default_options = { 'url': window.location.href, 'unescape': true, 'convert_num': true }; if (typeof options !== "object") { options = default_options; } else { for (option_key in default_options) { if (default_options.hasOwnProperty(option_key)) { if (options[option_key] === undefined) { options[option_key] = default_options[option_key]; } } } } a.href = options.url; url_query = a.search.substring(1); url_search_arr = url_query.split('&'); if (url_search_arr[0].length > 1) { for (i = 0; i < url_search_arr.length; i += 1) { get_param = url_search_arr[i].split("="); if (options.unescape) { key = decodeURI(get_param[0]); val = decodeURI(get_param[1]); } else { key = get_param[0]; val = get_param[1]; } if (options.convert_num) { if (val.match(/^\d+$/)) { val = parseInt(val, 10); } else if (val.match(/^\d+\.\d+$/)) { val = parseFloat(val); } } if (url_get_params[key] === undefined) { url_get_params[key] = val; } else if (typeof url_get_params[key] === "string") { url_get_params[key] = [url_get_params[key], val]; } else { url_get_params[key].push(val); } get_param = []; } } urlObj = { protocol: a.protocol, hostname: a.hostname, host: a.host, port: a.port, hash: a.hash.substr(1), pathname: a.pathname, search: a.search, parameters: url_get_params }; return urlObj; } /* * MD5 and UTF8_ENCODE functions * Courtesy of phpjs.org */ function md5(str) { // discuss at: http://phpjs.org/functions/md5/ // original by: Webtoolkit.info (http://www.webtoolkit.info/) // improved by: Michael White (http://getsprink.com) // improved by: Jack // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // input by: Brett Zamir (http://brett-zamir.me) // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // depends on: utf8_encode // example 1: md5('Kevin van Zonneveld'); // returns 1: '6e658d4bfcb59cc13f96c14450ac40b9' var xl; var rotateLeft = function (lValue, iShiftBits) { return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); }; var addUnsigned = function (lX, lY) { var lX4, lY4, lX8, lY8, lResult; lX8 = (lX & 0x80000000); lY8 = (lY & 0x80000000); lX4 = (lX & 0x40000000); lY4 = (lY & 0x40000000); lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); if (lX4 & lY4) { return (lResult ^ 0x80000000 ^ lX8 ^ lY8); } if (lX4 | lY4) { if (lResult & 0x40000000) { return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); } else { return (lResult ^ 0x40000000 ^ lX8 ^ lY8); } } else { return (lResult ^ lX8 ^ lY8); } }; var _F = function (x, y, z) { return (x & y) | ((~x) & z); }; var _G = function (x, y, z) { return (x & z) | (y & (~z)); }; var _H = function (x, y, z) { return (x ^ y ^ z); }; var _I = function (x, y, z) { return (y ^ (x | (~z))); }; var _FF = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b); }; var _GG = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b); }; var _HH = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b); }; var _II = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b); }; var convertToWordArray = function (str) { var lWordCount; var lMessageLength = str.length; var lNumberOfWords_temp1 = lMessageLength + 8; var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64; var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16; var lWordArray = new Array(lNumberOfWords - 1); var lBytePosition = 0; var lByteCount = 0; while (lByteCount < lMessageLength) { lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition)); lByteCount++; } lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition); lWordArray[lNumberOfWords - 2] = lMessageLength << 3; lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; return lWordArray; }; var wordToHex = function (lValue) { var wordToHexValue = '', wordToHexValue_temp = '', lByte, lCount; for (lCount = 0; lCount <= 3; lCount++) { lByte = (lValue >>> (lCount * 8)) & 255; wordToHexValue_temp = '0' + lByte.toString(16); wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2); } return wordToHexValue; }; var x = [], k, AA, BB, CC, DD, a, b, c, d, S11 = 7, S12 = 12, S13 = 17, S14 = 22, S21 = 5, S22 = 9, S23 = 14, S24 = 20, S31 = 4, S32 = 11, S33 = 16, S34 = 23, S41 = 6, S42 = 10, S43 = 15, S44 = 21; str = utf8_encode(str); x = convertToWordArray(str); a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; xl = x.length; for (k = 0; k < xl; k += 16) { AA = a; BB = b; CC = c; DD = d; a = _FF(a, b, c, d, x[k + 0], S11, 0xD76AA478); d = _FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756); c = _FF(c, d, a, b, x[k + 2], S13, 0x242070DB); b = _FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE); a = _FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF); d = _FF(d, a, b, c, x[k + 5], S12, 0x4787C62A); c = _FF(c, d, a, b, x[k + 6], S13, 0xA8304613); b = _FF(b, c, d, a, x[k + 7], S14, 0xFD469501); a = _FF(a, b, c, d, x[k + 8], S11, 0x698098D8); d = _FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF); c = _FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1); b = _FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE); a = _FF(a, b, c, d, x[k + 12], S11, 0x6B901122); d = _FF(d, a, b, c, x[k + 13], S12, 0xFD987193); c = _FF(c, d, a, b, x[k + 14], S13, 0xA679438E); b = _FF(b, c, d, a, x[k + 15], S14, 0x49B40821); a = _GG(a, b, c, d, x[k + 1], S21, 0xF61E2562); d = _GG(d, a, b, c, x[k + 6], S22, 0xC040B340); c = _GG(c, d, a, b, x[k + 11], S23, 0x265E5A51); b = _GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA); a = _GG(a, b, c, d, x[k + 5], S21, 0xD62F105D); d = _GG(d, a, b, c, x[k + 10], S22, 0x2441453); c = _GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681); b = _GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8); a = _GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6); d = _GG(d, a, b, c, x[k + 14], S22, 0xC33707D6); c = _GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87); b = _GG(b, c, d, a, x[k + 8], S24, 0x455A14ED); a = _GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905); d = _GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8); c = _GG(c, d, a, b, x[k + 7], S23, 0x676F02D9); b = _GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A); a = _HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942); d = _HH(d, a, b, c, x[k + 8], S32, 0x8771F681); c = _HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122); b = _HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C); a = _HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44); d = _HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9); c = _HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60); b = _HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70); a = _HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6); d = _HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA); c = _HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085); b = _HH(b, c, d, a, x[k + 6], S34, 0x4881D05); a = _HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039); d = _HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5); c = _HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8); b = _HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665); a = _II(a, b, c, d, x[k + 0], S41, 0xF4292244); d = _II(d, a, b, c, x[k + 7], S42, 0x432AFF97); c = _II(c, d, a, b, x[k + 14], S43, 0xAB9423A7); b = _II(b, c, d, a, x[k + 5], S44, 0xFC93A039); a = _II(a, b, c, d, x[k + 12], S41, 0x655B59C3); d = _II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92); c = _II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D); b = _II(b, c, d, a, x[k + 1], S44, 0x85845DD1); a = _II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F); d = _II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0); c = _II(c, d, a, b, x[k + 6], S43, 0xA3014314); b = _II(b, c, d, a, x[k + 13], S44, 0x4E0811A1); a = _II(a, b, c, d, x[k + 4], S41, 0xF7537E82); d = _II(d, a, b, c, x[k + 11], S42, 0xBD3AF235); c = _II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB); b = _II(b, c, d, a, x[k + 9], S44, 0xEB86D391); a = addUnsigned(a, AA); b = addUnsigned(b, BB); c = addUnsigned(c, CC); d = addUnsigned(d, DD); } var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d); return temp.toUpperCase().substr(0, 10); } function utf8_encode(argString) { // discuss at: http://phpjs.org/functions/utf8_encode/ // original by: Webtoolkit.info (http://www.webtoolkit.info/) // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // improved by: sowberry // improved by: Jack // improved by: Yves Sucaet // improved by: kirilloid // bugfixed by: Onno Marsman // bugfixed by: Onno Marsman // bugfixed by: Ulrich // bugfixed by: Rafal Kukawski // bugfixed by: kirilloid // example 1: utf8_encode('Kevin van Zonneveld'); // returns 1: 'Kevin van Zonneveld' if (argString === null || typeof argString === 'undefined') { return ''; } // .replace(/\r\n/g, "\n").replace(/\r/g, "\n"); var string = (argString + ''); var utftext = '', start, end, stringl = 0; start = end = 0; stringl = string.length; for (var n = 0; n < stringl; n++) { var c1 = string.charCodeAt(n); var enc = null; if (c1 < 128) { end++; } else if (c1 > 127 && c1 < 2048) { enc = String.fromCharCode( (c1 >> 6) | 192, (c1 & 63) | 128 ); } else if ((c1 & 0xF800) != 0xD800) { enc = String.fromCharCode( (c1 >> 12) | 224, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128 ); } else { // surrogate pairs if ((c1 & 0xFC00) != 0xD800) { throw new RangeError('Unmatched trail surrogate at ' + n); } var c2 = string.charCodeAt(++n); if ((c2 & 0xFC00) != 0xDC00) { throw new RangeError('Unmatched lead surrogate at ' + (n - 1)); } c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000; enc = String.fromCharCode( (c1 >> 18) | 240, ((c1 >> 12) & 63) | 128, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128 ); } if (enc !== null) { if (end > start) { utftext += string.slice(start, end); } utftext += enc; start = end = n + 1; } } if (end > start) { utftext += string.slice(start, stringl); } return utftext; }