-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathGpgArguments.kt
121 lines (115 loc) · 4.21 KB
/
GpgArguments.kt
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
112
113
114
115
116
117
118
119
120
121
package org.ddosolitary.okcagent.gpg
import android.content.Context
import org.ddosolitary.okcagent.R
class GpgArguments(
val options: Map<String, String?>,
val arguments: List<String>,
val warnings: List<String>
) {
companion object {
private class OptionInfo(
val longName: String,
val altLongName: String?,
val shortName: Char?,
val hasValue: Boolean,
val notSupported: Boolean = false
)
@Suppress("BooleanLiteralArgument")
private val OptionList = arrayOf(
OptionInfo("sign", null, 's', false),
OptionInfo("clear-sign", "clearsign", null, false),
OptionInfo("detach-sign", null, 'b', false),
OptionInfo("encrypt", null, 'e', false),
OptionInfo("decrypt", null, 'd', false),
OptionInfo("verify", null, null, false),
OptionInfo("armor", null, 'a', false),
OptionInfo("recipient", null, 'r', true),
OptionInfo("compress-level", "bzip2-compress-level", null, true),
OptionInfo("set-filename", null, null, true),
OptionInfo("output", null, 'o', true),
OptionInfo("local-user", null, 'u', true, true),
OptionInfo("default-user", null, null, false, true),
OptionInfo("status-fd", null, null, true, false),
OptionInfo("keyid-format", null, null, true, true),
OptionInfo("quiet", null, 'q', false),
OptionInfo("yes", null, null, false),
OptionInfo("no", null, null, false),
OptionInfo("compress-algo", null, null, true, true),
OptionInfo("batch", null, null, false, true),
OptionInfo("no-batch", null, null, false, true),
OptionInfo("no-encrypt-to", null, null, false),
OptionInfo("use-agent", null, null, false),
OptionInfo("no-use-agent", null, null, false),
OptionInfo("verbose", null, 'v', false),
OptionInfo("no-verbose", null, null, false),
OptionInfo("no-secmem-warning", null, null, false),
OptionInfo("no-permission-warning", null, null, false),
OptionInfo("list-config", null, null, false),
OptionInfo("with-colons", null, null, false)
)
private fun errorInvalidOption(context: Context, name: String): Nothing {
throw Exception(context.getString(R.string.error_option).format(name))
}
private fun setOption(options: MutableMap<String, String?>, name: String, value: String?) {
if (name == "recipient" && options.containsKey(name) && value != null) {
options[name] = "%s\u0000%s".format(options[name], value)
} else {
options[name] = value
}
}
fun parse(context: Context, args: Collection<String>?): GpgArguments {
val options = mutableMapOf<String, String?>()
val arguments = mutableListOf<String>()
val warnings = mutableListOf<String>()
if (args == null) {
return GpgArguments(options, arguments, warnings)
}
var pendingArg: String? = null
for (s in args) {
val checkSupported = { name: String, option: OptionInfo ->
if (option.notSupported) {
warnings.add("[W] " + context.getString(R.string.msg_option_ignored).format(name))
}
}
if (pendingArg != null) {
setOption(options, pendingArg, s)
pendingArg = null
} else if (s.startsWith("--")) {
var pos = s.indexOf('=')
if (pos == -1) pos = s.length
val name = s.substring(2, pos)
val value = s.substring(minOf(s.length, pos + 1))
val info = OptionList.find { it.longName == name || it.altLongName == name }
?: errorInvalidOption(context, name)
checkSupported(name, info)
if (info.hasValue) {
if (value.isEmpty()) {
pendingArg = info.longName
} else {
setOption(options, info.longName, value)
}
} else {
if (value.isEmpty()) setOption(options, info.longName, null)
else errorInvalidOption(context, name)
}
} else if (s.startsWith('-') && s != "-") {
for (i in 1 until s.length) {
if (pendingArg != null) {
setOption(options, pendingArg, s.substring(i))
break
}
val info = OptionList.find { it.shortName == s[i] }
?: errorInvalidOption(context, s[i].toString())
checkSupported(s[i].toString(), info)
if (info.hasValue) pendingArg = info.longName
else setOption(options, info.longName, null)
}
} else {
arguments.add(s)
}
}
if (pendingArg != null) errorInvalidOption(context, pendingArg)
return GpgArguments(options, arguments, warnings)
}
}
}