X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fproto-common.c;h=729c8fcda38e0d3ef85c085c2cf188855e87a673;hb=7fe401a165cdfb1f102cf3d545e1dffb3896a2e9;hp=b5e5118a02e246706df003fbfdc5f21fb122dd52;hpb=fd209bd5cc9ffc7989c461a2f2a2011790668d32;p=srvx.git diff --git a/src/proto-common.c b/src/proto-common.c index b5e5118..729c8fc 100644 --- a/src/proto-common.c +++ b/src/proto-common.c @@ -1,5 +1,5 @@ /* proto-common.c - common IRC protocol parsing/sending support - * Copyright 2000-2004 srvx Development Team + * Copyright 2000-2006 srvx Development Team * * This file is part of srvx. * @@ -92,7 +92,7 @@ uplink_readable(struct io_fd *fd) { void socket_destroyed(struct io_fd *fd) { - if (fd && fd->eof) + if (fd && fd->state != IO_CONNECTED) log_module(MAIN_LOG, LOG_ERROR, "Connection to server lost."); socket_io_fd = NULL; cManager.uplink->state = DISCONNECTED; @@ -144,7 +144,6 @@ create_socket_client(struct uplinkNode *target) socket_io_fd->readable_cb = uplink_readable; socket_io_fd->destroy_cb = socket_destroyed; socket_io_fd->line_reads = 1; - socket_io_fd->wants_reads = 1; log_module(MAIN_LOG, LOG_INFO, "Connection to server established."); cManager.uplink = target; target->state = AUTHENTICATING; @@ -275,7 +274,8 @@ close_socket(void) replay_connected = 0; socket_destroyed(socket_io_fd); } else { - ioset_close(socket_io_fd->fd, 1); + ioset_close(socket_io_fd, 3); + socket_io_fd = NULL; } } @@ -311,11 +311,11 @@ static CMD_FUNC(cmd_pass) return 0; true_pass = cManager.uplink->their_password; if (true_pass && strcmp(true_pass, argv[1])) { - /* It might be good to mark the uplink as unavailable when - this happens, though there should be a way of resetting - the flag. */ - irc_squit(self, "Incorrect password received.", NULL); - return 1; + /* It might be good to mark the uplink as unavailable when + this happens, though there should be a way of resetting + the flag. */ + irc_squit(self, "Incorrect password received.", NULL); + return 1; } cManager.uplink->state = BURSTING; @@ -330,13 +330,13 @@ static CMD_FUNC(cmd_dummy) static CMD_FUNC(cmd_error) { - if (argv[1]) log_module(MAIN_LOG, LOG_ERROR, "Error: %s", argv[1]); + if (argv[1]) log_module(MAIN_LOG, LOG_ERROR, "Error from ircd: %s", argv[1]); log_module(MAIN_LOG, LOG_ERROR, "Error received from uplink, squitting."); if (cManager.uplink->state != CONNECTED) { - /* Error messages while connected should be fine. */ - cManager.uplink->flags |= UPLINK_UNAVAILABLE; - log_module(MAIN_LOG, LOG_ERROR, "Disabling uplink."); + /* Error messages while connected should be fine. */ + cManager.uplink->flags |= UPLINK_UNAVAILABLE; + log_module(MAIN_LOG, LOG_ERROR, "Disabling uplink."); } close_socket(); @@ -442,7 +442,6 @@ privmsg_chan_helper(struct chanNode *cn, void *data) /* Never send a NOTICE to a channel to one of the services */ if (!pd->is_notice && cf->func && ((cn->modes & MODE_REGISTERED) || GetUserMode(cn, cf->service))) - cf->func(pd->user, cn, pd->text+1, cf->service); /* This catches *all* text sent to the channel that the services server sees */ for (x = 0; x < ALLCHANMSG_FUNCS_MAX; x++) { @@ -464,17 +463,37 @@ privmsg_invalid(char *name, void *data) irc_numeric(pd->user, ERR_NOSUCHNICK, "%s@%s :No such nick", name, self->name); } +struct part_desc { + struct userNode *user; + const char *text; +}; + static void part_helper(struct chanNode *cn, void *data) { - DelChannelUser(data, cn, false, 0); + struct part_desc *desc = data; + DelChannelUser(desc->user, cn, desc->text, false); +} + +static CMD_FUNC(cmd_part) +{ + struct part_desc desc; + + if (argc < 2) + return 0; + desc.user = GetUserH(origin); + if (!desc.user) + return 0; + desc.text = (argc > 2) ? argv[argc - 1] : NULL; + parse_foreach(argv[1], part_helper, NULL, NULL, NULL, &desc); + return 1; } void reg_chanmsg_func(unsigned char prefix, struct userNode *service, chanmsg_func_t handler) { if (chanmsg_funcs[prefix].func) - log_module(MAIN_LOG, LOG_WARNING, "Re-registering new chanmsg handler for character `%c'.", prefix); + log_module(MAIN_LOG, LOG_WARNING, "Re-registering new chanmsg handler for character `%c'.", prefix); chanmsg_funcs[prefix].func = handler; chanmsg_funcs[prefix].service = service; } @@ -505,13 +524,13 @@ void reg_mode_change_func(mode_change_func_t handler) { if (mcf_used == mcf_size) { - if (mcf_size) { - mcf_size <<= 1; - mcf_list = realloc(mcf_list, mcf_size*sizeof(mode_change_func_t)); - } else { - mcf_size = 8; - mcf_list = malloc(mcf_size*sizeof(mode_change_func_t)); - } + if (mcf_size) { + mcf_size <<= 1; + mcf_list = realloc(mcf_list, mcf_size*sizeof(mode_change_func_t)); + } else { + mcf_size = 8; + mcf_list = malloc(mcf_size*sizeof(mode_change_func_t)); + } } mcf_list[mcf_used++] = handler; } @@ -543,6 +562,8 @@ mod_chanmode_dup(struct mod_chanmode *orig, unsigned int extra) res->modes_clear = orig->modes_clear; res->new_limit = orig->new_limit; memcpy(res->new_key, orig->new_key, sizeof(res->new_key)); + memcpy(res->new_upass, orig->new_upass, sizeof(res->new_upass)); + memcpy(res->new_apass, orig->new_apass, sizeof(res->new_apass)); res->argc = orig->argc; memcpy(res->args, orig->args, orig->argc*sizeof(orig->args[0])); } @@ -561,6 +582,10 @@ mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_ch channel->limit = change->new_limit; if (change->modes_set & MODE_KEY) strcpy(channel->key, change->new_key); + if (change->modes_set & MODE_UPASS) + strcpy(channel->upass, change->new_upass); + if (change->modes_set & MODE_APASS) + strcpy(channel->apass, change->new_apass); for (ii = 0; ii < change->argc; ++ii) { switch (change->args[ii].mode) { case MODE_BAN: @@ -622,12 +647,18 @@ mod_chanmode_free(struct mod_chanmode *change) int mod_chanmode(struct userNode *who, struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags) { + struct modeNode *member; struct mod_chanmode *change; unsigned int ii; + short base_oplevel; if (!modes || !modes[0]) return 0; - if (!(change = mod_chanmode_parse(channel, modes, argc, flags))) + if (who && (member = GetUserMode(channel, who))) + base_oplevel = member->oplevel; + else + base_oplevel = MAXOPLEVEL; + if (!(change = mod_chanmode_parse(channel, modes, argc, flags, base_oplevel))) return 0; if (flags & MC_ANNOUNCE) mod_chanmode_announce(who, channel, change); @@ -648,6 +679,8 @@ irc_make_chanmode(struct chanNode *chan, char *out) change.modes_set = chan->modes; change.new_limit = chan->limit; safestrncpy(change.new_key, chan->key, sizeof(change.new_key)); + safestrncpy(change.new_upass, chan->upass, sizeof(change.new_upass)); + safestrncpy(change.new_apass, chan->apass, sizeof(change.new_apass)); return strlen(mod_chanmode_format(&change, out)); } @@ -680,8 +713,9 @@ generate_hostmask(struct userNode *user, int options) } else if (IsHiddenHost(user) && user->handle_info && hidden_host_suffix && !(options & GENMASK_NO_HIDING)) { hostname = alloca(strlen(user->handle_info->handle) + strlen(hidden_host_suffix) + 2); sprintf(hostname, "%s.%s", user->handle_info->handle, hidden_host_suffix); - } else if (options & GENMASK_STRICT_HOST && options & GENMASK_BYIP) { - hostname = (char*)irc_ntoa(&user->ip); + } else if (options & GENMASK_STRICT_HOST) { + if (options & GENMASK_BYIP) + hostname = (char*)irc_ntoa(&user->ip); } else if ((options & GENMASK_BYIP) || irc_pton(&ip, NULL, hostname)) { /* Should generate an IP-based hostmask. */ hostname = alloca(IRC_NTOP_MAX_SIZE); @@ -702,8 +736,8 @@ generate_hostmask(struct userNode *user, int options) for (ii=cnt=0; hostname[ii]; ii++) if (hostname[ii] == '.') cnt++; - if (cnt == 1) { - /* only a two-level domain name; leave hostname */ + if (cnt == 0 || cnt == 1) { + /* only a one- or two-level domain name; leave hostname */ } else if (cnt == 2) { for (ii=0; user->hostname[ii] != '.'; ii++) ; /* Add 3 to account for the *. and \0. */