~vcs-imports-ii/znc/master

« back to all changes in this revision

Viewing changes to IRCSock.cpp

  • Committer: prozacx
  • Date: 2004-08-24 00:08:51 UTC
  • Revision ID: git-v1:538d3ece4e737807e7d5a11849aab177b87c1571
Initial revision


git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@2 726aef4b-f618-498e-8847-2d620e286838

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "znc.h"
 
2
#include "IRCSock.h"
 
3
#include "DCCBounce.h"
 
4
#include "UserSock.h"
 
5
 
 
6
CIRCSock::CIRCSock(CZNC* pZNC, CUser* pUser) : Csock() {
 
7
        m_pZNC = pZNC;
 
8
        m_pUser = pUser;
 
9
        m_pUserSock = NULL;
 
10
        m_uQueryBufferCount = 50;
 
11
        m_bISpoofReleased = false;
 
12
        m_bKeepNick = true;
 
13
        m_bAuthed = false;
 
14
        EnableReadLine();
 
15
        m_RawBuffer.SetLineCount(100);  // This should be more than enough raws, especially since we are asking the server to resend MOTD
 
16
        m_Nick.SetIdent(pUser->GetIdent());
 
17
        m_Nick.SetHost(pUser->GetVHost());
 
18
}
 
19
 
 
20
CIRCSock::~CIRCSock() {
 
21
        for (map<string, CChan*>::iterator a = m_msChans.begin(); a != m_msChans.end(); a++) {
 
22
                delete a->second;
 
23
        }
 
24
 
 
25
        if (!m_bISpoofReleased) {
 
26
                m_pZNC->ReleaseISpoof();
 
27
        }
 
28
 
 
29
        PutServ("QUIT :");
 
30
        m_msChans.clear();
 
31
}
 
