AMXX-BG.INFO ftp.inc Raw include

ftp.inc

Original include source with line numbers.

Back Download .inc
1
2 /*
3 FTP
4 v0.3
5 by bugsy
6
7 http://forums.alliedmods.net/showthread.php?t=142850
8 */
9
10 //#define TESTING
11
12 #if defined _ftp_included
13 #endinput
14 #endif
15 #define _ftp_included
16
17 #if !defined _engine_included
18 #include <engine>
19 #endif
20
21 #if !defined _socket_included
22 #include <sockets>
23 #endif
24
25 const BUFFER_SIZE = 4096;
26
27 enum FTPStatus
28 {
29 FTP_DISCONNECTED,
30 FTP_CONNECTING,
31 FTP_USER,
32 FTP_PASS,
33 FTP_READYFORDATA,
34 FTP_IDLE
35 }
36
37 enum FTPTransType
38 {
39 FTP_OPEN,
40 FTP_STOR,
41 FTP_RETR,
42 FTP_LIST
43 }
44
45 enum FTPInfo
46 {
47 UserName[ 64 ],
48 Password[ 64 ],
49 Server[ 128 ],
50 Port,
51 DataServer[ 16 ],
52 DataPort,
53 FileHandle,
54 LocalFile[ 64 ],
55 RemoteFile[ 64 ],
56 FileSize,
57 BytesTransferred,
58 Socket_Cmd,
59 Socket_Data,
60 FTPTransType:TransType,
61 FTPStatus:Status,
62 FWDHandles[ FTPTransType ],
63 bool:SentNoop
64 }
65
66 new FTP[ FTPInfo ] , g_iFTPEntity , g_DataBuffer[ BUFFER_SIZE ] , g_szCmdBuffer[ 128 ] , g_szCmd[ 128 ];
67
68 stock FTP_Open( const szServer[] , const iPort=21 , const szUser[] , const szPassword[] , const szForward[]="" )
69 {
70 if ( !FTP[ FWDHandles ][ FTP_OPEN ] )
71 FTP[ FWDHandles ][ FTP_OPEN ] = CreateMultiForward( szForward , ET_IGNORE , FP_CELL );
72
73 copy( FTP[ Server ] , charsmax( FTP[ Server ] ) , szServer );
74 FTP[ Port ] = iPort;
75 formatex( FTP[ UserName ] , charsmax( FTP[ UserName ] ) , "USER %s^r^n" , szUser );
76 formatex( FTP[ Password ] , charsmax( FTP[ Password ] ) , "PASS %s^r^n" , szPassword );
77
78 FTP[ Status ] = _:FTP_CONNECTING;
79 FTP[ TransType ] = _:FTP_OPEN;
80
81 new iError;
82 if ( ( FTP[ Socket_Cmd ] = socket_open( FTP[ Server ] , FTP[ Port ] , SOCKET_TCP , iError ) ) && !iError )
83 {
84 if ( !g_iFTPEntity )
85 CreateFTPEntity();
86
87 entity_set_float( g_iFTPEntity , EV_FL_nextthink , get_gametime() + 0.5 );
88 }
89 }
90
91 stock FTP_Close()
92 {
93 if ( FTP[ Status ] != FTP_IDLE )
94 return 0;
95
96 socket_send( FTP[ Socket_Cmd ] , "QUIT^r^n", 7 );
97 socket_close( FTP[ Socket_Cmd ] );
98 socket_close( FTP[ Socket_Data ] );
99 FTP[ Status ] = _:FTP_DISCONNECTED;
100
101 return 1;
102 }
103
104 stock FTP_SendFile( szLocalFile[] , szRemoteFile[] , szForward[]="" )
105 {
106 return FTP_Command( FTP_STOR , szLocalFile , szRemoteFile , szForward );
107 }
108
109 stock FTP_GetFile( szLocalFile[] , szRemoteFile[] , szForward[]="" )
110 {
111 return FTP_Command( FTP_RETR , szLocalFile , szRemoteFile , szForward );
112 }
113
114 stock FTP_GetList( szLocalFile[] , szRemoteFile[] , szForward[]="" )
115 {
116 return FTP_Command( FTP_LIST , szLocalFile , szRemoteFile , szForward );
117 }
118
119 stock FTP_Ready()
120 {
121 return ( FTP[ Status ] == FTP_IDLE );
122 }
123
124 FTP_Command( FTPTransType:FTPTT , szLocalFile[] , szRemoteFile[] , szForward[] )
125 {
126 if ( FTP[ Status ] != FTP_IDLE )
127 return 0;
128
129 if ( !FTP[ FWDHandles ][ FTPTT ] )
130 {
131 switch ( FTPTT )
132 {
133 case FTP_RETR , FTP_STOR: FTP[ FWDHandles ][ FTPTT ] = CreateMultiForward( szForward , ET_IGNORE , FP_STRING , FP_CELL , FP_CELL );
134 case FTP_LIST: FTP[ FWDHandles ][ FTPTT ] = CreateMultiForward( szForward , ET_IGNORE , FP_STRING , FP_CELL );
135 }
136 }
137
138 copy( FTP[ LocalFile ] , charsmax( FTP[ LocalFile ] ) , szLocalFile );
139 copy( FTP[ RemoteFile ] , charsmax( FTP[ RemoteFile ] ) , szRemoteFile );
140
141 FTP[ TransType ] = _:FTPTT;
142
143 socket_send( FTP[ Socket_Cmd ] , "PASV^r^n" , 6 );
144
145 return 1;
146 }
147
148 public _FTP_Think( iEntity )
149 {
150 if ( FTP[ Status ] != FTP_READYFORDATA )
151 {
152 if ( g_szCmdBuffer[ 0 ] || socket_change( FTP[ Socket_Cmd ] ) )
153 {
154 new szCode[ 4 ] , iPos ;
155
156 if ( !g_szCmdBuffer[ 0 ] )
157 socket_recv( FTP[ Socket_Cmd ] , g_szCmdBuffer , charsmax( g_szCmdBuffer ) );
158
159 parse( g_szCmdBuffer , szCode , charsmax( szCode ) );
160
161 #if defined TESTING
162 server_print( g_szCmdBuffer );
163 #endif
164
165 switch ( str_to_num( szCode ) )
166 {
167 case 150: // Opening BINARY mode data connection
168 {
169 if ( FTP[ TransType ] != FTP_LIST )
170 FTP[ Status ] = _:FTP_READYFORDATA;
171 }
172 case 200: // Type set to I. & 200 MODE S ok.
173 {
174 switch ( FTP[ TransType ] )
175 {
176 case FTP_STOR:
177 {
178 formatex( g_szCmd , charsmax( g_szCmd ) , "STOR %s^r^n" , FTP[ RemoteFile ] );
179 socket_send( FTP[ Socket_Cmd ] , g_szCmd , sizeof( g_szCmd ) );
180
181 new iError;
182 FTP[ Socket_Data ] = socket_open( FTP[ DataServer ] , FTP[ DataPort ] , SOCKET_TCP , iError );
183 FTP[ FileHandle ] = fopen( FTP[ LocalFile ] , "rb" );
184 FTP[ FileSize ] = file_size( FTP[ LocalFile ] );
185
186 if ( !FTP[ FileHandle ] )
187 set_fail_state( "FTP_STOR: File doesnt exist" );
188 }
189 case FTP_LIST:
190 {
191 formatex( g_szCmd , charsmax( g_szCmd ) , "NLST %s^r^n" , FTP[ RemoteFile ] );
192 socket_send( FTP[ Socket_Cmd ] , g_szCmd , sizeof( g_szCmd ) );
193 FTP[ Status ] = _:FTP_READYFORDATA;
194
195 new iError;
196 FTP[ Socket_Data ] = socket_open( FTP[ DataServer ] , FTP[ DataPort ] , SOCKET_TCP , iError );
197 FTP[ FileHandle ] = fopen( FTP[ LocalFile ] , "wt" );
198
199 if ( !FTP[ FileHandle ] )
200 set_fail_state( "FTP_LIST: Error creating local file" );
201 }
202 case FTP_RETR:
203 {
204 formatex( g_szCmd , charsmax( g_szCmd ) , "SIZE %s^r^n" , FTP[ RemoteFile ] );
205 socket_send( FTP[ Socket_Cmd ] , g_szCmd , sizeof( g_szCmd ) );
206 }
207 }
208 }
209 case 213: //For GetFile: 213 9545 (file size)
210 {
211 FTP[ FileSize ] = str_to_num( g_szCmdBuffer[ 4 ] );
212 formatex( g_szCmd , charsmax( g_szCmd ) , "RETR %s^r^n" , FTP[ RemoteFile ] );
213 socket_send( _:FTP[ Socket_Cmd ] , g_szCmd , sizeof( g_szCmd ) );
214
215 new iError;
216 FTP[ Socket_Data ] = socket_open( FTP[ DataServer ] , FTP[ DataPort ] , SOCKET_TCP , iError );
217 FTP[ FileHandle ] = fopen( FTP[ LocalFile ] , "wb" );
218
219 if ( !FTP[ FileHandle ] )
220 set_fail_state( "FTP_RETR: Error creating local file" );
221 }
222 case 220: // Welcome
223 {
224 if ( FTP[ Status ] == FTP_CONNECTING )
225 {
226 socket_send( FTP[ Socket_Cmd ] , FTP[ UserName ] , sizeof( FTP[ UserName ] ) );
227 FTP[ Status ] = _:FTP_USER;
228 }
229 }
230 case 226: // Transfer complete.
231 {
232 if ( FTP[ TransType ] == FTP_LIST )
233 {
234 fclose( FTP[ FileHandle ] );
235 socket_close( FTP[ Socket_Data ] );
236
237 FTP[ Status ] = _:FTP_IDLE;
238 }
239 }
240 case 227: // Entering Passive Mode (216,87,188,9,205,122)
241 {
242 new iStartPos = strfind( g_szCmdBuffer , "(" ) , iEndPos = strfind( g_szCmdBuffer , ")" );
243
244 if ( ( iStartPos == -1 ) || ( iEndPos == -1 ) )
245 return;
246
247 new szDataSvr[ 6 ][ 4 ];
248 g_szCmdBuffer[ iEndPos ] = EOS;
249 ExplodeString( szDataSvr , 6 , 4 , g_szCmdBuffer[ iStartPos + 1 ] , ',' );
250
251 formatex( FTP[ DataServer ] , charsmax( FTP[ DataServer ] ) , "%s.%s.%s.%s" , szDataSvr[ 0 ] , szDataSvr[ 1 ] , szDataSvr[ 2 ] , szDataSvr[ 3 ] );
252 FTP[ DataPort ] = ( ( str_to_num( szDataSvr[ 4 ] ) * 256 ) + str_to_num( szDataSvr[ 5 ] ) );
253
254 socket_send( FTP[ Socket_Cmd ] , "TYPE I^r^n" , 8 );
255
256 FTP[ Status ] = _:FTP_IDLE;
257 }
258 case 230: // Logged on
259 {
260 new iRet;
261 ExecuteForward( FTP[ FWDHandles ][ FTP[ TransType ] ] , iRet , 1 );
262 FTP[ Status ] = _:FTP_IDLE;
263 }
264 case 331: // Password required for XX
265 {
266 if ( FTP[ Status ] < FTP_PASS )
267 {
268 socket_send( FTP[ Socket_Cmd ] , FTP[ Password ] , sizeof( FTP[ Password ] ) );
269 FTP[ Status ] = _:FTP_PASS;
270 }
271 }
272 case 530: // Login incorrect
273 {
274 new iRet;
275 ExecuteForward( FTP[ FWDHandles ][ FTP[ TransType ] ] , iRet , 0 );
276 FTP[ Status ] = _:FTP_DISCONNECTED;
277 socket_close( FTP[ Socket_Cmd ] );
278 }
279 case 550: // File not found / Permission denied
280 {
281 FTP[ Status ] = _:FTP_IDLE;
282 socket_close( FTP[ Socket_Data ] );
283 fclose( FTP[ FileHandle ] );
284 }
285 }
286
287 if ( ( ( iPos = strfind( g_szCmdBuffer , "^r^n" ) ) != -1 ) && ( ( iPos + 2 ) < sizeof( g_szCmdBuffer ) ) && strlen( g_szCmdBuffer[ iPos + 2 ] ) )
288 {
289 copy( g_szCmdBuffer , charsmax( g_szCmdBuffer ) , g_szCmdBuffer[ iPos + 2 ] );
290 }
291 else
292 {
293 g_szCmdBuffer[ 0 ] = EOS;
294 }
295 }
296 }
297 else
298 {
299 switch ( FTP[ TransType ] )
300 {
301 case FTP_RETR , FTP_LIST:
302 {
303 if ( socket_change( FTP[ Socket_Data ] ) )
304 {
305 static iDataRecv , iRet;
306 iDataRecv = socket_recv( FTP[ Socket_Data ] , g_DataBuffer , sizeof( g_DataBuffer ) );
307 fwrite_blocks( FTP[ FileHandle ] , g_DataBuffer , iDataRecv , BLOCK_BYTE );
308
309 FTP[ BytesTransferred ] += iDataRecv;
310
311 if ( FTP[ TransType ] == FTP_LIST )
312 {
313 ExecuteForward( FTP[ FWDHandles ][ FTP_LIST ] , iRet , FTP[ LocalFile ] , FTP[ BytesTransferred ] );
314
315 fclose( FTP[ FileHandle ] );
316 socket_close( FTP[ Socket_Data ] );
317
318 FTP[ BytesTransferred ] = 0;
319 FTP[ Status ] = _:FTP_IDLE;
320 }
321 else
322 {
323 ExecuteForward( FTP[ FWDHandles ][ FTP_RETR ] , iRet , FTP[ RemoteFile ] , FTP[ BytesTransferred ] , FTP[ FileSize ] );
324 }
325 }
326 }
327 case FTP_STOR:
328 {
329 static iBlocksRead , iRet;
330 iBlocksRead = fread_blocks( FTP[ FileHandle ] , g_DataBuffer , BUFFER_SIZE , BLOCK_BYTE );
331 socket_send2( FTP[ Socket_Data ] , g_DataBuffer , iBlocksRead );
332
333 FTP[ BytesTransferred ] += iBlocksRead;
334 ExecuteForward( FTP[ FWDHandles ][ FTP[ TransType ] ] , iRet , FTP[ ( FTP[ TransType ] == FTP_STOR ) ? LocalFile : RemoteFile ] , FTP[ BytesTransferred ] , FTP[ FileSize ] );
335 }
336 }
337
338 if ( ( FTP[ TransType ] != FTP_LIST ) && ( FTP[ FileSize ] && ( FTP[ BytesTransferred ] == FTP[ FileSize ] ) ) )
339 {
340 fclose( FTP[ FileHandle ] );
341 socket_close( FTP[ Socket_Data ] );
342
343 FTP[ BytesTransferred ] = 0;
344 FTP[ Status ] = _:FTP_IDLE;
345 }
346 }
347
348 if ( FTP[ Status ] != FTP_DISCONNECTED )
349 entity_set_float( iEntity , EV_FL_nextthink , get_gametime() + ( ( FTP[ Status ] == FTP_READYFORDATA ) ? 0.01 : 0.5 ) );
350 }
351
352 CreateFTPEntity()
353 {
354 g_iFTPEntity = create_entity( "info_target" );
355 entity_set_string( g_iFTPEntity , EV_SZ_classname , "ftp_entity" );
356 register_think( "ftp_entity" , "_FTP_Think" );
357 }
358
359 ExplodeString( szOutput[][] , iNumOutputStrings , iOutputCharsMax , const szInput[] , cDelimiter )
360 {
361 new iIndex , iPos , iLen = strlen( szInput );
362
363 do
364 {
365 iPos += ( copyc( szOutput[ iIndex ] , iOutputCharsMax , szInput[ iPos ] , cDelimiter ) + 1 );
366 }
367 while( ( iPos < iLen ) && ( ++iIndex < iNumOutputStrings ) )
368
369 return iIndex;
370 }
371 /* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
372 *{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1033\\ f0\\ fs16 \n\\ par }
373 */
374