Опыт применения REXX FTP API
Автор: VicTor Smirnoff
Дата: апрель 2010
Источник: https://www.halfos.ru/
Данную книгу можно рассматривать как дополнение к переводу книги "Open Object REXX: Библиотека классов RxFtp. Справочник" и она является более ранним материалом, посвящённый исключительно полуосевой библиотеке функций RxFTP.
«В отличие от ooRexx, где лицензионные ограничения не помешали мне выполнить прямой перевод документации, здесь представлены результаты некоторого исследования поведения функций OS/2 REXX FTP API, что, конечно же, потребовало включения в материал и полного описания всех функций :)», говорит VicTor Smirnoff о своей книге.
Прочитать книгу в интернете, можно на сайте автора по этой ссылке.
Скачать книгу в формате doc, можно по этой ссылке.
Оглавление:
- Опыт применения REXX FTP API
- Введение
- Установка
- Коды возврата
- Функции
- Замечания по применению
- Послесловие
1. Предисловие.
Данная работа посвящена практическим особенностям использования REXX FTP API и основана на опыте, имеющемся у автора.
В ней подробно разобрана работа каждой функции библиотеки, реализующей REXX FTP API, описаны особенности и даны рекомендации для практического применения.
В качестве примеров приведены тексты законченных работоспособных программ. Работоспособность программ проверена на библиотеке rxFtp версии 2.1.
Если оригинальная документация противоречила практике применения, то такие случаи отмечены особо. Также отмечены ошибки и неточности, встреченные в оригинальной документации.
Сообщения об обнаруженных ошибках и неточностях будут с благодарностью приняты автором.
2. Введение.
Функции REXX FTP API обеспечивают доступ к FTP из программ на языке REXX, используя OS/2 FTP API. Поскольку названия функций REXX FTP API созвучны подкомандам FTP, то читателю, знакомому с основами FTP, не составит труда ориентироваться в них.
Примечание:
Описание подкоманд FTP можно найти в Руководстве по TCP/IP (TCP/IP Guide).
Описание функций FTP API можно найти в Описании команд TCP/IP (TCP/IP Command Reference).
3. Установка.
Работу REXX FTP API обеспечивает файл RXFTP.DLL. Этот модуль DLL должен быть размещён в одном из каталогов, перечисленных в операторе LIBPATH файла CONFIG.SYS.
Чтобы получить возможность использовать в программе функции REXX FTP API, необходимо включить в неё следующие инструкции:
rc = RxFuncAdd('FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs')
rc = FtpLoadFuncs( )
Чтобы выгрузить DLL, сначала надо выполнить вызов функции:
rc = FtpDropFuncs( )
Затем закрыть все сессии (CMD.EXE), в которых выполнялись программы REXX, использующие REXX FTP API. Библиотека будет освобождена системой и её можно будет удалить или заменить.
Примечание:
В некоторых случаях при возникновении ошибок библиотека может самостоятельно выводить на консоль диагностические сообщения. Например, возникновениеошибки FTPABORTможетсопровождатьсясообщением:
abort: The file or directory specified cannot be found.
Файл сообщений об ошибках DDE4.MSG должен находиться в одном из каталогов, перечисленных в переменной окружения DPATH, задаваемой в файле CONFIG.SYS.
4. Коды возврата.
Функции REXX FTP API сообщают вызывающей программе об успешном или неуспешном выполнении с помощью кодов возврата и специальной переменной FTPERRNO.
Но делают это совершенно разными способами:
- Большинство функций возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
- Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
- Функция FtpSys() возвращает одно из следующих значений:
Значение |
Описание |
<строка> |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
- Коды ошибок специальной переменной FTPERRNO смотри выше.
- Функция FtpVersion() всегда возвращает пустую строку ("").
Cпециальной переменной FTPERRNO всегда присваивается значение 0. - Функции FtpSetActiveMode(), FtpSetBinary() и FtpSetUser() возвращают одно из следующих значений:
Значение |
Описание |
1 |
нормальное завершение, ошибок нет |
0 |
ошибка, требуемое действие не выполнено |
- Cпециальной переменной FTPERRNO всегда присваивается значение 0.
- Функция FtpPing() возвращает одно из следующих значений:
Значение |
Описание |
<число> |
нормальное завершение, ошибок нет; |
PINGREPLY |
хост не отвечает |
PINGSOCKET |
невозможно получить сокет |
PINGPROTO |
неизвестный протокол ICMP |
PINGSEND |
передача завершилась с ошибкой |
PINGRECV |
приём завершился с ошибкой |
PINGHOST |
неизвестный хост |
Cпециальной переменной FTPERRNO всегда присваивается значение 0.- Функции FtpLoadFuncs() и FtpDropFuncs() возвращают 0 в случае успешного выполнения.
Значение специальной переменной FTPERRNO не изменяется.
5. Функции.
Названия большинства функций REXX FTP API созвучны соответствующим подкомандам FTP. Поэтому в них легко ориентироваться тем, кто знаком с основами FTP.
5.1. FtpAppend().
Копирует файл с вашей рабочей станции на сервер FTP, добавляя его в конец существующего на сервере файла.
Синтаксис:
rc = FtpAppend( localFile, remoteFile [, pMode] )
Параметры:
localFile
имя файла на локальной рабочей станции
remoteFile
имя файла на сервере FTP
pMode
(необязательный) строка, определяющая режим передачи файлов:
'Ascii' |
текстовый |
'Binary' |
двоичный |
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpAppend() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:
TYPE I=Binary, A=Ascii
PORT <данные> активный режим (по умолчанию)
APPE <содержимое параметра remoteFile>
или
TYPE I=Binary, A=Ascii
PASV пассивный режим
APPE <содержимое параметра remoteFile>
Если выполнение прошло успешно, то файл на сервере дописывается данными из локального файла.
Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).
Если параметр pMode опущен, то выбирается режим передачи файлов ранее установленный функцией FtpSetBinary() (по умолчанию, двоичный).
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует локальный файл на сервер, добавляя его в конец существующего на сервере файла.
/* rxFtpAppend.cmd - function example */
parse arg fromFile pHost '/' toFile
toFile = '/'||Strip( toFile );
if pHost = '' | toFile = '/' then do
say ''
say 'Usage: rxFtpAppend localfile host/remotefile'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( 0 )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpAppend( fromFile, toFile, 'Binary' )
if rc = -1 then do
say ''
say 'FtpAppend() FTPERRNO='||FTPERRNO
end
else do
say ''
say 'File '||fromFile||' appended to '||toFile||' OK'
end
rc = FtpLogoff()
/* end of file rxFtpAppend.cmd */
Примерырезультатоввыполнения:
X:>rxFtpAppend xxx.txt 127.0.0.1/Data/Ftp/Test.txt
File xxx.txt appended to /Data/Ftp/Test.txt OK
X:>rxFtpAppend C:\readme.txt 127.0.0.1/Data/Ftp/Test.txt
File C:\readme.txt appended to /Data/Ftp/Test.txt OK
Связанныефункции:
FtpDelete(), FtpGet(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpRename(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser()
5.2. FtpChDir().
Переходит в указанный каталог на сервере FTP и делает его текущим.
Синтаксис:
rc = FtpChDir( remoteDir )
Параметры:
remoteDir
имя каталога на сервере FTP
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpChDir() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем отправляет на сервер следующую последовательность команд:
CWD <содержимое параметра remoteDir>
Если выполнение прошло успешно, то текущим становится заданный каталог.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. А затем переходит в указанный каталог, делая его текущим на сервере.
/* rxFtpChDir.cmd - function example */
parse arg pHost '/' pDir
pDir = '/'||Strip( pDir );
if pHost = '' then do
say ''
say 'Usage: rxFtpChDir host[/dir]'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
if pDir \= '/' then do
rc = FtpChDir( pDir )
if rc = -1 then do
say ''
say 'FtpChDir() FTPERRNO='||FTPERRNO
signal halt
end
end
rc = FtpPwd( xPwd )
if rc = -1 then do
say ''
say 'FtpPwd() FTPERRNO='||FTPERRNO
end
else do
say ''
say xPwd
end
halt:
rc = FtpLogoff()
/* end of file rxFtpChDir.cmd */
Примерырезультатоввыполнения:
X:>rxFtpChDir 127.0.0.1/Data/Ftp/Public
"E:/data/ftp/public" is current directory.
X:>rxFtpChDir ftp.software.ibm.com/pub
"/pub" is current directory.
Связанныефункции:
FtpLogoff(), FtpMkDir(), FtpPwd(), FtpRmDir(), FtpSetUser()
5.3. FtpDelete().
Удаляет файл на сервере FTP.
Синтаксис:
rc = FtpDelete( remoteFile )
Параметры:
remoteFile
имя файла на сервере FTP
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpDelete() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем отправляет на сервер следующую последовательность команд:
DELE <содержимое параметра remoteFile>
Если выполнение прошло успешно, то файл на сервере удаляется.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя файла на сервере. Азатемудаляетуказанныйфайлнасервере.
/* rxFtpDelete.cmd - function example */
parse arg pHost '/' pFile
pFile = '/'||Strip( pFile );
if pHost = '' | pFile = '/' then do
say ''
say 'Usage: rxFtpDelete host/file'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpDelete( pFile )
if rc = -1 then do
say ''
say 'FtpDelete() FTPERRNO='||FTPERRNO
end
else do
say ''
say 'File '||pFile||' deleted OK'
end
rc = FtpLogoff()
/* end of file rxFtpDelete.cmd */
Примерырезультатоввыполнения:
X:>rxFtpDelete 127.0.0.1/Data/Ftp/Test.txt
File /Data/Ftp/Test.txt deleted OK
Связанные функции:
FtpAppend(), FtpGet(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpRename(), FtpSetUser()
5.4. FtpDir().
Получает список содержимого каталога сервера FTP в развернутом виде.
Синтаксис:
rc = FtpDir( pPattern, pStem )
Параметры:
pPattern
шаблон выборки содержимого каталога.
Может содержать имя файла, имя каталога или шаблон имени файла с использованием символов-заменителей '*' и '?'.
Назначение символов-заменителей стандартно:
'?' |
заменяет один любой символ в имени |
'*' |
заменяет любое количество символов в имени |
Если в шаблоне не указан путь, то он применяется к содержимому текущего каталога.
pStem
строка, определяющая имя-основу набора переменных, в который будут помещены результаты;
строка обязательно должна заканчиваться точкой ('.').
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpDir() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:
PORT <данные> активный режим (по умолчанию)
LIST <содержимое параметра pPattern>
или
PASV пассивный режим
LIST <содержимое параметра pPattern>
Если выполнение прошло успешно, то результатами заполняется набор переменных, имя-основа которых задаётся параметром pStem. Количество записей заносится в переменную из этого набора с индексом 0.
Например, пусть параметр pStem содержит строку 'files.'. Тогда в переменную files.0 будет помещено количество записей в списке, а сами записи будут последовательно помещены в переменные files.1, files.2 и т.д.
Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).
Примечание:
Строка, передаваемая в параметре pPattern, может содержать имя файла, имя каталога или шаблон имени файла с символами-заменителями '*' и '?'.
Казалось бы, указав в качестве шаблона строку '*', можно получить полный список содержимого текущего каталога.
Однако серверы FTP неоднозначно обрабатывают такой запрос. Некоторые выдают ожидаемый список содержимого текущего каталога. Другие выдают список, в котором отсутствуют имена подкаталогов. Третьи же, выдав список файлов текущего каталога, заодно выдают и списки содержимого подкаталогов текущего каталога.
Поэтому для получения списка содержимого текущего каталога лучше использовать строку '.' (т.е. имя текущего каталога) в качестве параметра.
Такой запрос все серверы FTP обрабатывают однозначно.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. А затем отображает содержимое указанного каталога.
/* rxFtpDir.cmd - function example */
parse arg pHost '/' pDir
pDir = '/'||Strip( pDir );
if pHost = '' then do
say ''
say 'Usage: rxFtpDir host[/dir]'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
if pDir \= '/' then do
rc = FtpChDir( pDir )
if rc = -1 then do
say ''
say 'FtpChDir() FTPERRNO='||FTPERRNO
signal halt
end
end
rc = FtpDir( '.', 'xFile.' )
if rc = -1 then do
say ''
say 'FtpDir() FTPERRNO='||FTPERRNO
end
else do
if xFile.0 > 0 then do
say ''
do i = 1 to xFile.0
say xFile.i
end
end
end
halt:
rc = FtpLogoff()
/* end of file rxFtpDir.cmd */
Примерырезультатоввыполнения:
X:>rxFtpDir 127.0.0.1
351 A 04-11-10 11:10 error.log
0 A DIR 04-12-10 08:59 Misc Tools
0 DIR 04-10-10 08:33 Public
50 04-10-10 08:34 ReadMe.txt
10 A 04-10-10 13:57 Test.txt
X:>rxFtpDir ftp.software.ibm.com/pub
total 520
-rw-r--r-- 1 102004493 201 192970 Jan 28 2001 00_Catalog
-rw-r--r-- 1 102004493 201 802 Jan 14 1999 00_index
-rw-r--r-- 1 102004493 201 595 Jan 14 1999 00_index.tab
-rw-r--r-- 1 102004493 201 2095 Jan 17 1999 User_Documentation
-rw-r--r-- 1 102004493 201 5890 Jan 19 1999 User_Documentation.990517.rsr
dr-xr-x--x 2 102004493 201 256 Aug 4 2008 bin
drwxrwxr-x 4 102004493 201 256 Jan 1 1980 comm
drwxrwxr-x 13 102004493 201 4096 Feb 9 08:02 demos
<...пропуск...>
Связанныефункции:
FtpLogoff(), FtpLs(), FtpSetActiveMode(), FtpSetUser()
5.5. FtpDropFuncs().
Сбрасывает регистрацию всех функций REXX FTP API и делает их недоступными для использования.
Синтаксис:
rc = FtpDropFuncs( )
Параметры:
Параметров нет.
Возвращаемое значение:
Функции FtpLoadFuncs() и FtpDropFuncs() возвращают 0 в случае успешного выполнения.
Значение специальной переменной FTPERRNO не изменяется.
Описание:
Сбрасывает регистрацию и делает недоступными для использования все функции REXX FTP API.
Затем, чтобы выгрузить DLL, обеспечивающий работу REXX FTP API, необходимо закрыть все сессии (CMD.EXE), в которых выполнялись программы REXX, использующие REXX FTP API. Библиотека будет освобождена системой и её можно будет удалить или заменить.
Пример:
Чтобы получить возможность выгрузить DLL, обеспечивающий работу REXX FTP API, необходимо включить в программу следующую инструкцию:
rc = FtpDropFuncs()
Связанные функции:
FtpLoadFuncs()
5.6. FtpGet().
Копирует одиночный файл с сервера FTP на рабочую станцию в указанный локальный файл.
Синтаксис:
rc = FtpGet( localFile, remoteFile [, pMode] )
Параметры:
localFile
имя файла на локальной рабочей станции
remoteFile
имя файла на сервере FTP
pMode
(необязательный) строка, определяющая режим передачи файлов:
'Ascii' |
текстовый |
'Binary' |
двоичный |
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpGet() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:
TYPE I=Binary, A=Ascii
PORT <данные> активный режим (по умолчанию)
RETR <содержимое параметра remoteFile>
или
TYPE I=Binary, A=Ascii
PASV пассивный режим
RETR <содержимое параметра remoteFile>
Если выполнение прошло успешно, то локальный файл переписывается данными из файла, полученного с сервера.
Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).
Если параметр pMode опущен, то выбирается режим передачи файлов ранее установленный функцией FtpSetBinary() (по умолчанию, двоичный).
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл с сервера на рабочую станцию в файл с указанным именем.
/* rxFtpGet.cmd - function example */
parse arg toFile pHost '/' fromFile
fromFile = '/'||Strip( fromFile );
if pHost = '' | toFile = '/' then do
say ''
say 'Usage: rxFtpGet localfile host/remotefile'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpGet( toFile, fromFile, 'Binary' )
if rc = -1 then do
say ''
say 'FtpGet() FTPERRNO='||FTPERRNO
end
else do
say ''
say 'File '||fromFile||' received to '||toFile||' OK'
end
rc = FtpLogoff()
/* end of file rxFtpGet.cmd */
Примерырезультатоввыполнения:
X:>rxFtpGet xxx.txt 127.0.0.1/Data/Ftp/Test.txt
File /Data/Ftp/Test.txt received to xxx.txt OK
X:>rxFtpGet C:\robots.txt ftp.software.ibm.com/robots.txt
File /robots.txt received to C:\robots.txt OK
Связанныефункции:
FtpAppend(), FtpDelete(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpRename(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser()
5.7. FtpLoadFuncs().
Регистрирует и делает доступными для использования все функции REXX FTP API.
Синтаксис:
rc = FtpLoadFuncs( [pMute] )
Параметры:
pMute
(необязательный) любое значение.
Если параметр задан, то подавляется вывод на консоль информации о библиотеке REXX FTP API.
Возвращаемое значение:
Функции FtpLoadFuncs() и FtpDropFuncs() возвращают 0 в случае успешного выполнения.
Значение специальной переменной FTPERRNO не изменяется.
Описание:
Регистрирует и делает доступными для использования все функции REXX FTP API.
Пример:
Чтобы получить возможность использовать в программе функции REXX FTP API, необходимо включить в неё следующие инструкции:
rc = RxFuncAdd('FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs')
rc = FtpLoadFuncs()
Пример вывода на консоль информации о библиотеке REXX FTP API:
RxFtp 2.1 - REXX function package for tcp/ip ftp
(c) Copyright International Business Machines Corporation 1993, 1999.
All Rights Reserved.
Связанныефункции:
FtpDropFuncs()
5.8. FtpLogoff().
Завершаетсессию FTP.
Синтаксис:
rc = FtpLogoff( )
Параметры:
Параметров нет.
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpLogoff() проверяет наличие соединения с сервером FTP.
И, если соединение с сервером FTP существует, то отправляет на сервер следующую последовательность команд:
QUIT
и закрывает соединение с сервером FTP.
Затем сбрасывает установки, сделанные функциями FtpSetBinary(), FtpSetActiveMode() и FtpSetUser(). Сессия FTP закрыта.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. Затем отправляет на сервер неполную команду, после чего сервер по тайм-ауту разрывает соединение. Соединение автоматически восстанавливается во время следующей попытки доступа к серверу. Затемсессиязакрываетсяиработастановитсяневозможна.
/* rxFtpLogoff.cmd - function example */
parse arg pHost
if pHost = '' then do
say ''
say 'Usage: rxFtpLogoff host'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpQuote( 'TYPE', xAnswer )
if rc = -1 then do
say ''
say 'FtpQuote() FTPERRNO='||FTPERRNO
end
else do
say ''
say xAnswer
end
rc = FtpSys( pSys )
if rc = -1 then do
say ''
say 'FtpSys() FTPERRNO='||FTPERRNO
end
else do
say ''
say pSys
end
rc = FtpLogoff()
if rc = -1 then do
say ''
say 'FtpLogoff() FTPERRNO='||FTPERRNO
end
rc = FtpSys( pSys )
if rc = -1 then do
say ''
say 'FtpSys() FTPERRNO='||FTPERRNO
end
else do
say ''
say pSys
end
/* end of file rxFtpLogoff.cmd */
Примерырезультатоввыполнения:
X:>rxFtpLogoff 127.0.0.1
FtpQuote() FTPERRNO=FTPCOMMAND
OS/2 operating system
FtpSys() FTPERRNO=FTPCOMMAND
Связанныефункции:
FtpAppend(), FtpChDir(), FtpDelete(), FtpDir(), FtpGet(), FtpLs(), FtpMkDir(), FtpPut(), FtpPutUnique(), FtpPwd(), FtpQuote(), FtpRename(), FtpRmDir(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser(), FtpSite(), FtpSys()
5.9. FtpLs().
Получает список содержимого каталога сервера FTP в сокращённом виде; в списке будут присутствуют только имена файлов и каталогов.
Синтаксис:
rc = FtpLs( pPattern, pStem )
Параметры:
pPattern
шаблон выборки содержимого каталога.
Может содержать имя файла, имя каталога или шаблон имени файла с использованием символов-заменителей '*' и '?'.
Назначение символов-заменителей стандартно:
'?' |
заменяет один любой символ в имени |
'*' |
заменяет любое количество символов в имени |
Если в шаблоне не указан путь, то он применяется к содержимому текущего каталога.
pStem
строка, определяющая имя-основу набора переменных, в который будут помещены результаты;
строка обязательно должна заканчиваться точкой ('.').
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpLs() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:
PORT <данные> активный режим (по умолчанию)
NLST <содержимое параметра pPattern>
или
PASV пассивный режим
NLST <содержимое параметра pPattern>
Если выполнение прошло успешно, то результатами заполняется набор переменных, имя-основа которых задаётся параметром pStem. Количество записей заносится в переменную из этого набора с индексом 0.
Например, пусть параметр pStem содержит строку 'files.'. Тогда в переменную files.0 будет помещено количество записей в списке, а сами записи будут последовательно помещены в переменные files.1, files.2 и т.д.
Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).
Примечание:
Строка, передаваемая в параметре pPattern, может содержать имя файла, имя каталога или шаблон имени файла с символами-заменителями '*' и '?'.
Казалось бы, указав в качестве шаблона строку '*', можно получить полный список содержимого текущего каталога.
Однако серверы FTP неоднозначно обрабатывают такой запрос. Некоторые выдают ожидаемый список содержимого текущего каталога. Другие выдают список, в котором отсутствуют имена подкаталогов. Третьи же, выдав список файлов текущего каталога, заодно выдают и списки содержимого подкаталогов текущего каталога.
Поэтому для получения списка содержимого текущего каталога лучше использовать строку '.' (т.е. имя текущего каталога) в качестве параметра.
Такой запрос все серверы FTP обрабатывают однозначно.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. Азатемотображаетсодержимоеуказанногокаталога.
/* rxFtpLs.cmd - function example */
parse arg pHost '/' pDir
pDir = '/'||Strip( pDir );
if pHost = '' then do
say ''
say 'Usage: rxFtpLs host[/dir]'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
if pDir \= '/' then do
rc = FtpChDir( pDir )
if rc = -1 then do
say ''
say 'FtpChDir() FTPERRNO='||FTPERRNO
signal halt
end
end
rc = FtpLs( '.', 'xFile.' )
if rc = -1 then do
say ''
say 'FtpLs() FTPERRNO='||FTPERRNO
end
else do
if xFile.0 > 0 then do
say ''
do i = 1 to xFile.0
say xFile.i
end
end
end
halt:
rc = FtpLogoff()
/* end of file rxFtpLs.cmd */
Примерырезультатоввыполнения:
X:>rxFtpLs 127.0.0.1
error.log
Misc Tools
Public
ReadMe.txt
Test.txt
X:>rxFtpLs ftp.software.ibm.com/pub
00_Catalog
00_index
00_index.tab
User_Documentation
User_Documentation.990517.rsr
dir_structure
dir_structure.990517.rsr
index.html
message.990517.rsr
Связанныефункции:
FtpLogoff(), FtpDir(), FtpSetActiveMode(), FtpSetUser()
5.10. FtpMkDir().
Создаёт новый каталог на сервере FTP.
Синтаксис:
rc = FtpMkDir( remoteDir )
Параметры:
remoteDir
имя каталога на сервере FTP
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpMkDir() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем отправляет на сервер следующую последовательность команд:
MKD <содержимое параметра remoteDir>
Если выполнение прошло успешно, то на сервере создаётся новый каталог.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. Затем создаёт новый каталог, делает его текущим и отображает его имя.
/* rxFtpMkDir.cmd - function example */
parse arg pHost '/' pDir
pDir = '/'||Strip( pDir );
if pHost = '' | pDir = '/' then do
say ''
say 'Usage: rxFtpMkDir host/dir'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpMkDir( pDir )
if rc = -1 then do
say ''
say 'FtpMkDir() FTPERRNO='||FTPERRNO
signal halt
end
rc = FtpChDir( pDir )
if rc = -1 then do
say ''
say 'FtpChDir() FTPERRNO='||FTPERRNO
signal halt
end
rc = FtpPwd( xPwd )
if rc = -1 then do
say ''
say 'FtpPwd() FTPERRNO='||FTPERRNO
end
else do
say ''
say xPwd
end
halt:
rc = FtpLogoff()
/* end of file rxFtpMkDir.cmd */
Примерырезультатоввыполнения:
X:>rxFtpMkDir 127.0.0.1/Data/Ftp/Other
"E:/data/ftp/other" is current directory.
Связанныефункции:
FtpChDir(), FtpLogoff(), FtpPwd(), FtpRmDir(), FtpSetUser()
5.11. FtpPing().
Проверяет доступность хоста.
Синтаксис:
rc = FtpPing( pHost, pLength )
Параметры:
pHost
имя или адрес хоста
pLength
длина порции данных в пакете ICMP (минимальное значение: 1)
Возвращаемое значение:
Функция FtpPing() возвращает одно из следующих значений:
Значение |
Описание |
<число> |
нормальное завершение, ошибок нет; |
PINGREPLY |
хост не отвечает |
PINGSOCKET |
невозможно получить сокет |
PINGPROTO |
неизвестный протокол ICMP |
PINGSEND |
передача завершилась с ошибкой |
PINGRECV |
приём завершился с ошибкой |
PINGHOST |
неизвестный хост |
Cпециальной переменной FTPERRNO всегда присваивается значение 0.
Описание:
Вполне самостоятельная функция, никак не связанная с остальными функциями REXX FTP API (за исключением FtpLoadFuncs() и FtpDropFuncs()). Более того, она даже не использует FTP.
Получив имя хоста в качестве параметра, FtpPing() посылает запрос на получение адреса хоста серверу DNS. Если сервер DNS в системе не определён, то для поиска адреса хоста используется файл TCPIP\ETC\HOSTS.
Затем FtpPing посылает указанному хосту одиночный пакет ICMP "запрос-отклика" ("echo-request") заданной длины и ожидает ответ опрашиваемой системы.
Получив ответ, возвращает в вызывающую функцию число - промежуток времени между посылкой запроса и получением ответа в миллисекундах. Если ответ не пришёл за определённое время, то возвращает код ошибки.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. А затем проверяет доступность указанного хоста (т.е. "пингует" его).
/* rxFtpPing.cmd - function example */
parse arg pHost .
if pHost = '' then do
say ''
say 'Usage: rxFtpPing host'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpPing( pHost, 64 )
if DataType(rc, 'N') then do
say ''
say pHost||' ping='||rc||'ms'
end
else do
say ''
say pHost||' error='||rc
end
/* end of file rxFtpPing.cmd */
Примерырезультатоввыполнения:
X:>rxFtpPing 127.0.0.1
127.0.0.1 ping=0ms
X:>rxFtpPing ftp.software.ibm.com
ftp.software.ibm.com error=PINGREPLY
Связанные функции:
Связанных функций нет.
5.12. FtpProxy().
Организует копирование файла напрямую с одного сервера на другой.
Синтаксис:
rc = FtpProxy( toHost, toUser, toPass, toAcct,
fromHost, fromUser, fromPass, fromAcct,
toFile, fromFile, pMode )
Параметры:
toHost
имя или адрес хоста-получателя
toUser
имя пользователя хоста-получателя
toPass
пароль пользователя хоста-получателя
toAcct
аккаунт пользователя хоста-получателя; если не требуется должна быть указана пустая строка
fromHost
имя или адрес хоста-отправителя
fromUser
имя пользователя хоста-отправителя
fromPass
пароль пользователя хоста-отправителя
fromAcct
аккаунт пользователя хоста-отправителя; если не требуется должна быть указана пустая строка
toFile
имя файла-назначения с указанием пути куда копируется файл
fromFile
имя файла-источника с указанием пути откуда копируется файл
pMode
строка, определяющая режим передачи файлов:
'Ascii' |
текстовый |
'Binary' |
двоичный |
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Вполне самостоятельная функция, никак не связанная с остальными функциями REXX FTP API (за исключением FtpLoadFuncs() и FtpDropFuncs()).
Получив имена хостов в качестве параметров, FtpProxy() посылает запросы на получение адресов хостов серверу DNS. Если сервер DNS в системе не определён, то для поиска адресов хостов используется файл TCPIP\ETC\HOSTS.
Затем FtpProxy() соединяется с серверами FTP, работающими на заданных хостах, и отправляет им команды в следующей последовательности:
Получатель Отправитель
------------------------------
USER
PASS
ACCT
PWD
TYPE I=Binary, A=Ascii
USER
PASS
ACCT
PWD
TYPE I=Binary, A=Ascii
PASV
PORT <данные,
которые
вернула
команда
PASV
переданная
источнику>
STOR
RETR
QUIT
QUIT
вынуждая сервер-получатель получить файл напрямую с сервера-отправителя.
Имя файла-назначения может отличаться от имени файла-источника.
Примечание:
В оригинальной документации отмечено, что параметр, определяющий режим передачи файлов не обязателен. Однако, если его опустить или задать неправильное значение, то FtpProxy() просто вернёт код возврата равный 0, не выполняя никаких действий.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имена или адреса хостов и имена исходного и сохраняемого файлов. А затем организует передачу файла напрямую между серверами.
/* rxFtpProxy.cmd - function example */
parse arg pTo pFrom .
parse var pTo toHost '/' toFile
parse var pFrom fromHost '/' fromFile
toFile = '/'||Strip( toFile )
fromFile = '/'||Strip( fromFile )
if toHost = '' | toFile = '/' | fromHost = '' | fromFile = '/' then do
say ''
say 'Usage: rxFtpProxy targetHost/targetFile sourceHost/sourceFile'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpProxy( toHost, 'anonymous', 'anonymous@guest.ftp', '', ,
fromHost, 'anonymous', 'anonymous@guest.ftp', '', ,
toFile, fromFile, 'Binary' )
if rc = -1 then do
say ''
say 'FtpProxy() FTPERRNO='||FTPERRNO
end
else do
say ''
say 'File transferred OK'
end
/* end of file rxFtpProxy.cmd */
Примерырезультатоввыполнения:
X:>rxFtpProxy 127.0.0.1/Data/Ftp/x.txt ftp.software.ibm.com/robots.txt
FtpProxy() FTPERRNO=FTPCOMMAND
X:>rxFtpProxy ftp.mydomain.com/robots.txt ftp.software.ibm.com/robots.txt
File transferred OK
Связанные функции:
Связанных функций нет.
5.13. FtpPut().
Копирует локальный файл с рабочей станции на сервер FTP, заменяя существующий.
Синтаксис:
rc = FtpPut( localFile, remoteFile [, pMode] )
Параметры:
localFile
имя файла на локальной рабочей станции
remoteFile
имя файла на сервере FTP
pMode
(необязательный) строка, определяющая режим передачи файлов:
'Ascii' |
текстовый |
'Binary' |
двоичный |
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpPut() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:
TYPE I=Binary, A=Ascii
PORT <данные> активный режим (по умолчанию)
STOR <содержимое параметра remoteFile>
или
TYPE I=Binary, A=Ascii
PASV пассивный режим
STOR <содержимое параметра remoteFile>
Если выполнение прошло успешно, то файл на сервере FTP переписывается данными из локального файла на рабочей станции.
Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).
Если параметр pMode опущен, то выбирается режим передачи файлов ранее установленный функцией FtpSetBinary() (по умолчанию, двоичный).
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл с рабочей станции на сервер в файл с указанным именем.
/* rxFtpPut.cmd - function example */
parse arg fromFile pHost '/' toFile
toFile = '/'||Strip( toFile );
if pHost = '' | toFile = '/' then do
say ''
say 'Usage: rxFtpPut localfile host/remotefile'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpPut( fromFile, toFile, 'Binary' )
if rc = -1 then do
say ''
say 'FtpPut() FTPERRNO='||FTPERRNO
end
else do
say ''
say 'File '||fromFile||' transferred to '||toFile||' OK'
end
rc = FtpLogoff()
/* end of file rxFtpPut.cmd */
Примерырезультатоввыполнения:
X:>rxFtpPut xxx.txt 127.0.0.1/Data/Ftp/Test.txt
File xxx.txt transferred to /Data/Ftp/Test.txt OK
X:>rxFtpPut C:\readme.txt 127.0.0.1/Data/Ftp/readme.txt
File C:\readme.txt transferred to /Data/Ftp/readme.txt OK
Связанныефункции:
FtpAppend(), FtpDelete(), FtpLogoff(), FtpGet(), FtpPutUnique(), FtpRename(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser()
5.14. FtpPutUnique().
Копирует локальный файл с рабочей станции на сервер FTP в файл с уникальным именем.
Синтаксис:
rc = FtpPutUnique( localFile, remoteFile [, pMode] )
Параметры:
localFile
имя файла на локальной рабочей станции
remoteFile
имя файла на сервере FTP
pMode
(необязательный) строка, определяющая режим передачи файлов:
'Ascii' |
текстовый |
'Binary' |
двоичный |
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpPutUnique() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:
TYPE I=Binary, A=Ascii
PORT <данные> активный режим (по умолчанию)
STOU <содержимое параметра remoteFile>
или
TYPE I=Binary, A=Ascii
PASV пассивный режим
STOU <содержимое параметра remoteFile>
Если выполнение прошло успешно, то выполняется копирование локального файла рабочей станции на сервер.
Если файл с указанным именем уже существует на сервере, то к имени файла последовательно добавляется индекс 1, 2 и т.д.
Например, если делается попытка сохранить файл readme.txt, а он уже существует, то пробуют сохранить в файл readme1.txt. Если же и он существует, то пытаются сохранить в файл readme2.txt и так до тех пор пока не обнаружится свободное имя файла.
Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).
Если параметр pMode опущен, то выбирается режим передачи файлов ранее установленный функцией FtpSetBinary() (по умолчанию, двоичный).
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл с рабочей станции на сервер в файл с указанным именем.
/* rxFtpPutUnique.cmd - function example */
parse arg fromFile pHost '/' toFile
toFile = '/'||Strip( toFile );
if pHost = '' | toFile = '/' then do
say ''
say 'Usage: rxFtpPutUnique localfile host/remotefile'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpPutUnique( fromFile, toFile, 'Binary' )
if rc = -1 then do
say ''
say 'FtpPutUnique() FTPERRNO='||FTPERRNO
end
else do
say ''
say 'File '||fromFile||' transferred to '||toFile||' OK'
end
rc = FtpLogoff()
/* end of file rxFtpPutUnique.cmd */
Примерырезультатоввыполнения:
X:>rxFtpPutUnique xxx.txt 127.0.0.1/Data/Ftp/Test.txt
File xxx.txt transferred to /Data/Ftp/Test.txt OK
X:>rxFtpPutUnique C:\readme.txt 127.0.0.1/Data/Ftp/readme.txt
File C:\readme.txt transferred to /Data/Ftp/readme.txt OK
Связанныефункции:
FtpAppend(), FtpDelete(), FtpLogoff(), FtpGet(), FtpPut(), FtpRename(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser()
5.15. FtpPwd().
Получает имя текущего каталога на сервере FTP.
Синтаксис:
rc = FtpPwd( pCurDir )
Параметры:
pCurDir
переменная, в которую будет помещена строка, с ответом сервера, содержащим имя текущего каталога.
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpPwd() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем отправляет на сервер следующую последовательность команд:
PWD
Если выполнение прошло успешно, то помещает ответ сервера в переменную, указанную в качестве параметра pCurDir, если она не инициализирована.
Если переменная инициализирована, то её значение не изменится. Во избежание ошибок рекомендуется сбросить её с помощью команды DROP непосредственно перед вызовом функции.
Имя текущего каталога в ответе сервера всегда заключено в двойные кавычки.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. А затем отображает ответ сервера с именем текущего каталога.
/* rxFtpPwd.cmd - function example */
parse arg pHost .
if pHost = '' then do
say ''
say 'Usage: rxFtpPwd host'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpPwd( xPwd )
if rc = -1 then do
say ''
say 'FtpPwd() FTPERRNO='||FTPERRNO
end
else do
say ''
say xPwd
end
rc = FtpLogoff()
/* end of file rxFtpPwd.cmd */
Примерырезультатоввыполнения:
X:>rxFtpPwd 127.0.0.1
"E:/data/ftp" is current directory.
X:>rxFtpPwd ftp.software.ibm.com
"/" is current directory.
Связанныефункции:
FtpChDir(), FtpLogoff(), FtpMkDir(), FtpRmDir(), FtpSetUser()
5.16. FtpQuote().
Передаёт команду серверу FTP.
Синтаксис:
rc = FtpQuote( pCmd [, pAnswer] )
Параметры:
pCmd
строка, содержащая команду FTP.
pAnswer
(необязательный) переменная, в которую будет помещена строка, с ответом сервера.
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpQuote() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем отправляет на сервер следующую последовательность команд:
<содержимое параметра pCmd>
Если выполнение прошло успешно, то помещает ответ сервера в переменную, указанную в качестве параметра pAnswer, если она не инициализирована.
Если переменная инициализирована, то её значение не изменится. Во избежание ошибок рекомендуется сбросить её с помощью команды DROP непосредственно перед вызовом функции.
Сервер должен поддерживать обработку переданной команды FTP.
Примечание:
Про наличие второго параметра в оригинальной документации не упоминается.
Длина строки, возвращаемой во втором параметре, не превышает 197 байт.
Если сервер формирует многострочный ответ, то он искажается, поскольку:
- все строки ответа могут не поместиться в 197 байт
- в каждой строке откидываются несколько символов от начала строки и опускаются символы
в конце строки
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и команду FTP. Азатемотображаетответсервера.
/* rxFtpQuote.cmd - function example */
parse arg pHost pCmd
if pHost = '' | pCmd = '' then do
say ''
say 'Usage: rxFtpQuote host cmd'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpQuote( pCmd, xAnswer )
if rc = -1 then do
say ''
say 'FtpQuote() FTPERRNO='||FTPERRNO
end
else do
say ''
say xAnswer
end
rc = FtpLogoff()
/* end of file rxFtpQuote.cmd */
Примерырезультатоввыполнения:
X:>rxFtpQuote 127.0.0.1 syst
OS/2 operating system
X:>rxFtpQuote ftp.software.ibm.com syst
UNIX Type: L8
X:>rxFtpQuote 127.0.0.1 type i
Type set to I (Image/Binary).
X:>rxFtpQuote ftp.software.ibm.com type i
TYPE is now 8-bit binary
Связанныефункции:
FtpLogoff(), FtpSite(), FtpSys(), FtpSetUser()
5.17. FtpRename().
Переименовывает файл на сервере FTP.
Синтаксис:
rc = FtpRename( remoteOldFile, remoteNewFile )
Параметры:
remoteOldFile
имя существующего файла на сервере FTP
remoteOldFile
новое имя, которое будет присвоено этому файлу
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpRename() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем отправляет на сервер следующую последовательность команд:
RNFR <содержимое параметра remoteOldFile>
RNTO <содержимое параметра remoteNewFile>
Если выполнение прошло успешно, то файл на сервере переименовывается.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста, имя файла на сервере и новое имя файла. Азатемпереименовываетуказанныйфайлнасервере.
/* rxFtpRename.cmd - function example */
parse arg pHost '/' oldFile newFile
oldFile = '/'||Strip( oldFile );
if pHost = '' | oldFile = '/' | newFile = '' then do
say ''
say 'Usage: rxFtpRename host/oldfile newfile'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpRename( oldFile, newFile )
if rc = -1 then do
say ''
say 'FtpRename() FTPERRNO='||FTPERRNO
end
else do
say ''
say 'File '||oldFile||' renamed to '||newFile||' OK'
end
rc = FtpLogoff()
/* end of file rxFtpRename.cmd */
Примерырезультатоввыполнения:
X:>rxFtpRename 127.0.0.1/Data/Ftp/Test.txt TestX.txt
File /Data/Ftp/Test.txt renamed to TestX.txt OK
Связанныефункции:
FtpAppend(), FtpDelete(), FtpGet(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpSetUser()
5.18. FtpRmDir().
Удаляет каталог на сервере FTP.
Синтаксис:
rc = FtpRmDir( remoteDir )
Параметры:
remoteDir
имя каталога на сервере FTP
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpRmDir() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем отправляет на сервер следующую последовательность команд:
RMD <содержимое параметра remoteDir>
Если выполнение прошло успешно, то каталог на сервере удаляется.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. Затемудаляетуказанныйкаталог.
/* rxFtpRmDir.cmd - function example */
parse arg pHost '/' pDir
pDir = '/'||Strip( pDir );
if pHost = '' | pDir = '/' then do
say ''
say 'Usage: rxFtpRmDir host/dir'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpRmDir( pDir )
if rc = -1 then do
say ''
say 'FtpRmDir() FTPERRNO='||FTPERRNO
end
else do
say ''
say 'Directory '||pDir||' removed OK'
end
rc = FtpLogoff()
/* end of file rxFtpRmDir.cmd */
Примерырезультатоввыполнения:
X:>rxFtpRmDir 127.0.0.1/Data/Ftp/Other
Directory /Data/Ftp/Other removed OK
Связанныефункции:
FtpChDir(), FtpLogoff(), FtpMkDir(), FtpPwd(), FtpSetUser()
5.19. FtpSetActiveMode().
Задаёт режим работы FTP, который будет использоваться функциями REXX FTP API по умолчанию.
Синтаксис:
rc = FtpSetActiveMode( pMode )
Параметры:
pMode
режим FTP:
'0' |
пассивный |
'1' |
активный |
Возвращаемое значение:
Функции FtpSetActiveMode(), FtpSetBinary() и FtpSetUser() возвращают одно из следующих значений:
Значение |
Описание |
1 |
нормальное завершение, ошибок нет |
0 |
ошибка, требуемое действие не выполнено |
Cпециальной переменной FTPERRNO всегда присваивается значение 0.
Описание:
В отличии от функций FtpSetBinary() и FtpSetUser(), которые просто выполняют установку параметров сессии FTP, функция FtpSetActiveMode() сначала проверяет наличие соединения с сервером и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем задаёт режим работы с FTP, который будет использоваться соответствующими функциями REXX FTP API по умолчанию.
В дальнейшем, функции:
FtpAppend() |
FtpLs() |
будут использовать режим, установленный функцией FtpSetActiveMode() (по умолчанию, активный).
Примечание:
В оргинальной документации утверждается, что режимом FTP по умолчанию является пассивный режим. На самом деле, по крайней мере для REXX FTP API версии 2.1, по умолчанию используется активный режим FTP.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл c сервера в разных режимах работы FTP.
/* rxFtpSetActiveMode.cmd - function example */
parse arg toFile pHost '/' fromFile
fromFile = '/'||Strip( fromFile );
if pHost = '' | toFile = '/' then do
say ''
say 'Usage: rxFtpSetActiveMode localfile host/remotefile'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpSetActiveMode( '0' );
if rc = 1 then do
say ''
say 'FTP mode is passive'
end
else do
say ''
say 'FtpSetActiveMode("0") error RC='||rc
signal halt
end
rc = FtpGet( toFile||'.p', fromFile )
if rc = -1 then do
say ''
say 'FtpGet() FTPERRNO='||FTPERRNO
signal halt
end
else do
say ''
say 'File '||fromFile||' received to '||toFile||'.p OK'
end
rc = FtpSetActiveMode( '1' );
if rc = 1 then do
say ''
say 'FTP mode is active'
end
else do
say ''
say 'FtpSetActiveMode("1") error RC='||rc
signal halt
end
rc = FtpGet( toFile||'.a', fromFile )
if rc = -1 then do
say ''
say 'FtpGet() FTPERRNO='||FTPERRNO
signal halt
end
else do
say ''
say 'File '||fromFile||' received to '||toFile||'.a OK'
end
halt:
rc = FtpLogoff()
/* end of file rxFtpSetActiveMode.cmd */
Примерырезультатоввыполнения:
X:>rxFtpSetActiveMode xxx.txt 127.0.0.1/Data/Ftp/Test.txt
FTP mode is passive
File /Data/Ftp/Test.txt received to xxx.txt.p OK
FTP mode is active
File /Data/Ftp/Test.txt received to xxx.txt.a OK
Связанныефункции:
FtpAppend(), FtpDir(), FtpGet(), FtpLogoff(), FtpLs(), FtpPut(), FtpPutUnique(), FtpSetUser()
5.20. FtpSetBinary().
Задаёт режим передачи файлов, который будет использоваться функциями REXX FTP API по умолчанию.
Синтаксис:
rc = FtpSetBinary( pMode )
Параметры:
pMode
режим передачи файлов:
'Ascii' |
текстовый |
'Binary' |
двоичный |
Возвращаемое значение:
Функции FtpSetActiveMode(), FtpSetBinary() и FtpSetUser() возвращают одно из следующих значений:
Значение |
Описание |
1 |
нормальное завершение, ошибок нет |
0 |
ошибка, требуемое действие не выполнено |
Cпециальной переменной FTPERRNO всегда присваивается значение 0.
Описание:
Если сессия FTP открыта, то функция FtpSetBinary() задаёт режим передачи файлов, который будет использоваться соответствующими функциями REXX FTP API по умолчанию.
В дальнейшем, если при вызове функций:
FtpAppend() |
FtpPut() |
будет опущен параметр, явно определяющий режим передачи файлов, то эти функции будут использовать режим, установленный функцией FtpSetBinary() (по умолчанию, двоичный).
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл c сервера в разных режимах передачи.
/* rxFtpSetBinary.cmd - function example */
parse arg toFile pHost '/' fromFile
fromFile = '/'||Strip( fromFile );
if pHost = '' | toFile = '/' then do
say ''
say 'Usage: rxFtpSetBinary localfile host/remotefile'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpSetBinary( 'Binary' );
if rc = 1 then do
say ''
say 'Transfer mode is "Binary"'
end
else do
say ''
say 'FtpSetBinary("Binary") error RC='||rc
signal halt
end
rc = FtpGet( toFile||'.b', fromFile )
if rc = -1 then do
say ''
say 'FtpGet() FTPERRNO='||FTPERRNO
signal halt
end
else do
say ''
say 'File '||fromFile||' received to '||toFile||'.b OK'
end
rc = FtpSetBinary( 'Ascii' );
if rc = 1 then do
say ''
say 'Transfer mode is "Ascii"'
end
else do
say ''
say 'FtpSetBinary("Ascii") error RC='||rc
signal halt
end
rc = FtpGet( toFile||'.a', fromFile )
if rc = -1 then do
say ''
say 'FtpGet() FTPERRNO='||FTPERRNO
signal halt
end
else do
say ''
say 'File '||fromFile||' received to '||toFile||'.a OK'
end
halt:
rc = FtpLogoff()
/* end of file rxFtpSetBinary.cmd */
Примерырезультатоввыполнения:
X:>rxFtpSetBinary xxx.txt 127.0.0.1/Data/Ftp/Test.txt
Transfer mode is "Binary"
File /Data/Ftp/Test.txt received to xxx.txt.b OK
Transfer mode is "Ascii"
File /Data/Ftp/Test.txt received to xxx.txt.a OK
Связанныефункции:
FtpAppend(), FtpGet(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpSetUser()
5.21. FtpSetUser().
Открывает сессию FTP.
Синтаксис:
rc = FtpSetUser( pHost, pUser, pPass [, pAcct] )
Параметры:
pHost
адрес или имя хоста (сервера FTP)
pUser
имя пользователя сервера FTP
pPass
пароль пользователя сервера FTP
pAcct
(необязательный) аккаунт пользователя сервера FTP; информация об аккаунте пользователя, зависящая от конкретного хоста
Возвращаемое значение:
Функции FtpSetActiveMode(), FtpSetBinary() и FtpSetUser() возвращают одно из следующих значений:
Значение |
Описание |
1 |
нормальное завершение, ошибок нет |
0 |
ошибка, требуемое действие не выполнено |
Cпециальной переменной FTPERRNO всегда присваивается значение 0.
Описание:
Функция FtpSetUser() открывает сессию FTP, задавая имя или адрес хоста, имя пользователя, пароль и аккаунт.
Никакого обмена по сети по время выполнения этой функции не происходит. Параметры, переданные функции, используются в дальнейшем для инициализации и восстановления соединения с сервером FTP.
Фактически соединение с сервером FTP будет выполнено при первом же вызове любой функции из перечисленных ниже:
FtpAppend() |
FtpMkDir() |
FtpRmDir() |
Именно тогда, перед выполнением вызванной функции, сначала будет послан запрос на получение адреса хоста серверу DNS. Если сервер DNS в системе не определён, то для поиска адреса хоста используется файл TCPIP\ETC\HOSTS.
Затем будет установлено соединение с сервером FTP и выполнена следующая последовательность команд:
USER <содержимое параметра pUser>
PASS <содержимое параметра pPass>
ACCT <содержимое параметра pAcct>
PWD
и только потом будут выполнены действия вызванной функции.
Все установки, выполненнные функцией FtpSetUser(), сбрасывает функция FtpLogoff(), закрывая сессию FTP.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. Затем отправляет на сервер неполную команду, после чего сервер по тайм-ауту разрывает соединение. Соединение автоматически восстанавливается во время следующей попытки доступа к серверу. Затемсессиязакрываетсяиработастановитсяневозможна.
/* rxFtpLogoff.cmd - function example */
parse arg pHost
if pHost = '' then do
say ''
say 'Usage: rxFtpLogoff host'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpQuote( 'TYPE', xAnswer )
if rc = -1 then do
say ''
say 'FtpQuote() FTPERRNO='||FTPERRNO
end
else do
say ''
say xAnswer
end
rc = FtpSys( pSys )
if rc = -1 then do
say ''
say 'FtpSys() FTPERRNO='||FTPERRNO
end
else do
say ''
say pSys
end
rc = FtpLogoff()
if rc = -1 then do
say ''
say 'FtpLogoff() FTPERRNO='||FTPERRNO
end
rc = FtpSys( pSys )
if rc = -1 then do
say ''
say 'FtpSys() FTPERRNO='||FTPERRNO
end
else do
say ''
say pSys
end
/* end of file rxFtpLogoff.cmd */
Примерырезультатоввыполнения:
X:>rxFtpLogoff 127.0.0.1
FtpQuote() FTPERRNO=FTPCOMMAND
OS/2 operating system
FtpSys() FTPERRNO=FTPCOMMAND
Связанныефункции:
FtpAppend(), FtpChDir(), FtpDelete(), FtpDir(), FtpGet(), FtpLogoff(), FtpLs(), FtpMkDir(), FtpPut(), FtpPutUnique(), FtpPwd(), FtpQuote(), FtpRename(), FtpRmDir(), FtpSetActiveMode(), FtpSetBinary(), FtpSite(), FtpSys()
5.22. FtpSite().
Передаёт информационную строку серверу FTP.
Синтаксис:
rc = FtpSite( pInfo )
Параметры:
pInfo
информационная строка для сервера FTP.
Возвращаемое значение:
Функция возвращает одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpSite() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем отправляет на сервер следующую последовательность команд:
SITE <содержимое параметра pInfo>
Сервер должен поддерживать обработку переданной информационной строки.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и информационную строку. Азатемотображаетрезультатпередачи.
/* rxFtpSite.cmd - function example */
parse arg pHost pInfo
if pHost = '' then do
say ''
say 'Usage: rxFtpSite host info'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpSite( pInfo )
if rc = -1 then do
say ''
say 'FtpSite() FTPERRNO='||FTPERRNO
end
else do
say ''
say 'Information transfered OK'
end
rc = FtpLogoff()
/* end of file rxFtpSite.cmd */
Примерырезультатоввыполнения:
X:>rxFtpSite 127.0.0.1 xxx
Information transfered OK
X:>rxFtpSite ftp.software.ibm.com xxx
FtpSite() FTPERRNO=FTPCOMMAND
Связанныефункции:
FtpLogoff(), FtpQuote(), FtpSys(), FtpSetUser()
5.23. FtpSys().
Получает информацию об операционной системе сервера FTP.
Синтаксис:
rc = FtpSys( pAnswer )
Параметры:
pAnswer
переменная, в которую будет помещена строка с информацией об операционной системе сервера.
Возвращаемое значение:
Функция FtpSys возвращает одно из следующих значений:
Значение |
Описание |
<строка> |
нормальное завершение, ошибок нет; |
-1 |
ошибка во время выполнения; |
Специальной переменной FTPERRNO присваивается одно из следующих значений:
Значение |
Описание |
0 |
нормальное завершение, ошибок нет |
FTPSERVICE |
неизвестный сервис |
FTPHOST |
неизвестный хост |
FTPSOCKET |
невозможно получить сокет |
FTPCONNECT |
невозможно соединиться с сервером |
FTPLOGIN |
регистрация не выполнена |
FTPABORT |
передача данных прервана |
FTPLOCALFILE |
проблемы с открытием локального файла |
FTPDATACONN |
проблемы с инициализацией соединения |
FTPCOMMAND |
выполнение команды прервано, соединение с сервером может быть разорвано |
FTPPROXYTHIRD |
прокси-сервер не поддерживает передачу третьей стороне |
FTPNOPRIMARY |
нет первичного соединения для передачи по доверенности (proxy transfer) |
FTPFAILURE |
команда не выполнена, соединение с сервером сохранено |
Описание:
Если сессия FTP открыта, то сначала функция FtpSys() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.
Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().
Затем отправляет на сервер следующую последовательность команд:
SYST
Если выполнение прошло успешно, то помещает информацию об операционной системе сервера в переменную, указанную в качестве параметра pAnswer, если она не инициализирована.
Если переменная инициализирована, то её значение не изменится. Во избежание ошибок рекомендуется сбросить её с помощью команды DROP непосредственно перед вызовом функции.
Пример:
Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. А затем отображает описание операционной системы, под которой работает сервер на этом хосте.
/* rxFtpSys.cmd - function example */
parse arg pHost .
if pHost = '' then do
say ''
say 'Usage: rxFtpSys host'
say ''
exit 1
end
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
if rc \= 1 then do
say 'FtpSetUser() - Not connected'
exit 1
end
rc = FtpSys( xSys )
if rc = -1 then do
say ''
say 'FtpSys() FTPERRNO='||FTPERRNO
end
else do
say ''
say rc
end
rc = FtpLogoff()
/* end of file rxFtpSys.cmd */
Примерырезультатоввыполнения:
X:>rxFtpSys 127.0.0.1
OS/2 operating system
X:>rxFtpSys ftp.software.ibm.com
UNIX Type: L8
Связанныефункции:
FtpLogoff(), FtpQuote(), FtpSite(), FtpSetUser()
5.24. FtpVersion().
Получаетверсиюбилиотеки REXX FTP API.
Синтаксис:
rc = FtpVersion( pAnswer )
Параметры:
pAnswer
переменная, в которую будет помещён номер версии библиотеки REXX FTP API.
Возвращаемое значение:
Функция FtpVersion() всегда возвращает пустую строку ("").
Cпециальной переменной FTPERRNO всегда присваивается значение 0.
Описание:
Вполне самостоятельная функция, никак не связанная с остальными функциями REXX FTP API (за исключением FtpLoadFuncs() и FtpDropFuncs()).
Всегда возвращает пустую строку в качестве кода возврата и помещает номер версии REXX FTP API в переменную, указанную в качестве параметра pAnswer, если она не инициализирована.
Если переменная инициализирована, то её значение не изменится. Во избежание ошибок рекомендуется сбросить её с помощью команды DROP непосредственно перед вызовом функции.
Пример:
Ниже приведён текст программы, которая демонстрирует номер версии библиотеки REXX FTP API.
/* rxFtpVersion.cmd - function example */
if RxFuncQuery( 'FtpLoadFuncs' ) then do
rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
rc = FtpLoadFuncs( )
end
rc = FtpVersion( pVer )
say ''
say 'REXX FTP API Version '||pVer
/* end of file rxFtpVersion.cmd */
Примеры результатов выполнения:
X:>rxFtpVersion
REXX FTP API Version 2.1
Связанные функции:
Связанных функций нет.
6. Замечания по применению.
В этом разделе автор попытался обобщить свой опыт применения REXX FTP API, чтобы показать не только КАК ИСПОЛЬЗОВАТЬ ту или иную функцию, но и ЧТО ПРОИСХОДИТ во время работы.
Для иллюстрации отдельных пунктов использованы программы, тексты которых приведены в разделе "Пример" описания соответствующих функций.
Отметим, что примеры выполнялись в операционной системе The Operating System/2 Version 4.50 Revision 14.088. В качестве сервера FTP использовался стандартный модуль ftpd из поставки OS/2 (хост 127.0.0.1).
Некоторые замечания уже были приведены в соответствующих разделах.
6.1. Активный и пассивный режимы FTP.
FTP использует два раздельных канала TCP/IP:
- один - для передачи управляющих команд,
- другой - для передачи данных.
Режимы работы FTP различаются по направлению инициирования канала данных:
активный
соединение для передачи команд инициирует клиент, а соединение для передачи данных - сервер,
пассивный
оба соединения инициирует клиент.
- Активный режим FTP.
Поскольку соединение для передачи данных инициирует сервер, то клиент должен сообщить ему номер порта, по которому он готов принять данные.
Делается это с помощью команды:
PORT a1,a2,a3,a4,p1,p2
-+--------- -+---
| |
| +--- номер порта = 256*p1+p2
+--------------- ip-адрес клиента
Пример получения клиентом файла с сервера FTP в активном режиме:
Клиент (192.168.2.22) Порты и направление Сервер (10.10.15.254)
------------------------------------------------------------------------------
Oткрывает свободный динамический порт (например, 51618) под канал управления.
Инициируетканалуправления (51618 -------> 21)
(51618 <------- 21) 220 FTP server ready.
USER
(51618 <------- 21) 331 Login ok, send password.
PASS
(51618 <------- 21) 230 Login ok.
PWD (51618 -------> 21)
(51618 <------- 21) 257 "/" is current directory.
TYPE I (51618 -------> 21)
(51618 <------- 21) 200 Type set to I.
Oткрывает свободный динамический порт (например, 51619) под канал данных
и начинает его прослушивать, ожидая данных.
PORT 192,168,2,22,201,163. (51618 -------> 21)
(51618 <------- 21) 200 PORT command successful.
RETR Test.txt (51618 -------> 21)
(51619 <------- 20) Инициирует канал данных
(51619 <------- 20) Передаёт данные
(51619 <------- 20) Закрывает канал данных
(51618 <------- 21) 226 Transfer complete.
Закрывает динамический порт, открытый под канал данных.
QUIT (51618 -------> 21)
(51618 <------- 21) 221 Goodbye.
Закрывает канал управления. (51618 -------> 21)
- Пассивный режим FTP.
Поскольку соединение для передачи данных инициирует клиент, то сервер должен сообщить ему номер порта, с которого он готов отправить данные.
Сервер делает это, отвечая на команду PASV:
227 Entering Passive Mode (a1,a2,a3,a4,p1,p2).
-+--------- -+---
| |
| +--- номер порта = 256*p1+p2
+--------------- ip-адрес сервера
Пример получения клиентом файла с сервера FTP в пассивном режиме:
Клиент (192.168.2.22) Порты и направление Сервер (10.10.15.254)
------------------------------------------------------------------------------
Oткрывает свободный динамический порт (например, 51618) под канал управления.
Инициируетканалуправления (51618 -------> 21)
(51618 <------- 21) 220 FTP server ready.
USER
(51618 <------- 21) 331 Login ok, send password.
PASS
(51618 <------- 21) 230 Login ok.
PWD (51618 -------> 21)
(51618 <------- 21) 257 "/" is current directory.
TYPE I (51618 -------> 21)
(51618 <------- 21) 200 Type set to I.
PASV (51618 -------> 21)
(51618 <------- 21) 227 Entering Passive Mode (10,10,15,254,105,207).
Oткрываетсвободныйдинамическийпорт (например, 51619) подканалданных.
Инициируетканалданных (51619 ----> 27087)
RETR Test.txt (51618 -------> 21)
(51618 <------- 21) 150 Opening BINARY mode data connection for /Test.txt (75 bytes).
(51619 <---- 27087) Передаёт данные
(51619 <---- 27087) Закрывает канал данных
(51618 <------- 21) 226 Transfer complete.
Закрывает динамический порт, открытый под канал данных.
QUIT (51618 -------> 21)
(51618 <------- 21) 221 Goodbye.
Закрывает канал управления. (51618 -------> 21)
Строго говоря, пассивный режим был придуман для преодоления проблем, возникающих из-за использования firewall/NAT, которыми защищена рабочая станция клиента, находящаяся в локальной сети.
Однако, практически все современные firewall/NAT, позволяют рабочим станциям клиента, находящимся в локальной сети, работать с серверами FTP, расположенными во внешней сети, в активном режиме:
- firewall/NAT, защищающий локальную сеть клиента, перехватывает команду PORT, отправляемую из локальной сети во внешнюю,
- в перехваченной команде PORT подменяет локальный адрес рабочей станции на внешний адрес firewall/NAT,
- строит временное правило firewall, разрешающее доступ с порта 20 внешнего сервера на порт, указанный в перехваченной команде,
- строит временное правило NAT, направляющее трафик между портом 20 внешнего сервера и портом, указанным в перехваченной команде, на соответствующую рабочую станцию в локальной сети.
Аналогичным образом могут быть защищены и серверы FTP, когда они размещены в локальной сети (чаще говорят про "демилитаризованную зону", но она тоже представляет из себя локальную сеть, только отделённую от основной как логически, так и физически).
В этом случае "умный" firewall/NAT, защищающий серверы:
- перехватывает ответ на команду PASV, отправляемый сервером клиенту во внешнюю сеть,
- в перехваченном ответе подменяет локальный адрес сервера на внешний адрес firewall/NAT,
- строит временное правило firewall, разрешающее доступ с любого порта внешнего клиента на порт, указанный в перехваченном ответе,
- строит временное правило NAT, направляющее трафик между любым портом внешнего клиента и портом, указанным в перехваченном ответе, на соответствующий сервер в локальной сети.
Но это тоже может не решить все проблемы, связанные с использованием firewall/NAT.
Иногда возникает ситуация, которая со стороны клиента внешне выглядит так:
- не удаётся скачать файл с сервера FTP с помощью функций REXX FTP API в пассивном режиме, хотя с помощью браузера (например, Firefox), который тоже использует пассивный режим, файл скачивается.
Эта проблема возникает из-за того, что в строке, получаемой клиентом в ответ на команду PASV, указан адрес, отличный от адреса сервера FTP. И, если браузер просто игнорирует этот адрес, то функции REXX FTP API пытаются установить соединение для передачи данных именно по адресу, указанному в ответе.
В этом случае надо использовать активный режим для функций REXX FTP API, если разрешит администратор безопасности сети.
6.2. Восстановление соединения.
Функция FtpSetUser() открывает сессию FTP, задавая имя или адрес хоста, имя пользователя, пароль и аккаунт.
Никакого обмена по сети по время выполнения этой функции не происходит. Параметры, переданные функции, используются в дальнейшем для инициализации и восстановления соединения с сервером FTP.
Фактически, как инициализация, так и восстановление соединения с сервером FTP выполняется при вызове любой функции из перечисленных ниже, если сессия FTP открыта, но соединение с сервером отсутствует:
FtpAppend() |
FtpMkDir() |
FtpRmDir() |
- Инициализация соединения.
Выполняется, если соединение с сервером ещё ни разу не устанавливалось после вызова FtpSetUser().
Сначала посылается запрос на получение адреса хоста серверу DNS. Если сервер DNS в системе не определён, то для поиска адреса хоста используется файл TCPIP\ETC\HOSTS.
Затем устанавливается соединение с сервером FTP и выполняется следующая последовательность команд:
USER
PASS
ACCT
PWD
- Восстановление соединения.
Выполняется, если соединение с сервером было разорвано во время выполнения.
Сначала устанавливается соединение с сервером FTP. Затем выполняется следующая последовательность команд:
USER
PASS
ACCT
где directory - имя текущего каталога на момент разрыва соединения.
6.3. О полезности FtpSys().
FtpSys() выдаёт информацию об операционной системе, под которой работает сервер FTP, а иногда и о нём самом. Эту информацию можно использовать для вынесения некоторых предположений о том, что можно ожидать от данного сервера.
Например, в каком формате будет предоставляться список содержимого каталога, формируемого функцией FtpDir(). Или, как будет выглядеть имя текущего каталоге в строке, возвращаемой функцией FtpPwd().
Многое, конечно, зависит от фантазии автора исходного кода конкретного сервера FTP и умения администратора, настроившего его на рабочем месте, но всё-таки какие-то основные правила обычно соблюдаются.
Примеры ответов некоторых серверов FTP на запрос информации об операционной системе:
Сервер Ответ
-------------------------------------------------------------
ftp.os2.ru OS/2 operating system
os2.fannet.ru UNIX type:OS/2
ftp.software.ibm.com UNIX Type: L8
ftp.relcom.ru UNIX Type: L8 Version: BSD-199506
ftp.demos.su UNIX Type: L8 Version: tnftpd 20080609
ftp.sun.com UNIX Type: L8 Version: SUNOS
ftp.asus.com UNIX emulated by FileZilla
ftp.gnupg.org UNIX
ftp.microsoft.com Windows_NT
ftp.softlab.ru Windows_NT version 5.0
ftp.mt.xplain.com MACOS Peter's Server
Итак, что же можно ожидать от сервера FTP, получив от него информацию об операционной системе:
- UNIX ...
- Независимо от операционной системы, под которой работает данный сервер FTP, функция FtpDir() будет возвращать списки содержимого каталогов в UNIX-подобном формате:
Пример 1:
- Независимо от операционной системы, под которой работает данный сервер FTP, функция FtpDir() будет возвращать списки содержимого каталогов в UNIX-подобном формате:
X:>rxFtpDir ftp.software.ibm.com
<...пропуск...>
drwxr-sr-x 7 102004493 201 256 Mar 9 2004 ps
lrwxrwxrwx 1 102004493 1 14 Sep 25 2009 pub -> software/lotus
drwxr-sr-x 19 102004493 201 4096 Jul 22 1999 publications
-rw-r--r-- 1 102004493 201 75 Feb 16 08:52 robots.txt
drwxr-sr-x 21 102004493 201 4096 Aug 20 2002 rs6000
drwxr-sr-x 38 102004493 201 4096 Apr 28 2008 s390
<...пропуск...>
где каждая запись состоит из нескольких полей, разделённых пробелами. Большинство реализаций серверов FTP формирует записи, состоящие из 9 полей, но встречаются и такие, которые формируют записи из 8 полей (например, DeleGate).
Важно тут то, что первое поле всегда содержит тип записи и права доступа для владельца, группы и остальных пользователей, а в последних пяти всегда последовательно располагаются длина, месяц, число, год (или время) создания/модификации файла и, наконец, имя.
Тип записи определяется по первому символу первого поля (подсвечен в вышеприведённом примере):
d - каталог, l - линк, - - файл и т.д.
Имя всегда находится в последнем поле (подсвечено в вышеприведённом примере) и может само содержать пробелы, что несколько усложняет разбор из-за разницы числа полей в записи для разных серверов.
- Домашний каталог будет корневым:
Пример 2:
X:>rxFtpPwd ftp.software.ibm.com
"/" is your current location
- Функция FtpPwd() возвращает имя текущего каталога так, как оно хранится в файловой системе, включая прописные и строчные буквы:
Пример 3:
X:>rxFtpDir ftp.dlink.ru/pub
drwxrwsr-x 73 33 106 4096 Apr 5 09:24 ADSL
drwxrwsr-x 57 33 106 4096 Dec 17 14:43 Adapter
drwxrwsr-x 13 33 106 4096 Feb 1 2006 Bootrom
<...пропуск...>
X:>rxFtpChDir ftp.dlink.ru/pub/Bootrom
"/pub/Bootrom" is your current location
- Тем не менее могут быть незначительные различия в работе функций с серверами различного исполнения:
- в списках содержимого каталогов (FtpDir()) могут присутствовать записи типа total:
total 208
drwxr-sr-x 13 102004493 201 4096 Apr 18 2008 4700
-rw-r--r-- 1 102004493 201 6981 Dec 20 1995 TRADEMARKS.TXT
<...пропуск...>
в начале или в конце списка,
- в списках содержимого каталогов (FtpDir()) могут присутствовать записи текущего и родительского каталогов:
dr--r--r-- 1 ftp ----- 0 Jan 2 1980 .
dr--r--r-- 1 ftp ----- 0 Jan 2 1980 ..
dr--r--r-- 1 ftp ----- 0 Dec 19 2007 fido
<...пропуск...>
в начале списка,
- в имени текущего каталога (FtpPwd) может присутствовать закрывающий символ '/':
"/pub/" is your current location
- OS/2 operating system
Такую строку выдаёт стандартный модуль ftpd из поставки OS/2.- Функция FtpDir() будет возвращать списки содержимого каталогов в неповторимой полуосёвой манере:
Пример 4:
- Функция FtpDir() будет возвращать списки содержимого каталогов в неповторимой полуосёвой манере:
X:>rxFtpDir 127.0.0.1
351 A 04-11-10 11:10 error.log
0 A DIR 04-12-10 08:59 Misc Tools
0 DIR 04-10-10 08:33 Public
50 04-10-10 08:34 ReadMe.txt
10 A 04-10-10 13:57 Test.txt
Конечно, строго говоря, здесь каждая запись состоит из 6 полей, разделённых пробелами.
Во втором поле перечисляются атрибуты файла.
В третьем - индикатор каталога.
В шестом - имя, которое само может содержать пробелы.
Однако, поля атрибутов и индикатора каталога могут быть пустыми (заполнены пробелами), что несколько усложняет разбор.
Если каталог пуст, то выдаётся единственная запись:
total 0
- Домашний каталог будет содержать полный путь, включая букву диска:
Пример 5:
X:>rxFtpPwd 127.0.0.1
"E:/data/ftp" is current directory.
что надо учитывать при переходах от корня. В программах, используемых здесь в качестве примера, как раз применяется механизм перехода от корня:
Пример 6:
X:>rxFtpChDir 127.0.0.1/Public
FtpChDir
FTPERRNO=FTPCOMMAND
X:>rxFtpChDir 127.0.0.1/data/ftp/Public
"E:/data/ftp/public" is current directory.
- Функция FtpPwd() возвращает имя текущего каталога исключительно строчными буквами:
Пример 7:
X:>rxFtpDir 127.0.0.1
351 A 04-11-10 11:10 error.log
0 A DIR 04-12-10 08:59 Misc Tools
0 DIR 04-10-10 08:33 Public
50 04-10-10 08:34 ReadMe.txt
10 A 04-10-10 13:57 Test.txt
X:>rxFtpChDir 127.0.0.1/data/ftp/Public
"E:/data/ftp/public" is current directory.
- Windows_NT
Так идентифицируются, по всей видимости, Microsoft IIS с версией меньше 5.- Функция FtpDir() будет возвращать списки содержимого каталогов в стиле Windows:
Пример 8:
- Функция FtpDir() будет возвращать списки содержимого каталогов в стиле Windows:
X:>rxFtpDir ftp.microsoft.com/MISC
08-05-09 01:13PM
04-08-94 06:13PM 15749 CBCP.TXT
08-05-09 01:13PM
08-05-09 01:13PM
04-12-93 05:30PM 710 DISCLAIM.TXT
<...пропуск...>
Конечно, строго говоря, здесь каждая запись состоит из 5 полей, разделённых пробелами.
В третьем поле отображается индикатор каталога.
В четвёртом - длина файла.
В пятом - имя, которое само может содержать пробелы.
Однако, для записей каталогов заполняется пробелами поле длины, а для записей файлов пробелами заполняется поле индикатора каталога, что и облегчает разбор, сводя всё к четырём полям.
- Остальные замечания аналогичны UNIX ... серверам.
- Windows_NT version 5.0
Так идентифицируются, по всей видимости, Microsoft IIS с версией 5 и выше.
Все замечания аналогичны UNIX ... серверам. - MACOS Peter's Server
Понятно, что это некий сервер под MACOS. Дальше мысль останавливается :) - Функция FtpDir() будет возвращать списки содержимого каталогов в формате, похожем на формат UNIX:
Пример 9:
X:>rxFtpDir ftp.mt.xplain.com
-rwxr-xr-x 0 214 214 Jun 30 2005 !readme
drwxr-xr-x folder 0 Jul 17 2006 adsales
drwxr-xr-x folder 0 Jul 17 2006 challenge
<...пропуск...>
drwxr-xr-x folder 0 Jul 17 2006 thinkref
drwxr-xr-x folder 0 Jul 17 2006 util
-rwxr-xr-x 332 7 339 Feb 5 2040 welcome.txt
Конечно, строго говоря, здесь каждая запись состоит из 8 полей, разделённых пробелами.
Первое поле содержит тип записи и права доступа для владельца, группы и остальных пользователей,
В третьем поле отображается индикатор каталога, который так же присутствует в первом символе первого поля.
В четвёртом - длина файла.
В пятом, шестом и седьмом - месяц, число и год (или время) создания/модификации файла, соответственно.
В восьмом - имя, которое само может содержать пробелы.
Однако, для записей каталогов второе поле заполняется пробелами. Поэтому при разборе можно считать, что записи каталогов содержат 7 полей, а записи файлов - 8.
- Остальные замечания аналогичны UNIX ... серверам.
6.4. Отличия FTPFAILURE и FTPCOMMAND.
В оригинальной документации значение FTPFAILURE отсутствует в списке возможных значений, которые может получать специальная переменная FTPERRNO.
Состояние FTPFAILURE похоже на состояние FTPCOMMAND, но отличается механизмом возникновения и результатом.
Пример 1:
X:>rxFtpQuote 127.0.0.1 XXX
FtpQuote() FTPERRNO=FTPFAILURE
В этом примере серверу, работающему на хосте 127.0.0.1, передается команда
XXX
Поскольку эта команда не реализована в данном сервере FTP, то в ответ он посылает сообщение:
502 Unknown command.
В результате, обработчик возврата функции REXX FTP API формирует состояние FTPFAILURE в специальной переменной FTPERRNO. Соединение с сервером не разрывается.
Пример 2:
X:>rxFtpQuote 127.0.0.1 TYPE
FtpQuote() FTPERRNO=FTPCOMMAND
В этом примере серверу, работающему на хосте 127.0.0.1, передается команда
TYPE
Эта команда реализована в сервере FTP, но в данном случае записана не полностью (отсутствует обязательный параметр). Сервер, начав выполнение команды, ожидает получения недостающего параметра и, не дождавшись, прекращает выполнение команды. Послечегопосылаетсообщение:
221 You could at least say goodbye.
и разрывает соединение.
В результате, обработчик возврата функции REXX FTP API формирует состояние FTPCOMMAND в специальной переменной FTPERRNO. Соединение с сервером разорвано по инициативе сервера.
6.5. Проблемы и недостатки.
- Неполная поставка
В некоторых случаях при возникновении ошибок библиотека может самостоятельно выводить на устройство stderr (обычно, консоль) диагностические сообщения. Например, возникновение ошибки FTPABORT может сопровождаться сообщением:
abort: The file or directory specified cannot be found.
Файл сообщений об ошибках DDE4.MSG должен находиться в одном из каталогов, перечисленных в переменной окружения DPATH, задаваемой в файле CONFIG.SYS.
Одним из недостатков является то, что вывод этих сообщений невозможно подавить, а другим - то, что файл DDE4.MSG отсутствует в поставке OS/2. Надо добавить, что в версиях eComStation, использующих LANGE, он присутствует.
- Неполная реализация
К сожалению, в REXX FTP API реализованы далеко не все функции OS/2 FTP API, чей надстройкой он, в сущности, и является.
Кроме того, и в самом OS/2 FTP API отсутствуют некоторые полезные функции, реализующие, например, докачку файлов с сервера FTP. - Искажение ответа сервера FTP в FtpQuote()
Недостатком является уже то, что в оригинальной документации не упоминается про наличие у функции второго параметра, в который помещается ответ сервера FTP на переданную ему команду.
Более существенный недостаток состоит в том, что ответ сервера FTP искажается:- обрезается до 197 символов,
- в каждой строке откидываются несколько символов от начала строки и опускаются символы
в конце строки, что особенно сказывается на многострочных ответах.
- Наивная реализация пассивного режима
Серверы FTP могут быть защищены с помощью firewall/NAT, когда они располагаются в локальной сети (чаще говорят про "демилитаризованную зону", но она тоже представляет из себя локальную сеть, только отделённую от основной как логически, так и физически).
Соответственно, ответ сервера на команду PASV будет корректироваться "умным" firewall/NAT, защищающим сервер, с целью замены в нём локального адреса сервера на внешний адрес firewall/NAT. В зависимости от фантазии строителя сети, в которой находится сервер FTP, ответ сервера может пройти через несколько "умных" firewall/NAT пока доберётся до клиента. И каждый такой "умный" firewall/NAT возможно будет корректировать данные ответа.
В результате до клиента может добраться ответ, в котором указан адрес, несоответствующий адресу сервера FTP.
И, если ушлые браузеры, использующие пассивный режим (например, Firefox), игнорируют этот адрес и строят канал передачи данных с тем же сервером, с которым установлено управляющее соединение, то функции REXX FTP API честно пытаются соединиться с хостом, чей адрес указан в ответе. - Проблемы FtpProxy()
- Документирование
В оригинальной документации отмечено, что параметр, определяющий режим передачи файлов, не обязателен. Однако, если его опустить или задать неправильное значение, то FtpProxy() просто вернёт код возврата равный 0, не выполняя никаких действий, что затрудняет диагностику ошибок. - Функционирование
Порождаются самой схемой работы функции:- потоки управляющих команд организуются между хостом, на котором выполняется программа, использующая FtpProxy(), и серверами,
- потоки данных организуются между серверами напрямую.
Поэтому работоспособность функции сильно зависит от наличия различных firewall/NAT не только между хостом и серверами, которыми он управляет, но и между самими серверами FTP.
Кроме того, серверы FTP могут проверять адрес, передаваемый в команде PORT, на соответствие адресу хоста, с которого осуществляется управление, и запрещать работу при несовпадении.
- Невозврат из функций REXX FTP API
Иногда наблюдается невозврат из функций REXX FTP API, приводящий к зависанию программ. Проявление этого эффекта было отмечено в некоторых программах, которые в течение одного сеанса многократно обращаются к серверу, например, в программе построения дерева каталогов сервера FTP.
Оказывается, функции REXX FTP API во время выполнения цепочек команд обильно уснащают процесс общения с сервером FTP командами NOOP. И, если передача значащих команд и получение ответов на них контролируется жёстко (выполняется повторная отправка команд каждые 64 секунды, через определённое количество неудачных попыток соединение разрывается и формируется соответствующая ошибка), то обработчик ошибок самовольно вставленных команд NOOP не так строг (повторная отправка команды не выполняется, соединение остаётся в состоянии ESTABLISHED до тех пор, пока не будет закрыто каким-либо способом).
Например, если функция FtpChDir() присутствует в цепочке других команд, то дополнительные команды NOOP могут быть выданы как перед командой CWD, так и после неё.
В этом случае неполучение ответа на команду CWD приведёт к возникновению соответствующей ошибки, а неполучение ответа на команду NOOP, самовольно добавленную REXX FTP API, приводит к невыходу из функции FtpChDir() (по крайней мере, до закрытия соединения).
Надо сказать, что эта ситуация возникает далеко не со всеми серверами FTP и, видимо, сильно зависит от настроек конкретного экземпляра сервера. - Несоответствие оригинальной документации реальному исполнению
Оригинальная документация достаточно скупа. Кроме того, в ряде случаев она содержит утверждения прямо противоположные действительности.
Например, утверждается, что по умолчанию функции REXX FTP API используют пассивный режим FTP, хотя на самом деле по умолчанию используется активный режим.
7. Послесловие.
Благодарности:
Автор благодарен Joseph Sharo за ряд ценных критических замечаний и предоставление доступа к своему серверу FTP для проведения ряда экспериментов.
Первоисточники:
- TCP/IP REXX FTP API Referenceизсостава OS/2 (файл rxFtp.inf)
(C)Copyright International Business Machines Corporation 1996. All rights reserved. - TCP/IP Command Referenceизсостава OS/2 (файл tcpcr.hlp)
(C)Copyright International Business Machines Corporation 1996, 1997. All rights reserved. - TCP/IP Version 4.21 Programming Referenceизсостава OS/2 Warp Toolkit (файл tcppr.inf)
(C)Copyright International Business Machines Corporation 1997, 1998. All rights reserved. - [RFC959] J.Postel and J.Reynolds, "File Transfer Protocol (FTP)", STD 9, RFC 959, October 1985.
- [RFC3659] P.Hethmon, "Extensions to FTP", RFC 3659, March 2007
Прочее:
- IBM - International Business Machines Corporation
- OS/2 - торговая марка IBM Corp.
- eComStation - торговаямарка Serenity Systems International