@@ -266,18 +266,46 @@ my %ALLOWED_CONTENT_BY_TYPE = (
266266
267267sub redact_event
268268{
269- my ( $event ) = @_ ;
269+ my ( $event , $room_version ) = @_ ;
270+ $room_version //= 1;
270271
271272 defined ( my $type = $event -> {type } ) or
272273 croak " Event requires a 'type'" ;
273274
275+ delete $event -> {redacts };
274276 my $old_content = delete $event -> {content };
275277 my $old_unsigned = delete $event -> {unsigned };
276278
277279 $ALLOWED_KEYS {$_ } or delete $event -> {$_ } for keys %$event ;
278280
279281 my $new_content = $event -> {content } = {};
280282
283+ # Room version 11+ uses updated redaction rules:
284+ # - m.room.create: entire content property is preserved
285+ # - m.room.power_levels: 'invite' is also preserved
286+ # - m.room.member: 'third_party_invite.signed' is also preserved
287+ # - m.room.redaction: 'redacts' is also preserved
288+ if ( defined $room_version and $room_version =~ / \A [0-9]+\z / and $room_version >= 11 ) {
289+ if ( $type eq ' m.room.create' ) {
290+ %$new_content = %{ $old_content // {} };
291+ $event -> {unsigned }{age_ts } = $old_unsigned -> {age_ts } if exists $old_unsigned -> {age_ts };
292+ return ;
293+ }
294+ if ( $type eq ' m.room.power_levels' ) {
295+ exists $old_content -> {invite } and $new_content -> {invite } = $old_content -> {invite };
296+ }
297+ if ( $type eq ' m.room.member' ) {
298+ my $tpi = $old_content -> {third_party_invite };
299+ if ( ref $tpi eq ' HASH' && exists $tpi -> {signed } ) {
300+ $new_content -> {third_party_invite } = { signed => $tpi -> {signed } };
301+ }
302+ }
303+ if ( $type eq ' m.room.redaction' ) {
304+ # In v11, 'redacts' moved into content; preserve content.redacts
305+ exists $old_content -> {redacts } and $new_content -> {redacts } = $old_content -> {redacts };
306+ }
307+ }
308+
281309 if ( my $allowed_content_keys = $ALLOWED_CONTENT_BY_TYPE {$type } ) {
282310 exists $old_content -> {$_ } and $new_content -> {$_ } = $old_content -> {$_ } for
283311 @$allowed_content_keys ;
@@ -288,8 +316,8 @@ sub redact_event
288316
289317sub redacted_event
290318{
291- my ( $event ) = @_ ;
292- redact_event( $event = { %$event } );
319+ my ( $event , $room_version ) = @_ ;
320+ redact_event( $event = { %$event }, $room_version );
293321 return $event ;
294322}
295323
@@ -309,6 +337,7 @@ sub sign_event_json
309337
310338 my $origin = $args {origin } or croak " Require an 'origin'" ;
311339 my $key_id = $args {key_id } or croak " Require a 'key_id'" ;
340+ my $room_version = delete $args {room_version };
312341
313342 # 'hashes' records the original unredacted version
314343 {
@@ -319,7 +348,7 @@ sub sign_event_json
319348 }
320349
321350 # Signature is of redacted version
322- sign_json( my $signed = redacted_event( $event ), %args );
351+ sign_json( my $signed = redacted_event( $event , $room_version ), %args );
323352
324353 $event -> {signatures } = $signed -> {signatures };
325354}
@@ -349,9 +378,10 @@ sub signed_event_json
349378
350379sub verify_event_json_signature
351380{
352- my ( $event , @ args ) = @_ ;
381+ my ( $event , % args ) = @_ ;
353382
354- verify_json_signature( redacted_event( $event ), @args );
383+ my $room_version = delete $args {room_version };
384+ verify_json_signature( redacted_event( $event , $room_version ), %args );
355385}
356386
357387=head1 AUTHOR
0 commit comments