Author: msahyoun
Date: Sat Mar 28 19:28:21 2026
New Revision: 1932647

Log:
PDFBOX-6185: improve handling of files in temp directory; Windows settings by 
Claude Sonnet 4.6

Modified:
   pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/ui/Tree.java

Modified: 
pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/ui/Tree.java
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/ui/Tree.java 
Sat Mar 28 18:45:04 2026        (r1932646)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/debugger/ui/Tree.java 
Sat Mar 28 19:28:21 2026        (r1932647)
@@ -39,11 +39,23 @@ import java.awt.event.MouseEvent;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.file.FileSystems;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.AclEntry;
+import java.nio.file.attribute.AclEntryPermission;
+import java.nio.file.attribute.AclEntryType;
+import java.nio.file.attribute.AclFileAttributeView;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.nio.file.attribute.UserPrincipal;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import java.util.StringJoiner;
+import java.util.stream.Stream;
+
 import org.apache.pdfbox.debugger.PDFDebugger;
 
 /**
@@ -58,6 +70,84 @@ public class Tree extends JTree
     private final JPopupMenu treePopupMenu;
     private final Object rootNode;
 
+    // Temporary files are stored in a private temp directory with restricted 
permissions,
+    // which is deleted on exit using a shutdown hook.
+    // PDFBOX-6185
+    private static final Path TEMP_DIR = createTempDir();
+
+    private static Path createTempDir()
+    {
+        try
+        {
+            Path tempDir = Files.createTempDirectory("pdfbox-");
+            applyOwnerOnlyPermissions(tempDir);
+
+            // use shutdown hook instead of deleteOnExit() to ensure deletion
+            // of the entire directory in case of not automatically deleted on 
+            // JVM exit (e.g. due to hard crash or kill -9)
+            Runtime.getRuntime().addShutdownHook(new Thread(() ->
+            {
+                try (Stream<Path> entries = Files.walk(tempDir))
+                {
+                    entries.sorted(Comparator.reverseOrder())
+                        .forEach(p -> p.toFile().delete());
+                }
+                catch (IOException ignored) {}
+            }));
+
+            return tempDir;
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException("Failed to create temporary directory 
for PDFDebugger", e);
+        }
+    }
+
+    private static void applyOwnerOnlyPermissions(Path dir) throws IOException
+    {
+        if 
(FileSystems.getDefault().supportedFileAttributeViews().contains("posix"))
+        {
+            // Unix/macOS — rwx------
+            Files.setPosixFilePermissions(dir, 
PosixFilePermissions.fromString("rwx------"));
+        }
+        else
+        {
+            // Windows — replace the entire ACL with a single owner-only ALLOW 
entry
+            AclFileAttributeView aclView =
+                Files.getFileAttributeView(dir, AclFileAttributeView.class);
+
+            if (aclView == null)
+            {
+                throw new IOException("Neither posix nor ACL view is supported 
on this file system");
+            }
+
+            UserPrincipal owner = aclView.getOwner();
+
+            AclEntry ownerFullControl = AclEntry.newBuilder()
+                .setType(AclEntryType.ALLOW)
+                .setPrincipal(owner)
+                .setPermissions(
+                    AclEntryPermission.READ_DATA,
+                    AclEntryPermission.WRITE_DATA,
+                    AclEntryPermission.APPEND_DATA,
+                    AclEntryPermission.READ_NAMED_ATTRS,
+                    AclEntryPermission.WRITE_NAMED_ATTRS,
+                    AclEntryPermission.EXECUTE,
+                    AclEntryPermission.DELETE_CHILD,
+                    AclEntryPermission.READ_ATTRIBUTES,
+                    AclEntryPermission.WRITE_ATTRIBUTES,
+                    AclEntryPermission.DELETE,
+                    AclEntryPermission.READ_ACL,
+                    AclEntryPermission.WRITE_ACL,
+                    AclEntryPermission.SYNCHRONIZE
+                )
+                .build();
+
+            // Set so that only the owner has permissions, and remove any 
inherited ACL entries
+            aclView.setAcl(Collections.singletonList(ownerFullControl));
+        }
+    }
+
     /**
      * Constructor.
      */
@@ -295,8 +385,7 @@ public class Tree extends JTree
         {
             try
             {
-                File temp = Files.createTempFile("pdfbox", "." + 
extension).toFile();
-                temp.deleteOnExit();
+                File temp = Files.createTempFile(TEMP_DIR, "pdfbox", "." + 
extension).toFile();
 
                 try (InputStream is = cosStream.createInputStream())
                 {

Reply via email to