]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/proto-common.c
Fixed a typo in ROUTING EXAMPLE
[irc/evilnet/x3.git] / src / proto-common.c
index 0254bbd91dce08071e6c5e82e1fb73496b139088..402ea68486011ba5176c9e5794c8b6f666583709 100644 (file)
@@ -3,9 +3,9 @@
  *
  * This file is part of x3.
  *
- * srvx is free software; you can redistribute it and/or modify
+ * x3 is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -23,6 +23,7 @@
 #include "ioset.h"
 #include "log.h"
 #include "nickserv.h"
+#include "spamserv.h"
 #include "shun.h"
 #include "timeq.h"
 #ifdef HAVE_SYS_SOCKET_H
@@ -70,6 +71,7 @@ typedef void (*foreach_nonchan) (char *name, void *data);
 typedef void (*foreach_userfunc) (struct userNode *user, void *data);
 typedef void (*foreach_nonuser) (char *name, void *data);
 static void parse_foreach(char *target_list, foreach_chanfunc cf, foreach_nonchan nc, foreach_userfunc uf, foreach_nonuser nu, void *data);
+static void call_channel_mode_funcs(struct userNode *who, struct chanNode *channel, char **modes, unsigned int argc);
 
 static void
 uplink_readable(struct io_fd *fd) {
@@ -93,7 +95,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;
@@ -106,7 +108,7 @@ void replay_event_loop(void)
     while (!quit_services) {
         if (!replay_connected) {
             /* this time fudging is to get some of the logging right */
-            self->link = self->boot = now;
+            self->link_time = self->boot = now;
             cManager.uplink->state = AUTHENTICATING;
             irc_introduce(cManager.uplink->password);
             replay_connected = 1;
@@ -145,7 +147,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;
@@ -276,7 +277,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;
     }
 }
 
@@ -432,7 +434,7 @@ privmsg_chan_helper(struct chanNode *cn, void *data)
 {
     struct privmsg_desc *pd = data;
     struct modeNode *mn;
-    struct chanmsg_func *cf = &chanmsg_funcs[(unsigned char)pd->text[0]];
+    struct chanmsg_func *cf;
     int x;
 
     /* Don't complain if it can't find the modeNode because the channel might
@@ -441,9 +443,11 @@ privmsg_chan_helper(struct chanNode *cn, void *data)
         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)))
-         cf->func(pd->user, cn, pd->text+1, cf->service);
+    cf = &chanmsg_funcs[(unsigned char)pd->text[0]];
+    if (!pd->is_notice && cf->func)
+        cf->func(pd->user, cn, pd->text+1, cf->service, pd->is_notice);
+    else
+        spamserv_channel_message(cn, pd->user, pd->text);
 
     /* This catches *all* text sent to the channel that the services server sees */
     for (x = 0; x < ALLCHANMSG_FUNCS_MAX; x++) {
@@ -451,7 +455,7 @@ privmsg_chan_helper(struct chanNode *cn, void *data)
        if (!cf->func)
          break; /* end of list */
        else
-         cf->func(pd->user, cn, pd->text, cf->service);
+         cf->func(pd->user, cn, pd->text, cf->service, pd->is_notice);
     }
 }
 
@@ -465,10 +469,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
@@ -517,6 +541,37 @@ reg_mode_change_func(mode_change_func_t handler)
     mcf_list[mcf_used++] = handler;
 }
 
