_prefixModes(QString()),
_useRandomServer(false),
_useAutoIdentify(false),
+ _useSasl(false),
_useAutoReconnect(false),
_autoReconnectInterval(60),
_autoReconnectRetries(10),
info.useAutoIdentify = useAutoIdentify();
info.autoIdentifyService = autoIdentifyService();
info.autoIdentifyPassword = autoIdentifyPassword();
+ info.useSasl = useSasl();
+ info.saslAccount = saslAccount();
+ info.saslPassword = saslPassword();
info.useAutoReconnect = useAutoReconnect();
info.autoReconnectInterval = autoReconnectInterval();
info.autoReconnectRetries = autoReconnectRetries();
if(info.useAutoIdentify != useAutoIdentify()) setUseAutoIdentify(info.useAutoIdentify);
if(info.autoIdentifyService != autoIdentifyService()) setAutoIdentifyService(info.autoIdentifyService);
if(info.autoIdentifyPassword != autoIdentifyPassword()) setAutoIdentifyPassword(info.autoIdentifyPassword);
+ if(info.useSasl != useSasl()) setUseSasl(info.useSasl);
+ if(info.saslAccount != saslAccount()) setSaslAccount(info.saslAccount);
+ if(info.saslPassword != saslPassword()) setSaslPassword(info.saslPassword);
if(info.useAutoReconnect != useAutoReconnect()) setUseAutoReconnect(info.useAutoReconnect);
if(info.autoReconnectInterval != autoReconnectInterval()) setAutoReconnectInterval(info.autoReconnectInterval);
if(info.autoReconnectRetries != autoReconnectRetries()) setAutoReconnectRetries(info.autoReconnectRetries);
emit configChanged();
}
+void Network::setUseSasl(bool use) {
+ _useSasl = use;
+ SYNC(ARG(use))
+ emit configChanged();
+}
+
+void Network::setSaslAccount(const QString &account) {
+ _saslAccount = account;
+ SYNC(ARG(account))
+ emit configChanged();
+}
+
+void Network::setSaslPassword(const QString &password) {
+ _saslPassword = password;
+ SYNC(ARG(password))
+ emit configChanged();
+}
+
void Network::setUseAutoReconnect(bool use) {
_useAutoReconnect = use;
SYNC(ARG(use))
useRandomServer(false),
useAutoIdentify(false),
autoIdentifyService("NickServ"),
+ useSasl(false),
useAutoReconnect(true),
autoReconnectInterval(60),
autoReconnectRetries(20),
if(useAutoIdentify != other.useAutoIdentify) return false;
if(autoIdentifyService != other.autoIdentifyService) return false;
if(autoIdentifyPassword != other.autoIdentifyPassword) return false;
+ if(useSasl != other.useSasl) return false;
+ if(saslAccount != other.saslAccount) return false;
+ if(saslPassword != other.saslPassword) return false;
if(useAutoReconnect != other.useAutoReconnect) return false;
if(autoReconnectInterval != other.autoReconnectInterval) return false;
if(autoReconnectRetries != other.autoReconnectRetries) return false;
i["UseAutoIdentify"] = info.useAutoIdentify;
i["AutoIdentifyService"] = info.autoIdentifyService;
i["AutoIdentifyPassword"] = info.autoIdentifyPassword;
+ i["UseSasl"] = info.useSasl;
+ i["SaslAccount"] = info.saslAccount;
+ i["SaslPassword"] = info.saslPassword;
i["UseAutoReconnect"] = info.useAutoReconnect;
i["AutoReconnectInterval"] = info.autoReconnectInterval;
i["AutoReconnectRetries"] = info.autoReconnectRetries;
info.useAutoIdentify = i["UseAutoIdentify"].toBool();
info.autoIdentifyService = i["AutoIdentifyService"].toString();
info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString();
+ info.useSasl = i["UseSasl"].toBool();
+ info.saslAccount = i["SaslAccount"].toString();
+ info.saslPassword = i["SaslPassword"].toString();
info.useAutoReconnect = i["UseAutoReconnect"].toBool();
info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt();
info.autoReconnectRetries = i["AutoReconnectRetries"].toInt();
<< " codecForServer = " << i.codecForServer << " codecForEncoding = " << i.codecForEncoding << " codecForDecoding = " << i.codecForDecoding
<< " serverList = " << i.serverList << " useRandomServer = " << i.useRandomServer << " perform = " << i.perform
<< " useAutoIdentify = " << i.useAutoIdentify << " autoIdentifyService = " << i.autoIdentifyService << " autoIdentifyPassword = " << i.autoIdentifyPassword
- << " useAutoReconnect = " << i.useAutoReconnect << " autoReconnectInterval = " << i.autoReconnectInterval
+ << " useSasl = " << i.useSasl << " saslAccount = " << i.saslAccount << " saslPassword = " << i.saslPassword
+ << " useAutoReconnect = " << i.useAutoReconnect << " autoReconnectInterval = " << i.autoReconnectInterval
<< " autoReconnectRetries = " << i.autoReconnectRetries << " unlimitedReconnectRetries = " << i.unlimitedReconnectRetries
<< " rejoinChannels = " << i.rejoinChannels << ")";
return dbg.space();
Q_PROPERTY(bool useAutoIdentify READ useAutoIdentify WRITE setUseAutoIdentify STORED false)
Q_PROPERTY(QString autoIdentifyService READ autoIdentifyService WRITE setAutoIdentifyService STORED false)
Q_PROPERTY(QString autoIdentifyPassword READ autoIdentifyPassword WRITE setAutoIdentifyPassword STORED false)
+ Q_PROPERTY(bool useSasl READ useSasl WRITE setUseSasl STORED false)
+ Q_PROPERTY(QString saslAccount READ saslAccount WRITE setSaslAccount STORED false)
+ Q_PROPERTY(QString saslPassword READ saslPassword WRITE setSaslPassword STORED false)
Q_PROPERTY(bool useAutoReconnect READ useAutoReconnect WRITE setUseAutoReconnect STORED false)
Q_PROPERTY(quint32 autoReconnectInterval READ autoReconnectInterval WRITE setAutoReconnectInterval STORED false)
Q_PROPERTY(quint16 autoReconnectRetries READ autoReconnectRetries WRITE setAutoReconnectRetries STORED false)
inline bool useAutoIdentify() const { return _useAutoIdentify; }
inline const QString &autoIdentifyService() const { return _autoIdentifyService; }
inline const QString &autoIdentifyPassword() const { return _autoIdentifyPassword; }
+ inline bool useSasl() const { return _useSasl; }
+ inline const QString &saslAccount() const { return _saslAccount; }
+ inline const QString &saslPassword() const { return _saslPassword; }
inline bool useAutoReconnect() const { return _useAutoReconnect; }
inline quint32 autoReconnectInterval() const { return _autoReconnectInterval; }
inline quint16 autoReconnectRetries() const { return _autoReconnectRetries; }
void setUseAutoIdentify(bool);
void setAutoIdentifyService(const QString &);
void setAutoIdentifyPassword(const QString &);
+ void setUseSasl(bool);
+ void setSaslAccount(const QString &);
+ void setSaslPassword(const QString &);
virtual void setUseAutoReconnect(bool);
virtual void setAutoReconnectInterval(quint32);
virtual void setAutoReconnectRetries(quint16);
QString _autoIdentifyService;
QString _autoIdentifyPassword;
+ bool _useSasl;
+ QString _saslAccount;
+ QString _saslPassword;
+
bool _useAutoReconnect;
quint32 _autoReconnectInterval;
quint16 _autoReconnectRetries;
QString autoIdentifyService;
QString autoIdentifyPassword;
+ bool useSasl;
+ QString saslAccount;
+ QString saslPassword;
+
bool useAutoReconnect;
quint32 autoReconnectInterval;
quint16 autoReconnectRetries;
_tokenBucket = _burstSize; // init with a full bucket
_tokenBucketTimer.start(_messageDelay);
+ if(networkInfo().useSasl) {
+ putRawLine(serverEncode(QString("CAP REQ :sasl")));
+ }
if(!server.password.isEmpty()) {
putRawLine(serverEncode(QString("PASS %1").arg(server.password)));
}
QString foo = serverDecode(params.takeFirst());
+ // with SASL, the command is 'AUTHENTICATE +' and we should check for this here.
+ if(foo == QString("AUTHENTICATE +")) {
+ handleAuthenticate();
+ return;
+ }
+
// a colon as the first chars indicates the existence of a prefix
if(foo[0] == ':') {
foo.remove(0, 1);
case 321: case 366: case 376:
break;
+ case 903: case 904: case 905: case 906: case 907:
+ {
+ network()->putRawLine("CAP END");
+ emit displayMsg(Message::Info, BufferInfo::StatusBuffer, "", "CAP: " + params.join(""));
+ }
// Everything else will be marked in red, so we can add them somewhere.
default:
if(_whois) {
emit displayMsg(Message::Topic, BufferInfo::ChannelBuffer, channel->name(), tr("%1 has changed topic for %2 to: \"%3\"").arg(ircuser->nick()).arg(channel->name()).arg(topic));
}
+void IrcServerHandler::handleCap(const QString &prefix, const QList<QByteArray> ¶ms) {
+ // for SASL, there will only be a single param of 'sasl', however you can check here for
+ // additional CAP messages (ls, multi-prefix, et cetera).
+
+ Q_UNUSED(prefix);
+
+ if(params.size() == 3) {
+ QString param = serverDecode(params[2]);
+ if(param == QString("sasl")) { // SASL Ready
+ network()->putRawLine(serverEncode("AUTHENTICATE PLAIN")); // Only working with PLAIN atm, blowfish later
+ }
+ }
+}
+
+void IrcServerHandler::handleAuthenticate() {
+ QString construct = network()->saslAccount();
+ construct.append(QChar(QChar::Null));
+ construct.append(network()->saslAccount());
+ construct.append(QChar(QChar::Null));
+ construct.append(network()->saslPassword());
+ QByteArray saslData = QByteArray(construct.toAscii().toBase64());
+ saslData.prepend(QString("AUTHENTICATE ").toAscii());
+ network()->putRawLine(saslData);
+}
+
/* RPL_WELCOME */
void IrcServerHandler::handle001(const QString &prefix, const QList<QByteArray> ¶ms) {
network()->setCurrentServer(prefix);
void handlePrivmsg(const QString &prefix, const QList<QByteArray> ¶ms);
void handleQuit(const QString &prefix, const QList<QByteArray> ¶ms);
void handleTopic(const QString &prefix, const QList<QByteArray> ¶ms);
-
+ void handleCap(const QString &prefix, const QList<QByteArray> ¶ms); // CAP framework
+ void handleAuthenticate(); // SASL auth - no params
void handle001(const QString &prefix, const QList<QByteArray> ¶ms); // RPL_WELCOME
void handle005(const QString &prefix, const QList<QByteArray> ¶ms); // RPL_ISUPPORT
void handle221(const QString &prefix, const QList<QByteArray> ¶ms); // RPL_UMODEIS
query.bindValue(":useautoidentify", info.useAutoIdentify);
query.bindValue(":autoidentifyservice", info.autoIdentifyService);
query.bindValue(":autoidentifypassword", info.autoIdentifyPassword);
+ query.bindValue(":usesasl", info.useSasl);
+ query.bindValue(":saslaccount", info.saslAccount);
+ query.bindValue(":saslpassword", info.saslPassword);
query.bindValue(":useautoreconnect", info.useAutoReconnect);
query.bindValue(":autoreconnectinterval", info.autoReconnectInterval);
query.bindValue(":autoreconnectretries", info.autoReconnectRetries);
net.autoReconnectRetries = networksQuery.value(13).toInt();
net.unlimitedReconnectRetries = networksQuery.value(14).toBool();
net.rejoinChannels = networksQuery.value(15).toBool();
+ net.useSasl = networksQuery.value(16).toBool();
+ net.saslAccount = networksQuery.value(17).toString();
+ net.saslPassword = networksQuery.value(18).toString();
serversQuery.bindValue(":networkid", net.networkId.toInt());
safeExec(serversQuery);
query.bindValue(":useautoidentify", info.useAutoIdentify ? 1 : 0);
query.bindValue(":autoidentifyservice", info.autoIdentifyService);
query.bindValue(":autoidentifypassword", info.autoIdentifyPassword);
+ query.bindValue(":usesasl", info.useSasl ? 1 : 0);
+ query.bindValue(":saslaccount", info.saslAccount);
+ query.bindValue(":saslpassword", info.saslPassword);
query.bindValue(":useautoreconnect", info.useAutoReconnect ? 1 : 0);
query.bindValue(":autoreconnectinterval", info.autoReconnectInterval);
query.bindValue(":autoreconnectretries", info.autoReconnectRetries);
net.autoReconnectRetries = networksQuery.value(13).toInt();
net.unlimitedReconnectRetries = networksQuery.value(14).toInt() == 1 ? true : false;
net.rejoinChannels = networksQuery.value(15).toInt() == 1 ? true : false;
+ net.useSasl = networksQuery.value(16).toInt() == 1 ? true : false;
+ net.saslAccount = networksQuery.value(17).toString();
+ net.saslPassword = networksQuery.value(18).toString();
serversQuery.bindValue(":networkid", net.networkId.toInt());
safeExec(serversQuery);
connect(ui.autoIdentify, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
connect(ui.autoIdentifyService, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
connect(ui.autoIdentifyPassword, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+ connect(ui.sasl, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+ connect(ui.saslAccount, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged()));
+ connect(ui.saslPassword, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged()));
connect(ui.useCustomEncodings, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
connect(ui.sendEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
connect(ui.recvEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged()));
ui.autoIdentify->setChecked(info.useAutoIdentify);
ui.autoIdentifyService->setText(info.autoIdentifyService);
ui.autoIdentifyPassword->setText(info.autoIdentifyPassword);
+ ui.sasl->setChecked(info.useSasl);
+ ui.saslAccount->setText(info.saslAccount);
+ ui.saslPassword->setText(info.saslPassword);
if(info.codecForEncoding.isEmpty()) {
ui.sendEncoding->setCurrentIndex(ui.sendEncoding->findText(Network::defaultCodecForEncoding()));
ui.recvEncoding->setCurrentIndex(ui.recvEncoding->findText(Network::defaultCodecForDecoding()));
ui.performEdit->clear();
ui.autoIdentifyService->clear();
ui.autoIdentifyPassword->clear();
+ ui.saslAccount->clear();
+ ui.saslPassword->clear();
setWidgetStates();
}
_ignoreWidgetChanges = false;
info.useAutoIdentify = ui.autoIdentify->isChecked();
info.autoIdentifyService = ui.autoIdentifyService->text();
info.autoIdentifyPassword = ui.autoIdentifyPassword->text();
+ info.useSasl = ui.sasl->isChecked();
+ info.saslAccount = ui.saslAccount->text();
+ info.saslPassword = ui.saslPassword->text();
if(!ui.useCustomEncodings->isChecked()) {
info.codecForEncoding.clear();
info.codecForDecoding.clear();
<x>0</x>
<y>0</y>
<width>515</width>
- <height>453</height>
+ <height>503</height>
</rect>
</property>
<property name="windowTitle">
</layout>
</widget>
</item>
+ <item>
+ <widget class="QGroupBox" name="sasl">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="title">
+ <string>Use SASL Authentication</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="saslAccount">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="saslPassword">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_11">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_10">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Account:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<tabstop>reconnectRetries</tabstop>
<tabstop>unlimitedRetries</tabstop>
<tabstop>rejoinOnReconnect</tabstop>
- <tabstop>autoIdentify</tabstop>
<tabstop>autoIdentifyService</tabstop>
<tabstop>autoIdentifyPassword</tabstop>
<tabstop>useCustomEncodings</tabstop>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>173</x>
- <y>296</y>
+ <x>317</x>
+ <y>331</y>
</hint>
<hint type="destinationlabel">
- <x>118</x>
- <y>294</y>
+ <x>209</x>
+ <y>334</y>
</hint>
</hints>
</connection>