diff --git a/.drone.yml b/.drone.yml index 5c97b452b..e4165d097 100644 --- a/.drone.yml +++ b/.drone.yml @@ -79,7 +79,7 @@ services: - su www-data -c "php /var/www/html/occ app:enable activity" - su www-data -c "git clone -b main https://github.com/nextcloud/text.git /var/www/html/apps/text/" - su www-data -c "php /var/www/html/occ app:enable text" - - su www-data -c "git clone -b artonge/feat/allow_metadata_update_for_subfolders https://github.com/nextcloud/end_to_end_encryption/ /var/www/html/apps/end_to_end_encryption/" + - su www-data -c "git clone -b master https://github.com/nextcloud/end_to_end_encryption/ /var/www/html/apps/end_to_end_encryption/" - su www-data -c "php /var/www/html/occ app:enable end_to_end_encryption" - su www-data -c "git clone -b master https://github.com/nextcloud/password_policy/ /var/www/html/apps/password_policy/" - su www-data -c "php /var/www/html/occ app:enable password_policy" @@ -213,6 +213,6 @@ trigger: - pull_request --- kind: signature -hmac: 56749c47df149cc2d3c06343c609210a310e27635ea6ccb040890ab0afbce79d +hmac: 6d69c7c3739747691580d04a781eb67cf95d2f33f8149d5ebd2cbcc30611b4f0 ... diff --git a/library/src/androidTest/java/com/nextcloud/extensions/DavPropertyProcessorTest.kt b/library/src/androidTest/java/com/nextcloud/extensions/DavPropertyProcessorTest.kt new file mode 100644 index 000000000..15da36748 --- /dev/null +++ b/library/src/androidTest/java/com/nextcloud/extensions/DavPropertyProcessorTest.kt @@ -0,0 +1,98 @@ +package com.nextcloud.extensions + +import com.google.gson.Gson +import org.apache.jackrabbit.webdav.property.DavProperty +import org.apache.jackrabbit.webdav.property.DavPropertyName +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.w3c.dom.Document +import org.w3c.dom.Element + +class DavPropertyProcessorTest { + data class TestData(val name: String, val age: Int) + + private val gson = Gson() + + @Test + fun testFromDavPropertyWhenGivenValidDataShouldReturnExpectedData() { + val result = + gson.fromDavProperty( + object : DavProperty { + override fun toXml(document: Document?): Element { + return createElement("TestData", value) + } + + override fun getName(): DavPropertyName { + return DavPropertyName.DISPLAYNAME + } + + override fun getValue(): String { + return "{\"name\":\"John\",\"age\":55}" + } + + override fun isInvisibleInAllprop(): Boolean { + return true + } + } + ) + val expected = TestData("John", 55) + assertEquals(expected, result) + } + + @Test + fun testFromDavPropertyWhenGivenValidDataAndExpectDifferentTypeShouldReturnNull() { + val result = + gson.fromDavProperty>( + object : DavProperty { + override fun toXml(document: Document?): Element { + return createElement("TestData", value) + } + + override fun getName(): DavPropertyName { + return DavPropertyName.DISPLAYNAME + } + + override fun getValue(): String { + return "{\"name\":\"John\",\"age\":55}" + } + + override fun isInvisibleInAllprop(): Boolean { + return true + } + } + ) + assertNull(result) + } + + @Test + fun testFromDavPropertyWhenGivenInvalidDataShouldReturnNull() { + val result = + gson.fromDavProperty( + object : DavProperty { + override fun toXml(document: Document?): Element { + return createElement("TestData", "") + } + + override fun getName(): DavPropertyName { + return DavPropertyName.DISPLAYNAME + } + + override fun getValue(): String? { + return null + } + + override fun isInvisibleInAllprop(): Boolean { + return true + } + } + ) + assertNull(result) + } + + @Test + fun testFromDavPropertyWhenGivenNullDataShouldReturnNull() { + val result = gson.fromDavProperty(null) + assertNull(result) + } +} diff --git a/library/src/androidTest/java/com/nextcloud/extensions/ElementCreator.kt b/library/src/androidTest/java/com/nextcloud/extensions/ElementCreator.kt new file mode 100644 index 000000000..137c4f8f1 --- /dev/null +++ b/library/src/androidTest/java/com/nextcloud/extensions/ElementCreator.kt @@ -0,0 +1,21 @@ +package com.nextcloud.extensions + +import org.w3c.dom.Element +import javax.xml.parsers.DocumentBuilderFactory + +fun createElement( + xml: String, + value: String +): Element { + val builder = + DocumentBuilderFactory.newInstance().run { + newDocumentBuilder() + } + val document = builder.newDocument() + val element = + document.createElement(xml).apply { + textContent = value + } + document.appendChild(element) + return element +} diff --git a/library/src/androidTest/java/com/nextcloud/extensions/XmlDataProcessorTest.kt b/library/src/androidTest/java/com/nextcloud/extensions/XmlDataProcessorTest.kt new file mode 100644 index 000000000..d2ff8127c --- /dev/null +++ b/library/src/androidTest/java/com/nextcloud/extensions/XmlDataProcessorTest.kt @@ -0,0 +1,67 @@ +package com.nextcloud.extensions + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.w3c.dom.Element + +class XmlDataProcessorTest { + @Test + fun testProcessXmlDataWhenGivenEmptyArrayListShouldReturnNull() { + val tag = "width" + val xmlData: ArrayList = arrayListOf() + val result = xmlData.processXmlData(tag) + assertNull(result) + } + + @Test + fun testProcessXmlDataWhenGivenWrongArrayListShouldReturnNull() { + val tag = "width" + val xmlData: ArrayList = arrayListOf("element") + val result = xmlData.processXmlData(tag) + assertNull(result) + } + + @Test + fun testProcessXmlDataWhenGivenValidDataShouldReturnFloat() { + val tag = "width" + val element = createElement(tag, "220") + val xmlData: ArrayList = arrayListOf(element) + val result = xmlData.processXmlData(tag) + assertEquals(220f, result) + } + + @Test + fun testProcessXmlDataWhenGivenValidDataAndWrongTagShouldReturnNull() { + val element = createElement("width", "220") + val xmlData: ArrayList = arrayListOf(element) + val result = xmlData.processXmlData("latitude") + assertNull(result) + } + + @Test + fun testProcessXmlDataWhenGivenNullElementShouldReturnNull() { + val tag = "width" + val xmlData: ArrayList = arrayListOf(null) + val result = xmlData.processXmlData(tag) + assertNull(result) + } + + @Test + fun testProcessXmlDataWhenGivenValidDataShouldReturnDouble() { + val tag = "latitude" + val element = createElement(tag, "12.4231") + val xmlData: ArrayList = arrayListOf(element) + val result = xmlData.processXmlData(tag) + assertEquals(12.4231, result) + } + + @Test + fun testProcessXmlDataWhenGivenDifferentValueTypeShouldReturnNull() { + val tag = "latitude" + val element = createElement(tag, "StringData") + val xmlData: ArrayList = arrayListOf(element) + val result = xmlData.processXmlData(tag) + assertNull(result) + } +} diff --git a/library/src/main/java/com/nextcloud/extensions/ArrayListExtensions.kt b/library/src/main/java/com/nextcloud/extensions/ArrayListExtensions.kt new file mode 100644 index 000000000..f05747800 --- /dev/null +++ b/library/src/main/java/com/nextcloud/extensions/ArrayListExtensions.kt @@ -0,0 +1,27 @@ +package com.nextcloud.extensions + +import org.w3c.dom.Element + +@Suppress("ReturnCount", "NestedBlockDepth") +inline fun ArrayList<*>.processXmlData(tagName: String): T? { + this.forEach { + val element = it as? Element + if (element != null && element.tagName == tagName) { + val textContent = element.firstChild.textContent + + return when (T::class) { + Float::class -> { + val floatValue = textContent.toFloatOrNull() + if (floatValue != null) floatValue as T else null + } + Double::class -> { + val doubleValue = textContent.toDoubleOrNull() + if (doubleValue != null) doubleValue as T else null + } + else -> return null + } + } + } + + return null +} diff --git a/library/src/main/java/com/nextcloud/extensions/GsonExtensions.kt b/library/src/main/java/com/nextcloud/extensions/GsonExtensions.kt index 48d773ba1..d0df4823f 100644 --- a/library/src/main/java/com/nextcloud/extensions/GsonExtensions.kt +++ b/library/src/main/java/com/nextcloud/extensions/GsonExtensions.kt @@ -1,11 +1,16 @@ package com.nextcloud.extensions import com.google.gson.Gson +import com.google.gson.JsonSyntaxException import org.apache.jackrabbit.webdav.property.DavProperty inline fun Gson.fromDavProperty(davProperty: DavProperty<*>?): T? { return if (davProperty != null && davProperty.value != null) { - fromJson(davProperty.value.toString(), T::class.java) + try { + fromJson(davProperty.value.toString(), T::class.java) + } catch (e: JsonSyntaxException) { + null + } } else { null } diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index 6906b44e4..598e53c34 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -26,6 +26,7 @@ package com.owncloud.android.lib.common.network import android.net.Uri import com.google.gson.Gson import com.nextcloud.extensions.fromDavProperty +import com.nextcloud.extensions.processXmlData import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.lib.resources.files.model.FileLockType import com.owncloud.android.lib.resources.files.model.FileLockType.Companion.fromValue @@ -428,19 +429,16 @@ class WebdavEntry constructor(ms: MultiStatusResponse, splitElement: String) { prop = propSet[EXTENDED_PROPERTY_METADATA_SIZE, ncNamespace] gson.fromDavProperty(prop) } else { - val xmlData = prop.value as ArrayList<*> - var width = 0f - var height = 0f - xmlData.forEach { - val element = it as Element - if (element.tagName == "width") { - width = element.firstChild.textContent.toFloat() - } else if (element.tagName == "height") { - height = element.firstChild.textContent.toFloat() - } - } + val xmlData = prop.value as? ArrayList<*> + val width = xmlData?.processXmlData("width") + val height = xmlData?.processXmlData("height") - ImageDimension(width, height) + if (width != null && height != null) { + ImageDimension(width, height) + } else { + prop = propSet[EXTENDED_PROPERTY_METADATA_SIZE, ncNamespace] + gson.fromDavProperty(prop) + } } // NC metadata gps property @@ -450,19 +448,16 @@ class WebdavEntry constructor(ms: MultiStatusResponse, splitElement: String) { prop = propSet[EXTENDED_PROPERTY_METADATA_GPS, ncNamespace] gson.fromDavProperty(prop) } else { - val xmlData = prop.value as ArrayList<*> - var latitude = 0.0 - var longitude = 0.0 - xmlData.forEach { - val element = it as Element - if (element.tagName == "latitude") { - latitude = element.firstChild.textContent.toDouble() - } else if (element.tagName == "longitude") { - longitude = element.firstChild.textContent.toDouble() - } - } + val xmlData = prop.value as? ArrayList<*> + val latitude = xmlData?.processXmlData("latitude") + val longitude = xmlData?.processXmlData("longitude") - GeoLocation(latitude, longitude) + if (latitude != null && longitude != null) { + GeoLocation(latitude, longitude) + } else { + prop = propSet[EXTENDED_PROPERTY_METADATA_GPS, ncNamespace] + gson.fromDavProperty(prop) + } } // NC metadata live photo property: