Browse Source

separate operations into a class running in a QThread, this prepares the menu for async operations like wifi control

master
Brad Parker 11 years ago
parent
commit
d5dc5bc90e
  1. 400
      tui/main.cpp
  2. 390
      tui/menu.cpp
  3. 39
      tui/menu.h
  4. 5
      tui/tui.pro

400
tui/main.cpp

@ -2,386 +2,8 @@
#include <stdio.h>
#include <curses.h>
#include <QCoreApplication>
#include <QRegularExpression>
#include <interface.h>
#include <neighbor.h>
#include <QStringList>
#include <QHash>
#define COLOR_DARK_GRAY 9
void red(WINDOW *window) {
wattron(window, COLOR_PAIR(1));
}
void cyan(WINDOW *window) {
wattron(window, COLOR_PAIR(5));
}
void green(WINDOW *window) {
wattron(window, COLOR_PAIR(2));
}
void magenta(WINDOW *window) {
wattron(window, COLOR_PAIR(6));
}
void quit(WINDOW *window) {
delwin(window);
endwin();
}
void msgbox(const char *text) {
//WINDOW *msgbox = newwin(LINES / 2, COLS / 2, LINES / 4, COLS / 4);
WINDOW *msgbox = newwin(8, COLS / 2, LINES / 4, COLS / 4);
wbkgd(msgbox, COLOR_PAIR(8));
box(msgbox, 0, 0);
mvwaddstr(msgbox, 1, 2, text);
move(3, 5);
wrefresh(msgbox);
WINDOW *ok = derwin(msgbox, 3, 6, msgbox->_maxy / 2 + 1, msgbox->_maxx / 2);
box(ok, 0, 0);
wattron(ok, COLOR_PAIR(5));
mvwaddstr(ok, 1, 2, "OK");
touchwin(msgbox);
wrefresh(ok);
check_return:
char c = getch();
if(c != '\r') {
goto check_return;
}
delwin(ok);
delwin(msgbox);
}
void arpMenu(WINDOW *window);
void interfaceMenu(WINDOW *window);
void interfaceSelect(WINDOW *window, QString interface);
void mainmenu(WINDOW *window) {
wclear(window);
cyan(window);
box(window, 0, 0);
red(window);
mvwaddstr(window, 1, 2, "System Configuration:");
green(window);
mvwaddstr(window, 3, 2, "1. Interfaces");
mvwaddstr(window, 4, 2, "2. ARP");
mvwaddstr(window, 5, 2, "3. Wireless");
cyan(window);
mvwaddstr(window, 7, 2, "q. Quit");
magenta(window);
mvwaddstr(window, 9, 2, "Enter selection: ");
wrefresh(window);
char c = getch();
if(c < '0' || c > '3') {
if(c != 27 && c != 'q') { // allow escape in addition to 0 for quit
mainmenu(window);
}
}else{
if(c == '1') {
interfaceMenu(window);
}else if(c == '2') {
arpMenu(window);
}
}
}
void arpMenu(WINDOW *window) {
wclear(window);
cyan(window);
box(window, 0, 0);
red(window);
mvwaddstr(window, 1, 2, "ARP Table:");
green(window);
QHash<QString, QString> arpList = Neighbor::list(QString());
int y = 3;
int width = 0;
int widthMAC = 0;
int widthIP = 0;
QString format = "%-";
foreach(QString arp, arpList.keys()) {
QString mac = arpList.value(arp);
widthMAC = qMax(widthMAC, mac.length());
widthIP = qMax(widthIP, arp.length());
}
width = widthMAC + widthIP;
format += QString::number(widthIP) + "s at %" + QString::number(widthMAC) + "s";
QByteArray formatArr = format.toLatin1();
const char *formatStr = formatArr.constData();
char *str = (char*)malloc(width + 5);
foreach(QString arp, arpList.keys()) {
//arp = QString::number(count) + ". " + arp;
memset(str, 0, width + 5);
QByteArray arpArray = arp.toLatin1();
QString arpMac = arpList.value(arp);
QByteArray arpMacArray = arpMac.toLatin1();
const char *arpStr = arpArray.constData();
const char *arpMacStr = arpMacArray.constData();
snprintf(str, width + 5, formatStr, arpStr, arpMacStr);
/*memcpy(str, arpStr, strlen(arpStr));
memcpy(str + strlen(arpStr), " at ", 4);
memcpy(str + strlen(arpStr) + 4, arpMacStr, strlen(arpMacStr));*/
mvwaddstr(window, y, 2, str);
++y;
}
free(str);
cyan(window);
mvwaddstr(window, y + 1, 2, "0. Back to main menu");
wrefresh(window);
arpChar:
char c = getch();
if(c != '0' && c != 27 && c != 'q') {
goto arpChar;
}else{
if(c != 'q') {
mainmenu(window);
}
}
}
void interfaceMenu(WINDOW *window) {
wclear(window);
cyan(window);
box(window, 0, 0);
red(window);
mvwaddstr(window, 1, 2, "Interfaces:");
green(window);
QStringList interfaceList = Interface::list();
int count = 1;
int y = 3;
int lastInterface = 0;
QHash<int, QString> interfaceHash;
foreach(QString interface, interfaceList) {
QString orig = interface;
interface = QString::number(count) + ". " + interface;
QByteArray interfaceArray = interface.toLatin1();
const char *interfaceStr = interfaceArray.constData();
mvwaddstr(window, y, 2, interfaceStr);
lastInterface = count + '0';
interfaceHash.insert(lastInterface, orig);
++y;
++count;
}
cyan(window);
mvwaddstr(window, y + 1, 2, "0. Back to main menu");
magenta(window);
mvwaddstr(window, y + 3, 2, "q. Quit");
mvwaddstr(window, y + 5, 2, "Enter selection: ");
wrefresh(window);
char c = getch();
if(c < '0' || c > lastInterface) {
if(c != 'q') {
if(c == 27) {
mainmenu(window);
}else{
interfaceMenu(window);
}
}
}else{
if(c == '0') {
mainmenu(window);
}else{
if(c > '0' && c <= lastInterface) {
interfaceSelect(window, interfaceHash.value(c));
}
}
}
}
void interfaceSelect(WINDOW *window, QString interface) {
wclear(window);
cyan(window);
box(window, 0, 0);
red(window);
QString title = QString("IP Addresses on: ") + interface;
QByteArray array = title.toLatin1();
const char *data = array.constData();
mvwaddstr(window, 1, 2, data);
green(window);
Interface obj(interface);
QStringList ipList = obj.addresses();
int count = 1;
int y = 3;
foreach(QString ip, ipList) {
ip = QString::number(count) + ". " + ip;
QByteArray ipArray = ip.toLatin1();
const char *ipStr = ipArray.constData();
mvwaddstr(window, y, 2, ipStr);
++y;
++count;
}
if(count == 1) {
mvwaddstr(window, y, 2, "No IP addresses found.");
++y;
}
cyan(window);
mvwaddstr(window, y + 1, 2, "0. Back to interfaces");
magenta(window);
mvwaddstr(window, y + 3, 2, "a. Add IP address");
mvwaddstr(window, y + 4, 2, "d. Delete IP address");
mvwaddstr(window, y + 5, 2, "q. Quit");
mvwaddstr(window, y + 7, 2, "Enter selection: ");
wrefresh(window);
char c = getch();
if(c < '0' || c > (count + '0' - 1)) {
if(c == 27) {
interfaceMenu(window);
}else if(c == 'q') {
// no-op, just quit
}else if(c == 'a') {
wdeleteln(window);
mvwaddstr(window, y + 7, 2, "Enter IP address to add: ");
wrefresh(window);
char ipToAdd[19] = {0};
echo();
wgetnstr(window, ipToAdd, sizeof(ipToAdd) / sizeof(char) - 1);
noecho();
QString ip = ipToAdd;
if(!ip.contains(QRegularExpression("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/([5-9]|[1-2][0-9]|3[0-2])$"))) {
msgbox("Invalid IP address. Please try again.");
interfaceSelect(window, interface);
return;
}
wdeleteln(window);
QString confirm = "Are you sure you want to add ";
confirm += ip;
confirm += " [y/n]? ";
QByteArray arr = confirm.toLatin1();
const char *confirmStr = arr.constData();
mvwaddstr(window, y + 7, 2, confirmStr);
wrefresh(window);
c = getch();
if(c == 'y') {
if(obj.addAddress(ip)) {
msgbox("Could not add IP address. Not enough permissions?");
}else{
msgbox("IP address added successfully.");
}
interfaceSelect(window, interface);
}else{
interfaceSelect(window, interface);
}
}else if(c == 'd') {
wdeleteln(window);
mvwaddstr(window, y + 7, 2, "Enter number of IP address to delete: ");
wrefresh(window);
char ipToDelete = getch();
if(ipToDelete < '1' || ipToDelete > '9') {
interfaceSelect(window, interface);
return;
}
if(!(ipList.count() >= ipToDelete - '0')) {
interfaceSelect(window, interface);
return;
}
wdeleteln(window);
QString confirm = "Are you sure you want to delete ";
confirm += ipList[ipToDelete - '0' - 1];
confirm += " [y/n]? ";
QByteArray arr = confirm.toLatin1();
const char *confirmStr = arr.constData();
mvwaddstr(window, y + 7, 2, confirmStr);
wrefresh(window);
c = getch();
if(c == 'y') {
if(obj.deleteAddress(ipList[ipToDelete - '0' - 1])) {
msgbox("Could not delete IP address. Not enough permissions?");
}else{
msgbox("IP address deleted successfully.");
}
interfaceSelect(window, interface);
}else{
interfaceSelect(window, interface);
}
}else{
interfaceSelect(window, interface);
}
}else{
if(c == '0') {
interfaceMenu(window);
}else{
interfaceSelect(window, interface);
}
}
}
#include <QThread>
#include "menu.h"
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
@ -423,11 +45,21 @@ int main(int argc, char *argv[]) {
//printf("\e[1;1H\e[2J");
mainmenu(window);
QThread *thread = new QThread;
Menu *menu = new Menu(window);
menu->moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), menu, SLOT(start()));
QObject::connect(menu, SIGNAL(finished()), thread, SLOT(quit()));
QObject::connect(menu, SIGNAL(finished()), menu, SLOT(deleteLater()));
QObject::connect(menu, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
int ret = app.exec();
quit(window);
/*int ret = app.exec();
return ret;
return ret;*/
return 0;
}

