1 /*
2 unetbootin.cpp from UNetbootin <http://unetbootin.sourceforge.net>
3 Copyright (C) 2007-2008 Geza Kovacs <geza0kovacs@gmail.com>
4 
5 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.
6 
7 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License at <http://www.gnu.org/licenses/> for more details.
8 */
9 
10 #include "unetbootin.h"
11 
12 #include <QMessageBox>
13 #include <QFileDialog>
14 #include <QProgressDialog>
15 #include <QDebug>
16 
17 static const QList<QRegExp> ignoredtypesbothRL = QList<QRegExp>()
18 << QRegExp("isolinux.bin$", Qt::CaseInsensitive)
19 << QRegExp("isolinux.cfg$", Qt::CaseInsensitive)
20 << QRegExp("memtest$", Qt::CaseInsensitive)
21 << QRegExp("memtest.bin$", Qt::CaseInsensitive)
22 << QRegExp("memtest86$", Qt::CaseInsensitive)
23 << QRegExp("memtest86.bin$", Qt::CaseInsensitive)
24 << QRegExp("memtest+$", Qt::CaseInsensitive)
25 << QRegExp("memtest+.bin$", Qt::CaseInsensitive)
26 << QRegExp("memtest86+$", Qt::CaseInsensitive)
27 << QRegExp("memtest86+.bin$", Qt::CaseInsensitive)
28 << QRegExp("memtestplus$", Qt::CaseInsensitive)
29 << QRegExp("memtestplus.bin$", Qt::CaseInsensitive)
30 << QRegExp("memtest86plus$", Qt::CaseInsensitive)
31 << QRegExp("memtest86plus.bin$", Qt::CaseInsensitive)
32 << QRegExp("mt86plus$", Qt::CaseInsensitive)
33 << QRegExp("mt86+$", Qt::CaseInsensitive)
34 << QRegExp("mt86.bin$", Qt::CaseInsensitive)
35 << QRegExp("mt86plus.bin$", Qt::CaseInsensitive)
36 << QRegExp("mt86+.bin$", Qt::CaseInsensitive)
37 << QRegExp("system.map$", Qt::CaseInsensitive)
38 << QRegExp(".efimg$", Qt::CaseInsensitive)
39 << QRegExp(".html$", Qt::CaseInsensitive)
40 << QRegExp(".jpg$", Qt::CaseInsensitive)
41 << QRegExp(".png$", Qt::CaseInsensitive)
42 << QRegExp(".pdf$", Qt::CaseInsensitive)
43 << QRegExp(".pcx$", Qt::CaseInsensitive)
44 << QRegExp(".rle$", Qt::CaseInsensitive)
45 << QRegExp(".fnt$", Qt::CaseInsensitive)
46 << QRegExp(".psd$", Qt::CaseInsensitive)
47 << QRegExp(".xcf$", Qt::CaseInsensitive)
48 << QRegExp(".bmp$", Qt::CaseInsensitive)
49 << QRegExp(".svg$", Qt::CaseInsensitive)
50 << QRegExp(".md5$", Qt::CaseInsensitive)
51 << QRegExp(".md5sum$", Qt::CaseInsensitive)
52 << QRegExp(".sha1$", Qt::CaseInsensitive)
53 << QRegExp(".sha1sum$", Qt::CaseInsensitive)
54 << QRegExp(".c32$", Qt::CaseInsensitive)
55 << QRegExp(".sig$", Qt::CaseInsensitive)
56 << QRegExp(".msg$", Qt::CaseInsensitive)
57 << QRegExp(".cat$", Qt::CaseInsensitive)
58 << QRegExp(".txt$", Qt::CaseInsensitive)
59 << QRegExp(".tar$", Qt::CaseInsensitive)
60 << QRegExp(".exe$", Qt::CaseInsensitive)
61 << QRegExp(".deb$", Qt::CaseInsensitive)
62 << QRegExp(".udeb$", Qt::CaseInsensitive)
63 << QRegExp("system.map", Qt::CaseInsensitive);
64 
65 static const QList<QRegExp> ignoredtypeskernelRL = QList<QRegExp>()
66 << QRegExp("initrd.gz$", Qt::CaseInsensitive)
67 << QRegExp("initrd.img$", Qt::CaseInsensitive);
68 
69 static const QList<QRegExp> ignoredtypesinitrdRL = QList<QRegExp>()
70 << QRegExp("bzImage$", Qt::CaseInsensitive);
71 
72 static const QString SALT_DETECTED = "*SaLT*";
73 
run()74 void callexternappT::run()
75 {
76 	#ifdef Q_OS_WIN32
77 	SHELLEXECUTEINFO ShExecInfo = {0};
78 	ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
79 	ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
80 	ShExecInfo.hwnd = NULL;
81 	if (QSysInfo::WindowsVersion == QSysInfo::WV_NT || QSysInfo::WindowsVersion == QSysInfo::WV_2000 || QSysInfo::WindowsVersion == QSysInfo::WV_XP || QSysInfo::WindowsVersion == QSysInfo::WV_2003 )
82 	{
83 		ShExecInfo.lpVerb = NULL;
84 	}
85 	else
86 	{
87 		ShExecInfo.lpVerb = L"runas";
88 	}
89 	ShExecInfo.lpFile = LPWSTR(execFile.utf16());
90 	ShExecInfo.lpParameters = LPWSTR(execParm.utf16());
91 	ShExecInfo.lpDirectory = NULL;
92 	ShExecInfo.nShow = SW_HIDE;
93 	ShExecInfo.hInstApp = NULL;
94 	ShellExecuteEx(&ShExecInfo);
95 	WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
96 	retnValu = "";
97 	#endif
98 	#ifdef Q_OS_UNIX
99 	QProcess lnexternapp;
100     lnexternapp.start("\"" + execFile + "\" " + execParm);
101 	lnexternapp.waitForFinished(-1);
102 	retnValu = QString(lnexternapp.readAll());
103 	#endif
104 }
105 
run()106 void callexternappWriteToStdinT::run()
107 {
108 	QProcess lnexternapp;
109 	lnexternapp.start("\"" + execFile + "\" " + execParm);
110 	lnexternapp.write(writeToStdin.toLatin1().data());
111 	lnexternapp.closeWriteChannel();
112 	lnexternapp.waitForFinished(-1);
113 	retnValu = QString(lnexternapp.readAll());
114 }
115 
run()116 void copyfileT::run()
117 {
118 	QFile srcF(source);
119 	srcF.open(QIODevice::ReadOnly);
120 	QFile dstF(destination);
121 	dstF.open(QIODevice::WriteOnly);
122 	qint64 maxbytes = srcF.size();
123 	qint64 dlbytes = 0;
124 	char *buf = new char[262144];
125 	while (!srcF.atEnd())
126 	{
127 		qint64 bytesread = srcF.read(buf, 262144);
128 		dstF.write(buf, bytesread);
129 		dlbytes += bytesread;
130 		emit datacopied64(dlbytes, maxbytes);
131 #ifdef Q_OS_UNIX
132 		unetbootin::callexternapp("sync", "");
133 #endif
134 	}
135 	delete[] buf;
136 	srcF.close();
137 	dstF.close();
138 	emit finished();
139 }
140 
randtmpfile(QString rfpath,QString rfextn)141 randtmpfile::randtmpfile(QString rfpath, QString rfextn)
142 {
143 	QString basefn = getrandfilename(rfpath, rfextn);
144 	this->setFileName(basefn);
145 }
146 
getrandfilename(QString rfpath,QString rfextn)147 QString randtmpfile::getrandfilename(QString rfpath, QString rfextn)
148 {
149 	qsrand((unsigned int)time(0));
150 	QString basefn = QString("%1un%2.%3").arg(rfpath).arg(qrand() % 999999).arg(rfextn);
151 	while (QFile::exists(basefn))
152 	{
153 		basefn = QString("%1%2.%3").arg(rfpath).arg(qrand() % 999999).arg(rfextn);
154 	}
155 	return basefn;
156 }
157 /*
158 void nDirListStor::sAppendSelfUrlInfoList(QUrlInfo curDirUrl)
159 {
160 	if (curDirUrl.isValid() && curDirUrl.isReadable() && curDirUrl.isFile() && curDirUrl.size() > nMinFileSizeBytes && curDirUrl.size() < nMaxFileSizeBytes)
161 	{
162 		nDirFileListSL.append(curDirUrl.name());
163 	}
164 	else if (this->searchsymlinks && curDirUrl.isReadable() && curDirUrl.isSymLink())
165 	{
166 		nDirFileListSL.append(curDirUrl.name());
167 	}
168 }
169 */
unetbootin(QWidget * parent)170 unetbootin::unetbootin(QWidget *parent)
171 	: QWidget(parent)
172 {
173 	setupUi(this);
174 }
175 
ubninitialize(QList<QPair<QString,QString>> oppairs)176 bool unetbootin::ubninitialize(QList<QPair<QString, QString> > oppairs)
177 {
178     skipExtraction = false;
179     redundanttopleveldir = false;
180 	isarch64 = false;
181 	islivecd = false;
182 	isnetinstall = false;
183 	ishdmedia = false;
184 	overwriteall = false;
185 	searchsymlinks = false;
186 	ignoreoutofspace = false;
187 	downloadFailed = false;
188 	exitOnCompletion = false;
189 	testingDownload = false;
190 	issalt = false;
191 	persistenceSpaceMB = 0;
192     logFile = 0;
193     logStream = 0;
194 #ifdef Q_OS_MAC
195 	ignoreoutofspace = true;
196 #endif
197 	dontgeneratesyslinuxcfg = false;
198 	#ifdef Q_OS_UNIX
199 	isext2 = false;
200 	#endif
201 	secondlayer->setEnabled(false);
202 	secondlayer->hide();
203 	firstlayer->setEnabled(true);
204 	firstlayer->show();
205 	this->setWindowTitle(UNETBOOTINB  " 702");
206 	overwriteall = false;
207 #ifndef Q_OS_MAC
208 	typeselect->addItem(tr("Hard Disk"));
209 #endif
210 	typeselect->addItem(tr("USB Drive"));
211 	diskimagetypeselect->addItem(tr("ISO"));
212 	diskimagetypeselect->addItem(tr("Floppy"));
213 	bool hideCustom = true;
214 	#ifdef NOEXTERN
215 	optionslayer->setEnabled(false);
216 	optionslayer->hide();
217 	radioFloppy->setEnabled(false);
218 	radioFloppy->hide();
219 	radioManual->setEnabled(false);
220 	radioManual->hide();
221 	intromessage->resize(intromessage->width(), intromessage->height() + 135);
222 	#endif
223 	#ifdef NOFLOPPY
224 	if (diskimagetypeselect->findText(tr("Floppy")) != -1)
225 		diskimagetypeselect->removeItem(diskimagetypeselect->findText(tr("Floppy")));
226 	#endif
227 	#ifdef NOISO
228 	if (diskimagetypeselect->findText(tr("ISO")) != -1)
229 		diskimagetypeselect->removeItem(diskimagetypeselect->findText(tr("ISO")));
230 	#endif
231 	#include "distrovercust.cpp"
232 	#ifdef STDUNETBOOTIN
233 	optionslayer->setEnabled(true);
234 	optionslayer->show();
235 	#include "distrover.cpp"
236 	#endif
237 	#include "customdistselect.cpp"
238 #ifdef Q_OS_MAC
239 	resourceDir = QDir(QApplication::applicationDirPath());
240 	resourceDir.cdUp();
241 	resourceDir.cd("Resources");
242 	syslinuxcommand = resourceDir.absoluteFilePath("syslinux-mac");
243 	sevzcommand = resourceDir.absoluteFilePath("7z-mac");
244 	mke2fscommand = resourceDir.absoluteFilePath("mke2fs");
245 	fdiskcommand = locatecommand("fdisk", tr("either"), "util-linux");
246 #endif
247 	#ifdef Q_OS_LINUX
248 	if (QFile::exists("/sbin/fdisk"))
249 		fdiskcommand = "/sbin/fdisk";
250 	else
251 				fdiskcommand = locatecommand("fdisk", tr("either"), "util-linux");
252 		if (QFile::exists("/bin/df"))
253 				dfcommand = "/bin/df";
254 		else
255 				dfcommand = locatecommand("df", tr("either"), "util-linux");
256 	if (QFile::exists("/sbin/sfdisk"))
257 		sfdiskcommand = "/sbin/sfdisk";
258 	else
259 		sfdiskcommand = locatecommand("sfdisk", tr("either"), "silent");
260 	if (QFile::exists("/lib/udev/vol_id"))
261 		volidcommand = "/lib/udev/vol_id";
262 	else
263 		volidcommand = locatecommand("vol_id", tr("either"), "silent");
264 	if (volidcommand.isEmpty())
265 	{
266 		if (QFile::exists("/sbin/blkid"))
267 			blkidcommand = "/sbin/blkid";
268 		else
269 			blkidcommand = locatecommand("blkid", tr("either"), "e2fsprogs");
270 	}
271 	else
272 		blkidcommand = "/sbin/blkid";
273 	if (QFile::exists("/sbin/mke2fs"))
274 		mke2fscommand = "/sbin/mke2fs";
275 	else
276 		mke2fscommand = locatecommand("mke2fs", tr("LiveUSB persistence"), "e2fsprogs");
277 	if (QFile::exists("/sbin/e2label"))
278 		e2labelcommand = "/sbin/e2label";
279 	else
280 		e2labelcommand = locatecommand("e2label", "Arch Linux", "e2fsprogs");
281 	if (QFile::exists("/usr/bin/mlabel"))
282 		mlabelcommand = "/usr/bin/mlabel";
283 	else
284 		mlabelcommand = locatecommand("mlabel", "Arch Linux", "mtools");
285 	syslinuxcommand = "/usr/bin/ubnsylnx";
286 	extlinuxcommand = "/usr/bin/ubnexlnx";
287 	#ifdef NOSTATIC
288 	if (QFile::exists("/usr/bin/syslinux"))
289 		syslinuxcommand = "/usr/bin/syslinux";
290 	else
291 		syslinuxcommand = locatecommand("syslinux", tr("FAT32-formatted USB drive"), "syslinux");
292 	if (QFile::exists("/usr/bin/extlinux"))
293 		extlinuxcommand = "/usr/bin/extlinux";
294 	else
295         extlinuxcommand = locatecommand("extlinux", tr("EXT2-formatted USB drive"), "extlinux");
296 	#endif
297 	sevzcommand = locatecommand("7z", tr("either"), "p7zip-full");
298 #endif // Q_OS_LINUX
299 #ifdef Q_OS_FREEBSD
300 	syslinuxcommand = locatecommand("syslinux", tr("FAT32-formatted USB drive"), "syslinux");
301 	sevzcommand = locatecommand("7z", tr("either"), "p7zip");
302 	mke2fscommand = locatecommand("mke2fs", tr("LiveUSB persistence"), "e2fsprogs");
303 #endif // Q_OS_FREEBSD
304 	ubntmpf = QDir::toNativeSeparators(QString("%1/").arg(QDir::tempPath()));
305     #ifdef Q_OS_UNIX
306     if (ubntmpf.isEmpty() || ubntmpf == "/")
307     {
308         ubntmpf = "/tmp/";
309     }
310     #endif
311     if (typeselect->findText(tr("USB Drive")) != -1)
312 		typeselect->setCurrentIndex(typeselect->findText(tr("USB Drive")));
313 	#ifdef HDDINSTALL
314 	if (typeselect->findText(tr("Hard Disk")) != -1)
315 		typeselect->setCurrentIndex(typeselect->findText(tr("Hard Disk")));
316 	#endif
317 	for (QList<QPair<QString, QString> >::const_iterator i = oppairs.constBegin(); i < oppairs.constEnd(); ++i)
318 	{
319 		QString pfirst(i->first);
320 		QString psecond(i->second);
321 		if (pfirst.contains("method", Qt::CaseInsensitive))
322 		{
323 			if (psecond.contains("distribution", Qt::CaseInsensitive))
324 				this->radioDistro->setChecked(true);
325 			else if (psecond.contains("diskimage", Qt::CaseInsensitive))
326 				this->radioFloppy->setChecked(true);
327 			else if (psecond.contains("custom", Qt::CaseInsensitive))
328 				this->radioManual->setChecked(true);
329 		}
330 		else if (pfirst.contains("distribution", Qt::CaseInsensitive))
331 		{
332 			int distidx = this->distroselect->findText(psecond, Qt::MatchFixedString);
333 			if (distidx != -1)
334 				this->distroselect->setCurrentIndex(distidx);
335 		}
336 		else if (pfirst.contains("version", Qt::CaseInsensitive))
337 		{
338 			QStringList verlist = this->distroselect->itemData(this->distroselect->currentIndex()).value<QStringList>();
339 			for (int j = 2; j < verlist.size(); ++j)
340 			{
341 				if (verlist[j].contains(psecond, Qt::CaseInsensitive))
342 				{
343 					this->dverselect->setCurrentIndex(j-2);
344 					break;
345 				}
346 			}
347 		}
348 		else if (pfirst.contains("isofile", Qt::CaseInsensitive))
349 		{
350 			this->diskimagetypeselect->setCurrentIndex(diskimagetypeselect->findText(tr("ISO")));
351 			this->FloppyPath->setText(psecond);
352             this->radioFloppy->setChecked(true);
353 		}
354 		else if (pfirst.contains("imgfile", Qt::CaseInsensitive))
355 		{
356 			this->diskimagetypeselect->setCurrentIndex(diskimagetypeselect->findText(tr("Floppy")));
357 			this->FloppyPath->setText(psecond);
358             this->radioFloppy->setChecked(true);
359 		}
360 		else if (pfirst.contains("kernelfile", Qt::CaseInsensitive))
361 		{
362 			this->KernelPath->setText(psecond);
363 		}
364 		else if (pfirst.contains("initrdfile", Qt::CaseInsensitive))
365 		{
366 			this->InitrdPath->setText(psecond);
367 		}
368 		else if (pfirst.contains("cfgfile", Qt::CaseInsensitive))
369 		{
370 			QString cfgoptstxt = getcfgkernargs(psecond, "", QStringList(), QStringList());
371 			if (cfgoptstxt.isEmpty())
372 			{
373 				cfgoptstxt = getgrubcfgargs(psecond);
374 			}
375 			this->OptionEnter->setText(cfgoptstxt);
376 		}
377 		else if (pfirst.contains("kernelopts", Qt::CaseInsensitive))
378 		{
379 			this->OptionEnter->setText(psecond);
380 		}
381 		else if (pfirst.contains("installtype", Qt::CaseInsensitive))
382 		{
383 			if (psecond.contains("Hard", Qt::CaseInsensitive) || psecond.contains("HDD", Qt::CaseInsensitive))
384 				this->typeselect->setCurrentIndex(this->typeselect->findText(tr("Hard Disk")));
385 			else
386 				this->typeselect->setCurrentIndex(this->typeselect->findText(tr("USB Drive")));
387 		}
388 		else if (pfirst.contains("targetdrive", Qt::CaseInsensitive))
389 		{
390 #ifdef Q_OS_WIN32
391 			if (!psecond.endsWith('\\'))
392 			{
393 				psecond = psecond + '\\';
394 			}
395 #endif
396 			int driveidx = this->driveselect->findText(psecond, Qt::MatchFixedString);
397 			if (driveidx != -1)
398 			{
399 				this->driveselect->setCurrentIndex(driveidx);
400 			}
401 			else
402 			{
403 				this->driveselect->addItem(psecond);
404 				this->driveselect->setCurrentIndex(this->driveselect->findText(psecond, Qt::MatchFixedString));
405 			}
406 		}
407 		else if (pfirst.contains("showcustom", Qt::CaseInsensitive))
408 		{
409 			if (psecond.contains('y', Qt::CaseInsensitive))
410 			{
411 				hideCustom = false;
412 			}
413 		}
414 		else if (pfirst.contains("nodistro", Qt::CaseInsensitive))
415 		{
416 			if (psecond.contains('y', Qt::CaseInsensitive))
417 			{
418 				radioDistro->setEnabled(false);
419 				radioDistro->hide();
420 				distroselect->setEnabled(false);
421 				distroselect->hide();
422 				dverselect->setEnabled(false);
423 				dverselect->hide();
424 				intromessage->move(intromessage->x(), intromessage->y()-20);
425 				intromessage->resize(intromessage->width(), intromessage->height() + 20);
426 			}
427 		}
428 		else if (pfirst.contains("message", Qt::CaseInsensitive))
429 		{
430 			intromessage->setText(psecond);
431 		}
432 		else if (pfirst.contains("persistentspace", Qt::CaseInsensitive))
433 		{
434 			bool isInt = false;
435 			int numMBpersistentSpace = psecond.toInt(&isInt, 10);
436 			if (isInt)
437 				this->persistencevalue->setValue(numMBpersistentSpace);
438 		}
439 		else if (pfirst.contains("testingdownload", Qt::CaseInsensitive))
440 		{
441 			if (psecond.contains('y', Qt::CaseInsensitive))
442 			{
443 				testingDownload = true;
444 				exitOnCompletion = true;
445 			}
446 		}
447 		else if (pfirst.contains("exitoncompletion", Qt::CaseInsensitive))
448 		{
449 			if (psecond.contains('y', Qt::CaseInsensitive))
450 			{
451 				exitOnCompletion = true;
452 			}
453 		}
454         else if (pfirst.contains("skipextraction", Qt::CaseInsensitive))
455         {
456             if (psecond.contains('y', Qt::CaseInsensitive))
457             {
458                 skipExtraction = true;
459             }
460         }
461 		else if (pfirst.contains("autoinstall", Qt::CaseInsensitive))
462 		{
463 			if (psecond.contains('y', Qt::CaseInsensitive))
464 			{
465 				exitOnCompletion = true;
466 				overwriteall = true;
467 				return true;
468 			}
469 		}
470 		else if (pfirst.contains("action", Qt::CaseInsensitive))
471 		{
472 			if (psecond.contains("listdistros", Qt::CaseInsensitive))
473 			{
474 				QTextStream out(stdout);
475 				for (int i = 1; i < this->distroselect->count(); ++i)
476 				{
477 					out << this->distroselect->itemText(i) << endl;
478 				}
479 				out.flush();
480 				QApplication::exit();
481 				exit(0);
482 			}
483 			else if (psecond.contains("listversions", Qt::CaseInsensitive))
484 			{
485 				QTextStream out(stdout);
486 				for (int i = 0; i < this->dverselect->count(); ++i)
487 				{
488 					out << this->dverselect->itemText(i) << endl;
489 				}
490 				out.flush();
491 				QApplication::exit();
492 				exit(0);
493 			}
494 		}
495 	}
496 	if (hideCustom)
497 	{
498 		radioManual->setEnabled(false);
499 		radioManual->hide();
500 		labelkernel->setEnabled(false);
501 		labelkernel->hide();
502 		labelinitrd->setEnabled(false);
503 		labelinitrd->hide();
504 		labeloption->setEnabled(false);
505 		labeloption->hide();
506 		KernelFileSelector->setEnabled(false);
507 		KernelFileSelector->hide();
508 		InitrdFileSelector->setEnabled(false);
509 		InitrdFileSelector->hide();
510 		CfgFileSelector->setEnabled(false);
511 		CfgFileSelector->hide();
512 		OptionEnter->setEnabled(false);
513 		OptionEnter->hide();
514 		KernelPath->setEnabled(false);
515 		KernelPath->hide();
516 		InitrdPath->setEnabled(false);
517 		InitrdPath->hide();
518 		KernelFileSelector->setEnabled(false);
519 		KernelFileSelector->hide();
520 		InitrdFileSelector->setEnabled(false);
521 		InitrdFileSelector->hide();
522 		radioLayout->removeItem(verticalSpacer);
523 	}
524 	return false;
525 }
526 
on_distroselect_currentIndexChanged(int distroselectIndex)527 void unetbootin::on_distroselect_currentIndexChanged(int distroselectIndex)
528 {
529 	dverselect->clear();
530 	if (distroselectIndex == -1)
531 		return;
532 	QStringList dverL = distroselect->itemData(distroselectIndex).value<QStringList>();
533 	for (int i = 2; i < dverL.size(); ++i)
534 	{
535 		if (!dverL.at(i).contains("someotherversion") && !dverL.at(i).isEmpty())
536 			dverselect->addItem(dverL.at(i));
537 	}
538 	if (dverselect->findText(dverL.at(0)) != -1)
539 		dverselect->setCurrentIndex(dverselect->findText(dverL.at(0)));
540 	intromessage->setText(dverL.at(1));
541 	radioDistro->setChecked(true);
542 }
543 
refreshdriveslist()544 void unetbootin::refreshdriveslist()
545 {
546 	driveselect->clear();
547 	QStringList driveslist = listcurdrives();
548 	for (int i = 0; i < driveslist.size(); ++i)
549 	{
550 	    driveselect->addItem(driveslist.at(i));
551 	}
552 }
553 
listcurdrives()554 QStringList unetbootin::listcurdrives()
555 {
556 	return listsanedrives();
557 }
558 
559 #ifdef Q_OS_MAC
is_external_drive_macos(const QString & drivename)560 bool unetbootin::is_external_drive_macos(const QString &drivename)
561 {
562     // drivename: disk3s1
563     QString device_info = callexternapp("diskutil", "info " + drivename);
564     if (device_info.contains("External"))
565     {
566         return true;
567     }
568     // stw "diskutil info" output changed; now look for line "Internal:    No"
569     QStringList infoLines = device_info.split("\n").filter("Internal");
570     for (int i = 0; i < infoLines.size(); i++) {
571         if (infoLines.at(i).contains("No"))
572             return true;
573     }
574 
575     return false;
576 }
577 #endif
578 
matchinglist(QRegExp regex,QString text)579 QStringList unetbootin::matchinglist(QRegExp regex, QString text)
580 {
581 QStringList matchinglist;
582 int pos = 0;
583 
584 while ((pos = regex.indexIn(text, pos)) != -1) {
585 	matchinglist << regex.cap(1);
586 	pos += regex.matchedLength();
587 }
588 
589 return matchinglist;
590 }
591 
listsanedrives()592 QStringList unetbootin::listsanedrives()
593 {
594 	QStringList fulldrivelist;
595 	if (typeselect->currentText() == tr("Hard Disk"))
596 	{
597 		fulldrivelist.append(QDir::toNativeSeparators(QDir::rootPath()).toUpper());
598 	}
599 	else if (typeselect->currentText() == tr("USB Drive"))
600 	{
601 		#ifdef Q_OS_WIN32
602 		QFileInfoList extdrivesList = QDir::drives();
603 		for (int i = 0; i < extdrivesList.size(); ++i)
604 		{
605 			if (QDir::toNativeSeparators(extdrivesList.at(i).path().toUpper()) != QDir::toNativeSeparators(QDir::rootPath().toUpper()) && !QDir::toNativeSeparators(extdrivesList.at(i).path().toUpper()).contains("A:") && !QDir::toNativeSeparators(extdrivesList.at(i).path().toUpper()).contains("B:"))
606 			{
607 				if (GetDriveType(LPWSTR(extdrivesList.at(i).path().toUpper().utf16())) == 2)
608 				{
609 					fulldrivelist.append(QDir::toNativeSeparators(extdrivesList.at(i).path().toUpper()));
610 				}
611 			}
612 		}
613 		#endif
614 				#ifdef Q_OS_LINUX
615 				QDir devlstdir("/dev/disk/by-id/");
616 				QFileInfoList usbfileinfoL = devlstdir.entryInfoList(QDir::NoDotAndDotDot|QDir::Files);
617 				for (int i = 0; i < usbfileinfoL.size(); ++i)
618 				{
619 //                    if (usbfileinfoL.at(i).contains(QRegExp("^usb-\\S{1,}-part\\d{1,}$")))
620 //                    {
621 //                        fulldrivelist.append(usbfileinfoL.at(i).canonicalFilePath());
622 //                    }
623                     if (usbfileinfoL.at(i).fileName().contains(QRegExp("^usb-\\S{1,}$")) ||
624                         usbfileinfoL.at(i).fileName().contains(QRegExp("^mmc-\\S{1,}$")))
625                     {
626 						if (!volidcommand.isEmpty())
627 						{
628 							if (QString(callexternapp(volidcommand, QString("-t %2").arg(usbfileinfoL.at(i).canonicalFilePath()))).contains(QRegExp("(vfat|ext2|ext3|ext4)")))
629 								fulldrivelist.append(usbfileinfoL.at(i).canonicalFilePath());
630 						}
631 						else
632 						{
633 							QString tstrblk = QString(callexternapp(blkidcommand, QString("-s TYPE %2").arg(usbfileinfoL.at(i).canonicalFilePath())));
634 							if (tstrblk.contains('='))
635 							{
636 								if (tstrblk.section('=', -1, -1).remove('"').contains(QRegExp("(vfat|ext2|ext3|ext4)")))
637 									fulldrivelist.append(usbfileinfoL.at(i).canonicalFilePath());
638 							}
639 						}
640 					}
641 				}
642 				/*
643 				QString fdisklusbdevsS = callexternapp(fdiskcommand, "-l");
644 				QStringList usbdevsL = QString(fdisklusbdevsS).split("\n").filter(QRegExp("\\.{0,}FAT|Disk\\.{0,}")).join("\n").split(" ").join("\n").split("\t").join("\n").split("\n").filter("/dev/");
645 		for (int i = 0; i < usbdevsL.size(); ++i)
646 		{
647 			if (usbdevsL.at(i).contains(":"))
648 			{
649 				if (!QString(callexternapp(volidcommand, QString("-t %2").arg(QString(usbdevsL.at(i)).remove(":")))).contains("vfat"))
650 					continue;
651 			}
652 			fulldrivelist.append(QString(usbdevsL.at(i)).remove(":"));
653 				}
654 				*/
655 		#endif
656 #ifdef Q_OS_FREEBSD
657 #ifdef __DragonFly__
658 		struct vfsconf fsconf;
659 #else
660 		struct xvfsconf fsconf;
661 #endif
662 		struct statfs *fslist;
663 
664 		/*
665 		 * Make sure that MSDOSFS is configured with the kernel.
666 		 * As a nice side effect, this would allow to compare a
667 		 * number (assigned by VFS) instead of "msdosfs" string
668 		 * when iterating over mounted filesystems.
669 		 */
670 		if (getvfsbyname("msdosfs", &fsconf) == -1)
671 			goto out;
672 
673 		/*
674 		 * Quick sanity check of the number of active mountpoints
675 		 * using the filesystem (we need mounted storage to work).
676 		 */
677 		if (fsconf.vfc_refcount < 1)
678 			goto out;
679 
680 		int numfs = getmntinfo(&fslist, MNT_NOWAIT);
681 		if (numfs < 1)
682 			goto out;
683 
684 		QRegExp pendrives_sdcards("^/dev/(da|mmcsd)\\d+");
685 
686 		for (int i = 0; i < numfs; ++i)
687 		{
688 			/*
689 			 * We're interested in MSDOSFS (FAT) filesystems
690 			 * that are mounted off removable storage (e.g.,
691 			 * USB memsticks, SD cards).  Assume that device
692 			 * names for those are /dev/da* and /dev/mmcsd*.
693 			 * (Perhaps not entirely accurate assumption.)
694 			 */
695 			if ((int)fslist[i].f_type == fsconf.vfc_typenum &&
696 				QString(fslist[i].f_mntfromname)
697 				.contains(pendrives_sdcards))
698 			{
699 				/*
700 				 * Unlike other implementations above, we
701 				 * append tuples of device name *and* the
702 				 * mount point, so we do not have to find
703 				 * mount point separately later.
704 				 */
705 				fulldrivelist.append(QString("%1:%2")
706 					.arg(fslist[i].f_mntfromname)
707 					.arg(fslist[i].f_mntonname));
708 			}
709 		}
710 #endif
711 #ifdef Q_OS_MAC
712 QString systemprofilertext = callexternapp("system_profiler", "SPStorageDataType");
713 QRegExp filesystemregex("File System: (.+)\\n");
714 QRegExp drivenameregex("BSD Name: (.+)\\n");
715 filesystemregex.setMinimal(true);
716 drivenameregex.setMinimal(true);
717 
718 QStringList filesystemlist = matchinglist(filesystemregex, systemprofilertext);
719 QStringList drivenamelist = matchinglist(drivenameregex, systemprofilertext);
720 
721 QRegExp fatfilesystems("FAT|Microsoft");
722 
723 for (int i = 0; i < filesystemlist.size(); ++i)
724 {
725 	if ((fatfilesystems.indexIn(filesystemlist.at(i),0) != -1) && is_external_drive_macos(drivenamelist.at(i))) {
726 		fulldrivelist.append("/dev/"+drivenamelist.at(i));
727 	}
728 }
729 #endif
730 	}
731 out:
732 	return fulldrivelist;
733 }
734 
735 
listalldrives()736 QStringList unetbootin::listalldrives()
737 {
738 	QStringList fulldrivelist;
739 	#ifdef Q_OS_WIN32
740 	QFileInfoList extdrivesList = QDir::drives();
741 	for (int i = 0; i < extdrivesList.size(); ++i)
742 	{
743 		fulldrivelist.append(QDir::toNativeSeparators(extdrivesList.at(i).path().toUpper()));
744 	}
745 	#endif
746 	#ifdef Q_OS_LINUX
747 		QString fdisklusbdevsS = callexternapp(fdiskcommand, "-l");
748 		QString dflusbdevsS = callexternapp(dfcommand, "");
749 		fulldrivelist = QString(dflusbdevsS).split(" ").join("\n").split("\t").join("\n").split("\n").filter("/dev/");
750 		QStringList fulldrivelist2 = QString(fdisklusbdevsS).split(" ").join("\n").split("\t").join("\n").split("\n").filter("/dev/").replaceInStrings(":", "");
751 		for (int i = 0; i < fulldrivelist2.size(); ++i)
752 		{
753 			if (!fulldrivelist.contains(fulldrivelist2.at(i)))
754 				fulldrivelist.append(fulldrivelist2.at(i));
755 		}
756 	#endif
757 #ifdef Q_OS_MAC
758 		return listsanedrives();
759 #endif
760 	return fulldrivelist;
761 }
762 
on_typeselect_currentIndexChanged(int)763 void unetbootin::on_typeselect_currentIndexChanged(int)
764 {
765 	refreshdriveslist();
766 }
767 
on_dverselect_currentIndexChanged(int)768 void unetbootin::on_dverselect_currentIndexChanged(int)
769 {
770 	radioDistro->setChecked(true);
771 }
772 
on_diskimagetypeselect_currentIndexChanged(int)773 void unetbootin::on_diskimagetypeselect_currentIndexChanged(int)
774 {
775 	radioFloppy->setChecked(true);
776 }
777 
on_FloppyFileSelector_clicked()778 void unetbootin::on_FloppyFileSelector_clicked()
779 {
780     QString nameFloppy = QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Disk Image File"), QDir::homePath(), tr("All Files") + " (*);;" + tr("ISO") + " (*.iso);;" + tr("Floppy") + " (*.img)", 0
781     #if (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0))
782     , QFileDialog::ReadOnly
783     #endif
784     ));
785 	if (QFileInfo(nameFloppy).completeSuffix().contains("iso", Qt::CaseInsensitive))
786 	{
787 		if (diskimagetypeselect->findText(tr("ISO")) != -1)
788 			diskimagetypeselect->setCurrentIndex(diskimagetypeselect->findText(tr("ISO")));
789 	}
790 	if (QFileInfo(nameFloppy).completeSuffix().contains("img", Qt::CaseInsensitive) || QFileInfo(nameFloppy).completeSuffix().contains("flp", Qt::CaseInsensitive))
791 	{
792 		if (diskimagetypeselect->findText(tr("Floppy")) != -1)
793 			diskimagetypeselect->setCurrentIndex(diskimagetypeselect->findText(tr("Floppy")));
794 	}
795 	FloppyPath->clear();
796 	FloppyPath->insert(nameFloppy);
797 	radioFloppy->setChecked(true);
798 }
799 
on_KernelFileSelector_clicked()800 void unetbootin::on_KernelFileSelector_clicked()
801 {
802     QString nameKernel = QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Kernel File"), QDir::homePath(), tr("All Files (*)"), 0
803     #if (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0))
804     , QFileDialog::ReadOnly
805     #endif
806     ));
807 	KernelPath->clear();
808 	KernelPath->insert(nameKernel);
809 	radioManual->setChecked(true);
810 }
811 
on_InitrdFileSelector_clicked()812 void unetbootin::on_InitrdFileSelector_clicked()
813 {
814     QString nameInitrd = QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Initrd File"), QDir::homePath(), tr("All Files (*)"), 0
815     #if (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0))
816     , QFileDialog::ReadOnly
817     #endif
818     ));
819 	InitrdPath->clear();
820 	InitrdPath->insert(nameInitrd);
821 	radioManual->setChecked(true);
822 }
823 
on_CfgFileSelector_clicked()824 void unetbootin::on_CfgFileSelector_clicked()
825 {
826     QString nameCfg = QFileDialog::getOpenFileName(this, tr("Open Bootloader Config File"), QDir::homePath(), tr("All Files (*)"), 0
827     #if (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0))
828     , QFileDialog::ReadOnly
829     #endif
830     );
831 	OptionEnter->clear();
832 	QString cfgoptstxt = getcfgkernargs(nameCfg, "", QStringList(), QStringList());
833 	if (cfgoptstxt.isEmpty())
834 	{
835 		cfgoptstxt = getgrubcfgargs(nameCfg);
836 	}
837 	OptionEnter->insert(cfgoptstxt);
838 	radioManual->setChecked(true);
839 }
840 
on_cancelbutton_clicked()841 void unetbootin::on_cancelbutton_clicked()
842 {
843 	close();
844 }
845 
on_okbutton_clicked()846 void unetbootin::on_okbutton_clicked()
847 {
848     if (typeselect->currentIndex() == typeselect->findText(tr("USB Drive")) && driveselect->currentText().isEmpty() && !testingDownload)
849 	{
850 		QMessageBox unotenoughinputmsgb;
851 		unotenoughinputmsgb.setIcon(QMessageBox::Information);
852 		unotenoughinputmsgb.setWindowTitle(tr("Insert a USB flash drive"));
853 		unotenoughinputmsgb.setText(tr("No USB flash drives were found. If you have already inserted a USB drive, try reformatting it as FAT32."));
854 		unotenoughinputmsgb.setStandardButtons(QMessageBox::Ok);
855 		switch (unotenoughinputmsgb.exec())
856 		{
857 			case QMessageBox::Ok:
858 				break;
859 			default:
860 				break;
861 		}
862 		refreshdriveslist(); // stw give it a chance to detect a new drive
863 	}
864 #ifdef Q_OS_MAC
865     if (locatemountpoint(driveselect->currentText()) == "NOT MOUNTED" && !testingDownload)
866 		callexternapp("diskutil", "mount "+driveselect->currentText());
867 #endif
868 	#ifdef Q_OS_LINUX
869 	else if (typeselect->currentIndex() == typeselect->findText(tr("USB Drive")) && locatemountpoint(driveselect->currentText()) == "NOT MOUNTED")
870 	{
871 		QMessageBox merrordevnotmountedmsgbx;
872 		merrordevnotmountedmsgbx.setIcon(QMessageBox::Warning);
873 		merrordevnotmountedmsgbx.setWindowTitle(QString(tr("%1 not mounted")).arg(driveselect->currentText()));
874 		merrordevnotmountedmsgbx.setText(QString(tr("You must first mount the USB drive %1 to a mountpoint. Most distributions will do this automatically after you remove and reinsert the USB drive.")).arg(driveselect->currentText()));
875 		merrordevnotmountedmsgbx.setStandardButtons(QMessageBox::Ok);
876 		switch (merrordevnotmountedmsgbx.exec())
877 		{
878 			case QMessageBox::Ok:
879 				break;
880 			default:
881 				break;
882 		}
883 	}
884 	#endif
885 	else if (radioDistro->isChecked() && distroselect->currentIndex() == distroselect->findText(unetbootin::tr("== Select Distribution ==")))
886 	{
887 		QMessageBox dnotenoughinputmsgb;
888 		dnotenoughinputmsgb.setIcon(QMessageBox::Information);
889 		dnotenoughinputmsgb.setWindowTitle(tr("Select a distro"));
890 		dnotenoughinputmsgb.setText(tr("You must select a distribution to load."));
891 		dnotenoughinputmsgb.setStandardButtons(QMessageBox::Ok);
892 		switch (dnotenoughinputmsgb.exec())
893 		{
894 			case QMessageBox::Ok:
895 				break;
896 			default:
897 				break;
898 		}
899 	}
900 	else if (radioFloppy->isChecked() && FloppyPath->text().isEmpty())
901 	{
902 		QMessageBox fnotenoughinputmsgb;
903 		fnotenoughinputmsgb.setIcon(QMessageBox::Information);
904 		fnotenoughinputmsgb.setWindowTitle(tr("Select a disk image file"));
905 		fnotenoughinputmsgb.setText(tr("You must select a disk image file to load."));
906 		fnotenoughinputmsgb.setStandardButtons(QMessageBox::Ok);
907 		switch (fnotenoughinputmsgb.exec())
908 		{
909 			case QMessageBox::Ok:
910 				break;
911 			default:
912 				break;
913 		}
914 	}
915 	else if (radioManual->isChecked() && KernelPath->text().isEmpty())
916 	{
917 		QMessageBox knotenoughinputmsgb;
918 		knotenoughinputmsgb.setIcon(QMessageBox::Information);
919 		knotenoughinputmsgb.setWindowTitle(tr("Select a kernel and/or initrd file"));
920 		knotenoughinputmsgb.setText(tr("You must select a kernel and/or initrd file to load."));
921 		knotenoughinputmsgb.setStandardButtons(QMessageBox::Ok);
922 		switch (knotenoughinputmsgb.exec())
923 		{
924 			case QMessageBox::Ok:
925 				break;
926 			default:
927 				break;
928 		}
929 	}
930 	else if (radioFloppy->isChecked() && !QFile::exists(FloppyPath->text()) && !FloppyPath->text().startsWith("http://") && !FloppyPath->text().startsWith("ftp://"))
931 	{
932 		QMessageBox ffnotexistsmsgb;
933 		ffnotexistsmsgb.setIcon(QMessageBox::Information);
934 		ffnotexistsmsgb.setWindowTitle(tr("Diskimage file not found"));
935 		ffnotexistsmsgb.setText(tr("The specified diskimage file %1 does not exist.").arg(FloppyPath->text()));
936 		ffnotexistsmsgb.setStandardButtons(QMessageBox::Ok);
937 		switch (ffnotexistsmsgb.exec())
938 		{
939 			case QMessageBox::Ok:
940 				break;
941 			default:
942 				break;
943 		}
944 	}
945 	else if (radioManual->isChecked() && !QFile::exists(KernelPath->text()) && !KernelPath->text().startsWith("http://") && !KernelPath->text().startsWith("ftp://"))
946 	{
947 		QMessageBox kfnotexistsmsgb;
948 		kfnotexistsmsgb.setIcon(QMessageBox::Information);
949 		kfnotexistsmsgb.setWindowTitle(tr("Kernel file not found"));
950 		kfnotexistsmsgb.setText(tr("The specified kernel file %1 does not exist.").arg(KernelPath->text()));
951 		kfnotexistsmsgb.setStandardButtons(QMessageBox::Ok);
952 		switch (kfnotexistsmsgb.exec())
953 		{
954 			case QMessageBox::Ok:
955 				break;
956 			default:
957 				break;
958 		}
959 	}
960 	else if (radioManual->isChecked() && InitrdPath->text().trimmed() != "" && !QFile::exists(InitrdPath->text())  && !InitrdPath->text().startsWith("http://") && !InitrdPath->text().startsWith("ftp://"))
961 	{
962 		QMessageBox ifnotexistsmsgb;
963 		ifnotexistsmsgb.setIcon(QMessageBox::Information);
964 		ifnotexistsmsgb.setWindowTitle(tr("Initrd file not found"));
965 		ifnotexistsmsgb.setText(tr("The specified initrd file %1 does not exist.").arg(InitrdPath->text()));
966 		ifnotexistsmsgb.setStandardButtons(QMessageBox::Ok);
967 		switch (ifnotexistsmsgb.exec())
968 		{
969 			case QMessageBox::Ok:
970 				break;
971 			default:
972 				break;
973 		}
974 	}
975 	else
976 	{
977 		runinst();
978 	}
979 }
980 
on_fexitbutton_clicked()981 void unetbootin::on_fexitbutton_clicked()
982 {
983 	close();
984 }
985 
displayfisize(quint64 fisize)986 QString unetbootin::displayfisize(quint64 fisize)
987 {
988 	if (fisize < 10000)
989 	{
990 		return QString("%1 B").arg(fisize);
991 	}
992 	else if (fisize < 10240000)
993 	{
994 		return QString("%1 KB").arg(fisize / 1024);
995 	}
996 	else
997 	{
998 		return QString("%1 MB").arg(fisize / 1048576);
999 	}
1000 }
1001 
listarchiveconts(QString archivefile)1002 QPair<QPair<QStringList, QList<quint64> >, QStringList> unetbootin::listarchiveconts(QString archivefile)
1003 {
1004 	#ifdef Q_OS_WIN32
1005 	if (sevzcommand.isEmpty())
1006 	{
1007 		installsvzip();
1008 	}
1009 	randtmpfile tmplsF(ubntmpf, "ufl");
1010 	callexternapp(getenv("COMSPEC"), QString("/c \"\"%1\" -bd -slt l \"%2\" > \"%3\"\"").arg(sevzcommand).arg(QFileInfo(archivefile).absoluteFilePath()).arg(QFileInfo(tmplsF).absoluteFilePath()));
1011 	tmplsF.open(QIODevice::ReadOnly | QIODevice::Text);
1012 	QTextStream tmplsS(&tmplsF);
1013 	#endif
1014 	#ifdef Q_OS_UNIX
1015     QString sevzlcommandout = callexternapp(sevzcommand, QString("-bd -slt l \"%1\"").arg(QFileInfo(archivefile).absoluteFilePath()));
1016 	QTextStream tmplsS(&sevzlcommandout);
1017 	#endif
1018 	QString tmplsL;
1019 	QStringList tmplsSLF;
1020 	QStringList tmplsSLD;
1021 	QList<quint64> tmplsSLFS;
1022 	QString tmplsN;
1023 	QString tmplsFS;
1024 	while (!tmplsS.atEnd())
1025 	{
1026 		tmplsL = tmplsS.readLine();
1027 		if (tmplsL.contains("Path = "))
1028 		{
1029 			if (tmplsL.contains("Path = [BOOT]"))
1030 				continue;
1031 			if (tmplsL == QString("Path = %1").arg(QFileInfo(archivefile).absoluteFilePath()))
1032 				continue;
1033 			if (tmplsL == QString("Path = %1").arg(QDir::toNativeSeparators(QFileInfo(archivefile).absoluteFilePath())))
1034 				continue;
1035 			tmplsN = tmplsS.readLine();
1036 			if (tmplsN.contains("Folder = 1") || tmplsN.contains("Folder = +"))
1037 			{
1038 				tmplsSLD.append(tmplsL.remove("Path = "));
1039 			}
1040 			else
1041 			{
1042 				tmplsSLF.append(tmplsL.remove("Path = "));
1043 				tmplsFS = QString(tmplsS.readLine()).remove("Size = ").trimmed();
1044 				tmplsSLFS.append(tmplsFS.toULongLong());
1045 			}
1046 		}
1047 	}
1048 	#ifdef Q_OS_WIN32
1049 	tmplsF.close();
1050 	rmFile(tmplsF);
1051 	#endif
1052 	return qMakePair(qMakePair(tmplsSLF, tmplsSLFS), tmplsSLD);
1053 }
1054 
overwritefileprompt(QString ovwfileloc)1055 bool unetbootin::overwritefileprompt(QString ovwfileloc)
1056 {
1057 	if (overwriteall)
1058 	{
1059 		rmFile(ovwfileloc);
1060 		return true;
1061 	}
1062 	QMessageBox overwritefilemsgbx;
1063 	overwritefilemsgbx.setIcon(QMessageBox::Warning);
1064 	overwritefilemsgbx.setWindowTitle(QString(tr("%1 exists, overwrite?")).arg(ovwfileloc));
1065 	overwritefilemsgbx.setText(QString(tr("The file %1 already exists. Press 'Yes to All' to overwrite it and not be prompted again, 'Yes' to overwrite files on an individual basis, and 'No' to retain your existing version. If in doubt, press 'Yes to All'.")).arg(ovwfileloc));
1066 	overwritefilemsgbx.setStandardButtons(QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No);
1067 	switch (overwritefilemsgbx.exec())
1068 	{
1069 		case QMessageBox::Yes:
1070 		{
1071 			rmFile(ovwfileloc);
1072 			return true;
1073 		}
1074 		case QMessageBox::YesToAll:
1075 		{
1076 			rmFile(ovwfileloc);
1077 			overwriteall = true;
1078 			return true;
1079 		}
1080 		case QMessageBox::No:
1081 			return false;
1082 		default:
1083 			return false;
1084 	}
1085 }
1086 
ignoreoutofspaceprompt(QString destindir)1087 bool unetbootin::ignoreoutofspaceprompt(QString destindir)
1088 {
1089 	QMessageBox overwritefilemsgbx;
1090 	overwritefilemsgbx.setIcon(QMessageBox::Warning);
1091 	overwritefilemsgbx.setWindowTitle(QString(tr("%1 is out of space, abort installation?")).arg(destindir));
1092 	overwritefilemsgbx.setText(QString(tr("The directory %1 is out of space. Press 'Yes' to abort installation, 'No' to ignore this error and attempt to continue installation, and 'No to All' to ignore all out-of-space errors.")).arg(destindir));
1093 	overwritefilemsgbx.setStandardButtons(QMessageBox::Yes | QMessageBox::NoToAll | QMessageBox::No);
1094 	switch (overwritefilemsgbx.exec())
1095 	{
1096 		case QMessageBox::Yes:
1097 		{
1098 			QApplication::quit();
1099 			return false;
1100 		}
1101 		case QMessageBox::No:
1102 		{
1103 			return true;
1104 		}
1105 		case QMessageBox::NoToAll:
1106 		{
1107 			this->ignoreoutofspace = true;
1108 			return true;
1109 		}
1110 		default:
1111 			return true;
1112 	}
1113 }
1114 
extractfile(QString filepath,QString destinfileL,QString archivefile)1115 bool unetbootin::extractfile(QString filepath, QString destinfileL, QString archivefile)
1116 {
1117 	#ifdef Q_OS_UNIX
1118 	if (installType != tr("USB Drive") && filepath.contains("boot/grub")) // don't nuke grub config
1119 		return false;
1120 	#endif
1121 	QString destindir = QFileInfo(destinfileL).dir().absolutePath();
1122 	QString destinfilename = QString("%1/%2").arg(destindir).arg(QFileInfo(destinfileL).fileName());
1123 	QString filepathfilename = QString("%1/%2").arg(destindir).arg(QFileInfo(filepath).fileName());
1124 	if (QFile::exists(filepathfilename))
1125 	{
1126 		if (!overwritefileprompt(filepathfilename))
1127 			return false;
1128 	}
1129 	if (QFile::exists(destinfilename))
1130 	{
1131 		if (!overwritefileprompt(destinfilename))
1132 			return false;
1133 	}
1134 	#ifdef Q_OS_WIN32
1135 	if (sevzcommand.isEmpty())
1136 	{
1137 		installsvzip();
1138 	}
1139 	#endif
1140 	callexternapp(sevzcommand, QString("-bd  -aos -o\"%1\" e \"%2\" \"%3\"").arg(QDir::toNativeSeparators(destindir), QDir::toNativeSeparators(archivefile), QDir::toNativeSeparators(filepath)));
1141 	int retv;
1142 	if (QFileInfo(filepathfilename).absoluteFilePath() == QFileInfo(destinfilename).absoluteFilePath())
1143 	{
1144 		retv = true;
1145 	}
1146 	else
1147 	{
1148 		retv = QFile::rename(filepathfilename, destinfilename);
1149 	}
1150 	this->checkifoutofspace(destindir);
1151 	return retv;
1152 }
1153 
checkifoutofspace(QString destindir)1154 bool unetbootin::checkifoutofspace(QString destindir)
1155 {
1156 	if  (ignoreoutofspace == true)
1157 		return false;
1158 	bool outofspace = false;
1159 	#ifdef Q_OS_UNIX
1160 	struct statfs diskstatS;
1161 	if (!statfs(QString(destindir+"/.").toLatin1(), &diskstatS))
1162 	{
1163 		/*
1164 		 * Refuse to work if available disk space is less than 1MB
1165 		 * (1024KB).  Even this seems very low, but original value
1166 		 * of 1024 bytes was simply ridiculous.
1167 		 */
1168 		if (diskstatS.f_bsize / 1024 * diskstatS.f_bavail < 1024)
1169 			outofspace = true;
1170 	}
1171 	#endif
1172 	#ifdef Q_OS_WIN32
1173 	ULARGE_INTEGER FreeBytesAvailable;
1174 	ULARGE_INTEGER TotalNumberOfBytes;
1175 	ULARGE_INTEGER TotalNumberOfFreeBytes;
1176 	if (GetDiskFreeSpaceExA(destindir.toUtf8(), &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
1177 	{
1178 		if (FreeBytesAvailable.QuadPart < 1024)
1179 			outofspace = true;
1180 	}
1181 	#endif
1182 	if (outofspace == true)
1183 	{
1184 		return !ignoreoutofspaceprompt(destindir);
1185 	}
1186 	return false;
1187 }
1188 
locatekernel(QString archivefile,QPair<QStringList,QList<quint64>> archivefileconts)1189 QString unetbootin::locatekernel(QString archivefile, QPair<QStringList, QList<quint64> > archivefileconts)
1190 {
1191 	pdesc1->setText(tr("Locating kernel file in %1").arg(archivefile));
1192 	if (issalt) {
1193 		// The grub2 boot loader is return,
1194 		// it is prepended with a Linux header,
1195 		// so that syslinux can chainload to it.
1196 		// The embeded configuration file will find the correct prefix using the .live file at the root of the USB key.
1197 		return "boot/grub2-linux.img";
1198 	}
1199 	else
1200 	{
1201         QStringList kernelnames = QStringList() << "vmlinuz" << "vmlinux" << "bzImage" << "kernel" << "sabayon" << "gentoo" << "linux26" << "linux24" << "bsd" << "unix" << "linux" << "rescue" << "xpud" << "bzI" << "kexec" << "vmlinuz.efi";
1202 	QStringList tnarchivefileconts;
1203 	QStringList narchivefileconts;
1204 	QString curarcitm;
1205 	for (int i = 0; i < archivefileconts.second.size(); ++i)
1206 	{
1207 //		curarcitm = archivefileconts.first.at(i).right(archivefileconts.first.at(i).size() - archivefileconts.first.at(i).lastIndexOf(QDir::toNativeSeparators("/")) - 1);
1208 //		if (curarcitm.contains("isolinux", Qt::CaseInsensitive) || curarcitm.contains("memtest", Qt::CaseInsensitive) || curarcitm.contains("system.map", Qt::CaseInsensitive) || curarcitm.contains(".efimg", Qt::CaseInsensitive) || curarcitm.contains(".jpg", Qt::CaseInsensitive) || curarcitm.contains(".png", Qt::CaseInsensitive) || curarcitm.contains(".pdf", Qt::CaseInsensitive) || curarcitm.contains(".txt", Qt::CaseInsensitive) || curarcitm.contains(".pcx", Qt::CaseInsensitive) || curarcitm.contains(".rle", Qt::CaseInsensitive) || curarcitm.contains(".fnt", Qt::CaseInsensitive) || curarcitm.contains(".msg", Qt::CaseInsensitive) || curarcitm.contains(".cat", Qt::CaseInsensitive) || curarcitm.contains(".tar", Qt::CaseInsensitive) || curarcitm.contains(".psd", Qt::CaseInsensitive) || curarcitm.contains(".xcf", Qt::CaseInsensitive) || curarcitm.contains(".bmp", Qt::CaseInsensitive) || curarcitm.contains(".svg", Qt::CaseInsensitive))
1209 //		{
1210 //			continue;
1211 //		}
1212 //		if (filteroutlist(curarcitm, ignoredtypesbothRL+ignoredtypeskernelRL).isEmpty())
1213 //		{
1214 //			continue;
1215 //		}
1216 		if (archivefileconts.second.at(i) > 614400 && archivefileconts.second.at(i) < 20971520) // between 600 KB and 20 MB
1217 		{
1218 			tnarchivefileconts.append(archivefileconts.first.at(i));
1219 		}
1220 	}
1221 	narchivefileconts = filteroutlistL(tnarchivefileconts, ignoredtypesbothRL+ignoredtypeskernelRL);
1222 	for (int i = 0; i < kernelnames.size(); ++i)
1223 	{
1224 		for (int j = 0; j < narchivefileconts.size(); ++j)
1225 		{
1226 			if (narchivefileconts.at(j).right(narchivefileconts.at(j).size() - narchivefileconts.at(j).lastIndexOf(QDir::toNativeSeparators("/")) - 1).contains(kernelnames.at(i), Qt::CaseInsensitive))
1227 			{
1228 				return narchivefileconts.at(j);
1229 			}
1230 		}
1231 	}
1232 	pdesc1->setText("");
1233 	return "";
1234 }
1235 }
1236 
extractkernel(QString archivefile,QString kernoutputfile,QPair<QStringList,QList<quint64>> archivefileconts)1237 bool unetbootin::extractkernel(QString archivefile, QString kernoutputfile, QPair<QStringList, QList<quint64> > archivefileconts)
1238 {
1239 	QString kfloc = locatekernel(archivefile, archivefileconts);
1240 	if (kfloc == "")
1241 		return false;
1242 	pdesc1->setText(tr("Copying kernel file from %1").arg(kfloc));
1243 	return extractfile(kfloc, kernoutputfile, archivefile);
1244 }
1245 
locateinitrd(QString archivefile,QPair<QStringList,QList<quint64>> archivefileconts)1246 QString unetbootin::locateinitrd(QString archivefile, QPair<QStringList, QList<quint64> > archivefileconts)
1247 {
1248 	pdesc1->setText(tr("Locating initrd file in %1").arg(archivefile));
1249 	QStringList kernelnames = QStringList() << "initrd.img.gz" << "initrd.lz" << "initrd.igz" << "initrd.gz" << "initrd.xz" << "initrd.lzma" << "initrd.img" << "initramfs.gz" << "initramfs.img" << "initrd" << "initramfs" << "minirt" << "miniroot" << "sabayon.igz" << "gentoo.igz" << "archlive.img" << "rootfs.gz" << ".igz" << ".cgz" << ".img" << "rootfs" << "fs.gz" << "root.gz" << ".gz" << "initram" << "initr" << "init" << "ram" << ".lz" << ".lzma" << ".xz";
1250 	QStringList tnarchivefileconts;
1251 	QStringList narchivefileconts;
1252 	QString curarcitm;
1253 	for (int i = 0; i < archivefileconts.second.size(); ++i)
1254 	{
1255 		curarcitm = archivefileconts.first.at(i).right(archivefileconts.first.at(i).size() - archivefileconts.first.at(i).lastIndexOf(QDir::toNativeSeparators("/")) - 1);
1256 //		if (curarcitm.contains("isolinux", Qt::CaseInsensitive) || curarcitm.contains("memtest", Qt::CaseInsensitive) || curarcitm.contains("system.map", Qt::CaseInsensitive) || curarcitm.contains(".efimg", Qt::CaseInsensitive) || curarcitm.contains(".jpg", Qt::CaseInsensitive) || curarcitm.contains(".png", Qt::CaseInsensitive) || curarcitm.contains(".pdf", Qt::CaseInsensitive) || curarcitm.contains(".txt", Qt::CaseInsensitive) || curarcitm.contains(".pcx", Qt::CaseInsensitive) || curarcitm.contains(".rle", Qt::CaseInsensitive) || curarcitm.contains(".fnt", Qt::CaseInsensitive) || curarcitm.contains(".msg", Qt::CaseInsensitive) || curarcitm.contains(".cat", Qt::CaseInsensitive) || curarcitm.contains(".tar", Qt::CaseInsensitive) || curarcitm.contains(".psd", Qt::CaseInsensitive) || curarcitm.contains(".xcf", Qt::CaseInsensitive) || curarcitm.contains(".bmp", Qt::CaseInsensitive) || curarcitm.contains(".svg", Qt::CaseInsensitive))
1257 //		{
1258 //			continue;
1259 //		}
1260 //		if (filteroutlist(curarcitm, ignoredtypesbothRL+ignoredtypesinitrdRL).isEmpty())
1261 //		{
1262 //			continue;
1263 //		}
1264         if (archivefileconts.second.at(i) >= 128000 && archivefileconts.second.at(i) < 314572800) // between 128 KB and 300 MB
1265 		{
1266 			tnarchivefileconts.append(archivefileconts.first.at(i));
1267 		}
1268 	}
1269 	narchivefileconts = filteroutlistL(tnarchivefileconts, ignoredtypesbothRL+ignoredtypesinitrdRL);
1270 	for (int i = 0; i < kernelnames.size(); ++i)
1271 	{
1272 		for (int j = 0; j < narchivefileconts.size(); ++j)
1273 		{
1274 			if (narchivefileconts.at(j).right(narchivefileconts.at(j).size() - narchivefileconts.at(j).lastIndexOf(QDir::toNativeSeparators("/")) - 1).contains(kernelnames.at(i), Qt::CaseInsensitive))
1275 			{
1276 				return narchivefileconts.at(j);
1277 			}
1278 		}
1279 	}
1280 	pdesc1->setText("");
1281 	return "";
1282 }
1283 
extractinitrd(QString archivefile,QString kernoutputfile,QPair<QStringList,QList<quint64>> archivefileconts)1284 bool unetbootin::extractinitrd(QString archivefile, QString kernoutputfile, QPair<QStringList, QList<quint64> > archivefileconts)
1285 {
1286 	QString kfloc = locateinitrd(archivefile, archivefileconts);
1287 	if (kfloc == "")
1288 		return false;
1289 	pdesc1->setText(tr("Copying initrd file from %1").arg(kfloc));
1290 	return extractfile(kfloc, kernoutputfile, archivefile);
1291 }
1292 
extractcfg(QString archivefile,QStringList archivefileconts)1293 QString unetbootin::extractcfg(QString archivefile, QStringList archivefileconts)
1294 {
1295 	pdesc1->setText(tr("Extracting bootloader configuration"));
1296 	QString saltpcfg;
1297 	QString grubpcfg;
1298 	QString syslinuxpcfg;
1299 	QStringList saltdetectfiles = QStringList() << "boot/grub2-linux.img" << "boot/grub/salt.env";
1300 	QStringList grubcfgtypes = QStringList() << "menu.lst" << "grub.conf";
1301 	QStringList mlstfoundfiles;
1302 	int saltDetected = 0; // must be equals to saltdetectfiles.size() to be considered as detected
1303 	for (int i = 0; i < saltdetectfiles.size(); ++i)
1304 	{
1305 		mlstfoundfiles = archivefileconts.filter(saltdetectfiles.at(i), Qt::CaseInsensitive);
1306 		if (!mlstfoundfiles.isEmpty())
1307 		{
1308 			saltDetected++;
1309 		}
1310 	}
1311 	if (saltDetected == saltdetectfiles.size()) {
1312 		saltpcfg = SALT_DETECTED; // not a real config, but used to inform that SaLT has been detected.
1313 	}
1314 	else
1315 	{
1316     for (int i = 0; i < grubcfgtypes.size(); ++i)
1317 	{
1318 		mlstfoundfiles = archivefileconts.filter(grubcfgtypes.at(i), Qt::CaseInsensitive);
1319 		if (!mlstfoundfiles.isEmpty())
1320 		{
1321 			for (int j = 0; j < mlstfoundfiles.size(); ++j)
1322 			{
1323 				randtmpfile mlstftf(ubntmpf, "lst");
1324 				extractfile(archivefileconts.filter(grubcfgtypes.at(i), Qt::CaseInsensitive).at(j), mlstftf.fileName(), archivefile);
1325 				grubpcfg = getgrubcfgargs(mlstftf.fileName()).trimmed();
1326 				rmFile(mlstftf);
1327 				if (!grubpcfg.isEmpty())
1328 					break;
1329 			}
1330 		}
1331 		if (!grubpcfg.isEmpty())
1332 			break;
1333 	}
1334 	QStringList syslinuxcfgtypes = QStringList() << "syslinux.cfg" << "isolinux.cfg" << "extlinux.cfg" << "pxelinux.cfg" << "grubenv" << "menu_en.cfg" << "en.cfg" << "extlinux.conf" << "grub.cfg" << ".cfg";
1335 	QStringList lcfgfoundfiles;
1336 	for (int i = 0; i < syslinuxcfgtypes.size(); ++i)
1337 	{
1338 		lcfgfoundfiles = archivefileconts.filter(syslinuxcfgtypes.at(i), Qt::CaseInsensitive);
1339 		if (!lcfgfoundfiles.isEmpty())
1340 		{
1341 			for (int j = 0; j < lcfgfoundfiles.size(); ++j)
1342 			{
1343 				randtmpfile ccfgftf(ubntmpf, "cfg");
1344 				extractfile(archivefileconts.filter(syslinuxcfgtypes.at(i), Qt::CaseInsensitive).at(j), ccfgftf.fileName(), archivefile);
1345 				if (lcfgfoundfiles.at(j).contains("grubenv"))
1346 					loadgrub2env(ccfgftf.fileName());
1347 				else if (lcfgfoundfiles.at(j).contains("grub"))
1348 					syslinuxpcfg = getgrub2cfgargs(ccfgftf.fileName(), archivefile, archivefileconts, QStringList() << lcfgfoundfiles.at(j)).trimmed();
1349 				else
1350 					syslinuxpcfg = getcfgkernargs(ccfgftf.fileName(), archivefile, archivefileconts, QStringList() << lcfgfoundfiles.at(j)).trimmed();
1351 				rmFile(ccfgftf);
1352 				if (!syslinuxpcfg.isEmpty())
1353 					break;
1354 			}
1355 		}
1356 		if (!syslinuxpcfg.isEmpty())
1357 			break;
1358 	}
1359 	}
1360 	if (!saltpcfg.isEmpty()) {
1361 		return saltpcfg;
1362 	}
1363 	else if (syslinuxpcfg.isEmpty())
1364 	{
1365 		return grubpcfg;
1366 	}
1367 	else
1368 	{
1369 		return syslinuxpcfg;
1370 	}
1371 }
1372 
extractcfgL(QString archivefile,QStringList archivefileconts)1373 QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > unetbootin::extractcfgL(QString archivefile, QStringList archivefileconts)
1374 {
1375 	pdesc1->setText(tr("Extracting bootloader configuration"));
1376 	QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > grubpcfgPL;
1377 	QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > syslinuxpcfgPL;
1378 	QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > combinedcfgPL;
1379 	QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > filteredcfgPL;
1380 	QStringList grubcfgtypes = QStringList() << "menu.lst" << "grub.conf";
1381 	QStringList mlstfoundfiles;
1382 	for (int i = 0; i < grubcfgtypes.size(); ++i)
1383 	{
1384 		mlstfoundfiles = archivefileconts.filter(grubcfgtypes.at(i), Qt::CaseInsensitive);
1385 		if (!mlstfoundfiles.isEmpty())
1386 		{
1387 			for (int j = 0; j < mlstfoundfiles.size(); ++j)
1388 			{
1389 				randtmpfile mlstftf(ubntmpf, "lst");
1390 				extractfile(archivefileconts.filter(grubcfgtypes.at(i), Qt::CaseInsensitive).at(j), mlstftf.fileName(), archivefile);
1391 				grubpcfgPL = getgrubcfgargsL(mlstftf.fileName());
1392 				rmFile(mlstftf);
1393 				combinedcfgPL.first.first += grubpcfgPL.first.first;
1394 				combinedcfgPL.first.second += grubpcfgPL.first.second;
1395 				combinedcfgPL.second.first += grubpcfgPL.second.first;
1396 				combinedcfgPL.second.second += grubpcfgPL.second.second;
1397 //				if (!grubpcfg.isEmpty())
1398 //					break;
1399 			}
1400 		}
1401 //		if (!grubpcfg.isEmpty())
1402 //			break;
1403 	}
1404 	QStringList syslinuxcfgtypes = QStringList() << "syslinux.cfg" << "isolinux.cfg" << "extlinux.cfg" << "pxelinux.cfg" << "grubenv" << "extlinux.conf" << "grub.cfg";
1405 	QStringList lcfgfoundfiles;
1406 	for (int i = 0; i < syslinuxcfgtypes.size(); ++i)
1407 	{
1408 		lcfgfoundfiles = archivefileconts.filter(syslinuxcfgtypes.at(i), Qt::CaseInsensitive);
1409 		if (!lcfgfoundfiles.isEmpty())
1410 		{
1411 			for (int j = 0; j < lcfgfoundfiles.size(); ++j)
1412 			{
1413 				randtmpfile ccfgftf(ubntmpf, "cfg");
1414                 extractfile(archivefileconts.filter(syslinuxcfgtypes.at(i), Qt::CaseInsensitive).at(j), ccfgftf.fileName(), archivefile);
1415 				if (lcfgfoundfiles.at(j).contains("grubenv"))
1416 					loadgrub2env(ccfgftf.fileName());
1417 				else if (lcfgfoundfiles.at(j).contains("grub"))
1418 					syslinuxpcfgPL = getgrub2cfgargsL(ccfgftf.fileName(), archivefile, archivefileconts, QStringList() << lcfgfoundfiles.at(j));
1419 				else
1420 					syslinuxpcfgPL = getcfgkernargsL(ccfgftf.fileName(), archivefile, archivefileconts, QStringList() << lcfgfoundfiles.at(j));
1421 				rmFile(ccfgftf);
1422 				combinedcfgPL.first.first += syslinuxpcfgPL.first.first;
1423 				combinedcfgPL.first.second += syslinuxpcfgPL.first.second;
1424 				combinedcfgPL.second.first += syslinuxpcfgPL.second.first;
1425 				combinedcfgPL.second.second += syslinuxpcfgPL.second.second;
1426 //				if (!syslinuxpcfg.isEmpty())
1427 //					break;
1428 			}
1429 		}
1430 //		if (!syslinuxpcfg.isEmpty())
1431 //			break;
1432 	}
1433 	/*
1434 	if (syslinuxpcfg.isEmpty())
1435 	{
1436 		return grubpcfg;
1437 	}
1438 	else
1439 	{
1440 		return syslinuxpcfg;
1441 	}
1442 	*/
1443 #ifdef NOINITRD
1444     for (int i = 0; i < combinedcfgPL.first.second.size(); ++i)
1445     {
1446         combinedcfgPL.first.second[i] = "";
1447     }
1448     for (int i = 0; i < combinedcfgPL.second.second.size(); ++i)
1449     {
1450         combinedcfgPL.second.second[i] = "";
1451     }
1452 #endif
1453 	for (int i = 0; i < combinedcfgPL.first.first.size(); ++i)
1454 	{
1455 		bool isduplicate = false;
1456 		for (int j = 0; j < filteredcfgPL.second.first.size(); ++j)
1457 		{
1458 			if (filteredcfgPL.second.first.at(j) == combinedcfgPL.second.first.at(i)) // duplicate title
1459 			{
1460 				isduplicate = true;
1461 				break;
1462 			}
1463 		}
1464 		if (isduplicate)
1465 			continue;
1466 		if (combinedcfgPL.first.first.at(i) == kernelLoc && combinedcfgPL.first.second.at(i) == initrdLoc && combinedcfgPL.second.first.at(i).contains("Untitled Entry") && combinedcfgPL.second.second.at(i).isEmpty())
1467 			continue;
1468 //		else if (filteredcfgPL.second.first.contains(combinedcfgPL.second.first.at(i)))
1469 //			continue;
1470 		else
1471 		{
1472 			if (combinedcfgPL.first.first.at(i).isEmpty())
1473 				filteredcfgPL.first.first.append(kernelLoc);
1474 			else
1475 			{
1476 				QString indvkrnloc = getfullarchivepath(combinedcfgPL.first.first.at(i), archivefileconts);
1477 				if (indvkrnloc.isEmpty())
1478 					filteredcfgPL.first.first.append(kernelLoc);
1479 				else
1480 					filteredcfgPL.first.first.append(indvkrnloc);
1481 			}
1482 //			filteredcfgPL.first.first.append(combinedcfgPL.first.first.at(i));
1483 			if (combinedcfgPL.first.second.at(i).isEmpty())
1484 				filteredcfgPL.first.second.append(kernelLoc);
1485 			else
1486 			{
1487 				QString indvitrloc = getfullarchivepath(combinedcfgPL.first.second.at(i), archivefileconts);
1488 				if (indvitrloc.isEmpty())
1489 				{
1490 					filteredcfgPL.first.second.append(initrdLoc);
1491 				}
1492 				else
1493 					filteredcfgPL.first.second.append(indvitrloc);
1494 			}
1495 //			filteredcfgPL.first.second.append(combinedcfgPL.first.second.at(i));
1496 			filteredcfgPL.second.first.append(combinedcfgPL.second.first.at(i));
1497 			filteredcfgPL.second.second.append(combinedcfgPL.second.second.at(i));
1498 		}
1499 	}
1500     if (redundanttopleveldir && !redundantrootdirname.isEmpty())
1501     {
1502         for (int i = 0; i < filteredcfgPL.first.second.size(); ++i)
1503         {
1504             if (filteredcfgPL.first.second.at(i).startsWith(redundantrootdirname))
1505             {
1506                 filteredcfgPL.first.second[i] = filteredcfgPL.first.second[i].mid(redundantrootdirname.length());
1507             }
1508             if (filteredcfgPL.first.second.at(i).startsWith("/" + redundantrootdirname))
1509             {
1510                 filteredcfgPL.first.second[i] = filteredcfgPL.first.second[i].mid(redundantrootdirname.length() + 1);
1511             }
1512         }
1513     }
1514     return filteredcfgPL;
1515 }
1516 
getfullarchivepath(QString relativefilepath,QStringList archivefile)1517 QString unetbootin::getfullarchivepath(QString relativefilepath, QStringList archivefile)
1518 {
1519 	QStringList pfoundmatches;
1520 	relativefilepath = QDir::fromNativeSeparators(relativefilepath);
1521 	if (relativefilepath.endsWith('/'))
1522 		relativefilepath = relativefilepath.left(relativefilepath.size()-1);
1523 	if (!relativefilepath.startsWith('/'))
1524 		relativefilepath = QString("/%1").arg(relativefilepath);
1525 //	if (!relativefilepath.endsWith('/'))
1526 //		relativefilepath = QString("%1/").arg(relativefilepath);
1527 	for (int i = 0; i < archivefile.size(); ++i)
1528 	{
1529 		QString curarchiveitem = QDir::fromNativeSeparators(archivefile.at(i));
1530 		if (curarchiveitem.endsWith('/'))
1531 			curarchiveitem = curarchiveitem.left(curarchiveitem.size()-1);
1532 		if (!curarchiveitem.startsWith('/'))
1533 			curarchiveitem = QString("/%1").arg(curarchiveitem);
1534 //		if (!curarchiveitem.endsWith('/'))
1535 //			curarchiveitem = QString("%1/").arg(curarchiveitem);
1536 		if (curarchiveitem.contains(QRegExp(relativefilepath+"$", Qt::CaseInsensitive)))
1537 			pfoundmatches.append(curarchiveitem);
1538 	}
1539 	if (pfoundmatches.isEmpty())
1540 		return "";
1541 	else
1542 	{
1543 		return filteroutlist(pfoundmatches, ignoredtypesbothRL);
1544 	}
1545 }
1546 
filteroutlist(QString listofdata,QList<QRegExp> listofmatches)1547 QString unetbootin::filteroutlist(QString listofdata, QList<QRegExp> listofmatches)
1548 {
1549 	if (listofdata.isEmpty())
1550 		return "";
1551 	return filteroutlist(QStringList() << listofdata, listofmatches);
1552 }
1553 
filteroutlist(QStringList listofdata,QList<QRegExp> listofmatches)1554 QString unetbootin::filteroutlist(QStringList listofdata, QList<QRegExp> listofmatches)
1555 {
1556 	if (listofdata.isEmpty())
1557 		return "";
1558 	QStringList fldatalist = filteroutlistL(listofdata, listofmatches);
1559 	if (!fldatalist.isEmpty())
1560 		return fldatalist.at(0);
1561 	else
1562 		return "";
1563 }
1564 
filteroutlistL(QStringList listofdata,QList<QRegExp> listofmatches)1565 QStringList unetbootin::filteroutlistL(QStringList listofdata, QList<QRegExp> listofmatches)
1566 {
1567 	if (listofdata.isEmpty())
1568 		return QStringList();
1569 	if (listofmatches.isEmpty())
1570 		return listofdata;
1571 	if (listofdata.size() == 1)
1572 		return listofdata;
1573 	QStringList newlistofdata;
1574 	for (int i = 0; i < listofdata.size(); ++i)
1575 	{
1576 		if (!listofdata.at(i).contains(listofmatches.at(0)))
1577 			newlistofdata.append(listofdata.at(i));
1578 	}
1579 //	QStringList newlistofdata = QStringList(listofdata).filter(listofmatches.at(0));
1580 	listofmatches.removeAt(0);
1581 	if (newlistofdata.isEmpty())
1582 	{
1583 		return filteroutlistL(listofdata, listofmatches);
1584 	}
1585 	else
1586 	{
1587 		return filteroutlistL(newlistofdata, listofmatches);
1588 	}
1589 }
1590 
extractiso(QString isofile)1591 void unetbootin::extractiso(QString isofile)
1592 {
1593 	if (!sdesc2->text().contains(trcurrent))
1594 	{
1595 		sdesc1->setText(QString(sdesc1->text()).remove("<b>").replace(trcurrent+"</b>", trdone));
1596 		sdesc2->setText(QString("<b>%1 %2</b>").arg(sdesc2->text()).arg(trcurrent));
1597 	}
1598 	tprogress->setValue(0);
1599 	QPair<QPair<QStringList, QList<quint64> >, QStringList> listfilesizedirpair = listarchiveconts(isofile);
1600 	if (listfilesizedirpair.first.first.size() == 1)
1601 	{
1602 		QString subarchivename = listfilesizedirpair.first.first.at(0);
1603 		randtmpfile tmpoutsubarchive(ubntmpf, subarchivename.right(3));
1604 		pdesc1->setText(tr("<b>Extracting compressed iso:</b> %1").arg(subarchivename));
1605 		extractfile(subarchivename, tmpoutsubarchive.fileName(), isofile);
1606 		return extractiso(tmpoutsubarchive.fileName());
1607 	}
1608 	if (listfilesizedirpair.first.first.contains(QDir::toNativeSeparators("rescue/KRD.VERSION"), Qt::CaseInsensitive))
1609 	{
1610 		return extractiso_krd10(isofile);
1611 	}
1612 	QFileInfo isofileFI(isofile);
1613 	qint64 isofileSize = isofileFI.size();
1614 	if (listfilesizedirpair.first.first.size() < 10 && isofileSize > 12)
1615 	{
1616 		bool foundiso = false;
1617 		quint64 isofileSizeOneFourth = isofileSize / 4;
1618 		quint64 isofileSizeThreeFourth = isofileSizeOneFourth * 3;
1619 		for (int i = 0; i < listfilesizedirpair.first.first.size() && i < listfilesizedirpair.first.second.size(); ++i)
1620 		{
1621 			if (listfilesizedirpair.first.first.at(i).contains(QRegExp(".iso$", Qt::CaseInsensitive)))
1622 			{
1623 				if (foundiso)
1624 					break;
1625 				foundiso = true;
1626 				if (listfilesizedirpair.first.second.at(i) > isofileSizeThreeFourth)
1627 				{
1628 					QString subarchivename = listfilesizedirpair.first.first.at(i);
1629 					randtmpfile tmpoutsubarchive(ubntmpf, subarchivename.right(3));
1630 					pdesc1->setText(tr("<b>Extracting compressed iso:</b> %1").arg(subarchivename));
1631 					extractfile(subarchivename, tmpoutsubarchive.fileName(), isofile);
1632 					return extractiso(tmpoutsubarchive.fileName());
1633 				}
1634 			}
1635 		}
1636 	}
1637 	QStringList filepathnames = listfilesizedirpair.first.first;
1638 	QStringList directorypathnames;
1639 	if (listfilesizedirpair.second.size() > 0)
1640 	{
1641         redundanttopleveldir = true;
1642         redundantrootdirname = listfilesizedirpair.second.at(0);
1643 		for (int i = 0; i < listfilesizedirpair.second.size(); ++i)
1644 		{
1645 			if (listfilesizedirpair.second.at(i).size() < redundantrootdirname.size())
1646 				redundantrootdirname = listfilesizedirpair.second.at(i);
1647 		}
1648 		if (redundantrootdirname == "boot" ||
1649 			redundantrootdirname == "syslinux" ||
1650 			redundantrootdirname == "grub" ||
1651 			redundantrootdirname == "isolinux" ||
1652 			redundantrootdirname == "extlinux" ||
1653 			redundantrootdirname == "pxelinux")
1654 			redundanttopleveldir = false;
1655 		for (int i = 0; i < listfilesizedirpair.second.size(); ++i) // redundant toplevel path in dirs
1656 		{
1657 			if (!listfilesizedirpair.second.at(i).startsWith(redundantrootdirname))
1658 				redundanttopleveldir = false;
1659 		}
1660 		if (redundanttopleveldir)
1661 		{
1662 			for (int i = 0; i < listfilesizedirpair.first.first.size(); ++i) // redundant toplevel path in files
1663 			{
1664 				if (!listfilesizedirpair.first.first.at(i).startsWith(redundantrootdirname))
1665 					redundanttopleveldir = false;
1666 			}
1667 		}
1668 		if (redundanttopleveldir)
1669 		{
1670 			int rmnumcharsrootdir = redundantrootdirname.size();
1671 			for (int i = 0; i < listfilesizedirpair.second.size(); ++i)
1672 			{
1673 				QString tmpdirectpath = listfilesizedirpair.second[i];
1674 				tmpdirectpath.remove(0, rmnumcharsrootdir);
1675 				if (tmpdirectpath.startsWith("/") || tmpdirectpath.startsWith(QDir::toNativeSeparators("/")))
1676 				{
1677 					tmpdirectpath.remove(0, 1);
1678 				}
1679 				if (!tmpdirectpath.isEmpty())
1680 				{
1681 					directorypathnames.append(tmpdirectpath);
1682 				}
1683 			}
1684 			for (int i = 0; i < listfilesizedirpair.first.first.size(); ++i)
1685 			{
1686 				filepathnames[i].remove(0, rmnumcharsrootdir);
1687 				if (filepathnames[i].startsWith("/") || filepathnames[i].startsWith(QDir::toNativeSeparators("/")))
1688 				{
1689 					filepathnames[i].remove(0, 1);
1690 				}
1691 			}
1692 		}
1693 		else
1694 		{
1695 			directorypathnames = listfilesizedirpair.second;
1696 		}
1697 	}
1698 	if (installType == tr("USB Drive"))
1699 	{
1700 		QStringList syslinuxfilepaths = QStringList() << "boot/syslinux/syslinux.cfg" << "syslinux/syslinux.cfg" << "syslinux.cfg" << "isolinux.cfg" << "extlinux.conf";
1701 		if (QString(QDir::toNativeSeparators("/")) != QString("/"))
1702 		{
1703             syslinuxfilepaths << QString("boot%1syslinux%1syslinux.cfg").arg(QDir::toNativeSeparators("/")) <<  QString("syslinux%1syslinux.cfg").arg(QDir::toNativeSeparators("/"));
1704 		}
1705 		for (int j = 0; j < syslinuxfilepaths.size(); ++j)
1706 		{
1707 			rmFile(QString("%1%2").arg(targetPath).arg(syslinuxfilepaths.at(j)));
1708 			for (int i = 0; i < filepathnames.size(); ++i)
1709 			{
1710 				if (filepathnames.at(i) == syslinuxfilepaths.at(j))
1711 				{
1712 					dontgeneratesyslinuxcfg = true;
1713 					locatedsyslinuxcfgfiles.append(syslinuxfilepaths.at(j));
1714 				}
1715 			}
1716 		}
1717 	}
1718 	if (!dontgeneratesyslinuxcfg)
1719 	{
1720 	kernelOpts = extractcfg(isofile, listfilesizedirpair.first.first);
1721 	issalt = (kernelOpts == SALT_DETECTED);
1722 	if (issalt)
1723 	{
1724 		QStringList mlstfoundfiles = listfilesizedirpair.second.filter(QRegExp("/modules$", Qt::CaseInsensitive));
1725 		if (!mlstfoundfiles.isEmpty())
1726 		{
1727       QString match = mlstfoundfiles.at(0);
1728 			saltRootDir = match.replace(QRegExp("(.*)/modules"), "\\1");
1729 		}
1730 		kernelLine = "linux";
1731 		kernelOpts = "";
1732 		initrdLoc = "";
1733 	  initrdOpts = "";
1734 	  initrdLine = "";
1735 	  slinitrdLine = "";
1736 	}
1737 	else
1738 	{
1739 	extraoptionsPL = extractcfgL(isofile, listfilesizedirpair.first.first);
1740 	}
1741 
1742 #ifndef NOEXTRACTKERNEL
1743 	extractkernel(isofile, QString("%1ubnkern").arg(targetPath), listfilesizedirpair.first);
1744 #endif
1745 #ifndef NOEXTRACTINITRD
1746 	if (!issalt)
1747 	{
1748 	extractinitrd(isofile, QString("%1ubninit").arg(targetPath), listfilesizedirpair.first);
1749 	}
1750 #endif
1751 	}
1752 	QStringList createdpaths = makepathtree(targetDrive, directorypathnames);
1753 	QFile ubnpathlF(QDir::toNativeSeparators(QString("%1ubnpathl.txt").arg(targetPath)));
1754 	if (ubnpathlF.exists())
1755 	{
1756 		rmFile(ubnpathlF);
1757 	}
1758 	ubnpathlF.open(QIODevice::WriteOnly | QIODevice::Text);
1759 	QTextStream ubnpathlS(&ubnpathlF);
1760 	for (int i = createdpaths.size() - 1; i > -1; i--)
1761 	{
1762 		ubnpathlS << createdpaths.at(i) << endl;
1763 	}
1764 	ubnpathlF.close();
1765     QStringList extractedfiles;
1766     if (!skipExtraction)
1767       extractedfiles = extractallfiles(isofile, targetDrive, listfilesizedirpair.first, filepathnames);
1768 	QFile ubnfilelF(QDir::toNativeSeparators(QString("%1ubnfilel.txt").arg(targetPath)));
1769 	if (ubnfilelF.exists())
1770 	{
1771 		rmFile(ubnfilelF);
1772 	}
1773 	ubnfilelF.open(QIODevice::WriteOnly | QIODevice::Text);
1774 	QTextStream ubnfilelS(&ubnfilelF);
1775 	for (int i = 0; i < extractedfiles.size(); ++i)
1776 	{
1777 		ubnfilelS << extractedfiles.at(i) << endl;
1778 	}
1779 	ubnfilelF.close();
1780 #ifdef XPUD
1781 	rmFile(QString("%1boot.cat").arg(targetPath));
1782 	rmFile(QString("%1isolinux.bin").arg(targetPath));
1783 	rmFile(QString("%1syslinux.cfg").arg(targetPath));
1784 	QFile::rename(QString("%1isolinux.cfg").arg(targetPath), QString("%1syslinux.cfg").arg(targetPath));
1785 	if (installType == tr("USB Drive"))
1786 	{
1787 		rmFile(QString("%1ubnfilel.txt").arg(targetPath));
1788 		rmFile(QString("%1ubnpathl.txt").arg(targetPath));
1789 	}
1790 #endif
1791 }
1792 
extractiso_krd10(QString isofile)1793 void unetbootin::extractiso_krd10(QString isofile)
1794 {
1795 	if (!sdesc2->text().contains(trcurrent))
1796 	{
1797 		sdesc1->setText(QString(sdesc1->text()).remove("<b>").replace(trcurrent+"</b>", trdone));
1798 		sdesc2->setText(QString("<b>%1 %2</b>").arg(sdesc2->text()).arg(trdone));
1799 	}
1800 	tprogress->setValue(0);
1801 	QPair<QPair<QStringList, QList<quint64> >, QStringList> listfilesizedirpair = listarchiveconts(isofile);
1802 	kernelLoc = QDir::fromNativeSeparators(locatekernel(isofile, listfilesizedirpair.first));
1803 	if (!kernelLoc.startsWith("/")) kernelLoc.prepend("/");
1804 	initrdLoc = QDir::fromNativeSeparators(locateinitrd(isofile, listfilesizedirpair.first));
1805 	if (!initrdLoc.startsWith("/")) initrdLoc.prepend("/");
1806 	kernelOpts = extractcfg(isofile, listfilesizedirpair.first.first);
1807 	extraoptionsPL.first.first.clear();
1808 	extraoptionsPL.first.second.clear();
1809 	extraoptionsPL.second.first.clear();
1810 	extraoptionsPL.second.second.clear();
1811 	QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > tmpoptionsL = extractcfgL(isofile, listfilesizedirpair.first.first);
1812 	for (int i = 0; i < tmpoptionsL.second.second.size(); ++i)
1813 	{
1814 		if (!tmpoptionsL.second.second.at(i).isEmpty())
1815 		{
1816 			extraoptionsPL.first.first.append(tmpoptionsL.first.first.at(i));
1817 			extraoptionsPL.first.second.append(tmpoptionsL.first.second.at(i));
1818 			extraoptionsPL.second.first.append(tmpoptionsL.second.first.at(i));
1819 			extraoptionsPL.second.second.append(tmpoptionsL.second.second.at(i));
1820 		}
1821 	}
1822 	QPair<QStringList, QList<quint64> > bootfiles;
1823 	for (int i = 0; i < listfilesizedirpair.first.first.size(); ++i)
1824 	{
1825 		if (listfilesizedirpair.first.first.at(i).startsWith("boot", Qt::CaseInsensitive))
1826 		{
1827 			bootfiles.first.append(listfilesizedirpair.first.first.at(i));
1828 			bootfiles.second.append(listfilesizedirpair.first.second.at(i));
1829 		}
1830 	}
1831 	QStringList bootpaths;
1832 	for (int i = 0; i < listfilesizedirpair.second.size(); ++i)
1833 	{
1834 		if (listfilesizedirpair.second.at(i).startsWith("boot", Qt::CaseInsensitive))
1835 		{
1836 			bootpaths.append(listfilesizedirpair.second.at(i));
1837 		}
1838 	}
1839 	if (!bootpaths.contains("rescue"))
1840 		bootpaths.append("rescue");
1841 	QStringList createdpaths = makepathtree(targetDrive, bootpaths);
1842 	QFile ubnpathlF(QDir::toNativeSeparators(QString("%1ubnpathl.txt").arg(targetPath)));
1843 	if (ubnpathlF.exists())
1844 	{
1845 		rmFile(ubnpathlF);
1846 	}
1847 	ubnpathlF.open(QIODevice::WriteOnly | QIODevice::Text);
1848 	QTextStream ubnpathlS(&ubnpathlF);
1849 	for (int i = createdpaths.size() - 1; i > -1; i--)
1850 	{
1851 		ubnpathlS << createdpaths.at(i) << endl;
1852 	}
1853 	ubnpathlF.close();
1854 	QStringList extractedfiles = extractallfiles(isofile, targetDrive, bootfiles, listfilesizedirpair.first.first);
1855 	if (QFile::exists(QString("%1liveusb").arg(targetDrive)))
1856 		overwritefileprompt(QString("%1liveusb").arg(targetDrive));
1857 	else
1858 		extractedfiles.append(QString("%1liveusb").arg(targetDrive));
1859 	QFile(QString("%1liveusb").arg(targetDrive)).open(QIODevice::WriteOnly);
1860 	pdesc1->setText(QString("Copying %1 to %2").arg(isofile).arg(QString("%1rescue%2rescue.iso").arg(targetDrive).arg(QDir::toNativeSeparators("/"))));
1861 	if (QFile::exists(QString("%1rescue%2rescue.iso").arg(targetDrive).arg(QDir::toNativeSeparators("/"))))
1862 		overwritefileprompt(QString("%1rescue%2rescue.iso").arg(targetDrive).arg(QDir::toNativeSeparators("/")));
1863 	else
1864 		extractedfiles.append(QString("%1rescue%2rescue.iso").arg(targetDrive).arg(QDir::toNativeSeparators("/")));
1865 	//QFile::copy(isofile, QString("%1rescue%2rescue.iso").arg(targetDrive).arg(QDir::toNativeSeparators("/")));
1866 	copyfilegui(isofile, QString("%1rescue%2rescue.iso").arg(targetDrive).arg(QDir::toNativeSeparators("/")));
1867 	QFile ubnfilelF(QDir::toNativeSeparators(QString("%1ubnfilel.txt").arg(targetPath)));
1868 	if (ubnfilelF.exists())
1869 	{
1870 		rmFile(ubnfilelF);
1871 	}
1872 	ubnfilelF.open(QIODevice::WriteOnly | QIODevice::Text);
1873 	QTextStream ubnfilelS(&ubnfilelF);
1874 	for (int i = 0; i < extractedfiles.size(); ++i)
1875 	{
1876 		ubnfilelS << extractedfiles.at(i) << endl;
1877 	}
1878 	ubnfilelF.close();
1879 }
1880 
copyfilegui(QString src,QString dst)1881 void unetbootin::copyfilegui(QString src, QString dst)
1882 {
1883 	pdesc5->setText("");
1884 	pdesc4->setText(tr("Copying file, please wait..."));
1885 	pdesc3->setText(tr("<b>Source:</b> <a href=\"%1\">%1</a>").arg(src));
1886 	pdesc2->setText(tr("<b>Destination:</b> %1").arg(dst));
1887 	pdesc1->setText(tr("<b>Copied:</b> 0 bytes"));
1888 	QEventLoop cpfw;
1889 	copyfileT cpft;
1890 	cpft.source = src;
1891 	cpft.destination = dst;
1892 	connect(&cpft, SIGNAL(datacopied64(qint64,qint64)), this, SLOT(cpprogressupdate64(qint64,qint64)));
1893 	connect(&cpft, SIGNAL(finished()), &cpfw, SLOT(quit()));
1894 	cpft.start();
1895 	cpfw.exec();
1896 	pdesc4->setText("");
1897 	pdesc3->setText("");
1898 	pdesc2->setText("");
1899 	pdesc1->setText("");
1900 	tprogress->setValue(0);
1901 }
1902 
makepathtree(QString dirmkpathw,QStringList pathlist)1903 QStringList unetbootin::makepathtree(QString dirmkpathw, QStringList pathlist)
1904 {
1905 	QStringList createdpaths;
1906 	QDir dir(dirmkpathw);
1907 	for (int i = 0; i < pathlist.size(); ++i)
1908 	{
1909 		if (dir.mkdir(pathlist.at(i)))
1910 		{
1911 			createdpaths.append(pathlist.at(i));
1912 		}
1913 	}
1914 	return createdpaths;
1915 }
1916 
extractallfiles(QString archivefile,QString dirxfilesto,QPair<QStringList,QList<quint64>> filesizelist,QStringList outputfilelist)1917 QStringList unetbootin::extractallfiles(QString archivefile, QString dirxfilesto, QPair<QStringList, QList<quint64> > filesizelist, QStringList outputfilelist)
1918 {
1919 	QStringList filelist = filesizelist.first;
1920 	QStringList extractedfiles;
1921 	QProgressDialog xprogress;
1922 	tprogress->setMaximum(filelist.size());
1923 	tprogress->setMinimum(0);
1924 	tprogress->setValue(0);
1925 	pdesc5->setText(tr("Extracting files, please wait..."));
1926 	pdesc4->setText(tr("<b>Archive:</b> %1").arg(archivefile));
1927 	pdesc3->setText(tr("<b>Source:</b>"));
1928 	pdesc2->setText(tr("<b>Destination:</b>"));
1929 	pdesc1->setText(tr("<b>Extracted:</b> 0 of %1 files").arg(filelist.size()));
1930 	for (int i = 0; i < filelist.size(); ++i)
1931 	{
1932 		pdesc3->setText(tr("<b>Source:</b> %1 (%2)").arg(filelist.at(i)).arg(displayfisize(filesizelist.second.at(i))));
1933 		pdesc2->setText(tr("<b>Destination:</b> %1%2").arg(dirxfilesto).arg(outputfilelist.at(i)));
1934 		pdesc1->setText(tr("<b>Extracted:</b> %1 of %2 files").arg(i).arg(filelist.size()));
1935 		tprogress->setValue(i);
1936 		if (extractfile(filelist.at(i), QString("%1%2").arg(dirxfilesto).arg(outputfilelist.at(i)), archivefile))
1937 		{
1938 			extractedfiles.append(filelist.at(i));
1939 		}
1940 	}
1941 	pdesc5->setText("");
1942 	pdesc4->setText("");
1943 	pdesc3->setText("");
1944 	pdesc2->setText("");
1945 	pdesc1->setText("");
1946 	tprogress->setValue(0);
1947 	return extractedfiles;
1948 }
1949 
getgrubcfgargs(QString cfgfile)1950 QString unetbootin::getgrubcfgargs(QString cfgfile)
1951 {
1952 	QFile cfgfileF(cfgfile);
1953 	cfgfileF.open(QIODevice::ReadOnly | QIODevice::Text);
1954 	QTextStream cfgfileS(&cfgfileF);
1955 	QString cfgfileCL;
1956 	while (!cfgfileS.atEnd())
1957 	{
1958 		cfgfileCL = cfgfileS.readLine().trimmed();
1959 		if (cfgfileCL.contains("#"))
1960 		{
1961 			cfgfileCL = cfgfileCL.left(cfgfileCL.indexOf("#")).trimmed();
1962 		}
1963 		if (cfgfileCL.contains(QRegExp("^kernel\\s{1,}\\S{1,}\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
1964 		{
1965 			return fixkernelbootoptions(QString(cfgfileCL).remove(QRegExp("^kernel\\s{1,}\\S{1,}\\s{1,}", Qt::CaseInsensitive)));
1966 		}
1967 	}
1968 	return "";
1969 }
1970 
getgrubcfgargsL(QString cfgfile)1971 QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > unetbootin::getgrubcfgargsL(QString cfgfile)
1972 {
1973 	QPair<QStringList, QStringList> kernelandinitrd;
1974 	QPair<QStringList, QStringList> titleandparams;
1975 	int curindex = 0;
1976 	bool kernelpassed = false;
1977 	QFile cfgfileF(cfgfile);
1978 	cfgfileF.open(QIODevice::ReadOnly | QIODevice::Text);
1979 	QTextStream cfgfileS(&cfgfileF);
1980 	QString cfgfileCL;
1981 	kernelandinitrd.first.append(kernelLoc);
1982 	kernelandinitrd.second.append(initrdLoc);
1983 	titleandparams.first.append(QString("Untitled Entry Grub %1").arg(curindex));
1984 	titleandparams.second.append("");
1985 	while (!cfgfileS.atEnd())
1986 	{
1987 		cfgfileCL = cfgfileS.readLine().trimmed();
1988 		if (cfgfileCL.contains("#"))
1989 		{
1990 			cfgfileCL = cfgfileCL.left(cfgfileCL.indexOf("#")).trimmed();
1991 		}
1992 		if (cfgfileCL.contains(QRegExp("^title\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
1993 		{
1994 			if (kernelpassed)
1995 			{
1996 				++curindex;
1997 				kernelandinitrd.first.append(kernelLoc);
1998 				kernelandinitrd.second.append(initrdLoc);
1999 				titleandparams.first.append(QString("Untitled Entry Grub %1").arg(curindex));
2000 				titleandparams.second.append("");
2001 				kernelpassed = false;
2002 			}
2003 			titleandparams.first[curindex] = QString(cfgfileCL).remove("title", Qt::CaseInsensitive).trimmed();
2004 			continue;
2005 		}
2006 		if (cfgfileCL.contains(QRegExp("^initrd\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2007 		{
2008 			kernelandinitrd.second[curindex] = getFirstTextBlock(QString(cfgfileCL).remove(QRegExp("^initrd", Qt::CaseInsensitive)).trimmed());
2009 //			if (kernelandinitrd.second.at(curindex).isEmpty())
2010 //				kernelandinitrd.second[curindex] = initrdLoc;
2011 			continue;
2012 		}
2013 //		if (cfgfileCL.contains(QRegExp("^module\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2014 //		{
2015 //			kernelandinitrd.second[curindex] = getFirstTextBlock(QString(cfgfileCL).remove(QRegExp("^module", Qt::CaseInsensitive)).trimmed());
2016 //			if (kernelandinitrd.second.at(curindex).isEmpty())
2017 //				kernelandinitrd.second[curindex] = initrdLoc;
2018 //		}
2019 		if (cfgfileCL.contains(QRegExp("^kernel\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2020 		{
2021 			if (kernelpassed)
2022 			{
2023 				++curindex;
2024 				kernelandinitrd.first.append(kernelLoc);
2025 				kernelandinitrd.second.append(initrdLoc);
2026 				titleandparams.first.append(QString("Untitled Entry Grub %1").arg(curindex));
2027 				titleandparams.second.append("");
2028 //				kernelpassed = false;
2029 			}
2030 			if (cfgfileCL.contains(QRegExp("^kernel\\s{1,}\\S{1,}\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2031 			{
2032 				titleandparams.second[curindex] = fixkernelbootoptions(QString(cfgfileCL).remove(QRegExp("^kernel\\s{1,}\\S{1,}\\s{1,}", Qt::CaseInsensitive)));
2033 			}
2034 			kernelandinitrd.first[curindex] = getFirstTextBlock(QString(cfgfileCL).remove(QRegExp("^kernel", Qt::CaseInsensitive)).trimmed());
2035 //			if (kernelandinitrd.first.at(curindex).isEmpty())
2036 //				kernelandinitrd.first[curindex] = kernelLoc;
2037 			kernelpassed = true;
2038 			continue;
2039 		}
2040 	}
2041 	return qMakePair(kernelandinitrd, titleandparams);
2042 }
2043 
getFirstTextBlock(QString fulltext)2044 QString unetbootin::getFirstTextBlock(QString fulltext)
2045 {
2046 	QStringList textblockL = fulltext.split(QRegExp("\\s{1,}")).filter(QRegExp("\\S{1,}"));
2047 	if (textblockL.isEmpty())
2048 		return "";
2049 	else
2050 	{
2051 		return textblockL.at(0);
2052 	}
2053 }
2054 
loadgrub2env(QString cfgfile)2055 void unetbootin::loadgrub2env(QString cfgfile)
2056 {
2057 	QFile cfgfileF(cfgfile);
2058 	cfgfileF.open(QIODevice::ReadOnly | QIODevice::Text);
2059 	QTextStream cfgfileS(&cfgfileF);
2060 	QString cfgfileCL;
2061 	while (!cfgfileS.atEnd())
2062 	{
2063 		cfgfileCL = cfgfileS.readLine().trimmed();
2064 		if (cfgfileCL.contains("#"))
2065 		{
2066 			cfgfileCL = cfgfileCL.left(cfgfileCL.indexOf("#")).trimmed();
2067 		}
2068 		if (cfgfileCL.contains("${"))
2069 		{
2070 			for (QMap<QString, QString>::const_iterator i = grub2vars.begin(); i != grub2vars.end(); ++i)
2071 			{
2072 				if (cfgfileCL.contains(QString("${%1}").arg(i.key())))
2073 					cfgfileCL.replace(QString("${%1}").arg(i.key()), i.value());
2074 			}
2075 		}
2076 		if (cfgfileCL.contains(QRegExp("^set\\s{1,}\\S{1,}\\s{0,}=\\s{0,}\".{1,}\"")))
2077 		{
2078 			QRegExp setrg("^set\\s{1,}(\\S{1,})\\s{0,}=\\s{0,}\"(.{1,})\"");
2079 			setrg.indexIn(cfgfileCL);
2080 			QStringList captxt = setrg.capturedTexts();
2081 			if (captxt.size() >= 2)
2082 			{
2083 				grub2vars[captxt.at(captxt.size()-2)] = captxt.at(captxt.size()-1);
2084 				continue;
2085 			}
2086 		}
2087 		if (cfgfileCL.contains(QRegExp("^set\\s{1,}\\S{1,}\\s{0,}=\\s{0,}\\S{1,}")))
2088 		{
2089 			QRegExp setrg("^set\\s{1,}(\\S{1,})\\s{0,}=\\s{0,}(\\S{1,})");
2090 			setrg.indexIn(cfgfileCL);
2091 			QStringList captxt = setrg.capturedTexts();
2092 			if (captxt.size() >= 2)
2093 			{
2094 				grub2vars[captxt.at(captxt.size()-2)] = captxt.at(captxt.size()-1);
2095 				continue;
2096 			}
2097 		}
2098 		if (cfgfileCL.count("=") == 1)
2099 		{
2100 			QStringList splp = cfgfileCL.split("=");
2101 			if (splp.size() == 2)
2102 			{
2103 				grub2vars[splp.at(0).trimmed()] = QString(splp.at(1)).remove("\"").trimmed();
2104 			}
2105 		}
2106 	}
2107 }
2108 
getgrub2cfgargs(QString cfgfile,QString archivefile,QStringList archivefileconts,QStringList visitedincludes)2109 QString unetbootin::getgrub2cfgargs(QString cfgfile, QString archivefile, QStringList archivefileconts, QStringList visitedincludes)
2110 {
2111 	QFile cfgfileF(cfgfile);
2112 	cfgfileF.open(QIODevice::ReadOnly | QIODevice::Text);
2113 	QTextStream cfgfileS(&cfgfileF);
2114 	QString cfgfileCL;
2115 	QString includesfile;
2116 	QString searchincfrs;
2117 	while (!cfgfileS.atEnd())
2118 	{
2119 		cfgfileCL = cfgfileS.readLine().trimmed();
2120 		if (cfgfileCL.contains("#"))
2121 		{
2122 			cfgfileCL = cfgfileCL.left(cfgfileCL.indexOf("#")).trimmed();
2123 		}
2124 		if (cfgfileCL.contains("${"))
2125 		{
2126 			for (QMap<QString, QString>::const_iterator i = grub2vars.begin(); i != grub2vars.end(); ++i)
2127 			{
2128 				if (cfgfileCL.contains(QString("${%1}").arg(i.key())))
2129 					cfgfileCL.replace(QString("${%1}").arg(i.key()), i.value());
2130 			}
2131 		}
2132 		if (cfgfileCL.contains(QRegExp("^set\\s{1,}\\S{1,}\\s{0,}=\\s{0,}\".{1,}\"")))
2133 		{
2134 			QRegExp setrg("^set\\s{1,}(\\S{1,})\\s{0,}=\\s{0,}\"(.{1,})\"");
2135 			setrg.indexIn(cfgfileCL);
2136 			QStringList captxt = setrg.capturedTexts();
2137 			if (captxt.size() >= 2)
2138 			{
2139 				grub2vars[captxt.at(captxt.size()-2)] = captxt.at(captxt.size()-1);
2140 				continue;
2141 			}
2142 		}
2143 		if (cfgfileCL.contains(QRegExp("^set\\s{1,}\\S{1,}\\s{0,}=\\s{0,}\\S{1,}")))
2144 		{
2145 			QRegExp setrg("^set\\s{1,}(\\S{1,})\\s{0,}=\\s{0,}(\\S{1,})");
2146 			setrg.indexIn(cfgfileCL);
2147 			QStringList captxt = setrg.capturedTexts();
2148 			if (captxt.size() >= 2)
2149 			{
2150 				grub2vars[captxt.at(captxt.size()-2)] = captxt.at(captxt.size()-1);
2151 				continue;
2152 			}
2153 		}
2154 		if (!archivefileconts.isEmpty() && QRegExp("^configfile\\s{1,}\\S{1,}.cfg$", Qt::CaseInsensitive).exactMatch(cfgfileCL))
2155 		{
2156 			includesfile = QDir::toNativeSeparators(QString(cfgfileCL).remove(QRegExp("^configfile\\s{1,}", Qt::CaseInsensitive))).trimmed();
2157 			searchincfrs = searchforgrub2includesfile(includesfile, archivefile, archivefileconts, visitedincludes).trimmed();
2158 			if (!searchincfrs.isEmpty())
2159 				return searchincfrs;
2160 		}
2161 		if (!archivefileconts.isEmpty() && QRegExp("^source\\s{1,}\\S{1,}.cfg$", Qt::CaseInsensitive).exactMatch(cfgfileCL))
2162 		{
2163 			includesfile = QDir::toNativeSeparators(QString(cfgfileCL).remove(QRegExp("^source\\s{1,}", Qt::CaseInsensitive))).trimmed();
2164 			searchincfrs = searchforgrub2includesfile(includesfile, archivefile, archivefileconts, visitedincludes).trimmed();
2165 			if (!searchincfrs.isEmpty())
2166 				return searchincfrs;
2167 		}
2168 		if (cfgfileCL.contains(QRegExp("^linux\\s{1,}\\S{1,}\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2169 		{
2170 			return fixkernelbootoptions(QString(cfgfileCL).remove(QRegExp("^linux\\s{1,}\\S{1,}\\s{1,}", Qt::CaseInsensitive))).remove(QRegExp("initrd=\\S{0,}")).trimmed();
2171 		}
2172 	}
2173 	return "";
2174 }
2175 
getgrub2cfgargsL(QString cfgfile,QString archivefile,QStringList archivefileconts,QStringList visitedincludes)2176 QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > unetbootin::getgrub2cfgargsL(QString cfgfile, QString archivefile, QStringList archivefileconts, QStringList visitedincludes)
2177 {
2178 	QPair<QStringList, QStringList> kernelandinitrd;
2179 	QPair<QStringList, QStringList> titleandparams;
2180 	int curindex = 0;
2181 	bool kernelpassed = false;
2182 	QFile cfgfileF(cfgfile);
2183 	cfgfileF.open(QIODevice::ReadOnly | QIODevice::Text);
2184 	QTextStream cfgfileS(&cfgfileF);
2185 	QString cfgfileCL;
2186 	kernelandinitrd.first.append(kernelLoc);
2187 	kernelandinitrd.second.append(initrdLoc);
2188 	titleandparams.first.append(QString("Untitled Entry Grub %1").arg(curindex));
2189 	titleandparams.second.append("");
2190 	QString includesfile;
2191 	QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > searchincfrs;
2192 	while (!cfgfileS.atEnd())
2193 	{
2194 		cfgfileCL = cfgfileS.readLine().trimmed();
2195 		if (cfgfileCL.contains("#"))
2196 		{
2197 			cfgfileCL = cfgfileCL.left(cfgfileCL.indexOf("#")).trimmed();
2198 		}
2199 		if (cfgfileCL.contains("${"))
2200 		{
2201 			for (QMap<QString, QString>::const_iterator i = grub2vars.begin(); i != grub2vars.end(); ++i)
2202 			{
2203 				if (cfgfileCL.contains(QString("${%1}").arg(i.key())))
2204 					cfgfileCL.replace(QString("${%1}").arg(i.key()), i.value());
2205 			}
2206 		}
2207 		if (cfgfileCL.contains(QRegExp("^set\\s{1,}\\S{1,}\\s{0,}=\\s{0,}\".{1,}\"")))
2208 		{
2209 			QRegExp setrg("^set\\s{1,}(\\S{1,})\\s{0,}=\\s{0,}\"(.{1,})\"");
2210 			setrg.indexIn(cfgfileCL);
2211 			QStringList captxt = setrg.capturedTexts();
2212 			if (captxt.size() >= 2)
2213 			{
2214 				grub2vars[captxt.at(captxt.size()-2)] = captxt.at(captxt.size()-1);
2215 				continue;
2216 			}
2217 		}
2218 		if (cfgfileCL.contains(QRegExp("^set\\s{1,}\\S{1,}\\s{0,}=\\s{0,}\\S{1,}")))
2219 		{
2220 			QRegExp setrg("^set\\s{1,}(\\S{1,})\\s{0,}=\\s{0,}(\\S{1,})");
2221 			setrg.indexIn(cfgfileCL);
2222 			QStringList captxt = setrg.capturedTexts();
2223 			if (captxt.size() >= 2)
2224 			{
2225 				grub2vars[captxt.at(captxt.size()-2)] = captxt.at(captxt.size()-1);
2226 				continue;
2227 			}
2228 		}
2229 		if (!archivefileconts.isEmpty() && QRegExp("^configfile\\s{1,}\\S{1,}.cfg$", Qt::CaseInsensitive).exactMatch(cfgfileCL))
2230 		{
2231 			includesfile = QDir::toNativeSeparators(QString(cfgfileCL).remove(QRegExp("^configfile\\s{1,}", Qt::CaseInsensitive))).trimmed();
2232 			searchincfrs = searchforgrub2includesfileL(includesfile, archivefile, archivefileconts, visitedincludes);
2233 			if (!searchincfrs.first.first.isEmpty())
2234 			{
2235 				kernelandinitrd.first += searchincfrs.first.first;
2236 				kernelandinitrd.second += searchincfrs.first.second;
2237 				titleandparams.first += searchincfrs.second.first;
2238 				titleandparams.second += searchincfrs.second.second;
2239 			}
2240 			continue;
2241 		}
2242 		if (!archivefileconts.isEmpty() && QRegExp("^source\\s{1,}\\S{1,}.cfg$", Qt::CaseInsensitive).exactMatch(cfgfileCL))
2243 		{
2244 			includesfile = QDir::toNativeSeparators(QString(cfgfileCL).remove(QRegExp("^source\\s{1,}", Qt::CaseInsensitive))).trimmed();
2245 			searchincfrs = searchforgrub2includesfileL(includesfile, archivefile, archivefileconts, visitedincludes);
2246 			if (!searchincfrs.first.first.isEmpty())
2247 			{
2248 				kernelandinitrd.first += searchincfrs.first.first;
2249 				kernelandinitrd.second += searchincfrs.first.second;
2250 				titleandparams.first += searchincfrs.second.first;
2251 				titleandparams.second += searchincfrs.second.second;
2252 			}
2253 			continue;
2254 		}
2255 		if (cfgfileCL.contains(QRegExp("^menuentry\\s{1,}\".{1,}\"", Qt::CaseInsensitive)))
2256 		{
2257 			if (kernelpassed)
2258 			{
2259 				++curindex;
2260 				kernelandinitrd.first.append(kernelLoc);
2261 				kernelandinitrd.second.append(initrdLoc);
2262 				titleandparams.first.append(QString("Untitled Entry Grub %1").arg(curindex));
2263 				titleandparams.second.append("");
2264 				kernelpassed = false;
2265 			}
2266 			titleandparams.first[curindex] = QString(cfgfileCL).remove("menuentry", Qt::CaseInsensitive).remove("\"").remove("{").remove("}").trimmed();
2267 			continue;
2268 		}
2269 		if (cfgfileCL.contains(QRegExp("^initrd\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2270 		{
2271 			kernelandinitrd.second[curindex] = getFirstTextBlock(QString(cfgfileCL).remove(QRegExp("^initrd", Qt::CaseInsensitive)).trimmed());
2272 //			if (kernelandinitrd.second.at(curindex).isEmpty())
2273 //				kernelandinitrd.second[curindex] = initrdLoc;
2274 			continue;
2275 		}
2276 //		if (cfgfileCL.contains(QRegExp("^module\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2277 //		{
2278 //			kernelandinitrd.second[curindex] = getFirstTextBlock(QString(cfgfileCL).remove(QRegExp("^module", Qt::CaseInsensitive)).trimmed());
2279 //			if (kernelandinitrd.second.at(curindex).isEmpty())
2280 //				kernelandinitrd.second[curindex] = initrdLoc;
2281 //		}
2282 		if (cfgfileCL.contains(QRegExp("^linux\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2283 		{
2284 			if (kernelpassed)
2285 			{
2286 				++curindex;
2287 				kernelandinitrd.first.append(kernelLoc);
2288 				kernelandinitrd.second.append(initrdLoc);
2289 				titleandparams.first.append(QString("Untitled Entry Grub %1").arg(curindex));
2290 				titleandparams.second.append("");
2291 //				kernelpassed = false;
2292 			}
2293 			if (cfgfileCL.contains(QRegExp("^linux\\s{1,}\\S{1,}\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2294 			{
2295 				titleandparams.second[curindex] = fixkernelbootoptions(QString(cfgfileCL).remove(QRegExp("^linux\\s{1,}\\S{1,}\\s{1,}", Qt::CaseInsensitive))).remove(QRegExp("initrd=\\S{0,}")).trimmed();
2296 			}
2297 			kernelandinitrd.first[curindex] = getFirstTextBlock(QString(cfgfileCL).remove(QRegExp("^linux", Qt::CaseInsensitive)).trimmed());
2298 //			if (kernelandinitrd.first.at(curindex).isEmpty())
2299 //				kernelandinitrd.first[curindex] = kernelLoc;
2300 			kernelpassed = true;
2301 			continue;
2302 		}
2303 	}
2304 	return qMakePair(kernelandinitrd, titleandparams);
2305 }
2306 
getcfgkernargs(QString cfgfile,QString archivefile,QStringList archivefileconts,QStringList visitedincludes)2307 QString unetbootin::getcfgkernargs(QString cfgfile, QString archivefile, QStringList archivefileconts, QStringList visitedincludes)
2308 {
2309 	QFile cfgfileF(cfgfile);
2310 	cfgfileF.open(QIODevice::ReadOnly | QIODevice::Text);
2311 	QTextStream cfgfileS(&cfgfileF);
2312 	QString cfgfileCL;
2313 	QString includesfile;
2314 	QString searchincfrs;
2315 	while (!cfgfileS.atEnd())
2316 	{
2317 		cfgfileCL = cfgfileS.readLine().trimmed();
2318 		if (cfgfileCL.contains("#"))
2319 		{
2320 			cfgfileCL = cfgfileCL.left(cfgfileCL.indexOf("#")).trimmed();
2321 		}
2322 		if (!archivefileconts.isEmpty() && QRegExp("^include\\s{1,}\\S{1,}.cfg$", Qt::CaseInsensitive).exactMatch(cfgfileCL))
2323 		{
2324 			includesfile = QDir::toNativeSeparators(QString(cfgfileCL).remove(QRegExp("^include\\s{1,}", Qt::CaseInsensitive))).trimmed();
2325 			searchincfrs = searchforincludesfile(includesfile, archivefile, archivefileconts, visitedincludes).trimmed();
2326 			if (!searchincfrs.isEmpty())
2327 				return searchincfrs;
2328 		}
2329 		if (!archivefileconts.isEmpty() && QRegExp("^append\\s{1,}\\S{1,}.cfg$", Qt::CaseInsensitive).exactMatch(cfgfileCL))
2330 		{
2331 			includesfile = QDir::toNativeSeparators(QString(cfgfileCL).remove(QRegExp("^append\\s{1,}", Qt::CaseInsensitive))).trimmed();
2332 			searchincfrs = searchforincludesfile(includesfile, archivefile, archivefileconts, visitedincludes).trimmed();
2333 			if (!searchincfrs.isEmpty())
2334 				return searchincfrs;
2335 		}
2336 		else if (cfgfileCL.contains(QRegExp("^\\s{0,}append\\s{1,}", Qt::CaseInsensitive)))
2337 		{
2338 			return fixkernelbootoptions(QString(cfgfileCL).remove(QRegExp("\\s{0,}append\\s{1,}", Qt::CaseInsensitive)).remove(QRegExp("\\s{0,1}initrd=\\S{0,}", Qt::CaseInsensitive)));
2339 		}
2340 	}
2341 	return "";
2342 }
2343 
getcfgkernargsL(QString cfgfile,QString archivefile,QStringList archivefileconts,QStringList visitedincludes)2344 QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > unetbootin::getcfgkernargsL(QString cfgfile, QString archivefile, QStringList archivefileconts, QStringList visitedincludes)
2345 {
2346 	/*
2347 	QString cfgfiledir;
2348 	if (cfgfile.contains(QDir::toNativeSeparators("/")))
2349 		cfgfiledir = QDir::fromNativeSeparators(QString(cfgfile).left(cfgfile.lastIndexOf(QDir::toNativeSeparators("/")) + 1));
2350 	if (!cfgfiledir.isEmpty())
2351 	{
2352 		if (!cfgfiledir.startsWith('/'))
2353 			cfgfiledir = QString("/%1").arg(cfgfiledir);
2354 		if (!cfgfiledir.endsWith('/'))
2355 			cfgfiledir = QString("%1/").arg(cfgfiledir);
2356 	}
2357 	*/
2358 	QPair<QStringList, QStringList> kernelandinitrd;
2359 	QPair<QStringList, QStringList> titleandparams;
2360 	int curindex = 0;
2361 	bool kernelpassed = false;
2362 	QFile cfgfileF(cfgfile);
2363 	cfgfileF.open(QIODevice::ReadOnly | QIODevice::Text);
2364 	QTextStream cfgfileS(&cfgfileF);
2365 	QString cfgfileCL;
2366 	kernelandinitrd.first.append(kernelLoc);
2367 	kernelandinitrd.second.append(initrdLoc);
2368 	titleandparams.first.append(QString("Untitled Entry Grub %1").arg(curindex));
2369 	titleandparams.second.append("");
2370 	QString includesfile;
2371 	QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > searchincfrs;
2372 	while (!cfgfileS.atEnd())
2373 	{
2374 		cfgfileCL = cfgfileS.readLine().trimmed();
2375 		if (cfgfileCL.contains("#"))
2376 		{
2377 			cfgfileCL = cfgfileCL.left(cfgfileCL.indexOf("#")).trimmed();
2378 		}
2379 		if (!archivefileconts.isEmpty() && QRegExp("^include\\s{1,}\\S{1,}.cfg$", Qt::CaseInsensitive).exactMatch(cfgfileCL))
2380 		{
2381 			includesfile = QDir::toNativeSeparators(QString(cfgfileCL).remove(QRegExp("^include\\s{1,}", Qt::CaseInsensitive))).trimmed();
2382 			searchincfrs = searchforincludesfileL(includesfile, archivefile, archivefileconts, visitedincludes);
2383 			if (!searchincfrs.first.first.isEmpty())
2384 			{
2385 				kernelandinitrd.first += searchincfrs.first.first;
2386 				kernelandinitrd.second += searchincfrs.first.second;
2387 				titleandparams.first += searchincfrs.second.first;
2388 				titleandparams.second += searchincfrs.second.second;
2389 			}
2390 			continue;
2391 		}
2392 		if (!archivefileconts.isEmpty() && QRegExp("^append\\s{1,}\\S{1,}.cfg$", Qt::CaseInsensitive).exactMatch(cfgfileCL))
2393 		{
2394 			includesfile = QDir::toNativeSeparators(QString(cfgfileCL).remove(QRegExp("^append\\s{1,}", Qt::CaseInsensitive))).trimmed();
2395 			searchincfrs = searchforincludesfileL(includesfile, archivefile, archivefileconts, visitedincludes);
2396 			if (!searchincfrs.first.first.isEmpty())
2397 			{
2398 				kernelandinitrd.first += searchincfrs.first.first;
2399 				kernelandinitrd.second += searchincfrs.first.second;
2400 				titleandparams.first += searchincfrs.second.first;
2401 				titleandparams.second += searchincfrs.second.second;
2402 			}
2403 			continue;
2404 		}
2405 		if (cfgfileCL.contains(QRegExp("^menu label\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2406 		{
2407 			titleandparams.first[curindex] = QString(cfgfileCL).remove(QRegExp("^menu label", Qt::CaseInsensitive)).trimmed();
2408 			continue;
2409 		}
2410 		if (cfgfileCL.contains(QRegExp("^append\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2411 		{
2412 			QString appendoptsL = QString(cfgfileCL).remove(QRegExp("^append", Qt::CaseInsensitive)).trimmed();
2413 			if (appendoptsL.contains(QRegExp("initrd=\\S{0,}", Qt::CaseInsensitive)))
2414 			{
2415 				kernelandinitrd.second[curindex] = getFirstTextBlock(QString(appendoptsL).remove(QRegExp(".{0,}initrd=", Qt::CaseInsensitive)));
2416 				appendoptsL = QString(appendoptsL).remove(QRegExp("initrd=\\S{0,}", Qt::CaseInsensitive));
2417 //				if (kernelandinitrd.second.at(curindex).isEmpty())
2418 //					kernelandinitrd.second[curindex] = initrdLoc;
2419 //				else if (!kernelandinitrd.second.at(curindex).contains('/'))
2420 //					kernelandinitrd.second[curindex] = QString("%1%2").arg(cfgfiledir, kernelandinitrd.second.at(curindex));
2421 			}
2422 			titleandparams.second[curindex] = fixkernelbootoptions(appendoptsL);
2423 			continue;
2424 		}
2425 		if (cfgfileCL.contains(QRegExp("^label\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2426 		{
2427 			if (kernelpassed)
2428 			{
2429 				++curindex;
2430 				kernelandinitrd.first.append(kernelLoc);
2431 				kernelandinitrd.second.append(initrdLoc);
2432 				titleandparams.first.append(QString("Untitled Entry Syslinux %1").arg(curindex));
2433 				titleandparams.second.append("");
2434 				kernelpassed = false;
2435 			}
2436 			titleandparams.first[curindex] = QString(cfgfileCL).remove(QRegExp("^label", Qt::CaseInsensitive)).trimmed();
2437 			continue;
2438 		}
2439 		if (cfgfileCL.contains(QRegExp("^kernel\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2440 		{
2441 			if (kernelpassed)
2442 			{
2443 				++curindex;
2444 				kernelandinitrd.first.append(kernelLoc);
2445 				kernelandinitrd.second.append(initrdLoc);
2446 				titleandparams.first.append(QString("Untitled Entry Syslinux %1").arg(curindex));
2447 				titleandparams.second.append("");
2448 //				kernelpassed = false;
2449 			}
2450 			kernelandinitrd.first[curindex] = getFirstTextBlock(QString(cfgfileCL).remove(QRegExp("^kernel", Qt::CaseInsensitive)).trimmed());
2451 //			if (kernelandinitrd.first.at(curindex).isEmpty())
2452 //				kernelandinitrd.first[curindex] = kernelLoc;
2453 //			else if (!kernelandinitrd.first.at(curindex).contains('/'))
2454 //				kernelandinitrd.first[curindex] = QString("%1%2").arg(cfgfiledir, kernelandinitrd.first.at(curindex));
2455 			kernelpassed = true;
2456 			continue;
2457 		}
2458 		if (cfgfileCL.contains(QRegExp("^initrd\\s{1,}\\S{1,}", Qt::CaseInsensitive)))
2459 		{
2460 			if (kernelandinitrd.second[curindex] == initrdLoc) {
2461 				kernelandinitrd.second[curindex] = getFirstTextBlock(QString(cfgfileCL).remove(QRegExp("^initrd", Qt::CaseInsensitive)).trimmed());
2462 			}
2463 			continue;
2464 		}
2465 	}
2466 	return qMakePair(kernelandinitrd, titleandparams);
2467 }
2468 
searchforincludesfile(QString includesfile,QString archivefile,QStringList archivefileconts,QStringList visitedincludes)2469 QString unetbootin::searchforincludesfile(QString includesfile, QString archivefile, QStringList archivefileconts, QStringList visitedincludes)
2470 {
2471 	if (includesfile.startsWith(QDir::toNativeSeparators("/")))
2472 	{
2473 		includesfile = includesfile.right(includesfile.size() - 1).trimmed();
2474 	}
2475 	QStringList includesfileL;
2476 	for (int i = 0; i < archivefileconts.size(); ++i)
2477 	{
2478 		QString curentry = archivefileconts.at(i);
2479 		if (curentry.endsWith("/") || curentry.endsWith(QDir::toNativeSeparators("/")))
2480 		{
2481 			curentry = curentry.left(curentry.size() - 1).trimmed();
2482 		}
2483 		if (curentry.contains("/"))
2484 		{
2485 			curentry = curentry.right(curentry.size() - 1 - curentry.indexOf("/"));
2486 		}
2487 		else if (curentry.contains(QDir::toNativeSeparators("/")))
2488 		{
2489 			curentry = curentry.right(curentry.size() - 1 - curentry.indexOf(QDir::toNativeSeparators("/")));
2490 		}
2491 		if (includesfile.compare(curentry, Qt::CaseInsensitive) == 0)
2492 		{
2493 			includesfileL.append(archivefileconts.at(i));
2494 		}
2495 	}
2496 	if (includesfileL.isEmpty())
2497 	{
2498 		includesfileL = archivefileconts.filter(includesfile, Qt::CaseInsensitive);
2499 	}
2500 	if (!includesfileL.isEmpty())
2501 	{
2502 		for (int i = 0; i < includesfileL.size(); ++i)
2503 		{
2504 			if (visitedincludes.contains(includesfileL.at(i)))
2505 				continue;
2506 			randtmpfile tmpoutputcfgf(ubntmpf, "cfg");
2507             extractfile(includesfileL.at(i), tmpoutputcfgf.fileName(), archivefile);
2508 			QStringList nextinclude = visitedincludes;
2509 			nextinclude.append(includesfileL.at(i));
2510 			QString extractcfgtmp = getcfgkernargs(tmpoutputcfgf.fileName(), archivefile, archivefileconts, nextinclude).trimmed();
2511 			rmFile(tmpoutputcfgf);
2512 			if (!extractcfgtmp.isEmpty())
2513 			{
2514 				return extractcfgtmp;
2515 			}
2516 		}
2517 	}
2518 	return "";
2519 }
2520 
searchforincludesfileL(QString includesfile,QString archivefile,QStringList archivefileconts,QStringList visitedincludes)2521 QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > unetbootin::searchforincludesfileL(QString includesfile, QString archivefile, QStringList archivefileconts, QStringList visitedincludes)
2522 {
2523 	if (includesfile.startsWith(QDir::toNativeSeparators("/")))
2524 	{
2525 		includesfile = includesfile.right(includesfile.size() - 1).trimmed();
2526 	}
2527 	QStringList includesfileL;
2528 	for (int i = 0; i < archivefileconts.size(); ++i)
2529 	{
2530 		QString curentry = archivefileconts.at(i);
2531 		if (curentry.endsWith("/") || curentry.endsWith(QDir::toNativeSeparators("/")))
2532 		{
2533 			curentry = curentry.left(curentry.size() - 1).trimmed();
2534 		}
2535 		if (curentry.contains("/"))
2536 		{
2537 			curentry = curentry.right(curentry.size() - 1 - curentry.indexOf("/"));
2538 		}
2539 		else if (curentry.contains(QDir::toNativeSeparators("/")))
2540 		{
2541 			curentry = curentry.right(curentry.size() - 1 - curentry.indexOf(QDir::toNativeSeparators("/")));
2542 		}
2543 		if (includesfile.compare(curentry, Qt::CaseInsensitive) == 0)
2544 		{
2545 			includesfileL.append(archivefileconts.at(i));
2546 		}
2547 	}
2548 	if (includesfileL.isEmpty())
2549 	{
2550 		includesfileL = archivefileconts.filter(includesfile, Qt::CaseInsensitive);
2551 	}
2552 	if (!includesfileL.isEmpty())
2553 	{
2554 		for (int i = 0; i < includesfileL.size(); ++i)
2555 		{
2556 			if (visitedincludes.contains(includesfileL.at(i)))
2557 				continue;
2558 			randtmpfile tmpoutputcfgf(ubntmpf, "cfg");
2559 			extractfile(includesfileL.at(i), tmpoutputcfgf.fileName(), archivefile);
2560 			QStringList nextinclude = visitedincludes;
2561 			nextinclude.append(includesfileL.at(i));
2562             QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > extractcfgtmp = getcfgkernargsL(tmpoutputcfgf.fileName(), archivefile, archivefileconts, nextinclude);
2563 			rmFile(tmpoutputcfgf);
2564 			if (!extractcfgtmp.first.first.isEmpty())
2565 			{
2566 				return extractcfgtmp;
2567 			}
2568 		}
2569 	}
2570 	return QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> >();
2571 }
2572 
searchforgrub2includesfile(QString includesfile,QString archivefile,QStringList archivefileconts,QStringList visitedincludes)2573 QString unetbootin::searchforgrub2includesfile(QString includesfile, QString archivefile, QStringList archivefileconts, QStringList visitedincludes)
2574 {
2575 	if (includesfile.startsWith(QDir::toNativeSeparators("/")))
2576 	{
2577 		includesfile = includesfile.right(includesfile.size() - 1).trimmed();
2578 	}
2579 	QStringList includesfileL;
2580 	for (int i = 0; i < archivefileconts.size(); ++i)
2581 	{
2582 		QString curentry = archivefileconts.at(i);
2583 		if (curentry.endsWith("/") || curentry.endsWith(QDir::toNativeSeparators("/")))
2584 		{
2585 			curentry = curentry.left(curentry.size() - 1).trimmed();
2586 		}
2587 		if (curentry.contains("/"))
2588 		{
2589 			curentry = curentry.right(curentry.size() - 1 - curentry.indexOf("/"));
2590 		}
2591 		else if (curentry.contains(QDir::toNativeSeparators("/")))
2592 		{
2593 			curentry = curentry.right(curentry.size() - 1 - curentry.indexOf(QDir::toNativeSeparators("/")));
2594 		}
2595 		if (includesfile.compare(curentry, Qt::CaseInsensitive) == 0)
2596 		{
2597 			includesfileL.append(archivefileconts.at(i));
2598 		}
2599 	}
2600 	if (includesfileL.isEmpty())
2601 	{
2602 		includesfileL = archivefileconts.filter(includesfile, Qt::CaseInsensitive);
2603 	}
2604 	if (!includesfileL.isEmpty())
2605 	{
2606 		for (int i = 0; i < includesfileL.size(); ++i)
2607 		{
2608 			if (visitedincludes.contains(includesfileL.at(i)))
2609 				continue;
2610 			randtmpfile tmpoutputcfgf(ubntmpf, "cfg");
2611 			extractfile(includesfileL.at(i), tmpoutputcfgf.fileName(), archivefile);
2612 			QStringList nextinclude = visitedincludes;
2613 			nextinclude.append(includesfileL.at(i));
2614 			QString extractcfgtmp = getgrub2cfgargs(tmpoutputcfgf.fileName(), archivefile, archivefileconts, nextinclude).trimmed();
2615 			rmFile(tmpoutputcfgf);
2616 			if (!extractcfgtmp.isEmpty())
2617 			{
2618 				return extractcfgtmp;
2619 			}
2620 		}
2621 	}
2622 	return "";
2623 }
2624 
searchforgrub2includesfileL(QString includesfile,QString archivefile,QStringList archivefileconts,QStringList visitedincludes)2625 QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > unetbootin::searchforgrub2includesfileL(QString includesfile, QString archivefile, QStringList archivefileconts, QStringList visitedincludes)
2626 {
2627 	if (includesfile.startsWith(QDir::toNativeSeparators("/")))
2628 	{
2629 		includesfile = includesfile.right(includesfile.size() - 1).trimmed();
2630 	}
2631 	QStringList includesfileL;
2632 	for (int i = 0; i < archivefileconts.size(); ++i)
2633 	{
2634 		QString curentry = archivefileconts.at(i);
2635 		if (curentry.endsWith("/") || curentry.endsWith(QDir::toNativeSeparators("/")))
2636 		{
2637 			curentry = curentry.left(curentry.size() - 1).trimmed();
2638 		}
2639 		if (curentry.contains("/"))
2640 		{
2641 			curentry = curentry.right(curentry.size() - 1 - curentry.indexOf("/"));
2642 		}
2643 		else if (curentry.contains(QDir::toNativeSeparators("/")))
2644 		{
2645 			curentry = curentry.right(curentry.size() - 1 - curentry.indexOf(QDir::toNativeSeparators("/")));
2646 		}
2647 		if (includesfile.compare(curentry, Qt::CaseInsensitive) == 0)
2648 		{
2649 			includesfileL.append(archivefileconts.at(i));
2650 		}
2651 	}
2652 	if (includesfileL.isEmpty())
2653 	{
2654 		includesfileL = archivefileconts.filter(includesfile, Qt::CaseInsensitive);
2655 	}
2656 	if (!includesfileL.isEmpty())
2657 	{
2658 		for (int i = 0; i < includesfileL.size(); ++i)
2659 		{
2660 			if (visitedincludes.contains(includesfileL.at(i)))
2661 				continue;
2662 			randtmpfile tmpoutputcfgf(ubntmpf, "cfg");
2663 			extractfile(includesfileL.at(i), tmpoutputcfgf.fileName(), archivefile);
2664 			QStringList nextinclude = visitedincludes;
2665 			nextinclude.append(includesfileL.at(i));
2666 			QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> > extractcfgtmp = getgrub2cfgargsL(tmpoutputcfgf.fileName(), archivefile, archivefileconts, nextinclude);
2667 			rmFile(tmpoutputcfgf);
2668 			if (!extractcfgtmp.first.first.isEmpty())
2669 			{
2670 				return extractcfgtmp;
2671 			}
2672 		}
2673 	}
2674 	return QPair<QPair<QStringList, QStringList>, QPair<QStringList, QStringList> >();
2675 }
2676 
downloadfile(QString fileurl,QString targetfile,qint64 minsize=524288)2677 void unetbootin::downloadfile(QString fileurl, QString targetfile, qint64 minsize=524288)
2678 {
2679 	if (fileurl.isEmpty())
2680 	{
2681 		showDownloadFailedScreen(fileurl);
2682 		return;
2683 	}
2684 	if (QFile::exists(targetfile))
2685 	{
2686 		rmFile(targetfile);
2687 	}
2688 	QNetworkAccessManager manager;
2689 	QNetworkRequest dlurl(fileurl);
2690 	QNetworkReply * networkReply = manager.get(dlurl);
2691 
2692 	QEventLoop dlewait;
2693 	pdesc5->setText("");
2694 	pdesc4->setText(tr("Downloading files, please wait..."));
2695 	pdesc3->setText(tr("<b>Source:</b> <a href=\"%1\">%1</a>").arg(fileurl));
2696 	pdesc2->setText(tr("<b>Destination:</b> %1").arg(targetfile));
2697 	pdesc1->setText(tr("<b>Downloaded:</b> 0 bytes"));
2698 
2699 	QUrl redirectUrl;
2700 	bool downloadFailed = false;
2701 	QNetworkReply::NetworkError errorCode;
2702 
2703 	connect(networkReply, &QNetworkReply::finished, &dlewait, &QEventLoop::quit);
2704 	connect(networkReply, &QNetworkReply::downloadProgress, this, &unetbootin::dlprogressupdate64);
2705 	connect(networkReply, &QNetworkReply::redirected, [&](const QUrl &url){ redirectUrl = url; });
2706 	connect(networkReply, static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error),
2707 			[&](QNetworkReply::NetworkError code){ downloadFailed = true; errorCode = code; });
2708 
2709 	QFile dloutfile;
2710 	if (installType == tr("USB Drive"))
2711 	{
2712 		dloutfile.setFileName(randtmpfile::getrandfilename(ubntmpf, "tmp"));
2713 	}
2714 	else
2715 	{
2716 		dloutfile.setFileName(targetfile);
2717 	}
2718 	dloutfile.open(QIODevice::WriteOnly);
2719 
2720 	connect(networkReply, &QNetworkReply::downloadProgress, [&](qint64, qint64){
2721 		dloutfile.write(networkReply->readAll());
2722 	});
2723 
2724 	dlewait.exec();
2725 
2726 	if (!redirectUrl.isEmpty())
2727 	{
2728 		networkReply->deleteLater();
2729 		downloadfile(redirectUrl.toString(), targetfile, minsize);
2730 		return;
2731 	}
2732 
2733 	if (downloadFailed)
2734 	{
2735 		qDebug() << "Failed to download URL: " << fileurl;
2736 		qDebug() << "Error code: " << errorCode;
2737 		qDebug() << "Error string: " << networkReply->errorString();
2738 		networkReply->deleteLater();
2739 		showDownloadFailedScreen(fileurl);
2740 		return;
2741 	}
2742 
2743 	dloutfile.write(networkReply->readAll());
2744 	networkReply->deleteLater();
2745 	dloutfile.close();
2746 	if (installType == tr("USB Drive"))
2747 	{
2748 		dloutfile.rename(targetfile);
2749 	}
2750 
2751 	if (QFile(targetfile).size() < minsize)
2752 	{
2753 		// download failed
2754 		showDownloadFailedScreen(fileurl);
2755 		return;
2756 	}
2757 	pdesc4->setText("");
2758 	pdesc3->setText("");
2759 	pdesc2->setText("");
2760 	pdesc1->setText("");
2761 	tprogress->setValue(0);
2762 	if (testingDownload)
2763 	{
2764 		// Note that this only tests that the first download succeeds
2765 		QTextStream out(stdout);
2766 		out << "exitstatus:downloadcomplete" << endl << flush;
2767 		QApplication::exit();
2768 		exit(0);
2769 	}
2770 }
2771 
showDownloadFailedScreen(const QString & fileurl)2772 void unetbootin::showDownloadFailedScreen(const QString &fileurl)
2773 {
2774 	progresslayer->setEnabled(false);
2775 	progresslayer->hide();
2776 	rebootlayer->setEnabled(true);
2777 	rebootlayer->show();
2778 	rebootmsgtext->setText(tr("Download of %1 %2 from %3 failed. Please try downloading the ISO file from the website directly and supply it via the diskimage option.").arg(nameDistro).arg(nameVersion).arg(fileurl));
2779 	this->downloadFailed = true;
2780 	if (exitOnCompletion)
2781 	{
2782 		QTextStream out(stdout);
2783 		out << "exitstatus:downloadfailed" << endl << flush;
2784 		QApplication::exit();
2785 		exit(0);
2786 	}
2787 }
2788 
dlprogressupdate64(qint64 dlbytes,qint64 maxbytes)2789 void unetbootin::dlprogressupdate64(qint64 dlbytes, qint64 maxbytes)
2790 {
2791 	QTime time = QTime::currentTime();
2792 	static int oldsec = 0;
2793 	// refresh the progress bar every second
2794 	if(oldsec != time.second())
2795 	{
2796 		oldsec = time.second();
2797 		tprogress->setValue(10000 * dlbytes / maxbytes);
2798 		tprogress->setMaximum(10000);
2799 		// display the downloaded size with suffix
2800 		pdesc1->setText(tr("<b>Downloaded:</b> %1 of %2").arg(displayfisize(dlbytes)).arg(displayfisize(maxbytes)));
2801 	}
2802 }
2803 
cpprogressupdate64(qint64 dlbytes,qint64 maxbytes)2804 void unetbootin::cpprogressupdate64(qint64 dlbytes, qint64 maxbytes)
2805 {
2806  QTime time = QTime::currentTime();
2807  static int oldsec = 0;
2808  // refresh the progress bar every second
2809  if(oldsec != time.second())
2810  {
2811    oldsec = time.second();
2812 	 tprogress->setValue(10000 * dlbytes / maxbytes);
2813 	 tprogress->setMaximum(10000);
2814    // display the downloaded size with suffix
2815 	 pdesc1->setText(tr("<b>Copied:</b> %1 of %2").arg(displayfisize(dlbytes)).arg(displayfisize(maxbytes)));
2816  }
2817 }
2818 
downloadpagecontents(QUrl pageurl)2819 QString unetbootin::downloadpagecontents(QUrl pageurl)
2820 {
2821 	QNetworkAccessManager manager;
2822 	QNetworkRequest dlurl(pageurl);
2823 	QNetworkReply * networkReply = manager.get(dlurl);
2824 	QEventLoop pgwait;
2825 	QUrl redirectUrl;
2826 	connect(networkReply, &QNetworkReply::finished, &pgwait, &QEventLoop::quit);
2827 	connect(networkReply, &QNetworkReply::redirected, [&redirectUrl](const QUrl &url){ redirectUrl = url; });
2828 
2829 	pgwait.exec();
2830 
2831 	if (!redirectUrl.isEmpty())
2832 	{
2833 		networkReply->deleteLater();
2834 		return downloadpagecontents(redirectUrl);
2835 	}
2836 
2837 	QString result = networkReply->readAll();
2838 	networkReply->close();
2839 	networkReply->deleteLater();
2840 	return result;
2841 }
2842 
lstFtpDirFiles(QString ldfDirStringUrl,qint64 ldfMinSize,qint64 ldfMaxSize)2843 QStringList unetbootin::lstFtpDirFiles(QString ldfDirStringUrl, qint64 ldfMinSize, qint64 ldfMaxSize)
2844 {
2845 	qDebug() << "lstFtpDirFiles called for " << ldfDirStringUrl;
2846 	return {};
2847 /*
2848 	QUrl ldfDirUrl(ldfDirStringUrl);
2849 	QFtp ldfFtp;
2850 	QEventLoop ldfWait;
2851 	nDirListStor nDirListStorL;
2852 	nDirListStorL.nMinFileSizeBytes = ldfMinSize;
2853 	nDirListStorL.nMaxFileSizeBytes = ldfMaxSize;
2854 	nDirListStorL.searchsymlinks = this->searchsymlinks;
2855 	connect(&ldfFtp, SIGNAL(done(bool)), &ldfWait, SLOT(quit()));
2856 	connect(&ldfFtp, SIGNAL(listInfo(QUrlInfo)), &nDirListStorL, SLOT(sAppendSelfUrlInfoList(QUrlInfo)));
2857 	ldfFtp.connectToHost(ldfDirUrl.host());
2858 	ldfFtp.login();
2859 	ldfFtp.list(ldfDirUrl.path());
2860 	ldfWait.exec();
2861 	ldfFtp.close();
2862 	return nDirListStorL.nDirFileListSL;*/
2863 }
2864 
lstHttpDirFiles(QString ldfDirStringUrl)2865 QStringList unetbootin::lstHttpDirFiles(QString ldfDirStringUrl)
2866 {
2867 	QStringList relativefilelinksL;
2868 	QStringList relativelinksLPreFilter =
2869 		downloadpagecontents(QUrl(ldfDirStringUrl))
2870 		.replace(">", ">\n")
2871 		.replace("<", "\n<")
2872 		.split("\n");
2873 	QStringList relativelinksLPart1 =
2874 		relativelinksLPreFilter
2875 		.filter(QRegExp("<a href=\"(?!\\?)\\S{1,}\">", Qt::CaseInsensitive))
2876 		.replaceInStrings(QRegExp("<a href=\"", Qt::CaseInsensitive), "")
2877 		.replaceInStrings("\">", "");
2878 	QStringList relativelinksLPart2 =
2879 		relativelinksLPreFilter
2880 		.filter(QRegExp("<a href=\'(?!\\?)\\S{1,}\'>", Qt::CaseInsensitive))
2881 		.replaceInStrings(QRegExp("<a href=\'", Qt::CaseInsensitive), "")
2882 		.replaceInStrings("\'>", "");
2883 	QStringList relativelinksL = relativelinksLPart1 << relativelinksLPart2;
2884 	for (int i = 0; i < relativelinksL.size(); ++i)
2885 	{
2886 		if (!relativelinksL.at(i).endsWith('/'))
2887 			relativefilelinksL.append(relativelinksL.at(i));
2888 	}
2889 	return relativefilelinksL;
2890 }
2891 
lstNetDirFiles(QString ldfDirStringUrl,qint64 ldfMinSize,qint64 ldfMaxSize)2892 QStringList unetbootin::lstNetDirFiles(QString ldfDirStringUrl, qint64 ldfMinSize, qint64 ldfMaxSize)
2893 {
2894 	if (!ldfDirStringUrl.endsWith('/'))
2895 		ldfDirStringUrl += '/';
2896 	if (ldfDirStringUrl.startsWith("ftp"))
2897 	{
2898 		return lstFtpDirFiles(ldfDirStringUrl, ldfMinSize, ldfMaxSize);
2899 	}
2900 	else
2901 	{
2902 		return lstHttpDirFiles(ldfDirStringUrl);
2903 	}
2904 }
2905 
weightedFilterNetDir(QString ldfDirStringUrl,qint64 ldfMinSize,qint64 ldfMaxSize,QList<QRegExp> ldfFileMatchExp)2906 QPair<QString, int> unetbootin::weightedFilterNetDir(QString ldfDirStringUrl, qint64 ldfMinSize, qint64 ldfMaxSize, QList<QRegExp> ldfFileMatchExp)
2907 {
2908 	if (!ldfDirStringUrl.endsWith('/'))
2909 		ldfDirStringUrl += '/';
2910 	pdesc1->setText(tr("Searching in <a href=\"%1\">%1</a>").arg(ldfDirStringUrl));
2911 	QPair<QString, int> relativeFileUrl = filterBestMatch(lstNetDirFiles(ldfDirStringUrl, ldfMinSize, ldfMaxSize), ldfFileMatchExp);
2912 	if (relativeFileUrl.first.startsWith('/'))
2913 		ldfDirStringUrl = ldfDirStringUrl.left(ldfDirStringUrl.indexOf('/', 8));
2914 	pdesc2->setText(tr("%1/%2 matches in <a href=\"%3\">%3</a>").arg(relativeFileUrl.second).arg(ldfFileMatchExp.size()).arg(ldfDirStringUrl));
2915 	return qMakePair(ldfDirStringUrl+relativeFileUrl.first, relativeFileUrl.second);
2916 }
2917 
fileFilterNetDir(QStringList ldfDirStringUrlList,qint64 ldfMinSize,qint64 ldfMaxSize,QList<QRegExp> ldfFileMatchExp)2918 QString unetbootin::fileFilterNetDir(QStringList ldfDirStringUrlList, qint64 ldfMinSize, qint64 ldfMaxSize, QList<QRegExp> ldfFileMatchExp)
2919 {
2920 	QPair<QString, int> curRemoteFileUrlSP;
2921 	int hRegxMatch = 0;
2922 	QString hRegxMatchString;
2923 	for (int i = 0; i < ldfDirStringUrlList.size(); ++i)
2924 	{
2925 		curRemoteFileUrlSP = weightedFilterNetDir(ldfDirStringUrlList.at(i), ldfMinSize, ldfMaxSize, ldfFileMatchExp);
2926 		if (curRemoteFileUrlSP.second == ldfFileMatchExp.size())
2927 			return curRemoteFileUrlSP.first;
2928 		if (curRemoteFileUrlSP.second > hRegxMatch)
2929 		{
2930 			hRegxMatch = curRemoteFileUrlSP.second;
2931 			hRegxMatchString = curRemoteFileUrlSP.first;
2932 		}
2933 	}
2934 	return hRegxMatchString;
2935 }
2936 
filterBestMatch(QStringList ufStringList,QList<QRegExp> filterExpList)2937 QPair<QString, int> unetbootin::filterBestMatch(QStringList ufStringList, QList<QRegExp> filterExpList)
2938 {
2939 	QString hRegxMatchString, hRegxMatchStringEnd;
2940 	int hRegxMatch = 0;
2941 	for (int i = 0; i < ufStringList.size(); ++i)
2942 	{
2943 		int regxmatches = 0;
2944 		hRegxMatchStringEnd = ufStringList.at(i).right(ufStringList.at(i).size() - ufStringList.at(i).lastIndexOf('/') - 1);
2945 		for (int j = 0; j < filterExpList.size(); ++j)
2946 		{
2947 			if (hRegxMatchStringEnd.contains(filterExpList.at(j)))
2948 				++regxmatches;
2949 		}
2950 		if (regxmatches >= hRegxMatch)
2951 		{
2952 			hRegxMatchString = ufStringList.at(i);
2953 			hRegxMatch = regxmatches;
2954 		}
2955 	}
2956 	return qMakePair(hRegxMatchString, hRegxMatch);
2957 }
2958 
2959 
callexternapp(QString xexecFile,QString xexecParm)2960 QString unetbootin::callexternapp(QString xexecFile, QString xexecParm)
2961 {
2962 	QEventLoop cxaw;
2963 	callexternappT cxat;
2964 	connect(&cxat, SIGNAL(finished()), &cxaw, SLOT(quit()));
2965 	cxat.execFile = xexecFile;
2966 	cxat.execParm = xexecParm;
2967 	cxat.start();
2968 	cxaw.exec();
2969 	return cxat.retnValu;
2970 }
2971 
callexternappWriteToStdin(QString xexecFile,QString xexecParm,QString xwriteToStdin)2972 QString unetbootin::callexternappWriteToStdin(QString xexecFile, QString xexecParm, QString xwriteToStdin)
2973 {
2974 	QEventLoop cxaw;
2975 	callexternappWriteToStdinT cxat;
2976 	connect(&cxat, SIGNAL(finished()), &cxaw, SLOT(quit()));
2977 	cxat.execFile = xexecFile;
2978 	cxat.execParm = xexecParm;
2979 	cxat.writeToStdin = xwriteToStdin;
2980 	cxat.start();
2981 	cxaw.exec();
2982 	return cxat.retnValu;
2983 }
2984 
getdevluid(QString voldrive)2985 QString unetbootin::getdevluid(QString voldrive)
2986 {
2987 #ifdef Q_OS_MAC
2988 	QString diskutilinfo = callexternapp("diskutil", "info " + voldrive);
2989 	QString uuidS = getuuid(voldrive, diskutilinfo);
2990 	if (uuidS == "None")
2991 	{
2992 		return QString("LABEL=%1").arg(getlabel(voldrive, diskutilinfo));
2993 	}
2994 	else
2995 	{
2996 		return QString("UUID=%1").arg(uuidS);
2997 	}
2998 #endif
2999 #ifndef Q_OS_MAC
3000 	QString uuidS = getuuid(voldrive);
3001 	if (uuidS == "None")
3002 	{
3003 		return QString("LABEL=%1").arg(getlabel(voldrive));
3004 	}
3005 	else
3006 	{
3007 		return QString("UUID=%1").arg(uuidS);
3008 	}
3009 #endif
3010 }
3011 
3012 #ifdef Q_OS_MAC
getlabel(QString voldrive,QString diskutilinfo)3013 QString unetbootin::getlabel(QString voldrive, QString diskutilinfo)
3014 {
3015 	QStringList diskutiloutput = diskutilinfo.split("\n");
3016 	QStringList labelLines = diskutiloutput.filter("Volume Name");
3017 	if (labelLines.size() == 0)
3018 		return "None";
3019 	QStringList labelAtEnd = labelLines.at(0).split(":");
3020 	if (labelAtEnd.size() < 2)
3021 		return "None";
3022 	return labelAtEnd.at(labelAtEnd.size()-1).trimmed();
3023 }
3024 #endif
3025 
getlabel(QString voldrive)3026 QString unetbootin::getlabel(QString voldrive)
3027 {
3028 #ifdef Q_OS_MAC
3029 	return getlabel(voldrive, callexternapp("diskutil", "info " + voldrive));
3030 #endif
3031 	#ifdef Q_OS_WIN32
3032 	voldrive.append("\\");
3033 	wchar_t vollabel[50];
3034 	GetVolumeInformation(LPWSTR(voldrive.utf16()), vollabel, 50, NULL, NULL, NULL, NULL, NULL);
3035 	QString vollabelS = QString::fromWCharArray(vollabel);
3036 	if (vollabelS.isEmpty())
3037 	{
3038 		return "None";
3039 	}
3040 	else
3041 	{
3042 		return vollabelS;
3043 	}
3044 	#endif
3045 	#ifdef Q_OS_LINUX
3046 	QString volidpS = "";
3047 	if (!volidcommand.isEmpty())
3048 		volidpS = QString(callexternapp(volidcommand, QString("-l %1").arg(voldrive))).remove("\r").remove("\n").trimmed();
3049 	else
3050 	{
3051 		QString tstrblk = QString(callexternapp(blkidcommand, QString("-s LABEL %1").arg(voldrive)));
3052 		if (tstrblk.contains('='))
3053 			volidpS = tstrblk.section('=', -1, -1).remove('"').remove("\r").remove("\n").trimmed();
3054 	}
3055 	if (volidpS.isEmpty())
3056 	{
3057 		return "None";
3058 	}
3059 	else
3060 	{
3061 		return volidpS;
3062 	}
3063 	#endif
3064 }
3065 
3066 #ifdef Q_OS_MAC
getuuid(QString voldrive,QString diskutilinfo)3067 QString unetbootin::getuuid(QString voldrive, QString diskutilinfo)
3068 {
3069 	QStringList diskutiloutput = diskutilinfo.split("\n");
3070 	QStringList uuidList = diskutiloutput.filter("UUID"); // TODO untested
3071 	if (uuidList.size() > 0)
3072 	{
3073 		uuidList = uuidList.at(0).split(" ");
3074 		return uuidList.at(uuidList.size()-1).trimmed();
3075 	}
3076 	// otherwise FAT32 or FAT16; return serial number
3077 	bool isFat32 = diskutiloutput.filter("FAT32").size() > 0;
3078 	if (!isFat32)
3079 	{
3080 		if (diskutiloutput.filter("FAT16").size() == 0 && diskutiloutput.filter("FAT12").size() == 0)
3081 			return "None";
3082 	}
3083 	callexternapp("diskutil", "umount "+targetDev);
3084 	QFile rawDevice(voldrive);
3085 	rawDevice.open(QIODevice::ReadOnly);
3086 	if (isFat32)
3087 	{
3088 		rawDevice.seek(67);
3089 	}
3090 	else // FAT16 or FAT12
3091 	{
3092 		rawDevice.seek(39);
3093 	}
3094 	unsigned char pserial[4];
3095 	rawDevice.read((char*)pserial, 4);
3096 	QString serialNumber = QString::number(pserial[3], 16).rightJustified(2, '0')+QString::number(pserial[2], 16).rightJustified(2, '0')+"-"+QString::number(pserial[1], 16).rightJustified(2, '0')+QString::number(pserial[0], 16).rightJustified(2, '0');
3097 	rawDevice.close();
3098 	callexternapp("diskutil", "mount "+targetDev);
3099 	return serialNumber.toUpper();
3100 }
3101 
3102 #endif
3103 
getuuid(QString voldrive)3104 QString unetbootin::getuuid(QString voldrive)
3105 {
3106 #ifdef Q_OS_MAC
3107 	return getuuid(voldrive, callexternapp("diskutil", "info " + voldrive));
3108 #endif
3109 	#ifdef Q_OS_WIN32
3110 	voldrive.append("\\");
3111     DWORD volserialnum = 0;
3112 	GetVolumeInformation(LPWSTR(voldrive.utf16()), NULL, NULL, &volserialnum, NULL, NULL, NULL, NULL);
3113     if (!(volserialnum >= 1))
3114 	{
3115 		return "None";
3116 	}
3117 	QString tvolsernum = QString::number(volserialnum, 16).toUpper();
3118 	if (tvolsernum.size() == 8)
3119 	{
3120 		return QString("%1-%2").arg(tvolsernum.left(4), tvolsernum.right(4));
3121 	}
3122 	else
3123 	{
3124 		return tvolsernum;
3125 	}
3126 	#endif
3127 	#ifdef Q_OS_LINUX
3128 	QString volidpS = "";
3129 	if (!volidcommand.isEmpty())
3130 		volidpS = QString(callexternapp(volidcommand, QString("-u %1").arg(voldrive))).remove("\r").remove("\n").trimmed();
3131 	else
3132 	{
3133 		QString tstrblk = QString(callexternapp(blkidcommand, QString("-s UUID %1").arg(voldrive)));
3134 		if (tstrblk.contains('='))
3135 			volidpS = tstrblk.section('=', -1, -1).remove('"').remove("\r").remove("\n").trimmed();
3136 	}
3137 	if (volidpS.isEmpty())
3138 	{
3139 		return "None";
3140 	}
3141 	else
3142 	{
3143 		return volidpS;
3144 	}
3145 	#endif
3146 }
3147 
3148 #ifdef Q_OS_UNIX
3149 
locatecommand(QString commandtolocate,QString reqforinstallmode,QString packagename)3150 QString unetbootin::locatecommand(QString commandtolocate, QString reqforinstallmode, QString packagename)
3151 {
3152 	QString commandbinpath = callexternapp("which", commandtolocate).trimmed();
3153 	if (!commandbinpath.isEmpty() && QFile::exists(commandbinpath))
3154 		return commandbinpath;
3155 	if (packagename == "silent")
3156 		return "";
3157 //	QString commandbinpath = callexternapp("whereis", commandtolocate);
3158 //	QStringList commandbinpathL = commandbinpath.split(" ").join("\n").split("\t").join("\n").split("\n");
3159 //	for (int i = 0; i < commandbinpathL.size(); ++i)
3160 //	{
3161 //		if (commandbinpathL.at(i).contains("bin/"))
3162 //		{
3163 //			return commandbinpathL.at(i);
3164 //		}
3165 //	}
3166 	QMessageBox errorcmdnotfoundmsgbx;
3167 	errorcmdnotfoundmsgbx.setIcon(QMessageBox::Warning);
3168 	errorcmdnotfoundmsgbx.setWindowTitle(QString(tr("%1 not found")).arg(commandtolocate));
3169 	errorcmdnotfoundmsgbx.setText(QString(tr("%1 not found. This is required for %2 install mode.\nInstall the \"%3\" package or your distribution's equivalent.")).arg(commandtolocate, reqforinstallmode, packagename));
3170 	errorcmdnotfoundmsgbx.setStandardButtons(QMessageBox::Ok);
3171 	switch (errorcmdnotfoundmsgbx.exec())
3172 	{
3173 		case QMessageBox::Ok:
3174 			break;
3175 		default:
3176 			break;
3177 	}
3178 	return commandtolocate;
3179 }
3180 
locatedevicenode(QString mountpoint)3181 QString unetbootin::locatedevicenode(QString mountpoint)
3182 {
3183 	QStringList rawdeviceL = QString(callexternapp("mount", "")).replace("\t", " ").split("\n").filter("/dev/").filter(QString(" %1 ").arg(mountpoint));
3184 	if (rawdeviceL.isEmpty())
3185 	{
3186 		return "NOT FOUND";
3187 	}
3188 	else
3189 	{
3190 		return QFileInfo(rawdeviceL.at(0).split(" ").at(0)).canonicalFilePath();
3191 	}
3192 }
3193 
locatemountpoint(QString devicenode)3194 QString unetbootin::locatemountpoint(QString devicenode)
3195 {
3196 	QStringList procmountsL = callexternapp("mount", "").split("\n");
3197 	for (int i = 0; i < procmountsL.size(); ++i)
3198 	{
3199 		QString mountinfo = procmountsL.at(i).split("\t").join(" ");
3200 		QStringList deviceAndRest = mountinfo.split(" on ");
3201 		if (deviceAndRest.size() < 2)
3202 			continue;
3203 		if (deviceAndRest.at(0).trimmed() != devicenode)
3204 			continue;
3205 		QStringList mountpointAndOptions = deviceAndRest.at(1).split(" (").join(" type ").split(" type ");
3206 		if (mountpointAndOptions.size() < 1)
3207 			continue;
3208 		QString mountpoint = mountpointAndOptions.at(0).trimmed();
3209 		if (QDir(mountpoint).exists())
3210 			return mountpoint;
3211 	}
3212 	return "NOT MOUNTED";
3213 }
3214 
getGrubNotation(QString devicenode)3215 QString unetbootin::getGrubNotation(QString devicenode)
3216 {
3217 	return QString("(hd%1,%2)").arg(getDiskNumber(devicenode)).arg(getPartitionNumber(devicenode));
3218 }
3219 
getGrub2Notation(QString devicenode)3220 QString unetbootin::getGrub2Notation(QString devicenode)
3221 {
3222 	return QString("(hd%1,%2)").arg(getDiskNumber(devicenode)).arg(getPartitionNumber(devicenode)+1);
3223 }
3224 
letterToNumber(QChar lettertoconvert)3225 int unetbootin::letterToNumber(QChar lettertoconvert)
3226 {
3227 	if (lettertoconvert.isLower())
3228 	{
3229 		return static_cast<int>(lettertoconvert.toLatin1() - 'a');
3230 	}
3231 	if (lettertoconvert.isUpper())
3232 	{
3233 		return static_cast<int>(lettertoconvert.toLatin1() - 'A');
3234 	}
3235 	else
3236 	{
3237 		return 999;
3238 	}
3239 }
3240 
getDiskNumber(QString devicenode)3241 int unetbootin::getDiskNumber(QString devicenode)
3242 {
3243 	QChar disknumchar(devicenode.at(devicenode.size() - 2));
3244 	if (disknumchar.isLetter())
3245 	{
3246 		return letterToNumber(disknumchar);
3247 	}
3248 	else
3249 	{
3250 		return disknumchar.digitValue() - 1;
3251 	}
3252 }
3253 
getPartitionNumber(QString devicenode)3254 int unetbootin::getPartitionNumber(QString devicenode)
3255 {
3256 	QChar partitionchar(devicenode.at(devicenode.size() - 1));
3257 	if (partitionchar.isLetter())
3258 	{
3259 		return letterToNumber(partitionchar);
3260 	}
3261 	else
3262 	{
3263 		return partitionchar.digitValue() - 1;
3264 	}
3265 }
3266 
3267 #endif
3268 
3269 #ifdef Q_OS_WIN32
3270 
installsvzip()3271 void unetbootin::installsvzip()
3272 {
3273 	if (QFile::exists(QString("%1\\7z.dll").arg(ubntmpf)))
3274 	{
3275 		rmFile(QString("%1\\7z.dll").arg(ubntmpf));
3276 	}
3277 	instIndvfl("sevnz.dll", QString("%1\\7z.dll").arg(ubntmpf));
3278 	if (QFile::exists(QString("%1sevnz.exe").arg(ubntmpf)))
3279 	{
3280 		rmFile(QString("%1sevnz.exe").arg(ubntmpf));
3281 	}
3282 	instIndvfl("sevnz.exe", QString("%1sevnz.exe").arg(ubntmpf));
3283 	sevzcommand = QString("%1sevnz.exe").arg(ubntmpf);
3284 }
3285 
configsysEdit()3286 void unetbootin::configsysEdit()
3287 {
3288 	SetFileAttributesA(QDir::toNativeSeparators(QString("%1config.sys").arg(targetDrive)).toUtf8(), FILE_ATTRIBUTE_NORMAL);
3289 	QFile::copy(QDir::toNativeSeparators(QString("%1config.sys").arg(targetDrive)), QString("%1config.sys").arg(targetPath));
3290 	QFile::copy(QDir::toNativeSeparators(QString("%1config.sys").arg(targetDrive)), QString("%1confignw.txt").arg(targetPath));
3291 	QFile confignwFile(QString("%1confignw.txt").arg(targetPath));
3292 	QFile configsysFile(QDir::toNativeSeparators(QString("%1config.sys").arg(targetDrive)));
3293 	confignwFile.open(QIODevice::ReadWrite | QIODevice::Text);
3294 	configsysFile.open(QIODevice::ReadOnly | QIODevice::Text);
3295 	QTextStream confignwOut(&confignwFile);
3296 	QTextStream configsysOut(&configsysFile);
3297 	QString configsysText = QString("[menu]\n"
3298 	"menucolor=15,0\n"
3299 	"menuitem=windows,Windows\n"
3300 	"menuitem=grub,"UNETBOOTINB"\n"
3301 	"menudefault=windows,30\n"
3302 	"[grub]\n"
3303 	"device=ubnldr.exe\n"
3304 	"[windows]\n%1").arg(configsysOut.readAll());
3305 	confignwOut << configsysText << endl;
3306 	if (!QFile::copy(QString("%1confignw.txt").arg(targetPath), QDir::toNativeSeparators(QString("%1config.sys").arg(targetDrive))))
3307 	{
3308 		rmFile(configsysFile);
3309 		QFile::copy(QString("%1confignw.txt").arg(targetPath), QDir::toNativeSeparators(QString("%1config.sys").arg(targetDrive)));
3310 	}
3311 }
3312 
bootiniEdit()3313 void unetbootin::bootiniEdit()
3314 {
3315 	SetFileAttributesW(LPWSTR(QDir::toNativeSeparators(QString("%1boot.ini").arg(targetDrive)).utf16()), FILE_ATTRIBUTE_NORMAL);
3316 	QFile::copy(QDir::toNativeSeparators(QString("%1boot.ini").arg(targetDrive)), QString("%1boot.ini").arg(targetPath));
3317 	QFile::copy(QDir::toNativeSeparators(QString("%1bootnw.ini").arg(targetDrive)), QString("%1bootnw.txt").arg(targetPath));
3318 	QFile bootnwFile(QString("%1bootnw.txt").arg(targetPath));
3319 	QFile bootiniFile(QDir::toNativeSeparators(QString("%1boot.ini").arg(targetDrive)));
3320 	bootnwFile.open(QIODevice::ReadWrite | QIODevice::Text);
3321 	bootiniFile.open(QIODevice::ReadOnly | QIODevice::Text);
3322 	QTextStream bootnwOut(&bootnwFile);
3323 	QTextStream bootiniOut(&bootiniFile);
3324 	QStringList bootiniCurTextL;
3325 	bool btimustreplacetimeout = true;
3326 	QRegExp btichkistimeout("\\s{0,}timeout.{0,}", Qt::CaseInsensitive);
3327 	QString bootiniCurLine;
3328 	while (!bootiniOut.atEnd())
3329 	{
3330 		bootiniCurLine = bootiniOut.readLine();
3331 		if (btimustreplacetimeout && btichkistimeout.exactMatch(bootiniCurLine))
3332 		{
3333 			bootiniCurTextL.append("timeout=15");
3334 			btimustreplacetimeout = false;
3335 		}
3336 		else
3337 		{
3338 			bootiniCurTextL.append(bootiniCurLine);
3339 		}
3340 	}
3341 	QString bootiniCurText = bootiniCurTextL.join("\n");
3342 	QString bootiniText = QString("%1\n%2=\""UNETBOOTINB"\"").arg(bootiniCurText).arg(QDir::toNativeSeparators(QString("%1ubnldr.mbr").arg(targetDrive)));
3343 	bootnwOut << bootiniText << endl;
3344 	if (!QFile::copy(QString("%1bootnw.txt").arg(targetPath), QDir::toNativeSeparators(QString("%1boot.ini").arg(targetDrive))))
3345 	{
3346 		rmFile(bootiniFile);
3347 		QFile::copy(QString("%1bootnw.txt").arg(targetPath), QDir::toNativeSeparators(QString("%1boot.ini").arg(targetDrive)));
3348 	}
3349 }
3350 
vistabcdEdit()3351 void unetbootin::vistabcdEdit()
3352 {
3353 	bool warch64 = false;
3354 	if (!QProcess::systemEnvironment().filter("ProgramW6432").isEmpty())
3355 		warch64 = true;
3356 	instIndvfl("emtxfile.exe", QString("%1emtxfile.exe").arg(targetPath));
3357 	QFile vbcdEditF1(QString("%1vbcdedit.bat").arg(targetPath));
3358 	vbcdEditF1.open(QIODevice::ReadWrite | QIODevice::Text);
3359 	QTextStream vbcdEditS1(&vbcdEditF1);
3360 	vbcdEditS1 << QString("bcdedit /create /d \""UNETBOOTINB"\" /application bootsector > %1tmpbcdid").arg(targetPath) << endl;
3361 	vbcdEditF1.close();
3362 	if (!warch64)
3363 		callexternapp(QString("%1vbcdedit.bat").arg(targetPath), "");
3364 	QFile vbcdTmpInF(QString("%1tmpbcdid").arg(targetPath));
3365 	vbcdTmpInF.open(QIODevice::ReadOnly | QIODevice::Text);
3366 	QTextStream vbcdTmpInS(&vbcdTmpInF);
3367 	QString qstmpvbcdin = vbcdTmpInS.readAll();
3368 	vbcdTmpInF.close();
3369 	QString vbcdIdTL;
3370 	QStringList vbcdIdTLSL;
3371 	if (!warch64)
3372 	{
3373 		vbcdIdTLSL = qstmpvbcdin.replace("{", "\n").replace("}", "\n").split("\n").filter("-");
3374 		if (!vbcdIdTLSL.isEmpty())
3375 			vbcdIdTL = vbcdIdTLSL.at(0);
3376 	}
3377 	else
3378 	{
3379 		callexternapp(QString("%1emtxfile.exe").arg(targetPath), QString("%1vbcdedit.bat runas").arg(targetPath));
3380 		vbcdTmpInF.open(QIODevice::ReadOnly | QIODevice::Text);
3381 		QTextStream vbcdTmpInS2(&vbcdTmpInF);
3382 		vbcdIdTLSL = vbcdTmpInS2.readAll().replace("{", "\n").replace("}", "\n").split("\n").filter("-");
3383 		if (!vbcdIdTLSL.isEmpty())
3384 			vbcdIdTL = vbcdIdTLSL.at(0);
3385 		vbcdTmpInF.close();
3386 	}
3387 	QSettings vdtistor("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\UNetbootin", QSettings::NativeFormat);
3388 	vdtistor.setValue("WArch64", warch64);
3389 	QFile vbcdEditF2(QString("%1vbcdedt2.bat").arg(targetPath));
3390 	vbcdEditF2.open(QIODevice::ReadWrite | QIODevice::Text);
3391 	QTextStream vbcdEditS2(&vbcdEditF2);
3392 	vbcdEditS2 << QString("bcdedit /set {%1} device boot\n"
3393 	"bcdedit /set {%1} path \\ubnldr.mbr\n"
3394 	"bcdedit /set {%1} device partition=%2\n"
3395 	"bcdedit /displayorder {%1} /addlast\n"
3396 	"bcdedit /timeout 30").arg(vbcdIdTL).arg(targetDev) << endl;
3397 	vbcdEditF2.close();
3398 	if (warch64)
3399 	{
3400 		callexternapp(QString("%1emtxfile.exe").arg(targetPath), QString("%1vbcdedt2.bat runas").arg(targetPath));
3401 	}
3402 	else
3403 	{
3404 		callexternapp(QString("%1vbcdedt2.bat").arg(targetPath), "");
3405 	}
3406 	QFile vbcdundoF(QString("%1vbcdundo.bat").arg(targetPath));
3407 	vbcdundoF.open(QIODevice::ReadWrite | QIODevice::Text);
3408 	QTextStream vbcdundoS(&vbcdundoF);
3409 	vbcdundoS << QString("bcdedit /delete {%1}").arg(vbcdIdTL) << endl;
3410 	vbcdundoF.close();
3411 }
3412 
3413 #endif
3414 
instIndvfl(QString srcfName,QString dstfName)3415 void unetbootin::instIndvfl(QString srcfName, QString dstfName)
3416 {
3417 	QFile srcF(QString(":/%1").arg(srcfName));
3418 	#ifdef NOSTATIC
3419 	if (srcfName == "memdisk")
3420 				srcF.setFileName(QFile::exists("/usr/share/syslinux/memdisk") ? "/usr/share/syslinux/memdisk" : "/usr/lib/syslinux/memdisk");
3421 	else if (srcfName == "menu.c32")
3422 	{
3423 #ifdef Q_OS_LINUX
3424 				srcF.setFileName(QFile::exists("/usr/share/syslinux/menu.c32") ? "/usr/share/syslinux/menu.c32" : "/usr/lib/syslinux/menu.c32");
3425 				if (QFile::exists("/usr/lib/syslinux/modules/bios/menu.c32"))
3426 					srcF.setFileName("/usr/lib/syslinux/modules/bios/menu.c32");
3427 #endif
3428 #ifdef Q_OS_FREEBSD
3429 		srcF.setFileName(LOCALBASE "/share/syslinux/bios/com32/menu/menu.c32");
3430 #endif
3431 	}
3432     else if (srcfName == "libutil.c32")
3433 	{
3434 #ifdef Q_OS_LINUX
3435                 srcF.setFileName(QFile::exists("/usr/share/syslinux/libutil.c32") ? "/usr/share/syslinux/libutil.c32" : "/usr/lib/syslinux/libutil.c32");
3436 		if (QFile::exists("/usr/lib/syslinux/modules/bios/libutil.c32"))
3437 			srcF.setFileName("/usr/lib/syslinux/modules/bios/libutil.c32");
3438 #endif
3439 #ifdef Q_OS_FREEBSD
3440 		srcF.setFileName(LOCALBASE "/share/syslinux/bios/com32/libutil/libutil.c32");
3441 #endif
3442 	}
3443     else if (srcfName == "libcom32.c32")
3444 	{
3445 #ifdef Q_OS_LINUX
3446                 srcF.setFileName(QFile::exists("/usr/share/syslinux/libcom32.c32") ? "/usr/share/syslinux/libcom32.c32" : "/usr/lib/syslinux/libcom32.c32");
3447 		if (QFile::exists("/usr/lib/syslinux/modules/bios/libcom32.c32"))
3448 			srcF.setFileName("/usr/lib/syslinux/modules/bios/libcom32.c32");
3449 #endif
3450 #ifdef Q_OS_FREEBSD
3451 		srcF.setFileName(LOCALBASE "/share/syslinux/bios/com32/lib/libcom32.c32");
3452 #endif
3453 	}
3454     else if (srcfName == "mbr.bin")
3455 	{
3456 			srcF.setFileName(QFile::exists("/usr/share/syslinux/mbr.bin") ? "/usr/share/syslinux/mbr.bin" : "/usr/lib/syslinux/mbr.bin");
3457 		if (QFile::exists("/usr/lib/syslinux/mbr/mbr.bin"))
3458 			srcF.setFileName("/usr/lib/syslinux/mbr/mbr.bin");
3459 	}
3460 	else if (srcfName == "ubnsylnx")
3461 		srcF.setFileName("/usr/bin/syslinux");
3462 //	else
3463 //		srcF.setFileName(QString("/usr/lib/unetbootin/%1").arg(srcfName));
3464 	#endif
3465     if (!srcF.exists())
3466     {
3467         return;
3468     }
3469     if (QFile::exists(dstfName))
3470     {
3471         if (!overwritefileprompt(dstfName))
3472             return;
3473     }
3474     QFile dstF(dstfName);
3475     dstF.open(QIODevice::WriteOnly);
3476     srcF.open(QIODevice::ReadOnly);
3477 	dstF.write(srcF.readAll());
3478 	dstF.close();
3479 	srcF.close();
3480 }
3481 
instTempfl(QString srcfName,QString dstfType)3482 QString unetbootin::instTempfl(QString srcfName, QString dstfType)
3483 {
3484 	QString dstfName = randtmpfile::getrandfilename(ubntmpf, dstfType);
3485 	instIndvfl(srcfName, dstfName);
3486 	return dstfName;
3487 }
3488 
runinst()3489 void unetbootin::runinst()
3490 {
3491 	this->trcurrent = tr("(Current)");
3492 	this->trdone = tr("(Done)");
3493 	firstlayer->setEnabled(false);
3494 	firstlayer->hide();
3495 	secondlayer->setEnabled(true);
3496 	secondlayer->show();
3497 	rebootlayer->setEnabled(false);
3498 	rebootlayer->hide();
3499 	progresslayer->setEnabled(true);
3500 	progresslayer->show();
3501 	sdesc1->setText(QString("<b>%1 %2</b>").arg(sdesc1->text()).arg(trcurrent));
3502 	tprogress->setValue(0);
3503 	installType = typeselect->currentText();
3504 	targetDrive = driveselect->currentText();
3505 	persistenceSpaceMB = this->persistencevalue->value();
3506 	QString ginstallDir;
3507 	QString installDir;
3508 	QString isotmpf = randtmpfile::getrandfilename(ubntmpf, "iso");
3509 	#ifdef Q_OS_WIN32
3510 	if (installType == tr("Hard Disk"))
3511 	{
3512 		ginstallDir = "unetbtin/";
3513 	}
3514 	if (installType == tr("USB Drive"))
3515 	{
3516 		ginstallDir = "";
3517 	}
3518 	installDir = ginstallDir;
3519 	targetDev = QString("%1").arg(targetDrive).remove("\\");
3520 	rawtargetDev = targetDev;
3521 	#endif
3522 	#ifdef Q_OS_UNIX
3523 	if (installType == tr("Hard Disk"))
3524 	{
3525 		QString devnboot = locatedevicenode("/boot");
3526 		if (devnboot == "NOT FOUND")
3527 		{
3528 			ginstallDir = "boot/";
3529 			installDir = ginstallDir;
3530 			targetDev = locatedevicenode("/");
3531 		}
3532 		else
3533 		{
3534 			ginstallDir = "";
3535 			installDir = "boot/";
3536 			targetDev = devnboot;
3537 		}
3538 		devluid = getdevluid(targetDev);
3539 	}
3540 	if (installType == tr("USB Drive"))
3541 	{
3542 #ifdef Q_OS_LINUX
3543 		targetDev = driveselect->currentText();
3544 		devluid = getdevluid(targetDev);
3545 		ginstallDir = "";
3546 		installDir = ginstallDir;
3547 		targetDrive = QString("%1/").arg(locatemountpoint(targetDev));
3548 #endif
3549 #ifdef Q_OS_FREEBSD
3550 		QStringList driveinfo = driveselect->currentText().split(":");
3551 		if (driveinfo.size() < 2) {
3552 			QTextStream out(stdout);
3553 			out << "/!\\ Target drive must be passed as "
3554 			    "<device-name>:<mount-point>" << endl << flush;
3555 			QApplication::exit();
3556 			exit(1);
3557 		}
3558 		targetDev = driveinfo.at(0);
3559 		installDir = ginstallDir = "";
3560 		targetDrive = QString("%1/").arg(driveinfo.at(1));
3561 #endif
3562 	}
3563 #ifdef Q_OS_LINUX
3564 	if (targetDev.contains(QRegExp("p\\d$")))
3565 		rawtargetDev = QString(targetDev).remove(QRegExp("p\\d$"));
3566 	else
3567 		rawtargetDev = QString(targetDev).remove(QRegExp("\\d$"));
3568 #endif
3569 #ifdef Q_OS_UNIX
3570 	rawtargetDev = QString(targetDev).remove(QRegExp("s\\d$"));
3571 #endif
3572 	#endif
3573 #ifndef Q_OS_UNIX
3574 	devluid = getdevluid(targetDev);
3575 #endif
3576 	kernelLine = "kernel";
3577 	kernelLoc = QString("/%1ubnkern").arg(ginstallDir);
3578 	initrdLine = "initrd";
3579 	slinitrdLine = "initrd=";
3580 	initrdLoc = QString("/%1ubninit").arg(ginstallDir);
3581 #ifdef NOINITRD
3582 	initrdLoc = "";
3583 	initrdOpts = "";
3584 	initrdLine = "";
3585 	slinitrdLine = "";
3586 #endif
3587 #ifdef NODEFAULTKERNEL
3588 	kernelLoc = "";
3589 #endif
3590 	targetPath = QDir::toNativeSeparators(QString("%1%2").arg(targetDrive).arg(installDir));
3591 	QDir dir;
3592 	if (!dir.exists(targetPath))
3593 	{
3594 		dir.mkpath(targetPath);
3595 	}
3596 	if (QFile::exists(QString("%1ubnkern").arg(targetPath)))
3597 	{
3598 		overwritefileprompt(QString("%1ubnkern").arg(targetPath));
3599 	}
3600 	if (QFile::exists(QString("%1ubninit").arg(targetPath)))
3601 	{
3602 		overwritefileprompt(QString("%1ubninit").arg(targetPath));
3603 	}
3604 	if (radioFloppy->isChecked())
3605 	{
3606 		if (diskimagetypeselect->currentIndex() == diskimagetypeselect->findText(tr("Floppy")))
3607 		{
3608 			instIndvfl("memdisk", QString("%1ubnkern").arg(targetPath));
3609 			if (!FloppyPath->text().startsWith("http://") && !FloppyPath->text().startsWith("ftp://"))
3610 				QFile::copy(FloppyPath->text(), QString("%1ubninit").arg(targetPath));
3611 			else
3612 				downloadfile(FloppyPath->text(), QString("%1ubninit").arg(targetPath));
3613 		}
3614 		if (diskimagetypeselect->currentIndex() == diskimagetypeselect->findText(tr("ISO")))
3615 		{
3616 			if (!FloppyPath->text().startsWith("http://") && !FloppyPath->text().startsWith("ftp://"))
3617 				extractiso(FloppyPath->text());
3618 			else
3619 			{
3620 				downloadfile(FloppyPath->text(), isotmpf);
3621 				extractiso(isotmpf);
3622 			}
3623 			if (QFile::exists(QString("%1sevnz.exe").arg(ubntmpf)))
3624 			{
3625 				rmFile(QString("%1sevnz.exe").arg(ubntmpf));
3626 			}
3627 			if (QFile::exists(QString("%1\\7z.dll").arg(ubntmpf)))
3628 			{
3629 				rmFile(QString("%1\\7z.dll").arg(ubntmpf));
3630 			}
3631 		}
3632 	}
3633 	else if (radioManual->isChecked())
3634 	{
3635 		if (!KernelPath->text().startsWith("http://") && !KernelPath->text().startsWith("ftp://"))
3636 			QFile::copy(KernelPath->text(), QString("%1ubnkern").arg(targetPath));
3637 		else
3638 			downloadfile(KernelPath->text(), QString("%1ubnkern").arg(targetPath));
3639 		if (!InitrdPath->text().startsWith("http://") && !InitrdPath->text().startsWith("ftp://"))
3640 			QFile::copy(InitrdPath->text(), QString("%1ubninit").arg(targetPath));
3641 		else
3642 			downloadfile(InitrdPath->text(), QString("%1ubninit").arg(targetPath));
3643 		kernelOpts = OptionEnter->text();
3644 	}
3645 	else if (radioDistro->isChecked())
3646 	{
3647 		nameDistro = distroselect->currentText();
3648 		nameVersion = dverselect->currentText();
3649 		if (nameVersion.contains("_Live"))
3650 		{
3651 			nameVersion.remove("_Live");
3652 			islivecd = true;
3653 		}
3654 		else
3655 		{
3656 			islivecd = false;
3657 		}
3658 		if (nameVersion.contains("_NetInstall"))
3659 		{
3660 			nameVersion.remove("_NetInstall");
3661 			isnetinstall = true;
3662 		}
3663 		if (nameVersion.contains("_HdMedia"))
3664 		{
3665 			nameVersion.remove("_HdMedia");
3666 			ishdmedia = true;
3667 		}
3668 		if (nameVersion.contains("_x64"))
3669 		{
3670 			nameVersion.remove("_x64");
3671 			isarch64 = true;
3672 		}
3673 		else
3674 		{
3675 			isarch64 = false;
3676 		}
3677 		QString cpuarch;
3678 		QString relname = nameVersion.toLower();
3679 		#include "customdistrolst.cpp"
3680 		if (QFile::exists(QString("%1sevnz.exe").arg(ubntmpf)))
3681 		{
3682 			rmFile(QString("%1sevnz.exe").arg(ubntmpf));
3683 		}
3684 		if (QFile::exists(QString("%1\\7z.dll").arg(ubntmpf)))
3685 		{
3686 			rmFile(QString("%1\\7z.dll").arg(ubntmpf));
3687 		}
3688 		if (downloadFailed)
3689 		{
3690 			return;
3691 		}
3692 	}
3693 	if (!sdesc1->text().contains(trdone))
3694 	{
3695 		sdesc1->setText(QString(sdesc1->text()).remove("<b>").replace(trcurrent+"</b>", trdone));
3696 	}
3697 	if (sdesc2->text().contains(trcurrent))
3698 	{
3699 		sdesc2->setText(QString(sdesc2->text()).remove("<b>").replace(trcurrent+"</b>", trdone));
3700 	}
3701 	else
3702 	{
3703 		sdesc2->setText(QString("%1 %2").arg(sdesc2->text()).arg(trdone));
3704 	}
3705 	sdesc3->setText(QString("<b>%1 %2</b>").arg(sdesc3->text()).arg(trcurrent));
3706 	tprogress->setValue(0);
3707 	if (this->persistenceSpaceMB > 0 && !issalt)
3708 	{
3709 		this->kernelOpts += " persistent";
3710 		for (int i = 0; i < this->extraoptionsPL.second.second.size(); ++i)
3711 		{
3712 			this->extraoptionsPL.second.second[i] += " persistent";
3713 		}
3714 	}
3715 	instDetType();
3716 }
3717 
instDetType()3718 void unetbootin::instDetType()
3719 {
3720 	if (installType == tr("Hard Disk"))
3721 	{
3722 		runinsthdd();
3723 	}
3724 	if (installType == tr("USB Drive"))
3725 	{
3726 		runinstusb();
3727 	}
3728 }
3729 
3730 #ifdef Q_OS_UNIX
3731 
writegrub2cfg()3732 void unetbootin::writegrub2cfg()
3733 {
3734 	QFile menulst;
3735 	menulst.setFileName("/boot/grub/grub.cfg");
3736 	if (QFile::exists(QString("%1.bak").arg(menulst.fileName())))
3737 		rmFile(QString("%1.bak").arg(menulst.fileName()));
3738 	QFile::copy(menulst.fileName(), QString("%1.bak").arg(menulst.fileName()));
3739 	QFile bkmenulst(QString("%1.bak").arg(menulst.fileName()));
3740 	bkmenulst.open(QIODevice::ReadOnly | QIODevice::Text);
3741 	QTextStream bkmenulstout(&bkmenulst);
3742 	menulst.open(QIODevice::WriteOnly | QIODevice::Text);
3743 	QTextStream menulstout(&menulst);
3744 	QRegExp mlstchkistimeout("\\s{0,}set\\s{1,}timeout=\\d{1,}.{0,}", Qt::CaseInsensitive);
3745 	QStringList ecurmenulstTextL;
3746 	bool mlstmustreplacetimeout = true;
3747 	QString menulstCurLine;
3748 	while (!bkmenulstout.atEnd())
3749 	{
3750 		menulstCurLine = bkmenulstout.readLine();
3751 		if (mlstmustreplacetimeout && mlstchkistimeout.exactMatch(menulstCurLine))
3752 		{
3753 			ecurmenulstTextL.append("set timeout=15");
3754 			mlstmustreplacetimeout = false;
3755 		}
3756 		else
3757 		{
3758 			ecurmenulstTextL.append(menulstCurLine);
3759 		}
3760 	}
3761 	QString ecurmenulstText = ecurmenulstTextL.join("\n");
3762 	QString menulstxt = QString(
3763 	"%9\n\n"
3764 #ifndef NODEFAULTBOOT
3765 	"\nmenuentry \"" UNETBOOTINB"\" {\n"
3766 	"\tset root=%8\n"
3767 	"\t%1 %2 %3 %4\n"
3768 	"\t%5 %6 %7\n"
3769 	"}\n"
3770 #endif
3771 	).arg(kernelLine.replace("kernel", "linux")).arg(kernelParam).arg(kernelLoc).arg(kernelOpts).arg(initrdLine).arg(initrdLoc).arg(initrdOpts)
3772 	.arg(getGrub2Notation(targetDev)).arg(ecurmenulstText)
3773 	;
3774 	if (!extraoptionsPL.first.first.isEmpty())
3775 	{
3776 		for (int i = 0; i < extraoptionsPL.first.first.size(); ++i)
3777 		{
3778 			menulstxt.append(QString("\nmenuentry \"%1\" {\n"
3779 			"\tset root=%5\n"
3780 			"\tlinux %2 %4\n"
3781 			"\tinitrd %3\n"
3782 			"}\n").arg(QString(extraoptionsPL.second.first.at(i)).remove("^")).arg(extraoptionsPL.first.first.at(i)).arg(extraoptionsPL.first.second.at(i)).arg(extraoptionsPL.second.second.at(i))
3783 			.arg(getGrubNotation(targetDev))
3784 			);
3785 		}
3786 	}
3787 	menulstout << menulstxt << endl;
3788 	menulst.close();
3789 }
3790 
3791 #endif
3792 
runinsthdd()3793 void unetbootin::runinsthdd()
3794 {
3795 	this->tprogress->setValue(this->tprogress->maximum()/3);
3796 	#ifdef Q_OS_UNIX
3797 	if (QFile::exists("/boot/grub/grub.cfg")) // has grub2
3798 	{
3799 		pdesc1->setText(tr("Configuring grub2 on %1").arg(targetDev));
3800 		writegrub2cfg();
3801 		if (!QFile::exists("/boot/grub/menu.lst")) // grub2-only
3802 		{
3803 			QSettings install(QSettings::SystemScope, "UNetbootin");
3804 			install.setValue("Location", "/");
3805 			fininstall();
3806 			return;
3807 		}
3808 	}
3809 	#endif
3810 	#ifdef Q_OS_WIN32
3811 	pdesc1->setText(tr("Configuring grldr on %1").arg(targetDev));
3812 	if (QFile::exists(QDir::toNativeSeparators(QString("%1unetbtin.exe").arg(targetDrive))))
3813 	{
3814 		rmFile(QDir::toNativeSeparators(QString("%1unetbtin.exe").arg(targetDrive)));
3815 	}
3816 	QFile::copy(appLoc, QDir::toNativeSeparators(QString("%1unetbtin.exe").arg(targetDrive)));
3817 	QFile::setPermissions(QDir::toNativeSeparators(QString("%1unetbtin.exe").arg(targetDrive)), QFile::ReadOther|QFile::WriteOther|QFile::ExeOther);
3818 	if (QFile::exists(QDir::toNativeSeparators(QString("%1ubnldr").arg(targetDrive))))
3819 	{
3820 		overwritefileprompt(QDir::toNativeSeparators(QString("%1ubnldr").arg(targetDrive)));
3821 	}
3822 	instIndvfl("ubnldr", QString("%1ubnldr").arg(targetDrive));
3823 	if (QFile::exists(QDir::toNativeSeparators(QString("%1ubnldr.mbr").arg(targetDrive))))
3824 	{
3825 		overwritefileprompt(QDir::toNativeSeparators(QString("%1ubnldr.mbr").arg(targetDrive)));
3826 	}
3827 	instIndvfl("ubnldr.mbr", QString("%1ubnldr.mbr").arg(targetDrive));
3828 	if (QFile::exists(QDir::toNativeSeparators(QString("%1ubnldr.exe").arg(targetDrive))))
3829 	{
3830 		overwritefileprompt(QDir::toNativeSeparators(QString("%1ubnldr.exe").arg(targetDrive)));
3831 	}
3832 	instIndvfl("ubnldr.exe", QString("%1ubnldr.exe").arg(targetDrive));
3833 	#endif
3834 	QFile menulst;
3835 	#ifdef Q_OS_WIN32
3836 	menulst.setFileName(QString("%1menu.lst").arg(targetPath));
3837 	#endif
3838 	#ifdef Q_OS_UNIX
3839 	pdesc1->setText(tr("Configuring grub on %1").arg(targetDev));
3840 	menulst.setFileName("/boot/grub/menu.lst");
3841 	if (QFile::exists(QString("%1.bak").arg(menulst.fileName())))
3842 		rmFile(QString("%1.bak").arg(menulst.fileName()));
3843 	QFile::copy(menulst.fileName(), QString("%1.bak").arg(menulst.fileName()));
3844 	QFile bkmenulst(QString("%1.bak").arg(menulst.fileName()));
3845 	bkmenulst.open(QIODevice::ReadOnly | QIODevice::Text);
3846 	QTextStream bkmenulstout(&bkmenulst);
3847 	#endif
3848 	menulst.open(QIODevice::WriteOnly | QIODevice::Text);
3849 	QTextStream menulstout(&menulst);
3850 	#ifdef Q_OS_UNIX
3851 	QRegExp mlstchkistimeout("\\s{0,}timeout\\s{1,}\\d{1,}.{0,}", Qt::CaseInsensitive);
3852 	QRegExp mlstchkishiddenmenu("\\s{0,}hiddenmenu.{0,}", Qt::CaseInsensitive);
3853 	QStringList ecurmenulstTextL;
3854 	bool mlstmustreplacetimeout = true;
3855 	bool mlstmustreplacehiddenmenu = true;
3856 	QString menulstCurLine;
3857 	while (!bkmenulstout.atEnd())
3858 	{
3859 		menulstCurLine = bkmenulstout.readLine();
3860 		if (mlstmustreplacehiddenmenu && mlstchkishiddenmenu.exactMatch(menulstCurLine))
3861 		{
3862 			ecurmenulstTextL.append("#hiddenmenu");
3863 			mlstmustreplacehiddenmenu = false;
3864 		}
3865 		else if (mlstmustreplacetimeout && mlstchkistimeout.exactMatch(menulstCurLine))
3866 		{
3867 			ecurmenulstTextL.append("timeout\t\t15");
3868 			mlstmustreplacetimeout = false;
3869 		}
3870 		else
3871 		{
3872 			ecurmenulstTextL.append(menulstCurLine);
3873 		}
3874 	}
3875 	QString ecurmenulstText = ecurmenulstTextL.join("\n");
3876 	#endif
3877 	QString menulstxt = QString(
3878 	#ifdef Q_OS_UNIX
3879 	"%9\n\n"
3880 	#endif
3881 	#ifdef Q_OS_WIN32
3882 	"default 0\n"
3883 	"timeout 10\n"
3884 	#endif
3885 #ifndef NODEFAULTBOOT
3886 	"\ntitle " UNETBOOTINB"\n"
3887 	#ifdef Q_OS_WIN32
3888 	"find --set-root %3\n"
3889 	#endif
3890 	#ifdef Q_OS_UNIX
3891 	"root %8\n"
3892 	#endif
3893 	"%1 %2 %3 %4\n"
3894 	"%5 %6 %7\n"
3895 	"boot\n"
3896 #endif
3897 	).arg(kernelLine).arg(kernelParam).arg(kernelLoc).arg(kernelOpts).arg(initrdLine).arg(initrdLoc).arg(initrdOpts)
3898 
3899 	#ifdef Q_OS_UNIX
3900 	.arg(getGrubNotation(targetDev)).arg(ecurmenulstText)
3901 	#endif
3902 	;
3903 	if (!extraoptionsPL.first.first.isEmpty())
3904 	{
3905 		for (int i = 0; i < extraoptionsPL.first.first.size(); ++i)
3906 		{
3907 			menulstxt.append(QString("\ntitle %1\n"
3908 			#ifdef Q_OS_WIN32
3909 			"find --set-root %2\n"
3910 			#endif
3911 			#ifdef Q_OS_UNIX
3912 			"root %5\n"
3913 			#endif
3914 			"kernel %2 %4\n"
3915 			"initrd %3\n"
3916 			"boot\n").arg(QString(extraoptionsPL.second.first.at(i)).remove("^")).arg(extraoptionsPL.first.first.at(i)).arg(extraoptionsPL.first.second.at(i)).arg(extraoptionsPL.second.second.at(i))
3917 			#ifdef Q_OS_UNIX
3918 			.arg(getGrubNotation(targetDev))
3919 			#endif
3920 			);
3921 		}
3922 	}
3923 	menulstout << menulstxt << endl;
3924 	menulst.close();
3925 	#ifdef Q_OS_WIN32
3926 	QSettings install("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\UNetbootin", QSettings::NativeFormat);
3927 	install.setValue("Location", targetDrive);
3928 	install.setValue("DisplayName", "UNetbootin");
3929 	install.setValue("UninstallString", QDir::toNativeSeparators(QString("%1unetbtin.exe").arg(targetDrive)));
3930 	//QSettings runonce("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce", QSettings::NativeFormat);
3931 	//runonce.setValue("UNetbootin Uninstaller", QDir::toNativeSeparators(QString("%1unetbtin.exe").arg(targetDrive)));
3932 	if (QSysInfo::WindowsVersion == QSysInfo::WV_32s || QSysInfo::WindowsVersion == QSysInfo::WV_95 || QSysInfo::WindowsVersion == QSysInfo::WV_98 || QSysInfo::WindowsVersion == QSysInfo::WV_Me)
3933 	{
3934 		configsysEdit();
3935 	}
3936 	else if (QSysInfo::WindowsVersion == QSysInfo::WV_NT || QSysInfo::WindowsVersion == QSysInfo::WV_2000 || QSysInfo::WindowsVersion == QSysInfo::WV_XP || QSysInfo::WindowsVersion == QSysInfo::WV_2003 )
3937 	{
3938 		bootiniEdit();
3939 	}
3940 	else if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA) //|| QSysInfo::WindowsVersion == QSysInfo::WV_WINDOWS7) // TODO when upgrading to latest Qt
3941 	{
3942 		vistabcdEdit();
3943 	}
3944 	else
3945 	{
3946 		configsysEdit();
3947 		bootiniEdit();
3948 		vistabcdEdit();
3949 	}
3950 	#endif
3951 	#ifdef Q_OS_UNIX
3952 	QSettings install(QSettings::SystemScope, "UNetbootin");
3953 	install.setValue("Location", "/");
3954 	#endif
3955 	fininstall();
3956 }
3957 
rmFile(QFile & fn)3958 void unetbootin::rmFile(QFile &fn)
3959 {
3960 	if (!fn.exists()) return;
3961 	fn.setPermissions(QFile::WriteUser);
3962 	fn.remove();
3963 #ifdef Q_OS_UNIX
3964 	callexternapp("sync", "");
3965 #endif
3966 }
3967 
rmFile(const QString & fn)3968 void unetbootin::rmFile(const QString &fn)
3969 {
3970 	if (!QFile::exists(fn)) return;
3971 	QFile::setPermissions(fn, QFile::WriteUser);
3972 	QFile::remove(fn);
3973 #ifdef Q_OS_UNIX
3974 	callexternapp("sync", "");
3975 #endif
3976 }
3977 
mvFile(QFile & fn,QFile & outfn)3978 void unetbootin::mvFile(QFile &fn, QFile &outfn)
3979 {
3980 	rmFile(outfn);
3981 	fn.rename(outfn.fileName());
3982 #ifdef Q_OS_UNIX
3983 	callexternapp("sync", "");
3984 #endif
3985 }
3986 
mvFile(const QString & fn,const QString & outfn)3987 void unetbootin::mvFile(const QString &fn, const QString &outfn)
3988 {
3989 	rmFile(outfn);
3990 	QFile::rename(fn, outfn);
3991 #ifdef Q_OS_UNIX
3992 	callexternapp("sync", "");
3993 #endif
3994 }
3995 
replaceTextInFile(QString repfilepath,QRegExp replaceme,QString replacewith)3996 void unetbootin::replaceTextInFile(QString repfilepath, QRegExp replaceme, QString replacewith)
3997 {
3998 	QFile repfileF(repfilepath);
3999 	randtmpfile nrepfileF(QFileInfo(repfilepath).canonicalPath(), "cfg");
4000 	QString nrepfilepath = QFileInfo(nrepfileF).canonicalFilePath();
4001 	repfileF.open(QIODevice::ReadOnly | QIODevice::Text);
4002 	nrepfileF.open(QIODevice::WriteOnly | QIODevice::Text);
4003 	QTextStream repfileTS(&repfileF);
4004 	QTextStream nrepfileTS(&nrepfileF);
4005 	while (!repfileTS.atEnd())
4006 	{
4007 		nrepfileTS << repfileTS.readLine().replace(replaceme, replacewith) << "\n";
4008 	}
4009 	repfileF.close();
4010 	rmFile(repfilepath);
4011 	nrepfileF.rename(repfilepath);
4012 	nrepfileF.close();
4013 	//mvFile(nrepfilepath, repfilepath);
4014 }
4015 
setLabel(QString devname,QString newlabel)4016 void unetbootin::setLabel(QString devname, QString newlabel)
4017 {
4018 #ifdef Q_OS_LINUX
4019 	if (isext2)
4020 	{
4021 		callexternapp(e2labelcommand, devname+" "+newlabel);
4022 	}
4023 	else
4024 	{
4025 		callexternapp(mlabelcommand, "-i "+devname+" ::"+newlabel);
4026 	}
4027 #endif
4028 #ifdef Q_OS_MAC
4029 	callexternapp("diskutil", "rename "+devname+" "+newlabel);
4030 #endif
4031 #ifdef Q_OS_WIN32
4032 	callexternapp("label", devname+" "+newlabel);
4033 #endif
4034 	this->devlabel = QString(newlabel);
4035 	if (this->devluid.startsWith("LABEL="))
4036 		this->devluid = "LABEL="+newlabel;
4037 #ifdef Q_OS_MAC
4038 	this->targetPath = this->locatemountpoint(devname) + "/";
4039 	this->targetDrive = this->targetPath;
4040 #endif
4041 }
4042 
fixkernelbootoptions(const QString & cfgfileCL)4043 QString unetbootin::fixkernelbootoptions(const QString &cfgfileCL)
4044 {
4045 	if (cfgfileCL.contains("archisolabel=") && (this->devlabel == "" || this->devlabel == "None"))
4046 	{
4047 		this->devlabel = this->getlabel(this->targetDev);
4048 		if  (this->installType == tr("USB Drive") && (this->devlabel == "" || this->devlabel == "None"))
4049 		{
4050 			QString isolabelopt = QString(cfgfileCL).trimmed();
4051 			int startIdx = isolabelopt.indexOf("archisolabel=");
4052 			if (startIdx >= 0)
4053 			{
4054 				isolabelopt = isolabelopt.right(isolabelopt.size() - startIdx - QString("archisolabel=").size()).trimmed();
4055 				int endIdx = isolabelopt.indexOf(" ");
4056 				if (endIdx > 0)
4057 				{
4058 					isolabelopt = isolabelopt.left(endIdx);
4059 					setLabel(this->targetDev, isolabelopt);
4060 				}
4061 			}
4062 		}
4063 	}
4064     if ((this->devlabel == "" || this->devlabel == "None") && devluid.contains("LABEL") && (cfgfileCL.contains(QRegExp("root=\\S{0,}LABEL=\\S{0,}")) || cfgfileCL.contains(QRegExp("root=\\S{0,}CDLABEL=\\S{0,}"))))
4065     {
4066         setLabel(this->targetDev, "LIVE");
4067     }
4068     QString ncfgfileCL = cfgfileCL;
4069     if (ncfgfileCL.contains("root=live:CDLABEL"))
4070     {
4071         ncfgfileCL = QString(ncfgfileCL)
4072         .replace(QRegExp("root=\\S{0,}LABEL=\\S{0,}"), QString("root=live:%1").arg(devluid))
4073         .replace(QRegExp("root=\\S{0,}CDLABEL=\\S{0,}"), QString("root=live:%1").arg(devluid));
4074     }
4075     else
4076     {
4077         ncfgfileCL = QString(ncfgfileCL)
4078         .replace(QRegExp("root=\\S{0,}LABEL=\\S{0,}"), QString("root=%1").arg(devluid))
4079         .replace(QRegExp("root=\\S{0,}CDLABEL=\\S{0,}"), QString("root=%1").arg(devluid));
4080     }
4081     return QString(ncfgfileCL)
4082 	.replace("rootfstype=iso9660", "rootfstype=auto")
4083     .replace("theme:sabayon", "theme:sabayon cdroot_type=vfat")
4084 	.replace("pmedia=cd", "pmedia=usbflash")
4085 	.replace(QRegExp("archisolabel=\\S{0,}"), QString("archisolabel=%1").arg(devlabel))
4086 	.trimmed();
4087 }
4088 
logText(const QString & text)4089 void unetbootin::logText(const QString &text)
4090 {
4091     return;
4092     /*
4093     if (targetPath.isNull() || targetPath.isEmpty())
4094     {
4095         loggedLinesNotYetWritten.append(text);
4096         return;
4097     }
4098     if (logStream == 0)
4099     {
4100         logFile = new QFile(QString("%1unetbootin-log.txt").arg(targetPath));
4101         logFile->open(QIODevice::WriteOnly | QIODevice::Text);
4102         logStream = new QTextStream(logFile);
4103         for (int i = 0; i < loggedLinesNotYetWritten.size(); ++i)
4104         {
4105             *logStream << loggedLinesNotYetWritten.at(i) << endl;
4106         }
4107         loggedLinesNotYetWritten.clear();
4108     }
4109     *logStream << text << endl;
4110     */
4111 }
4112 
finishLogging()4113 void unetbootin::finishLogging()
4114 {
4115     if (logFile != 0)
4116     {
4117         logFile->close();
4118     }
4119 }
4120 
writeTextToFile(const QString & text,const QString & filePath)4121 void unetbootin::writeTextToFile(const QString &text, const QString &filePath)
4122 {
4123     QFile syslinuxcfg(filePath);
4124     if (syslinuxcfg.exists())
4125     {
4126         rmFile(syslinuxcfg);
4127     }
4128     syslinuxcfg.open(QIODevice::WriteOnly | QIODevice::Text);
4129     QTextStream syslinuxcfgout(&syslinuxcfg);
4130     syslinuxcfgout << text << endl;
4131     syslinuxcfg.close();
4132 }
4133 
runinstusb()4134 void unetbootin::runinstusb()
4135 {
4136 	this->tprogress->setValue(this->tprogress->maximum()/3);
4137 	pdesc1->setText(tr("Installing syslinux to %1").arg(targetDev));
4138 	#ifdef Q_OS_WIN32
4139 	QString sysltfloc = instTempfl("syslinux.exe", "exe");
4140 	callexternapp(sysltfloc, QString("-ma %1").arg(targetDev));
4141 	rmFile(sysltfloc);
4142 	#endif
4143 	#ifdef STATICLINUX
4144 	if (QFile::exists(syslinuxcommand))
4145 		rmFile(syslinuxcommand);
4146 	instIndvfl("ubnsylnx", syslinuxcommand);
4147 		QFile::setPermissions(syslinuxcommand, QFile::ReadOwner|QFile::ExeOwner|QFile::ReadGroup|QFile::ExeGroup|QFile::ReadOther|QFile::ExeOther|QFile::WriteOwner);
4148 //	chmod(syslinuxcommand, S_IRUSR|S_IRGRP|S_IROTH|S_IRWXU);
4149 		if (QFile::exists(extlinuxcommand))
4150 				rmFile(extlinuxcommand);
4151 		instIndvfl("ubnexlnx", extlinuxcommand);
4152 		QFile::setPermissions(extlinuxcommand, QFile::ReadOwner|QFile::ExeOwner|QFile::ReadGroup|QFile::ExeGroup|QFile::ReadOther|QFile::ExeOther|QFile::WriteOwner);
4153 	#endif
4154 #ifdef Q_OS_LINUX
4155 		isext2 = false;
4156 		if (!volidcommand.isEmpty())
4157 		{
4158 			if (callexternapp(volidcommand, QString("-t %2").arg(targetDev)).contains(QRegExp("(ext2|ext3|ext4)")))
4159 				isext2 = true;
4160 		}
4161 		else
4162 		{
4163 			QString tstrblk = callexternapp(blkidcommand, QString("-s TYPE %2").arg(targetDev));
4164 			if (tstrblk.contains('='))
4165 			{
4166 				if (tstrblk.contains(QRegExp("(ext2|ext3|ext4)")))
4167 					isext2 = true;
4168 			}
4169 		}
4170 		if (isext2)
4171 		{
4172 			pdesc1->setText(tr("Installing extlinux to %1").arg(targetDev));
4173 			callexternapp(extlinuxcommand, QString("-i \"%1\"").arg(targetPath));
4174 		}
4175 		else
4176 			callexternapp(syslinuxcommand, targetDev);
4177 		if (rawtargetDev != targetDev)
4178 		{
4179 			// make active
4180 			if (sfdiskcommand != "") {
4181 				// use sfdisk if available
4182 				callexternapp(sfdiskcommand, QString("%1 -A %2").arg(rawtargetDev, QString(targetDev).remove(rawtargetDev).remove("p")));
4183 			} else {
4184 				// use fdisk if sfdisk is unavailable
4185 				bool isOk = false;
4186                 int partitionNumber = QString(targetDev).remove(rawtargetDev).remove("p").toInt(&isOk, 10);
4187 				if (isOk)
4188 				{
4189 					QString output = callexternapp("fdisk", "-l");
4190 					QStringList outputL = output.split('\n');
4191 					outputL = outputL.filter(targetDev);
4192 					if (outputL.size() > 0)
4193 					{
4194 						outputL = outputL.filter("*");
4195 						bool isActive = outputL.size() > 0;
4196 						if (!isActive)
4197 						{
4198 							QString fdiskWriteToStdin = "a\n";
4199 							fdiskWriteToStdin += (QString::number(partitionNumber) + "\n");
4200 							fdiskWriteToStdin += "w\n";
4201 							callexternappWriteToStdin("fdisk", rawtargetDev, fdiskWriteToStdin);
4202 						}
4203 					}
4204 				}
4205 			}
4206 			QFile usbmbrF(rawtargetDev);
4207 			QFile mbrbinF(":/mbr.bin");
4208 			#ifdef NOSTATIC
4209 			mbrbinF.setFileName(QFile::exists("/usr/share/syslinux/mbr.bin") ? "/usr/share/syslinux/mbr.bin" : "/usr/lib/syslinux/mbr.bin");
4210 			if (QFile::exists("/usr/lib/syslinux/mbr/mbr.bin"))
4211 				mbrbinF.setFileName("/usr/lib/syslinux/mbr/mbr.bin");
4212 			#endif
4213 			usbmbrF.open(QIODevice::WriteOnly);
4214 			mbrbinF.open(QIODevice::ReadOnly);
4215 			usbmbrF.write(mbrbinF.readAll());
4216 			mbrbinF.close();
4217 			usbmbrF.close();
4218 		}
4219 #endif
4220 #ifdef Q_OS_MAC
4221         callexternapp("sync", "");
4222         callexternapp("diskutil", "umount "+targetDev);
4223         callexternapp("sync", "");
4224         callexternapp("hdiutil", "unmount "+targetDev);
4225         callexternapp("sync", "");
4226         callexternapp(resourceDir.absoluteFilePath("mkbootable"), targetDev);
4227        /*
4228         callexternapp("sync", "");
4229         callexternapp("diskutil", "umount "+targetDev);
4230         callexternapp("sync", "");
4231         callexternapp("hdiutil", "unmount "+targetDev);
4232         callexternapp("sync", "");
4233 		QFile usbmbrF(rawtargetDev);
4234 		QFile mbrbinF(resourceDir.absoluteFilePath("mbr.bin"));
4235 		usbmbrF.open(QIODevice::WriteOnly);
4236 		mbrbinF.open(QIODevice::ReadOnly);
4237 		usbmbrF.write(mbrbinF.readAll());
4238 		mbrbinF.close();
4239 		usbmbrF.close();
4240         */
4241         callexternapp("sync", "");
4242 		callexternapp("diskutil", "mount "+targetDev);
4243         callexternapp("sync", "");
4244 #endif
4245 #ifndef XPUD
4246 	if (!dontgeneratesyslinuxcfg)
4247 	{
4248 	QString syslinuxcfgtxt = QString("default menu.c32\n"
4249 	"prompt 0\n"
4250 	"menu title UNetbootin\n"
4251 	"timeout 100\n\n"
4252 #ifndef NODEFAULTBOOT
4253 	"label unetbootindefault\n"
4254 	"menu label Default\n"
4255 	"kernel %1\n"
4256 	"append %4%2 %3\n"
4257 #endif
4258 	).arg(kernelLoc, initrdLoc, kernelOpts, slinitrdLine);
4259 
4260 	if (!extraoptionsPL.first.first.isEmpty())
4261 	{
4262 		for (int i = 0; i < extraoptionsPL.first.first.size(); ++i)
4263 		{
4264 			syslinuxcfgtxt.append(QString("\nlabel %5\n"
4265 			"menu label %1\n"
4266 			"kernel %2\n"
4267 			"append %6%3 %4\n").arg(extraoptionsPL.second.first.at(i)).arg(extraoptionsPL.first.first.at(i)).arg(extraoptionsPL.first.second.at(i)).arg(extraoptionsPL.second.second.at(i)).arg(QString("ubnentry%1").arg(i)).arg(slinitrdLine));
4268 		}
4269 	}
4270     writeTextToFile(syslinuxcfgtxt, QString("%1syslinux.cfg").arg(targetPath));
4271 	}
4272 	else
4273 	{
4274 		for (int j = 0; j < locatedsyslinuxcfgfiles.size(); ++j)
4275 		{
4276 			QString syslpathloc = QFileInfo(locatedsyslinuxcfgfiles.at(j)).path();
4277 			if (syslpathloc == ".") syslpathloc = "";
4278 			if (syslpathloc.contains(QDir::toNativeSeparators("/")))
4279 			{
4280 				if (!syslpathloc.endsWith(QDir::toNativeSeparators("/")))
4281 					syslpathloc.append(QDir::toNativeSeparators("/"));
4282 			}
4283 			else
4284 			{
4285 				if (!syslpathloc.endsWith("/"))
4286 					syslpathloc.append("/");
4287 			}
4288 			QString abssyslpathloc = QDir::fromNativeSeparators(QString(syslpathloc));
4289 			if (!abssyslpathloc.startsWith("/"))
4290 				abssyslpathloc.prepend("/");
4291 			instIndvfl("menu.c32", QString("%1%2menu.c32").arg(targetPath).arg(syslpathloc));
4292             instIndvfl("libutil.c32", QString("%1%2libutil.c32").arg(targetPath).arg(syslpathloc));
4293             instIndvfl("libcom32.c32", QString("%1%2libcom32.c32").arg(targetPath).arg(syslpathloc));
4294 			QString syslrealcfgloc = QString(locatedsyslinuxcfgfiles.at(j)).replace("isolinux.cfg", "syslinux.cfg").replace("extlinux.conf", "syslinux.cfg");
4295 			if (syslrealcfgloc != locatedsyslinuxcfgfiles.at(j))
4296 			{
4297 				QFile::copy(QString("%1%2").arg(targetPath).arg(locatedsyslinuxcfgfiles.at(j)), QString("%1%2").arg(targetPath).arg(syslrealcfgloc));
4298 			}
4299 			replaceTextInFile(QString("%1%2").arg(targetPath).arg(syslrealcfgloc), QRegExp("\\S{0,}vesamenu.c32"), QString("%1menu.c32").arg(abssyslpathloc));
4300 			#ifdef Q_OS_UNIX
4301 			if (isext2)
4302 			{
4303 				QFile::copy(QString("%1%2").arg(targetPath).arg(locatedsyslinuxcfgfiles.at(j)), QString("%1%2extlinux.conf").arg(targetPath).arg(syslpathloc));
4304 				QString extlpathloc = QString(syslpathloc).replace("syslinux", "extlinux");
4305 				if (syslpathloc != extlpathloc)
4306 					callexternapp("ln", QString("-s %1 %2").arg(syslpathloc).arg(extlpathloc));
4307 			}
4308 			#endif
4309 		}
4310 	}
4311 #endif
4312 		#ifdef Q_OS_UNIX
4313 		if (!dontgeneratesyslinuxcfg && isext2)
4314 			QFile::copy(QString("%1syslinux.cfg").arg(targetPath), QString("%1extlinux.conf").arg(targetPath));
4315 		#endif
4316 		if (!dontgeneratesyslinuxcfg)
4317         {
4318             instIndvfl("menu.c32", QString("%1menu.c32").arg(targetPath));
4319             instIndvfl("libutil.c32", QString("%1libutil.c32").arg(targetPath));
4320             instIndvfl("libcom32.c32", QString("%1libcom32.c32").arg(targetPath));
4321         }
4322 	setuppersspace();
4323 #ifdef Q_OS_FREEBSD
4324 		/*
4325 		 * On FreeBSD, we only support installing on MSDOSFS (no
4326 		 * extlinux in the ports).  This also simplifies things
4327 		 * a bit, and that's what most users usually want anyway.
4328 		 *
4329 		 * Because of syslinux' stupidity, we have to remove any
4330 		 * existing ldlinux.c32 and ldlinux.sys files, otherwise
4331 		 * it will fail to install loader (even with -f switch).
4332 		 * Then we have to unmount the filesystem to avoid the
4333 		 * "Operation not permitted" error, and must enforce it
4334 		 * because syslinux expects a block device, and, well,
4335 		 * there are no "block devices" in FreeBSD.
4336 		 */
4337 		rmFile(targetPath + "ldlinux.c32");
4338 		rmFile(targetPath + "ldlinux.sys");
4339 		callexternapp("umount", targetDev);
4340 		callexternapp(syslinuxcommand, "-i -f " + targetDev);
4341 
4342 		if (rawtargetDev != targetDev)
4343 		{
4344 			/*
4345 			 * We have partition table (not operating on raw
4346 			 * disk), so we need to install MBR and mark our
4347 			 * partition as active.  Assume our targetDev is
4348 			 * /dev/{da,mmcsd}XsY and use the last digit as
4349 			 * partition index for gpart(8).
4350 			 */
4351 			QString idx = targetDev.right(1);
4352 			callexternapp("gpart",
4353 				"bootcode -b /boot/mbr " + rawtargetDev);
4354 			callexternapp("gpart", "set -a "
4355 				"active -i " + idx + " " + rawtargetDev);
4356 		}
4357 #endif
4358 	fininstall();
4359 }
4360 
setuppersspace()4361 void unetbootin::setuppersspace()
4362 {
4363 	if (this->persistenceSpaceMB > 0)
4364 	{
4365 		pdesc1->setText(tr("Setting up persistence"));
4366 		this->tprogress->setMaximum(persistenceSpaceMB);
4367 		this->tprogress->setValue(0);
4368 		QString persfile = "casper-rw";
4369 		if (issalt && !saltRootDir.isEmpty()) {
4370 			QStringList persistencedir;
4371 			persistencedir.append("persistence");
4372 			makepathtree(QString("%1%2").arg(targetPath).arg(saltRootDir), persistencedir);
4373 			persfile = QString("%1/persistence/%1.save").arg(saltRootDir);
4374 		}
4375 #ifdef Q_OS_WIN32
4376 		QString mke2fscommand = instTempfl("mke2fs.exe", "exe");
4377 #endif
4378 		if (QFile::exists(QString("%1%2").arg(targetPath).arg(persfile)))
4379 		{
4380 			rmFile(QString("%1%2").arg(targetPath).arg(persfile));
4381 		}
4382 		QFile persistenceFile(QString("%1%2").arg(targetPath).arg(persfile));
4383 		persistenceFile.open(QFile::WriteOnly);
4384 		int bytesWritten = 1048576;
4385 		char writeEmpty[1048576];
4386 		memset(writeEmpty, 0, 1048576);
4387 		for (int i = 0; i < persistenceSpaceMB && bytesWritten == 1048576; ++i)
4388 		{
4389 			this->tprogress->setValue(i);
4390 			bytesWritten = persistenceFile.write(writeEmpty, 1048576);
4391 		}
4392 		this->tprogress->setValue(this->tprogress->maximum());
4393 #ifdef Q_OS_UNIX
4394 		callexternapp(mke2fscommand, QString("-F \"%1%2\"").arg(targetPath).arg(persfile));
4395 #endif
4396 #ifdef Q_OS_WIN32
4397 		callexternappWriteToStdin(mke2fscommand, QString("\"%1%2\"").arg(targetPath).arg(persfile), "\n");
4398 		rmFile(mke2fscommand);
4399 #endif
4400 	}
4401 }
4402 
killApplication()4403 void unetbootin::killApplication()
4404 {
4405 	exit(0);
4406 }
4407 
fininstall()4408 void unetbootin::fininstall()
4409 {
4410 	#ifdef Q_OS_UNIX
4411 	this->tprogress->setValue(this->tprogress->maximum()*2/3);
4412 	pdesc1->setText(tr("Syncing filesystems"));
4413 	callexternapp("sync", "");
4414 	#endif
4415 	pdesc1->setText("");
4416 	progresslayer->setEnabled(false);
4417 	progresslayer->hide();
4418 	rebootlayer->setEnabled(true);
4419 	rebootlayer->show();
4420 	sdesc3->setText(QString(sdesc3->text()).remove("<b>").replace(trcurrent+"</b>", trdone));
4421 	sdesc4->setText(QString("<b>%1 %2</b>").arg(sdesc4->text()).arg(trcurrent));
4422 	if (installType == tr("Hard Disk"))
4423 	{
4424 		rebootmsgtext->setText(tr("After rebooting, select the " UNETBOOTINB" menu entry to boot.%1").arg(postinstmsg));
4425 	}
4426 	if (installType == tr("USB Drive"))
4427 	{
4428 #ifndef Q_OS_MAC
4429 		rebootmsgtext->setText(tr("After rebooting, select the USB boot option in the BIOS boot menu.%1").arg(postinstmsg));
4430 #endif
4431 #ifdef Q_OS_MAC
4432 		rebootmsgtext->setText(tr("After rebooting, hold the option key and select your USB drive to boot from it.%1").arg(postinstmsg));
4433 #endif
4434 	}
4435     finishLogging();
4436 	if (exitOnCompletion)
4437 	{
4438 		QTextStream out(stdout);
4439 		out << "exitstatus:success" << endl << flush;
4440 		QApplication::exit();
4441 		exit(0);
4442 	}
4443 }
4444