Commit ff674e58 authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Merge branch 'master' of https://git.frostnerd.com/PublicAndroidApps/smokescreen into translations

parents 85c7c212 00c57f78
Pipeline #7064 failed with stages
in 3 minutes and 58 seconds
......@@ -42,3 +42,11 @@ captures/
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
libs/
libs/**
.idea/markdown-navigator-enh.xml
.idea/markdown-navigator.xml
.idea/navEditor.xml
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
......@@ -12,6 +12,10 @@ See below for a quick tutorial on how to use Weblate.
**Important!**<br>
I have both a DeepL and a Google Translate API key which I can use to automatically translate the texts to add suggestions to Weblate. Those suggestions won't be used as translations util they are approved. Suggestions fasten the process of translating tremendously as the automatic translation in some cases is already very good or just requires manual edits. Let me know if you want to translate into a new language and I can add the automatic suggestions for those languages to make it faster for you!<br>
## Credentials
If for whatever reason you don't want to create an account you can contact me. I'll then provide you with credentials.
This can for example be useful if you don't want your Name to be assigned with the commit and instead want to remain anonymous.
# How to view your translations
Contributed translations are pushed regularly by Weblate. In some cases it takes some times until this happens.
A new APK file is then automatically created which contains those new translations. You can always download the latest version of [this file here](https://git.frostnerd.com/PublicAndroidApps/smokescreen/-/jobs/artifacts/translations/raw/app/build/outputs/apk/normal/debug/app-normal-debug.apk?job=build_debug).
......
......@@ -6,20 +6,6 @@ apply plugin: 'kotlin-kapt'
def debugKeyPath = new File(System.properties['user.home'], ".android/debug.keystore")
android {
signingConfigs {
fromVariablesOrDebug {
storeFile new File(getSystemVariableOrDefault("KEYSTORE_FILE", debugKeyPath.path))
storePassword getSystemVariableOrDefault("KEYSTORE_PASSWORD", "android")
keyAlias = getSystemVariableOrDefault("KEYSTORE_KEY_NAME", "androiddebugkey")
keyPassword getSystemVariableOrDefault("KEYSTORE_KEY_PASSWORD", "android")
}
release {
storeFile new File(getSystemVariableOrDefault("KEYSTORE_FILE", ""))
storePassword getSystemVariableOrDefault("KEYSTORE_PASSWORD", "")
keyAlias = getSystemVariableOrDefault("KEYSTORE_KEY_NAME", "")
keyPassword getSystemVariableOrDefault("KEYSTORE_KEY_PASSWORD", "")
}
}
compileSdkVersion 29
defaultConfig {
applicationId "com.frostnerd.smokescreen"
......@@ -47,6 +33,20 @@ android {
useSupportLibrary = true
}
}
signingConfigs {
fromVariablesOrDebug {
storeFile new File(getSystemVariableOrDefault("KEYSTORE_FILE", debugKeyPath.path))
storePassword getSystemVariableOrDefault("KEYSTORE_PASSWORD", "android")
keyAlias = getSystemVariableOrDefault("KEYSTORE_KEY_NAME", "androiddebugkey")
keyPassword getSystemVariableOrDefault("KEYSTORE_KEY_PASSWORD", "android")
}
release {
storeFile new File(getSystemVariableOrDefault("KEYSTORE_FILE", ""))
storePassword getSystemVariableOrDefault("KEYSTORE_PASSWORD", "")
keyAlias = getSystemVariableOrDefault("KEYSTORE_KEY_NAME", "")
keyPassword getSystemVariableOrDefault("KEYSTORE_KEY_PASSWORD", "")
}
}
sourceSets {
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
debug.assets.srcDirs += files("$projectDir/schemas".toString())
......@@ -65,10 +65,12 @@ android {
buildConfigField("Boolean", "LEAK_DETECTION", "false")
}
leakCanary {
matchingFallbacks = ['debug']
initWith buildTypes.debug
buildConfigField("Boolean", "LEAK_DETECTION", "true")
}
fdroid {
matchingFallbacks = ['release']
initWith release
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
......@@ -83,10 +85,12 @@ android {
flavorDimensions "version"
productFlavors {
adblocker {
matchingFallbacks = ['default']
dimension "version"
versionNameSuffix "-adblock"
}
normal {
matchingFallbacks = ['default']
dimension "version"
}
}
......@@ -108,19 +112,27 @@ android {
}
}
static def compileBinariesLocally() {
return System.getenv("COMPILE_BINARIES") != null
}
dependencies {
def room_version = "2.2.5"
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5'
implementation('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6')
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6'
implementation 'com.frostnerd.utilskt:preferences:1.5.21' // https://git.frostnerd.com/AndroidUtils/preferenceskt
implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.3.35' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:1.5.191' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy
implementation 'com.frostnerd.utilskt:general:1.0.22' // https://git.frostnerd.com/AndroidUtils/generalkt
implementation 'com.frostnerd.utilskt:adapters:1.1.13' // https://git.frostnerd.com/AndroidUtils/Adapters
if(!compileBinariesLocally()) {
println "Using compiled binaries"
implementation 'com.frostnerd.utilskt:preferences:1.5.22' // https://git.frostnerd.com/AndroidUtils/preferenceskt
implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.3.36' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:1.5.195' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy
implementation 'com.frostnerd.utilskt:general:1.0.24' // https://git.frostnerd.com/AndroidUtils/generalkt
implementation 'com.frostnerd.utilskt:adapters:1.1.15' // https://git.frostnerd.com/AndroidUtils/Adapters
}
implementation 'androidx.work:work-runtime:2.3.4'
implementation 'androidx.appcompat:appcompat:1.1.0'
......@@ -138,7 +150,7 @@ dependencies {
implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01@aar'
implementation 'com.squareup.leakcanary:leaksentry:2.0-alpha-3'
leakCanaryImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'
leakCanaryImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
testImplementation 'junit:junit:4.13'
testImplementation "org.robolectric:robolectric:4.3.1"
......@@ -146,6 +158,28 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
git {
def selfCompile = compileBinariesLocally()
if(selfCompile) {
implementation "https://git.frostnerd.com/AndroidUtils/preferenceskt.git", {
projectPath "/library"
}
implementation "https://git.frostnerd.com/AndroidUtils/navigationdraweractivity.git", {
projectPath "/library"
}
implementation "https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy.git", {
projectPath "/library"
}
implementation "https://git.frostnerd.com/AndroidUtils/generalkt.git", {
projectPath "/library"
}
implementation "https://git.frostnerd.com/AndroidUtils/Adapters.git", {
projectPath "/library"
}
println "Self-compiling libraries"
}
}
def getGitCommitHash() {
def stdout = new ByteArrayOutputStream()
exec {
......
......@@ -24,8 +24,17 @@ import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import kotlinx.android.synthetic.main.dialog_new_server.*
import kotlinx.android.synthetic.main.dialog_new_server.view.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import org.minidns.dnsmessage.DnsMessage
import org.minidns.dnsmessage.Question
import org.minidns.record.Record
import java.lang.Exception
import java.util.concurrent.TimeUnit
/*
* Copyright (C) 2019 Daniel Wolf (Ch4t4r)
......@@ -190,35 +199,7 @@ class NewServerDialog(
onServerAdded: (DnsServerInformation<*>) -> Unit
) {
if (dnsOverHttps) {
val requestType = mapOf(RequestType.WIREFORMAT_POST to ResponseType.WIREFORMAT)
val serverInfo = mutableListOf<HttpsDnsServerConfiguration>()
serverInfo.add(
HttpsDnsServerConfiguration(
address = createHttpsUpstreamAddress(primary),
requestTypes = requestType,
experimental = false
)
)
if (!secondary.isNullOrBlank()) serverInfo.add(
HttpsDnsServerConfiguration(
address = createHttpsUpstreamAddress(
secondary
), requestTypes = requestType, experimental = false
)
)
onServerAdded.invoke(
HttpsDnsServerInformation(
name,
HttpsDnsServerSpecification(
Decision.UNKNOWN,
Decision.UNKNOWN,
Decision.UNKNOWN,
Decision.UNKNOWN
),
serverInfo,
emptyList()
)
)
detectDohServerTypes(name, primary, secondary, onServerAdded)
} else {
val serverInfo = mutableListOf<DnsServerConfiguration<TLSUpstreamAddress>>()
serverInfo.add(
......@@ -250,6 +231,73 @@ class NewServerDialog(
}
}
private fun detectDohServerTypes(
name: String,
primary: String,
secondary: String?,
onServerAdded: (DnsServerInformation<*>) -> Unit
) {
val defaultRequestType = RequestType.WIREFORMAT_POST to ResponseType.WIREFORMAT
val addresses = mutableListOf<HttpsUpstreamAddress>()
addresses.add(createHttpsUpstreamAddress(primary))
if (!secondary.isNullOrBlank()) addresses.add(createHttpsUpstreamAddress(secondary))
val dialog = LoadingDialog(
context,
R.string.dialog_doh_detect_type_title,
R.string.dialog_doh_detect_type_message
)
val httpClient = OkHttpClient.Builder()
.connectTimeout(1250, TimeUnit.MILLISECONDS)
.readTimeout(1250, TimeUnit.MILLISECONDS)
.build()
dialog.show()
GlobalScope.launch {
val availableTypes = mapOf(
defaultRequestType,
RequestType.WIREFORMAT to ResponseType.WIREFORMAT,
RequestType.PARAMETER_REQUEST to ResponseType.JSON
)
val serverInfo = mutableListOf<HttpsDnsServerConfiguration>()
for (address in addresses) {
val detectedTypes = mutableListOf<Pair<RequestType, ResponseType>>()
for (availableType in availableTypes) {
try {
val response = ServerConfiguration.createSimpleServerConfig(address, availableType.key, availableType.value).query(client = httpClient,
question = Question("example.com", Record.TYPE.A))
if(response != null && response.responseCode == DnsMessage.RESPONSE_CODE.NO_ERROR) {
detectedTypes.add(availableType.toPair())
}
} catch (ignored:Exception) {
}
}
if(detectedTypes.isEmpty()) detectedTypes.add(defaultRequestType)
serverInfo.add(HttpsDnsServerConfiguration(
address = address,
experimental = false,
requestTypes = detectedTypes.toMap()
))
}
GlobalScope.launch(Dispatchers.Main) {
dialog.dismiss()
onServerAdded.invoke(
HttpsDnsServerInformation(
name,
HttpsDnsServerSpecification(
Decision.UNKNOWN,
Decision.UNKNOWN,
Decision.UNKNOWN,
Decision.UNKNOWN
),
serverInfo,
emptyList()
)
)
}
}
}
private fun createHttpsUpstreamAddress(url: String): HttpsUpstreamAddress {
context.log("Creating HttpsUpstreamAddress for `$url`")
......
......@@ -357,7 +357,6 @@ class QueryGeneratorDialog(context: Context):AlertDialog(context, context.getPre
val callDomains = view.findViewById<CheckBox>(R.id.baseDomains)
val callDeepurls = view.findViewById<CheckBox>(R.id.deepurls)
val useChrome = view.findViewById<CheckBox>(R.id.useChrome)
val useRandomDelay = view.findViewById<CheckBox>(R.id.randomTimeout)
val delay = view.findViewById<EditText>(R.id.delay)
setView(view)
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:paddingLeft="@dimen/dialog_horizontal_margin"
android:paddingRight="@dimen/dialog_horizontal_margin"
android:paddingTop="@dimen/dialog_vertical_margin"
android:paddingBottom="@dimen/dialog_vertical_margin"
android:layout_width="match_parent"
tools:ignore="HardcodedText"
android:layout_height="match_parent">
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
android:orientation="vertical"
android:paddingLeft="@dimen/dialog_horizontal_margin"
android:paddingTop="@dimen/dialog_vertical_margin"
android:paddingRight="@dimen/dialog_horizontal_margin"
android:paddingBottom="@dimen/dialog_vertical_margin"
tools:ignore="HardcodedText">
<EditText
android:id="@+id/iterations"
android:layout_width="match_parent"
android:hint="Iterations"
android:layout_height="wrap_content"
android:digits="0123456789"
android:hint="Iterations"
android:importantForAutofill="no"
android:inputType="number"
android:id="@+id/iterations"
android:layout_height="wrap_content"/>
android:inputType="number" />
<EditText
android:id="@+id/delay"
android:layout_width="match_parent"
android:hint="Base delay time"
android:layout_height="wrap_content"
android:digits="0123456789"
android:hint="Base delay time"
android:importantForAutofill="no"
android:inputType="number"
android:id="@+id/delay"
android:text="20000"
android:layout_height="wrap_content"/>
android:text="20000" />
<CheckBox
android:id="@+id/baseDomains"
android:layout_width="wrap_content"
android:textColor="?android:attr/textColor"
android:layout_height="wrap_content"
android:text="Open base domains"
android:id="@+id/baseDomains"
android:layout_height="wrap_content"/>
android:textColor="?android:attr/textColor" />
<CheckBox
android:id="@+id/deepurls"
android:layout_width="wrap_content"
android:textColor="?android:attr/textColor"
android:layout_height="wrap_content"
android:text="Open deep urls"
android:id="@+id/deepurls"
android:layout_height="wrap_content"/>
android:textColor="?android:attr/textColor" />
<CheckBox
android:layout_width="wrap_content"
android:id="@+id/randomTimeout"
android:textColor="?android:attr/textColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add random delay"
android:layout_height="wrap_content"/>
android:textColor="?android:attr/textColor" />
<CheckBox
android:id="@+id/useChrome"
android:layout_width="wrap_content"
android:textColor="?android:attr/textColor"
android:layout_height="wrap_content"
android:text="Use chrome"
android:id="@+id/useChrome"
android:layout_height="wrap_content"/>
android:textColor="?android:attr/textColor" />
<CheckBox
android:layout_width="wrap_content"
android:textColor="?android:attr/textColor"
android:text="Restart vpn inbetween sites"
android:id="@+id/restartVpn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:layout_height="wrap_content"/>
android:text="Restart vpn inbetween sites"
android:textColor="?android:attr/textColor" />
</LinearLayout>
\ No newline at end of file
......@@ -187,4 +187,7 @@
<string name="dialog_raterequest_message">Hey there! If you are enjoying Nebulo, would you please take a moment to rate it on the store?</string>
<string name="dialog_vpn_permission_denied_message">The system has denied Nebulo to start its VPN. Please open the app to grant the permission there by clicking the start button.</string>
<string name="dialog_doh_detect_type_title">Detecting server type</string>
<string name="dialog_doh_detect_type_message">Please wait a moment.</string>
</resources>
// Top-level build file where you can add configuration options common to all sub-projects/modules.
static def getSystemVariableOrDefault(String variable, String defaultValue) {
def value = System.getenv(variable)
if(value == null) {
......@@ -8,27 +6,6 @@ static def getSystemVariableOrDefault(String variable, String defaultValue) {
return value
}
//ext.public_artifactory_user = "publicaccess"
//def getArtifactoryUser(Boolean useDefault = true){
// def user = System.getenv("ARTIFACTORY_USER")
// if(user == null && useDefault){
// println "Using public artifactory user"
// user = public_artifactory_user
// }
// return user
//}
//
//ext.public_artifactory_password = "AKCp5ekwNjBNhRDnT7YK3BRHxdep6v1FyUSptgrAMhQBfq2eDTauVemGLmgyKucJYeEPsNJGP"
//def getArtifactoryPassword(Boolean useDefault = true){
// def pw = System.getenv("ARTIFACTORY_PASSWORD")
// if(pw == null && useDefault){
// println "Using public artifactory Password"
// pw = public_artifactory_password
// }
//
// return pw
//}
ext.public_nexus_user = "publicaccess"
def getNexusUser(){
def user = System.getenv("NEXUS_USER")
......@@ -51,13 +28,26 @@ def getNexusPassword(){
return pw
}
//ext.artifactory_username = getArtifactoryUser()
//ext.artifactory_password = getArtifactoryPassword()
ext.nexus_user = getNexusUser()
ext.nexus_password = getNexusPassword()
buildscript {
ext.kotlin_version = '1.3.72'
ext.ANDROID_COMPILE_SDK = (System.getenv("ANDROID_COMPILE_SDK") == null ? 29 : System.getenv("ANDROID_COMPILE_SDK")).toInteger()
ext.ANDROID_TARGET_SDK = (System.getenv("ANDROID_TARGET_SDK") == null ? ANDROID_COMPILE_SDK : System.getenv("ANDROID_TARGET_SDK")).toInteger()
ext.ANDROID_MIN_SDK = (System.getenv("ANDROID_MIN_SDK") == null ? 14 : System.getenv("ANDROID_COMPILE_SDK")).toInteger()
ext.KOTLIN_VERSION = System.getenv("KOTLIN_VERSION") == null ? "1.3.72" : System.getenv("KOTLIN_VERSION")
ext.ANDROID_GRADLE_PLUGIN_VERSION = System.getenv("ANDROID_GRADLE_PLUGIN_VERSION") == null ? "3.6.3" : System.getenv("ANDROID_GRADLE_PLUGIN_VERSION")
ext.APPCOMPAT_VERSION = "1.1.0"
ext.COROUTINE_VERSION = "1.3.6"
ext.RECYCLERVIEW_VERSION = "1.1.0"
ext.ROBOELECTRIC_VERSION = "4.3"
println "COMPILE SDK Version: $ANDROID_COMPILE_SDK"
println "TARGET SDK Version: $ANDROID_TARGET_SDK"
println "MIN SDK: $ANDROID_MIN_SDK"
println "---------------------"
repositories {
google()
jcenter()
......@@ -68,6 +58,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:0.9.18"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......@@ -75,23 +66,10 @@ buildscript {
}
allprojects {
apply plugin: 'maven-publish'
repositories {
google()
jcenter()
//maven {
// url 'https://artifactory.frostnerd.com/artifactory/libs-release-local'
// credentials {
// username = "$artifactory_username"
// password = "$artifactory_password"
// }
//}
//maven {
// url 'https://artifactory.frostnerd.com/artifactory/libs-snapshot-local'
// credentials {
// username = "$artifactory_username"
// password = "$artifactory_password"
// }
//}
maven {
url 'https://nexus.frostnerd.com/repository/libs-release/'
credentials {
......
#Fri Apr 19 12:32:28 CEST 2019
#Mon May 11 21:37:01 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-all.zip
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
......@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m"'
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
......@@ -109,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
......@@ -138,19 +154,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" <