diff --git a/mozilla/extensions/irc/jar.mn b/mozilla/extensions/irc/jar.mn index 34424a4958b..2d7ae3be14b 100644 --- a/mozilla/extensions/irc/jar.mn +++ b/mozilla/extensions/irc/jar.mn @@ -32,6 +32,7 @@ chatzilla.jar: content/chatzilla/menus.js (xul/content/menus.js) content/chatzilla/static.js (xul/content/static.js) content/chatzilla/rdf.js (xul/content/rdf.js) + content/chatzilla/networks.js (xul/content/networks.js) content/chatzilla/dynamic.css (xul/content/dynamic.css) content/chatzilla/output-base.css (xul/content/output-base.css) content/chatzilla/chatzillaOverlay.xul (xul/content/chatzillaOverlay.xul) diff --git a/mozilla/extensions/irc/js/lib/irc.js b/mozilla/extensions/irc/js/lib/irc.js index a0f7afdbef9..f4e89f7cdcb 100644 --- a/mozilla/extensions/irc/js/lib/irc.js +++ b/mozilla/extensions/irc/js/lib/irc.js @@ -193,6 +193,16 @@ function net_hasSecure() return false; } +CIRCNetwork.prototype.clearServerList = +function net_clearserverlist() +{ + /* Note: we don't have to worry about being connected, since primServ + * keeps the currently connected server alive if we still need it. + */ + this.servers = new Object(); + this.serverList = new Array(); +} + /** Trigger an onDoConnect event after a delay. */ CIRCNetwork.prototype.delayedConnect = function net_delayedConnect(eventProperties) @@ -531,9 +541,9 @@ CIRCServer.prototype.canonicalChanModes = { getValue: function (modifier) { return (modifier == "+"); } }, k: { - name: "key", - getValue: function (modifier, data) - { + name: "key", + getValue: function (modifier, data) + { if (modifier == "+") return data; else @@ -958,13 +968,13 @@ function serv_uptimer() this.lastPing = this.lastPingSent = new Date(); } -CIRCServer.prototype.userhost = +CIRCServer.prototype.userhost = function serv_userhost(target) { this.sendData("USERHOST " + fromUnicode(target, this) + "\n"); } -CIRCServer.prototype.userip = +CIRCServer.prototype.userip = function serv_userip(target) { this.sendData("USERIP " + fromUnicode(target, this) + "\n"); diff --git a/mozilla/extensions/irc/js/lib/text-serializer.js b/mozilla/extensions/irc/js/lib/text-serializer.js index 4674d345990..b5dcfd39e03 100644 --- a/mozilla/extensions/irc/js/lib/text-serializer.js +++ b/mozilla/extensions/irc/js/lib/text-serializer.js @@ -158,6 +158,10 @@ function ts_serialize(obj) break; case "number": + case "boolean": + case "null": // (just in case) + case "undefined": + // These all serialise to what we want. writeProp(p, o[p]); break; @@ -167,23 +171,23 @@ function ts_serialize(obj) // Can't serialize non-RegExp functions (yet). break; - case "null": - writeProp(p, "null"); - break; - - case "undefined": - writeProp(p, "undefined"); - break; - case "object": - var className = ""; - if (o[p] instanceof Array) - className = " "; + if (o[p] == null) + { + // typeof null == "object", just to catch us out. + writeProp(p, "null"); + } + else + { + var className = ""; + if (o[p] instanceof Array) + className = " "; - me._fileStream.write(indent + "START " + className + - ecmaEscape(p) + me.lineEnd); - writeObjProps(o[p], indent + " "); - me._fileStream.write(indent + "END" + me.lineEnd); + me._fileStream.write(indent + "START " + className + + ecmaEscape(p) + me.lineEnd); + writeObjProps(o[p], indent + " "); + me._fileStream.write(indent + "END" + me.lineEnd); + } break; default: @@ -352,6 +356,10 @@ function ts_deserialize() { obj[command] = undefined; } + else if ((params == "true") || (params == "false")) // boolean + { + obj[command] = (params == "true"); + } else // Number { obj[command] = Number(params); diff --git a/mozilla/extensions/irc/xul/content/networks.js b/mozilla/extensions/irc/xul/content/networks.js new file mode 100644 index 00000000000..0621a7f3245 --- /dev/null +++ b/mozilla/extensions/irc/xul/content/networks.js @@ -0,0 +1,324 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is ChatZilla. + * + * The Initial Developer of the Original Code is James Ross. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * James Ross + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +function initNetworks() +{ + var networks = new Object(); + + // Set up default network list. + networks["moznet"] = { + displayName: "moznet", + isupportsKey: "Mozilla", + servers: [{hostname: "irc.mozilla.org", port:6667}, + {hostname: "irc.mozilla.org", port:6697, isSecure: true}]}; + networks["hybridnet"] = { + displayName: "hybridnet", + isupportsKey: "", + servers: [{hostname: "irc.ssc.net", port: 6667}]}; + networks["slashnet"] = { + displayName: "slashnet", + isupportsKey: "", + servers: [{hostname: "irc.slashnet.org", port:6667}]}; + networks["dalnet"] = { + displayName: "dalnet", + isupportsKey: "", + servers: [{hostname: "irc.dal.net", port:6667}]}; + networks["undernet"] = { + displayName: "undernet", + isupportsKey: "", + servers: [{hostname: "irc.undernet.org", port:6667}]}; + networks["webbnet"] = { + displayName: "webbnet", + isupportsKey: "", + servers: [{hostname: "irc.webbnet.info", port:6667}]}; + networks["quakenet"] = { + displayName: "quakenet", + isupportsKey: "", + servers: [{hostname: "irc.quakenet.org", port:6667}]}; + networks["freenode"] = { + displayName: "freenode", + isupportsKey: "", + servers: [{hostname: "irc.freenode.net", port:6667}]}; + networks["serenia"] = { + displayName: "serenia", + isupportsKey: "", + servers: [{hostname: "chat.serenia.net", port:9999, isSecure: true}]}; + networks["efnet"] = { + displayName: "efnet", + isupportsKey: "", + servers: [{hostname: "irc.prison.net", port: 6667}, + {hostname: "irc.magic.ca", port: 6667}]}; + + for (var name in networks) + networks[name].name = name; + + var builtInNames = keys(networks); + + var userNetworkList = new Array(); + + // Load the user's network list. + var networksFile = new nsLocalFile(client.prefs["profilePath"]); + networksFile.append("networks.txt"); + if (networksFile.exists()) + { + var networksLoader = new TextSerializer(networksFile); + if (networksLoader.open("<")) + { + var item = networksLoader.deserialize(); + if (item instanceof Array) + userNetworkList = item; + else + dd("Malformed networks file!"); + networksLoader.close(); + } + } + + // Merge the user's network list with the default ones. + for (var i = 0; i < userNetworkList.length; i++) + networks[userNetworkList[i].name] = userNetworkList[i]; + + /* Flag up all networks that are built-in, so they can be handled properly. + * We need to do this last so that it ensures networks overridden by the + * user's networks.txt are still flagged properly. + */ + for (var i = 0; i < builtInNames.length; i++) + networks[builtInNames[i]].isBuiltIn = true; + + // Push network list over to client.networkList. + client.networkList = new Array(); + for (var name in networks) + client.networkList.push(networks[name]); + + // Sync to client.networks. + networksSyncFromList(); +} + +function networksSyncToList() +{ + // Stores indexes of networks that should be kept. + var networkMap = new Object(); + + // Copy to and update client.networkList from client.networks. + for (var name in client.networks) + { + var net = client.networks[name]; + /* Skip temporary networks, as they're created to wrap standalone + * servers only. + */ + if (net.temporary) + continue; + + // Find the network in the networkList, if it exists. + var listNet = null; + for (var i = 0; i < client.networkList.length; i++) + { + if (client.networkList[i].name == name) + { + listNet = client.networkList[i]; + networkMap[i] = true; + break; + } + } + + // Network not in list, so construct a shiny new one. + if (listNet == null) + { + var listNet = { name: name, displayName: name, isupportsKey: "" }; + + // Collect the RPL_ISUPPORTS "network name" if available. + if (("primServ" in net) && net.primServ && + ("supports" in net.primServ) && net.primServ.supports && + ("network" in net.primServ.supports)) + { + listNet.isupportsKey = net.primServ.supports["network"]; + } + + client.networkList.push(listNet); + networkMap[client.networkList.length - 1] = true; + } + + // Populate server list (no merging here). + listNet.servers = new Array(); + for (i = 0; i < net.serverList.length; i++) + { + var serv = net.serverList[i]; + + // Find this server in the list... + var listServ = null; + for (var j = 0; j < listNet.servers.length; j++) + { + if ((serv.hostname == listNet.servers[j].hostname) && + (serv.port == listNet.servers[j].port)) + { + listServ = listNet.servers[j]; + break; + } + } + + // ...and add a new one if it isn't found. + if (listServ == null) + { + listServ = { name: serv.hostname, port: serv.port, + isSecure: serv.isSecure, password: null }; + listNet.servers.push(listServ); + } + + listServ.isSecure = serv.isSecure; + // Update the saved password (!! FIXME: plaintext password !!). + listServ.password = serv.password; + } + } + + // Remove any no-longer existing networks. + var index = 0; // (current pointer into client.networkList) + var mapIndex = 0; // (original position pointer) + while (index < client.networkList.length) + { + if (mapIndex in networkMap) + { + index++; + mapIndex++; + continue; + } + + var listNet = client.networkList[index]; + // Not seen this network in the client.networks collection. + if (("isBuiltIn" in listNet) && listNet.isBuiltIn) + { + // Network is a built-in. Replace with dummy. + client.networkList[index] = { name: listNet.name, isDeleted: true }; + index++; + } + else + { + // Network is not a built-in, just nuke. + // Note: don't do index++ here because we've removed the item. + client.networkList.splice(index, 1); + } + mapIndex++; + } +} + +function networksSyncFromList() +{ + var networkMap = new Object(); + + // Copy to and update client.networks from client.networkList. + for (var i = 0; i < client.networkList.length; i++) + { + var listNet = client.networkList[i]; + networkMap[listNet.name] = true; + + if ("isDeleted" in listNet) + { + /* This is a dummy entry that indicates a removed built-in network. + * Remove the network from client.networks if it exists, and then + * skip onto the next... + */ + if (listNet.name in client.networks) + client.removeNetwork(listNet.name); + continue; + } + + // Create new network object if necessary. + var net = null; + if (!(listNet.name in client.networks)) + client.addNetwork(listNet.name, []); + + // Get network object and make sure server list is empty. + net = client.networks[listNet.name]; + net.clearServerList(); + + // Make sure real network knows if it is a built-in one. + if ("isBuiltIn" in listNet) + net.isBuiltIn = listNet.isBuiltIn; + + // Update server list. + for (var j = 0; j < listNet.servers.length; j++) + { + var listServ = listNet.servers[j]; + + // Make sure these exist. + if (!("isSecure" in listServ)) + listServ.isSecure = false; + if (!("password" in listServ)) + listServ.password = null; + + // NOTE: this must match the name given by CIRCServer. + var servName = listServ.hostname + ":" + listServ.port; + + var serv = null; + if (!(servName in net.servers)) + { + net.addServer(listServ.hostname, listServ.port, + listServ.isSecure, listServ.password); + } + serv = net.servers[servName]; + + serv.isSecure = listServ.isSecure; + serv.password = listServ.password; + } + } + + // Remove network objects that aren't in networkList. + for (var name in client.networks) + { + // Skip temporary networks, as they don't matter. + if (client.networks[name].temporary) + continue; + if (!(name in networkMap)) + client.removeNetwork(name); + } +} + +function networksSaveList() +{ + try + { + var networksFile = new nsLocalFile(client.prefs["profilePath"]); + networksFile.append("networks.txt"); + var networksLoader = new TextSerializer(networksFile); + if (networksLoader.open(">")) + { + networksLoader.serialize(client.networkList); + networksLoader.close(); + } + } + catch(ex) + { + display("ERROR: " + formatException(ex), MT_ERROR); + } +} diff --git a/mozilla/extensions/irc/xul/content/scripts.xul b/mozilla/extensions/irc/xul/content/scripts.xul index 341c3c23fe7..694d0b8b1b5 100644 --- a/mozilla/extensions/irc/xul/content/scripts.xul +++ b/mozilla/extensions/irc/xul/content/scripts.xul @@ -81,6 +81,7 @@