diff options
Diffstat (limited to 'lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl')
-rw-r--r-- | lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl | 1061 |
1 files changed, 0 insertions, 1061 deletions
diff --git a/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl b/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl deleted file mode 100644 index 3a8285f092..0000000000 --- a/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl +++ /dev/null @@ -1,1061 +0,0 @@ -%%---------------------------------------------------------------------- -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% -%% -%%---------------------------------------------------------------------- -%% File : CosFileTransfer_FileTransferSession_impl.erl -%% Description : -%% -%% Created : 12 Sept 2000 -%%---------------------------------------------------------------------- --module('CosFileTransfer_FileTransferSession_impl'). - - -%%---------------------------------------------------------------------- -%% Include files -%%---------------------------------------------------------------------- --include_lib("orber/include/corba.hrl"). --include_lib("orber/src/orber_iiop.hrl"). - --include("cosFileTransferApp.hrl"). - -%%---------------------------------------------------------------------- -%% External exports -%%---------------------------------------------------------------------- --export([init/1, - terminate/2, - code_change/3, - handle_info/2]). - -%% Interface functions --export(['_get_protocols_supported'/2, - set_directory/3, - create_file/3, - create_directory/3, - get_file/3, - delete/3, - transfer/4, - append/4, - insert/5, - logout/2]). - -%%---------------------------------------------------------------------- -%% Internal exports -%%---------------------------------------------------------------------- --export([oe_orber_create_directory_current/2, oe_orber_get_content/4, - oe_orber_count_children/3]). --export([invoke_call/3]). - -%%---------------------------------------------------------------------- -%% Records -%%---------------------------------------------------------------------- --record(state, {protocols, server, type, current, module, connection, mytype, - connection_timeout}). - -%%---------------------------------------------------------------------- -%% Macros -%%---------------------------------------------------------------------- --define(create_InitState(P, S, T, C, M, Co, Ty, CT), - #state{protocols=P, server=S, type=T, current=C, module=M, connection=Co, - mytype=Ty, connection_timeout=CT}). - --define(get_Protocols(S), S#state.protocols). --define(get_Server(S), S#state.server). --define(get_CurrentDir(S), S#state.current). --define(get_Module(S), S#state.module). --define(get_Connection(S), S#state.connection). --define(get_MyType(S), S#state.mytype). --define(get_ConnectionTimeout(S), S#state.connection_timeout). --define(set_CurrentDir(S, C), S#state{current=C}). - --define(is_FTP(S), S#state.type=='FTP'). --define(is_FTAM(S), S#state.type=='FTAM'). --define(is_NATIVE(S), S#state.type=='NATIVE'). --define(is_ORBER_NATIVE(S), S#state.module==cosFileTransferNATIVE_file). - - -%%====================================================================== -%% External functions -%%====================================================================== -%%---------------------------------------------------------------------- -%% Function : init/1 -%% Returns : {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%% Description: Initiates the server -%%---------------------------------------------------------------------- -init(['FTP', Host, Port, User, Password, _Account, Protocol, Timeout]) -> - {ok, Pid} = inets:start(ftpc, [{host, Host}, {port, Port}], stand_alone), - ok = ftp:user(Pid, User, Password), - {ok, PWD} = ftp:pwd(Pid), - {Connection, ProtocolSupport} = setup_local(Protocol), - {ok, ?create_InitState(ProtocolSupport, Pid, 'FTP', - PWD, ftp, Connection, Protocol, Timeout)}; -init([{'NATIVE', Mod}, Host, Port, User, Password, _Account, Protocol, Timeout]) -> - {ok, Pid} = Mod:open(Host, Port), - ok = Mod:user(Pid, User, Password), - {ok, PWD} = Mod:pwd(Pid), - {Connection, ProtocolSupport} = setup_local(Protocol), - {ok, ?create_InitState(ProtocolSupport, Pid, 'NATIVE', - PWD, Mod, Connection, Protocol, Timeout)}. - - -%%---------------------------------------------------------------------- -%% Function : terminate/2 -%% Returns : any (ignored by gen_server) -%% Description: Shutdown the server -%%---------------------------------------------------------------------- -terminate(_Reason, #state{type = Type, server = Server, module = Mod} = State) -> - case ?get_MyType(State) of - ssl -> - catch ssl:close(?get_Connection(State)); - _ -> - catch gen_tcp:close(?get_Connection(State)) - end, - case Type of - 'FTP' -> - inets:stop(ftpc, Server); - 'NATIVE' -> - Mod:close(Server); - _ -> - ok - end, - ok. - -%%---------------------------------------------------------------------- -%% Function : code_change/3 -%% Returns : {ok, NewState} -%% Description: Convert process state when code is changed -%%---------------------------------------------------------------------- -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%---------------------------------------------------------------------% -%% function : handle_info/2 -%% Arguments: -%% Returns : -%% Effect : -%%---------------------------------------------------------------------- -handle_info(Info, State) -> - case Info of - {'EXIT', _Pid, Reason} -> - {stop, Reason, State}; - _Other -> - {noreply, State} - end. - -%%====================================================================== -%% CosFileTransfer::FileTransferSession -%%====================================================================== -%%---------------------------------------------------------------------% -%% Function : _get_protocols_supported -%% Arguments : -%% Returns : A list of CosFileTransfer::ProtocolSupport, i.e., -%% struct ProtocolSupport { -%% Istring protocol_name; -%% ProtocolAddressList addresses; %% eq a list of strings. -%% }; -%% Description: -%%---------------------------------------------------------------------- -'_get_protocols_supported'(_OE_This, State) -> - {reply, ?get_Protocols(State), State}. - -%%---------------------------------------------------------------------- -%% Function : set_directory -%% Arguments : Directory - CosFileTransfer::Directory -%% Returns : -%% Description: -%%---------------------------------------------------------------------- -set_directory(_OE_This, State, Directory) when ?is_FTP(State); ?is_NATIVE(State) -> - Mod = ?get_Module(State), - Path = filename:join('CosFileTransfer_Directory': - '_get_complete_file_name'(Directory)), - case catch Mod:cd(?get_Server(State), Path) of - ok -> - {reply, ok, ?set_CurrentDir(State, Path)}; - {error, epath} -> - corba:raise(#'CosFileTransfer_FileNotFoundException' - {reason="Directory not found."}); - {error, elogin} -> - corba:raise(#'CosFileTransfer_SessionException' - {reason="User not loggen in."}); - {error, econn} -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Premature connection ending."}); - _ -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason = "Unexpected error."}) - end. - -%%---------------------------------------------------------------------- -%% Function : create_file -%% Arguments : FileNameList -%% Returns : File -%% Description: This operation creates a File Object representing a -%% file which may or may not exist. Typically used as -%% argument when invoking transfer/3. See also get_file/2. -%%---------------------------------------------------------------------- -create_file(OE_This, State, FileNameList) -> - {reply, cosFileTransferApp:create_file(OE_This, FileNameList), State}. - -%%---------------------------------------------------------------------- -%% Function : create_directory -%% Arguments : FileNameList - full path name. -%% Returns : Directory -%% Description: -%%---------------------------------------------------------------------- -create_directory(OE_This, State, FileNameList) when ?is_FTP(State); - ?is_NATIVE(State) -> - Mod = ?get_Module(State), - case Mod:mkdir(?get_Server(State), filename:join(FileNameList)) of - ok -> - {reply, cosFileTransferApp:create_dir(OE_This, FileNameList), State}; - {error, epath} -> - corba:raise(#'CosFileTransfer_FileNotFoundException' - {reason="Directory not found."}); - {error, elogin} -> - corba:raise(#'CosFileTransfer_SessionException' - {reason="User not loggen in."}); - {error, econn} -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Premature connection ending."}); - _ -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Unknown error."}) - end. - - -%%---------------------------------------------------------------------- -%% Function : get_file -%% Arguments : FileNameList -%% Returns : FileWrapper -%% Description: This operation should be independent of the working Directory, -%% i.e., a full path name must be supplied. The file or -%% directory the returned object is supposed to represent -%% MUST(!!!!) exist. -%%---------------------------------------------------------------------- -get_file(OE_This, State, FileNameList) when ?is_FTP(State); - ?is_NATIVE(State) -> - case check_type(OE_This, State, filename:join(FileNameList)) of - {ndirectory, _Listing} -> - {reply, - #'CosFileTransfer_FileWrapper'{the_file = - cosFileTransferApp: - create_dir(OE_This, - FileNameList), - file_type = ndirectory}, - State}; - nfile -> - {reply, - #'CosFileTransfer_FileWrapper'{the_file = - cosFileTransferApp: - create_file(OE_This, - FileNameList), - file_type = nfile}, - State}; - Other -> - %% If we want to return {stop, ....} - Other - end. - -%%---------------------------------------------------------------------- -%% Function : delete -%% Arguments : File -%% Returns : - -%% Description: -%%---------------------------------------------------------------------- -delete(_OE_This, State, File) when ?is_FTP(State); ?is_NATIVE(State) -> - Mod = ?get_Module(State), - Result = - case 'CosPropertyService_PropertySet': - get_property_value(File, "is_directory") of - #any{value=false} -> - Mod:delete(?get_Server(State), - filename:join('CosFileTransfer_File': - '_get_complete_file_name'(File))); - #any{value=true} -> - Mod:rmdir(?get_Server(State), - filename:join('CosFileTransfer_File': - '_get_complete_file_name'(File))); - Other -> - Other - end, - case Result of - ok -> - {reply, ok, State}; - {error, epath} -> - corba:raise(#'CosFileTransfer_FileNotFoundException' - {reason="File or Directory not found."}); - {error, elogin} -> - corba:raise(#'CosFileTransfer_SessionException' - {reason="User not loggen in."}); - {error, econn} -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Premature connection ending."}); - _ -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Unknown error."}) - end. - -%%---------------------------------------------------------------------- -%% Function : transfer -%% Arguments : SrcFile eq DestFile eq CosFileTransfer::File -%% Returns : - -%% Description: DestFile must be a newly created File object, using create_file() -%% on the Target FileTransferSession, prior to calling transfer(). -%%---------------------------------------------------------------------- -transfer(OE_This, State, SrcFile, DestFile) when ?is_ORBER_NATIVE(State) -> - case which_FTS_type(OE_This, SrcFile, DestFile) of - {source, TargetFTS} -> - %% The source FTS is supposed to be the active one, set up a connection. - Protocols = 'CosFileTransfer_FileTransferSession': - '_get_protocols_supported'(TargetFTS), - SrcName = 'CosFileTransfer_File':'_get_complete_file_name'(SrcFile), - Pid = spawn(?MODULE, invoke_call, [self(), transfer, - [TargetFTS, SrcFile, DestFile]]), - send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State), - filename:join(SrcName)), - check_reply(Pid), - {reply, ok, State}; - {target, _SourceFTS} -> - DestName = 'CosFileTransfer_File':'_get_complete_file_name'(DestFile), - receive_file(?get_MyType(State), ?get_Connection(State), - ?get_ConnectionTimeout(State), - filename:join(DestName), write), - {reply, ok, State} - end; -transfer(OE_This, State, SrcFile, DestFile) when ?is_FTP(State); ?is_NATIVE(State) -> - case which_FTS_type(OE_This, SrcFile, DestFile) of - {source, TargetFTS} -> - source_FTS_operation(State, SrcFile, DestFile, transfer, 0, TargetFTS); - {target, _SourceFTS} -> - target_FTS_operation(State, SrcFile, DestFile, send, 0) - end. - - -%%---------------------------------------------------------------------- -%% Function : append -%% Arguments : SrcFile eq DestFile eq CosFileTransfer::File -%% Returns : - -%% Description: -%%---------------------------------------------------------------------- -append(OE_This, State, SrcFile, DestFile) when ?is_ORBER_NATIVE(State) -> - case which_FTS_type(OE_This, SrcFile, DestFile) of - {source, TargetFTS} -> - SrcName = filename:join('CosFileTransfer_File': - '_get_complete_file_name'(SrcFile)), - check_type(OE_This, State, SrcName), - %% The source FTS is supposed to be the active one, set up a connection. - Protocols = 'CosFileTransfer_FileTransferSession': - '_get_protocols_supported'(TargetFTS), - Pid = spawn(?MODULE, invoke_call, [self(), append, - [TargetFTS, SrcFile, DestFile]]), - send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State), - SrcName), - check_reply(Pid), - {reply, ok, State}; - {target, _SourceFTS} -> - DestName = filename:join('CosFileTransfer_File': - '_get_complete_file_name'(DestFile)), - check_type(OE_This, State, DestName), - receive_file(?get_MyType(State), ?get_Connection(State), - ?get_ConnectionTimeout(State), DestName, append), - {reply, ok, State} - end; -append(OE_This, State, SrcFile, DestFile) when ?is_NATIVE(State) -> - case which_FTS_type(OE_This, SrcFile, DestFile) of - {source, TargetFTS} -> - source_FTS_operation(State, SrcFile, DestFile, append, 0, TargetFTS); - {target, _SourceFTS} -> - target_FTS_operation(State, SrcFile, DestFile, append, 0) - end; -append(_OE_This, _State, _SrcFile, _DestFile) -> - corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}). - - -%%---------------------------------------------------------------------- -%% Function : insert -%% Arguments : SrcFile eq DestFile eq CosFileTransfer::File -%% Offset - long -%% Returns : - -%% Description: -%%---------------------------------------------------------------------- -insert(OE_This, State, SrcFile, DestFile, Offset) when ?is_NATIVE(State) -> - case which_FTS_type(OE_This, SrcFile, DestFile) of - {source, TargetFTS} when ?is_ORBER_NATIVE(State) -> - SrcName = 'CosFileTransfer_File':'_get_complete_file_name'(SrcFile), - check_type(OE_This, State, filename:join(SrcName)), - %% The source FTS is supposed to be the active one, set up a connection. - Protocols = 'CosFileTransfer_FileTransferSession': - '_get_protocols_supported'(TargetFTS), - Pid = spawn(?MODULE, invoke_call, [self(), insert, - [TargetFTS, SrcFile, - DestFile, Offset]]), - send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State), - filename:join(SrcName)), - check_reply(Pid), - {reply, ok, State}; - {source, TargetFTS} -> - source_FTS_operation(State, SrcFile, DestFile, insert, Offset, TargetFTS); - {target, _SourceFTS} -> - target_FTS_operation(State, SrcFile, DestFile, insert, Offset) - end; -insert(_OE_This, _State, _SrcFile, _DestFile, _Offset) -> - corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}). - - -%%---------------------------------------------------------------------- -%% Function : logout -%% Arguments : - -%% Returns : - -%% Description: -%%---------------------------------------------------------------------- -logout(_OE_This, State) when ?is_FTP(State); ?is_NATIVE(State) -> - Mod = ?get_Module(State), - catch Mod:close(?get_Server(State)), - {stop, normal, ok, State}. - -%%====================================================================== -%% Internal functions -%%====================================================================== -%%---------------------------------------------------------------------- -%% Function : oe_orber_create_directory_current -%% Arguments : - -%% Returns : Directory -%% Description: Creates a Directory describing the working directory -%% of the remote server, e.g., an FTP-server. -%%---------------------------------------------------------------------- -oe_orber_create_directory_current(OE_This, State) when ?is_FTP(State); - ?is_NATIVE(State) -> - Mod = ?get_Module(State), - FileNameList = filename:split(?get_CurrentDir(State)), - case Mod:nlist(?get_Server(State), ?get_CurrentDir(State)) of - {ok, _Listing} -> - {reply, cosFileTransferApp:create_dir(OE_This, FileNameList), - State}; - {error, epath} -> - corba:raise(#'CosFileTransfer_FileNotFoundException' - {reason="Directory not found."}); - {error, elogin} -> - corba:raise(#'CosFileTransfer_SessionException' - {reason="User not loggen in."}); - {error, econn} -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Premature connection ending."}); - _ -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Unknown error."}) - end. -%%---------------------------------------------------------------------- -%% Function : oe_orber_get_content -%% Arguments : - -%% Returns : string -%% Description: -%%---------------------------------------------------------------------- -oe_orber_get_content(OE_This, State, FileNameList, Parent) when ?is_FTP(State); - ?is_NATIVE(State) -> - Mod = ?get_Module(State), - case Mod:nlist(?get_Server(State), filename:join(FileNameList)) of - {ok, Listing} -> - create_content(Listing, OE_This, State, Parent, FileNameList); - {error, epath} -> - {reply, [], State}; - _ -> - corba:raise(#'CosFileTransfer_FileNotFoundException' - {reason="Directory not found."}) - end. - -%%---------------------------------------------------------------------- -%% Function : oe_orber_count_children -%% Arguments : - -%% Returns : string -%% Description: -%%---------------------------------------------------------------------- -oe_orber_count_children(OE_This, State, FileNameList) when ?is_FTP(State); - ?is_NATIVE(State) -> - case catch check_type(OE_This, State, filename:join(FileNameList)) of - {ndirectory, Members} -> - {reply, length(Members), State}; - {stop, normal, _, _} -> - {stop, normal, - {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}, - State}; - _-> - corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) - end. - -%%---------------------------------------------------------------------- -%% Function : delete_tmp_file -%% Arguments : - -%% Returns : ok | {'EXCEPTION', E} -%% Description: -%%---------------------------------------------------------------------- -delete_tmp_file(TmpFileName, ErrorMsg) -> - case file:delete(TmpFileName) of - ok -> - ok; - _ -> - corba:raise(#'CosFileTransfer_RequestFailureException'{reason=ErrorMsg}) - end. - - -%%---------------------------------------------------------------------- -%% Function : invoke_call -%% Arguments : - -%% Returns : ok | {'EXCEPTION', E} -%% Description: -%%---------------------------------------------------------------------- -invoke_call(Pid, Op, Args) -> - Result = (catch apply('CosFileTransfer_FileTransferSession', Op, Args)), - Pid ! {transfer_result, self(), Result}, - ok. - -%%---------------------------------------------------------------------- -%% Function : check_reply -%% Arguments : Pid - the pid of the spawned process. -%% Returns : ok | {'EXCEPTION', E} -%% Description: -%%---------------------------------------------------------------------- -check_reply(Pid) -> - receive - {transfer_result, Pid, ok} -> - ok; - {transfer_result, Pid, {'EXCEPTION', E}} -> - orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:check_reply(); -Raised exception: ", [?LINE, E], ?DEBUG_LEVEL), - corba:raise(E); - {transfer_result, Pid, {'EXIT', Reason}} -> - orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:check_reply(); -Got EXIT-signal with reason: ", [?LINE, Reason], ?DEBUG_LEVEL), - corba:raise(#'INTERNAL'{minor=199, - completion_status=?COMPLETED_NO}) - after infinity -> - %% Should we add an exception here or do we reuse the iiop_timeout? - %% For now keep as is. - corba:raise(#'INTERNAL'{minor=199, - completion_status=?COMPLETED_NO}) - end. - - -%%---------------------------------------------------------------------- -%% Function : which_FTS_type -%% Arguments : - -%% Returns : {source, FTS} | {target, FTS} | {'EXCEPTION', #'BAD_PARAM'{}} -%% Description: Used to determine if the target FTS is supposed to act -%% as sender or receiver and also return the counter part FTS. -%% An exception is raised if the user supplied incorrect parameters. -%%---------------------------------------------------------------------- -which_FTS_type(OE_This, SrcFile, DestFile) -> - TargetFTS = 'CosFileTransfer_File':'_get_associated_session'(DestFile), - SourceFTS = 'CosFileTransfer_File':'_get_associated_session'(SrcFile), - case corba_object:is_equivalent(OE_This, TargetFTS) of - true -> - {target, SourceFTS}; - false -> - case corba_object:is_equivalent(OE_This, SourceFTS) of - true -> - {source, TargetFTS}; - false -> - corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}) - end - end. - - -%%---------------------------------------------------------------------- -%% Function : setup_connection -%% Arguments : A list of #'CosFileTransfer_ProtocolSupport'{} -%% Returns : -%% Description: -%%---------------------------------------------------------------------- -setup_connection([], Protocol, _) -> - orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:setup_connection(~p); -The Protocols listed are not supported.", [?LINE, Protocol], ?DEBUG_LEVEL), - corba:raise(#'CosFileTransfer_TransferException'{reason="Unsupported protocol"}); -setup_connection([#'CosFileTransfer_ProtocolSupport'{protocol_name="TCP/IP", - addresses=Addr}|_], - tcp, Timeout) -> - setup_connection_helper(Addr, gen_tcp, [], Timeout); -setup_connection([#'CosFileTransfer_ProtocolSupport'{protocol_name="SSL", - addresses=Addr}|_], - ssl, Timeout) -> - Options = [{certfile, cosFileTransferApp:ssl_client_certfile()}, - {verify, cosFileTransferApp:ssl_client_verify()}, - {depth, cosFileTransferApp:ssl_client_depth()}] ++ - ssl_client_cacertfile_option(), - setup_connection_helper(Addr, ssl, Options, Timeout); -setup_connection([_|T], Type, Timeout) -> - setup_connection(T, Type, Timeout). - -setup_connection_helper([], _, _, _) -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Unable to contact remote server."}); -setup_connection_helper([H|T], Driver, Options, Timeout) -> - case string:tokens(H, ":") of - [Host, Port] when Driver == gen_tcp -> - case gen_tcp:connect(Host, list_to_integer(Port), - [binary, - {packet, raw}, - {reuseaddr, true}, - {nodelay, true}|Options], Timeout) of - {ok, Sock} -> - {gen_tcp, Sock}; - _-> - %% No response. - setup_connection_helper(T, Driver, Options, Timeout) - end; - [Host, Port] when Driver == ssl -> - case ssl:connect(Host, list_to_integer(Port), - [binary, - {packet, 0}, - {active, false}|Options], Timeout) of - {ok, Sock} -> - {ssl, Sock}; - _-> - %% No response. - setup_connection_helper(T, Driver, Options, Timeout) - end; - _ -> - %% Badly configured address. - setup_connection_helper(T, Driver, Options, Timeout) - end. - -ssl_client_cacertfile_option() -> - case cosFileTransferApp:ssl_client_cacertfile() of - [] -> - []; - X when is_list(X) -> - {cacertfile, X}; - _ -> - [] - end. - -%%---------------------------------------------------------------------- -%% Function : create_content -%% Arguments : -%% Returns : -%% Description: -%%---------------------------------------------------------------------- -create_content(Listing, OE_This, State, Parent, PathList) -> - create_content(string:tokens(Listing, ?SEPARATOR), OE_This, - State, Parent, PathList, []). - -create_content([], _OE_This, State, _Parent, _PathList, Acc) -> - {reply, Acc, State}; -create_content([H|T], OE_This, State, Parent, PathList, Acc) -> - FullPathList = PathList ++[filename:basename(H)], - case check_type(OE_This, State, filename:join(FullPathList)) of - nfile -> - create_content(T, OE_This, State, Parent, PathList, - [#'CosFileTransfer_FileWrapper' - {the_file = cosFileTransferApp:create_file(OE_This, - FullPathList, - Parent), - file_type = nfile}|Acc]); - {ndirectory, _Members} -> - create_content(T, OE_This, State, Parent, PathList, - [#'CosFileTransfer_FileWrapper' - {the_file = cosFileTransferApp:create_dir(OE_This, - FullPathList, - Parent), - file_type = ndirectory}|Acc]); - Other -> - Other - end. - - -%%---------------------------------------------------------------------- -%% Function : MISC functions -%% Arguments : -%% Returns : -%% Description: -%%---------------------------------------------------------------------- -setup_local(tcp) -> - {ok,Socket}=gen_tcp:listen(0, [binary, - {packet, 0}, - {backlog,1}, - {active, false}]), - {ok, Port} = inet:port(Socket), - {Socket, [#'CosFileTransfer_ProtocolSupport'{protocol_name="TCP/IP", - addresses = [local_address(Port)]}]}; -setup_local(ssl) -> - Options = [{certfile, cosFileTransferApp:ssl_server_certfile()}, - {verify, cosFileTransferApp:ssl_server_verify()}, - {depth, cosFileTransferApp:ssl_server_depth()}] ++ - ssl_server_cacertfile_option(), - {ok,Socket}=ssl:listen(0, [binary, - {packet, 0}, - {backlog,1}, - {active, false}|Options]), - {ok, {_Address, Port}} = ssl:sockname(Socket), - {Socket, [#'CosFileTransfer_ProtocolSupport'{protocol_name="SSL", - addresses = [local_address(Port)]}]}. - -local_address(Port) -> - {ok, Hostname} = inet:gethostname(), - {ok, {A1, A2, A3, A4}} = inet:getaddr(Hostname, inet), - integer_to_list(A1) ++ "." ++ integer_to_list(A2) ++ "." ++ integer_to_list(A3) - ++ "." ++ integer_to_list(A4)++":"++integer_to_list(Port). - -ssl_server_cacertfile_option() -> - case cosFileTransferApp:ssl_server_cacertfile() of - [] -> - []; - X when is_list(X) -> - [{cacertfile, X}]; - _ -> - [] - end. - -%%---------------------------------------------------------------------- -%% Function : source_file_operation -%% Arguments : -%% Returns : -%% Description: -%%---------------------------------------------------------------------- -source_FTS_operation(State, SrcFile, DestFile, Op, Offset, FTS) -> - Mod = ?get_Module(State), - %% The source FTS is supposed to be the active one, set up a connection. - Protocols = 'CosFileTransfer_FileTransferSession':'_get_protocols_supported'(FTS), - SrcName = 'CosFileTransfer_File':'_get_complete_file_name'(SrcFile), - TempName = cosFileTransferApp:create_name("TemporarySrcFile"), - case Mod:recv(?get_Server(State), filename:join(SrcName), TempName) of - ok when Op == insert -> - %% Downloaded the File, we are now ready to transmit. - Pid = spawn(?MODULE, invoke_call, [self(), insert, - [FTS, SrcFile, DestFile, Offset]]), - send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State), - TempName), - %% Delete the temporary local copy. - delete_tmp_file(TempName, - "Transfer completed but failed to remove temporary local copy."), - check_reply(Pid), - {reply, ok, State}; - ok -> - %% Downloaded the File, we are now ready to transmit. - Pid = spawn(?MODULE, invoke_call, [self(), Op, [FTS, SrcFile, DestFile]]), - send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State), - TempName), - %% Delete the temporary local copy. - delete_tmp_file(TempName, - "Transfer completed but failed to remove temporary local copy."), - check_reply(Pid), - {reply, ok, State}; - {error, epath} -> - corba:raise(#'CosFileTransfer_FileNotFoundException' - {reason="File not found."}); - {error, elogin} -> - corba:raise(#'CosFileTransfer_SessionException' - {reason="User not loggen in."}); - {error, econn} -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Premature connection ending."}) - end. - -%%---------------------------------------------------------------------- -%% Function : target_file_operation -%% Arguments : -%% Returns : -%% Description: -%%---------------------------------------------------------------------- -target_FTS_operation(State, _SrcFile, DestFile, Op, Offset) -> - Mod = ?get_Module(State), - DestName = 'CosFileTransfer_File':'_get_complete_file_name'(DestFile), - TempName = cosFileTransferApp:create_name("TemporaryDestFile"), - receive_file(?get_MyType(State), ?get_Connection(State), - ?get_ConnectionTimeout(State), TempName, write), - Result = - if - Op == insert -> - Mod:insert(?get_Server(State), TempName, filename:join(DestName), Offset); - true -> - Mod:Op(?get_Server(State), TempName, filename:join(DestName)) - end, - case Result of - ok -> - %% Delete the temporary local copy. - delete_tmp_file(TempName, - "Transfer completed but failed to remove temporary local copy."), - %% Completed the transfer successfully. - {reply, ok, State}; - {error, epath} -> - delete_tmp_file(TempName, - "IllegalOperationException and not able to remove temporary local copy."), - corba:raise(#'CosFileTransfer_IllegalOperationException' - {reason="Not allowed by destination."}); - {error, elogin} -> - delete_tmp_file(TempName, - "SessionException and not able to remove temporary local copy."), - corba:raise(#'CosFileTransfer_SessionException' - {reason="User not logged in."}); - {error, econn} -> - delete_tmp_file(TempName, - "TransferException and not able to remove temporary local copy."), - corba:raise(#'CosFileTransfer_TransferException' - {reason="Premature connection ending."}); - {error, etnospc} -> - delete_tmp_file(TempName, - "RequestFailureException and not able to remove temporary local copy."), - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Premature connection ending."}); - {error, efnamena} -> - delete_tmp_file(TempName, - "IllegalOperationException and not able to remove temporary local copy."), - corba:raise(#'CosFileTransfer_IllegalOperationException' - {reason="Not allowed by destination."}) - end. - -%%---------------------------------------------------------------------- -%% Function : receive_file -%% Arguments : Driver - currently only gen_tcp supported. -%% LSocket - which socket to use. -%% FileName - an absolute file name representing the -%% file we want to create or append to. -%% Type - 'read', 'write', 'append'. -%% Returns : -%% Description: -%%---------------------------------------------------------------------- -receive_file(tcp, LSock, Timeout, FileName, Type) -> - %% The Type can be the ones allowed by the file-module, i.e., - %% 'read', 'write' or 'append' - FD = file_open(FileName, Type), - case gen_tcp:accept(LSock, Timeout) of - {ok, Sock} -> - receive_file_helper(gen_tcp, Sock, FD); - {error, timeout} -> - orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n" - "gen_tcp:accept(~p) timed out", [?LINE, Timeout], ?DEBUG_LEVEL), - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="TCP accept timed out.."}); - {error, Why} -> - orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n" - "gen_tcp:accept(~p) failed: ~p", [?LINE, Timeout, Why], ?DEBUG_LEVEL), - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="TCP accept failed."}) - end; -receive_file(ssl, LSock, Timeout, FileName, Type) -> - %% The Type can be the ones allowed by the file-module, i.e., - %% 'read', 'write' or 'append' - FD = file_open(FileName, Type), - case ssl:transport_accept(LSock, Timeout) of - {ok, Sock} -> - case ssl:ssl_accept(Sock, Timeout) of - ok -> - receive_file_helper(ssl, Sock, FD); - {error, Error} -> - orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n" - "ssl:ssl_accept(~p) failed: ~p", - [?LINE, Timeout, Error], ?DEBUG_LEVEL), - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="TCP accept failed."}) - end; - {error, timeout} -> - orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n" - "ssl:transport_accept(~p) timed out", - [?LINE, Timeout], ?DEBUG_LEVEL), - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="TCP accept timed out.."}); - {error, Why} -> - orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n" - "ssl:transport_accept(~p) failed: ~p", - [?LINE, Timeout, Why], ?DEBUG_LEVEL), - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="TCP accept failed."}) - end. - -receive_file_helper(Driver, Sock, FD) -> - case Driver:recv(Sock, 0) of - {ok, Bin} -> - file:write(FD, Bin), - receive_file_helper(Driver, Sock, FD); - {error, closed} -> - file:close(FD); - What -> - orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:receive_file(~p); -Error occured when receiving data: ~p", [?LINE, Driver, What], ?DEBUG_LEVEL), - corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) - end. - -%%---------------------------------------------------------------------- -%% Function : send_file -%% Arguments : Driver - currently only gen_tcp supported. -%% Sock - which socket to use. -%% FileName - an absolute file name representing the -%% file we want to send. -%% Returns : -%% Description: -%%---------------------------------------------------------------------- -send_file(Protocols, Type, Timeout, FileName) -> - {Driver, Sock} = setup_connection(Protocols, Type, Timeout), - FD = file_open(FileName, read), - BuffSize = cosFileTransferApp:get_buffert_size(), - send_file_helper(Driver, Sock, FD, BuffSize). - -send_file_helper(Driver, Sock, FD, BuffSize) -> - case file:read(FD, BuffSize) of - eof -> - file:close(FD), - Driver:close(Sock); - {ok, Bin} -> - case Driver:send(Sock, Bin) of - ok -> - send_file_helper(Driver, Sock, FD, BuffSize); - What -> - orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:send_file_helper(~p); -Error occured when sending data: ~p", [?LINE, Driver, What], ?DEBUG_LEVEL), - corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) - end - end. - - -file_open(File, Type) -> - case file:open(File, [raw, binary, Type]) of - {ok, FD} -> - FD; - {error, What} -> - orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:file_open(~p); -Failed to open the file due to: ~p", [?LINE, File, What], ?DEBUG_LEVEL), - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Unable to open given file."}) - end. - -%%---------------------------------------------------------------------- -%% Function : check_type -%% Arguments : FullName - an absolute file name representing the -%% file or directory we want to evaluate. -%% Returns : -%% Description: -%% When communcating with FTP-servers on different platforms a variety of -%% answers can be returned. A few examples: -%% -%% ### ftp:nlist on an empty directory ### -%% {ok, ""}, {error, epath} -%% -%% ### ftp:nlist on a non-existing directory or file ### -%% {ok, "XXX: No such file or directory}, {error, epath} -%% -%% ### ftp:nlist on an existing directory with one contained item ### -%% {ok, "Item"} -%% -%% Comparing the above we see that it's virtually impossible to tell apart -%% {ok, "XXX: No such file or directory} and {ok, "Item"}. -%% Hence, it's easier to test if it's possible to do ftp:cd instead. -%% Ugly, but rather effective. If we look at the bright side, it's only -%% necessary when we try to lookup: -%% * non-existing item -%% * A directory with one member only. -%% * An empty directory. -%% -%% Furthermore, no need for traversing Listings etc. -%%---------------------------------------------------------------------- -check_type(_OE_This, State, FullName) when ?is_FTP(State); ?is_NATIVE(State) -> - Mod = ?get_Module(State), - Result = - case Mod:nlist(?get_Server(State), FullName) of - {ok, Listing} when length(Listing) > 0-> - case string:tokens(Listing, ?SEPARATOR) of - [FullName] -> - nfile; - Members when length(Members) > 1 -> - %% Must test if more than one member since sometimes - %% this operation returns for example: - %% {ok, "XXX No such file or drectory"} - {ndirectory, Members}; - Member -> - case Mod:cd(?get_Server(State), FullName) of - ok -> - case Mod:cd(?get_Server(State), - ?get_CurrentDir(State)) of - ok -> - {ndirectory, Member}; - _ -> - %% Failed, we cannot continue since the - %% FTS now pointso an incorrect Directory. - %% Hence, we must terminate. - {stop, normal, - {'EXCEPTION', - #'CosFileTransfer_RequestFailureException' - {reason="Unknown error."}}, State} - end; - {error, E} -> - {error, E}; - _ -> - nfile - end - end; - {error, epath} -> - %% Might be a file. - DirName = filename:dirname(FullName), - case Mod:nlist(?get_Server(State), DirName) of - {ok, Listing} when length(Listing) > 0-> - Members = string:tokens(Listing, ?SEPARATOR), - case lists:member(FullName, Members) of - true -> - nfile; - _ -> - BName = filename:basename(FullName), - case lists:member(BName, Members) of - true -> - nfile; - _ -> - {error, epath} - end - end; - _ -> - {error, epath} - end; - _ -> - case Mod:cd(?get_Server(State), FullName) of - ok -> - case Mod:cd(?get_Server(State), ?get_CurrentDir(State)) of - ok -> - {ndirectory, []}; - _ -> - %% Failed, we cannot continue since the - %% FTS now pointso an incorrect Directory. - %% Hence, we must terminate. - {stop, normal, - {'EXCEPTION', - #'CosFileTransfer_RequestFailureException' - {reason="Unknown error."}}, State} - end; - _ -> - {error, epath} - end - end, - case Result of - {error, epath} -> - corba:raise(#'CosFileTransfer_FileNotFoundException' - {reason="File or Directory not found."}); - {error, elogin} -> - corba:raise(#'CosFileTransfer_SessionException' - {reason="User not logged in."}); - {error, econn} -> - corba:raise(#'CosFileTransfer_RequestFailureException' - {reason="Premature connection ending."}); - Other -> - Other - end. - - - -%%====================================================================== -%% END OF MODULE -%%====================================================================== |