diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/Makefile.am | 1 | ||||
-rw-r--r-- | src/core/channels.c | 93 | ||||
-rw-r--r-- | src/core/channels.h | 3 | ||||
-rw-r--r-- | src/core/chat-protocols.c | 61 | ||||
-rw-r--r-- | src/core/chat-protocols.h | 18 | ||||
-rw-r--r-- | src/core/core.c | 7 | ||||
-rw-r--r-- | src/core/masks.c | 12 | ||||
-rw-r--r-- | src/core/nicklist.c | 45 | ||||
-rw-r--r-- | src/core/nicklist.h | 3 | ||||
-rw-r--r-- | src/core/queries.c | 6 | ||||
-rw-r--r-- | src/core/server-rec.h | 28 | ||||
-rw-r--r-- | src/core/servers-reconnect.c | 16 | ||||
-rw-r--r-- | src/core/servers.c | 1 |
13 files changed, 212 insertions, 82 deletions
diff --git a/src/core/Makefile.am b/src/core/Makefile.am index d6dd6e84..1cc943eb 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -18,6 +18,7 @@ libcore_a_SOURCES = \ channels.c \ channels-setup.c \ commands.c \ + chat-commands.c \ chat-protocols.c \ chatnets.c \ core.c \ diff --git a/src/core/channels.c b/src/core/channels.c index 1577472c..c21758af 100644 --- a/src/core/channels.c +++ b/src/core/channels.c @@ -21,10 +21,12 @@ #include "module.h" #include "signals.h" #include "misc.h" +#include "special-vars.h" +#include "servers.h" #include "channels.h" - -typedef CHANNEL_REC *(*CHANNEL_FIND_FUNC)(SERVER_REC *, const char *); +#include "channels-setup.h" +#include "nicklist.h" GSList *channels; /* List of all channels */ @@ -91,10 +93,7 @@ static CHANNEL_REC *channel_find_server(SERVER_REC *server, if (server->channel_find_func != NULL) { /* use the server specific channel find function */ - CHANNEL_FIND_FUNC channel_find_func; - channel_find_func = - (CHANNEL_FIND_FUNC) server->channel_find_func; - return channel_find_func(server, name); + return server->channel_find_func(server, name); } for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { @@ -122,11 +121,93 @@ CHANNEL_REC *channel_find(SERVER_REC *server, const char *name) (void *) name); } +/* connected to server, autojoin to channels. */ +static void event_connected(SERVER_REC *server) +{ + GString *chans; + GSList *tmp; + + g_return_if_fail(SERVER(server)); + + if (server->connrec->reconnection) + return; + + /* join to the channels marked with autojoin in setup */ + chans = g_string_new(NULL); + for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) { + CHANNEL_SETUP_REC *rec = tmp->data; + + if (!rec->autojoin || + !channel_chatnet_match(rec->chatnet, + server->connrec->chatnet)) + continue; + + g_string_sprintfa(chans, "%s,", rec->name); + } + + if (chans->len > 0) { + g_string_truncate(chans, chans->len-1); + server->channels_join(server, chans->str, TRUE); + } + + g_string_free(chans, TRUE); +} + +static int match_nick_flags(SERVER_REC *server, NICK_REC *nick, char flag) +{ + char *flags = server->get_nick_flags(); + + return (flag == flags[0] && nick->op) || + (flag == flags[1] && (nick->voice || nick->halfop || + nick->op)) || + (flag == flags[2] && (nick->halfop || nick->op)); +} + +/* Send the auto send command to channel */ +void channel_send_autocommands(CHANNEL_REC *channel) +{ + CHANNEL_SETUP_REC *rec; + NICK_REC *nick; + char **bots, **bot; + + g_return_if_fail(IS_CHANNEL(channel)); + + rec = channels_setup_find(channel->name, channel->server->connrec->chatnet); + if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd) + return; + + if (rec->botmasks == NULL || !*rec->botmasks) { + /* just send the command. */ + eval_special_string(rec->autosendcmd, "", channel->server, channel); + return; + } + + /* find first available bot.. */ + bots = g_strsplit(rec->botmasks, " ", -1); + for (bot = bots; *bot != NULL; bot++) { + const char *botnick = *bot; + + nick = nicklist_find(channel, + channel->server->isnickflag(*botnick) ? + botnick+1 : botnick); + if (nick == NULL || + !match_nick_flags(channel->server, nick, *botnick)) + continue; + + /* got one! */ + eval_special_string(rec->autosendcmd, nick->nick, channel->server, channel); + break; + } + g_strfreev(bots); +} + void channels_init(void) { + signal_add("event connected", (SIGNAL_FUNC) event_connected); } void channels_deinit(void) { + signal_remove("event connected", (SIGNAL_FUNC) event_connected); module_uniq_destroy("CHANNEL"); } diff --git a/src/core/channels.h b/src/core/channels.h index 91a330c1..1ebf7abb 100644 --- a/src/core/channels.h +++ b/src/core/channels.h @@ -29,6 +29,9 @@ void channel_destroy(CHANNEL_REC *channel); /* find channel by name, if `server' is NULL, search from all servers */ CHANNEL_REC *channel_find(SERVER_REC *server, const char *name); +/* Send the auto send command to channel */ +void channel_send_autocommands(CHANNEL_REC *channel); + void channels_init(void); void channels_deinit(void); diff --git a/src/core/chat-protocols.c b/src/core/chat-protocols.c index a5537f88..40413682 100644 --- a/src/core/chat-protocols.c +++ b/src/core/chat-protocols.c @@ -23,9 +23,7 @@ typedef struct { int id; - char *name; - char *fullname; - char *chatnet; + CHAT_PROTOCOL_REC *rec; } PROTOCOL_REC; static int id_counter; @@ -47,7 +45,7 @@ static PROTOCOL_REC *chat_protocol_find(const char *name) for (tmp = protocols; tmp != NULL; tmp = tmp->next) { PROTOCOL_REC *rec = tmp->data; - if (g_strcasecmp(rec->name, name) == 0) + if (g_strcasecmp(rec->rec->name, name) == 0) return rec; } @@ -71,25 +69,19 @@ static PROTOCOL_REC *chat_protocol_find_id(int id) } /* Register new chat protocol. */ -void chat_protocol_register(const char *name, - const char *fullname, - const char *chatnet) +void chat_protocol_register(CHAT_PROTOCOL_REC *rec) { - PROTOCOL_REC *rec; + PROTOCOL_REC *proto; - g_return_if_fail(name != NULL); - g_return_if_fail(fullname != NULL); - g_return_if_fail(chatnet != NULL); + g_return_if_fail(rec != NULL); - if (chat_protocol_find(name) != NULL) + if (chat_protocol_find(rec->name) != NULL) return; - rec = g_new0(PROTOCOL_REC, 1); - rec->id = ++id_counter; - rec->name = g_strdup(name); - rec->fullname = g_strdup(fullname); - rec->chatnet = g_strdup(chatnet); - protocols = g_slist_append(protocols, rec); + proto = g_new0(PROTOCOL_REC, 1); + proto->id = ++id_counter; + proto->rec = rec; + protocols = g_slist_append(protocols, proto); } static void chat_protocol_destroy(PROTOCOL_REC *rec) @@ -97,10 +89,7 @@ static void chat_protocol_destroy(PROTOCOL_REC *rec) g_return_if_fail(rec != NULL); protocols = g_slist_remove(protocols, rec); - - g_free(rec->name); - g_free(rec->fullname); - g_free(rec->chatnet); + g_free(rec->rec); g_free(rec); } @@ -126,37 +115,15 @@ int chat_protocol_lookup(const char *name) return rec == NULL ? -1 : rec->id; } -/* Return the name for the specified chat protocol ID. */ -const char *chat_protocol_get_name(int id) -{ - PROTOCOL_REC *rec; - - g_return_val_if_fail(id > 0, NULL); - - rec = chat_protocol_find_id(id); - return rec == NULL ? NULL : rec->name; -} - -/* Return the full name for the specified chat protocol ID. */ -const char *chat_protocol_get_fullname(int id) -{ - PROTOCOL_REC *rec; - - g_return_val_if_fail(id > 0, NULL); - - rec = chat_protocol_find_id(id); - return rec == NULL ? NULL : rec->fullname; -} - -/* Return the chatnet identifier name for the specified chat protocol ID. */ -const char *chat_protocol_get_chatnet(int id) +/* Return the record for the specified chat protocol ID. */ +CHAT_PROTOCOL_REC *chat_protocol_get_rec(int id) { PROTOCOL_REC *rec; g_return_val_if_fail(id > 0, NULL); rec = chat_protocol_find_id(id); - return rec == NULL ? NULL : rec->chatnet; + return rec == NULL ? NULL : rec->rec; } void chat_protocols_init(void) diff --git a/src/core/chat-protocols.h b/src/core/chat-protocols.h index 42b413cf..1f38da50 100644 --- a/src/core/chat-protocols.h +++ b/src/core/chat-protocols.h @@ -1,27 +1,27 @@ #ifndef __CHAT_PROTOCOLS_H #define __CHAT_PROTOCOLS_H +typedef struct { + char *name; + char *fullname; + char *chatnet; +} CHAT_PROTOCOL_REC; + #define PROTO_CHECK_CAST(object, cast, type_field, id) \ ((cast *) chat_protocol_check_cast(object, \ offsetof(cast, type_field), id)) void *chat_protocol_check_cast(void *object, int type_pos, const char *id); /* Register new chat protocol. */ -void chat_protocol_register(const char *name, - const char *fullname, - const char *chatnet); +void chat_protocol_register(CHAT_PROTOCOL_REC *rec); /* Unregister chat protocol. */ void chat_protocol_unregister(const char *name); /* Return the ID for the specified chat protocol. */ int chat_protocol_lookup(const char *name); -/* Return the name for the specified chat protocol ID. */ -const char *chat_protocol_get_name(int id); -/* Return the full name for the specified chat protocol ID. */ -const char *chat_protocol_get_fullname(int id); -/* Return the chatnet identifier name for the specified chat protocol ID. */ -const char *chat_protocol_get_chatnet(int id); +/* Return the record for the specified chat protocol ID. */ +CHAT_PROTOCOL_REC *chat_protocol_get_rec(int id); void chat_protocols_init(void); void chat_protocols_deinit(void); diff --git a/src/core/core.c b/src/core/core.c index c4e7e020..7ec453d1 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -39,6 +39,9 @@ #include "queries.h" #include "nicklist.h" +void chat_commands_init(void); +void chat_commands_deinit(void); + int irssi_gui; void core_init(void) @@ -62,6 +65,8 @@ void core_init(void) channels_init(); queries_init(); nicklist_init(); + + chat_commands_init(); } void core_deinit(void) @@ -69,6 +74,8 @@ void core_deinit(void) while (modules != NULL) module_unload(modules->data); + chat_commands_deinit(); + nicklist_deinit(); queries_deinit(); channels_deinit(); diff --git a/src/core/masks.c b/src/core/masks.c index 38fbdf45..909650b2 100644 --- a/src/core/masks.c +++ b/src/core/masks.c @@ -24,8 +24,6 @@ #include "servers.h" -typedef int (*MASK_MATCH_FUNC) (const char *, const char *); - /* Returns TRUE if mask contains '!' ie. address should be checked too. Also checks if mask contained any wildcards. */ static int check_address(const char *mask, int *wildcards) @@ -52,12 +50,9 @@ static int check_address(const char *mask, int *wildcards) static int check_mask(SERVER_REC *server, const char *mask, const char *str, int wildcards) { - MASK_MATCH_FUNC mask_match_func; - if (server != NULL && server->mask_match_func != NULL) { /* use server specified mask match function */ - mask_match_func = (MASK_MATCH_FUNC)server->mask_match_func; - return mask_match_func(mask, str); + return server->mask_match_func(mask, str); } return wildcards ? match_wildcards(mask, str) : @@ -103,7 +98,7 @@ int mask_match_address(SERVER_REC *server, const char *mask, int masks_match(SERVER_REC *server, const char *masks, const char *nick, const char *address) { - MASK_MATCH_FUNC mask_match_func; + int (*mask_match_func)(const char *, const char *); char **list, **tmp, *mask; int found; @@ -112,8 +107,7 @@ int masks_match(SERVER_REC *server, const char *masks, nick != NULL && address != NULL, FALSE); mask_match_func = server != NULL && server->mask_match_func != NULL ? - (MASK_MATCH_FUNC) server->mask_match_func : - (MASK_MATCH_FUNC) match_wildcards; + server->mask_match_func : match_wildcards; found = FALSE; mask = g_strdup_printf("%s!%s", nick, address); diff --git a/src/core/nicklist.c b/src/core/nicklist.c index 1ba78f94..0cb19123 100644 --- a/src/core/nicklist.c +++ b/src/core/nicklist.c @@ -25,6 +25,9 @@ #include "nicklist.h" #include "masks.h" +#define isalnumhigh(a) \ + (isalnum(a) || (unsigned char) (a) >= 128) + /* Add new nick to list */ NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick, int op, int voice, int send_massjoin) @@ -255,6 +258,48 @@ static void sig_channel_destroyed(CHANNEL_REC *channel) g_hash_table_destroy(channel->nicks); } +/* Check is `msg' is meant for `nick'. */ +int nick_match_msg(SERVER_REC *server, const char *msg, const char *nick) +{ + int len; + + 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); + + /* 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 + break; + + nick++; + } + + if (isalnumhigh(*msg)) { + /* message continues with another alphanumeric character, + it isn't for us. */ + return FALSE; + } + + /* 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++; + + return *nick == '\0'; +} + void nicklist_init(void) { signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created); diff --git a/src/core/nicklist.h b/src/core/nicklist.h index cd9276c3..c9015ab7 100644 --- a/src/core/nicklist.h +++ b/src/core/nicklist.h @@ -44,6 +44,9 @@ void nicklist_update_flags(SERVER_REC *server, const char *nick, /* Nick record comparision for sort functions */ int nicklist_compare(NICK_REC *p1, NICK_REC *p2); +/* Check is `msg' is meant for `nick'. */ +int nick_match_msg(SERVER_REC *server, const char *msg, const char *nick); + void nicklist_init(void); void nicklist_deinit(void); diff --git a/src/core/queries.c b/src/core/queries.c index c9793f7a..9be0f156 100644 --- a/src/core/queries.c +++ b/src/core/queries.c @@ -26,8 +26,6 @@ GSList *queries; -typedef QUERY_REC *(*QUERY_FIND_FUNC)(SERVER_REC *, const char *); - /* Create a new query */ QUERY_REC *query_create(int chat_type, SERVER_REC *server, const char *nick, int automatic) @@ -91,9 +89,7 @@ static QUERY_REC *query_find_server(SERVER_REC *server, const char *nick) if (server->query_find_func != NULL) { /* use the server specific query find function */ - QUERY_FIND_FUNC query_find_func; - query_find_func = (QUERY_FIND_FUNC) server->query_find_func; - return query_find_func(server, nick); + return server->query_find_func(server, nick); } for (tmp = server->queries; tmp != NULL; tmp = tmp->next) { diff --git a/src/core/server-rec.h b/src/core/server-rec.h index e9c069b7..8aaef6f9 100644 --- a/src/core/server-rec.h +++ b/src/core/server-rec.h @@ -32,6 +32,7 @@ GHashTable *module_data; char *version; /* server version */ char *away_reason; +char *last_invite; /* channel where you were last invited */ int server_operator:1; int usermode_away:1; int banned:1; /* not allowed to connect to this server */ @@ -43,9 +44,28 @@ int lag; /* server lag in milliseconds */ GSList *channels; GSList *queries; -/* support for multiple server types */ -void *channel_find_func; -void *query_find_func; -void *mask_match_func; +/* -- support for multiple server types -- */ + +/* -- must not be NULL: -- */ +/* join to a number of channels, channels are specified in `data' separated + with commas. there can exist other information after first space like + channel keys etc. */ +void (*channels_join)(void *server, const char *data, int automatic); +/* returns true if `flag' indicates a nick flag (op/voice/halfop) */ +int (*isnickflag)(char flag); +/* returns true if `flag' indicates a channel */ +int (*ischannel)(char flag); +/* returns all nick flag characters in order op, voice, halfop. If some + of them aren't supported '\0' can be used. */ +const char *(*get_nick_flags)(void); +/* send public or private message to server */ +void (*send_message)(void *server, const char *target, const char *msg); + +/* -- Default implementations are used if NULL -- */ +void *(*channel_find_func)(void *server, const char *name); +void *(*query_find_func)(void *server, const char *nick); +int (*mask_match_func)(const char *mask, const char *data); +/* returns true if `msg' was meant for `nick' */ +int (*nick_match_msg)(const char *nick, const char *msg); #undef STRUCT_SERVER_CONNECT_REC diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index d28863a1..00b3f132 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -244,6 +244,16 @@ static void sig_reconnect(SERVER_REC *server) } } +static void sig_connected(SERVER_REC *server) +{ + g_return_if_fail(IS_SERVER(server)); + if (!server->connrec->reconnection) + return; + + if (server->connrec->channels != NULL) + server->channels_join(server, server->connrec->channels, TRUE); +} + /* Remove all servers from reconnect list */ /* SYNTAX: RMRECONNS */ static void cmd_rmreconns(void) @@ -336,10 +346,11 @@ void servers_reconnect_init(void) signal_add("server connect failed", (SIGNAL_FUNC) sig_reconnect); signal_add("server disconnected", (SIGNAL_FUNC) sig_reconnect); + signal_add("event connected", (SIGNAL_FUNC) sig_connected); + signal_add("setup changed", (SIGNAL_FUNC) read_settings); command_bind("rmreconns", NULL, (SIGNAL_FUNC) cmd_rmreconns); command_bind("reconnect", NULL, (SIGNAL_FUNC) cmd_reconnect); command_bind_first("disconnect", NULL, (SIGNAL_FUNC) cmd_disconnect); - signal_add("setup changed", (SIGNAL_FUNC) read_settings); } void servers_reconnect_deinit(void) @@ -351,8 +362,9 @@ void servers_reconnect_deinit(void) signal_remove("server connect failed", (SIGNAL_FUNC) sig_reconnect); signal_remove("server disconnected", (SIGNAL_FUNC) sig_reconnect); + signal_remove("event connected", (SIGNAL_FUNC) sig_connected); + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); command_unbind("rmreconns", (SIGNAL_FUNC) cmd_rmreconns); command_unbind("reconnect", (SIGNAL_FUNC) cmd_reconnect); command_unbind("disconnect", (SIGNAL_FUNC) cmd_disconnect); - signal_remove("setup changed", (SIGNAL_FUNC) read_settings); } diff --git a/src/core/servers.c b/src/core/servers.c index b2f619ca..9ec53902 100644 --- a/src/core/servers.c +++ b/src/core/servers.c @@ -28,6 +28,7 @@ #include "rawlog.h" #include "settings.h" +#include "chat-protocols.h" #include "servers.h" #include "servers-reconnect.h" #include "servers-redirect.h" |