~ubuntu-branches/ubuntu/maverick/znc/maverick

« back to all changes in this revision

Viewing changes to IRCSock.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Matthäi
  • Date: 2010-05-24 18:05:44 UTC
  • mfrom: (1.3.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20100524180544-8e4s3f4nj0lhyw7n
Tags: 0.090~rc1-1
* New upstream release candidate.
  - Drop znc-webadmin package. It is now provided in the core source code.
  - Rename discon_kick module to disconkick.
  - Add charset and notes module.
* Add missing dependency on libc-ares-dev to znc-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
 
50
50
        m_pUser->IRCDisconnected();
51
51
 
52
 
        for (map<CString, CChan*>::iterator a = m_msChans.begin(); a != m_msChans.end(); a++) {
 
52
        for (map<CString, CChan*>::iterator a = m_msChans.begin(); a != m_msChans.end(); ++a) {
53
53
                delete a->second;
54
54
        }
55
55
 
63
63
        GetUser()->AddBytesWritten(GetBytesWritten());
64
64
}
65
65
 
66
 
void CIRCSock::Quit() {
67
 
        PutIRC("QUIT :" + m_pUser->GetQuitMsg());
 
66
void CIRCSock::Quit(const CString& sQuitMsg) {
 
67
        CString sMsg = (!sQuitMsg.empty()) ? sQuitMsg : m_pUser->GetQuitMsg();
 
68
        PutIRC("QUIT :" + sMsg);
68
69
        Close(CLT_AFTERWRITE);
69
70
}
70
71
 
105
106
                CString sRest = sLine.Token(3, true);
106
107
 
107
108
                switch (uRaw) {
108
 
                        case 1: {// :irc.server.com 001 nick :Welcome to the Internet Relay Network nick
 
109
                        case 1: { // :irc.server.com 001 nick :Welcome to the Internet Relay Network nick
 
110
                                if (m_bAuthed && sServer == "irc.znc.in") {
 
111
                                        // m_bAuthed == true => we already received another 001 => we might be in a traffic loop
 
112
                                        m_pUser->PutStatus("ZNC seems to be connected to itself, disconnecting...");
 
113
                                        Quit();
 
114
                                        return;
 
115
                                }
 
116
 
109
117
                                m_pUser->SetIRCServer(sServer);
110
 
                                SetTimeout(240, TMO_READ);      // Now that we are connected, let nature take its course
 
118
                                SetTimeout(240, TMO_READ);  // Now that we are connected, let nature take its course
111
119
                                PutIRC("WHO " + sNick);
112
120
 
113
121
                                m_bAuthed = true;
144
152
                        case 2:
145
153
                        case 3:
146
154
                        case 4:
147
 
                        case 250:       // highest connection count
148
 
                        case 251:       // user count
149
 
                        case 252:       // oper count
150
 
                        case 254:       // channel count
151
 
                        case 255:       // client count
152
 
                        case 265:       // local users
153
 
                        case 266:       // global users
 
155
                        case 250:  // highest connection count
 
156
                        case 251:  // user count
 
157
                        case 252:  // oper count
 
158
                        case 254:  // channel count
 
159
                        case 255:  // client count
 
160
                        case 265:  // local users
 
161
                        case 266:  // global users
154
162
                                m_pUser->UpdateRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
155
163
                                break;
156
164
                        case 305:
159
167
                        case 306:
160
168
                                m_pUser->SetIRCAway(true);
161
169
                                break;
162
 
                        case 324: {     // MODE
 
170
                        case 324: {  // MODE
163
171
                                sRest.Trim();
164
172
                                CChan* pChan = m_pUser->FindChan(sRest.Token(0));
165
173
 
239
247
 
240
248
                                break;
241
249
                        }
242
 
                        case 353: {     // NAMES
 
250
                        case 353: {  // NAMES
243
251
                                sRest.Trim();
244
252
                                // Todo: allow for non @+= server msgs
245
253
                                CChan* pChan = m_pUser->FindChan(sRest.Token(1));
259
267
                                // We forwarded it already, so return
260
268
                                return;
261
269
                        }
262
 
                        case 366: {     // end of names list
263
 
                                m_pUser->PutUser(sLine);        // First send them the raw
 
270
                        case 366: {  // end of names list
 
271
                                m_pUser->PutUser(sLine);  // First send them the raw
264
272
 
265
273
                                // :irc.server.com 366 nick #chan :End of /NAMES list.
266
274
                                CChan* pChan = m_pUser->FindChan(sRest.Token(0));
282
290
                                        }
283
291
                                }
284
292
 
285
 
                                return; // return so we don't send them the raw twice
 
293
                                return;  // return so we don't send them the raw twice
286
294
                        }
287
 
                        case 375:       // begin motd
288
 
                        case 422:       // MOTD File is missing
 
295
                        case 375:  // begin motd
 
296
                        case 422:  // MOTD File is missing
289
297
                                m_pUser->ClearMotdBuffer();
290
 
                        case 372:       // motd
291
 
                        case 376:       // end motd
 
298
                        case 372:  // motd
 
299
                        case 376:  // end motd
292
300
                                m_pUser->AddMotdBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
293
301
                                break;
294
302
                        case 437:
377
385
 
378
386
                        if (Nick.GetNick().Equals(GetNick())) {
379
387
                                m_pUser->PutStatus("You quit [" + sMessage + "]");
 
388
                                // We don't call module hooks and we don't
 
389
                                // forward this quit to clients (Some clients
 
390
                                // disconnect if they receive such a QUIT)
 
391
                                return;
380
392
                        }
381
393
 
382
394
                        vector<CChan*> vFoundChans;
475
487
                                }
476
488
                        } else if (sTarget == m_Nick.GetNick()) {
477
489
                                CString sModeArg = sModes.Token(0);
478
 
//                                      CString sArgs = sModes.Token(1, true); Usermode changes got no params
479
490
                                bool bAdd = true;
480
491
/* no module call defined (yet?)
481
492
                                MODULECALL(OnRawUserMode(*pOpNick, *this, sModeArg, sArgs), m_pUser, NULL, );
627
638
                        if (!m_pUser->IsUserAttached()) {
628
639
                                m_pUser->AddQueryBuffer(":" + Nick.GetNickMask() + " WALLOPS ", ":" + m_pUser->AddTimestamp(sMsg), false);
629
640
                        }
 
641
                } else if (sCmd.Equals("CAP")) {
 
642
                        // sRest.Token(0) is most likely "*". No idea why, the
 
643
                        // CAP spec don't mention this, but all implementations
 
644
                        // I've seen add this extra asterisk
 
645
                        CString sSubCmd = sRest.Token(1);
 
646
                        CString sArgs = sRest.Token(2, true).TrimPrefix_n(":");
 
647
 
 
648
                        if (sSubCmd == "LS" && !m_bAuthed) {
 
649
                                VCString vsTokens;
 
650
                                VCString::iterator it;
 
651
                                sArgs.Split(" ", vsTokens, false);
 
652
 
 
653
                                for (it = vsTokens.begin(); it != vsTokens.end(); ++it) {
 
654
                                        if (*it == "multi-prefix" || *it == "userhost-in-names") {
 
655
                                                PutIRC("CAP REQ " + *it);
 
656
                                        }
 
657
                                }
 
658
 
 
659
                                // Tell the IRC server we are done with CAP
 
660
                                PutIRC("CAP END");
 
661
                        } else if (sSubCmd == "ACK" && !m_bAuthed) {
 
662
                                VCString vsTokens;
 
663
                                VCString::iterator it;
 
664
                                sArgs.Split(" ", vsTokens, false);
 
665
 
 
666
                                for (it = vsTokens.begin(); it != vsTokens.end(); ++it) {
 
667
                                        if (*it == "multi-prefix") {
 
668
                                                m_bNamesx = true;
 
669
                                        } else if (*it == "userhost-in-names") {
 
670
                                                m_bUHNames = true;
 
671
                                        }
 
672
                                }
 
673
                        }
630
674
                }
631
675
        }
632
676
 
826
870
 
827
871
        MODULECALL(OnIRCRegistration(sPass, sNick, sIdent, sRealName), m_pUser, NULL, return);
828
872
 
 
873
        PutIRC("CAP LS");
 
874
 
829
875
        if (!sPass.empty()) {
830
876
                PutIRC("PASS " + sPass);
831
877
        }
854
900
        // otherwise, on reconnect, it might think it still
855
901
        // had user modes that it actually doesn't have.
856
902
        CString sUserMode;
857
 
        for (set<unsigned char>::const_iterator it = m_scUserModes.begin(); it != m_scUserModes.end(); it++) {
 
903
        for (set<unsigned char>::const_iterator it = m_scUserModes.begin(); it != m_scUserModes.end(); ++it) {
858
904
                sUserMode += *it;
859
905
        }
860
906
        if (!sUserMode.empty()) {
927
973
}
928
974
 
929
975
void CIRCSock::ParseISupport(const CString& sLine) {
930
 
        unsigned int i = 0;
931
 
        CString sArg = sLine.Token(i++);
932
 
 
933
 
        while (!sArg.empty()) {
934
 
                CString sName = sArg.Token(0, false, "=");
935
 
                CString sValue = sArg.Token(1, true, "=");
 
976
        VCString vsTokens;
 
977
        VCString::iterator it;
 
978
 
 
979
        sLine.Split(" ", vsTokens, false);
 
980
 
 
981
        for (it = vsTokens.begin(); it != vsTokens.end(); ++it) {
 
982
                CString sName = it->Token(0, false, "=");
 
983
                CString sValue = it->Token(1, true, "=");
936
984
 
937
985
                if (sName.Equals("PREFIX")) {
938
986
                        CString sPrefixes = sValue.Token(1, false, ")");
964
1012
                                }
965
1013
                        }
966
1014
                } else if (sName.Equals("NAMESX")) {
 
1015
                        if (m_bNamesx)
 
1016
                                continue;
967
1017
                        m_bNamesx = true;
968
1018
                        PutIRC("PROTOCTL NAMESX");
969
1019
                } else if (sName.Equals("UHNAMES")) {
 
1020
                        if (m_bUHNames)
 
1021
                                continue;
970
1022
                        m_bUHNames = true;
971
1023
                        PutIRC("PROTOCTL UHNAMES");
972
1024
                }
973
 
 
974
 
                sArg = sLine.Token(i++);
975
1025
        }
976
1026
}
977
1027
 
978
1028
void CIRCSock::ForwardRaw353(const CString& sLine) const {
979
1029
        vector<CClient*>& vClients = m_pUser->GetClients();
 
1030
        vector<CClient*>::iterator it;
 
1031
 
 
1032
        for (it = vClients.begin(); it != vClients.end(); ++it) {
 
1033
                ForwardRaw353(sLine, *it);
 
1034
        }
 
1035
}
 
1036
 
 
1037
void CIRCSock::ForwardRaw353(const CString& sLine, CClient* pClient) const {
980
1038
        CString sNicks = sLine.Token(5, true);
981
1039
        if (sNicks.Left(1) == ":")
982
1040
                sNicks.LeftChomp();
983
1041
 
984
 
        for (unsigned int a = 0; a < vClients.size(); a++) {
985
 
                if ((!m_bNamesx || vClients[a]->HasNamesx()) && (!m_bUHNames || vClients[a]->HasUHNames())) {
986
 
                        // Client and server have both the same UHNames and Namesx stuff enabled
987
 
                        m_pUser->PutUser(sLine, vClients[a]);
988
 
                } else {
989
 
                        // Get everything except the actual user list
990
 
                        CString sTmp = sLine.Token(0, false, " :") + " :";
991
 
 
992
 
                        unsigned int i = 0;
993
 
                        // This loop runs once for every nick on the channel
994
 
                        for (;;) {
995
 
                                CString sNick = sNicks.Token(i).Trim_n(" ");
996
 
                                if (sNick.empty())
997
 
                                        break;
998
 
 
999
 
                                if (m_bNamesx && !vClients[a]->HasNamesx() && IsPermChar(sNick[0])) {
1000
 
                                        // Server has, client doesn't have NAMESX, so we just use the first perm char
1001
 
                                        size_t pos = sNick.find_first_not_of(GetPerms());
1002
 
                                        if (pos >= 2 && pos != CString::npos) {
1003
 
                                                sNick = sNick[0] + sNick.substr(pos);
1004
 
                                        }
1005
 
                                }
1006
 
 
1007
 
                                if (m_bUHNames && !vClients[a]->HasUHNames()) {
1008
 
                                        // Server has, client hasnt UHNAMES,
1009
 
                                        // so we strip away ident and host.
1010
 
                                        sNick = sNick.Token(0, false, "!");
1011
 
                                }
1012
 
 
1013
 
                                sTmp += sNick + " ";
1014
 
                                i++;
1015
 
                        }
1016
 
                        // Strip away the spaces we inserted at the end
1017
 
                        sTmp.TrimRight(" ");
1018
 
                        m_pUser->PutUser(sTmp, vClients[a]);
 
1042
        if ((!m_bNamesx || pClient->HasNamesx()) && (!m_bUHNames || pClient->HasUHNames())) {
 
1043
                // Client and server have both the same UHNames and Namesx stuff enabled
 
1044
                m_pUser->PutUser(sLine, pClient);
 
1045
        } else {
 
1046
                // Get everything except the actual user list
 
1047
                CString sTmp = sLine.Token(0, false, " :") + " :";
 
1048
 
 
1049
                VCString vsNicks;
 
1050
                VCString::const_iterator it;
 
1051
 
 
1052
                // This loop runs once for every nick on the channel
 
1053
                sNicks.Split(" ", vsNicks, false);
 
1054
                for (it = vsNicks.begin(); it != vsNicks.end(); ++it) {
 
1055
                        CString sNick = *it;
 
1056
                        if (sNick.empty())
 
1057
                                break;
 
1058
 
 
1059
                        if (m_bNamesx && !pClient->HasNamesx() && IsPermChar(sNick[0])) {
 
1060
                                // Server has, client doesn't have NAMESX, so we just use the first perm char
 
1061
                                size_t pos = sNick.find_first_not_of(GetPerms());
 
1062
                                if (pos >= 2 && pos != CString::npos) {
 
1063
                                        sNick = sNick[0] + sNick.substr(pos);
 
1064
                                }
 
1065
                        }
 
1066
 
 
1067
                        if (m_bUHNames && !pClient->HasUHNames()) {
 
1068
                                // Server has, client hasnt UHNAMES,
 
1069
                                // so we strip away ident and host.
 
1070
                                sNick = sNick.Token(0, false, "!");
 
1071
                        }
 
1072
 
 
1073
                        sTmp += sNick + " ";
1019
1074
                }
 
1075
                // Strip away the spaces we inserted at the end
 
1076
                sTmp.TrimRight(" ");
 
1077
                m_pUser->PutUser(sTmp, pClient);
1020
1078
        }
1021
1079
}
1022
1080
 
1094
1152
}
1095
1153
 
1096
1154
void CIRCSock::ResetChans() {
1097
 
        for (map<CString, CChan*>::iterator a = m_msChans.begin(); a != m_msChans.end(); a++) {
 
1155
        for (map<CString, CChan*>::iterator a = m_msChans.begin(); a != m_msChans.end(); ++a) {
1098
1156
                a->second->Reset();
1099
1157
        }
1100
1158
}