Karl supplies us with an unusual bit of code. In the vein of a "true confession", it's code Karl wrote. In the vein of a good WTF, it had to be written like this because of bad choices made earlier in the pipeline.
But the code itself isn't a WTF. It's not good, but… well…
public override bool DirectoryExists(string dir)
{
//OH GOOOOD, DISGUSTING
//UGHHHH UGHHHH
try
{
FtpWebRequest ftpRequest = CreateRequest(dir);
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;
ftpRequest.GetResponse().Close();
return true;
}
catch
{
return false;
}
}
As you can see from the comments, Karl feels very bad about writing this code. Karl wrote it because, when examining the FTP access library he discovered that there wasn't a DirectoryExists
method, and Karl wanted to check to see if a directory existed.
Now, if you carefully examine the FTP commands, you'll note: there is no "exists" command. All you've got are a couple variations on list commands- the LIST
command (which has no standard format for how information is returned) and the MLST
/MLSD
commands, which do.
Karl's code takes a simple approach then: try and list the directory. If we can, return true. If we can't, that triggers an exception, we'll catch it and return false.
If there's anything bad in here, it's that we're not being selective about the exceptions. We want to catch whatever exception represents a file-not-found error, but let any other exception bubble up. Otherwise, this will return false
if the server is down, which is probably not what we want to have happen.
Given the features available in FTP, I'm not sure there's a more elegant way to do this.
Speaking of "inelegant ways to do this", Lothar recently sent us a different FTP WTF. Specifically, a customer was trying to bulk download JPGs from at FTP directory, and when they traced the FTP commands executed, they got this trace:
---> NLST *.jpg
<-- 150 Accepted data connection
<-- 226-Out of memory during globbing of *.jpg
<-- 226-(This probably means "Permission denied")
The --->
is the command sent, the <--
tells us what the server replies with. Much like HTTP, server responses lead with numeric status codes, and a 2xx
code represents a success. Obviously, this isn't a success, but we got a 226
response, which is explicitly a "we succeeded and we're closing the connection since we're all done here."
It's a weird message, and with a little googling, sometimes it's actually a memory issue, sometimes it really is a permission denied error, and sometimes it's apparently a certificate issue.
Which brings us to the real WTF, which isn't Karl's code or Lothar's error trace. It's FTP.
FTP is a legacy protocol which has been supplanted by more secure, more flexible, and definitely more usable file transfer protocols. But it's also still widely deployed, especially in enterprise spaces, because there are mainframe systems that need to send files and don't have a usable SFTP implementation (or, if they do, no one knows how to install it or set it up), or there's an EDI pipeline that was setup in 1986 that no one understands how it works but it is 100% central to the business process.
FTP is a legacy technology, and legacy technologies are like herpes: you might have had fun when it was getting installed, you probably went years without thinking about it, but when it goes wrong you regret everything, and you are never going to get rid of it.