390
tui/menu.cpp

@ -0,0 +1,390 @@
#include <QTimer>
#include "menu.h"
Menu::Menu(WINDOW *window, QObject *parent) :
QObject(parent),
m_window(window)
{
}
Menu::~Menu() {
emit finished();
}
void Menu::start() {
mainmenu(m_window);
}
void Menu::red(WINDOW *window) {
wattron(window, COLOR_PAIR(1));
}
void Menu::cyan(WINDOW *window) {
wattron(window, COLOR_PAIR(5));
}
void Menu::green(WINDOW *window) {
wattron(window, COLOR_PAIR(2));
}
void Menu::magenta(WINDOW *window) {
wattron(window, COLOR_PAIR(6));
}
void Menu::quit(WINDOW *window) {
delwin(window);
endwin();
qApp->quit();
}
void Menu::msgbox(const char *text) {
//WINDOW *msgbox = newwin(LINES / 2, COLS / 2, LINES / 4, COLS / 4);
WINDOW *msgbox = newwin(8, COLS / 2, LINES / 4, COLS / 4);
wbkgd(msgbox, COLOR_PAIR(8));
box(msgbox, 0, 0);
mvwaddstr(msgbox, 1, 2, text);
move(3, 5);
wrefresh(msgbox);
WINDOW *ok = derwin(msgbox, 3, 6, msgbox->_maxy / 2 + 1, msgbox->_maxx / 2);
box(ok, 0, 0);
wattron(ok, COLOR_PAIR(5));
mvwaddstr(ok, 1, 2, "OK");
touchwin(msgbox);
wrefresh(ok);
check_return:
char c = getch();
if(c != '\r') {
goto check_return;
}
delwin(ok);
delwin(msgbox);
}
void Menu::mainmenu(WINDOW *window) {
wclear(window);
cyan(window);
box(window, 0, 0);
red(window);
mvwaddstr(window, 1, 2, "System Configuration:");
green(window);
mvwaddstr(window, 3, 2, "1. Interfaces");
mvwaddstr(window, 4, 2, "2. ARP");
mvwaddstr(window, 5, 2, "3. Wireless");
cyan(window);
mvwaddstr(window, 7, 2, "q. Quit");
magenta(window);
mvwaddstr(window, 9, 2, "Enter selection: ");
wrefresh(window);
char c = getch();
if(c < '0' || c > '3') {
if(c != 27 && c != 'q') { // allow escape in addition to 0 for quit
mainmenu(window);
}
}else{
if(c == '1') {
interfaceMenu(window);
}else if(c == '2') {
arpMenu(window);
}
}
quit(window);
}
void Menu::arpMenu(WINDOW *window) {
wclear(window);
cyan(window);
box(window, 0, 0);
red(window);
mvwaddstr(window, 1, 2, "ARP Table:");
green(window);
QHash<QString, QString> arpList = Neighbor::list(QString());
int y = 3;
int width = 0;
int widthMAC = 0;
int widthIP = 0;
QString format = "%-";
foreach(QString arp, arpList.keys()) {
QString mac = arpList.value(arp);
widthMAC = qMax(widthMAC, mac.length());
widthIP = qMax(widthIP, arp.length());
}
width = widthMAC + widthIP;
format += QString::number(widthIP) + "s at %" + QString::number(widthMAC) + "s";
QByteArray formatArr = format.toLatin1();
const char *formatStr = formatArr.constData();
char *str = (char*)malloc(width + 5);
foreach(QString arp, arpList.keys()) {
//arp = QString::number(count) + ". " + arp;
memset(str, 0, width + 5);
QByteArray arpArray = arp.toLatin1();
QString arpMac = arpList.value(arp);
QByteArray arpMacArray = arpMac.toLatin1();
const char *arpStr = arpArray.constData();
const char *arpMacStr = arpMacArray.constData();
snprintf(str, width + 5, formatStr, arpStr, arpMacStr);
/*memcpy(str, arpStr, strlen(arpStr));
memcpy(str + strlen(arpStr), " at ", 4);
memcpy(str + strlen(arpStr) + 4, arpMacStr, strlen(arpMacStr));*/
mvwaddstr(window, y, 2, str);
++y;
}
free(str);
cyan(window);
mvwaddstr(window, y + 1, 2, "0. Back to main menu");
wrefresh(window);
arpChar:
char c = getch();
if(c != '0' && c != 27 && c != 'q') {
goto arpChar;
}else{
if(c != 'q') {
mainmenu(window);
}
}
}
void Menu::interfaceMenu(WINDOW *window) {
wclear(window);
cyan(window);
box(window, 0, 0);
red(window);
mvwaddstr(window, 1, 2, "Interfaces:");
green(window);
QStringList interfaceList = Interface::list();
int count = 1;
int y = 3;
int lastInterface = 0;
QHash<int, QString> interfaceHash;
foreach(QString interface, interfaceList) {
QString orig = interface;
interface = QString::number(count) + ". " + interface;
QByteArray interfaceArray = interface.toLatin1();
const char *interfaceStr = interfaceArray.constData();
mvwaddstr(window, y, 2, interfaceStr);
lastInterface = count + '0';
interfaceHash.insert(lastInterface, orig);
++y;
++count;
}
cyan(window);
mvwaddstr(window, y + 1, 2, "0. Back to main menu");
magenta(window);
mvwaddstr(window, y + 3, 2, "q. Quit");
mvwaddstr(window, y + 5, 2, "Enter selection: ");
wrefresh(window);
char c = getch();
if(c < '0' || c > lastInterface) {
if(c != 'q') {
if(c == 27) {
mainmenu(window);
}else{
interfaceMenu(window);
}
}
}else{
if(c == '0') {
mainmenu(window);
}else{
if(c > '0' && c <= lastInterface) {
interfaceSelect(window, interfaceHash.value(c));
}
}
}
}
void Menu::interfaceSelect(WINDOW *window, QString interface) {
wclear(window);
cyan(window);
box(window, 0, 0);
red(window);
QString title = QString("IP Addresses on: ") + interface;
QByteArray array = title.toLatin1();
const char *data = array.constData();
mvwaddstr(window, 1, 2, data);
green(window);
Interface obj(interface);
QStringList ipList = obj.addresses();
int count = 1;
int y = 3;
foreach(QString ip, ipList) {
ip = QString::number(count) + ". " + ip;
QByteArray ipArray = ip.toLatin1();
const char *ipStr = ipArray.constData();
mvwaddstr(window, y, 2, ipStr);
++y;
++count;
}
if(count == 1) {
mvwaddstr(window, y, 2, "No IP addresses found.");
++y;
}
cyan(window);
mvwaddstr(window, y + 1, 2, "0. Back to interfaces");
magenta(window);
mvwaddstr(window, y + 3, 2, "a. Add IP address");
mvwaddstr(window, y + 4, 2, "d. Delete IP address");
mvwaddstr(window, y + 5, 2, "q. Quit");
mvwaddstr(window, y + 7, 2, "Enter selection: ");
wrefresh(window);
char c = getch();
if(c < '0' || c > (count + '0' - 1)) {
if(c == 27) {
interfaceMenu(window);
}else if(c == 'q') {
// no-op, just quit
}else if(c == 'a') {
wdeleteln(window);
mvwaddstr(window, y + 7, 2, "Enter IP address to add: ");
wrefresh(window);
char ipToAdd[19] = {0};
echo();
wgetnstr(window, ipToAdd, sizeof(ipToAdd) / sizeof(char) - 1);
noecho();
QString ip = ipToAdd;
if(!ip.contains(QRegularExpression("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/([5-9]|[1-2][0-9]|3[0-2])$"))) {
msgbox("Invalid IP address. Please try again.");
interfaceSelect(window, interface);
return;
}
wdeleteln(window);
QString confirm = "Are you sure you want to add ";
confirm += ip;
confirm += " [y/n]? ";
QByteArray arr = confirm.toLatin1();
const char *confirmStr = arr.constData();
mvwaddstr(window, y + 7, 2, confirmStr);
wrefresh(window);
c = getch();
if(c == 'y') {
if(obj.addAddress(ip)) {
msgbox("Could not add IP address. Not enough permissions?");
}else{
msgbox("IP address added successfully.");
}
interfaceSelect(window, interface);
}else{
interfaceSelect(window, interface);
}
}else if(c == 'd') {
wdeleteln(window);
mvwaddstr(window, y + 7, 2, "Enter number of IP address to delete: ");
wrefresh(window);
char ipToDelete = getch();
if(ipToDelete < '1' || ipToDelete > '9') {
interfaceSelect(window, interface);
return;
}
if(!(ipList.count() >= ipToDelete - '0')) {
interfaceSelect(window, interface);
return;
}
wdeleteln(window);
QString confirm = "Are you sure you want to delete ";
confirm += ipList[ipToDelete - '0' - 1];
confirm += " [y/n]? ";
QByteArray arr = confirm.toLatin1();
const char *confirmStr = arr.constData();
mvwaddstr(window, y + 7, 2, confirmStr);
wrefresh(window);
c = getch();
if(c == 'y') {
if(obj.deleteAddress(ipList[ipToDelete - '0' - 1])) {
msgbox("Could not delete IP address. Not enough permissions?");
}else{
msgbox("IP address deleted successfully.");
}
interfaceSelect(window, interface);
}else{
interfaceSelect(window, interface);
}
}else{
interfaceSelect(window, interface);
}
}else{
if(c == '0') {
interfaceMenu(window);
}else{
interfaceSelect(window, interface);
}
}
}

39
tui/menu.h

@ -0,0 +1,39 @@
#include <iostream>
#include <stdio.h>
#include <curses.h>
#include <QCoreApplication>
#include <QRegularExpression>
#include <interface.h>
#include <neighbor.h>
#include <QStringList>
#include <QHash>
#define COLOR_DARK_GRAY 9
class Menu : public QObject {
Q_OBJECT
public:
Menu(WINDOW *window, QObject *parent = 0);
~Menu();
signals:
void finished();
public slots:
void start();
private:
WINDOW *m_window;
void red(WINDOW *window);
void cyan(WINDOW *window);
void green(WINDOW *window);
void magenta(WINDOW *window);
void quit(WINDOW *window);
void msgbox(const char *text);
void arpMenu(WINDOW *window);
void interfaceMenu(WINDOW *window);
void interfaceSelect(WINDOW *window, QString interface);
void mainmenu(WINDOW *window);
};

5
tui/tui.pro

@ -6,7 +6,10 @@ TEMPLATE = app
TARGET = tui
QT += core
SOURCES += main.cpp
SOURCES += main.cpp \
menu.cpp
HEADERS += menu.h
LIBS += -lncurses

Loading…
Cancel
Save