// Copyright © 2010-2012 sss // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), sock(NULL) { ui->setupUi(this); this->setWindowTitle(tr("Client")); this->setFixedSize(this->size()); show(); ui->state_lbl->show(); ui->state_lbl->setText(" "); ui->state_lbl->setText(tr("Preparing..")); get_socket(); _connect(); ui->state_lbl->setText(QString(" ")); } void MainWindow::get_socket() { if(!sock) { sock = new QSslSocket; QFile in(":/ca.crt"); in.open(QIODevice::ReadOnly); QByteArray buf = in.readAll(); in.close(); QList ca_list; ca_list.push_back(QSslCertificate(buf)); sock->setCaCertificates(ca_list); in.setFileName(":/cli.crt"); in.open(QIODevice::ReadOnly); buf = in.readAll(); in.close(); QSslCertificate c(buf); sock->setLocalCertificate(c); in.setFileName(":/cli.key"); in.open(QIODevice::ReadOnly); buf = in.readAll(); QSslKey key(buf, QSsl::Rsa); sock->setPrivateKey(key); sock->setPeerVerifyMode(QSslSocket::VerifyPeer); sock->setProtocol(QSsl::SslV3); connect(sock, SIGNAL(peerVerifyError(QSslError)), this, SLOT(ssl_verify_error_handler(QSslError))); } } void MainWindow::_connect() { if(!sock) { ui->state_lbl->setText(tr("Socket error..")); return; } ui->state_lbl->setText(tr("Connecting..")); sock->connectToHostEncrypted(host, 1313); connect(sock, SIGNAL(encrypted()), SLOT(connected())); connect(sock, SIGNAL(readyRead()), SLOT(handle_data())); connect(sock, SIGNAL(disconnected()), SLOT(disconnected())); } void MainWindow::connected() { packet *p = packet::cli_make_init_packet(); unsigned char *b = p->buf(); sock->write((char*)b, p->raw().size()); delete [] b; delete p; } void MainWindow::handle_data() { QByteArray a = sock->readAll(); std::vector v; v.assign(a.data(), a.data() + a.size()); packet p(v); if(!p.is_good()) { #ifdef DEBUG QMessageBox msg; msg.setText("bad packet"); msg.exec(); #endif return; } if(!p.is_server_packet()) { #ifdef DEBUG QMessageBox msg; msg.setText("not server packet"); msg.exec(); #endif return; } switch(p.get_type()) { case TYPE_SERVICES: { //TODO: controls positioning services = packet::cli_extract_services(p); for(std::list::iterator i = services->begin(), end = services->end(); i != end; ++i) { service_ui *u = new service_ui; u->group = new QGroupBox(i->service.c_str(), this); u->group->resize(this->size().width() - 10, 50); u->layout = new QHBoxLayout(u->group); for(std::list::iterator ii = i->cmds.begin(), eend = i->cmds.end(); ii != eend; ++ii) { u->commands.push_back(new QPushButton(QString::fromUtf8(ii->command.c_str()), u->group)); connect(u->commands.back(), SIGNAL(clicked()), SLOT(handle_button_click())); u->commands.back()->setToolTip(QString::fromUtf8(ii->description.c_str())); u->layout->addWidget(u->commands.back()); u->commands.back()->show(); svc_ui_list.push_back(u); } u->group->setLayout(u->layout); u->layout->activate(); u->group->show(); } } break; case TYPE_AUTH: { if(p.get_status() == STATUS_SUCCESS) { packet *p = packet::cli_make_request_services_packet(); unsigned char *b = p->buf(); sock->write((char*)b, p->raw().size()); delete [] b; delete p; } } break; case TYPE_COMMAND: { std::string ret = packet::cli_parse_command_reply(p); QMessageBox msg; if(!ret.empty()) msg.setText(QString::fromUtf8(ret.c_str())); else msg.setText(tr("no text in command reply")); if(p.get_status() == STATUS_SUCCESS) msg.setIcon(QMessageBox::Information); else msg.setIcon(QMessageBox::Critical); msg.exec(); } break; default: break; }; } void MainWindow::handle_button_click() { QPushButton *btn = qobject_cast(sender()); if(btn) { QGroupBox *svc = qobject_cast(btn->parent()); if(svc) { packet *p = packet::cli_make_command_packet(svc->title().toUtf8(), btn->text().toUtf8()); unsigned char *b = p->buf(); sock->write((char*)b, p->raw().size()); delete [] b; delete p; } } } void MainWindow::ssl_verify_error_handler(const QSslError error) { switch(error.error()) { case QSslError::InvalidCaCertificate: case QSslError::NoPeerCertificate: case QSslError::UnspecifiedError: case QSslError::AuthorityIssuerSerialNumberMismatch: ui->state_lbl->setText(tr("Connection error")); sock->abort(); return; default: break; } sock->ignoreSslErrors(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::disconnected() { ui->state_lbl->setText(QString::fromUtf8(" ")); for(std::list::iterator i = svc_ui_list.begin(), end = svc_ui_list.end(); i != end; ++i) delete *i; svc_ui_list.clear(); sock->deleteLater(); }