32
 
 
33
void CIRCSock::ReadLine(const string& sData) {
 
34
        string sLine = sData;
 
35
 
 
36
        while ((CUtils::Right(sLine, 1) == "\r") || (CUtils::Right(sLine, 1) == "\n")) {
 
37
                CUtils::RightChomp(sLine);
 
38
        }
 
39
 
 
40
        DEBUG_ONLY(cout << GetSockName() << " <- [" << sLine << "]" << endl);
 
41
 
 
42
#ifdef _MODULES
 
43
        if (m_pUser->GetModules().OnRaw(sLine)) {
 
44
                return;
 
45
        }
 
46
#endif
 
47
 
 
48
        if (strncasecmp(sLine.c_str(), "PING ", 5) == 0) {
 
49
                PutServ("PONG " + sLine.substr(5));
 
50
        } else if (CUtils::WildCmp(":* * *", sLine.c_str())) { //"^:(\\S+) (\\d\\d\\d) (.*?) (.*)$", vCap)) {
 
51
                string sCmd = CUtils::Token(sLine, 1);
 
52
 
 
53
                if ((sCmd.length() == 3) && (isdigit(sCmd[0])) && (isdigit(sCmd[1])) && (isdigit(sCmd[2]))) {
 
54
                        string sServer = CUtils::Token(sLine, 0); CUtils::LeftChomp(sServer);
 
55
                        unsigned int uRaw = strtoul(sCmd.c_str(), NULL, 10);
 
56
                        string sNick = CUtils::Token(sLine, 2);
 
57
                        string sRest = CUtils::Token(sLine, 3, true);
 
58
 
 
59
                        switch (uRaw) {
 
60
                                case 1: {// :irc.server.com 001 nick :Welcome to the Internet Relay Network nick
 
61
                                        SetTimeout(900);        // Now that we are connected, let nature take its course
 
62
                                        PutServ("WHO " + sNick);
 
63
#ifdef _MODULES
 
64
                                        m_pUser->GetModules().OnIRCConnected();
 
65
#endif
 
66
                                        m_bAuthed = true;
 
67
                                        m_pUser->PutStatus("Connected!");
 
68
 
 
69
                                        if (m_pUserSock) {
 
70
                                                string sClientNick = m_pUserSock->GetNick();
 
71
                                                if (strcasecmp(sClientNick.c_str(), sNick.c_str()) != 0) {
 
72
                                                        // If they connected with a nick that doesn't match the one we got on irc, then we need to update them
 
73
                                                        PutUser(":" + sClientNick + "!" + m_Nick.GetIdent() + "@" + m_Nick.GetHost() + " NICK :" + sNick);
 
74
                                                }
 
75
                                        }
 
76
 
 
77
                                        SetNick(sNick);
 
78
 
 
79
                                        m_RawBuffer.Clear();
 
80
                                        m_RawBuffer.AddLine(":" + sServer + " " + sCmd + " ", " " + sRest);
 
81
 
 
82
                                        // Now that we are connected, we need to join our chans
 
83
                                        const vector<CChan*>& vChans = m_pUser->GetChans();
 
84
 
 
85
                                        for (unsigned int a = 0; a < vChans.size(); a++) {
 
86
                                                PutServ("JOIN " + vChans[a]->GetName() + " " + vChans[a]->GetKey());
 
87
                                        }
 
88
 
 
89
                                        m_pZNC->ReleaseISpoof();
 
90
                                        m_bISpoofReleased = true;
 
91
 
 
92
                                        break;
 
93
                                }
 
94
                                case 2:
 
95
                                case 3:
 
96
                                case 4:
 
97
                                case 5:
 
98
                                case 250:       // highest connection count
 
99
                                case 251:       // user count
 
100
                                case 252:       // oper count
 
101
                                case 254:       // channel count
 
102
                                case 255:       // client count
 
103
                                case 265:       // local users
 
104
                                case 266:       // global users
 
105
                                        m_RawBuffer.AddLine(":" + sServer + " " + sCmd + " ", " " + sRest);
 
106
                                        break;
 
107
                                case 372:       // motd
 
108
                                case 375:       // begin motd
 
109
                                case 376:       // end motd
 
110
                                        break;
 
111
                                case 471: // :irc.server.net 471 nick #chan :Cannot join channel (+l)
 
112
                                case 473: // :irc.server.net 473 nick #chan :Cannot join channel (+i)
 
113
                                case 475: // :irc.server.net 475 nick #chan :Cannot join channel (+k)
 
114
                                        if (m_pUserSock) {
 
115
                                                CChan* pChan = m_pUser->FindChan(sRest.substr(0, sRest.find(' ')));
 
116
 
 
117
                                                if ((pChan) && (!pChan->IsOn())) {
 
118
                                                        if (!pChan->DecClientRequests()) {
 
119
                                                                return;
 
120
                                                        }
 
121
                                                }
 
122
                                        }
 
123
 
 
124
                                        break;
 
125
                                case 433: {
 
126
                                        string sBadNick = CUtils::Token(sRest, 0);
 
127
                                        string sConfNick = m_pUser->GetNick();
 
128
 
 
129
                                        if (sNick == "*") {
 
130
                                                string sAltNick = m_pUser->GetAltNick();
 
131
 
 
132
                                                if (strcasecmp(sBadNick.c_str(), sConfNick.c_str()) == 0) {
 
133
                                                        if ((!sAltNick.empty()) && (strcasecmp(sConfNick.c_str(), sAltNick.c_str()) != 0)) {
 
134
                                                                PutServ("NICK " + sAltNick);
 
135
                                                        } else {
 
136
                                                                PutServ("NICK " + CUtils::Left(sConfNick, 8) + "-");
 
137
                                                        }
 
138
                                                } else if (strcasecmp(sBadNick.c_str(), sAltNick.c_str()) == 0) {
 
139
                                                        PutServ("NICK " + CUtils::Left(sConfNick, 8) + "-");
 
140
                                                } else if (strcasecmp(sBadNick.c_str(), string(CUtils::Left(sConfNick, 8) + "-").c_str()) == 0) {
 
141
                                                        PutServ("NICK " + CUtils::Left(sConfNick, 8) + "|");
 
142
                                                } else if (strcasecmp(sBadNick.c_str(), string(CUtils::Left(sConfNick, 8) + "|").c_str()) == 0) {
 
143
                                                        PutServ("NICK " + CUtils::Left(sConfNick, 8) + "^");
 
144
                                                } else {
 
145
                                                        char cLetter = 0;
 
146
                                                        if (sBadNick.empty()) {
 
147
                                                                        Close();
 
148
                                                                        return;
 
149
                                                        }
 
150
 
 
151
                                                        cLetter = CUtils::Right(sBadNick, 1)[0];
 
152
 
 
153
                                                        if (cLetter == 'z') {
 
154
                                                                Close();
 
155
                                                                return;
 
156
                                                        }
 
157
 
 
158
                                                        string sSend = "NICK " + CUtils::Left(sConfNick, 8) + cLetter++;
 
159
                                                        PutServ(sSend);
 
160
                                                }
 
161
 
 
162
                                                return;
 
163
                                        } else {
 
164
                                                // :irc.server.net 433 mynick badnick :Nickname is already in use.
 
165
                                                if ((m_bKeepNick) && (m_pUser->KeepNick())) {
 
166
                                                        if (strcasecmp(sBadNick.c_str(), sConfNick.c_str()) == 0) {
 
167
                                                                if ((!m_pUserSock) || (!m_pUserSock->DecKeepNickCounter())) {
 
168
                                                                        return;
 
169
                                                                }
 
170
                                                        }
 
171
                                                }
 
172
                                        }
 
173
                                        break;
 
174
                                }
 
175
                                case 315: {
 
176
                                        // :irc.server.com 315 yournick #chan :End of /WHO list.
 
177
                                        CChan* pChan = m_pUser->FindChan(CUtils::Token(sLine, 3));
 
178
 
 
179
                                        if (pChan) {
 
180
                                                pChan->SetWhoDone();
 
181
                                        }
 
182
                                }
 
183
                                case 352: {
 
184
                                        // :irc.yourserver.com 352 yournick #chan ident theirhost.com irc.theirserver.com theirnick H :0 Real Name
 
185
                                        string sNick = CUtils::Token(sLine, 7);
 
186
                                        string sIdent = CUtils::Token(sLine, 4);
 
187
                                        string sHost = CUtils::Token(sLine, 5);
 
188
 
 
189
                                        if (strcasecmp(sNick.c_str(), GetNick().c_str()) == 0) {
 
190
                                                m_Nick.SetIdent(sIdent);
 
191
                                                m_Nick.SetHost(sHost);
 
192
                                        }
 
193
 
 
194
                                        const vector<CChan*>& vChans = m_pUser->GetChans();
 
195
 
 
196
                                        for (unsigned int a = 0; a < vChans.size(); a++) {
 
197
                                                vChans[a]->OnWho(sNick, sIdent, sHost);
 
198
                                        }
 
199
 
 
200
                                        break;
 
201
                                }
 
202
                                case 324: {     // MODE
 
203
                                        CUtils::Trim(sRest);
 
204
                                        CChan* pChan = m_pUser->FindChan(CUtils::Token(sRest, 0));
 
205
 
 
206
                                        if (pChan) {
 
207
                                                pChan->SetModes(CUtils::Token(sRest, 1, true));
 
208
                                        }
 
209
                                }
 
210
                                        break;
 
211
                                case 353: {     // NAMES
 
212
                                        CUtils::Trim(sRest);
 
213
                                        // Todo: allow for non @+= server msgs
 
214
                                        CChan* pChan = m_pUser->FindChan(CUtils::Token(sRest, 1));
 
215
                                        if (pChan) {
 
216
                                                string sNicks = CUtils::Token(sRest, 2, true);
 
217
                                                if (CUtils::Left(sNicks, 1) == ":") {
 
218
                                                        CUtils::LeftChomp(sNicks);
 
219
                                                }
 
220
 
 
221
                                                pChan->AddNicks(sNicks);
 
222
                                        }
 
223
                                }
 
224
                                        break;
 
225
                                case 366: {     // end of names list
 
226
                                        PutUser(sLine); // First send them the raw
 
227
 
 
228
                                        // :irc.server.com 366 nick #chan :End of /NAMES list.
 
229
                                        CChan* pChan = m_pUser->FindChan(CUtils::Token(sRest, 0));
 
230
 
 
231
                                        if (pChan) {
 
232
                                                if (IsUserAttached()) {
 
233
                                                        const vector<string>& vsBuffer = pChan->GetBuffer();
 
234
 
 
235
                                                        if (vsBuffer.size()) {
 
236
                                                                PutUser(":***!znc@znc.com PRIVMSG " + pChan->GetName() + " :Buffer Playback...");
 
237
 
 
238
                                                                for (unsigned int a = 0; a < vsBuffer.size(); a++) {
 
239
                                                                        PutUser(vsBuffer[a]);
 
240
                                                                }
 
241
 
 
242
                                                                if (!pChan->KeepBuffer()) {
 
243
                                                                        pChan->ClearBuffer();
 
244
                                                                }
 
245
 
 
246
                                                                PutUser(":***!znc@znc.com PRIVMSG " + pChan->GetName() + " :Playback Complete.");
 
247
                                                        }
 
248
                                                }
 
249
 
 
250
                                                if (!pChan->IsOn()) {
 
251
                                                        pChan->SetIsOn(true);
 
252
                                                        PutServ("MODE " + pChan->GetName());
 
253
 
 
254
                                                        // If we are the only one in the chan, set our default modes
 
255
                                                        if (pChan->GetNickCount() == 1) {
 
256
                                                                string sModes = pChan->GetDefaultModes();
 
257
 
 
258
                                                                if (sModes.empty()) {
 
259
                                                                        sModes = m_pUser->GetDefaultChanModes();
 
260
                                                                }
 
261
 
 
262
                                                                if (!sModes.empty()) {
 
263
                                                                        PutServ("MODE " + pChan->GetName() + " " + sModes);
 
264
                                                                }
 
265
                                                        }
 
266
                                                }
 
267
                                        }
 
268
 
 
269
                                        return; // return so we don't send them the raw twice
 
270
                                }
 
271
                        }
 
272
                } else { //if (CUtils::WildCmp(":*!*@* * *", sLine.c_str())) {
 
273
                        string sNickMask = CUtils::Token(sLine, 0);
 
274
                        CUtils::LeftChomp(sNickMask);
 
275
 
 
276
                        string sNick = CUtils::Token(sNickMask, 0, false, '!');
 
277
                        string sCmd = CUtils::Token(sLine, 1);
 
278
                        string sRest = CUtils::Token(sLine, 2, true);
 
279
 
 
280
                        if (strcasecmp(sCmd.c_str(), "NICK") == 0) {
 
281
                                string sNewNick = sRest;
 
282
                                if (CUtils::Left(sNewNick, 1) == ":") {
 
283
                                        CUtils::LeftChomp(sNewNick);
 
284
                                }
 
285
 
 
286
                                const vector<CChan*>& vChans = m_pUser->GetChans();
 
287
                                for (unsigned int a = 0; a < vChans.size(); a++) {
 
288
                                        vChans[a]->ChangeNick(sNick, sNewNick);
 
289
                                }
 
290
 
 
291
                                if (strcasecmp(sNick.c_str(), GetNick().c_str()) == 0) {
 
292
                                        SetNick(sNewNick);
 
293
                                        if (strcasecmp(sNick.c_str(), m_pUser->GetNick().c_str()) == 0) {
 
294
                                                // If the user changes his nick away from the config nick, we shut off keepnick for this session
 
295
                                                m_bKeepNick = false;
 
296
                                        }
 
297
                                } else if (strcasecmp(sNick.c_str(), m_pUser->GetNick().c_str()) == 0) {
 
298
                                        KeepNick();
 
299
                                }
 
300
#ifdef _MODULES
 
301
                                m_pUser->GetModules().OnNick(sNickMask, sNewNick);
 
302
#endif
 
303
                        } else if (strcasecmp(sCmd.c_str(), "QUIT") == 0) {
 
304
                                string sChan = sRest;
 
305
                                if (CUtils::Left(sChan, 1) == ":") {
 
306
                                        CUtils::LeftChomp(sChan);
 
307
                                }
 
308
 
 
309
                                // :nick!ident@host.com QUIT :message
 
310
                                CNick Nick(sNickMask);
 
311
 
 
312
                                const vector<CChan*>& vChans = m_pUser->GetChans();
 
313
                                for (unsigned int a = 0; a < vChans.size(); a++) {
 
314
                                        vChans[a]->RemNick(sNick);
 
315
                                }
 
316
 
 
317
                                if (strcasecmp(Nick.GetNick().c_str(), m_pUser->GetNick().c_str()) == 0) {
 
318
                                        KeepNick();
 
319
                                }
 
320
 
 
321
#ifdef _MODULES
 
322
                                m_pUser->GetModules().OnQuit(Nick, sChan);
 
323
#endif
 
324
                        } else if (strcasecmp(sCmd.c_str(), "JOIN") == 0) {
 
325
                                string sChan = sRest;
 
326
                                if (CUtils::Left(sChan, 1) == ":") {
 
327
                                        CUtils::LeftChomp(sChan);
 
328
                                }
 
329
 
 
330
                                if (strcasecmp(sNick.c_str(), GetNick().c_str()) == 0) {
 
331
                                        m_pUser->AddChan(sChan);
 
332
                                }
 
333
 
 
334
                                CChan* pChan = m_pUser->FindChan(sChan);
 
335
                                if (pChan) {
 
336
                                        pChan->AddNick(sNickMask);
 
337
#ifdef _MODULES
 
338
                                        m_pUser->GetModules().OnJoin(sNickMask, *pChan);
 
339
#endif
 
340
                                }
 
341
                        } else if (strcasecmp(sCmd.c_str(), "PART") == 0) {
 
342
                                string sChan = sRest;
 
343
                                if (CUtils::Left(sChan, 1) == ":") {
 
344
                                        CUtils::LeftChomp(sChan);
 
345
                                }
 
346
 
 
347
                                CChan* pChan = m_pUser->FindChan(sChan);
 
348
                                if (pChan) {
 
349
                                        pChan->RemNick(sNick);
 
350
#ifdef _MODULES
 
351
                                        m_pUser->GetModules().OnPart(sNickMask, *pChan);
 
352
#endif
 
353
                                }
 
354
 
 
355
                                if (strcasecmp(sNick.c_str(), GetNick().c_str()) == 0) {
 
356
                                        m_pUser->DelChan(sChan);
 
357
                                }
 
358
                        } else if (strcasecmp(sCmd.c_str(), "MODE") == 0) {
 
359
                                string sChan = CUtils::Token(sRest, 0);
 
360
                                string sModes = CUtils::Token(sRest, 1, true);
 
361
 
 
362
                                CChan* pChan = m_pUser->FindChan(sChan);
 
363
                                if (pChan) {
 
364
                                        pChan->ModeChange(sModes, sNick);
 
365
                                }
 
366
                        } else if (strcasecmp(sCmd.c_str(), "KICK") == 0) {
 
367
                                // :opnick!ident@host.com KICK #chan nick :msg
 
368
                                string sChan = CUtils::Token(sRest, 0);
 
369
                                string sKickedNick = CUtils::Token(sRest, 1);
 
370
                                string sMsg = CUtils::Token(sRest, 2, true);
 
371
                                CUtils::LeftChomp(sMsg);
 
372
 
 
373
                                CChan* pChan = m_pUser->FindChan(sChan);
 
374
 
 
375
                                if (pChan) {
 
376
                                        pChan->RemNick(sKickedNick);
 
377
#ifdef _MODULES
 
378
                                        m_pUser->GetModules().OnKick(sNickMask, sKickedNick, *pChan, sMsg);
 
379
#endif
 
380
                                }
 
381
 
 
382
                                if (strcasecmp(GetNick().c_str(), sKickedNick.c_str()) == 0) {
 
383
                                        string sKey;
 
384
 
 
385
                                        if (pChan) {
 
386
                                                sKey = pChan->GetKey();
 
387
                                                pChan->SetIsOn(false);
 
388
                                        }
 
389
 
 
390
                                        PutServ("JOIN " + sChan + " " + sKey);
 
391
                                }
 
392
                        } else if (strcasecmp(sCmd.c_str(), "NOTICE") == 0) {
 
393
                                // :nick!ident@host.com NOTICE #chan :Message
 
394
 
 
395
                                CNick Nick(sNickMask);
 
396
 
 
397
                                string sTarget = CUtils::Token(sRest, 0);
 
398
                                string sMsg = CUtils::Token(sRest, 1, true);
 
399
                                CUtils::LeftChomp(sMsg);
 
400
 
 
401
                                if (CUtils::WildCmp("\001*\001", sMsg.c_str())) {
 
402
                                        CUtils::LeftChomp(sMsg);
 
403
                                        CUtils::RightChomp(sMsg);
 
404
 
 
405
                                        if (strcasecmp(sTarget.c_str(), GetNick().c_str()) == 0) {
 
406
                                                if (OnCTCPReply(sNickMask, sMsg)) {
 
407
                                                        return;
 
408
                                                }
 
409
                                        }
 
410
 
 
411
                                        PutUser(":" + sNickMask + " NOTICE " + sTarget + " :\001" + sMsg + "\001");
 
412
                                        return;
 
413
                                } else {
 
414
                                        if (strcasecmp(sTarget.c_str(), GetNick().c_str()) == 0) {
 
415
                                                if (OnPrivNotice(sNickMask, sMsg)) {
 
416
                                                        return;
 
417
                                                }
 
418
                                        } else {
 
419
                                                if (OnChanNotice(sNickMask, sTarget, sMsg)) {
 
420
                                                        return;
 
421
                                                }
 
422
                                        }
 
423
                                }
 
424
 
 
425
                                PutUser(":" + sNickMask + " NOTICE " + sTarget + " :" + sMsg);
 
426
                                return;
 
427
                        } else if (strcasecmp(sCmd.c_str(), "PRIVMSG") == 0) {
 
428
                                // :nick!ident@host.com PRIVMSG #chan :Message
 
429
 
 
430
                                CNick Nick(sNickMask);
 
431
                                string sTarget = CUtils::Token(sRest, 0);
 
432
                                string sMsg = CUtils::Token(sRest, 1, true);
 
433
 
 
434
                                if (CUtils::Left(sMsg, 1) == ":") {
 
435
                                        CUtils::LeftChomp(sMsg);
 
436
                                }
 
437
 
 
438
                                if (CUtils::WildCmp("\001*\001", sMsg.c_str())) {
 
439
                                        CUtils::LeftChomp(sMsg);
 
440
                                        CUtils::RightChomp(sMsg);
 
441
 
 
442
                                        if (strcasecmp(sTarget.c_str(), GetNick().c_str()) == 0) {
 
443
                                                if (OnPrivCTCP(sNickMask, sMsg)) {
 
444
                                                        return;
 
445
                                                }
 
446
                                        } else {
 
447
                                                if (OnChanCTCP(sNickMask, sTarget, sMsg)) {
 
448
                                                        return;
 
449
                                                }
 
450
                                        }
 
451
 
 
452
                                        PutUser(":" + sNickMask + " PRIVMSG " + sTarget + " :\001" + sMsg + "\001");
 
453
                                        return;
 
454
                                } else {
 
455
                                        if (strcasecmp(sTarget.c_str(), GetNick().c_str()) == 0) {
 
456
                                                if (OnPrivMsg(sNickMask, sMsg)) {
 
457
                                                        return;
 
458
                                                }
 
459
                                        } else {
 
460
                                                if (OnChanMsg(sNickMask, sTarget, sMsg)) {
 
461
                                                        return;
 
462
                                                }
 
463
                                        }
 
464
 
 
465
                                        PutUser(":" + sNickMask + " PRIVMSG " + sTarget + " :" + sMsg);
 
466
                                        return;
 
467
                                }
 
468
                        }
 
469
                }
 
470
        }
 
471
 
 
472
        PutUser(sLine);
 
473
}
 
