Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:lmich
Licq
ssbi-licq2.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File ssbi-licq2.patch of Package Licq
diff -urN licq/include/licq_buffer.h licq-ssbi/include/licq_buffer.h --- licq/include/licq_buffer.h 2006-08-10 21:17:07.000000000 +0300 +++ licq-ssbi/include/licq_buffer.h 2008-01-22 01:11:26.000000000 +0200 @@ -85,6 +85,7 @@ CBuffer& operator >> (unsigned short &in); CBuffer& operator >> (unsigned long &in); char *UnpackRaw(char *, unsigned short); + char *UnpackBinBlock(char *, unsigned short); char *UnpackString(char *, unsigned short); char *UnpackString(); // Need to delete[] returned string char *UnpackStringBE(char *, unsigned short); diff -urN licq/include/licq_events.h licq-ssbi/include/licq_events.h --- licq/include/licq_events.h 2006-11-11 21:24:51.000000000 +0200 +++ licq-ssbi/include/licq_events.h 2008-01-22 01:11:26.000000000 +0200 @@ -249,6 +249,12 @@ // Daemon only unsigned short SubType() { return m_nSubType; } unsigned short ExtraInfo() { return m_nExtraInfo; } + void SetSubType(unsigned short nSubType) { m_nSubType = nSubType; } + bool NoAck() { return m_NoAck; } + void SetNoAck(bool NoAck) { m_NoAck = NoAck; } + bool IsCancelled() { return m_bCancelled; } + + void AttachPacket(CPacket *p); // Compare this event to another one bool CompareEvent(int, unsigned short) const; @@ -290,9 +296,11 @@ static unsigned long s_nNextEventId; friend class CICQDaemon; +friend class COscarService; friend class CMSN; friend void *ProcessRunningEvent_Client_tep(void *p); friend void *ProcessRunningEvent_Server_tep(void *p); +friend void *OscarServiceSendQueue_tep(void *p); friend void *MonitorSockets_tep(void *p); }; @@ -476,6 +484,8 @@ PROTOxREQUESTxINFO, //! The user has requested to update the owner's profile/information. PROTOxUPDATExINFO, + //! The user has requested the user's picture/icon/avatar/etc.. + PROTOxREQUESTxPICTURE, //! The user has requested this user be added to the Invisible/Block list. PROTOxBLOCKxUSER, //! The user has requested this user be removed from the Invisible/Block @@ -684,6 +694,13 @@ *m_szZipCode; }; +class CRequestPicture : public CSignal +{ +public: + CRequestPicture(const char *); + virtual ~CRequestPicture(); +}; + class CBlockUserSignal : public CSignal { public: diff -urN licq/include/licq_icqd.h licq-ssbi/include/licq_icqd.h --- licq/include/licq_icqd.h 2007-08-21 14:51:52.000000000 +0300 +++ licq-ssbi/include/licq_icqd.h 2008-01-22 01:11:26.000000000 +0200 @@ -42,6 +42,7 @@ class SrvSocket; class INetSocket; class ProxyServer; +class COscarService; class CReverseConnectToUserData; class CMSN; @@ -300,6 +301,8 @@ const char *szFaxNumber, const char *szAddress, const char *szCellularNumber, const char *szZipCode, unsigned short nCountryCode, bool bHideEmail); + unsigned long ProtoRequestPicture(const char *szId, unsigned long nPPID); + unsigned long ProtoOpenSecureChannel(const char *szId, unsigned long nPPID); unsigned long ProtoCloseSecureChannel(const char *szId, unsigned long nPPID); void ProtoOpenSecureChannelCancel(const char *szId, unsigned long nPPID, @@ -474,6 +477,7 @@ void icqUpdateContactList(); void icqTypingNotification(const char *_szId, bool _bActive); void icqCheckInvisible(const char *_szId); + void icqRequestService(unsigned short nFam); // Visible/Invisible/Ignore list functions void ProtoToggleInvisibleList(const char *_szId, unsigned long _nPPID); @@ -514,6 +518,8 @@ void UnregisterProtoPlugin(); char *ProtoPluginName(unsigned long); + EDaemonStatus Status() { return m_eStatus; } + void PluginUIViewEvent(const char *szId, unsigned long nPPID ) { PushPluginSignal(new CICQSignal(SIGNAL_UI_VIEWEVENT, 0, szId, nPPID, 0)); } @@ -567,7 +573,9 @@ // Proxy options void InitProxy(); + ProxyServer *CreateProxy(); bool ProxyEnabled() { return m_bProxyEnabled; } + ProxyServer *GetProxy() { return m_xProxy; } void SetProxyEnabled(bool b) { m_bProxyEnabled = b; } unsigned short ProxyType() { return m_nProxyType; } void SetProxyType(unsigned short t) { m_nProxyType = t; } @@ -609,10 +617,12 @@ // ICQ options bool UseServerContactList() { return m_bUseSS; } + bool UseServerSideBuddyIcons() { return m_bUseSSBI; } bool SendTypingNotification() { return m_bSendTN; } - void SetUseServerContactList(bool b) { m_bUseSS = b; } - void SetSendTypingNotification(bool b) { m_bSendTN = b; } + void SetUseServerContactList(bool b) { m_bUseSS = b; } + void SetUseServerSideBuddyIcons(bool b); + void SetSendTypingNotification(bool b) { m_bSendTN = b; } // Misc functions bool ReconnectAfterUinClash() { return m_bReconnectAfterUinClash; } @@ -700,8 +710,12 @@ char *m_szProxyPasswd; ProxyServer *m_xProxy; + // Services + COscarService *m_xSSBIService; + // Misc bool m_bUseSS; // server side list + bool m_bUseSSBI; // server side buddy icons bool m_bSendTN; // Send typing notifications bool m_bReconnectAfterUinClash; // reconnect after uin has been used from another location? @@ -729,6 +743,7 @@ pthread_t thread_monitorsockets, thread_ping, thread_updateusers, + thread_ssbiservice, thread_shutdown; pthread_cond_t cond_serverack; @@ -762,6 +777,7 @@ ICQEvent *DoneExtendedEvent(unsigned long tag, EventResult _eResult); bool hasServerEvent(unsigned long); void ProcessDoneEvent(ICQEvent *); + void PushEvent(ICQEvent *); void PushExtendedEvent(ICQEvent *); void PushPluginSignal(CICQSignal *); void PushPluginEvent(ICQEvent *); @@ -830,10 +846,12 @@ friend void *ReverseConnectToUser_tep(void *p); friend void *ProcessRunningEvent_Client_tep(void *p); friend void *ProcessRunningEvent_Server_tep(void *p); + friend void *OscarServiceSendQueue_tep(void *p); friend void *Shutdown_tep(void *p); friend void *ConnectToServer_tep(void *s); friend class ICQUser; friend class CSocketManager; + friend class COscarService; friend class CChatManager; friend class CFileTransferManager; friend class COnEventManager; diff -urN licq/include/licq_icq.h licq-ssbi/include/licq_icq.h --- licq/include/licq_icq.h 2008-01-03 16:09:22.000000000 +0200 +++ licq-ssbi/include/licq_icq.h 2008-01-22 01:11:26.000000000 +0200 @@ -34,6 +34,7 @@ const unsigned short ICQ_SNACxFAM_BUDDY = 0x0003; const unsigned short ICQ_SNACxFAM_MESSAGE = 0x0004; const unsigned short ICQ_SNACxFAM_BOS = 0x0009; +const unsigned short ICQ_SNACxFAM_SSBI = 0x0010; const unsigned short ICQ_SNACxFAM_LIST = 0x0013; const unsigned short ICQ_SNACxFAM_VARIOUS = 0x0015; const unsigned short ICQ_SNACxFAM_NEWUIN = 0x0017; @@ -104,6 +105,13 @@ const unsigned short ICQ_SNACxREQUEST_IMAGE = 0x000C; // client const unsigned short ICQ_SNACxSEND_IMAGE = 0x000D; // server +// Subtypes for SSBI family +const unsigned short ICQ_SNACxSSBI_ERROR = 0x0001; // server +const unsigned short ICQ_SNACxSSBI_UPLOAD = 0x0002; // client +const unsigned short ICQ_SNACxSSBI_UPLOADxACK = 0x0003; // server +const unsigned short ICQ_SNACxSSBI_ICONxREQUEST = 0x0006; // client +const unsigned short ICQ_SNACxSSBI_ICONxREPLY = 0x0007; // server + // Subtypes for list family const unsigned short ICQ_SNACxLIST_REQUESTxRIGHTS = 0x0002; // client const unsigned short ICQ_SNACxLIST_RIGHTSxGRANTED = 0x0003; // server @@ -544,6 +552,10 @@ 0x4E, 0xC5, 0x9D, 0x51, 0xA6, 0x47, 0x4E, 0x34, 0xF5, 0xA0 }; +const char ICQ_CAPABILITY_SSBI[] = { 0x09, 0x46, 0x13, 0x46, 0x4C, 0x7F, + 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, + 0x53, 0x54, 0x00, 0x00 }; + const char ICQ_CAPABILITY_LICQxVER[] = { 'L', 'i', 'c', 'q', ' ', 'c', 'l', 'i', 'e', 'n', 't', ' ', 0x00, 0x00, 0x00, 0x00 }; diff -urN licq/include/licq_oscarservice.h licq-ssbi/include/licq_oscarservice.h --- licq/include/licq_oscarservice.h 1970-01-01 03:00:00.000000000 +0300 +++ licq-ssbi/include/licq_oscarservice.h 2008-01-22 01:11:26.000000000 +0200 @@ -0,0 +1,61 @@ +#ifndef OSCARSERVICE_H +#define OSCARSERVICE_H + +#include <list> + +class CICQDaemon; +class ICQEvent; +class CBuffer; +class CPacket; +class ProxyServer; + +enum EOscarServiceStatus {STATUS_UNINITIALIZED, STATUS_SERVICE_REQ_SENT, + STATUS_SERVICE_REQ_ACKED, STATUS_CONNECTED, + STATUS_SRV_READY_RECV, STATUS_SRV_VER_RECV, + STATUS_SRV_RATE_RECV, STATUS_READY}; + +void *OscarServiceSendQueue_tep(void *p); + +class COscarService +{ +public: + COscarService(CICQDaemon *Daemon, unsigned short Fam); + ~COscarService(); + bool Initialize(); + bool ProcessPacket(CBuffer &packet); + unsigned long SendEvent(const char *Id, unsigned short SubType, bool Request); + void ClearQueue(); + + void SetConnectCredential(char *Server, unsigned short Port, + char *Cookie, unsigned short CookieLen); + void ChangeStatus(EOscarServiceStatus s); + int GetSocketDesc() { return mySocketDesc; } + void ResetSocket() { mySocketDesc = -1; } + unsigned short GetFam() { return myFam; } + +protected: + CICQDaemon *myDaemon; + unsigned short myFam; + int mySocketDesc; + ProxyServer *myProxy; + EOscarServiceStatus myStatus; + char *myServer, *myCookie; + unsigned short myPort, myCookieLen; + std::list <ICQEvent *> mySendQueue; + pthread_mutex_t mutex_sendqueue; + pthread_cond_t cond_sendqueue; + pthread_mutex_t mutex_status; + pthread_cond_t cond_status; + + bool SendPacket(CPacket *packet); + bool WaitForStatus(EOscarServiceStatus s); + bool SendSSBIFam(ICQEvent *e); + void ProcessNewChannel(CBuffer &packet); + void ProcessDataChannel(CBuffer &packet); + void ProcessServiceFam(CBuffer &packet, unsigned short SubType, unsigned long RequestId); + void ProcessSSBIFam(CBuffer &packet, unsigned short SubType, unsigned long RequestId); + + friend void *OscarServiceSendQueue_tep(void *p); +}; + +#endif diff -urN licq/include/licq_packets.h licq-ssbi/include/licq_packets.h --- licq/include/licq_packets.h 2008-01-03 16:09:22.000000000 +0200 +++ licq-ssbi/include/licq_packets.h 2008-01-22 01:11:26.000000000 +0200 @@ -134,7 +134,7 @@ void InitBuffer(); static bool s_bRegistered; - static unsigned short s_nSequence; + static unsigned short s_nSequence[32]; static unsigned short s_nSubSequence; static pthread_mutex_t s_xMutex; @@ -145,6 +145,7 @@ unsigned short m_nSubType; unsigned short m_nSubCommand; unsigned short m_nExtraInfo; + unsigned short m_nService; char *m_szSequenceOffset; }; @@ -219,7 +220,7 @@ class CPU_SendCookie : public CSrvPacketTcp { public: - CPU_SendCookie(const char *, int len); + CPU_SendCookie(const char *, int len, unsigned short nService = 0); virtual ~CPU_SendCookie(); }; @@ -237,7 +238,8 @@ class CPU_GenericFamily : public CPU_CommonFamily { public: - CPU_GenericFamily(unsigned short Family, unsigned short SubType); + CPU_GenericFamily(unsigned short Family, unsigned short SubType, + unsigned short nService = 0); virtual ~CPU_GenericFamily(); }; @@ -312,7 +314,9 @@ class CPU_ImICQ : public CPU_CommonFamily { public: - CPU_ImICQ(); + CPU_ImICQ(); + CPU_ImICQ(unsigned short VerArray[][2], unsigned short NumVer, + unsigned short nService); }; //-----ICQMode------------------------------------------------------------------ @@ -333,7 +337,7 @@ class CPU_RateAck : public CPU_CommonFamily { public: - CPU_RateAck(); + CPU_RateAck(unsigned short nService = 0); }; //-----GenericUinList------------------------------------------------------------ @@ -487,6 +491,8 @@ { public: CPU_ClientReady(); + CPU_ClientReady(unsigned short VerArray[][4], unsigned short NumVer, + unsigned short nService); }; //-----ClientAckNameInfo-------------------------------------------------------- @@ -1126,6 +1132,21 @@ CPU_RequestInfo(const char *szId); }; +//-----RequestBuddyIcon------------------------------------------------------ +class CPU_RequestBuddyIcon : public CPU_CommonFamily +{ +public: + CPU_RequestBuddyIcon(const char *szId, unsigned short _nBuddyIconType, + char _nBuddyIconHashType, const char *_szBuddyIconHash, + unsigned short nService); +}; + +class CPU_RequestService : public CPU_CommonFamily +{ +public: + CPU_RequestService(unsigned short nFam); +}; + //-----AIMFetchAwayMessage-------------------------------------------------- class CPU_AIMFetchAwayMessage : public CPU_CommonFamily { diff -urN licq/include/licq_proxy.h licq-ssbi/include/licq_proxy.h --- licq/include/licq_proxy.h 2006-11-11 21:24:51.000000000 +0200 +++ licq-ssbi/include/licq_proxy.h 2008-01-22 01:11:26.000000000 +0200 @@ -1,3 +1,6 @@ +#ifndef PROXY_H +#define PROXY_H + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -68,3 +71,5 @@ bool HTTPInitProxy(); bool HTTPOpenProxyConnection(const char *_szRemoteName, unsigned short _nRemotePort); }; + +#endif diff -urN licq/include/licq_socket.h licq-ssbi/include/licq_socket.h --- licq/include/licq_socket.h 2006-11-11 21:24:51.000000000 +0200 +++ licq-ssbi/include/licq_socket.h 2008-01-22 01:11:26.000000000 +0200 @@ -166,6 +166,7 @@ // Functions specific to Server TCP communication bool SendPacket(CBuffer *b); bool RecvPacket(); + bool ConnectTo(const char* server, unsigned short port, ProxyServer *xProxy); }; diff -urN licq/include/licq_user.h licq-ssbi/include/licq_user.h --- licq/include/licq_user.h 2008-01-21 22:47:35.000000000 +0200 +++ licq-ssbi/include/licq_user.h 2008-01-22 01:11:26.000000000 +0200 @@ -515,6 +515,10 @@ // Picture Info bool GetPicturePresent() { return m_bPicturePresent; } + unsigned short BuddyIconType() { return m_nBuddyIconType; } + char BuddyIconHashType() { return m_nBuddyIconHashType; } + char *BuddyIconHash() { return m_szBuddyIconHash; } + char *OurBuddyIconHash() { return m_szOurBuddyIconHash; } // Dynamic info fields for protocol plugins string GetPPField(const string &); @@ -634,6 +638,10 @@ // Picture info void SetPicturePresent(bool b) { m_bPicturePresent = b; SavePictureInfo(); } + void SetBuddyIconType(unsigned short s) { m_nBuddyIconType = s; } + void SetBuddyIconHashType(char s) { m_nBuddyIconHashType = s; } + void SetBuddyIconHash(char *s) { SetString(&m_szBuddyIconHash, s); } + void SetOurBuddyIconHash(char *s) { SetString(&m_szOurBuddyIconHash, s); } // Licq Info void SetAwaitingAuth(bool b) { m_bAwaitingAuth = b; } @@ -940,6 +948,9 @@ // Picture Info bool m_bPicturePresent; + unsigned short m_nBuddyIconType; + char m_nBuddyIconHashType; + char *m_szBuddyIconHash, *m_szOurBuddyIconHash; // Dynamic info fields for protocol plugins map<string, string> m_mPPFields; diff -urN licq/plugins/qt-gui/src/sigman.cpp licq-ssbi/plugins/qt-gui/src/sigman.cpp --- licq/plugins/qt-gui/src/sigman.cpp 2007-10-22 16:21:27.000000000 +0300 +++ licq-ssbi/plugins/qt-gui/src/sigman.cpp 2008-01-22 01:11:26.000000000 +0200 @@ -175,6 +175,7 @@ case MAKESNAC(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SENDxSERVER): case MAKESNAC(ICQ_SNACxFAM_LOCATION, ICQ_SNACxREQUESTxUSERxINFO): case MAKESNAC(ICQ_SNACxFAM_LOCATION, ICQ_SNACxLOC_INFOxREQ): + case MAKESNAC(ICQ_SNACxFAM_SSBI, ICQ_SNACxSSBI_ICONxREQUEST): emit signal_doneUserFcn(e); break; diff -urN licq/plugins/qt-gui/src/userinfodlg.cpp licq-ssbi/plugins/qt-gui/src/userinfodlg.cpp --- licq/plugins/qt-gui/src/userinfodlg.cpp 2007-11-25 17:37:31.000000000 +0200 +++ licq-ssbi/plugins/qt-gui/src/userinfodlg.cpp 2008-01-22 01:11:26.000000000 +0200 @@ -2358,11 +2358,7 @@ } case PictureInfo: { - ICQUser *u = gUserManager.FetchUser(m_szId, m_nPPID, LOCK_R); - if (u == NULL) return; - bool bSendServer = (u->SocketDesc(ICQ_CHNxINFO) < 0); - gUserManager.DropUser(u); - icqEventTag = server->icqRequestPicture(m_szId, bSendServer); + icqEventTag = server->ProtoRequestPicture(m_szId, m_nPPID); break; } } diff -urN licq/src/buffer.cpp licq-ssbi/src/buffer.cpp --- licq/src/buffer.cpp 2007-08-21 14:51:52.000000000 +0300 +++ licq-ssbi/src/buffer.cpp 2008-01-22 01:11:26.000000000 +0200 @@ -333,6 +333,12 @@ return sz; } +char *CBuffer::UnpackBinBlock(char *sz, unsigned short _nSize) +{ + for (unsigned short i = 0; i < _nSize; i++) *this >> sz[i]; + return sz; +} + char *CBuffer::UnpackStringBE(char* sz, unsigned short _usiSize) { unsigned short nLen; diff -urN licq/src/icqd.cpp licq-ssbi/src/icqd.cpp --- licq/src/icqd.cpp 2007-11-26 13:26:35.000000000 +0200 +++ licq-ssbi/src/icqd.cpp 2008-01-22 01:11:26.000000000 +0200 @@ -32,6 +32,7 @@ #include "licq_icq.h" #include "licq_user.h" +#include "licq_oscarservice.h" #include "licq_constants.h" #include "licq_file.h" #include "licq_log.h" @@ -270,8 +271,12 @@ m_szProxyPasswd = (char *)malloc(strlen(t_str) + 1); strcpy(m_szProxyPasswd, t_str); + // Services + m_xSSBIService = NULL; + // Misc licqConf.ReadBool("UseSS", m_bUseSS, true); // server side list + licqConf.ReadBool("UseSSBI", m_bUseSSBI, true); // server side buddy icons licqConf.ReadBool("SendTypingNotification", m_bSendTN, true); licqConf.ReadBool("ReconnectAfterUinClash", m_bReconnectAfterUinClash, false); @@ -447,10 +452,23 @@ nResult = pthread_create(&thread_updateusers, NULL, &UpdateUsers_tep, this); if (nResult != 0) { - gLog.Error("%sUnable to start ping thread:\n%s%s.\n", L_ERRORxSTR, L_BLANKxSTR, strerror(nResult)); + gLog.Error("%sUnable to start users update thread:\n%s%s.\n", L_ERRORxSTR, L_BLANKxSTR, strerror(nResult)); return false; } + if (UseServerSideBuddyIcons()) + { + m_xSSBIService = new COscarService(this, ICQ_SNACxFAM_SSBI); + nResult = pthread_create(&thread_ssbiservice, NULL, + &OscarServiceSendQueue_tep, m_xSSBIService); + if (nResult != 0) + { + gLog.Error(tr("%sUnable to start SSBI service thread:\n%s%s.\n"), + L_ERRORxSTR, L_BLANKxSTR, strerror(nResult)); + return false; + } + } + return true; } @@ -804,6 +822,7 @@ // Misc licqConf.WriteBool("UseSS", m_bUseSS); // server side list + licqConf.WriteBool("UseSSBI", m_bUseSSBI); // server side buddy icons licqConf.WriteBool("SendTypingNotification", m_bSendTN); licqConf.WriteBool("ReconnectAfterUinClash", m_bReconnectAfterUinClash); @@ -975,38 +994,46 @@ delete m_xProxy; m_xProxy = NULL; } + m_xProxy = CreateProxy(); +} + +ProxyServer *CICQDaemon::CreateProxy() +{ + ProxyServer *Proxy = NULL; switch (m_nProxyType) { case PROXY_TYPE_HTTP : - m_xProxy = new HTTPProxyServer(); + Proxy = new HTTPProxyServer(); break; default: break; } - if (m_xProxy != NULL) + if (Proxy != NULL) { gLog.Info(tr("%sResolving proxy: %s:%d...\n"), L_INITxSTR, m_szProxyHost, m_nProxyPort); - if (!m_xProxy->SetProxyAddr(m_szProxyHost, m_nProxyPort)) { + if (!Proxy->SetProxyAddr(m_szProxyHost, m_nProxyPort)) + { char buf[128]; gLog.Warn(tr("%sUnable to resolve proxy server %s:\n%s%s.\n"), L_ERRORxSTR, - m_szProxyHost, L_BLANKxSTR, m_xProxy->ErrorStr(buf, 128)); - delete m_xProxy; - m_xProxy = NULL; + m_szProxyHost, L_BLANKxSTR, Proxy->ErrorStr(buf, 128)); + delete Proxy; + Proxy = NULL; } - if (m_xProxy) + if (Proxy) { if (m_bProxyAuthEnabled) - m_xProxy->SetProxyAuth(m_szProxyLogin, m_szProxyPasswd); + Proxy->SetProxyAuth(m_szProxyLogin, m_szProxyPasswd); - m_xProxy->InitProxy(); + Proxy->InitProxy(); } } -} + return Proxy; +} unsigned short VersionToUse(unsigned short v_in) { @@ -1111,6 +1138,25 @@ m_nIgnoreTypes &= ~n; } +void CICQDaemon::SetUseServerSideBuddyIcons(bool b) +{ + if (b && m_xSSBIService == NULL) + { + m_xSSBIService = new COscarService(this, ICQ_SNACxFAM_SSBI); + int nResult = pthread_create(&thread_ssbiservice, NULL, + &OscarServiceSendQueue_tep, m_xSSBIService); + if (nResult != 0) + { + gLog.Error(tr("%sUnable to start SSBI service thread:\n%s%s.\n"), + L_ERRORxSTR, L_BLANKxSTR, strerror(nResult)); + } + else + m_bUseSSBI = true; + } + else + m_bUseSSBI = b; +} + bool CICQDaemon::AddUserToList(const char *szId, unsigned long nPPID, bool bNotify, bool bTempUser) { @@ -2029,6 +2075,13 @@ return(e); } +void CICQDaemon::PushEvent(ICQEvent *e) +{ + assert(e != NULL); + pthread_mutex_lock(&mutex_runningevents); + m_lxRunningEvents.push_back(e); + pthread_mutex_unlock(&mutex_runningevents); +} /*------------------------------------------------------------------------------ * PushExtendedEvent diff -urN licq/src/icqd-srv.cpp licq-ssbi/src/icqd-srv.cpp --- licq/src/icqd-srv.cpp 2008-01-03 16:09:23.000000000 +0200 +++ licq-ssbi/src/icqd-srv.cpp 2008-01-22 01:11:26.000000000 +0200 @@ -27,6 +27,7 @@ #include "licq_icqd.h" #include "licq_translate.h" +#include "licq_oscarservice.h" #include "licq_packets.h" #include "licq_socket.h" #include "licq_user.h" @@ -716,6 +717,43 @@ return icqRequestMetaInfo(szUin); } +//-----ProtoRequestPicture------------------------------------------------------ +unsigned long CICQDaemon::ProtoRequestPicture(const char *_szId, unsigned long _nPPID) +{ + unsigned long nRet = 0; + + if (_nPPID == LICQ_PPID) + { + ICQUser *u = gUserManager.FetchUser(_szId, LICQ_PPID, LOCK_R); + if (u == NULL) return 0; + + if (UseServerSideBuddyIcons() && strlen(u->BuddyIconHash()) > 0) + { + gUserManager.DropUser(u); + nRet = m_xSSBIService->SendEvent(_szId, ICQ_SNACxSSBI_ICONxREQUEST, true); + } + else + { + bool bSendServer = (u->SocketDesc(ICQ_CHNxINFO) < 0); + gUserManager.DropUser(u); + nRet = icqRequestPicture(_szId, bSendServer); + } + } + else + PushProtoSignal(new CRequestPicture(_szId), _nPPID); + + return nRet; +} + +//-----icqRequestService-------------------------------------------------------- +void CICQDaemon::icqRequestService(unsigned short nFam) +{ + CPU_CommonFamily *p = new CPU_RequestService(nFam); + gLog.Info(tr("%sRequesting service socket for FAM 0x%02X (#%hu/#%d)...\n"), + L_SRVxSTR, nFam, p->Sequence(), p->SubSequence()); + SendEvent_Server(p); +} + //-----icqSetStatus------------------------------------------------------------- unsigned long CICQDaemon::ProtoSetStatus(unsigned long _nPPID, unsigned short _nNewStatus) @@ -1736,6 +1774,7 @@ case MAKESNAC(ICQ_SNACxFAM_NEWUIN, ICQ_SNACxREGISTER_USER): case MAKESNAC(ICQ_SNACxFAM_LOCATION, ICQ_SNACxREQUESTxUSERxINFO): case MAKESNAC(ICQ_SNACxFAM_LOCATION, ICQ_SNACxLOC_INFOxREQ): + case MAKESNAC(ICQ_SNACxFAM_SSBI, ICQ_SNACxSSBI_ICONxREQUEST): PushPluginEvent(e); break; @@ -1876,6 +1915,16 @@ void CICQDaemon::postLogoff(int nSD, ICQEvent *cancelledEvent) { + if (m_xSSBIService) + { + if (m_xSSBIService->GetSocketDesc() != -1) + { + gSocketManager.CloseSocket(m_xSSBIService->GetSocketDesc()); + m_xSSBIService->ResetSocket(); + m_xSSBIService->ChangeStatus(STATUS_UNINITIALIZED); + m_xSSBIService->ClearQueue(); + } + } pthread_mutex_lock(&mutex_runningevents); pthread_mutex_lock(&mutex_sendqueue_server); pthread_mutex_lock(&mutex_extendedevents); @@ -2025,7 +2074,6 @@ delete s; return (-1); } - s->SetProxy(m_xProxy); } else if (m_xProxy != NULL) { @@ -2033,37 +2081,8 @@ m_xProxy = NULL; } - char ipbuf[32]; - - if (m_xProxy == NULL) - { - gLog.Info(tr("%sResolving %s port %d...\n"), L_SRVxSTR, server, port); - if (!s->SetRemoteAddr(server, port)) { - char buf[128]; - gLog.Warn(tr("%sUnable to resolve %s:\n%s%s.\n"), L_ERRORxSTR, - server, L_BLANKxSTR, s->ErrorStr(buf, 128)); - delete s; - return (-1); // no route to host (not connected) - } - gLog.Info(tr("%sICQ server found at %s:%d.\n"), L_SRVxSTR, - s->RemoteIpStr(ipbuf), s->RemotePort()); - } - else - { - // It doesn't matter if it resolves or not, the proxy should do it then - s->SetRemoteAddr(server, port); - } - - if (m_xProxy == NULL) - gLog.Info(tr("%sOpening socket to server.\n"), L_SRVxSTR); - else - gLog.Info("%sOpening socket to server via proxy.\n", L_SRVxSTR); - if (!s->OpenConnection()) + if (!s->ConnectTo(server, port, m_xProxy)) { - char buf[128]; - gLog.Warn(tr("%sUnable to connect to %s:%d:\n%s%s.\n"), L_ERRORxSTR, - s->RemoteIpStr(ipbuf), s->RemotePort(), L_BLANKxSTR, - s->ErrorStr(buf, 128)); delete s; return -1; } @@ -2215,9 +2234,15 @@ void CICQDaemon::ProcessServiceFam(CBuffer &packet, unsigned short nSubtype) { - packet.UnpackUnsignedShortBE(); // flags + unsigned short flags = packet.UnpackUnsignedShortBE(); // flags packet.UnpackUnsignedLongBE(); // sequence + if (flags & 0x8000) // version of the family that this SNAC, just ignore it + { + unsigned short len = packet.UnpackUnsignedShortBE(); + packet.incDataPosRead(len); + } + switch (nSubtype) { case ICQ_SNACxSUB_READYxSERVER: @@ -2241,6 +2266,67 @@ break; } + case ICQ_SNACxSUB_REDIRECT: + { + unsigned short nFam = 0; + + if (!packet.readTLV()) + { + gLog.Warn(tr("%sError during parsing service redirect packet!\n"), L_WARNxSTR); + break; + } + if (packet.getTLVLen(0x000D) == 2) + nFam = packet.UnpackUnsignedShortTLV(0x000D); + + gLog.Info(tr("%sRedirect for service 0x%02X received.\n"), L_SRVxSTR, nFam); + + char *szServer = packet.UnpackStringTLV(0x0005); + char *szCookie = packet.UnpackStringTLV(0x0006); + unsigned short nCookieLen = packet.getTLVLen(0x0006); + if (!szServer || !szCookie) + { + gLog.Warn(tr("%sInvalid servername (%s) or cookie (%s) in service redirect packet!\n"), + L_WARNxSTR, szServer ? szServer : "(null)", szCookie ? szCookie : "(null)"); + if (szServer) delete [] szServer; + if (szCookie) delete [] szCookie; + break; + } + + char *szPort = strchr(szServer, ':'); + unsigned short nPort; + if (szPort) + { + *szPort++ = '\0'; + nPort = atoi(szPort); + } else + { + nPort = m_nICQServerPort; + } + + switch (nFam) + { + case ICQ_SNACxFAM_SSBI: + if (m_xSSBIService) + { + m_xSSBIService->SetConnectCredential(szServer, nPort, szCookie, nCookieLen); + m_xSSBIService->ChangeStatus(STATUS_SERVICE_REQ_ACKED); + break; + } else + { + gLog.Warn(tr("%sService redirect packet for unallocated SSBI service.\n"), + L_WARNxSTR); + break; + } + default: + gLog.Warn(tr("%sService redirect packet for unhandled service 0x%02X.\n"), + L_WARNxSTR, nFam); + } + + delete [] szServer; + delete [] szCookie; + break; + } + case ICQ_SNACxSRV_ACKxIMxICQ: { // ICQOwner *o = gUserManager.FetchOwner(LICQ_PPID, LOCK_R); @@ -2842,6 +2928,41 @@ } } + if (packet.hasTLV(0x001d)) // Server-stored buddy icon information + { + CBuffer SSBI_info = packet.UnpackTLV(0x001d); + unsigned short IconType = SSBI_info.UnpackUnsignedShortBE(); + char HashType = SSBI_info.UnpackChar(); + char HashLenght = SSBI_info.UnpackChar(); + + switch (IconType) + { + case 0x01: // Simple Buddy Icon + case 0x0C: // Photo Buddy Icon + { + if (HashType == 1 && HashLenght > 0 && HashLenght <= 16) + { + char *Hash = new char[HashLenght]; + char *HashHex = new char[HashLenght*2 + 1]; + + SSBI_info.UnpackBinBlock(Hash, HashLenght); + u->SetBuddyIconHash(PrintHex(HashHex, Hash, HashLenght)); + u->SetBuddyIconType(IconType); + u->SetBuddyIconHashType(HashType); + u->SavePictureInfo(); + delete [] Hash; + delete [] HashHex; + } + break; + } + + default: // Unsupported types of SSBI + gLog.Warn(tr("%sUnsupported type 0x%02X of buddy icon for %s.\n"), + L_WARNxSTR, IconType, u->GetAlias()); + break; + } + } + // maybe use this for auto update info later u->SetClientTimestamp(nInfoTimestamp); u->SetClientInfoTimestamp(nInfoPluginTimestamp); diff -urN licq/src/icqd-tcp.cpp licq-ssbi/src/icqd-tcp.cpp --- licq/src/icqd-tcp.cpp 2007-10-10 13:36:54.000000000 +0300 +++ licq-ssbi/src/icqd-tcp.cpp 2008-01-22 01:11:26.000000000 +0200 @@ -3430,6 +3430,9 @@ { gLog.Info("%sPicture reply from %s.\n", szInfo, u->GetAlias()); packet.incDataPosRead(nEntries); // filename, don't care + unsigned long nLen = packet.UnpackUnsignedLong(); + if (nLen == 0) // do not create empty .pic files + break; char szFilename[MAX_FILENAME_LEN]; szFilename[MAX_FILENAME_LEN - 1] = '\0'; @@ -3444,7 +3447,6 @@ break; } - unsigned long nLen = packet.UnpackUnsignedLong(); char data[nLen]; for (unsigned long i = 0; i < nLen; i++) { @@ -3452,6 +3454,7 @@ } write(nFD, data, nLen); + close(nFD); u->SetEnableSave(false); u->SetPicturePresent(true); diff -urN licq/src/icqd-threads.cpp licq-ssbi/src/icqd-threads.cpp --- licq/src/icqd-threads.cpp 2007-10-10 13:36:54.000000000 +0300 +++ licq-ssbi/src/icqd-threads.cpp 2008-01-22 01:11:43.000000000 +0200 @@ -17,6 +17,7 @@ #include "licq_icqd.h" #include "licq_log.h" #include "licq_packets.h" +#include "licq_oscarservice.h" #include "licq_plugind.h" #include "licq.h" @@ -665,7 +666,7 @@ CICQDaemon *d = (CICQDaemon *)p; fd_set f; - int nSocketsAvailable, nCurrentSocket, l; + int nSocketsAvailable, nCurrentSocket, nServiceSocket, l; char buf[1024]; while (true) @@ -691,6 +692,14 @@ /*pthread_testcancel(); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);*/ + if (d->m_xSSBIService) + { + COscarService *svc = d->m_xSSBIService; + nServiceSocket = svc->GetSocketDesc(); + } + else + nServiceSocket = -1; + nCurrentSocket = 0; while (nSocketsAvailable > 0 && nCurrentSocket < l) { @@ -764,6 +773,37 @@ } } + // Message from the service sockets ----------------------------------- + else if (nCurrentSocket == nServiceSocket) + { + DEBUG_THREADS("[MonitorSockets_tep] Data on SSBI service socket.\n"); + COscarService *svc = d->m_xSSBIService; + SrvSocket *sock_svc = static_cast<SrvSocket*>(s); + if (sock_svc->Recv()) + { + CBuffer packet(sock_svc->RecvBuffer()); + sock_svc->ClearRecvBuffer(); + gSocketManager.DropSocket(sock_svc); + if (!svc->ProcessPacket(packet)) + { + gLog.Warn(tr("%sCan't process packet for service 0x%02X.\n"), + L_WARNxSTR, svc->GetFam()); + svc->ResetSocket(); + svc->ChangeStatus(STATUS_UNINITIALIZED); + gSocketManager.CloseSocket(nCurrentSocket); + } + } + else + { + gLog.Warn(tr("%sCan't receive packet for service 0x%02X.\n"), + L_WARNxSTR, svc->GetFam()); + svc->ResetSocket(); + svc->ChangeStatus(STATUS_UNINITIALIZED); + gSocketManager.DropSocket(sock_svc); + gSocketManager.CloseSocket(nCurrentSocket); + } + } + // Connection on the server port ------------------------------------- else if (nCurrentSocket == d->m_nTCPSocketDesc) { @@ -901,7 +941,11 @@ // Cancel the update users thread pthread_cancel(d->thread_updateusers); - + + // Cancel the SSBI service thread + if (d->m_xSSBIService) + pthread_cancel(d->thread_ssbiservice); + // Join our threads pthread_join(d->thread_monitorsockets, NULL); @@ -937,6 +981,7 @@ FOR_EACH_PROTO_USER_START(LICQ_PPID, LOCK_R) { bool bSent = false; + bool bSSBI = false; if (d->AutoUpdateInfo() && !pUser->UserUpdated() && pUser->ClientTimestamp() != pUser->OurClientTimestamp() @@ -946,6 +991,15 @@ bSent = true; } + if (d->UseServerSideBuddyIcons() && d->AutoUpdateInfo() && + strlen(pUser->BuddyIconHash()) > 0 && + strcmp(pUser->BuddyIconHash(), pUser->OurBuddyIconHash()) != 0) + { + d->m_xSSBIService->SendEvent(pUser->IdString(), ICQ_SNACxSSBI_ICONxREQUEST, true); + bSent = true; + bSSBI = true; + } + if (!pUser->StatusOffline() && !pUser->UserUpdated() && //Don't bother clients that we know don't support plugins pUser->Version() >= 7 && @@ -974,7 +1028,8 @@ gLog.Info("Updating %s's info plugins.\n", pUser->GetAlias()); d->icqRequestInfoPlugin(pUser, true, PLUGIN_QUERYxINFO); d->icqRequestInfoPlugin(pUser, true, PLUGIN_PHONExBOOK); - d->icqRequestInfoPlugin(pUser, true, PLUGIN_PICTURE); + if (!bSSBI) // Send only if we din't request SSBI already + d->icqRequestInfoPlugin(pUser, true, PLUGIN_PICTURE); bSent = true; } diff -urN licq/src/icqevent.cpp licq-ssbi/src/icqevent.cpp --- licq/src/icqevent.cpp 2006-11-11 21:24:53.000000000 +0200 +++ licq-ssbi/src/icqevent.cpp 2008-01-22 01:11:26.000000000 +0200 @@ -109,18 +109,32 @@ // : m_xBuffer(p.getBuffer()) { // set up internal variables - m_pPacket = p; m_bCancelled = false; m_Deleted = false; m_NoAck = false; - m_nChannel = p->Channel(); - m_nCommand = p->Command(); - m_nSNAC = p->SNAC(); - m_nSubCommand = p->SubCommand(); - m_nSequence = p->Sequence(); - m_nSubSequence = p->SubSequence(); - m_nSubType = (p->SNAC() & 0xFFFF); - m_nExtraInfo = p->ExtraInfo(); + if (p) + { + m_pPacket = p; + m_nChannel = p->Channel(); + m_nCommand = p->Command(); + m_nSNAC = p->SNAC(); + m_nSubCommand = p->SubCommand(); + m_nSequence = p->Sequence(); + m_nSubSequence = p->SubSequence(); + m_nSubType = (p->SNAC() & 0xFFFF); + m_nExtraInfo = p->ExtraInfo(); + } else + { + m_pPacket = NULL; + m_nChannel = 0; + m_nCommand = 0; + m_nSNAC = 0; + m_nSubCommand = 0; + m_nSequence = 0; + m_nSubSequence = 0; + m_nSubType = 0; + m_nExtraInfo = 0; + } m_nDestinationUin = 0; m_szId = _szId ? strdup(_szId) : 0; m_nPPID = _nPPID; @@ -200,6 +214,20 @@ } +//-----ICQEvent::AttachPacket--------------------------------------------------- +void ICQEvent::AttachPacket(CPacket *p) +{ + m_pPacket = p; + m_nChannel = p->Channel(); + m_nCommand = p->Command(); + m_nSNAC = p->SNAC(); + m_nSubCommand = p->SubCommand(); + m_nSequence = p->Sequence(); + m_nSubSequence = p->SubSequence(); + m_nSubType = (p->SNAC() & 0xFFFF); + m_nExtraInfo = p->ExtraInfo(); +} + //-----ICQEvent::CompareEvent--------------------------------------------------- bool ICQEvent::CompareEvent(int sockfd, unsigned short _nSequence) const { @@ -470,6 +498,15 @@ free(m_szZipCode); } +CRequestPicture::CRequestPicture(const char *szId) + : CSignal(PROTOxREQUESTxPICTURE, szId) +{ +} + +CRequestPicture::~CRequestPicture() +{ +} + CBlockUserSignal::CBlockUserSignal(const char *szId) : CSignal(PROTOxBLOCKxUSER, szId) { diff -urN licq/src/icqpacket.cpp licq-ssbi/src/icqpacket.cpp --- licq/src/icqpacket.cpp 2008-01-03 16:09:23.000000000 +0200 +++ licq-ssbi/src/icqpacket.cpp 2008-01-22 01:11:26.000000000 +0200 @@ -268,7 +268,8 @@ //======Server TCP============================================================ bool CSrvPacketTcp::s_bRegistered = false; -unsigned short CSrvPacketTcp::s_nSequence = 0; +unsigned short CSrvPacketTcp::s_nSequence[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned short CSrvPacketTcp::s_nSubSequence = 0; pthread_mutex_t CSrvPacketTcp::s_xMutex = PTHREAD_MUTEX_INITIALIZER; @@ -276,13 +277,14 @@ { m_nChannel = nChannel; pthread_mutex_lock(&s_xMutex); - m_nSequence = s_nSequence++; + // will set m_nSequence later, in InitBuffer; m_nSubSequence = s_nSubSequence++; pthread_mutex_unlock(&s_xMutex); m_nFamily = m_nSubType = m_nSubCommand = m_nExtraInfo = 0; buffer = NULL; m_nSize = 0; + m_nService = 0; m_szSequenceOffset = NULL; } @@ -300,6 +302,13 @@ void CSrvPacketTcp::InitBuffer() { + pthread_mutex_lock(&s_xMutex); + if (s_nSequence[m_nService] == 0xffff) + s_nSequence[m_nService] = rand() & 0x7fff; + m_nSequence = s_nSequence[m_nService]++; + s_nSequence[m_nService] &= 0x7fff; + pthread_mutex_unlock(&s_xMutex); + buffer = new CBuffer(m_nSize+6); buffer->PackChar(0x2a); buffer->PackChar(m_nChannel); @@ -686,9 +695,8 @@ m_nSize = 4; pthread_mutex_lock(&s_xMutex); - s_nSequence = rand() & 0x7fff; + s_nSequence[m_nService] = 0xffff; s_bRegistered = true; - m_nSequence = s_nSequence++; pthread_mutex_unlock(&s_xMutex); InitBuffer(); @@ -792,9 +800,8 @@ pthread_mutex_lock(&s_xMutex); if (!s_bRegistered) { - s_nSequence = rand() & 0x7fff; + s_nSequence[m_nService] = 0xffff; s_bRegistered = true; - m_nSequence = s_nSequence++; } pthread_mutex_unlock(&s_xMutex); @@ -847,13 +854,14 @@ } //-----SendCookie------------------------------------------------------------ -CPU_SendCookie::CPU_SendCookie(const char *szCookie, int nLen) +CPU_SendCookie::CPU_SendCookie(const char *szCookie, int nLen, + unsigned short nService) : CSrvPacketTcp(ICQ_CHNxNEW) { + m_nService = nService; m_nSize = nLen + 8; pthread_mutex_lock(&s_xMutex); - s_nSequence = (rand() & 0x7fff); - m_nSequence = s_nSequence++; + s_nSequence[m_nService] = 0xffff; pthread_mutex_unlock(&s_xMutex); InitBuffer(); @@ -887,7 +895,22 @@ buffer->PackUnsignedLongBE(0x000b0001); } -//-----ImICQ----------------------------------------------------------------- +CPU_ImICQ::CPU_ImICQ(unsigned short VerArray[][2], unsigned short NumVer, + unsigned short nService) + : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSRV_IMxICQ) +{ + m_nService = nService; + m_nSize += NumVer * 4; + InitBuffer(); + + for (int i = 0; i < NumVer; i++) + { + buffer->PackUnsignedShortBE(VerArray[i][0]); + buffer->PackUnsignedShortBE(VerArray[i][1]); + } +} + +//-----ImICQMode------------------------------------------------------------- CPU_ICQMode::CPU_ICQMode(unsigned short channel, unsigned long flags) : CPU_CommonFamily(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SETxICQxMODE) { @@ -907,9 +930,10 @@ } //-----RateAck----------------------------------------------------------------- -CPU_RateAck::CPU_RateAck() +CPU_RateAck::CPU_RateAck(unsigned short nService) : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSND_RATE_ACK) { + m_nService = nService; m_nSize += 10; InitBuffer(); @@ -923,7 +947,7 @@ CPU_CapabilitySettings::CPU_CapabilitySettings() : CPU_CommonFamily(ICQ_SNACxFAM_LOCATION, ICQ_SNACxLOC_SETxUSERxINFO) { - char data[7][CAP_LENGTH]; + char data[8][CAP_LENGTH]; m_nSize += 4 + sizeof(data); InitBuffer(); @@ -934,6 +958,7 @@ memcpy(data[4], ICQ_CAPABILITY_AIMxINTER, CAP_LENGTH); memcpy(data[5], ICQ_CAPABILITY_RTFxMSGS, CAP_LENGTH); memcpy(data[6], ICQ_CAPABILITY_ICHAT, CAP_LENGTH); + memcpy(data[7], ICQ_CAPABILITY_SSBI, CAP_LENGTH); // Send our licq version data[3][12] = INT_VERSION / 1000; @@ -946,6 +971,40 @@ buffer->PackTLV(0x05, sizeof(data), (char *)data); } +//-----RequestBuddyIcon--------------------------------------------------------- +CPU_RequestBuddyIcon::CPU_RequestBuddyIcon(const char *_szId, + unsigned short _nBuddyIconType, char _nBuddyIconHashType, + const char *_szBuddyIconHash, unsigned short nService) + : CPU_CommonFamily(ICQ_SNACxFAM_SSBI, ICQ_SNACxSSBI_ICONxREQUEST) +{ + int nSize = strlen(_szId); + int nHashLenght = strlen(_szBuddyIconHash)/2; + char *Hash = new char[nHashLenght]; + m_nService = nService; + m_nSize += 6 + nSize + nHashLenght; + + InitBuffer(); + + buffer->PackChar(nSize); + buffer->Pack(_szId, nSize); + buffer->PackChar(0x01); // unknown, probably type of request + buffer->PackUnsignedShortBE(_nBuddyIconType); + buffer->PackChar(_nBuddyIconHashType); + buffer->PackChar(nHashLenght); + buffer->Pack(ReadHex(Hash, _szBuddyIconHash, nHashLenght), nHashLenght); +} + +//-----RequestService----------------------------------------------------------- +CPU_RequestService::CPU_RequestService(unsigned short nFam) + : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSUB_NEW_SERVICE) +{ + m_nSize += 2; + + InitBuffer(); + + buffer->PackUnsignedShortBE(nFam); +} + //-----SetPrivacy--------------------------------------------------------------- CPU_SetPrivacy::CPU_SetPrivacy(unsigned char _cPrivacy) : CPU_CommonFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxUPD_GROUP) @@ -1190,9 +1249,11 @@ buffer->Pack(uin, n); } -CPU_GenericFamily::CPU_GenericFamily(unsigned short Family, unsigned short SubType) +CPU_GenericFamily::CPU_GenericFamily(unsigned short Family, unsigned short SubType, + unsigned short nService) : CPU_CommonFamily(Family, SubType) { + m_nService = nService; m_nSize += 0; InitBuffer(); } @@ -1284,6 +1345,23 @@ #endif } +CPU_ClientReady::CPU_ClientReady(unsigned short VerArray[][4], unsigned short NumVer, + unsigned short nService) + : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSUB_READYxCLIENT) +{ + m_nService = nService; + m_nSize += NumVer * 8; + InitBuffer(); + + for (int i = 0; i < NumVer; i++) + { + buffer->PackUnsignedShortBE(VerArray[i][0]); + buffer->PackUnsignedShortBE(VerArray[i][1]); + buffer->PackUnsignedShortBE(VerArray[i][2]); + buffer->PackUnsignedShortBE(VerArray[i][3]); + } +} + CPU_AckNameInfo::CPU_AckNameInfo() : CPU_CommonFamily(ICQ_SNACxFAM_SERVICE, ICQ_SNACxSND_NAMExINFOxACK) { diff -urN licq/src/Makefile.am licq-ssbi/src/Makefile.am --- licq/src/Makefile.am 2006-11-11 21:24:53.000000000 +0200 +++ licq-ssbi/src/Makefile.am 2008-01-22 01:11:26.000000000 +0200 @@ -11,7 +11,7 @@ bin_PROGRAMS = licq licq_SOURCES = licq.cpp main.cpp \ icqpacket.cpp proxy.cpp socket.cpp icqd.cpp \ - icqd-tcp.cpp icqd-srv.cpp icqd-threads.cpp \ + icqd-tcp.cpp icqd-srv.cpp icqd-threads.cpp oscarservice.cpp \ icqevent.cpp buffer.cpp user.cpp history.cpp \ utility.cpp countrycodes.c log.cpp translate.cpp \ file.cpp message.cpp support.c pthread_rdwr.c \ diff -urN licq/src/oscarservice.cpp licq-ssbi/src/oscarservice.cpp --- licq/src/oscarservice.cpp 1970-01-01 03:00:00.000000000 +0300 +++ licq-ssbi/src/oscarservice.cpp 2008-01-22 01:11:46.000000000 +0200 @@ -0,0 +1,660 @@ +// -*- c-basic-offset: 2 -*- +/* ---------------------------------------------------------------------------- + * Licq - A ICQ Client for Unix + * Copyright (C) 2007 Licq developers + * + * This program is licensed under the terms found in the LICENSE file. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include <cstdlib> +#include <cstdio> + +// Localization +#include "gettext.h" + +#include "licq_oscarservice.h" +#include "licq_icqd.h" +#include "licq_events.h" +#include "licq_socket.h" +#include "licq_proxy.h" +#include "licq_packets.h" +#include "licq_buffer.h" +#include "licq_log.h" +#include "support.h" + +COscarService::COscarService(CICQDaemon *Daemon, unsigned short Fam) +{ + myDaemon = Daemon; + myFam = Fam; + mySocketDesc = -1; + myProxy = NULL; + myStatus = STATUS_UNINITIALIZED; + myServer = NULL; + myCookie = NULL; + pthread_mutex_init(&mutex_sendqueue, NULL); + pthread_cond_init(&cond_sendqueue, NULL); + pthread_mutex_init(&mutex_status, NULL); + pthread_cond_init(&cond_status, NULL); +} + +COscarService::~COscarService() +{ + if (myProxy) delete myProxy; + if (myServer) free(myServer); + if (myCookie) delete [] myCookie; +} + +void COscarService::ChangeStatus(EOscarServiceStatus s) +{ + pthread_mutex_lock(&mutex_status); + myStatus = s; + pthread_cond_signal(&cond_status); + pthread_mutex_unlock(&mutex_status); +} + +bool COscarService::WaitForStatus(EOscarServiceStatus s) +{ + pthread_mutex_lock(&mutex_status); + + struct timespec ts; + ts.tv_nsec = 0; + //wait for 120 seconds + ts.tv_sec = time(NULL) + 120; + + if (pthread_cond_timedwait(&cond_status, &mutex_status, &ts) == ETIMEDOUT) + { + pthread_mutex_unlock(&mutex_status); + return false; + } + if (myStatus == s) + { + pthread_mutex_unlock(&mutex_status); + return true; + } + + pthread_mutex_unlock(&mutex_status); + return false; +} + +void COscarService::SetConnectCredential(char *Server, unsigned short Port, + char *Cookie, unsigned short CookieLen) +{ + if (myServer) free(myServer); + myServer = strdup(Server); + myPort = Port; + if (myCookie) delete [] myCookie; + myCookie = new char[CookieLen]; + memcpy(myCookie, Cookie, CookieLen); + myCookieLen = CookieLen; +} + +bool COscarService::SendPacket(CPacket *p) +{ + INetSocket *s = gSocketManager.FetchSocket(mySocketDesc); + if (s == NULL) return false; + CBuffer *b = p->Finalize(s); + if (!s->Send(b)) + { + char ErrorBuf[128]; + s->ErrorStr(ErrorBuf, 128); + gLog.Warn(tr("%sError sending event (FAM #%02X, Subtype #%02X, Sequence #%hu):\n%s%s.\n"), + L_WARNxSTR, (unsigned short)((p->SNAC() >> 16) & 0xffff), (unsigned short)(p->SNAC() & 0xffff), + p->Sequence(), L_BLANKxSTR, ErrorBuf); + gSocketManager.DropSocket(s); + delete b; + return false; + } + gSocketManager.DropSocket(s); + delete b; + return true; +} + +void COscarService::ClearQueue() +{ + pthread_mutex_lock(&mutex_sendqueue); + std::list<ICQEvent *>::iterator iter; + unsigned long i = mySendQueue.size(); + for (iter = mySendQueue.begin(); i > 0; i--) + { + ICQEvent *e = *iter; + mySendQueue.erase(iter); + if (e != NULL) + { + gLog.Info("Event #%hu is still on the service 0x%02X queue!\n", e->Sequence(), myFam); + delete e; + } + } + pthread_mutex_unlock(&mutex_sendqueue); +} + +unsigned long COscarService::SendEvent(const char *Id, + unsigned short SubType, bool Request) +{ + ICQEvent *e = new ICQEvent(myDaemon, mySocketDesc, NULL, CONNECT_SERVER, + Id, LICQ_PPID, NULL); + e->SetSubType(SubType); + if (Request) + myDaemon->PushEvent(e); + else + e->SetNoAck(true); + pthread_mutex_lock(&mutex_sendqueue); + mySendQueue.push_back(e); + pthread_cond_signal(&cond_sendqueue); + pthread_mutex_unlock(&mutex_sendqueue); + + return e->EventId(); +} + +bool COscarService::SendSSBIFam(ICQEvent *e) +{ + switch (e->SubType()) + { + case ICQ_SNACxSSBI_ICONxREQUEST: + { + ICQUser *u = gUserManager.FetchUser(e->Id(), LICQ_PPID, LOCK_R); + CPU_RequestBuddyIcon *p = new CPU_RequestBuddyIcon(e->Id(), u->BuddyIconType(), + u->BuddyIconHashType(), u->BuddyIconHash(), myFam); + gLog.Info(tr("%sRequesting buddy icon for %s (#%hu/#%d)...\n"), + L_SRVxSTR, u->GetAlias(), p->Sequence(), p->SubSequence()); + gUserManager.DropUser(u); + e->AttachPacket(p); + return (SendPacket(p)); + } + + default: + gLog.Warn(tr("%sEvent with unsupported subtype (%02X) for FAM %02X failed.\n"), + L_WARNxSTR, e->SubType(), myFam); + return false; + } + + return false; +} + +bool COscarService::ProcessPacket(CBuffer &packet) +{ + unsigned short Len; + unsigned short Sequence; + char startCode, Channel; + + // read in the serveice header info + packet >> startCode; + + if (startCode != 0x2a) + { + gLog.Warn(tr("%sbad start code %d for packet in socket of service 0x%02X.\n"), + L_WARNxSTR, startCode, myFam); + return false; + } + + packet >> Channel + >> Sequence + >> Len; + + rev_e_short(Sequence); + rev_e_short(Len); + + switch (Channel) + { + case ICQ_CHNxNEW: + ProcessNewChannel(packet); + break; + + case ICQ_CHNxDATA: + ProcessDataChannel(packet); + break; + + case ICQ_CHNxCLOSE: + gLog.Info(tr("%sServer send us request for close service 0x%02X.\n"), + L_SRVxSTR, myFam); + return false; + break; + + default: + gLog.Warn(tr("%sPacket from unhandled channel %02x for service 0x%02X.\n"), + L_WARNxSTR, Channel, myFam); + break; + } + + return true; +} + +void COscarService::ProcessNewChannel(CBuffer &packet) +{ + unsigned long Version = packet.UnpackUnsignedLongBE(); + + if (Version != 0x00000001) + { + gLog.Warn(tr("%sPacket with wrong version (0x%08lx) from new channel for service 0x%02X.\n"), + L_WARNxSTR, Version, myFam); + } +} + +void COscarService::ProcessDataChannel(CBuffer &packet) +{ + unsigned short Family, SubType, Flags; + unsigned long RequestId; + + packet >> Family >> SubType >> Flags >> RequestId; + rev_e_short(Family); + rev_e_short(SubType); + rev_e_short(Flags); + rev_e_long(RequestId); + + if (Flags & 0x8000) // version of the family that this SNAC, just ignore it + { + unsigned short len = packet.UnpackUnsignedShortBE(); + packet.incDataPosRead(len); + } + + switch (Family) + { + case ICQ_SNACxFAM_SERVICE: + ProcessServiceFam(packet, SubType, RequestId); + break; + + case ICQ_SNACxFAM_SSBI: + if (myFam == ICQ_SNACxFAM_SSBI) + ProcessSSBIFam(packet, SubType, RequestId); + else + gLog.Warn(tr("%sUsupported family %04hx\n on data channel of service %02X.\n"), + L_WARNxSTR, Family, myFam); + break; + + default: + gLog.Warn(tr("%sUnknown or usupported family %04hx\n on data channel of service %02X.\n"), + L_WARNxSTR, Family, myFam); + break; + } +} + +void COscarService::ProcessServiceFam(CBuffer &packet, unsigned short SubType, + unsigned long RequestId) +{ + switch (SubType) + { + case ICQ_SNACxSUB_ERROR: + { + unsigned short err = packet.UnpackUnsignedShortBE(); + unsigned short suberr = 0; + + packet.readTLV(); + if (packet.getTLVLen(0x0008) == 2) + suberr = packet.UnpackUnsignedShortTLV(0x0008); + gLog.Warn(tr("%sError #%02x.%02x in control FAM request (%ld) for service 0x%02X.\n"), + L_WARNxSTR, err, suberr, RequestId, myFam); + break; + } + + case ICQ_SNACxSUB_READYxSERVER: + gLog.Info(tr("%sServer says he's ready for service 0x%02X.\n"), + L_SRVxSTR, myFam); + ChangeStatus(STATUS_SRV_READY_RECV); + break; + + case ICQ_SNACxSRV_ACKxIMxICQ: + gLog.Info(tr("%sServer sent us channel capability list for service 0x%02X.\n"), + L_SRVxSTR, myFam); + ChangeStatus(STATUS_SRV_VER_RECV); + break; + + case ICQ_SNACxSUB_RATE_INFO: + gLog.Info(tr("%sServer sent us rate-limits information for service 0x%02X.\n"), + L_SRVxSTR, myFam); + ChangeStatus(STATUS_SRV_RATE_RECV); + break; + + default: + gLog.Warn(tr("%sUnknown or unsupported service FAM subtype 0x%02X for service 0x%02X.\n"), + L_WARNxSTR, SubType, myFam); + break; + } +} + +void COscarService::ProcessSSBIFam(CBuffer &packet, unsigned short SubType, + unsigned long RequestId) +{ + switch (SubType) + { + case ICQ_SNACxSSBI_ERROR: + { + unsigned short err = packet.UnpackUnsignedShortBE(); + unsigned short suberr = 0; + + packet.readTLV(); + if (packet.getTLVLen(0x0008) == 2) + suberr = packet.UnpackUnsignedShortTLV(0x0008); + gLog.Warn(tr("%sError #%02x.%02x in SSBI request (%ld) for service 0x%02X.\n"), + L_WARNxSTR, err, suberr, RequestId, myFam); + + ICQEvent *e = myDaemon->DoneServerEvent(RequestId, EVENT_ERROR); + if (e) + myDaemon->ProcessDoneEvent(e); + break; + } + + case ICQ_SNACxSSBI_ICONxREPLY: + { + char *Id = packet.UnpackUserString(); + ICQUser *u = gUserManager.FetchUser(Id, LICQ_PPID, LOCK_W); + if (u == NULL) + { + gLog.Warn(tr("%sBuddy icon for unknown user (%s).\n"), + L_WARNxSTR, Id); + delete [] Id; + break; + } + delete [] Id; + + unsigned short IconType = packet.UnpackUnsignedShortBE(); + char HashType = packet.UnpackChar(); + char HashLenght = packet.UnpackChar(); + switch (IconType) + { + case 0x01: // Simple Buddy Icon + case 0x0C: // Photo Buddy Icon + if (HashType == 1 && HashLenght > 0 && HashLenght <= 16) + { + char *Hash = new char[HashLenght]; + char *HashHex = new char[HashLenght*2 + 1]; + packet.UnpackBinBlock(Hash, HashLenght); + packet.UnpackChar(); // unknown (command ?) + packet.UnpackUnsignedShortBE(); // IconType once more + packet.UnpackChar(); // HashType once more + char HashLenght2 = packet.UnpackChar(); // HashLenght once more + packet.incDataPosRead(HashLenght2); // Hash once more + u->SetOurBuddyIconHash(PrintHex(HashHex, Hash, HashLenght)); + delete [] Hash; + delete [] HashHex; + + gLog.Info(tr("%sBuddy icon reply for %s.\n"), L_SRVxSTR, u->GetAlias()); + unsigned short IconLen = packet.UnpackUnsignedShortBE(); + if (IconLen > 0) // do not create empty .pic files + { + char Filename[MAX_FILENAME_LEN]; + Filename[MAX_FILENAME_LEN - 1] = '\0'; + snprintf(Filename, MAX_FILENAME_LEN - 1, "%s/%s/%lu.pic", + BASE_DIR, USER_DIR, u->Uin()); + int FD = open(Filename, O_WRONLY | O_CREAT | O_TRUNC, 00664); + if (FD == -1) + { + gLog.Error(tr("%sUnable to open picture file (%s):\n%s%s.\n"), + L_ERRORxSTR, Filename, L_BLANKxSTR, strerror(errno)); + break; + } + + char *Icon = new char[IconLen]; + packet.UnpackBinBlock(Icon, IconLen); + write(FD, Icon, IconLen); + close(FD); + delete [] Icon; + + u->SetEnableSave(false); + u->SetPicturePresent(true); + u->SetEnableSave(true); + } + u->SavePictureInfo(); + myDaemon->PushPluginSignal(new CICQSignal(SIGNAL_UPDATExUSER, USER_PICTURE, + u->IdString(), u->PPID())); + + ICQEvent *e = myDaemon->DoneServerEvent(RequestId, EVENT_SUCCESS); + if (e) + myDaemon->ProcessDoneEvent(e); + } + else + { + gLog.Warn(tr("%sBuddy icon reply for %s with wrong or unsupported hashtype (%d) or hashlenght (%d).\n"), + L_WARNxSTR, u->GetAlias(), HashType, HashLenght); + ICQEvent *e = myDaemon->DoneServerEvent(RequestId, EVENT_FAILED); + if (e) + myDaemon->ProcessDoneEvent(e); + } + break; + + default: + gLog.Warn(tr("%sBuddy icon reply for %s with wrong or unsupported icontype (0x%02x).\n"), + L_WARNxSTR, u->GetAlias(), IconType); + ICQEvent *e = myDaemon->DoneServerEvent(RequestId, EVENT_FAILED); + if (e) + myDaemon->ProcessDoneEvent(e); + break; + } + gUserManager.DropUser(u); + break; + } + + default: + break; + } +} + +bool COscarService::Initialize() +{ + ChangeStatus(STATUS_SERVICE_REQ_SENT); + myDaemon->icqRequestService(myFam); + + if (!WaitForStatus(STATUS_SERVICE_REQ_ACKED)) + { + gLog.Warn(tr("%sGive up waiting for redirect reply while initializing service 0x%02X.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + + ChangeStatus(STATUS_CONNECTED); + SrvSocket *s = new SrvSocket(gUserManager.OwnerUin()); + gLog.Info(tr("%sConnecting to separate server for service 0x%02X.\n"), + L_SRVxSTR, myFam); + if (myDaemon->GetProxy() == NULL) + { + if (myProxy != NULL) + { + delete myProxy; + myProxy = NULL; + } + } + else + { + if (myProxy == NULL) + myProxy = myDaemon->CreateProxy(); + } + if (!s->ConnectTo(myServer, myPort, myProxy)) + { + gLog.Warn(tr("%sCan't establish service 0x%02X socket.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + mySocketDesc = s->Descriptor(); + gSocketManager.AddSocket(s); + gSocketManager.DropSocket(s); + // Alert the select thread that there is a new socket + write(myDaemon->pipe_newsocket[PIPE_WRITE], "S", 1); + + CPU_SendCookie *p1 = new CPU_SendCookie(myCookie, myCookieLen, myFam); + gLog.Info(tr("%sSending cookie for service 0x%02X.\n"), + L_SRVxSTR, myFam); + if (!SendPacket(p1)) + { + gLog.Warn(tr("%sCan't send cookie while initializing service 0x%02X.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + + if (!WaitForStatus(STATUS_SRV_READY_RECV)) + { + gLog.Warn(tr("%sGive up waiting for server ready packet while initializing service 0x%02X.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + + unsigned short VerArray[2][2] = {{ 0x0001, 0x0004 }, // Service FAM + { 0x0010, 0x0001 }}; // SSBI FAM + CPU_ImICQ *p2 = new CPU_ImICQ(VerArray, 2, myFam); + gLog.Info(tr("%sSending our families versions for service 0x%02X.\n"), + L_SRVxSTR, myFam); + if (!SendPacket(p2)) + { + gLog.Warn(tr("%sCan't send channel capability request while initializing service 0x%02X.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + + if (!WaitForStatus(STATUS_SRV_VER_RECV)) + { + gLog.Warn(tr("%sGive up waiting for channel capability list while initializing service 0x%02X.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + + CPU_GenericFamily *p3 = new CPU_GenericFamily(ICQ_SNACxFAM_SERVICE, + ICQ_SNACxSUB_REQ_RATE_INFO, myFam); + gLog.Info(tr("%sSending request of rate-limits for service 0x%02X.\n"), + L_SRVxSTR, myFam); + if (!SendPacket(p3)) + { + gLog.Warn(tr("%sCan't send request for rate-limits while initializing service 0x%02X.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + + if (!WaitForStatus(STATUS_SRV_RATE_RECV)) + { + gLog.Warn(tr("%sGive up waiting for rate-limits while initializing service 0x%02X.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + + CPU_RateAck *p4 = new CPU_RateAck(myFam); + gLog.Info(tr("%sSending ack for rate-limits for service 0x%02X.\n"), + L_SRVxSTR, myFam); + if (!SendPacket(p4)) + { + gLog.Warn(tr("%sCan't send rate-limits ack while initializing service 0x%02X.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + unsigned short VerArray2[2][4] = {{ 0x0001, 0x0004, 0x0110, 0x08e4 }, // Service FAM + { 0x0010, 0x0001, 0x0110, 0x08e4 }}; // SSBI FAM + CPU_ClientReady *p5 = new CPU_ClientReady(VerArray2, 2, myFam); + gLog.Info(tr("%sSending client ready for service 0x%02X.\n"), + L_SRVxSTR, myFam); + if (!SendPacket(p5)) + { + gLog.Warn(tr("%sCan't send client ready while initializing service 0x%02X.\n"), + L_WARNxSTR, myFam); + ChangeStatus(STATUS_UNINITIALIZED); + return false; + } + + ChangeStatus(STATUS_READY); + return true; +} + +void *OscarServiceSendQueue_tep(void *p) +{ + pthread_detach(pthread_self()); + + COscarService *os = (COscarService *)p; + CICQDaemon *d = os->myDaemon; + + while (true) + { + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + pthread_mutex_lock(&os->mutex_sendqueue); + if (!os->mySendQueue.empty()) + { + std::list<ICQEvent *>::iterator iter = os->mySendQueue.begin(); + ICQEvent *e = *iter; + os->mySendQueue.erase(iter); + pthread_mutex_unlock(&os->mutex_sendqueue); + + if (e->IsCancelled()) + { + delete e; + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); + continue; + } + + if (d->Status() != STATUS_ONLINE) + { + gLog.Warn(tr("%sCan't send event for service 0x%02X because we are not online.\n"), + L_WARNxSTR, os->myFam); + if (d->DoneEvent(e, EVENT_ERROR) != NULL) + d->ProcessDoneEvent(e); + else + delete e; + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); + continue; + } + + if (os->mySocketDesc == -1) + { + gLog.Info(tr("%sInitializing socket for service 0x%02X.\n"), L_SRVxSTR, os->myFam); + if (!os->Initialize()) + { + gLog.Warn(tr("%sInitialization of socket for service 0x%02X failed, failing event\n"), + L_WARNxSTR, os->myFam); + if (d->DoneEvent(e, EVENT_ERROR) != NULL) + d->ProcessDoneEvent(e); + else + delete e; + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); + continue; + } + } + + bool Sent; + switch (os->myFam) + { + case ICQ_SNACxFAM_SSBI: + Sent = os->SendSSBIFam(e); + break; + + default: + gLog.Warn(tr("%sEvent for unknown or unsupported service 0x%02X failed.\n"), + L_WARNxSTR, os->myFam); + Sent = false; + break; + } + + if (!Sent) + { + if (d->DoneEvent(e, EVENT_ERROR) != NULL) + d->ProcessDoneEvent(e); + else + delete e; + } + + if (e->NoAck()) + delete e; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); + continue; + } + else + { + pthread_cond_wait(&os->cond_sendqueue, &os->mutex_sendqueue); + pthread_mutex_unlock(&os->mutex_sendqueue); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); + } + } + + pthread_exit(NULL); +} diff -urN licq/src/socket.cpp licq-ssbi/src/socket.cpp --- licq/src/socket.cpp 2007-10-22 16:20:56.000000000 +0300 +++ licq-ssbi/src/socket.cpp 2008-01-22 01:11:26.000000000 +0200 @@ -781,6 +781,50 @@ return (true); } +/*-----SrvSocket::ConnectTo-------------------------------------------------- +* Establish connection to server (through proxy or not) +*---------------------------------------------------------------------------*/ +bool SrvSocket::ConnectTo(const char* server, unsigned short port, + ProxyServer *xProxy) +{ + char ipbuf[32]; + + if (xProxy == NULL) + { + gLog.Info(tr("%sResolving %s port %d...\n"), L_SRVxSTR, server, port); + if (!SetRemoteAddr(server, port)) { + char buf[128]; + gLog.Warn(tr("%sUnable to resolve %s:\n%s%s.\n"), L_ERRORxSTR, + server, L_BLANKxSTR, ErrorStr(buf, 128)); + return false; + } + gLog.Info(tr("%sICQ server found at %s:%d.\n"), L_SRVxSTR, + RemoteIpStr(ipbuf), RemotePort()); + } + else + { + // It doesn't matter if it resolves or not, the proxy should do it then + SetProxy(xProxy); + SetRemoteAddr(server, port); + } + + if (xProxy == NULL) + gLog.Info(tr("%sOpening socket to server.\n"), L_SRVxSTR); + else + gLog.Info(tr("%sOpening socket to server %s:%d via proxy.\n"), + L_SRVxSTR, server, port); + if (!OpenConnection()) + { + char buf[128]; + gLog.Warn(tr("%sUnable to connect to %s:%d:\n%s%s.\n"), L_ERRORxSTR, + RemoteIpStr(ipbuf), RemotePort(), L_BLANKxSTR, + ErrorStr(buf, 128)); + return false; + } + + return true; +} + //=====TCPSocket=============================================================== TCPSocket::TCPSocket(unsigned long _nOwner) : INetSocket(_nOwner) { diff -urN licq/src/support.c licq-ssbi/src/support.c --- licq/src/support.c 2006-08-10 21:17:45.000000000 +0300 +++ licq-ssbi/src/support.c 2008-01-22 01:11:26.000000000 +0200 @@ -112,6 +112,62 @@ return (nRet == -1) ? _nSize - 1 : nRet; } +char *PrintHex(char *szPrint, const char *szHex, size_t nSize) +{ + int i, j = 0; + + for(i = 0; i < nSize ; i++) + { + unsigned char byte = (unsigned char)szHex[i]; + + unsigned char high = (byte >> 4) & 0x0f; + unsigned char low = byte & 0x0f; + + if (high > 9) + szPrint[j++] = 'A' + (high - 10); + else + szPrint[j++] = '0' + high; + + if (low > 9) + szPrint[j++] = 'A' + (low - 10); + else + szPrint[j++] = '0' + low; + } + szPrint[j] = '\0'; + + return szPrint; +} + +char *ReadHex(char *szHex, const char *szRead, size_t nSize) +{ + int i, j = 0; + for(i = 0; i < nSize ; i++) + { + unsigned char digit, high, low; + + if (szRead[j] == '\0') break; + digit = (unsigned char)szRead[j++]; + high = 0; + if (digit >= 'A') + high = digit - 'A' + 10; + else if (digit >= '0') + high = digit - '0'; + high <<= 4; + + if (szRead[j] == '\0') break; + digit = (unsigned char)szRead[j++]; + low = 0; + if (digit >= 'A') + low = digit - 'A' + 10; + else if (digit >= '0') + low = digit - '0'; + + szHex[i] = high + low; + } + + return szHex; +} + int Redirect(const char *_szFile) { int fd = open(_szFile, O_WRONLY | O_CREAT | O_APPEND, 00660); diff -urN licq/src/support.h licq-ssbi/src/support.h --- licq/src/support.h 2006-08-10 21:17:45.000000000 +0300 +++ licq-ssbi/src/support.h 2008-01-22 01:11:26.000000000 +0200 @@ -34,6 +34,9 @@ int UinString(char *_szBuf, size_t _nSize, unsigned long _nUin); +char *PrintHex(char *szPrint, const char *szHex, size_t nSize); +char *ReadHex(char *szHex, const char *szRead, size_t nSize); + int Redirect(const char *); int strlen_safe(const char *); diff -urN licq/src/user.cpp licq-ssbi/src/user.cpp --- licq/src/user.cpp 2007-11-25 17:37:21.000000000 +0200 +++ licq-ssbi/src/user.cpp 2008-01-22 01:11:30.000000000 +0200 @@ -2011,8 +2011,15 @@ //-----ICQUser::LoadPictureInfo---------------------------------------------- void ICQUser::LoadPictureInfo() { + char szTemp[MAX_LINE_LEN]; m_fConf.SetSection("user"); m_fConf.ReadBool("PicturePresent", m_bPicturePresent, false); + m_fConf.ReadNum("BuddyIconType", m_nBuddyIconType, 0); + m_fConf.ReadNum("BuddyIconHashType", m_nBuddyIconHashType, 0); + m_fConf.ReadStr("BuddyIconHash", szTemp, ""); + SetString(&m_szBuddyIconHash, szTemp ); + m_fConf.ReadStr("OurBuddyIconHash", szTemp, ""); + SetString(&m_szOurBuddyIconHash, szTemp ); } //-----ICQUser::LoadLicqInfo------------------------------------------------- @@ -2333,6 +2340,10 @@ // Picture m_bPicturePresent = false; + m_nBuddyIconType = 0; + m_nBuddyIconHashType = 0; + m_szBuddyIconHash = strdup(""); + m_szOurBuddyIconHash = strdup(""); // GPG key m_szGPGKey = strdup(""); @@ -3513,6 +3524,10 @@ } m_fConf.SetSection("user"); m_fConf.WriteBool("PicturePresent", m_bPicturePresent); + m_fConf.WriteNum("BuddyIconType", m_nBuddyIconType); + m_fConf.WriteNum("BuddyIconHashType", m_nBuddyIconHashType); + m_fConf.WriteStr("BuddyIconHash", m_szBuddyIconHash); + m_fConf.WriteStr("OurBuddyIconHash", m_szOurBuddyIconHash); if (!m_fConf.FlushFile()) { gLog.Error("%sError opening '%s' for writing.\n%sSee log for details.\n",
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor