File: ircpeer.cpp

package info (click to toggle)
libqxt 0.6.2-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 19,000 kB
  • ctags: 6,583
  • sloc: cpp: 57,582; xml: 296; sh: 256; makefile: 60; php: 14
file content (140 lines) | stat: -rw-r--r-- 5,424 bytes parent folder | download | duplicates (3)
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);
}