Skip to content

Commit

Permalink
seems to be in a working state on linux
Browse files Browse the repository at this point in the history
  • Loading branch information
jlre249 committed Nov 13, 2024
1 parent 3eb98b3 commit f12b482
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 9 deletions.
42 changes: 42 additions & 0 deletions src/downloadextractthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,48 @@ void DownloadExtractThread::extractMultiFileRun()
}
}

if(_imgWriterSettings.contains("UNRAID_LANG_JSON")) {
// remove this tmp file now that we're definitely done with it
QFile langJson(_imgWriterSettings["UNRAID_LANG_JSON"].toByteArray());
langJson.remove();
}

if(_imgWriterSettings.contains("UNRAID_LANG_CODE"))
{
QString unraidLangCode(_imgWriterSettings["UNRAID_LANG_CODE"].toString());
if(_imgWriterSettings.contains("UNRAID_LANG_XML")) {
QFile langXml(_imgWriterSettings["UNRAID_LANG_XML"].toByteArray());
QFile::rename(langXml.fileName(), folder + "/config/plugins/lang-" + unraidLangCode + ".xml");
}

if(_imgWriterSettings.contains("UNRAID_LANG_ZIP")) {
QFile langZip(_imgWriterSettings["UNRAID_LANG_ZIP"].toByteArray());
QFile::rename(langZip.fileName(), folder + "/config/plugins/dynamix/lang-" + unraidLangCode + ".zip");
}
QFile dynamixCfg(folder + "/config/plugins/dynamix/dynamix.cfg");
if (dynamixCfg.exists())
{
dynamixCfg.open(QIODevice::ReadOnly);
QString dataText = dynamixCfg.readAll();
dynamixCfg.close();

QString oldData(dataText);
dataText.replace("locale=\"\"", "locale=\"" + unraidLangCode + "\"", Qt::CaseInsensitive);
if(oldData == dataText)
{
// if this string wasn't found for replacement, just add it
dataText += "locale=\"" + unraidLangCode + "\"";
}

if (dynamixCfg.open(QFile::WriteOnly | QFile::Truncate))
{
QTextStream out(&dynamixCfg);
out << dataText;
}
dynamixCfg.close();
}
}

// restore make bootable scripts and/or syslinux, if necessary
QDir dirTarget(folder);
if (dirTarget.mkdir("syslinux"))
Expand Down
169 changes: 162 additions & 7 deletions src/imagewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <QVersionNumber>
#include <QtNetwork>
#include <QDesktopServices>
#include <QTemporaryFile>
#ifndef QT_NO_WIDGETS
#include <QFileDialog>
#include <QApplication>
Expand Down Expand Up @@ -188,6 +189,7 @@ ImageWriter::ImageWriter(QObject *parent)
{
_currentLang = langname;
_currentLangcode = currentlangcode;
_unraidLangcode = _generateUnraidLangcode(currentlangcode, langname);
}
}
//_currentKeyboard = "us";
Expand Down Expand Up @@ -354,15 +356,24 @@ void ImageWriter::startWrite()
if (_multipleFilesInZip)
{
static_cast<DownloadExtractThread *>(_thread)->enableMultipleFileExtraction();
QString label{""};
if(_initFormat == "UNRAID") {
// if this is an unraid zip, the volume label needs to be UNRAID for the make bootable script to work as intended
label = "UNRAID";
// in order to properly propagate language selection to the unraid usb files themselves,
// we need to kick of a chain of events that starts with formatting the drive,
// which then kicks off a download of the available languages json,
// which then kicks off a download of the select language xml,
// which, if there is a zip file specified in that xml, then kicks off a download of that zip file,
// which then kicks of the download/extract of the actual unraid files
QString label{"UNRAID"}; // since this is an unraid zip, the volume label needs to be UNRAID for the make bootable script to work as intended
DriveFormatThread *dft = new DriveFormatThread(_dst.toLatin1(), label, this);
connect(dft, SIGNAL(error(QString)), SLOT(onError(QString)));
connect(dft, SIGNAL(success()), SLOT(onUnraidFormatComplete()));
dft->start();
} else {
DriveFormatThread *dft = new DriveFormatThread(_dst.toLatin1(), "", this);
connect(dft, SIGNAL(success()), _thread, SLOT(start()));
connect(dft, SIGNAL(error(QString)), SLOT(onError(QString)));
dft->start();
}
DriveFormatThread *dft = new DriveFormatThread(_dst.toLatin1(), label, this);
connect(dft, SIGNAL(success()), _thread, SLOT(start()));
connect(dft, SIGNAL(error(QString)), SLOT(onError(QString)));
dft->start();
}
else
{
Expand Down Expand Up @@ -1355,6 +1366,7 @@ void ImageWriter::changeLanguage(const QString &newLanguageName)
replaceTranslator(trans);
_currentLang = newLanguageName;
_currentLangcode = langcode;
_unraidLangcode = _generateUnraidLangcode(_currentLangcode, _currentLang);
}
else
{
Expand Down Expand Up @@ -1520,3 +1532,146 @@ bool ImageWriter::windowsBuild() {
return false;
#endif
}

QString ImageWriter::_generateUnraidLangcode(const QString& langcode, const QString& languageName)
{
QString unraidLangcode = langcode + "_";

if (langcode == "en") {
unraidLangcode.append("US");
}
else if (langcode == "pt") {
if (languageName.contains("Brasil")) {
unraidLangcode.append("BR");
}
else {
unraidLangcode.append("PT");
}
}
else if (langcode == "sv") {
unraidLangcode.append("SE");
}
else if (langcode == "uk") {
unraidLangcode.append("UA");
}
else if (langcode == "zh") {
unraidLangcode.append("CN");
}
else {
unraidLangcode.append(langcode.toUpper());
}
return unraidLangcode;
}

QByteArray ImageWriter::_parseUnraidLangJson(const QByteArray& jsonFilePath, const QString& unraidLangCode)
{
QByteArray jsonData = _readFileContents(jsonFilePath);
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);

qDebug() << parseError.errorString();
if (parseError.error != QJsonParseError::NoError) {
onError(parseError.errorString());
}

QJsonObject jsonObj = jsonDoc.object();

QJsonValue langVal = jsonObj.value(unraidLangCode);
QJsonObject langObj = langVal.toObject();

QJsonValue url = langObj.value("URL");
return url.toString().toUtf8();
}

