Add support for RFC 2389 (FEAT) and RFC 2640 (UTF8) to ftpd(8).

The support for RFC 2640 (UTF8) is optional and rudimentary.
The server just advertises its capability to handle UTF-8 file
names and relies on its own 8-bit cleanness, as well as on
the backward compatibility of UTF-8 with ASCII.  So uploaded
files will have UTF-8 names, but the initial server contents
should be prepared in UTF-8 by hand, no on-the-fly conversion
of file names will be done.

PR:		bin/111714
Submitted by:	Zhang Weiwu <see email in the PR>
MFC after:	1 week
This commit is contained in:
Yaroslav Tykhiy 2007-04-18 22:43:39 +00:00
parent f1753e0585
commit 2ea4228214
3 changed files with 45 additions and 3 deletions

View File

@ -95,6 +95,7 @@ extern char proctitle[];
extern int usedefault;
extern char tmpline[];
extern int readonly;
extern int assumeutf8;
extern int noepsv;
extern int noretr;
extern int noguestretr;
@ -135,7 +136,7 @@ extern int epsvall;
ABOR DELE CWD LIST NLST SITE
STAT HELP NOOP MKD RMD PWD
CDUP STOU SMNT SYST SIZE MDTM
LPRT LPSV EPRT EPSV
LPRT LPSV EPRT EPSV FEAT
UMASK IDLE CHMOD MDFIVE
@ -687,6 +688,25 @@ cmd
if ($4 != NULL)
free($4);
}
| FEAT CRLF
{
lreply(211, "Extensions supported:");
#if 0
/* XXX these two keywords are non-standard */
printf(" EPRT\r\n");
if (!noepsv)
printf(" EPSV\r\n");
#endif
printf(" MDTM\r\n");
printf(" REST STREAM\r\n");
printf(" SIZE\r\n");
if (assumeutf8) {
/* TVFS requires UTF8, see RFC 3659 */
printf(" TVFS\r\n");
printf(" UTF8\r\n");
}
reply(211, "End.");
}
| SYST check_login CRLF
{
if ($2) {
@ -1112,6 +1132,7 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */
{ "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" },
{ "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" },
{ "SYST", SYST, ARGS, 1, "(get type of operating system)" },
{ "FEAT", FEAT, ARGS, 1, "(get extended features)" },
{ "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" },
{ "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
{ "NOOP", NOOP, ARGS, 1, "" },

View File

@ -40,7 +40,7 @@
.Nd Internet File Transfer Protocol server
.Sh SYNOPSIS
.Nm
.Op Fl 46ADdEhMmOoRrSUvW
.Op Fl 468ADdEhMmOoRrSUvW
.Op Fl l Op Fl l
.Op Fl a Ar address
.Op Fl P Ar port
@ -78,6 +78,21 @@ When
is specified, accept connections via
.Dv AF_INET6
socket.
.It Fl 8
The server is running in transparent UTF-8 mode.
That is, it just encourages RFC\ 2640 compliant clients to send
paths encoded in UTF-8 in their commands.
In particular, the names of files uploaded by such clients will
have UTF-8 encoding.
The clients will also assume that server replies and existing file
names have UTF-8 encoding, too.
The names of files preloaded to the server should meet this expectation
for the clients to present the correct file names to their users.
Own messages of
.Nm
are always encoded in ASCII, which in fact is a subset of UTF-8.
.Pp
Note that this option does not make the server do any encoding conversion.
.It Fl A
Allow only anonymous ftp access.
.It Fl a
@ -250,6 +265,7 @@ is specified.
.It DELE Ta "delete a file [RW]"
.It EPRT Ta "specify data connection port, multiprotocol"
.It EPSV Ta "prepare for server-to-server transfer, multiprotocol"
.It FEAT Ta "give information on extended features of server"
.It HELP Ta "give help information"
.It LIST Ta "give list files in a directory" Pq Dq Li "ls -lgA"
.It LPRT Ta "specify data connection port, multiprotocol"

View File

@ -128,6 +128,7 @@ int logging;
int restricted_data_ports = 1;
int paranoid = 1; /* be extra careful about security */
int anon_only = 0; /* Only anonymous ftp allowed */
int assumeutf8 = 0; /* Assume that server file names are in UTF-8 */
int guest;
int dochroot;
char *chrootdir;
@ -308,7 +309,7 @@ main(int argc, char *argv[], char **envp)
openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
while ((ch = getopt(argc, argv,
"46a:AdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) {
"468a:AdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) {
switch (ch) {
case '4':
family = (family == AF_INET6) ? AF_UNSPEC : AF_INET;
@ -318,6 +319,10 @@ main(int argc, char *argv[], char **envp)
family = (family == AF_INET) ? AF_UNSPEC : AF_INET6;
break;
case '8':
assumeutf8 = 1;
break;
case 'a':
bindname = optarg;
break;