added comments and clean up
This commit is contained in:
@@ -13,5 +13,5 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
public class BaseScanResponse {
|
||||
private QRCode scannedQRCode;
|
||||
private QRCodeType qrCodeType;
|
||||
private QRCodeType qrCode;
|
||||
}
|
||||
|
||||
@@ -10,5 +10,5 @@ import lombok.experimental.SuperBuilder;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public final class URLResponse extends BaseScanResponse{
|
||||
private QRCodeURL qrCodeURL;
|
||||
private QRCodeURL details;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.UuidGenerator;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
@@ -21,15 +21,16 @@ import java.util.UUID;
|
||||
public class QRCode {
|
||||
|
||||
@Id
|
||||
@JsonIgnore
|
||||
@GeneratedValue(generator = "UUID")
|
||||
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
|
||||
@UuidGenerator
|
||||
@Column(updatable = false, nullable = false)
|
||||
private UUID id;
|
||||
|
||||
@JsonIgnore
|
||||
@Column(name = "qr_code_type_id", nullable = false)
|
||||
private Long qrCodeTypeId;
|
||||
|
||||
@JsonIgnore
|
||||
private String userId;
|
||||
private String contents;
|
||||
|
||||
|
||||
@@ -7,10 +7,9 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.UuidGenerator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@@ -20,11 +19,10 @@ import java.util.UUID;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class QRCodeURL {
|
||||
|
||||
@Id
|
||||
@JsonIgnore
|
||||
@GeneratedValue(generator = "UUID")
|
||||
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
|
||||
@UuidGenerator
|
||||
@Column(updatable = false, nullable = false)
|
||||
private UUID id;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import reactor.core.publisher.Mono;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
@@ -44,6 +45,9 @@ public class QRCodeTypeService {
|
||||
@Autowired
|
||||
private URLRepository urlRepository;
|
||||
|
||||
|
||||
@Autowired
|
||||
private URLVerificationService urlVerificationService;
|
||||
@Autowired
|
||||
private SafeBrowsingService safeBrowsingService;
|
||||
|
||||
@@ -98,109 +102,29 @@ public class QRCodeTypeService {
|
||||
.findFirst()
|
||||
.orElse(defaultQRCodeType);
|
||||
}
|
||||
|
||||
private BaseScanResponse insertIntoRespectiveTable(QRCode qrCode, QRCodeType qrCodeType) {
|
||||
String contents = qrCode.getContents();
|
||||
try {
|
||||
String url = qrCode.getContents();
|
||||
QRCodeURL urlObj = breakdownURL(url);
|
||||
QRCodeURL urlObj = urlVerificationService.breakdownURL(contents);
|
||||
List<String> redirectChain = urlVerificationService.countAndTrackRedirects(contents);
|
||||
urlObj.setQrCodeId(qrCode.getId());
|
||||
List<String> redirectChain = countAndTrackRedirects(url);
|
||||
logger.info("Redirect chain: {}", redirectChain);
|
||||
for (int i = 0; i < redirectChain.size(); i++) {
|
||||
logger.info((i == 0 ? "Initial URL: " : "Redirect #" + i + ": ") + redirectChain.get(i));
|
||||
}
|
||||
urlObj.setRedirect(redirectChain.size() - 1);
|
||||
urlObj.setRedirectChain(redirectChain);
|
||||
|
||||
// Insert into URL table
|
||||
urlRepository.save(urlObj);
|
||||
|
||||
return URLResponse.builder()
|
||||
.scannedQRCode(qrCode)
|
||||
.qrCodeType(qrCodeType)
|
||||
.qrCodeURL(urlObj)
|
||||
.build();
|
||||
} catch (IOException e) {
|
||||
return URLResponse.builder().scannedQRCode(qrCode).qrCode(qrCodeType).details(urlObj).build();
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
logger.error("Error: ", e);
|
||||
}
|
||||
|
||||
return BaseScanResponse.builder()
|
||||
.scannedQRCode(qrCode)
|
||||
.qrCodeType(qrCodeType)
|
||||
.qrCode(qrCodeType)
|
||||
.build();
|
||||
}
|
||||
// Function to breakdown URL into subdomain, domain, topLevelDomain, query params, fragment
|
||||
public QRCodeURL breakdownURL(String urlString) throws MalformedURLException {
|
||||
URL url = new URL(urlString);
|
||||
QRCodeURL urlObj = new QRCodeURL();
|
||||
|
||||
String host = url.getHost();
|
||||
String[] hostParts = host.split("\\.");
|
||||
String subdomain = "";
|
||||
|
||||
if (hostParts.length >= 2) {
|
||||
urlObj.setTopLevelDomain(hostParts[hostParts.length - 1]);
|
||||
urlObj.setDomain(hostParts[hostParts.length - 2]);
|
||||
if (hostParts.length > 2) {
|
||||
subdomain = String.join(".", java.util.Arrays.copyOfRange(hostParts, 0, hostParts.length - 2));
|
||||
}
|
||||
}
|
||||
|
||||
urlObj.setSubdomain(subdomain);
|
||||
|
||||
String path = url.getPath();
|
||||
urlObj.setPath(path.isEmpty() ? "/" : path);
|
||||
|
||||
String query = url.getQuery();
|
||||
Map<String, String> queryParams = new HashMap<>();
|
||||
if (query != null) {
|
||||
for (String param : query.split("&")) {
|
||||
String[] pair = param.split("=");
|
||||
queryParams.put(pair[0], pair.length > 1 ? pair[1] : "");
|
||||
}
|
||||
logger.info("queryParams: {}", queryParams);
|
||||
}
|
||||
urlObj.setQuery(queryParams.toString());
|
||||
|
||||
String fragment = url.getRef();
|
||||
|
||||
urlObj.setFragment(fragment);
|
||||
|
||||
return urlObj;
|
||||
}
|
||||
|
||||
List<String> countAndTrackRedirects(String urlString) throws IOException {
|
||||
URL url = new URL(urlString);
|
||||
List<String> redirectChain = new ArrayList<>();
|
||||
redirectChain.add(urlString); // Add the initial URL to the chain
|
||||
boolean redirected;
|
||||
int redirectCount = 0;
|
||||
|
||||
do {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setInstanceFollowRedirects(false);
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
redirected = (responseCode >= 300 && responseCode < 400);
|
||||
|
||||
if (redirected) {
|
||||
String newUrl = connection.getHeaderField("Location");
|
||||
if (newUrl == null) {
|
||||
break;
|
||||
}
|
||||
// Handle relative URLs
|
||||
if (!newUrl.startsWith("http://") && !newUrl.startsWith("https://")) {
|
||||
newUrl = new URL(url, newUrl).toString();
|
||||
}
|
||||
url = new URL(newUrl);
|
||||
redirectChain.add(newUrl);
|
||||
redirectCount++;
|
||||
logger.info("Redirect #{}: {}",redirectCount, newUrl);
|
||||
}
|
||||
|
||||
connection.disconnect();
|
||||
} while (redirected && redirectCount < CommonConstants.MAX_REDIRECT_COUNT);
|
||||
|
||||
return redirectChain;
|
||||
}
|
||||
|
||||
public Mono<String> detectType(QRCodePayload payload) {
|
||||
String data = payload.getData();
|
||||
|
||||
@@ -1,12 +1,107 @@
|
||||
package com.safeqr.app.qrcode.service;
|
||||
|
||||
import com.safeqr.app.constants.CommonConstants;
|
||||
import com.safeqr.app.qrcode.dto.QRCodePayload;
|
||||
import com.safeqr.app.qrcode.dto.URLVerificationResponse;
|
||||
import com.safeqr.app.qrcode.entity.QRCodeURL;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class URLVerificationService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(URLVerificationService.class);
|
||||
|
||||
// Function to breakdown URL into subdomain, domain, topLevelDomain, query params, fragment
|
||||
public QRCodeURL breakdownURL(String urlString) throws MalformedURLException, URISyntaxException {
|
||||
URI uri = new URI(urlString);
|
||||
URL url = uri.toURL();
|
||||
QRCodeURL urlObj = new QRCodeURL();
|
||||
|
||||
String host = url.getHost();
|
||||
// split host into subdomain, domain, topLevelDomain
|
||||
String[] hostParts = host.split("\\.");
|
||||
String subdomain = "";
|
||||
|
||||
if (hostParts.length >= 2) {
|
||||
// set topLevelDomain to the last part of the host
|
||||
urlObj.setTopLevelDomain(hostParts[hostParts.length - 1]);
|
||||
// set domain to the second last part of the host
|
||||
urlObj.setDomain(hostParts[hostParts.length - 2]);
|
||||
// set subdomain to the first part of the host
|
||||
if (hostParts.length > 2) {
|
||||
subdomain = String.join(".", java.util.Arrays.copyOfRange(hostParts, 0, hostParts.length - 2));
|
||||
}
|
||||
}
|
||||
// set subdomain to URL host
|
||||
urlObj.setSubdomain(subdomain);
|
||||
|
||||
String path = url.getPath();
|
||||
//set path to URL path if it's not empty, otherwise set it to root path
|
||||
urlObj.setPath(path.isEmpty() ? "/" : path);
|
||||
|
||||
String query = url.getQuery();
|
||||
Map<String, String> queryParams = new HashMap<>();
|
||||
if (query != null) {
|
||||
// split query params into key value pairs
|
||||
for (String param : query.split("&")) {
|
||||
String[] pair = param.split("=");
|
||||
queryParams.put(pair[0], pair.length > 1 ? pair[1] : "");
|
||||
}
|
||||
logger.info("queryParams: {}", queryParams);
|
||||
}
|
||||
// set query params to URL query
|
||||
urlObj.setQuery(queryParams.toString());
|
||||
// set fragment to URL ref
|
||||
urlObj.setFragment(url.getRef());
|
||||
|
||||
return urlObj;
|
||||
}
|
||||
|
||||
List<String> countAndTrackRedirects(String urlString) throws IOException, URISyntaxException {
|
||||
URI uri = new URI(urlString);
|
||||
URL url = uri.toURL();
|
||||
List<String> redirectChain = new ArrayList<>();
|
||||
|
||||
// Add the initial URL to the chain
|
||||
redirectChain.add(urlString);
|
||||
boolean redirected;
|
||||
int redirectCount = 0;
|
||||
|
||||
do {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setInstanceFollowRedirects(false);
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
redirected = (responseCode >= 300 && responseCode < 400);
|
||||
// Handle redirects
|
||||
if (redirected) {
|
||||
// Location header contains the URL to redirect to
|
||||
String newUrl = connection.getHeaderField("Location");
|
||||
if (newUrl == null) {
|
||||
break;
|
||||
}
|
||||
// Handle relative URLs
|
||||
uri = uri.resolve(newUrl);
|
||||
url = uri.toURL();
|
||||
redirectChain.add(url.toString());
|
||||
redirectCount++;
|
||||
logger.info("Redirect #{}: {}",redirectCount, newUrl);
|
||||
}
|
||||
|
||||
connection.disconnect();
|
||||
} while (redirected && redirectCount < CommonConstants.MAX_REDIRECT_COUNT);
|
||||
|
||||
return redirectChain;
|
||||
}
|
||||
public URLVerificationResponse verifyURL(QRCodePayload payload) {
|
||||
URLVerificationResponse response = new URLVerificationResponse();
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user