KICK user only if he's really in the channel!
[srvx.git] / src / proto-p10.c
index 03a0fa0de76bfa3febbcd4da1671d9d78b52b4be..1e4702726fd9fcfe080c4f9a21beb34588056f24 100644 (file)
@@ -518,7 +518,6 @@ void
 irc_relay(char *message)
 {
     putsock("%s " P10_RELAY " %s", self->numeric, message);
-    fprintf(stderr,"%s " P10_RELAY " %s", self->numeric, message);
 }
 
 void 
@@ -703,12 +702,16 @@ irc_introduce(const char *passwd)
 void
 irc_gline(struct server *srv, struct gline *gline)
 {
+    //<prefix> GL <target> [!][+|-|>|<]<mask> [<expiration>] [<lastmod>] [<lifetime>] [:<reason>]
+    //expiration = relative time (seconds)
+    //lastmod = timestamp
+    //livetime = timestamp
     if (gline->lastmod)
-        putsock("%s " P10_GLINE " %s +%s %lu %lu %lu :%s",
-                self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires, gline->lastmod, gline->lifetime, gline->reason);
+        putsock("%s " P10_GLINE " %s +%s %lu %lu %lu :%s", self->numeric, (srv ? srv->numeric : "*"), 
+                gline->target, gline->expires-now, gline->lastmod, gline->lifetime, gline->reason);
     else
-        putsock("%s " P10_GLINE " %s +%s %lu :%s",
-                self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires, gline->reason);
+        putsock("%s " P10_GLINE " %s +%s %lu :%s", self->numeric, (srv ? srv->numeric : "*"), 
+                gline->target, gline->expires-now, gline->reason);
 }
 
 void
@@ -1755,9 +1758,10 @@ static CMD_FUNC(cmd_relay)
             //LQ !ABADE pk910 80.153.5.212 server.zoelle1.de ~watchcat :test
             //ok  let's check the login datas
             struct handle_info *hi;
-            char tmp[MAXLEN];
-            sprintf(tmp, "*!%s@%s",argv[7],argv[5]);
-            if((hi = checklogin(argv[4],argv[argc-1],&argv[3][1],tmp))) {
+            char tmp[MAXLEN], tmp2[MAXLEN];
+            sprintf(tmp, "%s@%s",argv[7],argv[6]);
+            sprintf(tmp2, "%s@%s",argv[7],argv[5]);
+            if((hi = checklogin(argv[4],argv[argc-1],&argv[3][1],tmp,tmp2))) {
              //login ok
              struct devnull_class *th;
              char devnull[512];
@@ -1773,6 +1777,10 @@ static CMD_FUNC(cmd_relay)
              } else {
                 devnull[0] = 0;
              }
+             /*
+             if(!HANDLE_FLAGGED(hi, AUTOHIDE)) {
+                sprintf(tmp,"%s LA %s 0 %s\n",argv[3],hi->handle,devnull);
+             } else */ 
              if(getfakehost(argv[4])) {
                 sprintf(tmp,"%s LA %s %s %s\n",argv[3],hi->handle,getfakehost(argv[4]),devnull);
              } else {
@@ -2555,7 +2563,7 @@ keyncpy(char output[], char input[], size_t output_size)
 }
 
 struct mod_chanmode *
-mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel)
+mod_chanmode_parse(struct chanNode *channel, struct userNode *user, char **modes, unsigned int argc, unsigned int flags, short base_oplevel)
 {
     struct mod_chanmode *change;
     unsigned int ii, in_arg, ch_arg, add;
@@ -2581,6 +2589,7 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
         case 'c': do_chan_mode(MODE_NOCOLORS); break;
         case 'M': do_chan_mode(MODE_NOAMSGS); break;
         case 'N': do_chan_mode(MODE_NONOTICES); break;
+        case 'u': do_chan_mode(MODE_AUDITORIUM); break;
         case 'i': do_chan_mode(MODE_INVITEONLY); break;
         case 'm': do_chan_mode(MODE_MODERATED); break;
         case 'n': do_chan_mode(MODE_NOPRIVMSGS); break;
@@ -2641,10 +2650,11 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
                            if (in_arg >= argc)
                     goto error;
                 char *mode = modes[in_arg++];
-                if(mode[0] == '!' && !(flags & MCP_OPERMODE)) { //noflood flag also for overriders
-                    //only allow opers
-                    goto error;
-                }
+                if(mode[0] == '!' && !(flags & MCP_OPERMODE)) //noflood flag also for overriders
+                   goto error;//only allow opers
+                else if(mode[0] == '!')
+                   mode++;
+                
                 if(mode[0] == '+' || mode[0] == '@') {
                     mode++;
                 }
@@ -2661,19 +2671,40 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un
                                                break;
                                }
                 }
-                if(count <= 0 || time <= 0 || count > 100 || time > 600) 
+                if(count <= 0 || time <= 0 || count > 100 || time > 600)
                                    goto error;
                                change->modes_set |= MODE_NOFLOOD;
                                safestrncpy(change->new_noflood, modes[in_arg - 1], sizeof(change->new_noflood));
                        } else {
                            change->modes_clear |= MODE_NOFLOOD;
                        }
