@@ -1259,7 +1259,7 @@ public void testSignUrlLeadingSlash() throws NoSuchAlgorithmException, InvalidKe
12591259 storage = options .toBuilder ().authCredentials (authCredentials ).build ().service ();
12601260 URL url =
12611261 storage .signUrl (BlobInfo .newBuilder (BUCKET_NAME1 , blobName ).build (), 14 , TimeUnit .DAYS );
1262- String escapedBlobName = UrlEscapers .urlPathSegmentEscaper ().escape (blobName );
1262+ String escapedBlobName = UrlEscapers .urlFragmentEscaper ().escape (blobName );
12631263 String stringUrl = url .toString ();
12641264 String expectedUrl = new StringBuilder ("https://storage.googleapis.com/" ).append (BUCKET_NAME1 )
12651265 .append (escapedBlobName ).append ("?GoogleAccessId=" ).append (ACCOUNT ).append ("&Expires=" )
@@ -1323,7 +1323,8 @@ public void testSignUrlForBlobWithSpecialChars() throws NoSuchAlgorithmException
13231323 String blobName = "/a" + specialChar + "b" ;
13241324 URL url =
13251325 storage .signUrl (BlobInfo .newBuilder (BUCKET_NAME1 , blobName ).build (), 14 , TimeUnit .DAYS );
1326- String escapedBlobName = UrlEscapers .urlPathSegmentEscaper ().escape (blobName );
1326+ String escapedBlobName =
1327+ UrlEscapers .urlFragmentEscaper ().escape (blobName ).replace ("?" , "%3F" );
13271328 String stringUrl = url .toString ();
13281329 String expectedUrl = new StringBuilder ("https://storage.googleapis.com/" ).append (BUCKET_NAME1 )
13291330 .append (escapedBlobName ).append ("?GoogleAccessId=" ).append (ACCOUNT ).append ("&Expires=" )
@@ -1343,6 +1344,36 @@ public void testSignUrlForBlobWithSpecialChars() throws NoSuchAlgorithmException
13431344 }
13441345 }
13451346
1347+ @ Test
1348+ public void testSignUrlForBlobWithSlashes () throws NoSuchAlgorithmException ,
1349+ InvalidKeyException , SignatureException , UnsupportedEncodingException {
1350+ EasyMock .replay (storageRpcMock );
1351+ ServiceAccountAuthCredentials authCredentials =
1352+ ServiceAccountAuthCredentials .createFor (ACCOUNT , privateKey );
1353+ storage = options .toBuilder ().authCredentials (authCredentials ).build ().service ();
1354+
1355+ String blobName = "/foo/bar/baz #%20other cool stuff.txt" ;
1356+ URL url =
1357+ storage .signUrl (BlobInfo .newBuilder (BUCKET_NAME1 , blobName ).build (), 14 , TimeUnit .DAYS );
1358+ String escapedBlobName = UrlEscapers .urlFragmentEscaper ().escape (blobName );
1359+ String stringUrl = url .toString ();
1360+ String expectedUrl = new StringBuilder ("https://storage.googleapis.com/" ).append (BUCKET_NAME1 )
1361+ .append (escapedBlobName ).append ("?GoogleAccessId=" ).append (ACCOUNT ).append ("&Expires=" )
1362+ .append (42L + 1209600 ).append ("&Signature=" ).toString ();
1363+ assertTrue (stringUrl .startsWith (expectedUrl ));
1364+ String signature = stringUrl .substring (expectedUrl .length ());
1365+
1366+ StringBuilder signedMessageBuilder = new StringBuilder ();
1367+ signedMessageBuilder .append (HttpMethod .GET ).append ("\n \n \n " ).append (42L + 1209600 )
1368+ .append ("\n /" ).append (BUCKET_NAME1 ).append (escapedBlobName );
1369+
1370+ Signature signer = Signature .getInstance ("SHA256withRSA" );
1371+ signer .initVerify (publicKey );
1372+ signer .update (signedMessageBuilder .toString ().getBytes (UTF_8 ));
1373+ assertTrue (signer .verify (BaseEncoding .base64 ().decode (
1374+ URLDecoder .decode (signature , UTF_8 .name ()))));
1375+ }
1376+
13461377 @ Test
13471378 public void testGetAllArray () {
13481379 BlobId blobId1 = BlobId .of (BUCKET_NAME1 , BLOB_NAME1 );
0 commit comments