diff --git a/mozilla/extensions/irc/js/lib/irc.js b/mozilla/extensions/irc/js/lib/irc.js index cf17eead050..f1d6a5f4489 100644 --- a/mozilla/extensions/irc/js/lib/irc.js +++ b/mozilla/extensions/irc/js/lib/irc.js @@ -101,6 +101,8 @@ function CIRCNetwork (name, serverList, eventPump) this.name = name; this.servers = new Object(); this.serverList = new Array(); + this.ignoreList = new Object(); + this.ignoreMaskCache = new Object(); this.connecting = false; for (var i = 0; i < serverList.length; ++i) @@ -239,6 +241,32 @@ function net_connected (e) return ("primServ" in this && this.primServ.isConnected); } +CIRCNetwork.prototype.ignore = +function net_ignore (hostmask) +{ + var input = getHostmaskParts(hostmask); + + if (input.mask in this.ignoreList) + return false; + + this.ignoreList[input.mask] = input; + this.ignoreMaskCache = new Object(); + return true; +} + +CIRCNetwork.prototype.unignore = +function net_ignore (hostmask) +{ + var input = getHostmaskParts(hostmask); + + if (!(input.mask in this.ignoreList)) + return false; + + delete this.ignoreList[input.mask]; + this.ignoreMaskCache = new Object(); + return true; +} + /* * irc server */ @@ -765,6 +793,51 @@ function serv_ppline(e) CIRCServer.prototype.onRawData = function serv_onRawData(e) { + function makeMaskRegExp(text) + { + function escapeChars(c) + { + if (c == "*") + return ".*"; + if (c == "?") + return "."; + return "\\" + c; + } + // Anything that's not alpha-numeric gets escaped. + // "*" and "?" are 'escaped' to ".*" and ".". + // Optimisation; * translates as 'match all'. + return new RegExp("^" + text.replace(/[^\w\d]/g, escapeChars) + "$", "i"); + }; + function hostmaskMatches(user, mask) + { + // Need to match .nick, .user, and .host. + if (!("nickRE" in mask)) + { + // We cache all the regexp objects, but use null if the term is + // just "*", so we can skip having the object *and* the .match + // later on. + if (mask.nick == "*") + mask.nickRE = null; + else + mask.nickRE = makeMaskRegExp(mask.nick); + + if (mask.user == "*") + mask.userRE = null; + else + mask.userRE = makeMaskRegExp(mask.user); + + if (mask.host == "*") + mask.hostRE = null; + else + mask.hostRE = makeMaskRegExp(mask.host); + } + if ((!mask.nickRE || user.nick.match(mask.nickRE)) && + (!mask.userRE || user.name.match(mask.userRE)) && + (!mask.hostRE || user.host.match(mask.hostRE))) + return true; + return false; + }; + var ary; var l = e.data; @@ -793,6 +866,33 @@ function serv_onRawData(e) } } } + + e.ignored = false; + if (("user" in e) && e.user && ("ignoreList" in this.parent)) + { + // Assumption: if "ignoreList" is in this.parent, we assume that: + // a) it's an array. + // b) ignoreMaskCache also exists, and + // c) it's an array too. + + if (!(e.source in this.parent.ignoreMaskCache)) + { + for (var m in this.parent.ignoreList) + { + if (hostmaskMatches(e.user, this.parent.ignoreList[m])) + { + e.ignored = true; + break; + } + } + /* Save this exact source in the cache, with results of tests. */ + this.parent.ignoreMaskCache[e.source] = e.ignored; + } + else + { + e.ignored = this.parent.ignoreMaskCache[e.source]; + } + } e.server = this; @@ -811,6 +911,10 @@ function serv_onRawData(e) e.decodeParam = decodeParam; e.code = e.params[0].toUpperCase(); + + // Ignore all Privmsg and Notice messages here. + if (e.ignored && ((e.code == "PRIVMSG") || (e.code == "NOTICE"))) + return true; e.type = "parseddata"; e.destObject = this; diff --git a/mozilla/extensions/irc/js/lib/utils.js b/mozilla/extensions/irc/js/lib/utils.js index db624ab2fe6..d03f87994ce 100644 --- a/mozilla/extensions/irc/js/lib/utils.js +++ b/mozilla/extensions/irc/js/lib/utils.js @@ -917,3 +917,31 @@ function promptPassword(msg, initial, parent, title) return rv.value; } + +function getHostmaskParts(hostmask) +{ + var rv; + // A bit cheeky this, we try the matches here, and then branch + // according to the ones we like. + var ary1 = hostmask.match(/(\S*)!(\S*)@(.*)/); + var ary2 = hostmask.match(/(\S*)@(.*)/); + var ary3 = hostmask.match(/(\S*)!(.*)/); + if (ary1) + rv = { nick: ary1[1], user: ary1[2], host: ary1[3] }; + else if (ary2) + rv = { nick: "*", user: ary2[1], host: ary2[2] }; + else if (ary3) + rv = { nick: ary3[1], user: ary3[2], host: "*" }; + else + rv = { nick: hostmask, user: "*", host: "*" }; + // Make sure we got something for all fields. + if (!rv.nick) + rv.nick = "*"; + if (!rv.user) + rv.user = "*"; + if (!rv.host) + rv.host = "*"; + // And re-construct the 'parsed' hostmask. + rv.mask = rv.nick + "!" + rv.user + "@" + rv.host; + return rv; +} diff --git a/mozilla/extensions/irc/xul/content/commands.js b/mozilla/extensions/irc/xul/content/commands.js index dd3d8490878..8882afc3410 100644 --- a/mozilla/extensions/irc/xul/content/commands.js +++ b/mozilla/extensions/irc/xul/content/commands.js @@ -78,6 +78,7 @@ function initCommands() ["goto-url-newtab", cmdGotoURL, 0], ["help", cmdHelp, CMD_CONSOLE], ["hide-view", cmdHideView, CMD_CONSOLE], + ["ignore", cmdIgnore, CMD_NEED_NET | CMD_CONSOLE], ["invite", cmdInvite, CMD_NEED_SRV | CMD_CONSOLE], ["join", cmdJoin, CMD_NEED_SRV | CMD_CONSOLE], ["join-charset", cmdJoin, CMD_NEED_SRV | CMD_CONSOLE], @@ -123,6 +124,7 @@ function initCommands() ["toggle-ui", cmdToggleUI, CMD_CONSOLE], ["toggle-pref", cmdTogglePref, 0], ["topic", cmdTopic, CMD_NEED_CHAN | CMD_CONSOLE], + ["unignore", cmdIgnore, CMD_NEED_NET | CMD_CONSOLE], ["unstalk", cmdUnstalk, CMD_CONSOLE], ["usermode", cmdUsermode, CMD_CONSOLE], ["user-charset", cmdCharset, CMD_NEED_USER | CMD_CONSOLE], @@ -2191,3 +2193,37 @@ function cmdTimestampFormat(e) view.prefs["timestampFormat"]])); } } + +function cmdIgnore(e) +{ + if (("mask" in e) && e.mask) + { + // FIXME: This is incorrect if CASEMAPPING is not ASCII, see bug 190749. + e.mask = e.mask.toLowerCase(); + + if (e.command.name == "ignore") + { + if (e.network.ignore(e.mask)) + display(getMsg(MSG_IGNORE_ADD, e.mask)); + else + display(getMsg(MSG_IGNORE_ADDERR, e.mask)); + } + else + { + if (e.network.unignore(e.mask)) + display(getMsg(MSG_IGNORE_DEL, e.mask)); + else + display(getMsg(MSG_IGNORE_DELERR, e.mask)); + } + } + else + { + var list = new Array(); + for (var m in e.network.ignoreList) + list.push(m); + if (list.length == 0) + display(MSG_IGNORE_LIST_1); + else + display(getMsg(MSG_IGNORE_LIST_2, arraySpeak(list))); + } +} diff --git a/mozilla/extensions/irc/xul/content/static.js b/mozilla/extensions/irc/xul/content/static.js index 32fc917ced0..1472ee78287 100644 --- a/mozilla/extensions/irc/xul/content/static.js +++ b/mozilla/extensions/irc/xul/content/static.js @@ -34,7 +34,7 @@ * Samuel Sieb, samuel@sieb.net, MIRC color codes, munger menu, and various */ -const __cz_version = "0.9.57"; +const __cz_version = "0.9.58"; const __cz_condition = "green"; var warn; diff --git a/mozilla/extensions/irc/xul/locale/en-US/chatzilla.properties b/mozilla/extensions/irc/xul/locale/en-US/chatzilla.properties index 22700449730..7560c371b29 100644 --- a/mozilla/extensions/irc/xul/locale/en-US/chatzilla.properties +++ b/mozilla/extensions/irc/xul/locale/en-US/chatzilla.properties @@ -194,6 +194,9 @@ cmd.toggle-timestamps.label = Show &Timestamps cmd.userlist.help = Toggles the visibility of the user list. +cmd.ignore.params = [] +cmd.ignore.help = Add someone to your ignore list for the current network. A nickname will suffice for , but you can also use a hostmask. With no parameters, it shows a list of all currently ignored users. + cmd.invite.params = [] cmd.invite.help = Invites to or current channel if not supplied. Requires operator status if +i is set. @@ -341,6 +344,9 @@ cmd.topic.help = If is specified and you are a chanop, or the chan cmd.tabstrip.help = Toggles the visibility of the channel tab strip. +cmd.unignore.params = +cmd.unignore.help = Removes someone from your ignore list for the current network. A nickname will suffice for , but you can also use a hostmask. + cmd.unstalk.params = cmd.unstalk.help = Remove word from list of terms for which you would like to see alerts. @@ -627,6 +633,13 @@ msg.whois.server = %S: attached to %S ``%S'' msg.whois.idle = %S: idle for %S (on since %S) msg.whois.end = End of WHOIS information for %S +msg.ignore.list.1 = Currently not ignoring anyone. +msg.ignore.list.2 = Currently ignoring [%S]. +msg.ignore.add = You are now ignoring %S. +msg.ignore.adderr = You are already ignoring %s. +msg.ignore.del = You are no longer ignoring %S. +msg.ignore.delerr = %S not found in your ignore list. + msg.you.invite = You have invited %S to %S msg.invite.you = %S (%S@%S) has invited you to %S