summaryrefslogtreecommitdiff
path: root/src/core/nicklist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/nicklist.c')
-rw-r--r--src/core/nicklist.c91
1 files changed, 69 insertions, 22 deletions
diff --git a/src/core/nicklist.c b/src/core/nicklist.c
index a54b005b..50623dcf 100644
--- a/src/core/nicklist.c
+++ b/src/core/nicklist.c
@@ -262,46 +262,93 @@ static void sig_channel_destroyed(CHANNEL_REC *channel)
g_hash_table_destroy(channel->nicks);
}
+static NICK_REC *nick_nfind(CHANNEL_REC *channel, const char *nick, int len)
+{
+ NICK_REC *rec;
+ char *tmpnick;
+
+ tmpnick = g_strndup(nick, len);
+ rec = g_hash_table_lookup(channel->nicks, tmpnick);
+ g_free(tmpnick);
+ return rec;
+}
+
/* Check is `msg' is meant for `nick'. */
-int nick_match_msg(SERVER_REC *server, const char *msg, const char *nick)
+int nick_match_msg(CHANNEL_REC *channel, const char *msg, const char *nick)
{
- int len;
+ const char *msgstart, *orignick;
+ int len, fullmatch;
g_return_val_if_fail(nick != NULL, FALSE);
g_return_val_if_fail(msg != NULL, FALSE);
- if (server != NULL && server->nick_match_msg != NULL)
- return server->nick_match_msg(msg, nick);
+ if (channel != NULL && channel->server->nick_match_msg != NULL)
+ return channel->server->nick_match_msg(msg, nick);
/* first check for identical match */
len = strlen(nick);
if (g_strncasecmp(msg, nick, len) == 0 && !isalnumhigh((int) msg[len]))
return TRUE;
- /* check if it matches for alphanumeric parts of nick */
- while (*nick != '\0' && *msg != '\0') {
- if (*nick == *msg) {
- /* total match */
- msg++;
- } else if (isalnum(*msg) && !isalnum(*nick)) {
- /* some strange char in your nick, pass it */
- } else
+ orignick = nick;
+ for (;;) {
+ nick = orignick;
+ msgstart = msg;
+ fullmatch = TRUE;
+
+ /* check if it matches for alphanumeric parts of nick */
+ while (*nick != '\0' && *msg != '\0') {
+ if (*nick == *msg) {
+ /* total match */
+ msg++;
+ } else if (isalnum(*msg) && !isalnum(*nick)) {
+ /* some strange char in your nick, pass it */
+ fullmatch = FALSE;
+ } else
+ break;
+
+ nick++;
+ }
+
+ if (msg != msgstart && !isalnumhigh(*msg)) {
+ /* at least some of the chars in line matched the
+ nick, and msg continue with non-alphanum character,
+ this might be for us.. */
+ if (*nick != '\0') {
+ /* remove the rest of the non-alphanum chars
+ from nick and check if it then matches. */
+ fullmatch = FALSE;
+ while (*nick != '\0' && !isalnum(*nick))
+ nick++;
+ }
+
+ if (*nick == '\0') {
+ /* yes, match! */
+ break;
+ }
+ }
+
+ /* no match. check if this is a message to multiple people
+ (like nick1,nick2: text) */
+ while (*msg != '\0' && *msg != ' ' && *msg != ',') msg++;
+
+ if (*msg != ',') {
+ nick = orignick;
break;
+ }
- nick++;
+ msg++;
}
- if (isalnumhigh(*msg)) {
- /* message continues with another alphanumeric character,
- it isn't for us. */
- return FALSE;
- }
+ if (*nick != '\0')
+ return FALSE; /* didn't match */
- /* remove all the non-alphanumeric characters at the end of
- the nick and check if message matched that far. */
- while (*nick != '\0' && !isalnum(*nick)) nick++;
+ if (fullmatch)
+ return TRUE; /* matched without fuzzyness */
- return *nick == '\0';
+ /* matched with some fuzzyness .. check if there's an exact match
+ for some other nick in the same channel. */
+ return nick_nfind(channel, msgstart, (int) (msg-msgstart)) == NULL;
}
void nicklist_init(void)