Fix typo in "gtrace criteria" help entry.
[srvx.git] / src / proto-common.c
index b5e5118a02e246706df003fbfdc5f21fb122dd52..f681a6ab1f86de7a87c56f1b5de346993d5e3ffa 100644 (file)
@@ -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;
     }
 }
 
@@ -439,9 +439,8 @@ privmsg_chan_helper(struct chanNode *cn, void *data)
     if ((mn = GetUserMode(cn, pd->user)))
         mn->idle_since = now;
 
-    /* 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)))
+    if (cf->func && !pd->is_notice
+        && (GetUserMode(cn, cf->service) && !IsDeaf(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 */
@@ -464,10 +463,30 @@ 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
@@ -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. */