+            break;
         case 'F':
             if (add) {
                 if (in_arg >= argc)
                     goto error;
+                char *altchan = modes[in_arg++];
+                struct chanNode *target;
+                if(!IsChannelName(altchan) || !(target = GetChannel(altchan)))
+                    goto error;
+                if(!(flags & MCP_OPERMODE)) {
+                    //check if the user has the permissions to use this channel as target
+                    struct modeNode *mn;
+                    struct userData *uData;
+                    struct chanData *cData;
+                    if(user && (mn = GetUserMode(target, user)) && (mn->modes & MODE_CHANOP)) {
+                        //allow - user is opped on target channel
+                    } else if(user && user->handle_info && 
+                              (uData = GetChannelUser(channel->channel_info, user->handle_info)) && 
+                              (cData = uData->channel) && 
+                              uData->access >= cData->lvlOpts[lvlGiveOps]
+                             ) {
+                        //allow - user has access to get op on the channel
+                    } else 
+                        goto error;
+                }
                 change->modes_set |= MODE_ALTCHAN;
-                safestrncpy(change->new_altchan, modes[in_arg++], sizeof(change->new_altchan));
+                safestrncpy(change->new_altchan, altchan, sizeof(change->new_altchan));
             } else {
                 change->modes_clear |= MODE_ALTCHAN;
             }
@@ -2867,6 +2898,7 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod
         DO_MODE_CHAR(NOCTCPS, 'C');
         DO_MODE_CHAR(NONOTICES, 'N');
         DO_MODE_CHAR(NOAMSGS, 'M');
+        DO_MODE_CHAR(AUDITORIUM, 'u');
         DO_MODE_CHAR(REGISTERED, 'z');
 #undef DO_MODE_CHAR
         if (change->modes_clear & channel->modes & MODE_KEY)
@@ -2912,6 +2944,7 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod
         DO_MODE_CHAR(NOCTCPS, 'C');
         DO_MODE_CHAR(NONOTICES, 'N');
         DO_MODE_CHAR(NOAMSGS, 'M');
+        DO_MODE_CHAR(AUDITORIUM, 'u');
         DO_MODE_CHAR(REGISTERED, 'z');
 #undef DO_MODE_CHAR
         if(change->modes_set & MODE_KEY)
@@ -2990,6 +3023,7 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
         DO_MODE_CHAR(NOCTCPS, 'C');
         DO_MODE_CHAR(NONOTICES, 'N');
         DO_MODE_CHAR(NOAMSGS, 'M');
+        DO_MODE_CHAR(AUDITORIUM, 'u');
         DO_MODE_CHAR(REGISTERED, 'z');
 #undef DO_MODE_CHAR
     }
@@ -3008,12 +3042,13 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
         DO_MODE_CHAR(NOCTCPS, 'C');
         DO_MODE_CHAR(NONOTICES, 'N');
                DO_MODE_CHAR(NOAMSGS, 'M');
+        DO_MODE_CHAR(AUDITORIUM, 'u');
         DO_MODE_CHAR(REGISTERED, 'z');
         DO_MODE_CHAR(LIMIT, 'l'), args_used += sprintf(args + args_used, " %d", change->new_limit);
         DO_MODE_CHAR(KEY, 'k'), args_used += sprintf(args + args_used, " %s", change->new_key);
-        DO_MODE_CHAR(KEY, 'a'), args_used += sprintf(args + args_used, " %d", change->new_access);
-        DO_MODE_CHAR(KEY, 'F'), args_used += sprintf(args + args_used, " %s", change->new_altchan);
-        DO_MODE_CHAR(KEY, 'f'), args_used += sprintf(args + args_used, " %s", change->new_noflood);
+        DO_MODE_CHAR(ACCESS, 'a'), args_used += sprintf(args + args_used, " %d", change->new_access);
+        DO_MODE_CHAR(ALTCHAN, 'F'), args_used += sprintf(args + args_used, " %s", change->new_altchan);
+        DO_MODE_CHAR(NOFLOOD, 'f'), args_used += sprintf(args + args_used, " %s", change->new_noflood);
         DO_MODE_CHAR(UPASS, 'U'), args_used += sprintf(args + args_used, " %s", change->new_upass);
         DO_MODE_CHAR(APASS, 'A'), args_used += sprintf(args + args_used, " %s", change->new_apass);
 #undef DO_MODE_CHAR
@@ -3072,6 +3107,7 @@ clear_chanmode(struct chanNode *channel, const char *modes)
         case 'c': cleared |= MODE_NOCOLORS; break;
         case 'C': cleared |= MODE_NOCTCPS; break;
         case 'M': cleared |= MODE_NOAMSGS; break;
+        case 'u': cleared |= MODE_AUDITORIUM; break;
         case 'N': cleared |= MODE_NONOTICES; break;
         case 'z': cleared |= MODE_REGISTERED; break;
         }