FTP: Difference between revisions
(created page) |
(alternative tcl implementation) |
||
Line 23: | Line 23: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
===Using package ftp=== |
|||
<lang Tcl> |
<lang Tcl> |
||
package require ftp |
package require ftp |
||
Line 33: | Line 34: | ||
::ftp::Type $conn binary |
::ftp::Type $conn binary |
||
::ftp::Get $conn README README |
::ftp::Get $conn README README |
||
</lang> |
|||
===Using a virtual file system=== |
|||
An alternative approach that uses the package [http://sourceforge.net/projects/tclvfs/ TclVFS] to access ftp:// paths as a virtual file system. |
|||
<lang tcl> |
|||
package require vfs::urltype |
|||
vfs::urltype::Mount ftp |
|||
# Patch to enable FTP passive mode. |
|||
source vfsftpfix.tcl |
|||
set dir [pwd] |
|||
cd ftp://kernel.org/pub/linux/kernel |
|||
foreach line [glob -dir ftp://kernel.org/pub/linux/kernel *] { |
|||
puts $line |
|||
} |
|||
file copy README [file join $dir README] |
|||
</lang> |
|||
The file <tt>vfsftpfix.tcl</tt> with the passive mode patch (see http://wiki.tcl.tk/12837): |
|||
<lang tcl> |
|||
# Replace vfs::ftp::Mount to enable vfs::ftp to work in passive |
|||
# mode and make that the default. |
|||
package require vfs::ftp |
|||
proc vfs::ftp::Mount {dirurl local {mode passive}} { |
|||
set dirurl [string trim $dirurl] |
|||
::vfs::log "ftp-vfs: attempt to mount $dirurl at $local" |
|||
if {[string index $dirurl end] != "/"} { |
|||
::vfs::log "ftp-vfs: adding missing directory delimiter to mount point" |
|||
append dirurl "/" |
|||
} |
|||
set urlRE {(?:ftp://)?(?:([^@:]*)(?::([^@]*))?@)?([^/:]+)(?::([0-9]*))?/(.*/)?$} |
|||
if {![regexp $urlRE $dirurl - user pass host port path]} { |
|||
return -code error "Sorry I didn't understand\ |
|||
the url address \"$dirurl\"" |
|||
} |
|||
if {![string length $user]} { |
|||
set user anonymous |
|||
} |
|||
if {![string length $port]} { |
|||
set port 21 |
|||
} |
|||
set fd [::ftp::Open $host $user $pass -port $port -output ::vfs::ftp::log -mode $mode] |
|||
if {$fd == -1} { |
|||
error "Mount failed" |
|||
} |
|||
if {$path != ""} { |
|||
if {[catch { |
|||
::ftp::Cd $fd $path |
|||
} err]} { |
|||
ftp::Close $fd |
|||
error "Opened ftp connection, but then received error: $err" |
|||
} |
|||
} |
|||
if {![catch {vfs::filesystem info $dirurl}]} { |
|||
# unmount old mount |
|||
::vfs::log "ftp-vfs: unmounted old mount point at $dirurl" |
|||
vfs::unmount $dirurl |
|||
} |
|||
::vfs::log "ftp $host, $path mounted at $fd" |
|||
vfs::filesystem mount $local [list vfs::ftp::handler $fd $path] |
|||
# Register command to unmount |
|||
vfs::RegisterMount $local [list ::vfs::ftp::Unmount $fd] |
|||
return $fd |
|||
} |
|||
</lang> |
</lang> |
Revision as of 20:05, 3 June 2014
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Connect to a server, change directory and download a file as binary using the FTP protocol. Use passive mode if available.
Python 2
<lang Python> from ftplib import FTP ftp = FTP('kernel.org') ftp.login() ftp.cwd('/pub/linux/kernel') ftp.set_pasv(True) # Default since Python 2.1 print ftp.retrlines('LIST') print ftp.retrbinary('RETR README', open('README', 'wb').write) ftp.quit() </lang>
REBOL
<lang REBOL> system/schemes/ftp/passive: on print read ftp://kernel.org/pub/linux/kernel/ write/binary %README read/binary ftp://kernel.org/pub/linux/kernel/README </lang>
Tcl
Using package ftp
<lang Tcl> package require ftp
set conn [::ftp::Open kernel.org anonymous "" -mode passive]
- ftp::Cd $conn /pub/linux/kernel
foreach line [ftp::NList $conn] {
puts $line
}
- ftp::Type $conn binary
- ftp::Get $conn README README
</lang>
Using a virtual file system
An alternative approach that uses the package TclVFS to access ftp:// paths as a virtual file system.
<lang tcl> package require vfs::urltype vfs::urltype::Mount ftp
- Patch to enable FTP passive mode.
source vfsftpfix.tcl
set dir [pwd] cd ftp://kernel.org/pub/linux/kernel foreach line [glob -dir ftp://kernel.org/pub/linux/kernel *] {
puts $line
} file copy README [file join $dir README] </lang>
The file vfsftpfix.tcl with the passive mode patch (see http://wiki.tcl.tk/12837): <lang tcl>
- Replace vfs::ftp::Mount to enable vfs::ftp to work in passive
- mode and make that the default.
package require vfs::ftp proc vfs::ftp::Mount {dirurl local {mode passive}} {
set dirurl [string trim $dirurl] ::vfs::log "ftp-vfs: attempt to mount $dirurl at $local" if {[string index $dirurl end] != "/"} { ::vfs::log "ftp-vfs: adding missing directory delimiter to mount point" append dirurl "/" }
set urlRE {(?:ftp://)?(?:([^@:]*)(?::([^@]*))?@)?([^/:]+)(?::([0-9]*))?/(.*/)?$} if {![regexp $urlRE $dirurl - user pass host port path]} { return -code error "Sorry I didn't understand\ the url address \"$dirurl\"" }
if {![string length $user]} { set user anonymous }
if {![string length $port]} { set port 21 }
set fd [::ftp::Open $host $user $pass -port $port -output ::vfs::ftp::log -mode $mode] if {$fd == -1} { error "Mount failed" }
if {$path != ""} { if {[catch { ::ftp::Cd $fd $path } err]} { ftp::Close $fd error "Opened ftp connection, but then received error: $err" } }
if {![catch {vfs::filesystem info $dirurl}]} { # unmount old mount ::vfs::log "ftp-vfs: unmounted old mount point at $dirurl" vfs::unmount $dirurl } ::vfs::log "ftp $host, $path mounted at $fd" vfs::filesystem mount $local [list vfs::ftp::handler $fd $path] # Register command to unmount vfs::RegisterMount $local [list ::vfs::ftp::Unmount $fd] return $fd
} </lang>