Loading app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt +82 −2 Original line number Original line Diff line number Diff line Loading @@ -19,10 +19,15 @@ import android.os.Bundle import android.os.Parcel import android.os.Parcel import android.os.RemoteException import android.os.RemoteException import android.provider.CalendarContract import android.provider.CalendarContract import android.provider.CalendarContract.ExtendedProperties import android.provider.ContactsContract import android.provider.ContactsContract import android.util.Base64 import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat import at.bitfire.davdroid.* import at.bitfire.davdroid.InvalidAccountException import at.bitfire.davdroid.R import at.bitfire.davdroid.TasksWatcher import at.bitfire.davdroid.closeCompat import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.model.AppDatabase import at.bitfire.davdroid.model.AppDatabase import at.bitfire.davdroid.model.Collection import at.bitfire.davdroid.model.Collection Loading @@ -32,13 +37,19 @@ import at.bitfire.davdroid.resource.LocalAddressBook import at.bitfire.davdroid.resource.LocalTask import at.bitfire.davdroid.resource.LocalTask import at.bitfire.davdroid.resource.TaskUtils import at.bitfire.davdroid.resource.TaskUtils import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.AndroidEvent import at.bitfire.ical4android.TaskProvider import at.bitfire.ical4android.TaskProvider import at.bitfire.ical4android.TaskProvider.ProviderName.OpenTasks import at.bitfire.ical4android.TaskProvider.ProviderName.OpenTasks import at.bitfire.ical4android.UnknownProperty import at.bitfire.vcard4android.ContactsStorageException import at.bitfire.vcard4android.ContactsStorageException import at.bitfire.vcard4android.GroupMethod import at.bitfire.vcard4android.GroupMethod import net.fortuna.ical4j.model.Property import net.fortuna.ical4j.model.property.Url import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils import org.dmfs.tasks.contract.TaskContract import org.dmfs.tasks.contract.TaskContract import java.io.ByteArrayInputStream import java.io.ObjectInputStream import java.util.logging.Level import java.util.logging.Level /** /** Loading @@ -54,7 +65,7 @@ class AccountSettings( companion object { companion object { const val CURRENT_VERSION = 11 const val CURRENT_VERSION = 12 const val KEY_SETTINGS_VERSION = "version" const val KEY_SETTINGS_VERSION = "version" const val KEY_SYNC_INTERVAL_ADDRESSBOOKS = "sync_interval_addressbooks" const val KEY_SYNC_INTERVAL_ADDRESSBOOKS = "sync_interval_addressbooks" Loading Loading @@ -419,6 +430,75 @@ class AccountSettings( } } @Suppress("unused","FunctionName") /** * Store event URLs as URL (extended property) instead of unknown property. At the same time, * convert legacy unknown properties to the current format. */ private fun update_11_12() { if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED) context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.use { provider -> // Attention: CalendarProvider does NOT limit the results of the ExtendedProperties query // to the given account! So all extended properties will be processed number-of-accounts times. val extUri = AndroidCalendar.syncAdapterURI(ExtendedProperties.CONTENT_URI, account) provider.query(extUri, arrayOf( ExtendedProperties._ID, // idx 0 ExtendedProperties.NAME, // idx 1 ExtendedProperties.VALUE // idx 2 ), null, null, null)?.use { cursor -> while (cursor.moveToNext()) { val id = cursor.getLong(0) val rawValue = cursor.getString(2) val uri by lazy { AndroidCalendar.syncAdapterURI(ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id), account) } when (cursor.getString(1)) { UnknownProperty.CONTENT_ITEM_TYPE -> { // unknown property; check whether it's a URL try { val property = UnknownProperty.fromJsonString(rawValue) if (property is Url) { // rewrite to MIMETYPE_URL val newValues = ContentValues(2) newValues.put(ExtendedProperties.NAME, AndroidEvent.MIMETYPE_URL) newValues.put(ExtendedProperties.VALUE, property.value) provider.update(uri, newValues, null, null) } } catch (e: Exception) { Logger.log.log(Level.WARNING, "Couldn't rewrite URL from unknown property to ${AndroidEvent.MIMETYPE_URL}", e) } } "unknown-property" -> { // unknown property (deprecated format); convert to current format try { val stream = ByteArrayInputStream(Base64.decode(rawValue, Base64.NO_WRAP)) ObjectInputStream(stream).use { (it.readObject() as? Property)?.let { property -> // rewrite to current format val newValues = ContentValues(2) newValues.put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) newValues.put(ExtendedProperties.VALUE, UnknownProperty.toJsonString(property)) provider.update(uri, newValues, null, null) } } } catch(e: Exception) { Logger.log.log(Level.WARNING, "Couldn't rewrite deprecated unknown property to current format", e) } } "unknown-property.v2" -> { // unknown property (deprecated MIME type); rewrite to current MIME type val newValues = ContentValues(1) newValues.put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) provider.update(uri, newValues, null, null) } } } } } } @Suppress("unused","FunctionName") @Suppress("unused","FunctionName") /** /** * The tasks sync interval should be stored in account settings. It's used to set the sync interval * The tasks sync interval should be stored in account settings. It's used to set the sync interval Loading ical4android @ 235cde2e Compare 7d79f861 to 235cde2e Original line number Original line Diff line number Diff line Subproject commit 7d79f861b0822173a9aaa6a2ab1ab6b9f5adac8d Subproject commit 235cde2ec49bbdfb588988c732b90b89561492d6 Loading
app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt +82 −2 Original line number Original line Diff line number Diff line Loading @@ -19,10 +19,15 @@ import android.os.Bundle import android.os.Parcel import android.os.Parcel import android.os.RemoteException import android.os.RemoteException import android.provider.CalendarContract import android.provider.CalendarContract import android.provider.CalendarContract.ExtendedProperties import android.provider.ContactsContract import android.provider.ContactsContract import android.util.Base64 import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat import at.bitfire.davdroid.* import at.bitfire.davdroid.InvalidAccountException import at.bitfire.davdroid.R import at.bitfire.davdroid.TasksWatcher import at.bitfire.davdroid.closeCompat import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.model.AppDatabase import at.bitfire.davdroid.model.AppDatabase import at.bitfire.davdroid.model.Collection import at.bitfire.davdroid.model.Collection Loading @@ -32,13 +37,19 @@ import at.bitfire.davdroid.resource.LocalAddressBook import at.bitfire.davdroid.resource.LocalTask import at.bitfire.davdroid.resource.LocalTask import at.bitfire.davdroid.resource.TaskUtils import at.bitfire.davdroid.resource.TaskUtils import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.AndroidEvent import at.bitfire.ical4android.TaskProvider import at.bitfire.ical4android.TaskProvider import at.bitfire.ical4android.TaskProvider.ProviderName.OpenTasks import at.bitfire.ical4android.TaskProvider.ProviderName.OpenTasks import at.bitfire.ical4android.UnknownProperty import at.bitfire.vcard4android.ContactsStorageException import at.bitfire.vcard4android.ContactsStorageException import at.bitfire.vcard4android.GroupMethod import at.bitfire.vcard4android.GroupMethod import net.fortuna.ical4j.model.Property import net.fortuna.ical4j.model.property.Url import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils import org.dmfs.tasks.contract.TaskContract import org.dmfs.tasks.contract.TaskContract import java.io.ByteArrayInputStream import java.io.ObjectInputStream import java.util.logging.Level import java.util.logging.Level /** /** Loading @@ -54,7 +65,7 @@ class AccountSettings( companion object { companion object { const val CURRENT_VERSION = 11 const val CURRENT_VERSION = 12 const val KEY_SETTINGS_VERSION = "version" const val KEY_SETTINGS_VERSION = "version" const val KEY_SYNC_INTERVAL_ADDRESSBOOKS = "sync_interval_addressbooks" const val KEY_SYNC_INTERVAL_ADDRESSBOOKS = "sync_interval_addressbooks" Loading Loading @@ -419,6 +430,75 @@ class AccountSettings( } } @Suppress("unused","FunctionName") /** * Store event URLs as URL (extended property) instead of unknown property. At the same time, * convert legacy unknown properties to the current format. */ private fun update_11_12() { if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED) context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.use { provider -> // Attention: CalendarProvider does NOT limit the results of the ExtendedProperties query // to the given account! So all extended properties will be processed number-of-accounts times. val extUri = AndroidCalendar.syncAdapterURI(ExtendedProperties.CONTENT_URI, account) provider.query(extUri, arrayOf( ExtendedProperties._ID, // idx 0 ExtendedProperties.NAME, // idx 1 ExtendedProperties.VALUE // idx 2 ), null, null, null)?.use { cursor -> while (cursor.moveToNext()) { val id = cursor.getLong(0) val rawValue = cursor.getString(2) val uri by lazy { AndroidCalendar.syncAdapterURI(ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id), account) } when (cursor.getString(1)) { UnknownProperty.CONTENT_ITEM_TYPE -> { // unknown property; check whether it's a URL try { val property = UnknownProperty.fromJsonString(rawValue) if (property is Url) { // rewrite to MIMETYPE_URL val newValues = ContentValues(2) newValues.put(ExtendedProperties.NAME, AndroidEvent.MIMETYPE_URL) newValues.put(ExtendedProperties.VALUE, property.value) provider.update(uri, newValues, null, null) } } catch (e: Exception) { Logger.log.log(Level.WARNING, "Couldn't rewrite URL from unknown property to ${AndroidEvent.MIMETYPE_URL}", e) } } "unknown-property" -> { // unknown property (deprecated format); convert to current format try { val stream = ByteArrayInputStream(Base64.decode(rawValue, Base64.NO_WRAP)) ObjectInputStream(stream).use { (it.readObject() as? Property)?.let { property -> // rewrite to current format val newValues = ContentValues(2) newValues.put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) newValues.put(ExtendedProperties.VALUE, UnknownProperty.toJsonString(property)) provider.update(uri, newValues, null, null) } } } catch(e: Exception) { Logger.log.log(Level.WARNING, "Couldn't rewrite deprecated unknown property to current format", e) } } "unknown-property.v2" -> { // unknown property (deprecated MIME type); rewrite to current MIME type val newValues = ContentValues(1) newValues.put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) provider.update(uri, newValues, null, null) } } } } } } @Suppress("unused","FunctionName") @Suppress("unused","FunctionName") /** /** * The tasks sync interval should be stored in account settings. It's used to set the sync interval * The tasks sync interval should be stored in account settings. It's used to set the sync interval Loading
ical4android @ 235cde2e Compare 7d79f861 to 235cde2e Original line number Original line Diff line number Diff line Subproject commit 7d79f861b0822173a9aaa6a2ab1ab6b9f5adac8d Subproject commit 235cde2ec49bbdfb588988c732b90b89561492d6