FTP: Difference between revisions
(→{{header|Go}}: Add Go) |
m (→{{header|Wren}}: Minor tidy) |
||
(64 intermediate revisions by 36 users not shown) | |||
Line 1: | Line 1: | ||
{{ |
{{task|Programming environment operations}}[[Category:Networking and Web Interaction]] |
||
;Task |
|||
Connect to a server, change directory, list its contents and download a file as binary using the FTP protocol. Use passive mode if available. |
Connect to a server, change directory, list its contents and download a file as binary using the FTP protocol. Use passive mode if available. |
||
<br/><br/> |
|||
=={{header|BASIC}}== |
|||
==={{header|BaCon}}=== |
|||
Using libCURL. |
|||
<syntaxhighlight lang="bacon">OPTION PARSE FALSE |
|||
PRAGMA INCLUDE <curl/curl.h> |
|||
PRAGMA LDFLAGS -lcurl |
|||
DECLARE easyhandle TYPE CURL* |
|||
OPEN "data.txt" FOR WRITING AS download |
|||
easyhandle = curl_easy_init() |
|||
curl_easy_setopt(easyhandle, CURLOPT_URL, "ftp://localhost/pub/data.txt") |
|||
curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, download) |
|||
curl_easy_setopt(easyhandle, CURLOPT_USERPWD, "anonymous") |
|||
success = curl_easy_perform(easyhandle) |
|||
curl_easy_cleanup(easyhandle) |
|||
CLOSE FILE download</syntaxhighlight> |
|||
Full native implementation without dependency to external libraries. |
|||
<syntaxhighlight lang="bacon">FUNCTION interact$(command$, connection, use_pasv) |
|||
LOCAL pasv$, data$, response$ |
|||
LOCAL port, passive |
|||
IF use_pasv THEN |
|||
SEND "PASV" & NL$ TO connection |
|||
RECEIVE data$ FROM connection |
|||
pasv$ = INBETWEEN$(data$, "(", ")") |
|||
port = VAL(TOKEN$(pasv$, 5, ","))*256 + VAL(TOKEN$(pasv$, 6, ",")) |
|||
OPEN "localhost:" & STR$(port) FOR NETWORK AS passive |
|||
ENDIF |
|||
IF LEN(command$) THEN SEND command$ & NL$ TO connection |
|||
WHILE WAIT(connection, 50) |
|||
RECEIVE data$ FROM connection |
|||
IF LEN(data$) = 0 THEN BREAK |
|||
response$ = response$ & data$ |
|||
WEND |
|||
IF use_pasv THEN |
|||
WHILE WAIT(passive, 50) |
|||
RECEIVE data$ FROM passive |
|||
IF LEN(data$) = 0 THEN BREAK |
|||
response$ = response$ & data$ |
|||
WEND |
|||
CLOSE NETWORK passive |
|||
ENDIF |
|||
RETURN response$ |
|||
ENDFUNC |
|||
OPEN "localhost:21" FOR NETWORK AS ftp |
|||
PRINT interact$("", ftp, 0) |
|||
PRINT interact$("USER anonymous", ftp, 0) |
|||
PRINT interact$("PASS ", ftp, 0) |
|||
PRINT interact$("CWD pub", ftp, 0) |
|||
PRINT interact$("LIST", ftp, 1) |
|||
PRINT interact$("TYPE I", ftp, 0) |
|||
PRINT interact$("RETR data.txt", ftp, 1) |
|||
PRINT interact$("QUIT", ftp, 0) |
|||
CLOSE NETWORK ftp</syntaxhighlight> |
|||
==={{header|FreeBASIC}}=== |
|||
Original code programmed by PaulSquires |
|||
[https://www.freebasic.net/forum/viewtopic.php?f=7&t=23867] |
|||
{{libheader|clsFTP}} |
|||
{{works with|Windows}} |
|||
====clsFTP.bas==== |
|||
<syntaxhighlight lang="vb">'' |
|||
'' |
|||
'' FTP class (Public Domain code - enjoy). |
|||
'' Windows only. Uses WinInet system functions. |
|||
'' Paul Squires of PlanetSquires Software (August 2015) |
|||
'' |
|||
'' Compiler: FreeBASIC 1.03 (32-bit) (64-bit) |
|||
'' |
|||
#Include Once "windows.bi" |
|||
#Include Once "\win\wininet.bi" |
|||
' // |
|||
' // |
|||
' // |
|||
Type clsFTP |
|||
Private: |
|||
m_hSession As HINTERNET |
|||
m_hConnection As HINTERNET |
|||
m_LastError As Integer |
|||
m_ServerPort As Integer |
|||
m_ServerName As String |
|||
m_UserName As String |
|||
m_Password As String |
|||
Public: |
|||
Declare Constructor |
|||
Declare Destructor |
|||
Declare Property hSession() As HINTERNET |
|||
Declare Property hSession(Byval nValue As HINTERNET) |
|||
Declare Property hConnection() As HINTERNET |
|||
Declare Property hConnection(Byval nValue As HINTERNET) |
|||
Declare Property LastError() As Integer |
|||
Declare Property ServerPort(Byval nValue As Integer) |
|||
Declare Property ServerPort() As Integer |
|||
Declare Property LastError(Byval nValue As Integer) |
|||
Declare Property ServerName() As String |
|||
Declare Property ServerName(Byval sValue As String) |
|||
Declare Property UserName() As String |
|||
Declare Property UserName(Byval sValue As String) |
|||
Declare Property Password() As String |
|||
Declare Property Password(Byval sValue As String) |
|||
Declare Function Connect Overload() As WINBOOL |
|||
Declare Function Connect Overload(Byval sServerName As String, _ |
|||
Byval sServerPort As Integer, _ |
|||
Byval sUserName As String, _ |
|||
Byval sPassword As String) As WINBOOL |
|||
Declare Sub Disconnect() |
|||
Declare Function SetCurrentFolder(Byval sFolderName As String) As WINBOOL |
|||
Declare Function GetCurrentFolder() As String |
|||
Declare Function RenameFile(Byval sOldFilename As String, _ |
|||
Byval sNewFilename As String) As WINBOOL |
|||
Declare Function UploadFile(Byval sLocal As String, _ |
|||
Byval sRemote As String) As WINBOOL |
|||
Declare Function DownloadFile(Byval sLocal As String, _ |
|||
Byval sRemote As String) As WINBOOL |
|||
Declare Function KillFile(Byval sRemote As String) As WINBOOL |
|||
End Type |
|||
'' |
|||
'' Initialize the class |
|||
'' |
|||
Constructor clsFTP |
|||
m_ServerPort = INTERNET_DEFAULT_FTP_PORT ' port 21 |
|||
End Constructor |
|||
'' |
|||
'' Close any open connection and session |
|||
'' |
|||
Destructor clsFTP |
|||
this.Disconnect |
|||
End Destructor |
|||
'' |
|||
'' hSession (Property) |
|||
'' |
|||
Property clsFTP.hSession() As HINTERNET |
|||
Property = this.m_hSession |
|||
End Property |
|||
Property clsFTp.hSession(Byval nValue As HINTERNET) |
|||
this.m_hSession = nValue |
|||
End Property |
|||
'' |
|||
'' hConnection (Property) |
|||
'' |
|||
Property clsFTP.hConnection() As HINTERNET |
|||
Property = this.m_hConnection |
|||
End Property |
|||
Property clsFTp.hConnection(Byval nValue As HINTERNET) |
|||
this.m_hConnection = nValue |
|||
End Property |
|||
'' |
|||
'' LastError (Property) |
|||
'' |
|||
Property clsFTP.LastError() As Integer |
|||
Property = this.m_LastError |
|||
End Property |
|||
Property clsFTp.LastError(Byval nValue As Integer) |
|||
this.m_LastError = nValue |
|||
End Property |
|||
'' |
|||
'' ServerPort (Property) |
|||
'' |
|||
Property clsFTP.ServerPort() As Integer |
|||
Property = this.m_ServerPort |
|||
End Property |
|||
Property clsFTp.ServerPort(Byval nValue As Integer) |
|||
this.m_ServerPort = nValue |
|||
End Property |
|||
'' |
|||
'' ServerName (Property) |
|||
'' |
|||
Property clsFTP.ServerName() As String |
|||
Property = this.m_ServerName |
|||
End Property |
|||
Property clsFTp.ServerName(Byval sValue As String) |
|||
this.m_ServerName = sValue |
|||
End Property |
|||
'' |
|||
'' UserName (Property) |
|||
'' |
|||
Property clsFTP.UserName() As String |
|||
Property = this.m_UserName |
|||
End Property |
|||
Property clsFTp.UserName(Byval sValue As String) |
|||
this.m_UserName = sValue |
|||
End Property |
|||
'' |
|||
'' Password (Property) |
|||
'' |
|||
Property clsFTP.Password() As String |
|||
Property = this.m_Password |
|||
End Property |
|||
Property clsFTp.Password(Byval sValue As String) |
|||
this.m_Password = sValue |
|||
End Property |
|||
'' |
|||
'' Close current connection and end session |
|||
'' |
|||
Sub clsFTP.Disconnect() |
|||
InternetCloseHandle this.hConnection |
|||
InternetCloseHandle this.hSession |
|||
this.hConnection = 0: this.hSession = 0 |
|||
End Sub |
|||
'' |
|||
'' Connect to an ftp host (overload). Returns TRUE if successful. |
|||
'' |
|||
Function clsFTP.Connect Overload() As WINBOOL |
|||
this.hSession = InternetOpen("ftpClass", INTERNET_OPEN_TYPE_DIRECT, "", "", 0) |
|||
If this.hSession = 0 Then |
|||
this.LastError = GetLastError |
|||
Function = False: Exit Function |
|||
End If |
|||
this.hConnection = InternetConnect(_ |
|||
this.hSession, this.ServerName, this.ServerPort, _ |
|||
this.UserName, this.Password, _ |
|||
INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0) |
|||
If this.hConnection = 0 Then |
|||
this.LastError = GetLastError |
|||
InternetCloseHandle(this.hSession) |
|||
Function = False: Exit Function |
|||
End If |
|||
Function = True |
|||
End Function |
|||
'' |
|||
'' Connect to an ftp host (overload). Returns TRUE if successful. |
|||
'' |
|||
Function clsFTP.Connect Overload (Byval sServerName As String, _ |
|||
Byval nServerPort As Integer, _ |
|||
Byval sUserName As String, _ |
|||
Byval sPassword As String) As WINBOOL |
|||
this.ServerName = sServerName |
|||
this.ServerPort = nServerPort |
|||
this.UserName = sUserName |
|||
this.Password = sPassword |
|||
Function = this.Connect |
|||
End Function |
|||
'' |
|||
'' Change to a folder on the server. Returns TRUE if successful. |
|||
'' |
|||
Function clsFTP.SetCurrentFolder(Byval sFolderName As String) As WINBOOL |
|||
Function = FtpSetCurrentDirectory(this.hConnection, sFolderName) |
|||
this.LastError = GetLastError |
|||
End Function |
|||
'' |
|||
'' Retrieves the name of current folder on the server. |
|||
'' |
|||
Function clsFTP.GetCurrentFolder() As String |
|||
Dim zBuffer As ZString * MAX_PATH |
|||
Dim nLength As Integer = MAX_PATH |
|||
FtpGetCurrentDirectory(this.hConnection, zBuffer, Cast(LPDWORD, @nLength)) |
|||
this.LastError = GetLastError |
|||
Function = zBuffer |
|||
End Function |
|||
'' |
|||
'' Rename a file on the server. Returns TRUE if successful. |
|||
'' |
|||
Function clsFTP.RenameFile(Byval sOldFilename As String, Byval sNewFilename As String) As WINBOOL |
|||
Function = FtpRenameFile(this.hConnection, sOldFilename, sNewFilename) |
|||
this.LastError = GetLastError |
|||
End Function |
|||
'' |
|||
'' Upload a file to the server. Returns TRUE if successful. |
|||
'' |
|||
Function clsFTP.UploadFile(Byval sLocal As String, Byval sRemote As String) As WINBOOL |
|||
Function = FtpPutFile(this.hConnection, sLocal, sRemote, FTP_TRANSFER_TYPE_BINARY, 0) |
|||
this.LastError = GetLastError |
|||
End Function |
|||
'' |
|||
'' Download a file from the server. Returns TRUE if successful. |
|||
'' |
|||
Function clsFTP.DownloadFile(Byval sLocal As String, Byval sRemote As String) As WINBOOL |
|||
Function = FtpGetFile(this.hConnection, sRemote, sLocal, False, _ |
|||
FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY Or INTERNET_FLAG_RELOAD, 0) |
|||
this.LastError = GetLastError |
|||
End Function |
|||
'' |
|||
'' Remove a file from the server. Returns TRUE if successful. |
|||
'' |
|||
Function clsFTP.KillFile(Byval sRemote As String) As WINBOOL |
|||
Function = FtpDeleteFile(this.hConnection, sRemote) |
|||
this.LastError = GetLastError |
|||
End Function</syntaxhighlight> |
|||
====simple_test.bas==== |
|||
<syntaxhighlight lang="vb">#Include Once "windows.bi" |
|||
#Include Once "clsFTP.bas" |
|||
Dim ftp As clsFTP |
|||
If ftp.Connect("ftp.ed.ac.uk", 21, "anonymous", "aaa@gmail.com") = False Then |
|||
Print "Error connecting to server. LastError = "; ftp.LastError |
|||
End If |
|||
If ftp.SetCurrentFolder("pub/courses") = False Then |
|||
Print "Error setting current folder. LastError = "; ftp.LastError |
|||
End If |
|||
Print "Current folder = "; ftp.GetCurrentFolder() |
|||
If ftp.DownloadFile("make.notes.tar", "make.notes.tar") = False Then |
|||
Print "Error downloading file. LastError = "; ftp.LastError |
|||
End If |
|||
ftp.Disconnect |
|||
Print "Done." |
|||
Sleep</syntaxhighlight> |
|||
==={{header|FutureBasic}}=== |
|||
FB for Mac easily interfaces with the terminal command line. NOTE: The curl command line tool used in this example offers upload and sending capabilities. It supports FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS, FILE, POP3, IMAP, SMTP, RTMP and RTSP. |
|||
<syntaxhighlight lang="futurebasic"> |
|||
include "NSLog.incl" |
|||
#plist NSAppTransportSecurity @{NSAllowsArbitraryLoads:YES} |
|||
local fn RunTerminalCommand( cmd as CFStringRef ) as CFStringRef |
|||
CFStringRef outputStr = NULL |
|||
TaskRef task = fn TaskInit |
|||
TaskSetExecutableURL( task, fn URLFileURLWithPath( @"/bin/zsh" ) ) |
|||
CFStringRef cmdStr = fn StringWithFormat( @"%@", cmd ) |
|||
CFArrayRef args = fn ArrayWithObjects( @"-c", cmdStr, NULL ) |
|||
TaskSetArguments( task, args ) |
|||
PipeRef p = fn PipeInit |
|||
TaskSetStandardOutput( task, p ) |
|||
TaskSetStandardError( task, p ) |
|||
FileHandleRef fh = fn PipeFileHandleForReading( p ) |
|||
fn TaskLaunch( task, NULL ) |
|||
TaskWaitUntilExit( task ) |
|||
ErrorRef err |
|||
CFDataRef dta = fn FileHandleReadDataToEndOfFile( fh, @err ) |
|||
if err then NSLog( @"%@", fn ErrorLocalizedDescription( err ) ) : exit fn |
|||
outputStr = fn StringWithData( dta, NSUTF8StringEncoding ) |
|||
end fn = outputStr |
|||
NSLog( @"%@", fn RunTerminalCommand( @"curl ftp://ftp.slackware.com/welcome.msg" ) ) |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
<pre style="font-size: 12px"> |
|||
% Total % Received % Xferd Average Speed Time Time Time Current |
|||
Dload Upload Total Spent Left Speed |
|||
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 |
|||
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 |
|||
100 754 100 754 0 0 1363 0 --:--:-- --:--:-- --:--:-- 1361 |
|||
--------------------------------------------------------------------------- |
|||
R S Y N C . O S U O S L . O R G |
|||
Oregon State University |
|||
Open Source Lab |
|||
Unauthorized use is prohibited - violators will be prosecuted |
|||
--------------------------------------------------------------------------- |
|||
For more information about the OSL visit: |
|||
http://osuosl.org/services/hosting |
|||
This host is the home to the primary archives of several |
|||
projects. We would prefer that only primary/secondary |
|||
mirrors use this service. Thanks! |
|||
--------------------------------------------------------------------------- |
|||
</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
Using the FTP package from [https://godoc.org/github.com/stacktic/ftp github.com/stacktic/ftp]. |
Using the FTP package from [https://godoc.org/github.com/stacktic/ftp github.com/stacktic/ftp]. |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 66: | Line 502: | ||
fmt.Println("Wrote", n, "bytes to", file) |
fmt.Println("Wrote", n, "bytes to", file) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Batch File}}== |
|||
This uses the native FTP.EXE in Windows. I am not sure, but I think FTP.EXE client does not support passive mode. |
|||
<syntaxhighlight lang="dos">::Playing with FTP |
|||
::Batch File Implementation |
|||
@echo off |
|||
set site="ftp.hq.nasa.gov" |
|||
set user="anonymous" |
|||
set pass="ftptest@example.com" |
|||
set dir="pub/issoutreach/Living in Space Stories (MP3 Files)" |
|||
set download="Gravity in the Brain.mp3" |
|||
( |
|||
echo.open %site% |
|||
echo.user %user% %pass% |
|||
echo.dir |
|||
echo.!echo. |
|||
echo.!echo.This is a just a text to seperate two directory listings. |
|||
echo.!echo. |
|||
echo.cd %dir% |
|||
echo.dir |
|||
echo.binary |
|||
echo.get %download% |
|||
echo.disconnect |
|||
)|ftp -n</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>\Desktop>RCFTP |
|||
-rw-r--r-- 1 ftpadmin ftp-adm 3997 May 26 1998 README |
|||
drwxrwx-wx 6 lgipson armd 696320 Jan 23 2015 armd |
|||
drwxrwx-wx 2 chmgt ftp-adm 4096 Aug 18 16:17 chmgt |
|||
-r-xr-xr-x 1 root root 18120 Nov 28 2001 ftp-exec |
|||
drwxrws-wx 2 ftpadmin ftp-adm 57344 Aug 18 13:08 incoming |
|||
-rw-rw-r-- 1 ftpadmin ftp-adm 133 Jan 29 1996 index.html |
|||
drwx------ 2 root root 4096 Apr 11 2003 lost+found |
|||
drwxr-sr-x 2 ftpadmin ftp-adm 4096 Apr 14 1998 office |
|||
drwxrwsr-x 17 ftpadmin ftp-adm 4096 Nov 4 2013 pub |
|||
-rw-r--r-- 1 root ftp-adm 26 Jan 27 2011 robots.txt |
|||
This is a just a text to seperate two directory listings. |
|||
-rw-rw-r-- 1 109 space-station 2327118 May 9 2005 09sept_spacepropulsion.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1260304 May 9 2005 Can People go to Mars.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1350270 May 9 2005 Distill some water.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1290888 May 9 2005 Good Vibrations.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1431834 May 9 2005 Gravity Hurts_So good.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1072644 May 9 2005 Gravity in the Brain.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1230594 May 9 2005 Power to the ISS.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1309062 May 9 2005 Space Bones.mp3 |
|||
-rw-rw-r-- 1 109 space-station 2292715 May 9 2005 Space Power.mp3 |
|||
-rw-rw-r-- 1 109 space-station 772075 May 9 2005 We have a solution.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1134654 May 9 2005 When Space Makes you Dizzy.mp3 |
|||
\Desktop></pre> |
|||
=={{header|C}}== |
|||
Using [http://nbpfaus.net/~pfau/ftplib/ ftplib] |
|||
<syntaxhighlight lang="c"> |
|||
#include <ftplib.h> |
|||
int main(void) |
|||
{ |
|||
netbuf *nbuf; |
|||
FtpInit(); |
|||
FtpConnect("kernel.org", &nbuf); |
|||
FtpLogin("anonymous", "", nbuf); |
|||
FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE, nbuf); |
|||
FtpChdir("pub/linux/kernel", nbuf); |
|||
FtpDir((void*)0, ".", nbuf); |
|||
FtpGet("ftp.README", "README", FTPLIB_ASCII, nbuf); |
|||
FtpQuit(nbuf); |
|||
return 0; |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|C++}}== |
|||
{{works with|c++|11}} |
|||
Using [http://nbpfaus.net/~pfau/ftplib/ ftplib], [https://github.com/saur0n/libftpxx libftp++] |
|||
<syntaxhighlight lang="cpp"> /* client.cpp |
|||
libftp++ C++ classes for ftplib C ftp library |
|||
compile: |
|||
clang++ -std=c++11 -o client client.cpp -lftp++ |
|||
*/ |
|||
#include <iostream> |
|||
#include <string> |
|||
#include <cstring> |
|||
#include <fstream> |
|||
#include <sys/stat.h> // stat |
|||
#include <ftplib.h> // libftp |
|||
#include <ftp++.hpp> // libftp++ |
|||
/* C++ classes: |
|||
Connection main ftp connection (user class) |
|||
ConnectionBase base class for Connection (internal) |
|||
DataConnection connection type, (internal) |
|||
read bytes from server, |
|||
write bytes to server |
|||
ConnectionException custom exception (thrown by Connection) |
|||
*/ |
|||
/** ftp::Connection class API |
|||
data members: |
|||
A Connection instance contains only a pointer as a data member |
|||
{ |
|||
protected: |
|||
netbuf * conn; // pointer to ftplib netbuf struct |
|||
} |
|||
member functions: |
|||
connect: |
|||
Connection(const char * host); // constructor |
|||
void setConnectionMode(Mode mode); // passive or port |
|||
void login(const char * user, const char * password); // Log in |
|||
info: |
|||
const char * getLastResponse(); // last server response |
|||
std::string getSystemType(); // server type |
|||
std::string getDirectory(); // remote pwd |
|||
void getList(const char * filename, const char * path); // short dir list |
|||
unsigned size(const char * path, TransferMode mode); |
|||
file transfer: |
|||
void get(const char * local, const char * remote, TransferMode mode); |
|||
void put(const char * local, const char * remote, TransferMode mode); |
|||
**/ |
|||
// libc functions |
|||
int stat(const char *pathname, struct stat *buf); // local file info |
|||
char *strerror(int errnum); // explanation of error |
|||
char *basename(char *path); // filename at end of path |
|||
// STL classes and functions used |
|||
namespace stl |
|||
{ |
|||
using std::cout; // stdout |
|||
using std::cerr; // stderr |
|||
using std::string; // string |
|||
using std::ifstream; // files on disk |
|||
using std::remove; // delete file on disk |
|||
}; |
|||
using namespace stl; |
|||
// connection modes |
|||
using Mode = ftp::Connection::Mode; |
|||
Mode PASV = Mode::PASSIVE; |
|||
Mode PORT = Mode::PORT; |
|||
//file transfer modes |
|||
using TransferMode = ftp::Connection::TransferMode; |
|||
TransferMode BINARY = TransferMode::BINARY; |
|||
TransferMode TEXT = TransferMode::TEXT; |
|||
/* ********************** */ |
|||
// ftp session parameters |
|||
struct session |
|||
{ |
|||
const string server; // server name |
|||
const string port; // usually 21 |
|||
const string user; // username |
|||
const string pass; // password |
|||
Mode mode; // PASV, PORT |
|||
TransferMode txmode; // BINARY, TEXT |
|||
string dir; // current or default dir |
|||
}; |
|||
/* ********************** */ |
|||
// local helper functions |
|||
ftp::Connection connect_ftp( const session& sess); |
|||
size_t get_ftp( ftp::Connection& conn, string const& path); |
|||
string readFile( const string& filename); |
|||
string login_ftp(ftp::Connection& conn, const session& sess); |
|||
string dir_listing( ftp::Connection& conn, const string& path); |
|||
/* ******************************** */ |
|||
// Read a file into one long string |
|||
string readFile( const string& filename) |
|||
{ |
|||
struct stat stat_buf; |
|||
string contents; |
|||
errno = 0; |
|||
if (stat(filename.c_str() , &stat_buf) != -1) // file stats |
|||
{ |
|||
size_t len = stat_buf.st_size; // size of file |
|||
string bytes(len+1, '\0'); // string big enough |
|||
ifstream ifs(filename); // open for input |
|||
ifs.read(&bytes[0], len); // read all bytes as chars into string |
|||
if (! ifs.fail() ) contents.swap(bytes); // swap into contents |
|||
ifs.close(); |
|||
} |
|||
else |
|||
{ |
|||
cerr << "stat error: " << strerror(errno); |
|||
} |
|||
return contents; |
|||
} |
|||
/* *************** */ |
|||
// start a session |
|||
ftp::Connection connect_ftp( const session& sess) |
|||
try |
|||
{ |
|||
string constr = sess.server + ":" + sess.port; |
|||
cerr << "connecting to " << constr << " ...\n"; |
|||
ftp::Connection conn{ constr.c_str() }; |
|||
cerr << "connected to " << constr << "\n"; |
|||
conn.setConnectionMode(sess.mode); |
|||
return conn; |
|||
} |
|||
catch (ftp::ConnectException e) |
|||
{ |
|||
cerr << "FTP error: could not connect to server" << "\n"; |
|||
} |
|||
/* ***** */ |
|||
// login |
|||
string login_ftp(ftp::Connection& conn, const session& sess) |
|||
{ |
|||
conn.login(sess.user.c_str() , sess.pass.c_str() ); |
|||
return conn.getLastResponse(); |
|||
} |
|||
/* ***************************** */ |
|||
// get remote directory listing |
|||
// ftplib writes to file for dir contents |
|||
// convert file contents to string |
|||
string dir_listing( ftp::Connection& conn, const string& path) |
|||
try |
|||
{ |
|||
// file on disk to write to |
|||
const char* dirdata = "/dev/shm/dirdata"; |
|||
conn.getList(dirdata, path.c_str() ); |
|||
// conn.getFullList(dirdata, path.c_str() ); |
|||
// conn.getFullList(NULL, path.c_str() ); // to stdout |
|||
string dir_string = readFile(dirdata); |
|||
cerr << conn.getLastResponse() << "\n"; |
|||
errno = 0; |
|||
if ( remove(dirdata) != 0 ) // delete file on disk |
|||
{ |
|||
cerr << "error: " << strerror(errno) << "\n"; |
|||
} |
|||
return dir_string; |
|||
} |
|||
catch (...) { |
|||
cerr << "error: getting dir contents: \n" |
|||
<< strerror(errno) << "\n"; |
|||
} |
|||
/* ************************* */ |
|||
// retrieve file from server |
|||
size_t get_ftp( ftp::Connection& conn, const string& r_path) |
|||
{ |
|||
size_t received = 0; |
|||
const char* path = r_path.c_str(); |
|||
unsigned remotefile_size = conn.size(path , BINARY); |
|||
const char* localfile = basename(path); |
|||
conn.get(localfile, path, BINARY); // get file |
|||
cerr << conn.getLastResponse() << "\n"; |
|||
// get local file size |
|||
struct stat stat_buf; |
|||
errno = 0; |
|||
if (stat(localfile, &stat_buf) != -1) |
|||
received = stat_buf.st_size; |
|||
else |
|||
cerr << strerror(errno); |
|||
return received; |
|||
} |
|||
/* ******************** */ |
|||
// default test session |
|||
const session sonic |
|||
{ |
|||
"mirrors.sonic.net", |
|||
"21" , |
|||
"anonymous", |
|||
"xxxx@nohost.org", |
|||
PASV, |
|||
BINARY, |
|||
"/pub/OpenBSD" |
|||
}; |
|||
/* **** */ |
|||
// main |
|||
int main(int argc, char* argv[], char * env[] ) |
|||
{ |
|||
const session remote = sonic; // copy session info |
|||
try |
|||
{ |
|||
// open an ftp connection |
|||
ftp::Connection conn = connect_ftp(remote); |
|||
// login with username and passwd |
|||
cerr << login_ftp(conn, remote); |
|||
// what type system |
|||
cout << "System type: " << conn.getSystemType() << "\n"; |
|||
cerr << conn.getLastResponse() << "\n"; |
|||
// cd to default session dir |
|||
conn.cd(remote.dir.c_str()); // change to dir on server |
|||
cerr << conn.getLastResponse() << "\n"; |
|||
// get current remote directory |
|||
string pwdstr = conn.getDirectory(); |
|||
cout << "PWD: " << pwdstr << "\n"; |
|||
cerr << conn.getLastResponse() << "\n"; |
|||
// get file listing |
|||
string dirlist = dir_listing(conn, pwdstr.c_str() ); |
|||
cout << dirlist << "\n"; |
|||
string filename = "ftplist"; // small text file |
|||
auto pos = dirlist.find(filename); // find filename in dir list |
|||
auto notfound = string::npos; |
|||
if (pos != notfound) // found filename |
|||
{ |
|||
// get file |
|||
size_t received = get_ftp(conn, filename.c_str() ); |
|||
if (received == 0) |
|||
cerr << "got 0 bytes\n"; |
|||
else |
|||
cerr << "got " << filename |
|||
<< " (" << received << " bytes)\n"; |
|||
} |
|||
else |
|||
{ |
|||
cerr << "file " << filename |
|||
<< "not found on server. \n"; |
|||
} |
|||
} |
|||
catch (ftp::ConnectException e) |
|||
{ |
|||
cerr << "FTP error: could not connect to server" << "\n"; |
|||
} |
|||
catch (ftp::Exception e) |
|||
{ |
|||
cerr << "FTP error: " << e << "\n"; |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "error: " << strerror(errno) << "\n"; |
|||
} |
|||
// logout, connection closes automatically when conn destructs |
|||
return 0; |
|||
} |
|||
/* END */ |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
connecting to mirrors.sonic.net:21 ... |
|||
connected to mirrors.sonic.net:21 |
|||
230 Anonymous access granted, restrictions apply |
|||
System type: UNIX |
|||
215 UNIX Type: L8 |
|||
250 CWD command successful |
|||
PWD: /openbsd |
|||
257 "/openbsd" is the current directory |
|||
226 Transfer complete |
|||
/openbsd/. |
|||
/openbsd/.. |
|||
/openbsd/Changelogs |
|||
/openbsd/LibreSSL |
|||
/openbsd/OpenBGPD |
|||
/openbsd/OpenNTPD |
|||
/openbsd/OpenSSH |
|||
/openbsd/doc |
|||
/openbsd/patches |
|||
/openbsd/snapshots |
|||
/openbsd/songs |
|||
/openbsd/syspatch |
|||
/openbsd/tools |
|||
/openbsd/ftplist |
|||
/openbsd/timestamp |
|||
/openbsd/rpki-client |
|||
/openbsd/6.7 |
|||
/openbsd/6.8 |
|||
226 Transfer complete |
|||
got ftplist (4992 bytes) |
|||
</pre> |
|||
=={{header|Common Lisp}}== |
|||
Using package [http://code.kepibu.org/cl-ftp/ cl-ftp]. |
|||
<syntaxhighlight lang="lisp">(use-package :ftp) |
|||
(with-ftp-connection (conn :hostname "ftp.hq.nasa.gov" |
|||
:passive-ftp-p t) |
|||
(send-cwd-command conn "/pub/issoutreach/Living in Space Stories (MP3 Files)") |
|||
(send-list-command conn t) |
|||
(let ((filename "Gravity in the Brain.mp3")) |
|||
(retrieve-file conn filename filename :type :binary))) |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
-rw-rw-r-- 1 109 space-station 2327118 May 9 2005 09sept_spacepropulsion.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1260304 May 9 2005 Can People go to Mars.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1350270 May 9 2005 Distill some water.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1290888 May 9 2005 Good Vibrations.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1431834 May 9 2005 Gravity Hurts_So good.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1072644 May 9 2005 Gravity in the Brain.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1230594 May 9 2005 Power to the ISS.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1309062 May 9 2005 Space Bones.mp3 |
|||
-rw-rw-r-- 1 109 space-station 2292715 May 9 2005 Space Power.mp3 |
|||
-rw-rw-r-- 1 109 space-station 772075 May 9 2005 We have a solution.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1134654 May 9 2005 When Space Makes you Dizzy.mp3 |
|||
</pre> |
|||
=={{header|Erlang}}== |
|||
Erlang implementation using ftp module. |
|||
<syntaxhighlight lang="erlang"> |
|||
%%%------------------------------------------------------------------- |
|||
%%% To execute in shell, Run the following commands:- |
|||
%%% >c("ftp_example"). |
|||
%%% >ftp_example:run(). |
|||
%%%------------------------------------------------------------------- |
|||
-module(ftp_example). |
|||
-export([run/0]). |
|||
run() -> |
|||
Host = "ftp.easynet.fr", |
|||
Opts = [{mode, passive}], |
|||
User = "anonymous", |
|||
Password = "", |
|||
Directory = "/debian/", |
|||
File = "README.html", |
|||
%%% Open connection with FTP Server |
|||
io:format("Opening connection with host ~p ~n", [Host]), |
|||
{ok, Pid} = ftp:open(Host, Opts), |
|||
%%% Login as Anonymous user |
|||
io:format("Logging in as user ~p ~n", [User]), |
|||
ftp:user(Pid, User, Password), |
|||
%%% Change Directory to "/debian/" |
|||
io:format("Changing Directory to ~p ~n", [Directory]), |
|||
ftp:cd(Pid, Directory), |
|||
%%% Listing contents of current Directory |
|||
io:format("Contents of Current Directory ~n"), |
|||
{ok, Listing} = ftp:ls(Pid), |
|||
io:format("~p ~n", [Listing]), |
|||
%%% Download file "README.html" |
|||
io:format("Downloading File ~p to current directory ~n", [File]), |
|||
ftp:recv(Pid, File), |
|||
%%% Close connection |
|||
io:format("Closing connection to FTP Server"), |
|||
ftp:close(Pid). |
|||
</syntaxhighlight> |
|||
=={{header|Groovy}}== |
|||
This is the code from [https://gist.github.com/ran488/1135043 Ran488 GitHub], modified to be executable. |
|||
It relies on external Apache FTP client. |
|||
Dependencies are automatically loaded with the @Grab annotation. |
|||
let's say the code is saved in the file ftpTest.groovy: |
|||
<syntaxhighlight lang="groovy"> |
|||
@Grab(group='commons-net', module='commons-net', version='2.0') |
|||
import org.apache.commons.net.ftp.FTPClient |
|||
println("About to connect...."); |
|||
new FTPClient().with { |
|||
connect "ftp.easynet.fr" |
|||
enterLocalPassiveMode() |
|||
login "anonymous", "ftptest@example.com" |
|||
changeWorkingDirectory "/debian/" |
|||
def incomingFile = new File("README.html") |
|||
incomingFile.withOutputStream { ostream -> retrieveFile "README.html", ostream } |
|||
disconnect() |
|||
} |
|||
println(" ...Done."); |
|||
</syntaxhighlight> |
|||
By typing groovy ftpTest.groovy, you should see a README.html file on your directory. |
|||
<pre> |
|||
Debian Archive |
|||
See http://www.debian.org/ for information about Debian GNU/Linux. |
|||
Current Releases |
|||
Four Debian releases are available on the main site: |
|||
Debian 6.0.10, or squeeze |
|||
Debian 6.0.10 was released Saturday, 19th July 2014. Please note that the 6.0 distribution is no longer receiving security support. If you are using the amd64 or i386 architecture and not able to upgrade to the current stable release, you may wish to investigate the "squeeze-lts" distribution. Installation and upgrading instructions, More information |
|||
.... |
|||
... |
|||
</pre> |
|||
=={{header|Haskell}}== |
|||
Example uses [https://hackage.haskell.org/package/ftphs <tt>ftphs</tt>] package: |
|||
<syntaxhighlight lang="haskell">module Main (main) where |
|||
import Control.Exception (bracket) |
|||
import Control.Monad (void) |
|||
import Data.Foldable (for_) |
|||
import Network.FTP.Client |
|||
( cwd |
|||
, easyConnectFTP |
|||
, getbinary |
|||
, loginAnon |
|||
, nlst |
|||
, quit |
|||
, setPassive |
|||
) |
|||
main :: IO () |
|||
main = bracket ((flip setPassive) True <$> easyConnectFTP "ftp.kernel.org") quit $ \h -> do |
|||
-- Log in anonymously |
|||
void $ loginAnon h |
|||
-- Change directory |
|||
void $ cwd h "/pub/linux/kernel/Historic" |
|||
-- List current directory |
|||
fileNames <- nlst h Nothing |
|||
for_ fileNames $ \fileName -> |
|||
putStrLn fileName |
|||
-- Download in binary mode |
|||
(fileData, _) <- getbinary h "linux-0.01.tar.gz.sign" |
|||
print fileData</syntaxhighlight> |
|||
=={{header|J}}== |
|||
<syntaxhighlight lang="j"> require 'web/gethttp' |
|||
gethttp 'ftp://anonymous:example@ftp.hq.nasa.gov/pub/issoutreach/Living%20in%20Space%20Stories%20(MP3%20Files)/' |
|||
-rw-rw-r-- 1 109 space-station 2327118 May 9 2005 09sept_spacepropulsion.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1260304 May 9 2005 Can People go to Mars.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1350270 May 9 2005 Distill some water.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1290888 May 9 2005 Good Vibrations.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1431834 May 9 2005 Gravity Hurts_So good.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1072644 May 9 2005 Gravity in the Brain.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1230594 May 9 2005 Power to the ISS.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1309062 May 9 2005 Space Bones.mp3 |
|||
-rw-rw-r-- 1 109 space-station 2292715 May 9 2005 Space Power.mp3 |
|||
-rw-rw-r-- 1 109 space-station 772075 May 9 2005 We have a solution.mp3 |
|||
-rw-rw-r-- 1 109 space-station 1134654 May 9 2005 When Space Makes you Dizzy.mp3 |
|||
#file=: gethttp rplc&(' ';'%20') 'ftp://anonymous:example@ftp.hq.nasa.gov/pub/issoutreach/Living in Space Stories (MP3 Files)/We have a solution.mp3' |
|||
772075</syntaxhighlight> |
|||
=={{header|Java}}== |
=={{header|Java}}== |
||
requires apache.commons.net |
requires apache.commons.net |
||
< |
<syntaxhighlight lang="java">import java.io.FileOutputStream; |
||
import java.io.IOException; |
import java.io.IOException; |
||
import java.io.OutputStream; |
import java.io.OutputStream; |
||
Line 142: | Line 1,206: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
Line 187: | Line 1,251: | ||
226 Transfer complete</pre> |
226 Transfer complete</pre> |
||
=={{header| |
=={{header|Julia}}== |
||
{{works with|Julia|0.6}} |
|||
<lang Python> |
|||
<syntaxhighlight lang="julia">using FTPClient |
|||
ftp = FTP(hostname = "ftp.ed.ac.uk", username = "anonymous") |
|||
cd(ftp, "pub/courses") |
|||
println(readdir(ftp)) |
|||
bytes = read(download(ftp, "make.notes.tar")) |
|||
close(ftp)</syntaxhighlight> |
|||
=={{header|Kotlin}}== |
|||
{{trans|C}} |
|||
{{libheader|ftplib}} |
|||
{{works with|Ubuntu 14.04}} |
|||
Assuming that ftplib is already installed on your system in the default location(s), you first need to build ftplib.klib using the following .def file and the cinterop tool. As the NetBuf struct is not defined in ftplib.h (but is in ftplib.c) it has been included in the .def file so that the tool can deal with it (and its alias 'netbuf') properly from a Kotlin perspective. |
|||
<pre> |
|||
headers = /usr/include/ftplib.h |
|||
linkerOpts.linux = -L/usr/lib -lftp |
|||
--- |
|||
#include <sys/time.h> |
|||
struct NetBuf { |
|||
char *cput,*cget; |
|||
int handle; |
|||
int cavail,cleft; |
|||
char *buf; |
|||
int dir; |
|||
netbuf *ctrl; |
|||
netbuf *data; |
|||
int cmode; |
|||
struct timeval idletime; |
|||
FtpCallback idlecb; |
|||
void *idlearg; |
|||
int xfered; |
|||
int cbbytes; |
|||
int xfered1; |
|||
char response[256]; |
|||
}; |
|||
</pre> |
|||
Next, you need to compile the following Kotlin program, linking against ftplib.klib. |
|||
<syntaxhighlight lang="scala">// Kotlin Native v0.6 |
|||
import kotlinx.cinterop.* |
|||
import ftplib.* |
|||
fun main(args: Array<String>) { |
|||
val nbuf = nativeHeap.allocPointerTo<netbuf>() |
|||
FtpInit() |
|||
FtpConnect("ftp.easynet.fr", nbuf.ptr) |
|||
val vnbuf = nbuf.value |
|||
FtpLogin("anonymous", "ftptest@example.com", vnbuf) |
|||
FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE.toLong(), vnbuf) |
|||
FtpChdir("/debian/", vnbuf) |
|||
FtpDir(null, ".", vnbuf) |
|||
FtpGet("ftp.README", "README.html", FTPLIB_ASCII.toByte(), vnbuf) |
|||
FtpQuit(vnbuf) |
|||
nativeHeap.free(nbuf) |
|||
}</syntaxhighlight> |
|||
Finally, the resulting .kexe file should be executed producing something similar to the following output: |
|||
<pre> |
|||
drwxr-xr-x 23 1002 1002 4096 Dec 9 09:44 dists |
|||
drwxr-xr-x 4 1002 1002 4096 Mar 3 19:52 doc |
|||
-rw-r--r-- 1 1002 1002 361654 Mar 3 20:49 extrafiles |
|||
drwxr-xr-x 3 1002 1002 4096 Mar 3 20:42 indices |
|||
-rw-r--r-- 1 1002 1002 14948661 Mar 3 20:42 ls-lR.gz |
|||
drwxr-xr-x 5 1002 1002 4096 Dec 19 2000 pool |
|||
drwxr-xr-x 4 1002 1002 4096 Nov 17 2008 project |
|||
-rw-r--r-- 1 1002 1002 1186 Dec 9 09:42 README |
|||
-rw-r--r-- 1 1002 1002 1290 Jun 26 2010 README.CD-manufacture |
|||
-rw-r--r-- 1 1002 1002 2903 Dec 9 09:42 README.html |
|||
-rw-r--r-- 1 1002 1002 291 Mar 4 2017 README.mirrors.html |
|||
-rw-r--r-- 1 1002 1002 86 Mar 4 2017 README.mirrors.txt |
|||
drwxr-xr-x 3 1002 1002 4096 Oct 10 2012 tools |
|||
drwxr-xr-x 23 1002 1002 4096 Jun 17 2017 zzz-dists |
|||
</pre> |
|||
=={{header|Lingo}}== |
|||
{{libheader|Curl Xtra}} |
|||
<syntaxhighlight lang="lingo">CURLOPT_URL = 10002 |
|||
ch = xtra("Curl").new() |
|||
url = "ftp://domain.com" |
|||
-- change to remote dir "/foo/bar/" |
|||
put "/foo/bar/" after url |
|||
ch.setOption(CURLOPT_URL, url) |
|||
res = ch.exec(1) |
|||
-- print raw FTP listing as string |
|||
put res.readRawString(res.length) |
|||
-- download file "download.mp3" (passive mode is the internal default behavior) |
|||
filename = "download.mp3" |
|||
ch.setOption(CURLOPT_URL, url & filename) |
|||
ch.setDestinationFile(_movie.path & filename) |
|||
res = ch.exec()</syntaxhighlight> |
|||
=={{header|LiveCode}}== |
|||
<syntaxhighlight lang="livecode">libURLSetFTPMode "passive" --default is passive anyway |
|||
put url "ftp://ftp.hq.nasa.gov/" into listing |
|||
repeat for each line ftpln in listing |
|||
set itemdel to space |
|||
if the first char of (the first item of ftpln) is "d" then |
|||
-- is a directory |
|||
put the last item of ftpln after dirlist |
|||
else |
|||
put the last item of ftpln after filelist |
|||
end if |
|||
end repeat |
|||
put listing //(subset) |
|||
// -rw-r--r-- 1 ftpadmin ftp-adm 3997 May 26 1998 README |
|||
// drwxrwsr-x 17 ftpadmin ftp-adm 4096 Sep 10 16:08 pub |
|||
put dirlist |
|||
// armd |
|||
// chmgt |
|||
// incoming |
|||
// lost+found |
|||
// office |
|||
// pub |
|||
put filelist |
|||
// README |
|||
// ftp-exec |
|||
// index.html |
|||
// robots.txt |
|||
-- downloading a file (upload is same, but use put) |
|||
-- you don't have to cd manually |
|||
-- file up/down transfer is binary in livecode (always enforced by livecode) |
|||
put URL "ftp://ftp.hq.nasa.gov/pub/robots.txt" into URL "file:myFile.txt" |
|||
You can execute any ftp command using the libURLftpCommand command |
|||
e.g. to know the working directory, issue "pwd", we could issue "list" for above too, |
|||
but using an url with slash on the end with the ftp protocol causes a dir listing by default. |
|||
put libURLftpCommand("PWD",ftp.example.org)</syntaxhighlight> |
|||
=={{header|Nim}}== |
|||
{{works with|Nim|1.4}} |
|||
<syntaxhighlight lang="nim">import asyncdispatch, asyncftpclient |
|||
const |
|||
Host = "speedtest.tele2.net" |
|||
Upload = "upload" |
|||
File = "1KB.zip" |
|||
proc main {.async.} = |
|||
# Create session and connect. |
|||
let ftp = newAsyncFtpClient(Host, user = "anonymous", pass = "anything") |
|||
await ftp.connect() |
|||
echo "Connected." |
|||
echo await ftp.send("PASV") # Switch to passive mode. |
|||
# Change directory and list its contents. |
|||
await ftp.cd(Upload) |
|||
echo "Changed to directory: ", Upload |
|||
echo "Contents of directory: ", Upload |
|||
for file in await ftp.listDirs(): |
|||
echo " ", file |
|||
# Download a file. |
|||
await ftp.cd("/") |
|||
echo "Returned to root directory." |
|||
await ftp.retrFile(file = File, dest = File) |
|||
echo "Downloaded file: ", File |
|||
echo await ftp.send("QUIT") # Disconnect. |
|||
waitFor main()</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Connected. |
|||
227 Entering Passive Mode (90,130,70,73,94,108). |
|||
Changed to directory: upload |
|||
Contents of directory: upload |
|||
1_2758858854070946631_17-9ULspeedtest.upt |
|||
2MB.zip |
|||
2_2758858854070946631_17-9ULspeedtest.upt |
|||
3_2758858854070946631_17-9ULspeedtest.upt |
|||
DCS-932LB1-WEBCAM-12021010316232001.jpg |
|||
DCS-932LB1-WEBCAM-12021010316292601.jpg |
|||
DCS-932LB1-WEBCAM-12021010316314601.jpg |
|||
speedtest_uplink_1.1G.zip |
|||
upload_file.txt |
|||
Returned to root directory. |
|||
Downloaded file: 1KB.zip |
|||
221 Goodbye.</pre> |
|||
=={{header|Perl}}== |
|||
<syntaxhighlight lang="perl">use Net::FTP; |
|||
# set server and credentials |
|||
my $host = 'speedtest.tele2.net'; |
|||
my $user = 'anonymous'; |
|||
my $password = ''; |
|||
# connect in passive mode |
|||
my $f = Net::FTP->new($host) or die "Can't open $host\n"; |
|||
$f->login($user, $password) or die "Can't login as $user\n"; |
|||
$f->passive(); |
|||
# change remote directory, list contents |
|||
$f->cwd('upload'); |
|||
@files = $f->ls(); |
|||
printf "Currently %d files in the 'upload' directory.\n", @files; |
|||
# download file in binary mode |
|||
$f->cwd('/'); |
|||
$f->type('binary'); |
|||
$local = $f->get('512KB.zip'); |
|||
print "Your file was stored as $local in the current directory\n";</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Currently 20 files in the 'upload' directory |
|||
Your file was stored as 512KB.zip in the current directory!</pre> |
|||
=={{header|Phix}}== |
|||
{{libheader|Phix/libcurl}} |
|||
<!--<syntaxhighlight lang="phix">(notonline)--> |
|||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- libcurl, allocate, file i/o</span> |
|||
<span style="color: #008080;">include</span> <span style="color: #000000;">libcurl</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">url</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"ftp://speedtest.tele2.net/"</span> |
|||
<span style="color: #7060A8;">curl_global_init</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">curl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">curl_easy_init</span><span style="color: #0000FF;">(),</span> |
|||
<span style="color: #000000;">pErrorBuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">CURL_ERROR_SIZE</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CURLOPT_ERRORBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pErrorBuffer</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CURLOPT_URL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">url</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">object</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">curl_easy_perform_ex</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #0000FF;">?{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">peek_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pErrorBuffer</span><span style="color: #0000FF;">)}</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">filename</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"1KB.zip"</span> |
|||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">delete_file</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">curl_easy_get_file</span><span style="color: #0000FF;">(</span><span style="color: #000000;">url</span><span style="color: #0000FF;">&</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #004600;">CURLE_OK</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"successfully downloaded %s (size %s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">get_file_size</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)})</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #0000FF;">?{</span><span style="color: #008000;">"error"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
-rw-r--r-- 1 0 0 1073741824000 Feb 19 2016 1000GB.zip |
|||
-rw-r--r-- 1 0 0 107374182400 Feb 19 2016 100GB.zip |
|||
-rw-r--r-- 1 0 0 102400 Feb 19 2016 100KB.zip |
|||
-rw-r--r-- 1 0 0 104857600 Feb 19 2016 100MB.zip |
|||
-rw-r--r-- 1 0 0 10737418240 Feb 19 2016 10GB.zip |
|||
-rw-r--r-- 1 0 0 10485760 Feb 19 2016 10MB.zip |
|||
-rw-r--r-- 1 0 0 1073741824 Feb 19 2016 1GB.zip |
|||
-rw-r--r-- 1 0 0 1024 Feb 19 2016 1KB.zip |
|||
-rw-r--r-- 1 0 0 1048576 Feb 19 2016 1MB.zip |
|||
-rw-r--r-- 1 0 0 209715200 Feb 19 2016 200MB.zip |
|||
-rw-r--r-- 1 0 0 20971520 Feb 19 2016 20MB.zip |
|||
-rw-r--r-- 1 0 0 2097152 Feb 19 2016 2MB.zip |
|||
-rw-r--r-- 1 0 0 3145728 Feb 19 2016 3MB.zip |
|||
-rw-r--r-- 1 0 0 524288000 Feb 19 2016 500MB.zip |
|||
-rw-r--r-- 1 0 0 52428800 Feb 19 2016 50MB.zip |
|||
-rw-r--r-- 1 0 0 524288 Feb 19 2016 512KB.zip |
|||
-rw-r--r-- 1 0 0 5242880 Feb 19 2016 5MB.zip |
|||
drwxr-xr-x 2 105 108 561152 Jul 18 13:11 upload |
|||
successfully downloaded 1KB.zip (size 1KB) |
|||
</pre> |
|||
=={{header|PHP}}== |
|||
<syntaxhighlight lang="php"> |
|||
$server = "speedtest.tele2.net"; |
|||
$user = "anonymous"; |
|||
$pass = "ftptest@example.com"; |
|||
$conn = ftp_connect($server); |
|||
if (!$conn) { |
|||
die('unable to connect to: '. $server); |
|||
} |
|||
$login = ftp_login($conn, $user, $pass); |
|||
if (!$login) { |
|||
echo 'unable to log in to '. $server. ' with user: '.$user.' and pass: '. $pass; |
|||
} else{ |
|||
echo 'connected successfully'.PHP_EOL; |
|||
$directory = ftp_nlist($conn,''); |
|||
print_r($directory); |
|||
} |
|||
if (ftp_get($conn, '1KB.zip', '1KB.zip', FTP_BINARY)) { |
|||
echo "Successfully downloaded file".PHP_EOL; |
|||
} else { |
|||
echo "failed to download file"; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
connected successfully |
|||
Array |
|||
( |
|||
[0] => 1000GB.zip |
|||
[1] => 100GB.zip |
|||
[2] => 100KB.zip |
|||
[3] => 100MB.zip |
|||
[4] => 10GB.zip |
|||
[5] => 10MB.zip |
|||
[6] => 1GB.zip |
|||
[7] => 1KB.zip |
|||
[8] => 1MB.zip |
|||
[9] => 200MB.zip |
|||
[10] => 20MB.zip |
|||
[11] => 2MB.zip |
|||
[12] => 3MB.zip |
|||
[13] => 500MB.zip |
|||
[14] => 50MB.zip |
|||
[15] => 512KB.zip |
|||
[16] => 5MB.zip |
|||
[17] => upload |
|||
) |
|||
Successfully downloaded file |
|||
Done. |
|||
</pre> |
|||
=={{header|PicoLisp}}== |
|||
Passive is the default behavior of 'curl' |
|||
<syntaxhighlight lang="picolisp">(in '(curl "-sl" "ftp://kernel.org/pub/site/") |
|||
(while (line) |
|||
(prinl @) ) ) |
|||
(call "curl" "-s" "-o" "sha256sums.asc" "ftp://kernel.org/pub/site/sha256sums.asc")</syntaxhighlight> |
|||
Output: |
|||
<pre>README |
|||
sample_mirror_script.pl |
|||
sha256sums.asc</pre> |
|||
=={{header|Python}}== |
|||
{{works with|Python|2.7.10}} |
|||
<syntaxhighlight lang="python"> |
|||
from ftplib import FTP |
from ftplib import FTP |
||
ftp = FTP('kernel.org') |
ftp = FTP('kernel.org') |
||
Line 197: | Line 1,599: | ||
print ftp.retrbinary('RETR README', open('README', 'wb').write) |
print ftp.retrbinary('RETR README', open('README', 'wb').write) |
||
ftp.quit() |
ftp.quit() |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
Note: <tt>net/ftp</tt> in Racket uses passive mode exclusively. |
Note: <tt>net/ftp</tt> in Racket uses passive mode exclusively. |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket |
#lang racket |
||
(require net/ftp) |
(require net/ftp) |
||
Line 217: | Line 1,619: | ||
(ftp-download-file conn "." "README") |
(ftp-download-file conn "." "README") |
||
(ftp-close-connection conn)) |
(ftp-close-connection conn)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|rakudo|2018.04}} |
|||
<syntaxhighlight lang="raku" line>use Net::FTP; |
|||
my $host = 'speedtest.tele2.net'; |
|||
my $user = 'anonymous'; |
|||
my $password = ''; |
|||
my $ftp = Net::FTP.new( host => $host, :passive ); |
|||
$ftp.login( user => $user, pass => $password ); |
|||
$ftp.cwd( 'upload' ); |
|||
$ftp.cwd( '/' ); |
|||
say $_<name> for $ftp.ls; |
|||
$ftp.get( '1KB.zip', :binary );</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1000GB.zip |
|||
100GB.zip |
|||
100KB.zip |
|||
100MB.zip |
|||
10GB.zip |
|||
10MB.zip |
|||
1GB.zip |
|||
1KB.zip |
|||
1MB.zip |
|||
200MB.zip |
|||
20MB.zip |
|||
2MB.zip |
|||
3MB.zip |
|||
500MB.zip |
|||
50MB.zip |
|||
512KB.zip |
|||
5MB.zip |
|||
upload</pre> |
|||
=={{header|REBOL}}== |
=={{header|REBOL}}== |
||
<syntaxhighlight lang="rebol"> |
|||
<lang REBOL> |
|||
system/schemes/ftp/passive: on |
system/schemes/ftp/passive: on |
||
print read ftp://kernel.org/pub/linux/kernel/ |
print read ftp://kernel.org/pub/linux/kernel/ |
||
write/binary %README read/binary ftp://kernel.org/pub/linux/kernel/README |
write/binary %README read/binary ftp://kernel.org/pub/linux/kernel/README |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
< |
<syntaxhighlight lang="ruby">require 'net/ftp' |
||
Net::FTP.open('ftp.ed.ac.uk', "anonymous","aaa@gmail.com" ) do |ftp| |
Net::FTP.open('ftp.ed.ac.uk', "anonymous","aaa@gmail.com" ) do |ftp| |
||
ftp.passive = true |
ftp.passive = true # default since Ruby 2.3 |
||
ftp.chdir('pub/courses') |
ftp.chdir('pub/courses') |
||
ftp.list |
puts ftp.list |
||
ftp.getbinaryfile("make.notes.tar") |
ftp.getbinaryfile("make.notes.tar") |
||
end</ |
end</syntaxhighlight> |
||
The connection is closed automatically at |
The connection is closed automatically at the end of the block. |
||
=={{header|Rust}}== |
|||
Using crate <code>ftp</code> version 3.0.1 |
|||
<syntaxhighlight lang="rust">use std::{error::Error, fs::File, io::copy}; |
|||
use ftp::FtpStream; |
|||
fn main() -> Result<(), Box<dyn Error>> { |
|||
let mut ftp = FtpStream::connect("ftp.easynet.fr:21")?; |
|||
ftp.login("anonymous", "")?; |
|||
ftp.cwd("debian")?; |
|||
for file in ftp.list(None)? { |
|||
println!("{}", file); |
|||
} |
|||
let mut stream = ftp.get("README")?; |
|||
let mut file = File::create("README")?; |
|||
copy(&mut stream, &mut file)?; |
|||
Ok(()) |
|||
}</syntaxhighlight> |
|||
=={{header|Scala}}== |
|||
{{libheader|commons-net}} |
|||
<syntaxhighlight lang="scala">import java.io.{File, FileOutputStream, InputStream} |
|||
import org.apache.commons.net.ftp.{FTPClient, FTPFile, FTPReply} |
|||
import scala.util.{Failure, Try} |
|||
object FTPconn extends App { |
|||
val (server, pass) = ("ftp.ed.ac.uk", "-ftptest@example.com") |
|||
val (dir, filename, ftpClient) = ("/pub/cartonet/", "readme.txt", new FTPClient()) |
|||
def canConnect(host: String): Boolean = { |
|||
ftpClient.connect(host) |
|||
val connectionWasEstablished = ftpClient.isConnected |
|||
ftpClient.disconnect() |
|||
connectionWasEstablished |
|||
} |
|||
def downloadFileStream(remote: String): InputStream = { |
|||
val stream: InputStream = ftpClient.retrieveFileStream(remote) |
|||
ftpClient.completePendingCommand() |
|||
stream |
|||
} |
|||
def uploadFile(remote: String, input: InputStream): Boolean = ftpClient.storeFile(remote, input) |
|||
if (Try { |
|||
def cwd(path: String): Boolean = ftpClient.changeWorkingDirectory(path) |
|||
def filesInCurrentDirectory: Seq[String] = listFiles().map(_.getName) |
|||
def listFiles(): List[FTPFile] = ftpClient.listFiles.toList |
|||
def downloadFile(remote: String): Boolean = { |
|||
val os = new FileOutputStream(new File(remote)) |
|||
ftpClient.retrieveFile(remote, os) |
|||
} |
|||
def connectWithAuth(host: String, |
|||
password: String, |
|||
username: String = "anonymous", |
|||
port: Int = 21): Try[Boolean] = { |
|||
def connect(): Try[Unit] = Try { |
|||
try { |
|||
ftpClient.connect(host, port) |
|||
} catch { |
|||
case ex: Throwable => |
|||
println(ex.getMessage) |
|||
Failure |
|||
} |
|||
ftpClient.enterLocalPassiveMode() |
|||
serverReply(ftpClient) |
|||
val replyCode = ftpClient.getReplyCode |
|||
if (!FTPReply.isPositiveCompletion(replyCode)) |
|||
println("Failure. Server reply code: " + replyCode) |
|||
} |
|||
for { |
|||
connection <- connect() |
|||
login <- Try { |
|||
ftpClient.login(username, password) |
|||
} |
|||
} yield login |
|||
} |
|||
def serverReply(ftpClient: FTPClient): Unit = |
|||
for (reply <- ftpClient.getReplyStrings) println(reply) |
|||
connectWithAuth(server, pass) |
|||
cwd(dir) |
|||
listFiles().foreach(println) |
|||
downloadFile(filename) |
|||
serverReply(ftpClient) |
|||
ftpClient.logout |
|||
}.isFailure) println(s"Failure.") |
|||
}</syntaxhighlight> |
|||
{{Out}}See it in running in your browser by [https://scastie.scala-lang.org/3Lq8ehzIQTCuAOPXWofNLw Scastie (JVM)]. |
|||
=={{header|Seed7}}== |
|||
The library [http://seed7.sourceforge.net/libraries/ftp.htm ftp.s7i] contains functions to |
|||
[http://seed7.sourceforge.net/libraries/ftp.htm#openFtp(in_string) open] and handle an |
|||
[http://seed7.sourceforge.net/libraries/ftp.htm#ftpFileSys ftpFileSys]. |
|||
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i"; |
|||
include "ftp.s7i"; |
|||
const proc: main is func |
|||
local |
|||
var ftpFileSys: ftp is fileSys.value; |
|||
var string: line is ""; |
|||
begin |
|||
ftp := openFtp("kernel.org"); |
|||
setActiveMode(ftp, FALSE); # Passive is the default. |
|||
chdir(ftp, "/pub/linux/kernel"); |
|||
for line range listDir(ftp, ".") do |
|||
writeln(line); |
|||
end for; |
|||
setAsciiTransfer(ftp, FALSE); |
|||
writeln(getFile(ftp, "README")); |
|||
close(ftp); |
|||
end func;</syntaxhighlight> |
|||
=={{header|Sidef}}== |
|||
{{trans|Ruby}} |
|||
<syntaxhighlight lang="ruby">require('Net::FTP'); |
|||
var ftp = %s'Net::FTP'.new('ftp.ed.ac.uk', Passive => 1); |
|||
ftp.login('anonymous','aaa@gmail.com'); |
|||
ftp.cwd('pub/courses'); |
|||
[ftp.dir].each {|line| say line }; |
|||
ftp.binary; # set binary mode |
|||
ftp.get("make.notes.tar"); |
|||
ftp.quit;</syntaxhighlight> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
===Using package ftp=== |
===Using package ftp=== |
||
<syntaxhighlight lang="tcl"> |
|||
<lang Tcl> |
|||
package require ftp |
package require ftp |
||
Line 248: | Line 1,828: | ||
::ftp::Type $conn binary |
::ftp::Type $conn binary |
||
::ftp::Get $conn README README |
::ftp::Get $conn README README |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Using a virtual file system=== |
===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. |
An alternative approach that uses the package [http://sourceforge.net/projects/tclvfs/ TclVFS] to access ftp:// paths as a virtual file system. |
||
< |
<syntaxhighlight lang="tcl"> |
||
package require vfs::urltype |
package require vfs::urltype |
||
vfs::urltype::Mount ftp |
vfs::urltype::Mount ftp |
||
Line 266: | Line 1,846: | ||
} |
} |
||
file copy README [file join $dir README] |
file copy README [file join $dir README] |
||
</syntaxhighlight> |
|||
</lang> |
|||
The file <tt>vfsftpfix.tcl</tt> with the passive mode patch (see http://wiki.tcl.tk/12837): |
The file <tt>vfsftpfix.tcl</tt> with the passive mode patch (see http://wiki.tcl.tk/12837): |
||
< |
<syntaxhighlight lang="tcl"> |
||
# Replace vfs::ftp::Mount to enable vfs::ftp to work in passive |
# Replace vfs::ftp::Mount to enable vfs::ftp to work in passive |
||
# mode and make that the default. |
# mode and make that the default. |
||
Line 320: | Line 1,900: | ||
return $fd |
return $fd |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|UNIX Shell}}== |
|||
Uses sftp which os available on all Linux distress by default. The commands are identical to ftp. This example uses the public free sftp server at test.rebex.net , the credentials are demo/password : |
|||
<syntaxhighlight lang="bash"> |
|||
Aamrun $ sftp demo@test.rebex.net |
|||
Password: |
|||
Connected to test.rebex.net. |
|||
sftp> ls |
|||
pub readme.txt |
|||
sftp> cd pub |
|||
sftp> ls |
|||
example |
|||
sftp> ls example |
|||
example/KeyGenerator.png example/KeyGeneratorSmall.png example/ResumableTransfer.png example/WinFormClient.png example/WinFormClientSmall.png example/imap-console-client.png example/mail-editor.png example/mail-send-winforms.png |
|||
example/mime-explorer.png example/pocketftp.png example/pocketftpSmall.png example/pop3-browser.png example/pop3-console-client.png example/readme.txt example/winceclient.png example/winceclientSmall.png |
|||
sftp> cd example |
|||
sftp> get KeyGenerator.png |
|||
Fetching /pub/example/KeyGenerator.png to KeyGenerator.png |
|||
/pub/example/KeyGenerator.png 100% 36KB 146.4KB/s 00:00 |
|||
sftp> exit |
|||
Aamrun$ |
|||
</syntaxhighlight> |
|||
=={{header|V (Vlang)}}== |
|||
<syntaxhighlight lang="v (vlang)"> |
|||
import net.ftp |
|||
fn main() { |
|||
result := ftp_client_test() or {println('Error: something went wrong') exit(1)} |
|||
println(result) |
|||
} |
|||
fn ftp_client_test() ?[]u8 { |
|||
mut zftp := ftp.new() |
|||
mut blob := []u8{} |
|||
defer { |
|||
zftp.close() or { |
|||
println('Error: failure to close ftp') |
|||
exit(10) |
|||
} |
|||
} |
|||
connect_result := zftp.connect('ftp.redhat.com') or { |
|||
println('Error: failed to connect') |
|||
exit(1) |
|||
} |
|||
login_result := zftp.login('ftp', 'ftp') or { |
|||
println('Error: failed to login') |
|||
exit(2) |
|||
} |
|||
pwd := zftp.pwd() or { |
|||
println('Error: failed to login') |
|||
exit(3) |
|||
} |
|||
if (connect_result == true) && (login_result == true) && (pwd.len > 0) { |
|||
zftp.cd('/') or { |
|||
println('Error: failed to get root directory') |
|||
exit(4) |
|||
} |
|||
} |
|||
dir_list1 := zftp.dir() or { |
|||
println('Error: failed to get directory listing') |
|||
exit(5) |
|||
} |
|||
if dir_list1.len > 0 { |
|||
zftp.cd('/suse/linux/enterprise/11Server/en/SAT-TOOLS/SRPMS/') or { |
|||
println('Error: failed to get directory listing') |
|||
exit(6) |
|||
} |
|||
} |
|||
dir_list2 := zftp.dir() or { |
|||
println('Error: failed to get directory listing') |
|||
exit(7) |
|||
} |
|||
if dir_list2.len > 0 { |
|||
if dir_list2.contains('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') == true { |
|||
blob = zftp.get('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') or { |
|||
println('Error: failed to get directory listing') |
|||
exit(8) |
|||
} |
|||
} |
|||
} |
|||
if blob.len <= 0 { |
|||
println('Error: failed to get data') |
|||
exit(9) |
|||
} |
|||
return blob |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Wren}}== |
|||
{{trans|C}} |
|||
{{libheader|ftplib}} |
|||
An embedded program so we can ask the C host to communicate with ''ftplib'' for us. |
|||
<syntaxhighlight lang="wren">/* FTP.wren */ |
|||
var FTPLIB_CONNMODE = 1 |
|||
var FTPLIB_PASSIVE = 1 |
|||
var FTPLIB_ASCII = 65 // 'A' |
|||
foreign class Ftp { |
|||
foreign static init() |
|||
construct connect(host) {} |
|||
foreign login(user, pass) |
|||
foreign options(opt, val) |
|||
foreign chdir(path) |
|||
foreign dir(outputFile, path) |
|||
foreign get(output, path, mode) |
|||
foreign quit() |
|||
} |
|||
Ftp.init() |
|||
var ftp = Ftp.connect("ftp.easynet.fr") |
|||
ftp.login("anonymous", "ftptest@example.com") |
|||
ftp.options(FTPLIB_CONNMODE, FTPLIB_PASSIVE) |
|||
ftp.chdir("/debian/") |
|||
ftp.dir("", ".") |
|||
ftp.get("ftp.README", "README", FTPLIB_ASCII) |
|||
ftp.quit()</syntaxhighlight> |
|||
<br> |
|||
We now embed this in the following C program, compile and run it. |
|||
<syntaxhighlight lang="c">#include <stdio.h> |
|||
#include <stdio_ext.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <ftplib.h> |
|||
#include "wren.h" |
|||
/* C <=> Wren interface functions */ |
|||
void C_init(WrenVM* vm) { |
|||
FtpInit(); |
|||
} |
|||
void C_ftpAllocate(WrenVM* vm) { |
|||
netbuf *nbuf; |
|||
const char *host = wrenGetSlotString(vm, 1); |
|||
FtpConnect(host, &nbuf); |
|||
netbuf** pnbuf = (netbuf**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(netbuf*)); |
|||
*pnbuf = nbuf; |
|||
} |
|||
void C_login(WrenVM* vm) { |
|||
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0); |
|||
const char *user = wrenGetSlotString(vm, 1); |
|||
const char *pass = wrenGetSlotString(vm, 2); |
|||
FtpLogin(user, pass, nbuf); |
|||
} |
|||
void C_options(WrenVM* vm) { |
|||
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0); |
|||
int opt = (int)wrenGetSlotDouble(vm, 1); |
|||
long val = (long)wrenGetSlotDouble(vm, 2); |
|||
FtpOptions(opt, val, nbuf); |
|||
} |
|||
void C_chdir(WrenVM* vm) { |
|||
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0); |
|||
const char *path = wrenGetSlotString(vm, 1); |
|||
FtpChdir(path, nbuf); |
|||
} |
|||
void C_dir(WrenVM* vm) { |
|||
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0); |
|||
const char *outputFile = wrenGetSlotString(vm, 1); |
|||
if (strlen(outputFile) == 0) outputFile = NULL; |
|||
const char *path = wrenGetSlotString(vm, 2); |
|||
FtpDir(outputFile, path, nbuf); |
|||
} |
|||
void C_get(WrenVM* vm) { |
|||
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0); |
|||
const char *output = wrenGetSlotString(vm, 1); |
|||
if (strlen(output) == 0) output = NULL; |
|||
const char *path = wrenGetSlotString(vm, 2); |
|||
char mode = (char)wrenGetSlotDouble(vm, 3); |
|||
FtpGet(output, path, mode, nbuf); |
|||
} |
|||
void C_quit(WrenVM* vm) { |
|||
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0); |
|||
FtpQuit(nbuf); |
|||
} |
|||
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) { |
|||
WrenForeignClassMethods methods; |
|||
methods.finalize = NULL; |
|||
if (strcmp(module, "main") == 0) { |
|||
if (strcmp(className, "Ftp") == 0) { |
|||
methods.allocate = C_ftpAllocate; |
|||
} |
|||
} |
|||
return methods; |
|||
} |
|||
WrenForeignMethodFn bindForeignMethod( |
|||
WrenVM* vm, |
|||
const char* module, |
|||
const char* className, |
|||
bool isStatic, |
|||
const char* signature) { |
|||
if (strcmp(module, "main") == 0) { |
|||
if (strcmp(className, "Ftp") == 0) { |
|||
if ( isStatic && strcmp(signature, "init()") == 0) return C_init; |
|||
if (!isStatic && strcmp(signature, "login(_,_)") == 0) return C_login; |
|||
if (!isStatic && strcmp(signature, "options(_,_)") == 0) return C_options; |
|||
if (!isStatic && strcmp(signature, "chdir(_)") == 0) return C_chdir; |
|||
if (!isStatic && strcmp(signature, "dir(_,_)") == 0) return C_dir; |
|||
if (!isStatic && strcmp(signature, "get(_,_,_)") == 0) return C_get; |
|||
if (!isStatic && strcmp(signature, "quit()") == 0) return C_quit; |
|||
} |
|||
} |
|||
return NULL; |
|||
} |
|||
static void writeFn(WrenVM* vm, const char* text) { |
|||
printf("%s", text); |
|||
} |
|||
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) { |
|||
switch (errorType) { |
|||
case WREN_ERROR_COMPILE: |
|||
printf("[%s line %d] [Error] %s\n", module, line, msg); |
|||
break; |
|||
case WREN_ERROR_STACK_TRACE: |
|||
printf("[%s line %d] in %s\n", module, line, msg); |
|||
break; |
|||
case WREN_ERROR_RUNTIME: |
|||
printf("[Runtime Error] %s\n", msg); |
|||
break; |
|||
} |
|||
} |
|||
char *readFile(const char *fileName) { |
|||
FILE *f = fopen(fileName, "r"); |
|||
fseek(f, 0, SEEK_END); |
|||
long fsize = ftell(f); |
|||
rewind(f); |
|||
char *script = malloc(fsize + 1); |
|||
fread(script, 1, fsize, f); |
|||
fclose(f); |
|||
script[fsize] = 0; |
|||
return script; |
|||
} |
|||
int main(int argc, char **argv) { |
|||
WrenConfiguration config; |
|||
wrenInitConfiguration(&config); |
|||
config.writeFn = &writeFn; |
|||
config.errorFn = &errorFn; |
|||
config.bindForeignClassFn = &bindForeignClass; |
|||
config.bindForeignMethodFn = &bindForeignMethod; |
|||
WrenVM* vm = wrenNewVM(&config); |
|||
const char* module = "main"; |
|||
const char* fileName = "FTP.wren"; |
|||
char *script = readFile(fileName); |
|||
WrenInterpretResult result = wrenInterpret(vm, module, script); |
|||
switch (result) { |
|||
case WREN_RESULT_COMPILE_ERROR: |
|||
printf("Compile Error!\n"); |
|||
break; |
|||
case WREN_RESULT_RUNTIME_ERROR: |
|||
printf("Runtime Error!\n"); |
|||
break; |
|||
case WREN_RESULT_SUCCESS: |
|||
break; |
|||
} |
|||
wrenFreeVM(vm); |
|||
free(script); |
|||
return 0; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
Sample output: |
|||
<pre> |
|||
drwxr-xr-x 25 1002 1002 4096 Aug 15 06:55 dists |
|||
drwxr-xr-x 4 1002 1002 4096 Sep 27 07:52 doc |
|||
-rw-r--r-- 1 1002 1002 254738 Sep 27 08:21 extrafiles |
|||
drwxr-xr-x 3 1002 1002 4096 Sep 27 08:15 indices |
|||
-rw-r--r-- 1 1002 1002 14538903 Sep 27 08:15 ls-lR.gz |
|||
drwxr-xr-x 5 1002 1002 4096 Dec 19 2000 pool |
|||
drwxr-xr-x 4 1002 1002 4096 Nov 17 2008 project |
|||
-rw-r--r-- 1 1002 1002 1320 Aug 14 09:28 README |
|||
-rw-r--r-- 1 1002 1002 1290 Jun 26 2010 README.CD-manufacture |
|||
-rw-r--r-- 1 1002 1002 3203 Aug 14 09:27 README.html |
|||
-rw-r--r-- 1 1002 1002 291 Mar 4 2017 README.mirrors.html |
|||
-rw-r--r-- 1 1002 1002 86 Mar 4 2017 README.mirrors.txt |
|||
drwxr-xr-x 3 1002 1002 4096 Oct 10 2012 tools |
|||
drwxr-xr-x 26 1002 1002 4096 Aug 14 13:55 zzz-dists |
|||
</pre> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
Using the cURL library, doing this from the REPL. Moving around in the tree isn't supported. |
Using the cURL library, doing this from the REPL. Moving around in the tree isn't supported. |
||
< |
<syntaxhighlight lang="zkl">zkl: var cURL=Import("zklCurl") |
||
zkl: var d=cURL().get("ftp.hq.nasa.gov/pub/issoutreach/Living in Space Stories (MP3 Files)/") |
zkl: var d=cURL().get("ftp.hq.nasa.gov/pub/issoutreach/Living in Space Stories (MP3 Files)/") |
||
L(Data(2,567),1630,23) // downloaded listing, 1630 bytes of header, 23 bytes of trailer |
L(Data(2,567),1630,23) // downloaded listing, 1630 bytes of header, 23 bytes of trailer |
||
Line 335: | Line 2,213: | ||
L(Data(1,136,358),1681,23) |
L(Data(1,136,358),1681,23) |
||
zkl: File("foo.mp3","w").write(d[0][1681,-23]) |
zkl: File("foo.mp3","w").write(d[0][1681,-23]) |
||
1134654 // note that this matches size in listing</ |
1134654 // note that this matches size in listing</syntaxhighlight> |
||
The resulting file foo.mp3 has a nice six minute description of what can happen when returning from space. |
The resulting file foo.mp3 has a nice six minute description of what can happen when returning from space. |
||
{{omit from|PARI/GP}} |
{{omit from|PARI/GP}} |
||
{{omit from|Commodore BASIC}} |
Revision as of 11:20, 6 December 2023
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Connect to a server, change directory, list its contents and download a file as binary using the FTP protocol. Use passive mode if available.
BASIC
BaCon
Using libCURL.
OPTION PARSE FALSE
PRAGMA INCLUDE <curl/curl.h>
PRAGMA LDFLAGS -lcurl
DECLARE easyhandle TYPE CURL*
OPEN "data.txt" FOR WRITING AS download
easyhandle = curl_easy_init()
curl_easy_setopt(easyhandle, CURLOPT_URL, "ftp://localhost/pub/data.txt")
curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, download)
curl_easy_setopt(easyhandle, CURLOPT_USERPWD, "anonymous")
success = curl_easy_perform(easyhandle)
curl_easy_cleanup(easyhandle)
CLOSE FILE download
Full native implementation without dependency to external libraries.
FUNCTION interact$(command$, connection, use_pasv)
LOCAL pasv$, data$, response$
LOCAL port, passive
IF use_pasv THEN
SEND "PASV" & NL$ TO connection
RECEIVE data$ FROM connection
pasv$ = INBETWEEN$(data$, "(", ")")
port = VAL(TOKEN$(pasv$, 5, ","))*256 + VAL(TOKEN$(pasv$, 6, ","))
OPEN "localhost:" & STR$(port) FOR NETWORK AS passive
ENDIF
IF LEN(command$) THEN SEND command$ & NL$ TO connection
WHILE WAIT(connection, 50)
RECEIVE data$ FROM connection
IF LEN(data$) = 0 THEN BREAK
response$ = response$ & data$
WEND
IF use_pasv THEN
WHILE WAIT(passive, 50)
RECEIVE data$ FROM passive
IF LEN(data$) = 0 THEN BREAK
response$ = response$ & data$
WEND
CLOSE NETWORK passive
ENDIF
RETURN response$
ENDFUNC
OPEN "localhost:21" FOR NETWORK AS ftp
PRINT interact$("", ftp, 0)
PRINT interact$("USER anonymous", ftp, 0)
PRINT interact$("PASS ", ftp, 0)
PRINT interact$("CWD pub", ftp, 0)
PRINT interact$("LIST", ftp, 1)
PRINT interact$("TYPE I", ftp, 0)
PRINT interact$("RETR data.txt", ftp, 1)
PRINT interact$("QUIT", ftp, 0)
CLOSE NETWORK ftp
FreeBASIC
Original code programmed by PaulSquires [1]
clsFTP.bas
''
''
'' FTP class (Public Domain code - enjoy).
'' Windows only. Uses WinInet system functions.
'' Paul Squires of PlanetSquires Software (August 2015)
''
'' Compiler: FreeBASIC 1.03 (32-bit) (64-bit)
''
#Include Once "windows.bi"
#Include Once "\win\wininet.bi"
' //
' //
' //
Type clsFTP
Private:
m_hSession As HINTERNET
m_hConnection As HINTERNET
m_LastError As Integer
m_ServerPort As Integer
m_ServerName As String
m_UserName As String
m_Password As String
Public:
Declare Constructor
Declare Destructor
Declare Property hSession() As HINTERNET
Declare Property hSession(Byval nValue As HINTERNET)
Declare Property hConnection() As HINTERNET
Declare Property hConnection(Byval nValue As HINTERNET)
Declare Property LastError() As Integer
Declare Property ServerPort(Byval nValue As Integer)
Declare Property ServerPort() As Integer
Declare Property LastError(Byval nValue As Integer)
Declare Property ServerName() As String
Declare Property ServerName(Byval sValue As String)
Declare Property UserName() As String
Declare Property UserName(Byval sValue As String)
Declare Property Password() As String
Declare Property Password(Byval sValue As String)
Declare Function Connect Overload() As WINBOOL
Declare Function Connect Overload(Byval sServerName As String, _
Byval sServerPort As Integer, _
Byval sUserName As String, _
Byval sPassword As String) As WINBOOL
Declare Sub Disconnect()
Declare Function SetCurrentFolder(Byval sFolderName As String) As WINBOOL
Declare Function GetCurrentFolder() As String
Declare Function RenameFile(Byval sOldFilename As String, _
Byval sNewFilename As String) As WINBOOL
Declare Function UploadFile(Byval sLocal As String, _
Byval sRemote As String) As WINBOOL
Declare Function DownloadFile(Byval sLocal As String, _
Byval sRemote As String) As WINBOOL
Declare Function KillFile(Byval sRemote As String) As WINBOOL
End Type
''
'' Initialize the class
''
Constructor clsFTP
m_ServerPort = INTERNET_DEFAULT_FTP_PORT ' port 21
End Constructor
''
'' Close any open connection and session
''
Destructor clsFTP
this.Disconnect
End Destructor
''
'' hSession (Property)
''
Property clsFTP.hSession() As HINTERNET
Property = this.m_hSession
End Property
Property clsFTp.hSession(Byval nValue As HINTERNET)
this.m_hSession = nValue
End Property
''
'' hConnection (Property)
''
Property clsFTP.hConnection() As HINTERNET
Property = this.m_hConnection
End Property
Property clsFTp.hConnection(Byval nValue As HINTERNET)
this.m_hConnection = nValue
End Property
''
'' LastError (Property)
''
Property clsFTP.LastError() As Integer
Property = this.m_LastError
End Property
Property clsFTp.LastError(Byval nValue As Integer)
this.m_LastError = nValue
End Property
''
'' ServerPort (Property)
''
Property clsFTP.ServerPort() As Integer
Property = this.m_ServerPort
End Property
Property clsFTp.ServerPort(Byval nValue As Integer)
this.m_ServerPort = nValue
End Property
''
'' ServerName (Property)
''
Property clsFTP.ServerName() As String
Property = this.m_ServerName
End Property
Property clsFTp.ServerName(Byval sValue As String)
this.m_ServerName = sValue
End Property
''
'' UserName (Property)
''
Property clsFTP.UserName() As String
Property = this.m_UserName
End Property
Property clsFTp.UserName(Byval sValue As String)
this.m_UserName = sValue
End Property
''
'' Password (Property)
''
Property clsFTP.Password() As String
Property = this.m_Password
End Property
Property clsFTp.Password(Byval sValue As String)
this.m_Password = sValue
End Property
''
'' Close current connection and end session
''
Sub clsFTP.Disconnect()
InternetCloseHandle this.hConnection
InternetCloseHandle this.hSession
this.hConnection = 0: this.hSession = 0
End Sub
''
'' Connect to an ftp host (overload). Returns TRUE if successful.
''
Function clsFTP.Connect Overload() As WINBOOL
this.hSession = InternetOpen("ftpClass", INTERNET_OPEN_TYPE_DIRECT, "", "", 0)
If this.hSession = 0 Then
this.LastError = GetLastError
Function = False: Exit Function
End If
this.hConnection = InternetConnect(_
this.hSession, this.ServerName, this.ServerPort, _
this.UserName, this.Password, _
INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0)
If this.hConnection = 0 Then
this.LastError = GetLastError
InternetCloseHandle(this.hSession)
Function = False: Exit Function
End If
Function = True
End Function
''
'' Connect to an ftp host (overload). Returns TRUE if successful.
''
Function clsFTP.Connect Overload (Byval sServerName As String, _
Byval nServerPort As Integer, _
Byval sUserName As String, _
Byval sPassword As String) As WINBOOL
this.ServerName = sServerName
this.ServerPort = nServerPort
this.UserName = sUserName
this.Password = sPassword
Function = this.Connect
End Function
''
'' Change to a folder on the server. Returns TRUE if successful.
''
Function clsFTP.SetCurrentFolder(Byval sFolderName As String) As WINBOOL
Function = FtpSetCurrentDirectory(this.hConnection, sFolderName)
this.LastError = GetLastError
End Function
''
'' Retrieves the name of current folder on the server.
''
Function clsFTP.GetCurrentFolder() As String
Dim zBuffer As ZString * MAX_PATH
Dim nLength As Integer = MAX_PATH
FtpGetCurrentDirectory(this.hConnection, zBuffer, Cast(LPDWORD, @nLength))
this.LastError = GetLastError
Function = zBuffer
End Function
''
'' Rename a file on the server. Returns TRUE if successful.
''
Function clsFTP.RenameFile(Byval sOldFilename As String, Byval sNewFilename As String) As WINBOOL
Function = FtpRenameFile(this.hConnection, sOldFilename, sNewFilename)
this.LastError = GetLastError
End Function
''
'' Upload a file to the server. Returns TRUE if successful.
''
Function clsFTP.UploadFile(Byval sLocal As String, Byval sRemote As String) As WINBOOL
Function = FtpPutFile(this.hConnection, sLocal, sRemote, FTP_TRANSFER_TYPE_BINARY, 0)
this.LastError = GetLastError
End Function
''
'' Download a file from the server. Returns TRUE if successful.
''
Function clsFTP.DownloadFile(Byval sLocal As String, Byval sRemote As String) As WINBOOL
Function = FtpGetFile(this.hConnection, sRemote, sLocal, False, _
FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY Or INTERNET_FLAG_RELOAD, 0)
this.LastError = GetLastError
End Function
''
'' Remove a file from the server. Returns TRUE if successful.
''
Function clsFTP.KillFile(Byval sRemote As String) As WINBOOL
Function = FtpDeleteFile(this.hConnection, sRemote)
this.LastError = GetLastError
End Function
simple_test.bas
#Include Once "windows.bi"
#Include Once "clsFTP.bas"
Dim ftp As clsFTP
If ftp.Connect("ftp.ed.ac.uk", 21, "anonymous", "aaa@gmail.com") = False Then
Print "Error connecting to server. LastError = "; ftp.LastError
End If
If ftp.SetCurrentFolder("pub/courses") = False Then
Print "Error setting current folder. LastError = "; ftp.LastError
End If
Print "Current folder = "; ftp.GetCurrentFolder()
If ftp.DownloadFile("make.notes.tar", "make.notes.tar") = False Then
Print "Error downloading file. LastError = "; ftp.LastError
End If
ftp.Disconnect
Print "Done."
Sleep
FutureBasic
FB for Mac easily interfaces with the terminal command line. NOTE: The curl command line tool used in this example offers upload and sending capabilities. It supports FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS, FILE, POP3, IMAP, SMTP, RTMP and RTSP.
include "NSLog.incl"
#plist NSAppTransportSecurity @{NSAllowsArbitraryLoads:YES}
local fn RunTerminalCommand( cmd as CFStringRef ) as CFStringRef
CFStringRef outputStr = NULL
TaskRef task = fn TaskInit
TaskSetExecutableURL( task, fn URLFileURLWithPath( @"/bin/zsh" ) )
CFStringRef cmdStr = fn StringWithFormat( @"%@", cmd )
CFArrayRef args = fn ArrayWithObjects( @"-c", cmdStr, NULL )
TaskSetArguments( task, args )
PipeRef p = fn PipeInit
TaskSetStandardOutput( task, p )
TaskSetStandardError( task, p )
FileHandleRef fh = fn PipeFileHandleForReading( p )
fn TaskLaunch( task, NULL )
TaskWaitUntilExit( task )
ErrorRef err
CFDataRef dta = fn FileHandleReadDataToEndOfFile( fh, @err )
if err then NSLog( @"%@", fn ErrorLocalizedDescription( err ) ) : exit fn
outputStr = fn StringWithData( dta, NSUTF8StringEncoding )
end fn = outputStr
NSLog( @"%@", fn RunTerminalCommand( @"curl ftp://ftp.slackware.com/welcome.msg" ) )
HandleEvents
- Output:
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 100 754 100 754 0 0 1363 0 --:--:-- --:--:-- --:--:-- 1361 --------------------------------------------------------------------------- R S Y N C . O S U O S L . O R G Oregon State University Open Source Lab Unauthorized use is prohibited - violators will be prosecuted --------------------------------------------------------------------------- For more information about the OSL visit: http://osuosl.org/services/hosting This host is the home to the primary archives of several projects. We would prefer that only primary/secondary mirrors use this service. Thanks! ---------------------------------------------------------------------------
Go
Using the FTP package from github.com/stacktic/ftp.
package main
import (
"fmt"
"io"
"log"
"os"
"github.com/stacktic/ftp"
)
func main() {
// Hard-coded demonstration values
const (
hostport = "localhost:21"
username = "anonymous"
password = "anonymous"
dir = "pub"
file = "somefile.bin"
)
conn, err := ftp.Connect(hostport)
if err != nil {
log.Fatal(err)
}
defer conn.Quit()
fmt.Println(conn)
if err = conn.Login(username, password); err != nil {
log.Fatal(err)
}
if err = conn.ChangeDir(dir); err != nil {
log.Fatal(err)
}
fmt.Println(conn.CurrentDir())
files, err := conn.List(".")
if err != nil {
log.Fatal(err)
}
for _, f := range files {
fmt.Printf("%v %12d %v %v\n", f.Time, f.Size, f.Type, f.Name)
}
r, err := conn.Retr(file)
if err != nil {
log.Fatal(err)
}
defer r.Close()
f, err := os.Create(file)
if err != nil {
log.Fatal(err)
}
defer f.Close()
n, err := io.Copy(f, r)
if err != nil {
log.Fatal(err)
}
fmt.Println("Wrote", n, "bytes to", file)
}
Batch File
This uses the native FTP.EXE in Windows. I am not sure, but I think FTP.EXE client does not support passive mode.
::Playing with FTP
::Batch File Implementation
@echo off
set site="ftp.hq.nasa.gov"
set user="anonymous"
set pass="ftptest@example.com"
set dir="pub/issoutreach/Living in Space Stories (MP3 Files)"
set download="Gravity in the Brain.mp3"
(
echo.open %site%
echo.user %user% %pass%
echo.dir
echo.!echo.
echo.!echo.This is a just a text to seperate two directory listings.
echo.!echo.
echo.cd %dir%
echo.dir
echo.binary
echo.get %download%
echo.disconnect
)|ftp -n
- Output:
\Desktop>RCFTP -rw-r--r-- 1 ftpadmin ftp-adm 3997 May 26 1998 README drwxrwx-wx 6 lgipson armd 696320 Jan 23 2015 armd drwxrwx-wx 2 chmgt ftp-adm 4096 Aug 18 16:17 chmgt -r-xr-xr-x 1 root root 18120 Nov 28 2001 ftp-exec drwxrws-wx 2 ftpadmin ftp-adm 57344 Aug 18 13:08 incoming -rw-rw-r-- 1 ftpadmin ftp-adm 133 Jan 29 1996 index.html drwx------ 2 root root 4096 Apr 11 2003 lost+found drwxr-sr-x 2 ftpadmin ftp-adm 4096 Apr 14 1998 office drwxrwsr-x 17 ftpadmin ftp-adm 4096 Nov 4 2013 pub -rw-r--r-- 1 root ftp-adm 26 Jan 27 2011 robots.txt This is a just a text to seperate two directory listings. -rw-rw-r-- 1 109 space-station 2327118 May 9 2005 09sept_spacepropulsion.mp3 -rw-rw-r-- 1 109 space-station 1260304 May 9 2005 Can People go to Mars.mp3 -rw-rw-r-- 1 109 space-station 1350270 May 9 2005 Distill some water.mp3 -rw-rw-r-- 1 109 space-station 1290888 May 9 2005 Good Vibrations.mp3 -rw-rw-r-- 1 109 space-station 1431834 May 9 2005 Gravity Hurts_So good.mp3 -rw-rw-r-- 1 109 space-station 1072644 May 9 2005 Gravity in the Brain.mp3 -rw-rw-r-- 1 109 space-station 1230594 May 9 2005 Power to the ISS.mp3 -rw-rw-r-- 1 109 space-station 1309062 May 9 2005 Space Bones.mp3 -rw-rw-r-- 1 109 space-station 2292715 May 9 2005 Space Power.mp3 -rw-rw-r-- 1 109 space-station 772075 May 9 2005 We have a solution.mp3 -rw-rw-r-- 1 109 space-station 1134654 May 9 2005 When Space Makes you Dizzy.mp3 \Desktop>
C
Using ftplib
#include <ftplib.h>
int main(void)
{
netbuf *nbuf;
FtpInit();
FtpConnect("kernel.org", &nbuf);
FtpLogin("anonymous", "", nbuf);
FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE, nbuf);
FtpChdir("pub/linux/kernel", nbuf);
FtpDir((void*)0, ".", nbuf);
FtpGet("ftp.README", "README", FTPLIB_ASCII, nbuf);
FtpQuit(nbuf);
return 0;
}
C++
/* client.cpp
libftp++ C++ classes for ftplib C ftp library
compile:
clang++ -std=c++11 -o client client.cpp -lftp++
*/
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <sys/stat.h> // stat
#include <ftplib.h> // libftp
#include <ftp++.hpp> // libftp++
/* C++ classes:
Connection main ftp connection (user class)
ConnectionBase base class for Connection (internal)
DataConnection connection type, (internal)
read bytes from server,
write bytes to server
ConnectionException custom exception (thrown by Connection)
*/
/** ftp::Connection class API
data members:
A Connection instance contains only a pointer as a data member
{
protected:
netbuf * conn; // pointer to ftplib netbuf struct
}
member functions:
connect:
Connection(const char * host); // constructor
void setConnectionMode(Mode mode); // passive or port
void login(const char * user, const char * password); // Log in
info:
const char * getLastResponse(); // last server response
std::string getSystemType(); // server type
std::string getDirectory(); // remote pwd
void getList(const char * filename, const char * path); // short dir list
unsigned size(const char * path, TransferMode mode);
file transfer:
void get(const char * local, const char * remote, TransferMode mode);
void put(const char * local, const char * remote, TransferMode mode);
**/
// libc functions
int stat(const char *pathname, struct stat *buf); // local file info
char *strerror(int errnum); // explanation of error
char *basename(char *path); // filename at end of path
// STL classes and functions used
namespace stl
{
using std::cout; // stdout
using std::cerr; // stderr
using std::string; // string
using std::ifstream; // files on disk
using std::remove; // delete file on disk
};
using namespace stl;
// connection modes
using Mode = ftp::Connection::Mode;
Mode PASV = Mode::PASSIVE;
Mode PORT = Mode::PORT;
//file transfer modes
using TransferMode = ftp::Connection::TransferMode;
TransferMode BINARY = TransferMode::BINARY;
TransferMode TEXT = TransferMode::TEXT;
/* ********************** */
// ftp session parameters
struct session
{
const string server; // server name
const string port; // usually 21
const string user; // username
const string pass; // password
Mode mode; // PASV, PORT
TransferMode txmode; // BINARY, TEXT
string dir; // current or default dir
};
/* ********************** */
// local helper functions
ftp::Connection connect_ftp( const session& sess);
size_t get_ftp( ftp::Connection& conn, string const& path);
string readFile( const string& filename);
string login_ftp(ftp::Connection& conn, const session& sess);
string dir_listing( ftp::Connection& conn, const string& path);
/* ******************************** */
// Read a file into one long string
string readFile( const string& filename)
{
struct stat stat_buf;
string contents;
errno = 0;
if (stat(filename.c_str() , &stat_buf) != -1) // file stats
{
size_t len = stat_buf.st_size; // size of file
string bytes(len+1, '\0'); // string big enough
ifstream ifs(filename); // open for input
ifs.read(&bytes[0], len); // read all bytes as chars into string
if (! ifs.fail() ) contents.swap(bytes); // swap into contents
ifs.close();
}
else
{
cerr << "stat error: " << strerror(errno);
}
return contents;
}
/* *************** */
// start a session
ftp::Connection connect_ftp( const session& sess)
try
{
string constr = sess.server + ":" + sess.port;
cerr << "connecting to " << constr << " ...\n";
ftp::Connection conn{ constr.c_str() };
cerr << "connected to " << constr << "\n";
conn.setConnectionMode(sess.mode);
return conn;
}
catch (ftp::ConnectException e)
{
cerr << "FTP error: could not connect to server" << "\n";
}
/* ***** */
// login
string login_ftp(ftp::Connection& conn, const session& sess)
{
conn.login(sess.user.c_str() , sess.pass.c_str() );
return conn.getLastResponse();
}
/* ***************************** */
// get remote directory listing
// ftplib writes to file for dir contents
// convert file contents to string
string dir_listing( ftp::Connection& conn, const string& path)
try
{
// file on disk to write to
const char* dirdata = "/dev/shm/dirdata";
conn.getList(dirdata, path.c_str() );
// conn.getFullList(dirdata, path.c_str() );
// conn.getFullList(NULL, path.c_str() ); // to stdout
string dir_string = readFile(dirdata);
cerr << conn.getLastResponse() << "\n";
errno = 0;
if ( remove(dirdata) != 0 ) // delete file on disk
{
cerr << "error: " << strerror(errno) << "\n";
}
return dir_string;
}
catch (...) {
cerr << "error: getting dir contents: \n"
<< strerror(errno) << "\n";
}
/* ************************* */
// retrieve file from server
size_t get_ftp( ftp::Connection& conn, const string& r_path)
{
size_t received = 0;
const char* path = r_path.c_str();
unsigned remotefile_size = conn.size(path , BINARY);
const char* localfile = basename(path);
conn.get(localfile, path, BINARY); // get file
cerr << conn.getLastResponse() << "\n";
// get local file size
struct stat stat_buf;
errno = 0;
if (stat(localfile, &stat_buf) != -1)
received = stat_buf.st_size;
else
cerr << strerror(errno);
return received;
}
/* ******************** */
// default test session
const session sonic
{
"mirrors.sonic.net",
"21" ,
"anonymous",
"xxxx@nohost.org",
PASV,
BINARY,
"/pub/OpenBSD"
};
/* **** */
// main
int main(int argc, char* argv[], char * env[] )
{
const session remote = sonic; // copy session info
try
{
// open an ftp connection
ftp::Connection conn = connect_ftp(remote);
// login with username and passwd
cerr << login_ftp(conn, remote);
// what type system
cout << "System type: " << conn.getSystemType() << "\n";
cerr << conn.getLastResponse() << "\n";
// cd to default session dir
conn.cd(remote.dir.c_str()); // change to dir on server
cerr << conn.getLastResponse() << "\n";
// get current remote directory
string pwdstr = conn.getDirectory();
cout << "PWD: " << pwdstr << "\n";
cerr << conn.getLastResponse() << "\n";
// get file listing
string dirlist = dir_listing(conn, pwdstr.c_str() );
cout << dirlist << "\n";
string filename = "ftplist"; // small text file
auto pos = dirlist.find(filename); // find filename in dir list
auto notfound = string::npos;
if (pos != notfound) // found filename
{
// get file
size_t received = get_ftp(conn, filename.c_str() );
if (received == 0)
cerr << "got 0 bytes\n";
else
cerr << "got " << filename
<< " (" << received << " bytes)\n";
}
else
{
cerr << "file " << filename
<< "not found on server. \n";
}
}
catch (ftp::ConnectException e)
{
cerr << "FTP error: could not connect to server" << "\n";
}
catch (ftp::Exception e)
{
cerr << "FTP error: " << e << "\n";
}
catch (...)
{
cerr << "error: " << strerror(errno) << "\n";
}
// logout, connection closes automatically when conn destructs
return 0;
}
/* END */
- Output:
connecting to mirrors.sonic.net:21 ... connected to mirrors.sonic.net:21 230 Anonymous access granted, restrictions apply System type: UNIX 215 UNIX Type: L8 250 CWD command successful PWD: /openbsd 257 "/openbsd" is the current directory 226 Transfer complete /openbsd/. /openbsd/.. /openbsd/Changelogs /openbsd/LibreSSL /openbsd/OpenBGPD /openbsd/OpenNTPD /openbsd/OpenSSH /openbsd/doc /openbsd/patches /openbsd/snapshots /openbsd/songs /openbsd/syspatch /openbsd/tools /openbsd/ftplist /openbsd/timestamp /openbsd/rpki-client /openbsd/6.7 /openbsd/6.8 226 Transfer complete got ftplist (4992 bytes)
Common Lisp
Using package cl-ftp.
(use-package :ftp)
(with-ftp-connection (conn :hostname "ftp.hq.nasa.gov"
:passive-ftp-p t)
(send-cwd-command conn "/pub/issoutreach/Living in Space Stories (MP3 Files)")
(send-list-command conn t)
(let ((filename "Gravity in the Brain.mp3"))
(retrieve-file conn filename filename :type :binary)))
- Output:
-rw-rw-r-- 1 109 space-station 2327118 May 9 2005 09sept_spacepropulsion.mp3 -rw-rw-r-- 1 109 space-station 1260304 May 9 2005 Can People go to Mars.mp3 -rw-rw-r-- 1 109 space-station 1350270 May 9 2005 Distill some water.mp3 -rw-rw-r-- 1 109 space-station 1290888 May 9 2005 Good Vibrations.mp3 -rw-rw-r-- 1 109 space-station 1431834 May 9 2005 Gravity Hurts_So good.mp3 -rw-rw-r-- 1 109 space-station 1072644 May 9 2005 Gravity in the Brain.mp3 -rw-rw-r-- 1 109 space-station 1230594 May 9 2005 Power to the ISS.mp3 -rw-rw-r-- 1 109 space-station 1309062 May 9 2005 Space Bones.mp3 -rw-rw-r-- 1 109 space-station 2292715 May 9 2005 Space Power.mp3 -rw-rw-r-- 1 109 space-station 772075 May 9 2005 We have a solution.mp3 -rw-rw-r-- 1 109 space-station 1134654 May 9 2005 When Space Makes you Dizzy.mp3
Erlang
Erlang implementation using ftp module.
%%%-------------------------------------------------------------------
%%% To execute in shell, Run the following commands:-
%%% >c("ftp_example").
%%% >ftp_example:run().
%%%-------------------------------------------------------------------
-module(ftp_example).
-export([run/0]).
run() ->
Host = "ftp.easynet.fr",
Opts = [{mode, passive}],
User = "anonymous",
Password = "",
Directory = "/debian/",
File = "README.html",
%%% Open connection with FTP Server
io:format("Opening connection with host ~p ~n", [Host]),
{ok, Pid} = ftp:open(Host, Opts),
%%% Login as Anonymous user
io:format("Logging in as user ~p ~n", [User]),
ftp:user(Pid, User, Password),
%%% Change Directory to "/debian/"
io:format("Changing Directory to ~p ~n", [Directory]),
ftp:cd(Pid, Directory),
%%% Listing contents of current Directory
io:format("Contents of Current Directory ~n"),
{ok, Listing} = ftp:ls(Pid),
io:format("~p ~n", [Listing]),
%%% Download file "README.html"
io:format("Downloading File ~p to current directory ~n", [File]),
ftp:recv(Pid, File),
%%% Close connection
io:format("Closing connection to FTP Server"),
ftp:close(Pid).
Groovy
This is the code from Ran488 GitHub, modified to be executable. It relies on external Apache FTP client. Dependencies are automatically loaded with the @Grab annotation. let's say the code is saved in the file ftpTest.groovy:
@Grab(group='commons-net', module='commons-net', version='2.0')
import org.apache.commons.net.ftp.FTPClient
println("About to connect....");
new FTPClient().with {
connect "ftp.easynet.fr"
enterLocalPassiveMode()
login "anonymous", "ftptest@example.com"
changeWorkingDirectory "/debian/"
def incomingFile = new File("README.html")
incomingFile.withOutputStream { ostream -> retrieveFile "README.html", ostream }
disconnect()
}
println(" ...Done.");
By typing groovy ftpTest.groovy, you should see a README.html file on your directory.
Debian Archive See http://www.debian.org/ for information about Debian GNU/Linux. Current Releases Four Debian releases are available on the main site: Debian 6.0.10, or squeeze Debian 6.0.10 was released Saturday, 19th July 2014. Please note that the 6.0 distribution is no longer receiving security support. If you are using the amd64 or i386 architecture and not able to upgrade to the current stable release, you may wish to investigate the "squeeze-lts" distribution. Installation and upgrading instructions, More information .... ...
Haskell
Example uses ftphs package:
module Main (main) where
import Control.Exception (bracket)
import Control.Monad (void)
import Data.Foldable (for_)
import Network.FTP.Client
( cwd
, easyConnectFTP
, getbinary
, loginAnon
, nlst
, quit
, setPassive
)
main :: IO ()
main = bracket ((flip setPassive) True <$> easyConnectFTP "ftp.kernel.org") quit $ \h -> do
-- Log in anonymously
void $ loginAnon h
-- Change directory
void $ cwd h "/pub/linux/kernel/Historic"
-- List current directory
fileNames <- nlst h Nothing
for_ fileNames $ \fileName ->
putStrLn fileName
-- Download in binary mode
(fileData, _) <- getbinary h "linux-0.01.tar.gz.sign"
print fileData
J
require 'web/gethttp'
gethttp 'ftp://anonymous:example@ftp.hq.nasa.gov/pub/issoutreach/Living%20in%20Space%20Stories%20(MP3%20Files)/'
-rw-rw-r-- 1 109 space-station 2327118 May 9 2005 09sept_spacepropulsion.mp3
-rw-rw-r-- 1 109 space-station 1260304 May 9 2005 Can People go to Mars.mp3
-rw-rw-r-- 1 109 space-station 1350270 May 9 2005 Distill some water.mp3
-rw-rw-r-- 1 109 space-station 1290888 May 9 2005 Good Vibrations.mp3
-rw-rw-r-- 1 109 space-station 1431834 May 9 2005 Gravity Hurts_So good.mp3
-rw-rw-r-- 1 109 space-station 1072644 May 9 2005 Gravity in the Brain.mp3
-rw-rw-r-- 1 109 space-station 1230594 May 9 2005 Power to the ISS.mp3
-rw-rw-r-- 1 109 space-station 1309062 May 9 2005 Space Bones.mp3
-rw-rw-r-- 1 109 space-station 2292715 May 9 2005 Space Power.mp3
-rw-rw-r-- 1 109 space-station 772075 May 9 2005 We have a solution.mp3
-rw-rw-r-- 1 109 space-station 1134654 May 9 2005 When Space Makes you Dizzy.mp3
#file=: gethttp rplc&(' ';'%20') 'ftp://anonymous:example@ftp.hq.nasa.gov/pub/issoutreach/Living in Space Stories (MP3 Files)/We have a solution.mp3'
772075
Java
requires apache.commons.net
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
public class FTPconn {
public static void main(String[] args) throws IOException {
String server = "ftp.hq.nasa.gov";
int port = 21;
String user = "anonymous";
String pass = "ftptest@example.com";
OutputStream output = null;
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
serverReply(ftpClient);
int replyCode = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(replyCode)) {
System.out.println("Failure. Server reply code: " + replyCode);
return;
}
serverReply(ftpClient);
if (!ftpClient.login(user, pass)) {
System.out.println("Could not login to the server.");
return;
}
String dir = "pub/issoutreach/Living in Space Stories (MP3 Files)/";
if (!ftpClient.changeWorkingDirectory(dir)) {
System.out.println("Change directory failed.");
return;
}
ftpClient.enterLocalPassiveMode();
for (FTPFile file : ftpClient.listFiles())
System.out.println(file);
String filename = "Can People go to Mars.mp3";
output = new FileOutputStream(filename);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
if (!ftpClient.retrieveFile(filename, output)) {
System.out.println("Retrieving file failed");
return;
}
serverReply(ftpClient);
ftpClient.logout();
} finally {
if (output != null)
output.close();
}
}
private static void serverReply(FTPClient ftpClient) {
for (String reply : ftpClient.getReplyStrings()) {
System.out.println(reply);
}
}
}
Output:
220-Warning: This system is owned and operated by the US Federal Government. Unauthorized access to this system is a violation of US Federal law and could lead to prosecution. This is NASA HQ ANONYMOUS FTP SERVER. Please read the README file located in the initial server root directory. IF you place files into the /incoming directory, it is IMPERATIVE that you notify ftp-admin@hq.nasa.gov that you have done so and of your intended disposition of those files. Absent such notification, all files placed in /incoming that cannot be identified will be immediately deleted. 220 FTP Server Ready 220-Warning: This system is owned and operated by the US Federal Government. Unauthorized access to this system is a violation of US Federal law and could lead to prosecution. This is NASA HQ ANONYMOUS FTP SERVER. Please read the README file located in the initial server root directory. IF you place files into the /incoming directory, it is IMPERATIVE that you notify ftp-admin@hq.nasa.gov that you have done so and of your intended disposition of those files. Absent such notification, all files placed in /incoming that cannot be identified will be immediately deleted. 220 FTP Server Ready -rw-rw-r-- 1 109 space-station 2327118 May 9 2005 09sept_spacepropulsion.mp3 -rw-rw-r-- 1 109 space-station 1260304 May 9 2005 Can People go to Mars.mp3 -rw-rw-r-- 1 109 space-station 1350270 May 9 2005 Distill some water.mp3 -rw-rw-r-- 1 109 space-station 1290888 May 9 2005 Good Vibrations.mp3 -rw-rw-r-- 1 109 space-station 1431834 May 9 2005 Gravity Hurts_So good.mp3 -rw-rw-r-- 1 109 space-station 1072644 May 9 2005 Gravity in the Brain.mp3 -rw-rw-r-- 1 109 space-station 1230594 May 9 2005 Power to the ISS.mp3 -rw-rw-r-- 1 109 space-station 1309062 May 9 2005 Space Bones.mp3 -rw-rw-r-- 1 109 space-station 2292715 May 9 2005 Space Power.mp3 -rw-rw-r-- 1 109 space-station 772075 May 9 2005 We have a solution.mp3 -rw-rw-r-- 1 109 space-station 1134654 May 9 2005 When Space Makes you Dizzy.mp3 226 Transfer complete
Julia
using FTPClient
ftp = FTP(hostname = "ftp.ed.ac.uk", username = "anonymous")
cd(ftp, "pub/courses")
println(readdir(ftp))
bytes = read(download(ftp, "make.notes.tar"))
close(ftp)
Kotlin
Assuming that ftplib is already installed on your system in the default location(s), you first need to build ftplib.klib using the following .def file and the cinterop tool. As the NetBuf struct is not defined in ftplib.h (but is in ftplib.c) it has been included in the .def file so that the tool can deal with it (and its alias 'netbuf') properly from a Kotlin perspective.
headers = /usr/include/ftplib.h linkerOpts.linux = -L/usr/lib -lftp --- #include <sys/time.h> struct NetBuf { char *cput,*cget; int handle; int cavail,cleft; char *buf; int dir; netbuf *ctrl; netbuf *data; int cmode; struct timeval idletime; FtpCallback idlecb; void *idlearg; int xfered; int cbbytes; int xfered1; char response[256]; };
Next, you need to compile the following Kotlin program, linking against ftplib.klib.
// Kotlin Native v0.6
import kotlinx.cinterop.*
import ftplib.*
fun main(args: Array<String>) {
val nbuf = nativeHeap.allocPointerTo<netbuf>()
FtpInit()
FtpConnect("ftp.easynet.fr", nbuf.ptr)
val vnbuf = nbuf.value
FtpLogin("anonymous", "ftptest@example.com", vnbuf)
FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE.toLong(), vnbuf)
FtpChdir("/debian/", vnbuf)
FtpDir(null, ".", vnbuf)
FtpGet("ftp.README", "README.html", FTPLIB_ASCII.toByte(), vnbuf)
FtpQuit(vnbuf)
nativeHeap.free(nbuf)
}
Finally, the resulting .kexe file should be executed producing something similar to the following output:
drwxr-xr-x 23 1002 1002 4096 Dec 9 09:44 dists drwxr-xr-x 4 1002 1002 4096 Mar 3 19:52 doc -rw-r--r-- 1 1002 1002 361654 Mar 3 20:49 extrafiles drwxr-xr-x 3 1002 1002 4096 Mar 3 20:42 indices -rw-r--r-- 1 1002 1002 14948661 Mar 3 20:42 ls-lR.gz drwxr-xr-x 5 1002 1002 4096 Dec 19 2000 pool drwxr-xr-x 4 1002 1002 4096 Nov 17 2008 project -rw-r--r-- 1 1002 1002 1186 Dec 9 09:42 README -rw-r--r-- 1 1002 1002 1290 Jun 26 2010 README.CD-manufacture -rw-r--r-- 1 1002 1002 2903 Dec 9 09:42 README.html -rw-r--r-- 1 1002 1002 291 Mar 4 2017 README.mirrors.html -rw-r--r-- 1 1002 1002 86 Mar 4 2017 README.mirrors.txt drwxr-xr-x 3 1002 1002 4096 Oct 10 2012 tools drwxr-xr-x 23 1002 1002 4096 Jun 17 2017 zzz-dists
Lingo
CURLOPT_URL = 10002
ch = xtra("Curl").new()
url = "ftp://domain.com"
-- change to remote dir "/foo/bar/"
put "/foo/bar/" after url
ch.setOption(CURLOPT_URL, url)
res = ch.exec(1)
-- print raw FTP listing as string
put res.readRawString(res.length)
-- download file "download.mp3" (passive mode is the internal default behavior)
filename = "download.mp3"
ch.setOption(CURLOPT_URL, url & filename)
ch.setDestinationFile(_movie.path & filename)
res = ch.exec()
LiveCode
libURLSetFTPMode "passive" --default is passive anyway
put url "ftp://ftp.hq.nasa.gov/" into listing
repeat for each line ftpln in listing
set itemdel to space
if the first char of (the first item of ftpln) is "d" then
-- is a directory
put the last item of ftpln after dirlist
else
put the last item of ftpln after filelist
end if
end repeat
put listing //(subset)
// -rw-r--r-- 1 ftpadmin ftp-adm 3997 May 26 1998 README
// drwxrwsr-x 17 ftpadmin ftp-adm 4096 Sep 10 16:08 pub
put dirlist
// armd
// chmgt
// incoming
// lost+found
// office
// pub
put filelist
// README
// ftp-exec
// index.html
// robots.txt
-- downloading a file (upload is same, but use put)
-- you don't have to cd manually
-- file up/down transfer is binary in livecode (always enforced by livecode)
put URL "ftp://ftp.hq.nasa.gov/pub/robots.txt" into URL "file:myFile.txt"
You can execute any ftp command using the libURLftpCommand command
e.g. to know the working directory, issue "pwd", we could issue "list" for above too,
but using an url with slash on the end with the ftp protocol causes a dir listing by default.
put libURLftpCommand("PWD",ftp.example.org)
Nim
import asyncdispatch, asyncftpclient
const
Host = "speedtest.tele2.net"
Upload = "upload"
File = "1KB.zip"
proc main {.async.} =
# Create session and connect.
let ftp = newAsyncFtpClient(Host, user = "anonymous", pass = "anything")
await ftp.connect()
echo "Connected."
echo await ftp.send("PASV") # Switch to passive mode.
# Change directory and list its contents.
await ftp.cd(Upload)
echo "Changed to directory: ", Upload
echo "Contents of directory: ", Upload
for file in await ftp.listDirs():
echo " ", file
# Download a file.
await ftp.cd("/")
echo "Returned to root directory."
await ftp.retrFile(file = File, dest = File)
echo "Downloaded file: ", File
echo await ftp.send("QUIT") # Disconnect.
waitFor main()
- Output:
Connected. 227 Entering Passive Mode (90,130,70,73,94,108). Changed to directory: upload Contents of directory: upload 1_2758858854070946631_17-9ULspeedtest.upt 2MB.zip 2_2758858854070946631_17-9ULspeedtest.upt 3_2758858854070946631_17-9ULspeedtest.upt DCS-932LB1-WEBCAM-12021010316232001.jpg DCS-932LB1-WEBCAM-12021010316292601.jpg DCS-932LB1-WEBCAM-12021010316314601.jpg speedtest_uplink_1.1G.zip upload_file.txt Returned to root directory. Downloaded file: 1KB.zip 221 Goodbye.
Perl
use Net::FTP;
# set server and credentials
my $host = 'speedtest.tele2.net';
my $user = 'anonymous';
my $password = '';
# connect in passive mode
my $f = Net::FTP->new($host) or die "Can't open $host\n";
$f->login($user, $password) or die "Can't login as $user\n";
$f->passive();
# change remote directory, list contents
$f->cwd('upload');
@files = $f->ls();
printf "Currently %d files in the 'upload' directory.\n", @files;
# download file in binary mode
$f->cwd('/');
$f->type('binary');
$local = $f->get('512KB.zip');
print "Your file was stored as $local in the current directory\n";
- Output:
Currently 20 files in the 'upload' directory Your file was stored as 512KB.zip in the current directory!
Phix
without js -- libcurl, allocate, file i/o include libcurl.e constant url = "ftp://speedtest.tele2.net/" curl_global_init() atom curl = curl_easy_init(), pErrorBuffer = allocate(CURL_ERROR_SIZE) curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, pErrorBuffer) curl_easy_setopt(curl, CURLOPT_URL, url) object res = curl_easy_perform_ex(curl) if integer(res) then ?{res,peek_string(pErrorBuffer)} else puts(1,res) end if string filename = "1KB.zip" {} = delete_file(filename) res = curl_easy_get_file(url&filename, "", filename) if res=CURLE_OK then printf(1,"successfully downloaded %s (size %s)\n",{filename,get_file_size(filename,true)}) else ?{"error",res} end if
- Output:
-rw-r--r-- 1 0 0 1073741824000 Feb 19 2016 1000GB.zip -rw-r--r-- 1 0 0 107374182400 Feb 19 2016 100GB.zip -rw-r--r-- 1 0 0 102400 Feb 19 2016 100KB.zip -rw-r--r-- 1 0 0 104857600 Feb 19 2016 100MB.zip -rw-r--r-- 1 0 0 10737418240 Feb 19 2016 10GB.zip -rw-r--r-- 1 0 0 10485760 Feb 19 2016 10MB.zip -rw-r--r-- 1 0 0 1073741824 Feb 19 2016 1GB.zip -rw-r--r-- 1 0 0 1024 Feb 19 2016 1KB.zip -rw-r--r-- 1 0 0 1048576 Feb 19 2016 1MB.zip -rw-r--r-- 1 0 0 209715200 Feb 19 2016 200MB.zip -rw-r--r-- 1 0 0 20971520 Feb 19 2016 20MB.zip -rw-r--r-- 1 0 0 2097152 Feb 19 2016 2MB.zip -rw-r--r-- 1 0 0 3145728 Feb 19 2016 3MB.zip -rw-r--r-- 1 0 0 524288000 Feb 19 2016 500MB.zip -rw-r--r-- 1 0 0 52428800 Feb 19 2016 50MB.zip -rw-r--r-- 1 0 0 524288 Feb 19 2016 512KB.zip -rw-r--r-- 1 0 0 5242880 Feb 19 2016 5MB.zip drwxr-xr-x 2 105 108 561152 Jul 18 13:11 upload successfully downloaded 1KB.zip (size 1KB)
PHP
$server = "speedtest.tele2.net";
$user = "anonymous";
$pass = "ftptest@example.com";
$conn = ftp_connect($server);
if (!$conn) {
die('unable to connect to: '. $server);
}
$login = ftp_login($conn, $user, $pass);
if (!$login) {
echo 'unable to log in to '. $server. ' with user: '.$user.' and pass: '. $pass;
} else{
echo 'connected successfully'.PHP_EOL;
$directory = ftp_nlist($conn,'');
print_r($directory);
}
if (ftp_get($conn, '1KB.zip', '1KB.zip', FTP_BINARY)) {
echo "Successfully downloaded file".PHP_EOL;
} else {
echo "failed to download file";
}
- Output:
connected successfully Array ( [0] => 1000GB.zip [1] => 100GB.zip [2] => 100KB.zip [3] => 100MB.zip [4] => 10GB.zip [5] => 10MB.zip [6] => 1GB.zip [7] => 1KB.zip [8] => 1MB.zip [9] => 200MB.zip [10] => 20MB.zip [11] => 2MB.zip [12] => 3MB.zip [13] => 500MB.zip [14] => 50MB.zip [15] => 512KB.zip [16] => 5MB.zip [17] => upload ) Successfully downloaded file Done.
PicoLisp
Passive is the default behavior of 'curl'
(in '(curl "-sl" "ftp://kernel.org/pub/site/")
(while (line)
(prinl @) ) )
(call "curl" "-s" "-o" "sha256sums.asc" "ftp://kernel.org/pub/site/sha256sums.asc")
Output:
README sample_mirror_script.pl sha256sums.asc
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()
Racket
Note: net/ftp in Racket uses passive mode exclusively.
#lang racket
(require net/ftp)
(let* ([server "kernel.org"]
[remote-dir "/pub/linux/kernel/"]
[conn (ftp-establish-connection
server
21
"anonymous"
"")])
(ftp-cd conn remote-dir)
(map
(lambda (elem) (displayln (string-join elem "\t")))
(ftp-directory-list conn "."))
(ftp-download-file conn "." "README")
(ftp-close-connection conn))
Raku
(formerly Perl 6)
use Net::FTP;
my $host = 'speedtest.tele2.net';
my $user = 'anonymous';
my $password = '';
my $ftp = Net::FTP.new( host => $host, :passive );
$ftp.login( user => $user, pass => $password );
$ftp.cwd( 'upload' );
$ftp.cwd( '/' );
say $_<name> for $ftp.ls;
$ftp.get( '1KB.zip', :binary );
- Output:
1000GB.zip 100GB.zip 100KB.zip 100MB.zip 10GB.zip 10MB.zip 1GB.zip 1KB.zip 1MB.zip 200MB.zip 20MB.zip 2MB.zip 3MB.zip 500MB.zip 50MB.zip 512KB.zip 5MB.zip upload
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
Ruby
require 'net/ftp'
Net::FTP.open('ftp.ed.ac.uk', "anonymous","aaa@gmail.com" ) do |ftp|
ftp.passive = true # default since Ruby 2.3
ftp.chdir('pub/courses')
puts ftp.list
ftp.getbinaryfile("make.notes.tar")
end
The connection is closed automatically at the end of the block.
Rust
Using crate ftp
version 3.0.1
use std::{error::Error, fs::File, io::copy};
use ftp::FtpStream;
fn main() -> Result<(), Box<dyn Error>> {
let mut ftp = FtpStream::connect("ftp.easynet.fr:21")?;
ftp.login("anonymous", "")?;
ftp.cwd("debian")?;
for file in ftp.list(None)? {
println!("{}", file);
}
let mut stream = ftp.get("README")?;
let mut file = File::create("README")?;
copy(&mut stream, &mut file)?;
Ok(())
}
Scala
import java.io.{File, FileOutputStream, InputStream}
import org.apache.commons.net.ftp.{FTPClient, FTPFile, FTPReply}
import scala.util.{Failure, Try}
object FTPconn extends App {
val (server, pass) = ("ftp.ed.ac.uk", "-ftptest@example.com")
val (dir, filename, ftpClient) = ("/pub/cartonet/", "readme.txt", new FTPClient())
def canConnect(host: String): Boolean = {
ftpClient.connect(host)
val connectionWasEstablished = ftpClient.isConnected
ftpClient.disconnect()
connectionWasEstablished
}
def downloadFileStream(remote: String): InputStream = {
val stream: InputStream = ftpClient.retrieveFileStream(remote)
ftpClient.completePendingCommand()
stream
}
def uploadFile(remote: String, input: InputStream): Boolean = ftpClient.storeFile(remote, input)
if (Try {
def cwd(path: String): Boolean = ftpClient.changeWorkingDirectory(path)
def filesInCurrentDirectory: Seq[String] = listFiles().map(_.getName)
def listFiles(): List[FTPFile] = ftpClient.listFiles.toList
def downloadFile(remote: String): Boolean = {
val os = new FileOutputStream(new File(remote))
ftpClient.retrieveFile(remote, os)
}
def connectWithAuth(host: String,
password: String,
username: String = "anonymous",
port: Int = 21): Try[Boolean] = {
def connect(): Try[Unit] = Try {
try {
ftpClient.connect(host, port)
} catch {
case ex: Throwable =>
println(ex.getMessage)
Failure
}
ftpClient.enterLocalPassiveMode()
serverReply(ftpClient)
val replyCode = ftpClient.getReplyCode
if (!FTPReply.isPositiveCompletion(replyCode))
println("Failure. Server reply code: " + replyCode)
}
for {
connection <- connect()
login <- Try {
ftpClient.login(username, password)
}
} yield login
}
def serverReply(ftpClient: FTPClient): Unit =
for (reply <- ftpClient.getReplyStrings) println(reply)
connectWithAuth(server, pass)
cwd(dir)
listFiles().foreach(println)
downloadFile(filename)
serverReply(ftpClient)
ftpClient.logout
}.isFailure) println(s"Failure.")
}
- Output:
See it in running in your browser by Scastie (JVM).
Seed7
The library ftp.s7i contains functions to open and handle an ftpFileSys.
$ include "seed7_05.s7i";
include "ftp.s7i";
const proc: main is func
local
var ftpFileSys: ftp is fileSys.value;
var string: line is "";
begin
ftp := openFtp("kernel.org");
setActiveMode(ftp, FALSE); # Passive is the default.
chdir(ftp, "/pub/linux/kernel");
for line range listDir(ftp, ".") do
writeln(line);
end for;
setAsciiTransfer(ftp, FALSE);
writeln(getFile(ftp, "README"));
close(ftp);
end func;
Sidef
require('Net::FTP');
var ftp = %s'Net::FTP'.new('ftp.ed.ac.uk', Passive => 1);
ftp.login('anonymous','aaa@gmail.com');
ftp.cwd('pub/courses');
[ftp.dir].each {|line| say line };
ftp.binary; # set binary mode
ftp.get("make.notes.tar");
ftp.quit;
Tcl
Using package ftp
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
Using a virtual file system
An alternative approach that uses the package TclVFS to access ftp:// paths as a virtual file system.
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]
The file vfsftpfix.tcl with the passive mode patch (see http://wiki.tcl.tk/12837):
# 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
}
UNIX Shell
Uses sftp which os available on all Linux distress by default. The commands are identical to ftp. This example uses the public free sftp server at test.rebex.net , the credentials are demo/password :
Aamrun $ sftp demo@test.rebex.net
Password:
Connected to test.rebex.net.
sftp> ls
pub readme.txt
sftp> cd pub
sftp> ls
example
sftp> ls example
example/KeyGenerator.png example/KeyGeneratorSmall.png example/ResumableTransfer.png example/WinFormClient.png example/WinFormClientSmall.png example/imap-console-client.png example/mail-editor.png example/mail-send-winforms.png
example/mime-explorer.png example/pocketftp.png example/pocketftpSmall.png example/pop3-browser.png example/pop3-console-client.png example/readme.txt example/winceclient.png example/winceclientSmall.png
sftp> cd example
sftp> get KeyGenerator.png
Fetching /pub/example/KeyGenerator.png to KeyGenerator.png
/pub/example/KeyGenerator.png 100% 36KB 146.4KB/s 00:00
sftp> exit
Aamrun$
V (Vlang)
import net.ftp
fn main() {
result := ftp_client_test() or {println('Error: something went wrong') exit(1)}
println(result)
}
fn ftp_client_test() ?[]u8 {
mut zftp := ftp.new()
mut blob := []u8{}
defer {
zftp.close() or {
println('Error: failure to close ftp')
exit(10)
}
}
connect_result := zftp.connect('ftp.redhat.com') or {
println('Error: failed to connect')
exit(1)
}
login_result := zftp.login('ftp', 'ftp') or {
println('Error: failed to login')
exit(2)
}
pwd := zftp.pwd() or {
println('Error: failed to login')
exit(3)
}
if (connect_result == true) && (login_result == true) && (pwd.len > 0) {
zftp.cd('/') or {
println('Error: failed to get root directory')
exit(4)
}
}
dir_list1 := zftp.dir() or {
println('Error: failed to get directory listing')
exit(5)
}
if dir_list1.len > 0 {
zftp.cd('/suse/linux/enterprise/11Server/en/SAT-TOOLS/SRPMS/') or {
println('Error: failed to get directory listing')
exit(6)
}
}
dir_list2 := zftp.dir() or {
println('Error: failed to get directory listing')
exit(7)
}
if dir_list2.len > 0 {
if dir_list2.contains('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') == true {
blob = zftp.get('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') or {
println('Error: failed to get directory listing')
exit(8)
}
}
}
if blob.len <= 0 {
println('Error: failed to get data')
exit(9)
}
return blob
}
Wren
An embedded program so we can ask the C host to communicate with ftplib for us.
/* FTP.wren */
var FTPLIB_CONNMODE = 1
var FTPLIB_PASSIVE = 1
var FTPLIB_ASCII = 65 // 'A'
foreign class Ftp {
foreign static init()
construct connect(host) {}
foreign login(user, pass)
foreign options(opt, val)
foreign chdir(path)
foreign dir(outputFile, path)
foreign get(output, path, mode)
foreign quit()
}
Ftp.init()
var ftp = Ftp.connect("ftp.easynet.fr")
ftp.login("anonymous", "ftptest@example.com")
ftp.options(FTPLIB_CONNMODE, FTPLIB_PASSIVE)
ftp.chdir("/debian/")
ftp.dir("", ".")
ftp.get("ftp.README", "README", FTPLIB_ASCII)
ftp.quit()
We now embed this in the following C program, compile and run it.
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <ftplib.h>
#include "wren.h"
/* C <=> Wren interface functions */
void C_init(WrenVM* vm) {
FtpInit();
}
void C_ftpAllocate(WrenVM* vm) {
netbuf *nbuf;
const char *host = wrenGetSlotString(vm, 1);
FtpConnect(host, &nbuf);
netbuf** pnbuf = (netbuf**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(netbuf*));
*pnbuf = nbuf;
}
void C_login(WrenVM* vm) {
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0);
const char *user = wrenGetSlotString(vm, 1);
const char *pass = wrenGetSlotString(vm, 2);
FtpLogin(user, pass, nbuf);
}
void C_options(WrenVM* vm) {
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0);
int opt = (int)wrenGetSlotDouble(vm, 1);
long val = (long)wrenGetSlotDouble(vm, 2);
FtpOptions(opt, val, nbuf);
}
void C_chdir(WrenVM* vm) {
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0);
const char *path = wrenGetSlotString(vm, 1);
FtpChdir(path, nbuf);
}
void C_dir(WrenVM* vm) {
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0);
const char *outputFile = wrenGetSlotString(vm, 1);
if (strlen(outputFile) == 0) outputFile = NULL;
const char *path = wrenGetSlotString(vm, 2);
FtpDir(outputFile, path, nbuf);
}
void C_get(WrenVM* vm) {
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0);
const char *output = wrenGetSlotString(vm, 1);
if (strlen(output) == 0) output = NULL;
const char *path = wrenGetSlotString(vm, 2);
char mode = (char)wrenGetSlotDouble(vm, 3);
FtpGet(output, path, mode, nbuf);
}
void C_quit(WrenVM* vm) {
netbuf* nbuf = *(netbuf**)wrenGetSlotForeign(vm, 0);
FtpQuit(nbuf);
}
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods;
methods.finalize = NULL;
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Ftp") == 0) {
methods.allocate = C_ftpAllocate;
}
}
return methods;
}
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Ftp") == 0) {
if ( isStatic && strcmp(signature, "init()") == 0) return C_init;
if (!isStatic && strcmp(signature, "login(_,_)") == 0) return C_login;
if (!isStatic && strcmp(signature, "options(_,_)") == 0) return C_options;
if (!isStatic && strcmp(signature, "chdir(_)") == 0) return C_chdir;
if (!isStatic && strcmp(signature, "dir(_,_)") == 0) return C_dir;
if (!isStatic && strcmp(signature, "get(_,_,_)") == 0) return C_get;
if (!isStatic && strcmp(signature, "quit()") == 0) return C_quit;
}
}
return NULL;
}
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignClassFn = &bindForeignClass;
config.bindForeignMethodFn = &bindForeignMethod;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "FTP.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}
- Output:
Sample output:
drwxr-xr-x 25 1002 1002 4096 Aug 15 06:55 dists drwxr-xr-x 4 1002 1002 4096 Sep 27 07:52 doc -rw-r--r-- 1 1002 1002 254738 Sep 27 08:21 extrafiles drwxr-xr-x 3 1002 1002 4096 Sep 27 08:15 indices -rw-r--r-- 1 1002 1002 14538903 Sep 27 08:15 ls-lR.gz drwxr-xr-x 5 1002 1002 4096 Dec 19 2000 pool drwxr-xr-x 4 1002 1002 4096 Nov 17 2008 project -rw-r--r-- 1 1002 1002 1320 Aug 14 09:28 README -rw-r--r-- 1 1002 1002 1290 Jun 26 2010 README.CD-manufacture -rw-r--r-- 1 1002 1002 3203 Aug 14 09:27 README.html -rw-r--r-- 1 1002 1002 291 Mar 4 2017 README.mirrors.html -rw-r--r-- 1 1002 1002 86 Mar 4 2017 README.mirrors.txt drwxr-xr-x 3 1002 1002 4096 Oct 10 2012 tools drwxr-xr-x 26 1002 1002 4096 Aug 14 13:55 zzz-dists
zkl
Using the cURL library, doing this from the REPL. Moving around in the tree isn't supported.
zkl: var cURL=Import("zklCurl")
zkl: var d=cURL().get("ftp.hq.nasa.gov/pub/issoutreach/Living in Space Stories (MP3 Files)/")
L(Data(2,567),1630,23) // downloaded listing, 1630 bytes of header, 23 bytes of trailer
zkl: d[0][1630,-23].text
-rw-rw-r-- 1 109 space-station 2327118 May 9 2005 09sept_spacepropulsion.mp3
...
-rw-rw-r-- 1 109 space-station 1134654 May 9 2005 When Space Makes you Dizzy.mp3
zkl: d=cURL().get("ftp.hq.nasa.gov/pub/issoutreach/Living in Space Stories (MP3 Files)/When Space Makes you Dizzy.mp3")
L(Data(1,136,358),1681,23)
zkl: File("foo.mp3","w").write(d[0][1681,-23])
1134654 // note that this matches size in listing
The resulting file foo.mp3 has a nice six minute description of what can happen when returning from space.
- Programming Tasks
- Programming environment operations
- Networking and Web Interaction
- BASIC
- BaCon
- FreeBASIC
- ClsFTP
- FutureBasic
- Go
- Batch File
- C
- C++
- Common Lisp
- Erlang
- Groovy
- Haskell
- J
- Java
- Julia
- Kotlin
- Ftplib
- Lingo
- Curl Xtra
- LiveCode
- Nim
- Perl
- Phix
- Phix/libcurl
- PHP
- PicoLisp
- Python
- Racket
- Raku
- REBOL
- Ruby
- Rust
- Scala
- Commons-net
- Seed7
- Sidef
- Tcl
- UNIX Shell
- V (Vlang)
- Wren
- Zkl
- PARI/GP/Omit
- Commodore BASIC/Omit