Browse Source

/site API endpoint now tales a signature rather than a file hash

This allows it to verify that the data in a transaction, after which it will then build the complete file from its chunks if needed.
qdn
CalDescent 3 years ago
parent
commit
f2feb12708
  1. 69
      src/main/java/org/qortal/api/resource/WebsiteResource.java

69
src/main/java/org/qortal/api/resource/WebsiteResource.java

@ -10,6 +10,7 @@ import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import io.swagger.v3.oas.annotations.Operation;
@ -38,6 +39,7 @@ import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager;
import org.qortal.settings.Settings;
import org.qortal.storage.DataFile;
import org.qortal.storage.DataFileChunk;
import org.qortal.transaction.ArbitraryTransaction;
import org.qortal.transaction.Transaction;
import org.qortal.transform.TransformationException;
@ -263,22 +265,48 @@ public class WebsiteResource {
if (!Files.exists(Paths.get(unzippedPath))) {
// Load file
DataFile dataFile = DataFile.fromHash58(resourceId);
if (dataFile == null || !dataFile.exists()) {
LOGGER.info("Unable to validate complete file hash");
return this.get404Response();
}
// Load the full transaction data so we can access the file hashes
try (final Repository repository = RepositoryManager.getRepository()) {
if (!dataFile.digest58().equals(resourceId)) {
LOGGER.info("Unable to validate complete file hash");
return this.get404Response();
}
ArbitraryTransactionData transactionData = (ArbitraryTransactionData) repository.getTransactionRepository().fromSignature(Base58.decode(resourceId));
if (!(transactionData instanceof ArbitraryTransactionData)) {
return this.get404Response();
}
// Load hashes
byte[] digest = transactionData.getData();
byte[] chunkHashes = transactionData.getChunkHashes();
// Load data file(s)
DataFile dataFile = DataFile.fromDigest(digest);
if (!dataFile.exists()) {
if (!dataFile.allChunksExist(chunkHashes)) {
// TODO: fetch them?
return this.get404Response();
}
// We have all the chunks but not the complete file, so join them
dataFile.addChunkHashes(chunkHashes);
dataFile.join();
}
// If the complete file still doesn't exist then something went wrong
if (!dataFile.exists()) {
return this.get404Response();
}
if (!Arrays.equals(dataFile.digest(), digest)) {
LOGGER.info("Unable to validate complete file hash");
return this.get404Response();
}
try {
ZipUtils.unzip(dataFile.getFilePath(), destPath);
} catch (IOException e) {
LOGGER.info("Unable to unzip file");
try {
ZipUtils.unzip(dataFile.getFilePath(), destPath);
} catch (IOException e) {
LOGGER.info("Unable to unzip file");
}
} catch (DataException e) {
return this.get500Response();
}
}
@ -343,6 +371,19 @@ public class WebsiteResource {
return response;
}
private HttpServletResponse get500Response() {
try {
String responseString = "500: Internal Server Error";
byte[] responseData = responseString.getBytes();
response.setStatus(500);
response.setContentLength(responseData.length);
response.getOutputStream().write(responseData);
} catch (IOException e) {
LOGGER.info("Error writing 500 response");
}
return response;
}
/**
* Find relative links and prefix them with the resource ID, using Jsoup
* @param path

Loading…
Cancel
Save