474
 
 
475
void CIRCSock::KeepNick() {
 
476
        const string& sConfNick = m_pUser->GetNick();
 
477
 
 
478
        if ((m_bAuthed) && (m_bKeepNick) && (m_pUser->KeepNick()) && (strcasecmp(GetNick().c_str(), sConfNick.c_str()) != 0)) {
 
479
                PutServ("NICK " + sConfNick);
 
480
        }
 
481
}
 
482
 
 
483
bool CIRCSock::OnCTCPReply(const string& sNickMask, string& sMessage) {
 
484
#ifdef _MODULES
 
485
        if (m_pUser->GetModules().OnCTCPReply(sNickMask, sMessage)) {
 
486
                return true;
 
487
        }
 
488
#endif
 
489
 
 
490
        return false;
 
491
}
 
492
 
 
493
bool CIRCSock::OnPrivCTCP(const string& sNickMask, string& sMessage) {
 
494
#ifdef _MODULES
 
495
        if (m_pUser->GetModules().OnPrivCTCP(sNickMask, sMessage)) {
 
496
                return true;
 
497
        }
 
498
#endif
 
499
 
 
500
        // DCC CHAT chat 2453612361 44592
 
501
        if (strncasecmp(sMessage.c_str(), "DCC ", 4) == 0) {
 
502
                string sType = CUtils::Token(sMessage, 1);
 
503
                string sFile = CUtils::Token(sMessage, 2);
 
504
                unsigned long uLongIP = strtoul(CUtils::Token(sMessage, 3).c_str(), NULL, 10);
 
505
                unsigned short uPort = strtoul(CUtils::Token(sMessage, 4).c_str(), NULL, 10);
 
506
                unsigned long uFileSize = strtoul(CUtils::Token(sMessage, 5).c_str(), NULL, 10);
 
507
 
 
508
                if (strcasecmp(sType.c_str(), "CHAT") == 0) {
 
509
                        if (m_pUserSock) {
 
510
                                CNick FromNick(sNickMask);
 
511
                                unsigned short uBNCPort = CDCCBounce::DCCRequest(FromNick.GetNick(), uLongIP, uPort, "", true, m_pUser, GetLocalIP(), CUtils::GetIP(uLongIP));
 
512
 
 
513
                                if (uBNCPort) {
 
514
                                        PutUser(":" + sNickMask + " PRIVMSG " + GetNick() + " :\001DCC CHAT chat " + CUtils::ToString(CUtils::GetLongIP(GetLocalIP())) + " " + CUtils::ToString(uBNCPort) + "\001");
 
515
                                }
 
516
                        }
 
517
                } else if (strcasecmp(sType.c_str(), "SEND") == 0) {
 
518
                        // DCC SEND readme.txt 403120438 5550 1104
 
519
                        CNick FromNick(sNickMask);
 
520
 
 
521
                        unsigned short uBNCPort = CDCCBounce::DCCRequest(FromNick.GetNick(), uLongIP, uPort, sFile, false, m_pUser, GetLocalIP(), CUtils::GetIP(uLongIP));
 
522
                        if (uBNCPort) {
 
523
                                PutUser(":" + sNickMask + " PRIVMSG " + GetNick() + " :\001DCC SEND " + sFile + " " + CUtils::ToString(CUtils::GetLongIP(GetLocalIP())) + " " + CUtils::ToString(uBNCPort) + " " + CUtils::ToString(uFileSize));
 
524
                        }
 
525
                } else if (strcasecmp(sType.c_str(), "RESUME") == 0) {
 
526
                        // Need to lookup the connection by port, filter the port, and forward to the user
 
527
                        CDCCBounce* pSock = (CDCCBounce*) m_pZNC->GetManager().FindSockByLocalPort(atoi(CUtils::Token(sMessage, 3).c_str()));
 
528
 
 
529
                        if ((pSock) && (strncasecmp(pSock->GetSockName().c_str(), "DCC::", 5) == 0)) {
 
530
                                PutUser(":" + sNickMask + " PRIVMSG " + GetNick() + " :\001DCC " + sType + " " + sFile + " " + CUtils::ToString(pSock->GetUserPort()) + " " + CUtils::Token(sMessage, 4) + "\001");
 
531
                        }
 
532
                } else if (strcasecmp(sType.c_str(), "ACCEPT") == 0) {
 
533
                        // Need to lookup the connection by port, filter the port, and forward to the user
 
534
                        TSocketManager<Csock>& Manager = m_pZNC->GetManager();
 
535
 
 
536
                        for (unsigned int a = 0; a < Manager.size(); a++) {
 
537
                                CDCCBounce* pSock = (CDCCBounce*) Manager[a];
 
538
 
 
539
                                if ((pSock) && (strncasecmp(pSock->GetSockName().c_str(), "DCC::", 5) == 0)) {
 
540
                                        if (pSock->GetUserPort() == atoi(CUtils::Token(sMessage, 3).c_str())) {
 
541
                                                PutUser(":" + sNickMask + " PRIVMSG " + GetNick() + " :\001DCC " + sType + " " + sFile + " " + CUtils::ToString(pSock->GetLocalPort()) + " " + CUtils::Token(sMessage, 4) + "\001");
 
542
                                        }
 
543
                                }
 
544
                        }
 
545
                }
 
546
 
 
547
                return true;
 
548
        }
 
549
 
 
550
        return false;
 
551
}
 
