void XPath::ProcessPath(LookupInfo &info, bool bCreate) { if (!info.nodeName) return; TCHAR *nodeName = (TCHAR *)alloca(sizeof(TCHAR) * (info.nodeName.length+1)); lstrcpyn(nodeName, info.nodeName.p, info.nodeName.length+1); if (info.attrName && info.attrValue) { TCHAR *attrName = (TCHAR *)alloca(sizeof(TCHAR)* (info.attrName.length + 1)); lstrcpyn(attrName, info.attrName.p, info.attrName.length + 1); TCHAR *attrValue = (TCHAR *)alloca(sizeof(TCHAR)* (info.attrValue.length + 1)); lstrcpyn(attrValue, info.attrValue.p, info.attrValue.length + 1); HXML hXml = xmlGetChildByTag(m_hXml, nodeName, attrName, attrValue); m_hXml = (hXml || !bCreate) ? hXml : (m_hXml << XCHILD(nodeName) << XATTR(attrName, attrValue)); } else if (info.nodeIndex) { int idx = _ttoi(info.nodeIndex.p); m_hXml = lstrcmp(nodeName, _T("*")) ? xmlGetNthChild(m_hXml, nodeName, idx) : xmlGetChild(m_hXml, idx - 1); } else { HXML hXml = xmlGetChild(m_hXml, nodeName); m_hXml = (hXml || !bCreate) ? hXml : (m_hXml << XCHILD(nodeName)); } info.Reset(); }
void scroll( short n ) { register row, col; if (!OPEN) return; col = 0; for ( row = 0; row < (HEIGHT-1); row++ ) copy_row( WIDTH, (short *)&XCHAR(row+1,col), (short *)&CHAR(row,col), (short *)&XCHAR(row,col) ); // for ( col = 0; col < WIDTH; col++ ) // { // CHAR( row, col ) = XCHAR( row+1, col ); // ATTR( row, col ) = XATTR( row+1, col ); // XCHAR( row, col ) = XCHAR( row+1, col ); // XATTR( row, col ) = XATTR( row+1, col ); // } for ( col = 0; col < WIDTH; col++ ) { CHAR( HEIGHT-1, col ) = ' '; ATTR( HEIGHT-1, col ) = XATTR( HEIGHT-1, col ); XCHAR( HEIGHT-1, col ) = ' '; } }
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); }
void CJabberProto::IbbSendThread(JABBER_IBB_TRANSFER *jibb) { debugLogA("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( AddIQ(&CJabberProto::OnIbbInitiateResult, JABBER_IQ_TYPE_SET, jibb->dstJID, 0, -1, jibb)) << XCHILDNS(_T("open"), 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( AddIQ(&CJabberProto::OnIbbCloseResult, JABBER_IQ_TYPE_SET, jibb->dstJID, 0, -1, jibb)) << XCHILDNS(_T("close"), 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); }
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::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); } } }
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 __cdecl CJabberProto::OnAddContactForever( DBCONTACTWRITESETTING* cws, HANDLE hContact ) { if ( cws->value.type != DBVT_DELETED && !( cws->value.type==DBVT_BYTE && cws->value.bVal==0 )) return; DBVARIANT jid, dbv; if ( JGetStringT( hContact, "jid", &jid )) return; TCHAR *nick; Log( "Add " TCHAR_STR_PARAM " permanently to list", jid.pszVal ); if ( !DBGetContactSettingTString( hContact, "CList", "MyHandle", &dbv )) { nick = mir_tstrdup( dbv.ptszVal ); JFreeVariant( &dbv ); } else if ( !JGetStringT( hContact, "Nick", &dbv )) { nick = mir_tstrdup( dbv.ptszVal ); JFreeVariant( &dbv ); } else nick = JabberNickFromJID( jid.ptszVal ); if ( nick == NULL ) { JFreeVariant( &jid ); return; } if ( !DBGetContactSettingTString( hContact, "CList", "Group", &dbv )) { AddContactToRoster( jid.ptszVal, nick, dbv.ptszVal ); JFreeVariant( &dbv ); } else AddContactToRoster( jid.ptszVal, nick, NULL ); m_ThreadInfo->send( XmlNode( _T("presence")) << XATTR( _T("to"), jid.ptszVal ) << XATTR( _T("type"), _T("subscribe"))); SendGetVcard( jid.ptszVal ); mir_free( nick ); DBDeleteContactSetting( hContact, "CList", "Hidden" ); JFreeVariant( &jid ); }
BOOL CJabberProto::OnHandleDiscoItemsRequest(HXML iqNode, CJabberIqInfo *pInfo) { if (!pInfo->GetChildNode()) return TRUE; // ad-hoc commands check: const TCHAR *szNode = XmlGetAttrValue(pInfo->GetChildNode(), _T("node")); if (szNode && m_adhocManager.HandleItemsRequest(iqNode, pInfo, szNode)) return TRUE; // another request, send empty result XmlNodeIq iq(_T("result"), pInfo); HXML resultQuery = iq << XQUERY(JABBER_FEAT_DISCO_ITEMS); if (szNode) XmlAddAttr(resultQuery, _T("node"), szNode); if (!szNode && m_options.EnableRemoteControl) resultQuery << XCHILD(_T("item")) << XATTR(_T("jid"), m_ThreadInfo->fullJID) << XATTR(_T("node"), JABBER_FEAT_COMMANDS) << XATTR(_T("name"), _T("Ad-hoc commands")); m_ThreadInfo->send(iq); 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; }
void mrefresh(short n) { short row, col; if (!OPEN) return; for (row=-1; row<HEIGHT+1; row++ ) for (col=-1; col<WIDTH+1; col++ ) { CHAR(row,col) = XCHAR(row,col); ATTR(row,col) = XATTR(row,col); } msetcursor( ROW+CROW, COL+CCOL ); }
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; }
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; }
void mclear( short n ) { short row, col; if (!OPEN) return; for (row=0; row<HEIGHT; row++ ) for (col=0; col<WIDTH; col++ ) { CHAR(row,col) = 32; ATTR(row,col) = 7; XCHAR(row,col) = 32; XATTR(row,col) = 7; } CCOL = 0; CROW = 0; }
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; }
void CJabberProto::GroupchatJoinRoom(const TCHAR *server, const TCHAR *room, const TCHAR *nick, const TCHAR *password, bool autojoin) { JabberGcRecentInfo info(this); bool found = false; for (int i = 0; i < 5; i++) { if (!info.loadRecent(i)) continue; if (info.equals(room, server, nick, password)) { found = true; break; } } if (!found) { for (int i = 4; i--;) { if (info.loadRecent(i)) info.saveRecent(i + 1); } info.fillData(room, server, nick, password); info.saveRecent(0); } TCHAR text[JABBER_MAX_JID_LEN + 1]; mir_sntprintf(text, _T("%s@%s/%s"), room, server, nick); JABBER_LIST_ITEM *item = ListAdd(LIST_CHATROOM, text); item->bAutoJoin = autojoin; replaceStrT(item->nick, nick); replaceStrT(item->password, info.m_password); int status = (m_iStatus == ID_STATUS_INVISIBLE) ? ID_STATUS_ONLINE : m_iStatus; XmlNode x(_T("x")); x << XATTR(_T("xmlns"), JABBER_FEAT_MUC); if (info.m_password && info.m_password[0]) x << XCHILD(_T("password"), info.m_password); SendPresenceTo(status, text, x); }
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; }
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; }
JabberCapsBits CJabberProto::GetResourceCapabilites(const TCHAR *jid, BOOL appendBestResource) { TCHAR fullJid[JABBER_MAX_JID_LEN]; if (appendBestResource) GetClientJID(jid, fullJid, SIZEOF(fullJid)); else _tcsncpy(fullJid, jid, SIZEOF(fullJid)); pResourceStatus r(ResourceInfoFromJID(fullJid)); if (r == NULL) return JABBER_RESOURCE_CAPS_ERROR; // XEP-0115 mode if (r->m_tszCapsNode && r->m_tszCapsVer) { JabberCapsBits jcbCaps = 0, jcbExtCaps = 0; BOOL bRequestSent = FALSE; JabberCapsBits jcbMainCaps = m_clientCapsManager.GetClientCaps(r->m_tszCapsNode, r->m_tszCapsVer); if (jcbMainCaps == JABBER_RESOURCE_CAPS_TIMEOUT && !r->m_dwDiscoInfoRequestTime) jcbMainCaps = JABBER_RESOURCE_CAPS_ERROR; if (jcbMainCaps == JABBER_RESOURCE_CAPS_UNINIT) { // send disco#info query CJabberIqInfo *pInfo = AddIQ(&CJabberProto::OnIqResultCapsDiscoInfo, JABBER_IQ_TYPE_GET, fullJid, JABBER_IQ_PARSE_FROM | JABBER_IQ_PARSE_CHILD_TAG_NODE); pInfo->SetTimeout(JABBER_RESOURCE_CAPS_QUERY_TIMEOUT); m_clientCapsManager.SetClientCaps(r->m_tszCapsNode, r->m_tszCapsVer, JABBER_RESOURCE_CAPS_IN_PROGRESS, pInfo->GetIqId()); r->m_dwDiscoInfoRequestTime = pInfo->GetRequestTime(); TCHAR queryNode[512]; mir_sntprintf(queryNode, SIZEOF(queryNode), _T("%s#%s"), r->m_tszCapsNode, r->m_tszCapsVer); m_ThreadInfo->send(XmlNodeIq(pInfo) << XQUERY(JABBER_FEAT_DISCO_INFO) << XATTR(_T("node"), queryNode)); bRequestSent = TRUE; } else if (jcbMainCaps == JABBER_RESOURCE_CAPS_IN_PROGRESS) bRequestSent = TRUE; else if (jcbMainCaps != JABBER_RESOURCE_CAPS_TIMEOUT) jcbCaps |= jcbMainCaps; if (jcbMainCaps != JABBER_RESOURCE_CAPS_TIMEOUT && r->m_tszCapsExt) { TCHAR *caps = mir_tstrdup(r->m_tszCapsExt); TCHAR *token = _tcstok(caps, _T(" ")); while (token) { switch (jcbExtCaps = m_clientCapsManager.GetClientCaps(r->m_tszCapsNode, token)) { case JABBER_RESOURCE_CAPS_ERROR: break; case JABBER_RESOURCE_CAPS_UNINIT: { // send disco#info query CJabberIqInfo *pInfo = AddIQ(&CJabberProto::OnIqResultCapsDiscoInfo, JABBER_IQ_TYPE_GET, fullJid, JABBER_IQ_PARSE_FROM | JABBER_IQ_PARSE_CHILD_TAG_NODE); pInfo->SetTimeout(JABBER_RESOURCE_CAPS_QUERY_TIMEOUT); m_clientCapsManager.SetClientCaps(r->m_tszCapsNode, token, JABBER_RESOURCE_CAPS_IN_PROGRESS, pInfo->GetIqId()); m_ThreadInfo->send( XmlNodeIq(pInfo) << XQUERY(JABBER_FEAT_DISCO_INFO) << XATTR(_T("node"), CMString(FORMAT, _T("%s#%s"), r->m_tszCapsNode, token))); bRequestSent = TRUE; } break; case JABBER_RESOURCE_CAPS_IN_PROGRESS: bRequestSent = TRUE; break; default: jcbCaps |= jcbExtCaps; } token = _tcstok(NULL, _T(" ")); } mir_free(caps); } if (bRequestSent) return JABBER_RESOURCE_CAPS_IN_PROGRESS; return jcbCaps | r->m_jcbManualDiscoveredCaps; } // capability mode (version request + service discovery) // no version info: if (!r->m_tszSoftwareVersion && !r->m_tszSoftware) { // version request not sent: if (!r->m_dwVersionRequestTime) { // send version query CJabberIqInfo *pInfo = AddIQ(&CJabberProto::OnIqResultVersion, JABBER_IQ_TYPE_GET, fullJid, JABBER_IQ_PARSE_FROM | JABBER_IQ_PARSE_HCONTACT | JABBER_IQ_PARSE_CHILD_TAG_NODE); pInfo->SetTimeout(JABBER_RESOURCE_CAPS_QUERY_TIMEOUT); r->m_dwVersionRequestTime = pInfo->GetRequestTime(); XmlNodeIq iq(pInfo); iq << XQUERY(JABBER_FEAT_VERSION); m_ThreadInfo->send(iq); return JABBER_RESOURCE_CAPS_IN_PROGRESS; } // version not received: else if (r->m_dwVersionRequestTime != -1) { // no timeout? if (GetTickCount() - r->m_dwVersionRequestTime < JABBER_RESOURCE_CAPS_QUERY_TIMEOUT) return JABBER_RESOURCE_CAPS_IN_PROGRESS; // timeout r->m_dwVersionRequestTime = -1; } // no version information, try direct service discovery if (!r->m_dwDiscoInfoRequestTime) { // send disco#info query CJabberIqInfo *pInfo = AddIQ(&CJabberProto::OnIqResultCapsDiscoInfo, JABBER_IQ_TYPE_GET, fullJid, JABBER_IQ_PARSE_FROM | JABBER_IQ_PARSE_CHILD_TAG_NODE); pInfo->SetTimeout(JABBER_RESOURCE_CAPS_QUERY_TIMEOUT); r->m_dwDiscoInfoRequestTime = pInfo->GetRequestTime(); XmlNodeIq iq(pInfo); iq << XQUERY(JABBER_FEAT_DISCO_INFO); m_ThreadInfo->send(iq); return JABBER_RESOURCE_CAPS_IN_PROGRESS; } else if (r->m_dwDiscoInfoRequestTime == -1) return r->m_jcbCachedCaps | r->m_jcbManualDiscoveredCaps; else if (GetTickCount() - r->m_dwDiscoInfoRequestTime < JABBER_RESOURCE_CAPS_QUERY_TIMEOUT) return JABBER_RESOURCE_CAPS_IN_PROGRESS; else r->m_dwDiscoInfoRequestTime = -1; // version request timeout: return JABBER_RESOURCE_CAPS_NONE; } // version info available: if (r->m_tszSoftware && r->m_tszSoftwareVersion) { JabberCapsBits jcbMainCaps = m_clientCapsManager.GetClientCaps(r->m_tszSoftware, r->m_tszSoftwareVersion); if (jcbMainCaps == JABBER_RESOURCE_CAPS_ERROR) { // Bombus hack: if (!_tcscmp(r->m_tszSoftware, _T("Bombus")) || !_tcscmp(r->m_tszSoftware, _T("BombusMod"))) { jcbMainCaps = JABBER_CAPS_SI | JABBER_CAPS_SI_FT | JABBER_CAPS_IBB | JABBER_CAPS_MESSAGE_EVENTS | JABBER_CAPS_MESSAGE_EVENTS_NO_DELIVERY | JABBER_CAPS_DATA_FORMS | JABBER_CAPS_LAST_ACTIVITY | JABBER_CAPS_VERSION | JABBER_CAPS_COMMANDS | JABBER_CAPS_VCARD_TEMP; m_clientCapsManager.SetClientCaps(r->m_tszSoftware, r->m_tszSoftwareVersion, jcbMainCaps); } // Neos hack: else if (!_tcscmp(r->m_tszSoftware, _T("neos"))) { jcbMainCaps = JABBER_CAPS_OOB | JABBER_CAPS_MESSAGE_EVENTS | JABBER_CAPS_MESSAGE_EVENTS_NO_DELIVERY | JABBER_CAPS_LAST_ACTIVITY | JABBER_CAPS_VERSION; m_clientCapsManager.SetClientCaps(r->m_tszSoftware, r->m_tszSoftwareVersion, jcbMainCaps); } // sim hack: else if (!_tcscmp(r->m_tszSoftware, _T("sim"))) { jcbMainCaps = JABBER_CAPS_OOB | JABBER_CAPS_VERSION | JABBER_CAPS_MESSAGE_EVENTS | JABBER_CAPS_MESSAGE_EVENTS_NO_DELIVERY; m_clientCapsManager.SetClientCaps(r->m_tszSoftware, r->m_tszSoftwareVersion, jcbMainCaps); } } else if (jcbMainCaps == JABBER_RESOURCE_CAPS_UNINIT) { // send disco#info query CJabberIqInfo *pInfo = AddIQ(&CJabberProto::OnIqResultCapsDiscoInfo, JABBER_IQ_TYPE_GET, fullJid, JABBER_IQ_PARSE_FROM | JABBER_IQ_PARSE_CHILD_TAG_NODE); pInfo->SetTimeout(JABBER_RESOURCE_CAPS_QUERY_TIMEOUT); m_clientCapsManager.SetClientCaps(r->m_tszSoftware, r->m_tszSoftwareVersion, JABBER_RESOURCE_CAPS_IN_PROGRESS, pInfo->GetIqId()); r->m_dwDiscoInfoRequestTime = pInfo->GetRequestTime(); XmlNodeIq iq(pInfo); iq << XQUERY(JABBER_FEAT_DISCO_INFO); m_ThreadInfo->send(iq); jcbMainCaps = JABBER_RESOURCE_CAPS_IN_PROGRESS; } return jcbMainCaps | r->m_jcbManualDiscoveredCaps; } return JABBER_RESOURCE_CAPS_NONE; }
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 CJabberProto::ByteReceiveParse( HANDLE hConn, JABBER_BYTE_TRANSFER *jbt, char* buffer, int datalen ) { int bytesReceived, 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[JABBER_MAX_JID_LEN*2]; 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_RECVING; m_ThreadInfo->send( XmlNodeIq( _T("result"), jbt->iqId, jbt->srcJID ) << XQUERY( _T(JABBER_FEAT_BYTESTREAMS)) << XCHILD( _T("streamhost-used")) << XATTR( _T("jid"), jbt->streamhostJID )); } else jbt->state = JBT_SOCKSERR; break; case JBT_RECVING: bytesReceived = (this->*jbt->pfnRecv)( hConn, jbt->ft, buffer, datalen ); if ( bytesReceived < 0 ) jbt->state = JBT_ERROR; else if ( bytesReceived == 0 ) jbt->state = JBT_DONE; break; } return num; }
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"))); }
void CJabberProto::ByteSendThread( JABBER_BYTE_TRANSFER *jbt ) { char* localAddr; char* localAddrInternal; struct in_addr in; DBVARIANT dbv; TCHAR szPort[8]; HANDLE hEvent = NULL; TCHAR* proxyJid; CJabberIqInfo* pInfo = NULL; int nIqId = 0; Log( "Thread started: type=bytestream_send" ); BOOL bDirect = m_options.BsDirect; if ( m_options.BsProxyManual ) { proxyJid = NULL; if ( !DBGetContactSettingString( NULL, m_szModuleName, "BsProxyServer", &dbv )) { proxyJid = mir_a2t( dbv.pszVal ); JFreeVariant( &dbv ); } if ( proxyJid ) { jbt->bProxyDiscovered = FALSE; jbt->szProxyHost = NULL; jbt->szProxyPort = NULL; jbt->szProxyJid = NULL; jbt->hProxyEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); pInfo = m_iqManager.AddHandler( &CJabberProto::IqResultProxyDiscovery, JABBER_IQ_TYPE_GET, proxyJid, 0, -1, jbt ); nIqId = pInfo->GetIqId(); XmlNodeIq iq( pInfo ); iq << XQUERY( _T(JABBER_FEAT_BYTESTREAMS)); m_ThreadInfo->send( iq ); WaitForSingleObject( jbt->hProxyEvent, INFINITE ); m_iqManager.ExpireIq ( nIqId ); CloseHandle( jbt->hProxyEvent ); jbt->hProxyEvent = NULL; mir_free( proxyJid ); if ( jbt->state == JBT_ERROR && !bDirect ) { Log( "Bytestream proxy failure" ); MsgPopup( pInfo->GetHContact(), TranslateT("Bytestream Proxy not available"), pInfo->GetReceiver()); jbt->ft->state = FT_DENIED; (this->*jbt->pfnFinal)( FALSE, jbt->ft ); jbt->ft = NULL; delete jbt; return; } } } pInfo = m_iqManager.AddHandler( &CJabberProto::ByteInitiateResult, JABBER_IQ_TYPE_SET, jbt->dstJID, 0, -1, jbt ); nIqId = pInfo->GetIqId(); { XmlNodeIq iq( pInfo ); HXML query = iq << XQUERY( _T(JABBER_FEAT_BYTESTREAMS)) << XATTR( _T("sid"), jbt->sid ); if ( bDirect ) { localAddr = NULL; if ( m_options.BsDirectManual == TRUE ) { if ( !DBGetContactSettingString( NULL, m_szModuleName, "BsDirectAddr", &dbv )) { localAddr = NEWSTR_ALLOCA( dbv.pszVal ); JFreeVariant( &dbv ); } } NETLIBBIND nlb = {0}; nlb.cbSize = sizeof( NETLIBBIND ); nlb.pfnNewConnectionV2 = JabberByteSendConnection; nlb.pExtra = this; nlb.wPort = 0; // Use user-specified incoming port ranges, if available jbt->hConn = ( HANDLE ) JCallService( MS_NETLIB_BINDPORT, ( WPARAM ) m_hNetlibUser, ( LPARAM )&nlb ); if ( jbt->hConn == NULL ) { Log( "Cannot allocate port for bytestream_send thread, thread ended." ); delete jbt; return; } if ( localAddr == NULL ) { in.S_un.S_addr = htonl(nlb.dwExternalIP); localAddr = NEWSTR_ALLOCA( inet_ntoa( in )); } in.S_un.S_addr = htonl(nlb.dwInternalIP); localAddrInternal = NEWSTR_ALLOCA( inet_ntoa( in )); mir_sntprintf( szPort, SIZEOF( szPort ), _T("%d"), nlb.wPort ); JABBER_LIST_ITEM *item = ListAdd( LIST_BYTE, szPort ); item->jbt = jbt; hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); jbt->hEvent = hEvent; jbt->hSendEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); query << XCHILD( _T("streamhost")) << XATTR( _T("jid"), m_ThreadInfo->fullJID ) << XATTR( _T("host"), _A2T(localAddr)) << XATTRI( _T("port"), nlb.wPort ); if ( strcmp( localAddr, localAddrInternal )) query << XCHILD( _T("streamhost")) << XATTR( _T("jid"), m_ThreadInfo->fullJID ) << XATTR( _T("host"), _A2T(localAddrInternal)) << XATTRI( _T("port"), nlb.wPort ); } if ( jbt->bProxyDiscovered ) query << XCHILD( _T("streamhost")) << XATTR( _T("jid"), jbt->szProxyJid ) << XATTR( _T("host"), jbt->szProxyHost ) << XATTR( _T("port"), jbt->szProxyPort ); jbt->hProxyEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); jbt->szStreamhostUsed = NULL; m_ThreadInfo->send( iq ); } WaitForSingleObject( jbt->hProxyEvent, INFINITE ); m_iqManager.ExpireIq( nIqId ); CloseHandle( jbt->hProxyEvent ); jbt->hProxyEvent = NULL; if ( !jbt->szStreamhostUsed ) { if ( bDirect ) { SetEvent( jbt->hSendEvent ); CloseHandle( jbt->hSendEvent ); CloseHandle( hEvent ); jbt->hEvent = NULL; if ( jbt->hConn != NULL ) Netlib_CloseHandle( jbt->hConn ); jbt->hConn = NULL; ListRemove( LIST_BYTE, szPort ); } (this->*jbt->pfnFinal)(( jbt->state==JBT_DONE )?TRUE:FALSE, jbt->ft ); jbt->ft = NULL; // stupid fix: wait for listening thread exit Sleep( 100 ); delete jbt; return; } if ( jbt->bProxyDiscovered && !_tcscmp( jbt->szProxyJid, jbt->szStreamhostUsed )) { // jabber proxy used if ( bDirect ) { SetEvent( jbt->hSendEvent ); CloseHandle( jbt->hSendEvent ); CloseHandle( hEvent ); jbt->hEvent = NULL; if ( jbt->hConn != NULL ) Netlib_CloseHandle( jbt->hConn ); jbt->hConn = NULL; ListRemove( LIST_BYTE, szPort ); } ByteSendViaProxy( jbt ); } else { SetEvent( jbt->hSendEvent ); WaitForSingleObject( hEvent, INFINITE ); CloseHandle( hEvent ); CloseHandle( jbt->hSendEvent ); jbt->hEvent = NULL; (this->*jbt->pfnFinal)(( jbt->state == JBT_DONE ) ? TRUE : FALSE, jbt->ft ); jbt->ft = NULL; if ( jbt->hConn != NULL ) Netlib_CloseHandle( jbt->hConn ); jbt->hConn = NULL; ListRemove( LIST_BYTE, szPort ); } // stupid fix: wait for listening connection thread exit Sleep( 100 ); delete jbt; Log( "Thread ended: type=bytestream_send" ); }
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); }
BOOL CJabberProto::OnIqRequestAvatar(HXML, CJabberIqInfo *pInfo) { if (!m_options.EnableAvatars) return TRUE; int pictureType = m_options.AvatarType; if (pictureType == PA_FORMAT_UNKNOWN) return TRUE; TCHAR *szMimeType; switch (pictureType) { case PA_FORMAT_JPEG: szMimeType = _T("image/jpeg"); break; case PA_FORMAT_GIF: szMimeType = _T("image/gif"); break; case PA_FORMAT_PNG: szMimeType = _T("image/png"); break; case PA_FORMAT_BMP: szMimeType = _T("image/bmp"); break; default: return TRUE; } TCHAR szFileName[MAX_PATH]; GetAvatarFileName(NULL, szFileName, _countof(szFileName)); FILE* in = _tfopen(szFileName, _T("rb")); if (in == NULL) return TRUE; long bytes = _filelength(_fileno(in)); ptrA buffer((char*)mir_alloc(bytes * 4 / 3 + bytes + 1000)); if (buffer == NULL) { fclose(in); return TRUE; } fread(buffer, bytes, 1, in); fclose(in); ptrA str(mir_base64_encode((PBYTE)(char*)buffer, bytes)); m_ThreadInfo->send(XmlNodeIq(_T("result"), pInfo) << XQUERY(JABBER_FEAT_AVATAR) << XCHILD(_T("query"), _A2T(str)) << XATTR(_T("mimetype"), szMimeType)); return TRUE; }
// XEP-0199: XMPP Ping support BOOL CJabberProto::OnIqRequestPing(HXML, CJabberIqInfo *pInfo) { m_ThreadInfo->send(XmlNodeIq(_T("result"), pInfo) << XATTR(_T("from"), m_ThreadInfo->fullJID)); return TRUE; }
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" ); }
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; }