forked from Qortal/qortal
Merge branch 'Qortal:master' into master
This commit is contained in:
commit
ff7a87ab18
@ -16,7 +16,9 @@ import javax.ws.rs.core.Context;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.ConnectException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.ProtocolException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
|
||||||
@ -44,16 +46,6 @@ public class DevProxyServerResource {
|
|||||||
try {
|
try {
|
||||||
String source = DevProxyManager.getInstance().getSourceHostAndPort();
|
String source = DevProxyManager.getInstance().getSourceHostAndPort();
|
||||||
|
|
||||||
// Convert localhost / 127.0.0.1 to IPv6 [::1]
|
|
||||||
if (source.startsWith("localhost") || source.startsWith("127.0.0.1")) {
|
|
||||||
int port = 80;
|
|
||||||
String[] parts = source.split(":");
|
|
||||||
if (parts.length > 1) {
|
|
||||||
port = Integer.parseInt(parts[1]);
|
|
||||||
}
|
|
||||||
source = String.format("[::1]:%d", port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!inPath.startsWith("/")) {
|
if (!inPath.startsWith("/")) {
|
||||||
inPath = "/" + inPath;
|
inPath = "/" + inPath;
|
||||||
}
|
}
|
||||||
@ -61,76 +53,37 @@ public class DevProxyServerResource {
|
|||||||
String queryString = request.getQueryString() != null ? "?" + request.getQueryString() : "";
|
String queryString = request.getQueryString() != null ? "?" + request.getQueryString() : "";
|
||||||
|
|
||||||
// Open URL
|
// Open URL
|
||||||
String urlString = String.format("http://%s%s%s", source, inPath, queryString);
|
URL url = new URL(String.format("http://%s%s%s", source, inPath, queryString));
|
||||||
URL url = new URL(urlString);
|
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
|
||||||
con.setRequestMethod(request.getMethod());
|
|
||||||
|
|
||||||
// Proxy the request headers
|
// Proxy the request data
|
||||||
Enumeration<String> headerNames = request.getHeaderNames();
|
this.proxyRequestToConnection(request, con);
|
||||||
while (headerNames.hasMoreElements()) {
|
|
||||||
String headerName = headerNames.nextElement();
|
try {
|
||||||
String headerValue = request.getHeader(headerName);
|
// Make the request and proxy the response code
|
||||||
con.setRequestProperty(headerName, headerValue);
|
response.setStatus(con.getResponseCode());
|
||||||
}
|
}
|
||||||
|
catch (ConnectException e) {
|
||||||
|
|
||||||
// TODO: proxy any POST parameters from "request" to "con"
|
// Tey converting localhost / 127.0.0.1 to IPv6 [::1]
|
||||||
|
if (source.startsWith("localhost") || source.startsWith("127.0.0.1")) {
|
||||||
// Proxy the response code
|
int port = 80;
|
||||||
int responseCode = con.getResponseCode();
|
String[] parts = source.split(":");
|
||||||
response.setStatus(responseCode);
|
if (parts.length > 1) {
|
||||||
|
port = Integer.parseInt(parts[1]);
|
||||||
// Proxy the response headers
|
}
|
||||||
for (int i = 0; ; i++) {
|
source = String.format("[::1]:%d", port);
|
||||||
String headerKey = con.getHeaderFieldKey(i);
|
|
||||||
String headerValue = con.getHeaderField(i);
|
|
||||||
if (headerKey != null && headerValue != null) {
|
|
||||||
response.addHeader(headerKey, headerValue);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
// Retry connection
|
||||||
|
url = new URL(String.format("http://%s%s%s", source, inPath, queryString));
|
||||||
|
con = (HttpURLConnection) url.openConnection();
|
||||||
|
this.proxyRequestToConnection(request, con);
|
||||||
|
response.setStatus(con.getResponseCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the response body
|
// Proxy the response data back to the caller
|
||||||
InputStream inputStream = con.getInputStream();
|
this.proxyConnectionToResponse(con, response, inPath);
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
byte[] buffer = new byte[4096];
|
|
||||||
int bytesRead;
|
|
||||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
|
||||||
outputStream.write(buffer, 0, bytesRead);
|
|
||||||
}
|
|
||||||
byte[] data = outputStream.toByteArray(); // TODO: limit file size that can be read into memory
|
|
||||||
|
|
||||||
// Close the streams
|
|
||||||
outputStream.close();
|
|
||||||
inputStream.close();
|
|
||||||
|
|
||||||
// Extract filename
|
|
||||||
String filename = "";
|
|
||||||
if (inPath.contains("/")) {
|
|
||||||
String[] parts = inPath.split("/");
|
|
||||||
if (parts.length > 0) {
|
|
||||||
filename = parts[parts.length - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse and modify output if needed
|
|
||||||
if (HTMLParser.isHtmlFile(filename)) {
|
|
||||||
// HTML file - needs to be parsed
|
|
||||||
HTMLParser htmlParser = new HTMLParser("", inPath, "", false, data, "proxy", Service.APP, null, "light", true);
|
|
||||||
htmlParser.addAdditionalHeaderTags();
|
|
||||||
response.addHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline' 'unsafe-eval'; media-src 'self' data: blob:; img-src 'self' data: blob:; connect-src 'self' ws:; font-src 'self' data:;");
|
|
||||||
response.setContentType(con.getContentType());
|
|
||||||
response.setContentLength(htmlParser.getData().length);
|
|
||||||
response.getOutputStream().write(htmlParser.getData());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Regular file - can be streamed directly
|
|
||||||
response.addHeader("Content-Security-Policy", "default-src 'self'");
|
|
||||||
response.setContentType(con.getContentType());
|
|
||||||
response.setContentLength(data.length);
|
|
||||||
response.getOutputStream().write(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, e.getMessage());
|
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, e.getMessage());
|
||||||
@ -139,4 +92,73 @@ public class DevProxyServerResource {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void proxyRequestToConnection(HttpServletRequest request, HttpURLConnection con) throws ProtocolException {
|
||||||
|
// Proxy the request method
|
||||||
|
con.setRequestMethod(request.getMethod());
|
||||||
|
|
||||||
|
// Proxy the request headers
|
||||||
|
Enumeration<String> headerNames = request.getHeaderNames();
|
||||||
|
while (headerNames.hasMoreElements()) {
|
||||||
|
String headerName = headerNames.nextElement();
|
||||||
|
String headerValue = request.getHeader(headerName);
|
||||||
|
con.setRequestProperty(headerName, headerValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: proxy any POST parameters from "request" to "con"
|
||||||
|
}
|
||||||
|
|
||||||
|
private void proxyConnectionToResponse(HttpURLConnection con, HttpServletResponse response, String inPath) throws IOException {
|
||||||
|
// Proxy the response headers
|
||||||
|
for (int i = 0; ; i++) {
|
||||||
|
String headerKey = con.getHeaderFieldKey(i);
|
||||||
|
String headerValue = con.getHeaderField(i);
|
||||||
|
if (headerKey != null && headerValue != null) {
|
||||||
|
response.addHeader(headerKey, headerValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the response body
|
||||||
|
InputStream inputStream = con.getInputStream();
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
byte[] data = outputStream.toByteArray(); // TODO: limit file size that can be read into memory
|
||||||
|
|
||||||
|
// Close the streams
|
||||||
|
outputStream.close();
|
||||||
|
inputStream.close();
|
||||||
|
|
||||||
|
// Extract filename
|
||||||
|
String filename = "";
|
||||||
|
if (inPath.contains("/")) {
|
||||||
|
String[] parts = inPath.split("/");
|
||||||
|
if (parts.length > 0) {
|
||||||
|
filename = parts[parts.length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse and modify output if needed
|
||||||
|
if (HTMLParser.isHtmlFile(filename)) {
|
||||||
|
// HTML file - needs to be parsed
|
||||||
|
HTMLParser htmlParser = new HTMLParser("", inPath, "", false, data, "proxy", Service.APP, null, "light", true);
|
||||||
|
htmlParser.addAdditionalHeaderTags();
|
||||||
|
response.addHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline' 'unsafe-eval'; media-src 'self' data: blob:; img-src 'self' data: blob:; connect-src 'self' ws:; font-src 'self' data:;");
|
||||||
|
response.setContentType(con.getContentType());
|
||||||
|
response.setContentLength(htmlParser.getData().length);
|
||||||
|
response.getOutputStream().write(htmlParser.getData());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Regular file - can be streamed directly
|
||||||
|
response.addHeader("Content-Security-Policy", "default-src 'self'");
|
||||||
|
response.setContentType(con.getContentType());
|
||||||
|
response.setContentLength(data.length);
|
||||||
|
response.getOutputStream().write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -743,8 +743,14 @@ public class OnlineAccountsManager {
|
|||||||
if (onlineAccounts == null)
|
if (onlineAccounts == null)
|
||||||
onlineAccounts = this.latestBlocksOnlineAccounts.get(timestamp);
|
onlineAccounts = this.latestBlocksOnlineAccounts.get(timestamp);
|
||||||
|
|
||||||
if (onlineAccounts != null)
|
if (onlineAccounts != null) {
|
||||||
blocksOnlineAccounts.removeAll(onlineAccounts);
|
// Remove accounts with matching timestamp, nonce, and public key
|
||||||
|
final Set<OnlineAccountData> finalOnlineAccounts = onlineAccounts;
|
||||||
|
blocksOnlineAccounts.removeIf(a1 -> finalOnlineAccounts.stream()
|
||||||
|
.anyMatch(a2 -> a2.getTimestamp() == a1.getTimestamp() &&
|
||||||
|
Objects.equals(a2.getNonce(), a1.getNonce()) &&
|
||||||
|
Arrays.equals(a2.getPublicKey(), a1.getPublicKey())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +25,8 @@ public class NamesDatabaseIntegrityCheck {
|
|||||||
TransactionType.REGISTER_NAME,
|
TransactionType.REGISTER_NAME,
|
||||||
TransactionType.UPDATE_NAME,
|
TransactionType.UPDATE_NAME,
|
||||||
TransactionType.BUY_NAME,
|
TransactionType.BUY_NAME,
|
||||||
TransactionType.SELL_NAME
|
TransactionType.SELL_NAME,
|
||||||
|
TransactionType.CANCEL_SELL_NAME
|
||||||
);
|
);
|
||||||
|
|
||||||
private List<TransactionData> nameTransactions = new ArrayList<>();
|
private List<TransactionData> nameTransactions = new ArrayList<>();
|
||||||
|
Loading…
Reference in New Issue
Block a user