paul.nowak wrote: Matt, thanks for the comments. I made an error on the version of Plone. It's 2.5 Plone running on Zope 2.9x.
In regards to the additional products, we have a skin installed and we have a product that we had custom developed for us that connects to a PostgreSQL database. We've looked at slow PostgreSQL queries causing problems and have not been able to find an issue. We've also tested for the case where the PostgreSQL server is down and have not been able to create an issue. We therefor...
If I had to pick the most underutilized and most misunderstood of all the ColdFusion tags, it would have to be the CFFTP tag. The CFFTP tag has been around since version 3.x of ColdFusion and allows ColdFusion applications to interact with FTP servers anywhere in the world. The CFFTP tag gives us the ability to perform a whole range of FTP commands from our ColdFusion applications. Everything from file uploads and downloads to remote directory and file manipulation can be handled by the tag. The power of the CFFTP tag opens up a whole host of possibilities for applications -- from Web-based FTP clients to agents that search FTP directories to see what files are available. The possibilities are limited only by your creativity.
The CFFTP tag differs from most other ColdFusion tags in that it isn't a native ColdFusion tag, but rather an external COM object that ColdFusion connects to via the CFOBJECT tag. Because of this, you must have the CFOBJECT tag enabled from the ColdFusion Administrator. You should also be aware that because the CFFTP tag makes use of a COM object, you can't use it if you are running ColdFusion on a Windows NT 3.5x machine.
Since its release, there has been a lot of confusion surrounding what the CFFTP tag can and can't be used for. To set the record straight, the CFFTP tag is used for FTP tasks between the ColdFusion server and an FTP server. This means that it can't be used to upload a file from a client's machine to your ColdFusion server (this is handled with the CFFILE tag) or to download a file from a remote FTP server to a client's machine (this is done with CFCONTENT).
That being said, let's take a look at how the CFFTP tag actually works and how you can use it to handle FTP tasks. All FTP operations start out by opening a connection to the remote FTP server. There are several different ways to do this. The most basic method is shown below.
<CFFTP ACTION="open"
SERVER="ftp.netscape.com"
USERNAME="anonymous"
PASSWORD="rbils@amkor.com"
CONNECTION="MyConnection"
STOPONERROR="No">
<CFIF NOT CFFTP.Succeeded>
Error!<BR>
<CFOUTPUT>
Error number #CFFTP.ErrorCode#: #CFFTP.ErrorText#
</CFOUTPUT>
<CFABORT>
</CFIF>
Connection to ftp.netscape.com opened successfully!
<CFFTP ACTION="close"
CONNECTION="MyConnection"
STOPONERROR="No">
<CFIF NOT CFFTP.Succeeded>
Error!<BR>
<CFOUTPUT>
Error number #CFFTP.ErrorCode#: #CFFTP.ErrorText#
</CFOUTPUT>
<CFABORT>
</CFIF>
Connection to ftp.netscape.com closed successfully!
First, the ACTION parameter is set to "open." This opens the connection to the FTP server listed in the SERVER attribute -- in this case, the anonymous FTP server hosted by Netscape. The USERNAME and PASSWORD attributes are used to send a username and password, respectively, to the FTP server. When connecting to anonymous FTP servers, it is customary to use "anonymous" as the username and your e-mail address as the password. CONNECTION is an optional attribute that allows you to use connection caching for your FTP connections. This means that by specifying a value for CONNECTION, the FTP session we establish can be reused on the page without having to specify the SERVER, USERNAME and PASSWORD for each additional FTP task. The final attribute shown in the example is STOPONERROR. STOPONERROR tells ColdFusion what to do in the event that an error occurs during the FTP process. If set to "Yes" ColdFusion will throw a standard ColdFusion error in the event that something goes wrong and halt processing of the template. If STOPONERROR is set to "No," as in our example, ColdFusion continues to process the template in the event that an error occurs and generates three variables: CFFTP.Succeeded, CFFTP.ErrorCode and CFFTP.ErrorText. These variables contain information about the state of the FTP operation.
The second part of the example looks at the CFFTP.Succeeded variable generated because STOPONERROR is set to "No." CFFTP.Succeeded returns as "Yes" if the FTP transaction is successful and "No" if it is not. In our case, if the FTP operation is successful, a message is returned to the Web browser stating that the connection was successful and the template continues processing. If an error is encountered, an error code and error message are returned to the user's Web browser and processing of the template is halted via a CFABORT tag. The values for CFFTP.ErrorCode and CFFTP.ErrorText are listed in the table below:
CFFTP.ErrorCode
CFFTP.ErrorText
0
Operation succeeded
1
System error (OS or FTP protocol error)
2
An Internet session could not be established
3
FTP session could not be opened
4
File transfer mode not recognized
5
Search connection could not be established
6
Invoked operation valid only during a search
7
Invalid timeout value
8
Invalid port number
9
Not enough memory to allocate system resources
10
Cannot read contents of local file
11
Cannot write to local file
12
Cannot open remote file for reading
13
Cannot read remote file
14
Cannot open local file for writing
15
Cannot write to remote file
16
Unknown error
17
Reserved
18
File already exists
19
Reserved
20
Reserved
21
Invalid retry count specified
The third part of our example calls the CFFTP tag again using the cached connection we established when we opened the FTP session with Netscape's server. This time, however, the ACTION attribute is set to "close." This tells ColdFusion that we want to close the FTP session with Netscape's server. Although it isn't technically necessary to close the connection with the remote server, it is the right thing to do. Failing to close an active FTP session results in the session remaining open for as long as the remote server allows inactive sessions to be open. For servers that limit the number of concurrent FTP sessions, this means that the session you are no longer using is tying up a session that someone else could be using.
Finally, the last part of the example performs another check to see if we were successful in closing the FTP session. If so, a message is written back to the browser confirming that the session has been closed. If, however, an error occurs, the error number and error message are written back to the browser and a CFABORT tag stops any further processing of the template.
Now that we see how to open a connection to the FTP server, let's look at some of the other functions that we can handle with the tag. Let's start with the CONNECTION attribute of the CFFTP tag. Remember I said that the attribute is used to name the FTP connection so that is can be reused throughout the template. This is almost always desirable because if you don't specify a value for CONNECTION, you have to include the SERVER, USERNAME and PASSWORD attribute with every subsequent call of the CFFTP tag you make within the same template.
Taking our previous example of establishing a cached session with Netscape's FTP server, let's add an additional CFFTP tag to get a list of the files and directories residing on the remote server. To do this, modify the previous example to look like this and save it on your ColdFusion server as ex1.cfm.
<!--- Set a default path for the CFFTP command to / --->
<CFPARAM NAME="URL.Path" DEFAULT="/">
<CFFTP ACTION="LISTDIR"
SERVER="ftp.netscape.com"
USERNAME="anonymous"
PASSWORD="rbils@amkor.com"
CONNECTION="MyConnection"
STOPONERROR="No"
NAME="ShowContents"
DIRECTORY="#Url.Path#">
<!--- if there is an error, report it and abort --->
<CFIF NOT CFFTP.Succeeded>
Error!<BR>
<CFOUTPUT>
Error number #CFFTP.ErrorCode#: #CFFTP.ErrorText#
</CFOUTPUT>
<CFABORT>
</CFIF>
Connection Opened Successfully!
<P>
<TABLE BORDER="1" CELLSPACING="1" CELLPADDING="3">
<TR>
<TH>Name</TH>
<TH>Path</TH>
<TH>URL</TH>
<TH>Length</TH>
<TH>Last Modified</TH>
<TH>Directory or File</TH>
<TH>Attributes</TH>
</TR>
<CFOUTPUT QUERY="ShowContents">
<TR>
<CFIF ISDirectory>
<TD>
<A HREF="ex1.cfm?
Path=#UrlEncodedFormat(path)#">
#name#</A>
</TD>
<CFELSE>
<TD>
<A HREF="ftp://ftp.netscape.com#path#">
#Name#</TD>
</CFIF>
<TD>#path#</TD>
<TD>#Url#</TD>
<TD>#length#</TD>
<TD>#DateFormat(lastmodified,'mm/dd/yyyy')#</TD>
<TD>
<CFIF ISDirectory> Directory <CFELSE> File
</CFIF>
</TD>
<TD>#Attributes#</TD>
</TR>
</CFOUTPUT>
</TABLE>
<!--- close the ftp connection --->
<CFFTP ACTION="close"
CONNECTION="MyConnection"
STOPONERROR="No">
<!--- If there is an error, report it and abort --->
<CFIF NOT CFFTP.Succeeded>
Error!<BR>
<CFOUTPUT>
Error number #CFFTP.ErrorCode#: #CFFTP.ErrorText#
</CFOUTPUT>
<CFABORT>
</CFIF>
<P>
Connection Closed Successfully!
The first thing that you should notice is that we got rid of the CFFTP tag that had ACTION set to "open." We can combine the opening of the FTP session with the actual action we want to perform -- in this case a directory listing using ACTION = "ListDir." What we get (assuming no errors are encountered during any of the FTP actions) are the directory contents of the root directory at ftp.Netscape.com. By setting the ACTION attribute to "ListDir," we let ColdFusion know to retrieve a directory listing from the remote server and store the results as a query object which we name in the NAME attribute. The query object that gets created contains the following fields:
QueryColumn
Description
Name
Name of the current file or directory
Path
File path of the current file or directory
URL
URL to the current file or directory
Length
Size of the current file or directory
LastModified
Date that the file or directory was last modified
Attributes
Currently not working as intended
IsDirectory
Returns "Yes" if the object is a directory, "No" if it is not
We can take our above example one step further. If we add this CFPARAM line
<!--- Set a default path for the CFFTP command to / ---> <CFPARAM NAME="URL.Path" DEFAULT="/">
to the top of our template, and modify the output table so that we change the NAME column from plain HTML to a hyperlink, it is possible to create the beginnings of a simple FTP client that allows users to drilldown through the Netscape FTP server and download any files they come across. Since the CFFTP tag only handles file downloading from a remote FTP server to your ColdFusion server, we must use a standard FTP link as opposed to the CFFTP tag to handle the actual download.
For now, go ahead and change the block of code between the <CFOUTPUT> </CFOUTPUT> tags to look like this:
What we've done here is put in a bit of conditional logic to determine if the object being listed is a directory or a file. If the object is a directory, the path to the directory gets appended to a hyperlink as a URL parameter called Path. If the link is clicked, it causes the page to reload with the value of Path being used to update the CFFTP tag. This allows a single template to be used to drill down through the FTP site. If the object being returned is a file, an FTP hyperlink is created directly to the file -- allowing the user to click on the link and download the file directly to their machine.
This example is by no means a complete FTP client, but it should start you off in the right direction. It would be fairly easy to modify the example to allow you to perform additional FTP actions such as uploading, renaming, and deleting files. Have fun!