or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authorizers.mdfilesystems.mdhandlers.mdindex.mdioloop.mdservers.mdutilities.md

handlers.mddocs/

0

# FTP Protocol Handlers

1

2

Main FTP protocol implementation providing comprehensive RFC-959 compliant FTP server functionality with 40+ FTP commands, SSL/TLS encryption, data transfer management, and extensive customization options through callback hooks and configurable parameters.

3

4

## Capabilities

5

6

### Main FTP Handler

7

8

Core FTP protocol interpreter implementing the complete FTP command set with configurable behavior and extensive callback hooks for customization.

9

10

```python { .api }

11

class FTPHandler:

12

# Core configuration attributes

13

authorizer: 'Authorizer' = DummyAuthorizer()

14

active_dtp: type = 'ActiveDTP'

15

passive_dtp: type = 'PassiveDTP'

16

dtp_handler: type = 'DTPHandler'

17

abstracted_fs: type = 'AbstractedFS'

18

proto_cmds: dict = {} # FTP command definitions

19

20

# Session and security settings

21

timeout: int = 300

22

banner: str = f"pyftpdlib {__ver__} ready."

23

max_login_attempts: int = 3

24

permit_foreign_addresses: bool = False

25

permit_privileged_ports: bool = False

26

27

# Network configuration

28

masquerade_address: str = None

29

masquerade_address_map: dict = {}

30

passive_ports: range = None

31

32

# Performance settings

33

use_gmt_times: bool = True

34

use_sendfile: bool = True # Use sendfile() system call if available

35

tcp_no_delay: bool = True # Disable Nagle algorithm

36

37

# Character encoding

38

encoding: str = "utf8"

39

unicode_errors: str = 'replace'

40

41

# Logging configuration

42

log_prefix: str = '%(remote_ip)s:%(remote_port)s-[%(username)s]'

43

auth_failed_timeout: int = 3

44

45

def __init__(self, conn, server, ioloop=None):

46

"""

47

Initialize FTP session handler.

48

49

Parameters:

50

- conn: client socket connection

51

- server: FTPServer instance

52

- ioloop: IOLoop instance (optional)

53

"""

54

55

# Session management

56

def handle(self):

57

"""Send welcome banner to client."""

58

59

def handle_max_cons(self):

60

"""Handle maximum connections limit reached."""

61

62

def handle_max_cons_per_ip(self):

63

"""Handle maximum connections per IP limit reached."""

64

65

def handle_timeout(self):

66

"""Handle session timeout."""

67

68

def process_command(self, cmd, *args, **kwargs):

69

"""

70

Process FTP command from client.

71

72

Parameters:

73

- cmd: FTP command name

74

- *args: command arguments

75

- **kwargs: additional options

76

"""

77

78

def flush_account(self):

79

"""Reset user session state."""

80

81

def run_as_current_user(self, function, *args, **kwargs):

82

"""Execute function with current user privileges."""

83

84

# Connection event callbacks

85

def on_connect(self):

86

"""Called when client connects."""

87

88

def on_disconnect(self):

89

"""Called when client disconnects."""

90

91

# Authentication event callbacks

92

def on_login(self, username):

93

"""Called when user successfully logs in."""

94

95

def on_login_failed(self, username):

96

"""Called when user login fails."""

97

98

def on_logout(self, username):

99

"""Called when user logs out."""

100

101

# File transfer event callbacks

102

def on_file_sent(self, file):

103

"""Called when file transfer (RETR) completes successfully."""

104

105

def on_file_received(self, file):

106

"""Called when file transfer (STOR/APPE) completes successfully."""

107

108

def on_incomplete_file_sent(self, file):

109

"""Called when file transfer (RETR) is interrupted."""

110

111

def on_incomplete_file_received(self, file):

112

"""Called when file transfer (STOR/APPE) is interrupted."""

113

114

# Authentication commands

115

def ftp_USER(self, line):

116

"""USER command - specify username."""

117

118

def ftp_PASS(self, line):

119

"""PASS command - specify password."""

120

121

def ftp_QUIT(self, line):

122

"""QUIT command - terminate session."""

123

124

# Data connection commands

125

def ftp_PORT(self, line):

126

"""PORT command - specify client port for active mode."""

127

128

def ftp_EPRT(self, line):

129

"""EPRT command - extended PORT for IPv6."""

130

131

def ftp_PASV(self, line):

132

"""PASV command - enter passive mode."""

133

134

def ftp_EPSV(self, line):

135

"""EPSV command - extended PASV for IPv6."""

136

137

# Directory listing commands

138

def ftp_LIST(self, path):

139

"""LIST command - detailed directory listing."""

140

141

def ftp_NLST(self, path):

142

"""NLST command - name-only directory listing."""

143

144

def ftp_MLST(self, path):

145

"""MLST command - machine-readable file info."""

146

147

def ftp_MLSD(self, path):

148

"""MLSD command - machine-readable directory listing."""

149

150

# File transfer commands

151

def ftp_RETR(self, file):

152

"""RETR command - retrieve/download file."""

153

154

def ftp_STOR(self, file):

155

"""STOR command - store/upload file."""

156

157

def ftp_APPE(self, file):

158

"""APPE command - append to file."""

159

160

def ftp_STOU(self, line):

161

"""STOU command - store file with unique name."""

162

163

def ftp_REST(self, line):

164

"""REST command - set file restart position."""

165

166

def ftp_ABOR(self, line):

167

"""ABOR command - abort current transfer."""

168

169

# Directory navigation commands

170

def ftp_CWD(self, path):

171

"""CWD command - change working directory."""

172

173

def ftp_CDUP(self, path):

174

"""CDUP command - change to parent directory."""

175

176

def ftp_PWD(self, line):

177

"""PWD command - print working directory."""

178

179

# File/directory management commands

180

def ftp_MKD(self, path):

181

"""MKD command - create directory."""

182

183

def ftp_RMD(self, path):

184

"""RMD command - remove directory."""

185

186

def ftp_DELE(self, path):

187

"""DELE command - delete file."""

188

189

def ftp_RNFR(self, path):

190

"""RNFR command - rename from (source)."""

191

192

def ftp_RNTO(self, path):

193

"""RNTO command - rename to (destination)."""

194

195

# File information commands

196

def ftp_SIZE(self, path):

197

"""SIZE command - get file size."""

198

199

def ftp_MDTM(self, path):

200

"""MDTM command - get file modification time."""

201

202

def ftp_MFMT(self, path):

203

"""MFMT command - set file modification time."""

204

205

# Transfer parameter commands

206

def ftp_TYPE(self, line):

207

"""TYPE command - set transfer type (ASCII/Binary)."""

208

209

def ftp_MODE(self, line):

210

"""MODE command - set transfer mode."""

211

212

def ftp_STRU(self, line):

213

"""STRU command - set file structure."""

214

215

# Server information commands

216

def ftp_STAT(self, line):

217

"""STAT command - server/transfer status."""

218

219

def ftp_FEAT(self, line):

220

"""FEAT command - list server features."""

221

222

def ftp_HELP(self, line):

223

"""HELP command - display help information."""

224

225

# SITE commands (server-specific)

226

def ftp_SITE_CHMOD(self, path):

227

"""SITE CHMOD command - change file permissions."""

228

229

def ftp_SITE_HELP(self, line):

230

"""SITE HELP command - SITE command help."""

231

```

