2 * wpa_gui - WpaGui class
3 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 /* Need to get getopt() */
21 #include <QMessageBox>
22 #include <QCloseEvent>
23 #include <QImageReader>
28 #include "userdatarequest.h"
29 #include "networkconfig.h"
33 #define printf wpagui_printf
34 static int wpagui_printf(const char *, ...)
40 WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
47 connect(fileEventHistoryAction, SIGNAL(triggered()), this,
48 SLOT(eventHistory()));
49 connect(fileSaveConfigAction, SIGNAL(triggered()), this,
51 connect(actionWPS, SIGNAL(triggered()), this, SLOT(wpsDialog()));
52 connect(fileExitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
53 connect(networkAddAction, SIGNAL(triggered()), this,
55 connect(networkEditAction, SIGNAL(triggered()), this,
56 SLOT(editSelectedNetwork()));
57 connect(networkRemoveAction, SIGNAL(triggered()), this,
58 SLOT(removeSelectedNetwork()));
59 connect(networkEnableAllAction, SIGNAL(triggered()), this,
60 SLOT(enableAllNetworks()));
61 connect(networkDisableAllAction, SIGNAL(triggered()), this,
62 SLOT(disableAllNetworks()));
63 connect(networkRemoveAllAction, SIGNAL(triggered()), this,
64 SLOT(removeAllNetworks()));
65 connect(helpIndexAction, SIGNAL(triggered()), this, SLOT(helpIndex()));
66 connect(helpContentsAction, SIGNAL(triggered()), this,
67 SLOT(helpContents()));
68 connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(helpAbout()));
69 connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));
70 connect(scanButton, SIGNAL(clicked()), this, SLOT(scan()));
71 connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB()));
72 connect(adapterSelect, SIGNAL(activated(const QString&)), this,
73 SLOT(selectAdapter(const QString&)));
74 connect(networkSelect, SIGNAL(activated(const QString&)), this,
75 SLOT(selectNetwork(const QString&)));
76 connect(addNetworkButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
77 connect(editNetworkButton, SIGNAL(clicked()), this,
78 SLOT(editListedNetwork()));
79 connect(removeNetworkButton, SIGNAL(clicked()), this,
80 SLOT(removeListedNetwork()));
81 connect(networkList, SIGNAL(itemSelectionChanged()), this,
82 SLOT(updateNetworkDisabledStatus()));
83 connect(enableRadioButton, SIGNAL(toggled(bool)), this,
84 SLOT(enableListedNetwork(bool)));
85 connect(disableRadioButton, SIGNAL(toggled(bool)), this,
86 SLOT(disableListedNetwork(bool)));
87 connect(scanNetworkButton, SIGNAL(clicked()), this, SLOT(scan()));
88 connect(networkList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
89 this, SLOT(editListedNetwork()));
90 connect(wpaguiTab, SIGNAL(currentChanged(int)), this,
91 SLOT(tabChanged(int)));
92 connect(wpsPbcButton, SIGNAL(clicked()), this, SLOT(wpsPbc()));
93 connect(wpsPinButton, SIGNAL(clicked()), this, SLOT(wpsGeneratePin()));
94 connect(wpsApPinEdit, SIGNAL(textChanged(const QString &)), this,
95 SLOT(wpsApPinChanged(const QString &)));
96 connect(wpsApPinButton, SIGNAL(clicked()), this, SLOT(wpsApPin()));
107 ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
111 if (QSystemTrayIcon::isSystemTrayAvailable())
112 createTrayIcon(startInTray);
116 textStatus->setText("connecting to wpa_supplicant");
117 timer = new QTimer(this);
118 connect(timer, SIGNAL(timeout()), SLOT(ping()));
119 timer->setSingleShot(FALSE);
122 if (openCtrlConnection(ctrl_iface) < 0) {
123 printf("Failed to open control connection to "
124 "wpa_supplicant.\n");
128 networkMayHaveChanged = true;
138 wpa_ctrl_detach(monitor_conn);
139 wpa_ctrl_close(monitor_conn);
143 wpa_ctrl_close(ctrl_conn);
168 free(ctrl_iface_dir);
169 ctrl_iface_dir = NULL;
173 void WpaGui::languageChange()
179 void WpaGui::parse_argv()
183 c = getopt(qApp->argc(), qApp->argv(), "i:p:t");
189 ctrl_iface = strdup(optarg);
192 free(ctrl_iface_dir);
193 ctrl_iface_dir = strdup(optarg);
203 int WpaGui::openCtrlConnection(const char *ifname)
207 char buf[2048], *pos, *pos2;
211 if (ifname != ctrl_iface) {
213 ctrl_iface = strdup(ifname);
216 #ifdef CONFIG_CTRL_IFACE_UDP
218 ctrl_iface = strdup("udp");
219 #endif /* CONFIG_CTRL_IFACE_UDP */
220 #ifdef CONFIG_CTRL_IFACE_UNIX
222 DIR *dir = opendir(ctrl_iface_dir);
226 while ((dent = readdir(dir))) {
227 #ifdef _DIRENT_HAVE_D_TYPE
228 /* Skip the file if it is not a socket.
229 * Also accept DT_UNKNOWN (0) in case
230 * the C library or underlying file
231 * system does not support d_type. */
232 if (dent->d_type != DT_SOCK &&
233 dent->d_type != DT_UNKNOWN)
235 #endif /* _DIRENT_HAVE_D_TYPE */
237 if (strcmp(dent->d_name, ".") == 0 ||
238 strcmp(dent->d_name, "..") == 0)
240 printf("Selected interface '%s'\n",
242 ctrl_iface = strdup(dent->d_name);
247 #endif /* CONFIG_CTRL_IFACE_UNIX */
248 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
249 struct wpa_ctrl *ctrl;
255 ctrl = wpa_ctrl_open(NULL);
257 len = sizeof(buf) - 1;
258 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf,
262 pos = strchr(buf, '\n');
265 ctrl_iface = strdup(buf);
267 wpa_ctrl_close(ctrl);
269 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
272 if (ctrl_iface == NULL)
275 #ifdef CONFIG_CTRL_IFACE_UNIX
276 flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
277 cfile = (char *) malloc(flen);
280 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface);
281 #else /* CONFIG_CTRL_IFACE_UNIX */
282 flen = strlen(ctrl_iface) + 1;
283 cfile = (char *) malloc(flen);
286 snprintf(cfile, flen, "%s", ctrl_iface);
287 #endif /* CONFIG_CTRL_IFACE_UNIX */
290 wpa_ctrl_close(ctrl_conn);
297 wpa_ctrl_detach(monitor_conn);
298 wpa_ctrl_close(monitor_conn);
302 printf("Trying to connect to '%s'\n", cfile);
303 ctrl_conn = wpa_ctrl_open(cfile);
304 if (ctrl_conn == NULL) {
308 monitor_conn = wpa_ctrl_open(cfile);
310 if (monitor_conn == NULL) {
311 wpa_ctrl_close(ctrl_conn);
314 if (wpa_ctrl_attach(monitor_conn)) {
315 printf("Failed to attach to wpa_supplicant\n");
316 wpa_ctrl_close(monitor_conn);
318 wpa_ctrl_close(ctrl_conn);
323 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
324 msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn),
325 QSocketNotifier::Read, this);
326 connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
329 adapterSelect->clear();
330 adapterSelect->addItem(ctrl_iface);
331 adapterSelect->setCurrentIndex(0);
333 len = sizeof(buf) - 1;
334 if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >=
339 pos2 = strchr(pos, '\n');
342 if (strcmp(pos, ctrl_iface) != 0)
343 adapterSelect->addItem(pos);
351 len = sizeof(buf) - 1;
352 if (wpa_ctrl_request(ctrl_conn, "GET_CAPABILITY eap", 18, buf, &len,
357 QStringList types = res.split(QChar(' '));
358 actionWPS->setEnabled(types.contains("WSC"));
365 static void wpa_gui_msg_cb(char *msg, size_t)
367 /* This should not happen anymore since two control connections are
369 printf("missed message: %s\n", msg);
373 int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen)
377 if (ctrl_conn == NULL)
379 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen,
382 printf("'%s' command timed out.\n", cmd);
384 printf("'%s' command failed.\n", cmd);
390 void WpaGui::updateStatus()
392 char buf[2048], *start, *end, *pos;
395 pingsToStatusUpdate = 10;
397 len = sizeof(buf) - 1;
398 if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) {
399 textStatus->setText("Could not get status from "
401 textAuthentication->clear();
402 textEncryption->clear();
405 textIpAddress->clear();
411 bool auth_updated = false, ssid_updated = false;
412 bool bssid_updated = false, ipaddr_updated = false;
413 bool status_updated = false;
414 char *pairwise_cipher = NULL, *group_cipher = NULL;
419 end = strchr(start, '\n');
423 while (end[0] && end[1])
428 pos = strchr(start, '=');
431 if (strcmp(start, "bssid") == 0) {
432 bssid_updated = true;
433 textBssid->setText(pos);
434 } else if (strcmp(start, "ssid") == 0) {
436 textSsid->setText(pos);
437 } else if (strcmp(start, "ip_address") == 0) {
438 ipaddr_updated = true;
439 textIpAddress->setText(pos);
440 } else if (strcmp(start, "wpa_state") == 0) {
441 status_updated = true;
442 textStatus->setText(pos);
443 } else if (strcmp(start, "key_mgmt") == 0) {
445 textAuthentication->setText(pos);
446 /* TODO: could add EAP status to this */
447 } else if (strcmp(start, "pairwise_cipher") == 0) {
448 pairwise_cipher = pos;
449 } else if (strcmp(start, "group_cipher") == 0) {
459 if (pairwise_cipher || group_cipher) {
461 if (pairwise_cipher && group_cipher &&
462 strcmp(pairwise_cipher, group_cipher) != 0) {
463 encr.append(pairwise_cipher);
465 encr.append(group_cipher);
466 } else if (pairwise_cipher) {
467 encr.append(pairwise_cipher);
469 encr.append(group_cipher);
470 encr.append(" [group key only]");
472 textEncryption->setText(encr);
474 textEncryption->clear();
479 textAuthentication->clear();
485 textIpAddress->clear();
489 void WpaGui::updateNetworks()
491 char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
493 int first_active = -1;
494 int was_selected = -1;
495 bool current = false;
497 if (!networkMayHaveChanged)
500 if (networkList->currentRow() >= 0)
501 was_selected = networkList->currentRow();
503 networkSelect->clear();
504 networkList->clear();
506 if (ctrl_conn == NULL)
509 len = sizeof(buf) - 1;
510 if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
514 start = strchr(buf, '\n');
521 end = strchr(start, '\n');
525 while (end[0] && end[1])
531 ssid = strchr(id, '\t');
535 bssid = strchr(ssid, '\t');
539 flags = strchr(bssid, '\t');
545 network.append(": ");
546 network.append(ssid);
547 networkSelect->addItem(network);
548 networkList->addItem(network);
550 if (strstr(flags, "[CURRENT]")) {
551 networkSelect->setCurrentIndex(networkSelect->count() -
554 } else if (first_active < 0 &&
555 strstr(flags, "[DISABLED]") == NULL)
556 first_active = networkSelect->count() - 1;
563 if (networkSelect->count() > 1)
564 networkSelect->addItem("Select any network");
566 if (!current && first_active >= 0)
567 networkSelect->setCurrentIndex(first_active);
569 if (was_selected >= 0 && networkList->count() > 0) {
570 if (was_selected < networkList->count())
571 networkList->setCurrentRow(was_selected);
573 networkList->setCurrentRow(networkList->count() - 1);
576 networkList->setCurrentRow(networkSelect->currentIndex());
578 networkMayHaveChanged = false;
582 void WpaGui::helpIndex()
584 printf("helpIndex\n");
588 void WpaGui::helpContents()
590 printf("helpContents\n");
594 void WpaGui::helpAbout()
596 QMessageBox::about(this, "wpa_gui for wpa_supplicant",
597 "Copyright (c) 2003-2008,\n"
598 "Jouni Malinen <j@w1.fi>\n"
599 "and contributors.\n"
601 "This program is free software. You can\n"
602 "distribute it and/or modify it under the terms "
604 "the GNU General Public License version 2.\n"
606 "Alternatively, this software may be distributed\n"
607 "under the terms of the BSD license.\n"
609 "This product includes software developed\n"
610 "by the OpenSSL Project for use in the\n"
611 "OpenSSL Toolkit (http://www.openssl.org/)\n");
615 void WpaGui::disconnect()
618 size_t reply_len = sizeof(reply);
619 ctrlRequest("DISCONNECT", reply, &reply_len);
631 scanres = new ScanResults();
634 scanres->setWpaGui(this);
640 void WpaGui::eventHistory()
647 eh = new EventHistory();
661 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
663 * QSocketNotifier cannot be used with Windows named pipes, so use a
664 * timer to check for received messages for now. This could be
665 * optimized be doing something specific to named pipes or Windows
666 * events, but it is not clear what would be the best way of doing that
670 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
672 if (scanres && !scanres->isVisible()) {
677 if (eh && !eh->isVisible()) {
682 if (udr && !udr->isVisible()) {
687 len = sizeof(buf) - 1;
688 if (ctrlRequest("PING", buf, &len) < 0) {
689 printf("PING failed - trying to reconnect\n");
690 if (openCtrlConnection(ctrl_iface) >= 0) {
691 printf("Reconnected successfully\n");
692 pingsToStatusUpdate = 0;
696 pingsToStatusUpdate--;
697 if (pingsToStatusUpdate <= 0) {
702 #ifndef CONFIG_CTRL_IFACE_NAMED_PIPE
703 /* Use less frequent pings and status updates when the main window is
704 * hidden (running in taskbar). */
705 int interval = isHidden() ? 5000 : 1000;
706 if (timer->interval() != interval)
707 timer->setInterval(interval);
708 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
712 static int str_match(const char *a, const char *b)
714 return strncmp(a, b, strlen(b)) == 0;
718 void WpaGui::processMsg(char *msg)
720 char *pos = msg, *pos2;
726 priority = atoi(pos);
727 pos = strchr(pos, '>');
734 WpaMsg wm(pos, priority);
738 while (msgs.count() > 100)
741 /* Update last message with truncated version of the event */
742 if (strncmp(pos, "CTRL-", 5) == 0) {
743 pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
750 QString lastmsg = pos2;
751 lastmsg.truncate(40);
752 textLastMessage->setText(lastmsg);
754 pingsToStatusUpdate = 0;
755 networkMayHaveChanged = true;
757 if (str_match(pos, WPA_CTRL_REQ))
758 processCtrlReq(pos + strlen(WPA_CTRL_REQ));
759 else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
760 scanres->updateResults();
761 else if (str_match(pos, WPA_EVENT_DISCONNECTED))
762 showTrayMessage(QSystemTrayIcon::Information, 3,
763 "Disconnected from network.");
764 else if (str_match(pos, WPA_EVENT_CONNECTED)) {
765 showTrayMessage(QSystemTrayIcon::Information, 3,
766 "Connection to network established.");
767 QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
769 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PBC)) {
770 showTrayMessage(QSystemTrayIcon::Information, 3,
771 "Wi-Fi Protected Setup (WPS) AP\n"
772 "in active PBC mode found.");
773 wpsStatusText->setText("WPS AP in active PBC mode found");
774 wpaguiTab->setCurrentWidget(wpsTab);
775 wpsInstructions->setText("Press the PBC button on the screen "
776 "to start registration");
777 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE_PIN)) {
778 showTrayMessage(QSystemTrayIcon::Information, 3,
779 "Wi-Fi Protected Setup (WPS) AP\n"
780 " in active PIN mode found.");
781 wpsStatusText->setText("WPS AP with recently selected "
783 wpaguiTab->setCurrentWidget(wpsTab);
784 } else if (str_match(pos, WPS_EVENT_AP_AVAILABLE)) {
785 showTrayMessage(QSystemTrayIcon::Information, 3,
786 "Wi-Fi Protected Setup (WPS)\n"
788 wpsStatusText->setText("WPS AP detected");
789 wpaguiTab->setCurrentWidget(wpsTab);
790 } else if (str_match(pos, WPS_EVENT_OVERLAP)) {
791 showTrayMessage(QSystemTrayIcon::Information, 3,
792 "Wi-Fi Protected Setup (WPS)\n"
793 "PBC mode overlap detected.");
794 wpsStatusText->setText("PBC mode overlap detected");
795 wpsInstructions->setText("More than one AP is currently in "
796 "active WPS PBC mode. Wait couple of "
797 "minutes and try again");
798 wpaguiTab->setCurrentWidget(wpsTab);
799 } else if (str_match(pos, WPS_EVENT_CRED_RECEIVED)) {
800 wpsStatusText->setText("Network configuration received");
801 wpaguiTab->setCurrentWidget(wpsTab);
802 } else if (str_match(pos, WPA_EVENT_EAP_METHOD)) {
803 if (strstr(pos, "(WSC)"))
804 wpsStatusText->setText("Registration started");
805 } else if (str_match(pos, WPS_EVENT_M2D)) {
806 wpsStatusText->setText("Registrar does not yet know PIN");
807 } else if (str_match(pos, WPS_EVENT_FAIL)) {
808 wpsStatusText->setText("Registration failed");
809 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
810 wpsStatusText->setText("Registration succeeded");
815 void WpaGui::processCtrlReq(const char *req)
821 udr = new UserDataRequest();
824 if (udr->setParams(this, req) < 0) {
834 void WpaGui::receiveMsgs()
839 while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) {
840 len = sizeof(buf) - 1;
841 if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) {
849 void WpaGui::connectB()
852 size_t reply_len = sizeof(reply);
853 ctrlRequest("REASSOCIATE", reply, &reply_len);
857 void WpaGui::selectNetwork( const QString &sel )
861 size_t reply_len = sizeof(reply);
863 if (cmd.startsWith("Select any")) {
866 int pos = cmd.indexOf(':');
868 printf("Invalid selectNetwork '%s'\n",
869 cmd.toAscii().constData());
874 cmd.prepend("SELECT_NETWORK ");
875 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
881 void WpaGui::enableNetwork(const QString &sel)
885 size_t reply_len = sizeof(reply);
887 if (!cmd.startsWith("all")) {
888 int pos = cmd.indexOf(':');
890 printf("Invalid enableNetwork '%s'\n",
891 cmd.toAscii().constData());
896 cmd.prepend("ENABLE_NETWORK ");
897 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
902 void WpaGui::disableNetwork(const QString &sel)
906 size_t reply_len = sizeof(reply);
908 if (!cmd.startsWith("all")) {
909 int pos = cmd.indexOf(':');
911 printf("Invalid disableNetwork '%s'\n",
912 cmd.toAscii().constData());
917 cmd.prepend("DISABLE_NETWORK ");
918 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
923 void WpaGui::editNetwork(const QString &sel)
928 if (!cmd.startsWith("Select any")) {
929 int pos = sel.indexOf(':');
931 printf("Invalid editNetwork '%s'\n",
932 cmd.toAscii().constData());
939 NetworkConfig *nc = new NetworkConfig();
945 nc->paramsFromConfig(id);
954 void WpaGui::editSelectedNetwork()
956 if (networkSelect->count() < 1) {
957 QMessageBox::information(this, "No Networks",
958 "There are no networks to edit.\n");
961 QString sel(networkSelect->currentText());
966 void WpaGui::editListedNetwork()
968 if (networkList->currentRow() < 0) {
969 QMessageBox::information(this, "Select A Network",
970 "Select a network from the list to"
974 QString sel(networkList->currentItem()->text());
979 void WpaGui::triggerUpdate()
982 networkMayHaveChanged = true;
987 void WpaGui::addNetwork()
989 NetworkConfig *nc = new NetworkConfig();
999 void WpaGui::removeNetwork(const QString &sel)
1003 size_t reply_len = sizeof(reply);
1005 if (cmd.startsWith("Select any"))
1008 if (!cmd.startsWith("all")) {
1009 int pos = cmd.indexOf(':');
1011 printf("Invalid removeNetwork '%s'\n",
1012 cmd.toAscii().constData());
1017 cmd.prepend("REMOVE_NETWORK ");
1018 ctrlRequest(cmd.toAscii().constData(), reply, &reply_len);
1023 void WpaGui::removeSelectedNetwork()
1025 if (networkSelect->count() < 1) {
1026 QMessageBox::information(this, "No Networks",
1027 "There are no networks to remove.\n");
1030 QString sel(networkSelect->currentText());
1035 void WpaGui::removeListedNetwork()
1037 if (networkList->currentRow() < 0) {
1038 QMessageBox::information(this, "Select A Network",
1039 "Select a network from the list to"
1043 QString sel(networkList->currentItem()->text());
1048 void WpaGui::enableAllNetworks()
1055 void WpaGui::disableAllNetworks()
1058 disableNetwork(sel);
1062 void WpaGui::removeAllNetworks()
1069 int WpaGui::getNetworkDisabled(const QString &sel)
1073 size_t reply_len = sizeof(reply) - 1;
1074 int pos = cmd.indexOf(':');
1076 printf("Invalid getNetworkDisabled '%s'\n",
1077 cmd.toAscii().constData());
1081 cmd.prepend("GET_NETWORK ");
1082 cmd.append(" disabled");
1084 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) >= 0
1085 && reply_len >= 1) {
1086 reply[reply_len] = '\0';
1087 if (!str_match(reply, "FAIL"))
1095 void WpaGui::updateNetworkDisabledStatus()
1097 if (networkList->currentRow() < 0)
1100 QString sel(networkList->currentItem()->text());
1102 switch (getNetworkDisabled(sel)) {
1104 if (!enableRadioButton->isChecked())
1105 enableRadioButton->setChecked(true);
1108 if (!disableRadioButton->isChecked())
1109 disableRadioButton->setChecked(true);
1115 void WpaGui::enableListedNetwork(bool enabled)
1117 if (networkList->currentRow() < 0 || !enabled)
1120 QString sel(networkList->currentItem()->text());
1122 if (getNetworkDisabled(sel) == 1)
1127 void WpaGui::disableListedNetwork(bool disabled)
1129 if (networkList->currentRow() < 0 || !disabled)
1132 QString sel(networkList->currentItem()->text());
1134 if (getNetworkDisabled(sel) == 0)
1135 disableNetwork(sel);
1139 void WpaGui::saveConfig()
1144 len = sizeof(buf) - 1;
1145 ctrlRequest("SAVE_CONFIG", buf, &len);
1149 if (str_match(buf, "FAIL"))
1150 QMessageBox::warning(this, "Failed to save configuration",
1151 "The configuration could not be saved.\n"
1153 "The update_config=1 configuration option\n"
1154 "must be used for configuration saving to\n"
1157 QMessageBox::information(this, "Saved configuration",
1158 "The current configuration was saved."
1163 void WpaGui::selectAdapter( const QString & sel )
1165 if (openCtrlConnection(sel.toAscii().constData()) < 0)
1166 printf("Failed to open control connection to "
1167 "wpa_supplicant.\n");
1173 void WpaGui::createTrayIcon(bool trayOnly)
1175 QApplication::setQuitOnLastWindowClosed(false);
1177 tray_icon = new QSystemTrayIcon(this);
1178 tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
1179 if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
1180 tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
1182 tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
1185 SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1186 this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
1188 ackTrayIcon = false;
1190 tray_menu = new QMenu(this);
1192 disconnectAction = new QAction("&Disconnect", this);
1193 reconnectAction = new QAction("Re&connect", this);
1194 connect(disconnectAction, SIGNAL(triggered()), this,
1195 SLOT(disconnect()));
1196 connect(reconnectAction, SIGNAL(triggered()), this,
1198 tray_menu->addAction(disconnectAction);
1199 tray_menu->addAction(reconnectAction);
1200 tray_menu->addSeparator();
1202 eventAction = new QAction("&Event History", this);
1203 scanAction = new QAction("Scan &Results", this);
1204 statAction = new QAction("S&tatus", this);
1205 connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
1206 connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
1207 connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
1208 tray_menu->addAction(eventAction);
1209 tray_menu->addAction(scanAction);
1210 tray_menu->addAction(statAction);
1211 tray_menu->addSeparator();
1213 showAction = new QAction("&Show Window", this);
1214 hideAction = new QAction("&Hide Window", this);
1215 quitAction = new QAction("&Quit", this);
1216 connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
1217 connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
1218 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
1219 tray_menu->addAction(showAction);
1220 tray_menu->addAction(hideAction);
1221 tray_menu->addSeparator();
1222 tray_menu->addAction(quitAction);
1224 tray_icon->setContextMenu(tray_menu);
1233 void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
1234 const QString & msg)
1236 if (!QSystemTrayIcon::supportsMessages())
1239 if (isVisible() || !tray_icon || !tray_icon->isVisible())
1242 tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
1246 void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
1249 /* use close() here instead of hide() and allow the
1250 * custom closeEvent handler take care of children */
1251 case QSystemTrayIcon::Trigger:
1258 case QSystemTrayIcon::MiddleClick:
1267 void WpaGui::showTrayStatus()
1272 len = sizeof(buf) - 1;
1273 if (ctrlRequest("STATUS", buf, &len) < 0)
1277 QString msg, status(buf);
1279 QStringList lines = status.split(QRegExp("\\n"));
1280 for (QStringList::Iterator it = lines.begin();
1281 it != lines.end(); it++) {
1282 int pos = (*it).indexOf('=') + 1;
1286 if ((*it).startsWith("bssid="))
1287 msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
1288 else if ((*it).startsWith("ssid="))
1289 msg.append("SSID: \t" + (*it).mid(pos) + "\n");
1290 else if ((*it).startsWith("pairwise_cipher="))
1291 msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
1292 else if ((*it).startsWith("group_cipher="))
1293 msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
1294 else if ((*it).startsWith("key_mgmt="))
1295 msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
1296 else if ((*it).startsWith("wpa_state="))
1297 msg.append("STATE:\t" + (*it).mid(pos) + "\n");
1298 else if ((*it).startsWith("ip_address="))
1299 msg.append("IP: \t" + (*it).mid(pos) + "\n");
1300 else if ((*it).startsWith("Supplicant PAE state="))
1301 msg.append("PAE: \t" + (*it).mid(pos) + "\n");
1302 else if ((*it).startsWith("EAP state="))
1303 msg.append("EAP: \t" + (*it).mid(pos) + "\n");
1307 showTrayMessage(QSystemTrayIcon::Information, 10, msg);
1311 void WpaGui::closeEvent(QCloseEvent *event)
1331 if (tray_icon && !ackTrayIcon) {
1332 /* give user a visual hint that the tray icon exists */
1333 if (QSystemTrayIcon::supportsMessages()) {
1335 showTrayMessage(QSystemTrayIcon::Information, 3,
1336 qAppName() + " will keep running in "
1337 "the system tray.");
1339 QMessageBox::information(this, qAppName() + " systray",
1340 "The program will keep "
1341 "running in the system "
1351 void WpaGui::wpsDialog()
1353 wpaguiTab->setCurrentWidget(wpsTab);
1357 void WpaGui::tabChanged(int index)
1365 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1366 if (bssFromScan.isEmpty())
1367 wpsApPinButton->setEnabled(false);
1371 void WpaGui::wpsPbc()
1374 size_t reply_len = sizeof(reply);
1376 if (ctrlRequest("WPS_PBC", reply, &reply_len) < 0)
1379 wpsPinEdit->setEnabled(false);
1380 if (wpsStatusText->text().compare("WPS AP in active PBC mode found")) {
1381 wpsInstructions->setText("Press the push button on the AP to "
1382 "start the PBC mode.");
1384 wpsInstructions->setText("If you have not yet done so, press "
1385 "the push button on the AP to start "
1388 wpsStatusText->setText("Waiting for Registrar");
1393 void WpaGui::wpsGeneratePin()
1396 size_t reply_len = sizeof(reply) - 1;
1398 if (ctrlRequest("WPS_PIN any", reply, &reply_len) < 0)
1401 reply[reply_len] = '\0';
1403 wpsPinEdit->setText(reply);
1404 wpsPinEdit->setEnabled(true);
1405 wpsInstructions->setText("Enter the generated PIN into the Registrar "
1406 "(either the internal one in the AP or an "
1408 wpsStatusText->setText("Waiting for Registrar");
1413 void WpaGui::setBssFromScan(const QString &bssid)
1415 bssFromScan = bssid;
1416 wpsApPinEdit->setEnabled(!bssFromScan.isEmpty());
1417 wpsApPinButton->setEnabled(wpsApPinEdit->text().length() == 8);
1418 wpsStatusText->setText("WPS AP selected from scan results");
1419 wpsInstructions->setText("If you want to use an AP device PIN, e.g., "
1420 "from a label in the device, enter the eight "
1421 "digit AP PIN and click Use AP PIN button.");
1425 void WpaGui::wpsApPinChanged(const QString &text)
1427 wpsApPinButton->setEnabled(text.length() == 8);
1431 void WpaGui::wpsApPin()
1434 size_t reply_len = sizeof(reply);
1436 QString cmd("WPS_REG " + bssFromScan + " " + wpsApPinEdit->text());
1437 if (ctrlRequest(cmd.toAscii().constData(), reply, &reply_len) < 0)
1440 wpsStatusText->setText("Waiting for AP/Enrollee");
1445 void WpaGui::stopWpsRun(bool success)
1448 wpsStatusText->setText(success ? "Connected to the network" :
1451 wpsStatusText->setText("");
1452 wpsPinEdit->setEnabled(false);
1453 wpsInstructions->setText("");
1456 wpsApPinEdit->setEnabled(false);
1457 wpsApPinButton->setEnabled(false);