const PORT = 26001; if (typeof EIB === "undefined") var EIB = { headers: {}, pending: [] }; const Cc = Components.classes, Ci = Components.interfaces, Cu = Components.utils, CC = Components.Constructor, Cr = Components.results; const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1", "nsIScriptableInputStream", "init"); Cu.import("resource://gre/modules/Services.jsm"); function install() {} function uninstall() {} EIB.listen = function () { this.serverSocket = Cc["@mozilla.org/network/server-socket;1"] .createInstance(Ci.nsIServerSocket); this.serverSocket.init(PORT, true, -1); const tm = Cc["@mozilla.org/thread-manager;1"].getService(); this.serverSocket.asyncListen({ onSocketAccepted: function (socket, transport) { var is = transport.openInputStream(0, 0, 0); var os = transport.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0); var sis = new ScriptableInputStream(is); var buf = ""; // TODO: run on separate thread is.asyncWait({ onInputStreamReady: function () { while (sis.available()) { buf += sis.read(2048); } if (buf.indexOf("\n\n") !== 2) { var headers = {}; var rx = /\n(EVE_[^:]*): (.*)$/gm, arr; while ((arr = rx.exec(buf)) !== null) { headers[arr[1]] = arr[2]; } EIB.headers = headers; var resp = "HTTP/1.0 200 OK\r\n"; resp += "Content-Type: text/html\r\n\r\n"; resp += "EVE-IGB Bridge"; if (headers["EVE_TRUSTED"]) { resp += ""; resp += headers["EVE_TRUSTED"] == "Yes" ? "Connected to the EVE-IGB Bridge. Please do not close this window. You may minimize it, however. Note that this window will refresh repeatedly; this does not indicate a malfunction and will not count towards your internet data usage if you have one." : "Please grant trust to this site, then refresh the page."; resp += ""; } else { resp += "Please open this page in the EVE in-game browser."; } os.write(resp, resp.length); is.close(); os.close(); } } }, 0, 0, tm.mainThread); } }); } var HttpObserver = { observe: function (subject, topic, data) { var channel = subject.QueryInterface(Ci.nsIHttpChannel); // TODO: is this secure? if (checkTrusted(channel.URI.specIgnoringRef)) { for (var header in EIB.headers) { channel.setRequestHeader(header, EIB.headers[header], false); } } } }; function forEachOpenWindow(todo) { var windows = Services.wm.getEnumerator("navigator:browser"); while (windows.hasMoreElements()) todo(windows.getNext().QueryInterface(Ci.nsIDOMWindow)); } var WindowListener = { onOpenWindow: function(xulWindow) { var window = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); function onWindowLoad() { window.removeEventListener("load", onWindowLoad); if (window.document.documentElement.getAttribute("windowtype") == "navigator:browser") loadIntoWindow(window); } window.addEventListener("load", onWindowLoad); }, }; var TrustedReparser = { observe: function () { if (!EIB.prefs.prefHasUserValue("trusted")) { EIB.prefs.setCharPref("trusted", "[]"); } EIB.trusted = JSON.parse(EIB.prefs.getCharPref("trusted")); } }; function startup(data, reason) { EIB.listen(); EIB.prefs = Services.prefs.getBranch("extensions.eib."); EIB.prefs.addObserver("trusted", TrustedReparser, false); TrustedReparser.observe(); forEachOpenWindow(loadIntoWindow); Services.wm.addListener(WindowListener); Services.obs.addObserver(HttpObserver, "http-on-modify-request", false); } function shutdown(data, reason) { if (reason === APP_SHUTDOWN) return; if (EIB.serverSocket) EIB.serverSocket.close(); delete EIB.serverSocket; EIB.prefs.removeObserver("trusted", TrustedReparser); forEachOpenWindow(unloadFromWindow); Services.wm.removeListener(WindowListener); Services.obs.removeObserver(HttpObserver, "http-on-modify-request"); } function checkTrusted(href) { for (var i = 0; i < EIB.trusted.length; i++) if (href.indexOf(EIB.trusted[i]) === 0) return true; return false; } function injectCCPEVE(e) { var window = e.originalTarget.defaultView; if (checkTrusted(window.location.href)) { var CCPEVE = Cu.createObjectIn(window, {defineAs: "CCPEVE"}); ["openEveMail", "showInfo", "showPreview", "showRouteTo", "showMap", "showFitting", "showContract", "showMarketDetails", "setDestination", "addWaypoint", "joinChannel", "joinMailingList", "createContract", "buyType", "findInContracts", "addToMarketQuickBar", "addContact", "removeContact", "addCorpContact", "removeCorpContact", "block", "addBounty", "inviteToFleet", "startConversation", "showContracts", "showOnMap", "editMember", "awardDecoration", "sendMail", "showContents", "bookmark"].forEach(function (n) { Object.defineProperty(CCPEVE, n, { value: Cu.exportFunction(function () { EIB.pending.push('CCPEVE.' + n + '(' + Array.prototype.join.call(arguments, ',') + ');'); return null; }, CCPEVE) }); }); } } function loadIntoWindow(window) { window.document.getElementById("appcontent").addEventListener("DOMContentLoaded", injectCCPEVE, false); } function unloadFromWindow(window) { window.document.getElementById("appcontent").removeEventListener("DOMContentLoaded", injectCCPEVE, false); }