1 /*
2 * This file is part of Licq, an instant messaging client for UNIX.
3 * Copyright (C) 1998-2014 Licq developers <licq-dev@googlegroups.com>
4 *
5 * Licq is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * Licq is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Licq; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "packet-srv.h"
21
22 #include <boost/foreach.hpp>
23 #include <ctime>
24 #include <cstdio>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <fcntl.h>
30
31 #include <cerrno>
32
33 #include <licq/byteorder.h>
34 #include <licq/contactlist/group.h>
35 #include <licq/contactlist/usermanager.h>
36 #include <licq/crypto.h>
37 #include <licq/daemon.h>
38 #include <licq/socket.h>
39 #include <licq/translator.h>
40 #include <licq/logging/log.h>
41 #include <licq/version.h>
42
43 #include "buffer.h"
44 #include "defines.h"
45 #include "gettext.h"
46 #include "icq.h"
47 #include "owner.h"
48 #include "user.h"
49
50 using namespace LicqIcq;
51 using Licq::Group;
52 using Licq::StringList;
53 using Licq::UserCategoryMap;
54 using Licq::UserGroupList;
55 using Licq::UserId;
56 using Licq::gLog;
57 using Licq::gTranslator;
58 using Licq::gUserManager;
59 using std::string;
60 using std::list;
61
62 // TODO: Remove when no longer needed
63 typedef Licq::User ICQUser;
64
65
lengthField(const string & field)66 static size_t lengthField(const string& field)
67 {
68 // By SC 27434326
69 // Auxiliary function for whitepage search
70 //+ 7 byte for command (2),length field (4)
71 // end string (1)
72
73 size_t len = field.size();
74 return (len ? (len + 7 ) : 0);
75 }
76
77 #define DEBUG_ENCRYPTION(x)
78 //#define DEBUG_ENCRYPTION(x) fprintf(stderr, x)
79
80 #if ICQ_VERSION == 4
81 static unsigned char icq_check_data[256] = {
82 0x0a, 0x5b, 0x31, 0x5d, 0x20, 0x59, 0x6f, 0x75,
83 0x20, 0x63, 0x61, 0x6e, 0x20, 0x6d, 0x6f, 0x64,
84 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20,
85 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x20, 0x49,
86 0x43, 0x51, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73,
87 0x2e, 0x20, 0x4a, 0x75, 0x73, 0x74, 0x20, 0x73,
88 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x22, 0x53,
89 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x20, 0x66,
90 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
91 0x22, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65,
92 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x6d, 0x69, 0x73,
93 0x63, 0x22, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x43,
94 0x51, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x72, 0x6f,
95 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x53,
96 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x20, 0x69,
97 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
98 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x70, 0x61,
99 0x6e, 0x65, 0x6c, 0x2e, 0x20, 0x43, 0x72, 0x65,
100 0x64, 0x69, 0x74, 0x3a, 0x20, 0x45, 0x72, 0x61,
101 0x6e, 0x0a, 0x5b, 0x32, 0x5d, 0x20, 0x43, 0x61,
102 0x6e, 0x27, 0x74, 0x20, 0x72, 0x65, 0x6d, 0x65,
103 0x6d, 0x62, 0x65, 0x72, 0x20, 0x77, 0x68, 0x61,
104 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x61,
105 0x69, 0x64, 0x3f, 0x20, 0x20, 0x44, 0x6f, 0x75,
106 0x62, 0x6c, 0x65, 0x2d, 0x63, 0x6c, 0x69, 0x63,
107 0x6b, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x20, 0x75,
108 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x67,
109 0x65, 0x74, 0x20, 0x61, 0x20, 0x64, 0x69, 0x61,
110 0x6c, 0x6f, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x61,
111 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
112 0x67, 0x65, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74,
113 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e,
114 };
115 #elif ICQ_VERSION == 5
116 static unsigned char icq_check_data[256] = {
117 0x59, 0x60, 0x37, 0x6B, 0x65, 0x62, 0x46, 0x48,
118 0x53, 0x61, 0x4C, 0x59, 0x60, 0x57, 0x5B, 0x3D,
119 0x5E, 0x34, 0x6D, 0x36, 0x50, 0x3F, 0x6F, 0x67,
120 0x53, 0x61, 0x4C, 0x59, 0x40, 0x47, 0x63, 0x39,
121 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x43, 0x69,
122 0x48, 0x33, 0x31, 0x64, 0x35, 0x5A, 0x4A, 0x42,
123 0x56, 0x40, 0x67, 0x53, 0x41, 0x07, 0x6C, 0x49,
124 0x58, 0x3B, 0x4D, 0x46, 0x68, 0x43, 0x69, 0x48,
125 0x33, 0x31, 0x44, 0x65, 0x62, 0x46, 0x48, 0x53,
126 0x41, 0x07, 0x6C, 0x69, 0x48, 0x33, 0x51, 0x54,
127 0x5D, 0x4E, 0x6C, 0x49, 0x38, 0x4B, 0x55, 0x4A,
128 0x62, 0x46, 0x48, 0x33, 0x51, 0x34, 0x6D, 0x36,
129 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x63,
130 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, 0x35, 0x5A,
131 0x6A, 0x52, 0x6E, 0x3C, 0x51, 0x34, 0x6D, 0x36,
132 0x50, 0x5F, 0x5F, 0x3F, 0x4F, 0x37, 0x4B, 0x35,
133 0x5A, 0x4A, 0x62, 0x66, 0x58, 0x3B, 0x4D, 0x66,
134 0x58, 0x5B, 0x5D, 0x4E, 0x6C, 0x49, 0x58, 0x3B,
135 0x4D, 0x66, 0x58, 0x3B, 0x4D, 0x46, 0x48, 0x53,
136 0x61, 0x4C, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64,
137 0x55, 0x6A, 0x32, 0x3E, 0x44, 0x45, 0x52, 0x6E,
138 0x3C, 0x31, 0x64, 0x55, 0x6A, 0x52, 0x4E, 0x6C,
139 0x69, 0x48, 0x53, 0x61, 0x4C, 0x39, 0x30, 0x6F,
140 0x47, 0x63, 0x59, 0x60, 0x57, 0x5B, 0x3D, 0x3E,
141 0x64, 0x35, 0x3A, 0x3A, 0x5A, 0x6A, 0x52, 0x4E,
142 0x6C, 0x69, 0x48, 0x53, 0x61, 0x6C, 0x49, 0x58,
143 0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F,
144 0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41,
145 0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E,
146 0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F,
147 0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D,
148 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00,
149 };
150 #endif
151
152 static unsigned short login_fix [] = {
153 5695, 23595, 23620, 23049, 0x2886, 0x2493, 23620, 23049, 2853, 17372, 1255, 1796, 1657, 13606, 1930, 23918, 31234, 30120, 0x1BEA, 0x5342, 0x30CC, 0x2294, 0x5697, 0x25FA, 0x3303, 0x078A, 0x0FC5, 0x25D6, 0x26EE,0x7570, 0x7F33, 0x4E94, 0x07C9, 0x7339, 0x42A8
154 };
155
Encrypt_Server(CBuffer *)156 void Encrypt_Server(CBuffer* /* buffer */)
157 {
158 #if ICQ_VERSION == 2
159 // No encryption in V2
160 #elif ICQ_VERSION == 4
161 buffer->log(Log::Debug, tr("Unencrypted Packet"));
162
163 unsigned long nCheckSum = 0;
164 unsigned long l = buffer->getDataSize();
165 unsigned char *buf = (unsigned char *)buffer->getDataStart();
166
167 unsigned long chk1 = ( buf[8] << 24) |
168 ( buf[4] << 16 ) |
169 ( buf[2] << 8 ) |
170 ( buf[6] );
171 unsigned short r1 = rand() % (l - 4);
172 unsigned short r2 = rand() & 0xFF;
173 unsigned long chk2 = ( r1 << 24 ) |
174 ( buf[r1] << 16 ) |
175 ( r2 << 8 ) |
176 ( icq_check_data[r2] );
177 chk2 ^= 0x00FF00FF;
178 nCheckSum = chk1 ^ chk2;
179 unsigned long key = l * 0x66756b65 + nCheckSum;
180 //fprintf(stderr, "key: 0x%08x\n", key);
181
182 unsigned long k = 0;
183 unsigned short n = (l + 3) >> 2;
184 for (unsigned short i = 0; i < n; i += 4)
185 {
186 // Skip check code field
187 //*((unsigned long *)(buf + i)) ^= (key + icq_check_data[i & 0xff]);
188 k = (key + icq_check_data[i & 0xff]);
189 // Make it work on any endianness
190 buf[i] ^= (k ) & 0xFF;
191 buf[i+1] ^= (k >> 8) & 0xFF;
192 buf[i+2] ^= (k >> 16) & 0xFF;
193 buf[i+3] ^= (k >> 24) & 0xFF;
194 }
195 // Restore the version number
196 buf[0] = 0x04;
197 buf[1] = 0x00;
198 // Stick in the checksum
199 buf[16] = nCheckSum & 0xFF;
200 buf[17] = (nCheckSum >> 8) & 0xFF;
201 buf[18] = (nCheckSum >> 16) & 0xFF;
202 buf[19] = (nCheckSum >> 24) & 0xFF;
203
204 #elif ICQ_VERSION == 5
205 unsigned long l = buffer->getDataSize();
206 unsigned long nCheckSum = 0;
207 unsigned char *buf = (unsigned char *)buffer->getDataStart();
208
209 // Make sure packet is long enough
210 if (l == 24)
211 {
212 buffer->PackUnsignedLong(rand());
213 l = buffer->getDataSize();
214 }
215
216 buffer->log(Log::Debug, tr("Unencrypted Packet (%lu bytes)"), l);
217
218 // Calculate checkcode
219 unsigned long chk1 = ( buf[8] << 24) |
220 ( buf[4] << 16 ) |
221 ( buf[2] << 8 ) |
222 ( buf[6] );
223 DEBUG_ENCRYPTION(("chk1: %08lX\n", chk1));
224 unsigned short r1 = 24 + rand() % (l - 24);
225 unsigned short r2 = rand() & 0xFF;
226 unsigned long chk2 = ( r1 << 24 ) |
227 ( buf[r1] << 16 ) |
228 ( r2 << 8 ) |
229 ( icq_check_data[r2] );
230 DEBUG_ENCRYPTION(("chk2: %08lX\n", chk2));
231 chk2 ^= 0x00FF00FF;
232 nCheckSum = chk1 ^ chk2;
233 unsigned long key = l * 0x68656C6C + nCheckSum;
234
235 unsigned long k = 0;
236 for (unsigned short i = 10; i < l; i += 4)
237 {
238 k = (key + icq_check_data[i & 0xff]);
239 // Make it work on any endianness
240 buf[i] ^= (k ) & 0xFF;
241 buf[i+1] ^= (k >> 8) & 0xFF;
242 buf[i+2] ^= (k >> 16) & 0xFF;
243 buf[i+3] ^= (k >> 24) & 0xFF;
244 }
245
246 // Add in the checkcode
247 DEBUG_ENCRYPTION(("checksum: %08lX\n", nCheckSum));
248 unsigned long a1 = nCheckSum & 0x0000001F;
249 unsigned long a2 = nCheckSum & 0x03E003E0;
250 unsigned long a3 = nCheckSum & 0xF8000400;
251 unsigned long a4 = nCheckSum & 0x0000F800;
252 unsigned long a5 = nCheckSum & 0x041F0000;
253 a1 <<= 0x0C;
254 a2 <<= 0x01;
255 a3 >>= 0x0A;
256 a4 <<= 0x10;
257 a5 >>= 0x0F;
258 unsigned long nNewCheckSum = a1 + a2 + a3 + a4 + a5;
259
260 // Stick in the checksum
261 buf[20] = nNewCheckSum & 0xFF;
262 buf[21] = (nNewCheckSum >> 8) & 0xFF;
263 buf[22] = (nNewCheckSum >> 16) & 0xFF;
264 buf[23] = (nNewCheckSum >> 24) & 0xFF;
265
266 #endif
267 }
268
269 //======Server TCP============================================================
270 bool CSrvPacketTcp::s_bRegistered = false;
271 unsigned short CSrvPacketTcp::s_nSequence[32];
272 unsigned short CSrvPacketTcp::s_nSubSequence = 0;
273 pthread_mutex_t CSrvPacketTcp::s_xMutex = PTHREAD_MUTEX_INITIALIZER;
274
initSequence(int service)275 void CSrvPacketTcp::initSequence(int service)
276 {
277 pthread_mutex_lock(&s_xMutex);
278 s_nSequence[service] = login_fix[ rand() % (sizeof(login_fix)/sizeof(login_fix[0])-1) ];
279 pthread_mutex_unlock(&s_xMutex);
280 }
281
CSrvPacketTcp(unsigned char icqChannel)282 CSrvPacketTcp::CSrvPacketTcp(unsigned char icqChannel)
283 : myIcqChannel(icqChannel)
284 {
285 pthread_mutex_lock(&s_xMutex);
286 // will set m_nSequence later, in InitBuffer;
287 m_nSubSequence = s_nSubSequence++;
288 pthread_mutex_unlock(&s_xMutex);
289 m_nFamily = m_nSubType = m_nSubCommand = m_nExtraInfo = 0;
290
291 buffer = NULL;
292 m_nSize = 0;
293 m_nService = 0;
294 m_szSequenceOffset = NULL;
295 }
296
~CSrvPacketTcp()297 CSrvPacketTcp::~CSrvPacketTcp()
298 {
299 delete buffer;
300 }
301
Finalize(Licq::INetSocket *)302 CBuffer *CSrvPacketTcp::Finalize(Licq::INetSocket*)
303 {
304 // m_szSequenceOffset
305 if (!getBuffer()) return new CBuffer;
306 return new CBuffer(*getBuffer());
307 }
308
InitBuffer()309 void CSrvPacketTcp::InitBuffer()
310 {
311 pthread_mutex_lock(&s_xMutex);
312 m_nSequence = s_nSequence[m_nService]++;
313 s_nSequence[m_nService] &= 0xffff;
314 pthread_mutex_unlock(&s_xMutex);
315
316 buffer = new Buffer(m_nSize+6);
317 buffer->PackChar(0x2a);
318 buffer->PackChar(myIcqChannel);
319 m_szSequenceOffset = buffer->getDataPosWrite();
320 buffer->PackUnsignedShortBE(m_nSequence);
321 buffer->PackUnsignedShortBE(m_nSize);
322 }
323
324 //=====UDP======================================================================
325 unsigned short CPacketUdp::s_nSequence = 0;
326 unsigned short CPacketUdp::s_nSubSequence = 0;
327 unsigned long CPacketUdp::s_nSessionId = 0;
328 bool CPacketUdp::s_bRegistered = false;
329
Finalize(Licq::INetSocket *)330 CBuffer *CPacketUdp::Finalize(Licq::INetSocket*)
331 {
332 if (!getBuffer()) return new CBuffer;
333 return new CBuffer(*getBuffer());
334 }
335
CPacketUdp(unsigned short _nCommand)336 CPacketUdp::CPacketUdp(unsigned short _nCommand)
337 {
338 #if ICQ_VERSION == 2
339 m_nVersion = 0x02;
340 #elif ICQ_VERSION == 4
341 m_nVersion = 0x04;
342 m_nRandom = rand();
343 m_nZero = 0;
344 m_nCheckSum = 0;
345 #elif ICQ_VERSION == 5
346 m_nVersion = 0x05;
347 m_nZero = 0;
348 m_nSessionId = s_nSessionId;
349 m_nCheckSum = 0;
350 #endif
351
352 m_nCommand = _nCommand;
353 // Fill in the sequences
354 switch(m_nCommand)
355 {
356 case ICQ_CMDxSND_ACK:
357 case ICQ_CMDxSND_LOGON:
358 case ICQ_CMDxSND_REGISTERxUSER:
359 {
360 m_nSequence = 0;
361 m_nSubSequence = 0;
362 break;
363 }
364 case ICQ_CMDxSND_PING:
365 {
366 m_nSequence = s_nSequence++;
367 m_nSubSequence = 0;
368 break;
369 }
370 default:
371 {
372 m_nSequence = s_nSequence++;
373 m_nSubSequence = s_nSubSequence++;
374 break;
375 }
376 }
377
378 buffer = NULL;
379 #if ICQ_VERSION == 2
380 m_nSize = 10;
381 #elif ICQ_VERSION == 4
382 m_nSize = 20;
383 #elif ICQ_VERSION == 5
384 m_nSize = 24;
385 #endif
386 }
387
~CPacketUdp()388 CPacketUdp::~CPacketUdp()
389 {
390 delete buffer;
391 }
392
InitBuffer()393 void CPacketUdp::InitBuffer()
394 {
395 buffer = new CBuffer(m_nSize + 8);
396 #if ICQ_VERSION == 2
397 buffer->PackUnsignedShort(m_nVersion);
398 buffer->PackUnsignedShort(m_nCommand);
399 buffer->PackUnsignedShort(m_nSequence);
400 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
401 #elif ICQ_VERSION == 4
402 buffer->add(m_nVersion);
403 buffer->add(m_nRandom);
404 buffer->add(m_nZero);
405 buffer->add(m_nCommand);
406 buffer->add(m_nSequence);
407 buffer->add(m_nSubSequence);
408 buffer->add(gIcqProtocol.icqOwnerUin());
409 buffer->add(m_nCheckSum);
410 #elif ICQ_VERSION == 5
411 buffer->PackUnsignedShort(m_nVersion);
412 buffer->PackUnsignedLong(m_nZero);
413 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
414 buffer->PackUnsignedLong(m_nSessionId);
415 buffer->PackUnsignedShort(m_nCommand);
416 buffer->PackUnsignedShort(m_nSequence);
417 buffer->PackUnsignedShort(m_nSubSequence);
418 buffer->PackUnsignedLong(m_nCheckSum);
419 #endif
420 }
421
422 //-----Register----------------------------------------------------------------
423 #if ICQ_VERSION == 2 || ICQ_VERSION == 6
CPU_Register(const string & password)424 CPU_Register::CPU_Register(const string& password)
425 {
426 m_nVersion = ICQ_VERSION;
427 m_nCommand = ICQ_CMDxSND_REGISTERxUSER;
428 m_nSequence = 0x001;
429 m_nPasswdLen = password.size() + 1;
430 myPassword = password;
431
432 m_nSize = myPassword.size() + 1 + 18;
433 buffer = new CBuffer(m_nSize);
434
435 buffer->PackUnsignedShort(m_nVersion);
436 buffer->PackUnsignedShort(m_nCommand);
437 buffer->PackUnsignedShort(m_nSequence);
438 buffer->PackUnsignedShort(0x02);
439 buffer->packString(myPassword);
440 buffer->PackUnsignedShort(0x72);
441 buffer->PackUnsignedShort(0x00);
442 }
443
~CPU_Register()444 CPU_Register::~CPU_Register()
445 {
446 // Empty
447 }
448
449 #elif ICQ_VERSION == 4 || ICQ_VERSION == 5
450
CPU_Register(const string & password)451 CPU_Register::CPU_Register(const string& password)
452 : CPacketUdp(ICQ_CMDxSND_REGISTERxUSER)
453 {
454 m_nSize += password.size() + 1 + 20;
455
456 #if ICQ_VERSION == 5
457 m_nSessionId = s_nSessionId = rand() & 0x3FFFFFFF;
458 #endif
459 s_nSequence = rand() & 0x7FFF;
460 m_nSequence = s_nSequence++;
461 m_nSubSequence = s_nSubSequence = 1;
462 s_bRegistered = true;
463
464 InitBuffer();
465
466 buffer->packString(password);
467 buffer->PackUnsignedLong(0x000000A0);
468 buffer->PackUnsignedLong(0x00002461);
469 buffer->PackUnsignedLong(0x00A00000);
470 buffer->PackUnsignedLong(0x00000000);
471 }
472
~CPU_Register()473 CPU_Register::~CPU_Register()
474 {
475 // Empty
476 }
477
478 #elif ICQ_VERSION >= 7
479
CPU_RegisterFirst()480 CPU_RegisterFirst::CPU_RegisterFirst()
481 : CSrvPacketTcp(ICQ_CHNxNEW)
482 {
483 m_nSize = 4;
484
485 initSequence(m_nService);
486 s_bRegistered = true;
487
488 InitBuffer();
489
490 buffer->PackUnsignedLongBE(1);
491 }
492
~CPU_RegisterFirst()493 CPU_RegisterFirst::~CPU_RegisterFirst()
494 {
495 // Empty
496 }
497
CPU_Register(const string & password)498 CPU_Register::CPU_Register(const string& password)
499 : CPU_CommonFamily(ICQ_SNACxFAM_AUTH, ICQ_SNACxREGISTER_USER)
500 {
501 int nPassLen = password.size();
502 m_nSize += 55 + nPassLen;
503
504 InitBuffer();
505
506 buffer->PackUnsignedShortBE(0x0001);
507 buffer->PackUnsignedShortBE(nPassLen+51);
508 buffer->PackUnsignedLongBE(0x00000000);
509 buffer->PackUnsignedLongBE(0x28000000);
510 buffer->PackUnsignedLongBE(0);
511 buffer->PackUnsignedLongBE(0);
512 buffer->PackUnsignedLongBE(0);//x82270000);
513 buffer->PackUnsignedLongBE(0);//x82270000);
514 for (int x = 0; x < 4; x++) buffer->PackUnsignedLongBE(0);
515 buffer->packShortNullStringLE(password);
516 buffer->PackUnsignedLongBE(0);//x82270000);
517 buffer->PackUnsignedLongBE(0xf2070000);
518 }
519
~CPU_Register()520 CPU_Register::~CPU_Register()
521 {
522 // Empty
523 }
524
525 #endif
526
CPU_VerifyRegistration()527 CPU_VerifyRegistration::CPU_VerifyRegistration()
528 : CPU_CommonFamily(ICQ_SNACxFAM_AUTH, ICQ_SNACxREQUEST_IMAGE)
529 {
530 // Yes, it's empty
531
532 InitBuffer();
533 }
534
~CPU_VerifyRegistration()535 CPU_VerifyRegistration::~CPU_VerifyRegistration()
536 {
537 // Empty
538 }
539
CPU_SendVerification(const string & password,const string & verification)540 CPU_SendVerification::CPU_SendVerification(const string& password, const string& verification)
541 : CPU_CommonFamily(ICQ_SNACxFAM_AUTH, ICQ_SNACxREGISTER_USER)
542 {
543 m_nSize += 55 + password.size() + verification.size() + 4;
544
545 InitBuffer();
546
547 buffer->PackUnsignedShortBE(0x0001);
548 buffer->PackUnsignedShortBE(password.size()+51);
549 buffer->PackUnsignedLongBE(0x00000000);
550 buffer->PackUnsignedLongBE(0x28000000);
551 buffer->PackUnsignedLongBE(0);
552 buffer->PackUnsignedLongBE(0);
553 buffer->PackUnsignedLongBE(0);//x82270000);
554 buffer->PackUnsignedLongBE(0);//x82270000);
555 for (int x = 0; x < 4; x++) buffer->PackUnsignedLongBE(0);
556 buffer->packShortNullStringLE(password);
557 buffer->PackUnsignedLongBE(0);//x82270000);
558 buffer->PackUnsignedLongBE(0xf2070000);
559 // Verification TLV
560 buffer->PackUnsignedShortBE(0x0009);
561 buffer->PackUnsignedShortBE(verification.size());
562 buffer->pack(verification);
563 }
564
~CPU_SendVerification()565 CPU_SendVerification::~CPU_SendVerification()
566 {
567 // Empty
568 }
569
CPU_ConnectStart()570 CPU_ConnectStart::CPU_ConnectStart()
571 : CSrvPacketTcp(ICQ_CHNxNEW)
572 {
573 if (!s_bRegistered) {
574 initSequence(m_nService);
575 s_bRegistered = true;
576 }
577
578 m_nSize = 12;
579 InitBuffer();
580
581 buffer->PackUnsignedLongBE(0x00000001);
582 buffer->PackUnsignedLongBE(0x80030004);
583 buffer->PackUnsignedLongBE(0x00100000);
584 }
585
CPU_RequestLogonSalt(const std::string & id)586 CPU_RequestLogonSalt::CPU_RequestLogonSalt(const std::string &id)
587 : CPU_CommonFamily(ICQ_SNACxFAM_AUTH, ICQ_SNACxAUTHxREQUEST_SALT)
588 {
589 m_nSize += id.size() + 4;
590 InitBuffer();
591
592 buffer->PackTLV(0x0001, id.size(), id.c_str());
593 }
594
595 //-----NewLogon-----------------------------------------------------------------
CPU_NewLogon(const string & password,const string & accountId,const string & md5Salt)596 CPU_NewLogon::CPU_NewLogon(const string& password, const string& accountId, const string& md5Salt)
597 : CPU_CommonFamily(ICQ_SNACxFAM_AUTH, ICQ_SNACxAUTHxLOGON)
598 {
599 // truncate password to MAX 8 characters
600 string pass(password);
601 if (pass.size() > 8)
602 {
603 gLog.warning(tr("Password too long, truncated to 8 Characters!"));
604 pass.erase(8);
605 }
606
607 m_nSize += accountId.size() + Licq::Md5::DIGEST_LENGTH + 70;
608 InitBuffer();
609
610 buffer->PackTLV(0x0001, accountId.size(), accountId.c_str());
611
612 {
613 const string toHash = md5Salt + pass + "AOL Instant Messenger (SM)";
614
615 using namespace Licq::Md5;
616 uint8_t digest[DIGEST_LENGTH];
617 hash(toHash, digest);
618
619 buffer->PackTLV(0x0025, DIGEST_LENGTH, reinterpret_cast<char *>(digest));
620 }
621
622 buffer->PackTLV(0x0003, 0x0008, "ICQBasic");
623
624 // Static versioning
625 buffer->PackUnsignedLongBE(0x00160002);
626 buffer->PackUnsignedShortBE(0x010B);
627 // Client version major (4 == ICQ2000, 5 == ICQ2001)
628 buffer->PackUnsignedLongBE(0x00170002);
629 buffer->PackUnsignedShortBE(0x0014);
630 // Client version minor
631 buffer->PackUnsignedLongBE(0x00180002);
632 buffer->PackUnsignedShortBE(0x0022);
633 buffer->PackUnsignedLongBE(0x00190002);
634 buffer->PackUnsignedShortBE(0x0000);
635 // Client version build
636 buffer->PackUnsignedLongBE(0x001a0002);
637 buffer->PackUnsignedShortBE(0x0BB8);
638 buffer->PackUnsignedLongBE(0x00140004);
639 buffer->PackUnsignedLongBE(0x0000043D);
640
641 // locale info, just use english, usa for now, i don't know what else they use
642 buffer->PackTLV(0x000f, 0x0002, "en");
643 buffer->PackTLV(0x000e, 0x0002, "us");
644 }
645
646 //-----Logon--------------------------------------------------------------------
CPU_Logon(const string & password,const string & accountId,unsigned short _nLogonStatus)647 CPU_Logon::CPU_Logon(const string& password, const string& accountId, unsigned short _nLogonStatus)
648 : CSrvPacketTcp(ICQ_CHNxNEW)
649 {
650 // truncate password to MAX 8 characters
651 string pass(password);
652 if (pass.size() > 8)
653 {
654 gLog.warning(tr("Password too long, truncated to 8 Characters!"));
655 pass.erase(8);
656 }
657
658 char szEncPass[16];
659 unsigned int j;
660
661 if (!s_bRegistered) {
662 initSequence(m_nService);
663 s_bRegistered = true;
664 }
665
666 m_nLogonStatus = _nLogonStatus;
667 m_nTcpVersion = ICQ_VERSION_TCP;
668
669 unsigned int pwlen = pass.size();
670
671 m_nSize = accountId.size() + pwlen + 74;
672 InitBuffer();
673
674 // Encrypt our password here
675 unsigned char xor_table[] = { 0xf3, 0x26, 0x81, 0xc4, 0x39, 0x86, 0xdb, 0x92,
676 0x71, 0xa3, 0xb9, 0xe6, 0x53, 0x7a, 0x95, 0x7c};
677 for (j = 0; j < pwlen; j++)
678 szEncPass[j] = (pass[j] ^ xor_table[j]);
679 szEncPass[j] = 0;
680
681 buffer->PackUnsignedLongBE(0x00000001);
682 buffer->PackTLV(0x0001, accountId.size(), accountId.c_str());
683 buffer->PackTLV(0x0002, pwlen, szEncPass);
684 buffer->PackTLV(0x0003, 0x0008, "ICQBasic");
685
686 // Static versioning
687 buffer->PackUnsignedLongBE(0x00160002);
688 buffer->PackUnsignedShortBE(0x010B);
689 // Client version major (4 == ICQ2000, 5 == ICQ2001)
690 buffer->PackUnsignedLongBE(0x00170002);
691 buffer->PackUnsignedShortBE(0x0014);
692 // Client version minor
693 buffer->PackUnsignedLongBE(0x00180002);
694 buffer->PackUnsignedShortBE(0x0022);
695 buffer->PackUnsignedLongBE(0x00190002);
696 buffer->PackUnsignedShortBE(0x0000);
697 // Client version build
698 buffer->PackUnsignedLongBE(0x001a0002);
699 buffer->PackUnsignedShortBE(0x0BB8);
700 buffer->PackUnsignedLongBE(0x00140004);
701 buffer->PackUnsignedLongBE(0x0000043D);
702
703 // locale info, just use english, usa for now, i don't know what else they use
704 buffer->PackTLV(0x000f, 0x0002, "en");
705 buffer->PackTLV(0x000e, 0x0002, "us");
706 }
707
~CPU_Logon()708 CPU_Logon::~CPU_Logon()
709 {
710 // Empty
711 }
712
713 //-----SendCookie------------------------------------------------------------
CPU_SendCookie(const string & cookie,unsigned short nService)714 CPU_SendCookie::CPU_SendCookie(const string& cookie, unsigned short nService)
715 : CSrvPacketTcp(ICQ_CHNxNEW)
716 {
717 m_nService = nService;
718 m_nSize = cookie.size() + 8;
719 initSequence(m_nService);
720 InitBuffer();
721
722 buffer->PackUnsignedLongBE(0x00000001);
723 buffer->PackTLV(0x0006, cookie.size(), cookie.c_str());
724 }
725
~CPU_SendCookie()726 CPU_SendCookie::~CPU_SendCookie()
727 {
728 // Empty
729 }
730
731 //-----ListRequestRights-----------------------------------------------------
CPU_ListRequestRights()732 CPU_ListRequestRights::CPU_ListRequestRights()
733 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_REQUESTxRIGHTS)
734 {
735 m_nSize += 6;
736 InitBuffer();
737
738 buffer->PackUnsignedLongBE(0x000b0002);
739 buffer->PackUnsignedShortBE(0x000f);
740 }
741
742 //-----ImICQ-----------------------------------------------------------------
CPU_ImICQ()743 CPU_ImICQ::CPU_ImICQ()
744 : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_IMxICQ)
745 {
746 m_nSize += 40;
747 InitBuffer();
748
749 // setting communication parameters (key / value pair) ?
750 // seems to say which channels should be enabled
751 buffer->PackUnsignedLongBE(0x00010004);
752 buffer->PackUnsignedLongBE(0x00130004);
753 buffer->PackUnsignedLongBE(0x00020001);
754 buffer->PackUnsignedLongBE(0x00030001);
755 buffer->PackUnsignedLongBE(0x00150001);
756 buffer->PackUnsignedLongBE(0x00040001);
757 buffer->PackUnsignedLongBE(0x00060001);
758 buffer->PackUnsignedLongBE(0x00090001);
759 buffer->PackUnsignedLongBE(0x000a0001);
760 buffer->PackUnsignedLongBE(0x000b0001);
761 }
762
CPU_ImICQ(unsigned short VerArray[][2],unsigned short NumVer,unsigned short nService)763 CPU_ImICQ::CPU_ImICQ(unsigned short VerArray[][2], unsigned short NumVer,
764 unsigned short nService)
765 : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_IMxICQ)
766 {
767 m_nService = nService;
768 m_nSize += NumVer * 4;
769 InitBuffer();
770
771 for (int i = 0; i < NumVer; i++)
772 {
773 buffer->PackUnsignedShortBE(VerArray[i][0]);
774 buffer->PackUnsignedShortBE(VerArray[i][1]);
775 }
776 }
777
778 //-----ImICQMode-------------------------------------------------------------
CPU_ICQMode(unsigned short channel,unsigned long flags)779 CPU_ICQMode::CPU_ICQMode(unsigned short channel, unsigned long flags)
780 : CPU_CommonFamily(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SETxICQxMODE)
781 {
782 m_nSize += 16;
783
784 InitBuffer();
785
786 /* channel 0 sets default options for channels we did not specifically
787 initialize */
788 buffer->PackUnsignedShortBE(channel);
789 buffer->PackUnsignedLongBE(flags); // the meanings of the flags are unknown
790 buffer->PackUnsignedShortBE(8000); // max message size
791 buffer->PackUnsignedShortBE(999); // max sender warning level
792 buffer->PackUnsignedShortBE(999); // max receiver warning level
793 buffer->PackUnsignedShortBE(0); // min message interval
794 buffer->PackUnsignedShortBE(0); // unknown
795 }
796
797 //-----RateAck-----------------------------------------------------------------
CPU_RateAck(unsigned short nService)798 CPU_RateAck::CPU_RateAck(unsigned short nService)
799 : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSND_RATE_ACK)
800 {
801 m_nService = nService;
802 m_nSize += 10;
803
804 InitBuffer();
805
806 buffer->PackUnsignedLongBE(0x00010002);
807 buffer->PackUnsignedLongBE(0x00030004);
808 buffer->PackUnsignedShortBE(0x0005);
809 }
810
811 //-----UINSettings-----------------------------------------------------------
CPU_CapabilitySettings()812 CPU_CapabilitySettings::CPU_CapabilitySettings()
813 : CPU_CommonFamily(ICQ_SNACxFAM_LOCATION, ICQ_SNACxLOC_SETxUSERxINFO)
814 {
815 char data[8][CAP_LENGTH];
816 m_nSize += 4 + sizeof(data);
817 InitBuffer();
818
819 memcpy(data[0], ICQ_CAPABILITY_DIRECT, CAP_LENGTH);
820 memcpy(data[1], ICQ_CAPABILITY_SRVxRELAY, CAP_LENGTH);
821 memcpy(data[2], ICQ_CAPABILITY_TYPING, CAP_LENGTH);
822 memcpy(data[3], ICQ_CAPABILITY_LICQxVER, CAP_LENGTH);
823 memcpy(data[4], ICQ_CAPABILITY_AIMxINTER, CAP_LENGTH);
824 memcpy(data[5], ICQ_CAPABILITY_RTFxMSGS, CAP_LENGTH);
825 memcpy(data[6], ICQ_CAPABILITY_ICHAT, CAP_LENGTH);
826 memcpy(data[7], ICQ_CAPABILITY_BART, CAP_LENGTH);
827
828 // Send our licq version
829 data[3][12] = Licq::extractMajorVersion(LICQ_VERSION);
830 data[3][13] = Licq::extractMinorVersion(LICQ_VERSION);
831 data[3][14] = Licq::extractReleaseVersion(LICQ_VERSION);
832 if (Licq::gDaemon.haveCryptoSupport())
833 data[3][15] = 1;
834 buffer->PackTLV(0x05, sizeof(data), (char *)data);
835 }
836
837 //-----RequestBuddyIcon---------------------------------------------------------
CPU_RequestBuddyIcon(const string & accountId,unsigned short _nBuddyIconType,char _nBuddyIconHashType,const string & buddyIconHash,unsigned short nService)838 CPU_RequestBuddyIcon::CPU_RequestBuddyIcon(const string& accountId,
839 unsigned short _nBuddyIconType, char _nBuddyIconHashType,
840 const string& buddyIconHash, unsigned short nService)
841 : CPU_CommonFamily(ICQ_SNACxFAM_BART, ICQ_SNACxBART_DOWNLOADxREQUEST)
842 {
843 m_nService = nService;
844 m_nSize += 6 + accountId.size() + buddyIconHash.size();
845
846 InitBuffer();
847
848 buffer->PackChar(accountId.size());
849 buffer->pack(accountId);
850 buffer->PackChar(0x01); // number of hashes being requested in this packet
851 buffer->PackUnsignedShortBE(_nBuddyIconType);
852 buffer->PackChar(_nBuddyIconHashType);
853 buffer->PackChar(buddyIconHash.size());
854 buffer->pack(buddyIconHash);
855 }
856
857 //-----RequestService-----------------------------------------------------------
CPU_RequestService(unsigned short nFam)858 CPU_RequestService::CPU_RequestService(unsigned short nFam)
859 : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSUB_NEW_SERVICE)
860 {
861 m_nSize += 2;
862
863 InitBuffer();
864
865 buffer->PackUnsignedShortBE(nFam);
866 }
867
868 //-----SetPrivacy---------------------------------------------------------------
CPU_SetPrivacy(unsigned char _cPrivacy)869 CPU_SetPrivacy::CPU_SetPrivacy(unsigned char _cPrivacy)
870 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxUPD_GROUP)
871 {
872 m_nSize += 15;
873
874 InitBuffer();
875
876 unsigned short nPDINFO;
877 {
878 OwnerReadGuard o(gIcqProtocol.ownerId());
879 nPDINFO = o->GetPDINFO();
880 }
881
882 buffer->PackUnsignedLongBE(0);
883 buffer->PackUnsignedShortBE(nPDINFO);
884 buffer->PackUnsignedLongBE(0x00040005);
885 buffer->PackUnsignedLongBE(0x00CA0001); // Privacy TLV
886 buffer->PackChar(_cPrivacy);
887 }
888
889 //-----SetStatus----------------------------------------------------------------
CPU_SetStatus(unsigned long _nNewStatus)890 CPU_SetStatus::CPU_SetStatus(unsigned long _nNewStatus)
891 : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_SETxSTATUS)
892 {
893 m_nNewStatus = _nNewStatus;
894
895 bool bInvis = _nNewStatus & ICQ_STATUS_FxPRIVATE;
896
897 m_nSize += 8;
898 if (!bInvis)
899 m_nSize += 47;
900
901 InitBuffer();
902
903 //ICQ 4.0 doesn't like this
904 m_nNewStatus &= ~(ICQ_STATUS_FxPFM | ICQ_STATUS_FxPFMxAVAILABLE);
905
906 buffer->PackUnsignedLongBE(0x00060004); // TLV
907 buffer->PackUnsignedLongBE(m_nNewStatus); // ICQ status
908 if (!bInvis)
909 {
910 buffer->PackUnsignedLongBE(0x000C0025); // TLV
911 buffer->PackUnsignedLong(s_nLocalIp); // direct connection info
912 buffer->PackUnsignedLongBE(s_nLocalPort);
913 buffer->PackChar(gIcqProtocol.directMode() ? MODE_DIRECT : MODE_INDIRECT);
914 buffer->PackUnsignedShortBE(ICQ_VERSION_TCP);
915 buffer->PackUnsignedLongBE(0x00000000); // local direction conn cookie
916 buffer->PackUnsignedLongBE(0x00000050);
917 buffer->PackUnsignedLongBE(0x00000003);
918 buffer->PackUnsignedLongBE(0);
919 // some kind of timestamp ?
920 buffer->PackUnsignedLongBE(0);
921 buffer->PackUnsignedLongBE(0);
922 buffer->PackUnsignedShort(0);
923
924 buffer->PackUnsignedLongBE(0x00080002); // TLV
925 buffer->PackUnsignedShort(0); // Error code
926 }
927 }
928
CPU_SetStatusFamily()929 CPU_SetStatusFamily::CPU_SetStatusFamily()
930 : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_SETxSTATUS)
931 {
932 m_nSize += 55;
933 }
934
InitBuffer()935 void CPU_SetStatusFamily::InitBuffer()
936 {
937 CPU_CommonFamily::InitBuffer();
938
939 //ICQ 4.0 doesn't like this
940 m_nNewStatus &= ~(ICQ_STATUS_FxPFM | ICQ_STATUS_FxPFMxAVAILABLE);
941
942 buffer->PackUnsignedLongBE(0x00060004); // TLV
943 buffer->PackUnsignedLongBE(m_nNewStatus); // ICQ status
944 buffer->PackUnsignedLongBE(0x00080002); // TLV
945 buffer->PackUnsignedShortBE(0); // error code ?
946 buffer->PackUnsignedLongBE(0x000c0025); // TLV
947 buffer->PackUnsignedLong(s_nLocalIp); // direct connection info
948 buffer->PackUnsignedLongBE(s_nLocalPort);
949 buffer->PackChar(gIcqProtocol.directMode() ? MODE_DIRECT : MODE_INDIRECT);
950 buffer->PackUnsignedShortBE(ICQ_VERSION_TCP);
951 buffer->PackUnsignedLongBE(0x00000000); // local direction conn cookie
952 buffer->PackUnsignedLongBE(0x00000050);
953 buffer->PackUnsignedLongBE(0x00000003);
954
955 // build date of the core DLL of Mirabilis ICQ
956 // we use that to tell other users that we're Licq
957 // ICQ99b: 0x385BFAAC;
958
959 /* should eventually switch to some other way to identify licq, probably
960 use capabilities */
961 OwnerReadGuard o(gIcqProtocol.ownerId());
962 if (Licq::gDaemon.haveCryptoSupport())
963 buffer->PackUnsignedLongBE(LICQ_WITHSSL | LICQ_VERSION);
964 else
965 buffer->PackUnsignedLongBE(LICQ_WITHOUTSSL | LICQ_VERSION);
966 // some kind of timestamp ?
967 buffer->PackUnsignedLongBE(o->ClientStatusTimestamp());
968 buffer->PackUnsignedLongBE(o->ClientInfoTimestamp());
969 buffer->PackUnsignedShortBE(0x0000);
970 }
971
CPU_SetLogonStatus(unsigned long _nNewStatus)972 CPU_SetLogonStatus::CPU_SetLogonStatus(unsigned long _nNewStatus)
973 : CPU_SetStatusFamily()
974 {
975 m_nNewStatus = _nNewStatus;
976
977 InitBuffer();
978 }
979
CPU_UpdateInfoTimestamp(const uint8_t * GUID)980 CPU_UpdateInfoTimestamp::CPU_UpdateInfoTimestamp(const uint8_t* GUID)
981 : CPU_SetStatusFamily()
982 {
983 unsigned long timestamp;
984 {
985 OwnerReadGuard o(gIcqProtocol.ownerId());
986 m_nNewStatus = IcqProtocol::addStatusFlags(IcqProtocol::icqStatusFromStatus(o->status()), *o);
987 timestamp = o->ClientInfoTimestamp();
988 }
989
990 m_nSize += 4 + 1 + 4 + 6 + GUID_LENGTH + 4 + 1;
991
992 InitBuffer();
993
994 buffer->PackUnsignedLongBE(0x00110022); // TLV
995 buffer->PackChar(2); // info update
996 buffer->PackUnsignedLong(timestamp);
997 buffer->PackUnsignedShort(2); //Unknown
998 buffer->PackUnsignedShort(1); //Unknown
999 buffer->PackUnsignedShort(1); //Unknown
1000 buffer->Pack(GUID, GUID_LENGTH);
1001 buffer->PackUnsignedLong(timestamp);
1002 buffer->PackChar(0); //No info follows ??
1003 }
1004
CPU_UpdateStatusTimestamp(const uint8_t * GUID,unsigned long nState,unsigned long nStatus)1005 CPU_UpdateStatusTimestamp::CPU_UpdateStatusTimestamp(const uint8_t* GUID,
1006 unsigned long nState,
1007 unsigned long nStatus)
1008 : CPU_SetStatusFamily()
1009 {
1010 unsigned long clientTime;
1011 {
1012 OwnerReadGuard o(gIcqProtocol.ownerId());
1013 m_nNewStatus = nStatus != ICQ_STATUS_OFFLINE ? nStatus :
1014 IcqProtocol::addStatusFlags(IcqProtocol::icqStatusFromStatus(o->status()), *o);
1015 clientTime = o->ClientStatusTimestamp();
1016 }
1017
1018 m_nSize += 4 + 1 + 4 + 6 + GUID_LENGTH + 1 + 4 + 4 + 6;
1019
1020 InitBuffer();
1021
1022 buffer->PackUnsignedLongBE(0x0011002C); // TLV
1023 buffer->PackChar(3); // info update
1024 buffer->PackUnsignedLong(clientTime);
1025 buffer->PackUnsignedShort(0); //Unknown
1026 buffer->PackUnsignedShort(1); //Unknown
1027 buffer->PackUnsignedShort(1); //Unknown
1028 buffer->Pack(GUID, GUID_LENGTH);
1029 buffer->PackChar(1); //Unknown
1030 buffer->PackUnsignedLong(nState);
1031 buffer->PackUnsignedLong(clientTime);
1032 buffer->PackUnsignedShort(0); //Unknown
1033 buffer->PackUnsignedShort(0); //Unknown
1034 buffer->PackUnsignedShort(1); //Unknown
1035 }
1036
CPU_UpdateTimestamp()1037 CPU_UpdateTimestamp::CPU_UpdateTimestamp()
1038 : CPU_SetStatusFamily()
1039 {
1040 OwnerReadGuard o(gIcqProtocol.ownerId());
1041 m_nNewStatus = IcqProtocol::addStatusFlags(IcqProtocol::icqStatusFromStatus(o->status()), *o);
1042
1043 m_nSize += 4 + 1 + 4;
1044
1045 InitBuffer();
1046
1047 buffer->PackUnsignedLongBE(0x00110005); // TLV
1048 buffer->PackChar(0); // server info update
1049 buffer->PackUnsignedLong(o->ClientTimestamp());
1050 }
1051
1052 //-----GenericUinList-----------------------------------------------------------
CPU_GenericUinList(const StringList & users,unsigned short family,unsigned short Subtype)1053 CPU_GenericUinList::CPU_GenericUinList(const StringList& users, unsigned short family, unsigned short Subtype)
1054 : CPU_CommonFamily(family, Subtype)
1055 {
1056 char len[2];
1057 len[1] = '\0';
1058 int nLen = 0;
1059 StringList::const_iterator it;
1060 for (it = users.begin(); it != users.end(); ++it)
1061 nLen += it->size() + 1;
1062
1063 string contacts;
1064
1065 for (it = users.begin(); it != users.end(); ++it) {
1066 len[0] = it->size();
1067 contacts += len;
1068 contacts += *it;
1069 }
1070
1071 m_nSize += contacts.size();
1072 InitBuffer();
1073
1074 buffer->pack(contacts);
1075 }
1076
CPU_GenericUinList(const string & accountId,unsigned short family,unsigned short Subtype)1077 CPU_GenericUinList::CPU_GenericUinList(const string& accountId, unsigned short family, unsigned short Subtype)
1078 : CPU_CommonFamily(family, Subtype)
1079 {
1080 m_nSize += accountId.size()+1;
1081 InitBuffer();
1082
1083 buffer->PackChar(accountId.size());
1084 buffer->pack(accountId);
1085 }
1086
CPU_GenericUinList(unsigned long _nUin,unsigned short family,unsigned short Subtype)1087 CPU_GenericUinList::CPU_GenericUinList(unsigned long _nUin, unsigned short family, unsigned short Subtype)
1088 : CPU_CommonFamily(family, Subtype)
1089 {
1090 char uin[13];
1091 uin[12] = '\0';
1092 int n = snprintf(uin, 12, "%lu", _nUin);
1093
1094 m_nSize += n+1;
1095 InitBuffer();
1096
1097 buffer->PackChar(n);
1098 buffer->Pack(uin, n);
1099 }
1100
CPU_GenericFamily(unsigned short Family,unsigned short SubType,unsigned short nService)1101 CPU_GenericFamily::CPU_GenericFamily(unsigned short Family, unsigned short SubType,
1102 unsigned short nService)
1103 : CPU_CommonFamily(Family, SubType)
1104 {
1105 m_nService = nService;
1106 m_nSize += 0;
1107 InitBuffer();
1108 }
1109
~CPU_GenericFamily()1110 CPU_GenericFamily::~CPU_GenericFamily()
1111 {
1112 // Empty
1113 }
1114
CPU_CommonFamily(unsigned short Family,unsigned short SubType)1115 CPU_CommonFamily::CPU_CommonFamily(unsigned short Family, unsigned short SubType)
1116 : CSrvPacketTcp(ICQ_CHNxDATA)
1117 {
1118 m_nSize += 10;
1119
1120 m_nFamily = Family;
1121 m_nSubType = SubType;
1122 }
1123
~CPU_CommonFamily()1124 CPU_CommonFamily::~CPU_CommonFamily()
1125 {
1126 // Empty
1127 }
1128
InitBuffer()1129 void CPU_CommonFamily::InitBuffer()
1130 {
1131 CSrvPacketTcp::InitBuffer();
1132
1133 buffer->PackUnsignedShortBE(m_nFamily);
1134 buffer->PackUnsignedShortBE(m_nSubType);
1135 buffer->PackUnsignedLongBE(0x00000000); // flags
1136 buffer->PackUnsignedShortBE(m_nSubSequence);
1137 }
1138
CPU_ClientReady()1139 CPU_ClientReady::CPU_ClientReady()
1140 : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSUB_READYxCLIENT)
1141 {
1142 #if 0
1143 m_nSize += 80;
1144
1145 InitBuffer();
1146 buffer->PackUnsignedLongBE(0x00010003);
1147 buffer->PackUnsignedLongBE(0x0110047b);
1148 buffer->PackUnsignedLongBE(0x00130002);
1149 buffer->PackUnsignedLongBE(0x0110047b);
1150 buffer->PackUnsignedLongBE(0x00020001);
1151
1152 buffer->PackUnsignedLongBE(0x0101047b);
1153 buffer->PackUnsignedLongBE(0x00030001);
1154 buffer->PackUnsignedLongBE(0x0110047b);
1155 buffer->PackUnsignedLongBE(0x00150001);
1156 buffer->PackUnsignedLongBE(0x0110047b);
1157
1158 buffer->PackUnsignedLongBE(0x00040001);
1159 buffer->PackUnsignedLongBE(0x0110047b);
1160 buffer->PackUnsignedLongBE(0x00060001);
1161 buffer->PackUnsignedLongBE(0x0110047b);
1162 buffer->PackUnsignedLongBE(0x00090001);
1163
1164 buffer->PackUnsignedLongBE(0x0110047b);
1165 buffer->PackUnsignedLongBE(0x000a0001);
1166 buffer->PackUnsignedLongBE(0x0110047b);
1167 buffer->PackUnsignedLongBE(0x000b0001);
1168 buffer->PackUnsignedLongBE(0x0110047b);
1169 #else
1170 m_nSize += 80;
1171
1172 InitBuffer();
1173
1174 buffer->PackUnsignedLongBE(0x00010004);
1175 buffer->PackUnsignedLongBE(0x011008e4);
1176 buffer->PackUnsignedLongBE(0x00020001);
1177 buffer->PackUnsignedLongBE(0x011008e4);
1178 buffer->PackUnsignedLongBE(0x00030001);
1179 buffer->PackUnsignedLongBE(0x011008e4);
1180 buffer->PackUnsignedLongBE(0x00150001);
1181 buffer->PackUnsignedLongBE(0x011008e4);
1182 buffer->PackUnsignedLongBE(0x00040001);
1183 buffer->PackUnsignedLongBE(0x011008e4);
1184 buffer->PackUnsignedLongBE(0x00060001);
1185 buffer->PackUnsignedLongBE(0x011008e4);
1186 buffer->PackUnsignedLongBE(0x00090001);
1187 buffer->PackUnsignedLongBE(0x011008e4);
1188 buffer->PackUnsignedLongBE(0x000a0001);
1189 buffer->PackUnsignedLongBE(0x011008e4);
1190 buffer->PackUnsignedLongBE(0x00130004);
1191 buffer->PackUnsignedLongBE(0x011008e4);
1192 buffer->PackUnsignedLongBE(0x000b0004);
1193 buffer->PackUnsignedLongBE(0x011008e4);
1194 #endif
1195 }
1196
CPU_ClientReady(unsigned short VerArray[][4],unsigned short NumVer,unsigned short nService)1197 CPU_ClientReady::CPU_ClientReady(unsigned short VerArray[][4], unsigned short NumVer,
1198 unsigned short nService)
1199 : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSUB_READYxCLIENT)
1200 {
1201 m_nService = nService;
1202 m_nSize += NumVer * 8;
1203 InitBuffer();
1204
1205 for (int i = 0; i < NumVer; i++)
1206 {
1207 buffer->PackUnsignedShortBE(VerArray[i][0]);
1208 buffer->PackUnsignedShortBE(VerArray[i][1]);
1209 buffer->PackUnsignedShortBE(VerArray[i][2]);
1210 buffer->PackUnsignedShortBE(VerArray[i][3]);
1211 }
1212 }
1213
CPU_AckNameInfo()1214 CPU_AckNameInfo::CPU_AckNameInfo()
1215 : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSND_NAMExINFOxACK)
1216 {
1217 m_nSize += 4;
1218
1219 InitBuffer();
1220
1221 buffer->PackUnsignedLongBE(0x00000000);
1222 }
1223
1224 //-----TypingNotification--------------------------------------------------
CPU_TypingNotification(const string & accountId,bool bActive)1225 CPU_TypingNotification::CPU_TypingNotification(const string& accountId, bool bActive)
1226 : CPU_CommonFamily(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_TYPING)
1227 {
1228 unsigned short nTyping = bActive ? ICQ_TYPING_ACTIVE : ICQ_TYPING_INACTIVEx0;
1229 m_nSize += 13 + accountId.size();
1230
1231 InitBuffer();
1232
1233 buffer->PackUnsignedLongBE(0x00000000);
1234 buffer->PackUnsignedLongBE(0x00000000);
1235 buffer->PackUnsignedShortBE(0x0001);
1236 buffer->PackChar(accountId.size());
1237 buffer->pack(accountId);
1238 buffer->PackUnsignedShortBE(nTyping);
1239 }
1240
1241 //-----CheckInvisible------------------------------------------------------
CPU_CheckInvisible(const string & accountId)1242 CPU_CheckInvisible::CPU_CheckInvisible(const string& accountId)
1243 : CPU_CommonFamily(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SENDxSERVER)
1244 {
1245 m_nSize += 15 + accountId.size();
1246
1247 InitBuffer();
1248
1249 buffer->PackUnsignedLongBE(0);
1250 buffer->PackUnsignedLongBE((unsigned long)m_nSequence);
1251 buffer->PackUnsignedShortBE(0x0002);
1252 buffer->PackChar(accountId.size());
1253 buffer->pack(accountId);
1254 buffer->PackUnsignedLongBE(0x00060000);
1255 }
1256
1257 //-----ThroughServer-------------------------------------------------------
CPU_ThroughServer(const string & accountId,unsigned char msgType,const string & message,unsigned short nCharset,bool bOffline)1258 CPU_ThroughServer::CPU_ThroughServer(const string& accountId,
1259 unsigned char msgType, const string& message, unsigned short nCharset, bool bOffline)
1260 : CPU_CommonFamily(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SENDxSERVER)
1261 {
1262 m_nSubCommand = msgType;
1263
1264 int msgLen = message.size();
1265 unsigned short nFormat = 0;
1266 int nTypeLen = 0, nTLVType = 0;
1267 Buffer tlvData;
1268
1269 switch (msgType)
1270 {
1271 case ICQ_CMDxSUB_MSG:
1272 nTypeLen = 13+msgLen;
1273 nFormat = 1;
1274 break;
1275
1276 case ICQ_CMDxSUB_URL:
1277 case ICQ_CMDxSUB_CONTACTxLIST:
1278 case ICQ_CMDxSUB_AUTHxGRANTED:
1279 case ICQ_CMDxSUB_AUTHxREFUSED:
1280 case ICQ_CMDxSUB_AUTHxREQUEST:
1281 case ICQ_CMDxSUB_ADDEDxTOxLIST:
1282 nTypeLen = 9+msgLen;
1283 nFormat = 4;
1284 break;
1285
1286 default:
1287 nTypeLen = msgLen = 0;
1288 gLog.warning(tr("Command not implemented yet (%04X)."), msgType);
1289 return;
1290 }
1291
1292 m_nSize += 11 + nTypeLen + accountId.size() + 4; // 11 all bytes pre-tlv
1293 // 8 fom tlv type, tlv len
1294 if (bOffline)
1295 m_nSize += 4;
1296
1297 InitBuffer();
1298
1299 buffer->PackUnsignedLongBE(0); // upper 4 bytes of message id
1300 buffer->PackUnsignedLongBE(0); // lower 4 bytes of message id
1301 buffer->PackUnsignedShortBE(nFormat); // message format
1302 buffer->PackChar(accountId.size());
1303 buffer->pack(accountId);
1304
1305 tlvData.Create(nTypeLen);
1306
1307 switch (nFormat)
1308 {
1309 case 1:
1310 nTLVType = 0x02;
1311
1312 tlvData.PackUnsignedLongBE(0x05010001);
1313 tlvData.PackUnsignedShortBE(0x0101);
1314 tlvData.PackChar(0x01);
1315 tlvData.PackUnsignedShortBE(msgLen + 4);
1316 tlvData.PackUnsignedShortBE(nCharset);
1317 tlvData.PackUnsignedShortBE(0);
1318 tlvData.Pack(message.c_str(), msgLen);
1319 break;
1320
1321 case 4:
1322 nTLVType = 0x05;
1323
1324 tlvData.PackUnsignedLong(gIcqProtocol.icqOwnerUin());
1325 tlvData.PackChar(msgType);
1326 tlvData.PackChar(0); // message flags
1327 tlvData.packShortNullStringLE(message);
1328 break;
1329 }
1330
1331 buffer->PackTLV(nTLVType, nTypeLen, &tlvData);
1332 if (bOffline)
1333 buffer->PackUnsignedLongBE(0x00060000); // tlv type: 6, tlv len: 0
1334 }
1335
1336 //-----Type2Message-------------------------------------------------------------
CPU_Type2Message(const User * u,bool _bAck,bool _bDirectInfo,const uint8_t * cap,unsigned long nMsgID1,unsigned long nMsgID2)1337 CPU_Type2Message::CPU_Type2Message(const User* u, bool _bAck, bool _bDirectInfo,
1338 const uint8_t *cap,
1339 unsigned long nMsgID1,
1340 unsigned long nMsgID2)
1341 : CPU_CommonFamily(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SENDxSERVER)
1342 {
1343 int nUinLen = u->accountId().size();
1344 unsigned short nDirectInfo = _bDirectInfo ? 14 : 0; //size of di
1345
1346 m_nSize += 55 + nUinLen + nDirectInfo;
1347
1348 m_pUser = u;
1349 m_bAck = _bAck;
1350 m_bDirectInfo = _bDirectInfo;
1351 m_nMsgID[0] = nMsgID1;
1352 m_nMsgID[1] = nMsgID2;
1353
1354 memcpy(m_cap, cap, CAP_LENGTH);
1355 m_nExtraLen = 0;
1356 }
1357
InitBuffer()1358 void CPU_Type2Message::InitBuffer()
1359 {
1360 CPU_CommonFamily::InitBuffer();
1361
1362 Licq::OwnerReadGuard o(gIcqProtocol.ownerId());
1363
1364 int nUinLen = m_pUser->accountId().size();
1365
1366 unsigned long nID1, nID2;
1367 unsigned short nDirectInfo = m_bDirectInfo ? 14 : 0; // size of direct info
1368
1369 if (m_bAck)
1370 {
1371 nID1 = m_nMsgID[0];
1372 nID2 = m_nMsgID[1];
1373 }
1374 else
1375 {
1376 nID1 = 0;
1377 nID2 = m_nSubSequence;
1378 }
1379
1380 buffer->PackUnsignedLongBE(nID1); // upper 4 bytes of message id
1381 buffer->PackUnsignedLongBE(nID2); // lower 4 bytes of message id
1382 buffer->PackUnsignedShortBE(0x02); // message format
1383 buffer->PackChar(nUinLen);
1384 buffer->pack(m_pUser->accountId());
1385
1386 buffer->PackUnsignedShortBE(0x0005); // tlv - message info
1387 buffer->PackUnsignedShortBE(m_nSize - 25 - nUinLen - m_nExtraLen);
1388 buffer->PackUnsignedShortBE(0);
1389 buffer->PackUnsignedLongBE(nID1); // upper 4 bytes of message id again
1390 buffer->PackUnsignedLongBE(nID2); // lower 4 bytes of message id again
1391 buffer->Pack(m_cap, CAP_LENGTH);
1392 buffer->PackUnsignedLongBE(0x000A0002); // tlv - ack or not
1393 buffer->PackUnsignedShortBE((m_bAck ? 2 : 1));
1394
1395 buffer->PackUnsignedLongBE(0x000F0000); // tlv - empty
1396
1397 if (nDirectInfo)
1398 {
1399 buffer->PackUnsignedLongBE(0x00030004); // tlv - internal ip
1400 buffer->PackUnsignedLong(o->IntIp());
1401 buffer->PackUnsignedLongBE(0x00050002); // tlv - listening port
1402 buffer->PackUnsignedShort(o->Port());
1403 }
1404 buffer->PackUnsignedShortBE(0x2711); // tlv - more message info
1405 buffer->PackUnsignedShortBE(m_nSize - 29 - nUinLen - 36 - nDirectInfo -
1406 m_nExtraLen);
1407 }
1408
1409 //-----ReverseConnect-----------------------------------------------------------
CPU_ReverseConnect(const User * u,unsigned long nLocalIP,unsigned short nLocalPort,unsigned short nRemotePort)1410 CPU_ReverseConnect::CPU_ReverseConnect(const User* u, unsigned long nLocalIP,
1411 unsigned short nLocalPort,
1412 unsigned short nRemotePort)
1413 : CPU_Type2Message(u, false, false, ICQ_CAPABILITY_DIRECT)
1414 {
1415 m_nSize += 4 + 4 + 4 + 1 + 4 + 4 + 2 + 4;
1416 // m_nExtraLen += 4; m_nSize += 4;
1417
1418 CPU_Type2Message::InitBuffer();
1419
1420 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
1421 buffer->PackUnsignedLong(nLocalIP);
1422 buffer->PackUnsignedLong(nLocalPort);
1423 buffer->PackChar(MODE_DIRECT); /* why would you set it to anything else?
1424 if you do icq just sends you back the
1425 same ip and port number to connect to */
1426 buffer->PackUnsignedLong(nRemotePort);
1427 buffer->PackUnsignedLong(nLocalPort);
1428 buffer->PackUnsignedShort(ICQ_VERSION_TCP);
1429 buffer->PackUnsignedLong(m_nSubSequence);
1430 // buffer->PackUnsignedLongBE(0x00030000);
1431 }
1432
CPU_ReverseConnectFailed(const string & accountId,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nFailedPort,unsigned short nOurPort,unsigned long nConnectID)1433 CPU_ReverseConnectFailed::CPU_ReverseConnectFailed(const string& accountId,
1434 unsigned long nMsgID1,
1435 unsigned long nMsgID2,
1436 unsigned short nFailedPort,
1437 unsigned short nOurPort,
1438 unsigned long nConnectID)
1439 : CPU_CommonFamily(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SERVERxREPLYxMSG)
1440 {
1441 m_nSize += 8 + 2 + 1 + accountId.size() + 2 + 4 + 4 + 4 + 2 + 4;
1442
1443 InitBuffer();
1444
1445 buffer->PackUnsignedLongBE(nMsgID1);
1446 buffer->PackUnsignedLongBE(nMsgID2);
1447 buffer->PackUnsignedShortBE(0x0002);
1448 buffer->PackChar(accountId.size());
1449 buffer->pack(accountId);
1450 buffer->PackUnsignedShortBE(0x0003);
1451 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
1452 buffer->PackUnsignedLong(nFailedPort);
1453 buffer->PackUnsignedLong(nOurPort);
1454 buffer->PackUnsignedShort(ICQ_VERSION_TCP);
1455 buffer->PackUnsignedLong(nConnectID);
1456 }
1457
1458 //-----PluginMessage-----------------------------------------------------------
CPU_PluginMessage(const User * u,bool bAck,const uint8_t * PluginGUID,unsigned long nMsgID1,unsigned long nMsgID2)1459 CPU_PluginMessage::CPU_PluginMessage(const User* u, bool bAck,
1460 const uint8_t* PluginGUID,
1461 unsigned long nMsgID1,
1462 unsigned long nMsgID2)
1463 : CPU_Type2Message(u, bAck, false, ICQ_CAPABILITY_SRVxRELAY, nMsgID1, nMsgID2)
1464 {
1465 m_nSize += 49;
1466
1467 memcpy(m_PluginGUID, PluginGUID, GUID_LENGTH);
1468 }
1469
InitBuffer()1470 void CPU_PluginMessage::InitBuffer()
1471 {
1472 CPU_Type2Message::InitBuffer();
1473
1474 buffer->PackUnsignedShort(0x001B); // len
1475 buffer->PackUnsignedShort(m_pUser->ConnectionVersion());
1476 buffer->Pack(m_PluginGUID, GUID_LENGTH);
1477 buffer->PackUnsignedLong(0x00000003); //unknown
1478 buffer->PackChar(0); //unknown
1479 buffer->PackUnsignedShort(m_nSequence);
1480 buffer->PackUnsignedShort(0x0012);
1481 buffer->PackUnsignedShort(m_nSequence);
1482 buffer->PackUnsignedLong(0);
1483 buffer->PackUnsignedLong(0);
1484 buffer->PackUnsignedLong(0);
1485 buffer->PackUnsignedShort(m_bAck ? 0 : 1);
1486 buffer->PackUnsignedShort(0);
1487 }
1488
1489 //-----Send error reply------------------------------------------------------
CPU_PluginError(const ICQUser * u,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nSequence,const uint8_t * cap)1490 CPU_PluginError::CPU_PluginError(const ICQUser* u, unsigned long nMsgID1,
1491 unsigned long nMsgID2,
1492 unsigned short nSequence, const uint8_t* cap)
1493 : CPU_AckThroughServer(u, nMsgID1, nMsgID2, nSequence, 0, true, 0, cap)
1494 {
1495 // this is a bit of a hack
1496 myMessage[0] = ICQ_PLUGIN_ERROR;
1497 InitBuffer();
1498 }
1499
1500 //-----Send info plugin request------------------------------------------------
CPU_InfoPluginReq(const User * u,const uint8_t * GUID,unsigned long nTime)1501 CPU_InfoPluginReq::CPU_InfoPluginReq(const User* u, const uint8_t* GUID,
1502 unsigned long nTime)
1503 : CPU_PluginMessage(u, false, PLUGIN_INFOxMANAGER)
1504 {
1505 m_nSize += 27;
1506 memcpy(m_ReqGUID, GUID, GUID_LENGTH);
1507
1508 InitBuffer();
1509 buffer->PackUnsignedShort(2);
1510 buffer->PackUnsignedShort(1);
1511 buffer->PackChar(0);
1512 buffer->Pack(GUID, GUID_LENGTH);
1513 buffer->PackUnsignedLong(nTime);
1514 }
1515
1516 //-----Send info plugin list---------------------------------------------------
CPU_InfoPluginListResp(const ICQUser * u,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nSequence)1517 CPU_InfoPluginListResp::CPU_InfoPluginListResp(const ICQUser *u,
1518 unsigned long nMsgID1,
1519 unsigned long nMsgID2,
1520 unsigned short nSequence)
1521 : CPU_AckThroughServer(u, nMsgID1, nMsgID2, nSequence, 0, true,
1522 ICQ_TCPxMSG_URGENT2, PLUGIN_INFOxMANAGER)
1523 {
1524 unsigned long num_plugins = sizeof(IcqProtocol::info_plugins)/sizeof(struct PluginList);
1525
1526 unsigned long nLen;
1527 if (num_plugins == 0)
1528 nLen = 0;
1529 else
1530 {
1531 nLen = 4 + 4;
1532 for (unsigned long i = 0; i < num_plugins; i ++)
1533 {
1534 nLen += GUID_LENGTH + 2 + 2 + 4 + strlen(IcqProtocol::info_plugins[i].name)
1535 + 4 + strlen(IcqProtocol::info_plugins[i].description) + 4;
1536 }
1537 }
1538
1539 m_nSize += 2 + 2 + 4 + 4 + nLen;
1540
1541 InitBuffer();
1542
1543 buffer->PackUnsignedShort(0);
1544 buffer->PackUnsignedShort(1);
1545
1546 {
1547 OwnerReadGuard o(gIcqProtocol.ownerId());
1548 buffer->PackUnsignedLong(o->ClientInfoTimestamp());
1549 }
1550 buffer->PackUnsignedLong(nLen);
1551 if (nLen != 0)
1552 {
1553 buffer->PackUnsignedLong(ICQ_PLUGIN_RESP_INFOxLIST);
1554 buffer->PackUnsignedLong(num_plugins);
1555 for (unsigned long i = 0; i < num_plugins; i++)
1556 {
1557 buffer->packRaw(IcqProtocol::info_plugins[i].guid, GUID_LENGTH);
1558
1559 buffer->PackUnsignedShort(0); //Unknown
1560 buffer->PackUnsignedShort(1); //Unknown
1561
1562 buffer->packString32LE(IcqProtocol::info_plugins[i].name,
1563 strlen(IcqProtocol::info_plugins[i].name));
1564
1565 buffer->packString32LE(IcqProtocol::info_plugins[i].description,
1566 strlen(IcqProtocol::info_plugins[i].description));
1567
1568 buffer->PackUnsignedLong(0); //Unknown
1569 }
1570 }
1571 }
1572
1573 //-----Send phone book response-----------------------------------------------
CPU_InfoPhoneBookResp(const ICQUser * u,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nSequence)1574 CPU_InfoPhoneBookResp::CPU_InfoPhoneBookResp(const ICQUser* u, unsigned long nMsgID1,
1575 unsigned long nMsgID2,
1576 unsigned short nSequence)
1577 : CPU_AckThroughServer(u, nMsgID1, nMsgID2, nSequence, 0, true,
1578 ICQ_TCPxMSG_URGENT2, PLUGIN_INFOxMANAGER)
1579 {
1580 OwnerReadGuard o(gIcqProtocol.ownerId());
1581 const Licq::IcqPhoneBookVector& book = o->getPhoneBook();
1582
1583 unsigned long nLen = 4 + 4;
1584 BOOST_FOREACH(const struct Licq::PhoneBookEntry& entry, book)
1585 {
1586 nLen += 4 + entry.description.size() + 4 + entry.areaCode.size()
1587 + 4 + entry.phoneNumber.size() + 4 + entry.extension.size()
1588 + 4 + entry.country.size() + 4 + 4 + 4
1589 + 4 + entry.gateway.size() + 4 + 4 + 4 + 4;
1590 }
1591
1592 m_nSize += 2 + 2 + 4 + 4 + nLen;
1593 InitBuffer();
1594
1595 buffer->PackUnsignedShort(0); //Unknown
1596 buffer->PackUnsignedShort(1); //Unknown
1597 buffer->PackUnsignedLong(o->ClientInfoTimestamp());
1598 buffer->PackUnsignedLong(nLen); //Bytes remaining in packet
1599
1600 buffer->PackUnsignedLong(ICQ_PLUGIN_RESP_PHONExBOOK); //Response ID
1601
1602 buffer->PackUnsignedLong(book.size());
1603
1604 BOOST_FOREACH(const struct Licq::PhoneBookEntry& entry, book)
1605 {
1606 buffer->packString32LE(entry.description);
1607 buffer->packString32LE(entry.areaCode);
1608 buffer->packString32LE(entry.phoneNumber);
1609 buffer->packString32LE(entry.extension);
1610 buffer->packString32LE(entry.country);
1611 buffer->packUInt32LE(entry.nActive);
1612 }
1613
1614 BOOST_FOREACH(const struct Licq::PhoneBookEntry& entry, book)
1615 {
1616 buffer->packUInt32LE(4 + 4 + entry.gateway.size() + 4 + 4 + 4 + 4);
1617 buffer->packUInt32LE(entry.nType);
1618 buffer->packString32LE(entry.gateway);
1619 buffer->packUInt32LE(entry.nGatewayType);
1620 buffer->packUInt32LE(entry.nSmsAvailable);
1621 buffer->packUInt32LE(entry.nRemoveLeading0s);
1622 buffer->packUInt32LE(entry.nPublish);
1623 }
1624 }
1625
1626 //-----Send picture response-------------------------------------------------
CPU_InfoPictureResp(const ICQUser * u,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nSequence)1627 CPU_InfoPictureResp::CPU_InfoPictureResp(const ICQUser* u, unsigned long nMsgID1,
1628 unsigned long nMsgID2,
1629 unsigned short nSequence)
1630 : CPU_AckThroughServer(u, nMsgID1, nMsgID2, nSequence, 0, true,
1631 ICQ_TCPxMSG_URGENT2, PLUGIN_INFOxMANAGER)
1632 {
1633 OwnerReadGuard o(gIcqProtocol.ownerId());
1634 string filename = o->pictureFileName();
1635 unsigned long nLen = 0, nFileLen = 0;
1636 int fd = -1;
1637 if (o->GetPicturePresent())
1638 {
1639 fd = open(filename.c_str(), O_RDONLY);
1640 if (fd == -1)
1641 {
1642 gLog.error(tr("Unable to open picture file (%s): %s."),
1643 filename.c_str(), strerror(errno));
1644 }
1645 else
1646 {
1647 struct stat fi;
1648 if (fstat(fd, &fi) == -1)
1649 {
1650 gLog.error(tr("Unable to stat picture file (%s): %s."),
1651 filename.c_str(), strerror(errno));
1652 }
1653 else
1654 {
1655 nFileLen = fi.st_size;
1656 nLen = 4 + 4 + 1 + 4 + nFileLen;
1657 }
1658 }
1659 }
1660
1661 m_nSize += 2 + 2 + 4 + 4 + nLen;
1662 InitBuffer();
1663
1664 buffer->PackUnsignedShort(0); //Unknown
1665 buffer->PackUnsignedShort(1); //Unknown
1666 buffer->PackUnsignedLong(o->ClientInfoTimestamp());
1667 buffer->PackUnsignedLong(nLen); //Bytes remaining in packet
1668
1669 if (nLen != 0)
1670 {
1671 buffer->PackUnsignedLong(ICQ_PLUGIN_RESP_PICTURE); //Response ID
1672
1673 buffer->PackUnsignedLong(1); //filename length
1674 buffer->PackChar('p'); //windows icq needs a filename
1675
1676 buffer->PackUnsignedLong(nFileLen);
1677
1678 char buf[8192];
1679 unsigned long nRead = 0;
1680 while (nRead < nFileLen)
1681 {
1682 unsigned long nToRead;
1683 if (sizeof(buf) < nFileLen - nRead)
1684 nToRead = sizeof(buf);
1685 else
1686 nToRead = nFileLen - nRead;
1687
1688 ssize_t nBytesRead = read(fd, buf, nToRead);
1689 if (nBytesRead == -1)
1690 {
1691 gLog.error(tr("Failed to read file (%s): %s."),
1692 filename.c_str(), strerror(errno));
1693 break;
1694 }
1695 if (nBytesRead == 0)
1696 {
1697 gLog.error(tr("Premature end of file (%s): %s."),
1698 filename.c_str(), strerror(errno));
1699 break;
1700 }
1701
1702 nRead += nBytesRead;
1703 for (ssize_t i = 0; i < nBytesRead; i++)
1704 buffer->PackChar(buf[i]);
1705 }
1706
1707 if (nRead < nFileLen)
1708 {
1709 //failed to read as much as predicted, fill with 0s
1710 for (; nRead < nFileLen; nRead++)
1711 buffer->PackChar(0);
1712 }
1713 }
1714
1715 if (fd != -1)
1716 close(fd);
1717 }
1718
1719 //-----Send status plugin request---------------------------------------------
CPU_StatusPluginReq(const User * u,const uint8_t * GUID,unsigned long nTime)1720 CPU_StatusPluginReq::CPU_StatusPluginReq(const User* u, const uint8_t* GUID,
1721 unsigned long nTime)
1722 : CPU_PluginMessage(u, false, PLUGIN_STATUSxMANAGER)
1723 {
1724 m_nSize += 27;
1725 memcpy(m_ReqGUID, GUID, GUID_LENGTH);
1726
1727 InitBuffer();
1728 buffer->PackUnsignedShort(0);
1729 buffer->PackUnsignedShort(1);
1730 buffer->PackChar(0);
1731 buffer->Pack(GUID, GUID_LENGTH);
1732 buffer->PackUnsignedLong(nTime);
1733 }
1734
1735 //-----Send status plugin list------------------------------------------------
CPU_StatusPluginListResp(const ICQUser * u,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nSequence)1736 CPU_StatusPluginListResp::CPU_StatusPluginListResp(const ICQUser* u,
1737 unsigned long nMsgID1,
1738 unsigned long nMsgID2,
1739 unsigned short nSequence)
1740 : CPU_AckThroughServer(u, nMsgID1, nMsgID2, nSequence, 0, true,
1741 0, PLUGIN_STATUSxMANAGER)
1742 {
1743 unsigned long num_plugins = sizeof(IcqProtocol::status_plugins)/sizeof(struct PluginList);
1744
1745 unsigned long nLen;
1746 if (num_plugins == 0)
1747 nLen = 0;
1748 else
1749 {
1750 nLen = 4 + 4;
1751 for (unsigned long i = 0; i < num_plugins; i ++)
1752 {
1753 nLen += GUID_LENGTH + 2 + 2 + 4 + strlen(IcqProtocol::status_plugins[i].name)
1754 + 4 + strlen(IcqProtocol::status_plugins[i].description) + 4;
1755 }
1756 }
1757
1758 m_nSize += 13 + 4 + 4 + nLen;
1759 InitBuffer();
1760
1761 buffer->PackUnsignedShort(0); //Unknown
1762 buffer->PackUnsignedShort(1); //Unknown
1763 buffer->PackUnsignedLong(0); //Unknown
1764 buffer->PackUnsignedLong(0); //Unknown
1765 buffer->PackChar(1); //Unknown
1766 {
1767 OwnerReadGuard o(gIcqProtocol.ownerId());
1768 buffer->PackUnsignedLong(o->ClientStatusTimestamp());
1769 }
1770 buffer->PackUnsignedLong(nLen); //Bytes remaining in packet
1771
1772 if (nLen != 0)
1773 {
1774 buffer->PackUnsignedLong(ICQ_PLUGIN_RESP_STATUSxLIST); //Response ID
1775 buffer->PackUnsignedLong(num_plugins);
1776 for (unsigned long i = 0; i < num_plugins; i++)
1777 {
1778 buffer->packRaw(IcqProtocol::status_plugins[i].guid, GUID_LENGTH);
1779
1780 buffer->PackUnsignedShort(0); //Unknown
1781 buffer->PackUnsignedShort(1); //Unknown
1782
1783 buffer->packString32LE(IcqProtocol::status_plugins[i].name,
1784 strlen(IcqProtocol::status_plugins[i].name));
1785
1786 buffer->packString32LE(IcqProtocol::status_plugins[i].description,
1787 strlen(IcqProtocol::status_plugins[i].description));
1788
1789 buffer->PackUnsignedLong(0); //Unknown
1790 }
1791 }
1792 }
1793
1794 //-----Send the plugin status------------------------------------------------
CPU_StatusPluginResp(const ICQUser * u,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nSequence,unsigned long nStatus)1795 CPU_StatusPluginResp::CPU_StatusPluginResp(const ICQUser* u, unsigned long nMsgID1,
1796 unsigned long nMsgID2,
1797 unsigned short nSequence,
1798 unsigned long nStatus)
1799 : CPU_AckThroughServer(u, nMsgID1, nMsgID2, nSequence, 0, true,
1800 0, PLUGIN_STATUSxMANAGER)
1801 {
1802 // this is a bit of a hack
1803 myMessage[0] = ICQ_PLUGIN_STATUSxREPLY;
1804 m_nSize += 2 + 2 + 4 + 4 + 1;
1805 InitBuffer();
1806
1807 buffer->PackUnsignedShort(0); //Unknown
1808 buffer->PackUnsignedShort(1); //Unknown
1809
1810 buffer->PackUnsignedLong(nStatus);
1811 OwnerReadGuard o(gIcqProtocol.ownerId());
1812 buffer->PackUnsignedLong(o->ClientStatusTimestamp());
1813 buffer->PackChar(1); //Unknown
1814 }
1815
1816 //-----AdvancedMessage---------------------------------------------------------
CPU_AdvancedMessage(const User * u,unsigned short _nMsgType,unsigned short _nMsgFlags,bool _bAck,unsigned short _nSequence,unsigned long nMsgID1,unsigned long nMsgID2)1817 CPU_AdvancedMessage::CPU_AdvancedMessage(const User* u, unsigned short _nMsgType,
1818 unsigned short _nMsgFlags, bool _bAck, unsigned short _nSequence,
1819 unsigned long nMsgID1, unsigned long nMsgID2)
1820 : CPU_Type2Message(u, _bAck,
1821 (_nMsgType == ICQ_CMDxSUB_ICBM) || (!_bAck && _nMsgType == ICQ_CMDxTCP_READxAWAYxMSG),
1822 ICQ_CAPABILITY_SRVxRELAY, nMsgID1, nMsgID2)
1823 {
1824 m_nSize += 54;
1825
1826 m_nMsgFlags = _nMsgFlags;
1827 m_nSequence = _nSequence;
1828
1829 if (!_bAck && _nMsgType == ICQ_CMDxTCP_READxAWAYxMSG)
1830 {
1831 // Get the correct message
1832 unsigned status = m_pUser->status();
1833 if (status & Licq::User::DoNotDisturbStatus)
1834 m_nSubCommand = ICQ_CMDxTCP_READxDNDxMSG;
1835 else if (status & Licq::User::OccupiedStatus)
1836 m_nSubCommand = ICQ_CMDxTCP_READxOCCUPIEDxMSG;
1837 else if (status & Licq::User::NotAvailableStatus)
1838 m_nSubCommand = ICQ_CMDxTCP_READxNAxMSG;
1839 else if (status & Licq::User::AwayStatus)
1840 m_nSubCommand = ICQ_CMDxTCP_READxAWAYxMSG;
1841 else if (status & Licq::User::FreeForChatStatus)
1842 m_nSubCommand = ICQ_CMDxTCP_READxFFCxMSG;
1843 else
1844 m_nSubCommand = ICQ_CMDxTCP_READxAWAYxMSG;
1845
1846 InitBuffer();
1847 }
1848 else
1849 {
1850 m_nSubCommand = _nMsgType;
1851 }
1852 }
1853
InitBuffer()1854 void CPU_AdvancedMessage::InitBuffer()
1855 {
1856 CPU_Type2Message::InitBuffer();
1857
1858 unsigned short nStatus;
1859 {
1860 Licq::OwnerReadGuard o(gIcqProtocol.ownerId());
1861 if (m_pUser->statusToUser() != Licq::User::OfflineStatus)
1862 nStatus = IcqProtocol::icqStatusFromStatus(m_pUser->statusToUser());
1863 else
1864 nStatus = IcqProtocol::icqStatusFromStatus(o->status());
1865 }
1866
1867 // XXX Is this really a status? XXX
1868 // If this is non-zero, ICQ5 ignores our accept file ack.
1869 nStatus = 0;
1870
1871 buffer->PackUnsignedShort(0x001B); // len
1872 buffer->PackUnsignedShort(m_pUser->ConnectionVersion());
1873 buffer->Pack(PLUGIN_NORMAL, GUID_LENGTH);
1874 buffer->PackUnsignedLong(0x00000003); // len
1875 buffer->PackChar(0x04); // accept connections or firewalled
1876 buffer->PackUnsignedShort(m_nSequence); // sequence
1877 buffer->PackUnsignedShort(0x000E); // len
1878 buffer->PackUnsignedShort(m_nSequence); // sequence
1879 buffer->PackUnsignedLongBE(0);
1880 buffer->PackUnsignedLongBE(0);
1881 buffer->PackUnsignedLongBE(0);
1882 buffer->PackUnsignedShort(m_nSubCommand);
1883 buffer->PackUnsignedShort(nStatus);
1884 buffer->PackUnsignedShort(m_nMsgFlags);
1885 buffer->PackUnsignedShort(0x0001); // message len
1886 buffer->PackChar(0); // message
1887 }
1888
1889 //-----ChatRequest-------------------------------------------------------------
CPU_ChatRequest(const string & message,const string & chatUsers,unsigned short nPort,unsigned short nLevel,const User * _pUser,bool bICBM)1890 CPU_ChatRequest::CPU_ChatRequest(const string& message, const string& chatUsers,
1891 unsigned short nPort, unsigned short nLevel,
1892 const User* _pUser, bool bICBM)
1893 : CPU_AdvancedMessage(_pUser, bICBM ? ICQ_CMDxSUB_ICBM : ICQ_CMDxSUB_CHAT,
1894 nLevel, false, 0)
1895 {
1896 m_nSize += 14 + chatUsers.size() + message.size();
1897 if (bICBM)
1898 m_nSize += 44 + 21; // 21 = strlen(pluginname)
1899
1900 // m_nExtraLen += 4; m_nSize += 4; //ack request
1901 InitBuffer();
1902
1903 if (bICBM)
1904 {
1905 buffer->PackUnsignedShort(0x3A); // len of following pluign info
1906 buffer->PackUnsignedLongBE(0xBFF720B2);
1907 buffer->PackUnsignedLongBE(0x378ED411);
1908 buffer->PackUnsignedLongBE(0xBD280004);
1909 buffer->PackUnsignedLongBE(0xAC96D905);
1910 buffer->PackUnsignedShort(0);
1911 buffer->PackUnsignedLong(0x15); // strlen of plugin name
1912 buffer->Pack("Send / Start ICQ Chat", 0x15);
1913 buffer->PackUnsignedLongBE(0x00000100);
1914 buffer->PackUnsignedLongBE(0x00010000);
1915 buffer->PackUnsignedLongBE(0);
1916 buffer->PackUnsignedShortBE(0);
1917 buffer->PackChar(0);
1918 buffer->PackUnsignedLong(message.size() + chatUsers.size() + 15);
1919 buffer->PackUnsignedLong(message.size());
1920 if (!message.empty())
1921 buffer->pack(message);
1922 }
1923 else
1924 buffer->packString(message);
1925
1926 buffer->packString(chatUsers);
1927 buffer->PackUnsignedShortBE(nPort);
1928 buffer->PackUnsignedShort(0);
1929 buffer->PackUnsignedShort(nPort);
1930 buffer->PackUnsignedShort(0);
1931 // buffer->PackUnsignedLongBE(0x00030000); // ack request
1932 }
1933
1934 //-----FileTransfer------------------------------------------------------------
CPU_FileTransfer(const User * u,const list<string> & lFileList,const string & file,const string & desc,unsigned short nLevel,bool bICBM)1935 CPU_FileTransfer::CPU_FileTransfer(const User* u, const list<string>& lFileList,
1936 const string& file, const string& desc, unsigned short nLevel, bool bICBM)
1937 : CPU_AdvancedMessage(u, bICBM ? ICQ_CMDxSUB_ICBM : ICQ_CMDxSUB_FILE, nLevel,
1938 false, 0),
1939 m_lFileList(lFileList.begin(), lFileList.end())
1940 {
1941 m_bValid = false;
1942 m_nFileSize = 0;
1943
1944 list<string>::iterator it;
1945 for (it = m_lFileList.begin(); it != m_lFileList.end(); ++it)
1946 {
1947 // Check file exists and get size
1948 struct stat buf;
1949 if (!(it->empty() || stat(it->c_str(), &buf) < 0))
1950 {
1951 m_nFileSize += buf.st_size;
1952 m_bValid = true;
1953 }
1954 }
1955
1956 // Remove path from filename (if it exists)
1957 myFilename = file;
1958 size_t posSlash = myFilename.rfind('/');
1959 if (posSlash != string::npos)
1960 myFilename.erase(0, posSlash+1);
1961
1962 if (!m_bValid) return;
1963
1964 myDesc = desc;
1965
1966 m_nSize += 18 + myFilename.size() + desc.size();
1967 if (bICBM)
1968 m_nSize += 44 + 4; // 4 = strlen("File")
1969 // m_nExtraLen += 4; m_nSize += 4; //the ack request
1970
1971 InitBuffer();
1972
1973 if (bICBM)
1974 {
1975 buffer->PackUnsignedShort(0x29); // len of following plugin info
1976 buffer->PackUnsignedLongBE(0xF02D12D9);
1977 buffer->PackUnsignedLongBE(0x3091D311);
1978 buffer->PackUnsignedLongBE(0x8DD70010);
1979 buffer->PackUnsignedLongBE(0x4B06462E);
1980 buffer->PackUnsignedShortBE(0x0000);
1981 buffer->PackUnsignedLong(0x04); // strlen - is 4 bytes though
1982 buffer->Pack("File", 4);
1983 buffer->PackUnsignedLongBE(0x00000100);
1984 buffer->PackUnsignedLongBE(0x00010000);
1985 buffer->PackUnsignedLongBE(0);
1986 buffer->PackUnsignedShortBE(0);
1987 buffer->PackChar(0);
1988 buffer->PackUnsignedLong(desc.size() + myFilename.size() + 19); //remaining - is 4 bytes
1989 //dont count last 4 bytes
1990 buffer->PackUnsignedLong(desc.size()); // file desc - is 4 bytes
1991 buffer->pack(desc);
1992 }
1993 else
1994 buffer->packString(desc);
1995
1996 buffer->PackUnsignedLongBE(0x2D384444); // ???
1997 buffer->packString(myFilename);
1998 buffer->PackUnsignedLong(m_nFileSize);
1999 buffer->PackUnsignedLongBE(0);
2000 // buffer->PackUnsignedLongBE(0x00030000); // ack request
2001 }
2002
2003 //-----NoManager------------------------------------------------------------
CPU_NoManager(const ICQUser * u,unsigned long nMsgID1,unsigned long nMsgID2)2004 CPU_NoManager::CPU_NoManager(const ICQUser* u, unsigned long nMsgID1,
2005 unsigned long nMsgID2)
2006 : CPU_CommonFamily(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SERVERxREPLYxMSG)
2007 {
2008 unsigned long nUinLen = u->accountId().size();
2009
2010 m_nSize += 17 + nUinLen;
2011
2012 InitBuffer();
2013
2014 buffer->PackUnsignedLongBE(nMsgID1);
2015 buffer->PackUnsignedLongBE(nMsgID2);
2016 buffer->PackUnsignedShortBE(2);
2017 buffer->PackChar(nUinLen);
2018 buffer->pack(u->accountId());
2019 buffer->PackUnsignedShortBE(0x03); /* tlv3?? who knows, doesn't fit with the
2020 ack below */
2021 buffer->PackUnsignedShortBE(0x02);
2022 buffer->PackUnsignedShort(0);
2023 }
2024
2025 //-----AckThroughServer--------------------------------------------------------
CPU_AckThroughServer(const ICQUser * u,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nSequence,unsigned short nMsgType,bool bAccept,unsigned short nLevel,const uint8_t * GUID)2026 CPU_AckThroughServer::CPU_AckThroughServer(const ICQUser* u,
2027 unsigned long nMsgID1,
2028 unsigned long nMsgID2,
2029 unsigned short nSequence,
2030 unsigned short nMsgType,
2031 bool bAccept, unsigned short nLevel,
2032 const uint8_t* GUID)
2033 : CPU_CommonFamily(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SERVERxREPLYxMSG)
2034 {
2035 myAccountId = u->accountId();
2036
2037 m_nSize += 66 + myAccountId.size();
2038
2039 m_nMsgID[0] = nMsgID1;
2040 m_nMsgID[1] = nMsgID2;
2041 m_nSequence = nSequence;
2042 m_nSubCommand = nMsgType;
2043 m_nSequence = nSequence;
2044 m_nLevel = nLevel;
2045 memcpy(m_GUID, GUID, GUID_LENGTH);
2046
2047 if (memcmp(GUID, PLUGIN_NORMAL, GUID_LENGTH) != 0)
2048 {
2049 myMessage.assign(1, (bAccept ? ICQ_PLUGIN_SUCCESS : ICQ_PLUGIN_REJECTED));
2050 m_nStatus = ICQ_TCPxACK_ONLINE;
2051 m_nSize ++;
2052 }
2053 else
2054 {
2055 unsigned short s;
2056 {
2057 Licq::OwnerReadGuard o(gIcqProtocol.ownerId());
2058 if (u->statusToUser() != Licq::User::OfflineStatus)
2059 s = IcqProtocol::icqStatusFromStatus(u->statusToUser());
2060 else
2061 s = IcqProtocol::icqStatusFromStatus(o->status());
2062 }
2063
2064 if (!bAccept)
2065 m_nStatus = ICQ_TCPxACK_REFUSE;
2066 else
2067 {
2068 if (s & Licq::User::DoNotDisturbStatus)
2069 m_nStatus = ICQ_TCPxACK_DNDxCAR;
2070 else if (s & Licq::User::OccupiedStatus)
2071 m_nStatus = ICQ_TCPxACK_OCCUPIEDxCAR;
2072 else if (s & Licq::User::NotAvailableStatus)
2073 m_nStatus = ICQ_TCPxACK_NA;
2074 else if (s & Licq::User::AwayStatus)
2075 m_nStatus = ICQ_TCPxACK_AWAY;
2076 else
2077 m_nStatus = ICQ_TCPxACK_ONLINE;
2078 }
2079
2080 myMessage = gTranslator.fromUtf8(u->makeAutoResponse());
2081
2082 // If message is 8099 characters or longer the server will disconnect us so better to truncate
2083 if (myMessage.size() >= 8099)
2084 myMessage.resize(8098);
2085
2086 m_nSize += myMessage.size() + 1;
2087 }
2088 }
2089
InitBuffer()2090 void CPU_AckThroughServer::InitBuffer()
2091 {
2092 CPU_CommonFamily::InitBuffer();
2093
2094 bool bPlugin = memcmp(m_GUID, PLUGIN_NORMAL, GUID_LENGTH) != 0;
2095
2096 buffer->PackUnsignedLongBE(m_nMsgID[0]);
2097 buffer->PackUnsignedLongBE(m_nMsgID[1]);
2098 buffer->PackUnsignedShortBE(2);
2099 buffer->PackChar(myAccountId.size());
2100 buffer->pack(myAccountId);
2101 buffer->PackUnsignedShortBE(0x03);
2102 buffer->PackUnsignedShort(0x1b);
2103 buffer->PackUnsignedShort(ICQ_VERSION_TCP);
2104 buffer->Pack(m_GUID, GUID_LENGTH);
2105 buffer->PackUnsignedLong(3);
2106 buffer->PackChar(0);
2107 buffer->PackUnsignedShort(m_nSequence);
2108 buffer->PackUnsignedShort(bPlugin ? 0x12 : 0x0E);
2109 buffer->PackUnsignedShort(m_nSequence);
2110 buffer->PackUnsignedLongBE(0);
2111 buffer->PackUnsignedLongBE(0);
2112 buffer->PackUnsignedLongBE(0);
2113 buffer->PackUnsignedShort(m_nSubCommand);
2114 buffer->PackUnsignedShort(m_nStatus);
2115 buffer->PackUnsignedShort(m_nLevel);
2116 if (bPlugin)
2117 {
2118 buffer->PackUnsignedShort(1);
2119 buffer->PackChar(myMessage[0]);
2120 }
2121 else
2122 buffer->PackString(myMessage.c_str());
2123 }
2124
2125 //-----AckGeneral--------------------------------------------------------------
CPU_AckGeneral(const ICQUser * u,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nSequence,unsigned short nMsgType,bool bAccept,unsigned short nLevel)2126 CPU_AckGeneral::CPU_AckGeneral(const ICQUser* u, unsigned long nMsgID1,
2127 unsigned long nMsgID2, unsigned short nSequence,
2128 unsigned short nMsgType, bool bAccept,
2129 unsigned short nLevel)
2130 : CPU_AckThroughServer(u, nMsgID1, nMsgID2, nSequence, nMsgType, bAccept,
2131 nLevel, PLUGIN_NORMAL)
2132 {
2133 m_nSize += 8;
2134 InitBuffer();
2135
2136 buffer->PackUnsignedLongBE(0);
2137 buffer->PackUnsignedLongBE(0xFFFFFF00);
2138 }
2139
2140
2141 //-----AckFileAccept-----------------------------------------------------------
CPU_AckFileAccept(const User * u,const unsigned long nMsgID[2],unsigned short nSequence,unsigned short nPort,const string & desc,const string & file,unsigned long nFileSize)2142 CPU_AckFileAccept::CPU_AckFileAccept(const User* u,
2143 const unsigned long nMsgID[2], unsigned short nSequence, unsigned short nPort,
2144 const string& desc, const string& file, unsigned long nFileSize)
2145 : CPU_AdvancedMessage(u, ICQ_CMDxSUB_ICBM, 0, true, nSequence, nMsgID[0],
2146 nMsgID[1])
2147 {
2148 m_nSize += 66 + file.size() + desc.size();
2149 InitBuffer();
2150
2151 buffer->PackUnsignedShort(0x29); // len of following plugin info
2152 buffer->PackUnsignedLongBE(0xF02D12D9);
2153 buffer->PackUnsignedLongBE(0x3091D311);
2154 buffer->PackUnsignedLongBE(0x8DD70010);
2155 buffer->PackUnsignedLongBE(0x4B06462E);
2156 buffer->PackUnsignedShortBE(0x0000);
2157 buffer->PackUnsignedLong(4); // strlen - is 13 bytes though
2158 buffer->Pack("File", 4);
2159 buffer->PackUnsignedLongBE(0x00000100);
2160 buffer->PackUnsignedLongBE(0x00010000);
2161 buffer->PackUnsignedLongBE(0);
2162 buffer->PackUnsignedShortBE(0);
2163 buffer->PackChar(0);
2164 buffer->PackUnsignedLong(19 + desc.size() + file.size());
2165 buffer->PackUnsignedLong(desc.size()); // file desc - is 4 bytes
2166 buffer->pack(desc); // file desc
2167 buffer->packUInt16BE(nPort); // port reversed
2168 buffer->packUInt16BE(0);
2169 buffer->packString(file); // filename
2170 buffer->PackUnsignedLong(nFileSize); // filesize
2171 buffer->PackUnsignedLong(nPort); // port
2172 }
2173
2174
2175 //-----AckFileRefuse-----------------------------------------------------------
CPU_AckFileRefuse(const User * u,const unsigned long nMsgID[2],unsigned short nSequence,const string & message)2176 CPU_AckFileRefuse::CPU_AckFileRefuse(const User* u, const unsigned long nMsgID[2],
2177 unsigned short nSequence, const string& message)
2178 : CPU_AckThroughServer(u, nMsgID[0], nMsgID[1], nSequence,
2179 ICQ_CMDxSUB_FILE, false, 0, PLUGIN_NORMAL)
2180 {
2181 // XXX This is not the ICBM way yet!
2182 m_nSize += message.size() + 18;
2183 InitBuffer();
2184
2185 buffer->packString(message);
2186 buffer->PackUnsignedLong(0); // port reversed
2187 buffer->PackString("");
2188 buffer->PackUnsignedLong(0);
2189 buffer->PackUnsignedLong(0);
2190 }
2191
2192 //-----AckChatAccept-----------------------------------------------------------
CPU_AckChatAccept(const User * u,const string & clients,const unsigned long nMsgID[2],unsigned short nSequence,unsigned short nPort)2193 CPU_AckChatAccept::CPU_AckChatAccept(const User* u, const string& clients,
2194 const unsigned long nMsgID[2], unsigned short nSequence,
2195 unsigned short nPort)
2196 : CPU_AdvancedMessage(u, ICQ_CMDxSUB_CHAT, 0, true, nSequence,
2197 nMsgID[0], nMsgID[1])
2198 {
2199 // XXX This is not the ICBM way yet!
2200 m_nSize += 11 + clients.size();
2201 InitBuffer();
2202
2203 buffer->packString(clients);
2204 buffer->packUInt16BE(nPort); // port reversed
2205 buffer->packUInt16BE(0);
2206 buffer->PackUnsignedLong(nPort);
2207 }
2208
2209 //-----AckChatRefuse-----------------------------------------------------------
CPU_AckChatRefuse(const User * u,const unsigned long nMsgID[2],unsigned short nSequence,const string & message)2210 CPU_AckChatRefuse::CPU_AckChatRefuse(const User* u, const unsigned long nMsgID[2],
2211 unsigned short nSequence, const string& message)
2212 : CPU_AckThroughServer(u, nMsgID[0], nMsgID[1], nSequence,
2213 ICQ_CMDxSUB_CHAT, false, 0, PLUGIN_NORMAL)
2214 {
2215 // XXX This is not the ICBM way yet!
2216 m_nSize += message.size() + 14;
2217 InitBuffer();
2218
2219 buffer->packString(message);
2220 buffer->PackString("");
2221 buffer->PackUnsignedLong(0);
2222 buffer->PackUnsignedLong(0);
2223 }
2224
2225 //-----SendSms-----------------------------------------------------------------
CPU_SendSms(const string & number,const string & message)2226 CPU_SendSms::CPU_SendSms(const string& number, const string& message)
2227 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
2228 {
2229 m_nMetaCommand = ICQ_CMDxMETA_SENDxSMS;
2230
2231 char szXmlStr[460];
2232
2233 char szTime[30];
2234 time_t tTime;
2235 struct tm *tmTime;
2236 time(&tTime);
2237 tmTime = gmtime(&tTime);
2238 strftime(szTime, 30, "%a, %d %b %Y %T %Z", tmTime);
2239
2240 string parsedNumber = IcqProtocol::parseDigits(number);
2241
2242 {
2243 Licq::OwnerReadGuard o(gIcqProtocol.ownerId());
2244 snprintf(szXmlStr, 460, "<icq_sms_message><destination>%s</destination><text>%.160s</text><codepage>1252</codepage><encoding>utf8</encoding><senders_UIN>%s</senders_UIN><senders_name>%s</senders_name><delivery_receipt>Yes</delivery_receipt><time>%s</time></icq_sms_message>",
2245 parsedNumber.c_str(), message.c_str(), o->accountId().c_str(), o->getAlias().c_str(), szTime);
2246 szXmlStr[459] = '\0';
2247 }
2248
2249 int nLenXmlStr = strlen(szXmlStr) + 1;
2250 int packetSize = 2+2+2+4+2+2+2 + 22 + 2 + nLenXmlStr;
2251 m_nSize += packetSize;
2252 InitBuffer();
2253
2254 buffer->PackUnsignedShortBE(1);
2255 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
2256
2257 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
2258 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
2259 buffer->PackUnsignedShortBE(0xD007); // type
2260 buffer->PackUnsignedShortBE(m_nSubSequence);
2261 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
2262
2263 buffer->PackUnsignedShortBE(0x0001);
2264 buffer->PackUnsignedShortBE(0x0016);
2265 buffer->PackUnsignedLong(0);
2266 buffer->PackUnsignedLong(0);
2267 buffer->PackUnsignedLong(0);
2268 buffer->PackUnsignedLong(0);
2269 buffer->PackUnsignedShort(0);
2270
2271 buffer->PackUnsignedShortBE(nLenXmlStr);
2272 buffer->Pack(szXmlStr, nLenXmlStr);
2273 }
2274
2275 //----RequestAuth------------------------------------------------------------
CPU_RequestAuth(const string & accountId,const string & message)2276 CPU_RequestAuth::CPU_RequestAuth(const string& accountId, const string& message)
2277 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_AUTHxREQ)
2278 {
2279 m_nSize += accountId.size() + message.size() + 5;
2280 InitBuffer();
2281
2282 buffer->PackChar(accountId.size());
2283 buffer->pack(accountId);
2284 buffer->PackUnsignedShortBE(message.size());
2285 buffer->pack(message);
2286 buffer->PackUnsignedShortBE(0);
2287 }
2288
2289 //-----Ack-------------------------------------------------------------------
2290 #if ICQ_VERSION == 2
CPU_Ack(unsigned short _nSequence)2291 CPU_Ack::CPU_Ack(unsigned short _nSequence) : CPacketUdp(ICQ_CMDxSND_ACK)
2292 {
2293 m_nSequence = _nSequence;
2294 InitBuffer();
2295 }
2296 #elif ICQ_VERSION == 4 || ICQ_VERSION == 5
CPU_Ack(unsigned short _nSequence,unsigned short _nSubSequence)2297 CPU_Ack::CPU_Ack(unsigned short _nSequence, unsigned short _nSubSequence)
2298 : CPacketUdp(ICQ_CMDxSND_ACK)
2299 {
2300 m_nSequence = _nSequence;
2301 m_nSubSequence = _nSubSequence;
2302 InitBuffer();
2303 }
2304 #endif
2305
2306 //-----AddUser------------------------------------------------------------------
CPU_AddUser(unsigned long _nAddedUin)2307 CPU_AddUser::CPU_AddUser(unsigned long _nAddedUin)
2308 : CPacketUdp(ICQ_CMDxSND_USERxADD)
2309 {
2310 m_nAddedUin = _nAddedUin;
2311
2312 m_nSize += 4;
2313 InitBuffer();
2314
2315 buffer->PackUnsignedLong(m_nAddedUin);
2316 }
2317
2318
2319 //-----Logoff-------------------------------------------------------------------
CPU_Logoff()2320 CPU_Logoff::CPU_Logoff()
2321 : CSrvPacketTcp(ICQ_CHNxCLOSE)
2322 {
2323 InitBuffer();
2324 }
2325
~CPU_Logoff()2326 CPU_Logoff::~CPU_Logoff()
2327 {
2328 // Empty
2329 }
2330
2331 //-----RequestList--------------------------------------------------------------
CPU_RequestList()2332 CPU_RequestList::CPU_RequestList()
2333 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_REQUESTxROST)
2334 {
2335 m_nSize += 6;
2336 InitBuffer();
2337
2338 OwnerReadGuard o(gIcqProtocol.ownerId());
2339 buffer->PackUnsignedLongBE(o->GetSSTime());
2340 buffer->PackUnsignedShortBE(o->GetSSCount());
2341 }
2342
2343 //-----ExportContactStart-------------------------------------------------------
CPU_ExportContactStart()2344 CPU_ExportContactStart::CPU_ExportContactStart()
2345 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxEDITxSTART)
2346 {
2347 m_nSize += 4;
2348 InitBuffer();
2349
2350 buffer->PackUnsignedLongBE(0x00010000);
2351 }
2352
2353 //-----ExportToServerList-------------------------------------------------------
CPU_ExportToServerList(const list<UserId> & users,unsigned short _nType)2354 CPU_ExportToServerList::CPU_ExportToServerList(const list<UserId>& users,
2355 unsigned short _nType)
2356 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxADD)
2357 {
2358 unsigned short m_nSID = 0;
2359 unsigned short m_nGSID = 0;
2360 int nSize = 0;
2361 Licq::UserId ownerId(gIcqProtocol.ownerId());
2362
2363 list<UserId>::const_iterator i;
2364 for (i = users.begin(); i != users.end(); ++i)
2365 {
2366 Licq::UserReadGuard pUser(*i);
2367 if (pUser.isLocked())
2368 {
2369 nSize += pUser->accountId().size();
2370 nSize += 10;
2371
2372 string::size_type nAliasLen = pUser->getAlias().size();
2373 if (nAliasLen && _nType == ICQ_ROSTxNORMAL)
2374 nSize += 4 + nAliasLen;
2375 }
2376 }
2377
2378 m_nSize += nSize;
2379 InitBuffer();
2380
2381 for (i = users.begin(); i != users.end(); i++)
2382 {
2383 int nLen;
2384 string unicodeName;
2385
2386 m_nSID = gIcqProtocol.generateSid();
2387
2388 // Save the SID
2389 UserWriteGuard u(*i);
2390 if (!u.isLocked())
2391 {
2392 gLog.warning(tr("Trying to export invalid user %s to server"),
2393 i->toString().c_str());
2394 continue;
2395 }
2396
2397 if (u->protocolId() != ICQ_PPID)
2398 {
2399 gLog.warning(tr("Trying to export non ICQ user %s to ICQ server."),
2400 i->toString().c_str());
2401 continue;
2402 }
2403
2404 switch (_nType)
2405 {
2406 case ICQ_ROSTxIGNORE: // same as ICQ_ROSTxNORMAL
2407 case ICQ_ROSTxNORMAL: u->SetSID(m_nSID); break;
2408 case ICQ_ROSTxINVISIBLE: u->SetInvisibleSID(m_nSID); break;
2409 case ICQ_ROSTxVISIBLE: u->SetVisibleSID(m_nSID); break;
2410 }
2411
2412 if (_nType == ICQ_ROSTxNORMAL)
2413 {
2414 // Use the first group that the user is in as the server stored group
2415 const UserGroupList& userGroups = u->GetGroups();
2416
2417 for (UserGroupList::const_iterator j = userGroups.begin(); j != userGroups.end(); ++j)
2418 {
2419 Licq::GroupReadGuard group(*j);
2420 m_nGSID = group->serverId(ownerId);
2421 if (m_nGSID != 0)
2422 break;
2423 }
2424
2425 // No group yet? Use ID of the first one in the list
2426 if (m_nGSID == 0)
2427 {
2428 // First group if none was specified
2429 {
2430 Licq::GroupListGuard groups(false);
2431 if (groups->size() > 0)
2432 {
2433 Group* g = *groups->begin();
2434 g->lockRead();
2435 m_nGSID = g->serverId(ownerId);
2436 g->unlockRead();
2437 }
2438 }
2439
2440 if (m_nGSID == 0)
2441 m_nGSID = 1; // Must never actually reach this point
2442
2443 u->addToGroup(gIcqProtocol.getGroupFromId(m_nGSID));
2444 }
2445
2446 u->SetGSID(m_nGSID);
2447 unicodeName = u->getAlias();
2448 }
2449
2450 string accountId = u->accountId();
2451
2452 SetExtraInfo(m_nGSID);
2453
2454 nLen = accountId.size();
2455 buffer->PackUnsignedShortBE(nLen);
2456 buffer->Pack(accountId.c_str(), nLen);
2457 buffer->PackUnsignedShortBE(m_nGSID);
2458 buffer->PackUnsignedShortBE(m_nSID);
2459 buffer->PackUnsignedShortBE(_nType);
2460
2461 if (!unicodeName.empty())
2462 {
2463 buffer->PackUnsignedShortBE(unicodeName.size() + 4);
2464 buffer->PackUnsignedShortBE(0x0131);
2465 buffer->PackUnsignedShortBE(unicodeName.size());
2466 buffer->pack(unicodeName);
2467 }
2468 else
2469 buffer->PackUnsignedShortBE(0);
2470 }
2471 }
2472
2473 //-----ExportGroupsToServerList-------------------------------------------------
CPU_ExportGroupsToServerList(const GroupNameMap & groups)2474 CPU_ExportGroupsToServerList::CPU_ExportGroupsToServerList(const GroupNameMap& groups)
2475 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxADD)
2476 {
2477 int nSize = 0;
2478 int nGSID = 0;
2479 Licq::UserId ownerId(gIcqProtocol.ownerId());
2480
2481 GroupNameMap::const_iterator g;
2482 for (g = groups.begin(); g != groups.end(); ++g)
2483 {
2484 string unicode = gTranslator.toUnicode(g->second);
2485 nSize += unicode.size();
2486 nSize += 10;
2487 }
2488
2489 m_nSize += nSize;
2490 InitBuffer();
2491
2492 // Not necessary, but just to make it explicit that it occurs
2493 SetExtraInfo(0); // top level group (contains all the groups)
2494
2495 for (g = groups.begin(); g != groups.end(); g++)
2496 {
2497 nGSID = gIcqProtocol.generateSid();
2498
2499 Licq::gUserManager.setGroupServerId(g->first, ownerId, nGSID);
2500
2501 string unicodeName = gTranslator.toUnicode(g->second);
2502
2503 buffer->PackUnsignedShortBE(unicodeName.size());
2504 buffer->pack(unicodeName);
2505 buffer->PackUnsignedShortBE(nGSID);
2506 buffer->PackUnsignedShortBE(0);
2507 buffer->PackUnsignedShortBE(ICQ_ROSTxGROUP);
2508 buffer->PackUnsignedShortBE(0);
2509 }
2510 }
2511
2512 //-----AddPrivacyInfo-----------------------------------------------------------
CPU_AddPDINFOToServerList()2513 CPU_AddPDINFOToServerList::CPU_AddPDINFOToServerList()
2514 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxADD), m_nSID(0),
2515 m_nGSID(0)
2516 {
2517 m_nSID = gIcqProtocol.generateSid();
2518 m_nSize += 15;
2519 InitBuffer();
2520
2521 OwnerWriteGuard o(gIcqProtocol.ownerId());
2522 o->SetPDINFO(m_nSID);
2523
2524 buffer->PackUnsignedShortBE(0);
2525 buffer->PackUnsignedShortBE(0);
2526 buffer->PackUnsignedShortBE(m_nSID);
2527 buffer->PackUnsignedShortBE(ICQ_ROSTxPDINFO);
2528 buffer->PackUnsignedShortBE(5);
2529 buffer->PackUnsignedLongBE(0x00CA0001);
2530 buffer->PackChar(ICQ_PRIVACY_ALLOW_ALL); // Default so users can see us
2531 }
2532
2533 //-----AddToServerList----------------------------------------------------------
CPU_AddToServerList(const Licq::UserId & userId,unsigned short _nType,unsigned short _nGroup,bool _bAuthReq)2534 CPU_AddToServerList::CPU_AddToServerList(const Licq::UserId& userId,
2535 unsigned short _nType,
2536 unsigned short _nGroup, bool _bAuthReq)
2537 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxADD),
2538 m_nSID(gIcqProtocol.generateSid()),
2539 m_nGSID(0)
2540 {
2541 Licq::UserId ownerId(gIcqProtocol.ownerId());
2542
2543 switch (_nType)
2544 {
2545 case ICQ_ROSTxNORMAL:
2546 {
2547 // Save the SID
2548 UserWriteGuard u(userId);
2549 u->SetSID(m_nSID);
2550 u->SetAwaitingAuth(_bAuthReq);
2551
2552 // Check for a group id
2553
2554 {
2555 // Passed in id
2556 m_nGSID = 0;
2557 Licq::GroupReadGuard group(_nGroup);
2558 if (group.isLocked())
2559 m_nGSID = group->serverId(ownerId);
2560 }
2561 if (m_nGSID == 0)
2562 {
2563 // Preset id
2564 m_nGSID = u->GetGSID();
2565 }
2566 if (m_nGSID == 0)
2567 {
2568 // Use the first group the user is in as the server stored group
2569 const UserGroupList& userGroups = u->GetGroups();
2570 for (UserGroupList::iterator iter = userGroups.begin(); iter != userGroups.end(); ++iter)
2571 {
2572 Licq::GroupReadGuard group(*iter);
2573 m_nGSID = group->serverId(ownerId);
2574 if (m_nGSID != 0)
2575 break;
2576 }
2577 }
2578 if (m_nGSID == 0)
2579 {
2580 // Use the first group from the list
2581 Licq::GroupListGuard groups;
2582 if (groups->size() > 0)
2583 {
2584 Group* g = *groups->begin();
2585 g->lockRead();
2586 m_nGSID = g->serverId(ownerId);
2587 g->unlockRead();
2588 }
2589 }
2590 if (m_nGSID == 0)
2591 m_nGSID = 1;
2592
2593 // Get all the TLV's attached to this user, otherwise the server will delete
2594 // all of the ones that we don't send
2595 TlvList tlvs = u->GetTLVList();
2596
2597 // We need to iterate two times since we don't have a dynamic CBuffer
2598 unsigned short extraTlvSize = 0;
2599 TlvList::iterator tlv_iter;
2600 for (tlv_iter = tlvs.begin(); tlv_iter != tlvs.end(); ++tlv_iter)
2601 extraTlvSize += tlv_iter->second->getLength() + 4;
2602
2603 // Make the proper sized buffer for all the TLVs the user has
2604 tlvBuffer.Create(extraTlvSize);
2605
2606 // Now copy them to the new buffer
2607 for (tlv_iter = tlvs.begin(); tlv_iter != tlvs.end(); ++tlv_iter)
2608 tlvBuffer.PackTLV(tlv_iter->second);
2609
2610 SetExtraInfo(m_nGSID);
2611 u->SetGSID(m_nGSID);
2612 u->addToGroup(gIcqProtocol.getGroupFromId(m_nGSID));
2613
2614 break;
2615 }
2616
2617 case ICQ_ROSTxINVISIBLE:
2618 case ICQ_ROSTxVISIBLE:
2619 case ICQ_ROSTxIGNORE:
2620 {
2621 m_nGSID = 0;
2622
2623 UserWriteGuard u(userId);
2624 if (_nType == ICQ_ROSTxIGNORE)
2625 {
2626 u->SetSID(m_nSID);
2627 u->SetGSID(0); // m_nGSID
2628 }
2629 else if (_nType == ICQ_ROSTxVISIBLE)
2630 u->SetVisibleSID(m_nSID);
2631 else
2632 u->SetInvisibleSID(m_nSID);
2633
2634 SetExtraInfo(0); // not necessary except by design
2635 break;
2636 }
2637 }
2638
2639 init(userId.accountId(), _nType, _bAuthReq, false);
2640 }
2641
CPU_AddToServerList(const std::string & groupName,bool _bAuthReq,bool _bTopLevel)2642 CPU_AddToServerList::CPU_AddToServerList(const std::string& groupName,
2643 bool _bAuthReq, bool _bTopLevel)
2644 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxADD),
2645 m_nSID(0),
2646 m_nGSID(_bTopLevel ? 0 : gIcqProtocol.generateSid())
2647 {
2648 Licq::UserId ownerId(gIcqProtocol.ownerId());
2649 SetExtraInfo(0);
2650
2651 if (!_bTopLevel)
2652 {
2653 int groupId = Licq::gUserManager.GetGroupFromName(groupName);
2654 if (groupId != 0)
2655 Licq::gUserManager.setGroupServerId(groupId, ownerId, m_nGSID);
2656 }
2657
2658 init(gTranslator.toUnicode(groupName), ICQ_ROSTxGROUP, _bAuthReq, _bTopLevel);
2659 }
2660
init(const string & name,unsigned short _nType,bool _bAuthReq,bool _bTopLevel)2661 void CPU_AddToServerList::init(const string& name, unsigned short _nType, bool _bAuthReq, bool _bTopLevel)
2662 {
2663 unsigned short nExportSize = (_bTopLevel ? (4 + (2 * gUserManager.NumGroups())) : 0);
2664
2665 // Do we need extras since we handle the tlvs as a complete block?
2666 m_nSize += 10+name.size()+nExportSize+(_bAuthReq ? 4 : 0)+tlvBuffer.getDataSize();
2667
2668 InitBuffer();
2669
2670 buffer->packString16BE(name);
2671 buffer->PackUnsignedShortBE(m_nGSID);
2672 buffer->PackUnsignedShortBE(m_nSID);
2673 buffer->PackUnsignedShortBE(_nType);
2674 // TODO should only be tlvBuffer.getDataSize()
2675 buffer->PackUnsignedShortBE(nExportSize+(_bAuthReq ? 4 : 0)+tlvBuffer.getDataSize());
2676 if (nExportSize)
2677 {
2678 if (_bTopLevel)
2679 {
2680 Licq::UserId ownerId(gIcqProtocol.ownerId());
2681
2682 // We are creating our top level group, so attach all the group ids now
2683 buffer->PackUnsignedShortBE(0x00C8);
2684 buffer->PackUnsignedShortBE(gUserManager.NumGroups() * 2);
2685
2686 Licq::GroupListGuard groupList(false);
2687 BOOST_FOREACH(const Licq::Group* group, **groupList)
2688 {
2689 Licq::GroupReadGuard pGroup(group);
2690 buffer->PackUnsignedShortBE(pGroup->serverId(ownerId));
2691 }
2692 }
2693 else
2694 {
2695 // Addming a normal user, so save their alias
2696 // TODO Have this be a part of tlvBuffer
2697 buffer->PackUnsignedShortBE(0x0131);
2698 buffer->PackUnsignedShortBE(nExportSize-4);
2699 if (_nType == ICQ_ROSTxGROUP)
2700 buffer->Pack(name.c_str(), nExportSize-4);
2701 }
2702 }
2703
2704 // TODO Have this be a part of tlvBuffer so we don't need this check against tlvBuffer
2705 if (_bAuthReq && !tlvBuffer.hasTLV(0x0066))
2706 buffer->PackUnsignedLongBE(0x00660000);
2707
2708 if (!tlvBuffer.Empty())
2709 buffer->Pack(&tlvBuffer);
2710 }
2711
2712 //-----RemoveFromServerList-----------------------------------------------------
CPU_RemoveFromServerList(const Licq::UserId & userId,unsigned short _nGSID,unsigned short _nSID,unsigned short _nType)2713 CPU_RemoveFromServerList::CPU_RemoveFromServerList(const Licq::UserId& userId,
2714 unsigned short _nGSID, unsigned short _nSID, unsigned short _nType)
2715 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxREM)
2716 {
2717 if (_nType == ICQ_ROSTxNORMAL)
2718 {
2719 UserReadGuard u(userId);
2720 if (u.isLocked())
2721 {
2722 TlvList tlvs = u->GetTLVList();
2723
2724 unsigned short extraTlvSize = 0;
2725 TlvList::iterator tlv_iter;
2726 for (tlv_iter = tlvs.begin(); tlv_iter != tlvs.end(); ++tlv_iter)
2727 extraTlvSize += tlv_iter->second->getLength() + 4;
2728
2729 // Make the proper sized buffer for all the TLVs the user has
2730 tlvBuffer.Create(extraTlvSize);
2731
2732 // Now copy them to the new buffer
2733 for (tlv_iter = tlvs.begin(); tlv_iter != tlvs.end(); ++tlv_iter)
2734 tlvBuffer.PackTLV(tlv_iter->second);
2735 }
2736 }
2737
2738 init(userId.accountId(), _nGSID, _nSID, _nType);
2739 }
2740
CPU_RemoveFromServerList(const string & groupName,unsigned short _nGSID)2741 CPU_RemoveFromServerList::CPU_RemoveFromServerList(const string& groupName,
2742 unsigned short _nGSID)
2743 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxREM)
2744 {
2745 init(gTranslator.toUnicode(groupName), _nGSID, 0, ICQ_ROSTxGROUP);
2746 }
2747
init(const string & name,unsigned short _nGSID,unsigned short _nSID,unsigned short _nType)2748 void CPU_RemoveFromServerList::init(const string& name,
2749 unsigned short _nGSID, unsigned short _nSID, unsigned short _nType)
2750 {
2751 m_nSize += 10+name.size()+tlvBuffer.getDataSize();
2752 InitBuffer();
2753
2754 buffer->packString16BE(name);
2755 buffer->PackUnsignedShortBE(_nGSID);
2756 buffer->PackUnsignedShortBE(_nSID);
2757 buffer->PackUnsignedShortBE(_nType);
2758 buffer->PackUnsignedShortBE(static_cast<unsigned short>(tlvBuffer.getDataSize()));
2759 if (!tlvBuffer.Empty())
2760 buffer->Pack(&tlvBuffer);
2761
2762 if (_nType == ICQ_ROSTxGROUP)
2763 SetExtraInfo(0);
2764 else
2765 SetExtraInfo(_nGSID);
2766 }
2767
2768 //-----ClearServerList------------------------------------------------------
CPU_ClearServerList(const std::list<Licq::UserId> & userIds,unsigned short _nType)2769 CPU_ClearServerList::CPU_ClearServerList(const std::list<Licq::UserId>& userIds,
2770 unsigned short _nType)
2771 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxREM)
2772 {
2773 int nSize = 0;
2774 std::list<Licq::UserId>::const_iterator i;
2775
2776 if (_nType == ICQ_ROSTxGROUP)
2777 return;
2778
2779 for (i = userIds.begin(); i != userIds.end(); ++i)
2780 {
2781 Licq::UserReadGuard u(*i);
2782 if (u.isLocked())
2783 {
2784 nSize += i->accountId().size() + 2;
2785 nSize += 8;
2786 if (u->GetAwaitingAuth())
2787 nSize += 4;
2788 }
2789 }
2790
2791 m_nSize += nSize;
2792 InitBuffer();
2793
2794 for (i = userIds.begin(); i != userIds.end(); i++)
2795 {
2796 UserWriteGuard pUser(*i);
2797 if (pUser.isLocked())
2798 {
2799 bool bAuthReq = pUser->GetAwaitingAuth();
2800 unsigned short nGSID = 0;
2801
2802 if (_nType == ICQ_ROSTxNORMAL)
2803 nGSID = pUser->GetGSID();
2804
2805 buffer->packString16BE(i->accountId());
2806 buffer->PackUnsignedShortBE(nGSID);
2807 buffer->PackUnsignedShortBE(pUser->GetSID());
2808 buffer->PackUnsignedShortBE(_nType);
2809 buffer->PackUnsignedShortBE(bAuthReq ? 4 : 0);
2810 if (bAuthReq)
2811 buffer->PackUnsignedLongBE(0x00660000);
2812
2813 // Clear their info now
2814 if (_nType == ICQ_ROSTxNORMAL)
2815 {
2816 pUser->SetSID(0);
2817 pUser->SetGSID(0);
2818 }
2819 else if (_nType == ICQ_ROSTxVISIBLE)
2820 pUser->SetVisibleSID(0);
2821 else if (_nType == ICQ_ROSTxINVISIBLE)
2822 pUser->SetInvisibleSID(0);
2823
2824 if (pUser->GetSID() == 0 && pUser->GetVisibleSID() == 0 &&
2825 pUser->GetInvisibleSID() == 0)
2826 pUser->SetAwaitingAuth(false);
2827
2828 pUser->save(Licq::User::SaveLicqInfo);
2829 }
2830 }
2831 }
2832
2833 //-----UpdateToServerList---------------------------------------------------
CPU_UpdateToServerList(const Licq::UserId & userId,unsigned short _nType,bool _bAuthReq)2834 CPU_UpdateToServerList::CPU_UpdateToServerList(const Licq::UserId& userId,
2835 unsigned short _nType,
2836 bool _bAuthReq)
2837 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxUPD_GROUP)
2838 {
2839 unsigned short nGSID = 0;
2840 unsigned short nSID = 0;
2841 unsigned short nExtraLen = 0;
2842
2843 switch (_nType)
2844 {
2845 case ICQ_ROSTxNORMAL:
2846 {
2847 UserReadGuard u(userId);
2848 if (u.isLocked())
2849 {
2850 if (u->GetAwaitingAuth())
2851 _bAuthReq = true;
2852
2853 // Get all the TLV's attached to this user, otherwise the server will delete
2854 // all of the ones that we don't send
2855 TlvList tlvs = u->GetTLVList();
2856
2857 // We need to iterate two times since we don't have a dynamic CBuffer
2858 unsigned short extraTlvSize = 0;
2859 TlvList::iterator tlv_iter;
2860 for (tlv_iter = tlvs.begin(); tlv_iter != tlvs.end(); ++tlv_iter)
2861 extraTlvSize += tlv_iter->second->getLength() + 4;
2862
2863 // Make the proper sized buffer for all the TLVs the user has
2864 tlvBuffer.Create(extraTlvSize);
2865
2866 // Now copy them to the new buffer
2867 for (tlv_iter = tlvs.begin(); tlv_iter != tlvs.end(); ++tlv_iter)
2868 tlvBuffer.PackTLV(tlv_iter->second);
2869
2870 nGSID = u->GetGSID();
2871 nSID = u->GetSID();
2872 nExtraLen = tlvBuffer.getDataSize();
2873 }
2874
2875 break;
2876 }
2877 }
2878
2879 init(userId.accountId(), _nType, _bAuthReq, nGSID, nSID, nExtraLen);
2880 }
2881
CPU_UpdateToServerList(const string & name,unsigned short nGSID)2882 CPU_UpdateToServerList::CPU_UpdateToServerList(const string& name, unsigned short nGSID)
2883 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxUPD_GROUP)
2884 {
2885 unsigned short nExtraLen = 0;
2886 Licq::UserId ownerId(gIcqProtocol.ownerId());
2887
2888 if (nGSID == 0)
2889 {
2890 // Get group ids from list, we'll need them later
2891 Licq::GroupListGuard groups;
2892 BOOST_FOREACH(const Group* i, **groups)
2893 {
2894 i->lockRead();
2895 groupIds.push_back(i->serverId(ownerId));
2896 i->unlockRead();
2897 }
2898 nExtraLen += (groups->size() * 2);
2899 }
2900 else
2901 {
2902 Licq::UserListGuard userList(ownerId);
2903 BOOST_FOREACH(const Licq::User* user, **userList)
2904 {
2905 if (user->protocolId() != ICQ_PPID)
2906 continue;
2907 UserReadGuard pUser(dynamic_cast<const User*>(user));
2908 if (pUser->GetGSID() == nGSID)
2909 nExtraLen += 2;
2910 }
2911 }
2912
2913 if (nExtraLen)
2914 nExtraLen += 4;
2915
2916 init(gTranslator.toUnicode(name), ICQ_ROSTxGROUP, false, nGSID, 0, nExtraLen);
2917 }
2918
init(const std::string & name,unsigned short _nType,bool _bAuthReq,unsigned short nGSID,unsigned short nSID,unsigned short nExtraLen)2919 void CPU_UpdateToServerList::init(const std::string& name, unsigned short _nType, bool _bAuthReq,
2920 unsigned short nGSID, unsigned short nSID, unsigned short nExtraLen)
2921 {
2922 m_nSize += 10 + name.size() + nExtraLen + (_bAuthReq ? 4 : 0);
2923 InitBuffer();
2924
2925 buffer->PackUnsignedShortBE(name.size());
2926 buffer->pack(name);
2927 buffer->PackUnsignedShortBE(nGSID);
2928 buffer->PackUnsignedShortBE(nSID);
2929 buffer->PackUnsignedShortBE(_nType);
2930 buffer->PackUnsignedShortBE(nExtraLen + (_bAuthReq ? 4 : 0));
2931 if (nExtraLen)
2932 {
2933 if (_nType == ICQ_ROSTxNORMAL)
2934 {
2935 buffer->Pack(&tlvBuffer);
2936 }
2937 else if (_nType == ICQ_ROSTxGROUP)
2938 {
2939 buffer->PackUnsignedShortBE(0x00C8);
2940 buffer->PackUnsignedShortBE(nExtraLen-4);
2941
2942 if (nGSID == 0)
2943 {
2944 BOOST_FOREACH(unsigned long id, groupIds)
2945 buffer->PackUnsignedShortBE(id);
2946 }
2947 else
2948 {
2949 Licq::UserListGuard userList;
2950 BOOST_FOREACH(const Licq::User* user, **userList)
2951 {
2952 if (user->protocolId() != ICQ_PPID)
2953 continue;
2954 UserReadGuard pUser(dynamic_cast<const User*>(user));
2955 if (pUser->GetGSID() == nGSID)
2956 buffer->PackUnsignedShortBE(pUser->GetSID());
2957 }
2958 }
2959 }
2960 }
2961
2962 if (_bAuthReq)
2963 buffer->PackUnsignedLongBE(0x00660000);
2964 }
2965
2966 //-----SearchWhitePages---------------------------------------------------------
CPU_SearchWhitePages(const string & firstName,const string & lastName,const string & alias,const string & email,unsigned short nMinAge,unsigned short nMaxAge,char nGender,char nLanguage,const string & city,const string & state,unsigned short nCountryCode,const string & coName,const string & coDept,const string & coPos,const string & keyword,bool bOnlineOnly)2967 CPU_SearchWhitePages::CPU_SearchWhitePages(const string& firstName, const string& lastName,
2968 const string& alias, const string& email, unsigned short nMinAge, unsigned short nMaxAge,
2969 char nGender, char nLanguage, const string& city, const string& state,
2970 unsigned short nCountryCode, const string& coName, const string& coDept,
2971 const string& coPos, const string& keyword, bool bOnlineOnly)
2972 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
2973 {
2974 unsigned short nDataLen; // length of data info to add packet size
2975
2976 nDataLen = lengthField(firstName) + lengthField(lastName) +
2977 lengthField(alias) + lengthField(city) +
2978 lengthField(email) + lengthField(state) +
2979 lengthField(coName) + lengthField(coDept) +
2980 lengthField(coPos) + lengthField(keyword);
2981
2982 nDataLen += 5*!(!nGender) + 6*!(!nLanguage) + 4*(!(!nMaxAge) + !(!nMinAge))
2983 + 6*(!(!nCountryCode)) + 5*(bOnlineOnly);
2984 m_nSize += 16 + nDataLen;
2985 m_nMetaCommand = ICQ_CMDxMETA_SEARCHxWP;
2986 InitBuffer();
2987
2988 // Fix invalid ages. Ensure that the plugin doesn't make an invalid request
2989 if (nMinAge != 0 || nMaxAge != 0)
2990 {
2991 if (nMinAge <= 18) nMinAge = 18;
2992 else if (nMinAge <= 23) nMinAge = 23;
2993 else if (nMinAge <= 30) nMinAge = 30;
2994 else if (nMinAge <= 40) nMinAge = 40;
2995 else if (nMinAge <= 50) nMinAge = 50;
2996 else nMinAge = 60;
2997
2998 switch (nMinAge)
2999 {
3000 case 18: nMaxAge = 22; break;
3001 case 23: nMaxAge = 29; break;
3002 case 30: nMaxAge = 39; break;
3003 case 40: nMaxAge = 49; break;
3004 case 50: nMaxAge = 59; break;
3005 case 60: nMaxAge = 10000; break;
3006 }
3007 }
3008
3009 buffer->PackUnsignedShortBE(0x0001);
3010 buffer->PackUnsignedShortBE(16 + nDataLen - 4);
3011 buffer->PackUnsignedShort(16 + nDataLen - 6);
3012 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3013 buffer->PackUnsignedShortBE(0xd007);
3014 buffer->PackUnsignedShortBE(m_nSubSequence);
3015 buffer->PackUnsignedShort(m_nMetaCommand);
3016
3017 packSearch(ICQ_CMDxWPxFNAME, firstName);
3018 packSearch(ICQ_CMDxWPxLNAME, lastName);
3019 packSearch(ICQ_CMDxWPxALIAS, alias);
3020 packSearch(ICQ_CMDxWPxEMAIL, email);
3021 packSearch(ICQ_CMDxWPxCITY, city);
3022 packSearch(ICQ_CMDxWPxSTATE, state);
3023 packSearch(ICQ_CMDxWPxCOMPANY, coName);
3024 packSearch(ICQ_CMDxWPxCODEPT, coDept);
3025 packSearch(ICQ_CMDxWPxCOPOS, coPos);
3026 packSearch(ICQ_CMDxWPxKEYWORD, keyword);
3027
3028 if (nMinAge)
3029 {
3030 buffer->PackUnsignedShortBE(ICQ_CMDxWPxAGE);
3031 buffer->PackUnsignedShort(0x04); // length
3032 buffer->PackUnsignedShort(nMinAge);
3033 buffer->PackUnsignedShort(nMaxAge);
3034 }
3035 if (nGender)
3036 {
3037 buffer->PackUnsignedShortBE(ICQ_CMDxWPxGENDER);
3038 buffer->PackUnsignedShort(0x01); // length
3039 buffer->PackChar(nGender);
3040 }
3041 if (nLanguage)
3042 {
3043 buffer->PackUnsignedShortBE(ICQ_CMDxWPxLANGUAGE);
3044 buffer->PackUnsignedShort(0x02); // length
3045 buffer->PackUnsignedShort(nLanguage);
3046 }
3047 if (nCountryCode)
3048 {
3049 buffer->PackUnsignedShortBE(ICQ_CMDxWPxCOUNTRY);
3050 buffer->PackUnsignedShort(0x02); // length
3051 buffer->PackUnsignedShort(nCountryCode);
3052 }
3053 if (bOnlineOnly)
3054 {
3055 buffer->PackUnsignedShortBE(ICQ_CMDxWPxONLINE);
3056 buffer->PackUnsignedShort(0x01); // length
3057 buffer->PackChar(0x01);
3058 }
3059 }
3060
packSearch(unsigned short nCmd,const string & field)3061 void CPU_SearchWhitePages::packSearch(unsigned short nCmd, const string& field)
3062 {
3063 // By SC
3064 // Pack string field info if exist
3065
3066 int nLenField = field.size() + 1;
3067
3068 if (nLenField > 1)
3069 {
3070 buffer->PackUnsignedShortBE(nCmd);
3071 buffer->PackUnsignedShort(nLenField + 2);
3072 buffer->packShortNullStringLE(field);
3073 }
3074 }
3075
3076 //-----SearchByUin--------------------------------------------------------------
CPU_SearchByUin(unsigned long nUin)3077 CPU_SearchByUin::CPU_SearchByUin(unsigned long nUin)
3078 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3079 {
3080 m_nMetaCommand = ICQ_CMDxMETA_SEARCHxUIN;
3081 int nPacketSize = 24; //2+2+2+4+2+2+2+4+4;
3082 m_nSize += nPacketSize;
3083 InitBuffer();
3084
3085 // TLV 1
3086 buffer->PackUnsignedShortBE(0x0001);
3087 buffer->PackUnsignedShortBE(nPacketSize - 4);
3088 buffer->PackUnsignedShort(nPacketSize - 6); // bytes remaining
3089 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3090 buffer->PackUnsignedShortBE(0xD007); // type
3091 buffer->PackUnsignedShortBE(m_nSubSequence);
3092 buffer->PackUnsignedShort(m_nMetaCommand); // sub type
3093
3094 buffer->PackUnsignedLongBE(0x36010400);
3095 buffer->PackUnsignedLong(nUin);
3096 }
3097
3098
3099 //-----UpdatePersonalInfo-------------------------------------------------------
CPU_UpdatePersonalBasicInfo(const string & alias,const string & firstName,const string & lastName,const string & email,bool bAuthorization)3100 CPU_UpdatePersonalBasicInfo::CPU_UpdatePersonalBasicInfo(const string& alias,
3101 const string& firstName, const string& lastName, const string& email, bool bAuthorization)
3102 : CPacketUdp(ICQ_CMDxSND_UPDATExBASIC),
3103 myAlias(alias), myFirstName(firstName), myLastName(lastName), myEmail(email)
3104 {
3105 m_nAuthorization = bAuthorization ? 0 : 1;
3106
3107 m_nSize += 15 + alias.size() + firstName.size() + lastName.size() + email.size();
3108 InitBuffer();
3109
3110 #if ICQ_VERSION == 2
3111 buffer->PackUnsignedShort(m_nSubSequence);
3112 #endif
3113
3114 buffer->packShortNullStringLE(alias);
3115 buffer->packShortNullStringLE(firstName);
3116 buffer->packShortNullStringLE(lastName);
3117 buffer->packShortNullStringLE(email);
3118 buffer->PackChar(m_nAuthorization);
3119
3120 }
3121
3122
3123 //-----UpdatePersonalExtInfo-------------------------------------------------------
CPU_UpdatePersonalExtInfo(const string & city,unsigned short nCountry,const string & state,unsigned short nAge,char cSex,const string & phone,const string & homepage,const string & about,unsigned long nZipcode)3124 CPU_UpdatePersonalExtInfo::CPU_UpdatePersonalExtInfo(const string& city,
3125 unsigned short nCountry, const string& state, unsigned short nAge, char cSex,
3126 const string& phone, const string& homepage, const string& about, unsigned long nZipcode)
3127 : CPacketUdp(ICQ_CMDxSND_UPDATExDETAIL),
3128 myCity(city), myState(state), myPhone(phone), myHomepage(homepage), myAbout(about)
3129 {
3130
3131 m_nCountry = nCountry;
3132 m_cTimezone = Licq::User::systemTimezone() / -1800;
3133 m_nAge = nAge;
3134 m_cSex = cSex;
3135 m_nZipcode = nZipcode;
3136 if (myState.size() > 5)
3137 myState.resize(5);
3138
3139 m_nSize += city.size() + state.size() + phone.size() + homepage.size() + about.size() + 27;
3140 InitBuffer();
3141
3142 #if ICQ_VERSION == 2
3143 buffer->PackUnsignedShort(m_nSubSequence);
3144 #endif
3145
3146 buffer->packShortNullStringLE(city);
3147 buffer->PackUnsignedShort(m_nCountry);
3148 buffer->PackChar(m_cTimezone);
3149 buffer->packShortNullStringLE(myState);
3150 buffer->PackUnsignedShort(m_nAge);
3151 buffer->PackChar(m_cSex);
3152 buffer->packShortNullStringLE(phone);
3153 buffer->packShortNullStringLE(homepage);
3154 buffer->packShortNullStringLE(about);
3155 buffer->PackUnsignedLong(m_nZipcode);
3156
3157 }
3158
3159
3160
3161 //-----Ping---------------------------------------------------------------------
CPU_Ping()3162 CPU_Ping::CPU_Ping()
3163 : CSrvPacketTcp(ICQ_CHNxPING)
3164 {
3165 InitBuffer();
3166 }
3167
3168
CPU_ReverseTCPRequest(unsigned long nDestinationUin,unsigned long nIp,unsigned short nPort,unsigned short nPort2)3169 CPU_ReverseTCPRequest::CPU_ReverseTCPRequest(unsigned long nDestinationUin,
3170 unsigned long nIp, unsigned short nPort,
3171 unsigned short nPort2)
3172 : CPacketUdp(ICQ_CMDxRCV_REVERSExTCP)
3173 {
3174 m_nDestinationUin = nDestinationUin;
3175 m_nSize += 21;
3176
3177 InitBuffer();
3178
3179 buffer->PackUnsignedLong( nDestinationUin );
3180 buffer->PackUnsignedLong( nIp ); // IP
3181 buffer->PackUnsignedShort( nPort ); // port
3182 buffer->PackUnsignedShort( nPort ); // junk
3183 buffer->PackChar( 6 );
3184 buffer->PackUnsignedShort( nPort2 ); //nport2
3185 buffer->PackUnsignedShort( nPort2 ); // junk nport2
3186 // junk twice
3187 buffer->PackUnsignedLong( nPort );
3188 }
3189 #if 0
3190 unsigned long nUin, nIp;
3191 unsigned short nPort, nJunk, nPort2, nVersion;
3192 char cJunk;
3193 packet >> nUin >> nIp
3194 >> nPort >> nJunk
3195 >> cJunk
3196 >> nPort2 >> nJunk // port which they tried to connect to
3197 >> nJunk >> nJunk // nPort again
3198 >> nVersion;
3199 nIp = LE_32(nIp);
3200 #endif
3201
3202
3203
3204 //-----Authorize----------------------------------------------------------------
CPU_Authorize(const string & accountId)3205 CPU_Authorize::CPU_Authorize(const string& accountId)
3206 : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_AUTHxGRANT)
3207 {
3208 m_nSize += 1 + accountId.size() + 5;
3209 InitBuffer();
3210
3211 buffer->PackChar(accountId.size());
3212 buffer->pack(accountId);
3213 buffer->PackChar(0x01);
3214 buffer->PackUnsignedLong(0);
3215 }
3216
3217 //------SetPassword---------------------------------------------------------
CPU_SetPassword(const string & password)3218 CPU_SetPassword::CPU_SetPassword(const string& password)
3219 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA),
3220 myPassword(password)
3221 {
3222 m_nSubCommand = ICQ_CMDxMETA_PASSWORDxSET;
3223
3224 unsigned short nDataLen = password.size() + 19;
3225 m_nSize += nDataLen;
3226 InitBuffer();
3227
3228 buffer->PackUnsignedShortBE(0x0001);
3229 buffer->PackUnsignedShortBE(nDataLen - 4);
3230 buffer->PackUnsignedShort(nDataLen - 6);
3231 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3232 buffer->PackUnsignedShortBE(0xd007);
3233 buffer->PackUnsignedShortBE(m_nSubSequence);
3234 buffer->PackUnsignedShort(ICQ_CMDxMETA_PASSWORDxSET);
3235
3236 // LNTS, but we want the password in this class
3237 //buffer->PackUnsignedShort(nDataLen - 19);
3238 buffer->packShortNullStringLE(password);
3239 //buffer->PackChar(0x00);
3240 }
3241
3242 //-----RequestSysMsg------------------------------------------------------------
CPU_RequestSysMsg()3243 CPU_RequestSysMsg::CPU_RequestSysMsg()
3244 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3245 {
3246 m_nMetaCommand = ICQ_CMDxSND_SYSxMSGxREQ;
3247 m_nSize += 14;
3248
3249 InitBuffer();
3250
3251 buffer->PackUnsignedLongBE(0x0001000a); // TLV
3252 buffer->PackUnsignedShort(8);
3253 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3254 buffer->PackUnsignedShort(ICQ_CMDxSND_SYSxMSGxREQ);
3255 buffer->PackUnsignedShortBE(0x0200);
3256 }
3257
3258 //-----SysMsgDoneAck------------------------------------------------------------
CPU_SysMsgDoneAck(unsigned short nId)3259 CPU_SysMsgDoneAck::CPU_SysMsgDoneAck(unsigned short nId)
3260 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3261 {
3262 m_nMetaCommand = ICQ_CMDxSND_SYSxMSGxDONExACK;
3263 m_nSize += 14;
3264
3265 InitBuffer();
3266
3267 buffer->PackUnsignedLongBE(0x0001000a); // TLV
3268 buffer->PackUnsignedShort(0x0008); // len again
3269 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3270 buffer->PackUnsignedShort(ICQ_CMDxSND_SYSxMSGxDONExACK);
3271 buffer->PackUnsignedShortBE(nId);
3272 }
3273
3274 //-----CPU_SetRandomChatGroup------------------------------------------------
CPU_SetRandomChatGroup(unsigned long nGroup)3275 CPU_SetRandomChatGroup::CPU_SetRandomChatGroup(unsigned long nGroup)
3276 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3277 {
3278 m_nGroup = nGroup;
3279 m_nMetaCommand = ICQ_CMDxMETA_SETxRANDOMxCHAT;
3280 unsigned short nPacketSize = 18;
3281 if (nGroup)
3282 nPacketSize += 33;
3283
3284 m_nSize += nPacketSize;
3285 InitBuffer();
3286
3287 // TLV 1
3288 buffer->PackUnsignedShortBE(0x0001);
3289 buffer->PackUnsignedShortBE(nPacketSize - 4);
3290 buffer->PackUnsignedShort(nPacketSize - 6); // bytes remaining
3291 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3292 buffer->PackUnsignedShortBE(0xD007); // type
3293 buffer->PackUnsignedShortBE(m_nSubSequence);
3294 buffer->PackUnsignedShort(m_nMetaCommand); // sub type
3295
3296 buffer->PackUnsignedShort(nGroup);
3297 if (nGroup)
3298 {
3299 buffer->PackUnsignedLongBE(0x00000300);
3300 buffer->PackUnsignedLong(RealIp());
3301 buffer->PackUnsignedLong(0); // port
3302 buffer->PackUnsignedLong(LocalIp());
3303 buffer->PackChar(gIcqProtocol.directMode() ? MODE_DIRECT : MODE_INDIRECT);
3304 buffer->PackUnsignedLong(ICQ_VERSION_TCP);
3305 buffer->PackUnsignedLong(0x00000000);
3306 buffer->PackUnsignedLong(0x00000050);
3307 buffer->PackUnsignedLong(0x00000003);
3308 }
3309 }
3310
3311
3312 //-----CPU_RandomChatSearch--------------------------------------------------
CPU_RandomChatSearch(unsigned long nGroup)3313 CPU_RandomChatSearch::CPU_RandomChatSearch(unsigned long nGroup)
3314 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3315 {
3316 m_nMetaCommand = ICQ_CMDxMETA_RANDOMxSEARCH;
3317 unsigned short nPacketSize = 18;
3318
3319 m_nSize += nPacketSize;
3320 InitBuffer();
3321
3322 // TLV 1
3323 buffer->PackUnsignedShortBE(0x0001);
3324 buffer->PackUnsignedShortBE(nPacketSize - 4);
3325 buffer->PackUnsignedShort(nPacketSize - 6); //bytes remaining
3326 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3327 buffer->PackUnsignedShortBE(0xD007); // type
3328 buffer->PackUnsignedShortBE(m_nSubSequence);
3329 buffer->PackUnsignedShort(m_nMetaCommand); // sub type
3330 buffer->PackUnsignedShort(nGroup);
3331 }
3332
3333
CPU_Meta_SetGeneralInfo(const string & alias,const string & firstName,const string & lastName,const string & emailPrimary,const string & city,const string & state,const string & phoneNumber,const string & faxNumber,const string & address,const string & cellularNumber,const string & zipCode,unsigned short nCountryCode,bool bHideEmail)3334 CPU_Meta_SetGeneralInfo::CPU_Meta_SetGeneralInfo(const string& alias,
3335 const string& firstName, const string& lastName, const string& emailPrimary,
3336 const string& city, const string& state, const string& phoneNumber,
3337 const string& faxNumber, const string& address, const string& cellularNumber,
3338 const string& zipCode, unsigned short nCountryCode, bool bHideEmail)
3339 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA),
3340 myAlias(alias), myFirstName(firstName), myLastName(lastName),
3341 myEmailPrimary(emailPrimary), myCity(city), myState(state),
3342 myPhoneNumber(phoneNumber), myFaxNumber(faxNumber), myAddress(address),
3343 myCellularNumber(cellularNumber), myZipCode(zipCode)
3344 {
3345 m_nMetaCommand = ICQ_CMDxMETA_WPxINFOxSET;
3346
3347 m_nCountryCode = nCountryCode;
3348 m_nTimezone = Licq::User::systemTimezone() / -1800;
3349 m_nHideEmail = bHideEmail ? 1 : 0;
3350
3351 int packetSize = 2+2+2+4+2+2+2 + alias.size() + firstName.size() + lastName.size() +
3352 emailPrimary.size() + city.size() + state.size() + phoneNumber.size() +
3353 faxNumber.size() + address.size() + zipCode.size() + cellularNumber.size() + 89;
3354 m_nSize += packetSize;
3355 InitBuffer();
3356
3357 buffer->PackUnsignedShortBE(1);
3358 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
3359 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
3360 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3361 buffer->PackUnsignedShortBE(0xD007); // type
3362 buffer->PackUnsignedShortBE(m_nSubSequence);
3363 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
3364
3365 buffer->PackUnsignedShortBE(ICQ_CMDxWPxTIMEZONE);
3366 buffer->PackUnsignedShort(0x0001);
3367 buffer->PackChar(m_nTimezone);
3368
3369 buffer->PackUnsignedShortBE(ICQ_CMDxWPxALIAS);
3370 buffer->PackUnsignedShort(alias.size()+3);
3371 buffer->packShortNullStringLE(alias);
3372
3373 buffer->PackUnsignedShortBE(ICQ_CMDxWPxFNAME);
3374 buffer->PackUnsignedShort(firstName.size()+3);
3375 buffer->packShortNullStringLE(firstName);
3376
3377 buffer->PackUnsignedShortBE(ICQ_CMDxWPxLNAME);
3378 buffer->PackUnsignedShort(lastName.size()+3);
3379 buffer->packShortNullStringLE(lastName);
3380
3381 buffer->PackUnsignedShortBE(ICQ_CMDxWPxEMAIL);
3382 buffer->PackUnsignedShort(emailPrimary.size()+3);
3383 buffer->packShortNullStringLE(emailPrimary);
3384 buffer->PackChar(m_nHideEmail);
3385
3386 buffer->PackUnsignedShortBE(ICQ_CMDxWPxCITY);
3387 buffer->PackUnsignedShort(city.size()+3);
3388 buffer->packShortNullStringLE(city);
3389
3390 buffer->PackUnsignedShortBE(ICQ_CMDxWPxSTATE);
3391 buffer->PackUnsignedShort(state.size()+3);
3392 buffer->packShortNullStringLE(state);
3393
3394 buffer->PackUnsignedShortBE(ICQ_CMDxWPxPHONExHOME);
3395 buffer->PackUnsignedShort(phoneNumber.size()+3);
3396 buffer->packShortNullStringLE(phoneNumber);
3397
3398 buffer->PackUnsignedShortBE(ICQ_CMDxWPxHOME_FAX);
3399 buffer->PackUnsignedShort(faxNumber.size()+3);
3400 buffer->packShortNullStringLE(faxNumber);
3401
3402 buffer->PackUnsignedShortBE(ICQ_CMDxWPxHOME_ADDR);
3403 buffer->PackUnsignedShort(address.size()+3);
3404 buffer->packShortNullStringLE(address);
3405
3406 buffer->PackUnsignedShortBE(ICQ_CMDxWPxPHONExCELL);
3407 buffer->PackUnsignedShort(cellularNumber.size()+3);
3408 buffer->packShortNullStringLE(cellularNumber);
3409
3410 buffer->PackUnsignedShortBE(ICQ_CMDxWPxHOME_ZIP);
3411 buffer->PackUnsignedShort(zipCode.size()+3);
3412 buffer->packShortNullStringLE(zipCode);
3413
3414 buffer->PackUnsignedShortBE(ICQ_CMDxWPxCOUNTRY);
3415 buffer->PackUnsignedShort(0x0002);
3416 buffer->PackUnsignedShort(m_nCountryCode);
3417
3418 // Check for possible problems
3419 //ar *sz = m_szAlias;
3420 //ile (*sz != '\0' && strncasecmp(sz, "icq", 3) != 0) sz++;
3421 // (*sz != '\0')
3422 //
3423 //gLog.warning(tr("Alias may not contain \"icq\"."));
3424 //*sz = '-';
3425 //
3426 }
3427
3428 //-----Meta_SetEmailInfo------------------------------------------------------
CPU_Meta_SetEmailInfo(const string & emailSecondary,const string & emailOld)3429 CPU_Meta_SetEmailInfo::CPU_Meta_SetEmailInfo(const string& emailSecondary, const string& emailOld)
3430 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA),
3431 myEmailSecondary(emailSecondary), myEmailOld(emailOld)
3432 {
3433 m_nMetaCommand = ICQ_CMDxMETA_EMAILxINFOxSET;
3434
3435 int packetSize = 2+2+2+4+2+2+2 + emailSecondary.size() + 3
3436 + emailOld.size() + 3 + 3;
3437 m_nSize += packetSize;
3438 InitBuffer();
3439
3440 buffer->PackUnsignedShortBE(1);
3441 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
3442
3443 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
3444 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3445 buffer->PackUnsignedShortBE(0xD007); // type
3446 buffer->PackUnsignedShortBE(m_nSubSequence);
3447 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
3448
3449 buffer->PackChar(2);
3450 buffer->PackChar(0);
3451 buffer->packShortNullStringLE(emailSecondary);
3452 buffer->PackChar(0);
3453 buffer->packShortNullStringLE(emailOld);
3454 }
3455
3456 //-----Meta_SetMoreInfo------------------------------------------------------
CPU_Meta_SetMoreInfo(unsigned short nAge,char nGender,const string & homepage,unsigned short nBirthYear,char nBirthMonth,char nBirthDay,char nLanguage1,char nLanguage2,char nLanguage3)3457 CPU_Meta_SetMoreInfo::CPU_Meta_SetMoreInfo( unsigned short nAge, char nGender,
3458 const string& homepage, unsigned short nBirthYear, char nBirthMonth,
3459 char nBirthDay, char nLanguage1, char nLanguage2, char nLanguage3)
3460 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA),
3461 myHomepage(homepage)
3462 {
3463 m_nMetaCommand = ICQ_CMDxMETA_WPxINFOxSET;
3464
3465 m_nAge = nAge;
3466 m_nGender = nGender;
3467 m_nBirthYear = nBirthYear;
3468 m_nBirthMonth = nBirthMonth;
3469 m_nBirthDay = nBirthDay;
3470 m_nLanguage1 = nLanguage1;
3471 m_nLanguage2 = nLanguage2;
3472 m_nLanguage3 = nLanguage3;
3473
3474 int packetSize = 2+2+2+4+2+2+2 + homepage.size()+3 + 43;
3475 m_nSize += packetSize;
3476 InitBuffer();
3477
3478 buffer->PackUnsignedShortBE(1);
3479 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
3480
3481 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
3482 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3483 buffer->PackUnsignedShortBE(0xD007); // type
3484 buffer->PackUnsignedShortBE(m_nSubSequence);
3485 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
3486
3487 buffer->PackUnsignedShortBE(ICQ_CMDxWPxAGE);
3488 buffer->PackUnsignedShort(0x0002);
3489 buffer->PackUnsignedShort(m_nAge);
3490
3491 buffer->PackUnsignedShortBE(ICQ_CMDxWPxGENDER);
3492 buffer->PackUnsignedShort(0x0001);
3493 buffer->PackChar(nGender);
3494
3495 buffer->PackUnsignedShortBE(ICQ_CMDxWPxHOMEPAGE);
3496 buffer->PackUnsignedShort(homepage.size()+3);
3497 buffer->packShortNullStringLE(homepage);
3498
3499 buffer->PackUnsignedShortBE(ICQ_CMDxWPxBIRTHDAY);
3500 buffer->PackUnsignedShort(0x0006);
3501 buffer->PackUnsignedShort(m_nBirthYear);
3502 buffer->PackUnsignedShort(m_nBirthMonth);
3503 buffer->PackUnsignedShort(m_nBirthDay);
3504
3505 buffer->PackUnsignedShortBE(ICQ_CMDxWPxLANGUAGE);
3506 buffer->PackUnsignedShort(0x0002);
3507 buffer->PackUnsignedShort(m_nLanguage1);
3508
3509 buffer->PackUnsignedShortBE(ICQ_CMDxWPxLANGUAGE);
3510 buffer->PackUnsignedShort(0x0002);
3511 buffer->PackUnsignedShort(m_nLanguage2);
3512
3513 buffer->PackUnsignedShortBE(ICQ_CMDxWPxLANGUAGE);
3514 buffer->PackUnsignedShort(0x0002);
3515 buffer->PackUnsignedShort(m_nLanguage3);
3516 }
3517
3518 //-----Meta_SetInterestsInfo----------------------------------------------------
CPU_Meta_SetInterestsInfo(const UserCategoryMap & interests)3519 CPU_Meta_SetInterestsInfo::CPU_Meta_SetInterestsInfo(const UserCategoryMap& interests)
3520 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3521 {
3522 m_nMetaCommand = ICQ_CMDxMETA_INTERESTSxINFOxSET;
3523
3524 int packetSize = 2 + 2 + 2 + 4 + 2 + 2 + 2 + 1;
3525 UserCategoryMap::const_iterator i;
3526 for (i = interests.begin(); i != interests.end(); ++i)
3527 {
3528 myInterests[i->first] = i->second;
3529 packetSize += 2 + 2 + i->second.size() + 1;
3530 }
3531
3532 m_nSize += packetSize;
3533 InitBuffer();
3534
3535 buffer->PackUnsignedShortBE(1);
3536 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
3537
3538 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
3539 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3540 buffer->PackUnsignedShortBE(0xD007); // type
3541 buffer->PackUnsignedShortBE(m_nSubSequence);
3542 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
3543
3544 buffer->PackChar(myInterests.size());
3545 for (i = myInterests.begin(); i != myInterests.end(); ++i)
3546 {
3547 buffer->PackUnsignedShort(i->first);
3548 buffer->PackString(i->second.c_str());
3549 }
3550 }
3551
3552 //-----Meta_SetOrgBackInfo------------------------------------------------------
CPU_Meta_SetOrgBackInfo(const UserCategoryMap & orgs,const UserCategoryMap & background)3553 CPU_Meta_SetOrgBackInfo::CPU_Meta_SetOrgBackInfo(const UserCategoryMap& orgs,
3554 const UserCategoryMap& background)
3555 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3556 {
3557 m_nMetaCommand = ICQ_CMDxMETA_ORGBACKxINFOxSET;
3558
3559 int packetSize = 2 + 2 + 2 + 4 + 2 + 2 + 2 + 2;
3560 UserCategoryMap::const_iterator i;
3561 for (i = orgs.begin(); i != orgs.end(); ++i)
3562 {
3563 myOrganizations[i->first] = i->second;
3564 packetSize += 2 + 2 + i->second.size() + 1;
3565 }
3566 for (i = background.begin(); i != background.end(); ++i)
3567 {
3568 myBackgrounds[i->first] = i->second;
3569 packetSize += 2 + 2 + i->second.size() + 1;
3570 }
3571
3572 m_nSize += packetSize;
3573 InitBuffer();
3574
3575 buffer->PackUnsignedShortBE(1);
3576 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
3577
3578 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
3579 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3580 buffer->PackUnsignedShortBE(0xD007); // type
3581 buffer->PackUnsignedShortBE(m_nSubSequence);
3582 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
3583
3584 buffer->PackChar(myBackgrounds.size());
3585 for (i = myBackgrounds.begin(); i != myBackgrounds.end(); ++i)
3586 {
3587 buffer->PackUnsignedShort(i->first);
3588 buffer->PackString(i->second.c_str());
3589 }
3590 buffer->PackChar(myOrganizations.size());
3591 for (i = myOrganizations.begin(); i != myOrganizations.end(); ++i)
3592 {
3593 buffer->PackUnsignedShort(i->first);
3594 buffer->PackString(i->second.c_str());
3595 }
3596 }
3597
3598 //-----Meta_SetWorkInfo------------------------------------------------------
CPU_Meta_SetWorkInfo(const string & city,const string & state,const string & phoneNumber,const string & faxNumber,const string & address,const string & zip,unsigned short nCompanyCountry,const string & name,const string & department,const string & position,unsigned short nCompanyOccupation,const string & homepage)3599 CPU_Meta_SetWorkInfo::CPU_Meta_SetWorkInfo(const string& city, const string& state,
3600 const string& phoneNumber, const string& faxNumber, const string& address,
3601 const string& zip, unsigned short nCompanyCountry, const string& name,
3602 const string& department, const string& position, unsigned short nCompanyOccupation,
3603 const string& homepage)
3604 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3605 {
3606 m_nMetaCommand = ICQ_CMDxMETA_WPxINFOxSET;
3607
3608 m_nCompanyCountry = nCompanyCountry;
3609 m_nCompanyOccupation = nCompanyOccupation;
3610
3611 string statebuf(state, 0, 5);
3612
3613 int packetSize = 2+2+2+4+2+2+2 + city.size() + statebuf.size() + phoneNumber.size() +
3614 faxNumber.size() + address.size() + zip.size() + name.size() + department.size() +
3615 position.size() + homepage.size() + 82;
3616 m_nSize += packetSize;
3617 InitBuffer();
3618
3619 buffer->PackUnsignedShortBE(1);
3620 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
3621
3622 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
3623 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3624 buffer->PackUnsignedShortBE(0xD007); // type
3625 buffer->PackUnsignedShortBE(m_nSubSequence);
3626 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
3627
3628 buffer->PackUnsignedShortBE(ICQ_CMDxWPxWORK_CITY);
3629 buffer->PackUnsignedShort(city.size()+3);
3630 buffer->packShortNullStringLE(city);
3631
3632 buffer->PackUnsignedShortBE(ICQ_CMDxWPxWORK_STATE);
3633 buffer->PackUnsignedShort(statebuf.size()+3);
3634 buffer->packShortNullStringLE(statebuf);
3635
3636 buffer->PackUnsignedShortBE(ICQ_CMDxWPxWORK_PHONE);
3637 buffer->PackUnsignedShort(phoneNumber.size()+3);
3638 buffer->packShortNullStringLE(phoneNumber);
3639
3640 buffer->PackUnsignedShortBE(ICQ_CMDxWPxWORK_FAX);
3641 buffer->PackUnsignedShort(faxNumber.size()+3);
3642 buffer->packShortNullStringLE(faxNumber);
3643
3644 buffer->PackUnsignedShortBE(ICQ_CMDxWPxWORK_ADDR);
3645 buffer->PackUnsignedShort(address.size()+3);
3646 buffer->packShortNullStringLE(address);
3647
3648 buffer->PackUnsignedShortBE(ICQ_CMDxWPxWORK_ZIP);
3649 buffer->PackUnsignedShort(zip.size()+3);
3650 buffer->packShortNullStringLE(zip);
3651
3652 buffer->PackUnsignedShortBE(ICQ_CMDxWPxWORK_COUNTRY);
3653 buffer->PackUnsignedShort(0x0002);
3654 buffer->PackUnsignedShort(nCompanyCountry);
3655
3656 buffer->PackUnsignedShortBE(ICQ_CMDxWPxCOMPANY);
3657 buffer->PackUnsignedShort(name.size()+3);
3658 buffer->packShortNullStringLE(name);
3659
3660 buffer->PackUnsignedShortBE(ICQ_CMDxWPxCODEPT);
3661 buffer->PackUnsignedShort(department.size()+3);
3662 buffer->packShortNullStringLE(department);
3663
3664 buffer->PackUnsignedShortBE(ICQ_CMDxWPxCOPOS);
3665 buffer->PackUnsignedShort(position.size()+3);
3666 buffer->packShortNullStringLE(position);
3667
3668 buffer->PackUnsignedShortBE(ICQ_CMDxWPxOCCUP);
3669 buffer->PackUnsignedShort(0x0002);
3670 buffer->PackUnsignedShort(m_nCompanyOccupation);
3671
3672 buffer->PackUnsignedShortBE(ICQ_CMDxWPxWORK_URL);
3673 buffer->PackUnsignedShort(homepage.size()+3);
3674 buffer->packShortNullStringLE(homepage);
3675 }
3676
3677 //-----Meta_SetAbout---------------------------------------------------------
CPU_Meta_SetAbout(const string & about)3678 CPU_Meta_SetAbout::CPU_Meta_SetAbout(const string& about)
3679 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA),
3680 myAbout(about)
3681 {
3682 m_nMetaCommand = ICQ_CMDxMETA_WPxINFOxSET;
3683
3684 if (myAbout.size() > (size_t)Licq::IcqProtocol::MaxMessageSize)
3685 myAbout.resize(Licq::IcqProtocol::MaxMessageSize);
3686
3687 int packetSize = 2+2+2+4+2+2+2 + myAbout.size() + 7;
3688 m_nSize += packetSize;
3689 InitBuffer();
3690
3691 buffer->PackUnsignedShortBE(1);
3692 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
3693
3694 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
3695 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3696 buffer->PackUnsignedShortBE(0xD007); // type
3697 buffer->PackUnsignedShortBE(m_nSubSequence);
3698 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
3699
3700 buffer->PackUnsignedShortBE(ICQ_CMDxWPxABOUT);
3701 buffer->PackUnsignedShort(myAbout.size()+3);
3702 buffer->packString(myAbout);
3703 }
3704
3705 //-----Meta_SetSecurityInfo--------------------------------------------------
CPU_Meta_SetSecurityInfo(bool bAuthorization,bool bWebAware)3706 CPU_Meta_SetSecurityInfo::CPU_Meta_SetSecurityInfo(
3707 bool bAuthorization,
3708 bool bWebAware)
3709 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3710 {
3711 m_nMetaCommand = ICQ_CMDxMETA_SECURITYxSET;
3712 m_nAuthorization = bAuthorization ? 0 : 1;
3713 m_nWebAware = bWebAware ? 1 : 0;
3714
3715
3716 int packetSize = 2+2+2+4+2+2+2+4+6;
3717 m_nSize += packetSize;
3718 InitBuffer();
3719
3720 buffer->PackUnsignedShortBE(1);
3721 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
3722
3723 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
3724 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3725 buffer->PackUnsignedShortBE(0xd007); // type
3726 buffer->PackUnsignedShortBE(m_nSubSequence);
3727 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
3728 buffer->PackUnsignedShortBE(0x0C03);
3729 buffer->PackUnsignedShortBE(0x0100);
3730 buffer->PackChar(m_nWebAware);
3731 buffer->PackChar(0xF8);
3732 buffer->PackChar(2);
3733 buffer->PackChar(1);
3734 buffer->PackChar(0);
3735 buffer->PackChar(m_nAuthorization);
3736 }
3737
3738
3739 //-----Meta_RequestInfo------------------------------------------------------
CPU_Meta_RequestAllInfo(const Licq::UserId & userId)3740 CPU_Meta_RequestAllInfo::CPU_Meta_RequestAllInfo(const Licq::UserId& userId)
3741 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3742 {
3743 if (userId.isOwner())
3744 m_nMetaCommand = ICQ_CMDxMETA_REQUESTxALLxINFO;
3745 else
3746 m_nMetaCommand = ICQ_CMDxMETA_REQUESTxALLxINFOxOWNER;
3747
3748 int packetSize = 2+2+2+4+2+2+2+4;
3749 m_nSize += packetSize;
3750 InitBuffer();
3751
3752 buffer->PackUnsignedShortBE(1);
3753 buffer->PackUnsignedShortBE(packetSize-2-2); // TLV 1
3754
3755 buffer->PackUnsignedShort(packetSize-2-2-2); // bytes remaining
3756 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3757 buffer->PackUnsignedShortBE(0xd007); // type
3758 buffer->PackUnsignedShortBE(m_nSubSequence);
3759 buffer->PackUnsignedShort(m_nMetaCommand); // subtype
3760 buffer->PackUnsignedLong(strtoul(userId.accountId().c_str(), (char **)NULL, 10));
3761 }
3762
3763 //-----Meta_RequestInfo------------------------------------------------------
CPU_Meta_RequestBasicInfo(const string & accountId)3764 CPU_Meta_RequestBasicInfo::CPU_Meta_RequestBasicInfo(const string& accountId)
3765 : CPU_CommonFamily(ICQ_SNACxFAM_VARIOUS, ICQ_SNACxMETA)
3766 {
3767 m_nMetaCommand = ICQ_CMDxMETA_REQUESTxBASICxINFO;
3768 myAccountId = accountId;
3769
3770 m_nSize += 20;
3771
3772 InitBuffer();
3773
3774 buffer->PackUnsignedLongBE(0x0001000e); // TLV
3775
3776 buffer->PackUnsignedShort(0x000c); // Bytes remaining
3777 buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
3778 buffer->PackUnsignedShort(m_nMetaCommand);
3779 buffer->PackUnsignedShort(m_nSubSequence);
3780 buffer->PackUnsignedLong(strtoul(myAccountId.c_str(), (char **)NULL, 10));
3781 }
3782
3783 //-----RequestInfo-------------------------------------------------------------
CPU_RequestInfo(const string & accountId)3784 CPU_RequestInfo::CPU_RequestInfo(const string& accountId)
3785 : CPU_CommonFamily(ICQ_SNACxFAM_LOCATION, ICQ_SNACxREQUESTxUSERxINFO)
3786 {
3787 m_nSize += 5 + accountId.size();
3788
3789 InitBuffer();
3790
3791 buffer->PackUnsignedLongBE(0x00000003);
3792 buffer->PackChar(accountId.size());
3793 buffer->pack(accountId);
3794 }
3795
3796 //-----AIMFetchAwayMessage-----------------------------------------------------
CPU_AIMFetchAwayMessage(const string & accountId)3797 CPU_AIMFetchAwayMessage::CPU_AIMFetchAwayMessage(const string& accountId)
3798 : CPU_CommonFamily(ICQ_SNACxFAM_LOCATION, ICQ_SNACxLOC_INFOxREQ)
3799 {
3800 m_nSize += 3 + accountId.size();
3801
3802 InitBuffer();
3803
3804 buffer->PackUnsignedShortBE(0x0003); // away message type
3805 buffer->PackChar(accountId.size());
3806 buffer->pack(accountId);
3807 }
3808