| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | ! Copyright (C) 2008 Doug Coleman. | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2010-09-04 23:16:57 -04:00
										 |  |  | USING: accessors calendar calendar.format classes combinators | 
					
						
							| 
									
										
										
										
											2010-02-20 23:00:48 -05:00
										 |  |  | combinators.short-circuit concurrency.promises continuations | 
					
						
							| 
									
										
										
										
											2010-09-04 23:16:57 -04:00
										 |  |  | destructors ftp io io.directories io.encodings | 
					
						
							|  |  |  | io.encodings.8-bit.latin1 io.encodings.binary io.encodings.utf8 | 
					
						
							|  |  |  | io.files io.files.info io.files.types io.pathnames | 
					
						
							| 
									
										
										
										
											2010-09-27 20:12:33 -04:00
										 |  |  | io.servers io.sockets io.streams.string io.timeouts | 
					
						
							| 
									
										
										
										
											2010-09-04 23:16:57 -04:00
										 |  |  | kernel logging math math.bitwise math.parser namespaces | 
					
						
							|  |  |  | sequences simple-tokenizer splitting strings threads | 
					
						
							| 
									
										
										
										
											2016-03-31 02:29:48 -04:00
										 |  |  | tools.files unicode ;
 | 
					
						
							| 
									
										
										
										
											2008-05-12 20:31:56 -04:00
										 |  |  | IN: ftp.server | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | SYMBOL: server | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | SYMBOL: client | 
					
						
							| 
									
										
										
										
											2008-05-12 20:31:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | TUPLE: ftp-server < threaded-server { serving-directory string } ;
 | 
					
						
							| 
									
										
										
										
											2008-11-13 20:33:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | TUPLE: ftp-client user password extra-connection ;
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | TUPLE: ftp-command raw tokenized ;
 | 
					
						
							|  |  |  | : <ftp-command> ( str -- obj )
 | 
					
						
							|  |  |  |     dup \ <ftp-command> DEBUG log-message | 
					
						
							|  |  |  |     ftp-command new
 | 
					
						
							|  |  |  |         over >>raw | 
					
						
							| 
									
										
										
										
											2010-02-20 23:00:48 -05:00
										 |  |  |         swap tokenize >>tokenized ;
 | 
					
						
							| 
									
										
										
										
											2008-05-12 20:31:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | TUPLE: ftp-get path ;
 | 
					
						
							| 
									
										
										
										
											2014-11-30 11:43:50 -05:00
										 |  |  | C: <ftp-get> ftp-get | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | TUPLE: ftp-put path ;
 | 
					
						
							| 
									
										
										
										
											2014-11-30 11:43:50 -05:00
										 |  |  | C: <ftp-put> ftp-put | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | TUPLE: ftp-list ;
 | 
					
						
							|  |  |  | C: <ftp-list> ftp-list | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | TUPLE: ftp-disconnect ;
 | 
					
						
							|  |  |  | C: <ftp-disconnect> ftp-disconnect | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : (send-response) ( n string separator -- )
 | 
					
						
							| 
									
										
										
										
											2008-12-16 02:50:25 -05:00
										 |  |  |     [ number>string write ] 2dip write ftp-send ;
 | 
					
						
							| 
									
										
										
										
											2008-05-12 20:31:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | : send-response ( ftp-response -- )
 | 
					
						
							|  |  |  |     [ n>> ] [ strings>> ] bi
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  |     [ but-last-slice [ "-" (send-response) ] with each ] | 
					
						
							|  |  |  |     [ first " " (send-response) ] 2bi ;
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-05 01:40:47 -04:00
										 |  |  | : make-path-relative? ( path -- ? )
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         [ absolute-path? ] | 
					
						
							|  |  |  |         [ drop server get serving-directory>> ] | 
					
						
							|  |  |  |     } 1&& ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : fixup-relative-path ( string -- string' )
 | 
					
						
							|  |  |  |     dup make-path-relative? [ | 
					
						
							|  |  |  |         [ server get serving-directory>> ] dip append-relative-path | 
					
						
							|  |  |  |     ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : server-response ( string n -- )
 | 
					
						
							|  |  |  |     2dup number>string swap ":" glue \ server-response DEBUG log-message | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  |     <ftp-response> | 
					
						
							|  |  |  |         swap >>n | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         swap add-response-line | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  |     send-response ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : serving? ( path -- ? )
 | 
					
						
							| 
									
										
										
										
											2010-02-03 16:26:37 -05:00
										 |  |  |     resolve-symlinks server get serving-directory>> head? ;
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : can-serve-directory? ( path -- ? )
 | 
					
						
							|  |  |  |     { [ exists? ] [ file-info directory? ] [ serving? ] } 1&& ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : can-serve-file? ( path -- ? )
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         [ exists? ] | 
					
						
							| 
									
										
										
										
											2015-08-05 21:33:35 -04:00
										 |  |  |         [ file-info regular-file? ] | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         [ serving? ] | 
					
						
							|  |  |  |     } 1&& ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : ftp-error ( string -- ) 500 server-response ;
 | 
					
						
							| 
									
										
										
										
											2014-11-30 11:43:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : ftp-unimplemented ( string -- ) 502 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | : send-banner ( -- )
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     "Welcome to " host-name append 220 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | : anonymous-only ( -- )
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     "This FTP server is anonymous only." 530 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | : handle-QUIT ( obj -- )
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     drop "Goodbye." 221 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | : handle-USER ( ftp-command -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |         tokenized>> second client get user<< | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         "Please specify the password." 331 server-response | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     ] [ | 
					
						
							|  |  |  |         2drop "bad USER" ftp-error | 
					
						
							|  |  |  |     ] recover ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : handle-PASS ( ftp-command -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |         tokenized>> second client get password<< | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         "Login successful" 230 server-response | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     ] [ | 
					
						
							|  |  |  |         2drop "PASS error" ftp-error | 
					
						
							|  |  |  |     ] recover ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ERROR: type-error type ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  | : parse-type ( string -- string' )
 | 
					
						
							|  |  |  |     >upper { | 
					
						
							|  |  |  |         { "IMAGE" [ "Binary" ] } | 
					
						
							|  |  |  |         { "I" [ "Binary" ] } | 
					
						
							| 
									
										
										
										
											2015-08-13 19:13:05 -04:00
										 |  |  |         [ type-error ] | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  |     } case ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | : handle-TYPE ( obj -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  |         tokenized>> second parse-type | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         "Switching to " " mode" surround 200 server-response | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     ] [ | 
					
						
							|  |  |  |         2drop "TYPE is binary only" ftp-error | 
					
						
							|  |  |  |     ] recover ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  | : random-local-server ( -- server )
 | 
					
						
							| 
									
										
										
										
											2011-10-24 20:00:09 -04:00
										 |  |  |     remote-address get class-of new binary <server> ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : port>bytes ( port -- hi lo )
 | 
					
						
							| 
									
										
										
										
											2008-12-16 02:50:25 -05:00
										 |  |  |     [ -8 shift ] keep [ 8 bits ] bi@ ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-05 01:40:47 -04:00
										 |  |  | : display-directory ( -- string )
 | 
					
						
							|  |  |  |     current-directory get server get serving-directory>> swap ?head drop
 | 
					
						
							|  |  |  |     [ "/" ] when-empty ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | : handle-PWD ( obj -- )
 | 
					
						
							|  |  |  |     drop
 | 
					
						
							| 
									
										
										
										
											2014-04-26 17:52:37 -04:00
										 |  |  |     display-directory "\"" dup surround 257 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  | : handle-SYST ( obj -- )
 | 
					
						
							|  |  |  |     drop
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     "UNIX Type: L8" 215 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : start-directory ( -- )
 | 
					
						
							|  |  |  |     "Here comes the directory listing." 150 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-20 12:05:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : transfer-outgoing-file ( path -- )
 | 
					
						
							|  |  |  |     [ "Opening BINARY mode data connection for " ] dip
 | 
					
						
							|  |  |  |     [ file-name ] [ | 
					
						
							|  |  |  |         file-info size>> number>string | 
					
						
							|  |  |  |         "(" " bytes)." surround
 | 
					
						
							|  |  |  |     ] bi " " glue append 150 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : transfer-incoming-file ( path -- )
 | 
					
						
							|  |  |  |     "Opening BINARY mode data connection for " prepend
 | 
					
						
							|  |  |  |     150 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : finish-file-transfer ( -- )
 | 
					
						
							|  |  |  |     "File send OK." 226 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | GENERIC: handle-passive-command ( stream obj -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : passive-loop ( server -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             |dispose | 
					
						
							|  |  |  |             30 seconds over set-timeout | 
					
						
							|  |  |  |             accept drop &dispose | 
					
						
							|  |  |  |             client get extra-connection>> | 
					
						
							|  |  |  |             30 seconds ?promise-timeout | 
					
						
							|  |  |  |             handle-passive-command | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         [ client get f >>extra-connection drop ] | 
					
						
							|  |  |  |         [ drop ] cleanup
 | 
					
						
							|  |  |  |     ] with-destructors ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : finish-directory ( -- )
 | 
					
						
							|  |  |  |     "Directory send OK." 226 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | M: ftp-list handle-passive-command ( stream obj -- )
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     drop
 | 
					
						
							| 
									
										
										
										
											2008-11-18 14:31:43 -05:00
										 |  |  |     start-directory [ | 
					
						
							| 
									
										
										
										
											2010-09-05 01:40:47 -04:00
										 |  |  |         utf8 encode-output [ | 
					
						
							| 
									
										
										
										
											2016-03-18 20:04:05 -04:00
										 |  |  |             "." directory. | 
					
						
							| 
									
										
										
										
											2010-09-05 01:40:47 -04:00
										 |  |  |         ] with-string-writer string-lines | 
					
						
							| 
									
										
										
										
											2008-11-18 14:31:43 -05:00
										 |  |  |         harvest [ ftp-send ] each
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     ] with-output-stream finish-directory ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | M: ftp-get handle-passive-command ( stream obj -- )
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     [ | 
					
						
							|  |  |  |         path>> | 
					
						
							| 
									
										
										
										
											2008-05-20 12:05:05 -04:00
										 |  |  |         [ transfer-outgoing-file ] | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |         [ binary <file-reader> swap stream-copy ] bi
 | 
					
						
							|  |  |  |         finish-file-transfer | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         3drop "File transfer failed" ftp-error | 
					
						
							|  |  |  |     ] recover ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | M: ftp-put handle-passive-command ( stream obj -- )
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     [ | 
					
						
							|  |  |  |         path>> | 
					
						
							| 
									
										
										
										
											2008-05-20 12:05:05 -04:00
										 |  |  |         [ transfer-incoming-file ] | 
					
						
							|  |  |  |         [ binary <file-writer> stream-copy ] bi
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |         finish-file-transfer | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         3drop "File transfer failed" ftp-error | 
					
						
							|  |  |  |     ] recover ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | M: ftp-disconnect handle-passive-command ( stream obj -- )
 | 
					
						
							|  |  |  |     drop dispose ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : fulfill-client ( obj -- )
 | 
					
						
							|  |  |  |     client get extra-connection>> [ | 
					
						
							|  |  |  |         fulfill | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         drop
 | 
					
						
							|  |  |  |         "Establish an active or passive connection first" ftp-error | 
					
						
							|  |  |  |     ] if* ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : handle-STOR ( obj -- )
 | 
					
						
							|  |  |  |     tokenized>> second
 | 
					
						
							|  |  |  |     dup can-serve-file? [ | 
					
						
							|  |  |  |         <ftp-put> fulfill-client | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2015-06-29 19:43:15 -04:00
										 |  |  |         drop
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         <ftp-disconnect> fulfill-client | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : handle-LIST ( obj -- )
 | 
					
						
							|  |  |  |     drop current-directory get
 | 
					
						
							|  |  |  |     can-serve-directory? [ | 
					
						
							|  |  |  |         <ftp-list> fulfill-client | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         <ftp-disconnect> fulfill-client | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : not-a-plain-file ( path -- )
 | 
					
						
							|  |  |  |     ": not a plain file." append ftp-error ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : handle-RETR ( obj -- )
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     tokenized>> second
 | 
					
						
							| 
									
										
										
										
											2010-09-05 01:40:47 -04:00
										 |  |  |     fixup-relative-path | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     dup can-serve-file? [ | 
					
						
							|  |  |  |         <ftp-get> fulfill-client | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         not-a-plain-file | 
					
						
							|  |  |  |         <ftp-disconnect> fulfill-client | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : handle-SIZE ( obj -- )
 | 
					
						
							|  |  |  |     tokenized>> second
 | 
					
						
							|  |  |  |     dup can-serve-file? [ | 
					
						
							|  |  |  |         file-info size>> number>string 213 server-response | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         not-a-plain-file | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  | : expect-connection ( -- port )
 | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |     <promise> client get extra-connection<< | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  |     random-local-server | 
					
						
							|  |  |  |     [ [ passive-loop ] curry in-thread ] | 
					
						
							|  |  |  |     [ addr>> port>> ] bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : handle-PASV ( obj -- )
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     drop
 | 
					
						
							| 
									
										
										
										
											2008-12-16 02:50:25 -05:00
										 |  |  |     expect-connection port>bytes [ number>string ] bi@ "," glue
 | 
					
						
							|  |  |  |     "Entering Passive Mode (127,0,0,1," ")" surround
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     221 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | : handle-EPSV ( obj -- )
 | 
					
						
							|  |  |  |     drop
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |     client get f >>extra-connection drop
 | 
					
						
							|  |  |  |     expect-connection number>string | 
					
						
							|  |  |  |     "Entering Extended Passive Mode (|||" "|)" surround
 | 
					
						
							|  |  |  |     229 server-response ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : handle-MDTM ( obj -- )
 | 
					
						
							| 
									
										
										
										
											2011-10-13 15:53:46 -04:00
										 |  |  |     tokenized>> ?second [ | 
					
						
							| 
									
										
										
										
											2010-09-05 01:40:47 -04:00
										 |  |  |         fixup-relative-path | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         dup file-info dup directory? [ | 
					
						
							|  |  |  |             drop not-a-plain-file | 
					
						
							|  |  |  |         ] [ | 
					
						
							|  |  |  |             nip
 | 
					
						
							|  |  |  |             modified>> timestamp>mdtm | 
					
						
							|  |  |  |             213 server-response | 
					
						
							|  |  |  |         ] if
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         "" not-a-plain-file | 
					
						
							|  |  |  |     ] if* ;
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : directory-change-success ( -- )
 | 
					
						
							|  |  |  |     "Directory successully changed." 250 server-response ;
 | 
					
						
							| 
									
										
										
										
											2008-11-13 20:33:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : directory-change-failed ( -- )
 | 
					
						
							|  |  |  |     "Failed to change directory." 553 server-response ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : handle-CWD ( obj -- )
 | 
					
						
							| 
									
										
										
										
											2011-10-13 15:53:46 -04:00
										 |  |  |     tokenized>> ?second [ | 
					
						
							| 
									
										
										
										
											2010-09-04 23:16:57 -04:00
										 |  |  |         fixup-relative-path | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         dup can-serve-directory? [ | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |             set-current-directory | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |             directory-change-success | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |         ] [ | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |             drop
 | 
					
						
							|  |  |  |             directory-change-failed | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |         ] if
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         directory-change-success | 
					
						
							|  |  |  |     ] if* ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 08:54:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : unrecognized-command ( obj -- )
 | 
					
						
							|  |  |  |     raw>> "Unrecognized command: " prepend ftp-error ;
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : client-loop-dispatch ( str/f -- ? )
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  |     dup tokenized>> first >upper { | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         { "QUIT" [ handle-QUIT f ] } | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |         { "USER" [ handle-USER t ] } | 
					
						
							|  |  |  |         { "PASS" [ handle-PASS t ] } | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         { "SYST" [ handle-SYST t ] } | 
					
						
							|  |  |  |         { "ACCT" [ drop "ACCT unimplemented" ftp-unimplemented t ] } | 
					
						
							|  |  |  |         { "PWD" [ handle-PWD t ] } | 
					
						
							|  |  |  |         { "TYPE" [ handle-TYPE t ] } | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |         { "CWD" [ handle-CWD t ] } | 
					
						
							| 
									
										
										
										
											2008-05-19 22:52:16 -04:00
										 |  |  |         { "PASV" [ handle-PASV t ] } | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         { "EPSV" [ handle-EPSV t ] } | 
					
						
							|  |  |  |         { "LIST" [ handle-LIST t ] } | 
					
						
							| 
									
										
										
										
											2008-05-20 12:05:05 -04:00
										 |  |  |         { "STOR" [ handle-STOR t ] } | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |         { "RETR" [ handle-RETR t ] } | 
					
						
							|  |  |  |         { "SIZE" [ handle-SIZE t ] } | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         { "MDTM" [ handle-MDTM t ] } | 
					
						
							|  |  |  |         [ drop unrecognized-command t ] | 
					
						
							|  |  |  |     } case ;
 | 
					
						
							| 
									
										
										
										
											2008-05-12 20:31:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : read-command ( -- ftp-command/f )
 | 
					
						
							|  |  |  |     readln [ f ] [ <ftp-command> ] if-empty ;
 | 
					
						
							| 
									
										
										
										
											2008-05-12 20:31:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : handle-client-loop ( -- )
 | 
					
						
							|  |  |  |     read-command [ | 
					
						
							|  |  |  |         client-loop-dispatch | 
					
						
							|  |  |  |         [ handle-client-loop ] when
 | 
					
						
							|  |  |  |     ] when* ;
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : serve-directory ( server -- )
 | 
					
						
							|  |  |  |     serving-directory>> [ | 
					
						
							|  |  |  |         send-banner | 
					
						
							|  |  |  |         handle-client-loop | 
					
						
							|  |  |  |     ] with-directory ;
 | 
					
						
							| 
									
										
										
										
											2008-06-18 02:59:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: ftp-server handle-client* ( server -- )
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     [ | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  |         "New client" \ handle-client* DEBUG log-message | 
					
						
							|  |  |  |         ftp-client new client set
 | 
					
						
							|  |  |  |         [ server set ] [ serve-directory ] bi
 | 
					
						
							| 
									
										
										
										
											2008-05-19 19:58:35 -04:00
										 |  |  |     ] with-destructors ;
 | 
					
						
							| 
									
										
										
										
											2008-05-12 20:31:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 14:36:23 -05:00
										 |  |  | : <ftp-server> ( directory port -- server )
 | 
					
						
							| 
									
										
										
										
											2009-05-30 20:15:53 -04:00
										 |  |  |     latin1 ftp-server new-threaded-server | 
					
						
							| 
									
										
										
										
											2008-06-18 02:59:29 -04:00
										 |  |  |         swap >>insecure | 
					
						
							| 
									
										
										
										
											2010-02-03 16:26:37 -05:00
										 |  |  |         swap resolve-symlinks >>serving-directory | 
					
						
							| 
									
										
										
										
											2008-06-18 02:59:29 -04:00
										 |  |  |         "ftp.server" >>name | 
					
						
							| 
									
										
										
										
											2009-05-30 20:15:53 -04:00
										 |  |  |         5 minutes >>timeout ;
 | 
					
						
							| 
									
										
										
										
											2008-06-18 02:59:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:38:02 -04:00
										 |  |  | : ftpd ( directory port -- server )
 | 
					
						
							| 
									
										
										
										
											2008-06-18 02:59:29 -04:00
										 |  |  |     <ftp-server> start-server ;
 | 
					
						
							| 
									
										
										
										
											2008-05-12 20:31:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:26:11 -04:00
										 |  |  | ! sudo tcpdump -i en1 -A -s 10000  tcp port 21 | 
					
						
							| 
									
										
										
										
											2010-09-04 23:16:57 -04:00
										 |  |  | ! [2010-09-04T22:07:58-05:00] DEBUG server-response: 500:Unrecognized command: EPRT |2|0:0:0:0:0:0:0:1|59359| |