Skip to content

Commit

Permalink
Multiple fixes
Browse files Browse the repository at this point in the history
* first-time load of saved sessions & saved from putty windows registry
* handle network disconnection
* message box for closing live session
* ignore 'open' action in settings window if no session is selected or
no hostname
* message box for unsupported configs in saved session
* support remote_cmd ssh option in settings window
* terminal not scrolling for mouse wheel scroll
* better handling of character-set/textcodec
  • Loading branch information
unknown authored and unknown committed May 16, 2013
1 parent 12d99a8 commit dc451e6
Show file tree
Hide file tree
Showing 21 changed files with 2,309 additions and 35 deletions.
25 changes: 25 additions & 0 deletions GuiMainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <QKeyEvent>
#include <QToolButton>
#include <QTabWidget>
#include <QMessageBox>
#include "GuiMainWindow.h"
#include "GuiTerminalWindow.h"
#include "GuiSettingsWindow.h"
Expand Down Expand Up @@ -73,16 +74,40 @@ void GuiMainWindow::closeTerminal(int index)
{
GuiTerminalWindow *termWnd = (GuiTerminalWindow*)tabArea->widget(index);
if (termWnd) {
if (termWnd->cfg.warn_on_close &&
termWnd->as->qtsock->state() == QAbstractSocket::ConnectedState &&
QMessageBox::No == QMessageBox::question(this, "Exit Confirmation?",
"Are you sure you want to close this session?",
QMessageBox::Yes|QMessageBox::No))
return;
terminalList.removeAll(termWnd);
}
tabArea->removeTab(index);
}

void GuiMainWindow::closeTerminal(GuiTerminalWindow *termWnd)
{
if (termWnd->cfg.warn_on_close &&
termWnd->as->qtsock->state() == QAbstractSocket::ConnectedState &&
QMessageBox::No == QMessageBox::question(this, "Exit Confirmation?",
"Are you sure you want to close this session?",
QMessageBox::Yes|QMessageBox::No))
return;
tabArea->removeTab(tabArea->indexOf(termWnd));
terminalList.removeAll(termWnd);
}

void GuiMainWindow::closeEvent ( QCloseEvent * event )
{
event->ignore();
if (QMessageBox::Yes == QMessageBox::question(this, "Exit Confirmation?",
"Are you sure you want to close all the sessions?",
QMessageBox::Yes|QMessageBox::No))
{
event->accept();
}
}

