Qt, implementing an SFTP client
-
@jsulm, thank you. As the development laptop is i386, how can I install the arm version of libssh so I can build it on the laptop then deploy to the target device?
@splatten You have an SDK for your device, right? Maybe it provides the possibility to install additional packages?
If not you can build these libs for your device using the SDK. -
@jsulm, I build on the laptop then deploy to the target, is the source available for libssh or libssh2 ?
Lifetime Qt Championwrote on 1 Aug 2019, 08:48 last edited by jsulm 8 Jan 2019, 09:04@splatten said in Qt, implementing an SFTP client:
is the source available for libssh or libssh2
yes, OpenSSH is open source
-
wrote on 1 Aug 2019, 09:43 last edited by
Slightly different approach....using QProcess
I plan to launch sftp and pass it the information for user name, address and port. Is there a way to grab the output from the console so I can look for the text "Password:" ?
-
Slightly different approach....using QProcess
I plan to launch sftp and pass it the information for user name, address and port. Is there a way to grab the output from the console so I can look for the text "Password:" ?
wrote on 1 Aug 2019, 10:58 last edited by JonB 8 Jan 2019, 10:59@splatten
You are (presumably) using some third-partysftp.exe
client? This is what I had to do in another (non-Qt) product. You should not have to parse output for things like host, port, username & password prompting. Look at the documentation for thesftp.exe
you intend to use, there should/is likely to be command-line, or possibly take-from-file, for these? -
wrote on 1 Aug 2019, 11:18 last edited by JonB 8 Jan 2019, 11:20
@splatten
OK, well I don't know about that! What aboutman sftp
(host, port, user at least on command line)? On, say, Ubuntu I see:The final usage format allows for automated sessions using the -b option. In such cases, it is necessary to configure non-interactive authentica‐ tion to obviate the need to enter a password at connection time (see sshd(8) and ssh-keygen(1) for details).
Anyway, you use
QProcess
methods like https://doc.qt.io/qt-5/qprocess.html#readAllStandardOutput or (better) https://doc.qt.io/qt-5/qprocess.html#readyReadStandardOutput signal to read from/write to the subprocess. You'll want to deal with all of stdin, stdout, & stderr, plus error signals, for proper control of your sub-process. -
wrote on 1 Aug 2019, 11:39 last edited by SPlatten 8 Jan 2019, 11:50
Here is my sample code:
QProcess* pProc = new QProcess(this); QString strHost = clsMainWnd::strGetHostName() ,strPort = clsMainWnd::strGetPort() ,strUsername = clsMainWnd::strGetUsername(); QStringList slstCmdArgs; slstCmdArgs << (strUsername + QString("@") + strHost) << (QString("-P") + strPort); pProc->start("sftp", slstCmdArgs); while( pProc->waitForStarted() != true ) { } QByteArray bytaryIn = pProc->readAllStandardOutput(); qDebug() << bytaryIn;
I've grabbed the content of slstCmdArgs and tried it in a terminal and it works, but in code I never see anything in "bytaryIn".
An example of what the code above does:
sftp User@HostName -P22
What I am expecting to see is:
User@HostName's password:
[Edit] I've now re-written this code to:
QString strHost = clsMainWnd::strGetHostName() ,strPort = clsMainWnd::strGetPort() ,strUsername = clsMainWnd::strGetUsername(); QStringList slstCmdArgs; slstCmdArgs << (strUsername + QString("@") + strHost) << (QString("-P") + strPort); mpSFTP = new QProcess(this); connect(mpSFTP, SIGNAL(readyReadStandardOutput()) ,this, SLOT(readSFTPoutput())); mpSFTP->start("sftp", slstCmdArgs);
-
Here is my sample code:
QProcess* pProc = new QProcess(this); QString strHost = clsMainWnd::strGetHostName() ,strPort = clsMainWnd::strGetPort() ,strUsername = clsMainWnd::strGetUsername(); QStringList slstCmdArgs; slstCmdArgs << (strUsername + QString("@") + strHost) << (QString("-P") + strPort); pProc->start("sftp", slstCmdArgs); while( pProc->waitForStarted() != true ) { } QByteArray bytaryIn = pProc->readAllStandardOutput(); qDebug() << bytaryIn;
I've grabbed the content of slstCmdArgs and tried it in a terminal and it works, but in code I never see anything in "bytaryIn".
An example of what the code above does:
sftp User@HostName -P22
What I am expecting to see is:
User@HostName's password:
[Edit] I've now re-written this code to:
QString strHost = clsMainWnd::strGetHostName() ,strPort = clsMainWnd::strGetPort() ,strUsername = clsMainWnd::strGetUsername(); QStringList slstCmdArgs; slstCmdArgs << (strUsername + QString("@") + strHost) << (QString("-P") + strPort); mpSFTP = new QProcess(this); connect(mpSFTP, SIGNAL(readyReadStandardOutput()) ,this, SLOT(readSFTPoutput())); mpSFTP->start("sftp", slstCmdArgs);
@splatten said in Qt, implementing an SFTP client:
QByteArray bytaryIn = pProc->readAllStandardOutput();
Don't do it like this - you don't know whether there is already anything to read. Use https://doc.qt.io/qt-5/qprocess.html#readyReadStandardOutput signal instead.
-
Here is my sample code:
QProcess* pProc = new QProcess(this); QString strHost = clsMainWnd::strGetHostName() ,strPort = clsMainWnd::strGetPort() ,strUsername = clsMainWnd::strGetUsername(); QStringList slstCmdArgs; slstCmdArgs << (strUsername + QString("@") + strHost) << (QString("-P") + strPort); pProc->start("sftp", slstCmdArgs); while( pProc->waitForStarted() != true ) { } QByteArray bytaryIn = pProc->readAllStandardOutput(); qDebug() << bytaryIn;
I've grabbed the content of slstCmdArgs and tried it in a terminal and it works, but in code I never see anything in "bytaryIn".
An example of what the code above does:
sftp User@HostName -P22
What I am expecting to see is:
User@HostName's password:
[Edit] I've now re-written this code to:
QString strHost = clsMainWnd::strGetHostName() ,strPort = clsMainWnd::strGetPort() ,strUsername = clsMainWnd::strGetUsername(); QStringList slstCmdArgs; slstCmdArgs << (strUsername + QString("@") + strHost) << (QString("-P") + strPort); mpSFTP = new QProcess(this); connect(mpSFTP, SIGNAL(readyReadStandardOutput()) ,this, SLOT(readSFTPoutput())); mpSFTP->start("sftp", slstCmdArgs);
wrote on 1 Aug 2019, 11:57 last edited by JonB 8 Jan 2019, 11:58@splatten
Which is why I said to use https://doc.qt.io/qt-5/qprocess.html#readyReadStandardOutput for better/proper behaviour....There is a wrinkle you may have to face. It is possible that your command-line
sftp
executable will not prompt for password if it detects that the user is not in an interactive terminal (stdin). E.g. its code may quite possibly haveif (isatty(0)) prompt_for_password(); else // do not prompt for password
That will be problematic if it is the case. You could try in a terminal
sftp < /dev/null
orsftp < file
: if that does not still prompt for password you have a (potential) problem.... -
wrote on 1 Aug 2019, 12:05 last edited by JonB 8 Jan 2019, 12:05
@splatten
Help what, in what way? If thesftp
requires a terminal stdin for password prompt, then no, if, say, you have a purely interactive Qt application. You can try it. But the first thing to test is whether yoursftp
behaves differently if its stdin is not attached to a terminal? -
wrote on 1 Aug 2019, 12:09 last edited by
Now the slot gets called and in my slot I have:
qDebug() << "readAllStandardOutput:"; qDebug() << mpSFTP->readAllStandardOutput(); qDebug() << "readChannel:"; qDebug() << mpSFTP->readChannel();
In the output I see:
readAllStandardOutput: "ssh_askpass: exec(/usr/local/libexec/ssh-askpass): No such file or directory " readChannel: 0
-
Now the slot gets called and in my slot I have:
qDebug() << "readAllStandardOutput:"; qDebug() << mpSFTP->readAllStandardOutput(); qDebug() << "readChannel:"; qDebug() << mpSFTP->readChannel();
In the output I see:
readAllStandardOutput: "ssh_askpass: exec(/usr/local/libexec/ssh-askpass): No such file or directory " readChannel: 0
Lifetime Qt Championwrote on 1 Aug 2019, 12:15 last edited by jsulm 8 Jan 2019, 12:15@splatten What happens if you execute exact same command manually in a terminal?
Also connect a slot to the error signal from QProcess and check whether you get any errors. -
Now the slot gets called and in my slot I have:
qDebug() << "readAllStandardOutput:"; qDebug() << mpSFTP->readAllStandardOutput(); qDebug() << "readChannel:"; qDebug() << mpSFTP->readChannel();
In the output I see:
readAllStandardOutput: "ssh_askpass: exec(/usr/local/libexec/ssh-askpass): No such file or directory " readChannel: 0
wrote on 1 Aug 2019, 13:36 last edited by JonB 8 Jan 2019, 13:37@splatten
As I have said before, so last time now:ssh_askpass: exec(/usr/local/libexec/ssh-askpass): No such file or directory
This is because your sftp is not willing/able to access stdin to get a password. Try what I said about seeing how your
sftp
behaves with input/output redirected when run from a terminal. I will not comment again, and leave it to you. -
wrote on 1 Aug 2019, 13:39 last edited by
ssh_askpass is not available on this linux distribution.
12/25