VIP Boost Банери Кредити
Основно Начало Сървъри Marketplace Новини Форум Сървъри
Общности Хостинг Добави Boost
Ресурси
Библиотеки Карти Видеа Магазин
Инструменти
Builder Demo CFG HUD
AMXX API
Вход Регистрация
/ Библиотеки / ftp.inc

ftp.inc

forums.alliedmods.net/showthread.php?t=142850

.inc 10.6 KB 374 реда 04.04.2026
Pawn / AMX Mod X

/*	
	   FTP
	  v0.3
	by bugsy
	
	http://forums.alliedmods.net/showthread.php?t=142850
*/

//#define TESTING

#if defined _ftp_included
	#endinput
#endif
#define _ftp_included

#if !defined _engine_included
	#include <engine>
#endif

#if !defined _socket_included
	#include <sockets>
#endif

const BUFFER_SIZE = 4096;

enum FTPStatus
{
	FTP_DISCONNECTED,
	FTP_CONNECTING,
	FTP_USER,
	FTP_PASS,
	FTP_READYFORDATA,
	FTP_IDLE
}

enum FTPTransType
{
	FTP_OPEN,
	FTP_STOR,
	FTP_RETR,
	FTP_LIST
}

enum FTPInfo
{
	UserName[ 64 ],
	Password[ 64 ],
	Server[ 128 ],
	Port,
	DataServer[ 16 ],
	DataPort,
	FileHandle,
	LocalFile[ 64 ],
	RemoteFile[ 64 ],
	FileSize,
	BytesTransferred,
	Socket_Cmd,
	Socket_Data,
	FTPTransType:TransType,
	FTPStatus:Status,
	FWDHandles[ FTPTransType ],
	bool:SentNoop
}

new FTP[ FTPInfo ] , g_iFTPEntity , g_DataBuffer[ BUFFER_SIZE ] , g_szCmdBuffer[ 128 ] , g_szCmd[ 128 ];

stock FTP_Open( const szServer[] , const iPort=21 , const szUser[] , const szPassword[] , const szForward[]="" )
{
	if ( !FTP[ FWDHandles ][ FTP_OPEN ] )
		FTP[ FWDHandles ][ FTP_OPEN ] = CreateMultiForward( szForward , ET_IGNORE , FP_CELL );
	
	copy( FTP[ Server ] , charsmax( FTP[ Server ] ) , szServer );
	FTP[ Port ] = iPort;
	formatex( FTP[ UserName ] , charsmax( FTP[ UserName ] ) , "USER %s^r^n" , szUser );
	formatex( FTP[ Password ] , charsmax( FTP[ Password ] ) , "PASS %s^r^n" , szPassword );

	FTP[ Status ] = _:FTP_CONNECTING;
	FTP[ TransType ] = _:FTP_OPEN;
	
	new iError;
	if ( ( FTP[ Socket_Cmd ] = socket_open( FTP[ Server ] , FTP[ Port ] , SOCKET_TCP , iError ) ) && !iError )
	{
		if ( !g_iFTPEntity )
			CreateFTPEntity();
		
		entity_set_float( g_iFTPEntity , EV_FL_nextthink , get_gametime() + 0.5 );
	}
}

stock FTP_Close()
{
	if ( FTP[ Status ] != FTP_IDLE )
		return 0;
		
	socket_send( FTP[ Socket_Cmd ] , "QUIT^r^n", 7 );  
	socket_close( FTP[ Socket_Cmd ] );
	socket_close( FTP[ Socket_Data ] );
	FTP[ Status ] = _:FTP_DISCONNECTED;
	
	return 1;
}

stock FTP_SendFile( szLocalFile[] , szRemoteFile[] , szForward[]="" )
{
	return FTP_Command( FTP_STOR , szLocalFile , szRemoteFile , szForward );
}

stock FTP_GetFile( szLocalFile[] , szRemoteFile[] , szForward[]="" )
{
	return FTP_Command( FTP_RETR , szLocalFile , szRemoteFile , szForward );
}

