• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jiangxincode / ApkToolBoxGUI / #1138

23 Aug 2025 09:51AM UTC coverage: 2.877% (-0.06%) from 2.94%
#1138

push

jiangxincode
add pdf password remover function

0 of 205 new or added lines in 4 files covered. (0.0%)

1 existing line in 1 file now uncovered.

236 of 8202 relevant lines covered (2.88%)

0.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/edu/jiangxin/apktoolbox/pdf/PdfUtils.java
1
package edu.jiangxin.apktoolbox.pdf;
2

3
import org.apache.logging.log4j.LogManager;
4
import org.apache.logging.log4j.Logger;
5
import org.apache.pdfbox.Loader;
6
import org.apache.pdfbox.pdmodel.PDDocument;
7
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
8
import org.apache.pdfbox.pdmodel.PDPage;
9
import org.apache.pdfbox.pdmodel.PDPageTree;
10
import org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy;
11
import org.apache.pdfbox.pdmodel.encryption.SecurityHandler;
12
import org.apache.pdfbox.text.PDFTextStripper;
13

14
import java.io.File;
15
import java.io.IOException;
16

17
public class PdfUtils {
×
18
    private static final Logger LOGGER = LogManager.getLogger(PdfUtils.class.getSimpleName());
×
19
    public static boolean isScannedPdf(File file, int threshold) {
20
        int length = 0;
×
21

22
        try (PDDocument document = Loader.loadPDF(file)) {
×
23
            boolean isEncrypted = document.isEncrypted();
×
24
            if (isEncrypted) {
×
25
                document.setAllSecurityToBeRemoved(true);
×
26
            }
27

28
            PDFTextStripper stripper = new PDFTextStripper();
×
29
            String text = stripper.getText(document).trim();
×
30
            length = text.length();
×
31
        } catch (IOException e) {
×
32
            LOGGER.error("Error reading PDF file: {}", e.getMessage());
×
33
            return false;
×
34
        }
×
35
        LOGGER.info("Processing file: {}, text size: {}", file.getPath(), length);
×
36
        return length < threshold;
×
37
    }
38

39
    public static boolean isEncryptedPdf(File file) {
40
        boolean isEncrypted;
41

42
        try (PDDocument document = Loader.loadPDF(file)) {
×
43
            isEncrypted = document.isEncrypted();
×
44
        } catch (IOException e) {
×
45
            LOGGER.error("Error reading PDF file: {}", e.getMessage());
×
46
            return false;
×
47
        }
×
48
        LOGGER.info("Processing file: {}, is encrypted: {}", file.getPath(), isEncrypted);
×
49
        return isEncrypted;
×
50
    }
51

52
    public static boolean isNonOutlinePdf(File file) {
53
        boolean hasOutline = false;
×
54

55
        try (PDDocument document = Loader.loadPDF(file)) {
×
56
            boolean isEncrypted = document.isEncrypted();
×
57
            if (isEncrypted) {
×
58
                document.setAllSecurityToBeRemoved(true);
×
59
            }
60

61
            if (document.getDocumentCatalog() != null && document.getDocumentCatalog().getDocumentOutline() != null) {
×
62
                hasOutline = true;
×
63
            }
64
        } catch (IOException e) {
×
65
            LOGGER.error("Error reading PDF file: {}", e.getMessage());
×
66
            return false;
×
67
        }
×
68
        LOGGER.info("Processing file: {}, has outline: {}", file.getPath(), hasOutline);
×
69
        return !hasOutline;
×
70
    }
71

72
    public static boolean hasAnnotations(File file) {
73
        boolean hasAnnotations = false;
×
74

75
        try (PDDocument document = Loader.loadPDF(file)) {
×
76
            boolean isEncrypted = document.isEncrypted();
×
77
            if (isEncrypted) {
×
78
                document.setAllSecurityToBeRemoved(true);
×
79
            }
80
            PDDocumentCatalog catalog = document.getDocumentCatalog();
×
81
            if (catalog == null) {
×
82
                return false;
×
83
            }
84
            PDPageTree pages = document.getDocumentCatalog().getPages();
×
85
            if (pages == null || pages.getCount() == 0) {
×
86
                return false;
×
87
            }
88

89
            for (PDPage page : pages) {
×
90
                if (page.getAnnotations() != null && !page.getAnnotations().isEmpty()) {
×
91
                    int pageNumber = page.getCOSObject().getInt("PageNumber", 0);
×
92
                    String subType = page.getAnnotations().get(0).getSubtype();
×
93
                    LOGGER.info("Found annotations on page: {}, subType: {}", pageNumber, subType);
×
94
                    if (!subType.equals("Link")) {
×
95
                        hasAnnotations = true;
×
96
                        break; // No need to check further if we found annotations
×
97
                    }
98
                }
99
            }
×
100
        } catch (IOException e) {
×
101
            LOGGER.error("Error reading PDF file: {}", e.getMessage());
×
102
            return hasAnnotations;
×
103
        }
×
104
        LOGGER.info("Processing file: {}, has annotations: {}", file.getPath(), hasAnnotations);
×
105
        return hasAnnotations;
×
106
    }
107

108
    public static void removePassword(File encryptedFile, File targetDir) {
NEW
109
        try (PDDocument document = Loader.loadPDF(encryptedFile)) {
×
NEW
110
            boolean isEncrypted = document.isEncrypted();
×
NEW
111
            if (isEncrypted) {
×
NEW
112
                document.setAllSecurityToBeRemoved(true);
×
113
            }
NEW
114
            String targetFilePath = targetDir.getAbsolutePath() + File.separator + encryptedFile.getName();
×
NEW
115
            document.save(targetFilePath);
×
NEW
116
            LOGGER.info("Remove password success: {}", targetFilePath);
×
NEW
117
        } catch (IOException e) {
×
NEW
118
            LOGGER.error("Error processing PDF file: {}", e.getMessage());
×
NEW
119
        }
×
NEW
120
    }
×
121
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc