0

I'm trying to create a script to log into something similar to ftp, but it does not use ftp commands. I'm thinking of trying a batch file or Python solution.

Manually it's done through a cmd shell as follows:

C:\Users..etc>
passiveftp 123.45.67.890 #connects to ftp in passive mode
#then asks for username and you don't see 'C:\Users..etc.' anymore
Connceted to 123.45.67.890
220 (vsFTPd 3.0.2)

User name:
#here you'd enter user name, then password, then start dl/ul'ing

For a standard ftp connection, I found that you can use a separate text file with each input and then just run the following command:

ftp -s:filename.txt

But it looks like this ftp program does not accept that. I tried it with the following text file:

passiveftp 123.45.67.890
usernamehere
passwordhere
hash

This resulted in the following output:

C:\Users\etc.>passiveftp -s:filename.txt
ftp> Invalid command.
ftp> Invalid command.
ftp> Invalid command.
ftp> Hash mark printing On  ftp: (2048 bytes/hash mark).
ftp>

Is there a way to automate this scenario like what can be done with ftp commands?

Eryk Sun
  • 33,190
  • 5
  • 92
  • 111
  • 1
    Have considered running `passiveftp` via Python's `subprocess.Popen` and piping the sequence of commands to stdin, with CRLF line endings? That should work in most cases, unless the program insists on reading input directly from the console. – Eryk Sun Jun 22 '17 at 16:32
  • Have a look at [pexpect](https://pexpect.readthedocs.io/en/stable/). The [API Overview](https://pexpect.readthedocs.io/en/stable/overview.html) shows how to control an FTP session. You should be able to adapt it to your specific needs. –  Jun 22 '17 at 16:46
  • It appears that PASV mode can be used with the Microsoft provided ftp.exe. https://stackoverflow.com/questions/18643542/how-to-use-passive-ftp-mode-in-windows-command-prompt Is there some other reason that you must use a different FTP program? – lit Jun 22 '17 at 16:58
  • @eryksun with something like `subprocess.Popen(["start", "/wait", "cmd", "/c", "passiveftp address"+"\r"+"\n", "username"+"\r"+"\n", "password"+"\r"+"\n"], stdout=subprocess.PIPE, shell=True)` a window appears and `passiveftp address` works, but it's the same as before where the username isn't entered. is that the correct use of CRLF? – baconpancakes Jun 22 '17 at 17:41
  • You don't need the shell, and the input should be written to stdin. for example: `p = subprocess.Popen(["passiveftp", address], stdin=subprocess.PIPE, bufsize=0);` `p.stdin.write(b"username\r\npassword\r\n");`. Eventually you can send it a command to quit, or just kill it with `p.kill()`. – Eryk Sun Jun 22 '17 at 17:49
  • do you know why `p = subprocess.Popen(["passiveftp", address], stdin=subprocess.PIPE, bufsize=0)` opens a window that crashes the program? "FTP command-line tool has stopped working" i've never used bufsize before, is it that? – baconpancakes Jun 22 '17 at 17:58
  • No, `bufsize` is to disable buffering for `p.stdin` in Python. It has nothing to do with the child process. It could be crashing because `stdin` is a pipe. – Eryk Sun Jun 22 '17 at 17:59
  • @eryksun does `p = subprocess.Popen(["passiveftp", address], stdin=subprocess.PIPE, bufsize=0)` do the same thing as opening a command prompt and typing `passiveftp address` in the default directory? it was crashing before because i changed the directory earlier and was in the wrong one. now it is saying `WindowsError: [Error 2] The system cannot find the file specified` when i start a new python idle and try – baconpancakes Jun 22 '17 at 18:04
  • In cmd it's more like running `(echo username & echo password) | passiveftp address`. But there's no cmd shell involved. It runs `passiveftp` directly with its stdin connected to a pipe, and on the other end of the pipe you have `p.stdin` to which you write the byte string `b"username\r\npassword\r\n"`. If you need to set the working directory, use the `cwd` argument of `Popen`, e.g. `cwd=r'C:\Temp'`. – Eryk Sun Jun 22 '17 at 18:09
  • with cwd set to the location of passiveftp.exe or the default directory of my cmd prompt window, i still get the same error.. passiveftp.exe is in `..windows\system32`, is that why it works in cmd? can it be emulated through `Popen`? – baconpancakes Jun 22 '17 at 18:20
  • Have you tried `p = subprocess.Popen(["passiveftp", address])` without `stdin=subprocess.PIPE`, to determine whether the pipe is causing the problem? Don't try to use `p.stdin` in this case since it's not set to a pipe. It should open in a new console and prompt for the username and password. – Eryk Sun Jun 22 '17 at 18:24
  • okay, yes. without `stdin=subprocess.PIPE` a console prompting for user name appears – baconpancakes Jun 22 '17 at 18:33
  • When you run `passiveftp` from cmd, does it run in the same console window? Or does it open a new window that just looks like the Windows console? – Eryk Sun Jun 22 '17 at 18:42
  • @eryksun yes, the same console window. it looks similar to how it works with an ftp connection. the default dir shown when you first open the window goes away and the 'ui (i guess)' changes to the passiveftp 'ui' – baconpancakes Jun 22 '17 at 21:38
  • @DavidCullen is the download for python 2.7 discontinued or canceled? – baconpancakes Jun 22 '17 at 22:06
  • @lit i see complaints about winscp being slow. is there a way to get the average speed of a download or upload via winscp? – baconpancakes Jun 22 '17 at 22:09
  • @baconpancakes: I [install pexpect via pip](https://pexpect.readthedocs.io/en/stable/install.html). Please note that [pexpect.popen_spawn.PopenSpawn](https://pexpect.readthedocs.io/en/stable/overview.html#windows) must be used on Windows. –  Jun 23 '17 at 13:13
  • @DavidCullen it looks like `pexpect.popen_spawn.PopenSpawn` does not have an `interact()` method, so i'm trying to make a basic one.. i tried this, but the console crashes after the `raw_input()` line: `.. s.sendline('hash') s.expect('.*Hash mark printing.*') interact = 1 while interact == 1: human = raw_input() #crashes here if human == '`': interact = 0 break else: s.sendline(human) s.wait() s.expect('ftp> ')` – baconpancakes Jun 26 '17 at 14:35
  • @baconpancakes: So you want to interact with the FTP session after you connect? –  Jun 26 '17 at 17:01
  • @DavidCullen yes, that's right. – baconpancakes Jun 26 '17 at 17:16
  • or at least be able to get something like subprocess.check_output() to return the result of downloading/uploading a file.. – baconpancakes Jun 26 '17 at 17:26
  • @baconpancakes: Where did you get `passiveftp`? –  Jun 26 '17 at 19:31
  • @DavidCullen it's from a colleague, so i can't see how it works.. i thought it would be simpler to work with it, but maybe it might better to start from scratch and learn more about passive mode.. – baconpancakes Jun 26 '17 at 20:06
  • You should probably have a look at this question: https://stackoverflow.com/q/18643542/3657941 –  Jun 26 '17 at 21:08
  • @DavidCullen it looks like the same thread from earlier by lit. the problem with 3rd party programs is that there's a concern when working with confidential devices that connect to the server. for example speedtest.net can't be used because it pulls information about connected devices. – baconpancakes Jun 27 '17 at 17:32
  • Have a look at the Python [ftplib](https://docs.python.org/2/library/ftplib.html). It has support for [PASV](https://docs.python.org/2/library/ftplib.html#ftplib.FTP.set_pasv). –  Jun 27 '17 at 20:05

0 Answers0