+static oper_func_t *of_list;
+
+static unsigned int of_size = 0, of_used = 0;
+
+void
+reg_oper_func(oper_func_t handler)
+{
+    if (of_used == of_size) {
+        if (of_size) {
+            of_size <<= 1;
+            of_list = realloc(of_list, of_size*sizeof(oper_func_t));
+        } else {
+            of_size = 8;
+            of_list = malloc(of_size*sizeof(oper_func_t));
+        }
+    }
+    of_list[of_used++] = handler;
+}
+
+static void
+call_oper_funcs(struct userNode *user)
+{
+    unsigned int n;
+    if (IsLocal(user))
+        return;
+    for (n=0; (n<of_used) && !user->dead; n++)
+    {
+        of_list[n](user);
+    }
+}
+
 struct mod_chanmode *
 mod_chanmode_alloc(unsigned int argc)
 {
@@ -686,6 +741,9 @@ mod_chanmode(struct userNode *who, struct chanNode *channel, char **modes, unsig
         base_oplevel = MAXOPLEVEL;
     if (!(change = mod_chanmode_parse(channel, modes, argc, flags, base_oplevel)))
         return 0;
+
+    call_channel_mode_funcs(who, channel, modes, argc);
+
     if (flags & MC_ANNOUNCE)
         mod_chanmode_announce(who, channel, change);
     else
@@ -710,6 +768,84 @@ irc_make_chanmode(struct chanNode *chan, char *out)
     return strlen(mod_chanmode_format(&change, out));
 }
 
+static user_mode_func_t *um_list;
+static unsigned int um_size = 0, um_used = 0;
+
+void
+reg_user_mode_func(user_mode_func_t handler)
+{
+       if (um_used == um_size) {
+               if (um_size) {
+                       um_size <<= 1;
+                       um_list = realloc(um_list, um_size*sizeof(user_mode_func_t));
+               } else {
+                       um_size = 8;
+                       um_list = malloc(um_size*sizeof(user_mode_func_t));
+               }
+       }
+       um_list[um_used++] = handler;
+}
+
+void
+unreg_user_mode_func(user_mode_func_t handler)
+{
+       unsigned int i;
+       for (i=0; i<um_used; i++) {
+               if (um_list[i] == handler) break;
+       }
+       if (i == um_used) return;
+       memmove(um_list+i, um_list+i+1, (um_used-i-1)*sizeof(um_list[0]));
+       um_used--;
+}
+
+static void
+call_user_mode_funcs(struct userNode *user, const char *mode_change)
+{
+       unsigned int n;
+       for (n=0; n<um_used; n++) {
+               um_list[n](user, mode_change);
+       }
+}
+
+static channel_mode_func_t *cm_list;
+static unsigned int cm_size = 0, cm_used = 0;
+
+void
+reg_channel_mode_func(channel_mode_func_t handler)
+{
+       if (cm_used == cm_size) {
+               if (cm_size) {
+                       cm_size <<= 1;
+                       cm_list = realloc(cm_list, cm_size*sizeof(channel_mode_func_t));
+               } else {
+                       cm_size = 8;
+                       cm_list = malloc(cm_size*sizeof(channel_mode_func_t));
+               }
+       }
+       cm_list[cm_used++] = handler;
+}
+
+void
+unreg_channel_mode_func(channel_mode_func_t handler)
+{
+       unsigned int i;
+       for (i=0; i<cm_used; i++) {
+               if(cm_list[i] == handler) break;
+       }
+       if (i == cm_used) return;
+       memmove(cm_list+i, cm_list+i+1, (cm_used-i-1)*sizeof(cm_list[0]));
+       cm_used--;
+}
+
+static void
+call_channel_mode_funcs(struct userNode *who, struct chanNode *channel, char **modes, unsigned int argc)
+{
+       unsigned int n;
+       for (n=0; n<cm_used; n++) {
+               cm_list[n](who, channel, modes, argc);
+       }
+}
+
 char *
 generate_hostmask(struct userNode *user, int options)
 {
@@ -749,9 +885,20 @@ generate_hostmask(struct userNode *user, int options)
     hostname = user->hostname;
     if (IsFakeHost(user) && IsHiddenHost(user) && !(options & GENMASK_NO_HIDING)) {
         hostname = user->fakehost;
-    } 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 (IsHiddenHost(user)) {
+        int style = 1;
+        char *data;
+        data = conf_get_data("server/hidden_host_type", RECDB_QSTRING);
+        if (data)
+            style = atoi(data);
+
+        if ((style == 1) && 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 ((style == 2) && !(options & GENMASK_NO_HIDING)) {
+            hostname = alloca(strlen(user->crypthost));
+            sprintf(hostname, "%s", user->crypthost);
+        }
     } else if (options & GENMASK_STRICT_HOST) {
         if (options & GENMASK_BYIP)
             hostname = (char*)irc_ntoa(&user->ip);
@@ -775,8 +922,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. */