1 /*
2 Copyright (C) 2011-2014 Yubico AB.  All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 
8    1. Redistributions of source code must retain the above copyright
9       notice, this list of conditions and the following disclaimer.
10 
11    2. Redistributions in binary form must reproduce the above
12       copyright notice, this list of conditions and the following
13       disclaimer in the documentation and/or other materials provided
14       with the distribution.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "settingpage.h"
30 #include "yubikeyfinder.h"
31 #include "yubikeyutil.h"
32 #include "yubikeywriter.h"
33 #include "yubikeylogger.h"
34 #include "ui_settingpage.h"
35 #include "ui/helpbox.h"
36 #include "toolpage.h"
37 
38 #include <QFile>
39 #include <QMessageBox>
40 #include <QDebug>
41 #include <QSettings>
42 #include <QSignalMapper>
43 #include <QRegExpValidator>
44 
45 #include "common.h"
46 
47 #define DECIMAL 0
48 #define MODHEX 1
49 #define HEX 2
50 
51 #define OUT_CHAR_RATE_STD 0
52 #define OUT_CHAR_RATE_SLOWDOWN_20 1
53 #define OUT_CHAR_RATE_SLOWDOWN_40 2
54 #define OUT_CHAR_RATE_SLOWDOWN_60 3
55 
SettingPage(QWidget * parent)56 SettingPage::SettingPage(QWidget *parent) :
57         QStackedWidget(parent),
58         ui(new Ui::SettingPage)
59 {
60     QSignalMapper *mapper = new QSignalMapper(this);
61     ui->setupUi(this);
62 
63     m_ykConfig = NULL;
64 
65     //Connect help buttons
66     connectHelpButtons();
67 
68     connect(ui->updateBtn, SIGNAL(clicked()), mapper, SLOT(map()));
69     connect(ui->updateBackBtn, SIGNAL(clicked()), mapper, SLOT(map()));
70     mapper->setMapping(ui->updateBtn, Page_Update);
71     mapper->setMapping(ui->updateBackBtn, Page_Base);
72     connect(mapper, SIGNAL(mapped(int)), this, SLOT(setCurrentPage(int)));
73     m_currentPage = 0;
74     setCurrentIndex(Page_Base);
75 
76     //Connect other signals and slots
77     connect(ui->restoreBtn, SIGNAL(clicked()),
78             this, SLOT(restore()));
79 
80     // autosave when changing settings
81     connect(ui->custPrefixCheck, SIGNAL(clicked()), this, SLOT(save()));
82     connect(ui->logOutputCheck, SIGNAL(clicked()), this, SLOT(save()));
83     connect(ui->tabFirstBtn, SIGNAL(clicked()), this, SLOT(save()));
84     connect(ui->appendTab1Btn, SIGNAL(clicked()), this, SLOT(save()));
85     connect(ui->appendTab2Btn, SIGNAL(clicked()), this, SLOT(save()));
86     connect(ui->appendCRBtn, SIGNAL(clicked()), this, SLOT(save()));
87     connect(ui->appendDelay1Check, SIGNAL(clicked()), this, SLOT(save()));
88     connect(ui->appendDelay2Check, SIGNAL(clicked()), this, SLOT(save()));
89     connect(ui->srBtnVisibleCheck, SIGNAL(clicked()), this, SLOT(save()));
90     connect(ui->srUsbVisibleCheck, SIGNAL(clicked()), this, SLOT(save()));
91     connect(ui->srApiVisibleCheck, SIGNAL(clicked()), this, SLOT(save()));
92     connect(ui->manUpdateCheck, SIGNAL(clicked()), this, SLOT(save()));
93     connect(ui->updateCheck, SIGNAL(clicked()), this, SLOT(save()));
94     connect(ui->fastTrigCheck, SIGNAL(clicked()), this, SLOT(save()));
95     connect(ui->ledInvertCheck, SIGNAL(clicked()), this, SLOT(save()));
96     connect(ui->useNumericKeypadCheck, SIGNAL(clicked()), this, SLOT(save()));
97     connect(ui->logFormatCombo, SIGNAL(activated(int)), this, SLOT(save()));
98     connect(ui->logFormatEdit, SIGNAL(textEdited(QString)), this, SLOT(save()));
99     connect(ui->outCharRateCombo, SIGNAL(activated(int)), this, SLOT(save()));
100     connect(ui->exportCheck, SIGNAL(clicked()), this, SLOT(save()));
101 
102     connect(YubiKeyFinder::getInstance(), SIGNAL(keyFound(bool, bool*, int)),
103             this, SLOT(keyFound(bool, bool*)));
104 
105     QRegExp modHexRx("^[cbdefghijklnrtuv]{0,4}$");
106     ui->custPrefixModhexTxt->setValidator(new QRegExpValidator(modHexRx, this));
107     QRegExp decRx("^[0-9]{0,5}$");
108     ui->custPrefixDecTxt->setValidator(new QRegExpValidator(decRx, this));
109     QRegExp hexRx("^[0-9a-f]{0,4}$");
110     ui->custPrefixHexTxt->setValidator(new QRegExpValidator(hexRx, this));
111 }
112 
~SettingPage()113 SettingPage::~SettingPage() {
114     delete ui->custPrefixModhexTxt->validator();
115     if(m_ykConfig != NULL) {
116         delete m_ykConfig;
117     }
118     delete ui;
119 }
120 
connectHelpButtons()121 void SettingPage::connectHelpButtons() {
122     //Map the values of the help buttons
123 
124     //Create a QMapper
125     QSignalMapper *mapper = new QSignalMapper(this);
126 
127     //Connect the clicked signal with the QSignalMapper
128     connect(ui->outFormatHelpBtn, SIGNAL(clicked()), mapper, SLOT(map()));
129     connect(ui->outSpeedHelpBtn, SIGNAL(clicked()), mapper, SLOT(map()));
130     connect(ui->srVisibilityHelpBtn, SIGNAL(clicked()), mapper, SLOT(map()));
131     connect(ui->updateHelpBtn, SIGNAL(clicked()), mapper, SLOT(map()));
132     connect(ui->swapHelpBtn, SIGNAL(clicked()), mapper, SLOT(map()));
133     connect(ui->manUpdateHelpBtn, SIGNAL(clicked()), mapper, SLOT(map()));
134     connect(ui->logFormatEditHelpBtn, SIGNAL(clicked()), mapper, SLOT(map()));
135 
136     //Set a value for each button
137     mapper->setMapping(ui->outFormatHelpBtn, HelpBox::Help_OutputFormat);
138     mapper->setMapping(ui->outSpeedHelpBtn, HelpBox::Help_OutputSpeed);
139     mapper->setMapping(ui->srVisibilityHelpBtn, HelpBox::Help_SrNoVisibility);
140     mapper->setMapping(ui->updateHelpBtn, HelpBox::Help_AllowUpdate);
141     mapper->setMapping(ui->swapHelpBtn, HelpBox::Help_Swap);
142     mapper->setMapping(ui->manUpdateHelpBtn, HelpBox::Help_ManUpdate);
143     mapper->setMapping(ui->logFormatEditHelpBtn, HelpBox::Help_LogFormat);
144 
145     //Connect the mapper
146     connect(mapper, SIGNAL(mapped(int)), this, SIGNAL(showHelp(int)));
147     connect(ui->configProtectionBox, SIGNAL(showHelp(int)), this, SIGNAL(showHelp(int)));
148 }
149 
setCurrentPage(int pageIndex)150 void SettingPage::setCurrentPage(int pageIndex) {
151     m_currentPage = pageIndex;
152     setCurrentIndex(pageIndex);
153 }
154 
init()155 void SettingPage::init() {
156     load();
157 }
158 
restoreDefaults()159 void SettingPage::restoreDefaults() {
160     QSettings settings;
161 
162     settings.setValue(SG_CUSTOMER_PREFIX_USED,  false);
163     settings.setValue(SG_CUSTOMER_PREFIX,       0);
164 
165     settings.setValue(SG_LOG_DISABLED,          false);
166     // we continue loading LOG_FILENAME since we use that to check if settings are loaded
167     settings.setValue(SG_LOG_FILENAME,          YubiKeyLogger::defaultLogFilename());
168     settings.setValue(SG_LOG_FORMAT,            YubiKeyLogger::Format_Traditional);
169 
170     settings.setValue(SG_EXPORT_FILENAME,       YubiKeyWriter::defaultExportFilename());
171     settings.setValue(SG_IMPORT_FILENAME,       ToolPage::defaultImportFilename());
172 
173     settings.setValue(SG_TAB_FIRST,             false);
174     settings.setValue(SG_APPEND_TAB1,           false);
175     settings.setValue(SG_APPEND_TAB2,           false);
176     settings.setValue(SG_APPEND_CR,             true);
177     settings.setValue(SG_APPEND_DELAY1,         false);
178     settings.setValue(SG_APPEND_DELAY2,         false);
179     settings.setValue(SG_PACING_10MS,           false);
180     settings.setValue(SG_PACING_20MS,           false);
181 
182     settings.setValue(SG_SR_BTN_VISIBLE,        true);
183     settings.setValue(SG_SR_USB_VISIBLE,        false);
184     settings.setValue(SG_SR_API_VISIBLE,        true);
185 
186     settings.setValue(SG_MAN_UPDATE,            false);
187 
188     settings.setValue(SG_ALLOW_UPDATE,          true);
189     settings.setValue(SG_FAST_TRIG,             false);
190     settings.setValue(SG_USE_NUMERIC_KEYPAD,    false);
191 
192     settings.setValue(SG_OATH_HOTP8,            false);
193     settings.setValue(SG_REQUIRE_INPUT,         false);
194     settings.setValue(SG_HMAC_LT64,             true);
195 
196     settings.setValue(SG_STRONG_PW1,            false);
197     settings.setValue(SG_STRONG_PW2,            false);
198     settings.setValue(SG_STRONG_PW3,            false);
199 
200     settings.setValue(SG_EXPORT_PREFERENCE,     false);
201 }
202 
load()203 void SettingPage::load() {
204     QSettings settings;
205 
206     QString logFilename = settings.value(SG_LOG_FILENAME).toString();
207     bool logDisabled = settings.value(SG_LOG_DISABLED).toBool();
208     int logFormat = settings.value(SG_LOG_FORMAT).toInt();
209     if(logFilename.isEmpty()) {
210         //This is the first time... set defaults
211         restoreDefaults();
212     }
213 
214     YubiKeyLogger::setLogFilename(logFilename);
215 
216     QString exportFilename = settings.value(SG_EXPORT_FILENAME).toString();
217     if(!exportFilename.isEmpty()) {
218         YubiKeyWriter::setExportFilename(exportFilename);
219     }
220 
221     QString importFilename = settings.value(SG_IMPORT_FILENAME).toString();
222     if(!importFilename.isEmpty()) {
223         ToolPage::setImportFilename(importFilename);
224     }
225 
226     //General settings...
227     //Customer prefix
228     bool custPrefixUsed = settings.value(SG_CUSTOMER_PREFIX_USED).toBool();
229     if(custPrefixUsed) {
230         ui->custPrefixCheck->setChecked(true);
231 
232         int custPrefix = settings.value(SG_CUSTOMER_PREFIX).toInt();
233         if(custPrefix > 0) {
234             custPrefixChanged(DECIMAL, QString::number(custPrefix));
235             ui->custPrefixDecTxt->setEnabled(true);
236             ui->custPrefixModhexTxt->setEnabled(true);
237             ui->custPrefixHexTxt->setEnabled(true);
238         }
239     } else {
240         ui->custPrefixCheck->setChecked(false);
241 
242         ui->custPrefixDecTxt->clear();
243         ui->custPrefixDecTxt->setEnabled(false);
244         ui->custPrefixModhexTxt->clear();
245         ui->custPrefixModhexTxt->setEnabled(false);
246         ui->custPrefixHexTxt->clear();
247         ui->custPrefixHexTxt->setEnabled(false);
248     }
249 
250 
251     // OTP output settings...
252     ui->tabFirstBtn->setChecked(settings.value(SG_TAB_FIRST).toBool());
253     ui->appendTab1Btn->setChecked(settings.value(SG_APPEND_TAB1).toBool());
254     ui->appendTab2Btn->setChecked(settings.value(SG_APPEND_TAB2).toBool());
255     ui->appendCRBtn->setChecked(settings.value(SG_APPEND_CR).toBool());
256 
257     ui->appendDelay1Check->setChecked(settings.value(SG_APPEND_DELAY1).toBool());
258     ui->appendDelay2Check->setChecked(settings.value(SG_APPEND_DELAY2).toBool());
259 
260     bool pacing10ms = settings.value(SG_PACING_10MS).toBool();
261     bool pacing20ms = settings.value(SG_PACING_20MS).toBool();
262     int outCharRateIndex = 0;
263     if(pacing10ms) {
264         if(pacing20ms) {
265             outCharRateIndex = OUT_CHAR_RATE_SLOWDOWN_60;
266         } else {
267             outCharRateIndex = OUT_CHAR_RATE_SLOWDOWN_20;
268         }
269     } else if(pacing20ms) {
270         outCharRateIndex =  OUT_CHAR_RATE_SLOWDOWN_40;
271     }
272     ui->outCharRateCombo->setCurrentIndex(outCharRateIndex);
273 
274 
275     //Serial # visibility settings...
276     ui->srBtnVisibleCheck->setChecked(settings.value(SG_SR_BTN_VISIBLE).toBool());
277     ui->srUsbVisibleCheck->setChecked(settings.value(SG_SR_USB_VISIBLE).toBool());
278     ui->srApiVisibleCheck->setChecked(settings.value(SG_SR_API_VISIBLE).toBool());
279 
280     //Static Password settings...
281     ui->manUpdateCheck->setChecked(settings.value(SG_MAN_UPDATE).toBool());
282 
283     //Updatable settings...
284     if(settings.contains(SG_ALLOW_UPDATE)) {
285         ui->updateCheck->setChecked(settings.value(SG_ALLOW_UPDATE).toBool());
286     } else {
287         ui->updateCheck->setChecked(true);
288     }
289 
290     // extended settings..
291     ui->fastTrigCheck->setChecked(settings.value(SG_FAST_TRIG).toBool());
292     ui->useNumericKeypadCheck->setChecked(settings.value(SG_USE_NUMERIC_KEYPAD).toBool());
293     ui->ledInvertCheck->setChecked(settings.value(SG_LED_INVERT).toBool());
294 
295     //Logging settings...
296     if(logDisabled) {
297         YubiKeyLogger::disableLogging();
298 
299         ui->logOutputCheck->setChecked(false);
300         ui->logFormatCombo->setEnabled(false);
301         ui->logFormatEdit->setEnabled(false);
302     } else {
303         YubiKeyLogger::enableLogging();
304 
305         ui->logOutputCheck->setChecked(true);
306         ui->logFormatCombo->setEnabled(true);
307         ui->logFormatCombo->setCurrentIndex(logFormat);
308         YubiKeyLogger::setLogFormat((YubiKeyLogger::Format)logFormat);
309         if(logFormat == YubiKeyLogger::Format_Flexible) {
310             QString format = settings.value(SG_LOG_FLEXIBLE).toString();
311             ui->logFormatEdit->setEnabled(true);
312             ui->logFormatEdit->setText(format);
313             YubiKeyLogger::setFlexibleFormat(format);
314         } else {
315             ui->logFormatEdit->setEnabled(false);
316         }
317     }
318 
319     ui->exportCheck->setChecked(settings.value(SG_EXPORT_PREFERENCE).toBool());
320 
321     //Signal everyone
322     emit settingsChanged();
323 }
324 
save()325 void SettingPage::save() {
326     QSettings settings;
327 
328     //General settings...
329 
330     //Customer prefix
331     int custPrefix = 0;
332     if(ui->custPrefixCheck->isChecked()) {
333         settings.setValue(SG_CUSTOMER_PREFIX_USED, true);
334         custPrefix = ui->custPrefixDecTxt->text().toInt();
335     } else {
336         settings.setValue(SG_CUSTOMER_PREFIX_USED, false);
337     }
338     settings.setValue(SG_CUSTOMER_PREFIX, custPrefix);
339 
340 
341     // OTP output settings...
342     settings.setValue(SG_TAB_FIRST,         ui->tabFirstBtn->isChecked());
343     settings.setValue(SG_APPEND_TAB1,       ui->appendTab1Btn->isChecked());
344     settings.setValue(SG_APPEND_TAB2,       ui->appendTab2Btn->isChecked());
345     settings.setValue(SG_APPEND_CR,         ui->appendCRBtn->isChecked());
346     settings.setValue(SG_APPEND_DELAY1,     ui->appendDelay1Check->isChecked());
347     settings.setValue(SG_APPEND_DELAY2,     ui->appendDelay2Check->isChecked());
348 
349     switch(ui->outCharRateCombo->currentIndex()) {
350     case OUT_CHAR_RATE_STD:
351         settings.setValue(SG_PACING_10MS,   false);
352         settings.setValue(SG_PACING_20MS,   false);
353         break;
354     case OUT_CHAR_RATE_SLOWDOWN_20:
355         settings.setValue(SG_PACING_10MS,   true);
356         settings.setValue(SG_PACING_20MS,   false);
357         break;
358     case OUT_CHAR_RATE_SLOWDOWN_40:
359         settings.setValue(SG_PACING_10MS,   false);
360         settings.setValue(SG_PACING_20MS,   true);
361         break;
362     case OUT_CHAR_RATE_SLOWDOWN_60:
363         settings.setValue(SG_PACING_10MS,   true);
364         settings.setValue(SG_PACING_20MS,   true);
365         break;
366     }
367 
368     //Serial # visibility settings...
369     settings.setValue(SG_SR_BTN_VISIBLE,    ui->srBtnVisibleCheck->isChecked());
370     settings.setValue(SG_SR_USB_VISIBLE,    ui->srUsbVisibleCheck->isChecked());
371     settings.setValue(SG_SR_API_VISIBLE,    ui->srApiVisibleCheck->isChecked());
372 
373     //Static Password settings...
374     settings.setValue(SG_MAN_UPDATE,        ui->manUpdateCheck->isChecked());
375 
376     // Updatable settings...
377     settings.setValue(SG_ALLOW_UPDATE, ui->updateCheck->isChecked());
378 
379     // Extended settings
380     settings.setValue(SG_FAST_TRIG, ui->fastTrigCheck->isChecked());
381     settings.setValue(SG_USE_NUMERIC_KEYPAD, ui->useNumericKeypadCheck->isChecked());
382     settings.setValue(SG_LED_INVERT, ui->ledInvertCheck->isChecked());
383 
384     //Logging settings...
385     if(ui->logOutputCheck->isChecked()) {
386         settings.setValue(SG_LOG_DISABLED,  false);
387         settings.setValue(SG_LOG_FORMAT, ui->logFormatCombo->currentIndex());
388         if(ui->logFormatCombo->currentIndex() == YubiKeyLogger::Format_Flexible) {
389             settings.setValue(SG_LOG_FLEXIBLE, ui->logFormatEdit->text());
390         }
391     } else {
392         settings.setValue(SG_LOG_DISABLED,  true);
393     }
394 
395     settings.setValue(SG_EXPORT_PREFERENCE, ui->exportCheck->isChecked());
396 
397     //Reload settings
398     load();
399 
400     showStatusMessage(tr(SETTINGS_SAVED), 0);
401 }
402 
restore()403 void SettingPage::restore() {
404     //Confirm restore
405     //Confirm from client
406     switch (
407             QMessageBox::question(
408                     this, tr(RESTORE_SETTING),
409                     tr(WARN_RESTORE_SETTING),
410                     tr("&Yes"), tr("&No"), QString::null, 1, 1 ))
411     {
412     case 0:
413         restoreDefaults();
414         //Reload settings
415         load();
416         showStatusMessage(tr(SETTINGS_RESTORED), 0);
417 
418         break;
419     default:
420         break;
421     }
422 }
423 
on_custPrefixCheck_stateChanged(int state)424 void SettingPage::on_custPrefixCheck_stateChanged(int state) {
425     if(state == 0) {
426         ui->custPrefixDecTxt->setEnabled(false);
427         ui->custPrefixModhexTxt->setEnabled(false);
428         ui->custPrefixHexTxt->setEnabled(false);
429     } else {
430         ui->custPrefixDecTxt->setEnabled(true);
431         ui->custPrefixModhexTxt->setEnabled(true);
432         ui->custPrefixHexTxt->setEnabled(true);
433     }
434 }
435 
on_custPrefixDecTxt_editingFinished()436 void SettingPage::on_custPrefixDecTxt_editingFinished() {
437     custPrefixChanged(DECIMAL, ui->custPrefixDecTxt->text());
438     save();
439 }
440 
on_custPrefixModhexTxt_editingFinished()441 void SettingPage::on_custPrefixModhexTxt_editingFinished() {
442     custPrefixChanged(MODHEX, ui->custPrefixModhexTxt->text());
443     save();
444 }
445 
on_custPrefixHexTxt_editingFinished()446 void SettingPage::on_custPrefixHexTxt_editingFinished() {
447     custPrefixChanged(HEX, ui->custPrefixHexTxt->text());
448     save();
449 }
450 
on_doUpdateBtn_clicked()451 void SettingPage::on_doUpdateBtn_clicked() {
452     int slot;
453 
454     if(ui->updateSlot1Radio->isChecked()) {
455         slot = 1;
456     } else if(ui->updateSlot2Radio->isChecked()) {
457         slot = 2;
458     } else {
459       emit showStatusMessage(tr(ERR_CONF_SLOT_NOT_SELECTED), 1);
460       return;
461     }
462 
463     if(m_ykConfig != NULL) {
464         delete m_ykConfig;
465     }
466     m_ykConfig = new YubiKeyConfig();
467 
468     m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_Update);
469     m_ykConfig->setConfigSlot(slot);
470 
471     // set serial
472     m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial()));
473 
474     // access code
475     m_ykConfig->setCurrentAccessCodeTxt(
476         ui->configProtectionBox->currentAccessCode());
477     m_ykConfig->setNewAccessCodeTxt(
478         ui->configProtectionBox->newAccessCode(),
479         ui->configProtectionBox->newAccMode());
480 
481     if(ui->updateDormantCheck->isChecked()) {
482         m_ykConfig->setDormant(true);
483     }
484 
485     //Write
486     connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)),
487             this, SLOT(updateConfigWritten(bool, const QString &)));
488 
489     YubiKeyWriter::getInstance()->writeConfig(m_ykConfig);
490 }
491 
updateConfigWritten(bool written,const QString & msg)492 void SettingPage::updateConfigWritten(bool written, const QString &msg) {
493     disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)),
494         this, SLOT(updateConfigWritten(bool, const QString &)));
495 
496     if(written) {
497         qDebug() << "Configuration updated." << msg;
498         emit showStatusMessage(tr("Configuration successfully updated.", 0));
499     } else {
500         qDebug() << "Failed update.";
501         emit showStatusMessage(msg, 1);;
502     }
503 
504 }
505 
on_swapBtn_clicked()506 void SettingPage::on_swapBtn_clicked() {
507     if(m_ykConfig != NULL) {
508         delete m_ykConfig;
509     }
510     m_ykConfig = new YubiKeyConfig();
511 
512     m_ykConfig->setProgrammingMode(YubiKeyConfig::Mode_Swap);
513 
514     // set serial
515     m_ykConfig->setSerial(QString::number(YubiKeyFinder::getInstance()->serial()));
516 
517     // access code
518     m_ykConfig->setCurrentAccessCodeTxt(
519         ui->configProtectionBox->currentAccessCode());
520     m_ykConfig->setNewAccessCodeTxt(
521         ui->configProtectionBox->newAccessCode(),
522         ui->configProtectionBox->newAccMode());
523 
524     //Write
525     connect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)),
526             this, SLOT(swapWritten(bool, const QString &)));
527 
528     YubiKeyWriter::getInstance()->writeConfig(m_ykConfig);
529 }
530 
swapWritten(bool written,const QString & msg)531 void SettingPage::swapWritten(bool written, const QString &msg) {
532     disconnect(YubiKeyWriter::getInstance(), SIGNAL(configWritten(bool, const QString &)),
533         this, SLOT(swapWritten(bool, const QString &)));
534 
535     if(written) {
536         qDebug() << "Configurations swapped." << msg;
537         emit showStatusMessage(tr("Configuration successfully swapped.", 0));
538     } else {
539         qDebug() << "Failed swapping." << msg;
540         emit showStatusMessage(msg, 1);;
541     }
542 }
543 
keyFound(bool found,bool * featuresMatrix)544 void SettingPage::keyFound(bool found, bool* featuresMatrix) {
545     if(found) {
546         if(featuresMatrix[YubiKeyFinder::Feature_Updatable]) {
547             ui->updateBtn->setEnabled(true);
548         }
549     } else {
550         ui->updateBtn->setEnabled(false);
551     }
552 }
553 
custPrefixChanged(int type,QString src)554 void SettingPage::custPrefixChanged(int type, QString src) {
555     unsigned char buf[16];
556     memset(buf, 0, sizeof(buf));
557     size_t bufLen = 0;
558 
559     switch(type) {
560         // decimal
561         case DECIMAL:
562             {
563                 QString tmp = QString::number(src.toULongLong(), 16);
564                 size_t len = tmp.length();
565                 if(len % 2 != 0) {
566                     len++;
567                 }
568                 YubiKeyUtil::qstrClean(&tmp, (size_t)len, true);
569                 YubiKeyUtil::qstrHexDecode(buf, &bufLen, tmp);
570                 break;
571             }
572         // modhex
573         case MODHEX:
574             YubiKeyUtil::qstrModhexDecode(buf, &bufLen, src);
575             break;
576         // hex
577         case HEX:
578             YubiKeyUtil::qstrHexDecode(buf, &bufLen, src);
579             break;
580     }
581     QString hex = YubiKeyUtil::qstrHexEncode(buf, bufLen);
582     QString modhex = YubiKeyUtil::qstrModhexEncode(buf, bufLen);
583     bool ok = false;
584     qulonglong dec = hex.toULongLong(&ok, 16);
585     if(dec > 0) {
586         ui->custPrefixDecTxt->setText(QString::number(dec));
587         ui->custPrefixModhexTxt->setText(modhex);
588         ui->custPrefixHexTxt->setText(hex);
589     }
590 }
591 
reloadSettings()592 void SettingPage::reloadSettings() {
593     load();
594 }
595