void XPath::ProcessPath(LookupInfo &info, bool bCreate) { if (!info.nodeName) return; TCHAR *nodeName = (TCHAR *)alloca(sizeof(TCHAR) * (info.nodeName.length+1)); mir_tstrncpy(nodeName, info.nodeName.p, info.nodeName.length+1); if (info.attrName && info.attrValue) { TCHAR *attrName = (TCHAR *)alloca(sizeof(TCHAR)* (info.attrName.length + 1)); mir_tstrncpy(attrName, info.attrName.p, info.attrName.length + 1); TCHAR *attrValue = (TCHAR *)alloca(sizeof(TCHAR)* (info.attrValue.length + 1)); mir_tstrncpy(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 = mir_tstrcmp(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(); }
BOOL CJabberProto::OnIqProcessIqOldTime(HXML, CJabberIqInfo *pInfo) { struct tm *gmt; time_t ltime; TCHAR stime[100], *dtime; _tzset(); time(<ime); gmt = gmtime(<ime); mir_sntprintf(stime, _countof(stime), _T("%.4i%.2i%.2iT%.2i:%.2i:%.2i"), gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min, gmt->tm_sec); dtime = _tctime(<ime); dtime[24] = 0; XmlNodeIq iq(_T("result"), pInfo); HXML queryNode = iq << XQUERY(JABBER_FEAT_ENTITY_TIME_OLD); queryNode << XCHILD(_T("utc"), stime); LPCTSTR szTZName = TimeZone_GetName(NULL); if (szTZName) queryNode << XCHILD(_T("tz"), szTZName); queryNode << XCHILD(_T("display"), dtime); m_ThreadInfo->send(iq); return TRUE; }
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); }
void CJabberProto::GroupchatJoinRoom( const TCHAR* server, const TCHAR* room, const TCHAR* nick, const TCHAR* password, bool autojoin ) { JabberGcRecentInfo info( this ); int i = 0; bool found = false; for (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 jid[512]; mir_sntprintf( jid, SIZEOF(jid), _T("%s@%s/%s"), room, server, nick ); JABBER_LIST_ITEM* item = ListAdd( LIST_CHATROOM, jid ); item->bAutoJoin = autojoin; replaceStr( item->nick, nick ); replaceStr( item->password, info.password ); int status = ( m_iStatus == ID_STATUS_INVISIBLE ) ? ID_STATUS_ONLINE : m_iStatus; XmlNode x( _T("x")); x << XATTR( _T("xmlns"), _T(JABBER_FEAT_MUC)); if ( info.password && info.password[0] ) x << XCHILD( _T("password"), info.password ); if (m_options.GcLogChatHistory) { HANDLE hContact = ChatRoomHContactFromJID(jid); time_t lasteventtime = JGetDword(hContact, "muc_lastevent", 0); if (hContact && lasteventtime) { TCHAR lasteventdate[40]; tmi.printTimeStamp(UTC_TIME_HANDLE, lasteventtime, _T("I"), lasteventdate, SIZEOF(lasteventdate), 0); x << XCHILD( _T("history") ) << XATTR( _T("since"), lasteventdate); } } SendPresenceTo( status, jid, x ); }
void CNoteList::SaveXml(HXML hXmlParent) { m_bIsModified = false; CNoteList &me = *this; for (int i = 0; i < getCount(); ++i) { HXML hXmlItem = hXmlParent << XCHILD(_T("note")); hXmlItem << XATTR(_T("from"), me[i].GetFrom()) << XATTR(_T("tags"), me[i].GetTagsStr()); hXmlItem << XCHILD(_T("title"), me[i].GetTitle()); hXmlItem << XCHILD(_T("text"), me[i].GetText()); } }
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; }
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; }
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; }
void __cdecl CJabberProto::OnAddContactForever(DBCONTACTWRITESETTING *cws, HANDLE hContact) { if (cws->value.type != DBVT_DELETED && !(cws->value.type == DBVT_BYTE && cws->value.bVal == 0)) return; ptrT jid(getTStringA(hContact, "jid")); if (jid == NULL) return; debugLogA("Add %S permanently to list", jid); ptrT nick(db_get_tsa(hContact, "CList", "MyHandle")); if (nick == NULL) nick = getTStringA(hContact, "Nick"); if (nick == NULL) nick = JabberNickFromJID(jid); if (nick == NULL) return; AddContactToRoster(jid, nick, ptrT(db_get_tsa(hContact, "CList", "Group"))); XmlNode xPresence(_T("presence")); xPresence << XATTR(_T("to"), LPCTSTR(jid)) << XATTR(_T("type"), _T("subscribe")); ptrT myNick(getTStringA(NULL, "Nick")); if (myNick != NULL) xPresence << XCHILD(_T("nick"), LPCTSTR(myNick)) << XATTR(_T("xmlns"), JABBER_FEAT_NICK); m_ThreadInfo->send(xPresence); SendGetVcard(jid); db_unset(hContact, "CList", "Hidden"); }
void CJabberProto::AppendVcardFromDB(HXML n, char *tag, char *key) { if (n == NULL || tag == NULL || key == NULL) return; ptrT tszValue(getTStringA(key)); n << XCHILD(_A2T(tag), tszValue); }
// 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; }
BOOL CJabberProto::OnIqRequestVersion(HXML, CJabberIqInfo *pInfo) { if (!pInfo->GetFrom()) return TRUE; if (!m_options.AllowVersionRequests) return FALSE; XmlNodeIq iq(_T("result"), pInfo); HXML query = iq << XQUERY(JABBER_FEAT_VERSION); query << XCHILD(_T("name"), _T("Miranda NG Jabber")); query << XCHILD(_T("version"), szCoreVersion); if (m_options.ShowOSVersion) { TCHAR os[256] = { 0 }; if (!GetOSDisplayString(os, _countof(os))) mir_tstrncpy(os, _T("Microsoft Windows"), _countof(os)); query << XCHILD(_T("os"), os); } 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; }
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::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; }
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; }
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::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::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 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); }
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" ); }
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"))); }
static INT_PTR CALLBACK JabberChangePasswordDlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) { CJabberProto* ppro = (CJabberProto*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA ); switch ( msg ) { case WM_INITDIALOG: ppro = (CJabberProto*)lParam; SetWindowLongPtr( hwndDlg, GWLP_USERDATA, ( LONG_PTR )lParam ); WindowSetIcon( hwndDlg, ppro, "key" ); TranslateDialogDefault( hwndDlg ); if ( ppro->m_bJabberOnline && ppro->m_ThreadInfo!=NULL ) { TCHAR text[1024]; mir_sntprintf( text, SIZEOF( text ), _T("%s %s@") _T(TCHAR_STR_PARAM), TranslateT( "Set New Password for" ), ppro->m_ThreadInfo->username, ppro->m_ThreadInfo->server ); SetWindowText( hwndDlg, text ); } return TRUE; case WM_COMMAND: switch ( LOWORD( wParam )) { case IDOK: if ( ppro->m_bJabberOnline && ppro->m_ThreadInfo!=NULL ) { TCHAR newPasswd[512], text[512]; GetDlgItemText( hwndDlg, IDC_NEWPASSWD, newPasswd, SIZEOF( newPasswd )); GetDlgItemText( hwndDlg, IDC_NEWPASSWD2, text, SIZEOF( text )); if ( _tcscmp( newPasswd, text )) { MessageBox( hwndDlg, TranslateT( "New password does not match." ), TranslateT( "Change Password" ), MB_OK|MB_ICONSTOP|MB_SETFOREGROUND ); break; } GetDlgItemText( hwndDlg, IDC_OLDPASSWD, text, SIZEOF( text )); if ( _tcscmp( text, ppro->m_ThreadInfo->password )) { MessageBox( hwndDlg, TranslateT( "Current password is incorrect." ), TranslateT( "Change Password" ), MB_OK|MB_ICONSTOP|MB_SETFOREGROUND ); break; } _tcsncpy( ppro->m_ThreadInfo->newPassword, newPasswd, SIZEOF( ppro->m_ThreadInfo->newPassword )); int iqId = ppro->SerialNext(); ppro->IqAdd( iqId, IQ_PROC_NONE, &CJabberProto::OnIqResultSetPassword ); XmlNodeIq iq( _T("set"), iqId, _A2T(ppro->m_ThreadInfo->server)); HXML q = iq << XQUERY( _T(JABBER_FEAT_REGISTER)); q << XCHILD( _T("username"), ppro->m_ThreadInfo->username ); q << XCHILD( _T("password"), newPasswd ); ppro->m_ThreadInfo->send( iq ); } DestroyWindow( hwndDlg ); break; case IDCANCEL: DestroyWindow( hwndDlg ); break; } break; case WM_CLOSE: DestroyWindow( hwndDlg ); break; case WM_DESTROY: ppro->m_hwndJabberChangePassword = NULL; WindowFreeIcon( hwndDlg ); break; } return FALSE; }
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 __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; }
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" ); }