Is there a way to pass username and password for the ftp currently open in the lister context?

Hello,
I wanted to create a FTP Context menu entry thats says "Open Cmder here" and automatically sshs to the server that is currently open in the lister with the username and password saved in DOpus and cd's to the open directory.
Is there a way to access the ftp information (username and password) saved there and pass it to an external program (like the Windows terminal that executes the ssh command?).
I found that I can get the host adress from the sourcepath with a bit of regex, but the same is not true for username and password... So how do I go about this?

I don't think there is a way to do this, at least that would be guaranteed to work. We try to prevent things from being able to get the password for the current connection in general.

(We can't completely prevent it, since it has to be in memory somewhere while the connection is active, and if it's saved in the address book -- which is optional -- then it'll be on disk in some form. But we try not to make it easy.)

1 Like

In the meantime I actually found a way to do it for my specific case, but I don't think it works in any way generally, just for my specific type of server and connection I can do this:

function OnClick(clickData) {
	var path = clickData.func.sourcetab.path
	var regex = "^ftp:\/\/(?:SITE=.*\\?)?(.+):(.*)@(.*)\/\/([a-zA-Z1-9]+(?:\/{1}[a-zA-z1-9]+)*)?$"
	var re = new RegExp(regex)
	var array = re.exec(path)

	var username = array[1]
	var password = array[2]
	var host = array[3]
	var path = "/" + array[4]

	var objShell = new ActiveXObject("WScript.Shell");
	objShell.Exec('wt -w 0 nt ssh -t ' + username + '@' + host + ' "cd "' + path + '" && bash --login"');
}

That's something we noticed while looking into this, and it won't work in the next update. It isn't meant to be possible for a script to get the password.

2 Likes

Oh... Well, that's sad. Kinda regret asking now--Is there a chance you will make it configurable and warn the user beforehand that they are doing this at their own risk?
Edit: Username, host and path would actually suffice for what I am doing here... The password gets no usage in the script.

I think most users would expect those details not to be so easily available (even if something that really wanted them cannot really be stopped from getting them, if it has access to install scripts on the machine or has tricked someone into installing malicious scripts). A config setting wouldn't really make sense as it'd be trivial to flip it via code.

The SITE=xyz part will remain after the update. That identifies the FTP Address Book entry. The information about each site entry is in /dopusdata/ConfigFiles/ftp.oxc, but you'd need to parse the XML to get to the username. Giving scripts objects/APIs to query FTP Address Book entries is possible, although would probably be a low priority unless more people express a need for it.

(The actual paths will look like this: ftp://SITE=Phone?:OPUS:ADDRESS:BOOK:LOOKUP://Leo where Phone is the site name in this example, :OPUS:ADDRESS:BOOK:LOOKUP: is a literal string that indicates the username, password and port details are not included in the path string and should be looked up via the address book entry, and /Leo is part of the path below the site.)

(Edit: Note that the site name can contain backslashes, since the address book is a tree and not a flat list. Site names are also URL encoded, e.g. turning spaces into %20. Example of both: ftp://SITE=Public\Demon%20NL?:OPUS:ADDRESS:BOOK:LOOKUP://pub/debian)

I tried to incoroporate the changes into the script. It feels really ugly, but I think this should work, but obviously I can't really test it before the update...

function OnClick(clickData) {
    var path = clickData.func.sourcetab.path
	
    
    if (String(path).indexOf(":OPUS:ADDRESS:BOOK:LOOKUP:") !== -1) {
        var regex = "^ftp:\/\/SITE=(.*?)\?.*\/(\/.*)$"
        var re = new RegExp(regex)
        var reres = re.exec(path)

        if (reres != null) {
            var entry = LookupFTPAdress(reres[1])
            var username = entry["user"]
            var host = entry["host"]
            var path = reres[2]
            OpenShell(username, host, path)
        } else {
            DOpus.output("Failed.")
        }
    } else {
        var path = clickData.func.sourcetab.path
        var regex = "^ftp:\/\/(?:SITE=.*\\?)?(.+):(?:.*)@(.*)\/\/([a-zA-Z1-9]+(?:\/{1}[a-zA-z1-9]+)*)?$"
        var re = new RegExp(regex)
        var reres = re.exec(path)

        if (reres != null) {
            var username = reres[1]
            var host = reres[2]
            var path = "/" + reres[3]
            OpenShell(username, host, path)
        } else {
            DOpus.output("Failed.")
        }
    }
}

function OpenShell(username, host, path) {
    var objShell = new ActiveXObject("WScript.Shell");
    objShell.Exec('wt -w 0 nt ssh -t ' + username + '@' + host + ' "cd "' + path + '" && bash --login"')
}

function LookupFTPAdress(sitename) {
    var ftpConfig = DOpus.FSUtil.Resolve("/dopusdata/ConfigFiles/ftp.oxc")
	ftpConfig = String(ftpConfig).replace(/\\/g, '/')

	var doc = new ActiveXObject("msxml2.DOMDocument.6.0")
	doc.async = false
	doc.resolveExternals = false
	doc.validateOnParse = false
	doc.load(ftpConfig)
	
	var ftpsites = doc.getElementsByTagName("ftpsites")[0]
	var sites = ftpsites.childNodes

	for (var i = 0; i < sites.length; i++) {
		var site = sites[i]
		var name = site.getAttribute("name")

		if (sitename == name) {
            var hostNode = site.getElementsByTagName("host")[0]
            var host = hostNode.getAttribute("host")
            var user = hostNode.getAttribute("user")

            return {
                "user": user,
                "host": host
            }
		}
	}
}
1 Like