Why doesn't FTPWebRequest, or WebRequest in general accept a /../ path? - c#

I am trying to automate some upload/download tasks from an ftp web server. When I connect to the server through client, or through Firefox even, in order to get to my directory, I have to specify a path like this:
ftp://ftpserver.com/../AB00000/incoming/files
If I try to access this:
ftp://ftpserver.com/AB00000/incoming/files
The server throws an error that the directory does not exist. So, the problem:
I am trying to create an FTPWebRequest with the first ftp address, but it always parses out the "/../" part and then my server says the path doesn't exist.
I've tried these:
Uri target = new Uri("ftp://ftpserver.com/../AB00000/incoming/files");
FtpWebRequest request = (FtpWebRequest)WebReqeuest.Create(target);
and
string target = "ftp://ftpserver.com/../AB00000/incoming/files";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(target);
In the first bit, the path is already incorrect when the Uri object is instantiated, in the second bit, it's after the WebRequest.Create method. Any ideas what's going on?
EDIT:
Additionally, since I posted this, I have tried creating the URI with the no parse option. I have also tried something like this:
string ftpserver = "ftp://ftpserver.com/../";
string path = "12345/01/01/file.toupload";
Uri = new Uri(ftpserver, path, true);
And it always parses out the root part ("/../").

Try escaping the .. with something like:
Uri target = new Uri("ftp://ftpserver.com/%2E%2E/AB00000/incoming/files");
That works according to this blog which I found in this discussion.

Not really sure about it, but it may be for security reasons, since allowing "/../" URIs would potentially let people navigate freely on any server's file system.
Also, the official URI RFC states that when resolving an URI one of the steps performed is actually the removal of "/../" segments, so it's not a problem in the C# library but it's regular URI behavior.

