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

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

Run sync after adding a user

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