232

233

### SSL/TLS FTP Handler

234

235

FTP handler with SSL/TLS encryption support providing secure FTP (FTPS) capabilities with flexible security requirements.

236

237

```python { .api }

238

class TLS_FTPHandler(FTPHandler):

239

# SSL/TLS configuration

240

tls_control_required: bool = False

241

tls_data_required: bool = False

242

certfile: str = None

243

keyfile: str = None

244

ssl_protocol = None # SSL.TLS_SERVER_METHOD

245

ssl_options = None # SSL options (no SSLv2/SSLv3/compression)

246

ssl_context = None # Pre-configured SSL context

247

248

# Additional SSL/TLS commands

249

def ftp_AUTH(self, line):

250

"""AUTH command - initiate SSL/TLS handshake."""

251

252

def ftp_PBSZ(self, line):

253

"""PBSZ command - set protection buffer size."""

254

255

def ftp_PROT(self, line):

256

"""PROT command - set data channel protection level."""

257

258

def secure_connection(self, ssl_context):

259

"""Upgrade connection to SSL/TLS."""

260

261

def handle_ssl_established(self):

262

"""Called when SSL handshake completes."""

263

264

def handle_ssl_shutdown(self):

265

"""Called when SSL connection shuts down."""

266

267

def handle_failed_ssl_handshake(self):

268

"""Called when SSL handshake fails."""

269

```

