int CJabberProto::OnContactDeleted( WPARAM wParam, LPARAM ) { if( !m_bJabberOnline ) // should never happen return 0; DBVARIANT dbv; if ( !JGetStringT(( HANDLE ) wParam, JGetByte( (HANDLE ) wParam, "ChatRoom", 0 )?(char*)"ChatRoomID":(char*)"jid", &dbv )) { if ( ListExist( LIST_ROSTER, dbv.ptszVal )) { if ( !_tcschr( dbv.ptszVal, _T( '@' ))) { TCHAR szStrippedJid[JABBER_MAX_JID_LEN]; JabberStripJid( m_ThreadInfo->fullJID, szStrippedJid, SIZEOF(szStrippedJid) ); TCHAR *szDog = _tcschr( szStrippedJid, _T('@')); if ( szDog && _tcsicmp( szDog + 1, dbv.ptszVal )) m_ThreadInfo->send( XmlNodeIq( _T("set"), SerialNext(), dbv.ptszVal ) << XQUERY( _T(JABBER_FEAT_REGISTER)) << XCHILD( _T("remove"))); } // Remove from roster, server also handles the presence unsubscription process. m_ThreadInfo->send( XmlNodeIq( _T("set"), SerialNext()) << XQUERY( _T(JABBER_FEAT_IQ_ROSTER)) << XCHILD( _T("item")) << XATTR( _T("jid"), dbv.ptszVal ) << XATTR( _T("subscription"), _T("remove"))); } JFreeVariant( &dbv ); } return 0; }
int CJabberProto::OnContactDeleted(WPARAM wParam, LPARAM) { if (!m_bJabberOnline) // should never happen return 0; HANDLE hContact = (HANDLE)wParam; ptrT jid(getTStringA(hContact, isChatRoom(hContact) ? "ChatRoomID" : "jid")); if (jid == NULL) return 0; if (ListGetItemPtr(LIST_ROSTER, jid)) { if (!_tcschr(jid, _T('@'))) { TCHAR szStrippedJid[JABBER_MAX_JID_LEN]; JabberStripJid(m_ThreadInfo->fullJID, szStrippedJid, SIZEOF(szStrippedJid)); TCHAR *szDog = _tcschr(szStrippedJid, _T('@')); if (szDog && _tcsicmp(szDog + 1, jid)) m_ThreadInfo->send(XmlNodeIq(_T("set"), SerialNext(), jid) << XQUERY(JABBER_FEAT_REGISTER) << XCHILD(_T("remove"))); } // Remove from roster, server also handles the presence unsubscription process. m_ThreadInfo->send(XmlNodeIq(_T("set"), SerialNext()) << XQUERY(JABBER_FEAT_IQ_ROSTER) << XCHILD(_T("item")) << XATTR(_T("jid"), jid) << XATTR(_T("subscription"), _T("remove"))); } return 0; }
void __cdecl CJabberProto::IbbReceiveThread(JABBER_IBB_TRANSFER *jibb) { debugLogA("Thread started: type=ibb_recv"); filetransfer *ft = jibb->ft; jibb->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); jibb->bStreamClosed = FALSE; jibb->wPacketId = 0; jibb->dwTransferredSize = 0; jibb->state = JIBB_RECVING; WaitForSingleObject(jibb->hEvent, INFINITE); CloseHandle(jibb->hEvent); jibb->hEvent = NULL; if (jibb->state == JIBB_ERROR) m_ThreadInfo->send( XmlNodeIq(_T("set"), SerialNext(), jibb->dstJID) << XCHILDNS(_T("close"), JABBER_FEAT_IBB) << XATTR(_T("sid"), jibb->sid)); if (jibb->bStreamClosed && jibb->dwTransferredSize == ft->dwExpectedRecvFileSize) jibb->state = JIBB_DONE; (this->*jibb->pfnFinal)((jibb->state==JIBB_DONE)?TRUE:FALSE, jibb->ft); jibb->ft = NULL; ListRemove(LIST_FTRECV, jibb->sid); JabberIbbFreeJibb(jibb); }
int CJabberProto::SearchRenewFields(HWND hwndDlg, JabberSearchData * dat) { TCHAR szServerName[100]; EnableWindow(GetDlgItem(hwndDlg, IDC_GO),FALSE); GetDlgItemText(hwndDlg,IDC_SERVER,szServerName,SIZEOF(szServerName)); dat->CurrentHeight = 0; dat->curPos = 0; SetScrollPos( GetDlgItem( hwndDlg, IDC_VSCROLL ), SB_CTL, 0, FALSE ); JabberSearchFreeData( hwndDlg, dat ); JabberSearchRefreshFrameScroll( hwndDlg, dat ); if ( m_bJabberOnline ) SetDlgItemText(hwndDlg,IDC_INSTRUCTIONS,TranslateT("Please wait...\r\nConnecting search server...")); else SetDlgItemText(hwndDlg,IDC_INSTRUCTIONS,TranslateT("You have to be connected to server")); if ( !m_bJabberOnline ) return 0; searchHandleDlg = hwndDlg; int iqId = SerialNext(); IqAdd( iqId, IQ_PROC_GETSEARCHFIELDS, &CJabberProto::OnIqResultGetSearchFields ); m_ThreadInfo->send( XmlNodeIq( _T("get"), iqId, szServerName ) << XQUERY( _T("jabber:iq:search"))); return iqId; }
void CJabberProto::SetMucConfig( HXML node, void *from ) { if ( m_ThreadInfo && from ) { XmlNodeIq iq( _T("set"), SerialNext(), ( TCHAR* )from ); HXML query = iq << XQUERY( xmlnsOwner ); xmlAddChild( query, node ); m_ThreadInfo->send( iq ); } }
void CJabberProto::AddContactToRoster(const TCHAR *jid, const TCHAR *nick, const TCHAR *grpName) { XmlNodeIq iq(_T("set"), SerialNext()); HXML query = iq << XQUERY(JABBER_FEAT_IQ_ROSTER) << XCHILD(_T("item")) << XATTR(_T("jid"), jid) << XATTR(_T("name"), nick); if (grpName) query << XCHILD(_T("group"), grpName); m_ThreadInfo->send(iq); }
HWND __cdecl CJabberProto::SearchAdvanced( HWND hwndDlg ) { if ( !m_bJabberOnline || !hwndDlg ) return 0; //error JabberSearchData * dat=(JabberSearchData *)GetWindowLongPtr(hwndDlg,GWLP_USERDATA); if ( !dat ) return 0; //error // check if server connected (at least one field exists) if ( dat->nJSInfCount == 0 ) return 0; // formating request BOOL fRequestNotEmpty=FALSE; // get server name TCHAR szServerName[100]; GetDlgItemText( hwndDlg, IDC_SERVER, szServerName, SIZEOF( szServerName )); // formating query int iqId = SerialNext(); XmlNodeIq iq( _T("set"), iqId, szServerName ); HXML query = iq << XQUERY( _T("jabber:iq:search")); if ( m_tszSelectedLang ) iq << XATTR( _T("xml:lang"), m_tszSelectedLang ); // i'm sure :) // next can be 2 cases: // Forms: XEP-0055 Example 7 if ( dat->fSearchRequestIsXForm ) { fRequestNotEmpty=TRUE; HXML n = JabberFormGetData(GetDlgItem(hwndDlg, IDC_FRAME), dat->xNode); xmlAddChild( query, n ); xi.destroyNode( n ); } else { //and Simple fields: XEP-0055 Example 3 for ( int i=0; i<dat->nJSInfCount; i++ ) { TCHAR szFieldValue[100]; GetWindowText(dat->pJSInf[i].hwndValueItem, szFieldValue, SIZEOF(szFieldValue)); if ( szFieldValue[0] != _T('\0')) { xmlAddChild( query, dat->pJSInf[i].szFieldName, szFieldValue ); fRequestNotEmpty=TRUE; } } } if ( fRequestNotEmpty ) { // register search request result handler IqAdd( iqId, IQ_PROC_GETSEARCH, &CJabberProto::OnIqResultAdvancedSearch ); // send request m_ThreadInfo->send( iq ); return ( HWND )iqId; } return 0; }
void CJabberProto::ProcessOutgoingNote(CNoteItem *pNote, bool ok) { if (!ok || !pNote->IsNotEmpty()) { delete pNote; return; } TCHAR buf[1024]; mir_sntprintf(buf, SIZEOF(buf), _T("Incoming note: %s\n\n%s\nTags: %s"), pNote->GetTitle(), pNote->GetText(), pNote->GetTagsStr()); JabberCapsBits jcb = GetResourceCapabilites( pNote->GetFrom(), TRUE ); if ( jcb & JABBER_RESOURCE_CAPS_ERROR ) jcb = JABBER_RESOURCE_CAPS_NONE; int nMsgId = SerialNext(); XmlNode m(_T("message")); m << XATTR(_T("type"), _T("chat")) << XATTR( _T("to"), pNote->GetFrom() ) << XATTRID( nMsgId ); m << XCHILD(_T("body"), buf); HXML hXmlItem = m << XCHILDNS(_T("x"), _T(JABBER_FEAT_MIRANDA_NOTES)) << XCHILD(_T("note")); hXmlItem << XATTR(_T("tags"), pNote->GetTagsStr()); hXmlItem << XCHILD(_T("title"), pNote->GetTitle()); hXmlItem << XCHILD(_T("text"), pNote->GetText()); // message receipts XEP priority if ( jcb & JABBER_CAPS_MESSAGE_RECEIPTS ) m << XCHILDNS( _T("request"), _T(JABBER_FEAT_MESSAGE_RECEIPTS)); else if ( jcb & JABBER_CAPS_MESSAGE_EVENTS ) { HXML x = m << XCHILDNS( _T("x"), _T(JABBER_FEAT_MESSAGE_EVENTS)); x << XCHILD( _T("delivered")); x << XCHILD( _T("offline")); } else nMsgId = -1; m_ThreadInfo->send(m); delete pNote; }
void CJabberProto::EnableArchive(bool bEnable) { m_ThreadInfo->send( XmlNodeIq(_T("set"), SerialNext()) << XCHILDNS( _T("auto"), JABBER_FEAT_ARCHIVE) << XATTR(_T("save"), (bEnable) ? _T("true") : _T("false"))); }
void __cdecl CJabberProto::FileServerThread(filetransfer *ft) { debugLogA("Thread started: type=file_send"); ThreadData info(this, NULL); ft->type = FT_OOB; NETLIBBIND nlb = { 0 }; nlb.cbSize = sizeof(NETLIBBIND); nlb.pfnNewConnectionV2 = JabberFileServerConnection; nlb.pExtra = this; nlb.wPort = 0; // Use user-specified incoming port ranges, if available info.s = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)m_hNetlibUser, (LPARAM)&nlb); if (info.s == NULL) { debugLogA("Cannot allocate port to bind for file server thread, thread ended."); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0); delete ft; return; } ft->s = info.s; debugLogA("ft->s = %d", info.s); HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); ft->hFileEvent = hEvent; TCHAR szPort[20]; mir_sntprintf(szPort, _countof(szPort), _T("%d"), nlb.wPort); JABBER_LIST_ITEM *item = ListAdd(LIST_FILE, szPort); item->ft = ft; TCHAR *ptszResource = ListGetBestClientResourceNamePtr(ft->jid); if (ptszResource != NULL) { ft->state = FT_CONNECTING; for (int i = 0; i < ft->std.totalFiles && ft->state != FT_ERROR && ft->state != FT_DENIED; i++) { ft->std.currentFileNumber = i; ft->state = FT_CONNECTING; if (ft->httpPath) mir_free(ft->httpPath); ft->httpPath = NULL; TCHAR *p; if ((p = _tcschr(ft->std.ptszFiles[i], '\\')) != NULL) p++; else p = ft->std.ptszFiles[i]; ptrA pFileName(mir_urlEncode(T2Utf(p))); if (pFileName != NULL) { ft->szId = JabberId2string(SerialNext()); ptrA myAddr; if (m_options.BsDirect && m_options.BsDirectManual) myAddr = getStringA("BsDirectAddr"); if (myAddr == NULL) myAddr = (char*)CallService(MS_NETLIB_ADDRESSTOSTRING, 1, nlb.dwExternalIP); char szAddr[256]; mir_snprintf(szAddr, _countof(szAddr), "http://%s:%d/%s", myAddr, nlb.wPort, pFileName); size_t len = mir_tstrlen(ptszResource) + mir_tstrlen(ft->jid) + 2; TCHAR *fulljid = (TCHAR *)alloca(sizeof(TCHAR) * len); mir_sntprintf(fulljid, len, _T("%s/%s"), ft->jid, ptszResource); XmlNodeIq iq(_T("set"), ft->szId, fulljid); HXML query = iq << XQUERY(JABBER_FEAT_OOB); query << XCHILD(_T("url"), _A2T(szAddr)); query << XCHILD(_T("desc"), ft->szDescription); m_ThreadInfo->send(iq); debugLogA("Waiting for the file to be sent..."); WaitForSingleObject(hEvent, INFINITE); } debugLogA("File sent, advancing to the next file..."); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0); } CloseHandle(hEvent); ft->hFileEvent = NULL; debugLogA("Finish all files"); } ft->s = NULL; debugLogA("ft->s is NULL"); ListRemove(LIST_FILE, szPort); switch (ft->state) { case FT_DONE: debugLogA("Finish successfully"); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0); break; case FT_DENIED: ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ft, 0); break; default: // FT_ERROR: debugLogA("Finish with errors"); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0); break; } debugLogA("Thread ended: type=file_send"); delete ft; }
int CJabberProto::ByteSendProxyParse( HANDLE hConn, JABBER_BYTE_TRANSFER *jbt, char* buffer, int datalen ) { int num = datalen; switch ( jbt->state ) { case JBT_INIT: // received: // 00-00 ver ( 0x05 ) // 01-01 selected method ( 0=no auth, 0xff=error ) // send: // 00-00 ver ( 0x05 ) // 01-01 cmd ( 1=connect ) // 02-02 reserved ( 0 ) // 03-03 address type ( 3 ) // 04-44 dst.addr ( 41 bytes: 1-byte length, 40-byte SHA1 hash of [sid,srcJID,dstJID] ) // 45-46 dst.port ( 0 ) if ( datalen==2 && buffer[0]==5 && buffer[1]==0 ) { BYTE data[47]; ZeroMemory( data, sizeof( data )); *(( DWORD* )data ) = 0x03000105; data[4] = 40; TCHAR text[256]; TCHAR *szInitiatorJid = JabberPrepareJid(jbt->srcJID); TCHAR *szTargetJid = JabberPrepareJid(jbt->dstJID); mir_sntprintf( text, SIZEOF( text ), _T("%s%s%s"), jbt->sid, szInitiatorJid, szTargetJid ); mir_free(szInitiatorJid); mir_free(szTargetJid); char* szAuthString = mir_utf8encodeT( text ); Log( "Auth: '%s'", szAuthString ); char* szHash = JabberSha1( szAuthString ); strncpy(( char* )( data+5 ), szHash, 40 ); mir_free( szHash ); Netlib_Send( hConn, ( char* )data, 47, 0 ); jbt->state = JBT_CONNECT; mir_free( szAuthString ); } else jbt->state = JBT_SOCKSERR; break; case JBT_CONNECT: // received: // 00-00 ver ( 0x05 ) // 01-01 reply ( 0=success,2=not allowed ) // 02-02 reserved ( 0 ) // 03-03 address type ( 1=IPv4 address,3=host address ) // 04-mm bnd.addr server bound address ( 4-byte IP if IPv4, 1-byte length + n-byte host address string if host address ) // nn-nn+1 bnd.port server bound port if ( datalen>=5 && buffer[0]==5 && buffer[1]==0 && ( buffer[3]==1 || buffer[3]==3 || buffer[3]==0 )) { if ( buffer[3]==1 && datalen>=10 ) num = 10; else if ( buffer[3]==3 && datalen>=buffer[4]+7 ) num = buffer[4] + 7; else if ( buffer[3]==0 && datalen>=6 ) num = 6; else { jbt->state = JBT_SOCKSERR; break; } jbt->state = JBT_SENDING; jbt->hProxyEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); jbt->bStreamActivated = FALSE; int iqId = SerialNext(); TCHAR listJid[256]; mir_sntprintf(listJid, SIZEOF( listJid ), _T("ftproxy_%d"), iqId); JABBER_LIST_ITEM *item = ListAdd( LIST_FTIQID, listJid ); item->jbt = jbt; IqAdd( iqId, IQ_PROC_NONE, &CJabberProto::IqResultStreamActivate ); m_ThreadInfo->send( XmlNodeIq( _T("set"), iqId, jbt->streamhostJID ) << XQUERY( _T(JABBER_FEAT_BYTESTREAMS)) << XATTR( _T("sid"), jbt->sid ) << XCHILD( _T("activate"), jbt->dstJID )); WaitForSingleObject( jbt->hProxyEvent, INFINITE ); CloseHandle( jbt->hProxyEvent ); jbt->hProxyEvent = NULL; ListRemove( LIST_FTIQID, listJid ); if ( jbt->bStreamActivated) jbt->state = (this->*jbt->pfnSend)( hConn, jbt->ft ) ? JBT_DONE : JBT_ERROR; else jbt->state = JBT_ERROR; } else jbt->state = JBT_SOCKSERR; break; } return num; }
void __cdecl CJabberProto::FileServerThread( filetransfer* ft ) { Log( "Thread started: type=file_send" ); ThreadData info( this, JABBER_SESSION_NORMAL ); ft->type = FT_OOB; NETLIBBIND nlb = {0}; nlb.cbSize = sizeof( NETLIBBIND ); nlb.pfnNewConnectionV2 = JabberFileServerConnection; nlb.pExtra = this; nlb.wPort = 0; // Use user-specified incoming port ranges, if available info.s = ( HANDLE ) JCallService( MS_NETLIB_BINDPORT, ( WPARAM ) m_hNetlibUser, ( LPARAM )&nlb ); if ( info.s == NULL ) { Log( "Cannot allocate port to bind for file server thread, thread ended." ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); delete ft; return; } ft->s = info.s; Log( "ft->s = %d", info.s ); HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); ft->hFileEvent = hEvent; TCHAR szPort[20]; mir_sntprintf( szPort, SIZEOF( szPort ), _T("%d"), nlb.wPort ); JABBER_LIST_ITEM *item = ListAdd( LIST_FILE, szPort ); item->ft = ft; TCHAR* ptszResource = ListGetBestClientResourceNamePtr( ft->jid ); if ( ptszResource != NULL ) { ft->state = FT_CONNECTING; for ( int i=0; i < ft->std.totalFiles && ft->state != FT_ERROR && ft->state != FT_DENIED; i++ ) { ft->std.currentFileNumber = i; ft->state = FT_CONNECTING; if ( ft->httpPath ) mir_free( ft->httpPath ); ft->httpPath = NULL; TCHAR* p; if (( p = _tcschr( ft->std.ptszFiles[i], '\\' )) != NULL ) p++; else p = ft->std.ptszFiles[i]; in_addr in; in.S_un.S_addr = m_dwJabberLocalIP; TCHAR* pFileName = JabberHttpUrlEncode( p ); if ( pFileName != NULL ) { int id = SerialNext(); if ( ft->iqId ) mir_free( ft->iqId ); ft->iqId = ( TCHAR* )mir_alloc( sizeof(TCHAR)*( strlen( JABBER_IQID )+20 )); wsprintf( ft->iqId, _T(JABBER_IQID)_T("%d"), id ); char *myAddr; DBVARIANT dbv; if (m_options.BsDirect && m_options.BsDirectManual) { if ( !DBGetContactSettingString( NULL, m_szModuleName, "BsDirectAddr", &dbv )) { myAddr = NEWSTR_ALLOCA( dbv.pszVal ); JFreeVariant( &dbv ); } else myAddr = inet_ntoa( in ); } else myAddr = inet_ntoa( in ); char szAddr[ 256 ]; mir_snprintf( szAddr, sizeof(szAddr), "http://%s:%d/%s", myAddr, nlb.wPort, pFileName ); int len = lstrlen(ptszResource) + lstrlen(ft->jid) + 2; TCHAR* fulljid = ( TCHAR* )alloca( sizeof( TCHAR )*len ); wsprintf( fulljid, _T("%s/%s"), ft->jid, ptszResource ); XmlNodeIq iq( _T("set"), id, fulljid ); HXML query = iq << XQUERY( _T(JABBER_FEAT_OOB)); query << XCHILD( _T("url"), _A2T(szAddr)); query << XCHILD( _T("desc"), ft->szDescription); m_ThreadInfo->send( iq ); Log( "Waiting for the file to be sent..." ); WaitForSingleObject( hEvent, INFINITE ); mir_free( pFileName ); } Log( "File sent, advancing to the next file..." ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0 ); } CloseHandle( hEvent ); ft->hFileEvent = NULL; Log( "Finish all files" ); } ft->s = NULL; Log( "ft->s is NULL" ); ListRemove( LIST_FILE, szPort ); switch ( ft->state ) { case FT_DONE: Log( "Finish successfully" ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0 ); break; case FT_DENIED: JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ft, 0 ); break; default: // FT_ERROR: Log( "Finish with errors" ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); break; } Log( "Thread ended: type=file_send" ); delete ft; }
int CJabberProto::OnProcessSrmmEvent(WPARAM, LPARAM lParam) { MessageWindowEventData *event = (MessageWindowEventData *)lParam; if (event->uType == MSG_WINDOW_EVT_OPEN) { if (!hDialogsList) hDialogsList = WindowList_Create(); WindowList_Add(hDialogsList, event->hwndWindow, event->hContact); ptrT jid(getTStringA(event->hContact, "jid")); if (jid != NULL) { JABBER_LIST_ITEM *pItem = ListGetItemPtr(LIST_ROSTER, jid); if (pItem && (m_ThreadInfo->jabberServerCaps & JABBER_CAPS_ARCHIVE_AUTO) && m_options.EnableMsgArchive) RetrieveMessageArchive(event->hContact, pItem); } } else if (event->uType == MSG_WINDOW_EVT_CLOSING) { if (hDialogsList) WindowList_Remove(hDialogsList, event->hwndWindow); DBVARIANT dbv; BOOL bSupportTyping = FALSE; if (!db_get(event->hContact, "SRMsg", "SupportTyping", &dbv)) { bSupportTyping = dbv.bVal == 1; db_free(&dbv); } else if (!db_get(NULL, "SRMsg", "DefaultTyping", &dbv)) { bSupportTyping = dbv.bVal == 1; db_free(&dbv); } if (!bSupportTyping || !m_bJabberOnline) return 0; TCHAR jid[JABBER_MAX_JID_LEN]; if (GetClientJID(event->hContact, jid, _countof(jid))) { pResourceStatus r(ResourceInfoFromJID(jid)); if (r && r->m_bMessageSessionActive) { r->m_bMessageSessionActive = FALSE; if (GetResourceCapabilites(jid, TRUE) & JABBER_CAPS_CHATSTATES) m_ThreadInfo->send( XmlNode(_T("message")) << XATTR(_T("to"), jid) << XATTR(_T("type"), _T("chat")) << XATTRID(SerialNext()) << XCHILDNS(_T("gone"), JABBER_FEAT_CHATSTATES)); } } } return 0; }