void GuiMainWindow::openSettingsWindow()
{
GuiSettingsWindow *ss = new GuiSettingsWindow(mainWindow);
Expand Down
1 change: 1 addition & 0 deletions GuiMainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class GuiMainWindow : public QMainWindow
~GuiMainWindow();
GuiTerminalWindow *newTerminal();
bool winEvent ( MSG * msg, long * result );
void closeEvent ( QCloseEvent * event );

QTabWidget *tabArea;
private:
Expand Down
57 changes: 47 additions & 10 deletions GuiSettingsWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <QAbstractButton>
#include<QRadioButton>
#include<QString>
#include <QMessageBox>
#include "QtCommon.h"
#include "QtConfig.h"
extern "C" {
Expand Down Expand Up @@ -66,7 +67,7 @@ GuiSettingsWindow::GuiSettingsWindow(QWidget *parent) :

ui->gp_logfile->setId(ui->rb_sessionlog_overwrite, LGXF_OVR);
ui->gp_logfile->setId(ui->rb_sessionlog_append, LGXF_APN);
ui->gp_logfile->setId(ui->rb_sessionlog_askuser, LGXF_ASK);
ui->gp_logfile->setId(ui->rb_sessionlog_askuser, LGXF_ASK__);

ui->gp_termopt_echo->setId(ui->rb_termopt_echoauto, AUTO);
ui->gp_termopt_echo->setId(ui->rb_termopt_echoon, FORCE_ON);
Expand Down Expand Up @@ -121,18 +122,28 @@ void GuiSettingsWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, int col
ui->stackedWidget->setCurrentIndex(item->data(column, Qt::UserRole).toInt());
}

void qstring_to_char(char *dst, QString src, int dstlen)
{
QByteArray name = src.toUtf8();
strncpy(dst, name.constData(), dstlen);
}

void GuiSettingsWindow::on_buttonBox_accepted()
{
int rc;
GuiTerminalWindow *newWnd = mainWindow->newTerminal();
GuiTerminalWindow *newWnd;

if (ui->le_hostname->text() == "" &&
ui->l_saved_sess->currentItem()->text() == QUTTY_DEFAULT_CONFIG_SETTINGS) {
return;
} else if (ui->le_hostname->text() == "") {
char config_name[100];
qstring_to_char(config_name, ui->l_saved_sess->currentItem()->text(), sizeof(config_name));
if (qutty_config.config_list.find(config_name) == qutty_config.config_list.end())
return;
setConfig(&qutty_config.config_list[config_name]);
}

newWnd = mainWindow->newTerminal();
newWnd->cfg = *this->getConfig();

// check for NOT_YET_SUPPORTED configs
chkUnsupportedConfigs(newWnd->cfg);

if ((rc=newWnd->initTerminal())) {
delete newWnd;
} else { // success
Expand All @@ -154,8 +165,8 @@ void GuiSettingsWindow::setConfig(Config *_cfg)

// update the ui with the given settings
ui->le_hostname->setText(cfg.host);
ui->le_port->setText(QString::number(cfg.port));
(cfg.protocol==PROT_SSH ? ui->rb_contype_ssh : ui->rb_contype_telnet)->click();
ui->le_port->setText(QString::number(cfg.port));
ui->le_saved_sess->setText(cfg.config_name);
QList<QListWidgetItem*> sel_saved_sess = ui->l_saved_sess->findItems(cfg.config_name, Qt::MatchExactly);
if (sel_saved_sess.size() > 0)
Expand All @@ -164,7 +175,10 @@ void GuiSettingsWindow::setConfig(Config *_cfg)
/* Options controlling session logging */
ui->gp_seslog->button(cfg.logtype)->click();
ui->le_sessionlog_filename->setText(cfg.logfilename.path);
ui->gp_logfile->button(cfg.logxfovr)->click();
if (cfg.logxfovr == LGXF_ASK) // handle -ve value
ui->gp_logfile->button(LGXF_ASK__)->click();
else
ui->gp_logfile->button(cfg.logxfovr)->click();
ui->chb_sessionlog_flush->setChecked(cfg.logflush);
ui->chb_sessionlog_omitpasswd->setChecked(cfg.logomitpass);
ui->chb_sessionlog_omitdata->setChecked(cfg.logomitdata);
Expand Down Expand Up @@ -232,6 +246,9 @@ void GuiSettingsWindow::setConfig(Config *_cfg)
ui->le_termtype->setText(cfg.termtype);
ui->le_termspeed->setText(cfg.termspeed);

/* ssh options */
ui->le_remote_cmd->setText(cfg.remote_cmd);

/* ssh auth options */
ui->chb_ssh_no_userauth->setChecked(cfg.ssh_no_userauth);
ui->chb_ssh_show_banner->setChecked(cfg.ssh_show_banner);
Expand Down Expand Up @@ -322,6 +339,9 @@ Config *GuiSettingsWindow::getConfig()
qstring_to_char(cfg->termtype, ui->le_termtype->text(), sizeof(cfg->termtype));
qstring_to_char(cfg->termspeed, ui->le_termspeed->text(), sizeof(cfg->termspeed));

/* ssh options */
qstring_to_char(cfg->remote_cmd, ui->le_remote_cmd->text(), sizeof(cfg->remote_cmd));

/* ssh auth options */
cfg->ssh_no_userauth = ui->chb_ssh_no_userauth->isChecked();
cfg->ssh_show_banner = ui->chb_ssh_show_banner->isChecked();
Expand Down Expand Up @@ -402,3 +422,20 @@ void GuiSettingsWindow::on_btn_ssh_auth_browse_keyfile_clicked()
this, tr("Select private key file"),
ui->le_ssh_auth_keyfile->text(), tr("*.ppk")));
}

void GuiSettingsWindow::chkUnsupportedConfigs(Config &cfg)
{
QString opt_unsupp = "";

if (cfg.try_gssapi_auth) {
cfg.try_gssapi_auth = 0;
}
if (cfg.portfwd[0] != '\0') {
cfg.portfwd[0] = '\0';
opt_unsupp += " * SSH Tunnels/port forwarding\n";
}
if (opt_unsupp.length() > 0)
QMessageBox::warning(NULL, QObject::tr("Qutty Configuration"),
QObject::tr("Following options are not yet supported in QuTTY.\n\n%1")
.arg(opt_unsupp));
}
2 changes: 2 additions & 0 deletions GuiSettingsWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ private slots:

