Skip to content

Commit f5f84bb

Browse files
committed
SLING-7402 - Sling Server Icon is all red
Read the file names from the zip archive instead of assuming the order is the same as the one in the signing request.
1 parent 52df805 commit f5f84bb

File tree

1 file changed

+87
-73
lines changed

1 file changed

+87
-73
lines changed

codesign/src/main/java/org/apache/tomcat/buildutil/SignCodeMojo.java

Lines changed: 87 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
import java.net.MalformedURLException;
2626
import java.net.URL;
2727
import java.util.ArrayList;
28+
import java.util.HashMap;
2829
import java.util.List;
30+
import java.util.Map;
2931
import java.util.zip.ZipEntry;
3032
import java.util.zip.ZipInputStream;
3133
import java.util.zip.ZipOutputStream;
@@ -199,9 +201,11 @@ public void execute() throws MojoExecutionException {
199201
oldSslDebug = System.setProperty("javax.net.debug","all");
200202
}
201203

204+
SignedFiles signedFiles = new SignedFiles(filesToSign);
205+
202206
try {
203-
String signingSetID = makeSigningRequest(filesToSign);
204-
downloadSignedFiles(filesToSign, signingSetID);
207+
String signingSetID = makeSigningRequest(signedFiles);
208+
downloadSignedFiles(signedFiles, signingSetID);
205209
} catch (SOAPException | IOException e) {
206210
throw new MojoExecutionException("Signing failed : " + e.getMessage(), e);
207211
} finally {
@@ -216,7 +220,7 @@ public void execute() throws MojoExecutionException {
216220
}
217221

218222

219-
private String makeSigningRequest(List<File> filesToSign) throws SOAPException, IOException, MojoExecutionException {
223+
private String makeSigningRequest(SignedFiles signedFiles) throws SOAPException, IOException, MojoExecutionException {
220224
log("Constructing the code signing request");
221225

222226
SOAPMessage message = SOAP_MSG_FACTORY.createMessage();
@@ -240,15 +244,13 @@ private String makeSigningRequest(List<File> filesToSign) throws SOAPException,
240244
requestSigningRequest.addChildElement("signingServiceName", NS);
241245
signingServiceName.addTextNode(this.signingService);
242246

243-
List<String> fileNames = getFileNames(filesToSign);
244-
245247
SOAPElement commaDelimitedFileNames =
246248
requestSigningRequest.addChildElement("commaDelimitedFileNames", NS);
247-
commaDelimitedFileNames.addTextNode(StringUtils.join(fileNames.iterator(), ","));
249+
commaDelimitedFileNames.addTextNode(signedFiles.getCommaSeparatedUploadFileNames());
248250

249251
SOAPElement application =
250252
requestSigningRequest.addChildElement("application", NS);
251-
application.addTextNode(getApplicationString(fileNames, filesToSign));
253+
application.addTextNode(signedFiles.getApplicationString());
252254

253255
// Send the message
254256
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
@@ -332,7 +334,7 @@ public BuildException(String message) {
332334

333335
}
334336

335-
private void downloadSignedFiles(List<File> filesToSign, String id)
337+
private void downloadSignedFiles(SignedFiles signedFiles, String id)
336338
throws SOAPException, IOException, BuildException {
337339

338340
log("Downloading signed files. The signing set ID is: " + id);
@@ -387,7 +389,7 @@ private void downloadSignedFiles(List<File> filesToSign, String id)
387389
throw new BuildException("Download failed. Result code was: " + result);
388390
}
389391

390-
extractFilesFromApplicationString(data, filesToSign);
392+
signedFiles.extractFilesFromApplicationString(data);
391393
}
392394

393395

@@ -415,80 +417,92 @@ private static void addCredentials(SOAPElement requestSigningRequest,
415417
}
416418

417419

418-
/**
419-
* Signing service requires unique files names. Since files will be returned
420-
* in order, use dummy names that we know are unique but retain the file
421-
* extension since the signing service appears to use it to figure out what
422-
* to sign and how to sign it.
423-
*/
424-
private static List<String> getFileNames(List<File> filesToSign) {
425-
List<String> result = new ArrayList<>(filesToSign.size());
426-
427-
for (int i = 0; i < filesToSign.size(); i++) {
428-
File f = filesToSign.get(i);
429-
String fileName = f.getName();
430-
int extIndex = fileName.lastIndexOf('.');
431-
String newName;
432-
if (extIndex < 0) {
433-
newName = Integer.toString(i);
434-
} else {
435-
newName = Integer.toString(i) + fileName.substring(extIndex);
436-
}
437-
result.add(newName);
438-
}
439-
return result;
440-
}
441-
442420

443421
/**
444-
* Zips the files, base 64 encodes the resulting zip and then returns the
445-
* string. It would be far more efficient to stream this directly to the
446-
* signing server but the files that need to be signed are relatively small
447-
* and this simpler to write.
422+
* Ensures that unique file names are sent to the signing service
423+
*
424+
* <p>We can't rely on the order in which we set the file names in the signing request, since
425+
* that is not preserved in the zipped response.</p>
426+
*
427+
* <p>The file extension is kept since the signing service appears to use it to figure out what
428+
* to sign and how to sign it.</p>
448429
*
449-
* @param fileNames Modified names of files
450-
* @param files Files to be signed
451430
*/
452-
private static String getApplicationString(List<String> fileNames, List<File> files)
453-
throws IOException {
454-
// 16 MB should be more than enough for Tomcat
455-
// TODO: Refactoring this entire class so it uses streaming rather than
456-
// buffering the entire set of files in memory would make it more
457-
// widely useful.
458-
ByteArrayOutputStream baos = new ByteArrayOutputStream(16 * 1024 * 1024);
459-
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
460-
byte[] buf = new byte[32 * 1024];
461-
for (int i = 0; i < files.size(); i++) {
462-
try (FileInputStream fis = new FileInputStream(files.get(i))) {
463-
ZipEntry zipEntry = new ZipEntry(fileNames.get(i));
464-
zos.putNextEntry(zipEntry);
465-
int numRead;
466-
while ( (numRead = fis.read(buf)) >= 0) {
467-
zos.write(buf, 0, numRead);
468-
}
431+
static class SignedFiles {
432+
433+
private Map<String, File> fileNameMapping = new HashMap<>();
434+
435+
public SignedFiles(List<File> filesToSign) {
436+
for (int i = 0; i < filesToSign.size(); i++) {
437+
File f = filesToSign.get(i);
438+
String fileName = f.getName();
439+
int extIndex = fileName.lastIndexOf('.');
440+
String newName;
441+
if (extIndex < 0) {
442+
newName = Integer.toString(i);
443+
} else {
444+
newName = Integer.toString(i) + fileName.substring(extIndex);
469445
}
446+
447+
fileNameMapping.put(newName, f);
470448
}
471449
}
450+
451+
public String getCommaSeparatedUploadFileNames() {
452+
453+
return StringUtils.join(fileNameMapping.keySet().iterator(), ",");
454+
}
472455

473-
return new String(Base64.encodeBase64(baos.toByteArray()), "UTF-8");
474-
}
456+
/**
457+
* Zips the files, base 64 encodes the resulting zip and then returns the
458+
* string. It would be far more efficient to stream this directly to the
459+
* signing server but the files that need to be signed are relatively small
460+
* and this simpler to write.
461+
*
462+
* @throws IOException in case of any IO problems
463+
*
464+
*/
465+
public String getApplicationString() throws IOException {
466+
467+
// 16 MB should be more than enough for Tomcat
468+
// TODO: Refactoring this entire class so it uses streaming rather than
469+
// buffering the entire set of files in memory would make it more
470+
// widely useful.
471+
ByteArrayOutputStream baos = new ByteArrayOutputStream(16 * 1024 * 1024);
472+
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
473+
byte[] buf = new byte[32 * 1024];
474+
for ( Map.Entry<String, File> entry : fileNameMapping.entrySet() ) {
475+
try (FileInputStream fis = new FileInputStream(entry.getValue())) {
476+
ZipEntry zipEntry = new ZipEntry(entry.getKey());
477+
zos.putNextEntry(zipEntry);
478+
int numRead;
479+
while ( (numRead = fis.read(buf)) >= 0) {
480+
zos.write(buf, 0, numRead);
481+
}
482+
}
483+
}
484+
}
475485

486+
return new String(Base64.encodeBase64(baos.toByteArray()), "UTF-8");
487+
}
476488

477-
/**
478-
* Removes base64 encoding, unzips the files and writes the new files over
479-
* the top of the old ones.
480-
*/
481-
private static void extractFilesFromApplicationString(String data, List<File> files)
482-
throws IOException {
483-
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decodeBase64(data.getBytes("UTF-8")));
484-
try (ZipInputStream zis = new ZipInputStream(bais)) {
485-
byte[] buf = new byte[32 * 1024];
486-
for (int i = 0; i < files.size(); i ++) {
487-
try (FileOutputStream fos = new FileOutputStream(files.get(i))) {
488-
zis.getNextEntry();
489-
int numRead;
490-
while ( (numRead = zis.read(buf)) >= 0) {
491-
fos.write(buf, 0 , numRead);
489+
/**
490+
* Removes base64 encoding, unzips the files and writes the new files over
491+
* the top of the old ones.
492+
*/
493+
public void extractFilesFromApplicationString(String data) throws IOException {
494+
495+
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decodeBase64(data.getBytes("UTF-8")));
496+
try (ZipInputStream zis = new ZipInputStream(bais)) {
497+
byte[] buf = new byte[32 * 1024];
498+
ZipEntry entry;
499+
while ((entry = zis.getNextEntry()) != null) {
500+
File outFile = fileNameMapping.get(entry.getName());
501+
try (FileOutputStream fos = new FileOutputStream(outFile)) {
502+
int numRead;
503+
while ((numRead = zis.read(buf)) >= 0) {
504+
fos.write(buf, 0, numRead);
505+
}
492506
}
493507
}
494508
}

0 commit comments

Comments
 (0)