F# FTP Fails where C# Succeeds - ftp

I've an application written in C# (.Net 3.5) with this code.
using System;
using System.Net;
string strURI = String.Format("ftp://x{0}ftp/%2F'{1}'", parm1, parm2);
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(strURI);
ftp.Proxy = null;
ftp.KeepAlive = true;
ftp.UsePassive = false;
ftp.UseBinary = false;
ftp.Credentials = new NetworkCredential("uid", "pass");
ftp.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
...
I've translated this into F# (.Net 4.0) to use in my application.
open System.Net
let uri = sprintf "ftp://x%sftp/%%2F'%s'" parm1 parm2
let ftp = FtpWebRequest.Create(uri) :?> FtpWebRequest
ftp.Credentials <- new NetworkCredential("uid", "pass")
ftp.Method <- WebRequestMethods.Ftp.DownloadFile
ftp.Proxy <- null
let response = ftp.GetResponse() :?> FtpWebResponse
...
At this point, FSI complains.
System.Net.WebException: The remote server returned an error: (550) File unavailable (e.g. file not found, no access).
Yet the C# application runs and successfully downloads the file. What am I missing in F# (besides the properties that aren't there in 4.0, i.e. KeepAlive, UsePassive, and UseBinary)?

The code may have errors, I don't have F# compiler right now.
open System
open System.Reflection
open System.Net
let switch_to_legacy_mode _ =
let wtype = typeof<FtpWebRequest>
let mfield = wtype.GetField("m_MethodInfo", BindingFlags.NonPublic ||| BindingFlags.Instance)
let mtype = mfield.FieldType
let knfield = mtype.GetField("KnownMethodInfo", BindingFlags.Static ||| BindingFlags.NonPublic)
let knarr = knfield.GetValue(null) :?> Array
let flags = mtype.GetField("Flags", BindingFlags.NonPublic ||| BindingFlags.Instance)
let flag_val = 0x100
for f in knarr do
let mutable ff = flags.GetValue(f) :?> int
ff <- ff ||| flag_val
flags.SetValue(f, ff)
let uri = sprintf "ftp://x%sftp/%%2F'%s'" parm1 parm2
do switch_to_legacy_mode () // Call it once before making first FTP request
let ftp = FtpWebRequest.Create(uri) :?> FtpWebRequest
ftp.Credentials <- new NetworkCredential("uid", "pass")
ftp.Method <- WebRequestMethods.Ftp.DownloadFile
ftp.Proxy <- null
let response = ftp.GetResponse() :?> FtpWebResponse
Source: http://support.microsoft.com/kb/2134299
The cause of this issue is due to a behavior change in the
System.Net.FtpWebRequest class in .Net Framework 4. There has been a
change made to the System.Net.FtpWebRequest class from .Net Framework
3.5 to .Net Framework 4 to streamline the use of the CWD protocol commands. The new implementation of the System.Net.FtpWebRequest class
prevents the send of extra CWD commands before issuing the actual
command which the user requested and instead directly sends the
requested command. For fully RFC compliant FTP servers, this should
not be an issue, however for non-fully RFC compliant servers, you will
see these types of errors.

Try this instead:
open System
open System.Net
let parm1 = "test"
let parm2 = "othertest"
let uri = String.Format("ftp://x{0}ftp/%2F'{1}'", parm1, parm2)
let ftp = FtpWebRequest.Create(uri) :?> FtpWebRequest;;
I had to add a dummy parm1 and parm2 but I'm assuming you've got parm1 and parm2 defined in your actual code. I'd guess that whatever the issue is, it lies in the uri string. That is, I think you'll find the problem by comparing uri to the known to be good uri string.

Related

How to do an HTTP2 request with H2 using the new async-await syntax in Rust?

