diff --git a/tests/51media/01unicode.pl b/tests/51media/01unicode.pl deleted file mode 100644 index b450d4be6..000000000 --- a/tests/51media/01unicode.pl +++ /dev/null @@ -1,242 +0,0 @@ -use HTTP::Headers::Util qw( split_header_words ); -use URI::Escape qw( uri_escape ); -use SyTest::TCPProxy; -use utf8; - -my $FILENAME = "\xf0\x9f\x90\x94"; -my $FILENAME_ENCODED = uc uri_escape( $FILENAME ); - -my $content_id; - -my $PROXY_SERVER = fixture( - name => 'PROXY_SERVER', - - requires => [ $main::HOMESERVER_INFO[0] ], - - setup => sub { - my ( $server_info ) = @_; - - $OUTPUT->diag( "Starting proxy server" ); - - my $listener = SyTest::TCPProxy->new( - host => $server_info->federation_host, - port => $server_info->federation_port, - output => $OUTPUT, - ); - - $loop->add( $listener ); - - $listener->listen( - addr => { family => "inet" }, - )->on_done( sub { - my $sock = $listener->read_handle; - $OUTPUT->diag( "Proxy now listening at port " . $sock->sockport ); - return $listener; - }); - }, - - teardown => sub { - my ( $listener ) = @_; - $listener->close(); - }, -); - - -=head2 upload_test_content - - my ( $content_id, $content_uri ) = upload_test_content( - $user, filename => "filename", - ) -> get; - -Uploads some test content with the given filename. - -Returns the content id of the uploaded content. - -=cut -sub upload_test_content -{ - my ( $user, %params ) = @_; - - $user->http->do_request( - method => "POST", - full_uri => "/_matrix/media/v3/upload", - content => "Test media file", - content_type => "text/plain", - - params => { - access_token => $user->access_token, - %params, - }, - )->then( sub { - my ( $body ) = @_; - - assert_json_keys( $body, qw( content_uri )); - - my $content_uri = $body->{content_uri}; - - my $parsed_uri = URI->new( $body->{content_uri} ); - my $server = $parsed_uri->authority; - my $path = $parsed_uri->path; - - my $content_id = "$server$path"; - - Future->done( $content_id, $content_uri ); - }); -} -push our @EXPORT, qw( upload_test_content ); - - -=head2 get_media - - my ( $content_disposition_params, $content ) = get_media( $http, $content_id ) -> get; - -Fetches a piece of media from the server. - -=cut -sub get_media -{ - my ( $http, $content_id ) = @_; - - $http->do_request( - method => "GET", - full_uri => "/_matrix/media/v3/download/$content_id", - )->then( sub { - my ( $body, $response ) = @_; - - my $disposition = $response->header( "Content-Disposition" ); - - my $cd_params; - if ( defined $disposition ) { - $cd_params = parse_content_disposition_params( $disposition ); - } - Future->done( $cd_params, $body ); - }); -} -push @EXPORT, qw( get_media ); - -sub parse_content_disposition_params { - my ( $disposition ) = @_; - my @parts = split_header_words( $disposition ); - - # should be only one list of words - assert_eq( scalar @parts, 1, "number of content-dispostion header lists" ); - @parts = @{$parts[0]}; - - # the first part must be 'attachment' - my $k = shift @parts; - my $v = shift @parts; - assert_eq( $k, "attachment", "content-disposition" ); - die "invalid CD" if defined $v; - - my %params; - while (@parts) { - my $k = shift @parts; - my $v = shift @parts; - die "multiple $k params" if exists $params{$k}; - die "unknown param $k" unless ( $k eq 'filename' || $k eq 'filename*' ); - $params{$k} = $v; - } - return \%params; -} - - -test "Can upload with Unicode file name", - requires => [ local_user_fixture(), - qw( can_upload_media )], - - proves => [qw( can_upload_media_unicode )], - - do => sub { - my ( $user ) = @_; - - upload_test_content( $user, filename=>$FILENAME )->then( sub { - ( $content_id ) = @_; - Future->done(1) - }); - }; - -# These next two tests do the same thing with two different HTTP clients, to -# test locally and via federation - -sub test_using_client -{ - my ( $client, $content ) = @_; - - if( ! defined( $content )) { - $content = $content_id; - } - - get_media( $client, $content )->then( sub { - my ( $cd_params ) = @_; - - # The Content-Disposition header can take two formats - either: - # * filename=utf-8"filename_here" - # * filename*=utf-8''filename_here - # This checks the format of whichever one we were provided with. - if (exists( $cd_params->{filename} )) { - assert_eq( $cd_params->{filename}, "utf-8\"$FILENAME\"", "filename" ); - } else { - assert_eq( $cd_params->{'filename*'}, "utf-8''$FILENAME_ENCODED", "filename*" ); - } - - Future->done(1); - }); -} - -test "Can download with Unicode file name locally", - requires => [ $main::API_CLIENTS[0], - qw( can_upload_media_unicode )], - - check => sub { - my ( $http ) = @_; - test_using_client( $http ); - }; - -test "Can download with Unicode file name over federation", - requires => [ $main::API_CLIENTS[1], - qw( can_upload_media_unicode ) ], - - check => sub { - my ( $http ) = @_; - test_using_client( $http ); - }; - -test "Alternative server names do not cause a routing loop", - # https://github.com/matrix-org/synapse/issues/1991 - requires => [ $main::API_CLIENTS[0], $PROXY_SERVER ], - - check => sub { - my ( $http, $proxy ) = @_; - # we use a proxy server which routes connections straight back to the - # homeserver, to mimic the behaviour when the remote server name points - # back to the homeserver. - my $sock = $proxy->read_handle; - my $proxy_address = "localhost:" . $proxy->read_handle->sockport; - my $content = "$proxy_address/test_content"; - test_using_client( $http, $content )->main::expect_http_404; - }; - -test "Can download specifying a different Unicode file name", - requires => [ $main::API_CLIENTS[0], - qw( can_upload_media_unicode )], - - check => sub { - my ( $http ) = @_; - - my $alt_filename = "☕"; - my $alt_filename_encoded = "%E2%98%95"; - - $http->do_request( - method => "GET", - full_uri => "/_matrix/media/v3/download/$content_id/$alt_filename_encoded", - )->then( sub { - my ( $body, $response ) = @_; - - my $disposition = $response->header( "Content-Disposition" ); - uc $disposition eq uc "attachment; filename*=utf-8''$alt_filename_encoded" or - uc $disposition eq uc "attachment; filename=utf-8\"$alt_filename\"" or - die "Expected a UTF-8 filename parameter"; - - Future->done(1); - }); - }; diff --git a/tests/51media/02nofilename.pl b/tests/51media/02nofilename.pl deleted file mode 100644 index 968a7a6cb..000000000 --- a/tests/51media/02nofilename.pl +++ /dev/null @@ -1,47 +0,0 @@ -my $content_id; - -test "Can upload without a file name", - requires => [ local_user_fixture() ], - - do => sub { - my ( $user ) = @_; - - upload_test_content( $user, )->then( sub { - ( $content_id ) = @_; - Future->done(1) - }); - }; - -# These next two tests do the same thing with two different HTTP clients, to -# test locally and via federation - -sub test_using_client -{ - my ( $client ) = @_; - - get_media( $client, $content_id )->then( sub { - my ( $disposition ) = @_; - - # Require `attachment` `Content-Disposition` without a filename portion. - # See `get_media`: {} means attachment with no key-value components in the header value. - assert_eq( scalar %$disposition, 0, "content-disposition" ); - - Future->done(1); - }); -} - -test "Can download without a file name locally", - requires => [ $main::API_CLIENTS[0] ], - - check => sub { - my ( $http ) = @_; - test_using_client( $http ); - }; - -test "Can download without a file name over federation", - requires => [ $main::API_CLIENTS[1] ], - - check => sub { - my ( $http ) = @_; - test_using_client( $http ); - }; diff --git a/tests/51media/03ascii.pl b/tests/51media/03ascii.pl deleted file mode 100644 index 6adb05958..000000000 --- a/tests/51media/03ascii.pl +++ /dev/null @@ -1,126 +0,0 @@ -my $content_id; -my $content_uri; - -test "Can upload with ASCII file name", - requires => [ local_user_fixture() ], - - do => sub { - my ( $user ) = @_; - upload_test_content( $user, filename=>"ascii" )->then( sub { - ( $content_id, $content_uri ) = @_; - Future->done(1); - }); - }; - -# we only need one user for these tests -my $user_fixture = local_user_fixture(); - -sub assert_cd_params_match_filename { - my ( $filename, $cd_params ) = @_; - - # either we need a valid "filename*" param - if ( $cd_params->{"filename*"} ) { - my $f = $cd_params->{"filename*"}; - $f =~ s/%(..)/chr hex $1/eg; - assert_eq( $f, "utf-8''$filename", "filename*" ); - - # there might also be a 'filename', but it doesn't really matter what it - # is. - return; - } - - # or we need a valid filename - my $f = $cd_params->{"filename"}; - assert_eq( $f, $filename, "filename" ); -} - -foreach my $filename ( "ascii", "name with spaces", "name;with;semicolons" ) { - test "Can download file '$filename'", - requires => [ - $user_fixture, $main::API_CLIENTS[1] - ], - - check => sub { - my ( $user, $federation_client ) = @_; - - my $content_id; - - # first upload the content with the given filename - upload_test_content( $user, filename=>$filename )->then( sub { - ( $content_id ) = @_; - - # try and fetch it as a local user - get_media( $user->http, $content_id ); - })->then( sub { - assert_cd_params_match_filename( $filename, $_[0] ); - - # do the same over federation - get_media( $federation_client, $content_id ); - })->then( sub { - assert_cd_params_match_filename( $filename, $_[0] ); - Future->done(1); - }); - }; -} - - -test "Can download specifying a different ASCII file name", - requires => [ $main::API_CLIENTS[0] ], - - check => sub { - my ( $http ) = @_; - - $http->do_request( - method => "GET", - full_uri => "/_matrix/media/v3/download/$content_id/also_ascii", - )->then( sub { - my ( $body, $response ) = @_; - - my $disposition = $response->header( "Content-Disposition" ); - $disposition eq "attachment; filename=also_ascii" or - die "Expected an ASCII filename parameter"; - - Future->done(1); - }); - }; - -test "Can send image in room message", - requires => [ $main::API_CLIENTS[0], local_user_and_room_fixtures() ], - - check => sub { - my ( $http, $user, $room_id ) = @_; - matrix_send_room_message( $user, $room_id, - content => { msgtype => "m.file", body => "test.txt", url => $content_uri } - ); - }; - -test "Can fetch images in room", - requires => [ $main::API_CLIENTS[0], local_user_and_room_fixtures() ], - - check => sub { - my ( $http, $user, $room_id ) = @_; - matrix_send_room_message_synced( $user, $room_id, - content => { msgtype => "m.text", body => "test" } - )->then( sub { - matrix_send_room_message_synced( $user, $room_id, - content => { msgtype => "m.file", body => "test.txt", url => $content_uri } - ) - })->then( sub { - do_request_json_for( $user, - method => "GET", - uri => "/v3/rooms/$room_id/messages", - params => { - filter => '{"contains_url":true}', - dir => 'b', - } - ) - })->then( sub { - my ( $body ) = @_; - - assert_json_keys( $body, qw( start end chunk )); - - assert_eq( scalar @{ $body->{chunk} }, 1, "Expected 1 message" ); - - Future->done( 1 ); - }); - }; diff --git a/tests/51media/10thumbnail.pl b/tests/51media/10thumbnail.pl deleted file mode 100644 index 0951c55b0..000000000 --- a/tests/51media/10thumbnail.pl +++ /dev/null @@ -1,107 +0,0 @@ -use File::Basename qw( dirname ); -use File::Slurper qw( read_binary ); - -my $dir = dirname __FILE__; - -test "POSTed media can be thumbnailed", - requires => [ $main::API_CLIENTS[0], local_user_fixture(), - qw( can_upload_media can_download_media )], - - do => sub { - my ( $http, $user ) = @_; - - upload_test_image( - $user, - )->then( sub { - my ( $content_uri ) = @_; - fetch_and_validate_thumbnail( $http, $content_uri ); - }); - }; - - -test "Remote media can be thumbnailed", - requires => [ local_user_fixture(), remote_user_fixture(), - qw( can_upload_media can_download_media )], - do => sub { - my ( $local_user, $remote_user ) = @_; - - upload_test_image( - $local_user, - )->then( sub { - my ( $content_uri ) = @_; - fetch_and_validate_thumbnail( $remote_user->http, $content_uri ); - }); - }; - - -sub upload_test_image -{ - my ( $user ) = @_; - - my $pngdata = read_binary( "$dir/test.png" ); - - # Because we're POST'ing non-JSON - return $user->http->do_request( - method => "POST", - full_uri => "/_matrix/media/v3/upload", - params => { - access_token => $user->access_token, - }, - - content_type => "image/png", - content => $pngdata, - )->then( sub { - my ( $body ) = @_; - log_if_fail "Upload response", $body; - my $content_uri = URI->new( $body->{content_uri} ); - Future->done( $content_uri ); - }); -} - -sub fetch_and_validate_thumbnail -{ - my ( $http, $mxc_uri ) = @_; - - return $http->do_request( - method => "GET", - full_uri => "/_matrix/media/v3/thumbnail/" . - join( "", $mxc_uri->authority, $mxc_uri->path ), - params => { - width => 32, - height => 32, - method => "scale", - } - )->then( sub { - my ( $body, $response ) = @_; - for( $response->content_type ) { - m{^image/png$} and validate_png( $body ), last; - - # TODO: should probably write a JPEG recogniser too - - die "Unrecognised Content-Type ($_) - unable to detect if this is a valid image"; - } - - Future->done(1); - }); -} - -# We won't assert too heavily that it's a valid image as that's hard to do -# without using a full image parsing library like Imager. Instead we'll just -# detect file magic of a likely-valid encoding as this should cover most common -# implementation bugs, such as sending plain-text error messages with image -# MIME headers, or claiming one MIME type while being another. - -sub validate_png -{ - my ( $body ) = @_; - - # All PNG images begin with the same 8 byte header - $body =~ s/^\x89PNG\x0D\x0A\x1A\x0A// or - die "Invalid PNG magic"; - - # All PNG images have an IHDR header first. This header is 13 bytes long - $body =~ s/^\0\0\0\x0DIHDR// or - die "Invalid IHDR chunk"; - - return 1; -}