aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt
blob: 2438a9be383d2a374bec378ebf054dbc465c2f59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package at.hannibal2.skyhanni.data.repo

import at.hannibal2.skyhanni.test.command.ErrorManager
import com.google.gson.Gson
import java.io.BufferedReader
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStreamReader
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.util.zip.ZipInputStream
import java.lang.reflect.Type

object RepoUtils {

    fun recursiveDelete(file: File) {
        if (file.isDirectory && !Files.isSymbolicLink(file.toPath())) {
            for (child in file.listFiles()) {
                recursiveDelete(child)
            }
        }
        file.delete()
    }

    /**
     * Modified from https://www.journaldev.com/960/java-unzip-file-example
     */
    fun unzipIgnoreFirstFolder(zipFilePath: String, destDir: String) {
        val dir = File(destDir)
        // create output directory if it doesn't exist
        if (!dir.exists()) dir.mkdirs()
        val fis: FileInputStream
        //buffer for read and write data to file
        val buffer = ByteArray(1024)
        try {
            fis = FileInputStream(zipFilePath)
            val zis = ZipInputStream(fis)
            var ze = zis.nextEntry
            while (ze != null) {
                if (!ze.isDirectory) {
                    var fileName = ze.name
                    fileName = fileName.substring(fileName.split("/").toTypedArray()[0].length + 1)
                    val newFile = File(destDir + File.separator + fileName)
                    //create directories for sub directories in zip
                    File(newFile.parent).mkdirs()
                    if (!isInTree(dir, newFile)) {
                        throw RuntimeException(
                            "SkyHanni detected an invalid zip file. This is a potential security risk, please report this on the SkyHanni discord."
                        )
                    }
                    val fos = FileOutputStream(newFile)
                    var len: Int
                    while (zis.read(buffer).also { len = it } > 0) {
                        fos.write(buffer, 0, len)
                    }
                    fos.close()
                }
                //close this ZipEntry
                zis.closeEntry()
                ze = zis.nextEntry
            }
            //close last ZipEntry
            zis.closeEntry()
            zis.close()
            fis.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    @Suppress("NAME_SHADOWING")
    @Throws(IOException::class)
    private fun isInTree(rootDirectory: File, file: File): Boolean {
        var rootDirectory = rootDirectory
        var file: File? = file
        file = file!!.canonicalFile
        rootDirectory = rootDirectory.canonicalFile
        while (file != null) {
            if (file == rootDirectory) return true
            file = file.parentFile
        }
        return false
    }

    fun <T> getConstant(repo: File, constant: String, gson: Gson, clazz: Class<T>?, type: Type? = null): T? {
        if (!repo.exists()) return null

        val jsonFile = File(repo, "constants/$constant.json")
        if (!jsonFile.isFile) {
            ErrorManager.logError(
                Error("File '$jsonFile' not found!"),
                "File in repo missing! ($jsonFile). Try §e/shupdaterepo"
            )
            return null
        }
        BufferedReader(
            InputStreamReader(
                FileInputStream(jsonFile),
                StandardCharsets.UTF_8
            )
        ).use { reader ->
            if (type == null) {
                return gson.fromJson(reader, clazz)
            } else {
                return gson.fromJson(reader, type)
            }
        }
    }
}