Tabular IQ

FileTransfer Class

Class Index By Category

Overview

FileTransfer transfers files to and from a remote server. Plain FTP, FTP over TLS (FTPS, see setSecure), and SFTP -- file transfer carried over SSH -- are all supported; the protocol is chosen by the url scheme (|ftp://|, |ftps://|, |sftp://|).

SFTP identifies the server by its SSH host key rather than by a certificate chain, so there is no system trust store to fall back on. An |sftp://| transfer therefore requires the expected host key to be supplied first, with either setHostKeySha256 or setKnownHosts; without one of them the transfer fails immediately rather than connecting to an unverified server.

Constructor

FileTransfer()

Events

FileTransfer.finished
Fired when asynchronous file transfers are finished

Methods

FileTransfer.cancel
Cancels an asynchronous transfer
FileTransfer.download
Downloads a file from an FTP or SFTP server
FileTransfer.getBytesTransferred
Returns the total number of bytes received or sent.
FileTransfer.getErrorString
Returns a description of the last transfer failure
FileTransfer.isDone
Returns a value indicating whether the request is done
FileTransfer.isSuccess
Returns whether the last transfer completed successfully
FileTransfer.rename
Renames a filename on a remote FTP or SFTP server
FileTransfer.setAsync
Turns asynchronous mode on or off
FileTransfer.setCaInfo
Sets a certificate authority bundle to verify the server against
FileTransfer.setHostKeySha256
Sets the SSH host key an SFTP server must present
FileTransfer.setKnownHosts
Sets an OpenSSH known_hosts file to verify an SFTP server against
FileTransfer.setSecure
Turns FTPS (FTP over TLS) on or off
FileTransfer.setVerifyServer
Turns verification of the server's identity on or off
FileTransfer.upload
Uploads a file to an FTP or SFTP server

Example

// a small wrapper around FileTransfer that fills in the sftp url, the
// credentials and the directories, so a caller only has to name the file
// it wants moved.  The server is Wing FTP Server's public demo, which
// serves files out of /download and accepts uploads into /upload.

class BasicSftpRequest {
    server       = "demo.wftpserver.com:2222";
    username     = "demo";
    password     = "demo";
    download_dir = "/download/";
    upload_dir   = "/upload/";
    local_dir    = "";  // set in the constructor
    file         = "";  // file to download/upload; set later
    transfer     = null;

    // SFTP runs over SSH, so the server is verified by host key rather than
    // by a certificate.  This is the base64 SHA-256 fingerprint OpenSSH
    // prints after "SHA256:"; reread it with "ssh-keygen -lf" if it changes.
    host_key = "8fo3mJ9x2Cn+jXjcceuFDDcZXiS4LymvfnFrnDHw7fk";

    constructor() {
        this.local_dir = `${Environment.getTempPath()}/`;

        this.transfer = new FileTransfer();
        this.transfer.setAsync(true);
        this.transfer.finished.connect(this, this.onFinished);

        // without this -- or setKnownHosts() -- an sftp:// transfer is
        // refused before it connects
        this.transfer.setHostKeySha256(this.host_key);
    }

    // e.g. "sftp://demo:demo@demo.wftpserver.com:2222/download/version.txt"
    remotePath(server_dir) {
        const credentials = `${this.username}:${this.password}`;

        return `sftp://${credentials}@${this.server}${server_dir}${this.file}`;
    }

    localPath() {
        return `${this.local_dir}${this.file}`;
    }

    onFinished() {
        alert(`Finished transferring ${this.file} to ${this.localPath()}`);
        Application.exit();
    }

    download(file) {
        this.file = file;

        return this.transfer.download(this.remotePath(this.download_dir),
                                      this.localPath());
    }

    upload(file) {
        this.file = file;

        return this.transfer.upload(this.localPath(),
                                    this.remotePath(this.upload_dir));
    }
}

// the class has to be declared before it is used
const sftp = new BasicSftpRequest();
sftp.download("version.txt");

// run the app -- necessary for processing events
Application.run();

FileTransfer.cancel

function FileTransfer.cancel()

Description

Calling this method causes an asynchronous transfer to abort.

FileTransfer.download

function FileTransfer.download(url : String, destination_filename : String) : Boolean

Arguments

url
The remote location to download
destination_filename
The filename to save, with full path name.

Returns

Returns true upon successful completion, otherwise false if an error occurred.

Description

Calling this method downloads a file from an FTP or an SFTP server onto the local computer. The url specified in the url parameter takes the following format: sftp://username:password@servername.domain.com/path/to/filename.ext -- If you wish to use the ftp protocol, change the protocol identifier before the first colon in the url string.

An |sftp://| url requires the server's host key to have been supplied first, with setHostKeySha256 or setKnownHosts; with neither, this method fails without connecting.

FileTransfer.getBytesTransferred

function FileTransfer.getBytesTransferred() : Number

Returns

Total number of transferred bytes

Description

A call to this method returns the total number of bytes received or sent. This function may also be called during asynchronous transfers.

FileTransfer.getErrorString

function FileTransfer.getErrorString() : String

Returns

A description of the last failure, or an empty string

Description

Calling this method returns a short description of why the most recently completed transfer or rename failed, for example "SSL connect error" or "Access denied to remote resource". If the last operation succeeded, or no operation has run yet, an empty string is returned. In asynchronous mode the result is meaningful once isDone() returns true; a natural place to call it is a finished event handler that found isSuccess() false.

FileTransfer.isDone

function FileTransfer.isDone() : Boolean

Returns

True if the file transfer is finished, false if it is still running

Description

Returns a boolean value indicating whether the most recent file transfer operation is finished.

FileTransfer.isSuccess

function FileTransfer.isSuccess() : Boolean

Returns

True if the last completed transfer succeeded, false otherwise

Description

Returns true if the most recently completed transfer succeeded, false otherwise. In asynchronous mode download() and upload() return as soon as the request is started, so their return value only reports that; call this from the finished event handler (or after isDone() turns true) to find out whether the transfer actually worked.

FileTransfer.rename

function FileTransfer.rename(source_url : String, new_name : String) : Boolean

Arguments

source_url
The file to rename on the remote server
new_name
The new name the file should take

Returns

Returns true upon successful completion, otherwise false if an error occurred.

Description

Calling this method renames a file on a remote FTP or SFTP server The source url specified in source_url parameter takes the following format: sftp://username:password@servername.domain.com/path/to/filename.ext -- If you wish to use the ftp protocol, change the protocol identifier before the first colon in the url string. The filename specified in the new_name parameter indicates the new name that the file will take. It should be specified as a simple filename, without a qualifying path name.

The server is the one from the most recent download or upload on this object, and for |sftp://| it is verified the same way -- with the host key supplied through setHostKeySha256 or setKnownHosts.

FileTransfer.setAsync

function FileTransfer.setAsync(value : Boolean)

Arguments

value
Specifying true turns on asynchronous mode and false turns it off

Description

Turns asynchronous mode on or off. If asynchronous mode is on, requests will return immediately and the processing will be done in the background. Upon completion of the request, the finished event is fired.

FileTransfer.setCaInfo

function FileTransfer.setCaInfo(path : String)

Arguments

path
Path to a PEM file, or an empty string for the system store

Description

Points the TLS layer at a PEM file holding the certificate authority (or self-signed server certificate) that the server's certificate should be verified against, for servers whose certificate is not issued by an authority in the system trust store. Passing an empty string restores the default, which is the system store.

This ADDS a trust anchor; it does not turn verification off. A server presenting a certificate that does not chain to the supplied bundle is still rejected.

FileTransfer.setHostKeySha256

function FileTransfer.setHostKeySha256(fingerprint : String)

Arguments

fingerprint
Base64 SHA-256 host key fingerprint, or an empty string to clear it

Description

Pins the SSH host key for |sftp://| transfers. The fingerprint is the base64-encoded SHA-256 digest of the server's public host key -- the same string OpenSSH prints after the |SHA256:| prefix, and the one an administrator can read off the server with |ssh-keygen -lf| on its public host key file. Supply it with or without that prefix. A server presenting any other key is rejected and the transfer fails.

This is the simplest way to verify an SFTP server: it is one string, it needs no file on disk, and it can be read off the server once and stored with the script. setKnownHosts is the alternative for callers who already keep an OpenSSH known_hosts file. Passing an empty string clears the pin.

SFTP transfers require one of the two: with neither set, download, upload and rename fail without connecting, rather than trusting whatever key the server offers. The single exception is |setVerifyServer(false)|, which waives the requirement and makes this setting a no-op.

FileTransfer.setKnownHosts

function FileTransfer.setKnownHosts(path : String)

Arguments

path
Path to an OpenSSH known_hosts file, or an empty string to clear it

Description

Points the SSH layer at an OpenSSH-format known_hosts file holding the public host keys of the servers this object is allowed to talk to, for |sftp://| transfers. Only an exact match is accepted: a server whose key is absent from the file, or present under a different value, is rejected and the transfer fails.

Use this when the caller already maintains a known_hosts file; setHostKeySha256 pins a single server without one. Passing an empty string clears the setting.

SFTP transfers require one of the two: with neither set, download, upload and rename fail without connecting, rather than trusting whatever key the server offers. The single exception is |setVerifyServer(false)|, which waives the requirement and makes this setting a no-op.

FileTransfer.setSecure

function FileTransfer.setSecure(value : Boolean)

Arguments

value
Specifying true turns on FTPS and false turns it off

Description

Turns FTPS on or off. When on, the connection is upgraded to TLS with the AUTH command before any credentials are sent, and both the control and data channels are encrypted; the transfer fails rather than continuing in the clear if the server does not support TLS. This is "explicit" FTPS and uses ordinary ftp:// urls on the usual port. For "implicit" FTPS, use an ftps:// url instead, which does not require this setting.

Note that FTPS is not SFTP: SFTP is a different protocol, carried over SSH. This setting has no effect on |sftp://| urls, which are encrypted by SSH itself -- see setHostKeySha256 and setKnownHosts for how an SFTP server is verified.

FileTransfer.setVerifyServer

function FileTransfer.setVerifyServer(value : Boolean)

Arguments

value
Specifying false turns verification off; true, or no argument at all, turns it back on

Description

Verification is ON by default and should stay on. Turning it off disables EVERY check that the server is who it claims to be: for |ftps://| and FTPS the TLS certificate chain and host name are no longer checked, and for |sftp://| the SSH host key is accepted whatever it is, so setHostKeySha256 and setKnownHosts stop having any effect. The connection is still encrypted, but an attacker who can redirect it can present their own certificate or host key, read everything sent -- including the password -- and pass the traffic through unchanged.

This exists for talking to a server whose credentials cannot be verified at all, typically a test box with a self-signed certificate or a freshly imaged host. Prefer setCaInfo for a private certificate authority and setHostKeySha256 for an SSH host key: both let a specific server be trusted while everything else is still rejected. Turn this off only for a host you would be willing to hand the password to over an unauthenticated link.

FileTransfer.upload

function FileTransfer.upload(source_filename : String, destination_url : String) : Boolean

Arguments

source_filename
The filename to upload
destination_url
The destination location of the upload

Returns

Returns true upon successful completion, otherwise false if an error occurred.

Description

Calling this method uploads a file from the local computer to an FTP or an SFTP server. The destination url specified in the destination_url parameter takes the following format: sftp://username:password@servername.domain.com/path/to/filename.ext -- If you wish to use the ftp protocol, change the protocol identifier before the first colon in the url string.

An |sftp://| url requires the server's host key to have been supplied first, with setHostKeySha256 or setKnownHosts; with neither, this method fails without connecting.

FileTransfer.finished