QString ImageWriter::_parseUnraidLangXml(const QByteArray& xmlFilePath)
{
QByteArray xmlData = _readFileContents(xmlFilePath);
QXmlStreamReader xml(xmlData);
int count = 0;
QString found;

while (!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
if (xml.name() == "LanguageURL") {
xml.readNext();
if (xml.atEnd()) {
break;
}

if (xml.isCharacters() && (xml.text() != "\n")) {
found.append(xml.text().toString());
}
}
}
}

return found;
}

QByteArray ImageWriter::_readFileContents(const QByteArray& filePath)
{
QFile fileIn(filePath);
if(!fileIn.open(QIODevice::ReadOnly)) {
onError("Error opening " + filePath);
}
// remove excess null characters (they cause the qt json parser to fail)
QByteArray data = fileIn.readAll().replace('\0', "");
fileIn.close();
if(!fileIn.open(QIODevice::WriteOnly)) {
onError("Error opening " + filePath);
}
fileIn.write(data);
return data;
}

void ImageWriter::onUnraidFormatComplete()
{
QTemporaryFile tmp;
tmp.open(); // need this to actually generate a unique file path
_unraidLangJsonTmpPath = tmp.fileName().toUtf8();
setSetting("imagecustomization/UNRAID_LANG_JSON", _unraidLangJsonTmpPath);
DownloadThread * dl_thread = new DownloadThread(_unraidLangJsonUrl, _unraidLangJsonTmpPath, "", this);
connect(dl_thread, SIGNAL(error(QString)), SLOT(onError(QString)));
connect(dl_thread, SIGNAL(success()), SLOT(onUnraidJsonDownloadComplete()));
dl_thread->start();
}

void ImageWriter::onUnraidJsonDownloadComplete()
{
QByteArray xmlUrl = _parseUnraidLangJson(_unraidLangJsonTmpPath, _unraidLangcode);
QTemporaryFile tmp;
tmp.open(); // need this to actually generate a unique file path
_unraidLangXmlTmpPath = tmp.fileName().toUtf8();
setSetting("imagecustomization/UNRAID_LANG_XML", _unraidLangXmlTmpPath);
DownloadThread * dl_thread = new DownloadThread(xmlUrl, _unraidLangXmlTmpPath, "", this);
connect(dl_thread, SIGNAL(error(QString)), SLOT(onError(QString)));
connect(dl_thread, SIGNAL(success()), SLOT(onUnraidXmlDownloadComplete()));
dl_thread->start();
}

