[REBOL] interactive FTP
From: sqlab:gmx at: 15-Jun-2001 10:39
Hi
Inspired by the telnet scheme from Frank Sievertsen, the recent discussion
about FTP and some problems I had last year with non standard FTP servers I
finished this script now.
(Un)fortunately I do not use a proxy, so don't ask me about that feature.
I hope the formatting is not to much changed by my remailer program.
AR
REBOL [title: "mFT"
date: 15-June-2001
Author: "Anton Reisacher"
Email: [sqlab--gmx--net]
File: %mftp.r
Version: 1.0
Description: {minimal interactive ftp scheme without conversion to Rebol
standards
should allow usage of any ftp command supported by your host,
even Xxxx commands
for example just do %mftp.r
port: open mftp://user:[pass--host]
insert port "HELP"
print copy port ; and you see what your server supports
insert port "XCWD $volume.subvolume" ; if your host uses a
different filesystem
copy port
insert port "LIST"
print copy port ; complete listing
got: make string! 1000
insert port "TYPE I"
copy port
insert port "RETR file"
while [get: copy port ] [append got get] ; retrieve all data
insert port "TYPE A" ; take care of CRLF in ASCII mode by
yourself
copy port
insert port "STOR Test"
insert port data ; you can do repeated inserts until you do a
copy
copy port
close port
Proxies are not supported.
}
Category: 'ftp
]
mftp: make root-protocol [
scheme: 'mftp
port-id: 21
port-flags: system/standard/port-flags/pass-thru
open: func [port [port! url!]
/local tmp
] [
open-proto port
port/sub-port/state/flags: port/sub-port/state/flags or 2051
port/state/flags: port/state/flags or
system/standard/port-flags/direct or 2051
if port/user [
tmp: make string! 512
until [
if not wait [port/sub-port port/timeout] [net-error
Timeout
]
any [find/any append tmp copy port"log?n"
find/any tmp "user"
find/any tmp "name"
]
]
system/words/insert port/sub-port join "USER " port/user
]
if port/pass [
tmp: make string! 256
until [
if not wait [port/sub-port port/timeout] [net-error
Timeout
]
find/any append tmp copy port"pass"
]
system/words/insert port/sub-port join "PASS " port/pass
]
tmp: make string! 128
until [
if not wait [port/sub-port port/timeout] [net-error "Timeout"]
find/any append tmp copy port"230"
]
port/user-data: tmp
]
copy: func [port [port!] /part len [integer!] /local tmp ;leng
] [ tmp: make string! 4096
either port/local-service = 'in [
port/local-service: none
system/words/close port/remote-service
port/remote-service: none
if not wait [port/sub-port port/timeout] [net-error "Timeout"]
net-utils/net-log append tmp system/words/copy port/sub-port
] [ either port/remote-service [
all [
port/local-service <> 'out
port/local-service: 'out
not wait [port/remote-service port/timeout]
net-error "Timeout"
]
either part [
tmp: system/words/copy/part port/remote-service len
][
tmp: system/words/copy port/remote-service
]
either tmp [
; leng: :leng + length? tmp
net-utils/net-log to-string tmp
] [
tmp: net-utils/net-log system/words/copy port/sub-port
; if leng <> check length?
system/words/close port/remote-service
port/remote-service: none
]
] [either port/user-data [
tmp: port/user-data
port/user-data: none
tmp
] [
net-utils/net-log append tmp system/words/copy port/sub-port
] ] ]
]
insert: func [port [port!] data /local listen-port tmp] [
either all [port/remote-service
port/local-service <> 'out
port/local-service: 'in
] [
system/words/insert port/remote-service data
] [
error? try [catch [close port/remote-service]]
port/remote-service: none
port/local-service: none
; either all [not proxy not passive] [listen-port: get-port
port] [data-connect]
listen-port: system/words/open/binary/direct tcp://:0
tmp: form reduce port/sub-port/local-ip
append tmp rejoin ["." form to-integer (listen-port/port-id /
256)
"." (listen-port/port-id // 256)
]
replace/all tmp #"." #","
system/words/insert port/sub-port net-utils/net-log join "PORT "
tmp
tmp: make string! 128
until [
if not wait [port/sub-port port/timeout] [net-error
Timeout
]
find/any append tmp copy port"200"
]
system/words/insert port/sub-port net-utils/net-log data
tmp: make string! 128
until [
if not wait [port/sub-port port/timeout] [net-error
Timeout
]
find/any append tmp copy port"???"
]
either find tmp "150" [
port/remote-service: first listen-port
] [
port/user-data: tmp
port/remote-service: none
]
system/words/close listen-port
]
]
close: func [port [port!] ] [
system/words/insert port/sub-port net-utils/net-log"QUIT"
system/words/close port/sub-port
error? try [catch [system/words/close data/remote-service]]
]
net-utils/net-install 'mFtp self 21
]