/usr/local/CPAN/Qt/SslClient.pm
package SslClient;
use strict;
use warnings;
use QtCore4;
use QtGui4;
use QtNetwork4;
use QtCore4::isa qw( Qt::Widget );
use QtCore4::slots
updateEnabledState => [],
secureConnect => [],
socketStateChanged => ['QAbstractSocket::SocketState'],
socketEncrypted => [],
socketReadyRead => [],
sendData => [],
sslErrors => ['const QList<QSslError> &'],
displayCertificateInfo => [];
use CertificateInfo;
use Ui_Form;
use Ui_SslErrors;
sub socket() {
return this->{socket};
}
sub padLock() {
return this->{padLock};
}
sub form() {
return this->{form};
}
sub executingDialog() {
return this->{executingDialog};
}
sub NEW
{
my ($class, $parent) = @_;
$class->SUPER::NEW($parent);
this->{executingDialog} = 0;
this->{form} = Ui_Form->setupUi(this);
form->hostNameEdit->setSelection(0, length form->hostNameEdit->text());
form->sessionOutput->setHtml(this->tr('<not connected>'));
this->connect(form->hostNameEdit, SIGNAL 'textChanged(QString)',
this, SLOT 'updateEnabledState()');
this->connect(form->connectButton, SIGNAL 'clicked()',
this, SLOT 'secureConnect()');
this->connect(form->sendButton, SIGNAL 'clicked()',
this, SLOT 'sendData()');
}
sub updateEnabledState
{
my $unconnected = !defined this->socket() || this->socket()->state() == Qt::AbstractSocket::UnconnectedState();
form->hostNameEdit->setReadOnly(!$unconnected);
form->hostNameEdit->setFocusPolicy($unconnected ? Qt::StrongFocus() : Qt::NoFocus());
form->hostNameLabel->setEnabled($unconnected);
form->portBox->setEnabled($unconnected);
form->portLabel->setEnabled($unconnected);
form->connectButton->setEnabled($unconnected && form->hostNameEdit->text());
my $connected = defined this->socket() && this->socket->state() == Qt::AbstractSocket::ConnectedState();
form->sessionBox->setEnabled($connected);
form->sessionOutput->setEnabled($connected);
form->sessionInput->setEnabled($connected);
form->sessionInputLabel->setEnabled($connected);
form->sendButton->setEnabled($connected);
}
sub secureConnect
{
if (!defined this->socket()) {
this->{socket} = Qt::SslSocket(this);
this->connect(this->socket, SIGNAL 'stateChanged(QAbstractSocket::SocketState)',
this, SLOT 'socketStateChanged(QAbstractSocket::SocketState)');
this->connect(this->socket, SIGNAL 'encrypted()',
this, SLOT 'socketEncrypted()');
this->connect(this->socket, SIGNAL 'sslErrors(QList<QSslError>)',
this, SLOT 'sslErrors(QList<QSslError>)');
this->connect(this->socket, SIGNAL 'readyRead()',
this, SLOT 'socketReadyRead()');
}
this->socket()->connectToHostEncrypted(form->hostNameEdit->text(), form->portBox->value());
updateEnabledState();
}
sub socketStateChanged
{
my ($state) = @_;
if (executingDialog) {
return;
}
updateEnabledState();
if ($state == Qt::AbstractSocket::UnconnectedState()) {
form->hostNameEdit->setPalette(Qt::Palette());
form->hostNameEdit->setFocus();
form->cipherLabel->setText(this->tr('<none>'));
if (defined padLock()) {
padLock->hide();
}
this->socket->deleteLater();
this->{socket} = undef;
}
}
sub socketEncrypted
{
if (!defined this->socket) {
return; # might have disconnected already
}
form->sessionOutput->clear();
form->sessionInput->setFocus();
my $palette = Qt::Palette();
$palette->setColor(Qt::Palette::Base(), Qt::Color(255, 255, 192));
form->hostNameEdit->setPalette($palette);
my $ciph = this->socket->sessionCipher();
my $cipher = sprintf '%s, %s (%s/%s)', $ciph->authenticationMethod(),
$ciph->name(), $ciph->usedBits(), $ciph->supportedBits();
form->cipherLabel->setText($cipher);
if (!defined padLock) {
this->{padLock} = Qt::ToolButton();
padLock->setIcon(Qt::Icon(':/encrypted.png'));
padLock->setCursor(Qt::Cursor(Qt::ArrowCursor()));
padLock->setToolTip(this->tr('Display encryption details.'));
my $extent = form->hostNameEdit->height() - 2;
padLock->resize($extent, $extent);
padLock->setSizePolicy(Qt::SizePolicy::Fixed(), Qt::SizePolicy::Ignored());
my $layout = Qt::HBoxLayout(form->hostNameEdit);
$layout->setMargin(form->hostNameEdit->style()->pixelMetric(Qt::Style::PM_DefaultFrameWidth()));
$layout->setSpacing(0);
$layout->addStretch();
$layout->addWidget(padLock);
form->hostNameEdit->setLayout($layout);
this->connect(padLock, SIGNAL 'clicked()',
this, SLOT 'displayCertificateInfo()');
} else {
padLock->show();
}
}
sub socketReadyRead
{
my $readAll = this->socket()->readAll();
utf8::encode($readAll);
appendString($readAll);
}
sub sendData
{
my $input = form->sessionInput->text();
appendString($input . "\n");
utf8::decode($input);
this->socket->write($input . "\r\n");
form->sessionInput->clear();
}
sub sslErrors
{
my ($errors) = @_;
my $errorDialog = Qt::Dialog(this);
my $ui = Ui_SslErrors->setupUi($errorDialog);
this->connect($ui->certificateChainButton, SIGNAL 'clicked()',
this, SLOT 'displayCertificateInfo()');
foreach my $error ( @{$errors} ) {
$ui->sslErrorList->addItem($error->errorString());
}
this->{executingDialog} = 1;
if ($errorDialog->exec() == Qt::Dialog::Accepted()) {
this->socket->ignoreSslErrors();
}
this->{executingDialog} = 0;
# did the socket state change?
if (this->socket->state() != Qt::AbstractSocket::ConnectedState()) {
socketStateChanged(this->socket->state());
}
}
sub displayCertificateInfo
{
my $info = CertificateInfo(this);
$info->setCertificateChain(this->socket->peerCertificateChain());
$info->exec();
#$info->deleteLater();
}
sub appendString
{
my ($line) = @_;
my $cursor = Qt::TextCursor(form->sessionOutput->textCursor());
$cursor->movePosition(Qt::TextCursor::End());
$cursor->insertText($line);
form->sessionOutput->verticalScrollBar()->setValue(form->sessionOutput->verticalScrollBar()->maximum());
}
1;