Пример #1
0
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 );
}
Пример #2
0
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 );
}
Пример #3
0
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 );
	}
}
Пример #4
0
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 );
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
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;
}
Пример #8
0
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 );
}
Пример #9
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 );
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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 );
}