April 03, 2012
Hello all,

I'm trying to use curl library to satisfy my file transfer needs under Windows 7. I've spent all the day and the most of functionality I have already tried works like a charm. But I have a few issues with "upload" function.

First of all, if I try to use something like:
   auto client = FTP("192.168.110.58");
or:
   upload!FTP("file.zip", "192.168.110.58");
curl wrapper does not understand we are trying to use ftp-protocol and uses http instead, returning something like:
   <?xml version="1.0" encoding="iso-8859-1"?>
   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
     <title>400 - Bad Request</title>
    </head>
    <body>
     <h1>400 - Bad Request</h1>
    </body>
   </html>
Not a big deal, I'll use "ftp://xx.xx.xx.xx" format everywhere below.

Here is the code I'm trying to use to upload a local file to the ftp-host with an authentication:
   auto client = FTP();
   client.setAuthentication("login", "pass");
   upload!FTP("file.zip", "ftp://192.168.110.58/file.zip", client);
This will pass the authentication but won't upload the file.

Then I decided to take a look to the code of std.net.curl.upload function and use a low-level API the same way to find the solution. Here is what I got:
   auto f = new std.stream.BufferedFile("file.zip", FileMode.In);
   scope (exit) f.close();
   auto client = FTP("ftp://192.168.110.58");
   client.verbose(true);
   client.setAuthentication("login", "pass");
   client.onSend = (void[] data)
   {
      return f.read(cast(ubyte[])data);
   };
   client.contentLength = cast(size_t)f.size;
   client.perform();
It's basically the same as "upload" function. This authenticates correctly, gets directory listing and then nothing happens:
   * Connection #0 to host 192.168.110.58 left intact
   > QUIT
   < 221 Goodbye.
   * Closing connection #0
And it looks correct for me, why should it upload any file!?

So I decided to replace the last line of the code with the following:
   client.addCommand("epsv");
   client.addCommand("stor file.zip");
   client.perform();
Here is the results:
   > epsv
   < 229 Entering Extended Passive Mode (|||12761|)
   > stor file.zip
   * FTP response timeout
   * Connection #0 to host 192.168.110.58 left intact
   * Timeout was reached
   > QUIT
   * server response timeout
   * Closing connection #0
   std.net.curl.CurlTimeoutException@std\net\curl.d(3333): 6B2BD8C6 on handle 166CB60
This way the file was created on the server, but it's empty. It looks like client.onSend statements are never executed. Unfortunately, I didn't managed to find out why, it's somewhere in object "private RefCounted!Impl p" (curl.d:1956), but I didn't find where it is.

So, what am I doing wrong? Does std.net.curl.upload work for you correctly? How do I upload a file to the ftp-host with authentication? What is "RefCounted!Impl p" and where do I find it's "p.curl.perform()" method?

P.S.: Firewall is not the case, other ftp clients and std.net.curl.download function work fine, rules for the program are created (just in case).

Thank you in advance, any advice is really appreciated.