~ubuntu-branches/ubuntu/oneiric/znc/oneiric-backports

1.1.3 by Joey Hess
Import upstream version 0.052
1
/*
1.3.10 by Patrick Matthäi
Import upstream version 0.098
2
 * Copyright (C) 2004-2011  See the AUTHORS file for details.
1.1.3 by Joey Hess
Import upstream version 0.052
3
 *
4
 * This program is free software; you can redistribute it and/or modify it
5
 * under the terms of the GNU General Public License version 2 as published
6
 * by the Free Software Foundation.
7
 */
1.1.1 by Joey Hess
Import upstream version 0.047
8
1 by Joey Hess
Import upstream version 0.045
9
#include "Chan.h"
1.3.11 by Patrick Matthäi
Import upstream version 0.200
10
#include "FileUtils.h"
1.1.4 by Joey Hess
Import upstream version 0.054
11
#include "IRCSock.h"
12
#include "User.h"
1 by Joey Hess
Import upstream version 0.045
13
#include "znc.h"
1.3.11 by Patrick Matthäi
Import upstream version 0.200
14
#include "Config.h"
1 by Joey Hess
Import upstream version 0.045
15
1.3.11 by Patrick Matthäi
Import upstream version 0.200
16
CChan::CChan(const CString& sName, CUser* pUser, bool bInConfig, CConfig *pConfig) {
1 by Joey Hess
Import upstream version 0.045
17
	m_sName = sName.Token(0);
18
	m_sKey = sName.Token(1);
1.1.1 by Joey Hess
Import upstream version 0.047
19
	m_pUser = pUser;
1 by Joey Hess
Import upstream version 0.045
20
1.1.1 by Joey Hess
Import upstream version 0.047
21
	if (!m_pUser->IsChan(m_sName)) {
1 by Joey Hess
Import upstream version 0.045
22
		m_sName = "#" + m_sName;
23
	}
24
25
	m_bInConfig = bInConfig;
26
	m_Nick.SetUser(pUser);
27
	m_bDetached = false;
28
	m_uBufferCount = m_pUser->GetBufferCount();
29
	m_bKeepBuffer = m_pUser->KeepBuffer();
1.1.2 by Joey Hess
Import upstream version 0.050
30
	m_bDisabled = false;
1 by Joey Hess
Import upstream version 0.045
31
	Reset();
1.3.11 by Patrick Matthäi
Import upstream version 0.200
32
33
	if (pConfig) {
34
		CString sValue;
35
		if (pConfig->FindStringEntry("buffer", sValue))
36
			SetBufferCount(sValue.ToUInt(), true);
37
		if (pConfig->FindStringEntry("keepbuffer", sValue))
38
			SetKeepBuffer(sValue.ToBool());
39
		if (pConfig->FindStringEntry("detached", sValue))
40
			SetDetached(sValue.ToBool());
41
		if (pConfig->FindStringEntry("autocycle", sValue))
42
			if (sValue.Equals("true"))
43
				CUtils::PrintError("WARNING: AutoCycle has been removed, instead try -> LoadModule = autocycle " + sName);
44
		if (pConfig->FindStringEntry("key", sValue))
45
			SetKey(sValue);
46
		if (pConfig->FindStringEntry("modes", sValue))
47
			SetDefaultModes(sValue);
48
	}
1 by Joey Hess
Import upstream version 0.045
49
}
1.1.2 by Joey Hess
Import upstream version 0.050
50
1 by Joey Hess
Import upstream version 0.045
51
CChan::~CChan() {
52
	ClearNicks();
53
}
54
55
void CChan::Reset() {
56
	m_bIsOn = false;
57
	m_musModes.clear();
58
	m_sTopic = "";
59
	m_sTopicOwner = "";
60
	m_ulTopicDate = 0;
1.1.1 by Joey Hess
Import upstream version 0.047
61
	m_ulCreationDate = 0;
1.1.9 by Patrick Matthäi
Import upstream version 0.062
62
	m_Nick.Reset();
1 by Joey Hess
Import upstream version 0.045
63
	ClearNicks();
1.1.2 by Joey Hess
Import upstream version 0.050
64
	ResetJoinTries();
1 by Joey Hess
Import upstream version 0.045
65
}
66
67
bool CChan::WriteConfig(CFile& File) {
68
	if (!InConfig()) {
69
		return false;
70
	}
71
1.2.1 by Patrick Matthäi
Import upstream version 0.066
72
	File.Write("\t<Chan " + GetName().FirstLine() + ">\n");
1 by Joey Hess
Import upstream version 0.045
73
1.1.4 by Joey Hess
Import upstream version 0.054
74
	if (m_pUser->GetBufferCount() != GetBufferCount())
1.2.1 by Patrick Matthäi
Import upstream version 0.066
75
		m_pUser->PrintLine(File, "\tBuffer", CString(GetBufferCount()));
1.1.4 by Joey Hess
Import upstream version 0.054
76
	if (m_pUser->KeepBuffer() != KeepBuffer())
1.2.1 by Patrick Matthäi
Import upstream version 0.066
77
		m_pUser->PrintLine(File, "\tKeepBuffer", CString(KeepBuffer()));
1.1.4 by Joey Hess
Import upstream version 0.054
78
	if (IsDetached())
1.2.1 by Patrick Matthäi
Import upstream version 0.066
79
		m_pUser->PrintLine(File, "\tDetached", "true");
80
	if (!GetKey().empty())
81
		m_pUser->PrintLine(File, "\tKey", GetKey());
82
	if (!GetDefaultModes().empty())
83
		m_pUser->PrintLine(File, "\tModes", GetDefaultModes());
1 by Joey Hess
Import upstream version 0.045
84
1.1.5 by Patrick Matthäi
Import upstream version 0.056
85
	File.Write("\t</Chan>\n");
1 by Joey Hess
Import upstream version 0.045
86
	return true;
87
}
88
1.1.5 by Patrick Matthäi
Import upstream version 0.056
89
void CChan::Clone(CChan& chan) {
90
	// We assume that m_sName and m_pUser are equal
1.3.8 by Patrick Matthäi
Import upstream version 0.094
91
	SetBufferCount(chan.GetBufferCount(), true);
1.1.5 by Patrick Matthäi
Import upstream version 0.056
92
	SetKeepBuffer(chan.KeepBuffer());
93
	SetKey(chan.GetKey());
94
	SetDefaultModes(chan.GetDefaultModes());
95
96
	if (IsDetached() != chan.IsDetached()) {
97
		// Only send something if it makes sense
98
		// (= Only detach if client is on the channel
99
		//    and only attach if we are on the channel)
100
		if (IsOn()) {
101
			if (IsDetached()) {
102
				JoinUser(false, "");
103
			} else {
104
				DetachUser();
105
			}
106
		}
107
		SetDetached(chan.IsDetached());
108
	}
1 by Joey Hess
Import upstream version 0.045
109
}
110
1.3.8 by Patrick Matthäi
Import upstream version 0.094
111
bool CChan::SetBufferCount(unsigned int u, bool bForce) {
112
	if (!bForce && u > CZNC::Get().GetMaxBufferSize())
113
		return false;
114
	m_uBufferCount = u;
1.3.11 by Patrick Matthäi
Import upstream version 0.200
115
	TrimBuffer(m_uBufferCount);
1.3.8 by Patrick Matthäi
Import upstream version 0.094
116
	return true;
117
}
118
1 by Joey Hess
Import upstream version 0.045
119
void CChan::Cycle() const {
120
	m_pUser->PutIRC("PART " + GetName() + "\r\nJOIN " + GetName() + " " + GetKey());
121
}
122
123
void CChan::JoinUser(bool bForce, const CString& sKey, CClient* pClient) {
124
	if (!bForce && (!IsOn() || !IsDetached())) {
125
		m_pUser->PutIRC("JOIN " + GetName() + " " + ((sKey.empty()) ? GetKey() : sKey));
20 by Patrick Matthäi
* Merge 0.092-1~bpo50+1 changelog.
126
		SetDetached(false);
1 by Joey Hess
Import upstream version 0.045
127
		return;
128
	}
129
130
	m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " JOIN :" + GetName(), pClient);
