void CJabberProto::IbbSendThread( JABBER_IBB_TRANSFER *jibb ) { Log( "Thread started: type=ibb_send" ); jibb->hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); jibb->bStreamInitialized = FALSE; jibb->bStreamClosed = FALSE; jibb->state = JIBB_SENDING; m_ThreadInfo->send( XmlNodeIq( m_iqManager.AddHandler( &CJabberProto::OnIbbInitiateResult, JABBER_IQ_TYPE_SET, jibb->dstJID, 0, -1, jibb )) << XCHILDNS( _T("open"), _T(JABBER_FEAT_IBB)) << XATTR( _T("sid"), jibb->sid ) << XATTRI( _T("block-size"), JABBER_IBB_BLOCK_SIZE ) << XATTR( _T("stanza"), _T("message"))); WaitForSingleObject( jibb->hEvent, INFINITE ); CloseHandle( jibb->hEvent ); jibb->hEvent = NULL; if ( jibb->bStreamInitialized ) { jibb->wPacketId = 0; BOOL bSent = (this->*jibb->pfnSend)( JABBER_IBB_BLOCK_SIZE, jibb->ft ); if ( !jibb->bStreamClosed ) { jibb->hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); m_ThreadInfo->send( XmlNodeIq( m_iqManager.AddHandler( &CJabberProto::OnIbbCloseResult, JABBER_IQ_TYPE_SET, jibb->dstJID, 0, -1, jibb )) << XCHILDNS( _T("close"), _T(JABBER_FEAT_IBB)) << XATTR( _T("sid"), jibb->sid )); WaitForSingleObject( jibb->hEvent, INFINITE ); CloseHandle( jibb->hEvent ); jibb->hEvent = NULL; if ( jibb->bStreamClosed && bSent ) jibb->state = JIBB_DONE; } else { jibb->state = JIBB_ERROR; } } (this->*jibb->pfnFinal)(( jibb->state==JIBB_DONE )?TRUE:FALSE, jibb->ft ); jibb->ft = NULL; JabberIbbFreeJibb( jibb ); }
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); }
void CJabberDlgBookmarks::UpdateData() { if (!m_proto->m_bJabberOnline) return; m_proto->m_ThreadInfo->send( XmlNodeIq( m_proto->AddIQ(&CJabberProto::OnIqResultDiscoBookmarks, JABBER_IQ_TYPE_GET)) << XQUERY(JABBER_FEAT_PRIVATE_STORAGE) << XCHILDNS(_T("storage"), _T("storage:bookmarks"))); }
void btnSave_OnClick(CCtrlButton *) { XmlNodeIq iq(_T("set")); HXML query = iq << XQUERY( _T(JABBER_FEAT_PRIVATE_STORAGE)); HXML storage = query << XCHILDNS(_T("storage"), _T(JABBER_FEAT_MIRANDA_NOTES)); m_proto->m_notes.SaveXml(storage); m_proto->m_ThreadInfo->send(iq); EnableControls(); }
int CJabberProto::SendGetVcard(const TCHAR *jid) { if (!m_bJabberOnline) return 0; CJabberIqInfo *pInfo = AddIQ(&CJabberProto::OnIqResultGetVcard, JABBER_IQ_TYPE_GET, jid); m_ThreadInfo->send(XmlNodeIq(pInfo) << XCHILDNS(_T("vCard"), JABBER_FEAT_VCARD_TEMP) << XATTR(_T("prodid"), _T("-//HandGen//NONSGML vGen v1.0//EN")) << XATTR(_T("version"), _T("2.0"))); return pInfo->GetIqId(); }
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::ProcessIncomingNote(CNoteItem *pNote, bool ok) { if (ok && pNote->IsNotEmpty()) { m_notes.insert(pNote); XmlNodeIq iq(_T("set")); HXML query = iq << XQUERY(JABBER_FEAT_PRIVATE_STORAGE); HXML storage = query << XCHILDNS(_T("storage"), JABBER_FEAT_MIRANDA_NOTES); m_notes.SaveXml(storage); m_ThreadInfo->send(iq); } else delete pNote; }
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; }
BOOL CJabberProto::SendHttpAuthReply(CJabberHttpAuthParams *pParams, BOOL bAuthorized) { if (!m_bJabberOnline || !pParams || !m_ThreadInfo) return FALSE; if (pParams->m_nType == CJabberHttpAuthParams::IQ) { XmlNodeIq iq(bAuthorized ? _T("result") : _T("error"), pParams->m_szIqId, pParams->m_szFrom); if (!bAuthorized) { iq << XCHILDNS(_T("confirm"), JABBER_FEAT_HTTP_AUTH) << XATTR(_T("id"), pParams->m_szId) << XATTR(_T("method"), pParams->m_szMethod) << XATTR(_T("url"), pParams->m_szUrl); iq << XCHILD(_T("error")) << XATTRI(_T("code"), 401) << XATTR(_T("type"), _T("auth")) << XCHILDNS(_T("not-authorized"), _T("urn:ietf:params:xml:xmpp-stanzas")); } m_ThreadInfo->send(iq); } else if (pParams->m_nType == CJabberHttpAuthParams::MSG) { XmlNode msg(_T("message")); msg << XATTR(_T("to"), pParams->m_szFrom); if (!bAuthorized) msg << XATTR(_T("type"), _T("error")); if (pParams->m_szThreadId) msg << XCHILD(_T("thread"), pParams->m_szThreadId); msg << XCHILDNS(_T("confirm"), JABBER_FEAT_HTTP_AUTH) << XATTR(_T("id"), pParams->m_szId) << XATTR(_T("method"), pParams->m_szMethod) << XATTR(_T("url"), pParams->m_szUrl); if (!bAuthorized) msg << XCHILD(_T("error")) << XATTRI(_T("code"), 401) << XATTR(_T("type"), _T("auth")) << XCHILDNS(_T("not-authorized"), _T("urn:ietf:params:xml:xmpp-stanzas")); m_ThreadInfo->send(msg); } else return FALSE; return TRUE; }
BOOL CJabberProto::OnSiRequest(HXML node, CJabberIqInfo *pInfo) { const TCHAR *szProfile = XmlGetAttrValue(pInfo->GetChildNode(), _T("profile")); if (szProfile && !mir_tstrcmp(szProfile, JABBER_FEAT_SI_FT)) FtHandleSiRequest(node); else { XmlNodeIq iq(_T("error"), pInfo); HXML error = iq << XCHILD(_T("error")) << XATTRI(_T("code"), 400) << XATTR(_T("type"), _T("cancel")); error << XCHILDNS(_T("bad-request"), _T("urn:ietf:params:xml:ns:xmpp-stanzas")); error << XCHILD(_T("bad-profile")); m_ThreadInfo->send(iq); } return TRUE; }
void CJabberProto::RetrieveMessageArchive(MCONTACT hContact, JABBER_LIST_ITEM *pItem) { if (pItem->bHistoryRead) return; pItem->bHistoryRead = TRUE; XmlNodeIq iq( AddIQ(&CJabberProto::OnIqResultGetCollectionList, JABBER_IQ_TYPE_GET)); HXML list = iq << XCHILDNS( _T("list"), JABBER_FEAT_ARCHIVE) << XATTR(_T("with"), pItem->jid); time_t tmLast = getDword(hContact, "LastCollection", 0); if (tmLast) { TCHAR buf[40]; list << XATTR(_T("start"), time2str(tmLast, buf, SIZEOF(buf))); } m_ThreadInfo->send(iq); }
// entity time (XEP-0202) support BOOL CJabberProto::OnIqRequestTime(HXML, CJabberIqInfo *pInfo) { TCHAR stime[100]; TCHAR szTZ[10]; TimeZone_PrintDateTime(UTC_TIME_HANDLE, _T("I"), stime, _countof(stime), 0); int nGmtOffset = GetGMTOffset(); mir_sntprintf(szTZ, _countof(szTZ), _T("%+03d:%02d"), nGmtOffset / 60, nGmtOffset % 60); XmlNodeIq iq(_T("result"), pInfo); HXML timeNode = iq << XCHILDNS(_T("time"), JABBER_FEAT_ENTITY_TIME); timeNode << XCHILD(_T("utc"), stime); timeNode << XCHILD(_T("tzo"), szTZ); LPCTSTR szTZName = TimeZone_GetName(NULL); if (szTZName) timeNode << XCHILD(_T("tz"), szTZName); m_ThreadInfo->send(iq); return TRUE; }
void CJabberProto::OnIqResultGetCollectionList(HXML iqNode, CJabberIqInfo*) { const TCHAR *to = xmlGetAttrValue(iqNode, _T("to")); if (to == NULL || mir_tstrcmp( xmlGetAttrValue(iqNode, _T("type")), _T("result"))) return; HXML list = xmlGetChild(iqNode, "list"); if (!list || mir_tstrcmp( xmlGetAttrValue(list, _T("xmlns")), JABBER_FEAT_ARCHIVE)) return; MCONTACT hContact = NULL; time_t tmLast = 0; for (int nodeIdx = 1; ; nodeIdx++) { HXML itemNode = xmlGetNthChild(list, _T("chat"), nodeIdx); if (!itemNode) break; const TCHAR* start = xmlGetAttrValue(itemNode, _T("start")); const TCHAR* with = xmlGetAttrValue(itemNode, _T("with")); if (!start || !with) continue; if (hContact == NULL) { if ((hContact = HContactFromJID(with)) == NULL) continue; tmLast = getDword(hContact, "LastCollection", 0); } m_ThreadInfo->send( XmlNodeIq( AddIQ(&CJabberProto::OnIqResultGetCollection, JABBER_IQ_TYPE_GET)) << XCHILDNS( _T("retrieve"), JABBER_FEAT_ARCHIVE) << XATTR(_T("with"), with) << XATTR(_T("start"), start)); time_t tmThis = str2time(start); if ( tmThis > tmLast) { tmLast = tmThis; setDword(hContact, "LastCollection", tmLast+1); } } }
BOOL CJabberProto::OnHandleDiscoInfoRequest(HXML iqNode, CJabberIqInfo *pInfo) { if (!pInfo->GetChildNode()) return TRUE; const TCHAR *szNode = XmlGetAttrValue(pInfo->GetChildNode(), _T("node")); // caps hack if (m_clientCapsManager.HandleInfoRequest(iqNode, pInfo, szNode)) return TRUE; // ad-hoc hack: if (szNode && m_adhocManager.HandleInfoRequest(iqNode, pInfo, szNode)) return TRUE; // another request, send empty result m_ThreadInfo->send( XmlNodeIq(_T("error"), pInfo) << XCHILD(_T("error")) << XATTRI(_T("code"), 404) << XATTR(_T("type"), _T("cancel")) << XCHILDNS(_T("item-not-found"), _T("urn:ietf:params:xml:ns:xmpp-stanzas"))); return TRUE; }
// XEP-0224 support (Attention/Nudge) INT_PTR __cdecl CJabberProto::JabberSendNudge(WPARAM wParam, LPARAM) { if (!m_bJabberOnline) return 0; HANDLE hContact = (HANDLE)wParam; ptrT jid( getTStringA(hContact, "jid")); if (jid == NULL) return 0; TCHAR tszJid[JABBER_MAX_JID_LEN]; TCHAR *szResource = ListGetBestClientResourceNamePtr(jid); if (szResource) mir_sntprintf(tszJid, SIZEOF(tszJid), _T("%s/%s"), jid, szResource); else mir_sntprintf(tszJid, SIZEOF(tszJid), _T("%s"), jid); JabberCapsBits jcb = GetResourceCapabilites(tszJid, FALSE); m_ThreadInfo->send( XmlNode(_T("message")) << XATTR(_T("type"), _T("headline")) << XATTR(_T("to"), tszJid) << XCHILDNS(_T("attention"), JABBER_FEAT_ATTENTION)); return 0; }
BOOL CJabberProto::OnFtHandleIbbIq(HXML iqNode, CJabberIqInfo *pInfo) { if (!mir_tstrcmp(pInfo->GetChildNodeName(), _T("open"))) FtHandleIbbRequest(iqNode, TRUE); else if (!mir_tstrcmp(pInfo->GetChildNodeName(), _T("close"))) FtHandleIbbRequest(iqNode, FALSE); else if (!mir_tstrcmp(pInfo->GetChildNodeName(), _T("data"))) { BOOL bOk = FALSE; const TCHAR *sid = XmlGetAttrValue(pInfo->GetChildNode(), _T("sid")); const TCHAR *seq = XmlGetAttrValue(pInfo->GetChildNode(), _T("seq")); if (sid && seq && XmlGetText(pInfo->GetChildNode())) bOk = OnIbbRecvdData(XmlGetText(pInfo->GetChildNode()), sid, seq); if (bOk) m_ThreadInfo->send( XmlNodeIq(_T("result"), pInfo)); else m_ThreadInfo->send( XmlNodeIq(_T("error"), pInfo) << XCHILD(_T("error")) << XATTRI(_T("code"), 404) << XATTR(_T("type"), _T("cancel")) << XCHILDNS(_T("item-not-found"), _T("urn:ietf:params:xml:ns:xmpp-stanzas"))); } return TRUE; }
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"))); }
INT_PTR __cdecl CJabberProto::JabberGetAvatarInfo(WPARAM wParam, LPARAM lParam) { if (!m_options.EnableAvatars) return GAIR_NOAVATAR; PROTO_AVATAR_INFORMATIONT* AI = (PROTO_AVATAR_INFORMATIONT*)lParam; ptrA szHashValue( getStringA(AI->hContact, "AvatarHash")); if (szHashValue == NULL) { debugLogA("No avatar"); return GAIR_NOAVATAR; } TCHAR tszFileName[MAX_PATH]; GetAvatarFileName(AI->hContact, tszFileName, SIZEOF(tszFileName)); _tcsncpy(AI->filename, tszFileName, SIZEOF(AI->filename)); AI->format = (AI->hContact == NULL) ? PA_FORMAT_PNG : getByte(AI->hContact, "AvatarType", 0); if (::_taccess(AI->filename, 0) == 0) { ptrA szSavedHash( getStringA(AI->hContact, "AvatarSaved")); if (szSavedHash != NULL && !strcmp(szSavedHash, szHashValue)) { debugLogA("Avatar is Ok: %s == %s", szSavedHash, szHashValue); return GAIR_SUCCESS; } } if ((wParam & GAIF_FORCE) != 0 && AI->hContact != NULL && m_bJabberOnline) { ptrT tszJid( getTStringA(AI->hContact, "jid")); if (tszJid != NULL) { JABBER_LIST_ITEM *item = ListGetItemPtr(LIST_ROSTER, tszJid); if (item != NULL) { BOOL isXVcard = getByte(AI->hContact, "AvatarXVcard", 0); TCHAR szJid[JABBER_MAX_JID_LEN]; szJid[0] = 0; if (item->arResources.getCount() != NULL && !isXVcard) if (TCHAR *bestResName = ListGetBestClientResourceNamePtr(tszJid)) mir_sntprintf(szJid, SIZEOF(szJid), _T("%s/%s"), tszJid, bestResName); if (szJid[0] == 0) _tcsncpy_s(szJid, SIZEOF(szJid), tszJid, _TRUNCATE); debugLogA("Rereading %s for %S", isXVcard ? JABBER_FEAT_VCARD_TEMP : JABBER_FEAT_AVATAR, szJid); m_ThreadInfo->send((isXVcard) ? XmlNodeIq( AddIQ(&CJabberProto::OnIqResultGetVCardAvatar, JABBER_IQ_TYPE_GET, szJid)) << XCHILDNS(_T("vCard"), JABBER_FEAT_VCARD_TEMP) : XmlNodeIq( AddIQ(&CJabberProto::OnIqResultGetClientAvatar, JABBER_IQ_TYPE_GET, szJid)) << XQUERY(JABBER_FEAT_AVATAR)); return GAIR_WAITFOR; } } } debugLogA("No avatar"); return GAIR_NOAVATAR; }
void __cdecl CJabberProto::ByteReceiveThread( JABBER_BYTE_TRANSFER *jbt ) { HXML iqNode, queryNode = NULL, n; const TCHAR *sid = NULL, *from = NULL, *to = NULL, *szId = NULL, *szHost, *szPort, *str; int i; WORD port; HANDLE hConn; char data[3]; char* buffer; int datalen, bytesParsed, recvResult; BOOL validStreamhost = FALSE; if ( jbt == NULL ) return; jbt->state = JBT_INIT; if ( iqNode = jbt->iqNode ) { from = xmlGetAttrValue( iqNode, _T("from")); to = xmlGetAttrValue( iqNode, _T("to")); szId = xmlGetAttrValue( iqNode, _T("id")); queryNode = xmlGetChild( iqNode , "query" ); if ( queryNode ) sid = xmlGetAttrValue( queryNode, _T("sid")); } if ( szId && from && to && sid && ( n = xmlGetChild( queryNode , "streamhost" ))!=NULL ) { jbt->iqId = mir_tstrdup( szId ); jbt->srcJID = mir_tstrdup( from ); jbt->dstJID = mir_tstrdup( to ); jbt->sid = mir_tstrdup( sid ); if (( buffer=( char* )mir_alloc( JABBER_NETWORK_BUFFER_SIZE ))) { for ( i=1; ( n = xmlGetNthChild( queryNode, _T("streamhost"), i ))!=NULL; i++ ) { if (( szHost = xmlGetAttrValue( n, _T("host"))) != NULL && ( szPort = xmlGetAttrValue( n, _T("port"))) != NULL && ( str = xmlGetAttrValue( n, _T("jid"))) != NULL ) { port = ( WORD )_ttoi( szPort ); if ( jbt->streamhostJID ) mir_free( jbt->streamhostJID ); jbt->streamhostJID = mir_tstrdup( str ); Log( "bytestream_recv connecting to " TCHAR_STR_PARAM ":%d", szHost, port ); NETLIBOPENCONNECTION nloc = { 0 }; nloc.cbSize = sizeof( nloc ); nloc.szHost = mir_t2a(szHost); nloc.wPort = port; hConn = ( HANDLE ) JCallService( MS_NETLIB_OPENCONNECTION, ( WPARAM ) m_hNetlibUser, ( LPARAM )&nloc ); mir_free((void*)nloc.szHost); if ( hConn == NULL ) { Log( "bytestream_recv_connection connection failed ( %d ), try next streamhost", WSAGetLastError()); continue; } jbt->hConn = hConn; data[0] = 5; data[1] = 1; data[2] = 0; Netlib_Send( hConn, data, 3, 0 ); jbt->state = JBT_INIT; datalen = 0; while ( jbt->state!=JBT_DONE && jbt->state!=JBT_ERROR && jbt->state!=JBT_SOCKSERR ) { recvResult = Netlib_Recv( hConn, buffer+datalen, JABBER_NETWORK_BUFFER_SIZE-datalen, 0 ); if ( recvResult <= 0 ) break; datalen += recvResult; bytesParsed = ByteReceiveParse( hConn, jbt, buffer, datalen ); if ( bytesParsed < datalen ) memmove( buffer, buffer+bytesParsed, datalen-bytesParsed ); datalen -= bytesParsed; if ( jbt->state == JBT_RECVING ) validStreamhost = TRUE; } Netlib_CloseHandle( hConn ); Log( "bytestream_recv_connection closing connection" ); } if ( jbt->state==JBT_ERROR || validStreamhost==TRUE ) break; Log( "bytestream_recv_connection stream cannot be established, try next streamhost" ); } mir_free( buffer ); } } (this->*jbt->pfnFinal)(( jbt->state==JBT_DONE )?TRUE:FALSE, jbt->ft ); jbt->ft = NULL; if ( !validStreamhost && szId && from ) { Log( "bytestream_recv_connection session not completed" ); m_ThreadInfo->send( XmlNodeIq( _T("error"), szId, from ) << XCHILD( _T("error")) << XATTRI( _T("code"), 404 ) << XATTR( _T("type"), _T("cancel")) << XCHILDNS( _T("item-not-found"), _T("urn:ietf:params:xml:ns:xmpp-stanzas"))); } delete jbt; Log( "Thread ended: type=bytestream_recv" ); }
void CJabberProto::ByteSendViaProxy( JABBER_BYTE_TRANSFER *jbt ) { TCHAR *szHost, *szPort; WORD port; HANDLE hConn; char data[3]; char* buffer; int datalen, bytesParsed, recvResult; BOOL validStreamhost; if ( jbt == NULL ) return; if (( buffer=( char* )mir_alloc( JABBER_NETWORK_BUFFER_SIZE )) == NULL ) { m_ThreadInfo->send( XmlNodeIq( _T("error"), jbt->iqId, jbt->srcJID ) << XCHILD( _T("error")) << XATTRI( _T("code"), 406 ) << XATTR( _T("type"), _T("auth")) << XCHILDNS( _T("not-acceptable"), _T("urn:ietf:params:xml:ns:xmpp-stanzas"))); return; } jbt->state = JBT_INIT; validStreamhost = FALSE; szPort = jbt->szProxyPort; szHost = jbt->szProxyHost; port = ( WORD )_ttoi( szPort ); if ( jbt->streamhostJID ) mir_free( jbt->streamhostJID ); jbt->streamhostJID = mir_tstrdup( jbt->szProxyJid ); NETLIBOPENCONNECTION nloc = { 0 }; nloc.cbSize = sizeof( nloc ); nloc.szHost = mir_t2a(szHost); nloc.wPort = port; hConn = ( HANDLE ) JCallService( MS_NETLIB_OPENCONNECTION, ( WPARAM ) m_hNetlibUser, ( LPARAM )&nloc ); mir_free((void*)nloc.szHost); if ( hConn != NULL ) { jbt->hConn = hConn; data[0] = 5; data[1] = 1; data[2] = 0; Netlib_Send( hConn, data, 3, 0 ); jbt->state = JBT_INIT; datalen = 0; while ( jbt->state!=JBT_DONE && jbt->state!=JBT_ERROR && jbt->state!=JBT_SOCKSERR ) { recvResult = Netlib_Recv( hConn, buffer+datalen, JABBER_NETWORK_BUFFER_SIZE-datalen, 0 ); if ( recvResult <= 0 ) break; datalen += recvResult; bytesParsed = ByteSendProxyParse( hConn, jbt, buffer, datalen ); if ( bytesParsed < datalen ) memmove( buffer, buffer+bytesParsed, datalen-bytesParsed ); datalen -= bytesParsed; if ( jbt->state == JBT_DONE ) validStreamhost = TRUE; } Netlib_CloseHandle( hConn ); } mir_free( buffer ); (this->*jbt->pfnFinal)(( jbt->state == JBT_DONE ) ? TRUE : FALSE, jbt->ft ); jbt->ft = NULL; if ( !validStreamhost ) m_ThreadInfo->send( XmlNodeIq( _T("error"), jbt->iqId, jbt->srcJID ) << XCHILD( _T("error")) << XATTRI( _T("code"), 404 ) << XATTR( _T("type"), _T("cancel")) << XCHILDNS( _T("item-not-found"), _T("urn:ietf:params:xml:ns:xmpp-stanzas"))); }
BOOL CJabberClientCapsManager::HandleInfoRequest(HXML, CJabberIqInfo *pInfo, const TCHAR *szNode) { int i; JabberCapsBits jcb = 0; if (szNode) { for (i=0; g_JabberFeatCapPairsExt[i].szFeature; i++) { if (!g_JabberFeatCapPairsExt[i].Valid()) continue; TCHAR szExtCap[ 512 ]; mir_sntprintf(szExtCap, SIZEOF(szExtCap), _T("%s#%s"), JABBER_CAPS_MIRANDA_NODE, g_JabberFeatCapPairsExt[i].szFeature); if (!_tcscmp(szNode, szExtCap)) { jcb = g_JabberFeatCapPairsExt[i].jcbCap; break; } } // check features registered through IJabberNetInterface::RegisterFeature() and IJabberNetInterface::AddFeatures() for (i=0; i < ppro->m_lstJabberFeatCapPairsDynamic.getCount(); i++) { TCHAR szExtCap[ 512 ]; mir_sntprintf(szExtCap, SIZEOF(szExtCap), _T("%s#%s"), JABBER_CAPS_MIRANDA_NODE, ppro->m_lstJabberFeatCapPairsDynamic[i]->szExt); if (!_tcscmp(szNode, szExtCap)) { jcb = ppro->m_lstJabberFeatCapPairsDynamic[i]->jcbCap; break; } } // unknown node, not XEP-0115 request if (!jcb) return FALSE; } else { jcb = JABBER_CAPS_MIRANDA_ALL; for (i=0; i < ppro->m_lstJabberFeatCapPairsDynamic.getCount(); i++) jcb |= ppro->m_lstJabberFeatCapPairsDynamic[i]->jcbCap; } if (!ppro->m_options.AllowVersionRequests) jcb &= ~JABBER_CAPS_VERSION; XmlNodeIq iq(_T("result"), pInfo); HXML query = iq << XQUERY(JABBER_FEAT_DISCO_INFO); if (szNode) query << XATTR(_T("node"), szNode); query << XCHILD(_T("identity")) << XATTR(_T("category"), _T("client")) << XATTR(_T("type"), _T("pc")) << XATTR(_T("name"), _T("Miranda")); for (i=0; g_JabberFeatCapPairs[i].szFeature; i++) if (jcb & g_JabberFeatCapPairs[i].jcbCap) query << XCHILD(_T("feature")) << XATTR(_T("var"), g_JabberFeatCapPairs[i].szFeature); for (i=0; i < ppro->m_lstJabberFeatCapPairsDynamic.getCount(); i++) if (jcb & ppro->m_lstJabberFeatCapPairsDynamic[i]->jcbCap) query << XCHILD(_T("feature")) << XATTR(_T("var"), ppro->m_lstJabberFeatCapPairsDynamic[i]->szFeature); if (ppro->m_options.AllowVersionRequests && !szNode) { TCHAR szOsBuffer[256] = {0}; TCHAR *os = szOsBuffer; if (ppro->m_options.ShowOSVersion) { if (!GetOSDisplayString(szOsBuffer, SIZEOF(szOsBuffer))) lstrcpyn(szOsBuffer, _T(""), SIZEOF(szOsBuffer)); else { TCHAR *szOsWindows = _T("Microsoft Windows"); size_t nOsWindowsLength = _tcslen(szOsWindows); if (!_tcsnicmp(szOsBuffer, szOsWindows, nOsWindowsLength)) os += nOsWindowsLength + 1; } } HXML form = query << XCHILDNS(_T("x"), JABBER_FEAT_DATA_FORMS) << XATTR(_T("type"), _T("result")); form << XCHILD(_T("field")) << XATTR(_T("var"), _T("FORM_TYPE")) << XATTR(_T("type"), _T("hidden")) << XCHILD(_T("value"), _T("urn:xmpp:dataforms:softwareinfo")); if (ppro->m_options.ShowOSVersion) { form << XCHILD(_T("field")) << XATTR(_T("var"), _T("os")) << XCHILD(_T("value"), _T("Microsoft Windows")); form << XCHILD(_T("field")) << XATTR(_T("var"), _T("os_version")) << XCHILD(_T("value"), os); } form << XCHILD(_T("field")) << XATTR(_T("var"), _T("software")) << XCHILD(_T("value"), _T("Miranda NG Jabber Protocol")); form << XCHILD(_T("field")) << XATTR(_T("var"), _T("software_version")) << XCHILD(_T("value"), _T(__VERSION_STRING_DOTS)); form << XCHILD(_T("field")) << XATTR(_T("var"), _T("x-miranda-core-version")) << XCHILD(_T("value"), szCoreVersion); } ppro->m_ThreadInfo->send(iq); return TRUE; }
void CJabberProto::SetServerVcard(BOOL bPhotoChanged, TCHAR* szPhotoFileName) { if (!m_bJabberOnline) return; int i; char idstr[33]; XmlNodeIq iq(AddIQ(&CJabberProto::OnIqResultSetVcard, JABBER_IQ_TYPE_SET)); HXML v = iq << XCHILDNS(_T("vCard"), JABBER_FEAT_VCARD_TEMP); AppendVcardFromDB(v, "FN", "FullName"); HXML n = v << XCHILD(_T("N")); AppendVcardFromDB(n, "GIVEN", "FirstName"); AppendVcardFromDB(n, "MIDDLE", "MiddleName"); AppendVcardFromDB(n, "FAMILY", "LastName"); AppendVcardFromDB(v, "NICKNAME", "Nick"); AppendVcardFromDB(v, "BDAY", "BirthDate"); AppendVcardFromDB(v, "GENDER", "GenderString"); for (i = 0;; i++) { mir_snprintf(idstr, "e-mail%d", i); ptrT email(getTStringA(idstr)); if (email == NULL) break; HXML e = v << XCHILD(_T("EMAIL"), email); AppendVcardFromDB(e, "USERID", idstr); mir_snprintf(idstr, "e-mailFlag%d", i); WORD nFlag = getWord(idstr, 0); if (nFlag & JABBER_VCEMAIL_HOME) e << XCHILD(_T("HOME")); if (nFlag & JABBER_VCEMAIL_WORK) e << XCHILD(_T("WORK")); if (nFlag & JABBER_VCEMAIL_INTERNET) e << XCHILD(_T("INTERNET")); if (nFlag & JABBER_VCEMAIL_X400) e << XCHILD(_T("X400")); } n = v << XCHILD(_T("ADR")); n << XCHILD(_T("HOME")); AppendVcardFromDB(n, "STREET", "Street"); AppendVcardFromDB(n, "EXTADR", "Street2"); AppendVcardFromDB(n, "EXTADD", "Street2"); // for compatibility with client using old vcard format AppendVcardFromDB(n, "LOCALITY", "City"); AppendVcardFromDB(n, "REGION", "State"); AppendVcardFromDB(n, "PCODE", "ZIP"); AppendVcardFromDB(n, "CTRY", "Country"); AppendVcardFromDB(n, "COUNTRY", "Country"); // for compatibility with client using old vcard format n = v << XCHILD(_T("ADR")); n << XCHILD(_T("WORK")); AppendVcardFromDB(n, "STREET", "CompanyStreet"); AppendVcardFromDB(n, "EXTADR", "CompanyStreet2"); AppendVcardFromDB(n, "EXTADD", "CompanyStreet2"); // for compatibility with client using old vcard format AppendVcardFromDB(n, "LOCALITY", "CompanyCity"); AppendVcardFromDB(n, "REGION", "CompanyState"); AppendVcardFromDB(n, "PCODE", "CompanyZIP"); AppendVcardFromDB(n, "CTRY", "CompanyCountry"); AppendVcardFromDB(n, "COUNTRY", "CompanyCountry"); // for compatibility with client using old vcard format n = v << XCHILD(_T("ORG")); AppendVcardFromDB(n, "ORGNAME", "Company"); AppendVcardFromDB(n, "ORGUNIT", "CompanyDepartment"); AppendVcardFromDB(v, "TITLE", "CompanyPosition"); AppendVcardFromDB(v, "ROLE", "Role"); AppendVcardFromDB(v, "URL", "Homepage"); AppendVcardFromDB(v, "DESC", "About"); for (i = 0;; i++) { mir_snprintf(idstr, "Phone%d", i); ptrT phone(getTStringA(idstr)); if (phone == NULL) break; n = v << XCHILD(_T("TEL")); AppendVcardFromDB(n, "NUMBER", idstr); mir_snprintf(idstr, "PhoneFlag%d", i); WORD nFlag = getWord(idstr, 0); if (nFlag & JABBER_VCTEL_HOME) n << XCHILD(_T("HOME")); if (nFlag & JABBER_VCTEL_WORK) n << XCHILD(_T("WORK")); if (nFlag & JABBER_VCTEL_VOICE) n << XCHILD(_T("VOICE")); if (nFlag & JABBER_VCTEL_FAX) n << XCHILD(_T("FAX")); if (nFlag & JABBER_VCTEL_PAGER) n << XCHILD(_T("PAGER")); if (nFlag & JABBER_VCTEL_MSG) n << XCHILD(_T("MSG")); if (nFlag & JABBER_VCTEL_CELL) n << XCHILD(_T("CELL")); if (nFlag & JABBER_VCTEL_VIDEO) n << XCHILD(_T("VIDEO")); if (nFlag & JABBER_VCTEL_BBS) n << XCHILD(_T("BBS")); if (nFlag & JABBER_VCTEL_MODEM) n << XCHILD(_T("MODEM")); if (nFlag & JABBER_VCTEL_ISDN) n << XCHILD(_T("ISDN")); if (nFlag & JABBER_VCTEL_PCS) n << XCHILD(_T("PCS")); } TCHAR szAvatarName[MAX_PATH], *szFileName; GetAvatarFileName(NULL, szAvatarName, _countof(szAvatarName)); if (bPhotoChanged) szFileName = szPhotoFileName; else szFileName = szAvatarName; // Set photo element, also update the global jabberVcardPhotoFileName to reflect the update debugLog(_T("Before update, file name = %s"), szFileName); if (szFileName == NULL || szFileName[0] == 0) { v << XCHILD(_T("PHOTO")); DeleteFile(szAvatarName); delSetting("AvatarSaved"); delSetting("AvatarHash"); } else { debugLog(_T("Saving picture from %s"), szFileName); struct _stat st; if (_tstat(szFileName, &st) >= 0) { // Note the FILE_SHARE_READ attribute so that the CopyFile can succeed HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { ptrA buffer((char*)mir_alloc(st.st_size)); if (buffer != NULL) { DWORD nRead; if (ReadFile(hFile, buffer, st.st_size, &nRead, NULL)) { ptrA str(mir_base64_encode((PBYTE)(LPSTR)buffer, nRead)); if (str != NULL) { n = v << XCHILD(_T("PHOTO")); TCHAR *szFileType; switch (ProtoGetBufferFormat(buffer)) { case PA_FORMAT_PNG: szFileType = _T("image/png"); break; case PA_FORMAT_GIF: szFileType = _T("image/gif"); break; case PA_FORMAT_BMP: szFileType = _T("image/bmp"); break; default: szFileType = _T("image/jpeg"); break; } n << XCHILD(_T("TYPE"), szFileType); n << XCHILD(_T("BINVAL"), _A2T(str)); // NEED TO UPDATE OUR AVATAR HASH: BYTE digest[MIR_SHA1_HASH_SIZE]; mir_sha1_ctx sha1ctx; mir_sha1_init(&sha1ctx); mir_sha1_append(&sha1ctx, (BYTE*)(LPSTR)buffer, nRead); mir_sha1_finish(&sha1ctx, digest); char buf[MIR_SHA1_HASH_SIZE * 2 + 1]; bin2hex(digest, sizeof(digest), buf); m_options.AvatarType = ProtoGetBufferFormat(buffer); if (bPhotoChanged) { DeleteFile(szAvatarName); GetAvatarFileName(NULL, szAvatarName, _countof(szAvatarName)); CopyFile(szFileName, szAvatarName, FALSE); } setString("AvatarHash", buf); setString("AvatarSaved", buf); } } } CloseHandle(hFile); } } } m_ThreadInfo->send(iq); }