SftpServerType.Unix not working ?

0 votes
asked May 8, 2013 by snake-apps (160 points)
edited May 14, 2013

I am connecting to SFTP server using C#.NET Rebex.Net.Sftp class Using Version 3.0.4546.0 of the Rebex.Sftp assembly

//Setting TransferType Rebex.Net.Sftp.TransferType = SftpTransferType.Ascii; //Setting ServerType Rebex.Net.Sftp.ServerType = SftpServerType.Unix;

However when I upload a file containing 0D 0A (CRLF) its not converted to 0A (LF). The SFTP server is running on Windows, but still I would expect the above code to work. What am I missing ?

commented May 8, 2013 by Lukas Pokorny (86,990 points)
edited May 8, 2013

I would say that it should actually work. Even though Rebex SFTP detects some Windows servers automatically, it should still prefer the ServerType property if set to Unix. So something might really be wrong. We will look into this and let you know! Which server do you use, by the way?

2 Answers

0 votes
answered May 9, 2013 by Tomas Knopp (58,580 points)
edited May 14, 2013
 
Best answer

I have tested the option SftpServerType in combination with SftpTransferType.Ascii and it yields proper results for me (uploaded file contains CRLF for SftpServerType.Windows and LF for SftpServerType.Unix.)

Could you please run the following code and see if CRLF are properly converted to LF with your Windows server?

        Sftp sftp = new Sftp();
        sftp.LogWriter = new FileLogWriter(@"C:\myData\log.txt");
        sftp.TransferType = SftpTransferType.Ascii;

        // change this property and see if remoteFileContents contains either
        // 'CRLF' sequence for newlines - in case of SftpServerType.Windows
        // or 'LF' for newlines - in case of SftpServerType.Unix
        sftp.ServerType = SftpServerType.Unix;

        sftp.Connect("server");
        sftp.Login("user", "password");

        string remoteFile = "test0123.txt";
        string textWithCRLF = "line1\r\nline2\r\nline3\r\nline4";
        var ms = new MemoryStream(Encoding.ASCII.GetBytes(textWithCRLF));

        sftp.PutFile(ms, remoteFile);

        // now download the file in binary mode and display it
        sftp.TransferType = SftpTransferType.Binary;

        ms = new MemoryStream();
        sftp.GetFile(remoteFile, ms);

        string remoteFileContents = Encoding.ASCII.GetString(ms.ToArray());

        // display it so that CR and LF are visible
        Console.WriteLine(remoteFileContents.Replace("\r", " {CR} ").Replace("\n", " {LF} "));
        sftp.Disconnect();
commented May 13, 2013 by snake-apps (160 points)
edited May 13, 2013

The sample code sample you delivered - works fine - no problems with converting there !!

However, my code is a bit different, as I'm using method below to obtain a Stream

public System.IO.Stream GetUploadStream(string remotePath) Member of Rebex.Net.Sftp

I was then using using Write methods below - and this is apperently where I got it wrong

public abstract void Write(byte[] buffer, int offset, int count) Member of System.IO.Stream

+1 vote
answered May 14, 2013 by Tomas Knopp (58,580 points)
edited May 14, 2013

GetUploadStream is a low level API and it would not be easily possible for us to modify line endings when uploading directly with this low-level approach. So the automatic line ending conversion in ASCII mode is only supported in Download, Upload, GetFile and PutFile methods.

However, if you need to take advantage of the automatic PutFile conversion, and at the same time use Stream for uploading, you could use Rebex experimental Pipe class like this:

        Sftp sftp = new Sftp();
        sftp.TransferType = SftpTransferType.Ascii;

        // change this property and see if remoteFileContents contains either
        // 'CRLF' sequence for newlines - in case of SftpServerType.Windows
        // or 'LF' for newlines - in case of SftpServerType.Unix
        sftp.ServerType = SftpServerType.Unix;

        sftp.Connect("server");
        sftp.Login("user", "password");

        string remoteFile = "test0123.txt";
        string textWithCRLF = "line1\r\nline2\r\nline3\r\nline4";
        var ms = new MemoryStream(Encoding.ASCII.GetBytes(textWithCRLF));

        ms.Position = 0;
        using (var pipe = new Rebex.IO.Pipe())
        {
            var dst = pipe.Input;
            var ar = sftp.BeginPutFile(pipe.Output, remoteFile, null, null);
            var buffer = new byte[0x7000];
            while (true)
            {
                int read = ms.Read(buffer, 0, buffer.Length);
                if (read <= 0) break;
                dst.Write(buffer, 0, read);
            }
            dst.Close();
            long n = sftp.EndPutFile(ar);
        }

        // now download the file in binary mode and display it
        sftp.TransferType = SftpTransferType.Binary;

        ms = new MemoryStream();
        sftp.GetFile(remoteFile, ms);

        string remoteFileContents = Encoding.ASCII.GetString(ms.ToArray());

        // display it so that CR and LF are visible
        Console.WriteLine(remoteFileContents.Replace("\r", " {CR} ").Replace("\n", " {LF} "));
        sftp.Disconnect();
...