131
132
	if (!GetTopic().empty()) {
133
		m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 332 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :" + GetTopic(), pClient);
1.1.1 by Joey Hess
Import upstream version 0.047
134
		m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 333 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " " + GetTopicOwner() + " " + CString(GetTopicDate()), pClient);
1 by Joey Hess
Import upstream version 0.045
135
	}
136
1.1.1 by Joey Hess
Import upstream version 0.047
137
	CString sPre = ":" + m_pUser->GetIRCServer() + " 353 " + m_pUser->GetIRCNick().GetNick() + " " + GetModeForNames() + " " + GetName() + " :";
1 by Joey Hess
Import upstream version 0.045
138
	CString sLine = sPre;
1.1.1 by Joey Hess
Import upstream version 0.047
139
	CString sPerm, sNick;
140
141
	vector<CClient*>& vpClients = m_pUser->GetClients();
1.3.5 by Patrick Matthäi
Import upstream version 0.090~rc1
142
	for (vector<CClient*>::iterator it = vpClients.begin(); it != vpClients.end(); ++it) {
1.1.1 by Joey Hess
Import upstream version 0.047
143
		CClient* pThisClient;
144
		if (!pClient)
145
			pThisClient = *it;
146
		else
147
			pThisClient = pClient;
148
1.3.10 by Patrick Matthäi
Import upstream version 0.098
149
		for (map<CString,CNick>::iterator a = m_msNicks.begin(); a != m_msNicks.end(); ++a) {
1.1.5 by Patrick Matthäi
Import upstream version 0.056
150
			if (pThisClient->HasNamesx()) {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
151
				sPerm = a->second.GetPermStr();
1.1.1 by Joey Hess
Import upstream version 0.047
152
			} else {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
153
				char c = a->second.GetPermChar();
1.1.1 by Joey Hess
Import upstream version 0.047
154
				sPerm = "";
155
				if (c != '\0') {
156
					sPerm += c;
157
				}
158
			}
1.3.10 by Patrick Matthäi
Import upstream version 0.098
159
			if (pThisClient->HasUHNames() && !a->second.GetIdent().empty() && !a->second.GetHost().empty()) {
160
				sNick = a->first + "!" + a->second.GetIdent() + "@" + a->second.GetHost();
1.1.1 by Joey Hess
Import upstream version 0.047
161
			} else {
162
				sNick = a->first;
163
			}
164
165
			sLine += sPerm + sNick;
166
167
			if (sLine.size() >= 490 || a == (--m_msNicks.end())) {
168
				m_pUser->PutUser(sLine, pThisClient);
169
				sLine = sPre;
170
			} else {
171
				sLine += " ";
172
			}
173
		}
174
175
		if (pClient) // We only want to do this for one client
176
			break;
1 by Joey Hess
Import upstream version 0.045
177
	}
