From acf22bb318c651217be5abf0aeca41f9accf9daa Mon Sep 17 00:00:00 2001 From: M66B Date: Tue, 1 Nov 2022 14:07:48 +0100 Subject: [PATCH] Proof of concept: auto insert invites --- app/src/fdroid/AndroidManifest.xml | 2 + app/src/github/AndroidManifest.xml | 2 + .../main/java/eu/faircode/email/Helper.java | 13 +++ .../java/eu/faircode/email/MessageHelper.java | 87 +++++++++++++++++++ 4 files changed, 104 insertions(+) diff --git a/app/src/fdroid/AndroidManifest.xml b/app/src/fdroid/AndroidManifest.xml index 568aa2c751..ab44a8fe1b 100644 --- a/app/src/fdroid/AndroidManifest.xml +++ b/app/src/fdroid/AndroidManifest.xml @@ -14,6 +14,8 @@ + + diff --git a/app/src/github/AndroidManifest.xml b/app/src/github/AndroidManifest.xml index abeb6c632f..f446bbe8c7 100644 --- a/app/src/github/AndroidManifest.xml +++ b/app/src/github/AndroidManifest.xml @@ -14,6 +14,8 @@ + + diff --git a/app/src/main/java/eu/faircode/email/Helper.java b/app/src/main/java/eu/faircode/email/Helper.java index 4fa792cb29..6358b090ca 100644 --- a/app/src/main/java/eu/faircode/email/Helper.java +++ b/app/src/main/java/eu/faircode/email/Helper.java @@ -428,6 +428,19 @@ public class Helper { permissions.add(Manifest.permission.READ_CONTACTS); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) permissions.add(Manifest.permission.POST_NOTIFICATIONS); + + try { + PackageManager pm = context.getPackageManager(); + PackageInfo pi = pm.getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_PERMISSIONS); + for (int i = 0; i < pi.requestedPermissions.length; i++) + if (Manifest.permission.READ_CALENDAR.equals(pi.requestedPermissions[i])) + permissions.add(Manifest.permission.READ_CALENDAR); + else if (Manifest.permission.WRITE_CALENDAR.equals(pi.requestedPermissions[i])) + permissions.add(Manifest.permission.WRITE_CALENDAR); + } catch (Throwable ex) { + Log.w(ex); + } + return permissions.toArray(new String[0]); } diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java index 2b1c067922..0a9a5b2604 100644 --- a/app/src/main/java/eu/faircode/email/MessageHelper.java +++ b/app/src/main/java/eu/faircode/email/MessageHelper.java @@ -21,10 +21,16 @@ package eu.faircode.email; import static android.system.OsConstants.ENOSPC; +import android.Manifest; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; import android.content.Context; import android.content.SharedPreferences; +import android.database.Cursor; import android.net.Uri; import android.os.Build; +import android.provider.CalendarContract; import android.system.ErrnoException; import android.text.SpannableStringBuilder; import android.text.TextUtils; @@ -139,7 +145,9 @@ import javax.mail.internet.ParseException; import biweekly.Biweekly; import biweekly.ICalendar; +import biweekly.component.VEvent; import biweekly.property.Method; +import biweekly.util.ICalDate; public class MessageHelper { private boolean ensuredEnvelope = false; @@ -3681,6 +3689,85 @@ public class MessageHelper { db.attachment().setWarning(local.id, Log.formatThrowable(ex)); } + else if ("text/calendar".equals(local.type)) + try { + EntityMessage message = db.message().getMessage(local.message); + EntityFolder folder = (message == null ? null : db.folder().getFolder(message.folder)); + EntityAccount account = (folder == null ? null : db.account().getAccount(folder.account)); + if (folder != null && EntityFolder.INBOX.equals(folder.type) && + Helper.hasPermission(context, Manifest.permission.WRITE_CALENDAR)) { + ICalendar icalendar = Biweekly.parse(file).first(); + VEvent event = icalendar.getEvents().get(0); + + String summary = (event.getSummary() == null ? null : event.getSummary().getValue()); + String description = (event.getDescription() == null ? null : event.getDescription().getValue()); + String location = (event.getLocation() == null ? null : event.getLocation().getValue()); + + ICalDate start = (event.getDateStart() == null ? null : event.getDateStart().getValue()); + ICalDate end = (event.getDateEnd() == null ? null : event.getDateEnd().getValue()); + + String uid = (event.getUid() == null ? null : event.getUid().getValue()); + + if (start != null && end != null) { + ContentResolver resolver = context.getContentResolver(); + + if (!TextUtils.isEmpty(uid)) + try (Cursor cursor = resolver.query(CalendarContract.Events.CONTENT_URI, + new String[]{CalendarContract.Events._ID}, + CalendarContract.Events.UID_2445 + " = ? ", + new String[]{uid}, + null)) { + while (cursor.moveToNext()) { + long eventId = cursor.getLong(0); + + // https://developer.android.com/guide/topics/providers/calendar-provider#delete-event + Uri deleteUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventId); + int rows = resolver.delete(deleteUri, null, null); + EntityLog.log(context, EntityLog.Type.General, message, "Deleted event id=" + eventId + " rows=" + rows); + } + } + + try (Cursor cursor = resolver.query(CalendarContract.Calendars.CONTENT_URI, + new String[]{CalendarContract.Calendars._ID}, + CalendarContract.Calendars.VISIBLE + " = 1 AND " + + CalendarContract.Calendars.IS_PRIMARY + " = 1 AND " + + CalendarContract.Calendars.ACCOUNT_NAME + " = ?", + new String[]{account.user}, + null)) { + while (cursor.moveToNext()) { + // https://developer.android.com/guide/topics/providers/calendar-provider#add-event + // https://developer.android.com/reference/android/provider/CalendarContract.EventsColumns + ContentValues values = new ContentValues(); + values.put(CalendarContract.Events.CALENDAR_ID, cursor.getLong(0)); + if (!TextUtils.isEmpty(uid)) + values.put(CalendarContract.Events.UID_2445, uid); + values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID()); + values.put(CalendarContract.Events.DTSTART, start.getTime()); + values.put(CalendarContract.Events.DTEND, end.getTime()); + if (!TextUtils.isEmpty(summary)) + values.put(CalendarContract.Events.TITLE, summary); + if (!TextUtils.isEmpty(description)) + values.put(CalendarContract.Events.DESCRIPTION, description); + if (!TextUtils.isEmpty(location)) + values.put(CalendarContract.Events.EVENT_LOCATION, location); + values.put(CalendarContract.Events.STATUS, CalendarContract.Events.STATUS_TENTATIVE); + + Uri uri = resolver.insert(CalendarContract.Events.CONTENT_URI, values); + long eventId = Long.parseLong(uri.getLastPathSegment()); + EntityLog.log(context, EntityLog.Type.General, message, "Inserted event" + + " id=" + eventId + + " start=" + new Date(start.getTime()) + + " end=" + new Date(end.getTime()) + + " summary=" + summary); + } + } + } + } + } catch (Throwable ex) { + Log.w(ex); + db.attachment().setWarning(local.id, Log.formatThrowable(ex)); + } + else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && local.isCompressed()) { // https://commons.apache.org/proper/commons-compress/examples.html SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);