From ce867d91698a9414ff7238e902215e9b76d10459 Mon Sep 17 00:00:00 2001 From: Orochimarufan Date: Sun, 24 Feb 2013 17:06:00 +0100 Subject: [PATCH] Port minecraft.jar version detection to Qt --- java/constants.h | 12 +++-- java/javautils.cpp | 130 +++++++++++++++++++++++++-------------------- java/javautils.h | 25 +++++++-- 3 files changed, 101 insertions(+), 66 deletions(-) diff --git a/java/constants.h b/java/constants.h index 2f968d2e..80697ebe 100644 --- a/java/constants.h +++ b/java/constants.h @@ -7,7 +7,7 @@ namespace java class constant { public: - enum type_t:uint8_t + enum type_t : uint8_t { j_hole = 0, // HACK: this is a hole in the array, because java is crazy j_string_data = 1, @@ -22,6 +22,7 @@ namespace java j_interface_methodref = 11, j_nameandtype = 12 } type; + constant(util::membuffer & buf ) { buf.read(type); @@ -66,10 +67,12 @@ namespace java break; } } + constant(int fake) { type = j_hole; } + std::string toString() { std::ostringstream ss; @@ -142,7 +145,8 @@ namespace java uint16_t descriptor_index; } name_and_type; }; - }; + }; + /** * A helper class that represents the custom container used in Java class file for storage of constants */ @@ -181,7 +185,7 @@ namespace java index++; } } - }; + } typedef std::vector container_type; /** * Access constants based on jar file index numbers (index of the first element is 1) @@ -204,5 +208,5 @@ namespace java } private: container_type constants; - }; + }; } diff --git a/java/javautils.cpp b/java/javautils.cpp index a07d1541..bf4b5cdf 100644 --- a/java/javautils.cpp +++ b/java/javautils.cpp @@ -1,69 +1,81 @@ +/* Copyright 2013 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 "multimc_pragma.h" #include "classfile.h" #include "javautils.h" -//#include -#include -//#include -//#include "mcversionlist.h" + +#include +#include namespace javautils { -QString GetMinecraftJarVersion(QString jar) + +QString GetMinecraftJarVersion(QString jarName) { - return "Unknown"; - /* - wxString fullpath = jar.GetFullPath(); - wxString version = MCVer_Unknown; - if(!jar.FileExists()) - return version; - std::auto_ptr entry; - // convert the local name we are looking for into the internal format - wxString name = wxZipEntry::GetInternalName("net/minecraft/client/Minecraft.class",wxPATH_UNIX); + QString version = MCVer_Unknown; - // open the zip - wxFFileInputStream inStream(jar.GetFullPath()); - wxZipInputStream zipIn(inStream); + // 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; +} - // call GetNextEntry() until the required internal name is found - do - { - entry.reset(zipIn.GetNextEntry()); - } - while (entry.get() != NULL && entry->GetInternalName() != name); - auto myentry = entry.get(); - if (myentry == NULL) - return version; - - // we got the entry, read the data - std::size_t size = myentry->GetSize(); - char *classdata = new char[size]; - zipIn.Read(classdata,size); - try - { - char * temp = classdata; - java::classfile Minecraft_jar(temp,size); - auto cnst = Minecraft_jar.constants; - auto iter = cnst.begin(); - while (iter != cnst.end()) - { - const java::constant & constant = *iter; - if(constant.type != java::constant::j_string_data) - { - iter++; - continue; - } - auto & str = constant.str_data; - const char * lookfor = "Minecraft Minecraft "; // length = 20 - if(str.compare(0,20,lookfor) == 0) - { - version = str.substr(20).data(); - break; - } - iter++; - } - } catch(java::classfile_exception &){} - delete[] classdata; - return version; - */ } -} \ No newline at end of file diff --git a/java/javautils.h b/java/javautils.h index c8b5a793..7f9b6d89 100644 --- a/java/javautils.h +++ b/java/javautils.h @@ -1,9 +1,28 @@ +/* Copyright 2013 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 + +#define MCVer_Unknown "Unknown" + namespace javautils { - /* - * Get the version from a minecraft.jar by parsing its class files. Expensive! + /** + * @brief Get the version from a minecraft.jar by parsing its class files. Expensive! */ QString GetMinecraftJarVersion(QString jar); -} \ No newline at end of file +}