forked from pool/bluez
Accepting request 1003685 from home:joeyli:branches:Base:System
For pushing bluez 5.65 to 15-SP5 (bluez-5.62), sync the patches and log (jsc#PED-1407) OBS-URL: https://build.opensuse.org/request/show/1003685 OBS-URL: https://build.opensuse.org/package/show/Base:System/bluez?expand=0&rev=332
This commit is contained in:
parent
2ed80b1192
commit
f8af464f41
@ -0,0 +1,35 @@
|
||||
From 4de2871675d3b039b5797e77cc1d6ce4070e86b2 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Tue, 16 Feb 2016 16:39:09 +0000
|
||||
Subject: [PATCH] bcm43xx: The UART speed must be reset after the firmware
|
||||
download
|
||||
|
||||
---
|
||||
tools/hciattach_bcm43xx.c | 6 ++----
|
||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
Index: bluez-5.60/tools/hciattach_bcm43xx.c
|
||||
===================================================================
|
||||
--- bluez-5.60.orig/tools/hciattach_bcm43xx.c
|
||||
+++ bluez-5.60/tools/hciattach_bcm43xx.c
|
||||
@@ -354,11 +354,8 @@ int bcm43xx_init(int fd, int def_speed,
|
||||
return -1;
|
||||
|
||||
if (bcm43xx_locate_patch(FIRMWARE_DIR, chip_name, fw_path)) {
|
||||
- fprintf(stderr, "Patch not found, continue anyway\n");
|
||||
+ fprintf(stderr, "Patch not found for %s, continue anyway\n", chip_name);
|
||||
} else {
|
||||
- if (bcm43xx_set_speed(fd, ti, speed))
|
||||
- return -1;
|
||||
-
|
||||
if (bcm43xx_load_firmware(fd, fw_path))
|
||||
return -1;
|
||||
|
||||
@@ -368,6 +365,7 @@ int bcm43xx_init(int fd, int def_speed,
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ sleep(1);
|
||||
if (bcm43xx_reset(fd))
|
||||
return -1;
|
||||
}
|
601
bluez-test-2to3.diff
Normal file
601
bluez-test-2to3.diff
Normal file
@ -0,0 +1,601 @@
|
||||
Index: bluez-5.65/test/bluezutils.py
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/bluezutils.py
|
||||
+++ bluez-5.65/test/bluezutils.py
|
||||
@@ -17,7 +17,7 @@ def find_adapter(pattern=None):
|
||||
|
||||
def find_adapter_in_objects(objects, pattern=None):
|
||||
bus = dbus.SystemBus()
|
||||
- for path, ifaces in objects.items():
|
||||
+ for path, ifaces in list(objects.items()):
|
||||
adapter = ifaces.get(ADAPTER_INTERFACE)
|
||||
if adapter is None:
|
||||
continue
|
||||
@@ -37,7 +37,7 @@ def find_device_in_objects(objects, devi
|
||||
if adapter_pattern:
|
||||
adapter = find_adapter_in_objects(objects, adapter_pattern)
|
||||
path_prefix = adapter.object_path
|
||||
- for path, ifaces in objects.items():
|
||||
+ for path, ifaces in list(objects.items()):
|
||||
device = ifaces.get(DEVICE_INTERFACE)
|
||||
if device is None:
|
||||
continue
|
||||
Index: bluez-5.65/test/example-advertisement
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/example-advertisement
|
||||
+++ bluez-5.65/test/example-advertisement
|
||||
@@ -164,7 +164,7 @@ def find_adapter(bus):
|
||||
DBUS_OM_IFACE)
|
||||
objects = remote_om.GetManagedObjects()
|
||||
|
||||
- for o, props in objects.items():
|
||||
+ for o, props in list(objects.items()):
|
||||
if LE_ADVERTISING_MANAGER_IFACE in props:
|
||||
return o
|
||||
|
||||
Index: bluez-5.65/test/example-gatt-client
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/example-gatt-client
|
||||
+++ bluez-5.65/test/example-gatt-client
|
||||
@@ -33,7 +33,7 @@ hr_ctrl_pt_chrc = None
|
||||
|
||||
|
||||
def generic_error_cb(error):
|
||||
- print('D-Bus call failed: ' + str(error))
|
||||
+ print(('D-Bus call failed: ' + str(error)))
|
||||
mainloop.quit()
|
||||
|
||||
|
||||
@@ -69,10 +69,10 @@ def sensor_contact_val_to_str(val):
|
||||
|
||||
def body_sensor_val_cb(value):
|
||||
if len(value) != 1:
|
||||
- print('Invalid body sensor location value: ' + repr(value))
|
||||
+ print(('Invalid body sensor location value: ' + repr(value)))
|
||||
return
|
||||
|
||||
- print('Body sensor location value: ' + body_sensor_val_to_str(value[0]))
|
||||
+ print(('Body sensor location value: ' + body_sensor_val_to_str(value[0])))
|
||||
|
||||
|
||||
def hr_msrmt_start_notify_cb():
|
||||
@@ -104,12 +104,12 @@ def hr_msrmt_changed_cb(iface, changed_p
|
||||
hr_msrmt = value[1] | (value[2] << 8)
|
||||
next_ind = 3
|
||||
|
||||
- print('\tHR: ' + str(int(hr_msrmt)))
|
||||
- print('\tSensor Contact status: ' +
|
||||
- sensor_contact_val_to_str(sc_status))
|
||||
+ print(('\tHR: ' + str(int(hr_msrmt))))
|
||||
+ print(('\tSensor Contact status: ' +
|
||||
+ sensor_contact_val_to_str(sc_status)))
|
||||
|
||||
if ee_status:
|
||||
- print('\tEnergy Expended: ' + str(int(value[next_ind])))
|
||||
+ print(('\tEnergy Expended: ' + str(int(value[next_ind]))))
|
||||
|
||||
|
||||
def start_client():
|
||||
@@ -147,7 +147,7 @@ def process_chrc(chrc_path):
|
||||
global hr_ctrl_pt_chrc
|
||||
hr_ctrl_pt_chrc = (chrc, chrc_props)
|
||||
else:
|
||||
- print('Unrecognized characteristic: ' + uuid)
|
||||
+ print(('Unrecognized characteristic: ' + uuid))
|
||||
|
||||
return True
|
||||
|
||||
@@ -162,7 +162,7 @@ def process_hr_service(service_path, chr
|
||||
if uuid != HR_SVC_UUID:
|
||||
return False
|
||||
|
||||
- print('Heart Rate Service found: ' + service_path)
|
||||
+ print(('Heart Rate Service found: ' + service_path))
|
||||
|
||||
# Process the characteristics.
|
||||
for chrc_path in chrc_paths:
|
||||
@@ -199,14 +199,14 @@ def main():
|
||||
chrcs = []
|
||||
|
||||
# List characteristics found
|
||||
- for path, interfaces in objects.items():
|
||||
- if GATT_CHRC_IFACE not in interfaces.keys():
|
||||
+ for path, interfaces in list(objects.items()):
|
||||
+ if GATT_CHRC_IFACE not in list(interfaces.keys()):
|
||||
continue
|
||||
chrcs.append(path)
|
||||
|
||||
# List sevices found
|
||||
- for path, interfaces in objects.items():
|
||||
- if GATT_SERVICE_IFACE not in interfaces.keys():
|
||||
+ for path, interfaces in list(objects.items()):
|
||||
+ if GATT_SERVICE_IFACE not in list(interfaces.keys()):
|
||||
continue
|
||||
|
||||
chrc_paths = [d for d in chrcs if d.startswith(path + "/")]
|
||||
Index: bluez-5.65/test/example-gatt-server
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/example-gatt-server
|
||||
+++ bluez-5.65/test/example-gatt-server
|
||||
@@ -293,7 +293,7 @@ class HeartRateMeasurementChrc(Character
|
||||
min(0xffff, self.service.energy_expended + 1)
|
||||
self.hr_ee_count += 1
|
||||
|
||||
- print('Updating value: ' + repr(value))
|
||||
+ print(('Updating value: ' + repr(value)))
|
||||
|
||||
self.PropertiesChanged(GATT_CHRC_IFACE, { 'Value': value }, [])
|
||||
|
||||
@@ -355,7 +355,7 @@ class HeartRateControlPointChrc(Characte
|
||||
raise InvalidValueLengthException()
|
||||
|
||||
byte = value[0]
|
||||
- print('Control Point value: ' + repr(byte))
|
||||
+ print(('Control Point value: ' + repr(byte)))
|
||||
|
||||
if byte != 1:
|
||||
raise FailedException("0x80")
|
||||
@@ -408,12 +408,12 @@ class BatteryLevelCharacteristic(Charact
|
||||
self.battery_lvl -= 2
|
||||
if self.battery_lvl < 0:
|
||||
self.battery_lvl = 0
|
||||
- print('Battery Level drained: ' + repr(self.battery_lvl))
|
||||
+ print(('Battery Level drained: ' + repr(self.battery_lvl)))
|
||||
self.notify_battery_level()
|
||||
return True
|
||||
|
||||
def ReadValue(self, options):
|
||||
- print('Battery Level read: ' + repr(self.battery_lvl))
|
||||
+ print(('Battery Level read: ' + repr(self.battery_lvl)))
|
||||
return [dbus.Byte(self.battery_lvl)]
|
||||
|
||||
def StartNotify(self):
|
||||
@@ -466,11 +466,11 @@ class TestCharacteristic(Characteristic)
|
||||
CharacteristicUserDescriptionDescriptor(bus, 1, self))
|
||||
|
||||
def ReadValue(self, options):
|
||||
- print('TestCharacteristic Read: ' + repr(self.value))
|
||||
+ print(('TestCharacteristic Read: ' + repr(self.value)))
|
||||
return self.value
|
||||
|
||||
def WriteValue(self, value, options):
|
||||
- print('TestCharacteristic Write: ' + repr(value))
|
||||
+ print(('TestCharacteristic Write: ' + repr(value)))
|
||||
self.value = value
|
||||
|
||||
|
||||
@@ -538,11 +538,11 @@ class TestEncryptCharacteristic(Characte
|
||||
CharacteristicUserDescriptionDescriptor(bus, 3, self))
|
||||
|
||||
def ReadValue(self, options):
|
||||
- print('TestEncryptCharacteristic Read: ' + repr(self.value))
|
||||
+ print(('TestEncryptCharacteristic Read: ' + repr(self.value)))
|
||||
return self.value
|
||||
|
||||
def WriteValue(self, value, options):
|
||||
- print('TestEncryptCharacteristic Write: ' + repr(value))
|
||||
+ print(('TestEncryptCharacteristic Write: ' + repr(value)))
|
||||
self.value = value
|
||||
|
||||
class TestEncryptDescriptor(Descriptor):
|
||||
@@ -584,11 +584,11 @@ class TestSecureCharacteristic(Character
|
||||
CharacteristicUserDescriptionDescriptor(bus, 3, self))
|
||||
|
||||
def ReadValue(self, options):
|
||||
- print('TestSecureCharacteristic Read: ' + repr(self.value))
|
||||
+ print(('TestSecureCharacteristic Read: ' + repr(self.value)))
|
||||
return self.value
|
||||
|
||||
def WriteValue(self, value, options):
|
||||
- print('TestSecureCharacteristic Write: ' + repr(value))
|
||||
+ print(('TestSecureCharacteristic Write: ' + repr(value)))
|
||||
self.value = value
|
||||
|
||||
|
||||
@@ -616,7 +616,7 @@ def register_app_cb():
|
||||
|
||||
|
||||
def register_app_error_cb(error):
|
||||
- print('Failed to register application: ' + str(error))
|
||||
+ print(('Failed to register application: ' + str(error)))
|
||||
mainloop.quit()
|
||||
|
||||
|
||||
@@ -625,8 +625,8 @@ def find_adapter(bus):
|
||||
DBUS_OM_IFACE)
|
||||
objects = remote_om.GetManagedObjects()
|
||||
|
||||
- for o, props in objects.items():
|
||||
- if GATT_MANAGER_IFACE in props.keys():
|
||||
+ for o, props in list(objects.items()):
|
||||
+ if GATT_MANAGER_IFACE in list(props.keys()):
|
||||
return o
|
||||
|
||||
return None
|
||||
Index: bluez-5.65/test/list-devices
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/list-devices
|
||||
+++ bluez-5.65/test/list-devices
|
||||
@@ -33,16 +33,16 @@ def extract_uuids(uuid_list):
|
||||
objects = manager.GetManagedObjects()
|
||||
|
||||
all_devices = (str(path) for path, interfaces in objects.items() if
|
||||
- "org.bluez.Device1" in interfaces.keys())
|
||||
+ "org.bluez.Device1" in list(interfaces.keys()))
|
||||
|
||||
for path, interfaces in objects.items():
|
||||
- if "org.bluez.Adapter1" not in interfaces.keys():
|
||||
+ if "org.bluez.Adapter1" not in list(interfaces.keys()):
|
||||
continue
|
||||
|
||||
print("[ " + path + " ]")
|
||||
|
||||
properties = interfaces["org.bluez.Adapter1"]
|
||||
- for key in properties.keys():
|
||||
+ for key in list(properties.keys()):
|
||||
value = properties[key]
|
||||
if (key == "UUIDs"):
|
||||
list = extract_uuids(value)
|
||||
@@ -58,7 +58,7 @@ for path, interfaces in objects.items():
|
||||
dev = objects[dev_path]
|
||||
properties = dev["org.bluez.Device1"]
|
||||
|
||||
- for key in properties.keys():
|
||||
+ for key in list(properties.keys()):
|
||||
value = properties[key]
|
||||
if (key == "UUIDs"):
|
||||
list = extract_uuids(value)
|
||||
Index: bluez-5.65/test/pbap-client
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/pbap-client
|
||||
+++ bluez-5.65/test/pbap-client
|
||||
@@ -135,11 +135,11 @@ if __name__ == '__main__':
|
||||
print(header)
|
||||
for line in lines:
|
||||
print(line),
|
||||
- print
|
||||
+ print()
|
||||
|
||||
def test_paths(paths):
|
||||
if len(paths) == 0:
|
||||
- print
|
||||
+ print()
|
||||
print("FINISHED")
|
||||
mainloop.quit()
|
||||
return
|
||||
Index: bluez-5.65/test/sap_client.py
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/sap_client.py
|
||||
+++ bluez-5.65/test/sap_client.py
|
||||
@@ -165,7 +165,7 @@ class SAPParam_ConnectionStatus(SAPParam
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None and self.value not in (0x00, 0x01, 0x02, 0x03, 0x04):
|
||||
- print "Warning. ConnectionStatus value in reserved range (0x%x)" % self.value
|
||||
+ print("Warning. ConnectionStatus value in reserved range (0x%x)" % self.value)
|
||||
|
||||
def deserialize(self, buf):
|
||||
ret = SAPParam.deserialize(self, buf)
|
||||
@@ -183,7 +183,7 @@ class SAPParam_ResultCode(SAPParam):
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None and self.value not in (0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07):
|
||||
- print "Warning. ResultCode value in reserved range (0x%x)" % self.value
|
||||
+ print("Warning. ResultCode value in reserved range (0x%x)" % self.value)
|
||||
|
||||
def deserialize(self, buf):
|
||||
ret = SAPParam.deserialize(self, buf)
|
||||
@@ -201,7 +201,7 @@ class SAPParam_DisconnectionType(SAPPara
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None and self.value not in (0x00, 0x01):
|
||||
- print "Warning. DisconnectionType value in reserved range (0x%x)" % self.value
|
||||
+ print("Warning. DisconnectionType value in reserved range (0x%x)" % self.value)
|
||||
|
||||
def deserialize(self, buf):
|
||||
ret = SAPParam.deserialize(self, buf)
|
||||
@@ -227,7 +227,7 @@ class SAPParam_StatusChange(SAPParam):
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None and self.value not in (0x00, 0x01, 0x02, 0x03, 0x04, 0x05):
|
||||
- print "Warning. StatusChange value in reserved range (0x%x)" % self.value
|
||||
+ print("Warning. StatusChange value in reserved range (0x%x)" % self.value)
|
||||
|
||||
def deserialize(self, buf):
|
||||
ret = SAPParam.deserialize(self, buf)
|
||||
@@ -245,7 +245,7 @@ class SAPParam_TransportProtocol(SAPPara
|
||||
|
||||
def __validate(self):
|
||||
if self.value is not None and self.value not in (0x00, 0x01):
|
||||
- print "Warning. TransportProtoco value in reserved range (0x%x)" % self.value
|
||||
+ print("Warning. TransportProtoco value in reserved range (0x%x)" % self.value)
|
||||
|
||||
def deserialize(self, buf):
|
||||
ret = SAPParam.deserialize(self, buf)
|
||||
@@ -728,7 +728,7 @@ class SAPClient:
|
||||
self.port = first_match["port"]
|
||||
self.host = first_match["host"]
|
||||
|
||||
- print "SAP Service found on %s(%s)" % first_match["name"] % self.host
|
||||
+ print("SAP Service found on %s(%s)" % first_match["name"] % self.host)
|
||||
|
||||
def __connectRFCOMM(self):
|
||||
self.sock=BluetoothSocket( RFCOMM )
|
||||
@@ -739,19 +739,19 @@ class SAPClient:
|
||||
def __sendMsg(self, msg):
|
||||
if isinstance(msg, SAPMessage):
|
||||
s = msg.serialize()
|
||||
- print "\tTX: " + msg.getContent()
|
||||
+ print("\tTX: " + msg.getContent())
|
||||
return self.sock.send(s.tostring())
|
||||
|
||||
def __rcvMsg(self, msg):
|
||||
if isinstance(msg, SAPMessage):
|
||||
- print "\tRX Wait: %s(id = 0x%.2x)" % (msg.name, msg.id)
|
||||
+ print("\tRX Wait: %s(id = 0x%.2x)" % (msg.name, msg.id))
|
||||
data = self.sock.recv(self.bufsize)
|
||||
if data:
|
||||
if msg.deserialize(array('B',data)):
|
||||
- print "\tRX: len(%d) %s" % (len(data), msg.getContent())
|
||||
+ print("\tRX: len(%d) %s" % (len(data), msg.getContent()))
|
||||
return msg
|
||||
else:
|
||||
- print "msg: %s" % array('B',data)
|
||||
+ print("msg: %s" % array('B',data))
|
||||
raise BluetoothError ("Message deserialization failed.")
|
||||
else:
|
||||
raise BluetoothError ("Timeout. No data received.")
|
||||
@@ -797,8 +797,8 @@ class SAPClient:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_disconnectByClient(self, timeout=0):
|
||||
@@ -808,8 +808,8 @@ class SAPClient:
|
||||
time.sleep(timeout) # let srv to close rfcomm
|
||||
self.__disconnectRFCOMM()
|
||||
return True
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_disconnectByServer(self, timeout=0):
|
||||
@@ -823,8 +823,8 @@ class SAPClient:
|
||||
|
||||
return self.proc_disconnectByClient(timeout)
|
||||
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_transferAPDU(self, apdu = "Sample APDU command"):
|
||||
@@ -832,8 +832,8 @@ class SAPClient:
|
||||
self.__sendMsg(SAPMessage_TRANSFER_APDU_REQ(apdu))
|
||||
params = self.__rcvMsg(SAPMessage_TRANSFER_APDU_RESP()).getParams()
|
||||
return True
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_transferATR(self):
|
||||
@@ -841,8 +841,8 @@ class SAPClient:
|
||||
self.__sendMsg(SAPMessage_TRANSFER_ATR_REQ())
|
||||
params = self.__rcvMsg(SAPMessage_TRANSFER_ATR_RESP()).getParams()
|
||||
return True
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_powerSimOff(self):
|
||||
@@ -850,8 +850,8 @@ class SAPClient:
|
||||
self.__sendMsg(SAPMessage_POWER_SIM_OFF_REQ())
|
||||
params = self.__rcvMsg(SAPMessage_POWER_SIM_OFF_RESP()).getParams()
|
||||
return True
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_powerSimOn(self):
|
||||
@@ -862,8 +862,8 @@ class SAPClient:
|
||||
return self.proc_transferATR()
|
||||
|
||||
return True
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_resetSim(self):
|
||||
@@ -874,23 +874,23 @@ class SAPClient:
|
||||
return self.proc_transferATR()
|
||||
|
||||
return True
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_reportStatus(self):
|
||||
try:
|
||||
params = self.__rcvMsg(SAPMessage_STATUS_IND()).getParams()
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_transferCardReaderStatus(self):
|
||||
try:
|
||||
self.__sendMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_REQ())
|
||||
params = self.__rcvMsg(SAPMessage_TRANSFER_CARD_READER_STATUS_RESP()).getParams()
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_errorResponse(self):
|
||||
@@ -899,8 +899,8 @@ class SAPClient:
|
||||
self.__sendMsg(SAPMessage_CONNECT_REQ())
|
||||
|
||||
params = self.__rcvMsg(SAPMessage_ERROR_RESP()).getParams()
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
def proc_setTransportProtocol(self, protocol = 0):
|
||||
@@ -922,8 +922,8 @@ class SAPClient:
|
||||
else:
|
||||
return False
|
||||
|
||||
- except BluetoothError , e:
|
||||
- print "Error. " +str(e)
|
||||
+ except BluetoothError as e:
|
||||
+ print("Error. " +str(e))
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
Index: bluez-5.65/test/simple-agent
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/simple-agent
|
||||
+++ bluez-5.65/test/simple-agent
|
||||
@@ -24,9 +24,9 @@ dev_path = None
|
||||
|
||||
def ask(prompt):
|
||||
try:
|
||||
- return raw_input(prompt)
|
||||
- except:
|
||||
return input(prompt)
|
||||
+ except:
|
||||
+ return eval(input(prompt))
|
||||
|
||||
def set_trusted(path):
|
||||
props = dbus.Interface(bus.get_object("org.bluez", path),
|
||||
Index: bluez-5.65/test/simple-player
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/simple-player
|
||||
+++ bluez-5.65/test/simple-player
|
||||
@@ -119,7 +119,7 @@ class InputHandler:
|
||||
return True
|
||||
|
||||
try:
|
||||
- exec "self.player.%s" % s
|
||||
+ exec("self.player.%s" % s)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
pass
|
||||
Index: bluez-5.65/test/test-adapter
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/test-adapter
|
||||
+++ bluez-5.65/test/test-adapter
|
||||
@@ -69,7 +69,7 @@ if (args[0] == "list"):
|
||||
|
||||
props = interfaces["org.bluez.Adapter1"]
|
||||
|
||||
- for (key, value) in props.items():
|
||||
+ for (key, value) in list(props.items()):
|
||||
if (key == "Class"):
|
||||
print(" %s = 0x%06x" % (key, value))
|
||||
else:
|
||||
Index: bluez-5.65/test/test-discovery
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/test-discovery
|
||||
+++ bluez-5.65/test/test-discovery
|
||||
@@ -39,10 +39,10 @@ def print_compact(address, properties):
|
||||
def print_normal(address, properties):
|
||||
print("[ " + address + " ]")
|
||||
|
||||
- for key in properties.keys():
|
||||
+ for key in list(properties.keys()):
|
||||
value = properties[key]
|
||||
if type(value) is dbus.String:
|
||||
- value = unicode(value).encode('ascii', 'replace')
|
||||
+ value = str(value).encode('ascii', 'replace')
|
||||
if (key == "Class"):
|
||||
print(" %s = 0x%06x" % (key, value))
|
||||
else:
|
||||
@@ -71,7 +71,7 @@ def interfaces_added(path, interfaces):
|
||||
|
||||
if compact and skip_dev(dev, properties):
|
||||
return
|
||||
- devices[path] = dict(devices[path].items() + properties.items())
|
||||
+ devices[path] = dict(list(devices[path].items()) + list(properties.items()))
|
||||
else:
|
||||
devices[path] = properties
|
||||
|
||||
@@ -94,7 +94,7 @@ def properties_changed(interface, change
|
||||
|
||||
if compact and skip_dev(dev, changed):
|
||||
return
|
||||
- devices[path] = dict(devices[path].items() + changed.items())
|
||||
+ devices[path] = dict(list(devices[path].items()) + list(changed.items()))
|
||||
else:
|
||||
devices[path] = changed
|
||||
|
||||
Index: bluez-5.65/test/test-hfp
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/test-hfp
|
||||
+++ bluez-5.65/test/test-hfp
|
||||
@@ -186,7 +186,7 @@ class HfpProfile(dbus.service.Object):
|
||||
version = 0x0105
|
||||
features = 0
|
||||
print("NewConnection(%s, %d)" % (path, fd))
|
||||
- for key in properties.keys():
|
||||
+ for key in list(properties.keys()):
|
||||
if key == "Version":
|
||||
version = properties[key]
|
||||
elif key == "Features":
|
||||
Index: bluez-5.65/test/test-profile
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/test-profile
|
||||
+++ bluez-5.65/test/test-profile
|
||||
@@ -34,7 +34,7 @@ class Profile(dbus.service.Object):
|
||||
def NewConnection(self, path, fd, properties):
|
||||
self.fd = fd.take()
|
||||
print("NewConnection(%s, %d)" % (path, self.fd))
|
||||
- for key in properties.keys():
|
||||
+ for key in list(properties.keys()):
|
||||
if key == "Version" or key == "Features":
|
||||
print(" %s = 0x%04x" % (key, properties[key]))
|
||||
else:
|
||||
Index: bluez-5.65/test/map-client
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/test/map-client
|
||||
+++ bluez-5.65/test/map-client
|
||||
@@ -27,7 +27,7 @@ def unwrap(x):
|
||||
printed. Taken from d-feet """
|
||||
|
||||
if isinstance(x, list):
|
||||
- return map(unwrap, x)
|
||||
+ return list(map(unwrap, x))
|
||||
|
||||
if isinstance(x, tuple):
|
||||
return tuple(map(unwrap, x))
|
||||
@@ -35,7 +35,7 @@ def unwrap(x):
|
||||
if isinstance(x, dict):
|
||||
return dict([(unwrap(k), unwrap(v)) for k, v in x.items()])
|
||||
|
||||
- for t in [unicode, str, long, int, float, bool]:
|
||||
+ for t in [str, str, int, int, float, bool]:
|
||||
if isinstance(x, t):
|
||||
return t(x)
|
||||
|
@ -1,3 +1,38 @@
|
||||
-------------------------------------------------------------------
|
||||
Wed Sep 14 07:56:19 UTC 2022 - Joey Lee <jlee@suse.com>
|
||||
|
||||
- For pushing bluez 5.65 to 15-SP5 (bluez-5.62), sync the patches and
|
||||
log: (jsc#PED-1407)
|
||||
- hcidump-fixed-hci-frame-dump-stack-buffer-overflow.patch patch
|
||||
be merged to 5.51 mainline. So 5.65 bluez already includes it.
|
||||
- Add the following patches from the bluez-5.62 of 15-SP5:
|
||||
- disable_some_obex_tests.patch
|
||||
- disable tests for bypass boo#1078285
|
||||
- hcidump-Add-assoc-dump-function-assoc-date-length-ch.patch
|
||||
- bsc#1013708 CVE-2016-9797
|
||||
- Al Cho has sent it to upstream but it not be merged:
|
||||
https://lore.kernel.org/all/20181031081508.25927-1-acho@suse.com/T/
|
||||
- hcidump-Fix-memory-leak-with-malformed-packet.patch
|
||||
- bsc#1015171 CVE-2016-9917
|
||||
- Al Cho has sent it to upstream but it not be merged:
|
||||
https://www.spinics.net/lists/linux-bluetooth/msg79852.html
|
||||
- hcidump-Fixed-malformed-segment-frame-length.patch
|
||||
- bsc#1013712 CVE-2016-9798
|
||||
- Did not send to upstream.
|
||||
- 0001-rpi3-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch
|
||||
- Move 43xx firmware path for RPi3 bluetooth support bsc#1140688 bsc#995059 bsc#1094902
|
||||
- From https://www.yoctoproject.org/pipermail/yocto/2016-April/029424.html
|
||||
- Respin the following patches
|
||||
- bluez-test-2to3.diff
|
||||
- Removed some parts of patch because those codes be included
|
||||
in a1939bd51e0faba9a8550eea2590d99cb63a33c1 since 5.65.
|
||||
- The following patches are the same between SLE15-SP5 with openSUSE TW:
|
||||
- bluez-5.45-disable-broken-tests.diff in 15-SP5 matchs with
|
||||
bluez-disable-broken-tests.diff in openSUSE TW.
|
||||
- 0002-rpi3-Move-the-43xx-firmware-into-lib-firmware.patch in 15-SP5
|
||||
matchs with RPi-Move-the-43xx-firmware-into-lib-firmware.patch in
|
||||
openSUSE TW.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Aug 17 20:26:50 UTC 2022 - Dirk Müller <dmueller@suse.com>
|
||||
|
||||
|
12
bluez.spec
12
bluez.spec
@ -55,11 +55,23 @@ Patch10: RPi-Move-the-43xx-firmware-into-lib-firmware.patch
|
||||
#
|
||||
# PATCH-FIX-UPSTREAM 0001-obex-Use-GLib-helper-function-to-manipulate-paths.patch -- obex: Use GLib helper function to manipulate paths
|
||||
Patch11: https://src.fedoraproject.org/rpms/bluez/raw/rawhide/f/0001-obex-Use-GLib-helper-function-to-manipulate-paths.patch
|
||||
# disable tests for bypass boo#1078285
|
||||
Patch12: disable_some_obex_tests.patch
|
||||
# get rid of python2. WARNING: this is autogenerated by 2to3 and might not work
|
||||
Patch13: bluez-test-2to3.diff
|
||||
# bsc#1013708 CVE-2016-9797
|
||||
Patch14: hcidump-Add-assoc-dump-function-assoc-date-length-ch.patch
|
||||
# bsc#1015171 CVE-2016-9917
|
||||
Patch15: hcidump-Fix-memory-leak-with-malformed-packet.patch
|
||||
# bsc#1013712 CVE-2016-9798
|
||||
Patch16: hcidump-Fixed-malformed-segment-frame-length.patch
|
||||
# Upstream suggests to use btmon instead of hcidump and does not want those patches
|
||||
# => PATCH-FIX-OPENSUSE for those two :-)
|
||||
# fix some memory leak with malformed packet (reported upstream but not yet fixed)
|
||||
Patch101: CVE-2016-9800-tool-hcidump-Fix-memory-leak-with-malformed-packet.patch
|
||||
Patch102: CVE-2016-9804-tool-hcidump-Fix-memory-leak-with-malformed-packet.patch
|
||||
# Move 43xx firmware path for RPi3 bluetooth support bsc#1140688 bsc#995059 bsc#1094902
|
||||
Patch201: 0001-rpi3-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch
|
||||
# mesh-cfgtest only compiles with gcc8 or newer, Leap 15 has gcc7.5.0 as default
|
||||
%if 0%{?suse_version} < 1550
|
||||
BuildRequires: gcc8
|
||||
|
28
disable_some_obex_tests.patch
Normal file
28
disable_some_obex_tests.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From: Michel Normand <normand@linux.vnet.ibm.com>
|
||||
Subject: disable some obex tests
|
||||
Date: Tue, 30 Jan 2018 17:01:45 +0100
|
||||
|
||||
disable some obex tests as transient failures
|
||||
reported by bug
|
||||
https://bugzilla.suse.com/show_bug.cgi?id=1078285
|
||||
|
||||
Signed-off-by: Michel Normand <normand@linux.vnet.ibm.com>
|
||||
---
|
||||
Makefile.am | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
Index: bluez-5.65/Makefile.am
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/Makefile.am
|
||||
+++ bluez-5.65/Makefile.am
|
||||
@@ -502,8 +502,8 @@ unit_test_gdbus_client_LDADD = gdbus/lib
|
||||
src/libshared-glib.la $(GLIB_LIBS) $(DBUS_LIBS)
|
||||
|
||||
if OBEX
|
||||
-unit_tests += unit/test-gobex-header unit/test-gobex-packet unit/test-gobex \
|
||||
- unit/test-gobex-transfer unit/test-gobex-apparam
|
||||
+unit_tests += unit/test-gobex-header unit/test-gobex-packet \
|
||||
+ unit/test-gobex-apparam
|
||||
|
||||
unit_test_gobex_SOURCES = $(gobex_sources) unit/util.c unit/util.h \
|
||||
unit/test-gobex.c
|
159
hcidump-Add-assoc-dump-function-assoc-date-length-ch.patch
Normal file
159
hcidump-Add-assoc-dump-function-assoc-date-length-ch.patch
Normal file
@ -0,0 +1,159 @@
|
||||
From 08a69d36726b6345df6e64892cadd5ab5d5ca2a6 Mon Sep 17 00:00:00 2001
|
||||
From: "Cho, Yu-Chen" <acho@suse.com>
|
||||
Date: Tue, 19 Mar 2019 15:54:09 +0800
|
||||
Subject: [PATCH BlueZ] hcidump: Add assoc dump function assoc date length check
|
||||
|
||||
amp_assoc_dump() didn't check the length of amp assoc struct.
|
||||
If there is wrong length size of assoc date, amp_assoc_dump() and
|
||||
amp_dump_chanlist() will read over the size(heap-buffer-overflow).
|
||||
|
||||
use t_len to save the length avoid use the wrong size of date.
|
||||
---
|
||||
tools/parser/amp.c | 35 +++++++++++++++++++++++++++--------
|
||||
tools/parser/hci.c | 4 ++--
|
||||
tools/parser/l2cap.c | 6 ++++--
|
||||
tools/parser/parser.h | 2 +-
|
||||
4 files changed, 34 insertions(+), 13 deletions(-)
|
||||
|
||||
Index: bluez-5.65/tools/parser/amp.c
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/tools/parser/amp.c
|
||||
+++ bluez-5.65/tools/parser/amp.c
|
||||
@@ -15,7 +15,8 @@
|
||||
#include "parser.h"
|
||||
#include "lib/amp.h"
|
||||
|
||||
-static void amp_dump_chanlist(int level, struct amp_tlv *tlv, char *prefix)
|
||||
+static void amp_dump_chanlist(int level, struct amp_tlv *tlv,
|
||||
+ uint16_t t_len, char *prefix)
|
||||
{
|
||||
struct amp_chan_list *chan_list = (void *) tlv->val;
|
||||
struct amp_country_triplet *triplet;
|
||||
@@ -25,6 +26,12 @@ static void amp_dump_chanlist(int level,
|
||||
|
||||
printf("%s (number of triplets %d)\n", prefix, num);
|
||||
|
||||
+ if (btohs(tlv->len) > t_len) {
|
||||
+ p_indent(level+1, 0);
|
||||
+ printf("Wrong number of triplets\n");
|
||||
+ num = (t_len - sizeof(*chan_list)) / sizeof(*triplet);
|
||||
+ }
|
||||
+
|
||||
p_indent(level+2, 0);
|
||||
|
||||
printf("Country code: %c%c%c\n", chan_list->country_code[0],
|
||||
@@ -55,7 +62,7 @@ static void amp_dump_chanlist(int level,
|
||||
}
|
||||
}
|
||||
|
||||
-void amp_assoc_dump(int level, uint8_t *assoc, uint16_t len)
|
||||
+void amp_assoc_dump(int level, uint8_t *assoc, uint16_t len, uint16_t t_len)
|
||||
{
|
||||
struct amp_tlv *tlv = (void *) assoc;
|
||||
|
||||
@@ -63,6 +70,14 @@ void amp_assoc_dump(int level, uint8_t *
|
||||
printf("Assoc data [len %d]:\n", len);
|
||||
|
||||
while (len > sizeof(*tlv)) {
|
||||
+ if (btohs(tlv->len) > (t_len - sizeof(struct amp_tlv))) {
|
||||
+ p_indent(level+1, 0);
|
||||
+ printf("Assoc data get error size\n");
|
||||
+ t_len -= sizeof(struct amp_tlv);
|
||||
+ } else {
|
||||
+ t_len -= sizeof(struct amp_tlv) + btohs(tlv->len);
|
||||
+ }
|
||||
+
|
||||
uint16_t tlvlen = btohs(tlv->len);
|
||||
struct amp_pal_ver *ver;
|
||||
|
||||
@@ -78,11 +93,13 @@ void amp_assoc_dump(int level, uint8_t *
|
||||
break;
|
||||
|
||||
case A2MP_PREF_CHANLIST_TYPE:
|
||||
- amp_dump_chanlist(level, tlv, "Preferred Chan List");
|
||||
+ amp_dump_chanlist(level, tlv,
|
||||
+ t_len, "Preferred Chan List");
|
||||
break;
|
||||
|
||||
case A2MP_CONNECTED_CHAN:
|
||||
- amp_dump_chanlist(level, tlv, "Connected Chan List");
|
||||
+ amp_dump_chanlist(level, tlv,
|
||||
+ t_len, "Connected Chan List");
|
||||
break;
|
||||
|
||||
case A2MP_PAL_CAP_TYPE:
|
||||
@@ -106,9 +123,11 @@ void amp_assoc_dump(int level, uint8_t *
|
||||
printf("Unrecognized type %d\n", tlv->type);
|
||||
break;
|
||||
}
|
||||
-
|
||||
- len -= tlvlen + sizeof(*tlv);
|
||||
- assoc += tlvlen + sizeof(*tlv);
|
||||
- tlv = (struct amp_tlv *) assoc;
|
||||
+ if (btohs(tlv->len) <= t_len) {
|
||||
+ len -= tlvlen + sizeof(*tlv);
|
||||
+ assoc += tlvlen + sizeof(*tlv);
|
||||
+ tlv = (struct amp_tlv *) assoc;
|
||||
+ } else
|
||||
+ len = 0;
|
||||
}
|
||||
}
|
||||
Index: bluez-5.65/tools/parser/hci.c
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/tools/parser/hci.c
|
||||
+++ bluez-5.65/tools/parser/hci.c
|
||||
@@ -1667,7 +1667,7 @@ static inline void write_remote_amp_asso
|
||||
printf("handle 0x%2.2x len_so_far %d remaining_len %d\n", cp->handle,
|
||||
cp->length_so_far, cp->remaining_length);
|
||||
|
||||
- amp_assoc_dump(level + 1, cp->fragment, frm->len - 5);
|
||||
+ amp_assoc_dump(level + 1, cp->fragment, frm->len - 5, frm->len - 5);
|
||||
}
|
||||
|
||||
static inline void command_dump(int level, struct frame *frm)
|
||||
@@ -2650,7 +2650,7 @@ static inline void read_local_amp_assoc_
|
||||
p_indent(level, frm);
|
||||
printf("Error: %s\n", status2str(rp->status));
|
||||
} else {
|
||||
- amp_assoc_dump(level + 1, rp->fragment, len);
|
||||
+ amp_assoc_dump(level + 1, rp->fragment, len, frm->len - 4);
|
||||
}
|
||||
}
|
||||
|
||||
Index: bluez-5.65/tools/parser/l2cap.c
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/tools/parser/l2cap.c
|
||||
+++ bluez-5.65/tools/parser/l2cap.c
|
||||
@@ -1159,7 +1159,8 @@ static inline void a2mp_assoc_rsp(int le
|
||||
|
||||
printf("Get AMP Assoc rsp: id %d status (%d) %s\n",
|
||||
h->id, h->status, a2mpstatus2str(h->status));
|
||||
- amp_assoc_dump(level + 1, h->assoc_data, len - sizeof(*h));
|
||||
+ amp_assoc_dump(level + 1, h->assoc_data,
|
||||
+ len - sizeof(*h), frm->len - sizeof(*h));
|
||||
}
|
||||
|
||||
static inline void a2mp_create_req(int level, struct frame *frm, uint16_t len)
|
||||
@@ -1168,7 +1169,8 @@ static inline void a2mp_create_req(int l
|
||||
|
||||
printf("Create Physical Link req: local id %d remote id %d\n",
|
||||
h->local_id, h->remote_id);
|
||||
- amp_assoc_dump(level + 1, h->assoc_data, len - sizeof(*h));
|
||||
+ amp_assoc_dump(level + 1, h->assoc_data,
|
||||
+ len - sizeof(*h), frm->len - sizeof(*h));
|
||||
}
|
||||
|
||||
static inline void a2mp_create_rsp(int level, struct frame *frm)
|
||||
Index: bluez-5.65/tools/parser/parser.h
|
||||
===================================================================
|
||||
--- bluez-5.65.orig/tools/parser/parser.h
|
||||
+++ bluez-5.65/tools/parser/parser.h
|
||||
@@ -236,7 +236,7 @@ void ericsson_dump(int level, struct fra
|
||||
void csr_dump(int level, struct frame *frm);
|
||||
void bpa_dump(int level, struct frame *frm);
|
||||
|
||||
-void amp_assoc_dump(int level, uint8_t *assoc, uint16_t len);
|
||||
+void amp_assoc_dump(int level, uint8_t *assoc, uint16_t len, uint16_t t_len);
|
||||
|
||||
static inline void parse(struct frame *frm)
|
||||
{
|
33
hcidump-Fix-memory-leak-with-malformed-packet.patch
Normal file
33
hcidump-Fix-memory-leak-with-malformed-packet.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From 98bee47cca1b8a6b17bb0178f951fe7902abc2f0 Mon Sep 17 00:00:00 2001
|
||||
From: "Cho, Yu-Chen" <acho@suse.com>
|
||||
Date: Wed, 24 Apr 2019 16:10:56 +0800
|
||||
Subject: [PATCH BlueZ] tool/hcidump: Fix memory leak with malformed packet
|
||||
|
||||
Do not allow to read more than allocated data buffer size.
|
||||
Because of the buffer is malloc(HCI_MAX_FRAME_SIZE),
|
||||
so there is heap buffer overflow if read the size more than
|
||||
HCI_MAX_FRAME_SIZE and fd size is larger than HCI_MAX_FRAME_SIZE.
|
||||
---
|
||||
tools/hcidump.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
Index: bluez-5.60/tools/hcidump.c
|
||||
===================================================================
|
||||
--- bluez-5.60.orig/tools/hcidump.c
|
||||
+++ bluez-5.60/tools/hcidump.c
|
||||
@@ -92,6 +92,15 @@ struct pktlog_hdr {
|
||||
static inline int read_n(int fd, char *buf, int len)
|
||||
{
|
||||
int t = 0, w;
|
||||
+ off_t fsize, currentpos, startpos;
|
||||
+
|
||||
+ currentpos = lseek(fd, 0, SEEK_CUR);
|
||||
+ fsize = lseek(fd, 0, SEEK_END);
|
||||
+ lseek(fd, currentpos, SEEK_SET);
|
||||
+ fsize -= currentpos;
|
||||
+
|
||||
+ if (fsize > HCI_MAX_FRAME_SIZE && len > HCI_MAX_FRAME_SIZE)
|
||||
+ return -1;
|
||||
|
||||
while (len > 0) {
|
||||
if ((w = read(fd, buf, len)) < 0) {
|
26
hcidump-Fixed-malformed-segment-frame-length.patch
Normal file
26
hcidump-Fixed-malformed-segment-frame-length.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From da04ba5e6b3f151c1644a17ac0fa2317ebc81edd Mon Sep 17 00:00:00 2001
|
||||
From: "Cho, Yu-Chen" <acho@suse.com>
|
||||
Date: Tue, 15 Oct 2019 15:45:43 +0800
|
||||
Subject: [PATCH] hcidump: Fixed malformed segment frame length
|
||||
|
||||
Ensure the L2CAP SDUs whose length field match the actual frame length.
|
||||
---
|
||||
tools/parser/l2cap.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
Index: bluez-5.60/tools/parser/l2cap.c
|
||||
===================================================================
|
||||
--- bluez-5.60.orig/tools/parser/l2cap.c
|
||||
+++ bluez-5.60/tools/parser/l2cap.c
|
||||
@@ -759,6 +759,11 @@ static inline void conf_rsp(int level, l
|
||||
scid, btohs(h->flags), result, clen);
|
||||
|
||||
if (clen > 0) {
|
||||
+ if (clen != (btohs(frm->len) - L2CAP_CONF_RSP_SIZE)) {
|
||||
+ fprintf(stderr, "Not match the actual frame length\n");
|
||||
+ clen = btohs(frm->len) - L2CAP_CONF_RSP_SIZE;
|
||||
+ }
|
||||
+
|
||||
if (result) {
|
||||
p_indent(level + 1, frm);
|
||||
printf("%s\n", confresult2str(result));
|
Loading…
Reference in New Issue
Block a user