If you need to FTP with PL/SQL...

If you need to perform FTP from within PL/SQL and your database version has the UTL_TCP package, here is a free package you can use. The source code is hopefully documented well enough for you to tell what's going on and how to use the functions. Suggestions on improving the code are welcome, and I can provide limited support via email for what I've written, but I would encourage anyone who uses the code to modify/fix it according to their needs. If you modify the code, I respectfully request that you leave intact the authorship and note comments at the beginning of the package.
Please note that I have not rigorously tested this code, but it has successfully transferred files in both directions in the limited tests that I have performed.
-- Copy the code below and run it in your favorite SQL editor --
CREATE OR REPLACE PACKAGE FTP IS
Simplified FTP client API using UTL_TCP package
Author: Alan Wessman, Brigham Young University
Note: This FTP client attempts to adhere to the protocol and advice found at:
http://cr.yp.to/ftp.html
No warranties are made regarding the correctness of this code.
Notes:
1. Most of these functions will raise UTL_TCP.NETWORK_ERROR if the connection
is not open or is reset during the network transaction. They will also
raise VALUE_ERROR if the server response is ill-formed or a buffer is
too small to hold data. (Most buffers in this package are defined as
VARCHAR2(32767) to avoid size limitations; reduce this if memory overhead
is a concern.)
2. "Verbose mode" can be enabled/disabled by changing the default value of
the vDebug variable in the package body. Setting vDebug to TRUE will
cause a session transcript to be output to DBMS_OUTPUT.
3. The following is an example of how this package might be used:
declare
c utl_tcp.connection;
vresp varchar2(32767);
vbuf varchar2(32767);
vresp_code number;
vremote_host varchar2(32) := 'some.hostname.com';
vusername varchar2(8) := 'username';
vpassword varchar2(8) := 'password';
begin
dbms_output.put_line( 'Opening session...' );
vresp_code := ftp.open_session( c,
vremote_host,
vusername,
vpassword,
vresp,
5 );
vresp_code := ftp.put( c,
'/home/somebody',
'local.test',
'remote.test',
vresp );
vresp_code := ftp.remote_command( c, 'CHMOD 660 remote.test' );
vresp_code := ftp.chdir( c, '/home/somebody/subdir' );
vresp_code := ftp.pwd( c );
vresp_code := ftp.get( c,
'/home/somebody',
'new_file.test',
'another_remote_file.test',
vresp );
vresp_code := ftp.close_session( c );
dbms_output.put_line( 'Closed session.' );
exception
when others then dbms_output.put_line( sqlcode || ':' || sqlerrm );
end;
Function: Open_Session
Description: Begins an FTP session with the remote server.
Parameters:
conn OUT parameter that contains the connection info; to be passed
in to subsequent commands to maintain session state.
host Name or IP address of remote server
username User ID to use for login
password Password to use for login
response OUT parameter; buffer for server replies
timeout_secs Number of seconds for TCP timeout. Pass in NULL to disable
timeout (wait forever for responses). Pass in 0 (zero) for
no wait.
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if host parameter is incorrect or if
some other networking error occurs.
May raise VALUE_ERROR if server response is ill-formed.
FUNCTION Open_Session( conn OUT NOCOPY UTL_TCP.Connection,
host IN VARCHAR2,
username IN VARCHAR2,
password IN VARCHAR2,
response OUT VARCHAR2,
timeout_secs IN NUMBER DEFAULT 60 ) RETURN NUMBER;
Function: Get
Description: Retrieves a file on the remote server and stores its contents in
a VARCHAR2 buffer.
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
buf OUT parameter; buffer for retrieved file contents
remote_path Pathname (including file name) indicating location of remote
file to be retrieved
response OUT parameter; buffer for server replies.
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if some networking error occurs.
May raise VALUE_ERROR if server response is ill-formed or buf is
too small for file contents.
FUNCTION Get( conn IN OUT NOCOPY UTL_TCP.Connection,
buf OUT VARCHAR2,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER;
Function: Get
Description: Retrieves a file on the remote server and stores its contents in
a local file. Assumes an open file handle and does not close it.
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
local_file IN OUT parameter; UTL_FILE file handle for input file. File
is assumed to be open for writing.
remote_path Pathname (including file name) indicating location of remote
file to be retrieved
response OUT parameter; buffer for server replies.
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if some networking error occurs.
May raise VALUE_ERROR if server response is ill-formed or buf is
too small for file contents.
May raise any of the UTL_FILE exceptions if file write operations
fail. See UTL_FILE documentation for additional details.
FUNCTION Get( conn IN OUT NOCOPY UTL_TCP.Connection,
local_file IN OUT UTL_FILE.File_Type,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER;
Function: Get
Description: Retrieves a file on the remote server and stores its contents in
a local file. Opens and closes local file automatically.
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
local_path Pathname of local directory in which to store the retrieved
file's contents
local_filename Name of local file in which to store retrieved file's contents
(creates new file or overwrites existing file)
remote_path Pathname (including file name) indicating location of remote
file to be retrieved
response OUT parameter; buffer for server replies.
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if some networking error occurs.
May raise VALUE_ERROR if server response is ill-formed or buf is
too small for file contents.
May raise any of the UTL_FILE exceptions if file open, write, or
close operations fail. See UTL_FILE documentation for additional
details.
FUNCTION Get( conn IN OUT NOCOPY UTL_TCP.Connection,
local_path IN VARCHAR2,
local_filename IN VARCHAR2,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER;
Function: Put
Description: Stores data as a file on the remote server
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
buf IN parameter; contains data to upload
remote_path Pathname (including file name) indicating location of remote
file to be created/overwritten
response OUT parameter; buffer for server replies.
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if some networking error occurs.
May raise VALUE_ERROR if server response is ill-formed.
FUNCTION Put( conn IN OUT NOCOPY UTL_TCP.Connection,
buf IN VARCHAR2,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER;
Function: Put
Description: Uploads a local file to the remote server. Assumes an open file
handle and does not close it.
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
local_file IN OUT parameter; UTL_FILE file handle for input file. File
is assumed to be open for reading.
remote_path Pathname (including file name) indicating location of remote
file to be created/overwritten.
response OUT parameter; buffer for server replies.
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if some networking error occurs.
May raise VALUE_ERROR if server response is ill-formed.
May raise any of the UTL_FILE exceptions if file read operations
fail. See UTL_FILE documentation for additional details.
FUNCTION Put( conn IN OUT NOCOPY UTL_TCP.Connection,
local_file IN OUT UTL_FILE.File_Type,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER;
Function: Put
Description: Uploads a local file to the remote server. Opens and closes local
file automatically.
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
local_path Pathname of local directory in which file to upload exists.
local_filename Name of local file to upload.
remote_path Pathname (including file name) indicating location of remote
file to be created/overwritten.
response OUT parameter; buffer for server replies.
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if some networking error occurs.
May raise VALUE_ERROR if server response is ill-formed.
May raise any of the UTL_FILE exceptions if file open, read, or
close operations fail. See UTL_FILE documentation for additional
details.
FUNCTION Put( conn IN OUT NOCOPY UTL_TCP.Connection,
local_path IN VARCHAR2,
local_filename IN VARCHAR2,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER;
Function: Remote_Command
Description: Sends an arbitrary command to the server via the SITE command.
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
command Command and parameter(s) to send to the server, e.g.
'CHMOD 600 foo.txt'
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if some networking error occurs.
May raise VALUE_ERROR if server response is ill-formed.
FUNCTION Remote_Command( conn IN OUT NOCOPY UTL_TCP.Connection,
command IN VARCHAR2 ) RETURN NUMBER;
Function: Chdir
Description: Changes current working directory on remote server to specified
path.
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
remote_path Path on remote server to change to.
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if some networking error occurs.
May raise VALUE_ERROR if server response is ill-formed.
FUNCTION Chdir( conn IN OUT NOCOPY UTL_TCP.Connection,
remote_path IN VARCHAR2 ) RETURN NUMBER;
Function: Pwd
Description: Prints current working directory (on remote server) to debugging
output if debugging is turned on.
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
Return value: 0 (zero) if operation is successful; FTP error code if operation
is not successful.
Exceptions: May raise UTL_TCP.NETWORK_ERROR if some networking error occurs.
May raise VALUE_ERROR if server response is ill-formed.
FUNCTION Pwd( conn IN OUT NOCOPY UTL_TCP.Connection ) RETURN NUMBER;
Function: Close_Session
Description: Closes the TCP connection to the remote server.
Parameters:
conn IN OUT parameter that contains the connection info; to be
passed in to subsequent commands to maintain session state.
Return value: 0 (zero)
Exceptions: None raised.
FUNCTION Close_Session( conn IN OUT NOCOPY UTL_TCP.Connection ) RETURN NUMBER;
Function: Close_All_Sessions
Description: Closes all currently open TCP connections.
Parameters: None.
Return value: 0 (zero)
Exceptions: None raised.
FUNCTION Close_All_Sessions RETURN NUMBER;
END FTP;
CREATE OR REPLACE PACKAGE BODY FTP IS
vDebug BOOLEAN := TRUE;
FATAL_ERROR EXCEPTION;
PROCEDURE Debug( msg IN VARCHAR2 ) IS
BEGIN
IF vDebug THEN
DBMS_OUTPUT.Put_Line( msg );
END IF;
END Debug;
FUNCTION Get_Response( conn IN OUT NOCOPY UTL_TCP.Connection,
buf IN OUT VARCHAR2 ) RETURN NUMBER IS
vLen NUMBER;
vCode NUMBER;
vResp VARCHAR2(32767);
BEGIN
vLen := UTL_TCP.READ_LINE( conn, vResp );
Debug( vResp );
-- If TO_NUMBER below fails, let the exception propagate to calling proc
vCode := TO_NUMBER( SUBSTR( vResp, 1, 3 ) );
vResp := SUBSTR( vResp, 4 );
buf := buf || SUBSTR( vResp, 2 );
IF SUBSTR( vResp, 1, 1 ) = '-' THEN
LOOP
vLen := UTL_TCP.READ_LINE( conn, vResp );
Debug( vResp );
<<Get_Code>>
BEGIN
vCode := TO_NUMBER( SUBSTR( vResp, 1, 3 ) );
vResp := SUBSTR( vResp, 4 );
IF SUBSTR( vResp, 1, 1 ) = ' ' THEN
buf := buf || SUBSTR( vResp, 2 );
EXIT;
END IF;
EXCEPTION WHEN VALUE_ERROR THEN NULL;
END Get_Code;
buf := buf || vResp;
END LOOP;
END IF;
RETURN vCode;
END Get_Response;
FUNCTION Do_Command( conn IN OUT NOCOPY UTL_TCP.Connection,
cmd IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER IS
vResult NUMBER := 0;
BEGIN
vResult := UTL_TCP.WRITE_LINE( conn, cmd );
vResult := Get_Response( conn, response );
RETURN vResult;
END Do_Command;
FUNCTION Parse_Port_Number( port_string IN VARCHAR2 ) RETURN NUMBER IS
vResult NUMBER;
vNew_Port_String VARCHAR2(32767);
BEGIN
-- This stuff parses out the port number encoding from the server reply
-- Reply is in the format xyzh1,h2,h3,h4,p1,p2xyz
-- xyz = possible character data (server-dependent, may not exist)
-- h1-h4 = server IP elements; ignore since we know the host already
-- p1,p2 = port number encoding (port number = p1 * 256 + p2 )
vNew_Port_String := TRANSLATE( port_string, '0123456789', '0000000000' );
vNew_Port_String := SUBSTR( port_string,
INSTR( vNew_Port_String, '0' ),
INSTR( vNew_Port_String, '0', -1 ) -
INSTR( vNew_Port_String, '0' ) + 1 );
vNew_Port_String := SUBSTR( vNew_Port_String,
INSTR( vNew_Port_String, ',', 1, 4 ) + 1 );
vResult := 256 * TO_NUMBER( SUBSTR( vNew_Port_String,
1,
INSTR( vNew_Port_String, ',' ) - 1 ) );
vResult := vResult + TO_NUMBER( SUBSTR( vNew_Port_String,
INSTR( vNew_Port_String, ',' ) + 1 ) );
RETURN vResult;
-- Allow VALUE_ERROR to propagate
END Parse_Port_Number;
FUNCTION Open_Session( conn OUT NOCOPY UTL_TCP.Connection,
host IN VARCHAR2,
username IN VARCHAR2,
password IN VARCHAR2,
response OUT VARCHAR2,
timeout_secs IN NUMBER DEFAULT 60 ) RETURN NUMBER IS
vResp_Code NUMBER;
vGarbage NUMBER; -- For calling functions when we don't care about return val
BEGIN
conn := UTL_TCP.OPEN_CONNECTION( host,
21,
tx_timeout => timeout_secs );
vResp_Code := Get_Response( conn, response );
IF vResp_Code = 220 THEN
vResp_Code := Do_Command( conn, 'USER ' || username, response );
IF vResp_Code IN ( 331, 332 ) THEN
vResp_Code := Do_Command( conn, 'PASS ' || password, response );
IF vResp_Code NOT IN ( 202, 230 ) THEN
RAISE FATAL_ERROR;
END IF;
ELSE
RAISE FATAL_ERROR;
END IF;
END IF;
vResp_Code := Do_Command( conn, 'TYPE I', response );
Debug( 'Logged into ' || conn.remote_host || ' at port ' || conn.remote_port );
RETURN 0;
EXCEPTION
WHEN FATAL_ERROR THEN
Debug( 'Fatal error opening session:' );
Debug( ' Code: ' || vResp_Code );
Debug( ' Response: ' || response );
vGarbage := Close_Session( conn );
RETURN vResp_Code;
END Open_Session;
FUNCTION Get( conn IN OUT NOCOPY UTL_TCP.Connection,
buf OUT VARCHAR2,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER IS
vResp VARCHAR2(32767);
vResp_Code NUMBER;
vNew_Conn UTL_TCP.Connection;
vNew_Port NUMBER;
BEGIN
-- do PASV
vResp_Code := Do_Command( conn, 'PASV', response );
IF vResp_Code = 227 THEN
<<Switch_Port>>
BEGIN
vNew_Port := Parse_Port_Number( response );
vNew_Conn := UTL_TCP.OPEN_CONNECTION( conn.remote_host,
vNew_Port,
tx_timeout => conn.tx_timeout );
Debug( 'Data connection: ' || vNew_Conn.remote_host || ':' || vNew_Conn.remote_port );
vResp_Code := Do_Command( conn, 'RETR ' || REPLACE( remote_path, CHR(12), CHR(0) ), response );
IF vResp_Code <> 150 THEN
RAISE FATAL_ERROR;
END IF;
<<Get_Download>>
BEGIN
LOOP
vResp := vResp || UTL_TCP.GET_LINE( vNew_Conn, FALSE );
END LOOP;
EXCEPTION
WHEN UTL_TCP.END_OF_INPUT THEN NULL;
END Get_Download;
vResp_Code := Close_Session( vNew_Conn );
vResp_Code := Get_Response( conn, response );
IF vResp_Code BETWEEN 400 AND 599 THEN
RAISE FATAL_ERROR;
END IF;
EXCEPTION
WHEN OTHERS THEN
Debug( SQLERRM );
RAISE FATAL_ERROR;
END Switch_Port;
ELSE
RAISE FATAL_ERROR;
END IF;
vResp_Code := Close_Session( vNew_Conn );
buf := vResp;
RETURN 0;
EXCEPTION
WHEN FATAL_ERROR THEN
Debug( 'Fatal error getting ' || remote_path || ':' );
Debug( ' Code: ' || vResp_Code );
Debug( ' Response: ' || response );
vResp_Code := Close_Session( vNew_Conn );
RETURN vResp_Code;
WHEN OTHERS THEN
Debug( vResp_Code || ': ' || SQLERRM );
RETURN vResp_Code;
END Get;
FUNCTION Get( conn IN OUT NOCOPY UTL_TCP.Connection,
local_file IN OUT UTL_FILE.File_Type,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER IS
vResp VARCHAR2(32767);
vResp_Code NUMBER := -1;
vNew_Conn UTL_TCP.Connection;
vNew_Port NUMBER;
BEGIN
-- do PASV
vResp_Code := Do_Command( conn, 'PASV', response );
IF vResp_Code = 227 THEN
<<Switch_Port>>
BEGIN
vNew_Port := Parse_Port_Number( response );
vNew_Conn := UTL_TCP.OPEN_CONNECTION( conn.remote_host,
vNew_Port,
tx_timeout => conn.tx_timeout );
Debug( 'Data connection: ' || vNew_Conn.remote_host || ':' || vNew_Conn.remote_port );
vResp_Code := Do_Command( conn, 'RETR ' || REPLACE( remote_path, CHR(12), CHR(0) ), response );
IF vResp_Code <> 150 THEN
RAISE FATAL_ERROR;
END IF;
<<Get_Download>>
BEGIN
LOOP
vResp := UTL_TCP.GET_LINE( vNew_Conn, FALSE );
UTL_FILE.Put( local_file, vResp );
END LOOP;
EXCEPTION
WHEN UTL_TCP.END_OF_INPUT THEN NULL;
END Get_Download;
vResp_Code := Close_Session( vNew_Conn );
vResp_Code := Get_Response( conn, response );
IF vResp_Code BETWEEN 400 AND 599 THEN
RAISE FATAL_ERROR;
END IF;
EXCEPTION
WHEN OTHERS THEN
Debug( SQLERRM );
RAISE FATAL_ERROR;
END Switch_Port;
ELSE
RAISE FATAL_ERROR;
END IF;
vResp_Code := Close_Session( vNew_Conn );
RETURN 0;
EXCEPTION
WHEN FATAL_ERROR THEN
Debug( 'Fatal error getting ' || remote_path || ':' );
Debug( ' Code: ' || vResp_Code );
Debug( ' Response: ' || response );
vResp_Code := Close_Session( vNew_Conn );
RETURN vResp_Code;
WHEN OTHERS THEN
Debug( vResp_Code || ': ' || SQLERRM );
RETURN vResp_Code;
END Get;
FUNCTION Get( conn IN OUT NOCOPY UTL_TCP.Connection,
local_path IN VARCHAR2,
local_filename IN VARCHAR2,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER IS
vFile UTL_FILE.File_Type;
vResult NUMBER := -1;
BEGIN
vFile := UTL_FILE.FOPEN( local_path, local_filename, 'w' );
vResult := Get( conn, vFile, remote_path, response );
UTL_FILE.FCLOSE( vFile );
RETURN vResult;
EXCEPTION WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN( vFile ) THEN
UTL_FILE.FCLOSE( vFile );
END IF;
RAISE;
END Get;
FUNCTION Put( conn IN OUT NOCOPY UTL_TCP.Connection,
buf IN VARCHAR2,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER IS
vResp VARCHAR2(32767);
vResp_Code NUMBER;
vNew_Conn UTL_TCP.Connection;
vNew_Port NUMBER;
BEGIN
-- do PASV
vResp_Code := Do_Command( conn, 'PASV', response );
IF vResp_Code = 227 THEN
<<Switch_Port>>
BEGIN
vNew_Port := Parse_Port_Number( response );
vNew_Conn := UTL_TCP.OPEN_CONNECTION( conn.remote_host,
vNew_Port,
tx_timeout => conn.tx_timeout );
Debug( 'Data connection: ' || vNew_Conn.remote_host || ':' || vNew_Conn.remote_port );
vResp_Code := Do_Command( conn, 'STOR ' || REPLACE( remote_path, CHR(12), CHR(0) ), response );
IF vResp_Code <> 150 THEN
RAISE FATAL_ERROR;
END IF;
vResp_Code := UTL_TCP.WRITE_TEXT( vNew_Conn, buf );
UTL_TCP.FLUSH( vNew_Conn );
vResp_Code := Close_Session( vNew_Conn );
vResp_Code := Get_Response( conn, response );
IF vResp_Code BETWEEN 400 AND 599 THEN
RAISE FATAL_ERROR;
END IF;
EXCEPTION
WHEN OTHERS THEN
Debug( SQLERRM );
RAISE FATAL_ERROR;
END Switch_Port;
ELSE
RAISE FATAL_ERROR;
END IF;
vResp_Code := Close_Session( vNew_Conn );
response := vResp;
RETURN 0;
EXCEPTION
WHEN FATAL_ERROR THEN
Debug( 'Fatal error putting ' || remote_path || ':' );
Debug( ' Code: ' || vResp_Code );
Debug( ' Response: ' || response );
vResp_Code := Close_Session( vNew_Conn );
RETURN vResp_Code;
WHEN OTHERS THEN
Debug( vResp_Code || ': ' || SQLERRM );
RETURN vResp_Code;
END Put;
FUNCTION Put( conn IN OUT NOCOPY UTL_TCP.Connection,
local_file IN OUT UTL_FILE.File_Type,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER IS
vResp VARCHAR2(32767);
vResp_Code NUMBER;
vNew_Conn UTL_TCP.Connection;
vNew_Port NUMBER;
vNew_Port_String VARCHAR2(32767);
BEGIN
-- do PASV
vResp_Code := Do_Command( conn, 'PASV', response );
IF vResp_Code = 227 THEN
<<Switch_Port>>
BEGIN
vNew_Port := Parse_Port_Number( response );
vNew_Conn := UTL_TCP.OPEN_CONNECTION( conn.remote_host,
vNew_Port,
tx_timeout => conn.tx_timeout );
Debug( 'Data connection: ' || vNew_Conn.remote_host || ':' || vNew_Conn.remote_port );
vResp_Code := Do_Command( conn, 'STOR ' || REPLACE( remote_path, CHR(12), CHR(0) ), response );
IF vResp_Code <> 150 THEN
RAISE FATAL_ERROR;
END IF;
<<Get_Download>>
BEGIN
LOOP
UTL_FILE.Get_Line( local_file, vResp );
vResp_Code := UTL_TCP.WRITE_LINE( vNew_Conn, vResp );
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END Get_Download;
vResp_Code := Close_Session( vNew_Conn );
vResp_Code := Get_Response( conn, response );
IF vResp_Code BETWEEN 400 AND 599 THEN
RAISE FATAL_ERROR;
END IF;
EXCEPTION
WHEN OTHERS THEN
Debug( SQLERRM );
RAISE FATAL_ERROR;
END Switch_Port;
ELSE
RAISE FATAL_ERROR;
END IF;
vResp_Code := Close_Session( vNew_Conn );
RETURN 0;
EXCEPTION
WHEN FATAL_ERROR THEN
Debug( 'Fatal error putting ' || remote_path || ':' );
Debug( ' Code: ' || vResp_Code );
Debug( ' Response: ' || response );
vResp_Code := Close_Session( vNew_Conn );
RETURN vResp_Code;
WHEN OTHERS THEN
Debug( vResp_Code || ': ' || SQLERRM );
RETURN vResp_Code;
END Put;
FUNCTION Put( conn IN OUT NOCOPY UTL_TCP.Connection,
local_path IN VARCHAR2,
local_filename IN VARCHAR2,
remote_path IN VARCHAR2,
response OUT VARCHAR2 ) RETURN NUMBER IS
vFile UTL_FILE.File_Type;
vResult NUMBER;
BEGIN
vFile := UTL_FILE.FOPEN( local_path, local_filename, 'r' );
vResult := Put( conn, vFile, remote_path, response );
UTL_FILE.FCLOSE( vFile );
RETURN vResult;
EXCEPTION WHEN OTHERS THEN
IF UTL_FILE.IS_OPEN( vFile ) THEN
UTL_FILE.FCLOSE( vFile );
END IF;
RAISE;
END Put;
FUNCTION Remote_Command( conn IN OUT NOCOPY UTL_TCP.Connection,
command IN VARCHAR2 ) RETURN NUMBER IS
vResp_Code NUMBER;
vResponse VARCHAR2(32767);
BEGIN
vResp_Code := Do_Command( conn, 'SITE ' || command, vResponse );
IF vResp_Code BETWEEN 500 AND 599 THEN
RETURN vResp_Code;
END IF;
RETURN 0;
END Remote_Command;
FUNCTION Chdir( conn IN OUT NOCOPY UTL_TCP.Connection,
remote_path IN VARCHAR2 ) RETURN NUMBER IS
vResp_Code NUMBER;
vResponse VARCHAR2(32767);
BEGIN
vResp_Code := Do_Command( conn, 'CWD ' || REPLACE( remote_path, CHR(12), CHR(0) ), vResponse );
IF vResp_Code BETWEEN 500 AND 599 THEN
RETURN vResp_Code;
END IF;
RETURN 0;
END Chdir;
FUNCTION Pwd( conn IN OUT NOCOPY UTL_TCP.Connection ) RETURN NUMBER IS
vResp_Code NUMBER;
vResponse VARCHAR2(32767);
BEGIN
vResp_Code := Do_Command( conn, 'PWD', vResponse );
IF vResp_Code BETWEEN 500 AND 599 THEN
RETURN vResp_Code;
END IF;
RETURN 0;
END Pwd;
FUNCTION Close_Session( conn IN OUT NOCOPY UTL_TCP.Connection ) RETURN NUMBER IS
BEGIN
IF conn.remote_host IS NULL THEN
RETURN 0;
END IF;
Debug( 'Closing connection on ' || conn.remote_host || ':' || conn.remote_port );
UTL_TCP.Close_Connection( conn );
RETURN 0;
EXCEPTION
WHEN UTL_TCP.NETWORK_ERROR THEN RETURN 0;
END Close_Session;
FUNCTION Close_All_Sessions RETURN NUMBER IS
BEGIN
UTL_TCP.Close_All_Connections;
RETURN 0;
END Close_All_Sessions;
END FTP;

Here's another PL/SQL package that will FTP ASCII text files. It assumes that you have proper permissions on the remote host and simply want to transfer one or more text files, not perform any other miscellaneous commands.
Also, from what I have read, in 9i UTL_FILE supports reading and writing of binary data so an FTP client could be written to transfer either ASCII or BINARY files.
Regards,
Russ
CREATE OR REPLACE PACKAGE BRNC_FTP_PKG
AS
* PL/SQL FTP Client
* Created by: Russ Johnson, Braun Consulting
* www.braunconsult.com
* OVERVIEW
* This package uses the standard packages UTL_FILE and UTL_TCP to perform
* client-side FTP functionality (PUT and GET) for text files as defined in
* the World Wide Web Consortium's RFC 959 document - http://www.w3.org/Protocols/rfc959/
* The procedures and functions in this package allow single or multiple file transfer using
* standard TCP/IP connections.
* LIMITATIONS
* Currently the API is limited to transfer of ASCII text files only. This is
* primarily because UTL_FILE only supports text I/O, but also because the original
* design was for creating text files from data in the Oracle database, then transferring the file to a remote host.
* Furthermore, the API does not support SSH/Secure FTP or connection through a proxy server.
* Keep in mind that FTP passes the username/password combo in plain text over TCP/IP.
* DB versions - 8i (8.1.x) and above. 8.0.x may work if it has the SYS.UTL_TCP package.
* Note: Since UTL_FILE is used for the client-side I/O, this package is also limited to
* transfer of files that exist in directories available to UTL_FILE for read/write.
* These directories are defined by the UTL_FILE_DIR parameter in the init.ora file.
* USAGE
* Three functions are available for FTP - PUT, GET, and FTP_MULTIPLE. FTP_MULTIPLE takes
* a table of records that define the files to be transferred (filename, directory, etc.).
* That table can have 1 record or multiple records. The PUT and GET functions are included
* for convenience to FTP one file at a time. PUT and GET return true if the file is transferred
* successfully and false if it fails. FTP_MULTIPLE returns true if no batch-level errors occur
* (such as an invalid host, refused connection, or invalid login information). It also takes the
* table of file records IN and passes it back OUT. Each record contains individual error information.
* EXAMPLE
* Transfer multiple files - 1 GET and 2 PUT from a Windows machine to a host (assuming UNIX here).
* Display any errors that occur.
* DECLARE
*      v_username      VARCHAR2(40) := 'rjohnson';
* v_password      VARCHAR2(40) := 'password';
* v_hostname      VARCHAR2(255) := 'ftp.oracle.com';
* v_error_message      VARCHAR2(1000);
* b_put           BOOLEAN;
* t_files      BRNC_FTP_PKG.t_ftp_rec; -- Declare our table of file records
* BEGIN
* t_files(1).localpath           := 'd:\oracle\utl_file\outbound';
* t_files(1).filename           := 'myfile1.txt';
* t_files(1).remotepath           := '/home/oracle/text_files';
* t_files(1).transfer_mode      := 'PUT';
* t_files(2).localpath           := 'd:\oracle\utl_file\inbound';
* t_files(2).filename           := 'incoming_file.xml';
* t_files(2).remotepath           := '/home/oracle/xml_files';
* t_files(2).transfer_mode      := 'GET';
* t_files(3).localpath           := 'd:\oracle\utl_file\outbound';
* t_files(3).filename           := 'myfile2.txt';
* t_files(3).remotepath      := '/home';
* t_files(3).transfer_mode      := 'PUT';
* b_put := BRNC_FTP_PKG.FTP_MULTIPLE(v_error_message,
* t_files,
* v_username,
* v_password,
* v_hostname);
* IF b_put = TRUE
* THEN
*     FOR i IN t_files.FIRST..t_files.LAST
*     LOOP
* IF t_files.EXISTS(i)
* THEN
*      DBMS_OUTPUT.PUT_LINE(t_files(i).status||' | '||
* t_files(i).error_message||' | '||
* to_char(t_files(i).bytes_transmitted)||' | '||
* to_char(t_files(i).trans_start,'YYYY-MM-DD HH:MI:SS')||' | '||
* to_char(t_files(i).trans_end,'YYYY-MM-DD HH:MI:SS'));
* END IF;
*      END LOOP;
* ELSE
*      DBMS_OUTPUT.PUT_LINE(v_error_message);
* END IF;
* EXCEPTION
* WHEN OTHERS
* THEN
* DBMS_OUTPUT.PUT_LINE(SQLERRM);
* END;
* CREDITS
* The W3C's RFC 959 that describes the FTP process.
* http://www.w3c.org
* Much of the PL/SQL code in this package was based on Java code written by
* Bruce Blackshaw of Enterprise Distributed Technologies Ltd. None of that code
* was copied, but the objects and methods greatly helped my understanding of the
* FTP Client process.
* http://www.enterprisedt.com
*     VERSION HISTORY
* 1.0 11/19/2002 Unit-tested single and multiple transfers between disparate hosts.                                    
* Exceptions
ctrl_exception     EXCEPTION;
data_exception     EXCEPTION;
* Constants - FTP valid response codes
CONNECT_CODE     CONSTANT PLS_INTEGER := 220;
USER_CODE          CONSTANT PLS_INTEGER := 331;
LOGIN_CODE          CONSTANT PLS_INTEGER := 230;
PWD_CODE          CONSTANT PLS_INTEGER := 257;
PASV_CODE          CONSTANT PLS_INTEGER := 227;
CWD_CODE          CONSTANT PLS_INTEGER := 250;
TSFR_START_CODE1     CONSTANT PLS_INTEGER := 125;
TSFR_START_CODE2     CONSTANT PLS_INTEGER := 150;
TSFR_END_CODE     CONSTANT PLS_INTEGER := 226;
QUIT_CODE          CONSTANT PLS_INTEGER := 221;
SYST_CODE          CONSTANT PLS_INTEGER := 215;
TYPE_CODE          CONSTANT PLS_INTEGER := 200;
* FTP File record datatype
* Elements:
* localpath - full directory name in which the local file resides or will reside
* Windows: 'd:\oracle\utl_file'
* UNIX: '/home/oracle/utl_file'
* filename - filename and extension for the file to be received or sent
* changing the filename for the PUT or GET is currently not allowed
* Examples: 'myfile.dat' 'myfile20021119.xml'
* remotepath - full directory name in which the local file will be sent or the
* remote file exists. Should be in UNIX format regardless of FTP server - '/one/two/three'
* filetype - reserved for future use, ignored in code
* transfer_mode - 'PUT' or 'GET'
* status - status of the transfer. 'ERROR' or 'SUCCESS'
* error_message - meaningful (hopefully) error message explaining the reason for failure
* bytes_transmitted - how many bytes were sent/received
* trans_start - date/time the transmission started
* trans_end - date/time the transmission ended
TYPE r_ftp_rec IS RECORD(localpath           VARCHAR2(255),
               filename           VARCHAR2(255),
               remotepath      VARCHAR2(255),
               filetype           VARCHAR2(20),
               transfer_mode      VARCHAR2(5),
               status           VARCHAR2(40),
               error_message      VARCHAR2(255),
               bytes_transmitted      NUMBER,
               trans_start     DATE,
               trans_end          DATE);
* FTP File Table - used to store many files for transfer
TYPE t_ftp_rec IS TABLE of r_ftp_rec INDEX BY BINARY_INTEGER;
* Internal convenience procedure for creating passive host IP address
* and port number.
PROCEDURE CREATE_PASV(p_pasv_cmd IN VARCHAR2,
               p_pasv_host OUT VARCHAR2,
               p_pasv_port OUT NUMBER);
* Function used to validate FTP server responses based on the
* code passed in p_code. Reads single or multi-line responses.
FUNCTION VALIDATE_REPLY(p_ctrl_con      IN OUT UTL_TCP.CONNECTION,
               p_code      IN PLS_INTEGER,
               p_reply      OUT VARCHAR2)
     RETURN BOOLEAN;
* Function used to validate FTP server responses based on the
* code passed in p_code. Reads single or multi-line responses.
* Overloaded because some responses can have 2 valid codes.
FUNCTION VALIDATE_REPLY(p_ctrl_con      IN OUT UTL_TCP.CONNECTION,
               p_code1      IN PLS_INTEGER,
               p_code2     IN PLS_INTEGER,
               p_reply      OUT VARCHAR2)
     RETURN BOOLEAN;
* Procedure that handles the actual data transfer. Meant
* for internal package use. Returns information about the
* actual transfer.
PROCEDURE TRANSFER_ASCII(u_ctrl_con IN OUT UTL_TCP.CONNECTION,
               p_localpath IN VARCHAR2,
               p_filename IN VARCHAR2,
               p_pasv_host IN VARCHAR2,
               p_pasv_port IN PLS_INTEGER,
               p_transfer_mode IN VARCHAR2,
               v_status OUT VARCHAR2,
               v_error_message OUT VARCHAR2,
               n_bytes_transmitted OUT NUMBER,
               d_trans_start OUT DATE,
d_trans_end OUT DATE);
* Function to handle FTP of many files.
* Returns TRUE if no batch-level errors occur.
* Returns FALSE if a batch-level error occurs.
* Parameters:
* p_error_msg - error message for batch level errors
* p_files - BRNC_FTP_PKG.t_ftp_rec table type. Accepts
* list of files to be transferred (may be any combination of PUT or GET)
* returns the table updated with transfer status, error message,
* bytes_transmitted, transmission start date/time and transmission end
* date/time
* p_username - username for FTP server
* p_password - password for FTP server
* p_hostname - hostname or IP address of server Ex: 'ftp.oracle.com' or '127.0.0.1'
* p_port - port number to connect on. FTP is usually on 21, but this may be overridden
* if the server is configured differently.
FUNCTION FTP_MULTIPLE(p_error_msg OUT VARCHAR2,
               p_files IN OUT t_ftp_rec,
               p_username IN VARCHAR2,
               p_password IN VARCHAR2,
               p_hostname IN VARCHAR2,
               p_port IN PLS_INTEGER DEFAULT 21)
     RETURN BOOLEAN;
* Convenience function for single-file PUT
* Parameters:
* p_localpath - full directory name in which the local file resides or will reside
* Windows: 'd:\oracle\utl_file'
* UNIX: '/home/oracle/utl_file'
* p_filename - filename and extension for the file to be received or sent
* changing the filename for the PUT or GET is currently not allowed
* Examples: 'myfile.dat' 'myfile20021119.xml'
* p_remotepath - full directory name in which the local file will be sent or the
* remote file exists. Should be in UNIX format regardless of FTP server - '/one/two/three'
* p_username - username for FTP server
* p_password - password for FTP server
* p_hostname - FTP server IP address or host name Ex: 'ftp.oracle.com' or '127.0.0.1'
* v_status - status of the transfer. 'ERROR' or 'SUCCESS'
* v_error_message - meaningful (hopefully) error message explaining the reason for failure
* n_bytes_transmitted - how many bytes were sent/received
* d_trans_start - date/time the transmission started
* d_trans_end - date/time the transmission ended
* p_port - port number to connect to, default is 21
* p_filetype - always set to 'ASCII', reserved for future use, ignored in code
FUNCTION PUT(p_localpath IN VARCHAR2,
          p_filename IN VARCHAR2,
          p_remotepath IN VARCHAR2,
          p_username IN VARCHAR2,
          p_password IN VARCHAR2,
          p_hostname IN VARCHAR2,
          v_status OUT VARCHAR2,
          v_error_message OUT VARCHAR2,
          n_bytes_transmitted OUT NUMBER,
          d_trans_start OUT DATE,
d_trans_end OUT DATE,
          p_port     IN PLS_INTEGER DEFAULT 21,
          p_filetype IN VARCHAR2 := 'ASCII')
     RETURN BOOLEAN;
* Convenience function for single-file GET
* Parameters:
* p_localpath - full directory name in which the local file resides or will reside
* Windows: 'd:\oracle\utl_file'
* UNIX: '/home/oracle/utl_file'
* p_filename - filename and extension for the file to be received or sent
* changing the filename for the PUT or GET is currently not allowed
* Examples: 'myfile.dat' 'myfile20021119.xml'
* p_remotepath - full directory name in which the local file will be sent or the
* remote file exists. Should be in UNIX format regardless of FTP server - '/one/two/three'
* p_username - username for FTP server
* p_password - password for FTP server
* p_hostname - FTP server IP address or host name Ex: 'ftp.oracle.com' or '127.0.0.1'
* v_status - status of the transfer. 'ERROR' or 'SUCCESS'
* v_error_message - meaningful (hopefully) error message explaining the reason for failure
* n_bytes_transmitted - how many bytes were sent/received
* d_trans_start - date/time the transmission started
* d_trans_end - date/time the transmission ended
* p_port - port number to connect to, default is 21
* p_filetype - always set to 'ASCII', reserved for future use, ignored in code
FUNCTION GET(p_localpath IN VARCHAR2,
          p_filename IN VARCHAR2,
          p_remotepath IN VARCHAR2,
          p_username IN VARCHAR2,
          p_password IN VARCHAR2,
          p_hostname IN VARCHAR2,
          v_status OUT VARCHAR2,
          v_error_message OUT VARCHAR2,
          n_bytes_transmitted OUT NUMBER,
          d_trans_start OUT DATE,
d_trans_end OUT DATE,
          p_port     IN PLS_INTEGER DEFAULT 21,
          p_filetype IN VARCHAR2 := 'ASCII')
     RETURN BOOLEAN;
END BRNC_FTP_PKG;
CREATE OR REPLACE PACKAGE BODY BRNC_FTP_PKG
AS
** Create the passive host IP and port number to connect to
PROCEDURE CREATE_PASV(p_pasv_cmd IN VARCHAR2,
               p_pasv_host OUT VARCHAR2,
               p_pasv_port OUT NUMBER)
IS
     v_pasv_cmd     VARCHAR2(30) := p_pasv_cmd; --Host and port to connect to for data transfer
n_port_dec     NUMBER;
     n_port_add     NUMBER;
BEGIN
     p_pasv_host := REPLACE(SUBSTR(v_pasv_cmd,1,INSTR(v_pasv_cmd,',',1,4)-1),',','.');
     n_port_dec := TO_NUMBER(SUBSTR(v_pasv_cmd,INSTR(v_pasv_cmd,',',1,4)+1,(INSTR(v_pasv_cmd,',',1,5)-(INSTR(v_pasv_cmd,',',1,4)+1))));
     n_port_add := TO_NUMBER(SUBSTR(v_pasv_cmd,INSTR(v_pasv_cmd,',',1,5)+1,LENGTH(v_pasv_cmd)-INSTR(v_pasv_cmd,',',1,5)));
     p_pasv_port := (n_port_dec*256) + n_port_add;
EXCEPTION
WHEN OTHERS
THEN
     --DBMS_OUTPUT.PUT_LINE(SQLERRM);
     RAISE;
END CREATE_PASV;
** Read a single or multi-line reply from the FTP server and validate
** it against the code passed in p_code.
** Return TRUE if reply code matches p_code, FALSE if it doesn't or error
** occurs
** Send full server response back to calling procedure
FUNCTION VALIDATE_REPLY(p_ctrl_con      IN OUT UTL_TCP.CONNECTION,
               p_code      IN PLS_INTEGER,
               p_reply      OUT VARCHAR2)
RETURN BOOLEAN
IS
     n_code           VARCHAR2(3) := p_code;
     n_byte_count      PLS_INTEGER;
     v_msg          VARCHAR2(255);
     n_line_count     PLS_INTEGER := 0;
BEGIN
     LOOP
     v_msg := UTL_TCP.GET_LINE(p_ctrl_con);
     n_line_count := n_line_count + 1;
     IF n_line_count = 1
     THEN
          p_reply := v_msg;
     ELSE
          p_reply := p_reply || SUBSTR(v_msg,4);
     END IF;
     EXIT WHEN INSTR(v_msg,'-',1,1) <> 4;
     END LOOP;
IF to_number(SUBSTR(p_reply,1,3)) = n_code
     THEN
     RETURN TRUE;
     ELSE
     RETURN FALSE;
     END IF;
EXCEPTION
WHEN OTHERS
THEN
p_reply := SQLERRM;
RETURN FALSE;
END VALIDATE_REPLY;
** Reads a single or multi-line reply from the FTP server
** Return TRUE if reply code matches p_code1 or p_code2,
** FALSE if it doesn't or error occurs
** Send full server response back to calling procedure
FUNCTION VALIDATE_REPLY(p_ctrl_con      IN OUT UTL_TCP.CONNECTION,
               p_code1      IN PLS_INTEGER,
               p_code2     IN PLS_INTEGER,
               p_reply      OUT VARCHAR2)
RETURN BOOLEAN
IS
     v_code1      VARCHAR2(3) := to_char(p_code1);
     v_code2      VARCHAR2(3) := to_char(p_code2);
     v_msg          VARCHAR2(255);
     n_line_count     PLS_INTEGER := 0;
BEGIN
     LOOP
     v_msg := UTL_TCP.GET_LINE(p_ctrl_con);
     n_line_count := n_line_count + 1;
     IF n_line_count = 1
     THEN
          p_reply := v_msg;
     ELSE
          p_reply := p_reply || SUBSTR(v_msg,4);
     END IF;
     EXIT WHEN INSTR(v_msg,'-',1,1) <> 4;
     END LOOP;
IF to_number(SUBSTR(p_reply,1,3)) IN(v_code1,v_code2)
     THEN
     RETURN TRUE;
     ELSE
     RETURN FALSE;
     END IF;
EXCEPTION
WHEN OTHERS
THEN
p_reply := SQLERRM;
RETURN FALSE;
END VALIDATE_REPLY;
** Handles actual data transfer. Responds with status, error message, and
** transfer statistics.
** Potential errors could be with connection or file i/o
PROCEDURE TRANSFER_ASCII(u_ctrl_con IN OUT UTL_TCP.CONNECTION,
               p_localpath IN VARCHAR2,
               p_filename IN VARCHAR2,
               p_pasv_host IN VARCHAR2,
               p_pasv_port IN PLS_INTEGER,
               p_transfer_mode IN VARCHAR2,
               v_status OUT VARCHAR2,
               v_error_message OUT VARCHAR2,
               n_bytes_transmitted OUT NUMBER,
               d_trans_start OUT DATE,
d_trans_end OUT DATE)
IS
     u_data_con          UTL_TCP.CONNECTION;
     u_filehandle          UTL_FILE.FILE_TYPE;
v_tsfr_mode          VARCHAR2(3) := p_transfer_mode;
     v_mode               VARCHAR2(1);
v_tsfr_cmd          VARCHAR2(10);
     v_buffer          VARCHAR2(32767);
     v_localpath          VARCHAR2(255)      := p_localpath;
     v_filename          VARCHAR2(255)      := p_filename;
     v_host               VARCHAR2(20)      := p_pasv_host;
     n_port               PLS_INTEGER      := p_pasv_port;
     n_bytes               NUMBER;
     v_msg               VARCHAR2(255);
     v_reply               VARCHAR2(1000);
     v_err_status          VARCHAR2(20) := 'ERROR';
BEGIN
     /** Initialize some of our OUT variables **/
     v_status          := 'SUCCESS';
     v_error_message          := ' ';
     n_bytes_transmitted     := 0;
     IF UPPER(v_tsfr_mode) = 'PUT'
THEN
     v_mode      := 'r';
     v_tsfr_cmd      := 'STOR ';
     ELSIF UPPER(v_tsfr_mode) = 'GET'
     THEN
     v_mode     := 'w';
     v_tsfr_cmd := 'RETR ';
END IF;
     /** Open data connection on Passive host and port **/
     u_data_con := UTL_TCP.OPEN_CONNECTION(v_host,n_port);
     /** Open the local file to read and transfer data **/
     u_filehandle := UTL_FILE.FOPEN(v_localpath,v_filename,v_mode);
     /** Send the STOR command to tell the server we're going to upload a file **/
     n_bytes := UTL_TCP.WRITE_LINE(u_ctrl_con,v_tsfr_cmd||v_filename);
     IF VALIDATE_REPLY(u_ctrl_con,TSFR_START_CODE1,TSFR_START_CODE2,v_reply) = FALSE
     THEN
     RAISE ctrl_exception;
     END IF;
     d_trans_start := SYSDATE;
     IF UPPER(v_tsfr_mode) = 'PUT'
     THEN
     LOOP
          BEGIN
          UTL_FILE.GET_LINE(u_filehandle,v_buffer);
          EXCEPTION
          WHEN NO_DATA_FOUND
          THEN
          EXIT;
          END;
          n_bytes := UTL_TCP.WRITE_LINE(u_data_con,v_buffer);
          n_bytes_transmitted := n_bytes_transmitted + n_bytes;
     END LOOP;
     ELSIF UPPER(v_tsfr_mode) = 'GET'
     THEN
     LOOP
          BEGIN
          v_buffer := UTL_TCP.GET_LINE(u_data_con,TRUE);
          /** Sometimes the TCP/IP buffer sends null data **/
/** we only want to receive the actual data **/
          IF v_buffer IS NOT NULL
          THEN
          UTL_FILE.PUT_LINE(u_filehandle,v_buffer);
          n_bytes := LENGTH(v_buffer);
          n_bytes_transmitted := n_bytes_transmitted + n_bytes;
          END IF;
          EXCEPTION
          WHEN UTL_TCP.END_OF_INPUT
          THEN
          EXIT;
          END;
     END LOOP;
     END IF;
     /** Flush the buffer on the data connection **/
     --UTL_TCP.FLUSH(u_data_con);
     d_trans_end := SYSDATE;
     /** Close the file **/
     UTL_FILE.FCLOSE(u_filehandle);
     /** Close the Data Connection **/
     UTL_TCP.CLOSE_CONNECTION(u_data_con);
     /** Verify the transfer succeeded **/
     IF VALIDATE_REPLY(u_ctrl_con,TSFR_END_CODE,v_reply) = FALSE
     THEN
     RAISE ctrl_exception;
     END IF;
EXCEPTION
WHEN ctrl_exception
THEN
     v_status := v_err_status;
     v_error_message := v_reply;
     IF UTL_FILE.IS_OPEN(u_filehandle)
     THEN
     UTL_FILE.FCLOSE(u_filehandle);
     END IF;
     UTL_TCP.CLOSE_CONNECTION(u_data_con);
WHEN UTL_FILE.invalid_path
THEN
     v_status      := v_err_status;
     v_error_message := 'Directory '||v_localpath||' is not available to UTL_FILE. Check the init.ora file for valid UTL_FILE directories.';
     UTL_TCP.CLOSE_CONNECTION(u_data_con);
WHEN UTL_FILE.invalid_operation
THEN
     v_status := v_err_status;
     IF UPPER(v_tsfr_mode) = 'PUT'
     THEN
     v_error_message := 'The file '||V_filename||' in the directory '||v_localpath||' could not be opened for reading.';
     ELSIF UPPER(v_tsfr_mode) = 'GET'
     THEN
     v_error_message := 'The file '||V_filename||' in the directory '||v_localpath||' could not be opened for writing.';
     END IF;     
     IF UTL_FILE.IS_OPEN(u_filehandle)
     THEN
     UTL_FILE.FCLOSE(u_filehandle);
     END IF;
     UTL_TCP.CLOSE_CONNECTION(u_data_con);
WHEN UTL_FILE.read_error
THEN
     v_status := v_err_status;
     v_error_message := 'The system encountered an error while trying to read '||v_filename||' in the directory '||v_localpath;
     IF UTL_FILE.IS_OPEN(u_filehandle)
     THEN
     UTL_FILE.FCLOSE(u_filehandle);
     END IF;
     UTL_TCP.CLOSE_CONNECTION(u_data_con);
WHEN UTL_FILE.write_error
THEN
     v_status := v_err_status;
     v_error_message := 'The system encountered an error while trying to write to '||v_filename||' in the directory '||v_localpath;
     IF UTL_FILE.IS_OPEN(u_filehandle)
     THEN
     UTL_FILE.FCLOSE(u_filehandle);
     END IF;
     UTL_TCP.CLOSE_CONNECTION(u_data_con);
WHEN UTL_FILE.internal_error
THEN
     v_status := v_err_status;
     v_error_message := 'The UTL_FILE package encountered an unexpected internal system error.';
     IF UTL_FILE.IS_OPEN(u_filehandle)
     THEN
     UTL_FILE.FCLOSE(u_filehandle);
     END IF;
     UTL_TCP.CLOSE_CONNECTION(u_data_con);
WHEN OTHERS
THEN
     v_status := v_err_status;
     v_error_message := SQLERRM;
     IF UTL_FILE.IS_OPEN(u_filehandle)
     THEN
     UTL_FILE.FCLOSE(u_filehandle);
     END IF;
     UTL_TCP.CLOSE_CONNECTION(u_data_con);
END TRANSFER_ASCII;
** Handles connection to host and FTP of multiple files
** Files can be any combination of PUT and GET
FUNCTION FTP_MULTIPLE(p_error_msg OUT VARCHAR2,
               p_files IN OUT t_ftp_rec,
               p_username IN VARCHAR2,
               p_password IN VARCHAR2,
               p_hostname IN VARCHAR2,
               p_port IN PLS_INTEGER DEFAULT 21)
RETURN BOOLEAN
IS
     v_username           VARCHAR2(30)      := p_username;
     v_password           VARCHAR2(30)      := p_password;
     v_hostname           VARCHAR2(30)      := p_hostname;
     n_port               PLS_INTEGER      := p_port;
     u_ctrl_con          UTL_TCP.CONNECTION;
     n_byte_count          PLS_INTEGER;
     n_first_index          NUMBER;
     v_msg               VARCHAR2(250);
     v_reply               VARCHAR2(1000);
v_pasv_host          VARCHAR2(20);
n_pasv_port          NUMBER;
     invalid_transfer     EXCEPTION;
BEGIN
     p_error_msg := 'FTP Successful'; --Assume the overall transfer will succeed
     /** Attempt to connect to the host machine **/
     u_ctrl_con := UTL_TCP.OPEN_CONNECTION(v_hostname,n_port);
     IF VALIDATE_REPLY(u_ctrl_con,CONNECT_CODE,v_reply) = FALSE
     THEN
     RAISE ctrl_exception;
     END IF;
     /** Send username **/
     n_byte_count := UTL_TCP.WRITE_LINE(u_ctrl_con,'USER '||v_username);
     IF VALIDATE_REPLY(u_ctrl_con,USER_CODE,v_reply) = FALSE
     THEN
     RAISE ctrl_exception;
     END IF;
     /** Send password **/
     n_byte_count := UTL_TCP.WRITE_LINE(u_ctrl_con,'PASS '||v_password);
     IF VALIDATE_REPLY(u_ctrl_con,LOGIN_CODE,v_reply) = FALSE
     THEN
     RAISE ctrl_exception;
     END IF;
     /** We should be logged in, time to transfer all files **/
     FOR i IN p_files.FIRST..p_files.LAST
LOOP
     IF p_files.EXISTS(i)
     THEN
          BEGIN
          /** Change to the remotepath directory **/
          n_byte_count := UTL_TCP.WRITE_LINE(u_ctrl_con,'CWD '||p_files(i).remotepath);
          IF VALIDATE_REPLY(u_ctrl_con,CWD_CODE,v_reply) = FALSE
          THEN
               RAISE ctrl_exception;
          END IF;
          /** Switch to IMAGE mode **/
          n_byte_count := UTL_TCP.WRITE_LINE(u_ctrl_con,'TYPE I');
          IF VALIDATE_REPLY(u_ctrl_con,TYPE_CODE,v_reply) = FALSE
          THEN
               RAISE ctrl_exception;
          END IF;
          /** Get a Passive connection to use for data transfer **/
          n_byte_count := UTL_TCP.WRITE_LINE(u_ctrl_con,'PASV');
          IF VALIDATE_REPLY(u_ctrl_con,PASV_CODE,v_reply) = FALSE
          THEN
               RAISE ctrl_exception;
          END IF;
          CREATE_PASV(SUBSTR(v_reply,INSTR(v_reply,'(',1,1)+1,INSTR(v_reply,')',1,1)-INSTR(v_reply,'(',1,1)-1),v_pasv_host,n_pasv_port);
          /** Transfer Data **/
          IF UPPER(p_files(i).transfer_mode) = 'PUT'
          THEN
               TRANSFER_ASCII(u_ctrl_con,
                    p_files(i).localpath,
                    p_files(i).filename,
                    v_pasv_host,
                    n_pasv_port,
                    p_files(i).transfer_mode,
                    p_files(i).status,
                    p_files(i).error_message,
                    p_files(i).bytes_transmitted,
                    p_files(i).trans_start,
     p_files(i).trans_end);
          ELSIF UPPER(p_files(i).transfer_mode) = 'GET'
          THEN
               TRANSFER_ASCII(u_ctrl_con,
                    p_files(i).localpath,
                    p_files(i).filename,
                    v_pasv_host,
                    n_pasv_port,
                    p_files(i).transfer_mode,
                    p_files(i).status,
                    p_files(i).error_message,
                    p_files(i).bytes_transmitted,
                    p_files(i).trans_start,
     p_files(i).trans_end);
          ELSE
               RAISE invalid_transfer; -- Raise an exception here
          END IF;
          EXCEPTION
          WHEN ctrl_exception
          THEN
          p_files(i).status := 'ERROR';
          p_files(i).error_message := v_reply;
          WHEN invalid_transfer
          THEN
          p_files(i).status := 'ERROR';
          p_files(i).error_message := 'Invalid transfer method. Use PUT or GET.';
          END;
     END IF;
     END LOOP;
     /** Send QUIT command **/
     n_byte_count := UTL_TCP.WRITE_LINE(u_ctrl_con,'QUIT');
     /** Don't need to validate QUIT, just close the connection **/
     UTL_TCP.CLOSE_CONNECTION(u_ctrl_con);
     RETURN TRUE;
EXCEPTION
WHEN ctrl_exception
THEN
     p_error_msg := v_reply;
     UTL_TCP.CLOSE_ALL_CONNECTIONS;
     RETURN FALSE;
WHEN OTHERS
THEN
     p_error_msg := SQLERRM;
     UTL_TCP.CLOSE_ALL_CONNECTIONS;
     RETURN FALSE;
END FTP_MULTIPLE;
** Convenience function for single-file PUT
** Formats file information for FTP_MULTIPLE function and calls it.
FUNCTION PUT(p_localpath IN VARCHAR2,
          p_filename IN VARCHAR2,
          p_remotepath IN VARCHAR2,
          p_username IN VARCHAR2,
          p_password IN VARCHAR2,
          p_hostname IN VARCHAR2,
          v_status OUT VARCHAR2,
          v_error_message OUT VARCHAR2,
          n_bytes_transmitted OUT NUMBER,
          d_trans_start OUT DATE,
d_trans_end OUT DATE,
          p_port     IN PLS_INTEGER DEFAULT 21,
          p_filetype IN VARCHAR2 := 'ASCII')
RETURN BOOLEAN
IS
     t_files      t_ftp_rec;
     v_username     VARCHAR2(30)      := p_username;
     v_password     VARCHAR2(50)      := p_password;
     v_hostname     VARCHAR2(100)      := p_hostname;
     n_port          PLS_INTEGER      := p_port;
v_err_msg     VARCHAR2(255);
     b_ftp          BOOLEAN;
BEGIN
     t_files(1).localpath          := p_localpath;
     t_files(1).filename           := p_filename;
     t_files(1).remotepath          := p_remotepath;
     t_files(1).filetype          := p_filetype;
     t_files(1).transfer_mode     := 'PUT';
     b_ftp := FTP_MULTIPLE(v_err_msg,
               t_files,
               v_username,
               v_password,
               v_hostname,
               n_port);
     IF b_ftp = FALSE
     THEN
     v_status := 'ERROR';
     v_error_message := v_err_msg;
     RETURN FALSE;
     ELSIF b_ftp = TRUE
     THEN
     v_status                := t_files(1).status;
     v_error_message           := t_files(1).error_message;
     n_bytes_transmitted      := t_files(1).bytes_transmitted;
     d_trans_start           := t_files(1).trans_start;
     d_trans_end           := t_files(1).trans_end;
     RETURN TRUE;
     END IF;
EXCEPTION
WHEN OTHERS
THEN
     v_status      := 'ERROR';
     v_error_message := SQLERRM;
     RETURN FALSE;
     --DBMS_OUTPUT.PUT_LINE(SQLERRM);
END PUT;
** Convenience function for single-file GET
** Formats file information for FTP_MULTIPLE function and calls it.
FUNCTION GET(p_localpath IN VARCHAR2,
          p_filename IN VARCHAR2,
          p_remotepath IN VARCHAR2,
          p_username IN VARCHAR2,
          p_password IN VARCHAR2,
          p_hostname IN VARCHAR2,
          v_status OUT VARCHAR2,
          v_error_message OUT VARCHAR2,
          n_bytes_transmitted OUT NUMBER,
          d_trans_start OUT DATE,
d_trans_end OUT DATE,
          p_port     IN PLS_INTEGER DEFAULT 21,
          p_filetype IN VARCHAR2 := 'ASCII')
RETURN BOOLEAN
IS
     t_files      t_ftp_rec;
     v_username     VARCHAR2(30)      := p_username;
     v_password     VARCHAR2(50)      := p_password;
     v_hostname     VARCHAR2(100)      := p_hostname;
     n_port          PLS_INTEGER      := p_port;
v_err_msg     VARCHAR2(255);
     b_ftp          BOOLEAN;
BEGIN
     t_files(1).localpath          := p_localpath;
     t_files(1).filename           := p_filename;
     t_files(1).remotepath          := p_remotepath;
     t_files(1).filetype          := p_filetype;
     t_files(1).transfer_mode     := 'GET';
     b_ftp := FTP_MULTIPLE(v_err_msg,
               t_files,
               v_username,
               v_password,
               v_hostname,
               n_port);
     IF b_ftp = FALSE
     THEN
     v_status := 'ERROR';
     v_error_message := v_err_msg;
     RETURN FALSE;
     ELSIF b_ftp = TRUE
     THEN
     v_status           := t_files(1).status;
     v_error_message      := t_files(1).error_message;
     n_bytes_transmitted := t_files(1).bytes_transmitted;
     d_trans_start      := t_files(1).trans_start;
     d_trans_end      := t_files(1).trans_end;
     RETURN TRUE;
     END IF;
EXCEPTION
WHEN OTHERS
THEN
     v_status      := 'ERROR';
     v_error_message := SQLERRM;
     RETURN FALSE;
     --DBMS_OUTPUT.PUT_LINE(SQLERRM);
END GET;
END BRNC_FTP_PKG;
/

Similar Messages

  • How many problems do you need to have with a mac book pro to get it replaced i have had 6 problems and they say they have fixed everything and somthing new happends

    how many problems do you need to have with a mac book pro to get it replaced i have had 6 problems and they say they have fixed everything and somthing new happends
    I have had thehad the:
    ram replaced
    Battery
    Audio
    Trackpad
    os operating system
    fans
    And they still won't replace the laptop for me worst buy ever but i have had a imac for 2 months and nothing at all wrong .

    You could try calling Apple and ask for Customer Relations.
    From Readers Digest-February, 2005
    How to Complain
          You call customer service to complain about a product, and you hang up angrier than when you started. That’s customer rage, a feeling experienced by millions of people with a major complaint, says Scott Broetzmann, president an American firm that tells companies how to offer the best customer service. His secrets to getting good service:
    Have a goal
    If you want your product repaired, say so. Want an apology? Speak up.
    Keep it short
    Focus on one problem, and be succinct.
    Stick with it
    You have to invest the time it takes. Don’t get what you want? Ask for a supervisor.
    Skip ultimatums
    Don’t threaten not to do business with them again. Why should they help you if you won’t buy from them in the future?
    Plead your case
    Many companies have information such as how much money you’ve spent with them and how often you complain. If you’re a good customer, they may be more willing to help.
    Be nice
    You’re unlikely to get what you want if you’re rude.
    Good luck.

  • I've been trying to get a book sample and a dialogue box comes up saying: To receive book samples, you need a device with the latest versions of iOS and ibooks installed and Automatic Download enabled.  I have iBooks installed and automatic download enabl

    I've been trying to get a book sample and a dialogue box comes up saying: To receive book samples, you need a device with the latest versions of iOS and ibooks installed and Automatic Download enabled.  I have iBooks installed and automatic download enabled.  I don't know if it's talking about a new version of iOS on my iphone or my laptop. You people sure like to make things difficult.

    trevbeats,
    I had the same problem. It turned out the issue for me was that I had Automatic downloads turned off on my devices!
    see below how to turn it on.
    Tap Settings > iTunes & App Stores on your device.
    Tap Sign In if you're not already signed in to the iTunes Store.
    Enter your Apple ID and password.
    Tap On/Off switch to enable or disable Automatic Downloads for each content type.

  • HT3702 I have almost $300 worth of charges on a game that I just downloaded from iTunes.  I have never had a problem with this, I do have a 5 year old using my Ipad, but $300. I was told that you need to authorize with a passcode again before additional p

    I have so many charges that just came in this morning, I have tried multiple times to get in touch w/ Apple by chat, online and phone with absolutely NO LUCK.  I purchased a stupid game for my 5 year old, but somehow I have $300 in charges this morning..  Who can I get in touch with?  I thought that you needed additional authorization to charge anything else?  If I cannot get help, I will cancel all of our iTunes and everyone can buy a gift certificate with $10 on it for all future use.
    Does anyone have a phone number where I can talk to a live person? or a chat that actually works?

    You can try contacting iTunes Support and see if they will refund or credit you : http://www.apple.com/support/itunes/contact/ - click on Contact iTunes Store Support on the right-hand side of the page, then Purchases, Billing & Redemption. The contact methods that are available vary by country (and possibly by time of day), but you might get options on that page.
    You can turn off in-app purchases on your iPad via Settings > General > Restrictions > In-App Purchases 'off', and depending upon what version of iOS that you have on it you may have a Require Password option on the Restrictions screen that you can set to 'Immediately' (there is a default 15 minutes during which it doesn't need to be re-entered).

  • Do you need a phone with Broadband?

    Recently had a line fitted for broadband in our new build. Would I need to have a phone or can I have phone-less broadband?
    And is it cheaper?
    Any help would be much appreciated as I want to avoid calling the helpline.
    Many Thanks
    Carly

    no  you need a phone line to get broadband
    you may find the option with some small companies but I would expect the broadband cost to be higher
    If you like a post, or want to say thanks for a helpful answer, please click on the Ratings star on the left-hand side of the post.
    If someone answers your question correctly please let other members know by clicking on ’Mark as Accepted Solution’.

  • Do you need the remote with the dock?

    Hi,
    i'm thinking of buying the Apple Dock, i don't want or need the apple remote, i'm just getting the dock to charge/dock and to TV, when the iPod is pluged in the dock, can i use the the buttons on the the iPod to control the functions like i normally would, or when i put it in the dock does that take over and need the remote? any help much appreciated.
    - Mike

    Jeff,
    You are correct... I was over simplifying some what on the whole DPI vs pixels, etc. I still haven't decided whether I like the 480 x 480 MPEG4 or the 320 x 240 H.264.
    My main point was that the signal is not digital comming out of the iPod, whether using the A/V cables directly or using through the dock. Secondly, that even though the standard definition TV at 480 lines, and using a 480 x 480 pixel video from the iPod, it is still not nearly as crisp on a large screen as on the iPod. The small screen just makes it look finer. Still, there should be no distortion, which would indicate a problem with teh A/V cable he was using.
    As a side, I have my iPod connected to a HDTV. Whether I use 1080i or 720p, the TV must upscale the output from the iPod to fill the the remaining pixels on the TV screen, which ovwerall makes it look worse that on a standard definition TV... even then, there is no distrotion that Mike was having problems with.
    ..and yes, I am a proponent of using the S-Video cable versus composite A/V. As I said, S-Video should provide a better quality picture. However, my own personal experince is that it is only a marginally nocitable improvement, despite what all of the videophile techies procliam.

  • How careful do you need to be with SwingUtilities.invokeLater()

    Is it safe to call an SwingUtilities.invokeLater() from within a method that was invoked with SwingUtilites.invokeLater() ?
    I'll give a quick example below.
        public void setWindowLocation(final Point p) {
            //Throw this on to the ETD with a recursive method call.
            if(!SwingUtilities.isEventDispatchThread()){
                SwingUtilities.invokeLater(new Runnable(){
                    public void run() {
                        setWindowLocation(p);
                //don't execute recursive call twice.
                return;
            }// end - EDT section.
            assert EventQueue.isDispatchThread():"Not Event Dispatch Thread";
            frame.setLocation(p);
            someOtherMethodThatCallsInvokeLater();
    public void someOtherMethodThatCallsInvokeLater(){
          //be lazy don't bother to check if already on event dispatch thread.
           Runnable update = new Runnable(){
                public void run(){
                    remoteModeWindow.setTransparency(50);
            SwingUtilities.invokeLater(update);
    }What would happen would when the second method is called that didn't bother to see if it was already on the Event Dispatch thread, and just called invokeLater() anyway. Is that harmless, or can it lead to deadlock, or some other inefficiency?
    The reason I ask, is I've seen some code in one class check and some in a different class that previously was only called from a non-dispatch thread never bothered to check. It is now possible that the "don't bother to check" method could be called in either situation (i.e. from a dispatch thread, or non-dispatch thread).
    Comments appreciated. What is a general guideline for this situation? Too many of the Swing books I've seen only lightly cover a few pages on this topic.
    Edited by: asnyder on Jul 2, 2009 7:14 PM

    Calling invokeLater(...) in this manner is absolutely safe with regards to deadlocks. What happens is that your runnable is enqueued at the end of the event queue. There is a possibility that another runnable has been dispatched in the mean time, so there is no guarantee that your code will be executed immediately:
    1. EDT enters someOtherMethodThatCallsInvokeLater()
    2. Another event (from another thread) triggers a repaint for a component or some other UI operation, which is enqueued
    3. Your runnable is enqueued on the EDT
    So highly theoretically there may be a delay which could be avoided if you immediately executed the runnable:
    public void someOtherMethodThatCallsInvokeLater(){
           Runnable update = new Runnable(){
                public void run(){
                    remoteModeWindow.setTransparency(50);
            if (SwingUtilities.isEventDispatchThread())
                update.run();
            else
                SwingUtilities.invokeLater(update);
    }In my experience though this kind of 'optimization' has no practical implications whatsoever.

  • SFTP and FTPs with jsse

    Is it easy to implement the sFTP and FTPs with JSSE API? If it is, can anybody give me an sample for each of them?
    Can any kind of you show me some open source ftp client libraries which support secure ftp? Thank you very much!

    Is it easy to implement the sFTP and FTPs with JSSE API?On the contrary, it is impossible to implement SFTP with the JSSE API. What you need is an SSH API.
    You can implement FTPS with the JSSE API.

  • How to create a FTP with my mac

    Hi how do you creat a ftp with a mac, ive tried to find FTP ACCESS in my sharing but the option is not there any ideas
    Thanks

    Applications>>Utilities>>AirportUtility.app>>Manual Setup>>Advanced>>Port Mapping >> + >>Choose a Service>>FTP Access.

  • What do i need to install with a WLC ?

    Hello everybody !
    I have a question, I have to implement a wifi solution in my company, and the Cisco solution seems to be adapted.
    But there are so many documents so I'm lost in the informations.
    Can you please say me what I need to have a complete and reliable solution ?
    What is the difference between NCS, WCS, Prime infrastructure ?? Is it necessary or I can to only install a controller and put the adapted license ?
    Thank you guys.
    Raphaël
    P.S : Sorry if my english is not perfect !

    Yes you can start with that...
    The only reason I say that you need to speak with someone is because I have seen many environments that was just slapped together in hopes that it would work. Design it right from the start and it will cost less in the long run. There are many options of WLC's and access points that you need to take into consideration. Redundancy, how will you secure the wireless and also implementing a solution that will still work for you in 5 years. Trust me on this... You don't want us to just tell you what to buy and putting all your requirements into a thread would be difficult. Speak with someone and then if you have questions or maybe want us to validate the design or purchase, we can help you there.
    Sent from Cisco Technical Support iPhone App

  • Help with starting sql developer

    Hi everyone
    I have had oracle express and sql developer on my laptop before untill my hard drive went, now iv installed them again but when I start sql developer I make a new connection then go to create a new user, but when I click create new user, there is no list under the "Roles" tab as there should be, its just a blank grey screen. Has anyone had this problem before who might be able to help?
    I am kind of in a rush because I need it for a college assesment on monday so any help will be really appreciated:)
    Thanks
    Ryan

    Welcome to the forum!
    Whenever you post you need to provide the full sql developer that you are using and all of the details about what you are doing and the problem you are having.
    You haven't provided the version, what user you are connnecting as, what type of connection it is (normal, sysdba), the type of connection you are connecting as (thin, oci), the JDBC jar version if using one, the Oracle client or server versions.

  • I am disabled, so I need voice contact with someone in Support. An alien program has taken over Firefox and I can't locate the files to delete front he rogue.

    The program that has taken over Firefox is called "inbox." I have disabled its cookies, but now, of course, I can't use the Firefox no matter who had taken it over.
    This is serious. I can' find the files with any routine search of my computer files, so they must be hidden.

    Do a malware check with some malware scan programs. You need to scan with all programs because each program detects different malware. Make sure that you update each program to get the latest version of the database before doing a scan.
    * http://www.malwarebytes.org/mbam.php - Malwarebytes' Anti-Malware
    * http://www.superantispyware.com/ - SuperAntispyware
    * http://www.microsoft.com/windows/products/winfamily/defender/default.mspx - Windows Defender: Home Page
    * http://www.safer-networking.org/en/index.html - Spybot Search & Destroy
    * http://www.lavasoft.com/products/ad_aware_free.php - Ad-Aware Free
    See also "Spyware on Windows": http://kb.mozillazine.org/Popups_not_blocked and [[Searches are redirected to another site]]

  • Form created with Livecycle Designer with a SQL database - do you need LiveCycle Forms installed?

    Hello,
    I'm REALLY hoping someone here can help me, I have spent over four hours on the phone to Adobe in the last 3 days and I'm getting no where what-so-ever. I can't even find out where /how to complain about it! (but thats another story)
    Here's my situtation:
    I work for a company with approx 140 staff. On one computer, we have Adobe Livecycle Designer ES installed, and we have used that program to create a form which has a link to a SQL database.
    The link in this form doesn't work on the other computers which has the basic (free) Adobe Reader. From doing research within these forums
     , I have found that the form will not work on other computers unless they have Adobe Livecycle forms installed on their machines. 
    What I need to know (and what they cannot seem to tell me when I call), is two things:
    Is it correct that in order to use a form created in Livecycle Designer which has a link to a SQL database, that the machine must have LiveCycle forms installed?
    How much does Adobe LiveCycle Forms costs?
    PLEASE, if you can answer this question, I would REALLY appriciate it....
    Thank you!

    I presume you are asking if you need Livecycle Forms ES? Forms ES is a component of the livecycle software suite intended as a document service which will be installed on a server within the organisation. A couple of things this document service can do is to render XDP into multiple formats (PDF, html, etc.), execute script server side (for example the database connection) on behalf of the client (reader, etc.), integrate with backend components, etc. So no you do not install this on each client.
    For database connections to work, you either have a server with Forms ES installed which can connect on each clients behalf (ie. Client->Forms ES Server->Database), or you have a reader-extended PDF to allow connections to be use in the free basic Reader (i.e. direct calls to the database or using web service calls to your own database components). However, reader-extended pdf would probably require Reader Extensions ES component installed on a server (you once off extend your developed pdf through this and then hand it out to each of the end users). Not sure if the Acrobat Reader extensions will cover this functionality since I have not tried that. I dont think it does. Otherwise you would need full acrobat on each client.
    How much database integration is your form actually doing at the moment? read only? Full access? And how many clients do you expect to hit your database? Depending on what you need the form to do, there is always the option to try and build the integration yourself. Do simple http submits from the browser (hosting reader as a plugin) to some component somewhere which in turn hits your database. Wouldnt require additional licensing but alot more development work.
    As for cost for the various components, thats a question only Adobe can answer for you since they all sit squarely in the enterprise space and licensing for that is not as simple as off the shelf products.
    Maybe someone else has a view on it or has an alternative.

  • I need to host a website with a SQL database - Azure pricing details are too confusing

    Hello,
    I need to give a potential client a hosting price for a somewhat simple web application they want me to build. I told them it shouldn't be a problem. After gathering the requirements, I figured I would use the following technology to build and host
    it:
    ASP.NET 4.5
    MVC 5
    1 SQL Database ~ 25GB with options to expand and also with a backup
    SSL certificate needed
    Hosting would be on Azure because I have some experience using Visual Studio 2012 and integrating the Visual Studio Online (TFS) source code and scrum web applications. I've never actually spun up a website with a SQL database using Azure before, but I
    imagined it wasn't too difficult to find a general hosting plan to support the above requirements.
    The use of the website will be very simple and limited to the basic CRUD operations. Will support forms authentication using the Identity 2.0 framework. The web applications main purpose is to fill out a form for new accounts, have a search page for
    those accounts, a page to view a created account and add notes to it. So performance wise, it isn't asking for much. I just want it to be fast and secure.
    So I start looking on the Azure's pricing landing page which is here: (can't put links in here, but search Azure pricing on Bing) and I see this Pricing Calculator, so I click it
    First thing I notice is the Websites tab doesn't mention SQL Database - in fact the Data Management is a separate tab from Websites. And if I made my selections on the Websites tab, the estimated monthly price doesn't stay the same when I go to the Data
    Management tab - so I get the illusion I have to have two separate purchases.
    I'm not exactly sure if the Pay as You Go billing feature would be okay because it's just a bit scary to leave every monthly payment up to chance; somewhat. Would love to know if there is other payment options that I could see for what I described above.
    I want to use Azure to host my asp.net website - it makes sense and the integration with Visual Studio is amazing. I love the publish feature for both MVC 5 Projects and SQL Database Projects.
    Thanks in advance for the help!

    Hello jdevanderson,
    I suggest that you start by looking at the pricing TIERS for the Azure website. This link will give you clarity on different Service TIERS that are availaible:
    http://azure.microsoft.com/en-in/pricing/details/websites/
    You can guage your requirement and choose the Service TIER accordingly.
    And regarding the database, you are right about it. You will be charged seperately for the database. You can refer to this link that will give you clarity on SQL database pricing:
    http://azure.microsoft.com/en-in/pricing/details/sql-database/
    Refer to this link for more information on 'How pricing works':
    http://azure.microsoft.com/en-in/pricing/
    Use the full calculator to add your website and the database to get an estimated cost:
    http://azure.microsoft.com/en-in/pricing/calculator/?scenario=full
    Thanks,
    Syed Irfan Hussain

  • Need Help/Advice with Photo Web Gallery coming from SQL Database

    This is my first attempt at a database driven website. I assume what I am trying to accomplish should be fairly easy for more experienced but I am stuck at this point.
    First, let me explain what I am trying to accomplish.
    I want to create a thumbnail photo gallery displayed in columns and rows. I want to be able to hover over or click on the thumbnail image and have a lightbox script display the image over the thumb page. I am developing locally right now with intent to upload to the hosting site upon completion.
    I am developing with ASP vbScript pages. I have an SQL database where the paths to the image thumbnails and pictures are stored in a table. On the gallery page, I have created a div tag to hold my image recordset. Within this div, I have inserted 3 absolute positioned divs to hold the pictureID, the pictureName and the image inserted as a datasource. I then inserted the information from the bindings panel of my recordset. Last, I used a horizontal looper extension from Tom Muck to get the thumbnails to display in columns and rows. Everything works up to this point just fine.
    Now, I want to be able to hover or click on a thumnail image and have it displayed in a lightbox. I downloaded and used a javascript called Lightbox 2 which contains 3 javascript files and a css stylesheet. I inserted the files into the head tag like instructed to but could not get things to work properly. Here is where I need help. Currently, I am clicking on the thumbImage binding within the image Div and creating a link holder. I am then binding the larger pictureImage to it with the a.href selected in the bind to. I am then adding the command to call the lightbox javascript. Now, when I test my page, my thumbnail images do not show up (my alt text does in its place) but the links are in place and you can click on the alt text and it will return the correct larger image, but not in the lightbox, just in a new window with no styles.
    Am I going about this correctly? Can you use lightbox scripts with data-driven galleries? Does anybody have any suggestions of what I may be doing wrong or missing? Are there better ways to go about accomplishing this?
    Any help would be appreciated as this dynamic data thing has my head spinning. Although I know a database is needed to simplify the update and maintenance of the photos while allowing them to be searchable by keywords and tags also set up in the database.
    Thanks

    As I explained, I am developing locally a the moment. I will see about getting the databased moved up to the hosting server and then provide a link for an example.
    In the mean time, can you or anyone else explain a way that you would go about displaying an image thumbnail photo gallery laid out in rows / columns, with any lighbox script that would overlay the larger image over the existing page instead of opening a new browser window?
    I don't have to use the method I tried to describe.
    In all of the lightbox examples I have looked at thus far, they give instructions on how to append that javascript to a single static image or a group of static images, not images from a datasource. That is where I am getting confused.
    Don't know if this will help or not but please see code below:
    Javascript and CSS positioned in head tag
    <!--beginning of lightbox script with css -->
    <link href="CSS/lightbox.css" rel="stylesheet" type="text/css" />
    <script src="Scripts/protype.js" type="text/javascript"></script>
    <script src="Scripts/scriptaculous.js?load=effects,builder" type="text/javascript"></script>
    <script src="Scripts/lightbox.js" type="text/javascript"></script>
    <!--end of lightbox script with css -->
    Calling for javascript in the galleryimage div when hovering over thumbnail image
        <!--beginning of gallery div -->
        <div id="gallery">
          <p>
            <!--beginning of galleryImage div -->
          </p>
          <table width="400" border="0" align="center" id="galleryNav2">
            <tr>
              <td width="100" align="center"><% If MM_offset <> 0 Then %>
                  <a href="<%=MM_moveFirst%>">First</a>
              <% End If ' end MM_offset <> 0 %></td>
              <td width="100" align="center"><% If MM_offset <> 0 Then %>
                <a href="<%=MM_movePrev%>">Previous</a>
              <% End If ' end MM_offset <> 0 %></td>
              <td width="100" align="center"><% If Not MM_atTotal Then %>
                <a href="<%=MM_moveNext%>">Next</a>
              <% End If ' end Not MM_atTotal %></td>
              <td width="100" align="center"><% If Not MM_atTotal Then %>
                <a href="<%=MM_moveLast%>">Last</a>
              <% End If ' end Not MM_atTotal %></td>
            </tr>
          </table>
          <p> </p>
          <table align="center" id="HorzLooper">
            <%
    startrw = 0
    endrw = HLooper1__index
    numberColumns = 5
    numrows = 5
    while((numrows <> 0) AND (Not rs_ssfGallery.EOF))
    startrw = endrw + 1
    endrw = endrw + numberColumns
    %>
            <tr align="center" valign="top">
              <%
    While ((startrw <= endrw) AND (Not rs_ssfGallery.EOF))
    %>
              <td><div id="galleryImage">
                <div id="galleryThumb"><a href="images/pic/<%=(rs_ssfGallery.Fields.Item("picture_url").Value)%>"rel="lightbox"><img src="images/thumb/<%=(rs_ssfGallery.Fields.Item("thumb_url").Value)%>" alt="<%=(rs_ssfGallery.Fields.Item("alt_url").Value)%>" /></a></div>
                <div id="galleryImageID"><%=(rs_ssfGallery.Fields.Item("picture_ID").Value)%></div>
                <div id="galleryImageFamily"><%=(rs_ssfGallery.Fields.Item("family").Value)%></div>
              </div></td>
              <%
    startrw = startrw + 1
    rs_ssfGallery.MoveNext()
    Wend
    %>
            </tr>
            <%
    numrows=numrows-1
    Wend
    %>
          </table>
          <p> </p>
          <table width="400" border="0" align="center" id="galleryNav">
            <tr>
              <td width="100" align="center"><% If MM_offset <> 0 Then %>
                  <a href="<%=MM_moveFirst%>">First</a>
              <% End If ' end MM_offset <> 0 %></td>
              <td width="100" align="center"><% If MM_offset <> 0 Then %>
                  <a href="<%=MM_movePrev%>">Previous</a>
              <% End If ' end MM_offset <> 0 %></td>
              <td width="100" align="center"><% If Not MM_atTotal Then %>
                  <a href="<%=MM_moveNext%>">Next</a>
              <% End If ' end Not MM_atTotal %></td>
              <td width="100" align="center"><% If Not MM_atTotal Then %>
                  <a href="<%=MM_moveLast%>">Last</a>
              <% End If ' end Not MM_atTotal %></td>
            </tr>
          </table>
    <!--end of galleryImage div -->
        </div>
        <!--end of gallery div -->
    Thanks for any help or suggestions.

Maybe you are looking for