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-tcp.h"
21 
22 #include <boost/foreach.hpp>
23 #include <cstdio>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <fcntl.h>
29 
30 #include <cerrno>
31 
32 #include <licq/byteorder.h>
33 #include <licq/color.h>
34 #include <licq/contactlist/usermanager.h>
35 #include <licq/translator.h>
36 #include <licq/logging/log.h>
37 #include <licq/version.h>
38 
39 #include "buffer.h"
40 #include "defines.h"
41 #include "gettext.h"
42 #include "icq.h"
43 #include "socket.h"
44 #include "owner.h"
45 #include "user.h"
46 
47 using namespace LicqIcq;
48 using Licq::UserId;
49 using Licq::gLog;
50 using Licq::gTranslator;
51 using std::list;
52 using std::string;
53 
54 //=====TCP===================================================================
55 static unsigned char client_check_data[] = {
56   "As part of this software beta version Mirabilis is "
57   "granting a limited access to the ICQ network, "
58   "servers, directories, listings, information and databases (\""
59   "ICQ Services and Information\"). The "
60   "ICQ Service and Information may databases (\""
61   "ICQ Services and Information\"). The "
62   "ICQ Service and Information may\0"
63 };
64 
65 
66 #define DEBUG_ENCRYPTION(x)
67 //#define DEBUG_ENCRYPTION(x) fprintf(stderr, x)
68 
Encrypt_Client(CBuffer * pkt,unsigned long version)69 void LicqIcq::Encrypt_Client(CBuffer* pkt, unsigned long version)
70 {
71   unsigned long B1, M1, check;
72   unsigned int i;
73   unsigned char X1, X2, X3;
74   unsigned char* buf = (unsigned char*)pkt->getDataStart() + 2;
75   unsigned char bak[6];
76   unsigned long offset;
77   unsigned long size = pkt->getDataSize() - 2;
78 
79   if (version < 4)
80     return;  // no encryption necessary.
81 
82   switch(version)
83   {
84     case 4:
85     case 5:
86       offset = 6;
87       break;
88     case 7:
89     case 8:
90     case 6:
91     default:
92       offset = 0;
93   }
94 
95   pkt->log(Licq::Log::Debug, tr("Unencrypted (ICQ) TCP Packet (%lu bytes)"), size);
96 
97   // Fuck AOL
98   if (version > 6)
99   {
100     buf += 1;
101     size -= 1;
102   }
103 
104   // calculate verification data
105   M1 = (rand() % ((size < 255 ? size : 255)-10))+10;
106   X1 = buf[M1] ^ 0xFF;
107   X2 = rand() % 220;
108   X3 = client_check_data[X2] ^ 0xFF;
109   if(offset) {
110     for(i=0;i<6;i++)  bak[i] = buf[i];
111     B1 = (buf[offset+4]<<24)|(buf[offset+6]<<16)|(buf[2]<<8)|buf[0];
112   }
113   else
114     B1 = (buf[4]<<24)|(buf[6]<<16)|(buf[4]<<8)|(buf[6]);
115 
116   // calculate checkcode
117   check = (M1 << 24) | (X1 << 16) | (X2 << 8) | X3;
118   check ^= B1;
119   DEBUG_ENCRYPTION(("complete check %08lx\n", check));
120 
121   // main XOR key
122   unsigned long key = 0x67657268 * size + check;
123 
124   // XORing the actual data
125   for(i=0;i<(size+3)/4;i+=4){
126     unsigned long hex = key + client_check_data[i&0xFF];
127     buf[i+0] ^= hex&0xFF;buf[i+1] ^= (hex>>8)&0xFF;
128     buf[i+2] ^= (hex>>16)&0xFF;buf[i+3] ^= (hex>>24)&0xFF;
129   }
130 
131   // in TCPv4 are the first 6 bytes unencrypted
132   // so restore them
133   if(offset)  for(i=0;i<6;i++) buf[i] = bak[i];
134 
135   // storing the checkcode
136   buf[offset+3] = (check>>24)&0xFF;
137   buf[offset+2] = (check>>16)&0xFF;
138   buf[offset+1] = (check>>8)&0xFF;
139   buf[offset+0] = check&0xFF;
140 }
141 
142 
Decrypt_Client(CBuffer * pkt,unsigned long version)143 bool LicqIcq::Decrypt_Client(CBuffer* pkt, unsigned long version)
144 {
145   unsigned long hex, key, B1, M1, check;
146   unsigned int i;
147   unsigned char X1, X2, X3;
148   unsigned char* buf = (unsigned char*)pkt->getDataStart() + 2;
149   unsigned char bak[6];
150   unsigned long size = pkt->getDataSize() - 2;
151   unsigned long offset;
152 
153   if(version < 4)
154     return true;  // no decryption necessary.
155 
156   switch(version){
157   case 4:
158   case 5:
159     offset = 6;
160     break;
161   case 7:
162   case 8:
163   case 6:
164   default:
165     offset = 0;
166   }
167 
168   // Fuck AOL
169   if (version > 6)
170   {
171     buf += 1;
172     size -= 1;
173   }
174 
175   // backup the first 6 bytes
176   if(offset)
177     for(i=0;i<6;i++)  bak[i] = buf[i];
178 
179   // retrieve checkcode
180   check = (buf[offset+3]<<24)|(buf[offset+2]<<16)|(buf[offset+1]<<8)|(buf[offset+0]);
181 
182   DEBUG_ENCRYPTION(("size %d, check %08lx\n", size, check));
183 
184   // main XOR key
185   key = 0x67657268 * size + check;
186 
187   for(i=4; i<(size+3)/4; i+=4) {
188     hex = key + client_check_data[i&0xFF];
189     buf[i+0] ^= hex&0xFF;buf[i+1] ^= (hex>>8)&0xFF;
190     buf[i+2] ^= (hex>>16)&0xFF;buf[i+3] ^= (hex>>24)&0xFF;
191   }
192 
193   // retrive validate data
194   if(offset) {
195     // in TCPv4 are the first 6 bytes unencrypted
196     // so restore them
197     for(i=0;i<6;i++) buf[i] = bak[i];
198     B1 = (buf[offset+4]<<24)|(buf[offset+6]<<16)|(buf[2]<<8)|buf[0];
199   }
200   else
201     B1 = (buf[4]<<24) | (buf[6]<<16) | (buf[4]<<8) | (buf[6]<<0);
202 
203   // special decryption
204   B1 ^= check;
205 
206   // validate packet
207   M1 = (B1 >> 24) & 0xFF;
208   if(M1 < 10 || M1 >= size) {
209     DEBUG_ENCRYPTION(("range check failed, M1 is %02x, returning false\n", M1));
210     return false;
211   }
212 
213   X1 = buf[M1] ^ 0xFF;
214   if(((B1 >> 16) & 0xFF) != X1) {
215     DEBUG_ENCRYPTION(("M1 is %02x\n", M1));
216     DEBUG_ENCRYPTION(("calculated X1 (%02lx) != %02x\n", X1, (B1 >> 16) & 0xFF));
217     return false;
218   }
219 
220   X2 = ((B1 >> 8) & 0xFF);
221   if(X2 < 220) {
222     X3 = client_check_data[X2] ^ 0xFF;
223     if((B1 & 0xFF) != X3) {
224       DEBUG_ENCRYPTION(("calculated X3 (%02x) does not match B1 (%02x)\n", X3, B1 & 0xFF));
225       return false;
226     }
227   }
228 
229   pkt->log(Licq::Log::Debug, tr("Decrypted (ICQ) TCP Packet (%lu bytes)"), size);
230 
231   return true;
232 }
233 
CPacketTcp_Handshake()234 CPacketTcp_Handshake::CPacketTcp_Handshake()
235   : buffer(NULL)
236 {
237   // Empty
238 }
239 
~CPacketTcp_Handshake()240 CPacketTcp_Handshake::~CPacketTcp_Handshake()
241 {
242   delete buffer;
243 }
244 
CPacketTcp_Handshake_v2(unsigned long nLocalPort)245 CPacketTcp_Handshake_v2::CPacketTcp_Handshake_v2(unsigned long nLocalPort)
246 {
247   m_nLocalPort = nLocalPort;
248 
249   m_nSize = 28;
250   buffer = new CBuffer(m_nSize);
251   buffer->packUInt16LE(m_nSize-2); // Packet length
252 
253   buffer->PackChar(ICQ_CMDxTCP_HANDSHAKE);
254   buffer->PackUnsignedLong(ICQ_VERSION_TCP);
255   buffer->PackUnsignedLong(m_nLocalPort);
256   buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
257   buffer->PackUnsignedLong(s_nLocalIp);
258   buffer->PackUnsignedLong(s_nRealIp);
259   buffer->PackChar(gIcqProtocol.directMode() ? MODE_DIRECT : MODE_INDIRECT);
260   buffer->PackUnsignedLong(m_nLocalPort);
261 }
262 
263 
CPacketTcp_Handshake_v4(unsigned long nLocalPort)264 CPacketTcp_Handshake_v4::CPacketTcp_Handshake_v4(unsigned long nLocalPort)
265 {
266   m_nLocalPort = nLocalPort;
267 
268   m_nSize = 28;
269   buffer = new CBuffer(m_nSize);
270   buffer->packUInt16LE(m_nSize-2); // Packet length
271 
272   buffer->PackChar(ICQ_CMDxTCP_HANDSHAKE);
273   buffer->PackUnsignedLong(ICQ_VERSION_TCP);
274   buffer->PackUnsignedLong(0x00000000);
275   buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
276   buffer->PackUnsignedLong(s_nLocalIp); // maybe should be 0
277   buffer->PackUnsignedLong(s_nRealIp);
278   buffer->PackChar(gIcqProtocol.directMode() ? MODE_DIRECT : MODE_INDIRECT);
279   buffer->PackUnsignedLong(m_nLocalPort);
280 }
281 
282 
283 //=====PacketTcp_Handshake======================================================
CPacketTcp_Handshake_v6(unsigned long nDestinationUin,unsigned long,unsigned short nLocalPort)284 CPacketTcp_Handshake_v6::CPacketTcp_Handshake_v6(unsigned long nDestinationUin,
285    unsigned long /* nSessionId */, unsigned short nLocalPort)
286 {
287   m_nDestinationUin = nDestinationUin;
288 
289   m_nSize = 46;
290   buffer = new CBuffer(m_nSize);
291   buffer->packUInt16LE(m_nSize-2); // Packet length
292 
293   buffer->PackChar(ICQ_CMDxTCP_HANDSHAKE);
294   buffer->PackUnsignedShort(ICQ_VERSION_TCP);
295   buffer->PackUnsignedShort(0x0027); //size
296   buffer->PackUnsignedLong(m_nDestinationUin);
297   buffer->PackUnsignedShort(0);
298   buffer->PackUnsignedLong(nLocalPort);
299   buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
300   buffer->PackUnsignedLong(s_nLocalIp);
301   buffer->PackUnsignedLong(s_nRealIp);
302   buffer->PackChar(gIcqProtocol.directMode() ? MODE_DIRECT : MODE_INDIRECT);
303   buffer->PackUnsignedLong(nLocalPort == 0 ? s_nLocalPort : nLocalPort);
304 
305   char id[16];
306   snprintf(id, 16, "%lu", nDestinationUin);
307   UserId userId(gIcqProtocol.ownerId(), id);
308   UserReadGuard u(userId);
309   if (u.isLocked())
310   {
311     buffer->PackUnsignedLong(u->Cookie());
312     m_nSessionId = u->Cookie();
313   }
314   else
315   {
316     m_nSessionId = 0;
317     buffer->PackUnsignedLong(0);
318   }
319 
320   buffer->PackUnsignedLong(0x00000050); // constant
321   buffer->PackUnsignedLong(0x00000003); // constant
322 }
323 
324 
CPacketTcp_Handshake_v6(CBuffer * inbuf)325 CPacketTcp_Handshake_v6::CPacketTcp_Handshake_v6(CBuffer *inbuf)
326 {
327   inbuf->unpackUInt16LE(); // Packet length
328   m_nHandshake = inbuf->UnpackChar();
329   m_nVersionMajor = inbuf->UnpackUnsignedShort();
330   m_nVersionMinor = inbuf->UnpackUnsignedShort();
331   m_nDestinationUin = inbuf->UnpackUnsignedLong();
332   inbuf->UnpackUnsignedLong();
333   inbuf->UnpackUnsignedShort();
334   m_nSourceUin = inbuf->UnpackUnsignedLong();
335   m_nLocalIp = inbuf->UnpackUnsignedLong();
336   m_nRealIp = inbuf->UnpackUnsignedLong();
337   m_nMode = inbuf->UnpackChar();
338   inbuf->UnpackUnsignedLong(); // port of some kind...?
339   m_nSessionId = inbuf->UnpackUnsignedLong();
340   //inbuf->UnpackUnsignedLong(); // constant
341   //inbuf->UnpackUnsignedLong(); // constant
342 }
343 
344 
CPacketTcp_Handshake_v7(unsigned long nDestinationUin,unsigned long,unsigned short nLocalPort,unsigned long nId)345 CPacketTcp_Handshake_v7::CPacketTcp_Handshake_v7(unsigned long nDestinationUin,
346    unsigned long /* nSessionId */, unsigned short nLocalPort, unsigned long nId)
347 {
348   m_nDestinationUin = nDestinationUin;
349 
350   m_nSize = 50;
351   buffer = new CBuffer(m_nSize);
352   buffer->packUInt16LE(m_nSize-2); // Packet length
353 
354   buffer->PackChar(ICQ_CMDxTCP_HANDSHAKE);
355   buffer->PackUnsignedShort(ICQ_VERSION_TCP);
356   buffer->PackUnsignedShort(0x002b); // size
357   buffer->PackUnsignedLong(m_nDestinationUin);
358   buffer->PackUnsignedShort(0);
359   buffer->PackUnsignedLong(nLocalPort == 0 ? s_nLocalPort : nLocalPort);
360   buffer->PackUnsignedLong(gIcqProtocol.icqOwnerUin());
361   buffer->PackUnsignedLong(s_nRealIp);
362   buffer->PackUnsignedLong(s_nLocalIp);
363   buffer->PackChar(gIcqProtocol.directMode() ? MODE_DIRECT : MODE_INDIRECT);
364   buffer->PackUnsignedLong(nLocalPort == 0 ? s_nLocalPort : nLocalPort);
365 
366   char id[16];
367   snprintf(id, 16, "%lu", nDestinationUin);
368   UserId userId(gIcqProtocol.ownerId(), id);
369   UserReadGuard u(userId);
370   if (u.isLocked())
371   {
372     buffer->PackUnsignedLong(u->Cookie());
373     m_nSessionId = u->Cookie();
374   }
375   else
376   {
377     m_nSessionId = 0;
378     buffer->PackUnsignedLong(0);
379   }
380 
381   buffer->PackUnsignedLong(0x00000050); // constant
382   buffer->PackUnsignedLong(0x00000003); // constant
383   buffer->PackUnsignedLong(nId); // the connection id for reverse connect
384 
385 }
386 
387 
CPacketTcp_Handshake_v7(CBuffer * inbuf)388 CPacketTcp_Handshake_v7::CPacketTcp_Handshake_v7(CBuffer *inbuf)
389 {
390   inbuf->unpackUInt16LE(); // Packet length
391   m_nHandshake = inbuf->UnpackChar();
392   m_nVersionMajor = inbuf->UnpackUnsignedShort();
393   inbuf->UnpackUnsignedShort();  // Length
394   m_nDestinationUin = inbuf->UnpackUnsignedLong();
395   inbuf->UnpackUnsignedShort();
396   inbuf->UnpackUnsignedLong();
397   m_nSourceUin = inbuf->UnpackUnsignedLong();
398   m_nRealIp = inbuf->UnpackUnsignedLong();
399   m_nLocalIp = inbuf->UnpackUnsignedLong();
400   m_nMode = inbuf->UnpackChar();
401   inbuf->UnpackUnsignedLong();
402   m_nSessionId = inbuf->UnpackUnsignedLong(); // Mmmm cookie
403   inbuf->incDataPosRead(8);
404   m_nId = inbuf->UnpackUnsignedLong();
405 }
406 
407 
CPacketTcp_Handshake_Ack()408 CPacketTcp_Handshake_Ack::CPacketTcp_Handshake_Ack()
409 {
410   m_nSize = 6;
411   buffer = new CBuffer(m_nSize);
412   buffer->packUInt16LE(m_nSize-2); // Packet length
413 
414   buffer->PackUnsignedLong(1);
415 }
416 
CPacketTcp_Handshake_Confirm(int channel,unsigned short nSequence)417 CPacketTcp_Handshake_Confirm::CPacketTcp_Handshake_Confirm(int channel,
418   unsigned short nSequence)
419   : myChannel(channel)
420 {
421   m_nSize = 35;
422   buffer = new CBuffer(m_nSize);
423   buffer->packUInt16LE(m_nSize-2); // Packet length
424 
425   const uint8_t* GUID;
426   unsigned long nOurId;
427   switch (channel)
428   {
429     case DcSocket::ChannelNormal:
430     nOurId = 0x00000001;
431     GUID = PLUGIN_NORMAL;
432       break;
433     case DcSocket::ChannelInfo:
434     nOurId = 0x000003EB;
435     GUID = PLUGIN_INFOxMANAGER;
436       break;
437     case DcSocket::ChannelStatus:
438     nOurId = 0x000003EA;
439     GUID = PLUGIN_STATUSxMANAGER;
440     break;
441     default:
442       gLog.warning(tr("Channel %u is not implemented"), channel);
443       return;
444   }
445 
446   buffer->PackChar(0x03);
447   buffer->PackUnsignedLong(0x0000000A);
448   buffer->PackUnsignedLong(nOurId);
449   buffer->PackUnsignedLong(nSequence);
450   if (nSequence == 0)  //we are initiating the connection
451   {
452     buffer->Pack(GUID, 16);
453     buffer->PackUnsignedLong(0x00040001);
454   }
455   else
456   {
457     buffer->Pack(GUID, 8);
458     buffer->PackUnsignedLong(0x00040001);
459     buffer->Pack(GUID + 8, 8);
460   }
461 }
462 
CPacketTcp_Handshake_Confirm(CBuffer * inbuf)463 CPacketTcp_Handshake_Confirm::CPacketTcp_Handshake_Confirm(CBuffer *inbuf)
464 {
465   inbuf->incDataPosRead(5); //skip over junk
466   m_nId = inbuf->UnpackUnsignedLong(); // some sort of id??
467   inbuf->UnpackUnsignedLong(); // 0 in incomming, our id in outgoing
468 
469   char GUID[16];
470   for (int i = 0; i < 16; i ++)
471     (*inbuf) >> GUID[i];
472 
473   if (memcmp(GUID, PLUGIN_NORMAL, 16) == 0)
474     myChannel = DcSocket::ChannelNormal;
475   else if (memcmp(GUID, PLUGIN_INFOxMANAGER, 16) == 0)
476     myChannel = DcSocket::ChannelInfo;
477   else if (memcmp(GUID, PLUGIN_STATUSxMANAGER, 16) == 0)
478     myChannel = DcSocket::ChannelStatus;
479   else
480   {
481     gLog.warning(tr("Unknown channel GUID."));
482     myChannel = DcSocket::ChannelUnknown;
483   }
484 }
485 
486 //=====PacketTcp================================================================
Finalize(Licq::INetSocket * s)487 Licq::Buffer* CPacketTcp::Finalize(Licq::INetSocket *s)
488 {
489   // Set the local port in the tcp packet now
490   if (s != NULL && LocalPortOffset() != NULL)
491   {
492     LocalPortOffset()[0] = s->getLocalPort() & 0xFF;
493     LocalPortOffset()[1] = (s->getLocalPort() >> 8) & 0xFF;
494   }
495 
496   Encrypt_Client(buffer, m_nVersion);
497   return buffer;
498 }
499 
CPacketTcp(unsigned long _nCommand,unsigned short _nSubCommand,int channel,const string & message,bool _bAccept,unsigned short nLevel,User * user)500 CPacketTcp::CPacketTcp(unsigned long _nCommand, unsigned short _nSubCommand, int channel,
501     const string& message, bool _bAccept, unsigned short nLevel, User* user)
502   : myChannel(channel)
503 {
504   // Setup the message type and status fields using our online status
505   Licq::OwnerReadGuard o(gIcqProtocol.ownerId());
506   unsigned short s;
507   if (user->statusToUser() != Licq::User::OfflineStatus)
508     s = IcqProtocol::icqStatusFromStatus(user->statusToUser());
509   else
510     s = IcqProtocol::icqStatusFromStatus(o->status());
511   m_nLevel = nLevel;
512   m_nVersion = user->ConnectionVersion();
513   if (m_nVersion >= 7)
514   {
515     if (nLevel & ICQ_TCPxMSG_URGENT)
516     {
517       nLevel &= ~ICQ_TCPxMSG_URGENT;
518       nLevel |= ICQ_TCPxMSG_URGENT2;
519     }
520     else if (nLevel & ICQ_TCPxMSG_LIST)
521     {
522       nLevel &= ~ICQ_TCPxMSG_LIST;
523       nLevel |= ICQ_TCPxMSG_LIST2;
524     }
525   }
526 
527   switch(_nCommand)
528   {
529     case ICQ_CMDxTCP_CANCEL:
530     case ICQ_CMDxTCP_START:
531     {
532       m_nStatus = 0;
533       m_nMsgType = nLevel;
534       if (m_nVersion >= 7)
535       {
536         m_nStatus = s;
537         break;
538       }
539 
540       switch (s)
541       {
542         case ICQ_STATUS_AWAY: m_nMsgType |= ICQ_TCPxMSG_FxAWAY; break;
543         case ICQ_STATUS_NA: m_nMsgType |= ICQ_TCPxMSG_FxNA; break;
544         case ICQ_STATUS_DND: m_nMsgType |= ICQ_TCPxMSG_FxDND; break;
545         case ICQ_STATUS_OCCUPIED: m_nMsgType |= ICQ_TCPxMSG_FxOCCUPIED; break;
546         case ICQ_STATUS_ONLINE:
547         case ICQ_STATUS_FREEFORCHAT:
548         default: m_nMsgType |= ICQ_TCPxMSG_FxONLINE; break;
549       }
550       if (o->isInvisible())
551         m_nMsgType |= ICQ_TCPxMSG_FxINVISIBLE;
552       break;
553     }
554 
555     case ICQ_CMDxTCP_ACK:
556     {
557       m_nMsgType = ICQ_TCPxMSG_AUTOxREPLY;
558       if (!_bAccept)
559         m_nStatus = ICQ_TCPxACK_REFUSE;
560       // If we are accepting a chat or file request then always say we are online
561       else if (nLevel == ICQ_TCPxMSG_URGENT ||
562                nLevel == ICQ_TCPxMSG_URGENT2 ||
563                _nSubCommand == ICQ_CMDxSUB_CHAT ||
564                _nSubCommand == ICQ_CMDxSUB_FILE)
565         m_nStatus = ICQ_TCPxACK_ONLINE;
566       else
567       {
568         switch (s)
569         {
570           case ICQ_STATUS_AWAY: m_nStatus = ICQ_TCPxACK_AWAY; break;
571           case ICQ_STATUS_NA: m_nStatus = ICQ_TCPxACK_NA; break;
572           case ICQ_STATUS_DND:
573             m_nStatus = (!user->customAutoResponse().empty() && _nSubCommand == ICQ_CMDxTCP_READxDNDxMSG)
574               ? ICQ_TCPxACK_DNDxCAR : ICQ_TCPxACK_DND;
575             break;
576           case ICQ_STATUS_OCCUPIED:
577             m_nStatus = (!user->customAutoResponse().empty() && _nSubCommand == ICQ_CMDxTCP_READxOCCUPIEDxMSG)
578               ? ICQ_TCPxACK_OCCUPIEDxCAR : ICQ_TCPxACK_OCCUPIED;
579             break;
580           case ICQ_STATUS_ONLINE:
581           case ICQ_STATUS_FREEFORCHAT:
582           default: m_nStatus = ICQ_TCPxACK_ONLINE; break;
583         }
584       }
585       break;
586     }
587   }
588   o.unlock();
589 
590   m_nSourceUin = gIcqProtocol.icqOwnerUin();
591   m_nCommand = _nCommand;
592   m_nSubCommand = _nSubCommand;
593   myMessage = message;
594   m_nLocalPort = user->LocalPort();
595 
596   // don't increment the sequence if this is an ack and cancel packet
597   if (m_nCommand == ICQ_CMDxTCP_START) m_nSequence = user->Sequence(true);
598 
599   // Buffer and size are set by InitBuffer
600   m_nSize = 0;
601   buffer = NULL;
602 }
603 
~CPacketTcp()604 CPacketTcp::~CPacketTcp()
605 {
606   delete buffer;
607 }
608 
609 
InitBuffer()610 void CPacketTcp::InitBuffer()
611 {
612   switch (m_nVersion)
613   {
614     case 6:
615       InitBuffer_v6();
616       break;
617     case 4:
618     case 5:
619       InitBuffer_v4();
620       break;
621     case 2:
622     case 3:
623       InitBuffer_v2();
624       break;
625     case 7:
626     case 8:
627     default:
628       InitBuffer_v7();
629       break;
630   }
631 }
632 
PostBuffer()633 void CPacketTcp::PostBuffer()
634 {
635   switch (m_nVersion)
636   {
637     case 7:
638     case 8:
639       PostBuffer_v7();
640       break;
641     case 6:
642       PostBuffer_v6();
643       break;
644     case 4:
645     case 5:
646       PostBuffer_v4();
647       break;
648     case 2:
649     case 3:
650       PostBuffer_v2();
651       break;
652   }
653 
654   if (buffer->getDataSize() != m_nSize)
655   {
656     gLog.warning(tr("Packet length (%lu) different than expected (%i)"),
657         buffer->getDataSize(), m_nSize);
658     *((uint16_t*)buffer->getDataStart()) = LE_16(buffer->getDataSize() - 2);
659   }
660 }
661 
662 
InitBuffer_v2()663 void CPacketTcp::InitBuffer_v2()
664 {
665   m_nSize += 35 + myMessage.size() + 4;
666   if (m_nVersion != 2)
667     m_nSize += 3;
668   buffer = new CBuffer(m_nSize);
669   buffer->packUInt16LE(m_nSize-2); // Packet length
670 
671   buffer->PackUnsignedLong(m_nSourceUin);
672   buffer->PackUnsignedShort(m_nVersion == 2 ? 2 : ICQ_VERSION_TCP);
673   buffer->PackUnsignedLong(m_nCommand);
674   buffer->PackUnsignedLong(m_nSourceUin);
675   buffer->PackUnsignedShort(m_nSubCommand);
676   buffer->pack(myMessage);
677   buffer->PackUnsignedLong(s_nLocalIp);
678   buffer->PackUnsignedLong(s_nRealIp);
679   m_szLocalPortOffset = buffer->getDataPosWrite();
680   buffer->PackUnsignedLong(m_nLocalPort);
681   buffer->PackChar(gIcqProtocol.directMode() ? MODE_DIRECT : MODE_INDIRECT);
682   buffer->PackUnsignedShort(m_nStatus);
683   buffer->PackUnsignedShort(m_nMsgType);
684 }
685 
PostBuffer_v2()686 void CPacketTcp::PostBuffer_v2()
687 {
688   buffer->PackUnsignedLong(m_nSequence);
689   // several V2 clients don't like our extension, so we omit it for them
690   if (m_nVersion != 2)
691   {
692     buffer->PackChar('L');
693     buffer->PackUnsignedShort(LICQ_VERSION);
694   }
695 }
696 
697 
InitBuffer_v4()698 void CPacketTcp::InitBuffer_v4()
699 {
700   m_nSize += 39 + myMessage.size() + 7;
701   buffer = new CBuffer(m_nSize);
702   buffer->packUInt16LE(m_nSize-2); // Packet length
703 
704   buffer->PackUnsignedLong(m_nSourceUin);
705   buffer->PackUnsignedShort(ICQ_VERSION_TCP);
706   buffer->PackUnsignedLong(0x00000000);  // Checksum
707   buffer->PackUnsignedLong(m_nCommand);
708   buffer->PackUnsignedLong(m_nSourceUin);
709   buffer->PackUnsignedShort(m_nSubCommand);
710   buffer->pack(myMessage);
711   buffer->PackUnsignedLong(s_nLocalIp);
712   buffer->PackUnsignedLong(s_nRealIp);
713   m_szLocalPortOffset = buffer->getDataPosWrite();
714   buffer->PackUnsignedLong(m_nLocalPort);
715   buffer->PackChar(gIcqProtocol.directMode() ? MODE_DIRECT : MODE_INDIRECT);
716   buffer->PackUnsignedShort(m_nStatus);
717   buffer->PackUnsignedShort(m_nMsgType);
718 }
719 
PostBuffer_v4()720 void CPacketTcp::PostBuffer_v4()
721 {
722   buffer->PackUnsignedLong(m_nSequence);
723   buffer->PackChar('L');
724   buffer->PackUnsignedShort(LICQ_VERSION);
725 }
726 
727 
InitBuffer_v6()728 void CPacketTcp::InitBuffer_v6()
729 {
730   m_nSize += 32 + myMessage.size() + 0;
731   buffer = new CBuffer(m_nSize);
732   buffer->packUInt16LE(m_nSize-2); // Packet length
733 
734   buffer->PackUnsignedLong(0); // Checksum
735   buffer->PackUnsignedShort(m_nCommand);
736   buffer->PackUnsignedShort(0x000E);  //???
737   buffer->PackUnsignedShort(m_nSequence);
738   buffer->PackUnsignedLong(0); // Always zero, probably decryption validation
739   buffer->PackUnsignedLong(0); //   ""
740   buffer->PackUnsignedLong(0); //   ""
741   buffer->PackUnsignedShort(m_nSubCommand);
742   buffer->PackUnsignedShort(m_nStatus);
743   buffer->PackUnsignedShort(m_nMsgType);
744   buffer->PackUnsignedShort(myMessage.size());
745   buffer->pack(myMessage);
746 
747   m_szLocalPortOffset = NULL;
748 }
749 
PostBuffer_v6()750 void CPacketTcp::PostBuffer_v6()
751 {
752 // don't break ICQ2000
753 //   buffer->PackChar('L');
754 //   buffer->PackUnsignedShort(LICQ_VERSION);
755 }
756 
InitBuffer_v7()757 void CPacketTcp::InitBuffer_v7()
758 {
759   m_nSize += 31;
760   if (channel() == DcSocket::ChannelNormal)
761     m_nSize += 2 + myMessage.size();
762   else
763     m_nSize += 3;
764   buffer = new CBuffer(m_nSize);
765   buffer->packUInt16LE(m_nSize-2); // Packet length
766 
767   buffer->PackChar(0x02);
768   buffer->PackUnsignedLong(0); // Checksum
769   buffer->PackUnsignedShort(m_nCommand);
770   buffer->PackUnsignedShort((channel() == DcSocket::ChannelNormal) ? 0x000E : 0x0012);
771   buffer->PackUnsignedShort(m_nSequence);
772   buffer->PackUnsignedLong(0);
773   buffer->PackUnsignedLong(0);
774   buffer->PackUnsignedLong(0);
775   buffer->PackUnsignedShort(m_nSubCommand);
776   buffer->PackUnsignedShort(m_nStatus);
777   buffer->PackUnsignedShort((channel() == DcSocket::ChannelNormal) ? m_nMsgType : m_nLevel);
778 
779   if (channel() == DcSocket::ChannelNormal)
780   {
781     buffer->PackUnsignedShort(myMessage.size());
782     buffer->pack(myMessage);
783   }
784   else
785   {
786     buffer->PackUnsignedShort(1);
787     buffer->PackChar(myMessage[0]);
788   }
789 
790   m_szLocalPortOffset = NULL;
791 }
792 
PostBuffer_v7()793 void CPacketTcp::PostBuffer_v7()
794 {
795 }
796 
797 
798 //-----Message------------------------------------------------------------------
CPT_Message(const string & message,unsigned short nLevel,bool bMR,const Licq::Color * pColor,User * pUser,bool isUtf8)799 CPT_Message::CPT_Message(const string& message, unsigned short nLevel, bool bMR,
800     const Licq::Color* pColor, User* pUser, bool isUtf8)
801   : CPacketTcp(ICQ_CMDxTCP_START,
802        ICQ_CMDxSUB_MSG | (bMR ? ICQ_CMDxSUB_FxMULTIREC : 0),
803         DcSocket::ChannelNormal,
804         message, true, nLevel, pUser)
805 {
806   if (m_nVersion >= 6)
807   {
808     m_nSize += 8;
809     if (isUtf8)
810       m_nSize += 4 + sizeof(ICQ_CAPABILITY_UTF8_STR)-1;
811   }
812   InitBuffer();
813   if (m_nVersion >= 6)
814   {
815     if (pColor == NULL)
816     {
817       buffer->PackUnsignedLong(0x00000000);
818       buffer->PackUnsignedLong(0x00FFFFFF);
819     }
820     else
821     {
822       buffer->PackUnsignedLong(pColor->foreground());
823       buffer->PackUnsignedLong(pColor->background());
824     }
825 
826     if (isUtf8)
827     {
828       buffer->PackUnsignedLong(sizeof(ICQ_CAPABILITY_UTF8_STR)-1);
829       buffer->Pack(ICQ_CAPABILITY_UTF8_STR, sizeof(ICQ_CAPABILITY_UTF8_STR)-1);
830     }
831   }
832   PostBuffer();
833 }
834 
835 //-----Url----------------------------------------------------------------------
CPT_Url(const string & message,unsigned short nLevel,bool bMR,const Licq::Color * pColor,User * pUser)836 CPT_Url::CPT_Url(const string& message, unsigned short nLevel, bool bMR,
837     const Licq::Color* pColor, User* pUser)
838   : CPacketTcp(ICQ_CMDxTCP_START,
839        ICQ_CMDxSUB_URL | (bMR ? ICQ_CMDxSUB_FxMULTIREC : 0),
840         DcSocket::ChannelNormal,
841         message, true, nLevel, pUser)
842 {
843   if (m_nVersion >= 6)
844     m_nSize += 8;
845   InitBuffer();
846   if (m_nVersion >= 6)
847   {
848     if (pColor == NULL)
849     {
850       buffer->PackUnsignedLong(0x00000000);
851       buffer->PackUnsignedLong(0x00FFFFFF);
852     }
853     else
854     {
855       buffer->PackUnsignedLong(pColor->foreground());
856       buffer->PackUnsignedLong(pColor->background());
857     }
858   }
859   PostBuffer();
860 }
861 
862 
863 //-----ContactList-----------------------------------------------------------
CPT_ContactList(const string & message,unsigned short nLevel,bool bMR,const Licq::Color * pColor,User * pUser)864 CPT_ContactList::CPT_ContactList(const string& message, unsigned short nLevel, bool bMR,
865     const Licq::Color* pColor, User* pUser)
866   : CPacketTcp(ICQ_CMDxTCP_START,
867        ICQ_CMDxSUB_CONTACTxLIST | (bMR ? ICQ_CMDxSUB_FxMULTIREC : 0),
868         DcSocket::ChannelNormal,
869         message, true, nLevel, pUser)
870 {
871   if (m_nVersion >= 6)
872     m_nSize += 8;
873   InitBuffer();
874   if (m_nVersion >= 6)
875   {
876     if (pColor == NULL)
877     {
878       buffer->PackUnsignedLong(0x00000000);
879       buffer->PackUnsignedLong(0x00FFFFFF);
880     }
881     else
882     {
883       buffer->PackUnsignedLong(pColor->foreground());
884       buffer->PackUnsignedLong(pColor->background());
885     }
886   }
887   PostBuffer();
888 }
889 
890 
891 //-----ReadAwayMessage----------------------------------------------------------
CPT_ReadAwayMessage(User * _cUser)892 CPT_ReadAwayMessage::CPT_ReadAwayMessage(User* _cUser)
893   : CPacketTcp(ICQ_CMDxTCP_START, ICQ_CMDxTCP_READxAWAYxMSG,
894         DcSocket::ChannelNormal, "", true, ICQ_TCPxMSG_AUTOxREPLY, _cUser)
895 {
896   // Properly set the subcommand to get the correct away message
897   unsigned status = _cUser->status();
898   if (status & Licq::User::DoNotDisturbStatus)
899     m_nSubCommand = ICQ_CMDxTCP_READxDNDxMSG;
900   else if (status & Licq::User::OccupiedStatus)
901     m_nSubCommand = ICQ_CMDxTCP_READxOCCUPIEDxMSG;
902   else if (status & Licq::User::NotAvailableStatus)
903     m_nSubCommand = ICQ_CMDxTCP_READxNAxMSG;
904   else if (status & Licq::User::AwayStatus)
905     m_nSubCommand = ICQ_CMDxTCP_READxAWAYxMSG;
906   else if (status & Licq::User::FreeForChatStatus)
907     m_nSubCommand = ICQ_CMDxTCP_READxFFCxMSG;
908   else
909     m_nSubCommand = ICQ_CMDxTCP_READxAWAYxMSG;
910 
911   if (m_nVersion == 6)
912     m_nSize += 8;
913   InitBuffer();
914   if (m_nVersion == 6)
915   {
916     buffer->PackUnsignedLong(0xFFFFFFFF);
917     buffer->PackUnsignedLong(0xFFFFFFFF);
918   }
919   PostBuffer();
920 }
921 
922 //-----ChatRequest--------------------------------------------------------------
CPT_ChatRequest(const string & message,const string & chatUsers,unsigned short nPort,unsigned short nLevel,User * pUser,bool bICBM)923 CPT_ChatRequest::CPT_ChatRequest(const string& message, const string& chatUsers,
924    unsigned short nPort, unsigned short nLevel, User* pUser, bool bICBM)
925   : CPacketTcp(ICQ_CMDxTCP_START, bICBM ? ICQ_CMDxSUB_ICBM : ICQ_CMDxSUB_CHAT,
926         DcSocket::ChannelNormal,
927         bICBM ? "" : message, true, nLevel, pUser)
928 {
929   m_nSize += 2 + chatUsers.size() + 1 + 8;
930   if (bICBM)
931     m_nSize += 47 + message.size() + 21;
932 
933   InitBuffer();
934 
935   if (bICBM)
936   {
937     buffer->PackUnsignedShort(0x3A);
938     buffer->PackUnsignedLongBE(0xBFF720B2);
939     buffer->PackUnsignedLongBE(0x378ED411);
940     buffer->PackUnsignedLongBE(0xBD280004);
941     buffer->PackUnsignedLongBE(0xAC96D905);
942     buffer->PackUnsignedShort(0);
943 
944     buffer->PackUnsignedLong(21);
945     buffer->Pack("Send / Start ICQ Chat", 21);
946 
947     buffer->PackUnsignedLongBE(0x00000100);
948     buffer->PackUnsignedLongBE(0x00010000);
949     buffer->PackUnsignedLongBE(0);
950     buffer->PackUnsignedShortBE(0);
951     buffer->PackChar(0);
952 
953     buffer->PackUnsignedLong(message.size() + chatUsers.size() + 15);
954 
955     buffer->PackUnsignedLong(message.size());
956 
957     if (!message.empty())
958       buffer->pack(message);
959 
960     buffer->packString(chatUsers);
961 
962     buffer->PackUnsignedShortBE(nPort);
963     buffer->PackUnsignedShort(0);
964     buffer->PackUnsignedShort(nPort);
965     buffer->PackUnsignedShort(0);
966   }
967   else
968   {
969     buffer->packString(chatUsers);
970     buffer->packUInt16BE(nPort);
971     buffer->packUInt16BE(0);
972     buffer->PackUnsignedLong(nPort);
973   }
974 
975   PostBuffer();
976 }
977 
978 
979 //-----FileTransfer--------------------------------------------------------------
CPT_FileTransfer(const list<string> & lFileList,const string & filename,const string & description,unsigned short nLevel,User * _cUser)980 CPT_FileTransfer::CPT_FileTransfer(const list<string>& lFileList, const string& filename,
981     const string& description, unsigned short nLevel, User* _cUser)
982   : CPacketTcp(ICQ_CMDxTCP_START, ICQ_CMDxSUB_FILE, DcSocket::ChannelNormal,
983         description, true, nLevel, _cUser),
984     m_lFileList(lFileList.begin(), lFileList.end())
985 {
986   m_bValid = false;
987   m_nFileSize = 0;
988 
989   list<string>::iterator it;
990   for (it = m_lFileList.begin(); it != m_lFileList.end(); ++it)
991   {
992     // Check file exists and get size
993     struct stat buf;
994     if (!(it->empty() || stat(it->c_str(), &buf) < 0))
995     {
996        m_nFileSize += buf.st_size;
997        m_bValid = true;
998     }
999   }
1000 
1001   // Remove path from filename (if it exists)
1002   myFilename = filename;
1003   size_t posSlash = myFilename.rfind('/');
1004   if (posSlash != string::npos)
1005     myFilename.erase(0, posSlash+1);
1006 
1007 	if (!m_bValid)  return;
1008 
1009   m_nSize += 15 + myFilename.size();
1010   InitBuffer();
1011 
1012   buffer->PackUnsignedLong(0);
1013   buffer->packString(myFilename);
1014   buffer->PackUnsignedLong(m_nFileSize);
1015   buffer->PackUnsignedLong(0);
1016 
1017   PostBuffer();
1018 }
1019 
1020 
1021 //-----Key------------------------------------------------------------------
CPT_OpenSecureChannel(User * _cUser)1022 CPT_OpenSecureChannel::CPT_OpenSecureChannel(User* _cUser)
1023   : CPacketTcp(ICQ_CMDxTCP_START, ICQ_CMDxSUB_SECURExOPEN,
1024         DcSocket::ChannelNormal,
1025        "", true, ICQ_TCPxMSG_NORMAL, _cUser)
1026 {
1027   InitBuffer();
1028   PostBuffer();
1029 }
1030 
1031 
CPT_CloseSecureChannel(User * _cUser)1032 CPT_CloseSecureChannel::CPT_CloseSecureChannel(User* _cUser)
1033   : CPacketTcp(ICQ_CMDxTCP_START, ICQ_CMDxSUB_SECURExCLOSE,
1034         DcSocket::ChannelNormal,
1035        "", true, ICQ_TCPxMSG_NORMAL, _cUser)
1036 {
1037   InitBuffer();
1038   PostBuffer();
1039 }
1040 
1041 
1042 //+++++Ack++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1043 
CPT_Ack(unsigned short _nSubCommand,unsigned short _nSequence,bool _bAccept,bool l,User * pUser)1044 CPT_Ack::CPT_Ack(unsigned short _nSubCommand, unsigned short _nSequence,
1045     bool _bAccept, bool l, User* pUser)
1046   : CPacketTcp(ICQ_CMDxTCP_ACK, _nSubCommand, DcSocket::ChannelNormal,
1047       "", _bAccept, l ? ICQ_TCPxMSG_URGENT : ICQ_TCPxMSG_NORMAL, pUser)
1048 {
1049   m_nSequence = _nSequence;
1050   myMessage = gTranslator.fromUtf8(pUser->makeAutoResponse());
1051 }
1052 
~CPT_Ack()1053 CPT_Ack::~CPT_Ack()
1054 {
1055   // Empty
1056 }
1057 
1058 //-----AckGeneral---------------------------------------------------------------
CPT_AckGeneral(unsigned short nCmd,unsigned short nSequence,bool bAccept,bool nLevel,User * pUser)1059 CPT_AckGeneral::CPT_AckGeneral(unsigned short nCmd, unsigned short nSequence,
1060     bool bAccept, bool nLevel, User* pUser)
1061   : CPT_Ack(nCmd, nSequence, bAccept, nLevel, pUser)
1062 {
1063   if (m_nVersion >= 6)
1064     m_nSize += 8;
1065   InitBuffer();
1066   if (m_nVersion == 6)
1067   {
1068     buffer->PackUnsignedLong(0x00000000);
1069     buffer->PackUnsignedLong(0x00000000);
1070   }
1071   else if (m_nVersion >= 7)
1072 	{
1073     buffer->PackUnsignedLong(0x00000000);
1074     buffer->PackUnsignedLong(0x00FFFFFF);
1075   }
1076 
1077   PostBuffer();
1078 }
1079 
1080 
1081 //-----AckKey---------------------------------------------------------------
CPT_AckOpenSecureChannel(unsigned short nSequence,bool ok,User * pUser)1082 CPT_AckOpenSecureChannel::CPT_AckOpenSecureChannel(unsigned short nSequence,
1083     bool ok, User* pUser)
1084   : CPT_Ack(ICQ_CMDxSUB_SECURExOPEN, nSequence, true, true, pUser)
1085 {
1086   myMessage = (ok ? "1" : "");
1087   InitBuffer();
1088   PostBuffer();
1089 }
1090 
1091 
CPT_AckOldSecureChannel(unsigned short nSequence,User * pUser)1092 CPT_AckOldSecureChannel::CPT_AckOldSecureChannel(unsigned short nSequence,
1093     User* pUser)
1094   : CPT_Ack(ICQ_CMDxSUB_SECURExOPEN, nSequence, true, true, pUser)
1095 {
1096   myMessage.clear();
1097   if (m_nVersion == 6)
1098     m_nSize += 8;
1099 
1100   InitBuffer();
1101   if (m_nVersion == 6)
1102   {
1103     buffer->PackUnsignedLong(0x00000000);
1104     buffer->PackUnsignedLong(0x00000000);
1105   }
1106   PostBuffer();
1107 }
1108 
1109 
CPT_AckCloseSecureChannel(unsigned short nSequence,User * pUser)1110 CPT_AckCloseSecureChannel::CPT_AckCloseSecureChannel(unsigned short nSequence,
1111     User* pUser)
1112   : CPT_Ack(ICQ_CMDxSUB_SECURExCLOSE, nSequence, true, true, pUser)
1113 {
1114   myMessage.clear();
1115   InitBuffer();
1116   PostBuffer();
1117 }
1118 
1119 
1120 
1121 #if 0
1122 //-----AckMessage---------------------------------------------------------------
1123 CPT_AckMessage::CPT_AckMessage(unsigned short _nSequence, bool _bAccept,
1124     bool nLevel, User* _cUser)
1125   : CPT_Ack(ICQ_CMDxSUB_MSG, _nSequence, _bAccept, nLevel, _cUser)
1126 {
1127   InitBuffer();
1128   PostBuffer();
1129 }
1130 
1131 
1132 
1133 //-----AckReadAwayMessage-------------------------------------------------------
1134 CPT_AckReadAwayMessage::CPT_AckReadAwayMessage(unsigned short _nSubCommand,
1135     unsigned short _nSequence, bool _bAccept, User* _cUser)
1136   : CPT_Ack(_nSubCommand, _nSequence, _bAccept, false, _cUser)
1137 {
1138   InitBuffer();
1139   PostBuffer();
1140 }
1141 
1142 
1143 //-----AckUrl-------------------------------------------------------------------
1144 CPT_AckUrl::CPT_AckUrl(unsigned short _nSequence, bool _bAccept, bool nLevel,
1145     User* _cUser)
1146   : CPT_Ack(ICQ_CMDxSUB_URL, _nSequence, _bAccept, nLevel, _cUser)
1147 {
1148   InitBuffer();
1149   PostBuffer();
1150 }
1151 
1152 
1153 //-----AckContactList--------------------------------------------------------
1154 CPT_AckContactList::CPT_AckContactList(unsigned short _nSequence, bool _bAccept,
1155     bool nLevel, User* _cUser)
1156   : CPT_Ack(ICQ_CMDxSUB_CONTACTxLIST, _nSequence, _bAccept, nLevel, _cUser)
1157 {
1158   InitBuffer();
1159   PostBuffer();
1160 }
1161 #endif
1162 
1163 //-----AckChatRefuse------------------------------------------------------------
CPT_AckChatRefuse(const string & reason,unsigned short _nSequence,User * _cUser)1164 CPT_AckChatRefuse::CPT_AckChatRefuse(const string& reason,
1165     unsigned short _nSequence, User *_cUser)
1166   : CPT_Ack(ICQ_CMDxSUB_CHAT, _nSequence, false, false, _cUser)
1167 {
1168   myMessage = reason;
1169   char temp_1[11] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1170 
1171   m_nSize += 11;
1172   InitBuffer();
1173   buffer->Pack(temp_1, 11);
1174   PostBuffer();
1175 }
1176 
1177 
1178 //-----AckChatAccept------------------------------------------------------------
CPT_AckChatAccept(unsigned short _nPort,const string & clients,unsigned short _nSequence,User * _cUser,bool bICBM)1179 CPT_AckChatAccept::CPT_AckChatAccept(unsigned short _nPort, const string& clients,
1180     unsigned short _nSequence, User* _cUser, bool bICBM)
1181   : CPT_Ack(bICBM ? ICQ_CMDxSUB_ICBM : ICQ_CMDxSUB_CHAT, _nSequence, true, true, _cUser)
1182 {
1183   m_nPort = _nPort;
1184   m_nStatus = ICQ_TCPxACK_ONLINE;
1185 
1186   m_nSize += 11 + clients.size();
1187   if (bICBM)
1188     m_nSize += 68;
1189 
1190   InitBuffer();
1191 
1192   if (bICBM)
1193   {
1194     buffer->PackUnsignedShort(0x3A);
1195     buffer->PackUnsignedLongBE(0xBFF720B2);
1196     buffer->PackUnsignedLongBE(0x378ED411);
1197     buffer->PackUnsignedLongBE(0xBD280004);
1198     buffer->PackUnsignedLongBE(0xAC96D905);
1199     buffer->PackUnsignedShort(0);
1200 
1201     buffer->PackUnsignedLong(21);
1202     buffer->Pack("Send / Start ICQ Chat", 21);
1203 
1204     buffer->PackUnsignedLongBE(0x00000100);
1205     buffer->PackUnsignedLongBE(0x00010000);
1206     buffer->PackUnsignedLongBE(0);
1207     buffer->PackUnsignedShortBE(0);
1208     buffer->PackChar(0);
1209 
1210     buffer->PackUnsignedLong(15 + clients.size());
1211 
1212     buffer->PackUnsignedLong(0);
1213 
1214     buffer->packString(clients);
1215 
1216     buffer->PackUnsignedShortBE(m_nPort);
1217     buffer->PackUnsignedShort(0);
1218     buffer->PackUnsignedShort(m_nPort);
1219     buffer->PackUnsignedShort(0);
1220   }
1221   else
1222   {
1223     buffer->PackString("");
1224     buffer->packUInt16BE(m_nPort);
1225     buffer->packUInt16BE(0);
1226     buffer->PackUnsignedLong(m_nPort);
1227   }
1228 
1229   PostBuffer();
1230 }
1231 
1232 
1233 //-----AckFileRefuse------------------------------------------------------------
CPT_AckFileRefuse(const string & reason,unsigned short _nSequence,User * _cUser)1234 CPT_AckFileRefuse::CPT_AckFileRefuse(const string& reason,
1235     unsigned short _nSequence, User* _cUser)
1236   : CPT_Ack(ICQ_CMDxSUB_FILE, _nSequence, false, false, _cUser)
1237 {
1238   myMessage = reason;
1239 
1240   m_nSize += 15;
1241   InitBuffer();
1242 
1243   buffer->PackUnsignedLong(0);
1244   buffer->PackString("");
1245   buffer->PackUnsignedLong(0);
1246   buffer->PackUnsignedLong(0);
1247 
1248   PostBuffer();
1249 }
1250 
1251 
1252 //-----AckFileAccept------------------------------------------------------------
CPT_AckFileAccept(unsigned short _nPort,unsigned short _nSequence,User * _cUser)1253 CPT_AckFileAccept::CPT_AckFileAccept(unsigned short _nPort,
1254     unsigned short _nSequence, User* _cUser)
1255   : CPT_Ack(ICQ_CMDxSUB_FILE, _nSequence, true, true, _cUser)
1256 {
1257   m_nFileSize = 0;
1258   m_nPort = _nPort;
1259   m_nStatus = ICQ_TCPxACK_ONLINE;
1260 
1261   m_nSize += 15;
1262   InitBuffer();
1263 
1264   buffer->packUInt16BE(m_nPort);
1265   buffer->packUInt16BE(0);
1266   buffer->PackString("");
1267   buffer->PackUnsignedLong(m_nFileSize);
1268   buffer->PackUnsignedLong(m_nPort);
1269 
1270   PostBuffer();
1271 }
1272 
1273 
1274 //+++++Cancel+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CPT_Cancel(unsigned short _nSubCommand,unsigned short _nSequence,User * _cUser)1275 CPT_Cancel::CPT_Cancel(unsigned short _nSubCommand, unsigned short _nSequence,
1276     User* _cUser)
1277   : CPacketTcp(ICQ_CMDxTCP_CANCEL, _nSubCommand, DcSocket::ChannelNormal, "", true, 0, _cUser)
1278 {
1279   m_nSequence = _nSequence;
1280 }
1281 
1282 
1283 
1284 //-----CancelChat---------------------------------------------------------------
CPT_CancelChat(unsigned short _nSequence,User * _cUser)1285 CPT_CancelChat::CPT_CancelChat(unsigned short _nSequence, User* _cUser)
1286   : CPT_Cancel(ICQ_CMDxSUB_CHAT, _nSequence, _cUser)
1287 {
1288   char temp_1[11] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1289 
1290   m_nSize += 11;
1291   InitBuffer();
1292   buffer->Pack(temp_1, 11);
1293   PostBuffer();
1294 }
1295 
1296 
1297 //-----CancelFile---------------------------------------------------------------
CPT_CancelFile(unsigned short _nSequence,User * _cUser)1298 CPT_CancelFile::CPT_CancelFile(unsigned short _nSequence, User* _cUser)
1299   : CPT_Cancel(ICQ_CMDxSUB_FILE, _nSequence, _cUser)
1300 {
1301   m_nSize += 15;
1302   InitBuffer();
1303 
1304   buffer->PackUnsignedLong(0);
1305   buffer->PackString("");
1306   buffer->PackUnsignedLong(0);
1307   buffer->PackUnsignedLong(0);
1308 
1309   PostBuffer();
1310 }
1311 
1312 //-----Send error reply------------------------------------------------------
CPT_PluginError(User * _cUser,unsigned short nSequence,int channel)1313 CPT_PluginError::CPT_PluginError(User* _cUser, unsigned short nSequence,
1314     int channel)
1315   : CPacketTcp(ICQ_CMDxTCP_ACK, 0, channel, "\x03", true, 0, _cUser)
1316 {
1317   m_nSequence = nSequence;
1318 
1319   InitBuffer();
1320   PostBuffer();
1321 }
1322 
1323 //-----Send info plugin request------------------------------------------------
CPT_InfoPluginReq(User * _cUser,const uint8_t * GUID,unsigned long nTime)1324 CPT_InfoPluginReq::CPT_InfoPluginReq(User* _cUser, const uint8_t* GUID,
1325   unsigned long nTime)
1326   : CPacketTcp(ICQ_CMDxTCP_START, ICQ_CMDxSUB_MSG, DcSocket::ChannelInfo, "", true, 0, _cUser)
1327 {
1328   m_nSize += GUID_LENGTH + 4;
1329   memcpy(m_ReqGUID, GUID, GUID_LENGTH);
1330 
1331   InitBuffer();
1332 
1333   buffer->Pack(GUID, GUID_LENGTH);
1334 
1335   buffer->PackUnsignedLong(nTime);
1336 
1337   PostBuffer();
1338 }
1339 
1340 //----Reply to phone book request-----------------------------------------------
CPT_InfoPhoneBookResp(User * _cUser,unsigned short nSequence)1341 CPT_InfoPhoneBookResp::CPT_InfoPhoneBookResp(User* _cUser,
1342   unsigned short nSequence)
1343   : CPacketTcp(ICQ_CMDxTCP_ACK, 0, DcSocket::ChannelInfo, "\x01", true, ICQ_TCPxMSG_URGENT2, _cUser)
1344 {
1345   OwnerReadGuard o(gIcqProtocol.ownerId());
1346   const Licq::IcqPhoneBookVector& book = o->getPhoneBook();
1347 
1348   unsigned long nLen = 4 + 4;
1349   BOOST_FOREACH(const struct Licq::PhoneBookEntry& entry, book)
1350   {
1351     nLen += 4 + entry.description.size() + 4 + entry.areaCode.size()
1352         + 4 + entry.phoneNumber.size() + 4 + entry.extension.size()
1353         + 4 + entry.country.size() + 4 + 4 + 4
1354         + 4 + entry.gateway.size() + 4 + 4 + 4 + 4;
1355   }
1356 
1357   m_nSize += 2 + 2 + 4 + 4 + nLen;
1358   m_nSequence = nSequence;
1359   InitBuffer();
1360 
1361   buffer->PackUnsignedShort(0);   //Unknown
1362   buffer->PackUnsignedShort(1);   //Unknown
1363   buffer->PackUnsignedLong(o->ClientInfoTimestamp());
1364   buffer->PackUnsignedLong(nLen);  //Bytes remaining in packet
1365 
1366   buffer->PackUnsignedLong(ICQ_PLUGIN_RESP_PHONExBOOK); //Response ID
1367 
1368   buffer->PackUnsignedLong(book.size());
1369 
1370   BOOST_FOREACH(const struct Licq::PhoneBookEntry& entry, book)
1371   {
1372     buffer->packString32LE(entry.description);
1373     buffer->packString32LE(entry.areaCode);
1374     buffer->packString32LE(entry.phoneNumber);
1375     buffer->packString32LE(entry.extension);
1376     buffer->packString32LE(entry.country);
1377     buffer->packUInt32LE(entry.nActive);
1378   }
1379 
1380   BOOST_FOREACH(const struct Licq::PhoneBookEntry& entry, book)
1381   {
1382     buffer->packUInt32LE(4 + 4 + entry.gateway.size() + 4 + 4 + 4 + 4);
1383     buffer->packUInt32LE(entry.nType);
1384     buffer->packString32LE(entry.gateway);
1385     buffer->packUInt32LE(entry.nGatewayType);
1386     buffer->packUInt32LE(entry.nSmsAvailable);
1387     buffer->packUInt32LE(entry.nRemoveLeading0s);
1388     buffer->packUInt32LE(entry.nPublish);
1389   }
1390 
1391   PostBuffer();
1392 }
1393 
1394 //----Reply to picture request--------------------------------------------------
CPT_InfoPictureResp(User * _cUser,unsigned short nSequence)1395 CPT_InfoPictureResp::CPT_InfoPictureResp(User* _cUser, unsigned short nSequence)
1396   : CPacketTcp(ICQ_CMDxTCP_ACK, 0, DcSocket::ChannelInfo, "\x01", true, ICQ_TCPxMSG_URGENT2, _cUser)
1397 {
1398   OwnerReadGuard o(gIcqProtocol.ownerId());
1399   string filename = o->pictureFileName();
1400   unsigned long nLen = 0, nFileLen = 0;
1401   int fd = -1;
1402   if (o->GetPicturePresent())
1403   {
1404     fd = open(filename.c_str(), O_RDONLY);
1405     if (fd == -1)
1406     {
1407       gLog.error(tr("Unable to open picture file (%s): %s."),
1408           filename.c_str(), strerror(errno));
1409     }
1410     else
1411     {
1412       struct stat fi;
1413       if (fstat(fd, &fi) == -1)
1414       {
1415         gLog.error(tr("Unable to stat picture file (%s):%s."),
1416             filename.c_str(), strerror(errno));
1417       }
1418       else
1419       {
1420         nFileLen = fi.st_size;
1421         nLen = 4 + 4 + 1 + 4 + nFileLen;
1422       }
1423     }
1424   }
1425 
1426   m_nSize += 2 + 2 + 4 + 4 + nLen;
1427   m_nSequence = nSequence;
1428   InitBuffer();
1429 
1430   buffer->PackUnsignedShort(0);   //Unknown
1431   buffer->PackUnsignedShort(1);   //Unknown
1432   buffer->PackUnsignedLong(o->ClientInfoTimestamp());
1433   buffer->PackUnsignedLong(nLen);  //Bytes remaining in packet
1434 
1435   if (nLen != 0)
1436   {
1437     buffer->PackUnsignedLong(ICQ_PLUGIN_RESP_PICTURE); //Response ID
1438 
1439     buffer->PackUnsignedLong(1); //filename length
1440     buffer->PackChar('p'); //windows icq needs a filename
1441 
1442     buffer->PackUnsignedLong(nFileLen);
1443 
1444     char buf[8192];
1445     unsigned long nRead = 0;
1446     while (nRead < nFileLen)
1447     {
1448       unsigned long nToRead;
1449       if (sizeof(buf) < nFileLen - nRead)
1450         nToRead = sizeof(buf);
1451       else
1452         nToRead = nFileLen - nRead;
1453 
1454       ssize_t nBytesRead = read(fd, buf, nToRead);
1455       if (nBytesRead == -1)
1456       {
1457         gLog.error(tr("Failed to read file (%s): %s."),
1458             filename.c_str(), strerror(errno));
1459         break;
1460       }
1461       if (nBytesRead == 0)
1462       {
1463         gLog.error(tr("Premature end of file (%s): %s."),
1464             filename.c_str(), strerror(errno));
1465         break;
1466       }
1467 
1468       nRead += nBytesRead;
1469       for (ssize_t i = 0; i < nBytesRead; i++)
1470         buffer->PackChar(buf[i]);
1471     }
1472 
1473     if (nRead < nFileLen)
1474     {
1475       //failed to read as much as predicted, fill with 0s
1476       for (; nRead < nFileLen; nRead++)
1477         buffer->PackChar(0);
1478     }
1479   }
1480 
1481   if (fd != -1)
1482     close(fd);
1483 }
1484 
1485 //----Reply to plugin list request----------------------------------------------
CPT_InfoPluginListResp(User * _cUser,unsigned short nSequence)1486 CPT_InfoPluginListResp::CPT_InfoPluginListResp(User* _cUser, unsigned short nSequence)
1487   : CPacketTcp(ICQ_CMDxTCP_ACK, 0, DcSocket::ChannelInfo, "\x01", true, ICQ_TCPxMSG_URGENT2, _cUser)
1488 {
1489   unsigned long num_plugins = sizeof(IcqProtocol::info_plugins)/sizeof(struct PluginList);
1490 
1491   unsigned long nLen;
1492   if (num_plugins == 0)
1493     nLen = 0;
1494   else
1495   {
1496     nLen = 4 + 4;
1497     for (unsigned long i = 0; i < num_plugins; i ++)
1498     {
1499       nLen += GUID_LENGTH + 2 + 2 + 4 + strlen(IcqProtocol::info_plugins[i].name)
1500           + 4 + strlen(IcqProtocol::info_plugins[i].description) + 4;
1501     }
1502   }
1503 
1504   m_nSize += 2 + 2 + 4 + 4 + nLen;
1505   m_nSequence = nSequence;
1506   InitBuffer();
1507 
1508   buffer->PackUnsignedShort(0);   //Unknown
1509   buffer->PackUnsignedShort(1);   //Unknown
1510   {
1511     OwnerReadGuard o(gIcqProtocol.ownerId());
1512     buffer->PackUnsignedLong(o->ClientInfoTimestamp());
1513   }
1514   buffer->PackUnsignedLong(nLen);  //Bytes remaining in packet
1515   if (nLen != 0)
1516   {
1517     buffer->PackUnsignedLong(ICQ_PLUGIN_RESP_INFOxLIST); //Response ID
1518     buffer->PackUnsignedLong(num_plugins);
1519     for (unsigned long i = 0; i < num_plugins; i++)
1520     {
1521       buffer->packRaw(IcqProtocol::info_plugins[i].guid, GUID_LENGTH);
1522 
1523       buffer->PackUnsignedShort(0); //Unknown
1524       buffer->PackUnsignedShort(1); //Unknown
1525 
1526       buffer->packString32LE(IcqProtocol::info_plugins[i].name,
1527           strlen(IcqProtocol::info_plugins[i].name));
1528 
1529       buffer->packString32LE(IcqProtocol::info_plugins[i].description,
1530           strlen(IcqProtocol::info_plugins[i].description));
1531 
1532       buffer->PackUnsignedLong(0);  //Unknown
1533     }
1534   }
1535   PostBuffer();
1536 }
1537 
1538 //-----Send status plugin request----------------------------------------------
CPT_StatusPluginReq(User * _cUser,const uint8_t * GUID,unsigned long nTime)1539 CPT_StatusPluginReq::CPT_StatusPluginReq(User* _cUser, const uint8_t* GUID,
1540   unsigned long nTime)
1541   : CPacketTcp(ICQ_CMDxTCP_START, ICQ_CMDxSUB_MSG, DcSocket::ChannelStatus, "", true, 0, _cUser)
1542 {
1543   m_nSize += GUID_LENGTH + 4;
1544   memcpy(m_ReqGUID, GUID, GUID_LENGTH);
1545 
1546   InitBuffer();
1547 
1548   buffer->Pack(GUID, GUID_LENGTH);
1549 
1550   buffer->PackUnsignedLong(nTime);
1551 
1552   PostBuffer();
1553 }
1554 
1555 //----Reply to plugin list request----------------------------------------------
CPT_StatusPluginListResp(User * _cUser,unsigned short nSequence)1556 CPT_StatusPluginListResp::CPT_StatusPluginListResp(User* _cUser, unsigned short nSequence)
1557   : CPacketTcp(ICQ_CMDxTCP_ACK, 0, DcSocket::ChannelStatus, "\x01", true, 0, _cUser)
1558 {
1559   unsigned long num_plugins = sizeof(IcqProtocol::status_plugins)/sizeof(struct PluginList);
1560 
1561   unsigned long nLen;
1562   if (num_plugins == 0)
1563     nLen = 0;
1564   else
1565   {
1566     nLen = 4 + 4;
1567     for (unsigned long i = 0; i < num_plugins; i ++)
1568     {
1569       nLen += GUID_LENGTH + 2 + 2 + 4 + strlen(IcqProtocol::status_plugins[i].name)
1570           + 4 + strlen(IcqProtocol::status_plugins[i].description) + 4;
1571     }
1572   }
1573 
1574   m_nSize += 13 + 4 + 4 + nLen;
1575   m_nSequence = nSequence;
1576   InitBuffer();
1577 
1578   buffer->PackUnsignedShort(0);   //Unknown
1579   buffer->PackUnsignedShort(1);   //Unknown
1580   buffer->PackUnsignedLong(0);    //Unknown
1581   buffer->PackUnsignedLong(0);    //Unknown
1582   buffer->PackChar(1);            //Unknown
1583   {
1584     OwnerReadGuard o(gIcqProtocol.ownerId());
1585     buffer->PackUnsignedLong(o->ClientStatusTimestamp());
1586   }
1587   buffer->PackUnsignedLong(nLen);  //Bytes remaining in packet
1588   if (nLen != 0)
1589   {
1590     buffer->PackUnsignedLong(ICQ_PLUGIN_RESP_STATUSxLIST); //Response ID
1591     buffer->PackUnsignedLong(num_plugins);
1592     for (unsigned long i = 0; i < num_plugins; i++)
1593     {
1594       buffer->packRaw(IcqProtocol::status_plugins[i].guid, GUID_LENGTH);
1595 
1596       buffer->PackUnsignedShort(0); //Unknown
1597       buffer->PackUnsignedShort(1); //Unknown
1598 
1599       buffer->packString32LE(IcqProtocol::status_plugins[i].name,
1600           strlen(IcqProtocol::status_plugins[i].name));
1601 
1602       buffer->packString32LE(IcqProtocol::status_plugins[i].description,
1603           strlen(IcqProtocol::status_plugins[i].description));
1604 
1605       buffer->PackUnsignedLong(0);  //Unknown
1606     }
1607   }
1608   PostBuffer();
1609 }
1610 
1611 //----Reply to status request--------------------------------------------------
CPT_StatusPluginResp(User * _cUser,unsigned short nSequence,unsigned long nStatus)1612 CPT_StatusPluginResp::CPT_StatusPluginResp(User* _cUser,
1613   unsigned short nSequence,
1614   unsigned long nStatus)
1615   : CPacketTcp(ICQ_CMDxTCP_ACK, 0, DcSocket::ChannelStatus, "\x02", true, 0, _cUser)
1616 {
1617   m_nSize += 2 + 2 + 4 + 4 + 1;
1618   m_nSequence = nSequence;
1619   InitBuffer();
1620 
1621   buffer->PackUnsignedShort(0);   //Unknown
1622   buffer->PackUnsignedShort(1);   //Unknown
1623   buffer->PackUnsignedLong(nStatus);
1624   {
1625     OwnerReadGuard o(gIcqProtocol.ownerId());
1626     buffer->PackUnsignedLong(o->ClientStatusTimestamp());
1627   }
1628   buffer->PackChar(1);            //Unknown
1629 
1630   PostBuffer();
1631 }
1632