summaryrefslogtreecommitdiffstats
path: root/heimdall-frontend/Source
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--heimdall-frontend/Source/Alerts.cpp2
-rw-r--r--heimdall-frontend/Source/FirmwareInfo.cpp17
-rw-r--r--heimdall-frontend/Source/FirmwareInfo.h2
-rw-r--r--heimdall-frontend/Source/Packaging.cpp321
-rw-r--r--heimdall-frontend/Source/Packaging.h5
5 files changed, 318 insertions, 29 deletions
diff --git a/heimdall-frontend/Source/Alerts.cpp b/heimdall-frontend/Source/Alerts.cpp
index e8e8752..5dc0337 100644
--- a/heimdall-frontend/Source/Alerts.cpp
+++ b/heimdall-frontend/Source/Alerts.cpp
@@ -29,6 +29,7 @@ using namespace HeimdallFrontend;
void Alerts::DisplayError(const QString& errorMessage)
{
QMessageBox messageBox;
+ messageBox.setModal(true);
messageBox.setText(errorMessage);
messageBox.setIcon(QMessageBox::Critical);
messageBox.exec();
@@ -37,6 +38,7 @@ void Alerts::DisplayError(const QString& errorMessage)
void Alerts::DisplayWarning(const QString& warningMessage)
{
QMessageBox messageBox;
+ messageBox.setModal(true);
messageBox.setText(warningMessage);
messageBox.setIcon(QMessageBox::Warning);
messageBox.exec();
diff --git a/heimdall-frontend/Source/FirmwareInfo.cpp b/heimdall-frontend/Source/FirmwareInfo.cpp
index aee9313..7870621 100644
--- a/heimdall-frontend/Source/FirmwareInfo.cpp
+++ b/heimdall-frontend/Source/FirmwareInfo.cpp
@@ -18,9 +18,13 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
+// Qt
+#include "QRegExp"
+
// Heimdall Frontend
#include "Alerts.h"
#include "FirmwareInfo.h"
+#include "Packaging.h"
using namespace HeimdallFrontend;
@@ -320,7 +324,7 @@ bool FileInfo::ParseXml(QXmlStreamReader& xml)
return (false);
}
-void FileInfo::WriteXml(QXmlStreamWriter& xml) const
+void FileInfo::WriteXml(QXmlStreamWriter& xml, const QString& filename) const
{
xml.writeStartElement("file");
@@ -329,14 +333,7 @@ void FileInfo::WriteXml(QXmlStreamWriter& xml) const
xml.writeEndElement();
xml.writeStartElement("filename");
-
- int lastSlash = filename.lastIndexOf('/');
-
- if (lastSlash < 0)
- lastSlash = filename.lastIndexOf('\\');
-
- xml.writeCharacters(filename.mid(lastSlash + 1));
-
+ xml.writeCharacters(filename);
xml.writeEndElement();
xml.writeEndElement();
@@ -775,7 +772,7 @@ void FirmwareInfo::WriteXml(QXmlStreamWriter& xml) const
xml.writeStartElement("files");
for (int i = 0; i < fileInfos.length(); i++)
- fileInfos[i].WriteXml(xml);
+ fileInfos[i].WriteXml(xml, Packaging::ClashlessFilename(fileInfos, i));
xml.writeEndElement();
diff --git a/heimdall-frontend/Source/FirmwareInfo.h b/heimdall-frontend/Source/FirmwareInfo.h
index 64c73cb..5765199 100644
--- a/heimdall-frontend/Source/FirmwareInfo.h
+++ b/heimdall-frontend/Source/FirmwareInfo.h
@@ -126,7 +126,7 @@ namespace HeimdallFrontend
FileInfo(unsigned int partitionId, const QString& filename);
bool ParseXml(QXmlStreamReader& xml);
- void WriteXml(QXmlStreamWriter& xml) const;
+ void WriteXml(QXmlStreamWriter& xml, const QString& filename) const;
unsigned int GetPartitionId(void) const
{
diff --git a/heimdall-frontend/Source/Packaging.cpp b/heimdall-frontend/Source/Packaging.cpp
index fc41ba6..6c3890b 100644
--- a/heimdall-frontend/Source/Packaging.cpp
+++ b/heimdall-frontend/Source/Packaging.cpp
@@ -221,12 +221,12 @@ bool Packaging::ExtractTar(QTemporaryFile& tarFile, PackageData *packageData)
return (true);
}
-bool Packaging::WriteTarEntry(const QString& filename, QTemporaryFile *tarFile, bool firmwareXml)
+bool Packaging::WriteTarEntry(const QString& filePath, QTemporaryFile *tarFile, const QString& entryFilename)
{
TarHeader tarHeader;
memset(tarHeader.buffer, 0, TarHeader::kBlockLength);
- QFile file(filename);
+ QFile file(filePath);
if (!file.open(QFile::ReadOnly))
{
@@ -243,19 +243,12 @@ bool Packaging::WriteTarEntry(const QString& filename, QTemporaryFile *tarFile,
QFileInfo qtFileInfo(file);
QByteArray utfFilename;
- if (firmwareXml)
- {
- utfFilename = QString("firmware.xml").toUtf8();
- }
- else
- {
- utfFilename = qtFileInfo.fileName().toUtf8();
+ utfFilename = entryFilename.toUtf8();
- if (utfFilename.length() > 100)
- {
- Alerts::DisplayError(QString("File name is too long:\n%1").arg(qtFileInfo.fileName()));
- return (false);
- }
+ if (utfFilename.length() > 100)
+ {
+ Alerts::DisplayError(QString("File name is too long:\n%1").arg(qtFileInfo.fileName()));
+ return (false);
}
strcpy(tarHeader.fields.name, utfFilename.constData());
@@ -388,7 +381,15 @@ bool Packaging::CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarF
for (int i = 0; i < fileInfos.length(); i++)
{
- if (!WriteTarEntry(fileInfos[i].GetFilename(), tarFile))
+ QString filename = ClashlessFilename(fileInfos, i);
+
+ if (filename == "firmware.xml")
+ {
+ Alerts::DisplayError("You cannot name your partition files \"firmware.xml\".\nIt is a reserved name.");
+ return (false);
+ }
+
+ if (!WriteTarEntry(fileInfos[i].GetFilename(), tarFile, ClashlessFilename(fileInfos, i)))
{
tarFile->resize(0);
tarFile->close();
@@ -411,7 +412,20 @@ bool Packaging::CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarF
}
}
- if (!WriteTarEntry(firmwareInfo.GetPitFilename(), tarFile))
+ int lastSlash = firmwareInfo.GetPitFilename().lastIndexOf('/');
+
+ if (lastSlash < 0)
+ lastSlash = firmwareInfo.GetPitFilename().lastIndexOf('\\');
+
+ QString pitFilename = ClashlessFilename(fileInfos, firmwareInfo.GetPitFilename().mid(lastSlash + 1));
+
+ if (pitFilename == "firmware.xml")
+ {
+ Alerts::DisplayError("You cannot name your PIT file \"firmware.xml\".\nIt is a reserved name.");
+ return (false);
+ }
+
+ if (!WriteTarEntry(firmwareInfo.GetPitFilename(), tarFile, pitFilename))
{
tarFile->resize(0);
tarFile->close();
@@ -431,7 +445,7 @@ bool Packaging::CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarF
return (false);
}
- if (!WriteTarEntry(firmwareXmlFile.fileName(), tarFile, true))
+ if (!WriteTarEntry(firmwareXmlFile.fileName(), tarFile, "firmware.xml"))
{
tarFile->resize(0);
tarFile->close();
@@ -558,7 +572,12 @@ bool Packaging::BuildPackage(const QString& packagePath, const FirmwareInfo& fir
QTemporaryFile tar("XXXXXX.tar");
if (!CreateTar(firmwareInfo, &tar))
+ {
+ fclose(compressedPackageFile);
+ remove(packagePath.toStdString().c_str());
+
return (false);
+ }
if (!tar.open())
{
@@ -626,3 +645,271 @@ bool Packaging::BuildPackage(const QString& packagePath, const FirmwareInfo& fir
return (true);
}
+
+QString Packaging::ClashlessFilename(const QList<FileInfo>& fileInfos, int fileInfoIndex)
+{
+ int lastSlash = fileInfos[fileInfoIndex].GetFilename().lastIndexOf('/');
+
+ if (lastSlash < 0)
+ lastSlash = fileInfos[fileInfoIndex].GetFilename().lastIndexOf('\\');
+
+ QString filename = fileInfos[fileInfoIndex].GetFilename().mid(lastSlash + 1);
+ unsigned int renameIndex = 0;
+
+ // Check for name clashes
+ for (int i = 0; i < fileInfoIndex; i++)
+ {
+ lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
+
+ if (lastSlash < 0)
+ lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
+
+ QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1);
+
+ if (filename == otherFilename)
+ renameIndex++;
+ }
+
+ if (renameIndex > 0)
+ {
+ int lastPeriodIndex = filename.lastIndexOf(QChar('.'));
+ QString shortFilename;
+ QString fileType;
+
+ if (lastPeriodIndex >= 0)
+ {
+ shortFilename = filename.left(lastPeriodIndex);
+ fileType = filename.mid(lastPeriodIndex);
+ }
+ else
+ {
+ shortFilename = filename;
+ }
+
+ unsigned int renameIndexOffset = 0;
+ bool validIndexOffset = true;
+
+ // Before we append a rename index we must ensure it doesn't produce further collisions.
+ for (int i = 0; i < fileInfos.length(); i++)
+ {
+ int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
+
+ if (lastSlash < 0)
+ lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
+
+ QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1);
+
+ if (otherFilename.length() > filename.length() + 1)
+ {
+ QString trimmedOtherFilename = otherFilename.left(shortFilename.length());
+
+ if (shortFilename == trimmedOtherFilename)
+ {
+ lastPeriodIndex = otherFilename.lastIndexOf(QChar('.'));
+ QString shortOtherFilename;
+
+ if (lastPeriodIndex >= 0)
+ shortOtherFilename = otherFilename.left(lastPeriodIndex);
+ else
+ shortOtherFilename = otherFilename;
+
+ QRegExp renameExp("-[0-9]+");
+
+ if (renameExp.lastIndexIn(shortOtherFilename) == shortFilename.length())
+ {
+ unsigned int trailingInteger = shortOtherFilename.mid(shortFilename.length() + 1).toUInt(&validIndexOffset);
+
+ if (!validIndexOffset)
+ break;
+
+ if (trailingInteger > renameIndexOffset)
+ renameIndexOffset = trailingInteger;
+ }
+ }
+ }
+ }
+
+ if (validIndexOffset)
+ {
+ // Ensure renaming won't involve integer overflow!
+ if (renameIndex > static_cast<unsigned int>(-1) - renameIndexOffset)
+ validIndexOffset = false;
+ }
+
+ if (validIndexOffset)
+ {
+ shortFilename.append(QChar('-'));
+ shortFilename.append(QString::number(renameIndexOffset + renameIndex));
+
+ return (shortFilename + fileType);
+ }
+ else
+ {
+ // Fallback behaviour... an absolutely terrible brute force implementation!
+ QString filename;
+ QString renamePrefix;
+
+ for (;;)
+ {
+ renamePrefix.append(QChar('+'));
+
+ for (unsigned int i = 0; i < static_cast<unsigned int>(-1); i++)
+ {
+ filename = shortFilename + renamePrefix + QString::number(i) + fileType;
+
+ bool valid = true;
+
+ for (int i = 0; i < fileInfos.length(); i++)
+ {
+ int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
+
+ if (lastSlash < 0)
+ lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
+
+ if (filename == fileInfos[i].GetFilename().mid(lastSlash + 1))
+ {
+ valid = false;
+ break;
+ }
+ }
+
+ if (valid)
+ return (filename);
+ }
+ }
+ }
+ }
+ else
+ {
+ return (filename);
+ }
+}
+
+QString Packaging::ClashlessFilename(const QList<FileInfo>& fileInfos, const QString& filename)
+{
+ unsigned int renameIndex = 0;
+
+ // Check for name clashes
+ for (int i = 0; i < fileInfos.length(); i++)
+ {
+ int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
+
+ if (lastSlash < 0)
+ lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
+
+ QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1);
+
+ if (filename == otherFilename)
+ renameIndex++;
+ }
+
+ if (renameIndex > 0)
+ {
+ int lastPeriodIndex = filename.lastIndexOf(QChar('.'));
+ QString shortFilename;
+ QString fileType;
+
+ if (lastPeriodIndex >= 0)
+ {
+ shortFilename = filename.left(lastPeriodIndex);
+ fileType = filename.mid(lastPeriodIndex);
+ }
+ else
+ {
+ shortFilename = filename;
+ }
+
+ unsigned int renameIndexOffset = 0;
+ bool validIndexOffset = true;
+
+ // Before we append a rename index we must ensure it doesn't produce further collisions.
+ for (int i = 0; i < fileInfos.length(); i++)
+ {
+ int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
+
+ if (lastSlash < 0)
+ lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
+
+ QString otherFilename = fileInfos[i].GetFilename().mid(lastSlash + 1);
+
+ if (otherFilename.length() > filename.length() + 1)
+ {
+ QString trimmedOtherFilename = otherFilename.left(filename.length());
+
+ if (filename == trimmedOtherFilename)
+ {
+ lastPeriodIndex = otherFilename.lastIndexOf(QChar('.'));
+ QString shortOtherFilename;
+
+ if (lastPeriodIndex >= 0)
+ shortOtherFilename = otherFilename.left(lastPeriodIndex);
+ else
+ shortOtherFilename = otherFilename;
+
+ QRegExp renameExp("-[0-9]+");
+
+ if (renameExp.lastIndexIn(shortOtherFilename) == shortFilename.length())
+ {
+ unsigned int trailingInteger = shortOtherFilename.mid(shortFilename.length() + 1).toUInt(&validIndexOffset);
+
+ if (!validIndexOffset)
+ break;
+
+ if (trailingInteger > renameIndexOffset)
+ renameIndexOffset = trailingInteger;
+ }
+ }
+ }
+ }
+
+ if (validIndexOffset)
+ {
+ // Ensure renaming won't involve integer overflow!
+ if (renameIndex > static_cast<unsigned int>(-1) - renameIndexOffset)
+ validIndexOffset = false;
+ }
+
+ if (validIndexOffset)
+ {
+ shortFilename.append(QChar('-'));
+ shortFilename.append(QString::number(renameIndexOffset + renameIndex));
+
+ return (shortFilename + fileType);
+ }
+ else
+ {
+ // Fallback behaviour, brute-force/semi-random.
+ bool valid;
+ QString filename;
+
+ do
+ {
+ valid = true;
+
+ filename = shortFilename + "-";
+ for (int i = 0; i < 8; i++)
+ filename.append(QChar(qrand() % ('Z' - 'A' + 1) + 'A'));
+
+ for (int i = 0; i < fileInfos.length(); i++)
+ {
+ int lastSlash = fileInfos[i].GetFilename().lastIndexOf('/');
+
+ if (lastSlash < 0)
+ lastSlash = fileInfos[i].GetFilename().lastIndexOf('\\');
+
+ if (filename == fileInfos[i].GetFilename().mid(lastSlash + 1))
+ {
+ valid = false;
+ break;
+ }
+ }
+ } while (!valid);
+
+ return (filename);
+ }
+ }
+ else
+ {
+ return (filename);
+ }
+}
diff --git a/heimdall-frontend/Source/Packaging.h b/heimdall-frontend/Source/Packaging.h
index 402f786..b6bac8d 100644
--- a/heimdall-frontend/Source/Packaging.h
+++ b/heimdall-frontend/Source/Packaging.h
@@ -103,7 +103,7 @@ namespace HeimdallFrontend
// TODO: Add support for sparse files to both methods?
static bool ExtractTar(QTemporaryFile& tarFile, PackageData *packageData);
- static bool WriteTarEntry(const QString& filename, QTemporaryFile *tarFile, bool firmwareXml = false);
+ static bool WriteTarEntry(const QString& filePath, QTemporaryFile *tarFile, const QString& entryFilename);
static bool CreateTar(const FirmwareInfo& firmwareInfo, QTemporaryFile *tarFile); // Uses original TAR format.
public:
@@ -112,6 +112,9 @@ namespace HeimdallFrontend
static bool ExtractPackage(const QString& packagePath, PackageData *packageData);
static bool BuildPackage(const QString& packagePath, const FirmwareInfo& firmwareInfo);
+
+ static QString ClashlessFilename(const QList<FileInfo>& fileInfos, int fileInfoIndex);
+ static QString ClashlessFilename(const QList<FileInfo>& fileInfos, const QString& filename);
};
}