stock FTP_GetList( szLocalFile[] , szRemoteFile[] , szForward[]="" )
{
	return FTP_Command( FTP_LIST , szLocalFile , szRemoteFile , szForward );
}

stock FTP_Ready()
{
	return ( FTP[ Status ] == FTP_IDLE );
}

FTP_Command( FTPTransType:FTPTT , szLocalFile[] , szRemoteFile[] , szForward[] )
{
	if ( FTP[ Status ] != FTP_IDLE )
		return 0;
		
	if ( !FTP[ FWDHandles ][ FTPTT ] )
	{
		switch ( FTPTT )
		{
			case FTP_RETR , FTP_STOR: FTP[ FWDHandles ][ FTPTT ] = CreateMultiForward( szForward , ET_IGNORE , FP_STRING , FP_CELL , FP_CELL );
			case FTP_LIST: FTP[ FWDHandles ][ FTPTT ] = CreateMultiForward( szForward , ET_IGNORE , FP_STRING , FP_CELL );
		}
	}
	
	copy( FTP[ LocalFile ] , charsmax( FTP[ LocalFile ] ) , szLocalFile );
	copy( FTP[ RemoteFile ] , charsmax( FTP[ RemoteFile ] ) , szRemoteFile );
	
	FTP[ TransType ] = _:FTPTT;
	
	socket_send( FTP[ Socket_Cmd ] , "PASV^r^n" , 6 );
	
	return 1;	
}

