Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,6 @@ dependencies {
implementation libs.apache.ftpserver.ftplet.api
implementation libs.apache.ftpserver.core

implementation libs.eventbus

implementation libs.libsu.core
implementation libs.libsu.io

Expand Down
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@
android:exported="true"
android:icon="@drawable/ic_ftp_dark"
android:label="@string/ftp"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
tools:targetApi="24">
<intent-filter>
<action
android:name="android.service.quicksettings.action.QS_TILE" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.amaze.filemanager.asynchronous.services.ftp

import com.amaze.filemanager.ui.fragments.FtpServerFragment
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow

/**
* Replacement event bus to handle [FtpService] events using Kotlin's Flow.
*
* Original idea: https://mirchev.medium.com/its-21st-century-stop-using-eventbus-3ff5d9c6a00f
*
* @see [FtpService]
* @see [FtpTileService]
* @see [FtpServerFragment]
*/
object FtpEventBus {
private val _events = MutableSharedFlow<FtpService.FtpReceiverActions>(replay = 0)
val events = _events.asSharedFlow()

/**
* Emit the event signal to the event bus as [MutableSharedFlow].
*
* @param event The event to be emitted.
*/
suspend fun emit(event: FtpService.FtpReceiverActions) {
_events.emit(event)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import android.os.PowerManager
import android.os.SystemClock
import android.provider.DocumentsContract
import androidx.core.app.ServiceCompat
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.amaze.filemanager.BuildConfig
import com.amaze.filemanager.R
Expand All @@ -52,6 +53,10 @@ import com.amaze.filemanager.ui.notifications.FtpNotification
import com.amaze.filemanager.ui.notifications.NotificationConstants
import com.amaze.filemanager.utils.ObtainableServiceBinder
import com.amaze.filemanager.utils.PasswordUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import org.apache.ftpserver.ConnectionConfigFactory
import org.apache.ftpserver.FtpServer
import org.apache.ftpserver.FtpServerFactory
Expand All @@ -61,13 +66,13 @@ import org.apache.ftpserver.ssl.ClientAuth
import org.apache.ftpserver.ssl.impl.DefaultSslConfiguration
import org.apache.ftpserver.usermanager.impl.BaseUser
import org.apache.ftpserver.usermanager.impl.WritePermission
import org.greenrobot.eventbus.EventBus
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.IOException
import java.security.GeneralSecurityException
import java.security.KeyStore
import java.util.LinkedList
import java.util.concurrent.TimeUnit
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.TrustManagerFactory
import kotlin.concurrent.thread
Expand All @@ -79,6 +84,7 @@ import kotlin.concurrent.thread
* Edited by zent-co on 30-07-2019 Edited by bowiechen on 2019-10-19.
*/
class FtpService : Service(), Runnable {
private val serviceScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
private val binder: IBinder = ObtainableServiceBinder(this)

// Service will broadcast via event bus when server start/stop
Expand All @@ -95,6 +101,12 @@ class FtpService : Service(), Runnable {
private var isStartedByTile = false
private lateinit var wakeLock: PowerManager.WakeLock

private fun publishEvent(event: FtpReceiverActions) {
serviceScope.launch {
FtpEventBus.emit(event)
}
}

override fun onStartCommand(
intent: Intent?,
flags: Int,
Expand Down Expand Up @@ -126,7 +138,7 @@ class FtpService : Service(), Runnable {
} else {
startForeground(NotificationConstants.FTP_ID, notification)
}
return START_NOT_STICKY
return START_STICKY
}

override fun onCreate() {
Expand All @@ -143,6 +155,8 @@ class FtpService : Service(), Runnable {

@Suppress("LongMethod")
override fun run() {
// Acquire the WakeLock for 1 hour, per recommended.
wakeLock.acquire(TimeUnit.HOURS.toMillis(1L))
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
FtpServerFactory().run {
val connectionConfigFactory = ConnectionConfigFactory()
Expand Down Expand Up @@ -175,7 +189,7 @@ class FtpService : Service(), Runnable {
}.onFailure {
log.warn("failed to decrypt password in ftp service", it)
AppConfig.toast(applicationContext, R.string.error)
preferences.edit().putString(KEY_PREFERENCE_PASSWORD, "").apply()
preferences.edit { putString(KEY_PREFERENCE_PASSWORD, "") }
isPasswordProtected = false
}
}
Expand Down Expand Up @@ -224,9 +238,9 @@ class FtpService : Service(), Runnable {
)
fac.isImplicitSsl = true
} catch (e: GeneralSecurityException) {
preferences.edit().putBoolean(KEY_PREFERENCE_SECURE, false).apply()
preferences.edit { putBoolean(KEY_PREFERENCE_SECURE, false) }
} catch (e: IOException) {
preferences.edit().putBoolean(KEY_PREFERENCE_SECURE, false).apply()
preferences.edit { putBoolean(KEY_PREFERENCE_SECURE, false) }
}
}
fac.port = getPort(preferences)
Expand All @@ -237,23 +251,22 @@ class FtpService : Service(), Runnable {
server =
createServer().apply {
start()
EventBus.getDefault()
.post(
if (isStartedByTile) {
FtpReceiverActions.STARTED_FROM_TILE
} else {
FtpReceiverActions.STARTED
},
)
publishEvent(
if (isStartedByTile) {
FtpReceiverActions.STARTED_FROM_TILE
} else {
FtpReceiverActions.STARTED
},
)
}
}.onFailure {
EventBus.getDefault().post(FtpReceiverActions.FAILED_TO_START)
wakeLock.release()
publishEvent(FtpReceiverActions.FAILED_TO_START)
}
}
}

override fun onDestroy() {
wakeLock.release()
serverThread?.let { serverThread ->
serverThread.interrupt()
// wait 10 sec for server thread to finish
Expand All @@ -263,9 +276,13 @@ class FtpService : Service(), Runnable {
Companion.serverThread = null
}
server?.stop().also {
EventBus.getDefault().post(FtpReceiverActions.STOPPED)
publishEvent(FtpReceiverActions.STOPPED)
}
}

if (wakeLock.isHeld) {
wakeLock.release()
}
}

// Restart the service if the app is closed from the recent list
Expand Down Expand Up @@ -312,39 +329,6 @@ class FtpService : Service(), Runnable {
const val TAG_STARTED_BY_TILE = "started_by_tile"
// attribute of action_started, used by notification

private lateinit var _enabledCipherSuites: Array<String>

init {
_enabledCipherSuites =
LinkedList<String>().apply {
if (SDK_INT >= Q) {
add("TLS_AES_128_GCM_SHA256")
add("TLS_AES_256_GCM_SHA384")
add("TLS_CHACHA20_POLY1305_SHA256")
}
if (SDK_INT >= N) {
add("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256")
add("TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256")
}
if (SDK_INT >= LOLLIPOP) {
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA")
add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA")
add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384")
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA")
add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA")
add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384")
add("TLS_RSA_WITH_AES_128_GCM_SHA256")
add("TLS_RSA_WITH_AES_256_GCM_SHA384")
}
if (SDK_INT < LOLLIPOP) {
add("TLS_RSA_WITH_AES_128_CBC_SHA")
add("TLS_RSA_WITH_AES_256_CBC_SHA")
}
}.toTypedArray()
}

/**
* Return a list of available ciphers for ftpserver.
*
Expand All @@ -355,7 +339,34 @@ class FtpService : Service(), Runnable {
* @see [javax.net.ssl.SSLEngine]
*/
@JvmStatic
val enabledCipherSuites = _enabledCipherSuites
val enabledCipherSuites: Array<String> =
LinkedList<String>().apply {
if (SDK_INT >= Q) {
add("TLS_AES_128_GCM_SHA256")
add("TLS_AES_256_GCM_SHA384")
add("TLS_CHACHA20_POLY1305_SHA256")
}
if (SDK_INT >= N) {
add("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256")
add("TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256")
}
if (SDK_INT >= LOLLIPOP) {
add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA")
add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA")
add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384")
add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA")
add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA")
add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384")
add("TLS_RSA_WITH_AES_128_GCM_SHA256")
add("TLS_RSA_WITH_AES_256_GCM_SHA384")
}
if (SDK_INT < LOLLIPOP) {
add("TLS_RSA_WITH_AES_128_CBC_SHA")
add("TLS_RSA_WITH_AES_256_CBC_SHA")
}
}.toTypedArray()

private var serverThread: Thread? = null
private var server: FtpServer? = null
Expand Down

This file was deleted.

Loading
Loading