diff --git a/CHANGES.md b/CHANGES.md
index feff52b7b3..1a095d20be 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,6 +12,7 @@ Improvements 🙌:
  - Picture preview when replying. Also add the image preview in the message detail bottomsheet (#2916)
  - Api interceptor to allow app developers peek responses (#2986)
  - Update reactions to Unicode 13.1 (#2998)
+ - Be more robust when parsing some enums
 
 Bugfix 🐛:
  - Fix bad theme change for the MainActivity
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Membership.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Membership.kt
index 5844aead8d..a5d0f63722 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Membership.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/Membership.kt
@@ -23,24 +23,13 @@ import com.squareup.moshi.JsonClass
  * Represents the membership of a user on a room
  */
 @JsonClass(generateAdapter = false)
-enum class Membership(val value: String) {
-
-    NONE("none"),
-
-    @Json(name = "invite")
-    INVITE("invite"),
-
-    @Json(name = "join")
-    JOIN("join"),
-
-    @Json(name = "knock")
-    KNOCK("knock"),
-
-    @Json(name = "leave")
-    LEAVE("leave"),
-
-    @Json(name = "ban")
-    BAN("ban");
+enum class Membership {
+    NONE,
+    @Json(name = "invite") INVITE,
+    @Json(name = "join") JOIN,
+    @Json(name = "knock") KNOCK,
+    @Json(name = "leave") LEAVE,
+    @Json(name = "ban") BAN;
 
     fun isLeft(): Boolean {
         return this == KNOCK || this == LEAVE || this == BAN
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt
index 99b035d30e..0760c6f1b4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room.model
 
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
+import timber.log.Timber
 
 /**
  * Class representing the EventType.STATE_ROOM_GUEST_ACCESS state event content
@@ -26,14 +27,20 @@ import com.squareup.moshi.JsonClass
 @JsonClass(generateAdapter = true)
 data class RoomGuestAccessContent(
         // Required. Whether guests can join the room. One of: ["can_join", "forbidden"]
-        @Json(name = "guest_access") val guestAccess: GuestAccess? = null
-)
+        @Json(name = "guest_access") val _guestAccess: String? = null
+) {
+    val guestAccess: GuestAccess? = when (_guestAccess) {
+        "can_join"  -> GuestAccess.CanJoin
+        "forbidden" -> GuestAccess.Forbidden
+        else        -> {
+            Timber.w("Invalid value for GuestAccess: `$_guestAccess`")
+            null
+        }
+    }
+}
 
 @JsonClass(generateAdapter = false)
-enum class GuestAccess(val value: String) {
-    @Json(name = "can_join")
-    CanJoin("can_join"),
-
-    @Json(name = "forbidden")
-    Forbidden("forbidden")
+enum class GuestAccess {
+    @Json(name = "can_join") CanJoin,
+    @Json(name = "forbidden") Forbidden
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt
index 31493be7ea..3ac14e48de 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt
@@ -18,8 +18,20 @@ package org.matrix.android.sdk.api.session.room.model
 
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
+import timber.log.Timber
 
 @JsonClass(generateAdapter = true)
 data class RoomHistoryVisibilityContent(
-        @Json(name = "history_visibility") val historyVisibility: RoomHistoryVisibility? = null
-)
+        @Json(name = "history_visibility") val _historyVisibility: String? = null
+) {
+    val historyVisibility: RoomHistoryVisibility? = when (_historyVisibility) {
+        "world_readable" -> RoomHistoryVisibility.WORLD_READABLE
+        "shared"         -> RoomHistoryVisibility.SHARED
+        "invited"        -> RoomHistoryVisibility.INVITED
+        "joined"         -> RoomHistoryVisibility.JOINED
+        else             -> {
+            Timber.w("Invalid value for RoomHistoryVisibility: `$_historyVisibility`")
+            null
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRules.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRules.kt
index 09aacfabbe..f3e8d357f3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRules.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRules.kt
@@ -24,17 +24,9 @@ import com.squareup.moshi.JsonClass
  * Enum for [RoomJoinRulesContent] : https://matrix.org/docs/spec/client_server/r0.4.0#m-room-join-rules
  */
 @JsonClass(generateAdapter = false)
-enum class RoomJoinRules(val value: String) {
-
-    @Json(name = "public")
-    PUBLIC("public"),
-
-    @Json(name = "invite")
-    INVITE("invite"),
-
-    @Json(name = "knock")
-    KNOCK("knock"),
-
-    @Json(name = "private")
-    PRIVATE("private")
+enum class RoomJoinRules {
+    @Json(name = "public") PUBLIC,
+    @Json(name = "invite") INVITE,
+    @Json(name = "knock") KNOCK,
+    @Json(name = "private") PRIVATE
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt
index 3be2d38be7..8082486b22 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomJoinRulesContent.kt
@@ -19,11 +19,23 @@ package org.matrix.android.sdk.api.session.room.model
 
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
+import timber.log.Timber
 
 /**
  * Class representing the EventType.STATE_ROOM_JOIN_RULES state event content
  */
 @JsonClass(generateAdapter = true)
 data class RoomJoinRulesContent(
-        @Json(name = "join_rule") val joinRules: RoomJoinRules? = null
-)
+        @Json(name = "join_rule") val _joinRules: String? = null
+) {
+    val joinRules: RoomJoinRules? = when (_joinRules) {
+        "public"  -> RoomJoinRules.PUBLIC
+        "invite"  -> RoomJoinRules.INVITE
+        "knock"   -> RoomJoinRules.KNOCK
+        "private" -> RoomJoinRules.PRIVATE
+        else      -> {
+            Timber.w("Invalid value for RoomJoinRules: `$_joinRules`")
+            null
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt
index 20cb49ee8a..b065a30fc9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.room
 
 import org.matrix.android.sdk.api.session.events.model.Content
 import org.matrix.android.sdk.api.session.events.model.Event
+import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
 import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
 import org.matrix.android.sdk.api.util.JsonDict
@@ -100,8 +101,8 @@ internal interface RoomAPI {
     @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/members")
     fun getMembers(@Path("roomId") roomId: String,
                    @Query("at") syncToken: String?,
-                   @Query("membership") membership: String?,
-                   @Query("not_membership") notMembership: String?
+                   @Query("membership") membership: Membership?,
+                   @Query("not_membership") notMembership: Membership?
     ): Call<RoomMembersResponse>
 
     /**
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt
index cc491d1cd9..6adf3c59d1 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt
@@ -91,7 +91,7 @@ internal class DefaultLoadRoomMembersTask @Inject constructor(
         val lastToken = syncTokenStore.getLastToken()
         val response = try {
             executeRequest<RoomMembersResponse>(globalErrorReceiver) {
-                apiCall = roomAPI.getMembers(params.roomId, lastToken, null, params.excludeMembership?.value)
+                apiCall = roomAPI.getMembers(params.roomId, lastToken, null, params.excludeMembership)
             }
         } catch (throwable: Throwable) {
             // Revert status to NONE
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt
index f2640fd1e7..615bc99096 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt
@@ -27,10 +27,8 @@ import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toContent
 import org.matrix.android.sdk.api.session.room.model.GuestAccess
 import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
-import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
 import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
 import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
-import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
 import org.matrix.android.sdk.api.session.room.state.StateService
 import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.api.util.MimeTypes
@@ -131,14 +129,14 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
         if (joinRules != null) {
             sendStateEvent(
                     eventType = EventType.STATE_ROOM_JOIN_RULES,
-                    body = RoomJoinRulesContent(joinRules).toContent(),
+                    body = mapOf("join_rule" to joinRules),
                     stateKey = null
             )
         }
         if (guestAccess != null) {
             sendStateEvent(
                     eventType = EventType.STATE_ROOM_GUEST_ACCESS,
-                    body = RoomGuestAccessContent(guestAccess).toContent(),
+                    body = mapOf("guest_access" to guestAccess),
                     stateKey = null
             )
         }
diff --git a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt
index fa1c50f419..859df7d714 100644
--- a/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt
+++ b/vector/src/main/java/im/vector/app/core/utils/ExternalApplicationsUtil.kt
@@ -514,7 +514,7 @@ fun selectTxtFileToWrite(
 @Suppress("DEPRECATION")
 fun saveFileIntoLegacy(sourceFile: File, dstDirPath: File, outputFilename: String?): File? {
     // defines another name for the external media
-    val dstFileName: String
+    var dstFileName: String
 
     // build a filename is not provided
     if (null == outputFilename) {
@@ -529,6 +529,9 @@ fun saveFileIntoLegacy(sourceFile: File, dstDirPath: File, outputFilename: Strin
         dstFileName = outputFilename
     }
 
+    // remove dangerous characters from the filename
+    dstFileName = dstFileName.replace(Regex("""[/\\]"""), "_")
+
     var dstFile = File(dstDirPath, dstFileName)
 
     // if the file already exists, append a marker