static void JabberAdminSet( const TCHAR* to, const char* ns, const char* szItem, const TCHAR* itemVal, const char* var, const TCHAR* varVal ) { XmlNodeIq iq( "set", NOID, to ); XmlNode* query = iq.addQuery( ns ); XmlNode* item = query->addChild( "item" ); item->addAttr( szItem, itemVal ); item->addAttr( var, varVal ); JabberSend( jabberThreadInfo->s, iq ); }
XmlNode *CFormCtrlBase::CreateNode() { XmlNode* field = new XmlNode("field"); field->addAttr("var", m_field->GetVar()); field->addAttr("type", m_field->GetTypeName()); return field; }
static void InviteUser(TCHAR *room, TCHAR *pUser, TCHAR *text) { int iqId = JabberSerialNext(); XmlNode m( "message" ); m.addAttr( "from", jabberJID ); m.addAttr( "to", room ); m.addAttrID( iqId ); XmlNode* x = m.addChild( "x" ); x->addAttr( "xmlns", _T("http://jabber.org/protocol/muc#user")); XmlNode* i = x->addChild( "invite" ); i->addAttr( "to", pUser ); if ( text[0] != 0 ) i->addChild( "reason", text ); JabberSend( jabberThreadInfo->s, m ); }
XmlNode *CJabberDlgDataPage::FetchData() { XmlNode *result = new XmlNode("x"); result->addAttr("xmlns", JABBER_FEAT_DATA_FORMS); result->addAttr("type", "submit"); for (int i = 0; i < m_controls.getCount(); ++i) if (XmlNode *field = m_controls[i].FetchData()) result->addChild(field); return result; }
void JabberFtAcceptSiRequest( filetransfer* ft ) { if ( !jabberOnline || ft==NULL || ft->jid==NULL || ft->sid==NULL ) return; JABBER_LIST_ITEM *item; if (( item=JabberListAdd( LIST_FTRECV, ft->sid )) != NULL ) { item->ft = ft; XmlNodeIq iq( "result", ft->iqId, ft->jid ); XmlNode* si = iq.addChild( "si" ); si->addAttr( "xmlns", "http://jabber.org/protocol/si" ); XmlNode* f = si->addChild( "feature" ); f->addAttr( "xmlns", "http://jabber.org/protocol/feature-neg" ); XmlNode* x = f->addChild( "x" ); x->addAttr( "xmlns", "jabber:x:data" ); x->addAttr( "type", "submit" ); XmlNode* fl = x->addChild( "field" ); fl->addAttr( "var", "stream-method" ); fl->addChild( "value", "http://jabber.org/protocol/bytestreams" ); JabberSend( jabberThreadInfo->s, iq ); } }
static int JabbeSearchrRenewFields(HWND hwndDlg, JabberSearchData * dat) { char szServerName[100]; EnableWindow(GetDlgItem(hwndDlg, IDC_GO),FALSE); GetDlgItemTextA(hwndDlg,IDC_SERVER,szServerName,sizeof(szServerName)); dat->CurrentHeight = 0; dat->curPos = 0; SetScrollPos( GetDlgItem( hwndDlg, IDC_VSCROLL ), SB_CTL, 0, FALSE ); JabberSearchFreeData( hwndDlg, dat ); JabberSearchRefreshFrameScroll( hwndDlg, dat ); if ( jabberOnline ) SetDlgItemText(hwndDlg,IDC_INSTRUCTIONS,TranslateT("Please wait...\r\nConnecting search server...")); else SetDlgItemText(hwndDlg,IDC_INSTRUCTIONS,TranslateT("You have to be connected to server")); if ( !jabberOnline ) return 0; searchHandleDlg = hwndDlg; int iqId = JabberSerialNext(); XmlNodeIq iq( "get", iqId, szServerName ); XmlNode* query = iq.addChild( "query" ); query->addAttr( "xmlns", "jabber:iq:search" ); JabberIqAdd( iqId, IQ_PROC_GETSEARCHFIELDS, JabberIqResultGetSearchFields ); JabberSend( jabberThreadInfo->s, iq ); return iqId; }
static void JabberAdminGet( const TCHAR* to, const char* ns, const char* var, const TCHAR* varVal, JABBER_IQ_PFUNC foo ) { int id = JabberSerialNext(); JabberIqAdd( id, IQ_PROC_NONE, foo ); XmlNodeIq iq( "get", id, to ); XmlNode* query = iq.addQuery( ns ); XmlNode* item = query->addChild( "item" ); item->addAttr( var, varVal ); JabberSend( jabberThreadInfo->s, iq ); }
void JabberAddContactToRoster( const TCHAR* jid, const TCHAR* nick, const TCHAR* grpName, JABBER_SUBSCRIPTION subscription ) { XmlNodeIq iq( "set" ); XmlNode* query = iq.addQuery( "jabber:iq:roster" ); XmlNode* item = query->addChild( "item" ); item->addAttr( "jid", jid ); if ( nick ) item->addAttr( "name", nick ); switch( subscription ) { case SUB_BOTH: item->addAttr( "subscription", "both" ); break; case SUB_TO: item->addAttr( "subscription", "to" ); break; case SUB_FROM: item->addAttr( "subscription", "from" ); break; default: item->addAttr( "subscription", "none" ); break; } if ( grpName != NULL ) item->addChild( "group", grpName ); JabberSend( jabberThreadInfo->s, iq ); }
int JabberSearchByAdvanced( WPARAM wParam, LPARAM lParam ) { if ( !jabberOnline || !lParam) return 0; //error HWND hwndDlg=(HWND) lParam; JabberSearchData * dat=(JabberSearchData *)GetWindowLong(hwndDlg,GWL_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 char szServerName[100]; GetDlgItemTextA( hwndDlg, IDC_SERVER, szServerName, sizeof( szServerName )); // formating query int iqId = JabberSerialNext(); XmlNodeIq iq( "set", iqId, szServerName ); XmlNode* query = iq.addChild( "query" ), *field; iq.addAttr( "xml:lang", "en" ); //? not sure is it needed ? query->addAttr( "xmlns", "jabber:iq:search" ); // next can be 2 cases: // Forms: XEP-0055 Example 7 if ( dat->fSearchRequestIsXForm ) { fRequestNotEmpty=TRUE; query->addChild(JabberFormGetData(GetDlgItem(hwndDlg, IDC_FRAME), dat->xNode)); } 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')) { char* szTemp=t2a(dat->pJSInf[i].szFieldName); field = query->addChild( szTemp, szFieldValue ); mir_free(szTemp); fRequestNotEmpty=TRUE; } } } if ( fRequestNotEmpty ) { // register search request result handler JabberIqAdd( iqId, IQ_PROC_GETSEARCH, JabberIqResultAdvancedSearch ); // send request JabberSend( jabberThreadInfo->s, iq ); return iqId; } return 0; }
void JabberGroupchatJoinRoom( const TCHAR* server, const TCHAR* room, const TCHAR* nick, const TCHAR* password ) { TCHAR text[JABBER_MAX_JID_LEN]; mir_sntprintf( text, SIZEOF(text), _T("%s@%s/%s"), room, server, nick ); JABBER_LIST_ITEM* item = JabberListAdd( LIST_CHATROOM, text ); replaceStr( item->nick, nick ); int status = ( jabberStatus == ID_STATUS_INVISIBLE ) ? ID_STATUS_ONLINE : jabberStatus; XmlNode* x = new XmlNode( "x" ); x->addAttr( "xmlns", "http://jabber.org/protocol/muc" ); if ( password && password[0]!='\0' ) x->addChild( "password", password ); JabberSendPresenceTo( status, text, x ); }
static void sttNickListHook( JABBER_LIST_ITEM* item, GCHOOK* gch ) { JABBER_RESOURCE_STATUS *me = NULL, *him = NULL; for ( int i=0; i < item->resourceCount; i++ ) { JABBER_RESOURCE_STATUS& p = item->resource[i]; if ( !lstrcmp( p.resourceName, item->nick )) me = &p; if ( !lstrcmp( p.resourceName, gch->ptszUID )) him = &p; } if ( him == NULL || me == NULL ) return; TCHAR szBuffer[ 1024 ]; switch( gch->dwData ) { case IDM_LEAVE: JabberGcQuit( item, 0, 0 ); break; case IDM_VCARD: { HANDLE hContact; JABBER_SEARCH_RESULT jsr; // _tcsncpy(jsr.jid, him->jid, SIZEOF(jsr.jid)); mir_sntprintf(jsr.jid, SIZEOF(jsr.jid), _T("%s/%s"), item->jid, him->resourceName ); jsr.hdr.cbSize = sizeof(JABBER_SEARCH_RESULT); JABBER_LIST_ITEM* item = JabberListAdd( LIST_VCARD_TEMP, jsr.jid ); JabberListAddResource( LIST_VCARD_TEMP, jsr.jid, him->status, him->statusMessage); hContact=(HANDLE)CallProtoService(jabberProtoName, PS_ADDTOLIST, PALF_TEMPORARY,(LPARAM)&jsr); int iqId = JabberSerialNext(); // Requesto for version XmlNodeIq iq( "get", iqId, jsr.jid ); XmlNode* query = iq.addQuery( "jabber:iq:version" ); JabberSend( jabberThreadInfo->s, iq ); CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)hContact,0); break; } case IDM_KICK: { mir_sntprintf( szBuffer, SIZEOF(szBuffer), _T("%s %s"), TranslateT( "Reason to kick" ), him->resourceName ); if ( JabberEnterString( szBuffer, SIZEOF(szBuffer))) { XmlNodeIq iq( "set", NOID, item->jid ); XmlNode* query = iq.addQuery( xmlnsAdmin ); XmlNode* item = query->addChild( "item" ); item->addAttr( "nick", him->resourceName ); item->addAttr( "role", "none" ); item->addChild( "reason", szBuffer ); JabberSend( jabberThreadInfo->s, iq ); } break; } case IDM_BAN: mir_sntprintf( szBuffer, SIZEOF(szBuffer), _T("%s %s"), TranslateT( "Reason to ban" ), him->resourceName ); if ( JabberEnterString( szBuffer, SIZEOF(szBuffer))) { XmlNodeIq iq( "set", NOID, item->jid ); XmlNode* query = iq.addQuery( xmlnsAdmin ); XmlNode* item = query->addChild( "item" ); item->addAttr( "nick", him->resourceName ); item->addAttr( "affiliation", "outcast" ); item->addChild( "reason", szBuffer ); JabberSend( jabberThreadInfo->s, iq ); } break; case IDM_VOICE: JabberAdminSet( item->jid, xmlnsAdmin, "nick", him->resourceName, "role", ( him->role == ROLE_PARTICIPANT ) ? _T("visitor") : _T("participant")); break; case IDM_MODERATOR: JabberAdminSet( item->jid, xmlnsAdmin, "nick", him->resourceName, "role", ( him->role == ROLE_MODERATOR ) ? _T("participant") : _T("moderator")); break; case IDM_ADMIN: JabberAdminSet( item->jid, xmlnsAdmin, "nick", him->resourceName, "affiliation", ( him->affiliation==AFFILIATION_ADMIN )? _T("member") : _T("admin")); break; case IDM_OWNER: JabberAdminSet( item->jid, xmlnsAdmin, "nick", him->resourceName, "affiliation", ( him->affiliation==AFFILIATION_OWNER ) ? _T("admin") : _T("owner")); break; } }
static BOOL CALLBACK JabberGroupchatDlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) { HWND lv; LVCOLUMN lvCol; LVITEM lvItem; JABBER_LIST_ITEM *item; switch ( msg ) { case WM_INITDIALOG: // lParam is the initial conference server ( if any ) SendMessage( hwndDlg, WM_SETICON, ICON_BIG, ( LPARAM )iconBigList[0] ); TranslateDialogDefault( hwndDlg ); sortColumn = -1; // Add columns lv = GetDlgItem( hwndDlg, IDC_ROOM ); lvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; lvCol.pszText = TranslateT( "JID" ); lvCol.cx = 210; lvCol.iSubItem = 0; ListView_InsertColumn( lv, 0, &lvCol ); lvCol.pszText = TranslateT( "Name" ); lvCol.cx = 150; lvCol.iSubItem = 1; ListView_InsertColumn( lv, 1, &lvCol ); lvCol.pszText = TranslateT( "Type" ); lvCol.cx = 60; lvCol.iSubItem = 2; ListView_InsertColumn( lv, 2, &lvCol ); if ( jabberOnline ) { if (( TCHAR* )lParam != NULL ) { SetDlgItemText( hwndDlg, IDC_SERVER, ( TCHAR* )lParam ); int iqId = JabberSerialNext(); JabberIqAdd( iqId, IQ_PROC_DISCOROOMSERVER, JabberIqResultDiscoRoomItems ); XmlNodeIq iq( "get", iqId, ( TCHAR* )lParam ); XmlNode* query = iq.addQuery( "http://jabber.org/protocol/disco#items" ); JabberSend( jabberThreadInfo->s, iq ); } else { for ( int i=0; i < GC_SERVER_LIST_SIZE; i++ ) { char text[100]; mir_snprintf( text, sizeof( text ), "GcServerLast%d", i ); DBVARIANT dbv; if ( !JGetStringT( NULL, text, &dbv )) { SendDlgItemMessage( hwndDlg, IDC_SERVER, CB_ADDSTRING, 0, ( LPARAM )dbv.ptszVal ); JFreeVariant( &dbv ); } } } } else EnableWindow( GetDlgItem( hwndDlg, IDC_JOIN ), FALSE ); return TRUE; case WM_JABBER_ACTIVATE: // lParam = server from which agent information is obtained if ( lParam ) SetDlgItemText( hwndDlg, IDC_SERVER, ( TCHAR* )lParam ); ListView_DeleteAllItems( GetDlgItem( hwndDlg, IDC_ROOM )); EnableWindow( GetDlgItem( hwndDlg, IDC_BROWSE ), FALSE ); return TRUE; case WM_JABBER_REFRESH: // lParam = server from which agent information is obtained { int i; TCHAR szBuffer[256]; char text[128]; if ( lParam ){ _tcsncpy( szBuffer, ( TCHAR* )lParam, SIZEOF( szBuffer )); for ( i=0; i<GC_SERVER_LIST_SIZE; i++ ) { mir_snprintf( text, SIZEOF( text ), "GcServerLast%d", i ); DBVARIANT dbv; if ( !JGetStringT( NULL, text, &dbv )) { JSetStringT( NULL, text, szBuffer ); if ( !_tcsicmp( dbv.ptszVal, ( TCHAR* )lParam )) { JFreeVariant( &dbv ); break; } _tcsncpy( szBuffer, dbv.ptszVal, SIZEOF( szBuffer )); JFreeVariant( &dbv ); } else { JSetStringT( NULL, text, szBuffer ); break; } } SendDlgItemMessage( hwndDlg, IDC_SERVER, CB_RESETCONTENT, 0, 0 ); for ( i=0; i<GC_SERVER_LIST_SIZE; i++ ) { mir_snprintf( text, SIZEOF( text ), "GcServerLast%d", i ); DBVARIANT dbv; if ( !JGetStringT( NULL, text, &dbv )) { SendDlgItemMessage( hwndDlg, IDC_SERVER, CB_ADDSTRING, 0, ( LPARAM )dbv.ptszVal ); JFreeVariant( &dbv ); } } SetDlgItemText( hwndDlg, IDC_SERVER, ( TCHAR* )lParam ); } i = 0; lv = GetDlgItem( hwndDlg, IDC_ROOM ); ListView_DeleteAllItems( lv ); LVITEM lvItem; lvItem.iItem = 0; while (( i=JabberListFindNext( LIST_ROOM, i )) >= 0 ) { if (( item=JabberListGetItemPtrFromIndex( i )) != NULL ) { lvItem.mask = LVIF_PARAM | LVIF_TEXT; lvItem.iSubItem = 0; _tcsncpy( szBuffer, item->jid, SIZEOF(szBuffer)); szBuffer[ SIZEOF(szBuffer)-1 ] = 0; lvItem.lParam = ( LPARAM )item->jid; lvItem.pszText = szBuffer; ListView_InsertItem( lv, &lvItem ); lvItem.mask = LVIF_TEXT; lvItem.iSubItem = 1; lvItem.pszText = item->name; ListView_SetItem( lv, &lvItem ); lvItem.iSubItem = 2; lvItem.pszText = item->type; ListView_SetItem( lv, &lvItem ); lvItem.iItem++; } i++; } EnableWindow( GetDlgItem( hwndDlg, IDC_BROWSE ), TRUE ); } return TRUE; case WM_JABBER_CHECK_ONLINE: { TCHAR text[128]; if ( jabberOnline ) { EnableWindow( GetDlgItem( hwndDlg, IDC_JOIN ), TRUE ); GetDlgItemText( hwndDlg, IDC_SERVER, text, SIZEOF( text )); EnableWindow( GetDlgItem( hwndDlg, IDC_BROWSE ), ( text[0]!='\0' )); } else { EnableWindow( GetDlgItem( hwndDlg, IDC_JOIN ), FALSE ); EnableWindow( GetDlgItem( hwndDlg, IDC_BROWSE ), FALSE ); SetDlgItemTextA( hwndDlg, IDC_SERVER, "" ); lv = GetDlgItem( hwndDlg, IDC_ROOM ); ListView_DeleteAllItems( lv ); } break; } case WM_NOTIFY: switch ( wParam ) { case IDC_ROOM: switch (( ( LPNMHDR )lParam )->code ) { case LVN_COLUMNCLICK: { LPNMLISTVIEW pnmlv = ( LPNMLISTVIEW ) lParam; if ( pnmlv->iSubItem>=0 && pnmlv->iSubItem<=1 ) { if ( pnmlv->iSubItem == sortColumn ) sortAscending = !sortAscending; else { sortAscending = TRUE; sortColumn = pnmlv->iSubItem; } ListView_SortItems( GetDlgItem( hwndDlg, IDC_ROOM ), GroupchatCompare, sortColumn ); } } break; } break; } break; case WM_COMMAND: switch ( LOWORD( wParam )) { case WM_JABBER_JOIN: if ( jabberChatDllPresent ) { lv = GetDlgItem( hwndDlg, IDC_ROOM ); if (( lvItem.iItem=ListView_GetNextItem( lv, -1, LVNI_SELECTED )) >= 0 ) { lvItem.iSubItem = 0; lvItem.mask = LVIF_PARAM; ListView_GetItem( lv, &lvItem ); ListView_SetItemState( lv, lvItem.iItem, 0, LVIS_SELECTED ); // Unselect the item DialogBoxParam( hInst, MAKEINTRESOURCE( IDD_GROUPCHAT_JOIN ), hwndDlg, JabberGroupchatJoinDlgProc, ( LPARAM )lvItem.lParam ); } else { TCHAR text[128]; GetDlgItemText( hwndDlg, IDC_SERVER, text, SIZEOF( text )); DialogBoxParam( hInst, MAKEINTRESOURCE( IDD_GROUPCHAT_JOIN ), hwndDlg, JabberGroupchatJoinDlgProc, ( LPARAM )text ); } } else JabberChatDllError(); return TRUE; case WM_JABBER_ADD_TO_ROSTER: lv = GetDlgItem( hwndDlg, IDC_ROOM ); if (( lvItem.iItem=ListView_GetNextItem( lv, -1, LVNI_SELECTED )) >= 0 ) { lvItem.iSubItem = 0; lvItem.mask = LVIF_PARAM; ListView_GetItem( lv, &lvItem ); TCHAR* jid = ( TCHAR* )lvItem.lParam; { GCSESSION gcw = {0}; gcw.cbSize = sizeof(GCSESSION); gcw.iType = GCW_CHATROOM; gcw.pszID = t2a(jid); gcw.pszModule = jabberProtoName; gcw.pszName = NEWSTR_ALLOCA(gcw.pszID); char* p = ( char* )strchr( gcw.pszName, '@' ); if ( p != NULL ) *p = 0; CallService( MS_GC_NEWSESSION, 0, ( LPARAM )&gcw ); mir_free((void*)gcw.pszID); } { XmlNodeIq iq( "set" ); XmlNode* query = iq.addQuery( "jabber:iq:roster" ); XmlNode* item = query->addChild( "item" ); item->addAttr( "jid", jid ); JabberSend( jabberThreadInfo->s, iq ); } { XmlNode p( "presence" ); p.addAttr( "to", jid ); p.addAttr( "type", "subscribe" ); JabberSend( jabberThreadInfo->s, p ); } } break; case WM_JABBER_ADD_TO_BOOKMARKS: lv = GetDlgItem( hwndDlg, IDC_ROOM ); if (( lvItem.iItem=ListView_GetNextItem( lv, -1, LVNI_SELECTED )) >= 0 ) { lvItem.iSubItem = 0; lvItem.mask = LVIF_PARAM; ListView_GetItem( lv, &lvItem ); JABBER_LIST_ITEM* item = JabberListGetItemPtr( LIST_BOOKMARK, ( TCHAR* )lvItem.lParam ); if ( item == NULL ) { item = JabberListGetItemPtr( LIST_ROOM, ( TCHAR* )lvItem.lParam ); if (item != NULL) { item->type = _T("conference"); JabberAddEditBookmark(NULL, (LPARAM) item); } } } break; case IDC_SERVER: { TCHAR text[ 128 ]; GetDlgItemText( hwndDlg, IDC_SERVER, text, SIZEOF( text )); if ( jabberOnline && ( text[0] || HIWORD( wParam )==CBN_SELCHANGE )) EnableWindow( GetDlgItem( hwndDlg, IDC_BROWSE ), TRUE ); break; } case IDC_BROWSE: { TCHAR text[ 128 ]; GetDlgItemText( hwndDlg, IDC_SERVER, text, SIZEOF( text )); if ( jabberOnline && text[0] ) { EnableWindow( GetDlgItem( hwndDlg, IDC_BROWSE ), FALSE ); ListView_DeleteAllItems( GetDlgItem( hwndDlg, IDC_ROOM )); GetDlgItemText( hwndDlg, IDC_SERVER, text, SIZEOF( text )); int iqId = JabberSerialNext(); JabberIqAdd( iqId, IQ_PROC_DISCOROOMSERVER, JabberIqResultDiscoRoomItems ); XmlNodeIq iq( "get", iqId, text ); XmlNode* query = iq.addQuery( "http://jabber.org/protocol/disco#items" ); JabberSend( jabberThreadInfo->s, iq ); } return TRUE; } case IDCLOSE: DestroyWindow( hwndDlg ); return TRUE; } break; case WM_CONTEXTMENU: if (( HWND )wParam == GetDlgItem( hwndDlg, IDC_ROOM )) { HMENU hMenu = CreatePopupMenu(); AppendMenu( hMenu, MF_STRING, WM_JABBER_JOIN, TranslateT( "Join" )); AppendMenu( hMenu, MF_STRING, WM_JABBER_ADD_TO_ROSTER, TranslateT( "Add to roster" )); if ( jabberThreadInfo->caps & CAPS_BOOKMARK ) AppendMenu( hMenu, MF_STRING, WM_JABBER_ADD_TO_BOOKMARKS, TranslateT( "Add to Bookmarks" )); TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_NONOTIFY, LOWORD(lParam), HIWORD(lParam), 0, hwndDlg, 0 ); ::DestroyMenu( hMenu ); return TRUE; } break; case WM_CLOSE: DestroyWindow( hwndDlg ); break; case WM_DESTROY: hwndJabberGroupchat = NULL; break; } return FALSE; }
void JabberFtInitiate( TCHAR* jid, filetransfer* ft ) { int iqId; TCHAR *rs; char *filename, *p; TCHAR idStr[32]; JABBER_LIST_ITEM *item; int i; TCHAR sid[9]; if ( jid==NULL || ft==NULL || !jabberOnline || ( rs=JabberListGetBestClientResourceNamePtr( jid ))==NULL ) { JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); delete ft; return; } iqId = JabberSerialNext(); JabberIqAdd( iqId, IQ_PROC_NONE, JabberFtSiResult ); mir_sntprintf( idStr, SIZEOF( idStr ), _T(JABBER_IQID)_T("%d"), iqId ); if (( item=JabberListAdd( LIST_FTSEND, idStr )) == NULL ) { JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); delete ft; return; } item->ft = ft; ft->type = FT_SI; for ( i=0; i<8; i++ ) sid[i] = ( rand()%10 ) + '0'; sid[8] = '\0'; if ( ft->sid != NULL ) mir_free( ft->sid ); ft->sid = mir_tstrdup( sid ); filename = ft->std.files[ ft->std.currentFileNumber ]; if (( p=strrchr( filename, '\\' )) != NULL ) filename = p+1; TCHAR tszJid[200]; mir_sntprintf( tszJid, SIZEOF(tszJid), _T("%s/%s"), jid, rs ); XmlNodeIq iq( "set", iqId, tszJid ); XmlNode* si = iq.addChild( "si" ); si->addAttr( "xmlns", "http://jabber.org/protocol/si" ); si->addAttr( "id", sid ); si->addAttr( "mime-type", "binary/octet-stream" ); si->addAttr( "profile", "http://jabber.org/protocol/si/profile/file-transfer" ); XmlNode* file = si->addChild( "file" ); file->addAttr( "name", filename ); file->addAttr( "size", ft->fileSize[ ft->std.currentFileNumber ] ); file->addAttr( "xmlns", "http://jabber.org/protocol/si/profile/file-transfer" ); file->addChild( "desc", ft->szDescription ); XmlNode* feature = si->addChild( "feature" ); feature->addAttr( "xmlns", "http://jabber.org/protocol/feature-neg" ); XmlNode* x = feature->addChild( "x" ); x->addAttr( "xmlns", "jabber:x:data" ); x->addAttr( "type", "form" ); XmlNode* field = x->addChild( "field" ); field->addAttr( "var", "stream-method" ); field->addAttr( "type", "list-single" ); XmlNode* option = field->addChild( "option" ); option->addChild( "value", "http://jabber.org/protocol/bytestreams" ); JabberSend( jabberThreadInfo->s, iq ); }
void JabberFtHandleSiRequest( XmlNode *iqNode ) { TCHAR* from, *sid, *str, *szId, *filename; XmlNode *siNode, *fileNode, *featureNode, *xNode, *fieldNode, *optionNode, *n; int filesize, i; JABBER_FT_TYPE ftType; if ( iqNode==NULL || ( from=JabberXmlGetAttrValue( iqNode, "from" ))==NULL || ( str=JabberXmlGetAttrValue( iqNode, "type" ))==NULL || _tcscmp( str, _T("set")) || ( siNode=JabberXmlGetChildWithGivenAttrValue( iqNode, "si", "xmlns", _T("http://jabber.org/protocol/si"))) == NULL ) return; szId = JabberXmlGetAttrValue( iqNode, "id" ); if (( sid=JabberXmlGetAttrValue( siNode, "id" ))!=NULL && ( fileNode=JabberXmlGetChildWithGivenAttrValue( siNode, "file", "xmlns", _T("http://jabber.org/protocol/si/profile/file-transfer")))!=NULL && ( filename=JabberXmlGetAttrValue( fileNode, "name" ))!=NULL && ( str=JabberXmlGetAttrValue( fileNode, "size" ))!=NULL ) { filesize = _ttoi( str ); if (( featureNode=JabberXmlGetChildWithGivenAttrValue( siNode, "feature", "xmlns", _T("http://jabber.org/protocol/feature-neg"))) != NULL && ( xNode=JabberXmlGetChildWithGivenAttrValue( featureNode, "x", "xmlns", _T("jabber:x:data")))!=NULL && ( fieldNode=JabberXmlGetChildWithGivenAttrValue( xNode, "field", "var", _T("stream-method")))!=NULL ) { for ( i=0; i<fieldNode->numChild; i++ ) { optionNode = fieldNode->child[i]; if ( optionNode->name && !strcmp( optionNode->name, "option" )) { if (( n=JabberXmlGetChild( optionNode, "value" ))!=NULL && n->text ) { if ( !_tcscmp( n->text, _T("http://jabber.org/protocol/bytestreams"))) { ftType = FT_BYTESTREAM; break; } } } } if ( i < fieldNode->numChild ) { // Found known stream mechanism CCSDATA ccs; PROTORECVEVENT pre; char *localFilename = t2a( filename ); char *desc = (( n=JabberXmlGetChild( fileNode, "desc" ))!=NULL && n->text!=NULL ) ? t2a( n->text ) : mir_strdup( "" ); filetransfer* ft = new filetransfer; ft->jid = mir_tstrdup( from ); ft->std.hContact = JabberHContactFromJID( from ); ft->sid = mir_tstrdup( sid ); ft->iqId = mir_tstrdup( szId ); ft->type = ftType; ft->std.totalFiles = 1; ft->std.currentFile = localFilename; ft->std.totalBytes = ft->std.currentFileSize = filesize; char* szBlob = ( char* )alloca( sizeof( DWORD )+ strlen( localFilename ) + strlen( desc ) + 2 ); *(( PDWORD ) szBlob ) = ( DWORD )ft; strcpy( szBlob + sizeof( DWORD ), localFilename ); strcpy( szBlob + sizeof( DWORD )+ strlen( localFilename ) + 1, desc ); pre.flags = 0; pre.timestamp = time( NULL ); pre.szMessage = szBlob; pre.lParam = 0; ccs.szProtoService = PSR_FILE; ccs.hContact = ft->std.hContact; ccs.wParam = 0; ccs.lParam = ( LPARAM )⪯ JCallService( MS_PROTO_CHAINRECV, 0, ( LPARAM )&ccs ); mir_free( desc ); return; } else { // Unknown stream mechanism XmlNodeIq iq( "error", szId, from ); XmlNode* e = iq.addChild( "error" ); e->addAttr( "code", 400 ); e->addAttr( "type", "cancel" ); XmlNode* br = e->addChild( "bad-request" ); br->addAttr( "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas" ); XmlNode* nvs = e->addChild( "no-valid-streams" ); nvs->addAttr( "xmlns", "http://jabber.org/protocol/si" ); JabberSend( jabberThreadInfo->s, iq ); return; } } } // Bad stream initiation, reply with bad-profile XmlNodeIq iq( "error", szId, from ); XmlNode* e = iq.addChild( "error" ); e->addAttr( "code", 400 ); e->addAttr( "type", "cancel" ); XmlNode* br = e->addChild( "bad-request" ); br->addAttr( "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas" ); XmlNode* nvs = e->addChild( "bad-profile" ); nvs->addAttr( "xmlns", "http://jabber.org/protocol/si" ); JabberSend( jabberThreadInfo->s, iq ); }