aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-web/src/main/java/at
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-web/src/main/java/at')
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/PdfAsWeb.java32
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/PdfAsSpringBootApplicationContextInitializer.java71
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/PdfAsWebSpringConfiguration.java18
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java217
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsSecurityLayerException.java5
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/ExceptionCatchFilter.java68
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/UserAgentFilter.java14
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java456
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsParameterExtractor.java19
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/RemotePDFFetcher.java3
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/UrlParameterExtractor.java5
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultEncoder.java4
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultHTMLEncoder.java4
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultJSONEncoder.java4
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/ExceptionFormatter.java17
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/JacksonConfig.java26
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/SignController.java37
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/SoapLogicBridgeBean.java15
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/VerifyController.java22
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java54
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java15
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java191
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java88
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java8
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureCertificateData.java13
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureData.java15
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFURLData.java10
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PlaceholderGeneratorServlet.java8
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java17
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ReloadServlet.java44
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SLDataURLServlet.java20
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SoapServiceServlet.java68
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java53
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java118
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VisBlockServlet.java9
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/JsonSecurityUtils.java18
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/SL20HttpBindingUtils.java7
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticFrontend.java39
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/impl/StatisticMicrometerBackend.java75
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java4
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java31
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/RequestStore.java8
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/FilterBridge.java52
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/ServletBridge.java107
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/WelcomeFileBridge.java12
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java54
-rw-r--r--pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASVerificationImpl.java12
47 files changed, 1238 insertions, 949 deletions
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/PdfAsWeb.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/PdfAsWeb.java
new file mode 100644
index 00000000..2324d4ea
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/PdfAsWeb.java
@@ -0,0 +1,32 @@
+package at.gv.egiz.pdfas.web;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@SpringBootApplication
+public class PdfAsWeb extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder createSpringApplicationBuilder() {
+ SpringApplicationBuilder builder = new SpringApplicationBuilder();
+ builder.sources(PdfAsWeb.class);
+ return builder;
+
+ }
+
+ public static void main(String[] args) {
+ log.info("=============== Initializing Spring-Boot context! ===============");
+ final SpringApplication springApp = new SpringApplication(PdfAsWeb.class);
+
+ log.debug("Run SpringBoot initialization process ... ");
+ springApp.run(args);
+
+ log.info("Initialization of PDF-AS-Web finished.");
+
+ }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/PdfAsSpringBootApplicationContextInitializer.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/PdfAsSpringBootApplicationContextInitializer.java
new file mode 100644
index 00000000..184030d2
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/PdfAsSpringBootApplicationContextInitializer.java
@@ -0,0 +1,71 @@
+package at.gv.egiz.pdfas.web.config;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Properties;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.PropertiesPropertySource;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class PdfAsSpringBootApplicationContextInitializer
+ implements ApplicationContextInitializer<ConfigurableApplicationContext> {
+
+ private static final String SYSTEMD_PROP_NAME = "pdf-as-web.conf";
+ private static final String FILE_PREFIX = "file:";
+
+ @Override
+ public void initialize(ConfigurableApplicationContext applicationContext) {
+ final String rawConfigPath = System.getProperty(SYSTEMD_PROP_NAME);
+
+ if (StringUtils.isBlank(rawConfigPath)) {
+ log.info("No SystemD property '{}' found. No external configuration loaded.", SYSTEMD_PROP_NAME);
+ return;
+ }
+
+ log.debug("Found configuration source from SystemD property '{}'.", SYSTEMD_PROP_NAME);
+
+ final String configPath = stripFilePrefix(rawConfigPath);
+ injectConfiguration(Path.of(configPath), applicationContext);
+ }
+
+ private static String stripFilePrefix(String configPath) {
+ return configPath.startsWith(FILE_PREFIX)
+ ? configPath.substring(FILE_PREFIX.length())
+ : configPath;
+ }
+
+ private void injectConfiguration(
+ Path configPath,
+ ConfigurableApplicationContext applicationContext) {
+
+ if (!Files.isRegularFile(configPath)) {
+ log.error("Configuration from SystemD property '{}' does not exist or is not a file: {}",
+ SYSTEMD_PROP_NAME, configPath);
+ return;
+ }
+
+ try (InputStream inputStream = Files.newInputStream(configPath)) {
+ final Properties properties = new Properties();
+ properties.load(inputStream);
+
+ applicationContext
+ .getEnvironment()
+ .getPropertySources()
+ .addFirst(new PropertiesPropertySource(SYSTEMD_PROP_NAME, properties));
+
+ log.info("Loaded configuration source from SystemD property '{}': {}",
+ SYSTEMD_PROP_NAME, configPath);
+
+ } catch (IOException e) {
+ log.error("Configuration from SystemD property '{}' at location '{}' cannot be loaded.",
+ SYSTEMD_PROP_NAME, configPath, e);
+ }
+ }
+} \ No newline at end of file
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/PdfAsWebSpringConfiguration.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/PdfAsWebSpringConfiguration.java
new file mode 100644
index 00000000..2a64307a
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/PdfAsWebSpringConfiguration.java
@@ -0,0 +1,18 @@
+package at.gv.egiz.pdfas.web.config;
+
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+@Component
+@Slf4j
+public class PdfAsWebSpringConfiguration {
+ /** path to pdf-as-web.properties as loaded from spring sources */
+ @Value("${pdf-as-web.conf}")
+ @Getter
+ @NonNull String pdfAsWebConfPath;
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java
index 7177541c..f781b258 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java
@@ -25,6 +25,7 @@ package at.gv.egiz.pdfas.web.config;
import java.io.File;
import java.io.FileInputStream;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -67,6 +68,7 @@ public class WebConfiguration implements IConfigurationConstants {
public static final String MOA_LIST = "moal";
public static final String MOA_URL = "url";
+ public static final String MOA_TIMEOUT = "timeout";
public static final String MOA_KEYID = "KeyIdentifier";
public static final String MOA_CERT = "Certificate";
@@ -115,7 +117,7 @@ public class WebConfiguration implements IConfigurationConstants {
public static final String UPLOAD_FILESIZE_THRESHOLD = "web.upload.filesizeThreshold";
public static final String UPLOAD_MAX_FILESIZE = "web.upload.filesizeMax";
- public static final String UPLOAD_MAX_REQUESTSIZE = "web.upload.RequestsizeMax";
+ public static final String UPLOAD_MAX_REQUESTSIZE = "web.upload.requestsizeMax";
public static final String PLACEHOLDER_GENERATOR_ENABLED = "qr.placeholder.generator.enabled";
@@ -123,32 +125,62 @@ public class WebConfiguration implements IConfigurationConstants {
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB
- private static Properties properties = new Properties();
- private static Properties hibernateProps = new Properties();
+ private static final Properties properties = new Properties();
+ private static final Properties hibernateProps = new Properties();
private static final Logger logger = LoggerFactory
.getLogger(WebConfiguration.class);
- private static List<String> whiteListregEx = new ArrayList<String>();
- private static List<String> overwritewhiteListregEx = new ArrayList<String>();
+ private static final List<String> whiteListregEx = new ArrayList<String>();
+ private static final List<String> overwritewhiteListregEx = new ArrayList<String>();
+
+ public static void configure(String configFile) {
+ try (InputStream is = new FileInputStream(configFile)) {
+ logger.info("Loading PDF-AS Web configuration from '{}'...", configFile);
+ configure(is);
+ } catch (Exception e) {
+ logger.error("Failed to load configuration {}", configFile, e);
+ if (e instanceof RuntimeException ex)
+ throw ex;
+ else
+ throw new RuntimeException(e);
+ }
+ }
- public static void configure(String config) {
+ public static void configure(InputStream config) {
properties.clear();
+ hibernateProps.clear();
whiteListregEx.clear();
overwritewhiteListregEx.clear();
try {
- properties.load(new FileInputStream(config));
+ properties.load(config);
} catch (Exception e) {
- logger.error("Failed to load configuration: " + e.getMessage());
+ logger.error("Failed to load configuration.", e);
throw new RuntimeException(e);
}
+ { // validate
+ if (properties.isEmpty()) {
+ logger.error("No properties were loaded from web configuration. You likely did not specify `pdf-as-web.conf` correctly.");
+ throw new RuntimeException("No properties were loaded from the web configuration. Check if you specified `pdf-as-web.conf` correctly.");
+ }
+ String pdfASDir = getPdfASDir();
+ if (pdfASDir == null) {
+ logger.error("Please configure the PDF-AS working directory in the web configuration");
+ throw new RuntimeException(
+ "Please configure PDF-AS working directory in the web configuration");
+ }
+ File f = new File(pdfASDir);
+ if (!f.exists() || !f.isDirectory()) {
+ logger.error("PDF-AS working directory does not exist or is not a directory!: {}", pdfASDir);
+ throw new RuntimeException("PDF-AS working directory does not exists or is not a directory!");
+ }
+ }
+
if (isWhiteListEnabled()) {
- Iterator<Object> keyIt = properties.keySet().iterator();
- while (keyIt.hasNext()) {
- Object keyObj = keyIt.next();
+ for (Object keyObj : properties.keySet()) {
if (keyObj != null) {
String key = keyObj.toString();
if (key.startsWith(WHITELIST_VALUE_PRE)) {
@@ -163,9 +195,7 @@ public class WebConfiguration implements IConfigurationConstants {
}
if (isAllowExtOverwrite()) {
- Iterator<Object> keyIt = properties.keySet().iterator();
- while (keyIt.hasNext()) {
- Object keyObj = keyIt.next();
+ for (Object keyObj : properties.keySet()) {
if (keyObj != null) {
String key = keyObj.toString();
if (key.startsWith(ALLOW_EXT_WHITELIST_VALUE_PRE)) {
@@ -179,9 +209,7 @@ public class WebConfiguration implements IConfigurationConstants {
}
}
- Iterator<Object> keyIt = properties.keySet().iterator();
- while (keyIt.hasNext()) {
- Object keyObj = keyIt.next();
+ for (Object keyObj : properties.keySet()) {
if (keyObj != null) {
String key = keyObj.toString();
if (key.startsWith(HIBERNATE_PREFIX)) {
@@ -196,9 +224,7 @@ public class WebConfiguration implements IConfigurationConstants {
if (hibernateProps.size() != 0) {
logger.debug("DB Properties: ");
- Iterator<Object> hibkeyIt = hibernateProps.keySet().iterator();
- while (hibkeyIt.hasNext()) {
- Object keyObj = hibkeyIt.next();
+ for (Object keyObj : hibernateProps.keySet()) {
if (keyObj != null) {
String key = keyObj.toString();
String value = hibernateProps.getProperty(key);
@@ -206,22 +232,6 @@ public class WebConfiguration implements IConfigurationConstants {
}
}
}
-
- String pdfASDir = getPdfASDir();
- if (pdfASDir == null) {
- logger.error("Please configure pdf as working directory in the web configuration");
- throw new RuntimeException(
- "Please configure pdf as working directory in the web configuration");
- }
-
- File f = new File(pdfASDir);
-
- if (!f.exists() || !f.isDirectory()) {
- logger.error("Pdf As working directory does not exists or is not a directory!: "
- + pdfASDir);
- throw new RuntimeException(
- "Pdf As working directory does not exists or is not a directory!");
- }
}
public static String getPublicURL() {
@@ -314,12 +324,7 @@ public class WebConfiguration implements IConfigurationConstants {
public static boolean isAllowExtOverwrite() {
String value = properties.getProperty(ALLOW_EXT_OVERWRITE);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(value);
}
public static synchronized boolean isOverwriteAllowed(String key) {
@@ -344,47 +349,31 @@ public class WebConfiguration implements IConfigurationConstants {
public static boolean isJSONAPIEnabled() {
String value = properties.getProperty(JSON_API_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(value);
}
public static boolean isKeepSignedDocument() {
String value = properties.getProperty(KEEP_SIGNED_DOCUMENT);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(value);
}
public static boolean isMoaEnabled(String keyIdentifier) {
String value = properties.getProperty(MOA_LIST + "." + keyIdentifier + ".enabled");
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(value);
}
public static boolean isQRPlaceholderGenerator() {
String value = properties.getProperty(PLACEHOLDER_GENERATOR_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(value);
}
public static String getMoaURL(String keyIdentifier) {
return properties.getProperty(MOA_LIST + "." + keyIdentifier + "." + MOA_URL);
}
+
+ public static String getMoaTimeout(String keyIdentifier) {
+ return properties.getProperty(MOA_LIST + "." + keyIdentifier + "." + MOA_TIMEOUT);
+ }
public static String getMoaKeyID(String keyIdentifier) {
return properties.getProperty(MOA_LIST + "." + keyIdentifier + "." + MOA_KEYID);
@@ -429,121 +418,57 @@ public class WebConfiguration implements IConfigurationConstants {
public static boolean getMOASSEnabled() {
String value = properties.getProperty(MOA_SS_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(value);
}
public static boolean getKeystoreDefaultEnabled() {
String value = properties.getProperty(KEYSTORE_DEFAULT_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(value);
}
public static boolean getKeystoreEnabled(String keyIdentifier) {
String value = properties.getProperty(KEYSTORE_LIST + "." + keyIdentifier + "." + KEYSTORE_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(value);
}
public static boolean getLocalBKUEnabled() {
- String value = properties.getProperty(LOCAL_BKU_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(properties.getProperty(LOCAL_BKU_ENABLED));
}
public static boolean getMobileBKUEnabled() {
- String value = properties.getProperty(MOBILE_BKU_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(properties.getProperty(MOBILE_BKU_ENABLED));
}
public static boolean getOnlineBKUEnabled() {
- String value = properties.getProperty(ONLINE_BKU_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(properties.getProperty(ONLINE_BKU_ENABLED));
}
public static boolean getSL20Enabled() {
- String value = properties.getProperty(SL20_BKU_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(properties.getProperty(SL20_BKU_ENABLED));
}
public static boolean getSoapSignEnabled() {
- String value = properties.getProperty(SOAP_SIGN_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(properties.getProperty(SOAP_SIGN_ENABLED));
}
public static boolean isSoapSignWithVerifyEnabled() {
String value = properties.getProperty(SOAP_SIGN_WITH_VERIFY_ENABLED);
if (value != null) {
- return value.equals("true");
-
+ return Boolean.parseBoolean(value);
}
return getSoapSignEnabled();
}
public static boolean getSoapVerifyEnabled() {
- String value = properties.getProperty(SOAP_VERIFY_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(properties.getProperty(SOAP_VERIFY_ENABLED));
}
public static boolean isShowErrorDetails() {
- String value = properties.getProperty(ERROR_DETAILS);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(properties.getProperty(ERROR_DETAILS));
}
public static boolean isWhiteListEnabled() {
- String value = properties.getProperty(WHITELIST_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(properties.getProperty(WHITELIST_ENABLED));
}
public static synchronized boolean isProvidePdfURLinWhitelist(String url) {
@@ -598,13 +523,7 @@ public class WebConfiguration implements IConfigurationConstants {
}
public static boolean getReloadEnabled() {
- String value = properties.getProperty(RELOAD_ENABLED);
- if (value != null) {
- if (value.equals("true")) {
- return true;
- }
- }
- return false;
+ return Boolean.parseBoolean(properties.getProperty(RELOAD_ENABLED));
}
public static int getFilesizeThreshold() {
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsSecurityLayerException.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsSecurityLayerException.java
index 08577034..bc5a4d02 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsSecurityLayerException.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsSecurityLayerException.java
@@ -33,5 +33,10 @@ public class PdfAsSecurityLayerException extends Exception {
public PdfAsSecurityLayerException(String info, int errorcode) {
super("SecurityLayer Error: [" + errorcode + "] " + info);
}
+
+ public PdfAsSecurityLayerException(String info, int errorcode, Exception e) {
+ super("SecurityLayer Error: [" + errorcode + "] " + info, e);
+
+ }
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/ExceptionCatchFilter.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/ExceptionCatchFilter.java
index 5d1abc15..65fcdd33 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/ExceptionCatchFilter.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/ExceptionCatchFilter.java
@@ -28,22 +28,22 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
+import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import com.beust.jcommander.Strings;
import com.beust.jcommander.internal.Lists;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
/**
@@ -90,22 +90,25 @@ public class ExceptionCatchFilter implements Filter {
throws IOException, ServletException {
try {
- if (request instanceof HttpServletRequest) {
- HttpServletRequest httpRequest = (HttpServletRequest) request;
-
- HttpSession session = httpRequest.getSession(isStatefull(httpRequest.getServletPath()));
+ if (request instanceof HttpServletRequest httpRequest) {
+
+ HttpSession session = httpRequest.getSession(isStatefull(httpRequest.getServletPath()));
String sessionId = session != null ? session.getId() : "-";
MDC.put("SESSION_ID", sessionId);
- log.info("Access from IP: {}", getClientIpAddr(httpRequest));
- log.info("Access to: {} in Session: {}", httpRequest.getServletPath(), sessionId);
-
- log.debug("Processing Parameters into Attributes");
- @SuppressWarnings("unchecked")
- Enumeration<String> parameterNames = httpRequest.getParameterNames();
- while (parameterNames.hasMoreElements()) {
- String name = parameterNames.nextElement();
- String value = httpRequest.getParameter(name);
- request.setAttribute(name, value);
+ log.debug("Access from IP: {}", getClientIpAddr(httpRequest));
+ log.debug("Access to: {} in Session: {}", httpRequest.getServletPath(), sessionId);
+
+ if (!JakartaServletFileUpload.isMultipartContent(httpRequest)) {
+ log.debug("Processing Parameters into Attributes");
+ @SuppressWarnings("unchecked")
+ Enumeration<String> parameterNames = httpRequest.getParameterNames();
+ while (parameterNames.hasMoreElements()) {
+ String name = parameterNames.nextElement();
+ String value = httpRequest.getParameter(name);
+ request.setAttribute(name, value);
+ }
+ } else {
+ log.debug("Skipping global parameter parsing for multipart request");
}
}
@@ -113,13 +116,11 @@ public class ExceptionCatchFilter implements Filter {
chain.doFilter(request, response);
} finally {
- if (response instanceof HttpServletResponse) {
- HttpServletResponse resp = (HttpServletResponse) response;
- log.debug("Got response status: {}", resp.getStatus());
-
- } else {
- log.warn("Response is not a HttpServletResponse!");
-
+ if (response instanceof HttpServletResponse) {
+ HttpServletResponse resp = (HttpServletResponse) response;
+ log.debug("Got response status: {}", resp.getStatus());
+ } else {
+ log.warn("Response is not a HttpServletResponse!");
}
}
} catch (Throwable e) {
@@ -139,7 +140,10 @@ public class ExceptionCatchFilter implements Filter {
}
private boolean isStatefull(String contextPath) {
- boolean statefull = !statelessPaths.contains(contextPath);
+ boolean statefull = !statelessPaths.stream()
+ .filter(el -> contextPath.startsWith(el))
+ .findFirst()
+ .isPresent();
log.trace("ServletPath: {} is marked as {}", contextPath, statefull ? "statefull" : "stateless");
return statefull;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/UserAgentFilter.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/UserAgentFilter.java
index ef7d391d..15cadb48 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/UserAgentFilter.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/filter/UserAgentFilter.java
@@ -2,13 +2,13 @@ package at.gv.egiz.pdfas.web.filter;
import java.io.IOException;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java
index 9900dda4..554d79d1 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java
@@ -32,28 +32,27 @@ import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
+import java.util.*;
import javax.imageio.ImageIO;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import javax.xml.bind.JAXBElement;
-import javax.xml.ws.WebServiceException;
-
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import jakarta.xml.bind.JAXBElement;
+import jakarta.xml.ws.WebServiceException;
+
+import lombok.Getter;
+import lombok.val;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.text.StringEscapeUtils;
import org.apache.http.entity.ContentType;
import com.google.gson.JsonArray;
@@ -155,7 +154,8 @@ public class PdfAsHelper {
private static PdfAs pdfAs;
private static ObjectFactory of = new ObjectFactory();
- private static Configuration pdfAsConfig;
+ @Getter
+ private static Configuration pdfAsConfig;
static {
reloadConfig();
@@ -169,44 +169,17 @@ public class PdfAsHelper {
public static synchronized void reloadConfig() {
log.info("Creating PDF-AS");
- pdfAs = PdfAsFactory.createPdfAs(new File(WebConfiguration
- .getPdfASDir()));
+ val workdir = WebConfiguration.getPdfASDir();
+ if (workdir == null) {
+ throw new IllegalStateException(
+ "WebConfiguration is not yet initialized. This is an application start-up order bug.");
+ }
+ pdfAs = PdfAsFactory.createPdfAs(new File(workdir));
pdfAsConfig = pdfAs.getConfiguration();
log.info("Creating PDF-AS done");
}
- public static Configuration getPdfAsConfig() {
- return pdfAsConfig;
- }
-
- private static void validatePdfSize(HttpServletRequest request,
- HttpServletResponse response, byte[] pdfData)
- throws PdfAsWebException {
- // Try to check num-bytes
- String pdfSizeString = PdfAsParameterExtractor.getNumBytes(request);
- if (pdfSizeString != null) {
- long pdfSize = -1;
- try {
- pdfSize = Long.parseLong(pdfSizeString);
- } catch (NumberFormatException e) {
- throw new PdfAsWebException(
- PdfAsParameterExtractor.PARAM_NUM_BYTES
- + " parameter has to be a positiv number!", e);
- }
- if (pdfSize <= 0) {
- throw new PdfAsWebException(
- "Invalid PDF Size! Has to bigger than zero!");
- }
-
- if (pdfData.length != pdfSize) {
- throw new PdfAsWebException("Signature Data Size and "
- + PdfAsParameterExtractor.PARAM_NUM_BYTES
- + " missmatch!");
- }
- }
- }
-
- public static String buildPosString(HttpServletRequest request,
+ public static String buildPosString(HttpServletRequest request,
HttpServletResponse response) throws PdfAsWebException {
String posP = PdfAsParameterExtractor.getSigPosP(request);
String posX = PdfAsParameterExtractor.getSigPosX(request);
@@ -268,22 +241,22 @@ public class PdfAsHelper {
sb.append("w:auto;");
}
}
- sb.append("w:" + posW.trim() + ";");
+ sb.append("w:").append(posW.trim()).append(";");
} else {
sb.append("w:auto;");
}
if (posP != null) {
- if (!(posP.equals("auto") || posP.equals("new"))) {
+ if (!(posP.equals("auto") || posP.equals("new") || posP.equals("last"))) {
try {
Integer.parseInt(posP);
} catch (NumberFormatException e) {
throw new PdfAsWebException(
PdfAsParameterExtractor.PARAM_SIG_POS_P
- + " has invalid value! (auto | new )");
+ + " has invalid value! (auto | new | last)");
}
}
- sb.append("p:" + posP.trim() + ";");
+ sb.append("p:").append(posP.trim()).append(";");
} else {
sb.append("p:auto;");
}
@@ -298,7 +271,7 @@ public class PdfAsHelper {
+ " has invalid value!", e);
}
}
- sb.append("r:" + posR.trim() + ";");
+ sb.append("r:").append(posR.trim()).append(";");
} else {
sb.append("r:0;");
}
@@ -315,7 +288,7 @@ public class PdfAsHelper {
sb.append("f:0;");
}
}
- sb.append("f:" + posF.trim() + ";");
+ sb.append("f:").append(posF.trim()).append(";");
} else {
sb.append("f:0;");
}
@@ -349,9 +322,7 @@ public class PdfAsHelper {
verifyParameter.setConfiguration(config);
verifyParameter.setWhichSignature(signIdx);
- List<VerifyResult> results = pdfAs.verify(verifyParameter);
-
- return results;
+ return pdfAs.verify(verifyParameter);
}
public static List<VerifyResult> synchronousVerify(byte[] pdfData,
@@ -372,9 +343,7 @@ public class PdfAsHelper {
verifyParameter.setConfiguration(config);
verifyParameter.setWhichSignature(signIdx);
- List<VerifyResult> results = pdfAs.verify(verifyParameter);
-
- return results;
+ return pdfAs.verify(verifyParameter);
}
public static PdfasSignResponse synchronousServerSignature(PdfasSignRequest internalReq) throws Exception {
@@ -384,10 +353,9 @@ public class PdfAsHelper {
respBuilder.transactionId(internalReq.getCoreParams().getTransactionId());
// sign each document
- Iterator<DocumentToSign> docsToSign = internalReq.getInput().iterator();
- while(docsToSign.hasNext()) {
- respBuilder.signedPdf(synchronousServerSignature(docsToSign.next(), internalReq.getCoreParams()));
-
+ for (DocumentToSign documentToSign : internalReq.getInput()) {
+ respBuilder.signedPdf(synchronousServerSignature(documentToSign, internalReq.getCoreParams()));
+
}
log.debug("Signing process finished.");
@@ -419,39 +387,31 @@ public class PdfAsHelper {
new ByteArrayDataSource(documentToSign.getInputData()), baos);
// Get Connector
+ val connector = coreParams.getConnector();
+ val keyIdentifier = coreParams.getKeyIdentifier();
+ PdfAsHelper.checkConnectorSupported(connector, keyIdentifier);
IPlainSigner signer;
- if (coreParams.getConnector().equals(Connector.MOA)) {
- String keyIdentifier = coreParams.getKeyIdentifier();
+ if (connector == Connector.MOA) {
if (keyIdentifier != null) {
- if (!WebConfiguration.isMoaEnabled(keyIdentifier)) {
- throw new PdfAsWebException("MOA connector ["
- + keyIdentifier + "] disabled or not existing.");
- }
-
String url = WebConfiguration.getMoaURL(keyIdentifier);
+ String timeout = WebConfiguration.getMoaTimeout(keyIdentifier);
String keyId = WebConfiguration.getMoaKeyID(keyIdentifier);
String certificate = WebConfiguration
.getMoaCertificate(keyIdentifier);
config.setValue(IConfigurationConstants.MOA_SIGN_URL, url);
+ config.setValue(IConfigurationConstants.MOA_SIGN_TIMEOUT, timeout);
config.setValue(IConfigurationConstants.MOA_SIGN_KEY_ID, keyId);
config.setValue(IConfigurationConstants.MOA_SIGN_CERTIFICATE,
certificate);
- } else {
- if (!WebConfiguration.getMOASSEnabled()) {
- throw new PdfAsWebException("MOA connector disabled.");
- }
}
signer = new PAdESSigner(new MOAConnector(config));
- } else if (coreParams.getConnector().equals(Connector.JKS)) {
- String keyIdentifier = coreParams.getKeyIdentifier();
-
- boolean ksEnabled = false;
+ } else if (connector == Connector.JKS) {
String ksFile = null;
String ksAlias = null;
String ksPass = null;
@@ -459,14 +419,12 @@ public class PdfAsHelper {
String ksType = null;
if (keyIdentifier != null) {
- ksEnabled = WebConfiguration.getKeystoreEnabled(keyIdentifier);
ksFile = WebConfiguration.getKeystoreFile(keyIdentifier);
ksAlias = WebConfiguration.getKeystoreAlias(keyIdentifier);
ksPass = WebConfiguration.getKeystorePass(keyIdentifier);
ksKeyPass = WebConfiguration.getKeystoreKeyPass(keyIdentifier);
ksType = WebConfiguration.getKeystoreType(keyIdentifier);
} else {
- ksEnabled = WebConfiguration.getKeystoreDefaultEnabled();
ksFile = WebConfiguration.getKeystoreDefaultFile();
ksAlias = WebConfiguration.getKeystoreDefaultAlias();
ksPass = WebConfiguration.getKeystoreDefaultPass();
@@ -474,27 +432,6 @@ public class PdfAsHelper {
ksType = WebConfiguration.getKeystoreDefaultType();
}
- if (!ksEnabled) {
- if (keyIdentifier != null) {
- throw new PdfAsWebException("JKS connector ["
- + keyIdentifier + "] disabled or not existing.");
- } else {
- throw new PdfAsWebException(
- "DEFAULT JKS connector disabled.");
- }
- }
-
- if (ksFile == null || ksAlias == null || ksPass == null
- || ksKeyPass == null || ksType == null) {
- if (keyIdentifier != null) {
- throw new PdfAsWebException("JKS connector ["
- + keyIdentifier + "] not correctly configured.");
- } else {
- throw new PdfAsWebException(
- "DEFAULT JKS connector not correctly configured.");
- }
- }
-
signer = new PAdESSignerKeystore(ksFile, ksAlias, ksPass,
ksKeyPass, ksType);
@@ -552,28 +489,26 @@ public class PdfAsHelper {
SignResult signResult = pdfAs.sign(signParameter);
- PDFASVerificationResponse verResponse = new PDFASVerificationResponse();
- verResponse.setSignerCertificate(signResult.getSignerCertificate().getEncoded());
+ PDFASVerificationResponse verResponse = new PDFASVerificationResponse();
+ verResponse.setSignerCertificate(signResult.getSignerCertificate().getEncoded());
-
- SignedDocument signPdfDoc = SignedDocument.builder()
- .signingTimestamp(Long.valueOf(System.currentTimeMillis()))
- .outputData(baos.toByteArray())
- .fileName(documentToSign.getFileName())
- .verificationResponse(verResponse)
- .signerCertificate(Base64.encodeBase64String(signResult.getSignerCertificate().getEncoded()))
- .build();
-
- return signPdfDoc;
+
+ return SignedDocument.builder()
+ .signingTimestamp(System.currentTimeMillis())
+ .outputData(baos.toByteArray())
+ .fileName(documentToSign.getFileName())
+ .verificationResponse(verResponse)
+ .signerCertificate(Base64.encodeBase64String(signResult.getSignerCertificate().getEncoded()))
+ .build();
}
public static void startSignatureJson(HttpServletRequest request, HttpServletResponse response,
- ServletContext context, String connector, PdfasSignRequest pdfAsRequest) throws Exception {
+ ServletContext context, Connector connector, PdfasSignRequest pdfAsRequest) throws Exception {
HttpSession session = request.getSession();
log.info("Starting signature in session: " + session.getId());
- session.setAttribute(PDF_PROCESSING_REQUEST, pdfAsRequest);
+ session.setAttribute(PDF_PROCESSING_REQUEST, pdfAsRequest);
StatusRequest statusRequest = initializeSigningContextForNewDocument(request, connector, pdfAsRequest);
session.setAttribute(PDF_STATUS, statusRequest);
@@ -581,7 +516,7 @@ public class PdfAsHelper {
}
public static void startSignature(HttpServletRequest request, HttpServletResponse response,
- ServletContext context, String connector, PdfasSignRequest pdfAsRequest) throws Exception {
+ ServletContext context, Connector connector, PdfasSignRequest pdfAsRequest) throws Exception {
HttpSession session = request.getSession();
log.info("Starting signature in session: " + session.getId());
session.setAttribute(PDF_PROCESSING_REQUEST, pdfAsRequest);
@@ -594,7 +529,7 @@ public class PdfAsHelper {
}
- private static StatusRequest initializeSigningContextForNewDocument(HttpServletRequest request, String connector, PdfasSignRequest pdfAsRequest)
+ private static StatusRequest.Stage1 initializeSigningContextForNewDocument(HttpServletRequest request, Connector connector, PdfasSignRequest pdfAsRequest)
throws PdfAsWebException, WriterException, IOException, PdfAsException, PDFASError {
HttpSession session = request.getSession();
@@ -606,7 +541,7 @@ public class PdfAsHelper {
session.setAttribute(PDF_SL_INTERACTIVE, connector);
// prepare first document
- IPlainSigner signer = getSignerFromConnector(connector, config, session);
+ IPlainSigner signer = getSignerFromConnector(connector, session);
session.setAttribute(PDF_SIGNER, signer);
String qrCodeContent = PdfAsHelper.getQRCodeContent(request);
@@ -619,7 +554,7 @@ public class PdfAsHelper {
}
- private static StatusRequest buildPdfasStatusRequestToSignSingleDocument(DocumentToSign pdfToSign, HttpSession session, IPlainSigner signer,
+ private static StatusRequest.Stage1 buildPdfasStatusRequestToSignSingleDocument(DocumentToSign pdfToSign, HttpSession session, IPlainSigner signer,
CoreSignParams coreSignParams, String qrCodeContent, Configuration config) throws WriterException, IOException, PdfAsException, PDFASError {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
session.setAttribute(PDF_OUTPUT, baos);
@@ -671,23 +606,14 @@ public class PdfAsHelper {
}
- private static IPlainSigner getSignerFromConnector(String connector, Configuration config, HttpSession session) throws PdfAsWebException {
- if (connector.equals("bku") || connector.equals("onlinebku")
- || connector.equals("mobilebku")) {
- BKUSLConnector conn = new BKUSLConnector(config);
- session.setAttribute(PDF_SL_CONNECTOR, conn);
- return new PAdESSigner(conn);
-
-
- } else if (connector.equals("sl20")) {
- SL20Connector conn = new SL20Connector(config);
- session.setAttribute(PDF_SL_CONNECTOR, conn);
- return new PAdESSigner(conn);
-
- } else {
- throw new PdfAsWebException(
- "Invalid connector (bku | onlinebku | mobilebku | moa | jks | sl20)");
- }
+ private static IPlainSigner getSignerFromConnector(Connector connector, HttpSession session) throws PdfAsWebException {
+ val slConnector = switch(connector) {
+ case BKU, ONLINEBKU, MOBILEBKU -> new BKUSLConnector(generateBKUURL(connector));
+ case SECLAYER20 -> new SL20Connector(WebConfiguration.getSecurityLayer20URL());
+ default -> throw new PdfAsWebException("Invalid connector (bku | onlinebku | mobilebku | sl20)");
+ };
+ session.setAttribute(PDF_SL_CONNECTOR, slConnector);
+ return new PAdESSigner(slConnector);
}
public static byte[] getCertificate(
@@ -738,7 +664,7 @@ public class PdfAsHelper {
.getAttribute(PDF_STATUS);
if(statusObject != null && statusObject instanceof StatusRequest) {
StatusRequest statusRequest = (StatusRequest)statusObject;
- if(statusRequest.needCertificate() || statusRequest.needSignature()) {
+ if (statusRequest instanceof StatusRequest.Stage1 || statusRequest instanceof StatusRequest.Stage2) {
return true;
}
}
@@ -756,21 +682,19 @@ public class PdfAsHelper {
StatusRequest statusRequest = (StatusRequest) session
.getAttribute(PDF_STATUS);
- if (statusRequest == null) {
+ if (!(statusRequest instanceof StatusRequest.Stage1 statusRequest1)) {
throw new PdfAsWebException("No Signature running in session:"
+ session.getId());
}
-
- statusRequest.setCertificate(certificate);
- statusRequest = pdfAs.process(statusRequest);
- session.setAttribute(PDF_STATUS, statusRequest);
+ val statusRequest2 = statusRequest1.setCertificate(certificate);
+ session.setAttribute(PDF_STATUS, statusRequest2);
PdfAsHelper.process(request, response, context);
}
public static void injectSignature(HttpServletRequest request,
HttpServletResponse response,
- byte[] cmsSginature,
+ byte[] cmsSignature,
ServletContext context) throws Exception {
log.debug("Got CMS Signature Response");
@@ -779,14 +703,13 @@ public class PdfAsHelper {
StatusRequest statusRequest = (StatusRequest) session
.getAttribute(PDF_STATUS);
- if (statusRequest == null) {
+ if (!(statusRequest instanceof StatusRequest.Stage2 statusRequest2)) {
throw new PdfAsWebException("No Signature running in session:"
+ session.getId());
}
- statusRequest.setSigature(cmsSginature);
- statusRequest = pdfAs.process(statusRequest);
- session.setAttribute(PDF_STATUS, statusRequest);
+ val statusRequest3 = statusRequest2.setSignature(cmsSignature);
+ session.setAttribute(PDF_STATUS, statusRequest3);
PdfAsHelper.process(request, response, context);
}
@@ -800,14 +723,14 @@ public class PdfAsHelper {
// IPlainSigner plainSigner = (IPlainSigner) session
// .getAttribute(PDF_SIGNER);
- String connector = (String) session.getAttribute(PDF_SL_INTERACTIVE);
+ Connector connector = (Connector) session.getAttribute(PDF_SL_INTERACTIVE);
+ PdfAsHelper.checkConnectorSupported(connector, null);
- if (connector.equals("bku") || connector.equals("onlinebku")
- || connector.equals("mobilebku")) {
+ if (connector == Connector.BKU || connector == Connector.ONLINEBKU || connector == Connector.MOBILEBKU) {
BKUSLConnector bkuSLConnector = (BKUSLConnector) session
.getAttribute(PDF_SL_CONNECTOR);
- if (statusRequest.needCertificate()) {
+ if (statusRequest instanceof StatusRequest.Stage1) {
log.debug("Needing Certificate from BKU");
// build SL Request to read certificate
InfoboxReadRequestType readCertificateRequest = bkuSLConnector
@@ -833,14 +756,15 @@ public class PdfAsHelper {
throws Exception {
HttpSession session = request.getSession();
- StatusRequest statusRequest = (StatusRequest) session.getAttribute(PDF_STATUS);
+ StatusRequest statusRequestGeneric = (StatusRequest) session.getAttribute(PDF_STATUS);
PdfasSignRequest pdfAsRequest = (PdfasSignRequest) session.getAttribute(PDF_PROCESSING_REQUEST);
// IPlainSigner plainSigner = (IPlainSigner) session
// .getAttribute(PDF_SIGNER);
- String connector = (String) session.getAttribute(PDF_SL_INTERACTIVE);
+ Connector connector = (Connector) session.getAttribute(PDF_SL_INTERACTIVE);
+ PdfAsHelper.checkConnectorSupported(connector, null);
//load connector
ISLConnector slConnector = (ISLConnector) session.getAttribute(PDF_SL_CONNECTOR);
@@ -849,7 +773,7 @@ public class PdfAsHelper {
if (!joseTools.isInitialized())
joseTools = null;
- if (statusRequest.needCertificate()) {
+ if (statusRequestGeneric instanceof StatusRequest.Stage1 statusRequest) {
log.debug("Needing Certificate from BKU");
// build SL Request to read certificate
InfoboxReadRequestType readCertificateRequest = slConnector
@@ -888,11 +812,10 @@ public class PdfAsHelper {
response.setContentType("text/html");
response.getWriter().close();
- } else if (slConnector instanceof SL20Connector) {
- //generate request for getCertificate command
- SL20Connector sl20Connector = (SL20Connector)slConnector;
-
- //use 'SecureSigningKeypair' per default
+ } else if (slConnector instanceof SL20Connector sl20Connector) {
+ //generate request for getCertificate command
+
+ //use 'SecureSigningKeypair' per default
String keyId = SL20Connector.SecureSignatureKeypair;
java.security.cert.X509Certificate x5cEnc = null;
@@ -976,7 +899,7 @@ public class PdfAsHelper {
} else
throw new PdfAsWebException("Invalid connector: " + slConnector.getClass().getName());
- } else if (statusRequest.needSignature()) {
+ } else if (statusRequestGeneric instanceof StatusRequest.Stage2 statusRequest) {
log.debug("Needing Signature from BKU");
// build SL Request for cms signature
RequestPackage pack = slConnector.createCMSRequest(
@@ -1077,7 +1000,7 @@ public class PdfAsHelper {
log.trace("Write 'createCAdES' command to VDA: " + sl20CreateCAdES.toString());
StringWriter writer = new StringWriter();
writer.write(sl20CreateCAdES.toString());
- final byte[] content = writer.toString().getBytes("UTF-8");
+ final byte[] content = writer.toString().getBytes(StandardCharsets.UTF_8);
response.setStatus(HttpServletResponse.SC_OK);
response.setContentLength(content.length);
response.setContentType(ContentType.APPLICATION_JSON.toString());
@@ -1088,9 +1011,9 @@ public class PdfAsHelper {
}
- } else if (statusRequest.isReady()) {
+ } else if (statusRequestGeneric instanceof StatusRequest.Stage3 statusRequest) {
log.debug("Single document is ready. Perform post-processing ... ");
- SignResult result = pdfAs.finishSign(statusRequest);
+ SignResult result = statusRequest.finishSign();
ByteArrayOutputStream baos = (ByteArrayOutputStream) session.getAttribute(PDF_OUTPUT);
baos.close();
@@ -1112,7 +1035,7 @@ public class PdfAsHelper {
.getCode());
SignedDocument signPdfDoc = SignedDocument.builder()
- .signingTimestamp(Long.valueOf(System.currentTimeMillis()))
+ .signingTimestamp(System.currentTimeMillis())
.outputData(baos.toByteArray())
.fileName(PdfAsHelper.getPDFFileName(request))
.verificationResponse(verResponse)
@@ -1125,28 +1048,28 @@ public class PdfAsHelper {
// check if more files are available
if (pdfAsRequest.hasNext()) {
log.debug("Find additional file, restarting signing process again ... ");
- StatusRequestImpl nextStatusRequest = (StatusRequestImpl)initializeSigningContextForNewDocument(request, connector, pdfAsRequest);
- nextStatusRequest.setCertificate(((StatusRequestImpl)statusRequest).getCertificate().getEncoded());
- nextStatusRequest.setNeedCertificate(true);
-
- statusRequest = pdfAs.process(nextStatusRequest);
- session.setAttribute(PDF_STATUS, nextStatusRequest);
-
- PdfAsHelper.process(request, response, context);
- session.setAttribute(PDF_STATUS, nextStatusRequest);
+ StatusRequest.Stage1 nextStatusRequest1 = initializeSigningContextForNewDocument(request, connector, pdfAsRequest);
+ StatusRequest.Stage2 nextStatusRequest2 = nextStatusRequest1.setCertificate(
+ statusRequest.getRequestedSignature().getCertificate().getEncoded());
+
+ session.setAttribute(PDF_STATUS, nextStatusRequest2);
+
+ // recurse
+ PdfAsHelper.process(request, response, context);
} else {
- if (slConnector instanceof BKUSLConnector) {
- PdfAsHelper.gotoProvidePdf(context, request, response);
-
- } else if (slConnector instanceof SL20Connector) {
- //TODO: add code to send SL20 redirect command to redirect the user from DataURL connection to App Front-End connection
- String callUrl = generateProvideURL(request, response);
- String transactionId = (String) request.getAttribute(PdfAsHelper.PDF_SESSION_PREFIX + SL20Constants.SL20_TRANSACTIONID);
- buildSL20RedirectResponse(request, response, transactionId, callUrl);
-
- } else
- throw new PdfAsWebException("Invalid connector: " + slConnector.getClass().getName());
+ if (slConnector instanceof BKUSLConnector) {
+ PdfAsHelper.gotoProvidePdf(context, request, response);
+
+ } else if (slConnector instanceof SL20Connector) {
+ //TODO: add code to send SL20 redirect command to redirect the user from DataURL connection to App Front-End connection
+ String callUrl = generateProvideURL(request, response);
+ String transactionId = (String) request.getAttribute(PdfAsHelper.PDF_SESSION_PREFIX + SL20Constants.SL20_TRANSACTIONID);
+ buildSL20RedirectResponse(request, response, transactionId, callUrl);
+
+ } else {
+ throw new PdfAsWebException("Invalid connector: " + slConnector.getClass().getName());
+ }
}
@@ -1154,52 +1077,54 @@ public class PdfAsHelper {
throw new PdfAsWebException("Invalid state!");
}
- }
+ }
private static String getTemplateSL() throws IOException {
String xml = FileUtils.readFileToString(
- FileUtils.toFile(PdfAsHelper.class.getResource("/template_sl.html")));
+ FileUtils.toFile(PdfAsHelper.class.getResource("/template_sl.html")),
+ StandardCharsets.UTF_8);
return xml;
}
public static String getErrorRedirectTemplateSL() throws IOException {
- String xml = FileUtils.readFileToString(FileUtils
- .toFile(PdfAsHelper.class
- .getResource("/template_error_redirect.html")));
+ String xml = FileUtils.readFileToString(
+ FileUtils.toFile(PdfAsHelper.class.getResource("/template_error_redirect.html")),
+ StandardCharsets.UTF_8);
return xml;
}
public static String getProvideTemplate() throws IOException {
- String xml = FileUtils
- .readFileToString(FileUtils.toFile(PdfAsHelper.class
- .getResource("/template_provide.html")));
+ String xml = FileUtils.readFileToString(
+ FileUtils.toFile(PdfAsHelper.class.getResource("/template_provide.html")),
+ StandardCharsets.UTF_8);
return xml;
}
public static String getErrorTemplate() throws IOException {
- String xml = FileUtils.readFileToString(FileUtils
- .toFile(PdfAsHelper.class.getResource("/template_error.html")));
+ String xml = FileUtils.readFileToString(
+ FileUtils.toFile(PdfAsHelper.class.getResource("/template_error.html")),
+ StandardCharsets.UTF_8);
return xml;
}
public static String getGenericTemplate() throws IOException {
- String xml = FileUtils.readFileToString(FileUtils
- .toFile(PdfAsHelper.class
- .getResource("/template_generic_param.html")));
+ String xml = FileUtils.readFileToString(
+ FileUtils.toFile(PdfAsHelper.class.getResource("/template_generic_param.html")),
+ StandardCharsets.UTF_8);
return xml;
}
public static String getInvokeRedirectTemplateSL() throws IOException {
- String xml = FileUtils.readFileToString(FileUtils
- .toFile(PdfAsHelper.class
- .getResource("/template_invoke_redirect.html")));
+ String xml = FileUtils.readFileToString(
+ FileUtils.toFile(PdfAsHelper.class.getResource("/template_invoke_redirect.html")),
+ StandardCharsets.UTF_8);
return xml;
}
public static String getInvokeRedirectTemplateMoreFiles() throws IOException {
- String xml = FileUtils.readFileToString(FileUtils
- .toFile(PdfAsHelper.class
- .getResource("/template_invoke_redirect_more_files.html")));
+ String xml = FileUtils.readFileToString(
+ FileUtils.toFile(PdfAsHelper.class.getResource("/template_invoke_redirect_more_files.html")),
+ StandardCharsets.UTF_8);
return xml;
}
@@ -1442,28 +1367,19 @@ public class PdfAsHelper {
}
String baseURL = publicURL + PDF_USERENTRY_PAGE;
- try {
- return baseURL + "?" + UIEntryPointServlet.REQUEST_ID_PARAM + "="
- + URLEncoder.encode(storeId, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- log.warn("Encoding not supported for URL encoding", e);
- }
- return baseURL + "?" + UIEntryPointServlet.REQUEST_ID_PARAM + "="
- + storeId;
- }
-
- public static String generateBKUURL(String connector) {
- if (connector.equals("bku")) {
- return WebConfiguration.getLocalBKUURL();
- } else if (connector.equals("onlinebku")) {
- return WebConfiguration.getOnlineBKUURL();
- } else if (connector.equals("mobilebku")) {
- return WebConfiguration.getHandyBKUURL();
- } else if (connector.equals("sl20")) {
- return WebConfiguration.getSecurityLayer20URL();
- }
- return WebConfiguration.getLocalBKUURL();
- }
+ return baseURL + "?" + UIEntryPointServlet.REQUEST_ID_PARAM + "="
+ + URLEncoder.encode(storeId, StandardCharsets.UTF_8);
+ }
+
+ public static String generateBKUURL(Connector connector) {
+ return switch (connector) {
+ case BKU -> WebConfiguration.getLocalBKUURL();
+ case ONLINEBKU -> WebConfiguration.getOnlineBKUURL();
+ case MOBILEBKU -> WebConfiguration.getHandyBKUURL();
+ case SECLAYER20 -> WebConfiguration.getSecurityLayer20URL();
+ default -> throw new IllegalStateException("Attempt to get BKU URL for connector: "+connector.name());
+ };
+ }
public static void setFromDataUrl(HttpServletRequest request) {
request.setAttribute(REQUEST_FROM_DU, (Boolean) true);
@@ -1473,7 +1389,7 @@ public class PdfAsHelper {
Object obj = request.getAttribute(REQUEST_FROM_DU);
if (obj != null) {
if (obj instanceof Boolean) {
- return ((Boolean) obj).booleanValue();
+ return (Boolean) obj;
}
}
return false;
@@ -1602,7 +1518,7 @@ public class PdfAsHelper {
public static void setSignatureActive(HttpServletRequest request,
boolean value) {
HttpSession session = request.getSession();
- session.setAttribute(SIGNATURE_ACTIVE, new Boolean(value));
+ session.setAttribute(SIGNATURE_ACTIVE, Boolean.valueOf(value));
}
public static boolean isSignatureActive(HttpServletRequest request) {
@@ -1672,7 +1588,7 @@ public class PdfAsHelper {
log.trace("SL20 response to VDA: " + respContainer);
StringWriter writer = new StringWriter();
writer.write(respContainer.toString());
- final byte[] content = writer.toString().getBytes("UTF-8");
+ final byte[] content = writer.toString().getBytes(StandardCharsets.UTF_8);
response.setStatus(HttpServletResponse.SC_OK);
response.setContentLength(content.length);
response.setContentType(ContentType.APPLICATION_JSON.toString());
@@ -1686,4 +1602,82 @@ public class PdfAsHelper {
}
}
+ private static boolean anyNull(Object... any) {
+ return (Arrays.stream(any).anyMatch(Objects::isNull));
+ }
+
+ public static void checkConnectorSupported(Connector connector, String keyIdentifier) throws PdfAsWebException {
+ if (connector == null) {
+ throw new PdfAsWebException("Invalid or unknown connector value");
+ } else if (connector == Connector.BKU) {
+ if (!WebConfiguration.getLocalBKUEnabled()) {
+ throw new PdfAsWebException("Connector bku is not enabled in configuration");
+ }
+ if (WebConfiguration.getLocalBKUURL() == null) {
+ throw new PdfAsWebException("Connector bku is not properly configured");
+ }
+ } else if (connector == Connector.ONLINEBKU) {
+ if (!WebConfiguration.getOnlineBKUEnabled()) {
+ throw new PdfAsWebException("Connector onlinebku is not enabled in configuration");
+ }
+ if (WebConfiguration.getOnlineBKUURL() == null) {
+ throw new PdfAsWebException("Connector onlinebku is not properly configured");
+ }
+ } else if (connector == Connector.MOBILEBKU) {
+ if (!WebConfiguration.getMobileBKUEnabled()) {
+ throw new PdfAsWebException("Connector mobilebku is not enabled in configuration");
+ }
+ if (WebConfiguration.getHandyBKUURL() == null) {
+ throw new PdfAsWebException("Connector mobilebku is not properly configured");
+ }
+ } else if (connector == Connector.SECLAYER20) {
+ if (!WebConfiguration.getSL20Enabled()) {
+ throw new PdfAsWebException("Connector sl20 is not enabled in configuration");
+ }
+ if (WebConfiguration.getSecurityLayer20URL() == null) {
+ throw new PdfAsWebException("Connector sl20 is not properly configured");
+ }
+ } else if (connector == Connector.MOA) {
+ if (keyIdentifier != null) {
+ if (!WebConfiguration.isMoaEnabled(keyIdentifier)) {
+ throw new PdfAsWebException("Connector moa[keyId="+keyIdentifier+"] is not enabled in configuration");
+ }
+ } else {
+ if (!WebConfiguration.getMOASSEnabled()) {
+ throw new PdfAsWebException("Connector moa[default] is not enabled in configuration");
+ }
+ }
+ } else if (connector == Connector.JKS) {
+ if (keyIdentifier != null) {
+ if (!WebConfiguration.getKeystoreEnabled(keyIdentifier)) {
+ throw new PdfAsWebException("Connector jks[keyId="+keyIdentifier+"] is not enabled in configuration");
+ }
+ if (
+ anyNull(
+ WebConfiguration.getKeystoreFile(keyIdentifier),
+ WebConfiguration.getKeystoreAlias(keyIdentifier),
+ WebConfiguration.getKeystorePass(keyIdentifier),
+ WebConfiguration.getKeystoreKeyPass(keyIdentifier),
+ WebConfiguration.getKeystoreType(keyIdentifier)))
+ {
+ throw new PdfAsWebException("Connector jks[keyId="+keyIdentifier+"] is not properly configured");
+ }
+ } else {
+ if (!WebConfiguration.getKeystoreDefaultEnabled()) {
+ throw new PdfAsWebException("Connector jks[default] is not enabled in configuration");
+ }
+ if (
+ anyNull(
+ WebConfiguration.getKeystoreDefaultFile(),
+ WebConfiguration.getKeystoreDefaultAlias(),
+ WebConfiguration.getKeystoreDefaultPass(),
+ WebConfiguration.getKeystoreDefaultKeyPass(),
+ WebConfiguration.getKeystoreDefaultType()))
+ {
+ throw new PdfAsWebException("Connector jks[default] is not properly configured");
+ }
+ }
+ }
+ }
+
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsParameterExtractor.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsParameterExtractor.java
index 1ed85e98..a0c407c9 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsParameterExtractor.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsParameterExtractor.java
@@ -28,7 +28,8 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
+import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector;
+import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@@ -41,7 +42,6 @@ public class PdfAsParameterExtractor {
public static final String PARAM_CONNECTOR = "connector";
public static final String PARAM_TRANSACTION_ID = "transactionId";
- public static final String PARAM_CONNECTOR_DEFAULT = "bku";
public static final String PARAM_FORMAT = "format";
public static final String PARAM_HTML = "html";
@@ -63,7 +63,6 @@ public class PdfAsParameterExtractor {
public static final String PARAM_VERIFY_LEVEL_OPTION_INT_ONLY = "intOnly";
public static final String PARAM_LOCALE = "locale";
- public static final String PARAM_NUM_BYTES = "num-bytes";
public static final String PARAM_PDF_URL = "pdf-url";
public static final String PARAM_SIG_TYPE = "sig-type";
public static final String PARAM_SIG_TYPE_ALIAS = "sig_type";
@@ -84,12 +83,8 @@ public class PdfAsParameterExtractor {
private static final Logger logger = LoggerFactory
.getLogger(PdfAsParameterExtractor.class);
- public static String getConnector(HttpServletRequest request) {
- String connector = (String)request.getAttribute(PARAM_CONNECTOR);
- if(connector != null) {
- return connector;
- }
- return PARAM_CONNECTOR_DEFAULT;
+ public static Connector getConnector(HttpServletRequest request) {
+ return Connector.fromString((String)request.getAttribute(PARAM_CONNECTOR));
}
public static Map<String,String> getDynamicSignatureBlockParameters(HttpServletRequest request) throws Exception {
@@ -234,10 +229,6 @@ public class PdfAsParameterExtractor {
return null;
}
- public static String getNumBytes(HttpServletRequest request) {
- return (String)request.getAttribute(PARAM_NUM_BYTES);
- }
-
public static String getPdfUrl(HttpServletRequest request) {
return (String)request.getAttribute(PARAM_PDF_URL);
}
@@ -278,7 +269,7 @@ public class PdfAsParameterExtractor {
return (String)request.getAttribute(PARAM_SIG_IDX);
}
- public static String getResonseMode(HttpServletRequest request) {
+ public static String getResponseMode(HttpServletRequest request) {
return (String)request.getAttribute(PARAM_RESPONSE_MODE);
}
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/RemotePDFFetcher.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/RemotePDFFetcher.java
index 696a3dc1..33811617 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/RemotePDFFetcher.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/RemotePDFFetcher.java
@@ -28,6 +28,7 @@ import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
@@ -108,7 +109,7 @@ public class RemotePDFFetcher {
if(fetchInfos.length == 3) {
String userpass = fetchInfos[1] + ":" + fetchInfos[2];
- String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes("UTF-8"));
+ String basicAuth = "Basic " + jakarta.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes(StandardCharsets.UTF_8));
uc.setRequestProperty("Authorization", basicAuth);
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/UrlParameterExtractor.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/UrlParameterExtractor.java
index 64043cac..cfb78008 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/UrlParameterExtractor.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/UrlParameterExtractor.java
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -20,8 +21,8 @@ public class UrlParameterExtractor {
for (String pair : pairs) {
int idx = pair.indexOf("=");
query_pairs.put(
- URLDecoder.decode(pair.substring(0, idx), "UTF-8"),
- URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
+ URLDecoder.decode(pair.substring(0, idx), StandardCharsets.UTF_8),
+ URLDecoder.decode(pair.substring(idx + 1), StandardCharsets.UTF_8));
}
}
return query_pairs;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultEncoder.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultEncoder.java
index 42a4068a..8b477c2e 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultEncoder.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultEncoder.java
@@ -3,8 +3,8 @@ package at.gv.egiz.pdfas.web.helper;
import java.io.IOException;
import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import at.gv.egiz.pdfas.lib.api.verify.VerifyResult;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultHTMLEncoder.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultHTMLEncoder.java
index 590e93a1..3db45370 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultHTMLEncoder.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultHTMLEncoder.java
@@ -6,8 +6,8 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import at.gv.egiz.pdfas.lib.api.verify.VerifyResult;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultJSONEncoder.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultJSONEncoder.java
index 43ad3581..b6eac5bc 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultJSONEncoder.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/VerifyResultJSONEncoder.java
@@ -7,8 +7,8 @@ import java.io.OutputStream;
import java.security.cert.CertificateEncodingException;
import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/ExceptionFormatter.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/ExceptionFormatter.java
new file mode 100644
index 00000000..8d5f1cea
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/ExceptionFormatter.java
@@ -0,0 +1,17 @@
+package at.gv.egiz.pdfas.web.json_api;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import java.util.Map;
+
+@RestControllerAdvice(basePackages = "at.gv.egiz.pdfas.web.json_api")
+public class ExceptionFormatter {
+ @ExceptionHandler(jakarta.xml.ws.WebServiceException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public Map<String, Object> mapError(jakarta.xml.ws.WebServiceException e) {
+ return Map.of("error", e.getMessage());
+ }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/JacksonConfig.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/JacksonConfig.java
new file mode 100644
index 00000000..9d316f74
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/JacksonConfig.java
@@ -0,0 +1,26 @@
+package at.gv.egiz.pdfas.web.json_api;
+
+import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
+import tools.jackson.databind.cfg.EnumFeature;
+import tools.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationModule;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/** To match how SOAP serializes enum values */
+@Configuration
+public class JacksonConfig {
+ @Bean
+ public JsonMapperBuilderCustomizer enumsShouldUseToStringToMatchXML() {
+ return b -> b.enable(
+ EnumFeature.WRITE_ENUMS_USING_TO_STRING,
+ EnumFeature.READ_ENUMS_USING_TO_STRING
+ );
+ }
+
+ @Bean
+ public JsonMapperBuilderCustomizer useJaxbJsonNames() {
+ return b -> b.addModule(
+ new JakartaXmlBindAnnotationModule()
+ );
+ }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/SignController.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/SignController.java
new file mode 100644
index 00000000..e20e7ad0
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/SignController.java
@@ -0,0 +1,37 @@
+package at.gv.egiz.pdfas.web.json_api;
+
+import at.gv.egiz.pdfas.api.ws.*;
+import at.gv.egiz.pdfas.web.ws.PDFASSigningImpl;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/v2/sign")
+@AllArgsConstructor
+public class SignController {
+ private final PDFASSigningImpl signingImpl;
+
+ @PostMapping(value = "/single", consumes = "application/json", produces = "application/json")
+ public PDFASSignResponse signSingle(@RequestBody PDFASSignRequest request) {
+ return signingImpl.signPDFDokument(request);
+ }
+
+ @PostMapping(value = "/bulk", consumes = "application/json", produces = "application/json")
+ public PDFASBulkSignResponse signBulk(@RequestBody PDFASBulkSignRequest request) {
+ return signingImpl.signPDFDokument(request);
+ }
+
+ @PostMapping(value = "/multiple", consumes = "application/json", produces = "application/json")
+ public PdfasSignMultipleResponse signMultiple(@RequestBody PdfasSignMultipleRequest request) {
+ return signingImpl.signPDFDokument(request);
+ }
+
+ @PostMapping(value = "/multiple/get-result", consumes = "application/json", produces = "application/json")
+ public PdfasSignMultipleResponse getMultiple(@RequestBody PdfasGetMultipleRequest request) {
+ return signingImpl.getSignedDokument(request);
+ }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/SoapLogicBridgeBean.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/SoapLogicBridgeBean.java
new file mode 100644
index 00000000..b35abfd1
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/SoapLogicBridgeBean.java
@@ -0,0 +1,15 @@
+package at.gv.egiz.pdfas.web.json_api;
+
+import at.gv.egiz.pdfas.web.ws.PDFASSigningImpl;
+import at.gv.egiz.pdfas.web.ws.PDFASVerificationImpl;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/** Exposes the SOAP service implementations as Spring beans to new code */
+@Configuration
+public class SoapLogicBridgeBean {
+ @Bean
+ public PDFASSigningImpl signingImplBridge() { return new PDFASSigningImpl(); }
+ @Bean
+ public PDFASVerificationImpl verificationImplBridge() { return new PDFASVerificationImpl(); }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/VerifyController.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/VerifyController.java
new file mode 100644
index 00000000..83e287a9
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/json_api/VerifyController.java
@@ -0,0 +1,22 @@
+package at.gv.egiz.pdfas.web.json_api;
+
+import at.gv.egiz.pdfas.api.ws.PDFASVerifyRequest;
+import at.gv.egiz.pdfas.api.ws.PDFASVerifyResponse;
+import at.gv.egiz.pdfas.web.ws.PDFASVerificationImpl;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/v2/verify")
+@AllArgsConstructor
+public class VerifyController {
+ private final PDFASVerificationImpl verifyImpl;
+
+ @PostMapping(consumes = "application/json", produces = "application/json")
+ public PDFASVerifyResponse verify(@RequestBody PDFASVerifyRequest request) {
+ return verifyImpl.verifyPDFDokument(request);
+ }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java
index 50c3b063..f98e5a7b 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java
@@ -25,13 +25,14 @@ package at.gv.egiz.pdfas.web.servlets;
import java.io.IOException;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.MultipartConfig;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.bind.JAXBElement;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.MultipartConfig;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.xml.bind.JAXBElement;
+import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -78,41 +79,58 @@ public class DataURLServlet extends HttpServlet {
}
protected void process(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
- try {
+ HttpServletResponse response) throws ServletException, IOException {
+ String xmlResponse = null;
+ try {
if(!PdfAsHelper.checkDataUrlAccess(request)) {
throw new Exception("No valid dataURL access");
+
}
PdfAsHelper.setFromDataUrl(request);
- String xmlResponse = request.getParameter("XMLResponse");
+ xmlResponse = request.getParameter("XMLResponse");
- //System.out.println(xmlResponse);
+ if (StringUtils.isEmpty(xmlResponse)) {
+ logger.error("SL response is null or empty");
+ throw new PdfAsSecurityLayerException("SL response is null or empty", 9999);
+
+ }
JAXBElement<?> jaxbObject = (JAXBElement<?>) SLMarschaller.unmarshalFromString(xmlResponse);
if(jaxbObject.getValue() instanceof InfoboxReadResponseType) {
InfoboxReadResponseType infoboxReadResponseType = (InfoboxReadResponseType)jaxbObject.getValue();
logger.info("Got InfoboxReadResponseType");
PdfAsHelper.injectCertificate(request, response, PdfAsHelper.getCertificate(infoboxReadResponseType), getServletContext());
+
} else if(jaxbObject.getValue() instanceof CreateCMSSignatureResponseType) {
CreateCMSSignatureResponseType createCMSSignatureResponseType = (CreateCMSSignatureResponseType)jaxbObject.getValue();
logger.info("Got CreateCMSSignatureResponseType");
PdfAsHelper.injectSignature(request, response, createCMSSignatureResponseType.getCMSSignature(), getServletContext());
+
} else if(jaxbObject.getValue() instanceof ErrorResponseType) {
ErrorResponseType errorResponseType = (ErrorResponseType)jaxbObject.getValue();
logger.warn("SecurityLayer: " + errorResponseType.getErrorCode() + " " + errorResponseType.getInfo());
- throw new PdfAsSecurityLayerException(errorResponseType.getInfo(),
- errorResponseType.getErrorCode());
+ throw new PdfAsSecurityLayerException(errorResponseType.getInfo(), errorResponseType.getErrorCode());
+
} else {
logger.error("Unknown SL response {}", xmlResponse);
- throw new PdfAsSecurityLayerException("Unknown SL response",
- 9999);
+ throw new PdfAsSecurityLayerException("Unknown SL response", 9999);
+
}
- } catch (Exception e) {
- logger.warn("Error in DataURL Servlet. " , e);
- PdfAsHelper.setSessionException(request, response, e.getMessage(),
- e);
+
+ } catch (PdfAsSecurityLayerException e) {
+ PdfAsHelper.setSessionException(request, response, e.getMessage(), e);
+ PdfAsHelper.gotoError(getServletContext(), request, response);
+
+ } catch (Exception e) {
+ logger.debug("Receive XML response from VDA: {}",
+ StringUtils.isNotEmpty(xmlResponse) ? xmlResponse : " ...empty response...");
+ logger.warn("General Error in DataURL Servlet. " , e);
+
+ PdfAsHelper.setSessionException(request, response, e.getMessage(),
+ new PdfAsSecurityLayerException("Invalid SL response", 9999, e));
PdfAsHelper.gotoError(getServletContext(), request, response);
+
}
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java
index 42236f5e..38d883fa 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java
@@ -26,13 +26,14 @@ package at.gv.egiz.pdfas.web.servlets;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
-import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.text.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -141,13 +142,13 @@ public class ErrorPage extends HttpServlet {
if (e != null && WebConfiguration.isShowErrorDetails()) {
template = template.replace("##CAUSE##",
- URLEncoder.encode(e.getMessage(), "UTF-8"));
+ URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8));
} else {
template = template.replace("##CAUSE##", "");
}
if (message != null) {
template = template.replace("##ERROR##",
- URLEncoder.encode(message, "UTF-8"));
+ URLEncoder.encode(message, StandardCharsets.UTF_8));
} else {
template = template.replace("##ERROR##",
"Unbekannter Fehler");
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java
index 957614b1..546b07ac 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java
@@ -28,14 +28,15 @@ import java.io.IOException;
import java.util.List;
import java.util.Map;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import at.gv.egiz.pdfas.web.config.PdfAsWebSpringConfiguration;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import lombok.val;
+import org.apache.commons.fileupload2.core.DiskFileItem;
+import org.apache.commons.fileupload2.core.DiskFileItemFactory;
import at.gv.egiz.pdfas.api.processing.CoreSignParams;
import at.gv.egiz.pdfas.api.processing.DocumentToSign;
@@ -61,16 +62,21 @@ import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source;
import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status;
import at.gv.egiz.pdfas.web.stats.StatisticFrontend;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletDiskFileUpload;
+import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.boot.web.servlet.ServletRegistration;
+import org.springframework.stereotype.Component;
/**
* Servlet implementation class Sign
*/
@Slf4j
+@Component
+@ServletRegistration(urlMappings = "/Sign")
public class ExternSignServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
-
- public static final String PDF_AS_WEB_CONF = "pdf-as-web.conf";
private static final String UPLOAD_PDF_DATA = "pdf-file";
private static final String UPLOAD_DIRECTORY = "upload";
@@ -79,15 +85,8 @@ public class ExternSignServlet extends HttpServlet {
* Default constructor.
*/
- public ExternSignServlet(){
- String webconfig = System.getProperty(PDF_AS_WEB_CONF);
-
- if(webconfig == null) {
- log.error("No web configuration provided! Please specify: " + PDF_AS_WEB_CONF);
- throw new RuntimeException("No web configuration provided! Please specify: " + PDF_AS_WEB_CONF);
- }
-
- WebConfiguration.configure(webconfig);
+ public ExternSignServlet(final PdfAsWebSpringConfiguration config) {
+ WebConfiguration.configure(config.getPdfAsWebConfPath());
PdfAsHelper.init();
try {
@@ -176,7 +175,7 @@ public class ExternSignServlet extends HttpServlet {
byte[] filecontent = null;
// checks if the request actually contains upload file
- if (!ServletFileUpload.isMultipartContent(request)) {
+ if (!JakartaServletFileUpload.isMultipartContent(request)) {
// No Uploaded data!
if (PdfAsParameterExtractor.getPdfUrl(request) != null) {
doGet(request, response);
@@ -187,14 +186,14 @@ public class ExternSignServlet extends HttpServlet {
} else {
// configures upload settings
- DiskFileItemFactory factory = new DiskFileItemFactory();
- factory.setSizeThreshold(WebConfiguration.getFilesizeThreshold());
- factory.setRepository(new File(System
- .getProperty("java.io.tmpdir")));
+ DiskFileItemFactory factory = DiskFileItemFactory.builder()
+ .setThreshold(WebConfiguration.getFilesizeThreshold())
+ .setPath(new File(System.getProperty("java.io.tmpdir")).toPath())
+ .get();
- ServletFileUpload upload = new ServletFileUpload(factory);
- upload.setFileSizeMax(WebConfiguration.getMaxFilesize());
- upload.setSizeMax(WebConfiguration.getMaxRequestsize());
+ val upload = new JakartaServletDiskFileUpload(factory);
+ upload.setMaxFileSize(WebConfiguration.getMaxFilesize());
+ upload.setMaxSize(WebConfiguration.getMaxRequestsize());
// constructs the directory path to store upload file
String uploadPath = getServletContext().getRealPath("")
@@ -205,9 +204,9 @@ public class ExternSignServlet extends HttpServlet {
uploadDir.mkdir();
}
- List<?> formItems = upload.parseRequest(request);
+ List<DiskFileItem> formItems = upload.parseRequest(request);
log.debug(formItems.size() + " Items in form data");
- if (formItems.size() < 1) {
+ if (formItems.isEmpty()) {
// No Uploaded data!
// Try do get
// No Uploaded data!
@@ -219,41 +218,35 @@ public class ExternSignServlet extends HttpServlet {
"No Signature data defined!");
}
} else {
- for(int i = 0; i < formItems.size(); i++) {
- Object obj = formItems.get(i);
- if(obj instanceof FileItem) {
- FileItem item = (FileItem) obj;
- if(item.getFieldName().equals(UPLOAD_PDF_DATA)) {
- filecontent = item.get();
- try {
- File f = new File(item.getName());
- String name = f.getName();
- log.debug("Got upload: " + item.getName());
- if(name != null) {
- if(!(name.endsWith(".pdf") || name.endsWith(".PDF"))) {
- name += ".pdf";
- }
-
- log.debug("Setting Filename in session: " + name);
- PdfAsHelper.setPDFFileName(request, name);
- }
- }
- catch(Throwable e) {
- log.warn("In resolving filename", e);
- }
- if(filecontent.length < 10) {
- filecontent = null;
- } else {
- log.debug("Found pdf Data! Size: " + filecontent.length);
- }
- } else {
- request.setAttribute(item.getFieldName(), item.getString());
- log.debug("Setting " + item.getFieldName() + " = " + item.getString());
- }
- } else {
- log.debug(obj.getClass().getName() + " - " + obj.toString());
- }
- }
+ for (DiskFileItem item : formItems) {
+ if (item != null) {
+ if (item.getFieldName().equals(UPLOAD_PDF_DATA)) {
+ filecontent = item.getInputStream().readAllBytes();
+ try {
+ val filename = FilenameUtils.getName(item.getName());
+ File f = new File(filename);
+ String name = f.getName();
+ log.debug("Got upload: {}", filename);
+ if (!(name.endsWith(".pdf") || name.endsWith(".PDF"))) {
+ name += ".pdf";
+ }
+
+ log.debug("Setting Filename in session: " + name);
+ PdfAsHelper.setPDFFileName(request, name);
+ } catch (Throwable e) {
+ log.warn("In resolving filename", e);
+ }
+ if (filecontent.length < 10) {
+ filecontent = null;
+ } else {
+ log.debug("Found pdf Data! Size: " + filecontent.length);
+ }
+ } else {
+ request.setAttribute(item.getFieldName(), item.getString());
+ log.debug("Setting " + item.getFieldName() + " = " + item.getString());
+ }
+ }
+ }
}
}
@@ -315,13 +308,15 @@ public class ExternSignServlet extends HttpServlet {
}
// Get Connector
- String connector = PdfAsParameterExtractor.getConnector(request);
+ Connector connector = PdfAsParameterExtractor.getConnector(request);
+ String keyIdentifier = PdfAsParameterExtractor.getKeyIdentifier(request);
+ PdfAsHelper.checkConnectorSupported(connector, keyIdentifier);
String transactionId = PdfAsParameterExtractor.getTransactionId(request);
statisticEvent.setFilesize(pdfData.length);
statisticEvent.setProfileId(null);
- statisticEvent.setDevice(connector);
+ statisticEvent.setDevice(connector.toString());
String invokeUrl = PdfAsParameterExtractor.getInvokeURL(request);
PdfAsHelper.setInvokeURL(request, response, invokeUrl);
@@ -341,7 +336,7 @@ public class ExternSignServlet extends HttpServlet {
String locale = PdfAsParameterExtractor.getLocale(request);
PdfAsHelper.setLocale(request, response, locale);
- String responseMode = PdfAsParameterExtractor.getResonseMode(request);
+ String responseMode = PdfAsParameterExtractor.getResponseMode(request);
PdfAsHelper.setResponseMode(request, response, responseMode);
String filename = PdfAsParameterExtractor.getFilename(request);
@@ -365,8 +360,8 @@ public class ExternSignServlet extends HttpServlet {
CoreSignParams coreParams = new CoreSignParams();
coreParams.setSignatureBlockParameters(dynamicSignatureBlockArguments);
- coreParams.setConnector(Connector.fromString(connector));
- coreParams.setKeyIdentifier(PdfAsParameterExtractor.getKeyIdentifier(request));
+ coreParams.setConnector(connector);
+ coreParams.setKeyIdentifier(keyIdentifier);
coreParams.setOverrides(PdfAsParameterExtractor.getOverwriteMap(request));
coreParams.setPreprocessor(PdfAsParameterExtractor.getPreProcessorMap(request));
coreParams.setInvokeErrorUrl(errorUrl);
@@ -388,67 +383,18 @@ public class ExternSignServlet extends HttpServlet {
//IPlainSigner signer;
- if (connector.equals("bku") || connector.equals("onlinebku") || connector.equals("mobilebku")
- || connector.equals("sl20")) {
+ if (Connector.isAsynchronous(connector)) {
// start asynchronous signature creation
-
- if(connector.equals("bku")) {
- if(WebConfiguration.getLocalBKUURL() == null) {
- throw new PdfAsWebException("Invalid connector bku is not supported");
- }
- }
- if(connector.equals("mobilebku")) {
- if(WebConfiguration.getHandyBKUURL() == null) {
- throw new PdfAsWebException("Invalid connector mobilebku is not supported");
- }
- }
- if(connector.equals("onlinebku")) {
- if(WebConfiguration.getOnlineBKUURL() == null) {
- throw new PdfAsWebException("Invalid connector bku is not supported");
- }
- }
- if (connector.equals("sl20")) {
- if(WebConfiguration.getSecurityLayer20URL() == null) {
- throw new PdfAsWebException("Invalid connector bku is not supported");
- }
- }
PdfAsHelper.setStatisticEvent(request, response, statisticEvent);
- // sign document
+ // sign document
PdfAsHelper.startSignature(request, response, getServletContext(), connector, data);
return;
- } else if (connector.equals("jks") || connector.equals("moa")) {
- // start synchronous siganture creation
-
- if(connector.equals("jks")) {
-
- String keyIdentifier = PdfAsParameterExtractor.getKeyIdentifier(request);
-
- boolean ksEnabled = false;
-
- if (keyIdentifier != null) {
- ksEnabled = WebConfiguration.getKeystoreEnabled(keyIdentifier);
- } else {
- ksEnabled = WebConfiguration.getKeystoreDefaultEnabled();
- }
-
- if (!ksEnabled) {
- if(keyIdentifier != null) {
- throw new PdfAsWebException("JKS connector [" + keyIdentifier + "] disabled or not existing.");
- } else {
- throw new PdfAsWebException("DEFAULT JKS connector disabled.");
- }
- }
- }
-
- if(connector.equals("moa")) {
- if(!WebConfiguration.getMOASSEnabled()) {
- throw new PdfAsWebException("Invalid connector moa is not supported");
- }
- }
+ } else {
+ // start synchronous signature creation
// sign document
PdfasSignResponse pdfSignedData = PdfAsHelper.synchronousServerSignature(data);
@@ -466,9 +412,6 @@ public class ExternSignServlet extends HttpServlet {
PdfAsHelper.gotoProvidePdf(getServletContext(), request, response);
return;
- } else {
- throw new PdfAsWebException("Invalid connector (bku | moa | jks)");
-
}
}
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java
index d5ef2079..a9b282a2 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/JSONAPIServlet.java
@@ -1,14 +1,15 @@
package at.gv.egiz.pdfas.web.servlets;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
@@ -65,7 +66,7 @@ public class JSONAPIServlet extends HttpServlet {
return;
}
- String jsonString = IOUtils.toString(req.getInputStream(), "UTF-8");
+ String jsonString = IOUtils.toString(req.getInputStream(), StandardCharsets.UTF_8);
logger.debug("Reading json String {}", jsonString);
@@ -86,7 +87,7 @@ public class JSONAPIServlet extends HttpServlet {
String profile = jsonObject.has(JSON_PROFILE) ? jsonObject.getString(JSON_PROFILE) : null;
String position = jsonObject.has(JSON_POSITION) ? jsonObject.getString(JSON_POSITION) : null;
- String connector = jsonObject.getString(JSON_CONNECTOR);
+ Connector connector = Connector.fromString(jsonObject.getString(JSON_CONNECTOR));
String input = jsonObject.getString(JSON_INPUT);
String requestID = jsonObject.has(JSON_REQUEST_ID) ? jsonObject.getString(JSON_REQUEST_ID) : null;
@@ -105,40 +106,14 @@ public class JSONAPIServlet extends HttpServlet {
try {
- if(connector == null) {
- throw new ServletException(
- "Invalid connector value!");
- }
-
- PDFASSignParameters.Connector connectorEnum = null;
-
- if(PDFASSignParameters.Connector.MOA.equalsName(connector)) {
- connectorEnum = PDFASSignParameters.Connector.MOA;
- } else if(PDFASSignParameters.Connector.JKS.equalsName(connector)) {
- connectorEnum = PDFASSignParameters.Connector.JKS;
- } else if(PDFASSignParameters.Connector.BKU.equalsName(connector)) {
- connectorEnum = PDFASSignParameters.Connector.BKU;
- } else if(PDFASSignParameters.Connector.MOBILEBKU.equalsName(connector)) {
- connectorEnum = PDFASSignParameters.Connector.MOBILEBKU;
- } else if(PDFASSignParameters.Connector.ONLINEBKU.equalsName(connector)) {
- connectorEnum = PDFASSignParameters.Connector.ONLINEBKU;
- } else if(PDFASSignParameters.Connector.SECLAYER20.equalsName(connector)) {
- connectorEnum = PDFASSignParameters.Connector.SECLAYER20;
- }
-
- if(connectorEnum == null) {
- throw new ServletException(
- "Invalid connector value!");
- }
-
- // TODO: check connector is enabled!
+ PdfAsHelper.checkConnectorSupported(connector, null);
statisticEvent.setFilesize(inputDocument.length);
statisticEvent.setProfileId(profile);
- statisticEvent.setDevice(connector);
+ statisticEvent.setDevice(connector.toString());
PDFASSignParameters parameters = new PDFASSignParameters();
- parameters.setConnector(connectorEnum);
+ parameters.setConnector(connector);
parameters.setPosition(position);
parameters.setProfile(profile);
@@ -155,8 +130,8 @@ public class JSONAPIServlet extends HttpServlet {
signatureBlockParametersMap.put(values[0], values[1]);
}
}
- }catch(Exception e){
- e.printStackTrace();
+ } catch(Exception e) {
+ logger.warn("Failed to process JSON sbp parameter", e);
}
@@ -166,7 +141,7 @@ public class JSONAPIServlet extends HttpServlet {
CoreSignParams coreParams = new CoreSignParams();
coreParams.setSignatureBlockParameters(signatureBlockParametersMap);
- coreParams.setConnector(Connector.fromString(connector));
+ coreParams.setConnector(connector);
data.setCoreParams(coreParams);
DocumentToSign document = new DocumentToSign();
@@ -177,8 +152,7 @@ public class JSONAPIServlet extends HttpServlet {
- if (PDFASSignParameters.Connector.MOA.equals(connectorEnum)
- || PDFASSignParameters.Connector.JKS.equals(connectorEnum)) {
+ if (!Connector.isAsynchronous(connector)) {
// Plain server based signatures!!
@@ -235,36 +209,8 @@ public class JSONAPIServlet extends HttpServlet {
// start asynchronous signature creation
- if (PDFASSignParameters.Connector.BKU.equals(connectorEnum)) {
- if (WebConfiguration.getLocalBKUURL() == null) {
- throw new PdfAsWebException(
- "Invalid connector bku is not supported");
- }
- }
-
- if (PDFASSignParameters.Connector.ONLINEBKU.equals(connectorEnum)) {
- if (WebConfiguration.getLocalBKUURL() == null) {
- throw new PdfAsWebException(
- "Invalid connector onlinebku is not supported");
- }
- }
-
- if (PDFASSignParameters.Connector.MOBILEBKU.equals(connectorEnum)) {
- if (WebConfiguration.getLocalBKUURL() == null) {
- throw new PdfAsWebException(
- "Invalid connector mobilebku is not supported");
- }
- }
-
- if (PDFASSignParameters.Connector.SECLAYER20.equals(connectorEnum)) {
- if (WebConfiguration.getSecurityLayer20URL() == null) {
- throw new PdfAsWebException(
- "Invalid connector mobilebku is not supported");
- }
- }
-
- PdfAsHelper.startSignatureJson(request, response, getServletContext(),
- connectorEnum.toString(), data);
+ PdfAsHelper.startSignatureJson(request, response, getServletContext(),
+ connector, data);
JSONStartResponse jsonStartResponse = PdfAsHelper.startJsonProcess(request, response, getServletContext());
@@ -279,7 +225,7 @@ public class JSONAPIServlet extends HttpServlet {
}
response.setContentType("application/json");
- IOUtils.write(jsonResponse.toString(), response.getOutputStream(), "UTF-8");
+ IOUtils.write(jsonResponse.toString(), response.getOutputStream(), StandardCharsets.UTF_8);
} catch (Throwable e) {
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java
index 96d02f16..e7556569 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java
@@ -34,10 +34,10 @@ import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import at.gv.egiz.pdfas.api.processing.PdfasSignResponse;
import at.gv.egiz.pdfas.api.processing.SignedDocument;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureCertificateData.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureCertificateData.java
index e4465e77..bf3f3f85 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureCertificateData.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureCertificateData.java
@@ -28,10 +28,10 @@ import java.io.OutputStream;
import java.security.cert.CertificateEncodingException;
import java.util.List;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -95,15 +95,16 @@ public class PDFSignatureCertificateData extends HttpServlet {
"Content-Disposition",
"inline;filename=cert_" + id + ".cer");
response.setContentType("application/pkix-cert");
+ response.setHeader("X-Content-Type-Options", "nosniff");
OutputStream os = response.getOutputStream();
os.write(res.getSignerCertificate().getEncoded());
os.close();
} else {
- logger.warn("Verification CERT not found! for id " + request.getParameter(SIGN_ID) + " in session " + request.getSession().getId());
+ logger.warn("Verification CERT not found! for id {} in session {}", request.getParameter(SIGN_ID), request.getSession().getId());
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} catch (NumberFormatException e) {
- logger.warn("Verification CERT not found! for id " + request.getParameter(SIGN_ID) + " in session " + request.getSession().getId());
+ logger.warn("Verification CERT not found! for id {} in session {}", request.getParameter(SIGN_ID), request.getSession().getId());
response.sendError(HttpServletResponse.SC_NOT_FOUND);
} catch (PdfAsException e) {
logger.warn("Verification CERT not found:", e);
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureData.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureData.java
index e493f4ae..14f13f05 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureData.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFSignatureData.java
@@ -27,10 +27,10 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -94,15 +94,16 @@ public class PDFSignatureData extends HttpServlet {
"Content-Disposition",
"inline;filename=signed_data_" + id + ".pdf");
response.setContentType("application/pdf");
+ response.setHeader("X-Content-Type-Options", "nosniff");
OutputStream os = response.getOutputStream();
- os.write(res.getSignatureData());
+ os.write(res.getSignatureData().getBaseData());
os.close();
} else {
- logger.warn("Verification DATA not found! for id " + request.getParameter(SIGN_ID) + " in session " + request.getSession().getId());
+ logger.warn("Verification DATA not found! for id {} in session {}", request.getParameter(SIGN_ID), request.getSession().getId());
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} catch (NumberFormatException e) {
- logger.warn("Verification DATA not found! for id " + request.getParameter(SIGN_ID) + " in session " + request.getSession().getId());
+ logger.warn("Verification DATA not found! for id {} in session {}", request.getParameter(SIGN_ID), request.getSession().getId());
response.sendError(HttpServletResponse.SC_NOT_FOUND);
} catch (PdfAsException e) {
logger.warn("Verification DATA not found:", e);
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFURLData.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFURLData.java
index d4112cad..63172175 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFURLData.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFURLData.java
@@ -6,11 +6,11 @@ import at.gv.egiz.pdfas.lib.api.StatusRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.io.OutputStream;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PlaceholderGeneratorServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PlaceholderGeneratorServlet.java
index b07293b1..388c7e9d 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PlaceholderGeneratorServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PlaceholderGeneratorServlet.java
@@ -10,10 +10,10 @@ import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java
index 47469eb2..f6b42024 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java
@@ -26,15 +26,16 @@ package at.gv.egiz.pdfas.web.servlets;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.List;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
-import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.text.StringEscapeUtils;
import at.gv.egiz.pdfas.api.processing.SignedDocument;
import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
@@ -214,8 +215,8 @@ public class ProvidePDFServlet extends HttpServlet {
template = template.replace("##TARGET##", StringEscapeUtils.escapeHtml4(target));
template = template.replace("##PDFURL##",
- URLEncoder.encode(PdfAsHelper.generatePdfURL(request, response),
- "UTF-8"));
+ URLEncoder.encode(PdfAsHelper.generatePdfURL(request, response),
+ StandardCharsets.UTF_8));
response.setContentType("text/html");
response.getWriter().write(template);
response.getWriter().close();
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ReloadServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ReloadServlet.java
index 84e86634..89d33e80 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ReloadServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ReloadServlet.java
@@ -3,17 +3,26 @@ package at.gv.egiz.pdfas.web.servlets;
import java.io.IOException;
import java.io.OutputStream;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import at.gv.egiz.pdfas.web.config.PdfAsWebSpringConfiguration;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import at.gv.egiz.pdfas.web.config.WebConfiguration;
import at.gv.egiz.pdfas.web.helper.PdfAsHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.servlet.ServletRegistration;
+import org.springframework.stereotype.Component;
+@Slf4j
+@Component
+@ServletRegistration(urlMappings = "/Reload")
public class ReloadServlet extends HttpServlet {
/**
@@ -21,17 +30,12 @@ public class ReloadServlet extends HttpServlet {
*/
private static final long serialVersionUID = 6108555300743896727L;
- private static final Logger logger = LoggerFactory
- .getLogger(ReloadServlet.class);
-
- public static final String PDF_AS_WEB_CONF = "pdf-as-web.conf";
public static final String PARAM_PASSWD = "PASSWD";
- /**
- * @see HttpServlet#HttpServlet()
- */
- public ReloadServlet() {
+ private final PdfAsWebSpringConfiguration config;
+ public ReloadServlet(final PdfAsWebSpringConfiguration config) {
super();
+ this.config = config;
}
/**
@@ -42,15 +46,15 @@ public class ReloadServlet extends HttpServlet {
HttpServletResponse response) throws ServletException, IOException {
if(!WebConfiguration.getReloadEnabled()) {
- logger.info("Reload Servlet disabled. " + request.getRemoteAddr() + " tried to call it");
+ log.info("Reload Servlet disabled. " + request.getRemoteAddr() + " tried to call it");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentLength(0);
return;
}
- logger.info("Called Reload Servlet from: " + request.getRemoteAddr());
+ log.info("Called Reload Servlet from: " + request.getRemoteAddr());
- logger.info("Checking Password!");
+ log.info("Checking Password!");
String pwd = request.getParameter(PARAM_PASSWD);
@@ -66,17 +70,11 @@ public class ReloadServlet extends HttpServlet {
return;
}
- String webconfig = System.getProperty(PDF_AS_WEB_CONF);
-
- if(webconfig == null) {
- logger.error("No web configuration provided! Please specify: " + PDF_AS_WEB_CONF);
- throw new RuntimeException("No web configuration provided! Please specify: " + PDF_AS_WEB_CONF);
- }
-
+ String webconfig = config.getPdfAsWebConfPath();
WebConfiguration.configure(webconfig);
PdfAsHelper.reloadConfig();
- logger.info("Reloaded!");
+ log.info("Reloaded!");
StringBuilder sb = new StringBuilder();
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SLDataURLServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SLDataURLServlet.java
index 55946afb..9f144f84 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SLDataURLServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SLDataURLServlet.java
@@ -1,16 +1,17 @@
package at.gv.egiz.pdfas.web.servlets;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.MultipartConfig;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.MultipartConfig;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.jose4j.base64url.Base64Url;
@@ -81,7 +82,7 @@ public class SLDataURLServlet extends HttpServlet {
String sl20Result = request.getParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM);
if (StringUtils.isEmpty(sl20Result)) {
//Workaround for SIC Handy-Signature, because it sends result in InputStream
- String isReqInput = StreamUtils.readStream(request.getInputStream(), "UTF-8");
+ String isReqInput = StreamUtils.readStream(request.getInputStream(), StandardCharsets.UTF_8);
if (StringUtils.isNotEmpty(isReqInput)) {
logger.info("Use SIC Handy-Signature work-around!");
sl20Result = isReqInput.substring("slcommand=".length());
@@ -93,17 +94,16 @@ public class SLDataURLServlet extends HttpServlet {
}
- logger.trace("Received SL2.0 command: " + sl20Result);
+ logger.trace("Received SL2.0 command: {}", sl20Result);
//parse SL2.0 command/result into JSON
try {
- JsonParser jsonParser = new JsonParser();
- JsonElement sl20Req = jsonParser.parse(Base64Url.decodeToUtf8String(sl20Result));
+ JsonElement sl20Req = JsonParser.parseString(Base64Url.decodeToUtf8String(sl20Result));
sl20ReqObj = sl20Req.getAsJsonObject();
} catch (JsonSyntaxException e) {
logger.warn("SL2.0 command or result is NOT valid JSON.", e);
- logger.debug("SL2.0 msg: " + sl20Result);
+ logger.debug("SL2.0 msg: {}", sl20Result);
throw new SL20Exception("sl20.02", e);
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SoapServiceServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SoapServiceServlet.java
index ca005abe..8b97d7f7 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SoapServiceServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/SoapServiceServlet.java
@@ -1,15 +1,24 @@
package at.gv.egiz.pdfas.web.servlets;
-import javax.servlet.ServletConfig;
-import javax.xml.ws.Endpoint;
+import jakarta.servlet.ServletConfig;
+import jakarta.xml.ws.Endpoint;
+import lombok.extern.slf4j.Slf4j;
+import lombok.val;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
+import org.apache.cxf.jaxws.EndpointImpl;
+import org.apache.cxf.logging.FaultListener;
+import org.apache.cxf.message.Message;
import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
import at.gv.egiz.pdfas.web.ws.PDFASSigningImpl;
import at.gv.egiz.pdfas.web.ws.PDFASVerificationImpl;
+import java.util.LinkedList;
+import java.util.List;
+
+@Slf4j
public class SoapServiceServlet extends CXFNonSpringServlet {
/**
@@ -17,24 +26,47 @@ public class SoapServiceServlet extends CXFNonSpringServlet {
*/
private static final long serialVersionUID = -8903883276191902043L;
+ @Slf4j
+ public static class Faults implements FaultListener {
+ @Override
+ public boolean faultOccurred(Exception exception, String description, Message message) {
+ String operation = "-";
+ if (message != null && message.getExchange() != null) {
+ val boi = message.getExchange().getBindingOperationInfo();
+ if (boi != null && boi.getName() != null) {
+ operation = boi.getName().toString();
+ }
+ }
+
+ log.error("Unhandled SOAP fault in operation {}: {}", operation, description, exception);
+ return false;
+ }
+ }
+
+ private final List<EndpointImpl> endpoints = new LinkedList<>();
@Override
protected void loadBus(ServletConfig sc) {
- super.loadBus(sc);
-
// You could add the endpoint publish codes here
- Bus bus = this.getBus();
- BusFactory.setDefaultBus(bus);
- Endpoint signEp = Endpoint.publish("/wssign", new PDFASSigningImpl());
- /*
- * SOAPBinding signBinding = (SOAPBinding)signEp.getBinding();
- signBinding.setMTOMEnabled(true);
- */
-
- Endpoint verifyEp = Endpoint.publish("/wsverify", new PDFASVerificationImpl());
- /*
- SOAPBinding verifyBinding = (SOAPBinding)verifyEp.getBinding();
- verifyBinding.setMTOMEnabled(true);
- */
-
+ Bus bus = BusFactory.newInstance(BusFactory.DEFAULT_BUS_FACTORY).createBus();
+ bus.setProperty(FaultListener.class.getName(), new Faults());
+ setBus(bus);
+
+ val signingEndpoint = new EndpointImpl(bus, new PDFASSigningImpl());
+ endpoints.add(signingEndpoint);
+ signingEndpoint.publish("/wssign");
+
+ val verificationEndpoint = new EndpointImpl(bus, new PDFASVerificationImpl());
+ endpoints.add(verificationEndpoint);
+ verificationEndpoint.publish("/wsverify");
+ }
+
+ @Override
+ public void destroyBus() {
+ endpoints.forEach(p -> {
+ try { p.close(); } catch (Exception e) { log.warn("Failed to close endpoint cleanly", e); }
+ });
+ endpoints.clear();
+ BusFactory.clearDefaultBusForAnyThread(getBus());
+ super.destroyBus();
}
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java
index d7a3d3c6..51cc5573 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/UIEntryPointServlet.java
@@ -25,10 +25,10 @@ package at.gv.egiz.pdfas.web.servlets;
import java.io.IOException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import at.gv.egiz.pdfas.api.processing.PdfasSignRequest;
import at.gv.egiz.pdfas.api.ws.PDFASSignParameters.Connector;
@@ -42,6 +42,7 @@ import at.gv.egiz.pdfas.web.helper.PdfAsHelper;
import at.gv.egiz.pdfas.web.stats.StatisticEvent;
import at.gv.egiz.pdfas.web.store.RequestStore;
import lombok.extern.slf4j.Slf4j;
+import lombok.val;
@Slf4j
public class UIEntryPointServlet extends HttpServlet {
@@ -76,20 +77,21 @@ public class UIEntryPointServlet extends HttpServlet {
throw new PdfAsStoreException("Wrong Parameters");
}
- PdfasSignRequest pdfAsRequest = RequestStore.getInstance()
+ val storeEntry = RequestStore.getInstance()
.fetchStoreEntry(storeId);
- if (pdfAsRequest == null) {
+ if (storeEntry == null) {
throw new PdfAsStoreException("Invalid " + REQUEST_ID_PARAM
+ " value");
}
- StatisticEvent statisticEvent = RequestStore.getInstance()
- .fetchStatisticEntry(storeId);
+ val pdfAsRequest = storeEntry.getFirst();
+ val statisticEvent = storeEntry.getSecond();
PdfAsHelper.setStatisticEvent(req, resp, statisticEvent);
Connector connector = pdfAsRequest.getCoreParams().getConnector();
+ PdfAsHelper.checkConnectorSupported(connector, null);
String invokeUrl = pdfAsRequest.getCoreParams().getInvokeUrl();
PdfAsHelper.setInvokeURL(req, resp, invokeUrl);
@@ -125,41 +127,10 @@ public class UIEntryPointServlet extends HttpServlet {
log.debug("Starting signature creation with: " + connector);
// IPlainSigner signer;
- if (connector.equals(Connector.BKU)
- || connector.equals(Connector.ONLINEBKU)
- || connector.equals(Connector.MOBILEBKU)
- || connector.equals(Connector.SECLAYER20)) {
+ if (Connector.isAsynchronous(connector)) {
// start asynchronous signature creation
-
- if (connector.equals(Connector.BKU)) {
- if (WebConfiguration.getLocalBKUURL() == null) {
- throw new PdfAsWebException(
- "Invalid connector bku is not supported");
- }
- }
-
- if (connector.equals(Connector.ONLINEBKU)) {
- if (WebConfiguration.getOnlineBKUURL() == null) {
- throw new PdfAsWebException(
- "Invalid connector onlinebku is not supported");
- }
- }
-
- if (connector.equals(Connector.MOBILEBKU)) {
- if (WebConfiguration.getHandyBKUURL() == null) {
- throw new PdfAsWebException(
- "Invalid connector mobilebku is not supported");
- }
- }
-
- if (connector.equals(Connector.SECLAYER20)) {
- if (WebConfiguration.getSecurityLayer20URL() == null) {
- throw new PdfAsWebException(
- "Invalid connector mobilebku is not supported");
- }
- }
- PdfAsHelper.startSignature(req, resp, getServletContext(), connector.toString(), pdfAsRequest);
+ PdfAsHelper.startSignature(req, resp, getServletContext(), connector, pdfAsRequest);
} else {
throw new PdfAsWebException("Invalid connector ("
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java
index 003a4a73..2334597a 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VerifyServlet.java
@@ -27,14 +27,18 @@ import java.io.File;
import java.io.IOException;
import java.util.List;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import lombok.val;
+import org.apache.commons.fileupload2.core.DiskFileItem;
+import org.apache.commons.fileupload2.core.FileItem;
+import org.apache.commons.fileupload2.core.DiskFileItemFactory;
+import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletDiskFileUpload;
+import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload;
+import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,10 +58,15 @@ import at.gv.egiz.pdfas.web.stats.StatisticEvent.Operation;
import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source;
import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status;
import at.gv.egiz.pdfas.web.stats.StatisticFrontend;
+import org.springframework.boot.web.servlet.ServletRegistration;
+import org.springframework.stereotype.Component;
/**
* Servlet implementation class VerifyServlet
*/
+
+@Component
+@ServletRegistration(urlMappings = "/Verify")
public class VerifyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@@ -159,7 +168,7 @@ public class VerifyServlet extends HttpServlet {
byte[] filecontent = null;
// checks if the request actually contains upload file
- if (!ServletFileUpload.isMultipartContent(request)) {
+ if (!JakartaServletFileUpload.isMultipartContent(request)) {
// No Uploaded data!
if (PdfAsParameterExtractor.getPdfUrl(request) != null) {
doGet(request, response);
@@ -169,14 +178,14 @@ public class VerifyServlet extends HttpServlet {
}
} else {
// configures upload settings
- DiskFileItemFactory factory = new DiskFileItemFactory();
- factory.setSizeThreshold(THRESHOLD_SIZE);
- factory.setRepository(new File(System
- .getProperty("java.io.tmpdir")));
+ DiskFileItemFactory factory = DiskFileItemFactory.builder()
+ .setThreshold(THRESHOLD_SIZE)
+ .setPath(new File(System.getProperty("java.io.tmpdir")).toPath())
+ .get();
- ServletFileUpload upload = new ServletFileUpload(factory);
- upload.setFileSizeMax(MAX_FILE_SIZE);
- upload.setSizeMax(MAX_REQUEST_SIZE);
+ val upload = new JakartaServletDiskFileUpload(factory);
+ upload.setMaxFileSize(MAX_FILE_SIZE);
+ upload.setMaxSize(MAX_REQUEST_SIZE);
// constructs the directory path to store upload file
String uploadPath = getServletContext().getRealPath("")
@@ -187,9 +196,9 @@ public class VerifyServlet extends HttpServlet {
uploadDir.mkdir();
}
- List<?> formItems = upload.parseRequest(request);
+ List<DiskFileItem> formItems = upload.parseRequest(request);
logger.debug(formItems.size() + " Items in form data");
- if (formItems.size() < 1) {
+ if (formItems.isEmpty()) {
// No Uploaded data!
// Try do get
// No Uploaded data!
@@ -201,48 +210,41 @@ public class VerifyServlet extends HttpServlet {
"No Signature data defined!");
}
} else {
- for (int i = 0; i < formItems.size(); i++) {
- Object obj = formItems.get(i);
- if (obj instanceof FileItem) {
- FileItem item = (FileItem) obj;
- if (item.getFieldName().equals(UPLOAD_PDF_DATA)) {
- filecontent = item.get();
- try {
- File f = new File(item.getName());
- String name = f.getName();
- logger.debug("Got upload: "
- + item.getName());
- if (name != null) {
- if (!(name.endsWith(".pdf") || name
- .endsWith(".PDF"))) {
- name += ".pdf";
- }
+ for (DiskFileItem item : formItems) {
+ if (item != null) {
+ if (item.getFieldName().equals(UPLOAD_PDF_DATA)) {
+ filecontent = item.getInputStream().readAllBytes();
+ try {
+ val filename = FilenameUtils.getName(item.getName());
+ File f = new File(filename);
+ String name = f.getName();
+ logger.debug("Got upload: {}", filename);
+ if (!(name.endsWith(".pdf") || name
+ .endsWith(".PDF"))) {
+ name += ".pdf";
+ }
- logger.debug("Setting Filename in session: "
- + name);
- PdfAsHelper.setPDFFileName(request,
- name);
- }
- } catch (Throwable e) {
- logger.warn("In resolving filename", e);
- }
- if (filecontent.length < 10) {
- filecontent = null;
- } else {
- logger.debug("Found pdf Data! Size: "
- + filecontent.length);
- }
- } else {
- request.setAttribute(item.getFieldName(),
- item.getString());
- logger.debug("Setting " + item.getFieldName()
- + " = " + item.getString());
- }
- } else {
- logger.debug(obj.getClass().getName() + " - "
- + obj.toString());
- }
- }
+ logger.debug("Setting Filename in session: "
+ + name);
+ PdfAsHelper.setPDFFileName(request,
+ name);
+ } catch (Throwable e) {
+ logger.warn("In resolving filename", e);
+ }
+ if (filecontent.length < 10) {
+ filecontent = null;
+ } else {
+ logger.debug("Found pdf Data! Size: "
+ + filecontent.length);
+ }
+ } else {
+ request.setAttribute(item.getFieldName(),
+ item.getString());
+ logger.debug("Setting " + item.getFieldName()
+ + " = " + item.getString());
+ }
+ }
+ }
}
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VisBlockServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VisBlockServlet.java
index b49264f7..eda6eef0 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VisBlockServlet.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/VisBlockServlet.java
@@ -4,10 +4,10 @@ import java.io.IOException;
import java.io.OutputStream;
import java.security.cert.CertificateException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -72,6 +72,7 @@ public class VisBlockServlet extends HttpServlet {
response.setHeader("Content-Disposition", "inline;filename="
+ profile + "_" + resolution + ".png");
response.setContentType("image/png");
+ response.setHeader("X-Content-Type-Options", "nosniff");
OutputStream os = response.getOutputStream();
os.write(imageData);
os.close();
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/JsonSecurityUtils.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/JsonSecurityUtils.java
index bf37b290..7a4d24ae 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/JsonSecurityUtils.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/JsonSecurityUtils.java
@@ -181,10 +181,10 @@ public class JsonSecurityUtils implements IJOSETools{
jws.setCompactSerialization(serializedContent);
//set security constrains
- jws.setAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.WHITELIST,
- SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])));
+ jws.setAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.PERMIT,
+ SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.toArray(new String[0])));
- //load signinc certs
+ //load signing certs
Key selectedKey = null;
List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue();
String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue();
@@ -232,7 +232,7 @@ public class JsonSecurityUtils implements IJOSETools{
//load payLoad
logger.debug("SL2.0 commando signature validation sucessfull");
- JsonElement sl20Req = new JsonParser().parse(jws.getPayload());
+ JsonElement sl20Req = JsonParser.parseString(jws.getPayload());
return new VerificationResult(sl20Req.getAsJsonObject(), null, valid) ;
@@ -252,11 +252,11 @@ public class JsonSecurityUtils implements IJOSETools{
//set security constrains
receiverJwe.setAlgorithmConstraints(
- new AlgorithmConstraints(ConstraintType.WHITELIST,
- SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.size()])));
+ new AlgorithmConstraints(ConstraintType.PERMIT,
+ SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.toArray(new String[0])));
receiverJwe.setContentEncryptionAlgorithmConstraints(
- new AlgorithmConstraints(ConstraintType.WHITELIST,
- SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.size()])));
+ new AlgorithmConstraints(ConstraintType.PERMIT,
+ SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.toArray(new String[0])));
//set payload
receiverJwe.setCompactSerialization(compactSerialization);
@@ -295,7 +295,7 @@ public class JsonSecurityUtils implements IJOSETools{
//decrypt payload
- return new JsonParser().parse(receiverJwe.getPlaintextString());
+ return JsonParser.parseString(receiverJwe.getPlaintextString());
} catch (JoseException e) {
logger.warn("SL2.0 result decryption FAILED", e);
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/SL20HttpBindingUtils.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/SL20HttpBindingUtils.java
index e43ebfcf..d59f649a 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/SL20HttpBindingUtils.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/sl20/SL20HttpBindingUtils.java
@@ -3,9 +3,10 @@ package at.gv.egiz.pdfas.web.sl20;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
@@ -27,7 +28,7 @@ public class SL20HttpBindingUtils {
log.debug("Client request containts 'native client' header ... ");
StringWriter writer = new StringWriter();
writer.write(sl20Forward.toString());
- final byte[] content = writer.toString().getBytes("UTF-8");
+ final byte[] content = writer.toString().getBytes(StandardCharsets.UTF_8);
response.setStatus(HttpServletResponse.SC_OK);
response.setContentLength(content.length);
response.setContentType(ContentType.APPLICATION_JSON.toString());
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticFrontend.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticFrontend.java
index f006be54..e78e63ab 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticFrontend.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/StatisticFrontend.java
@@ -23,23 +23,16 @@ public class StatisticFrontend implements StatisticBackend {
private List<StatisticBackend> statisticBackends = new ArrayList<StatisticBackend>();
private StatisticFrontend() {
- Iterator<StatisticBackend> statisticIterator = backendLoader.iterator();
List<String> enabledBackends = WebConfiguration.getStatisticBackends();
if (enabledBackends == null) {
- logger.info("No statitistic backends configured using all available.");
+ logger.info("No statistic backends configured, using all available.");
} else {
- Iterator<String> enabledBackendsIterator = enabledBackends
- .iterator();
logger.info("Allowing the following statistic backends:");
- while (enabledBackendsIterator.hasNext()) {
- logger.info(" - {}", enabledBackendsIterator.next());
- }
+ enabledBackends.forEach(it -> logger.info(" - {}", it));
}
- while (statisticIterator.hasNext()) {
- StatisticBackend statisticBackend = statisticIterator.next();
-
+ for (StatisticBackend statisticBackend : backendLoader) {
if (enabledBackends == null
|| enabledBackends.contains(statisticBackend.getName())) {
logger.info("adding Statistic Logger {} [{}]", statisticBackend
@@ -54,22 +47,8 @@ public class StatisticFrontend implements StatisticBackend {
}
if (enabledBackends != null) {
- Iterator<String> enabledBackendsIterator = enabledBackends
- .iterator();
- while (enabledBackendsIterator.hasNext()) {
- String enabledBackend = enabledBackendsIterator.next();
- statisticIterator = statisticBackends.iterator();
- boolean found = false;
- while (statisticIterator.hasNext()) {
- StatisticBackend statisticBackend = statisticIterator
- .next();
- if (statisticBackend.getName().equals(enabledBackend)) {
- found = true;
- break;
- }
- }
-
- if (!found) {
+ for (String enabledBackend : enabledBackends) {
+ if (statisticBackends.stream().noneMatch(it -> it.getName().equals(enabledBackend))) {
logger.warn(
"Failed to load statistic backend {}. Not in classpath?",
enabledBackend);
@@ -103,13 +82,7 @@ public class StatisticFrontend implements StatisticBackend {
return;
}
- Iterator<StatisticBackend> statisticBackendIterator = statisticBackends
- .iterator();
-
- while (statisticBackendIterator.hasNext()) {
- StatisticBackend statisticBackend = statisticBackendIterator.next();
- statisticBackend.storeEvent(statisticEvent);
- }
+ statisticBackends.forEach(statisticBackend -> statisticBackend.storeEvent(statisticEvent));
}
}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/impl/StatisticMicrometerBackend.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/impl/StatisticMicrometerBackend.java
new file mode 100644
index 00000000..8b8fb489
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/stats/impl/StatisticMicrometerBackend.java
@@ -0,0 +1,75 @@
+package at.gv.egiz.pdfas.web.stats.impl;
+
+import at.gv.egiz.pdfas.web.stats.StatisticBackend;
+import at.gv.egiz.pdfas.web.stats.StatisticEvent;
+import io.micrometer.core.instrument.Counter;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
+import io.micrometer.core.instrument.Timer;
+import lombok.extern.slf4j.Slf4j;
+import lombok.val;
+import org.jspecify.annotations.NonNull;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
+
+@Slf4j
+public class StatisticMicrometerBackend implements StatisticBackend {
+ /** bridge between ServiceLoader component and Boot's beans */
+ @Component
+ public static class SpringContextProxy {
+ public static MeterRegistry meterRegistry;
+ SpringContextProxy(MeterRegistry registry) { meterRegistry = registry; }
+ }
+ public static final String NAME = "StatisticMicrometerBackend";
+ @Override public String getName() { return NAME; }
+
+ @Override
+ public void storeEvent(StatisticEvent e) {
+ if (e == null) return;
+
+ MeterRegistry registry = SpringContextProxy.meterRegistry;
+ if (registry == null) {
+ log.warn("Spring MeterRegistry not available, skipped micrometer metric logging");
+ return;
+ }
+
+ Tags baseTags = Tags.of(
+ "operation", safeName(e.getOperation(), v -> v.getName()),
+ "status", safeName(e.getStatus(), v -> v.getName()),
+ "source", safeName(e.getSource(), v -> v.getName()),
+ "device", safeString(e.getDevice()),
+ "profile", safeString(e.getProfileId())
+ );
+
+ Timer.builder("pdfas_requests")
+ .description("Duration of PDF-AS operations")
+ .tags(baseTags)
+ .publishPercentileHistogram()
+ .register(registry)
+ .record(Math.max(0, e.getDuration()), TimeUnit.MILLISECONDS);
+
+ if (e.getStatus() == StatisticEvent.Status.ERROR) {
+ String whichException = safeName(e.getException(), it -> it.getClass().getSimpleName());
+ Counter.builder("pdfas_errors")
+ .description("Failed PDF-AS operations")
+ .tags(baseTags.and("exception", whichException))
+ .register(registry)
+ .increment();
+ }
+ }
+
+ private static @NonNull String safeString(String str) {
+ return ((str == null) || str.isBlank()) ? "unknown" : str;
+ }
+
+ private static <T> @NonNull String safeName(T v, @NonNull Function<T, String> op) {
+ return safeString((v != null) ? op.apply(v) : null);
+ }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java
index 643d3ea0..fdcded6c 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/IRequestStore.java
@@ -26,11 +26,11 @@ package at.gv.egiz.pdfas.web.store;
import at.gv.egiz.pdfas.api.processing.PdfasSignRequest;
import at.gv.egiz.pdfas.api.processing.PdfasSignResponse;
import at.gv.egiz.pdfas.web.stats.StatisticEvent;
+import kotlin.Pair;
public interface IRequestStore {
- public StatisticEvent fetchStatisticEntry(String id);
public String createNewStoreEntry(PdfasSignRequest request, StatisticEvent event);
- public PdfasSignRequest fetchStoreEntry(String id);
+ public Pair<PdfasSignRequest, StatisticEvent> fetchStoreEntry(String id);
public String createNewResponseEntry(PdfasSignResponse response);
public PdfasSignResponse fetchStoreResponse(String id);
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java
index 6ab58ce0..378714e4 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/InMemoryRequestStore.java
@@ -26,6 +26,8 @@ package at.gv.egiz.pdfas.web.store;
import java.util.Map;
import java.util.UUID;
+import kotlin.Pair;
+import lombok.val;
import org.apache.commons.collections4.map.PassiveExpiringMap;
import at.gv.egiz.pdfas.api.processing.PdfasSignRequest;
@@ -37,40 +39,27 @@ public class InMemoryRequestStore implements IRequestStore {
// expires after 10 minutes
private static final long DEFAULT_EXPIRATION = 10 * 60 * 1000;
- private Map<String, PdfasSignRequest> reqStore = new PassiveExpiringMap<>(DEFAULT_EXPIRATION);
+ private Map<String, Pair<PdfasSignRequest, StatisticEvent>> reqStore = new PassiveExpiringMap<>(DEFAULT_EXPIRATION);
private Map<String, PdfasSignResponse> respStore = new PassiveExpiringMap<>(DEFAULT_EXPIRATION);
- private Map<String, StatisticEvent> statEvents = new PassiveExpiringMap<>(DEFAULT_EXPIRATION);
public InMemoryRequestStore() {
}
-
+
+ @Override
public String createNewStoreEntry(PdfasSignRequest request, StatisticEvent event) {
UUID id = UUID.randomUUID();
String sid = id.toString();
- this.reqStore.put(sid, request);
- this.statEvents.put(sid, event);
+ this.reqStore.put(sid, new Pair<>(request, event));
return sid;
-
}
- public StatisticEvent fetchStatisticEntry(String id) {
- if(statEvents.containsKey(id)) {
- StatisticEvent event = statEvents.get(id);
- statEvents.remove(id);
- return event;
-
- }
-
- return null;
- }
-
- public PdfasSignRequest fetchStoreEntry(String id) {
+ @Override
+ public Pair<PdfasSignRequest, StatisticEvent> fetchStoreEntry(String id) {
if(reqStore.containsKey(id)) {
- PdfasSignRequest request = reqStore.get(id);
+ val storeEntry = reqStore.get(id);
reqStore.remove(id);
- return request;
-
+ return storeEntry;
}
return null;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/RequestStore.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/RequestStore.java
index a5e961ef..e39e9399 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/RequestStore.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/store/RequestStore.java
@@ -42,15 +42,15 @@ public class RequestStore {
logger.info("Using Request Store: " + storeClass);
Class<?> clazz = Class.forName(storeClass);
- Object store = clazz.newInstance();
+ Object store = clazz.getDeclaredConstructor().newInstance();
if(store instanceof IRequestStore) {
instance = (IRequestStore)store;
} else {
- throw new PdfAsStoreException("Failed to instanciate Request Store from " + storeClass);
+ throw new PdfAsStoreException("Failed to instantiate Request Store from " + storeClass);
}
} catch (Throwable e) {
- e.printStackTrace();
- throw new PdfAsStoreException("Failed to instanciate Request Store", e);
+ logger.error("Failed to instantiate Request Store", e);
+ throw new PdfAsStoreException("Failed to instantiate Request Store", e);
}
}
return instance;
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/FilterBridge.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/FilterBridge.java
new file mode 100644
index 00000000..ee9d0cb4
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/FilterBridge.java
@@ -0,0 +1,52 @@
+package at.gv.egiz.pdfas.web.web_xml_bridges;
+
+import org.apache.catalina.filters.SetCharacterEncodingFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.thetransactioncompany.cors.CORSFilter;
+
+import at.gv.egiz.pdfas.web.filter.ExceptionCatchFilter;
+import at.gv.egiz.pdfas.web.filter.UserAgentFilter;
+import jakarta.servlet.Filter;
+import lombok.val;
+
+/** Takes the old web.xml filter mappings and exposes them to Spring Boot */
+@Configuration
+public class FilterBridge {
+ @Bean
+ public FilterRegistrationBean<Filter> setCharacterEncodingFilter() {
+ val reg = new FilterRegistrationBean<Filter>(new SetCharacterEncodingFilter());
+ reg.addUrlPatterns("/*");
+ reg.addInitParameter("encoding", "UTF-8");
+ reg.setOrder(1);
+ return reg;
+ }
+
+ @Bean
+ public FilterRegistrationBean<Filter> exceptionCatchFilter() {
+ val reg = new FilterRegistrationBean<Filter>(new ExceptionCatchFilter());
+ reg.addUrlPatterns("/*");
+ reg.addInitParameter("statelessServlets", "/actuator,/placeholder,/visblock");
+ reg.setOrder(2);
+ return reg;
+ }
+
+ @Bean
+ public FilterRegistrationBean<Filter> userAgentFilter() {
+ val reg = new FilterRegistrationBean<Filter>(new UserAgentFilter());
+ reg.addUrlPatterns("/*");
+ reg.setOrder(3);
+ return reg;
+ }
+
+ @Bean
+ public FilterRegistrationBean<Filter> cors() {
+ val reg = new FilterRegistrationBean<Filter>(new CORSFilter());
+ reg.addUrlPatterns("/*");
+ reg.addInitParameter("cors.allowOrigin", "*");
+ reg.setOrder(4);
+ return reg;
+ }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/ServletBridge.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/ServletBridge.java
new file mode 100644
index 00000000..3337a417
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/ServletBridge.java
@@ -0,0 +1,107 @@
+package at.gv.egiz.pdfas.web.web_xml_bridges;
+
+import at.gv.egiz.pdfas.web.servlets.*;
+import jakarta.servlet.Servlet;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/** Takes the old web.xml servlet mappings and exposes them to Spring Boot */
+@Configuration
+public class ServletBridge {
+ @Bean
+ public ServletRegistrationBean<Servlet> cxfServlet() {
+ return new ServletRegistrationBean<>(
+ /** from <servlet> */ new SoapServiceServlet(),
+ /** from <servlet-mapping> */ "/services/*"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> visBlockServlet() {
+ return new ServletRegistrationBean<>(
+ new VisBlockServlet(),
+ "/visblock"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> providePDF() {
+ return new ServletRegistrationBean<>(
+ new ProvidePDFServlet(),
+ "/ProvidePDF"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> dataURLServlet() {
+ return new ServletRegistrationBean<>(
+ new DataURLServlet(),
+ "/DataURL"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> slDataURLServlet() {
+ return new ServletRegistrationBean<>(
+ new SLDataURLServlet(),
+ "/DataURLSL20"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> pdfData() {
+ return new ServletRegistrationBean<>(
+ new PDFData(),
+ "/PDFData"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> errorPage() {
+ return new ServletRegistrationBean<>(
+ new ErrorPage(),
+ "/ErrorPage"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> pdfVerifyData() {
+ return new ServletRegistrationBean<>(
+ new PDFSignatureData(),
+ "/signData"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> pdfVerifyCert() {
+ return new ServletRegistrationBean<>(
+ new PDFSignatureCertificateData(),
+ "/signCert"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> uiEntryPointServlet() {
+ return new ServletRegistrationBean<>(
+ new UIEntryPointServlet(),
+ "/userentry"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> qrPlaceholderGenerator() {
+ return new ServletRegistrationBean<>(
+ new PlaceholderGeneratorServlet(),
+ "/placeholder"
+ );
+ }
+
+ @Bean
+ public ServletRegistrationBean<Servlet> jsonAPIServlet() {
+ return new ServletRegistrationBean<>(
+ new JSONAPIServlet(),
+ "/api/v1/sign"
+ );
+ }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/WelcomeFileBridge.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/WelcomeFileBridge.java
new file mode 100644
index 00000000..6fcf47fa
--- /dev/null
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/web_xml_bridges/WelcomeFileBridge.java
@@ -0,0 +1,12 @@
+package at.gv.egiz.pdfas.web.web_xml_bridges;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class WelcomeFileBridge {
+ @GetMapping("/")
+ public String welcomeFile() {
+ return "forward:/index.jsp";
+ }
+}
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java
index dce3e34c..83e59706 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASSigningImpl.java
@@ -28,10 +28,13 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-import javax.jws.WebService;
-import javax.xml.ws.WebServiceException;
-import javax.xml.ws.soap.MTOM;
+import at.gv.egiz.pdfas.lib.api.PdfAs;
+import at.gv.egiz.pdfas.lib.impl.ErrorExtractor;
+import jakarta.jws.WebService;
+import jakarta.xml.ws.WebServiceException;
+import jakarta.xml.ws.soap.MTOM;
+import lombok.val;
import org.apache.commons.lang3.StringUtils;
import at.gv.egiz.pdfas.api.processing.CoreSignParams;
@@ -88,28 +91,31 @@ public class PDFASSigningImpl implements PDFASSigning {
log.warn("SOAP Sign Request is null!");
return null;
}
+ if (request.getParameters() == null) {
+ throw new WebServiceException("SOAP Sign Request parameters are missing");
+ }
// map request into internal data-structure
final PdfasSignRequest internalReq = buildOperationRequest(request);
+ val connector = internalReq.getCoreParams().getConnector();
+ val keyIdentifier = internalReq.getCoreParams().getKeyIdentifier();
+
final StatisticEvent statisticEvent = new StatisticEvent();
statisticEvent.setSource(Source.SOAP);
statisticEvent.setOperation(Operation.SIGN);
statisticEvent.setUserAgent(UserAgentFilter.getUserAgent());
statisticEvent.setProfileId(request.getParameters().getProfile());
- statisticEvent.setDevice(request.getParameters().getConnector().toString());
+ if (connector != null) {
+ statisticEvent.setDevice(connector.toString());
+ }
statisticEvent.setStartNow();
PDFASSignResponse response = new PDFASSignResponse();
try {
- if (request.getParameters().getConnector() == null) {
- throw new WebServiceException(
- "Invalid connector value!");
- }
+ PdfAsHelper.checkConnectorSupported(connector, keyIdentifier);
- if (request.getParameters().getConnector().equals(Connector.MOA)
- || request.getParameters().getConnector()
- .equals(Connector.JKS)) {
+ if (!Connector.isAsynchronous(connector)) {
// perform technical signing process
final PdfasSignResponse internalResp = PdfAsHelper.synchronousServerSignature(internalReq);
@@ -142,20 +148,20 @@ public class PDFASSigningImpl implements PDFASSigning {
}
} catch (final Throwable e) {
+ val pdfAsError = ErrorExtractor.searchPdfAsError(e, null);
+
statisticEvent.setStatus(Status.ERROR);
statisticEvent.setException(e);
- if (e instanceof PDFASError) {
- statisticEvent.setErrorCode(((PDFASError) e).getCode());
- }
+ statisticEvent.setErrorCode(pdfAsError.getCode());
statisticEvent.setEndNow();
statisticEvent.setTimestampNow();
StatisticFrontend.getInstance().storeEvent(statisticEvent);
statisticEvent.setLogged(true);
log.warn("Error in Soap Service", e);
+ response.setErrorCode(pdfAsError.getCode());
if (e.getCause() != null) {
response.setError(e.getCause().getMessage());
-
} else {
response.setError(e.getMessage());
@@ -210,24 +216,23 @@ public class PDFASSigningImpl implements PDFASSigning {
// map request into internal data-structure
final PdfasSignRequest internalReq = buildOperationRequest(request);
+ val connector = internalReq.getCoreParams().getConnector();
+ val keyIdentifier = internalReq.getCoreParams().getKeyIdentifier();
final StatisticEvent statisticEvent = new StatisticEvent();
statisticEvent.setSource(Source.SOAP);
statisticEvent.setOperation(Operation.SIGNBULK);
statisticEvent.setUserAgent(UserAgentFilter.getUserAgent());
- statisticEvent.setDevice(internalReq.getCoreParams().getConnector().toString());
+ if (connector != null) {
+ statisticEvent.setDevice(connector.toString());
+ }
statisticEvent.setStartNow();
PdfasSignMultipleResponse response = new PdfasSignMultipleResponse();
try {
- if (internalReq.getCoreParams().getConnector() == null) {
- throw new WebServiceException(
- "Invalid connector value!");
- }
+ PdfAsHelper.checkConnectorSupported(connector, keyIdentifier);
- if (internalReq.getCoreParams().getConnector().equals(Connector.MOA)
- || internalReq.getCoreParams().getConnector()
- .equals(Connector.JKS)) {
+ if (!Connector.isAsynchronous(connector)) {
// perform technical signing process
final PdfasSignResponse internalResp = PdfAsHelper.synchronousServerSignature(internalReq);
@@ -370,6 +375,9 @@ public class PDFASSigningImpl implements PDFASSigning {
coreParams.setTransactionId(request.getTransactionId());
data.setCoreParams(coreParams);
+ if (request.getInput() == null || request.getInput().isEmpty()) {
+ throw new WebServiceException("SignMultipleRequest contains no input documents");
+ }
request.getInput().forEach(el -> {
final DocumentToSign document = new DocumentToSign();
document.setInputData(el.getInputData());
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASVerificationImpl.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASVerificationImpl.java
index b1bca4ba..1afd0c2d 100644
--- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASVerificationImpl.java
+++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/ws/PDFASVerificationImpl.java
@@ -16,9 +16,9 @@ import iaik.x509.X509Certificate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.jws.WebService;
-import javax.xml.ws.WebServiceException;
-import javax.xml.ws.soap.MTOM;
+import jakarta.jws.WebService;
+import jakarta.xml.ws.WebServiceException;
+import jakarta.xml.ws.soap.MTOM;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -69,7 +69,11 @@ public class PDFASVerificationImpl implements PDFASVerification {
}
statisticEvent.setFilesize(request.getInputData().length);
statisticEvent.setProfileId(null);
- statisticEvent.setDevice(request.getVerificationLevel().toString());
+ statisticEvent.setDevice(
+ (lvl == SignatureVerificationLevel.FULL_VERIFICATION ?
+ VerificationLevel.FULL_CERT_PATH :
+ VerificationLevel.INTEGRITY_ONLY)
+ .toString());
List<VerifyResult> results = PdfAsHelper.synchronousVerify(
request.getInputData(), sigIdx, lvl, preProcessor);