552
 
 
553
bool CIRCSock::OnPrivNotice(const string& sNickMask, string& sMessage) {
 
554
#ifdef _MODULES
 
555
        if (m_pUser->GetModules().OnPrivNotice(sNickMask, sMessage)) {
 
556
                return true;
 
557
        }
 
558
#endif
 
559
        if (!m_pUserSock) {
 
560
                // If the user is detached, add to the buffer
 
561
                m_QueryBuffer.AddLine(":" + sNickMask + " NOTICE ", " :" + sMessage);
 
562
        }
 
563
 
 
564
        return false;
 
565
}
 
566
 
 
567
bool CIRCSock::OnPrivMsg(const string& sNickMask, string& sMessage) {
 
568
#ifdef _MODULES
 
569
        if (m_pUser->GetModules().OnPrivMsg(sNickMask, sMessage)) {
 
570
                return true;
 
571
        }
 
572
#endif
 
573
        if (!m_pUserSock) {
 
574
                // If the user is detached, add to the buffer
 
575
                m_QueryBuffer.AddLine(":" + sNickMask + " PRIVMSG ", " :" + sMessage);
 
576
        }
 
577
 
 
578
        return false;
 
579
}
 
580
 
 
581
bool CIRCSock::OnChanCTCP(const string& sNickMask, const string& sChan, string& sMessage) {
 
582
        CChan* pChan = m_pUser->FindChan(sChan);
 
583
        if (pChan) {
 
584
#ifdef _MODULES
 
585
                if (m_pUser->GetModules().OnChanCTCP(sNickMask, *pChan, sMessage)) {
 
586
                        return true;
 
587
                }
 
588
#endif
 
589
        }
 
590
 
 
591
        return false;
 
592
}
 
