aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Szymon Tomasz Stefanek2015-08-05 03:16:17 +0200
committerGravatar Szymon Tomasz Stefanek2015-08-05 03:16:17 +0200
commite3de2f90169961969caa8d041a1db60bee29e5fc (patch)
treef7e35ee526aed7a76a99e3b36b4a60ed27f91718
parentFix cache in appveyor (diff)
downloadKVIrc-e3de2f90169961969caa8d041a1db60bee29e5fc.tar.gz
KVIrc-e3de2f90169961969caa8d041a1db60bee29e5fc.tar.bz2
KVIrc-e3de2f90169961969caa8d041a1db60bee29e5fc.zip
Rework automatic channel join process a bit. Fixes #1500
-rw-r--r--src/kvilib/irc/KviIrcServerReconnectInfo.cpp5
-rw-r--r--src/kvilib/irc/KviIrcServerReconnectInfo.h8
-rw-r--r--src/kvirc/kernel/KviIrcConnection.cpp141
-rw-r--r--src/kvirc/kernel/KviIrcConnection.h20
-rw-r--r--src/kvirc/kernel/KviIrcConnectionServerInfo.cpp6
-rw-r--r--src/kvirc/kernel/KviIrcConnectionServerInfo.h1
-rw-r--r--src/kvirc/kernel/KviIrcContext.cpp44
7 files changed, 131 insertions, 94 deletions
diff --git a/src/kvilib/irc/KviIrcServerReconnectInfo.cpp b/src/kvilib/irc/KviIrcServerReconnectInfo.cpp
index 4f2e11bdb..9edffe0ca 100644
--- a/src/kvilib/irc/KviIrcServerReconnectInfo.cpp
+++ b/src/kvilib/irc/KviIrcServerReconnectInfo.cpp
@@ -38,7 +38,8 @@ KviIrcServerReconnectInfo::KviIrcServerReconnectInfo(const KviIrcServerReconnect
m_szNick = info.m_szNick;
m_szPass = info.m_szPass;
m_szAwayReason = info.m_szAwayReason;
- m_szJoinChannels = info.m_szJoinChannels;
- m_szOpenQueryes = info.m_szOpenQueryes;
+ //m_szJoinChannels = info.m_szJoinChannels;
+ m_lJoinChannels = info.m_lJoinChannels;
+ m_lOpenQueries = info.m_lOpenQueries;
m_bIsAway = info.m_bIsAway;
}
diff --git a/src/kvilib/irc/KviIrcServerReconnectInfo.h b/src/kvilib/irc/KviIrcServerReconnectInfo.h
index 901583402..20e690f79 100644
--- a/src/kvilib/irc/KviIrcServerReconnectInfo.h
+++ b/src/kvilib/irc/KviIrcServerReconnectInfo.h
@@ -37,6 +37,8 @@
#include <QString>
#include <QStringList>
+#include <QList>
+#include <QPair>
/**
* \class KviIrcServerReconnectInfo
@@ -66,9 +68,11 @@ public:
QString m_szNick;
QString m_szPass;
QString m_szAwayReason;
- QString m_szJoinChannels;
- QStringList m_szOpenQueryes;
+ QStringList m_lOpenQueries;
bool m_bIsAway;
+
+ // The list of channels to join (first = channel name, second = password)
+ QList< QPair< QString,QString > > m_lJoinChannels;
};
#endif //_KVI_IRCSERVER_INFO_H_
diff --git a/src/kvirc/kernel/KviIrcConnection.cpp b/src/kvirc/kernel/KviIrcConnection.cpp
index 7f24f9b4d..fdd31b362 100644
--- a/src/kvirc/kernel/KviIrcConnection.cpp
+++ b/src/kvirc/kernel/KviIrcConnection.cpp
@@ -74,6 +74,7 @@
#include <QTimer>
#include <QTextCodec>
+#include <QtGlobal>
extern KVIRC_API KviIrcServerDataBase * g_pServerDataBase;
extern KVIRC_API KviProxyDataBase * g_pProxyDataBase;
@@ -1702,6 +1703,83 @@ bool KviIrcConnection::changeUserMode(char cMode, bool bSet)
return true;
}
+void KviIrcConnection::gatherChannelAndPasswordPairs(QList< QPair< QString,QString > > &lChannelsAndPasses)
+{
+ for(KviChannelWindow * c = m_pChannelList->first();c;c = m_pChannelList->next())
+ lChannelsAndPasses.append(
+ QPair<QString,QString>(
+ c->windowName(),
+ c->hasChannelMode('k') ? c->channelModeParam('k') : QString()
+ )
+ );
+}
+
+void KviIrcConnection::gatherQueryNames(QStringList &lQueryNames)
+{
+ for(KviQueryWindow * q = m_pQueryList->first(); q; q = m_pQueryList->next())
+ lQueryNames.append(q->target());
+}
+
+void KviIrcConnection::joinChannels(const QList< QPair< QString,QString > > &lChannelsAndPasses)
+{
+ if(lChannelsAndPasses.count() < 1)
+ return;
+
+ // Sort the list so the channels with passwords come first
+ QList< QPair< QString,QString> > lSorted;
+
+ QPair<QString,QString> oChanAndPass;
+ Q_FOREACH(oChanAndPass,lChannelsAndPasses)
+ {
+ if(oChanAndPass.second.isEmpty())
+ lSorted.append(oChanAndPass);
+ else
+ lSorted.prepend(oChanAndPass);
+ }
+
+ // We send the channel list in chunks to avoid overflowing the 510 character limit on the message.
+ QString szChans,szPasses;
+ QString szCommand;
+
+ while(lSorted.count() > 0)
+ {
+ QPair<QString,QString> oChanAndPass = lSorted.takeFirst();
+
+ if(!szChans.isEmpty())
+ szChans.append(',');
+ szChans.append(oChanAndPass.first);
+
+ if(!oChanAndPass.second.isEmpty())
+ {
+ if(!szPasses.isEmpty())
+ szPasses.append(',');
+ szPasses.append(oChanAndPass.second);
+ }
+
+ // empirical limit
+ if((szChans.length() + szPasses.length()) > 450)
+ {
+ szCommand = szChans;
+ if(!szPasses.isEmpty())
+ {
+ szCommand.append(" ");
+ szCommand.append(szPasses);
+ }
+ sendFmtData("JOIN %s",encodeText(szCommand).data());
+ szChans = QString();
+ szPasses = QString();
+ }
+ }
+
+ szCommand = szChans;
+ if(!szPasses.isEmpty())
+ {
+ szCommand.append(" ");
+ szCommand.append(szPasses);
+ }
+ sendFmtData("JOIN %s",encodeText(szCommand).data());
+}
+
void KviIrcConnection::loginComplete(const QString & szNickName)
{
if(context()->state() == KviIrcContext::Connected)
@@ -1807,16 +1885,16 @@ void KviIrcConnection::loginComplete(const QString & szNickName)
if(target()->server()->reconnectInfo())
{
- if(!target()->server()->reconnectInfo()->m_szJoinChannels.isEmpty())
+ if(!target()->server()->reconnectInfo()->m_lJoinChannels.isEmpty())
{
bJoinStdChannels=false;
- sendFmtData("JOIN %s",encodeText(target()->server()->reconnectInfo()->m_szJoinChannels).data());
+ joinChannels(target()->server()->reconnectInfo()->m_lJoinChannels);
}
KviQueryWindow * pQuery;
- for(QStringList::Iterator it = target()->server()->reconnectInfo()->m_szOpenQueryes.begin();
- it != target()->server()->reconnectInfo()->m_szOpenQueryes.end();it++)
+ for(QStringList::Iterator it = target()->server()->reconnectInfo()->m_lOpenQueries.begin();
+ it != target()->server()->reconnectInfo()->m_lOpenQueries.end();it++)
{
QString szNick = *it;
pQuery = findQuery(szNick);
@@ -1844,6 +1922,8 @@ void KviIrcConnection::loginComplete(const QString & szNickName)
if(bJoinStdChannels)
{
+ QList< QPair< QString,QString > > lChansAndPass;
+
if(target()->network()->autoJoinChannelList())
{
if(_OUTPUT_VERBOSE)
@@ -1856,23 +1936,9 @@ void KviIrcConnection::loginComplete(const QString & szNickName)
szCurChan = (*it).section(':',0,0);
if(szCurChan.isEmpty())
continue;
- if(szCurPass.isEmpty())
- {
- if(!szChannels.isEmpty())
- szChannels.append(",");
- if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!' || szCurChan[0]=='+'))
- szCurChan.prepend('#');
- szChannels.append(szCurChan);
- } else {
- if(!szProtectedChannels.isEmpty())
- szProtectedChannels.append(",");
- if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!' || szCurChan[0]=='+'))
- szCurChan.prepend('#');
- szProtectedChannels.append(szCurChan);
- if(!szPasswords.isEmpty())
- szPasswords.append(",");
- szPasswords.append(szCurPass);
- }
+ if(!m_pServerInfo->isSupportedChannelType(szCurChan[0]))
+ szCurChan.prepend('#');
+ lChansAndPass.append(QPair<QString,QString>(szCurChan,szCurPass));
}
}
@@ -1888,38 +1954,13 @@ void KviIrcConnection::loginComplete(const QString & szNickName)
szCurChan = (*it).section(':',0,0);
if(szCurChan.isEmpty())
continue;
- if(szCurPass.isEmpty())
- {
- if(!szChannels.isEmpty())
- szChannels.append(",");
- if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!' || szCurChan[0]=='+'))
- szCurChan.prepend('#');
- szChannels.append(szCurChan);
- } else {
- if(!szProtectedChannels.isEmpty())
- szProtectedChannels.append(",");
- if(!(szCurChan[0]=='#' || szCurChan[0]=='&' || szCurChan[0]=='!' || szCurChan[0]=='+'))
- szCurChan.prepend('#');
- szProtectedChannels.append(szCurChan);
- if(!szPasswords.isEmpty())
- szPasswords.append(",");
- szPasswords.append(szCurPass);
- }
+ if(!m_pServerInfo->isSupportedChannelType(szCurChan[0]))
+ szCurChan.prepend('#');
+ lChansAndPass.append(QPair<QString,QString>(szCurChan,szCurPass));
}
}
- QString szCommand;
- if( (!szChannels.isEmpty()) || (!szProtectedChannels.isEmpty()) )
- {
- szCommand.append(szProtectedChannels);
- if(!szProtectedChannels.isEmpty() && !szChannels.isEmpty())
- szCommand.append(',');
- szCommand.append(szChannels);
- szCommand.append(" ");
- szCommand.append(szPasswords);
-
- sendFmtData("JOIN %s",encodeText(szCommand).data());
- }
+ joinChannels(lChansAndPass);
}
// minimize after connect
if(KVI_OPTION_BOOL(KviOption_boolMinimizeConsoleAfterConnect))
diff --git a/src/kvirc/kernel/KviIrcConnection.h b/src/kvirc/kernel/KviIrcConnection.h
index fbde1fdbf..f473dd61a 100644
--- a/src/kvirc/kernel/KviIrcConnection.h
+++ b/src/kvirc/kernel/KviIrcConnection.h
@@ -37,6 +37,9 @@
#include <QObject>
#include <QByteArray>
+#include <QStringList>
+#include <QList>
+#include <QPair>
class QTimer;
class QTextCodec;
@@ -753,6 +756,23 @@ protected:
void loginToIrcServer();
/**
+ * Joins a list of channels.
+ * The first element of the pair is the channel name, the second element of the pair is the eventual password.
+ * May send multiple JOIN messages.
+ */
+ void joinChannels(const QList< QPair< QString,QString > > &lChannelsAndPasses);
+
+ /**
+ * Gather the list of currently joined channels with the relative passwords.
+ */
+ void gatherChannelAndPasswordPairs(QList< QPair< QString,QString > > &lChannelsAndPasses);
+
+ /**
+ * Gather the list of currently open query names.
+ */
+ void gatherQueryNames(QStringList &lQueryNames);
+
+ /**
* Picks the next login nickname to be tried. If bForceDefaultIfPrimaryNicknamesEmpty is true then the algorithm
* will return a default nickname in case the primary setting in the options is empty. If bForceDefaultIfPrimaryNicknamesEmpty
* is false then the algorithm will try the alternative nicknames instead, then try some random options and finally
diff --git a/src/kvirc/kernel/KviIrcConnectionServerInfo.cpp b/src/kvirc/kernel/KviIrcConnectionServerInfo.cpp
index a699d8e32..abd222d5f 100644
--- a/src/kvirc/kernel/KviIrcConnectionServerInfo.cpp
+++ b/src/kvirc/kernel/KviIrcConnectionServerInfo.cpp
@@ -58,6 +58,12 @@ KviIrcConnectionServerInfo::~KviIrcConnectionServerInfo()
KviMemory::free(m_pModePrefixTable);
}
+bool KviIrcConnectionServerInfo::isSupportedChannelType(QChar c)
+{
+ return m_szSupportedChannelTypes.contains(c);
+}
+
+
void KviIrcConnectionServerInfo::addSupportedCaps(const QString &szCapList)
{
m_bSupportsCap = true;
diff --git a/src/kvirc/kernel/KviIrcConnectionServerInfo.h b/src/kvirc/kernel/KviIrcConnectionServerInfo.h
index 397a6d6d6..1867a31e3 100644
--- a/src/kvirc/kernel/KviIrcConnectionServerInfo.h
+++ b/src/kvirc/kernel/KviIrcConnectionServerInfo.h
@@ -240,6 +240,7 @@ public:
const QString & getChannelModeDescription(char mode) { return m_pServInfo->getChannelModeDescription(mode); };
const QString & getUserModeDescription(QChar mode) { return m_pServInfo->getUserModeDescription(mode); };
+ bool isSupportedChannelType(QChar c);
bool isSupportedModePrefix(QChar c);
bool isSupportedModeFlag(QChar c);
QChar modePrefixChar(kvi_u32_t flag);
diff --git a/src/kvirc/kernel/KviIrcContext.cpp b/src/kvirc/kernel/KviIrcContext.cpp
index 7f25d4379..9a69577b4 100644
--- a/src/kvirc/kernel/KviIrcContext.cpp
+++ b/src/kvirc/kernel/KviIrcContext.cpp
@@ -738,48 +738,10 @@ void KviIrcContext::connectionTerminated()
if(KVI_OPTION_BOOL(KviOption_boolAutoReconnectOnUnexpectedDisconnect))
{
if(KVI_OPTION_BOOL(KviOption_boolRejoinChannelsAfterReconnect))
- {
- // FIXME: THIS SHOULD BE A KviIrcConnection FUNCTION
- KviChannelWindow * c;
- QString szChannels, szProtectedChannels, szPasswords, szCurPass, szCurChan;
- // first only chans without key, in groups of 4
- for(c = connection()->channelList()->first(); c; c = connection()->channelList()->next())
- {
- szCurPass = c->hasChannelMode('k') ? c->channelModeParam('k') : "";
- szCurChan = c->windowName();
- if(szCurPass.isEmpty())
- {
- if(!szChannels.isEmpty())
- szChannels.append(",");
- szChannels.append(szCurChan);
- } else {
- if(!szProtectedChannels.isEmpty())
- szProtectedChannels.append(",");
- szProtectedChannels.append(szCurChan);
- if(!szPasswords.isEmpty())
- szPasswords.append(",");
- szPasswords.append(szCurPass);
- }
- }
- if((!szChannels.isEmpty()) || (!szProtectedChannels.isEmpty()))
- {
- info.m_szJoinChannels.append(szProtectedChannels);
- if(!szProtectedChannels.isEmpty() && !szChannels.isEmpty())
- info.m_szJoinChannels.append(',');
- info.m_szJoinChannels.append(szChannels);
- info.m_szJoinChannels.append(" ");
- info.m_szJoinChannels.append(szPasswords);
- }
- }
-
+ connection()->gatherChannelAndPasswordPairs(info.m_lJoinChannels);
if(KVI_OPTION_BOOL(KviOption_boolReopenQueriesAfterReconnect))
- {
- for(KviQueryWindow * q = connection()->queryList()->first(); q; q = connection()->queryList()->next())
- {
- info.m_szOpenQueryes.append(q->target());
- }
- }
+ connection()->gatherQueryNames(info.m_lOpenQueries);
}
if(KVI_OPTION_BOOL(KviOption_boolKeepChannelsOpenOnUnexpectedDisconnect) || KVI_OPTION_BOOL(KviOption_boolKeepChannelsOpenOnDisconnect))
@@ -816,6 +778,7 @@ void KviIrcContext::connectionTerminated()
//m_uConnectAttemptCount = 1;
if(!_OUTPUT_MUTE)
m_pConsole->output(KVI_OUT_CONNECTION,__tr2qs("The connection terminated unexpectedly. Trying to reconnect..."));
+
KviAsynchronousConnectionData * d = new KviAsynchronousConnectionData();
d->szServerId = oldServer.id();
d->szServer = oldServer.hostName();
@@ -827,6 +790,7 @@ void KviIrcContext::connectionTerminated()
d->szPass = oldServer.password();
d->szInitUMode = oldServer.initUMode();
d->m_pReconnectInfo = new KviIrcServerReconnectInfo(info);
+
setAsynchronousConnectionData(d);
beginAsynchronousConnect(1000 * KVI_OPTION_UINT(KviOption_uintAutoReconnectDelay));