diff --git a/.project b/.project new file mode 100644 index 0000000..fabf3ff --- /dev/null +++ b/.project @@ -0,0 +1,28 @@ + + + ModsListDownloader + Project ModsListDownloader created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + + + 1625690947479 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..57d07cc --- /dev/null +++ b/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,13 @@ +arguments= +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.8)) +connection.project.dir= +eclipse.preferences.version=1 +gradle.user.home= +java.home=/usr/lib/jvm/java-11-graalvm +jvm.arguments= +offline.mode=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/MANIFEST.MF b/ModsListDownloader/MANIFEST.MF similarity index 100% rename from MANIFEST.MF rename to ModsListDownloader/MANIFEST.MF diff --git a/ModsListDownloader/lib/commons-compress-1.20.jar b/ModsListDownloader/lib/commons-compress-1.20.jar new file mode 100644 index 0000000..17c1c7b Binary files /dev/null and b/ModsListDownloader/lib/commons-compress-1.20.jar differ diff --git a/ModsListDownloader/lib/gson-2.8.6.jar b/ModsListDownloader/lib/gson-2.8.6.jar new file mode 100644 index 0000000..4765c4a Binary files /dev/null and b/ModsListDownloader/lib/gson-2.8.6.jar differ diff --git a/makefile b/ModsListDownloader/makefile similarity index 100% rename from makefile rename to ModsListDownloader/makefile diff --git a/scripts/build.sh b/ModsListDownloader/scripts/build.sh similarity index 100% rename from scripts/build.sh rename to ModsListDownloader/scripts/build.sh diff --git a/scripts/clean.sh b/ModsListDownloader/scripts/clean.sh similarity index 100% rename from scripts/clean.sh rename to ModsListDownloader/scripts/clean.sh diff --git a/scripts/fatPackage.sh b/ModsListDownloader/scripts/fatPackage.sh similarity index 100% rename from scripts/fatPackage.sh rename to ModsListDownloader/scripts/fatPackage.sh diff --git a/scripts/package.sh b/ModsListDownloader/scripts/package.sh similarity index 100% rename from scripts/package.sh rename to ModsListDownloader/scripts/package.sh diff --git a/.gitignore b/ModsListDownloader/src/.gitignore similarity index 100% rename from .gitignore rename to ModsListDownloader/src/.gitignore diff --git a/downloader/CurseForgeModFile.java b/ModsListDownloader/src/downloader/CurseForgeModFile.java similarity index 99% rename from downloader/CurseForgeModFile.java rename to ModsListDownloader/src/downloader/CurseForgeModFile.java index 21ca2f1..2aaf669 100644 --- a/downloader/CurseForgeModFile.java +++ b/ModsListDownloader/src/downloader/CurseForgeModFile.java @@ -19,7 +19,6 @@ public class CurseForgeModFile extends ProjectInfo { public int getFileID() { return this.fileID; } - public int getProjectID() { return this.projectID; } diff --git a/downloader/DBConnector.java b/ModsListDownloader/src/downloader/DBConnector.java similarity index 100% rename from downloader/DBConnector.java rename to ModsListDownloader/src/downloader/DBConnector.java diff --git a/ModsListDownloader/src/downloader/Database.java b/ModsListDownloader/src/downloader/Database.java new file mode 100644 index 0000000..9b8987f --- /dev/null +++ b/ModsListDownloader/src/downloader/Database.java @@ -0,0 +1,138 @@ +package downloader; + +import java.io.File; +import java.net.MalformedURLException; +import java.sql.ResultSet; +import java.sql.SQLException; + +import com.google.gson.Gson; + +import downloader.forgeSvc.ForgeSvcEntry; +import downloader.forgeSvc.ForgeSvcFile; +import downloader.helper.HttpHelper; + +public class Database { + DBConnector connector; + IntegrityChecker integrityChecker; + + Gson gson; + + public Database() { + this.connector = new DBConnector(); + try { + this.connector.connect((new File("database.dat")).getAbsolutePath()); + } catch (SQLException e) { + //database hs + System.exit(1); + } + + integrityChecker = new IntegrityChecker(); + this.gson = new Gson(); + } + + private int findProjectBySlug(String slug, int ptype) { + int modID = -1; + ResultSet rs = this.connector.executeRequest("select projectid from projects where type =" + ptype + " and slug =\"" + + slug.trim().toLowerCase() + "\""); + try { + if (rs.next()) { + modID = rs.getInt("projectid"); + } else { + Log.e("DB", "not found " + slug); + return -1; + } + } catch (SQLException e) { + e.printStackTrace(); + return -1; + } + return modID; + } + + private int findModBySlug(String slug) { + return findProjectBySlug(slug, 0); + } + + private ProjectInfo getProjectInfo(int projectId) { + ResultSet rs = this.connector.executeRequest( + "select slug, name, description from projects where projectid = " + projectId + " and type = 0"); + try { + if (rs.next()) + return new ProjectInfo(rs.getString("slug"), rs.getString("name"), rs.getString("description")); + } catch (SQLException sQLException) {} + return null; + } + + public boolean fetchMod(String string) { + String name = string.split("/")[5]; + int modID = findModBySlug(name); + if (modID == -1) { + Log.e("DB", "could not find mod id"); + return false; + } + ProjectInfo pj = getProjectInfo(modID); + if (pj == null) + return false; + CurseForgeModFile modfile = new CurseForgeModFile(pj, modID, -1, false); + ForgeSvcFile file = getLastestFile("1.12.2", modfile); + if (file != null) { + try { + boolean upToDate; + String downloadUrl = file.getDownloadUrl(modID); + if (Main.verbose) + Log.i("MOD", "checking " + pj.getName().replace(" ", "-")); + if (this.integrityChecker.isModIdKnown(modID)) { + if (Main.verbose) + Log.i("DB", "found " + name); + upToDate = this.integrityChecker + .checkAndDelete(new File("mods/" + HttpHelper.getFileNameFromURL(downloadUrl)), modID); + } else { + Log.i("DB", "NEW MOD DETECTED " + modID); + upToDate = this.integrityChecker.checkAndDelete( + new File("mods/" + HttpHelper.getFileNameFromURL(downloadUrl)), pj.getSlug()); + } + if (!upToDate) { + if (Main.verbose) + Log.i("MOD", "downloading " + pj.getName().replace(" ", "-")); + if (!Main.checkingonly) + HttpHelper.readFileFromUrlToFolder(downloadUrl, "mods"); + if (Main.verbose) + Log.i("MOD", "download finished"); + if (!this.integrityChecker.isModIdKnown(modID) && !Main.checkingonly) { + this.integrityChecker.addModsToTheList(HttpHelper.getFileNameFromURL(downloadUrl), modID); + if (Main.verbose) + Log.i("DB", "added a mod to the registry"); + } + } + return true; + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } else { + Log.e("DB", "no file in server"); + } + return false; + } + + public ForgeSvcFile getLastestFile(String minecraftVer, CurseForgeModFile mod) { + String jsonProject, projectUrl = "https://addons-ecs.forgesvc.net/api/v2/addon/" + mod.getProjectID(); + try { + jsonProject = HttpHelper.readStringFromUrl(projectUrl); + if (jsonProject.equals("error")) + return null; + } catch (MalformedURLException e) { + e.printStackTrace(); + return null; + } + ForgeSvcEntry entry = (ForgeSvcEntry)this.gson.fromJson(jsonProject, ForgeSvcEntry.class); + byte b; + int i; + ForgeSvcFile[] arrayOfForgeSvcFile; + for (i = (arrayOfForgeSvcFile = entry.getFiles()).length, b = 0; b < i; ) { + ForgeSvcFile f = arrayOfForgeSvcFile[b]; + if (f.getGameVersion().equals(minecraftVer)) + return f; + b++; + } + return null; + } +} diff --git a/ModsListDownloader/src/downloader/DatabaseVersionManager.java b/ModsListDownloader/src/downloader/DatabaseVersionManager.java new file mode 100644 index 0000000..9f09b2a --- /dev/null +++ b/ModsListDownloader/src/downloader/DatabaseVersionManager.java @@ -0,0 +1,88 @@ +package downloader; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.net.MalformedURLException; + +import downloader.helper.ArchiveHelper; +import downloader.helper.HttpHelper; + +public class DatabaseVersionManager { + + private String version; + private static final String Iam = "DBUpdater"; + + public DatabaseVersionManager() { + try { + this.version = fetchVersionFromFile(); + } catch (FileNotFoundException e) { + this.version = null; + } + } + + public void updateIfNeeded() { + String latestVersion = fetchLatestVersion(); + + if( !version.equals(latestVersion) ) { + Log.i(Iam, "new dbVersion avaliable downloading..."); + downloadDatabase(latestVersion); + } else { + Log.i(Iam, "update to Date"); + } + } + + private void downloadDatabase(String dbVersion) { + Log.i(Iam, "fetching=" + "http://files.mcdex.net/data/mcdex-v5-" + dbVersion + ".dat.bz2"); + File archive; + try { + archive = HttpHelper.readFileFromUrl("http://files.mcdex.net/data/mcdex-v5-" + dbVersion + ".dat.bz2"); + } catch (MalformedURLException e) { + Log.e(Iam, "Error invalid database download url"); + System.exit(1); + //utile pour le lint + return; + } + Log.i(Iam, "download finished"); + Log.i(Iam, "decompressing db"); + try { + ArchiveHelper.decompressBz2(archive, "database.dat"); + archive.delete(); + } catch (IOException e) { + Log.e(Iam, "[ERROR]cannot extract database"); + if(archive.exists()) archive.delete(); + System.exit(1); + } + } + + private String fetchLatestVersion() { + try { + return HttpHelper.readStringFromUrl("http://files.mcdex.net/data/latest.v5"); + } catch (MalformedURLException e) { + //erreur critique il ne faut pas continuer + e.printStackTrace(); + System.exit(1); + } + return null; + } + + private static String fetchVersionFromFile() throws FileNotFoundException { + File versionFile = new File("dbVersion"); + if( versionFile.exists()) { + BufferedReader bfr = new BufferedReader(new FileReader(versionFile)); + try { + String version = bfr.readLine(); + bfr.close(); + return version; + } catch (IOException e) { + //si on peut pas lire le fichier on le suprime + versionFile.delete(); + return null; + } + } else { + throw new FileNotFoundException(); + } + } +} diff --git a/ModsListDownloader/src/downloader/IntegrityChecker.java b/ModsListDownloader/src/downloader/IntegrityChecker.java new file mode 100644 index 0000000..eb8a578 --- /dev/null +++ b/ModsListDownloader/src/downloader/IntegrityChecker.java @@ -0,0 +1,158 @@ +package downloader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.zip.ZipFile; + +public class IntegrityChecker { + public String[] fileList; + public SortedMap installedMods; + public File modsMap; + + @SuppressWarnings("unchecked") + public IntegrityChecker() + { + fileList = new File("mods").list(); + modsMap = new File("mods/modsMap.sav"); + if(modsMap.exists()) + { + try { + ObjectInputStream ois = new ObjectInputStream(new FileInputStream(modsMap)); + installedMods = (SortedMap) ois.readObject(); + if(installedMods == null)installedMods = new TreeMap<>(); + ois.close(); + } catch (Exception e) { + installedMods = new TreeMap<>(); + modsMap.delete(); + } + }else { + try { + modsMap.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(modsMap)); + oos.writeObject(installedMods); + oos.close(); + } catch (IOException e) { + Log.e("SAV", "erreur pas de sauvegarde"); + System.exit(1); + } + } + + public boolean checkAndDelete(File modToDownload, int modid) { + String alredyInstalledName = installedMods.get(modid).toLowerCase(); + File alredyInstalledMods= null; + + + //on cherche le fichier local affin de ne pas voir d'erreur avec la casse + File dir = new File("mods/"); + for(String fileName : dir.list()) + { + if(fileName.equalsIgnoreCase(alredyInstalledName)) + { + alredyInstalledMods = new File("mods/"+fileName); + } + } + if(alredyInstalledMods == null) { + Log.e("IntegrityChecker", "alredy installed mod not found ("+alredyInstalledName+")"); + installedMods.remove(modid); + + return false; + } + + if (alredyInstalledMods.exists()) { + try { + //si sa balance une exception sa veut dire que le jar n'est pas lisible + new ZipFile(alredyInstalledMods).close(); + } catch (IOException e) { + Log.i("integrityChecker","Corruption detected redownloading"); + alredyInstalledMods.delete(); + installedMods.remove(modid); + updateFile(); + return false; + } + if(!modToDownload.getAbsolutePath().equalsIgnoreCase(alredyInstalledMods.getAbsolutePath())) + { + alredyInstalledMods.delete(); + Log.i("integrityChecker","Outdated mod detected redownloading ("+alredyInstalledName+" -> "+modToDownload.getName()+")"); + installedMods.remove(modid); + updateFile(); + return false; + } + return true; + }else { + if(modToDownload.exists()) + { + installedMods.put(modid, modToDownload.getName()); + updateFile(); + Log.i("interessting", modToDownload.getName()); + } + } + return false; + } + + + + public boolean checkAndDelete(File modToDownload, String slug) { + if (modToDownload.exists()) { + try { + //si sa balance une exception sa veut dire que le jar n'est pas lisible + new ZipFile(modToDownload).close(); + } catch (IOException e) { + Log.i("integrityChecker","Corruption detected redownloading"); + modToDownload.delete(); + return false; + } + + for (String s : fileList) { + if (s.contains(slug)) { + if (!modToDownload.getName().contains(s)) { + new File(s).delete(); + Log.i("integrityChecker","Corruption detected redownloading"); + return false; + } + return true; + } + } + return false; + + } + return false; + } + + /** + * un chemin d'acces ne marche pas + * @param fileName + * @param modID + */ + public void addModsToTheList(String fileName,int modID) + { + installedMods.put(modID, fileName); + updateFile(); + } + + public boolean isModIdKnown(int modId) + { + return installedMods.get(modId) != null; + } + + private void updateFile() + { + try { + modsMap.delete(); + ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(modsMap)); + oos.writeObject(installedMods); + oos.close(); + } catch (IOException e) {} + } + +} diff --git a/downloader/Log.java b/ModsListDownloader/src/downloader/Log.java similarity index 93% rename from downloader/Log.java rename to ModsListDownloader/src/downloader/Log.java index 95ca52c..f5c3b32 100644 --- a/downloader/Log.java +++ b/ModsListDownloader/src/downloader/Log.java @@ -1,6 +1,8 @@ package downloader; public class Log { + private Log() {} + public static void e(String who, String msg) { System.err.println(String.valueOf(who) + " : " + msg); } diff --git a/ModsListDownloader/src/downloader/Main.java b/ModsListDownloader/src/downloader/Main.java new file mode 100644 index 0000000..f0a9503 --- /dev/null +++ b/ModsListDownloader/src/downloader/Main.java @@ -0,0 +1,93 @@ +package downloader; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Iterator; + +public class Main { + + public static boolean verbose; + public static boolean checkingonly; + public static Integer threadNb; + private static Database db; + + public static void main(String[] args) { + checkModsDirectory(); + new DatabaseVersionManager().updateIfNeeded(); + db = new Database(); + interpretArgs(args); + } + + public static void checkModsDirectory() { + File modDir = new File("mods"); + if(!modDir.exists()) { + try { + Files.createDirectories(Paths.get("mods")); + } catch (IOException e) { + Log.e("Main","could not create folder"); + System.exit(0); + } + } + } + + private static void interpretArgs(String[] args) { + Iterator it = Arrays.asList(args).iterator(); + final int cores = Runtime.getRuntime().availableProcessors(); + + while (it.hasNext()) { + String cmd = it.next(); + switch (cmd) { + case "--check": + checkingonly = true; + continue; + case "-t": + if (threadNb != null) { + Log.e("main", "error conflicting arguments --thread and -t"); + System.exit(1); + } + + if (cores <= 0) { + Log.i("main","java think you have no cpu core... sooo lets go for 4"); + threadNb = Integer.valueOf(4); + continue; + } + Log.i("main", "running on " + cores + " thread"); + threadNb = Integer.valueOf(cores); + continue; + + case "-v": + verbose = true; + continue; + + case "--thread": + if (threadNb != null) { + Log.e("main", "error conflicting arguments --thread and -t"); + System.exit(1); + } + if (!it.hasNext()) { + Log.e("main", "arguments invalid please refer to --help"); + System.exit(1); + } + String threadNumber = it.next(); + if (threadNumber.matches("[0-9]*")) { + threadNb = Integer.valueOf(Integer.parseInt(threadNumber)); + continue; + } + Log.e("main","arguments invalid please refer to --help"); + System.exit(1); + continue; + + case "--help": + Log.i("main", "use --check to check without updating\nuse --help to see this help\nuse -v to see verbose\nuse --threads to specify the number of threads\nuse -t to set the number of thread automaticaly"); + System.exit(0); + continue; + default: + Log.e("main", "unknown args " + cmd + "\nsee --help for help"); + System.exit(1); + } + } + } +} diff --git a/downloader/ProjectInfo.java b/ModsListDownloader/src/downloader/ProjectInfo.java similarity index 100% rename from downloader/ProjectInfo.java rename to ModsListDownloader/src/downloader/ProjectInfo.java diff --git a/downloader/forgeSvc/ForgeSvcEntry.java b/ModsListDownloader/src/downloader/forgeSvc/ForgeSvcEntry.java similarity index 100% rename from downloader/forgeSvc/ForgeSvcEntry.java rename to ModsListDownloader/src/downloader/forgeSvc/ForgeSvcEntry.java diff --git a/downloader/forgeSvc/ForgeSvcFile.java b/ModsListDownloader/src/downloader/forgeSvc/ForgeSvcFile.java similarity index 94% rename from downloader/forgeSvc/ForgeSvcFile.java rename to ModsListDownloader/src/downloader/forgeSvc/ForgeSvcFile.java index 9d96cf4..589e3b1 100644 --- a/downloader/forgeSvc/ForgeSvcFile.java +++ b/ModsListDownloader/src/downloader/forgeSvc/ForgeSvcFile.java @@ -1,8 +1,9 @@ package downloader.forgeSvc; -import downloader.HttpHelper; import java.net.MalformedURLException; +import downloader.helper.HttpHelper; + public class ForgeSvcFile { private String gameVersion; private int fileType; diff --git a/ModsListDownloader/src/downloader/helper/ArchiveHelper.java b/ModsListDownloader/src/downloader/helper/ArchiveHelper.java new file mode 100644 index 0000000..65934ae --- /dev/null +++ b/ModsListDownloader/src/downloader/helper/ArchiveHelper.java @@ -0,0 +1,23 @@ +package downloader.helper; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; +import org.apache.commons.compress.utils.IOUtils; + +public class ArchiveHelper { + private ArchiveHelper(){} + + public static File decompressBz2(File inputFile, String outputFile) throws IOException { + BZip2CompressorInputStream input = new BZip2CompressorInputStream( + new BufferedInputStream(new FileInputStream(inputFile))); + File decompressedFile = new File(outputFile); + FileOutputStream output = new FileOutputStream(decompressedFile); + IOUtils.copy(input, output); + return decompressedFile; + } +} diff --git a/downloader/HttpHelper.java b/ModsListDownloader/src/downloader/helper/HttpHelper.java similarity index 52% rename from downloader/HttpHelper.java rename to ModsListDownloader/src/downloader/helper/HttpHelper.java index e3f1669..265c761 100644 --- a/downloader/HttpHelper.java +++ b/ModsListDownloader/src/downloader/helper/HttpHelper.java @@ -1,112 +1,142 @@ -package downloader; +package downloader.helper; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; -import java.nio.file.attribute.FileAttribute; + +import downloader.Log; public class HttpHelper { + private HttpHelper() {} + public static String readStringFromUrl(String urlToFetch) throws MalformedURLException { - HttpURLConnection con; URL url = new URL(urlToFetch); + HttpURLConnection con; try { - con = (HttpURLConnection)url.openConnection(); + con = (HttpURLConnection) url.openConnection(); } catch (IOException e1) { e1.printStackTrace(); return "error"; - } + } + String str = ""; - try { - Exception exception2, exception1 = null; - } catch (IOException iOException) {} + + try (InputStream in = con.getInputStream()) { + // par tranche de 4mo + for (;;) { + byte[] buffer = new byte[4096]; + int nbBytesRead = in.read(buffer); + if (nbBytesRead < 0) + break; + + for (int i = 0; i < nbBytesRead; i++) { + str += (char) buffer[i]; + } + } + + } catch (IOException e) {} + return str; } - + public static File readFileFromUrl(String urlToFetch) throws MalformedURLException { String[] url = urlToFetch.split("/"); if (url.length == 0) - throw new MalformedURLException(); + throw new MalformedURLException(); + return readFileFromUrl(urlToFetch, url[url.length - 1]); } - + public static File readFileFromUrl(String urlToFetch, String filename) throws MalformedURLException { return readFileFromUrl(urlToFetch, new File(filename)); } - + public static File readFileFromUrlToFolder(String urlToFetch, String folder) throws MalformedURLException { String name = getFileNameFromURL(urlToFetch); - if (name == null) - throw new MalformedURLException(); - return readFileFromUrlToFolder(urlToFetch, folder, name); + if(name == null)throw new MalformedURLException(); + + return readFileFromUrlToFolder(urlToFetch, folder,name); } - public static File readFileFromUrlToFolder(String urlToFetch, String folder, String name) throws MalformedURLException { + public static File readFileFromUrlToFolder(String urlToFetch, String folder,String name) throws MalformedURLException { try { - Files.createDirectories(Paths.get(folder, new String[0]), (FileAttribute[])new FileAttribute[0]); + Files.createDirectories(Paths.get(folder)); } catch (IOException e) { - Log.e("HTTPHelper", "could not create folder"); + Log.e("HTTPHelper","could not create folder"); return null; - } + } + if (!folder.endsWith("/")) - folder = String.valueOf(folder) + "/"; - return readFileFromUrl(urlToFetch, new File((String.valueOf(folder) + name.toLowerCase()).trim())); + folder += "/"; + + return readFileFromUrl(urlToFetch, new File((folder + name.toLowerCase()).trim())); } - + private static File readFileFromUrl(String urlToFetch, File destination) throws MalformedURLException { - HttpURLConnection con; - FileOutputStream downloadingWriter; URL url = new URL(urlToFetch); + HttpURLConnection con; try { - con = (HttpURLConnection)url.openConnection(); + con = (HttpURLConnection) url.openConnection(); } catch (IOException e1) { e1.printStackTrace(); return null; - } + } + File downloadingFile = destination; System.out.println(downloadingFile.getAbsolutePath()); - if (downloadingFile.exists()) - return downloadingFile; - try { - System.out.println(downloadingFile); - downloadingFile.createNewFile(); - } catch (IOException e) { - Log.e("HTTPHelper", "permission error could not write file"); - e.printStackTrace(); - System.exit(1); - } + + if (downloadingFile.exists()) { + return downloadingFile; + } else { + try { + System.out.println(downloadingFile); + downloadingFile.createNewFile(); + } catch (IOException e) { + Log.e("HTTPHelper","permission error could not write file"); + e.printStackTrace(); + System.exit(1); + } + } + FileOutputStream downloadingWriter; try { downloadingWriter = new FileOutputStream(downloadingFile); } catch (FileNotFoundException e1) { e1.printStackTrace(); return null; - } - try { - Exception exception1 = null, exception2 = null; - try { - - } finally { - exception2 = null; - if (exception1 == null) { - exception1 = exception2; - } else if (exception1 != exception2) { - exception1.addSuppressed(exception2); - } - } - } catch (IOException iOException) { - return null; - } + // imposible vu qu'on l'a crée precedament + } + + try (InputStream in = con.getInputStream()) { + // on lit par tranche de 4mo + byte[] buffer = new byte[4096]; + + while (true) { + int bytesRead = in.read(buffer); + if (bytesRead < 0) + break; + downloadingWriter.write(buffer, 0, bytesRead); + } + downloadingWriter.close(); + return downloadingFile; + } catch (IOException e) {} + return null; + } - public static String getFileNameFromURL(String url) { + public static String getFileNameFromURL(String url) + { String[] urlsplit = url.split("/"); if (urlsplit.length == 0) - return null; + return null; return urlsplit[urlsplit.length - 1]; } + + } diff --git a/downloader/Database.java b/downloader/Database.java deleted file mode 100644 index b375eef..0000000 --- a/downloader/Database.java +++ /dev/null @@ -1,220 +0,0 @@ -package downloader; - -import com.google.gson.Gson; -import downloader.forgeSvc.ForgeSvcEntry; -import downloader.forgeSvc.ForgeSvcFile; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.net.MalformedURLException; -import java.sql.ResultSet; -import java.sql.SQLException; -import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; -import org.apache.commons.compress.utils.IOUtils; - -public class Database { - String version; - - DBConnector connector; - - Gson gson; - - IntegrityChecker integrityChecker; - - File dbVer = new File("dbVersion"); - - public Database() { - if (this.dbVer.exists()) { - try { - BufferedReader bfr = new BufferedReader(new FileReader(this.dbVer)); - this.version = bfr.readLine(); - bfr.close(); - this.connector = new DBConnector(); - this.connector.connect((new File("database.dat")).getAbsolutePath()); - } catch (IOException|SQLException e) { - this.dbVer.delete(); - this.version = ""; - } - } else { - this.version = ""; - } - this.gson = new Gson(); - this.integrityChecker = new IntegrityChecker(); - } - - public void updateDatabase() { - try { - File decompressedDatabase; - String dbVersion = HttpHelper.readStringFromUrl("http://files.mcdex.net/data/latest.v5"); - if (dbVersion.equals(this.version)) { - Log.i("DB", "alredy up to date"); - return; - } - if (dbVersion.equals("error") || dbVersion.trim().equals("")) { - Log.i("DB", "an error ocured"); - System.exit(1); - } - - Log.i("DB", "newer version found"); - if (!this.version.isEmpty()) { - Log.i("DB", "current=" + this.version + " remote=" + dbVersion); - } else { - Log.i("DB", "new=" + dbVersion); - } - Log.i("DB", "fetching=http://files.mcdex.net/data/mcdex-v5-" + dbVersion + ".dat.bz2"); - File archive = HttpHelper.readFileFromUrl("http://files.mcdex.net/data/mcdex-v5-" + dbVersion + ".dat.bz2"); - Log.i("DB", "download finished"); - Log.i("DB", "decompressing db"); - try { - decompressedDatabase = decompressBz2(archive, "database.dat"); - } catch (IOException e) { - Log.i("DB", "cannot extract database"); - return; - } - Log.i("DB", "done"); - Log.i("DB", "loading the database"); - this.connector = new DBConnector(); - try { - this.connector.connect(decompressedDatabase.getAbsolutePath()); - } catch (SQLException e) { - return; - } - Log.i("DB", "database loaded"); - this.version = dbVersion; - Log.i("DB", "saving db data"); - this.dbVer.delete(); - try { - this.dbVer.createNewFile(); - PrintWriter p = new PrintWriter(this.dbVer); - p.print(this.version); - p.close(); - } catch (Exception e) { - Log.e("DB", "failed to save db"); - } - } catch (MalformedURLException e) { - Log.i("DB", "database link is dead"); - System.exit(1); - } - } - - private File decompressBz2(File inputFile, String outputFile) throws IOException { - BZip2CompressorInputStream input = new BZip2CompressorInputStream( - new BufferedInputStream(new FileInputStream(inputFile))); - File decompressedFile = new File(outputFile); - FileOutputStream output = new FileOutputStream(decompressedFile); - IOUtils.copy((InputStream)input, output); - return decompressedFile; - } - - private int findProjectBySlug(String slug, int ptype) { - int modID = -1; - ResultSet rs = this.connector.executeRequest("select projectid from projects where type =" + ptype + " and slug =\"" + - slug.trim().toLowerCase() + "\""); - try { - if (rs.next()) { - modID = rs.getInt("projectid"); - } else { - Log.e("DB", "not found " + slug); - return -1; - } - } catch (SQLException e) { - e.printStackTrace(); - return -1; - } - return modID; - } - - private int findModBySlug(String slug) { - return findProjectBySlug(slug, 0); - } - - private ProjectInfo getProjectInfo(int projectId) { - ResultSet rs = this.connector.executeRequest( - "select slug, name, description from projects where projectid = " + projectId + " and type = 0"); - try { - if (rs.next()) - return new ProjectInfo(rs.getString("slug"), rs.getString("name"), rs.getString("description")); - } catch (SQLException sQLException) {} - return null; - } - - public boolean fetchMod(String string) { - String name = string.split("/")[5]; - int modID = findModBySlug(name); - if (modID == -1) { - Log.e("DB", "could not find mod id"); - return false; - } - ProjectInfo pj = getProjectInfo(modID); - if (pj == null) - return false; - CurseForgeModFile modfile = new CurseForgeModFile(pj, modID, -1, false); - ForgeSvcFile file = getLastestFile("1.12.2", modfile); - if (file != null) { - try { - boolean upToDate; - String downloadUrl = file.getDownloadUrl(modID); - if (Main.isVersbose()) - Log.i("MOD", "checking " + pj.getName().replace(" ", "-")); - if (this.integrityChecker.isModIdKnown(modID)) { - if (Main.isVersbose()) - Log.i("DB", "found " + name); - upToDate = this.integrityChecker - .checkAndDelete(new File("mods/" + HttpHelper.getFileNameFromURL(downloadUrl)), modID); - } else { - Log.i("DB", "NEW MOD DETECTED " + modID); - upToDate = this.integrityChecker.checkAndDelete( - new File("mods/" + HttpHelper.getFileNameFromURL(downloadUrl)), pj.getSlug()); - } - if (!upToDate) { - if (Main.isVersbose()) - Log.i("MOD", "downloading " + pj.getName().replace(" ", "-")); - if (!Main.isCheckingOnly()) - HttpHelper.readFileFromUrlToFolder(downloadUrl, "mods"); - if (Main.isVersbose()) - Log.i("MOD", "download finished"); - if (!this.integrityChecker.isModIdKnown(modID) && !Main.isCheckingOnly()) { - this.integrityChecker.addModsToTheList(HttpHelper.getFileNameFromURL(downloadUrl), modID); - if (Main.isVersbose()) - Log.i("DB", "added a mod to the registry"); - } - } - return true; - } catch (MalformedURLException e) { - e.printStackTrace(); - } - } else { - Log.e("DB", "no file in server"); - } - return false; - } - - public ForgeSvcFile getLastestFile(String minecraftVer, CurseForgeModFile mod) { - String jsonProject, projectUrl = "https://addons-ecs.forgesvc.net/api/v2/addon/" + mod.getProjectID(); - try { - jsonProject = HttpHelper.readStringFromUrl(projectUrl); - if (jsonProject.equals("error")) - return null; - } catch (MalformedURLException e) { - e.printStackTrace(); - return null; - } - ForgeSvcEntry entry = (ForgeSvcEntry)this.gson.fromJson(jsonProject, ForgeSvcEntry.class); - byte b; - int i; - ForgeSvcFile[] arrayOfForgeSvcFile; - for (i = (arrayOfForgeSvcFile = entry.getFiles()).length, b = 0; b < i; ) { - ForgeSvcFile f = arrayOfForgeSvcFile[b]; - if (f.getGameVersion().equals(minecraftVer)) - return f; - b++; - } - return null; - } -} diff --git a/downloader/IntegrityChecker.java b/downloader/IntegrityChecker.java deleted file mode 100644 index 77bf45c..0000000 --- a/downloader/IntegrityChecker.java +++ /dev/null @@ -1,137 +0,0 @@ -package downloader; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.zip.ZipFile; - -public class IntegrityChecker { - public String[] fileList = (new File("mods")).list(); - - public SortedMap installedMods; - - public File modsMap = new File("mods/modsMap.sav"); - - public IntegrityChecker() { - if (this.modsMap.exists()) { - try { - ObjectInputStream ois = new ObjectInputStream(new FileInputStream(this.modsMap)); - this.installedMods = (SortedMap)ois.readObject(); - if (this.installedMods == null) - this.installedMods = new TreeMap<>(); - ois.close(); - } catch (Exception e) { - this.installedMods = new TreeMap<>(); - this.modsMap.delete(); - } - } else { - try { - this.modsMap.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - } - } - try { - ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(this.modsMap)); - oos.writeObject(this.installedMods); - oos.close(); - } catch (IOException e) { - Log.e("SAV", "erreur pas de sauvegarde"); - System.exit(1); - } - } - - public boolean checkAndDelete(File modToDownload, int modid) { - String alredyInstalledName = ((String)this.installedMods.get(Integer.valueOf(modid))).toLowerCase(); - File alredyInstalledMods = null; - File dir = new File("mods/"); - byte b; - int i; - String[] arrayOfString; - for (i = (arrayOfString = dir.list()).length, b = 0; b < i; ) { - String fileName = arrayOfString[b]; - if (fileName.equalsIgnoreCase(alredyInstalledName)) - alredyInstalledMods = new File("mods/" + fileName); - b++; - } - if (alredyInstalledMods == null) { - Log.e("IntegrityChecker", "alredy installed mod not found (" + alredyInstalledName + ")"); - this.installedMods.remove(Integer.valueOf(modid)); - return false; - } - if (alredyInstalledMods.exists()) { - try { - (new ZipFile(alredyInstalledMods)).close(); - } catch (IOException e) { - Log.i("integrityChecker", "Corruption detected redownloading"); - alredyInstalledMods.delete(); - this.installedMods.remove(Integer.valueOf(modid)); - updateFile(); - return false; - } - if (!modToDownload.getAbsolutePath().equalsIgnoreCase(alredyInstalledMods.getAbsolutePath())) { - alredyInstalledMods.delete(); - Log.i("integrityChecker", "Outdated mod detected redownloading (" + alredyInstalledName + " -> " + modToDownload.getName() + ")"); - this.installedMods.remove(Integer.valueOf(modid)); - updateFile(); - return false; - } - return true; - } - if (modToDownload.exists()) { - this.installedMods.put(Integer.valueOf(modid), modToDownload.getName()); - updateFile(); - Log.i("interessting", modToDownload.getName()); - } - return false; - } - - public boolean checkAndDelete(File modToDownload, String slug) { - if (modToDownload.exists()) - try { - (new ZipFile(modToDownload)).close(); - return true; - } catch (IOException e) { - Log.i("integrityChecker", "Corruption detected redownloading"); - modToDownload.delete(); - return false; - } - byte b; - int i; - String[] arrayOfString; - for (i = (arrayOfString = this.fileList).length, b = 0; b < i; ) { - String s = arrayOfString[b]; - if (s.toLowerCase().contains(slug.trim())) { - if (modToDownload.getName().trim().equalsIgnoreCase(s.trim())) - return true; - (new File(s)).delete(); - break; - } - b++; - } - return false; - } - - public void addModsToTheList(String fileName, int modID) { - this.installedMods.put(Integer.valueOf(modID), fileName); - Main.changes.set(Main.changes.get() + 1); - } - - public boolean isModIdKnown(int modId) { - return (this.installedMods.get(Integer.valueOf(modId)) != null); - } - - public void updateFile() { - try { - this.modsMap.delete(); - ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(this.modsMap)); - oos.writeObject(this.installedMods); - oos.close(); - } catch (IOException iOException) {} - } -} diff --git a/downloader/Main.java b/downloader/Main.java deleted file mode 100644 index ae31211..0000000 --- a/downloader/Main.java +++ /dev/null @@ -1,175 +0,0 @@ -package downloader; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.attribute.FileAttribute; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -public class Main { - private static File f = null; - - private static boolean verbose = false; - - private static boolean checkingonly = false; - - public static final AtomicInteger changes = new AtomicInteger(0); - - private static Integer threadNb = null; - - public static void main(String[] args) throws FileNotFoundException, IOException, URISyntaxException { - try { - Files.createDirectories(Paths.get("mods", new String[0]), (FileAttribute[])new FileAttribute[0]); - } catch (IOException e) { - Log.e("HTTPHelper", "could not create folder"); - System.exit(0); - } - interpretArgs(args); - if (f == null) - f = new File("modpack.txt"); - if (!f.exists()) { - System.out.println("file not found"); - System.exit(1); - } - IntegrityChecker updateManager = new IntegrityChecker(); - Database db = new Database(); - db.updateDatabase(); - BufferedReader in = new BufferedReader(new FileReader(f)); - if (threadNb == null) - threadNb = Integer.valueOf(4); - List threads = new ArrayList<>(threadNb.intValue()); - while (in.ready()) { - String line = in.readLine(); - if (!isAComment(line)) { - checkThreadState(threads); - Thread newLineTerpreter = new NewLineInterpreter(line, updateManager, db); - newLineTerpreter.start(); - threads.add(newLineTerpreter); - } - } - checkThreadState(threads); - in.close(); - while (threads.size() != 0) { - try { - Thread.sleep(100L); - } catch (InterruptedException interruptedException) {} - checkThreadState(threads); - } - if (changes.get() != 0 && verbose) - Log.i("Main", "changed " + changes.get() + " mod(s)"); - Log.i("Main", "finished"); - } - - private static void checkThreadState(List threads) { - do { - if (threads.size() >= threadNb.intValue()) - try { - Thread.sleep(100L); - } catch (InterruptedException interruptedException) {} - Iterator it = threads.iterator(); - while (it.hasNext()) { - Thread t = it.next(); - if (!t.isAlive()) - it.remove(); - } - } while (threads.size() >= threadNb.intValue()); - } - - private static void interpretArgs(String[] args) { - Iterator it = Arrays.asList(args).iterator(); - while (it.hasNext()) { - String cmd = it.next(); - if (cmd.startsWith("-")) { - String nbt; - int cores; - String str1; - switch ((str1 = cmd).hashCode()) { - case -1629068440: - if (!str1.equals("--check")) - break; - checkingonly = true; - continue; - case 1511: - if (!str1.equals("-t")) - break; - if (threadNb != null) { - System.out.println("error conflicting arguments --thread and -t"); - System.exit(1); - } - cores = Runtime.getRuntime().availableProcessors(); - if (cores <= 0) { - System.out.println("java think you have no cpu core... sooo lets go for 4"); - threadNb = Integer.valueOf(4); - continue; - } - System.out.println("running on " + cores + " thread"); - threadNb = Integer.valueOf(cores); - continue; - case 1513: - if (!str1.equals("-v")) - break; - verbose = true; - continue; - case 48044553: - if (!str1.equals("--threads")) - break; - if (threadNb != null) { - System.out.println("error conflicting arguments --thread and -t"); - System.exit(1); - } - if (!it.hasNext()) { - System.err.println("arguments invalid please refer to --help"); - System.exit(1); - } - nbt = it.next(); - if (nbt.matches("[0-9]*")) { - threadNb = Integer.valueOf(Integer.parseInt(nbt)); - continue; - } - System.err.println("arguments invalid please refer to --help"); - System.exit(1); - continue; - case 1333013276: - if (!str1.equals("--file")) - break; - if (!it.hasNext()) { - System.err.println("arguments invalid please refer to --help"); - System.exit(1); - } - f = new File(it.next()); - continue; - case 1333069025: - if (!str1.equals("--help")) - break; - System.out.println("use --file to specify the modfile\nuse --check to check without updating\nuse --help to see this help\nuse -v to see verbose\nuse --threads to specify the number of threads\nuse -t to set the number of thread automaticaly"); - System.exit(0); - continue; - } - System.err.print("unknown args " + cmd + "\n" + - "see --help for help"); - System.exit(1); - } - } - } - - public static boolean isAComment(String line) { - return line.startsWith("//"); - } - - public static boolean isVersbose() { - return verbose; - } - - public static boolean isCheckingOnly() { - return checkingonly; - } -} diff --git a/downloader/NewLineInterpreter.java b/downloader/NewLineInterpreter.java deleted file mode 100644 index 1439089..0000000 --- a/downloader/NewLineInterpreter.java +++ /dev/null @@ -1,58 +0,0 @@ -package downloader; - -import java.io.File; -import java.net.MalformedURLException; - -public class NewLineInterpreter extends Thread { - private String line; - - private IntegrityChecker updateManager; - - private Database db; - - public NewLineInterpreter(String line, IntegrityChecker updateManager, Database db) { - this.line = line; - this.updateManager = updateManager; - this.db = db; - } - - public void run() { - super.run(); - interpretLine(); - } - - private void interpretLine() { - if (this.line.startsWith("direct=")) { - String url = this.line.replaceFirst("direct=.*@", ""); - String filename = extractNameFromLink(this.line).toLowerCase(); - String slug = extractSlugFromLink(this.line).toLowerCase(); - boolean upToDate = this.updateManager.checkAndDelete(new File("mods/" + filename), slug); - if (!upToDate) { - if (Main.isVersbose()) - Log.i("main", "downloading " + filename); - if (!Main.isCheckingOnly()) - try { - HttpHelper.readFileFromUrlToFolder(url, "mods", filename); - } catch (MalformedURLException e) { - Log.e("main", "error bad mod url " + this.line); - } - } else if (Main.isVersbose()) { - Log.i("main", "alredy installed"); - } - } else if ((this.line.split("/")).length >= 5 && !this.db.fetchMod(this.line)) { - Log.e("main", "error could not get " + this.line); - } - } - - private String extractSlugFromLink(String line) { - char[] chars = new char[line.length() - line.indexOf(";") - "direct=".length() + 1]; - line.getChars("direct=".length(), line.indexOf(";"), chars, 0); - return new String(chars); - } - - private String extractNameFromLink(String line) { - char[] chars = new char[line.indexOf("@") - line.indexOf(";")]; - line.getChars(line.indexOf(";") + 1, line.indexOf("@"), chars, 0); - return new String(chars); - } -}