Kaidul

XmppCommCtrl.cpp

Nov 18th, 2014
278
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 91.75 KB | None | 0 0
  1. // XmppCommCtrl.cpp : Implementation of CXmppCommCtrl
  2.  
  3. #include "stdafx.h"
  4. #include <sstream>
  5. #include "PAL.h"
  6. #include "PALcritsec.h"
  7. #include "PALthread.h"
  8. #include "Event.h"
  9.  
  10. #if defined(WIN32) && !(defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  11. #include <atlapp.h>
  12. #include <atldlgs.h>
  13. #include "EComUtil.h"
  14. #include "EFileUtil.h"
  15. #include "registry.h"
  16. #else
  17. #ifndef NO_FILE_TRANSFER
  18. #include "FileUtilities.h"
  19. using namespace FileUtilities;
  20. #endif
  21. #endif
  22.  
  23. #if defined(__unix__) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  24. #include "XmppCommCtrl_unix.h"
  25. #else
  26. #ifndef _WIN32_WCE
  27. #include "XmppComm_win.h"
  28. #else
  29. #include "XmppCommCE.h"
  30. #endif
  31. #include "XmppCommCtrl.h"
  32. #endif
  33. #include "TextUtil.h"
  34. #if !(defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  35. #include "PALinet.h"
  36. #endif
  37. #include "JabberUtil.h"
  38. #include "JabberBuddy.h"
  39. #include "JabberRoster.h"
  40. #include "JabberPresence.h"
  41. #include "JabberMessage.h"
  42. #include "JabberParser.h"
  43. #ifdef _COMCAST
  44. #include "JabberPrivacy2.h"
  45. #else
  46. #include "JabberPrivacy.h"
  47. #endif
  48. #include "JabberIQ.h"
  49. #include "JabberAuth.h"
  50. #include "PALsystime.h"
  51. #include "sha.h"
  52.  
  53. #ifdef USE_NSSTREAM_FOR_XMPP
  54. #include "NSsocket.h"
  55. #endif
  56. #include "AnyFirewallEngine_dll.h"
  57.  
  58. #include "common.h"
  59. #include <openssl/bio.h>
  60. #include <openssl/x509.h>
  61. #include <openssl/x509_vfy.h>
  62. #include <openssl/pem.h>
  63. #include <openssl/x509v3.h>
  64.  
  65. using std::string;
  66. #ifndef __unix__
  67. using namespace eyeball;
  68. #endif
  69. using namespace JabberUtil;
  70.  
  71.  
  72. #define CHECK_POINTER(X) \
  73.     if (NULL == (X))\
  74.         return ThrowError("NULL pointer.");
  75.  
  76. #define CHECK_LOGIN() \
  77.     if (m_pJabberStream->m_StreamState != JABBER_STREAM_CONNECTED) \
  78.         return ThrowError("ERROR: Not logged in to XMPP.");
  79.  
  80. #define CHECK_NOT_LOGGEDIN() \
  81.     if (m_pJabberStream->m_StreamState != JABBER_STREAM_OFFLINE) \
  82.         return ThrowError("ERROR: Already logged in to XMPP.");
  83.  
  84. #define FIRE_EVENT(X, ...)  _FIRE_EVENT(this, X, __VA_ARGS__)
  85.  
  86. #define KEEP_ALIVE_TIMER            1
  87. #define LOGIN_TIMER                 2
  88. #define DETECT_CONNECTIVITY_TIMEOUT 10  // 10 seconds
  89. #define LOGIN_CONNECT_TIMEOUT       10 // 5 seconds
  90. #define LOGIN_TIMEOUT               30 // 30 seconds
  91.  
  92. #define REGISTRATION_TIMER          3
  93. #define REGISTRATION_TIMEOUT        300 // 30 seconds
  94.  
  95. #ifdef _COMCAST
  96. #define KEEP_ALIVE_TIMEOUT  120 //  120 seconds
  97. #else
  98. #define KEEP_ALIVE_TIMEOUT  30  //  disabled
  99. #endif
  100.  
  101. #define MAX_KEEP_ALIVES     3
  102.  
  103. // file transfer defines
  104. #define EXTENSION_FILTER \
  105.     _T("All Files (*.*)\0*.*\0\0")
  106.  
  107. #define E_INVALID_FILE_ID       "Invalid file transfer ID."
  108. #define E_FILE_ABORTED          "File transfer is already aborted."
  109. #define E_NOT_FILE_RECEIVER     "Not a file receiver."
  110. #define E_NOT_FILE_SENDER       "Not a file sender."
  111.  
  112. #ifdef _COMCAST
  113. //#define SUPPORT_MULTICAST_DISPLAYNAME
  114. #endif
  115.  
  116. #ifndef _COMCAST
  117. #define USE_REMOVE_BUDDY
  118. #endif
  119.  
  120. /////////////////////////////////////////////////////////////////////////////
  121. // Helper functions
  122.  
  123. static string GetStateString(const u_int16_t& uState)
  124. {
  125.     switch(uState)
  126.     {
  127.     case FTS_UNKNOWN:
  128.         return "unknown";
  129.  
  130.     case FTS_ERROR:
  131.         return "connection error";
  132.  
  133.     case FTS_DISCONNECTED:
  134.         return "disconnected";
  135.  
  136.     case FTS_REQUEST_REJECTED:
  137.         return "request rejected";
  138.  
  139.     case FTS_ABORTED:
  140.         return "aborted";
  141.  
  142.     case FTS_SENT_REQUEST:
  143.         return "request sent";
  144.  
  145.     case FTS_RECEIVE_REQUEST:
  146.         return "request received";
  147.  
  148.     case FTS_REQUEST_ACCEPTED:
  149.         return "request accepted";
  150.  
  151.     case FTS_RECEIVE_CONNECTING:
  152.         return "connecting to sender";
  153.  
  154.     case FTS_SEND_CONNECTING:
  155.         return "connecting to receiver";
  156.  
  157.     case FTS_RECEIVING:
  158.         return "receiving";
  159.  
  160.     case FTS_SENDING:
  161.         return "sending";
  162.  
  163.     case FTS_RECEIVE_COMPLETE:
  164.         return "receive complete";
  165.  
  166.     case FTS_SEND_COMPLETE:
  167.         return "send complete";
  168.  
  169.     default:
  170.         PAL_DB_ASSERT(0);
  171.     }
  172.     return "";
  173. }
  174.  
  175. static string TruncateSpace(const string& sInput)
  176. {
  177.     string sOutput;
  178.  
  179.     size_t iPos = sInput.find_first_not_of(" ");
  180.     if (iPos == string::npos)
  181.     {
  182.         // all are space
  183.         return sOutput;
  184.     }
  185.     else
  186.     {
  187.         sOutput = sInput.substr(iPos);
  188.     }
  189.  
  190.     iPos = sOutput.find_last_not_of(" ");
  191.  
  192.     sOutput = sOutput.substr(0, iPos+1);
  193.     return sOutput;
  194. }
  195. /////////////////////////////////////////////////////////////////////////////
  196. // FtContainerMap
  197.  
  198. FtContainerMap::iterator FtContainerMap::FindTransferId(u_int32_t uTransferId)
  199. {
  200.     iterator iter = begin();
  201.     for (; iter != end(); ++iter)
  202.     {
  203. /*
  204.         if ((iter->second.m_fti.m_uTransferId == uTransferId) &&
  205.             (FTS_ABORTED != iter->second.m_uState) &&
  206.             (FTS_ERROR != iter->second.m_uState))
  207.             return iter;
  208. */
  209.         if (iter->second.m_fti.m_uTransferId == uTransferId)
  210.         {
  211.             return iter;
  212.         }
  213.     }
  214.  
  215.     return end();
  216. }
  217.  
  218. /////////////////////////////////////////////////////////////////////////////
  219. // CXmppCommCtrl
  220. #if defined(__unix__) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  221. CXmppCommCtrl::CXmppCommCtrl(CXmppCommEventHandler_PTR callback_handler):
  222.     CCustomTimer(this),
  223.     m_iLoginDnsChannel(AF_CHANNEL_INVALID),
  224.     m_iGeneralDnsChannel(AF_CHANNEL_INVALID)
  225. {
  226.     m_CallbackHandler = callback_handler;
  227.     FinalConstruct();
  228.     BOOL bHandled = TRUE;
  229.     OnCreate(0, 0, 0, bHandled);
  230. }
  231. #endif
  232.  
  233. CXmppCommCtrl *pCXmppCommCtrl = NULL;
  234.  
  235. /*
  236. int X509_cmp(const X509 *cert1, const X509 *cert2) {
  237.     X509_check_purpose((X509 *)cert1, -1, 0);
  238.     X509_check_purpose((X509 *)cert2, -1, 0);
  239.     return memcmp(cert1->sha1_hash, cert2->sha1_hash, SHA_DIGEST_LENGTH);
  240. }
  241. */
  242.  
  243. static int custom_callback(void *ctx, void *arg)
  244. {
  245.     OpenSSL_add_all_algorithms();
  246.     X509_STORE_CTX store_ctx = X509_STORE_CTX(*(X509_STORE_CTX*)ctx);
  247.     int rc = X509_verify_cert(&store_ctx); // rc = 1 if validation success otherwise failure
  248.     X509 *cert = X509_STORE_CTX_get_current_cert(&store_ctx);
  249.     if(!cert) {
  250.         pCXmppCommCtrl->m_pJabberStream->Log("Server certificate invalid.");
  251.         return 0;
  252.     }
  253.     pCXmppCommCtrl->m_pJabberStream->Log(cert->name);
  254.    
  255.     const char *path = "C:\\Users\\eyeball\\Desktop\\cert\\ss.pem";
  256.     FILE* fp = fopen(path, "r");
  257.     if(!fp) {
  258.         pCXmppCommCtrl->m_pJabberStream->Log("Unable to open local certificate.");
  259.         return 0;
  260.     }
  261.     fseek(fp, 0, SEEK_END);
  262.     size_t size = ftell(fp);
  263.     char* data = new char[size];
  264.     rewind(fp);
  265.     fread(data, sizeof(char), size, fp);
  266.     fclose(fp);
  267.  
  268.     BIO *bio = BIO_new(BIO_s_mem());
  269.     BIO_puts(bio, data);
  270.     delete[] data;
  271.  
  272.     X509 *cert2 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
  273.     BIO_free(bio);
  274.    
  275.     if(!cert2) {
  276.         X509_free(cert);
  277.         pCXmppCommCtrl->m_pJabberStream->Log("Local certificate x509 object invalid..");
  278.         return 0;
  279.     }
  280.  
  281.     EVP_PKEY *pkey=X509_get_pubkey(cert2);
  282.     int result = X509_verify(cert, pkey);
  283.     pCXmppCommCtrl->m_pJabberStream->Log("X509_verify(): " + tostring(result));
  284.     EVP_PKEY_free(pkey);
  285.    
  286.     // pCXmppCommCtrl->m_pJabberStream->Log("My local certificate:");
  287.     // pCXmppCommCtrl->m_pJabberStream->Log(cert2->name);
  288.     // char *issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
  289.     // char *issuer2 = X509_NAME_oneline(X509_get_issuer_name(cert2), NULL, 0);
  290.     // pCXmppCommCtrl->m_pJabberStream->Log("Issuers:");
  291.     // pCXmppCommCtrl->m_pJabberStream->Log(std::string(issuer));
  292.     // pCXmppCommCtrl->m_pJabberStream->Log(std::string(issuer2));
  293.  
  294.     // char *subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
  295.     // char *subj2 = X509_NAME_oneline(X509_get_subject_name(cert2), NULL, 0);
  296.     // pCXmppCommCtrl->m_pJabberStream->Log("Subjects:");
  297.     // pCXmppCommCtrl->m_pJabberStream->Log(std::string(subj));
  298.     // pCXmppCommCtrl->m_pJabberStream->Log(std::string(subj2));
  299.    
  300.  
  301.     // check whether issuer and subject are same
  302.     // return (strcmp(issuer, issuer2) == 0 && strcmp(subj, subj2) == 0);  
  303.    
  304.     /*
  305.     int cmp = X509_cmp(cert, cert2);
  306.     if(cmp == 0) {
  307.         pCXmppCommCtrl->m_pJabberStream->Log("Certificate Verification Success.");
  308.     } else {
  309.         pCXmppCommCtrl->m_pJabberStream->Log("Certificate Verification Failed.");
  310.     }
  311.     */
  312.  
  313.     X509_free(cert2);
  314.     X509_free(cert);
  315.    
  316.     // return (cmp == 0);
  317.  
  318.     return result > 0;
  319. }
  320.  
  321. HRESULT CXmppCommCtrl::FinalConstruct()
  322. {
  323.     pCXmppCommCtrl = this;
  324.     //m_pWinsockInit = new PAL::Network::SocketInit;    // WS2_32.DLL is initiated in AFE, so don't think it's necessary here
  325.  
  326. #ifdef USE_NSSTREAM_FOR_XMPP
  327.     m_pNSsocket = new CNSsocket;
  328. #else
  329.     m_pAFEngine = new CAnyFirewallEngine;
  330.  
  331. #if defined(WIN32) && !(defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  332.     CLSID clsid = DEF_CLSID_ANYFIREWALL;
  333.     LPOLESTR wszCLSID = NULL;
  334.     HRESULT hr = StringFromCLSID(clsid, &wszCLSID);
  335.  
  336.     tstring sClsID = wszCLSID;
  337.     // Free memory.
  338.     CoTaskMemFree(wszCLSID);
  339.  
  340.     tstring sKey = TEXT("CLSID\\");
  341.     sKey += sClsID;
  342.     sKey += TEXT("\\InprocServer32");
  343.  
  344.     tstring sData;
  345.     tstring sValue;
  346.     GetRegistryEntry(HKEY_CLASSES_ROOT, sKey, sValue, sData);
  347. #endif
  348.  
  349. #if (defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  350.     m_bAFEngineInit = m_pAFEngine->Init(AF_MODE_STANDARD, true);
  351. #elif defined(WIN32)
  352.     m_bAFEngineInit = m_pAFEngine->InitDll(_Module.GetModuleInstance(),
  353. #if (AF_DLL_VERSION > 950000 && AF_DLL_VERSION < 9600000)
  354.         AF_MODE_AUTO, true
  355. #else
  356.         sData.mbs()
  357. #endif
  358.     );
  359. #else
  360.     m_bAFEngineInit = m_pAFEngine->Init();
  361. #endif
  362.  
  363. #if (AF_DLL_VERSION > 9600000)
  364. #if (AF_DLL_VERSION > 10011600)
  365.     if(PAL::IsLogEnabled(PAL::PAL_LOG_AF_MESSAGE)){
  366.         m_pAFEngine->SetLogFilePath(PAL::GetLogPath().c_str());
  367.     }
  368. #endif
  369.     m_pAFEngine->SetLogFileOptions(5, 2);
  370.     m_iAFEServerStoreID = m_pAFEngine->CreateServerStore(AF_MODE_AUTO, true);
  371.    
  372. #if (AF_DLL_VERSION >= 10011619)
  373.     m_pAFEngine->SetNetworkType(m_iAFEServerStoreID, EAfIPv4Only);
  374. #endif
  375. #endif
  376. #endif  // USE_NSSTREAM_FOR_XMPP
  377.  
  378.     // certificate verification
  379.     m_pAFEngine->SetCertificateVerificationCallback(custom_callback);
  380.  
  381.     srand(rand() ^ (rand() << 16) ^ (int)PAL::getCurrentTimeInMilliSeconds());
  382.     m_nNextFileId = rand();
  383.     m_iKeepAliveTimer = 0;
  384.     m_iKeepAlivePeriod = KEEP_ALIVE_TIMEOUT;
  385.     m_iLoginTimer = 0;
  386.     m_iRegistrationTimer = 0;
  387.     m_nFileTransferPort = 0;
  388.     m_pJabberStream = new CJabberStream(this);
  389. #ifdef USE_NSSTREAM_FOR_XMPP
  390.     m_pJabberStream->SetNSsocket(m_pNSsocket);
  391. #else
  392.     m_pJabberStream->SetAFEngine(m_pAFEngine, m_iAFEServerStoreID);
  393. #endif
  394.  
  395.     m_iConsecutiveKeepalives = 0;
  396.  
  397. #ifndef USE_NSSTREAM_FOR_XMPP
  398.     if (m_bAFEngineInit)
  399.     {
  400. //      m_pAFEngine->SetFirewallDetectionPeriod(0);
  401.     }
  402.     else
  403.     {
  404.         m_pJabberStream->Log("AFEngine failed to load");
  405.         ThrowError("ERROR: AFEngine failed to load");
  406.     }
  407. #endif
  408.  
  409. #ifdef PROXY_DETECTION
  410.     m_ProxyDetection.CoCreateInstance(CLSID_CProxyDetectionCtl, NULL, CLSCTX_INPROC_SERVER);
  411. #endif
  412.  
  413. //  m_iStunPassServerPort = 0;
  414.     m_iStunServerPort = 0;
  415.     m_iTurnUdpPort = 0;
  416.     m_iTurnTcpPort = 0;
  417.  
  418.     m_pLoginMutex    = new PAL::Mutex;
  419.     m_pLoginThread   = NULL;
  420.     m_pLoginDnsMutex = new PAL::Mutex;
  421.     m_bQuitLogin     = false;
  422.     m_pFileTransferMutex = new PAL::Mutex;
  423.  
  424. #ifndef USE_NSSTREAM_FOR_XMPP
  425.     m_iLoginDnsChannel = AF_CHANNEL_INVALID;
  426.     m_iGeneralDnsChannel = m_pAFEngine->Create(
  427. #if (AF_DLL_VERSION > 9600000)
  428.         m_iAFEServerStoreID,
  429. #endif
  430.         AF_CHANNEL_DNS
  431. #if (AF_DLL_VERSION > 950000)
  432.         , 0, 0, 0
  433. #endif
  434.     );
  435. #endif
  436.  
  437.     return S_OK;
  438. }
  439.  
  440. #if defined(__unix__) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  441. CXmppCommCtrl::~CXmppCommCtrl()
  442. {
  443.     BOOL bHandled = TRUE;
  444.     OnDestroy(0, 0, 0, bHandled);
  445.     FinalRelease();
  446. }
  447. #endif
  448.  
  449. void CXmppCommCtrl::FinalRelease()
  450. {
  451. #ifndef USE_NSSTREAM_FOR_XMPP
  452.     CLOSE_CHANNEL(m_iGeneralDnsChannel);
  453. #endif
  454.  
  455.     Logout();
  456.     FtCleanup();
  457.     SAFE_DELETE(m_pJabberStream);
  458.  
  459. #ifdef USE_NSSTREAM_FOR_XMPP
  460.     SAFE_DELETE(m_pNSsocket);
  461. #else
  462. #if (AF_DLL_VERSION > 9600000)
  463.     m_pAFEngine->CloseServerStore(m_iAFEServerStoreID);
  464. #endif
  465.     m_pAFEngine->Release();
  466.     SAFE_DELETE(m_pAFEngine);
  467. #endif
  468.  
  469. #ifdef PROXY_DETECTION
  470.     if (m_ProxyDetection)
  471.     {
  472.         m_ProxyDetection.Release();
  473.     }
  474. #endif
  475.  
  476.     //SAFE_DELETE(m_pWinsockInit);
  477.  
  478.     SAFE_DELETE(m_pLoginMutex);
  479.     SAFE_DELETE(m_pLoginDnsMutex);
  480.     SAFE_DELETE(m_pFileTransferMutex);
  481. }
  482.  
  483. LRESULT CXmppCommCtrl::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  484. {
  485. #if defined(__unix__) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  486.     m_pJabberStream->SetWindowHandle(this);
  487.     m_pJabberStream->m_pJabberParser->SetWindowHandle(this);
  488. #else
  489.     m_pJabberStream->SetWindowHandle(m_hWnd);
  490.     m_pJabberStream->m_pJabberParser->SetWindowHandle(m_hWnd);
  491. #endif
  492.     if (m_iKeepAlivePeriod)
  493.     {
  494.         m_iConsecutiveKeepalives = 0;
  495.         m_iKeepAliveTimer = SetTimer(KEEP_ALIVE_TIMER, m_iKeepAlivePeriod*1000);
  496.     }
  497.     return 0;
  498. }
  499.  
  500. LRESULT CXmppCommCtrl::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  501. {
  502.     if (m_iKeepAliveTimer != 0)
  503.         KillTimer(m_iKeepAliveTimer);
  504.     m_iKeepAliveTimer = 0;
  505.     m_iConsecutiveKeepalives = 0;
  506.  
  507.     KillLoginTimer();
  508.     KillRegistrationTimer();
  509.     return 0;
  510. }
  511.  
  512. LRESULT CXmppCommCtrl::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  513. {
  514.     m_pJabberStream->Log("OnTimer: triggered for " + tostring(wParam));
  515.     if (wParam == m_iKeepAliveTimer
  516.         &&  m_pJabberStream->m_StreamState == JABBER_STREAM_CONNECTED )
  517.     {
  518.         m_pJabberStream->jabber_keepalive();
  519.         if (++m_iConsecutiveKeepalives >= MAX_KEEP_ALIVES)
  520.         {
  521.             m_pJabberStream->Log("Did not receive keep-alives. Closing broken connection.");
  522. #if defined(__unix__) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  523.             m_pJabberStream->m_pXmppComm->PostMessage(WM_NETWORK_DOWN, NULL, NULL);
  524. #else
  525.             ::PostMessage(m_pJabberStream->m_pXmppComm->m_hWnd, WM_NETWORK_DOWN, NULL, NULL);
  526. #endif
  527.         }
  528.     }
  529.  
  530.     if (wParam == m_iLoginTimer)
  531.     {
  532.         PAL::Critical_Section cs(*m_pLoginMutex);
  533.  
  534.         KillLoginTimer();
  535.         BOOL bLoggedin = m_pJabberStream->m_StreamState == JABBER_STREAM_CONNECTED;
  536.         if (bLoggedin)
  537.         {
  538.             return 0;
  539.         }
  540.  
  541.         QuitLogin(false);
  542.  
  543.         bool bAnyMoreServersToTry = false;
  544.         while (TRUE)
  545.         {
  546.             if (!m_pJabberStream->SetNextServer())
  547.                 break;
  548.  
  549.             bAnyMoreServersToTry = true;
  550.  
  551.             if (m_pJabberStream->jabber_login())
  552.             {
  553.                 KillLoginTimer();
  554.                 m_iLoginTimer = SetTimer(LOGIN_TIMER, LOGIN_CONNECT_TIMEOUT*1000);
  555.                 return 0;
  556.             }
  557.  
  558.             m_pJabberStream->jabber_logout();
  559.         }
  560.         KillLoginTimer();
  561.         m_pJabberStream->jabber_full_close();
  562.  
  563.         if (bAnyMoreServersToTry)
  564.         {
  565.             m_pJabberStream->Log("Login Response: server unreachable");
  566.             FIRE_EVENT(Fire_OnLoginResponse, JABBER_LOGIN_SERVER_UNREACHABLE);
  567.         }
  568.         else
  569.         {
  570.             m_pJabberStream->Log("Login Response: timeout");
  571.             FIRE_EVENT(Fire_OnLoginResponse, JABBER_LOGIN_TIMEOUT);
  572.         }
  573.     }
  574.  
  575.     else if (wParam == m_iRegistrationTimer)
  576.     {
  577.         KillRegistrationTimer();
  578.         FIRE_EVENT(Fire_OnCreateAccountResponse, JABBER_REGISTRATION_TIMEOUT);
  579.     }
  580.     return 0;
  581. }
  582.  
  583. LRESULT CXmppCommCtrl::OnPacket(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  584. {
  585.     //Refresh keepalive timer
  586.     m_iConsecutiveKeepalives = 0;
  587.     if (m_iKeepAliveTimer)
  588.     {
  589.         KillTimer(m_iKeepAliveTimer);
  590.         m_iKeepAliveTimer = 0;
  591.     }
  592.     if (m_iKeepAlivePeriod)
  593.     {
  594.         m_iKeepAliveTimer = SetTimer(KEEP_ALIVE_TIMER, m_iKeepAlivePeriod*1000);
  595.     }
  596.     KillLoginTimer();
  597.     KillRegistrationTimer();
  598.     m_pJabberStream->jabber_process_packet();
  599.     return 0;
  600. }
  601.  
  602. LRESULT CXmppCommCtrl::OnConnected(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  603. {
  604.     KillLoginTimer();
  605.     m_iLoginTimer = SetTimer(LOGIN_TIMER, LOGIN_TIMEOUT*1000);
  606.     m_pJabberStream->jabber_process_connected();
  607.     return 0;
  608. }
  609.  
  610. LRESULT CXmppCommCtrl::OnInitialized(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  611. {
  612.     m_pJabberStream->jabber_process_initialized();
  613.     return 0;
  614. }
  615.  
  616. LRESULT CXmppCommCtrl::OnNetworkDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  617. {
  618.     m_pJabberStream->Log("Network Down " + itoa(wParam));
  619.  
  620.     PAL::Critical_Section cs(*m_pLoginMutex);
  621.     m_bQuitLogin = true;
  622.     bool bTryingLogin = false;
  623.  
  624. #ifndef USE_NSSTREAM_FOR_XMPP
  625.     {
  626.         //Close DNS channel
  627.         { PAL::Critical_Section cs(*m_pLoginDnsMutex);
  628.             CLOSE_CHANNEL(m_iLoginDnsChannel);
  629.         } //end of critical section
  630.     }
  631. #endif
  632.  
  633.     if (m_pLoginThread)
  634.     {
  635.         bTryingLogin = true;
  636.         m_pJabberStream->Log("Waiting for login thread to exit");
  637.         m_pLoginThread->join();
  638.         SAFE_DELETE(m_pLoginThread);
  639.     }
  640.  
  641. //  u_int32_t dwCurrTick = GetTickCount();
  642. //  u_int32_t dwDiff = dwCurrTick-dwLastTick;
  643.  
  644.     //if(dwDiff>2000)
  645. //  {
  646. //      dwLastTick = dwCurrTick;
  647. //  }
  648.  
  649.     //If disconnect happens quickly, e.g. wrong domain, this will freeze login
  650.     //failover.
  651.  
  652.     //else
  653.     //{
  654.     //  return 0;//ignore
  655.     //}
  656.  
  657.     KillLoginTimer();
  658.     KillRegistrationTimer();
  659.  
  660.     if (m_pJabberStream->m_StreamState == JABBER_STREAM_OFFLINE){
  661.         m_pJabberStream->Log("State is offline already. bTryingLogin = " + itoa((int)bTryingLogin));
  662. #ifdef __unix__
  663.         if(bTryingLogin){
  664.             FIRE_EVENT(Fire_OnLoginResponse, JABBER_LOGIN_UNKNOWN_RESPONSE);
  665.         }
  666. #endif
  667.         return 0;
  668.     }
  669.  
  670.     if (m_pJabberStream->m_bIsRegister == true)
  671.     {
  672.         FIRE_EVENT(Fire_OnCreateAccountResponse, JABBER_REGISTRATION_SERVER_UNREACHABLE);
  673.         return 0;
  674.     }
  675.  
  676.     BOOL bLoggedin = (m_pJabberStream->m_StreamState == JABBER_STREAM_CONNECTED);
  677.     m_pJabberStream->jabber_logout();
  678.  
  679.     if (bLoggedin)
  680.     {
  681.         m_pJabberStream->jabber_full_close();
  682.         m_pJabberStream->Log("Connection lost.");
  683.         FIRE_EVENT(Fire_OnConnectionLost);
  684.     }
  685.     else
  686.     {
  687.         bool bEventFired = false;
  688.         if (wParam == JABBER_LOGIN_CONNECTION_TO_SERVER_LOST)
  689.         {
  690.             //FIRE_EVENT(Fire_OnConnectionLost);
  691.             FIRE_EVENT(Fire_OnLoginResponse, JABBER_LOGIN_SERVER_UNREACHABLE);
  692.             bEventFired = true;
  693.         }
  694.  
  695.         if (wParam == JABBER_LOGIN_BASIC_PROXY_AUTHENTICATION_ERROR)
  696.         {
  697.             FIRE_EVENT(Fire_OnLoginResponse, JABBER_LOGIN_BASIC_PROXY_AUTHENTICATION_ERROR);
  698.             bEventFired = true;
  699.         }
  700.  
  701.         if (wParam == JABBER_LOGIN_NTLM_PROXY_AUTHENTICATION_ERROR)
  702.         {
  703.             FIRE_EVENT(Fire_OnLoginResponse, JABBER_LOGIN_NTLM_PROXY_AUTHENTICATION_ERROR);
  704.             bEventFired = true;
  705.         }
  706.  
  707.         if (wParam == JABBER_LOGIN_HTTP_PROXY_CONNECTION_ERROR)
  708.         {
  709.             FIRE_EVENT(Fire_OnLoginResponse, JABBER_LOGIN_HTTP_PROXY_CONNECTION_ERROR);
  710.             bEventFired = true;
  711.         }
  712.  
  713.         if (wParam == JABBER_LOGIN_NTLM_DOMAIN_EMPTY)
  714.         {
  715.             FIRE_EVENT(Fire_OnLoginResponse, JABBER_LOGIN_NTLM_DOMAIN_EMPTY);
  716.             bEventFired = true;
  717.         }
  718.  
  719.         while (TRUE)
  720.         {
  721.             if (!m_pJabberStream->SetNextServer())
  722.                 break;
  723.  
  724.             if (m_pJabberStream->jabber_login())
  725.             {
  726.                 KillLoginTimer();
  727.                 m_iLoginTimer = SetTimer(LOGIN_TIMER, LOGIN_CONNECT_TIMEOUT*1000);
  728.                 return 0;
  729.             }
  730.  
  731.             KillLoginTimer();
  732.             m_pJabberStream->jabber_logout();
  733.         }
  734.         m_pJabberStream->jabber_full_close();
  735.  
  736.         m_pJabberStream->Log("Login Response: server unreachable");
  737.         if(!bEventFired){
  738.             FIRE_EVENT(Fire_OnLoginResponse, JABBER_LOGIN_SERVER_UNREACHABLE);
  739.         }
  740.     }
  741.     return 0;
  742. }
  743.  
  744. LRESULT CXmppCommCtrl::OnFireLoginResponse(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  745. {
  746.     FIRE_EVENT(Fire_OnLoginResponse, wParam);
  747.     return 0;
  748. }
  749.  
  750. LRESULT CXmppCommCtrl::OnAutoUpdate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  751. {
  752.     m_pJabberStream->m_pJabberIQ->jabber_handle_auto_update((CXmlNode*)wParam);
  753.     return 0;
  754. }
  755.  
  756. LRESULT CXmppCommCtrl::OnUpdateFile(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  757. {
  758. #ifndef NO_FILE_TRANSFER
  759.     {
  760.         PAL::Critical_Section cs(*m_pFileTransferMutex);
  761.         FtContainerMap::iterator iter = m_FtContainerMap.FindTransferId(wParam);
  762.         if (iter == m_FtContainerMap.end())
  763.             return 0;
  764.  
  765.         FtContainer& fts = (iter->second);
  766.        
  767.         // Query the file transfer objects for the current transfer state.
  768.         if (NULL != fts.m_pFileSender.get())
  769.         {
  770.             fts.m_pFileSender->Log("OnUpdateFile: State = " + itoa(fts.m_uState) + ", IsTransferComplete = " + itoa((int)fts.m_pFileSender->IsTransferComplete()) + ", IsForcedComplete =  " + itoa((int)fts.m_pFileSender->IsForcedComplete()));
  771.             if ((fts.m_uState == FTS_ABORTED) ||
  772.                 (fts.m_uState == FTS_SEND_COMPLETE) ||
  773.                 (fts.m_uState == FTS_REQUEST_REJECTED) )
  774.             {
  775.                 // ignored
  776.                 CloseFtContainer(fts);
  777.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  778.                 return 0;
  779.             }
  780.             else if (fts.m_pFileSender->IsTransferComplete())
  781.             {
  782.                 fts.m_uState = FTS_SEND_COMPLETE;
  783.                 CloseFtContainer(fts);
  784.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  785.                 return 0;
  786.             }
  787.             else if (!(fts.m_pFileSender->CheckStatus()))
  788.             {
  789.                 fts.m_uState = FTS_ERROR;
  790.                 CloseFtContainer(fts);
  791. #ifndef MESSAGE_FILE_TRANSFER
  792.                 m_pJabberStream->m_pJabberIQ->FileTransferCancel(fts.m_sUserId, iter->first);
  793. #else
  794.                 m_pJabberStream->m_pJabberMessage->FileTransferCancel(fts.m_sUserId, iter->first);
  795. #endif
  796.                 //m_pChatService->SendFileEnd(fts.m_sUserId, fts.m_fti.m_uTransferId, ECS_FAILURE);
  797.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  798.                 return 0;
  799.             }
  800.             else if (fts.m_pFileSender->IsTimeout())
  801.             {
  802.                 //check the boolean and set fts.m_uState = FTS_SEND_COMPLETE;
  803.                 if(fts.m_pFileSender->IsConnected())
  804.                 {
  805.                     if(fts.m_pFileSender->IsForcedComplete())
  806.                     {
  807.                         fts.m_uState = FTS_SEND_COMPLETE;
  808.                         fts.m_pFileSender->SetForcedComplete(false);
  809.                     }
  810.                     else
  811.                     {
  812.                         fts.m_uState = FTS_DISCONNECTED;
  813.                     }
  814.                 }
  815.                 else
  816.                 {
  817.                     fts.m_uState = FTS_ERROR;
  818.                 }
  819.  
  820.                 CloseFtContainer(fts);
  821.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  822.                 return 0;
  823.             }
  824.             else if (fts.m_pFileSender->IsOpen())
  825.             {
  826.                 fts.m_uState = FTS_SENDING;
  827.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  828.                 return 0;
  829.             }
  830.             if (fts.m_uState == FTS_REQUEST_ACCEPTED)
  831.             {
  832.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);  // <-- This is pointless... the update will probably not be retrieved before the next update event is sent
  833.                 fts.m_uState = FTS_SEND_CONNECTING;
  834.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  835.                 return 0;
  836.             }
  837.         }
  838.         else if (NULL != fts.m_pFileReceiver.get())
  839.         {
  840.             if ((fts.m_uState == FTS_ABORTED) ||
  841.                 (fts.m_uState == FTS_RECEIVE_COMPLETE) ||
  842.                 (fts.m_uState == FTS_REQUEST_REJECTED) )
  843.             {
  844.                 // Ignore update
  845.                 CloseFtContainer(fts);
  846.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  847.                 return 0;
  848.             }
  849.             else if (fts.m_pFileReceiver->IsTransferComplete())
  850.             {
  851.                 fts.m_uState = FTS_RECEIVE_COMPLETE;
  852.                 CloseFtContainer(fts);
  853.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  854.                 return 0;
  855.             }
  856.             else if (!fts.m_pFileReceiver->CheckStatus())
  857.             {
  858.                 fts.m_uState = FTS_ERROR;
  859.                 CloseFtContainer(fts);
  860. #ifndef MESSAGE_FILE_TRANSFER
  861.                 m_pJabberStream->m_pJabberIQ->FileTransferCancel(fts.m_sUserId, iter->first);
  862. #else
  863.                 m_pJabberStream->m_pJabberMessage->FileTransferCancel(fts.m_sUserId, iter->first);
  864. #endif
  865.                 //m_pChatService->SendFileEnd(fts.m_sUserId, fts.m_fti.m_uTransferId, ECS_FAILURE);
  866.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  867.                 return 0;
  868.             }
  869.             else if (fts.m_pFileReceiver->IsTimeout())
  870.             {
  871.                 if(fts.m_pFileReceiver->IsConnected())
  872.                 {
  873.                     if(fts.m_pFileReceiver->IsForcedComplete())
  874.                     {
  875.                         fts.m_uState = FTS_RECEIVE_COMPLETE;
  876.                         fts.m_pFileReceiver->SetForcedComplete(false);
  877.                     }
  878.                     else
  879.                     {
  880.                         fts.m_uState = FTS_DISCONNECTED;
  881.                     }
  882.                 }
  883.                 else
  884.                 {
  885.                     fts.m_uState = FTS_ERROR;
  886.                 }
  887.  
  888.                 CloseFtContainer(fts);
  889.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  890.                 return 0;
  891.             }
  892.             else if (fts.m_pFileReceiver->IsOpen())
  893.             {
  894.                 fts.m_uState = FTS_RECEIVING;
  895.                 FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  896.                 return 0;
  897.             }
  898.         }
  899.     }
  900. #endif
  901.  
  902.     FIRE_EVENT(Fire_OnFileTransferUpdate, wParam);
  903.  
  904.     return 0;
  905. }
  906.  
  907. #if defined(__unix__) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  908. LRESULT CXmppCommCtrl::MessageHandlers(UINT uMsg, WPARAM wParam, LPARAM lParam)
  909. {
  910.     MESSAGE_HANDLER(WM_PACKET, OnPacket)
  911.     MESSAGE_HANDLER(WM_NETWORK_DOWN, OnNetworkDown)
  912.     MESSAGE_HANDLER(WM_CONNECTED, OnConnected)
  913.     MESSAGE_HANDLER(WM_INITIALIZED, OnInitialized)
  914.     MESSAGE_HANDLER(WM_AUTO_UPDATE, OnAutoUpdate)
  915.     MESSAGE_HANDLER(WM_UPDATE_FILE, OnUpdateFile)
  916.     MESSAGE_HANDLER(WM_FIRE_LOGIN_RESPONSE, OnFireLoginResponse)
  917.     MESSAGE_HANDLER(WM_TIMER, OnTimer)
  918.  
  919.     // Reaching here means no matching handler found.
  920.     return -1;
  921. }
  922. #endif
  923.  
  924. HRESULT CXmppCommCtrl::ThrowError(const string& sError)
  925. {
  926. #if defined(__unix__) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
  927.     FIRE_EVENT(Fire_OnError, ToBstr(sError));
  928.     return E_FAIL;
  929. #else
  930.     return Error(ToBstr(sError), IID_IXmppComm, E_FAIL);
  931. #endif
  932. }
  933.  
  934. string CXmppCommCtrl::ToBareJid(const string &bstrJid)
  935. {
  936.     if (bstrJid.empty())
  937.         return bstrJid;
  938.  
  939.     JabberID* jid = jabber_id_new(bstrJid);
  940.     if (jid->m_sNode.empty() && !jid->m_sDomain.empty())
  941.     {
  942.         // a jabber id must have domain, but may not have node.
  943.         // so the user's input may be wrongly treated
  944.         jid->m_sNode = jid->m_sDomain;
  945.         jid->m_sDomain = "";
  946.     }
  947.  
  948.     if (jid->m_sDomain.empty())
  949.         jid->m_sDomain = m_pJabberStream->m_sDomain;
  950.  
  951.     string s = jid->m_sNode + "@" + jid->m_sDomain;
  952.     jabber_id_free(jid);
  953.  
  954.     return s;
  955. }
  956.  
  957. string CXmppCommCtrl::ToFullJid(const string &bstrJid)
  958. {
  959.     if (bstrJid.empty())
  960.         return bstrJid;
  961.  
  962.     JabberID* jid = jabber_id_new(bstrJid);
  963.     if (jid->m_sNode.empty() && !jid->m_sDomain.empty())
  964.     {
  965.         // a jabber id must have domain, but may not have node.
  966.         // so the user's input may be wrongly treated
  967.         jid->m_sNode = jid->m_sDomain;
  968.         jid->m_sDomain = "";
  969.     }
  970.  
  971.     if (jid->m_sDomain.empty())
  972.         jid->m_sDomain = m_pJabberStream->m_sDomain;
  973.  
  974.     string s = jid->m_sNode + "@" + jid->m_sDomain;
  975.  
  976.     if (!jid->m_sResource.empty())
  977.     {
  978.         s += "/";
  979.         s += jid->m_sResource;
  980.     }
  981.  
  982.     jabber_id_free(jid);
  983.  
  984.     return s;
  985. }
  986.  
  987.  
  988. STDMETHODIMP CXmppCommCtrl::SetServer(BSTR bstrServerName, int iServerPort)
  989. {
  990.     string sServer = ToStringA(bstrServerName);
  991.  
  992.     //if (sServer.empty())
  993.     //  return ThrowError("ERROR: Empty Server Name.");
  994.  
  995.     if (iServerPort == 0)
  996.         iServerPort = 5222;
  997.  
  998.     m_pJabberStream->SetServerName(sServer);
  999.     m_pJabberStream->SetServerPort(iServerPort);
  1000.  
  1001.     return S_OK;
  1002. }
  1003.  
  1004. STDMETHODIMP CXmppCommCtrl::CreateAccount(BSTR bstrUserName, BSTR bstrPassword)
  1005. {
  1006.     if (m_pJabberStream->m_StreamState != JABBER_STREAM_OFFLINE)
  1007.         return ThrowError("ERROR: Invalid XMPP login state");
  1008.  
  1009.     m_pJabberStream->m_sUserName = ToStringA(bstrUserName);
  1010.     m_pJabberStream->m_sPassword = ToStringA(bstrPassword);
  1011.  
  1012.     if (m_pJabberStream->m_sUserName.empty())
  1013.         return ThrowError("ERROR: Please select a User Name.");
  1014.  
  1015.     m_pJabberStream->LookupServer(m_iGeneralDnsChannel, m_pJabberStream->m_sSrvDomain);
  1016.  
  1017.     if (m_pJabberStream->m_sDomain.empty()) {
  1018.         m_pJabberStream->m_sDomain = m_pJabberStream->m_sSrvDomain;
  1019.     }
  1020.  
  1021.     bool bServerAvailable = false;
  1022.     while (TRUE)
  1023.     {
  1024.         if (m_pJabberStream->SetNextServer()) {
  1025.             bServerAvailable = true;
  1026.         }
  1027.         else {
  1028.             if (!bServerAvailable) {
  1029.                 return ThrowError("ERROR: No server is available for login.");
  1030.             }
  1031.             else {
  1032.                 return ThrowError("ERROR: Unable to login to server.");
  1033.             }
  1034.         }
  1035.  
  1036.         if (m_pJabberStream->jabber_register())
  1037.             break;
  1038.  
  1039.     }
  1040.  
  1041.  
  1042.     KillRegistrationTimer();
  1043.     m_iRegistrationTimer = SetTimer(REGISTRATION_TIMER, REGISTRATION_TIMEOUT*1000);
  1044.     return S_OK;
  1045. }
  1046.  
  1047. STDMETHODIMP CXmppCommCtrl::SetTURNUsernamePassword(BSTR bstrUsername, BSTR bstrPassword ) // , BSTR bstrRealm) mainul
  1048. {
  1049.     m_sTurnUsername = ToStringA(bstrUsername);
  1050.     m_sTurnPassword = ToStringA(bstrPassword);
  1051. //  m_sStunRealm    = ToStringA(bstrRealm);
  1052. #ifndef USE_NSSTREAM_FOR_XMPP
  1053.     m_pAFEngine->SetTURNUsernamePassword(
  1054. #if (AF_DLL_VERSION > 9600000)
  1055.         m_iAFEServerStoreID,
  1056. #endif
  1057.         m_sTurnUsername, m_sTurnPassword); // , m_sStunRealm);
  1058. #endif
  1059.  
  1060.  
  1061.     return S_OK;
  1062. }
  1063.  
  1064. STDMETHODIMP CXmppCommCtrl::Login(BSTR bstrUserName, BSTR bstrPassword, BSTR bstrResource)
  1065. {
  1066.     PAL::Critical_Section cs(*m_pLoginMutex);
  1067.  
  1068.     m_pJabberStream->Log("Logging to XMPP as " + ToStringA(bstrUserName) + "/" + ToStringA(bstrResource));
  1069.  
  1070. #ifndef USE_NSSTREAM_FOR_XMPP
  1071.     if (!m_bAFEngineInit)
  1072.     {
  1073.         if (m_pAFEngine->VersionCheckFailed())
  1074.         {
  1075.             return ThrowError("ERROR: AnyFirewallEngine version mismatch");
  1076.         }
  1077.         if (!m_pAFEngine->LoadLibraryFailed())
  1078.         {
  1079.             return ThrowError("ERROR: License expired");
  1080.         }
  1081.         return ThrowError("ERROR: AnyFirewallEngine failed to load");
  1082.     }
  1083. #endif
  1084.  
  1085.     if (m_bQuitLogin)
  1086.     {
  1087.         //Did not call logout yet -- login thread just quit.
  1088.         if (m_pLoginThread)
  1089.         {
  1090.             KillLoginTimer();
  1091.  
  1092. #ifndef USE_NSSTREAM_FOR_XMPP
  1093.             {
  1094.                 //Close DNS Channel
  1095.                 { PAL::Critical_Section cs(*m_pLoginDnsMutex);
  1096.                     CLOSE_CHANNEL(m_iLoginDnsChannel);
  1097.                 } //end of critical section
  1098.             }
  1099. #endif
  1100.  
  1101.             m_pLoginThread->join();
  1102.             SAFE_DELETE(m_pLoginThread);
  1103.         }
  1104.     }
  1105.  
  1106.     if (m_pLoginThread || (m_pJabberStream->m_StreamState != JABBER_STREAM_OFFLINE))
  1107.         return ThrowError("ERROR: Invalid XMPP login state.");
  1108.  
  1109.     m_pJabberStream->m_sUserName = ToStringA(bstrUserName);
  1110.     m_pJabberStream->m_sPassword = ToStringA(bstrPassword);
  1111.  
  1112.     if (m_pJabberStream->m_sUserName.empty())
  1113.         return ThrowError("ERROR: Please select a User Name.");
  1114.  
  1115.     string sResource = ToStringA(bstrResource);
  1116.     if (!sResource.empty())
  1117.         m_pJabberStream->m_sResource = sResource;
  1118.  
  1119.     m_bQuitLogin = false;
  1120.  
  1121. #ifndef USE_NSSTREAM_FOR_XMPP
  1122.     // Create DNS Channel
  1123.     { PAL::Critical_Section cs(*m_pLoginDnsMutex);
  1124.  
  1125.         if (m_iLoginDnsChannel < 0)
  1126.         {
  1127.             m_iLoginDnsChannel = m_pAFEngine->Create(
  1128. #if (AF_DLL_VERSION > 9600000)
  1129.                 m_iAFEServerStoreID,
  1130. #endif
  1131.                 AF_CHANNEL_DNS
  1132. #if (AF_DLL_VERSION > 950000)
  1133.                 , 0, 0, 0
  1134. #endif
  1135.             );
  1136.         }
  1137.     } //end of critical section
  1138. #endif
  1139.  
  1140.     m_pLoginThread = new PAL::Thread(LoginThread, this);
  1141.     PAL_ASSERT(m_pLoginThread);
  1142.  
  1143.     return S_OK;
  1144. }
  1145.  
  1146. void* CXmppCommCtrl::LoginThread(void* arg)
  1147. {
  1148.     SET_CURRENT_THREAD_NAME;
  1149.     CXmppCommCtrl* pThis = (CXmppCommCtrl*)arg;
  1150.     pThis->LoginThreadImpl();
  1151.     return NULL;
  1152. }
  1153.  
  1154. void CXmppCommCtrl::LoginThreadImpl()
  1155. {
  1156.     if (m_bQuitLogin)
  1157.         return;
  1158.  
  1159. #ifndef USE_NSSTREAM_FOR_XMPP
  1160.     //Wait for firewall detection to finish
  1161.     m_pJabberStream->Log("Waiting for detect connectivity");
  1162.     for (int i = 0; i < 100; i++)
  1163.     {
  1164.         if (m_pAFEngine->WaitForDetectConnectivity(
  1165. #if (AF_DLL_VERSION > 9600000)
  1166.             m_iAFEServerStoreID,
  1167. #endif
  1168.             100) == 0)
  1169.         {
  1170.             break;
  1171.         }
  1172.         // Check if the login is to be canceled
  1173.         if (m_bQuitLogin){
  1174.             m_pJabberStream->Log("Login canceled");
  1175.             return;
  1176.         }
  1177.     }
  1178.     m_pJabberStream->Log("Wait for detect connectivity done");
  1179.  
  1180.     if (m_bQuitLogin)
  1181.         return;
  1182. #endif
  1183.  
  1184.     m_pJabberStream->LookupServer(m_iLoginDnsChannel, m_pJabberStream->m_sSrvDomain);
  1185.     if (m_bQuitLogin)
  1186.         return;
  1187.  
  1188.     if (m_pJabberStream->m_sDomain.empty()) {
  1189.         m_pJabberStream->m_sDomain = m_pJabberStream->m_sSrvDomain;
  1190.     }
  1191.     if (m_bQuitLogin)
  1192.         return;
  1193.  
  1194.     m_pJabberStream->ResetServerIndex();
  1195.  
  1196.     bool bServerAvailable = false;
  1197.     while (TRUE)
  1198.     {
  1199.         if (m_bQuitLogin) return;
  1200.         if (m_pJabberStream->SetNextServer()) {
  1201.             bServerAvailable = true;
  1202.         }
  1203.         else {
  1204.             m_bQuitLogin = true;
  1205.             if (!bServerAvailable) {
  1206.                 m_pJabberStream->Log("Login Response: no server available for login");
  1207.                 PostMessage(WM_FIRE_LOGIN_RESPONSE, JABBER_LOGIN_SERVER_UNREACHABLE, 0);
  1208.             }
  1209.             else {
  1210.                 m_pJabberStream->Log("Login Response: server unreachable");
  1211.                 PostMessage(WM_FIRE_LOGIN_RESPONSE, JABBER_LOGIN_SERVER_UNREACHABLE, 0);
  1212.             }
  1213.             return;
  1214.         }
  1215.  
  1216.         if (m_pJabberStream->jabber_login())
  1217.             break;
  1218.  
  1219.         m_pJabberStream->jabber_logout();
  1220.     }
  1221.  
  1222.     KillLoginTimer();
  1223.     if (m_bQuitLogin)
  1224.         return;
  1225.     m_iLoginTimer = SetTimer(LOGIN_TIMER, LOGIN_CONNECT_TIMEOUT*1000);
  1226. }
  1227.  
  1228. STDMETHODIMP CXmppCommCtrl::Logout()
  1229. {
  1230.     m_pJabberStream->Log("XMPP logout");
  1231.     QuitLogin(true);
  1232.     return S_OK;
  1233. }
  1234.  
  1235. void CXmppCommCtrl::QuitLogin(bool bFullClose)
  1236. {
  1237.     m_pJabberStream->Log("Quit Login");
  1238.  
  1239.     PAL::Critical_Section cs(*m_pLoginMutex);
  1240.  
  1241.     m_bQuitLogin = true;
  1242.  
  1243. #ifndef USE_NSSTREAM_FOR_XMPP
  1244.     {
  1245.         //Close DNS channel
  1246.         { PAL::Critical_Section cs(*m_pLoginDnsMutex);
  1247.             CLOSE_CHANNEL(m_iLoginDnsChannel);
  1248.         } //end of critical section
  1249.     }
  1250. #endif
  1251.  
  1252.     KillLoginTimer();
  1253.     m_pJabberStream->jabber_logout();
  1254.     if (bFullClose)
  1255.     {
  1256.         m_pJabberStream->jabber_full_close();
  1257.     }
  1258.     else
  1259.     {
  1260.         m_pJabberStream->jabber_close();
  1261.     }
  1262.  
  1263.     if (m_pLoginThread)
  1264.     {
  1265.         m_pLoginThread->join();
  1266.         SAFE_DELETE(m_pLoginThread);
  1267.     }
  1268. }
  1269.  
  1270. STDMETHODIMP CXmppCommCtrl::SetNATTraversalServer(int iServerType, BSTR bstrAddr, int iPort, VARIANT_BOOL bDone)
  1271. {
  1272. #ifndef USE_NSSTREAM_FOR_XMPP
  1273.     string sServerName = TruncateSpace(ToStringA(bstrAddr));
  1274.     m_pJabberStream->Log("Setting AFS: iServerType = " + tostring(iServerType) + " " + sServerName + ":" + tostring(iPort) + ", bDone = " + tostring(bDone));
  1275.  
  1276. #if (AF_DLL_VERSION > 950000)
  1277.     struct AfConnectionParams connParams;
  1278.     connParams.iRTO = 500;
  1279.     connParams.iRc = 1;
  1280.     connParams.iRm = 16;
  1281.     connParams.iTi = 5000;
  1282. #endif
  1283.  
  1284.     switch(iServerType)
  1285.     {
  1286.     case eServerSRV:
  1287.         {
  1288.             string sSrvDomain = sServerName;
  1289.             m_pJabberStream->SetSrvDomain(sSrvDomain);
  1290.         }
  1291.         break;
  1292.     case eServerHttpProxy:
  1293.         {
  1294.             PAL_DB2("Proxy address: ", sServerName.c_str());
  1295.             PAL_DB2("Proxy port: ", iPort);
  1296.  
  1297.             if(sServerName.length() > 0 && iPort > 0)
  1298.             {
  1299.                 string sProxyHost = m_pAFEngine->CreateHost(
  1300.                     AF_HOST_PUBLIC, sServerName, iPort, AF_PROTOCOL_TCP
  1301. #if (AF_DLL_VERSION > 950000)
  1302.                     , &connParams
  1303. #endif
  1304.                 );
  1305.  
  1306. #if (AF_DLL_VERSION > 9600000)
  1307.                 m_pAFEngine->SetHTTPProxy(
  1308.                     m_iAFEServerStoreID,
  1309.                     sProxyHost,
  1310.                     m_pAFEngine->GetHTTPProxyUsername(m_iAFEServerStoreID),
  1311.                     m_pAFEngine->GetHTTPProxyPassword(m_iAFEServerStoreID),
  1312.                     m_pAFEngine->GetHTTPProxyDomain(m_iAFEServerStoreID));
  1313. #else
  1314.                 m_pAFEngine->SetHTTPProxy(
  1315.                     sProxyHost,
  1316.                     m_pAFEngine->GetHTTPProxyUsername(),
  1317.                     m_pAFEngine->GetHTTPProxyPassword(),
  1318.                     m_pAFEngine->GetHTTPProxyDomain());
  1319. #endif
  1320.             }
  1321.         }
  1322.         break;
  1323.     case eServerStunUdp:
  1324.         m_sStunServerAddress = sServerName;
  1325.  
  1326.         if (iPort == 0)
  1327.             iPort = 3478;
  1328.  
  1329.         m_iStunServerPort = iPort;
  1330.         break;
  1331.     case eServerTurnUdp:
  1332.         m_sTurnUdpAddress = sServerName;
  1333.         m_iTurnUdpPort    = iPort;
  1334.         break;
  1335.     case eServerTurnTcp:
  1336.         m_sTurnTcpAddress = sServerName;
  1337.         m_iTurnTcpPort    = iPort;
  1338.         break;
  1339.     default:    // there is no eServerStunTcp for XMPP
  1340.         break;
  1341.     }
  1342.  
  1343.     if(bDone)
  1344.     {
  1345.         string sStunHost;
  1346.         if (!m_pJabberStream->m_sSrvDomain.empty())
  1347.         {
  1348.             sStunHost = m_pAFEngine->CreateHost(AF_HOST_DNS_SRV, "_stun._udp." + m_pJabberStream->m_sSrvDomain, 0, AF_PROTOCOL_UDP
  1349. #if (AF_DLL_VERSION > 950000)
  1350.                     , &connParams
  1351. #endif
  1352.             );
  1353.             /*
  1354.             m_pAFEngine->DNS_SRV_Lookup(m_iLoginDnsChannel,
  1355.                     "_stun._udp." + m_pJabberStream->m_sSrvDomain,
  1356.                     AF_PROTOCOL_UDP);
  1357.             */
  1358.         }
  1359. //---------------------------addtion timing features to be added here--------------
  1360.         if ((!m_sStunServerAddress.empty()) && (m_iStunServerPort != 0))
  1361.         {
  1362.             sStunHost += m_pAFEngine->CreateHost(AF_HOST_PUBLIC,
  1363.                                         m_sStunServerAddress,
  1364.                                         m_iStunServerPort,
  1365.                                         AF_PROTOCOL_UDP
  1366. #if (AF_DLL_VERSION > 950000)
  1367.                                         , &connParams
  1368. #endif
  1369.                                         );
  1370.         }
  1371.  
  1372.         m_pAFEngine->SetSTUNServer(
  1373. #if (AF_DLL_VERSION > 9600000)
  1374.             m_iAFEServerStoreID,
  1375. #endif
  1376.             sStunHost);
  1377. //---------------------------------------end -----------------------------------------
  1378.         string sTurnHost;
  1379.         if (!m_pJabberStream->m_sSrvDomain.empty())
  1380.         {
  1381.             sTurnHost = m_pAFEngine->CreateHost(AF_HOST_DNS_SRV, "_turn._udp." + m_pJabberStream->m_sSrvDomain, 0, AF_PROTOCOL_UDP
  1382. #if (AF_DLL_VERSION > 950000)
  1383.                     , &connParams
  1384. #endif
  1385.                 );
  1386.  
  1387.             /*  m_pAFEngine->DNS_SRV_Lookup(m_iLoginDnsChannel,
  1388.                         "_stun-relay._udp." + m_pJabberStream->m_sSrvDomain,
  1389.                         AF_PROTOCOL_UDP); */
  1390.         }
  1391.  
  1392.         if ((!m_sTurnUdpAddress.empty()) && (m_iTurnUdpPort != 0))
  1393.         {
  1394.             sTurnHost += m_pAFEngine->CreateHost(AF_HOST_PUBLIC,
  1395.                                         m_sTurnUdpAddress,
  1396.                                         m_iTurnUdpPort,
  1397.                                         AF_PROTOCOL_UDP
  1398. #if (AF_DLL_VERSION > 950000)
  1399.                                         , &connParams
  1400. #endif
  1401.                                         );
  1402.         }
  1403.  
  1404.         if (!m_pJabberStream->m_sSrvDomain.empty())
  1405.         {
  1406.             sTurnHost += m_pAFEngine->CreateHost(AF_HOST_DNS_SRV, "_turn._tcp." + m_pJabberStream->m_sSrvDomain, 0, AF_PROTOCOL_TCP
  1407. #if (AF_DLL_VERSION > 950000)
  1408.                     , &connParams
  1409. #endif
  1410.                 );
  1411.  
  1412.                 /* m_pAFEngine->DNS_SRV_Lookup(m_iLoginDnsChannel,
  1413.                     "_stun-relay._tcp." + m_pJabberStream->m_sSrvDomain,
  1414.                     AF_PROTOCOL_TCP); */
  1415.         }
  1416.  
  1417.         if ((!m_sTurnTcpAddress.empty()) && (m_iTurnTcpPort != 0))
  1418.         {
  1419.             sTurnHost += m_pAFEngine->CreateHost(AF_HOST_PUBLIC,
  1420.                                         m_sTurnTcpAddress,
  1421.                                         m_iTurnTcpPort,
  1422.                                         AF_PROTOCOL_TCP
  1423. #if (AF_DLL_VERSION > 950000)
  1424.                                         , &connParams
  1425. #endif
  1426.                                         );
  1427.         }
  1428.  
  1429.         m_pAFEngine->SetTURNServer(
  1430. #if (AF_DLL_VERSION > 9600000)
  1431.             m_iAFEServerStoreID,
  1432. #endif
  1433.             sTurnHost);
  1434.  
  1435. #if (AF_DLL_VERSION > 950000)
  1436.         AfFirewallDetectionParams param;
  1437.         param.iDetectUdpConnectivity = 1;
  1438.         param.iDetectTcpConnectivity = 1;
  1439.         param.iDetectProxyConnectivity = 1;
  1440.         param.iDetectUPnPConnectivity = 1;
  1441.         param.iCheckTurnCredentials = 0;
  1442.         param.iUPnPDeviceDiscoveryTimeout = 500;
  1443.         m_pAFEngine->DetectConnectivity(
  1444. #if (AF_DLL_VERSION > 9600000)
  1445.             m_iAFEServerStoreID,
  1446. #endif
  1447.             /*NULL*/&param);
  1448. #else  
  1449.         m_pAFEngine->DetectConnectivity();
  1450. #endif
  1451.     }
  1452.     m_pJabberStream->Log("DetectConnectivity called");
  1453. #endif
  1454.  
  1455.     return S_OK;
  1456. }
  1457.  
  1458. STDMETHODIMP CXmppCommCtrl::AddContact(
  1459.     BSTR bstrJid,
  1460.     BSTR bstrFirstName,
  1461.     BSTR bstrLastName,
  1462.     BSTR bstrDisplayName,
  1463.     BSTR bstrGroupName)
  1464. {
  1465.     string sJID = ToBareJid(ToStringA(bstrJid));
  1466.     string sDisplayName = ToStringU8(bstrDisplayName);
  1467.     string sGroupName = ToStringU8(bstrGroupName);
  1468.  
  1469.     if (sJID.empty())
  1470.         return ThrowError("ERROR: Empty ID.");
  1471.  
  1472.     if (sJID.size() > 2047)
  1473.         return ThrowError("ERROR: Contact's length too long.");
  1474.  
  1475.     if (compare_i(sJID, m_pJabberStream->jabber_get_bare_jid()))
  1476.         return ThrowError("ERROR: Invalid contact.");
  1477.  
  1478.     if (m_pJabberStream->m_pJabberBuddy->jabber_is_in_buddy_list(sJID))
  1479.         return ThrowError("ERROR: Already in the contact list.");
  1480.  
  1481.     m_pJabberStream->m_pJabberRoster->jabber_roster_add_buddy(
  1482.         sJID,
  1483.         sDisplayName,
  1484.         sGroupName);
  1485.  
  1486.     return S_OK;
  1487. }
  1488.  
  1489. STDMETHODIMP CXmppCommCtrl::RemoveContact(BSTR bstrJid)
  1490. {
  1491.     string sJID = ToBareJid(ToStringA(bstrJid));
  1492.  
  1493.     if (sJID.empty())
  1494.         return ThrowError("ERROR: Empty ID.");
  1495.  
  1496. #ifdef USE_REMOVE_BUDDY
  1497.     m_pJabberStream->m_pJabberRoster->jabber_roster_remove_buddy(sJID);
  1498. #else
  1499.     m_pJabberStream->m_pJabberPresence->jabber_presence_subscription_set(sJID, "unsubscribe");
  1500.     m_pJabberStream->m_pJabberBuddy->jabber_buddy_remove(sJID);
  1501. #endif
  1502.  
  1503.     return S_OK;
  1504. }
  1505.  
  1506. #ifdef USE_VARIANT_IN_EVENT
  1507. STDMETHODIMP CXmppCommCtrl::GetContactList(SAFEARRAY **pVal)
  1508. #else
  1509. STDMETHODIMP CXmppCommCtrl::GetContactList(std::vector<std::string> *pVal)
  1510. #endif
  1511. {
  1512.     CHECK_POINTER(pVal);
  1513.     ListofString ls;
  1514.     m_pJabberStream->m_pJabberBuddy->jabber_get_buddy_list(ls);
  1515.  
  1516.     ListofString::const_iterator iter = ls.begin();
  1517. #ifdef USE_VARIANT_IN_EVENT
  1518.     BstrArray aContacts(ls.size());
  1519.     int nIndex = 0;
  1520.     for (; iter != ls.end(); ++iter)
  1521.     {
  1522.         aContacts.PutString(nIndex++, *iter);
  1523.     }
  1524.  
  1525.     aContacts.Detach(pVal);
  1526. #else
  1527.     pVal->clear();
  1528.     for (; iter != ls.end(); ++iter)
  1529.     {
  1530.         pVal->push_back(*iter);
  1531.     }
  1532. #endif
  1533.  
  1534.     return S_OK;
  1535. }
  1536.  
  1537. STDMETHODIMP CXmppCommCtrl::get_ContactDisplayName(BSTR bstrJid, BSTR *pVal)
  1538. {
  1539.     CHECK_POINTER(pVal);
  1540.  
  1541.     string sJid = ToBareJid(ToStringA(bstrJid));
  1542.     if (sJid.empty())
  1543.         return ThrowError("ERROR: Please select a User Name.");
  1544.  
  1545.     string sDisplayName = GetContactDisplayName(sJid);
  1546.  
  1547.     BstrFromStringU8(pVal, sDisplayName);
  1548.     return S_OK;
  1549. }
  1550.  
  1551. STDMETHODIMP CXmppCommCtrl::put_ContactDisplayName(BSTR bstrJid, BSTR newVal)
  1552. {
  1553.     string sJid = ToBareJid(ToStringA(bstrJid));
  1554.     if (sJid.empty())
  1555.         return ThrowError("ERROR: Please select a User Name.");
  1556.  
  1557.     string sDisplayName = ToStringU8(newVal);
  1558.  
  1559.     JabberBuddy* jb = m_pJabberStream->m_pJabberBuddy->jabber_buddy_find(sJid);
  1560.     if (jb)
  1561.     {
  1562.         jb->m_sDisplayName = sDisplayName;
  1563.     }
  1564.  
  1565.     if (!m_pJabberStream->m_pJabberRoster->jabber_roster_alias_change(sJid, sDisplayName))
  1566.     {
  1567.         m_pJabberStream->m_pJabberBuddy->SetExtDisplayName(sJid, sDisplayName);
  1568.     }
  1569.     return S_OK;
  1570. }
  1571.  
  1572. STDMETHODIMP CXmppCommCtrl::get_Nickname(BSTR *pVal)
  1573. {
  1574.     CHECK_POINTER(pVal);
  1575.  
  1576.     string sDisplayName = m_pJabberStream->m_sDisplayName;
  1577.     if (sDisplayName.empty())
  1578.     {
  1579.         sDisplayName = jabber_get_node(m_pJabberStream->jabber_get_bare_jid());
  1580.     }
  1581.     BstrFromStringU8(pVal, sDisplayName);
  1582.     return S_OK;
  1583. }
  1584.  
  1585. STDMETHODIMP CXmppCommCtrl::put_Nickname(BSTR newVal)
  1586. {
  1587.     string sDisplayName = ToStringU8(newVal);
  1588.     if (m_pJabberStream->m_sDisplayName != sDisplayName)
  1589.     {
  1590.         m_pJabberStream->m_sDisplayName = sDisplayName;
  1591.  
  1592.         if (m_pJabberStream->m_StreamState != JABBER_STREAM_OFFLINE)
  1593.         {
  1594.             m_pJabberStream->m_pJabberIQ->StorePrivateData(
  1595.                 "nick",
  1596.                 "http://jabber.org/protocol/nick",
  1597.                 sDisplayName);
  1598.  
  1599.             m_pJabberStream->SendNicknameToContacts(sDisplayName);
  1600.         }
  1601.     }
  1602.     return S_OK;
  1603. }
  1604.  
  1605. STDMETHODIMP CXmppCommCtrl::AddContactResponse(BSTR bstrJid, VARIANT_BOOL bAccept)
  1606. {
  1607.     string sJid = ToBareJid(ToStringA(bstrJid));
  1608.     if (sJid.empty())
  1609.         return ThrowError("ERROR: Please select a User Name.");
  1610.  
  1611.     m_pJabberStream->m_pJabberPresence->jabber_presence_subscription_set(
  1612.         sJid,
  1613.         ToBOOL(bAccept) ? "subscribed" : "unsubscribed");
  1614.  
  1615.     // Sept 19, 2005: requested by Comcast to remove buddy if rejecting an add contact request
  1616.     //if (!bAccept)
  1617.     //{
  1618.     //  m_pJabberStream->m_pJabberRoster->jabber_roster_remove_buddy(sJid);
  1619.     //}
  1620.  
  1621. /*
  1622.     if (bAccept)
  1623.     {
  1624.         JabberBuddy* jb = m_pJabberStream->m_pJabberBuddy->jabber_buddy_find(sJid);
  1625.         if (jb)
  1626.         {
  1627.             if (jb->m_sSubscription == "none"
  1628.                 && (jb->m_iSubscription & JABBER_SUB_PENDING) == 0)
  1629.             {
  1630.                 m_pJabberStream->m_pJabberPresence->jabber_presence_subscription_set(
  1631.                     sJid, "subscribe");
  1632.             }
  1633.         }
  1634.     }
  1635. */
  1636.     return S_OK;
  1637. }
  1638.  
  1639. STDMETHODIMP CXmppCommCtrl::GuestAddContactResponse(BSTR bstrGuestEmail, VARIANT_BOOL bAccept)
  1640. {
  1641.     string sGuestEmail = ToStringA(bstrGuestEmail);
  1642.     if (sGuestEmail.empty())
  1643.         return ThrowError("ERROR: Empty guest email address.");
  1644.  
  1645.     m_pJabberStream->m_pJabberMessage->GuestAddContactResponse(
  1646.         sGuestEmail,
  1647.         ToBOOL(bAccept));
  1648.  
  1649.     return S_OK;
  1650. }
  1651.  
  1652. #ifdef USE_VARIANT_IN_EVENT
  1653. STDMETHODIMP CXmppCommCtrl::GetContactResource(BSTR bstrJid, SAFEARRAY **pVal)
  1654. #else
  1655. STDMETHODIMP CXmppCommCtrl::GetContactResource(BSTR bstrJid, std::vector<std::string> *pVal)
  1656. #endif
  1657. {
  1658.     CHECK_POINTER(pVal);
  1659.  
  1660.     string sJid = ToBareJid(ToStringA(bstrJid));
  1661.     if (sJid.empty())
  1662.         return ThrowError("ERROR: Please select a User Name.");
  1663.  
  1664.     JabberBuddy* jb = m_pJabberStream->m_pJabberBuddy->jabber_buddy_find(sJid);
  1665.     if (!jb)
  1666.         return ThrowError("ERROR: Invalid user name.");
  1667.  
  1668.     JabberResourceList::iterator iter = jb->m_resourceList.begin();
  1669.  
  1670. #ifdef USE_VARIANT_IN_EVENT
  1671.     BstrArray aResource(jb->m_resourceList.size() * 7);
  1672.     int iIndex = 0;
  1673.     for (; iter != jb->m_resourceList.end(); ++iter)
  1674.     {
  1675.         JabberBuddyResource* jbr = *iter;
  1676.  
  1677.         aResource.PutBstr(iIndex++, StringU8ToBstr(jbr->m_sResourceName));
  1678.         aResource.PutBstr(iIndex++, StringU8ToBstr(jbr->m_sShowState));
  1679.         aResource.PutBstr(iIndex++, StringU8ToBstr(jbr->m_sStatus));
  1680.         aResource.PutString(iIndex++, jbr->m_sAvatar);
  1681.         aResource.PutString(iIndex++, itoa(jbr->m_bVideoSupport));
  1682.         aResource.PutString(iIndex++, itoa(jbr->m_bAudioSupport));
  1683.         aResource.PutString(iIndex++, jbr->m_iDeliveryReceiptSupport == DELIVERY_RECEIPT_CAPS_SUPPORTED ? "1" : "0");
  1684.     }
  1685.  
  1686.     aResource.Detach(pVal);
  1687. #else
  1688.     pVal->clear();
  1689.     for (; iter != jb->m_resourceList.end(); ++iter)
  1690.     {
  1691.         JabberBuddyResource* jbr = *iter;
  1692.  
  1693.         pVal->push_back(jbr->m_sResourceName);
  1694.         pVal->push_back(jbr->m_sShowState);
  1695.         pVal->push_back(jbr->m_sStatus);
  1696.         pVal->push_back(jbr->m_sAvatar);
  1697.         pVal->push_back(itoa(jbr->m_bVideoSupport));
  1698.         pVal->push_back(itoa(jbr->m_bAudioSupport));
  1699.         pVal->push_back(jbr->m_iDeliveryReceiptSupport == DELIVERY_RECEIPT_CAPS_SUPPORTED ? "1" : "0");
  1700.     }
  1701. #endif
  1702.     return S_OK;
  1703. }
  1704.  
  1705.  
  1706. #ifdef USE_VARIANT_IN_EVENT
  1707. STDMETHODIMP CXmppCommCtrl::GetContactGroupList(BSTR bstrJid, SAFEARRAY **pVal)
  1708. #else
  1709. STDMETHODIMP CXmppCommCtrl::GetContactGroupList(BSTR bstrJid, std::vector<std::string> *pVal)
  1710. #endif
  1711. {
  1712.     CHECK_POINTER(pVal);
  1713.  
  1714.     string sJid = ToBareJid(ToStringA(bstrJid));
  1715.     if (sJid.empty())
  1716.         return ThrowError("ERROR: Please select a User Name.");
  1717.  
  1718.     JabberBuddy* jb = m_pJabberStream->m_pJabberBuddy->jabber_buddy_find(sJid);
  1719.     if (!jb)
  1720.         return ThrowError("ERROR: Invalid user name.");
  1721.  
  1722.     ListofString::iterator iter = jb->m_groupList.begin();
  1723.  
  1724. #ifdef USE_VARIANT_IN_EVENT
  1725.     BstrArray aGroups(jb->m_groupList.size());
  1726.     int iIndex = 0;
  1727.     for (; iter != jb->m_groupList.end(); ++iter)
  1728.     {
  1729.         aGroups.PutBstr(iIndex++, StringU8ToBstr(*iter));
  1730.     }
  1731.  
  1732.     aGroups.Detach(pVal);
  1733. #else
  1734.     pVal->clear();
  1735.     for (; iter != jb->m_groupList.end(); ++iter)
  1736.     {
  1737.         pVal->push_back(*iter);
  1738.     }
  1739. #endif
  1740.     return S_OK;
  1741. }
  1742.  
  1743. STDMETHODIMP CXmppCommCtrl::AddContactGroup(BSTR bstrJid, BSTR bstrGroup)
  1744. {
  1745.     string sJid = ToBareJid(ToStringA(bstrJid));
  1746.     if (sJid.empty())
  1747.         return ThrowError("ERROR: Please select a User Name.");
  1748.  
  1749.     string sGroup = ToStringU8(bstrGroup);
  1750.     if (sGroup.empty())
  1751.         return ThrowError("ERROR: Empty group name.");
  1752.  
  1753.     m_pJabberStream->m_pJabberRoster->jabber_roster_group_add(sJid, sGroup);
  1754.  
  1755.     return S_OK;
  1756. }
  1757.  
  1758. STDMETHODIMP CXmppCommCtrl::RemoveContactGroup(BSTR bstrJid, BSTR bstrGroup)
  1759. {
  1760.     string sJid = ToBareJid(ToStringA(bstrJid));
  1761.     if (sJid.empty())
  1762.         return ThrowError("ERROR: Please select a User Name.");
  1763.  
  1764.     string sGroup = ToStringU8(bstrGroup);
  1765.     if (sGroup.empty())
  1766.         return ThrowError("ERROR: Empty group name.");
  1767.  
  1768.     m_pJabberStream->m_pJabberRoster->jabber_roster_group_remove(sJid, sGroup);
  1769.     return S_OK;
  1770. }
  1771.  
  1772. //Removed
  1773. //November 11, 2008
  1774.  
  1775. //STDMETHODIMP CXmppCommCtrl::GetMyResource(SAFEARRAY **pVal)
  1776. //{
  1777. //  CHECK_POINTER(pVal);
  1778. //  string sBareJid = m_pJabberStream->jabber_get_bare_jid();
  1779. //
  1780. //  JabberBuddy* jb = m_pJabberStream->m_pJabberBuddy->jabber_buddy_find(sBareJid);
  1781. //  //JabberBuddy* jb = new JabberBuddy;
  1782. //  if (!jb)
  1783. //      return S_OK;
  1784. //
  1785. //  int iSize = jb->m_resourceList.size() * 5;
  1786. //  if (iSize <= 0)
  1787. //      return S_OK;
  1788. //
  1789. //  JabberResourceList::iterator iter = jb->m_resourceList.begin();
  1790. //  for (; iter != jb->m_resourceList.end(); ++iter)
  1791. //  {
  1792. //      JabberBuddyResource* jbr = *iter;
  1793. //      if (jbr->m_sResourceName == m_pJabberStream->m_sResource)
  1794. //      {
  1795. //          iSize -= 5;
  1796. //      }
  1797. //  }
  1798. //
  1799. //  if (iSize <= 0)
  1800. //  {
  1801. //      return S_OK;
  1802. //  }
  1803. //
  1804. //  BstrArray aResources(iSize);
  1805. //  int iIndex = 0;
  1806. //  iter = jb->m_resourceList.begin();
  1807. //  for (; iter != jb->m_resourceList.end(); ++iter)
  1808. //  {
  1809. //      JabberBuddyResource* jbr = *iter;
  1810. //      if (jbr->m_sResourceName == m_pJabberStream->m_sResource)
  1811. //          continue;
  1812. //
  1813. //      if (jbr->m_sShowState.empty())
  1814. //          jbr->m_sShowState = "Available";
  1815. //
  1816. //      aResources.PutBstr(iIndex++, StringU8ToBstr(jbr->m_sResourceName));
  1817. //      aResources.PutBstr(iIndex++, StringU8ToBstr(jbr->m_sShowState));
  1818. //      aResources.PutBstr(iIndex++, StringU8ToBstr(jbr->m_sStatus));
  1819. //      aResources.PutString(iIndex++, jbr->m_sAvatar);
  1820. //      aResources.PutString(iIndex++, itoa(jbr->m_bVideoSupport));
  1821. //  }
  1822. //
  1823. //  aResources.Detach(pVal);
  1824. //  return S_OK;
  1825. //}
  1826. //
  1827.  
  1828. STDMETHODIMP CXmppCommCtrl::SendChatMessage(int iChatID, BSTR bstrJid, BSTR bstrMsg)
  1829. {
  1830.     BSTR bstrHtml;
  1831.     BstrFromString(&bstrHtml, string(""));
  1832.     return SendChatMessageHTML(iChatID, bstrJid, bstrMsg, bstrHtml);
  1833. }
  1834.  
  1835. STDMETHODIMP CXmppCommCtrl::SendChatMessageHTML(
  1836.     int iChatID,
  1837.     BSTR bstrJid,
  1838.     BSTR bstrMsg,
  1839.     BSTR bstrHTML)
  1840. {
  1841.     string sMsg = ToStringU8(bstrMsg);
  1842.     string sHtml = ToStringU8(bstrHTML);
  1843.     if (sMsg.empty() && sHtml.empty())
  1844.         return ThrowError("ERROR: Empty chat message and HTML message.");
  1845.  
  1846.     string sJid = ToFullJid(ToStringA(bstrJid));
  1847.     if (sJid.empty())
  1848.         return ThrowError("ERROR: Please select a User Name.");
  1849.  
  1850. #if 0
  1851.     if (sMsg.length() <= 2)
  1852.     {
  1853.         int nCh = atoi(sMsg.c_str());
  1854.         char szTest[1];
  1855.         szTest[0] = nCh;
  1856.         szTest[1] = '\0';
  1857.         sMsg.assign(szTest);
  1858.     }
  1859. #endif
  1860.  
  1861.     int iMessageID = m_pJabberStream->m_pJabberMessage->jabber_message_send_chat(iChatID, sJid, sMsg, sHtml);
  1862.     if (iMessageID <= 0)
  1863.         return ThrowError("ERROR: Invalid XHTML message");
  1864.  
  1865.     return (HRESULT)iMessageID;
  1866. }
  1867.  
  1868. STDMETHODIMP CXmppCommCtrl::AddBlock(BSTR bstrJid)
  1869. {
  1870.     string sJid = ToBareJid(ToStringA(bstrJid));
  1871.     if (sJid.empty())
  1872.         return ThrowError("ERROR: Please select a User Name.");
  1873.  
  1874.     m_pJabberStream->m_pJabberPrivacy->jabber_privacy_add_block(sJid);
  1875.     return S_OK;
  1876. }
  1877.  
  1878. STDMETHODIMP CXmppCommCtrl::RemoveBlock(BSTR bstrJid)
  1879. {
  1880.     string sJid = ToBareJid(ToStringA(bstrJid));
  1881.     if (sJid.empty())
  1882.         return ThrowError("ERROR: Please select a User Name.");
  1883.  
  1884.     m_pJabberStream->m_pJabberPrivacy->jabber_privacy_remove_block(sJid);
  1885.     return S_OK;
  1886. }
  1887.  
  1888. #ifdef USE_VARIANT_IN_EVENT
  1889. STDMETHODIMP CXmppCommCtrl::GetBlockList(SAFEARRAY **pVal)
  1890. #else
  1891. STDMETHODIMP CXmppCommCtrl::GetBlockList(std::vector<std::string> *pVal)
  1892. #endif
  1893. {
  1894.     CHECK_POINTER(pVal);
  1895.  
  1896.     ListofString ls;
  1897.     m_pJabberStream->m_pJabberPrivacy->jabber_privacy_get_block_list(ls);
  1898.  
  1899.     ListofString::iterator iter = ls.begin();
  1900.  
  1901. #ifdef USE_VARIANT_IN_EVENT
  1902.     BstrArray a(ls.size());
  1903.     int i = 0;
  1904.     for (; iter != ls.end(); ++iter)
  1905.     {
  1906.         a.PutString(i++, *iter);
  1907.     }
  1908.     a.Detach(pVal);
  1909. #else
  1910.     pVal->clear();
  1911.     for(; iter != ls.end(); ++iter)
  1912.     {
  1913.         pVal->push_back(*iter);
  1914.     }
  1915. #endif
  1916.     return S_OK;
  1917. }
  1918.  
  1919. #ifdef USE_VARIANT_IN_EVENT
  1920. STDMETHODIMP CXmppCommCtrl::GetChatSessionParticipants(int iChatID, SAFEARRAY** pVal)
  1921. #else
  1922. STDMETHODIMP CXmppCommCtrl::GetChatSessionParticipants(int iChatID, std::vector<std::string> *pVal)
  1923. #endif
  1924. {
  1925.     SetofString participants;
  1926.     m_pJabberStream->m_pJabberMessage->jabber_get_chat_session_participants(iChatID, participants);
  1927.  
  1928.     tstring id = m_pJabberStream->m_sUserName;
  1929.  
  1930.     //Remove your own id
  1931.     participants.erase(m_pJabberStream->NormalizeJid(ToFullJid(m_pJabberStream->m_sUserName)));
  1932.  
  1933.     SetofString::iterator iterSS = participants.begin();
  1934.  
  1935. #ifdef USE_VARIANT_IN_EVENT
  1936.     BstrArray aJid(participants.size());
  1937.     int i = 0;
  1938.     for (; iterSS != participants.end(); iterSS++) {
  1939.         aJid.PutString(i++, *iterSS);
  1940.     }
  1941.     aJid.Detach(pVal);
  1942. #else
  1943.     pVal->clear();
  1944.     for(; iterSS != participants.end(); iterSS++)
  1945.     {
  1946.         pVal->push_back(*iterSS);
  1947.     }
  1948. #endif
  1949.     return S_OK;
  1950. }
  1951.  
  1952.  
  1953. #ifdef USE_VARIANT_IN_EVENT
  1954. STDMETHODIMP CXmppCommCtrl::SendMulticastMessage(int iChatID, VARIANT vJid, BSTR bstrMsg)
  1955. #else
  1956. STDMETHODIMP CXmppCommCtrl::SendMulticastMessage(int iChatID, const std::vector<std::string> &vJid, BSTR bstrMsg)
  1957. #endif
  1958. {
  1959.     BSTR bstrHtml;
  1960.     BstrFromString(&bstrHtml, string(""));
  1961.     return SendMulticastMessageHTML(iChatID, vJid, bstrMsg, bstrHtml);
  1962. }
  1963.  
  1964. STDMETHODIMP CXmppCommCtrl::SendMulticastMessageHTML(
  1965.     int iChatID,
  1966. #ifdef USE_VARIANT_IN_EVENT
  1967.     VARIANT vJid,
  1968. #else
  1969.     const std::vector<std::string> &vJid,
  1970. #endif
  1971.     BSTR bstrMsg,
  1972.     BSTR bstrHTML)
  1973. {
  1974. #ifdef USE_VARIANT_IN_EVENT
  1975.     BstrArray aJid;
  1976.     aJid.Attach(&vJid);
  1977.     int iSize = aJid.GetSize();
  1978. #else
  1979.     int iSize = vJid.size();
  1980. #endif
  1981.     if (iSize == 0)
  1982.         return ThrowError("ERROR: Empty recipient.");
  1983.  
  1984.     string sMsg = ToStringU8(bstrMsg);
  1985.     string sHtml = ToStringU8(bstrHTML);
  1986.     if (sMsg.empty() && sHtml.empty())
  1987.         return ThrowError("ERROR: Empty message.");
  1988.  
  1989.     SetofString ss;
  1990.     for (int i = 0; i < iSize; i++)
  1991.     {
  1992. #ifdef USE_VARIANT_IN_EVENT
  1993.         ss.insert(ToFullJid(ToStringA(aJid.GetBstr(i))));
  1994. #else
  1995.         ss.insert(ToFullJid(ToStringA(vJid[i])));
  1996. #endif
  1997.     }
  1998.  
  1999.     bool bGoodHtml = m_pJabberStream->m_pJabberMessage->jabber_message_send_multicast(
  2000.         iChatID,
  2001.         ss,
  2002.         sMsg,
  2003.         sHtml);
  2004.  
  2005. #ifdef USE_VARIANT_IN_EVENT
  2006.     aJid.Detach();
  2007. #endif
  2008.  
  2009.     if (!bGoodHtml) {
  2010.         return ThrowError("ERROR: Invalid XHTML message");
  2011.     }
  2012.  
  2013.     return S_OK;
  2014. }
  2015.  
  2016. STDMETHODIMP CXmppCommCtrl::SendXML(BSTR bstrXML)
  2017. {
  2018.     string sMsg = ToStringU8(bstrXML);
  2019.     if (sMsg.empty())
  2020.     {
  2021.         return ThrowError("ERROR: Empty XML message.");
  2022.     }
  2023.     m_pJabberStream->jabber_send_raw(sMsg);
  2024.     return S_OK;
  2025. }
  2026.  
  2027. STDMETHODIMP CXmppCommCtrl::TransportMode(BSTR bstrTransportMode)
  2028. {
  2029.     string sMode = ToStringA(bstrTransportMode);
  2030.  
  2031.     if (sMode.empty())
  2032.         return ThrowError("ERROR: Empty Transport Mode.");
  2033.  
  2034.     if (m_pJabberStream->m_StreamState != JABBER_STREAM_OFFLINE)
  2035.         return ThrowError("ERROR: Must be logout first.");
  2036.  
  2037.     if (compare_i(sMode, "tls"))
  2038.     {
  2039.         m_pJabberStream->UseTLS(true);
  2040.     }
  2041.     else
  2042.     {
  2043.         m_pJabberStream->UseTLS(false);
  2044.         if (!compare_i(sMode, "tcp"))
  2045.         {
  2046.             return ThrowError(sMode +" Transport Mode not supported.");
  2047.         }
  2048.     }
  2049.     return S_OK;
  2050. }
  2051.  
  2052. STDMETHODIMP CXmppCommCtrl::SetApplicationActiveMode(int eApplicationActiveMode)
  2053. {
  2054.     return S_OK;
  2055. }
  2056.  
  2057. STDMETHODIMP CXmppCommCtrl::ApplicationKeepAliveHandler()
  2058. {
  2059.     m_pJabberStream->Log("ApplicationKeepAliveHandler");
  2060.     if (m_pJabberStream->m_StreamState == JABBER_STREAM_CONNECTED)
  2061.     {
  2062.         m_pJabberStream->jabber_keepalive();
  2063.     }
  2064.     return S_OK;
  2065. }
  2066.  
  2067. #ifdef PROXY_DETECTION
  2068. STDMETHODIMP CXmppCommCtrl::DetectHttpProxy(VARIANT_BOOL* pVal)
  2069. {
  2070.     CHECK_POINTER(pVal);
  2071.  
  2072.     *pVal = VARIANT_FALSE;
  2073.  
  2074.     if (m_ProxyDetection)
  2075.     {
  2076.         tstring sUrl = m_pJabberStream->GetServerName();
  2077.         long nPort = m_pJabberStream->GetServerPort();
  2078.         CComBSTR bstrUrl = ToBstr(sUrl);
  2079.  
  2080.         VARIANT_BOOL vbDetected = VARIANT_FALSE;
  2081.         if (SUCCEEDED(m_ProxyDetection->DetectHTTPProxy(bstrUrl, nPort, &vbDetected)))
  2082.         {
  2083.             if (vbDetected == VARIANT_TRUE)
  2084.             {
  2085.                 CComBSTR bstrAddress;
  2086.                 m_ProxyDetection->GetDetectedAddress(&bstrAddress);
  2087.                 m_ProxyDetection->GetDetectedPort(&nPort);
  2088.  
  2089.                 string sAddress = ToStringA(bstrAddress);
  2090.                 if (!sAddress.empty())
  2091.                 {
  2092.                     SetNATTraversalServer(eServerHttpProxy, bstrAddress, nPort, false);
  2093.                     *pVal = VARIANT_TRUE;
  2094.                 }
  2095.             }
  2096.         }
  2097.     }
  2098.  
  2099.     return S_OK;
  2100. }
  2101. #endif
  2102.  
  2103. STDMETHODIMP CXmppCommCtrl::CreateChatSession(int *pVal)
  2104. {
  2105.     CHECK_POINTER(pVal);
  2106.     *pVal = m_pJabberStream->m_pJabberMessage->jabber_new_chat_session_id();
  2107.     return S_OK;
  2108. }
  2109.  
  2110. STDMETHODIMP CXmppCommCtrl::get_IsSubscriptionPending(BSTR bstrJid, VARIANT_BOOL *pVal)
  2111. {
  2112.     CHECK_POINTER(pVal);
  2113.  
  2114.     string sJid = ToBareJid(ToStringA(bstrJid));
  2115.     if (sJid.empty())
  2116.         return ThrowError("ERROR: Please select a User Name.");
  2117.  
  2118.     JabberBuddy* jb = m_pJabberStream->m_pJabberBuddy->jabber_buddy_find(sJid);
  2119.     if (!jb)
  2120.         return ThrowError("ERROR: Invalid user name.");
  2121.  
  2122.     if (jb->m_resourceList.size() != 0)
  2123.     {
  2124.         *pVal = ToVB(FALSE);
  2125.     }
  2126.     else
  2127.     {
  2128.         *pVal = ToVB((jb->m_iSubscription & JABBER_SUB_PENDING) != 0);
  2129.     }
  2130.     return S_OK;
  2131. }
  2132.  
  2133. STDMETHODIMP CXmppCommCtrl::get_IgnoreResource(VARIANT_BOOL *pVal)
  2134. {
  2135.     CHECK_POINTER(pVal);
  2136.  
  2137.     *pVal = ToVB(m_pJabberStream->m_bIgnoreResource);
  2138.     return S_OK;
  2139. }
  2140.  
  2141. STDMETHODIMP CXmppCommCtrl::put_IgnoreResource(VARIANT_BOOL newVal)
  2142. {
  2143.     m_pJabberStream->m_bIgnoreResource = ToBOOL(newVal);
  2144.     return S_OK;
  2145. }
  2146.  
  2147.  
  2148. STDMETHODIMP CXmppCommCtrl::RetrieveOfflineMessage(BSTR bstrJid)
  2149. {
  2150.     string sJid = ToBareJid(ToStringA(bstrJid));
  2151.     if (sJid.empty())
  2152.         return ThrowError("ERROR: Please select a User Name.");
  2153.  
  2154.     m_pJabberStream->m_pJabberMessage->jabber_retrieve_offline_message(sJid, 0);
  2155.     return S_OK;
  2156. }
  2157.  
  2158. STDMETHODIMP CXmppCommCtrl::RemoveOfflineMessage(BSTR bstrJid, BSTR bstrMsgID)
  2159. {
  2160.     CHECK_LOGIN();
  2161.     string sJid = ToBareJid(ToStringA(bstrJid));
  2162.     if (sJid.empty())
  2163.         return ThrowError("ERROR: Please select a User Name.");
  2164.  
  2165.     m_pJabberStream->m_pJabberMessage->jabber_remove_offline_message(
  2166.         sJid,
  2167.         ToStringA(bstrMsgID));
  2168.     return S_OK;
  2169. }
  2170.  
  2171. STDMETHODIMP CXmppCommCtrl::RetrieveContactProfile(BSTR bstrJid)
  2172. {
  2173.     CHECK_LOGIN();
  2174.  
  2175.     string s = ToBareJid(ToStringA(bstrJid));
  2176.     if (s.empty())
  2177.         return ThrowError("ERROR: Please select a User Name.");
  2178.  
  2179.     m_pJabberStream->m_pJabberRoster->jabber_roster_retrieve_vcard(s);
  2180.     return S_OK;
  2181. }
  2182.  
  2183. STDMETHODIMP CXmppCommCtrl::GetPresenceState(BSTR *pVal)
  2184. {
  2185.     CHECK_POINTER(pVal);
  2186.  
  2187.     BstrFromString(pVal, m_pJabberStream->m_sPresenceState);
  2188.     return S_OK;
  2189. }
  2190.  
  2191. STDMETHODIMP CXmppCommCtrl::GetPresenceStatus(BSTR *pVal)
  2192. {
  2193.     CHECK_POINTER(pVal);
  2194.  
  2195.     BstrFromStringU8(pVal, m_pJabberStream->m_sPresenceStatus);
  2196.     return S_OK;
  2197. }
  2198.  
  2199. STDMETHODIMP CXmppCommCtrl::SetPresence(BSTR bstrState, BSTR bstrStatus)
  2200. {
  2201.     CHECK_LOGIN();
  2202.  
  2203.     string s = ToStringA(bstrState);
  2204.     if (!jabber_presence_state_validate(s))
  2205.         return ThrowError("ERROR: Invalid presence state.");
  2206.  
  2207.     if (compare_i(s, "available"))
  2208.         s = "chat";
  2209.  
  2210.     m_pJabberStream->m_sPresenceState = s;
  2211.     m_pJabberStream->m_sPresenceStatus = ToStringU8(bstrStatus);
  2212.  
  2213.     m_pJabberStream->m_pJabberPresence->jabber_presence_send(
  2214.         m_pJabberStream->m_sPresenceState,
  2215.         m_pJabberStream->m_sPresenceStatus);
  2216.  
  2217.     return S_OK;
  2218. }
  2219.  
  2220. STDMETHODIMP CXmppCommCtrl::IsLoggedIn(VARIANT_BOOL *pVal)
  2221. {
  2222.     CHECK_POINTER(pVal);
  2223.  
  2224.     *pVal = ToVB(m_pJabberStream->m_StreamState == JABBER_STREAM_CONNECTED);
  2225.     return S_OK;
  2226. }
  2227.  
  2228. STDMETHODIMP CXmppCommCtrl::IsInContactList(BSTR bstrJid, VARIANT_BOOL *pVal)
  2229. {
  2230.     CHECK_POINTER(pVal);
  2231.     CHECK_LOGIN();
  2232.     string sJid = ToBareJid(ToStringA(bstrJid));
  2233.     *pVal = ToVB(m_pJabberStream->m_pJabberBuddy->jabber_is_in_buddy_list(sJid));
  2234.     return S_OK;
  2235. }
  2236.  
  2237. STDMETHODIMP CXmppCommCtrl::get_UserName(BSTR *pVal)
  2238. {
  2239.     CHECK_POINTER(pVal);
  2240.     CHECK_LOGIN();
  2241.  
  2242.     BstrFromString(pVal, m_pJabberStream->m_sUserName);
  2243.     return S_OK;
  2244. }
  2245.  
  2246. STDMETHODIMP CXmppCommCtrl::get_Domain(BSTR *pVal)
  2247. {
  2248.     CHECK_POINTER(pVal);
  2249.     BstrFromString(pVal, m_pJabberStream->m_sDomain);
  2250.     return S_OK;
  2251. }
  2252.  
  2253. STDMETHODIMP CXmppCommCtrl::put_Domain(BSTR newVal)
  2254. {
  2255.     if (m_pJabberStream->m_StreamState != JABBER_STREAM_OFFLINE)
  2256.         return ThrowError("ERROR: Invalid XMPP login state.");
  2257.  
  2258.     m_pJabberStream->m_sDomain = ToStringA(newVal);
  2259.     return S_OK;
  2260. }
  2261.  
  2262. STDMETHODIMP CXmppCommCtrl::SetVideoSupport(VARIANT_BOOL bSupport)
  2263. {
  2264.     // video support can be toggled on/off
  2265.     m_pJabberStream->m_bVideoSupport = ToBOOL(bSupport);
  2266.     if (m_pJabberStream->m_StreamState == JABBER_STREAM_CONNECTED)
  2267.         m_pJabberStream->m_pJabberPresence->UpdateVideoSupport();
  2268.     return S_OK;
  2269. }
  2270.  
  2271. STDMETHODIMP CXmppCommCtrl::SetAudioSupport(VARIANT_BOOL bSupport)
  2272. {
  2273.     m_pJabberStream->m_bAudioSupport = ToBOOL(bSupport);
  2274. #ifndef _COMCAST
  2275.     // setting audio support also sends capability message
  2276.     if (m_pJabberStream->m_StreamState == JABBER_STREAM_CONNECTED)
  2277.         m_pJabberStream->m_pJabberPresence->UpdateVideoSupport();
  2278. #endif
  2279.     return S_OK;
  2280. }
  2281.  
  2282. void CXmppCommCtrl::KillLoginTimer()
  2283. {
  2284.     if (m_iLoginTimer)
  2285.         KillTimer(m_iLoginTimer);
  2286.  
  2287.     m_iLoginTimer = 0;
  2288. }
  2289.  
  2290. void CXmppCommCtrl::KillRegistrationTimer()
  2291. {
  2292.     if (m_iRegistrationTimer)
  2293.         KillTimer(m_iRegistrationTimer);
  2294.  
  2295.     m_iRegistrationTimer = 0;
  2296. }
  2297.  
  2298.  
  2299. #ifdef USE_VARIANT_IN_EVENT
  2300. STDMETHODIMP CXmppCommCtrl::GetAllowList(SAFEARRAY **pVal)
  2301. #else
  2302. STDMETHODIMP CXmppCommCtrl::GetAllowList(std::vector<std::string> *pVal)
  2303. #endif
  2304. {
  2305.     CHECK_POINTER(pVal);
  2306.     CHECK_LOGIN();
  2307.  
  2308.     ListofString ls;
  2309.     m_pJabberStream->m_pJabberBuddy->jabber_get_allow_list(ls);
  2310.  
  2311.     ListofString::const_iterator iter = ls.begin();
  2312.  
  2313. #ifdef USE_VARIANT_IN_EVENT
  2314.     BstrArray aContacts(ls.size());
  2315.     int nIndex = 0;
  2316.     for (; iter != ls.end(); ++iter)
  2317.     {
  2318.         aContacts.PutString(nIndex++, *iter);
  2319.     }
  2320.  
  2321.     aContacts.Detach(pVal);
  2322. #else
  2323.     pVal->clear();
  2324.     for(; iter != ls.end(); iter++)
  2325.     {
  2326.         pVal->push_back(*iter);
  2327.     }
  2328. #endif
  2329.     return S_OK;
  2330. }
  2331.  
  2332. STDMETHODIMP CXmppCommCtrl::SendTypingEvent(int iChatID, BSTR bstrJid, VARIANT_BOOL bStart)
  2333. {
  2334.     CHECK_LOGIN();
  2335.     string sJid = ToBareJid(ToStringA(bstrJid));
  2336.     if (sJid.empty())
  2337.         return ThrowError("ERROR: Please select a User Name.");
  2338.  
  2339.     m_pJabberStream->m_pJabberMessage->jabber_send_typing_event(iChatID, sJid, ToBOOL(bStart));
  2340.     return S_OK;
  2341. }
  2342.  
  2343. STDMETHODIMP CXmppCommCtrl::get_Avatar(BSTR *pVal)
  2344. {
  2345.     CHECK_POINTER(pVal);
  2346.     BstrFromString(pVal, m_pJabberStream->m_sAvatar);
  2347.     return S_OK;
  2348. }
  2349.  
  2350. STDMETHODIMP CXmppCommCtrl::put_Avatar(BSTR newVal)
  2351. {
  2352.     string sAvatar = ToStringA(newVal);
  2353.     if (sAvatar.empty())
  2354.         return ThrowError("ERROR: Empty avatar.");
  2355.    
  2356.     m_pJabberStream->m_sAvatar = sAvatar;
  2357.     m_pJabberStream->m_pJabberPresence->jabber_update_avatar();
  2358.    
  2359.     return S_OK;
  2360. }
  2361.  
  2362. STDMETHODIMP CXmppCommCtrl::SetAvatar(BSTR bstrFile)
  2363. {
  2364. #ifdef USE_VCARD_FOR_AVATAR
  2365.     string sAvatar = ToStringA(bstrFile);
  2366.     if (sAvatar.empty()){
  2367.         if(!m_pJabberStream->m_mpVCard[eVCardInfoTypeAvatarHash].empty()){
  2368.             m_pJabberStream->m_mpVCard[eVCardInfoTypeAvatarHash].clear();
  2369.             m_pJabberStream->m_mpVCard[eVCardInfoTypePublishedAvatarHash] = INVALID_STRING;
  2370.             m_pJabberStream->m_mpVCard[eVCardInfoTypeAvatarPath].clear();
  2371.             m_pJabberStream->m_pJabberPresence->jabber_update_avatar();
  2372.         }
  2373.     }
  2374.     else{
  2375.         // Get image type from extension
  2376.         size_t dotPos = sAvatar.find_last_of('.');
  2377.         if(dotPos == string::npos){
  2378.             return ThrowError("Invalid image type for avatar.");
  2379.         }
  2380.         string sType = sAvatar.substr(dotPos + 1);
  2381.        
  2382.         ifstream fileReader(sAvatar.c_str(), ios::in | ios::binary);
  2383.         if(!fileReader.is_open()){
  2384.             return ThrowError("Error in opening image file for avatar.");
  2385.         }
  2386.        
  2387.         // Check size of the iamge
  2388.         long begin = (long)fileReader.tellg();
  2389.         fileReader.seekg (0, ios::end);
  2390.         long end = (long)fileReader.tellg();
  2391.         long size = end - begin;
  2392.         if(size > (8 * 1024)){
  2393.             fileReader.close();
  2394.             return ThrowError("Avatar file size too large.");
  2395.         }
  2396.        
  2397.         fileReader.seekg (0, ios::beg);
  2398.         ostringstream oss;
  2399.         oss << fileReader.rdbuf();
  2400.         string sImageData(oss.str());
  2401.        
  2402.         string sImageHash = jabber_sha_hash(sImageData);
  2403.         // publish if it's a different image
  2404.         if(m_pJabberStream->m_mpVCard[eVCardInfoTypeAvatarHash] != sImageHash){
  2405.             m_pJabberStream->m_mpVCard[eVCardInfoTypeAvatarHash] = sImageHash;
  2406.             m_pJabberStream->m_mpVCard[eVCardInfoTypePublishedAvatarHash] = sImageHash;
  2407.            
  2408.             m_pJabberStream->m_pJabberRoster->jabber_vcard_set_photo(sType, sImageData);
  2409.             // presence will be published after server acknowledges vcard publication
  2410.         }
  2411.     }
  2412. #endif
  2413.    
  2414.     return S_OK;
  2415. }
  2416.  
  2417. STDMETHODIMP CXmppCommCtrl::DownloadAvatar(BSTR bstrJid, BSTR bstrDir)
  2418. {
  2419. #ifdef USE_VCARD_FOR_AVATAR
  2420.     string sJid = ToBareJid(ToStringA(bstrJid));
  2421.     std::map<EVCardInfoType, std::string> *pmpVCard = NULL;
  2422.    
  2423.     if (sJid.empty()){
  2424.         // Self
  2425.         sJid = m_pJabberStream->jabber_get_bare_jid();
  2426.         pmpVCard = &m_pJabberStream->m_mpVCard;
  2427.     }
  2428.     else{
  2429.         JabberBuddy* jb = m_pJabberStream->m_pJabberBuddy->jabber_buddy_find(sJid);
  2430.         if (!jb)
  2431.             return ThrowError("ERROR: Invalid user name.");
  2432.         pmpVCard = &jb->m_mpVCard;
  2433.     }
  2434.    
  2435.     if((*pmpVCard)[eVCardInfoTypeAvatarHash] == (*pmpVCard)[eVCardInfoTypePublishedAvatarHash]){
  2436.         // Fire an event to let know avatar is ready
  2437.         FIRE_EVENT(Fire_OnAvatarDownloaded, sJid, (*pmpVCard)[eVCardInfoTypeAvatarPath]);
  2438.         return S_OK;
  2439.     }
  2440.    
  2441.     (*pmpVCard)[eVCardInfoTypeAvatarPath] = ToStringA(bstrDir);
  2442.    
  2443.     m_pJabberStream->m_pJabberRoster->jabber_vcard_request(ToBareJid(ToStringA(bstrJid))); // Send bstrJid instead of sJid because jabber_vcard_request takes empty string for self
  2444. #endif
  2445.     return S_OK;
  2446. }
  2447.  
  2448. STDMETHODIMP CXmppCommCtrl::SendEmotiphon(int iChatID, BSTR bstrJid, BSTR bstrEmotiphon)
  2449. {
  2450.     CHECK_LOGIN();
  2451.     string sJid = ToBareJid(ToStringA(bstrJid));
  2452.     if (sJid.empty())
  2453.         return ThrowError("ERROR: Please select a User Name.");
  2454.     string sEmotiphon = ToStringU8(bstrEmotiphon);
  2455.     if (sEmotiphon.empty())
  2456.         return ThrowError("ERROR: Empty emotiphon.");
  2457.  
  2458.     m_pJabberStream->m_pJabberMessage->jabber_send_emotiphon(iChatID, sJid, sEmotiphon);
  2459.     return S_OK;
  2460. }
  2461.  
  2462. STDMETHODIMP CXmppCommCtrl::get_SeeContactState(BSTR bstrJid, VARIANT_BOOL *pVal)
  2463. {
  2464.     CHECK_LOGIN();
  2465.     CHECK_POINTER(pVal);
  2466.     string sJid = ToBareJid(ToStringA(bstrJid));
  2467.     if (sJid.empty())
  2468.         return ThrowError("ERROR: Please select a User Name.");
  2469.  
  2470.     *pVal = ToVB(m_pJabberStream->m_pJabberPrivacy->GetSeeContactState(sJid));
  2471.     return S_OK;
  2472. }
  2473.  
  2474. STDMETHODIMP CXmppCommCtrl::put_SeeContactState(BSTR bstrJid, VARIANT_BOOL newVal)
  2475. {
  2476.     CHECK_LOGIN();
  2477.     string sJid = ToBareJid(ToStringA(bstrJid));
  2478.     if (sJid.empty())
  2479.         return ThrowError("ERROR: Please select a User Name.");
  2480.  
  2481.     m_pJabberStream->m_pJabberPrivacy->SetSeeContactState(sJid, ToBOOL(newVal));
  2482.     return S_OK;
  2483. }
  2484.  
  2485. STDMETHODIMP CXmppCommCtrl::get_BlockContactMessage(BSTR bstrJid, VARIANT_BOOL *pVal)
  2486. {
  2487.     CHECK_LOGIN();
  2488.     CHECK_POINTER(pVal);
  2489.     string sJid = ToBareJid(ToStringA(bstrJid));
  2490.     if (sJid.empty())
  2491.         return ThrowError("ERROR: Please select a User Name.");
  2492.  
  2493.     *pVal = ToVB(m_pJabberStream->m_pJabberPrivacy->GetBlockContactMessage(sJid));
  2494.     return S_OK;
  2495. }
  2496.  
  2497. STDMETHODIMP CXmppCommCtrl::put_BlockContactMessage(BSTR bstrJid, VARIANT_BOOL newVal)
  2498. {
  2499.     CHECK_LOGIN();
  2500.     string sJid = ToBareJid(ToStringA(bstrJid));
  2501.     if (sJid.empty())
  2502.         return ThrowError("ERROR: Please select a User Name.");
  2503.  
  2504.     m_pJabberStream->m_pJabberPrivacy->SetBlockContactMessage(sJid, ToBOOL(newVal));
  2505.     return S_OK;
  2506. }
  2507.  
  2508. STDMETHODIMP CXmppCommCtrl::get_AllowViewMyState(BSTR bstrJid, VARIANT_BOOL *pVal)
  2509. {
  2510.     CHECK_LOGIN();
  2511.     CHECK_POINTER(pVal);
  2512.     string sJid = ToBareJid(ToStringA(bstrJid));
  2513.     if (sJid.empty())
  2514.         return ThrowError("ERROR: Please select a User Name.");
  2515.  
  2516.     *pVal = ToVB(m_pJabberStream->m_pJabberPrivacy->GetAllowViewMyState(sJid));
  2517.     return S_OK;
  2518. }
  2519.  
  2520. STDMETHODIMP CXmppCommCtrl::put_AllowViewMyState(BSTR bstrJid, VARIANT_BOOL newVal)
  2521. {
  2522.     CHECK_LOGIN();
  2523.     string sJid = ToBareJid(ToStringA(bstrJid));
  2524.     if (sJid.empty())
  2525.         return ThrowError("ERROR: Please select a User Name.");
  2526.  
  2527.     m_pJabberStream->m_pJabberPrivacy->SetAllowViewMyState(sJid, ToBOOL(newVal));
  2528.     return S_OK;
  2529. }
  2530.  
  2531. STDMETHODIMP CXmppCommCtrl::get_Version(BSTR *pVal)
  2532. {
  2533.     CHECK_POINTER(pVal);
  2534.     BstrFromString(pVal, m_pJabberStream->m_sVersion);
  2535.     return S_OK;
  2536. }
  2537.  
  2538. STDMETHODIMP CXmppCommCtrl::put_Version(BSTR newVal)
  2539. {
  2540.     CHECK_NOT_LOGGEDIN();
  2541.  
  2542.     string sVersion = ToStringA(newVal);
  2543.     if (sVersion.empty())
  2544.         return ThrowError("ERROR: Empty version number.");
  2545.  
  2546.     m_pJabberStream->m_sVersion = sVersion;
  2547.     return S_OK;
  2548. }
  2549.  
  2550. STDMETHODIMP CXmppCommCtrl::get_SignalPort(int *pVal)
  2551. {
  2552.     CHECK_POINTER(pVal);
  2553.     *pVal = 0;
  2554.     m_pJabberStream->Log("get_SignalPort not supported");
  2555.     return S_OK;
  2556. }
  2557.  
  2558. STDMETHODIMP CXmppCommCtrl::put_SignalPort(int newVal)
  2559. {
  2560.     CHECK_NOT_LOGGEDIN();
  2561.     m_pJabberStream->Log("put_SignalPort not supported");
  2562.     return S_OK;
  2563. }
  2564.  
  2565. #ifdef USE_VARIANT_IN_EVENT
  2566. STDMETHODIMP CXmppCommCtrl::GetContactListInGroup(BSTR bstrGroupName, SAFEARRAY **pVal)
  2567. #else
  2568. STDMETHODIMP CXmppCommCtrl::GetContactListInGroup(BSTR bstrGroupName, std::vector<std::string> *pVal)
  2569. #endif
  2570. {
  2571.     CHECK_LOGIN();
  2572.     CHECK_POINTER(pVal);
  2573.  
  2574.     string sGroupName = ToStringU8(bstrGroupName);
  2575.     if (sGroupName.empty())
  2576.         return ThrowError("ERROR: Empty group name.");
  2577.  
  2578.     ListofString ls;
  2579.     m_pJabberStream->m_pJabberBuddy->GetContactListInGroup(sGroupName, ls);
  2580.  
  2581.     ListofString::const_iterator iter = ls.begin();
  2582.  
  2583. #ifdef USE_VARIANT_IN_EVENT
  2584.     BstrArray aContacts(ls.size());
  2585.     int nIndex = 0;
  2586.     for (; iter != ls.end(); ++iter)
  2587.     {
  2588.         aContacts.PutString(nIndex++, *iter);
  2589.     }
  2590.  
  2591.     aContacts.Detach(pVal);
  2592. #else
  2593.     pVal->clear();
  2594.     for(; iter != ls.end(); iter++)
  2595.     {
  2596.         pVal->push_back(*iter);
  2597.     }
  2598. #endif
  2599.     return S_OK;
  2600. }
  2601.  
  2602. STDMETHODIMP CXmppCommCtrl::ChangeGroupName(BSTR bstrJid, BSTR bstrOldGroupName, BSTR bstrNewGroupName)
  2603. {
  2604.     CHECK_LOGIN();
  2605.     string sOldGroupName = ToStringU8(bstrOldGroupName);
  2606.     string sNewGroupName = ToStringU8(bstrNewGroupName);
  2607.  
  2608.     if (sOldGroupName.empty() || sNewGroupName.empty())
  2609.         return ThrowError("ERROR: Empty group name");
  2610.  
  2611.     string sJid = ToBareJid(ToStringA(bstrJid));
  2612.  
  2613.     m_pJabberStream->m_pJabberRoster->ChangeGroupName(sJid, sOldGroupName, sNewGroupName);
  2614.     return S_OK;
  2615. }
  2616.  
  2617. STDMETHODIMP CXmppCommCtrl::get_KeepAlivePeriod(int *pVal)
  2618. {
  2619.     CHECK_POINTER(pVal);
  2620.     *pVal = m_iKeepAlivePeriod;
  2621.     return S_OK;
  2622. }
  2623.  
  2624. STDMETHODIMP CXmppCommCtrl::put_KeepAlivePeriod(int newVal)
  2625. {
  2626.     if (newVal <= 0)
  2627.         newVal = 0;
  2628.  
  2629.     m_pJabberStream->Log("Setting keep alive period to " + tostring(newVal));
  2630.     m_iConsecutiveKeepalives = 0;
  2631.     m_iKeepAlivePeriod = newVal;
  2632.     if (m_iKeepAliveTimer)
  2633.     {
  2634.         KillTimer(m_iKeepAliveTimer);
  2635.         m_iKeepAliveTimer = 0;
  2636.     }
  2637.     if (m_iKeepAlivePeriod)
  2638.     {
  2639.         m_iKeepAliveTimer = SetTimer(KEEP_ALIVE_TIMER, m_iKeepAlivePeriod*1000);
  2640.     }
  2641.     return S_OK;
  2642. }
  2643.  
  2644. STDMETHODIMP CXmppCommCtrl::SendPresence(BSTR bstrJid)
  2645. {
  2646.     CHECK_LOGIN();
  2647.     string sJid = ToFullJid(ToStringA(bstrJid));
  2648.     if (sJid.empty())
  2649.         return ThrowError("ERROR: Please select a User Name.");
  2650.  
  2651.     m_pJabberStream->m_pJabberPresence->SendPresence(sJid);
  2652.     return S_OK;
  2653. }
  2654.  
  2655. STDMETHODIMP CXmppCommCtrl::ContinueLogin()
  2656. {
  2657.     m_pJabberStream->m_pJabberIQ->jabber_iq_accept_prefs();
  2658.     return S_OK;
  2659. }
  2660.  
  2661. #ifdef USE_VARIANT_IN_EVENT
  2662. STDMETHODIMP CXmppCommCtrl::SendExitChat(int iChatID, VARIANT vJID)
  2663. #else
  2664. STDMETHODIMP CXmppCommCtrl::SendExitChat(int iChatID, const std::vector<std::string> &vJID)
  2665. #endif
  2666. {
  2667. #ifdef USE_VARIANT_IN_EVENT
  2668.     BstrArray aJid;
  2669.     aJid.Attach(&vJID);
  2670.     int iSize = aJid.GetSize();
  2671. #else
  2672.     int iSize = vJID.size();
  2673. #endif
  2674.     if (iSize == 0)
  2675.         return ThrowError("ERROR: Empty recipient.");
  2676.  
  2677.     SetofString ss;
  2678.     for (int i = 0; i < iSize; i++)
  2679.     {
  2680. #ifdef USE_VARIANT_IN_EVENT
  2681.         ss.insert(ToFullJid(ToStringA(aJid.GetBstr(i))));
  2682. #else
  2683.         ss.insert(ToFullJid(ToStringA(vJID[i])));
  2684. #endif
  2685.     }
  2686.  
  2687. #ifdef USE_VARIANT_IN_EVENT
  2688.     aJid.Detach();
  2689. #endif
  2690.  
  2691.     m_pJabberStream->m_pJabberMessage->jabber_send_exit_chat(iChatID, ss);
  2692.     return S_OK;
  2693. }
  2694.  
  2695.  
  2696. STDMETHODIMP CXmppCommCtrl::get_HashedPassword(BSTR* pVal)
  2697. {
  2698.     CHECK_LOGIN();
  2699.     CHECK_POINTER(pVal);
  2700.     BstrFromString(pVal, m_pJabberStream->m_pJabberAuth->GetHashedPassword());
  2701.     return S_OK;
  2702. }
  2703.  
  2704. STDMETHODIMP CXmppCommCtrl::put_HashedPassword(BSTR newVal)
  2705. {
  2706.     if (m_pJabberStream->m_StreamState == JABBER_STREAM_CONNECTED)
  2707.         return ThrowError("ERROR: Already loggin.");
  2708.  
  2709.     m_pJabberStream->m_pJabberAuth->SetHashedPassword(ToStringA(newVal));
  2710.     return S_OK;
  2711. }
  2712.  
  2713. STDMETHODIMP CXmppCommCtrl::StorePrivateData(BSTR bstrName, BSTR bstrNameSpace, BSTR bstrData)
  2714. {
  2715.     CHECK_LOGIN();
  2716.     string sName = ToStringA(bstrName);
  2717.     string sNameSpace = ToStringA(bstrNameSpace);
  2718.     string sData = ToStringU8(bstrData);
  2719.     if (sName.empty() || sNameSpace.empty() || sData.empty())
  2720.         return ThrowError("ERROR: Empty string.");
  2721.  
  2722.     m_pJabberStream->m_pJabberIQ->StorePrivateData(sName, sNameSpace, sData);
  2723.     return S_OK;
  2724. }
  2725.  
  2726. STDMETHODIMP CXmppCommCtrl::RetrievePrivateData(BSTR bstrName, BSTR bstrNameSpace)
  2727. {
  2728.     CHECK_LOGIN();
  2729.     string sName = ToStringA(bstrName);
  2730.     string sNameSpace = ToStringA(bstrNameSpace);
  2731.     if (sName.empty() || sNameSpace.empty())
  2732.         return ThrowError("ERROR: Empty string.");
  2733.  
  2734.     m_pJabberStream->m_pJabberIQ->RetrievePrivateData(sName, sNameSpace);
  2735.     return S_OK;
  2736. }
  2737.  
  2738. STDMETHODIMP CXmppCommCtrl::SendPresence2(BSTR bstrJid, BSTR bstrState, BSTR bstrStatus)
  2739. {
  2740.     CHECK_LOGIN();
  2741.     string sJid = ToFullJid(ToStringA(bstrJid));
  2742.     if (sJid.empty())
  2743.         return ThrowError("ERROR: Please select a User Name");
  2744.  
  2745.     string sState = ToStringA(bstrState);
  2746.     if (sState.empty())
  2747.         return ThrowError("ERROR: Empty state.");
  2748.  
  2749.     m_pJabberStream->m_pJabberPresence->SendPresence2(sJid, sState, ToStringU8(bstrStatus));
  2750.     return S_OK;
  2751. }
  2752.  
  2753. STDMETHODIMP CXmppCommCtrl::SendFile(
  2754.     BSTR bstrJid,
  2755.     BSTR bstrFileName,
  2756.     int* pVal)
  2757. {
  2758.     CHECK_LOGIN();
  2759.     CHECK_POINTER(pVal);
  2760.  
  2761.     string sJid = ToFullJid(ToStringA(bstrJid));
  2762.     if (sJid.empty())
  2763.     {
  2764.         return ThrowError("ERROR: Please select a User Name.");
  2765.     }
  2766.  
  2767.     int nFileId = GetNextFileId();
  2768.  
  2769.     // SendFileHelper takes wide-byte string as file name
  2770.     string sErrorMsg = SendFileHelper(sJid, ToString(bstrFileName), nFileId);
  2771.  
  2772.     if (!sErrorMsg.empty())
  2773.     {
  2774.         return ThrowError(sErrorMsg);
  2775.     }
  2776.  
  2777.     *pVal = nFileId;
  2778.  
  2779.     return S_OK;
  2780. }
  2781.  
  2782. STDMETHODIMP CXmppCommCtrl::AcceptFileTransfer(int nFileId, BSTR bstrFileName, VARIANT_BOOL bAccept)
  2783. {
  2784. //  CHECK_LOGIN();
  2785. #ifndef NO_FILE_TRANSFER
  2786.     bool bIsAccept = (bAccept == VARIANT_TRUE);
  2787.  
  2788.     FtContainer* pFt;
  2789.     FtContainerMap::iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  2790.     if (iter == m_FtContainerMap.end())
  2791.     {
  2792.         return ThrowError(E_INVALID_FILE_ID);
  2793.     }
  2794.  
  2795.     if (iter->second.m_uState == FTS_ABORTED)
  2796.     {
  2797.         return ThrowError(E_FILE_ABORTED);
  2798.     }
  2799.  
  2800.     string sId = iter->first;
  2801.     pFt = &(iter->second);
  2802.  
  2803.     if (pFt->m_bFileSender)
  2804.     {
  2805.         return ThrowError(E_NOT_FILE_RECEIVER);
  2806.     }
  2807.  
  2808.     tstring sPathName = ToString(bstrFileName); // this string is not used to be sent through XMPP,
  2809.                                                 // so it can be wide byte
  2810.  
  2811.     if (bIsAccept)
  2812.     {
  2813.         string sDisplayName = GetContactDisplayName(iter->second.m_sUserId);
  2814.         tstring sFileName = iter->second.m_fti.m_sFileName;
  2815.  
  2816.         if (sPathName.empty())
  2817.         {
  2818.             tstring sTitle = tstring("Receive File from ") + tstring(sDisplayName);
  2819.  
  2820.             sPathName = PromptFileDlg(sTitle, sFileName, false);
  2821.  
  2822.             if (sPathName.empty())
  2823.             {
  2824.                 bIsAccept = false;
  2825.             }
  2826.         }
  2827.     }
  2828.  
  2829.     string sAnswerSDP;
  2830.  
  2831.     if (bIsAccept)
  2832.     {
  2833.         CreateFtReceiver(pFt->m_sUserId, nFileId, *pFt);
  2834.         UpdateReceiverParams(*pFt, sPathName);
  2835.         sAnswerSDP = pFt->m_pFileReceiver->GetFileTransferInfo().m_sLocalSDP;
  2836.         if (sAnswerSDP.empty())
  2837.         {
  2838.             bIsAccept = false;
  2839.         }
  2840.  
  2841.         pFt->m_pFileReceiver->Log("reply Xmpp response to " + pFt->m_sUserId);
  2842.         pFt->m_pFileReceiver->Log("Receiver SDP:\r\n " + sAnswerSDP);
  2843.         pFt->m_pFileReceiver->Log("remote SDP:\r\n " + pFt->m_fti.m_sRemoteSDP);
  2844.     }
  2845.  
  2846.     if (!bIsAccept)
  2847.     {
  2848.         iter->second.m_uState = FTS_ABORTED;
  2849.     }
  2850.  
  2851. #ifndef MESSAGE_FILE_TRANSFER
  2852. #ifdef JINGLE_FILE_TRANSFER
  2853.     m_pJabberStream->m_pJabberIQ->FileTransferResponse(pFt->m_sUserId, sId.c_str(), itoa(nFileId), sAnswerSDP, bIsAccept, *pFt);
  2854. #else
  2855.     string sPrimaryAddr = "";
  2856.     string sSecondaryAddr = "";
  2857.     int nPrimaryPort = 0;
  2858.     int nSecondaryPort = 0;
  2859.     m_pJabberStream->m_pJabberIQ->FileTransferResponse(pFt->m_sUserId, iter->first, itoa(nFileId), sPrimaryAddr, nPrimaryPort, sSecondaryAddr, nSecondaryPort, bIsAccept);
  2860. #endif
  2861. #else
  2862.     m_pJabberStream->m_pJabberMessage->FileTransferResponse(pFt->m_sUserId, sId.c_str(), itoa(nFileId), sAnswerSDP, bIsAccept, *pFt);
  2863. #endif
  2864. #endif
  2865.  
  2866.     return S_OK;
  2867. }
  2868.  
  2869. STDMETHODIMP CXmppCommCtrl::CancelFileTransfer(int nFileId)
  2870. {
  2871. #ifndef NO_FILE_TRANSFER
  2872. //  CHECK_LOGIN();
  2873.  
  2874.     FtContainerMap::iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  2875.     if (iter == m_FtContainerMap.end())
  2876.     {
  2877.         return ThrowError(E_INVALID_FILE_ID);
  2878.     }
  2879.  
  2880.     FtContainer& fts = iter->second;
  2881.  
  2882.     // Should not cancel in these states
  2883.     switch (fts.m_uState)
  2884.     {
  2885.     case FTS_UNKNOWN:
  2886.     case FTS_ERROR:
  2887.     case FTS_ABORTED:
  2888.     case FTS_REQUEST_REJECTED:
  2889.     case FTS_SEND_COMPLETE:
  2890.     case FTS_RECEIVE_COMPLETE:
  2891.         return S_OK;
  2892.     }
  2893.  
  2894.     fts.m_uState = FTS_ABORTED;
  2895.     CloseFtContainer(fts);
  2896.  
  2897. #ifndef MESSAGE_FILE_TRANSFER
  2898.     m_pJabberStream->m_pJabberIQ->FileTransferCancel(fts.m_sUserId, iter->first);
  2899. #else
  2900.     m_pJabberStream->m_pJabberMessage->FileTransferCancel(fts.m_sUserId, iter->first);
  2901. #endif
  2902. #endif
  2903.     return S_OK;
  2904. }
  2905.  
  2906. STDMETHODIMP CXmppCommCtrl::GetTransferFile(int nFileId, BSTR* pVal)
  2907. {
  2908. //  CHECK_LOGIN();
  2909.     CHECK_POINTER(pVal);
  2910.  
  2911.     FtContainerMap::iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  2912.     if (iter != m_FtContainerMap.end())
  2913.     {
  2914.         tstring sPathName = iter->second.m_fti.m_sFileName;
  2915.         tstring sDirectory = iter->second.m_fti.m_sDirectory;
  2916.         if (!sDirectory.empty())
  2917.         {
  2918. #ifdef __unix__
  2919.             sPathName = sDirectory + tstring("/") + sPathName;
  2920. #else
  2921.             sPathName = sDirectory + tstring("\\") + sPathName;
  2922. #endif
  2923.         }
  2924.  
  2925.         BstrFromString(pVal, sPathName.mbs());
  2926.     }
  2927.     else
  2928.     {
  2929.         return ThrowError(E_INVALID_FILE_ID);
  2930.     }
  2931.  
  2932.     return S_OK;
  2933. }
  2934.  
  2935. STDMETHODIMP CXmppCommCtrl::GetTransferPartner(int nFileId, BSTR* pVal)
  2936. {
  2937. //  CHECK_LOGIN();
  2938.     CHECK_POINTER(pVal);
  2939.  
  2940.     FtContainerMap::const_iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  2941.     if (iter == m_FtContainerMap.end())
  2942.         return ThrowError(E_INVALID_FILE_ID);
  2943.  
  2944.     BstrFromStringU8(pVal, (iter->second).m_sUserId);
  2945.  
  2946.     return S_OK;
  2947. }
  2948.  
  2949. STDMETHODIMP CXmppCommCtrl::GetTransferState(int nFileId, BSTR* pVal)
  2950. {
  2951. //  CHECK_LOGIN();
  2952.     CHECK_POINTER(pVal);
  2953.  
  2954.     FtContainerMap::const_iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  2955.     if (iter == m_FtContainerMap.end())
  2956.         return ThrowError(E_INVALID_FILE_ID);
  2957.  
  2958.     BstrFromString(pVal, GetStateString((iter->second).m_uState));
  2959.  
  2960.     return S_OK;
  2961. }
  2962.  
  2963. STDMETHODIMP CXmppCommCtrl::GetTransferProgress(int nFileId, int* pVal)
  2964. {
  2965. //  CHECK_LOGIN();
  2966.     CHECK_POINTER(pVal);
  2967. #ifndef NO_FILE_TRANSFER
  2968.     TransferStats stats;
  2969.     *pVal = 0;
  2970.     FtContainerMap::const_iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  2971.     if (iter == m_FtContainerMap.end())
  2972.         return ThrowError(E_INVALID_FILE_ID);
  2973.  
  2974.     const FtContainer& fts = iter->second;
  2975.  
  2976.     if (NULL != fts.m_pFileSender.get())
  2977.     {
  2978.         fts.m_pFileSender->GetTransferStats(stats);
  2979.     }
  2980.     else if (NULL != fts.m_pFileReceiver.get())
  2981.     {
  2982.         fts.m_pFileReceiver->GetTransferStats(stats);
  2983.     }
  2984.     else
  2985.     {
  2986.         return S_FALSE;
  2987.     }
  2988.  
  2989.     int nPercent = 0;
  2990.  
  2991.     switch (fts.m_uState)
  2992.     {
  2993.     case FTS_RECEIVE_COMPLETE:
  2994.     case FTS_SEND_COMPLETE:
  2995.         nPercent = 100;
  2996.  
  2997.     case FTS_RECEIVING:
  2998.     case FTS_SENDING:
  2999.         break;
  3000.  
  3001.     default:
  3002.         return S_FALSE;
  3003.     }
  3004.  
  3005.     if(stats.m_bTransferComplete || stats.m_bForcedTransferComplete)
  3006.         nPercent = 100;
  3007.  
  3008.     if (0 == nPercent && stats.m_dwCurrentBytes == 0)
  3009.         return S_FALSE;
  3010.  
  3011.     if (0 == nPercent && stats.m_dwTotalBytes == 0)
  3012.         return S_FALSE;
  3013.  
  3014. #if 0
  3015.     int nTotalTime = 0;
  3016.  
  3017.     if (stats.m_bTransferComplete || stats.m_bForcedTransferComplete)
  3018.     {
  3019.         nTotalTime = stats.m_dwEndTime - stats.m_dwStartTime;
  3020.     }
  3021.     else
  3022.     {
  3023.         nTotalTime = stats.m_dwCurrentTime - stats.m_dwStartTime;
  3024.     }
  3025.  
  3026.     if (0 == nPercent && nTotalTime <= 0){
  3027.         return S_FALSE;
  3028.     }
  3029. #endif
  3030.  
  3031.     if(0 == nPercent)
  3032.         nPercent = (int)PERCENT(stats.m_dwCurrentBytes, stats.m_dwTotalBytes);
  3033.     if (100 == nPercent)
  3034.     {
  3035.         // avoid displaying 100%
  3036.         nPercent = 99;
  3037.     }
  3038.     *pVal = nPercent;
  3039. #endif
  3040.     return S_OK;
  3041. }
  3042.  
  3043. STDMETHODIMP CXmppCommCtrl::GetTransferSize(int nFileId, int* pVal)
  3044. {
  3045. //  CHECK_LOGIN();
  3046.     CHECK_POINTER(pVal);
  3047.  
  3048.     FtContainerMap::const_iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  3049.     if (iter == m_FtContainerMap.end())
  3050.         return ThrowError(E_INVALID_FILE_ID);
  3051.  
  3052.     *pVal = (iter->second).m_uFileSize;
  3053.  
  3054.     return S_OK;
  3055. }
  3056.  
  3057. STDMETHODIMP CXmppCommCtrl::IsInbound(int nFileId, VARIANT_BOOL* pVal)
  3058. {
  3059. //  CHECK_LOGIN();
  3060.     CHECK_POINTER(pVal);
  3061.  
  3062.     FtContainerMap::iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  3063.     if (iter != m_FtContainerMap.end())
  3064.     {
  3065.         bool bIsSender = iter->second.m_bFileSender;
  3066.         *pVal = ToVB(!bIsSender);
  3067.     }
  3068.     else
  3069.     {
  3070.         return ThrowError(E_INVALID_FILE_ID);
  3071.     }
  3072.  
  3073.     return S_OK;
  3074. }
  3075.  
  3076. STDMETHODIMP CXmppCommCtrl::get_FileTransferPort(int *pVal)
  3077. {
  3078. //  CHECK_POINTER(pVal);
  3079.  
  3080.     *pVal = 0; //m_nFileTransferPort;
  3081.  
  3082.     return S_OK;
  3083. }
  3084.  
  3085. STDMETHODIMP CXmppCommCtrl::put_FileTransferPort(int newVal)
  3086. {
  3087. //  m_nFileTransferPort = newVal;
  3088.  
  3089.     return S_OK;
  3090. }
  3091.  
  3092. STDMETHODIMP CXmppCommCtrl::RequestFile(
  3093.     BSTR bstrJid,
  3094.     BSTR bstrFileName,
  3095.     int* pVal)
  3096. {
  3097. #ifndef NO_FILE_TRANSFER
  3098.     CHECK_LOGIN();
  3099.     CHECK_POINTER(pVal);
  3100.  
  3101.     string sJid = ToFullJid(ToStringA(bstrJid));
  3102.     if (sJid.empty())
  3103.     {
  3104.         return ThrowError("ERROR: Please select a User Name.");
  3105.     }
  3106.  
  3107.     tstring sFileName = ToStringU8(bstrFileName);
  3108.  
  3109.     int nFileId = GetNextFileId();
  3110.  
  3111.     FtContainer ftContainer;
  3112.     ftContainer.m_fti.m_sFileName = sFileName;
  3113.     ftContainer.m_fti.m_uFileType = FileTransferInfo::GENERIC_FILE;
  3114.     ftContainer.m_fti.m_sDetails = "";
  3115.     ftContainer.m_fti.m_uTransferId = nFileId;
  3116.     ftContainer.m_sUserId = sJid;
  3117.     ftContainer.m_uState = FTS_SENT_REQUEST;
  3118.  
  3119.     PostMessage(WM_UPDATE_FILE, ftContainer.m_fti.m_uTransferId, 0);
  3120.  
  3121.     ftContainer.m_bFileSender = true;
  3122.     ftContainer.m_bFilePull = true;
  3123.     m_pJabberStream->m_pJabberMessage->SendRequestFile(sJid, sFileName, "filetransfer",
  3124.         itoa(nFileId), ftContainer);
  3125.  
  3126.     *pVal = nFileId;
  3127. #endif
  3128.  
  3129.     return S_OK;
  3130. }
  3131.  
  3132. STDMETHODIMP CXmppCommCtrl::AcceptFileRequest(int nFileId, BSTR bstrFileName, VARIANT_BOOL bAccept)
  3133. {
  3134. //  CHECK_LOGIN();
  3135.  
  3136.     bool bIsAccept = Tobool(bAccept);
  3137. //  bIsAccept = false;
  3138.  
  3139.     FtContainer* pFt;
  3140.     FtContainerMap::iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  3141.     if (iter == m_FtContainerMap.end())
  3142.     {
  3143.         return ThrowError(E_INVALID_FILE_ID);
  3144.     }
  3145.  
  3146.     string sId = iter->first;
  3147.     pFt = &(iter->second);
  3148.  
  3149.     if (bIsAccept)
  3150.     {
  3151. //      string sPathName = ToStringU8(bstrFileName);
  3152.         // SendFileHelper takes wide-byte string as file name
  3153.         tstring sPathName = ToString(bstrFileName);
  3154.         string sErrorMsg = SendFileHelper(pFt->m_sUserId, sPathName, nFileId);
  3155.         if (!sErrorMsg.empty())
  3156.         {
  3157.             bIsAccept = false;
  3158.         }
  3159.     }
  3160.  
  3161.     if (!bIsAccept)
  3162.     {
  3163.         m_pJabberStream->m_pJabberMessage->FileTransferCancel(pFt->m_sUserId, itoa(nFileId));
  3164.     }
  3165.     return S_OK;
  3166. }
  3167.  
  3168. #ifndef NO_PROXY_IN_XMPP
  3169. STDMETHODIMP CXmppCommCtrl::GetHttpProxyAddr(BSTR* pVal)
  3170. {
  3171.     CHECK_POINTER(pVal);
  3172.  
  3173.     string sProxyHost = m_pAFEngine->GetHTTPProxy(
  3174. #if (AF_DLL_VERSION > 9600000)
  3175.         m_iAFEServerStoreID
  3176. #endif
  3177.         );
  3178.     BstrFromString(pVal, m_pAFEngine->GetHostAddress(sProxyHost));
  3179.  
  3180.     return S_OK;
  3181. }
  3182.  
  3183. STDMETHODIMP CXmppCommCtrl::GetHttpProxyPort(int* pVal)
  3184. {
  3185.     CHECK_POINTER(pVal);
  3186.  
  3187.     string sProxyHost = m_pAFEngine->GetHTTPProxy(
  3188. #if (AF_DLL_VERSION > 9600000)
  3189.         m_iAFEServerStoreID
  3190. #endif
  3191.         );
  3192.     *pVal = m_pAFEngine->GetHostPort(sProxyHost);
  3193.  
  3194.     return S_OK;
  3195. }
  3196.  
  3197. STDMETHODIMP CXmppCommCtrl::SetHttpProxyAuthentication(BSTR bstrUserName, BSTR bstrPassword, BSTR bstrDomain)
  3198. {
  3199.     string sUsername = ToStringA(bstrUserName);
  3200.     string sPassword = ToStringA(bstrPassword);
  3201.     string sDomain   = ToStringA(bstrDomain);
  3202.  
  3203.     m_pAFEngine->SetHTTPProxy(
  3204. #if (AF_DLL_VERSION > 9600000)
  3205.         m_iAFEServerStoreID,
  3206. #endif
  3207.         m_pAFEngine->GetHTTPProxy(
  3208. #if (AF_DLL_VERSION > 9600000)
  3209.         m_iAFEServerStoreID
  3210. #endif
  3211.         ),
  3212.         sUsername,
  3213.         sPassword,
  3214.         sDomain);
  3215.  
  3216.     return S_OK;
  3217. }
  3218.  
  3219. STDMETHODIMP CXmppCommCtrl::GetHttpProxyUserName(BSTR* pVal)
  3220. {
  3221.     CHECK_POINTER(pVal);
  3222.  
  3223.     BstrFromString(pVal, m_pAFEngine->GetHTTPProxyUsername(
  3224. #if (AF_DLL_VERSION > 9600000)
  3225.         m_iAFEServerStoreID
  3226. #endif
  3227.         ));
  3228.  
  3229.     return S_OK;
  3230. }
  3231.  
  3232. STDMETHODIMP CXmppCommCtrl::GetHttpProxyPassword(BSTR* pVal)
  3233. {
  3234.     CHECK_POINTER(pVal);
  3235.  
  3236.     BstrFromString(pVal, m_pAFEngine->GetHTTPProxyPassword(
  3237. #if (AF_DLL_VERSION > 9600000)
  3238.         m_iAFEServerStoreID
  3239. #endif
  3240.         ));
  3241.  
  3242.     return S_OK;
  3243. }
  3244.  
  3245. STDMETHODIMP CXmppCommCtrl::GetHttpProxyDomain(BSTR* pVal)
  3246. {
  3247.     CHECK_POINTER(pVal);
  3248.  
  3249.     BstrFromString(pVal, m_pAFEngine->GetHTTPProxyDomain(
  3250. #if (AF_DLL_VERSION > 9600000)
  3251.         m_iAFEServerStoreID
  3252. #endif
  3253.         ));
  3254.  
  3255.     return S_OK;
  3256. }
  3257. #endif  // NO_PROXY_IN_XMPP
  3258.  
  3259. void CXmppCommCtrl::AddFTEntry(const string& sKey, FtContainer& ft)
  3260. {
  3261.     m_FtContainerMap[sKey] = ft;
  3262. }
  3263.  
  3264. void CXmppCommCtrl::RemoveFTEntry(const string& sKey)
  3265. {
  3266.     FtContainerMap::iterator iter = m_FtContainerMap.find(sKey);
  3267.     if (iter != m_FtContainerMap.end())
  3268.     {
  3269.         m_FtContainerMap.erase(iter);
  3270. //      CloseFtContainer(iter->second);
  3271.     }
  3272. }
  3273.  
  3274. void CXmppCommCtrl::FileTransferAccepted(int nFileId)
  3275. {
  3276. #ifndef NO_FILE_TRANSFER
  3277.     FtContainer* pFt;
  3278.     FtContainerMap::iterator iter = m_FtContainerMap.FindTransferId(nFileId);
  3279.     if (iter != m_FtContainerMap.end())
  3280.     {
  3281.         pFt = &(iter->second);
  3282.         if (pFt->m_uState == FTS_SENT_REQUEST)
  3283.         {
  3284.             pFt->m_uState = FTS_REQUEST_ACCEPTED;
  3285. #ifdef __unix__
  3286.             m_pJabberStream->m_pXmppComm->PostMessage(WM_UPDATE_FILE, nFileId, 0);
  3287. #else
  3288.             ::PostMessage(m_pJabberStream->m_pXmppComm->m_hWnd, WM_UPDATE_FILE, nFileId, 0);
  3289. #endif
  3290.  
  3291.             if (pFt->m_pFileSender.get())
  3292.             {
  3293.                 pFt->m_pFileSender->Log("File Transfer Accepted.");
  3294.                 pFt->m_pFileSender->SetFileTransferInfo(pFt->m_fti);
  3295.  
  3296.                 pFt->m_pFileSender->Log("Remote SDP: \r\n" + pFt->m_fti.m_sRemoteSDP);
  3297.                 //pFt->m_uState = FTS_SEND_CONNECTING;
  3298.                 pFt->m_pFileSender->RudpConnect(pFt->m_fti.m_sRemoteSDP);
  3299.                 pFt->m_pFileSender->Log("Rudp Connect");
  3300.             }
  3301.         }
  3302.     }
  3303. #endif
  3304. }
  3305.  
  3306. int CXmppCommCtrl::GetNextFileId()
  3307. {
  3308.     if (m_nNextFileId == INT_MAX)
  3309.     {
  3310.         m_nNextFileId = rand();
  3311.         return GetNextFileId();
  3312.     }
  3313.     return m_nNextFileId++;
  3314. }
  3315.  
  3316. FtContainer CXmppCommCtrl::CreateFtSender(
  3317.     const string& sJid,
  3318.     const tstring& sPathName,
  3319.     int nFileId,
  3320.     u_int16_t uFileType,
  3321.     const string& sSubject)
  3322. {
  3323.     FtContainer ftContainer;
  3324. #ifndef NO_FILE_TRANSFER
  3325.     ftContainer.m_pFileSender.reset(new FileSender);
  3326.     ftContainer.m_pFileSender->SetAFEngine(m_pAFEngine, m_iAFEServerStoreID);
  3327.     ftContainer.m_pFileObserver.reset(new WindowObserver);
  3328. #ifdef __unix__
  3329.     ftContainer.m_pFileObserver->Init(this, WM_UPDATE_FILE, nFileId);
  3330. #else
  3331.     ftContainer.m_pFileObserver->Init(m_hWnd, WM_UPDATE_FILE, nFileId);
  3332. #endif
  3333.     ftContainer.m_pFileSender->Attach(ftContainer.m_pFileObserver.get());
  3334.  
  3335.     ftContainer.m_fti.m_sDirectory = GetDirName(sPathName);
  3336.  
  3337.     ftContainer.m_fti.m_sFileName = GetFileName(sPathName);
  3338.  
  3339.     ftContainer.m_fti.m_uFileType = uFileType;
  3340.  
  3341.     ftContainer.m_fti.m_sDetails = sSubject;
  3342.  
  3343.     ftContainer.m_fti.m_uTransferId = nFileId;
  3344.  
  3345.     ftContainer.m_bFileSender = true;
  3346.  
  3347.     ftContainer.m_pFileSender->OpenLogFile(ftContainer.m_fti.m_sFileName);
  3348.  
  3349.     ftContainer.m_pFileSender->SetFileTransferInfo(ftContainer.m_fti);
  3350.  
  3351.     ftContainer.m_uState = FTS_SENT_REQUEST;
  3352.  
  3353.     PostMessage(WM_UPDATE_FILE, ftContainer.m_fti.m_uTransferId, 0);
  3354.  
  3355.     ftContainer.m_sUserId = sJid;
  3356. #endif
  3357.     return ftContainer;
  3358. }
  3359.  
  3360. void CXmppCommCtrl::CreateFtReceiver(
  3361.     const string& sJid,
  3362.     int nFileId,
  3363.     FtContainer& ftContainer)
  3364. {
  3365. #ifndef NO_FILE_TRANSFER
  3366.     ftContainer.m_pFileReceiver.reset(new FileReceiver);
  3367.     ftContainer.m_pFileReceiver->SetAFEngine(m_pAFEngine, m_iAFEServerStoreID);
  3368.     ftContainer.m_pFileObserver.reset(new WindowObserver);
  3369. #ifdef __unix__
  3370.     ftContainer.m_pFileObserver->Init(this, WM_UPDATE_FILE, nFileId);
  3371. #else
  3372.     ftContainer.m_pFileObserver->Init(m_hWnd, WM_UPDATE_FILE, nFileId);
  3373. #endif
  3374.     ftContainer.m_pFileReceiver->Attach(ftContainer.m_pFileObserver.get());
  3375.  
  3376.     ftContainer.m_sUserId = sJid;
  3377.     ftContainer.m_uState = FTS_RECEIVE_REQUEST;
  3378. #endif
  3379. }
  3380.  
  3381. void CXmppCommCtrl::UpdateReceiverParams(
  3382.     FtContainer& ftContainer,
  3383.     const tstring& sPathName)
  3384. {
  3385. #ifndef NO_FILE_TRANSFER
  3386.     ftContainer.m_fti.m_sFileName = ::GetFileName(sPathName);
  3387.     ftContainer.m_fti.m_sDirectory = GetDirName(sPathName);
  3388.  
  3389.     if (ftContainer.m_pFileReceiver.get() == NULL)
  3390.         return;
  3391.  
  3392.     ftContainer.m_pFileReceiver->OpenLogFile(ftContainer.m_fti.m_sFileName);
  3393.  
  3394.     ftContainer.m_pFileReceiver->SetFileTransferInfo(ftContainer.m_fti);
  3395.  
  3396.     ftContainer.m_uState = FTS_RECEIVE_CONNECTING;
  3397.  
  3398.     PostMessage(WM_UPDATE_FILE, ftContainer.m_fti.m_uTransferId, 0);
  3399.  
  3400.     ftContainer.m_pFileReceiver->Log("Initialize RUDP Channel.");
  3401.  
  3402.     ftContainer.m_pFileReceiver->Log("Rudp Connect.");
  3403.  
  3404.     ftContainer.m_pFileReceiver->RudpConnect(ftContainer.m_fti.m_sRemoteSDP);
  3405. #endif
  3406. }
  3407.  
  3408. bool CXmppCommCtrl::CloseFtContainer(FtContainer& ft)
  3409. {
  3410. #ifndef NO_FILE_TRANSFER
  3411.     PAL::Critical_Section cs(*m_pFileTransferMutex);
  3412.     if (NULL != ft.m_pFileSender.get())
  3413.     {
  3414.         PAL_DB("FT Closing SENDER");
  3415.         ft.m_pFileSender->Close();
  3416.         ft.m_pFileSender->Detach(ft.m_pFileObserver.get());
  3417.         ft.m_pFileSender.reset();
  3418.         ft.m_pFileObserver.reset();
  3419.  
  3420.         PAL_DB("FT SENDER Closed");
  3421.         return true;
  3422.     }
  3423.     else if (NULL != ft.m_pFileReceiver.get())
  3424.     {
  3425.         PAL_DB("FT Closing RECEIVER");
  3426.         ft.m_pFileReceiver->Close();
  3427.         ft.m_pFileReceiver->Detach(ft.m_pFileObserver.get());
  3428.         ft.m_pFileReceiver.reset();
  3429.         ft.m_pFileObserver.reset();
  3430.  
  3431.         PAL_DB("FT RECEIVER Closed");
  3432.         return true;
  3433.     }
  3434. #endif
  3435.     return false;
  3436. }
  3437.  
  3438. // clean up all ongoing file transfers
  3439. void CXmppCommCtrl::FtCleanup()
  3440. {
  3441.     if (m_FtContainerMap.empty())
  3442.         return;
  3443.  
  3444.     FtContainerMap::iterator iter = m_FtContainerMap.begin();
  3445.     for (; iter != m_FtContainerMap.end(); ++iter)
  3446.     {
  3447.         //CloseFtContainer(iter->second);
  3448.         FtContainer& fts = (iter->second);
  3449.         fts.m_uState = FTS_ERROR;
  3450.         bool b = CloseFtContainer(fts);
  3451.         if (b)
  3452.         {
  3453. #ifndef NO_FILE_TRANSFER
  3454. #ifndef MESSAGE_FILE_TRANSFER
  3455.             m_pJabberStream->m_pJabberIQ->FileTransferCancel(fts.m_sUserId, iter->first);
  3456. #else
  3457.             m_pJabberStream->m_pJabberMessage->FileTransferCancel(fts.m_sUserId, iter->first);
  3458. #endif
  3459. #endif
  3460. //          m_pChatService->SendFileEnd(fts.m_sUserId, fts.m_fti.m_uTransferId, ECS_FAILURE);
  3461.         }
  3462.     }
  3463.  
  3464.     m_FtContainerMap.clear();
  3465.     m_FileIdMap.clear();
  3466. }
  3467.  
  3468. string CXmppCommCtrl::FileIdToString(int nFileId)
  3469. {
  3470. //  string sFileId = m_pJabberStream->jabber_get_full_jid() + itoa(nFileId);
  3471.     string sFileId = itoa(nFileId);
  3472.     return sFileId;
  3473. }
  3474.  
  3475. int CXmppCommCtrl::FindFileId(string sFileId)
  3476. {
  3477.     std::map<int, string>::iterator iter = m_FileIdMap.begin();
  3478.     for (; iter != m_FileIdMap.end(); ++iter)
  3479.     {
  3480.         if (iter->second == sFileId)
  3481.         {
  3482.             return iter->first;
  3483.         }
  3484.     }
  3485.  
  3486.     return -1;
  3487. }
  3488.  
  3489. string CXmppCommCtrl::GetContactDisplayName(const string& sJid)
  3490. {
  3491.     JabberBuddy* jb = m_pJabberStream->m_pJabberBuddy->jabber_buddy_find(sJid);
  3492.  
  3493. #ifdef SUPPORT_MULTICAST_DISPLAYNAME
  3494.     string sDisplayName;
  3495.     if (jb && !jb->m_sDisplayName.empty())
  3496.     {
  3497.         sDisplayName = jb->m_sDisplayName;
  3498.     }
  3499.     else
  3500.     {
  3501.         sDisplayName = m_pJabberStream->m_pJabberBuddy->FindExtDisplayName(sJid);
  3502.         if (sDisplayName.empty())
  3503.         {
  3504.             sDisplayName = jabber_get_node(sJid);
  3505.         }
  3506.     }
  3507. #else
  3508.     if (!jb)
  3509.     {
  3510.         return "";
  3511.     }
  3512.     string sDisplayName = jb->m_sDisplayName;
  3513. #endif
  3514.  
  3515.     return sDisplayName;
  3516. }
  3517.  
  3518. tstring CXmppCommCtrl::PromptFileDlg(const tstring& sTitle, const tstring& sFileName, bool bOpen)
  3519. {
  3520. #ifndef __unix__
  3521. #ifndef NO_FILE_TRANSFER
  3522.     CFileDialog dlg(bOpen);
  3523.  
  3524. #ifndef _WIN32_WCE
  3525.     if (!sFileName.empty())
  3526.     {
  3527.         TCSCPY(dlg.m_szFileName, sFileName.c_str());
  3528.     }
  3529. #else
  3530.     tstring tsName = sFileName;
  3531.     tsName += L".ext"; //dummy extenstion
  3532.     TCSCPY(dlg.m_szFileName, tsName.c_str());
  3533. #endif
  3534.     dlg.m_ofn.lpstrTitle = sTitle.c_str();
  3535.     dlg.m_ofn.lpstrFilter = EXTENSION_FILTER;
  3536.     dlg.m_ofn.Flags |= OFN_OVERWRITEPROMPT;
  3537.     int iRet = dlg.DoModal();
  3538.     if (IDOK != iRet)
  3539.     {
  3540.         return "";
  3541.     }
  3542.  
  3543.     return dlg.m_szFileName;
  3544. #else
  3545.     return "";
  3546. #endif
  3547. #else   // __unix__
  3548.     return "";
  3549. #endif
  3550. }
  3551.  
  3552. string CXmppCommCtrl::SendFileHelper(
  3553.     const string& sJid,
  3554.     const tstring& sPathNameOrg, // expected to be in wide-byte
  3555.     int nFileId)
  3556. {
  3557. #ifndef NO_FILE_TRANSFER
  3558.     CComBSTR bstrJid = ToBstr(sJid);
  3559.     tstring sDisplayName = GetContactDisplayName(ToBareJid(ToStringA(bstrJid)));
  3560.     tstring sPathName = sPathNameOrg;
  3561.     if (sPathName.empty())
  3562.     {
  3563.         tstring sTitle = tstring("Send File to ") + tstring(sDisplayName);
  3564.  
  3565.         sPathName = PromptFileDlg(sTitle, "");
  3566.  
  3567.         if (sPathName.empty())
  3568.         {
  3569.             return "No file selected.";
  3570.         }
  3571.     }
  3572.  
  3573.     if (!FileExists(sPathName.c_str()))
  3574.     {
  3575.         return "File does not exist.";
  3576.     }
  3577.  
  3578.     long nSize = GetFileSize(sPathName);
  3579.     if (nSize <= 0)
  3580.     {
  3581.         return "File is empty or is in use.";
  3582.     }
  3583.  
  3584.     tstring sFileName = GetFileName(sPathName);
  3585.  
  3586.     string sTransferId = FileIdToString(nFileId);
  3587.     m_FileIdMap[nFileId] = sTransferId;
  3588.     string sSubject = "filetransfer";
  3589.     FtContainer ft;
  3590.     ft = CreateFtSender(sJid, sPathName, nFileId, FileTransferInfo::GENERIC_FILE,   sSubject);
  3591.  
  3592.     ft.m_pFileSender->Log("Initialize Sender UDP.");
  3593.  
  3594.     if (!ft.m_pFileSender->InitRudpChannel())
  3595.     {
  3596.         return "RUDP channel initialization error";
  3597.     }
  3598.  
  3599.     string sOfferSDP = ft.m_pFileSender->GetFileTransferInfo().m_sLocalSDP;
  3600.  
  3601.     ft.m_uFileSize = nSize;
  3602.  
  3603.     ft.m_pFileSender->Log("Sending Xmpp request to " + sJid);
  3604.     ft.m_pFileSender->Log("Sender SDP: \r\n" + sOfferSDP);
  3605.  
  3606. #ifndef MESSAGE_FILE_TRANSFER
  3607. #ifdef JINGLE_FILE_TRANSFER
  3608.     m_pJabberStream->m_pJabberIQ->FileTransferRequest(sJid, sFileName, sSubject, nSize, sTransferId, sOfferSDP, ft);
  3609. #else
  3610.     string sPrimaryAddr = "";
  3611.     string sSecondaryAddr = "";
  3612.     int nPrimaryPort = 0;
  3613.     int nSecondaryPort = 0;
  3614.     m_pJabberStream->m_pJabberIQ->FileTransferRequest(sJid, sFileName, sSubject, nSize, sTransferId, sPrimaryAddr, nPrimaryPort, sSecondaryAddr, nSecondaryPort, ft);
  3615. #endif
  3616. #else
  3617.     m_pJabberStream->m_pJabberMessage->FileTransferRequest(sJid, sFileName, sSubject, nSize, sTransferId, sOfferSDP, ft);
  3618. #endif
  3619. #endif
  3620.     return "";
  3621. }
  3622.  
  3623. HRESULT CXmppCommCtrl::Call_Fire_OnLoginResponse(int iResponse)
  3624. {
  3625.     if (iResponse == JABBER_LOGIN_SUCCESS)
  3626.     {
  3627.         m_pJabberStream->m_pJabberIQ->RetrievePrivateData(
  3628.             "nick",
  3629.             "http://jabber.org/protocol/nick");
  3630.     }
  3631.     FIRE_EVENT(Fire_OnLoginResponse, iResponse);
  3632.     return S_OK;
  3633. }
  3634.  
  3635. HRESULT CXmppCommCtrl::Call_Fire_OnPrivateDataRetrieved(const string& sName, const string& sNameSpace, const string& sUtf8Data)
  3636. {
  3637.     if ((sName == "nick") && (sNameSpace == "http://jabber.org/protocol/nick"))
  3638.     {
  3639.         //if (m_pJabberStream->m_sDisplayName != sUtf8Data)
  3640.         {
  3641.             m_pJabberStream->m_sDisplayName = sUtf8Data;
  3642.             FIRE_EVENT(Fire_OnUpdateMyNickname, ToBstr(sUtf8Data));
  3643.         }
  3644.         return S_OK;
  3645.     }
  3646.  
  3647. #ifdef USE_VARIANT_IN_EVENT
  3648.     BstrArray aData(3);
  3649.     aData.PutString(0, sName);
  3650.     aData.PutString(1, sNameSpace);
  3651.     aData.PutBstr(2, StringU8ToBstr(sUtf8Data));
  3652.  
  3653.     _FIRE_EVENT(m_pJabberStream->m_pXmppComm, Fire_OnPrivateDataRetrieved, aData.GetVariantRef());
  3654. #else
  3655.     CComBSTR bstrName = ToBstr(sName);
  3656.     CComBSTR bstrNameSpace = ToBstr(sNameSpace);
  3657.     CComBSTR bstrData = StringU8ToBstr(sUtf8Data);
  3658.  
  3659.     _FIRE_EVENT(m_pJabberStream->m_pXmppComm, Fire_OnPrivateDataRetrieved, bstrName, bstrNameSpace, bstrData);
  3660. #endif
  3661.  
  3662.     return S_OK;
  3663. }
Advertisement
Add Comment
Please, Sign In to add comment