ftp_response.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 191 行
ERL
191 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%%% Description: This module impements handling of ftp server responses.-module(ftp_response).%% Internal API-export([parse_lines/3, interpret/1, error_string/1]).-include("ftp_internal.hrl").%% First group of reply code digits -define(POS_PREL, 1).-define(POS_COMPL, 2).-define(POS_INTERM, 3).-define(TRANS_NEG_COMPL, 4).-define(PERM_NEG_COMPL, 5).%% Second group of reply code digits-define(SYNTAX,0).-define(INFORMATION,1).-define(CONNECTION,2).-define(AUTH_ACC,3).-define(UNSPEC,4).-define(FILE_SYSTEM,5).%%%=========================================================================%%% INTERNAL API %%%=========================================================================%%--------------------------------------------------------------------------%% parse_lines(Data, AccLines, StatusCode) -> {ok, Lines} | %% {continue, {Data, %% AccLines, StatusCode}}%%%% Data = binary() - data recived on the control connection from the %% ftp-server. %% AccLines = [string()] %% StatusCode = start | {byte(), byte(), byte()} | finish -%% Indicates where in the parsing process we are.%% start - (looking for the status code of the message)%% {byte(), byte(), byte()} - status code found, now%% looking for the last line indication.%% finish - now on the last line.%% Description: Parses a ftp control response message. %% "A reply is defined to contain the 3-digit code, followed by Space%% <SP>, followed by one line of text (where some maximum line length%% has been specified), and terminated by the Telnet end-of-line%% code (CRLF), or a so called multilined reply for example:%%%% 123-First line%% Second line%% 234 A line beginning with numbers%% 123 The last line%%%% The user-process then simply needs to search for the second%% occurrence of the same reply code, followed by <SP> (Space), at%% the beginning of a line, and ignore all intermediary lines. If%% an intermediary line begins with a 3-digit number, the Server%% will pad the front to avoid confusion.%%--------------------------------------------------------------------------%% Make sure we received the first 4 bytes so we know how to parse%% the FTP server response e.i. is the response composed of one%% or multiple lines.parse_lines(Bin, Lines, start) when size(Bin) < 4 -> {continue, {Bin, Lines, start}};%% Multiple lines existparse_lines(<<C1, C2, C3, $-, Rest/binary>>, Lines, start) -> parse_lines(Rest, [$-, C3, C2, C1 | Lines], {C1, C2, C3});%% Only one line existsparse_lines(<<C1, C2, C3, ?WHITE_SPACE, Bin/binary>>, Lines, start) -> parse_lines(Bin, [?WHITE_SPACE, C3, C2, C1 | Lines], finish);%% Last line foundparse_lines(<<C1, C2, C3, ?WHITE_SPACE, Rest/binary>>, Lines, {C1, C2, C3}) -> parse_lines(Rest, [?WHITE_SPACE, C3, C2, C1 | Lines], finish);%% Potential end found wait for more data parse_lines(<<C1, C2, C3>> = Bin, Lines, {C1, C2, C3}) -> {continue, {Bin, Lines, {C1, C2, C3}}};%% Intermidate line begining with status codeparse_lines(<<C1, C2, C3, Rest/binary>>, Lines, {C1, C2, C3}) -> parse_lines(Rest, [C3, C2, C1 | Lines], {C1, C2, C3});%% Potential last line wait for more dataparse_lines(<<C1, C2>> = Data, Lines, {C1, C2, _} = StatusCode) -> {continue, {Data, Lines, StatusCode}};parse_lines(<<C1>> = Data, Lines, {C1, _, _} = StatusCode) -> {continue, {Data, Lines, StatusCode}};parse_lines(<<>> = Data, Lines, {_,_,_} = StatusCode) -> {continue, {Data, Lines, StatusCode}};%% Part of the multiple linesparse_lines(<<Octet, Rest/binary>>, Lines, {_,_, _} = StatusCode) -> parse_lines(Rest, [Octet | Lines], StatusCode);%% End of FTP server response foundparse_lines(<<?CR, ?LF>>, Lines, finish) -> {ok, lists:reverse([?LF, ?CR | Lines]), <<>>}; parse_lines(<<?CR, ?LF, Rest/binary>>, Lines, finish) -> {ok, lists:reverse([?LF, ?CR | Lines]), Rest}; %% Potential end found wait for more data parse_lines(<<?CR>> = Data, Lines, finish) -> {continue, {Data, Lines, finish}};parse_lines(<<>> = Data, Lines, finish) -> {continue, {Data, Lines, finish}};%% Part of last lineparse_lines(<<Octet, Rest/binary>>, Lines, finish) -> parse_lines(Rest, [Octet | Lines], finish).%%--------------------------------------------------------------------------%% interpret(Lines) -> {Status, Text} %% Lines = [byte(), byte(), byte() | Text] - ftp server response as%% returned by parse_lines/3%% Stauts = atom() (see interpret_status/3)%% Text = [string()]%%%% Description: Create nicer data to match on.%%--------------------------------------------------------------------------interpret([Didgit1, Didgit2, Didgit3 | Data]) -> Code1 = Didgit1 - $0, Code2 = Didgit2 - $0, Code3 = Didgit3 - $0, {interpret_status(Code1, Code2, Code3), Data}.%%--------------------------------------------------------------------------%% error_string(Error) -> string()%% Error = {error, term()} | term()%%%% Description: Translates error codes into strings intended for%% human interpretation.%%--------------------------------------------------------------------------error_string({error, Reason}) -> error_string(Reason);error_string(echunk) -> "Synchronisation error during chunk sending.";error_string(eclosed) -> "Session has been closed.";error_string(econn) -> "Connection to remote server prematurely closed.";error_string(eexists) ->"File or directory already exists.";error_string(ehost) -> "Host not found, FTP server not found, " "or connection rejected.";error_string(elogin) -> "User not logged in.";error_string(enotbinary) -> "Term is not a binary.";error_string(epath) -> "No such file or directory, already exists, " "or permission denied.";error_string(etype) -> "No such type.";error_string(euser) -> "User name or password not valid.";error_string(etnospc) -> "Insufficient storage space in system.";error_string(epnospc) -> "Exceeded storage allocation " "(for current directory or dataset).";error_string(efnamena) -> "File name not allowed.";error_string(Reason) -> lists:flatten(io_lib:format("Unknown error: ~w", [Reason])).%%%========================================================================%%% Internal functions%%%========================================================================%% Positive Preleminary Replyinterpret_status(?POS_PREL,_,_) -> pos_prel; %% Positive Completion Replyinterpret_status(?POS_COMPL,_,_) -> pos_compl;%% Positive Intermediate Reply nedd accountinterpret_status(?POS_INTERM,?AUTH_ACC,2) -> pos_interm_acct;%% Positive Intermediate Replyinterpret_status(?POS_INTERM,_,_) -> pos_interm; %% No storage area no action takeninterpret_status(?TRANS_NEG_COMPL,?FILE_SYSTEM,2) -> etnospc;%% Temporary Error, no action takeninterpret_status(?TRANS_NEG_COMPL,_,_) -> trans_neg_compl;%% Permanent disk space error, the user shall not try againinterpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,0) -> epath;interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,2) -> epnospc;interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,3) -> efnamena; interpret_status(?PERM_NEG_COMPL,_,_) -> perm_neg_compl.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?