@@ -990,33 +990,30 @@ static void got_uninvite(struct chanset_t *chan, char *nick, char *from,
990990
991991static int gotmode (char * from , char * origmsg )
992992{
993- char * nick , * ch , * op , * chg , * msg ;
993+ char * nick , * ch , * chg ;
994994 char s [UHOSTLEN ], buf [511 ];
995- char ms2 [3 ];
996- int z ;
995+ char ms2 [3 ], * arg ;
996+ int nextarg ;
997+ struct parsed_irc msg ;
997998 struct userrec * u ;
998999 memberlist * m ;
9991000 struct chanset_t * chan ;
10001001
10011002 strlcpy (buf , origmsg , sizeof buf );
1002- msg = buf ;
1003+ msg = parse_irc ( buf ) ;
10031004 /* Usermode changes? */
1004- if (msg [0 ] && (strchr (CHANMETA , msg [0 ]) != NULL )) {
1005- ch = newsplit (& msg );
1006- chg = newsplit (& msg );
1005+ if (msg .argc > 1 && (strchr (CHANMETA , msg .argv [0 ][0 ]) != NULL )) {
1006+ ch = msg .argv [0 ];
1007+ chg = msg .argv [1 ];
1008+ nextarg = 2 ;
10071009 reversing = 0 ;
10081010 chan = findchan (ch );
10091011 if (!chan ) {
10101012 putlog (LOG_MISC , "*" , CHAN_FORCEJOIN , ch );
10111013 dprintf (DP_SERVER , "PART %s\n" , ch );
10121014 } else if (channel_active (chan ) || channel_pending (chan )) {
1013- z = strlen (msg );
1014- if (msg [-- z ] == ' ' ) /* I hate cosmetic bugs :P -poptix */
1015- msg [z ] = 0 ;
1016- if (msg [0 ] == ':' )
1017- msg ++ ;
10181015 putlog (LOG_MODES , chan -> dname , "%s: mode change '%s %s' by %s" , ch , chg ,
1019- msg , from );
1016+ join_str_array ( msg . argv + 2 , msg . argc - 2 , " " ) , from );
10201017 nick = splitnick (& from );
10211018 m = ismember (chan , nick );
10221019 if (m ) {
@@ -1046,8 +1043,19 @@ static int gotmode(char *from, char *origmsg)
10461043 ms2 [0 ] = '+' ;
10471044 ms2 [2 ] = 0 ;
10481045 while ((ms2 [1 ] = * chg )) {
1046+ arg = NULL ;
10491047 int todo = 0 ;
10501048
1049+ if (* chg != '+' && * chg != '-' ) {
1050+ if ((ms2 [0 ] == '+' && MODE_HAS_SET_ARG (* chg )) || (ms2 [0 ] == '-' && MODE_HAS_UNSET_ARG (* chg ))) {
1051+ if (nextarg < msg .argc ) {
1052+ arg = msg .argv [nextarg ++ ];
1053+ } else {
1054+ putlog (LOG_MISC , "*" , "Error parsing modes in '%s', not enough arguments for %c%c" , origmsg , ms2 [0 ], * chg );
1055+ }
1056+ }
1057+ debug5 ("%s: split mode change '%s%s%s' by %s" , ch , ms2 , arg ? " " : "" , arg ? arg : "" , from );
1058+ }
10511059 switch (* chg ) {
10521060 case '+' :
10531061 ms2 [0 ] = '+' ;
@@ -1163,11 +1171,7 @@ static int gotmode(char *from, char *origmsg)
11631171 }
11641172 chan -> channel .maxmembers = 0 ;
11651173 } else {
1166- op = newsplit (& msg );
1167- fixcolon (op );
1168- if (* op == '\0' )
1169- break ;
1170- chan -> channel .maxmembers = atoi (op );
1174+ chan -> channel .maxmembers = atoi (arg );
11711175 check_tcl_mode (nick , from , u , chan -> dname , ms2 ,
11721176 int_to_base10 (chan -> channel .maxmembers ));
11731177 /* The Tcl proc might have modified/removed the chan or user */
@@ -1192,19 +1196,14 @@ static int gotmode(char *from, char *origmsg)
11921196 chan -> channel .mode |= CHANKEY ;
11931197 else
11941198 chan -> channel .mode &= ~CHANKEY ;
1195- op = newsplit (& msg );
1196- fixcolon (op );
1197- if (* op == '\0' ) {
1198- break ;
1199- }
1200- check_tcl_mode (nick , from , u , chan -> dname , ms2 , op );
1199+ check_tcl_mode (nick , from , u , chan -> dname , ms2 , arg );
12011200 /* The Tcl proc might have modified/removed the chan or user */
12021201 if (!(chan = modebind_refresh (ch , from , & user , NULL , NULL )))
12031202 return 0 ;
12041203 if (ms2 [0 ] == '+' ) {
1205- set_key (chan , op );
1204+ set_key (chan , arg );
12061205 if (channel_active (chan ))
1207- got_key (chan , nick , from , op );
1206+ got_key (chan , nick , from , arg );
12081207 } else {
12091208 if (channel_active (chan )) {
12101209 if (reversing && chan -> channel .key [0 ])
@@ -1217,29 +1216,23 @@ static int gotmode(char *from, char *origmsg)
12171216 }
12181217 break ;
12191218 case 'o' :
1220- op = newsplit (& msg );
1221- fixcolon (op );
12221219 if (ms2 [0 ] == '+' )
1223- got_op (chan , nick , from , op , u , & user );
1220+ got_op (chan , nick , from , arg , u , & user );
12241221 else
1225- got_deop (chan , nick , from , op , u );
1222+ got_deop (chan , nick , from , arg , u );
12261223 break ;
12271224 case 'h' :
1228- op = newsplit (& msg );
1229- fixcolon (op );
12301225 if (ms2 [0 ] == '+' )
1231- got_halfop (chan , nick , from , op , u , & user );
1226+ got_halfop (chan , nick , from , arg , u , & user );
12321227 else
1233- got_dehalfop (chan , nick , from , op , u );
1228+ got_dehalfop (chan , nick , from , arg , u );
12341229 break ;
12351230 case 'v' :
1236- op = newsplit (& msg );
1237- fixcolon (op );
1238- m = ismember (chan , op );
1231+ m = ismember (chan , arg );
12391232 if (!m ) {
12401233 if (channel_pending (chan ))
12411234 break ;
1242- putlog (LOG_MISC , chan -> dname , CHAN_BADCHANMODE , chan -> dname , op );
1235+ putlog (LOG_MISC , chan -> dname , CHAN_BADCHANMODE , chan -> dname , arg );
12431236 chan -> status |= CHAN_PEND ;
12441237 refresh_who_chan (chan -> name );
12451238 } else {
@@ -1248,21 +1241,21 @@ static int gotmode(char *from, char *origmsg)
12481241 if (ms2 [0 ] == '+' ) {
12491242 m -> flags &= ~SENTVOICE ;
12501243 m -> flags |= CHANVOICE ;
1251- check_tcl_mode (nick , from , u , chan -> dname , ms2 , op );
1244+ check_tcl_mode (nick , from , u , chan -> dname , ms2 , arg );
12521245 if (!(chan = modebind_refresh (ch , from , & user , s , & victim )))
12531246 return 0 ;
12541247 if (channel_active (chan ) && !glob_master (user ) &&
12551248 !chan_master (user ) && !match_my_nick (nick )) {
12561249 if (chan_quiet (victim ) ||
12571250 (glob_quiet (victim ) && !chan_voice (victim )))
1258- add_mode (chan , '-' , 'v' , op );
1251+ add_mode (chan , '-' , 'v' , arg );
12591252 else if (reversing )
1260- add_mode (chan , '-' , 'v' , op );
1253+ add_mode (chan , '-' , 'v' , arg );
12611254 }
12621255 } else {
12631256 m -> flags &= ~SENTDEVOICE ;
12641257 m -> flags &= ~CHANVOICE ;
1265- check_tcl_mode (nick , from , u , chan -> dname , ms2 , op );
1258+ check_tcl_mode (nick , from , u , chan -> dname , ms2 , arg );
12661259 if (!(chan = modebind_refresh (ch , from , & user , s , & victim )))
12671260 return 0 ;
12681261 if (channel_active (chan ) && !glob_master (user ) &&
@@ -1271,36 +1264,30 @@ static int gotmode(char *from, char *origmsg)
12711264 (chan_voice (victim ) || glob_voice (victim ))) ||
12721265 (!chan_quiet (victim ) && (glob_gvoice (victim ) ||
12731266 chan_gvoice (victim ))))
1274- add_mode (chan , '+' , 'v' , op );
1267+ add_mode (chan , '+' , 'v' , arg );
12751268 else if (reversing )
1276- add_mode (chan , '+' , 'v' , op );
1269+ add_mode (chan , '+' , 'v' , arg );
12771270 }
12781271 }
12791272 }
12801273 break ;
12811274 case 'b' :
1282- op = newsplit (& msg );
1283- fixcolon (op );
12841275 if (ms2 [0 ] == '+' )
1285- got_ban (chan , nick , from , op , ch , u );
1276+ got_ban (chan , nick , from , arg , ch , u );
12861277 else
1287- got_unban (chan , nick , from , op , ch , u );
1278+ got_unban (chan , nick , from , arg , ch , u );
12881279 break ;
12891280 case 'e' :
1290- op = newsplit (& msg );
1291- fixcolon (op );
12921281 if (ms2 [0 ] == '+' )
1293- got_exempt (chan , nick , from , op , ch , u );
1282+ got_exempt (chan , nick , from , arg , ch , u );
12941283 else
1295- got_unexempt (chan , nick , from , op , ch , u );
1284+ got_unexempt (chan , nick , from , arg , ch , u );
12961285 break ;
12971286 case 'I' :
1298- op = newsplit (& msg );
1299- fixcolon (op );
13001287 if (ms2 [0 ] == '+' )
1301- got_invite (chan , nick , from , op , ch , u );
1288+ got_invite (chan , nick , from , arg , ch , u );
13021289 else
1303- got_uninvite (chan , nick , from , op , ch , u );
1290+ got_uninvite (chan , nick , from , arg , ch , u );
13041291 break ;
13051292 }
13061293 if (todo ) {
0 commit comments