diff --git a/src/core/chat-protocols.c b/src/core/chat-protocols.c index c53b01b3..83d7ee88 100644 --- a/src/core/chat-protocols.c +++ b/src/core/chat-protocols.c @@ -47,7 +47,7 @@ int chat_protocol_lookup(const char *name) g_return_val_if_fail(name != NULL, -1); rec = chat_protocol_find(name); - return rec == NULL ? -1 : rec->id; + return rec == NULL ? -1 : rec->not_initialized ? CHAT_PROTOCOL_NOT_INITIALIZED : rec->id; } CHAT_PROTOCOL_REC *chat_protocol_find(const char *name) @@ -99,6 +99,22 @@ CHAT_PROTOCOL_REC *chat_protocol_find_net(GHashTable *optlist) return NULL; } +static void chat_protocol_destroy(CHAT_PROTOCOL_REC *rec) +{ + g_return_if_fail(rec != NULL); + + chat_protocols = g_slist_remove(chat_protocols, rec); + + if (default_proto == rec) { + chat_protocol_set_default(chat_protocols == NULL ? NULL : chat_protocols->data); + } + + signal_emit("chat protocol destroyed", 1, rec); + + g_free(rec->name); + g_free(rec); +} + /* Register new chat protocol. */ CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec) { @@ -108,7 +124,11 @@ CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec) g_return_val_if_fail(rec != NULL, NULL); newrec = chat_protocol_find(rec->name); - created = newrec == NULL; + if (newrec != NULL && newrec->not_initialized) { + chat_protocol_destroy(newrec); + newrec = NULL; + } + created = newrec == NULL; if (newrec == NULL) { newrec = g_new0(CHAT_PROTOCOL_REC, 1); chat_protocols = g_slist_append(chat_protocols, newrec); @@ -131,23 +151,6 @@ CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec) return newrec; } -static void chat_protocol_destroy(CHAT_PROTOCOL_REC *rec) -{ - g_return_if_fail(rec != NULL); - - chat_protocols = g_slist_remove(chat_protocols, rec); - - if (default_proto == rec) { - chat_protocol_set_default(chat_protocols == NULL ? NULL : - chat_protocols->data); - } - - signal_emit("chat protocol destroyed", 1, rec); - - g_free(rec->name); - g_free(rec); -} - /* Unregister chat protocol. */ void chat_protocol_unregister(const char *name) { @@ -218,8 +221,10 @@ CHAT_PROTOCOL_REC *chat_protocol_get_unknown(const char *name) rec->create_chatnet = create_chatnet; rec->create_server_setup = create_server_setup; rec->create_channel_setup = create_channel_setup; + /* rec->create_server_connect = create_server_connect; rec->destroy_server_connect = destroy_server_connect; + */ newrec = chat_protocol_register(rec); g_free(rec); diff --git a/src/core/chat-protocols.h b/src/core/chat-protocols.h index ab7327bd..2a51c8c4 100644 --- a/src/core/chat-protocols.h +++ b/src/core/chat-protocols.h @@ -35,6 +35,8 @@ void *chat_protocol_check_cast(void *object, int type_pos, const char *id); ((object) == NULL ? chat_protocol_get_default() : \ chat_protocol_find_id((object)->chat_type)) +#define CHAT_PROTOCOL_NOT_INITIALIZED -2 + /* Register new chat protocol. */ CHAT_PROTOCOL_REC *chat_protocol_register(CHAT_PROTOCOL_REC *rec); diff --git a/src/core/chatnets.c b/src/core/chatnets.c index 2d49a6df..4e880a10 100644 --- a/src/core/chatnets.c +++ b/src/core/chatnets.c @@ -24,12 +24,13 @@ #include #include #include +#include #include #include #include -GSList *chatnets; /* list of available chat networks */ +GSList *chatnets, *chatnets_unavailable; /* list of available chat networks */ static void chatnet_config_save(CHATNET_REC *chatnet) { @@ -60,8 +61,9 @@ static void chatnet_config_remove(CHATNET_REC *chatnet) void chatnet_create(CHATNET_REC *chatnet) { g_return_if_fail(chatnet != NULL); + g_return_if_fail(!CHAT_PROTOCOL(chatnet)->not_initialized); - chatnet->type = module_get_uniq_id("CHATNET", 0); + chatnet->type = module_get_uniq_id("CHATNET", 0); if (g_slist_find(chatnets, chatnet) == NULL) chatnets = g_slist_append(chatnets, chatnet); @@ -112,6 +114,21 @@ CHATNET_REC *chatnet_find(const char *name) return NULL; } +gboolean chatnet_find_unavailable(const char *name) +{ + CHAT_PROTOCOL_REC *proto; + + if (i_slist_find_icase_string(chatnets_unavailable, name) != NULL) + return TRUE; + + proto = CHAT_PROTOCOL(chatnet_find(name)); + + if (proto == NULL || proto->not_initialized) + return TRUE; + + return FALSE; +} + static void sig_connected(SERVER_REC *server) { CHATNET_REC *rec; @@ -136,14 +153,22 @@ static void chatnet_read(CONFIG_NODE *node) return; type = config_node_get_str(node, "type", NULL); - proto = type == NULL ? NULL : chat_protocol_find(type); - if (proto == NULL) { - proto = type == NULL ? chat_protocol_get_default() : - chat_protocol_get_unknown(type); + if (type == NULL) { + proto = chat_protocol_get_default(); + } else { + proto = chat_protocol_find(type); } - if (type == NULL) + if (proto == NULL) { + /* protocol not loaded */ + if (i_slist_find_icase_string(chatnets_unavailable, node->key) == NULL) + chatnets_unavailable = + g_slist_append(chatnets_unavailable, g_strdup(node->key)); + + return; + } else if (type == NULL) { iconfig_node_set_str(node, "type", proto->name); + } rec = proto->create_chatnet(); rec->type = module_get_uniq_id("CHATNET", 0); @@ -167,6 +192,12 @@ static void read_chatnets(void) while (chatnets != NULL) chatnet_destroy(chatnets->data); + while (chatnets_unavailable != NULL) { + char *name = chatnets_unavailable->data; + chatnets_unavailable = g_slist_remove(chatnets_unavailable, name); + g_free(name); + } + node = iconfig_node_traverse("chatnets", FALSE); if (node != NULL) { tmp = config_node_first(node->value); diff --git a/src/core/chatnets.h b/src/core/chatnets.h index 6f36fe33..accdd0ad 100644 --- a/src/core/chatnets.h +++ b/src/core/chatnets.h @@ -25,6 +25,8 @@ void chatnet_destroy(CHATNET_REC *chatnet); /* Find the chat network by name */ CHATNET_REC *chatnet_find(const char *name); +/* Check if this chatnet is unavailable because the protocol is not loaded */ +gboolean chatnet_find_unavailable(const char *name); void chatnets_init(void); void chatnets_deinit(void); diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c index 82e5f6be..440f5593 100644 --- a/src/core/servers-setup.c +++ b/src/core/servers-setup.c @@ -305,6 +305,8 @@ static SERVER_CONNECT_REC *create_addr_conn(int chat_type, const char *address, proto = chat_type >= 0 ? chat_protocol_find_id(chat_type) : chat_protocol_get_default(); + g_return_val_if_fail(proto != NULL, NULL); + conn = proto->create_server_connect(); server_connect_ref(conn); @@ -469,6 +471,10 @@ static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node) chatnetrec = chatnet == NULL ? NULL : chatnet_find(chatnet); if (chatnetrec == NULL && chatnet != NULL) { /* chat network not found, create it. */ + if (chatnet_find_unavailable(chatnet)) { + /* no protocols loaded, skip loading servers */ + return NULL; + } chatnetrec = chat_protocol_get_default()->create_chatnet(); chatnetrec->chat_type = chat_protocol_get_default()->id; chatnetrec->name = g_strdup(chatnet); diff --git a/src/perl/perl-common.c b/src/perl/perl-common.c index 7eaab8eb..d9d00035 100644 --- a/src/perl/perl-common.c +++ b/src/perl/perl-common.c @@ -583,6 +583,10 @@ static void perl_register_protocol(CHAT_PROTOCOL_REC *rec) SV *sv; chat_type = chat_protocol_lookup(rec->name); + if (chat_type == CHAT_PROTOCOL_NOT_INITIALIZED) { + return; + } + g_return_if_fail(chat_type >= 0); name = g_ascii_strdown(rec->name,-1);