593
 
 
594
bool CIRCSock::OnChanNotice(const string& sNickMask, const string& sChan, string& sMessage) {
 
595
        CChan* pChan = m_pUser->FindChan(sChan);
 
596
        if (pChan) {
 
597
#ifdef _MODULES
 
598
                if (m_pUser->GetModules().OnChanNotice(sNickMask, *pChan, sMessage)) {
 
599
                        return true;
 
600
                }
 
601
#endif
 
602
                if ((pChan->KeepBuffer()) || (!m_pUserSock)) {
 
603
                        pChan->AddBuffer(":" + sNickMask + " NOTICE " + sChan + " :" + sMessage);
 
604
                }
 
605
        }
 
606
 
 
607
        return false;
 
608
}
 
609
 
 
610
bool CIRCSock::OnChanMsg(const string& sNickMask, const string& sChan, string& sMessage) {
 
611
        CChan* pChan = m_pUser->FindChan(sChan);
 
612
        if (pChan) {
 
613
#ifdef _MODULES
 
614
                if (m_pUser->GetModules().OnChanMsg(sNickMask, *pChan, sMessage)) {
 
615
                        return true;
 
616
                }
 
617
#endif
 
618
                if ((pChan->KeepBuffer()) || (!m_pUserSock)) {
 
619
                        pChan->AddBuffer(":" + sNickMask + " PRIVMSG " + sChan + " :" + sMessage);
 
620
                }
 
621
        }
 
622
 
 
623
        return false;
 
624
}
 