void ImageWriter::onUnraidXmlDownloadComplete()
{
QString zipUrl = _parseUnraidLangXml(_unraidLangXmlTmpPath);
setSetting("imagecustomization/UNRAID_LANG_CODE", _unraidLangcode);
if(zipUrl.isEmpty())
{
// this has to be called again so getSavedCustomizationSettings returns the updated qvariantmap
_thread->setImageCustomization(_config, _cmdline, _firstrun, _cloudinit, _cloudinitNetwork, _initFormat, getSavedCustomizationSettings());
_thread->start();
}
else
{
QTemporaryFile tmp;
tmp.open(); // need this to actually generate a unique file path
_unraidLangZipTmpPath = tmp.fileName().toUtf8();
setSetting("imagecustomization/UNRAID_LANG_ZIP", _unraidLangZipTmpPath);
// this has to be called again so getSavedCustomizationSettings returns the updated qvariantmap
_thread->setImageCustomization(_config, _cmdline, _firstrun, _cloudinit, _cloudinitNetwork, _initFormat, getSavedCustomizationSettings());
DownloadThread * dl_thread = new DownloadThread(zipUrl.toUtf8(), _unraidLangZipTmpPath, "", this);
connect(dl_thread, SIGNAL(error(QString)), SLOT(onError(QString)));
connect(dl_thread, SIGNAL(success()), _thread, SLOT(start()));
dl_thread->start();
}
}

14 changes: 13 additions & 1 deletion src/imagewriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <QUrl>
#include <QSettings>
#include <QVariant>
#include <QTemporaryFile>
#include "config.h"
#include "powersaveblocker.h"
#include "drivelistmodel.h"
Expand Down Expand Up @@ -183,6 +184,9 @@ protected slots:
void onPreparationStatusUpdate(QString msg);
void handleNetworkRequestFinished(QNetworkReply *data);
void onSTPdetected();
void onUnraidFormatComplete();
void onUnraidJsonDownloadComplete();
void onUnraidXmlDownloadComplete();

private:
// Recursively walk all the entries with subitems and, for any which
Expand All @@ -195,7 +199,7 @@ protected slots:

protected:
QUrl _src, _repo;
QString _dst, _cacheFileName, _parentCategory, _osName, _currentLang, _currentLangcode, _currentKeyboard;
QString _dst, _cacheFileName, _parentCategory, _osName, _currentLang, _currentLangcode, _currentKeyboard, _unraidLangcode;
QByteArray _expectedHash, _cachedFileHash, _cmdline, _config, _firstrun, _cloudinit, _cloudinitNetwork, _initFormat;
quint64 _downloadLen, _extrLen, _devLen, _dlnow, _verifynow;
DriveListModel _drivelist;
Expand All @@ -212,13 +216,21 @@ protected slots:
QWinTaskbarButton *_taskbarButton;
#endif
bool _guidValid;
const QByteArray _unraidLangJsonUrl{"https://assets.ca.unraid.net/feed/languageSelection.json"};
QByteArray _unraidLangJsonTmpPath;
QByteArray _unraidLangXmlTmpPath;
QByteArray _unraidLangZipTmpPath;

void _parseCompressedFile();
void _parseXZFile();
QString _pubKeyFileName();
QString _privKeyFileName();
QString _sshKeyDir();
QString _sshKeyGen();
QString _generateUnraidLangcode(const QString& langcode, const QString& languageName);
QByteArray _readFileContents(const QByteArray& filePath);
QString _parseUnraidLangXml(const QByteArray& xmlFilePath);
QByteArray _parseUnraidLangJson(const QByteArray& jsonFilePath, const QString& unraidLangCode);
};

#endif // IMAGEWRITER_H
2 changes: 1 addition & 1 deletion src/qmlcomponents/regex_validator_qt6.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import QtQuick
import QtQuick 2.9

RegularExpressionValidator {
regularExpression: /^[A-Za-z0-9]([A-Za-z0-9\-\.]{0,13}[A-Za-z0-9])?$/
Expand Down

0 comments on commit f12b482

Please sign in to comment.