www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - upload with curl

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.
Apr 03 2012