2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-22 09:58:08 +00:00
Albert Vaca Cintora 2024-05-19 10:02:28 +00:00
parent e8f7e86b35
commit 440f1d4fa3
7 changed files with 69 additions and 6 deletions

View File

@ -183,7 +183,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="pair_requested">Pair requested</string>
<string name="pair_succeeded">Pair succeeded</string>
<string name="pairing_verification_code" translatable="false">🔑 %1s</string>
<string name="pairing_request_from">Pairing request from "%1s"</string>
<string name="pairing_request_from">Pairing request from \'%1s\'</string>
<plurals name="incoming_file_title">Receiving file from %1s>
<item quantity="one">Receiving %1$d file from %2$s</item>
<item quantity="other">Receiving %1$d files from %2$s</item>

View File

@ -22,6 +22,7 @@ import android.util.Log
import org.apache.commons.io.IOUtils
import org.kde.kdeconnect.Backends.BaseLinkProvider
import org.kde.kdeconnect.Device
import org.kde.kdeconnect.DeviceInfo
import org.kde.kdeconnect.DeviceInfo.Companion.fromIdentityPacketAndCert
import org.kde.kdeconnect.Helpers.DeviceHelper
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper
@ -44,6 +45,12 @@ class BluetoothLinkProvider(private val context: Context) : BaseLinkProvider() {
@Throws(CertificateException::class)
private fun addLink(identityPacket: NetworkPacket, link: BluetoothLink) {
if (!DeviceInfo.isValidIdentityPacket(identityPacket)) {
Log.w("KDE/LanLinkProvider", "Invalid identity packet received.")
return
}
val deviceId = identityPacket.getString("deviceId")
Log.i("BluetoothLinkProvider", "addLink to $deviceId")
val oldLink = visibleDevices[deviceId]
@ -369,6 +376,13 @@ class BluetoothLinkProvider(private val context: Context) : BaseLinkProvider() {
socket.close()
return
}
if (!DeviceInfo.isValidIdentityPacket(identityPacket)) {
Log.w("KDE/LanLinkProvider", "Invalid identity packet received.")
connection.close()
return
}
Log.i("BTLinkProvider/Client", "Received identity packet")
val myId = DeviceHelper.getDeviceId(context)
if (identityPacket.getString("deviceId") == myId) {

View File

@ -125,6 +125,12 @@ public class LanLinkProvider extends BaseLinkProvider {
String message = new String(packet.getData(), Charsets.UTF_8);
final NetworkPacket identityPacket = NetworkPacket.unserialize(message);
if (!DeviceInfo.isValidIdentityPacket(identityPacket)) {
Log.w("KDE/LanLinkProvider", "Invalid identity packet received.");
return;
}
final String deviceId = identityPacket.getString("deviceId");
if (!identityPacket.getType().equals(NetworkPacket.PACKET_TYPE_IDENTITY)) {
Log.e("KDE/LanLinkProvider", "Expecting an UDP identity packet");
@ -192,6 +198,11 @@ public class LanLinkProvider extends BaseLinkProvider {
@WorkerThread
private void identityPacketReceived(final NetworkPacket identityPacket, final Socket socket, final LanLink.ConnectionStarted connectionStarted) throws IOException {
if (!DeviceInfo.isValidIdentityPacket(identityPacket)) {
Log.w("KDE/LanLinkProvider", "Invalid identity packet received.");
return;
}
String myId = DeviceHelper.getDeviceId(context);
final String deviceId = identityPacket.getString("deviceId");
if (deviceId.equals(myId)) {

View File

@ -10,6 +10,7 @@ import android.content.Context
import android.content.SharedPreferences
import android.util.Base64
import androidx.core.content.ContextCompat
import org.kde.kdeconnect.Helpers.DeviceHelper
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper
import org.kde.kdeconnect_tp.R
import java.security.cert.Certificate
@ -90,7 +91,7 @@ class DeviceInfo(
with(identityPacket) {
DeviceInfo(
id = getString("deviceId"), // Redundant: We could read this from the certificate instead
name = getString("deviceName", "unknown"),
name = DeviceHelper.filterName(getString("deviceName", "unknown")),
type = DeviceType.fromString(getString("deviceType", "desktop")),
certificate = certificate,
protocolVersion = getInt("protocolVersion"),
@ -98,6 +99,11 @@ class DeviceInfo(
outgoingCapabilities = getStringSet("outgoingCapabilities")
)
}
@JvmStatic
fun isValidIdentityPacket(identityPacket: NetworkPacket): Boolean = with(identityPacket) {
DeviceHelper.filterName(getString("deviceName", "")).isNotBlank() && getString("deviceId", "").isNotBlank()
}
}
}

View File

@ -38,6 +38,9 @@ object DeviceHelper {
private const val DEVICE_DATABASE = "https://storage.googleapis.com/play_public/supported_devices.csv"
private val NAME_INVALID_CHARACTERS_REGEX = "[\"',;:.!?()\\[\\]<>]".toRegex()
const val MAX_DEVICE_NAME_LENGTH = 32
private val isTablet: Boolean by lazy {
val config = Resources.getSystem().configuration
//This assumes that the values for the screen sizes are consecutive, so XXLARGE > XLARGE > LARGE
@ -119,8 +122,9 @@ object DeviceHelper {
}
fun setDeviceName(context: Context, name: String) {
val filteredName = filterName(name)
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
preferences.edit().putString(KEY_DEVICE_NAME_PREFERENCE, name).apply()
preferences.edit().putString(KEY_DEVICE_NAME_PREFERENCE, filteredName).apply()
}
fun initializeDeviceId(context: Context) {
@ -160,4 +164,7 @@ object DeviceHelper {
PluginFactory.getOutgoingCapabilities()
)
}
@JvmStatic
fun filterName(input: String): String = input.replace(NAME_INVALID_CHARACTERS_REGEX, "").take(MAX_DEVICE_NAME_LENGTH)
}

View File

@ -7,14 +7,13 @@
package org.kde.kdeconnect.UserInterface;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.text.InputFilter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -33,6 +32,7 @@ import androidx.preference.TwoStatePreference;
import com.google.android.material.snackbar.Snackbar;
import org.apache.commons.lang3.StringUtils;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Helpers.DeviceHelper;
import org.kde.kdeconnect.Helpers.NotificationHelper;
@ -66,6 +66,10 @@ public class SettingsFragment extends PreferenceFragmentCompat {
renameDevice.setKey(DeviceHelper.KEY_DEVICE_NAME_PREFERENCE);
renameDevice.setSelectable(true);
renameDevice.setOnBindEditTextListener(TextView::setSingleLine);
renameDevice.setOnBindEditTextListener(editText -> editText.setFilters(new InputFilter[] {
(source, start, end, dest, dstart, dend) -> DeviceHelper.filterName(source.subSequence(start, end).toString()),
new InputFilter.LengthFilter(DeviceHelper.MAX_DEVICE_NAME_LENGTH),
}));
String deviceName = DeviceHelper.getDeviceName(context);
renameDevice.setTitle(R.string.settings_rename);
renameDevice.setSummary(deviceName);
@ -76,7 +80,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
renameDevice.setOnPreferenceChangeListener((preference, newValue) -> {
String name = (String) newValue;
if (TextUtils.isEmpty(name)) {
if (StringUtils.isBlank(name)) {
if (getView() != null) {
Snackbar snackbar = Snackbar.make(getView(), R.string.invalid_device_name, Snackbar.LENGTH_LONG);
int currentTheme = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;

View File

@ -132,6 +132,27 @@ public class DeviceTest {
assertEquals(di.outgoingCapabilities, np.getStringSet("outgoingCapabilities"));
}
@Test
public void testIsValidIdentityPacket() {
NetworkPacket np = new NetworkPacket(NetworkPacket.PACKET_TYPE_IDENTITY);
assertFalse(DeviceInfo.Companion.isValidIdentityPacket(np));
String validName = "MyDevice";
String validId = "123";
np.set("deviceName", validName);
np.set("deviceId", validId);
assertTrue(DeviceInfo.Companion.isValidIdentityPacket(np));
np.set("deviceName", " ");
assertFalse(DeviceInfo.Companion.isValidIdentityPacket(np));
np.set("deviceName", "<><><><><><><><><>"); // Only invalid characters
assertFalse(DeviceInfo.Companion.isValidIdentityPacket(np));
np.set("deviceName", validName);
np.set("deviceId", " ");
assertFalse(DeviceInfo.Companion.isValidIdentityPacket(np));
}
@Test
public void testDeviceType() {
assertEquals(DeviceType.PHONE, DeviceType.fromString(DeviceType.PHONE.toString()));