2020import java .time .Instant ;
2121import java .util .ArrayList ;
2222import java .util .Arrays ;
23+ import java .util .Base64 ;
2324import java .util .Collections ;
2425import java .util .HashMap ;
2526import java .util .List ;
2627import java .util .Locale ;
2728import java .util .Map ;
2829import java .util .Set ;
30+ import java .util .function .Function ;
2931import java .util .function .Predicate ;
3032import java .util .regex .Matcher ;
3133import java .util .regex .Pattern ;
4648import smithereen .activitypub .objects .Document ;
4749import smithereen .activitypub .objects .Image ;
4850import smithereen .activitypub .objects .LocalImage ;
51+ import smithereen .api .methods .ApiUtils ;
4952import smithereen .controllers .ObjectLinkResolver ;
5053import smithereen .exceptions .BadRequestException ;
5154import smithereen .exceptions .ObjectNotFoundException ;
100103import smithereen .text .TextProcessor ;
101104import smithereen .util .CaptchaGenerator ;
102105import smithereen .util .CharacterRange ;
106+ import smithereen .util .CryptoUtils ;
103107import smithereen .util .JsonArrayBuilder ;
104108import smithereen .util .JsonObjectBuilder ;
105109import smithereen .util .NamedMutexCollection ;
@@ -434,7 +438,17 @@ void updateContainerInDatabase(@NotNull DatabaseConnection conn, @NotNull Photo
434438 }
435439 try {
436440 SessionInfo sessionInfo =sessionInfo (req );
437- if (sessionInfo ==null || sessionInfo .account ==null ){ // Only download attachments for logged-in users. Prevents crawlers from causing unnecessary churn in the media cache
441+ boolean canProceed =sessionInfo !=null && sessionInfo .account !=null ;
442+ boolean hadCorrectApiHash =false ;
443+ if (!canProceed ){
444+ String apiHash =req .queryParams ("api" );
445+ if (StringUtils .isNotEmpty (apiHash )){
446+ Map <String , String > params =req .queryParams ().stream ().collect (Collectors .toMap (Function .identity (), req ::queryParams ));
447+ canProceed =apiHash .equals (ApiUtils .getExternalMediaHash (params ));
448+ hadCorrectApiHash =canProceed ;
449+ }
450+ }
451+ if (!canProceed ){ // Only download attachments for logged-in users. Prevents crawlers from causing unnecessary churn in the media cache
438452 if (req .queryParams ("fb" )!=null ){
439453 boolean is2x =req .queryParams ("2x" )!=null ;
440454 resp .redirect (Config .localURI (sizeType ==SizedImage .Type .AVA_SQUARE_SMALL || (is2x && sizeType ==SizedImage .Type .AVA_SQUARE_MEDIUM ) ? "/res/broken_photo_small.svg" : "/res/broken_photo.svg" ).toString ());
@@ -452,20 +466,27 @@ void updateContainerInDatabase(@NotNull DatabaseConnection conn, @NotNull Photo
452466 if (item ==null ){
453467 if (itemType ==MediaCache .ItemType .AVATAR && req .queryParams ("retrying" )==null ){
454468 try {
455- String extraParams = "" ;
469+ HashMap < String , String > params = new HashMap <>() ;
456470 if (req .queryParams ("fb" )!=null )
457- extraParams += "& fb" ;
471+ params . put ( " fb", "" ) ;
458472 if (req .queryParams ("2x" )!=null )
459- extraParams +="&2x" ;
473+ params .put ("fb" , "" );
474+ params .put ("size" , sizeType .suffix ());
475+ params .put ("format" , format .fileExtension ());
476+ params .put ("retrying" , "" );
460477 if (user !=null ){
461478 ForeignUser updatedUser =context (req ).getObjectLinkResolver ().resolve (user .activityPubID , ForeignUser .class , true , true , true );
462- resp . redirect ( Config . localURI ( "/system/downloadExternalMedia? type=user_ava&user_id=" + updatedUser . id + "&size=" + sizeType . suffix ()+ "&format=" + format . fileExtension ()+ "&retrying" + extraParams ). toString () );
463- return "" ;
479+ params . put ( " type" , "user_ava" );
480+ params . put ( "user_id" , updatedUser . id + "" ) ;
464481 }else {
465482 ForeignGroup updatedGroup =context (req ).getObjectLinkResolver ().resolve (group .activityPubID , ForeignGroup .class , true , true , true );
466- resp . redirect ( Config . localURI ( "/system/downloadExternalMedia? type=group_ava&user_id=" + updatedGroup . id + "&size=" + sizeType . suffix ()+ "&format=" + format . fileExtension ()+ "&retrying" + extraParams ). toString () );
467- return "" ;
483+ params . put ( " type" , "group_ava" );
484+ params . put ( "group_id" , updatedGroup . id + "" ) ;
468485 }
486+ if (hadCorrectApiHash )
487+ params .put ("api" , ApiUtils .getExternalMediaHash (params ));
488+ resp .redirect ("/system/downloadExternalMedia?" +params .entrySet ().stream ().map (e ->e .getKey ()+"=" +URLEncoder .encode (e .getValue (), StandardCharsets .UTF_8 )).collect (Collectors .joining ("&" )));
489+ return "" ;
469490 }catch (ObjectNotFoundException ignore ){}
470491 }
471492 LOG .debug ("downloadExternalMedia: all attempts failed for {}" , uri );
0 commit comments