source: src-qt4/pc-firstbootgui/firstboot.cpp @ 5e274ef

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2
Last change on this file since 5e274ef was 5e274ef, checked in by Kris Moore <kris@…>, 11 months ago

Switch from system() to QProcess::execute() for enable_user_pefs to do more advanced argument pass-through

  • Property mode set to 100644
File size: 14.3 KB
Line 
1#include <QProcess>
2#include <QTimer>
3#include <QGraphicsPixmapItem>
4#include <QTemporaryFile>
5#include <QCloseEvent>
6#include <pcbsd-netif.h>
7#include <pcbsd-utils.h>
8
9#include <sys/types.h>
10#include <pwd.h>
11#include <unistd.h>
12
13#include "backend.h"
14#include "ui_firstboot.h"
15#include "firstboot.h"
16#include "helpText.h"
17
18Installer::Installer(QWidget *parent) : QMainWindow(parent)
19{
20    setupUi(this);
21    translator = new QTranslator();
22
23    connect(backButton, SIGNAL(clicked()), this, SLOT(slotBack()));
24    connect(nextButton, SIGNAL(clicked()), this, SLOT(slotNext()));
25
26    connect(helpButton, SIGNAL(clicked()), this, SLOT(slotHelp()));
27    connect(pushTouchKeyboard, SIGNAL(clicked()), this, SLOT(slotPushVirtKeyboard()));
28    connect(pushChangeKeyLayout, SIGNAL(clicked()), this, SLOT(slotPushKeyLayout()));
29
30    connect(lineHostname,SIGNAL(textChanged(const QString)),this,SLOT(slotCheckHost()));
31
32    connect(lineRootPW, SIGNAL(textChanged ( const QString &)), this, SLOT(slotCheckRootPW()));
33    connect(lineRootPW2, SIGNAL(textChanged ( const QString &)), this, SLOT(slotCheckRootPW()));
34
35    connect(lineName,SIGNAL(textChanged(const QString)),this,SLOT(slotCheckUser()));
36    connect(lineName,SIGNAL(editingFinished()),this,SLOT(slotSuggestUsername()));
37    connect(lineUsername,SIGNAL(textChanged(const QString)),this,SLOT(slotCheckUser()));
38    connect(linePW,SIGNAL(textChanged(const QString)),this,SLOT(slotCheckUser()));
39    connect(linePW2,SIGNAL(textChanged(const QString)),this,SLOT(slotCheckUser()));
40
41    backButton->setText(tr("&Back"));
42    nextButton->setText(tr("&Next"));
43
44
45    // Load the keyboard info
46    keyModels = Scripts::Backend::keyModels();
47    keyLayouts = Scripts::Backend::keyLayouts();
48
49    // Load the timezones
50    comboBoxTimezone->clear();
51    comboBoxTimezone->addItems(Scripts::Backend::timezones());
52    // Set America/New_York to default
53    int index = comboBoxTimezone->findText("America/New_York", Qt::MatchStartsWith);
54    if (index != -1)
55       comboBoxTimezone->setCurrentIndex(index);
56
57    // Load the hostname
58    lineHostname->setText(pcbsd::Utils::getConfFileValue("/etc/rc.conf", "hostname=", 1));
59
60    // Start on the first screen
61    installStackWidget->setCurrentIndex(0);
62    backButton->setVisible(false);
63}
64
65Installer::~Installer()
66{
67    //delete ui;
68}
69
70void Installer::slotSuggestUsername()
71{
72  if ( ! lineUsername->text().isEmpty() || lineName->text().isEmpty() )
73    return;
74  QString name;
75  if ( lineName->text().indexOf(" ") != -1 ) {
76    name = lineName->text().section(' ', 0, 0).toLower();
77    name.truncate(1);
78  }
79  name = name + lineName->text().section(' ', -1, -1).toLower();
80  lineUsername->setText(name);
81}
82
83void Installer::slotPushKeyLayout()
84{
85  wKey = new widgetKeyboard();
86  wKey->programInit(keyModels, keyLayouts);
87  wKey->setWindowModality(Qt::ApplicationModal);
88  connect(wKey, SIGNAL(changedLayout(QString, QString, QString)), this, SLOT(slotKeyLayoutUpdated(QString, QString, QString)));
89  wKey->show();
90  wKey->raise();
91}
92
93// Start xvkbd
94void Installer::slotPushVirtKeyboard()
95{
96   system("killall -9 xvkbd; xvkbd -compact &");
97}
98
99void Installer::initInstall()
100{
101    // load languages
102    comboLanguage->clear();
103    languages = Scripts::Backend::languages();
104    for (int i=0; i < languages.count(); ++i) {
105        QString languageStr = languages.at(i);
106        QString language = languageStr.split("-").at(0);
107        comboLanguage->addItem(language.trimmed());
108    }
109    connect(comboLanguage, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotChangeLanguage()));
110}
111
112void Installer::proceed(bool forward)
113{
114    int count = installStackWidget->count() - 1;
115    int index = installStackWidget->currentIndex();
116
117    index = forward ?
118            (index == count ? count : index + 1) :
119            (index == 0 ? 0 : index - 1);
120
121    installStackWidget->setCurrentIndex(index);
122}
123
124// Check root pw
125void Installer::slotCheckRootPW()
126{
127  nextButton->setEnabled(false);
128
129  if ( lineRootPW->text().isEmpty() )
130     return;
131  if ( lineRootPW2->text().isEmpty() )
132     return;
133  if ( lineRootPW->text() != lineRootPW2->text() )
134     return;
135  // if we get this far, all the fields are filled in
136  nextButton->setEnabled(true);
137}
138
139void Installer::slotCheckHost()
140{
141  QRegExp hostnameRegExp("^(([a-z0-9][a-z0-9-].*[a-z0-9])|([a-z0-9]+))$");
142  nextButton->setEnabled(false);
143  lineHostname->setText(lineHostname->text().toLower());
144  if (lineHostname->text().isEmpty())
145  {
146     lineHostname->setToolTip(tr("Please enter a hostname"));
147     return;
148  } 
149  else if (hostnameRegExp.indexIn(lineHostname->text()) == -1)
150  {
151     lineHostname->setToolTip(tr("Hostname may only contain letters and numbers"));
152     return;
153  }
154  nextButton->setEnabled(true);
155}
156
157void Installer::slotCheckUser()
158{
159  nextButton->setEnabled(false);
160  if ( lineName->text().isEmpty() )
161     return;
162  if ( lineUsername->text().isEmpty() )
163     return;
164  if ( lineUsername->text().contains(" ") )
165     return;
166  else if( getpwnam(lineUsername->text().toUtf8()) != NULL )
167     return;
168  if ( linePW->text().isEmpty() )
169     return;
170  if ( linePW2->text().isEmpty() )
171     return;
172  if ( linePW->text() != linePW2->text() )
173     return;
174  nextButton->setEnabled(true);
175}
176
177// Slot which is called when the Finish button is clicked
178void Installer::slotFinished()
179{
180  qApp->quit();
181}
182
183void Installer::slotNext()
184{
185   QString tmp;
186   backButton->setVisible(true);
187
188   // Check rootPW match
189   if ( installStackWidget->currentIndex() == 1)
190     slotCheckRootPW();
191   // Check user info
192   if ( installStackWidget->currentIndex() == 2)
193     slotCheckUser();
194
195   // Check if we have a wireless device
196   if ( installStackWidget->currentIndex() == 3) {
197     if ( system("ifconfig wlan0") == 0 ) {
198       haveWifi = true;
199       QTimer::singleShot(50,this,SLOT(slotScanNetwork()));
200       connect(pushButtonRescan, SIGNAL(clicked()), this, SLOT(slotScanNetwork()));
201       connect(listWidgetWifi, SIGNAL(itemPressed(QListWidgetItem *)), this, SLOT(slotAddNewWifi()));
202     } else {
203       haveWifi = false;
204     }
205   }
206
207   // If not doing a wireless connection
208   if ( installStackWidget->currentIndex() == 3 && ! haveWifi) {
209      installStackWidget->setCurrentIndex(5);
210      // Save the settings
211      saveSettings();
212      nextButton->setText(tr("&Finish"));
213      backButton->setVisible(false);
214      nextButton->disconnect();
215      connect(nextButton, SIGNAL(clicked()), this, SLOT(slotFinished()));
216      return;
217   }
218
219   // Finished screen
220   if ( installStackWidget->currentIndex() == 4 ) {
221      // Save the settings
222      saveSettings();
223      nextButton->setText(tr("&Finish"));
224      backButton->setVisible(false);
225      nextButton->disconnect();
226      connect(nextButton, SIGNAL(clicked()), this, SLOT(slotFinished()));
227   }
228
229   proceed(true);
230}
231
232void Installer::slotBack()
233{
234   nextButton->setEnabled(true);
235
236   if ( installStackWidget->currentIndex() == 1 )
237     backButton->setVisible(false);
238   else
239     backButton->setVisible(true);
240
241   proceed(false);
242}
243
244void Installer::slotChangeLanguage()
245{
246    if ( comboLanguage->currentIndex() == -1 )
247      return;
248
249    // Figure out the language code
250    QString langCode = languages.at(comboLanguage->currentIndex());
251   
252    // Grab the language code
253    langCode.truncate(langCode.lastIndexOf(")"));
254    langCode.remove(0, langCode.lastIndexOf("(") + 1); 
255
256    // Check what directory our app is in
257    QString appDir;
258    if ( QFile::exists("/usr/local/bin/pc-sysinstaller") )
259      appDir = "/usr/local/share/pcbsd";
260    else
261      appDir = QCoreApplication::applicationDirPath();
262   
263    //QTranslator *translator = new QTranslator();
264    qDebug() << "Remove the translator";
265    if ( ! translator->isEmpty() )
266      QCoreApplication::removeTranslator(translator);
267   
268    if (translator->load( QString("FirstBoot_") + langCode, appDir + "/i18n/" )) {
269      qDebug() << "Load new Translator" << langCode;
270      QCoreApplication::installTranslator(translator);
271      this->retranslateUi(this);
272    }
273
274}
275
276void Installer::changeLang(QString code)
277{
278   // Change the language in the combobox with the current running one
279   comboLanguage->disconnect();
280
281   for (int i=0; i < languages.count(); ++i) {
282      if ( languages.at(i).indexOf("(" + code + ")" ) != -1 ) {
283        comboLanguage->setCurrentIndex(i); 
284      }
285   }
286
287   connect(comboLanguage, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotChangeLanguage()));
288}
289
290void Installer::slotHelp()
291{
292        pcHelp = new dialogHelp();
293        switch (installStackWidget->currentIndex()) {
294        case 0:
295                pcHelp->dialogInit(HELPTEXT0);
296                break;
297        case 1:
298                pcHelp->dialogInit(HELPTEXT1);
299                break;
300        case 2:
301                pcHelp->dialogInit(HELPTEXT2);
302                break;
303        case 3:
304                pcHelp->dialogInit(HELPTEXT3);
305                break;
306        case 4:
307                pcHelp->dialogInit(HELPTEXT4);
308                break;
309        case 5:
310                pcHelp->dialogInit(HELPTEXT5);
311                break;
312        default:
313                pcHelp->dialogInit("Missing help file...");
314                break;
315        }
316        pcHelp->show();
317}
318
319void Installer::slotScanNetwork()
320{
321  QString strength, ssid, security, FileLoad;
322  QStringList ifconfout, ifline;
323  int foundItem = 0;
324
325  // Clear the list box and disable the add button
326  listWidgetWifi->clear();
327
328  // Start the scan and get the output
329  //ifconfout = pcbsd::Utils::runShellCommand("ifconfig -v wlan0 up list scan");
330  ifconfout = pcbsd::Utils::runShellCommand("ifconfig -v wlan0 list scan");
331 
332  qDebug() << ifconfout;
333
334  //display the info for each wifi access point
335  for(int i=1; i<ifconfout.size(); i++){    //Skip the header line by starting at 1
336    ifline = NetworkInterface::parseWifiScanLine(ifconfout[i],true); //get a single line
337    //save the info for this wifi
338    ssid = ifline[0];
339    strength = ifline[4];
340    //determine the icon based on if there is security encryption
341    security = ifline[6]; //NetworkInterface::getWifiSecurity(ssid,DeviceName);
342    if(security.contains("None")){
343      FileLoad = ":/modules/images/object-unlocked.png";
344    }else{
345      FileLoad = ":/modules/images/object-locked.png";
346    }
347    //Add the wifi access point to the list
348    listWidgetWifi->addItem(new QListWidgetItem(QIcon(FileLoad), ssid + " (signal: " +strength + ")") );
349    foundItem = 1; //set the flag for wifi signals found
350  }
351   
352  if ( foundItem == 1 )
353    listWidgetWifi->setCurrentRow(-1);
354}
355
356void Installer::slotAddNewWifi()
357{
358  if ((listWidgetWifi->currentRow()) ==-1 )
359     return;
360
361  QString line = listWidgetWifi->item(listWidgetWifi->currentRow())->text();
362  QString ssidc = line.section(" (",0,0,QString::SectionSkipEmpty);
363  addNetworkProfile(ssidc);
364}
365
366void Installer::addNetworkProfile(QString ssid)
367{
368  //get the full SSID string
369  QString dat = pcbsd::Utils::runShellCommandSearch("ifconfig -v wlan0 list scan",ssid);
370  QStringList wdat = NetworkInterface::parseWifiScanLine(dat,true);
371  QString SSID = wdat[0];
372 
373  //Get the Security Type
374  QString sectype = wdat[6];
375 
376  if(sectype == "None"){
377    //run the Quick-Connect slot without a key
378    slotQuickConnect("",SSID);
379  }else{
380    //Open the dialog to prompt for the Network Security Key
381    dialogNetKey = new netKey();
382    //Insert the SSID into the dialog
383    dialogNetKey->setSSID(SSID);
384    //connect the signal from the dialog to the quick-connect slot
385    connect(dialogNetKey,SIGNAL( saved(QString,QString) ),this,SLOT( slotQuickConnect(QString,QString) ) );
386    //Activate the dialog
387    dialogNetKey->exec();
388  }
389}
390
391void Installer::slotQuickConnect(QString key,QString SSID){
392 
393  // Run the wifiQuickConnect function
394  NetworkInterface::wifiQuickConnect(SSID,key,"wlan0");
395 
396  // Restart the network
397  system("/etc/rc.d/netif restart &");
398 
399  // Move to finish screen
400  installStackWidget->setCurrentIndex(5);
401
402  // Save the settings
403  saveSettings();
404  nextButton->setText(tr("&Finish"));
405  backButton->setVisible(false);
406  nextButton->disconnect();
407  connect(nextButton, SIGNAL(clicked()), this, SLOT(slotFinished()));
408}
409
410void Installer::saveSettings()
411{
412  // Check if we need to change the language
413  if ( comboLanguage->currentIndex() != 0 ) {
414    QString lang = languages.at(comboLanguage->currentIndex());
415    // Grab the language code
416    lang.truncate(lang.lastIndexOf(")"));
417    lang.remove(0, lang.lastIndexOf("(") + 1);
418    qDebug() << "Set Lang:" << lang;
419    system("/usr/local/share/pcbsd/scripts/set-lang.sh " + lang.toLatin1());
420  }
421
422  // Set the timezone
423  QString tz = comboBoxTimezone->currentText();
424  if ( tz.indexOf(":") != -1 )
425   tz = tz.section(":", 0, 0);
426  system("cp /usr/share/zoneinfo/" + tz.toLatin1() + " /etc/localtime");
427
428  // Set the root PW
429  QTemporaryFile rfile("/tmp/.XXXXXXXX");
430  if ( rfile.open() ) {
431    QTextStream stream( &rfile );
432      stream << lineRootPW->text();
433    rfile.close();
434  }
435  system("cat " + rfile.fileName().toLatin1() + " | pw usermod root -h 0 ");
436  rfile.remove();
437
438  // Create the new home-directory
439  system("/usr/local/share/pcbsd/scripts/mkzfsdir.sh /usr/home/" + lineUsername->text().toLatin1() );
440
441  // Create the new username
442  QTemporaryFile ufile("/tmp/.XXXXXXXX");
443  if ( ufile.open() ) {
444    QTextStream stream( &ufile );
445      stream << linePW->text();
446    ufile.close();
447  }
448  QString userCmd = " | pw useradd -n \"" + lineUsername->text() + "\" -c \"" + lineName->text() + "\" -h 0 -s \"/bin/csh\" -m -d \"/usr/home/" + lineUsername->text() + "\" -G \"wheel,operator,vboxusers\"";
449  system("cat " + ufile.fileName().toLatin1() + userCmd.toLatin1());
450  ufile.remove();
451
452  // Enable Flash for the new user
453  QString flashCmd = "su -m " + lineUsername->text() + " -c \"flashpluginctl on\"";
454  system(flashCmd.toLatin1());
455 
456  // Encrypt the users home-directory?
457  if ( checkEnc->isChecked() )
458    QProcess::execute("enable_user_pefs", QStringList() << lineUsername->text() << linePW->text());
459
460  // Do we need to change the system hostname?
461  if ( lineHostname->text() != pcbsd::Utils::getConfFileValue("/etc/rc.conf", "hostname=", 1) )
462  {
463      pcbsd::Utils::setConfFileValue("/etc/rc.conf", "hostname=", "hostname=\"" + lineHostname->text() + "\"", -1);
464      pcbsd::Utils::setConfFileValue("/etc/hosts", "::1", "::1\t\t\tlocalhost localhost.localdomain " + lineHostname->text() + ".localhost " + lineHostname->text(), -1);
465      pcbsd::Utils::setConfFileValue("/etc/hosts", "127.0.0.1", "127.0.0.1\t\tlocalhost localhost.localdomain " + lineHostname->text() + ".localhost " + lineHostname->text(), -1);
466
467      // Now set the hostname on the system
468      sethostname(lineHostname->text().toLatin1(), lineHostname->text().length());
469  }
470
471}
472
473void Installer::slotKeyLayoutUpdated(QString mod, QString lay, QString var)
474{
475  kbMod = mod;
476  kbLay = lay;
477  kbVar = var;
478}
479
480void Installer::closeEvent(QCloseEvent *event)
481{
482   event->ignore();
483}
Note: See TracBrowser for help on using the repository browser.