mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-10-25 11:17:28 +02:00 
			
		
		
		
	File paths dynamic (#2605)
# Description Please provide a summary of the changes, including relevant motivation and context. Closes #(issue_number) ## Checklist - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have performed a self-review of my own code - [ ] I have attached images of the change if it is UI based - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] If my code has heavily changed functionality I have updated relevant docs on [Stirling-PDFs doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) - [ ] My changes generate no new warnings - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) --------- Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com> Co-authored-by: a <a>
This commit is contained in:
		
							parent
							
								
									f08f8c734b
								
							
						
					
					
						commit
						ed633616e7
					
				
							
								
								
									
										11
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @ -47,6 +47,17 @@ jobs: | ||||
|         env: | ||||
|           DOCKER_ENABLE_SECURITY: true | ||||
| 
 | ||||
|       - name: Upload Test Reports | ||||
|         if: always() | ||||
|         uses: actions/upload-artifact@v4 | ||||
|         with: | ||||
|           name: test-reports-jdk-${{ matrix.jdk-version }} | ||||
|           path: | | ||||
|             build/reports/tests/ | ||||
|             build/test-results/ | ||||
|             build/reports/problems/ | ||||
|           retention-days: 3 | ||||
|            | ||||
|   docker-compose-tests: | ||||
|     # if: github.event_name == 'push' && github.ref == 'refs/heads/main' || | ||||
|     #     (github.event_name == 'pull_request' && | ||||
|  | ||||
							
								
								
									
										12
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								build.gradle
									
									
									
									
									
								
							| @ -123,11 +123,13 @@ jpackage { | ||||
|     windows { | ||||
|     	launcherAsService = false | ||||
|     	appVersion = project.version | ||||
|         winConsole = false | ||||
|         winDirChooser = true | ||||
|         winMenu = true | ||||
|         winShortcut = true | ||||
|         winPerUserInstall = true | ||||
|     	 | ||||
|     	winConsole = false | ||||
|         winMenu = true  // Creates start menu entry | ||||
|         winShortcut = true  // Creates desktop shortcut | ||||
|         winShortcutPrompt = true  // Lets user choose whether to create shortcuts | ||||
|         winDirChooser = true  // Allows users to choose installation directory | ||||
|         winPerUserInstall = false | ||||
|         winMenuGroup = "Stirling Software" | ||||
|         winUpgradeUuid = "2a43ed0c-b8c2-40cf-89e1-751129b87641" // Unique identifier for updates | ||||
|         winHelpUrl = "https://github.com/Stirling-Tools/Stirling-PDF" | ||||
|  | ||||
| @ -2,6 +2,7 @@ package stirling.software.SPDF; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.net.ServerSocket; | ||||
| import java.net.URISyntaxException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| @ -24,6 +25,7 @@ import jakarta.annotation.PreDestroy; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.UI.WebBrowser; | ||||
| import stirling.software.SPDF.config.ConfigInitializer; | ||||
| import stirling.software.SPDF.config.InstallationPathConfig; | ||||
| import stirling.software.SPDF.model.ApplicationProperties; | ||||
| 
 | ||||
| @SpringBootApplication | ||||
| @ -76,15 +78,27 @@ public class SPdfApplication { | ||||
|             props.put("spring.main.web-application-type", "servlet"); | ||||
|         } | ||||
|         app.setAdditionalProfiles("default"); | ||||
|         app.addInitializers(new ConfigInitializer()); | ||||
| 
 | ||||
|         ConfigInitializer initializer = new ConfigInitializer(); | ||||
|         try { | ||||
|             initializer.ensureConfigExists(); | ||||
|         } catch (IOException | URISyntaxException e) { | ||||
|             log.error("Error initialising configuration", e); | ||||
|         } | ||||
| 
 | ||||
|         Map<String, String> propertyFiles = new HashMap<>(); | ||||
|         // External config files | ||||
|         if (Files.exists(Paths.get("configs/settings.yml"))) { | ||||
|             propertyFiles.put("spring.config.additional-location", "file:configs/settings.yml"); | ||||
|         log.info("Settings file: {}", InstallationPathConfig.getSettingsPath()); | ||||
|         if (Files.exists(Paths.get(InstallationPathConfig.getSettingsPath()))) { | ||||
|             propertyFiles.put( | ||||
|                     "spring.config.additional-location", | ||||
|                     "file:" + InstallationPathConfig.getSettingsPath()); | ||||
|         } else { | ||||
|             log.warn("External configuration file 'configs/settings.yml' does not exist."); | ||||
|             log.warn( | ||||
|                     "External configuration file '{}' does not exist.", | ||||
|                     InstallationPathConfig.getSettingsPath()); | ||||
|         } | ||||
|         if (Files.exists(Paths.get("configs/custom_settings.yml"))) { | ||||
|         if (Files.exists(Paths.get(InstallationPathConfig.getCustomSettingsPath()))) { | ||||
|             String existingLocation = | ||||
|                     propertyFiles.getOrDefault("spring.config.additional-location", ""); | ||||
|             if (!existingLocation.isEmpty()) { | ||||
| @ -92,9 +106,11 @@ public class SPdfApplication { | ||||
|             } | ||||
|             propertyFiles.put( | ||||
|                     "spring.config.additional-location", | ||||
|                     existingLocation + "file:configs/custom_settings.yml"); | ||||
|                     existingLocation + "file:" + InstallationPathConfig.getCustomSettingsPath()); | ||||
|         } else { | ||||
|             log.warn("Custom configuration file 'configs/custom_settings.yml' does not exist."); | ||||
|             log.warn( | ||||
|                     "Custom configuration file '{}' does not exist.", | ||||
|                     InstallationPathConfig.getCustomSettingsPath()); | ||||
|         } | ||||
|         Properties finalProps = new Properties(); | ||||
|         if (!propertyFiles.isEmpty()) { | ||||
| @ -110,8 +126,8 @@ public class SPdfApplication { | ||||
|         app.run(args); | ||||
|         // Ensure directories are created | ||||
|         try { | ||||
|             Files.createDirectories(Path.of("customFiles/static/")); | ||||
|             Files.createDirectories(Path.of("customFiles/templates/")); | ||||
|             Files.createDirectories(Path.of(InstallationPathConfig.getTemplatesPath())); | ||||
|             Files.createDirectories(Path.of(InstallationPathConfig.getStaticPath())); | ||||
|         } catch (Exception e) { | ||||
|             log.error("Error creating directories: {}", e.getMessage()); | ||||
|         } | ||||
|  | ||||
| @ -40,6 +40,7 @@ import me.friwi.jcefmaven.EnumProgress; | ||||
| import me.friwi.jcefmaven.MavenCefAppHandlerAdapter; | ||||
| import me.friwi.jcefmaven.impl.progress.ConsoleProgressHandler; | ||||
| import stirling.software.SPDF.UI.WebBrowser; | ||||
| import stirling.software.SPDF.config.InstallationPathConfig; | ||||
| 
 | ||||
| @Component | ||||
| @Slf4j | ||||
| @ -72,7 +73,8 @@ public class DesktopBrowser implements WebBrowser { | ||||
|                         CefAppBuilder builder = new CefAppBuilder(); | ||||
|                         configureCefSettings(builder); | ||||
|                         builder.setProgressHandler(createProgressHandler()); | ||||
| 
 | ||||
|                         builder.setInstallDir( | ||||
|                                 new File(InstallationPathConfig.getClientWebUIPath())); | ||||
|                         // Build and initialize CEF | ||||
|                         cefApp = builder.build(); | ||||
|                         client = cefApp.createClient(); | ||||
| @ -99,8 +101,16 @@ public class DesktopBrowser implements WebBrowser { | ||||
| 
 | ||||
|     private void configureCefSettings(CefAppBuilder builder) { | ||||
|         CefSettings settings = builder.getCefSettings(); | ||||
|         settings.cache_path = new File("jcef-bundle").getAbsolutePath(); | ||||
|         settings.root_cache_path = new File("jcef-bundle").getAbsolutePath(); | ||||
|         String basePath = InstallationPathConfig.getClientWebUIPath(); | ||||
|         log.info("basePath " + basePath); | ||||
|         settings.cache_path = new File(basePath + "cache").getAbsolutePath(); | ||||
|         settings.root_cache_path = new File(basePath + "root_cache").getAbsolutePath(); | ||||
|         //        settings.browser_subprocess_path = new File(basePath + | ||||
|         // "subprocess").getAbsolutePath(); | ||||
|         //        settings.resources_dir_path = new File(basePath + "resources").getAbsolutePath(); | ||||
|         //        settings.locales_dir_path = new File(basePath + "locales").getAbsolutePath(); | ||||
|         settings.log_file = new File(basePath, "debug.log").getAbsolutePath(); | ||||
| 
 | ||||
|         settings.persist_session_cookies = true; | ||||
|         settings.windowless_rendering_enabled = false; | ||||
|         settings.log_severity = CefSettings.LogSeverity.LOGSEVERITY_INFO; | ||||
| @ -212,6 +222,9 @@ public class DesktopBrowser implements WebBrowser { | ||||
|     } | ||||
| 
 | ||||
|     private void setupLoadHandler() { | ||||
|         final long initStartTime = System.currentTimeMillis(); | ||||
|         log.info("Setting up load handler at: {}", initStartTime); | ||||
| 
 | ||||
|         client.addLoadHandler( | ||||
|                 new CefLoadHandlerAdapter() { | ||||
|                     @Override | ||||
| @ -220,32 +233,77 @@ public class DesktopBrowser implements WebBrowser { | ||||
|                             boolean isLoading, | ||||
|                             boolean canGoBack, | ||||
|                             boolean canGoForward) { | ||||
|                         log.debug( | ||||
|                                 "Loading state change - isLoading: {}, canGoBack: {}, canGoForward: {}, " | ||||
|                                         + "browserInitialized: {}, Time elapsed: {}ms", | ||||
|                                 isLoading, | ||||
|                                 canGoBack, | ||||
|                                 canGoForward, | ||||
|                                 browserInitialized, | ||||
|                                 System.currentTimeMillis() - initStartTime); | ||||
| 
 | ||||
|                         if (!isLoading && !browserInitialized) { | ||||
|                             log.info( | ||||
|                                     "Browser finished loading, preparing to initialize UI components"); | ||||
|                             browserInitialized = true; | ||||
|                             SwingUtilities.invokeLater( | ||||
|                                     () -> { | ||||
|                                         if (loadingWindow != null) { | ||||
|                                             Timer timer = | ||||
|                                                     new Timer( | ||||
|                                                             500, | ||||
|                                                             e -> { | ||||
|                                                                 loadingWindow.dispose(); | ||||
|                                                                 loadingWindow = null; | ||||
|                                         try { | ||||
|                                             if (loadingWindow != null) { | ||||
|                                                 log.info("Starting UI initialization sequence"); | ||||
| 
 | ||||
|                                                                 frame.dispose(); | ||||
|                                                                 frame.setOpacity(1.0f); | ||||
|                                                                 frame.setUndecorated(false); | ||||
|                                                                 frame.pack(); | ||||
|                                                                 frame.setSize(1280, 800); | ||||
|                                                                 frame.setLocationRelativeTo(null); | ||||
|                                                                 frame.setVisible(true); | ||||
|                                                                 frame.requestFocus(); | ||||
|                                                                 frame.toFront(); | ||||
|                                                                 browser.getUIComponent() | ||||
|                                                                         .requestFocus(); | ||||
|                                                             }); | ||||
|                                             timer.setRepeats(false); | ||||
|                                             timer.start(); | ||||
|                                                 // Close loading window first | ||||
|                                                 loadingWindow.setVisible(false); | ||||
|                                                 loadingWindow.dispose(); | ||||
|                                                 loadingWindow = null; | ||||
|                                                 log.info("Loading window disposed"); | ||||
| 
 | ||||
|                                                 // Then setup the main frame | ||||
|                                                 frame.setVisible(false); | ||||
|                                                 frame.dispose(); | ||||
|                                                 frame.setOpacity(1.0f); | ||||
|                                                 frame.setUndecorated(false); | ||||
|                                                 frame.pack(); | ||||
|                                                 frame.setSize(1280, 800); | ||||
|                                                 frame.setLocationRelativeTo(null); | ||||
|                                                 log.debug("Frame reconfigured"); | ||||
| 
 | ||||
|                                                 // Show the main frame | ||||
|                                                 frame.setVisible(true); | ||||
|                                                 frame.requestFocus(); | ||||
|                                                 frame.toFront(); | ||||
|                                                 log.info("Main frame displayed and focused"); | ||||
| 
 | ||||
|                                                 // Focus the browser component | ||||
|                                                 Timer focusTimer = | ||||
|                                                         new Timer( | ||||
|                                                                 100, | ||||
|                                                                 e -> { | ||||
|                                                                     try { | ||||
|                                                                         browser.getUIComponent() | ||||
|                                                                                 .requestFocus(); | ||||
|                                                                         log.info( | ||||
|                                                                                 "Browser component focused"); | ||||
|                                                                     } catch (Exception ex) { | ||||
|                                                                         log.error( | ||||
|                                                                                 "Error focusing browser", | ||||
|                                                                                 ex); | ||||
|                                                                     } | ||||
|                                                                 }); | ||||
|                                                 focusTimer.setRepeats(false); | ||||
|                                                 focusTimer.start(); | ||||
|                                             } | ||||
|                                         } catch (Exception e) { | ||||
|                                             log.error("Error during UI initialization", e); | ||||
|                                             // Attempt cleanup on error | ||||
|                                             if (loadingWindow != null) { | ||||
|                                                 loadingWindow.dispose(); | ||||
|                                                 loadingWindow = null; | ||||
|                                             } | ||||
|                                             if (frame != null) { | ||||
|                                                 frame.setVisible(true); | ||||
|                                                 frame.requestFocus(); | ||||
|                                             } | ||||
|                                         } | ||||
|                                     }); | ||||
|                         } | ||||
|  | ||||
| @ -14,9 +14,12 @@ public class LoadingWindow extends JDialog { | ||||
|     private final JLabel statusLabel; | ||||
|     private final JPanel mainPanel; | ||||
|     private final JLabel brandLabel; | ||||
|     private long startTime; | ||||
| 
 | ||||
|     public LoadingWindow(Frame parent, String initialUrl) { | ||||
|         super(parent, "Initializing Stirling-PDF", true); | ||||
|         startTime = System.currentTimeMillis(); | ||||
|         log.info("Creating LoadingWindow - initialization started at: {}", startTime); | ||||
| 
 | ||||
|         // Initialize components | ||||
|         mainPanel = new JPanel(); | ||||
| @ -29,8 +32,8 @@ public class LoadingWindow extends JDialog { | ||||
|         gbc.gridwidth = GridBagConstraints.REMAINDER; | ||||
|         gbc.fill = GridBagConstraints.HORIZONTAL; | ||||
|         gbc.insets = new Insets(5, 5, 5, 5); | ||||
|         gbc.weightx = 1.0; // Add horizontal weight | ||||
|         gbc.weighty = 0.0; // Add vertical weight | ||||
|         gbc.weightx = 1.0; | ||||
|         gbc.weighty = 0.0; | ||||
| 
 | ||||
|         // Add icon | ||||
|         try { | ||||
| @ -43,12 +46,14 @@ public class LoadingWindow extends JDialog { | ||||
|                         iconLabel.setHorizontalAlignment(SwingConstants.CENTER); | ||||
|                         gbc.gridy = 0; | ||||
|                         mainPanel.add(iconLabel, gbc); | ||||
|                         log.debug("Icon loaded and scaled successfully"); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } catch (Exception e) { | ||||
|             log.error("Failed to load icon", e); | ||||
|         } | ||||
| 
 | ||||
|         // URL Label with explicit size | ||||
|         brandLabel = new JLabel(initialUrl); | ||||
|         brandLabel.setHorizontalAlignment(SwingConstants.CENTER); | ||||
| @ -63,6 +68,7 @@ public class LoadingWindow extends JDialog { | ||||
|         statusLabel.setPreferredSize(new Dimension(300, 25)); | ||||
|         gbc.gridy = 2; | ||||
|         mainPanel.add(statusLabel, gbc); | ||||
| 
 | ||||
|         // Progress bar with explicit size | ||||
|         progressBar = new JProgressBar(0, 100); | ||||
|         progressBar.setStringPainted(true); | ||||
| @ -82,33 +88,78 @@ public class LoadingWindow extends JDialog { | ||||
|         setAlwaysOnTop(true); | ||||
|         setProgress(0); | ||||
|         setStatus("Starting..."); | ||||
| 
 | ||||
|         log.info( | ||||
|                 "LoadingWindow initialization completed in {}ms", | ||||
|                 System.currentTimeMillis() - startTime); | ||||
|     } | ||||
| 
 | ||||
|     public void setProgress(final int progress) { | ||||
|         SwingUtilities.invokeLater( | ||||
|                 () -> { | ||||
|                     try { | ||||
|                         progressBar.setValue(Math.min(Math.max(progress, 0), 100)); | ||||
|                         progressBar.setString(progress + "%"); | ||||
|                         int validProgress = Math.min(Math.max(progress, 0), 100); | ||||
|                         log.info( | ||||
|                                 "Setting progress to {}% at {}ms since start", | ||||
|                                 validProgress, System.currentTimeMillis() - startTime); | ||||
| 
 | ||||
|                         // Log additional details when near 90% | ||||
|                         if (validProgress >= 85 && validProgress <= 95) { | ||||
|                             log.info( | ||||
|                                     "Near 90% progress - Current status: {}, Window visible: {}, " | ||||
|                                             + "Progress bar responding: {}, Memory usage: {}MB", | ||||
|                                     statusLabel.getText(), | ||||
|                                     isVisible(), | ||||
|                                     progressBar.isEnabled(), | ||||
|                                     Runtime.getRuntime().totalMemory() / (1024 * 1024)); | ||||
| 
 | ||||
|                             // Add thread state logging | ||||
|                             Thread currentThread = Thread.currentThread(); | ||||
|                             log.debug( | ||||
|                                     "Current thread state - Name: {}, State: {}, Priority: {}", | ||||
|                                     currentThread.getName(), | ||||
|                                     currentThread.getState(), | ||||
|                                     currentThread.getPriority()); | ||||
|                         } | ||||
| 
 | ||||
|                         progressBar.setValue(validProgress); | ||||
|                         progressBar.setString(validProgress + "%"); | ||||
|                         mainPanel.revalidate(); | ||||
|                         mainPanel.repaint(); | ||||
|                     } catch (Exception e) { | ||||
|                         log.error("Error updating progress", e); | ||||
|                         log.error("Error updating progress to " + progress, e); | ||||
|                     } | ||||
|                 }); | ||||
|     } | ||||
| 
 | ||||
|     public void setStatus(final String status) { | ||||
|         log.info(status); | ||||
|         log.info( | ||||
|                 "Status update at {}ms - Setting status to: {}", | ||||
|                 System.currentTimeMillis() - startTime, | ||||
|                 status); | ||||
| 
 | ||||
|         SwingUtilities.invokeLater( | ||||
|                 () -> { | ||||
|                     try { | ||||
|                         statusLabel.setText(status != null ? status : ""); | ||||
|                         String validStatus = status != null ? status : ""; | ||||
|                         statusLabel.setText(validStatus); | ||||
| 
 | ||||
|                         // Log UI state when status changes | ||||
|                         log.debug( | ||||
|                                 "UI State - Window visible: {}, Progress: {}%, Status: {}", | ||||
|                                 isVisible(), progressBar.getValue(), validStatus); | ||||
| 
 | ||||
|                         mainPanel.revalidate(); | ||||
|                         mainPanel.repaint(); | ||||
|                     } catch (Exception e) { | ||||
|                         log.error("Error updating status", e); | ||||
|                         log.error("Error updating status to: " + status, e); | ||||
|                     } | ||||
|                 }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void dispose() { | ||||
|         log.info("LoadingWindow disposing after {}ms", System.currentTimeMillis() - startTime); | ||||
|         super.dispose(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -136,16 +136,6 @@ public class AppConfig { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     @Bean(name = "watchedFoldersDir") | ||||
|     public String watchedFoldersDir() { | ||||
|         return "./pipeline/watchedFolders/"; | ||||
|     } | ||||
| 
 | ||||
|     @Bean(name = "finishedFoldersDir") | ||||
|     public String finishedFoldersDir() { | ||||
|         return "./pipeline/finishedFolders/"; | ||||
|     } | ||||
| 
 | ||||
|     @Bean(name = "directoryFilter") | ||||
|     public Predicate<Path> processOnlyFiles() { | ||||
|         return path -> { | ||||
|  | ||||
| @ -16,27 +16,15 @@ import org.simpleyaml.configuration.comments.CommentType; | ||||
| import org.simpleyaml.configuration.file.YamlFile; | ||||
| import org.simpleyaml.configuration.implementation.SimpleYamlImplementation; | ||||
| import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions; | ||||
| import org.springframework.context.ApplicationContextInitializer; | ||||
| import org.springframework.context.ConfigurableApplicationContext; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| 
 | ||||
| @Slf4j | ||||
| public class ConfigInitializer | ||||
|         implements ApplicationContextInitializer<ConfigurableApplicationContext> { | ||||
| 
 | ||||
|     @Override | ||||
|     public void initialize(ConfigurableApplicationContext applicationContext) { | ||||
|         try { | ||||
|             ensureConfigExists(); | ||||
|         } catch (Exception e) { | ||||
|             throw new RuntimeException("Failed to initialize application configuration", e); | ||||
|         } | ||||
|     } | ||||
| public class ConfigInitializer { | ||||
| 
 | ||||
|     public void ensureConfigExists() throws IOException, URISyntaxException { | ||||
|         // Define the path to the external config directory | ||||
|         Path destPath = Paths.get("configs", "settings.yml"); | ||||
|         Path destPath = Paths.get(InstallationPathConfig.getSettingsPath()); | ||||
| 
 | ||||
|         // Check if the file already exists | ||||
|         if (Files.notExists(destPath)) { | ||||
| @ -53,10 +41,11 @@ public class ConfigInitializer | ||||
|                             "Resource file not found: settings.yml.template"); | ||||
|                 } | ||||
|             } | ||||
|             log.info("Created settings file from template"); | ||||
|         } else { | ||||
| 
 | ||||
|             // Define the path to the config settings file | ||||
|             Path settingsPath = Paths.get("configs", "settings.yml"); | ||||
|             Path settingsPath = Paths.get(InstallationPathConfig.getSettingsPath()); | ||||
|             // Load the template resource | ||||
|             URL settingsTemplateResource = | ||||
|                     getClass().getClassLoader().getResource("settings.yml.template"); | ||||
| @ -120,7 +109,7 @@ public class ConfigInitializer | ||||
|         } | ||||
| 
 | ||||
|         // Create custom settings file if it doesn't exist | ||||
|         Path customSettingsPath = Paths.get("configs", "custom_settings.yml"); | ||||
|         Path customSettingsPath = Paths.get(InstallationPathConfig.getCustomSettingsPath()); | ||||
|         if (!Files.exists(customSettingsPath)) { | ||||
|             Files.createFile(customSettingsPath); | ||||
|         } | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| package stirling.software.SPDF.config; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashSet; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| @ -267,20 +268,26 @@ public class EndpointConfiguration { | ||||
|     } | ||||
| 
 | ||||
|     private void processEnvironmentConfigs() { | ||||
|         List<String> endpointsToRemove = applicationProperties.getEndpoints().getToRemove(); | ||||
|         List<String> groupsToRemove = applicationProperties.getEndpoints().getGroupsToRemove(); | ||||
|         if (!bookAndHtmlFormatsInstalled) { | ||||
|             groupsToRemove.add("Calibre"); | ||||
|         } | ||||
|         if (endpointsToRemove != null) { | ||||
|             for (String endpoint : endpointsToRemove) { | ||||
|                 disableEndpoint(endpoint.trim()); | ||||
|             } | ||||
|         } | ||||
|         if (applicationProperties != null && applicationProperties.getEndpoints() != null) { | ||||
|             List<String> endpointsToRemove = applicationProperties.getEndpoints().getToRemove(); | ||||
|             List<String> groupsToRemove = applicationProperties.getEndpoints().getGroupsToRemove(); | ||||
| 
 | ||||
|         if (groupsToRemove != null) { | ||||
|             for (String group : groupsToRemove) { | ||||
|                 disableGroup(group.trim()); | ||||
|             if (!bookAndHtmlFormatsInstalled) { | ||||
|                 if (groupsToRemove == null) { | ||||
|                     groupsToRemove = new ArrayList<>(); | ||||
|                 } | ||||
|                 groupsToRemove.add("Calibre"); | ||||
|             } | ||||
|             if (endpointsToRemove != null) { | ||||
|                 for (String endpoint : endpointsToRemove) { | ||||
|                     disableEndpoint(endpoint.trim()); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (groupsToRemove != null) { | ||||
|                 for (String group : groupsToRemove) { | ||||
|                     disableGroup(group.trim()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -33,7 +33,8 @@ public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateRe | ||||
|             String characterEncoding, | ||||
|             Map<String, Object> templateResolutionAttributes) { | ||||
|         Resource resource = | ||||
|                 resourceLoader.getResource("file:./customFiles/templates/" + resourceName); | ||||
|                 resourceLoader.getResource( | ||||
|                         "file:" + InstallationPathConfig.getTemplatesPath() + resourceName); | ||||
|         try { | ||||
|             if (resource.exists() && resource.isReadable()) { | ||||
|                 return new FileTemplateResource(resource.getFile().getPath(), characterEncoding); | ||||
|  | ||||
| @ -0,0 +1,132 @@ | ||||
| package stirling.software.SPDF.config; | ||||
| 
 | ||||
| import java.io.File; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| 
 | ||||
| @Slf4j | ||||
| public class InstallationPathConfig { | ||||
|     private static final String BASE_PATH; | ||||
| 
 | ||||
|     // Root paths | ||||
|     private static final String LOG_PATH; | ||||
|     private static final String CONFIG_PATH; | ||||
|     private static final String PIPELINE_PATH; | ||||
|     private static final String CUSTOM_FILES_PATH; | ||||
|     private static final String CLIENT_WEBUI_PATH; | ||||
| 
 | ||||
|     // Config paths | ||||
|     private static final String SETTINGS_PATH; | ||||
|     private static final String CUSTOM_SETTINGS_PATH; | ||||
| 
 | ||||
|     // Pipeline paths | ||||
|     private static final String PIPELINE_WATCHED_FOLDERS_PATH; | ||||
|     private static final String PIPELINE_FINISHED_FOLDERS_PATH; | ||||
| 
 | ||||
|     // Custom file paths | ||||
|     private static final String STATIC_PATH; | ||||
|     private static final String TEMPLATES_PATH; | ||||
|     private static final String SIGNATURES_PATH; | ||||
| 
 | ||||
|     static { | ||||
|         BASE_PATH = initializeBasePath(); | ||||
| 
 | ||||
|         // Initialize root paths | ||||
|         LOG_PATH = BASE_PATH + "logs" + File.separator; | ||||
|         CONFIG_PATH = BASE_PATH + "configs" + File.separator; | ||||
|         PIPELINE_PATH = BASE_PATH + "pipeline" + File.separator; | ||||
|         CUSTOM_FILES_PATH = BASE_PATH + "customFiles" + File.separator; | ||||
|         CLIENT_WEBUI_PATH = BASE_PATH + "clientWebUI" + File.separator; | ||||
| 
 | ||||
|         // Initialize config paths | ||||
|         SETTINGS_PATH = CONFIG_PATH + "settings.yml"; | ||||
|         CUSTOM_SETTINGS_PATH = CONFIG_PATH + "custom_settings.yml"; | ||||
| 
 | ||||
|         // Initialize pipeline paths | ||||
|         PIPELINE_WATCHED_FOLDERS_PATH = PIPELINE_PATH + "watchedFolders" + File.separator; | ||||
|         PIPELINE_FINISHED_FOLDERS_PATH = PIPELINE_PATH + "finishedFolders" + File.separator; | ||||
| 
 | ||||
|         // Initialize custom file paths | ||||
|         STATIC_PATH = CUSTOM_FILES_PATH + "static" + File.separator; | ||||
|         TEMPLATES_PATH = CUSTOM_FILES_PATH + "templates" + File.separator; | ||||
|         SIGNATURES_PATH = CUSTOM_FILES_PATH + "signatures" + File.separator; | ||||
|     } | ||||
| 
 | ||||
|     private static String initializeBasePath() { | ||||
|         if (Boolean.parseBoolean(System.getProperty("STIRLING_PDF_DESKTOP_UI", "false"))) { | ||||
|             String os = System.getProperty("os.name").toLowerCase(); | ||||
|             if (os.contains("win")) { | ||||
|                 return System.getenv("APPDATA") + File.separator + "Stirling-PDF" + File.separator; | ||||
|             } else if (os.contains("mac")) { | ||||
|                 return System.getProperty("user.home") | ||||
|                         + File.separator | ||||
|                         + "Library" | ||||
|                         + File.separator | ||||
|                         + "Application Support" | ||||
|                         + File.separator | ||||
|                         + "Stirling-PDF" | ||||
|                         + File.separator; | ||||
|             } else { | ||||
|                 return System.getProperty("user.home") | ||||
|                         + File.separator | ||||
|                         + ".config" | ||||
|                         + File.separator | ||||
|                         + "Stirling-PDF" | ||||
|                         + File.separator; | ||||
|             } | ||||
|         } | ||||
|         return "./"; | ||||
|     } | ||||
| 
 | ||||
|     public static String getPath() { | ||||
|         return BASE_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getLogPath() { | ||||
|         return LOG_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getConfigPath() { | ||||
|         return CONFIG_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getPipelinePath() { | ||||
|         return PIPELINE_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getCustomFilesPath() { | ||||
|         return CUSTOM_FILES_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getClientWebUIPath() { | ||||
|         return CLIENT_WEBUI_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getSettingsPath() { | ||||
|         return SETTINGS_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getCustomSettingsPath() { | ||||
|         return CUSTOM_SETTINGS_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getPipelineWatchedFoldersDir() { | ||||
|         return PIPELINE_WATCHED_FOLDERS_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getPipelineFinishedFoldersDir() { | ||||
|         return PIPELINE_FINISHED_FOLDERS_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getStaticPath() { | ||||
|         return STATIC_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getTemplatesPath() { | ||||
|         return TEMPLATES_PATH; | ||||
|     } | ||||
| 
 | ||||
|     public static String getSignaturesPath() { | ||||
|         return SIGNATURES_PATH; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| package stirling.software.SPDF.config; | ||||
| 
 | ||||
| import ch.qos.logback.core.PropertyDefinerBase; | ||||
| 
 | ||||
| public class LogbackPropertyLoader extends PropertyDefinerBase { | ||||
|     @Override | ||||
|     public String getPropertyValue() { | ||||
|         return InstallationPathConfig.getLogPath(); | ||||
|     } | ||||
| } | ||||
| @ -23,7 +23,8 @@ public class WebMvcConfig implements WebMvcConfigurer { | ||||
|     public void addResourceHandlers(ResourceHandlerRegistry registry) { | ||||
|         // Handler for external static resources | ||||
|         registry.addResourceHandler("/**") | ||||
|                 .addResourceLocations("file:customFiles/static/", "classpath:/static/"); | ||||
|                 .addResourceLocations( | ||||
|                         "file:" + InstallationPathConfig.getStaticPath(), "classpath:/static/"); | ||||
|         // .setCachePeriod(0); // Optional: disable caching | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -16,7 +16,6 @@ public class YamlPropertySourceFactory implements PropertySourceFactory { | ||||
|             throws IOException { | ||||
|         YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean(); | ||||
|         factory.setResources(encodedResource.getResource()); | ||||
| 
 | ||||
|         Properties properties = factory.getObject(); | ||||
| 
 | ||||
|         return new PropertiesPropertySource( | ||||
|  | ||||
| @ -11,13 +11,11 @@ import org.springframework.core.convert.converter.Converter; | ||||
| import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||||
| import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken; | ||||
| import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; | ||||
| import org.springframework.stereotype.Component; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.config.security.UserService; | ||||
| import stirling.software.SPDF.model.User; | ||||
| 
 | ||||
| @Component | ||||
| @Slf4j | ||||
| public class CustomSaml2ResponseAuthenticationConverter | ||||
|         implements Converter<ResponseToken, Saml2Authentication> { | ||||
|  | ||||
| @ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import io.swagger.v3.oas.annotations.Hidden; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| 
 | ||||
| import stirling.software.SPDF.config.InstallationPathConfig; | ||||
| import stirling.software.SPDF.model.ApplicationProperties; | ||||
| import stirling.software.SPDF.utils.GeneralUtils; | ||||
| 
 | ||||
| @ -33,7 +34,8 @@ public class SettingsController { | ||||
|         if (!"undefined".equals(applicationProperties.getSystem().getEnableAnalytics())) { | ||||
|             return ResponseEntity.status(HttpStatus.ALREADY_REPORTED) | ||||
|                     .body( | ||||
|                             "Setting has already been set, To adjust please edit /config/settings.yml"); | ||||
|                             "Setting has already been set, To adjust please edit " | ||||
|                                     + InstallationPathConfig.getSettingsPath()); | ||||
|         } | ||||
|         GeneralUtils.saveKeyToConfig("system.enableAnalytics", String.valueOf(enabled), false); | ||||
|         applicationProperties.getSystem().setEnableAnalytics(String.valueOf(enabled)); | ||||
|  | ||||
| @ -24,7 +24,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.model.ApplicationProperties; | ||||
| import stirling.software.SPDF.model.PipelineConfig; | ||||
| import stirling.software.SPDF.model.api.HandleDataRequest; | ||||
| import stirling.software.SPDF.utils.WebResponseUtils; | ||||
| @ -35,22 +34,12 @@ import stirling.software.SPDF.utils.WebResponseUtils; | ||||
| @Tag(name = "Pipeline", description = "Pipeline APIs") | ||||
| public class PipelineController { | ||||
| 
 | ||||
|     final String watchedFoldersDir = "./pipeline/watchedFolders/"; | ||||
| 
 | ||||
|     final String finishedFoldersDir = "./pipeline/finishedFolders/"; | ||||
| 
 | ||||
|     private final PipelineProcessor processor; | ||||
| 
 | ||||
|     private final ApplicationProperties applicationProperties; | ||||
| 
 | ||||
|     private final ObjectMapper objectMapper; | ||||
| 
 | ||||
|     public PipelineController( | ||||
|             PipelineProcessor processor, | ||||
|             ApplicationProperties applicationProperties, | ||||
|             ObjectMapper objectMapper) { | ||||
|     public PipelineController(PipelineProcessor processor, ObjectMapper objectMapper) { | ||||
|         this.processor = processor; | ||||
|         this.applicationProperties = applicationProperties; | ||||
|         this.objectMapper = objectMapper; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -16,7 +16,6 @@ import java.util.List; | ||||
| import java.util.Optional; | ||||
| import java.util.stream.Stream; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Qualifier; | ||||
| import org.springframework.core.io.ByteArrayResource; | ||||
| import org.springframework.core.io.Resource; | ||||
| import org.springframework.scheduling.annotation.Scheduled; | ||||
| @ -25,6 +24,7 @@ import org.springframework.stereotype.Service; | ||||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.config.InstallationPathConfig; | ||||
| import stirling.software.SPDF.model.PipelineConfig; | ||||
| import stirling.software.SPDF.model.PipelineOperation; | ||||
| import stirling.software.SPDF.utils.FileMonitor; | ||||
| @ -48,14 +48,12 @@ public class PipelineDirectoryProcessor { | ||||
|     public PipelineDirectoryProcessor( | ||||
|             ObjectMapper objectMapper, | ||||
|             ApiDocService apiDocService, | ||||
|             @Qualifier("watchedFoldersDir") String watchedFoldersDir, | ||||
|             @Qualifier("finishedFoldersDir") String finishedFoldersDir, | ||||
|             PipelineProcessor processor, | ||||
|             FileMonitor fileMonitor) { | ||||
|         this.objectMapper = objectMapper; | ||||
|         this.apiDocService = apiDocService; | ||||
|         this.watchedFoldersDir = watchedFoldersDir; | ||||
|         this.finishedFoldersDir = finishedFoldersDir; | ||||
|         this.watchedFoldersDir = InstallationPathConfig.getPipelineWatchedFoldersDir(); | ||||
|         this.finishedFoldersDir = InstallationPathConfig.getPipelineFinishedFoldersDir(); | ||||
|         this.processor = processor; | ||||
|         this.fileMonitor = fileMonitor; | ||||
|     } | ||||
|  | ||||
| @ -25,6 +25,7 @@ import io.swagger.v3.oas.annotations.Hidden; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.config.InstallationPathConfig; | ||||
| import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface; | ||||
| import stirling.software.SPDF.model.SignatureFile; | ||||
| import stirling.software.SPDF.service.SignatureService; | ||||
| @ -34,8 +35,6 @@ import stirling.software.SPDF.service.SignatureService; | ||||
| @Slf4j | ||||
| public class GeneralWebController { | ||||
| 
 | ||||
|     private static final String SIGNATURE_BASE_PATH = "customFiles/static/signatures/"; | ||||
|     private static final String ALL_USERS_FOLDER = "ALL_USERS"; | ||||
|     private final SignatureService signatureService; | ||||
|     private final UserServiceInterface userService; | ||||
|     private final ResourceLoader resourceLoader; | ||||
| @ -223,7 +222,9 @@ public class GeneralWebController { | ||||
|         // Extract font names from classpath | ||||
|         fontNames.addAll(getFontNamesFromLocation("classpath:static/fonts/*.woff2")); | ||||
|         // Extract font names from external directory | ||||
|         fontNames.addAll(getFontNamesFromLocation("file:customFiles/static/fonts/*")); | ||||
|         fontNames.addAll( | ||||
|                 getFontNamesFromLocation( | ||||
|                         "file:" + InstallationPathConfig.getStaticPath() + "fonts/*")); | ||||
|         return fontNames; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| package stirling.software.SPDF.model; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileNotFoundException; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.net.HttpURLConnection; | ||||
| @ -13,18 +15,23 @@ import java.util.List; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.context.annotation.PropertySource; | ||||
| import org.springframework.core.Ordered; | ||||
| import org.springframework.core.annotation.Order; | ||||
| import org.springframework.core.env.ConfigurableEnvironment; | ||||
| import org.springframework.core.env.PropertySource; | ||||
| import org.springframework.core.io.ClassPathResource; | ||||
| import org.springframework.core.io.FileSystemResource; | ||||
| import org.springframework.core.io.Resource; | ||||
| import org.springframework.core.io.support.EncodedResource; | ||||
| 
 | ||||
| import lombok.Data; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import lombok.ToString; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.config.InstallationPathConfig; | ||||
| import stirling.software.SPDF.config.YamlPropertySourceFactory; | ||||
| import stirling.software.SPDF.model.provider.GithubProvider; | ||||
| import stirling.software.SPDF.model.provider.GoogleProvider; | ||||
| @ -33,11 +40,37 @@ import stirling.software.SPDF.model.provider.UnsupportedProviderException; | ||||
| 
 | ||||
| @Configuration | ||||
| @ConfigurationProperties(prefix = "") | ||||
| @PropertySource(value = "file:./configs/settings.yml", factory = YamlPropertySourceFactory.class) | ||||
| @Data | ||||
| @Order(Ordered.HIGHEST_PRECEDENCE) | ||||
| @Slf4j | ||||
| public class ApplicationProperties { | ||||
| 
 | ||||
|     @Bean | ||||
|     public PropertySource<?> dynamicYamlPropertySource(ConfigurableEnvironment environment) | ||||
|             throws IOException { | ||||
|         String configPath = InstallationPathConfig.getSettingsPath(); | ||||
|         log.debug("Attempting to load settings from: " + configPath); | ||||
| 
 | ||||
|         File file = new File(configPath); | ||||
|         if (!file.exists()) { | ||||
|             log.error("Warning: Settings file does not exist at: " + configPath); | ||||
|         } | ||||
| 
 | ||||
|         Resource resource = new FileSystemResource(configPath); | ||||
|         if (!resource.exists()) { | ||||
|             throw new FileNotFoundException("Settings file not found at: " + configPath); | ||||
|         } | ||||
| 
 | ||||
|         EncodedResource encodedResource = new EncodedResource(resource); | ||||
|         PropertySource<?> propertySource = | ||||
|                 new YamlPropertySourceFactory().createPropertySource(null, encodedResource); | ||||
|         environment.getPropertySources().addFirst(propertySource); | ||||
| 
 | ||||
|         log.debug("Loaded properties: " + propertySource.getSource()); | ||||
| 
 | ||||
|         return propertySource; | ||||
|     } | ||||
| 
 | ||||
|     private Legal legal = new Legal(); | ||||
|     private Security security = new Security(); | ||||
|     private System system = new System(); | ||||
| @ -153,6 +186,7 @@ public class ApplicationProperties { | ||||
|             } | ||||
| 
 | ||||
|             public Resource getSpCert() { | ||||
|                 if (spCert == null) return null; | ||||
|                 if (spCert.startsWith("classpath:")) { | ||||
|                     return new ClassPathResource(spCert.substring("classpath:".length())); | ||||
|                 } else { | ||||
| @ -161,6 +195,7 @@ public class ApplicationProperties { | ||||
|             } | ||||
| 
 | ||||
|             public Resource getidpCert() { | ||||
|                 if (idpCert == null) return null; | ||||
|                 if (idpCert.startsWith("classpath:")) { | ||||
|                     return new ClassPathResource(idpCert.substring("classpath:".length())); | ||||
|                 } else { | ||||
|  | ||||
| @ -13,14 +13,19 @@ import org.springframework.stereotype.Service; | ||||
| import org.thymeleaf.util.StringUtils; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.config.InstallationPathConfig; | ||||
| import stirling.software.SPDF.model.SignatureFile; | ||||
| 
 | ||||
| @Service | ||||
| @Slf4j | ||||
| public class SignatureService { | ||||
| 
 | ||||
|     private static final String SIGNATURE_BASE_PATH = "customFiles/signatures/"; | ||||
|     private static final String ALL_USERS_FOLDER = "ALL_USERS"; | ||||
|     private final String SIGNATURE_BASE_PATH; | ||||
|     private final String ALL_USERS_FOLDER = "ALL_USERS"; | ||||
| 
 | ||||
|     public SignatureService() { | ||||
|         SIGNATURE_BASE_PATH = InstallationPathConfig.getSignaturesPath(); | ||||
|     } | ||||
| 
 | ||||
|     public boolean hasAccessToFile(String username, String fileName) throws IOException { | ||||
|         validateFileName(fileName); | ||||
|  | ||||
| @ -15,6 +15,7 @@ import org.springframework.scheduling.annotation.Scheduled; | ||||
| import org.springframework.stereotype.Component; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.config.InstallationPathConfig; | ||||
| 
 | ||||
| @Component | ||||
| @Slf4j | ||||
| @ -34,9 +35,7 @@ public class FileMonitor { | ||||
|      *     monitored, false otherwise | ||||
|      */ | ||||
|     @Autowired | ||||
|     public FileMonitor( | ||||
|             @Qualifier("watchedFoldersDir") String rootDirectory, | ||||
|             @Qualifier("directoryFilter") Predicate<Path> pathFilter) | ||||
|     public FileMonitor(@Qualifier("directoryFilter") Predicate<Path> pathFilter) | ||||
|             throws IOException { | ||||
|         this.newlyDiscoveredFiles = new HashSet<>(); | ||||
|         this.path2KeyMapping = new HashMap<>(); | ||||
| @ -44,7 +43,7 @@ public class FileMonitor { | ||||
|         this.pathFilter = pathFilter; | ||||
|         this.readyForProcessingFiles = ConcurrentHashMap.newKeySet(); | ||||
|         this.watchService = FileSystems.getDefault().newWatchService(); | ||||
|         this.rootDir = Path.of(rootDirectory); | ||||
|         this.rootDir = Path.of(InstallationPathConfig.getPipelineWatchedFoldersDir()); | ||||
|     } | ||||
| 
 | ||||
|     private boolean shouldNotProcess(Path path) { | ||||
|  | ||||
| @ -13,8 +13,6 @@ import java.util.ArrayList; | ||||
| import java.util.Enumeration; | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
| 
 | ||||
| import org.simpleyaml.configuration.file.YamlFile; | ||||
| import org.simpleyaml.configuration.file.YamlFileWrapper; | ||||
| @ -28,6 +26,7 @@ import io.github.pixee.security.HostValidator; | ||||
| import io.github.pixee.security.Urls; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.config.InstallationPathConfig; | ||||
| 
 | ||||
| @Slf4j | ||||
| public class GeneralUtils { | ||||
| @ -85,7 +84,7 @@ public class GeneralUtils { | ||||
| 
 | ||||
|             // Allow only http and https protocols | ||||
|             String protocol = url.getProtocol(); | ||||
|             if (!protocol.equals("http") && !protocol.equals("https")) { | ||||
|             if (!"http".equals(protocol) && !"https".equals(protocol)) { | ||||
|                 return false; // Disallow other protocols | ||||
|             } | ||||
| 
 | ||||
| @ -229,8 +228,7 @@ public class GeneralUtils { | ||||
|             Double result = evaluator.evaluate(sanitizedExpression); | ||||
| 
 | ||||
|             // Check if the result is null or not within bounds | ||||
|             if (result == null) | ||||
|                 break; | ||||
|             if (result == null) break; | ||||
| 
 | ||||
|             if (result.intValue() > 0 && result.intValue() <= maxValue) | ||||
|                 results.add(result.intValue()); | ||||
| @ -241,11 +239,15 @@ public class GeneralUtils { | ||||
| 
 | ||||
|     private static String sanitizeNFunction(String expression, int nValue) { | ||||
|         String sanitizedExpression = expression.replace(" ", ""); | ||||
|         String multiplyByOpeningRoundBracketPattern = "([0-9n)])\\("; // example: n(n-1), 9(n-1), (n-1)(n-2) | ||||
|         sanitizedExpression = sanitizedExpression.replaceAll(multiplyByOpeningRoundBracketPattern, "$1*("); | ||||
|         String multiplyByOpeningRoundBracketPattern = | ||||
|                 "([0-9n)])\\("; // example: n(n-1), 9(n-1), (n-1)(n-2) | ||||
|         sanitizedExpression = | ||||
|                 sanitizedExpression.replaceAll(multiplyByOpeningRoundBracketPattern, "$1*("); | ||||
| 
 | ||||
|         String multiplyByClosingRoundBracketPattern = "\\)([0-9n)])"; // example: (n-1)n, (n-1)9, (n-1)(n-2) | ||||
|         sanitizedExpression = sanitizedExpression.replaceAll(multiplyByClosingRoundBracketPattern, ")*$1"); | ||||
|         String multiplyByClosingRoundBracketPattern = | ||||
|                 "\\)([0-9n)])"; // example: (n-1)n, (n-1)9, (n-1)(n-2) | ||||
|         sanitizedExpression = | ||||
|                 sanitizedExpression.replaceAll(multiplyByClosingRoundBracketPattern, ")*$1"); | ||||
| 
 | ||||
|         sanitizedExpression = insertMultiplicationBeforeN(sanitizedExpression, nValue); | ||||
|         return sanitizedExpression; | ||||
| @ -341,7 +343,10 @@ public class GeneralUtils { | ||||
| 
 | ||||
|     public static void saveKeyToConfig(String id, String key, boolean autoGenerated) | ||||
|             throws IOException { | ||||
|         Path path = Paths.get("configs", "settings.yml"); // Target the configs/settings.yml | ||||
|         Path path = | ||||
|                 Paths.get( | ||||
|                         InstallationPathConfig | ||||
|                                 .getSettingsPath()); // Target the configs/settings.yml | ||||
| 
 | ||||
|         final YamlFile settingsYml = new YamlFile(path.toFile()); | ||||
|         DumperOptions yamlOptionssettingsYml = | ||||
| @ -359,7 +364,7 @@ public class GeneralUtils { | ||||
| 
 | ||||
|     public static void saveKeyToConfig(String id, boolean key, boolean autoGenerated) | ||||
|             throws IOException { | ||||
|         Path path = Paths.get("configs", "settings.yml"); | ||||
|         Path path = Paths.get(InstallationPathConfig.getSettingsPath()); | ||||
| 
 | ||||
|         final YamlFile settingsYml = new YamlFile(path.toFile()); | ||||
|         DumperOptions yamlOptionssettingsYml = | ||||
|  | ||||
| @ -1,3 +0,0 @@ | ||||
| package stirling.software.SPDF.utils; | ||||
| 
 | ||||
| public class PDFManipulationUtils {} | ||||
| @ -9,6 +9,7 @@ import java.nio.file.Path; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| import java.util.zip.ZipEntry; | ||||
| import java.util.zip.ZipOutputStream; | ||||
| 
 | ||||
| @ -64,7 +65,7 @@ public class PDFToFile { | ||||
|                             .runCommandWithOutputHandling(command, tempOutputDir.toFile()); | ||||
| 
 | ||||
|             // Get output files | ||||
|             List<File> outputFiles = Arrays.asList(tempOutputDir.toFile().listFiles()); | ||||
|             File[] outputFiles = Objects.requireNonNull(tempOutputDir.toFile().listFiles()); | ||||
| 
 | ||||
|             // Return output files in a ZIP archive | ||||
|             fileName = pdfBaseName + "ToHtml.zip"; | ||||
|  | ||||
| @ -22,9 +22,11 @@ import org.apache.pdfbox.text.TextPosition; | ||||
| import org.springframework.core.io.InputStreamResource; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import stirling.software.SPDF.model.api.misc.HighContrastColorCombination; | ||||
| import stirling.software.SPDF.model.api.misc.ReplaceAndInvert; | ||||
| 
 | ||||
| @Slf4j | ||||
| public class CustomColorReplaceStrategy extends ReplaceAndInvertColorStrategy { | ||||
| 
 | ||||
|     private String textColor; | ||||
| @ -93,17 +95,17 @@ public class CustomColorReplaceStrategy extends ReplaceAndInvertColorStrategy { | ||||
|                         try { | ||||
|                             font = PDFontFactory.createFont(text.getFont().getCOSObject()); | ||||
|                         } catch (IOException io) { | ||||
|                             System.out.println("Primary font not found, using fallback font."); | ||||
|                             log.info("Primary font not found, using fallback font."); | ||||
|                             font = new PDType1Font(Standard14Fonts.FontName.HELVETICA); | ||||
|                         } | ||||
|                         // if a character is not supported by font, then look for supported font | ||||
|                         try { | ||||
|                             byte[] bytes = font.encode(unicodeText); | ||||
|                         } catch (IOException io) { | ||||
|                             System.out.println("text could not be encoded "); | ||||
|                             log.info("text could not be encoded "); | ||||
|                             font = checkSupportedFontForCharacter(unicodeText); | ||||
|                         } catch (IllegalArgumentException ie) { | ||||
|                             System.out.println("text not supported by font "); | ||||
|                             log.info("text not supported by font "); | ||||
|                             font = checkSupportedFontForCharacter(unicodeText); | ||||
|                         } finally { | ||||
|                             // if any other font is not supported, then replace default character * | ||||
| @ -157,9 +159,9 @@ public class CustomColorReplaceStrategy extends ReplaceAndInvertColorStrategy { | ||||
|                 byte[] bytes = currentFont.encode(unicodeText); | ||||
|                 return currentFont; | ||||
|             } catch (IOException io) { | ||||
|                 System.out.println("text could not be encoded "); | ||||
|                 log.info("text could not be encoded "); | ||||
|             } catch (IllegalArgumentException ie) { | ||||
|                 System.out.println("text not supported by font "); | ||||
|                 log.info("text not supported by font "); | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|  | ||||
| @ -27,8 +27,7 @@ spring.devtools.restart.exclude=stirling.software.SPDF.config.security/** | ||||
| spring.thymeleaf.encoding=UTF-8 | ||||
| spring.web.resources.mime-mappings.webmanifest=application/manifest+json | ||||
| spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000} | ||||
| #spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/ | ||||
| #spring.thymeleaf.cache=false | ||||
| 
 | ||||
| spring.datasource.url=jdbc:h2:file:./configs/stirling-pdf-DB-2.3.232;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE | ||||
| spring.datasource.driver-class-name=org.h2.Driver | ||||
| spring.datasource.username=sa | ||||
|  | ||||
| @ -1,4 +1,6 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <configuration> | ||||
| 	<define name="LOG_PATH" class="stirling.software.SPDF.config.LogbackPropertyLoader" /> | ||||
| 
 | ||||
|     <!-- Console Appender --> | ||||
|     <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> | ||||
| @ -7,35 +9,30 @@ | ||||
|         </encoder> | ||||
|     </appender> | ||||
| 
 | ||||
|     <!-- Rolling File Appender --> | ||||
|     <!-- Rolling File Appender for Auth Logs --> | ||||
|     <appender name="AUTHLOG" class="ch.qos.logback.core.rolling.RollingFileAppender"> | ||||
|         <file>logs/invalid-auths.log</file> | ||||
|         <file>${LOG_PATH}/invalid-auths.log</file> | ||||
|         <encoder> | ||||
|             <pattern>%d %p %c{1} [%thread] %m%n</pattern> | ||||
|         </encoder> | ||||
| 
 | ||||
|         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | ||||
|             <!-- daily rollover and keep 7 days' worth of history --> | ||||
|             <fileNamePattern>logs/auth-%d{yyyy-MM-dd}.log</fileNamePattern> | ||||
|             <fileNamePattern>${LOG_PATH}/auth-%d{yyyy-MM-dd}.log</fileNamePattern> | ||||
|             <maxHistory>1</maxHistory> | ||||
|         </rollingPolicy> | ||||
|     </appender> | ||||
| 
 | ||||
|     <!-- Rolling File Appender --> | ||||
|     <!-- Rolling File Appender for General Logs --> | ||||
|     <appender name="GENERAL" class="ch.qos.logback.core.rolling.RollingFileAppender"> | ||||
|         <file>logs/info.log</file> | ||||
|         <file>${LOG_PATH}/info.log</file> | ||||
|         <encoder> | ||||
|             <pattern>%d %p %c{1} [%thread] %m%n</pattern> | ||||
|         </encoder> | ||||
| 
 | ||||
|         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | ||||
|             <!-- daily rollover and keep 7 days' worth of history --> | ||||
|             <fileNamePattern>logs/info-%d{yyyy-MM-dd}.log</fileNamePattern> | ||||
|             <fileNamePattern>${LOG_PATH}/info-%d{yyyy-MM-dd}.log</fileNamePattern> | ||||
|             <maxHistory>1</maxHistory> | ||||
|         </rollingPolicy> | ||||
|     </appender> | ||||
| 
 | ||||
| 
 | ||||
|     <!-- Root Logger --> | ||||
|     <root level="INFO"> | ||||
|         <appender-ref ref="CONSOLE"/> | ||||
| @ -43,10 +40,9 @@ | ||||
|     </root> | ||||
| 
 | ||||
|     <!-- Specific Logger --> | ||||
|     <logger name="stirling.software.SPDF.config.security.CustomAuthenticationFailureHandler" level="ERROR" | ||||
|             additivity="false"> | ||||
|     <logger name="stirling.software.SPDF.config.security.CustomAuthenticationFailureHandler"  | ||||
|             level="ERROR" additivity="false"> | ||||
|         <appender-ref ref="CONSOLE"/> | ||||
|         <appender-ref ref="AUTHLOG"/> | ||||
|     </logger> | ||||
| 
 | ||||
| </configuration> | ||||
| </configuration> | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user