Bug 214258

Summary: Commands like /op and /deop cause an invalid MODE command to be send preceding a correct one
Product: [Applications] konversation Reporter: Eike Hein <hein>
Component: protocolAssignee: Konversation Developers <konversation-devel>
Status: RESOLVED FIXED    
Severity: normal    
Priority: NOR    
Version: Git   
Target Milestone: ---   
Platform: Unlisted Binaries   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Eike Hein 2009-11-12 13:41:48 UTC
"/op <target>" will cause Konvi to send "MODE #currentchan +o" before "MODE #currentchan +o <target>", and similar for "/deop" and various other commands that make use of OutputFilter::changeMode(). Here's some background bandied about on IRC:

[13:35] <Sho_> psn: In case you want to take a stab at this later when I'm likely offline: There's a for loop in OutputFilter::changeMode() to produce things like "+ooo nick nick nick", and the if block in that loop block there seems to be stupid and the cause for Elmaron's problem of Konvi sending "MODE #chan +o" before "MODE #chan +o nick" on /op (also happens on /deop etc), but I'm too fever-addled atm to think through the ramifications or deduce why the original author 
[13:35] <Sho_> added it.
[13:35] <Sho_> psn: Change dates back to http://websvn.kde.org/tags/konversation/0.15/kdeextragear-2/konversation/konversation/outputfilter.cpp?r1=239559&r2=253633
[13:36] <Sho_> psn: I tried 1.1 and the same bug is in there, too
Comment 1 Travis McHenry 2009-12-15 11:17:36 UTC
commit 43c80ed14c824ac0d77e19918f1da04893b3a746
Author: Travis McHenry <wordsizzle@gmail.com>
Date:   Tue Dec 15 03:15:07 2009 -0700

    Fix a bug causing an empty mode message
    
    It looks like the job of this if statement is to chop it off
    after 3 destinations have been added, append that to the result,
    and give the for loop a blank line to add more nicks to.The
    problem seems to arise from the fact that 0%3 is 0, so the line
    gets cut off at index 0 when no nicks have been added.
    BUG:214258

diff --git a/src/irc/outputfilter.cpp b/src/irc/outputfilter.cpp
index dbf5872..fc43d69 100644
--- a/src/irc/outputfilter.cpp
+++ b/src/irc/outputfilter.cpp
@@ -1875,7 +1875,7 @@ namespace Konversation
 
                 for(unsigned int index = 0; index < modeCount; index++)
                 {
-                    if((index % 3) == 0)
+                    if(index != 0 && (index % 3) == 0)
                     {
                         result.toServerList.append(token);
                         token = tmpToken;
Comment 2 Eike Hein 2009-12-15 11:57:49 UTC
That got rid of the empty MODE, but there's this problem now:

/deop foo foo foo foo

leads to:

[11:54] << MODE #konvi-test2 -oooo foo foo foo
[11:55] << MODE #konvi-test2 -oooo foo

I.e. while it's correctly wrapping after three destinations, it has as many mode chars as it has destinations on both lines, unnecessarily.
Comment 3 Travis McHenry 2009-12-15 23:08:33 UTC
commit 446b3bc892090221aa37b6a2c83901c0ea7b92a7
Author: Travis McHenry <wordsizzle@gmail.com>
Date:   Tue Dec 15 14:58:24 2009 -0700

    Fix the number of mode chars sent in op/deop
    
    Previously the modes portion would fill up for all the nicks
    so if you had 5 nicks, that would split into two lines with 3
    on the first and 2 on the second. But on both you would have 5
    mode chars. Now we add one mode per nick at the same time the
    nick is added.
    BUG:214258

diff --git a/src/irc/outputfilter.cpp b/src/irc/outputfilter.cpp
index fc43d69..fd9cb8b 100644
--- a/src/irc/outputfilter.cpp
+++ b/src/irc/outputfilter.cpp
@@ -1866,25 +1866,30 @@ namespace Konversation
             // Only continue if there was no error
             if(token.length())
             {
-                unsigned int modeCount = nickList.count();
-                QString modes;
-                modes.fill(mode, modeCount);
+                QString modeToken;
+                QString nickToken;
+
+                modeToken = QString(" ") + QChar(giveTake);
 
-                token += QString(" ") + QChar(giveTake) + modes;
                 tmpToken = token;
 
-                for(unsigned int index = 0; index < modeCount; index++)
+                for(int index = 0; index < nickList.count(); index++)
                 {
                     if(index != 0 && (index % 3) == 0)
                     {
+                        token += modeToken + nickToken;
                         result.toServerList.append(token);
                         token = tmpToken;
+                        nickToken = QString();
+                        modeToken = QString(" ") + QChar(giveTake);
                     }
-                    token += ' ' + nickList[index];
+                    nickToken += ' ' + nickList[index];
+                    modeToken += mode;
                 }
 
-                if(token != tmpToken)
+                if(!nickToken.isEmpty())
                 {
+                    token += modeToken + nickToken;
                     result.toServerList.append(token);
                 }
             }