270

271

### Data Transfer Protocol Handlers

272

273

Classes managing FTP data connections for file transfers, supporting both active and passive modes with optional SSL/TLS encryption.

274

275

```python { .api }

276

class DTPHandler:

277

# Transfer configuration

278

timeout: int = 300

279

ac_in_buffer_size: int = 65536

280

ac_out_buffer_size: int = 65536

281

282

def __init__(self, sock, cmd_channel):

283

"""

284

Initialize data transfer handler.

285

286

Parameters:

287

- sock: data connection socket

288

- cmd_channel: associated FTP command channel

289

"""

290

291

def use_sendfile(self):

292

"""Check if sendfile() optimization can be used."""

293

294

def push(self, data):

295

"""Send data to client."""

296

297

def push_with_producer(self, producer):

298

"""Send data using producer pattern."""

299

300

def enable_receiving(self, type, cmd):

301

"""Enable data receiving mode for uploads."""

302

303

def get_transmitted_bytes(self):

304

"""Get number of bytes transferred."""

305

306

def get_elapsed_time(self):

307

"""Get transfer duration in seconds."""

308

309

def transfer_in_progress(self):

310

"""Check if transfer is currently active."""

311

312

def handle_read(self):

313

"""Handle incoming data during upload."""

314

315

def handle_timeout(self):

316

"""Handle stalled transfer timeout."""

317

318

def close(self):

319

"""Close data connection and cleanup."""

320

321

class ThrottledDTPHandler(DTPHandler):

322

# Bandwidth limiting

323

read_limit: int = 0 # Max read bytes/sec (0 = unlimited)

324

write_limit: int = 0 # Max write bytes/sec (0 = unlimited)

325

auto_sized_buffers: bool = True

326

327

class TLS_DTPHandler(DTPHandler):

328

"""SSL/TLS enabled data transfer handler."""

329

330

class PassiveDTP:

331

timeout: int = 30

332

backlog: int = None

333

334

def __init__(self, cmd_channel, extmode=False):

335

"""Initialize passive data connection listener."""

336

337

def handle_accepted(self, sock, addr):

338

"""Handle client connection to passive port."""

339

340

class ActiveDTP:

341

timeout: int = 30

342

343

def __init__(self, ip, port, cmd_channel):

344

"""Initialize active data connection to client."""

345

346

def handle_connect(self):

347

"""Handle successful connection to client."""

348

```

349

350

### Data Producers

351

352

Producer classes for efficient file transfer using the producer/consumer pattern.

353

354

```python { .api }

355

class FileProducer:

356

buffer_size: int = 65536

357

358

def __init__(self, file, type):

359

"""

360

Initialize file producer.

361

362

Parameters:

363

- file: file object to read from

364

- type: transfer type ('i' for binary, 'a' for ASCII)

365

"""

366

367

def more(self):

368

"""Read and return next chunk of file data."""

369

370

class BufferedIteratorProducer:

371

loops: int = 20

372

373

def __init__(self, iterator):

374

"""Initialize producer from iterator."""

375

376

def more(self):

377

"""Get next batch from iterator."""

378

```

379

380

## Exception Classes

381

382

```python { .api }

383

class _FileReadWriteError(OSError):

384

"""File read/write errors during transfer."""

385

386

class _GiveUpOnSendfile(Exception):

387

"""Fallback from sendfile() to regular send()."""

388

```

389

390

## Constants

391

392

```python { .api }

393

CR_BYTE: int # Carriage return byte value

394

proto_cmds: dict # FTP command definitions with properties

395

```

396

397

## Usage Examples

398

399

### Basic FTP Handler Setup

