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 JabberSetServerStatus( int iNewStatus ) { if ( !jabberConnected ) return; // change status int oldStatus = jabberStatus; switch ( iNewStatus ) { case ID_STATUS_ONLINE: case ID_STATUS_NA: case ID_STATUS_FREECHAT: case ID_STATUS_INVISIBLE: jabberStatus = iNewStatus; break; case ID_STATUS_AWAY: case ID_STATUS_ONTHEPHONE: case ID_STATUS_OUTTOLUNCH: jabberStatus = ID_STATUS_AWAY; break; case ID_STATUS_DND: case ID_STATUS_OCCUPIED: jabberStatus = ID_STATUS_DND; break; default: return; } // send presence update JabberSendPresence( jabberStatus, true ); JSendBroadcast( NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, ( HANDLE ) oldStatus, jabberStatus ); }
void JabberFtCancel( filetransfer* ft ) { JABBER_LIST_ITEM *item; JABBER_BYTE_TRANSFER *jbt; int i; JabberLog( "Invoking JabberFtCancel()" ); // For file sending session that is still in si negotiation phase for ( i=0; ( i=JabberListFindNext( LIST_FTSEND, i ))>=0; i++ ) { item = JabberListGetItemPtrFromIndex( i ); if ( item->ft == ft ) { JabberLog( "Canceling file sending session while in si negotiation" ); JabberListRemoveByIndex( i ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); delete ft; return; } } // For file receiving session that is still in si negotiation phase for ( i=0; ( i=JabberListFindNext( LIST_FTRECV, i ))>=0; i++ ) { item = JabberListGetItemPtrFromIndex( i ); if ( item->ft == ft ) { JabberLog( "Canceling file receiving session while in si negotiation" ); JabberListRemoveByIndex( i ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); delete ft; return; } } // For file transfer through bytestream if (( jbt=ft->jbt ) != NULL ) { JabberLog( "Canceling bytestream session" ); jbt->state = JBT_ERROR; if ( jbt->hConn ) { JabberLog( "Force closing bytestream session" ); Netlib_CloseHandle( jbt->hConn ); jbt->hConn = NULL; } if ( jbt->hEvent ) SetEvent( jbt->hEvent ); } }
static void JabberFtSiResult( XmlNode *iqNode, void *userdata ) { TCHAR* type, *from, *to, *idStr, *str; XmlNode *siNode, *fileNode, *rangeNode, *featureNode, *xNode, *fieldNode, *valueNode; JABBER_LIST_ITEM *item; int offset, length; JABBER_BYTE_TRANSFER *jbt; if (( type=JabberXmlGetAttrValue( iqNode, "type" )) == NULL ) return; if (( from=JabberXmlGetAttrValue( iqNode, "from" )) == NULL ) return; if (( to=JabberXmlGetAttrValue( iqNode, "to" )) == NULL ) return; idStr = JabberXmlGetAttrValue( iqNode, "id" ); if (( item=JabberListGetItemPtr( LIST_FTSEND, idStr )) == NULL ) return; if ( !_tcscmp( type, _T("result"))) { if (( siNode=JabberXmlGetChild( iqNode, "si" )) != NULL ) { if (( fileNode=JabberXmlGetChild( siNode, "file" )) != NULL ) { if (( rangeNode=JabberXmlGetChild( fileNode, "range" )) != NULL ) { // ************** Need to store offset/length in ft structure ********************** // but at this tiem, we should not get <range/> tag since we don't sent <range/> on our request if (( str=JabberXmlGetAttrValue( rangeNode, "offset" )) != NULL ) offset = _ttoi( str ); if (( str=JabberXmlGetAttrValue( rangeNode, "length" )) != NULL ) length = _ttoi( str ); } } if (( featureNode=JabberXmlGetChild( siNode, "feature" )) != NULL ) { if (( xNode=JabberXmlGetChildWithGivenAttrValue( featureNode, "x", "xmlns", _T("jabber:x:data"))) != NULL ) { if (( fieldNode=JabberXmlGetChildWithGivenAttrValue( xNode, "field", "var", _T("stream-method"))) != NULL ) { if (( valueNode=JabberXmlGetChild( fieldNode, "value" ))!=NULL && valueNode->text!=NULL ) { if ( !_tcscmp( valueNode->text, _T("http://jabber.org/protocol/bytestreams"))) { // Start Bytestream session jbt = ( JABBER_BYTE_TRANSFER * ) mir_alloc( sizeof( JABBER_BYTE_TRANSFER )); ZeroMemory( jbt, sizeof( JABBER_BYTE_TRANSFER )); jbt->srcJID = mir_tstrdup( to ); jbt->dstJID = mir_tstrdup( from ); jbt->sid = mir_tstrdup( item->ft->sid ); jbt->pfnSend = JabberFtSend; jbt->pfnFinal = JabberFtSendFinal; jbt->userdata = item->ft; item->ft->type = FT_BYTESTREAM; item->ft->jbt = jbt; mir_forkthread(( pThreadFunc )JabberByteSendThread, jbt ); } } } } } } } else if ( !_tcscmp( type, _T("error"))) { JabberLog( "File transfer stream initiation request denied" ); JSendBroadcast( item->ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, item->ft, 0 ); delete item->ft; item->ft = NULL; } JabberListRemove( LIST_FTSEND, idStr ); }
static void JabberFtSendFinal( BOOL success, void *userdata ) { filetransfer* ft = ( filetransfer* )userdata; if ( !success ) { JabberLog( "File transfer complete with error" ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); } else { if ( ft->std.currentFileNumber < ft->std.totalFiles-1 ) { ft->std.currentFileNumber++; replaceStr( ft->std.currentFile, ft->std.files[ ft->std.currentFileNumber ] ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0 ); JabberFtInitiate( ft->jid, ft ); return; } JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0 ); } delete ft; }
static int JabberFtReceive( HANDLE hConn, void *userdata, char* buffer, int datalen ) { filetransfer* ft = ( filetransfer* )userdata; if ( ft->create() == -1 ) return -1; int remainingBytes = ft->std.currentFileSize - ft->std.currentFileProgress; if ( remainingBytes > 0 ) { int writeSize = ( remainingBytes<datalen ) ? remainingBytes : datalen; if ( _write( ft->fileId, buffer, writeSize ) != writeSize ) { JabberLog( "_write() error" ); return -1; } ft->std.currentFileProgress += writeSize; ft->std.totalProgress += writeSize; JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, ( LPARAM )&ft->std ); return ( ft->std.currentFileSize == ft->std.currentFileProgress ) ? 0 : writeSize; } return 0; }
static BOOL JabberFtSend( HANDLE hConn, void *userdata ) { filetransfer* ft = ( filetransfer* ) userdata; struct _stat statbuf; int fd; char* buffer; int numRead; JabberLog( "Sending [%s]", ft->std.files[ ft->std.currentFileNumber ] ); _stat( ft->std.files[ ft->std.currentFileNumber ], &statbuf ); // file size in statbuf.st_size if (( fd=_open( ft->std.files[ ft->std.currentFileNumber ], _O_BINARY|_O_RDONLY )) < 0 ) { JabberLog( "File cannot be opened" ); return FALSE; } ft->std.sending = TRUE; ft->std.currentFileSize = statbuf.st_size; ft->std.currentFileProgress = 0; if (( buffer=( char* )mir_alloc( 2048 )) != NULL ) { while (( numRead=_read( fd, buffer, 2048 )) > 0 ) { if ( Netlib_Send( hConn, buffer, numRead, 0 ) != numRead ) { mir_free( buffer ); _close( fd ); return FALSE; } ft->std.currentFileProgress += numRead; ft->std.totalProgress += numRead; JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, ( LPARAM )&ft->std ); } mir_free( buffer ); } _close( fd ); return TRUE; }
void CJabberProto::OnIqResultAdvancedSearch( HXML iqNode ) { const TCHAR* type; int id; U_TCHAR_MAP mColumnsNames(10); LIST<void> SearchResults(2); if ((( id = JabberGetPacketID( iqNode )) == -1 ) || (( type = xmlGetAttrValue( iqNode, _T("type"))) == NULL )) { JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 ); return; } if ( !lstrcmp( type, _T("result"))) { HXML queryNode = xmlGetNthChild( iqNode, _T("query"), 1 ); HXML xNode = xmlGetChildByTag( queryNode, "x", "xmlns", _T(JABBER_FEAT_DATA_FORMS)); if (xNode) { //1. Form search results info HXML reportNode = xmlGetNthChild( xNode, _T("reported"), 1 ); if (reportNode) { int i = 1; while ( HXML fieldNode = xmlGetNthChild( reportNode, _T("field"), i++ )) { TCHAR* var = ( TCHAR* )xmlGetAttrValue( fieldNode, _T( "var" )); if ( var ) { TCHAR* Label = ( TCHAR* )xmlGetAttrValue( fieldNode, _T( "label" )); mColumnsNames.insert(var, (Label!=NULL) ? Label : var); } } } int i=1; HXML itemNode; while ( itemNode = xmlGetNthChild( xNode, _T("item"), i++ )) { U_TCHAR_MAP *pUserColumn = new U_TCHAR_MAP(10); int j = 1; while ( HXML fieldNode = xmlGetNthChild( itemNode, _T("field"), j++ )) { if ( TCHAR* var = (TCHAR*)xmlGetAttrValue( fieldNode, _T("var"))) { if ( TCHAR* Text = (TCHAR*)xmlGetText( xmlGetChild( fieldNode, _T("value")))) { if ( !mColumnsNames[var] ) mColumnsNames.insert(var,var); pUserColumn->insert(var,Text); } } } SearchResults.insert((void*)pUserColumn); } } else { //2. Field list search results info int i=1; while ( HXML itemNode = xmlGetNthChild( queryNode, _T("item"), i++ )) { U_TCHAR_MAP *pUserColumn=new U_TCHAR_MAP(10); TCHAR* jid = (TCHAR*)xmlGetAttrValue( itemNode, _T("jid")); TCHAR* keyReturned; mColumnsNames.insertCopyKey( _T("jid"),_T("jid"),&keyReturned, CopyKey, DestroyKey ); mColumnsNames.insert( _T("jid"), keyReturned ); pUserColumn->insertCopyKey( _T("jid"), jid, NULL, CopyKey, DestroyKey ); for ( int j=0; ; j++ ) { HXML child = xmlGetChild( itemNode, j ); if ( !child ) break; const TCHAR* szColumnName = xmlGetName( child ); if ( szColumnName ) { if ( xmlGetText( child ) && xmlGetText( child )[0] != _T('\0')) { mColumnsNames.insertCopyKey(( TCHAR* )szColumnName,_T(""),&keyReturned, CopyKey, DestroyKey); mColumnsNames.insert(( TCHAR* )szColumnName,keyReturned); pUserColumn->insertCopyKey(( TCHAR* )szColumnName, ( TCHAR* )xmlGetText( child ),NULL, CopyKey, DestroyKey); } } } SearchResults.insert((void*)pUserColumn); } } } else if (!lstrcmp( type, _T("error"))) { const TCHAR* code=NULL; const TCHAR* description=NULL; TCHAR buff[255]; HXML errorNode = xmlGetChild( iqNode , "error" ); if (errorNode) { code = xmlGetAttrValue( errorNode, _T("code")); description = xmlGetText( errorNode ); } _sntprintf(buff,SIZEOF(buff),TranslateT("Error %s %s\r\nTry to specify more detailed"),code ? code : _T(""),description?description:_T("")); JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 ); if (searchHandleDlg ) SetDlgItemText(searchHandleDlg,IDC_INSTRUCTIONS,buff); else MessageBox(NULL, buff, TranslateT("Search error"), MB_OK|MB_ICONSTOP); return; } SearchReturnResults((HANDLE)id, (void*)&SearchResults, (U_TCHAR_MAP *)&mColumnsNames); for (int i=0; i < SearchResults.getCount(); i++ ) delete ((U_TCHAR_MAP *)SearchResults[i]); //send success to finish searching JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 ); }
void CJabberProto::SearchReturnResults( HANDLE id, void * pvUsersInfo, U_TCHAR_MAP * pmAllFields ) { LIST<TCHAR> ListOfNonEmptyFields(20,(LIST<TCHAR>::FTSortFunc)TCharKeyCmp); LIST<TCHAR> ListOfFields(20); LIST<void>* plUsersInfo = ( LIST<void>* )pvUsersInfo; int i, nUsersFound = plUsersInfo->getCount(); // lets fill the ListOfNonEmptyFields but in users order for ( i=0; i < nUsersFound; i++ ) { U_TCHAR_MAP* pmUserData = ( U_TCHAR_MAP* )plUsersInfo->operator [](i); int nUserFields = pmUserData->getCount(); for (int j=0; j < nUserFields; j++) { TCHAR* var = pmUserData->getKeyName(j); if (var && ListOfNonEmptyFields.getIndex(var) < 0) ListOfNonEmptyFields.insert(var); } } // now fill the ListOfFields but order is from pmAllFields int nAllCount = pmAllFields->getCount(); for ( i=0; i < nAllCount; i++ ) { TCHAR * var=pmAllFields->getUnOrderedKeyName(i); if ( var && ListOfNonEmptyFields.getIndex(var) < 0 ) continue; ListOfFields.insert(var); } // now lets transfer field names int nFieldCount = ListOfFields.getCount(); JABBER_CUSTOMSEARCHRESULTS Results={0}; Results.nSize=sizeof(Results); Results.pszFields=(TCHAR**)mir_alloc(sizeof(TCHAR*)*nFieldCount); Results.nFieldCount=nFieldCount; /* Sending Columns Titles */ for ( i=0; i < nFieldCount; i++ ) { TCHAR* var = ListOfFields[i]; if ( var ) Results.pszFields[i] = pmAllFields->operator [](var); } Results.jsr.hdr.cbSize = 0; // sending column names JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SEARCHRESULT, id, (LPARAM) &Results ); /* Sending Users Data */ Results.jsr.hdr.cbSize = sizeof(Results.jsr); // sending user data for ( i=0; i < nUsersFound; i++ ) { TCHAR buff[200]=_T(""); Results.jsr.jid[0]=_T('\0'); U_TCHAR_MAP * pmUserData = (U_TCHAR_MAP *) plUsersInfo->operator [](i); for ( int j=0; j < nFieldCount; j++ ) { TCHAR* var = ListOfFields[j]; TCHAR* value = pmUserData->operator [](var); Results.pszFields[j] = value ? value : (TCHAR *)_T(" "); if (!_tcsicmp(var,_T("jid")) && value ) _tcsncpy(Results.jsr.jid, value, SIZEOF(Results.jsr.jid)); } { TCHAR * nickfields[]={ _T("nick"), _T("nickname"), _T("fullname"), _T("name"), _T("given"), _T("first"), _T("jid"), NULL }; TCHAR * nick=NULL; int k=0; while (nickfields[k] && !nick) nick=pmUserData->operator [](nickfields[k++]); if (_tcsicmp(nick, Results.jsr.jid)) _sntprintf(buff,SIZEOF(buff),_T("%s ( %s )"),nick, Results.jsr.jid); else _tcsncpy(buff, nick, SIZEOF(buff)); Results.jsr.hdr.nick = nick ? buff : NULL; Results.jsr.hdr.flags = PSR_TCHAR; } JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SEARCHRESULT, id, (LPARAM) &Results ); Results.jsr.hdr.nick=NULL; } mir_free( Results.pszFields ); }
int CJabberProto::FileSendParse( JABBER_SOCKET s, filetransfer* ft, char* buffer, int datalen ) { char* p, *q, *t, *eob; char* str; int num; int currentFile; int fileId; int numRead; eob = buffer + datalen; p = buffer; num = 0; while ( ft->state==FT_CONNECTING || ft->state==FT_INITIALIZING ) { for ( q=p; q+1<eob && ( *q!='\r' || *( q+1 )!='\n' ); q++ ); if ( q+1 >= eob ) break; if (( str=( char* )mir_alloc( q-p+1 )) == NULL ) { ft->state = FT_ERROR; break; } strncpy( str, p, q-p ); str[q-p] = '\0'; Log( "FT Got: %s", str ); if ( ft->state == FT_CONNECTING ) { // looking for "GET filename.ext HTTP/1.1" if ( !strncmp( str, "GET ", 4 )) { for ( t=str+4; *t!='\0' && *t!=' '; t++ ); *t = '\0'; for ( t=str+4; *t!='\0' && *t=='/'; t++ ); ft->httpPath = mir_a2t( t ); JabberHttpUrlDecode( ft->httpPath ); ft->state = FT_INITIALIZING; Log( "Change to FT_INITIALIZING" ); } } else { // FT_INITIALIZING if ( str[0] == '\0' ) { struct _stati64 statbuf; mir_free( str ); num += 2; currentFile = ft->std.currentFileNumber; TCHAR* t = _tcsrchr( ft->std.ptszFiles[ currentFile ], '\\' ); if ( t != NULL ) t++; else t = ft->std.ptszFiles[currentFile]; if ( ft->httpPath==NULL || lstrcmp( ft->httpPath, t )) { if ( ft->httpPath == NULL ) Log( "Requested file name does not matched ( httpPath==NULL )" ); else Log( "Requested file name does not matched ( '%s' vs. '%s' )", ft->httpPath, t ); ft->state = FT_ERROR; break; } Log( "Sending [%s]", ft->std.ptszFiles[ currentFile ] ); _tstati64( ft->std.ptszFiles[ currentFile ], &statbuf ); // file size in statbuf.st_size if (( fileId = _topen( ft->std.ptszFiles[currentFile], _O_BINARY|_O_RDONLY )) < 0 ) { Log( "File cannot be opened" ); ft->state = FT_ERROR; mir_free( ft->httpPath ); ft->httpPath = NULL; break; } char fileBuffer[ 2048 ]; int bytes = mir_snprintf( fileBuffer, sizeof(fileBuffer), "HTTP/1.1 200 OK\r\nContent-Length: %I64u\r\n\r\n", statbuf.st_size ); WsSend( s, fileBuffer, bytes, MSG_DUMPASTEXT ); ft->std.flags |= PFTS_SENDING; ft->std.currentFileProgress = 0; Log( "Sending file data..." ); while (( numRead = _read( fileId, fileBuffer, 2048 )) > 0 ) { if ( Netlib_Send( s, fileBuffer, numRead, 0 ) != numRead ) { ft->state = FT_ERROR; break; } ft->std.currentFileProgress += numRead; ft->std.totalProgress += numRead; JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, ( LPARAM )&ft->std ); } _close( fileId ); if ( ft->state != FT_ERROR ) ft->state = FT_DONE; Log( "Finishing this file..." ); mir_free( ft->httpPath ); ft->httpPath = NULL; break; } } mir_free( str ); q += 2; num += ( q-p ); p = q; } return num; }
void __cdecl CJabberProto::FileReceiveThread( filetransfer* ft ) { char* buffer; int datalen; ThreadData info( this, JABBER_SESSION_NORMAL ); Log( "Thread started: type=file_receive server='%s' port='%d'", ft->httpHostName, ft->httpPort ); ft->type = FT_OOB; if (( buffer=( char* )mir_alloc( JABBER_NETWORK_BUFFER_SIZE )) == NULL ) { Log( "Cannot allocate network buffer, thread ended" ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); delete ft; return; } NETLIBOPENCONNECTION nloc = { 0 }; nloc.cbSize = sizeof( nloc ); nloc.cbSize = sizeof( NETLIBOPENCONNECTION ); nloc.szHost = ft->httpHostName; nloc.wPort = ft->httpPort; info.s = ( HANDLE ) JCallService( MS_NETLIB_OPENCONNECTION, ( WPARAM ) m_hNetlibUser, ( LPARAM )&nloc ); if ( info.s == NULL ) { Log( "Connection failed ( %d ), thread ended", WSAGetLastError()); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); mir_free( buffer ); delete ft; return; } ft->s = info.s; info.send( "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", ft->httpPath, ft->httpHostName ); ft->state = FT_CONNECTING; Log( "Entering file_receive recv loop" ); datalen = 0; while ( ft->state != FT_DONE && ft->state != FT_ERROR ) { int recvResult, bytesParsed; Log( "Waiting for data..." ); recvResult = info.recv( buffer+datalen, JABBER_NETWORK_BUFFER_SIZE-datalen ); if ( recvResult <= 0 ) break; datalen += recvResult; bytesParsed = FileReceiveParse( ft, buffer, datalen ); if ( bytesParsed < datalen ) memmove( buffer, buffer+bytesParsed, datalen-bytesParsed ); datalen -= bytesParsed; } ft->s = NULL; if ( ft->state==FT_DONE || ( ft->state==FT_RECEIVING && ft->std.currentFileSize < 0 )) ft->complete(); Log( "Thread ended: type=file_receive server='%s'", ft->httpHostName ); mir_free( buffer ); delete ft; }
void __cdecl CJabberProto::FileServerThread( filetransfer* ft ) { Log( "Thread started: type=file_send" ); ThreadData info( this, JABBER_SESSION_NORMAL ); ft->type = FT_OOB; NETLIBBIND nlb = {0}; nlb.cbSize = sizeof( NETLIBBIND ); nlb.pfnNewConnectionV2 = JabberFileServerConnection; nlb.pExtra = this; nlb.wPort = 0; // Use user-specified incoming port ranges, if available info.s = ( HANDLE ) JCallService( MS_NETLIB_BINDPORT, ( WPARAM ) m_hNetlibUser, ( LPARAM )&nlb ); if ( info.s == NULL ) { Log( "Cannot allocate port to bind for file server thread, thread ended." ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); delete ft; return; } ft->s = info.s; Log( "ft->s = %d", info.s ); HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); ft->hFileEvent = hEvent; TCHAR szPort[20]; mir_sntprintf( szPort, SIZEOF( szPort ), _T("%d"), nlb.wPort ); JABBER_LIST_ITEM *item = ListAdd( LIST_FILE, szPort ); item->ft = ft; TCHAR* ptszResource = ListGetBestClientResourceNamePtr( ft->jid ); if ( ptszResource != NULL ) { ft->state = FT_CONNECTING; for ( int i=0; i < ft->std.totalFiles && ft->state != FT_ERROR && ft->state != FT_DENIED; i++ ) { ft->std.currentFileNumber = i; ft->state = FT_CONNECTING; if ( ft->httpPath ) mir_free( ft->httpPath ); ft->httpPath = NULL; TCHAR* p; if (( p = _tcschr( ft->std.ptszFiles[i], '\\' )) != NULL ) p++; else p = ft->std.ptszFiles[i]; in_addr in; in.S_un.S_addr = m_dwJabberLocalIP; TCHAR* pFileName = JabberHttpUrlEncode( p ); if ( pFileName != NULL ) { int id = SerialNext(); if ( ft->iqId ) mir_free( ft->iqId ); ft->iqId = ( TCHAR* )mir_alloc( sizeof(TCHAR)*( strlen( JABBER_IQID )+20 )); wsprintf( ft->iqId, _T(JABBER_IQID)_T("%d"), id ); char *myAddr; DBVARIANT dbv; if (m_options.BsDirect && m_options.BsDirectManual) { if ( !DBGetContactSettingString( NULL, m_szModuleName, "BsDirectAddr", &dbv )) { myAddr = NEWSTR_ALLOCA( dbv.pszVal ); JFreeVariant( &dbv ); } else myAddr = inet_ntoa( in ); } else myAddr = inet_ntoa( in ); char szAddr[ 256 ]; mir_snprintf( szAddr, sizeof(szAddr), "http://%s:%d/%s", myAddr, nlb.wPort, pFileName ); int len = lstrlen(ptszResource) + lstrlen(ft->jid) + 2; TCHAR* fulljid = ( TCHAR* )alloca( sizeof( TCHAR )*len ); wsprintf( fulljid, _T("%s/%s"), ft->jid, ptszResource ); XmlNodeIq iq( _T("set"), id, fulljid ); HXML query = iq << XQUERY( _T(JABBER_FEAT_OOB)); query << XCHILD( _T("url"), _A2T(szAddr)); query << XCHILD( _T("desc"), ft->szDescription); m_ThreadInfo->send( iq ); Log( "Waiting for the file to be sent..." ); WaitForSingleObject( hEvent, INFINITE ); mir_free( pFileName ); } Log( "File sent, advancing to the next file..." ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0 ); } CloseHandle( hEvent ); ft->hFileEvent = NULL; Log( "Finish all files" ); } ft->s = NULL; Log( "ft->s is NULL" ); ListRemove( LIST_FILE, szPort ); switch ( ft->state ) { case FT_DONE: Log( "Finish successfully" ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0 ); break; case FT_DENIED: JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ft, 0 ); break; default: // FT_ERROR: Log( "Finish with errors" ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0 ); break; } Log( "Thread ended: type=file_send" ); delete ft; }
int CJabberProto::FileReceiveParse( filetransfer* ft, char* buffer, int datalen ) { char* p, *q, *s, *eob; char* str; int num, code; eob = buffer + datalen; p = buffer; num = 0; while ( true ) { if ( ft->state==FT_CONNECTING || ft->state==FT_INITIALIZING ) { for ( q=p; q+1<eob && ( *q!='\r' || *( q+1 )!='\n' ); q++ ); if ( q+1 < eob ) { if (( str=( char* )mir_alloc( q-p+1 )) != NULL ) { strncpy( str, p, q-p ); str[q-p] = '\0'; Log( "FT Got: %s", str ); if ( ft->state == FT_CONNECTING ) { // looking for "HTTP/1.1 200 OK" if ( sscanf( str, "HTTP/%*d.%*d %d %*s", &code )==1 && code==200 ) { ft->state = FT_INITIALIZING; ft->std.currentFileSize = -1; Log( "Change to FT_INITIALIZING" ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0 ); } } else { // FT_INITIALIZING if ( str[0] == '\0' ) { TCHAR* s; if (( s = _tcsrchr( ft->httpPath, '/' )) != NULL ) s++; else s = ft->httpPath; ft->std.tszCurrentFile = mir_tstrdup( s ); JabberHttpUrlDecode( ft->std.tszCurrentFile ); if ( ft->create() == -1 ) { ft->state = FT_ERROR; break; } ft->state = FT_RECEIVING; ft->std.currentFileProgress = 0; Log( "Change to FT_RECEIVING" ); } else if (( s=strchr( str, ':' )) != NULL ) { *s = '\0'; if ( !strcmp( str, "Content-Length" )) ft->std.totalBytes = ft->std.currentFileSize = _atoi64( s+1 ); } } mir_free( str ); q += 2; num += ( q-p ); p = q; } else { ft->state = FT_ERROR; break; } } else { break; } } else if ( ft->state == FT_RECEIVING ) { int bufferSize, writeSize; __int64 remainingBytes; if ( ft->std.currentFileSize < 0 || ft->std.currentFileProgress < ft->std.currentFileSize ) { bufferSize = eob - p; remainingBytes = ft->std.currentFileSize - ft->std.currentFileProgress; if ( remainingBytes < bufferSize ) writeSize = remainingBytes; else writeSize = bufferSize; if ( _write( ft->fileId, p, writeSize ) != writeSize ) { Log( "_write() error" ); ft->state = FT_ERROR; } else { ft->std.currentFileProgress += writeSize; ft->std.totalProgress += writeSize; JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, ( LPARAM )&ft->std ); if ( ft->std.currentFileProgress == ft->std.currentFileSize ) ft->state = FT_DONE; } } num = datalen; break; } else break; } return num; }
static void JabberIqResultAdvancedSearch( XmlNode *iqNode, void *userdata ) { TCHAR* type; int id; U_TCHAR_MAP mColumnsNames(10); LIST<void> SearchResults(2); if ((( id = JabberGetPacketID( iqNode )) == -1 ) || (( type = JabberXmlGetAttrValue( iqNode, "type" )) == NULL )) { JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 ); return; } if ( !lstrcmp( type, _T("result"))) { XmlNode* queryNode=JabberXmlGetNthChild(iqNode,"query",1); XmlNode* xNode = JabberXmlGetChildWithGivenAttrValue( queryNode, "x", "xmlns", _T("jabber:x:data")); if (xNode) { //1. Form search results info XmlNode* reportNode=JabberXmlGetNthChild(xNode,"reported",1); if (reportNode) { int i = 1; while ( XmlNode* fieldNode = JabberXmlGetNthChild( reportNode, "field", i++ )) { TCHAR* var = JabberXmlGetAttrValue( fieldNode, "var" ); if ( var ) { TCHAR * Label=JabberXmlGetAttrValue(fieldNode,"label"); mColumnsNames.insert(var, (Label!=NULL) ? Label : var); } } } int i=1; XmlNode* itemNode; while ( itemNode = JabberXmlGetNthChild( xNode, "item", i++ )) { U_TCHAR_MAP *pUserColumn = new U_TCHAR_MAP(10); int j = 1; while ( XmlNode* fieldNode = JabberXmlGetNthChild( itemNode, "field", j++ )) { if (TCHAR * var=JabberXmlGetAttrValue(fieldNode,"var" )) { if (TCHAR * Text=(JabberXmlGetChild(fieldNode,"value")->text)) { if (!mColumnsNames[var]) mColumnsNames.insert(var,var); pUserColumn->insert(var,Text); } } } SearchResults.insert((void*)pUserColumn); } } else { //2. Field list search results info int i=1; while ( XmlNode* itemNode = JabberXmlGetNthChild( queryNode, "item", i++ )) { U_TCHAR_MAP *pUserColumn=new U_TCHAR_MAP(10); TCHAR* jid = JabberXmlGetAttrValue( itemNode, "jid" ); TCHAR* keyReturned; mColumnsNames.insertCopyKey( _T("jid"),_T("jid"),&keyReturned, CopyKey, DestroyKey ); mColumnsNames.insert( _T("jid"), keyReturned ); pUserColumn->insertCopyKey( _T("jid"), jid, NULL, CopyKey, DestroyKey ); for ( int j=0; j < itemNode->numChild; j++ ) { XmlNode* child = itemNode->child[j]; if ( child->name ) { TCHAR * szColumnName=a2t(child->name); if ( child->text && child->text[0] != _T('\0')) { TCHAR *keyReturned; mColumnsNames.insertCopyKey(szColumnName,_T(""),&keyReturned, CopyKey, DestroyKey); mColumnsNames.insert(szColumnName,keyReturned); pUserColumn->insertCopyKey(szColumnName,child->text,NULL, CopyKey, DestroyKey); mir_free(szColumnName); } } } SearchResults.insert((void*)pUserColumn); } } } else if (!lstrcmp( type, _T("error"))) { TCHAR * code=NULL; TCHAR * description=NULL; TCHAR buff[255]; XmlNode* errorNode = JabberXmlGetChild( iqNode, "error" ); if (errorNode) { code = JabberXmlGetAttrValue(errorNode,"code"); description = errorNode->text; } _sntprintf(buff,SIZEOF(buff),TranslateT("Error %s %s\r\nTry to specify more detailed"),code ? code : _T(""),description?description:_T("")); JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 ); if (searchHandleDlg ) SetDlgItemText(searchHandleDlg,IDC_INSTRUCTIONS,buff); else MessageBox(NULL, buff, TranslateT("Search error"), MB_OK|MB_ICONSTOP); return; } JabberSearchReturnResults((HANDLE)id, (void*)&SearchResults, (U_TCHAR_MAP *)&mColumnsNames); for (int i=0; i < SearchResults.getCount(); i++ ) delete ((U_TCHAR_MAP *)SearchResults[i]); //send success to finish searching JSendBroadcast( NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, ( HANDLE ) id, 0 ); }