public _FTP_Think( iEntity )
{
	if ( FTP[ Status ] != FTP_READYFORDATA )
	{
		if ( g_szCmdBuffer[ 0 ] || socket_change( FTP[ Socket_Cmd ] ) )
		{
			new szCode[ 4 ] , iPos ; 
				
			if ( !g_szCmdBuffer[ 0 ] )
				socket_recv( FTP[ Socket_Cmd ] , g_szCmdBuffer , charsmax( g_szCmdBuffer ) );
	
			parse( g_szCmdBuffer , szCode , charsmax( szCode ) );
			
			#if defined TESTING
			server_print( g_szCmdBuffer );
			#endif
			
			switch ( str_to_num( szCode ) )
			{
				case 150:  // Opening BINARY mode data connection
				{	
					if ( FTP[ TransType ] != FTP_LIST )
						FTP[ Status ] = _:FTP_READYFORDATA;
				}
				case 200: // Type set to I. & 200 MODE S ok.
				{
					switch ( FTP[ TransType ] )
					{
						case FTP_STOR:
						{
							formatex( g_szCmd , charsmax( g_szCmd ) , "STOR %s^r^n" , FTP[ RemoteFile ] );
							socket_send( FTP[ Socket_Cmd ] , g_szCmd , sizeof( g_szCmd ) );
							
							new iError;
							FTP[ Socket_Data ] = socket_open( FTP[ DataServer ] , FTP[ DataPort ] , SOCKET_TCP , iError );
							FTP[ FileHandle ] = fopen( FTP[ LocalFile ] , "rb" );
							FTP[ FileSize ] = file_size( FTP[ LocalFile ] );
							
							if ( !FTP[ FileHandle ] )
								set_fail_state( "FTP_STOR: File doesnt exist" );
						}
						case FTP_LIST:
						{	
							formatex( g_szCmd , charsmax( g_szCmd ) , "NLST %s^r^n" ,  FTP[ RemoteFile ] );
							socket_send( FTP[ Socket_Cmd ] , g_szCmd , sizeof( g_szCmd ) ); 
							FTP[ Status ] = _:FTP_READYFORDATA;	
							
							new iError;
							FTP[ Socket_Data ] = socket_open( FTP[ DataServer ] , FTP[ DataPort ] , SOCKET_TCP , iError );
							FTP[ FileHandle ] = fopen( FTP[ LocalFile ] , "wt" );
							
							if ( !FTP[ FileHandle ] )
								set_fail_state( "FTP_LIST: Error creating local file" );
						}
						case FTP_RETR:
						{
							formatex( g_szCmd , charsmax( g_szCmd ) , "SIZE %s^r^n" , FTP[ RemoteFile ] );
							socket_send( FTP[ Socket_Cmd ] , g_szCmd , sizeof( g_szCmd ) );
						}
					}
				}
				case 213: //For GetFile: 213 9545  (file size)
				{
					FTP[ FileSize ] = str_to_num( g_szCmdBuffer[ 4 ] );
					formatex( g_szCmd , charsmax( g_szCmd ) , "RETR %s^r^n" , FTP[ RemoteFile ] );
					socket_send( _:FTP[ Socket_Cmd ] , g_szCmd , sizeof( g_szCmd ) );
						
					new iError;
					FTP[ Socket_Data ] = socket_open( FTP[ DataServer ] , FTP[ DataPort ] , SOCKET_TCP , iError );
					FTP[ FileHandle ] = fopen( FTP[ LocalFile ] , "wb" );
					
					if ( !FTP[ FileHandle ] )
						set_fail_state( "FTP_RETR: Error creating local file" );
				}
				case 220: // Welcome
				{
					if ( FTP[ Status ] == FTP_CONNECTING )
					{
						socket_send( FTP[ Socket_Cmd ] , FTP[ UserName ] , sizeof( FTP[ UserName ] ) );
						FTP[ Status ] = _:FTP_USER;
					}
				}
				case 226: // Transfer complete.
				{
					if ( FTP[ TransType ] == FTP_LIST )
					{
						fclose( FTP[ FileHandle ] );
						socket_close( FTP[ Socket_Data ] );
							
						FTP[ Status ] = _:FTP_IDLE;
					}
				}
				case 227: // Entering Passive Mode (216,87,188,9,205,122)
				{
					new iStartPos = strfind( g_szCmdBuffer , "(" ) , iEndPos = strfind( g_szCmdBuffer , ")" );
				
					if ( ( iStartPos == -1 ) || ( iEndPos == -1 ) )
						return;
	
					new szDataSvr[ 6 ][ 4 ];
					g_szCmdBuffer[ iEndPos ] = EOS;
					ExplodeString( szDataSvr , 6 , 4 , g_szCmdBuffer[ iStartPos + 1 ] , ',' );
					
					formatex( FTP[ DataServer ] , charsmax( FTP[ DataServer ] ) , "%s.%s.%s.%s" , szDataSvr[ 0 ] , szDataSvr[ 1 ] , szDataSvr[ 2 ] , szDataSvr[ 3 ] );
					FTP[ DataPort ] = ( ( str_to_num( szDataSvr[ 4 ] ) * 256 ) + str_to_num( szDataSvr[ 5 ] ) );
					
					socket_send( FTP[ Socket_Cmd ] , "TYPE I^r^n" , 8 );
			
					FTP[ Status ] = _:FTP_IDLE;
				}
				case 230: // Logged on
				{
					new iRet;
					ExecuteForward( FTP[ FWDHandles ][ FTP[ TransType ] ] , iRet , 1 );
					FTP[ Status ] = _:FTP_IDLE;
				}
				case 331: // Password required for XX
				{
					if ( FTP[ Status ] < FTP_PASS )
					{				
						socket_send( FTP[ Socket_Cmd ] , FTP[ Password ] , sizeof( FTP[ Password ] ) );
						FTP[ Status ] = _:FTP_PASS;
					}
				}
				case 530: // Login incorrect
				{
					new iRet;
					ExecuteForward( FTP[ FWDHandles ][ FTP[ TransType ] ] , iRet , 0 );
					FTP[ Status ] = _:FTP_DISCONNECTED;	
					socket_close( FTP[ Socket_Cmd ] );
				}
				case 550: // File not found / Permission denied
				{
					FTP[ Status ] = _:FTP_IDLE;	
					socket_close( FTP[ Socket_Data ] );
					fclose( FTP[ FileHandle ] );
				}
			}
		
			if ( ( ( iPos = strfind( g_szCmdBuffer , "^r^n" ) ) != -1 ) && ( ( iPos + 2 ) < sizeof( g_szCmdBuffer ) ) && strlen( g_szCmdBuffer[ iPos + 2 ] ) )
			{
				copy( g_szCmdBuffer , charsmax( g_szCmdBuffer ) , g_szCmdBuffer[ iPos + 2 ] ); 
			}	
			else
			{
				g_szCmdBuffer[ 0 ] = EOS;
			}
		}
	}
	else
	{	
		switch ( FTP[ TransType ] )
		{
			case FTP_RETR , FTP_LIST:
			{
				if ( socket_change( FTP[ Socket_Data ] ) )
				{
					static iDataRecv , iRet;
					iDataRecv = socket_recv( FTP[ Socket_Data ] , g_DataBuffer , sizeof( g_DataBuffer ) );
					fwrite_blocks( FTP[ FileHandle ] , g_DataBuffer , iDataRecv , BLOCK_BYTE );
				
					FTP[ BytesTransferred ] += iDataRecv;
					
					if ( FTP[ TransType ] == FTP_LIST )
					{
						ExecuteForward( FTP[ FWDHandles ][ FTP_LIST ] , iRet , FTP[ LocalFile ] , FTP[ BytesTransferred ] );
						
						fclose( FTP[ FileHandle ] );
						socket_close( FTP[ Socket_Data ] );
						
						FTP[ BytesTransferred ] = 0;
						FTP[ Status ] = _:FTP_IDLE;	
					}
					else
					{
						ExecuteForward( FTP[ FWDHandles ][ FTP_RETR ] , iRet , FTP[ RemoteFile ] , FTP[ BytesTransferred ] , FTP[ FileSize ] );
					}
				}
			}
			case FTP_STOR:
			{
				static iBlocksRead , iRet;
				iBlocksRead = fread_blocks( FTP[ FileHandle ] , g_DataBuffer , BUFFER_SIZE , BLOCK_BYTE );
				socket_send2( FTP[ Socket_Data ] , g_DataBuffer , iBlocksRead );		
				
				FTP[ BytesTransferred ] += iBlocksRead;
				ExecuteForward( FTP[ FWDHandles ][ FTP[ TransType ] ] , iRet , FTP[ ( FTP[ TransType ] == FTP_STOR ) ? LocalFile : RemoteFile ] , FTP[ BytesTransferred ] , FTP[ FileSize ] );
			}
		}
	
		if ( ( FTP[ TransType ] != FTP_LIST ) && ( FTP[ FileSize ] && ( FTP[ BytesTransferred ] == FTP[ FileSize ] ) ) )
		{
			fclose( FTP[ FileHandle ] );
			socket_close( FTP[ Socket_Data ] );
			
			FTP[ BytesTransferred ] = 0;
			FTP[ Status ] = _:FTP_IDLE;
		}
	}
	
	if ( FTP[ Status ] != FTP_DISCONNECTED )
		entity_set_float( iEntity , EV_FL_nextthink , get_gametime() + ( ( FTP[ Status ] == FTP_READYFORDATA ) ? 0.01 : 0.5 ) );
}

CreateFTPEntity()
{
	g_iFTPEntity = create_entity( "info_target" );
	entity_set_string( g_iFTPEntity , EV_SZ_classname , "ftp_entity" );
	register_think( "ftp_entity" , "_FTP_Think" );	
}

ExplodeString( szOutput[][] , iNumOutputStrings , iOutputCharsMax , const szInput[] , cDelimiter )
{
	new iIndex , iPos , iLen = strlen( szInput );
	
	do
	{
		iPos += ( copyc( szOutput[ iIndex ] , iOutputCharsMax , szInput[ iPos ] , cDelimiter ) + 1 );
	}
	while( ( iPos < iLen ) && ( ++iIndex < iNumOutputStrings ) )
	
	return iIndex;
}
/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1033\\ f0\\ fs16 \n\\ par }
*/
РЕКЛАМИРАЙ ПРИ НАС!
AMXX-BG.INFO
КАК ДА ИЗПОЛЗВАМ
Добави в началото на .sma файла:
#include <ftp>
1. Изтегли
Свали файла от бутона по-горе
2. Копирай
Постави в scripting/include/
3. Включи
Добави #include директивата
4. Компилирай
Използвай amxxpc или scripting/compile.exe