void on_btn_ssh_auth_browse_keyfile_clicked();

void chkUnsupportedConfigs(Config &cfg);

private:
Ui::GuiSettingsWindow *ui;
};
Expand Down
2 changes: 1 addition & 1 deletion GuiSettingsWindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -4146,7 +4146,7 @@
<string>Remote command:</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit_33">
<widget class="QLineEdit" name="le_remote_cmd">
<property name="geometry">
<rect>
<x>10</x>
Expand Down
47 changes: 37 additions & 10 deletions GuiTerminalWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ GuiTerminalWindow::GuiTerminalWindow(QWidget *parent) :

connect(verticalScrollBar(), SIGNAL(actionTriggered(int)), this, SLOT(vertScrollBarAction(int)));
connect(verticalScrollBar(), SIGNAL(sliderMoved(int)), this, SLOT(vertScrollBarMoved(int)));
connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(vertScrollBarMoved(int)));

QPalette pal(palette());
// set black background // not working as expected
Expand Down Expand Up @@ -70,22 +71,13 @@ int GuiTerminalWindow::initTerminal()
{
char *realhost = NULL;
char *ip_addr = cfg.host;
void *logctx;

memset(&ucsdata, 0, sizeof(struct unicode_data));
init_ucs(&cfg, &ucsdata);
setTermFont(&cfg.font);
cfgtopalette(&cfg);

term = term_init(&cfg, &ucsdata, this);
term_size(term, cfg.height, cfg.width, cfg.savelines);
resize(cfg.width*fontWidth, cfg.height*fontHeight);
// resize according to config if window is smaller
if ( !(mainWindow->windowState() & Qt::WindowMaximized) &&
( mainWindow->size().width() < cfg.width*fontWidth ||
mainWindow->size().height() < cfg.height*fontHeight))
mainWindow->resize(cfg.width*fontWidth,
cfg.height*fontHeight);

backend = backend_from_proto(cfg.protocol);
const char * error = backend->init(this, &backhandle, &cfg, (char*)ip_addr, cfg.port, &realhost, 1, 0);
if (realhost)
Expand All @@ -99,6 +91,18 @@ int GuiTerminalWindow::initTerminal()
goto cu0;
}

term = term_init(&cfg, &ucsdata, this);
logctx = log_init(NULL, &cfg);
term_provide_logctx(term, logctx);
term_size(term, cfg.height, cfg.width, cfg.savelines);
resize(cfg.width*fontWidth, cfg.height*fontHeight);
// resize according to config if window is smaller
if ( !(mainWindow->windowState() & Qt::WindowMaximized) &&
( mainWindow->size().width() < cfg.width*fontWidth ||
mainWindow->size().height() < cfg.height*fontHeight))
mainWindow->resize(cfg.width*fontWidth,
cfg.height*fontHeight);

switch(cfg.protocol) {
case PROT_TELNET:
as = (Actual_Socket)get_telnet_socket(backhandle);
Expand All @@ -111,6 +115,10 @@ int GuiTerminalWindow::initTerminal()
}
qtsock = as->qtsock;
QObject::connect(as->qtsock, SIGNAL(readyRead()), this, SLOT(readyRead()));
QObject::connect(as->qtsock, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(sockError()));
QObject::connect(as->qtsock, SIGNAL(disconnected()),
this, SLOT(sockDisconnected()));

