mirror of
https://github.com/moparisthebest/hexchat
synced 2024-12-22 15:48:52 -05:00
Merge pull request #700 from orium/url-chan-prefix
Server aware nickname and channel matching
This commit is contained in:
commit
ce40e5a111
238
src/common/url.c
238
src/common/url.c
@ -32,15 +32,22 @@
|
|||||||
|
|
||||||
void *url_tree = NULL;
|
void *url_tree = NULL;
|
||||||
GTree *url_btree = NULL;
|
GTree *url_btree = NULL;
|
||||||
static int do_an_re (const char *word, int *start, int *end, int *type);
|
static gboolean regex_match (const GRegex *re, const char *word,
|
||||||
static GRegex *re_url (void);
|
int *start, int *end);
|
||||||
static GRegex *re_host (void);
|
static const GRegex *re_url (void);
|
||||||
static GRegex *re_host6 (void);
|
static const GRegex *re_host (void);
|
||||||
static GRegex *re_email (void);
|
static const GRegex *re_host6 (void);
|
||||||
static GRegex *re_nick (void);
|
static const GRegex *re_email (void);
|
||||||
static GRegex *re_channel (void);
|
static const GRegex *re_nick (void);
|
||||||
static GRegex *re_path (void);
|
static const GRegex *re_channel (void);
|
||||||
|
static const GRegex *re_path (void);
|
||||||
|
static gboolean match_nick (const char *word, int *start, int *end);
|
||||||
|
static gboolean match_channel (const char *word, int *start, int *end);
|
||||||
|
static gboolean match_email (const char *word, int *start, int *end);
|
||||||
|
static gboolean match_url (const char *word, int *start, int *end);
|
||||||
|
static gboolean match_host (const char *word, int *start, int *end);
|
||||||
|
static gboolean match_host6 (const char *word, int *start, int *end);
|
||||||
|
static gboolean match_path (const char *word, int *start, int *end);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
url_free (char *url, void *data)
|
url_free (char *url, void *data)
|
||||||
@ -189,50 +196,111 @@ static int laststart = 0;
|
|||||||
static int lastend = 0;
|
static int lastend = 0;
|
||||||
static int lasttype = 0;
|
static int lasttype = 0;
|
||||||
|
|
||||||
static int
|
#define NICKPRE "~+!@%&"
|
||||||
strchrs (char c, char *s)
|
#define CHANPRE "#&!+"
|
||||||
{
|
|
||||||
while (*s)
|
|
||||||
if (c == *s++)
|
|
||||||
return TRUE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NICKPRE "~+!@%%&"
|
|
||||||
int
|
int
|
||||||
url_check_word (const char *word)
|
url_check_word (const char *word)
|
||||||
{
|
{
|
||||||
laststart = lastend = lasttype = 0;
|
struct {
|
||||||
if (do_an_re (word, &laststart, &lastend, &lasttype))
|
gboolean (*match) (const char *word, int *start, int *end);
|
||||||
{
|
int type;
|
||||||
switch (lasttype)
|
} m[] = {
|
||||||
{
|
{ match_url, WORD_URL },
|
||||||
char *str;
|
{ match_email, WORD_EMAIL },
|
||||||
|
{ match_nick, WORD_NICK },
|
||||||
|
{ match_channel, WORD_CHANNEL },
|
||||||
|
{ match_host6, WORD_HOST6 },
|
||||||
|
{ match_host, WORD_HOST },
|
||||||
|
{ match_path, WORD_PATH },
|
||||||
|
{ NULL, 0}
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
case WORD_NICK:
|
laststart = lastend = lasttype = 0;
|
||||||
if (strchrs (word[laststart], NICKPRE))
|
|
||||||
laststart++;
|
for (i = 0; m[i].match; i++)
|
||||||
str = g_strndup (&word[laststart], lastend - laststart);
|
if (m[i].match (word, &laststart, &lastend))
|
||||||
if (!userlist_find (current_sess, str))
|
{
|
||||||
lasttype = 0;
|
lasttype = m[i].type;
|
||||||
g_free (str);
|
return lasttype;
|
||||||
return lasttype;
|
|
||||||
case WORD_EMAIL:
|
|
||||||
if (!isalnum (word[laststart]))
|
|
||||||
laststart++;
|
|
||||||
/* Fall through */
|
|
||||||
case WORD_URL:
|
|
||||||
case WORD_HOST:
|
|
||||||
case WORD_HOST6:
|
|
||||||
case WORD_CHANNEL:
|
|
||||||
case WORD_PATH:
|
|
||||||
return lasttype;
|
|
||||||
default:
|
|
||||||
return 0; /* Should not occur */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
match_nick (const char *word, int *start, int *end)
|
||||||
|
{
|
||||||
|
const server *serv = current_sess->server;
|
||||||
|
const char *nick_prefixes = serv ? serv->nick_prefixes : NICKPRE;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
if (!regex_match (re_nick (), word, start, end))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* ignore matches with prefixes that the server doesn't use */
|
||||||
|
if (strchr (NICKPRE, word[*start])
|
||||||
|
&& !strchr (nick_prefixes, word[*start]))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* nick prefix is not part of the matched word */
|
||||||
|
if (strchr (nick_prefixes, word[*start]))
|
||||||
|
(*start)++;
|
||||||
|
|
||||||
|
str = g_strndup (&word[*start], *end - *start);
|
||||||
|
|
||||||
|
if (!userlist_find (current_sess, str))
|
||||||
|
{
|
||||||
|
g_free (str);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return 0;
|
g_free (str);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
match_channel (const char *word, int *start, int *end)
|
||||||
|
{
|
||||||
|
const server *serv = current_sess->server;
|
||||||
|
const char *chan_prefixes = serv ? serv->chantypes : CHANPRE;
|
||||||
|
|
||||||
|
if (!regex_match (re_channel (), word, start, end))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return strchr (chan_prefixes, word[*start]) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
match_email (const char *word, int *start, int *end)
|
||||||
|
{
|
||||||
|
return regex_match (re_email (), word, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
match_url (const char *word, int *start, int *end)
|
||||||
|
{
|
||||||
|
return regex_match (re_url (), word, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
match_host (const char *word, int *start, int *end)
|
||||||
|
{
|
||||||
|
return regex_match (re_host (), word, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
match_host6 (const char *word, int *start, int *end)
|
||||||
|
{
|
||||||
|
return regex_match (re_host6 (), word, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
match_path (const char *word, int *start, int *end)
|
||||||
|
{
|
||||||
|
return regex_match (re_path (), word, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* List of IRC commands for which contents (and thus possible URLs)
|
/* List of IRC commands for which contents (and thus possible URLs)
|
||||||
@ -307,46 +375,28 @@ url_last (int *lstart, int *lend)
|
|||||||
return lasttype;
|
return lasttype;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static gboolean
|
||||||
do_an_re(const char *word, int *start, int *end, int *type)
|
regex_match (const GRegex *re, const char *word, int *start, int *end)
|
||||||
{
|
{
|
||||||
typedef struct func_s {
|
|
||||||
GRegex *(*fn)(void);
|
|
||||||
int type;
|
|
||||||
} func_t;
|
|
||||||
func_t funcs[] =
|
|
||||||
{
|
|
||||||
{ re_url, WORD_URL },
|
|
||||||
{ re_email, WORD_EMAIL },
|
|
||||||
{ re_channel, WORD_CHANNEL },
|
|
||||||
{ re_host6, WORD_HOST6 },
|
|
||||||
{ re_host, WORD_HOST },
|
|
||||||
{ re_path, WORD_PATH },
|
|
||||||
{ re_nick, WORD_NICK }
|
|
||||||
};
|
|
||||||
|
|
||||||
GMatchInfo *gmi;
|
GMatchInfo *gmi;
|
||||||
int k;
|
|
||||||
|
|
||||||
for (k = 0; k < sizeof funcs / sizeof (func_t); k++)
|
g_regex_match (re, word, 0, &gmi);
|
||||||
|
|
||||||
|
if (!g_match_info_matches (gmi))
|
||||||
{
|
{
|
||||||
g_regex_match (funcs[k].fn(), word, 0, &gmi);
|
|
||||||
if (!g_match_info_matches (gmi))
|
|
||||||
{
|
|
||||||
g_match_info_free (gmi);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
while (g_match_info_matches (gmi))
|
|
||||||
{
|
|
||||||
g_match_info_fetch_pos (gmi, 0, start, end);
|
|
||||||
g_match_info_next (gmi, NULL);
|
|
||||||
}
|
|
||||||
g_match_info_free (gmi);
|
g_match_info_free (gmi);
|
||||||
*type = funcs[k].type;
|
return FALSE;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
while (g_match_info_matches (gmi))
|
||||||
|
{
|
||||||
|
g_match_info_fetch_pos (gmi, 0, start, end);
|
||||||
|
g_match_info_next (gmi, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_match_info_free (gmi);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Miscellaneous description --- */
|
/* Miscellaneous description --- */
|
||||||
@ -376,7 +426,7 @@ make_re (char *grist)
|
|||||||
|
|
||||||
/* HOST description --- */
|
/* HOST description --- */
|
||||||
/* (see miscellaneous above) */
|
/* (see miscellaneous above) */
|
||||||
static GRegex *
|
static const GRegex *
|
||||||
re_host (void)
|
re_host (void)
|
||||||
{
|
{
|
||||||
static GRegex *host_ret;
|
static GRegex *host_ret;
|
||||||
@ -384,7 +434,7 @@ re_host (void)
|
|||||||
|
|
||||||
if (host_ret) return host_ret;
|
if (host_ret) return host_ret;
|
||||||
|
|
||||||
grist = g_strdup_printf (
|
grist = g_strdup (
|
||||||
"("
|
"("
|
||||||
"(" HOST_URL PORT ")|(" HOST ")"
|
"(" HOST_URL PORT ")|(" HOST ")"
|
||||||
")"
|
")"
|
||||||
@ -393,7 +443,7 @@ re_host (void)
|
|||||||
return host_ret;
|
return host_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GRegex *
|
static const GRegex *
|
||||||
re_host6 (void)
|
re_host6 (void)
|
||||||
{
|
{
|
||||||
static GRegex *host6_ret;
|
static GRegex *host6_ret;
|
||||||
@ -401,7 +451,7 @@ re_host6 (void)
|
|||||||
|
|
||||||
if (host6_ret) return host6_ret;
|
if (host6_ret) return host6_ret;
|
||||||
|
|
||||||
grist = g_strdup_printf (
|
grist = g_strdup (
|
||||||
"("
|
"("
|
||||||
"(" IPV6ADDR ")|(" "\\[" IPV6ADDR "\\]" PORT ")"
|
"(" IPV6ADDR ")|(" "\\[" IPV6ADDR "\\]" PORT ")"
|
||||||
")"
|
")"
|
||||||
@ -489,7 +539,7 @@ struct
|
|||||||
{ NULL, "", 0}
|
{ NULL, "", 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static GRegex *
|
static const GRegex *
|
||||||
re_url (void)
|
re_url (void)
|
||||||
{
|
{
|
||||||
static GRegex *url_ret = NULL;
|
static GRegex *url_ret = NULL;
|
||||||
@ -546,7 +596,7 @@ re_url (void)
|
|||||||
/* EMAIL description --- */
|
/* EMAIL description --- */
|
||||||
#define EMAIL "[a-z][-_a-z0-9]+@" "(" HOST_URL ")"
|
#define EMAIL "[a-z][-_a-z0-9]+@" "(" HOST_URL ")"
|
||||||
|
|
||||||
static GRegex *
|
static const GRegex *
|
||||||
re_email (void)
|
re_email (void)
|
||||||
{
|
{
|
||||||
static GRegex *email_ret;
|
static GRegex *email_ret;
|
||||||
@ -554,7 +604,7 @@ re_email (void)
|
|||||||
|
|
||||||
if (email_ret) return email_ret;
|
if (email_ret) return email_ret;
|
||||||
|
|
||||||
grist = g_strdup_printf (
|
grist = g_strdup (
|
||||||
"("
|
"("
|
||||||
EMAIL
|
EMAIL
|
||||||
")"
|
")"
|
||||||
@ -582,7 +632,7 @@ re_email (void)
|
|||||||
#define NICK1 "[" NICKHYP NICKLET NICKDIG NICKSPE "]*"
|
#define NICK1 "[" NICKHYP NICKLET NICKDIG NICKSPE "]*"
|
||||||
#define NICK NICK0 NICK1
|
#define NICK NICK0 NICK1
|
||||||
|
|
||||||
static GRegex *
|
static const GRegex *
|
||||||
re_nick (void)
|
re_nick (void)
|
||||||
{
|
{
|
||||||
static GRegex *nick_ret;
|
static GRegex *nick_ret;
|
||||||
@ -590,7 +640,7 @@ re_nick (void)
|
|||||||
|
|
||||||
if (nick_ret) return nick_ret;
|
if (nick_ret) return nick_ret;
|
||||||
|
|
||||||
grist = g_strdup_printf (
|
grist = g_strdup (
|
||||||
"("
|
"("
|
||||||
NICK
|
NICK
|
||||||
")"
|
")"
|
||||||
@ -600,9 +650,9 @@ re_nick (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* CHANNEL description --- */
|
/* CHANNEL description --- */
|
||||||
#define CHANNEL "#[^ \t\a,:]+"
|
#define CHANNEL "[" CHANPRE "][^ \t\a,:]+"
|
||||||
|
|
||||||
static GRegex *
|
static const GRegex *
|
||||||
re_channel (void)
|
re_channel (void)
|
||||||
{
|
{
|
||||||
static GRegex *channel_ret;
|
static GRegex *channel_ret;
|
||||||
@ -610,7 +660,7 @@ re_channel (void)
|
|||||||
|
|
||||||
if (channel_ret) return channel_ret;
|
if (channel_ret) return channel_ret;
|
||||||
|
|
||||||
grist = g_strdup_printf (
|
grist = g_strdup (
|
||||||
"("
|
"("
|
||||||
CHANNEL
|
CHANNEL
|
||||||
")"
|
")"
|
||||||
@ -628,7 +678,7 @@ re_channel (void)
|
|||||||
#define FS_PATH "^(/|\\./|\\.\\./).*"
|
#define FS_PATH "^(/|\\./|\\.\\./).*"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static GRegex *
|
static const GRegex *
|
||||||
re_path (void)
|
re_path (void)
|
||||||
{
|
{
|
||||||
static GRegex *path_ret;
|
static GRegex *path_ret;
|
||||||
@ -636,7 +686,7 @@ re_path (void)
|
|||||||
|
|
||||||
if (path_ret) return path_ret;
|
if (path_ret) return path_ret;
|
||||||
|
|
||||||
grist = g_strdup_printf (
|
grist = g_strdup (
|
||||||
"("
|
"("
|
||||||
FS_PATH
|
FS_PATH
|
||||||
")"
|
")"
|
||||||
|
Loading…
Reference in New Issue
Block a user