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