From c51512f94036b7d13b98cb02b8e8c1e549e7b448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Wed, 27 Sep 2017 15:39:13 +0200 Subject: NOISSUE use classparser for importing Legacy instances with undecided Minecraft versions --- CMakeLists.txt | 1 + api/logic/CMakeLists.txt | 2 +- api/logic/minecraft/legacy/LegacyInstance.cpp | 4 +- api/logic/minecraft/legacy/LegacyUpgradeTask.cpp | 16 +++-- libraries/classparser/CMakeLists.txt | 11 +-- libraries/classparser/include/classparser.h | 27 ++++++++ libraries/classparser/include/javautils.h | 29 -------- libraries/classparser/src/classparser.cpp | 85 ++++++++++++++++++++++++ libraries/classparser/src/javautils.cpp | 83 ----------------------- 9 files changed, 134 insertions(+), 124 deletions(-) create mode 100644 libraries/classparser/include/classparser.h delete mode 100644 libraries/classparser/include/javautils.h create mode 100644 libraries/classparser/src/classparser.cpp delete mode 100644 libraries/classparser/src/javautils.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f0f4de23..761ce347 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,7 @@ add_subdirectory(libraries/pack200) # java pack200 compression add_subdirectory(libraries/rainbow) # Qt extension for colors add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions +add_subdirectory(libraries/classparser) # google analytics library ############################### Built Artifacts ############################### diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index a99d22ab..38b15286 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -448,7 +448,7 @@ set_target_properties(MultiMC_logic PROPERTIES CXX_VISIBILITY_PRESET hidden VISI generate_export_header(MultiMC_logic) # Link -target_link_libraries(MultiMC_logic xz-embedded MultiMC_unpack200 systeminfo MultiMC_quazip ${NBT_NAME} ${ZLIB_LIBRARIES}) +target_link_libraries(MultiMC_logic xz-embedded MultiMC_unpack200 systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES}) qt5_use_modules(MultiMC_logic Core Xml Network Concurrent) # Mark and export headers diff --git a/api/logic/minecraft/legacy/LegacyInstance.cpp b/api/logic/minecraft/legacy/LegacyInstance.cpp index 21acf675..0b69acf2 100644 --- a/api/logic/minecraft/legacy/LegacyInstance.cpp +++ b/api/logic/minecraft/legacy/LegacyInstance.cpp @@ -31,8 +31,8 @@ LegacyInstance::LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectP { settings->registerSetting("NeedsRebuild", true); settings->registerSetting("ShouldUpdate", false); - settings->registerSetting("JarVersion", "Unknown"); - settings->registerSetting("IntendedJarVersion", ""); + settings->registerSetting("JarVersion", QString()); + settings->registerSetting("IntendedJarVersion", QString()); /* * custom base jar has no default. it is determined in code... see the accessor methods for *it diff --git a/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp b/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp index cb0572ed..e41d87cb 100644 --- a/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp +++ b/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp @@ -8,6 +8,7 @@ #include "LegacyInstance.h" #include "minecraft/MinecraftInstance.h" #include "minecraft/MinecraftProfile.h" +#include "classparser.h" LegacyUpgradeTask::LegacyUpgradeTask(SettingsObjectPtr settings, const QString & stagingPath, InstancePtr origInstance, const QString & newName) { @@ -50,7 +51,6 @@ static QString decideVersion(const QString& currentVersion, const QString& inten return intendedVersion; } } - // TODO: possibly add fallback to the old jar/classfile analysis method from MultiMC4 return QString(); } @@ -74,9 +74,17 @@ void LegacyUpgradeTask::copyFinished() QString preferredVersionNumber = decideVersion(legacyInst->currentVersionId(), legacyInst->intendedVersionId()); if(preferredVersionNumber.isNull()) { - // FIXME: let the user decide - emitFailed(tr("Could not decide Minecraft version.")); - return; + // try to decide version based on the jar(s?) + preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->baseJar()); + if(preferredVersionNumber.isNull()) + { + preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->runnableJar()); + if(preferredVersionNumber.isNull()) + { + emitFailed(tr("Could not decide Minecraft version.")); + return; + } + } } inst->setComponentVersion("net.minecraft", preferredVersionNumber); diff --git a/libraries/classparser/CMakeLists.txt b/libraries/classparser/CMakeLists.txt index a6c3fa14..db266f53 100644 --- a/libraries/classparser/CMakeLists.txt +++ b/libraries/classparser/CMakeLists.txt @@ -18,7 +18,7 @@ include_directories(${Qt5Base_INCLUDE_DIRS}) set(CLASSPARSER_HEADERS # Public headers include/classparser_config.h -include/javautils.h +include/classparser.h # Private headers src/annotations.h @@ -30,12 +30,13 @@ src/membuffer.h ) set(CLASSPARSER_SOURCES -src/javautils.cpp +src/classparser.cpp src/annotations.cpp ) add_definitions(-DCLASSPARSER_LIBRARY) -add_library(classparser SHARED ${CLASSPARSER_SOURCES} ${CLASSPARSER_HEADERS}) -target_include_directories(classparser PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") -qt5_use_modules(classparser Core) +add_library(MultiMC_classparser STATIC ${CLASSPARSER_SOURCES} ${CLASSPARSER_HEADERS}) +target_include_directories(MultiMC_classparser PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(MultiMC_classparser MultiMC_quazip) +qt5_use_modules(MultiMC_classparser Core) diff --git a/libraries/classparser/include/classparser.h b/libraries/classparser/include/classparser.h new file mode 100644 index 00000000..7ce3f24a --- /dev/null +++ b/libraries/classparser/include/classparser.h @@ -0,0 +1,27 @@ +/* Copyright 2013-2017 MultiMC Contributors + * + * Authors: Orochimarufan + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once +#include +#include "classparser_config.h" + +namespace classparser +{ +/** + * @brief Get the version from a minecraft.jar by parsing its class files. Expensive! + */ +QString GetMinecraftJarVersion(QString jar); +} diff --git a/libraries/classparser/include/javautils.h b/libraries/classparser/include/javautils.h deleted file mode 100644 index aad7b504..00000000 --- a/libraries/classparser/include/javautils.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright 2013-2017 MultiMC Contributors - * - * Authors: Orochimarufan - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once -#include -#include "classparser_config.h" - -#define MCVer_Unknown "Unknown" - -namespace javautils -{ -/** - * @brief Get the version from a minecraft.jar by parsing its class files. Expensive! - */ -QString GetMinecraftJarVersion(QString jar); -} diff --git a/libraries/classparser/src/classparser.cpp b/libraries/classparser/src/classparser.cpp new file mode 100644 index 00000000..ebbdc887 --- /dev/null +++ b/libraries/classparser/src/classparser.cpp @@ -0,0 +1,85 @@ +/* Copyright 2013-2017 MultiMC Contributors + * + * Authors: Orochimarufan + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "classfile.h" +#include "classparser.h" + +#include +#include +#include + +namespace classparser +{ + +QString GetMinecraftJarVersion(QString jarName) +{ + QString version; + + // check if minecraft.jar exists + QFile jar(jarName); + if (!jar.exists()) + return version; + + // open minecraft.jar + QuaZip zip(&jar); + if (!zip.open(QuaZip::mdUnzip)) + return version; + + // open Minecraft.class + zip.setCurrentFile("net/minecraft/client/Minecraft.class", QuaZip::csSensitive); + QuaZipFile Minecraft(&zip); + if (!Minecraft.open(QuaZipFile::ReadOnly)) + return version; + + // read Minecraft.class + qint64 size = Minecraft.size(); + char *classfile = new char[size]; + Minecraft.read(classfile, size); + + // parse Minecraft.class + try + { + char *temp = classfile; + java::classfile MinecraftClass(temp, size); + java::constant_pool constants = MinecraftClass.constants; + for (java::constant_pool::container_type::const_iterator iter = constants.begin(); + iter != constants.end(); iter++) + { + const java::constant &constant = *iter; + if (constant.type != java::constant::j_string_data) + continue; + const std::string &str = constant.str_data; + qDebug() << QString::fromStdString(str); + if (str.compare(0, 20, "Minecraft Minecraft ") == 0) + { + version = str.substr(20).data(); + break; + } + } + } + catch (java::classfile_exception &) + { + } + + // clean up + delete[] classfile; + Minecraft.close(); + zip.close(); + jar.close(); + + return version; +} +} diff --git a/libraries/classparser/src/javautils.cpp b/libraries/classparser/src/javautils.cpp deleted file mode 100644 index 719032af..00000000 --- a/libraries/classparser/src/javautils.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright 2013-2017 MultiMC Contributors - * - * Authors: Orochimarufan - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "classfile.h" -#include "javautils.h" - -#include -#include - -namespace javautils -{ - -QString GetMinecraftJarVersion(QString jarName) -{ - QString version = MCVer_Unknown; - - // check if minecraft.jar exists - QFile jar(jarName); - if (!jar.exists()) - return version; - - // open minecraft.jar - QuaZip zip(&jar); - if (!zip.open(QuaZip::mdUnzip)) - return version; - - // open Minecraft.class - zip.setCurrentFile("net/minecraft/client/Minecraft.class", QuaZip::csSensitive); - QuaZipFile Minecraft(&zip); - if (!Minecraft.open(QuaZipFile::ReadOnly)) - return version; - - // read Minecraft.class - qint64 size = Minecraft.size(); - char *classfile = new char[size]; - Minecraft.read(classfile, size); - - // parse Minecraft.class - try - { - char *temp = classfile; - java::classfile MinecraftClass(temp, size); - java::constant_pool constants = MinecraftClass.constants; - for (java::constant_pool::container_type::const_iterator iter = constants.begin(); - iter != constants.end(); iter++) - { - const java::constant &constant = *iter; - if (constant.type != java::constant::j_string_data) - continue; - const std::string &str = constant.str_data; - if (str.compare(0, 20, "Minecraft Minecraft ") == 0) - { - version = str.substr(20).data(); - break; - } - } - } - catch (java::classfile_exception &) - { - } - - // clean up - delete[] classfile; - Minecraft.close(); - zip.close(); - jar.close(); - - return version; -} -} -- cgit v1.2.3