178
179
	m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 366 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :End of /NAMES list.", pClient);
180
	m_bDetached = false;
181
182
	// Send Buffer
1.1.1 by Joey Hess
Import upstream version 0.047
183
	SendBuffer(pClient);
1 by Joey Hess
Import upstream version 0.045
184
}
185
186
void CChan::DetachUser() {
187
	if (!m_bDetached) {
188
		m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " PART " + GetName());
189
		m_bDetached = true;
190
	}
191
}
192
193
void CChan::AttachUser() {
194
	if (m_bDetached) {
195
		m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " JOIN " + GetName());
196
		m_bDetached = false;
197
	}
198
}
199
200
CString CChan::GetModeString() const {
201
	CString sModes, sArgs;
202
1.3.5 by Patrick Matthäi
Import upstream version 0.090~rc1
203
	for (map<unsigned char, CString>::const_iterator it = m_musModes.begin(); it != m_musModes.end(); ++it) {
1 by Joey Hess
Import upstream version 0.045
204
		sModes += it->first;
205
		if (it->second.size()) {
206
			sArgs += " " + it->second;
207
		}
208
	}
209
1.1.2 by Joey Hess
Import upstream version 0.050
210
	return sModes.empty() ? sModes : CString("+" + sModes + sArgs);
1 by Joey Hess
Import upstream version 0.045
211
}
212
1.1.1 by Joey Hess
Import upstream version 0.047
213
CString CChan::GetModeForNames() const {
214
	CString sMode;
1.1.4 by Joey Hess
Import upstream version 0.054
215
1.3.5 by Patrick Matthäi
Import upstream version 0.090~rc1
216
	for (map<unsigned char, CString>::const_iterator it = m_musModes.begin(); it != m_musModes.end(); ++it) {
1.1.1 by Joey Hess
Import upstream version 0.047
217
		if (it->first == 's') {
1.1.9 by Patrick Matthäi
Import upstream version 0.062
218
			sMode = "@";
1.3.12 by Patrick Matthäi
Import upstream version 0.202
219
		} else if ((it->first == 'p') && sMode.empty()) {
1.1.9 by Patrick Matthäi
Import upstream version 0.062
220
			sMode = "*";
1.1.1 by Joey Hess
Import upstream version 0.047
221
		}
222
	}
223
224
	return (sMode.empty() ? "=" : sMode);
225
}
1.1.4 by Joey Hess
Import upstream version 0.054
226
1 by Joey Hess
Import upstream version 0.045
227
void CChan::SetModes(const CString& sModes) {
228
	m_musModes.clear();
229
	ModeChange(sModes);
230
}
231
232
void CChan::OnWho(const CString& sNick, const CString& sIdent, const CString& sHost) {
233
	CNick* pNick = FindNick(sNick);
234
235
	if (pNick) {
236
		pNick->SetIdent(sIdent);
237
		pNick->SetHost(sHost);
238
	}
239
}
240
1.3.10 by Patrick Matthäi
Import upstream version 0.098
241
void CChan::ModeChange(const CString& sModes, const CNick* pOpNick) {
1 by Joey Hess
Import upstream version 0.045
242
	CString sModeArg = sModes.Token(0);
243
	CString sArgs = sModes.Token(1, true);
244
	bool bAdd = true;
245
1.3.10 by Patrick Matthäi
Import upstream version 0.098
246
	/* Try to find a CNick* from this channel so that pOpNick->HasPerm()
247
	 * works as expected. */
248
	if (pOpNick) {
249
		CNick* OpNick = FindNick(pOpNick->GetNick());
250
		/* If nothing was found, use the original pOpNick, else use the
251
		 * CNick* from FindNick() */
252
		if (OpNick)
253
			pOpNick = OpNick;
254
	}
1 by Joey Hess
Import upstream version 0.045
255
256
	if (pOpNick) {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
257
		MODULECALL(OnRawMode(*pOpNick, *this, sModeArg, sArgs), m_pUser, NULL, NOTHING);
1 by Joey Hess
Import upstream version 0.045
258
	}
259
260
	for (unsigned int a = 0; a < sModeArg.size(); a++) {
261
		const unsigned char& uMode = sModeArg[a];
262
263
		if (uMode == '+') {
264
			bAdd = true;
265
		} else if (uMode == '-') {
266
			bAdd = false;
267
		} else if (m_pUser->GetIRCSock()->IsPermMode(uMode)) {
268
			CString sArg = GetModeArg(sArgs);
269
			CNick* pNick = FindNick(sArg);
270
			if (pNick) {
271
				unsigned char uPerm = m_pUser->GetIRCSock()->GetPermFromMode(uMode);
272
273
				if (uPerm) {
274
					if (bAdd) {
1.1.10 by Patrick Matthäi
Import upstream version 0.064
275
						pNick->AddPerm(uPerm);
1 by Joey Hess
Import upstream version 0.045
276
1.1.9 by Patrick Matthäi
Import upstream version 0.062
277
						if (pNick->GetNick().Equals(m_pUser->GetCurNick())) {
1 by Joey Hess
Import upstream version 0.045
278
							AddPerm(uPerm);
279
						}
280
					} else {
1.1.10 by Patrick Matthäi
Import upstream version 0.064
281
						pNick->RemPerm(uPerm);
1 by Joey Hess
Import upstream version 0.045
282
1.1.9 by Patrick Matthäi
Import upstream version 0.062
283
						if (pNick->GetNick().Equals(m_pUser->GetCurNick())) {
1 by Joey Hess
Import upstream version 0.045
284
							RemPerm(uPerm);
285
						}
286
					}
287
					bool bNoChange = (pNick->HasPerm(uPerm) == bAdd);
288
289
					if (uMode && pOpNick) {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
290
						MODULECALL(OnChanPermission(*pOpNick, *pNick, *this, uMode, bAdd, bNoChange), m_pUser, NULL, NOTHING);
1 by Joey Hess
Import upstream version 0.045
291
292
						if (uMode == CChan::M_Op) {
293
							if (bAdd) {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
294
								MODULECALL(OnOp(*pOpNick, *pNick, *this, bNoChange), m_pUser, NULL, NOTHING);
1 by Joey Hess
Import upstream version 0.045
295
							} else {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
296
								MODULECALL(OnDeop(*pOpNick, *pNick, *this, bNoChange), m_pUser, NULL, NOTHING);
1 by Joey Hess
Import upstream version 0.045
297
							}
298
						} else if (uMode == CChan::M_Voice) {
299
							if (bAdd) {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
300
								MODULECALL(OnVoice(*pOpNick, *pNick, *this, bNoChange), m_pUser, NULL, NOTHING);
1 by Joey Hess
Import upstream version 0.045
301
							} else {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
302
								MODULECALL(OnDevoice(*pOpNick, *pNick, *this, bNoChange), m_pUser, NULL, NOTHING);
1 by Joey Hess
Import upstream version 0.045
303
							}
304
						}
305
					}
306
				}
307
			}
308
		} else {
309
			bool bList = false;
310
			CString sArg;
311
312
			switch (m_pUser->GetIRCSock()->GetModeType(uMode)) {
1.3.12 by Patrick Matthäi
Import upstream version 0.202
313
			case CIRCSock::ListArg:
314
				bList = true;
315
				sArg = GetModeArg(sArgs);
316
				break;
317
			case CIRCSock::HasArg:
318
				sArg = GetModeArg(sArgs);
319
				break;
320
			case CIRCSock::NoArg:
321
				break;
322
			case CIRCSock::ArgWhenSet:
323
				if (bAdd) {
324
					sArg = GetModeArg(sArgs);
325
				}
1 by Joey Hess
Import upstream version 0.045
326
1.3.12 by Patrick Matthäi
Import upstream version 0.202
327
				break;
1 by Joey Hess
Import upstream version 0.045
328
			}
329
1.1.9 by Patrick Matthäi
Import upstream version 0.062
330
			bool bNoChange;
331
			if (bList) {
332
				bNoChange = false;
333
			} else if (bAdd) {
334
				bNoChange = HasMode(uMode) && GetModeArg(uMode) == sArg;
335
			} else {
336
				bNoChange = !HasMode(uMode);
1 by Joey Hess
Import upstream version 0.045
337
			}
1.3.10 by Patrick Matthäi
Import upstream version 0.098
338
			MODULECALL(OnMode(*pOpNick, *this, uMode, sArg, bAdd, bNoChange), m_pUser, NULL, NOTHING);
1 by Joey Hess
Import upstream version 0.045
339
340
			if (!bList) {
1.3.5 by Patrick Matthäi
Import upstream version 0.090~rc1
341
				(bAdd) ? AddMode(uMode, sArg) : RemMode(uMode);
1 by Joey Hess
Import upstream version 0.045
342
			}
343
		}
344
	}
345
}
346
347
CString CChan::GetOptions() const {
348
	CString sRet;
349
350
	if (IsDetached()) {
351
		sRet += (sRet.empty()) ? "Detached" : ", Detached";
352
	}
353
354
	if (KeepBuffer()) {
355
		sRet += (sRet.empty()) ? "KeepBuffer" : ", KeepBuffer";
356
	}
357
358
	return sRet;
359
}
360
361
CString CChan::GetModeArg(unsigned char uMode) const {
362
	if (uMode) {
363
		map<unsigned char, CString>::const_iterator it = m_musModes.find(uMode);
364
365
		if (it != m_musModes.end()) {
366
			return it->second;
367
		}
368
	}
369
370
	return "";
371
}
372
373
bool CChan::HasMode(unsigned char uMode) const {
374
	return (uMode && m_musModes.find(uMode) != m_musModes.end());
375
}
376
377
bool CChan::AddMode(unsigned char uMode, const CString& sArg) {
378
	m_musModes[uMode] = sArg;
379
	return true;
380
}
381
1.3.5 by Patrick Matthäi
Import upstream version 0.090~rc1
382
bool CChan::RemMode(unsigned char uMode) {
1 by Joey Hess
Import upstream version 0.045
383
	if (!HasMode(uMode)) {
384
		return false;
385
	}
386
387
	m_musModes.erase(uMode);
388
	return true;
389
}
390
391
CString CChan::GetModeArg(CString& sArgs) const {
392
	CString sRet = sArgs.substr(0, sArgs.find(' '));
393
	sArgs = (sRet.size() < sArgs.size()) ? sArgs.substr(sRet.size() +1) : "";
394
	return sRet;
395
}
396
397
void CChan::ClearNicks() {
398
	m_msNicks.clear();
399
}
400
401
int CChan::AddNicks(const CString& sNicks) {
402
	int iRet = 0;
1.1.10 by Patrick Matthäi
Import upstream version 0.064
403
	VCString vsNicks;
404
	VCString::iterator it;
405
406
	sNicks.Split(" ", vsNicks, false);
407
1.3.5 by Patrick Matthäi
Import upstream version 0.090~rc1
408
	for (it = vsNicks.begin(); it != vsNicks.end(); ++it) {
1.1.10 by Patrick Matthäi
Import upstream version 0.064
409
		if (AddNick(*it)) {
1 by Joey Hess
Import upstream version 0.045
410
			iRet++;
411
		}
412
	}
413
414
	return iRet;
415
}
416
417
bool CChan::AddNick(const CString& sNick) {
418
	const char* p = sNick.c_str();
1.1.1 by Joey Hess
Import upstream version 0.047
419
	CString sPrefix, sTmp, sIdent, sHost;
1 by Joey Hess
Import upstream version 0.045
420
1.1.1 by Joey Hess
Import upstream version 0.047
421
	while (m_pUser->GetIRCSock()->IsPermChar(*p)) {
422
		sPrefix += *p;
1 by Joey Hess
Import upstream version 0.045
423
424
		if (!*++p) {
425
			return false;
426
		}
427
	}
428
1.1.1 by Joey Hess
Import upstream version 0.047
429
	sTmp = p;
1.2.4 by Patrick Matthäi
Import upstream version 0.074
430
431
	// The UHNames extension gets us nick!ident@host instead of just plain nick
432
	sIdent = sTmp.Token(1, true, "!");
433
	sHost  = sIdent.Token(1, true, "@");
434
	sIdent = sIdent.Token(0, false, "@");
435
	// Get the nick
436
	sTmp   = sTmp.Token(0, false, "!");
1.1.1 by Joey Hess
Import upstream version 0.047
437
1.3.11 by Patrick Matthäi
Import upstream version 0.200
438
	CNick tmpNick(sTmp);
1.1.1 by Joey Hess
Import upstream version 0.047
439
	CNick* pNick = FindNick(sTmp);
1 by Joey Hess
Import upstream version 0.045
440
	if (!pNick) {
1.3.11 by Patrick Matthäi
Import upstream version 0.200
441
		pNick = &tmpNick;
1 by Joey Hess
Import upstream version 0.045
442
		pNick->SetUser(m_pUser);
443
	}
444
1.1.5 by Patrick Matthäi
Import upstream version 0.056
445
	if (!sIdent.empty())
1.1.1 by Joey Hess
Import upstream version 0.047
446
		pNick->SetIdent(sIdent);
1.1.5 by Patrick Matthäi
Import upstream version 0.056
447
	if (!sHost.empty())
1.1.1 by Joey Hess
Import upstream version 0.047
448
		pNick->SetHost(sHost);
449
1.1.5 by Patrick Matthäi
Import upstream version 0.056
450
	for (CString::size_type i = 0; i < sPrefix.length(); i++) {
1.1.10 by Patrick Matthäi
Import upstream version 0.064
451
		pNick->AddPerm(sPrefix[i]);
1 by Joey Hess
Import upstream version 0.045
452
	}
453
1.1.9 by Patrick Matthäi
Import upstream version 0.062
454
	if (pNick->GetNick().Equals(m_pUser->GetCurNick())) {
1.1.5 by Patrick Matthäi
Import upstream version 0.056
455
		for (CString::size_type i = 0; i < sPrefix.length(); i++) {
1.1.1 by Joey Hess
Import upstream version 0.047
456
			AddPerm(sPrefix[i]);
457
		}
1 by Joey Hess
Import upstream version 0.045
458
	}
459
1.3.10 by Patrick Matthäi
Import upstream version 0.098
460
	m_msNicks[pNick->GetNick()] = *pNick;
1 by Joey Hess
Import upstream version 0.045
461
462
	return true;
463
}
464
1.1.10 by Patrick Matthäi
Import upstream version 0.064
465
map<char, unsigned int> CChan::GetPermCounts() const {
466
	map<char, unsigned int> mRet;
467
1.3.10 by Patrick Matthäi
Import upstream version 0.098
468
	map<CString,CNick>::const_iterator it;
1.3.5 by Patrick Matthäi
Import upstream version 0.090~rc1
469
	for (it = m_msNicks.begin(); it != m_msNicks.end(); ++it) {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
470
		CString sPerms = it->second.GetPermStr();
1.1.10 by Patrick Matthäi
Import upstream version 0.064
471
472
		for (unsigned int p = 0; p < sPerms.size(); p++) {
473
			mRet[sPerms[p]]++;
1 by Joey Hess
Import upstream version 0.045
474
		}
475
	}
1.1.10 by Patrick Matthäi
Import upstream version 0.064
476
477
	return mRet;
1 by Joey Hess
Import upstream version 0.045
478
}
479
480
bool CChan::RemNick(const CString& sNick) {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
481
	map<CString,CNick>::iterator it;
1.1.4 by Joey Hess
Import upstream version 0.054
482
	set<unsigned char>::iterator it2;
483
484
	it = m_msNicks.find(sNick);
1 by Joey Hess
Import upstream version 0.045
485
	if (it == m_msNicks.end()) {
486
		return false;
487
	}
488
489
	m_msNicks.erase(it);
490
491
	return true;
492
}
493
494
bool CChan::ChangeNick(const CString& sOldNick, const CString& sNewNick) {
1.3.10 by Patrick Matthäi
Import upstream version 0.098
495
	map<CString,CNick>::iterator it = m_msNicks.find(sOldNick);
1 by Joey Hess
Import upstream version 0.045
496
497
	if (it == m_msNicks.end()) {
498
		return false;
499
	}
500
501
	// Rename this nick
1.3.10 by Patrick Matthäi
Import upstream version 0.098
502
	it->second.SetNick(sNewNick);
1 by Joey Hess
Import upstream version 0.045
503
504
	// Insert a new element into the map then erase the old one, do this to change the key to the new nick
505
	m_msNicks[sNewNick] = it->second;
506
	m_msNicks.erase(it);
507
508
	return true;
509
}
510
1.3.10 by Patrick Matthäi
Import upstream version 0.098
511
const CNick* CChan::FindNick(const CString& sNick) const {
512
	map<CString,CNick>::const_iterator it = m_msNicks.find(sNick);
513
	return (it != m_msNicks.end()) ? &it->second : NULL;
514
}
515
516
CNick* CChan::FindNick(const CString& sNick) {
517
	map<CString,CNick>::iterator it = m_msNicks.find(sNick);
518
	return (it != m_msNicks.end()) ? &it->second : NULL;
1 by Joey Hess
Import upstream version 0.045
519
}
520
521
int CChan::AddBuffer(const CString& sLine) {
522
	// Todo: revisit the buffering
523
	if (!m_uBufferCount) {
524
		return 0;
525
	}
526
527
	if (m_vsBuffer.size() >= m_uBufferCount) {
528
		m_vsBuffer.erase(m_vsBuffer.begin());
529
	}
530
531
	m_vsBuffer.push_back(sLine);
532
	return m_vsBuffer.size();
533
}
534
535
void CChan::ClearBuffer() {
536
	m_vsBuffer.clear();
537
}
1.1.1 by Joey Hess
Import upstream version 0.047
538
1.3.11 by Patrick Matthäi
Import upstream version 0.200
539
void CChan::TrimBuffer(const unsigned int uMax) {
540
	if (m_vsBuffer.size() > uMax) {
1.3.12 by Patrick Matthäi
Import upstream version 0.202
541
		m_vsBuffer.erase(m_vsBuffer.begin(), m_vsBuffer.begin() + (m_vsBuffer.size() - uMax));
1.3.11 by Patrick Matthäi
Import upstream version 0.200
542
	}
543
}
544
1.1.1 by Joey Hess
Import upstream version 0.047
545
void CChan::SendBuffer(CClient* pClient) {
546
	if (m_pUser && m_pUser->IsUserAttached()) {
547
		const vector<CString>& vsBuffer = GetBuffer();
548
1.3.12 by Patrick Matthäi
Import upstream version 0.202
549
		// in the event that pClient is NULL, need to send this to all clients for the user
550
		// I'm presuming here that pClient is listed inside vClients thus vClients at this
551
		// point can't be empty.
552
		//
553
		// This loop has to be cycled twice to maintain the existing behavior which is
554
		// 1. OnChanBufferStarting
555
		// 2. OnChanBufferPlayLine
556
		// 3. ClearBuffer() if not keeping the buffer
557
		// 4. OnChanBufferEnding
558
		//
559
		// With the exception of ClearBuffer(), this needs to happen per client, and
560
		// if pClient is not NULL, the loops break after the first iteration.
561
		//
562
		// Rework this if you like ...
1.1.1 by Joey Hess
Import upstream version 0.047
563
		if (vsBuffer.size()) {
1.3.12 by Patrick Matthäi
Import upstream version 0.202
564
			const vector<CClient*> & vClients = m_pUser->GetClients();
565
			for( size_t uClient = 0; uClient < vClients.size(); ++uClient ) {
566
567
				CClient * pUseClient = ( pClient ? pClient : vClients[uClient] );
568
				bool bSkipStatusMsg = false;
569
				MODULECALL(OnChanBufferStarting(*this, *pUseClient), m_pUser, NULL, bSkipStatusMsg = true);
570
571
				if (!bSkipStatusMsg) {
572
					m_pUser->PutUser(":***!znc@znc.in PRIVMSG " + GetName() + " :Buffer Playback...", pUseClient);
573
				}
574
575
				for (unsigned int a = 0; a < vsBuffer.size(); a++) {
576
					CString sLine(vsBuffer[a]);
577
					MODULECALL(OnChanBufferPlayLine(*this, *pUseClient, sLine), m_pUser, NULL, continue);
578
					m_pUser->PutUser(sLine, pUseClient);
579
				}
580
581
				if( pClient )
582
					break;
583
1.1.1 by Joey Hess
Import upstream version 0.047
584
			}
585
586
			if (!KeepBuffer()) {
587
				ClearBuffer();
588
			}
589
1.3.12 by Patrick Matthäi
Import upstream version 0.202
590
			for( size_t uClient = 0; uClient < vClients.size(); ++uClient ) {
591
592
				CClient * pUseClient = ( pClient ? pClient : vClients[uClient] );
593
				bool bSkipStatusMsg = false;
594
				MODULECALL(OnChanBufferEnding(*this, *pUseClient), m_pUser, NULL, bSkipStatusMsg = true);
595
596
				if (!bSkipStatusMsg) {
597
					m_pUser->PutUser(":***!znc@znc.in PRIVMSG " + GetName() + " :Playback Complete.", pUseClient);
598
				}
599
600
				if( pClient )
601
					break;
1.2.3 by Patrick Matthäi
Import upstream version 0.070
602
			}
1.3.12 by Patrick Matthäi
Import upstream version 0.202
603
1.1.1 by Joey Hess
Import upstream version 0.047
604
		}
605
	}
606
}