12#include <QAbstractSocket>
15#include <QSslConfiguration>
23namespace QFtpCompatInternal {
struct Command; }
69class QFtpCompat :
public QObject
160 explicit QFtpCompat(QObject *parent =
nullptr);
199 int open(
const QUrl &url,
230 int get(
const QUrl &url, QIODevice *dst,
241 int get(
const QUrl &url, QByteArray *dst,
252 int put(
const QUrl &url,
const QByteArray &data,
267 int put(
const QUrl &url, QIODevice *src,
284 int list(
const QUrl &url);
291 int mkdir(
const QUrl &url);
298 int rmdir(
const QUrl &url);
305 int remove(
const QUrl &url);
314 int rename(
const QUrl &from,
const QUrl &to);
321 int cd(
const QUrl &url);
349 [[nodiscard]] QString
errorString() const noexcept;
351 [[nodiscard]]
int currentId() const noexcept;
386 void clearPendingCommands();
450 void onControlConnected();
451 void onControlReadyRead();
452 void onControlError(QAbstractSocket::SocketError socketError);
454 void onDataConnected();
455 void onDataReadyRead();
456 void onDataDisconnected();
457 void onDataError(QAbstractSocket::SocketError socketError);
458 void onTransferCompleted();
464 enum class ControlState {
472 WaitingForTransferStartAck,
474 WaitingForTransferCompleteAck,
481 WaitingForAuthTlsAck,
484 WaitingForControlHandshake,
485 WaitingForDataHandshake,
491 int enqueue(QFtpCompatInternal::Command *cmd);
492 void startNextCommand();
493 void startCurrentCommand();
495 void finalizeCommand(
bool hadError);
500 void sendCommand(
const QByteArray &cmd);
501 void processResponse(
int code,
const QByteArray &message);
503 void beginDataTransfer();
504 void sendTypeCommand();
506 void sendDataTransferCommand();
507 void startDataChannelEncryption();
509 [[nodiscard]]
bool parsePasvAddress(
const QByteArray &msg,
510 QString &host, quint16 &port)
const;
512 void setError(
Error err,
const QString &detail);
513 void setState(
State s);
515 [[nodiscard]]
bool isDataTransferCommand() const noexcept;
520 QSslSocket *m_control{
nullptr};
521 QSslSocket *m_data{
nullptr};
524 QSslConfiguration m_sslConfig{QSslConfiguration::defaultConfiguration()};
526 QByteArray m_dataReadBuf;
529 ControlState m_ctrlState{ControlState::Idle};
531 QString m_errorString;
537 QFtpCompatInternal::Command *m_current{
nullptr};
538 QQueue<QFtpCompatInternal::Command *> m_queue;
543 bool m_dataChannelClosed{
false};
544 bool m_ctrlTransferComplete{
false};
546 bool m_abortPending{
false};
548 qint64 m_downloadReceived{0};
549 qint64 m_uploadTotal{0};
550 qint64 m_uploadTransferred{0};
Represents a single entry from an FTP LIST response.
Asynchronous FTP client for Qt6.
int currentId() const noexcept
ID of the command currently being executed, or -1 if idle.
int remove(const QUrl &url)
Deletes a file on the server (DELE).
void abort()
Aborts the current data transfer and clears the command queue.
State state() const noexcept
Current connection state.
void done(bool error)
Emitted when all queued commands have completed.
int pwd()
Requests the current working directory path (PWD).
int open(const QUrl &url, EncryptionMode mode=EncryptionMode::None)
Connects to the FTP server and logs in using the URL credentials.
TransferMode
FTP data channel mode.
@ Active
PORT – server opens the data connection (not implemented).
@ Passive
PASV – client opens the data connection (firewall-friendly).
int rmdir(const QUrl &url)
Removes an empty directory on the server (RMD).
int put(const QUrl &url, const QByteArray &data, TransferType type=TransferType::Binary)
Uploads data to the remote path in url.
int rawCommand(const QString &command)
Sends an arbitrary FTP command on the control channel.
void stateChanged(QFtpCompat::State newState)
Emitted when the connection state changes.
int cd(const QUrl &url)
Changes the current working directory (CWD).
void rawCommandReply(int code, QString detail)
Emitted for rawCommand() responses and pwd() results.
EncryptionMode
FTP encryption mode. \value None Plain FTP – default, fully backward-compatible. \value Explicit Expl...
int mkdir(const QUrl &url)
Creates a directory on the server (MKD).
void commandStarted(int id)
Emitted when a queued command begins executing.
int list(const QUrl &url)
Requests a directory listing (LIST).
Error
Error codes set on the most recent failed command.
@ TlsHandshakeFailed
TLS handshake failed on control or data channel.
@ FileNotFound
Server returned 550 for a file operation.
@ NotConnected
Command issued without an active connection.
@ NetworkError
Generic socket error.
@ PermissionDenied
Server returned 553 / 550 permission error.
@ LoginFailed
USER/PASS rejected by the server.
@ NotLoggedIn
Command requires authentication.
@ NoError
No error since the last successful command.
@ Aborted
Operation cancelled by abort().
@ ServerError
Unexpected server response code.
@ LocalFileError
Could not open or write to the local file/device.
@ ConnectionRefused
Server actively refused the TCP connection.
@ UnknownError
Catch-all for unclassified errors.
@ TransferFailed
Data channel closed before transfer completed.
@ ParseError
Failed to parse a server response (PASV, LIST).
@ AuthTlsRejected
Server rejected the AUTH TLS command.
@ NetworkTimeout
No activity within the inactivity timeout.
@ HostNotFound
DNS resolution failed.
void listInfo(QFtpCompatDirEntry entry)
Emitted once per entry during a list() command.
void close()
Sends QUIT and closes the connection gracefully.
int rename(const QUrl &from, const QUrl &to)
Renames or moves a file on the server (RNFR + RNTO).
void setSslConfiguration(const QSslConfiguration &config)
Removes all pending (not yet started) commands from the queue.
Error error() const noexcept
Error code set by the most recent failed command.
void commandFinished(int id, bool error)
Emitted when a command completes (successfully or with error).
int get(const QUrl &url, QIODevice *dst, TransferType type=TransferType::Binary)
Downloads a remote file into dst.
void sslErrors(const QList< QSslError > &errors)
Emitted when SSL/TLS errors occur.
State
High-level connection state.
@ Unconnected
No TCP connection established.
@ Connected
TCP connected, waiting for server greeting (220).
@ Closing
QUIT sent, waiting for server acknowledgement.
@ Connecting
TCP connect in progress.
@ LoggedIn
Authenticated; ready to accept commands.
QSslConfiguration sslConfiguration() const
Returns the current SSL configuration.
bool hasPendingCommands() const noexcept
true if commands are waiting in the queue.
QString errorString() const noexcept
Verbose, human-readable description of the last error.
TransferType
FTP data representation type (RFC 959 §3.1.1).
@ Binary
TYPE I – raw binary (8-bit) transfer. Fully implemented.
@ Ascii
TYPE A – text transfer. Protocol-level TYPE sent; no CRLF transform (TODO).
void dataTransferProgress(qint64 bytesTransferred, qint64 bytesTotal)
Emitted periodically during data transfers.
FTP directory entry returned by QFtpCompat::list().