/*
* Connect the terminal to the backend for resize purposes.
Expand Down Expand Up @@ -139,6 +147,8 @@ TmuxWindowPane *GuiTerminalWindow::initTmuxClientTerminal(TmuxGateway *gateway,
cfgtopalette(&cfg);

term = term_init(&cfg, &ucsdata, this);
void *logctx = log_init(NULL, &cfg);
term_provide_logctx(term, logctx);
// resize according to config if window is smaller
if ( !(mainWindow->windowState() & Qt::WindowMaximized) &&
( mainWindow->size().width() < cfg.width*fontWidth ||
Expand Down Expand Up @@ -688,3 +698,20 @@ void GuiTerminalWindow::detachTmuxControllerMode()
_tmuxGateway = NULL;
_tmuxMode = TMUX_MODE_NONE;
}

void GuiTerminalWindow::sockError (QAbstractSocket::SocketError socketError)
{
char errStr[256];
qstring_to_char(errStr, as->qtsock->errorString(), sizeof(errStr));
(*as->plug)->closing(as->plug, errStr, socketError, 0);
}

void GuiTerminalWindow::sockDisconnected()
{
char errStr[256], winTitle[256];
qstring_to_char(errStr, as->qtsock->errorString(), sizeof(errStr));
(*as->plug)->closing(as->plug, errStr, as->qtsock->error(), 0);
qstring_to_char(winTitle, this->windowTitle(), sizeof(winTitle));
strncat(winTitle, " (inactive)", sizeof(winTitle));
set_title(this, winTitle);
}
2 changes: 2 additions & 0 deletions GuiTerminalWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ public slots:
void vertScrollBarAction(int action);
void vertScrollBarMoved(int value);
void detachTmuxControllerMode();
void sockError(QAbstractSocket::SocketError socketError);
void sockDisconnected();

};

Expand Down
6 changes: 6 additions & 0 deletions QtCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,3 +437,9 @@ int tmux_from_backend(void *frontend, int is_stderr, const char *data, int len)
GuiTerminalWindow *f = static_cast<GuiTerminalWindow*>(frontend);
return f->tmuxGateway()->fromBackend(is_stderr, data, len);
}

void qstring_to_char(char *dst, QString src, int dstlen)
{
QByteArray name = src.toUtf8();
strncpy(dst, name.constData(), dstlen);
}
2 changes: 2 additions & 0 deletions QtCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,6 @@ typedef struct telnet_tag {
Pinger pinger;
} *Telnet;

void qstring_to_char(char *dst, QString src, int dstlen);

#endif // QTCOMMON_H
63 changes: 63 additions & 0 deletions QtConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include <QObject>
#include <QMessageBox>
#include <QDebug>
extern "C" {
#include "WINDOWS\STORAGE.H"
}

QtConfig::QtConfig()
{
Expand Down Expand Up @@ -181,6 +184,11 @@ bool QtConfig::restoreConfig()
{
config_list.clear();
QFile file(QDir::home().filePath("qutty.xml"));

if (!file.exists()) {
restoreFromPuttyWinRegistry();
}

if (!file.exists()) {
Config cfg;
initConfigDefaults(&cfg);
Expand All @@ -199,6 +207,61 @@ bool QtConfig::restoreConfig()
return true;
}

/*
* Windows only: Try loading the sessions stored in registry by PUTTY
*/
bool QtConfig::restoreFromPuttyWinRegistry()
{
bool rc = true;
struct sesslist savedSess;
void *sesskey;
Config cfg;

get_sesslist(&savedSess, TRUE);
qDebug() << "putty nsessions " << savedSess.nsessions;
for (int i=0; i<savedSess.nsessions; i++) {
memset(&cfg, 0, sizeof(cfg));

sesskey = open_settings_r(savedSess.sessions[i]);
load_open_settings(sesskey, &cfg);
close_settings_r(sesskey);

strncpy(cfg.config_name, savedSess.sessions[i], sizeof(cfg.config_name));
this->config_list[cfg.config_name] = cfg;

qDebug() << "putty session " << i << " name " << savedSess.sessions[i]
<< " host " << cfg.host << " port " << cfg.port;
}

// load ssh hostkey list from registry
void *handle = enum_sshhostkey_start();
uchar hostkey[512], hostkey_val[2048];
if (handle) {
while (enum_sshhostkey_next(handle, hostkey, sizeof(hostkey),
hostkey_val, sizeof(hostkey_val))) {
qutty_config.ssh_host_keys[string((char*)hostkey)] = string((char*)hostkey_val);
}
enum_sshhostkey_finish(handle);
}

if (savedSess.nsessions > 0) {
rc = this->saveConfig();
if (rc) {
QMessageBox::information(NULL, QObject::tr("Qutty first-time Configuration"),
QObject::tr("Automatically loaded %1 saved sessions from PuTTY")
.arg(savedSess.nsessions-1));
} else {
QMessageBox::warning(NULL, QObject::tr("Qutty first-time Configuration"),
QObject::tr("Failed to save %1 saved sessions from PuTTY")
.arg(savedSess.nsessions-1));
}
}

get_sesslist(&savedSess, FALSE); /* free */

return rc;
}

bool QtConfig::saveConfig()
{
QFile file(QDir::home().filePath("qutty.xml"));
Expand Down
Loading

0 comments on commit dc451e6

Please sign in to comment.