EnglishРусский  

   ..

   ftp.g

   http.g

   ping.g

   proxy.g

   socket.g

   strinet.g

Bookmark and Share

Ads

Perfect Automation tool
All-In-One: Script editor, Launcher, Scheduler, Keyboard & Mouse Recorder. Try now!

CreateInstall
Freeware and commercial installers.

Cell Phone Batteries
Batteries Plus offers batteries for laptop, camcorder, cell phone, camera.

Gentee needs your help!
How to advertise with us
 
laptop battery

  1 
  2 type ftp
  3 {
  4    str        path        // Дополнительный путь при открытии
  5 	socket     sock        // Главный сокет
  6 	socket     sockdata    // Сокет передачи данных
  7 	socket     sockserv    // Сокет передачи данных PORT
  8 	sockaddr   local       // Локальный адрес
  9 	uint       notify      // Функция для уведомлений
 10 	inetnotify ni
 11 	uint       anonymous   // 1 если anonymous
 12 	uint       passive     // 1 если passive mode
 13 }
 14 
 15 define
 16 {
 17 	FTP_OPENING = 150   /* 150 Opening data connection*/
 18 	FTP_ENDTRAN = 226   /* 226 Transfer Complete */
 19 	FTP_OK      = 200   
 20    FTP_FILESTAT = 213  // File status.
 21 	FTP_HELLO   = 220
 22 	FTP_GOODBYE = 221
 23 	FTP_PASSIVEOK = 227 
 24 	FTP_LOGINOK = 230   
 25 	FTP_CWDOK   = 250    /* 250 CWD command successful. */
 26 	FTP_MKDIROK = 257
 27 	FTP_PASSWD  = 331
 28 	FTP_FILEOK  = 350    /* RNFR command successful */    
 29 	FTP_LOGINBAD = 530  
 30 	FTP_NOTFOUND = 550   /* 550 No such file or directory */
 31 }
 32 
 33 define <export>
 34 {
 35 	FTP_ANONYM   = 0x0001      // anonymous
 36 	FTP_PASV     = 0x0002      // passive mode
 37 	FTP_BINARY   = 0x0004      // TYPE как IMAGE 
 38 	FTP_TEXT     = 0x0008      // TYPE как текстовый файл
 39 	FTP_CONTINUE = 0x0010      // докачка 
 40 	FTP_SETTIME  = 0x0020      // для get - установить время 
 41 	FTP_STR      = 0x0100      // для get - добавлять 0 байт в конце 
 42 	FTP_FILE     = 0x1000      // для метода get - закачка в файл 
 43 
 44 	S_IRWXU    = 0x0700
 45 	S_IRUSR    = 0x0400
 46 	S_IWUSR    = 0x0200
 47 	S_IXUSR    = 0x0100
 48 	S_IRWXG    = 0x0070
 49 	S_IRGRP    = 0x0040
 50 	S_IWGRP    = 0x0020
 51 	S_IXGRP    = 0x0010
 52 	S_IRWXO    = 0x0007
 53 	S_IROTH    = 0x0004
 54 	S_IWOTH    = 0x0002
 55 	S_IXOTH    = 0x0001
 56 }
 57 
 58 method uint ftp.notify( uint code )
 59 {
 60    if !this.notify : return 1
 61       
 62    if !this.notify->func( code, this.ni )
 63    {
 64       ineterror = $ERRINET_USERBREAK
 65 //      ret = 0
 66       return 0
 67    }
 68 	if code == $NFYINET_ERROR : return 0 
 69    return 1
 70 }
 71 
 72 method uint ftp.cmdresponse
 73 {
 74 	uint ret i
 75 	buf  data
 76 	arrstr  lines 
 77 
 78 	subfunc uint nodigit( ubyte ch )
 79 	{
 80 		return ch < '0' || ch > '9'
 81 	}
 82 	label again
 83 	this.sock.recv( data )
 84 	data += byte( 0 )
 85    this.ni.head = data->str
 86 
 87 	if *data == 1 : return 0
 88 
 89 	this.ni.head.split( lines, 0xA, 0 )	
 90 	foreach cur, lines
 91 	{
 92 		if nodigit( cur[0] ) || nodigit( cur[1] ) || nodigit( cur[2] ) ||
 93 			( cur[3] != ' ' && cur[3] != '-' )
 94 		{
 95 			ineterror = $ERRFTP_RESPONSE
 96 			return 0						
 97 		} 
 98 		ret = uint( cur )
 99 	}
100 	if (lines[ *lines - 1 ])[ 3 ] != ' '
101 	{
102 		data.use-- 
103  		goto again
104 	}
105 
106 	this.notify( $NFYFTP_RESPONSE )
107 	return ret	
108 }
109 
110 method str ftp.lastresponse( str out )
111 {
112 	return out = this.ni.head
113 }
114 
115 method uint ftp.sendcmd( str cmd )
116 {
117 	this.ni.head = cmd
118 	if !this.ni.head.islast( 0xA ) : this.ni.head += "\l"
119 
120 	if !this.sock.send( this.ni.head ) : return this.notify( $NFYINET_ERROR )
121 	this.notify( $NFYFTP_SENDCMD )
122 
123 	return 1	
124 }
125 
126 method uint ftp.command( str cmd )
127 {
128 	if !this.sendcmd( cmd ) : return 0
129 	return this.cmdresponse()	
130 }
131 
132 method uint ftp.close
133 {
134 	uint cmd ret = 1
135 
136 	if this.sock.socket
137 	{
138 		cmd = this.command( "QUIT" )
139 	  	if cmd && cmd != $FTP_GOODBYE
140 		{
141 			ineterror = $ERRFTP_QUIT
142 	      this.notify( $NFYINET_ERROR )
143 			ret = 0
144 		}
145 	  	this.sock.close( )
146 	}
147 	return ret
148 }
149 
150 method uint ftp.open( str url user password, uint flag notify )
151 {
152 	uint len
153 	str  host
154 
155 	this.notify = notify
156    ineterror = 0
157    this.ni.url = url
158 
159 	if flag & $FTP_ANONYM : this.anonymous = 1 
160 	if flag & $FTP_PASV : this.passive = 1 
161 
162    this.notify( $NFYINET_CONNECT )
163 
164 	this.sock.flag |= $SOCKF_FTP
165 
166    if !this.sock.urlconnect( url, host, this.path ) : goto error 
167 	if this.cmdresponse() != $FTP_HELLO : goto error
168 	len = sizeof( sockaddr )
169 
170    if getsockname( this.sock.socket, &this.local, &len )  
171    {
172 		inet_seterror()
173 		goto error
174    }
175 	
176 	if !*user || this.anonymous : user = "anonymous"
177  
178 	if !this.sendcmd( "USER \( user )" ) : return 0
179   
180    switch this.cmdresponse( )
181    {
182 		case $FTP_LOGINOK {}   
183       case $FTP_LOGINBAD
184 		{
185 			ineterror = $ERRFTP_BADUSER
186 			goto error	
187 		}
188 	   case $FTP_PASSWD
189 		{
190 	      if !this.sendcmd( "PASS \( password )" ) : return 0
191       
192 	      switch this.cmdresponse()
193 			{
194 				case $FTP_LOGINOK {}
195 				case $FTP_LOGINBAD
196 				{
197 					ineterror = $ERRFTP_BADPSW
198 					goto error	
199 				}
200 				default 
201  				{
202 					ineterror = $ERRFTP_RESPONSE
203 					goto error
204 				}
205 			}
206 	   }
207     	default
208 		{
209 			ineterror = $ERRFTP_RESPONSE
210 			goto error
211 		}
212    }
213 	return 1
214 
215 	label error
216    this.notify( $NFYINET_ERROR )
217    this.close( )
218    return 0
219 }
220 
221 method uint ftp.listen
222 {
223 	uint cmd sin addr port
224 	sockaddr in  
225 
226 	if this.passive
227    {
228       cmd = this.command( "PASV" )
229       if cmd == $FTP_PASSIVEOK
230 		{
231 			str   ports response 
232 			uint  off till
233 			arrstr   portval 
234 
235 			off = this.lastresponse( response ).findch( '(', 0 ) + 1
236 			till = response.findchfrom( ')', off )
237 			ports.substr( response, off, till - off )
238 			ports.split( portval, ',', 0 )
239 			if *portval != 6 
240 			{
241 				ineterror = $ERRFTP_RESPONSE
242 				goto error
243 			}
244 			this.sockdata.host = "\(portval[0]).\(portval[1]).\(portval[2]).\(portval[3])"
245 			this.sockdata.port = (uint( portval[4] ) << 8) + uint( portval[5] )
246 			if this.sockdata.connect() : return 1
247 		}
248 		this.passive = 0
249 		this.notify( $NFYFTP_NOTPASV )
250 	}
251 
252 	this.sockserv.socket = createsocket( $AF_INET, $SOCK_STREAM, $IPPROTO_TCP ) 
253   
254    if this.sockserv.socket == $INVALID_SOCKET : return inet_seterror()
255 
256 	sin = sizeof( sockaddr )
257 	mcopy( &in, &this.local, sin )
258   	in->sockaddr_in.sin_port = 0
259   
260  	if bind( this.sockserv.socket, &in, sin ) ||
261 		listen( this.sockserv.socket, 1 ) ||
262 		getsockname( this.sockserv.socket, &in, &sin )
263    {
264 		inet_seterror()
265 		goto error
266    }
267 
268   	addr = ntohl( this.local->sockaddr_in.sin_addr )
269   	port = ntohs( in->sockaddr_in.sin_port )
270   
271 	if this.command( "PORT \((addr >> 24) & 0xFF ),\((addr >> 16) & 0xFF ),\((addr >> 8) & 0xFF ),\(addr & 0xFF ),\((port >> 8) & 0xFF ),\(port & 0xFF )") != $FTP_OK
272    {
273 		ineterror = $ERRFTP_PORT
274       goto error
275    }
276 	return 1
277 
278 	label error
279 	this.notify( $NFYINET_ERROR )
280 	return 0
281 }
282 
283 method uint ftp.accept
284 {
285 	if !this.passive && ( this.sockdata.socket = 
286                 accept( this.sockserv.socket, 0, 0 )) == $INVALID_SOCKET 
287 	{
288 		inet_seterror()
289 		this.notify( $NFYINET_ERROR )
290 		return 0
291 	}
292   	return this.sockdata.socket
293 }
294 
295 method uint ftp.list( str data, str mode )
296 {
297 	uint i dif
298 
299 	if !this.listen() : return 0
300 
301 //	if this.command( "MLSD" ) != $FTP_OPENING : return 0
302 	if this.command( mode ) != $FTP_OPENING : return 0
303 
304 	if !this.accept() : return 0
305 
306 	data->buf.use = 0
307    do 
308    {
309       i = *data
310       this.sockdata.recv( data->buf )
311       dif = *data - i
312    } while dif
313 
314 	data->buf += byte( 0 )
315 
316 	this.sockdata.close()
317 
318 	// ? надо или нет закрывать
319 	if !this.passive : this.sockserv.close()
320  
321 	if this.cmdresponse() != $FTP_ENDTRAN
322    {
323 		ineterror = $ERRFTP_RESPONSE
324 		this.notify( $NFYINET_ERROR )
325 		return 0
326    }
327 	return 1
328 }
329 
330 method uint ftp.createdir( str dirname )
331 {
332 	return this.command("MKD \(dirname)") == $FTP_MKDIROK
333 }
334 
335 method uint ftp.deldir( str dirname )
336 {
337 	return this.command("RMD \(dirname)") == $FTP_CWDOK
338 }
339 
340 method uint ftp.delfile( str filename )
341 {
342 	return this.command("DELE \(filename)") == $FTP_CWDOK
343 }
344 
345 method uint ftp.setcurdir( str dirname )
346 {
347 	return this.command("CWD \(dirname)") == $FTP_CWDOK
348 }
349 
350 method uint ftp.getcurdir( str dirname )
351 {
352 	str   response 
353 	uint  off till
354 
355 	dirname.clear()
356 	if this.command("PWD") != $FTP_MKDIROK : return 0
357 
358 	off = this.lastresponse( response ).findch( '"', 0 ) + 1
359 	till = response.findchfrom( '"', off )
360 	dirname.substr( response, off, till - off )
361 	if !*dirname : return 0
362 
363 	return 1
364 }
365 
366 method uint ftp.rename( str from to )
367 {
368 	if this.command("RNFR \(from)") != $FTP_FILEOK : return 0
369 	return this.command("RNTO \(to)") == $FTP_CWDOK 
370 }
371 
372 method uint ftp.getsize( str name, uint psize )
373 {
374 	str size
375 
376 	psize->uint = 0
377 	if this.command("SIZE \(name)") != $FTP_FILESTAT : return 0
378 
379 	this.lastresponse( size ).del( 0, 4 )
380 	psize->uint = uint( size )
381 	return 1 
382 }
383 
384 method uint ftp.gettime( str name, datetime dt )
385 {
386 	str time year month day
387 
388 	mzero( &dt, sizeof( datetime ))
389 	if this.command("MDTM \(name)") != $FTP_FILESTAT : return 0
390 
391 	this.lastresponse( time ).del( 0, 4 )
392 	time.trimspace()
393 	year.substr( time, 0, 4 )
394 	month.substr( time, 4, 2 )
395 	day.substr( time, 6, 2 )
396 	dt.setdate( uint( day ), uint( month ), uint( year ))
397 	dt.hour = uint( year.substr( time, 8, 2 ))
398 	dt.minute = uint( month.substr( time, 10, 2 ))
399 	dt.second = uint( day.substr( time, 12, 2 ))
400 	
401 	return 1 
402 }
403 
404 method uint ftp.setattrib( str name, uint mode )
405 {
406 //	str  chmode
407 
408 	mode &= $S_IRWXU | $S_IRWXG | $S_IRWXO
409 	
410 	if this.command("SITE CHMOD \(hex2strl( mode)) \(name)") != $FTP_OK
411 	{ 
412  		return 0
413 	}
414 	return 1 
415 }
416 
417 method uint ftp.getfile( str filename, buf databuf, uint flag )
418 {
419 	uint       data dif i 
420    buf        fbuf
421    uint       ret range
422    file       fdwn
423 	uint       isfile = flag & $FTP_FILE
424 	finfo      fi 
425 
426 	if this.command( "TYPE \(?( flag & $FTP_BINARY, "I", "A" ))") != $FTP_OK
427 	{ 
428 		return 0	
429 	}
430 	if !this.listen() : return 0
431 
432 	this.ni.param = 0
433  
434 	if isfile && flag & $FTP_CONTINUE
435    {  
436       getfileinfo( databuf->str, fi )
437       if fi.sizelo
438 		{
439 			if this.command( "REST \(fi.sizelo)" ) != $FTP_FILEOK
440 			{
441 				flag &= ~$FTP_CONTINUE
442 			}
443 			else : this.ni.param = fi.sizelo
444 		}	 
445    }
446 	data = ?( isfile, &fbuf, &databuf )
447    data as buf
448 
449    if isfile
450    {
451       data.expand( 0x20000 )
452       if !( fdwn.open( databuf->str, ?( flag & $FTP_CONTINUE,
453                             $OP_ALWAYS, $OP_CREATE )))
454       {
455          this.ni.sparam = databuf->str
456          ineterror = $ERRINET_OPENFILE
457          this.notify( $NFYINET_ERROR )
458          goto end
459       }
460 		if this.ni.param : fdwn.setpos( 0, $FILE_END )
461    }
462    else 
463    {
464 		uint fullsize
465 
466 		data.clear()
467 		this.getsize( filename, &fullsize )
468       if uint( fullsize ) : data.expand( uint( fullsize ) + 0x7FFF )
469    }
470 
471   	if this.command( "RETR \(filename)" ) != $FTP_OPENING : return 0 
472   
473 	if !this.accept() : return 0
474 
475 	do 
476    {
477       i = *data
478       if !this.notify( $NFYINET_GET )
479 		{
480 			this.sockdata.close()
481 //			this.command("ABOR") 
482  			goto end
483 		}
484       this.sockdata.recv( data )
485       
486 		dif = *data - i
487       this.ni.param += dif
488  
489       if isfile && ( *data >= 0x7FFF || !dif )
490       {
491          if !( fdwn.write( data ))
492          {
493             this.ni.sparam = databuf->str
494             ineterror = $ERRINET_WRITEFILE
495             this.notify( $NFYINET_ERROR )
496             goto end
497          }
498          data.use = 0
499       }
500    } while dif
501    
502    if flag & $FTP_STR : data += byte( 0 )
503    this.notify( $NFYINET_END )
504 	this.sockdata.close()
505 
506 	if this.cmdresponse() != $FTP_ENDTRAN
507 	{
508 		ineterror = $ERRFTP_RESPONSE
509 		goto end
510 	}
511 
512    ret = 1   
513    label end      
514    if fdwn.fopen 
515    {
516       if ret && flag & $FTP_SETTIME
517       {
518          filetime ft
519 			datetime dt
520          
521 			if this.gettime( filename, dt )
522 			{
523          	datetimetoftime( dt, ft )
524          	fdwn.settime( ft )
525 			}
526       }
527       fdwn.close( )
528    }
529    if !ret && ineterror : this.notify( $NFYINET_ERROR )
530    
531    return ret
532 }
533 
534 method uint ftp.getfile( str srcname destname, uint flag )
535 {
536    flag &= 0xF0FF
537    return this.getfile( srcname, destname->buf, flag | $FTP_FILE )
538 }
539 
540 method uint ftp.putfile( str srcname destname, uint flag )
541 {
542 	uint  offset size cur ret i
543    file  fdwn
544 	buf   data
545 	str   tmode
546 
547 	subfunc uint nextread
548 	{
549 		cur = min( size, 0x20000 )
550 		data.use = 0
551 		if fdwn.read( data, cur ) != cur
552 		{
553    		this.ni.sparam = srcname
554       	ineterror = $ERRINET_READFILE
555       	return 0
556 		}
557 		size -= cur
558 		return 1
559 	}
560 
561    if !( fdwn.open( srcname, $OP_READONLY ))
562    {
563    	this.ni.sparam = srcname
564       ineterror = $ERRINET_OPENFILE
565       this.notify( $NFYINET_ERROR )
566       return 0
567    }
568 	size = fdwn.getsize( ) 
569 	if flag & $FTP_CONTINUE
570 	{ 
571 		if !this.getsize( destname, &offset ) || offset >= size
572 		{
573 			flag &= ~$FTP_CONTINUE
574 		}
575 		else
576 		{
577 			this.ni.param = offset
578 			size -= offset
579 			fdwn.setpos(  offset, $FILE_BEGIN )
580 		}
581 	}
582    data.expand( 0x20000 )
583 	if !nextread() : goto end
584 
585 	tmode = "TYPE A"	
586 	if flag & $FTP_BINARY : tmode = "TYPE I" 	
587 	elif !( flag & $FTP_TEXT )
588 	{
589 		fornum i = 0, *data - 1
590 		{
591 			if !data[i] || ( data[i] == 0xD && data[i + 1] != 0xA )
592 			{
593 				tmode = "TYPE I"
594 				break		
595 			}    
596 		}		
597 	}
598 	if this.command( tmode ) != $FTP_OK : goto close	
599 	if !this.listen() : goto close
600 	
601 	if this.command( "\(?( flag & $FTP_CONTINUE, "APPE", 
602                     "STOR")) \( destname )") != $FTP_OPENING : goto close  
603 
604 	if !this.accept() : goto close 
605 
606 	while 1
607 	{
608 		uint off last
609 	   uint sent
610 
611 	  	last = *data
612    
613 	   while last
614    	{   
615       	sent = send( this.sockdata.socket, data.ptr() + off, min( 0x7FFF, last ), 
616                       0  )
617 			if	sent == $SOCKET_ERROR 
618 			{
619 				inet_seterror()
620 				this.sockdata.close()
621 				goto close
622 			}
623 			else
624 			{
625 				this.ni.param += sent
626 				if !this.notify( $NFYINET_PUT )
627 				{
628 					this.sockdata.close()
629  					goto close
630 				}
631 			}
632       	last -= sent
633       	off += sent
634    	}
635 //		this.sockdata.send( data )
636 		if !size : break
637 		nextread()
638 	}
639    this.notify( $NFYINET_END )
640 	this.sockdata.close()
641 	if this.cmdresponse() != $FTP_ENDTRAN
642 	{
643 		ineterror = $ERRFTP_RESPONSE
644 		goto end
645 	}
646    ret = 1   
647    label end      
648    if !ret && ineterror : this.notify( $NFYINET_ERROR )
649 	label close
650    fdwn.close( )
651    
652    return ret
653 }