diff --git a/launcher/minecraft/skins/SkinList.cpp b/launcher/minecraft/skins/SkinList.cpp index 56379aaab..be3bc776b 100644 --- a/launcher/minecraft/skins/SkinList.cpp +++ b/launcher/minecraft/skins/SkinList.cpp @@ -268,6 +268,26 @@ void SkinList::installSkins(const QStringList& iconFiles) installSkin(file); } +QString getUniqueFile(const QString& root, const QString& file) +{ + auto result = FS::PathCombine(root, file); + if (!QFileInfo::exists(result)) { + return result; + } + + QString baseName = QFileInfo(file).completeBaseName(); + QString extension = QFileInfo(file).suffix(); + int tries = 0; + while (QFileInfo::exists(result)) { + if (++tries > 256) + return {}; + + QString key = QString("%1%2.%3").arg(baseName).arg(tries).arg(extension); + result = FS::PathCombine(root, key); + } + + return result; +} QString SkinList::installSkin(const QString& file, const QString& name) { if (file.isEmpty()) @@ -282,7 +302,7 @@ QString SkinList::installSkin(const QString& file, const QString& name) if (fileinfo.suffix() != "png" && !SkinModel(fileinfo.absoluteFilePath()).isValid()) return tr("Skin images must be 64x64 or 64x32 pixel PNG files."); - QString target = FS::PathCombine(m_dir.absolutePath(), name.isEmpty() ? fileinfo.fileName() : name); + QString target = getUniqueFile(m_dir.absolutePath(), name.isEmpty() ? fileinfo.fileName() : name); return QFile::copy(file, target) ? "" : tr("Unable to copy file"); } @@ -371,7 +391,8 @@ bool SkinList::setData(const QModelIndex& idx, const QVariant& value, int role) auto& skin = m_skinList[row]; auto newName = value.toString(); if (skin.name() != newName) { - skin.rename(newName); + if (!skin.rename(newName)) + return false; save(); } return true; diff --git a/launcher/minecraft/skins/SkinModel.cpp b/launcher/minecraft/skins/SkinModel.cpp index b609bc6c7..209207215 100644 --- a/launcher/minecraft/skins/SkinModel.cpp +++ b/launcher/minecraft/skins/SkinModel.cpp @@ -122,7 +122,11 @@ QString SkinModel::name() const bool SkinModel::rename(QString newName) { auto info = QFileInfo(m_path); - m_path = FS::PathCombine(info.absolutePath(), newName + ".png"); + auto new_path = FS::PathCombine(info.absolutePath(), newName + ".png"); + if (QFileInfo::exists(new_path)) { + return false; + } + m_path = new_path; return FS::move(info.absoluteFilePath(), m_path); }