diff --git a/docs/manual.txt b/docs/manual.txt index f7f922d7..2cde9a97 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -362,7 +362,7 @@ /IRCNET ADD [-kicks ] [-msgs ] [-modes ] [-whois ] [-cmdspeed ] [-cmdmax ] - [-nick ] [-user ] [-name ] + [-nick ] [-user ] [-realname ] [-host ] -kicks: Maximum number of nicks in one /KICK command @@ -371,7 +371,7 @@ -whois: Maximum number of nicks in one /WHOIS command -cmdspeed: Same as /SET cmd_queue_speed, see section 3.1 -cmdmax: Same as /SET cmd_max_at_once, see section 3.1 - -nick, -user, -name: Specify what nick/username/realname to use + -nick, -user, -realname: Specify what nick/user/name to use -host: Specify what host name to use, if you have multiple /IRCNET REMOVE diff --git a/src/core/commands.c b/src/core/commands.c index 1a05e7a3..e4c7a5ff 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -352,13 +352,17 @@ char *cmd_get_params(const char *data, int count, ...) va_start(args, count); /* get the length of the arguments in string */ - old = datad = g_strdup(data); - if (count & PARAM_FLAG_MULTIARGS) - get_multi_args(&datad, TRUE, args); - else if (count & PARAM_FLAG_OPTARGS) - get_opt_args(&datad); - len = (int) (datad-old); - g_free(old); + if ((count & (PARAM_FLAG_MULTIARGS|PARAM_FLAG_OPTARGS)) == 0) + len = 0; + else { + old = datad = g_strdup(data); + if (count & PARAM_FLAG_MULTIARGS) + get_multi_args(&datad, TRUE, args); + else + get_opt_args(&datad); + len = (int) (datad-old); + g_free(old); + } /* send the text to custom functions to handle - skip arguments */ old = datad = cmd_get_callfuncs(data+len, &count, &args); @@ -392,7 +396,9 @@ char *cmd_get_params(const char *data, int count, ...) /* get rest */ arg = datad; } else { - arg = cmd_get_quoted_param(&datad); + arg = (count & PARAM_FLAG_NOQUOTES) ? + cmd_get_param(&datad) : + cmd_get_quoted_param(&datad); } str = (char **) va_arg(args, char **); diff --git a/src/core/commands.h b/src/core/commands.h index dcff89c2..74f66e45 100644 --- a/src/core/commands.h +++ b/src/core/commands.h @@ -36,7 +36,9 @@ void command_runsub(const char *cmd, const char *data, void *p1, void *p2); /* count can have these flags: */ #define PARAM_WITHOUT_FLAGS(a) ((a) & 0x00ffffff) -/* cmd_get_params() */ +/* don't check for quotes - "arg1 arg2" is NOT treated as one argument */ +#define PARAM_FLAG_NOQUOTES 0x01000000 +/* final argument gets all the rest of the arguments */ #define PARAM_FLAG_GETREST 0x02000000 /* optional arguments (-cmd -cmd2 -cmd3) */ #define PARAM_FLAG_OPTARGS 0x04000000 diff --git a/src/fe-common/irc/Makefile.am b/src/fe-common/irc/Makefile.am index 662caf9d..7c59e0d4 100644 --- a/src/fe-common/irc/Makefile.am +++ b/src/fe-common/irc/Makefile.am @@ -16,6 +16,7 @@ libfe_common_irc_la_SOURCES = \ fe-channels.c \ fe-irc-commands.c \ fe-irc-server.c \ + fe-ircnet.c \ fe-ctcp.c \ fe-events.c \ fe-events-numeric.c \ diff --git a/src/fe-common/irc/fe-channels.c b/src/fe-common/irc/fe-channels.c index 0d566fd7..1859ae7b 100644 --- a/src/fe-common/irc/fe-channels.c +++ b/src/fe-common/irc/fe-channels.c @@ -157,13 +157,13 @@ static void cmd_channel_list(void) g_string_truncate(str, 0); if (rec->autojoin) - g_string_append(str, "autojoin "); + g_string_append(str, "autojoin, "); if (rec->botmasks != NULL && *rec->botmasks != '\0') - g_string_sprintfa(str, "bots: %s ", rec->botmasks); + g_string_sprintfa(str, "bots: %s, ", rec->botmasks); if (rec->autosendcmd != NULL && *rec->autosendcmd != '\0') - g_string_sprintfa(str, "botcmd: %s ", rec->autosendcmd); + g_string_sprintfa(str, "botcmd: %s, ", rec->autosendcmd); - if (str->len > 0) g_string_truncate(str, str->len-1); + if (str->len > 1) g_string_truncate(str, str->len-1); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_CHANSETUP_LINE, rec->name, rec->ircnet == NULL ? "" : rec->ircnet, rec->password == NULL ? "" : rec->password, str->str); @@ -242,8 +242,8 @@ void fe_channels_init(void) signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected); command_bind("wjoin", NULL, (SIGNAL_FUNC) cmd_wjoin); - command_bind("channel ", NULL, (SIGNAL_FUNC) cmd_channel_list_joined); command_bind("channel", NULL, (SIGNAL_FUNC) cmd_channel); + command_bind("channel ", NULL, (SIGNAL_FUNC) cmd_channel_list_joined); command_bind("channel add", NULL, (SIGNAL_FUNC) cmd_channel_add); command_bind("channel remove", NULL, (SIGNAL_FUNC) cmd_channel_remove); command_bind("channel list", NULL, (SIGNAL_FUNC) cmd_channel_list); diff --git a/src/fe-common/irc/fe-common-irc.c b/src/fe-common/irc/fe-common-irc.c index 63430a69..7125dab5 100644 --- a/src/fe-common/irc/fe-common-irc.c +++ b/src/fe-common/irc/fe-common-irc.c @@ -40,6 +40,9 @@ void fe_channels_deinit(void); void fe_irc_commands_init(void); void fe_irc_commands_deinit(void); +void fe_ircnet_init(void); +void fe_ircnet_deinit(void); + void fe_irc_server_init(void); void fe_irc_server_deinit(void); @@ -100,6 +103,7 @@ void fe_common_irc_init(void) fe_channels_init(); fe_irc_commands_init(); + fe_ircnet_init(); fe_irc_server_init(); fe_ctcp_init(); fe_events_init(); @@ -119,6 +123,7 @@ void fe_common_irc_deinit(void) fe_channels_deinit(); fe_irc_commands_deinit(); + fe_ircnet_deinit(); fe_irc_server_deinit(); fe_ctcp_deinit(); fe_events_deinit(); diff --git a/src/fe-common/irc/fe-irc-server.c b/src/fe-common/irc/fe-irc-server.c index ee0978d7..24c662b4 100644 --- a/src/fe-common/irc/fe-irc-server.c +++ b/src/fe-common/irc/fe-irc-server.c @@ -101,14 +101,20 @@ static void server_add(const char *data) if (*portarg != '\0') rec->port = atoi(portarg); if (stristr(args, "-ircnet")) g_free_and_null(rec->ircnet); if (*password != '\0') g_free_and_null(rec->password); - if (stristr(args, "-host")) g_free_and_null(rec->own_host); + if (stristr(args, "-host")) { + g_free_and_null(rec->own_host); + rec->own_ip = NULL; + } } if (stristr(args, "-auto")) rec->autoconnect = TRUE; if (stristr(args, "-noauto")) rec->autoconnect = FALSE; if (*ircnet != '\0') rec->ircnet = g_strdup(ircnet); if (*password != '\0' && strcmp(password, "-") != 0) rec->password = g_strdup(password); - if (*host != '\0') rec->own_host = g_strdup(host); + if (*host != '\0') { + rec->own_host = g_strdup(host); + rec->own_ip = NULL; + } if (*cmdspeed != '\0') rec->cmd_queue_speed = atoi(cmdspeed); if (*cmdmax != '\0') rec->max_cmds_at_once = atoi(cmdmax); @@ -151,15 +157,17 @@ static void server_list(const char *data) g_string_truncate(str, 0); if (rec->password != NULL) - g_string_append(str, "(pass) "); + g_string_append(str, "(pass), "); if (rec->autoconnect) - g_string_append(str, "autoconnect "); + g_string_append(str, "autoconnect, "); if (rec->max_cmds_at_once > 0) - g_string_sprintfa(str, "cmdmax: %d ", rec->max_cmds_at_once); + g_string_sprintfa(str, "cmdmax: %d, ", rec->max_cmds_at_once); if (rec->cmd_queue_speed > 0) - g_string_sprintfa(str, "cmdspeed: %d ", rec->cmd_queue_speed); + g_string_sprintfa(str, "cmdspeed: %d, ", rec->cmd_queue_speed); if (rec->own_host != NULL) - g_string_sprintfa(str, "host: %s ", rec->own_host); + g_string_sprintfa(str, "host: %s, ", rec->own_host); + + if (str->len > 1) g_string_truncate(str, str->len-2); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_SETUPSERVER_LINE, rec->address, rec->port, rec->ircnet == NULL ? "" : rec->ircnet, diff --git a/src/fe-common/irc/module-formats.c b/src/fe-common/irc/module-formats.c index f09f50a4..c20089ff 100644 --- a/src/fe-common/irc/module-formats.c +++ b/src/fe-common/irc/module-formats.c @@ -47,6 +47,12 @@ FORMAT_REC fecommon_irc_formats[] = { { "netsplits_header", "Nick Channel Server Splitted server", 0 }, { "netsplits_line", "$[9]0 $[10]1 $[20]2 $3", 4, { 0, 0, 0, 0 } }, { "netsplits_footer", "", 0 }, + { "ircnet_added", "Ircnet $0 saved", 1, { 0 } }, + { "ircnet_removed", "Ircnet $0 removed", 1, { 0 } }, + { "ircnet_not_found", "Ircnet $0 not found", 1, { 0 } }, + { "ircnet_header", "Ircnets:", 0 }, + { "ircnet_line", "$0: $1", 2, { 0, 0 } }, + { "ircnet_footer", "", 0 }, /* ---- */ { NULL, "Channels", 0 }, diff --git a/src/fe-common/irc/module-formats.h b/src/fe-common/irc/module-formats.h index 56521f47..d4210461 100644 --- a/src/fe-common/irc/module-formats.h +++ b/src/fe-common/irc/module-formats.h @@ -25,6 +25,12 @@ enum { IRCTXT_NETSPLITS_HEADER, IRCTXT_NETSPLITS_LINE, IRCTXT_NETSPLITS_FOOTER, + IRCTXT_IRCNET_ADDED, + IRCTXT_IRCNET_REMOVED, + IRCTXT_IRCNET_NOT_FOUND, + IRCTXT_IRCNET_HEADER, + IRCTXT_IRCNET_LINE, + IRCTXT_IRCNET_FOOTER, IRCTXT_FILL_2, diff --git a/src/irc/core/ircnet-setup.c b/src/irc/core/ircnet-setup.c index 8296a7e8..bd913705 100644 --- a/src/irc/core/ircnet-setup.c +++ b/src/irc/core/ircnet-setup.c @@ -29,6 +29,64 @@ GSList *ircnets; /* list of available ircnets */ +static void ircnet_config_add(IRCNET_REC *ircnet) +{ + CONFIG_NODE *node; + + node = iconfig_node_traverse("ircnets", TRUE); + iconfig_node_set_str(node, ircnet->name, NULL); + node = config_node_section(node, ircnet->name, NODE_TYPE_BLOCK); + + iconfig_node_set_str(node, "nick", ircnet->nick); + iconfig_node_set_str(node, "username", ircnet->username); + iconfig_node_set_str(node, "realname", ircnet->realname); + iconfig_node_set_str(node, "host", ircnet->own_host); + + if (ircnet->max_cmds_at_once > 0) + config_node_set_int(node, "cmdmax", ircnet->max_cmds_at_once); + if (ircnet->cmd_queue_speed > 0) + config_node_set_int(node, "cmdspeed", ircnet->cmd_queue_speed); + + if (ircnet->max_kicks > 0) + config_node_set_int(node, "max_kicks", ircnet->max_kicks); + if (ircnet->max_msgs > 0) + config_node_set_int(node, "max_msgs", ircnet->max_msgs); + if (ircnet->max_modes > 0) + config_node_set_int(node, "max_modes", ircnet->max_modes); + if (ircnet->max_whois > 0) + config_node_set_int(node, "max_whois", ircnet->max_whois); + +} + +static void ircnet_config_remove(IRCNET_REC *ircnet) +{ + CONFIG_NODE *node; + + node = iconfig_node_traverse("ircnets", FALSE); + if (node != NULL) iconfig_node_set_str(node, ircnet->name, NULL); +} + +void ircnet_create(IRCNET_REC *ircnet) +{ + if (g_slist_find(ircnets, ircnet) == NULL) + ircnets = g_slist_append(ircnets, ircnet); + + ircnet_config_add(ircnet); +} + +void ircnet_destroy(IRCNET_REC *ircnet) +{ + ircnet_config_remove(ircnet); + ircnets = g_slist_remove(ircnets, ircnet); + + g_free(ircnet->name); + g_free_not_null(ircnet->nick); + g_free_not_null(ircnet->username); + g_free_not_null(ircnet->realname); + g_free_not_null(ircnet->own_host); + g_free(ircnet); +} + /* Find the irc network by name */ IRCNET_REC *ircnet_find(const char *name) { @@ -46,42 +104,29 @@ IRCNET_REC *ircnet_find(const char *name) return NULL; } -static void ircnet_destroy(IRCNET_REC *rec) -{ - ircnets = g_slist_remove(ircnets, rec); - - g_free(rec->name); - if (rec->nick != NULL) g_free(rec->nick); - if (rec->username != NULL) g_free(rec->username); - if (rec->realname != NULL) g_free(rec->realname); - g_free(rec); -} - static IRCNET_REC *ircnet_add(CONFIG_NODE *node) { IRCNET_REC *rec; - char *name, *nick, *username, *realname; g_return_val_if_fail(node != NULL, NULL); - - name = config_node_get_str(node, "name", NULL); - if (name == NULL) return NULL; - - nick = config_node_get_str(node, "nick", NULL); - username = config_node_get_str(node, "username", NULL); - realname = config_node_get_str(node, "realname", NULL); + if (node->key == NULL) return NULL; rec = g_new0(IRCNET_REC, 1); + + rec->name = g_strdup(node->key); + rec->nick = g_strdup(config_node_get_str(node, "nick", NULL)); + rec->username = g_strdup(config_node_get_str(node, "username", NULL)); + rec->realname = g_strdup(config_node_get_str(node, "realname", NULL)); + rec->own_host = g_strdup(config_node_get_str(node, "host", NULL)); + + rec->max_cmds_at_once = config_node_get_int(node, "cmdmax", 0); + rec->cmd_queue_speed = config_node_get_int(node, "cmdspeed", 0); + rec->max_kicks = config_node_get_int(node, "max_kicks", 0); rec->max_msgs = config_node_get_int(node, "max_msgs", 0); rec->max_modes = config_node_get_int(node, "max_modes", 0); rec->max_whois = config_node_get_int(node, "max_whois", 0); - rec->name = g_strdup(name); - rec->nick = (nick == NULL || *nick == '\0') ? NULL : g_strdup(nick); - rec->username = (username == NULL || *username == '\0') ? NULL : g_strdup(username); - rec->realname = (realname == NULL || *realname == '\0') ? NULL : g_strdup(realname); - ircnets = g_slist_append(ircnets, rec); return rec; } diff --git a/src/irc/core/ircnet-setup.h b/src/irc/core/ircnet-setup.h index dea530fb..2b82f171 100644 --- a/src/irc/core/ircnet-setup.h +++ b/src/irc/core/ircnet-setup.h @@ -8,12 +8,21 @@ typedef struct { char *username; char *realname; + char *own_host; /* address to use when connecting this server */ + IPADDR *own_ip; /* resolved own_address if not NULL */ + + int max_cmds_at_once; + int cmd_queue_speed; + /* max. number of kicks/msgs/mode/whois per command */ int max_kicks, max_msgs, max_modes, max_whois; } IRCNET_REC; extern GSList *ircnets; /* list of available ircnets */ +void ircnet_create(IRCNET_REC *ircnet); +void ircnet_destroy(IRCNET_REC *ircnet); + /* Find the irc network by name */ IRCNET_REC *ircnet_find(const char *name); diff --git a/src/irc/core/netsplit.c b/src/irc/core/netsplit.c index 5d7d3bf3..bfa40c3c 100644 --- a/src/irc/core/netsplit.c +++ b/src/irc/core/netsplit.c @@ -203,7 +203,7 @@ int quitmsg_is_split(const char *msg) /* get the two hosts */ ok = FALSE; - params = cmd_get_params(msg, 2, &host1, &host2); + params = cmd_get_params(msg, 2 | PARAM_FLAG_NOQUOTES, &host1, &host2); if (g_strcasecmp(host1, host2) != 0) { /* hosts can't be same.. */ /* check that domain length is 2 or 3 */ p = strrchr(host1, '.'); diff --git a/src/irc/core/server-setup.c b/src/irc/core/server-setup.c index 603d7142..66c0a932 100644 --- a/src/irc/core/server-setup.c +++ b/src/irc/core/server-setup.c @@ -49,6 +49,30 @@ static void get_source_host_ip(void) } } +static void conn_set_ip(IRC_SERVER_CONNECT_REC *conn, IPADDR **own_ip, const char *own_host) +{ + IPADDR ip; + + if (*own_ip != NULL) { + /* use already resolved IP */ + if (conn->own_ip == NULL) + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, *own_ip, sizeof(IPADDR)); + return; + } + + + /* resolve the IP and use it */ + if (net_gethostbyname(own_host, &ip) == 0) { + if (conn->own_ip == NULL) + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, &ip, sizeof(IPADDR)); + + *own_ip = g_new(IPADDR, 1); + memcpy(*own_ip, &ip, sizeof(IPADDR)); + } +} + /* Create server connection record. `address' is required, rest can be NULL */ static IRC_SERVER_CONNECT_REC * create_addr_conn(const char *address, int port, const char *password, @@ -91,25 +115,8 @@ create_addr_conn(const char *address, int port, const char *password, sserver = server_setup_find(address, -1); if (sserver == NULL) return conn; - if (sserver->own_ip != NULL) { - /* use already resolved IP */ - if (conn->own_ip == NULL) - conn->own_ip = g_new(IPADDR, 1); - memcpy(conn->own_ip, sserver->own_ip, sizeof(IPADDR)); - } else if (sserver->own_host != NULL) { - /* resolve the IP and use it */ - IPADDR ip; - - if (net_gethostbyname(sserver->own_host, &ip) == 0) { - if (conn->own_ip == NULL) - conn->own_ip = g_new(IPADDR, 1); - memcpy(conn->own_ip, &ip, sizeof(IPADDR)); - - sserver->own_ip = g_new(IPADDR, 1); - memcpy(sserver->own_ip, &ip, sizeof(IPADDR)); - } - } - + if (sserver->own_host != NULL) + conn_set_ip(conn, &sserver->own_ip, sserver->own_host); sserver->last_connect = time(NULL); if (sserver->ircnet) conn->ircnet = g_strdup(sserver->ircnet); @@ -141,6 +148,14 @@ create_addr_conn(const char *address, int port, const char *password, if (ircnet->max_modes > 0) conn->max_modes = ircnet->max_modes; if (ircnet->max_whois > 0) conn->max_whois = ircnet->max_whois; + if (ircnet->max_cmds_at_once > 0 && sserver->max_cmds_at_once <= 0) + conn->max_cmds_at_once = ircnet->max_cmds_at_once; + if (ircnet->cmd_queue_speed > 0 && sserver->cmd_queue_speed <= 0) + conn->cmd_queue_speed = ircnet->cmd_queue_speed; + + if (sserver->own_host == NULL && ircnet->own_host != NULL) + conn_set_ip(conn, &ircnet->own_ip, ircnet->own_host); + return conn; } diff --git a/src/irc/dcc/dcc-files.c b/src/irc/dcc/dcc-files.c index 2fb8d0b4..e2dc732d 100644 --- a/src/irc/dcc/dcc-files.c +++ b/src/irc/dcc/dcc-files.c @@ -272,7 +272,8 @@ static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server, g_return_if_fail(data != NULL); g_return_if_fail(sender != NULL); - params = cmd_get_params(data, 4, &type, &arg, &portstr, &sizestr); + params = cmd_get_params(data, 4 | PARAM_FLAG_NOQUOTES, + &type, &arg, &portstr, &sizestr); port = atoi(portstr); size = atol(sizestr); diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index ae6fd586..4f418555 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -287,7 +287,8 @@ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char g_return_if_fail(data != NULL); g_return_if_fail(sender != NULL); - params = cmd_get_params(data, 5, &type, &arg, &addrstr, &portstr, &sizestr); + params = cmd_get_params(data, 5 | PARAM_FLAG_NOQUOTES, + &type, &arg, &addrstr, &portstr, &sizestr); if (sscanf(portstr, "%d", &port) != 1) port = 0; if (sscanf(sizestr, "%lu", &size) != 1) size = 0;