diff --git a/Common/source/customskinloader/CustomSkinLoader.java b/Common/source/customskinloader/CustomSkinLoader.java index b8fd6b0..f326abc 100644 --- a/Common/source/customskinloader/CustomSkinLoader.java +++ b/Common/source/customskinloader/CustomSkinLoader.java @@ -21,7 +21,7 @@ import customskinloader.utils.MinecraftUtil; /** * Custom skin loader mod for Minecraft. - * @author (C) Jeremy Lam [JLChnToZ] 2013 & Alexander Xia [xfl03] 2014-2018 + * @author (C) Jeremy Lam [JLChnToZ] 2013-2014 & Alexander Xia [xfl03] 2014-2019 * @version @MOD_FULL_VERSION@ */ public class CustomSkinLoader { diff --git a/Common/source/customskinloader/loader/LegacyLoader.java b/Common/source/customskinloader/loader/LegacyLoader.java index e6984a4..e26c21f 100644 --- a/Common/source/customskinloader/loader/LegacyLoader.java +++ b/Common/source/customskinloader/loader/LegacyLoader.java @@ -2,6 +2,7 @@ package customskinloader.loader; import java.io.File; +import com.mojang.util.UUIDTypeAdapter; import org.apache.commons.lang3.StringUtils; import com.mojang.authlib.GameProfile; @@ -16,51 +17,54 @@ import customskinloader.utils.HttpRequestUtil.HttpResponce; import customskinloader.utils.HttpTextureUtil; import customskinloader.utils.HttpUtil0; +import javax.annotation.Nonnull; + public class LegacyLoader implements ProfileLoader.IProfileLoader { - public static final String USERNAME_PLACEHOLDER="{USERNAME}"; - + public static final String USERNAME_PLACEHOLDER = "{USERNAME}"; + public static final String UUID_PLACEHOLDER = "{UUID}"; + @Override public UserProfile loadProfile(SkinSiteProfile ssp, GameProfile gameProfile) throws Exception { - String username=gameProfile.getName(); - UserProfile profile=new UserProfile(); - if(StringUtils.isNoneEmpty(ssp.skin)){ - String skin=ssp.skin.replace(USERNAME_PLACEHOLDER, username); - if(HttpUtil0.isLocal(ssp.skin)){ - File skinFile=new File(CustomSkinLoader.DATA_DIR,skin); - if(skinFile.exists()&&skinFile.isFile()) - profile.skinUrl=HttpTextureUtil.getLocalLegacyFakeUrl(skin, HttpTextureUtil.getHash(skin, skinFile.length(), skinFile.lastModified())); - }else{ - HttpResponce responce = HttpRequestUtil.makeHttpRequest(new HttpRequest(skin).setUserAgent(ssp.userAgent).setCheckPNG(ssp.checkPNG!=null && ssp.checkPNG).setLoadContent(false).setCacheTime(90)); - if(responce.success) - profile.skinUrl=HttpTextureUtil.getLegacyFakeUrl(skin); + String username = gameProfile.getName(); + UserProfile profile = new UserProfile(); + if (StringUtils.isNoneEmpty(ssp.skin)) { + String skin = expandURL(ssp.skin, username); + if (HttpUtil0.isLocal(ssp.skin)) { + File skinFile = new File(CustomSkinLoader.DATA_DIR, skin); + if (skinFile.exists() && skinFile.isFile()) + profile.skinUrl = HttpTextureUtil.getLocalLegacyFakeUrl(skin, HttpTextureUtil.getHash(skin, skinFile.length(), skinFile.lastModified())); + } else { + HttpResponce responce = HttpRequestUtil.makeHttpRequest(new HttpRequest(skin).setUserAgent(ssp.userAgent).setCheckPNG(ssp.checkPNG != null && ssp.checkPNG).setLoadContent(false).setCacheTime(90)); + if (responce.success) + profile.skinUrl = HttpTextureUtil.getLegacyFakeUrl(skin); } - profile.model=profile.hasSkinUrl()?ssp.model:null; + profile.model = profile.hasSkinUrl() ? ssp.model : null; } - if(StringUtils.isNoneEmpty(ssp.cape)){ - String cape=ssp.cape.replace(USERNAME_PLACEHOLDER, username); - if(HttpUtil0.isLocal(ssp.cape)){ - File capeFile=new File(CustomSkinLoader.DATA_DIR,cape); - if(capeFile.exists()&&capeFile.isFile()) - profile.capeUrl=HttpTextureUtil.getLocalLegacyFakeUrl(cape, HttpTextureUtil.getHash(cape, capeFile.length(), capeFile.lastModified())); - }else{ - HttpResponce responce = HttpRequestUtil.makeHttpRequest(new HttpRequest(cape).setUserAgent(ssp.userAgent).setCheckPNG(ssp.checkPNG!=null && ssp.checkPNG).setLoadContent(false).setCacheTime(90)); - if(responce.success) - profile.capeUrl=HttpTextureUtil.getLegacyFakeUrl(cape); + if (StringUtils.isNoneEmpty(ssp.cape)) { + String cape = expandURL(ssp.cape, username); + if (HttpUtil0.isLocal(ssp.cape)) { + File capeFile = new File(CustomSkinLoader.DATA_DIR, cape); + if (capeFile.exists() && capeFile.isFile()) + profile.capeUrl = HttpTextureUtil.getLocalLegacyFakeUrl(cape, HttpTextureUtil.getHash(cape, capeFile.length(), capeFile.lastModified())); + } else { + HttpResponce responce = HttpRequestUtil.makeHttpRequest(new HttpRequest(cape).setUserAgent(ssp.userAgent).setCheckPNG(ssp.checkPNG != null && ssp.checkPNG).setLoadContent(false).setCacheTime(90)); + if (responce.success) + profile.capeUrl = HttpTextureUtil.getLegacyFakeUrl(cape); } } - if(ModelManager0.isElytraSupported()&&StringUtils.isNoneEmpty(ssp.elytra)){ - String elytra=ssp.elytra.replace(USERNAME_PLACEHOLDER, username); - if(HttpUtil0.isLocal(ssp.elytra)){ - File elytraFile=new File(CustomSkinLoader.DATA_DIR,elytra); - if(elytraFile.exists()&&elytraFile.isFile()) - profile.elytraUrl=HttpTextureUtil.getLocalLegacyFakeUrl(elytra, HttpTextureUtil.getHash(elytra, elytraFile.length(), elytraFile.lastModified())); - }else{ - HttpResponce responce=HttpRequestUtil.makeHttpRequest(new HttpRequest(elytra).setUserAgent(ssp.userAgent).setCheckPNG(ssp.checkPNG!=null && ssp.checkPNG).setLoadContent(false).setCacheTime(90)); - if(responce.success) - profile.elytraUrl=HttpTextureUtil.getLegacyFakeUrl(elytra); + if (ModelManager0.isElytraSupported() && StringUtils.isNoneEmpty(ssp.elytra)) { + String elytra = expandURL(ssp.elytra, username); + if (HttpUtil0.isLocal(ssp.elytra)) { + File elytraFile = new File(CustomSkinLoader.DATA_DIR, elytra); + if (elytraFile.exists() && elytraFile.isFile()) + profile.elytraUrl = HttpTextureUtil.getLocalLegacyFakeUrl(elytra, HttpTextureUtil.getHash(elytra, elytraFile.length(), elytraFile.lastModified())); + } else { + HttpResponce responce = HttpRequestUtil.makeHttpRequest(new HttpRequest(elytra).setUserAgent(ssp.userAgent).setCheckPNG(ssp.checkPNG != null && ssp.checkPNG).setLoadContent(false).setCacheTime(90)); + if (responce.success) + profile.elytraUrl = HttpTextureUtil.getLegacyFakeUrl(elytra); } } - if(profile.isEmpty()){ + if (profile.isEmpty()) { CustomSkinLoader.logger.info("Both skin and cape not found."); return null; } @@ -71,6 +75,7 @@ public class LegacyLoader implements ProfileLoader.IProfileLoader { public boolean compare(SkinSiteProfile ssp0, SkinSiteProfile ssp1) { return (!StringUtils.isNoneEmpty(ssp0.skin) || ssp0.skin.equalsIgnoreCase(ssp1.skin)) || (!StringUtils.isNoneEmpty(ssp0.cape) || ssp0.cape.equalsIgnoreCase(ssp1.cape)); } + @Override public String getName() { return "Legacy"; @@ -78,18 +83,36 @@ public class LegacyLoader implements ProfileLoader.IProfileLoader { @Override public void init(SkinSiteProfile ssp) { - if(HttpUtil0.isLocal(ssp.skin)) + if (HttpUtil0.isLocal(ssp.skin)) initFolder(ssp.skin); - if(HttpUtil0.isLocal(ssp.cape)) + if (HttpUtil0.isLocal(ssp.cape)) initFolder(ssp.cape); - if(HttpUtil0.isLocal(ssp.elytra)) + if (HttpUtil0.isLocal(ssp.elytra)) initFolder(ssp.elytra); } + @SuppressWarnings("ResultOfMethodCallIgnored") - private void initFolder(String target){ - String file=target.replace(USERNAME_PLACEHOLDER, "init"); - File folder=new File(CustomSkinLoader.DATA_DIR,file).getParentFile(); - if(folder!=null&&!folder.exists()) + private void initFolder(String target) { + String file = target.replace(USERNAME_PLACEHOLDER, "init"); + File folder = new File(CustomSkinLoader.DATA_DIR, file).getParentFile(); + if (folder != null && !folder.exists()) folder.mkdirs(); } + + private String expandURL(String url, String username) { + String t = url.replace(USERNAME_PLACEHOLDER, username); + if (t.contains(UUID_PLACEHOLDER)) + t = t.replace(UUID_PLACEHOLDER, getMojangUUID(username)); + return t; + } + + @Nonnull + private String getMojangUUID(String username) { + GameProfile profile = MojangAPILoader.loadGameProfile(MojangAPILoader.getMojangApiRoot(), username); + if (profile == null) { + CustomSkinLoader.logger.info("UUID for %s not found.", username); + return "{ABORT}"; + } + return UUIDTypeAdapter.fromUUID(profile.getId()); + } } diff --git a/Common/source/customskinloader/loader/MojangAPILoader.java b/Common/source/customskinloader/loader/MojangAPILoader.java index d50e0ee..5e0b848 100644 --- a/Common/source/customskinloader/loader/MojangAPILoader.java +++ b/Common/source/customskinloader/loader/MojangAPILoader.java @@ -129,6 +129,11 @@ public class MojangAPILoader implements ProfileLoader.IProfileLoader { ssp.apiRoot = "https://api.mojang.com/"; if (ssp.sessionRoot == null) ssp.sessionRoot = "https://sessionserver.mojang.com/"; + } + private static final String MOJANG_API_ROOT = "https://api{DO_NOT_MODIFY}.mojang.com/"; + + public static String getMojangApiRoot() { + return MOJANG_API_ROOT.replace("{DO_NOT_MODIFY}", ""); } } diff --git a/Common/source/customskinloader/utils/HttpRequestUtil.java b/Common/source/customskinloader/utils/HttpRequestUtil.java index 2b84e01..38ae03a 100644 --- a/Common/source/customskinloader/utils/HttpRequestUtil.java +++ b/Common/source/customskinloader/utils/HttpRequestUtil.java @@ -87,6 +87,10 @@ public class HttpRequestUtil { public static HttpResponce makeHttpRequest(HttpRequest request, int redirectTime) { try { + if(request.url.contains("{ABORT}")){ + CustomSkinLoader.logger.info("ABORT tag found in url, request has been aborted."); + return new HttpResponce(); + } CustomSkinLoader.logger.debug("Try to request '" + request.url + (request.userAgent == null ? "'." : "' with user agent '" + request.userAgent + "'.")); //Check Cache if (StringUtils.isNotEmpty(request.payload)) diff --git a/README.md b/README.md index 927b591..9764aa0 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,8 @@ Including some codes from - [RecursiveG/UniSkinMod](https://github.com/RecursiveG/UniSkinMod) (GPLv3) - [NekoCaffeine/Alchemy](https://github.com/NekoCaffeine/Alchemy) (GPLv3) -Copyright(C) 2013-2018 JLChnToZ xfl03 +Copyright © 2013-2014 Jeremy Lam "JLChnToZ". +Copyright © 2014-2019 Alexander Xia "xfl03". 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 3 of the License, or (at your option) any later version.