The problem I run into is that I tried to convert the H2 Akamai example into code using Rust's new async-await syntax.
I have been able to produce the following code, but it hangs on let response = response.compat().await; without me able to understand why.
#![feature(async_await)]
use tokio::net::TcpStream;
use std::sync::Arc;
use webpki::DNSNameRef;
use futures::compat::Future01CompatExt;
use futures::future::{FutureExt, TryFutureExt};
use h2::client;
use rustls::ClientConfig;
use tokio_rustls::ClientConfigExt;
use rustls::Session;
use std::net::ToSocketAddrs;
use hyper::{Method, Request};
pub fn setup_config() -> Arc<ClientConfig>
{
std::sync::Arc::new({
let mut c = rustls::ClientConfig::new();
c.root_store
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
c.alpn_protocols.push("h2".to_owned());
c
})
}
pub async fn worker()
{
// Set the address to run our socket on.
let address = "http2.akamai.com:443"
.to_socket_addrs()
.unwrap()
.next()
.unwrap();
let config = setup_config();
let dns_name = DNSNameRef::try_from_ascii_str("http2.akamai.com").unwrap();
// Open a TCP connection.
let tcp = TcpStream::connect(&address).compat().await.unwrap();
;
let tls = config.connect_async(dns_name, tcp).compat().await.unwrap();
let (_, session) = tls.get_ref();
let negotiated_protocol = session.get_alpn_protocol();
assert_eq!(Some("h2"), negotiated_protocol.as_ref().map(|x| &**x));
let res = client::handshake(tls).compat().await;
let (client, h2) = res.unwrap();
println!("Test5");
let request = Request::builder()
.method(Method::GET)
.uri("https://http2.akamai.com/")
.body(())
.unwrap();
println!("Test6");
let (response, x) = client.ready().compat().await.unwrap().send_request(request, true).unwrap();
println!("Test7");
let response = response.compat().await;
println!("Test8");
}
fn main()
{
// Call our `run_server` function, which returns a future.
// As with every `async fn`, for `run_server` to do anything,
// the returned future needs to be run. Additionally,
// we need to convert the returned future from a futures 0.3 future into a
// futures 0.1 future.
let futures_03_future = worker();
let futures_01_future = futures_03_future.unit_error().boxed().compat();
// Finally, we can run the future to completion using the `run` function
// provided by Hyper.
tokio::run(futures_01_future);
}
Cargo.toml:
[dependencies]
# The latest version of the "futures" library, which has lots of utilities
# for writing async code. Enable the "compat" feature to include the
# functions for using futures 0.3 and async/await with the Hyper library,
# which use futures 0.1.
futures-preview = { version = "=0.3.0-alpha.16", features = ["compat"] }
# Hyper is an asynchronous HTTP library. We'll use it to power our HTTP
# server and to make HTTP requests.
hyper = "0.12.9"
# Tokio
tokio = "0.1.22"
h2 = "0.1.26"
# RustTLS
rustls = "0.12"
tokio-rustls = "0.5.0"
webpki = "0.18"
webpki-roots = "0.14"
Output:
Test5
Test6
Test7
I hope you're able to help me on why it hangs during this request.
EDIT: I checked Wireshark as well, and the HTTP2 connection has been opened, but the request inside the connection is not being sent. But I still don't understand why.
I forgot to spawn the connection on a new thread as well:
tokio::spawn(h2.map_err(|_| panic!("connection failed")));
For more information see:
https://github.com/hyperium/h2/issues/390
https://github.com/hyperium/h2/issues/391

How to encode protobuf map in python?

I am using protobuf and grpc as interface between a client and server.
The server is written in C and the client uses python to communicate to the server.
I have a message created in protobuf like below.
message value_obj {
uint32 code = 1;
uint32 value = 2;
}
message list_of_maps {
map<uint32, value_obj> mapObj1 = 1;
map<uint32, value_obj> mapObj2 = 2;
}
I tried creating objects in Python like below:
obj = list_of_maps()
mapObjToStore = value_obj()
mapObjToStore.code = 10
obj.mapObj1[1].CopyFrom(mapObjToStore)
When I try to receive the message in server, I get wrong values (huge numbers!).
Any help on this will be greatly appreciated.
You can try using python dictionary for that:
map1 = {}
obj1 = value_obj()
map1[1] = obj1
map2 = {}
listOfMaps = list_of_maps(mapObj1=map1, mapObj2=map2)

How to set default file browse location with firefox addon sdk

Im new Firefox addon programming.
I want set default file browse location with firefox addon sdk.
Thank you so much.
open scratchpad copy and paste this:
const nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["#mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker);
var startDir = FileUtils.File('C:\\');
fp.displayDirectory = startDir;
fp.init(window, "Dialog Title", nsIFilePicker.modeOpen);
fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText);
var rv = fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
var file = fp.file;
// Get the path as string. Note that you usually won't
// need to work with the string paths.
var path = fp.file.path;
// work with returned nsILocalFile...
}
if thats what you want let me know, then ill put it in a default location

How to navigate to a sub directory through a proxy with FTPWebRequest

I am currently trying to log on to a ftp server via an ftp proxy. Using the following snippet
async {
let r = FtpWebRequest.Create("ftp://<ftp-proxy-address>") :?> FtpWebRequest
r.Method <- WebRequestMethods.Ftp.ListDirectoryDetails
r.Timeout <- req.Timeout.TotalMilliseconds |> int
r.Proxy <- null
r.Credentials <- NetworkCredential("user#host/subdirectory","password")
use! response = r.AsyncGetResponse()
use sr = new StreamReader(response.GetResponseStream(), req.Encoding)
let result = handler sr
return result
}
However this always logs me on to the user directory root not into the subdirectory I have specified in the user credentials. Is there a way to get this to work?
Note It seems to work if I do not use a FTP proxy instead specify a HTTP proxy.. I can see the CWD command being issued and I end up in the directory I expected
You have to logon first and then change directory.

CoreMidi with MacRuby

I am trying to use the CoreMidi.framework with MacRuby and I am getting hung up on the correct way to implement the CoreMidi mechanisms in Ruby. I have created the MIDIClient and the OutputPort:
clientName = "Client"
clientRef = Pointer.new(:uint)
MIDIClientCreate( clientName, nil, nil, clientRef )
portName = "Output"
outport = Pointer.new(:uint)
MIDIOutputPortCreate( clientRef[0], portName, outport )
numberOfDestinations = MIDIGetNumberOfDestinations()
destination = MIDIGetDestination( 0 )
After this, I am at a loss for exactly what to do. I need to create a MIDIPacketList to send to MIDISend, but I'm not sure how this would be done in Ruby. The program hangs when I try to create a packet list with:
packetList = MIDIPacketList.new
Any suggestions?

Resources