aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ccpp.yml20
-rw-r--r--BUILD.md2
-rw-r--r--CMakeLists.txt14
-rw-r--r--COPYING.md29
-rw-r--r--README.md33
-rw-r--r--api/logic/CMakeLists.txt25
-rw-r--r--api/logic/Commandline.h4
-rw-r--r--api/logic/Env.cpp1
-rw-r--r--api/logic/InstanceCopyTask.cpp6
-rw-r--r--api/logic/InstanceCopyTask.h3
-rw-r--r--api/logic/Version.cpp2
-rw-r--r--api/logic/minecraft/ComponentUpdateTask.cpp16
-rw-r--r--api/logic/minecraft/LaunchProfile.cpp22
-rw-r--r--api/logic/minecraft/LaunchProfile.h7
-rw-r--r--api/logic/minecraft/Library.cpp31
-rw-r--r--api/logic/minecraft/MinecraftUpdate.cpp1
-rw-r--r--api/logic/minecraft/OneSixVersionFormat.cpp25
-rw-r--r--api/logic/minecraft/VersionFile.cpp6
-rw-r--r--api/logic/minecraft/VersionFile.h3
-rw-r--r--api/logic/minecraft/forge/ForgeXzDownload.cpp393
-rw-r--r--api/logic/minecraft/forge/ForgeXzDownload.h61
-rw-r--r--api/logic/minecraft/mod/ModFolderModel.h4
-rw-r--r--api/logic/minecraft/update/LibrariesTask.cpp1
-rw-r--r--api/logic/modplatform/flame/UrlResolvingTask.cpp175
-rw-r--r--api/logic/modplatform/flame/UrlResolvingTask.h43
-rw-r--r--api/logic/modplatform/legacy_ftb/PackFetchTask.cpp (renamed from api/logic/modplatform/ftb/FtbPackFetchTask.cpp)46
-rw-r--r--api/logic/modplatform/legacy_ftb/PackFetchTask.h (renamed from api/logic/modplatform/ftb/FtbPackFetchTask.h)20
-rw-r--r--api/logic/modplatform/legacy_ftb/PackHelpers.h (renamed from api/logic/modplatform/ftb/PackHelpers.h)16
-rw-r--r--api/logic/modplatform/legacy_ftb/PackInstallTask.cpp (renamed from api/logic/modplatform/ftb/FtbPackInstallTask.cpp)50
-rw-r--r--api/logic/modplatform/legacy_ftb/PackInstallTask.h (renamed from api/logic/modplatform/ftb/FtbPackInstallTask.h)14
-rw-r--r--api/logic/modplatform/legacy_ftb/PrivatePackManager.cpp (renamed from api/logic/modplatform/ftb/FtbPrivatePackManager.cpp)10
-rw-r--r--api/logic/modplatform/legacy_ftb/PrivatePackManager.h (renamed from api/logic/modplatform/ftb/FtbPrivatePackManager.h)8
-rw-r--r--api/logic/net/URLConstants.h3
-rw-r--r--application/CMakeLists.txt28
-rw-r--r--application/MainWindow.cpp3
-rw-r--r--application/MainWindow.h4
-rw-r--r--application/MultiMC.cpp76
-rw-r--r--application/MultiMC.h2
-rw-r--r--application/dialogs/AboutDialog.cpp81
-rw-r--r--application/dialogs/AboutDialog.ui30
-rw-r--r--application/dialogs/CopyInstanceDialog.cpp19
-rw-r--r--application/dialogs/CopyInstanceDialog.h3
-rw-r--r--application/dialogs/CopyInstanceDialog.ui16
-rw-r--r--application/dialogs/EditAccountDialog.ui2
-rw-r--r--application/dialogs/LoginDialog.ui2
-rw-r--r--application/dialogs/NewInstanceDialog.cpp20
-rw-r--r--application/groupview/AccessibleGroupView.cpp4
-rw-r--r--application/groupview/AccessibleGroupView_p.h4
-rw-r--r--application/groupview/GroupView.cpp6
-rw-r--r--application/main.cpp1
-rwxr-xr-xapplication/package/linux/multimc.desktop2
-rw-r--r--application/package/ubuntu/multimc/DEBIAN/control4
-rw-r--r--application/pages/global/AccountListPage.cpp3
-rw-r--r--application/pages/global/PackagesPage.cpp224
-rw-r--r--application/pages/global/PackagesPage.h57
-rw-r--r--application/pages/global/PackagesPage.ui252
-rw-r--r--application/pages/global/ProxyPage.cpp2
-rw-r--r--application/pages/instance/ModFolderPage.cpp20
-rw-r--r--application/pages/instance/VersionPage.cpp15
-rw-r--r--application/pages/instance/VersionPage.h3
-rw-r--r--application/pages/instance/VersionPage.ui20
-rw-r--r--application/pages/modplatform/TechnicPage.cpp26
-rw-r--r--application/pages/modplatform/TechnicPage.h61
-rw-r--r--application/pages/modplatform/TechnicPage.ui113
-rw-r--r--application/pages/modplatform/TwitchPage.cpp60
-rw-r--r--application/pages/modplatform/TwitchPage.ui62
-rw-r--r--application/pages/modplatform/legacy_ftb/ListModel.cpp (renamed from application/pages/modplatform/FtbListModel.cpp)68
-rw-r--r--application/pages/modplatform/legacy_ftb/ListModel.h (renamed from application/pages/modplatform/FtbListModel.h)30
-rw-r--r--application/pages/modplatform/legacy_ftb/Page.cpp (renamed from application/pages/modplatform/FTBPage.cpp)114
-rw-r--r--application/pages/modplatform/legacy_ftb/Page.h (renamed from application/pages/modplatform/FTBPage.h)59
-rw-r--r--application/pages/modplatform/legacy_ftb/Page.ui (renamed from application/pages/modplatform/FTBPage.ui)4
-rw-r--r--application/pages/modplatform/twitch/TwitchData.h38
-rw-r--r--application/pages/modplatform/twitch/TwitchModel.cpp314
-rw-r--r--application/pages/modplatform/twitch/TwitchModel.h76
-rw-r--r--application/pages/modplatform/twitch/TwitchPage.cpp111
-rw-r--r--application/pages/modplatform/twitch/TwitchPage.h (renamed from application/pages/modplatform/TwitchPage.h)20
-rw-r--r--application/pages/modplatform/twitch/TwitchPage.ui88
-rw-r--r--application/resources/assets/assets.qrc7
-rw-r--r--application/resources/assets/deadglitch.svg66
-rw-r--r--application/resources/assets/underconstruction.pngbin14490 -> 0 bytes
-rw-r--r--application/widgets/DropLabel.cpp41
-rw-r--r--application/widgets/DropLabel.h20
-rw-r--r--application/widgets/ServerStatus.cpp2
-rw-r--r--application/widgets/VersionListView.cpp2
-rw-r--r--changelog.md75
-rw-r--r--libraries/launcher/net/minecraft/Launcher.java2
-rw-r--r--libraries/pack200/CMakeLists.txt50
-rw-r--r--libraries/pack200/LICENSE347
-rw-r--r--libraries/pack200/anti200.cpp43
-rw-r--r--libraries/pack200/include/unpack200.h37
-rw-r--r--libraries/pack200/src/bands.cpp423
-rw-r--r--libraries/pack200/src/bands.h489
-rw-r--r--libraries/pack200/src/bytes.cpp217
-rw-r--r--libraries/pack200/src/bytes.h286
-rw-r--r--libraries/pack200/src/coding.cpp1044
-rw-r--r--libraries/pack200/src/coding.h247
-rw-r--r--libraries/pack200/src/constants.h442
-rw-r--r--libraries/pack200/src/defines.h65
-rw-r--r--libraries/pack200/src/unpack.cpp4790
-rw-r--r--libraries/pack200/src/unpack.h549
-rw-r--r--libraries/pack200/src/unpack200.cpp162
-rw-r--r--libraries/pack200/src/utils.cpp71
-rw-r--r--libraries/pack200/src/utils.h53
-rw-r--r--libraries/pack200/src/zip.cpp589
-rw-r--r--libraries/pack200/src/zip.h112
-rw-r--r--travis/prepare.sh50
106 files changed, 1414 insertions, 12108 deletions
diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml
deleted file mode 100644
index af59213e..00000000
--- a/.github/workflows/ccpp.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: Smoke test
-
-on: [push]
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v1
- - name: configure
- run: |
- mkdir build && cd build && cmake ..
- - name: build
- run: |
- make -j4
- - name: test
- run: |
- ctest -V
diff --git a/BUILD.md b/BUILD.md
index 19a929a7..9f0061a0 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -169,9 +169,9 @@ Pick an installation path - this is where the final `.app` will be constructed w
```
git clone https://github.com/MultiMC/MultiMC5.git
+cd MultiMC5
git submodule init
git submodule update
-cd MultiMC5
mkdir build
cd build
export CMAKE_PREFIX_PATH=/usr/local/opt/qt5
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8f1032c0..fdc61c06 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,15 @@ cmake_minimum_required(VERSION 3.1)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
if(IS_IN_SOURCE_BUILD)
- message(AUTHOR_WARNING "You are building MultiMC in-source. This is NOT recommended!")
+ message(FATAL_ERROR "You are building MultiMC in-source. Please separate the build tree from the source tree.")
+endif()
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ if(CMAKE_HOST_SYSTEM_VERSION MATCHES ".*[Mm]icrosoft.*" OR
+ CMAKE_HOST_SYSTEM_VERSION MATCHES ".*WSL.*"
+ )
+ message(FATAL_ERROR "Building MultiMC is not supported in Linux-on-Windows distributions.")
+ endif()
endif()
if(WIN32)
@@ -13,6 +21,7 @@ endif()
project(MultiMC)
enable_testing()
+
##################################### Set CMake options #####################################
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
@@ -46,7 +55,7 @@ set(MultiMC_NEWS_RSS_URL "https://multimc.org/rss.xml" CACHE STRING "URL to fetc
######## Set version numbers ########
set(MultiMC_VERSION_MAJOR 0)
set(MultiMC_VERSION_MINOR 6)
-set(MultiMC_VERSION_HOTFIX 7)
+set(MultiMC_VERSION_HOTFIX 12)
# Build number
set(MultiMC_VERSION_BUILD -1 CACHE STRING "Build number. -1 for no build number.")
@@ -248,7 +257,6 @@ add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
add_subdirectory(libraries/javacheck) # java compatibility checker
add_subdirectory(libraries/xz-embedded) # xz compression
add_subdirectory(libraries/quazip) # zip manipulation library
-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
diff --git a/COPYING.md b/COPYING.md
index 8aa7e75e..70ff7ce2 100644
--- a/COPYING.md
+++ b/COPYING.md
@@ -128,35 +128,6 @@
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-# Pack200
-
- The GNU General Public License (GPL)
-
- Version 2, June 1991
-
- + "CLASSPATH" EXCEPTION TO THE GPL
-
- Certain source files distributed by Oracle America and/or its affiliates are
- subject to the following clarification and special exception to the GPL, but
- only where Oracle has expressly included in the particular source file's header
- the words "Oracle designates this particular file as subject to the "Classpath"
- exception as provided by Oracle in the LICENSE file that accompanied this code."
-
- Linking this library statically or dynamically with other modules is making
- a combined work based on this library. Thus, the terms and conditions of
- the GNU General Public License cover the whole combination.
-
- As a special exception, the copyright holders of this library give you
- permission to link this library with independent modules to produce an
- executable, regardless of the license terms of these independent modules,
- and to copy and distribute the resulting executable under terms of your
- choice, provided that you also meet, for each linked independent module,
- the terms and conditions of the license of that module. An independent
- module is a module which is not derived from or based on this library. If
- you modify this library, you may extend this exception to your version of
- the library, but you are not obligated to do so. If you do not wish to do
- so, delete this exception statement from your version.
-
# Quazip
Copyright (C) 2005-2011 Sergey A. Tachenov
diff --git a/README.md b/README.md
index f3dcde25..a66c21d3 100644
--- a/README.md
+++ b/README.md
@@ -44,3 +44,36 @@ Copyright © 2013-2019 MultiMC Contributors
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this program except in compliance with the License. You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](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.
+
+## Build status
+### Linux (Intel32)
+<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Linux32_Build&guest=1">
+Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Linux32_Build)/statusIcon"/>
+</a>
+<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Linux32_Deploy&guest=1">
+Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Linux32_Deploy)/statusIcon"/>
+</a>
+
+### Linux (AMD64)
+<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Linux64_Build&guest=1">
+Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Linux64_Build)/statusIcon"/>
+</a>
+<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Linux64_Deploy&guest=1">
+Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Linux64_Deploy)/statusIcon"/>
+</a>
+
+### macOS (AMD64)
+<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_MacOS_Build&guest=1">
+Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_MacOS_Build)/statusIcon"/>
+</a>
+<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_MacOS_Deploy&guest=1">
+Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_MacOS_Deploy)/statusIcon"/>
+</a>
+
+### Windows (Intel32)
+<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Windows_Build&guest=1">
+Build: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Windows_Build)/statusIcon"/>
+</a>
+<a href="https://teamcity.multimc.org/viewType.html?buildTypeId=MultiMC_Launcher_Windows_Deploy&guest=1">
+Deploy: <img src="https://teamcity.multimc.org/app/rest/builds/buildType:(id:MultiMC_Launcher_Windows_Deploy)/statusIcon"/>
+</a>
diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt
index db1a7dec..50c2cb6e 100644
--- a/api/logic/CMakeLists.txt
+++ b/api/logic/CMakeLists.txt
@@ -305,10 +305,6 @@ set(MINECRAFT_SOURCES
minecraft/AssetsUtils.h
minecraft/AssetsUtils.cpp
- # Forge and all things forge related
- minecraft/forge/ForgeXzDownload.h
- minecraft/forge/ForgeXzDownload.cpp
-
# Skin upload utilities
minecraft/SkinUpload.cpp
minecraft/SkinUpload.h
@@ -439,15 +435,14 @@ set(META_SOURCES
)
set(FTB_SOURCES
- modplatform/ftb/FtbPackFetchTask.h
- modplatform/ftb/FtbPackFetchTask.cpp
- modplatform/ftb/FtbPackInstallTask.h
- modplatform/ftb/FtbPackInstallTask.cpp
-
- modplatform/ftb/FtbPrivatePackManager.h
- modplatform/ftb/FtbPrivatePackManager.cpp
-
- modplatform/ftb/PackHelpers.h
+ modplatform/legacy_ftb/PackFetchTask.h
+ modplatform/legacy_ftb/PackFetchTask.cpp
+ modplatform/legacy_ftb/PackInstallTask.h
+ modplatform/legacy_ftb/PackInstallTask.cpp
+ modplatform/legacy_ftb/PrivatePackManager.h
+ modplatform/legacy_ftb/PrivatePackManager.cpp
+
+ modplatform/legacy_ftb/PackHelpers.h
)
set(FLAME_SOURCES
@@ -456,8 +451,6 @@ set(FLAME_SOURCES
modplatform/flame/PackManifest.cpp
modplatform/flame/FileResolvingTask.h
modplatform/flame/FileResolvingTask.cpp
- modplatform/flame/UrlResolvingTask.h
- modplatform/flame/UrlResolvingTask.cpp
)
add_unit_test(Index
@@ -498,7 +491,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 MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES})
+target_link_libraries(MultiMC_logic systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES})
target_link_libraries(MultiMC_logic Qt5::Core Qt5::Xml Qt5::Network Qt5::Concurrent)
# Mark and export headers
diff --git a/api/logic/Commandline.h b/api/logic/Commandline.h
index 5f6e5510..1adfb79d 100644
--- a/api/logic/Commandline.h
+++ b/api/logic/Commandline.h
@@ -69,8 +69,8 @@ namespace ArgumentStyle
{
enum Enum
{
- Space, /**< --option=value */
- Equals, /**< --option value */
+ Space, /**< --option value */
+ Equals, /**< --option=value */
SpaceAndEquals, /**< --option[= ]value */
#ifdef Q_OS_WIN32
Default = Equals
diff --git a/api/logic/Env.cpp b/api/logic/Env.cpp
index 77546bbc..0d496d4e 100644
--- a/api/logic/Env.cpp
+++ b/api/logic/Env.cpp
@@ -97,6 +97,7 @@ void Env::initHttpMetaCache()
m_metacache->addBase("liteloader", QDir("mods/liteloader").absolutePath());
m_metacache->addBase("general", QDir("cache").absolutePath());
m_metacache->addBase("FTBPacks", QDir("cache/FTBPacks").absolutePath());
+ m_metacache->addBase("TwitchPacks", QDir("cache/TwitchPacks").absolutePath());
m_metacache->addBase("skins", QDir("accounts/skins").absolutePath());
m_metacache->addBase("root", QDir::currentPath());
m_metacache->addBase("translations", QDir("translations").absolutePath());
diff --git a/api/logic/InstanceCopyTask.cpp b/api/logic/InstanceCopyTask.cpp
index a576a0fd..35adeaf9 100644
--- a/api/logic/InstanceCopyTask.cpp
+++ b/api/logic/InstanceCopyTask.cpp
@@ -5,9 +5,10 @@
#include "pathmatcher/RegexpMatcher.h"
#include <QtConcurrentRun>
-InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves)
+InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime)
{
m_origInstance = origInstance;
+ m_keepPlaytime = keepPlaytime;
if(!copySaves)
{
@@ -46,6 +47,9 @@ void InstanceCopyTask::copyFinished()
InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
inst->setName(m_instName);
inst->setIconKey(m_instIcon);
+ if(!m_keepPlaytime) {
+ inst->resetTimePlayed();
+ }
emitSucceeded();
}
diff --git a/api/logic/InstanceCopyTask.h b/api/logic/InstanceCopyTask.h
index 8dd55b40..6465e92d 100644
--- a/api/logic/InstanceCopyTask.h
+++ b/api/logic/InstanceCopyTask.h
@@ -15,7 +15,7 @@ class MULTIMC_LOGIC_EXPORT InstanceCopyTask : public InstanceTask
{
Q_OBJECT
public:
- explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves);
+ explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves, bool keepPlaytime);
protected:
//! Entry point for tasks.
@@ -28,4 +28,5 @@ private: /* data */
QFuture<bool> m_copyFuture;
QFutureWatcher<bool> m_copyFutureWatcher;
std::unique_ptr<IPathMatcher> m_matcher;
+ bool m_keepPlaytime;
};
diff --git a/api/logic/Version.cpp b/api/logic/Version.cpp
index 42eac669..6392a50f 100644
--- a/api/logic/Version.cpp
+++ b/api/logic/Version.cpp
@@ -78,7 +78,7 @@ void Version::parse()
// FIXME: this is bad. versions can contain a lot more separators...
QStringList parts = m_string.split('.');
- for (const auto part : parts)
+ for (const auto &part : parts)
{
m_sections.append(Section(part));
}
diff --git a/api/logic/minecraft/ComponentUpdateTask.cpp b/api/logic/minecraft/ComponentUpdateTask.cpp
index 15003160..84c0474c 100644
--- a/api/logic/minecraft/ComponentUpdateTask.cpp
+++ b/api/logic/minecraft/ComponentUpdateTask.cpp
@@ -451,13 +451,17 @@ static bool getTrivialComponentChanges(const ComponentIndex & index, const Requi
auto & comp = (*compIter);
if(comp->getVersion() != req.equalsVersion)
{
- if(comp->m_dependencyOnly)
- {
- decision = Decision::VersionNotSame;
- }
- else
- {
+ if(comp->isCustom()) {
decision = Decision::LockedVersionNotSame;
+ } else {
+ if(comp->m_dependencyOnly)
+ {
+ decision = Decision::VersionNotSame;
+ }
+ else
+ {
+ decision = Decision::LockedVersionNotSame;
+ }
}
break;
}
diff --git a/api/logic/minecraft/LaunchProfile.cpp b/api/logic/minecraft/LaunchProfile.cpp
index c39bdf04..41705187 100644
--- a/api/logic/minecraft/LaunchProfile.cpp
+++ b/api/logic/minecraft/LaunchProfile.cpp
@@ -11,6 +11,7 @@ void LaunchProfile::clear()
m_mainClass.clear();
m_appletClass.clear();
m_libraries.clear();
+ m_mavenFiles.clear();
m_traits.clear();
m_jarMods.clear();
m_mainJar.reset();
@@ -157,6 +158,22 @@ void LaunchProfile::applyLibrary(LibraryPtr library)
}
}
+void LaunchProfile::applyMavenFile(LibraryPtr mavenFile)
+{
+ if(!mavenFile->isActive())
+ {
+ return;
+ }
+
+ if(mavenFile->isNative())
+ {
+ return;
+ }
+
+ // unlike libraries, we do not keep only one version or try to dedupe them
+ m_mavenFiles.append(Library::limitedCopy(mavenFile));
+}
+
const LibraryPtr LaunchProfile::getMainJar() const
{
return m_mainJar;
@@ -253,6 +270,11 @@ const QList<LibraryPtr> & LaunchProfile::getNativeLibraries() const
return m_nativeLibraries;
}
+const QList<LibraryPtr> & LaunchProfile::getMavenFiles() const
+{
+ return m_mavenFiles;
+}
+
void LaunchProfile::getLibraryFiles(
const QString& architecture,
QStringList& jars,
diff --git a/api/logic/minecraft/LaunchProfile.h b/api/logic/minecraft/LaunchProfile.h
index 77174079..c1752531 100644
--- a/api/logic/minecraft/LaunchProfile.h
+++ b/api/logic/minecraft/LaunchProfile.h
@@ -20,6 +20,7 @@ public: /* application of profile variables from patches */
void applyJarMods(const QList<LibraryPtr> &jarMods);
void applyMods(const QList<LibraryPtr> &jarMods);
void applyLibrary(LibraryPtr library);
+ void applyMavenFile(LibraryPtr library);
void applyMainJar(LibraryPtr jar);
void applyProblemSeverity(ProblemSeverity severity);
/// clear the profile
@@ -37,6 +38,7 @@ public: /* getters for profile variables */
const QList<LibraryPtr> & getJarMods() const;
const QList<LibraryPtr> & getLibraries() const;
const QList<LibraryPtr> & getNativeLibraries() const;
+ const QList<LibraryPtr> & getMavenFiles() const;
const LibraryPtr getMainJar() const;
void getLibraryFiles(
const QString & architecture,
@@ -79,10 +81,13 @@ private:
/// the list of libraries
QList<LibraryPtr> m_libraries;
+ /// the list of maven files to be placed in the libraries folder, but not acted upon
+ QList<LibraryPtr> m_mavenFiles;
+
/// the main jar
LibraryPtr m_mainJar;
- /// the list of libraries
+ /// the list of native libraries
QList<LibraryPtr> m_nativeLibraries;
/// traits, collected from all the version files (version files can only add)
diff --git a/api/logic/minecraft/Library.cpp b/api/logic/minecraft/Library.cpp
index a56e8110..9ff8dcdc 100644
--- a/api/logic/minecraft/Library.cpp
+++ b/api/logic/minecraft/Library.cpp
@@ -3,7 +3,6 @@
#include <net/Download.h>
#include <net/ChecksumValidator.h>
-#include <minecraft/forge/ForgeXzDownload.h>
#include <Env.h>
#include <FileSystem.h>
@@ -88,26 +87,19 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
{
options |= Net::Download::Option::AcceptLocalFiles;
}
- if (isForge())
+
+ if(sha1.size())
{
- qDebug() << "XzDownload for:" << rawName() << "storage:" << storage << "url:" << url;
- out.append(ForgeXzDownload::make(url, storage, entry));
+ auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
+ auto dl = Net::Download::makeCached(url, entry, options);
+ dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
+ qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
+ out.append(dl);
}
else
{
- if(sha1.size())
- {
- auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
- auto dl = Net::Download::makeCached(url, entry, options);
- dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
- qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
- out.append(dl);
- }
- else
- {
- out.append(Net::Download::makeCached(url, entry, options));
- qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
- }
+ out.append(Net::Download::makeCached(url, entry, options));
+ qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
}
return true;
};
@@ -243,11 +235,6 @@ bool Library::isAlwaysStale() const
return m_hint == "always-stale";
}
-bool Library::isForge() const
-{
- return m_hint == "forge-pack-xz";
-}
-
void Library::setStoragePrefix(QString prefix)
{
m_storagePrefix = prefix;
diff --git a/api/logic/minecraft/MinecraftUpdate.cpp b/api/logic/minecraft/MinecraftUpdate.cpp
index 00558e37..f9ff114d 100644
--- a/api/logic/minecraft/MinecraftUpdate.cpp
+++ b/api/logic/minecraft/MinecraftUpdate.cpp
@@ -14,7 +14,6 @@
*/
#include "Env.h"
-#include <minecraft/forge/ForgeXzDownload.h>
#include "MinecraftUpdate.h"
#include "MinecraftInstance.h"
diff --git a/api/logic/minecraft/OneSixVersionFormat.cpp b/api/logic/minecraft/OneSixVersionFormat.cpp
index 6f3b926b..a0b6fd0e 100644
--- a/api/logic/minecraft/OneSixVersionFormat.cpp
+++ b/api/logic/minecraft/OneSixVersionFormat.cpp
@@ -144,14 +144,14 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
}
}
- auto readLibs = [&](const char * which)
+ auto readLibs = [&](const char * which, QList<LibraryPtr> & out)
{
for (auto libVal : requireArray(root.value(which)))
{
QJsonObject libObj = requireObject(libVal);
// parse the library
auto lib = libraryFromJson(libObj, filename);
- out->libraries.append(lib);
+ out.append(lib);
}
};
bool hasPlusLibs = root.contains("+libraries");
@@ -160,16 +160,20 @@ VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc
{
out->addProblem(ProblemSeverity::Warning,
QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported."));
- readLibs("libraries");
- readLibs("+libraries");
+ readLibs("libraries", out->libraries);
+ readLibs("+libraries", out->libraries);
}
else if (hasLibs)
{
- readLibs("libraries");
+ readLibs("libraries", out->libraries);
}
else if(hasPlusLibs)
{
- readLibs("+libraries");
+ readLibs("+libraries", out->libraries);
+ }
+
+ if(root.contains("mavenFiles")) {
+ readLibs("mavenFiles", out->mavenFiles);
}
// if we have mainJar, just use it
@@ -276,6 +280,15 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch
}
root.insert("libraries", array);
}
+ if (!patch->mavenFiles.isEmpty())
+ {
+ QJsonArray array;
+ for (auto value: patch->mavenFiles)
+ {
+ array.append(OneSixVersionFormat::libraryToJson(value.get()));
+ }
+ root.insert("mavenFiles", array);
+ }
if (!patch->jarMods.isEmpty())
{
QJsonArray array;
diff --git a/api/logic/minecraft/VersionFile.cpp b/api/logic/minecraft/VersionFile.cpp
index cfb9e504..5bad57e9 100644
--- a/api/logic/minecraft/VersionFile.cpp
+++ b/api/logic/minecraft/VersionFile.cpp
@@ -41,6 +41,10 @@ void VersionFile::applyTo(LaunchProfile *profile)
{
profile->applyLibrary(library);
}
+ for (auto mavenFile : mavenFiles)
+ {
+ profile->applyMavenFile(mavenFile);
+ }
profile->applyProblemSeverity(getProblemSeverity());
}
@@ -53,4 +57,4 @@ void VersionFile::applyTo(LaunchProfile *profile)
throw MinecraftVersionMismatch(uid, dependsOnMinecraftVersion, theirVersion);
}
}
-*/ \ No newline at end of file
+*/
diff --git a/api/logic/minecraft/VersionFile.h b/api/logic/minecraft/VersionFile.h
index 3dc9db96..29ddd0bc 100644
--- a/api/logic/minecraft/VersionFile.h
+++ b/api/logic/minecraft/VersionFile.h
@@ -75,6 +75,9 @@ public: /* data */
/// Mojang: list of libraries to add to the version
QList<LibraryPtr> libraries;
+ /// MultiMC: list of maven files to put in the libraries folder, but not in classpath
+ QList<LibraryPtr> mavenFiles;
+
/// The main jar (Minecraft version library, normally)
LibraryPtr mainJar;
diff --git a/api/logic/minecraft/forge/ForgeXzDownload.cpp b/api/logic/minecraft/forge/ForgeXzDownload.cpp
deleted file mode 100644
index c6465469..00000000
--- a/api/logic/minecraft/forge/ForgeXzDownload.cpp
+++ /dev/null
@@ -1,393 +0,0 @@
-/* Copyright 2013-2019 MultiMC Contributors
- *
- * 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 "Env.h"
-#include "ForgeXzDownload.h"
-#include <FileSystem.h>
-
-#include <QCryptographicHash>
-#include <QFileInfo>
-#include <QDateTime>
-#include <QDir>
-#include <QDebug>
-
-ForgeXzDownload::ForgeXzDownload(QString url, QString relative_path, MetaEntryPtr entry) : NetAction()
-{
- m_entry = entry;
- m_target_path = entry->getFullPath();
- m_pack200_xz_file.setFileTemplate("./dl_temp.XXXXXX");
- m_status = Job_NotStarted;
- m_url_path = relative_path;
- m_url = url + ".pack.xz";
-}
-
-void ForgeXzDownload::start()
-{
- if(m_status == Job_Aborted)
- {
- qWarning() << "Attempt to start an aborted Download:" << m_url.toString();
- emit aborted(m_index_within_job);
- return;
- }
- m_status = Job_InProgress;
- if (!m_entry->isStale())
- {
- m_status = Job_Finished;
- emit succeeded(m_index_within_job);
- return;
- }
- // can we actually create the real, final file?
- if (!FS::ensureFilePathExists(m_target_path))
- {
- m_status = Job_Failed;
- emit failed(m_index_within_job);
- return;
- }
-
- qDebug() << "Downloading " << m_url.toString();
- QNetworkRequest request(m_url);
- request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
- request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
-
- QNetworkReply *rep = ENV.qnam().get(request);
-
- m_reply.reset(rep);
- connect(rep, SIGNAL(downloadProgress(qint64, qint64)), SLOT(downloadProgress(qint64, qint64)));
- connect(rep, SIGNAL(finished()), SLOT(downloadFinished()));
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError)));
- connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead()));
-}
-
-void ForgeXzDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
-{
- m_total_progress = bytesTotal;
- m_progress = bytesReceived;
- emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
-}
-
-void ForgeXzDownload::downloadError(QNetworkReply::NetworkError error)
-{
- if(error == QNetworkReply::OperationCanceledError)
- {
- qCritical() << "Aborted " << m_url.toString();
- m_status = Job_Aborted;
- }
- else
- {
- // error happened during download.
- qCritical() << "Failed " << m_url.toString() << " with reason " << error;
- m_status = Job_Failed;
- }
-}
-
-void ForgeXzDownload::failAndTryNextMirror()
-{
- m_status = Job_Failed;
- emit failed(m_index_within_job);
-}
-
-void ForgeXzDownload::downloadFinished()
-{
- // if the download succeeded
- if (m_status != Job_Failed && m_status != Job_Aborted)
- {
- // nothing went wrong...
- m_status = Job_Finished;
- if (m_pack200_xz_file.isOpen())
- {
- // we actually downloaded something! process and isntall it
- decompressAndInstall();
- return;
- }
- else
- {
- // something bad happened -- on the local machine!
- m_status = Job_Failed;
- m_pack200_xz_file.remove();
- m_reply.reset();
- emit failed(m_index_within_job);
- return;
- }
- }
- else if(m_status == Job_Aborted)
- {
- m_pack200_xz_file.remove();
- m_reply.reset();
- emit failed(m_index_within_job);
- emit aborted(m_index_within_job);
- return;
- }
- // else the download failed
- else
- {
- m_status = Job_Failed;
- m_pack200_xz_file.close();
- m_pack200_xz_file.remove();
- m_reply.reset();
- failAndTryNextMirror();
- return;
- }
-}
-
-void ForgeXzDownload::downloadReadyRead()
-{
-
- if (!m_pack200_xz_file.isOpen())
- {
- if (!m_pack200_xz_file.open())
- {
- /*
- * Can't open the file... the job failed
- */
- m_reply->abort();
- emit failed(m_index_within_job);
- return;
- }
- }
- m_pack200_xz_file.write(m_reply->readAll());
-}
-
-#include "xz.h"
-#include "unpack200.h"
-#include <stdexcept>
-#include <unistd.h>
-
-const size_t buffer_size = 8196;
-
-// NOTE: once this gets here, it can't be aborted anymore. we don't care.
-void ForgeXzDownload::decompressAndInstall()
-{
- // rewind the downloaded temp file
- m_pack200_xz_file.seek(0);
- // de-xz'd file
- QTemporaryFile pack200_file("./dl_temp.XXXXXX");
- pack200_file.open();
-
- bool xz_success = false;
- // first, de-xz
- {
- uint8_t in[buffer_size];
- uint8_t out[buffer_size];
- struct xz_buf b;
- struct xz_dec *s;
- enum xz_ret ret;
- xz_crc32_init();
- xz_crc64_init();
- s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
- if (s == nullptr)
- {
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
- }
- b.in = in;
- b.in_pos = 0;
- b.in_size = 0;
- b.out = out;
- b.out_pos = 0;
- b.out_size = buffer_size;
- while (!xz_success)
- {
- if (b.in_pos == b.in_size)
- {
- b.in_size = m_pack200_xz_file.read((char *)in, sizeof(in));
- b.in_pos = 0;
- }
-
- ret = xz_dec_run(s, &b);
-
- if (b.out_pos == sizeof(out))
- {
- auto wresult = pack200_file.write((char *)out, b.out_pos);
- if (wresult < 0 || size_t(wresult) != b.out_pos)
- {
- // msg = "Write error\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
- }
-
- b.out_pos = 0;
- }
-
- if (ret == XZ_OK)
- continue;
-
- if (ret == XZ_UNSUPPORTED_CHECK)
- {
- // unsupported check. this is OK, but we should log this
- continue;
- }
-
- auto wresult = pack200_file.write((char *)out, b.out_pos);
- if (wresult < 0 || size_t(wresult) != b.out_pos)
- {
- // write error
- pack200_file.close();
- xz_dec_end(s);
- return;
- }
-
- switch (ret)
- {
- case XZ_STREAM_END:
- xz_dec_end(s);
- xz_success = true;
- break;
-
- case XZ_MEM_ERROR:
- qCritical() << "Memory allocation failed\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- case XZ_MEMLIMIT_ERROR:
- qCritical() << "Memory usage limit reached\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- case XZ_FORMAT_ERROR:
- qCritical() << "Not a .xz file\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- case XZ_OPTIONS_ERROR:
- qCritical() << "Unsupported options in the .xz headers\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- case XZ_DATA_ERROR:
- case XZ_BUF_ERROR:
- qCritical() << "File is corrupt\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
-
- default:
- qCritical() << "Bug!\n";
- xz_dec_end(s);
- failAndTryNextMirror();
- return;
- }
- }
- }
- m_pack200_xz_file.remove();
-
- // revert pack200
- pack200_file.seek(0);
- int handle_in = pack200_file.handle();
- // FIXME: dispose of file handles, pointers and the like. Ideally wrap in objects.
- if(handle_in == -1)
- {
- qCritical() << "Error reopening " << pack200_file.fileName();
- failAndTryNextMirror();
- return;
- }
- int handle_in_dup = dup (handle_in);
- if(handle_in_dup == -1)
- {
- qCritical() << "Error reopening " << pack200_file.fileName();
- failAndTryNextMirror();
- return;
- }
- FILE *file_in = fdopen (handle_in_dup, "rb");
- if(!file_in)
- {
- qCritical() << "Error reopening " << pack200_file.fileName();
- failAndTryNextMirror();
- return;
- }
- QFile qfile_out(m_target_path);
- if(!qfile_out.open(QIODevice::WriteOnly))
- {
- qCritical() << "Error opening " << qfile_out.fileName();
- failAndTryNextMirror();
- return;
- }
- int handle_out = qfile_out.handle();
- if(handle_out == -1)
- {
- qCritical() << "Error opening " << qfile_out.fileName();
- failAndTryNextMirror();
- return;
- }
- int handle_out_dup = dup (handle_out);
- if(handle_out_dup == -1)
- {
- qCritical() << "Error reopening " << qfile_out.fileName();
- failAndTryNextMirror();
- return;
- }
- FILE *file_out = fdopen (handle_out_dup, "wb");
- if(!file_out)
- {
- qCritical() << "Error opening " << qfile_out.fileName();
- failAndTryNextMirror();
- return;
- }
- try
- {
- // NOTE: this takes ownership of both FILE pointers. That's why we duplicate them above.
- unpack_200(file_in, file_out);
- }
- catch (const std::runtime_error &err)
- {
- m_status = Job_Failed;
- qCritical() << "Error unpacking " << pack200_file.fileName() << " : " << err.what();
- QFile f(m_target_path);
- if (f.exists())
- f.remove();
- failAndTryNextMirror();
- return;
- }
- pack200_file.remove();
-
- QFile jar_file(m_target_path);
-
- if (!jar_file.open(QIODevice::ReadOnly))
- {
- jar_file.remove();
- failAndTryNextMirror();
- return;
- }
- auto hash = QCryptographicHash::hash(jar_file.readAll(), QCryptographicHash::Md5);
- m_entry->setMD5Sum(hash.toHex().constData());
- jar_file.close();
-
- QFileInfo output_file_info(m_target_path);
- m_entry->setETag(m_reply->rawHeader("ETag").constData());
- m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch());
- m_entry->setStale(false);
- ENV.metacache()->updateEntry(m_entry);
-
- m_reply.reset();
- emit succeeded(m_index_within_job);
-}
-
-bool ForgeXzDownload::abort()
-{
- if(m_reply)
- m_reply->abort();
- m_status = Job_Aborted;
- return true;
-}
-
-bool ForgeXzDownload::canAbort()
-{
- return true;
-}
diff --git a/api/logic/minecraft/forge/ForgeXzDownload.h b/api/logic/minecraft/forge/ForgeXzDownload.h
deleted file mode 100644
index 63e75f71..00000000
--- a/api/logic/minecraft/forge/ForgeXzDownload.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright 2013-2019 MultiMC Contributors
- *
- * 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 "net/NetAction.h"
-#include "net/HttpMetaCache.h"
-#include <QFile>
-#include <QTemporaryFile>
-
-typedef std::shared_ptr<class ForgeXzDownload> ForgeXzDownloadPtr;
-
-class ForgeXzDownload : public NetAction
-{
- Q_OBJECT
-public:
- MetaEntryPtr m_entry;
- /// if saving to file, use the one specified in this string
- QString m_target_path;
- /// this is the output file, if any
- QTemporaryFile m_pack200_xz_file;
- /// path relative to the mirror base
- QString m_url_path;
-
-public:
- explicit ForgeXzDownload(QString url, QString relative_path, MetaEntryPtr entry);
- static ForgeXzDownloadPtr make(QString url, QString relative_path, MetaEntryPtr entry)
- {
- return ForgeXzDownloadPtr(new ForgeXzDownload(url, relative_path, entry));
- }
- virtual ~ForgeXzDownload(){};
- bool canAbort() override;
-
-protected
-slots:
- void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
- void downloadError(QNetworkReply::NetworkError error) override;
- void downloadFinished() override;
- void downloadReadyRead() override;
-
-public
-slots:
- void start() override;
- bool abort() override;
-
-private:
- void decompressAndInstall();
- void failAndTryNextMirror();
-};
diff --git a/api/logic/minecraft/mod/ModFolderModel.h b/api/logic/minecraft/mod/ModFolderModel.h
index 8394e405..03c584a9 100644
--- a/api/logic/minecraft/mod/ModFolderModel.h
+++ b/api/logic/minecraft/mod/ModFolderModel.h
@@ -85,6 +85,10 @@ public:
{
return mods[index];
}
+ const Mod &at(size_t index) const
+ {
+ return mods.at(index);
+ }
/// Reloads the mod list and returns true if the list changed.
bool update();
diff --git a/api/logic/minecraft/update/LibrariesTask.cpp b/api/logic/minecraft/update/LibrariesTask.cpp
index 912f492b..a000f77f 100644
--- a/api/logic/minecraft/update/LibrariesTask.cpp
+++ b/api/logic/minecraft/update/LibrariesTask.cpp
@@ -45,6 +45,7 @@ void LibrariesTask::executeTask()
QList<LibraryPtr> libArtifactPool;
libArtifactPool.append(profile->getLibraries());
libArtifactPool.append(profile->getNativeLibraries());
+ libArtifactPool.append(profile->getMavenFiles());
libArtifactPool.append(profile->getMainJar());
processArtifactPool(libArtifactPool, failedLocalLibraries, inst->getLocalLibraryPath());
diff --git a/api/logic/modplatform/flame/UrlResolvingTask.cpp b/api/logic/modplatform/flame/UrlResolvingTask.cpp
deleted file mode 100644
index 2a96f703..00000000
--- a/api/logic/modplatform/flame/UrlResolvingTask.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-#include "UrlResolvingTask.h"
-#include <QtXml>
-#include <Json.h>
-
-
-namespace {
- const char * metabase = "https://cursemeta.dries007.net";
-}
-
-Flame::UrlResolvingTask::UrlResolvingTask(const QString& toProcess)
- : m_url(toProcess)
-{
-}
-
-void Flame::UrlResolvingTask::executeTask()
-{
- resolveUrl();
-}
-
-void Flame::UrlResolvingTask::resolveUrl()
-{
- setStatus(tr("Resolving URL..."));
- setProgress(0, 1);
- QUrl actualUrl(m_url);
- if(actualUrl.host() != "www.curseforge.com") {
- emitFailed(tr("Not a Twitch URL."));
- return;
- }
- m_dljob.reset(new NetJob("URL resolver"));
-
- bool weAreDigging = false;
- needle = QString();
-
- if(m_url.startsWith("https://")) {
- if(m_url.endsWith("?client=y")) {
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download?client=y
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download/2697088?client=y
- m_url.chop(9);
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download/2697088
- }
- if(m_url.endsWith("/download")) {
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download -> need to dig inside html...
- weAreDigging = true;
- needle = m_url;
- needle.replace("https://", "twitch://");
- needle.replace("/download", "/download-client/");
- m_url.append("?client=y");
- } else if (m_url.contains("/download/")) {
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download/2697088
- m_url.replace("/download/", "/download-client/");
- }
- }
- else if(m_url.startsWith("twitch://")) {
- // twitch://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download-client/2697088
- m_url.replace(0, 9, "https://");
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download-client/2697088
- }
- auto dl = Net::Download::makeByteArray(QUrl(m_url), &results);
- m_dljob->addNetAction(dl);
- if(weAreDigging) {
- connect(m_dljob.get(), &NetJob::finished, this, &Flame::UrlResolvingTask::processHTML);
- } else {
- connect(m_dljob.get(), &NetJob::finished, this, &Flame::UrlResolvingTask::processCCIP);
- }
- m_dljob->start();
-}
-
-void Flame::UrlResolvingTask::processHTML()
-{
- QString htmlDoc = QString::fromUtf8(results);
- auto index = htmlDoc.indexOf(needle);
- if(index < 0) {
- emitFailed(tr("Couldn't find the needle in the haystack..."));
- return;
- }
- auto indexStart = index;
- int indexEnd = -1;
- while((index + 1) < htmlDoc.size() && htmlDoc[index] != '"') {
- index ++;
- if(htmlDoc[index] == '"') {
- indexEnd = index;
- break;
- }
- }
- if(indexEnd > 0) {
- QString found = htmlDoc.mid(indexStart, indexEnd - indexStart);
- qDebug() << "Found needle: " << found;
- // twitch://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download-client/2697088
- m_url = found;
- resolveUrl();
- return;
- }
- emitFailed(tr("Couldn't find the end of the needle in the haystack..."));
- return;
-}
-
-void Flame::UrlResolvingTask::processCCIP()
-{
- QDomDocument doc;
- if (!doc.setContent(results)) {
- qDebug() << results;
- emitFailed(tr("Resolving failed."));
- return;
- }
- auto packageNode = doc.namedItem("package");
- if(!packageNode.isElement()) {
- emitFailed(tr("Resolving failed: missing package root element."));
- return;
- }
- auto projectNode = packageNode.namedItem("project");
- if(!projectNode.isElement()) {
- emitFailed(tr("Resolving failed: missing project element."));
- return;
- }
- auto attribs = projectNode.attributes();
-
- auto projectIdNode = attribs.namedItem("id");
- if(!projectIdNode.isAttr()) {
- emitFailed(tr("Resolving failed: missing id attribute."));
- return;
- }
- auto fileIdNode = attribs.namedItem("file");
- if(!fileIdNode.isAttr()) {
- emitFailed(tr("Resolving failed: missing file attribute."));
- return;
- }
-
- auto projectId = projectIdNode.nodeValue();
- auto fileId = fileIdNode.nodeValue();
- bool success = true;
- m_result.projectId = projectId.toInt(&success);
- if(!success) {
- emitFailed(tr("Failed to resolve projectId as a number."));
- return;
- }
- m_result.fileId = fileId.toInt(&success);
- if(!success) {
- emitFailed(tr("Failed to resolve fileId as a number."));
- return;
- }
- qDebug() << "Resolved" << m_url << "as" << m_result.projectId << "/" << m_result.fileId;
- resolveIDs();
-}
-
-void Flame::UrlResolvingTask::resolveIDs()
-{
- setStatus(tr("Resolving mod IDs..."));
- m_dljob.reset(new NetJob("Mod id resolver"));
- auto projectIdStr = QString::number(m_result.projectId);
- auto fileIdStr = QString::number(m_result.fileId);
- QString metaurl = QString("%1/%2/%3.json").arg(metabase, projectIdStr, fileIdStr);
- auto dl = Net::Download::makeByteArray(QUrl(metaurl), &results);
- m_dljob->addNetAction(dl);
- connect(m_dljob.get(), &NetJob::finished, this, &Flame::UrlResolvingTask::processCursemeta);
- m_dljob->start();
-}
-
-void Flame::UrlResolvingTask::processCursemeta()
-{
- try {
- if(m_result.parseFromBytes(results)) {
- emitSucceeded();
- qDebug() << results;
- return;
- }
- } catch (const JSONValidationError &e) {
-
- qCritical() << "Resolving of" << m_result.projectId << m_result.fileId << "failed because of a parsing error:";
- qCritical() << e.cause();
- qCritical() << "JSON:";
- qCritical() << results;
- }
- emitFailed(tr("Failed to resolve the modpack file."));
-}
diff --git a/api/logic/modplatform/flame/UrlResolvingTask.h b/api/logic/modplatform/flame/UrlResolvingTask.h
deleted file mode 100644
index 98b78f67..00000000
--- a/api/logic/modplatform/flame/UrlResolvingTask.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#pragma once
-
-#include "tasks/Task.h"
-#include "net/NetJob.h"
-#include "PackManifest.h"
-
-#include "multimc_logic_export.h"
-
-namespace Flame
-{
-class MULTIMC_LOGIC_EXPORT UrlResolvingTask : public Task
-{
- Q_OBJECT
-public:
- explicit UrlResolvingTask(const QString &toProcess);
- virtual ~UrlResolvingTask() {};
-
- const Flame::File &getResults() const
- {
- return m_result;
- }
-
-protected:
- virtual void executeTask() override;
-
-protected slots:
- void processCCIP();
- void processHTML();
- void processCursemeta();
-
-private:
- void resolveUrl();
- void resolveIDs();
-
-private: /* data */
- QString m_url;
- QString needle;
- Flame::File m_result;
- QByteArray results;
- NetJobPtr m_dljob;
-};
-}
-
diff --git a/api/logic/modplatform/ftb/FtbPackFetchTask.cpp b/api/logic/modplatform/legacy_ftb/PackFetchTask.cpp
index fe3f3fac..43c1e6f8 100644
--- a/api/logic/modplatform/ftb/FtbPackFetchTask.cpp
+++ b/api/logic/modplatform/legacy_ftb/PackFetchTask.cpp
@@ -1,34 +1,36 @@
-#include "FtbPackFetchTask.h"
-#include <QDomDocument>
-#include "FtbPrivatePackManager.h"
+#include "PackFetchTask.h"
+#include "PrivatePackManager.h"
+#include <QDomDocument>
#include "net/URLConstants.h"
-void FtbPackFetchTask::fetch()
+namespace LegacyFTB {
+
+void PackFetchTask::fetch()
{
publicPacks.clear();
thirdPartyPacks.clear();
- NetJob *netJob = new NetJob("FtbModpackFetch");
+ NetJob *netJob = new NetJob("LegacyFTB::ModpackFetch");
- QUrl publicPacksUrl = QUrl(URLConstants::FTB_CDN_BASE_URL + "static/modpacks.xml");
+ QUrl publicPacksUrl = QUrl(URLConstants::LEGACY_FTB_CDN_BASE_URL + "static/modpacks.xml");
qDebug() << "Downloading public version info from" << publicPacksUrl.toString();
netJob->addNetAction(Net::Download::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData));
- QUrl thirdPartyUrl = QUrl(URLConstants::FTB_CDN_BASE_URL + "static/thirdparty.xml");
+ QUrl thirdPartyUrl = QUrl(URLConstants::LEGACY_FTB_CDN_BASE_URL + "static/thirdparty.xml");
qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString();
netJob->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData));
- QObject::connect(netJob, &NetJob::succeeded, this, &FtbPackFetchTask::fileDownloadFinished);
- QObject::connect(netJob, &NetJob::failed, this, &FtbPackFetchTask::fileDownloadFailed);
+ QObject::connect(netJob, &NetJob::succeeded, this, &PackFetchTask::fileDownloadFinished);
+ QObject::connect(netJob, &NetJob::failed, this, &PackFetchTask::fileDownloadFailed);
jobPtr.reset(netJob);
netJob->start();
}
-void FtbPackFetchTask::fetchPrivate(const QStringList & toFetch)
+void PackFetchTask::fetchPrivate(const QStringList & toFetch)
{
- QString privatePackBaseUrl = URLConstants::FTB_CDN_BASE_URL + "static/%1.xml";
+ QString privatePackBaseUrl = URLConstants::LEGACY_FTB_CDN_BASE_URL + "static/%1.xml";
for (auto &packCode: toFetch)
{
@@ -38,9 +40,9 @@ void FtbPackFetchTask::fetchPrivate(const QStringList & toFetch)
QObject::connect(job, &NetJob::succeeded, this, [this, job, data, packCode]
{
- FtbModpackList packs;
- parseAndAddPacks(*data, FtbPackType::Private, packs);
- foreach(FtbModpack currentPack, packs)
+ ModpackList packs;
+ parseAndAddPacks(*data, PackType::Private, packs);
+ foreach(Modpack currentPack, packs)
{
currentPack.packCode = packCode;
emit privateFileDownloadFinished(currentPack);
@@ -65,18 +67,18 @@ void FtbPackFetchTask::fetchPrivate(const QStringList & toFetch)
}
}
-void FtbPackFetchTask::fileDownloadFinished()
+void PackFetchTask::fileDownloadFinished()
{
jobPtr.reset();
QStringList failedLists;
- if(!parseAndAddPacks(publicModpacksXmlFileData, FtbPackType::Public, publicPacks))
+ if(!parseAndAddPacks(publicModpacksXmlFileData, PackType::Public, publicPacks))
{
failedLists.append(tr("Public Packs"));
}
- if(!parseAndAddPacks(thirdPartyModpacksXmlFileData, FtbPackType::ThirdParty, thirdPartyPacks))
+ if(!parseAndAddPacks(thirdPartyModpacksXmlFileData, PackType::ThirdParty, thirdPartyPacks))
{
failedLists.append(tr("Third Party Packs"));
}
@@ -91,7 +93,7 @@ void FtbPackFetchTask::fileDownloadFinished()
}
}
-bool FtbPackFetchTask::parseAndAddPacks(QByteArray &data, FtbPackType packType, FtbModpackList &list)
+bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, ModpackList &list)
{
QDomDocument doc;
@@ -112,7 +114,7 @@ bool FtbPackFetchTask::parseAndAddPacks(QByteArray &data, FtbPackType packType,
{
QDomElement element = nodes.at(i).toElement();
- FtbModpack modpack;
+ Modpack modpack;
modpack.name = element.attribute("name");
modpack.currentVersion = element.attribute("version");
modpack.mcVersion = element.attribute("mcVersion");
@@ -161,8 +163,10 @@ bool FtbPackFetchTask::parseAndAddPacks(QByteArray &data, FtbPackType packType,
return true;
}
-void FtbPackFetchTask::fileDownloadFailed(QString reason)
+void PackFetchTask::fileDownloadFailed(QString reason)
{
- qWarning() << "Fetching FtbPacks failed:" << reason;
+ qWarning() << "Fetching FTBPacks failed:" << reason;
emit failed(reason);
}
+
+}
diff --git a/api/logic/modplatform/ftb/FtbPackFetchTask.h b/api/logic/modplatform/legacy_ftb/PackFetchTask.h
index f955fe83..4a8469b1 100644
--- a/api/logic/modplatform/ftb/FtbPackFetchTask.h
+++ b/api/logic/modplatform/legacy_ftb/PackFetchTask.h
@@ -6,13 +6,15 @@
#include <QObject>
#include "PackHelpers.h"
-class MULTIMC_LOGIC_EXPORT FtbPackFetchTask : public QObject {
+namespace LegacyFTB {
+
+class MULTIMC_LOGIC_EXPORT PackFetchTask : public QObject {
Q_OBJECT
public:
- FtbPackFetchTask() = default;
- virtual ~FtbPackFetchTask() = default;
+ PackFetchTask() = default;
+ virtual ~PackFetchTask() = default;
void fetch();
void fetchPrivate(const QStringList &toFetch);
@@ -23,18 +25,20 @@ private:
QByteArray publicModpacksXmlFileData;
QByteArray thirdPartyModpacksXmlFileData;
- bool parseAndAddPacks(QByteArray &data, FtbPackType packType, FtbModpackList &list);
- FtbModpackList publicPacks;
- FtbModpackList thirdPartyPacks;
+ bool parseAndAddPacks(QByteArray &data, PackType packType, ModpackList &list);
+ ModpackList publicPacks;
+ ModpackList thirdPartyPacks;
protected slots:
void fileDownloadFinished();
void fileDownloadFailed(QString reason);
signals:
- void finished(FtbModpackList publicPacks, FtbModpackList thirdPartyPacks);
+ void finished(ModpackList publicPacks, ModpackList thirdPartyPacks);
void failed(QString reason);
- void privateFileDownloadFinished(FtbModpack modpack);
+ void privateFileDownloadFinished(Modpack modpack);
void privateFileDownloadFailed(QString reason, QString packCode);
};
+
+}
diff --git a/api/logic/modplatform/ftb/PackHelpers.h b/api/logic/modplatform/legacy_ftb/PackHelpers.h
index 4306caee..566210d0 100644
--- a/api/logic/modplatform/ftb/PackHelpers.h
+++ b/api/logic/modplatform/legacy_ftb/PackHelpers.h
@@ -5,15 +5,17 @@
#include <QStringList>
#include <QMetaType>
+namespace LegacyFTB {
+
//Header for structs etc...
-enum class FtbPackType
+enum class PackType
{
Public,
ThirdParty,
Private
};
-struct FtbModpack
+struct Modpack
{
QString name;
QString description;
@@ -31,11 +33,13 @@ struct FtbModpack
bool bugged = false;
bool broken = false;
- FtbPackType type;
+ PackType type;
QString packCode;
};
-//We need it for the proxy model
-Q_DECLARE_METATYPE(FtbModpack)
+typedef QList<Modpack> ModpackList;
-typedef QList<FtbModpack> FtbModpackList;
+}
+
+//We need it for the proxy model
+Q_DECLARE_METATYPE(LegacyFTB::Modpack)
diff --git a/api/logic/modplatform/ftb/FtbPackInstallTask.cpp b/api/logic/modplatform/legacy_ftb/PackInstallTask.cpp
index 4962bcac..ea7e2c0c 100644
--- a/api/logic/modplatform/ftb/FtbPackInstallTask.cpp
+++ b/api/logic/modplatform/legacy_ftb/PackInstallTask.cpp
@@ -1,28 +1,32 @@
-#include "FtbPackInstallTask.h"
+#include "PackInstallTask.h"
+
#include "Env.h"
#include "MMCZip.h"
-#include "QtConcurrent"
+
#include "BaseInstance.h"
#include "FileSystem.h"
#include "settings/INISettingsObject.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/ComponentList.h"
#include "minecraft/GradleSpecifier.h"
-
#include "net/URLConstants.h"
-FtbPackInstallTask::FtbPackInstallTask(FtbModpack pack, QString version)
+#include <QtConcurrent>
+
+namespace LegacyFTB {
+
+PackInstallTask::PackInstallTask(Modpack pack, QString version)
{
m_pack = pack;
m_version = version;
}
-void FtbPackInstallTask::executeTask()
+void PackInstallTask::executeTask()
{
downloadPack();
}
-void FtbPackInstallTask::downloadPack()
+void PackInstallTask::downloadPack()
{
setStatus(tr("Downloading zip for %1").arg(m_pack.name));
@@ -32,46 +36,46 @@ void FtbPackInstallTask::downloadPack()
entry->setStale(true);
QString url;
- if(m_pack.type == FtbPackType::Private)
+ if(m_pack.type == PackType::Private)
{
- url = QString(URLConstants::FTB_CDN_BASE_URL + "privatepacks/%1").arg(packoffset);
+ url = QString(URLConstants::LEGACY_FTB_CDN_BASE_URL + "privatepacks/%1").arg(packoffset);
}
else
{
- url = QString(URLConstants::FTB_CDN_BASE_URL + "modpacks/%1").arg(packoffset);
+ url = QString(URLConstants::LEGACY_FTB_CDN_BASE_URL + "modpacks/%1").arg(packoffset);
}
job->addNetAction(Net::Download::makeCached(url, entry));
archivePath = entry->getFullPath();
netJobContainer.reset(job);
- connect(job, &NetJob::succeeded, this, &FtbPackInstallTask::onDownloadSucceeded);
- connect(job, &NetJob::failed, this, &FtbPackInstallTask::onDownloadFailed);
- connect(job, &NetJob::progress, this, &FtbPackInstallTask::onDownloadProgress);
+ connect(job, &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded);
+ connect(job, &NetJob::failed, this, &PackInstallTask::onDownloadFailed);
+ connect(job, &NetJob::progress, this, &PackInstallTask::onDownloadProgress);
job->start();
progress(1, 4);
}
-void FtbPackInstallTask::onDownloadSucceeded()
+void PackInstallTask::onDownloadSucceeded()
{
abortable = false;
unzip();
}
-void FtbPackInstallTask::onDownloadFailed(QString reason)
+void PackInstallTask::onDownloadFailed(QString reason)
{
abortable = false;
emitFailed(reason);
}
-void FtbPackInstallTask::onDownloadProgress(qint64 current, qint64 total)
+void PackInstallTask::onDownloadProgress(qint64 current, qint64 total)
{
abortable = true;
progress(current, total * 4);
setStatus(tr("Downloading zip for %1 (%2%)").arg(m_pack.name).arg(current / 10));
}
-void FtbPackInstallTask::unzip()
+void PackInstallTask::unzip()
{
progress(2, 4);
setStatus(tr("Extracting modpack"));
@@ -85,22 +89,22 @@ void FtbPackInstallTask::unzip()
}
m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/unzip");
- connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &FtbPackInstallTask::onUnzipFinished);
- connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &FtbPackInstallTask::onUnzipCanceled);
+ connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &PackInstallTask::onUnzipFinished);
+ connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &PackInstallTask::onUnzipCanceled);
m_extractFutureWatcher.setFuture(m_extractFuture);
}
-void FtbPackInstallTask::onUnzipFinished()
+void PackInstallTask::onUnzipFinished()
{
install();
}
-void FtbPackInstallTask::onUnzipCanceled()
+void PackInstallTask::onUnzipCanceled()
{
emitAborted();
}
-void FtbPackInstallTask::install()
+void PackInstallTask::install()
{
progress(3, 4);
setStatus(tr("Installing modpack"));
@@ -197,7 +201,7 @@ void FtbPackInstallTask::install()
emitSucceeded();
}
-bool FtbPackInstallTask::abort()
+bool PackInstallTask::abort()
{
if(abortable)
{
@@ -205,3 +209,5 @@ bool FtbPackInstallTask::abort()
}
return false;
}
+
+} \ No newline at end of file
diff --git a/api/logic/modplatform/ftb/FtbPackInstallTask.h b/api/logic/modplatform/legacy_ftb/PackInstallTask.h
index 3319025e..1eec1880 100644
--- a/api/logic/modplatform/ftb/FtbPackInstallTask.h
+++ b/api/logic/modplatform/legacy_ftb/PackInstallTask.h
@@ -6,15 +6,17 @@
#include "meta/Index.h"
#include "meta/Version.h"
#include "meta/VersionList.h"
-#include "modplatform/ftb/PackHelpers.h"
+#include "PackHelpers.h"
-class MULTIMC_LOGIC_EXPORT FtbPackInstallTask : public InstanceTask
+namespace LegacyFTB {
+
+class MULTIMC_LOGIC_EXPORT PackInstallTask : public InstanceTask
{
Q_OBJECT
public:
- explicit FtbPackInstallTask(FtbModpack pack, QString version);
- virtual ~FtbPackInstallTask(){}
+ explicit PackInstallTask(Modpack pack, QString version);
+ virtual ~PackInstallTask(){}
bool abort() override;
@@ -43,6 +45,8 @@ private: /* data */
NetJobPtr netJobContainer;
QString archivePath;
- FtbModpack m_pack;
+ Modpack m_pack;
QString m_version;
};
+
+}
diff --git a/api/logic/modplatform/ftb/FtbPrivatePackManager.cpp b/api/logic/modplatform/legacy_ftb/PrivatePackManager.cpp
index c3477cec..501e6003 100644
--- a/api/logic/modplatform/ftb/FtbPrivatePackManager.cpp
+++ b/api/logic/modplatform/legacy_ftb/PrivatePackManager.cpp
@@ -1,10 +1,12 @@
-#include "FtbPrivatePackManager.h"
+#include "PrivatePackManager.h"
#include <QDebug>
#include "FileSystem.h"
-void FtbPrivatePackManager::load()
+namespace LegacyFTB {
+
+void PrivatePackManager::load()
{
try
{
@@ -18,7 +20,7 @@ void FtbPrivatePackManager::load()
}
}
-void FtbPrivatePackManager::save() const
+void PrivatePackManager::save() const
{
if(!dirty)
{
@@ -35,3 +37,5 @@ void FtbPrivatePackManager::save() const
qWarning() << "Failed to write third party FTB pack codes to" << m_filename;
}
}
+
+}
diff --git a/api/logic/modplatform/ftb/FtbPrivatePackManager.h b/api/logic/modplatform/legacy_ftb/PrivatePackManager.h
index 388224d6..0232bac7 100644
--- a/api/logic/modplatform/ftb/FtbPrivatePackManager.h
+++ b/api/logic/modplatform/legacy_ftb/PrivatePackManager.h
@@ -5,10 +5,12 @@
#include <QFile>
#include "multimc_logic_export.h"
-class MULTIMC_LOGIC_EXPORT FtbPrivatePackManager
+namespace LegacyFTB {
+
+class MULTIMC_LOGIC_EXPORT PrivatePackManager
{
public:
- ~FtbPrivatePackManager()
+ ~PrivatePackManager()
{
save();
}
@@ -38,3 +40,5 @@ private:
QString m_filename = "private_packs.txt";
mutable bool dirty = false;
};
+
+}
diff --git a/api/logic/net/URLConstants.h b/api/logic/net/URLConstants.h
index 5ff0f794..ebc495bb 100644
--- a/api/logic/net/URLConstants.h
+++ b/api/logic/net/URLConstants.h
@@ -29,7 +29,8 @@ const QString IMGUR_BASE_URL("https://api.imgur.com/3/");
const QString FMLLIBS_OUR_BASE_URL("https://files.multimc.org/fmllibs/");
const QString FMLLIBS_FORGE_BASE_URL("https://files.minecraftforge.net/fmllibs/");
const QString TRANSLATIONS_BASE_URL("https://files.multimc.org/translations/");
-const QString FTB_CDN_BASE_URL("https://ftb.forgecdn.net/FTB2/");
+
+const QString LEGACY_FTB_CDN_BASE_URL("https://dist.creeper.host/FTB2/");
QString getJarPath(QString version);
QString getLegacyJarUrl(QString version);
diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt
index ce204ae5..53c21866 100644
--- a/application/CMakeLists.txt
+++ b/application/CMakeLists.txt
@@ -125,20 +125,19 @@ SET(MULTIMC_SOURCES
pages/global/ProxyPage.h
pages/global/PasteEEPage.cpp
pages/global/PasteEEPage.h
- pages/global/PackagesPage.cpp
- pages/global/PackagesPage.h
# GUI - platform pages
pages/modplatform/VanillaPage.cpp
pages/modplatform/VanillaPage.h
- pages/modplatform/FTBPage.cpp
- pages/modplatform/FTBPage.h
- pages/modplatform/FtbListModel.h
- pages/modplatform/FtbListModel.cpp
- pages/modplatform/TwitchPage.cpp
- pages/modplatform/TwitchPage.h
- pages/modplatform/TechnicPage.cpp
- pages/modplatform/TechnicPage.h
+ pages/modplatform/legacy_ftb/Page.cpp
+ pages/modplatform/legacy_ftb/Page.h
+ pages/modplatform/legacy_ftb/ListModel.h
+ pages/modplatform/legacy_ftb/ListModel.cpp
+ pages/modplatform/twitch/TwitchData.h
+ pages/modplatform/twitch/TwitchModel.cpp
+ pages/modplatform/twitch/TwitchModel.h
+ pages/modplatform/twitch/TwitchPage.cpp
+ pages/modplatform/twitch/TwitchPage.h
pages/modplatform/ImportPage.cpp
pages/modplatform/ImportPage.h
@@ -182,6 +181,8 @@ SET(MULTIMC_SOURCES
widgets/Common.h
widgets/CustomCommands.cpp
widgets/CustomCommands.h
+ widgets/DropLabel.cpp
+ widgets/DropLabel.h
widgets/FocusLineEdit.cpp
widgets/FocusLineEdit.h
widgets/IconLabel.cpp
@@ -251,13 +252,11 @@ SET(MULTIMC_UIS
pages/global/MultiMCPage.ui
pages/global/ProxyPage.ui
pages/global/PasteEEPage.ui
- pages/global/PackagesPage.ui
# Platform pages
pages/modplatform/VanillaPage.ui
- pages/modplatform/FTBPage.ui
- pages/modplatform/TwitchPage.ui
- pages/modplatform/TechnicPage.ui
+ pages/modplatform/legacy_ftb/Page.ui
+ pages/modplatform/twitch/TwitchPage.ui
pages/modplatform/ImportPage.ui
# Dialogs
@@ -281,7 +280,6 @@ SET(MULTIMC_UIS
)
set(MULTIMC_QRCS
- resources/assets/assets.qrc
resources/backgrounds/backgrounds.qrc
resources/multimc/multimc.qrc
resources/pe_dark/pe_dark.qrc
diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp
index 5122e240..34ffc54b 100644
--- a/application/MainWindow.cpp
+++ b/application/MainWindow.cpp
@@ -578,6 +578,7 @@ public:
MainWindow->resize(800, 600);
MainWindow->setWindowIcon(MMC->getThemedIcon("logo"));
MainWindow->setWindowTitle("MultiMC 5");
+ MainWindow->setAccessibleName("MultiMC");
createMainToolbar(MainWindow);
@@ -1357,7 +1358,7 @@ void MainWindow::on_actionCopyInstance_triggered()
if (!copyInstDlg.exec())
return;
- auto copyTask = new InstanceCopyTask(m_selectedInstance, copyInstDlg.shouldCopySaves());
+ auto copyTask = new InstanceCopyTask(m_selectedInstance, copyInstDlg.shouldCopySaves(), copyInstDlg.shouldKeepPlaytime());
copyTask->setName(copyInstDlg.instName());
copyTask->setGroup(copyInstDlg.instGroup());
copyTask->setIcon(copyInstDlg.iconKey());
diff --git a/application/MainWindow.h b/application/MainWindow.h
index a415b5e8..00b8e043 100644
--- a/application/MainWindow.h
+++ b/application/MainWindow.h
@@ -57,6 +57,8 @@ public:
void checkInstancePathForProblems();
void updatesAllowedChanged(bool allowed);
+
+ void droppedURLs(QList<QUrl> urls);
signals:
void isClosing();
@@ -180,8 +182,6 @@ private slots:
*/
void downloadUpdates(GoUpdate::Status status);
- void droppedURLs(QList<QUrl> urls);
-
void konamiTriggered();
void globalSettingsClosed();
diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp
index c95d85be..a8d26498 100644
--- a/application/MultiMC.cpp
+++ b/application/MultiMC.cpp
@@ -15,7 +15,6 @@
#include "pages/global/ExternalToolsPage.h"
#include "pages/global/AccountListPage.h"
#include "pages/global/PasteEEPage.h"
-#include "pages/global/PackagesPage.h"
#include "pages/global/CustomCommandsPage.h"
#include "themes/ITheme.h"
@@ -35,6 +34,7 @@
#include <QNetworkAccessManager>
#include <QTranslator>
#include <QLibraryInfo>
+#include <QList>
#include <QStringList>
#include <QDebug>
#include <QStyleFactory>
@@ -146,6 +146,27 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
startTime = QDateTime::currentDateTime();
+#ifdef Q_OS_LINUX
+ {
+ QFile osrelease("/proc/sys/kernel/osrelease");
+ if (osrelease.open(QFile::ReadOnly | QFile::Text)) {
+ QTextStream in(&osrelease);
+ auto contents = in.readAll();
+ if(
+ contents.contains("WSL", Qt::CaseInsensitive) ||
+ contents.contains("Microsoft", Qt::CaseInsensitive)
+ ) {
+ showFatalErrorMessage(
+ "Unsupported system detected!",
+ "Linux-on-Windows distributions are not supported.\n\n"
+ "Please use the Windows MultiMC binary when playing on Windows."
+ );
+ return;
+ }
+ }
+ }
+#endif
+
// Don't quit on hiding the last window
this->setQuitOnLastWindowClosed(false);
@@ -174,6 +195,10 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
// --alive
parser.addSwitch("alive");
parser.addDocumentation("alive", "Write a small '" + liveCheckFile + "' file after MultiMC starts");
+ // --import
+ parser.addOption("import");
+ parser.addShortOpt("import", 'I');
+ parser.addDocumentation("import", "Import instance from specified zip (local path or URL)");
// parse the arguments
try
@@ -208,6 +233,7 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
}
m_instanceIdToLaunch = args["launch"].toString();
m_liveCheck = args["alive"].toBool();
+ m_zipToImport = args["import"].toUrl();
QString origcwdPath = QDir::currentPath();
QString binPath = applicationDirPath();
@@ -279,13 +305,20 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
connect(m_peerInstance, &LocalPeer::messageReceived, this, &MultiMC::messageReceived);
if(m_peerInstance->isClient())
{
+ int timeout = 2000;
+
if(m_instanceIdToLaunch.isEmpty())
{
- m_peerInstance->sendMessage("activate", 2000);
+ m_peerInstance->sendMessage("activate", timeout);
+
+ if(!m_zipToImport.isEmpty())
+ {
+ m_peerInstance->sendMessage("import " + m_zipToImport.toString(), timeout);
+ }
}
else
{
- m_peerInstance->sendMessage(m_instanceIdToLaunch, 2000);
+ m_peerInstance->sendMessage("launch " + m_instanceIdToLaunch, timeout);
}
m_status = MultiMC::Succeeded;
return;
@@ -527,7 +560,6 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
m_globalSettingsProvider->addPage<LanguagePage>();
m_globalSettingsProvider->addPage<CustomCommandsPage>();
m_globalSettingsProvider->addPage<ProxyPage>();
- // m_globalSettingsProvider->addPage<PackagesPage>();
m_globalSettingsProvider->addPage<ExternalToolsPage>();
m_globalSettingsProvider->addPage<AccountListPage>();
m_globalSettingsProvider->addPage<PasteEEPage>();
@@ -535,7 +567,9 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv)
qDebug() << "<> Settings loaded.";
}
+#ifndef QT_NO_ACCESSIBILITY
QAccessible::installFactory(groupViewAccessibleFactory);
+#endif /* !QT_NO_ACCESSIBILITY */
// load translations
{
@@ -812,6 +846,11 @@ void MultiMC::performMainStartupAction()
showMainWindow(false);
qDebug() << "<> Main window shown.";
}
+ if(!m_zipToImport.isEmpty())
+ {
+ qDebug() << "<> Importing instance from zip:" << m_zipToImport;
+ m_mainWindow->droppedURLs({ m_zipToImport });
+ }
}
void MultiMC::showFatalErrorMessage(const QString& title, const QString& content)
@@ -848,18 +887,41 @@ void MultiMC::messageReceived(const QString& message)
qDebug() << "Received message" << message << "while still initializing. It will be ignored.";
return;
}
- if(message == "activate")
+
+ QString command = message.section(' ', 0, 0);
+
+ if(command == "activate")
{
showMainWindow();
}
- else
+ else if(command == "import")
+ {
+ QString arg = message.section(' ', 1);
+ if(arg.isEmpty())
+ {
+ qWarning() << "Received" << command << "message without a zip path/URL.";
+ return;
+ }
+ m_mainWindow->droppedURLs({ QUrl(arg) });
+ }
+ else if(command == "launch")
{
- auto inst = instances()->getInstanceById(message);
+ QString arg = message.section(' ', 1);
+ if(arg.isEmpty())
+ {
+ qWarning() << "Received" << command << "message without an instance ID.";
+ return;
+ }
+ auto inst = instances()->getInstanceById(arg);
if(inst)
{
launch(inst, true, nullptr);
}
}
+ else
+ {
+ qWarning() << "Received invalid message" << message;
+ }
}
void MultiMC::analyticsSettingChanged(const Setting&, QVariant value)
diff --git a/application/MultiMC.h b/application/MultiMC.h
index d7c727e0..e6588a14 100644
--- a/application/MultiMC.h
+++ b/application/MultiMC.h
@@ -6,6 +6,7 @@
#include <QFlag>
#include <QIcon>
#include <QDateTime>
+#include <QUrl>
#include <updater/GoUpdate.h>
#include <BaseInstance.h>
@@ -221,5 +222,6 @@ private:
public:
QString m_instanceIdToLaunch;
bool m_liveCheck = false;
+ QUrl m_zipToImport;
std::unique_ptr<QFile> logFile;
};
diff --git a/application/dialogs/AboutDialog.cpp b/application/dialogs/AboutDialog.cpp
index ca1dfd94..c4e4ee24 100644
--- a/application/dialogs/AboutDialog.cpp
+++ b/application/dialogs/AboutDialog.cpp
@@ -23,56 +23,44 @@
#include "HoeDown.h"
+namespace {
// Credits
// This is a hack, but I can't think of a better way to do this easily without screwing with QTextDocument...
-static QString getCreditsHtml(QStringList patrons)
+QString getCreditsHtml(QStringList patrons)
{
- QString creditsHtml = QObject::tr(
- "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN' 'http://www.w3.org/TR/REC-html40/strict.dtd'>"
- "<html>"
- ""
- "<head>"
- "<meta name='qrichtext' content='1' />"
- "<style type='text/css'>"
- "p { white-space: pre-wrap; margin-top:2px; margin-bottom:2px; }"
- "</style>"
- "</head>"
- ""
- "<body style=' font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;'>"
- ""
- "<h3>MultiMC Developers</h3>"
- "<p>Andrew Okin &lt;<a href='mailto:forkk@forkk.net'>forkk@forkk.net</a>&gt;</p>"
- "<p>Petr Mrázek &lt;<a href='mailto:peterix@gmail.com'>peterix@gmail.com</a>&gt;</p>"
- "<p>Sky Welch &lt;<a href='mailto:multimc@bunnies.io'>multimc@bunnies.io</a>&gt;</p>"
- "<p>Jan (02JanDal) &lt;<a href='mailto:02jandal@gmail.com'>02jandal@gmail.com</a>&gt;</p>"
- "<p>RoboSky &lt;<a href='https://twitter.com/RoboSky_'>@RoboSky_</a>&gt;</p>"
- ""
- "<h3>With thanks to</h3>"
- "<p>Orochimarufan &lt;<a href='mailto:orochimarufan.x3@gmail.com'>orochimarufan.x3@gmail.com</a>&gt;</p>"
- "<p>TakSuyu &lt;<a href='mailto:taksuyu@gmail.com'>taksuyu@gmail.com</a>&gt;</p>"
- "<p>Kilobyte &lt;<a href='mailto:stiepen22@gmx.de'>stiepen22@gmx.de</a>&gt;</p>"
- "<p>Rootbear75 &lt;<a href='https://twitter.com/rootbear75'>@rootbear75</a>&gt;</p>"
- ""
- "<h3>Patrons</h3>"
- "%1"
- ""
- "</body>"
- "</html>");
- if (patrons.isEmpty())
- return creditsHtml.arg(QObject::tr("<p>Loading...</p>"));
- else
- {
- QString patronsStr;
+ QString patronsHeading = QObject::tr("Patrons", "About Credits");
+ QString output;
+ QTextStream stream(&output);
+ stream << "<center>\n";
+ // TODO: possibly retrieve from git history at build time?
+ stream << "<h3>" << QObject::tr("MultiMC Developers", "About Credits") << "</h3>\n";
+ stream << "<p>Andrew Okin &lt;<a href='mailto:forkk@forkk.net'>forkk@forkk.net</a>&gt;</p>\n";
+ stream << "<p>Petr Mrázek &lt;<a href='mailto:peterix@gmail.com'>peterix@gmail.com</a>&gt;</p>\n";
+ stream << "<p>Sky Welch &lt;<a href='mailto:multimc@bunnies.io'>multimc@bunnies.io</a>&gt;</p>\n";
+ stream << "<p>Jan (02JanDal) &lt;<a href='mailto:02jandal@gmail.com'>02jandal@gmail.com</a>&gt;</p>\n";
+ stream << "<p>RoboSky &lt;<a href='https://twitter.com/RoboSky_'>@RoboSky_</a>&gt;</p>\n";
+ stream << "<br />\n";
+
+ stream << "<h3>" << QObject::tr("With thanks to", "About Credits") << "</h3>\n";
+ stream << "<p>Orochimarufan &lt;<a href='mailto:orochimarufan.x3@gmail.com'>orochimarufan.x3@gmail.com</a>&gt;</p>\n";
+ stream << "<p>TakSuyu &lt;<a href='mailto:taksuyu@gmail.com'>taksuyu@gmail.com</a>&gt;</p>\n";
+ stream << "<p>Kilobyte &lt;<a href='mailto:stiepen22@gmx.de'>stiepen22@gmx.de</a>&gt;</p>\n";
+ stream << "<p>Rootbear75 &lt;<a href='https://twitter.com/rootbear75'>@rootbear75</a>&gt;</p>\n";
+ stream << "<p>Zeker Zhayard &lt;<a href='https://twitter.com/zeker_zhayard'>@Zeker_Zhayard</a>&gt;</p>\n";
+ stream << "<br />\n";
+
+ if(!patrons.isEmpty()) {
+ stream << "<h3>" << QObject::tr("Patrons", "About Credits") << "</h3>\n";
for (QString patron : patrons)
{
- patronsStr.append(QString("<p>%1</p>").arg(patron));
+ stream << "<p>" << patron << "</p>\n";
}
-
- return creditsHtml.arg(patronsStr);
}
+ stream << "</center>\n";
+ return output;
}
-static QString getLicenseHtml()
+QString getLicenseHtml()
{
HoeDown hoedown;
QFile dataFile(":/documents/COPYING.md");
@@ -81,6 +69,8 @@ static QString getLicenseHtml()
return output;
}
+}
+
AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog)
{
ui->setupUi(this);
@@ -109,6 +99,15 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
else
ui->channelLabel->setVisible(false);
+ ui->redistributionText->setHtml(tr(
+"<p>We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.</p>\n"
+"<p>Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. "
+"This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project "
+"icon and the title of windows, (no <b>MultiMC-fork</b> in the title).</p>\n"
+"<p>The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. "
+"However, it should be abundantly clear that the project is a fork <b>without</b> implying that you have our blessing.</p>"
+ ));
+
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
connect(ui->aboutQt, &QPushButton::clicked, &QApplication::aboutQt);
diff --git a/application/dialogs/AboutDialog.ui b/application/dialogs/AboutDialog.ui
index 47ec0293..c4096b32 100644
--- a/application/dialogs/AboutDialog.ui
+++ b/application/dialogs/AboutDialog.ui
@@ -217,16 +217,6 @@
</property>
</widget>
</item>
- <item>
- <widget class="QLineEdit" name="translationInfo">
- <property name="text">
- <string extracomment="Hey, Translator, feel free to put credit to you here">No Language file loaded.</string>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- </widget>
- </item>
</layout>
</widget>
<widget class="QWidget" name="licenseTab">
@@ -263,18 +253,7 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
- <widget class="QTextEdit" name="textEdit">
- <property name="html">
- <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Noto Sans'; font-size:12pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;Part of the reason for using the Apache license is we don't want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork &lt;/span&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;&quot;&gt;without&lt;/span&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt; implying that you have our blessing.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
+ <widget class="QTextEdit" name="redistributionText">
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
@@ -323,14 +302,11 @@ p, li { white-space: pre-wrap; }
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>creditsText</tabstop>
- <tabstop>translationInfo</tabstop>
<tabstop>licenseText</tabstop>
- <tabstop>textEdit</tabstop>
+ <tabstop>redistributionText</tabstop>
<tabstop>aboutQt</tabstop>
<tabstop>closeButton</tabstop>
</tabstops>
- <resources>
- <include location="../../resources/multimc/multimc.qrc"/>
- </resources>
+ <resources/>
<connections/>
</ui>
diff --git a/application/dialogs/CopyInstanceDialog.cpp b/application/dialogs/CopyInstanceDialog.cpp
index 6100860c..ab76e737 100644
--- a/application/dialogs/CopyInstanceDialog.cpp
+++ b/application/dialogs/CopyInstanceDialog.cpp
@@ -53,6 +53,7 @@ CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent)
ui->groupBox->setCurrentIndex(index);
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
ui->copySavesCheckbox->setChecked(m_copySaves);
+ ui->keepPlaytimeCheckbox->setChecked(m_keepPlaytime);
}
CopyInstanceDialog::~CopyInstanceDialog()
@@ -123,3 +124,21 @@ void CopyInstanceDialog::on_copySavesCheckbox_stateChanged(int state)
m_copySaves = true;
}
}
+
+bool CopyInstanceDialog::shouldKeepPlaytime() const
+{
+ return m_keepPlaytime;
+}
+
+
+void CopyInstanceDialog::on_keepPlaytimeCheckbox_stateChanged(int state)
+{
+ if(state == Qt::Unchecked)
+ {
+ m_keepPlaytime = false;
+ }
+ else if(state == Qt::Checked)
+ {
+ m_keepPlaytime = true;
+ }
+}
diff --git a/application/dialogs/CopyInstanceDialog.h b/application/dialogs/CopyInstanceDialog.h
index d46e647c..2b8475b7 100644
--- a/application/dialogs/CopyInstanceDialog.h
+++ b/application/dialogs/CopyInstanceDialog.h
@@ -40,16 +40,19 @@ public:
QString instGroup() const;
QString iconKey() const;
bool shouldCopySaves() const;
+ bool shouldKeepPlaytime() const;
private
slots:
void on_iconButton_clicked();
void on_instNameTextBox_textChanged(const QString &arg1);
void on_copySavesCheckbox_stateChanged(int state);
+ void on_keepPlaytimeCheckbox_stateChanged(int state);
private:
Ui::CopyInstanceDialog *ui;
QString InstIconKey;
InstancePtr m_original;
bool m_copySaves = true;
+ bool m_keepPlaytime = true;
};
diff --git a/application/dialogs/CopyInstanceDialog.ui b/application/dialogs/CopyInstanceDialog.ui
index bbb1bbb3..fa675455 100644
--- a/application/dialogs/CopyInstanceDialog.ui
+++ b/application/dialogs/CopyInstanceDialog.ui
@@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>345</width>
- <height>240</height>
+ <height>323</height>
</rect>
</property>
<property name="windowTitle">
@@ -117,6 +117,13 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="keepPlaytimeCheckbox">
+ <property name="text">
+ <string>Keep play time</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -128,6 +135,13 @@
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>iconButton</tabstop>
+ <tabstop>instNameTextBox</tabstop>
+ <tabstop>groupBox</tabstop>
+ <tabstop>copySavesCheckbox</tabstop>
+ <tabstop>keepPlaytimeCheckbox</tabstop>
+ </tabstops>
<resources>
<include location="../../graphics.qrc"/>
</resources>
diff --git a/application/dialogs/EditAccountDialog.ui b/application/dialogs/EditAccountDialog.ui
index 85e235ce..e87509bc 100644
--- a/application/dialogs/EditAccountDialog.ui
+++ b/application/dialogs/EditAccountDialog.ui
@@ -30,7 +30,7 @@
<item>
<widget class="QLineEdit" name="userTextBox">
<property name="placeholderText">
- <string>Email / Username</string>
+ <string>Email</string>
</property>
</widget>
</item>
diff --git a/application/dialogs/LoginDialog.ui b/application/dialogs/LoginDialog.ui
index 99b98215..d92fbae3 100644
--- a/application/dialogs/LoginDialog.ui
+++ b/application/dialogs/LoginDialog.ui
@@ -36,7 +36,7 @@
<item>
<widget class="QLineEdit" name="userTextBox">
<property name="placeholderText">
- <string>Email / Username</string>
+ <string>Email</string>
</property>
</widget>
</item>
diff --git a/application/dialogs/NewInstanceDialog.cpp b/application/dialogs/NewInstanceDialog.cpp
index 3533763d..511f991e 100644
--- a/application/dialogs/NewInstanceDialog.cpp
+++ b/application/dialogs/NewInstanceDialog.cpp
@@ -34,11 +34,9 @@
#include "widgets/PageContainer.h"
#include <pages/modplatform/VanillaPage.h>
-#include <pages/modplatform/FTBPage.h>
-#include <pages/modplatform/TwitchPage.h>
+#include <pages/modplatform/legacy_ftb/Page.h>
+#include <pages/modplatform/twitch/TwitchPage.h>
#include <pages/modplatform/ImportPage.h>
-#include <pages/modplatform/TechnicPage.h>
-
NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString & url, QWidget *parent)
@@ -97,14 +95,8 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
if(!url.isEmpty())
{
QUrl actualUrl(url);
- if(actualUrl.host() == "www.curseforge.com") {
- m_container->selectPage("twitch");
- twitchPage->setUrl(url);
- }
- else {
- m_container->selectPage("import");
- importPage->setUrl(url);
- }
+ m_container->selectPage("import");
+ importPage->setUrl(url);
}
updateDialogState();
@@ -133,8 +125,8 @@ QList<BasePage *> NewInstanceDialog::getPages()
{
new VanillaPage(this),
importPage,
- twitchPage,
- new FTBPage(this)
+ new LegacyFTB::Page(this),
+ twitchPage
};
}
diff --git a/application/groupview/AccessibleGroupView.cpp b/application/groupview/AccessibleGroupView.cpp
index 9a1bb821..c6541f18 100644
--- a/application/groupview/AccessibleGroupView.cpp
+++ b/application/groupview/AccessibleGroupView.cpp
@@ -6,6 +6,8 @@
#include <qaccessible.h>
#include <qheaderview.h>
+#ifndef QT_NO_ACCESSIBILITY
+
QAccessibleInterface *groupViewAccessibleFactory(const QString &classname, QObject *object)
{
QAccessibleInterface *iface = 0;
@@ -772,3 +774,5 @@ QAccessibleInterface *AccessibleGroupViewItem::child(int) const
{
return 0;
}
+
+#endif /* !QT_NO_ACCESSIBILITY */
diff --git a/application/groupview/AccessibleGroupView_p.h b/application/groupview/AccessibleGroupView_p.h
index cdec1c0a..e74da3be 100644
--- a/application/groupview/AccessibleGroupView_p.h
+++ b/application/groupview/AccessibleGroupView_p.h
@@ -1,10 +1,11 @@
#pragma once
-#include "GroupView.h"
#include "QtCore/qpointer.h"
#include <QtGui/qaccessible.h>
#include <QAccessibleWidget>
#include <QAbstractItemView>
+#ifndef QT_NO_ACCESSIBILITY
+#include "GroupView.h"
// #include <QHeaderView>
class QAccessibleTableCell;
@@ -114,3 +115,4 @@ private:
friend class AccessibleGroupView;
};
+#endif /* !QT_NO_ACCESSIBILITY */
diff --git a/application/groupview/GroupView.cpp b/application/groupview/GroupView.cpp
index ff0daee4..a1a28532 100644
--- a/application/groupview/GroupView.cpp
+++ b/application/groupview/GroupView.cpp
@@ -93,11 +93,13 @@ void GroupView::currentChanged(const QModelIndex& current, const QModelIndex& pr
{
QAbstractItemView::currentChanged(current, previous);
// TODO: for accessibility support, implement+register a factory, steal QAccessibleTable from Qt and return an instance of it for GroupView.
+#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive() && current.isValid()) {
QAccessibleEvent event(this, QAccessible::Focus);
event.setChild(current.row());
QAccessible::updateAccessibility(&event);
}
+#endif /* !QT_NO_ACCESSIBILITY */
}
@@ -392,6 +394,8 @@ void GroupView::mouseReleaseEvent(QMouseEvent *event)
updateGeometries();
viewport()->update();
event->accept();
+ m_pressedCategory = nullptr;
+ setState(NoState);
return;
}
else if (state() == CollapsingState)
@@ -402,6 +406,8 @@ void GroupView::mouseReleaseEvent(QMouseEvent *event)
updateGeometries();
viewport()->update();
event->accept();
+ m_pressedCategory = nullptr;
+ setState(NoState);
return;
}
}
diff --git a/application/main.cpp b/application/main.cpp
index c871bf1b..b0360c7e 100644
--- a/application/main.cpp
+++ b/application/main.cpp
@@ -43,7 +43,6 @@ int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(multimc);
Q_INIT_RESOURCE(backgrounds);
- Q_INIT_RESOURCE(assets);
Q_INIT_RESOURCE(pe_dark);
Q_INIT_RESOURCE(pe_light);
diff --git a/application/package/linux/multimc.desktop b/application/package/linux/multimc.desktop
index 770f24f1..c25be047 100755
--- a/application/package/linux/multimc.desktop
+++ b/application/package/linux/multimc.desktop
@@ -1,7 +1,7 @@
[Desktop Entry]
Version=1.0
Name=MultiMC
-GenericName=MultiMC
+GenericName=Minecraft Launcher
Comment=Free, open source launcher and instance manager for Minecraft.
Type=Application
Terminal=false
diff --git a/application/package/ubuntu/multimc/DEBIAN/control b/application/package/ubuntu/multimc/DEBIAN/control
index 34c223a5..9386e945 100644
--- a/application/package/ubuntu/multimc/DEBIAN/control
+++ b/application/package/ubuntu/multimc/DEBIAN/control
@@ -1,11 +1,11 @@
Package: multimc
-Version: 1.3-1
+Version: 1.4-1
Architecture: all
Maintainer: Petr Mrázek <peterix@gmail.com>
Section: games
Priority: optional
Installed-Size: 75
-Depends: zenity, desktop-file-utils, qt5-default
+Depends: zenity, desktop-file-utils, qt5-default, wget
Recommends: openjdk-8-jre
Homepage: http://multimc.org
Description: A local install wrapper for MultiMC
diff --git a/application/pages/global/AccountListPage.cpp b/application/pages/global/AccountListPage.cpp
index c14134f3..0453ae00 100644
--- a/application/pages/global/AccountListPage.cpp
+++ b/application/pages/global/AccountListPage.cpp
@@ -103,8 +103,7 @@ void AccountListPage::listChanged()
void AccountListPage::on_actionAdd_triggered()
{
- addAccount(tr("Please enter your Mojang or Minecraft account username and password to add "
- "your account."));
+ addAccount(tr("Please enter your Minecraft account email and password to add your account."));
}
void AccountListPage::on_actionRemove_triggered()
diff --git a/application/pages/global/PackagesPage.cpp b/application/pages/global/PackagesPage.cpp
deleted file mode 100644
index 1bbbed7a..00000000
--- a/application/pages/global/PackagesPage.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/* Copyright 2015-2019 MultiMC Contributors
- *
- * 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 "PackagesPage.h"
-#include "ui_PackagesPage.h"
-
-#include <QDateTime>
-#include <QSortFilterProxyModel>
-#include <QRegularExpression>
-
-#include "dialogs/ProgressDialog.h"
-#include "VersionProxyModel.h"
-
-#include "meta/Index.h"
-#include "meta/VersionList.h"
-#include "meta/Version.h"
-#include "Env.h"
-#include "MultiMC.h"
-
-using namespace Meta;
-
-static QString formatRequires(const VersionPtr &version)
-{
- QStringList lines;
- auto & reqs = version->requires();
- auto iter = reqs.begin();
- while (iter != reqs.end())
- {
- auto &uid = iter->uid;
- auto &version = iter->equalsVersion;
- const QString readable = ENV.metadataIndex()->hasUid(uid) ? ENV.metadataIndex()->get(uid)->humanReadable() : uid;
- if(!version.isEmpty())
- {
- lines.append(QString("%1 (%2)").arg(readable, version));
- }
- else
- {
- lines.append(QString("%1").arg(readable));
- }
- iter++;
- }
- return lines.join('\n');
-}
-
-PackagesPage::PackagesPage(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::PackagesPage)
-{
- ui->setupUi(this);
- ui->tabWidget->tabBar()->hide();
-
- m_fileProxy = new QSortFilterProxyModel(this);
- m_fileProxy->setSortRole(Qt::DisplayRole);
- m_fileProxy->setSortCaseSensitivity(Qt::CaseInsensitive);
- m_fileProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
- m_fileProxy->setFilterRole(Qt::DisplayRole);
- m_fileProxy->setFilterKeyColumn(0);
- m_fileProxy->sort(0);
- m_fileProxy->setSourceModel(ENV.metadataIndex().get());
- ui->indexView->setModel(m_fileProxy);
-
- m_filterProxy = new QSortFilterProxyModel(this);
- m_filterProxy->setSortRole(VersionList::SortRole);
- m_filterProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
- m_filterProxy->setFilterRole(Qt::DisplayRole);
- m_filterProxy->setFilterKeyColumn(0);
- m_filterProxy->sort(0, Qt::DescendingOrder);
- ui->versionsView->setModel(m_filterProxy);
-
- m_versionProxy = new VersionProxyModel(this);
- m_filterProxy->setSourceModel(m_versionProxy);
-
- connect(ui->indexView->selectionModel(), &QItemSelectionModel::currentChanged, this, &PackagesPage::updateCurrentVersionList);
- connect(ui->versionsView->selectionModel(), &QItemSelectionModel::currentChanged, this, &PackagesPage::updateVersion);
- connect(m_filterProxy, &QSortFilterProxyModel::dataChanged, this, &PackagesPage::versionListDataChanged);
-
- updateCurrentVersionList(QModelIndex());
- updateVersion();
-}
-
-PackagesPage::~PackagesPage()
-{
- delete ui;
-}
-
-QIcon PackagesPage::icon() const
-{
- return MMC->getThemedIcon("packages");
-}
-
-void PackagesPage::on_refreshIndexBtn_clicked()
-{
- ENV.metadataIndex()->load(Net::Mode::Online);
-}
-void PackagesPage::on_refreshFileBtn_clicked()
-{
- VersionListPtr list = ui->indexView->currentIndex().data(Index::ListPtrRole).value<VersionListPtr>();
- if (!list)
- {
- return;
- }
- list->load(Net::Mode::Online);
-}
-void PackagesPage::on_refreshVersionBtn_clicked()
-{
- VersionPtr version = ui->versionsView->currentIndex().data(VersionList::VersionPtrRole).value<VersionPtr>();
- if (!version)
- {
- return;
- }
- version->load(Net::Mode::Online);
-}
-
-void PackagesPage::on_fileSearchEdit_textChanged(const QString &search)
-{
- if (search.isEmpty())
- {
- m_fileProxy->setFilterFixedString(QString());
- }
- else
- {
- QStringList parts = search.split(' ');
- std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape);
- m_fileProxy->setFilterRegExp(".*" + parts.join(".*") + ".*");
- }
-}
-void PackagesPage::on_versionSearchEdit_textChanged(const QString &search)
-{
- if (search.isEmpty())
- {
- m_filterProxy->setFilterFixedString(QString());
- }
- else
- {
- QStringList parts = search.split(' ');
- std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape);
- m_filterProxy->setFilterRegExp(".*" + parts.join(".*") + ".*");
- }
-}
-
-void PackagesPage::updateCurrentVersionList(const QModelIndex &index)
-{
- if (index.isValid())
- {
- VersionListPtr list = index.data(Index::ListPtrRole).value<VersionListPtr>();
- ui->versionsBox->setEnabled(true);
- ui->refreshFileBtn->setEnabled(true);
- ui->fileUidLabel->setEnabled(true);
- ui->fileUid->setText(list->uid());
- ui->fileNameLabel->setEnabled(true);
- ui->fileName->setText(list->name());
- m_versionProxy->setSourceModel(list.get());
- ui->refreshFileBtn->setText(tr("Refresh %1").arg(list->humanReadable()));
- list->load(Net::Mode::Offline);
- }
- else
- {
- ui->versionsBox->setEnabled(false);
- ui->refreshFileBtn->setEnabled(false);
- ui->fileUidLabel->setEnabled(false);
- ui->fileUid->clear();
- ui->fileNameLabel->setEnabled(false);
- ui->fileName->clear();
- m_versionProxy->setSourceModel(nullptr);
- ui->refreshFileBtn->setText(tr("Refresh"));
- }
-}
-
-void PackagesPage::versionListDataChanged(const QModelIndex &tl, const QModelIndex &br)
-{
- if (QItemSelection(tl, br).contains(ui->versionsView->currentIndex()))
- {
- updateVersion();
- }
-}
-
-void PackagesPage::updateVersion()
-{
- VersionPtr version = std::dynamic_pointer_cast<Version>(
- ui->versionsView->currentIndex().data(VersionList::VersionPointerRole).value<BaseVersionPtr>());
- if (version)
- {
- ui->refreshVersionBtn->setEnabled(true);
- ui->versionVersionLabel->setEnabled(true);
- ui->versionVersion->setText(version->version());
- ui->versionTimeLabel->setEnabled(true);
- ui->versionTime->setText(version->time().toString("yyyy-MM-dd HH:mm"));
- ui->versionTypeLabel->setEnabled(true);
- ui->versionType->setText(version->type());
- ui->versionRequiresLabel->setEnabled(true);
- ui->versionRequires->setText(formatRequires(version));
- ui->refreshVersionBtn->setText(tr("Refresh %1").arg(version->version()));
- }
- else
- {
- ui->refreshVersionBtn->setEnabled(false);
- ui->versionVersionLabel->setEnabled(false);
- ui->versionVersion->clear();
- ui->versionTimeLabel->setEnabled(false);
- ui->versionTime->clear();
- ui->versionTypeLabel->setEnabled(false);
- ui->versionType->clear();
- ui->versionRequiresLabel->setEnabled(false);
- ui->versionRequires->clear();
- ui->refreshVersionBtn->setText(tr("Refresh"));
- }
-}
-
-void PackagesPage::openedImpl()
-{
- ENV.metadataIndex()->load(Net::Mode::Offline);
-}
diff --git a/application/pages/global/PackagesPage.h b/application/pages/global/PackagesPage.h
deleted file mode 100644
index 872961a5..00000000
--- a/application/pages/global/PackagesPage.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Copyright 2015-2019 MultiMC Contributors
- *
- * 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 <QWidget>
-
-#include "pages/BasePage.h"
-
-namespace Ui {
-class PackagesPage;
-}
-
-class QSortFilterProxyModel;
-class VersionProxyModel;
-
-class PackagesPage : public QWidget, public BasePage
-{
- Q_OBJECT
-public:
- explicit PackagesPage(QWidget *parent = 0);
- ~PackagesPage();
-
- QString id() const override { return "packages-global"; }
- QString displayName() const override { return tr("Packages"); }
- QIcon icon() const override;
- void openedImpl() override;
-
-private slots:
- void on_refreshIndexBtn_clicked();
- void on_refreshFileBtn_clicked();
- void on_refreshVersionBtn_clicked();
- void on_fileSearchEdit_textChanged(const QString &search);
- void on_versionSearchEdit_textChanged(const QString &search);
- void updateCurrentVersionList(const QModelIndex &index);
- void versionListDataChanged(const QModelIndex &tl, const QModelIndex &br);
-
-private:
- Ui::PackagesPage *ui;
- QSortFilterProxyModel *m_fileProxy;
- QSortFilterProxyModel *m_filterProxy;
- VersionProxyModel *m_versionProxy;
-
- void updateVersion();
-};
diff --git a/application/pages/global/PackagesPage.ui b/application/pages/global/PackagesPage.ui
deleted file mode 100644
index 158bf1b4..00000000
--- a/application/pages/global/PackagesPage.ui
+++ /dev/null
@@ -1,252 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>PackagesPage</class>
- <widget class="QWidget" name="PackagesPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>636</width>
- <height>621</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QTabWidget" name="tabWidget">
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="tab">
- <attribute name="title">
- <string>Tab 1</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="2">
- <widget class="QGroupBox" name="versionsBox">
- <property name="title">
- <string>Versions</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QLineEdit" name="versionSearchEdit">
- <property name="placeholderText">
- <string>Search...</string>
- </property>
- <property name="clearButtonEnabled">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTreeView" name="versionsView">
- <property name="alternatingRowColors">
- <bool>true</bool>
- </property>
- <attribute name="headerVisible">
- <bool>false</bool>
- </attribute>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
- <widget class="QPushButton" name="refreshVersionBtn">
- <property name="text">
- <string>Refresh</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QFormLayout" name="formLayout_2">
- <item row="0" column="0">
- <widget class="QLabel" name="versionVersionLabel">
- <property name="text">
- <string>Version:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="versionVersion">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="versionTimeLabel">
- <property name="text">
- <string>Time:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="versionTime">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="versionTypeLabel">
- <property name="text">
- <string>Type:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="versionType">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="versionRequiresLabel">
- <property name="text">
- <string>Dependencies:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLabel" name="versionRequires">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QGroupBox" name="versionListsBox">
- <property name="title">
- <string>Resources</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QLineEdit" name="fileSearchEdit">
- <property name="placeholderText">
- <string>Search...</string>
- </property>
- <property name="clearButtonEnabled">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTreeView" name="indexView">
- <property name="alternatingRowColors">
- <bool>true</bool>
- </property>
- <attribute name="headerVisible">
- <bool>false</bool>
- </attribute>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QPushButton" name="refreshFileBtn">
- <property name="text">
- <string>Refresh</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="fileUidLabel">
- <property name="text">
- <string>UID:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="fileUid">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="fileNameLabel">
- <property name="text">
- <string>Name:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="fileName">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- </item>
- <item row="0" column="1" colspan="2">
- <widget class="QPushButton" name="refreshIndexBtn">
- <property name="text">
- <string>Refresh Index</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/application/pages/global/ProxyPage.cpp b/application/pages/global/ProxyPage.cpp
index ee56a54e..3f0e766b 100644
--- a/application/pages/global/ProxyPage.cpp
+++ b/application/pages/global/ProxyPage.cpp
@@ -95,7 +95,7 @@ void ProxyPage::loadSettings()
ui->proxyHTTPBtn->setChecked(true);
ui->proxyAddrEdit->setText(s->get("ProxyAddr").toString());
- ui->proxyPortEdit->setValue(s->get("ProxyPort").value<qint16>());
+ ui->proxyPortEdit->setValue(s->get("ProxyPort").value<uint16_t>());
ui->proxyUserEdit->setText(s->get("ProxyUser").toString());
ui->proxyPassEdit->setText(s->get("ProxyPass").toString());
}
diff --git a/application/pages/instance/ModFolderPage.cpp b/application/pages/instance/ModFolderPage.cpp
index d449f8bf..ec4bf3c9 100644
--- a/application/pages/instance/ModFolderPage.cpp
+++ b/application/pages/instance/ModFolderPage.cpp
@@ -51,6 +51,26 @@ public:
}
protected:
+ bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const override {
+ ModFolderModel *model = qobject_cast<ModFolderModel *>(sourceModel());
+ if(!model) {
+ return false;
+ }
+ const auto &mod = model->at(source_row);
+ if(mod.name().contains(filterRegExp())) {
+ return true;
+ }
+ if(mod.description().contains(filterRegExp())) {
+ return true;
+ }
+ for(auto & author: mod.authors()) {
+ if (author.contains(filterRegExp())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
bool lessThan(const QModelIndex & source_left, const QModelIndex & source_right) const override
{
ModFolderModel *model = qobject_cast<ModFolderModel *>(sourceModel());
diff --git a/application/pages/instance/VersionPage.cpp b/application/pages/instance/VersionPage.cpp
index 8ca55934..c7a8dc30 100644
--- a/application/pages/instance/VersionPage.cpp
+++ b/application/pages/instance/VersionPage.cpp
@@ -43,6 +43,7 @@
#include "icons/IconList.h"
#include "Exception.h"
#include "Version.h"
+#include "DesktopServices.h"
#include <meta/Index.h>
#include <meta/VersionList.h>
@@ -60,7 +61,7 @@ public:
virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const override
{
- QVariant var = QIdentityProxyModel::data(mapToSource(proxyIndex), role);
+ QVariant var = QIdentityProxyModel::data(proxyIndex, role);
int column = proxyIndex.column();
if(column == 0 && role == Qt::DecorationRole && m_parentWidget)
{
@@ -205,7 +206,7 @@ void VersionPage::updateVersionControls()
bool newCraft = controlsEnabled && (minecraftVersion >= Version("1.14"));
bool oldCraft = controlsEnabled && (minecraftVersion <= Version("1.12.2"));
ui->actionInstall_Fabric->setEnabled(newCraft);
- ui->actionInstall_Forge->setEnabled(oldCraft);
+ ui->actionInstall_Forge->setEnabled(true);
ui->actionInstall_LiteLoader->setEnabled(oldCraft);
ui->actionReload->setEnabled(true);
updateButtons();
@@ -507,6 +508,16 @@ void VersionPage::on_actionInstall_LiteLoader_triggered()
}
}
+void VersionPage::on_actionLibrariesFolder_triggered()
+{
+ DesktopServices::openDirectory(m_inst->getLocalLibraryPath(), true);
+}
+
+void VersionPage::on_actionMinecraftFolder_triggered()
+{
+ DesktopServices::openDirectory(m_inst->gameRoot(), true);
+}
+
void VersionPage::versionCurrent(const QModelIndex &current, const QModelIndex &previous)
{
currentIdx = current.row();
diff --git a/application/pages/instance/VersionPage.h b/application/pages/instance/VersionPage.h
index 5ffd32f5..769fe997 100644
--- a/application/pages/instance/VersionPage.h
+++ b/application/pages/instance/VersionPage.h
@@ -66,6 +66,9 @@ private slots:
void on_actionCustomize_triggered();
void on_actionDownload_All_triggered();
+ void on_actionMinecraftFolder_triggered();
+ void on_actionLibrariesFolder_triggered();
+
void updateVersionControls();
private:
diff --git a/application/pages/instance/VersionPage.ui b/application/pages/instance/VersionPage.ui
index 32111aa5..718ad067 100644
--- a/application/pages/instance/VersionPage.ui
+++ b/application/pages/instance/VersionPage.ui
@@ -95,6 +95,10 @@
<addaction name="actionAdd_to_Minecraft_jar"/>
<addaction name="actionReplace_Minecraft_jar"/>
<addaction name="actionAdd_Empty"/>
+ <addaction name="separator"/>
+ <addaction name="actionMinecraftFolder"/>
+ <addaction name="actionLibrariesFolder"/>
+ <addaction name="separator"/>
<addaction name="actionReload"/>
<addaction name="actionDownload_All"/>
</widget>
@@ -223,6 +227,22 @@
<string>Download the files needed to launch the instance now.</string>
</property>
</action>
+ <action name="actionMinecraftFolder">
+ <property name="text">
+ <string>Open .minecraft</string>
+ </property>
+ <property name="toolTip">
+ <string>Open the instance's .minecraft folder.</string>
+ </property>
+ </action>
+ <action name="actionLibrariesFolder">
+ <property name="text">
+ <string>Open libraries</string>
+ </property>
+ <property name="toolTip">
+ <string>Open the instance's local libraries folder.</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>
diff --git a/application/pages/modplatform/TechnicPage.cpp b/application/pages/modplatform/TechnicPage.cpp
deleted file mode 100644
index 2f95bec8..00000000
--- a/application/pages/modplatform/TechnicPage.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "TechnicPage.h"
-#include "ui_TechnicPage.h"
-
-#include "MultiMC.h"
-#include "dialogs/NewInstanceDialog.h"
-
-TechnicPage::TechnicPage(NewInstanceDialog* dialog, QWidget *parent)
- : QWidget(parent), ui(new Ui::TechnicPage), dialog(dialog)
-{
- ui->setupUi(this);
-}
-
-TechnicPage::~TechnicPage()
-{
- delete ui;
-}
-
-bool TechnicPage::shouldDisplay() const
-{
- return true;
-}
-
-void TechnicPage::openedImpl()
-{
- dialog->setSuggestedPack();
-}
diff --git a/application/pages/modplatform/TechnicPage.h b/application/pages/modplatform/TechnicPage.h
deleted file mode 100644
index cc82ddf3..00000000
--- a/application/pages/modplatform/TechnicPage.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright 2013-2019 MultiMC Contributors
- *
- * 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 <QWidget>
-
-#include "pages/BasePage.h"
-#include <MultiMC.h>
-#include "tasks/Task.h"
-
-namespace Ui
-{
-class TechnicPage;
-}
-
-class NewInstanceDialog;
-
-class TechnicPage : public QWidget, public BasePage
-{
- Q_OBJECT
-
-public:
- explicit TechnicPage(NewInstanceDialog* dialog, QWidget *parent = 0);
- virtual ~TechnicPage();
- virtual QString displayName() const override
- {
- return tr("Technic");
- }
- virtual QIcon icon() const override
- {
- return MMC->getThemedIcon("technic");
- }
- virtual QString id() const override
- {
- return "technic";
- }
- virtual QString helpPage() const override
- {
- return "Technic-platform";
- }
- virtual bool shouldDisplay() const override;
-
- void openedImpl() override;
-
-private:
- Ui::TechnicPage *ui = nullptr;
- NewInstanceDialog* dialog = nullptr;
-};
diff --git a/application/pages/modplatform/TechnicPage.ui b/application/pages/modplatform/TechnicPage.ui
deleted file mode 100644
index 702427b5..00000000
--- a/application/pages/modplatform/TechnicPage.ui
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>TechnicPage</class>
- <widget class="QWidget" name="TechnicPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>546</width>
- <height>405</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_5">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QLabel" name="label">
- <property name="font">
- <font>
- <pointsize>40</pointsize>
- </font>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#ffc000</string>
- </property>
- <property name="text">
- <string notr="true">UNDER</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../resources/assets/assets.qrc">:/assets/underconstruction</pixmap>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_2">
- <property name="font">
- <font>
- <pointsize>40</pointsize>
- </font>
- </property>
- <property name="styleSheet">
- <string notr="true">color:#7ca32b</string>
- </property>
- <property name="text">
- <string notr="true">CONSTRUCTION</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <resources>
- <include location="../../resources/assets/assets.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/application/pages/modplatform/TwitchPage.cpp b/application/pages/modplatform/TwitchPage.cpp
deleted file mode 100644
index ea0f9267..00000000
--- a/application/pages/modplatform/TwitchPage.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "TwitchPage.h"
-#include "ui_TwitchPage.h"
-
-#include "MultiMC.h"
-#include "dialogs/NewInstanceDialog.h"
-#include <InstanceImportTask.h>
-
-TwitchPage::TwitchPage(NewInstanceDialog* dialog, QWidget *parent)
- : QWidget(parent), ui(new Ui::TwitchPage), dialog(dialog)
-{
- ui->setupUi(this);
- connect(ui->checkButton, &QPushButton::clicked, this, &TwitchPage::triggerCheck);
-}
-
-TwitchPage::~TwitchPage()
-{
- delete ui;
-}
-
-bool TwitchPage::shouldDisplay() const
-{
- return true;
-}
-
-void TwitchPage::openedImpl()
-{
- dialog->setSuggestedPack();
-}
-
-void TwitchPage::triggerCheck(bool)
-{
- if(m_modIdResolver) {
- return;
- }
- auto task = new Flame::UrlResolvingTask(ui->lineEdit->text());
- connect(task, &Task::finished, this, &TwitchPage::checkDone);
- m_modIdResolver.reset(task);
- task->start();
-}
-
-void TwitchPage::setUrl(const QString& url)
-{
- ui->lineEdit->setText(url);
- triggerCheck(true);
-}
-
-void TwitchPage::checkDone()
-{
- auto result = m_modIdResolver->getResults();
- auto formatted = QString("Project %1, File %2").arg(result.projectId).arg(result.fileId);
- if(result.resolved && result.type == Flame::File::Type::Modpack) {
- ui->twitchLabel->setText(formatted);
- QFileInfo fi(result.fileName);
- dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(result.url));
- } else {
- ui->twitchLabel->setPixmap(QPixmap(QString::fromUtf8(":/assets/deadglitch")));
- dialog->setSuggestedPack();
- }
- m_modIdResolver.reset();
-}
diff --git a/application/pages/modplatform/TwitchPage.ui b/application/pages/modplatform/TwitchPage.ui
deleted file mode 100644
index 0db2484d..00000000
--- a/application/pages/modplatform/TwitchPage.ui
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>TwitchPage</class>
- <widget class="QWidget" name="TwitchPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>546</width>
- <height>405</height>
- </rect>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="1">
- <widget class="QLineEdit" name="lineEdit"/>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Twitch URL:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0" colspan="3">
- <widget class="QLabel" name="twitchLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="font">
- <font>
- <pointsize>40</pointsize>
- </font>
- </property>
- <property name="pixmap">
- <pixmap resource="../../resources/assets/assets.qrc">:/assets/deadglitch</pixmap>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QPushButton" name="checkButton">
- <property name="text">
- <string>Check</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <tabstops>
- <tabstop>lineEdit</tabstop>
- <tabstop>checkButton</tabstop>
- </tabstops>
- <resources>
- <include location="../../resources/assets/assets.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/application/pages/modplatform/FtbListModel.cpp b/application/pages/modplatform/legacy_ftb/ListModel.cpp
index 51aec890..105db25a 100644
--- a/application/pages/modplatform/FtbListModel.cpp
+++ b/application/pages/modplatform/legacy_ftb/ListModel.cpp
@@ -1,4 +1,4 @@
-#include "FtbListModel.h"
+#include "ListModel.h"
#include "MultiMC.h"
#include <MMCStrings.h>
@@ -12,17 +12,19 @@
#include "net/URLConstants.h"
-FtbFilterModel::FtbFilterModel(QObject *parent) : QSortFilterProxyModel(parent)
+namespace LegacyFTB {
+
+FilterModel::FilterModel(QObject *parent) : QSortFilterProxyModel(parent)
{
currentSorting = Sorting::ByGameVersion;
sortings.insert(tr("Sort by name"), Sorting::ByName);
sortings.insert(tr("Sort by game version"), Sorting::ByGameVersion);
}
-bool FtbFilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
+bool FilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
- FtbModpack leftPack = sourceModel()->data(left, Qt::UserRole).value<FtbModpack>();
- FtbModpack rightPack = sourceModel()->data(right, Qt::UserRole).value<FtbModpack>();
+ Modpack leftPack = sourceModel()->data(left, Qt::UserRole).value<Modpack>();
+ Modpack rightPack = sourceModel()->data(right, Qt::UserRole).value<Modpack>();
if(currentSorting == Sorting::ByGameVersion) {
Version lv(leftPack.mcVersion);
@@ -38,66 +40,66 @@ bool FtbFilterModel::lessThan(const QModelIndex &left, const QModelIndex &right)
return true;
}
-bool FtbFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+bool FilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
return true;
}
-const QMap<QString, FtbFilterModel::Sorting> FtbFilterModel::getAvailableSortings()
+const QMap<QString, FilterModel::Sorting> FilterModel::getAvailableSortings()
{
return sortings;
}
-QString FtbFilterModel::translateCurrentSorting()
+QString FilterModel::translateCurrentSorting()
{
return sortings.key(currentSorting);
}
-void FtbFilterModel::setSorting(Sorting s)
+void FilterModel::setSorting(Sorting s)
{
currentSorting = s;
invalidate();
}
-FtbFilterModel::Sorting FtbFilterModel::getCurrentSorting()
+FilterModel::Sorting FilterModel::getCurrentSorting()
{
return currentSorting;
}
-FtbListModel::FtbListModel(QObject *parent) : QAbstractListModel(parent)
+ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
{
}
-FtbListModel::~FtbListModel()
+ListModel::~ListModel()
{
}
-QString FtbListModel::translatePackType(FtbPackType type) const
+QString ListModel::translatePackType(PackType type) const
{
switch(type)
{
- case FtbPackType::Public:
+ case PackType::Public:
return tr("Public Modpack");
- case FtbPackType::ThirdParty:
+ case PackType::ThirdParty:
return tr("Third Party Modpack");
- case FtbPackType::Private:
+ case PackType::Private:
return tr("Private Modpack");
}
qWarning() << "Unknown FTB modpack type:" << int(type);
return QString();
}
-int FtbListModel::rowCount(const QModelIndex &parent) const
+int ListModel::rowCount(const QModelIndex &parent) const
{
return modpacks.size();
}
-int FtbListModel::columnCount(const QModelIndex &parent) const
+int ListModel::columnCount(const QModelIndex &parent) const
{
return 1;
}
-QVariant FtbListModel::data(const QModelIndex &index, int role) const
+QVariant ListModel::data(const QModelIndex &index, int role) const
{
int pos = index.row();
if(pos >= modpacks.size() || pos < 0 || !index.isValid())
@@ -105,7 +107,7 @@ QVariant FtbListModel::data(const QModelIndex &index, int role) const
return QString("INVALID INDEX %1").arg(pos);
}
- FtbModpack pack = modpacks.at(pos);
+ Modpack pack = modpacks.at(pos);
if(role == Qt::DisplayRole)
{
return pack.name + "\n" + translatePackType(pack.type);
@@ -129,7 +131,7 @@ QVariant FtbListModel::data(const QModelIndex &index, int role) const
return (m_logoMap.value(pack.logo));
}
QIcon icon = MMC->getThemedIcon("screenshot-placeholder");
- ((FtbListModel *)this)->requestLogo(pack.logo);
+ ((ListModel *)this)->requestLogo(pack.logo);
return icon;
}
else if(role == Qt::TextColorRole)
@@ -156,33 +158,33 @@ QVariant FtbListModel::data(const QModelIndex &index, int role) const
return QVariant();
}
-void FtbListModel::fill(FtbModpackList modpacks)
+void ListModel::fill(ModpackList modpacks)
{
beginResetModel();
this->modpacks = modpacks;
endResetModel();
}
-void FtbListModel::addPack(FtbModpack modpack)
+void ListModel::addPack(Modpack modpack)
{
beginResetModel();
this->modpacks.append(modpack);
endResetModel();
}
-void FtbListModel::clear()
+void ListModel::clear()
{
beginResetModel();
modpacks.clear();
endResetModel();
}
-FtbModpack FtbListModel::at(int row)
+Modpack ListModel::at(int row)
{
return modpacks.at(row);
}
-void FtbListModel::remove(int row)
+void ListModel::remove(int row)
{
if(row < 0 || row >= modpacks.size())
{
@@ -194,20 +196,20 @@ void FtbListModel::remove(int row)
endRemoveRows();
}
-void FtbListModel::logoLoaded(QString logo, QIcon out)
+void ListModel::logoLoaded(QString logo, QIcon out)
{
m_loadingLogos.removeAll(logo);
m_logoMap.insert(logo, out);
emit dataChanged(createIndex(0, 0), createIndex(1, 0));
}
-void FtbListModel::logoFailed(QString logo)
+void ListModel::logoFailed(QString logo)
{
m_failedLogos.append(logo);
m_loadingLogos.removeAll(logo);
}
-void FtbListModel::requestLogo(QString file)
+void ListModel::requestLogo(QString file)
{
if(m_loadingLogos.contains(file) || m_failedLogos.contains(file))
{
@@ -216,7 +218,7 @@ void FtbListModel::requestLogo(QString file)
MetaEntryPtr entry = ENV.metacache()->resolveEntry("FTBPacks", QString("logos/%1").arg(file.section(".", 0, 0)));
NetJob *job = new NetJob(QString("FTB Icon Download for %1").arg(file));
- job->addNetAction(Net::Download::makeCached(QUrl(QString(URLConstants::FTB_CDN_BASE_URL + "static/%1").arg(file)), entry));
+ job->addNetAction(Net::Download::makeCached(QUrl(QString(URLConstants::LEGACY_FTB_CDN_BASE_URL + "static/%1").arg(file)), entry));
auto fullPath = entry->getFullPath();
QObject::connect(job, &NetJob::finished, this, [this, file, fullPath]
@@ -238,7 +240,7 @@ void FtbListModel::requestLogo(QString file)
m_loadingLogos.append(file);
}
-void FtbListModel::getLogo(const QString &logo, LogoCallback callback)
+void ListModel::getLogo(const QString &logo, LogoCallback callback)
{
if(m_logoMap.contains(logo))
{
@@ -250,7 +252,9 @@ void FtbListModel::getLogo(const QString &logo, LogoCallback callback)
}
}
-Qt::ItemFlags FtbListModel::flags(const QModelIndex &index) const
+Qt::ItemFlags ListModel::flags(const QModelIndex &index) const
{
return QAbstractListModel::flags(index);
}
+
+}
diff --git a/application/pages/modplatform/FtbListModel.h b/application/pages/modplatform/legacy_ftb/ListModel.h
index 34749b24..c55df000 100644
--- a/application/pages/modplatform/FtbListModel.h
+++ b/application/pages/modplatform/legacy_ftb/ListModel.h
@@ -1,6 +1,6 @@
#pragma once
-#include <modplatform/ftb/PackHelpers.h>
+#include <modplatform/legacy_ftb/PackHelpers.h>
#include <RWStorage.h>
#include <QAbstractListModel>
@@ -11,14 +11,16 @@
#include <functional>
-typedef QMap<QString, QIcon> FtbLogoMap;
+namespace LegacyFTB {
+
+typedef QMap<QString, QIcon> FTBLogoMap;
typedef std::function<void(QString)> LogoCallback;
-class FtbFilterModel : public QSortFilterProxyModel
+class FilterModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
- FtbFilterModel(QObject* parent = Q_NULLPTR);
+ FilterModel(QObject* parent = Q_NULLPTR);
enum Sorting {
ByName,
ByGameVersion
@@ -38,18 +40,18 @@ private:
};
-class FtbListModel : public QAbstractListModel
+class ListModel : public QAbstractListModel
{
Q_OBJECT
private:
- FtbModpackList modpacks;
+ ModpackList modpacks;
QStringList m_failedLogos;
QStringList m_loadingLogos;
- FtbLogoMap m_logoMap;
+ FTBLogoMap m_logoMap;
QMap<QString, LogoCallback> waitingCallbacks;
void requestLogo(QString file);
- QString translatePackType(FtbPackType type) const;
+ QString translatePackType(PackType type) const;
private slots:
@@ -57,18 +59,20 @@ private slots:
void logoLoaded(QString logo, QIcon out);
public:
- FtbListModel(QObject *parent);
- ~FtbListModel();
+ ListModel(QObject *parent);
+ ~ListModel();
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
- void fill(FtbModpackList modpacks);
- void addPack(FtbModpack modpack);
+ void fill(ModpackList modpacks);
+ void addPack(Modpack modpack);
void clear();
void remove(int row);
- FtbModpack at(int row);
+ Modpack at(int row);
void getLogo(const QString &logo, LogoCallback callback);
};
+
+}
diff --git a/application/pages/modplatform/FTBPage.cpp b/application/pages/modplatform/legacy_ftb/Page.cpp
index dca86efd..8e40ba9e 100644
--- a/application/pages/modplatform/FTBPage.cpp
+++ b/application/pages/modplatform/legacy_ftb/Page.cpp
@@ -1,27 +1,29 @@
-#include "FTBPage.h"
-#include "ui_FTBPage.h"
+#include "Page.h"
+#include "ui_Page.h"
#include <QInputDialog>
#include "MultiMC.h"
#include "dialogs/CustomMessageBox.h"
#include "dialogs/NewInstanceDialog.h"
-#include "modplatform/ftb/FtbPackFetchTask.h"
-#include "modplatform/ftb/FtbPackInstallTask.h"
-#include "modplatform/ftb/FtbPrivatePackManager.h"
-#include "FtbListModel.h"
+#include "modplatform/legacy_ftb/PackFetchTask.h"
+#include "modplatform/legacy_ftb/PackInstallTask.h"
+#include "modplatform/legacy_ftb/PrivatePackManager.h"
+#include "ListModel.h"
-FTBPage::FTBPage(NewInstanceDialog* dialog, QWidget *parent)
- : QWidget(parent), dialog(dialog), ui(new Ui::FTBPage)
+namespace LegacyFTB {
+
+Page::Page(NewInstanceDialog* dialog, QWidget *parent)
+ : QWidget(parent), dialog(dialog), ui(new Ui::Page)
{
- ftbFetchTask.reset(new FtbPackFetchTask());
- ftbPrivatePacks.reset(new FtbPrivatePackManager());
+ ftbFetchTask.reset(new PackFetchTask());
+ ftbPrivatePacks.reset(new PrivatePackManager());
ui->setupUi(this);
{
- publicFilterModel = new FtbFilterModel(this);
- publicListModel = new FtbListModel(this);
+ publicFilterModel = new FilterModel(this);
+ publicListModel = new ListModel(this);
publicFilterModel->setSourceModel(publicListModel);
ui->publicPackList->setModel(publicFilterModel);
@@ -39,8 +41,8 @@ FTBPage::FTBPage(NewInstanceDialog* dialog, QWidget *parent)
}
{
- thirdPartyFilterModel = new FtbFilterModel(this);
- thirdPartyModel = new FtbListModel(this);
+ thirdPartyFilterModel = new FilterModel(this);
+ thirdPartyModel = new ListModel(this);
thirdPartyFilterModel->setSourceModel(thirdPartyModel);
ui->thirdPartyPackList->setModel(thirdPartyFilterModel);
@@ -53,8 +55,8 @@ FTBPage::FTBPage(NewInstanceDialog* dialog, QWidget *parent)
}
{
- privateFilterModel = new FtbFilterModel(this);
- privateListModel = new FtbListModel(this);
+ privateFilterModel = new FilterModel(this);
+ privateListModel = new ListModel(this);
privateFilterModel->setSourceModel(privateListModel);
ui->privatePackList->setModel(privateFilterModel);
@@ -69,17 +71,17 @@ FTBPage::FTBPage(NewInstanceDialog* dialog, QWidget *parent)
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300);
- connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &FTBPage::onSortingSelectionChanged);
- connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &FTBPage::onVersionSelectionItemChanged);
+ connect(ui->sortByBox, &QComboBox::currentTextChanged, this, &Page::onSortingSelectionChanged);
+ connect(ui->versionSelectionBox, &QComboBox::currentTextChanged, this, &Page::onVersionSelectionItemChanged);
- connect(ui->publicPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &FTBPage::onPublicPackSelectionChanged);
- connect(ui->thirdPartyPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &FTBPage::onThirdPartyPackSelectionChanged);
- connect(ui->privatePackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &FTBPage::onPrivatePackSelectionChanged);
+ connect(ui->publicPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onPublicPackSelectionChanged);
+ connect(ui->thirdPartyPackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onThirdPartyPackSelectionChanged);
+ connect(ui->privatePackList->selectionModel(), &QItemSelectionModel::currentChanged, this, &Page::onPrivatePackSelectionChanged);
- connect(ui->addPackBtn, &QPushButton::pressed, this, &FTBPage::onAddPackClicked);
- connect(ui->removePackBtn, &QPushButton::pressed, this, &FTBPage::onRemovePackClicked);
+ connect(ui->addPackBtn, &QPushButton::pressed, this, &Page::onAddPackClicked);
+ connect(ui->removePackBtn, &QPushButton::pressed, this, &Page::onRemovePackClicked);
- connect(ui->tabWidget, &QTabWidget::currentChanged, this, &FTBPage::onTabChanged);
+ connect(ui->tabWidget, &QTabWidget::currentChanged, this, &Page::onTabChanged);
// ui->modpackInfo->setOpenExternalLinks(true);
@@ -90,25 +92,25 @@ FTBPage::FTBPage(NewInstanceDialog* dialog, QWidget *parent)
onTabChanged(ui->tabWidget->currentIndex());
}
-FTBPage::~FTBPage()
+Page::~Page()
{
delete ui;
}
-bool FTBPage::shouldDisplay() const
+bool Page::shouldDisplay() const
{
return true;
}
-void FTBPage::openedImpl()
+void Page::openedImpl()
{
if(!initialized)
{
- connect(ftbFetchTask.get(), &FtbPackFetchTask::finished, this, &FTBPage::ftbPackDataDownloadSuccessfully);
- connect(ftbFetchTask.get(), &FtbPackFetchTask::failed, this, &FTBPage::ftbPackDataDownloadFailed);
+ connect(ftbFetchTask.get(), &PackFetchTask::finished, this, &Page::ftbPackDataDownloadSuccessfully);
+ connect(ftbFetchTask.get(), &PackFetchTask::failed, this, &Page::ftbPackDataDownloadFailed);
- connect(ftbFetchTask.get(), &FtbPackFetchTask::privateFileDownloadFinished, this, &FTBPage::ftbPrivatePackDataDownloadSuccessfully);
- connect(ftbFetchTask.get(), &FtbPackFetchTask::privateFileDownloadFailed, this, &FTBPage::ftbPrivatePackDataDownloadFailed);
+ connect(ftbFetchTask.get(), &PackFetchTask::privateFileDownloadFinished, this, &Page::ftbPrivatePackDataDownloadSuccessfully);
+ connect(ftbFetchTask.get(), &PackFetchTask::privateFileDownloadFailed, this, &Page::ftbPrivatePackDataDownloadFailed);
ftbFetchTask->fetch();
ftbPrivatePacks->load();
@@ -118,13 +120,13 @@ void FTBPage::openedImpl()
suggestCurrent();
}
-void FTBPage::suggestCurrent()
+void Page::suggestCurrent()
{
if(isOpened)
{
if(!selected.broken)
{
- dialog->setSuggestedPack(selected.name, new FtbPackInstallTask(selected, selectedVersion));
+ dialog->setSuggestedPack(selected.name, new PackInstallTask(selected, selectedVersion));
QString editedLogoName;
if(selected.logo.toLower().startsWith("ftb"))
{
@@ -137,21 +139,21 @@ void FTBPage::suggestCurrent()
editedLogoName = editedLogoName.left(editedLogoName.lastIndexOf(".png"));
- if(selected.type == FtbPackType::Public)
+ if(selected.type == PackType::Public)
{
publicListModel->getLogo(selected.logo, [this, editedLogoName](QString logo)
{
dialog->setSuggestedIconFromFile(logo, editedLogoName);
});
}
- else if (selected.type == FtbPackType::ThirdParty)
+ else if (selected.type == PackType::ThirdParty)
{
thirdPartyModel->getLogo(selected.logo, [this, editedLogoName](QString logo)
{
dialog->setSuggestedIconFromFile(logo, editedLogoName);
});
}
- else if (selected.type == FtbPackType::Private)
+ else if (selected.type == PackType::Private)
{
privateListModel->getLogo(selected.logo, [this, editedLogoName](QString logo)
{
@@ -166,23 +168,23 @@ void FTBPage::suggestCurrent()
}
}
-void FTBPage::ftbPackDataDownloadSuccessfully(FtbModpackList publicPacks, FtbModpackList thirdPartyPacks)
+void Page::ftbPackDataDownloadSuccessfully(ModpackList publicPacks, ModpackList thirdPartyPacks)
{
publicListModel->fill(publicPacks);
thirdPartyModel->fill(thirdPartyPacks);
}
-void FTBPage::ftbPackDataDownloadFailed(QString reason)
+void Page::ftbPackDataDownloadFailed(QString reason)
{
//TODO: Display the error
}
-void FTBPage::ftbPrivatePackDataDownloadSuccessfully(FtbModpack pack)
+void Page::ftbPrivatePackDataDownloadSuccessfully(Modpack pack)
{
privateListModel->addPack(pack);
}
-void FTBPage::ftbPrivatePackDataDownloadFailed(QString reason, QString packCode)
+void Page::ftbPrivatePackDataDownloadFailed(QString reason, QString packCode)
{
auto reply = QMessageBox::question(
this,
@@ -195,40 +197,40 @@ void FTBPage::ftbPrivatePackDataDownloadFailed(QString reason, QString packCode)
}
}
-void FTBPage::onPublicPackSelectionChanged(QModelIndex now, QModelIndex prev)
+void Page::onPublicPackSelectionChanged(QModelIndex now, QModelIndex prev)
{
if(!now.isValid())
{
onPackSelectionChanged();
return;
}
- FtbModpack selectedPack = publicFilterModel->data(now, Qt::UserRole).value<FtbModpack>();
+ Modpack selectedPack = publicFilterModel->data(now, Qt::UserRole).value<Modpack>();
onPackSelectionChanged(&selectedPack);
}
-void FTBPage::onThirdPartyPackSelectionChanged(QModelIndex now, QModelIndex prev)
+void Page::onThirdPartyPackSelectionChanged(QModelIndex now, QModelIndex prev)
{
if(!now.isValid())
{
onPackSelectionChanged();
return;
}
- FtbModpack selectedPack = thirdPartyFilterModel->data(now, Qt::UserRole).value<FtbModpack>();
+ Modpack selectedPack = thirdPartyFilterModel->data(now, Qt::UserRole).value<Modpack>();
onPackSelectionChanged(&selectedPack);
}
-void FTBPage::onPrivatePackSelectionChanged(QModelIndex now, QModelIndex prev)
+void Page::onPrivatePackSelectionChanged(QModelIndex now, QModelIndex prev)
{
if(!now.isValid())
{
onPackSelectionChanged();
return;
}
- FtbModpack selectedPack = privateFilterModel->data(now, Qt::UserRole).value<FtbModpack>();
+ Modpack selectedPack = privateFilterModel->data(now, Qt::UserRole).value<Modpack>();
onPackSelectionChanged(&selectedPack);
}
-void FTBPage::onPackSelectionChanged(FtbModpack* pack)
+void Page::onPackSelectionChanged(Modpack* pack)
{
ui->versionSelectionBox->clear();
if(pack)
@@ -266,7 +268,7 @@ void FTBPage::onPackSelectionChanged(FtbModpack* pack)
suggestCurrent();
}
-void FTBPage::onVersionSelectionItemChanged(QString data)
+void Page::onVersionSelectionItemChanged(QString data)
{
if(data.isNull() || data.isEmpty())
{
@@ -278,15 +280,15 @@ void FTBPage::onVersionSelectionItemChanged(QString data)
suggestCurrent();
}
-void FTBPage::onSortingSelectionChanged(QString data)
+void Page::onSortingSelectionChanged(QString data)
{
- FtbFilterModel::Sorting toSet = publicFilterModel->getAvailableSortings().value(data);
+ FilterModel::Sorting toSet = publicFilterModel->getAvailableSortings().value(data);
publicFilterModel->setSorting(toSet);
thirdPartyFilterModel->setSorting(toSet);
privateFilterModel->setSorting(toSet);
}
-void FTBPage::onTabChanged(int tab)
+void Page::onTabChanged(int tab)
{
if(tab == 1)
{
@@ -311,7 +313,7 @@ void FTBPage::onTabChanged(int tab)
QModelIndex idx = currentList->currentIndex();
if(idx.isValid())
{
- auto pack = currentModel->data(idx, Qt::UserRole).value<FtbModpack>();
+ auto pack = currentModel->data(idx, Qt::UserRole).value<Modpack>();
onPackSelectionChanged(&pack);
}
else
@@ -320,7 +322,7 @@ void FTBPage::onTabChanged(int tab)
}
}
-void FTBPage::onAddPackClicked()
+void Page::onAddPackClicked()
{
bool ok;
QString text = QInputDialog::getText(
@@ -338,7 +340,7 @@ void FTBPage::onAddPackClicked()
}
}
-void FTBPage::onRemovePackClicked()
+void Page::onRemovePackClicked()
{
auto index = ui->privatePackList->currentIndex();
if(!index.isValid())
@@ -346,7 +348,7 @@ void FTBPage::onRemovePackClicked()
return;
}
auto row = index.row();
- FtbModpack pack = privateListModel->at(row);
+ Modpack pack = privateListModel->at(row);
auto answer = QMessageBox::question(
this,
tr("Remove pack"),
@@ -362,3 +364,5 @@ void FTBPage::onRemovePackClicked()
privateListModel->remove(row);
onPackSelectionChanged();
}
+
+}
diff --git a/application/pages/modplatform/FTBPage.h b/application/pages/modplatform/legacy_ftb/Page.h
index 215252ee..ed6d1657 100644
--- a/application/pages/modplatform/FTBPage.h
+++ b/application/pages/modplatform/legacy_ftb/Page.h
@@ -22,29 +22,32 @@
#include "pages/BasePage.h"
#include <MultiMC.h>
#include "tasks/Task.h"
-#include "modplatform/ftb/PackHelpers.h"
-#include "modplatform/ftb/FtbPackFetchTask.h"
+#include "modplatform/legacy_ftb/PackHelpers.h"
+#include "modplatform/legacy_ftb/PackFetchTask.h"
#include "QObjectPtr.h"
+class NewInstanceDialog;
+
+namespace LegacyFTB {
+
namespace Ui
{
-class FTBPage;
+class Page;
}
-class FtbListModel;
-class FtbFilterModel;
-class NewInstanceDialog;
-class FtbPrivatePackListModel;
-class FtbPrivatePackFilterModel;
-class FtbPrivatePackManager;
+class ListModel;
+class FilterModel;
+class PrivatePackListModel;
+class PrivatePackFilterModel;
+class PrivatePackManager;
-class FTBPage : public QWidget, public BasePage
+class Page : public QWidget, public BasePage
{
Q_OBJECT
public:
- explicit FTBPage(NewInstanceDialog * dialog, QWidget *parent = 0);
- virtual ~FTBPage();
+ explicit Page(NewInstanceDialog * dialog, QWidget *parent = 0);
+ virtual ~Page();
QString displayName() const override
{
return tr("FTB Legacy");
@@ -55,7 +58,7 @@ public:
}
QString id() const override
{
- return "ftb";
+ return "legacy_ftb";
}
QString helpPage() const override
{
@@ -66,13 +69,13 @@ public:
private:
void suggestCurrent();
- void onPackSelectionChanged(FtbModpack *pack = nullptr);
+ void onPackSelectionChanged(Modpack *pack = nullptr);
private slots:
- void ftbPackDataDownloadSuccessfully(FtbModpackList publicPacks, FtbModpackList thirdPartyPacks);
+ void ftbPackDataDownloadSuccessfully(ModpackList publicPacks, ModpackList thirdPartyPacks);
void ftbPackDataDownloadFailed(QString reason);
- void ftbPrivatePackDataDownloadSuccessfully(FtbModpack pack);
+ void ftbPrivatePackDataDownloadSuccessfully(Modpack pack);
void ftbPrivatePackDataDownloadFailed(QString reason, QString packCode);
void onSortingSelectionChanged(QString data);
@@ -88,27 +91,29 @@ private slots:
void onRemovePackClicked();
private:
- FtbFilterModel* currentModel = nullptr;
+ FilterModel* currentModel = nullptr;
QTreeView* currentList = nullptr;
QTextBrowser* currentModpackInfo = nullptr;
bool initialized = false;
- FtbModpack selected;
+ Modpack selected;
QString selectedVersion;
- FtbListModel* publicListModel = nullptr;
- FtbFilterModel* publicFilterModel = nullptr;
+ ListModel* publicListModel = nullptr;
+ FilterModel* publicFilterModel = nullptr;
- FtbListModel *thirdPartyModel = nullptr;
- FtbFilterModel *thirdPartyFilterModel = nullptr;
+ ListModel *thirdPartyModel = nullptr;
+ FilterModel *thirdPartyFilterModel = nullptr;
- FtbListModel *privateListModel = nullptr;
- FtbFilterModel *privateFilterModel = nullptr;
+ ListModel *privateListModel = nullptr;
+ FilterModel *privateFilterModel = nullptr;
- unique_qobject_ptr<FtbPackFetchTask> ftbFetchTask;
- std::unique_ptr<FtbPrivatePackManager> ftbPrivatePacks;
+ unique_qobject_ptr<PackFetchTask> ftbFetchTask;
+ std::unique_ptr<PrivatePackManager> ftbPrivatePacks;
NewInstanceDialog* dialog = nullptr;
- Ui::FTBPage *ui = nullptr;
+ Ui::Page *ui = nullptr;
};
+
+}
diff --git a/application/pages/modplatform/FTBPage.ui b/application/pages/modplatform/legacy_ftb/Page.ui
index e5ed78cb..36fb2359 100644
--- a/application/pages/modplatform/FTBPage.ui
+++ b/application/pages/modplatform/legacy_ftb/Page.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>FTBPage</class>
- <widget class="QWidget" name="FTBPage">
+ <class>LegacyFTB::Page</class>
+ <widget class="QWidget" name="LegacyFTB::Page">
<property name="geometry">
<rect>
<x>0</x>
diff --git a/application/pages/modplatform/twitch/TwitchData.h b/application/pages/modplatform/twitch/TwitchData.h
new file mode 100644
index 00000000..dd000b84
--- /dev/null
+++ b/application/pages/modplatform/twitch/TwitchData.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <QString>
+#include <QList>
+
+namespace Twitch {
+
+struct ModpackAuthor {
+ QString name;
+ QString url;
+};
+
+struct ModpackFile {
+ int addonId;
+ int fileId;
+ QString version;
+ QString mcVersion;
+ QString downloadUrl;
+};
+
+struct Modpack
+{
+ bool broken = true;
+ int addonId = 0;
+
+ QString name;
+ QString description;
+ QList<ModpackAuthor> authors;
+ QString mcVersion;
+ QString logoName;
+ QString logoUrl;
+ QString websiteUrl;
+
+ ModpackFile latestFile;
+};
+}
+
+Q_DECLARE_METATYPE(Twitch::Modpack)
diff --git a/application/pages/modplatform/twitch/TwitchModel.cpp b/application/pages/modplatform/twitch/TwitchModel.cpp
new file mode 100644
index 00000000..d9358941
--- /dev/null
+++ b/application/pages/modplatform/twitch/TwitchModel.cpp
@@ -0,0 +1,314 @@
+#include "TwitchModel.h"
+#include "MultiMC.h"
+
+#include <MMCStrings.h>
+#include <Version.h>
+
+#include <QtMath>
+#include <QLabel>
+
+#include <RWStorage.h>
+#include <Env.h>
+
+#include "net/URLConstants.h"
+
+namespace Twitch {
+
+ListModel::ListModel(QObject *parent) : QAbstractListModel(parent)
+{
+}
+
+ListModel::~ListModel()
+{
+}
+
+int ListModel::rowCount(const QModelIndex &parent) const
+{
+ return modpacks.size();
+}
+
+int ListModel::columnCount(const QModelIndex &parent) const
+{
+ return 1;
+}
+
+QVariant ListModel::data(const QModelIndex &index, int role) const
+{
+ int pos = index.row();
+ if(pos >= modpacks.size() || pos < 0 || !index.isValid())
+ {
+ return QString("INVALID INDEX %1").arg(pos);
+ }
+
+ Modpack pack = modpacks.at(pos);
+ if(role == Qt::DisplayRole)
+ {
+ return pack.name;
+ }
+ else if (role == Qt::ToolTipRole)
+ {
+ if(pack.description.length() > 100)
+ {
+ //some magic to prevent to long tooltips and replace html linebreaks
+ QString edit = pack.description.left(97);
+ edit = edit.left(edit.lastIndexOf("<br>")).left(edit.lastIndexOf(" ")).append("...");
+ return edit;
+
+ }
+ return pack.description;
+ }
+ else if(role == Qt::DecorationRole)
+ {
+ if(m_logoMap.contains(pack.logoName))
+ {
+ return (m_logoMap.value(pack.logoName));
+ }
+ QIcon icon = MMC->getThemedIcon("screenshot-placeholder");
+ ((ListModel *)this)->requestLogo(pack.logoName, pack.logoUrl);
+ return icon;
+ }
+ else if(role == Qt::UserRole)
+ {
+ QVariant v;
+ v.setValue(pack);
+ return v;
+ }
+
+ return QVariant();
+}
+
+void ListModel::logoLoaded(QString logo, QIcon out)
+{
+ m_loadingLogos.removeAll(logo);
+ m_logoMap.insert(logo, out);
+ for(int i = 0; i < modpacks.size(); i++) {
+ if(modpacks[i].logoName == logo) {
+ emit dataChanged(createIndex(i, 0), createIndex(i, 0), {Qt::DecorationRole});
+ }
+ }
+}
+
+void ListModel::logoFailed(QString logo)
+{
+ m_failedLogos.append(logo);
+ m_loadingLogos.removeAll(logo);
+}
+
+void ListModel::requestLogo(QString logo, QString url)
+{
+ if(m_loadingLogos.contains(logo) || m_failedLogos.contains(logo))
+ {
+ return;
+ }
+
+ MetaEntryPtr entry = ENV.metacache()->resolveEntry("TwitchPacks", QString("logos/%1").arg(logo.section(".", 0, 0)));
+ NetJob *job = new NetJob(QString("Twitch Icon Download %1").arg(logo));
+ job->addNetAction(Net::Download::makeCached(QUrl(url), entry));
+
+ auto fullPath = entry->getFullPath();
+ QObject::connect(job, &NetJob::finished, this, [this, logo, fullPath]
+ {
+ emit logoLoaded(logo, QIcon(fullPath));
+ if(waitingCallbacks.contains(logo))
+ {
+ waitingCallbacks.value(logo)(fullPath);
+ }
+ });
+
+ QObject::connect(job, &NetJob::failed, this, [this, logo]
+ {
+ emit logoFailed(logo);
+ });
+
+ job->start();
+
+ m_loadingLogos.append(logo);
+}
+
+void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback)
+{
+ if(m_logoMap.contains(logo))
+ {
+ callback(ENV.metacache()->resolveEntry("TwitchPacks", QString("logos/%1").arg(logo.section(".", 0, 0)))->getFullPath());
+ }
+ else
+ {
+ requestLogo(logo, logoUrl);
+ }
+}
+
+Qt::ItemFlags ListModel::flags(const QModelIndex &index) const
+{
+ return QAbstractListModel::flags(index);
+}
+
+bool ListModel::canFetchMore(const QModelIndex& parent) const
+{
+ return searchState == CanPossiblyFetchMore;
+}
+
+void ListModel::fetchMore(const QModelIndex& parent)
+{
+ if (parent.isValid())
+ return;
+ if(nextSearchOffset == 0) {
+ qWarning() << "fetchMore with 0 offset is wrong...";
+ return;
+ }
+ performPaginatedSearch();
+}
+
+void ListModel::performPaginatedSearch()
+{
+ NetJob *netJob = new NetJob("Twitch::Search");
+ auto searchUrl = QString(
+ "https://addons-ecs.forgesvc.net/api/v2/addon/search?"
+ "categoryId=0&"
+ "gameId=432&"
+ //"gameVersion=1.12.2&"
+ "index=%1&"
+ "pageSize=25&"
+ "searchFilter=%2&"
+ "sectionId=4471&"
+ "sort=0"
+ ).arg(nextSearchOffset).arg(currentSearchTerm);
+ netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
+ jobPtr = netJob;
+ jobPtr->start();
+ QObject::connect(netJob, &NetJob::succeeded, this, &ListModel::searchRequestFinished);
+ QObject::connect(netJob, &NetJob::failed, this, &ListModel::searchRequestFailed);
+}
+
+void ListModel::searchWithTerm(const QString& term)
+{
+ if(currentSearchTerm == term) {
+ return;
+ }
+ currentSearchTerm = term;
+ if(jobPtr) {
+ jobPtr->abort();
+ searchState = ResetRequested;
+ return;
+ }
+ else {
+ beginResetModel();
+ modpacks.clear();
+ endResetModel();
+ searchState = None;
+ }
+ nextSearchOffset = 0;
+ performPaginatedSearch();
+}
+
+void Twitch::ListModel::searchRequestFinished()
+{
+ jobPtr.reset();
+
+ QJsonParseError parse_error;
+ QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
+ if(parse_error.error != QJsonParseError::NoError) {
+ qWarning() << "Error while parsing JSON response from Twitch at " << parse_error.offset << " reason: " << parse_error.errorString();
+ qWarning() << response;
+ return;
+ }
+
+ QList<Modpack> newList;
+ auto objs = doc.array();
+ for(auto projectIter: objs) {
+ Modpack pack;
+ auto project = projectIter.toObject();
+ pack.addonId = project.value("id").toInt(0);
+ if (pack.addonId == 0) {
+ qWarning() << "Pack without an ID, skipping: " << pack.name;
+ continue;
+ }
+ pack.name = project.value("name").toString();
+ pack.websiteUrl = project.value("websiteUrl").toString();
+ pack.description = project.value("summary").toString();
+ bool thumbnailFound = false;
+ auto attachments = project.value("attachments").toArray();
+ for(auto attachmentIter: attachments) {
+ auto attachment = attachmentIter.toObject();
+ bool isDefault = attachment.value("isDefault").toBool(false);
+ if(isDefault) {
+ thumbnailFound = true;
+ pack.logoName = attachment.value("title").toString();
+ pack.logoUrl = attachment.value("thumbnailUrl").toString();
+ break;
+ }
+ }
+ if(!thumbnailFound) {
+ qWarning() << "Pack without an icon, skipping: " << pack.name;
+ continue;
+ }
+ auto authors = project.value("authors").toArray();
+ for(auto authorIter: authors) {
+ auto author = authorIter.toObject();
+ ModpackAuthor packAuthor;
+ packAuthor.name = author.value("name").toString();
+ packAuthor.url = author.value("url").toString();
+ pack.authors.append(packAuthor);
+ }
+ int defaultFileId = project.value("defaultFileId").toInt(0);
+ if(defaultFileId == 0) {
+ qWarning() << "Pack without default file, skipping: " << pack.name;
+ continue;
+ }
+ bool found = false;
+ auto files = project.value("latestFiles").toArray();
+ for(auto fileIter: files) {
+ auto file = fileIter.toObject();
+ int id = file.value("id").toInt(0);
+ // NOTE: for now, ignore everything that's not the default...
+ if(id != defaultFileId) {
+ continue;
+ }
+ pack.latestFile.addonId = pack.addonId;
+ pack.latestFile.fileId = id;
+ // FIXME: what to do when there's more than one, or there's no version?
+ auto versionArray = file.value("gameVersion").toArray();
+ if(versionArray.size() != 1) {
+ continue;
+ }
+ pack.latestFile.mcVersion = versionArray[0].toString();
+ pack.latestFile.version = file.value("displayName").toString();
+ pack.latestFile.downloadUrl = file.value("downloadUrl").toString();
+ found = true;
+ break;
+ }
+ if(!found) {
+ qWarning() << "Pack with no good file, skipping: " << pack.name;
+ continue;
+ }
+ pack.broken = false;
+ newList.append(pack);
+ }
+ if(objs.size() < 25) {
+ searchState = Finished;
+ } else {
+ nextSearchOffset += 25;
+ searchState = CanPossiblyFetchMore;
+ }
+ beginInsertRows(QModelIndex(), modpacks.size(), modpacks.size() + newList.size() - 1);
+ modpacks.append(newList);
+ endInsertRows();
+}
+
+void Twitch::ListModel::searchRequestFailed(QString reason)
+{
+ jobPtr.reset();
+
+ if(searchState == ResetRequested) {
+ beginResetModel();
+ modpacks.clear();
+ endResetModel();
+
+ nextSearchOffset = 0;
+ performPaginatedSearch();
+ } else {
+ searchState = Finished;
+ }
+}
+
+}
+
diff --git a/application/pages/modplatform/twitch/TwitchModel.h b/application/pages/modplatform/twitch/TwitchModel.h
new file mode 100644
index 00000000..ad355c64
--- /dev/null
+++ b/application/pages/modplatform/twitch/TwitchModel.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <modplatform/legacy_ftb/PackHelpers.h>
+#include <RWStorage.h>
+
+#include <QAbstractListModel>
+#include <QSortFilterProxyModel>
+#include <QThreadPool>
+#include <QIcon>
+#include <QStyledItemDelegate>
+#include <QList>
+#include <QString>
+#include <QStringList>
+#include <QMetaType>
+
+#include <functional>
+#include <net/NetJob.h>
+
+#include "TwitchData.h"
+
+namespace Twitch {
+
+
+typedef QMap<QString, QIcon> LogoMap;
+typedef std::function<void(QString)> LogoCallback;
+
+class ListModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ ListModel(QObject *parent);
+ virtual ~ListModel();
+
+ int rowCount(const QModelIndex &parent) const override;
+ int columnCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+ bool canFetchMore(const QModelIndex & parent) const override;
+ void fetchMore(const QModelIndex & parent) override;
+
+ void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
+ void searchWithTerm(const QString & term);
+
+private slots:
+ void performPaginatedSearch();
+
+ void logoFailed(QString logo);
+ void logoLoaded(QString logo, QIcon out);
+
+ void searchRequestFinished();
+ void searchRequestFailed(QString reason);
+
+private:
+ void requestLogo(QString file, QString url);
+
+private:
+ QList<Modpack> modpacks;
+ QStringList m_failedLogos;
+ QStringList m_loadingLogos;
+ LogoMap m_logoMap;
+ QMap<QString, LogoCallback> waitingCallbacks;
+
+ QString currentSearchTerm;
+ int nextSearchOffset = 0;
+ enum SearchState {
+ None,
+ CanPossiblyFetchMore,
+ ResetRequested,
+ Finished
+ } searchState = None;
+ NetJobPtr jobPtr;
+ QByteArray response;
+};
+
+}
diff --git a/application/pages/modplatform/twitch/TwitchPage.cpp b/application/pages/modplatform/twitch/TwitchPage.cpp
new file mode 100644
index 00000000..1e9f9dbb
--- /dev/null
+++ b/application/pages/modplatform/twitch/TwitchPage.cpp
@@ -0,0 +1,111 @@
+#include "TwitchPage.h"
+#include "ui_TwitchPage.h"
+
+#include "MultiMC.h"
+#include "dialogs/NewInstanceDialog.h"
+#include <InstanceImportTask.h>
+#include "TwitchModel.h"
+#include <QKeyEvent>
+
+TwitchPage::TwitchPage(NewInstanceDialog* dialog, QWidget *parent)
+ : QWidget(parent), ui(new Ui::TwitchPage), dialog(dialog)
+{
+ ui->setupUi(this);
+ connect(ui->searchButton, &QPushButton::clicked, this, &TwitchPage::triggerSearch);
+ ui->searchEdit->installEventFilter(this);
+ model = new Twitch::ListModel(this);
+ ui->packView->setModel(model);
+ connect(ui->packView->selectionModel(), &QItemSelectionModel::currentChanged, this, &TwitchPage::onSelectionChanged);
+}
+
+TwitchPage::~TwitchPage()
+{
+ delete ui;
+}
+
+bool TwitchPage::eventFilter(QObject* watched, QEvent* event)
+{
+ if (watched == ui->searchEdit && event->type() == QEvent::KeyPress) {
+ QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
+ if (keyEvent->key() == Qt::Key_Return) {
+ triggerSearch();
+ keyEvent->accept();
+ return true;
+ }
+ }
+ return QWidget::eventFilter(watched, event);
+}
+
+bool TwitchPage::shouldDisplay() const
+{
+ return true;
+}
+
+void TwitchPage::openedImpl()
+{
+ suggestCurrent();
+}
+
+void TwitchPage::triggerSearch()
+{
+ model->searchWithTerm(ui->searchEdit->text());
+}
+
+void TwitchPage::onSelectionChanged(QModelIndex first, QModelIndex second)
+{
+ if(!first.isValid())
+ {
+ if(isOpened)
+ {
+ dialog->setSuggestedPack();
+ }
+ ui->frame->clear();
+ return;
+ }
+
+ current = model->data(first, Qt::UserRole).value<Twitch::Modpack>();
+ QString text = "";
+ QString name = current.name;
+
+ if (current.websiteUrl.isEmpty())
+ text = name;
+ else
+ text = "<a href=\"" + current.websiteUrl + "\">" + name + "</a>";
+ if (!current.authors.empty()) {
+ auto authorToStr = [](Twitch::ModpackAuthor & author) {
+ if(author.url.isEmpty()) {
+ return author.name;
+ }
+ return QString("<a href=\"%1\">%2</a>").arg(author.url, author.name);
+ };
+ QStringList authorStrs;
+ for(auto & author: current.authors) {
+ authorStrs.push_back(authorToStr(author));
+ }
+ text += tr(" by ") + authorStrs.join(", ");
+ }
+
+ ui->frame->setModText(text);
+ ui->frame->setModDescription(current.description);
+ suggestCurrent();
+}
+
+void TwitchPage::suggestCurrent()
+{
+ if(!isOpened)
+ {
+ return;
+ }
+ if(current.broken)
+ {
+ dialog->setSuggestedPack();
+ }
+
+ dialog->setSuggestedPack(current.name, new InstanceImportTask(current.latestFile.downloadUrl));
+ QString editedLogoName;
+ editedLogoName = "twitch_" + current.logoName.section(".", 0, 0);
+ model->getLogo(current.logoName, current.logoUrl, [this, editedLogoName](QString logo)
+ {
+ dialog->setSuggestedIconFromFile(logo, editedLogoName);
+ });
+}
diff --git a/application/pages/modplatform/TwitchPage.h b/application/pages/modplatform/twitch/TwitchPage.h
index 600913cd..04e3a1c6 100644
--- a/application/pages/modplatform/TwitchPage.h
+++ b/application/pages/modplatform/twitch/TwitchPage.h
@@ -20,7 +20,7 @@
#include "pages/BasePage.h"
#include <MultiMC.h>
#include "tasks/Task.h"
-#include "modplatform/flame/UrlResolvingTask.h"
+#include "TwitchData.h"
namespace Ui
{
@@ -29,6 +29,10 @@ class TwitchPage;
class NewInstanceDialog;
+namespace Twitch {
+ class ListModel;
+}
+
class TwitchPage : public QWidget, public BasePage
{
Q_OBJECT
@@ -38,7 +42,7 @@ public:
virtual ~TwitchPage();
virtual QString displayName() const override
{
- return tr("Twitch URL");
+ return tr("Twitch");
}
virtual QIcon icon() const override
{
@@ -56,14 +60,18 @@ public:
void openedImpl() override;
- void setUrl(const QString & url);
+ bool eventFilter(QObject * watched, QEvent * event) override;
+
+private:
+ void suggestCurrent();
private slots:
- void triggerCheck(bool checked);
- void checkDone();
+ void triggerSearch();
+ void onSelectionChanged(QModelIndex first, QModelIndex second);
private:
Ui::TwitchPage *ui = nullptr;
NewInstanceDialog* dialog = nullptr;
- shared_qobject_ptr<Flame::UrlResolvingTask> m_modIdResolver;
+ Twitch::ListModel* model = nullptr;
+ Twitch::Modpack current;
};
diff --git a/application/pages/modplatform/twitch/TwitchPage.ui b/application/pages/modplatform/twitch/TwitchPage.ui
new file mode 100644
index 00000000..29bdc727
--- /dev/null
+++ b/application/pages/modplatform/twitch/TwitchPage.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TwitchPage</class>
+ <widget class="QWidget" name="TwitchPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>875</width>
+ <height>745</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLineEdit" name="searchEdit"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QPushButton" name="searchButton">
+ <property name="text">
+ <string>Search</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QTreeView" name="packView">
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>48</width>
+ <height>48</height>
+ </size>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="uniformRowHeights">
+ <bool>true</bool>
+ </property>
+ <property name="itemsExpandable">
+ <bool>false</bool>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="MCModInfoFrame" name="frame">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>MCModInfoFrame</class>
+ <extends>QFrame</extends>
+ <header>widgets/MCModInfoFrame.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>searchEdit</tabstop>
+ <tabstop>searchButton</tabstop>
+ <tabstop>packView</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/application/resources/assets/assets.qrc b/application/resources/assets/assets.qrc
deleted file mode 100644
index 38638e7f..00000000
--- a/application/resources/assets/assets.qrc
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE RCC>
-<RCC version="1.0">
- <qresource prefix="/assets">
- <file alias="underconstruction">underconstruction.png</file>
- <file alias="deadglitch">deadglitch.svg</file>
- </qresource>
-</RCC>
diff --git a/application/resources/assets/deadglitch.svg b/application/resources/assets/deadglitch.svg
deleted file mode 100644
index 5682b8a3..00000000
--- a/application/resources/assets/deadglitch.svg
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- class="tw-svg__asset tw-svg__asset--deadglitch tw-svg__asset--inherit"
- width="92px"
- height="96px"
- version="1.1"
- viewBox="0 0 30 30"
- x="0px"
- y="0px"
- id="svg8"
- sodipodi:docname="deadglitch.svg"
- inkscape:version="0.92.2 2405546, 2018-03-11">
- <metadata
- id="metadata14">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs12" />
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="1353"
- inkscape:window-height="828"
- id="namedview10"
- showgrid="false"
- inkscape:zoom="4.9166667"
- inkscape:cx="44.285787"
- inkscape:cy="52.833458"
- inkscape:window-x="2958"
- inkscape:window-y="702"
- inkscape:window-maximized="0"
- inkscape:current-layer="svg8" />
- <g
- id="g6"
- style="fill:#898395;fill-opacity:1">
- <path
- d="M26,17.4589613 L26,3 L4,3 L4,22.0601057 L10.0032868,22.0601057 L10.0032868,26 L14.0004537,22.0601057 L21.3322933,22.0601057 L26,17.4589613 L26,17.4589613 Z M21.0896458,26.0850335 L15.1583403,26.0850335 L11.2051771,30 L7.24798611,30 L7.24798611,26.0850335 L0,26.0850335 L0,5.21746493 L1.97773958,0 L29,0 L29,18.2620736 L21.0896458,26.0850335 L21.0896458,26.0850335 Z"
- id="path2"
- style="fill:#898395;fill-opacity:1" />
- <path
- d="M20.8587626,12.1710126 L22.4052753,13.7175252 L23.7175252,12.4052753 L22.1710126,10.8587626 L23.7175252,9.31224999 L22.4052753,8 L20.8587626,9.54651264 L19.31225,8 L18,9.31224999 L19.5465126,10.8587626 L18,12.4052753 L19.31225,13.7175252 L20.8587626,12.1710126 Z M11.8587626,12.1710126 L13.4052753,13.7175252 L14.7175252,12.4052753 L13.1710126,10.8587626 L14.7175252,9.31224999 L13.4052753,8 L11.8587626,9.54651264 L10.31225,8 L9,9.31224999 L10.5465126,10.8587626 L9,12.4052753 L10.31225,13.7175252 L11.8587626,12.1710126 Z"
- id="path4"
- style="fill:#898395;fill-opacity:1" />
- </g>
-</svg>
diff --git a/application/resources/assets/underconstruction.png b/application/resources/assets/underconstruction.png
deleted file mode 100644
index 6ae06476..00000000
--- a/application/resources/assets/underconstruction.png
+++ /dev/null
Binary files differ
diff --git a/application/widgets/DropLabel.cpp b/application/widgets/DropLabel.cpp
new file mode 100644
index 00000000..a900e57c
--- /dev/null
+++ b/application/widgets/DropLabel.cpp
@@ -0,0 +1,41 @@
+#include "DropLabel.h"
+
+#include <QMimeData>
+#include <QDropEvent>
+
+DropLabel::DropLabel(QWidget *parent) : QLabel(parent)
+{
+ setAcceptDrops(true);
+}
+
+void DropLabel::dragEnterEvent(QDragEnterEvent *event)
+{
+ event->acceptProposedAction();
+}
+
+void DropLabel::dragMoveEvent(QDragMoveEvent *event)
+{
+ event->acceptProposedAction();
+}
+
+void DropLabel::dragLeaveEvent(QDragLeaveEvent *event)
+{
+ event->accept();
+}
+
+void DropLabel::dropEvent(QDropEvent *event)
+{
+ const QMimeData *mimeData = event->mimeData();
+
+ if (!mimeData)
+ {
+ return;
+ }
+
+ if (mimeData->hasUrls()) {
+ auto urls = mimeData->urls();
+ emit droppedURLs(urls);
+ }
+
+ event->acceptProposedAction();
+}
diff --git a/application/widgets/DropLabel.h b/application/widgets/DropLabel.h
new file mode 100644
index 00000000..c5ca0bcc
--- /dev/null
+++ b/application/widgets/DropLabel.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <QLabel>
+
+class DropLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ explicit DropLabel(QWidget *parent = nullptr);
+
+signals:
+ void droppedURLs(QList<QUrl> urls);
+
+protected:
+ void dropEvent(QDropEvent *event) override;
+ void dragEnterEvent(QDragEnterEvent *event) override;
+ void dragMoveEvent(QDragMoveEvent *event) override;
+ void dragLeaveEvent(QDragLeaveEvent *event) override;
+};
diff --git a/application/widgets/ServerStatus.cpp b/application/widgets/ServerStatus.cpp
index a7016c0c..ce0aed9c 100644
--- a/application/widgets/ServerStatus.cpp
+++ b/application/widgets/ServerStatus.cpp
@@ -125,7 +125,7 @@ void ServerStatus::addStatus(QString key, QString name)
void ServerStatus::clicked()
{
- DesktopServices::openUrl(QUrl("https://help.mojang.com/"));
+ DesktopServices::openUrl(QUrl("https://github.com/MultiMC/MultiMC5/wiki/Mojang-Services-Status"));
}
void ServerStatus::setStatus(QString key, int value)
diff --git a/application/widgets/VersionListView.cpp b/application/widgets/VersionListView.cpp
index 09df75b7..fdcb84e6 100644
--- a/application/widgets/VersionListView.cpp
+++ b/application/widgets/VersionListView.cpp
@@ -82,7 +82,9 @@ void VersionListView::setEmptyMode(VersionListView::EmptyMode mode)
void VersionListView::updateEmptyViewPort()
{
+#ifndef QT_NO_ACCESSIBILITY
setAccessibleDescription(currentEmptyString());
+#endif /* !QT_NO_ACCESSIBILITY */
if(!m_itemCount)
{
diff --git a/changelog.md b/changelog.md
index 544c7abf..e315950c 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,4 +1,69 @@
-# MultiMC 0.6.7
+# MultiMC 0.6.11
+
+This adds Forge 1.13+ support using [ForgeWrapper](https://github.com/ZekerZhayard/ForgeWrapper) by ZekerZhayard.
+
+### New or changed features
+
+- GH-2988: You can now import instances and curse modpacks from the command line with the `--import` option followed by either an URL or a local file path.
+
+- GH-2544: MultiMC now supports downloading library files without including them on the Java classpath.
+
+ This is done by adding them to the `mavenFiles` list instead of the `libraries` list.
+
+ Such downloads are not deduplicated or version upgraded like libraries are.
+
+ This enables ForgeWrapper to work - MultiMC downloads all the files, and ForgeWrapper runs the Forge installer during instance start when needed.
+
+# Previous releases
+
+## MultiMC 0.6.8
+
+This is mostly about removal of the 'curse URL' related features, because they were of low quality and generally unreliable.
+
+There are some bug fixes included.
+
+MultiMC also migrated to a new continuous deployment system, which makes everything that much smoother.
+
+### New or changed features
+
+- GH-852: Instance group expansion status now saves/loads as expected.
+
+- The bees have invaded the launcher. We now have a bee icon.
+
+- Translations have been overhauled, yet again...
+
+ - We now have a [crowdin site](https://translate.multimc.org/) for all the translation work.
+
+ - Translations are made based on the development version, and for the development version.
+
+ - Many strings have been tweaked to make translating the application easier.
+
+ - When selecting languages, European Portuguese is now displaying properly.
+
+- Accessibility has been further improved - the main window reads as `MultiMC`, not a long string of nonsensical version numbers, when announced by a screen reader.
+
+- Removed the unimplemented Technic page from instance creation dialog.
+
+- GH-2859: Broken twitch URL import method was removed.
+
+- GH-2819: Filter bar in mod lists now also works with descriptions and author lists.
+
+- GH-2832: Version page now has buttons for opening the Minecraft and internal libraries folders of the instance.
+
+- GH-2769: When copying an instance, there's now an option to keep or remove the total play time from the copy.
+
+### Bugfixes
+
+- GH-2880: Clicking the service status indicators now opens a valid site again, instead of going nowhere.
+
+- GH-2853: When collapsing groups in instance view, the action no longer becomes 'sticky' and doesn't apply to items clicked afterwards.
+
+- GH-2787: "Download All" button works again.
+
+- When a component is customized, the launcher will not try to update it in an infinite loop when something else requires a different version.
+
+
+## MultiMC 0.6.7
The previous release introduced some extra buttons that made the instance window way too big for some displays. This release is aimed at fixing that, along with other UI and performance improvements.
@@ -47,8 +112,6 @@ There are some accessibility fixes thrown in too.
Sorting cascades from 'Enabled' to 'Name' and then 'Version'. This means that if you sort 'Enabled', the enabled and disabled mods are still sorted
by name and mods with the same name will be also sorted by version.
-# Previous releases
-
## MultiMC 0.6.6
This release is mostly the smaller things that have accumulated over time, along with a big change in linux packaging.
@@ -70,7 +133,7 @@ MultiMC on linux is built with Qt 5.4 and older versions of Qt will not work.
This should be a massive improvement to system integration on linux and resolves GH-1784, GH-2605, GH-1979, GH-2271, GH-1992, GH-1816 and their many duplicates.
-#### New or changed features
+### New or changed features
- GH-2487: No is now the default button when deleting instances.
@@ -100,7 +163,7 @@ This should be a massive improvement to system integration on linux and resolves
You can now drag the purple download buttons from CurseForge into MultiMC and get a modpack out of it. Much easier!
-#### Bugfixes
+### Bugfixes
- Translation folder is now created sooner, making first launch translation fetch work again.
@@ -134,7 +197,7 @@ This should be a massive improvement to system integration on linux and resolves
Finalizing the translation workflow improvements and adding fixes for sounds missing in old game versions.
-#### New or changed features
+### New or changed features
- UI for the language settings has been unified across the application
diff --git a/libraries/launcher/net/minecraft/Launcher.java b/libraries/launcher/net/minecraft/Launcher.java
index dd704484..29ddbd3e 100644
--- a/libraries/launcher/net/minecraft/Launcher.java
+++ b/libraries/launcher/net/minecraft/Launcher.java
@@ -143,7 +143,7 @@ public class Launcher extends Applet implements AppletStub
public URL getDocumentBase()
{
try {
- return new URL("http://www.minecraft.net/game/");
+ return new URL("http", "www.minecraft.net", 80, "/game/", null);
} catch (MalformedURLException e) {
e.printStackTrace();
}
diff --git a/libraries/pack200/CMakeLists.txt b/libraries/pack200/CMakeLists.txt
deleted file mode 100644
index 31eb0f73..00000000
--- a/libraries/pack200/CMakeLists.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-cmake_minimum_required(VERSION 3.1)
-
-project(MultiMC_unpack200)
-
-option(PACK200_BUILD_BINARY "Build a tiny utility that decompresses pack200 streams" OFF)
-
-# Find ZLIB for quazip
-find_package(ZLIB REQUIRED)
-
-set(PACK200_SRC
- include/unpack200.h
- src/bands.cpp
- src/bands.h
- src/bytes.cpp
- src/bytes.h
- src/coding.cpp
- src/coding.h
- src/constants.h
- src/defines.h
- src/unpack200.cpp
- src/unpack.cpp
- src/unpack.h
- src/utils.cpp
- src/utils.h
- src/zip.cpp
- src/zip.h
-)
-
-if (Qt5_POSITION_INDEPENDENT_CODE)
- SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
-endif()
-
-add_library(MultiMC_unpack200 SHARED ${PACK200_SRC})
-target_include_directories(MultiMC_unpack200 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}" PRIVATE ${ZLIB_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src")
-target_link_libraries(MultiMC_unpack200 ${ZLIB_LIBRARIES})
-
-set_target_properties(MultiMC_unpack200 PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN 1)
-generate_export_header(MultiMC_unpack200)
-
-# Install it
-install(
- TARGETS MultiMC_unpack200
- RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
- LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
-)
-
-if(PACK200_BUILD_BINARY)
- add_executable(anti200 anti200.cpp)
- target_link_libraries(anti200 MultiMC_unpack200)
-endif()
diff --git a/libraries/pack200/LICENSE b/libraries/pack200/LICENSE
deleted file mode 100644
index b40a0f45..00000000
--- a/libraries/pack200/LICENSE
+++ /dev/null
@@ -1,347 +0,0 @@
-The GNU General Public License (GPL)
-
-Version 2, June 1991
-
-Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-Everyone is permitted to copy and distribute verbatim copies of this license
-document, but changing it is not allowed.
-
-Preamble
-
-The licenses for most software are designed to take away your freedom to share
-and change it. By contrast, the GNU General Public License is intended to
-guarantee your freedom to share and change free software--to make sure the
-software is free for all its users. This General Public License applies to
-most of the Free Software Foundation's software and to any other program whose
-authors commit to using it. (Some other Free Software Foundation software is
-covered by the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
-When we speak of free software, we are referring to freedom, not price. Our
-General Public Licenses are designed to make sure that you have the freedom to
-distribute copies of free software (and charge for this service if you wish),
-that you receive source code or can get it if you want it, that you can change
-the software or use pieces of it in new free programs; and that you know you
-can do these things.
-
-To protect your rights, we need to make restrictions that forbid anyone to deny
-you these rights or to ask you to surrender the rights. These restrictions
-translate to certain responsibilities for you if you distribute copies of the
-software, or if you modify it.
-
-For example, if you distribute copies of such a program, whether gratis or for
-a fee, you must give the recipients all the rights that you have. You must
-make sure that they, too, receive or can get the source code. And you must
-show them these terms so they know their rights.
-
-We protect your rights with two steps: (1) copyright the software, and (2)
-offer you this license which gives you legal permission to copy, distribute
-and/or modify the software.
-
-Also, for each author's protection and ours, we want to make certain that
-everyone understands that there is no warranty for this free software. If the
-software is modified by someone else and passed on, we want its recipients to
-know that what they have is not the original, so that any problems introduced
-by others will not reflect on the original authors' reputations.
-
-Finally, any free program is threatened constantly by software patents. We
-wish to avoid the danger that redistributors of a free program will
-individually obtain patent licenses, in effect making the program proprietary.
-To prevent this, we have made it clear that any patent must be licensed for
-everyone's free use or not licensed at all.
-
-The precise terms and conditions for copying, distribution and modification
-follow.
-
-TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-0. This License applies to any program or other work which contains a notice
-placed by the copyright holder saying it may be distributed under the terms of
-this General Public License. The "Program", below, refers to any such program
-or work, and a "work based on the Program" means either the Program or any
-derivative work under copyright law: that is to say, a work containing the
-Program or a portion of it, either verbatim or with modifications and/or
-translated into another language. (Hereinafter, translation is included
-without limitation in the term "modification".) Each licensee is addressed as
-"you".
-
-Activities other than copying, distribution and modification are not covered by
-this License; they are outside its scope. The act of running the Program is
-not restricted, and the output from the Program is covered only if its contents
-constitute a work based on the Program (independent of having been made by
-running the Program). Whether that is true depends on what the Program does.
-
-1. You may copy and distribute verbatim copies of the Program's source code as
-you receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice and
-disclaimer of warranty; keep intact all the notices that refer to this License
-and to the absence of any warranty; and give any other recipients of the
-Program a copy of this License along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and you may
-at your option offer warranty protection in exchange for a fee.
-
-2. You may modify your copy or copies of the Program or any portion of it, thus
-forming a work based on the Program, and copy and distribute such modifications
-or work under the terms of Section 1 above, provided that you also meet all of
-these conditions:
-
- a) You must cause the modified files to carry prominent notices stating
- that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in whole or
- in part contains or is derived from the Program or any part thereof, to be
- licensed as a whole at no charge to all third parties under the terms of
- this License.
-
- c) If the modified program normally reads commands interactively when run,
- you must cause it, when started running for such interactive use in the
- most ordinary way, to print or display an announcement including an
- appropriate copyright notice and a notice that there is no warranty (or
- else, saying that you provide a warranty) and that users may redistribute
- the program under these conditions, and telling the user how to view a copy
- of this License. (Exception: if the Program itself is interactive but does
- not normally print such an announcement, your work based on the Program is
- not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If identifiable
-sections of that work are not derived from the Program, and can be reasonably
-considered independent and separate works in themselves, then this License, and
-its terms, do not apply to those sections when you distribute them as separate
-works. But when you distribute the same sections as part of a whole which is a
-work based on the Program, the distribution of the whole must be on the terms
-of this License, whose permissions for other licensees extend to the entire
-whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest your
-rights to work written entirely by you; rather, the intent is to exercise the
-right to control the distribution of derivative or collective works based on
-the Program.
-
-In addition, mere aggregation of another work not based on the Program with the
-Program (or with a work based on the Program) on a volume of a storage or
-distribution medium does not bring the other work under the scope of this
-License.
-
-3. You may copy and distribute the Program (or a work based on it, under
-Section 2) in object code or executable form under the terms of Sections 1 and
-2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable source
- code, which must be distributed under the terms of Sections 1 and 2 above
- on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three years, to
- give any third party, for a charge no more than your cost of physically
- performing source distribution, a complete machine-readable copy of the
- corresponding source code, to be distributed under the terms of Sections 1
- and 2 above on a medium customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer to
- distribute corresponding source code. (This alternative is allowed only
- for noncommercial distribution and only if you received the program in
- object code or executable form with such an offer, in accord with
- Subsection b above.)
-
-The source code for a work means the preferred form of the work for making
-modifications to it. For an executable work, complete source code means all
-the source code for all modules it contains, plus any associated interface
-definition files, plus the scripts used to control compilation and installation
-of the executable. However, as a special exception, the source code
-distributed need not include anything that is normally distributed (in either
-source or binary form) with the major components (compiler, kernel, and so on)
-of the operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the source
-code from the same place counts as distribution of the source code, even though
-third parties are not compelled to copy the source along with the object code.
-
-4. You may not copy, modify, sublicense, or distribute the Program except as
-expressly provided under this License. Any attempt otherwise to copy, modify,
-sublicense or distribute the Program is void, and will automatically terminate
-your rights under this License. However, parties who have received copies, or
-rights, from you under this License will not have their licenses terminated so
-long as such parties remain in full compliance.
-
-5. You are not required to accept this License, since you have not signed it.
-However, nothing else grants you permission to modify or distribute the Program
-or its derivative works. These actions are prohibited by law if you do not
-accept this License. Therefore, by modifying or distributing the Program (or
-any work based on the Program), you indicate your acceptance of this License to
-do so, and all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-6. Each time you redistribute the Program (or any work based on the Program),
-the recipient automatically receives a license from the original licensor to
-copy, distribute or modify the Program subject to these terms and conditions.
-You may not impose any further restrictions on the recipients' exercise of the
-rights granted herein. You are not responsible for enforcing compliance by
-third parties to this License.
-
-7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues), conditions
-are imposed on you (whether by court order, agreement or otherwise) that
-contradict the conditions of this License, they do not excuse you from the
-conditions of this License. If you cannot distribute so as to satisfy
-simultaneously your obligations under this License and any other pertinent
-obligations, then as a consequence you may not distribute the Program at all.
-For example, if a patent license would not permit royalty-free redistribution
-of the Program by all those who receive copies directly or indirectly through
-you, then the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply and
-the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any patents or
-other property right claims or to contest validity of any such claims; this
-section has the sole purpose of protecting the integrity of the free software
-distribution system, which is implemented by public license practices. Many
-people have made generous contributions to the wide range of software
-distributed through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing to
-distribute software through any other system and a licensee cannot impose that
-choice.
-
-This section is intended to make thoroughly clear what is believed to be a
-consequence of the rest of this License.
-
-8. If the distribution and/or use of the Program is restricted in certain
-countries either by patents or by copyrighted interfaces, the original
-copyright holder who places the Program under this License may add an explicit
-geographical distribution limitation excluding those countries, so that
-distribution is permitted only in or among countries not thus excluded. In
-such case, this License incorporates the limitation as if written in the body
-of this License.
-
-9. The Free Software Foundation may publish revised and/or new versions of the
-General Public License from time to time. Such new versions will be similar in
-spirit to the present version, but may differ in detail to address new problems
-or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any later
-version", you have the option of following the terms and conditions either of
-that version or of any later version published by the Free Software Foundation.
-If the Program does not specify a version number of this License, you may
-choose any version ever published by the Free Software Foundation.
-
-10. If you wish to incorporate parts of the Program into other free programs
-whose distribution conditions are different, write to the author to ask for
-permission. For software which is copyrighted by the Free Software Foundation,
-write to the Free Software Foundation; we sometimes make exceptions for this.
-Our decision will be guided by the two goals of preserving the free status of
-all derivatives of our free software and of promoting the sharing and reuse of
-software generally.
-
-NO WARRANTY
-
-11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
-THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
-STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
-PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
-INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
-PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
-YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
-ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
-PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
-INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
-BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
-OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-END OF TERMS AND CONDITIONS
-
-How to Apply These Terms to Your New Programs
-
-If you develop a new program, and you want it to be of the greatest possible
-use to the public, the best way to achieve this is to make it free software
-which everyone can redistribute and change under these terms.
-
-To do so, attach the following notices to the program. It is safest to attach
-them to the start of each source file to most effectively convey the exclusion
-of warranty; and each file should have at least the "copyright" line and a
-pointer to where the full notice is found.
-
- One line to give the program's name and a brief idea of what it does.
-
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc., 59
- Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this when it
-starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
- with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
- software, and you are welcome to redistribute it under certain conditions;
- type 'show c' for details.
-
-The hypothetical commands 'show w' and 'show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may be
-called something other than 'show w' and 'show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your school,
-if any, to sign a "copyright disclaimer" for the program, if necessary. Here
-is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- 'Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- signature of Ty Coon, 1 April 1989
-
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General Public
-License instead of this License.
-
-
-"CLASSPATH" EXCEPTION TO THE GPL
-
-Certain source files distributed by Oracle America and/or its affiliates are
-subject to the following clarification and special exception to the GPL, but
-only where Oracle has expressly included in the particular source file's header
-the words "Oracle designates this particular file as subject to the "Classpath"
-exception as provided by Oracle in the LICENSE file that accompanied this code."
-
- Linking this library statically or dynamically with other modules is making
- a combined work based on this library. Thus, the terms and conditions of
- the GNU General Public License cover the whole combination.
-
- As a special exception, the copyright holders of this library give you
- permission to link this library with independent modules to produce an
- executable, regardless of the license terms of these independent modules,
- and to copy and distribute the resulting executable under terms of your
- choice, provided that you also meet, for each linked independent module,
- the terms and conditions of the license of that module. An independent
- module is a module which is not derived from or based on this library. If
- you modify this library, you may extend this exception to your version of
- the library, but you are not obligated to do so. If you do not wish to do
- so, delete this exception statement from your version.
diff --git a/libraries/pack200/anti200.cpp b/libraries/pack200/anti200.cpp
deleted file mode 100644
index 1e672847..00000000
--- a/libraries/pack200/anti200.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This is trivial. Do what thou wilt with it. Public domain.
- */
-
-#include <stdexcept>
-#include <iostream>
-#include "unpack200.h"
-
-int main(int argc, char **argv)
-{
- if (argc != 3)
- {
- std::cerr << "Simple pack200 unpacker!" << std::endl << "Run like this:" << std::endl
- << " " << argv[0] << " input.jar.lzma output.jar" << std::endl;
- return EXIT_FAILURE;
- }
-
- FILE *input = fopen(argv[1], "rb");
- if (!input)
- {
- std::cerr << "Can't open input file";
- return EXIT_FAILURE;
- }
- FILE *output = fopen(argv[2], "wb");
- if (!output)
- {
- fclose(input);
- std::cerr << "Can't open output file";
- return EXIT_FAILURE;
- }
- try
- {
- unpack_200(input, output);
- }
- catch (const std::runtime_error &e)
- {
- std::cerr << "Bad things happened: " << e.what() << std::endl;
- fclose(input);
- fclose(output);
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
-}
diff --git a/libraries/pack200/include/unpack200.h b/libraries/pack200/include/unpack200.h
deleted file mode 100644
index 30ce6656..00000000
--- a/libraries/pack200/include/unpack200.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#pragma once
-
-#include "multimc_unpack200_export.h"
-
-/**
- * @brief Unpack a PACK200 file
- *
- * @param input_path Path to the input file in PACK200 format. System native string encoding.
- * @param output_path Path to the output file in PACK200 format. System native string encoding.
- * @throw std::runtime_error for any error encountered
- */
-MULTIMC_UNPACK200_EXPORT void unpack_200(FILE * input_path, FILE * output_path);
diff --git a/libraries/pack200/src/bands.cpp b/libraries/pack200/src/bands.cpp
deleted file mode 100644
index e82613b5..00000000
--- a/libraries/pack200/src/bands.cpp
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// -*- C++ -*-
-// Small program for unpacking specially compressed Java packages.
-// John R. Rose
-
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <stdint.h>
-
-#include "defines.h"
-#include "bytes.h"
-#include "utils.h"
-#include "coding.h"
-#include "bands.h"
-
-#include "constants.h"
-#include "unpack.h"
-
-void band::readData(int expectedLength)
-{
- assert(expectedLength >= 0);
- assert(vs[0].cmk == cmk_ERROR);
- if (expectedLength != 0)
- {
- assert(length == 0);
- length = expectedLength;
- }
- if (length == 0)
- {
- assert((rplimit = cm.vs0.rp = u->rp) != nullptr);
- return;
- }
- assert(length > 0);
-
- bool is_BYTE1 = (defc->spec == BYTE1_spec);
-
- if (is_BYTE1)
- {
- // No possibility of coding change. Sizing is exact.
- u->ensure_input(length);
- }
- else
- {
- // Make a conservatively generous estimate of band size in bytes.
- // Assume B == 5 everywhere.
- // Assume awkward pop with all {U} values (2*5 per value)
- int64_t generous = (int64_t)length * (B_MAX * 3 + 1) + C_SLOP;
- u->ensure_input(generous);
- }
-
- // Read one value to see what it might be.
- int XB = _meta_default;
- if (!is_BYTE1)
- {
- // must be a variable-length coding
- assert(defc->B() > 1 && defc->L() > 0);
-
- value_stream xvs;
- coding *valc = defc;
- if (valc->D() != 0)
- {
- valc = coding::findBySpec(defc->B(), defc->H(), defc->S());
- assert(!valc->isMalloc);
- }
- xvs.init(u->rp, u->rplimit, valc);
- int X = xvs.getInt();
- if (valc->S() != 0)
- {
- assert(valc->min <= -256);
- XB = -1 - X;
- }
- else
- {
- int L = valc->L();
- assert(valc->max >= L + 255);
- XB = X - L;
- }
- if (0 <= XB && XB < 256)
- {
- // Skip over the escape value.
- u->rp = xvs.rp;
- }
- else
- {
- // No, it's still default.
- XB = _meta_default;
- }
- }
-
- if (XB <= _meta_canon_max)
- {
- byte XB_byte = (byte)XB;
- byte *XB_ptr = &XB_byte;
- cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, nullptr);
- }
- else
- {
- assert(u->meta_rp != nullptr);
- // Scribble the initial byte onto the band.
- byte *save_meta_rp = --u->meta_rp;
- byte save_meta_xb = (*save_meta_rp);
- (*save_meta_rp) = (byte)XB;
- cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, nullptr);
- (*save_meta_rp) = save_meta_xb; // put it back, just to be tidy
- }
- rplimit = u->rp;
-
- rewind();
-}
-
-void band::setIndex(cpindex *ix_)
-{
- assert(ix_ == nullptr || ixTag == ix_->ixTag);
- ix = ix_;
-}
-void band::setIndexByTag(byte tag)
-{
- setIndex(u->cp.getIndex(tag));
-}
-
-entry *band::getRefCommon(cpindex *ix_, bool nullOKwithCaller)
-{
- assert(ix_->ixTag == ixTag ||
- (ixTag == CONSTANT_Literal && ix_->ixTag >= CONSTANT_Integer &&
- ix_->ixTag <= CONSTANT_String));
- int n = vs[0].getInt() - nullOK;
- // Note: band-local nullOK means nullptr encodes as 0.
- // But nullOKwithCaller means caller is willing to tolerate a nullptr.
- entry *ref = ix_->get(n);
- if (ref == nullptr && !(nullOKwithCaller && n == -1))
- unpack_abort(n == -1 ? "nullptr ref" : "bad ref");
- return ref;
-}
-
-int64_t band::getLong(band &lo_band, bool have_hi)
-{
- band &hi_band = (*this);
- assert(lo_band.bn == hi_band.bn + 1);
- uint32_t lo = lo_band.getInt();
- if (!have_hi)
- {
- assert(hi_band.length == 0);
- return makeLong(0, lo);
- }
- uint32_t hi = hi_band.getInt();
- return makeLong(hi, lo);
-}
-
-int band::getIntTotal()
-{
- if (length == 0)
- return 0;
- if (total_memo > 0)
- return total_memo - 1;
- int total = getInt();
- // overflow checks require that none of the addends are <0,
- // and that the partial sums never overflow (wrap negative)
- if (total < 0)
- {
- unpack_abort("overflow detected");
- }
- for (int k = length - 1; k > 0; k--)
- {
- int prev_total = total;
- total += vs[0].getInt();
- if (total < prev_total)
- {
- unpack_abort("overflow detected");
- }
- }
- rewind();
- total_memo = total + 1;
- return total;
-}
-
-int band::getIntCount(int tag)
-{
- if (length == 0)
- return 0;
- if (tag >= HIST0_MIN && tag <= HIST0_MAX)
- {
- if (hist0 == nullptr)
- {
- // Lazily calculate an approximate histogram.
- hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN) + 1);
- for (int k = length; k > 0; k--)
- {
- int x = vs[0].getInt();
- if (x >= HIST0_MIN && x <= HIST0_MAX)
- hist0[x - HIST0_MIN] += 1;
- }
- rewind();
- }
- return hist0[tag - HIST0_MIN];
- }
- int total = 0;
- for (int k = length; k > 0; k--)
- {
- total += (vs[0].getInt() == tag) ? 1 : 0;
- }
- rewind();
- return total;
-}
-
-#define INDEX_INIT(tag, nullOK, subindex) ((tag) + (subindex) * SUBINDEX_BIT + (nullOK) * 256)
-
-#define INDEX(tag) INDEX_INIT(tag, 0, 0)
-#define NULL_OR_INDEX(tag) INDEX_INIT(tag, 1, 0)
-#define SUB_INDEX(tag) INDEX_INIT(tag, 0, 1)
-#define NO_INDEX 0
-
-struct band_init
-{
- int defc;
- int index;
-};
-
-#define BAND_INIT(name, cspec, ix) \
- { \
- cspec, ix \
- }
-
-const band_init all_band_inits[] =
- {
- // BAND_INIT(archive_magic, BYTE1_spec, 0),
- // BAND_INIT(archive_header, UNSIGNED5_spec, 0),
- // BAND_INIT(band_headers, BYTE1_spec, 0),
- BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0),
- BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0),
- BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), BAND_INIT(cp_Int, UDELTA5_spec, 0),
- BAND_INIT(cp_Float, UDELTA5_spec, 0), BAND_INIT(cp_Long_hi, UDELTA5_spec, 0),
- BAND_INIT(cp_Long_lo, DELTA5_spec, 0), BAND_INIT(cp_Double_hi, UDELTA5_spec, 0),
- BAND_INIT(cp_Double_lo, DELTA5_spec, 0),
- BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(attr_definition_headers, BYTE1_spec, 0),
- BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(ic_flags, UNSIGNED5_spec, 0),
- BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)),
- BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
- BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_interface_count, DELTA5_spec, 0),
- BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_field_count, DELTA5_spec, 0),
- BAND_INIT(class_method_count, DELTA5_spec, 0),
- BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0),
- BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0),
- BAND_INIT(field_attr_count, UNSIGNED5_spec, 0),
- BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0),
- BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0),
- BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)),
- BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1),
- BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)),
- BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0),
- BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0),
- BAND_INIT(method_attr_count, UNSIGNED5_spec, 0),
- BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0),
- BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0),
- BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0),
- BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_attr_bands, -1, -1),
- BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0),
- BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0),
- BAND_INIT(class_attr_count, UNSIGNED5_spec, 0),
- BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0),
- BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0),
- BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
- BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec,
- NULL_OR_INDEX(CONSTANT_NameandType)),
- BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(class_metadata_bands, -1, -1),
- BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0),
- BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0),
- BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
- BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
- BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0),
- BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0),
- BAND_INIT(class_attr_bands, -1, -1), BAND_INIT(code_headers, BYTE1_spec, 0),
- BAND_INIT(code_max_stack, UNSIGNED5_spec, 0),
- BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0),
- BAND_INIT(code_handler_count, UNSIGNED5_spec, 0),
- BAND_INIT(code_handler_start_P, BCI5_spec, 0),
- BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0),
- BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0),
- BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
- BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0),
- BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0),
- BAND_INIT(code_attr_count, UNSIGNED5_spec, 0),
- BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0),
- BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0),
- BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0),
- BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0),
- BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
- BAND_INIT(code_StackMapTable_P, BCI5_spec, 0),
- BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0),
- BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0),
- BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0),
- BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0),
- BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
- BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0),
- BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0),
- BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0),
- BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0),
- BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec,
- INDEX(CONSTANT_Signature)),
- BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0),
- BAND_INIT(code_attr_bands, -1, -1), BAND_INIT(bc_codes, BYTE1_spec, 0),
- BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), BAND_INIT(bc_case_value, DELTA5_spec, 0),
- BAND_INIT(bc_byte, BYTE1_spec, 0), BAND_INIT(bc_short, DELTA5_spec, 0),
- BAND_INIT(bc_local, UNSIGNED5_spec, 0), BAND_INIT(bc_label, BRANCH5_spec, 0),
- BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)),
- BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)),
- BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)),
- BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)),
- BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)),
- BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
- BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)),
- BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)),
- BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)),
- BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
- BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
- BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
- BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
- BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
- BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)),
- BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), BAND_INIT(bc_escsize, UNSIGNED5_spec, 0),
- BAND_INIT(bc_escbyte, BYTE1_spec, 0),
- BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
- BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), BAND_INIT(file_size_lo, UNSIGNED5_spec, 0),
- BAND_INIT(file_modtime, DELTA5_spec, 0), BAND_INIT(file_options, UNSIGNED5_spec, 0),
- // BAND_INIT(file_bits, BYTE1_spec, 0),
- {0, 0}};
-
-band *band::makeBands(unpacker *u)
-{
- band *tmp_all_bands = U_NEW(band, BAND_LIMIT);
- for (int i = 0; i < BAND_LIMIT; i++)
- {
- assert((byte *)&all_band_inits[i + 1] <
- (byte *)all_band_inits + sizeof(all_band_inits));
- const band_init &bi = all_band_inits[i];
- band &b = tmp_all_bands[i];
- coding *defc = coding::findBySpec(bi.defc);
- assert((defc == nullptr) == (bi.defc == -1)); // no garbage, please
- assert(defc == nullptr || !defc->isMalloc);
- b.init(u, i, defc);
- if (bi.index > 0)
- {
- b.nullOK = ((bi.index >> 8) & 1);
- b.ixTag = (bi.index & 0xFF);
- }
- }
- return tmp_all_bands;
-}
-
-void band::initIndexes(unpacker *u)
-{
- band *tmp_all_bands = u->all_bands;
- for (int i = 0; i < BAND_LIMIT; i++)
- {
- band *scan = &tmp_all_bands[i];
- uint32_t tag = scan->ixTag; // Cf. #define INDEX(tag) above
- if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
- {
- scan->setIndex(u->cp.getIndex(tag));
- }
- }
-}
diff --git a/libraries/pack200/src/bands.h b/libraries/pack200/src/bands.h
deleted file mode 100644
index 66c5aec4..00000000
--- a/libraries/pack200/src/bands.h
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// -*- C++ -*-
-struct entry;
-struct cpindex;
-struct unpacker;
-
-struct band
-{
- int bn; // band_number of this band
- coding *defc; // default coding method
- cpindex *ix; // CP entry mapping, if CPRefBand
- byte ixTag; // 0 or 1; nullptr is coded as (nullOK?0:-1)
- byte nullOK; // 0 or 1; nullptr is coded as (nullOK?0:-1)
- int length; // expected # values
- unpacker *u; // back pointer
-
- value_stream vs[2]; // source of values
- coding_method cm; // method used for initial state of vs[0]
- byte *rplimit; // end of band (encoded, transmitted)
-
- int total_memo; // cached value of getIntTotal, or -1
- int *hist0; // approximate. histogram
- enum
- {
- HIST0_MIN = 0,
- HIST0_MAX = 255
- }; // catches the usual cases
-
- // properties for attribute layout elements:
- byte le_kind; // EK_XXX
- byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO
- byte le_back; // ==EF_BACK
- byte le_len; // 0,1,2,4 (size in classfile), or call addr
- band **le_body; // body of repl, union, call (nullptr-terminated)
-// Note: EK_CASE elements use hist0 to record union tags.
-#define le_casetags hist0
-
- band &nextBand()
- {
- return this[1];
- }
- band &prevBand()
- {
- return this[-1];
- }
-
- void init(unpacker *u_, int bn_, coding *defc_)
- {
- u = u_;
- cm.u = u_;
- bn = bn_;
- defc = defc_;
- }
- void init(unpacker *u_, int bn_, int defcSpec)
- {
- init(u_, bn_, coding::findBySpec(defcSpec));
- }
- void initRef(int ixTag_ = 0, bool nullOK_ = false)
- {
- ixTag = ixTag_;
- nullOK = nullOK_;
- setIndexByTag(ixTag);
- }
-
- void expectMoreLength(int l)
- {
- assert(length >= 0); // able to accept a length
- assert((int)l >= 0); // no overflow
- assert(rplimit == nullptr); // readData not yet called
- length += l;
- assert(length >= l); // no overflow
- }
-
- void setIndex(cpindex *ix_);
- void setIndexByTag(byte tag);
-
- // Parse the band and its meta-coding header.
- void readData(int expectedLength = 0);
-
- // Reset the band for another pass (Cf. Java Band.resetForSecondPass.)
- void rewind()
- {
- cm.reset(&vs[0]);
- }
-
- byte *&curRP()
- {
- return vs[0].rp;
- }
- byte *minRP()
- {
- return cm.vs0.rp;
- }
- byte *maxRP()
- {
- return rplimit;
- }
- size_t size()
- {
- return maxRP() - minRP();
- }
-
- int getByte()
- {
- assert(ix == nullptr);
- return vs[0].getByte();
- }
- int getInt()
- {
- assert(ix == nullptr);
- return vs[0].getInt();
- }
- entry *getRefN()
- {
- assert(ix != nullptr);
- return getRefCommon(ix, true);
- }
- entry *getRef()
- {
- assert(ix != nullptr);
- return getRefCommon(ix, false);
- }
- entry *getRefUsing(cpindex *ix2)
- {
- assert(ix == nullptr);
- return getRefCommon(ix2, true);
- }
- entry *getRefCommon(cpindex *ix, bool nullOK);
- int64_t getLong(band &lo_band, bool have_hi);
-
- static int64_t makeLong(uint32_t hi, uint32_t lo)
- {
- return ((uint64_t)hi << 32) + (((uint64_t)lo << 32) >> 32);
- }
-
- int getIntTotal();
- int getIntCount(int tag);
-
- static band *makeBands(unpacker *u);
- static void initIndexes(unpacker *u);
-};
-
-extern band all_bands[];
-
-#define BAND_LOCAL /* \
- band* band_temp = all_bands; \
- band* all_bands = band_temp */
-
-// Band schema:
-enum band_number
-{
- // e_archive_magic,
- // e_archive_header,
- // e_band_headers,
-
- // constant pool contents
- e_cp_Utf8_prefix,
- e_cp_Utf8_suffix,
- e_cp_Utf8_chars,
- e_cp_Utf8_big_suffix,
- e_cp_Utf8_big_chars,
- e_cp_Int,
- e_cp_Float,
- e_cp_Long_hi,
- e_cp_Long_lo,
- e_cp_Double_hi,
- e_cp_Double_lo,
- e_cp_String,
- e_cp_Class,
- e_cp_Signature_form,
- e_cp_Signature_classes,
- e_cp_Descr_name,
- e_cp_Descr_type,
- e_cp_Field_class,
- e_cp_Field_desc,
- e_cp_Method_class,
- e_cp_Method_desc,
- e_cp_Imethod_class,
- e_cp_Imethod_desc,
-
- // bands which define transmission of attributes
- e_attr_definition_headers,
- e_attr_definition_name,
- e_attr_definition_layout,
-
- // band for hardwired InnerClasses attribute (shared across the package)
- e_ic_this_class,
- e_ic_flags,
- // These bands contain data only where flags sets ACC_IC_LONG_FORM:
- e_ic_outer_class,
- e_ic_name,
-
- // bands for carrying class schema information:
- e_class_this,
- e_class_super,
- e_class_interface_count,
- e_class_interface,
-
- // bands for class members
- e_class_field_count,
- e_class_method_count,
- e_field_descr,
- e_field_flags_hi,
- e_field_flags_lo,
- e_field_attr_count,
- e_field_attr_indexes,
- e_field_attr_calls,
- e_field_ConstantValue_KQ,
- e_field_Signature_RS,
- e_field_metadata_bands,
- e_field_attr_bands,
- e_method_descr,
- e_method_flags_hi,
- e_method_flags_lo,
- e_method_attr_count,
- e_method_attr_indexes,
- e_method_attr_calls,
- e_method_Exceptions_N,
- e_method_Exceptions_RC,
- e_method_Signature_RS,
- e_method_metadata_bands,
- e_method_attr_bands,
- e_class_flags_hi,
- e_class_flags_lo,
- e_class_attr_count,
- e_class_attr_indexes,
- e_class_attr_calls,
- e_class_SourceFile_RUN,
- e_class_EnclosingMethod_RC,
- e_class_EnclosingMethod_RDN,
- e_class_Signature_RS,
- e_class_metadata_bands,
- e_class_InnerClasses_N,
- e_class_InnerClasses_RC,
- e_class_InnerClasses_F,
- e_class_InnerClasses_outer_RCN,
- e_class_InnerClasses_name_RUN,
- e_class_ClassFile_version_minor_H,
- e_class_ClassFile_version_major_H,
- e_class_attr_bands,
- e_code_headers,
- e_code_max_stack,
- e_code_max_na_locals,
- e_code_handler_count,
- e_code_handler_start_P,
- e_code_handler_end_PO,
- e_code_handler_catch_PO,
- e_code_handler_class_RCN,
-
- // code attributes
- e_code_flags_hi,
- e_code_flags_lo,
- e_code_attr_count,
- e_code_attr_indexes,
- e_code_attr_calls,
- e_code_StackMapTable_N,
- e_code_StackMapTable_frame_T,
- e_code_StackMapTable_local_N,
- e_code_StackMapTable_stack_N,
- e_code_StackMapTable_offset,
- e_code_StackMapTable_T,
- e_code_StackMapTable_RC,
- e_code_StackMapTable_P,
- e_code_LineNumberTable_N,
- e_code_LineNumberTable_bci_P,
- e_code_LineNumberTable_line,
- e_code_LocalVariableTable_N,
- e_code_LocalVariableTable_bci_P,
- e_code_LocalVariableTable_span_O,
- e_code_LocalVariableTable_name_RU,
- e_code_LocalVariableTable_type_RS,
- e_code_LocalVariableTable_slot,
- e_code_LocalVariableTypeTable_N,
- e_code_LocalVariableTypeTable_bci_P,
- e_code_LocalVariableTypeTable_span_O,
- e_code_LocalVariableTypeTable_name_RU,
- e_code_LocalVariableTypeTable_type_RS,
- e_code_LocalVariableTypeTable_slot,
- e_code_attr_bands,
-
- // bands for bytecodes
- e_bc_codes,
- // remaining bands provide typed opcode fields required by the bc_codes
- e_bc_case_count,
- e_bc_case_value,
- e_bc_byte,
- e_bc_short,
- e_bc_local,
- e_bc_label,
-
- // ldc* operands:
- e_bc_intref,
- e_bc_floatref,
- e_bc_longref,
- e_bc_doubleref,
- e_bc_stringref,
- e_bc_classref,
- e_bc_fieldref,
- e_bc_methodref,
- e_bc_imethodref,
-
- // _self_linker_op family
- e_bc_thisfield,
- e_bc_superfield,
- e_bc_thismethod,
- e_bc_supermethod,
-
- // bc_invokeinit family:
- e_bc_initref,
-
- // bytecode escape sequences
- e_bc_escref,
- e_bc_escrefsize,
- e_bc_escsize,
- e_bc_escbyte,
-
- // file attributes and contents
- e_file_name,
- e_file_size_hi,
- e_file_size_lo,
- e_file_modtime,
- e_file_options,
- // e_file_bits, // handled specially as an appendix
- BAND_LIMIT
-};
-
-// Symbolic names for bands, as if in a giant global struct:
-//#define archive_magic all_bands[e_archive_magic]
-//#define archive_header all_bands[e_archive_header]
-//#define band_headers all_bands[e_band_headers]
-#define cp_Utf8_prefix all_bands[e_cp_Utf8_prefix]
-#define cp_Utf8_suffix all_bands[e_cp_Utf8_suffix]
-#define cp_Utf8_chars all_bands[e_cp_Utf8_chars]
-#define cp_Utf8_big_suffix all_bands[e_cp_Utf8_big_suffix]
-#define cp_Utf8_big_chars all_bands[e_cp_Utf8_big_chars]
-#define cp_Int all_bands[e_cp_Int]
-#define cp_Float all_bands[e_cp_Float]
-#define cp_Long_hi all_bands[e_cp_Long_hi]
-#define cp_Long_lo all_bands[e_cp_Long_lo]
-#define cp_Double_hi all_bands[e_cp_Double_hi]
-#define cp_Double_lo all_bands[e_cp_Double_lo]
-#define cp_String all_bands[e_cp_String]
-#define cp_Class all_bands[e_cp_Class]
-#define cp_Signature_form all_bands[e_cp_Signature_form]
-#define cp_Signature_classes all_bands[e_cp_Signature_classes]
-#define cp_Descr_name all_bands[e_cp_Descr_name]
-#define cp_Descr_type all_bands[e_cp_Descr_type]
-#define cp_Field_class all_bands[e_cp_Field_class]
-#define cp_Field_desc all_bands[e_cp_Field_desc]
-#define cp_Method_class all_bands[e_cp_Method_class]
-#define cp_Method_desc all_bands[e_cp_Method_desc]
-#define cp_Imethod_class all_bands[e_cp_Imethod_class]
-#define cp_Imethod_desc all_bands[e_cp_Imethod_desc]
-#define attr_definition_headers all_bands[e_attr_definition_headers]
-#define attr_definition_name all_bands[e_attr_definition_name]
-#define attr_definition_layout all_bands[e_attr_definition_layout]
-#define ic_this_class all_bands[e_ic_this_class]
-#define ic_flags all_bands[e_ic_flags]
-#define ic_outer_class all_bands[e_ic_outer_class]
-#define ic_name all_bands[e_ic_name]
-#define class_this all_bands[e_class_this]
-#define class_super all_bands[e_class_super]
-#define class_interface_count all_bands[e_class_interface_count]
-#define class_interface all_bands[e_class_interface]
-#define class_field_count all_bands[e_class_field_count]
-#define class_method_count all_bands[e_class_method_count]
-#define field_descr all_bands[e_field_descr]
-#define field_flags_hi all_bands[e_field_flags_hi]
-#define field_flags_lo all_bands[e_field_flags_lo]
-#define field_attr_count all_bands[e_field_attr_count]
-#define field_attr_indexes all_bands[e_field_attr_indexes]
-#define field_ConstantValue_KQ all_bands[e_field_ConstantValue_KQ]
-#define field_Signature_RS all_bands[e_field_Signature_RS]
-#define field_attr_bands all_bands[e_field_attr_bands]
-#define method_descr all_bands[e_method_descr]
-#define method_flags_hi all_bands[e_method_flags_hi]
-#define method_flags_lo all_bands[e_method_flags_lo]
-#define method_attr_count all_bands[e_method_attr_count]
-#define method_attr_indexes all_bands[e_method_attr_indexes]
-#define method_Exceptions_N all_bands[e_method_Exceptions_N]
-#define method_Exceptions_RC all_bands[e_method_Exceptions_RC]
-#define method_Signature_RS all_bands[e_method_Signature_RS]
-#define method_attr_bands all_bands[e_method_attr_bands]
-#define class_flags_hi all_bands[e_class_flags_hi]
-#define class_flags_lo all_bands[e_class_flags_lo]
-#define class_attr_count all_bands[e_class_attr_count]
-#define class_attr_indexes all_bands[e_class_attr_indexes]
-#define class_SourceFile_RUN all_bands[e_class_SourceFile_RUN]
-#define class_EnclosingMethod_RC all_bands[e_class_EnclosingMethod_RC]
-#define class_EnclosingMethod_RDN all_bands[e_class_EnclosingMethod_RDN]
-#define class_Signature_RS all_bands[e_class_Signature_RS]
-#define class_InnerClasses_N all_bands[e_class_InnerClasses_N]
-#define class_InnerClasses_RC all_bands[e_class_InnerClasses_RC]
-#define class_InnerClasses_F all_bands[e_class_InnerClasses_F]
-#define class_InnerClasses_outer_RCN all_bands[e_class_InnerClasses_outer_RCN]
-#define class_InnerClasses_name_RUN all_bands[e_class_InnerClasses_name_RUN]
-#define class_ClassFile_version_minor_H all_bands[e_class_ClassFile_version_minor_H]
-#define class_ClassFile_version_major_H all_bands[e_class_ClassFile_version_major_H]
-#define class_attr_bands all_bands[e_class_attr_bands]
-#define code_headers all_bands[e_code_headers]
-#define code_max_stack all_bands[e_code_max_stack]
-#define code_max_na_locals all_bands[e_code_max_na_locals]
-#define code_handler_count all_bands[e_code_handler_count]
-#define code_handler_start_P all_bands[e_code_handler_start_P]
-#define code_handler_end_PO all_bands[e_code_handler_end_PO]
-#define code_handler_catch_PO all_bands[e_code_handler_catch_PO]
-#define code_handler_class_RCN all_bands[e_code_handler_class_RCN]
-#define code_flags_hi all_bands[e_code_flags_hi]
-#define code_flags_lo all_bands[e_code_flags_lo]
-#define code_attr_count all_bands[e_code_attr_count]
-#define code_attr_indexes all_bands[e_code_attr_indexes]
-#define code_StackMapTable_N all_bands[e_code_StackMapTable_N]
-#define code_StackMapTable_frame_T all_bands[e_code_StackMapTable_frame_T]
-#define code_StackMapTable_local_N all_bands[e_code_StackMapTable_local_N]
-#define code_StackMapTable_stack_N all_bands[e_code_StackMapTable_stack_N]
-#define code_StackMapTable_offset all_bands[e_code_StackMapTable_offset]
-#define code_StackMapTable_T all_bands[e_code_StackMapTable_T]
-#define code_StackMapTable_RC all_bands[e_code_StackMapTable_RC]
-#define code_StackMapTable_P all_bands[e_code_StackMapTable_P]
-#define code_LineNumberTable_N all_bands[e_code_LineNumberTable_N]
-#define code_LineNumberTable_bci_P all_bands[e_code_LineNumberTable_bci_P]
-#define code_LineNumberTable_line all_bands[e_code_LineNumberTable_line]
-#define code_LocalVariableTable_N all_bands[e_code_LocalVariableTable_N]
-#define code_LocalVariableTable_bci_P all_bands[e_code_LocalVariableTable_bci_P]
-#define code_LocalVariableTable_span_O all_bands[e_code_LocalVariableTable_span_O]
-#define code_LocalVariableTable_name_RU all_bands[e_code_LocalVariableTable_name_RU]
-#define code_LocalVariableTable_type_RS all_bands[e_code_LocalVariableTable_type_RS]
-#define code_LocalVariableTable_slot all_bands[e_code_LocalVariableTable_slot]
-#define code_LocalVariableTypeTable_N all_bands[e_code_LocalVariableTypeTable_N]
-#define code_LocalVariableTypeTable_bci_P all_bands[e_code_LocalVariableTypeTable_bci_P]
-#define code_LocalVariableTypeTable_span_O all_bands[e_code_LocalVariableTypeTable_span_O]
-#define code_LocalVariableTypeTable_name_RU all_bands[e_code_LocalVariableTypeTable_name_RU]
-#define code_LocalVariableTypeTable_type_RS all_bands[e_code_LocalVariableTypeTable_type_RS]
-#define code_LocalVariableTypeTable_slot all_bands[e_code_LocalVariableTypeTable_slot]
-#define code_attr_bands all_bands[e_code_attr_bands]
-#define bc_codes all_bands[e_bc_codes]
-#define bc_case_count all_bands[e_bc_case_count]
-#define bc_case_value all_bands[e_bc_case_value]
-#define bc_byte all_bands[e_bc_byte]
-#define bc_short all_bands[e_bc_short]
-#define bc_local all_bands[e_bc_local]
-#define bc_label all_bands[e_bc_label]
-#define bc_intref all_bands[e_bc_intref]
-#define bc_floatref all_bands[e_bc_floatref]
-#define bc_longref all_bands[e_bc_longref]
-#define bc_doubleref all_bands[e_bc_doubleref]
-#define bc_stringref all_bands[e_bc_stringref]
-#define bc_classref all_bands[e_bc_classref]
-#define bc_fieldref all_bands[e_bc_fieldref]
-#define bc_methodref all_bands[e_bc_methodref]
-#define bc_imethodref all_bands[e_bc_imethodref]
-#define bc_thisfield all_bands[e_bc_thisfield]
-#define bc_superfield all_bands[e_bc_superfield]
-#define bc_thismethod all_bands[e_bc_thismethod]
-#define bc_supermethod all_bands[e_bc_supermethod]
-#define bc_initref all_bands[e_bc_initref]
-#define bc_escref all_bands[e_bc_escref]
-#define bc_escrefsize all_bands[e_bc_escrefsize]
-#define bc_escsize all_bands[e_bc_escsize]
-#define bc_escbyte all_bands[e_bc_escbyte]
-#define file_name all_bands[e_file_name]
-#define file_size_hi all_bands[e_file_size_hi]
-#define file_size_lo all_bands[e_file_size_lo]
-#define file_modtime all_bands[e_file_modtime]
-#define file_options all_bands[e_file_options]
diff --git a/libraries/pack200/src/bytes.cpp b/libraries/pack200/src/bytes.cpp
deleted file mode 100644
index 767fe0a5..00000000
--- a/libraries/pack200/src/bytes.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdint.h>
-#include "defines.h"
-#include "bytes.h"
-#include "utils.h"
-
-static byte dummy[1 << 10];
-
-bool bytes::inBounds(const void *p)
-{
- return p >= ptr && p < limit();
-}
-
-void bytes::malloc(size_t len_)
-{
- len = len_;
- ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always
- if (ptr == nullptr)
- {
- // set ptr to some victim memory, to ease escape
- set(dummy, sizeof(dummy) - 1);
- unpack_abort(ERROR_ENOMEM);
- }
-}
-
-void bytes::realloc(size_t len_)
-{
- if (len == len_)
- return; // nothing to do
- if (ptr == dummy)
- return; // escaping from an error
- if (ptr == nullptr)
- {
- malloc(len_);
- return;
- }
- byte *oldptr = ptr;
- ptr = (len_ >= PSIZE_MAX) ? nullptr : (byte *)::realloc(ptr, add_size(len_, 1));
- if (ptr != nullptr)
- {
- if (len < len_)
- memset(ptr + len, 0, len_ - len);
- ptr[len_] = 0;
- len = len_;
- }
- else
- {
- ptr = oldptr; // ease our escape
- unpack_abort(ERROR_ENOMEM);
- }
-}
-
-void bytes::free()
-{
- if (ptr == dummy)
- return; // escaping from an error
- if (ptr != nullptr)
- {
- ::free(ptr);
- }
- len = 0;
- ptr = 0;
-}
-
-int bytes::indexOf(byte c)
-{
- byte *p = (byte *)memchr(ptr, c, len);
- return (p == 0) ? -1 : (int)(p - ptr);
-}
-
-byte *bytes::writeTo(byte *bp)
-{
- memcpy(bp, ptr, len);
- return bp + len;
-}
-
-int bytes::compareTo(bytes &other)
-{
- size_t l1 = len;
- size_t l2 = other.len;
- int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2);
- if (cmp != 0)
- return cmp;
- return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
-}
-
-void bytes::saveFrom(const void *ptr_, size_t len_)
-{
- malloc(len_);
- // Save as much as possible.
- if (len_ > len)
- {
- assert(ptr == dummy); // error recovery
- len_ = len;
- }
- copyFrom(ptr_, len_);
-}
-
-//#TODO: Need to fix for exception handling
-void bytes::copyFrom(const void *ptr_, size_t len_, size_t offset)
-{
- assert(len_ == 0 || inBounds(ptr + offset));
- assert(len_ == 0 || inBounds(ptr + offset + len_ - 1));
- memcpy(ptr + offset, ptr_, len_);
-}
-
-// Make sure there are 'o' bytes beyond the fill pointer,
-// advance the fill pointer, and return the old fill pointer.
-byte *fillbytes::grow(size_t s)
-{
- size_t nlen = add_size(b.len, s);
- if (nlen <= allocated)
- {
- b.len = nlen;
- return limit() - s;
- }
- size_t maxlen = nlen;
- if (maxlen < 128)
- maxlen = 128;
- if (maxlen < allocated * 2)
- maxlen = allocated * 2;
- if (allocated == 0)
- {
- // Initial buffer was not malloced. Do not reallocate it.
- bytes old = b;
- b.malloc(maxlen);
- if (b.len == maxlen)
- old.writeTo(b.ptr);
- }
- else
- {
- b.realloc(maxlen);
- }
- allocated = b.len;
- if (allocated != maxlen)
- {
- b.len = nlen - s; // back up
- return dummy; // scribble during error recov.
- }
- // after realloc, recompute pointers
- b.len = nlen;
- assert(b.len <= allocated);
- return limit() - s;
-}
-
-void fillbytes::ensureSize(size_t s)
-{
- if (allocated >= s)
- return;
- size_t len0 = b.len;
- grow(s - size());
- b.len = len0; // put it back
-}
-
-int ptrlist::indexOf(const void *x)
-{
- int len = length();
- for (int i = 0; i < len; i++)
- {
- if (get(i) == x)
- return i;
- }
- return -1;
-}
-
-void ptrlist::freeAll()
-{
- int len = length();
- for (int i = 0; i < len; i++)
- {
- void *p = (void *)get(i);
- if (p != nullptr)
- {
- ::free(p);
- }
- }
- free();
-}
-
-int intlist::indexOf(int x)
-{
- int len = length();
- for (int i = 0; i < len; i++)
- {
- if (get(i) == x)
- return i;
- }
- return -1;
-}
diff --git a/libraries/pack200/src/bytes.h b/libraries/pack200/src/bytes.h
deleted file mode 100644
index 2ce1f7f4..00000000
--- a/libraries/pack200/src/bytes.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#pragma once
-
-struct bytes
-{
- int8_t *ptr;
- size_t len;
- int8_t *limit()
- {
- return ptr + len;
- }
-
- void set(int8_t *ptr_, size_t len_)
- {
- ptr = ptr_;
- len = len_;
- }
- void set(const char *str)
- {
- ptr = (int8_t *)str;
- len = strlen(str);
- }
- bool inBounds(const void *p); // p in [ptr, limit)
- void malloc(size_t len_);
- void realloc(size_t len_);
- void free();
- void copyFrom(const void *ptr_, size_t len_, size_t offset = 0);
- void saveFrom(const void *ptr_, size_t len_);
- void saveFrom(const char *str)
- {
- saveFrom(str, strlen(str));
- }
- void copyFrom(bytes &other, size_t offset = 0)
- {
- copyFrom(other.ptr, other.len, offset);
- }
- void saveFrom(bytes &other)
- {
- saveFrom(other.ptr, other.len);
- }
- void clear(int fill_byte = 0)
- {
- memset(ptr, fill_byte, len);
- }
- int8_t *writeTo(int8_t *bp);
- bool equals(bytes &other)
- {
- return 0 == compareTo(other);
- }
- int compareTo(bytes &other);
- bool contains(int8_t c)
- {
- return indexOf(c) >= 0;
- }
- int indexOf(int8_t c);
- // substrings:
- static bytes of(int8_t *ptr, size_t len)
- {
- bytes res;
- res.set(ptr, len);
- return res;
- }
- bytes slice(size_t beg, size_t end)
- {
- bytes res;
- res.ptr = ptr + beg;
- res.len = end - beg;
- assert(res.len == 0 ||(inBounds(res.ptr) && inBounds(res.limit() - 1)));
- return res;
- }
- // building C strings inside byte buffers:
- bytes &strcat(const char *str)
- {
- ::strcat((char *)ptr, str);
- return *this;
- }
- bytes &strcat(bytes &other)
- {
- ::strncat((char *)ptr, (char *)other.ptr, other.len);
- return *this;
- }
- char *strval()
- {
- assert(strlen((char *)ptr) == len);
- return (char *)ptr;
- }
-};
-#define BYTES_OF(var) (bytes::of((int8_t *)&(var), sizeof(var)))
-
-struct fillbytes
-{
- bytes b;
- size_t allocated;
-
- int8_t *base()
- {
- return b.ptr;
- }
- size_t size()
- {
- return b.len;
- }
- int8_t *limit()
- {
- return b.limit();
- } // logical limit
- void setLimit(int8_t *lp)
- {
- assert(isAllocated(lp));
- b.len = lp - b.ptr;
- }
- int8_t *end()
- {
- return b.ptr + allocated;
- } // physical limit
- int8_t *loc(size_t o)
- {
- assert(o < b.len);
- return b.ptr + o;
- }
- void init()
- {
- allocated = 0;
- b.set(nullptr, 0);
- }
- void init(size_t s)
- {
- init();
- ensureSize(s);
- }
- void free()
- {
- if (allocated != 0)
- b.free();
- allocated = 0;
- }
- void empty()
- {
- b.len = 0;
- }
- int8_t *grow(size_t s); // grow so that limit() += s
- int getByte(uint32_t i)
- {
- return *loc(i) & 0xFF;
- }
- void addByte(int8_t x)
- {
- *grow(1) = x;
- }
- void ensureSize(size_t s); // make sure allocated >= s
- void trimToSize()
- {
- if (allocated > size())
- b.realloc(allocated = size());
- }
- bool canAppend(size_t s)
- {
- return allocated > b.len + s;
- }
- bool isAllocated(int8_t *p)
- {
- return p >= base() && p <= end();
- } // asserts
- void set(bytes &src)
- {
- set(src.ptr, src.len);
- }
-
- void set(int8_t *ptr, size_t len)
- {
- b.set(ptr, len);
- allocated = 0; // mark as not reallocatable
- }
-
- // block operations on resizing byte buffer:
- fillbytes &append(const void *ptr_, size_t len_)
- {
- memcpy(grow(len_), ptr_, len_);
- return (*this);
- }
- fillbytes &append(bytes &other)
- {
- return append(other.ptr, other.len);
- }
- fillbytes &append(const char *str)
- {
- return append(str, strlen(str));
- }
-};
-
-struct ptrlist : fillbytes
-{
- typedef const void *cvptr;
- int length()
- {
- return (int)(size() / sizeof(cvptr));
- }
- cvptr *base()
- {
- return (cvptr *)fillbytes::base();
- }
- cvptr &get(int i)
- {
- return *(cvptr *)loc(i * sizeof(cvptr));
- }
- cvptr *limit()
- {
- return (cvptr *)fillbytes::limit();
- }
- void add(cvptr x)
- {
- *(cvptr *)grow(sizeof(x)) = x;
- }
- void popTo(int l)
- {
- assert(l <= length());
- b.len = l * sizeof(cvptr);
- }
- int indexOf(cvptr x);
- bool contains(cvptr x)
- {
- return indexOf(x) >= 0;
- }
- void freeAll(); // frees every ptr on the list, plus the list itself
-};
-// Use a macro rather than mess with subtle mismatches
-// between member and non-member function pointers.
-#define PTRLIST_QSORT(ptrls, fn) ::qsort((ptrls).base(), (ptrls).length(), sizeof(void *), fn)
-
-struct intlist : fillbytes
-{
- int length()
- {
- return (int)(size() / sizeof(int));
- }
- int *base()
- {
- return (int *)fillbytes::base();
- }
- int &get(int i)
- {
- return *(int *)loc(i * sizeof(int));
- }
- int *limit()
- {
- return (int *)fillbytes::limit();
- }
- void add(int x)
- {
- *(int *)grow(sizeof(x)) = x;
- }
- void popTo(int l)
- {
- assert(l <= length());
- b.len = l * sizeof(int);
- }
- int indexOf(int x);
- bool contains(int x)
- {
- return indexOf(x) >= 0;
- }
-};
diff --git a/libraries/pack200/src/coding.cpp b/libraries/pack200/src/coding.cpp
deleted file mode 100644
index 8e872013..00000000
--- a/libraries/pack200/src/coding.cpp
+++ /dev/null
@@ -1,1044 +0,0 @@
-/*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// -*- C++ -*-
-// Small program for unpacking specially compressed Java packages.
-// John R. Rose
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <stdint.h>
-
-#include "defines.h"
-#include "bytes.h"
-#include "utils.h"
-#include "coding.h"
-
-#include "constants.h"
-#include "unpack.h"
-
-extern coding basic_codings[];
-
-// CODING_PRIVATE causes a lot of them
-#pragma GCC diagnostic ignored "-Wunused-variable"
-
-#define CODING_PRIVATE(spec) \
- int spec_ = spec; \
- int B = CODING_B(spec_); \
- int H = CODING_H(spec_); \
- int L = 256 - H; \
- int S = CODING_S(spec_); \
- int D = CODING_D(spec_)
-
-#define IS_NEG_CODE(S, codeVal) ((((int)(codeVal) + 1) & ((1 << S) - 1)) == 0)
-
-#define DECODE_SIGN_S1(ux) (((uint32_t)(ux) >> 1) ^ -((int)(ux) & 1))
-
-static int decode_sign(int S, uint32_t ux)
-{ // == Coding.decodeSign32
- assert(S > 0);
- uint32_t sigbits = (ux >> S);
- if (IS_NEG_CODE(S, ux))
- return (int)(~sigbits);
- else
- return (int)(ux - sigbits);
- // Note that (int)(ux-sigbits) can be negative, if ux is large enough.
-}
-
-coding *coding::init()
-{
- if (umax > 0)
- return this; // already done
- assert(spec != 0); // sanity
-
- // fill in derived fields
- CODING_PRIVATE(spec);
-
- // Return nullptr if 'arb(BHSD)' parameter constraints are not met:
- if (B < 1 || B > B_MAX)
- return nullptr;
- if (H < 1 || H > 256)
- return nullptr;
- if (S < 0 || S > 2)
- return nullptr;
- if (D < 0 || D > 1)
- return nullptr;
- if (B == 1 && H != 256)
- return nullptr; // 1-byte coding must be fixed-size
- if (B >= 5 && H == 256)
- return nullptr; // no 5-byte fixed-size coding
-
- // first compute the range of the coding, in 64 bits
- int64_t range = 0;
- {
- int64_t H_i = 1;
- for (int i = 0; i < B; i++)
- {
- range += H_i;
- H_i *= H;
- }
- range *= L;
- range += H_i;
- }
- assert(range > 0); // no useless codings, please
-
- int this_umax;
-
- // now, compute min and max
- if (range >= ((int64_t)1 << 32))
- {
- this_umax = INT_MAX_VALUE;
- this->umin = INT_MIN_VALUE;
- this->max = INT_MAX_VALUE;
- this->min = INT_MIN_VALUE;
- }
- else
- {
- this_umax = (range > INT_MAX_VALUE) ? INT_MAX_VALUE : (int)range - 1;
- this->max = this_umax;
- this->min = this->umin = 0;
- if (S != 0 && range != 0)
- {
- int64_t maxPosCode = range - 1;
- int64_t maxNegCode = range - 1;
- while (IS_NEG_CODE(S, maxPosCode))
- --maxPosCode;
- while (!IS_NEG_CODE(S, maxNegCode))
- --maxNegCode;
- int maxPos = decode_sign(S, (uint32_t)maxPosCode);
- if (maxPos < 0)
- this->max = INT_MAX_VALUE; // 32-bit wraparound
- else
- this->max = maxPos;
- if (maxNegCode < 0)
- this->min = 0; // No negative codings at all.
- else
- this->min = decode_sign(S, (uint32_t)maxNegCode);
- }
- }
-
- assert(!(isFullRange | isSigned | isSubrange)); // init
- if (min < 0)
- this->isSigned = true;
- if (max < INT_MAX_VALUE && range <= INT_MAX_VALUE)
- this->isSubrange = true;
- if (max == INT_MAX_VALUE && min == INT_MIN_VALUE)
- this->isFullRange = true;
-
- // do this last, to reduce MT exposure (should have a membar too)
- this->umax = this_umax;
-
- return this;
-}
-
-coding *coding::findBySpec(int spec)
-{
- for (coding *scan = &basic_codings[0];; scan++)
- {
- if (scan->spec == spec)
- return scan->init();
- if (scan->spec == 0)
- break;
- }
- coding *ptr = NEW(coding, 1);
- if (!ptr)
- return nullptr;
- coding *c = ptr->initFrom(spec);
- if (c == nullptr)
- {
- ::free(ptr);
- }
- else
- // else caller should free it...
- c->isMalloc = true;
- return c;
-}
-
-coding *coding::findBySpec(int B, int H, int S, int D)
-{
- if (B < 1 || B > B_MAX)
- return nullptr;
- if (H < 1 || H > 256)
- return nullptr;
- if (S < 0 || S > 2)
- return nullptr;
- if (D < 0 || D > 1)
- return nullptr;
- return findBySpec(CODING_SPEC(B, H, S, D));
-}
-
-void coding::free()
-{
- if (isMalloc)
- {
- ::free(this);
- }
-}
-
-void coding_method::reset(value_stream *state)
-{
- assert(state->rp == state->rplimit); // not in mid-stream, please
- // assert(this == vs0.cm);
- state[0] = vs0;
- if (uValues != nullptr)
- {
- uValues->reset(state->helper());
- }
-}
-
-uint32_t coding::parse(byte *&rp, int B, int H)
-{
- int L = 256 - H;
- byte *ptr = rp;
- // hand peel the i==0 part of the loop:
- uint32_t b_i = *ptr++ & 0xFF;
- if (B == 1 || b_i < (uint32_t)L)
- {
- rp = ptr;
- return b_i;
- }
- uint32_t sum = b_i;
- uint32_t H_i = H;
- assert(B <= B_MAX);
- for (int i = 2; i <= B_MAX; i++)
- { // easy for compilers to unroll if desired
- b_i = *ptr++ & 0xFF;
- sum += b_i * H_i;
- if (i == B || b_i < (uint32_t)L)
- {
- rp = ptr;
- return sum;
- }
- H_i *= H;
- }
- assert(false);
- return 0;
-}
-
-uint32_t coding::parse_lgH(byte *&rp, int B, int H, int lgH)
-{
- assert(H == (1 << lgH));
- int L = 256 - (1 << lgH);
- byte *ptr = rp;
- // hand peel the i==0 part of the loop:
- uint32_t b_i = *ptr++ & 0xFF;
- if (B == 1 || b_i < (uint32_t)L)
- {
- rp = ptr;
- return b_i;
- }
- uint32_t sum = b_i;
- uint32_t lg_H_i = lgH;
- assert(B <= B_MAX);
- for (int i = 2; i <= B_MAX; i++)
- { // easy for compilers to unroll if desired
- b_i = *ptr++ & 0xFF;
- sum += b_i << lg_H_i;
- if (i == B || b_i < (uint32_t)L)
- {
- rp = ptr;
- return sum;
- }
- lg_H_i += lgH;
- }
- assert(false);
- return 0;
-}
-
-static const char ERB[] = "EOF reading band";
-
-void coding::parseMultiple(byte *&rp, int N, byte *limit, int B, int H)
-{
- if (N < 0)
- {
- unpack_abort("bad value count");
- return;
- }
- byte *ptr = rp;
- if (B == 1 || H == 256)
- {
- size_t len = (size_t)N * B;
- if (len / B != (size_t)N || ptr + len > limit)
- {
- unpack_abort(ERB);
- return;
- }
- rp = ptr + len;
- return;
- }
- // Note: We assume rp has enough zero-padding.
- int L = 256 - H;
- int n = B;
- while (N > 0)
- {
- ptr += 1;
- if (--n == 0)
- {
- // end of encoding at B bytes, regardless of byte value
- }
- else
- {
- int b = (ptr[-1] & 0xFF);
- if (b >= L)
- {
- // keep going, unless we find a byte < L
- continue;
- }
- }
- // found the last byte
- N -= 1;
- n = B; // reset length counter
- // do an error check here
- if (ptr > limit)
- {
- unpack_abort(ERB);
- return;
- }
- }
- rp = ptr;
- return;
-}
-
-bool value_stream::hasHelper()
-{
- // If my coding method is a pop-style method,
- // then I need a second value stream to transmit
- // unfavored values.
- // This can be determined by examining fValues.
- return cm->fValues != nullptr;
-}
-
-void value_stream::init(byte *rp_, byte *rplimit_, coding *defc)
-{
- rp = rp_;
- rplimit = rplimit_;
- sum = 0;
- cm = nullptr; // no need in the simple case
- setCoding(defc);
-}
-
-void value_stream::setCoding(coding *defc)
-{
- if (defc == nullptr)
- {
- unpack_abort("bad coding");
- defc = coding::findByIndex(_meta_canon_min); // random pick for recovery
- }
-
- c = (*defc);
-
- // choose cmk
- cmk = cmk_ERROR;
- switch (c.spec)
- {
- case BYTE1_spec:
- cmk = cmk_BYTE1;
- break;
- case CHAR3_spec:
- cmk = cmk_CHAR3;
- break;
- case UNSIGNED5_spec:
- cmk = cmk_UNSIGNED5;
- break;
- case DELTA5_spec:
- cmk = cmk_DELTA5;
- break;
- case BCI5_spec:
- cmk = cmk_BCI5;
- break;
- case BRANCH5_spec:
- cmk = cmk_BRANCH5;
- break;
- default:
- if (c.D() == 0)
- {
- switch (c.S())
- {
- case 0:
- cmk = cmk_BHS0;
- break;
- case 1:
- cmk = cmk_BHS1;
- break;
- default:
- cmk = cmk_BHS;
- break;
- }
- }
- else
- {
- if (c.S() == 1)
- {
- if (c.isFullRange)
- cmk = cmk_BHS1D1full;
- if (c.isSubrange)
- cmk = cmk_BHS1D1sub;
- }
- if (cmk == cmk_ERROR)
- cmk = cmk_BHSD1;
- }
- }
-}
-
-static int getPopValue(value_stream *self, uint32_t uval)
-{
- if (uval > 0)
- {
- // note that the initial parse performed a range check
- assert(uval <= (uint32_t)self->cm->fVlength);
- return self->cm->fValues[uval - 1];
- }
- else
- {
- // take an unfavored value
- return self->helper()->getInt();
- }
-}
-
-int coding::sumInUnsignedRange(int x, int y)
-{
- assert(isSubrange);
- int range = (int)(umax + 1);
- assert(range > 0);
- x += y;
- if (x != (int)((int64_t)(x - y) + (int64_t)y))
- {
- // 32-bit overflow interferes with range reduction.
- // Back off from the overflow by adding a multiple of range:
- if (x < 0)
- {
- x -= range;
- assert(x >= 0);
- }
- else
- {
- x += range;
- assert(x < 0);
- }
- }
- if (x < 0)
- {
- x += range;
- if (x >= 0)
- return x;
- }
- else if (x >= range)
- {
- x -= range;
- if (x < range)
- return x;
- }
- else
- {
- // in range
- return x;
- }
- // do it the hard way
- x %= range;
- if (x < 0)
- x += range;
- return x;
-}
-
-static int getDeltaValue(value_stream *self, uint32_t uval, bool isSubrange)
-{
- assert((uint32_t)(self->c.isSubrange) == (uint32_t)isSubrange);
- assert(self->c.isSubrange | self->c.isFullRange);
- if (isSubrange)
- return self->sum = self->c.sumInUnsignedRange(self->sum, (int)uval);
- else
- return self->sum += (int)uval;
-}
-
-bool value_stream::hasValue()
-{
- if (rp < rplimit)
- return true;
- if (cm == nullptr)
- return false;
- if (cm->next == nullptr)
- return false;
- cm->next->reset(this);
- return hasValue();
-}
-
-int value_stream::getInt()
-{
- if (rp >= rplimit)
- {
- // Advance to next coding segment.
- if (rp > rplimit || cm == nullptr || cm->next == nullptr)
- {
- // Must perform this check and throw an exception on bad input.
- unpack_abort(ERB);
- return 0;
- }
- cm->next->reset(this);
- return getInt();
- }
-
- CODING_PRIVATE(c.spec);
- uint32_t uval;
- enum
- {
- B5 = 5,
- B3 = 3,
- H128 = 128,
- H64 = 64,
- H4 = 4
- };
- switch (cmk)
- {
- case cmk_BHS:
- assert(D == 0);
- uval = coding::parse(rp, B, H);
- if (S == 0)
- return (int)uval;
- return decode_sign(S, uval);
-
- case cmk_BHS0:
- assert(S == 0 && D == 0);
- uval = coding::parse(rp, B, H);
- return (int)uval;
-
- case cmk_BHS1:
- assert(S == 1 && D == 0);
- uval = coding::parse(rp, B, H);
- return DECODE_SIGN_S1(uval);
-
- case cmk_BYTE1:
- assert(c.spec == BYTE1_spec);
- assert(B == 1 && H == 256 && S == 0 && D == 0);
- return *rp++ & 0xFF;
-
- case cmk_CHAR3:
- assert(c.spec == CHAR3_spec);
- assert(B == B3 && H == H128 && S == 0 && D == 0);
- return coding::parse_lgH(rp, B3, H128, 7);
-
- case cmk_UNSIGNED5:
- assert(c.spec == UNSIGNED5_spec);
- assert(B == B5 && H == H64 && S == 0 && D == 0);
- return coding::parse_lgH(rp, B5, H64, 6);
-
- case cmk_BHSD1:
- assert(D == 1);
- uval = coding::parse(rp, B, H);
- if (S != 0)
- uval = (uint32_t)decode_sign(S, uval);
- return getDeltaValue(this, uval, (bool)c.isSubrange);
-
- case cmk_BHS1D1full:
- assert(S == 1 && D == 1 && c.isFullRange);
- uval = coding::parse(rp, B, H);
- uval = (uint32_t)DECODE_SIGN_S1(uval);
- return getDeltaValue(this, uval, false);
-
- case cmk_BHS1D1sub:
- assert(S == 1 && D == 1 && c.isSubrange);
- uval = coding::parse(rp, B, H);
- uval = (uint32_t)DECODE_SIGN_S1(uval);
- return getDeltaValue(this, uval, true);
-
- case cmk_DELTA5:
- assert(c.spec == DELTA5_spec);
- assert(B == B5 && H == H64 && S == 1 && D == 1 && c.isFullRange);
- uval = coding::parse_lgH(rp, B5, H64, 6);
- sum += DECODE_SIGN_S1(uval);
- return sum;
-
- case cmk_BCI5:
- assert(c.spec == BCI5_spec);
- assert(B == B5 && H == H4 && S == 0 && D == 0);
- return coding::parse_lgH(rp, B5, H4, 2);
-
- case cmk_BRANCH5:
- assert(c.spec == BRANCH5_spec);
- assert(B == B5 && H == H4 && S == 2 && D == 0);
- uval = coding::parse_lgH(rp, B5, H4, 2);
- return decode_sign(S, uval);
-
- case cmk_pop:
- uval = coding::parse(rp, B, H);
- if (S != 0)
- {
- uval = (uint32_t)decode_sign(S, uval);
- }
- if (D != 0)
- {
- assert(c.isSubrange | c.isFullRange);
- if (c.isSubrange)
- sum = c.sumInUnsignedRange(sum, (int)uval);
- else
- sum += (int)uval;
- uval = (uint32_t)sum;
- }
- return getPopValue(this, uval);
-
- case cmk_pop_BHS0:
- assert(S == 0 && D == 0);
- uval = coding::parse(rp, B, H);
- return getPopValue(this, uval);
-
- case cmk_pop_BYTE1:
- assert(c.spec == BYTE1_spec);
- assert(B == 1 && H == 256 && S == 0 && D == 0);
- return getPopValue(this, *rp++ & 0xFF);
-
- default:
- break;
- }
- assert(false);
- return 0;
-}
-
-static int moreCentral(int x, int y)
-{ // used to find end of Pop.{F}
- // Suggested implementation from the Pack200 specification:
- uint32_t kx = (x >> 31) ^ (x << 1);
- uint32_t ky = (y >> 31) ^ (y << 1);
- return (kx < ky ? x : y);
-}
-// static maybe_inline
-// int moreCentral2(int x, int y, int min) {
-// // Strict implementation of buggy 150.7 specification.
-// // The bug is that the spec. says absolute-value ties are broken
-// // in favor of positive numbers, but the suggested implementation
-// // (also mentioned in the spec.) breaks ties in favor of negative numbers.
-// if ((x + y) != 0)
-// return min;
-// else
-// // return the other value, which breaks a tie in the positive direction
-// return (x > y)? x: y;
-//}
-
-static const byte *no_meta[] = {nullptr};
-#define NO_META (*(byte **)no_meta)
-enum
-{
- POP_FAVORED_N = -2
-};
-
-// mode bits
-#define DISABLE_RUN 1 // used immediately inside ACodee
-#define DISABLE_POP 2 // used recursively in all pop sub-bands
-
-// This function knows all about meta-coding.
-void coding_method::init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode,
- coding *defc, int N, intlist *valueSink)
-{
- assert(N != 0);
-
- assert(u != nullptr); // must be pre-initialized
- // if (u == nullptr) u = unpacker::current(); // expensive
-
- int op = (meta_rp == nullptr) ? _meta_default : (*meta_rp++ & 0xFF);
- coding *foundc = nullptr;
- coding *to_free = nullptr;
-
- if (op == _meta_default)
- {
- foundc = defc;
- // and fall through
- }
- else if (op >= _meta_canon_min && op <= _meta_canon_max)
- {
- foundc = coding::findByIndex(op);
- // and fall through
- }
- else if (op == _meta_arb)
- {
- int args = (*meta_rp++ & 0xFF);
- // args = (D:[0..1] + 2*S[0..2] + 8*(B:[1..5]-1))
- int D = ((args >> 0) & 1);
- int S = ((args >> 1) & 3);
- int B = ((args >> 3) & -1) + 1;
- // & (H[1..256]-1)
- int H = (*meta_rp++ & 0xFF) + 1;
- foundc = coding::findBySpec(B, H, S, D);
- to_free = foundc; // findBySpec may dynamically allocate
- if (foundc == nullptr)
- {
- unpack_abort("illegal arbitrary coding");
- return;
- }
- // and fall through
- }
- else if (op >= _meta_run && op < _meta_pop)
- {
- int args = (op - _meta_run);
- // args: KX:[0..3] + 4*(KBFlag:[0..1]) + 8*(ABDef:[0..2])
- int KX = ((args >> 0) & 3);
- int KBFlag = ((args >> 2) & 1);
- int ABDef = ((args >> 3) & -1);
- assert(ABDef <= 2);
- // & KB: one of [0..255] if KBFlag=1
- int KB = (!KBFlag ? 3 : (*meta_rp++ & 0xFF));
- int K = (KB + 1) << (KX * 4);
- int N2 = (N >= 0) ? N - K : N;
- if (N == 0 || (N2 <= 0 && N2 != N))
- {
- unpack_abort("illegal run encoding");
- }
- if ((mode & DISABLE_RUN) != 0)
- {
- unpack_abort("illegal nested run encoding");
- }
-
- // & Enc{ ACode } if ADef=0 (ABDef != 1)
- // No direct nesting of 'run' in ACode, but in BCode it's OK.
- int disRun = mode | DISABLE_RUN;
- if (ABDef == 1)
- {
- this->init(band_rp, band_limit, NO_META, disRun, defc, K, valueSink);
- }
- else
- {
- this->init(band_rp, band_limit, meta_rp, disRun, defc, K, valueSink);
- }
-
- // & Enc{ BCode } if BDef=0 (ABDef != 2)
- coding_method *tail = U_NEW(coding_method, 1);
- if (!tail)
- return;
- tail->u = u;
-
- // The 'run' codings may be nested indirectly via 'pop' codings.
- // This means that this->next may already be filled in, if
- // ACode was of type 'pop' with a 'run' token coding.
- // No problem: Just chain the upcoming BCode onto the end.
- for (coding_method *self = this;; self = self->next)
- {
- if (self->next == nullptr)
- {
- self->next = tail;
- break;
- }
- }
-
- if (ABDef == 2)
- {
- tail->init(band_rp, band_limit, NO_META, mode, defc, N2, valueSink);
- }
- else
- {
- tail->init(band_rp, band_limit, meta_rp, mode, defc, N2, valueSink);
- }
- // Note: The preceding calls to init should be tail-recursive.
-
- return; // done; no falling through
- }
- else if (op >= _meta_pop && op < _meta_limit)
- {
- int args = (op - _meta_pop);
- // args: (FDef:[0..1]) + 2*UDef:[0..1] + 4*(TDefL:[0..11])
- int FDef = ((args >> 0) & 1);
- int UDef = ((args >> 1) & 1);
- int TDefL = ((args >> 2) & -1);
- assert(TDefL <= 11);
- int TDef = (TDefL > 0);
- int TL = (TDefL <= 6) ? (2 << TDefL) : (256 - (4 << (11 - TDefL)));
- int TH = (256 - TL);
- if (N <= 0)
- {
- unpack_abort("illegal pop encoding");
- }
- if ((mode & DISABLE_POP) != 0)
- {
- unpack_abort("illegal nested pop encoding");
- }
-
- // No indirect nesting of 'pop', but 'run' is OK.
- int disPop = DISABLE_POP;
-
- // & Enc{ FCode } if FDef=0
- int FN = POP_FAVORED_N;
- assert(valueSink == nullptr);
- intlist fValueSink;
- fValueSink.init();
- coding_method fval;
- BYTES_OF(fval).clear();
- fval.u = u;
- if (FDef != 0)
- {
- fval.init(band_rp, band_limit, NO_META, disPop, defc, FN, &fValueSink);
- }
- else
- {
- fval.init(band_rp, band_limit, meta_rp, disPop, defc, FN, &fValueSink);
- }
- bytes fvbuf;
- fValues = (u->saveTo(fvbuf, fValueSink.b), (int *)fvbuf.ptr);
- fVlength = fValueSink.length(); // i.e., the parameter K
- fValueSink.free();
-
- // Skip the first {F} run in all subsequent passes.
- // The next call to this->init(...) will set vs0.rp to point after the {F}.
-
- // & Enc{ TCode } if TDef=0 (TDefL==0)
- if (TDef != 0)
- {
- coding *tcode = coding::findBySpec(1, 256); // BYTE1
- // find the most narrowly sufficient code:
- for (int B = 2; B <= B_MAX; B++)
- {
- if (fVlength <= tcode->umax)
- break; // found it
- tcode->free();
- tcode = coding::findBySpec(B, TH);
- if (!tcode)
- return;
- }
- if (!(fVlength <= tcode->umax))
- {
- unpack_abort("pop.L value too small");
- }
- this->init(band_rp, band_limit, NO_META, disPop, tcode, N, nullptr);
- tcode->free();
- }
- else
- {
- this->init(band_rp, band_limit, meta_rp, disPop, defc, N, nullptr);
- }
-
- // Count the number of zero tokens right now.
- // Also verify that they are in bounds.
- int UN = 0; // one {U} for each zero in {T}
- value_stream vs = vs0;
- for (int i = 0; i < N; i++)
- {
- uint32_t val = vs.getInt();
- if (val == 0)
- UN += 1;
- if (!(val <= (uint32_t)fVlength))
- {
- unpack_abort("pop token out of range");
- }
- }
- vs.done();
-
- // & Enc{ UCode } if UDef=0
- if (UN != 0)
- {
- uValues = U_NEW(coding_method, 1);
- if (uValues == nullptr)
- return;
- uValues->u = u;
- if (UDef != 0)
- {
- uValues->init(band_rp, band_limit, NO_META, disPop, defc, UN, nullptr);
- }
- else
- {
- uValues->init(band_rp, band_limit, meta_rp, disPop, defc, UN, nullptr);
- }
- }
- else
- {
- if (UDef == 0)
- {
- int uop = (*meta_rp++ & 0xFF);
- if (uop > _meta_canon_max)
- // %%% Spec. requires the more strict (uop != _meta_default).
- unpack_abort("bad meta-coding for empty pop/U");
- }
- }
-
- // Bug fix for 6259542
- // Last of all, adjust vs0.cmk to the 'pop' flavor
- for (coding_method *self = this; self != nullptr; self = self->next)
- {
- coding_method_kind cmk2 = cmk_pop;
- switch (self->vs0.cmk)
- {
- case cmk_BHS0:
- cmk2 = cmk_pop_BHS0;
- break;
- case cmk_BYTE1:
- cmk2 = cmk_pop_BYTE1;
- break;
- default:
- break;
- }
- self->vs0.cmk = cmk2;
- if (self != this)
- {
- assert(self->fValues == nullptr); // no double init
- self->fValues = this->fValues;
- self->fVlength = this->fVlength;
- assert(self->uValues == nullptr); // must stay nullptr
- }
- }
-
- return; // done; no falling through
- }
- else
- {
- unpack_abort("bad meta-coding");
- }
-
- // Common code here skips a series of values with one coding.
- assert(foundc != nullptr);
-
- assert(vs0.cmk == cmk_ERROR); // no garbage, please
- assert(vs0.rp == nullptr); // no garbage, please
- assert(vs0.rplimit == nullptr); // no garbage, please
- assert(vs0.sum == 0); // no garbage, please
-
- vs0.init(band_rp, band_limit, foundc);
-
- // Done with foundc. Free if necessary.
- if (to_free != nullptr)
- {
- to_free->free();
- to_free = nullptr;
- }
- foundc = nullptr;
-
- coding &c = vs0.c;
- CODING_PRIVATE(c.spec);
- // assert sane N
- assert((uint32_t)N < INT_MAX_VALUE || N == POP_FAVORED_N);
-
- // Look at the values, or at least skip over them quickly.
- if (valueSink == nullptr)
- {
- // Skip and ignore values in the first pass.
- c.parseMultiple(band_rp, N, band_limit, B, H);
- }
- else if (N >= 0)
- {
- // Pop coding, {F} sequence, initial run of values...
- assert((mode & DISABLE_POP) != 0);
- value_stream vs = vs0;
- for (int n = 0; n < N; n++)
- {
- int val = vs.getInt();
- valueSink->add(val);
- }
- band_rp = vs.rp;
- }
- else
- {
- // Pop coding, {F} sequence, final run of values...
- assert((mode & DISABLE_POP) != 0);
- assert(N == POP_FAVORED_N);
- int min = INT_MIN_VALUE; // farthest from the center
- // min2 is based on the buggy specification of centrality in version 150.7
- // no known implementations transmit this value, but just in case...
- // int min2 = INT_MIN_VALUE;
- int last = 0;
- // if there were initial runs, find the potential sentinels in them:
- for (int i = 0; i < valueSink->length(); i++)
- {
- last = valueSink->get(i);
- min = moreCentral(min, last);
- // min2 = moreCentral2(min2, last, min);
- }
- value_stream vs = vs0;
- for (;;)
- {
- int val = vs.getInt();
- if (valueSink->length() > 0 && (val == last || val == min)) //|| val == min2
- break;
- valueSink->add(val);
- last = val;
- min = moreCentral(min, last);
- // min2 = moreCentral2(min2, last, min);
- }
- band_rp = vs.rp;
- }
-
- // Get an accurate upper limit now.
- vs0.rplimit = band_rp;
- vs0.cm = this;
-
- return; // success
-}
-
-coding basic_codings[] = {
- // This one is not a usable irregular coding, but is used by cp_Utf8_chars.
- CODING_INIT(3, 128, 0, 0),
-
- // Fixed-length codings:
- CODING_INIT(1, 256, 0, 0), CODING_INIT(1, 256, 1, 0), CODING_INIT(1, 256, 0, 1),
- CODING_INIT(1, 256, 1, 1), CODING_INIT(2, 256, 0, 0), CODING_INIT(2, 256, 1, 0),
- CODING_INIT(2, 256, 0, 1), CODING_INIT(2, 256, 1, 1), CODING_INIT(3, 256, 0, 0),
- CODING_INIT(3, 256, 1, 0), CODING_INIT(3, 256, 0, 1), CODING_INIT(3, 256, 1, 1),
- CODING_INIT(4, 256, 0, 0), CODING_INIT(4, 256, 1, 0), CODING_INIT(4, 256, 0, 1),
- CODING_INIT(4, 256, 1, 1),
-
- // Full-range variable-length codings:
- CODING_INIT(5, 4, 0, 0), CODING_INIT(5, 4, 1, 0), CODING_INIT(5, 4, 2, 0),
- CODING_INIT(5, 16, 0, 0), CODING_INIT(5, 16, 1, 0), CODING_INIT(5, 16, 2, 0),
- CODING_INIT(5, 32, 0, 0), CODING_INIT(5, 32, 1, 0), CODING_INIT(5, 32, 2, 0),
- CODING_INIT(5, 64, 0, 0), CODING_INIT(5, 64, 1, 0), CODING_INIT(5, 64, 2, 0),
- CODING_INIT(5, 128, 0, 0), CODING_INIT(5, 128, 1, 0), CODING_INIT(5, 128, 2, 0),
- CODING_INIT(5, 4, 0, 1), CODING_INIT(5, 4, 1, 1), CODING_INIT(5, 4, 2, 1),
- CODING_INIT(5, 16, 0, 1), CODING_INIT(5, 16, 1, 1), CODING_INIT(5, 16, 2, 1),
- CODING_INIT(5, 32, 0, 1), CODING_INIT(5, 32, 1, 1), CODING_INIT(5, 32, 2, 1),
- CODING_INIT(5, 64, 0, 1), CODING_INIT(5, 64, 1, 1), CODING_INIT(5, 64, 2, 1),
- CODING_INIT(5, 128, 0, 1), CODING_INIT(5, 128, 1, 1), CODING_INIT(5, 128, 2, 1),
-
- // Variable length subrange codings:
- CODING_INIT(2, 192, 0, 0), CODING_INIT(2, 224, 0, 0), CODING_INIT(2, 240, 0, 0),
- CODING_INIT(2, 248, 0, 0), CODING_INIT(2, 252, 0, 0), CODING_INIT(2, 8, 0, 1),
- CODING_INIT(2, 8, 1, 1), CODING_INIT(2, 16, 0, 1), CODING_INIT(2, 16, 1, 1),
- CODING_INIT(2, 32, 0, 1), CODING_INIT(2, 32, 1, 1), CODING_INIT(2, 64, 0, 1),
- CODING_INIT(2, 64, 1, 1), CODING_INIT(2, 128, 0, 1), CODING_INIT(2, 128, 1, 1),
- CODING_INIT(2, 192, 0, 1), CODING_INIT(2, 192, 1, 1), CODING_INIT(2, 224, 0, 1),
- CODING_INIT(2, 224, 1, 1), CODING_INIT(2, 240, 0, 1), CODING_INIT(2, 240, 1, 1),
- CODING_INIT(2, 248, 0, 1), CODING_INIT(2, 248, 1, 1), CODING_INIT(3, 192, 0, 0),
- CODING_INIT(3, 224, 0, 0), CODING_INIT(3, 240, 0, 0), CODING_INIT(3, 248, 0, 0),
- CODING_INIT(3, 252, 0, 0), CODING_INIT(3, 8, 0, 1), CODING_INIT(3, 8, 1, 1),
- CODING_INIT(3, 16, 0, 1), CODING_INIT(3, 16, 1, 1), CODING_INIT(3, 32, 0, 1),
- CODING_INIT(3, 32, 1, 1), CODING_INIT(3, 64, 0, 1), CODING_INIT(3, 64, 1, 1),
- CODING_INIT(3, 128, 0, 1), CODING_INIT(3, 128, 1, 1), CODING_INIT(3, 192, 0, 1),
- CODING_INIT(3, 192, 1, 1), CODING_INIT(3, 224, 0, 1), CODING_INIT(3, 224, 1, 1),
- CODING_INIT(3, 240, 0, 1), CODING_INIT(3, 240, 1, 1), CODING_INIT(3, 248, 0, 1),
- CODING_INIT(3, 248, 1, 1), CODING_INIT(4, 192, 0, 0), CODING_INIT(4, 224, 0, 0),
- CODING_INIT(4, 240, 0, 0), CODING_INIT(4, 248, 0, 0), CODING_INIT(4, 252, 0, 0),
- CODING_INIT(4, 8, 0, 1), CODING_INIT(4, 8, 1, 1), CODING_INIT(4, 16, 0, 1),
- CODING_INIT(4, 16, 1, 1), CODING_INIT(4, 32, 0, 1), CODING_INIT(4, 32, 1, 1),
- CODING_INIT(4, 64, 0, 1), CODING_INIT(4, 64, 1, 1), CODING_INIT(4, 128, 0, 1),
- CODING_INIT(4, 128, 1, 1), CODING_INIT(4, 192, 0, 1), CODING_INIT(4, 192, 1, 1),
- CODING_INIT(4, 224, 0, 1), CODING_INIT(4, 224, 1, 1), CODING_INIT(4, 240, 0, 1),
- CODING_INIT(4, 240, 1, 1), CODING_INIT(4, 248, 0, 1), CODING_INIT(4, 248, 1, 1),
- CODING_INIT(0, 0, 0, 0)};
-#define BASIC_INDEX_LIMIT (int)(sizeof(basic_codings) / sizeof(basic_codings[0]) - 1)
-
-coding *coding::findByIndex(int idx)
-{
- int index_limit = BASIC_INDEX_LIMIT;
- assert(_meta_canon_min == 1 && _meta_canon_max + 1 == index_limit);
-
- if (idx >= _meta_canon_min && idx <= _meta_canon_max)
- return basic_codings[idx].init();
- else
- return nullptr;
-}
diff --git a/libraries/pack200/src/coding.h b/libraries/pack200/src/coding.h
deleted file mode 100644
index bfdd252e..00000000
--- a/libraries/pack200/src/coding.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-struct unpacker;
-
-#define INT_MAX_VALUE ((int)0x7FFFFFFF)
-#define INT_MIN_VALUE ((int)0x80000000)
-
-#define CODING_SPEC(B, H, S, D) ((B) << 20 | (H) << 8 | (S) << 4 | (D) << 0)
-#define CODING_B(x) ((x) >> 20 & 0xF)
-#define CODING_H(x) ((x) >> 8 & 0xFFF)
-#define CODING_S(x) ((x) >> 4 & 0xF)
-#define CODING_D(x) ((x) >> 0 & 0xF)
-
-#define CODING_INIT(B, H, S, D) \
- { \
- CODING_SPEC(B, H, S, D), 0, 0, 0, 0, 0, 0, 0, 0 \
- }
-
-// For debugging purposes, some compilers do not like this and will complain.
-// #define long do_not_use_C_long_types_use_jlong_or_int
-// Use of the type "long" is problematic, do not use it.
-
-struct coding
-{
- int spec; // B,H,S,D
-
- // Handy values derived from the spec:
- int B()
- {
- return CODING_B(spec);
- }
- int H()
- {
- return CODING_H(spec);
- }
- int S()
- {
- return CODING_S(spec);
- }
- int D()
- {
- return CODING_D(spec);
- }
- int L()
- {
- return 256 - CODING_H(spec);
- }
- int min, max;
- int umin, umax;
- char isSigned, isSubrange, isFullRange, isMalloc;
-
- coding *init(); // returns self or nullptr if error
- coding *initFrom(int spec_)
- {
- assert(this->spec == 0);
- this->spec = spec_;
- return init();
- }
-
- static coding *findBySpec(int spec);
- static coding *findBySpec(int B, int H, int S = 0, int D = 0);
- static coding *findByIndex(int irregularCodingIndex);
-
- static uint32_t parse(byte *&rp, int B, int H);
- static uint32_t parse_lgH(byte *&rp, int B, int H, int lgH);
- static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
-
- uint32_t parse(byte *&rp)
- {
- return parse(rp, CODING_B(spec), CODING_H(spec));
- }
- void parseMultiple(byte *&rp, int N, byte *limit)
- {
- parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec));
- }
-
- bool canRepresent(int x)
- {
- return (x >= min && x <= max);
- }
- bool canRepresentUnsigned(int x)
- {
- return (x >= umin && x <= umax);
- }
-
- int sumInUnsignedRange(int x, int y);
-
- int readFrom(byte *&rpVar, int *dbase);
- void readArrayFrom(byte *&rpVar, int *dbase, int length, int *values);
- void skipArrayFrom(byte *&rpVar, int length)
- {
- readArrayFrom(rpVar, (int *)NULL, length, (int *)NULL);
- }
-
- void free(); // free self if isMalloc
-};
-
-enum coding_method_kind
-{
- cmk_ERROR,
- cmk_BHS,
- cmk_BHS0,
- cmk_BHS1,
- cmk_BHSD1,
- cmk_BHS1D1full, // isFullRange
- cmk_BHS1D1sub, // isSubRange
-
- // special cases hand-optimized (~50% of all decoded values)
- cmk_BYTE1, //(1,256) 6%
- cmk_CHAR3, //(3,128) 7%
- cmk_UNSIGNED5, //(5,64) 13%
- cmk_DELTA5, //(5,64,1,1) 5%
- cmk_BCI5, //(5,4) 18%
- cmk_BRANCH5, //(5,4,2) 4%
- // cmk_UNSIGNED5H16, //(5,16) 5%
- // cmk_UNSIGNED2H4, //(2,4) 6%
- // cmk_DELTA4H8, //(4,8,1,1) 10%
- // cmk_DELTA3H16, //(3,16,1,1) 9%
- cmk_BHS_LIMIT,
- cmk_pop,
- cmk_pop_BHS0,
- cmk_pop_BYTE1,
- cmk_pop_LIMIT,
- cmk_LIMIT
-};
-
-enum
-{
- BYTE1_spec = CODING_SPEC(1, 256, 0, 0),
- CHAR3_spec = CODING_SPEC(3, 128, 0, 0),
- UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0),
- UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0),
- SIGNED5_spec = CODING_SPEC(5, 64, 1, 0),
- DELTA5_spec = CODING_SPEC(5, 64, 1, 1),
- UDELTA5_spec = CODING_SPEC(5, 64, 0, 1),
- MDELTA5_spec = CODING_SPEC(5, 64, 2, 1),
- BCI5_spec = CODING_SPEC(5, 4, 0, 0),
- BRANCH5_spec = CODING_SPEC(5, 4, 2, 0)
-};
-
-enum
-{
- B_MAX = 5,
- C_SLOP = B_MAX * 10
-};
-
-struct coding_method;
-
-// iterator under the control of a meta-coding
-struct value_stream
-{
- // current coding of values or values
- coding c; // B,H,S,D,etc.
- coding_method_kind cmk; // type of decoding needed
- byte *rp; // read pointer
- byte *rplimit; // final value of read pointer
- int sum; // partial sum of all values so far (D=1 only)
- coding_method *cm; // coding method that defines this stream
-
- void init(byte *band_rp, byte *band_limit, coding *defc);
- void init(byte *band_rp, byte *band_limit, int spec)
- {
- init(band_rp, band_limit, coding::findBySpec(spec));
- }
-
- void setCoding(coding *c);
- void setCoding(int spec)
- {
- setCoding(coding::findBySpec(spec));
- }
-
- // Parse and decode a single value.
- int getInt();
-
- // Parse and decode a single byte, with no error checks.
- int getByte()
- {
- assert(cmk == cmk_BYTE1);
- assert(rp < rplimit);
- return *rp++ & 0xFF;
- }
-
- // Used only for asserts.
- bool hasValue();
-
- void done()
- {
- assert(!hasValue());
- }
-
- // Sometimes a value stream has an auxiliary (but there are never two).
- value_stream *helper()
- {
- assert(hasHelper());
- return this + 1;
- }
- bool hasHelper();
-};
-
-struct coding_method
-{
- value_stream vs0; // initial state snapshot (vs.meta==this)
-
- coding_method *next; // what to do when we run out of bytes
-
- // these fields are used for pop codes only:
- int *fValues; // favored value array
- int fVlength; // maximum favored value token
- coding_method *uValues; // unfavored value stream
-
- // pointer to outer unpacker, for error checks etc.
- unpacker *u;
-
- // Initialize a value stream.
- void reset(value_stream *state);
-
- // Parse a band header, size a band, and initialize for further action.
- // band_rp advances (but not past band_limit), and meta_rp advances.
- // The mode gives context, such as "inside a pop".
- // The defc and N are the incoming parameters to a meta-coding.
- // The value sink is used to collect output values, when desired.
- void init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode, coding *defc, int N,
- intlist *valueSink);
-};
diff --git a/libraries/pack200/src/constants.h b/libraries/pack200/src/constants.h
deleted file mode 100644
index f1baf42a..00000000
--- a/libraries/pack200/src/constants.h
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- Java Class Version numbers history
- 1.0 to 1.3.X 45,3
- 1.4 to 1.4.X 46,0
- 1.5 to 1.5.X 49,0
- 1.6 to 1.5.x 50,0 NOTE Assumed for now
-*/
-
-// classfile constants
-#define JAVA_MAGIC 0xCAFEBABE
-#define JAVA_MIN_MAJOR_VERSION 45
-#define JAVA_MIN_MINOR_VERSION 3
-#define JAVA5_MAX_MAJOR_VERSION 49
-#define JAVA5_MAX_MINOR_VERSION 0
-// NOTE: Assume for now
-#define JAVA6_MAX_MAJOR_VERSION 50
-#define JAVA6_MAX_MINOR_VERSION 0
-
-// package file constants
-#define JAVA_PACKAGE_MAGIC 0xCAFED00D
-#define JAVA5_PACKAGE_MAJOR_VERSION 150
-#define JAVA5_PACKAGE_MINOR_VERSION 7
-
-#define JAVA6_PACKAGE_MAJOR_VERSION 160
-#define JAVA6_PACKAGE_MINOR_VERSION 1
-
-// magic number for gzip streams (for processing pack200-gzip data)
-#define GZIP_MAGIC 0x1F8B0800
-#define GZIP_MAGIC_MASK 0xFFFFFF00 // last \bchar\b is variable "flg" field
-
-enum
-{
- CONSTANT_None,
- CONSTANT_Utf8,
- CONSTANT_unused2, /* unused, was Unicode */
- CONSTANT_Integer,
- CONSTANT_Float,
- CONSTANT_Long,
- CONSTANT_Double,
- CONSTANT_Class,
- CONSTANT_String,
- CONSTANT_Fieldref,
- CONSTANT_Methodref,
- CONSTANT_InterfaceMethodref,
- CONSTANT_NameandType,
- CONSTANT_Signature = 13,
- CONSTANT_All = 14,
- CONSTANT_Limit = 15,
- CONSTANT_NONE = 0,
- CONSTANT_Literal = 20, // pseudo-tag for debugging
- CONSTANT_Member = 21, // pseudo-tag for debugging
- SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag
- ACC_STATIC = 0x0008,
- ACC_IC_LONG_FORM = (1 << 16), // for ic_flags
- CLASS_ATTR_SourceFile = 17,
- CLASS_ATTR_EnclosingMethod = 18,
- CLASS_ATTR_InnerClasses = 23,
- CLASS_ATTR_ClassFile_version = 24,
- FIELD_ATTR_ConstantValue = 17,
- METHOD_ATTR_Code = 17,
- METHOD_ATTR_Exceptions = 18,
- METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
- METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
- METHOD_ATTR_AnnotationDefault = 25,
- CODE_ATTR_StackMapTable = 0,
- CODE_ATTR_LineNumberTable = 1,
- CODE_ATTR_LocalVariableTable = 2,
- CODE_ATTR_LocalVariableTypeTable = 3,
- // X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined
- X_ATTR_Signature = 19,
- X_ATTR_Deprecated = 20,
- X_ATTR_RuntimeVisibleAnnotations = 21,
- X_ATTR_RuntimeInvisibleAnnotations = 22,
- X_ATTR_OVERFLOW = 16,
- X_ATTR_LIMIT_NO_FLAGS_HI = 32,
- X_ATTR_LIMIT_FLAGS_HI = 63,
-
-#define O_ATTR_DO(F) \
- F(X_ATTR_OVERFLOW, 01) \
- /*(end)*/
-#define X_ATTR_DO(F) \
- O_ATTR_DO(F) F(X_ATTR_Signature, Signature) F(X_ATTR_Deprecated, Deprecated) \
- F(X_ATTR_RuntimeVisibleAnnotations, RuntimeVisibleAnnotations) \
- F(X_ATTR_RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations) \
- /*F(X_ATTR_Synthetic,Synthetic)*/ \
- /*(end)*/
-#define CLASS_ATTR_DO(F) \
- F(CLASS_ATTR_SourceFile, SourceFile) F(CLASS_ATTR_InnerClasses, InnerClasses) \
- F(CLASS_ATTR_EnclosingMethod, EnclosingMethod) F(CLASS_ATTR_ClassFile_version, 02) \
- /*(end)*/
-#define FIELD_ATTR_DO(F) \
- F(FIELD_ATTR_ConstantValue, ConstantValue) \
- /*(end)*/
-#define METHOD_ATTR_DO(F) \
- F(METHOD_ATTR_Code, Code) F(METHOD_ATTR_Exceptions, Exceptions) \
- F(METHOD_ATTR_RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations) \
- F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, \
- RuntimeInvisibleParameterAnnotations) \
- F(METHOD_ATTR_AnnotationDefault, AnnotationDefault) \
- /*(end)*/
-#define CODE_ATTR_DO(F) \
- F(CODE_ATTR_StackMapTable, StackMapTable) F(CODE_ATTR_LineNumberTable, LineNumberTable) \
- F(CODE_ATTR_LocalVariableTable, LocalVariableTable) \
- F(CODE_ATTR_LocalVariableTypeTable, LocalVariableTypeTable) \
- /*(end)*/
-#define ALL_ATTR_DO(F) \
- X_ATTR_DO(F) CLASS_ATTR_DO(F) FIELD_ATTR_DO(F) METHOD_ATTR_DO(F) CODE_ATTR_DO(F) \
- /*(end)*/
-
- // attribute "context types"
- ATTR_CONTEXT_CLASS = 0,
- ATTR_CONTEXT_FIELD = 1,
- ATTR_CONTEXT_METHOD = 2,
- ATTR_CONTEXT_CODE = 3,
- ATTR_CONTEXT_LIMIT = 4,
-
- // constants for parsed layouts (stored in band::le_kind)
- EK_NONE = 0, // not a layout element
- EK_INT = 'I', // B H I SH etc., also FH etc.
- EK_BCI = 'P', // PH etc.
- EK_BCID = 'Q', // POH etc.
- EK_BCO = 'O', // OH etc.
- EK_REPL = 'N', // NH[...] etc.
- EK_REF = 'R', // RUH, RUNH, KQH, etc.
- EK_UN = 'T', // TB(...)[...] etc.
- EK_CASE = 'K', // (...)[...] etc.
- EK_CALL = '(', // (0), (1), etc.
- EK_CBLE = '[', // [...][...] etc.
- NO_BAND_INDEX = -1,
-
- // File option bits, from LSB in ascending bit position.
- FO_DEFLATE_HINT = 1 << 0,
- FO_IS_CLASS_STUB = 1 << 1,
-
- // Archive option bits, from LSB in ascending bit position:
- AO_HAVE_SPECIAL_FORMATS = 1 << 0,
- AO_HAVE_CP_NUMBERS = 1 << 1,
- AO_HAVE_ALL_CODE_FLAGS = 1 << 2,
- AO_3_UNUSED_MBZ = 1 << 3,
- AO_HAVE_FILE_HEADERS = 1 << 4,
- AO_DEFLATE_HINT = 1 << 5,
- AO_HAVE_FILE_MODTIME = 1 << 6,
- AO_HAVE_FILE_OPTIONS = 1 << 7,
- AO_HAVE_FILE_SIZE_HI = 1 << 8,
- AO_HAVE_CLASS_FLAGS_HI = 1 << 9,
- AO_HAVE_FIELD_FLAGS_HI = 1 << 10,
- AO_HAVE_METHOD_FLAGS_HI = 1 << 11,
- AO_HAVE_CODE_FLAGS_HI = 1 << 12,
-#define ARCHIVE_BIT_DO(F) \
- F(AO_HAVE_SPECIAL_FORMATS) F(AO_HAVE_CP_NUMBERS) F(AO_HAVE_ALL_CODE_FLAGS) \
- /*F(AO_3_UNUSED_MBZ)*/ \
- F(AO_HAVE_FILE_HEADERS) F(AO_DEFLATE_HINT) F(AO_HAVE_FILE_MODTIME) \
- F(AO_HAVE_FILE_OPTIONS) F(AO_HAVE_FILE_SIZE_HI) F(AO_HAVE_CLASS_FLAGS_HI) \
- F(AO_HAVE_FIELD_FLAGS_HI) F(AO_HAVE_METHOD_FLAGS_HI) F(AO_HAVE_CODE_FLAGS_HI) \
- /*(end)*/
-
- // Constants for decoding attribute definition header bytes.
- ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK)
- ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT)
- ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB
-#define ADH_BYTE(context, index) ((((index) + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT) + (context))
-#define ADH_BYTE_CONTEXT(adhb) ((adhb) & ADH_CONTEXT_MASK)
-#define ADH_BYTE_INDEX(adhb) (((adhb) >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB)
- NO_MODTIME = 0, // nullptr modtime value
-
- // meta-coding
- _meta_default = 0,
- _meta_canon_min = 1,
- _meta_canon_max = 115,
- _meta_arb = 116,
- _meta_run = 117,
- _meta_pop = 141,
- _meta_limit = 189,
- _meta_error = 255,
- _xxx_1_end
-};
-
-// Bytecodes.
-
-enum
-{
- bc_nop = 0, // 0x00
- bc_aconst_null = 1, // 0x01
- bc_iconst_m1 = 2, // 0x02
- bc_iconst_0 = 3, // 0x03
- bc_iconst_1 = 4, // 0x04
- bc_iconst_2 = 5, // 0x05
- bc_iconst_3 = 6, // 0x06
- bc_iconst_4 = 7, // 0x07
- bc_iconst_5 = 8, // 0x08
- bc_lconst_0 = 9, // 0x09
- bc_lconst_1 = 10, // 0x0a
- bc_fconst_0 = 11, // 0x0b
- bc_fconst_1 = 12, // 0x0c
- bc_fconst_2 = 13, // 0x0d
- bc_dconst_0 = 14, // 0x0e
- bc_dconst_1 = 15, // 0x0f
- bc_bipush = 16, // 0x10
- bc_sipush = 17, // 0x11
- bc_ldc = 18, // 0x12
- bc_ldc_w = 19, // 0x13
- bc_ldc2_w = 20, // 0x14
- bc_iload = 21, // 0x15
- bc_lload = 22, // 0x16
- bc_fload = 23, // 0x17
- bc_dload = 24, // 0x18
- bc_aload = 25, // 0x19
- bc_iload_0 = 26, // 0x1a
- bc_iload_1 = 27, // 0x1b
- bc_iload_2 = 28, // 0x1c
- bc_iload_3 = 29, // 0x1d
- bc_lload_0 = 30, // 0x1e
- bc_lload_1 = 31, // 0x1f
- bc_lload_2 = 32, // 0x20
- bc_lload_3 = 33, // 0x21
- bc_fload_0 = 34, // 0x22
- bc_fload_1 = 35, // 0x23
- bc_fload_2 = 36, // 0x24
- bc_fload_3 = 37, // 0x25
- bc_dload_0 = 38, // 0x26
- bc_dload_1 = 39, // 0x27
- bc_dload_2 = 40, // 0x28
- bc_dload_3 = 41, // 0x29
- bc_aload_0 = 42, // 0x2a
- bc_aload_1 = 43, // 0x2b
- bc_aload_2 = 44, // 0x2c
- bc_aload_3 = 45, // 0x2d
- bc_iaload = 46, // 0x2e
- bc_laload = 47, // 0x2f
- bc_faload = 48, // 0x30
- bc_daload = 49, // 0x31
- bc_aaload = 50, // 0x32
- bc_baload = 51, // 0x33
- bc_caload = 52, // 0x34
- bc_saload = 53, // 0x35
- bc_istore = 54, // 0x36
- bc_lstore = 55, // 0x37
- bc_fstore = 56, // 0x38
- bc_dstore = 57, // 0x39
- bc_astore = 58, // 0x3a
- bc_istore_0 = 59, // 0x3b
- bc_istore_1 = 60, // 0x3c
- bc_istore_2 = 61, // 0x3d
- bc_istore_3 = 62, // 0x3e
- bc_lstore_0 = 63, // 0x3f
- bc_lstore_1 = 64, // 0x40
- bc_lstore_2 = 65, // 0x41
- bc_lstore_3 = 66, // 0x42
- bc_fstore_0 = 67, // 0x43
- bc_fstore_1 = 68, // 0x44
- bc_fstore_2 = 69, // 0x45
- bc_fstore_3 = 70, // 0x46
- bc_dstore_0 = 71, // 0x47
- bc_dstore_1 = 72, // 0x48
- bc_dstore_2 = 73, // 0x49
- bc_dstore_3 = 74, // 0x4a
- bc_astore_0 = 75, // 0x4b
- bc_astore_1 = 76, // 0x4c
- bc_astore_2 = 77, // 0x4d
- bc_astore_3 = 78, // 0x4e
- bc_iastore = 79, // 0x4f
- bc_lastore = 80, // 0x50
- bc_fastore = 81, // 0x51
- bc_dastore = 82, // 0x52
- bc_aastore = 83, // 0x53
- bc_bastore = 84, // 0x54
- bc_castore = 85, // 0x55
- bc_sastore = 86, // 0x56
- bc_pop = 87, // 0x57
- bc_pop2 = 88, // 0x58
- bc_dup = 89, // 0x59
- bc_dup_x1 = 90, // 0x5a
- bc_dup_x2 = 91, // 0x5b
- bc_dup2 = 92, // 0x5c
- bc_dup2_x1 = 93, // 0x5d
- bc_dup2_x2 = 94, // 0x5e
- bc_swap = 95, // 0x5f
- bc_iadd = 96, // 0x60
- bc_ladd = 97, // 0x61
- bc_fadd = 98, // 0x62
- bc_dadd = 99, // 0x63
- bc_isub = 100, // 0x64
- bc_lsub = 101, // 0x65
- bc_fsub = 102, // 0x66
- bc_dsub = 103, // 0x67
- bc_imul = 104, // 0x68
- bc_lmul = 105, // 0x69
- bc_fmul = 106, // 0x6a
- bc_dmul = 107, // 0x6b
- bc_idiv = 108, // 0x6c
- bc_ldiv = 109, // 0x6d
- bc_fdiv = 110, // 0x6e
- bc_ddiv = 111, // 0x6f
- bc_irem = 112, // 0x70
- bc_lrem = 113, // 0x71
- bc_frem = 114, // 0x72
- bc_drem = 115, // 0x73
- bc_ineg = 116, // 0x74
- bc_lneg = 117, // 0x75
- bc_fneg = 118, // 0x76
- bc_dneg = 119, // 0x77
- bc_ishl = 120, // 0x78
- bc_lshl = 121, // 0x79
- bc_ishr = 122, // 0x7a
- bc_lshr = 123, // 0x7b
- bc_iushr = 124, // 0x7c
- bc_lushr = 125, // 0x7d
- bc_iand = 126, // 0x7e
- bc_land = 127, // 0x7f
- bc_ior = 128, // 0x80
- bc_lor = 129, // 0x81
- bc_ixor = 130, // 0x82
- bc_lxor = 131, // 0x83
- bc_iinc = 132, // 0x84
- bc_i2l = 133, // 0x85
- bc_i2f = 134, // 0x86
- bc_i2d = 135, // 0x87
- bc_l2i = 136, // 0x88
- bc_l2f = 137, // 0x89
- bc_l2d = 138, // 0x8a
- bc_f2i = 139, // 0x8b
- bc_f2l = 140, // 0x8c
- bc_f2d = 141, // 0x8d
- bc_d2i = 142, // 0x8e
- bc_d2l = 143, // 0x8f
- bc_d2f = 144, // 0x90
- bc_i2b = 145, // 0x91
- bc_i2c = 146, // 0x92
- bc_i2s = 147, // 0x93
- bc_lcmp = 148, // 0x94
- bc_fcmpl = 149, // 0x95
- bc_fcmpg = 150, // 0x96
- bc_dcmpl = 151, // 0x97
- bc_dcmpg = 152, // 0x98
- bc_ifeq = 153, // 0x99
- bc_ifne = 154, // 0x9a
- bc_iflt = 155, // 0x9b
- bc_ifge = 156, // 0x9c
- bc_ifgt = 157, // 0x9d
- bc_ifle = 158, // 0x9e
- bc_if_icmpeq = 159, // 0x9f
- bc_if_icmpne = 160, // 0xa0
- bc_if_icmplt = 161, // 0xa1
- bc_if_icmpge = 162, // 0xa2
- bc_if_icmpgt = 163, // 0xa3
- bc_if_icmple = 164, // 0xa4
- bc_if_acmpeq = 165, // 0xa5
- bc_if_acmpne = 166, // 0xa6
- bc_goto = 167, // 0xa7
- bc_jsr = 168, // 0xa8
- bc_ret = 169, // 0xa9
- bc_tableswitch = 170, // 0xaa
- bc_lookupswitch = 171, // 0xab
- bc_ireturn = 172, // 0xac
- bc_lreturn = 173, // 0xad
- bc_freturn = 174, // 0xae
- bc_dreturn = 175, // 0xaf
- bc_areturn = 176, // 0xb0
- bc_return = 177, // 0xb1
- bc_getstatic = 178, // 0xb2
- bc_putstatic = 179, // 0xb3
- bc_getfield = 180, // 0xb4
- bc_putfield = 181, // 0xb5
- bc_invokevirtual = 182, // 0xb6
- bc_invokespecial = 183, // 0xb7
- bc_invokestatic = 184, // 0xb8
- bc_invokeinterface = 185, // 0xb9
- bc_xxxunusedxxx = 186, // 0xba
- bc_new = 187, // 0xbb
- bc_newarray = 188, // 0xbc
- bc_anewarray = 189, // 0xbd
- bc_arraylength = 190, // 0xbe
- bc_athrow = 191, // 0xbf
- bc_checkcast = 192, // 0xc0
- bc_instanceof = 193, // 0xc1
- bc_monitorenter = 194, // 0xc2
- bc_monitorexit = 195, // 0xc3
- bc_wide = 196, // 0xc4
- bc_multianewarray = 197, // 0xc5
- bc_ifnull = 198, // 0xc6
- bc_ifnonnull = 199, // 0xc7
- bc_goto_w = 200, // 0xc8
- bc_jsr_w = 201, // 0xc9
- bc_bytecode_limit = 202 // 0xca
-};
-
-enum
-{
- bc_end_marker = 255,
- bc_byte_escape = 254,
- bc_ref_escape = 253,
- _first_linker_op = bc_getstatic,
- _last_linker_op = bc_invokestatic,
- _num_linker_ops = (_last_linker_op - _first_linker_op) + 1,
- _self_linker_op = bc_bytecode_limit,
- _self_linker_aload_flag = 1 * _num_linker_ops,
- _self_linker_super_flag = 2 * _num_linker_ops,
- _self_linker_limit = _self_linker_op + 4 * _num_linker_ops,
- _invokeinit_op = _self_linker_limit,
- _invokeinit_self_option = 0,
- _invokeinit_super_option = 1,
- _invokeinit_new_option = 2,
- _invokeinit_limit = _invokeinit_op + 3,
- _xldc_op = _invokeinit_limit,
- bc_aldc = bc_ldc,
- bc_cldc = _xldc_op + 0,
- bc_ildc = _xldc_op + 1,
- bc_fldc = _xldc_op + 2,
- bc_aldc_w = bc_ldc_w,
- bc_cldc_w = _xldc_op + 3,
- bc_ildc_w = _xldc_op + 4,
- bc_fldc_w = _xldc_op + 5,
- bc_lldc2_w = bc_ldc2_w,
- bc_dldc2_w = _xldc_op + 6,
- _xldc_limit = _xldc_op + 7,
- _xxx_3_end
-};
diff --git a/libraries/pack200/src/defines.h b/libraries/pack200/src/defines.h
deleted file mode 100644
index cfe5fc28..00000000
--- a/libraries/pack200/src/defines.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// random definitions
-
-#ifdef _MSC_VER
-#include <windows.h>
-#include <winuser.h>
-#else
-#include <unistd.h>
-#endif
-
-// Error messages that we have
-#define ERROR_ENOMEM "Memory allocation failed"
-#define ERROR_FORMAT "Corrupted pack file"
-#define ERROR_RESOURCE "Cannot extract resource file"
-#define ERROR_OVERFLOW "Internal buffer overflow"
-#define ERROR_INTERNAL "Internal error"
-
-#define lengthof(array) (sizeof(array) / sizeof(array[0]))
-
-#define NEW(T, n) (T *) must_malloc((int)(scale_size(n, sizeof(T))))
-#define U_NEW(T, n) (T *) u->alloc(scale_size(n, sizeof(T)))
-#define T_NEW(T, n) (T *) u->temp_alloc(scale_size(n, sizeof(T)))
-
-typedef signed char byte;
-
-#ifdef _MSC_VER
-#define MKDIR(dir) mkdir(dir)
-#define getpid() _getpid()
-#define PATH_MAX MAX_PATH
-#define dup2(a, b) _dup2(a, b)
-#define strcasecmp(s1, s2) _stricmp(s1, s2)
-#define tempname _tempname
-#define sleep Sleep
-#else
-#define MKDIR(dir) mkdir(dir, 0777);
-#endif
-
-/* Must cast to void *, then size_t, then int. */
-#define ptrlowbits(x) ((int)(size_t)(void *)(x))
-
-#define DEFAULT_ARCHIVE_MODTIME 1060000000 // Aug 04, 2003 5:26 PM PDT
diff --git a/libraries/pack200/src/unpack.cpp b/libraries/pack200/src/unpack.cpp
deleted file mode 100644
index 9c4c633c..00000000
--- a/libraries/pack200/src/unpack.cpp
+++ /dev/null
@@ -1,4790 +0,0 @@
-/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// -*- C++ -*-
-// Program for unpacking specially compressed Java packages.
-// John R. Rose
-
-/*
- * When compiling for a 64bit LP64 system (longs and pointers being 64bits),
- * the printf format %ld is correct and use of %lld will cause warning
- * errors from some compilers (gcc/g++).
- * _LP64 can be explicitly set (used on Linux).
- * Solaris compilers will define __sparcv9 or __x86_64 on 64bit compilations.
- */
-#include <cinttypes>
-
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <limits.h>
-#include <time.h>
-#include <stdint.h>
-
-#include "defines.h"
-#include "bytes.h"
-#include "utils.h"
-#include "coding.h"
-#include "bands.h"
-
-#include "constants.h"
-
-#include "zip.h"
-
-#include "unpack.h"
-
-// tags, in canonical order:
-static const byte TAGS_IN_ORDER[] = {
- CONSTANT_Utf8, CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long,
- CONSTANT_Double, CONSTANT_String, CONSTANT_Class, CONSTANT_Signature,
- CONSTANT_NameandType, CONSTANT_Fieldref, CONSTANT_Methodref, CONSTANT_InterfaceMethodref};
-#define N_TAGS_IN_ORDER (sizeof TAGS_IN_ORDER)
-
-// REQUESTED must be -2 for u2 and REQUESTED_LDC must be -1 for u1
-enum
-{
- NOT_REQUESTED = 0,
- REQUESTED = -2,
- REQUESTED_LDC = -1
-};
-
-#define NO_INORD ((uint32_t) - 1)
-
-struct entry
-{
- byte tag;
- unsigned short nrefs; // pack w/ tag
-
- int outputIndex;
- uint32_t inord; // &cp.entries[cp.tag_base[this->tag]+this->inord] == this
-
- entry **refs;
-
- // put last to pack best
- union
- {
- bytes b;
- int i;
- int64_t l;
- } value;
-
- void requestOutputIndex(constant_pool &cp, int req = REQUESTED);
- int getOutputIndex()
- {
- assert(outputIndex > NOT_REQUESTED);
- return outputIndex;
- }
-
- entry *ref(int refnum)
- {
- assert((uint32_t)refnum < nrefs);
- return refs[refnum];
- }
-
- const char *utf8String()
- {
- assert(tagMatches(CONSTANT_Utf8));
- assert(value.b.len == strlen((const char *)value.b.ptr));
- return (const char *)value.b.ptr;
- }
-
- entry *className()
- {
- assert(tagMatches(CONSTANT_Class));
- return ref(0);
- }
-
- entry *memberClass()
- {
- assert(tagMatches(CONSTANT_Member));
- return ref(0);
- }
-
- entry *memberDescr()
- {
- assert(tagMatches(CONSTANT_Member));
- return ref(1);
- }
-
- entry *descrName()
- {
- assert(tagMatches(CONSTANT_NameandType));
- return ref(0);
- }
-
- entry *descrType()
- {
- assert(tagMatches(CONSTANT_NameandType));
- return ref(1);
- }
-
- int typeSize();
-
- bytes &asUtf8();
- int asInteger()
- {
- assert(tag == CONSTANT_Integer);
- return value.i;
- }
-
- bool isUtf8(bytes &b)
- {
- return tagMatches(CONSTANT_Utf8) && value.b.equals(b);
- }
-
- bool isDoubleWord()
- {
- return tag == CONSTANT_Double || tag == CONSTANT_Long;
- }
-
- bool tagMatches(byte tag2)
- {
- return (tag2 == tag) || (tag2 == CONSTANT_Utf8 && tag == CONSTANT_Signature) ||
- (tag2 == CONSTANT_Literal && tag >= CONSTANT_Integer && tag <= CONSTANT_String &&
- tag != CONSTANT_Class) ||
- (tag2 == CONSTANT_Member && tag >= CONSTANT_Fieldref &&
- tag <= CONSTANT_InterfaceMethodref);
- }
-};
-
-entry *cpindex::get(uint32_t i)
-{
- if (i >= len)
- return nullptr;
- else if (base1 != nullptr)
- // primary index
- return &base1[i];
- else
- // secondary index
- return base2[i];
-}
-
-inline bytes &entry::asUtf8()
-{
- assert(tagMatches(CONSTANT_Utf8));
- return value.b;
-}
-
-int entry::typeSize()
-{
- assert(tagMatches(CONSTANT_Utf8));
- const char *sigp = (char *)value.b.ptr;
- switch (*sigp)
- {
- case '(':
- sigp++;
- break; // skip opening '('
- case 'D':
- case 'J':
- return 2; // double field
- default:
- return 1; // field
- }
- int siglen = 0;
- for (;;)
- {
- int ch = *sigp++;
- switch (ch)
- {
- case 'D':
- case 'J':
- siglen += 1;
- break;
- case '[':
- // Skip rest of array info.
- while (ch == '[')
- {
- ch = *sigp++;
- }
- if (ch != 'L')
- break;
- // else fall through
- case 'L':
- sigp = strchr(sigp, ';');
- if (sigp == nullptr)
- {
- unpack_abort("bad data");
- return 0;
- }
- sigp += 1;
- break;
- case ')': // closing ')'
- return siglen;
- }
- siglen += 1;
- }
-}
-
-inline cpindex *constant_pool::getFieldIndex(entry *classRef)
-{
- assert(classRef->tagMatches(CONSTANT_Class));
- assert((uint32_t)classRef->inord < (uint32_t)tag_count[CONSTANT_Class]);
- return &member_indexes[classRef->inord * 2 + 0];
-}
-inline cpindex *constant_pool::getMethodIndex(entry *classRef)
-{
- assert(classRef->tagMatches(CONSTANT_Class));
- assert((uint32_t)classRef->inord < (uint32_t)tag_count[CONSTANT_Class]);
- return &member_indexes[classRef->inord * 2 + 1];
-}
-
-struct inner_class
-{
- entry *inner;
- entry *outer;
- entry *name;
- int flags;
- inner_class *next_sibling;
- bool requested;
-};
-
-// Here is where everything gets deallocated:
-void unpacker::free()
-{
- int i;
- if (jarout != nullptr)
- jarout->reset();
- if (gzin != nullptr)
- {
- gzin->free();
- gzin = nullptr;
- }
- if (free_input)
- input.free();
- /*
- * free everybody ever allocated with U_NEW or (recently) with T_NEW
- */
- assert(smallbuf.base() == nullptr || mallocs.contains(smallbuf.base()));
- assert(tsmallbuf.base() == nullptr || tmallocs.contains(tsmallbuf.base()));
- mallocs.freeAll();
- tmallocs.freeAll();
- smallbuf.init();
- tsmallbuf.init();
- bcimap.free();
- class_fixup_type.free();
- class_fixup_offset.free();
- class_fixup_ref.free();
- code_fixup_type.free();
- code_fixup_offset.free();
- code_fixup_source.free();
- requested_ics.free();
- cur_classfile_head.free();
- cur_classfile_tail.free();
- for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
- attr_defs[i].free();
-
- // free CP state
- cp.outputEntries.free();
- for (i = 0; i < CONSTANT_Limit; i++)
- cp.tag_extras[i].free();
-}
-
-// input handling
-// Attempts to advance rplimit so that (rplimit-rp) is at least 'more'.
-// Will eagerly read ahead by larger chunks, if possible.
-// Returns false if (rplimit-rp) is not at least 'more',
-// unless rplimit hits input.limit().
-bool unpacker::ensure_input(int64_t more)
-{
- uint64_t want = more - input_remaining();
- if ((int64_t)want <= 0)
- return true; // it's already in the buffer
- if (rplimit == input.limit())
- return true; // not expecting any more
-
- if (read_input_fn == nullptr)
- {
- // assume it is already all there
- bytes_read += input.limit() - rplimit;
- rplimit = input.limit();
- return true;
- }
-
- uint64_t remaining = (input.limit() - rplimit); // how much left to read?
- byte *rpgoal = (want >= remaining) ? input.limit() : rplimit + (size_t)want;
- enum
- {
- CHUNK_SIZE = (1 << 14)
- };
- uint64_t fetch = want;
- if (fetch < CHUNK_SIZE)
- fetch = CHUNK_SIZE;
- if (fetch > remaining * 3 / 4)
- fetch = remaining;
- // Try to fetch at least "more" bytes.
- while ((int64_t)fetch > 0)
- {
- int64_t nr = (*read_input_fn)(this, rplimit, fetch, remaining);
- if (nr <= 0)
- {
- return (rplimit >= rpgoal);
- }
- remaining -= nr;
- rplimit += nr;
- fetch -= nr;
- bytes_read += nr;
- assert(remaining == (uint64_t)(input.limit() - rplimit));
- }
- return true;
-}
-
-// output handling
-
-fillbytes *unpacker::close_output(fillbytes *which)
-{
- assert(wp != nullptr);
- if (which == nullptr)
- {
- if (wpbase == cur_classfile_head.base())
- {
- which = &cur_classfile_head;
- }
- else
- {
- which = &cur_classfile_tail;
- }
- }
- assert(wpbase == which->base());
- assert(wplimit == which->end());
- which->setLimit(wp);
- wp = nullptr;
- wplimit = nullptr;
- // wpbase = nullptr;
- return which;
-}
-
-// maybe_inline
-void unpacker::ensure_put_space(size_t size)
-{
- if (wp + size <= wplimit)
- return;
- // Determine which segment needs expanding.
- fillbytes *which = close_output();
- byte *wp0 = which->grow(size);
- wpbase = which->base();
- wplimit = which->end();
- wp = wp0;
-}
-
-byte *unpacker::put_space(size_t size)
-{
- byte *wp0 = wp;
- byte *wp1 = wp0 + size;
- if (wp1 > wplimit)
- {
- ensure_put_space(size);
- wp0 = wp;
- wp1 = wp0 + size;
- }
- wp = wp1;
- return wp0;
-}
-
-void unpacker::putu2_at(byte *wp, int n)
-{
- if (n != (unsigned short)n)
- {
- unpack_abort(ERROR_OVERFLOW);
- return;
- }
- wp[0] = (n) >> 8;
- wp[1] = (n) >> 0;
-}
-
-void unpacker::putu4_at(byte *wp, int n)
-{
- wp[0] = (n) >> 24;
- wp[1] = (n) >> 16;
- wp[2] = (n) >> 8;
- wp[3] = (n) >> 0;
-}
-
-void unpacker::putu8_at(byte *wp, int64_t n)
-{
- putu4_at(wp + 0, (int)((uint64_t)n >> 32));
- putu4_at(wp + 4, (int)((uint64_t)n >> 0));
-}
-
-void unpacker::putu2(int n)
-{
- putu2_at(put_space(2), n);
-}
-
-void unpacker::putu4(int n)
-{
- putu4_at(put_space(4), n);
-}
-
-void unpacker::putu8(int64_t n)
-{
- putu8_at(put_space(8), n);
-}
-
-int unpacker::putref_index(entry *e, int size)
-{
- if (e == nullptr)
- return 0;
- else if (e->outputIndex > NOT_REQUESTED)
- return e->outputIndex;
- else if (e->tag == CONSTANT_Signature)
- return putref_index(e->ref(0), size);
- else
- {
- e->requestOutputIndex(cp, -size);
- // Later on we'll fix the bits.
- class_fixup_type.addByte(size);
- class_fixup_offset.add((int)wpoffset());
- class_fixup_ref.add(e);
- return 0;
- }
-}
-
-void unpacker::putref(entry *e)
-{
- int oidx = putref_index(e, 2);
- putu2_at(put_space(2), oidx);
-}
-
-void unpacker::putu1ref(entry *e)
-{
- int oidx = putref_index(e, 1);
- putu1_at(put_space(1), oidx);
-}
-
-// Allocation of small and large blocks.
-
-enum
-{
- CHUNK = (1 << 14),
- SMALL = (1 << 9)
-};
-
-// Call malloc. Try to combine small blocks and free much later.
-void *unpacker::alloc_heap(size_t size, bool smallOK, bool temp)
-{
- if (!smallOK || size > SMALL)
- {
- void *res = must_malloc((int)size);
- (temp ? &tmallocs : &mallocs)->add(res);
- return res;
- }
- fillbytes &xsmallbuf = *(temp ? &tsmallbuf : &smallbuf);
- if (!xsmallbuf.canAppend(size + 1))
- {
- xsmallbuf.init(CHUNK);
- (temp ? &tmallocs : &mallocs)->add(xsmallbuf.base());
- }
- int growBy = (int)size;
- growBy += -growBy & 7; // round up mod 8
- return xsmallbuf.grow(growBy);
-}
-
-void unpacker::saveTo(bytes &b, byte *ptr, size_t len)
-{
- b.ptr = U_NEW(byte, add_size(len, 1));
- b.len = len;
- b.copyFrom(ptr, len);
-}
-
-// Read up through band_headers.
-// Do the archive_size dance to set the size of the input mega-buffer.
-void unpacker::read_file_header()
-{
- // Read file header to determine file type and total size.
- enum
- {
- MAGIC_BYTES = 4,
- AH_LENGTH_0 = 3, // minver, majver, options are outside of archive_size
- AH_LENGTH_0_MAX = AH_LENGTH_0 + 1, // options might have 2 bytes
- AH_LENGTH = 26, // maximum archive header length (w/ all fields)
- // Length contributions from optional header fields:
- AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files
- AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN
- AH_CP_NUMBER_LEN = 4, // int/float/long/double
- AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
- AH_LENGTH_MIN =
- AH_LENGTH - (AH_FILE_HEADER_LEN + AH_SPECIAL_FORMAT_LEN + AH_CP_NUMBER_LEN),
- ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN),
- FIRST_READ = MAGIC_BYTES + AH_LENGTH_MIN
- };
-
- assert(AH_LENGTH_MIN == 15); // # of UNSIGNED5 fields required after archive_magic
- assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size
- // An absolute minimum nullptr archive is magic[4], {minver,majver,options}[3],
- // archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes.
- // (Note that archive_size is optional; it may be 0..10 bytes in length.)
- // The first read must capture everything up through the options field.
- // This happens to work even if {minver,majver,options} is a pathological
- // 15 bytes long. Legal pack files limit those three fields to 1+1+2 bytes.
- assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0 * B_MAX);
-
- // Up through archive_size, the largest possible archive header is
- // magic[4], {minver,majver,options}[4], archive_size[10].
- // (Note only the low 12 bits of options are allowed to be non-zero.)
- // In order to parse archive_size, we need at least this many bytes
- // in the first read. Of course, if archive_size_hi is more than
- // a byte, we probably will fail to allocate the buffer, since it
- // will be many gigabytes long. This is a practical, not an
- // architectural limit to Pack200 archive sizes.
- assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0_MAX + 2 * B_MAX);
-
- bool foreign_buf = (read_input_fn == nullptr);
- byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200]; // 200 is for JAR I/O
- if (foreign_buf)
- {
- // inbytes is all there is
- input.set(inbytes);
- rp = input.base();
- rplimit = input.limit();
- }
- else
- {
- // inbytes, if not empty, contains some read-ahead we must use first
- // ensure_input will take care of copying it into initbuf,
- // then querying read_input_fn for any additional data needed.
- // However, the caller must assume that we use up all of inbytes.
- // There is no way to tell the caller that we used only part of them.
- // Therefore, the caller must use only a bare minimum of read-ahead.
- if (inbytes.len > FIRST_READ)
- {
- unpack_abort("too much read-ahead");
- }
- input.set(initbuf, sizeof(initbuf));
- input.b.clear();
- input.b.copyFrom(inbytes);
- rplimit = rp = input.base();
- rplimit += inbytes.len;
- bytes_read += inbytes.len;
- }
- // Read only 19 bytes, which is certain to contain #archive_options fields,
- // but is certain not to overflow past the archive_header.
- input.b.len = FIRST_READ;
- if (!ensure_input(FIRST_READ))
- unpack_abort("EOF reading archive magic number");
-
- if (rp[0] == 'P' && rp[1] == 'K')
- {
- // In the Unix-style program, we simply simulate a copy command.
- // Copy until EOF; assume the JAR file is the last segment.
- fprintf(stderr, "Copy-mode.\n");
- for (;;)
- {
- jarout->write_data(rp, (int)input_remaining());
- if (foreign_buf)
- break; // one-time use of a passed in buffer
- if (input.size() < CHUNK)
- {
- // Get some breathing room.
- input.set(U_NEW(byte, (size_t)CHUNK + C_SLOP), (size_t)CHUNK);
- }
- rp = rplimit = input.base();
- if (!ensure_input(1))
- break;
- }
- jarout->closeJarFile(false);
- return;
- }
-
- // Read the magic number.
- magic = 0;
- for (int i1 = 0; i1 < (int)sizeof(magic); i1++)
- {
- magic <<= 8;
- magic += (*rp++ & 0xFF);
- }
-
- // Read the first 3 values from the header.
- value_stream hdr;
- int hdrVals = 0;
- int hdrValsSkipped = 0; // debug only
- hdr.init(rp, rplimit, UNSIGNED5_spec);
- minver = hdr.getInt();
- majver = hdr.getInt();
- hdrVals += 2;
-
- if (magic != (int)JAVA_PACKAGE_MAGIC ||
- (majver != JAVA5_PACKAGE_MAJOR_VERSION && majver != JAVA6_PACKAGE_MAJOR_VERSION) ||
- (minver != JAVA5_PACKAGE_MINOR_VERSION && minver != JAVA6_PACKAGE_MINOR_VERSION))
- {
- char message[200];
- sprintf(message, "@" ERROR_FORMAT ": magic/ver = "
- "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d\n",
- magic, majver, minver, JAVA_PACKAGE_MAGIC, JAVA5_PACKAGE_MAJOR_VERSION,
- JAVA5_PACKAGE_MINOR_VERSION, JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION,
- JAVA6_PACKAGE_MINOR_VERSION);
- unpack_abort(message);
- }
-
- archive_options = hdr.getInt();
- hdrVals += 1;
- assert(hdrVals == AH_LENGTH_0); // first three fields only
-
-#define ORBIT(bit) | (bit)
- int OPTION_LIMIT = (0 ARCHIVE_BIT_DO(ORBIT));
-#undef ORBIT
- if ((archive_options & ~OPTION_LIMIT) != 0)
- {
- fprintf(stderr, "Warning: Illegal archive options 0x%x\n", archive_options);
- unpack_abort("illegal archive options");
- return;
- }
-
- if ((archive_options & AO_HAVE_FILE_HEADERS) != 0)
- {
- uint32_t hi = hdr.getInt();
- uint32_t lo = hdr.getInt();
- uint64_t x = band::makeLong(hi, lo);
- archive_size = (size_t)x;
- if (archive_size != x)
- {
- // Silly size specified; force overflow.
- archive_size = PSIZE_MAX + 1;
- }
- hdrVals += 2;
- }
- else
- {
- hdrValsSkipped += 2;
- }
-
- // Now we can size the whole archive.
- // Read everything else into a mega-buffer.
- rp = hdr.rp;
- int header_size_0 = (int)(rp - input.base()); // used-up header (4byte + 3int)
- int header_size_1 = (int)(rplimit - rp); // buffered unused initial fragment
- int header_size = header_size_0 + header_size_1;
- unsized_bytes_read = header_size_0;
- if (foreign_buf)
- {
- if (archive_size > (size_t)header_size_1)
- {
- unpack_abort("EOF reading fixed input buffer");
- return;
- }
- }
- else if (archive_size != 0)
- {
- if (archive_size < ARCHIVE_SIZE_MIN)
- {
- unpack_abort("impossible archive size"); // bad input data
- return;
- }
- if (archive_size < (size_t)header_size_1)
- {
- unpack_abort("too much read-ahead"); // somehow we pre-fetched too much?
- return;
- }
- input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)),
- (size_t)header_size_0 + archive_size);
- assert(input.limit()[0] == 0);
- // Move all the bytes we read initially into the real buffer.
- input.b.copyFrom(initbuf, header_size);
- rp = input.b.ptr + header_size_0;
- rplimit = input.b.ptr + header_size;
- }
- else
- {
- // It's more complicated and painful.
- // A zero archive_size means that we must read until EOF.
- input.init(CHUNK * 2);
- input.b.len = input.allocated;
- rp = rplimit = input.base();
- // Set up input buffer as if we already read the header:
- input.b.copyFrom(initbuf, header_size);
- rplimit += header_size;
- while (ensure_input(input.limit() - rp))
- {
- size_t dataSoFar = input_remaining();
- size_t nextSize = add_size(dataSoFar, CHUNK);
- input.ensureSize(nextSize);
- input.b.len = input.allocated;
- rp = rplimit = input.base();
- rplimit += dataSoFar;
- }
- size_t dataSize = (rplimit - input.base());
- input.b.len = dataSize;
- input.grow(C_SLOP);
- free_input = true; // free it later
- input.b.len = dataSize;
- assert(input.limit()[0] == 0);
- rp = rplimit = input.base();
- rplimit += dataSize;
- rp += header_size_0; // already scanned these bytes...
- }
- live_input = true; // mark as "do not reuse"
-
- // read the rest of the header fields
- ensure_input((AH_LENGTH - AH_LENGTH_0) * B_MAX);
- hdr.rp = rp;
- hdr.rplimit = rplimit;
-
- if ((archive_options & AO_HAVE_FILE_HEADERS) != 0)
- {
- archive_next_count = hdr.getInt();
- if (archive_next_count < 0)
- unpack_abort("bad archive_next_count");
- archive_modtime = hdr.getInt();
- file_count = hdr.getInt();
- if (file_count < 0)
- unpack_abort("bad file_count");
- hdrVals += 3;
- }
- else
- {
- hdrValsSkipped += 3;
- }
-
- if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0)
- {
- band_headers_size = hdr.getInt();
- if (band_headers_size < 0)
- unpack_abort("bad band_headers_size");
- attr_definition_count = hdr.getInt();
- if (attr_definition_count < 0)
- unpack_abort("bad attr_definition_count");
- hdrVals += 2;
- }
- else
- {
- hdrValsSkipped += 2;
- }
-
- int cp_counts[N_TAGS_IN_ORDER];
- for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++)
- {
- if (!(archive_options & AO_HAVE_CP_NUMBERS))
- {
- switch (TAGS_IN_ORDER[k])
- {
- case CONSTANT_Integer:
- case CONSTANT_Float:
- case CONSTANT_Long:
- case CONSTANT_Double:
- cp_counts[k] = 0;
- hdrValsSkipped += 1;
- continue;
- }
- }
- cp_counts[k] = hdr.getInt();
- if (cp_counts[k] < 0)
- unpack_abort("bad cp_counts");
- hdrVals += 1;
- }
-
- ic_count = hdr.getInt();
- if (ic_count < 0)
- unpack_abort("bad ic_count");
-
- default_class_minver = hdr.getInt();
- default_class_majver = hdr.getInt();
-
- class_count = hdr.getInt();
- if (class_count < 0)
- unpack_abort("bad class_count");
-
- hdrVals += 4;
-
- // done with archive_header
- hdrVals += hdrValsSkipped;
- assert(hdrVals == AH_LENGTH);
-
- rp = hdr.rp;
- if (rp > rplimit)
- unpack_abort("EOF reading archive header");
-
- // Now size the CP.
- cp.init(this, cp_counts);
-
- default_file_modtime = archive_modtime;
- if (default_file_modtime == 0 && !(archive_options & AO_HAVE_FILE_MODTIME))
- default_file_modtime = DEFAULT_ARCHIVE_MODTIME; // taken from driver
- if ((archive_options & AO_DEFLATE_HINT) != 0)
- default_file_options |= FO_DEFLATE_HINT;
-
- // meta-bytes, if any, immediately follow archive header
- // band_headers.readData(band_headers_size);
- ensure_input(band_headers_size);
- if (input_remaining() < (size_t)band_headers_size)
- {
- unpack_abort("EOF reading band headers");
- return;
- }
- bytes band_headers;
- // The "1+" allows an initial byte to be pushed on the front.
- band_headers.set(1 + U_NEW(byte, 1 + band_headers_size + C_SLOP), band_headers_size);
-
- // Start scanning band headers here:
- band_headers.copyFrom(rp, band_headers.len);
- rp += band_headers.len;
- assert(rp <= rplimit);
- meta_rp = band_headers.ptr;
- // Put evil meta-codes at the end of the band headers,
- // so we are sure to throw an error if we run off the end.
- bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error);
-}
-
-void unpacker::finish()
-{
- if (verbose >= 1)
- {
- fprintf(stderr, "A total of %" PRIu64 " bytes were read in %d segment(s).\n",
- (bytes_read_before_reset + bytes_read), segments_read_before_reset + 1);
- fprintf(stderr, "A total of %" PRIu64 " file content bytes were written.\n",
- (bytes_written_before_reset + bytes_written));
- fprintf(stderr,
- "A total of %d files (of which %d are classes) were written to output.\n",
- files_written_before_reset + files_written,
- classes_written_before_reset + classes_written);
- }
- if (jarout != nullptr)
- jarout->closeJarFile(true);
-}
-
-// Cf. PackageReader.readConstantPoolCounts
-void constant_pool::init(unpacker *u_, int counts[NUM_COUNTS])
-{
- this->u = u_;
-
- // Fill-pointer for CP.
- int next_entry = 0;
-
- // Size the constant pool:
- for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++)
- {
- byte tag = TAGS_IN_ORDER[k];
- int len = counts[k];
- tag_count[tag] = len;
- tag_base[tag] = next_entry;
- next_entry += len;
- // Detect and defend against constant pool size overflow.
- // (Pack200 forbids the sum of CP counts to exceed 2^29-1.)
- enum
- {
- CP_SIZE_LIMIT = (1 << 29),
- IMPLICIT_ENTRY_COUNT = 1 // empty Utf8 string
- };
- if (len >= (1 << 29) || len < 0 || next_entry >= CP_SIZE_LIMIT + IMPLICIT_ENTRY_COUNT)
- {
- unpack_abort("archive too large: constant pool limit exceeded");
- }
- }
-
- // Close off the end of the CP:
- nentries = next_entry;
-
- // place a limit on future CP growth:
- int generous = 0;
- generous = add_size(generous, u->ic_count); // implicit name
- generous = add_size(generous, u->ic_count); // outer
- generous = add_size(generous, u->ic_count); // outer.utf8
- generous = add_size(generous, 40); // WKUs, misc
- generous = add_size(generous, u->class_count); // implicit SourceFile strings
- maxentries = add_size(nentries, generous);
-
- // Note that this CP does not include "empty" entries
- // for longs and doubles. Those are introduced when
- // the entries are renumbered for classfile output.
-
- entries = U_NEW(entry, maxentries);
-
- first_extra_entry = &entries[nentries];
-
- // Initialize the standard indexes.
- tag_count[CONSTANT_All] = nentries;
- tag_base[CONSTANT_All] = 0;
- for (int tag = 0; tag < CONSTANT_Limit; tag++)
- {
- entry *cpMap = &entries[tag_base[tag]];
- tag_index[tag].init(tag_count[tag], cpMap, tag);
- }
-
- // Initialize hashTab to a generous power-of-two size.
- uint32_t pow2 = 1;
- uint32_t target = maxentries + maxentries / 2; // 60% full
- while (pow2 < target)
- pow2 <<= 1;
- hashTab = U_NEW(entry *, hashTabLength = pow2);
-}
-
-static byte *store_Utf8_char(byte *cp, unsigned short ch)
-{
- if (ch >= 0x001 && ch <= 0x007F)
- {
- *cp++ = (byte)ch;
- }
- else if (ch <= 0x07FF)
- {
- *cp++ = (byte)(0xC0 | ((ch >> 6) & 0x1F));
- *cp++ = (byte)(0x80 | ((ch >> 0) & 0x3F));
- }
- else
- {
- *cp++ = (byte)(0xE0 | ((ch >> 12) & 0x0F));
- *cp++ = (byte)(0x80 | ((ch >> 6) & 0x3F));
- *cp++ = (byte)(0x80 | ((ch >> 0) & 0x3F));
- }
- return cp;
-}
-
-static byte *skip_Utf8_chars(byte *cp, int len)
-{
- for (;; cp++)
- {
- int ch = *cp & 0xFF;
- if ((ch & 0xC0) != 0x80)
- {
- if (len-- == 0)
- return cp;
- if (ch < 0x80 && len == 0)
- return cp + 1;
- }
- }
-}
-
-static int compare_Utf8_chars(bytes &b1, bytes &b2)
-{
- int l1 = (int)b1.len;
- int l2 = (int)b2.len;
- int l0 = (l1 < l2) ? l1 : l2;
- byte *p1 = b1.ptr;
- byte *p2 = b2.ptr;
- int c0 = 0;
- for (int i = 0; i < l0; i++)
- {
- int c1 = p1[i] & 0xFF;
- int c2 = p2[i] & 0xFF;
- if (c1 != c2)
- {
- // Before returning the obvious answer,
- // check to see if c1 or c2 is part of a 0x0000,
- // which encodes as {0xC0,0x80}. The 0x0000 is the
- // lowest-sorting Java char value, and yet it encodes
- // as if it were the first char after 0x7F, which causes
- // strings containing nulls to sort too high. All other
- // comparisons are consistent between Utf8 and Java chars.
- if (c1 == 0xC0 && (p1[i + 1] & 0xFF) == 0x80)
- c1 = 0;
- if (c2 == 0xC0 && (p2[i + 1] & 0xFF) == 0x80)
- c2 = 0;
- if (c0 == 0xC0)
- {
- assert(((c1 | c2) & 0xC0) == 0x80); // c1 & c2 are extension chars
- if (c1 == 0x80)
- c1 = 0; // will sort below c2
- if (c2 == 0x80)
- c2 = 0; // will sort below c1
- }
- return c1 - c2;
- }
- c0 = c1; // save away previous char
- }
- // common prefix is identical; return length difference if any
- return l1 - l2;
-}
-
-// Cf. PackageReader.readUtf8Bands
-void unpacker::read_Utf8_values(entry *cpMap, int len)
-{
- // Implicit first Utf8 string is the empty string.
- enum
- {
- // certain bands begin with implicit zeroes
- PREFIX_SKIP_2 = 2,
- SUFFIX_SKIP_1 = 1
- };
-
- int i;
-
- // First band: Read lengths of shared prefixes.
- if (len > PREFIX_SKIP_2)
- cp_Utf8_prefix.readData(len - PREFIX_SKIP_2);
-
- // Second band: Read lengths of unshared suffixes:
- if (len > SUFFIX_SKIP_1)
- cp_Utf8_suffix.readData(len - SUFFIX_SKIP_1);
-
- bytes *allsuffixes = T_NEW(bytes, len);
-
- int nbigsuf = 0;
- fillbytes charbuf; // buffer to allocate small strings
- charbuf.init();
-
- // Third band: Read the char values in the unshared suffixes:
- cp_Utf8_chars.readData(cp_Utf8_suffix.getIntTotal());
- for (i = 0; i < len; i++)
- {
- int suffix = (i < SUFFIX_SKIP_1) ? 0 : cp_Utf8_suffix.getInt();
- if (suffix < 0)
- {
- unpack_abort("bad utf8 suffix");
- }
- if (suffix == 0 && i >= SUFFIX_SKIP_1)
- {
- // chars are packed in cp_Utf8_big_chars
- nbigsuf += 1;
- continue;
- }
- bytes &chars = allsuffixes[i];
- uint32_t size3 = suffix * 3; // max Utf8 length
- bool isMalloc = (suffix > SMALL);
- if (isMalloc)
- {
- chars.malloc(size3);
- }
- else
- {
- if (!charbuf.canAppend(size3 + 1))
- {
- assert(charbuf.allocated == 0 || tmallocs.contains(charbuf.base()));
- charbuf.init(CHUNK); // Reset to new buffer.
- tmallocs.add(charbuf.base());
- }
- chars.set(charbuf.grow(size3 + 1), size3);
- }
-
- byte *chp = chars.ptr;
- for (int j = 0; j < suffix; j++)
- {
- unsigned short ch = cp_Utf8_chars.getInt();
- chp = store_Utf8_char(chp, ch);
- }
- // shrink to fit:
- if (isMalloc)
- {
- chars.realloc(chp - chars.ptr);
- tmallocs.add(chars.ptr); // free it later
- }
- else
- {
- int shrink = (int)(chars.limit() - chp);
- chars.len -= shrink;
- charbuf.b.len -= shrink; // ungrow to reclaim buffer space
- // Note that we did not reclaim the final '\0'.
- assert(chars.limit() == charbuf.limit() - 1);
- assert(strlen((char *)chars.ptr) == chars.len);
- }
- }
- // cp_Utf8_chars.done();
-
- // Fourth band: Go back and size the specially packed strings.
- int maxlen = 0;
- cp_Utf8_big_suffix.readData(nbigsuf);
- cp_Utf8_suffix.rewind();
- for (i = 0; i < len; i++)
- {
- int suffix = (i < SUFFIX_SKIP_1) ? 0 : cp_Utf8_suffix.getInt();
- int prefix = (i < PREFIX_SKIP_2) ? 0 : cp_Utf8_prefix.getInt();
- if (prefix < 0 || prefix + suffix < 0)
- {
- unpack_abort("bad utf8 prefix");
- }
- bytes &chars = allsuffixes[i];
- if (suffix == 0 && i >= SUFFIX_SKIP_1)
- {
- suffix = cp_Utf8_big_suffix.getInt();
- assert(chars.ptr == nullptr);
- chars.len = suffix; // just a momentary hack
- }
- else
- {
- assert(chars.ptr != nullptr);
- }
- if (maxlen < prefix + suffix)
- {
- maxlen = prefix + suffix;
- }
- }
- // cp_Utf8_suffix.done(); // will use allsuffixes[i].len (ptr!=nullptr)
- // cp_Utf8_big_suffix.done(); // will use allsuffixes[i].len
-
- // Fifth band(s): Get the specially packed characters.
- cp_Utf8_big_suffix.rewind();
- for (i = 0; i < len; i++)
- {
- bytes &chars = allsuffixes[i];
- if (chars.ptr != nullptr)
- continue; // already input
- int suffix = (int)chars.len; // pick up the hack
- uint32_t size3 = suffix * 3;
- if (suffix == 0)
- continue; // done with empty string
- chars.malloc(size3);
- byte *chp = chars.ptr;
- band saved_band = cp_Utf8_big_chars;
- cp_Utf8_big_chars.readData(suffix);
- for (int j = 0; j < suffix; j++)
- {
- unsigned short ch = cp_Utf8_big_chars.getInt();
- chp = store_Utf8_char(chp, ch);
- }
- chars.realloc(chp - chars.ptr);
- tmallocs.add(chars.ptr); // free it later
- // cp_Utf8_big_chars.done();
- cp_Utf8_big_chars = saved_band; // reset the band for the next string
- }
- cp_Utf8_big_chars.readData(0); // zero chars
- // cp_Utf8_big_chars.done();
-
- // Finally, sew together all the prefixes and suffixes.
- bytes bigbuf;
- bigbuf.malloc(maxlen * 3 + 1); // max Utf8 length, plus slop for nullptr
- int prevlen = 0; // previous string length (in chars)
- tmallocs.add(bigbuf.ptr); // free after this block
- cp_Utf8_prefix.rewind();
- for (i = 0; i < len; i++)
- {
- bytes &chars = allsuffixes[i];
- int prefix = (i < PREFIX_SKIP_2) ? 0 : cp_Utf8_prefix.getInt();
- int suffix = (int)chars.len;
- byte *fillp;
- // by induction, the buffer is already filled with the prefix
- // make sure the prefix value is not corrupted, though:
- if (prefix > prevlen)
- {
- unpack_abort("utf8 prefix overflow");
- return;
- }
- fillp = skip_Utf8_chars(bigbuf.ptr, prefix);
- // copy the suffix into the same buffer:
- fillp = chars.writeTo(fillp);
- assert(bigbuf.inBounds(fillp));
- *fillp = 0; // bigbuf must contain a well-formed Utf8 string
- int length = (int)(fillp - bigbuf.ptr);
- bytes &value = cpMap[i].value.b;
- value.set(U_NEW(byte, add_size(length, 1)), length);
- value.copyFrom(bigbuf.ptr, length);
- // Index all Utf8 strings
- entry *&htref = cp.hashTabRef(CONSTANT_Utf8, value);
- if (htref == nullptr)
- {
- // Note that if two identical strings are transmitted,
- // the first is taken to be the canonical one.
- htref = &cpMap[i];
- }
- prevlen = prefix + suffix;
- }
- // cp_Utf8_prefix.done();
-
- // Free intermediate buffers.
- free_temps();
-}
-
-void unpacker::read_single_words(band &cp_band, entry *cpMap, int len)
-{
- cp_band.readData(len);
- for (int i = 0; i < len; i++)
- {
- cpMap[i].value.i = cp_band.getInt(); // coding handles signs OK
- }
-}
-
-void unpacker::read_double_words(band &cp_bands, entry *cpMap, int len)
-{
- band &cp_band_hi = cp_bands;
- band &cp_band_lo = cp_bands.nextBand();
- cp_band_hi.readData(len);
- cp_band_lo.readData(len);
- for (int i = 0; i < len; i++)
- {
- cpMap[i].value.l = cp_band_hi.getLong(cp_band_lo, true);
- }
- // cp_band_hi.done();
- // cp_band_lo.done();
-}
-
-void unpacker::read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len)
-{
- assert(refTag == CONSTANT_Utf8);
- cp_band.setIndexByTag(refTag);
- cp_band.readData(len);
- int indexTag = (cp_band.bn == e_cp_Class) ? CONSTANT_Class : 0;
- for (int i = 0; i < len; i++)
- {
- entry &e = cpMap[i];
- e.refs = U_NEW(entry *, e.nrefs = 1);
- entry *utf = cp_band.getRef();
- e.refs[0] = utf;
- e.value.b = utf->value.b; // copy value of Utf8 string to self
- if (indexTag != 0)
- {
- // Maintain cross-reference:
- entry *&htref = cp.hashTabRef(indexTag, e.value.b);
- if (htref == nullptr)
- {
- // Note that if two identical classes are transmitted,
- // the first is taken to be the canonical one.
- htref = &e;
- }
- }
- }
- // cp_band.done();
-}
-
-void unpacker::read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap,
- int len)
-{
- band &cp_band1 = cp_band;
- band &cp_band2 = cp_band.nextBand();
- cp_band1.setIndexByTag(ref1Tag);
- cp_band2.setIndexByTag(ref2Tag);
- cp_band1.readData(len);
- cp_band2.readData(len);
- for (int i = 0; i < len; i++)
- {
- entry &e = cpMap[i];
- e.refs = U_NEW(entry *, e.nrefs = 2);
- e.refs[0] = cp_band1.getRef();
- e.refs[1] = cp_band2.getRef();
- }
- // cp_band1.done();
- // cp_band2.done();
-}
-
-// Cf. PackageReader.readSignatureBands
-void unpacker::read_signature_values(entry *cpMap, int len)
-{
- cp_Signature_form.setIndexByTag(CONSTANT_Utf8);
- cp_Signature_form.readData(len);
- int ncTotal = 0;
- int i;
- for (i = 0; i < len; i++)
- {
- entry &e = cpMap[i];
- entry &form = *cp_Signature_form.getRef();
- int nc = 0;
-
- for (const char *ncp = form.utf8String(); *ncp; ncp++)
- {
- if (*ncp == 'L')
- nc++;
- }
-
- ncTotal += nc;
- e.refs = U_NEW(entry *, cpMap[i].nrefs = 1 + nc);
- e.refs[0] = &form;
- }
- // cp_Signature_form.done();
- cp_Signature_classes.setIndexByTag(CONSTANT_Class);
- cp_Signature_classes.readData(ncTotal);
- for (i = 0; i < len; i++)
- {
- entry &e = cpMap[i];
- for (int j = 1; j < e.nrefs; j++)
- {
- e.refs[j] = cp_Signature_classes.getRef();
- }
- }
- // cp_Signature_classes.done();
-}
-
-// Cf. PackageReader.readConstantPool
-void unpacker::read_cp()
-{
- int i;
-
- for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++)
- {
- byte tag = TAGS_IN_ORDER[k];
- int len = cp.tag_count[tag];
- int base = cp.tag_base[tag];
-
- entry *cpMap = &cp.entries[base];
- for (i = 0; i < len; i++)
- {
- cpMap[i].tag = tag;
- cpMap[i].inord = i;
- }
-
- switch (tag)
- {
- case CONSTANT_Utf8:
- read_Utf8_values(cpMap, len);
- break;
- case CONSTANT_Integer:
- read_single_words(cp_Int, cpMap, len);
- break;
- case CONSTANT_Float:
- read_single_words(cp_Float, cpMap, len);
- break;
- case CONSTANT_Long:
- read_double_words(cp_Long_hi /*& cp_Long_lo*/, cpMap, len);
- break;
- case CONSTANT_Double:
- read_double_words(cp_Double_hi /*& cp_Double_lo*/, cpMap, len);
- break;
- case CONSTANT_String:
- read_single_refs(cp_String, CONSTANT_Utf8, cpMap, len);
- break;
- case CONSTANT_Class:
- read_single_refs(cp_Class, CONSTANT_Utf8, cpMap, len);
- break;
- case CONSTANT_Signature:
- read_signature_values(cpMap, len);
- break;
- case CONSTANT_NameandType:
- read_double_refs(cp_Descr_name /*& cp_Descr_type*/, CONSTANT_Utf8,
- CONSTANT_Signature, cpMap, len);
- break;
- case CONSTANT_Fieldref:
- read_double_refs(cp_Field_class /*& cp_Field_desc*/, CONSTANT_Class,
- CONSTANT_NameandType, cpMap, len);
- break;
- case CONSTANT_Methodref:
- read_double_refs(cp_Method_class /*& cp_Method_desc*/, CONSTANT_Class,
- CONSTANT_NameandType, cpMap, len);
- break;
- case CONSTANT_InterfaceMethodref:
- read_double_refs(cp_Imethod_class /*& cp_Imethod_desc*/, CONSTANT_Class,
- CONSTANT_NameandType, cpMap, len);
- break;
- default:
- assert(false);
- break;
- }
- }
-
- cp.expandSignatures();
- cp.initMemberIndexes();
-
-#define SNAME(n, s) #s "\0"
- const char *symNames = (ALL_ATTR_DO(SNAME) "<init>");
-#undef SNAME
-
- for (int sn = 0; sn < constant_pool::s_LIMIT; sn++)
- {
- assert(symNames[0] >= '0' && symNames[0] <= 'Z'); // sanity
- bytes name;
- name.set(symNames);
- if (name.len > 0 && name.ptr[0] != '0')
- {
- cp.sym[sn] = cp.ensureUtf8(name);
- }
- symNames += name.len + 1; // skip trailing nullptr to next name
- }
-
- band::initIndexes(this);
-}
-
-static band *no_bands[] = {nullptr}; // shared empty body
-
-inline band &unpacker::attr_definitions::fixed_band(int e_class_xxx)
-{
- return u->all_bands[xxx_flags_hi_bn + (e_class_xxx - e_class_flags_hi)];
-}
-inline band &unpacker::attr_definitions::xxx_flags_hi()
-{
- return fixed_band(e_class_flags_hi);
-}
-inline band &unpacker::attr_definitions::xxx_flags_lo()
-{
- return fixed_band(e_class_flags_lo);
-}
-inline band &unpacker::attr_definitions::xxx_attr_count()
-{
- return fixed_band(e_class_attr_count);
-}
-inline band &unpacker::attr_definitions::xxx_attr_indexes()
-{
- return fixed_band(e_class_attr_indexes);
-}
-inline band &unpacker::attr_definitions::xxx_attr_calls()
-{
- return fixed_band(e_class_attr_calls);
-}
-
-inline unpacker::layout_definition *
-unpacker::attr_definitions::defineLayout(int idx, entry *nameEntry, const char *layout)
-{
- const char *name = nameEntry->value.b.strval();
- layout_definition *lo = defineLayout(idx, name, layout);
- lo->nameEntry = nameEntry;
- return lo;
-}
-
-unpacker::layout_definition *unpacker::attr_definitions::defineLayout(int idx, const char *name,
- const char *layout)
-{
- assert(flag_limit != 0); // must be set up already
- if (idx >= 0)
- {
- // Fixed attr.
- if (idx >= (int)flag_limit)
- unpack_abort("attribute index too large");
- if (isRedefined(idx))
- unpack_abort("redefined attribute index");
- redef |= ((uint64_t)1 << idx);
- }
- else
- {
- idx = flag_limit + overflow_count.length();
- overflow_count.add(0); // make a new counter
- }
- layout_definition *lo = U_NEW(layout_definition, 1);
- lo->idx = idx;
- lo->name = name;
- lo->layout = layout;
- for (int adds = (idx + 1) - layouts.length(); adds > 0; adds--)
- {
- layouts.add(nullptr);
- }
- layouts.get(idx) = lo;
- return lo;
-}
-
-band **unpacker::attr_definitions::buildBands(unpacker::layout_definition *lo)
-{
- int i;
- if (lo->elems != nullptr)
- return lo->bands();
- if (lo->layout[0] == '\0')
- {
- lo->elems = no_bands;
- }
- else
- {
- // Create bands for this attribute by parsing the layout.
- bool hasCallables = lo->hasCallables();
- bands_made = 0x10000; // base number for bands made
- const char *lp = lo->layout;
- lp = parseLayout(lp, lo->elems, -1);
- if (lp[0] != '\0' || band_stack.length() > 0)
- {
- unpack_abort("garbage at end of layout");
- }
- band_stack.popTo(0);
-
- // Fix up callables to point at their callees.
- band **bands = lo->elems;
- assert(bands == lo->bands());
- int num_callables = 0;
- if (hasCallables)
- {
- while (bands[num_callables] != nullptr)
- {
- if (bands[num_callables]->le_kind != EK_CBLE)
- {
- unpack_abort("garbage mixed with callables");
- break;
- }
- num_callables += 1;
- }
- }
- for (i = 0; i < calls_to_link.length(); i++)
- {
- band &call = *(band *)calls_to_link.get(i);
- assert(call.le_kind == EK_CALL);
- // Determine the callee.
- int call_num = call.le_len;
- if (call_num < 0 || call_num >= num_callables)
- {
- unpack_abort("bad call in layout");
- break;
- }
- band &cble = *bands[call_num];
- // Link the call to it.
- call.le_body[0] = &cble;
- // Distinguish backward calls and callables:
- assert(cble.le_kind == EK_CBLE);
- // FIXME: hit this one
- // assert(cble.le_len == call_num);
- cble.le_back |= call.le_back;
- }
- calls_to_link.popTo(0);
- }
- return lo->elems;
-}
-
-/* attribute layout language parser
-
- attribute_layout:
- ( layout_element )* | ( callable )+
- layout_element:
- ( integral | replication | union | call | reference )
-
- callable:
- '[' body ']'
- body:
- ( layout_element )+
-
- integral:
- ( unsigned_int | signed_int | bc_index | bc_offset | flag )
- unsigned_int:
- uint_type
- signed_int:
- 'S' uint_type
- any_int:
- ( unsigned_int | signed_int )
- bc_index:
- ( 'P' uint_type | 'PO' uint_type )
- bc_offset:
- 'O' any_int
- flag:
- 'F' uint_type
- uint_type:
- ( 'B' | 'H' | 'I' | 'V' )
-
- replication:
- 'N' uint_type '[' body ']'
-
- union:
- 'T' any_int (union_case)* '(' ')' '[' (body)? ']'
- union_case:
- '(' union_case_tag (',' union_case_tag)* ')' '[' (body)? ']'
- union_case_tag:
- ( numeral | numeral '-' numeral )
- call:
- '(' numeral ')'
-
- reference:
- reference_type ( 'N' )? uint_type
- reference_type:
- ( constant_ref | schema_ref | utf8_ref | untyped_ref )
- constant_ref:
- ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' )
- schema_ref:
- ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' )
- utf8_ref:
- 'RU'
- untyped_ref:
- 'RQ'
-
- numeral:
- '(' ('-')? (digit)+ ')'
- digit:
- ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
-
-*/
-
-const char *unpacker::attr_definitions::parseIntLayout(const char *lp, band *&res, byte le_kind,
- bool can_be_signed)
-{
- band *b = U_NEW(band, 1);
- char le = *lp++;
- int spec = UNSIGNED5_spec;
- if (le == 'S' && can_be_signed)
- {
- // Note: This is the last use of sign. There is no 'EF_SIGN'.
- spec = SIGNED5_spec;
- le = *lp++;
- }
- else if (le == 'B')
- {
- spec = BYTE1_spec; // unsigned byte
- }
- b->init(u, bands_made++, spec);
- b->le_kind = le_kind;
- int le_len = 0;
- switch (le)
- {
- case 'B':
- le_len = 1;
- break;
- case 'H':
- le_len = 2;
- break;
- case 'I':
- le_len = 4;
- break;
- case 'V':
- le_len = 0;
- break;
- default:
- unpack_abort("bad layout element");
- }
- b->le_len = le_len;
- band_stack.add(b);
- res = b;
- return lp;
-}
-
-const char *unpacker::attr_definitions::parseNumeral(const char *lp, int &res)
-{
- bool sgn = false;
- if (*lp == '0')
- {
- res = 0;
- return lp + 1;
- } // special case '0'
- if (*lp == '-')
- {
- sgn = true;
- lp++;
- }
- const char *dp = lp;
- int con = 0;
- while (*dp >= '0' && *dp <= '9')
- {
- int con0 = con;
- con *= 10;
- con += (*dp++) - '0';
- if (con <= con0)
- {
- con = -1;
- break;
- } // numeral overflow
- }
- if (lp == dp)
- {
- unpack_abort("missing numeral in layout");
- }
- lp = dp;
- if (con < 0 && !(sgn && con == -con))
- {
- // (Portability note: Misses the error if int is not 32 bits.)
- unpack_abort("numeral overflow");
- }
- if (sgn)
- con = -con;
- res = con;
- return lp;
-}
-
-band **unpacker::attr_definitions::popBody(int bs_base)
-{
- // Return everything that was pushed, as a nullptr-terminated pointer array.
- int bs_limit = band_stack.length();
- if (bs_base == bs_limit)
- {
- return no_bands;
- }
- else
- {
- int nb = bs_limit - bs_base;
- band **res = U_NEW(band *, add_size(nb, 1));
- for (int i = 0; i < nb; i++)
- {
- band *b = (band *)band_stack.get(bs_base + i);
- res[i] = b;
- }
- band_stack.popTo(bs_base);
- return res;
- }
-}
-
-const char *unpacker::attr_definitions::parseLayout(const char *lp, band **&res, int curCble)
-{
- int bs_base = band_stack.length();
- bool top_level = (bs_base == 0);
- band *b;
- enum
- {
- can_be_signed = true
- }; // optional arg to parseIntLayout
-
- for (bool done = false; !done;)
- {
- switch (*lp++)
- {
- case 'B':
- case 'H':
- case 'I':
- case 'V': // unsigned_int
- case 'S': // signed_int
- --lp; // reparse
- case 'F':
- lp = parseIntLayout(lp, b, EK_INT);
- break;
- case 'P':
- {
- int le_bci = EK_BCI;
- if (*lp == 'O')
- {
- ++lp;
- le_bci = EK_BCID;
- }
- assert(*lp != 'S'); // no PSH, etc.
- lp = parseIntLayout(lp, b, EK_INT);
- b->le_bci = le_bci;
- if (le_bci == EK_BCI)
- b->defc = coding::findBySpec(BCI5_spec);
- else
- b->defc = coding::findBySpec(BRANCH5_spec);
- }
- break;
- case 'O':
- lp = parseIntLayout(lp, b, EK_INT, can_be_signed);
- b->le_bci = EK_BCO;
- b->defc = coding::findBySpec(BRANCH5_spec);
- break;
- case 'N': // replication: 'N' uint32_t '[' elem ... ']'
- lp = parseIntLayout(lp, b, EK_REPL);
- assert(*lp == '[');
- ++lp;
- lp = parseLayout(lp, b->le_body, curCble);
- break;
- case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']'
- lp = parseIntLayout(lp, b, EK_UN, can_be_signed);
- {
- int union_base = band_stack.length();
- for (;;)
- { // for each case
- band &k_case = *U_NEW(band, 1);
- band_stack.add(&k_case);
- k_case.le_kind = EK_CASE;
- k_case.bn = bands_made++;
- if (*lp++ != '(')
- {
- unpack_abort("bad union case");
- return "";
- }
- if (*lp++ != ')')
- {
- --lp; // reparse
- // Read some case values. (Use band_stack for temp. storage.)
- int case_base = band_stack.length();
- for (;;)
- {
- int caseval = 0;
- lp = parseNumeral(lp, caseval);
- band_stack.add((void *)(size_t)caseval);
- if (*lp == '-')
- {
- // new in version 160, allow (1-5) for (1,2,3,4,5)
- if (u->majver < JAVA6_PACKAGE_MAJOR_VERSION)
- {
- unpack_abort(
- "bad range in union case label (old archive format)");
- return "";
- }
- int caselimit = caseval;
- lp++;
- lp = parseNumeral(lp, caselimit);
- if (caseval >= caselimit ||
- (uint32_t)(caselimit - caseval) > 0x10000)
- {
- // Note: 0x10000 is arbitrary implementation restriction.
- // We can remove it later if it's important to.
- unpack_abort("bad range in union case label");
- }
- for (;;)
- {
- ++caseval;
- band_stack.add((void *)(size_t)caseval);
- if (caseval == caselimit)
- break;
- }
- }
- if (*lp != ',')
- break;
- lp++;
- }
- if (*lp++ != ')')
- {
- unpack_abort("bad case label");
- }
- // save away the case labels
- int ntags = band_stack.length() - case_base;
- int *tags = U_NEW(int, add_size(ntags, 1));
- k_case.le_casetags = tags;
- *tags++ = ntags;
- for (int i = 0; i < ntags; i++)
- {
- *tags++ = ptrlowbits(band_stack.get(case_base + i));
- }
- band_stack.popTo(case_base);
- }
- // Got le_casetags. Now grab the body.
- assert(*lp == '[');
- ++lp;
- lp = parseLayout(lp, k_case.le_body, curCble);
- if (k_case.le_casetags == nullptr)
- break; // done
- }
- b->le_body = popBody(union_base);
- }
- break;
- case '(': // call: '(' -?NN* ')'
- {
- band &call = *U_NEW(band, 1);
- band_stack.add(&call);
- call.le_kind = EK_CALL;
- call.bn = bands_made++;
- call.le_body = U_NEW(band *, 2); // fill in later
- int call_num = 0;
- lp = parseNumeral(lp, call_num);
- call.le_back = (call_num <= 0);
- call_num += curCble; // numeral is self-relative offset
- call.le_len = call_num; // use le_len as scratch
- calls_to_link.add(&call);
- if (*lp++ != ')')
- {
- unpack_abort("bad call label");
- }
- }
- break;
- case 'K': // reference_type: constant_ref
- case 'R': // reference_type: schema_ref
- {
- int ixTag = CONSTANT_None;
- if (lp[-1] == 'K')
- {
- switch (*lp++)
- {
- case 'I':
- ixTag = CONSTANT_Integer;
- break;
- case 'J':
- ixTag = CONSTANT_Long;
- break;
- case 'F':
- ixTag = CONSTANT_Float;
- break;
- case 'D':
- ixTag = CONSTANT_Double;
- break;
- case 'S':
- ixTag = CONSTANT_String;
- break;
- case 'Q':
- ixTag = CONSTANT_Literal;
- break;
- }
- }
- else
- {
- switch (*lp++)
- {
- case 'C':
- ixTag = CONSTANT_Class;
- break;
- case 'S':
- ixTag = CONSTANT_Signature;
- break;
- case 'D':
- ixTag = CONSTANT_NameandType;
- break;
- case 'F':
- ixTag = CONSTANT_Fieldref;
- break;
- case 'M':
- ixTag = CONSTANT_Methodref;
- break;
- case 'I':
- ixTag = CONSTANT_InterfaceMethodref;
- break;
- case 'U':
- ixTag = CONSTANT_Utf8;
- break; // utf8_ref
- case 'Q':
- ixTag = CONSTANT_All;
- break; // untyped_ref
- }
- }
- if (ixTag == CONSTANT_None)
- {
- unpack_abort("bad reference layout");
- break;
- }
- bool nullOK = false;
- if (*lp == 'N')
- {
- nullOK = true;
- lp++;
- }
- lp = parseIntLayout(lp, b, EK_REF);
- b->defc = coding::findBySpec(UNSIGNED5_spec);
- b->initRef(ixTag, nullOK);
- }
- break;
- case '[':
- {
- // [callable1][callable2]...
- if (!top_level)
- {
- unpack_abort("bad nested callable");
- break;
- }
- curCble += 1;
- band &cble = *U_NEW(band, 1);
- band_stack.add(&cble);
- cble.le_kind = EK_CBLE;
- cble.bn = bands_made++;
- lp = parseLayout(lp, cble.le_body, curCble);
- }
- break;
- case ']':
- // Hit a closing brace. This ends whatever body we were in.
- done = true;
- break;
- case '\0':
- // Hit a nullptr. Also ends the (top-level) body.
- --lp; // back up, so caller can see the nullptr also
- done = true;
- break;
- default:
- unpack_abort("bad layout");
- }
- }
-
- // Return the accumulated bands:
- res = popBody(bs_base);
- return lp;
-}
-
-void unpacker::read_attr_defs()
-{
- int i;
-
- // Tell each AD which attrc it is and where its fixed flags are:
- attr_defs[ATTR_CONTEXT_CLASS].attrc = ATTR_CONTEXT_CLASS;
- attr_defs[ATTR_CONTEXT_CLASS].xxx_flags_hi_bn = e_class_flags_hi;
- attr_defs[ATTR_CONTEXT_FIELD].attrc = ATTR_CONTEXT_FIELD;
- attr_defs[ATTR_CONTEXT_FIELD].xxx_flags_hi_bn = e_field_flags_hi;
- attr_defs[ATTR_CONTEXT_METHOD].attrc = ATTR_CONTEXT_METHOD;
- attr_defs[ATTR_CONTEXT_METHOD].xxx_flags_hi_bn = e_method_flags_hi;
- attr_defs[ATTR_CONTEXT_CODE].attrc = ATTR_CONTEXT_CODE;
- attr_defs[ATTR_CONTEXT_CODE].xxx_flags_hi_bn = e_code_flags_hi;
-
- // Decide whether bands for the optional high flag words are present.
- attr_defs[ATTR_CONTEXT_CLASS]
- .setHaveLongFlags((archive_options & AO_HAVE_CLASS_FLAGS_HI) != 0);
- attr_defs[ATTR_CONTEXT_FIELD]
- .setHaveLongFlags((archive_options & AO_HAVE_FIELD_FLAGS_HI) != 0);
- attr_defs[ATTR_CONTEXT_METHOD]
- .setHaveLongFlags((archive_options & AO_HAVE_METHOD_FLAGS_HI) != 0);
- attr_defs[ATTR_CONTEXT_CODE]
- .setHaveLongFlags((archive_options & AO_HAVE_CODE_FLAGS_HI) != 0);
-
- // Set up built-in attrs.
- // (The simple ones are hard-coded. The metadata layouts are not.)
- const char *md_layout = (
-// parameter annotations:
-#define MDL0 "[NB[(1)]]"
- MDL0
-// annotations:
-#define MDL1 \
- "[NH[(1)]]" \
- "[RSHNH[RUH(1)]]"
- MDL1
- // member_value:
- "[TB"
- "(66,67,73,83,90)[KIH]"
- "(68)[KDH]"
- "(70)[KFH]"
- "(74)[KJH]"
- "(99)[RSH]"
- "(101)[RSHRUH]"
- "(115)[RUH]"
- "(91)[NH[(0)]]"
- "(64)["
- // nested annotation:
- "RSH"
- "NH[RUH(0)]"
- "]"
- "()[]"
- "]");
-
- const char *md_layout_P = md_layout;
- const char *md_layout_A = md_layout + strlen(MDL0);
- const char *md_layout_V = md_layout + strlen(MDL0 MDL1);
- assert(0 == strncmp(&md_layout_A[-3], ")]][", 4));
- assert(0 == strncmp(&md_layout_V[-3], ")]][", 4));
-
- for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
- {
- attr_definitions &ad = attr_defs[i];
- ad.defineLayout(X_ATTR_RuntimeVisibleAnnotations, "RuntimeVisibleAnnotations",
- md_layout_A);
- ad.defineLayout(X_ATTR_RuntimeInvisibleAnnotations, "RuntimeInvisibleAnnotations",
- md_layout_A);
- if (i != ATTR_CONTEXT_METHOD)
- continue;
- ad.defineLayout(METHOD_ATTR_RuntimeVisibleParameterAnnotations,
- "RuntimeVisibleParameterAnnotations", md_layout_P);
- ad.defineLayout(METHOD_ATTR_RuntimeInvisibleParameterAnnotations,
- "RuntimeInvisibleParameterAnnotations", md_layout_P);
- ad.defineLayout(METHOD_ATTR_AnnotationDefault, "AnnotationDefault", md_layout_V);
- }
-
- attr_definition_headers.readData(attr_definition_count);
- attr_definition_name.readData(attr_definition_count);
- attr_definition_layout.readData(attr_definition_count);
-
-// Initialize correct predef bits, to distinguish predefs from new defs.
-#define ORBIT(n, s) | ((uint64_t)1 << n)
- attr_defs[ATTR_CONTEXT_CLASS].predef = (0 X_ATTR_DO(ORBIT) CLASS_ATTR_DO(ORBIT));
- attr_defs[ATTR_CONTEXT_FIELD].predef = (0 X_ATTR_DO(ORBIT) FIELD_ATTR_DO(ORBIT));
- attr_defs[ATTR_CONTEXT_METHOD].predef = (0 X_ATTR_DO(ORBIT) METHOD_ATTR_DO(ORBIT));
- attr_defs[ATTR_CONTEXT_CODE].predef = (0 O_ATTR_DO(ORBIT) CODE_ATTR_DO(ORBIT));
-#undef ORBIT
- // Clear out the redef bits, folding them back into predef.
- for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
- {
- attr_defs[i].predef |= attr_defs[i].redef;
- attr_defs[i].redef = 0;
- }
-
- // Now read the transmitted locally defined attrs.
- // This will set redef bits again.
- for (i = 0; i < attr_definition_count; i++)
- {
- int header = attr_definition_headers.getByte();
- int attrc = ADH_BYTE_CONTEXT(header);
- int idx = ADH_BYTE_INDEX(header);
- entry *name = attr_definition_name.getRef();
- entry *layout = attr_definition_layout.getRef();
- attr_defs[attrc].defineLayout(idx, name, layout->value.b.strval());
- }
-}
-
-#define NO_ENTRY_YET ((entry *)-1)
-
-static bool isDigitString(bytes &x, int beg, int end)
-{
- if (beg == end)
- return false; // nullptr string
- byte *xptr = x.ptr;
- for (int i = beg; i < end; i++)
- {
- char ch = xptr[i];
- if (!(ch >= '0' && ch <= '9'))
- return false;
- }
- return true;
-}
-
-enum
-{ // constants for parsing class names
- SLASH_MIN = '.',
- SLASH_MAX = '/',
- DOLLAR_MIN = 0,
- DOLLAR_MAX = '-'};
-
-static int lastIndexOf(int chmin, int chmax, bytes &x, int pos)
-{
- byte *ptr = x.ptr;
- for (byte *cp = ptr + pos; --cp >= ptr;)
- {
- assert(x.inBounds(cp));
- if (*cp >= chmin && *cp <= chmax)
- return (int)(cp - ptr);
- }
- return -1;
-}
-
-inner_class *constant_pool::getIC(entry *inner)
-{
- if (inner == nullptr)
- return nullptr;
- assert(inner->tag == CONSTANT_Class);
- if (inner->inord == NO_INORD)
- return nullptr;
- inner_class *ic = ic_index[inner->inord];
- assert(ic == nullptr || ic->inner == inner);
- return ic;
-}
-
-inner_class *constant_pool::getFirstChildIC(entry *outer)
-{
- if (outer == nullptr)
- return nullptr;
- assert(outer->tag == CONSTANT_Class);
- if (outer->inord == NO_INORD)
- return nullptr;
- inner_class *ic = ic_child_index[outer->inord];
- assert(ic == nullptr || ic->outer == outer);
- return ic;
-}
-
-inner_class *constant_pool::getNextChildIC(inner_class *child)
-{
- inner_class *ic = child->next_sibling;
- assert(ic == nullptr || ic->outer == child->outer);
- return ic;
-}
-
-void unpacker::read_ics()
-{
- int i;
- int index_size = cp.tag_count[CONSTANT_Class];
- inner_class **ic_index = U_NEW(inner_class *, index_size);
- inner_class **ic_child_index = U_NEW(inner_class *, index_size);
- cp.ic_index = ic_index;
- cp.ic_child_index = ic_child_index;
- ics = U_NEW(inner_class, ic_count);
- ic_this_class.readData(ic_count);
- ic_flags.readData(ic_count);
- // Scan flags to get count of long-form bands.
- int long_forms = 0;
- for (i = 0; i < ic_count; i++)
- {
- int flags = ic_flags.getInt(); // may be long form!
- if ((flags & ACC_IC_LONG_FORM) != 0)
- {
- long_forms += 1;
- ics[i].name = NO_ENTRY_YET;
- }
- flags &= ~ACC_IC_LONG_FORM;
- entry *inner = ic_this_class.getRef();
- uint32_t inord = inner->inord;
- assert(inord < (uint32_t)cp.tag_count[CONSTANT_Class]);
- if (ic_index[inord] != nullptr)
- {
- unpack_abort("identical inner class");
- break;
- }
- ic_index[inord] = &ics[i];
- ics[i].inner = inner;
- ics[i].flags = flags;
- assert(cp.getIC(inner) == &ics[i]);
- }
- // ic_this_class.done();
- // ic_flags.done();
- ic_outer_class.readData(long_forms);
- ic_name.readData(long_forms);
- for (i = 0; i < ic_count; i++)
- {
- if (ics[i].name == NO_ENTRY_YET)
- {
- // Long form.
- ics[i].outer = ic_outer_class.getRefN();
- ics[i].name = ic_name.getRefN();
- }
- else
- {
- // Fill in outer and name based on inner.
- bytes &n = ics[i].inner->value.b;
- bytes pkgOuter;
- bytes number;
- bytes name;
- // Parse n into pkgOuter and name (and number).
- int dollar1, dollar2; // pointers to $ in the pattern
- // parse n = (<pkg>/)*<outer>($<number>)?($<name>)?
- int nlen = (int)n.len;
- int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, nlen) + 1;
- dollar2 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, nlen);
- if (dollar2 < 0)
- {
- unpack_abort();
- }
- assert(dollar2 >= pkglen);
- if (isDigitString(n, dollar2 + 1, nlen))
- {
- // n = (<pkg>/)*<outer>$<number>
- number = n.slice(dollar2 + 1, nlen);
- name.set(nullptr, 0);
- dollar1 = dollar2;
- }
- else if (pkglen < (dollar1 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, dollar2 - 1)) &&
- isDigitString(n, dollar1 + 1, dollar2))
- {
- // n = (<pkg>/)*<outer>$<number>$<name>
- number = n.slice(dollar1 + 1, dollar2);
- name = n.slice(dollar2 + 1, nlen);
- }
- else
- {
- // n = (<pkg>/)*<outer>$<name>
- dollar1 = dollar2;
- number.set(nullptr, 0);
- name = n.slice(dollar2 + 1, nlen);
- }
- if (number.ptr == nullptr)
- pkgOuter = n.slice(0, dollar1);
- else
- pkgOuter.set(nullptr, 0);
-
- if (pkgOuter.ptr != nullptr)
- ics[i].outer = cp.ensureClass(pkgOuter);
-
- if (name.ptr != nullptr)
- ics[i].name = cp.ensureUtf8(name);
- }
-
- // update child/sibling list
- if (ics[i].outer != nullptr)
- {
- uint32_t outord = ics[i].outer->inord;
- if (outord != NO_INORD)
- {
- assert(outord < (uint32_t)cp.tag_count[CONSTANT_Class]);
- ics[i].next_sibling = ic_child_index[outord];
- ic_child_index[outord] = &ics[i];
- }
- }
- }
- // ic_outer_class.done();
- // ic_name.done();
-}
-
-void unpacker::read_classes()
-{
- class_this.readData(class_count);
- class_super.readData(class_count);
- class_interface_count.readData(class_count);
- class_interface.readData(class_interface_count.getIntTotal());
-
-#if 0
- int i;
- // Make a little mark on super-classes.
- for (i = 0; i < class_count; i++) {
- entry* e = class_super.getRefN();
- if (e != nullptr) e->bits |= entry::EB_SUPER;
- }
- class_super.rewind();
-#endif
-
- // Members.
- class_field_count.readData(class_count);
- class_method_count.readData(class_count);
-
- int field_count = class_field_count.getIntTotal();
- int method_count = class_method_count.getIntTotal();
-
- field_descr.readData(field_count);
- read_attrs(ATTR_CONTEXT_FIELD, field_count);
- method_descr.readData(method_count);
- read_attrs(ATTR_CONTEXT_METHOD, method_count);
- read_attrs(ATTR_CONTEXT_CLASS, class_count);
- read_code_headers();
-}
-
-int unpacker::attr_definitions::predefCount(uint32_t idx)
-{
- return isPredefined(idx) ? flag_count[idx] : 0;
-}
-
-void unpacker::read_attrs(int attrc, int obj_count)
-{
- attr_definitions &ad = attr_defs[attrc];
- assert(ad.attrc == attrc);
-
- int i, idx, count;
-
- bool haveLongFlags = ad.haveLongFlags();
-
- band &xxx_flags_hi = ad.xxx_flags_hi();
- if (haveLongFlags)
- xxx_flags_hi.readData(obj_count);
-
- band &xxx_flags_lo = ad.xxx_flags_lo();
- xxx_flags_lo.readData(obj_count);
-
- // pre-scan flags, counting occurrences of each index bit
- uint64_t indexMask = ad.flagIndexMask(); // which flag bits are index bits?
- for (i = 0; i < obj_count; i++)
- {
- uint64_t indexBits = xxx_flags_hi.getLong(xxx_flags_lo, haveLongFlags);
- if ((indexBits & ~indexMask) > (ushort) - 1)
- {
- unpack_abort("undefined attribute flag bit");
- return;
- }
- indexBits &= indexMask; // ignore classfile flag bits
- for (idx = 0; indexBits != 0; idx++, indexBits >>= 1)
- {
- ad.flag_count[idx] += (int)(indexBits & 1);
- }
- }
- // we'll scan these again later for output:
- xxx_flags_lo.rewind();
- xxx_flags_hi.rewind();
-
- band &xxx_attr_count = ad.xxx_attr_count();
- // There is one count element for each 1<<16 bit set in flags:
- xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW));
-
- band &xxx_attr_indexes = ad.xxx_attr_indexes();
- int overflowIndexCount = xxx_attr_count.getIntTotal();
- xxx_attr_indexes.readData(overflowIndexCount);
- // pre-scan attr indexes, counting occurrences of each value
- for (i = 0; i < overflowIndexCount; i++)
- {
- idx = xxx_attr_indexes.getInt();
- if (!ad.isIndex(idx))
- {
- unpack_abort("attribute index out of bounds");
- return;
- }
- ad.getCount(idx) += 1;
- }
- xxx_attr_indexes.rewind(); // we'll scan it again later for output
-
- // We will need a backward call count for each used backward callable.
- int backwardCounts = 0;
- for (idx = 0; idx < ad.layouts.length(); idx++)
- {
- layout_definition *lo = ad.getLayout(idx);
- if (lo != nullptr && ad.getCount(idx) != 0)
- {
- // Build the bands lazily, only when they are used.
- band **bands = ad.buildBands(lo);
- if (lo->hasCallables())
- {
- for (i = 0; bands[i] != nullptr; i++)
- {
- if (bands[i]->le_back)
- {
- assert(bands[i]->le_kind == EK_CBLE);
- backwardCounts += 1;
- }
- }
- }
- }
- }
- ad.xxx_attr_calls().readData(backwardCounts);
-
- // Read built-in bands.
- // Mostly, these are hand-coded equivalents to readBandData().
- switch (attrc)
- {
- case ATTR_CONTEXT_CLASS:
-
- count = ad.predefCount(CLASS_ATTR_SourceFile);
- class_SourceFile_RUN.readData(count);
-
- count = ad.predefCount(CLASS_ATTR_EnclosingMethod);
- class_EnclosingMethod_RC.readData(count);
- class_EnclosingMethod_RDN.readData(count);
-
- count = ad.predefCount(X_ATTR_Signature);
- class_Signature_RS.readData(count);
-
- ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
- ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
-
- count = ad.predefCount(CLASS_ATTR_InnerClasses);
- class_InnerClasses_N.readData(count);
-
- count = class_InnerClasses_N.getIntTotal();
- class_InnerClasses_RC.readData(count);
- class_InnerClasses_F.readData(count);
-
- // Drop remaining columns wherever flags are zero:
- count -= class_InnerClasses_F.getIntCount(0);
- class_InnerClasses_outer_RCN.readData(count);
- class_InnerClasses_name_RUN.readData(count);
-
- count = ad.predefCount(CLASS_ATTR_ClassFile_version);
- class_ClassFile_version_minor_H.readData(count);
- class_ClassFile_version_major_H.readData(count);
- break;
-
- case ATTR_CONTEXT_FIELD:
-
- count = ad.predefCount(FIELD_ATTR_ConstantValue);
- field_ConstantValue_KQ.readData(count);
-
- count = ad.predefCount(X_ATTR_Signature);
- field_Signature_RS.readData(count);
-
- ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
- ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
- break;
-
- case ATTR_CONTEXT_METHOD:
-
- code_count = ad.predefCount(METHOD_ATTR_Code);
- // Code attrs are handled very specially below...
-
- count = ad.predefCount(METHOD_ATTR_Exceptions);
- method_Exceptions_N.readData(count);
- count = method_Exceptions_N.getIntTotal();
- method_Exceptions_RC.readData(count);
-
- count = ad.predefCount(X_ATTR_Signature);
- method_Signature_RS.readData(count);
-
- ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
- ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
- ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations);
- ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations);
- ad.readBandData(METHOD_ATTR_AnnotationDefault);
- break;
-
- case ATTR_CONTEXT_CODE:
- // (keep this code aligned with its brother in unpacker::write_attrs)
- count = ad.predefCount(CODE_ATTR_StackMapTable);
- // disable this feature in old archives!
- if (count != 0 && majver < JAVA6_PACKAGE_MAJOR_VERSION)
- {
- unpack_abort("undefined StackMapTable attribute (old archive format)");
- return;
- }
- code_StackMapTable_N.readData(count);
- count = code_StackMapTable_N.getIntTotal();
- code_StackMapTable_frame_T.readData(count);
- // the rest of it depends in a complicated way on frame tags
- {
- int fat_frame_count = 0;
- int offset_count = 0;
- int type_count = 0;
- for (int k = 0; k < count; k++)
- {
- int tag = code_StackMapTable_frame_T.getByte();
- if (tag <= 127)
- {
- // (64-127) [(2)]
- if (tag >= 64)
- type_count++;
- }
- else if (tag <= 251)
- {
- // (247) [(1)(2)]
- // (248-251) [(1)]
- if (tag >= 247)
- offset_count++;
- if (tag == 247)
- type_count++;
- }
- else if (tag <= 254)
- {
- // (252) [(1)(2)]
- // (253) [(1)(2)(2)]
- // (254) [(1)(2)(2)(2)]
- offset_count++;
- type_count += (tag - 251);
- }
- else
- {
- // (255) [(1)NH[(2)]NH[(2)]]
- fat_frame_count++;
- }
- }
-
- // done pre-scanning frame tags:
- code_StackMapTable_frame_T.rewind();
-
- // deal completely with fat frames:
- offset_count += fat_frame_count;
- code_StackMapTable_local_N.readData(fat_frame_count);
- type_count += code_StackMapTable_local_N.getIntTotal();
- code_StackMapTable_stack_N.readData(fat_frame_count);
- type_count += code_StackMapTable_stack_N.getIntTotal();
- // read the rest:
- code_StackMapTable_offset.readData(offset_count);
- code_StackMapTable_T.readData(type_count);
- // (7) [RCH]
- count = code_StackMapTable_T.getIntCount(7);
- code_StackMapTable_RC.readData(count);
- // (8) [PH]
- count = code_StackMapTable_T.getIntCount(8);
- code_StackMapTable_P.readData(count);
- }
-
- count = ad.predefCount(CODE_ATTR_LineNumberTable);
- code_LineNumberTable_N.readData(count);
- count = code_LineNumberTable_N.getIntTotal();
- code_LineNumberTable_bci_P.readData(count);
- code_LineNumberTable_line.readData(count);
-
- count = ad.predefCount(CODE_ATTR_LocalVariableTable);
- code_LocalVariableTable_N.readData(count);
- count = code_LocalVariableTable_N.getIntTotal();
- code_LocalVariableTable_bci_P.readData(count);
- code_LocalVariableTable_span_O.readData(count);
- code_LocalVariableTable_name_RU.readData(count);
- code_LocalVariableTable_type_RS.readData(count);
- code_LocalVariableTable_slot.readData(count);
-
- count = ad.predefCount(CODE_ATTR_LocalVariableTypeTable);
- code_LocalVariableTypeTable_N.readData(count);
- count = code_LocalVariableTypeTable_N.getIntTotal();
- code_LocalVariableTypeTable_bci_P.readData(count);
- code_LocalVariableTypeTable_span_O.readData(count);
- code_LocalVariableTypeTable_name_RU.readData(count);
- code_LocalVariableTypeTable_type_RS.readData(count);
- code_LocalVariableTypeTable_slot.readData(count);
- break;
- }
-
- // Read compressor-defined bands.
- for (idx = 0; idx < ad.layouts.length(); idx++)
- {
- if (ad.getLayout(idx) == nullptr)
- continue; // none at this fixed index <32
- if (idx < (int)ad.flag_limit && ad.isPredefined(idx))
- continue; // already handled
- if (ad.getCount(idx) == 0)
- continue; // no attributes of this type (then why transmit layouts?)
- ad.readBandData(idx);
- }
-}
-
-void unpacker::attr_definitions::readBandData(int idx)
-{
- int j;
- uint32_t count = getCount(idx);
- if (count == 0)
- return;
- layout_definition *lo = getLayout(idx);
- bool hasCallables = lo->hasCallables();
- band **bands = lo->bands();
- if (!hasCallables)
- {
- // Read through the rest of the bands in a regular way.
- readBandData(bands, count);
- }
- else
- {
- // Deal with the callables.
- // First set up the forward entry count for each callable.
- // This is stored on band::length of the callable.
- bands[0]->expectMoreLength(count);
- for (j = 0; bands[j] != nullptr; j++)
- {
- band &j_cble = *bands[j];
- assert(j_cble.le_kind == EK_CBLE);
- if (j_cble.le_back)
- {
- // Add in the predicted effects of backward calls, too.
- int back_calls = xxx_attr_calls().getInt();
- j_cble.expectMoreLength(back_calls);
- // In a moment, more forward calls may increment j_cble.length.
- }
- }
- // Now consult whichever callables have non-zero entry counts.
- readBandData(bands, (uint32_t) - 1);
- }
-}
-
-// Recursive helper to the previous function:
-void unpacker::attr_definitions::readBandData(band **body, uint32_t count)
-{
- int j, k;
- for (j = 0; body[j] != nullptr; j++)
- {
- band &b = *body[j];
- if (b.defc != nullptr)
- {
- // It has data, so read it.
- b.readData(count);
- }
- switch (b.le_kind)
- {
- case EK_REPL:
- {
- int reps = b.getIntTotal();
- readBandData(b.le_body, reps);
- }
- break;
- case EK_UN:
- {
- int remaining = count;
- for (k = 0; b.le_body[k] != nullptr; k++)
- {
- band &k_case = *b.le_body[k];
- int k_count = 0;
- if (k_case.le_casetags == nullptr)
- {
- k_count = remaining; // last (empty) case
- }
- else
- {
- int *tags = k_case.le_casetags;
- int ntags = *tags++; // 1st element is length (why not?)
- while (ntags-- > 0)
- {
- int tag = *tags++;
- k_count += b.getIntCount(tag);
- }
- }
- readBandData(k_case.le_body, k_count);
- remaining -= k_count;
- }
- assert(remaining == 0);
- }
- break;
- case EK_CALL:
- // Push the count forward, if it is not a backward call.
- if (!b.le_back)
- {
- band &cble = *b.le_body[0];
- assert(cble.le_kind == EK_CBLE);
- cble.expectMoreLength(count);
- }
- break;
- case EK_CBLE:
- assert((int)count == -1); // incoming count is meaningless
- k = b.length;
- assert(k >= 0);
- // This is intended and required for non production mode.
- assert((b.length = -1)); // make it unable to accept more calls now.
- readBandData(b.le_body, k);
- break;
- }
- }
-}
-
-static inline band **findMatchingCase(int matchTag, band **cases)
-{
- for (int k = 0; cases[k] != nullptr; k++)
- {
- band &k_case = *cases[k];
- if (k_case.le_casetags != nullptr)
- {
- // If it has tags, it must match a tag.
- int *tags = k_case.le_casetags;
- int ntags = *tags++; // 1st element is length
- for (; ntags > 0; ntags--)
- {
- int tag = *tags++;
- if (tag == matchTag)
- break;
- }
- if (ntags == 0)
- continue; // does not match
- }
- return k_case.le_body;
- }
- return nullptr;
-}
-
-// write attribute band data:
-void unpacker::putlayout(band **body)
-{
- int i;
- int prevBII = -1;
- int prevBCI = -1;
- if (body == NULL)
- {
- unpack_abort("putlayout: unexpected NULL for body");
- return;
- }
- for (i = 0; body[i] != nullptr; i++)
- {
- band &b = *body[i];
- byte le_kind = b.le_kind;
-
- // Handle scalar part, if any.
- int x = 0;
- entry *e = nullptr;
- if (b.defc != nullptr)
- {
- // It has data, so unparse an element.
- if (b.ixTag != CONSTANT_None)
- {
- assert(le_kind == EK_REF);
- if (b.ixTag == CONSTANT_Literal)
- e = b.getRefUsing(cp.getKQIndex());
- else
- e = b.getRefN();
- switch (b.le_len)
- {
- case 0:
- break;
- case 1:
- putu1ref(e);
- break;
- case 2:
- putref(e);
- break;
- case 4:
- putu2(0);
- putref(e);
- break;
- default:
- assert(false);
- }
- }
- else
- {
- assert(le_kind == EK_INT || le_kind == EK_REPL || le_kind == EK_UN);
- x = b.getInt();
-
- assert(!b.le_bci || prevBCI == (int)to_bci(prevBII));
- switch (b.le_bci)
- {
- case EK_BCI: // PH: transmit R(bci), store bci
- x = to_bci(prevBII = x);
- prevBCI = x;
- break;
- case EK_BCID: // POH: transmit D(R(bci)), store bci
- x = to_bci(prevBII += x);
- prevBCI = x;
- break;
- case EK_BCO: // OH: transmit D(R(bci)), store D(bci)
- x = to_bci(prevBII += x) - prevBCI;
- prevBCI += x;
- break;
- }
- assert(!b.le_bci || prevBCI == (int)to_bci(prevBII));
-
- switch (b.le_len)
- {
- case 0:
- break;
- case 1:
- putu1(x);
- break;
- case 2:
- putu2(x);
- break;
- case 4:
- putu4(x);
- break;
- default:
- assert(false);
- }
- }
- }
-
- // Handle subparts, if any.
- switch (le_kind)
- {
- case EK_REPL:
- // x is the repeat count
- while (x-- > 0)
- {
- putlayout(b.le_body);
- }
- break;
- case EK_UN:
- // x is the tag
- putlayout(findMatchingCase(x, b.le_body));
- break;
- case EK_CALL:
- {
- band &cble = *b.le_body[0];
- assert(cble.le_kind == EK_CBLE);
- // FIXME: hit this one
- // assert(cble.le_len == b.le_len);
- putlayout(cble.le_body);
- }
- break;
-
- case EK_CBLE:
- case EK_CASE:
- assert(false); // should not reach here
- }
- }
-}
-
-void unpacker::read_files()
-{
- file_name.readData(file_count);
- if ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0)
- file_size_hi.readData(file_count);
- file_size_lo.readData(file_count);
- if ((archive_options & AO_HAVE_FILE_MODTIME) != 0)
- file_modtime.readData(file_count);
- int allFiles = file_count + class_count;
- if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0)
- {
- file_options.readData(file_count);
- // FO_IS_CLASS_STUB might be set, causing overlap between classes and files
- for (int i = 0; i < file_count; i++)
- {
- if ((file_options.getInt() & FO_IS_CLASS_STUB) != 0)
- {
- allFiles -= 1; // this one counts as both class and file
- }
- }
- file_options.rewind();
- }
- assert((default_file_options & FO_IS_CLASS_STUB) == 0);
- files_remaining = allFiles;
-}
-
-void unpacker::get_code_header(int &max_stack, int &max_na_locals, int &handler_count,
- int &cflags)
-{
- int sc = code_headers.getByte();
- if (sc == 0)
- {
- max_stack = max_na_locals = handler_count = cflags = -1;
- return;
- }
- // Short code header is the usual case:
- int nh;
- int mod;
- if (sc < 1 + 12 * 12)
- {
- sc -= 1;
- nh = 0;
- mod = 12;
- }
- else if (sc < 1 + 12 * 12 + 8 * 8)
- {
- sc -= 1 + 12 * 12;
- nh = 1;
- mod = 8;
- }
- else
- {
- assert(sc < 1 + 12 * 12 + 8 * 8 + 7 * 7);
- sc -= 1 + 12 * 12 + 8 * 8;
- nh = 2;
- mod = 7;
- }
- max_stack = sc % mod;
- max_na_locals = sc / mod; // caller must add static, siglen
- handler_count = nh;
- if ((archive_options & AO_HAVE_ALL_CODE_FLAGS) != 0)
- cflags = -1;
- else
- cflags = 0; // this one has no attributes
-}
-
-// Cf. PackageReader.readCodeHeaders
-void unpacker::read_code_headers()
-{
- code_headers.readData(code_count);
- int totalHandlerCount = 0;
- int totalFlagsCount = 0;
- for (int i = 0; i < code_count; i++)
- {
- int max_stack, max_locals, handler_count, cflags;
- get_code_header(max_stack, max_locals, handler_count, cflags);
- if (max_stack < 0)
- code_max_stack.expectMoreLength(1);
- if (max_locals < 0)
- code_max_na_locals.expectMoreLength(1);
- if (handler_count < 0)
- code_handler_count.expectMoreLength(1);
- else
- totalHandlerCount += handler_count;
- if (cflags < 0)
- totalFlagsCount += 1;
- }
- code_headers.rewind(); // replay later during writing
-
- code_max_stack.readData();
- code_max_na_locals.readData();
- code_handler_count.readData();
- totalHandlerCount += code_handler_count.getIntTotal();
-
- // Read handler specifications.
- // Cf. PackageReader.readCodeHandlers.
- code_handler_start_P.readData(totalHandlerCount);
- code_handler_end_PO.readData(totalHandlerCount);
- code_handler_catch_PO.readData(totalHandlerCount);
- code_handler_class_RCN.readData(totalHandlerCount);
-
- read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount);
-}
-
-static inline bool is_in_range(uint32_t n, uint32_t min, uint32_t max)
-{
- return n - min <= max - min; // unsigned arithmetic!
-}
-static inline bool is_field_op(int bc)
-{
- return is_in_range(bc, bc_getstatic, bc_putfield);
-}
-static inline bool is_invoke_init_op(int bc)
-{
- return is_in_range(bc, _invokeinit_op, _invokeinit_limit - 1);
-}
-static inline bool is_self_linker_op(int bc)
-{
- return is_in_range(bc, _self_linker_op, _self_linker_limit - 1);
-}
-static bool is_branch_op(int bc)
-{
- return is_in_range(bc, bc_ifeq, bc_jsr) || is_in_range(bc, bc_ifnull, bc_jsr_w);
-}
-static bool is_local_slot_op(int bc)
-{
- return is_in_range(bc, bc_iload, bc_aload) || is_in_range(bc, bc_istore, bc_astore) ||
- bc == bc_iinc || bc == bc_ret;
-}
-band *unpacker::ref_band_for_op(int bc)
-{
- switch (bc)
- {
- case bc_ildc:
- case bc_ildc_w:
- return &bc_intref;
- case bc_fldc:
- case bc_fldc_w:
- return &bc_floatref;
- case bc_lldc2_w:
- return &bc_longref;
- case bc_dldc2_w:
- return &bc_doubleref;
- case bc_aldc:
- case bc_aldc_w:
- return &bc_stringref;
- case bc_cldc:
- case bc_cldc_w:
- return &bc_classref;
-
- case bc_getstatic:
- case bc_putstatic:
- case bc_getfield:
- case bc_putfield:
- return &bc_fieldref;
-
- case bc_invokevirtual:
- case bc_invokespecial:
- case bc_invokestatic:
- return &bc_methodref;
- case bc_invokeinterface:
- return &bc_imethodref;
-
- case bc_new:
- case bc_anewarray:
- case bc_checkcast:
- case bc_instanceof:
- case bc_multianewarray:
- return &bc_classref;
- }
- return nullptr;
-}
-
-band *unpacker::ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar)
-{
- if (!is_self_linker_op(bc))
- return nullptr;
- int idx = (bc - _self_linker_op);
- bool isSuper = (idx >= _self_linker_super_flag);
- if (isSuper)
- idx -= _self_linker_super_flag;
- bool isAload = (idx >= _self_linker_aload_flag);
- if (isAload)
- idx -= _self_linker_aload_flag;
- int origBC = _first_linker_op + idx;
- bool isField = is_field_op(origBC);
- isAloadVar = isAload;
- origBCVar = _first_linker_op + idx;
- if (!isSuper)
- return isField ? &bc_thisfield : &bc_thismethod;
- else
- return isField ? &bc_superfield : &bc_supermethod;
-}
-
-// Cf. PackageReader.readByteCodes
-inline // called exactly once => inline
- void
-unpacker::read_bcs()
-{
- // read from bc_codes and bc_case_count
- fillbytes all_switch_ops;
- all_switch_ops.init();
-
- // Read directly from rp/rplimit.
- // Do this later: bc_codes.readData(...)
- byte *rp0 = rp;
-
- band *bc_which;
- byte *opptr = rp;
- byte *oplimit = rplimit;
-
- bool isAload; // passed by ref and then ignored
- int junkBC; // passed by ref and then ignored
- for (int k = 0; k < code_count; k++)
- {
- // Scan one method:
- for (;;)
- {
- if (opptr + 2 > oplimit)
- {
- rp = opptr;
- ensure_input(2);
- oplimit = rplimit;
- rp = rp0; // back up
- }
- if (opptr == oplimit)
- {
- unpack_abort();
- }
- int bc = *opptr++ & 0xFF;
- bool isWide = false;
- if (bc == bc_wide)
- {
- if (opptr == oplimit)
- {
- unpack_abort();
- }
- bc = *opptr++ & 0xFF;
- isWide = true;
- }
- // Adjust expectations of various band sizes.
- switch (bc)
- {
- case bc_tableswitch:
- case bc_lookupswitch:
- all_switch_ops.addByte(bc);
- break;
- case bc_iinc:
- bc_local.expectMoreLength(1);
- bc_which = isWide ? &bc_short : &bc_byte;
- bc_which->expectMoreLength(1);
- break;
- case bc_sipush:
- bc_short.expectMoreLength(1);
- break;
- case bc_bipush:
- bc_byte.expectMoreLength(1);
- break;
- case bc_newarray:
- bc_byte.expectMoreLength(1);
- break;
- case bc_multianewarray:
- assert(ref_band_for_op(bc) == &bc_classref);
- bc_classref.expectMoreLength(1);
- bc_byte.expectMoreLength(1);
- break;
- case bc_ref_escape:
- bc_escrefsize.expectMoreLength(1);
- bc_escref.expectMoreLength(1);
- break;
- case bc_byte_escape:
- bc_escsize.expectMoreLength(1);
- // bc_escbyte will have to be counted too
- break;
- default:
- if (is_invoke_init_op(bc))
- {
- bc_initref.expectMoreLength(1);
- break;
- }
- bc_which = ref_band_for_self_op(bc, isAload, junkBC);
- if (bc_which != nullptr)
- {
- bc_which->expectMoreLength(1);
- break;
- }
- if (is_branch_op(bc))
- {
- bc_label.expectMoreLength(1);
- break;
- }
- bc_which = ref_band_for_op(bc);
- if (bc_which != nullptr)
- {
- bc_which->expectMoreLength(1);
- assert(bc != bc_multianewarray); // handled elsewhere
- break;
- }
- if (is_local_slot_op(bc))
- {
- bc_local.expectMoreLength(1);
- break;
- }
- break;
- case bc_end_marker:
- // Increment k and test against code_count.
- goto doneScanningMethod;
- }
- }
- doneScanningMethod:
- {
- }
- }
-
- // Go through the formality, so we can use it in a regular fashion later:
- assert(rp == rp0);
- bc_codes.readData((int)(opptr - rp));
-
- int i = 0;
-
- // To size instruction bands correctly, we need info on switches:
- bc_case_count.readData((int)all_switch_ops.size());
- for (i = 0; i < (int)all_switch_ops.size(); i++)
- {
- int caseCount = bc_case_count.getInt();
- int bc = all_switch_ops.getByte(i);
- bc_label.expectMoreLength(1 + caseCount); // default label + cases
- bc_case_value.expectMoreLength(bc == bc_tableswitch ? 1 : caseCount);
- }
- bc_case_count.rewind(); // uses again for output
-
- all_switch_ops.free();
-
- for (i = e_bc_case_value; i <= e_bc_escsize; i++)
- {
- all_bands[i].readData();
- }
-
- // The bc_escbyte band is counted by the immediately previous band.
- bc_escbyte.readData(bc_escsize.getIntTotal());
-}
-
-void unpacker::read_bands()
-{
- read_file_header();
-
- if (cp.nentries == 0)
- {
- // read_file_header failed to read a CP, because it copied a JAR.
- return;
- }
-
- // Do this after the file header has been read:
- check_options();
-
- read_cp();
- read_attr_defs();
- read_ics();
- read_classes();
- read_bcs();
- read_files();
-}
-
-/// CP routines
-
-entry *&constant_pool::hashTabRef(byte tag, bytes &b)
-{
- uint32_t hash = tag + (int)b.len;
- for (int i = 0; i < (int)b.len; i++)
- {
- hash = hash * 31 + (0xFF & b.ptr[i]);
- }
- entry **ht = hashTab;
- int hlen = hashTabLength;
- assert((hlen & (hlen - 1)) == 0); // must be power of 2
- uint32_t hash1 = hash & (hlen - 1); // == hash % hlen
- uint32_t hash2 = 0; // lazily computed (requires mod op.)
-#ifndef NDEBUG
- int probes = 0;
-#endif
- while (ht[hash1] != nullptr)
- {
- entry &e = *ht[hash1];
- if (e.value.b.equals(b) && e.tag == tag)
- break;
- if (hash2 == 0)
- // Note: hash2 must be relatively prime to hlen, hence the "|1".
- hash2 = (((hash % 499) & (hlen - 1)) | 1);
- hash1 += hash2;
- if (hash1 >= (uint32_t)hlen)
- hash1 -= hlen;
- assert(hash1 < (uint32_t)hlen);
- assert(++probes < hlen);
- }
- return ht[hash1];
-}
-
-static void insert_extra(entry *e, ptrlist &extras)
-{
- // This ordering helps implement the Pack200 requirement
- // of a predictable CP order in the class files produced.
- e->inord = NO_INORD; // mark as an "extra"
- extras.add(e);
- // Note: We will sort the list (by string-name) later.
-}
-
-entry *constant_pool::ensureUtf8(bytes &b)
-{
- entry *&ix = hashTabRef(CONSTANT_Utf8, b);
- if (ix != nullptr)
- return ix;
- // Make one.
- if (nentries == maxentries)
- {
- unpack_abort("cp utf8 overflow");
- return &entries[tag_base[CONSTANT_Utf8]]; // return something
- }
- entry &e = entries[nentries++];
- e.tag = CONSTANT_Utf8;
- u->saveTo(e.value.b, b);
- assert(&e >= first_extra_entry);
- insert_extra(&e, tag_extras[CONSTANT_Utf8]);
- return ix = &e;
-}
-
-entry *constant_pool::ensureClass(bytes &b)
-{
- entry *&ix = hashTabRef(CONSTANT_Class, b);
- if (ix != nullptr)
- return ix;
- // Make one.
- if (nentries == maxentries)
- {
- unpack_abort("cp class overflow");
- return &entries[tag_base[CONSTANT_Class]]; // return something
- }
- entry &e = entries[nentries++];
- e.tag = CONSTANT_Class;
- e.nrefs = 1;
- e.refs = U_NEW(entry *, 1);
- ix = &e; // hold my spot in the index
- entry *utf = ensureUtf8(b);
- e.refs[0] = utf;
- e.value.b = utf->value.b;
- assert(&e >= first_extra_entry);
- insert_extra(&e, tag_extras[CONSTANT_Class]);
- return &e;
-}
-
-void constant_pool::expandSignatures()
-{
- int i;
- int nsigs = 0;
- int nreused = 0;
- int first_sig = tag_base[CONSTANT_Signature];
- int sig_limit = tag_count[CONSTANT_Signature] + first_sig;
- fillbytes buf;
- buf.init(1 << 10);
- for (i = first_sig; i < sig_limit; i++)
- {
- entry &e = entries[i];
- assert(e.tag == CONSTANT_Signature);
- int refnum = 0;
- bytes form = e.refs[refnum++]->asUtf8();
- buf.empty();
- for (int j = 0; j < (int)form.len; j++)
- {
- int c = form.ptr[j];
- buf.addByte(c);
- if (c == 'L')
- {
- entry *cls = e.refs[refnum++];
- buf.append(cls->className()->asUtf8());
- }
- }
- assert(refnum == e.nrefs);
- bytes &sig = buf.b;
-
- // try to find a pre-existing Utf8:
- entry *&e2 = hashTabRef(CONSTANT_Utf8, sig);
- if (e2 != nullptr)
- {
- assert(e2->isUtf8(sig));
- e.value.b = e2->value.b;
- e.refs[0] = e2;
- e.nrefs = 1;
- nreused++;
- }
- else
- {
- // there is no other replacement; reuse this CP entry as a Utf8
- u->saveTo(e.value.b, sig);
- e.tag = CONSTANT_Utf8;
- e.nrefs = 0;
- e2 = &e;
- }
- nsigs++;
- }
- buf.free();
-
- // go expunge all references to remaining signatures:
- for (i = 0; i < (int)nentries; i++)
- {
- entry &e = entries[i];
- for (int j = 0; j < e.nrefs; j++)
- {
- entry *&e2 = e.refs[j];
- if (e2 != nullptr && e2->tag == CONSTANT_Signature)
- e2 = e2->refs[0];
- }
- }
-}
-
-void constant_pool::initMemberIndexes()
-{
- // This function does NOT refer to any class schema.
- // It is totally internal to the cpool.
- int i, j;
-
- // Get the pre-existing indexes:
- int nclasses = tag_count[CONSTANT_Class];
- // entry *classes = tag_base[CONSTANT_Class] + entries; // UNUSED
- int nfields = tag_count[CONSTANT_Fieldref];
- entry *fields = tag_base[CONSTANT_Fieldref] + entries;
- int nmethods = tag_count[CONSTANT_Methodref];
- entry *methods = tag_base[CONSTANT_Methodref] + entries;
-
- int *field_counts = T_NEW(int, nclasses);
- int *method_counts = T_NEW(int, nclasses);
- cpindex *all_indexes = U_NEW(cpindex, nclasses * 2);
- entry **field_ix = U_NEW(entry *, add_size(nfields, nclasses));
- entry **method_ix = U_NEW(entry *, add_size(nmethods, nclasses));
-
- for (j = 0; j < nfields; j++)
- {
- entry &f = fields[j];
- i = f.memberClass()->inord;
- assert(i < nclasses);
- field_counts[i]++;
- }
- for (j = 0; j < nmethods; j++)
- {
- entry &m = methods[j];
- i = m.memberClass()->inord;
- assert(i < nclasses);
- method_counts[i]++;
- }
-
- int fbase = 0, mbase = 0;
- for (i = 0; i < nclasses; i++)
- {
- int fc = field_counts[i];
- int mc = method_counts[i];
- all_indexes[i * 2 + 0].init(fc, field_ix + fbase, CONSTANT_Fieldref + SUBINDEX_BIT);
- all_indexes[i * 2 + 1].init(mc, method_ix + mbase, CONSTANT_Methodref + SUBINDEX_BIT);
- // reuse field_counts and member_counts as fill pointers:
- field_counts[i] = fbase;
- method_counts[i] = mbase;
- fbase += fc + 1;
- mbase += mc + 1;
- // (the +1 leaves a space between every subarray)
- }
- assert(fbase == nfields + nclasses);
- assert(mbase == nmethods + nclasses);
-
- for (j = 0; j < nfields; j++)
- {
- entry &f = fields[j];
- i = f.memberClass()->inord;
- field_ix[field_counts[i]++] = &f;
- }
- for (j = 0; j < nmethods; j++)
- {
- entry &m = methods[j];
- i = m.memberClass()->inord;
- method_ix[method_counts[i]++] = &m;
- }
-
- member_indexes = all_indexes;
-
- // Free intermediate buffers.
- u->free_temps();
-}
-
-void entry::requestOutputIndex(constant_pool &cp, int req)
-{
- assert(outputIndex <= NOT_REQUESTED); // must not have assigned indexes yet
- if (tag == CONSTANT_Signature)
- {
- ref(0)->requestOutputIndex(cp, req);
- return;
- }
- assert(req == REQUESTED || req == REQUESTED_LDC);
- if (outputIndex != NOT_REQUESTED)
- {
- if (req == REQUESTED_LDC)
- outputIndex = req; // this kind has precedence
- return;
- }
- outputIndex = req;
- // assert(!cp.outputEntries.contains(this));
- assert(tag != CONSTANT_Signature);
- cp.outputEntries.add(this);
- for (int j = 0; j < nrefs; j++)
- {
- ref(j)->requestOutputIndex(cp);
- }
-}
-
-void constant_pool::resetOutputIndexes()
-{
- int i;
- int noes = outputEntries.length();
- entry **oes = (entry **)outputEntries.base();
- for (i = 0; i < noes; i++)
- {
- entry &e = *oes[i];
- e.outputIndex = NOT_REQUESTED;
- }
- outputIndexLimit = 0;
- outputEntries.empty();
-}
-
-static const byte TAG_ORDER[CONSTANT_Limit] = {0, 1, 0, 2, 3, 4, 5, 7, 6, 10, 11, 12, 9, 8};
-
-extern "C" int outputEntry_cmp(const void *e1p, const void *e2p)
-{
- // Sort entries according to the Pack200 rules for deterministic
- // constant pool ordering.
- //
- // The four sort keys as follows, in order of decreasing importance:
- // 1. ldc first, then non-ldc guys
- // 2. normal cp_All entries by input order (i.e., address order)
- // 3. after that, extra entries by lexical order (as in tag_extras[*])
- entry &e1 = *(entry *)*(void **)e1p;
- entry &e2 = *(entry *)*(void **)e2p;
- int oi1 = e1.outputIndex;
- int oi2 = e2.outputIndex;
- assert(oi1 == REQUESTED || oi1 == REQUESTED_LDC);
- assert(oi2 == REQUESTED || oi2 == REQUESTED_LDC);
- if (oi1 != oi2)
- {
- if (oi1 == REQUESTED_LDC)
- return 0 - 1;
- if (oi2 == REQUESTED_LDC)
- return 1 - 0;
- // Else fall through; neither is an ldc request.
- }
- if (e1.inord != NO_INORD || e2.inord != NO_INORD)
- {
- // One or both is normal. Use input order.
- if (&e1 > &e2)
- return 1 - 0;
- if (&e1 < &e2)
- return 0 - 1;
- return 0; // equal pointers
- }
- // Both are extras. Sort by tag and then by value.
- if (e1.tag != e2.tag)
- {
- return TAG_ORDER[e1.tag] - TAG_ORDER[e2.tag];
- }
- // If the tags are the same, use string comparison.
- return compare_Utf8_chars(e1.value.b, e2.value.b);
-}
-
-void constant_pool::computeOutputIndexes()
-{
- int i;
-
- int noes = outputEntries.length();
- entry **oes = (entry **)outputEntries.base();
-
- // Sort the output constant pool into the order required by Pack200.
- PTRLIST_QSORT(outputEntries, outputEntry_cmp);
-
- // Allocate a new index for each entry that needs one.
- // We do this in two passes, one for LDC entries and one for the rest.
- int nextIndex = 1; // always skip index #0 in output cpool
- for (i = 0; i < noes; i++)
- {
- entry &e = *oes[i];
- assert(e.outputIndex == REQUESTED || e.outputIndex == REQUESTED_LDC);
- e.outputIndex = nextIndex++;
- if (e.isDoubleWord())
- nextIndex++; // do not use the next index
- }
- outputIndexLimit = nextIndex;
-}
-
-// Unpacker Start
-// Deallocate all internal storage and reset to a clean state.
-// Do not disturb any input or output connections, including
-// infileptr, inbytes, read_input_fn, jarout, or errstrm.
-// Do not reset any unpack options.
-void unpacker::reset()
-{
- bytes_read_before_reset += bytes_read;
- bytes_written_before_reset += bytes_written;
- files_written_before_reset += files_written;
- classes_written_before_reset += classes_written;
- segments_read_before_reset += 1;
- if (verbose >= 2)
- {
- fprintf(stderr, "After segment %d, %" PRIu64 " bytes read and %" PRIu64 " bytes written.\n",
- segments_read_before_reset - 1, bytes_read_before_reset,
- bytes_written_before_reset);
- fprintf(stderr,
- "After segment %d, %d files (of which %d are classes) written to output.\n",
- segments_read_before_reset - 1, files_written_before_reset,
- classes_written_before_reset);
- if (archive_next_count != 0)
- {
- fprintf(stderr, "After segment %d, %d segment%s remaining (estimated).\n",
- segments_read_before_reset - 1, archive_next_count,
- archive_next_count == 1 ? "" : "s");
- }
- }
-
- unpacker save_u = (*this); // save bytewise image
- infileptr = nullptr; // make asserts happy
- jarout = nullptr; // do not close the output jar
- gzin = nullptr; // do not close the input gzip stream
- this->free();
- this->init(read_input_fn);
-
- // restore selected interface state:
- infileptr = save_u.infileptr;
- inbytes = save_u.inbytes;
- jarout = save_u.jarout;
- gzin = save_u.gzin;
- verbose = save_u.verbose;
- deflate_hint_or_zero = save_u.deflate_hint_or_zero;
- modification_time_or_zero = save_u.modification_time_or_zero;
- bytes_read_before_reset = save_u.bytes_read_before_reset;
- bytes_written_before_reset = save_u.bytes_written_before_reset;
- files_written_before_reset = save_u.files_written_before_reset;
- classes_written_before_reset = save_u.classes_written_before_reset;
- segments_read_before_reset = save_u.segments_read_before_reset;
- // Note: If we use strip_names, watch out: They get nuked here.
-}
-
-void unpacker::init(read_input_fn_t input_fn)
-{
- int i;
- BYTES_OF(*this).clear();
- this->u = this; // self-reference for U_NEW macro
- read_input_fn = input_fn;
- all_bands = band::makeBands(this);
- // Make a default jar buffer; caller may safely overwrite it.
- jarout = U_NEW(jar, 1);
- jarout->init(this);
- for (i = 0; i < ATTR_CONTEXT_LIMIT; i++)
- attr_defs[i].u = u; // set up outer ptr
-}
-
-// Usage: unpack a byte buffer
-// packptr is a reference to byte buffer containing a
-// packed file and len is the length of the buffer.
-// If nullptr, the callback is used to fill an internal buffer.
-void unpacker::start(void *packptr, size_t len)
-{
- if (packptr != nullptr && len != 0)
- {
- inbytes.set((byte *)packptr, len);
- }
- read_bands();
-}
-
-void unpacker::check_options()
-{
- if (deflate_hint_or_zero != 0)
- {
- bool force_deflate_hint = (deflate_hint_or_zero > 0);
- if (force_deflate_hint)
- default_file_options |= FO_DEFLATE_HINT;
- else
- default_file_options &= ~FO_DEFLATE_HINT;
- // Turn off per-file deflate hint by force.
- suppress_file_options |= FO_DEFLATE_HINT;
- }
- if (modification_time_or_zero != 0)
- {
- default_file_modtime = modification_time_or_zero;
- // Turn off per-file modtime by force.
- archive_options &= ~AO_HAVE_FILE_MODTIME;
- }
-}
-
-// classfile writing
-
-void unpacker::reset_cur_classfile()
-{
- // set defaults
- cur_class_minver = default_class_minver;
- cur_class_majver = default_class_majver;
-
- // reset constant pool state
- cp.resetOutputIndexes();
-
- // reset fixups
- class_fixup_type.empty();
- class_fixup_offset.empty();
- class_fixup_ref.empty();
- requested_ics.empty();
-}
-
-cpindex *constant_pool::getKQIndex()
-{
- char ch = '?';
- if (u->cur_descr != nullptr)
- {
- entry *type = u->cur_descr->descrType();
- ch = type->value.b.ptr[0];
- }
- byte tag = CONSTANT_Integer;
- switch (ch)
- {
- case 'L':
- tag = CONSTANT_String;
- break;
- case 'I':
- tag = CONSTANT_Integer;
- break;
- case 'J':
- tag = CONSTANT_Long;
- break;
- case 'F':
- tag = CONSTANT_Float;
- break;
- case 'D':
- tag = CONSTANT_Double;
- break;
- case 'B':
- case 'S':
- case 'C':
- case 'Z':
- tag = CONSTANT_Integer;
- break;
- default:
- unpack_abort("bad KQ reference");
- break;
- }
- return getIndex(tag);
-}
-
-uint32_t unpacker::to_bci(uint32_t bii)
-{
- uint32_t len = bcimap.length();
- uint32_t *map = (uint32_t *)bcimap.base();
- assert(len > 0); // must be initialized before using to_bci
- if (bii < len)
- return map[bii];
- // Else it's a fractional or out-of-range BCI.
- uint32_t key = bii - len;
- for (int i = len;; i--)
- {
- if (map[i - 1] - (i - 1) <= key)
- break;
- else
- --bii;
- }
- return bii;
-}
-
-void unpacker::put_stackmap_type()
-{
- int tag = code_StackMapTable_T.getByte();
- putu1(tag);
- switch (tag)
- {
- case 7: // (7) [RCH]
- putref(code_StackMapTable_RC.getRef());
- break;
- case 8: // (8) [PH]
- putu2(to_bci(code_StackMapTable_P.getInt()));
- break;
- }
-}
-
-// Functions for writing code.
-
-void unpacker::put_label(int curIP, int size)
-{
- code_fixup_type.addByte(size);
- code_fixup_offset.add((int)put_empty(size));
- code_fixup_source.add(curIP);
-}
-
-inline // called exactly once => inline
- void
-unpacker::write_bc_ops()
-{
- bcimap.empty();
- code_fixup_type.empty();
- code_fixup_offset.empty();
- code_fixup_source.empty();
-
- band *bc_which;
-
- byte *opptr = bc_codes.curRP();
- // No need for oplimit, since the codes are pre-counted.
-
- size_t codeBase = wpoffset();
-
- bool isAload; // copy-out result
- int origBC;
-
- entry *thisClass = cur_class;
- entry *superClass = cur_super;
- entry *newClass = nullptr; // class of last _new opcode
-
- // overwrite any prior index on these bands; it changes w/ current class:
- bc_thisfield.setIndex(cp.getFieldIndex(thisClass));
- bc_thismethod.setIndex(cp.getMethodIndex(thisClass));
- if (superClass != nullptr)
- {
- bc_superfield.setIndex(cp.getFieldIndex(superClass));
- bc_supermethod.setIndex(cp.getMethodIndex(superClass));
- }
-
- for (int curIP = 0;; curIP++)
- {
- int curPC = (int)(wpoffset() - codeBase);
- bcimap.add(curPC);
- ensure_put_space(10); // covers most instrs w/o further bounds check
- int bc = *opptr++ & 0xFF;
-
- putu1_fast(bc);
- // Note: See '--wp' below for pseudo-bytecodes like bc_end_marker.
-
- bool isWide = false;
- if (bc == bc_wide)
- {
- bc = *opptr++ & 0xFF;
- putu1_fast(bc);
- isWide = true;
- }
- switch (bc)
- {
- case bc_end_marker:
- --wp; // not really part of the code
- assert(opptr <= bc_codes.maxRP());
- bc_codes.curRP() = opptr; // advance over this in bc_codes
- goto doneScanningMethod;
- case bc_tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label))
- case bc_lookupswitch: // apc: (df, nc, nc*(case, label))
- {
- int caseCount = bc_case_count.getInt();
- while (((wpoffset() - codeBase) % 4) != 0)
- putu1_fast(0);
- ensure_put_space(30 + caseCount * 8);
- put_label(curIP, 4); // int df = bc_label.getInt();
- if (bc == bc_tableswitch)
- {
- int lo = bc_case_value.getInt();
- int hi = lo + caseCount - 1;
- putu4(lo);
- putu4(hi);
- for (int j = 0; j < caseCount; j++)
- {
- put_label(curIP, 4); // int lVal = bc_label.getInt();
- // int cVal = lo + j;
- }
- }
- else
- {
- putu4(caseCount);
- for (int j = 0; j < caseCount; j++)
- {
- int cVal = bc_case_value.getInt();
- putu4(cVal);
- put_label(curIP, 4); // int lVal = bc_label.getInt();
- }
- }
- assert((int)to_bci(curIP) == curPC);
- continue;
- }
- case bc_iinc:
- {
- int local = bc_local.getInt();
- int delta = (isWide ? bc_short : bc_byte).getInt();
- if (isWide)
- {
- putu2(local);
- putu2(delta);
- }
- else
- {
- putu1_fast(local);
- putu1_fast(delta);
- }
- continue;
- }
- case bc_sipush:
- {
- int val = bc_short.getInt();
- putu2(val);
- continue;
- }
- case bc_bipush:
- case bc_newarray:
- {
- int val = bc_byte.getByte();
- putu1_fast(val);
- continue;
- }
- case bc_ref_escape:
- {
- // Note that insnMap has one entry for this.
- --wp; // not really part of the code
- int size = bc_escrefsize.getInt();
- entry *ref = bc_escref.getRefN();
- switch (size)
- {
- case 1:
- putu1ref(ref);
- break;
- case 2:
- putref(ref);
- break;
- default:
- assert(false);
- }
- continue;
- }
- case bc_byte_escape:
- {
- // Note that insnMap has one entry for all these bytes.
- --wp; // not really part of the code
- int size = bc_escsize.getInt();
- ensure_put_space(size);
- for (int j = 0; j < size; j++)
- putu1_fast(bc_escbyte.getByte());
- continue;
- }
- default:
- if (is_invoke_init_op(bc))
- {
- origBC = bc_invokespecial;
- entry *classRef;
- switch (bc - _invokeinit_op)
- {
- case _invokeinit_self_option:
- classRef = thisClass;
- break;
- case _invokeinit_super_option:
- classRef = superClass;
- break;
- default:
- assert(bc == _invokeinit_op + _invokeinit_new_option);
- case _invokeinit_new_option:
- classRef = newClass;
- break;
- }
- wp[-1] = origBC; // overwrite with origBC
- int coding = bc_initref.getInt();
- // Find the nth overloading of <init> in classRef.
- entry *ref = nullptr;
- cpindex *ix = (classRef == nullptr) ? nullptr : cp.getMethodIndex(classRef);
- for (int j = 0, which_init = 0;; j++)
- {
- ref = (ix == nullptr) ? nullptr : ix->get(j);
- if (ref == nullptr)
- break; // oops, bad input
- assert(ref->tag == CONSTANT_Methodref);
- if (ref->memberDescr()->descrName() == cp.sym[constant_pool::s_lt_init_gt])
- {
- if (which_init++ == coding)
- break;
- }
- }
- putref(ref);
- continue;
- }
- bc_which = ref_band_for_self_op(bc, isAload, origBC);
- if (bc_which != nullptr)
- {
- if (!isAload)
- {
- wp[-1] = origBC; // overwrite with origBC
- }
- else
- {
- wp[-1] = bc_aload_0; // overwrite with _aload_0
- // Note: insnMap keeps the _aload_0 separate.
- bcimap.add(++curPC);
- ++curIP;
- putu1_fast(origBC);
- }
- entry *ref = bc_which->getRef();
- putref(ref);
- continue;
- }
- if (is_branch_op(bc))
- {
- // int lVal = bc_label.getInt();
- if (bc < bc_goto_w)
- {
- put_label(curIP, 2); // putu2(lVal & 0xFFFF);
- }
- else
- {
- assert(bc <= bc_jsr_w);
- put_label(curIP, 4); // putu4(lVal);
- }
- assert((int)to_bci(curIP) == curPC);
- continue;
- }
- bc_which = ref_band_for_op(bc);
- if (bc_which != nullptr)
- {
- entry *ref = bc_which->getRefCommon(bc_which->ix, bc_which->nullOK);
- if (ref == nullptr && bc_which == &bc_classref)
- {
- // Shorthand for class self-references.
- ref = thisClass;
- }
- origBC = bc;
- switch (bc)
- {
- case bc_ildc:
- case bc_cldc:
- case bc_fldc:
- case bc_aldc:
- origBC = bc_ldc;
- break;
- case bc_ildc_w:
- case bc_cldc_w:
- case bc_fldc_w:
- case bc_aldc_w:
- origBC = bc_ldc_w;
- break;
- case bc_lldc2_w:
- case bc_dldc2_w:
- origBC = bc_ldc2_w;
- break;
- case bc_new:
- newClass = ref;
- break;
- }
- wp[-1] = origBC; // overwrite with origBC
- if (origBC == bc_ldc)
- {
- putu1ref(ref);
- }
- else
- {
- putref(ref);
- }
- if (origBC == bc_multianewarray)
- {
- // Copy the trailing byte also.
- int val = bc_byte.getByte();
- putu1_fast(val);
- }
- else if (origBC == bc_invokeinterface)
- {
- int argSize = ref->memberDescr()->descrType()->typeSize();
- putu1_fast(1 + argSize);
- putu1_fast(0);
- }
- continue;
- }
- if (is_local_slot_op(bc))
- {
- int local = bc_local.getInt();
- if (isWide)
- {
- putu2(local);
- if (bc == bc_iinc)
- {
- int iVal = bc_short.getInt();
- putu2(iVal);
- }
- }
- else
- {
- putu1_fast(local);
- if (bc == bc_iinc)
- {
- int iVal = bc_byte.getByte();
- putu1_fast(iVal);
- }
- }
- continue;
- }
- // Random bytecode. Just copy it.
- assert(bc < bc_bytecode_limit);
- }
- }
-doneScanningMethod:
-{
-}
- // bcimap.add(curPC); // PC limit is already also in map, from bc_end_marker
-
- // Armed with a bcimap, we can now fix up all the labels.
- for (int i = 0; i < (int)code_fixup_type.size(); i++)
- {
- int type = code_fixup_type.getByte(i);
- byte *bp = wp_at(code_fixup_offset.get(i));
- int curIP = code_fixup_source.get(i);
- int destIP = curIP + bc_label.getInt();
- int span = to_bci(destIP) - to_bci(curIP);
- switch (type)
- {
- case 2:
- putu2_at(bp, (ushort)span);
- break;
- case 4:
- putu4_at(bp, span);
- break;
- default:
- assert(false);
- }
- }
-}
-
-inline // called exactly once => inline
- void
-unpacker::write_code()
-{
- int j;
-
- int max_stack, max_locals, handler_count, cflags;
- get_code_header(max_stack, max_locals, handler_count, cflags);
-
- if (max_stack < 0)
- max_stack = code_max_stack.getInt();
- if (max_locals < 0)
- max_locals = code_max_na_locals.getInt();
- if (handler_count < 0)
- handler_count = code_handler_count.getInt();
-
- int siglen = cur_descr->descrType()->typeSize();
- if ((cur_descr_flags & ACC_STATIC) == 0)
- siglen++;
- max_locals += siglen;
-
- putu2(max_stack);
- putu2(max_locals);
- size_t bcbase = put_empty(4);
-
- // Write the bytecodes themselves.
- write_bc_ops();
-
- byte *bcbasewp = wp_at(bcbase);
- putu4_at(bcbasewp, (int)(wp - (bcbasewp + 4))); // size of code attr
-
- putu2(handler_count);
- for (j = 0; j < handler_count; j++)
- {
- int bii = code_handler_start_P.getInt();
- putu2(to_bci(bii));
- bii += code_handler_end_PO.getInt();
- putu2(to_bci(bii));
- bii += code_handler_catch_PO.getInt();
- putu2(to_bci(bii));
- putref(code_handler_class_RCN.getRefN());
- }
-
- uint64_t indexBits = cflags;
- if (cflags < 0)
- {
- bool haveLongFlags = attr_defs[ATTR_CONTEXT_CODE].haveLongFlags();
- indexBits = code_flags_hi.getLong(code_flags_lo, haveLongFlags);
- }
- write_attrs(ATTR_CONTEXT_CODE, indexBits);
-}
-
-int unpacker::write_attrs(int attrc, uint64_t indexBits)
-{
- if (indexBits == 0)
- {
- // Quick short-circuit.
- putu2(0);
- return 0;
- }
-
- attr_definitions &ad = attr_defs[attrc];
-
- int i, j, j2, idx, count;
-
- int oiCount = 0;
- if (ad.isPredefined(X_ATTR_OVERFLOW) && (indexBits & ((uint64_t)1 << X_ATTR_OVERFLOW)) != 0)
- {
- indexBits -= ((uint64_t)1 << X_ATTR_OVERFLOW);
- oiCount = ad.xxx_attr_count().getInt();
- }
-
- int bitIndexes[X_ATTR_LIMIT_FLAGS_HI];
- int biCount = 0;
-
- // Fill bitIndexes with index bits, in order.
- for (idx = 0; indexBits != 0; idx++, indexBits >>= 1)
- {
- if ((indexBits & 1) != 0)
- bitIndexes[biCount++] = idx;
- }
- assert(biCount <= (int)lengthof(bitIndexes));
-
- // Write a provisional attribute count, perhaps to be corrected later.
- int naOffset = (int)wpoffset();
- int na0 = biCount + oiCount;
- putu2(na0);
-
- int na = 0;
- for (i = 0; i < na0; i++)
- {
- if (i < biCount)
- idx = bitIndexes[i];
- else
- idx = ad.xxx_attr_indexes().getInt();
- assert(ad.isIndex(idx));
- entry *aname = nullptr;
- entry *ref; // scratch
- size_t abase = put_empty(2 + 4);
- if (idx < (int)ad.flag_limit && ad.isPredefined(idx))
- {
- // Switch on the attrc and idx simultaneously.
- switch (ADH_BYTE(attrc, idx))
- {
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_OVERFLOW) :
- case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_OVERFLOW) :
- case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_OVERFLOW) :
- case ADH_BYTE(ATTR_CONTEXT_CODE, X_ATTR_OVERFLOW) :
- // no attribute at all, so back up on this one
- wp = wp_at(abase);
- continue;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_ClassFile_version) :
- cur_class_minver = class_ClassFile_version_minor_H.getInt();
- cur_class_majver = class_ClassFile_version_major_H.getInt();
- // back up; not a real attribute
- wp = wp_at(abase);
- continue;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_InnerClasses) :
- // note the existence of this attr, but save for later
- if (cur_class_has_local_ics)
- unpack_abort("too many InnerClasses attrs");
- cur_class_has_local_ics = true;
- wp = wp_at(abase);
- continue;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_SourceFile) :
- aname = cp.sym[constant_pool::s_SourceFile];
- ref = class_SourceFile_RUN.getRefN();
- if (ref == nullptr)
- {
- bytes &n = cur_class->ref(0)->value.b;
- // parse n = (<pkg>/)*<outer>?($<id>)*
- int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, (int)n.len) + 1;
- bytes prefix = n.slice(pkglen, n.len);
- for (;;)
- {
- // Work backwards, finding all '$', '#', etc.
- int dollar =
- lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, prefix, (int)prefix.len);
- if (dollar < 0)
- break;
- prefix = prefix.slice(0, dollar);
- }
- const char *suffix = ".java";
- int len = (int)(prefix.len + strlen(suffix));
- bytes name;
- name.set(T_NEW(byte, add_size(len, 1)), len);
- name.strcat(prefix).strcat(suffix);
- ref = cp.ensureUtf8(name);
- }
- putref(ref);
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod) :
- aname = cp.sym[constant_pool::s_EnclosingMethod];
- putref(class_EnclosingMethod_RC.getRefN());
- putref(class_EnclosingMethod_RDN.getRefN());
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_FIELD, FIELD_ATTR_ConstantValue) :
- aname = cp.sym[constant_pool::s_ConstantValue];
- putref(field_ConstantValue_KQ.getRefUsing(cp.getKQIndex()));
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Code) :
- aname = cp.sym[constant_pool::s_Code];
- write_code();
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Exceptions) :
- aname = cp.sym[constant_pool::s_Exceptions];
- putu2(count = method_Exceptions_N.getInt());
- for (j = 0; j < count; j++)
- {
- putref(method_Exceptions_RC.getRefN());
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_StackMapTable) :
- aname = cp.sym[constant_pool::s_StackMapTable];
- // (keep this code aligned with its brother in unpacker::read_attrs)
- putu2(count = code_StackMapTable_N.getInt());
- for (j = 0; j < count; j++)
- {
- int tag = code_StackMapTable_frame_T.getByte();
- putu1(tag);
- if (tag <= 127)
- {
- // (64-127) [(2)]
- if (tag >= 64)
- put_stackmap_type();
- }
- else if (tag <= 251)
- {
- // (247) [(1)(2)]
- // (248-251) [(1)]
- if (tag >= 247)
- putu2(code_StackMapTable_offset.getInt());
- if (tag == 247)
- put_stackmap_type();
- }
- else if (tag <= 254)
- {
- // (252) [(1)(2)]
- // (253) [(1)(2)(2)]
- // (254) [(1)(2)(2)(2)]
- putu2(code_StackMapTable_offset.getInt());
- for (int k = (tag - 251); k > 0; k--)
- {
- put_stackmap_type();
- }
- }
- else
- {
- // (255) [(1)NH[(2)]NH[(2)]]
- putu2(code_StackMapTable_offset.getInt());
- putu2(j2 = code_StackMapTable_local_N.getInt());
- while (j2-- > 0)
- put_stackmap_type();
- putu2(j2 = code_StackMapTable_stack_N.getInt());
- while (j2-- > 0)
- put_stackmap_type();
- }
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LineNumberTable) :
- aname = cp.sym[constant_pool::s_LineNumberTable];
- putu2(count = code_LineNumberTable_N.getInt());
- for (j = 0; j < count; j++)
- {
- putu2(to_bci(code_LineNumberTable_bci_P.getInt()));
- putu2(code_LineNumberTable_line.getInt());
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTable) :
- aname = cp.sym[constant_pool::s_LocalVariableTable];
- putu2(count = code_LocalVariableTable_N.getInt());
- for (j = 0; j < count; j++)
- {
- int bii = code_LocalVariableTable_bci_P.getInt();
- int bci = to_bci(bii);
- putu2(bci);
- bii += code_LocalVariableTable_span_O.getInt();
- putu2(to_bci(bii) - bci);
- putref(code_LocalVariableTable_name_RU.getRefN());
- putref(code_LocalVariableTable_type_RS.getRefN());
- putu2(code_LocalVariableTable_slot.getInt());
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTypeTable) :
- aname = cp.sym[constant_pool::s_LocalVariableTypeTable];
- putu2(count = code_LocalVariableTypeTable_N.getInt());
- for (j = 0; j < count; j++)
- {
- int bii = code_LocalVariableTypeTable_bci_P.getInt();
- int bci = to_bci(bii);
- putu2(bci);
- bii += code_LocalVariableTypeTable_span_O.getInt();
- putu2(to_bci(bii) - bci);
- putref(code_LocalVariableTypeTable_name_RU.getRefN());
- putref(code_LocalVariableTypeTable_type_RS.getRefN());
- putu2(code_LocalVariableTypeTable_slot.getInt());
- }
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Signature) :
- aname = cp.sym[constant_pool::s_Signature];
- putref(class_Signature_RS.getRefN());
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Signature) :
- aname = cp.sym[constant_pool::s_Signature];
- putref(field_Signature_RS.getRefN());
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Signature) :
- aname = cp.sym[constant_pool::s_Signature];
- putref(method_Signature_RS.getRefN());
- break;
-
- case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Deprecated) :
- case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Deprecated) :
- case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Deprecated) :
- aname = cp.sym[constant_pool::s_Deprecated];
- // no data
- break;
- }
- }
-
- if (aname == nullptr)
- {
- // Unparse a compressor-defined attribute.
- layout_definition *lo = ad.getLayout(idx);
- if (lo == nullptr)
- {
- unpack_abort("bad layout index");
- break;
- }
- assert((int)lo->idx == idx);
- aname = lo->nameEntry;
- if (aname == nullptr)
- {
- bytes nameb;
- nameb.set(lo->name);
- aname = cp.ensureUtf8(nameb);
- // Cache the name entry for next time.
- lo->nameEntry = aname;
- }
- // Execute all the layout elements.
- band **bands = lo->bands();
- if (lo->hasCallables())
- {
- band &cble = *bands[0];
- assert(cble.le_kind == EK_CBLE);
- bands = cble.le_body;
- }
- putlayout(bands);
- }
-
- if (aname == nullptr)
- unpack_abort("bad attribute index");
-
- byte *wp1 = wp;
- wp = wp_at(abase);
-
- // DTRT if this attr is on the strip-list.
- // (Note that we emptied the data out of the band first.)
- if (ad.strip_names.contains(aname))
- {
- continue;
- }
-
- // patch the name and length
- putref(aname);
- putu4((int)(wp1 - (wp + 4))); // put the attr size
- wp = wp1;
- na++; // count the attrs actually written
- }
-
- if (na != na0)
- // Refresh changed count.
- putu2_at(wp_at(naOffset), na);
- return na;
-}
-
-void unpacker::write_members(int num, int attrc)
-{
- attr_definitions &ad = attr_defs[attrc];
- band &member_flags_hi = ad.xxx_flags_hi();
- band &member_flags_lo = ad.xxx_flags_lo();
- band &member_descr = (&member_flags_hi)[e_field_descr - e_field_flags_hi];
- bool haveLongFlags = ad.haveLongFlags();
-
- putu2(num);
- uint64_t indexMask = attr_defs[attrc].flagIndexMask();
- for (int i = 0; i < num; i++)
- {
- uint64_t mflags = member_flags_hi.getLong(member_flags_lo, haveLongFlags);
- entry *mdescr = member_descr.getRef();
- cur_descr = mdescr;
- putu2(cur_descr_flags = (ushort)(mflags & ~indexMask));
- putref(mdescr->descrName());
- putref(mdescr->descrType());
- write_attrs(attrc, (mflags & indexMask));
- }
- cur_descr = nullptr;
-}
-
-extern "C" int raw_address_cmp(const void *p1p, const void *p2p)
-{
- void *p1 = *(void **)p1p;
- void *p2 = *(void **)p2p;
- return (p1 > p2) ? 1 : (p1 < p2) ? -1 : 0;
-}
-
-void unpacker::write_classfile_tail()
-{
- cur_classfile_tail.empty();
- set_output(&cur_classfile_tail);
-
- int i, num;
-
- attr_definitions &ad = attr_defs[ATTR_CONTEXT_CLASS];
-
- bool haveLongFlags = ad.haveLongFlags();
- uint64_t kflags = class_flags_hi.getLong(class_flags_lo, haveLongFlags);
- uint64_t indexMask = ad.flagIndexMask();
-
- cur_class = class_this.getRef();
- cur_super = class_super.getRef();
-
- if (cur_super == cur_class)
- cur_super = nullptr;
- // special representation for java/lang/Object
-
- putu2((ushort)(kflags & ~indexMask));
- putref(cur_class);
- putref(cur_super);
-
- putu2(num = class_interface_count.getInt());
- for (i = 0; i < num; i++)
- {
- putref(class_interface.getRef());
- }
-
- write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD);
- write_members(class_method_count.getInt(), ATTR_CONTEXT_METHOD);
-
- cur_class_has_local_ics = false; // may be set true by write_attrs
-
- int naOffset = (int)wpoffset();
- int na = write_attrs(ATTR_CONTEXT_CLASS, (kflags & indexMask));
-
-// at the very last, choose which inner classes (if any) pertain to k:
-#ifdef ASSERT
- for (i = 0; i < ic_count; i++)
- {
- assert(!ics[i].requested);
- }
-#endif
- // First, consult the global table and the local constant pool,
- // and decide on the globally implied inner classes.
- // (Note that we read the cpool's outputIndex fields, but we
- // do not yet write them, since the local IC attribute might
- // reverse a global decision to declare an IC.)
- assert(requested_ics.length() == 0); // must start out empty
- // Always include all members of the current class.
- for (inner_class *child = cp.getFirstChildIC(cur_class); child != nullptr;
- child = cp.getNextChildIC(child))
- {
- child->requested = true;
- requested_ics.add(child);
- }
- // And, for each inner class mentioned in the constant pool,
- // include it and all its outers.
- int noes = cp.outputEntries.length();
- entry **oes = (entry **)cp.outputEntries.base();
- for (i = 0; i < noes; i++)
- {
- entry &e = *oes[i];
- if (e.tag != CONSTANT_Class)
- continue; // wrong sort
- for (inner_class *ic = cp.getIC(&e); ic != nullptr; ic = cp.getIC(ic->outer))
- {
- if (ic->requested)
- break; // already processed
- ic->requested = true;
- requested_ics.add(ic);
- }
- }
- int local_ics = requested_ics.length();
- // Second, consult a local attribute (if any) and adjust the global set.
- inner_class *extra_ics = nullptr;
- int num_extra_ics = 0;
- if (cur_class_has_local_ics)
- {
- // adjust the set of ICs by symmetric set difference w/ the locals
- num_extra_ics = class_InnerClasses_N.getInt();
- if (num_extra_ics == 0)
- {
- // Explicit zero count has an irregular meaning: It deletes the attr.
- local_ics = 0; // (short-circuit all tests of requested bits)
- }
- else
- {
- extra_ics = T_NEW(inner_class, num_extra_ics);
- // Note: extra_ics will be freed up by next call to get_next_file().
- }
- }
- for (i = 0; i < num_extra_ics; i++)
- {
- inner_class &extra_ic = extra_ics[i];
- extra_ic.inner = class_InnerClasses_RC.getRef();
- // Find the corresponding equivalent global IC:
- inner_class *global_ic = cp.getIC(extra_ic.inner);
- int flags = class_InnerClasses_F.getInt();
- if (flags == 0)
- {
- // The extra IC is simply a copy of a global IC.
- if (global_ic == nullptr)
- {
- unpack_abort("bad reference to inner class");
- break;
- }
- extra_ic = (*global_ic); // fill in rest of fields
- }
- else
- {
- flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero
- extra_ic.flags = flags;
- extra_ic.outer = class_InnerClasses_outer_RCN.getRefN();
- extra_ic.name = class_InnerClasses_name_RUN.getRefN();
- // Detect if this is an exact copy of the global tuple.
- if (global_ic != nullptr)
- {
- if (global_ic->flags != extra_ic.flags || global_ic->outer != extra_ic.outer ||
- global_ic->name != extra_ic.name)
- {
- global_ic = nullptr; // not really the same, so break the link
- }
- }
- }
- if (global_ic != nullptr && global_ic->requested)
- {
- // This local repetition reverses the globally implied request.
- global_ic->requested = false;
- extra_ic.requested = false;
- local_ics -= 1;
- }
- else
- {
- // The global either does not exist, or is not yet requested.
- extra_ic.requested = true;
- local_ics += 1;
- }
- }
- // Finally, if there are any that survived, put them into an attribute.
- // (Note that a zero-count attribute is always deleted.)
- // The putref calls below will tell the constant pool to add any
- // necessary local CP references to support the InnerClasses attribute.
- // This step must be the last round of additions to the local CP.
- if (local_ics > 0)
- {
- // append the new attribute:
- putref(cp.sym[constant_pool::s_InnerClasses]);
- putu4(2 + 2 * 4 * local_ics);
- putu2(local_ics);
- PTRLIST_QSORT(requested_ics, raw_address_cmp);
- int num_global_ics = requested_ics.length();
- for (i = -num_global_ics; i < num_extra_ics; i++)
- {
- inner_class *ic;
- if (i < 0)
- ic = (inner_class *)requested_ics.get(num_global_ics + i);
- else
- ic = &extra_ics[i];
- if (ic->requested)
- {
- putref(ic->inner);
- putref(ic->outer);
- putref(ic->name);
- putu2(ic->flags);
- }
- }
- putu2_at(wp_at(naOffset), ++na); // increment class attr count
- }
-
- // Tidy up global 'requested' bits:
- for (i = requested_ics.length(); --i >= 0;)
- {
- inner_class *ic = (inner_class *)requested_ics.get(i);
- ic->requested = false;
- }
- requested_ics.empty();
-
- close_output();
-
- // rewrite CP references in the tail
- cp.computeOutputIndexes();
- int nextref = 0;
- for (i = 0; i < (int)class_fixup_type.size(); i++)
- {
- int type = class_fixup_type.getByte(i);
- byte *fixp = wp_at(class_fixup_offset.get(i));
- entry *e = (entry *)class_fixup_ref.get(nextref++);
- int idx = e->getOutputIndex();
- switch (type)
- {
- case 1:
- putu1_at(fixp, idx);
- break;
- case 2:
- putu2_at(fixp, idx);
- break;
- default:
- assert(false); // should not reach here
- }
- }
-}
-
-void unpacker::write_classfile_head()
-{
- cur_classfile_head.empty();
- set_output(&cur_classfile_head);
-
- putu4(JAVA_MAGIC);
- putu2(cur_class_minver);
- putu2(cur_class_majver);
- putu2(cp.outputIndexLimit);
-
-#ifndef NDEBUG
- int checkIndex = 1;
-#endif
- int noes = cp.outputEntries.length();
- entry **oes = (entry **)cp.outputEntries.base();
- for (int i = 0; i < noes; i++)
- {
- entry &e = *oes[i];
- assert(e.getOutputIndex() == checkIndex++);
- byte tag = e.tag;
- assert(tag != CONSTANT_Signature);
- putu1(tag);
- switch (tag)
- {
- case CONSTANT_Utf8:
- putu2((int)e.value.b.len);
- put_bytes(e.value.b);
- break;
- case CONSTANT_Integer:
- case CONSTANT_Float:
- putu4(e.value.i);
- break;
- case CONSTANT_Long:
- case CONSTANT_Double:
- putu8(e.value.l);
- assert(checkIndex++);
- break;
- case CONSTANT_Class:
- case CONSTANT_String:
- // just write the ref
- putu2(e.refs[0]->getOutputIndex());
- break;
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- case CONSTANT_NameandType:
- putu2(e.refs[0]->getOutputIndex());
- putu2(e.refs[1]->getOutputIndex());
- break;
- default:
- unpack_abort(ERROR_INTERNAL);
- }
- }
- close_output();
-}
-
-unpacker::file *unpacker::get_next_file()
-{
- free_temps();
- if (files_remaining == 0)
- {
- // Leave a clue that we're exhausted.
- cur_file.name = nullptr;
- cur_file.size = 0;
- if (archive_size != 0)
- {
- uint64_t predicted_size = unsized_bytes_read + archive_size;
- if (predicted_size != bytes_read)
- unpack_abort("archive header had incorrect size");
- }
- return nullptr;
- }
- files_remaining -= 1;
- assert(files_written < file_count || classes_written < class_count);
- cur_file.name = "";
- cur_file.size = 0;
- cur_file.modtime = default_file_modtime;
- cur_file.options = default_file_options;
- cur_file.data[0].set(nullptr, 0);
- cur_file.data[1].set(nullptr, 0);
- if (files_written < file_count)
- {
- entry *e = file_name.getRef();
- cur_file.name = e->utf8String();
- bool haveLongSize = ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0);
- cur_file.size = file_size_hi.getLong(file_size_lo, haveLongSize);
- if ((archive_options & AO_HAVE_FILE_MODTIME) != 0)
- cur_file.modtime += file_modtime.getInt(); // relative to archive modtime
- if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0)
- cur_file.options |= file_options.getInt() & ~suppress_file_options;
- }
- else if (classes_written < class_count)
- {
- // there is a class for a missing file record
- cur_file.options |= FO_IS_CLASS_STUB;
- }
- if ((cur_file.options & FO_IS_CLASS_STUB) != 0)
- {
- assert(classes_written < class_count);
- classes_written += 1;
- if (cur_file.size != 0)
- {
- unpack_abort("class file size transmitted");
- }
- reset_cur_classfile();
-
- // write the meat of the classfile:
- write_classfile_tail();
- cur_file.data[1] = cur_classfile_tail.b;
-
- // write the CP of the classfile, second:
- write_classfile_head();
- cur_file.data[0] = cur_classfile_head.b;
-
- cur_file.size += cur_file.data[0].len;
- cur_file.size += cur_file.data[1].len;
- if (cur_file.name[0] == '\0')
- {
- bytes &prefix = cur_class->ref(0)->value.b;
- const char *suffix = ".class";
- int len = (int)(prefix.len + strlen(suffix));
- bytes name;
- name.set(T_NEW(byte, add_size(len, 1)), len);
- cur_file.name = name.strcat(prefix).strcat(suffix).strval();
- }
- }
- else
- {
- // If there is buffered file data, produce a pointer to it.
- if (cur_file.size != (size_t)cur_file.size)
- {
- // Silly size specified.
- unpack_abort("resource file too large");
- }
- size_t rpleft = input_remaining();
- if (rpleft > 0)
- {
- if (rpleft > cur_file.size)
- rpleft = (size_t)cur_file.size;
- cur_file.data[0].set(rp, rpleft);
- rp += rpleft;
- }
- if (rpleft < cur_file.size)
- {
- // Caller must read the rest.
- size_t fleft = (size_t)cur_file.size - rpleft;
- bytes_read += fleft; // Credit it to the overall archive size.
- }
- }
- bytes_written += cur_file.size;
- files_written += 1;
- return &cur_file;
-}
-
-// Write a file to jarout.
-void unpacker::write_file_to_jar(unpacker::file *f)
-{
- size_t htsize = f->data[0].len + f->data[1].len;
- uint64_t fsize = f->size;
- if (htsize == fsize)
- {
- jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, f->data[0], f->data[1]);
- }
- else
- {
- assert(input_remaining() == 0);
- bytes part1, part2;
- part1.len = f->data[0].len;
- part1.set(T_NEW(byte, part1.len), part1.len);
- part1.copyFrom(f->data[0]);
- assert(f->data[1].len == 0);
- part2.set(nullptr, 0);
- size_t fleft = (size_t)fsize - part1.len;
- assert(bytes_read > fleft); // part2 already credited by get_next_file
- bytes_read -= fleft;
- if (fleft > 0)
- {
- // Must read some more.
- if (live_input)
- {
- // Stop using the input buffer. Make a new one:
- if (free_input)
- input.free();
- input.init(fleft > (1 << 12) ? fleft : (1 << 12));
- free_input = true;
- live_input = false;
- }
- else
- {
- // Make it large enough.
- assert(free_input); // must be reallocable
- input.ensureSize(fleft);
- }
- rplimit = rp = input.base();
- input.setLimit(rp + fleft);
- if (!ensure_input(fleft))
- unpack_abort("EOF reading resource file");
- part2.ptr = input_scan();
- part2.len = input_remaining();
- rplimit = rp = input.base();
- }
- jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, part1, part2);
- }
- if (verbose >= 3)
- {
- fprintf(stderr, "Wrote %" PRIu64 " bytes to: %s\n", fsize, f->name);
- }
-}
diff --git a/libraries/pack200/src/unpack.h b/libraries/pack200/src/unpack.h
deleted file mode 100644
index cc5dd60a..00000000
--- a/libraries/pack200/src/unpack.h
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#pragma once
-
-// Global Structures
-struct jar;
-struct gunzip;
-struct band;
-struct constant_pool;
-struct entry;
-struct cpindex;
-struct inner_class;
-struct value_stream;
-
-typedef int64_t (*read_input_fn_t)(unpacker *self, void *buf, int64_t minlen, int64_t maxlen);
-
-struct cpindex
-{
- uint32_t len;
- entry *base1; // base of primary index
- entry **base2; // base of secondary index
- byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
- enum
- {
- SUB_TAG = 64
- };
-
- entry *get(uint32_t i);
-
- void init(int len_, entry *base1_, int ixTag_)
- {
- len = len_;
- base1 = base1_;
- base2 = nullptr;
- ixTag = ixTag_;
- }
- void init(int len_, entry **base2_, int ixTag_)
- {
- len = len_;
- base1 = nullptr;
- base2 = base2_;
- ixTag = ixTag_;
- }
-};
-
-struct constant_pool
-{
- uint32_t nentries;
- entry *entries;
- entry *first_extra_entry;
- uint32_t maxentries; // total allocated size of entries
-
- // Position and size of each homogeneous subrange:
- int tag_count[CONSTANT_Limit];
- int tag_base[CONSTANT_Limit];
- cpindex tag_index[CONSTANT_Limit];
- ptrlist tag_extras[CONSTANT_Limit];
-
- cpindex *member_indexes; // indexed by 2*CONSTANT_Class.inord
- cpindex *getFieldIndex(entry *classRef);
- cpindex *getMethodIndex(entry *classRef);
-
- inner_class **ic_index;
- inner_class **ic_child_index;
- inner_class *getIC(entry *inner);
- inner_class *getFirstChildIC(entry *outer);
- inner_class *getNextChildIC(inner_class *child);
-
- int outputIndexLimit; // index limit after renumbering
- ptrlist outputEntries; // list of entry* needing output idx assigned
-
- entry **hashTab;
- uint32_t hashTabLength;
- entry *&hashTabRef(byte tag, bytes &b);
- entry *ensureUtf8(bytes &b);
- entry *ensureClass(bytes &b);
-
- // Well-known Utf8 symbols.
- enum
- {
-#define SNAME(n, s) s_##s,
- ALL_ATTR_DO(SNAME)
-#undef SNAME
- s_lt_init_gt, // <init>
- s_LIMIT
- };
- entry *sym[s_LIMIT];
-
- // read counts from hdr, allocate main arrays
- enum
- {
- NUM_COUNTS = 12
- };
- void init(unpacker *u, int counts[NUM_COUNTS]);
-
- // pointer to outer unpacker, for error checks etc.
- unpacker *u;
-
- int getCount(byte tag)
- {
- assert((uint32_t)tag < CONSTANT_Limit);
- return tag_count[tag];
- }
- cpindex *getIndex(byte tag)
- {
- assert((uint32_t)tag < CONSTANT_Limit);
- return &tag_index[tag];
- }
- cpindex *getKQIndex(); // uses cur_descr
-
- void expandSignatures();
- void initMemberIndexes();
-
- void computeOutputOrder();
- void computeOutputIndexes();
- void resetOutputIndexes();
-};
-
-/*
- * The unpacker provides the entry points to the unpack engine,
- * as well as maintains the state of the engine.
- */
-struct unpacker
-{
- // One element of the resulting JAR.
- struct file
- {
- const char *name;
- uint64_t size;
- int modtime;
- int options;
- bytes data[2];
- // Note: If Sum(data[*].len) < size,
- // remaining bytes must be read directly from the input stream.
- bool deflate_hint()
- {
- return ((options & FO_DEFLATE_HINT) != 0);
- }
- };
-
- // if running Unix-style, here are the inputs and outputs
- FILE *infileptr; // buffered
- bytes inbytes; // direct
- gunzip *gzin; // gunzip filter, if any
- jar *jarout; // output JAR file
-
- // pointer to self, for U_NEW macro
- unpacker *u;
-
- ptrlist mallocs; // list of guys to free when we are all done
- ptrlist tmallocs; // list of guys to free on next client request
- fillbytes smallbuf; // supplies small alloc requests
- fillbytes tsmallbuf; // supplies temporary small alloc requests
-
- // option management members
- int verbose; // verbose level, 0 means no output
- int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
- int modification_time_or_zero;
-
- // input stream
- fillbytes input; // the whole block (size is predicted, has slop too)
- bool live_input; // is the data in this block live?
- bool free_input; // must the input buffer be freed?
- byte *rp; // read pointer (< rplimit <= input.limit())
- byte *rplimit; // how much of the input block has been read?
- uint64_t bytes_read;
- int unsized_bytes_read;
-
- // callback to read at least one byte, up to available input
- read_input_fn_t read_input_fn;
-
- // archive header fields
- int magic, minver, majver;
- size_t archive_size;
- int archive_next_count, archive_options, archive_modtime;
- int band_headers_size;
- int file_count, attr_definition_count, ic_count, class_count;
- int default_class_minver, default_class_majver;
- int default_file_options, suppress_file_options; // not header fields
- int default_archive_modtime, default_file_modtime; // not header fields
- int code_count; // not a header field
- int files_remaining; // not a header field
-
- // engine state
- band *all_bands; // indexed by band_number
- byte *meta_rp; // read-pointer into (copy of) band_headers
- constant_pool cp; // all constant pool information
- inner_class *ics; // InnerClasses
-
- // output stream
- bytes output; // output block (either classfile head or tail)
- byte *wp; // write pointer (< wplimit == output.limit())
- byte *wpbase; // write pointer starting address (<= wp)
- byte *wplimit; // how much of the output block has been written?
-
- // output state
- file cur_file;
- entry *cur_class; // CONSTANT_Class entry
- entry *cur_super; // CONSTANT_Class entry or nullptr
- entry *cur_descr; // CONSTANT_NameandType entry
- int cur_descr_flags; // flags corresponding to cur_descr
- int cur_class_minver, cur_class_majver;
- bool cur_class_has_local_ics;
- fillbytes cur_classfile_head;
- fillbytes cur_classfile_tail;
- int files_written; // also tells which file we're working on
- int classes_written; // also tells which class we're working on
- uint64_t bytes_written;
- intlist bcimap;
- fillbytes class_fixup_type;
- intlist class_fixup_offset;
- ptrlist class_fixup_ref;
- fillbytes code_fixup_type; // which format of branch operand?
- intlist code_fixup_offset; // location of operand needing fixup
- intlist code_fixup_source; // encoded ID of branch insn
- ptrlist requested_ics; // which ics need output?
-
- // stats pertaining to multiple segments (updated on reset)
- uint64_t bytes_read_before_reset;
- uint64_t bytes_written_before_reset;
- int files_written_before_reset;
- int classes_written_before_reset;
- int segments_read_before_reset;
-
- // attribute state
- struct layout_definition
- {
- uint32_t idx; // index (0..31...) which identifies this layout
- const char *name; // name of layout
- entry *nameEntry;
- const char *layout; // string of layout (not yet parsed)
- band **elems; // array of top-level layout elems (or callables)
-
- bool hasCallables()
- {
- return layout[0] == '[';
- }
- band **bands()
- {
- assert(elems != nullptr);
- return elems;
- }
- };
- struct attr_definitions
- {
- unpacker *u; // pointer to self, for U_NEW macro
- int xxx_flags_hi_bn; // locator for flags, count, indexes, calls bands
- int attrc; // ATTR_CONTEXT_CLASS, etc.
- uint32_t flag_limit; // 32 or 63, depending on archive_options bit
- uint64_t predef; // mask of built-in definitions
- uint64_t redef; // mask of local flag definitions or redefinitions
- ptrlist layouts; // local (compressor-defined) defs, in index order
- int flag_count[X_ATTR_LIMIT_FLAGS_HI];
- intlist overflow_count;
- ptrlist strip_names; // what attribute names are being stripped?
- ptrlist band_stack; // Temp., used during layout parsing.
- ptrlist calls_to_link; // (ditto)
- int bands_made; // (ditto)
-
- void free()
- {
- layouts.free();
- overflow_count.free();
- strip_names.free();
- band_stack.free();
- calls_to_link.free();
- }
-
- // Locate the five fixed bands.
- band &xxx_flags_hi();
- band &xxx_flags_lo();
- band &xxx_attr_count();
- band &xxx_attr_indexes();
- band &xxx_attr_calls();
- band &fixed_band(int e_class_xxx);
-
- // Register a new layout, and make bands for it.
- layout_definition *defineLayout(int idx, const char *name, const char *layout);
- layout_definition *defineLayout(int idx, entry *nameEntry, const char *layout);
- band **buildBands(layout_definition *lo);
-
- // Parse a layout string or part of one, recursively if necessary.
- const char *parseLayout(const char *lp, band **&res, int curCble);
- const char *parseNumeral(const char *lp, int &res);
- const char *parseIntLayout(const char *lp, band *&res, byte le_kind,
- bool can_be_signed = false);
- band **popBody(int band_stack_base); // pops a body off band_stack
-
- // Read data into the bands of the idx-th layout.
- void readBandData(int idx); // parse layout, make bands, read data
- void readBandData(band **body, uint32_t count); // recursive helper
-
- layout_definition *getLayout(uint32_t idx)
- {
- if (idx >= (uint32_t)layouts.length())
- return nullptr;
- return (layout_definition *)layouts.get(idx);
- }
-
- void setHaveLongFlags(bool z)
- {
- assert(flag_limit == 0); // not set up yet
- flag_limit = (z ? X_ATTR_LIMIT_FLAGS_HI : X_ATTR_LIMIT_NO_FLAGS_HI);
- }
- bool haveLongFlags()
- {
- assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
- flag_limit == X_ATTR_LIMIT_FLAGS_HI);
- return flag_limit == X_ATTR_LIMIT_FLAGS_HI;
- }
-
- // Return flag_count if idx is predef and not redef, else zero.
- int predefCount(uint32_t idx);
-
- bool isRedefined(uint32_t idx)
- {
- if (idx >= flag_limit)
- return false;
- return (bool)((redef >> idx) & 1);
- }
- bool isPredefined(uint32_t idx)
- {
- if (idx >= flag_limit)
- return false;
- return (bool)(((predef & ~redef) >> idx) & 1);
- }
- uint64_t flagIndexMask()
- {
- return (predef | redef);
- }
- bool isIndex(uint32_t idx)
- {
- assert(flag_limit != 0); // must be set up already
- if (idx < flag_limit)
- return (bool)(((predef | redef) >> idx) & 1);
- else
- return (idx - flag_limit < (uint32_t)overflow_count.length());
- }
- int &getCount(uint32_t idx)
- {
- assert(isIndex(idx));
- if (idx < flag_limit)
- return flag_count[idx];
- else
- return overflow_count.get(idx - flag_limit);
- }
- };
-
- attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
-
- // Initialization
- void init(read_input_fn_t input_fn = nullptr);
- // Resets to a known sane state
- void reset();
- // Deallocates all storage.
- void free();
- // Deallocates temporary storage (volatile after next client call).
- void free_temps()
- {
- tsmallbuf.init();
- tmallocs.freeAll();
- }
-
- // Option management methods
- bool set_option(const char *option, const char *value);
- const char *get_option(const char *option);
-
- // Fetching input.
- bool ensure_input(int64_t more);
- byte *input_scan()
- {
- return rp;
- }
- size_t input_remaining()
- {
- return rplimit - rp;
- }
- size_t input_consumed()
- {
- return rp - input.base();
- }
-
- // Entry points to the unpack engine
- static int run(int argc, char **argv); // Unix-style entry point.
- void check_options();
- void start(void *packptr = nullptr, size_t len = 0);
- void write_file_to_jar(file *f);
- void finish();
-
- // Public post unpack methods
- int get_files_remaining()
- {
- return files_remaining;
- }
- int get_segments_remaining()
- {
- return archive_next_count;
- }
- file *get_next_file(); // returns nullptr on last file
-
- // General purpose methods
- void *alloc(size_t size)
- {
- return alloc_heap(size, true);
- }
- void *temp_alloc(size_t size)
- {
- return alloc_heap(size, true, true);
- }
- void *alloc_heap(size_t size, bool smallOK = false, bool temp = false);
- void saveTo(bytes &b, const char *str)
- {
- saveTo(b, (byte *)str, strlen(str));
- }
- void saveTo(bytes &b, bytes &data)
- {
- saveTo(b, data.ptr, data.len);
- }
- void saveTo(bytes &b, byte *ptr, size_t len); //{ b.ptr = U_NEW...}
- const char *saveStr(const char *str)
- {
- bytes buf;
- saveTo(buf, str);
- return buf.strval();
- }
- const char *saveIntStr(int num)
- {
- char buf[30];
- sprintf(buf, "%d", num);
- return saveStr(buf);
- }
- static unpacker *current(); // find current instance
-
- // Output management
- void set_output(fillbytes *which)
- {
- assert(wp == nullptr);
- which->ensureSize(1 << 12); // covers the average classfile
- wpbase = which->base();
- wp = which->limit();
- wplimit = which->end();
- }
- fillbytes *close_output(fillbytes *which = nullptr); // inverse of set_output
-
- // These take an implicit parameter of wp/wplimit, and resize as necessary:
- byte *put_space(size_t len); // allocates space at wp, returns pointer
- size_t put_empty(size_t s)
- {
- byte *p = put_space(s);
- return p - wpbase;
- }
- void ensure_put_space(size_t len);
- void put_bytes(bytes &b)
- {
- b.writeTo(put_space(b.len));
- }
- void putu1(int n)
- {
- putu1_at(put_space(1), n);
- }
- void putu1_fast(int n)
- {
- putu1_at(wp++, n);
- }
- void putu2(int n); // { putu2_at(put_space(2), n); }
- void putu4(int n); // { putu4_at(put_space(4), n); }
- void putu8(int64_t n); // { putu8_at(put_space(8), n); }
- void putref(entry *e); // { putu2_at(put_space(2), putref_index(e, 2)); }
- void putu1ref(entry *e); // { putu1_at(put_space(1), putref_index(e, 1)); }
- int putref_index(entry *e, int size); // size in [1..2]
- void put_label(int curIP, int size); // size in {2,4}
- void putlayout(band **body);
- void put_stackmap_type();
-
- size_t wpoffset()
- {
- return (size_t)(wp - wpbase);
- } // (unvariant across overflow)
- byte *wp_at(size_t offset)
- {
- return wpbase + offset;
- }
- uint32_t to_bci(uint32_t bii);
- void get_code_header(int &max_stack, int &max_na_locals, int &handler_count, int &cflags);
- band *ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar);
- band *ref_band_for_op(int bc);
-
- // Definitions of standard classfile int formats:
- static void putu1_at(byte *wp, int n)
- {
- assert(n == (n & 0xFF));
- wp[0] = n;
- }
- static void putu2_at(byte *wp, int n);
- static void putu4_at(byte *wp, int n);
- static void putu8_at(byte *wp, int64_t n);
-
- // Private stuff
- void reset_cur_classfile();
- void write_classfile_tail();
- void write_classfile_head();
- void write_code();
- void write_bc_ops();
- void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
- int write_attrs(int attrc, uint64_t indexBits);
-
- // The readers
- void read_bands();
- void read_file_header();
- void read_cp();
- void read_cp_counts(value_stream &hdr);
- void read_attr_defs();
- void read_ics();
- void read_attrs(int attrc, int obj_count);
- void read_classes();
- void read_code_headers();
- void read_bcs();
- void read_bc_ops();
- void read_files();
- void read_Utf8_values(entry *cpMap, int len);
- void read_single_words(band &cp_band, entry *cpMap, int len);
- void read_double_words(band &cp_bands, entry *cpMap, int len);
- void read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len);
- void read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap, int len);
- void read_signature_values(entry *cpMap, int len);
-};
diff --git a/libraries/pack200/src/unpack200.cpp b/libraries/pack200/src/unpack200.cpp
deleted file mode 100644
index e8826f28..00000000
--- a/libraries/pack200/src/unpack200.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <assert.h>
-#include <limits.h>
-#include <time.h>
-#include <stdint.h>
-
-#include "constants.h"
-#include "utils.h"
-#include "defines.h"
-#include "bytes.h"
-#include "coding.h"
-#include "unpack200.h"
-#include "unpack.h"
-#include "zip.h"
-
-// Callback for fetching data, Unix style.
-static int64_t read_input_via_stdio(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
-{
- assert(u->infileptr != nullptr);
- assert(minlen <= maxlen); // don't talk nonsense
- int64_t numread = 0;
- char *bufptr = (char *)buf;
- while (numread < minlen)
- {
- // read available input, up to buf.length or maxlen
- int readlen = (1 << 16);
- if (readlen > (maxlen - numread))
- readlen = (int)(maxlen - numread);
- int nr = 0;
-
- nr = (int)fread(bufptr, 1, readlen, u->infileptr);
- if (nr <= 0)
- {
- if (errno != EINTR)
- break;
- nr = 0;
- }
- numread += nr;
- bufptr += nr;
- assert(numread <= maxlen);
- }
- return numread;
-}
-
-enum
-{
- EOF_MAGIC = 0,
- BAD_MAGIC = -1
-};
-
-static int read_magic(unpacker *u, char peek[], int peeklen)
-{
- assert(peeklen == 4); // magic numbers are always 4 bytes
- int64_t nr = (u->read_input_fn)(u, peek, peeklen, peeklen);
- if (nr != peeklen)
- {
- return (nr == 0) ? EOF_MAGIC : BAD_MAGIC;
- }
- int magic = 0;
- for (int i = 0; i < peeklen; i++)
- {
- magic <<= 8;
- magic += peek[i] & 0xFF;
- }
- return magic;
-}
-
-void unpack_200(FILE *input, FILE *output)
-{
- unpacker u;
- u.init(read_input_via_stdio);
-
- // initialize jar output
- // the output takes ownership of the file handle
- jar jarout;
- jarout.init(&u);
- jarout.jarfp = output;
-
- // the input doesn't
- u.infileptr = input;
-
- // read the magic!
- char peek[4];
- int magic;
- magic = read_magic(&u, peek, (int)sizeof(peek));
-
- // if it is a gzip encoded file, we need an extra gzip input filter
- if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
- {
- gunzip *gzin = NEW(gunzip, 1);
- gzin->init(&u);
- // FIXME: why the side effects? WHY?
- u.gzin->start(magic);
- u.start();
- }
- else
- {
- // otherwise, feed the bytes to the unpacker directly
- u.start(peek, sizeof(peek));
- }
-
- // Note: The checks to u.aborting() are necessary to gracefully
- // terminate processing when the first segment throws an error.
- for (;;)
- {
- // Each trip through this loop unpacks one segment
- // and then resets the unpacker.
- for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
- {
- u.write_file_to_jar(filep);
- }
-
- // Peek ahead for more data.
- magic = read_magic(&u, peek, (int)sizeof(peek));
- if (magic != (int)JAVA_PACKAGE_MAGIC)
- {
- // we do not feel strongly about this kind of thing...
- /*
- if (magic != EOF_MAGIC)
- unpack_abort("garbage after end of pack archive");
- */
- break; // all done
- }
-
- // Release all storage from parsing the old segment.
- u.reset();
- // Restart, beginning with the peek-ahead.
- u.start(peek, sizeof(peek));
- }
- u.finish();
- u.free(); // tidy up malloc blocks
- fclose(input);
-}
diff --git a/libraries/pack200/src/utils.cpp b/libraries/pack200/src/utils.cpp
deleted file mode 100644
index fd6dad60..00000000
--- a/libraries/pack200/src/utils.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <assert.h>
-#include <stdint.h>
-
-#include <sys/stat.h>
-
-#ifdef _MSC_VER
-#include <direct.h>
-#include <io.h>
-#include <process.h>
-#else
-#include <unistd.h>
-#endif
-
-#include "constants.h"
-#include "defines.h"
-#include "bytes.h"
-#include "utils.h"
-
-#include "unpack.h"
-
-void *must_malloc(size_t size)
-{
- size_t msize = size;
- void *ptr = (msize > PSIZE_MAX) ? nullptr : malloc(msize);
- if (ptr != nullptr)
- {
- memset(ptr, 0, size);
- }
- else
- {
- throw std::runtime_error(ERROR_ENOMEM);
- }
- return ptr;
-}
-
-void unpack_abort(const char *msg)
-{
- if (msg == nullptr)
- msg = "corrupt pack file or internal error";
- throw std::runtime_error(msg);
-}
diff --git a/libraries/pack200/src/utils.h b/libraries/pack200/src/utils.h
deleted file mode 100644
index 3bd2dae7..00000000
--- a/libraries/pack200/src/utils.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// Definitions of our util functions
-
-#include <stdexcept>
-
-void *must_malloc(size_t size);
-
-// overflow management
-#define OVERFLOW ((size_t) - 1)
-#define PSIZE_MAX (OVERFLOW / 2) /* normal size limit */
-
-inline size_t scale_size(size_t size, size_t scale)
-{
- return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
-}
-
-inline size_t add_size(size_t size1, size_t size2)
-{
- return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) ? OVERFLOW : size1 + size2;
-}
-
-inline size_t add_size(size_t size1, size_t size2, int size3)
-{
- return add_size(add_size(size1, size2), size3);
-}
-
-struct unpacker;
-/// This throws an exception!
-extern void unpack_abort(const char *msg = nullptr);
diff --git a/libraries/pack200/src/zip.cpp b/libraries/pack200/src/zip.cpp
deleted file mode 100644
index e776510b..00000000
--- a/libraries/pack200/src/zip.cpp
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * Note: Lifted from uncrunch.c from jdk sources
- */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <stdint.h>
-
-#include <stdlib.h>
-#include <assert.h>
-
-#ifndef _MSC_VER
-#include <strings.h>
-#endif
-
-#include "defines.h"
-#include "bytes.h"
-#include "utils.h"
-
-#include "constants.h"
-#include "unpack.h"
-
-#include "zip.h"
-
-#include "zlib.h"
-
-inline uint32_t jar::get_crc32(uint32_t c, uchar *ptr, uint32_t len)
-{
- return crc32(c, ptr, len);
-}
-
-// FIXME: this is bullshit. Do real endianness detection.
-#ifdef sparc
-#define SWAP_BYTES(a) ((((a) << 8) & 0xff00) | 0x00ff) & (((a) >> 8) | 0xff00)
-#else
-#define SWAP_BYTES(a) (a)
-#endif
-
-#define GET_INT_LO(a) SWAP_BYTES(a & 0xFFFF)
-
-#define GET_INT_HI(a) SWAP_BYTES((a >> 16) & 0xFFFF);
-
-void jar::init(unpacker *u_)
-{
- BYTES_OF(*this).clear();
- u = u_;
- u->jarout = this;
-}
-
-// Write data to the ZIP output stream.
-void jar::write_data(void *buff, int len)
-{
- while (len > 0)
- {
- int rc = (int)fwrite(buff, 1, len, jarfp);
- if (rc <= 0)
- {
- fprintf(stderr, "Error: write on output file failed err=%d\n", errno);
- exit(1); // Called only from the native standalone unpacker
- }
- output_file_offset += rc;
- buff = ((char *)buff) + rc;
- len -= rc;
- }
-}
-
-void jar::add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
- uint32_t crc)
-{
- uint32_t fname_length = (uint32_t)strlen(fname);
- ushort header[23];
- if (modtime == 0)
- modtime = default_modtime;
- uint32_t dostime = get_dostime(modtime);
-
- header[0] = (ushort)SWAP_BYTES(0x4B50);
- header[1] = (ushort)SWAP_BYTES(0x0201);
- header[2] = (ushort)SWAP_BYTES(0xA);
-
- // required version
- header[3] = (ushort)SWAP_BYTES(0xA);
-
- // flags 02 = maximum sub-compression flag
- header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
-
- // Compression method 8=deflate.
- header[5] = (store) ? 0x0 : SWAP_BYTES(0x08);
-
- // Last modified date and time.
- header[6] = (ushort)GET_INT_LO(dostime);
- header[7] = (ushort)GET_INT_HI(dostime);
-
- // CRC
- header[8] = (ushort)GET_INT_LO(crc);
- header[9] = (ushort)GET_INT_HI(crc);
-
- // Compressed length:
- header[10] = (ushort)GET_INT_LO(clen);
- header[11] = (ushort)GET_INT_HI(clen);
-
- // Uncompressed length.
- header[12] = (ushort)GET_INT_LO(len);
- header[13] = (ushort)GET_INT_HI(len);
-
- // Filename length
- header[14] = (ushort)SWAP_BYTES(fname_length);
- // So called "extra field" length.
- header[15] = 0;
- // So called "comment" length.
- header[16] = 0;
- // Disk number start
- header[17] = 0;
- // File flags => binary
- header[18] = 0;
- // More file flags
- header[19] = 0;
- header[20] = 0;
- // Offset within ZIP file.
- header[21] = (ushort)GET_INT_LO(output_file_offset);
- header[22] = (ushort)GET_INT_HI(output_file_offset);
-
- // Copy the whole thing into the central directory.
- central_directory.append(header, sizeof(header));
-
- // Copy the fname to the header.
- central_directory.append(fname, fname_length);
-
- central_directory_count++;
-}
-
-void jar::write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
- uint32_t crc)
-{
- uint32_t fname_length = (uint32_t)strlen(fname);
- ushort header[15];
- if (modtime == 0)
- modtime = default_modtime;
- uint32_t dostime = get_dostime(modtime);
-
- // ZIP LOC magic.
- header[0] = (ushort)SWAP_BYTES(0x4B50);
- header[1] = (ushort)SWAP_BYTES(0x0403);
-
- // Version
- header[2] = (ushort)SWAP_BYTES(0xA);
-
- // flags 02 = maximum sub-compression flag
- header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
-
- // Compression method = deflate
- header[4] = (store) ? 0x0 : SWAP_BYTES(0x08);
-
- // Last modified date and time.
- header[5] = (ushort)GET_INT_LO(dostime);
- header[6] = (ushort)GET_INT_HI(dostime);
-
- // CRC
- header[7] = (ushort)GET_INT_LO(crc);
- header[8] = (ushort)GET_INT_HI(crc);
-
- // Compressed length:
- header[9] = (ushort)GET_INT_LO(clen);
- header[10] = (ushort)GET_INT_HI(clen);
-
- // Uncompressed length.
- header[11] = (ushort)GET_INT_LO(len);
- header[12] = (ushort)GET_INT_HI(len);
-
- // Filename length
- header[13] = (ushort)SWAP_BYTES(fname_length);
- // So called "extra field" length.
- header[14] = 0;
-
- // Write the LOC header to the output file.
- write_data(header, (int)sizeof(header));
-
- // Copy the fname to the header.
- write_data((char *)fname, (int)fname_length);
-}
-
-void jar::write_central_directory()
-{
- bytes mc;
- mc.set("PACK200");
-
- ushort header[11];
-
- // Create the End of Central Directory structure.
- header[0] = (ushort)SWAP_BYTES(0x4B50);
- header[1] = (ushort)SWAP_BYTES(0x0605);
- // disk numbers
- header[2] = 0;
- header[3] = 0;
- // Number of entries in central directory.
- header[4] = (ushort)SWAP_BYTES(central_directory_count);
- header[5] = (ushort)SWAP_BYTES(central_directory_count);
- // Size of the central directory}
- header[6] = (ushort)GET_INT_LO((int)central_directory.size());
- header[7] = (ushort)GET_INT_HI((int)central_directory.size());
- // Offset of central directory within disk.
- header[8] = (ushort)GET_INT_LO(output_file_offset);
- header[9] = (ushort)GET_INT_HI(output_file_offset);
- // zipfile comment length;
- header[10] = (ushort)SWAP_BYTES((int)mc.len);
-
- // Write the central directory.
- write_data(central_directory.b);
-
- // Write the End of Central Directory structure.
- write_data(header, (int)sizeof(header));
-
- // Write the comment.
- write_data(mc);
-}
-
-// Public API
-
-// Open a Jar file and initialize.
-void jar::openJarFile(const char *fname)
-{
- if (!jarfp)
- {
- jarfp = fopen(fname, "wb");
- if (!jarfp)
- {
- fprintf(stderr, "Error: Could not open jar file: %s\n", fname);
- exit(3); // Called only from the native standalone unpacker
- }
- }
-}
-
-// Add a ZIP entry and copy the file data
-void jar::addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
- bytes &tail)
-{
- int len = (int)(head.len + tail.len);
- int clen = 0;
-
- uint32_t crc = get_crc32(0, Z_NULL, 0);
- if (head.len != 0)
- crc = get_crc32(crc, (uchar *)head.ptr, (uint32_t)head.len);
- if (tail.len != 0)
- crc = get_crc32(crc, (uchar *)tail.ptr, (uint32_t)tail.len);
-
- bool deflate = (deflate_hint && len > 0);
-
- if (deflate)
- {
- if (deflate_bytes(head, tail) == false)
- {
- deflate = false;
- }
- }
- clen = (int)((deflate) ? deflated.size() : len);
- add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
- write_jar_header(fname, !deflate, modtime, len, clen, crc);
-
- if (deflate)
- {
- write_data(deflated.b);
- }
- else
- {
- write_data(head);
- write_data(tail);
- }
-}
-
-// Add a ZIP entry for a directory name no data
-void jar::addDirectoryToJarFile(const char *dir_name)
-{
- bool store = true;
- add_to_jar_directory((const char *)dir_name, store, default_modtime, 0, 0, 0);
- write_jar_header((const char *)dir_name, store, default_modtime, 0, 0, 0);
-}
-
-// Write out the central directory and close the jar file.
-void jar::closeJarFile(bool central)
-{
- if (jarfp)
- {
- fflush(jarfp);
- if (central)
- write_central_directory();
- fflush(jarfp);
- fclose(jarfp);
- }
- reset();
-}
-
-/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
- * time (date in high two bytes, time in low two bytes allowing magnitude
- * comparison).
- */
-inline uint32_t jar::dostime(int y, int n, int d, int h, int m, int s)
-{
- return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0)
- : (((uint32_t)y - 1980) << 25) | ((uint32_t)n << 21) | ((uint32_t)d << 16) |
- ((uint32_t)h << 11) | ((uint32_t)m << 5) | ((uint32_t)s >> 1);
-}
-/*
-#ifdef _REENTRANT // solaris
-extern "C" struct tm *gmtime_r(const time_t *, struct tm *);
-#else
-#define gmtime_r(t, s) gmtime(t)
-#endif
-*/
-/*
- * Return the Unix time in DOS format
- */
-uint32_t jar::get_dostime(int modtime)
-{
- // see defines.h
- if (modtime != 0 && modtime == modtime_cache)
- return dostime_cache;
- if (modtime != 0 && default_modtime == 0)
- default_modtime = modtime; // catch a reasonable default
- time_t t = modtime;
- struct tm sbuf;
- (void)memset((void *)&sbuf, 0, sizeof(sbuf));
- struct tm *s = gmtime_r(&t, &sbuf);
- modtime_cache = modtime;
- dostime_cache =
- dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec);
- // printf("modtime %d => %d\n", modtime_cache, dostime_cache);
- return dostime_cache;
-}
-
-/* Returns true on success, and will set the clen to the compressed
- length, the caller should verify if true and clen less than the
- input data
-*/
-bool jar::deflate_bytes(bytes &head, bytes &tail)
-{
- int len = (int)(head.len + tail.len);
-
- z_stream zs;
- BYTES_OF(zs).clear();
-
- // NOTE: the window size should always be -MAX_WBITS normally -15.
- // unzip/zipup.c and java/Deflater.c
-
- int error =
- deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
- if (error != Z_OK)
- {
- /*
- switch (error)
- {
- case Z_MEM_ERROR:
- PRINTCR((2, "Error: deflate error : Out of memory \n"));
- break;
- case Z_STREAM_ERROR:
- PRINTCR((2, "Error: deflate error : Invalid compression level \n"));
- break;
- case Z_VERSION_ERROR:
- PRINTCR((2, "Error: deflate error : Invalid version\n"));
- break;
- default:
- PRINTCR((2, "Error: Internal deflate error error = %d\n", error));
- }
- */
- return false;
- }
-
- deflated.empty();
- zs.next_out = (uchar *)deflated.grow(len + (len / 2));
- zs.avail_out = (int)deflated.size();
-
- zs.next_in = (uchar *)head.ptr;
- zs.avail_in = (int)head.len;
-
- bytes *first = &head;
- bytes *last = &tail;
- if (last->len == 0)
- {
- first = nullptr;
- last = &head;
- }
- else if (first->len == 0)
- {
- first = nullptr;
- }
-
- if (first != nullptr && error == Z_OK)
- {
- zs.next_in = (uchar *)first->ptr;
- zs.avail_in = (int)first->len;
- error = deflate(&zs, Z_NO_FLUSH);
- }
- if (error == Z_OK)
- {
- zs.next_in = (uchar *)last->ptr;
- zs.avail_in = (int)last->len;
- error = deflate(&zs, Z_FINISH);
- }
- if (error == Z_STREAM_END)
- {
- if (len > (int)zs.total_out)
- {
- deflated.b.len = zs.total_out;
- deflateEnd(&zs);
- return true;
- }
- deflateEnd(&zs);
- return false;
- }
-
- deflateEnd(&zs);
- return false;
-}
-
-// Callback for fetching data from a GZIP input stream
-static int64_t read_input_via_gzip(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
-{
- assert(minlen <= maxlen); // don't talk nonsense
- int64_t numread = 0;
- char *bufptr = (char *)buf;
- char *inbuf = u->gzin->inbuf;
- size_t inbuflen = sizeof(u->gzin->inbuf);
- read_input_fn_t read_gzin_fn = u->gzin->read_input_fn;
- z_stream &zs = *(z_stream *)u->gzin->zstream;
- while (numread < minlen)
- {
- int readlen = (1 << 16); // pretty arbitrary
- if (readlen > (maxlen - numread))
- readlen = (int)(maxlen - numread);
- zs.next_out = (uchar *)bufptr;
- zs.avail_out = readlen;
- if (zs.avail_in == 0)
- {
- zs.avail_in = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
- zs.next_in = (uchar *)inbuf;
- }
- int error = inflate(&zs, Z_NO_FLUSH);
- if (error != Z_OK && error != Z_STREAM_END)
- {
- unpack_abort("error inflating input");
- break;
- }
- int nr = readlen - zs.avail_out;
- numread += nr;
- bufptr += nr;
- assert(numread <= maxlen);
- if (error == Z_STREAM_END)
- {
- enum
- {
- TRAILER_LEN = 8
- };
- // skip 8-byte trailer
- if (zs.avail_in >= TRAILER_LEN)
- {
- zs.avail_in -= TRAILER_LEN;
- }
- else
- {
- // Bug: 5023768,we read past the TRAILER_LEN to see if there is
- // any extraneous data, as we dont support concatenated .gz
- // files just yet.
- int extra = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
- zs.avail_in += extra - TRAILER_LEN;
- }
- // %%% should check final CRC and length here
- // %%% should check for concatenated *.gz files here
- if (zs.avail_in > 0)
- unpack_abort("garbage after end of deflated input stream");
- // pop this filter off:
- u->gzin->free();
- break;
- }
- }
-
- // fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
- // (int)minlen, (int)maxlen, (int)numread);
- return numread;
-}
-
-void gunzip::init(unpacker *u_)
-{
- BYTES_OF(*this).clear();
- u = u_;
- assert(u->gzin == nullptr); // once only, please
- read_input_fn = u->read_input_fn;
- zstream = NEW(z_stream, 1);
- u->gzin = this;
- u->read_input_fn = read_input_via_gzip;
-}
-
-void gunzip::start(int magic)
-{
- assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
- int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes
- enum
- {
- FHCRC = (1 << 1),
- FEXTRA = (1 << 2),
- FNAME = (1 << 3),
- FCOMMENT = (1 << 4)
- };
- char gz_mtime[4];
- char gz_xfl[1];
- char gz_os[1];
- char gz_extra_len[2];
- char gz_hcrc[2];
- char gz_ignore;
- // do not save extra, name, comment
- read_fixed_field(gz_mtime, sizeof(gz_mtime));
- read_fixed_field(gz_xfl, sizeof(gz_xfl));
- read_fixed_field(gz_os, sizeof(gz_os));
- if (gz_flg & FEXTRA)
- {
- read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
- int extra_len = gz_extra_len[0] & 0xFF;
- extra_len += (gz_extra_len[1] & 0xFF) << 8;
- for (; extra_len > 0; extra_len--)
- {
- read_fixed_field(&gz_ignore, 1);
- }
- }
- int null_terms = 0;
- if (gz_flg & FNAME)
- null_terms++;
- if (gz_flg & FCOMMENT)
- null_terms++;
- for (; null_terms; null_terms--)
- {
- for (;;)
- {
- gz_ignore = 0;
- read_fixed_field(&gz_ignore, 1);
- if (gz_ignore == 0)
- break;
- }
- }
- if (gz_flg & FHCRC)
- read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
-
- // now the input stream is ready to read into the inflater
- int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
- if (error != Z_OK)
- {
- unpack_abort("cannot create input");
- }
-}
-
-void gunzip::free()
-{
- assert(u->gzin == this);
- u->gzin = nullptr;
- u->read_input_fn = this->read_input_fn;
- inflateEnd((z_stream *)zstream);
- ::free(zstream);
- zstream = nullptr;
- ::free(this);
-}
-
-void gunzip::read_fixed_field(char *buf, size_t buflen)
-{
- int64_t nr = read_input_fn(u, buf, buflen, buflen);
- if ((size_t)nr != buflen)
- unpack_abort("short stream header");
-}
diff --git a/libraries/pack200/src/zip.h b/libraries/pack200/src/zip.h
deleted file mode 100644
index ff973a86..00000000
--- a/libraries/pack200/src/zip.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-#pragma once
-
-#include <stdint.h>
-typedef unsigned short ushort;
-typedef unsigned int uint32_t;
-typedef unsigned char uchar;
-
-#include "unpack.h"
-
-struct jar
-{
- // JAR file writer
- FILE *jarfp;
- int default_modtime;
-
- // Used by unix2dostime:
- int modtime_cache;
- uint32_t dostime_cache;
-
- // Private members
- fillbytes central_directory;
- ushort central_directory_count;
- uint32_t output_file_offset;
- fillbytes deflated; // temporary buffer
-
- // pointer to outer unpacker, for error checks etc.
- unpacker *u;
-
- // Public Methods
- void openJarFile(const char *fname);
- void addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
- bytes &tail);
- void addDirectoryToJarFile(const char *dir_name);
- void closeJarFile(bool central);
-
- void init(unpacker *u_);
-
- void free()
- {
- central_directory.free();
- deflated.free();
- }
-
- void reset()
- {
- free();
- init(u);
- }
-
- // Private Methods
- void write_data(void *ptr, int len);
- void write_data(bytes &b)
- {
- write_data(b.ptr, (int)b.len);
- }
- void add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
- uint32_t crc);
- void write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
- unsigned int crc);
- void write_central_directory();
- uint32_t dostime(int y, int n, int d, int h, int m, int s);
- uint32_t get_dostime(int modtime);
-
- // The definitions of these depend on the NO_ZLIB option:
- bool deflate_bytes(bytes &head, bytes &tail);
- static uint32_t get_crc32(uint32_t c, unsigned char *ptr, uint32_t len);
-};
-
-struct gunzip
-{
- // optional gzip input stream control block
-
- // pointer to outer unpacker, for error checks etc.
- unpacker *u;
-
- read_input_fn_t read_input_fn; // underlying \bchar\b stream
- void *zstream; // inflater state
- char inbuf[1 << 14]; // input buffer
-
- void init(unpacker *u_); // pushes new value on u->read_input_fn
-
- void free();
-
- void start(int magic);
-
- // private stuff
- void read_fixed_field(char *buf, size_t buflen);
-};
diff --git a/travis/prepare.sh b/travis/prepare.sh
deleted file mode 100644
index 9395bc78..00000000
--- a/travis/prepare.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-set -e
-
-if [ "$TRAVIS_OS_NAME" = "linux" ]
-then
- QT_WITHOUT_DOTS=qt$(echo $QT_VERSION | grep -oP "[^\.]*" | tr -d '\n' | tr '[:upper:]' '[:lower]')
- QT_PKG_PREFIX=$(echo $QT_WITHOUT_DOTS | cut -c1-4)
- QT_PKG_INSTALL=$QT_PKG_PREFIX
- if [ "$QT_PKG_PREFIX" = "qt50" ]; then QT_PKG_PREFIX=qt QT_PKG_INSTALL=qt5; fi
- echo $QT_WITHOUT_DOTS
- echo $QT_PKG_PREFIX
- echo $QT_PKG_INSTALL
- if [ "$TRAVIS_DIST" = "precise" ]; then
- sudo add-apt-repository -y ppa:beineri/opt-${QT_WITHOUT_DOTS}
- else
- sudo add-apt-repository -y ppa:beineri/opt-${QT_WITHOUT_DOTS}-$TRAVIS_DIST
- fi
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test # for a recent GCC
- sudo add-apt-repository "deb http://llvm.org/apt/${TRAVIS_DIST}/ llvm-toolchain-${TRAVIS_DIST}-3.5 main"
-
- sudo apt-get update -qq
- sudo apt-get install ${QT_PKG_PREFIX}base ${QT_PKG_PREFIX}svg ${QT_PKG_PREFIX}tools
-
- sudo mkdir -p /opt/cmake-3/
- wget --no-check-certificate http://www.cmake.org/files/v3.9/cmake-3.9.3-Linux-x86_64.sh
- sudo sh cmake-3.9.3-Linux-x86_64.sh --skip-license --prefix=/opt/cmake-3/
-
- export CMAKE_PREFIX_PATH=/opt/$QT_PKG_INSTALL/lib/cmake
- export PATH=/opt/cmake-3/bin:/opt/$QT_PKG_INSTALL/bin:$PATH
-
- if [ "$CXX" = "g++" ]; then
- sudo apt-get install -y -qq g++-5
- export CXX='g++-5' CC='gcc-5'
- fi
- if [ "$CXX" = "clang++" ]; then
- wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add -
- sudo apt-get install -y -qq clang-3.5 liblldb-3.5 libclang1-3.5 libllvm3.5 lldb-3.5 llvm-3.5 llvm-3.5-runtime
- export CXX='clang++-3.5' CC='clang-3.5'
- fi
-else
- brew update
- brew install qt5
- brew install cmake
- export CMAKE_PREFIX_PATH=/usr/local/lib/cmake
-fi
-
-# Output versions
-cmake -version
-qmake -version
-$CXX -v
-echo "CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH"