Bug 13343 - FTPWebrequest error from Android.
Summary: FTPWebrequest error from Android.
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: BCL Class Libraries ()
Version: 4.6.x
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2013-07-19 12:33 UTC by phillygen
Modified: 2013-09-18 12:57 UTC (History)
1 user (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Wireshark of ftp commands. (180.97 KB, image/png)
2013-07-24 16:26 UTC, phillygen
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description phillygen 2013-07-19 12:33:29 UTC
I'm developing an android app that uses ftp. When my ftp server path starts with a "\" rather than a "/", I get the following exception thrown when trying to get an FTPWebResponse.

System.UriFormatException: Invalid URI: The hostname could not be parsed. at System.Uri.Parse (UriKind kind, System.String uriString) [0x00000] in :0 at System.Uri.ParseUri (UriKind kind) [0x00000] in :0 at System.Uri..ctor (System.String uriString, Boolean dontEscape) [0x00000] in :0 at System.Uri..ctor (System.String uriString) [0x00000] in :0 at System.Net.FtpWebRequest.GetRemoteFolderPath (System.Uri uri) [0x00000] in :0 at System.Net.FtpWebRequest.CWDAndSetFileName (System.Uri uri) [0x00000] in :0 at System.Net.FtpWebRequest.ProcessMethod () [0x00000] in :0 at System.Net.FtpWebRequest.ProcessRequest () [0x00000] in :0 There was an error connecting to the FTP Server.

Code: 
FtpWebRequest request = FtpWebRequest.Create(FTPAddress + "/" + filename) as FtpWebRequest; 
request.Method = WebRequestMethods.Ftp.DownloadFile; 
request.Credentials = new NetworkCredential(username, password); 
request.UsePassive = true; 
request.UseBinary = true; 
request.KeepAlive = true; //close the connection when done 

//Streams 
FtpWebResponse response = request.GetResponse() as FtpWebResponse; //Error here!

I have no problems using the same code with a windows application on my PC. And I can access my server with a 3rd party ftp tool, like FileZilla.
Comment 1 phillygen 2013-07-23 20:01:26 UTC
static string GetInitialPath (FtpStatus status)

Found in FtpWebRequest.cs in System.Net

if (!msg.EndsWith ("/"))
    msg += "/";

return msg;

Seems like this function is appending another "/" forward slash that will affects parsing later on in the code. In our case, the resulting string 'msg' becomes "\/".

One possible fix is to add code to look for a backslash '\' and replace with a forward slash '/'
Another option is to parse the slash that is returned in this function from the ftp server and use that for all future slash handling.
Comment 2 Jonathan Pryor 2013-07-24 14:08:06 UTC
> When my ftp server path starts with a "\" rather than a "/",

What's the value of FTPAddress?

Also note the stack trace: Uri.Parse() is throwing the UriFormatException. FtpWebRequest.GetRemoteFolderPath() is assuming/requiring that the path is a valid URI. I'm guessing that the construction `FTPAddress + "/" + filename` is not in fact a valid URI.
Comment 3 phillygen 2013-07-24 14:17:18 UTC
the value of FTPAddress is

For example:
ftp://1.2.3.4

i've tried the following URIs

ftp://1.2.3.4/filename.xxx
ftp://1.2.3.4\filename.xxx

same exception is thrown for either case
Comment 4 Jonathan Pryor 2013-07-24 15:02:52 UTC
Sorry, I misread...lots of things.

`FTPAddress + "/" + filename` (1) doesn't appear to be the problem, and (2) if it were, the WebRequest.Create() call would be throwing, which isn't the case. Clearly `FTPAddress` and `filename` aren't immediately at fault.

What appears to be happening is FtpWebRequest.OpenControlConnection() sends a Ftp.PrintWorkingDirectory request to the FTP server. The request is read back, and the result is processed. It's the processing which fails.

Rephrased: I don't think our FTP infrastructure likes your FTP server (or hasn't been tested with it). :-(

What's your FTP server? :-)

That said, I don't think FtpWebRequest.GetInitialPath() appending '/' to the path will be a problem; usually lots of "/"'s are canonicalized into a single directory separator by the server, so "foo//bar" should be treated as "foo/bar". This also _appends_ '/' to the path.

I think the problem is actually in FtpRequest.GetFolderPath(): https://github.com/mono/mono/blob/master/mcs/class/System/System.Net/FtpWebRequest.cs#L552

	Uri initial = new Uri ("ftp://dummy-host" + initial_path);

_This_ is where things go wrong; if initial_path starts with a '\', or doesn't start with anything (possible?), then we can get either:

    ftp://dummy-host\initial_path
    ftp://dummy-hostinitial_path

Either way, the URL is invalid, it throws, and we get the stack trace in the initial bug request.
Comment 5 Jonathan Pryor 2013-07-24 16:15:30 UTC
phillygen@gmail.com : Assuming Comment #4's analysis is correct, could you please connect to your FTP server through e.g. the command-line `ftp` program, and provide the output of the PWD command?
Comment 6 phillygen 2013-07-24 16:26:19 UTC
Created attachment 4425 [details]
Wireshark of ftp commands.

Wireshark of ftp commands.
Comment 7 phillygen 2013-07-24 17:06:44 UTC
BTW, the FTP Server is an Embedded FTP Server in a Industrial Automation Hardware.
Comment 8 Jonathan Pryor 2013-07-24 17:11:44 UTC
So, the good news is my hypothesis is correct.

Yay.

The bad news is that when I fix FtpRequest.GetFolderPath() so that it behaves better with '\'-prefixed directories, paths are still "munged", and I don't know if this will work with your server.

For example, assume that we want to download ftp://example.org/path/file:

$ ftp example.org
ftp> PWD
257 "\"

Assuming the above works, we'd try:

ftp> CWD /path

The question: using '/' instead of '\' actually work with your server? Or will your server require '\path'?

If your server will accept '/', then things are fine. If your server won't, then the CWD command Mono generates will need to be fixed to use the appropriate directory separator char.

phillygen@gmail.com: does `CWD /` work without error? Is use of '/' acceptable by your FTP server?
Comment 9 phillygen 2013-07-24 19:04:10 UTC
The app needs to access folder paths of either

\folder1\folder2\file.xxx

or 

/folder1/folder2/file.xxx

I've had no problem accessing ftp servers with the forward slash.
Comment 10 phillygen 2013-07-24 19:11:37 UTC
I managed to achieve my results using the following ftpclient code:
http://netftp.codeplex.com/

but i would prefer to use the built-in class libraries instead of this.
Comment 11 Jonathan Pryor 2013-07-24 21:20:25 UTC
If forward slash is acceptable, I have a fix. Will be committing tomorrow; should make it into 4.8.1.
Comment 12 Jonathan Pryor 2013-07-25 11:41:02 UTC
mono/f9d78260d contains the FtpWebRequest fix:

https://github.com/mono/mono/commit/f9d78260db9141db87ba000b772d997ff1a64caf
Comment 13 Jonathan Pryor 2013-07-25 12:15:18 UTC
Fixed in monodroid/fbfec206.
Comment 14 phillygen 2013-08-16 13:58:55 UTC
I've installed the 4.8.1 version, but now it's worse!

I get an error on this line:

FtpWebRequest request = FtpWebRequest.Create(FTPAddress + "/" + filename) as FtpWebRequest;

System.UriFormatException: Invalid URI: The format of the URI could not be determined: 10.167.65.128/usr/tablet/tabinfo.xml
  at System.Uri..ctor (System.String uriString, Boolean dontEscape) [0x00000] in <filename unknown>:0 
  at System.Uri..ctor (System.String uriString) [0x00000] in <filename unknown>:0 
  at System.Net.WebRequest.Create (System.String requestUriString) [0x00000] in <filename unknown>:0 
  at HMI.FTPManager.downloadFile (System.String FTPAddress, System.String filename, System.String username, System.St


This exception is thrown when my device is either "/" or "\"
Comment 15 Jonathan Pryor 2013-08-28 14:41:39 UTC
XA 4.8.2 contains this fix, not 4.8.1:

http://docs.xamarin.com/releases/android/xamarin.android_4/xamarin.android_4.8#Xamarin.Android_4.8.2

Furthermore, FtpWebRequest doesn't contain FtpWebRequest.Create(); it's inherited from WebRequest.Create(). Consequently this:

    FtpWebRequest.Create(FTPAddress + "/" + filename)

is _actually_:

    WebRequest.Create(FTPAddress + "/" + filename)

If FTPAddress doesn't start with "ftp://", then there's no way for WebRequest to know that you want FTP access. Please make sure you have the correct URI prefix.
Comment 16 phillygen 2013-09-11 19:51:11 UTC
After installing the 4.8.2 alpha release, I was able access server paths that have both either "/" or "\" successfully.

Thank you!
Comment 17 Jonathan Pryor 2013-09-18 12:57:33 UTC
Marking as fixed, as per Comment #16.