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 + -
显示快捷键?