fun main()

in tools/src/main/kotlin/jetbrains/exodus/crypto/Scytale.kt [36:129]


fun main(args: Array<String>) {
    if (args.size < 2) {
        printUsage()
    }
    var sourcePath: String? = null
    var targetPath: String? = null
    var key: ByteArray? = null
    var basicIV: Long? = null
    var compress = false
    var gzip = false
    var overwrite = false
    var type = "chacha"

    for (arg in args) {
        if (arg.startsWith('-') && arg.length < 3) {
            when (arg.lowercase().substring(1)) {
                "g" -> gzip = true
                "z" -> compress = true
                "o" -> overwrite = true
                else -> {
                    printUsage()
                }
            }
        } else {
            if (sourcePath == null) {
                sourcePath = arg
            } else if (targetPath == null) {
                targetPath = arg
            } else if (key == null) {
                key = toBinaryKey(arg)
            } else if (basicIV == null) {
                basicIV = parseIV(arg)
            } else {
                type = arg.lowercase()
                break
            }
        }
    }

    if (sourcePath == null || targetPath == null || key == null || basicIV == null) {
        printUsage()
    }

    val cipherId = when (type) {
        "salsa" -> SALSA20_CIPHER_ID
        "chacha" -> CHACHA_CIPHER_ID
        else -> {
            abort("Unknown cipher id: $type")
        }
    }

    val source = File(sourcePath)
    val target = File(targetPath)

    if (!source.exists()) {
        abort("File not found: ${source.absolutePath}")
    }

    if (target.exists()) {
        val files = target.list()
        files?.let {
            if (files.isNotEmpty()) {
                if (!overwrite) {
                    abort("File exists: ${target.absolutePath}")
                }
                if (!target.deleteRecursively()) {
                    abort("File cannot be fully deleted: ${target.absolutePath}")
                }
            }
        } ?: target.let {
            if (!overwrite) {
                println("Invalid file: ${target.absolutePath}")
            }
        }
    }
    val enCrypted = if (source.isDirectory) {
        BackupUtil.reEncryptBackup(FileTreeArchiveInputStream(source), key, basicIV, null, 0, newCipherProvider(cipherId))
    } else {
        val stream = ArchiveStreamFactory().createArchiveInputStream(BufferedInputStream(
            if (gzip) {
                GZIPInputStream(source.inputStream())
            } else {
                source.inputStream()
            }
        ))
        BackupUtil.reEncryptBackup(stream, key, basicIV, null, 0, newCipherProvider(cipherId))
    }

    if (compress) {
        IOUtils.copy(enCrypted, target.outputStream())
    } else {
        Expander().expand(TarArchiveInputStream(GZIPInputStream(enCrypted)), target.toPath())
    }
}