Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83f257f0 authored by Ricki Hirner's avatar Ricki Hirner
Browse files

Events: support URL as extended property; rewrite deprecated unknown properties to current format

parent 1d35f80a
Loading
Loading
Loading
Loading
+82 −2
Original line number Original line Diff line number Diff line
@@ -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
@@ -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


/**
/**
@@ -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"
@@ -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
Compare 7d79f861 to 235cde2e
Original line number Original line Diff line number Diff line
Subproject commit 7d79f861b0822173a9aaa6a2ab1ab6b9f5adac8d
Subproject commit 235cde2ec49bbdfb588988c732b90b89561492d6