625
 
 
626
void CIRCSock::UserConnected(CUserSock* pUserSock) {
 
627
        if (m_pUserSock) {
 
628
                m_pUserSock->BouncedOff();
 
629
        }
 
630
 
 
631
        m_pUserSock = pUserSock;
 
632
 
 
633
        if (m_RawBuffer.IsEmpty()) {
 
634
                PutUser(":irc.znc.com 001 " + m_pUserSock->GetNick() + " :- Welcome to ZNC -");
 
635
        } else {
 
636
                unsigned int uIdx = 0;
 
637
                string sLine;
 
638
 
 
639
                while (m_RawBuffer.GetLine(GetNick(), sLine, uIdx++)) {
 
640
                        PutUser(sLine);
 
641
                }
 
642
        }
 
643
 
 
644
        PutServ("MOTD");
 
645
 
 
646
        const vector<CChan*>& vChans = m_pUser->GetChans();
 
647
        for (unsigned int a = 0; a < vChans.size(); a++) {
 
648
                if (vChans[a]->IsOn()) {
 
649
                        PutUser(":" + m_Nick.GetNickMask() + " JOIN :" + vChans[a]->GetName());
 
650
                        PutServ("NAMES " + vChans[a]->GetName());
 
651
                }
 
652
        }
 
653
 
 
654
        //PutUser("");
 
655
 
 
656
        string sBufLine;
 
657
        while (m_QueryBuffer.GetNextLine(GetNick(), sBufLine)) {
 
658
                PutUser(sBufLine);
 
659
        }
 
660
}
 
