From 1f0d6200de288393211f7cc8fe3f686ea772736c Mon Sep 17 00:00:00 2001 From: "gijskruitbosch%gmail.com" Date: Mon, 31 Jul 2006 11:46:21 +0000 Subject: [PATCH] Updating to ChatZilla 0.9.75 on 1.8 branch r=silver blanket-a=SeaMonkey Council (See bug 334161) ChatZilla Only git-svn-id: svn://10.0.0.236/branches/MOZILLA_1_8_BRANCH@206124 18797224-902f-48f8-a5cc-f745e15eee43 --- .../extensions/irc/js/lib/command-manager.js | 3 + .../extensions/irc/js/lib/connection-xpcom.js | 85 +++++++++----- mozilla/extensions/irc/js/lib/dcc.js | 4 +- mozilla/extensions/irc/js/lib/irc.js | 98 ++++++++++------ mozilla/extensions/irc/js/lib/utils.js | 28 +++-- .../extensions/irc/xpi/resources/install.rdf | 10 +- .../extensions/irc/xul/content/commands.js | 78 ++++++++++--- .../extensions/irc/xul/content/contents.rdf | 2 +- .../extensions/irc/xul/content/handlers.js | 107 ++++++++++++------ mozilla/extensions/irc/xul/content/prefs.js | 15 +++ mozilla/extensions/irc/xul/content/static.js | 37 +++--- .../irc/xul/locale/en-US/chatzilla.properties | 28 +++-- 12 files changed, 350 insertions(+), 145 deletions(-) diff --git a/mozilla/extensions/irc/js/lib/command-manager.js b/mozilla/extensions/irc/js/lib/command-manager.js index 11bedee9cb3..a11761c366c 100644 --- a/mozilla/extensions/irc/js/lib/command-manager.js +++ b/mozilla/extensions/irc/js/lib/command-manager.js @@ -172,6 +172,9 @@ function CommandManager (defaultBundle) { this.commands = new Object(); this.defaultBundle = defaultBundle; + this.currentDispatchDepth = 0; + this.maxDispatchDepth = 10; + this.dispatchUnwinding = false; } CommandManager.prototype.defaultFlags = 0; diff --git a/mozilla/extensions/irc/js/lib/connection-xpcom.js b/mozilla/extensions/irc/js/lib/connection-xpcom.js index 0c0207e5bb1..2569c0abce2 100644 --- a/mozilla/extensions/irc/js/lib/connection-xpcom.js +++ b/mozilla/extensions/irc/js/lib/connection-xpcom.js @@ -51,7 +51,7 @@ const NS_NET_STATUS_SENDING_TO = NS_ERROR_MODULE_NETWORK + 5; const NS_NET_STATUS_RECEIVING_FROM = NS_ERROR_MODULE_NETWORK + 6; const NS_NET_STATUS_CONNECTING_TO = NS_ERROR_MODULE_NETWORK + 7; -// Security Constants. +// Security Constants. const STATE_IS_BROKEN = 1; const STATE_IS_SECURE = 2; const STATE_IS_INSECURE = 3; @@ -166,47 +166,67 @@ function CBSConnection (binary) CBSConnection.prototype.workingBinaryStreams = -1; CBSConnection.prototype.connect = -function bc_connect(host, port, bind, tcp_flag, isSecure, observer) +function bc_connect(host, port, config, observer) { - if (typeof tcp_flag == "undefined") - tcp_flag = false; - this.host = host.toLowerCase(); this.port = port; - this.bind = bind; - this.tcp_flag = tcp_flag; + + if (typeof config != "object") + config = {}; // Lets get a transportInfo for this - var cls = - Components.classes["@mozilla.org/network/protocol-proxy-service;1"]; - var pps = cls.getService(Components.interfaces.nsIProtocolProxyService); - + var pps = getService("@mozilla.org/network/protocol-proxy-service;1", + "nsIProtocolProxyService"); if (!pps) throw ("Couldn't get protocol proxy service"); - var ios = Components.classes["@mozilla.org/network/io-service;1"]. - getService(Components.interfaces.nsIIOService); - var spec = "irc://" + host + ':' + port; - var uri = ios.newURI(spec,null,null); - // As of 2005-03-25, 'examineForProxy' was replaced by 'resolve'. - var info = null; - if ("resolve" in pps) - info = pps.resolve(uri, 0); - else if ("examineForProxy" in pps) - info = pps.examineForProxy(uri); + var ios = getService("@mozilla.org/network/io-service;1", "nsIIOService"); + + function getProxyFor(uri) + { + var uri = ios.newURI(uri, null, null); + // As of 2005-03-25, 'examineForProxy' was replaced by 'resolve'. + if ("resolve" in pps) + return pps.resolve(uri, 0); + if ("examineForProxy" in pps) + return pps.examineForProxy(uri); + return null; + }; + + var proxyInfo = null; + var usingHTTPCONNECT = false; + if ("proxy" in config) + { + /* Force Necko to supply the HTTP proxy info if desired. For none, + * force no proxy. Other values will get default treatment. + */ + if (config.proxy == "http") + proxyInfo = getProxyFor("http://" + host + ":" + port); + else if (config.proxy != "none") + proxyInfo = getProxyFor("irc://" + host + ":" + port); + + /* Since the proxy info is opaque, we need to check that we got + * something for our HTTP proxy - we can't just check proxyInfo.type. + */ + usingHTTPCONNECT = ((config.proxy == "http") && proxyInfo); + } + else + { + proxyInfo = getProxyFor("irc://" + host + ":" + port); + } if (jsenv.HAS_STREAM_PROVIDER) { - if (isSecure) + if (("isSecure" in config) && config.isSecure) { this._transport = this._sockService. - createTransportOfType("ssl", host, port, info, - 0, 0); + createTransportOfType("ssl", host, port, + proxyInfo, 0, 0); } else { this._transport = this._sockService. - createTransport(host, port, info, 0, 0); + createTransport(host, port, proxyInfo, 0, 0); } if (!this._transport) throw ("Error creating transport."); @@ -238,15 +258,16 @@ function bc_connect(host, port, bind, tcp_flag, isSecure, observer) else { /* use new necko interfaces */ - if (isSecure) + if (("isSecure" in config) && config.isSecure) { this._transport = this._sockService. - createTransport(["ssl"], 1, host, port, info); + createTransport(["ssl"], 1, host, port, + proxyInfo); } else { this._transport = this._sockService. - createTransport(null, 0, host, port, info); + createTransport(null, 0, host, port, proxyInfo); } if (!this._transport) throw ("Error creating transport."); @@ -276,6 +297,12 @@ function bc_connect(host, port, bind, tcp_flag, isSecure, observer) this.connectDate = new Date(); this.isConnected = true; + // Bootstrap the connection if we're proxying via an HTTP proxy. + if (usingHTTPCONNECT) + { + this.sendData("CONNECT " + host + ":" + port + " HTTP/1.1\r\n\r\n"); + } + return this.isConnected; } @@ -313,8 +340,6 @@ function bc_accept(transport, observer) this._transport = transport; this.host = this._transport.host.toLowerCase(); this.port = this._transport.port; - //this.bind = bind; - //this.tcp_flag = tcp_flag; if (jsenv.HAS_STREAM_PROVIDER) { diff --git a/mozilla/extensions/irc/js/lib/dcc.js b/mozilla/extensions/irc/js/lib/dcc.js index 67a43bb1c1a..6bc24363b4c 100644 --- a/mozilla/extensions/irc/js/lib/dcc.js +++ b/mozilla/extensions/irc/js/lib/dcc.js @@ -633,7 +633,7 @@ function dchat_accept() this.state.sendAccept(); this.connection = new CBSConnection(); - if (this.connection.connect(this.remoteIP, this.port, null, true, null)) + if (this.connection.connect(this.remoteIP, this.port)) { this.state.socketConnected(); @@ -1061,7 +1061,7 @@ function dfile_accept(localFile) this.connection = new CBSConnection(true); this.position = 0; - if (this.connection.connect(this.remoteIP, this.port, null, true, null)) + if (this.connection.connect(this.remoteIP, this.port)) { this.state.socketConnected(); diff --git a/mozilla/extensions/irc/js/lib/irc.js b/mozilla/extensions/irc/js/lib/irc.js index 5abcbd57911..bcc38b440f7 100644 --- a/mozilla/extensions/irc/js/lib/irc.js +++ b/mozilla/extensions/irc/js/lib/irc.js @@ -130,6 +130,9 @@ CIRCNetwork.prototype.MAX_CONNECT_ATTEMPTS = 5; CIRCNetwork.prototype.getReconnectDelayMs = function() { return 15000; } CIRCNetwork.prototype.stayingPower = false; +// "http" = use HTTP proxy, "none" = none, anything else = auto. +CIRCNetwork.prototype.PROXY_TYPE_OVERRIDE = ""; + CIRCNetwork.prototype.TYPE = "IRCNetwork"; CIRCNetwork.prototype.getURL = @@ -212,6 +215,19 @@ function net_delayedConnect(eventProperties) network.immediateConnect(eventProperties); }; + if ((-1 != this.MAX_CONNECT_ATTEMPTS) && + (this.connectAttempt >= this.MAX_CONNECT_ATTEMPTS)) + { + this.state = NET_OFFLINE; + + var ev = new CEvent("network", "error", this, "onError"); + ev.debug = "Connection attempts exhausted, giving up."; + ev.errorCode = JSIRC_ERR_EXHAUSTED; + this.eventPump.addEvent(ev); + + return; + } + this.state = NET_WAITING; this.reconnectTimer = setTimeout(reconnectFn, this.getReconnectDelayMs(), @@ -344,20 +360,6 @@ function net_doconnect(e) this.connectAttempt++; this.connectCandidate++; - if ((-1 != this.MAX_CONNECT_ATTEMPTS) && - (this.connectAttempt > this.MAX_CONNECT_ATTEMPTS)) - { - this.state = NET_OFFLINE; - - ev = new CEvent ("network", "error", this, "onError"); - ev.server = this; - ev.debug = "Connection attempts exhausted, giving up."; - ev.errorCode = JSIRC_ERR_EXHAUSTED; - this.eventPump.addEvent(ev); - - return false; - } - this.state = NET_CONNECTING; /* connection is considered "made" when server * sends a 001 message (see server.on001) */ @@ -674,7 +676,11 @@ function serv_connect (password) return false; } - if (this.connection.connect(this.hostname, this.port, null, true, this.isSecure, null)) + var config = { isSecure: this.isSecure }; + if (this.parent.PROXY_TYPE_OVERRIDE) + config.proxy = this.parent.PROXY_TYPE_OVERRIDE; + + if (this.connection.connect(this.hostname, this.port, config)) { var ev = new CEvent("server", "connect", this, "onConnect"); @@ -2271,48 +2277,74 @@ function serv_invite(e) CIRCServer.prototype.onNotice = function serv_notice (e) { - if (!("user" in e)) + var targetName = e.params[1]; + + // Strip off one (and only one) user mode prefix. + for (var i = 0; i < this.userModes.length; i++) + { + if (targetName[0] == this.userModes[i].symbol) + { + targetName = targetName.substr(1); + break; + } + } + + if (arrayIndexOf(this.channelTypes, targetName[0]) != -1) + { + e.channel = new CIRCChannel(this, null, targetName); + if ("user" in e) + e.user = new CIRCChanUser(e.channel, e.user.unicodeName); + e.replyTo = e.channel; + e.set = "channel"; + } + else if (!("user" in e)) { e.set = "network"; e.destObject = this.parent; return true; } - - if (arrayIndexOf(this.channelTypes, e.params[1][0]) != -1) + else { - e.channel = new CIRCChannel(this, null, e.params[1]); - e.user = new CIRCChanUser(e.channel, e.user.unicodeName); - e.replyTo = e.channel; - e.set = "channel"; + e.set = "user"; + e.replyTo = e.user; /* send replies to the user who sent the message */ } - else if (e.params[2].search (/\x01.*\x01/i) != -1) + + if (e.params[2].search (/\x01.*\x01/i) != -1) { e.type = "ctcp-reply"; e.destMethod = "onCTCPReply"; e.set = "server"; e.destObject = this; - return true; } else { - e.set = "user"; - e.replyTo = e.user; /* send replys to the user who sent the message */ + e.msg = e.decodeParam(2, e.replyTo); + e.destObject = e.replyTo; } - e.msg = e.decodeParam(2, e.replyTo); - e.destObject = e.replyTo; - return true; } CIRCServer.prototype.onPrivmsg = function serv_privmsg (e) { - /* setting replyTo provides a standard place to find the target for */ - /* replys associated with this event. */ - if (arrayIndexOf(this.channelTypes, e.params[1][0]) != -1) + var targetName = e.params[1]; + + // Strip off one (and only one) user mode prefix. + for (var i = 0; i < this.userModes.length; i++) { - e.channel = new CIRCChannel(this, null, e.params[1]); + if (targetName[0] == this.userModes[i].symbol) + { + targetName = targetName.substr(1); + break; + } + } + + /* setting replyTo provides a standard place to find the target for */ + /* replies associated with this event. */ + if (arrayIndexOf(this.channelTypes, targetName[0]) != -1) + { + e.channel = new CIRCChannel(this, null, targetName); e.user = new CIRCChanUser(e.channel, e.user.unicodeName); e.replyTo = e.channel; e.set = "channel"; diff --git a/mozilla/extensions/irc/js/lib/utils.js b/mozilla/extensions/irc/js/lib/utils.js index ad42b23bbec..bab101f28f5 100644 --- a/mozilla/extensions/irc/js/lib/utils.js +++ b/mozilla/extensions/irc/js/lib/utils.js @@ -682,14 +682,26 @@ function formatDateOffset (offset, format) if (!format) { var ary = new Array(); - if (days > 0) - ary.push (getMsg(MSG_DAYS, days)); - if (hours > 0) - ary.push (getMsg(MSG_HOURS, hours)); - if (minutes > 0) - ary.push (getMsg(MSG_MINUTES, minutes)); - if (seconds > 0 || offset == 0) - ary.push (getMsg(MSG_SECONDS, seconds)); + + if (days == 1) + ary.push(MSG_DAY); + else if (days > 0) + ary.push(getMsg(MSG_DAYS, days)); + + if (hours == 1) + ary.push(MSG_HOUR); + else if (hours > 0) + ary.push(getMsg(MSG_HOURS, hours)); + + if (minutes == 1) + ary.push(MSG_MINUTE); + else if (minutes > 0) + ary.push(getMsg(MSG_MINUTES, minutes)); + + if (seconds == 1) + ary.push(MSG_SECOND); + else if (seconds > 0 || offset == 0) + ary.push(getMsg(MSG_SECONDS, seconds)); format = ary.join(", "); } diff --git a/mozilla/extensions/irc/xpi/resources/install.rdf b/mozilla/extensions/irc/xpi/resources/install.rdf index 76acbeddc3c..f509c9a5dab 100644 --- a/mozilla/extensions/irc/xpi/resources/install.rdf +++ b/mozilla/extensions/irc/xpi/resources/install.rdf @@ -14,21 +14,21 @@ - + {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - 0.9 - 3.0 + 1.0 + 3.0a1 - + {92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} 1.0 - 1.0 + 1.1 diff --git a/mozilla/extensions/irc/xul/content/commands.js b/mozilla/extensions/irc/xul/content/commands.js index 7a595651e11..4b8f2098c7e 100644 --- a/mozilla/extensions/irc/xul/content/commands.js +++ b/mozilla/extensions/irc/xul/content/commands.js @@ -354,6 +354,12 @@ function dispatch(text, e, isInteractive, flags) /* split command from arguments */ var ary = text.match(/(\S+) ?(.*)/); + if (!ary) + { + display(getMsg(MSG_ERR_NO_COMMAND, "")); + return null; + } + e.commandText = ary[1]; if (ary[2]) e.inputData = stringTrim(ary[2]); @@ -381,6 +387,21 @@ function dispatch(text, e, isInteractive, flags) case 1: /* one match, good for you */ + var cm = client.commandManager; + + if (cm.currentDispatchDepth >= cm.maxDispatchDepth) + { + /* We've reatched the max dispatch depth, so we need to unwind + * the entire stack of commands. + */ + cm.dispatchUnwinding = true; + } + // Don't start any new commands while unwinding. + if (cm.dispatchUnwinding) + break; + + cm.currentDispatchDepth++; + var ex; try { @@ -396,6 +417,19 @@ function dispatch(text, e, isInteractive, flags) else dd(formatException(ex), MT_ERROR); } + + cm.currentDispatchDepth--; + if (cm.dispatchUnwinding && (cm.currentDispatchDepth == 0)) + { + /* Last level to unwind, and this is where we display the + * message. We need to leave it until here because displaying + * a message invokes a couple of commands itself, and we need + * to not be right on the dispatch limit for that. + */ + cm.dispatchUnwinding = false; + display(getMsg(MSG_ERR_MAX_DISPATCH_DEPTH, ary[0].name), + MT_ERROR); + } break; default: @@ -1859,28 +1893,47 @@ function cmdDescribe(e) function cmdMode(e) { - // get our canonical channel name, so we know what channel we talk about - var chan = fromUnicode(e.target, e.server); + var chan; // Make sure the user can leave the channel name out from a channel view. - if (e.channel && /^[\+\-].+/.test(e.target) && - !(e.server.toLowerCase(chan) in e.server.channels)) + if ((!e.target || /^[\+\-].+/.test(e.target)) && + !(chan && e.server.getChannel(chan))) { - chan = e.channel.canonicalName; - if (e.param && e.modestr) + if (e.channel) { - e.paramList.unshift(e.modestr); + chan = e.channel.canonicalName; + if (e.param && e.modestr) + { + e.paramList.unshift(e.modestr); + } + else if (e.modestr) + { + e.paramList = [e.modestr]; + e.param = e.modestr; + } + e.modestr = e.target; } - else if (e.modestr) + else { - e.paramList = [e.modestr]; - e.param = e.modestr; + display(getMsg(MSG_ERR_REQUIRED_PARAM, "target"), MT_ERROR); + return; } - e.modestr = e.target; + } + else + { + chan = fromUnicode(e.target, e.server); } // Check whether our mode string makes sense - if (!(/^([+-][a-z]+)+$/i).test(e.modestr)) + if (!e.modestr) + { + e.modestr = ""; + if (!e.channel && arrayContains(e.server.channelTypes, chan[0])) + e.channel = new CIRCChannel(e.server, null, chan); + if (e.channel) + e.channel.pendingModeReply = true; + } + else if (!(/^([+-][a-z]+)+$/i).test(e.modestr)) { display(getMsg(MSG_ERR_INVALID_MODE, e.modestr), MT_ERROR); return; @@ -1889,7 +1942,6 @@ function cmdMode(e) var params = (e.param) ? " " + e.paramList.join(" ") : ""; e.server.sendData("MODE " + chan + " " + fromUnicode(e.modestr, e.server) + params + "\n"); - } function cmdMotif(e) diff --git a/mozilla/extensions/irc/xul/content/contents.rdf b/mozilla/extensions/irc/xul/content/contents.rdf index d862dcb9cf5..7cc498a875a 100644 --- a/mozilla/extensions/irc/xul/content/contents.rdf +++ b/mozilla/extensions/irc/xul/content/contents.rdf @@ -9,7 +9,7 @@ to the channel as a statement in the thi cmd.motd.help = Displays the "Message of the Day", which usually contains information about the network and current server, as well as any usage policies. -cmd.mode.params = [ [ [<...>]]] +cmd.mode.params = [] [ [ [<...>]]] cmd.mode.help = Changes the channel or user mode of using and any subsequent if added. When used from a channel view, may be omitted. For a list of modes you may use, see http://irchelp.org. cmd.motif.params = [] @@ -709,6 +709,7 @@ msg.err.notimplemented = Sorry, ``%1$S'' has not been implemented. msg.err.required.param = Missing required parameter %1$S. msg.err.ambigcommand = Ambiguous command, ``%1$S'', %2$S commands match [%3$S]. msg.err.required.nr.param = Missing %1$S parameters. This alias requires at least %2$S parameters. +msg.err.max.dispatch.depth = Reached max dispatch depth while attempting to dispatch ``%1$S''. ## chatzilla error messages ## msg.err.invalid.pref = Invalid value for preference %1$S (%2$S). @@ -737,7 +738,6 @@ msg.err.need.recip = Command ``%1$S'' must be run in the context of a user or msg.err.no.default = Please do not just type into this tab, use an actual command instead. msg.err.no.match = No match for ``%S''. msg.err.no.socket = Error creating socket. -msg.err.exhausted = Connection attempts exhausted, giving up. msg.err.no.secure = The network ``%S'' has no secure servers defined. msg.err.cancelled = Connection process canceled. msg.err.offline = The host software platform (e.g. Mozilla, Firefox) is in ``offline mode''. No network connections can be made in this mode. @@ -834,6 +834,10 @@ msg.days = "%S days msg.hours = "%S hours msg.minutes = "%S minutes msg.seconds = "%S seconds +msg.day = 1 day +msg.hour = 1 hour +msg.minute = 1 minute +msg.second = 1 second msg.rsp.hello = [HELLO] @@ -977,6 +981,8 @@ msg.exceptlist.item = "%S excepted %S from bans in %S on %S. msg.exceptlist.button = [[Remove][Remove this ban exception][%S]] msg.exceptlist.end = End of %S exception list. +msg.channel.needops = You need to be an operator in %S to do that. + msg.ctcphelp.clientinfo = CLIENTINFO gives information on available CTCP commands msg.ctcphelp.action = ACTION performs an action at the user msg.ctcphelp.time = TIME gives the local date and time for the client @@ -1088,8 +1094,8 @@ msg.si.speed.6 = EiB/s msg.ident.server.not.possible = Ident Server is unavailable in this version of the host software platform (e.g. Mozilla, Firefox) - the feature "scriptable server sockets" is missing. Mozilla builds after 2003-11-15 should contain this feature (e.g. Mozilla 1.6 or later). -msg.url.password = Enter a password for the url %S: -msg.url.key = Enter key for url %S: +msg.host.password = Enter a password for the server %S: +msg.url.key = Enter key for url %S: msg.startup.added = <%1$S> will now open at startup. msg.startup.removed = <%1$S> will no longer open at startup. @@ -1154,8 +1160,7 @@ msg.list.end = Displayed %S of %S channels. msg.who.end = End of WHO results for ``%S'', %S user(s) found. msg.who.match = User %S, (%S@%S) ``%S'' (%S), member of %S, is connected to , %S hop(s). -msg.connection.attempt = Connecting to %S (%S), attempt %S of %S... -msg.connection.attempt.unlimited = Connecting to %S (%S), attempt %S, next attempt in %S seconds... +msg.connection.attempt = Connecting to %S (%S)... msg.connection.refused = Connection to %S (%S) refused. msg.connection.timeout = Connection to %S (%S) timed out. msg.unknown.host = Unknown host ``%S'' connecting to %S (%S). @@ -1164,6 +1169,12 @@ msg.connection.reset = Connection to %S (%S) reset. msg.connection.quit = Disconnected from %S (%S). msg.close.status = Connection to %S (%S) closed with status %S. +# In these messages, %1$S is a connection error from above. +msg.connection.exhausted = "%1$S Connection attempts exhausted, giving up. +msg.reconnecting.in = "%1$S Reconnecting in %2$S. +msg.reconnecting.in.left = "%1$S %2$S attempts left, reconnecting in %3$S. +msg.reconnecting.in.left1 = "%1$S 1 attempt left, reconnecting in %2$S. + msg.reconnecting = Reconnecting... msg.confirm.disconnect.all = Are you sure you want to disconnect from ALL networks? msg.no.connected.nets = You are not connected to any networks. @@ -1186,6 +1197,7 @@ msg.someone.left.reason = "%S has left %S (%S) msg.youre.gone = YOU (%S) have been booted from %S by %S (%S) msg.someone.gone = "%S was booted from %S by %S (%S) +msg.mode.all = Mode for %S is %S" msg.mode.changed = Mode %S by %S" msg.away.on = You are now marked as away (%S). Click the nickname button or use the |/back| command to return from being away. @@ -1457,6 +1469,8 @@ pref.outputWindowURL.label = Output Window pref.outputWindowURL.help = You probably don't want to change this. The chat view loads this URL to display the actual messages, header, etc., and the file must correctly define certain items or you'll get JavaScript errors and a blank chat window! pref.profilePath.label = Profile path pref.profilePath.help = This is the base location for Chatzilla-related files. By default, Chatzilla loads scripts from the "scripts" subdirectory, and stores log files in the "logs" subdirectory. +pref.proxy.typeOverride.label = Proxy Type +pref.proxy.typeOverride.help = Override the normal proxy choice by specifying "http" to use your browser's HTTP Proxy or "none" to force no proxy to be used (not even the SOCKS proxy). Note that this usually only works when the browser is set to use a manual proxy configuration. pref.reconnect.label = Reconnect when disconnected unexpectedly pref.reconnect.help = When your connection is lost unexpectedly, Chatzilla can automatically reconnect to the server for you. pref.showModeSymbols.label = Show user mode symbols