1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
#include "ircpeer.h"
#include <QRegExp>
IRCSerializer::IRCSerializer() : QxtAbstractSignalSerializer() {
qRegisterMetaType<IRCName>();
}
bool IRCSerializer::canDeserialize(const QByteArray& buffer) const {
return buffer.indexOf('\n') != -1 || buffer.indexOf('\r') != -1;
}
static bool serializeParam(QTextStream& str, QVariant p) {
if(!p.isValid() || !p.canConvert(QVariant::ByteArray)) {
str << "\r\n" << flush;
return true;
}
QByteArray ba = p.toByteArray();
if(ba.contains(' ') || ba[0] == ':')
{
str << " :" << ba << "\r\n" << flush;
return true;
}
str << " " << ba << flush;
return false;
}
QByteArray IRCSerializer::serialize(const QString& fn, const QVariant& p1, const QVariant& p2, const QVariant& p3,
const QVariant& p4, const QVariant& p5, const QVariant& p6, const QVariant& p7, const QVariant& p8) const {
if(fn == "raw") return p1.toString().toUtf8() + "\r\n";
QByteArray rv;
QTextStream str(&rv);
if(p1.isValid()) {
if(p1.canConvert<IRCName>()) {
QByteArray name = p1.value<IRCName>().assemble();
if(!name.isEmpty())
str << ":" << p1.value<IRCName>().assemble() << " ";
} else if(!p1.toByteArray().isEmpty()) {
str << ":" << p1.toByteArray() << " ";
}
}
str << fn << flush;
if(serializeParam(str, p2)) return rv;
if(serializeParam(str, p3)) return rv;
if(serializeParam(str, p4)) return rv;
if(serializeParam(str, p5)) return rv;
if(serializeParam(str, p6)) return rv;
if(serializeParam(str, p7)) return rv;
if(serializeParam(str, p8)) return rv;
return rv + "\r\n";
}
QPair<QString, QList<QVariant> > IRCSerializer::deserialize(QByteArray& data) {
int lfPos = data.indexOf('\n'), crPos = data.indexOf('\r'), wordPos = 0, endPos = (crPos == -1 || lfPos < crPos) ? lfPos : crPos;
QByteArray message = data.left(endPos).trimmed(), prefix;
data = data.mid(endPos+1);
if(message.isEmpty()) return qMakePair(QString(), QList<QVariant>());
QList<QByteArray> words = message.split(' ');
if(words[0][0] == ':') {
prefix = words[0].mid(1);
while(wordPos < words.count() && words[wordPos++].isEmpty())
return qMakePair(QString(), QList<QVariant>() << QVariant());
}
QString command(words[wordPos]);
QList<QVariant> params;
int cmdNum = command.toInt();
if(cmdNum != 0) {
params << QVariant::fromValue(IRCName((prefix + ':' + command).toUtf8(), "", prefix));
command = "numeric";
} else {
if(prefix.isEmpty()) params << QVariant::fromValue(IRCName("","",""));
else if(prefix.contains('@')) params << QVariant::fromValue(IRCName::fromName(prefix));
else params << QVariant::fromValue(IRCName(prefix, prefix, prefix));
}
while(wordPos++ < words.count()-1) {
if(words[wordPos].isEmpty()) continue;
if(words[wordPos][0] == ':') {
QByteArray trailing = words[wordPos++].mid(1);
while(wordPos < words.count())
trailing = trailing + ' ' + words[wordPos++];
params << trailing;
break;
}
params << words[wordPos];
}
if(command == "numeric") {
params.removeAt(1); // always your own nick
while(params[1].toByteArray() == "=" || params[1].toByteArray() == "@")
params.removeAt(1); // nothing important
if(params.size() == 2) {
params.push_front(QByteArray()); // make it show up in the system window
params.swap(0, 1);
} else if(cmdNum < 300 || params.size() > 3) { // some numeric responses aren't a single string
QList<QVariant> newparams;
newparams << params[0];
int i;
if(cmdNum < 300) {
newparams << QByteArray();
i = 1;
} else {
newparams << params[1];
i = 2;
}
QByteArray ba;
for(; i < params.count(); i++) ba += params[i].toByteArray() + ' ';
newparams << ba;
params = newparams;
}
} else if(command == "PRIVMSG") {
QByteArray p2 = params[2].toByteArray();
if(p2.size() > 0 && p2[0] == '\001') {
message = p2.replace("\001", "");
int spacePos = message.indexOf(' ');
if(spacePos == -1) spacePos = message.size();
command = "CTCP-"+message.left(spacePos);
params[2] = message.mid(spacePos);
}
} else if(command == "NOTICE" && params[0].isNull()) {
params[0] = QVariant::fromValue(IRCName(params[1].toByteArray(), "", params[1].toByteArray()));
}
return qMakePair(command, params);
}
IRCName IRCName::fromName(const QByteArray& name) {
QRegExp re("([^@!]*)(?:!([^@]*)?)(?:@(.*))?");
re.exactMatch(QString::fromUtf8(name.data()));
return IRCName(re.cap(1).toUtf8(), re.cap(2).toUtf8(), re.cap(3).toUtf8());
}
IRCName::IRCName(QByteArray nick, QByteArray ident, QByteArray host) : nick(nick), ident(ident), host(host) {}
QByteArray IRCName::assemble() const {
return nick + (ident.isEmpty() ? QByteArray() : '!' + ident) + (host.isEmpty() ? QByteArray() : '@' + host);
}
|