400

401

```python

402

from pyftpdlib.handlers import FTPHandler

403

from pyftpdlib.authorizers import DummyAuthorizer

404

405

# Configure authorizer

406

authorizer = DummyAuthorizer()

407

authorizer.add_user("user", "pass", "/home/user", perm="elradfmwMT")

408

409

# Configure handler

410

handler = FTPHandler

411

handler.authorizer = authorizer

412

handler.banner = "Welcome to my FTP server"

413

handler.timeout = 600

414

```

415

416

### SSL/TLS FTP Server

417

418

```python

419

from pyftpdlib.handlers import TLS_FTPHandler

420

421

class MyTLS_FTPHandler(TLS_FTPHandler):

422

certfile = "/path/to/certificate.pem"

423

keyfile = "/path/to/private_key.pem"

424

tls_control_required = True

425

tls_data_required = True

426

427

handler = MyTLS_FTPHandler

428

handler.authorizer = authorizer

429

```

430

431

### Custom Handler with Callbacks

432

433

```python

434

class CustomFTPHandler(FTPHandler):

435

def on_connect(self):

436

print(f"Client connected from {self.remote_ip}")

437

438

def on_login(self, username):

439

print(f"User {username} logged in successfully")

440

441

def on_file_sent(self, file):

442

print(f"File {file} sent to {self.username}")

443

444

def on_file_received(self, file):

445

print(f"File {file} received from {self.username}")

446

447

def on_logout(self, username):

448

print(f"User {username} logged out")

449

450

handler = CustomFTPHandler

451

handler.authorizer = authorizer

452

```

453

454

### Performance Optimization

455

456

```python

457

class OptimizedFTPHandler(FTPHandler):

458

# Enable performance optimizations

459

use_sendfile = True # Use sendfile() for uploads

460

tcp_no_delay = True # Disable Nagle algorithm

461

462

# Configure timeouts

463

timeout = 300 # 5 minute session timeout

464

auth_failed_timeout = 1 # Fast auth failure response

465

466

# Buffer sizes for data transfers

467

dtp_handler = ThrottledDTPHandler

468

469

# Configure bandwidth limits

470

class BandwidthLimitedDTPHandler(ThrottledDTPHandler):

471

read_limit = 1024 * 100 # 100 KB/s download limit

472

write_limit = 1024 * 50 # 50 KB/s upload limit

473

474

handler = OptimizedFTPHandler

475

handler.dtp_handler = BandwidthLimitedDTPHandler

476

```

477

478

### Network Configuration

479

480

```python

481

class NetworkConfiguredHandler(FTPHandler):

482

# NAT/Firewall configuration

483

masquerade_address = "203.0.113.10" # External IP for PASV

484

passive_ports = range(50000, 50099) # PASV port range

485

permit_foreign_addresses = False # Block FXP transfers

486

permit_privileged_ports = False # Block privileged ports

487

488

handler = NetworkConfiguredHandler

489

handler.authorizer = authorizer

490

```

491

492

### Logging Configuration

493

494

```python

495

class LoggingFTPHandler(FTPHandler):

496

log_prefix = '[%(asctime)s] %(remote_ip)s:%(remote_port)s-[%(username)s]'

497

498

def process_command(self, cmd, *args, **kwargs):

499

print(f"Command: {cmd} {' '.join(args) if args else ''}")

500

return super().process_command(cmd, *args, **kwargs)

501

502

handler = LoggingFTPHandler

503

handler.authorizer = authorizer

504

```

505

506

### Custom Command Implementation

507

508

```python

509

class ExtendedFTPHandler(FTPHandler):

510

def ftp_SITE_USAGE(self, line):

511

"""Custom SITE USAGE command."""

512

# Implementation here

513

self.respond("200 Disk usage: 50% of 1TB")

514

515

# Add to proto_cmds to register command

516

proto_cmds = FTPHandler.proto_cmds.copy()

517

proto_cmds['SITE USAGE'] = dict(

518

perm=None, auth=True, help='Syntax: SITE USAGE (show disk usage)'

519

)

520

521

handler = ExtendedFTPHandler

522

handler.authorizer = authorizer

523

```