Have you tried using the # symbol like so?
Uri target = new Uri(#"ftp://ftpserver.com/../AB00000/incoming/files");
FtpWebRequest request = (FtpWebRequest)WebReqeuest.Create(target);

Related

URI encodes control signs into absolute path

We are sending data to an API with several endpoints. For this we put the base URL into a variable and appending the route info to it. But the request cannot be resolved to a service, as the URI-object is putting not printable characters into the path.
The code for create the URI object:
var uri = new Uri(_url + "/api/v1/create");
The result is:
https://localhost%E2%80%8B/api%E2%80%8B/v1%E2%80%8B/create
We are using .Net Framework 4.7.2.
Does anyone know, whats happening?
As canton7 pointed out, the problem had been the zero-length space here
We retyped the whole method calls - not only the URLs - and now the system is running. Thanks.

How to set a proxy when using SoapPortClient?

I'm trying to execute a function using a Soap Port Client object (from an external WebService), and I need to set a proxy (address and credentials) for it. Because when I test the app (not on localhost), the WS functionality doesn't work.
Namespace.WebService.SoapPortClient foo = new Namespace.WebService.SoapPortClient();
short cod_error;
string des_error;
string url = "";
int fooNumber = 10;
url = foo.Execute(fooNumber, out cod_error, out des_error);
...code continues
In the above example, I need to set a proxy for 'foo'. I've tried with foo.Proxy but this property doesn't exists in the SoapPortClient.
Thank you all!
After reading your comments and problem I realized that you are talking about WCF.
Regards to your latest problem:
Now I'm getting the following error: The content type text/HTML of the response message does not match the content type of the binding (text/XML; charset=utf-8)
My first suggestion would be to check that the user you're running the WCF client under has access to the resource.
Can't say much since it's very hard to say something without seeing the config file or code in general.

Correct way of manipulating the url coming from App.config

I have a URL ("http://localhost:2477/") on which I do get and post request. I have stored this URL in the app.config file of my project.
In the code, depending on the function, I add the string "getValue?id={0}" or "postValue" to this URL. But I later ran into an issue when I changed the URL to "http://localhost:2477" (no forward slash in the end) in the app.config.
Took me some embarrassing amount of time to figure out this issue, which made me wonder if there is a good way to handle this case.
Irrespective of the case when there is a forward slash or not in the URL, I want my code to change it to a proper URL.
Always use Path.Combine(string, string). This method will conform a valid path and should add the / if needed.
edit
I realized my answer does not work for URL, just for file paths.
What you’re looking for is Uri constructor instead.
Uri baseUri = new Uri("http://www.contoso.com");
Uri myUri = new Uri(baseUri, "catalog/shownew.htm");
Using the Uri class you can modify your URL more elegantly. You can access the Host, Port, Query, etc. with ease. A similar question was asked here.
Try to use the UriBuilder, it's far more flexible as the Uri Constructor.
See https://stackoverflow.com/a/20164328/10574963

Uri Constructor .NET Framework Bug?

Why the thirdRelativeUri fails? Is this a .NET bug? Seems like not fixed in 4.0 either.
var googleU = new Uri("http://www.google.com");
var secondRelativeUri = new Uri(googleU,"//test.htm"); // doesn't fail
var thirdRelativeUri = new Uri(googleU,"///test.htm"); // fails - Invalid URI: The hostname could not be parsed.
UPDATE:
#dariom pointed out that this is because protocol relative URL handling in .NET which make sense however this still seems buggy to me:
var thirdRelativeUri = new Uri("///test.htm",UriKind.Relative); // works as expected
var newUri = new Uri(googleU,thirdRelativeUri); //Fails, same error even though it's a relative URI
It fails even when the second Uri is Relative
The file uri scheme (RFC 1738) file://[host]/path shows that host is optional. ///test.html would mean "Since this usually used for local files the host from RFC 1738 is often empty leading to a starting triple /. (ref)"
Change ///test.htm to file:///test.htm and the URI constructor will parse it properly. It's AbsolutePath will be /test.html.
Hope this helps.
I think that the constructor is interpreting "//test.htm" as a URI with no scheme and a hostname of test.htm. You can see this by examining the value of secondRelativeUri - it's "http://test.htm/".
The third URI you're creating is invalid because you have too many slashes.
new Uri(googleU,"//test.htm") mean Uri = http://test.html/ /* valid, Anyway a root somewhere */
new Uri(googleU,"///test.htm") mean Uri = http:///test.html/ /* invalid, Meaningless */
new Uri("///test.htm",UriKind.Relative); //=> Uri = ///test.htm same mistake, not relative location
var r = new Uri("test.htm",UriKind.Relative);
new Uri(googleU, r); // => Uri = http://www.google.com/test.htm
Even when creating relative URLs, .net treats a string that starts with tow slashes as a host name like in "//example.org/document". Similarly three slahes makes a confusion and an exception is thrown. If you are pretty sure these //test.htm and ///test.htm are paths, then you can try using UriBuilder class.

C# decodes URL containing %2F on path, is there any way to instruct API to send the URL as it is?

I am having a URL in below format
abcd.com/xyz/pqr%2Fss/abc
I want this to be send to server as it is.
When I build Uri using System.Uri it converts it to abcd.com/xyz/pqr/ss/abc
and it fails as I don't have a URL with the specified path.
When I tried with double encoding
(abcd.com/xyz/pqr%252Fss/abc) it send the Uri as it is but it fails as server side it is converted to (abcd.com/xyz/pqr%2Fss/abc)
If you construct your uri as such:
Uri u = new Uri("http://abcd.com/xyz/pqr%2Fss/abc")
Access the encoded string like this:
u.OriginalString
I had this problem too, but I found the solution: when you use HttpUtility.UrlEncode to be sure that the application will read the url right you have to construct the link this way:
http://www.abcd.com/xyz?val=pqr%2Fss
and not like this
http://www.abcd.com/xyz/pqr%2Fss
where pqr%2Fss is the result of the HttpUtility.UrlEncode("SOME STRING")

Categories