661
 
 
662
void CIRCSock::UserDisconnected() {
 
663
        m_pUserSock = NULL;
 
664
}
 
665
 
 
666
void CIRCSock::PutServ(const string& sLine) {
 
667
        DEBUG_ONLY(cout << GetSockName() << " -> [" << sLine << "]" << endl);
 
668
        Write(sLine + "\r\n");
 
669
}
 
670
 
 
671
void CIRCSock::PutUser(const string& sLine) {
 
672
        if (m_pUserSock) {
 
673
                m_pUserSock->PutServ(sLine);
 
674
        }
 
675
}
 
676
 
 
677
void CIRCSock::PutStatus(const string& sLine) {
 
678
        if (m_pUserSock) {
 
679
                m_pUserSock->PutStatus(sLine);
 
680
        }
 
681
}
 
682
 
 
683
void CIRCSock::SetNick(const string& sNick) {
 
684
        m_Nick.SetNick(sNick);
 
685
 
 
686
        if (m_pUserSock) {
 
687
                m_pUserSock->SetNick(sNick);
 
688
        }
 
689
}
 
690
 
 
691
void CIRCSock::Connected() {
 
692
        DEBUG_ONLY(cout << GetSockName() << " == Connected()" << endl);
 
693
 
 
694
        CUserSock* pUserSock = (CUserSock*) m_pZNC->FindSockByName("USR::" + m_pUser->GetUserName());
 
695
 
 
696
        if (pUserSock) {
 
697
                m_pUserSock = pUserSock;
 
698
                pUserSock->IRCConnected(this);
 
699
        }
 
700
 
 
701
        if (!m_sPass.empty()) {
 
702
                PutServ("PASS " + m_sPass);
 
703
        }
 
704
 
 
705
        PutServ("NICK " + m_pUser->GetNick());
 
706
        PutServ("USER " + m_pUser->GetIdent() + " \"" + m_pUser->GetIdent() + "\" \"" + m_pUser->GetIdent() + "\" :" + m_pUser->GetRealName());
 
707
}
 
708
 
 
709
void CIRCSock::Disconnected() {
 
710
        DEBUG_ONLY(cout << GetSockName() << " == Disconnected()" << endl);
 
711
        m_pUser->PutStatus("Disconnected from IRC.  Reconnecting...");
 
712
 
 
713
#ifdef _MODULES
 
714
        m_pUser->GetModules().OnIRCDisconnected();
 
715
#endif
 
716
 
 
717
        const vector<CChan*>& vChans = m_pUser->GetChans();
 
718
        for (unsigned int a = 0; a < vChans.size(); a++) {
 
719
                vChans[a]->SetIsOn(false);
 
720
        }
 
721
 
 
722
        if (m_pUserSock) {
 
723
                m_pUserSock->IRCDisconnected();
 
724
                m_pUserSock = NULL;
 
725
        }
 
726
}
 
727
 
 
728
void CIRCSock::SockError(int iErrno) {
 
729
        DEBUG_ONLY(cout << GetSockName() << " == SockError(" << iErrno << ")" << endl);
 
730
        m_pUser->PutStatus("Disconnected from IRC.  Reconnecting...");
 
731
}
 
732
 
 
733
void CIRCSock::Timeout() {
 
734
        DEBUG_ONLY(cout << GetSockName() << " == Timeout()" << endl);
 
735
        m_pUser->PutStatus("IRC connection timed out.  Reconnecting...");
 
736
}
 
737
 
 
738
void CIRCSock::ConnectionRefused() {
 
739
        DEBUG_ONLY(cout << GetSockName() << " == ConnectionRefused()" << endl);
 
740
        m_pUser->PutStatus("Connection Refused.  Reconnecting...");
 
741
}
 
742